diff options
author | Andrew Burgess <aburgess@redhat.com> | 2023-03-09 10:58:54 +0000 |
---|---|---|
committer | Andrew Burgess <aburgess@redhat.com> | 2023-03-30 10:25:46 +0100 |
commit | 44d9b0a174b08f283001f01aaf84102ba0a2726a (patch) | |
tree | e4c000a5119a306ad11bd72eaf24737b6ee53d58 /gdb/testsuite/gdb.python | |
parent | 3194ca90fefda8e3e43cb11cb149a1e5c074d45c (diff) | |
download | binutils-44d9b0a174b08f283001f01aaf84102ba0a2726a.zip binutils-44d9b0a174b08f283001f01aaf84102ba0a2726a.tar.gz binutils-44d9b0a174b08f283001f01aaf84102ba0a2726a.tar.bz2 |
gdb/python: add PENDING_FRAMEPY_REQUIRE_VALID macro in py-unwind.c
This commit copies the pattern that is present in many other py-*.c
files: having a single macro to check that the Python object is still
valid.
This cleans up the code a little throughout the py-unwind.c file.
Some of the exception messages will change slightly with this commit,
though the type of the exceptions is still ValueError in all cases.
I started writing some tests for this change and immediately ran into
a problem: GDB would crash. It turns out that the PendingFrame
objects are not being marked as invalid!
In pyuw_sniffer where the pending frames are created, we make use of a
scoped_restore to invalidate the pending frame objects. However, this
only restores the pending_frame_object::frame_info field to its
previous value -- and it turns out we never actually give this field
an initial value, it's left undefined.
So, when the scoped_restore (called invalidate_frame) performs its
cleanup, it actually restores the frame_info field to an undefined
value. If this undefined value is not nullptr then any future
accesses to the PendingFrame object result in undefined behaviour and
most likely, a crash.
As part of this commit I now initialize the frame_info field, which
ensures all the new tests now pass.
Reviewed-By: Tom Tromey <tom@tromey.com>
Diffstat (limited to 'gdb/testsuite/gdb.python')
-rw-r--r-- | gdb/testsuite/gdb.python/py-unwind.exp | 19 | ||||
-rw-r--r-- | gdb/testsuite/gdb.python/py-unwind.py | 7 |
2 files changed, 26 insertions, 0 deletions
diff --git a/gdb/testsuite/gdb.python/py-unwind.exp b/gdb/testsuite/gdb.python/py-unwind.exp index 337e5dc..3e214ee 100644 --- a/gdb/testsuite/gdb.python/py-unwind.exp +++ b/gdb/testsuite/gdb.python/py-unwind.exp @@ -142,3 +142,22 @@ gdb_test "python obj = simple_unwinder(True)" \ [multi_line \ "TypeError: incorrect type for name: <class 'bool'>" \ "Error while executing Python code\\."] + +# Now register the simple_unwinder with a valid name, and use the +# unwinder to capture a PendingFrame object. +gdb_test_no_output "python obj = simple_unwinder(\"simple\")" +gdb_test_no_output "python gdb.unwinder.register_unwinder(None, obj)" +check_for_broken_backtrace "backtrace to capture a PendingFrame object" + +# Call methods on the captured gdb.PendingFrame and check we see the +# expected error. +gdb_test_no_output "python pf = captured_pending_frame" +foreach cmd {"pf.read_register(\"pc\")" \ + "pf.create_unwind_info(None)" \ + "pf.architecture()" \ + "pf.level()"} { + gdb_test "python $cmd" \ + [multi_line \ + "ValueError: gdb\\.PendingFrame is invalid\\." \ + "Error while executing Python code\\."] +} diff --git a/gdb/testsuite/gdb.python/py-unwind.py b/gdb/testsuite/gdb.python/py-unwind.py index edd2e30..b30e843 100644 --- a/gdb/testsuite/gdb.python/py-unwind.py +++ b/gdb/testsuite/gdb.python/py-unwind.py @@ -133,12 +133,19 @@ class TestUnwinder(Unwinder): global_test_unwinder = TestUnwinder() gdb.unwinder.register_unwinder(None, global_test_unwinder, True) +# This is filled in by the simple_unwinder class. +captured_pending_frame = None + class simple_unwinder(Unwinder): def __init__(self, name): super().__init__(name) def __call__(self, pending_frame): + global captured_pending_frame + + if captured_pending_frame is None: + captured_pending_frame = pending_frame return None |