... [ 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(a)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(a)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(a)redhat.com
 > 
https://www.redhat.com/mailman/listinfo/crash-utility
 > 
 
 --
 Crash-utility mailing list
 Crash-utility(a)redhat.com
 
https://www.redhat.com/mailman/listinfo/crash-utility