[v8,3/7] Refactor arm_software_single_step to use regcache
Commit Message
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
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 <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.
@@ -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)
@@ -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. */