[lld][WebAssembly] Handle weakly referenced symbols when lazy (archive) version is see first

When a weak reference of a lazy symbol occurs we were not correctly
updating the lazy symbol.  We need to tag the existing lazy symbol
as weak and, in the case of a function symbol, give it a signature.

Without the signature we can't then create the dummy function which
is needed when an weakly undefined function is called.

We had tests for weakly referenced lazy symbols but we were only
tests in the case where the reference was seen before the lazy
symbol.

See: https://github.com/WebAssembly/wasi-libc/pull/214

Differential Revision: https://reviews.llvm.org/D85567
This commit is contained in:
Sam Clegg 2020-08-07 16:12:33 -07:00
parent 9a368d2b00
commit b34ec5969f
4 changed files with 27 additions and 9 deletions

View File

@ -1,4 +1,4 @@
; Test that weak undefined symbols do not fetch members from archive files.
;; Test that weak undefined symbols do not fetch members from archive files.
; RUN: llc -filetype=obj %s -o %t.o
; RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/ret32.s -o %t.ret32.o
; RUN: llvm-mc -filetype=obj -triple=wasm32-unknown-unknown %p/Inputs/hello.s -o %t.hello.o
@ -8,6 +8,10 @@
; RUN: wasm-ld %t.o %t.a -o %t.wasm
; RUN: obj2yaml %t.wasm | FileCheck %s
;; Also test with the library symbols being read first
; RUN: wasm-ld %t.a %t.o -o %t2.wasm
; RUN: obj2yaml %t2.wasm | FileCheck %s
; RUN: wasm-ld -u hello_str %t.o %t.a -o %t2.wasm
; RUN: obj2yaml %t2.wasm | FileCheck %s -check-prefix=CHECK-DATA

View File

@ -458,11 +458,16 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef name,
file, sig, isCalledDirectly);
};
if (wasInserted)
if (wasInserted) {
replaceSym();
else if (auto *lazy = dyn_cast<LazySymbol>(s))
lazy->fetch();
else {
} else if (auto *lazy = dyn_cast<LazySymbol>(s)) {
if ((flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
lazy->setWeak();
lazy->signature = sig;
} else {
lazy->fetch();
}
} else {
auto existingFunction = dyn_cast<FunctionSymbol>(s);
if (!existingFunction) {
reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION);
@ -499,12 +504,16 @@ Symbol *SymbolTable::addUndefinedData(StringRef name, uint32_t flags,
if (s->traced)
printTraceSymbolUndefined(name, file);
if (wasInserted)
if (wasInserted) {
replaceSymbol<UndefinedData>(s, name, flags, file);
else if (auto *lazy = dyn_cast<LazySymbol>(s))
lazy->fetch();
else if (s->isDefined())
} else if (auto *lazy = dyn_cast<LazySymbol>(s)) {
if ((flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK)
lazy->setWeak();
else
lazy->fetch();
} else if (s->isDefined()) {
checkDataType(s, file);
}
return s;
}

View File

@ -339,6 +339,10 @@ const OutputSectionSymbol *SectionSymbol::getOutputSectionSymbol() const {
void LazySymbol::fetch() { cast<ArchiveFile>(file)->addMember(&archiveSymbol); }
void LazySymbol::setWeak() {
flags |= (flags & ~WASM_SYMBOL_BINDING_MASK) | WASM_SYMBOL_BINDING_WEAK;
}
MemoryBufferRef LazySymbol::getMemberBuffer() {
Archive::Child c =
CHECK(archiveSymbol.getMember(),

View File

@ -411,6 +411,7 @@ public:
static bool classof(const Symbol *s) { return s->kind() == LazyKind; }
void fetch();
void setWeak();
MemoryBufferRef getMemberBuffer();
// Lazy symbols can have a signature because they can replace an