Inject instrumentation's global dtor on MachO

Summary:
This diff is a preparation for dumping the profile generated by BOLT's instrumenation on MachO.

1/  Function "bolt_instr_fini" is placed into the predefined section "__fini"

2/ In the instrumentation pass we create a symbol "bolt_instr_fini" and
replace the last global destructor with it.

This is a temporary solution, in the future we need to register bolt_instr_fini in addition to the existing destructors without dropping the last one.

(cherry picked from FBD25071864)
This commit is contained in:
Alexander Shaposhnikov 2020-11-19 18:18:28 -08:00 committed by Maksim Panchenko
parent 1b258b8908
commit e067f2adf4
4 changed files with 52 additions and 17 deletions

View file

@ -1472,4 +1472,9 @@ extern "C" __attribute((section("__TEXT,__setup"))) void _bolt_instr_setup() {
__write(2, Message, 7);
}
extern "C" __attribute((section("__TEXT,__fini"))) void _bolt_instr_fini() {
const char* Message = "Bye!\n";
__write(2, Message, 5);
}
#endif

View file

@ -57,7 +57,8 @@ uint8_t *ExecutableFileMemoryManager::allocateSection(intptr_t Size,
.toStringRef(Buf);
} else if (BC.isMachO()) {
assert((SectionName == "__text" || SectionName == "__data" ||
SectionName == "__setup" || SectionName == "__cstring") &&
SectionName == "__fini" || SectionName == "__setup" ||
SectionName == "__cstring") &&
"Unexpected section in the instrumentation library");
SectionName = ("I" + Twine(SectionName)).toStringRef(Buf);
}

View file

@ -429,6 +429,7 @@ void MachORewriteInstance::emitAndLink() {
// TODO: Refactor addRuntimeLibSections to work properly on Mach-O
// and use it here.
mapInstrumentationSection(Key, "I__setup");
mapInstrumentationSection(Key, "I__fini");
mapInstrumentationSection(Key, "I__data");
mapInstrumentationSection(Key, "I__text");
mapInstrumentationSection(Key, "I__cstring");
@ -495,6 +496,7 @@ void MachORewriteInstance::rewriteFile() {
// TODO: Refactor addRuntimeLibSections to work properly on Mach-O and
// use it here.
writeInstrumentationSection("I__setup", OS);
writeInstrumentationSection("I__fini", OS);
writeInstrumentationSection("I__data", OS);
writeInstrumentationSection("I__text", OS);
writeInstrumentationSection("I__cstring", OS);

View file

@ -283,6 +283,9 @@ void Instrumentation::instrumentFunction(BinaryContext &BC,
if (Function.hasUnknownControlFlow())
return;
if (BC.isMachO() && Function.hasName("___GLOBAL_init_65535/1"))
return;
SplitWorklistTy SplitWorklist;
SplitInstrsTy SplitInstrs;
@ -533,23 +536,48 @@ void Instrumentation::runOnFunctions(BinaryContext &BC) {
createAuxiliaryFunctions(BC);
if (BC.isMachO() && BC.StartFunctionAddress) {
BinaryFunction *Main =
BC.getBinaryFunctionAtAddress(*BC.StartFunctionAddress);
assert(Main && "Entry point function not found");
BinaryBasicBlock &BB = Main->front();
if (BC.isMachO()) {
if (BC.StartFunctionAddress) {
BinaryFunction *Main =
BC.getBinaryFunctionAtAddress(*BC.StartFunctionAddress);
assert(Main && "Entry point function not found");
BinaryBasicBlock &BB = Main->front();
ErrorOr<BinarySection &> SetupSection =
BC.getUniqueSectionByName("I__setup");
if (!SetupSection) {
llvm::errs() << "Cannot find I__setup section\n";
exit(1);
ErrorOr<BinarySection &> SetupSection =
BC.getUniqueSectionByName("I__setup");
if (!SetupSection) {
llvm::errs() << "Cannot find I__setup section\n";
exit(1);
}
MCSymbol *Target = BC.registerNameAtAddress(
"__bolt_instr_setup", SetupSection->getAddress(), 0, 0);
MCInst NewInst;
BC.MIB->createCall(NewInst, Target, BC.Ctx.get());
BB.insertInstruction(BB.begin(), std::move(NewInst));
} else {
llvm::errs() << "BOLT-WARNING: Entry point not found\n";
}
if (BinaryData *BD = BC.getBinaryDataByName("___GLOBAL_init_65535/1")) {
BinaryFunction *Ctor = BC.getBinaryFunctionAtAddress(BD->getAddress());
assert(Ctor && "___GLOBAL_init_65535 function not found");
BinaryBasicBlock &BB = Ctor->front();
ErrorOr<BinarySection &> FiniSection =
BC.getUniqueSectionByName("I__fini");
if (!FiniSection) {
llvm::errs() << "Cannot find I__fini section\n";
exit(1);
}
MCSymbol *Target = BC.registerNameAtAddress(
"__bolt_instr_fini", FiniSection->getAddress(), 0, 0);
auto IsLEA = [&BC](const MCInst &Inst) { return BC.MIB->isLEA64r(Inst); };
const auto LEA = std::find_if(std::next(std::find_if(
BB.rbegin(), BB.rend(), IsLEA)), BB.rend(), IsLEA);
LEA->getOperand(4).setExpr(
MCSymbolRefExpr::create(Target, MCSymbolRefExpr::VK_None, *BC.Ctx));
} else {
llvm::errs() << "BOLT-WARNING: ___GLOBAL_init_65535 not found\n";
}
MCSymbol *Target = BC.registerNameAtAddress(
"__bolt_instr_setup", SetupSection->getAddress(), 0, 0);
MCInst NewInst;
BC.MIB->createCall(NewInst, Target, BC.Ctx.get());
BB.insertInstruction(BB.begin(), std::move(NewInst));
}
setupRuntimeLibrary(BC);
@ -579,7 +607,6 @@ void Instrumentation::createAuxiliaryFunctions(BinaryContext &BC) {
Summary->InitialIndTailCallHandlerFunction =
createSimpleFunction("__bolt_instr_default_ind_tailcall_handler",
BC.MIB->createInstrumentedNoopIndTailCallHandler());
}
void Instrumentation::setupRuntimeLibrary(BinaryContext &BC) {