forked from OSchip/llvm-project
[BOLT] Fix relocation verification
Summary: We verify that relocation information matches a value stored in a binary, i.e. "ExtractedValue == SymbolValue + Addend". However, because of the size of the relocation, and the fact that an addend is always of type int64_t, we have to sign-extend the extracted value, and then we might get mismatch in higher bits in certain scenarios. Hence, we should only compare values that are truncated to a relocation size. Discovered while processing hhvm binary with modified compiler flags. (cherry picked from FBD7462559)
This commit is contained in:
parent
77f35bd0e9
commit
0d729f218b
|
@ -463,6 +463,10 @@ MCPlusBuilder *createMCPlusBuilder(const Triple::ArchType Arch,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int64_t truncateToSize(int64_t Value, unsigned Bytes) {
|
||||||
|
return Value & ((uint64_t) (int64_t) -1 >> (64 - Bytes * 8));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr const char *RewriteInstance::SectionsToOverwrite[];
|
constexpr const char *RewriteInstance::SectionsToOverwrite[];
|
||||||
|
@ -1760,7 +1764,7 @@ void RewriteInstance::readSpecialSections() {
|
||||||
EHFrame = BC->DwCtx->getEHFrame();
|
EHFrame = BC->DwCtx->getEHFrame();
|
||||||
if (opts::DumpEHFrame) {
|
if (opts::DumpEHFrame) {
|
||||||
outs() << "BOLT-INFO: Dumping original binary .eh_frame\n";
|
outs() << "BOLT-INFO: Dumping original binary .eh_frame\n";
|
||||||
EHFrame->dump(outs(), NoneType());
|
EHFrame->dump(outs(), &*BC->MRI, NoneType());
|
||||||
}
|
}
|
||||||
CFIRdWrt.reset(new CFIReaderWriter(*EHFrame));
|
CFIRdWrt.reset(new CFIReaderWriter(*EHFrame));
|
||||||
}
|
}
|
||||||
|
@ -1904,7 +1908,9 @@ bool RewriteInstance::analyzeRelocation(const RelocationRef &Rel,
|
||||||
<< "; address = 0x" << Twine::utohexstr(SymbolAddress + Addend)
|
<< "; address = 0x" << Twine::utohexstr(SymbolAddress + Addend)
|
||||||
<< '\n';
|
<< '\n';
|
||||||
}
|
}
|
||||||
assert(ExtractedValue == SymbolAddress + Addend && "value mismatch");
|
assert(truncateToSize(ExtractedValue, RelSize) ==
|
||||||
|
truncateToSize(SymbolAddress + Addend, RelSize) &&
|
||||||
|
"value mismatch");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1912,7 +1918,8 @@ bool RewriteInstance::analyzeRelocation(const RelocationRef &Rel,
|
||||||
if (!Relocation::isTLS(Rel.getType()) &&
|
if (!Relocation::isTLS(Rel.getType()) &&
|
||||||
SymbolName != "__hot_start" &&
|
SymbolName != "__hot_start" &&
|
||||||
SymbolName != "__hot_end" &&
|
SymbolName != "__hot_end" &&
|
||||||
ExtractedValue != SymbolAddress + Addend - PCRelOffset) {
|
truncateToSize(ExtractedValue, RelSize) !=
|
||||||
|
truncateToSize(SymbolAddress + Addend - PCRelOffset, RelSize)) {
|
||||||
auto Section = Symbol.getSection();
|
auto Section = Symbol.getSection();
|
||||||
SmallString<16> TypeName;
|
SmallString<16> TypeName;
|
||||||
Rel.getTypeName(TypeName);
|
Rel.getTypeName(TypeName);
|
||||||
|
@ -1939,7 +1946,8 @@ bool RewriteInstance::analyzeRelocation(const RelocationRef &Rel,
|
||||||
Relocation::isTLS(Rel.getType()) ||
|
Relocation::isTLS(Rel.getType()) ||
|
||||||
SymbolName == "__hot_start" ||
|
SymbolName == "__hot_start" ||
|
||||||
SymbolName == "__hot_end" ||
|
SymbolName == "__hot_end" ||
|
||||||
ExtractedValue == SymbolAddress + Addend - PCRelOffset) &&
|
truncateToSize(ExtractedValue, RelSize) ==
|
||||||
|
truncateToSize(SymbolAddress + Addend - PCRelOffset, RelSize)) &&
|
||||||
"extracted relocation value should match relocation components");
|
"extracted relocation value should match relocation components");
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -2718,51 +2726,48 @@ void RewriteInstance::emitFunctions() {
|
||||||
object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
|
object::ObjectFile::createObjectFile(ObjectMemBuffer->getMemBufferRef()),
|
||||||
"error creating in-memory object");
|
"error creating in-memory object");
|
||||||
|
|
||||||
auto Resolver = orc::createLambdaResolver(
|
auto Resolver = orc::createLegacyLookupResolver(
|
||||||
[&](const std::string &Name) -> JITSymbol {
|
[&](const std::string &Name) -> JITSymbol {
|
||||||
DEBUG(dbgs() << "BOLT: looking for " << Name << "\n");
|
DEBUG(dbgs() << "BOLT: looking for " << Name << "\n");
|
||||||
if (auto *I = BC->getBinaryDataByName(Name))
|
if (auto *I = BC->getBinaryDataByName(Name))
|
||||||
return JITSymbol(I->getAddress(), JITSymbolFlags());
|
return JITSymbol(I->getAddress(), JITSymbolFlags());
|
||||||
return JITSymbol(nullptr);
|
return JITSymbol(nullptr);
|
||||||
},
|
},
|
||||||
[](const std::string &S) {
|
[](Error Err) { cantFail(std::move(Err), "lookup failed"); });
|
||||||
DEBUG(dbgs() << "BOLT: resolving " << S << "\n");
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
Resolver->setAllowsZeroSymbols(true);
|
Resolver->setAllowsZeroSymbols(true);
|
||||||
|
|
||||||
MCAsmLayout FinalLayout(
|
MCAsmLayout FinalLayout(
|
||||||
static_cast<MCObjectStreamer *>(Streamer.get())->getAssembler());
|
static_cast<MCObjectStreamer *>(Streamer.get())->getAssembler());
|
||||||
|
|
||||||
|
SSP.reset(new decltype(SSP)::element_type());
|
||||||
|
ES.reset(new decltype(ES)::element_type(*SSP));
|
||||||
OLT.reset(new decltype(OLT)::element_type(
|
OLT.reset(new decltype(OLT)::element_type(
|
||||||
[this]() {
|
*ES,
|
||||||
|
[this, &Resolver](orc::VModuleKey Key) {
|
||||||
|
orc::RTDyldObjectLinkingLayer::Resources R;
|
||||||
|
R.MemMgr = EFMM;
|
||||||
|
R.Resolver = Resolver;
|
||||||
// Get memory manager
|
// Get memory manager
|
||||||
return EFMM;
|
return R;
|
||||||
},
|
},
|
||||||
// Loaded notifier
|
// Loaded notifier
|
||||||
[&](orc::RTDyldObjectLinkingLayerBase::ObjHandleT Handle,
|
[&](orc::VModuleKey Key, const object::ObjectFile &Obj,
|
||||||
const orc::RTDyldObjectLinkingLayer::ObjectPtr &Obj,
|
|
||||||
const RuntimeDyld::LoadedObjectInfo &) {
|
const RuntimeDyld::LoadedObjectInfo &) {
|
||||||
// Assign addresses to all sections.
|
// Assign addresses to all sections.
|
||||||
mapFileSections(Handle);
|
mapFileSections(Key);
|
||||||
},
|
},
|
||||||
// Finalized notifier
|
// Finalized notifier
|
||||||
[&](orc::RTDyldObjectLinkingLayerBase::ObjHandleT Handle) {
|
[&](orc::VModuleKey Key) {
|
||||||
// Update output addresses based on the new section map and
|
// Update output addresses based on the new section map and
|
||||||
// layout.
|
// layout.
|
||||||
updateOutputValues(FinalLayout);
|
updateOutputValues(FinalLayout);
|
||||||
}));
|
}));
|
||||||
|
|
||||||
OLT->setProcessAllSections(true);
|
OLT->setProcessAllSections(true);
|
||||||
auto ObjectsHandle = cantFail(
|
auto K = ES->allocateVModule();
|
||||||
OLT->addObject(std::unique_ptr<OwningBinary<object::ObjectFile>>(
|
cantFail(OLT->addObject(K, std::move(ObjectMemBuffer)));
|
||||||
new OwningBinary<object::ObjectFile>(
|
|
||||||
std::move(Obj), std::move(ObjectMemBuffer))),
|
|
||||||
std::move(Resolver)),
|
|
||||||
"failed in addObject()");
|
|
||||||
|
|
||||||
cantFail(OLT->emitAndFinalize(ObjectsHandle));
|
cantFail(OLT->emitAndFinalize(K));
|
||||||
|
|
||||||
if (opts::PrintCacheMetrics) {
|
if (opts::PrintCacheMetrics) {
|
||||||
outs() << "BOLT-INFO: cache metrics after emitting functions:\n";
|
outs() << "BOLT-INFO: cache metrics after emitting functions:\n";
|
||||||
|
@ -2773,8 +2778,7 @@ void RewriteInstance::emitFunctions() {
|
||||||
TempOut->keep();
|
TempOut->keep();
|
||||||
}
|
}
|
||||||
|
|
||||||
void RewriteInstance::mapFileSections(
|
void RewriteInstance::mapFileSections(orc::VModuleKey Key) {
|
||||||
orc::RTDyldObjectLinkingLayer::ObjHandleT &ObjectsHandle) {
|
|
||||||
NewTextSectionStartAddress = NextAvailableAddress;
|
NewTextSectionStartAddress = NextAvailableAddress;
|
||||||
if (BC->HasRelocations) {
|
if (BC->HasRelocations) {
|
||||||
auto TextSection = BC->getUniqueSectionByName(".text");
|
auto TextSection = BC->getUniqueSectionByName(".text");
|
||||||
|
@ -2812,8 +2816,7 @@ void RewriteInstance::mapFileSections(
|
||||||
<< Twine::utohexstr(TextSection->getAllocAddress())
|
<< Twine::utohexstr(TextSection->getAllocAddress())
|
||||||
<< " to 0x" << Twine::utohexstr(NewTextSectionStartAddress)
|
<< " to 0x" << Twine::utohexstr(NewTextSectionStartAddress)
|
||||||
<< '\n');
|
<< '\n');
|
||||||
OLT->mapSectionAddress(ObjectsHandle,
|
OLT->mapSectionAddress(Key, TextSection->getSectionID(),
|
||||||
TextSection->getSectionID(),
|
|
||||||
NewTextSectionStartAddress);
|
NewTextSectionStartAddress);
|
||||||
} else {
|
} else {
|
||||||
for (auto &BFI : BinaryFunctions) {
|
for (auto &BFI : BinaryFunctions) {
|
||||||
|
@ -2828,8 +2831,7 @@ void RewriteInstance::mapFileSections(
|
||||||
<< Twine::utohexstr(FuncSection->getAllocAddress())
|
<< Twine::utohexstr(FuncSection->getAllocAddress())
|
||||||
<< " to 0x" << Twine::utohexstr(Function.getAddress())
|
<< " to 0x" << Twine::utohexstr(Function.getAddress())
|
||||||
<< '\n');
|
<< '\n');
|
||||||
OLT->mapSectionAddress(ObjectsHandle,
|
OLT->mapSectionAddress(Key, FuncSection->getSectionID(),
|
||||||
FuncSection->getSectionID(),
|
|
||||||
Function.getAddress());
|
Function.getAddress());
|
||||||
Function.setImageAddress(FuncSection->getAllocAddress());
|
Function.setImageAddress(FuncSection->getAllocAddress());
|
||||||
Function.setImageSize(FuncSection->getOutputSize());
|
Function.setImageSize(FuncSection->getOutputSize());
|
||||||
|
@ -2849,7 +2851,7 @@ void RewriteInstance::mapFileSections(
|
||||||
DEBUG(dbgs() << "BOLT-DEBUG: mapping " << Section->getName()
|
DEBUG(dbgs() << "BOLT-DEBUG: mapping " << Section->getName()
|
||||||
<< " to 0x" << Twine::utohexstr(JT->getAddress())
|
<< " to 0x" << Twine::utohexstr(JT->getAddress())
|
||||||
<< '\n');
|
<< '\n');
|
||||||
OLT->mapSectionAddress(ObjectsHandle, Section->getSectionID(),
|
OLT->mapSectionAddress(Key, Section->getSectionID(),
|
||||||
JT->getAddress());
|
JT->getAddress());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2882,8 +2884,7 @@ void RewriteInstance::mapFileSections(
|
||||||
<< Twine::utohexstr(ColdPart.getAddress())
|
<< Twine::utohexstr(ColdPart.getAddress())
|
||||||
<< " with size "
|
<< " with size "
|
||||||
<< Twine::utohexstr(ColdPart.getImageSize()) << '\n');
|
<< Twine::utohexstr(ColdPart.getImageSize()) << '\n');
|
||||||
OLT->mapSectionAddress(ObjectsHandle,
|
OLT->mapSectionAddress(Key, ColdSection->getSectionID(),
|
||||||
ColdSection->getSectionID(),
|
|
||||||
ColdPart.getAddress());
|
ColdPart.getAddress());
|
||||||
|
|
||||||
NextAvailableAddress += ColdPart.getImageSize();
|
NextAvailableAddress += ColdPart.getImageSize();
|
||||||
|
@ -2927,9 +2928,7 @@ void RewriteInstance::mapFileSections(
|
||||||
<< ") to 0x" << Twine::utohexstr(NextAvailableAddress)
|
<< ") to 0x" << Twine::utohexstr(NextAvailableAddress)
|
||||||
<< '\n');
|
<< '\n');
|
||||||
|
|
||||||
OLT->mapSectionAddress(ObjectsHandle,
|
OLT->mapSectionAddress(Key, Section->getSectionID(), NextAvailableAddress);
|
||||||
Section->getSectionID(),
|
|
||||||
NextAvailableAddress);
|
|
||||||
Section->setFileAddress(NextAvailableAddress);
|
Section->setFileAddress(NextAvailableAddress);
|
||||||
Section->setFileOffset(getFileOffsetForAddress(NextAvailableAddress));
|
Section->setFileOffset(getFileOffsetForAddress(NextAvailableAddress));
|
||||||
|
|
||||||
|
@ -2960,8 +2959,7 @@ void RewriteInstance::mapFileSections(
|
||||||
<< ") to 0x" << Twine::utohexstr(Section.getAddress())
|
<< ") to 0x" << Twine::utohexstr(Section.getAddress())
|
||||||
<< '\n');
|
<< '\n');
|
||||||
|
|
||||||
OLT->mapSectionAddress(ObjectsHandle,
|
OLT->mapSectionAddress(Key, OrgSection->getSectionID(),
|
||||||
OrgSection->getSectionID(),
|
|
||||||
Section.getAddress());
|
Section.getAddress());
|
||||||
|
|
||||||
OrgSection->setFileAddress(Section.getAddress());
|
OrgSection->setFileAddress(Section.getAddress());
|
||||||
|
@ -4240,7 +4238,7 @@ void RewriteInstance::rewriteFile() {
|
||||||
auto DwCtx = DWARFContext::create(*E);
|
auto DwCtx = DWARFContext::create(*E);
|
||||||
const auto &EHFrame = DwCtx->getEHFrame();
|
const auto &EHFrame = DwCtx->getEHFrame();
|
||||||
outs() << "BOLT-INFO: Dumping rewritten .eh_frame\n";
|
outs() << "BOLT-INFO: Dumping rewritten .eh_frame\n";
|
||||||
EHFrame->dump(outs(), NoneType());
|
EHFrame->dump(outs(), &*BC->MRI, NoneType());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue