loader.efi: panic() should show stack trace

Because panic() does provide mechanism to have architecture specific
panic call, we can instruct it to print out stack trace too
(in hope we actually can print). While there, also implement simple
check to detect loop in trace.

illumos issue: https://www.illumos.org/issues/17887
This commit is contained in:
Toomas Soome
2026-04-09 14:36:12 +03:00
parent c1c97f18b5
commit aacf448007
+59 -29
View File
@@ -82,14 +82,68 @@ struct frame {
};
void report_exc(struct trapframe *tf);
void
report_exc(struct trapframe *tf)
static void
stack_trace(struct frame *fp, uintptr_t pc)
{
struct frame *fp;
uintptr_t pc, base;
uintptr_t base;
char buf[80];
base = (uintptr_t)boot_img->ImageBase;
printf("Stack trace:\n");
pager_open();
while (fp != NULL || pc != 0) {
struct frame *nfp;
char *source = "PC";
if (pc >= base && pc < base + boot_img->ImageSize) {
pc -= base;
source = "loader PC";
}
(void) snprintf(buf, sizeof (buf), "FP %016lx: %s 0x%016lx\n",
(uintptr_t)fp, source, pc);
if (pager_output(buf))
break;
if (fp == NULL)
break;
nfp = fp->fr_savfp;
if (nfp != NULL && nfp <= fp) {
printf("FP %016lx: loop detected, stopping trace\n",
(uintptr_t)nfp);
break;
}
fp = nfp;
if (fp != NULL)
pc = fp->fr_savpc;
else
pc = 0;
}
pager_close();
}
void
panic_action(void)
{
struct frame *fp;
uintptr_t rip;
__asm __volatile("movq %%rbp,%0" : "=r" (fp));
rip = fp->fr_savpc;
stack_trace(fp, rip);
printf("--> Press a key on the console to reboot <--\n");
getchar();
printf("Rebooting...\n");
exit(1);
}
void
report_exc(struct trapframe *tf)
{
/*
* printf() depends on loader runtime and UEFI firmware health
* to produce the console output, in case of exception, the
@@ -116,32 +170,8 @@ report_exc(struct trapframe *tf)
tf->tf_r9, tf->tf_rax, tf->tf_rbx, tf->tf_rbp, tf->tf_r10,
tf->tf_r11, tf->tf_r12, tf->tf_r13, tf->tf_r14, tf->tf_r15);
fp = (struct frame *)tf->tf_rbp;
pc = tf->tf_rip;
stack_trace((struct frame *)tf->tf_rbp, tf->tf_rip);
printf("Stack trace:\n");
pager_open();
while (fp != NULL || pc != 0) {
char *source = "PC";
if (pc >= base && pc < base + boot_img->ImageSize) {
pc -= base;
source = "loader PC";
}
(void) snprintf(buf, sizeof (buf), "FP %016lx: %s 0x%016lx\n",
(uintptr_t)fp, source, pc);
if (pager_output(buf))
break;
if (fp != NULL)
fp = fp->fr_savfp;
if (fp != NULL)
pc = fp->fr_savpc;
else
pc = 0;
}
pager_close();
printf("Machine stopped.\n");
}