diff options
-rw-r--r-- | gdb/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/arm-linux-tdep.c | 18 | ||||
-rw-r--r-- | gdb/gdbserver/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/gdbserver/linux-arm-low.c | 16 |
4 files changed, 42 insertions, 6 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 705c2e1..0f0078b 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,10 @@ +2016-01-21 Yao Qi <yao.qi@linaro.org> + + * arm-linux-tdep.c (arm_linux_sigreturn_next_pc): Add parameter + is_thumb and set it according to CPSR saved on the stack. + (arm_linux_get_next_pcs_syscall_next_pc): Pass is_thumb to + arm_linux_sigreturn_next_pc. + 2016-01-20 Simon Marchi <simon.marchi@polymtl.ca> * python/lib/gdb/printing.py (FlagEnumerationPrinter.__call__): diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c index 2306bda..f6a831a 100644 --- a/gdb/arm-linux-tdep.c +++ b/gdb/arm-linux-tdep.c @@ -782,10 +782,12 @@ arm_linux_sigreturn_return_addr (struct frame_info *frame, } /* Find the value of the next PC after a sigreturn or rt_sigreturn syscall - based on current processor state. */ + based on current processor state. In addition, set IS_THUMB depending + on whether we will return to ARM or Thumb code. */ + static CORE_ADDR arm_linux_sigreturn_next_pc (struct regcache *regcache, - unsigned long svc_number) + unsigned long svc_number, int *is_thumb) { ULONGEST sp; unsigned long sp_data; @@ -794,6 +796,7 @@ arm_linux_sigreturn_next_pc (struct regcache *regcache, enum bfd_endian byte_order = gdbarch_byte_order (gdbarch); int pc_offset = 0; int is_sigreturn = 0; + CORE_ADDR cpsr; gdb_assert (svc_number == ARM_SIGRETURN || svc_number == ARM_RT_SIGRETURN); @@ -807,6 +810,10 @@ arm_linux_sigreturn_next_pc (struct regcache *regcache, next_pc = read_memory_unsigned_integer (sp + pc_offset, 4, byte_order); + /* Set IS_THUMB according the CPSR saved on the stack. */ + cpsr = read_memory_unsigned_integer (sp + pc_offset + 4, 4, byte_order); + *is_thumb = ((cpsr & arm_psr_thumb_bit (gdbarch)) != 0); + return next_pc; } @@ -899,7 +906,12 @@ arm_linux_get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self, } if (svc_number == ARM_SIGRETURN || svc_number == ARM_RT_SIGRETURN) - next_pc = arm_linux_sigreturn_next_pc (self->regcache, svc_number); + { + /* SIGRETURN or RT_SIGRETURN may affect the arm thumb mode, so + update IS_THUMB. */ + next_pc = arm_linux_sigreturn_next_pc (self->regcache, svc_number, + &is_thumb); + } /* Addresses for calling Thumb functions have the bit 0 set. */ if (is_thumb) diff --git a/gdb/gdbserver/ChangeLog b/gdb/gdbserver/ChangeLog index 4eb92db..c33c5d3 100644 --- a/gdb/gdbserver/ChangeLog +++ b/gdb/gdbserver/ChangeLog @@ -1,3 +1,10 @@ +2016-01-21 Yao Qi <yao.qi@linaro.org> + + * linux-arm-low.c (arm_sigreturn_next_pc): Add parameter + is_thumb and set it according to CPSR saved on the stack. + (get_next_pcs_syscall_next_pc): Pass is_thumb to + arm_sigreturn_next_pc. + 2016-01-18 Yao Qi <yao.qi@linaro.org> * linux-low.c (linux_set_pc_64bit): New function. diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c index 57cb855..c4f43bb 100644 --- a/gdb/gdbserver/linux-arm-low.c +++ b/gdb/gdbserver/linux-arm-low.c @@ -750,16 +750,20 @@ arm_prepare_to_resume (struct lwp_info *lwp) } } -/* Find the next pc for a sigreturn or rt_sigreturn syscall. +/* Find the next pc for a sigreturn or rt_sigreturn syscall. In + addition, set IS_THUMB depending on whether we will return to ARM + or Thumb code. See arm-linux.h for stack layout details. */ static CORE_ADDR -arm_sigreturn_next_pc (struct regcache *regcache, int svc_number) +arm_sigreturn_next_pc (struct regcache *regcache, int svc_number, + int *is_thumb) { unsigned long sp; unsigned long sp_data; /* Offset of PC register. */ int pc_offset = 0; CORE_ADDR next_pc = 0; + CORE_ADDR cpsr; gdb_assert (svc_number == __NR_sigreturn || svc_number == __NR_rt_sigreturn); @@ -771,6 +775,10 @@ arm_sigreturn_next_pc (struct regcache *regcache, int svc_number) (*the_target->read_memory) (sp + pc_offset, (unsigned char *) &next_pc, 4); + /* Set IS_THUMB according the CPSR saved on the stack. */ + (*the_target->read_memory) (sp + pc_offset + 4, (unsigned char *) &cpsr, 4); + *is_thumb = ((cpsr & CPSR_T) != 0); + return next_pc; } @@ -812,7 +820,9 @@ get_next_pcs_syscall_next_pc (struct arm_get_next_pcs *self, CORE_ADDR pc) /* This is a sigreturn or sigreturn_rt syscall. */ if (svc_number == __NR_sigreturn || svc_number == __NR_rt_sigreturn) { - next_pc = arm_sigreturn_next_pc (regcache, svc_number); + /* SIGRETURN or RT_SIGRETURN may affect the arm thumb mode, so + update IS_THUMB. */ + next_pc = arm_sigreturn_next_pc (regcache, svc_number, &is_thumb); } /* Addresses for calling Thumb functions have the bit 0 set. */ |