[Crash-utility] [PATCH v3] arm64: more improvement of bt -f
AKASHI Takahiro
takahiro.akashi at linaro.org
Wed Jun 22 04:46:33 UTC 2016
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 at linaro.org>
> > 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 at linaro.org>
> > ---
> > 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 at redhat.com
> > https://www.redhat.com/mailman/listinfo/crash-utility
> >
>
> --
> Crash-utility mailing list
> Crash-utility at redhat.com
> https://www.redhat.com/mailman/listinfo/crash-utility
More information about the Crash-utility
mailing list