[PATCH 3/5] arm64: implement printing backtraces

Heinrich Schuchardt heinrich.schuchardt at canonical.com
Thu Jul 3 14:08:32 CEST 2025


On 03.07.25 13:39, Casey Connolly wrote:
>
> On 03/07/2025 07:19, Heinrich Schuchardt wrote:
>> 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
> from my testing, current arm64 builds of U-Boot will make use of a frame
> pointer, it seems to be the default.

The built-in defaults may depend on the distro providing the compiler 
and may be different on LLVM and GCC.

>
> So if CONFIG_FRAMEPOINTER is disabled we should explicitly add the
> -fomit-frame-pointer flag I think? Or we ignore CONFIG_FRAMEPOINTER for
> arm64 and accept that we always have a framepointer (I'm not sure how
> significant the space saving really is here).
>
>> +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");
> This should be a capital 'B' as with the other headers.

ok

>
> In my series the output looks like:
>
> Backtrace:
> 	<0x000001ffdfb344> do_mem_mw+0xbc
> 	<0x000001ffe0f07c> cmd_process+0x130
> 	<0x000001ffe06440> run_list_real+0x6d0
> 	<0x000001ffe065cc> parse_stream_outer+0x14c
> 	<0x000001ffe06b10> parse_file_outer+0x34
> 	<0x000001ffe0e3a4> cli_loop+0x18
> 	<0x000001ffe03b9c> main_loop+0x74
> 	<0x000001ffe07984> board_init_r+0x3c8

Please, provide a link to your series.

Showing function names would be great.

Best regards

Heinrich

>
> The aim was to match how the kernel backtraces look. I think it makes
> sense to do that here too.
>
>> +
>> +	while (fp) {
>> +		lr = fp[1];
>> +		printf("%3d: fp: %p lr: %p",
>> +		       count, fp, lr);
> The address of the framepointer isn't so interesting, neither is the
> index imo. I think the useful info here is the address of the function
> and the offset from that to lr.
>
> Printing the lr pre and post relocation does maybe make sense though, to
> be useful for interactive debugging or analyzing an objdump.
>
> Kind regards,
>
>> +
>> +		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");
>>   }




More information about the U-Boot mailing list