Skip to content

Conversation

mkeeter
Copy link
Contributor

@mkeeter mkeeter commented Oct 2, 2025

Fixes oxidecomputer/hubris#2236

Functions defined with naked_asm do not have unwind info (see also rust-lang/rust#146736). For tasks which are in a syscall stub, this prevents our stack unwinder from making any progress: it can't get the unwind info for the bottom stack frame, so can't walk up the stack at all.

This PR adds a new function stack_syscall which assumes that we're at a syscall, and begins stack walking one frame up to escape the tarpit: we use LR as the program counter, and populate register values based on the pushes at syscall entry. We then prepend a synthetic stack frame with details about the syscall stub, since we can get its name from ELF tables.

stack_syscall is called if the normal hubris.stack(..) call fails, but we did get registers (indicating that there wasn't a stack overflow). In practice, it blends in well:

$ humility -d humility-bin/tests/cmd/cores/hubris.core.new-compiler tasks -sl user_leds
system time = 6611
ID TASK                       GEN PRI STATE
 2 user_leds                    0   5 recv, notif: timer
   |
   +--->  0x240019a0 0x080091dc userlib::sys_recv_stub <-- this is the synthetic stack frame
          0x24001a00 0x08009323 userlib::sys_recv
                     @ /hubris/sys/userlib/src/lib.rs:320:8
          0x24001a00 0x08009323 idol_runtime::dispatch
                     @ /git/idolatry-25cdcedc9b4829b2/f67fffe/runtime/src/lib.rs:237:20
          0x24001a00 0x08009323 main
                     @ /hubris/drv/user-leds/src/main.rs:206:9

Comment on lines +520 to +522
let Some(pushed) = hubris.syscall_pushes_at(*pc) else {
bail!("could not find syscall pushes at {pc:#x?}");
};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

bail vs anyhow?

Copy link
Contributor Author

@mkeeter mkeeter Oct 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think bail is correct, because it builds + returns the error. anyhow just builds the error, so it would be more verbose (return anyhow!(..)).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh yeah I think I have convinced myself that bail actually means "exit the program with this error" which is not actually true because we actually handle the error with the .or_else above

@mkeeter mkeeter force-pushed the mkeeter/fix-backtraces branch from f38b03c to a880720 Compare October 2, 2025 19:39
@mkeeter mkeeter enabled auto-merge (squash) October 2, 2025 19:40
@mkeeter mkeeter merged commit 0da567a into master Oct 2, 2025
11 checks passed
@mkeeter mkeeter deleted the mkeeter/fix-backtraces branch October 3, 2025 19:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Stack traces are broken after compiler bump
2 participants