[WebAssembly] Error on relocations against undefined data symbols.

We can't (currently) meaningfully resolve certain types of relocations
against undefined data symbols.  Previously when `--allow-undefined` was
used we were treating such relocation much like weak data symbols and
simply inserting zeros.  This change turns such use cases in to an
error.

This means that `--allow-undefined` is no longer effective for data
symbols.

Fixes https://bugs.llvm.org/show_bug.cgi?id=40364

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

llvm-svn: 358899
This commit is contained in:
Sam Clegg 2019-04-22 16:12:54 +00:00
parent 55043e2336
commit 7cdec273dd
3 changed files with 50 additions and 16 deletions

View File

@ -1,6 +1,7 @@
; RUN: llc -filetype=obj %s -o %t.o ; 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 -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=BADRELOC ; RUN: not wasm-ld --allow-undefined -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=ALLOW
; RUN: not wasm-ld --shared -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=SHARED
target triple = "wasm32-unknown-unknown" target triple = "wasm32-unknown-unknown"
@ -13,4 +14,5 @@ entry:
} }
; UNDEF: undefined symbol: data_external ; UNDEF: undefined symbol: data_external
; BADRELOC: undefined-data.ll.tmp.o: relocation R_WASM_MEMORY_ADDR_LEB cannot be used againt symbol data_external; recompile with -fPIC ; ALLOW: undefined-data.ll.tmp.o: cannot resolve relocation of type R_WASM_MEMORY_ADDR_LEB against undefined (non-weak) data symbol: data_external
; SHARED: undefined-data.ll.tmp.o: relocation R_WASM_MEMORY_ADDR_LEB cannot be used againt symbol data_external; recompile with -fPIC

View File

@ -141,6 +141,30 @@ uint32_t ObjFile::calcExpectedValue(const WasmRelocation &Reloc) const {
// Translate from the relocation's index into the final linked output value. // Translate from the relocation's index into the final linked output value.
uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const { uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const {
const Symbol* Sym = nullptr;
if (Reloc.Type != R_WASM_TYPE_INDEX_LEB) {
Sym = Symbols[Reloc.Index];
// We can end up with relocations against non-live symbols. For example
// 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;
if (Config->Shared && 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) { switch (Reloc.Type) {
case R_WASM_TABLE_INDEX_I32: case R_WASM_TABLE_INDEX_I32:
case R_WASM_TABLE_INDEX_SLEB: case R_WASM_TABLE_INDEX_SLEB:
@ -150,28 +174,22 @@ uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const {
case R_WASM_MEMORY_ADDR_I32: case R_WASM_MEMORY_ADDR_I32:
case R_WASM_MEMORY_ADDR_LEB: case R_WASM_MEMORY_ADDR_LEB:
case R_WASM_MEMORY_ADDR_REL_SLEB: case R_WASM_MEMORY_ADDR_REL_SLEB:
if (auto *Sym = dyn_cast<DefinedData>(getDataSymbol(Reloc.Index))) return cast<DefinedData>(Sym)->getVirtualAddress() + Reloc.Addend;
if (Sym->isLive())
return Sym->getVirtualAddress() + Reloc.Addend;
return 0;
case R_WASM_TYPE_INDEX_LEB: case R_WASM_TYPE_INDEX_LEB:
return TypeMap[Reloc.Index]; return TypeMap[Reloc.Index];
case R_WASM_FUNCTION_INDEX_LEB: case R_WASM_FUNCTION_INDEX_LEB:
return getFunctionSymbol(Reloc.Index)->getFunctionIndex(); return getFunctionSymbol(Reloc.Index)->getFunctionIndex();
case R_WASM_GLOBAL_INDEX_LEB: { case R_WASM_GLOBAL_INDEX_LEB:
const Symbol* Sym = Symbols[Reloc.Index];
if (auto GS = dyn_cast<GlobalSymbol>(Sym)) if (auto GS = dyn_cast<GlobalSymbol>(Sym))
return GS->getGlobalIndex(); return GS->getGlobalIndex();
return Sym->getGOTIndex(); return Sym->getGOTIndex();
} case R_WASM_EVENT_INDEX_LEB: case R_WASM_EVENT_INDEX_LEB:
return getEventSymbol(Reloc.Index)->getEventIndex(); return getEventSymbol(Reloc.Index)->getEventIndex();
case R_WASM_FUNCTION_OFFSET_I32: case R_WASM_FUNCTION_OFFSET_I32: {
if (auto *Sym = dyn_cast<DefinedFunction>(getFunctionSymbol(Reloc.Index))) { auto *F = cast<DefinedFunction>(Sym);
if (Sym->isLive()) return F->Function->OutputOffset + F->Function->getFunctionCodeOffset() +
return Sym->Function->OutputOffset + Reloc.Addend;
Sym->Function->getFunctionCodeOffset() + Reloc.Addend;
} }
return 0;
case R_WASM_SECTION_OFFSET_I32: case R_WASM_SECTION_OFFSET_I32:
return getSectionSymbol(Reloc.Index)->Section->OutputOffset + Reloc.Addend; return getSectionSymbol(Reloc.Index)->Section->OutputOffset + Reloc.Addend;
default: default:

View File

@ -1170,6 +1170,20 @@ void Writer::processRelocations(InputChunk *Chunk) {
Sym->setGOTIndex(NumImportedGlobals++); Sym->setGOTIndex(NumImportedGlobals++);
GOTSymbols.push_back(Sym); GOTSymbols.push_back(Sym);
} }
break;
}
case R_WASM_MEMORY_ADDR_SLEB:
case R_WASM_MEMORY_ADDR_LEB:
case R_WASM_MEMORY_ADDR_REL_SLEB: {
if (!Config->Relocatable) {
auto* Sym = File->getSymbols()[Reloc.Index];
if (Sym->isUndefined() && !Sym->isWeak()) {
error(toString(File) + ": cannot resolve relocation of type " +
relocTypeToString(Reloc.Type) +
" against undefined (non-weak) data symbol: " + toString(*Sym));
}
}
break;
} }
} }