[Crash-utility] [PATCH] ARM: dump also userspace registers when backtracing

Dave Anderson anderson at redhat.com
Fri Dec 10 13:20:43 UTC 2010


----- "Mika Westerberg" <ext-mika.1.westerberg at nokia.com> wrote:

> On Wed, Dec 01, 2010 at 11:27:32AM -0500, ext Dave Anderson wrote:
> > 
> > ----- "Mika Westerberg" <ext-mika.1.westerberg at nokia.com> wrote:
> > 
> > > Enhance backtracing code to print out userspace registers in case we
> > > are at syscall entry. Other architectures supported by crash are 
> > > already doing this.
> > > 
> > > Signed-off-by: Mika Westerberg <ext-mika.1.westerberg at nokia.com>
> > > ---
> > > I tested this with both unwind tables and framepointers enabled on
> > > my test vmcores, and also on live system.
> > 
> > Works well on my sample dumpfiles -- queued for the next release.
> 
> Dave,
> 
> I just noticed that there's a bug in this patch - it handles slow
> syscall return path wrong.
> 
> Below is a patch which applies on top of this and fixes the slow
> path also. If you prefer, I can also send you a single patch which
> combines both of the patches.
> 
> Sorry about the mess.

No problem -- the patch applies fine to 5.1.0, and it's queued for
the next release.

Thanks,
  Dave
 
> Regards,
> MW
> 
> diff --git a/arm.c b/arm.c
> index a8a34b9..751fe00 100644
> --- a/arm.c
> +++ b/arm.c
> @@ -31,7 +31,7 @@ static int arm_verify_symbol(const char *, ulong,
> char);
>  static int arm_is_module_addr(ulong);
>  static int arm_is_kvaddr(ulong);
>  static int arm_in_exception_text(ulong);
> -static int arm_in_ret_from_syscall(ulong);
> +static int arm_in_ret_from_syscall(ulong, int *);
>  static void arm_back_trace(struct bt_info *);
>  static void arm_back_trace_cmd(struct bt_info *);
>  static ulong arm_processor_speed(void);
> @@ -669,13 +669,44 @@ arm_in_exception_text(ulong pc)
>  }
>  
>  /*
> - * Returns TRUE if given pc points to a return from syscall
> entrypoint.
> + * Returns TRUE if given pc points to a return from syscall
> + * entrypoint. In case the function returns TRUE and if offset is
> given,
> + * it is filled with the offset that should be added to the SP to
> get
> + * address of the exception frame where the user registers are.
>   */
>  static int
> -arm_in_ret_from_syscall(ulong pc)
> +arm_in_ret_from_syscall(ulong pc, int *offset)
>  {
> -	return (pc == symbol_value("ret_fast_syscall") ||
> -		pc == symbol_value("ret_slow_syscall"));
> +	/*
> +	 * On fast syscall return path, the stack looks like:
> +	 *
> +	 * SP + 0	{r4, r5}
> +	 * SP + 8	user pt_regs
> +	 *
> +	 * The asm syscall handler pushes fifth and sixth registers
> +	 * onto the stack before calling the actual syscall handler.
> +	 *
> +	 * So in order to print out the user registers at the time
> +	 * the syscall was made, we need to adjust SP for 8.
> +	 */
> +	if (pc == symbol_value("ret_fast_syscall")) {
> +		if (offset)
> +			*offset = 8;
> +		return TRUE;
> +	}
> +
> +	/*
> +	 * In case we are on the slow syscall path, the SP already
> +	 * points to the start of the user registers hence no
> +	 * adjustments needs to be done.
> +	 */
> +	if (pc == symbol_value("ret_slow_syscall")) {
> +		if (offset)
> +			*offset = 0;
> +		return TRUE;
> +	}
> +
> +	return FALSE;
>  }
>  
>  /*
> @@ -1178,6 +1209,7 @@ arm_dump_backtrace_entry(struct bt_info *bt, int
> level, ulong from, ulong sp)
>  {
>  	struct load_module *lm;
>  	const char *name;
> +	int offset = 0;
>  
>  	name = closest_symbol(bt->instptr);
>  
> @@ -1201,23 +1233,10 @@ arm_dump_backtrace_entry(struct bt_info *bt,
> int level, ulong from, ulong sp)
>  
>  	if (arm_in_exception_text(bt->instptr)) {
>  		arm_dump_exception_stack(sp, sp + sizeof(struct arm_pt_regs));
> -	} else if (arm_in_ret_from_syscall(from)) {
> -		/*
> -		 * When we are returning from the syscall, here is
> -		 * what the stack frame looks like:
> -		 *
> -		 * SP + 0	{r4, r5}
> -		 * SP + 8	user pt_regs
> -		 *
> -		 * The asm syscall handler pushes fifth and sixth
> -		 * registers onto the stack before calling the
> -		 * actual syscall handler.
> -		 *
> -		 * So in order to print out the user registers when
> -		 * the syscall was made, we need to adjust sp for 8.
> -		 */
> -		arm_dump_exception_stack(sp + 8,
> -					 sp + 8 + sizeof(struct arm_pt_regs));
> +	} else if (arm_in_ret_from_syscall(from, &offset)) {
> +		ulong nsp = sp + offset;
> +
> +		arm_dump_exception_stack(nsp, nsp + sizeof(struct arm_pt_regs));
>  	}
>  
>  	if (bt->flags & BT_FULL) {




More information about the Crash-utility mailing list