Apply stub unwinder to 'bx reg' trampoline
authorYao Qi <yao@codesourcery.com>
Fri, 30 May 2014 08:06:32 +0000 (16:06 +0800)
committerYao Qi <yao@codesourcery.com>
Tue, 24 Jun 2014 01:30:29 +0000 (09:30 +0800)
In target arm-none-eabi, prologue unwinder is used for trampoline
'bx reg'.  However, in target arm-linux, exidx unwinder is selected for
trampoline at first, which is not expected.  The main function and the
trampoline is,

   0x00009dfc <main+0>: push    {r4, r5, r6, r7, lr}
   ......
   0x0000ac30 <main+3636>:      ldrdeq  r3, [r1], -r8
   0x0000ac34:  bx      r2
   0x0000ac36:  bx      r4

and .ARM.exidx is:

0x9dfc <main>: @0xb404
  Compact model index: 1
  0x97      vsp = r7
  0x20      vsp = vsp + 132
  0x3f      vsp = vsp + 256
  0x80 0xf0 pop {r8, r9, r10, r11}
  0xab      pop {r4, r5, r6, r7, r14}

0xac38 <__aeabi_drsub>: 0x1 [cantunwind]

Trampolines 'bx r2' and 'bx r4' doesn't belong to main, but the exidx
for main is still selected form them because there is no end address
of each exidx entry.

Instead of teaching exidx unwinder ignore this trampoline (which looks
complicated and error prone), I decide to let stub unwinder to handle
trampoline, because stub undwinder is installed before exidx unwinder,
and this trampoline can be regarded as a stub too.

This patch is to add the code to match 'bx reg' trampoline in the
sniffer of stub unwinder.

gdb:

2014-06-24  Yao Qi  <yao@codesourcery.com>

* arm-tdep.c (arm_stub_unwind_sniffer): Return 1 if
arm_skip_bx_reg returns non-zero.

gdb/ChangeLog
gdb/arm-tdep.c

index bc81f4f1bc6cac55620923e12a1931711de206ae..19a66576af112dc52b1cd22c3529e31f39fe12a3 100644 (file)
@@ -1,3 +1,8 @@
+2014-06-24  Yao Qi  <yao@codesourcery.com>
+
+       * arm-tdep.c (arm_stub_unwind_sniffer): Return 1 if
+       arm_skip_bx_reg returns non-zero.
+
 2014-06-24  Yao Qi  <yao@codesourcery.com>
 
        * arm-tdep.c (arm_skip_bx_reg): New function.
index eabca4ce10da6d35806435f7f5be62196ff3c553..8cc60a4bb1322115c2fea803689fe3cc7f9e1286 100644 (file)
@@ -2964,12 +2964,19 @@ arm_stub_unwind_sniffer (const struct frame_unwind *self,
 {
   CORE_ADDR addr_in_block;
   gdb_byte dummy[4];
+  CORE_ADDR pc, start_addr;
+  const char *name;
 
   addr_in_block = get_frame_address_in_block (this_frame);
+  pc = get_frame_pc (this_frame);
   if (in_plt_section (addr_in_block)
       /* We also use the stub winder if the target memory is unreadable
         to avoid having the prologue unwinder trying to read it.  */
-      || target_read_memory (get_frame_pc (this_frame), dummy, 4) != 0)
+      || target_read_memory (pc, dummy, 4) != 0)
+    return 1;
+
+  if (find_pc_partial_function (pc, &name, &start_addr, NULL) == 0
+      && arm_skip_bx_reg (this_frame, pc) != 0)
     return 1;
 
   return 0;