[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
This commit is contained in:
Sam Clegg 2018-01-23 01:23:17 +00:00
parent 4ce341ffb6
commit 60ec30340f
5 changed files with 56 additions and 62 deletions

View File

@ -499,25 +499,44 @@ static const MCSymbolWasm* ResolveSymbol(const MCSymbolWasm& Symbol) {
} }
// Compute a value to write into the code at the location covered // Compute a value to write into the code at the location covered
// by RelEntry. This value isn't used by the static linker, since // by RelEntry. This value isn't used by the static linker; it just serves
// we have addends; it just serves to make the code more readable // to make the object format more readable and more likely to be directly
// and to make standalone wasm modules directly usable. // useable.
uint32_t uint32_t
WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) { WasmObjectWriter::getProvisionalValue(const WasmRelocationEntry &RelEntry) {
const MCSymbolWasm *Sym = ResolveSymbol(*RelEntry.Symbol);
// For undefined symbols, use zero switch (RelEntry.Type) {
if (!Sym->isDefined()) case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
return 0; 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]; uint32_t GlobalIndex = SymbolIndices[Sym];
const WasmGlobal& Global = Globals[GlobalIndex - NumGlobalImports]; const WasmGlobal& Global = Globals[GlobalIndex - NumGlobalImports];
uint64_t Address = Global.InitialValue + RelEntry.Addend; uint64_t Address = Global.InitialValue + RelEntry.Addend;
// Ignore overflow. LLVM allows address arithmetic to silently wrap. // Ignore overflow. LLVM allows address arithmetic to silently wrap.
uint32_t Value = Address; return Address;
}
return Value; default:
llvm_unreachable("invalid relocation type");
}
} }
static void addData(SmallVectorImpl<char> &DataBytes, static void addData(SmallVectorImpl<char> &DataBytes,
@ -564,32 +583,19 @@ static void addData(SmallVectorImpl<char> &DataBytes,
DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n"); DEBUG(dbgs() << "addData -> " << DataBytes.size() << "\n");
} }
uint32_t WasmObjectWriter::getRelocationIndexValue( uint32_t
const WasmRelocationEntry &RelEntry) { WasmObjectWriter::getRelocationIndexValue(const WasmRelocationEntry &RelEntry) {
switch (RelEntry.Type) { if (RelEntry.Type == wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB) {
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:
if (!TypeIndices.count(RelEntry.Symbol)) if (!TypeIndices.count(RelEntry.Symbol))
report_fatal_error("symbol not found in type index space: " + report_fatal_error("symbol not found in type index space: " +
RelEntry.Symbol->getName()); RelEntry.Symbol->getName());
return TypeIndices[RelEntry.Symbol]; 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 // Apply the portions of the relocation records that we can handle ourselves
@ -603,35 +609,23 @@ void WasmObjectWriter::applyRelocations(
RelEntry.Offset; RelEntry.Offset;
DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n"); DEBUG(dbgs() << "applyRelocation: " << RelEntry << "\n");
uint32_t Value = getProvisionalValue(RelEntry);
switch (RelEntry.Type) { switch (RelEntry.Type) {
case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB: case wasm::R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB: case wasm::R_WEBASSEMBLY_TYPE_INDEX_LEB:
case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB: { case wasm::R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
uint32_t Index = getRelocationIndexValue(RelEntry); case wasm::R_WEBASSEMBLY_MEMORY_ADDR_LEB:
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);
WritePatchableLEB(Stream, Value, Offset); WritePatchableLEB(Stream, Value, Offset);
break; break;
} case wasm::R_WEBASSEMBLY_TABLE_INDEX_I32:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32: { case wasm::R_WEBASSEMBLY_MEMORY_ADDR_I32:
uint32_t Value = getProvisionalValue(RelEntry);
WriteI32(Stream, Value, Offset); WriteI32(Stream, Value, Offset);
break; break;
} case wasm::R_WEBASSEMBLY_TABLE_INDEX_SLEB:
case wasm::R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
WritePatchableSLEB(Stream, Value, Offset);
break;
default: default:
llvm_unreachable("invalid relocation type"); llvm_unreachable("invalid relocation type");
} }

View File

@ -34,5 +34,5 @@ declare void @f1(i32) #1
; CHECK: - Type: DATA ; CHECK: - Type: DATA
; CHECK-NEXT: Relocations: ; CHECK-NEXT: Relocations:
; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32
; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Index: 0
; CHECK-NEXT: Offset: 0x00000006 ; CHECK-NEXT: Offset: 0x00000006

View File

@ -42,6 +42,6 @@ entry:
; CHECK: Relocation { ; CHECK: Relocation {
; CHECK: Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB (1) ; CHECK: Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB (1)
; CHECK: Offset: 0x1E ; CHECK: Offset: 0x1E
; CHECK: Index: 0x1 ; CHECK: Index: 0x2
; CHECK: } ; CHECK: }
; CHECK: } ; CHECK: }

View File

@ -95,7 +95,7 @@ declare void @func3()
; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Index: 0
; CHECK-NEXT: Offset: 0x00000004 ; CHECK-NEXT: Offset: 0x00000004
; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB
; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Index: 5
; CHECK-NEXT: Offset: 0x0000000F ; CHECK-NEXT: Offset: 0x0000000F
; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB
; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Index: 0
@ -107,7 +107,7 @@ declare void @func3()
; CHECK-NEXT: Index: 2 ; CHECK-NEXT: Index: 2
; CHECK-NEXT: Offset: 0x0000002C ; CHECK-NEXT: Offset: 0x0000002C
; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB
; CHECK-NEXT: Index: 2 ; CHECK-NEXT: Index: 7
; CHECK-NEXT: Offset: 0x00000037 ; CHECK-NEXT: Offset: 0x00000037
; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB ; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB
; CHECK-NEXT: Index: 0 ; CHECK-NEXT: Index: 0

View File

@ -174,7 +174,7 @@ entry:
; CHECK-NEXT: Index: 1 ; CHECK-NEXT: Index: 1
; CHECK-NEXT: Offset: 0x0000000F ; CHECK-NEXT: Offset: 0x0000000F
; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32 ; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32
; CHECK-NEXT: Index: 2 ; CHECK-NEXT: Index: 0
; CHECK-NEXT: Offset: 0x00000018 ; CHECK-NEXT: Offset: 0x00000018
; CHECK-NEXT: Segments: ; CHECK-NEXT: Segments:
; CHECK-NEXT: - SectionOffset: 6 ; CHECK-NEXT: - SectionOffset: 6