Skip to content

Cranelift: RISCV frame pointer position differs from LLVM #10281

Open
@JonasKruckenberg

Description

@JonasKruckenberg

Cranelift on RISCV (when frame pointers are enabled) generated code where the fp register always points to the next frame pointer like so:

----  frame ----
ra,
fp,   <- fp points here
...
---- frame ----

while LLVM generates code where fp points one word above the frame like so:

----  frame ---- <- fp points here
ra,
fp,
...
---- frame ----

While this is not a problem in isolation it means that stack walkers (for backtraces, perf stack traces, unwinding) cannot walk across a boundary where LLVM generated code calls cranelift generated code and vice-versa.

Since we cannot really change LLVMs behavior cranelift should match LLVM even though that means a really nasty breaking change for cranelift consumers that rely on the frame pointer position (nasty since code would continue to compile just be broken at runtime in weird ways).

AFAIK supporting this change in wasmtime would be quite trivial, it would just mean changing this from 0 to -2 * size_of::<usize>()

pub const NEXT_OLDER_FP_FROM_FP_OFFSET: usize = 0;

which would mean this assertion no longer holds
assert_eq!(unwind.next_older_fp_from_fp_offset(), 0);

and the corresponding code in save_last_wasm_exit_fp_pc needs to be adjusted
// The FP always points to the next older FP for all supported
// targets. See assertion in
// `crates/wasmtime/src/runtime/vm/traphandlers/backtrace.rs`.
0,

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugIncorrect behavior in the current implementation that needs fixingcraneliftIssues related to the Cranelift code generatorcranelift:area:debugcranelift:area:riscv64Issues related to the RISC-V 64 backend.wasmtime:debuggingIssues related to debugging of JIT'ed code

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions