From b34ec5969f1ad27f48ebc0d35a3fe37e810a8a32 Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Fri, 7 Aug 2020 16:12:33 -0700 Subject: [PATCH] [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 --- lld/test/wasm/archive-weak-undefined.ll | 6 +++++- lld/wasm/SymbolTable.cpp | 25 +++++++++++++++++-------- lld/wasm/Symbols.cpp | 4 ++++ lld/wasm/Symbols.h | 1 + 4 files changed, 27 insertions(+), 9 deletions(-) diff --git a/lld/test/wasm/archive-weak-undefined.ll b/lld/test/wasm/archive-weak-undefined.ll index 530ff8aeb61832a..9539cf91af36a78 100644 --- a/lld/test/wasm/archive-weak-undefined.ll +++ b/lld/test/wasm/archive-weak-undefined.ll @@ -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 diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp index f233646cbb65193..b3cb87c8ef17469 100644 --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -458,11 +458,16 @@ Symbol *SymbolTable::addUndefinedFunction(StringRef name, file, sig, isCalledDirectly); }; - if (wasInserted) + if (wasInserted) { replaceSym(); - else if (auto *lazy = dyn_cast(s)) - lazy->fetch(); - else { + } else if (auto *lazy = dyn_cast(s)) { + if ((flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) { + lazy->setWeak(); + lazy->signature = sig; + } else { + lazy->fetch(); + } + } else { auto existingFunction = dyn_cast(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(s, name, flags, file); - else if (auto *lazy = dyn_cast(s)) - lazy->fetch(); - else if (s->isDefined()) + } else if (auto *lazy = dyn_cast(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; } diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp index 33923fb3e9f4bec..4b40f95ed52db57 100644 --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -339,6 +339,10 @@ const OutputSectionSymbol *SectionSymbol::getOutputSectionSymbol() const { void LazySymbol::fetch() { cast(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(), diff --git a/lld/wasm/Symbols.h b/lld/wasm/Symbols.h index 9588a5595206cd8..73f555217f26089 100644 --- a/lld/wasm/Symbols.h +++ b/lld/wasm/Symbols.h @@ -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