diff --git a/cranelift/codegen/meta/src/shared/settings.rs b/cranelift/codegen/meta/src/shared/settings.rs index 0f344d25e9..286a98be49 100644 --- a/cranelift/codegen/meta/src/shared/settings.rs +++ b/cranelift/codegen/meta/src/shared/settings.rs @@ -237,6 +237,19 @@ pub(crate) fn define() -> SettingGroup { true, ); + settings.add_bool( + "preserve_frame_pointers", + "Preserve frame pointers", + r#" + Preserving frame pointers -- even inside leaf functions -- makes it + easy to capture the stack of a running program, without requiring any + side tables or metadata (like `.eh_frame` sections). Many sampling + profilers and similar tools walk frame pointers to capture stacks. + Enabling this option will play nice with those tools. + "#, + false, + ); + settings.add_bool( "machine_code_cfg_info", "Generate CFG metadata for machine code.", @@ -324,7 +337,7 @@ pub(crate) fn define() -> SettingGroup { for the out-of-bounds case, a misspeculation of that conditional branch (falsely predicted in-bounds) will select an in-bounds index to load on the speculative path. - + This option is enabled by default because it is highly recommended for secure sandboxing. The embedder should consider the security implications carefully before disabling this option. diff --git a/cranelift/codegen/src/machinst/abi_impl.rs b/cranelift/codegen/src/machinst/abi_impl.rs index 718871e827..3d110e3a92 100644 --- a/cranelift/codegen/src/machinst/abi_impl.rs +++ b/cranelift/codegen/src/machinst/abi_impl.rs @@ -1410,12 +1410,13 @@ impl ABICallee for ABICalleeImpl { if !self.call_conv.extends_baldrdash() { self.fixed_frame_storage_size += total_stacksize; - self.setup_frame = M::is_frame_setup_needed( - self.is_leaf, - self.stack_args_size(), - clobbered_callee_saves.len(), - self.fixed_frame_storage_size, - ); + self.setup_frame = self.flags.preserve_frame_pointers() + || M::is_frame_setup_needed( + self.is_leaf, + self.stack_args_size(), + clobbered_callee_saves.len(), + self.fixed_frame_storage_size, + ); insts.extend( M::gen_debug_frame_info(self.call_conv, &self.flags, &self.isa_flags).into_iter(), diff --git a/cranelift/codegen/src/settings.rs b/cranelift/codegen/src/settings.rs index f94380ea66..8cb37ff725 100644 --- a/cranelift/codegen/src/settings.rs +++ b/cranelift/codegen/src/settings.rs @@ -541,6 +541,7 @@ enable_atomics = true enable_safepoints = false enable_llvm_abi_extensions = false unwind_info = true +preserve_frame_pointers = false machine_code_cfg_info = false emit_all_ones_funcaddrs = false enable_probestack = true diff --git a/cranelift/filetests/filetests/isa/aarch64/leaf.clif b/cranelift/filetests/filetests/isa/aarch64/leaf.clif new file mode 100644 index 0000000000..1e797eb0ec --- /dev/null +++ b/cranelift/filetests/filetests/isa/aarch64/leaf.clif @@ -0,0 +1,15 @@ +;; Test compilation of leaf functions without preserving frame pointers. + +test compile precise-output +set unwind_info=false +set preserve_frame_pointers=false +target aarch64 + +function %leaf(i64) -> i64 { +block0(v0: i64): + return v0 +} + +; block0: +; ret + diff --git a/cranelift/filetests/filetests/isa/aarch64/leaf_with_preserve_frame_pointers.clif b/cranelift/filetests/filetests/isa/aarch64/leaf_with_preserve_frame_pointers.clif new file mode 100644 index 0000000000..e61389350a --- /dev/null +++ b/cranelift/filetests/filetests/isa/aarch64/leaf_with_preserve_frame_pointers.clif @@ -0,0 +1,18 @@ +;; Test compilation of leaf functions while preserving frame pointers. + +test compile precise-output +set unwind_info=false +set preserve_frame_pointers=true +target aarch64 + +function %leaf(i64) -> i64 { +block0(v0: i64): + return v0 +} + +; stp fp, lr, [sp, #-16]! +; mov fp, sp +; block0: +; ldp fp, lr, [sp], #16 +; ret + diff --git a/cranelift/filetests/filetests/isa/x64/leaf.clif b/cranelift/filetests/filetests/isa/x64/leaf.clif new file mode 100644 index 0000000000..b51148f972 --- /dev/null +++ b/cranelift/filetests/filetests/isa/x64/leaf.clif @@ -0,0 +1,20 @@ +;; Test compilation of leaf functions without preserving frame pointers. + +test compile precise-output +set unwind_info=false +set preserve_frame_pointers=false +target x86_64 + +function %leaf(i64) -> i64 { +block0(v0: i64): + return v0 +} + +; pushq %rbp +; movq %rsp, %rbp +; block0: +; movq %rdi, %rax +; movq %rbp, %rsp +; popq %rbp +; ret + diff --git a/cranelift/filetests/filetests/isa/x64/leaf_with_preserve_frame_pointers.clif b/cranelift/filetests/filetests/isa/x64/leaf_with_preserve_frame_pointers.clif new file mode 100644 index 0000000000..f7aa76b742 --- /dev/null +++ b/cranelift/filetests/filetests/isa/x64/leaf_with_preserve_frame_pointers.clif @@ -0,0 +1,20 @@ +;; Test compilation of leaf functions while preserving frame pointers. + +test compile precise-output +set unwind_info=false +set preserve_frame_pointers=true +target x86_64 + +function %leaf(i64) -> i64 { +block0(v0: i64): + return v0 +} + +; pushq %rbp +; movq %rsp, %rbp +; block0: +; movq %rdi, %rax +; movq %rbp, %rsp +; popq %rbp +; ret + diff --git a/crates/wasmtime/src/engine.rs b/crates/wasmtime/src/engine.rs index c644d742dc..b21a08e8f0 100644 --- a/crates/wasmtime/src/engine.rs +++ b/crates/wasmtime/src/engine.rs @@ -393,6 +393,7 @@ impl Engine { | "machine_code_cfg_info" | "tls_model" // wasmtime doesn't use tls right now | "opt_level" // opt level doesn't change semantics + | "preserve_frame_pointers" // we don't currently rely on frame pointers | "enable_alias_analysis" // alias analysis-based opts don't change semantics | "probestack_func_adjusts_sp" // probestack above asserted disabled | "probestack_size_log2" // probestack above asserted disabled