Skip to content

Commit

Permalink
[lld][WebAssembly] Handle weakly referenced symbols when lazy (archiv…
Browse files Browse the repository at this point in the history
…e) 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: WebAssembly/wasi-libc#214

Differential Revision: https://reviews.llvm.org/D85567
  • Loading branch information
sbc100 authored and memfrob committed Oct 4, 2022
1 parent 3532b6e commit 91b4f6b
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 9 deletions.
6 changes: 5 additions & 1 deletion lld/test/wasm/archive-weak-undefined.ll
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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

Expand Down
25 changes: 17 additions & 8 deletions lld/wasm/SymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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;
}

Expand Down
4 changes: 4 additions & 0 deletions lld/wasm/Symbols.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down
1 change: 1 addition & 0 deletions lld/wasm/Symbols.h
Original file line number Diff line number Diff line change
Expand Up @@ -411,6 +411,7 @@ class LazySymbol : public Symbol {

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
Expand Down

0 comments on commit 91b4f6b

Please sign in to comment.