This value is used to mask the PAC bits and generate correct backtrace and symbol name. (amit.kachhap@xxxxxxx) --- Changes since v1: * Moved PAC mask code from arm64_print_stackframe_entry to arm64_unwind_frame. * PAC mask check on all kernel text during complete stack parsing with bt -t <pid> command. * dump_machdep_table now prints CONFIG_ARM64_KERNELPACMASK. The kernel version for the corresponding vmcoreinfo entry is posted here[1]. [1]: https://lore.kernel.org/patchwork/patch/1211981/ arm64.c | 52 ++++++++++++++++++++++++++++++++++++++++++---------- defs.h | 1 + 2 files changed, 43 insertions(+), 10 deletions(-) diff --git a/arm64.c b/arm64.c index 7662d71..326b8e0 100644 --- a/arm64.c +++ b/arm64.c @@ -84,6 +84,7 @@ static int arm64_get_kvaddr_ranges(struct vaddr_range *); static void arm64_get_crash_notes(void); static void arm64_calc_VA_BITS(void); static int arm64_is_uvaddr(ulong, struct task_context *); +static void arm64_calc_KERNELPACMASK(void); /* @@ -213,6 +214,7 @@ arm64_init(int when) machdep->pagemask = ~((ulonglong)machdep->pageoffset); arm64_calc_VA_BITS(); + arm64_calc_KERNELPACMASK(); ms = machdep->machspec; if (ms->VA_BITS_ACTUAL) { ms->page_offset = ARM64_PAGE_OFFSET_ACTUAL; @@ -472,6 +474,7 @@ arm64_init(int when) case LOG_ONLY: machdep->machspec = &arm64_machine_specific; arm64_calc_VA_BITS(); + arm64_calc_KERNELPACMASK(); arm64_calc_phys_offset(); machdep->machspec->page_offset = ARM64_PAGE_OFFSET; break; @@ -659,6 +662,11 @@ arm64_dump_machdep_table(ulong arg) fprintf(fp, "%ld\n", ms->VA_BITS_ACTUAL); else fprintf(fp, "(unused)\n"); + fprintf(fp, "CONFIG_ARM64_KERNELPACMASK: "); + if (ms->CONFIG_ARM64_KERNELPACMASK) + fprintf(fp, "%lx\n", ms->CONFIG_ARM64_KERNELPACMASK); + else + fprintf(fp, "(unused)\n"); fprintf(fp, " userspace_top: %016lx\n", ms->userspace_top); fprintf(fp, " page_offset: %016lx\n", ms->page_offset); fprintf(fp, " vmalloc_start_addr: %016lx\n", ms->vmalloc_start_addr); @@ -1774,13 +1782,14 @@ static int arm64_is_kernel_exception_frame(struct bt_info *bt, ulong stkptr) { struct arm64_pt_regs *regs; + struct machine_specific *ms = machdep->machspec; regs = (struct arm64_pt_regs *)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(stkptr))]; if (INSTACK(regs->sp, bt) && INSTACK(regs->regs[29], bt) && !(regs->pstate & (0xffffffff00000000ULL | PSR_MODE32_BIT)) && - is_kernel_text(regs->pc) && - is_kernel_text(regs->regs[30])) { + is_kernel_text(regs->pc | ms->CONFIG_ARM64_KERNELPACMASK) && + is_kernel_text(regs->regs[30] | ms->CONFIG_ARM64_KERNELPACMASK)) { switch (regs->pstate & PSR_MODE_MASK) { case PSR_MODE_EL1t: @@ -1924,6 +1933,7 @@ arm64_print_stackframe_entry(struct bt_info *bt, int level, struct arm64_stackfr * See, for example, "bl schedule" before ret_to_user(). */ branch_pc = frame->pc - 4; + name = closest_symbol(branch_pc); name_plus_offset = NULL; @@ -2135,7 +2145,7 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame) unsigned long stack_mask; unsigned long irq_stack_ptr, orig_sp; struct arm64_pt_regs *ptregs; - struct machine_specific *ms; + struct machine_specific *ms = machdep->machspec; stack_mask = (unsigned long)(ARM64_STACK_SIZE) - 1; fp = frame->fp; @@ -2149,6 +2159,8 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame) frame->sp = fp + 0x10; frame->fp = GET_STACK_ULONG(fp); frame->pc = GET_STACK_ULONG(fp + 8); + if (is_kernel_text(frame->pc | ms->CONFIG_ARM64_KERNELPACMASK)) + frame->pc |= ms->CONFIG_ARM64_KERNELPACMASK; if ((frame->fp == 0) && (frame->pc == 0)) return FALSE; @@ -2200,7 +2212,6 @@ arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame) * irq_stack_ptr = IRQ_STACK_PTR(raw_smp_processor_id()); * orig_sp = IRQ_STACK_TO_TASK_STACK(irq_stack_ptr); (pt_regs pointer on process stack) */ - ms = machdep->machspec; irq_stack_ptr = ms->irq_stacks[bt->tc->processor] + ms->irq_stack_size - 16; if (frame->sp == irq_stack_ptr) { @@ -2802,6 +2813,8 @@ arm64_print_text_symbols(struct bt_info *bt, struct arm64_stackframe *frame, FIL char buf2[BUFSIZE]; char *name; ulong start; + ulong val; + struct machine_specific *ms = machdep->machspec; if (bt->flags & BT_TEXT_SYMBOLS_ALL) start = bt->stackbase; @@ -2816,8 +2829,10 @@ arm64_print_text_symbols(struct bt_info *bt, struct arm64_stackframe *frame, FIL for (i = (start - bt->stackbase)/sizeof(ulong); i < LONGS_PER_STACK; i++) { up = (ulong *)(&bt->stackbuf[i*sizeof(ulong)]); - if (is_kernel_text(*up)) { - name = closest_symbol(*up); + val = *up; + if (is_kernel_text(val | ms->CONFIG_ARM64_KERNELPACMASK)) { + val |= ms->CONFIG_ARM64_KERNELPACMASK; + name = closest_symbol(val); fprintf(ofp, " %s[%s] %s at %lx", bt->flags & BT_ERROR_MASK ? " " : "", @@ -2826,13 +2841,13 @@ arm64_print_text_symbols(struct bt_info *bt, struct arm64_stackframe *frame, FIL MKSTR(bt->stackbase + (i * sizeof(long)))), bt->flags & BT_SYMBOL_OFFSET ? - value_to_symstr(*up, buf2, bt->radix) : - name, *up); - if (module_symbol(*up, NULL, &lm, NULL, 0)) + value_to_symstr(val, buf2, bt->radix) : + name, val); + if (module_symbol(val, NULL, &lm, NULL, 0)) fprintf(ofp, " [%s]", lm->mod_name); fprintf(ofp, "\n"); if (BT_REFERENCE_CHECK(bt)) - arm64_do_bt_reference_check(bt, *up, name); + arm64_do_bt_reference_check(bt, val, name); } } } @@ -3135,6 +3150,7 @@ arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int mode, FILE *o struct syment *sp; ulong LR, SP, offset; char buf[BUFSIZE]; + struct machine_specific *ms = machdep->machspec; if (CRASHDEBUG(1)) fprintf(ofp, "pt_regs: %lx\n", pt_regs); @@ -3150,6 +3166,8 @@ arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int mode, FILE *o rows = 4; } else { LR = regs->regs[30]; + if (is_kernel_text (LR | ms->CONFIG_ARM64_KERNELPACMASK)) + LR |= ms->CONFIG_ARM64_KERNELPACMASK; SP = regs->sp; top_reg = 29; is_64_bit = TRUE; @@ -4058,6 +4076,20 @@ arm64_swp_offset(ulong pte) return pte; } +static void arm64_calc_KERNELPACMASK(void) +{ + ulong value; + char *string; + + if ((string = pc->read_vmcoreinfo("NUMBER(KERNELPACMASK)"))) { + value = htol(string, QUIET, NULL); + free(string); + machdep->machspec->CONFIG_ARM64_KERNELPACMASK = value; + if (CRASHDEBUG(1)) + fprintf(fp, "CONFIG_ARM64_KERNELPACMASK=%lx\n", value); + } +} + #endif /* ARM64 */ diff --git a/defs.h b/defs.h index ac24a5d..4c3e509 100644 --- a/defs.h +++ b/defs.h @@ -3263,6 +3263,7 @@ struct machine_specific { ulong machine_kexec_end; ulong VA_BITS_ACTUAL; ulong CONFIG_ARM64_VA_BITS; + ulong CONFIG_ARM64_KERNELPACMASK; ulong VA_START; }; -- 2.17.1 -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility