Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

wrong return address in @panic on riscv+freestanding #22436

Open
benburkert opened this issue Jan 6, 2025 · 3 comments
Open

wrong return address in @panic on riscv+freestanding #22436

benburkert opened this issue Jan 6, 2025 · 3 comments
Labels
bug Observed behavior contradicts documented or intended behavior

Comments

@benburkert
Copy link

Zig Version

0.14.0-dev.2613+0bf44c309

Steps to Reproduce and Observed Behavior

This repo has a reproduction: https://github.com/benburkert/freestanding.zig

$ git clone https://github.com/benburkert/freestanding.zig && cd freestanding.zig
$ cd examples/riscv-stacktrace
$ zig build run

(requires qemu with qemu-system-riscv64)

The stacktrace has the anonymous panic function instead of root.bang because the return address is incorrect when the panic handler runs:

$ zig build run
panic: kaboom!
         /Users/benburkert/.asdf/installs/zig/master/lib/std/debug.zig:0422:000: 0x8002fbe6 in panic__anon_8196 (riscv-stacktrace)
/Users/benburkert/src/github.com/benburkert/freestanding.zig/examples/riscv-stacktrace/src/root.zig:0042:009: 0x8002fbce in bar (riscv-stacktrace)
/Users/benburkert/src/github.com/benburkert/freestanding.zig/examples/riscv-stacktrace/src/root.zig:0038:008: 0x8002fbb6 in foo (riscv-stacktrace)
/Users/benburkert/src/github.com/benburkert/freestanding.zig/examples/riscv-stacktrace/src/root.zig:0034:008: 0x8002fb9e in main (riscv-stacktrace)
/Users/benburkert/src/github.com/benburkert/freestanding.zig/examples/riscv-stacktrace/src/root.zig:0030:009: 0x8002fb86 in start (riscv-stacktrace)
/Users/benburkert/src/github.com/benburkert/freestanding.zig/examples/riscv-stacktrace/src/root.zig:0019:005: 0x80000010 in _start (riscv-stacktrace)

Expected Behavior

The stacktrace should start with root.bang instead of panic__anon_8196.

@benburkert benburkert added the bug Observed behavior contradicts documented or intended behavior label Jan 6, 2025
@benburkert
Copy link
Author

I think the panic is causing the compiler to compile root.bang as noreturn, which is causing the corrupted return address. For some additional context, here is some of the dissablembly:

000000008002fbbe <root.bar>:
    8002fbbe:   1141                    addi    sp,sp,-16
...
    8002fbc6:   00000097                auipc   ra,0x0
    8002fbca:   010080e7                jalr    16(ra) # 8002fbd6 <root.bang>
    8002fbce:   60a2                    ld      ra,8(sp)
    8002fbd0:   6402                    ld      s0,0(sp)
    8002fbd2:   0141                    addi    sp,sp,16
    8002fbd4:   8082                    ret

000000008002fbd6 <root.bang>:
    8002fbd6:   1141                    addi    sp,sp,-16
    8002fbd8:   e406                    sd      ra,8(sp)
    8002fbda:   e022                    sd      s0,0(sp)
    8002fbdc:   0800                    addi    s0,sp,16
    8002fbde:   00000097                auipc   ra,0x0
    8002fbe2:   008080e7                jalr    8(ra) # 8002fbe6 <debug.panic__anon_8196>

000000008002fbe6 <debug.panic__anon_8196>:
    8002fbe6:   714d                    addi    sp,sp,-336
...
    8002fc0c:   00000097                auipc   ra,0x0
    8002fc10:   044080e7                jalr    68(ra) # 8002fc50 <debug.errorReturnTraceHelper>
...

The ra after 8002fbe2 is 8002fbe6 (same as pc), which causes the stacktrace to not include root.bang.

Is the lack of epilogue instructions after 8002fbe2 the cause of the bad return address?

This happens for both @panic and std.debug.panic: the ra updates to the next instruction after the jalr in root.bang, which ends up being the preamble of the next function.

@benburkert
Copy link
Author

making the panic runtime conditional produces the expected stacktrace:

$ zig build run
panic: kaboom!
/Users/benburkert/src/github.com/benburkert/freestanding.zig/examples/riscv-stacktrace/src/root.zig:0049:024: 0x8002fc00 in bang (riscv-stacktrace)
/Users/benburkert/src/github.com/benburkert/freestanding.zig/examples/riscv-stacktrace/src/root.zig:0042:009: 0x8002fbce in bar (riscv-stacktrace)
/Users/benburkert/src/github.com/benburkert/freestanding.zig/examples/riscv-stacktrace/src/root.zig:0038:008: 0x8002fbb6 in foo (riscv-stacktrace)
/Users/benburkert/src/github.com/benburkert/freestanding.zig/examples/riscv-stacktrace/src/root.zig:0034:008: 0x8002fb9e in main (riscv-stacktrace)
/Users/benburkert/src/github.com/benburkert/freestanding.zig/examples/riscv-stacktrace/src/root.zig:0030:009: 0x8002fb86 in start (riscv-stacktrace)
/Users/benburkert/src/github.com/benburkert/freestanding.zig/examples/riscv-stacktrace/src/root.zig:0019:005: 0x80000010 in _start (riscv-stacktrace)

And the disassembly includes a function epilogue:

000000008002fbd6 <root.bang>:
    8002fbd6:   1141                    addi    sp,sp,-16
    8002fbd8:   e406                    sd      ra,8(sp)
    8002fbda:   e022                    sd      s0,0(sp)
    8002fbdc:   0800                    addi    s0,sp,16

000000008002fbde <.Lpcrel_hi1359>:
    8002fbde:   0001b517                auipc   a0,0x1b
    8002fbe2:   42a50513                addi    a0,a0,1066 # 8004b008 <root.one>
    8002fbe6:   6108                    ld      a0,0(a0)
    8002fbe8:   4585                    li      a1,1
    8002fbea:   00b50763                beq     a0,a1,8002fbf8 <.Lpcrel_hi1359+0x1a>
    8002fbee:   a809                    j       8002fc00 <.Lpcrel_hi1359+0x22>
    8002fbf0:   60a2                    ld      ra,8(sp)
    8002fbf2:   6402                    ld      s0,0(sp)
    8002fbf4:   0141                    addi    sp,sp,16
    8002fbf6:   8082                    ret
    8002fbf8:   00000097                auipc   ra,0x0
    8002fbfc:   00a080e7                jalr    10(ra) # 8002fc02 <debug.panic__anon_8198>
    8002fc00:   bfc5                    j       8002fbf0 <.Lpcrel_hi1359+0x12>

000000008002fc02 <debug.panic__anon_8198>:
    8002fc02:   714d                    addi    sp,sp,-336
    8002fc04:   e686                    sd      ra,328(sp)
    8002fc06:   e2a2                    sd      s0,320(sp)
    8002fc08:   0a80                    addi    s0,sp,336
...

@0xfacadeull
Copy link
Contributor

0xfacadeull commented Jan 9, 2025

The return address stored by the jalr instruction is the address of the subsequent instruction (pc + 4), so the return addresses are correct.

Your call stack trace implementation is displaying these return addresses, whereas your intent might be to display the addresses of the instruction that caused the call, which is the previous instruction return_address - 4.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior
Projects
None yet
Development

No branches or pull requests

2 participants