From d291c78308490024058968511bbdf76d6e5852bc Mon Sep 17 00:00:00 2001 From: Sam Clegg Date: Mon, 12 Jun 2017 23:52:44 +0000 Subject: [PATCH] [WebAssembly] MC: Fix value of R_WEBASSEMBLY_TABLE_INDEX relocations Previously we were writing the value function index space value but for these types of relocations we want to be writing the table element index space value. Add a test case for these relocation types that fails without this change. Differential Revision: https://reviews.llvm.org/D33962 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@305253 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/MC/WasmObjectWriter.cpp | 34 +++++++++++--------- test/MC/WebAssembly/func-address.ll | 48 +++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 14 deletions(-) create mode 100644 test/MC/WebAssembly/func-address.ll diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp index 4b3dc6e0c21..99d577dab9e 100644 --- a/lib/MC/WasmObjectWriter.cpp +++ b/lib/MC/WasmObjectWriter.cpp @@ -181,7 +181,10 @@ class WasmObjectWriter : public MCObjectWriter { // Index values to use for fixing up call_indirect type indices. // Maps function symbols to the index of the type of the function DenseMap TypeIndices; - + // Maps function symbols to the table element index space. Used + // for TABLE_INDEX relocation types (i.e. address taken functions). + DenseMap IndirectSymbolIndices; + // Maps function/global symbols to the function/global index space. DenseMap SymbolIndices; DenseMap @@ -210,6 +213,7 @@ private: DataRelocations.clear(); TypeIndices.clear(); SymbolIndices.clear(); + IndirectSymbolIndices.clear(); FunctionTypeIndices.clear(); MCObjectWriter::reset(); } @@ -233,7 +237,7 @@ private: void writeTypeSection(const SmallVector &FunctionTypes); void writeImportSection(const SmallVector &Imports); void writeFunctionSection(const SmallVector &Functions); - void writeTableSection(const SmallVector &TableElems); + void writeTableSection(uint32_t NumElements); void writeMemorySection(const SmallVector &DataBytes); void writeGlobalSection(const SmallVector &Globals); void writeExportSection(const SmallVector &Exports); @@ -464,9 +468,11 @@ static uint32_t ProvisionalValue(const WasmRelocationEntry &RelEntry) { uint32_t WasmObjectWriter::getRelocationIndexValue( const WasmRelocationEntry &RelEntry) { switch (RelEntry.Type) { - case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB: case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32: + assert(IndirectSymbolIndices.count(RelEntry.Symbol)); + return IndirectSymbolIndices[RelEntry.Symbol]; + case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_LEB: case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_SLEB: case wasm::R_WEBASSEMBLY_GLOBAL_ADDR_I32: @@ -617,21 +623,19 @@ void WasmObjectWriter::writeFunctionSection( endSection(Section); } -void WasmObjectWriter::writeTableSection( - const SmallVector &TableElems) { +void WasmObjectWriter::writeTableSection(uint32_t NumElements) { // For now, always emit the table section, since indirect calls are not // valid without it. In the future, we could perhaps be more clever and omit // it if there are no indirect calls. + SectionBookkeeping Section; startSection(Section, wasm::WASM_SEC_TABLE); - // The number of tables, fixed to 1 for now. - encodeULEB128(1, getStream()); - - encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); - - encodeULEB128(0, getStream()); // flags - encodeULEB128(TableElems.size(), getStream()); // initial + encodeULEB128(1, getStream()); // The number of tables. + // Fixed to 1 for now. + encodeSLEB128(wasm::WASM_TYPE_ANYFUNC, getStream()); // Type of table + encodeULEB128(0, getStream()); // flags + encodeULEB128(NumElements, getStream()); // initial endSection(Section); } @@ -1072,8 +1076,10 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, } // If needed, prepare the function to be called indirectly. - if (IsAddressTaken.count(&WS)) + if (IsAddressTaken.count(&WS)) { + IndirectSymbolIndices[&WS] = TableElems.size(); TableElems.push_back(Index); + } } else { if (WS.isTemporary() && !WS.getSize()) continue; @@ -1180,7 +1186,7 @@ void WasmObjectWriter::writeObject(MCAssembler &Asm, writeTypeSection(FunctionTypes); writeImportSection(Imports); writeFunctionSection(Functions); - writeTableSection(TableElems); + writeTableSection(TableElems.size()); writeMemorySection(DataBytes); writeGlobalSection(Globals); writeExportSection(Exports); diff --git a/test/MC/WebAssembly/func-address.ll b/test/MC/WebAssembly/func-address.ll new file mode 100644 index 00000000000..c0a9d9a801f --- /dev/null +++ b/test/MC/WebAssembly/func-address.ll @@ -0,0 +1,48 @@ +; RUN: llc -mtriple wasm32-unknown-unknown-wasm -O2 -filetype=obj %s -o - | llvm-readobj -r -s -expand-relocs | FileCheck %s + +declare i32 @import1() +declare i32 @import2() +declare i32 @import3() + +; call the imports to make sure they are included in the imports section +define hidden void @call_imports() #0 { +entry: + %call = call i32 @import1() + %call1 = call i32 @import2() + ret void +} + +; take the address of the third import. This should generate a TABLE_INDEX +; relocation with index of 0 since its the first and only address taken +; function. +define hidden void @call_indirect() #0 { +entry: + %adr = alloca i32 ()*, align 4 + store i32 ()* @import3, i32 ()** %adr, align 4 + ret void +} + +; CHECK: Section { +; CHECK: Type: ELEM (0x9) +; CHECK: Size: 7 +; CHECK: Offset: 165 +; CHECK: } + +; CHECK: Relocations [ +; CHECK: Section (9) CODE { +; CHECK: Relocation { +; CHECK: Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB (0) +; CHECK: Offset: 0x4 +; CHECK: Index: 0x0 +; CHECK: } +; CHECK: Relocation { +; CHECK: Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB (0) +; CHECK: Offset: 0xB +; CHECK: Index: 0x1 +; CHECK: } +; CHECK: Relocation { +; CHECK: Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB (1) +; CHECK: Offset: 0x1A +; CHECK: Index: 0x0 +; CHECK: } +; CHECK: } -- 2.50.1