public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [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 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 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 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).