forked from OSchip/llvm-project
Linux kernel marker to update special sections
Summary: This diff adds SDT marker like LK marker to update special lk sections (cherry picked from FBD22932157)
This commit is contained in:
parent
8f2a962866
commit
0033a7612d
|
@ -579,6 +579,10 @@ public:
|
||||||
/// Map SDT locations to SDT markers info
|
/// Map SDT locations to SDT markers info
|
||||||
std::unordered_map<uint64_t, SDTMarkerInfo> SDTMarkers;
|
std::unordered_map<uint64_t, SDTMarkerInfo> SDTMarkers;
|
||||||
|
|
||||||
|
/// Map linux kernel program locations/instructions to their pointers in
|
||||||
|
/// special linux kernel sections
|
||||||
|
std::unordered_map<uint64_t, std::vector<LKInstructionMarkerInfo>> LKMarkers;
|
||||||
|
|
||||||
BinaryContext(std::unique_ptr<MCContext> Ctx,
|
BinaryContext(std::unique_ptr<MCContext> Ctx,
|
||||||
std::unique_ptr<DWARFContext> DwCtx,
|
std::unique_ptr<DWARFContext> DwCtx,
|
||||||
std::unique_ptr<Triple> TheTriple,
|
std::unique_ptr<Triple> TheTriple,
|
||||||
|
|
|
@ -1979,9 +1979,10 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
|
||||||
const auto InstrInputAddr = I->first + Address;
|
const auto InstrInputAddr = I->first + Address;
|
||||||
bool IsSDTMarker =
|
bool IsSDTMarker =
|
||||||
MIB->isNoop(Instr) && BC.SDTMarkers.count(InstrInputAddr);
|
MIB->isNoop(Instr) && BC.SDTMarkers.count(InstrInputAddr);
|
||||||
if (IsSDTMarker) {
|
bool IsLKMarker = BC.LKMarkers.count(InstrInputAddr);
|
||||||
|
if (IsSDTMarker || IsLKMarker) {
|
||||||
HasSDTMarker = true;
|
HasSDTMarker = true;
|
||||||
DEBUG(dbgs() << "SDTMarker detected in the input at : "
|
DEBUG(dbgs() << "SDTMarker or LKMarker detected in the input at : "
|
||||||
<< utohexstr(InstrInputAddr) << "\n");
|
<< utohexstr(InstrInputAddr) << "\n");
|
||||||
if (!MIB->hasAnnotation(Instr, "Offset")) {
|
if (!MIB->hasAnnotation(Instr, "Offset")) {
|
||||||
MIB->addAnnotation(Instr, "Offset", static_cast<uint32_t>(Offset),
|
MIB->addAnnotation(Instr, "Offset", static_cast<uint32_t>(Offset),
|
||||||
|
@ -1992,7 +1993,7 @@ bool BinaryFunction::buildCFG(MCPlusBuilder::AllocatorIdTy AllocatorId) {
|
||||||
// Ignore nops except SDT markers. We use nops to derive alignment of the
|
// Ignore nops except SDT markers. We use nops to derive alignment of the
|
||||||
// next basic block. It will not always work, as some blocks are naturally
|
// next basic block. It will not always work, as some blocks are naturally
|
||||||
// aligned, but it's just part of heuristic for block alignment.
|
// aligned, but it's just part of heuristic for block alignment.
|
||||||
if (MIB->isNoop(Instr) && !PreserveNops && !IsSDTMarker) {
|
if (MIB->isNoop(Instr) && !PreserveNops && !IsSDTMarker && !IsLKMarker) {
|
||||||
IsLastInstrNop = true;
|
IsLastInstrNop = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
|
@ -515,6 +515,15 @@ struct SDTMarkerInfo {
|
||||||
unsigned PCOffset;
|
unsigned PCOffset;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// Linux Kernel special sections point to a specific instruction in many cases.
|
||||||
|
/// Unlike SDTMarkerInfo, these markers can come from different sections.
|
||||||
|
struct LKInstructionMarkerInfo {
|
||||||
|
uint64_t SectionOffset;
|
||||||
|
int32_t PCRelativeOffset;
|
||||||
|
bool IsPCRelative;
|
||||||
|
StringRef SectionName;
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace bolt
|
} // namespace bolt
|
||||||
} // namespace llvm
|
} // namespace llvm
|
||||||
|
|
||||||
|
|
|
@ -2820,6 +2820,7 @@ void RewriteInstance::emitAndLink() {
|
||||||
|
|
||||||
void RewriteInstance::updateMetadata() {
|
void RewriteInstance::updateMetadata() {
|
||||||
updateSDTMarkers();
|
updateSDTMarkers();
|
||||||
|
updateLKMarkers();
|
||||||
|
|
||||||
if (opts::UpdateDebugSections) {
|
if (opts::UpdateDebugSections) {
|
||||||
NamedRegionTimer T("updateDebugInfo", "update debug info", TimerGroupName,
|
NamedRegionTimer T("updateDebugInfo", "update debug info", TimerGroupName,
|
||||||
|
@ -2850,6 +2851,74 @@ void RewriteInstance::updateSDTMarkers() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RewriteInstance::updateLKMarkers() {
|
||||||
|
if (BC->LKMarkers.size() == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
NamedRegionTimer T("updateLKMarkers", "update LK markers", TimerGroupName,
|
||||||
|
TimerGroupDesc, opts::TimeRewrite);
|
||||||
|
|
||||||
|
std::unordered_map<std::string, uint64_t> PatchCounts;
|
||||||
|
for (auto &LKMarkerInfoKV : BC->LKMarkers) {
|
||||||
|
const auto OriginalAddress = LKMarkerInfoKV.first;
|
||||||
|
const auto *F =
|
||||||
|
BC->getBinaryFunctionContainingAddress(OriginalAddress, false, true);
|
||||||
|
if (!F) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
uint64_t NewAddress = F->translateInputToOutputAddress(OriginalAddress);
|
||||||
|
if (NewAddress == 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// rather than making address range of BBL 64_bit use base for LK BBLs
|
||||||
|
if (OriginalAddress >= 0xffffffff00000000 && NewAddress < 0xffffffff) {
|
||||||
|
NewAddress = NewAddress + 0xffffffff00000000;
|
||||||
|
}
|
||||||
|
if (OriginalAddress == NewAddress) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
uint64_t NumEntries = LKMarkerInfoKV.second.size();
|
||||||
|
if (NumEntries > 1) {
|
||||||
|
DEBUG(dbgs() << "Original linux kernel address 0x"
|
||||||
|
<< Twine::utohexstr(OriginalAddress) << " belongs to "
|
||||||
|
<< NumEntries << " marker entries.\n";);
|
||||||
|
}
|
||||||
|
for (auto &LKMarkerInfo : LKMarkerInfoKV.second) {
|
||||||
|
const auto SectionName = LKMarkerInfo.SectionName;
|
||||||
|
SimpleBinaryPatcher *LKPatcher;
|
||||||
|
if (SectionPatchers.find(SectionName) != SectionPatchers.end()) {
|
||||||
|
LKPatcher = static_cast<SimpleBinaryPatcher *>(
|
||||||
|
SectionPatchers[SectionName].get());
|
||||||
|
PatchCounts[SectionName]++;
|
||||||
|
} else {
|
||||||
|
DEBUG(dbgs() << "Starting the patch for section, " << SectionName
|
||||||
|
<< '\n');
|
||||||
|
PatchCounts[SectionName] = 1;
|
||||||
|
SectionPatchers[SectionName] = llvm::make_unique<SimpleBinaryPatcher>();
|
||||||
|
LKPatcher = static_cast<SimpleBinaryPatcher *>(
|
||||||
|
SectionPatchers[SectionName].get());
|
||||||
|
}
|
||||||
|
DEBUG(dbgs() << "LK patching from address 0x"
|
||||||
|
<< Twine::utohexstr(OriginalAddress) << ','
|
||||||
|
<< " to address 0x" << Twine::utohexstr(NewAddress) << '\n');
|
||||||
|
if (LKMarkerInfo.IsPCRelative) {
|
||||||
|
LKPatcher->addLE32Patch(LKMarkerInfo.SectionOffset,
|
||||||
|
NewAddress - OriginalAddress +
|
||||||
|
LKMarkerInfo.PCRelativeOffset);
|
||||||
|
} else {
|
||||||
|
LKPatcher->addLE64Patch(LKMarkerInfo.SectionOffset, NewAddress);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
outs() << "BOLT-INFO: patching linux kernel sections. Total patches per "
|
||||||
|
"section are as follows:\n";
|
||||||
|
for (const auto &KV : PatchCounts) {
|
||||||
|
outs() << " Section: " << KV.first << ", patch-counts: " << KV.second
|
||||||
|
<< '\n';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void RewriteInstance::mapFileSections(orc::VModuleKey Key) {
|
void RewriteInstance::mapFileSections(orc::VModuleKey Key) {
|
||||||
mapCodeSections(Key);
|
mapCodeSections(Key);
|
||||||
mapDataSections(Key);
|
mapDataSections(Key);
|
||||||
|
|
|
@ -153,6 +153,9 @@ private:
|
||||||
/// Update SDTMarkers' locations for the output binary.
|
/// Update SDTMarkers' locations for the output binary.
|
||||||
void updateSDTMarkers();
|
void updateSDTMarkers();
|
||||||
|
|
||||||
|
/// Update LKMarkers' locations for the output binary.
|
||||||
|
void updateLKMarkers();
|
||||||
|
|
||||||
/// Return the list of code sections in the output order.
|
/// Return the list of code sections in the output order.
|
||||||
std::vector<BinarySection *> getCodeSections();
|
std::vector<BinarySection *> getCodeSections();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue