[PATCH] [binutils/readelf] Fix printing of dwarf5 .debug_info.dwo
Tom de Vries
tdevries@suse.de
Mon May 20 07:32:18 GMT 2024
When compiling a hello world like this:
...
$ gcc ~/data/hello.c -gsplit-dwarf -gdwarf-5
...
we get with readelf -w a-hello.dwo for the split full compilation unit entry
incorrect strings, for instance an incorrect producer string:
...
<15> DW_AT_producer : (indexed string: 0xb): /home/vries/data/hello.c
...
The problem is that a str_offsets_base of 0 is used, so the header of the
.debug_str_offsets section of size 8 is treated as two offsets, and the index
0xb is mapped to entry 9 instead of 11:
...
9 0000006c /home/vries/data/hello.c
...
11 00000097 GNU C17 15.0.0 -gsplit-dwarf -gdwarf-5
...
The DW_AT_str_offsets_base attribute is inherited from the corresponding
skeleton compilation unit in a.out, but:
- that's outside the scope of the .dwo file, and
- it's also not there (though it is there when using clang instead).
Fix this by assuming a sane default for str_offsets_base for dwarf5: the size
of the header of the .debug_str_offsets section, which is 8 for 32-bit dwarf
and 16 for 64-bit dwarf.
Implement this by moving the reading of DW_AT_str_offsets_base to read_bases,
which also fixes the printing of DW_FORM_strx strings in the skeleton
compilation unit entries for attributes before the DW_AT_str_offsets_base
attribute.
Conforming with the other code in read_bases, we only handle
DW_FORM_sec_offset, which means the code dealing with negative
str_offsets_base can be dropped.
Tested on x86_64-linux.
---
binutils/dwarf.c | 38 ++++++++++++-------
.../binutils-all/readelf-str-offsets-base.d | 17 +++++++++
.../binutils-all/readelf-str-offsets-base.s | 30 +++++++++++++++
binutils/testsuite/binutils-all/readelf.exp | 1 +
4 files changed, 72 insertions(+), 14 deletions(-)
create mode 100644 binutils/testsuite/binutils-all/readelf-str-offsets-base.d
create mode 100644 binutils/testsuite/binutils-all/readelf-str-offsets-base.s
diff --git a/binutils/dwarf.c b/binutils/dwarf.c
index d375148dc26..3fde898602e 100644
--- a/binutils/dwarf.c
+++ b/binutils/dwarf.c
@@ -2874,20 +2874,7 @@ read_and_display_attr_value (unsigned long attribute,
break;
case DW_AT_str_offsets_base:
- if (debug_info_p->str_offsets_base)
- warn (_("CU @ %#" PRIx64 " has multiple str_offsets_base values "
- "%#" PRIx64 " and %#" PRIx64 ")\n"),
- debug_info_p->cu_offset,
- debug_info_p->str_offsets_base, uvalue);
- svalue = uvalue;
- if (svalue < 0)
- {
- warn (_("CU @ %#" PRIx64 " has has a negative stroffsets_base "
- "value of %#" PRIx64 " - treating as zero\n"),
- debug_info_p->cu_offset, svalue);
- uvalue = 0;
- }
- debug_info_p->str_offsets_base = uvalue;
+ /* Assignment to debug_info_p->str_offsets_base is now elsewhere. */
break;
case DW_AT_frame_base:
@@ -3685,6 +3672,8 @@ read_bases (abbrev_entry * entry,
{
abbrev_attr *attr;
+ uint64_t initial_str_offsets_base = debug_info_p->str_offsets_base;
+
for (attr = entry->first_attr;
attr && attr->attribute;
attr = attr->next)
@@ -3711,10 +3700,31 @@ read_bases (abbrev_entry * entry,
else
warn (_("Unexpected form of DW_AT_addr_base in the top DIE\n"));
}
+ if (attr->attribute == DW_AT_str_offsets_base)
+ {
+ if (attr->form == DW_FORM_sec_offset)
+ {
+ SAFE_BYTE_GET_AND_INC (uvalue, data, offset_size, end);
+ if (initial_str_offsets_base == 0 && debug_info_p->str_offsets_base != 0)
+ warn (_("CU @ %#" PRIx64 " has multiple str_offsets_base values "
+ "%#" PRIx64 " and %#" PRIx64 ")\n"),
+ debug_info_p->cu_offset,
+ debug_info_p->str_offsets_base, uvalue);
+ debug_info_p->str_offsets_base = uvalue;
+ }
+ else
+ warn (_("Unexpected form of DW_AT_str_offsets_base in the top DIE\n"));
+ }
else
data = skip_attribute (attr->form, data, end, pointer_size,
offset_size, dwarf_version);
}
+
+ /* Provide a sane default for str_offsets_base: the size of the header of
+ the .debug_str_offsets section. */
+ if (dwarf_version >= 5 && initial_str_offsets_base == 0
+ && debug_info_p->str_offsets_base == 0)
+ debug_info_p->str_offsets_base = offset_size == 4 ? 8 : 16;
}
/* Process the contents of a .debug_info section.
diff --git a/binutils/testsuite/binutils-all/readelf-str-offsets-base.d b/binutils/testsuite/binutils-all/readelf-str-offsets-base.d
new file mode 100644
index 00000000000..063c7ef8b44
--- /dev/null
+++ b/binutils/testsuite/binutils-all/readelf-str-offsets-base.d
@@ -0,0 +1,17 @@
+#name: readelf -wi readelf-str-offsets-base
+#source: readelf-str-offsets-base.s
+#readelf: -wi
+
+Contents of the .debug_info.dwo section:
+
+ Compilation Unit @ offset 0:
+ Length: 0x13 \(32-bit\)
+ Version: 5
+ Unit Type: DW_UT_split_compile \(5\)
+ Abbrev Offset: 0
+ Pointer Size: 8
+ DWO ID: 0xba7e77f573c097b6
+ <0><14>: Abbrev Number: 1 \(DW_TAG_compile_unit\)
+ <15> DW_AT_producer : \(indexed string: 0\): FIRST
+ <1><16>: Abbrev Number: 0
+
diff --git a/binutils/testsuite/binutils-all/readelf-str-offsets-base.s b/binutils/testsuite/binutils-all/readelf-str-offsets-base.s
new file mode 100644
index 00000000000..6e21e6dc0b1
--- /dev/null
+++ b/binutils/testsuite/binutils-all/readelf-str-offsets-base.s
@@ -0,0 +1,30 @@
+ .section .debug_str.dwo,"MS",%progbits,1
+ .asciz "FIRST"
+ .asciz "SECOND"
+ .section .debug_str_offsets.dwo,"MS",%progbits,1
+ .long 16
+ .short 5
+ .short 0
+ .4byte 0
+ .4byte 6
+ .section .debug_info.dwo,"e",%progbits
+ .long .Ldebug_info_dwo_end0-.Ldebug_info_dwo_start0 /* Length of Unit */
+.Ldebug_info_dwo_start0:
+ .2byte 0x5 /* DWARF macro version number. */
+ .byte 5 /* DWARF Unit Type */
+ .byte 8 /* Address Size (in bytes) */
+ .long 0 /* Offset Into Abbrev. Section */
+ .quad -5008433839496718410 /* DWO ID */
+ .byte 1 /* Abbrev [1] 0x14:0x1a DW_TAG_compile_unit */
+ .byte 0 /* DW_AT_producer */
+ .byte 0 /* End Of Children Mark */
+.Ldebug_info_dwo_end0:
+ .section .debug_abbrev.dwo,"e",%progbits
+ .byte 1 /* Abbreviation Code */
+ .byte 17 /* DW_TAG_compile_unit */
+ .byte 1 /* DW_CHILDREN_yes */
+ .byte 37 /* DW_AT_producer */
+ .byte 37 /* DW_FORM_strx1 */
+ .byte 0 /* EOM(1) */
+ .byte 0 /* EOM(2) */
+ .byte 0 /* EOM(3) */
diff --git a/binutils/testsuite/binutils-all/readelf.exp b/binutils/testsuite/binutils-all/readelf.exp
index 9f20cb42812..b381562dbc6 100644
--- a/binutils/testsuite/binutils-all/readelf.exp
+++ b/binutils/testsuite/binutils-all/readelf.exp
@@ -403,6 +403,7 @@ if {[which $AS] != 0} then {
run_dump_test "readelf-maskos-1a"
run_dump_test "readelf-maskos-1b"
run_dump_test "readelf-debug-str-offsets-dw4"
+ run_dump_test "readelf-str-offsets-base"
if {![istarget *-*-hpux*]} then {
run_dump_test pr26548
if {![binutils_assemble_flags $srcdir/$subdir/pr26548.s tmpdir/pr26548e.o {--defsym ERROR=1}]} then {
base-commit: 84f7f8940760d0eaeb51a38b345db369b4207e5b
--
2.35.3
More information about the Binutils
mailing list