Consider a hello world, compiled as the fission board does, with -g3 added: ... $ gcc -gdwarf-4 -gsplit-dwarf -ggnu-pubnames -fdebug-types-section -Wl,--gdb-index -fuse-ld=gold ~/gdb/hello.c -g3 ... When loading the exec in gdb, we get: ... $ gdb -q a.out Reading symbols from a.out... DW_FORM_strp pointing outside of .debug_str section [in module /home/vries/binutils/a.out] (gdb) ... Debugging this shows that this is triggered from: ... 207 if (str_offset >= size) 208 error (_("%s pointing outside of %s section [in module %s]"), 209 form_name, get_name (), get_file_name ()); ... with: ... (gdb) p size $3 = 33 (gdb) p str_offset $4 = 553845450 ... Clearly there's something going wrong with the str_offset, that's way too big. But the size of 33 is very small. It's correct though, it's the size of the .debug_str section in a.out. Going up to dwarf_decode_macro_bytes, we see this is the reason we're using that .debug_str section: ... 533 body = per_objfile->per_bfd->str.read_string (objfile, ... However, there's a str_section argument that points to the .debug_str section in a-hello.dwo: ... gdb) p *str_section $6 = {s = {section = 0xaaaaabc1a718, containing_section = 0xaaaaabc1a718}, buffer = 0xaaaaabc1b5b0 "__LDBL_DECIMAL_DIG__ 36", size = 24351, virtual_offset = 0, readin = true, is_virtual = false} ... I wonder if we shouldn't be using that one.
Using: ... diff --git a/gdb/dwarf2/macro.c b/gdb/dwarf2/macro.c index a511d0a3b44..7ecaf8044b9 100644 --- a/gdb/dwarf2/macro.c +++ b/gdb/dwarf2/macro.c @@ -529,9 +529,8 @@ dwarf_decode_macro_bytes (dwarf2_per_objfile *per_objfile, body = dwz->read_string (objfile, str_offset); } else - body = per_objfile->per_bfd->str.read_string (objfile, - str_offset, - "DW_FORM_strp"); + body = str_section->read_string (objfile, str_offset, + "DW_FORM_strp"); } is_define = (macinfo_type == DW_MACRO_define ... I get instead: ... $ gdb -q -batch a.out -ex "p main" DW_FORM_strp pointing outside of .debug_str.dwo section [in module /home/vries/gdb/a-hello.dwo] ...
When compiling the test-case with gcc 14 instead of 13 the error disappears. But that's due to a complaint, which is silently ignored by default: ... $ gdb -q -batch -iex "set complaints 1000" a.out -ex "p main" During symbol reading: unrecognized DW_MACINFO or DW_MACRO opcode 0xcc $1 = {int (void)} 0x4006ac <main> ... and aborts reading of .debug_macros before reaching the second pass in dwarf_decode_macros.
I found a bug in gcc dwarf generation ( https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115066 ), and the tentative fix makes this problem unlikely to hit. Nevertheless, using the fixed dwarf, we run into a bug in gdb, observable, by enabling complaints. Fixed by: ... diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 049ee4d52ff..e2cfa46516b 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -21200,7 +21200,10 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset, str_offsets_section = &cu->dwo_unit->dwo_file ->sections.str_offsets; str_section = &cu->dwo_unit->dwo_file->sections.str; - str_offsets_base = cu->header.addr_size; + if (cu->per_cu->version () <= 4) + str_offsets_base = 0; + else + str_offsets_base = cu->header.addr_size; } else { ... FWIW, the "str_offsets_base = cu->header.addr_size" makes no sense to me atm.
(In reply to Tom de Vries from comment #3) > FWIW, the "str_offsets_base = cu->header.addr_size" makes no sense to me atm. Yeah, that's gotta be 8 for dwarf32 and 16 for dwarf64.
(In reply to Tom de Vries from comment #4) > (In reply to Tom de Vries from comment #3) > > FWIW, the "str_offsets_base = cu->header.addr_size" makes no sense to me atm. > > Yeah, that's gotta be 8 for dwarf32 and 16 for dwarf64. Which probably should be handled elsewhere. At the point we're assigning this, there's no knowledge of whether the .debug_str_offsets section is dwarf32 or dwarf64.
This seems to work: ... diff --git a/gdb/dwarf2/read.c b/gdb/dwarf2/read.c index 049ee4d52ff..2ab94b0dd27 100644 --- a/gdb/dwarf2/read.c +++ b/gdb/dwarf2/read.c @@ -21200,7 +21200,21 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset, str_offsets_section = &cu->dwo_unit->dwo_file ->sections.str_offsets; str_section = &cu->dwo_unit->dwo_file->sections.str; - str_offsets_base = cu->header.addr_size; + if (cu->per_cu->version () <= 4) + str_offsets_base = 0; + else + { + bfd *abfd = str_offsets_section->get_bfd_owner (); + unsigned int bytes_read; + read_initial_length (abfd, str_offsets_section->buffer, &bytes_read, false); + if (!(bytes_read == 4 || bytes_read == 12)) + { + complaint (_("Can't get initial length of %s"), str_offsets_section->get_name ()); + return; + } + const bool is_dwarf64 = bytes_read != 4; + str_offsets_base = is_dwarf64 ? 16 : 8; + } } else { ...
The fix from comment 1 is probably a good fix, but it'll need a dwarf assembly test-case to trigger it. The fix from comment 6 is submitted in bits and pieces in the patch series submitted here ( https://sourceware.org/pipermail/gdb-patches/2024-May/209298.html ).