[2/3] Apply stub unwinder to 'bx reg' trampoline
Commit Message
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-09 Yao Qi <yao@codesourcery.com>
* arm-tdep.c (arm_skip_bx_reg): Declare.
(arm_stub_unwind_sniffer): Return 1 if arm_skip_bx_reg returns
non-zero.
---
gdb/arm-tdep.c | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
Comments
> 2014-06-09 Yao Qi <yao@codesourcery.com>
>
> * arm-tdep.c (arm_skip_bx_reg): Declare.
> (arm_stub_unwind_sniffer): Return 1 if arm_skip_bx_reg returns
> non-zero.
This is OK as well. As suggested in patch #1, consider moving
arm_skip_bx_reg up to avoid the need for the declaration.
> ---
> gdb/arm-tdep.c | 11 ++++++++++-
> 1 file changed, 10 insertions(+), 1 deletion(-)
>
> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
> index 2430a86..e3f7f0c 100644
> --- a/gdb/arm-tdep.c
> +++ b/gdb/arm-tdep.c
> @@ -2899,6 +2899,8 @@ arm_stub_this_id (struct frame_info *this_frame,
> *this_id = frame_id_build (cache->prev_sp, get_frame_pc (this_frame));
> }
>
> +static CORE_ADDR arm_skip_bx_reg (struct frame_info *frame, CORE_ADDR pc);
> +
> static int
> arm_stub_unwind_sniffer (const struct frame_unwind *self,
> struct frame_info *this_frame,
> @@ -2906,12 +2908,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;
> --
> 1.9.0
@@ -2899,6 +2899,8 @@ arm_stub_this_id (struct frame_info *this_frame,
*this_id = frame_id_build (cache->prev_sp, get_frame_pc (this_frame));
}
+static CORE_ADDR arm_skip_bx_reg (struct frame_info *frame, CORE_ADDR pc);
+
static int
arm_stub_unwind_sniffer (const struct frame_unwind *self,
struct frame_info *this_frame,
@@ -2906,12 +2908,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;