diff options
| author | Sam Clegg <sbc@chromium.org> | 2019-03-16 01:18:12 +0000 |
|---|---|---|
| committer | Sam Clegg <sbc@chromium.org> | 2019-03-16 01:18:12 +0000 |
| commit | 632c217921c094b983bc54b5b18e3cd9b9a7fb1a (patch) | |
| tree | 65dfb497cdd2b14a3a7ea043d620393c4399745e | |
| parent | 7097e83dab7af66b02408df656afeae014e46711 (diff) | |
| download | bcm5719-llvm-632c217921c094b983bc54b5b18e3cd9b9a7fb1a.tar.gz bcm5719-llvm-632c217921c094b983bc54b5b18e3cd9b9a7fb1a.zip | |
[WebAssembly] Error on R_WASM_MEMORY_ADDR relocations against undefined data symbols.
For these types of relocations an absolute memory address is
required which is not possible for undefined data symbols. For symbols
that can be undefined at link time (i.e. external data symbols in
shared libraries) a different type of relocation (i.e. via a GOT) will
be needed.
Differential Revision: https://reviews.llvm.org/D59337
llvm-svn: 356310
| -rw-r--r-- | lld/test/wasm/shared.ll | 24 | ||||
| -rw-r--r-- | lld/test/wasm/undefined-data.ll | 16 | ||||
| -rw-r--r-- | lld/wasm/Writer.cpp | 66 |
3 files changed, 70 insertions, 36 deletions
diff --git a/lld/test/wasm/shared.ll b/lld/test/wasm/shared.ll index b83e61ed1a8..a40cfbe3051 100644 --- a/lld/test/wasm/shared.ll +++ b/lld/test/wasm/shared.ll @@ -13,10 +13,12 @@ entry: ; To ensure we use __stack_pointer %ptr = alloca i32 %0 = load i32, i32* @data, align 4 - %1 = load i32, i32* @data_external, align 4 - %2 = load i32 ()*, i32 ()** @indirect_func, align 4 - call i32 %2() - ret i32 %1 + ; TODO(sbc): Re-enable once the codegen supports generating the correct + ; relocation type when referencing external data in shared libraries. + ; %1 = load i32, i32* @data_external, align 4 + %1 = load i32 ()*, i32 ()** @indirect_func, align 4 + call i32 %1() + ret i32 %0 } declare void @func_external() @@ -29,7 +31,7 @@ declare void @func_external() ; CHECK: Sections: ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: dylink -; CHECK-NEXT: MemorySize: 8 +; CHECK-NEXT: MemorySize: 12 ; CHECK-NEXT: MemoryAlignment: 2 ; CHECK-NEXT: TableSize: 2 ; CHECK-NEXT: TableAlignment: 0 @@ -62,11 +64,11 @@ declare void @func_external() ; CHECK-NEXT: Kind: GLOBAL ; CHECK-NEXT: GlobalType: I32 ; CHECK-NEXT: GlobalMutable: false -; CHECK-NEXT: - Module: env -; CHECK-NEXT: Field: data_external -; CHECK-NEXT: Kind: GLOBAL -; CHECK-NEXT: GlobalType: I32 -; CHECK-NEXT: GlobalMutable: true +; XCHECK-NEXT: - Module: env +; XCHECK-NEXT: Field: data_external +; XCHECK-NEXT: Kind: GLOBAL +; XCHECK-NEXT: GlobalType: I32 +; XCHECK-NEXT: GlobalMutable: true ; CHECK-NEXT: - Module: env ; CHECK-NEXT: Field: func_external ; CHECK-NEXT: Kind: FUNCTION @@ -90,4 +92,4 @@ declare void @func_external() ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: GLOBAL_GET ; CHECK-NEXT: Index: 1 -; CHECK-NEXT: Content: '0000000001000000' +; CHECK-NEXT: Content: '020000000000000001000000' diff --git a/lld/test/wasm/undefined-data.ll b/lld/test/wasm/undefined-data.ll new file mode 100644 index 00000000000..8063d333efa --- /dev/null +++ b/lld/test/wasm/undefined-data.ll @@ -0,0 +1,16 @@ +; 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=BADRELOC + +target triple = "wasm32-unknown-unknown" + +@data_external = external global i32 + +define i32 @_start() { +entry: + %0 = load i32, i32* @data_external, align 4 + ret i32 %0 +} + +; UNDEF: undefined symbol: data_external +; BADRELOC: undefined-data.ll.tmp.o: relocation of type R_WASM_MEMORY_ADDR_* against undefined data symbol: data_external diff --git a/lld/wasm/Writer.cpp b/lld/wasm/Writer.cpp index 42affb4168a..96c473629cf 100644 --- a/lld/wasm/Writer.cpp +++ b/lld/wasm/Writer.cpp @@ -66,6 +66,7 @@ private: void createCtorFunction(); void calculateInitFunctions(); + void processRelocations(InputChunk *Chunk); void assignIndexes(); void calculateImports(); void calculateExports(); @@ -1018,6 +1019,43 @@ void Writer::calculateTypes() { registerType(E->Signature); } +void Writer::processRelocations(InputChunk *Chunk) { + if (!Chunk->Live) + return; + ObjFile *File = Chunk->File; + ArrayRef<WasmSignature> Types = File->getWasmObj()->types(); + for (const WasmRelocation &Reloc : Chunk->getRelocations()) { + switch (Reloc.Type) { + case R_WASM_TABLE_INDEX_I32: + case R_WASM_TABLE_INDEX_SLEB: { + FunctionSymbol *Sym = File->getFunctionSymbol(Reloc.Index); + if (Sym->hasTableIndex() || !Sym->hasFunctionIndex()) + continue; + Sym->setTableIndex(TableBase + IndirectFunctions.size()); + IndirectFunctions.emplace_back(Sym); + break; + } + case R_WASM_TYPE_INDEX_LEB: + // Mark target type as live + File->TypeMap[Reloc.Index] = registerType(Types[Reloc.Index]); + File->TypeIsUsed[Reloc.Index] = true; + break; + case R_WASM_MEMORY_ADDR_SLEB: + case R_WASM_MEMORY_ADDR_I32: + case R_WASM_MEMORY_ADDR_LEB: { + DataSymbol *DataSym = File->getDataSymbol(Reloc.Index); + if (!Config->Relocatable && !isa<DefinedData>(DataSym) && + !DataSym->isWeak()) + error(File->getName() + + ": relocation of type R_WASM_MEMORY_ADDR_* " + "against undefined data symbol: " + + DataSym->getName()); + break; + } + } + } +} + void Writer::assignIndexes() { assert(InputFunctions.empty()); uint32_t FunctionIndex = NumImportedFunctions; @@ -1037,36 +1075,14 @@ void Writer::assignIndexes() { AddDefinedFunction(Func); } - uint32_t TableIndex = TableBase; - auto HandleRelocs = [&](InputChunk *Chunk) { - if (!Chunk->Live) - return; - ObjFile *File = Chunk->File; - ArrayRef<WasmSignature> Types = File->getWasmObj()->types(); - for (const WasmRelocation &Reloc : Chunk->getRelocations()) { - if (Reloc.Type == R_WASM_TABLE_INDEX_I32 || - Reloc.Type == R_WASM_TABLE_INDEX_SLEB) { - FunctionSymbol *Sym = File->getFunctionSymbol(Reloc.Index); - if (Sym->hasTableIndex() || !Sym->hasFunctionIndex()) - continue; - Sym->setTableIndex(TableIndex++); - IndirectFunctions.emplace_back(Sym); - } else if (Reloc.Type == R_WASM_TYPE_INDEX_LEB) { - // Mark target type as live - File->TypeMap[Reloc.Index] = registerType(Types[Reloc.Index]); - File->TypeIsUsed[Reloc.Index] = true; - } - } - }; - for (ObjFile *File : Symtab->ObjectFiles) { LLVM_DEBUG(dbgs() << "Handle relocs: " << File->getName() << "\n"); for (InputChunk *Chunk : File->Functions) - HandleRelocs(Chunk); + processRelocations(Chunk); for (InputChunk *Chunk : File->Segments) - HandleRelocs(Chunk); + processRelocations(Chunk); for (auto &P : File->CustomSections) - HandleRelocs(P); + processRelocations(P); } assert(InputGlobals.empty()); |

