gdb/python: fix FinishBreakpoint.return_value for tail call functions

The FinishBreakpoint.return_value attribute will not be populated
correctly for tail call functions.

In bpfinishpy_init (python/py-finishbreakpoint.c) we use the function
get_frame_pc_if_available to return an address, and then use this
address to lookup a function symbol.

The problem is that, for tail call functions, the address returned by
get_frame_pc_if_available can be outside the bounds of the function,
as a result GDB might find no function symbol at all, or might find
the wrong function symbol, if the tail call function is immediately
adjacent to the next function.

Fix this by using get_frame_address_in_block_if_available instead.
For tail call functions this will return an address within the bounds
of the function, which means that GDB should find the correct function
symbol, and from this the correct return type.

I've extended the existing FinishBreakpoint with tail call test case
to include printing the return value, this test fails without this
patch, but now works.

Approved-By: Tom Tromey <tom@tromey.com>
This commit is contained in:
Andrew Burgess 2026-01-23 09:57:24 +00:00
parent e6bdfed6f5
commit d0c1dcb58e
3 changed files with 11 additions and 4 deletions

View file

@ -174,7 +174,6 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
struct frame_id frame_id;
PyObject *internal = NULL;
int internal_bp = 0;
std::optional<CORE_ADDR> pc;
if (!gdb_PyArg_ParseTupleAndKeywords (args, kwargs, "|OO", keywords,
&frame_obj, &internal))
@ -248,9 +247,10 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
try
{
if ((pc = get_frame_pc_if_available (frame)))
CORE_ADDR pc;
if (get_frame_address_in_block_if_available (frame, &pc))
{
struct symbol *function = find_symbol_for_pc (*pc);
struct symbol *function = find_symbol_for_pc (pc);
if (function != nullptr)
{
struct type *ret_type =