[arm] Fix fails in gdb.base/disp-step-syscall.exp
authorYao Qi <yao.qi@linaro.org>
Wed, 15 Apr 2015 13:34:03 +0000 (14:34 +0100)
committerYao Qi <yao.qi@linaro.org>
Wed, 15 Apr 2015 14:14:37 +0000 (15:14 +0100)
Hi,
I see this fail on arm-linux target,

 FAIL: gdb.base/disp-step-syscall.exp: fork: single step over fork final pc

which is caused by the PC isn't expected after displaced stepping the
svc instruction.  The code is:

=> 0xb6ead9a4 <__libc_do_syscall+4>:    svc     0
   0xb6ead9a6 <__libc_do_syscall+6>:    pop     {r7, pc}
   0xb6ead9a8:  nop.w^M
   0xb6ead9ac:  nop.w

after single step svc instruction, pc should be 0xb6ead9a6, but the
actual value of pc is 0xb6ead9a8.  The problem is illustrated by
turning on debug message of displaced stepping,

stepi^M
displaced: stepping Thread 12031 now^M
displaced: saved 0x8574: 02 bc 6a 46 04 b4 01 b4 df f8 10 c0 4d f8 04 cd 03 48 04 4b ff f7 d2 ef ff f7 e8 ef 0d 87 00 00 ^M
displaced: process thumb insn df00 at b6ead9a4^M
displaced: copying svc insn df00^M
displaced: read r7 value 00000078^M
displaced: sigreturn/rt_sigreturn SVC call not in signal trampoline frame^M
displaced: writing insn df00 at 00008574^M
displaced: copy 0xb6ead9a4->0x8574: displaced: check mode of b6ead9a4 instead of 00008574^M
displaced: displaced pc to 0x8574^M
displaced: run 0x8574: 00 df 01 de ^M
displaced: restored Thread 12031 0x8574^M
displaced: PC is apparently 00008576 after SVC step (within scratch space)^M
displaced: writing pc b6ead9a8  <----- WRONG ADDRESS

GDB writes the wrong address back to pc because GDB thinks the
instruction size is 4, which isn't true for thumb instruction.
This patch is to replace 4 with dsc->insn_size.

gdb:

2015-04-15  Yao Qi  <yao.qi@linaro.org>

* arm-linux-tdep.c (arm_linux_cleanup_svc): Use
dsc->insn_size instead of 4.

gdb/ChangeLog
gdb/arm-linux-tdep.c

index acb408b7e053773433f1c172a35494b1a4be4ef9..a97e720203ddb35f0ea6cbac94a47c1c1077dee8 100644 (file)
@@ -1,3 +1,8 @@
+2015-04-15  Yao Qi  <yao.qi@linaro.org>
+
+       * arm-linux-tdep.c (arm_linux_cleanup_svc): Use
+       dsc->insn_size instead of 4.
+
 2015-04-14  Gary Benson <gbenson@redhat.com>
 
        * jit.c (mem_bfd_iovec_stat): Zero supplied buffer.
index f58da846e65250599e428e977102e4802cd9d0ec..60266b52f875a19eb97d3e823d61e3ddd646113f 100644 (file)
@@ -939,7 +939,6 @@ arm_linux_cleanup_svc (struct gdbarch *gdbarch,
                       struct regcache *regs,
                       struct displaced_step_closure *dsc)
 {
-  CORE_ADDR from = dsc->insn_addr;
   ULONGEST apparent_pc;
   int within_scratch;
 
@@ -960,7 +959,8 @@ arm_linux_cleanup_svc (struct gdbarch *gdbarch,
     }
 
   if (within_scratch)
-    displaced_write_reg (regs, dsc, ARM_PC_REGNUM, from + 4, BRANCH_WRITE_PC);
+    displaced_write_reg (regs, dsc, ARM_PC_REGNUM,
+                        dsc->insn_addr + dsc->insn_size, BRANCH_WRITE_PC);
 }
 
 static int
@@ -1027,7 +1027,7 @@ arm_linux_copy_svc (struct gdbarch *gdbarch, struct regcache *regs,
   /* Preparation: If we detect sigreturn, set momentary breakpoint at resume
                  location, else nothing.
      Insn: unmodified svc.
-     Cleanup: if pc lands in scratch space, pc <- insn_addr + 4
+     Cleanup: if pc lands in scratch space, pc <- insn_addr + insn_size
               else leave pc alone.  */