[lld] Fix SEGFAULT in wasm-ld when importing wrapped symbol (PR #169656)

Lukas Döllerer via llvm-commits llvm-commits at lists.llvm.org
Thu Nov 27 01:13:31 PST 2025


https://github.com/Lukasdoe updated https://github.com/llvm/llvm-project/pull/169656

>From 7c377f0c4f13cf33b91d738ac6992ca415a71525 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lukas=20D=C3=B6llerer?= <lukas.doellerer at tum.de>
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<WrappedSymbol> 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<FunctionSymbol>(sym)) {
-    ImportKey<WasmSignature> key(*(f->getSignature()), module, name);
+    const WasmSignature *sig = f->getSignature();
+    assert(sig && "imported functions must have a signature");
+    ImportKey<WasmSignature> 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?= <lukas.doellerer at tum.de>
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



More information about the llvm-commits mailing list