From: Sam Clegg Date: Thu, 25 Apr 2019 17:11:54 +0000 (+0000) Subject: [WebAssembly] Always take into account added when applying runtime relocations X-Git-Tag: llvmorg-10-init~7017 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b685ddf28882cf3b92575bc3ed7a42665324664e;p=platform%2Fupstream%2Fllvm.git [WebAssembly] Always take into account added when applying runtime relocations The code we generate for applying data relocations at runtime omitted the symbols with GOT entries. Also refactor the code to reduce duplication. Differential Revision: https://reviews.llvm.org/D61111 llvm-svn: 359207 --- diff --git a/lld/test/wasm/shared.ll b/lld/test/wasm/shared.ll index 678d628..50a4c8b 100644 --- a/lld/test/wasm/shared.ll +++ b/lld/test/wasm/shared.ll @@ -9,8 +9,14 @@ target triple = "wasm32-unknown-unknown" @indirect_func = local_unnamed_addr global i32 ()* @foo, align 4 @indirect_func_external = local_unnamed_addr global void ()* @func_external, align 4 +; Test data relocations @data_addr = local_unnamed_addr global i32* @data, align 4 +; .. against external symbols @data_addr_external = local_unnamed_addr global i32* @data_external, align 4 +; .. including addends +%struct.s = type { i32, i32 } +@extern_struct = external global %struct.s +@extern_struct_internal_ptr = local_unnamed_addr global i32* getelementptr inbounds (%struct.s, %struct.s* @extern_struct, i32 0, i32 1), align 4 define hidden i32 @foo() { entry: @@ -46,7 +52,7 @@ declare void @func_external() ; CHECK: Sections: ; CHECK-NEXT: - Type: CUSTOM ; CHECK-NEXT: Name: dylink -; CHECK-NEXT: MemorySize: 20 +; CHECK-NEXT: MemorySize: 24 ; CHECK-NEXT: MemoryAlignment: 2 ; CHECK-NEXT: TableSize: 3 ; CHECK-NEXT: TableAlignment: 0 @@ -98,6 +104,11 @@ declare void @func_external() ; CHECK-NEXT: Kind: GLOBAL ; CHECK-NEXT: GlobalType: I32 ; CHECK-NEXT: GlobalMutable: true +; CHECK-NEXT: - Module: GOT.mem +; CHECK-NEXT: Field: extern_struct +; CHECK-NEXT: Kind: GLOBAL +; CHECK-NEXT: GlobalType: I32 +; CHECK-NEXT: GlobalMutable: true ; CHECK-NEXT: - Type: FUNCTION ; CHECK: - Type: EXPORT @@ -125,7 +136,7 @@ declare void @func_external() ; CHECK-NEXT: Body: 10020B ; CHECK-NEXT: - Index: 2 ; CHECK-NEXT: Locals: [] -; CHECK-NEXT: Body: 230141046A230241016A360200230141086A230241026A3602002301410C6A230141006A360200230141106A23033602000B +; CHECK-NEXT: Body: 230141046A230241016A360200230141086A23043602002301410C6A230141006A360200230141106A2303360200230141146A230541046A3602000B ; check the data segment initialized with __memory_base global as offset @@ -136,4 +147,4 @@ declare void @func_external() ; CHECK-NEXT: Offset: ; CHECK-NEXT: Opcode: GLOBAL_GET ; CHECK-NEXT: Index: 1 -; CHECK-NEXT: Content: '0200000001000000020000000000000000000000' +; CHECK-NEXT: Content: '020000000100000002000000000000000000000000000000' diff --git a/lld/wasm/InputChunks.cpp b/lld/wasm/InputChunks.cpp index b609069..735eb77 100644 --- a/lld/wasm/InputChunks.cpp +++ b/lld/wasm/InputChunks.cpp @@ -301,10 +301,19 @@ void InputFunction::writeTo(uint8_t *Buf) const { // This is only called when generating shared libaries (PIC) where address are // not known at static link time. void InputSegment::generateRelocationCode(raw_ostream &OS) const { + LLVM_DEBUG(dbgs() << "generating runtime relocations: " << getName() + << " count=" << Relocations.size() << "\n"); + + // TODO(sbc): Encode the relocations in the data section and write a loop + // here to apply them. uint32_t SegmentVA = OutputSeg->StartVA + OutputSegmentOffset; for (const WasmRelocation &Rel : Relocations) { uint32_t Offset = Rel.Offset - getInputSectionOffset(); - uint32_t OutputVA = SegmentVA + Offset; + uint32_t OutputOffset = SegmentVA + Offset; + + LLVM_DEBUG(dbgs() << "gen reloc: type=" << relocTypeToString(Rel.Type) + << " addend=" << Rel.Addend << " index=" << Rel.Index + << " output offset=" << OutputOffset << "\n"); // Get __memory_base writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); @@ -312,38 +321,28 @@ void InputSegment::generateRelocationCode(raw_ostream &OS) const { // Add the offset of the relocation writeU8(OS, WASM_OPCODE_I32_CONST, "I32_CONST"); - writeSleb128(OS, OutputVA, "offset"); + writeSleb128(OS, OutputOffset, "offset"); writeU8(OS, WASM_OPCODE_I32_ADD, "ADD"); + Symbol *Sym = File->getSymbol(Rel); // Now figure out what we want to store - switch (Rel.Type) { - case R_WASM_TABLE_INDEX_I32: - // Add the table index to the __table_base + if (Sym->hasGOTIndex()) { writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); - writeUleb128(OS, WasmSym::TableBase->getGlobalIndex(), "table_base"); - writeU8(OS, WASM_OPCODE_I32_CONST, "CONST"); - writeSleb128(OS, File->calcNewValue(Rel), "new table index"); - writeU8(OS, WASM_OPCODE_I32_ADD, "ADD"); - break; - case R_WASM_MEMORY_ADDR_I32: { - Symbol *Sym = File->getSymbol(Rel); - if (Sym->isLocal() || Sym->isHidden()) { - // Hidden/Local data symbols are accessed via known offset from - // __memory_base - writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); - writeUleb128(OS, WasmSym::MemoryBase->getGlobalIndex(), "memory_base"); + writeUleb128(OS, Sym->getGOTIndex(), "global index"); + if (Rel.Addend) { writeU8(OS, WASM_OPCODE_I32_CONST, "CONST"); - writeSleb128(OS, File->calcNewValue(Rel), "new memory offset"); + writeSleb128(OS, Rel.Addend, "addend"); writeU8(OS, WASM_OPCODE_I32_ADD, "ADD"); - } else { - // Default data symbols are accessed via imported GOT globals - writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); - writeUleb128(OS, Sym->getGOTIndex(), "global index"); } - break; - } - default: - llvm_unreachable("unexpected relocation type in data segment"); + } else { + const GlobalSymbol* BaseSymbol = WasmSym::MemoryBase; + if (Rel.Type == R_WASM_TABLE_INDEX_I32) + BaseSymbol = WasmSym::TableBase; + writeU8(OS, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET"); + writeUleb128(OS, BaseSymbol->getGlobalIndex(), "base"); + writeU8(OS, WASM_OPCODE_I32_CONST, "CONST"); + writeSleb128(OS, File->calcNewValue(Rel), "offset"); + writeU8(OS, WASM_OPCODE_I32_ADD, "ADD"); } // Store that value at the virtual address diff --git a/lld/wasm/Symbols.cpp b/lld/wasm/Symbols.cpp index c2bd003..74fa723 100644 --- a/lld/wasm/Symbols.cpp +++ b/lld/wasm/Symbols.cpp @@ -97,6 +97,9 @@ void Symbol::setOutputSymbolIndex(uint32_t Index) { void Symbol::setGOTIndex(uint32_t Index) { LLVM_DEBUG(dbgs() << "setGOTIndex " << Name << " -> " << Index << "\n"); assert(GOTIndex == INVALID_INDEX); + // Any symbol that is assigned a GOT entry must be exported othewise the + // dynamic linker won't be able create the entry that contains it. + ForceExport = true; GOTIndex = Index; }