[lld][WebAssembly] Fix handling of mixed strong and weak references
authorSam Clegg <sbc@chromium.org>
Fri, 24 Feb 2023 18:09:07 +0000 (10:09 -0800)
committerSam Clegg <sbc@chromium.org>
Mon, 27 Feb 2023 22:20:01 +0000 (14:20 -0800)
When adding a undefined symbols to the symbol table, if the existing
reference is weak replace the symbol flags with (potentially) non-weak
binding.

Fixes: https://github.com/llvm/llvm-project/issues/60829

Differential Revision: https://reviews.llvm.org/D144747

lld/test/wasm/Inputs/strong-refs.s [new file with mode: 0644]
lld/test/wasm/weak-undefined.s
lld/wasm/SymbolTable.cpp
llvm/lib/Object/WasmObjectFile.cpp

diff --git a/lld/test/wasm/Inputs/strong-refs.s b/lld/test/wasm/Inputs/strong-refs.s
new file mode 100644 (file)
index 0000000..bbf04e1
--- /dev/null
@@ -0,0 +1,5 @@
+.globl  f2
+f2:
+  .functype f2 () -> (i32)
+  i32.const global_var
+  end_function
index 5b8b977..e1f551d 100644 (file)
@@ -1,9 +1,18 @@
+# Test that undefined weak externals (global_var) and (foo) don't cause
+# link failures and resolve to zero.
+
 # RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
 # RUN: wasm-ld -strip-all %t.o -o %t.wasm
 # RUN: obj2yaml %t.wasm | FileCheck %s
 
-# Test that undefined weak externals (global_var) and (foo) don't cause
-# link failures and resolve to zero.
+# Also verify test that strong references in another file do cause link
+# failure (See https://github.com/llvm/llvm-project/issues/60806)
+
+# RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/strong-refs.s -o %t-strong.o
+# RUN: not wasm-ld -strip-all %t.o %t-strong.o -o %t.wasm 2>&1 | FileCheck --check-prefix=ERROR %s
+# RUN: not wasm-ld -strip-all %t-strong.o %t.o -o %t.wasm 2>&1 | FileCheck --check-prefix=ERROR %s
+
+# ERROR: undefined symbol: global_var
 
 .functype foo () -> (i32)
 
@@ -33,7 +42,6 @@ _start:
 .weak foo
 .weak global_var
 
-
 # CHECK:      --- !WASM
 # CHECK-NEXT: FileHeader:
 # CHECK-NEXT:   Version:         0x1
index 8ca5e94..d14e9d5 100644 (file)
@@ -548,6 +548,8 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef name,
                           file);
       if (isCalledDirectly)
         existingUndefined->isCalledDirectly = true;
+      if (s->isWeak())
+        s->flags = flags;
     }
   }
 
@@ -574,6 +576,8 @@ Symbol *SymbolTable::addUndefinedData(StringRef name, uint32_t flags,
       lazy->fetch();
   } else if (s->isDefined()) {
     checkDataType(s, file);
+  } else if (s->isWeak()) {
+    s->flags = flags;
   }
   return s;
 }
@@ -599,6 +603,8 @@ Symbol *SymbolTable::addUndefinedGlobal(StringRef name,
     lazy->fetch();
   else if (s->isDefined())
     checkGlobalType(s, file, type);
+  else if (s->isWeak())
+    s->flags = flags;
   return s;
 }
 
@@ -623,6 +629,8 @@ Symbol *SymbolTable::addUndefinedTable(StringRef name,
     lazy->fetch();
   else if (s->isDefined())
     checkTableType(s, file, type);
+  else if (s->isWeak())
+    s->flags = flags;
   return s;
 }
 
@@ -647,6 +655,8 @@ Symbol *SymbolTable::addUndefinedTag(StringRef name,
     lazy->fetch();
   else if (s->isDefined())
     checkTagType(s, file, sig);
+  else if (s->isWeak())
+    s->flags = flags;
   return s;
 }
 
index 400911d..471b68f 100644 (file)
@@ -38,7 +38,18 @@ using namespace object;
 void WasmSymbol::print(raw_ostream &Out) const {
   Out << "Name=" << Info.Name
       << ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x"
-      << Twine::utohexstr(Info.Flags);
+      << Twine::utohexstr(Info.Flags) << " [";
+  switch (getBinding()) {
+    case wasm::WASM_SYMBOL_BINDING_GLOBAL: Out << "global"; break;
+    case wasm::WASM_SYMBOL_BINDING_LOCAL: Out << "local"; break;
+    case wasm::WASM_SYMBOL_BINDING_WEAK: Out << "weak"; break;
+  }
+  if (isHidden()) {
+    Out << ", hidden";
+  } else {
+    Out << ", default";
+  }
+  Out << "]";
   if (!isTypeData()) {
     Out << ", ElemIndex=" << Info.ElementIndex;
   } else if (isDefined()) {