On Tue, Jun 21, 2016 at 04:52:32PM -0400, Dave Anderson wrote: > > > Dave, > > > > This patch addresses all the issues that I mentioned in [1], and > > re-factored arm64_back_trace_cmd() to make it simpler, while > > arm64_unwind_frame() gets a bit complicated. But those changes, > > I believe, make the code more readable and easily maintainable. > > (The only ugly part is arm64_in_exp_entry(). I have no better ideas.) > > > > Please pick up this patch if you like. > > It is to be applied on top of your current master. > > > > [1] https://www.redhat.com/archives/crash-utility/2016-June/msg00040.html > > > > Thanks, > > -Takahiro AKASHI > > Takahiro, > > I hope to be able to take a look at this tomorrow, but upon an initial compile, > there's an error at line 1782 that prevents a chunk of code from ever being > executed: > > # make warn Oops, I forget to run "make warn" again. > ... [ cut ] ... > cc -c -g -DARM64 -DLZO -DSNAPPY -DGDB_7_6 arm64.c -Wall -O2 -Wstrict-prototypes -Wmissing-prototypes -fstack-protector -Wformat-security > arm64.c: In function 'arm64_unwind_frame': > arm64.c:1782:14: warning: suggest parentheses around operand of '!' or change '&' to '&& or '!' to '~' [-Wparentheses] > } else if (!machdep->flags & IRQ_STACKS) { > ^ > arm64.c:1729:31: warning: unused variable 'orig_sp' [-Wunused-variable] > unsigned long irq_stack_ptr, orig_sp; > ^ > arm64.c: At top level: > arm64.c:1489:1: warning: 'arm64_in_exception_text' defined but not used [-Wunused-function] > arm64_in_exception_text(ulong ptr) > ^ > ... Fixed them. > Here it is: > > 1773 if (ext_frame.fp == 0) { > 1774 /* > 1775 * Either on process stack or on IRQ stack, > 1776 * the next frame is the last one on process stack. > 1777 */ > 1778 > 1779 frame->sp = bt->stacktop > 1780 - sizeof(struct arm64_pt_regs) - 0x10; > 1781 frame->fp = frame->sp; > 1782 } else if (!machdep->flags & IRQ_STACKS) { > 1783 /* > 1784 * We are on process stack. Just fake a dummy frame > 1785 */ > 1786 > 1787 frame->sp = ext_frame.fp > 1788 - sizeof(struct arm64_pt_regs); > 1789 frame->fp = frame->sp; > 1790 } else { > 1791 /* We are on IRQ stack */ > 1792 > 1793 ms = machdep->machspec; > 1794 irq_stack_ptr = ms->irq_stacks[bt->tc->processor] > 1795 + ms->irq_stack_size - 0x20; > 1796 > > I know what it should look like, but I can't understand how the code works as-is? I can't neither :) You're right. I mistakenly used IRQ_STACKS here. Please review my next version. (I'm now testing crash util with various vmcore's, and have faced some corner cases.) Thanks, -Takahiro AKASHI > Dave > > > > > > > > > ======8<====== > > >From c1e06fdd21bb70d247babd43cf2762e0cdf6979c Mon Sep 17 00:00:00 2001 > > From: AKASHI Takahiro <takahiro.akashi@xxxxxxxxxx> > > Date: Thu, 16 Jun 2016 09:29:52 +0900 > > Subject: [PATCH v3] arm64: more improvement of bt -f > > > > Signed-off-by: AKASHI Takahiro <takahiro.akashi@xxxxxxxxxx> > > --- > > arm64.c | 486 > > +++++++++++++++++++++++++++++++++++++++++++--------------------- > > defs.h | 6 + > > 2 files changed, 337 insertions(+), 155 deletions(-) > > > > diff --git a/arm64.c b/arm64.c > > index 06676d1..9d42fe6 100644 > > --- a/arm64.c > > +++ b/arm64.c > > @@ -43,17 +43,18 @@ static void arm64_stackframe_init(void); > > static int arm64_eframe_search(struct bt_info *); > > static int arm64_is_kernel_exception_frame(struct bt_info *, ulong); > > static int arm64_in_exception_text(ulong); > > +static int arm64_in_exp_entry(ulong); > > static void arm64_back_trace_cmd(struct bt_info *); > > static void arm64_print_text_symbols(struct bt_info *, struct > > arm64_stackframe *, FILE *); > > static int arm64_print_stackframe_entry(struct bt_info *, int, struct > > arm64_stackframe *, FILE *); > > -static void arm64_display_full_frame(struct bt_info *, ulong); > > -static int arm64_unwind_frame(struct bt_info *, struct arm64_stackframe *); > > +static void arm64_display_full_frame(struct bt_info *, struct > > arm64_stackframe *, struct arm64_stackframe *); > > +static int arm64_unwind_frame(struct bt_info *, struct arm64_stackframe *, > > FILE *); > > static int arm64_get_dumpfile_stackframe(struct bt_info *, struct > > arm64_stackframe *); > > static int arm64_in_kdump_text(struct bt_info *, struct arm64_stackframe *); > > static int arm64_in_kdump_text_on_irq_stack(struct bt_info *); > > -static int arm64_switch_stack(struct bt_info *, struct arm64_stackframe *, > > FILE *); > > static int arm64_get_stackframe(struct bt_info *, struct arm64_stackframe > > *); > > static void arm64_get_stack_frame(struct bt_info *, ulong *, ulong *); > > +static void arm64_gen_hidden_frame(struct bt_info *bt, ulong, struct > > arm64_stackframe *); > > static void arm64_print_exception_frame(struct bt_info *, ulong, int, FILE > > *); > > static void arm64_do_bt_reference_check(struct bt_info *, ulong, char *); > > static int arm64_translate_pte(ulong, void *, ulonglong); > > @@ -580,6 +581,10 @@ arm64_dump_machdep_table(ulong arg) > > fprintf(fp, " __exception_text_end: %lx\n", ms->__exception_text_end); > > fprintf(fp, " __irqentry_text_start: %lx\n", ms->__irqentry_text_start); > > fprintf(fp, " __irqentry_text_end: %lx\n", ms->__irqentry_text_end); > > + fprintf(fp, " exp_entry1_start: %lx\n", ms->exp_entry1_start); > > + fprintf(fp, " exp_entry1_end: %lx\n", ms->exp_entry1_end); > > + fprintf(fp, " exp_entry2_start: %lx\n", ms->exp_entry2_start); > > + fprintf(fp, " exp_entry2_end: %lx\n", ms->exp_entry2_end); > > fprintf(fp, " panic_task_regs: %lx\n", (ulong)ms->panic_task_regs); > > fprintf(fp, " PTE_PROT_NONE: %lx\n", ms->PTE_PROT_NONE); > > fprintf(fp, " PTE_FILE: "); > > @@ -1286,6 +1291,15 @@ arm64_stackframe_init(void) > > machdep->machspec->__irqentry_text_start = sp1->value; > > machdep->machspec->__irqentry_text_end = sp2->value; > > } > > + if ((sp1 = kernel_symbol_search("vectors")) && > > + (sp1n = kernel_symbol_search("cpu_switch_to")) && > > + (sp2 = kernel_symbol_search("ret_fast_syscall")) && > > + (sp2n = kernel_symbol_search("sys_rt_sigreturn_wrapper"))) { > > + machdep->machspec->exp_entry1_start = sp1->value; > > + machdep->machspec->exp_entry1_end = sp1n->value; > > + machdep->machspec->exp_entry2_start = sp2->value; > > + machdep->machspec->exp_entry2_end = sp2n->value; > > + } > > > > if ((sp1 = kernel_symbol_search("crash_kexec")) && > > (sp1n = next_symbol(NULL, sp1)) && > > @@ -1488,9 +1502,21 @@ arm64_in_exception_text(ulong ptr) > > return FALSE; > > } > > > > +static int > > +arm64_in_exp_entry(ulong addr) > > +{ > > + struct machine_specific *ms; > > + > > + ms = machdep->machspec; > > + if ((ms->exp_entry1_start <= addr) && (addr < ms->exp_entry1_end)) > > + return TRUE; > > + if ((ms->exp_entry2_start <= addr) && (addr < ms->exp_entry2_end)) > > + return TRUE; > > + return FALSE; > > +} > > + > > #define BACKTRACE_CONTINUE (1) > > #define BACKTRACE_COMPLETE_KERNEL (2) > > -#define BACKTRACE_COMPLETE_USER (3) > > > > static int > > arm64_print_stackframe_entry(struct bt_info *bt, int level, struct > > arm64_stackframe *frame, FILE *ofp) > > @@ -1511,11 +1537,6 @@ arm64_print_stackframe_entry(struct bt_info *bt, int > > level, struct arm64_stackfr > > value_to_symstr(frame->pc, buf, bt->radix); > > } > > > > - if ((bt->flags & BT_FULL) && level) { > > - arm64_display_full_frame(bt, frame->fp); > > - bt->frameptr = frame->fp; > > - } > > - > > fprintf(ofp, "%s#%d [%8lx] %s at %lx", level < 10 ? " " : "", level, > > frame->fp ? frame->fp : bt->stacktop - USER_EFRAME_OFFSET, > > name_plus_offset ? name_plus_offset : name, frame->pc); > > @@ -1534,7 +1555,8 @@ arm64_print_stackframe_entry(struct bt_info *bt, int > > level, struct arm64_stackfr > > fprintf(ofp, " %s\n", buf); > > } > > > > - if (STREQ(name, "start_kernel") || STREQ(name, "secondary_start_kernel") || > > + if (STREQ(name, "start_kernel") || > > + STREQ(name, "secondary_start_kernel") || > > STREQ(name, "kthread") || STREQ(name, "kthreadd")) > > return BACKTRACE_COMPLETE_KERNEL; > > > > @@ -1542,46 +1564,169 @@ arm64_print_stackframe_entry(struct bt_info *bt, int > > level, struct arm64_stackfr > > } > > > > static void > > -arm64_display_full_frame(struct bt_info *bt, ulong sp) > > +arm64_display_full_frame(struct bt_info *bt, struct arm64_stackframe *cur, > > + struct arm64_stackframe *next) > > { > > + struct machine_specific *ms; > > + ulong next_fp, stackbase; > > + char *stackbuf; > > int i, u_idx; > > ulong *up; > > ulong words, addr; > > char buf[BUFSIZE]; > > > > - if (bt->frameptr == sp) > > - return; > > + stackbase = bt->stackbase; > > + stackbuf = bt->stackbuf; > > + ms = machdep->machspec; > > > > - if (!INSTACK(sp, bt) || !INSTACK(bt->frameptr, bt)) { > > - if (sp == 0) > > - sp = bt->stacktop - USER_EFRAME_OFFSET; > > - else > > - return; > > - } > > + /* Calc next fp for dump */ > > + if (next->fp == 0) > > + /* last stackframe on kernel tack */ > > + next_fp = bt->stacktop - 0x10; > > + else if (!INSTACK(cur->sp, bt)) { > > + /* We have just switched over stacks */ > > + next_fp = ms->irq_stacks[bt->tc->processor] > > + + ms->irq_stack_size - 0x10; > > + > > + /* > > + * We are already buffering a process stack. > > + * So use an old buffer for IRQ stack. > > + */ > > + stackbase = ms->irq_stacks[bt->tc->processor]; > > + stackbuf = ms->irq_stackbuf; > > + } else > > + next_fp = next->fp; > > + > > + if (CRASHDEBUG(1)) > > + fprintf(fp, " frame <%016lx:%016lx>\n", cur->fp, next_fp); > > > > - words = (sp - bt->frameptr) / sizeof(ulong); > > + /* Check here because we want to see a debug message above. */ > > + if (!(bt->flags & BT_FULL)) > > + return; > > > > - addr = bt->frameptr; > > - u_idx = (bt->frameptr - bt->stackbase)/sizeof(ulong); > > + /* Dump */ > > + words = (next_fp - cur->fp) / sizeof(ulong); > > + addr = cur->fp; > > + u_idx = (cur->fp - stackbase)/sizeof(ulong); > > for (i = 0; i < words; i++, u_idx++) { > > if (!(i & 1)) > > fprintf(fp, "%s %lx: ", i ? "\n" : "", addr); > > > > - up = (ulong *)(&bt->stackbuf[u_idx*sizeof(ulong)]); > > + up = (ulong *)(&stackbuf[u_idx*sizeof(ulong)]); > > fprintf(fp, "%s ", format_stack_entry(bt, buf, *up, 0)); > > > > addr += sizeof(ulong); > > } > > fprintf(fp, "\n"); > > + > > + if (stackbuf == ms->irq_stackbuf) > > + FREEBUF(stackbuf); > > } > > > > -static int > > -arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame) > > +/* > > + * (1)Normal frame: > > + * +------+ > > + * | pfp | > > + * | cpc | > > + * psp + + > > + * | | > > + * | | > > + * pfp +------+ <--- :prev stackframe = <pfp, psp, ppc> > > + * | cfp | > > + * | npc | > > + * csp + + > > + * | | > > + * | | > > + * cfp +------+ <--- :curr stackframe = <cfp, csp, cpc> > > + * | nfp | | cfp = *pfp > > + * | Npc | | csp = pfp + 0x10 > > + * nsp + + real stackframe > > + * | | | at cpc > > + * | | | > > + * nfp +------+ <--- :next stackframe = <nfp, nsp, npc> > > + * | | > > + * > > + * (2)Exception: > > + * +------+ > > + * | pfp | > > + * | cpc | > > + * psp + + > > + * | | > > + * | | > > + * pfp +------+ <--- :prev stackframe = <pfp, psp, ppc> > > + * | cfp | > > + * | npc | > > + * csp + + > > + * | | > > + * | | > > + * cfp +------+ <--- :stackframe = <cfp, csp, cpc> > > + * | nfp | > > + * | epc | > > + * + + > > + * | | > > + * | | calced dummy > > + * esp +------+ <--- :exp stackframe = <---, esp, epc> > > + * | | esp = nsp - sizeof(pt_regs) > > + * | | > > + * | Npc | > > + * | nfp | > > + * | nsp | > > + * | npc | > > + * nsp + + > > + * | | calced missing > > + * nfp +------+ <--- :task stackframe = <nfp, nsp, npc> > > + * | Nfp | > > + * | NNpc | > > + * Nsp + + > > + * | | > > + * Nfp +------+ <--- :task stackframe = <Nfp, Nsp, Npc> > > + * | NNfp | > > + * > > + * (3)At interrupt: > > + * +------+ > > + * | pfp | > > + * | cpc | > > + * psp + + > > + * | | > > + * | | > > + * pfp +------+ <--- :prev stackframe = <pfp, psp, ppc> > > + * | cfp | > > + * | epc | > > + * csp + + > > + * | | > > + * | | calced dummy > > + * cfp +------+ <--- :irq stackframe = <cfp, csp, epc> > > + * | nfp | | if (cfp == IRQ_STACK_PTR) > > + * | esp | V > > + * top +------+ <---, esp, epc> > > + * IRQ stack > > + * > > + * calced dummy > > + * esp +------+ <--- :exp stackframe = <---, esp, epc> > > + * | | esp = nsp - sizeof(pt_regs) > > + * | | > > + * | Npc | > > + * | nfp | > > + * | nsp | > > + * | npc | calced missing > > + * nfp +------+ <--- :task stackframe = <nfp, nsp, npc> > > + * | Nfp | > > + * | NNpc | > > + * Nsp + + > > + * | | > > + * Nfp +------+ <--- :task stackframe = <Nfp, Nsp, Npc> > > + * | NNfp | > > + */ > > + > > +static struct arm64_stackframe ext_frame; > > + > > +static int > > +arm64_unwind_frame(struct bt_info *bt, struct arm64_stackframe *frame, > > + FILE *ofp) > > { > > unsigned long high, low, fp; > > unsigned long stack_mask; > > unsigned long irq_stack_ptr, orig_sp; > > - struct arm64_pt_regs *ptregs; > > struct machine_specific *ms; > > > > stack_mask = (unsigned long)(ARM64_STACK_SIZE) - 1; > > @@ -1593,54 +1738,101 @@ arm64_unwind_frame(struct bt_info *bt, struct > > arm64_stackframe *frame) > > if (fp < low || fp > high || fp & 0xf) > > return FALSE; > > > > - frame->sp = fp + 0x10; > > - frame->fp = GET_STACK_ULONG(fp); > > + if (CRASHDEBUG(1)) > > + fprintf(ofp, " cur fp:%016lx sp:%016lx pc:%016lx\n", > > + frame->fp, frame->sp, frame->pc); > > + > > + if (ext_frame.pc) { > > + /* > > + * Previous frame was a dummy for exception entry. > > + * So insert a hidden (real) stackframe. > > + */ > > + frame->fp = ext_frame.fp; > > + frame->sp = ext_frame.sp; > > + frame->pc = ext_frame.pc; > > + > > + ext_frame.pc = 0; /* back to normal unwinding */ > > + > > + goto unwind_done; > > + } > > + > > frame->pc = GET_STACK_ULONG(fp + 8); > > + if (!arm64_in_exp_entry(frame->pc)) { > > + /* Normal stack frame */ > > > > - /* > > - * The kernel's manner of determining the end of the IRQ stack: > > - * > > - * #define THREAD_SIZE 16384 > > - * #define THREAD_START_SP (THREAD_SIZE - 16) > > - * #define IRQ_STACK_START_SP THREAD_START_SP > > - * #define IRQ_STACK_PTR(cpu) ((unsigned long)per_cpu(irq_stack, cpu) + > > IRQ_STACK_START_SP) > > - * #define IRQ_STACK_TO_TASK_STACK(ptr) (*((unsigned long *)((ptr) - > > 0x08))) > > - * > > - * 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) > > - */ > > - if (machdep->flags & IRQ_STACKS) { > > - ms = machdep->machspec; > > - irq_stack_ptr = ms->irq_stacks[bt->tc->processor] + ms->irq_stack_size - > > 16; > > - > > - if (frame->sp == irq_stack_ptr) { > > - orig_sp = GET_STACK_ULONG(irq_stack_ptr - 8); > > - arm64_set_process_stack(bt); > > - if (INSTACK(orig_sp, bt) && (INSTACK(frame->fp, bt) || (frame->fp == 0))) > > { > > - ptregs = (struct arm64_pt_regs > > *)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(orig_sp))]; > > - frame->sp = orig_sp; > > - frame->pc = ptregs->pc; > > - bt->bptr = fp; > > - if (CRASHDEBUG(1)) > > - error(INFO, > > - "arm64_unwind_frame: switch stacks: fp: %lx sp: %lx pc: %lx\n", > > - frame->fp, frame->sp, frame->pc); > > + frame->sp = fp + 0x10; > > + frame->fp = GET_STACK_ULONG(fp); > > + } else { > > + /* > > + * We are in exception entry code, and so need to > > + * - fake a dummy frame for exception frame, and > > + * - complement a stackframe hidden by exception > > + */ > > + > > + ext_frame.fp = GET_STACK_ULONG(fp); > > + if (ext_frame.fp == 0) { > > + /* > > + * Either on process stack or on IRQ stack, > > + * the next frame is the last one on process stack. > > + */ > > + > > + frame->sp = bt->stacktop > > + - sizeof(struct arm64_pt_regs) - 0x10; > > + frame->fp = frame->sp; > > + } else if (!machdep->flags & IRQ_STACKS) { > > + /* > > + * We are on process stack. Just fake a dummy frame > > + */ > > + > > + frame->sp = ext_frame.fp > > + - sizeof(struct arm64_pt_regs); > > + frame->fp = frame->sp; > > + } else { > > + /* We are on IRQ stack */ > > + > > + ms = machdep->machspec; > > + irq_stack_ptr = ms->irq_stacks[bt->tc->processor] > > + + ms->irq_stack_size - 0x20; > > + if (ext_frame.fp != irq_stack_ptr) { > > + /* Just fake a dummy frame */ > > + > > + frame->sp = ext_frame.fp > > + - sizeof(struct arm64_pt_regs); > > + frame->fp = frame->sp; > > } else { > > - error(WARNING, > > - "arm64_unwind_frame: on IRQ stack: oriq_sp: %lx%s fp: %lx%s\n", > > - orig_sp, INSTACK(orig_sp, bt) ? "" : " (?)", > > - frame->fp, INSTACK(frame->fp, bt) ? "" : " (?)"); > > - return FALSE; > > + /* > > + * switch from IRQ stack to process stack > > + */ > > + > > + frame->sp = GET_STACK_ULONG(irq_stack_ptr + 8); > > + frame->fp = frame->sp; > > + > > + /* > > + * Keep a buffer for a while until > > + * displaying the last frame on IRQ stack. > > + * Ugly? > > + */ > > + if (bt->flags | BT_FULL) > > + ms->irq_stackbuf = bt->stackbuf; > > + > > + arm64_set_process_stack(bt); > > } > > } > > + > > + arm64_gen_hidden_frame(bt, frame->sp, &ext_frame); > > } > > > > +unwind_done: > > + if (CRASHDEBUG(1)) > > + fprintf(ofp, " nxt fp:%016lx sp:%016lx pc:%016lx\n", > > + frame->fp, frame->sp, frame->pc); > > + > > return TRUE; > > } > > > > -/* > > +/* > > * A layout of a stack frame in a function looks like: > > - * > > + * > > * stack grows to lower addresses. > > * /|\ > > * | > > @@ -1658,7 +1850,7 @@ arm64_unwind_frame(struct bt_info *bt, struct > > arm64_stackframe *frame) > > * | vars | > > * old fp +------+ > > * | | > > - * > > + * > > * - On function entry, sp is decremented down to new fp. > > * > > * - and old fp and sp are saved into this stack frame. > > @@ -1680,13 +1872,13 @@ arm64_unwind_frame(struct bt_info *bt, struct > > arm64_stackframe *frame) > > * sp shows "callee's static local variables", old fp and sp. > > * > > * Diagram and explanation courtesy of Takahiro Akashi > > - */ > > + */ > > > > static void > > arm64_back_trace_cmd(struct bt_info *bt) > > { > > - struct arm64_stackframe stackframe; > > - int level; > > + struct arm64_stackframe stackframe, cur_frame; > > + int level, mode; > > ulong exception_frame; > > FILE *ofp; > > > > @@ -1708,17 +1900,7 @@ arm64_back_trace_cmd(struct bt_info *bt) > > stackframe.fp = GET_STACK_ULONG(bt->bptr - 8); > > stackframe.pc = GET_STACK_ULONG(bt->bptr); > > stackframe.sp = bt->bptr + 8; > > - bt->frameptr = stackframe.sp; > > - } else if (bt->hp && bt->hp->esp) { > > - if (arm64_on_irq_stack(bt->tc->processor, bt->hp->esp)) { > > - arm64_set_irq_stack(bt); > > - bt->flags |= BT_IRQSTACK; > > - } > > - stackframe.fp = GET_STACK_ULONG(bt->hp->esp - 8); > > - stackframe.pc = bt->hp->eip ? > > - bt->hp->eip : GET_STACK_ULONG(bt->hp->esp); > > - stackframe.sp = bt->hp->esp + 8; > > - bt->flags &= ~BT_REGS_NOT_FOUND; > > + bt->frameptr = stackframe.fp; > > } else { > > stackframe.sp = bt->stkptr; > > stackframe.pc = bt->instptr; > > @@ -1739,8 +1921,14 @@ arm64_back_trace_cmd(struct bt_info *bt) > > return; > > > > if (!(bt->flags & BT_KDUMP_ADJUST)) { > > - if (bt->flags & BT_USER_SPACE) > > - goto complete_user; > > + if (bt->flags & BT_USER_SPACE) { > > + exception_frame = bt->stacktop - USER_EFRAME_OFFSET; > > + arm64_print_exception_frame(bt, exception_frame, > > + USER_MODE, ofp); > > + fprintf(ofp, " #0 [user space]\n"); > > + > > + return; > > + } > > > > if (DUMPFILE() && is_task_active(bt->task)) { > > exception_frame = stackframe.fp - SIZE(pt_regs); > > @@ -1750,53 +1938,55 @@ arm64_back_trace_cmd(struct bt_info *bt) > > } > > } > > > > - level = exception_frame = 0; > > - while (1) { > > + for (level = 0;; level++) { > > bt->instptr = stackframe.pc; > > > > - switch (arm64_print_stackframe_entry(bt, level, &stackframe, ofp)) > > - { > > - case BACKTRACE_COMPLETE_KERNEL: > > - return; > > - case BACKTRACE_COMPLETE_USER: > > - goto complete_user; > > - case BACKTRACE_CONTINUE: > > + /* > > + * Show one-line stackframe info > > + */ > > + if (arm64_print_stackframe_entry(bt, level, &stackframe, ofp) > > + == BACKTRACE_COMPLETE_KERNEL) > > break; > > - } > > - > > - if (exception_frame) { > > - arm64_print_exception_frame(bt, exception_frame, KERNEL_MODE, ofp); > > - exception_frame = 0; > > - } > > > > - if (!arm64_unwind_frame(bt, &stackframe)) > > + cur_frame = stackframe; > > + if (!arm64_unwind_frame(bt, &stackframe, ofp)) > > break; > > > > - if (arm64_in_exception_text(bt->instptr) && INSTACK(stackframe.fp, bt)) { > > - if (!(bt->flags & BT_IRQSTACK) || > > - (((stackframe.sp + SIZE(pt_regs)) < bt->stacktop))) > > - exception_frame = stackframe.fp - SIZE(pt_regs); > > - } > > + /* > > + * Dump the contents of the current stackframe. > > + * We need to know the next stackframe to determine > > + * the dump range: > > + * <cur_frame.fp:stackframe.fp> > > + */ > > + arm64_display_full_frame(bt, &cur_frame, &stackframe); > > > > - if ((bt->flags & BT_IRQSTACK) && > > - !arm64_on_irq_stack(bt->tc->processor, stackframe.sp)) { > > - bt->flags &= ~BT_IRQSTACK; > > - if (arm64_switch_stack(bt, &stackframe, ofp) == USER_MODE) > > - break; > > - } > > + /* > > + * If we are in a normal stackframe, just continue, > > + * otherwise show an exception frame. > > + * Since exception entry code doesn't have a real > > + * stackframe, we fake a dummy frame here. > > + */ > > + if (!arm64_in_exp_entry(stackframe.pc)) > > + continue; > > > > + if (!INSTACK(cur_frame.sp, bt)) > > + fprintf(ofp, "--- <IRQ stack> ---\n"); > > > > - level++; > > - } > > + arm64_print_stackframe_entry(bt, ++level, &stackframe, ofp); > > + cur_frame = stackframe; > > + arm64_unwind_frame(bt, &stackframe, ofp); > > > > - if (is_kernel_thread(bt->tc->task)) > > - return; > > + /* > > + * and don't show the contenxts. Instead, > > + * show an exception frame below > > + */ > > + mode = (stackframe.pc < machdep->machspec->userspace_top) ? > > + USER_MODE : KERNEL_MODE; > > + arm64_print_exception_frame(bt, cur_frame.sp, mode, ofp); > > > > -complete_user: > > - exception_frame = bt->stacktop - USER_EFRAME_OFFSET; > > - arm64_print_exception_frame(bt, exception_frame, USER_MODE, ofp); > > - if ((bt->flags & (BT_USER_SPACE|BT_KDUMP_ADJUST)) == BT_USER_SPACE) > > - fprintf(ofp, " #0 [user space]\n"); > > + if (mode == USER_MODE) > > + break; > > + } > > } > > > > static void > > @@ -1932,41 +2122,6 @@ arm64_in_kdump_text_on_irq_stack(struct bt_info *bt) > > return FALSE; > > } > > > > -static int > > -arm64_switch_stack(struct bt_info *bt, struct arm64_stackframe *frame, FILE > > *ofp) > > -{ > > - int i; > > - ulong stacktop, words, addr; > > - ulong *stackbuf; > > - char buf[BUFSIZE]; > > - struct machine_specific *ms = machdep->machspec; > > - > > - if (bt->flags & BT_FULL) { > > - stacktop = ms->irq_stacks[bt->tc->processor] + ms->irq_stack_size; > > - words = (stacktop - bt->bptr) / sizeof(ulong); > > - stackbuf = (ulong *)GETBUF(words * sizeof(ulong)); > > - readmem(bt->bptr, KVADDR, stackbuf, words * sizeof(long), > > - "top of IRQ stack", FAULT_ON_ERROR); > > - > > - addr = bt->bptr; > > - for (i = 0; i < words; i++) { > > - if (!(i & 1)) > > - fprintf(ofp, "%s %lx: ", i ? "\n" : "", addr); > > - fprintf(ofp, "%s ", format_stack_entry(bt, buf, stackbuf[i], 0)); > > - addr += sizeof(ulong); > > - } > > - fprintf(ofp, "\n"); > > - FREEBUF(stackbuf); > > - } > > - fprintf(ofp, "--- <IRQ stack> ---\n"); > > - > > - if (frame->fp == 0) > > - return USER_MODE; > > - > > - arm64_print_exception_frame(bt, frame->sp, KERNEL_MODE, ofp); > > - return KERNEL_MODE; > > -} > > - > > static int > > arm64_get_dumpfile_stackframe(struct bt_info *bt, struct arm64_stackframe > > *frame) > > { > > @@ -2047,6 +2202,20 @@ arm64_get_stack_frame(struct bt_info *bt, ulong *pcp, > > ulong *spp) > > } > > > > static void > > +arm64_gen_hidden_frame(struct bt_info *bt, ulong sp, > > + struct arm64_stackframe *frame) > > +{ > > + struct arm64_pt_regs *ptregs; > > + > > + ptregs = (struct arm64_pt_regs *) > > + &bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(sp))]; > > + > > + frame->pc = ptregs->pc; > > + frame->fp = ptregs->regs[29]; > > + frame->sp = ptregs->sp; > > +} > > + > > +static void > > arm64_print_exception_frame(struct bt_info *bt, ulong pt_regs, int mode, > > FILE *ofp) > > { > > int i, r, rows, top_reg, is_64_bit; > > @@ -2055,10 +2224,16 @@ arm64_print_exception_frame(struct bt_info *bt, ulong > > pt_regs, int mode, FILE *o > > ulong LR, SP, offset; > > char buf[BUFSIZE]; > > > > + if (mode == KERNEL_MODE) > > + fprintf(ofp, "--- <Exception in kernel> ---\n"); > > + else > > + fprintf(ofp, "--- <Exception in user> ---\n"); > > + > > if (CRASHDEBUG(1)) > > fprintf(ofp, "pt_regs: %lx\n", pt_regs); > > > > - regs = (struct arm64_pt_regs > > *)&bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(pt_regs))]; > > + regs = (struct arm64_pt_regs *) > > + &bt->stackbuf[(ulong)(STACK_OFFSET_TYPE(pt_regs))]; > > > > if ((mode == USER_MODE) && (regs->pstate & PSR_MODE32_BIT)) { > > LR = regs->regs[14]; > > @@ -2130,10 +2305,11 @@ arm64_print_exception_frame(struct bt_info *bt, ulong > > pt_regs, int mode, FILE *o > > } > > > > if (is_64_bit) { > > - fprintf(ofp, "ORIG_X0: %016lx SYSCALLNO: %lx", > > - (ulong)regs->orig_x0, (ulong)regs->syscallno); > > - if (mode == USER_MODE) > > + if (mode == USER_MODE) { > > + fprintf(ofp, "ORIG_X0: %016lx SYSCALLNO: %lx", > > + (ulong)regs->orig_x0, (ulong)regs->syscallno); > > fprintf(ofp, " PSTATE: %08lx", (ulong)regs->pstate); > > + } > > fprintf(ofp, "\n"); > > } > > > > diff --git a/defs.h b/defs.h > > index d6f719c..f7ea5a0 100644 > > --- a/defs.h > > +++ b/defs.h > > @@ -3058,8 +3058,14 @@ struct machine_specific { > > ulong kernel_flags; > > ulong irq_stack_size; > > ulong *irq_stacks; > > + char *irq_stackbuf; > > ulong __irqentry_text_start; > > ulong __irqentry_text_end; > > + /* for exception vector code */ > > + ulong exp_entry1_start; > > + ulong exp_entry1_end; > > + ulong exp_entry2_start; > > + ulong exp_entry2_end; > > /* only needed for v4.6 or later kernel */ > > ulong kimage_voffset; > > ulong kimage_text; > > -- > > 2.9.0 > > > > -- > > Crash-utility mailing list > > Crash-utility@xxxxxxxxxx > > https://www.redhat.com/mailman/listinfo/crash-utility > > > > -- > Crash-utility mailing list > Crash-utility@xxxxxxxxxx > https://www.redhat.com/mailman/listinfo/crash-utility -- Crash-utility mailing list Crash-utility@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/crash-utility