[lld] r327325 - [WebAssembly] Verify contents of relocation target before writing it
Sam Clegg via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 12 12:54:26 PDT 2018
Author: sbc
Date: Mon Mar 12 12:54:26 2018
New Revision: 327325
URL: http://llvm.org/viewvc/llvm-project?rev=327325&view=rev
Log:
[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
Modified:
lld/trunk/wasm/InputChunks.cpp
lld/trunk/wasm/InputFiles.cpp
lld/trunk/wasm/InputFiles.h
Modified: lld/trunk/wasm/InputChunks.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputChunks.cpp?rev=327325&r1=327324&r2=327325&view=diff
==============================================================================
--- lld/trunk/wasm/InputChunks.cpp (original)
+++ lld/trunk/wasm/InputChunks.cpp Mon Mar 12 12:54:26 2018
@@ -61,6 +61,7 @@ void InputChunk::writeTo(uint8_t *Buf) c
for (const WasmRelocation &Rel : Relocations) {
uint8_t *Loc = Buf + Rel.Offset + Off;
uint32_t Value = File->calcNewValue(Rel);
+ uint32_t ExistingValue;
DEBUG(dbgs() << "apply reloc: type=" << ReloctTypeToString(Rel.Type)
<< " addend=" << Rel.Addend << " index=" << Rel.Index
<< " value=" << Value << " offset=" << Rel.Offset << "\n");
@@ -70,19 +71,28 @@ void InputChunk::writeTo(uint8_t *Buf) c
case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:
case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:
case R_WEBASSEMBLY_MEMORY_ADDR_LEB:
+ ExistingValue = decodeULEB128(Loc);
encodeULEB128(Value, Loc, 5);
break;
case R_WEBASSEMBLY_TABLE_INDEX_SLEB:
case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
+ ExistingValue = static_cast<uint32_t>(decodeSLEB128(Loc));
encodeSLEB128(static_cast<int32_t>(Value), Loc, 5);
break;
case R_WEBASSEMBLY_TABLE_INDEX_I32:
case R_WEBASSEMBLY_MEMORY_ADDR_I32:
+ ExistingValue = static_cast<uint32_t>(read32le(Loc));
write32le(Loc, Value);
break;
default:
llvm_unreachable("unknown relocation type");
}
+
+ uint32_t ExpectedValue = File->calcExpectedValue(Rel);
+ if (ExpectedValue != ExistingValue)
+ error("unexpected existing value for " + ReloctTypeToString(Rel.Type) +
+ ": existing=" + Twine(ExistingValue) +
+ " expected=" + Twine(ExpectedValue));
}
}
Modified: lld/trunk/wasm/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.cpp?rev=327325&r1=327324&r2=327325&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.cpp (original)
+++ lld/trunk/wasm/InputFiles.cpp Mon Mar 12 12:54:26 2018
@@ -60,6 +60,37 @@ uint32_t ObjFile::calcNewIndex(const Was
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()) {
Modified: lld/trunk/wasm/InputFiles.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/wasm/InputFiles.h?rev=327325&r1=327324&r2=327325&view=diff
==============================================================================
--- lld/trunk/wasm/InputFiles.h (original)
+++ lld/trunk/wasm/InputFiles.h Mon Mar 12 12:54:26 2018
@@ -94,12 +94,16 @@ public:
uint32_t calcNewIndex(const WasmRelocation &Reloc) const;
uint32_t calcNewValue(const WasmRelocation &Reloc) const;
+ uint32_t calcExpectedValue(const WasmRelocation &Reloc) const;
const WasmSection *CodeSection = nullptr;
const WasmSection *DataSection = nullptr;
+ // Maps input type indices to output type indices
std::vector<uint32_t> TypeMap;
std::vector<bool> TypeIsUsed;
+ // Maps function indices to table indices
+ std::vector<uint32_t> TableEntries;
std::vector<InputSegment *> Segments;
std::vector<InputFunction *> Functions;
std::vector<InputGlobal *> Globals;
More information about the llvm-commits
mailing list