Skip to content

Commit 5a11912

Browse files
authored
[BOLT] Refactor interface for creating instruction patches. NFCI (#129404)
Add BinaryContext::createInstructionPatch() interface for patching parts of the original binary with new instruction sequences. Refactor PatchEntries pass to use the new interface.
1 parent a0540e6 commit 5a11912

File tree

4 files changed

+44
-14
lines changed

4 files changed

+44
-14
lines changed

bolt/include/bolt/Core/BinaryContext.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -537,6 +537,17 @@ class BinaryContext {
537537
BinaryFunction *createInjectedBinaryFunction(const std::string &Name,
538538
bool IsSimple = true);
539539

540+
/// Patch the original binary contents at address \p Address with a sequence
541+
/// of instructions from the \p Instructions list. The callee is responsible
542+
/// for checking that the sequence doesn't cross any function or section
543+
/// boundaries.
544+
///
545+
/// Optional \p Name can be assigned to the patch. The name will be emitted to
546+
/// the symbol table at \p Address.
547+
BinaryFunction *createInstructionPatch(uint64_t Address,
548+
InstructionListType &Instructions,
549+
const Twine &Name = "");
550+
540551
std::vector<BinaryFunction *> &getInjectedBinaryFunctions() {
541552
return InjectedBinaryFunctions;
542553
}

bolt/include/bolt/Passes/PatchEntries.h

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,6 @@ class PatchEntries : public BinaryFunctionPass {
2626
struct Patch {
2727
const MCSymbol *Symbol;
2828
uint64_t Address;
29-
uint64_t FileOffset;
30-
BinarySection *Section;
3129
};
3230

3331
public:

bolt/lib/Core/BinaryContext.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2400,6 +2400,32 @@ BinaryContext::createInjectedBinaryFunction(const std::string &Name,
24002400
return BF;
24012401
}
24022402

2403+
BinaryFunction *BinaryContext::createInstructionPatch(
2404+
uint64_t Address, InstructionListType &Instructions, const Twine &Name) {
2405+
ErrorOr<BinarySection &> Section = getSectionForAddress(Address);
2406+
assert(Section && "cannot get section for patching");
2407+
assert(Section->hasSectionRef() && Section->isText() &&
2408+
"can only patch input file code sections");
2409+
2410+
const uint64_t FileOffset =
2411+
Section->getInputFileOffset() + Address - Section->getAddress();
2412+
2413+
std::string PatchName = Name.str();
2414+
if (PatchName.empty()) {
2415+
// Assign unique name to the patch.
2416+
static uint64_t N = 0;
2417+
PatchName = "__BP_" + std::to_string(N++);
2418+
}
2419+
2420+
BinaryFunction *PBF = createInjectedBinaryFunction(PatchName);
2421+
PBF->setOutputAddress(Address);
2422+
PBF->setFileOffset(FileOffset);
2423+
PBF->setOriginSection(&Section.get());
2424+
PBF->addBasicBlock()->addInstructions(Instructions);
2425+
2426+
return PBF;
2427+
}
2428+
24032429
std::pair<size_t, size_t>
24042430
BinaryContext::calculateEmittedSize(BinaryFunction &BF, bool FixBranches) {
24052431
// Adjust branch instruction to match the current layout.

bolt/lib/Passes/PatchEntries.cpp

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,8 @@ Error PatchEntries::runOnFunctions(BinaryContext &BC) {
8383
return false;
8484
}
8585

86-
PendingPatches.emplace_back(Patch{Symbol, Function.getAddress() + Offset,
87-
Function.getFileOffset() + Offset,
88-
Function.getOriginSection()});
86+
PendingPatches.emplace_back(
87+
Patch{Symbol, Function.getAddress() + Offset});
8988
NextValidByte = Offset + PatchSize;
9089
if (NextValidByte > Function.getMaxSize()) {
9190
if (opts::Verbosity >= 1)
@@ -118,16 +117,12 @@ Error PatchEntries::runOnFunctions(BinaryContext &BC) {
118117
}
119118

120119
for (Patch &Patch : PendingPatches) {
121-
BinaryFunction *PatchFunction = BC.createInjectedBinaryFunction(
120+
// Add instruction patch to the binary.
121+
InstructionListType Instructions;
122+
BC.MIB->createLongTailCall(Instructions, Patch.Symbol, BC.Ctx.get());
123+
BinaryFunction *PatchFunction = BC.createInstructionPatch(
124+
Patch.Address, Instructions,
122125
NameResolver::append(Patch.Symbol->getName(), ".org.0"));
123-
// Force the function to be emitted at the given address.
124-
PatchFunction->setOutputAddress(Patch.Address);
125-
PatchFunction->setFileOffset(Patch.FileOffset);
126-
PatchFunction->setOriginSection(Patch.Section);
127-
128-
InstructionListType Seq;
129-
BC.MIB->createLongTailCall(Seq, Patch.Symbol, BC.Ctx.get());
130-
PatchFunction->addBasicBlock()->addInstructions(Seq);
131126

132127
// Verify the size requirements.
133128
uint64_t HotSize, ColdSize;

0 commit comments

Comments
 (0)