diff --git a/Cargo.lock b/Cargo.lock index f90a90431b30..506975af0416 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4010,6 +4010,7 @@ dependencies = [ "wasmparser 0.107.0", "wasmtime-cranelift-shared", "wasmtime-environ", + "wasmtime-versioned-export-macros", ] [[package]] @@ -4086,6 +4087,7 @@ dependencies = [ "cfg-if", "rustix", "wasmtime-asm-macros", + "wasmtime-versioned-export-macros", "windows-sys 0.48.0", ] @@ -4175,6 +4177,7 @@ dependencies = [ "object", "once_cell", "rustix", + "wasmtime-versioned-export-macros", ] [[package]] @@ -4209,6 +4212,7 @@ dependencies = [ "wasmtime-environ", "wasmtime-fiber", "wasmtime-jit-debug", + "wasmtime-versioned-export-macros", "windows-sys 0.48.0", ] @@ -4222,6 +4226,15 @@ dependencies = [ "wasmparser 0.107.0", ] +[[package]] +name = "wasmtime-versioned-export-macros" +version = "12.0.0" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.16", +] + [[package]] name = "wasmtime-wasi" version = "12.0.0" diff --git a/Cargo.toml b/Cargo.toml index 42cacff034ad..fdc14b7aafdc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -145,6 +145,7 @@ wasmtime-wasi-threads = { path = "crates/wasi-threads", version = "12.0.0" } wasmtime-component-util = { path = "crates/component-util", version = "=12.0.0" } wasmtime-component-macro = { path = "crates/component-macro", version = "=12.0.0" } wasmtime-asm-macros = { path = "crates/asm-macros", version = "=12.0.0" } +wasmtime-versioned-export-macros = { path = "crates/versioned-export-macros", version = "=12.0.0" } component-test-util = { path = "crates/misc/component-test-util" } component-fuzz-util = { path = "crates/misc/component-fuzz-util" } wiggle = { path = "crates/wiggle", version = "=12.0.0", default-features = false } diff --git a/crates/cranelift/Cargo.toml b/crates/cranelift/Cargo.toml index 40a0a9bfc2d6..1de960f2f41d 100644 --- a/crates/cranelift/Cargo.toml +++ b/crates/cranelift/Cargo.toml @@ -26,6 +26,7 @@ target-lexicon = { workspace = true } gimli = { workspace = true } object = { workspace = true, features = ['write'] } thiserror = { workspace = true } +wasmtime-versioned-export-macros = { workspace = true } [features] all-arch = ["cranelift-codegen/all-arch"] diff --git a/crates/cranelift/src/debug/transform/unit.rs b/crates/cranelift/src/debug/transform/unit.rs index 1b220097c43e..eefed56d071b 100644 --- a/crates/cranelift/src/debug/transform/unit.rs +++ b/crates/cranelift/src/debug/transform/unit.rs @@ -15,6 +15,7 @@ use gimli::write; use gimli::{AttributeValue, DebuggingInformationEntry, Unit}; use std::collections::HashSet; use wasmtime_environ::DefinedFuncIndex; +use wasmtime_versioned_export_macros::versioned_stringify_ident; struct InheritedAttr { stack: Vec<(usize, T)>, @@ -198,7 +199,7 @@ where // .. .. DW_AT_type = // .. .. DW_AT_artificial = 1 add_tag!(wrapper_die_id, gimli::DW_TAG_subprogram => deref_op_die as deref_op_die_id { - gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add("resolve_vmctx_memory_ptr")), + gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add(versioned_stringify_ident!(resolve_vmctx_memory_ptr))), gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("ptr")), gimli::DW_AT_type = write::AttributeValue::UnitRef(ptr_type_id) }); @@ -215,7 +216,7 @@ where // .. .. DW_AT_type = // .. .. DW_AT_artificial = 1 add_tag!(wrapper_die_id, gimli::DW_TAG_subprogram => deref_op_die as deref_op_die_id { - gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add("resolve_vmctx_memory_ptr")), + gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add(versioned_stringify_ident!(resolve_vmctx_memory_ptr))), gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("operator*")), gimli::DW_AT_type = write::AttributeValue::UnitRef(ref_type_id) }); @@ -232,7 +233,7 @@ where // .. .. DW_AT_type = // .. .. DW_AT_artificial = 1 add_tag!(wrapper_die_id, gimli::DW_TAG_subprogram => deref_op_die as deref_op_die_id { - gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add("resolve_vmctx_memory_ptr")), + gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add(versioned_stringify_ident!(resolve_vmctx_memory_ptr))), gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("operator->")), gimli::DW_AT_type = write::AttributeValue::UnitRef(ptr_type_id) }); diff --git a/crates/cranelift/src/debug/transform/utils.rs b/crates/cranelift/src/debug/transform/utils.rs index 161612812528..0ffd19062490 100644 --- a/crates/cranelift/src/debug/transform/utils.rs +++ b/crates/cranelift/src/debug/transform/utils.rs @@ -6,8 +6,8 @@ use anyhow::Error; use cranelift_codegen::isa::TargetIsa; use gimli::write; use wasmtime_environ::DefinedFuncIndex; - -/// Adds internal Wasm utility types DIEs such as WebAssemblyPtr and +use wasmtime_versioned_export_macros::versioned_stringify_ident; +///Adds internal Wasm utility types DIEs such as WebAssemblyPtr and /// WasmtimeVMContext. /// /// For unwrapping Wasm pointer, the WasmtimeVMContext has the `set()` method @@ -113,7 +113,7 @@ pub(crate) fn add_internal_types( // .. .. DW_AT_type = // .. .. DW_AT_artificial = 1 add_tag!(vmctx_die_id, gimli::DW_TAG_subprogram => vmctx_set as vmctx_set_id { - gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add("set_vmctx_memory")), + gimli::DW_AT_linkage_name = write::AttributeValue::StringRef(out_strings.add(versioned_stringify_ident!(set_vmctx_memory))), gimli::DW_AT_name = write::AttributeValue::StringRef(out_strings.add("set")) }); add_tag!(vmctx_set_id, gimli::DW_TAG_formal_parameter => vmctx_set_this_param as vmctx_set_this_param_id { diff --git a/crates/fiber/Cargo.toml b/crates/fiber/Cargo.toml index e2acc6c0f444..f62c2f2fb689 100644 --- a/crates/fiber/Cargo.toml +++ b/crates/fiber/Cargo.toml @@ -7,14 +7,9 @@ license = "Apache-2.0 WITH LLVM-exception" repository = "https://github.com/bytecodealliance/wasmtime" edition.workspace = true -# We link to some native code with symbols that don't change often, so let Cargo -# know that we can't show up multiple times in a crate graph. If this is an -# issue in the future we should tweak the build script to set `#define` -# directives or similar to embed a version number of this crate in symbols. -links = "wasmtime-fiber-shims" - [dependencies] cfg-if = { workspace = true } +wasmtime-versioned-export-macros = { workspace = true } [target.'cfg(unix)'.dependencies] rustix = { workspace = true, features = ["mm", "param"] } @@ -29,6 +24,7 @@ features = [ [build-dependencies] cc = "1.0" +wasmtime-versioned-export-macros = { workspace = true } [dev-dependencies] backtrace = "0.3.61" diff --git a/crates/fiber/build.rs b/crates/fiber/build.rs index 6bfc5c4b9daa..079a58167617 100644 --- a/crates/fiber/build.rs +++ b/crates/fiber/build.rs @@ -1,4 +1,5 @@ use std::env; +use wasmtime_versioned_export_macros::versioned_suffix; fn main() { let mut build = cc::Build::new(); @@ -7,9 +8,11 @@ fn main() { if os == "windows" { println!("cargo:rerun-if-changed=src/windows.c"); build.file("src/windows.c"); + build.define("VERSIONED_SUFFIX", Some(versioned_suffix!())); } else if arch == "s390x" { println!("cargo:rerun-if-changed=src/unix/s390x.S"); build.file("src/unix/s390x.S"); + build.define("VERSIONED_SUFFIX", Some(versioned_suffix!())); } else { // assume that this is included via inline assembly in the crate itself, // and the crate will otherwise have a `compile_error!` for unsupported diff --git a/crates/fiber/src/unix.rs b/crates/fiber/src/unix.rs index ef0ddea6b8fe..b148ff324bca 100644 --- a/crates/fiber/src/unix.rs +++ b/crates/fiber/src/unix.rs @@ -117,13 +117,16 @@ pub struct Fiber; pub struct Suspend(*mut u8); extern "C" { + #[wasmtime_versioned_export_macros::versioned_link] fn wasmtime_fiber_init( top_of_stack: *mut u8, entry: extern "C" fn(*mut u8, *mut u8), entry_arg0: *mut u8, ); + #[wasmtime_versioned_export_macros::versioned_link] fn wasmtime_fiber_switch(top_of_stack: *mut u8); #[allow(dead_code)] // only used in inline assembly for some platforms + #[wasmtime_versioned_export_macros::versioned_link] fn wasmtime_fiber_start(); } diff --git a/crates/fiber/src/unix/aarch64.rs b/crates/fiber/src/unix/aarch64.rs index d77b1f2fbe25..92a09c24b0b1 100644 --- a/crates/fiber/src/unix/aarch64.rs +++ b/crates/fiber/src/unix/aarch64.rs @@ -39,7 +39,7 @@ cfg_if::cfg_if! { // fn(top_of_stack(%x0): *mut u8) asm_func!( - "wasmtime_fiber_switch", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_switch), concat!( " .cfi_startproc @@ -114,7 +114,7 @@ asm_func!( // wasmtime_fiber_start(), and provides wider coverage. #[rustfmt::skip] asm_func!( - "wasmtime_fiber_init", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_init), concat!( " .cfi_startproc @@ -144,7 +144,7 @@ asm_func!( // doing. Like over there note that the relative offsets to registers here // match the frame layout in `wasmtime_fiber_switch`. asm_func!( - "wasmtime_fiber_start", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_start), " .cfi_startproc simple .cfi_def_cfa_offset 0 diff --git a/crates/fiber/src/unix/arm.rs b/crates/fiber/src/unix/arm.rs index 1d320fd1f85e..c2b3c0f0b248 100644 --- a/crates/fiber/src/unix/arm.rs +++ b/crates/fiber/src/unix/arm.rs @@ -12,7 +12,7 @@ use wasmtime_asm_macros::{asm_func, asm_sym}; // fn(top_of_stack(%r0): *mut u8) asm_func!( - "wasmtime_fiber_switch", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_switch), " // Save callee-saved registers push {{r4-r11,lr}} @@ -34,7 +34,7 @@ asm_func!( // entry_arg0(%r2): *mut u8, // ) asm_func!( - "wasmtime_fiber_init", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_init), " adr r3, wasmtime_fiber_start str r3, [r0, #-0x0c] // => lr @@ -49,7 +49,7 @@ asm_func!( ); asm_func!( - "wasmtime_fiber_start", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_start), " .cfi_startproc simple .cfi_def_cfa_offset 0 diff --git a/crates/fiber/src/unix/riscv64.rs b/crates/fiber/src/unix/riscv64.rs index 9c7b0cb01f0e..61966f7b3f05 100644 --- a/crates/fiber/src/unix/riscv64.rs +++ b/crates/fiber/src/unix/riscv64.rs @@ -9,7 +9,7 @@ use wasmtime_asm_macros::asm_func; // fn(top_of_stack(rdi): *mut u8) asm_func!( - "wasmtime_fiber_switch", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_switch), " // See https://github.com/rust-lang/rust/issues/80608. .attribute arch, \"rv64gc\" @@ -90,7 +90,7 @@ asm_func!( // ) #[rustfmt::skip] asm_func!( - "wasmtime_fiber_init", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_init), " lla t0,{} sd t0,-0x18(a0) // ra,first should be wasmtime_fiber_start. @@ -107,7 +107,7 @@ asm_func!( ); asm_func!( - "wasmtime_fiber_start", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_start), " .cfi_startproc simple .cfi_def_cfa_offset 0 diff --git a/crates/fiber/src/unix/s390x.S b/crates/fiber/src/unix/s390x.S index a5a47118bedb..4207fcb70c1d 100644 --- a/crates/fiber/src/unix/s390x.S +++ b/crates/fiber/src/unix/s390x.S @@ -10,11 +10,14 @@ .text -#define GLOBL(fnname) .globl fnname -#define HIDDEN(fnname) .hidden fnname -#define TYPE(fnname) .type fnname,@function -#define FUNCTION(fnname) fnname -#define SIZE(fnname) .size fnname,.-fnname +#define CONCAT2(a, b) a ## b +#define CONCAT(a, b) CONCAT2(a , b) +#define VERSIONED_SYMBOL(a) CONCAT(a, VERSIONED_SUFFIX) +#define GLOBL(fnname) .globl VERSIONED_SYMBOL(fnname) +#define HIDDEN(fnname) .hidden VERSIONED_SYMBOL(fnname) +#define TYPE(fnname) .type VERSIONED_SYMBOL(fnname),@function +#define FUNCTION(fnname) VERSIONED_SYMBOL(fnname) +#define SIZE(fnname) .size VERSIONED_SYMBOL(fnname),.-VERSIONED_SYMBOL(fnname) // fn(top_of_stack(%x0): *mut u8) HIDDEN(wasmtime_fiber_switch) diff --git a/crates/fiber/src/unix/x86_64.rs b/crates/fiber/src/unix/x86_64.rs index 420111c04361..15e4fd57a99f 100644 --- a/crates/fiber/src/unix/x86_64.rs +++ b/crates/fiber/src/unix/x86_64.rs @@ -9,7 +9,7 @@ use wasmtime_asm_macros::asm_func; // fn(top_of_stack(rdi): *mut u8) asm_func!( - "wasmtime_fiber_switch", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_switch), " // We're switching to arbitrary code somewhere else, so pessimistically // assume that all callee-save register are clobbered. This means we need @@ -49,7 +49,7 @@ asm_func!( // ) #[rustfmt::skip] asm_func!( - "wasmtime_fiber_init", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_init), " // Here we're going to set up a stack frame as expected by // `wasmtime_fiber_switch`. The values we store here will get restored into @@ -89,7 +89,7 @@ asm_func!( // If you're curious a decent introduction to CFI things and unwinding is at // https://www.imperialviolet.org/2017/01/18/cfi.html asm_func!( - "wasmtime_fiber_start", + wasmtime_versioned_export_macros::versioned_stringify_ident!(wasmtime_fiber_start), " // Use the `simple` directive on the startproc here which indicates that // some default settings for the platform are omitted, since this diff --git a/crates/fiber/src/windows.c b/crates/fiber/src/windows.c index 9e017f9b0260..9d4176eb1b7b 100644 --- a/crates/fiber/src/windows.c +++ b/crates/fiber/src/windows.c @@ -1,5 +1,9 @@ #include -LPVOID wasmtime_fiber_get_current() { +#define CONCAT2(a, b) a ## b +#define CONCAT(a, b) CONCAT2(a , b) +#define VERSIONED_SYMBOL(a) CONCAT(a, VERSIONED_SUFFIX) + +LPVOID VERSIONED_SYMBOL(wasmtime_fiber_get_current)() { return GetCurrentFiber(); } diff --git a/crates/fiber/src/windows.rs b/crates/fiber/src/windows.rs index 04452bd87a90..2e09f28b7951 100644 --- a/crates/fiber/src/windows.rs +++ b/crates/fiber/src/windows.rs @@ -46,6 +46,7 @@ struct StartState { const FIBER_FLAG_FLOAT_SWITCH: u32 = 1; extern "C" { + #[wasmtime_versioned_export_macros::versioned_link] fn wasmtime_fiber_get_current() -> *mut c_void; } diff --git a/crates/jit-debug/Cargo.toml b/crates/jit-debug/Cargo.toml index 5515be10199a..85c6b6840db3 100644 --- a/crates/jit-debug/Cargo.toml +++ b/crates/jit-debug/Cargo.toml @@ -13,6 +13,7 @@ edition.workspace = true [dependencies] once_cell = { workspace = true, optional = true } object = { workspace = true, optional = true } +wasmtime-versioned-export-macros = { workspace = true } [target.'cfg(target_os = "linux")'.dependencies] rustix = { workspace = true, features = ["mm", "param", "time"], optional = true } diff --git a/crates/jit-debug/src/gdb_jit_int.rs b/crates/jit-debug/src/gdb_jit_int.rs index e887cddb0d40..87ecd7ee4dac 100644 --- a/crates/jit-debug/src/gdb_jit_int.rs +++ b/crates/jit-debug/src/gdb_jit_int.rs @@ -6,6 +6,7 @@ use once_cell::sync::Lazy; use std::pin::Pin; use std::ptr; use std::sync::Mutex; +use wasmtime_versioned_export_macros::versioned_link; #[repr(C)] struct JITCodeEntry { @@ -28,6 +29,7 @@ struct JITDescriptor { } extern "C" { + #[versioned_link] fn wasmtime_jit_debug_descriptor() -> *mut JITDescriptor; fn __jit_debug_register_code(); } diff --git a/crates/runtime/Cargo.toml b/crates/runtime/Cargo.toml index 279bc0b72e3b..b32291c01fc4 100644 --- a/crates/runtime/Cargo.toml +++ b/crates/runtime/Cargo.toml @@ -15,6 +15,7 @@ wasmtime-asm-macros = { workspace = true } wasmtime-environ = { workspace = true } wasmtime-fiber = { workspace = true, optional = true } wasmtime-jit-debug = { workspace = true, features = ["gdb_jit_int"] } +wasmtime-versioned-export-macros = { workspace = true } libc = { version = "0.2.112", default-features = false } log = { workspace = true } memoffset = "0.8.0" @@ -50,6 +51,7 @@ once_cell = { workspace = true } [build-dependencies] cc = "1.0" +wasmtime-versioned-export-macros = { workspace = true } [features] async = ["wasmtime-fiber"] diff --git a/crates/runtime/build.rs b/crates/runtime/build.rs index 5cf6326b3219..571f0c4b2267 100644 --- a/crates/runtime/build.rs +++ b/crates/runtime/build.rs @@ -1,4 +1,5 @@ use std::env; +use wasmtime_versioned_export_macros::versioned_suffix; fn main() { let mut build = cc::Build::new(); @@ -7,6 +8,7 @@ fn main() { let os = env::var("CARGO_CFG_TARGET_OS").unwrap(); build.define(&format!("CFG_TARGET_OS_{}", os), None); build.define(&format!("CFG_TARGET_ARCH_{}", arch), None); + build.define("VERSIONED_SUFFIX", Some(versioned_suffix!())); if arch == "s390x" { println!("cargo:rerun-if-changed=src/trampolines/s390x.S"); build.file("src/trampolines/s390x.S"); diff --git a/crates/runtime/src/debug_builtins.rs b/crates/runtime/src/debug_builtins.rs index 9e7ef295a374..82ac1cf37609 100644 --- a/crates/runtime/src/debug_builtins.rs +++ b/crates/runtime/src/debug_builtins.rs @@ -3,10 +3,11 @@ use crate::instance::Instance; use crate::vmcontext::VMContext; use wasmtime_environ::{EntityRef, MemoryIndex}; +use wasmtime_versioned_export_macros::versioned_export; static mut VMCTX_AND_MEMORY: (*mut VMContext, usize) = (std::ptr::null_mut(), 0); -#[no_mangle] +#[versioned_export] pub unsafe extern "C" fn resolve_vmctx_memory(ptr: usize) -> *const u8 { Instance::from_vmctx(VMCTX_AND_MEMORY.0, |handle| { assert!( @@ -19,7 +20,7 @@ pub unsafe extern "C" fn resolve_vmctx_memory(ptr: usize) -> *const u8 { }) } -#[no_mangle] +#[versioned_export] pub unsafe extern "C" fn resolve_vmctx_memory_ptr(p: *const u32) -> *const u8 { let ptr = std::ptr::read(p); assert!( @@ -37,7 +38,7 @@ pub unsafe extern "C" fn resolve_vmctx_memory_ptr(p: *const u32) -> *const u8 { }) } -#[no_mangle] +#[versioned_export] pub unsafe extern "C" fn set_vmctx_memory(vmctx_ptr: *mut VMContext) { // TODO multi-memory VMCTX_AND_MEMORY = (vmctx_ptr, 0); diff --git a/crates/runtime/src/helpers.c b/crates/runtime/src/helpers.c index 96019669de63..e3c9bb58240b 100644 --- a/crates/runtime/src/helpers.c +++ b/crates/runtime/src/helpers.c @@ -42,7 +42,11 @@ typedef void *platform_jmp_buf[5]; // this is the documented size; see the docs #endif -int wasmtime_setjmp( +#define CONCAT2(a, b) a ## b +#define CONCAT(a, b) CONCAT2(a , b) +#define VERSIONED_SYMBOL(a) CONCAT(a, VERSIONED_SUFFIX) + +int VERSIONED_SYMBOL(wasmtime_setjmp)( void **buf_storage, void (*body)(void*, void*), void *payload, @@ -56,7 +60,7 @@ int wasmtime_setjmp( return 1; } -void wasmtime_longjmp(void *JmpBuf) { +void VERSIONED_SYMBOL(wasmtime_longjmp)(void *JmpBuf) { platform_jmp_buf *buf = (platform_jmp_buf*) JmpBuf; platform_longjmp(*buf, 1); } @@ -99,6 +103,6 @@ struct JITDescriptor __jit_debug_descriptor = {1, 0, NULL, NULL}; -struct JITDescriptor* wasmtime_jit_debug_descriptor() { +struct JITDescriptor* VERSIONED_SYMBOL(wasmtime_jit_debug_descriptor)() { return &__jit_debug_descriptor; } diff --git a/crates/runtime/src/libcalls.rs b/crates/runtime/src/libcalls.rs index 9b133d3cc8c1..a4b4db518026 100644 --- a/crates/runtime/src/libcalls.rs +++ b/crates/runtime/src/libcalls.rs @@ -91,6 +91,7 @@ pub mod trampolines { extern "C" { #[allow(missing_docs)] #[allow(improper_ctypes)] + #[wasmtime_versioned_export_macros::versioned_link] pub fn $name( vmctx: *mut VMContext, $( $pname: libcall!(@ty $param), )* @@ -109,7 +110,7 @@ pub mod trampolines { // the `sym` operator to get the symbol here, but other targets // like s390x need to use outlined assembly files which requires // `no_mangle`. - #[cfg_attr(target_arch = "s390x", no_mangle)] + #[cfg_attr(target_arch = "s390x", wasmtime_versioned_export_macros::versioned_export)] unsafe extern "C" fn []( vmctx: *mut VMContext, $( $pname : libcall!(@ty $param), )* diff --git a/crates/runtime/src/trampolines/aarch64.rs b/crates/runtime/src/trampolines/aarch64.rs index 80edd8ae5a89..29852bad1ae1 100644 --- a/crates/runtime/src/trampolines/aarch64.rs +++ b/crates/runtime/src/trampolines/aarch64.rs @@ -2,7 +2,7 @@ macro_rules! wasm_to_libcall_trampoline { ($libcall:ident ; $libcall_impl:ident) => { wasmtime_asm_macros::asm_func!( - stringify!($libcall), + wasmtime_versioned_export_macros::versioned_stringify_ident!($libcall), " .cfi_startproc bti c diff --git a/crates/runtime/src/trampolines/riscv64.rs b/crates/runtime/src/trampolines/riscv64.rs index 456800594367..e3b06863b217 100644 --- a/crates/runtime/src/trampolines/riscv64.rs +++ b/crates/runtime/src/trampolines/riscv64.rs @@ -2,7 +2,7 @@ macro_rules! wasm_to_libcall_trampoline { ($libcall:ident ; $libcall_impl:ident) => { wasmtime_asm_macros::asm_func!( - stringify!($libcall), + wasmtime_versioned_export_macros::versioned_stringify_ident!($libcall), concat!( " .cfi_startproc diff --git a/crates/runtime/src/trampolines/s390x.S b/crates/runtime/src/trampolines/s390x.S index e014e1205082..b6b8bf01d0c2 100644 --- a/crates/runtime/src/trampolines/s390x.S +++ b/crates/runtime/src/trampolines/s390x.S @@ -9,12 +9,16 @@ .type host_to_wasm_trampoline,@function .p2align 2 +#define CONCAT2(a, b) a ## b +#define CONCAT(a, b) CONCAT2(a , b) +#define VERSIONED_SYMBOL(a) CONCAT(a, VERSIONED_SUFFIX) + #define LIBCALL_TRAMPOLINE(libcall, libcall_impl) \ - .hidden libcall ; \ - .globl libcall ; \ - .type libcall,@function ; \ + .hidden VERSIONED_SYMBOL(libcall) ; \ + .globl VERSIONED_SYMBOL(libcall) ; \ + .type VERSIONED_SYMBOL(libcall),@function ; \ .p2align 2 ; \ -libcall: ; \ +VERSIONED_SYMBOL(libcall): ; \ .cfi_startproc ; \ \ /* Load the pointer to `VMRuntimeLimits` in `%r1`. */ \ @@ -28,10 +32,10 @@ libcall: ; stg %r14, 32(%r1) ; \ \ /* Tail call to the actual implementation of this libcall. */ \ - jg libcall_impl ; \ + jg VERSIONED_SYMBOL(libcall_impl) ; \ \ .cfi_endproc ; \ - .size libcall,.-libcall + .size VERSIONED_SYMBOL(libcall),.-VERSIONED_SYMBOL(libcall) LIBCALL_TRAMPOLINE(memory32_grow, impl_memory32_grow) LIBCALL_TRAMPOLINE(table_grow_func_ref, impl_table_grow_func_ref) diff --git a/crates/runtime/src/trampolines/x86_64.rs b/crates/runtime/src/trampolines/x86_64.rs index d5af4446dc71..d22bcaf1a0e3 100644 --- a/crates/runtime/src/trampolines/x86_64.rs +++ b/crates/runtime/src/trampolines/x86_64.rs @@ -21,7 +21,7 @@ cfg_if::cfg_if! { macro_rules! wasm_to_libcall_trampoline { ($libcall:ident ; $libcall_impl:ident) => { wasmtime_asm_macros::asm_func!( - stringify!($libcall), + wasmtime_versioned_export_macros::versioned_stringify_ident!($libcall), concat!( " .cfi_startproc simple diff --git a/crates/runtime/src/traphandlers.rs b/crates/runtime/src/traphandlers.rs index 25d852671ba5..c43c9779f3b2 100644 --- a/crates/runtime/src/traphandlers.rs +++ b/crates/runtime/src/traphandlers.rs @@ -24,6 +24,7 @@ cfg_if::cfg_if! { struct WasmtimeLongjmp; + #[wasmtime_versioned_export_macros::versioned_export] unsafe extern "C" fn wasmtime_setjmp( _jmp_buf: *mut *const u8, callback: extern "C" fn(*mut u8, *mut VMContext), @@ -46,12 +47,14 @@ cfg_if::cfg_if! { } } + #[wasmtime_versioned_export_macros::versioned_export] unsafe extern "C" fn wasmtime_longjmp(_jmp_buf: *const u8) -> ! { std::panic::panic_any(WasmtimeLongjmp) } } else { #[link(name = "wasmtime-helpers")] extern "C" { + #[wasmtime_versioned_export_macros::versioned_link] #[allow(improper_ctypes)] fn wasmtime_setjmp( jmp_buf: *mut *const u8, @@ -59,6 +62,7 @@ cfg_if::cfg_if! { payload: *mut u8, callee: *mut VMContext, ) -> i32; + #[wasmtime_versioned_export_macros::versioned_link] fn wasmtime_longjmp(jmp_buf: *const u8) -> !; } } diff --git a/crates/versioned-export-macros/Cargo.toml b/crates/versioned-export-macros/Cargo.toml new file mode 100644 index 000000000000..e8e3318231f8 --- /dev/null +++ b/crates/versioned-export-macros/Cargo.toml @@ -0,0 +1,18 @@ +[package] +authors = ["The Wasmtime Project Developers"] +description = "Macros for defining versioned exports in Wasmtime" +edition.workspace = true +license = "Apache-2.0 WITH LLVM-exception" +name = "wasmtime-versioned-export-macros" +repository = "https://github.com/bytecodealliance/wasmtime" +version.workspace = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +syn = { version = "2.0", features = ["full"] } +quote = "1.0" +proc-macro2 = "1.0" + +[lib] +proc-macro = true diff --git a/crates/versioned-export-macros/src/lib.rs b/crates/versioned-export-macros/src/lib.rs new file mode 100644 index 000000000000..065a0fc501f4 --- /dev/null +++ b/crates/versioned-export-macros/src/lib.rs @@ -0,0 +1,66 @@ +//! This crate defines macros to easily define and use functions with a +//! versioned suffix, to facilitate using multiple versions of the same +//! crate that generate assembly. + +use quote::ToTokens; + +const VERSION: &str = env!("CARGO_PKG_VERSION"); + +fn version(value: impl std::fmt::Display) -> String { + format!("{}_{}", value, VERSION.replace('.', "_")) +} + +fn versioned_lit_str(value: impl std::fmt::Display) -> syn::LitStr { + syn::LitStr::new(version(value).as_str(), proc_macro2::Span::call_site()) +} + +#[proc_macro_attribute] +pub fn versioned_export( + _attr: proc_macro::TokenStream, + item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + let mut function = syn::parse_macro_input!(item as syn::ItemFn); + + let export_name = versioned_lit_str(&function.sig.ident); + function + .attrs + .push(syn::parse_quote! { #[export_name = #export_name] }); + + function.to_token_stream().into() +} + +#[proc_macro_attribute] +pub fn versioned_link( + _attr: proc_macro::TokenStream, + item: proc_macro::TokenStream, +) -> proc_macro::TokenStream { + let mut function = syn::parse_macro_input!(item as syn::ForeignItemFn); + + let link_name = versioned_lit_str(&function.sig.ident); + function + .attrs + .push(syn::parse_quote! { #[link_name = #link_name] }); + + function.to_token_stream().into() +} + +#[proc_macro] +pub fn versioned_stringify_ident(item: proc_macro::TokenStream) -> proc_macro::TokenStream { + let ident = syn::parse_macro_input!(item as syn::Ident); + + versioned_lit_str(ident).to_token_stream().into() +} + +#[proc_macro] +pub fn versioned_suffix(item: proc_macro::TokenStream) -> proc_macro::TokenStream { + if !item.is_empty() { + return syn::Error::new( + proc_macro2::Span::call_site(), + "`versioned_suffix!` accepts no input", + ) + .to_compile_error() + .into(); + }; + + versioned_lit_str("").to_token_stream().into() +} diff --git a/scripts/publish.rs b/scripts/publish.rs index 513b0fea6099..29ccf1372ecf 100644 --- a/scripts/publish.rs +++ b/scripts/publish.rs @@ -45,6 +45,7 @@ const CRATES_TO_PUBLISH: &[&str] = &[ "winch", // wasmtime "wasmtime-asm-macros", + "wasmtime-versioned-export-macros", "wasmtime-component-util", "wasmtime-wit-bindgen", "wasmtime-component-macro", diff --git a/supply-chain/config.toml b/supply-chain/config.toml index 0b1f6b87af04..48bd80f22f96 100644 --- a/supply-chain/config.toml +++ b/supply-chain/config.toml @@ -148,6 +148,9 @@ audit-as-crates-io = true [policy.wasmtime-types] audit-as-crates-io = true +[policy.wasmtime-versioned-export-macros] +audit-as-crates-io = false + [policy.wasmtime-wasi] audit-as-crates-io = true