[Bug gdb/34245] New: unstable frame-id when stepping through outermost frame
aburgess at redhat dot com via Gdb-prs <[email protected]>
| Newsgroups | gmane.comp.gdb.bugs.discuss |
|---|---|
| Message-ID | <[email protected]/bugzilla/> |
https://sourceware.org/bugzilla/show_bug.cgi?id=34245
Bug ID: 34245
Summary: unstable frame-id when stepping through outermost
frame
Product: gdb
Version: HEAD
Status: NEW
Severity: normal
Priority: P2
Component: gdb
Assignee: unassigned at sourceware dot org
Reporter: aburgess at redhat dot com
Target Milestone: ---
I noticed that the frame-id would change while stepping through the outermost
function.
(gdb) starti
Starting program: /tmp/some-program
Program stopped.
0x0000000000401ac0 in _start ()
(gdb) maintenance print frame-id
frame-id for frame #0:
{stack=0x7fffffffa6a8,code=0x0000000000401ac0,!special}
(gdb) si
0x0000000000401ac4 in _start ()
(gdb) maintenance print frame-id
frame-id for frame #0: {stack=<outer>,!code,special=0x0000000000000000}
(gdb)
Notice that the frame-id changed even though we are still in the function
_start.
This is on x86-64 GNU/Linux. I suspect that this is likely architecture
dependent.
What's happening here is that we have DWARF unwind information. At the first
instruction of the function the default unwinder state applies, and GDB uses
$rip as the return address, as a result the DWARF unwinder is able to build a
frame-id for this frame.
However, the FDE for this frame is:
00000018 0000000000000010 0000001c FDE cie=00000000
pc=0000000000401ac0..0000000000401aef
DW_CFA_advance_loc: 4 to 0000000000401ac4
DW_CFA_undefined: r16 (rip)
So once we step to the second instruction the $rip register is marked as
undefined. As such the DWARF unwinder is unable to create a frame-id for the
frame.
This change in frame-id originates from compute_frame_id (in frame.c), where we
first set the frame-id to outer_frame_id, then call the unwinder to calculate
the frame-id. In the case where the DWARF unwinder can compute a frame-id
(first instruction), we override outer-frame-id with our freshly computed id.
On the second instruction, where $rip is undefined, we don't compute a frame-id
in the DWARF unwinder and leave the frame-id as outer_frame_id.
A changing frame-id is not a good thing. I'm working on a patch to fix some
issues with "until" in the outer frame, which is how I ran into this issue. An
"until" breakpoint stores the frame-id of the frame in which the breakpoint was
created, in this case, if "until" is used on the first instruction then we
store the full, calculated frame-id. When we later hit the "until" breakpoint
later in the function, the frame-id has changed to outer_frame_id, and the
"until" breakpoint doesn't trigger.
I wonder if we should be adding a special case in compute_frame_id to catch the
outer frame case? Or maybe we should be adding a new unwinder, somewhere near
the top of the unwinder stack, which is the outer_frame_unwinder. This will
claim the frame if we think this is the outer frame, and will always just
return outer_frame_id as the frame-id?
FYI: GDB's ability to spot the outer frame in dynamically linker executables is
also broken, see program_space::entry_point_address_query, which only returns
the entry address for the main executable. As such, if testing this bug with C
programs you'll need to compile a static executable.
--
You are receiving this mail because:
You are on the CC list for the bug.