aboutsummaryrefslogtreecommitdiff
path: root/gdb/infcmd.c
diff options
context:
space:
mode:
authorCarl Love <cel@us.ibm.com>2023-03-09 16:10:18 -0500
committerCarl Love <cel@us.ibm.com>2023-03-17 16:02:57 -0400
commit2a8339b71f37f2d02f5b2194929c9d702ef27223 (patch)
treef10acfc073773080a64f34e3ab240ecac3ce6c41 /gdb/infcmd.c
parent334d405c2ac395fca67b952affb20893002d969f (diff)
downloadgdb-2a8339b71f37f2d02f5b2194929c9d702ef27223.zip
gdb-2a8339b71f37f2d02f5b2194929c9d702ef27223.tar.gz
gdb-2a8339b71f37f2d02f5b2194929c9d702ef27223.tar.bz2
PowerPC: fix for gdb.reverse/finish-precsave.exp and gdb.reverse/finish-reverse.exp
PPC64 multiple entry points, a normal entry point and an alternate entry point. The alternate entry point is to setup the Table of Contents (TOC) register before continuing at the normal entry point. When the TOC is already valid, the normal entry point is used, this is typically the case. The alternate entry point is typically referred to as the global entry point (GEP) in IBM. The normal entry point is typically referred to as the local entry point (LEP). When GDB is executing the finish command in reverse, the function finish_backward currently sets the break point at the alternate entry point. This issue is if the function, when executing in the forward direction, entered the function via the normal entry point, execution in the reverse direction will never sees the break point at the alternate entry point. In this case, the reverse execution continues until the next break point is encountered thus stopping at the wrong place. This patch adds a new address to struct execution_control_state to hold the address of the alternate entry point (GEP). The finish_backwards function is updated, if the stopping point is between the normal entry point (LEP) and the end of the function, a breakpoint is set at the normal entry point. If the stopping point is between the entry points, a breakpoint is set at the alternate entry point. This ensures that GDB will always stop at the normal entry point. If the function did enter via the alternate entry point, GDB will detect that and continue to execute backwards in the function until the alternate entry point is reached. The patch fixes the behavior of the reverse-finish command on PowerPC to match the behavior of the command on other platforms, specifically X86. The patch does not change the behavior of the command on X86. A new test is added to verify the reverse-finish command on PowerPC correctly stops at the instruction where the function call is made. The patch fixes 11 regression errors in test gdb.reverse/finish-precsave.exp and 11 regression errors in test gdb.reverse/finish-reverse.exp. The patch has been tested on Power 10 and X86 processor with no new regression failures.
Diffstat (limited to 'gdb/infcmd.c')
-rw-r--r--gdb/infcmd.c32
1 files changed, 23 insertions, 9 deletions
diff --git a/gdb/infcmd.c b/gdb/infcmd.c
index c369b79..f464615 100644
--- a/gdb/infcmd.c
+++ b/gdb/infcmd.c
@@ -1710,6 +1710,10 @@ finish_backward (struct finish_command_fsm *sm)
struct thread_info *tp = inferior_thread ();
CORE_ADDR pc;
CORE_ADDR func_addr;
+ CORE_ADDR alt_entry_point = sal.pc;
+ CORE_ADDR entry_point = alt_entry_point;
+ frame_info_ptr frame = get_selected_frame (nullptr);
+ struct gdbarch *gdbarch = get_frame_arch (frame);
pc = get_frame_pc (get_current_frame ());
@@ -1718,6 +1722,15 @@ finish_backward (struct finish_command_fsm *sm)
sal = find_pc_line (func_addr, 0);
+ if (gdbarch_skip_entrypoint_p (gdbarch))
+ /* Some architectures, like PowerPC use local and global entry points.
+ There is only one Entry Point (GEP = LEP) for other architectures.
+ The GEP is an alternate entry point. The LEP is the normal entry point.
+ The value of entry_point was initialized to the alternate entry point
+ (GEP). It will be adjusted to the normal entry point if the function
+ has two entry points. */
+ entry_point = gdbarch_skip_entrypoint (gdbarch, sal.pc);
+
tp->control.proceed_to_finish = 1;
/* Special case: if we're sitting at the function entry point,
then all we need to do is take a reverse singlestep. We
@@ -1728,15 +1741,12 @@ finish_backward (struct finish_command_fsm *sm)
no way that a function up the stack can have a return address
that's equal to its entry point. */
- if (sal.pc != pc)
+ if ((pc < alt_entry_point) || (pc > entry_point))
{
- frame_info_ptr frame = get_selected_frame (nullptr);
- struct gdbarch *gdbarch = get_frame_arch (frame);
-
- /* Set a step-resume at the function's entry point. Once that's
- hit, we'll do one more step backwards. */
+ /* We are in the body of the function. Set a breakpoint to go back to
+ the normal entry point. */
symtab_and_line sr_sal;
- sr_sal.pc = sal.pc;
+ sr_sal.pc = entry_point;
sr_sal.pspace = get_frame_program_space (frame);
insert_step_resume_breakpoint_at_sal (gdbarch,
sr_sal, null_frame_id);
@@ -1745,8 +1755,12 @@ finish_backward (struct finish_command_fsm *sm)
}
else
{
- /* We're almost there -- we just need to back up by one more
- single-step. */
+ /* We are either at one of the entry points or between the entry points.
+ If we are not at the alt_entry point, go back to the alt_entry_point
+ If we at the normal entry point step back one instruction, when we
+ stop we will determine if we entered via the entry point or the
+ alternate entry point. If we are at the alternate entry point,
+ single step back to the function call. */
tp->control.step_range_start = tp->control.step_range_end = 1;
proceed ((CORE_ADDR) -1, GDB_SIGNAL_DEFAULT);
}