mbox series

[RFC,0/3] ARM64: add symbol name lookup and print a backtrace on exception

Message ID 20240710-arm64-backtrace-v1-0-5a2ba50485dd@linaro.org
Headers show
Series ARM64: add symbol name lookup and print a backtrace on exception | expand

Message

Caleb Connolly July 10, 2024, 4:26 p.m. UTC
U-Boot already emits frame pointers on ARM64, but lacks the code to
parse them, as well as a mechanism for looking up symbol names at
runtime.

There was some (seemingly?) leftover code for symbols lookups in
common/kallsyms.c and associated parts in the makefile, however it
appears to be entirely unused and unsupported. It relied on generating
one long string of all symbol addresses and names.

The approach taken here is instead largely based on the implementation
in the Xen hypervisor, it performs basic compression using non-ASCII
bytes to tokenize repeated string segments which can later be expanded
back out at runtime.

This is then utilized in the ARM64 interrupt handling routine to dump a
backtrace in the show_regs() debug function. As well as providing a
general purpose unwind_stack() function which can be used for debugging.

== Relocation ==

Since U-Boot relocates itself at runtime, and can be built to be
position independent in the first place (effectively "relocating" itself
when it first starts too), we can't really rely on gd->reloc_off.

The approach taken here is to subtract CONFIG_TEXT_BASE from the address
of each symbol in the lookup table (while it's being generated), then
when decoding we just subtract the address of the _start label. Since
this label address is updated to make U-Boot position independent and
during relocation, it allows us to avoid re-implementing the relocation
state handling stuff in the symbol decoder.

== Size ==

By default this feature is off, and will not effect the size of U-Boot
binaries. The generated symbols object file is ~85k with the (fairly
hefty) qcom_defconfig, so there is certainly a cost to be taken into
account.

I hope that this implementation can be later extended for other
platforms. However this is currently beyond my (skill, time)
capabilities.

---
Caleb Connolly (3):
      drop unused kallsyms support
      add support for symbol lookups
      arm64: unwind stack on exception

 Makefile                      |  24 +-
 arch/arm/include/asm/ptrace.h |   4 +
 arch/arm/lib/interrupts_64.c  |  76 +++++
 common/Makefile               |   1 -
 common/kallsyms.c             |  43 ---
 common/system_map.c           |   8 -
 include/symbols.h             |  19 ++
 lib/Kconfig                   |   8 +
 lib/Makefile                  |   1 +
 lib/symbols.c                 | 126 ++++++++
 tools/Makefile                |   3 +
 tools/symbols.c               | 646 ++++++++++++++++++++++++++++++++++++++++++
 12 files changed, 896 insertions(+), 63 deletions(-)
---
change-id: 20240710-arm64-backtrace-2926f764dbdc
base-commit: 13f9c5668411aa18ef64846d5bc86e9e6be52082

// Caleb (they/them)

Comments

Tom Rini July 12, 2024, 4:48 p.m. UTC | #1
On Wed, Jul 10, 2024 at 06:26:17PM +0200, Caleb Connolly wrote:

> U-Boot already emits frame pointers on ARM64, but lacks the code to
> parse them, as well as a mechanism for looking up symbol names at
> runtime.
> 
> There was some (seemingly?) leftover code for symbols lookups in
> common/kallsyms.c and associated parts in the makefile, however it
> appears to be entirely unused and unsupported. It relied on generating
> one long string of all symbol addresses and names.
> 
> The approach taken here is instead largely based on the implementation
> in the Xen hypervisor, it performs basic compression using non-ASCII
> bytes to tokenize repeated string segments which can later be expanded
> back out at runtime.
> 
> This is then utilized in the ARM64 interrupt handling routine to dump a
> backtrace in the show_regs() debug function. As well as providing a
> general purpose unwind_stack() function which can be used for debugging.

Just a few minor comments from me in general, and I'm glad to see this.
Please submit the next version non-RFC, thanks.
Caleb Connolly July 14, 2024, 7:47 p.m. UTC | #2
On 12/07/2024 18:48, Tom Rini wrote:
> On Wed, Jul 10, 2024 at 06:26:17PM +0200, Caleb Connolly wrote:
> 
>> U-Boot already emits frame pointers on ARM64, but lacks the code to
>> parse them, as well as a mechanism for looking up symbol names at
>> runtime.
>>
>> There was some (seemingly?) leftover code for symbols lookups in
>> common/kallsyms.c and associated parts in the makefile, however it
>> appears to be entirely unused and unsupported. It relied on generating
>> one long string of all symbol addresses and names.
>>
>> The approach taken here is instead largely based on the implementation
>> in the Xen hypervisor, it performs basic compression using non-ASCII
>> bytes to tokenize repeated string segments which can later be expanded
>> back out at runtime.
>>
>> This is then utilized in the ARM64 interrupt handling routine to dump a
>> backtrace in the show_regs() debug function. As well as providing a
>> general purpose unwind_stack() function which can be used for debugging.
> 
> Just a few minor comments from me in general, and I'm glad to see this.
> Please submit the next version non-RFC, thanks.

Thanks for the review.

One thing I'm a little unsure about before sending the next version: is 
it better to print the address in the link register or the address of 
the function in the backtrace?

In the example below I print the function address offset by _start, but 
that doesn't seem very useful for either interactive debugging or 
decompilation. Maybe the absolute address in the link register would be 
more useful.

I'm leaning towards the latter, but open to ideas.

Backtrace:
         <0x0000000001bb4c> do_mem_mw+0xbc
         <0x000000bb729cec> cmd_process+0x130
         <0x000000bb7213f8> run_list_real+0x6d0
         <0x000000bb721b08> parse_stream_outer+0x14c
         <0x000000bb722164> parse_file_outer+0x34
         <0x000000bb72929c> cli_loop+0x1c
         <0x000000bb71f1dc> main_loop+0x54
         <0x000000bb7229dc> run_main_loop+0x14
         <0x000000bb777664> initcall_run_list+0x7c
         <0x000000bb722bf8> board_init_r+0x34
>