* i386-tdep.h (i386_displaced_step_copy_insn): Declare.
* i386-tdep.c (i386_displaced_step_copy_insn): New function. (i386_syscall_p): Change type of lengthp to int. (i386_displaced_step_fixup): Handle kernels that run one past a syscall insn. * i386-linux-tdep.c (i386_linux_init_abi): Use i386_displaced_step_copy_insn instead of simple_displaced_step_copy_insn.
This commit is contained in:
parent
d5bc977ffb
commit
b55078be0a
|
@ -1,3 +1,14 @@
|
|||
2010-06-21 Doug Evans <dje@google.com>
|
||||
|
||||
* i386-tdep.h (i386_displaced_step_copy_insn): Declare.
|
||||
* i386-tdep.c (i386_displaced_step_copy_insn): New function.
|
||||
(i386_syscall_p): Change type of lengthp to int.
|
||||
(i386_displaced_step_fixup): Handle kernels that run one past a
|
||||
syscall insn.
|
||||
* i386-linux-tdep.c (i386_linux_init_abi): Use
|
||||
i386_displaced_step_copy_insn instead of
|
||||
simple_displaced_step_copy_insn.
|
||||
|
||||
2010-06-21 Tom Tromey <tromey@redhat.com>
|
||||
|
||||
* dwarf2read.c (read_base_type): Handle DW_ATE_UTF.
|
||||
|
|
|
@ -888,7 +888,7 @@ i386_linux_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch)
|
|||
|
||||
/* Displaced stepping. */
|
||||
set_gdbarch_displaced_step_copy_insn (gdbarch,
|
||||
simple_displaced_step_copy_insn);
|
||||
i386_displaced_step_copy_insn);
|
||||
set_gdbarch_displaced_step_fixup (gdbarch, i386_displaced_step_fixup);
|
||||
set_gdbarch_displaced_step_free_closure (gdbarch,
|
||||
simple_displaced_step_free_closure);
|
||||
|
|
|
@ -518,7 +518,7 @@ i386_call_p (const gdb_byte *insn)
|
|||
length in bytes. Otherwise, return zero. */
|
||||
|
||||
static int
|
||||
i386_syscall_p (const gdb_byte *insn, ULONGEST *lengthp)
|
||||
i386_syscall_p (const gdb_byte *insn, int *lengthp)
|
||||
{
|
||||
if (insn[0] == 0xcd)
|
||||
{
|
||||
|
@ -529,6 +529,43 @@ i386_syscall_p (const gdb_byte *insn, ULONGEST *lengthp)
|
|||
return 0;
|
||||
}
|
||||
|
||||
/* Some kernels may run one past a syscall insn, so we have to cope.
|
||||
Otherwise this is just simple_displaced_step_copy_insn. */
|
||||
|
||||
struct displaced_step_closure *
|
||||
i386_displaced_step_copy_insn (struct gdbarch *gdbarch,
|
||||
CORE_ADDR from, CORE_ADDR to,
|
||||
struct regcache *regs)
|
||||
{
|
||||
size_t len = gdbarch_max_insn_length (gdbarch);
|
||||
gdb_byte *buf = xmalloc (len);
|
||||
|
||||
read_memory (from, buf, len);
|
||||
|
||||
/* GDB may get control back after the insn after the syscall.
|
||||
Presumably this is a kernel bug.
|
||||
If this is a syscall, make sure there's a nop afterwards. */
|
||||
{
|
||||
int syscall_length;
|
||||
gdb_byte *insn;
|
||||
|
||||
insn = i386_skip_prefixes (buf, len);
|
||||
if (insn != NULL && i386_syscall_p (insn, &syscall_length))
|
||||
insn[syscall_length] = NOP_OPCODE;
|
||||
}
|
||||
|
||||
write_memory (to, buf, len);
|
||||
|
||||
if (debug_displaced)
|
||||
{
|
||||
fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ",
|
||||
paddress (gdbarch, from), paddress (gdbarch, to));
|
||||
displaced_step_dump_bytes (gdb_stdlog, buf, len);
|
||||
}
|
||||
|
||||
return (struct displaced_step_closure *) buf;
|
||||
}
|
||||
|
||||
/* Fix up the state of registers and memory after having single-stepped
|
||||
a displaced instruction. */
|
||||
|
||||
|
@ -587,7 +624,7 @@ i386_displaced_step_fixup (struct gdbarch *gdbarch,
|
|||
&& ! i386_ret_p (insn))
|
||||
{
|
||||
ULONGEST orig_eip;
|
||||
ULONGEST insn_len;
|
||||
int insn_len;
|
||||
|
||||
regcache_cooked_read_unsigned (regs, I386_EIP_REGNUM, &orig_eip);
|
||||
|
||||
|
@ -606,7 +643,12 @@ i386_displaced_step_fixup (struct gdbarch *gdbarch,
|
|||
it unrelocated. Goodness help us if there are PC-relative
|
||||
system calls. */
|
||||
if (i386_syscall_p (insn, &insn_len)
|
||||
&& orig_eip != to + (insn - insn_start) + insn_len)
|
||||
&& orig_eip != to + (insn - insn_start) + insn_len
|
||||
/* GDB can get control back after the insn after the syscall.
|
||||
Presumably this is a kernel bug.
|
||||
i386_displaced_step_copy_insn ensures its a nop,
|
||||
we add one to the length for it. */
|
||||
&& orig_eip != to + (insn - insn_start) + insn_len + 1)
|
||||
{
|
||||
if (debug_displaced)
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
|
|
|
@ -362,6 +362,9 @@ extern const struct regset *
|
|||
const char *sect_name, size_t sect_size);
|
||||
|
||||
|
||||
extern struct displaced_step_closure *i386_displaced_step_copy_insn
|
||||
(struct gdbarch *gdbarch, CORE_ADDR from, CORE_ADDR to,
|
||||
struct regcache *regs);
|
||||
extern void i386_displaced_step_fixup (struct gdbarch *gdbarch,
|
||||
struct displaced_step_closure *closure,
|
||||
CORE_ADDR from, CORE_ADDR to,
|
||||
|
|
Loading…
Reference in New Issue