Refactor arm_software_single_step to use regcache
This patch is in preparation for software single step support on ARM in GDBServer. It refactors arm_*_software_single_step and sub-functions to use regcache instead of frame to access registers so that the code can be shared more easily between GDB and GDBServer. Note also that since the intention is at some point to get rid of frame completely in that function, memory reads have also been replaced by read_memory_unsigned_integer rather than get_frame_memory_unsigned. No regressions, tested on ubuntu 14.04 ARMv7 and x86. With gdbserver-{native,extended} / { -marm -mthumb } gdb/ChangeLog: * arm-linux-tdep.c (arm_linux_sigreturn_next_pc_offset): New function. (arm_linux_sigreturn_next_pc): Likewise. (arm_linux_syscall_next_pc): Use regcache instead of frame. (arm_linux_software_single_step): Likewise. * arm-tdep.c (arm_is_thumb): New function. (shifted_reg_va): Use regcache instead of frame. (thumb_get_next_pc_raw): Likewise. (arm_get_next_pc_raw): Likewise. (arm_get_next_pc): Likewise. (thumb_deal_with_atomic_sequence_raw): Likewise. (arm_deal_with_atomic_sequence_raw): Likewise. (arm_deal_with_atomic_sequence): Likewise. (arm_software_single_step): Likewise. * arm-tdep.h (struct gdbarch_tdep): Use regcache for syscall_next_pc. (arm_get_next_pc): Use regcache. (arm_deal_with_atomic_sequence): Likewise. (arm_is_thumb): New declaration. * regcache.c (regcache_raw_get_unsigned): New function. * regcache.h (regcache_raw_get_unsigned): New function declaration.
This commit is contained in:
parent
cba7e83fda
commit
d0e59a6888
@ -1,3 +1,25 @@
|
|||||||
|
2015-12-18 Antoine Tremblay <antoine.tremblay@ericsson.com>
|
||||||
|
|
||||||
|
* arm-linux-tdep.c (arm_linux_sigreturn_next_pc_offset): New function.
|
||||||
|
(arm_linux_sigreturn_next_pc): Likewise.
|
||||||
|
(arm_linux_syscall_next_pc): Use regcache instead of frame.
|
||||||
|
(arm_linux_software_single_step): Likewise.
|
||||||
|
* arm-tdep.c (arm_is_thumb): New function.
|
||||||
|
(shifted_reg_va): Use regcache instead of frame.
|
||||||
|
(thumb_get_next_pc_raw): Likewise.
|
||||||
|
(arm_get_next_pc_raw): Likewise.
|
||||||
|
(arm_get_next_pc): Likewise.
|
||||||
|
(thumb_deal_with_atomic_sequence_raw): Likewise.
|
||||||
|
(arm_deal_with_atomic_sequence_raw): Likewise.
|
||||||
|
(arm_deal_with_atomic_sequence): Likewise.
|
||||||
|
(arm_software_single_step): Likewise.
|
||||||
|
* arm-tdep.h (struct gdbarch_tdep): Use regcache for syscall_next_pc.
|
||||||
|
(arm_get_next_pc): Use regcache.
|
||||||
|
(arm_deal_with_atomic_sequence): Likewise.
|
||||||
|
(arm_is_thumb): New declaration.
|
||||||
|
* regcache.c (regcache_raw_get_unsigned): New function.
|
||||||
|
* regcache.h (regcache_raw_get_unsigned): New function declaration.
|
||||||
|
|
||||||
2015-12-18 Antoine Tremblay <antoine.tremblay@ericsson.com>
|
2015-12-18 Antoine Tremblay <antoine.tremblay@ericsson.com>
|
||||||
|
|
||||||
* arch/arm.c (bitcount): Move from arm-tdep.c.
|
* arch/arm.c (bitcount): Move from arm-tdep.c.
|
||||||
|
@ -257,6 +257,11 @@ static const gdb_byte arm_linux_thumb2_le_breakpoint[] = { 0xf0, 0xf7, 0x00, 0xa
|
|||||||
#define ARM_LDR_PC_SP_12 0xe49df00c
|
#define ARM_LDR_PC_SP_12 0xe49df00c
|
||||||
#define ARM_LDR_PC_SP_4 0xe49df004
|
#define ARM_LDR_PC_SP_4 0xe49df004
|
||||||
|
|
||||||
|
/* Syscall number for sigreturn. */
|
||||||
|
#define ARM_SIGRETURN 119
|
||||||
|
/* Syscall number for rt_sigreturn. */
|
||||||
|
#define ARM_RT_SIGRETURN 173
|
||||||
|
|
||||||
static void
|
static void
|
||||||
arm_linux_sigtramp_cache (struct frame_info *this_frame,
|
arm_linux_sigtramp_cache (struct frame_info *this_frame,
|
||||||
struct trad_frame_cache *this_cache,
|
struct trad_frame_cache *this_cache,
|
||||||
@ -805,6 +810,70 @@ arm_linux_sigreturn_return_addr (struct frame_info *frame,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Calculate the offset from stack pointer of the pc register on the stack
|
||||||
|
in the case of a sigreturn or sigreturn_rt syscall. */
|
||||||
|
static int
|
||||||
|
arm_linux_sigreturn_next_pc_offset (unsigned long sp,
|
||||||
|
unsigned long sp_data,
|
||||||
|
unsigned long svc_number,
|
||||||
|
int is_sigreturn)
|
||||||
|
{
|
||||||
|
/* Offset of R0 register. */
|
||||||
|
int r0_offset = 0;
|
||||||
|
/* Offset of PC register. */
|
||||||
|
int pc_offset = 0;
|
||||||
|
|
||||||
|
if (is_sigreturn)
|
||||||
|
{
|
||||||
|
if (sp_data == ARM_NEW_SIGFRAME_MAGIC)
|
||||||
|
r0_offset = ARM_UCONTEXT_SIGCONTEXT + ARM_SIGCONTEXT_R0;
|
||||||
|
else
|
||||||
|
r0_offset = ARM_SIGCONTEXT_R0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (sp_data == sp + ARM_OLD_RT_SIGFRAME_SIGINFO)
|
||||||
|
r0_offset = ARM_OLD_RT_SIGFRAME_UCONTEXT;
|
||||||
|
else
|
||||||
|
r0_offset = ARM_NEW_RT_SIGFRAME_UCONTEXT;
|
||||||
|
|
||||||
|
r0_offset += ARM_UCONTEXT_SIGCONTEXT + ARM_SIGCONTEXT_R0;
|
||||||
|
}
|
||||||
|
|
||||||
|
pc_offset = r0_offset + INT_REGISTER_SIZE * ARM_PC_REGNUM;
|
||||||
|
|
||||||
|
return pc_offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Find the value of the next PC after a sigreturn or rt_sigreturn syscall
|
||||||
|
based on current processor state. */
|
||||||
|
static CORE_ADDR
|
||||||
|
arm_linux_sigreturn_next_pc (struct regcache *regcache,
|
||||||
|
unsigned long svc_number)
|
||||||
|
{
|
||||||
|
ULONGEST sp;
|
||||||
|
unsigned long sp_data;
|
||||||
|
CORE_ADDR next_pc = 0;
|
||||||
|
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||||
|
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||||
|
int pc_offset = 0;
|
||||||
|
int is_sigreturn = 0;
|
||||||
|
|
||||||
|
gdb_assert (svc_number == ARM_SIGRETURN
|
||||||
|
|| svc_number == ARM_RT_SIGRETURN);
|
||||||
|
|
||||||
|
is_sigreturn = (svc_number == ARM_SIGRETURN);
|
||||||
|
regcache_cooked_read_unsigned (regcache, ARM_SP_REGNUM, &sp);
|
||||||
|
sp_data = read_memory_unsigned_integer (sp, 4, byte_order);
|
||||||
|
|
||||||
|
pc_offset = arm_linux_sigreturn_next_pc_offset (sp, sp_data, svc_number,
|
||||||
|
is_sigreturn);
|
||||||
|
|
||||||
|
next_pc = read_memory_unsigned_integer (sp + pc_offset, 4, byte_order);
|
||||||
|
|
||||||
|
return next_pc;
|
||||||
|
}
|
||||||
|
|
||||||
/* At a ptrace syscall-stop, return the syscall number. This either
|
/* At a ptrace syscall-stop, return the syscall number. This either
|
||||||
comes from the SWI instruction (OABI) or from r7 (EABI).
|
comes from the SWI instruction (OABI) or from r7 (EABI).
|
||||||
|
|
||||||
@ -858,25 +927,26 @@ arm_linux_get_syscall_number (struct gdbarch *gdbarch,
|
|||||||
return svc_number;
|
return svc_number;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* When FRAME is at a syscall instruction, return the PC of the next
|
/* When the processor is at a syscall instruction, return the PC of the
|
||||||
instruction to be executed. */
|
next instruction to be executed. */
|
||||||
|
|
||||||
static CORE_ADDR
|
static CORE_ADDR
|
||||||
arm_linux_syscall_next_pc (struct frame_info *frame)
|
arm_linux_syscall_next_pc (struct regcache *regcache)
|
||||||
{
|
{
|
||||||
CORE_ADDR pc = get_frame_pc (frame);
|
CORE_ADDR pc = regcache_read_pc (regcache);
|
||||||
CORE_ADDR return_addr = 0;
|
CORE_ADDR next_pc = 0;
|
||||||
int is_thumb = arm_frame_is_thumb (frame);
|
int is_thumb = arm_is_thumb (regcache);
|
||||||
ULONGEST svc_number = 0;
|
ULONGEST svc_number = 0;
|
||||||
|
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||||
|
|
||||||
if (is_thumb)
|
if (is_thumb)
|
||||||
{
|
{
|
||||||
svc_number = get_frame_register_unsigned (frame, 7);
|
svc_number = regcache_raw_get_unsigned (regcache, 7);
|
||||||
return_addr = pc + 2;
|
next_pc = pc + 2;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = get_frame_arch (frame);
|
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||||
enum bfd_endian byte_order_for_code =
|
enum bfd_endian byte_order_for_code =
|
||||||
gdbarch_byte_order_for_code (gdbarch);
|
gdbarch_byte_order_for_code (gdbarch);
|
||||||
unsigned long this_instr =
|
unsigned long this_instr =
|
||||||
@ -889,19 +959,20 @@ arm_linux_syscall_next_pc (struct frame_info *frame)
|
|||||||
}
|
}
|
||||||
else /* EABI. */
|
else /* EABI. */
|
||||||
{
|
{
|
||||||
svc_number = get_frame_register_unsigned (frame, 7);
|
svc_number = regcache_raw_get_unsigned (regcache, 7);
|
||||||
}
|
}
|
||||||
|
|
||||||
return_addr = pc + 4;
|
next_pc = pc + 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
arm_linux_sigreturn_return_addr (frame, svc_number, &return_addr, &is_thumb);
|
if (svc_number == ARM_SIGRETURN || svc_number == ARM_RT_SIGRETURN)
|
||||||
|
next_pc = arm_linux_sigreturn_next_pc (regcache, svc_number);
|
||||||
|
|
||||||
/* Addresses for calling Thumb functions have the bit 0 set. */
|
/* Addresses for calling Thumb functions have the bit 0 set. */
|
||||||
if (is_thumb)
|
if (is_thumb)
|
||||||
return_addr |= 1;
|
next_pc = MAKE_THUMB_ADDR (next_pc);
|
||||||
|
|
||||||
return return_addr;
|
return next_pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -910,11 +981,13 @@ arm_linux_syscall_next_pc (struct frame_info *frame)
|
|||||||
static int
|
static int
|
||||||
arm_linux_software_single_step (struct frame_info *frame)
|
arm_linux_software_single_step (struct frame_info *frame)
|
||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = get_frame_arch (frame);
|
struct regcache *regcache = get_current_regcache ();
|
||||||
struct address_space *aspace = get_frame_address_space (frame);
|
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||||
|
struct address_space *aspace = get_regcache_aspace (regcache);
|
||||||
|
|
||||||
CORE_ADDR next_pc;
|
CORE_ADDR next_pc;
|
||||||
|
|
||||||
if (arm_deal_with_atomic_sequence (frame))
|
if (arm_deal_with_atomic_sequence (regcache))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
/* If the target does have hardware single step, GDB doesn't have
|
/* If the target does have hardware single step, GDB doesn't have
|
||||||
@ -922,7 +995,7 @@ arm_linux_software_single_step (struct frame_info *frame)
|
|||||||
if (target_can_do_single_step () == 1)
|
if (target_can_do_single_step () == 1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
next_pc = arm_get_next_pc (frame, get_frame_pc (frame));
|
next_pc = arm_get_next_pc (regcache, regcache_read_pc (regcache));
|
||||||
|
|
||||||
/* The Linux kernel offers some user-mode helpers in a high page. We can
|
/* The Linux kernel offers some user-mode helpers in a high page. We can
|
||||||
not read this page (as of 2.6.23), and even if we could then we couldn't
|
not read this page (as of 2.6.23), and even if we could then we couldn't
|
||||||
|
132
gdb/arm-tdep.c
132
gdb/arm-tdep.c
@ -281,6 +281,19 @@ arm_psr_thumb_bit (struct gdbarch *gdbarch)
|
|||||||
return CPSR_T;
|
return CPSR_T;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Determine if the processor is currently executing in Thumb mode. */
|
||||||
|
|
||||||
|
int
|
||||||
|
arm_is_thumb (struct regcache *regcache)
|
||||||
|
{
|
||||||
|
ULONGEST cpsr;
|
||||||
|
ULONGEST t_bit = arm_psr_thumb_bit (get_regcache_arch (regcache));
|
||||||
|
|
||||||
|
cpsr = regcache_raw_get_unsigned (regcache, ARM_PS_REGNUM);
|
||||||
|
|
||||||
|
return (cpsr & t_bit) != 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* Determine if FRAME is executing in Thumb mode. */
|
/* Determine if FRAME is executing in Thumb mode. */
|
||||||
|
|
||||||
int
|
int
|
||||||
@ -4302,7 +4315,7 @@ convert_to_extended (const struct floatformat *fmt, void *dbl, const void *ptr,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static unsigned long
|
static unsigned long
|
||||||
shifted_reg_val (struct frame_info *frame, unsigned long inst, int carry,
|
shifted_reg_val (struct regcache *regcache, unsigned long inst, int carry,
|
||||||
unsigned long pc_val, unsigned long status_reg)
|
unsigned long pc_val, unsigned long status_reg)
|
||||||
{
|
{
|
||||||
unsigned long res, shift;
|
unsigned long res, shift;
|
||||||
@ -4313,14 +4326,14 @@ shifted_reg_val (struct frame_info *frame, unsigned long inst, int carry,
|
|||||||
{
|
{
|
||||||
int rs = bits (inst, 8, 11);
|
int rs = bits (inst, 8, 11);
|
||||||
shift = (rs == 15 ? pc_val + 8
|
shift = (rs == 15 ? pc_val + 8
|
||||||
: get_frame_register_unsigned (frame, rs)) & 0xFF;
|
: regcache_raw_get_unsigned (regcache, rs)) & 0xFF;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
shift = bits (inst, 7, 11);
|
shift = bits (inst, 7, 11);
|
||||||
|
|
||||||
res = (rm == ARM_PC_REGNUM
|
res = (rm == ARM_PC_REGNUM
|
||||||
? (pc_val + (bit (inst, 4) ? 12 : 8))
|
? (pc_val + (bit (inst, 4) ? 12 : 8))
|
||||||
: get_frame_register_unsigned (frame, rm));
|
: regcache_raw_get_unsigned (regcache, rm));
|
||||||
|
|
||||||
switch (shifttype)
|
switch (shifttype)
|
||||||
{
|
{
|
||||||
@ -4372,10 +4385,10 @@ thumb_advance_itstate (unsigned int itstate)
|
|||||||
another breakpoint by our caller. */
|
another breakpoint by our caller. */
|
||||||
|
|
||||||
static CORE_ADDR
|
static CORE_ADDR
|
||||||
thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
thumb_get_next_pc_raw (struct regcache *regcache, CORE_ADDR pc)
|
||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = get_frame_arch (frame);
|
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||||
struct address_space *aspace = get_frame_address_space (frame);
|
struct address_space *aspace = get_regcache_aspace (regcache);
|
||||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||||
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);
|
||||||
unsigned long pc_val = ((unsigned long) pc) + 4; /* PC after prefetch */
|
unsigned long pc_val = ((unsigned long) pc) + 4; /* PC after prefetch */
|
||||||
@ -4397,7 +4410,7 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
base condition. One of the low four bits will be set if an IT
|
base condition. One of the low four bits will be set if an IT
|
||||||
block is active. These bits read as zero on earlier
|
block is active. These bits read as zero on earlier
|
||||||
processors. */
|
processors. */
|
||||||
status = get_frame_register_unsigned (frame, ARM_PS_REGNUM);
|
status = regcache_raw_get_unsigned (regcache, ARM_PS_REGNUM);
|
||||||
itstate = ((status >> 8) & 0xfc) | ((status >> 25) & 0x3);
|
itstate = ((status >> 8) & 0xfc) | ((status >> 25) & 0x3);
|
||||||
|
|
||||||
/* If-Then handling. On GNU/Linux, where this routine is used, we
|
/* If-Then handling. On GNU/Linux, where this routine is used, we
|
||||||
@ -4512,7 +4525,7 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
/* Fetch the saved PC from the stack. It's stored above
|
/* Fetch the saved PC from the stack. It's stored above
|
||||||
all of the other registers. */
|
all of the other registers. */
|
||||||
offset = bitcount (bits (inst1, 0, 7)) * INT_REGISTER_SIZE;
|
offset = bitcount (bits (inst1, 0, 7)) * INT_REGISTER_SIZE;
|
||||||
sp = get_frame_register_unsigned (frame, ARM_SP_REGNUM);
|
sp = regcache_raw_get_unsigned (regcache, ARM_SP_REGNUM);
|
||||||
nextpc = read_memory_unsigned_integer (sp + offset, 4, byte_order);
|
nextpc = read_memory_unsigned_integer (sp + offset, 4, byte_order);
|
||||||
}
|
}
|
||||||
else if ((inst1 & 0xf000) == 0xd000) /* conditional branch */
|
else if ((inst1 & 0xf000) == 0xd000) /* conditional branch */
|
||||||
@ -4524,7 +4537,7 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
tdep = gdbarch_tdep (gdbarch);
|
tdep = gdbarch_tdep (gdbarch);
|
||||||
|
|
||||||
if (tdep->syscall_next_pc != NULL)
|
if (tdep->syscall_next_pc != NULL)
|
||||||
nextpc = tdep->syscall_next_pc (frame);
|
nextpc = tdep->syscall_next_pc (regcache);
|
||||||
|
|
||||||
}
|
}
|
||||||
else if (cond != 0x0f && condition_true (cond, status))
|
else if (cond != 0x0f && condition_true (cond, status))
|
||||||
@ -4568,7 +4581,7 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
else if (inst1 == 0xf3de && (inst2 & 0xff00) == 0x3f00)
|
else if (inst1 == 0xf3de && (inst2 & 0xff00) == 0x3f00)
|
||||||
{
|
{
|
||||||
/* SUBS PC, LR, #imm8. */
|
/* SUBS PC, LR, #imm8. */
|
||||||
nextpc = get_frame_register_unsigned (frame, ARM_LR_REGNUM);
|
nextpc = regcache_raw_get_unsigned (regcache, ARM_LR_REGNUM);
|
||||||
nextpc -= inst2 & 0x00ff;
|
nextpc -= inst2 & 0x00ff;
|
||||||
}
|
}
|
||||||
else if ((inst2 & 0xd000) == 0x8000 && (inst1 & 0x0380) != 0x0380)
|
else if ((inst2 & 0xd000) == 0x8000 && (inst1 & 0x0380) != 0x0380)
|
||||||
@ -4626,14 +4639,15 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
|
|
||||||
if (load_pc)
|
if (load_pc)
|
||||||
{
|
{
|
||||||
CORE_ADDR addr = get_frame_register_unsigned (frame, rn);
|
CORE_ADDR addr = regcache_raw_get_unsigned (regcache, rn);
|
||||||
nextpc = get_frame_memory_unsigned (frame, addr + offset, 4);
|
nextpc = read_memory_unsigned_integer (addr + offset, 4,
|
||||||
|
byte_order);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if ((inst1 & 0xffef) == 0xea4f && (inst2 & 0xfff0) == 0x0f00)
|
else if ((inst1 & 0xffef) == 0xea4f && (inst2 & 0xfff0) == 0x0f00)
|
||||||
{
|
{
|
||||||
/* MOV PC or MOVS PC. */
|
/* MOV PC or MOVS PC. */
|
||||||
nextpc = get_frame_register_unsigned (frame, bits (inst2, 0, 3));
|
nextpc = regcache_raw_get_unsigned (regcache, bits (inst2, 0, 3));
|
||||||
nextpc = MAKE_THUMB_ADDR (nextpc);
|
nextpc = MAKE_THUMB_ADDR (nextpc);
|
||||||
}
|
}
|
||||||
else if ((inst1 & 0xff70) == 0xf850 && (inst2 & 0xf000) == 0xf000)
|
else if ((inst1 & 0xff70) == 0xf850 && (inst2 & 0xf000) == 0xf000)
|
||||||
@ -4643,7 +4657,7 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
int rn, load_pc = 1;
|
int rn, load_pc = 1;
|
||||||
|
|
||||||
rn = bits (inst1, 0, 3);
|
rn = bits (inst1, 0, 3);
|
||||||
base = get_frame_register_unsigned (frame, rn);
|
base = regcache_raw_get_unsigned (regcache, rn);
|
||||||
if (rn == ARM_PC_REGNUM)
|
if (rn == ARM_PC_REGNUM)
|
||||||
{
|
{
|
||||||
base = (base + 4) & ~(CORE_ADDR) 0x3;
|
base = (base + 4) & ~(CORE_ADDR) 0x3;
|
||||||
@ -4667,14 +4681,14 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
else if ((inst2 & 0x0fc0) == 0x0000)
|
else if ((inst2 & 0x0fc0) == 0x0000)
|
||||||
{
|
{
|
||||||
int shift = bits (inst2, 4, 5), rm = bits (inst2, 0, 3);
|
int shift = bits (inst2, 4, 5), rm = bits (inst2, 0, 3);
|
||||||
base += get_frame_register_unsigned (frame, rm) << shift;
|
base += regcache_raw_get_unsigned (regcache, rm) << shift;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
/* Reserved. */
|
/* Reserved. */
|
||||||
load_pc = 0;
|
load_pc = 0;
|
||||||
|
|
||||||
if (load_pc)
|
if (load_pc)
|
||||||
nextpc = get_frame_memory_unsigned (frame, base, 4);
|
nextpc = read_memory_unsigned_integer (base, 4, byte_order);
|
||||||
}
|
}
|
||||||
else if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf000)
|
else if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf000)
|
||||||
{
|
{
|
||||||
@ -4685,10 +4699,11 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
if (tbl_reg == 0x0f)
|
if (tbl_reg == 0x0f)
|
||||||
table = pc + 4; /* Regcache copy of PC isn't right yet. */
|
table = pc + 4; /* Regcache copy of PC isn't right yet. */
|
||||||
else
|
else
|
||||||
table = get_frame_register_unsigned (frame, tbl_reg);
|
table = regcache_raw_get_unsigned (regcache, tbl_reg);
|
||||||
|
|
||||||
offset = get_frame_register_unsigned (frame, bits (inst2, 0, 3));
|
offset = regcache_raw_get_unsigned (regcache, bits (inst2, 0, 3));
|
||||||
length = 2 * get_frame_memory_unsigned (frame, table + offset, 1);
|
length = 2 * read_memory_unsigned_integer (table + offset, 1,
|
||||||
|
byte_order);
|
||||||
nextpc = pc_val + length;
|
nextpc = pc_val + length;
|
||||||
}
|
}
|
||||||
else if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf010)
|
else if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf010)
|
||||||
@ -4700,10 +4715,11 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
if (tbl_reg == 0x0f)
|
if (tbl_reg == 0x0f)
|
||||||
table = pc + 4; /* Regcache copy of PC isn't right yet. */
|
table = pc + 4; /* Regcache copy of PC isn't right yet. */
|
||||||
else
|
else
|
||||||
table = get_frame_register_unsigned (frame, tbl_reg);
|
table = regcache_raw_get_unsigned (regcache, tbl_reg);
|
||||||
|
|
||||||
offset = 2 * get_frame_register_unsigned (frame, bits (inst2, 0, 3));
|
offset = 2 * regcache_raw_get_unsigned (regcache, bits (inst2, 0, 3));
|
||||||
length = 2 * get_frame_memory_unsigned (frame, table + offset, 2);
|
length = 2 * read_memory_unsigned_integer (table + offset, 2,
|
||||||
|
byte_order);
|
||||||
nextpc = pc_val + length;
|
nextpc = pc_val + length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -4712,14 +4728,14 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
if (bits (inst1, 3, 6) == 0x0f)
|
if (bits (inst1, 3, 6) == 0x0f)
|
||||||
nextpc = UNMAKE_THUMB_ADDR (pc_val);
|
nextpc = UNMAKE_THUMB_ADDR (pc_val);
|
||||||
else
|
else
|
||||||
nextpc = get_frame_register_unsigned (frame, bits (inst1, 3, 6));
|
nextpc = regcache_raw_get_unsigned (regcache, bits (inst1, 3, 6));
|
||||||
}
|
}
|
||||||
else if ((inst1 & 0xff87) == 0x4687) /* mov pc, REG */
|
else if ((inst1 & 0xff87) == 0x4687) /* mov pc, REG */
|
||||||
{
|
{
|
||||||
if (bits (inst1, 3, 6) == 0x0f)
|
if (bits (inst1, 3, 6) == 0x0f)
|
||||||
nextpc = pc_val;
|
nextpc = pc_val;
|
||||||
else
|
else
|
||||||
nextpc = get_frame_register_unsigned (frame, bits (inst1, 3, 6));
|
nextpc = regcache_raw_get_unsigned (regcache, bits (inst1, 3, 6));
|
||||||
|
|
||||||
nextpc = MAKE_THUMB_ADDR (nextpc);
|
nextpc = MAKE_THUMB_ADDR (nextpc);
|
||||||
}
|
}
|
||||||
@ -4727,7 +4743,7 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
{
|
{
|
||||||
/* CBNZ or CBZ. */
|
/* CBNZ or CBZ. */
|
||||||
int imm = (bit (inst1, 9) << 6) + (bits (inst1, 3, 7) << 1);
|
int imm = (bit (inst1, 9) << 6) + (bits (inst1, 3, 7) << 1);
|
||||||
ULONGEST reg = get_frame_register_unsigned (frame, bits (inst1, 0, 2));
|
ULONGEST reg = regcache_raw_get_unsigned (regcache, bits (inst1, 0, 2));
|
||||||
|
|
||||||
if (bit (inst1, 11) && reg != 0)
|
if (bit (inst1, 11) && reg != 0)
|
||||||
nextpc = pc_val + imm;
|
nextpc = pc_val + imm;
|
||||||
@ -4746,9 +4762,9 @@ thumb_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
address. */
|
address. */
|
||||||
|
|
||||||
static CORE_ADDR
|
static CORE_ADDR
|
||||||
arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
arm_get_next_pc_raw (struct regcache *regcache, CORE_ADDR pc)
|
||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = get_frame_arch (frame);
|
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||||
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
|
||||||
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);
|
||||||
unsigned long pc_val;
|
unsigned long pc_val;
|
||||||
@ -4759,7 +4775,7 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
pc_val = (unsigned long) pc;
|
pc_val = (unsigned long) pc;
|
||||||
this_instr = read_memory_unsigned_integer (pc, 4, byte_order_for_code);
|
this_instr = read_memory_unsigned_integer (pc, 4, byte_order_for_code);
|
||||||
|
|
||||||
status = get_frame_register_unsigned (frame, ARM_PS_REGNUM);
|
status = regcache_raw_get_unsigned (regcache, ARM_PS_REGNUM);
|
||||||
nextpc = (CORE_ADDR) (pc_val + 4); /* Default case */
|
nextpc = (CORE_ADDR) (pc_val + 4); /* Default case */
|
||||||
|
|
||||||
if (bits (this_instr, 28, 31) == INST_NV)
|
if (bits (this_instr, 28, 31) == INST_NV)
|
||||||
@ -4809,7 +4825,7 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
rn = bits (this_instr, 0, 3);
|
rn = bits (this_instr, 0, 3);
|
||||||
nextpc = ((rn == ARM_PC_REGNUM)
|
nextpc = ((rn == ARM_PC_REGNUM)
|
||||||
? (pc_val + 8)
|
? (pc_val + 8)
|
||||||
: get_frame_register_unsigned (frame, rn));
|
: regcache_raw_get_unsigned (regcache, rn));
|
||||||
|
|
||||||
return nextpc;
|
return nextpc;
|
||||||
}
|
}
|
||||||
@ -4819,7 +4835,7 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
rn = bits (this_instr, 16, 19);
|
rn = bits (this_instr, 16, 19);
|
||||||
operand1 = ((rn == ARM_PC_REGNUM)
|
operand1 = ((rn == ARM_PC_REGNUM)
|
||||||
? (pc_val + 8)
|
? (pc_val + 8)
|
||||||
: get_frame_register_unsigned (frame, rn));
|
: regcache_raw_get_unsigned (regcache, rn));
|
||||||
|
|
||||||
if (bit (this_instr, 25))
|
if (bit (this_instr, 25))
|
||||||
{
|
{
|
||||||
@ -4829,7 +4845,7 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
& 0xffffffff;
|
& 0xffffffff;
|
||||||
}
|
}
|
||||||
else /* operand 2 is a shifted register. */
|
else /* operand 2 is a shifted register. */
|
||||||
operand2 = shifted_reg_val (frame, this_instr, c,
|
operand2 = shifted_reg_val (regcache, this_instr, c,
|
||||||
pc_val, status);
|
pc_val, status);
|
||||||
|
|
||||||
switch (bits (this_instr, 21, 24))
|
switch (bits (this_instr, 21, 24))
|
||||||
@ -4928,7 +4944,7 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
rn = bits (this_instr, 16, 19);
|
rn = bits (this_instr, 16, 19);
|
||||||
base = ((rn == ARM_PC_REGNUM)
|
base = ((rn == ARM_PC_REGNUM)
|
||||||
? (pc_val + 8)
|
? (pc_val + 8)
|
||||||
: get_frame_register_unsigned (frame, rn));
|
: regcache_raw_get_unsigned (regcache, rn));
|
||||||
|
|
||||||
if (bit (this_instr, 24))
|
if (bit (this_instr, 24))
|
||||||
{
|
{
|
||||||
@ -4936,7 +4952,8 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
int c = (status & FLAG_C) ? 1 : 0;
|
int c = (status & FLAG_C) ? 1 : 0;
|
||||||
unsigned long offset =
|
unsigned long offset =
|
||||||
(bit (this_instr, 25)
|
(bit (this_instr, 25)
|
||||||
? shifted_reg_val (frame, this_instr, c, pc_val, status)
|
? shifted_reg_val (regcache, this_instr, c, pc_val,
|
||||||
|
status)
|
||||||
: bits (this_instr, 0, 11));
|
: bits (this_instr, 0, 11));
|
||||||
|
|
||||||
if (bit (this_instr, 23))
|
if (bit (this_instr, 23))
|
||||||
@ -4961,8 +4978,8 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
/* loading pc */
|
/* loading pc */
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
unsigned long rn_val
|
unsigned long rn_val
|
||||||
= get_frame_register_unsigned (frame,
|
= regcache_raw_get_unsigned (regcache,
|
||||||
bits (this_instr, 16, 19));
|
bits (this_instr, 16, 19));
|
||||||
|
|
||||||
if (bit (this_instr, 23))
|
if (bit (this_instr, 23))
|
||||||
{
|
{
|
||||||
@ -5000,7 +5017,7 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
tdep = gdbarch_tdep (gdbarch);
|
tdep = gdbarch_tdep (gdbarch);
|
||||||
|
|
||||||
if (tdep->syscall_next_pc != NULL)
|
if (tdep->syscall_next_pc != NULL)
|
||||||
nextpc = tdep->syscall_next_pc (frame);
|
nextpc = tdep->syscall_next_pc (regcache);
|
||||||
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -5019,14 +5036,14 @@ arm_get_next_pc_raw (struct frame_info *frame, CORE_ADDR pc)
|
|||||||
loop is detected. */
|
loop is detected. */
|
||||||
|
|
||||||
CORE_ADDR
|
CORE_ADDR
|
||||||
arm_get_next_pc (struct frame_info *frame, CORE_ADDR pc)
|
arm_get_next_pc (struct regcache *regcache, CORE_ADDR pc)
|
||||||
{
|
{
|
||||||
CORE_ADDR nextpc;
|
CORE_ADDR nextpc;
|
||||||
|
|
||||||
if (arm_frame_is_thumb (frame))
|
if (arm_is_thumb (regcache))
|
||||||
nextpc = thumb_get_next_pc_raw (frame, pc);
|
nextpc = thumb_get_next_pc_raw (regcache, pc);
|
||||||
else
|
else
|
||||||
nextpc = arm_get_next_pc_raw (frame, pc);
|
nextpc = arm_get_next_pc_raw (regcache, pc);
|
||||||
|
|
||||||
return nextpc;
|
return nextpc;
|
||||||
}
|
}
|
||||||
@ -5057,12 +5074,12 @@ arm_insert_single_step_breakpoint (struct gdbarch *gdbarch,
|
|||||||
the sequence. */
|
the sequence. */
|
||||||
|
|
||||||
static int
|
static int
|
||||||
thumb_deal_with_atomic_sequence_raw (struct frame_info *frame)
|
thumb_deal_with_atomic_sequence_raw (struct regcache *regcache)
|
||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = get_frame_arch (frame);
|
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||||
struct address_space *aspace = get_frame_address_space (frame);
|
struct address_space *aspace = get_regcache_aspace (regcache);
|
||||||
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);
|
||||||
CORE_ADDR pc = get_frame_pc (frame);
|
CORE_ADDR pc = regcache_read_pc (regcache);
|
||||||
CORE_ADDR breaks[2] = {-1, -1};
|
CORE_ADDR breaks[2] = {-1, -1};
|
||||||
CORE_ADDR loc = pc;
|
CORE_ADDR loc = pc;
|
||||||
unsigned short insn1, insn2;
|
unsigned short insn1, insn2;
|
||||||
@ -5073,7 +5090,7 @@ thumb_deal_with_atomic_sequence_raw (struct frame_info *frame)
|
|||||||
ULONGEST status, itstate;
|
ULONGEST status, itstate;
|
||||||
|
|
||||||
/* We currently do not support atomic sequences within an IT block. */
|
/* We currently do not support atomic sequences within an IT block. */
|
||||||
status = get_frame_register_unsigned (frame, ARM_PS_REGNUM);
|
status = regcache_raw_get_unsigned (regcache, ARM_PS_REGNUM);
|
||||||
itstate = ((status >> 8) & 0xfc) | ((status >> 25) & 0x3);
|
itstate = ((status >> 8) & 0xfc) | ((status >> 25) & 0x3);
|
||||||
if (itstate & 0x0f)
|
if (itstate & 0x0f)
|
||||||
return 0;
|
return 0;
|
||||||
@ -5188,12 +5205,12 @@ thumb_deal_with_atomic_sequence_raw (struct frame_info *frame)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
arm_deal_with_atomic_sequence_raw (struct frame_info *frame)
|
arm_deal_with_atomic_sequence_raw (struct regcache *regcache)
|
||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = get_frame_arch (frame);
|
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||||
struct address_space *aspace = get_frame_address_space (frame);
|
struct address_space *aspace = get_regcache_aspace (regcache);
|
||||||
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);
|
||||||
CORE_ADDR pc = get_frame_pc (frame);
|
CORE_ADDR pc = regcache_read_pc (regcache);
|
||||||
CORE_ADDR breaks[2] = {-1, -1};
|
CORE_ADDR breaks[2] = {-1, -1};
|
||||||
CORE_ADDR loc = pc;
|
CORE_ADDR loc = pc;
|
||||||
unsigned int insn;
|
unsigned int insn;
|
||||||
@ -5263,12 +5280,12 @@ arm_deal_with_atomic_sequence_raw (struct frame_info *frame)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
arm_deal_with_atomic_sequence (struct frame_info *frame)
|
arm_deal_with_atomic_sequence (struct regcache *regcache)
|
||||||
{
|
{
|
||||||
if (arm_frame_is_thumb (frame))
|
if (arm_is_thumb (regcache))
|
||||||
return thumb_deal_with_atomic_sequence_raw (frame);
|
return thumb_deal_with_atomic_sequence_raw (regcache);
|
||||||
else
|
else
|
||||||
return arm_deal_with_atomic_sequence_raw (frame);
|
return arm_deal_with_atomic_sequence_raw (regcache);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* single_step() is called just before we want to resume the inferior,
|
/* single_step() is called just before we want to resume the inferior,
|
||||||
@ -5279,14 +5296,15 @@ arm_deal_with_atomic_sequence (struct frame_info *frame)
|
|||||||
int
|
int
|
||||||
arm_software_single_step (struct frame_info *frame)
|
arm_software_single_step (struct frame_info *frame)
|
||||||
{
|
{
|
||||||
struct gdbarch *gdbarch = get_frame_arch (frame);
|
struct regcache *regcache = get_current_regcache ();
|
||||||
struct address_space *aspace = get_frame_address_space (frame);
|
struct gdbarch *gdbarch = get_regcache_arch (regcache);
|
||||||
|
struct address_space *aspace = get_regcache_aspace (regcache);
|
||||||
CORE_ADDR next_pc;
|
CORE_ADDR next_pc;
|
||||||
|
|
||||||
if (arm_deal_with_atomic_sequence (frame))
|
if (arm_deal_with_atomic_sequence (regcache))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
next_pc = arm_get_next_pc (frame, get_frame_pc (frame));
|
next_pc = arm_get_next_pc (regcache, regcache_read_pc (regcache));
|
||||||
arm_insert_single_step_breakpoint (gdbarch, aspace, next_pc);
|
arm_insert_single_step_breakpoint (gdbarch, aspace, next_pc);
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -135,9 +135,9 @@ struct gdbarch_tdep
|
|||||||
struct type *neon_double_type;
|
struct type *neon_double_type;
|
||||||
struct type *neon_quad_type;
|
struct type *neon_quad_type;
|
||||||
|
|
||||||
/* Return the expected next PC if FRAME is stopped at a syscall
|
/* Return the expected next PC if the program is stopped at a syscall
|
||||||
instruction. */
|
instruction. */
|
||||||
CORE_ADDR (*syscall_next_pc) (struct frame_info *frame);
|
CORE_ADDR (*syscall_next_pc) (struct regcache *regcache);
|
||||||
|
|
||||||
/* syscall record. */
|
/* syscall record. */
|
||||||
int (*arm_syscall_record) (struct regcache *regcache, unsigned long svc_number);
|
int (*arm_syscall_record) (struct regcache *regcache, unsigned long svc_number);
|
||||||
@ -250,11 +250,12 @@ extern void
|
|||||||
ULONGEST val, enum pc_write_style write_pc);
|
ULONGEST val, enum pc_write_style write_pc);
|
||||||
|
|
||||||
CORE_ADDR arm_skip_stub (struct frame_info *, CORE_ADDR);
|
CORE_ADDR arm_skip_stub (struct frame_info *, CORE_ADDR);
|
||||||
CORE_ADDR arm_get_next_pc (struct frame_info *, CORE_ADDR);
|
CORE_ADDR arm_get_next_pc (struct regcache *regcache, CORE_ADDR pc);
|
||||||
void arm_insert_single_step_breakpoint (struct gdbarch *,
|
void arm_insert_single_step_breakpoint (struct gdbarch *,
|
||||||
struct address_space *, CORE_ADDR);
|
struct address_space *, CORE_ADDR);
|
||||||
int arm_deal_with_atomic_sequence (struct frame_info *);
|
int arm_deal_with_atomic_sequence (struct regcache *);
|
||||||
int arm_software_single_step (struct frame_info *);
|
int arm_software_single_step (struct frame_info *);
|
||||||
|
int arm_is_thumb (struct regcache *regcache);
|
||||||
int arm_frame_is_thumb (struct frame_info *frame);
|
int arm_frame_is_thumb (struct frame_info *frame);
|
||||||
|
|
||||||
extern struct displaced_step_closure *
|
extern struct displaced_step_closure *
|
||||||
|
@ -715,6 +715,21 @@ regcache_raw_read_unsigned (struct regcache *regcache, int regnum,
|
|||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Return the register's value or throw if it's not available. */
|
||||||
|
|
||||||
|
ULONGEST
|
||||||
|
regcache_raw_get_unsigned (struct regcache *regcache, int regnum)
|
||||||
|
{
|
||||||
|
ULONGEST value;
|
||||||
|
enum register_status status;
|
||||||
|
|
||||||
|
status = regcache_raw_read_unsigned (regcache, regnum, &value);
|
||||||
|
if (status == REG_UNAVAILABLE)
|
||||||
|
throw_error (NOT_AVAILABLE_ERROR,
|
||||||
|
_("Register %d is not available"), regnum);
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
regcache_raw_write_signed (struct regcache *regcache, int regnum, LONGEST val)
|
regcache_raw_write_signed (struct regcache *regcache, int regnum, LONGEST val)
|
||||||
{
|
{
|
||||||
|
@ -81,6 +81,10 @@ extern enum register_status
|
|||||||
extern enum register_status
|
extern enum register_status
|
||||||
regcache_raw_read_unsigned (struct regcache *regcache,
|
regcache_raw_read_unsigned (struct regcache *regcache,
|
||||||
int regnum, ULONGEST *val);
|
int regnum, ULONGEST *val);
|
||||||
|
|
||||||
|
ULONGEST regcache_raw_get_unsigned (struct regcache *regcache,
|
||||||
|
int regnum);
|
||||||
|
|
||||||
extern void regcache_raw_write_signed (struct regcache *regcache,
|
extern void regcache_raw_write_signed (struct regcache *regcache,
|
||||||
int regnum, LONGEST val);
|
int regnum, LONGEST val);
|
||||||
extern void regcache_raw_write_unsigned (struct regcache *regcache,
|
extern void regcache_raw_write_unsigned (struct regcache *regcache,
|
||||||
|
Loading…
Reference in New Issue
Block a user