2011-03-02 Yao Qi <yao@codesourcery.com>

* arm-tdep.h (struct displaced_step_closure): Add two new fields
	is_thumb and insn_size.
	* arm-tdep.c (displaced_read_reg): Adjust correct pipeline offset
	on both ARM and Thumb mode.
	(arm_process_displaced_insn): Set is_thumb and insn_size.
	(arm_displaced_init_closure): Handle both 16-bit and 32-bit.
	(arm_displaced_step_fixup): Likewise.
This commit is contained in:
Yao Qi
2011-03-02 05:33:37 +00:00
parent b123da992d
commit 4db71c0b79
3 changed files with 74 additions and 10 deletions

View File

@ -1,3 +1,13 @@
2011-03-02 Yao Qi <yao@codesourcery.com>
* arm-tdep.h (struct displaced_step_closure): Add two new fields
is_thumb and insn_size.
* arm-tdep.c (displaced_read_reg): Adjust correct pipeline offset
on both ARM and Thumb mode.
(arm_process_displaced_insn): Set is_thumb and insn_size.
(arm_displaced_init_closure): Handle both 16-bit and 32-bit.
(arm_displaced_step_fixup): Likewise.
2011-03-01 Michael Snyder <msnyder@vmware.com> 2011-03-01 Michael Snyder <msnyder@vmware.com>
* cli/cli-dump.c (dump_bfd_file): Check error return and warn. * cli/cli-dump.c (dump_bfd_file): Check error return and warn.

View File

@ -5106,6 +5106,8 @@ arm_adjust_breakpoint_address (struct gdbarch *gdbarch, CORE_ADDR bpaddr)
/* NOP instruction (mov r0, r0). */ /* NOP instruction (mov r0, r0). */
#define ARM_NOP 0xe1a00000 #define ARM_NOP 0xe1a00000
static int displaced_in_arm_mode (struct regcache *regs);
/* Helper for register reads for displaced stepping. In particular, this /* Helper for register reads for displaced stepping. In particular, this
returns the PC as it would be seen by the instruction at its original returns the PC as it would be seen by the instruction at its original
location. */ location. */
@ -5117,10 +5119,21 @@ displaced_read_reg (struct regcache *regs, CORE_ADDR from, int regno)
if (regno == 15) if (regno == 15)
{ {
/* Compute pipeline offset:
- When executing an ARM instruction, PC reads as the address of the
current instruction plus 8.
- When executing a Thumb instruction, PC reads as the address of the
current instruction plus 4. */
if (displaced_in_arm_mode (regs))
from += 8;
else
from += 4;
if (debug_displaced) if (debug_displaced)
fprintf_unfiltered (gdb_stdlog, "displaced: read pc value %.8lx\n", fprintf_unfiltered (gdb_stdlog, "displaced: read pc value %.8lx\n",
(unsigned long) from + 8); (unsigned long) from);
return (ULONGEST) from + 8; /* Pipeline offset. */ return (ULONGEST) from;
} }
else else
{ {
@ -6861,6 +6874,8 @@ arm_process_displaced_insn (struct gdbarch *gdbarch, CORE_ADDR from,
if (!displaced_in_arm_mode (regs)) if (!displaced_in_arm_mode (regs))
return thumb_process_displaced_insn (gdbarch, from, to, regs, dsc); return thumb_process_displaced_insn (gdbarch, from, to, regs, dsc);
dsc->is_thumb = 0;
dsc->insn_size = 4;
insn = read_memory_unsigned_integer (from, 4, byte_order_for_code); insn = read_memory_unsigned_integer (from, 4, byte_order_for_code);
if (debug_displaced) if (debug_displaced)
fprintf_unfiltered (gdb_stdlog, "displaced: stepping insn %.8lx " fprintf_unfiltered (gdb_stdlog, "displaced: stepping insn %.8lx "
@ -6904,23 +6919,49 @@ arm_displaced_init_closure (struct gdbarch *gdbarch, CORE_ADDR from,
CORE_ADDR to, struct displaced_step_closure *dsc) CORE_ADDR to, struct displaced_step_closure *dsc)
{ {
struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
unsigned int i; unsigned int i, len, offset;
enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch); enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
int size = dsc->is_thumb? 2 : 4;
const unsigned char *bkp_insn;
offset = 0;
/* Poke modified instruction(s). */ /* Poke modified instruction(s). */
for (i = 0; i < dsc->numinsns; i++) for (i = 0; i < dsc->numinsns; i++)
{ {
if (debug_displaced) if (debug_displaced)
fprintf_unfiltered (gdb_stdlog, "displaced: writing insn %.8lx at " {
"%.8lx\n", (unsigned long) dsc->modinsn[i], fprintf_unfiltered (gdb_stdlog, "displaced: writing insn ");
(unsigned long) to + i * 4); if (size == 4)
write_memory_unsigned_integer (to + i * 4, 4, byte_order_for_code, fprintf_unfiltered (gdb_stdlog, "%.8lx",
dsc->modinsn[i]);
else if (size == 2)
fprintf_unfiltered (gdb_stdlog, "%.4x",
(unsigned short)dsc->modinsn[i]);
fprintf_unfiltered (gdb_stdlog, " at %.8lx\n",
(unsigned long) to + offset);
}
write_memory_unsigned_integer (to + offset, size,
byte_order_for_code,
dsc->modinsn[i]); dsc->modinsn[i]);
offset += size;
}
/* Choose the correct breakpoint instruction. */
if (dsc->is_thumb)
{
bkp_insn = tdep->thumb_breakpoint;
len = tdep->thumb_breakpoint_size;
}
else
{
bkp_insn = tdep->arm_breakpoint;
len = tdep->arm_breakpoint_size;
} }
/* Put breakpoint afterwards. */ /* Put breakpoint afterwards. */
write_memory (to + dsc->numinsns * 4, tdep->arm_breakpoint, write_memory (to + offset, bkp_insn, len);
tdep->arm_breakpoint_size);
if (debug_displaced) if (debug_displaced)
fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ", fprintf_unfiltered (gdb_stdlog, "displaced: copy %s->%s: ",
@ -6956,7 +6997,9 @@ arm_displaced_step_fixup (struct gdbarch *gdbarch,
dsc->cleanup (gdbarch, regs, dsc); dsc->cleanup (gdbarch, regs, dsc);
if (!dsc->wrote_to_pc) if (!dsc->wrote_to_pc)
regcache_cooked_write_unsigned (regs, ARM_PC_REGNUM, dsc->insn_addr + 4); regcache_cooked_write_unsigned (regs, ARM_PC_REGNUM,
dsc->insn_addr + dsc->insn_size);
} }
#include "bfd-in2.h" #include "bfd-in2.h"

View File

@ -262,6 +262,17 @@ struct displaced_step_closure
struct displaced_step_closure *dsc); struct displaced_step_closure *dsc);
} svc; } svc;
} u; } u;
/* The size of original instruction, 2 or 4. */
unsigned int insn_size;
/* True if the original insn (and thus all replacement insns) are Thumb
instead of ARM. */
unsigned int is_thumb;
/* The slots in the array is used in this way below,
- ARM instruction occupies one slot,
- Thumb 16 bit instruction occupies one slot,
- Thumb 32-bit instruction occupies *two* slots, one part for each. */
unsigned long modinsn[DISPLACED_MODIFIED_INSNS]; unsigned long modinsn[DISPLACED_MODIFIED_INSNS];
int numinsns; int numinsns;
CORE_ADDR insn_addr; CORE_ADDR insn_addr;