From 3b876cc3e776712bee39a8337871109f9e206096 Mon Sep 17 00:00:00 2001 From: Alexander Shaposhnikov Date: Thu, 28 Jan 2021 12:32:03 -0800 Subject: [PATCH] [BOLT] Add support for dumping counters on MacOS Summary: Add support for dumping counters on MacOS (cherry picked from FBD25750516) --- bolt/runtime/common.h | 22 +++++------ bolt/runtime/instr.cpp | 49 +++++++++++++++++++++--- bolt/src/MCPlusBuilder.h | 10 +++++ bolt/src/MachORewriteInstance.cpp | 3 +- bolt/src/Passes/Instrumentation.cpp | 5 +++ bolt/src/Target/X86/X86MCPlusBuilder.cpp | 46 ++++++++++++++++++++++ 6 files changed, 116 insertions(+), 19 deletions(-) diff --git a/bolt/runtime/common.h b/bolt/runtime/common.h index 3f813d51c695..f10fcfbf529d 100644 --- a/bolt/runtime/common.h +++ b/bolt/runtime/common.h @@ -180,6 +180,17 @@ uint32_t strLen(const char *Str) { return Size; } +void reportNumber(const char *Msg, uint64_t Num, uint32_t Base) { + char Buf[BufSize]; + char *Ptr = Buf; + Ptr = strCopy(Ptr, Msg, BufSize - 23); + Ptr = intToStr(Ptr, Num, Base); + Ptr = strCopy(Ptr, "\n"); + __write(2, Buf, Ptr - Buf); +} + +void report(const char *Msg) { __write(2, Msg, strLen(Msg)); } + #if !defined(__APPLE__) // We use a stack-allocated buffer for string manipulation in many pieces of // this code, including the code that prints each line of the fdata file. This @@ -332,17 +343,6 @@ void assert(bool Assertion, const char *Msg) { reportError(Buf, Ptr - Buf); } -void reportNumber(const char *Msg, uint64_t Num, uint32_t Base) { - char Buf[BufSize]; - char *Ptr = Buf; - Ptr = strCopy(Ptr, Msg, BufSize - 23); - Ptr = intToStr(Ptr, Num, Base); - Ptr = strCopy(Ptr, "\n"); - __write(2, Buf, Ptr - Buf); -} - -void report(const char *Msg) { __write(2, Msg, strLen(Msg)); } - /// 1B mutex accessed by lock xchg class Mutex { volatile bool InUse{false}; diff --git a/bolt/runtime/instr.cpp b/bolt/runtime/instr.cpp index 3533da7e4d84..cf5e27cfce03 100644 --- a/bolt/runtime/instr.cpp +++ b/bolt/runtime/instr.cpp @@ -57,7 +57,16 @@ {} #endif -#if !defined(__APPLE__) + +#if defined(__APPLE__) +extern "C" { + +extern uint64_t* _bolt_instr_locations_getter(); +extern uint32_t _bolt_num_counters_getter(); + +} + +#else // Main counters inserted by instrumentation, incremented during runtime when // points of interest (locations) in the program are reached. Those are direct @@ -1463,17 +1472,45 @@ extern "C" void __bolt_instr_fini() { DEBUG(report("Finished.\n")); } -#else +#endif + +#if defined(__APPLE__) // On OSX/iOS the final symbol name of an extern "C" function/variable contains // one extra leading underscore: _bolt_instr_setup -> __bolt_instr_setup. -extern "C" __attribute((section("__TEXT,__setup"))) void _bolt_instr_setup() { - const char* Message = "Hello!\n"; +extern "C" +__attribute__((section("__TEXT,__setup"))) +__attribute__((force_align_arg_pointer)) +void _bolt_instr_setup() { + const char *Message = "Hello!\n"; __write(2, Message, 7); + + uint32_t NumCounters = _bolt_num_counters_getter(); + reportNumber("__bolt_instr_setup, number of counters: ", NumCounters, 10); + + uint64_t *Locs = _bolt_instr_locations_getter(); + reportNumber("__bolt_instr_setup, address of counters: ", + reinterpret_cast(Locs), 10); + + for (size_t I = 0; I < NumCounters; ++I) + reportNumber("Counter value: ", Locs[I], 10); } -extern "C" __attribute((section("__TEXT,__fini"))) void _bolt_instr_fini() { - const char* Message = "Bye!\n"; +extern "C" +__attribute__((section("__TEXT,__fini"))) +__attribute__((force_align_arg_pointer)) +void _bolt_instr_fini() { + uint32_t NumCounters = _bolt_num_counters_getter(); + reportNumber("__bolt_instr_fini, number of counters: ", NumCounters, 10); + + uint64_t *Locs = _bolt_instr_locations_getter(); + reportNumber("__bolt_instr_fini, address of counters: ", + reinterpret_cast(Locs), 10); + + for (size_t I = 0; I < NumCounters; ++I) + reportNumber("Counter value: ", Locs[I], 10); + + const char *Message = "Bye!\n"; __write(2, Message, 5); } diff --git a/bolt/src/MCPlusBuilder.h b/bolt/src/MCPlusBuilder.h index 13bd15abb651..05785a9fc34c 100644 --- a/bolt/src/MCPlusBuilder.h +++ b/bolt/src/MCPlusBuilder.h @@ -1738,6 +1738,16 @@ public: return std::vector(); } + virtual std::vector createNumCountersGetter(MCContext *Ctx) const { + llvm_unreachable("not implemented"); + return {}; + } + + virtual std::vector createInstrLocationsGetter(MCContext *Ctx) const { + llvm_unreachable("not implemented"); + return {}; + } + /// This method takes an indirect call instruction and splits it up into an /// equivalent set of instructions that use direct calls for target /// symbols/addresses that are contained in the Targets vector. This is done diff --git a/bolt/src/MachORewriteInstance.cpp b/bolt/src/MachORewriteInstance.cpp index bc20443d95c9..159654f2ab2f 100644 --- a/bolt/src/MachORewriteInstance.cpp +++ b/bolt/src/MachORewriteInstance.cpp @@ -344,6 +344,7 @@ void MachORewriteInstance::mapCodeSections(orc::VModuleKey Key) { BOLT->getInputFileOffset()); Function->setImageAddress(FuncSection->getAllocAddress()); Function->setImageSize(FuncSection->getOutputSize()); + BC->registerNameAtAddress(Function->getOneName(), Addr, 0, 0); Addr += FuncSection->getOutputSize(); } } @@ -386,8 +387,6 @@ void MachORewriteInstance::emitAndLink() { auto Resolver = orc::createLegacyLookupResolver( [&](const std::string &Name) -> JITSymbol { llvm::errs() << "looking for " << Name << "\n"; - assert(!BC->EFMM->ObjectsLoaded && - "Linking multiple objects is unsupported"); DEBUG(dbgs() << "BOLT: looking for " << Name << "\n"); if (auto *I = BC->getBinaryDataByName(Name)) { const uint64_t Address = I->isMoved() && !I->isJumpTable() diff --git a/bolt/src/Passes/Instrumentation.cpp b/bolt/src/Passes/Instrumentation.cpp index 4dd09ff22fff..aaa2003f77c7 100644 --- a/bolt/src/Passes/Instrumentation.cpp +++ b/bolt/src/Passes/Instrumentation.cpp @@ -607,6 +607,11 @@ void Instrumentation::createAuxiliaryFunctions(BinaryContext &BC) { Summary->InitialIndTailCallHandlerFunction = createSimpleFunction("__bolt_instr_default_ind_tailcall_handler", BC.MIB->createInstrumentedNoopIndTailCallHandler()); + + createSimpleFunction("__bolt_num_counters_getter", + BC.MIB->createNumCountersGetter(BC.Ctx.get())); + createSimpleFunction("__bolt_instr_locations_getter", + BC.MIB->createInstrLocationsGetter(BC.Ctx.get())); } void Instrumentation::setupRuntimeLibrary(BinaryContext &BC) { diff --git a/bolt/src/Target/X86/X86MCPlusBuilder.cpp b/bolt/src/Target/X86/X86MCPlusBuilder.cpp index 56d9bbfff184..0c0183cf44ba 100644 --- a/bolt/src/Target/X86/X86MCPlusBuilder.cpp +++ b/bolt/src/Target/X86/X86MCPlusBuilder.cpp @@ -3325,6 +3325,22 @@ public: return Insts; } + std::vector createNumCountersGetter(MCContext *Ctx) const override { + std::vector Insts(2); + MCSymbol *NumLocs = Ctx->getOrCreateSymbol("__bolt_num_counters"); + createMove(Insts[0], NumLocs, X86::EAX, Ctx); + createReturn(Insts[1]); + return Insts; + } + + std::vector createInstrLocationsGetter(MCContext *Ctx) const override { + std::vector Insts(2); + MCSymbol *Locs = Ctx->getOrCreateSymbol("__bolt_instr_locations"); + createLea(Insts[0], Locs, X86::EAX, Ctx); + createReturn(Insts[1]); + return Insts; + } + BlocksVectorTy indirectCallPromotion( const MCInst &CallInst, const std::vector> &Targets, @@ -3627,6 +3643,36 @@ public: return Results; } +private: + + bool createMove(MCInst &Inst, const MCSymbol *Src, unsigned Reg, + MCContext *Ctx) const { + Inst.setOpcode(X86::MOV64rm); + Inst.addOperand(MCOperand::createReg(Reg)); + Inst.addOperand(MCOperand::createReg(X86::RIP)); // BaseReg + Inst.addOperand(MCOperand::createImm(1)); // ScaleAmt + Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg + Inst.addOperand(MCOperand::createExpr( + MCSymbolRefExpr::create(Src, MCSymbolRefExpr::VK_None, + *Ctx))); // Displacement + Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg + + return true; + } + + bool createLea(MCInst &Inst, const MCSymbol *Src, unsigned Reg, + MCContext *Ctx) const { + Inst.setOpcode(X86::LEA64r); + Inst.addOperand(MCOperand::createReg(Reg)); + Inst.addOperand(MCOperand::createReg(X86::RIP)); // BaseReg + Inst.addOperand(MCOperand::createImm(1)); // ScaleAmt + Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // IndexReg + Inst.addOperand(MCOperand::createExpr( + MCSymbolRefExpr::create(Src, MCSymbolRefExpr::VK_None, + *Ctx))); // Displacement + Inst.addOperand(MCOperand::createReg(X86::NoRegister)); // AddrSegmentReg + return true; + } }; }