[2/2] gdb/dwarf: keep going even if reading macro information fails
Checks
Context |
Check |
Description |
linaro-tcwg-bot/tcwg_gdb_build--master-aarch64 |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gdb_build--master-arm |
success
|
Build passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-aarch64 |
success
|
Test passed
|
linaro-tcwg-bot/tcwg_gdb_check--master-arm |
success
|
Test passed
|
Commit Message
On Debian 12, with gcc 12 and ld 2.40, I get some failures when running:
$ make check TESTS="gdb.base/style.exp" RUNTESTFLAGS="--target_board=fission"
I think I stumble on this bug [1], preventing the test from doing
anything that requires expanding the compilation unit:
$ ./gdb -nx -q --data-directory=data-directory testsuite/outputs/gdb.base/style/style
Reading symbols from testsuite/outputs/gdb.base/style/style...
(gdb) p main
DW_FORM_strp pointing outside of .debug_str section [in module /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/style/style]
(gdb)
The error is thrown here:
#0 0x00007ffff693f0a1 in __cxa_throw () from /lib/x86_64-linux-gnu/libstdc++.so.6
#1 0x0000555569ce6852 in throw_it(return_reason, errors, const char *, typedef __va_list_tag __va_list_tag *) (reason=RETURN_ERROR, error=GENERIC_ERROR, fmt=0x555562a9fc40 "%s pointing outside of %s section [in module %s]", ap=0x7fffffff8df0) at /home/smarchi/src/binutils-gdb/gdbsupport/common-exceptions.cc:203
#2 0x0000555569ce690f in throw_verror (error=GENERIC_ERROR, fmt=0x555562a9fc40 "%s pointing outside of %s section [in module %s]", ap=0x7fffffff8df0) at /home/smarchi/src/binutils-gdb/gdbsupport/common-exceptions.cc:211
#3 0x000055556879c0cb in verror (string=0x555562a9fc40 "%s pointing outside of %s section [in module %s]", args=0x7fffffff8df0) at /home/smarchi/src/binutils-gdb/gdb/utils.c:193
#4 0x0000555569cfa88d in error (fmt=0x555562a9fc40 "%s pointing outside of %s section [in module %s]") at /home/smarchi/src/binutils-gdb/gdbsupport/errors.cc:45
#5 0x000055556667dbff in dwarf2_section_info::read_string (this=0x61b000042a08, objfile=0x616000055e80, str_offset=262811, form_name=0x555562886b40 "DW_FORM_strp") at /home/smarchi/src/binutils-gdb/gdb/dwarf2/section.c:211
#6 0x00005555662486b7 in dwarf_decode_macro_bytes (per_objfile=0x616000056180, builder=0x614000006040, abfd=0x6120000f4b40, mac_ptr=0x60300004f5be "", mac_end=0x60300004f5bb "\002\004", current_file=0x62100007ad70, lh=0x60f000028bd0, section=0x61700008ba78, section_is_gnu=1, section_is_dwz=0, offset_size=4, str_section=0x61700008bac8, str_offsets_section=0x61700008baf0, str_offsets_base=std::optional<unsigned long> = {...}, include_hash=..., cu=0x61700008b600) at /home/smarchi/src/binutils-gdb/gdb/dwarf2/macro.c:511
#7 0x000055556624af0e in dwarf_decode_macros (per_objfile=0x616000056180, builder=0x614000006040, section=0x61700008ba78, lh=0x60f000028bd0, offset_size=4, offset=0, str_section=0x61700008bac8, str_offsets_section=0x61700008baf0, str_offsets_base=std::optional<unsigned long> = {...}, section_is_gnu=1, cu=0x61700008b600) at /home/smarchi/src/binutils-gdb/gdb/dwarf2/macro.c:934
#8 0x000055556642cb82 in dwarf_decode_macros (cu=0x61700008b600, offset=0, section_is_gnu=1) at /home/smarchi/src/binutils-gdb/gdb/dwarf2/read.c:19435
#9 0x000055556639bd12 in read_file_scope (die=0x6210000885c0, cu=0x61700008b600) at /home/smarchi/src/binutils-gdb/gdb/dwarf2/read.c:6366
#10 0x0000555566392d99 in process_die (die=0x6210000885c0, cu=0x61700008b600) at /home/smarchi/src/binutils-gdb/gdb/dwarf2/read.c:5310
#11 0x0000555566390d72 in process_full_comp_unit (cu=0x61700008b600, pretend_language=language_minimal) at /home/smarchi/src/binutils-gdb/gdb/dwarf2/read.c:5075
The exception is then only caught at the event-loop level
(start_event_loop), causing the whole debug info reading process to be
aborted. I think it's a little harsh, considering that a lot of things
could work even if we failed to read macro information.
Catch the exception inside read_file_scope, print the exception, and
carry on. We could go even more fine-grained: if reading the string for
one macro definition fails, we could continue reading the macro
information. Perhaps it's just that one macro definition that is
broken. However, I don't need this level of granularity, so I haven't
attempted this. Also, my experience is that macro reading fails when
the compiler or linker has a bug, in which case pretty much everything
is messed up.
With this patch, it now looks like:
$ ./gdb -nx -q --data-directory=data-directory testsuite/outputs/gdb.base/style/style
Reading symbols from testsuite/outputs/gdb.base/style/style...
(gdb) p main
While reading section .debug_macro.dwo: DW_FORM_strp pointing outside of .debug_str section [in module /home/smarchi/build/binutils-gdb/gdb/testsuite/outputs/gdb.base/style/style]
$1 = {int (int, char **)} 0x684 <main>
(gdb)
In the test I am investigating (gdb.base/style.exp with the fission
board), it allows more tests to run:
-# of expected passes 107
-# of unexpected failures 17
+# of expected passes 448
+# of unexpected failures 19
Of course, we still see the error about the macro information, and some
macro-related tests still fail (those would be kfailed ideally), but
many tests that are not macro-dependent now pass.
[1] https://gcc.gnu.org/bugzilla/show_bug.cgi?id=111409
Change-Id: I0bdb01f153eff23c63c96ce3f41114bb027e5796
---
gdb/dwarf2/read.c | 17 ++++++++++++++---
1 file changed, 14 insertions(+), 3 deletions(-)
Comments
>>>>> "Simon" == Simon Marchi <simon.marchi@efficios.com> writes:
Simon> Catch the exception inside read_file_scope, print the exception, and
Simon> carry on.
Thanks for doing this.
Approved-By: Tom Tromey <tom@tromey.com>
[finer-grained exception handling]
Simon> However, I don't need this level of granularity, so I haven't
Simon> attempted this. Also, my experience is that macro reading fails when
Simon> the compiler or linker has a bug, in which case pretty much everything
Simon> is messed up.
FWIW I agree with this approach.
Tom
On 3/13/25 11:33 AM, Tom Tromey wrote:
>>>>>> "Simon" == Simon Marchi <simon.marchi@efficios.com> writes:
>
> Simon> Catch the exception inside read_file_scope, print the exception, and
> Simon> carry on.
>
> Thanks for doing this.
> Approved-By: Tom Tromey <tom@tromey.com>
>
>
> [finer-grained exception handling]
> Simon> However, I don't need this level of granularity, so I haven't
> Simon> attempted this. Also, my experience is that macro reading fails when
> Simon> the compiler or linker has a bug, in which case pretty much everything
> Simon> is messed up.
>
> FWIW I agree with this approach.
>
> Tom
Thanks, pushed both.
Simon
@@ -50,6 +50,7 @@
#include "bfd.h"
#include "elf-bfd.h"
#include "event-top.h"
+#include "exceptions.h"
#include "gdbsupport/task-group.h"
#include "symtab.h"
#include "gdbtypes.h"
@@ -19432,9 +19433,19 @@ dwarf_decode_macros (struct dwarf2_cu *cu, unsigned int offset,
str_offsets_base = cu->str_offsets_base;
}
- dwarf_decode_macros (per_objfile, builder, section, lh,
- offset_size, offset, str_section, str_offsets_section,
- str_offsets_base, section_is_gnu, cu);
+ try
+ {
+ dwarf_decode_macros (per_objfile, builder, section, lh, offset_size,
+ offset, str_section, str_offsets_section,
+ str_offsets_base, section_is_gnu, cu);
+ }
+ catch (const gdb_exception_error &error)
+ {
+ /* Print the error and carry on with no (or partial) macro
+ information. */
+ exception_fprintf (gdb_stderr, error, _("While reading section %s: "),
+ section->get_name ());
+ }
}
/* Return the .debug_loc section to use for CU.