diff options
author | Carl Love <cel@us.ibm.com> | 2023-03-09 16:10:18 -0500 |
---|---|---|
committer | Carl Love <cel@us.ibm.com> | 2023-03-17 16:02:57 -0400 |
commit | 2a8339b71f37f2d02f5b2194929c9d702ef27223 (patch) | |
tree | f10acfc073773080a64f34e3ab240ecac3ce6c41 /gdb/infcmd.c | |
parent | 334d405c2ac395fca67b952affb20893002d969f (diff) | |
download | gdb-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.c | 32 |
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); } |