[v8,3/7] Refactor arm_software_single_step to use regcache

Message ID 86h9ibt4sg.fsf@gmail.com
State New, archived
Headers

Commit Message

Yao Qi Jan. 18, 2016, 1:07 p.m. UTC
  Yao Qi <qiyaoltc@gmail.com> writes:

> As a record, this patch causes regressions at least in
> gdb.base/sigstep.exp,
>
> (gdb) PASS: gdb.base/sigstep.exp: continue to handler, si+advance in
> handler, step from handler: advance in handler
> step^M
> 39      } /* handler */^M
> 1: x/i $pc^M
> => 0x8740 <handler+80>: sub     sp, r11, #0^M
> (gdb) step^M
> ^M
> Program received signal SIGSEGV, Segmentation fault.^M
> setitimer () at ../sysdeps/unix/syscall-template.S:81^M
> 81      ../sysdeps/unix/syscall-template.S: No such file or directory.^M
> 1: x/i $pc^M
> => 0xb6eff9c0 <setitimer>:      push    {r7}^M
> (gdb) FAIL: gdb.base/sigstep.exp: continue to handler, si+advance in
> handler, step from handler: leave handler
>
> Could you take a look at it?

Here is my patch fixing the regression in sigstep.exp.  The regression
test is running now.
  

Comments

Antoine Tremblay Jan. 18, 2016, 2:02 p.m. UTC | #1
On 01/18/2016 08:07 AM, Yao Qi wrote:
> Yao Qi <qiyaoltc@gmail.com> writes:
>
>> As a record, this patch causes regressions at least in
>> gdb.base/sigstep.exp,
>>
>> (gdb) PASS: gdb.base/sigstep.exp: continue to handler, si+advance in
>> handler, step from handler: advance in handler
>> step^M
>> 39      } /* handler */^M
>> 1: x/i $pc^M
>> => 0x8740 <handler+80>: sub     sp, r11, #0^M
>> (gdb) step^M
>> ^M
>> Program received signal SIGSEGV, Segmentation fault.^M
>> setitimer () at ../sysdeps/unix/syscall-template.S:81^M
>> 81      ../sysdeps/unix/syscall-template.S: No such file or directory.^M
>> 1: x/i $pc^M
>> => 0xb6eff9c0 <setitimer>:      push    {r7}^M
>> (gdb) FAIL: gdb.base/sigstep.exp: continue to handler, si+advance in
>> handler, step from handler: leave handler
>>
>> Could you take a look at it?
>
> Here is my patch fixing the regression in sigstep.exp.  The regression
> test is running now.
>

You've beat me to it, thanks for the fix !

Patch LGTM.

Regards,
Antoine
  
Yao Qi Jan. 21, 2016, 7:52 a.m. UTC | #2
Yao Qi <qiyaoltc@gmail.com> writes:

> Here is my patch fixing the regression in sigstep.exp.  The regression
> test is running now.

Regression tests are done.  Patch is pushed in.
  

Patch

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/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c
index 927a6fa..01a3bc0 100644
--- a/gdb/gdbserver/linux-arm-low.c
+++ b/gdb/gdbserver/linux-arm-low.c
@@ -769,16 +769,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);
 
@@ -790,6 +794,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;
 }
 
@@ -831,7 +839,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.  */