forked from Imagelibrary/binutils-gdb
PPC64: Fix gdb.arch/ppc64-atomic-inst.exp with displaced stepping
The ppc64 displaced step code can't handle atomic sequences. Fallback to stepping over the breakpoint in-line if we detect one. gdb/ChangeLog: 2015-08-07 Pedro Alves <palves@redhat.com> * infrun.c (displaced_step_prepare_throw): Return -1 if gdbarch_displaced_step_copy_insn returns NULL. Update intro comment. * rs6000-tdep.c (LWARX_MASK, LWARX_INSTRUCTION, LDARX_INSTRUCTION) (STWCX_MASK, STWCX_INSTRUCTION, STDCX_INSTRUCTION): Move higher up in file. (ppc_displaced_step_copy_insn): New function. (ppc_displaced_step_fixup): Update comment. (rs6000_gdbarch_init): Install ppc_displaced_step_copy_insn as gdbarch_displaced_step_copy_insn hook. * gdbarch.sh (displaced_step_copy_insn): Document what happens on NULL return. * gdbarch.h: Regenerate. gdb/testsuite/ChangeLog: 2015-08-07 Pedro Alves <palves@redhat.com> * gdb.arch/ppc64-atomic-inst.exp (do_test): New procedure, move tests here. (top level): Run do_test with and without displaced stepping.
This commit is contained in:
@@ -974,6 +974,61 @@ rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
|
||||
#define BXL_INSN 0x4c000000
|
||||
#define BP_INSN 0x7C000008
|
||||
|
||||
/* Instruction masks used during single-stepping of atomic
|
||||
sequences. */
|
||||
#define LWARX_MASK 0xfc0007fe
|
||||
#define LWARX_INSTRUCTION 0x7c000028
|
||||
#define LDARX_INSTRUCTION 0x7c0000A8
|
||||
#define STWCX_MASK 0xfc0007ff
|
||||
#define STWCX_INSTRUCTION 0x7c00012d
|
||||
#define STDCX_INSTRUCTION 0x7c0001ad
|
||||
|
||||
/* We can't displaced step atomic sequences. Otherwise this is just
|
||||
like simple_displaced_step_copy_insn. */
|
||||
|
||||
static struct displaced_step_closure *
|
||||
ppc_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);
|
||||
struct cleanup *old_chain = make_cleanup (xfree, buf);
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||
int insn;
|
||||
|
||||
read_memory (from, buf, len);
|
||||
|
||||
insn = extract_signed_integer (buf, PPC_INSN_SIZE, byte_order);
|
||||
|
||||
/* Assume all atomic sequences start with a lwarx/ldarx instruction. */
|
||||
if ((insn & LWARX_MASK) == LWARX_INSTRUCTION
|
||||
|| (insn & LWARX_MASK) == LDARX_INSTRUCTION)
|
||||
{
|
||||
if (debug_displaced)
|
||||
{
|
||||
fprintf_unfiltered (gdb_stdlog,
|
||||
"displaced: can't displaced step "
|
||||
"atomic sequence at %s\n",
|
||||
paddress (gdbarch, from));
|
||||
}
|
||||
do_cleanups (old_chain);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
discard_cleanups (old_chain);
|
||||
return (struct displaced_step_closure *) buf;
|
||||
}
|
||||
|
||||
/* Fix up the state of registers and memory after having single-stepped
|
||||
a displaced instruction. */
|
||||
static void
|
||||
@@ -983,8 +1038,7 @@ ppc_displaced_step_fixup (struct gdbarch *gdbarch,
|
||||
struct regcache *regs)
|
||||
{
|
||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||
/* Since we use simple_displaced_step_copy_insn, our closure is a
|
||||
copy of the instruction. */
|
||||
/* Our closure is a copy of the instruction. */
|
||||
ULONGEST insn = extract_unsigned_integer ((gdb_byte *) closure,
|
||||
PPC_INSN_SIZE, byte_order);
|
||||
ULONGEST opcode = 0;
|
||||
@@ -1077,14 +1131,6 @@ ppc_displaced_step_hw_singlestep (struct gdbarch *gdbarch,
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Instruction masks used during single-stepping of atomic sequences. */
|
||||
#define LWARX_MASK 0xfc0007fe
|
||||
#define LWARX_INSTRUCTION 0x7c000028
|
||||
#define LDARX_INSTRUCTION 0x7c0000A8
|
||||
#define STWCX_MASK 0xfc0007ff
|
||||
#define STWCX_INSTRUCTION 0x7c00012d
|
||||
#define STDCX_INSTRUCTION 0x7c0001ad
|
||||
|
||||
/* Checks for an atomic sequence of instructions beginning with a LWARX/LDARX
|
||||
instruction and ending with a STWCX/STDCX instruction. If such a sequence
|
||||
is found, attempt to step through it. A breakpoint is placed at the end of
|
||||
@@ -5923,7 +5969,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
|
||||
|
||||
/* Setup displaced stepping. */
|
||||
set_gdbarch_displaced_step_copy_insn (gdbarch,
|
||||
simple_displaced_step_copy_insn);
|
||||
ppc_displaced_step_copy_insn);
|
||||
set_gdbarch_displaced_step_hw_singlestep (gdbarch,
|
||||
ppc_displaced_step_hw_singlestep);
|
||||
set_gdbarch_displaced_step_fixup (gdbarch, ppc_displaced_step_fixup);
|
||||
|
||||
Reference in New Issue
Block a user