From 7c377f0c4f13cf33b91d738ac6992ca415a71525 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=B6llerer?= Date: Wed, 26 Nov 2025 15:12:29 +0100 Subject: [PATCH 1/2] Fix SEGFAULT in wasm-ld when importing wrapped symbol When wrapping a symbol `foo`, we create the symbol `__wrap_foo` that replaces all mentions of `foo`. This change adds the correct signature to the wrapped symbol to enable generating an import for it. --- lld/test/wasm/wrap_import.s | 36 ++++++++++++++++++++++++++++++++++ lld/wasm/Driver.cpp | 8 +++++--- lld/wasm/SyntheticSections.cpp | 4 +++- 3 files changed, 44 insertions(+), 4 deletions(-) create mode 100644 lld/test/wasm/wrap_import.s diff --git a/lld/test/wasm/wrap_import.s b/lld/test/wasm/wrap_import.s new file mode 100644 index 0000000000000..526c1f539a4fd --- /dev/null +++ b/lld/test/wasm/wrap_import.s @@ -0,0 +1,36 @@ +# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o +# RUN: wasm-ld -emit-relocs -wrap nosuchsym -wrap foo -allow-undefined -o %t.wasm %t.o +# RUN: obj2yaml %t.wasm | FileCheck %s + +.globl foo +.globl _start + +foo: + .functype foo () -> (i32) + i32.const 1 + end_function + +_start: + .functype _start () -> () + call foo + drop + end_function + +# CHECK: - Type: IMPORT +# CHECK-NEXT: Imports: +# CHECK-NEXT: - Module: env +# CHECK-NEXT: Field: __wrap_foo +# CHECK-NEXT: Kind: FUNCTION +# CHECK-NEXT SigIndex: 0 + +# CHECK: - Type: CODE +# CHECK-NEXT: Relocations: +# CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB +# CHECK-NEXT: Index: 1 +# CHECK-NEXT: Offset: 0x4 + +# CHECK: FunctionNames: +# CHECK-NEXT: - Index: 0 +# CHECK-NEXT: Name: __wrap_foo +# CHECK-NEXT: - Index: 1 +# CHECK-NEXT: Name: _start diff --git a/lld/wasm/Driver.cpp b/lld/wasm/Driver.cpp index fac166587cb9b..97e50783985a8 100644 --- a/lld/wasm/Driver.cpp +++ b/lld/wasm/Driver.cpp @@ -1173,9 +1173,10 @@ struct WrappedSymbol { Symbol *wrap; }; -static Symbol *addUndefined(StringRef name) { +static Symbol *addUndefined(StringRef name, + const WasmSignature *signature = nullptr) { return symtab->addUndefinedFunction(name, std::nullopt, std::nullopt, - WASM_SYMBOL_UNDEFINED, nullptr, nullptr, + WASM_SYMBOL_UNDEFINED, nullptr, signature, false); } @@ -1198,7 +1199,8 @@ static std::vector addWrappedSymbols(opt::InputArgList &args) { continue; Symbol *real = addUndefined(saver().save("__real_" + name)); - Symbol *wrap = addUndefined(saver().save("__wrap_" + name)); + Symbol *wrap = + addUndefined(saver().save("__wrap_" + name), sym->getSignature()); v.push_back({sym, real, wrap}); // We want to tell LTO not to inline symbols to be overwritten diff --git a/lld/wasm/SyntheticSections.cpp b/lld/wasm/SyntheticSections.cpp index 399a5084e6595..5e7b9c229f3ed 100644 --- a/lld/wasm/SyntheticSections.cpp +++ b/lld/wasm/SyntheticSections.cpp @@ -196,7 +196,9 @@ void ImportSection::addImport(Symbol *sym) { StringRef module = sym->importModule.value_or(defaultModule); StringRef name = sym->importName.value_or(sym->getName()); if (auto *f = dyn_cast(sym)) { - ImportKey key(*(f->getSignature()), module, name); + const WasmSignature *sig = f->getSignature(); + assert(sig && "imported functions must have a signature"); + ImportKey key(*sig, module, name); auto entry = importedFunctions.try_emplace(key, numImportedFunctions); if (entry.second) { importedSymbols.emplace_back(sym); From 1304c26b4e6b9798dcf3deeb9f23c1119105ee97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20D=C3=B6llerer?= Date: Thu, 27 Nov 2025 10:12:55 +0100 Subject: [PATCH 2/2] fixes from review --- lld/test/wasm/wrap_import.s | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/lld/test/wasm/wrap_import.s b/lld/test/wasm/wrap_import.s index 526c1f539a4fd..ce3b6f57f10c4 100644 --- a/lld/test/wasm/wrap_import.s +++ b/lld/test/wasm/wrap_import.s @@ -1,19 +1,17 @@ # RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %s -o %t.o -# RUN: wasm-ld -emit-relocs -wrap nosuchsym -wrap foo -allow-undefined -o %t.wasm %t.o +# RUN: wasm-ld -wrap nosuchsym -wrap foo -allow-undefined -o %t.wasm %t.o # RUN: obj2yaml %t.wasm | FileCheck %s .globl foo .globl _start foo: - .functype foo () -> (i32) - i32.const 1 + .functype foo () -> () end_function _start: .functype _start () -> () call foo - drop end_function # CHECK: - Type: IMPORT @@ -24,10 +22,8 @@ _start: # CHECK-NEXT SigIndex: 0 # CHECK: - Type: CODE -# CHECK-NEXT: Relocations: -# CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB +# CHECK-NEXT: Functions: # CHECK-NEXT: Index: 1 -# CHECK-NEXT: Offset: 0x4 # CHECK: FunctionNames: # CHECK-NEXT: - Index: 0