aboutsummaryrefslogtreecommitdiff
path: root/gdb/infrun.c
diff options
context:
space:
mode:
authorCarl Love <cel@us.ibm.com>2023-01-13 17:59:33 -0500
committerCarl Love <cel@us.ibm.com>2023-01-17 11:39:42 -0500
commit92e07580db6a5572573d5177ca23933064158f89 (patch)
tree3b6e814c5360a226f3f57d0a0f4fa23f69f0b197 /gdb/infrun.c
parentb22548ddb30bfb167708e82d3bb932461c1b703a (diff)
downloadgdb-92e07580db6a5572573d5177ca23933064158f89.zip
gdb-92e07580db6a5572573d5177ca23933064158f89.tar.gz
gdb-92e07580db6a5572573d5177ca23933064158f89.tar.bz2
PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
PR record/29927 - reverse-finish requires two reverse next instructions to reach previous source line PowerPC uses two entry points called the local entry point (LEP) and the global entry point (GEP). Normally the LEP is used when calling a function. However, if the table of contents (TOC) value in register 2 is not valid the GEP is called to setup the TOC before execution continues at the LEP. When executing in reverse, the function finish_backward sets the break point at the alternate entry point (GEP). However if the forward execution enters via the normal entry point (LEP), the reverse execution never sees the break point at the GEP of the function. Reverse execution continues until the next break point is encountered or the end of the recorded log is reached causing gdb to stop at the wrong place. This patch adds a new address to struct execution_control_state to hold the address of the alternate function start address, known as the GEP on PowerPC. The finish_backwards function is updated. If the stopping point is between the two entry points (the LEP and GEP on PowerPC), the stepping range is set to execute back to the alternate entry point (GEP on PowerPC). Otherwise, a breakpoint is inserted at the normal entry point (LEP on PowerPC). Function process_event_stop_test checks uses a stepping range to stop execution in the caller at the first instruction of the source code line. Note, on systems that only support one entry point, the address of the two entry points are the same. Test finish-reverse-next.exp is updated to include tests for the reverse-finish command when the function is entered via the normal entry point (i.e. the LEP) and the alternate entry point (i.e. the GEP). The patch has been tested on X86 and PowerPC with no regressions.
Diffstat (limited to 'gdb/infrun.c')
-rw-r--r--gdb/infrun.c16
1 files changed, 14 insertions, 2 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c
index 05b150b..9c81521 100644
--- a/gdb/infrun.c
+++ b/gdb/infrun.c
@@ -1868,6 +1868,7 @@ struct execution_control_state
struct target_waitstatus ws;
int stop_func_filled_in = 0;
+ CORE_ADDR stop_func_alt_start = 0;
CORE_ADDR stop_func_start = 0;
CORE_ADDR stop_func_end = 0;
const char *stop_func_name = nullptr;
@@ -4663,6 +4664,12 @@ fill_in_stop_func (struct gdbarch *gdbarch,
&block);
ecs->stop_func_name = gsi == nullptr ? nullptr : gsi->print_name ();
+ /* PowerPC functions have a Local Entry Point and a Global Entry
+ Point. There is only one Entry Point (GEP = LEP) for other
+ architectures. Save the alternate entry point address (GEP) for
+ use later. */
+ ecs->stop_func_alt_start = ecs->stop_func_start;
+
/* The call to find_pc_partial_function, above, will set
stop_func_start and stop_func_end to the start and end
of the range containing the stop pc. If this range
@@ -4679,6 +4686,9 @@ fill_in_stop_func (struct gdbarch *gdbarch,
+= gdbarch_deprecated_function_start_offset (gdbarch);
if (gdbarch_skip_entrypoint_p (gdbarch))
+ /* The PowerPC architecture uses two entry points. Stop at the
+ regular entry point (LEP on PowerPC) initially. Will setup a
+ breakpoint for the alternate entry point (GEP) later. */
ecs->stop_func_start
= gdbarch_skip_entrypoint (gdbarch, ecs->stop_func_start);
}
@@ -6754,7 +6764,7 @@ process_event_stop_test (struct execution_control_state *ecs)
/* Return using a step range so we will keep stepping back to the
first instruction in the source code line. */
- tp->control.step_range_start = ecs->stop_func_start;
+ tp->control.step_range_start = ecs->stop_func_alt_start;
tp->control.step_range_end = ecs->stop_func_start;
keep_going (ecs);
return;
@@ -6891,8 +6901,10 @@ process_event_stop_test (struct execution_control_state *ecs)
(unless it's the function entry point, in which case
keep going back to the call point). */
CORE_ADDR stop_pc = ecs->event_thread->stop_pc ();
+
if (stop_pc == ecs->event_thread->control.step_range_start
- && stop_pc != ecs->stop_func_start
+ && (stop_pc < ecs->stop_func_alt_start
+ || stop_pc > ecs->stop_func_start)
&& execution_direction == EXEC_REVERSE)
end_stepping_range (ecs);
else