[Crash-utility] [PATCH] ARM: fix unwinding on recent kernels

Dave Anderson anderson at redhat.com
Tue Feb 14 14:44:11 UTC 2012



----- Original Message -----
> On Mon, Feb 13, 2012 at 11:59:04AM -0500, Dave Anderson wrote:
> > > Maybe add some comment explaining why we do this check (a reference to the
> > > kernel commit perhaps)?
> > 
> > I agree about the comment -- and then some...
> > 
> > This seems to be a fairly signficant piece of information to be hidden
> > in a static variable:
> > 
> > +static int index_in_prel31;
> > 
> > Can you put it in the ARM machine_specific data structure?  And then
> > display it in arm_dump_machdep_table() for "help -m".
> 
> Here's a v2 of the patch.
> 
> Rabin

Nice -- queued for crash-6.0.4.

Thanks,
  Dave

 
> diff --git a/arm.c b/arm.c
> index 4ca2fcd..4be224e 100644
> --- a/arm.c
> +++ b/arm.c
> @@ -406,6 +406,7 @@ arm_dump_machdep_table(ulong arg)
>  	fprintf(fp, "exception_text_start: %lx\n",
>  	ms->exception_text_start);
>  	fprintf(fp, " exception_text_end: %lx\n", ms->exception_text_end);
>  	fprintf(fp, "    crash_task_regs: %lx\n",
>  	(ulong)ms->crash_task_regs);
> +	fprintf(fp, "unwind_index_prel31: %d\n", ms->unwind_index_prel31);
>  }
>  
>  /*
> diff --git a/defs.h b/defs.h
> index 82d51e5..2e7f6bd 100755
> --- a/defs.h
> +++ b/defs.h
> @@ -4241,6 +4241,7 @@ struct machine_specific {
>  	ulong exception_text_start;
>  	ulong exception_text_end;
>  	struct arm_pt_regs *crash_task_regs;
> +	int unwind_index_prel31;
>  };
>  
>  int init_unwind_tables(void);
> diff --git a/unwind_arm.c b/unwind_arm.c
> index d86ec63..640d6c9 100644
> --- a/unwind_arm.c
> +++ b/unwind_arm.c
> @@ -104,6 +104,7 @@ static int is_core_kernel_text(ulong);
>  static struct unwind_table *search_table(ulong);
>  static struct unwind_idx *search_index(const struct unwind_table *,
>  ulong);
>  static ulong prel31_to_addr(ulong, ulong);
> +static void index_prel31_to_addr(struct unwind_table *);
>  static int unwind_frame(struct stackframe *, ulong);
>  
>  /*
> @@ -187,6 +188,19 @@ init_kernel_unwind_table(void)
>  		goto fail;
>  	}
>  
> +	/*
> +	 * Kernel versions before v3.2 (specifically, before commit
> +	 * de66a979012db "ARM: 7187/1: fix unwinding for XIP kernels")
> +	 * converted the prel31 offsets in the unwind index table to absolute
> +	 * addresses on startup.  Newer kernels don't perform this conversion,
> +	 * and have a slightly more involved search algorithm.
> +	 *
> +	 * We always just use the older search method (a straightforward binary
> +	 * search) and convert the index table offsets ourselves if we detect
> +	 * that the kernel didn't do it.
> +	 */
> +	machdep->machspec->unwind_index_prel31 = !is_kernel_text(kernel_unwind_table->idx[0].addr);
> +
>  	kernel_unwind_table->start = kernel_unwind_table->idx;
>  	kernel_unwind_table->end = (struct unwind_idx *)
>  		((char *)kernel_unwind_table->idx + idx_size);
> @@ -194,6 +208,9 @@ init_kernel_unwind_table(void)
>  	kernel_unwind_table->end_addr = (kernel_unwind_table->end - 1)->addr;
>  	kernel_unwind_table->kv_base = idx_start;
>  
> +	if (machdep->machspec->unwind_index_prel31)
> +		index_prel31_to_addr(kernel_unwind_table);
> +
>  	if (CRASHDEBUG(1)) {
>  		fprintf(fp, "UNWIND: master kernel table start\n");
>  		fprintf(fp, "UNWIND: size      : %ld\n", idx_size);
> @@ -260,6 +277,9 @@ read_module_unwind_table(struct unwind_table *tbl, ulong addr)
>  	tbl->end_addr = TABLE_VALUE(buf, unwind_table_end_addr);
>  	tbl->kv_base = idx_start;
>  
> +	if (machdep->machspec->unwind_index_prel31)
> +		index_prel31_to_addr(tbl);
> +
>  	if (CRASHDEBUG(1)) {
>  		fprintf(fp, "UNWIND: module table start\n");
>  		fprintf(fp, "UNWIND: start     : %p\n", tbl->start);
> @@ -571,6 +591,16 @@ prel31_to_addr(ulong addr, ulong insn)
>  	return addr + offset;
>  }
>  
> +static void
> +index_prel31_to_addr(struct unwind_table *tbl)
> +{
> +	struct unwind_idx *idx = tbl->start;
> +	ulong kvaddr = tbl->kv_base;
> +
> +	for (; idx < tbl->end; idx++, kvaddr += sizeof(struct unwind_idx))
> +		idx->addr = prel31_to_addr(kvaddr, idx->addr);
> +}
> +
>  static int
>  unwind_frame(struct stackframe *frame, ulong stacktop)
>  {




More information about the Crash-utility mailing list