This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH 1/3] Skip 'bx reg' trampoline on arm-none-eabi


> 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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]