* [PATCH] gdb: skip objfiles with no BFD in DWARF unwinder @ 2022-04-05 10:04 Jan Vrany 2022-04-05 14:19 ` Lancelot SIX ` (2 more replies) 0 siblings, 3 replies; 9+ messages in thread From: Jan Vrany @ 2022-04-05 10:04 UTC (permalink / raw) To: gdb-patches; +Cc: Jan Vrany While playing with JIT reader I experienced GDB to crash on null-pointer dereference when stepping through non-jitted code. The problem was that dwarf2_frame_find_fde () assumed that all objfiles have BFD but that's not always true. To address this problem, this commit skips such objfiles. As for the test, I initially tried to use temporary breakpoint and then 'continue' to get out of the jitted code but this for some reason did not trigger the crash. Using 'finish' to get out of jitted code followed by 'next' triggered it. --- gdb/dwarf2/frame.c | 3 +++ gdb/objfiles.h | 4 +++- gdb/testsuite/gdb.base/jit-reader.exp | 10 ++++++++++ 3 files changed, 16 insertions(+), 1 deletion(-) diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c index 5878d72f922..514ae8c694f 100644 --- a/gdb/dwarf2/frame.c +++ b/gdb/dwarf2/frame.c @@ -1565,6 +1565,9 @@ dwarf2_frame_find_fde (CORE_ADDR *pc, dwarf2_per_objfile **out_per_objfile) CORE_ADDR offset; CORE_ADDR seek_pc; + if (objfile->obfd == nullptr) + continue; + comp_unit *unit = find_comp_unit (objfile); if (unit == NULL) { diff --git a/gdb/objfiles.h b/gdb/objfiles.h index 8bd76705688..429dea1da4c 100644 --- a/gdb/objfiles.h +++ b/gdb/objfiles.h @@ -636,7 +636,9 @@ struct objfile struct compunit_symtab *compunit_symtabs = nullptr; /* The object file's BFD. Can be null if the objfile contains only - minimal symbols, e.g. the run time common symbols for SunOS4. */ + minimal symbols (e.g. the run time common symbols for SunOS4) or + if the objfile is a dynamic objfile (e.g. created by JIT reader + API). */ bfd *obfd; diff --git a/gdb/testsuite/gdb.base/jit-reader.exp b/gdb/testsuite/gdb.base/jit-reader.exp index d94360cd7d9..0de552b1ce5 100644 --- a/gdb/testsuite/gdb.base/jit-reader.exp +++ b/gdb/testsuite/gdb.base/jit-reader.exp @@ -271,6 +271,16 @@ proc jit_reader_test {} { "#1 ${any} in main ${any}" \ ] } + + # check that the DWARF unwinder does not crash in presence of + # JIT objfiles. + gdb_test "fin" \ + [multi_line \ + "Run till exit from ${any} jit_function_stack_mangle ${any}" \ + "main ${any} at ${any}.*" \ + ] + gdb_test "bt" "#0 main ${any} at ${any}" + gdb_test "next" } jit_reader_test -- 2.35.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] gdb: skip objfiles with no BFD in DWARF unwinder 2022-04-05 10:04 [PATCH] gdb: skip objfiles with no BFD in DWARF unwinder Jan Vrany @ 2022-04-05 14:19 ` Lancelot SIX 2022-04-05 14:46 ` Simon Marchi 2022-04-05 19:08 ` Pedro Alves 2 siblings, 0 replies; 9+ messages in thread From: Lancelot SIX @ 2022-04-05 14:19 UTC (permalink / raw) To: Jan Vrany; +Cc: gdb-patches Hi, > diff --git a/gdb/testsuite/gdb.base/jit-reader.exp b/gdb/testsuite/gdb.base/jit-reader.exp > index d94360cd7d9..0de552b1ce5 100644 > --- a/gdb/testsuite/gdb.base/jit-reader.exp > +++ b/gdb/testsuite/gdb.base/jit-reader.exp > @@ -271,6 +271,16 @@ proc jit_reader_test {} { > "#1 ${any} in main ${any}" \ > ] > } > + > + # check that the DWARF unwinder does not crash in presence of > + # JIT objfiles. > + gdb_test "fin" \ > + [multi_line \ > + "Run till exit from ${any} jit_function_stack_mangle ${any}" \ > + "main ${any} at ${any}.*" \ > + ] > + gdb_test "bt" "#0 main ${any} at ${any}" > + gdb_test "next" > } The tests above use with_test_prefix to create logical blocks. You probably want to wrap what you just added in a similar construct. This is for consistency, it creates .sum/.log files easier to work with and also if one wants to add other commands just below those one, we do not risk having DUPLICATE test names. Best, Lancelot. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] gdb: skip objfiles with no BFD in DWARF unwinder 2022-04-05 10:04 [PATCH] gdb: skip objfiles with no BFD in DWARF unwinder Jan Vrany 2022-04-05 14:19 ` Lancelot SIX @ 2022-04-05 14:46 ` Simon Marchi 2022-04-06 17:50 ` Jan Vrany 2022-04-05 19:08 ` Pedro Alves 2 siblings, 1 reply; 9+ messages in thread From: Simon Marchi @ 2022-04-05 14:46 UTC (permalink / raw) To: Jan Vrany, gdb-patches On 2022-04-05 06:04, Jan Vrany via Gdb-patches wrote: > While playing with JIT reader I experienced GDB to crash on null-pointer > dereference when stepping through non-jitted code. > > The problem was that dwarf2_frame_find_fde () assumed that all objfiles > have BFD but that's not always true. To address this problem, this > commit skips such objfiles. > > As for the test, I initially tried to use temporary breakpoint and then > 'continue' to get out of the jitted code but this for some reason did > not trigger the crash. Using 'finish' to get out of jitted code followed > by 'next' triggered it. > --- > gdb/dwarf2/frame.c | 3 +++ > gdb/objfiles.h | 4 +++- > gdb/testsuite/gdb.base/jit-reader.exp | 10 ++++++++++ > 3 files changed, 16 insertions(+), 1 deletion(-) > > diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c > index 5878d72f922..514ae8c694f 100644 > --- a/gdb/dwarf2/frame.c > +++ b/gdb/dwarf2/frame.c > @@ -1565,6 +1565,9 @@ dwarf2_frame_find_fde (CORE_ADDR *pc, dwarf2_per_objfile **out_per_objfile) > CORE_ADDR offset; > CORE_ADDR seek_pc; > > + if (objfile->obfd == nullptr) > + continue; Ok, I presume that this is the case only for JIT-ed objfiles whose debuginfo was created using the JIT debug info reader API. If the JIT engine produced an executable file in memory with DWARF in it and we consumed it, then I suppose that objfile will have a bfd, since it was opened and parsed using bfd. > + > comp_unit *unit = find_comp_unit (objfile); > if (unit == NULL) > { > diff --git a/gdb/objfiles.h b/gdb/objfiles.h > index 8bd76705688..429dea1da4c 100644 > --- a/gdb/objfiles.h > +++ b/gdb/objfiles.h > @@ -636,7 +636,9 @@ struct objfile > struct compunit_symtab *compunit_symtabs = nullptr; > > /* The object file's BFD. Can be null if the objfile contains only > - minimal symbols, e.g. the run time common symbols for SunOS4. */ > + minimal symbols (e.g. the run time common symbols for SunOS4) or > + if the objfile is a dynamic objfile (e.g. created by JIT reader > + API). */ > > bfd *obfd; > > diff --git a/gdb/testsuite/gdb.base/jit-reader.exp b/gdb/testsuite/gdb.base/jit-reader.exp > index d94360cd7d9..0de552b1ce5 100644 > --- a/gdb/testsuite/gdb.base/jit-reader.exp > +++ b/gdb/testsuite/gdb.base/jit-reader.exp > @@ -271,6 +271,16 @@ proc jit_reader_test {} { > "#1 ${any} in main ${any}" \ > ] > } > + > + # check that the DWARF unwinder does not crash in presence of Capital C to "check". > + # JIT objfiles. > + gdb_test "fin" \ > + [multi_line \ > + "Run till exit from ${any} jit_function_stack_mangle ${any}" \ > + "main ${any} at ${any}.*" \ > + ] > + gdb_test "bt" "#0 main ${any} at ${any}" > + gdb_test "next" Please take in consideration Lancelot's comment, the patch LGTM with that feedback addressed. Simon ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] gdb: skip objfiles with no BFD in DWARF unwinder 2022-04-05 14:46 ` Simon Marchi @ 2022-04-06 17:50 ` Jan Vrany 0 siblings, 0 replies; 9+ messages in thread From: Jan Vrany @ 2022-04-06 17:50 UTC (permalink / raw) To: Simon Marchi, gdb-patches; +Cc: Lancelot SIX On Tue, 2022-04-05 at 10:46 -0400, Simon Marchi wrote: > On 2022-04-05 06:04, Jan Vrany via Gdb-patches wrote: > > While playing with JIT reader I experienced GDB to crash on null-pointer > > dereference when stepping through non-jitted code. > > > > The problem was that dwarf2_frame_find_fde () assumed that all objfiles > > have BFD but that's not always true. To address this problem, this > > commit skips such objfiles. > > > > As for the test, I initially tried to use temporary breakpoint and then > > 'continue' to get out of the jitted code but this for some reason did > > not trigger the crash. Using 'finish' to get out of jitted code followed > > by 'next' triggered it. > > --- > > gdb/dwarf2/frame.c | 3 +++ > > gdb/objfiles.h | 4 +++- > > gdb/testsuite/gdb.base/jit-reader.exp | 10 ++++++++++ > > 3 files changed, 16 insertions(+), 1 deletion(-) > > > > diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c > > index 5878d72f922..514ae8c694f 100644 > > --- a/gdb/dwarf2/frame.c > > +++ b/gdb/dwarf2/frame.c > > @@ -1565,6 +1565,9 @@ dwarf2_frame_find_fde (CORE_ADDR *pc, dwarf2_per_objfile **out_per_objfile) > > CORE_ADDR offset; > > CORE_ADDR seek_pc; > > > > + if (objfile->obfd == nullptr) > > + continue; > > Ok, I presume that this is the case only for JIT-ed objfiles whose > debuginfo was created using the JIT debug info reader API. If the JIT > engine produced an executable file in memory with DWARF in it and we > consumed it, then I suppose that objfile will have a bfd, since it was > opened and parsed using bfd. Exactly. jit_bfd_try_read_symtab() calls objfile = symbol_file_add_from_bfd (nbfd.get (), ...); > > > + > > comp_unit *unit = find_comp_unit (objfile); > > if (unit == NULL) > > { > > diff --git a/gdb/objfiles.h b/gdb/objfiles.h > > index 8bd76705688..429dea1da4c 100644 > > --- a/gdb/objfiles.h > > +++ b/gdb/objfiles.h > > @@ -636,7 +636,9 @@ struct objfile > > struct compunit_symtab *compunit_symtabs = nullptr; > > > > /* The object file's BFD. Can be null if the objfile contains only > > - minimal symbols, e.g. the run time common symbols for SunOS4. */ > > + minimal symbols (e.g. the run time common symbols for SunOS4) or > > + if the objfile is a dynamic objfile (e.g. created by JIT reader > > + API). */ > > > > bfd *obfd; > > > > diff --git a/gdb/testsuite/gdb.base/jit-reader.exp b/gdb/testsuite/gdb.base/jit-reader.exp > > index d94360cd7d9..0de552b1ce5 100644 > > --- a/gdb/testsuite/gdb.base/jit-reader.exp > > +++ b/gdb/testsuite/gdb.base/jit-reader.exp > > @@ -271,6 +271,16 @@ proc jit_reader_test {} { > > "#1 ${any} in main ${any}" \ > > ] > > } > > + > > + # check that the DWARF unwinder does not crash in presence of > > Capital C to "check". > > > + # JIT objfiles. > > + gdb_test "fin" \ > > + [multi_line \ > > + "Run till exit from ${any} jit_function_stack_mangle ${any}" \ > > + "main ${any} at ${any}.*" \ > > + ] > > + gdb_test "bt" "#0 main ${any} at ${any}" > > + gdb_test "next" > > Please take in consideration Lancelot's comment, the patch LGTM with > that feedback addressed. Sure! Thanks Lancelot! Jan ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] gdb: skip objfiles with no BFD in DWARF unwinder 2022-04-05 10:04 [PATCH] gdb: skip objfiles with no BFD in DWARF unwinder Jan Vrany 2022-04-05 14:19 ` Lancelot SIX 2022-04-05 14:46 ` Simon Marchi @ 2022-04-05 19:08 ` Pedro Alves 2022-04-06 18:06 ` Jan Vrany 2022-04-06 18:55 ` [PATCH v2] " Jan Vrany 2 siblings, 2 replies; 9+ messages in thread From: Pedro Alves @ 2022-04-05 19:08 UTC (permalink / raw) To: Jan Vrany, gdb-patches On 2022-04-05 11:04, Jan Vrany via Gdb-patches wrote: > While playing with JIT reader I experienced GDB to crash on null-pointer > dereference when stepping through non-jitted code. > > The problem was that dwarf2_frame_find_fde () assumed that all objfiles > have BFD but that's not always true. To address this problem, this > commit skips such objfiles. > > As for the test, I initially tried to use temporary breakpoint and then > 'continue' to get out of the jitted code but this for some reason did > not trigger the crash. Using 'finish' to get out of jitted code followed > by 'next' triggered it. I tried it here and here's what I saw. So "next" is stepping over the "function_add" function. While "next"ing, GDB stops at the first instruction of function_add, and looks at the frame's type, which runs all the frame sniffers looking for one that claims the frame, including the DWARF unwinder, and here is where we run into the crash: $ gdb ... (gdb) start ... Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdc08) at /home/pedro/gdb/binutils-gdb/src/gdb/testsuite/gdb.base/jit-reader-host.c:58 58 struct jithost_abi *symfile = malloc (sizeof (struct jithost_abi)); (gdb) jit-reader-load /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/jit-reader/jit-reader.so (gdb) b 95 Breakpoint 2 at 0x555555555322: file /home/pedro/gdb/binutils-gdb/src/gdb/testsuite/gdb.base/jit-reader-host.c, line 95. (gdb) c Continuing. Program received signal SIGTRAP, Trace/breakpoint trap. 0x00007ffff7ffb001 in jit_function_stack_mangle () (gdb) c Continuing. Breakpoint 2, main (argc=1, argv=0x7fffffffdc08) at /home/pedro/gdb/binutils-gdb/src/gdb/testsuite/gdb.base/jit-reader-host.c:95 95 function_add (5, 6); (gdb) set debug infrun 1 (gdb) n ... [infrun] start_step_over: exit [infrun] context_switch: Switching context from 0.0.0 to 353387.353387.0 [infrun] handle_signal_stop: stop_pc=0x7ffff7ffb00a ... Thread 1 "gdb" received signal SIGSEGV, Segmentation fault. 0x00005555559886c8 in bfd_usrdata (abfd=0x0) at ../bfd/bfd.h:6919 6919 return abfd->usrdata; (top-gdb) bt #0 0x00005555559886c8 in bfd_usrdata (abfd=0x0) at ../bfd/bfd.h:6919 #1 0x000055555598a65f in gdb_bfd_requires_relocations (abfd=0x0) at /home/pedro/gdb/binutils-gdb/src/gdb/gdb_bfd.c:1030 #2 0x0000555555885dbb in find_comp_unit (objfile=0x5555565a6170) at /home/pedro/gdb/binutils-gdb/src/gdb/dwarf2/frame.c:1538 #3 0x0000555555885efa in dwarf2_frame_find_fde (pc=0x7fffffffd008, out_per_objfile=0x0) at /home/pedro/gdb/binutils-gdb/src/gdb/dwarf2/frame.c:1568 #4 0x0000555555885591 in dwarf2_frame_sniffer (self=0x555556426440 <dwarf2_frame_unwind>, this_frame=0x555556d6b7f0, this_cache=0x555556d6b808) at /home/pedro/gdb/binutils-gdb/src/gdb/dwarf2/frame.c:1254 #5 0x0000555555979639 in frame_unwind_try_unwinder (this_frame=0x555556d6b7f0, this_cache=0x555556d6b808, unwinder=0x555556426440 <dwarf2_frame_unwind>) at /home/pedro/gdb/binutils-gdb/src/gdb/frame-unwind.c:131 #6 0x000055555597991a in frame_unwind_find_by_frame (this_frame=0x555556d6b7f0, this_cache=0x555556d6b808) at /home/pedro/gdb/binutils-gdb/src/gdb/frame-unwind.c:203 #7 0x0000555555980948 in get_frame_type (frame=0x555556d6b7f0) at /home/pedro/gdb/binutils-gdb/src/gdb/frame.c:2817 #8 0x0000555555a2187b in process_event_stop_test (ecs=0x7fffffffd7c0) at /home/pedro/gdb/binutils-gdb/src/gdb/infrun.c:6966 #9 0x0000555555a20b3f in handle_signal_stop (ecs=0x7fffffffd7c0) at /home/pedro/gdb/binutils-gdb/src/gdb/infrun.c:6585 #10 0x0000555555a1ec37 in handle_inferior_event (ecs=0x7fffffffd7c0) at /home/pedro/gdb/binutils-gdb/src/gdb/infrun.c:5837 ... That get_frame_type call is from here: 6963 if (ecs->event_thread->control.step_range_end != 1 6964 && (ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE 6965 || ecs->event_thread->control.step_over_calls == STEP_OVER_ALL) 6966 && get_frame_type (frame) == SIGTRAMP_FRAME) 6967 { 6968 infrun_debug_printf ("stepped into signal trampoline"); OK, that makes sense. We stopped at 0x7ffff7ffb00a, which is function_add, and GDB tried to get info about the current frame. This means that we can write a more targeted testcase that does not rely on how "next" works. What is important is that we trigger the unwinding machinery inside the "function_add" function. So... (gdb) jit-reader-load /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/jit-reader/jit-reader.so (gdb) b 95 Breakpoint 1 at 0x1322: file /home/pedro/gdb/binutils-gdb/src/gdb/testsuite/gdb.base/jit-reader-host.c, line 95. (gdb) r Starting program: /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/jit-reader/jit-reader Program received signal SIGTRAP, Trace/breakpoint trap. 0x00007ffff7ffb001 in jit_function_stack_mangle () (gdb) c Continuing. Breakpoint 1, main (argc=1, argv=0x7fffffffdc08) at /home/pedro/gdb/binutils-gdb/src/gdb/testsuite/gdb.base/jit-reader-host.c:95 95 function_add (5, 6); (gdb) b *function_add Breakpoint 2 at 0x7ffff7ffb00a (gdb) c Continuing. Thread 1 "gdb" received signal SIGSEGV, Segmentation fault. 0x00005555559886c8 in bfd_usrdata (During symbol reading: incomplete CFI data; unspecified registers (e.g., rax) at 0x5555559886d0 abfd=0x0) at ../bfd/bfd.h:6919 6919 return abfd->usrdata; (top-gdb) So in a nutshell, it would be better for the test to do: fin b *function_add c << this crashes as GDB prints the current frame bt << add this for good measure. Instead of: fin bt << not clear what this is for next << reaches the unwinder today, triggering the crash, but who knows the future ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH] gdb: skip objfiles with no BFD in DWARF unwinder 2022-04-05 19:08 ` Pedro Alves @ 2022-04-06 18:06 ` Jan Vrany 2022-04-06 18:55 ` [PATCH v2] " Jan Vrany 1 sibling, 0 replies; 9+ messages in thread From: Jan Vrany @ 2022-04-06 18:06 UTC (permalink / raw) To: Pedro Alves, gdb-patches On Tue, 2022-04-05 at 20:08 +0100, Pedro Alves wrote: > On 2022-04-05 11:04, Jan Vrany via Gdb-patches wrote: > > While playing with JIT reader I experienced GDB to crash on null-pointer > > dereference when stepping through non-jitted code. > > > > The problem was that dwarf2_frame_find_fde () assumed that all objfiles > > have BFD but that's not always true. To address this problem, this > > commit skips such objfiles. > > > > As for the test, I initially tried to use temporary breakpoint and then > > 'continue' to get out of the jitted code but this for some reason did > > not trigger the crash. Using 'finish' to get out of jitted code followed > > by 'next' triggered it. > > I tried it here and here's what I saw. So "next" is stepping over the > "function_add" function. While "next"ing, GDB stops at the first instruction of > function_add, and looks at the frame's type, which runs all the frame sniffers > looking for one that claims the frame, including the DWARF unwinder, and here is > where we run into the crash: > > $ gdb ... > (gdb) start > ... > Temporary breakpoint 1, main (argc=1, argv=0x7fffffffdc08) at /home/pedro/gdb/binutils-gdb/src/gdb/testsuite/gdb.base/jit-reader-host.c:58 > 58 struct jithost_abi *symfile = malloc (sizeof (struct jithost_abi)); > (gdb) jit-reader-load /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/jit-reader/jit-reader.so > (gdb) b 95 > Breakpoint 2 at 0x555555555322: file /home/pedro/gdb/binutils-gdb/src/gdb/testsuite/gdb.base/jit-reader-host.c, line 95. > (gdb) c > Continuing. > > Program received signal SIGTRAP, Trace/breakpoint trap. > 0x00007ffff7ffb001 in jit_function_stack_mangle () > (gdb) c > Continuing. > > Breakpoint 2, main (argc=1, argv=0x7fffffffdc08) at /home/pedro/gdb/binutils-gdb/src/gdb/testsuite/gdb.base/jit-reader-host.c:95 > 95 function_add (5, 6); > (gdb) set debug infrun 1 > (gdb) n > > ... > [infrun] start_step_over: exit > [infrun] context_switch: Switching context from 0.0.0 to 353387.353387.0 > [infrun] handle_signal_stop: stop_pc=0x7ffff7ffb00a > ... > > > Thread 1 "gdb" received signal SIGSEGV, Segmentation fault. > 0x00005555559886c8 in bfd_usrdata (abfd=0x0) at ../bfd/bfd.h:6919 > 6919 return abfd->usrdata; > (top-gdb) bt > #0 0x00005555559886c8 in bfd_usrdata (abfd=0x0) at ../bfd/bfd.h:6919 > #1 0x000055555598a65f in gdb_bfd_requires_relocations (abfd=0x0) at /home/pedro/gdb/binutils-gdb/src/gdb/gdb_bfd.c:1030 > #2 0x0000555555885dbb in find_comp_unit (objfile=0x5555565a6170) at /home/pedro/gdb/binutils-gdb/src/gdb/dwarf2/frame.c:1538 > #3 0x0000555555885efa in dwarf2_frame_find_fde (pc=0x7fffffffd008, out_per_objfile=0x0) at /home/pedro/gdb/binutils-gdb/src/gdb/dwarf2/frame.c:1568 > #4 0x0000555555885591 in dwarf2_frame_sniffer (self=0x555556426440 <dwarf2_frame_unwind>, this_frame=0x555556d6b7f0, this_cache=0x555556d6b808) at /home/pedro/gdb/binutils-gdb/src/gdb/dwarf2/frame.c:1254 > #5 0x0000555555979639 in frame_unwind_try_unwinder (this_frame=0x555556d6b7f0, this_cache=0x555556d6b808, unwinder=0x555556426440 <dwarf2_frame_unwind>) at /home/pedro/gdb/binutils-gdb/src/gdb/frame-unwind.c:131 > #6 0x000055555597991a in frame_unwind_find_by_frame (this_frame=0x555556d6b7f0, this_cache=0x555556d6b808) at /home/pedro/gdb/binutils-gdb/src/gdb/frame-unwind.c:203 > #7 0x0000555555980948 in get_frame_type (frame=0x555556d6b7f0) at /home/pedro/gdb/binutils-gdb/src/gdb/frame.c:2817 > #8 0x0000555555a2187b in process_event_stop_test (ecs=0x7fffffffd7c0) at /home/pedro/gdb/binutils-gdb/src/gdb/infrun.c:6966 > #9 0x0000555555a20b3f in handle_signal_stop (ecs=0x7fffffffd7c0) at /home/pedro/gdb/binutils-gdb/src/gdb/infrun.c:6585 > #10 0x0000555555a1ec37 in handle_inferior_event (ecs=0x7fffffffd7c0) at /home/pedro/gdb/binutils-gdb/src/gdb/infrun.c:5837 > ... > > That get_frame_type call is from here: > > 6963 if (ecs->event_thread->control.step_range_end != 1 > 6964 && (ecs->event_thread->control.step_over_calls == STEP_OVER_UNDEBUGGABLE > 6965 || ecs->event_thread->control.step_over_calls == STEP_OVER_ALL) > 6966 && get_frame_type (frame) == SIGTRAMP_FRAME) > 6967 { > 6968 infrun_debug_printf ("stepped into signal trampoline"); > > > > OK, that makes sense. We stopped at 0x7ffff7ffb00a, which is function_add, and GDB tried to get info > about the current frame. > > This means that we can write a more targeted testcase that does not rely on how "next" works. > What is important is that we trigger the unwinding machinery inside the "function_add" function. > Ah, I see now why I was puzzled why it did not work for me. The important bit (which I missed) is that in the test the JIT reader unwinder does not unwind function_add, *only* jit_function_stack_mangle, so it falls to back DWARF unwinder which then hit the objfile with no BFD. If I stop in main, it would likely find an objfile for the PC before hitting the JIT objfile so it won't trigger the crash. Thanks! I'll send v2 with updated testcase and commit message shortly. > So... > > (gdb) jit-reader-load /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/jit-reader/jit-reader.so > (gdb) b 95 > Breakpoint 1 at 0x1322: file /home/pedro/gdb/binutils-gdb/src/gdb/testsuite/gdb.base/jit-reader-host.c, line 95. > (gdb) r > Starting program: /home/pedro/gdb/binutils-gdb/build/gdb/testsuite/outputs/gdb.base/jit-reader/jit-reader > > Program received signal SIGTRAP, Trace/breakpoint trap. > 0x00007ffff7ffb001 in jit_function_stack_mangle () > (gdb) c > Continuing. > > Breakpoint 1, main (argc=1, argv=0x7fffffffdc08) at /home/pedro/gdb/binutils-gdb/src/gdb/testsuite/gdb.base/jit-reader-host.c:95 > 95 function_add (5, 6); > (gdb) b *function_add > Breakpoint 2 at 0x7ffff7ffb00a > (gdb) c > Continuing. > > Thread 1 "gdb" received signal SIGSEGV, Segmentation fault. > 0x00005555559886c8 in bfd_usrdata (During symbol reading: incomplete CFI data; unspecified registers (e.g., rax) at 0x5555559886d0 > abfd=0x0) at ../bfd/bfd.h:6919 > 6919 return abfd->usrdata; > (top-gdb) > > > So in a nutshell, it would be better for the test to do: > > fin > b *function_add > c << this crashes as GDB prints the current frame > bt << add this for good measure. > > Instead of: > > fin > bt << not clear what this is for > next << reaches the unwinder today, triggering the crash, but who knows the future ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2] gdb: skip objfiles with no BFD in DWARF unwinder 2022-04-05 19:08 ` Pedro Alves 2022-04-06 18:06 ` Jan Vrany @ 2022-04-06 18:55 ` Jan Vrany 2022-12-07 11:07 ` Jan Vraný 2022-12-07 16:07 ` Simon Marchi 1 sibling, 2 replies; 9+ messages in thread From: Jan Vrany @ 2022-04-06 18:55 UTC (permalink / raw) To: gdb-patches; +Cc: Jan Vrany Changes since v1: * use with_test_prefix as Lancelot suggested * rewrote test as Pedro suggested * updated commit message -- >8 -- While playing with JIT reader I experienced GDB to crash on null-pointer dereference when stepping through non-jitted code. The problem was that dwarf2_frame_find_fde () assumed that all objfiles have BFD but that's not always true. To address this problem, this commit skips such objfiles. To test the fix we put breakpoint in jit_function_add (). The JIT reader does not know how unwind this function so unwinding eventually falls back to DWARF unwinder which in turn iterates over objfiles. Since the the code is jitted, it is guaranteed it would eventually process JIT objfile. --- gdb/dwarf2/frame.c | 3 +++ gdb/objfiles.h | 4 +++- gdb/testsuite/gdb.base/jit-reader.exp | 13 +++++++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c index 5878d72f922..514ae8c694f 100644 --- a/gdb/dwarf2/frame.c +++ b/gdb/dwarf2/frame.c @@ -1565,6 +1565,9 @@ dwarf2_frame_find_fde (CORE_ADDR *pc, dwarf2_per_objfile **out_per_objfile) CORE_ADDR offset; CORE_ADDR seek_pc; + if (objfile->obfd == nullptr) + continue; + comp_unit *unit = find_comp_unit (objfile); if (unit == NULL) { diff --git a/gdb/objfiles.h b/gdb/objfiles.h index 8bd76705688..429dea1da4c 100644 --- a/gdb/objfiles.h +++ b/gdb/objfiles.h @@ -636,7 +636,9 @@ struct objfile struct compunit_symtab *compunit_symtabs = nullptr; /* The object file's BFD. Can be null if the objfile contains only - minimal symbols, e.g. the run time common symbols for SunOS4. */ + minimal symbols (e.g. the run time common symbols for SunOS4) or + if the objfile is a dynamic objfile (e.g. created by JIT reader + API). */ bfd *obfd; diff --git a/gdb/testsuite/gdb.base/jit-reader.exp b/gdb/testsuite/gdb.base/jit-reader.exp index d94360cd7d9..756b400906c 100644 --- a/gdb/testsuite/gdb.base/jit-reader.exp +++ b/gdb/testsuite/gdb.base/jit-reader.exp @@ -271,6 +271,19 @@ proc jit_reader_test {} { "#1 ${any} in main ${any}" \ ] } + + with_test_prefix "test dwarf unwinder" { + # Check that the DWARF unwinder does not crash in presence of + # JIT objfiles. + gdb_test "up" + gdb_breakpoint "*function_add" temporary + gdb_test "cont" ".*Temporary breakpoint ${any} in jit_function_add .*" + gdb_test "bt" \ + [multi_line \ + "#0 ${any} in jit_function_add ${any}" \ + "#1 ${any} in main ${any}" \ + ] + } } jit_reader_test -- 2.35.1 ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] gdb: skip objfiles with no BFD in DWARF unwinder 2022-04-06 18:55 ` [PATCH v2] " Jan Vrany @ 2022-12-07 11:07 ` Jan Vraný 2022-12-07 16:07 ` Simon Marchi 1 sibling, 0 replies; 9+ messages in thread From: Jan Vraný @ 2022-12-07 11:07 UTC (permalink / raw) To: gdb-patches Oops, I was travelling shortly after sending this patch and completely forgot about it. So, a ping after a long time. For reference: * V1 patch: https://sourceware.org/pipermail/gdb-patches/2022-April/187457.html * Lancelot's comment: https://sourceware.org/pipermail/gdb-patches/2022-April/187475.html * Pedro's comment: https://sourceware.org/pipermail/gdb-patches/2022-April/187494.html Jan On Wed, 2022-04-06 at 20:55 +0200, Jan Vrany wrote: > Changes since v1: > > * use with_test_prefix as Lancelot suggested > * rewrote test as Pedro suggested > * updated commit message > > -- >8 -- > While playing with JIT reader I experienced GDB to crash on null-pointer > dereference when stepping through non-jitted code. > > The problem was that dwarf2_frame_find_fde () assumed that all objfiles > have BFD but that's not always true. To address this problem, this > commit skips such objfiles. > > To test the fix we put breakpoint in jit_function_add (). The JIT reader > does not know how unwind this function so unwinding eventually falls > back to DWARF unwinder which in turn iterates over objfiles. Since the > the code is jitted, it is guaranteed it would eventually process JIT > objfile. > --- > gdb/dwarf2/frame.c | 3 +++ > gdb/objfiles.h | 4 +++- > gdb/testsuite/gdb.base/jit-reader.exp | 13 +++++++++++++ > 3 files changed, 19 insertions(+), 1 deletion(-) > > diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c > index 5878d72f922..514ae8c694f 100644 > --- a/gdb/dwarf2/frame.c > +++ b/gdb/dwarf2/frame.c > @@ -1565,6 +1565,9 @@ dwarf2_frame_find_fde (CORE_ADDR *pc, dwarf2_per_objfile **out_per_objfile) > CORE_ADDR offset; > CORE_ADDR seek_pc; > > + if (objfile->obfd == nullptr) > + continue; > + > comp_unit *unit = find_comp_unit (objfile); > if (unit == NULL) > { > diff --git a/gdb/objfiles.h b/gdb/objfiles.h > index 8bd76705688..429dea1da4c 100644 > --- a/gdb/objfiles.h > +++ b/gdb/objfiles.h > @@ -636,7 +636,9 @@ struct objfile > struct compunit_symtab *compunit_symtabs = nullptr; > > /* The object file's BFD. Can be null if the objfile contains only > - minimal symbols, e.g. the run time common symbols for SunOS4. */ > + minimal symbols (e.g. the run time common symbols for SunOS4) or > + if the objfile is a dynamic objfile (e.g. created by JIT reader > + API). */ > > bfd *obfd; > > diff --git a/gdb/testsuite/gdb.base/jit-reader.exp b/gdb/testsuite/gdb.base/jit-reader.exp > index d94360cd7d9..756b400906c 100644 > --- a/gdb/testsuite/gdb.base/jit-reader.exp > +++ b/gdb/testsuite/gdb.base/jit-reader.exp > @@ -271,6 +271,19 @@ proc jit_reader_test {} { > "#1 ${any} in main ${any}" \ > ] > } > + > + with_test_prefix "test dwarf unwinder" { > + # Check that the DWARF unwinder does not crash in presence of > + # JIT objfiles. > + gdb_test "up" > + gdb_breakpoint "*function_add" temporary > + gdb_test "cont" ".*Temporary breakpoint ${any} in jit_function_add .*" > + gdb_test "bt" \ > + [multi_line \ > + "#0 ${any} in jit_function_add ${any}" \ > + "#1 ${any} in main ${any}" \ > + ] > + } > } > > jit_reader_test ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v2] gdb: skip objfiles with no BFD in DWARF unwinder 2022-04-06 18:55 ` [PATCH v2] " Jan Vrany 2022-12-07 11:07 ` Jan Vraný @ 2022-12-07 16:07 ` Simon Marchi 1 sibling, 0 replies; 9+ messages in thread From: Simon Marchi @ 2022-12-07 16:07 UTC (permalink / raw) To: Jan Vrany, gdb-patches On 4/6/22 14:55, Jan Vrany via Gdb-patches wrote: > Changes since v1: > > * use with_test_prefix as Lancelot suggested > * rewrote test as Pedro suggested > * updated commit message > > -- >8 -- > While playing with JIT reader I experienced GDB to crash on null-pointer > dereference when stepping through non-jitted code. > > The problem was that dwarf2_frame_find_fde () assumed that all objfiles > have BFD but that's not always true. To address this problem, this > commit skips such objfiles. > > To test the fix we put breakpoint in jit_function_add (). The JIT reader > does not know how unwind this function so unwinding eventually falls > back to DWARF unwinder which in turn iterates over objfiles. Since the > the code is jitted, it is guaranteed it would eventually process JIT > objfile. > --- > gdb/dwarf2/frame.c | 3 +++ > gdb/objfiles.h | 4 +++- > gdb/testsuite/gdb.base/jit-reader.exp | 13 +++++++++++++ > 3 files changed, 19 insertions(+), 1 deletion(-) > > diff --git a/gdb/dwarf2/frame.c b/gdb/dwarf2/frame.c > index 5878d72f922..514ae8c694f 100644 > --- a/gdb/dwarf2/frame.c > +++ b/gdb/dwarf2/frame.c > @@ -1565,6 +1565,9 @@ dwarf2_frame_find_fde (CORE_ADDR *pc, dwarf2_per_objfile **out_per_objfile) > CORE_ADDR offset; > CORE_ADDR seek_pc; > > + if (objfile->obfd == nullptr) > + continue; > + > comp_unit *unit = find_comp_unit (objfile); > if (unit == NULL) > { > diff --git a/gdb/objfiles.h b/gdb/objfiles.h > index 8bd76705688..429dea1da4c 100644 > --- a/gdb/objfiles.h > +++ b/gdb/objfiles.h > @@ -636,7 +636,9 @@ struct objfile > struct compunit_symtab *compunit_symtabs = nullptr; > > /* The object file's BFD. Can be null if the objfile contains only > - minimal symbols, e.g. the run time common symbols for SunOS4. */ > + minimal symbols (e.g. the run time common symbols for SunOS4) or > + if the objfile is a dynamic objfile (e.g. created by JIT reader > + API). */ > > bfd *obfd; > > diff --git a/gdb/testsuite/gdb.base/jit-reader.exp b/gdb/testsuite/gdb.base/jit-reader.exp > index d94360cd7d9..756b400906c 100644 > --- a/gdb/testsuite/gdb.base/jit-reader.exp > +++ b/gdb/testsuite/gdb.base/jit-reader.exp > @@ -271,6 +271,19 @@ proc jit_reader_test {} { > "#1 ${any} in main ${any}" \ > ] > } > + > + with_test_prefix "test dwarf unwinder" { > + # Check that the DWARF unwinder does not crash in presence of > + # JIT objfiles. > + gdb_test "up" > + gdb_breakpoint "*function_add" temporary > + gdb_test "cont" ".*Temporary breakpoint ${any} in jit_function_add .*" > + gdb_test "bt" \ > + [multi_line \ > + "#0 ${any} in jit_function_add ${any}" \ > + "#1 ${any} in main ${any}" \ > + ] > + } This test function is getting a tad long. In general, I find that it makes it difficult to know if some part of the test depends on the state left by a previous portion of the test, if adding something in the middle will break something later (or silently make a test not test what it intended to test anymore). I therefore like to split things up in small independent functions that each start with a clean GDB. This still LGTM though, not a blocker, but I thought I'd mention it for future changes. Approved-By: Simon Marchi <simon.marchi@efficios.com> Simon ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2022-12-07 16:07 UTC | newest] Thread overview: 9+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2022-04-05 10:04 [PATCH] gdb: skip objfiles with no BFD in DWARF unwinder Jan Vrany 2022-04-05 14:19 ` Lancelot SIX 2022-04-05 14:46 ` Simon Marchi 2022-04-06 17:50 ` Jan Vrany 2022-04-05 19:08 ` Pedro Alves 2022-04-06 18:06 ` Jan Vrany 2022-04-06 18:55 ` [PATCH v2] " Jan Vrany 2022-12-07 11:07 ` Jan Vraný 2022-12-07 16:07 ` Simon Marchi
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox; as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).