[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:
parent
45391e1394
commit
d65ed8cde0
5
lld/test/wasm/Inputs/strong-refs.s
Normal file
5
lld/test/wasm/Inputs/strong-refs.s
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
.globl f2
|
||||||
|
f2:
|
||||||
|
.functype f2 () -> (i32)
|
||||||
|
i32.const global_var
|
||||||
|
end_function
|
@ -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: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown -o %t.o %s
|
||||||
# RUN: wasm-ld -strip-all %t.o -o %t.wasm
|
# RUN: wasm-ld -strip-all %t.o -o %t.wasm
|
||||||
# RUN: obj2yaml %t.wasm | FileCheck %s
|
# RUN: obj2yaml %t.wasm | FileCheck %s
|
||||||
|
|
||||||
# Test that undefined weak externals (global_var) and (foo) don't cause
|
# Also verify test that strong references in another file do cause link
|
||||||
# link failures and resolve to zero.
|
# 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)
|
.functype foo () -> (i32)
|
||||||
|
|
||||||
@ -33,7 +42,6 @@ _start:
|
|||||||
.weak foo
|
.weak foo
|
||||||
.weak global_var
|
.weak global_var
|
||||||
|
|
||||||
|
|
||||||
# CHECK: --- !WASM
|
# CHECK: --- !WASM
|
||||||
# CHECK-NEXT: FileHeader:
|
# CHECK-NEXT: FileHeader:
|
||||||
# CHECK-NEXT: Version: 0x1
|
# CHECK-NEXT: Version: 0x1
|
||||||
|
@ -548,6 +548,8 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef name,
|
|||||||
file);
|
file);
|
||||||
if (isCalledDirectly)
|
if (isCalledDirectly)
|
||||||
existingUndefined->isCalledDirectly = true;
|
existingUndefined->isCalledDirectly = true;
|
||||||
|
if (s->isWeak())
|
||||||
|
s->flags = flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -574,6 +576,8 @@ Symbol *SymbolTable::addUndefinedData(StringRef name, uint32_t flags,
|
|||||||
lazy->fetch();
|
lazy->fetch();
|
||||||
} else if (s->isDefined()) {
|
} else if (s->isDefined()) {
|
||||||
checkDataType(s, file);
|
checkDataType(s, file);
|
||||||
|
} else if (s->isWeak()) {
|
||||||
|
s->flags = flags;
|
||||||
}
|
}
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
@ -599,6 +603,8 @@ Symbol *SymbolTable::addUndefinedGlobal(StringRef name,
|
|||||||
lazy->fetch();
|
lazy->fetch();
|
||||||
else if (s->isDefined())
|
else if (s->isDefined())
|
||||||
checkGlobalType(s, file, type);
|
checkGlobalType(s, file, type);
|
||||||
|
else if (s->isWeak())
|
||||||
|
s->flags = flags;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -623,6 +629,8 @@ Symbol *SymbolTable::addUndefinedTable(StringRef name,
|
|||||||
lazy->fetch();
|
lazy->fetch();
|
||||||
else if (s->isDefined())
|
else if (s->isDefined())
|
||||||
checkTableType(s, file, type);
|
checkTableType(s, file, type);
|
||||||
|
else if (s->isWeak())
|
||||||
|
s->flags = flags;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -647,6 +655,8 @@ Symbol *SymbolTable::addUndefinedTag(StringRef name,
|
|||||||
lazy->fetch();
|
lazy->fetch();
|
||||||
else if (s->isDefined())
|
else if (s->isDefined())
|
||||||
checkTagType(s, file, sig);
|
checkTagType(s, file, sig);
|
||||||
|
else if (s->isWeak())
|
||||||
|
s->flags = flags;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -38,7 +38,18 @@ using namespace object;
|
|||||||
void WasmSymbol::print(raw_ostream &Out) const {
|
void WasmSymbol::print(raw_ostream &Out) const {
|
||||||
Out << "Name=" << Info.Name
|
Out << "Name=" << Info.Name
|
||||||
<< ", Kind=" << toString(wasm::WasmSymbolType(Info.Kind)) << ", Flags=0x"
|
<< ", 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()) {
|
if (!isTypeData()) {
|
||||||
Out << ", ElemIndex=" << Info.ElementIndex;
|
Out << ", ElemIndex=" << Info.ElementIndex;
|
||||||
} else if (isDefined()) {
|
} else if (isDefined()) {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user