mirror of
https://github.com/intel/llvm.git
synced 2026-01-20 10:58:11 +08:00
[WebAssembly] Verify contents of relocation target before writing it
Verify that the location where a relocation is about the be applied contains the expected existing value. This is essentially a sanity check to catch bugs in the compiler and the linker. Differential Revision: https://reviews.llvm.org/D44349 llvm-svn: 327325
This commit is contained in:
@@ -60,6 +60,37 @@ uint32_t ObjFile::calcNewIndex(const WasmRelocation &Reloc) const {
|
||||
return Symbols[Reloc.Index]->getOutputSymbolIndex();
|
||||
}
|
||||
|
||||
// Calculate the value we expect to find at the relocation location.
|
||||
// This is used as a sanity check before applying a relocation to a given
|
||||
// location. It is useful for catching bugs in the compiler and linker.
|
||||
uint32_t ObjFile::calcExpectedValue(const WasmRelocation &Reloc) const {
|
||||
switch (Reloc.Type) {
|
||||
case R_WEBASSEMBLY_TABLE_INDEX_I32:
|
||||
case R_WEBASSEMBLY_TABLE_INDEX_SLEB: {
|
||||
const WasmSymbol& Sym = WasmObj->syms()[Reloc.Index];
|
||||
return TableEntries[Sym.Info.ElementIndex];
|
||||
}
|
||||
case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
|
||||
case R_WEBASSEMBLY_MEMORY_ADDR_I32:
|
||||
case R_WEBASSEMBLY_MEMORY_ADDR_LEB: {
|
||||
const WasmSymbol& Sym = WasmObj->syms()[Reloc.Index];
|
||||
if (Sym.isUndefined())
|
||||
return 0;
|
||||
const WasmSegment& Segment = WasmObj->dataSegments()[Sym.Info.DataRef.Segment];
|
||||
return Segment.Data.Offset.Value.Int32 + Sym.Info.DataRef.Offset;
|
||||
}
|
||||
case R_WEBASSEMBLY_TYPE_INDEX_LEB:
|
||||
return Reloc.Index;
|
||||
case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
|
||||
case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: {
|
||||
const WasmSymbol& Sym = WasmObj->syms()[Reloc.Index];
|
||||
return Sym.Info.ElementIndex;
|
||||
}
|
||||
default:
|
||||
llvm_unreachable("unknown relocation type");
|
||||
}
|
||||
}
|
||||
|
||||
// Translate from the relocation's index into the final linked output value.
|
||||
uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const {
|
||||
switch (Reloc.Type) {
|
||||
@@ -97,6 +128,22 @@ void ObjFile::parse() {
|
||||
Bin.release();
|
||||
WasmObj.reset(Obj);
|
||||
|
||||
// Build up a map of function indices to table indices for use when
|
||||
// verifying the existing table index relocations
|
||||
uint32_t TotalFunctions =
|
||||
WasmObj->getNumImportedFunctions() + WasmObj->functions().size();
|
||||
TableEntries.resize(TotalFunctions);
|
||||
for (const WasmElemSegment &Seg : WasmObj->elements()) {
|
||||
if (Seg.Offset.Opcode != WASM_OPCODE_I32_CONST)
|
||||
fatal(toString(this) + ": invalid table elements");
|
||||
uint32_t Offset = Seg.Offset.Value.Int32;
|
||||
for (uint32_t Index = 0; Index < Seg.Functions.size(); Index++) {
|
||||
|
||||
uint32_t FunctionIndex = Seg.Functions[Index];
|
||||
TableEntries[FunctionIndex] = Offset + Index;
|
||||
}
|
||||
}
|
||||
|
||||
// Find the code and data sections. Wasm objects can have at most one code
|
||||
// and one data section.
|
||||
for (const SectionRef &Sec : WasmObj->sections()) {
|
||||
|
||||
Reference in New Issue
Block a user