diff --git a/lld/test/wasm/undefined-data.ll b/lld/test/wasm/undefined-data.ll --- a/lld/test/wasm/undefined-data.ll +++ b/lld/test/wasm/undefined-data.ll @@ -1,6 +1,6 @@ ; RUN: llc -filetype=obj %s -o %t.o ; RUN: not wasm-ld -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=UNDEF -; RUN: not wasm-ld --allow-undefined -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=ALLOW +; RUN: not wasm-ld --allow-undefined -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=UNDEF ; RUN: not wasm-ld --shared -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=SHARED target triple = "wasm32-unknown-unknown" @@ -14,5 +14,4 @@ } ; UNDEF: error: {{.*}}undefined-data.ll.tmp.o: undefined symbol: data_external -; ALLOW: error: {{.*}}undefined-data.ll.tmp.o: cannot resolve relocation of type R_WASM_MEMORY_ADDR_LEB against undefined (non-weak) data symbol: data_external ; SHARED: error: {{.*}}undefined-data.ll.tmp.o: relocation R_WASM_MEMORY_ADDR_LEB cannot be used against symbol data_external; recompile with -fPIC diff --git a/lld/test/wasm/undefined.ll b/lld/test/wasm/undefined.ll --- a/lld/test/wasm/undefined.ll +++ b/lld/test/wasm/undefined.ll @@ -1,7 +1,7 @@ ; RUN: llc -filetype=obj %s -o %t.o ; RUN: wasm-ld --allow-undefined -o %t.wasm %t.o -; Fails due to undefined 'foo' +; Fails due to undefined 'foo' ; RUN: not wasm-ld --undefined=baz -o %t.wasm %t.o 2>&1 | FileCheck %s ; CHECK: error: {{.*}}.o: undefined symbol: foo ; CHECK-NOT: undefined symbol: baz @@ -16,7 +16,8 @@ target triple = "wasm32-unknown-unknown" ; Takes the address of the external foo() resulting in undefined external -@bar = hidden local_unnamed_addr global i8* bitcast (i32 ()* @foo to i8*), align 4 +@bar = global i8* bitcast (i32 ()* @foo to i8*), align 4 +@llvm.used = appending global [1 x i8**] [i8** @bar], section "llvm.metadata" declare i32 @foo() #0 diff --git a/lld/wasm/InputFiles.cpp b/lld/wasm/InputFiles.cpp --- a/lld/wasm/InputFiles.cpp +++ b/lld/wasm/InputFiles.cpp @@ -161,21 +161,9 @@ if ((isa(Sym) || isa(Sym)) && !Sym->isLive()) return 0; - // Special handling for undefined data symbols. Most relocations against - // such symbols cannot be resolved. - if (isa(Sym) && Sym->isUndefined()) { - if (Sym->isWeak() || Config->Relocatable) - return 0; - // R_WASM_MEMORY_ADDR_I32 relocations in PIC code are turned into runtime - // fixups in __wasm_apply_relocs - if (Config->Pic && Reloc.Type == R_WASM_MEMORY_ADDR_I32) - return 0; - if (Reloc.Type != R_WASM_GLOBAL_INDEX_LEB) { - llvm_unreachable( - ("invalid relocation against undefined data symbol: " + toString(*Sym)) - .c_str()); - } - } + // Special handling for undefined data symbols. + if (isa(Sym)) + return 0; } switch (Reloc.Type) { diff --git a/lld/wasm/Relocations.cpp b/lld/wasm/Relocations.cpp --- a/lld/wasm/Relocations.cpp +++ b/lld/wasm/Relocations.cpp @@ -21,6 +21,25 @@ return Config->Pic && !Sym->isHidden() && !Sym->isLocal(); } +static bool allowUndefined(const Symbol* Sym) { + // Historically --allow-undefined doesn't work for data symbols since we don't + // have any way to represent these as imports in the final binary. The idea + // behind allowing undefined symbols is to allow importing these symbols from + // the embedder and we can't do this for data symbols (at least not without + // compiling with -fPIC) + if (isa(Sym)) + return false; + return (Config->AllowUndefined || + Config->AllowUndefinedSymbols.count(Sym->getName()) != 0); +} + +static void reportUndefined(const Symbol* Sym) { + assert(Sym->isUndefined()); + assert(!Sym->isWeak()); + if (!allowUndefined(Sym)) + error(toString(Sym->getFile()) + ": undefined symbol: " + toString(*Sym)); +} + void lld::wasm::scanRelocations(InputChunk *Chunk) { if (!Chunk->Live) return; @@ -50,15 +69,12 @@ if (!isa(Sym)) Out.ImportSec->addGOTEntry(Sym); break; - case R_WASM_MEMORY_ADDR_SLEB: - case R_WASM_MEMORY_ADDR_LEB: - case R_WASM_MEMORY_ADDR_REL_SLEB: - if (!Config->Relocatable && Sym->isUndefined() && !Sym->isWeak()) { - error(toString(File) + ": cannot resolve relocation of type " + - relocTypeToString(Reloc.Type) + - " against undefined (non-weak) data symbol: " + toString(*Sym)); - } - break; + } + + // Handle undefined symbols. + if (Sym->isUndefined() && !Config->Relocatable && !Sym->isWeak()) { + if (!(Config->Pic && Reloc.Type == R_WASM_MEMORY_ADDR_I32)) + reportUndefined(Sym); } if (Config->Pic) { diff --git a/lld/wasm/SymbolTable.h b/lld/wasm/SymbolTable.h --- a/lld/wasm/SymbolTable.h +++ b/lld/wasm/SymbolTable.h @@ -41,8 +41,6 @@ void addCombinedLTOObject(); - void reportRemainingUndefines(); - ArrayRef getSymbols() const { return SymVector; } Symbol *find(StringRef Name); diff --git a/lld/wasm/SymbolTable.cpp b/lld/wasm/SymbolTable.cpp --- a/lld/wasm/SymbolTable.cpp +++ b/lld/wasm/SymbolTable.cpp @@ -80,19 +80,6 @@ } } -void SymbolTable::reportRemainingUndefines() { - for (const auto& Pair : SymMap) { - const Symbol *Sym = SymVector[Pair.second]; - if (!Sym->isUndefined() || Sym->isWeak()) - continue; - if (Config->AllowUndefinedSymbols.count(Sym->getName()) != 0) - continue; - if (!Sym->IsUsedInRegularObj) - continue; - error(toString(Sym->getFile()) + ": undefined symbol: " + toString(*Sym)); - } -} - Symbol *SymbolTable::find(StringRef Name) { auto It = SymMap.find(CachedHashStringRef(Name)); if (It == SymMap.end() || It->second == -1) diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -827,13 +827,6 @@ if (Config->Pic) createApplyRelocationsFunction(); createCallCtorsFunction(); - - // Make sure we have resolved all symbols. - if (!Config->AllowUndefined) - Symtab->reportRemainingUndefines(); - - if (errorCount()) - return; } log("-- calculateTypes");