This is the mail archive of the
binutils@sources.redhat.com
mailing list for the binutils project.
properly handle extensions to DWARF 2 line number information
- To: gdb-patches at sources dot redhat dot com, binutils at sources dot redhat dot com
- Subject: properly handle extensions to DWARF 2 line number information
- From: Geoffrey Keating <geoffk at cygnus dot com>
- Date: Sun, 11 Nov 2001 04:26:22 -0800
[Get raw message]
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. */
============================================================