]> git.ipfire.org Git - thirdparty/binutils-gdb.git/commit - gdb/testsuite/ChangeLog
gdb: avoid premature dummy frame garbage collection
authorAndrew Burgess <andrew.burgess@embecosm.com>
Thu, 29 Aug 2019 11:37:00 +0000 (12:37 +0100)
committerAndrew Burgess <andrew.burgess@embecosm.com>
Tue, 1 Jun 2021 08:23:34 +0000 (09:23 +0100)
commitb4b3e2dee20dcde6eb47ebdc6231f5d8edf60ff5
tree011709cafd49177bc49f47523f03ef3e772089f8
parenta2cf3633b33ec21b967f4c7ddfb7f1b80e676d2d
gdb: avoid premature dummy frame garbage collection

Consider the following chain of events:

  * GDB is performing an inferior call, and

  * the inferior calls longjmp, and

  * GDB detects that the longjmp has completed, stops, and enters
    check_longjmp_breakpoint_for_call_dummy (in breakpoint.c), and

  * GDB tries to unwind the stack in order to check that the dummy
    frame (setup for the inferior call) is still on the stack, but

  * The unwind fails, possibly due to missing debug information, so

  * GDB incorrectly concludes that the inferior has longjmp'd past the
    dummy frame, and so deletes the dummy frame, including the dummy
    frame breakpoint, but then

  * The inferior continues, and eventually returns to the dummy frame,
    which is usually (always?) on the stack, the inferior starts
    trying to execute the random contents of the stack, this results
    in undefined behaviour.

This situation is already warned about in the comment on the function
check_longjmp_breakpoint_for_call_dummy where we say:

   You should call this function only at places where it is safe to currently
   unwind the whole stack.  Failed stack unwind would discard live dummy
   frames.

The warning here is fine, the problem is that, even though we call the
function from a location within GDB where we hope to be able to
unwind, sometime the state of the inferior means that the unwind will
not succeed.

This commit tries to improve the situation by adding the following
additional check; when GDB fails to find the dummy frame on the stack,
instead of just assuming that the dummy frame can be garbage
collected, first find the stop_reason for the last frame on the stack.
If this stop_reason indicates that the stack unwinding may have failed
then we assume that the dummy frame is still in use.  However, if the
last frame's stop_reason indicates that the stack unwind completed
successfully then we can be confident that the dummy frame is no
longer in use, and we garbage collect it.

Tested on x86-64 GNU/Linux.

gdb/ChangeLog:

* breakpoint.c (check_longjmp_breakpoint_for_call_dummy): Add
check for why the backtrace stopped.

gdb/testsuite/ChangeLog:

* gdb.base/premature-dummy-frame-removal.c: New file.
* gdb.base/premature-dummy-frame-removal.exp: New file.
* gdb.base/premature-dummy-frame-removal.py: New file.

Change-Id: I8f330cfe0f3f33beb3a52a36994094c4abada07e
gdb/ChangeLog
gdb/breakpoint.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/premature-dummy-frame-removal.c [new file with mode: 0644]
gdb/testsuite/gdb.base/premature-dummy-frame-removal.exp [new file with mode: 0644]
gdb/testsuite/gdb.base/premature-dummy-frame-removal.py [new file with mode: 0644]