Skip to content

Commit f6f8c73

Browse files
committed
[BOLT] Refactor interface for creating instruction patches. NFCI
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 9b7b7d6 commit f6f8c73

File tree

4 files changed

+46
-14
lines changed

4 files changed

+46
-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: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2400,6 +2400,34 @@ BinaryContext::createInjectedBinaryFunction(const std::string &Name,
24002400
return BF;
24012401
}
24022402

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