Unwinding doesn't work on recent ARM kernels since after the following commit the kernel doesn't perform the prel31_to_addr() conversion of the offsets in the index table. The leads to crash not finding the correct unwind instructions. http://git.kernel.org/linus/de66a979012dbc66b1ec0125795a3f79ee667b8a The patch below makes crash do the conversion itself if necessary. Rabin diff --git a/unwind_arm.c b/unwind_arm.c index d86ec63..e804cfb 100644 --- a/unwind_arm.c +++ b/unwind_arm.c @@ -71,6 +71,8 @@ struct unwind_table { static struct unwind_table *kernel_unwind_table; static struct unwind_table *module_unwind_tables; +static int index_in_prel31; + struct unwind_ctrl_block { ulong vrs[16]; ulong insn; @@ -104,6 +106,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 +190,8 @@ init_kernel_unwind_table(void) goto fail; } + index_in_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 +199,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 (index_in_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 +268,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 (index_in_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 +582,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) { -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility