* arm-tdep.c (cleanup_branch): Set a correct return address in
authorYao Qi <yao@codesourcery.com>
Thu, 7 Apr 2011 03:42:51 +0000 (03:42 +0000)
committerYao Qi <yao@codesourcery.com>
Thu, 7 Apr 2011 03:42:51 +0000 (03:42 +0000)
LR for ARM and Thumb.

gdb/ChangeLog
gdb/arm-tdep.c

index 349e47e155dac551d1d6d0a147dfd03ccf480165..42b8b93f241695d1e17ba9537832993f6af0b742 100644 (file)
@@ -1,3 +1,8 @@
+2011-04-07  Yao Qi  <yao@codesourcery.com>
+
+       * arm-tdep.c (cleanup_branch): Set a correct return address in
+       LR for ARM and Thumb.
+
 2011-04-06  Jan Kratochvil  <jan.kratochvil@redhat.com>
 
        Code cleanup.
index bb52ad4255e866dea8ae8c70a591e5d047f28a62..024191b9b3bd9422b488749645e73f65d8eda0d8 100644 (file)
@@ -5493,8 +5493,16 @@ cleanup_branch (struct gdbarch *gdbarch, struct regcache *regs,
 
   if (dsc->u.branch.link)
     {
-      ULONGEST pc = displaced_read_reg (regs, dsc, ARM_PC_REGNUM);
-      displaced_write_reg (regs, dsc, ARM_LR_REGNUM, pc - 4, CANNOT_WRITE_PC);
+      /* The value of LR should be the next insn of current one.  In order
+       not to confuse logic hanlding later insn `bx lr', if current insn mode
+       is Thumb, the bit 0 of LR value should be set to 1.  */
+      ULONGEST next_insn_addr = dsc->insn_addr + dsc->insn_size;
+
+      if (dsc->is_thumb)
+       next_insn_addr |= 0x1;
+
+      displaced_write_reg (regs, dsc, ARM_LR_REGNUM, next_insn_addr,
+                          CANNOT_WRITE_PC);
     }
 
   displaced_write_reg (regs, dsc, ARM_PC_REGNUM, dsc->u.branch.dest, write_pc);