From 60ec30340ff0c9b51fd1da4b7173dc087e2a96ae Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Tue, 23 Jan 2018 01:23:17 +0000 Subject: [PATCH] [WebAssembly] Store function index rather than table index in TABLE_INDEX relocations Relocations of type R_WEBASSEMBLY_TABLE_INDEX represent places where the table index for a given function is needed. While the value stored in this location is a table index, the index in the relocation entry itself is a function index (the index of the function which is to be called indirectly). This is how is was spec'd originally but the LLVM implementation didn't do this. This makes things a little simpler in the linker since the table in the input file can essentially be ignored that the output table can be created purely based on these relocations. Patch by Nicholas Wilson! Differential Revision: https://reviews.llvm.org/D42080 llvm-svn: 323165 --- llvm/lib/MC/WasmObjectWriter.cpp | 112 ++++++++++------------ llvm/test/MC/WebAssembly/external-func-address.ll | 2 +- llvm/test/MC/WebAssembly/func-address.ll | 2 +- llvm/test/MC/WebAssembly/global-ctor-dtor.ll | 4 +- llvm/test/MC/WebAssembly/weak-alias.ll | 2 +- 5 files changed, 58 insertions(+), 64 deletions(-) diff --git a/llvm/lib/MC/WasmObjectWriter.cpp b/llvm/lib/MC/WasmObjectWriter.cpp index 473f9fe..f70d57f 100644 --- a/llvm/lib/MC/WasmObjectWriter.cpp +++ b/llvm/lib/MC/WasmObjectWriter.cpp @@ -499,25 +499,44 @@ static const MCSymbolWasm* ResolveSymbol(const MCSymbolWasm& Symbol) { } // Compute a value to write into the code at the location covered -// by RelEntry. This value isn't used by the static linker, since -// we have addends; it just serves to make the code more readable -// and to make standalone wasm modules directly usable. +// by RelEntry. This value isn't used by the static linker; it just serves +// to make the object format more readable and more likely to be directly +// useable. uint32_t WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) { - const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol); - // For undefined symbols, use zero - if (!Sym->isDefined()) - return 0; - - uint32_t GlobalIndex = SymbolIndices[Sym]; - const WasmGlobal& Global = Globals[GlobalIndex - NumGlobalImports]; - uint64_t Address = Global.InitialValue + RelEntry.Addend; - - // Ignore overflow. LLVM allows address arithmetic to silently wrap. - uint32_t Value = Address; - - return Value; + switch (RelEntry.Type) { + case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: + case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: + // Provitional value is the indirect symbol index + if (!IndirectSymbolIndices.count(RelEntry.Symbol)) + report_fatal_error("symbol not found in table index space: " + + RelEntry.Symbol->getName()); + return IndirectSymbolIndices[RelEntry.Symbol]; + case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: + case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: + case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: + // Provitional value is function/type/global index itself + return getRelocationIndexValue(RelEntry); + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: { + // Provitional value is address of the global + const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol); + // For undefined symbols, use zero + if (!Sym->isDefined()) + return 0; + + uint32_t GlobalIndex = SymbolIndices[Sym]; + const WasmGlobal& Global = Globals[GlobalIndex - NumGlobalImports]; + uint64_t Address = Global.InitialValue + RelEntry.Addend; + + // Ignore overflow. LLVM allows address arithmetic to silently wrap. + return Address; + } + default: + llvm_unreachable("invalid relocation type"); + } } static void addData(SmallVectorImpl &DataBytes, @@ -564,32 +583,19 @@ static void addData(SmallVectorImpl &DataBytes, DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n"); } -uint32_t WasmObjectWriter::getRelocationIndexValue( - const WasmRelocationEntry &RelEntry) { - switch (RelEntry.Type) { - case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: - case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: - if (!IndirectSymbolIndices.count(RelEntry.Symbol)) - report_fatal_error("symbol not found in table index space: " + - RelEntry.Symbol->getName()); - return IndirectSymbolIndices[RelEntry.Symbol]; - case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: - case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: - case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: - case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: - case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: - if (!SymbolIndices.count(RelEntry.Symbol)) - report_fatal_error("symbol not found in function/global index space: " + - RelEntry.Symbol->getName()); - return SymbolIndices[RelEntry.Symbol]; - case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: +uint32_t +WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) { + if (RelEntry.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB) { if (!TypeIndices.count(RelEntry.Symbol)) report_fatal_error("symbol not found in type index space: " + RelEntry.Symbol->getName()); return TypeIndices[RelEntry.Symbol]; - default: - llvm_unreachable("invalid relocation type"); } + + if (!SymbolIndices.count(RelEntry.Symbol)) + report_fatal_error("symbol not found in function/global index space: " + + RelEntry.Symbol->getName()); + return SymbolIndices[RelEntry.Symbol]; } // Apply the portions of the relocation records that we can handle ourselves @@ -603,35 +609,23 @@ void WasmObjectWriter::applyRelocations( RelEntry.Offset; DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n"); + uint32_t Value = getProvisionalValue(RelEntry); + switch (RelEntry.Type) { - case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: - case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: { - uint32_t Index = getRelocationIndexValue(RelEntry); - WritePatchableSLEB(Stream, Index, Offset); - break; - } - case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: { - uint32_t Index = getRelocationIndexValue(RelEntry); - WriteI32(Stream, Index, Offset); - break; - } - case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: { - uint32_t Value = getProvisionalValue(RelEntry); - WritePatchableSLEB(Stream, Value, Offset); - break; - } - case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: { - uint32_t Value = getProvisionalValue(RelEntry); + case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB: WritePatchableLEB(Stream, Value, Offset); break; - } - case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: { - uint32_t Value = getProvisionalValue(RelEntry); + case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: WriteI32(Stream, Value, Offset); break; - } + case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: + case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB: + WritePatchableSLEB(Stream, Value, Offset); + break; default: llvm_unreachable("invalid relocation type"); } diff --git a/llvm/test/MC/WebAssembly/external-func-address.ll b/llvm/test/MC/WebAssembly/external-func-address.ll index c8dff40..2918152 100644 --- a/llvm/test/MC/WebAssembly/external-func-address.ll +++ b/llvm/test/MC/WebAssembly/external-func-address.ll @@ -34,5 +34,5 @@ declare void @f1(i32) #1 ; CHECK: - Type: DATA ; CHECK-NEXT: Relocations: ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 -; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Offset: 0x00000006 diff --git a/llvm/test/MC/WebAssembly/func-address.ll b/llvm/test/MC/WebAssembly/func-address.ll index 8532aa9..39a968b 100644 --- a/llvm/test/MC/WebAssembly/func-address.ll +++ b/llvm/test/MC/WebAssembly/func-address.ll @@ -42,6 +42,6 @@ entry: ; CHECK: Relocation { ; CHECK: Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB (1) ; CHECK: Offset: 0x1E -; CHECK: Index: 0x1 +; CHECK: Index: 0x2 ; CHECK: } ; CHECK: } diff --git a/llvm/test/MC/WebAssembly/global-ctor-dtor.ll b/llvm/test/MC/WebAssembly/global-ctor-dtor.ll index 75f0044..9f42651 100644 --- a/llvm/test/MC/WebAssembly/global-ctor-dtor.ll +++ b/llvm/test/MC/WebAssembly/global-ctor-dtor.ll @@ -95,7 +95,7 @@ declare void @func3() ; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Offset: 0x00000004 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; CHECK-NEXT: Index: 1 +; CHECK-NEXT: Index: 5 ; CHECK-NEXT: Offset: 0x0000000F ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB ; CHECK-NEXT: Index: 0 @@ -107,7 +107,7 @@ declare void @func3() ; CHECK-NEXT: Index: 2 ; CHECK-NEXT: Offset: 0x0000002C ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB -; CHECK-NEXT: Index: 2 +; CHECK-NEXT: Index: 7 ; CHECK-NEXT: Offset: 0x00000037 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB ; CHECK-NEXT: Index: 0 diff --git a/llvm/test/MC/WebAssembly/weak-alias.ll b/llvm/test/MC/WebAssembly/weak-alias.ll index 83f2eeb..f3c4f4a 100644 --- a/llvm/test/MC/WebAssembly/weak-alias.ll +++ b/llvm/test/MC/WebAssembly/weak-alias.ll @@ -174,7 +174,7 @@ entry: ; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Offset: 0x0000000F ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 -; CHECK-NEXT: Index: 2 +; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Offset: 0x00000018 ; CHECK-NEXT: Segments: ; CHECK-NEXT: - SectionOffset: 6 -- 2.7.4