public inbox for gdb@sourceware.org
 help / color / mirror / Atom feed
* Unwind cycle detection false positive mixing frame view and backtrace
@ 2024-03-21 18:29 Carlos Sánchez de La Lama
  2024-05-07 17:40 ` Tom Tromey
  0 siblings, 1 reply; 2+ messages in thread
From: Carlos Sánchez de La Lama @ 2024-03-21 18:29 UTC (permalink / raw)
  To: gdb

I have found a problem which cases a false positive detection of cycles
when "frame view" specifier is used in combination with "bt"; the
consequence is affected frames are (wrongly) reported as impossible to be
further traversed.

To reproduce, I use a debug build of GNU hello-2.12
hello-2.12$ ./configure && make CFLAGS="-g -O0"

Now I debug that with gdb (master branch, commit
53ff349e553fa9fc446a8711e37fd252282b088b)

-------- CODE BEGIN --------
$ gdb ./hello
[...]
(gdb) break getopt_long
Breakpoint 1 at 0x2480
(gdb) run
Starting program: /home/carlossanchez/src/hello-2.12/hello

Breakpoint 1, 0x00007ffff7eb05d0 in getopt_long () from
/lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0  0x00007ffff7eb05d0 in getopt_long () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x0000555555556a8d in parse_options (argc=1, argv=0x7fffffffde98,
greeting_msg=0x7fffffffdd68) at src/hello.c:99
#2  0x0000555555556bf9 in main (argc=1, argv=0x7fffffffde98) at src/hello.c:157
(gdb) info frame 1
Stack frame at 0x7fffffffdd50:
 rip = 0x555555556a8d in parse_options (src/hello.c:99); saved rip =
0x555555556bf9
 called by frame at 0x7fffffffddb0, caller of frame at 0x7fffffffdcf0
 source language c.
 Arglist at 0x7fffffffdd40, args: argc=1, argv=0x7fffffffde98,
greeting_msg=0x7fffffffdd68
 Locals at 0x7fffffffdd40, Previous frame's sp is 0x7fffffffdd50
 Saved registers:
  rbx at 0x7fffffffdd28, rbp at 0x7fffffffdd40, r12 at 0x7fffffffdd30,
r13 at 0x7fffffffdd38, rip at 0x7fffffffdd48
(gdb) info frame view 0x7fffffffdd50 0x555555556a8d
Stack frame at 0x7fffffffdd50:
 rip = 0x555555556a8d in parse_options (src/hello.c:99); saved rip = <not saved>
 Outermost frame: previous frame identical to this frame (corrupt stack?)
 source language c.
 Arglist at 0x7fffffffdd40, args: argc=1, argv=0x7fffffffde98,
greeting_msg=0x7fffffffdd68
 Locals at 0x7fffffffdd40, Previous frame's sp is 0x7fffffffdd50
 Saved registers:
  rbx at 0x7fffffffdd28, rbp at 0x7fffffffdd40, r12 at 0x7fffffffdd30,
r13 at 0x7fffffffdd38, rip at 0x7fffffffdd48
-------- CODE END --------

The frame at 0x7fffffffdd50 gets reported ad being called out of
nowhere (corrupt stack)
when inspected with "frame wiew".

Now I try doing the "frame view" first:

-------- CODE BEGIN --------
$ gdb ./hello
[...]
(gdb) break getopt_long
Breakpoint 1 at 0x2480
(gdb) run
Starting program: /home/carlossanchez/src/hello-2.12/hello

Breakpoint 1, 0x00007ffff7eb05d0 in getopt_long () from
/lib/x86_64-linux-gnu/libc.so.6
(gdb) info frame view 0x7fffffffdd50 0x555555556a8d
Stack frame at 0x7fffffffdd50:
 rip = 0x555555556a8d in parse_options (src/hello.c:99); saved rip =
0x555555556bf9
 called by frame at 0x7fffffffddb0
 source language c.
 Arglist at 0x7fffffffdd40, args: argc=1, argv=0x7fffffffde98,
greeting_msg=0x7fffffffdd68
 Locals at 0x7fffffffdd40, Previous frame's sp is 0x7fffffffdd50
 Saved registers:
  rbx at 0x7fffffffdd28, rbp at 0x7fffffffdd40, r12 at 0x7fffffffdd30,
r13 at 0x7fffffffdd38, rip at 0x7fffffffdd48
(gdb) bt
#0  0x00007ffff7eb05d0 in getopt_long () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x0000555555556a8d in parse_options (argc=1, argv=0x7fffffffde98,
greeting_msg=0x7fffffffdd68) at src/hello.c:99
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
-------- CODE END --------

Inspecting with "frame view" works, but now the backtrace stops prematurely!

I have debugged gdb itself and found the problem to be in gdb/frame.c:2250.
frame_stash_add is called to detect cycles in the frame sequence: if the same
frame id is already in the stash, it means we are traversing the same frame
twice (we found a cycle) and the stack is corrupt. When calling "bt" twice, the
higher level dwarf2 frame cache prevents creation of new frame_info structs, so
frame_stash_add is not really called twice and the problem is not observed.
But when mixing "frame view" and "bt", different frame_info structures
which refer
to the same frame in memory are created. As the hash used by frame_stash_add
is based on CFA and PC (so based on the real frame in memory, and not on
the frame_info pointer) a cycle is wrongly detected.

I was going to create a bug report, but I want to hear comments on the
expected behaviour here:
Option 1) this works as expected, you are not supposed to "frame view" frames
which are on your current backtrace
Option 2) make "frame view" reset the frame stash before and after running
Option 3) condition the frame traverser to skip the cycle detection
when using "frame view"

Suggestions?

Carlos

^ permalink raw reply	[flat|nested] 2+ messages in thread

* Re: Unwind cycle detection false positive mixing frame view and backtrace
  2024-03-21 18:29 Unwind cycle detection false positive mixing frame view and backtrace Carlos Sánchez de La Lama
@ 2024-05-07 17:40 ` Tom Tromey
  0 siblings, 0 replies; 2+ messages in thread
From: Tom Tromey @ 2024-05-07 17:40 UTC (permalink / raw)
  To: Carlos Sánchez de La Lama via Gdb; +Cc: Carlos Sánchez de La Lama

>>>>> "Carlos" == Carlos Sánchez de La Lama via Gdb <gdb@sourceware.org> writes:

Carlos> I have found a problem which cases a false positive detection of cycles
Carlos> when "frame view" specifier is used in combination with "bt"; the
Carlos> consequence is affected frames are (wrongly) reported as impossible to be
Carlos> further traversed.
...

Carlos> I was going to create a bug report, but I want to hear comments on the
Carlos> expected behaviour here:
Carlos> Option 1) this works as expected, you are not supposed to "frame view" frames
Carlos> which are on your current backtrace
Carlos> Option 2) make "frame view" reset the frame stash before and after running
Carlos> Option 3) condition the frame traverser to skip the cycle detection
Carlos> when using "frame view"

Carlos> Suggestions?

I don't really know the answer, but I didn't want your note to go too
long without some kind of response.

It's not clear to me we ever really worked out all the implications of
"frame view".

On the one hand, it seems like it should flush the frame cache and let
you "bt".  On the other hand, the docs say you can then do "frame level
0" to reset back to gdb's "native" notion of frames -- which seems a
little incoherent to me.

If we had green thread support I guess I'd be tempted to make "frame
view" make a temporary, gdb-side-only green thread.  Then switching away
from the thread would delete the frame view.

Tom

^ permalink raw reply	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2024-05-07 17:40 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-03-21 18:29 Unwind cycle detection false positive mixing frame view and backtrace Carlos Sánchez de La Lama
2024-05-07 17:40 ` Tom Tromey

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).