Skip to content

Commit

Permalink
[lld][WebAssembly] Report undefined symbols during scanRelocations
Browse files Browse the repository at this point in the history
This puts handling of undefined symbols in a single location.  Its
also more in line with the ELF backend which only reports undefined
symbols based on relocations.

One side effect is that we no longer report undefined symbols that are
only referenced in GC'd sections.

This also fixes a crash reported in the emscripten toolchain:
emscripten-core/emscripten#8930.

Differential Revision: https://reviews.llvm.org/D64280

llvm-svn: 365553
  • Loading branch information
sbc100 committed Jul 9, 2019
1 parent 5ca39e8 commit 9abe8c4
Show file tree
Hide file tree
Showing 7 changed files with 30 additions and 51 deletions.
3 changes: 1 addition & 2 deletions lld/test/wasm/undefined-data.ll
Original file line number Diff line number Diff line change
@@ -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"
Expand All @@ -14,5 +14,4 @@ entry:
}

; 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
5 changes: 3 additions & 2 deletions lld/test/wasm/undefined.ll
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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

Expand Down
18 changes: 2 additions & 16 deletions lld/wasm/InputFiles.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -160,22 +160,6 @@ uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const {
// in debug sections.
if ((isa<FunctionSymbol>(Sym) || isa<DataSymbol>(Sym)) && !Sym->isLive())
return 0;

// Special handling for undefined data symbols. Most relocations against
// such symbols cannot be resolved.
if (isa<DataSymbol>(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());
}
}
}

switch (Reloc.Type) {
Expand All @@ -189,6 +173,8 @@ uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const {
case R_WASM_MEMORY_ADDR_I32:
case R_WASM_MEMORY_ADDR_LEB:
case R_WASM_MEMORY_ADDR_REL_SLEB:
if (isa<UndefinedData>(Sym))
return 0;
return cast<DefinedData>(Sym)->getVirtualAddress() + Reloc.Addend;
case R_WASM_TYPE_INDEX_LEB:
return TypeMap[Reloc.Index];
Expand Down
33 changes: 24 additions & 9 deletions lld/wasm/Relocations.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,25 @@ static bool requiresGOTAccess(const Symbol *Sym) {
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<DataSymbol>(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;
Expand Down Expand Up @@ -50,15 +69,6 @@ void lld::wasm::scanRelocations(InputChunk *Chunk) {
if (!isa<GlobalSymbol>(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;
}

if (Config->Pic) {
Expand All @@ -81,6 +91,11 @@ void lld::wasm::scanRelocations(InputChunk *Chunk) {
Out.ImportSec->addGOTEntry(Sym);
break;
}
} else {
// Report undefined symbols
if (Sym->isUndefined() && !Config->Relocatable && !Sym->isWeak())
reportUndefined(Sym);
}

}
}
13 changes: 0 additions & 13 deletions lld/wasm/SymbolTable.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -80,19 +80,6 @@ void SymbolTable::addCombinedLTOObject() {
}
}

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)
Expand Down
2 changes: 0 additions & 2 deletions lld/wasm/SymbolTable.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,6 @@ class SymbolTable {

void addCombinedLTOObject();

void reportRemainingUndefines();

ArrayRef<Symbol *> getSymbols() const { return SymVector; }

Symbol *find(StringRef Name);
Expand Down
7 changes: 0 additions & 7 deletions lld/wasm/Writer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -827,13 +827,6 @@ void Writer::run() {
if (Config->Pic)
createApplyRelocationsFunction();
createCallCtorsFunction();

// Make sure we have resolved all symbols.
if (!Config->AllowUndefined)
Symtab->reportRemainingUndefines();

if (errorCount())
return;
}

log("-- calculateTypes");
Expand Down

0 comments on commit 9abe8c4

Please sign in to comment.