[WebAssembly] Add placeholders for R_WASM_TABLE_INDEX_REL_SLEB relocations

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
This commit is contained in:
Sam Clegg
2020-05-28 18:39:27 -07:00
parent 61412b762d
commit 81443ac1bc
4 changed files with 21 additions and 5 deletions

View 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;
}
}

View 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;

View 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);

View 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