[lld][WebAssembly] Fix handling of mixed strong and weak references

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
This commit is contained in:
Sam Clegg 2023-02-24 10:09:07 -08:00
parent 45391e1394
commit d65ed8cde0
4 changed files with 38 additions and 4 deletions

View File

@ -0,0 +1,5 @@
.globl f2
f2:
.functype f2 () -> (i32)
i32.const global_var
end_function

View 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

View 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;
}

View 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()) {