[WebAssembly] Add placeholders for R_WASM_TABLE_INDEX_REL_SLEB relocations
authorSam Clegg <sbc@chromium.org>
Fri, 29 May 2020 01:39:27 +0000 (18:39 -0700)
committerSam Clegg <sbc@chromium.org>
Fri, 29 May 2020 17:57:26 +0000 (10:57 -0700)
Previously in the object format we punted on this and simply wrote
zeros (and didn't include the function in the elem segment).  With
this change we write a meaningful value which is the segment
relative table index of the associated function.

This matches the that wasm-ld produces in `-r` mode.  This inconsistency
between the output the MC object writer and the wasm-ld object
writer could cause warnings to be emitted when reading back in the
output of `wasm-ld -r`.  See:
https://github.com/emscripten-core/emscripten/issues/11217

This only applies to this one relocation type which is only generated
when compiling in PIC mode.

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

lld/wasm/InputFiles.cpp
lld/wasm/InputFiles.h
llvm/lib/MC/WasmObjectWriter.cpp
llvm/test/MC/WebAssembly/reloc-pic.s

index b7d90fe..7390575 100644 (file)
@@ -122,11 +122,14 @@ uint32_t ObjFile::calcNewAddend(const WasmRelocation &reloc) const {
 uint32_t ObjFile::calcExpectedValue(const WasmRelocation &reloc) const {
   switch (reloc.Type) {
   case R_WASM_TABLE_INDEX_I32:
-  case R_WASM_TABLE_INDEX_SLEB:
-  case R_WASM_TABLE_INDEX_REL_SLEB: {
+  case R_WASM_TABLE_INDEX_SLEB: {
     const WasmSymbol &sym = wasmObj->syms()[reloc.Index];
     return tableEntries[sym.Info.ElementIndex];
   }
+  case R_WASM_TABLE_INDEX_REL_SLEB: {
+    const WasmSymbol &sym = wasmObj->syms()[reloc.Index];
+    return tableEntriesRel[sym.Info.ElementIndex];
+  }
   case R_WASM_MEMORY_ADDR_SLEB:
   case R_WASM_MEMORY_ADDR_I32:
   case R_WASM_MEMORY_ADDR_LEB:
@@ -266,6 +269,7 @@ void ObjFile::parse(bool ignoreComdats) {
   // verifying the existing table index relocations
   uint32_t totalFunctions =
       wasmObj->getNumImportedFunctions() + wasmObj->functions().size();
+  tableEntriesRel.resize(totalFunctions);
   tableEntries.resize(totalFunctions);
   for (const WasmElemSegment &seg : wasmObj->elements()) {
     if (seg.Offset.Opcode != WASM_OPCODE_I32_CONST)
@@ -274,6 +278,7 @@ void ObjFile::parse(bool ignoreComdats) {
     for (uint32_t index = 0; index < seg.Functions.size(); index++) {
 
       uint32_t functionIndex = seg.Functions[index];
+      tableEntriesRel[functionIndex] = index;
       tableEntries[functionIndex] = offset + index;
     }
   }
index bf4a4ec..661aa89 100644 (file)
@@ -118,6 +118,7 @@ public:
   std::vector<bool> typeIsUsed;
   // Maps function indices to table indices
   std::vector<uint32_t> tableEntries;
+  std::vector<uint32_t> tableEntriesRel;
   std::vector<bool> keptComdats;
   std::vector<InputSegment *> segments;
   std::vector<InputFunction *> functions;
index 0c09f99..c6a2789 100644 (file)
@@ -565,7 +565,10 @@ WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
     // Provisional value is table address of the resolved symbol itself
     const MCSymbolWasm *Sym = resolveSymbol(*RelEntry.Symbol);
     assert(Sym->isFunction());
-    return TableIndices[Sym];
+    if (RelEntry.Type == wasm::R_WASM_TABLE_INDEX_REL_SLEB)
+      return TableIndices[Sym] - InitialTableOffset;
+    else
+      return TableIndices[Sym];
   }
   case wasm::R_WASM_TYPE_INDEX_LEB:
     // Provisional value is same as the index
@@ -1559,7 +1562,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm,
       // purely to make the object file's provisional values readable, and is
       // ignored by the linker, which re-calculates the relocations itself.
       if (Rel.Type != wasm::R_WASM_TABLE_INDEX_I32 &&
-          Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB)
+          Rel.Type != wasm::R_WASM_TABLE_INDEX_SLEB &&
+          Rel.Type != wasm::R_WASM_TABLE_INDEX_REL_SLEB)
         return;
       assert(Rel.Symbol->isFunction());
       const MCSymbolWasm &WS = *resolveSymbol(*Rel.Symbol);
index 626f8d9..4732b7e 100644 (file)
@@ -68,7 +68,7 @@ hidden_func:
 # CHECK-NEXT:         Table:
 # CHECK-NEXT:           ElemType:        FUNCREF
 # CHECK-NEXT:           Limits:
-# CHECK-NEXT:             Initial:         0x00000000
+# CHECK-NEXT:             Initial:         0x00000001
 # CHECK-NEXT:       - Module:          env
 # CHECK-NEXT:         Field:           default_func
 # CHECK-NEXT:         Kind:            FUNCTION
@@ -85,6 +85,12 @@ hidden_func:
 # CHECK-NEXT:         GlobalMutable:   true
 # CHECK-NEXT:   - Type:            FUNCTION
 # CHECK-NEXT:     FunctionTypes:   [ 0, 0, 0, 0, 0 ]
+# CHECK-NEXT:   - Type:            ELEM
+# CHECK-NEXT:     Segments:
+# CHECK-NEXT:        Offset:
+# CHECK-NEXT:          Opcode:          I32_CONST
+# CHECK-NEXT:          Value:           1
+# CHECK-NEXT:        Functions:       [ 5 ]
 # CHECK-NEXT:   - Type:            DATACOUNT
 # CHECK-NEXT:     Count:           1
 # CHECK-NEXT:   - Type:            CODE