summaryrefslogtreecommitdiff
path: root/gdb/arm-linux-tdep.c
diff options
context:
space:
mode:
authorUlrich Weigand <uweigand@de.ibm.com>2011-04-01 11:57:00 +0000
committerUlrich Weigand <uweigand@de.ibm.com>2011-04-01 11:57:00 +0000
commita0a832c9e97e681a6bdd4bc03fa2b6cfe902b8ad (patch)
tree3240ecee37d1ed3225fa13f508792790fa4cb695 /gdb/arm-linux-tdep.c
parenteb706c8f92aa03ae30f09cb6a3007694c3cb466a (diff)
downloadgdb-a0a832c9e97e681a6bdd4bc03fa2b6cfe902b8ad.tar.gz
gdb/
* arm-tdep.h (arm_insert_single_step_breakpoint): Add prototype. * arm-tdep.c (arm_override_mode): New global. (arm_pc_is_thumb): Respect arm_override_mode. Remove single-step execution mode heuristics. (thumb_get_next_pc_raw): Remove INSERT_BKTP argument; always insert second single-step breakpoint if needed, using arm_insert_single_step_breakpoint. (arm_get_next_pc_raw): Remove INSERT_BKTP argument. Only handle ARM execution mode, do not call thumb_get_next_pc_raw. (arm_get_next_pc): Encode execution mode in return value. Call either arm_get_next_pc_raw or thumb_get_next_pc_raw. (arm_insert_single_step_breakpoint): New function. (arm_software_single_step): Call it. * arm-linux-tdep.c (arm_linux_sigreturn_return_addr): Add IS_THUMB argument to return execution mode of sigreturn target. (arm_linux_syscall_next_pc): Use it. (arm_linux_copy_svc): Update call. (arm_linux_software_single_step): Call arm_insert_single_step_breakpoint. gdb/testsuite/ * gdb.arch/thumb-singlestep.S: New file. * gdb.arch/thumb-singlestep.exp: Likewise.
Diffstat (limited to 'gdb/arm-linux-tdep.c')
-rw-r--r--gdb/arm-linux-tdep.c38
1 files changed, 18 insertions, 20 deletions
diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c
index 2f3109c15e7..9db125eecfb 100644
--- a/gdb/arm-linux-tdep.c
+++ b/gdb/arm-linux-tdep.c
@@ -669,18 +669,24 @@ arm_linux_regset_from_core_section (struct gdbarch *gdbarch,
}
/* Copy the value of next pc of sigreturn and rt_sigrturn into PC,
- and return 1. Return 0 if it is not a rt_sigreturn/sigreturn
- syscall. */
+ return 1. In addition, set IS_THUMB depending on whether we
+ will return to ARM or Thumb code. Return 0 if it is not a
+ rt_sigreturn/sigreturn syscall. */
static int
arm_linux_sigreturn_return_addr (struct frame_info *frame,
unsigned long svc_number,
- CORE_ADDR *pc)
+ CORE_ADDR *pc, int *is_thumb)
{
/* Is this a sigreturn or rt_sigreturn syscall? */
if (svc_number == 119 || svc_number == 173)
{
if (get_frame_type (frame) == SIGTRAMP_FRAME)
{
+ ULONGEST t_bit = arm_psr_thumb_bit (frame_unwind_arch (frame));
+ CORE_ADDR cpsr
+ = frame_unwind_register_unsigned (frame, ARM_PS_REGNUM);
+
+ *is_thumb = (cpsr & t_bit) != 0;
*pc = frame_unwind_caller_pc (frame);
return 1;
}
@@ -698,11 +704,11 @@ arm_linux_syscall_next_pc (struct frame_info *frame)
CORE_ADDR return_addr = 0;
int is_thumb = arm_frame_is_thumb (frame);
ULONGEST svc_number = 0;
- int is_sigreturn = 0;
if (is_thumb)
{
svc_number = get_frame_register_unsigned (frame, 7);
+ return_addr = pc + 2;
}
else
{
@@ -721,24 +727,15 @@ arm_linux_syscall_next_pc (struct frame_info *frame)
{
svc_number = get_frame_register_unsigned (frame, 7);
}
+
+ return_addr = pc + 4;
}
- is_sigreturn = arm_linux_sigreturn_return_addr (frame, svc_number,
- &return_addr);
+ arm_linux_sigreturn_return_addr (frame, svc_number, &return_addr, &is_thumb);
- if (is_sigreturn)
- return return_addr;
-
+ /* Addresses for calling Thumb functions have the bit 0 set. */
if (is_thumb)
- {
- return_addr = pc + 2;
- /* Addresses for calling Thumb functions have the bit 0 set. */
- return_addr |= 1;
- }
- else
- {
- return_addr = pc + 4;
- }
+ return_addr |= 1;
return return_addr;
}
@@ -761,7 +758,7 @@ arm_linux_software_single_step (struct frame_info *frame)
if (next_pc > 0xffff0000)
next_pc = get_frame_register_unsigned (frame, ARM_LR_REGNUM);
- insert_single_step_breakpoint (gdbarch, aspace, next_pc);
+ arm_insert_single_step_breakpoint (gdbarch, aspace, next_pc);
return 1;
}
@@ -806,6 +803,7 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
struct frame_info *frame;
unsigned int svc_number = displaced_read_reg (regs, dsc, 7);
int is_sigreturn = 0;
+ int is_thumb;
if (debug_displaced)
fprintf_unfiltered (gdb_stdlog, "displaced: copying Linux svc insn %.8lx\n",
@@ -814,7 +812,7 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, uint32_t insn, CORE_ADDR to,
frame = get_current_frame ();
is_sigreturn = arm_linux_sigreturn_return_addr(frame, svc_number,
- &return_to);
+ &return_to, &is_thumb);
if (is_sigreturn)
{
struct symtab_and_line sal;