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/infrun.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/infrun.c')
-rw-r--r-- | gdb/infrun.c | 24 |
1 files changed, 24 insertions, 0 deletions
diff --git a/gdb/infrun.c b/gdb/infrun.c index 33aa0c8..5c9babb 100644 --- a/gdb/infrun.c +++ b/gdb/infrun.c @@ -1938,6 +1938,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; @@ -4822,6 +4823,11 @@ fill_in_stop_func (struct gdbarch *gdbarch, ecs->stop_func_start += gdbarch_deprecated_function_start_offset (gdbarch); + /* PowerPC functions have a Local Entry Point (LEP) and a Global + Entry Point (GEP). There is only one Entry Point (GEP = LEP) for + other architectures. */ + ecs->stop_func_alt_start = ecs->stop_func_start; + if (gdbarch_skip_entrypoint_p (gdbarch)) ecs->stop_func_start = gdbarch_skip_entrypoint (gdbarch, ecs->stop_func_start); @@ -7411,6 +7417,24 @@ process_event_stop_test (struct execution_control_state *ecs) } } + if (execution_direction == EXEC_REVERSE + && ecs->event_thread->control.proceed_to_finish + && ecs->event_thread->stop_pc () >= ecs->stop_func_alt_start + && ecs->event_thread->stop_pc () < ecs->stop_func_start) + { + /* We are executing the reverse-finish command. + If the system supports multiple entry points and we are finishing a + function in reverse. If we are between the entry points singe-step + back to the alternate entry point. If we are at the alternate entry + point -- just need to back up by one more single-step, which + should take us back to the function call. */ + ecs->event_thread->control.step_range_start + = ecs->event_thread->control.step_range_end = 1; + keep_going (ecs); + return; + + } + if (ecs->event_thread->control.step_range_end == 1) { /* It is stepi or nexti. We always want to stop stepping after |