----- Original Message -----
> 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
... [ 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)
 ^
...

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?

Dave





> 
> ======8<======
> >From c1e06fdd21bb70d247babd43cf2762e0cdf6979c Mon Sep 17 00:00:00 2001
> From: AKASHI Takahiro <[email protected]>
> Date: Thu, 16 Jun 2016 09:29:52 +0900
> Subject: [PATCH v3] arm64: more improvement of bt -f
> 
> Signed-off-by: AKASHI Takahiro <[email protected]>
> ---
>  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
> [email protected]
> https://www.redhat.com/mailman/listinfo/crash-utility
> 

--
Crash-utility mailing list
[email protected]
https://www.redhat.com/mailman/listinfo/crash-utility

Reply via email to