[PATCH 3/5] arm64: implement printing backtraces

Casey Connolly casey.connolly at linaro.org
Mon Jul 7 15:12:27 CEST 2025



On 7/3/25 14:08, Heinrich Schuchardt wrote:
> 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.

I think you missed the second half of my comment vv>
>>
>> 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.

Already sent in a different mail but just for completeness sake

https://lore.kernel.org/u-boot/20240808-arm64-backtrace-v2-0-29665a2265cf@linaro.org/

> 
> 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");
>>>   }
> 
> 

-- 
Casey (she/they)



More information about the U-Boot mailing list