Stacks

Aerology currently supports 2 subcommands that help with looking through stacks: stacks for a summary of the filled-level of all thread stacks Aerology can find, and backtrace for backtracing all stacks in the system.

stacks subcommand

The stacks subcommand renders a pretty version of stack usage in a table format:

$ aerology stacks dhcpv4_client.core.0
Key: █: currently in use ▒: used in the past ░: never used
name                 used    max   size
zephyr::logging       32b    32b   768b ░░░
zephyr::shell_uart    32b    32b  2048b ░░░░░░░░
zephyr::idle 00       32b    32b   320b ░
zephyr::main          88b   216b  1024b ░░░░
tfm_s::3000bf40      312b  2440b  8192b █▒▒▒▒▒▒▒▒▒░░░░░░░░░░░░░░░░░░░░░░░░░
tfm_s::3000bf88      192b   192b  2688b ░░░░░░░░░░░
tfm_s::3000bfd0      168b   776b  2048b ▒▒▒░░░░░
tfm_s::3000c018      176b   644b  1664b ▒▒░░░░░
tfm_s::3000c060      120b   256b  1280b ▒░░░░
tfm_s::3000c0a8       72b   300b  1024b ▒░░░
tfm_s::3000c0f0       72b    20b   256b ░

This might be helpful for determining the maximum stack usage of a given thread, for example.

backtrace subcommand

The backtrace subcommand is where Aerology really shines; it backtraces all threads in the system including stacks of TFM partitions:

$ aerology backtrace dhcpv4_client.core.0
Registers
  ├─ 11008a60 in tfm_access_violation_handler
  ╞═ Exception Handler Called
  ├─ 01069bfc in smsc_init
  ├─ 01069ce3 in eth_init
  ├─ 01069fe5 in z_sys_init_run_level
  ├─ 0106a1af in bg_thread_main
  ├─ 0106bae1 in z_thread_entry
  └─ 010645e3 in arch_switch_to_main_thread
Thread zephyr::idle 00
  ├─ 0106bad4 in z_thread_entry
  └─ aaaaaaaa in <unknown>
Thread zephyr::logging
  ├─ 0106bad4 in z_thread_entry
  └─ aaaaaaaa in <unknown>
Thread zephyr::main
  ├─ 010644f8 in arch_swap
  ├─ 0106b8dd in k_sys_work_q_init
  ├─ 01069fe5 in z_sys_init_run_level
  ├─ 0106a1af in bg_thread_main
  ├─ 0106bae1 in z_thread_entry
  └─ 010645e3 in arch_switch_to_main_thread
Thread zephyr::shell_uart
  ├─ 0106bad4 in z_thread_entry
  └─ aaaaaaaa in <unknown>
Thread tfm_s::sp_crypto
  ├─ 11008e70 in tfm_arch_trigger_pendsv
  ├─ 11007ee3 in spm_interface_thread_dispatcher
  └─ 11021187 in psa_interface_unified_abi
Thread tfm_s::sp_initial_attestation
  ├─ 11008e70 in tfm_arch_trigger_pendsv
  ├─ 11007ee3 in spm_interface_thread_dispatcher
  └─ 11021187 in psa_interface_unified_abi
Thread tfm_s::sp_ps
  ├─ 11008e70 in tfm_arch_trigger_pendsv
  ├─ 11007ee3 in spm_interface_thread_dispatcher
  └─ 11021187 in psa_interface_unified_abi
Thread tfm_s::sp_its
  ├─ 11008e70 in tfm_arch_trigger_pendsv
  ├─ 11007ee3 in spm_interface_thread_dispatcher
  └─ 11021187 in psa_interface_unified_abi
Thread tfm_s::sp_platform
  ├─ 11008e70 in tfm_arch_trigger_pendsv
  ├─ 11007ee3 in spm_interface_thread_dispatcher
  └─ 11021187 in psa_interface_unified_abi
Thread tfm_s::sp_ns_agent
  └─ 11008c85 in tfm_nspm_thread_entry
Thread tfm_s::idle
  └─ 11008ca5 in tfm_idle_thread

Optionally, you can have Aerology dump the registers at each stack frame with the --regs. The following in an excert from the same backtrace with -r applied:

Thread zephyr::main
  ├─ 010644f8 in arch_swap
  │  R0  00000000 R1  01071470 R2  01071618 R3  01069ce3
  │  R4  00000000 R5  00000000 R6  01071480 R7  0106a1a1
  │  R8  01064cd8 R9  01064cd8 R10 01064cd8 R11 01064cd8
  │  R12 00000000 Sp  210037c8 Lr  0106b8dd Pc  010644f8
  │  Psr 61000000
  ├─ 0106b8dd in k_sys_work_q_init
  │  R0  00000000 R1  01071470 R2  01071618 R3  01069ce3
  │  R4  01071470 R5  00000000 R6  01071480 R7  0106a1a1
  │  R8  01064cd8 R9  01064cd8 R10 01064cd8 R11 01064cd8
  │  R12 00000000 Sp  210037e0 Lr  01069fe5 Pc  0106b8dd
  │  Psr 61000000
  ├─ 01069fe5 in z_sys_init_run_level
  │  R0  00000000 R1  01071470 R2  01071618 R3  01069ce3
  │  R4  0106a1a1 R5  21000e98 R6  21003800 R7  0106a1a1
  │  R8  01064cd8 R9  01064cd8 R10 01064cd8 R11 01064cd8
  │  R12 00000000 Sp  210037f0 Lr  0106a1af Pc  01069fe5
  │  Psr 61000000
  ├─ 0106a1af in bg_thread_main
  │  R0  00000000 R1  01071470 R2  01071618 R3  00000000
  │  R4  0106a1a1 R5  21000e98 R6  21003800 R7  0106a1a1
  │  R8  01064cd8 R9  01064cd8 R10 01064cd8 R11 01064cd8
  │  R12 00000000 Sp  210037f8 Lr  0106bae1 Pc  0106a1af
  │  Psr 61000000
  ├─ 0106bae1 in z_thread_entry
  │  R0  00000000 R1  01071470 R2  01071618 R3  00000000
  │  R4  0106a1a1 R5  21000e98 R6  21003800 R7  0106a1a1
  │  R8  01064cd8 R9  01064cd8 R10 01064cd8 R11 01064cd8
  │  R12 00000000 Sp  21003800 Lr  010645e3 Pc  0106bae1
  │  Psr 61000000
  └─ 010645e3 in arch_switch_to_main_thread
     R0  00000000 R1  01071470 R2  01071618 R3  00000000
     R4  0106a1a1 R5  21000e98 R6  21003800 R7  0106a1a1
     R8  01064cd8 R9  01064cd8 R10 01064cd8 R11 01064cd8
     R12 00000000 Sp  21003800 Lr  010645e3 Pc  010645e3
     Psr 61000000

Since each stack frame takes up 6 lines instead of 1, all of the backtraces together becomes quite long.