This is the mail archive of the
gdb-patches@sourceware.org
mailing list for the GDB project.
Re: [PATCH 1/3] Skip 'bx reg' trampoline on arm-none-eabi
- From: Joel Brobecker <brobecker at adacore dot com>
- To: Yao Qi <yao at codesourcery dot com>
- Cc: gdb-patches at sourceware dot org
- Date: Mon, 23 Jun 2014 06:17:49 -0700
- Subject: Re: [PATCH 1/3] Skip 'bx reg' trampoline on arm-none-eabi
- Authentication-results: sourceware.org; auth=none
- References: <1402279983-1907-1-git-send-email-yao at codesourcery dot com> <1402279983-1907-2-git-send-email-yao at codesourcery dot com>
> 2014-06-09 Yao Qi <yao@codesourcery.com>
>
> * arm-tdep.c (arm_skip_bx_reg): New function.
> (arm_skip_stub): Call arm_skip_bx_reg.
Sorry about the delay, Yao. This is OK. Perhaps consider the idea
of moving this function up a bit so that you don't have to add an
prototype in patch #2.
> ---
> gdb/arm-tdep.c | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
> 1 file changed, 67 insertions(+), 1 deletion(-)
>
> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
> index 74942b1..2430a86 100644
> --- a/gdb/arm-tdep.c
> +++ b/gdb/arm-tdep.c
> @@ -9214,6 +9214,64 @@ arm_get_longjmp_target (struct frame_info *frame, CORE_ADDR *pc)
> return 1;
> }
>
> +/* Recognize GCC's trampoline for thumb call-indirect. If we are in a
> + trampoline, return the target PC. Otherwise return 0.
> +
> + void call0a (char c, short s, int i, long l) {}
> +
> + int main (void)
> + {
> + (*pointer_to_call0a) (c, s, i, l);
> + }
> +
> + Instead of calling a stub library function _call_via_xx (xx is
> + the register name), GCC may inline the trampoline in the object
> + file as below (register r2 has the address of call0a).
> +
> + .global main
> + .type main, %function
> + ...
> + bl .L1
> + ...
> + .size main, .-main
> +
> + .L1:
> + bx r2
> +
> + The trampoline 'bx r2' doesn't belong to main. */
> +
> +static CORE_ADDR
> +arm_skip_bx_reg (struct frame_info *frame, CORE_ADDR pc)
> +{
> + /* The heuristics of recognizing such trampoline is that FRAME is
> + executing in Thumb mode and the instruction on PC is 'bx Rm'. */
> + if (arm_frame_is_thumb (frame))
> + {
> + gdb_byte buf[2];
> +
> + if (target_read_memory (pc, buf, 2) == 0)
> + {
> + struct gdbarch *gdbarch = get_frame_arch (frame);
> + enum bfd_endian byte_order_for_code
> + = gdbarch_byte_order_for_code (gdbarch);
> + uint16_t insn
> + = extract_unsigned_integer (buf, 2, byte_order_for_code);
> +
> + if ((insn & 0xff80) == 0x4700) /* bx <Rm> */
> + {
> + CORE_ADDR dest
> + = get_frame_register_unsigned (frame, bits (insn, 3, 6));
> +
> + /* Clear the LSB so that gdb core sets step-resume
> + breakpoint at the right address. */
> + return UNMAKE_THUMB_ADDR (dest);
> + }
> + }
> + }
> +
> + return 0;
> +}
> +
> /* Recognize GCC and GNU ld's trampolines. If we are in a trampoline,
> return the target PC. Otherwise return 0. */
>
> @@ -9226,7 +9284,15 @@ arm_skip_stub (struct frame_info *frame, CORE_ADDR pc)
>
> /* Find the starting address and name of the function containing the PC. */
> if (find_pc_partial_function (pc, &name, &start_addr, NULL) == 0)
> - return 0;
> + {
> + /* Trampoline 'bx reg' doesn't belong to any functions. Do the
> + check here. */
> + start_addr = arm_skip_bx_reg (frame, pc);
> + if (start_addr != 0)
> + return start_addr;
> +
> + return 0;
> + }
>
> /* If PC is in a Thumb call or return stub, return the address of the
> target PC, which is in a register. The thunk functions are called
> --
> 1.9.0
--
Joel