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>
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))
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 =
set saw_stopped_message false
set saw_breakpoint_line false
set saw_source_line false
+ set saw_return_value false
gdb_test_multiple "continue" "" {
-re "^Stopped at MyFinishBreakpoint\r\n" {
set saw_stopped_message true
exp_continue
}
+ -re "^Return value is 43\r\n" {
+ set saw_return_value true
+ exp_continue
+ }
-re "^Breakpoint $::decimal, main \\(\\) at \[^\r\n\]+/$::srcfile:$lineno\r\n" {
set saw_breakpoint_line true
exp_continue
-re "^$::gdb_prompt $" {
gdb_assert { $saw_stopped_message \
&& $saw_breakpoint_line \
- && $saw_source_line } $gdb_test_name
+ && $saw_source_line \
+ && $saw_return_value } $gdb_test_name
}
-re "^\[^\r\n\]*\r\n" {
exp_continue
class MyFinishBreakpoint(gdb.FinishBreakpoint):
def stop(self):
print("Stopped at MyFinishBreakpoint")
+ print("Return value is {}".format(self.return_value))
return True