----- "Mika Westerberg" <ext-mika.1.westerberg(a)nokia.com> wrote:
 On Wed, Dec 01, 2010 at 11:27:32AM -0500, ext Dave Anderson wrote:
 > 
 > ----- "Mika Westerberg" <ext-mika.1.westerberg(a)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(a)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) {