properly handle extensions to DWARF 2 line number information
Jim Blandy
jimb@zwingli.cygnus.com
Thu Nov 1 16:15:00 GMT 2001
The GDB portion of this patch is approved for the trunk.
Geoffrey Keating <geoffk@cygnus.com> writes:
>
>
> The forthcoming DWARF 3 standard extends the DWARF 2 line number
> information in a backwards-compatible way, by increasing opcode_base
> and defining new standard opcodes.
>
> That is, it's backwards-compatible if the DWARF 2 reader properly
> ignores unknown standard opcodes. Unfortunately, the ones in BFD,
> GDB, and binutils don't; they expect that any opcodes they don't know
> about must be special opcodes.
>
> It would be good to get this patch into the next GDB release (5.1?),
> because I hope soon to implement one of the extensions in GAS, the
> DW_LNS_set_isa opcode, and the effect of this bug is that GDB can't
> understand any files in which this opcode is used.
>
> This has been tested on x86-linux using target 'unix/-gdwarf-2'. It
> has also been tested with a file with the DW_LNS_set_isa included (the
> file was generated by hand).
>
> OK to commit? I think I need approval from both GDB and binutils
> maintainers.
>
> --
> Geoff Keating <geoffk@redhat.com>
>
> ===File ~/patches/gdb-lineextend.patch======================
> Index: bfd/ChangeLog
> 2001-11-11 Geoffrey Keating <geoffk@redhat.com>
>
> * dwarf2.c (decode_line_info): Properly deal with unknown standard
> opcodes.
>
> Index: binutils/ChangeLog
> 2001-11-11 Geoffrey Keating <geoffk@redhat.com>
>
> * readelf.c (display_debug_lines): Deal with unknown standard
> opcodes. Handle DW_LNS_set_prologue_end, DW_LNS_set_epilogue_begin,
> DW_LNS_set_isa.
>
> Index: gdb/ChangeLog
> 2001-11-11 Geoffrey Keating <geoffk@redhat.com>
>
> * dwarf2read.c (dwarf_decode_lines): Properly deal with
> unknown standard opcodes.
>
> Index: include/elf/ChangeLog
> 2001-11-11 Geoffrey Keating <geoffk@redhat.com>
>
> * dwarf2.h (dwarf_line_number_ops): Add DWARF 3 opcodes.
>
> Index: bfd/dwarf2.c
> ===================================================================
> RCS file: /cvs/src/src/bfd/dwarf2.c,v
> retrieving revision 1.24
> diff -p -u -p -r1.24 dwarf2.c
> --- dwarf2.c 2001/10/06 10:01:09 1.24
> +++ dwarf2.c 2001/11/11 11:42:13
> @@ -979,7 +979,22 @@ decode_line_info (unit, stash)
> op_code = read_1_byte (abfd, line_ptr);
> line_ptr += 1;
>
> - switch (op_code)
> + if (op_code >= lh.opcode_base)
> + { /* Special operand. */
> + adj_opcode = op_code - lh.opcode_base;
> + address += (adj_opcode / lh.line_range)
> + * lh.minimum_instruction_length;
> + line += lh.line_base + (adj_opcode % lh.line_range);
> + /* Append row to matrix using current values. */
> + add_line_info (table, address, filename, line, column, 0);
> + basic_block = 1;
> + if (need_low_pc)
> + {
> + need_low_pc = 0;
> + low_pc = address;
> + }
> + }
> + else switch (op_code)
> {
> case DW_LNS_extended_op:
> line_ptr += 1; /* Ignore length. */
> @@ -1079,19 +1094,15 @@ decode_line_info (unit, stash)
> address += read_2_bytes (abfd, line_ptr);
> line_ptr += 2;
> break;
> - default: /* Special operand. */
> - adj_opcode = op_code - lh.opcode_base;
> - address += (adj_opcode / lh.line_range)
> - * lh.minimum_instruction_length;
> - line += lh.line_base + (adj_opcode % lh.line_range);
> - /* Append row to matrix using current values. */
> - add_line_info (table, address, filename, line, column, 0);
> - basic_block = 1;
> - if (need_low_pc)
> - {
> - need_low_pc = 0;
> - low_pc = address;
> - }
> + default:
> + { /* Unknown standard opcode, ignore it. */
> + int i;
> + for (i = 0; i < lh.standard_opcode_lengths[op_code]; i++)
> + {
> + (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
> + line_ptr += bytes_read;
> + }
> + }
> }
> }
> }
> Index: binutils/readelf.c
> ===================================================================
> RCS file: /cvs/src/src/binutils/readelf.c,v
> retrieving revision 1.131
> diff -p -u -p -r1.131 readelf.c
> --- readelf.c 2001/11/10 00:55:48 1.131
> +++ readelf.c 2001/11/11 11:42:14
> @@ -5888,8 +5888,20 @@ display_debug_lines (section, start, fil
>
> op_code = * data ++;
>
> - switch (op_code)
> + if (op_code >= info.li_opcode_base)
> {
> + op_code -= info.li_opcode_base;
> + adv = (op_code / info.li_line_range) * info.li_min_insn_length;
> + state_machine_regs.address += adv;
> + printf (_(" Special opcode %d: advance Address by %d to 0x%lx"),
> + op_code, adv, state_machine_regs.address);
> + adv = (op_code % info.li_line_range) + info.li_line_base;
> + state_machine_regs.line += adv;
> + printf (_(" and Line by %d to %d\n"),
> + adv, state_machine_regs.line);
> + }
> + else switch (op_code)
> + {
> case DW_LNS_extended_op:
> data += process_extended_line_op (data, info.li_default_is_stmt,
> debug_line_pointer_size);
> @@ -5958,20 +5970,36 @@ display_debug_lines (section, start, fil
> adv, state_machine_regs.address);
> break;
>
> + case DW_LNS_set_prologue_end:
> + printf (_(" Set prologue_end to true\n"));
> + break;
> +
> + case DW_LNS_set_epilogue_begin:
> + printf (_(" Set epilogue_begin to true\n"));
> + break;
> +
> + case DW_LNS_set_isa:
> + adv = read_leb128 (data, & bytes_read, 0);
> + data += bytes_read;
> + printf (_(" Set ISA to %d\n"), adv);
> + break;
> +
> default:
> - op_code -= info.li_opcode_base;
> - adv = (op_code / info.li_line_range) * info.li_min_insn_length;
> - state_machine_regs.address += adv;
> - printf (_(" Special opcode %d: advance Address by %d to 0x%lx"),
> - op_code, adv, state_machine_regs.address);
> - adv = (op_code % info.li_line_range) + info.li_line_base;
> - state_machine_regs.line += adv;
> - printf (_(" and Line by %d to %d\n"),
> - adv, state_machine_regs.line);
> + printf (_(" Unknown opcode %d with operands: "), op_code);
> + {
> + int i;
> + for (i = standard_opcodes[op_code - 1]; i > 0 ; --i)
> + {
> + printf ("0x%lx%s", read_leb128 (data, &bytes_read, 0),
> + i == 1 ? "" : ", ");
> + data += bytes_read;
> + }
> + putchar ('\n');
> + }
> break;
> }
> }
> - printf ("\n");
> + putchar ('\n');
> }
>
> return 1;
> Index: gdb/dwarf2read.c
> ===================================================================
> RCS file: /cvs/src/src/gdb/dwarf2read.c,v
> retrieving revision 1.33
> diff -p -u -p -r1.33 dwarf2read.c
> --- dwarf2read.c 2001/11/06 23:38:14 1.33
> +++ dwarf2read.c 2001/11/11 11:42:16
> @@ -3963,7 +3963,18 @@ dwarf_decode_lines (unsigned int offset,
> {
> op_code = read_1_byte (abfd, line_ptr);
> line_ptr += 1;
> - switch (op_code)
> +
> + if (op_code >= lh.opcode_base)
> + { /* Special operand. */
> + adj_opcode = op_code - lh.opcode_base;
> + address += (adj_opcode / lh.line_range)
> + * lh.minimum_instruction_length;
> + line += lh.line_base + (adj_opcode % lh.line_range);
> + /* append row to matrix using current values */
> + record_line (current_subfile, line, address);
> + basic_block = 1;
> + }
> + else switch (op_code)
> {
> case DW_LNS_extended_op:
> line_ptr += 1; /* ignore length */
> @@ -4061,14 +4072,15 @@ dwarf_decode_lines (unsigned int offset,
> address += read_2_bytes (abfd, line_ptr);
> line_ptr += 2;
> break;
> - default: /* special operand */
> - adj_opcode = op_code - lh.opcode_base;
> - address += (adj_opcode / lh.line_range)
> - * lh.minimum_instruction_length;
> - line += lh.line_base + (adj_opcode % lh.line_range);
> - /* append row to matrix using current values */
> - record_line (current_subfile, line, address);
> - basic_block = 1;
> + default:
> + { /* Unknown standard opcode, ignore it. */
> + int i;
> + for (i = 0; i < lh.standard_opcode_lengths[op_code]; i++)
> + {
> + (void) read_unsigned_leb128 (abfd, line_ptr, &bytes_read);
> + line_ptr += bytes_read;
> + }
> + }
> }
> }
> }
> Index: include/elf/dwarf2.h
> ===================================================================
> RCS file: /cvs/src/src/include/elf/dwarf2.h,v
> retrieving revision 1.6
> diff -p -u -p -r1.6 dwarf2.h
> --- dwarf2.h 2001/06/30 08:58:10 1.6
> +++ dwarf2.h 2001/11/11 11:42:18
> @@ -588,7 +588,11 @@ enum dwarf_line_number_ops
> DW_LNS_negate_stmt = 6,
> DW_LNS_set_basic_block = 7,
> DW_LNS_const_add_pc = 8,
> - DW_LNS_fixed_advance_pc = 9
> + DW_LNS_fixed_advance_pc = 9,
> + /* DWARF 3 */
> + DW_LNS_set_prologue_end = 10,
> + DW_LNS_set_epilogue_begin = 11,
> + DW_LNS_set_isa = 12
> };
>
> /* Line number extended opcodes. */
> ============================================================
>
More information about the Binutils
mailing list