aboutsummaryrefslogtreecommitdiff
path: root/gdb/amd64-tdep.c
diff options
context:
space:
mode:
Diffstat (limited to 'gdb/amd64-tdep.c')
-rw-r--r--gdb/amd64-tdep.c27
1 files changed, 13 insertions, 14 deletions
diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c
index 228b751..8d34525 100644
--- a/gdb/amd64-tdep.c
+++ b/gdb/amd64-tdep.c
@@ -1690,7 +1690,7 @@ void
amd64_displaced_step_fixup (struct gdbarch *gdbarch,
struct displaced_step_copy_insn_closure *dsc_,
CORE_ADDR from, CORE_ADDR to,
- struct regcache *regs)
+ struct regcache *regs, bool completed_p)
{
amd64_displaced_step_copy_insn_closure *dsc
= (amd64_displaced_step_copy_insn_closure *) dsc_;
@@ -1725,14 +1725,14 @@ amd64_displaced_step_fixup (struct gdbarch *gdbarch,
the displaced instruction; make it relative to the original insn.
Well, signal handler returns don't need relocation either, but we use the
value of %rip to recognize those; see below. */
- if (! amd64_absolute_jmp_p (insn_details)
- && ! amd64_absolute_call_p (insn_details)
- && ! amd64_ret_p (insn_details))
+ if (!completed_p
+ || (!amd64_absolute_jmp_p (insn_details)
+ && !amd64_absolute_call_p (insn_details)
+ && !amd64_ret_p (insn_details)))
{
- ULONGEST orig_rip;
int insn_len;
- regcache_cooked_read_unsigned (regs, AMD64_RIP_REGNUM, &orig_rip);
+ CORE_ADDR pc = regcache_read_pc (regs);
/* A signal trampoline system call changes the %rip, resuming
execution of the main program after the signal handler has
@@ -1749,24 +1749,23 @@ amd64_displaced_step_fixup (struct gdbarch *gdbarch,
it unrelocated. Goodness help us if there are PC-relative
system calls. */
if (amd64_syscall_p (insn_details, &insn_len)
- && orig_rip != to + insn_len
/* GDB can get control back after the insn after the syscall.
- Presumably this is a kernel bug.
- Fixup ensures its a nop, we add one to the length for it. */
- && orig_rip != to + insn_len + 1)
+ Presumably this is a kernel bug. Fixup ensures its a nop, we
+ add one to the length for it. */
+ && (pc < to || pc > (to + insn_len + 1)))
displaced_debug_printf ("syscall changed %%rip; not relocating");
else
{
- ULONGEST rip = orig_rip - insn_offset;
+ CORE_ADDR rip = pc - insn_offset;
/* If we just stepped over a breakpoint insn, we don't backup
the pc on purpose; this is to match behaviour without
stepping. */
- regcache_cooked_write_unsigned (regs, AMD64_RIP_REGNUM, rip);
+ regcache_write_pc (regs, rip);
displaced_debug_printf ("relocated %%rip from %s to %s",
- paddress (gdbarch, orig_rip),
+ paddress (gdbarch, pc),
paddress (gdbarch, rip));
}
}
@@ -1779,7 +1778,7 @@ amd64_displaced_step_fixup (struct gdbarch *gdbarch,
/* If the instruction was a call, the return address now atop the
stack is the address following the copied instruction. We need
to make it the address following the original instruction. */
- if (amd64_call_p (insn_details))
+ if (completed_p && amd64_call_p (insn_details))
{
ULONGEST rsp;
ULONGEST retaddr;