[gdb/python] Make gdb.UnwindInfo.add_saved_register more robust

On arm-linux, until commit bbb12eb9c8 ("gdb/arm: Remove tpidruro register
from non-FreeBSD target descriptions") I ran into:
...
FAIL: gdb.base/inline-frame-cycle-unwind.exp: cycle at level 5: \
  backtrace when the unwind is broken at frame 5
...

What happens is the following:
- the TestUnwinder from inline-frame-cycle-unwind.py calls
  gdb.UnwindInfo.add_saved_register with reg == tpidruro and value
  "<unavailable>",
- pyuw_sniffer calls value->contents ().data () to access the value of the
  register, which throws an UNAVAILABLE_ERROR,
- this causes the TestUnwinder unwinder to fail, after which another unwinder
  succeeds and returns the correct frame, and
- the test-case fails because it's counting on the TestUnwinder to succeed and
  return an incorrect frame.

Fix this by checking for !value::entirely_available as well as
valued::optimized_out in unwind_infopy_add_saved_register.

Tested on x86_64-linux and arm-linux.

Approved-By: Andrew Burgess <aburgess@redhat.com>

PR python/31437
Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31437
This commit is contained in:
Tom de Vries
2024-05-08 14:13:11 +02:00
parent c144f63833
commit 2236c5e384

View File

@@ -361,6 +361,18 @@ unwind_infopy_add_saved_register (PyObject *self, PyObject *args, PyObject *kw)
return nullptr;
}
if (value->optimized_out () || !value->entirely_available ())
{
/* If we allow this value to be registered here, pyuw_sniffer is going
to run into an exception when trying to access its contents.
Throwing an exception here just puts a burden on the user to
implement the same checks on the user side. We could return False
here and True otherwise, but again that might require changes in user
code. So, handle this with minimal impact for the user, while
improving robustness: silently ignore the register/value pair. */
Py_RETURN_NONE;
}
gdbpy_ref<> new_value = gdbpy_ref<>::new_reference (pyo_reg_value);
bool found = false;
for (saved_reg &reg : *unwind_info->saved_regs)