[PATCH 3/5] arm64: implement printing backtraces

Heinrich Schuchardt heinrich.schuchardt at canonical.com
Thu Jul 3 07:19:49 CEST 2025


Add a function to print frame pointers depending on symbols
CONFIG_(SPL)_FRAMEPOINTER.

Signed-off-by: Heinrich Schuchardt <heinrich.schuchardt at canonical.com>
---
 arch/arm/Makefile            |  9 ++++++-
 arch/arm/lib/interrupts_64.c | 46 ++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/arch/arm/Makefile b/arch/arm/Makefile
index 5ecadb2ef1b..41e75b5bcb1 100644
--- a/arch/arm/Makefile
+++ b/arch/arm/Makefile
@@ -33,6 +33,13 @@ endif
 # Evaluate arch cc-option calls now
 arch-y := $(arch-y)
 
+ifeq ($(CONFIG_$(PHASE_)FRAMEPOINTER),y)
+	ARCH_FLAGS += -fno-omit-frame-pointer
+endif
+
+PLATFORM_CPPFLAGS	+= $(ARCH_FLAGS)
+CFLAGS_EFI		+= $(ARCH_FLAGS)
+
 # This selects how we optimise for the processor.
 tune-$(CONFIG_CPU_ARM720T)	=-mtune=arm7tdmi
 tune-$(CONFIG_CPU_ARM920T)	=
@@ -47,7 +54,7 @@ tune-$(CONFIG_ARM64)		=
 # Evaluate tune cc-option calls now
 tune-y := $(tune-y)
 
-PLATFORM_CPPFLAGS += $(arch-y) $(tune-y)
+PLATFORM_CPPFLAGS += $(ARCH_FLAGS) $(arch-y) $(tune-y)
 
 # Machine directory name.  This list is sorted alphanumerically
 # by CONFIG_* macro name.
diff --git a/arch/arm/lib/interrupts_64.c b/arch/arm/lib/interrupts_64.c
index b3024ba514e..970f8b6831f 100644
--- a/arch/arm/lib/interrupts_64.c
+++ b/arch/arm/lib/interrupts_64.c
@@ -98,6 +98,35 @@ void show_regs(struct pt_regs *regs)
 	dump_instr(regs);
 }
 
+/**
+ * show_backtrace() - show backtrace using frame pointers
+ *
+ * @regs - registers
+ */
+static void show_backtrace(struct pt_regs *regs)
+{
+	void **fp = (void **)regs->regs[29];
+	unsigned int count = 0;
+	void *lr;
+
+	printf("\nbacktrace:\n");
+
+	while (fp) {
+		lr = fp[1];
+		printf("%3d: fp: %p lr: %p",
+		       count, fp, lr);
+
+		if (gd && gd->flags & GD_FLG_RELOC)
+			printf(" - %p (reloc)\n", lr - gd->reloc_off);
+		else
+			printf("\n");
+
+		fp = fp[0];
+		++count;
+	}
+	printf("\n");
+}
+
 /*
  * Try to "emulate" a semihosting call in the event that we don't have a
  * debugger attached.
@@ -149,6 +179,8 @@ void do_bad_sync(struct pt_regs *pt_regs)
 	printf("Bad mode in \"Synchronous Abort\" handler, esr 0x%08lx\n",
 	       pt_regs->esr);
 	show_regs(pt_regs);
+	if (CONFIG_IS_ENABLED(FRAMEPOINTER))
+		show_backtrace(pt_regs);
 	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
@@ -161,6 +193,8 @@ void do_bad_irq(struct pt_regs *pt_regs)
 	efi_restore_gd();
 	printf("Bad mode in \"Irq\" handler, esr 0x%08lx\n", pt_regs->esr);
 	show_regs(pt_regs);
+	if (CONFIG_IS_ENABLED(FRAMEPOINTER))
+		show_backtrace(pt_regs);
 	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
@@ -173,6 +207,8 @@ void do_bad_fiq(struct pt_regs *pt_regs)
 	efi_restore_gd();
 	printf("Bad mode in \"Fiq\" handler, esr 0x%08lx\n", pt_regs->esr);
 	show_regs(pt_regs);
+	if (CONFIG_IS_ENABLED(FRAMEPOINTER))
+		show_backtrace(pt_regs);
 	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
@@ -185,6 +221,8 @@ void do_bad_error(struct pt_regs *pt_regs)
 	efi_restore_gd();
 	printf("Bad mode in \"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
 	show_regs(pt_regs);
+	if (CONFIG_IS_ENABLED(FRAMEPOINTER))
+		show_backtrace(pt_regs);
 	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
@@ -202,6 +240,8 @@ void do_sync(struct pt_regs *pt_regs)
 	dump_far(pt_regs->esr);
 	printf("\n");
 	show_regs(pt_regs);
+	if (CONFIG_IS_ENABLED(FRAMEPOINTER))
+		show_backtrace(pt_regs);
 	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
@@ -214,6 +254,8 @@ void do_irq(struct pt_regs *pt_regs)
 	efi_restore_gd();
 	printf("\"Irq\" handler, esr 0x%08lx\n", pt_regs->esr);
 	show_regs(pt_regs);
+	if (CONFIG_IS_ENABLED(FRAMEPOINTER))
+		show_backtrace(pt_regs);
 	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
@@ -226,6 +268,8 @@ void do_fiq(struct pt_regs *pt_regs)
 	efi_restore_gd();
 	printf("\"Fiq\" handler, esr 0x%08lx\n", pt_regs->esr);
 	show_regs(pt_regs);
+	if (CONFIG_IS_ENABLED(FRAMEPOINTER))
+		show_backtrace(pt_regs);
 	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
@@ -241,6 +285,8 @@ void __weak do_error(struct pt_regs *pt_regs)
 	efi_restore_gd();
 	printf("\"Error\" handler, esr 0x%08lx\n", pt_regs->esr);
 	show_regs(pt_regs);
+	if (CONFIG_IS_ENABLED(FRAMEPOINTER))
+		show_backtrace(pt_regs);
 	show_efi_loaded_images(pt_regs);
 	panic("Resetting CPU ...\n");
 }
-- 
2.48.1



More information about the U-Boot mailing list