* i386-linux-tdep.c (i386_linux_displaced_step_fixup): New. (i386_linux_init_abi): Install i386_linux_displaced_step_fixup. --- gdb/i386-linux-tdep.c | 32 +++++++++++++++++++++++++++++++- 1 files changed, 31 insertions(+), 1 deletions(-) diff --git a/gdb/i386-linux-tdep.c b/gdb/i386-linux-tdep.c index 61800b4..cbfe857 100644 --- a/gdb/i386-linux-tdep.c +++ b/gdb/i386-linux-tdep.c @@ -644,6 +644,36 @@ i386_linux_core_read_description (struct gdbarch *gdbarch, } static void +i386_linux_displaced_step_fixup (struct gdbarch *gdbarch, + struct displaced_step_closure *closure, + CORE_ADDR from, CORE_ADDR to, + struct regcache *regs) +{ + ULONGEST orig_eip; + + regcache_cooked_read_unsigned (regs, I386_EIP_REGNUM, &orig_eip); + + if (orig_eip == to) + { + /* The inferior is stopped without any pc value updates. This usually + means pc value has been incremented in previous syscall event. In + this case, set pc value to its original place. */ + ULONGEST eip = (orig_eip - (to - from)) & 0xffffffffUL; + + regcache_cooked_write_unsigned (regs, I386_EIP_REGNUM, eip); + + if (debug_displaced) + fprintf_unfiltered (gdb_stdlog, + "displaced: " + "relocated %%eip from %s to %s\n", + paddress (gdbarch, orig_eip), + paddress (gdbarch, eip)); + } + else + i386_displaced_step_fixup (gdbarch, closure, from, to, regs); +} + +static void i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); @@ -891,7 +921,7 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) /* Displaced stepping. */ set_gdbarch_displaced_step_copy_insn (gdbarch, i386_displaced_step_copy_insn); - set_gdbarch_displaced_step_fixup (gdbarch, i386_displaced_step_fixup); + set_gdbarch_displaced_step_fixup (gdbarch, i386_linux_displaced_step_fixup); set_gdbarch_displaced_step_free_closure (gdbarch, simple_displaced_step_free_closure); set_gdbarch_displaced_step_location (gdbarch, -- 1.7.0.4