17ddf7d87SPrem Chintalapudi //===----- PerfSupportPlugin.cpp --- Utils for perf support -----*- C++ -*-===// 27ddf7d87SPrem Chintalapudi // 37ddf7d87SPrem Chintalapudi // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 47ddf7d87SPrem Chintalapudi // See https://llvm.org/LICENSE.txt for license information. 57ddf7d87SPrem Chintalapudi // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 67ddf7d87SPrem Chintalapudi // 77ddf7d87SPrem Chintalapudi //===----------------------------------------------------------------------===// 87ddf7d87SPrem Chintalapudi // 97ddf7d87SPrem Chintalapudi // Handles support for registering code with perf 107ddf7d87SPrem Chintalapudi // 117ddf7d87SPrem Chintalapudi //===----------------------------------------------------------------------===// 127ddf7d87SPrem Chintalapudi 137ddf7d87SPrem Chintalapudi #include "llvm/ExecutionEngine/Orc/Debugging/PerfSupportPlugin.h" 147ddf7d87SPrem Chintalapudi 157ddf7d87SPrem Chintalapudi #include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h" 167ddf7d87SPrem Chintalapudi #include "llvm/ExecutionEngine/Orc/LookupAndRecordAddrs.h" 177ddf7d87SPrem Chintalapudi #include "llvm/ExecutionEngine/Orc/Shared/WrapperFunctionUtils.h" 187ddf7d87SPrem Chintalapudi 197ddf7d87SPrem Chintalapudi #define DEBUG_TYPE "orc" 207ddf7d87SPrem Chintalapudi 217ddf7d87SPrem Chintalapudi using namespace llvm; 227ddf7d87SPrem Chintalapudi using namespace llvm::orc; 237ddf7d87SPrem Chintalapudi using namespace llvm::jitlink; 247ddf7d87SPrem Chintalapudi 257ddf7d87SPrem Chintalapudi namespace { 267ddf7d87SPrem Chintalapudi 277ddf7d87SPrem Chintalapudi // Creates an EH frame header prepared for a 32-bit relative relocation 287ddf7d87SPrem Chintalapudi // to the start of the .eh_frame section. Absolute injects a 64-bit absolute 297ddf7d87SPrem Chintalapudi // address space offset 4 bytes from the start instead of 4 bytes 307ddf7d87SPrem Chintalapudi Expected<std::string> createX64EHFrameHeader(Section &EHFrame, 31a9d50568SKazu Hirata llvm::endianness endianness, 327ddf7d87SPrem Chintalapudi bool absolute) { 337ddf7d87SPrem Chintalapudi uint8_t Version = 1; 347ddf7d87SPrem Chintalapudi uint8_t EhFramePtrEnc = 0; 357ddf7d87SPrem Chintalapudi if (absolute) { 367ddf7d87SPrem Chintalapudi EhFramePtrEnc |= dwarf::DW_EH_PE_sdata8 | dwarf::DW_EH_PE_absptr; 377ddf7d87SPrem Chintalapudi } else { 387ddf7d87SPrem Chintalapudi EhFramePtrEnc |= dwarf::DW_EH_PE_sdata4 | dwarf::DW_EH_PE_datarel; 397ddf7d87SPrem Chintalapudi } 407ddf7d87SPrem Chintalapudi uint8_t FDECountEnc = dwarf::DW_EH_PE_omit; 417ddf7d87SPrem Chintalapudi uint8_t TableEnc = dwarf::DW_EH_PE_omit; 427ddf7d87SPrem Chintalapudi // X86_64_64 relocation to the start of the .eh_frame section 437ddf7d87SPrem Chintalapudi uint32_t EHFrameRelocation = 0; 447ddf7d87SPrem Chintalapudi // uint32_t FDECount = 0; 457ddf7d87SPrem Chintalapudi // Skip the FDE binary search table 467ddf7d87SPrem Chintalapudi // We'd have to reprocess the CIEs to get this information, 477ddf7d87SPrem Chintalapudi // which seems like more trouble than it's worth 487ddf7d87SPrem Chintalapudi // TODO consider implementing this. 497ddf7d87SPrem Chintalapudi // binary search table goes here 507ddf7d87SPrem Chintalapudi 517ddf7d87SPrem Chintalapudi size_t HeaderSize = 527ddf7d87SPrem Chintalapudi (sizeof(Version) + sizeof(EhFramePtrEnc) + sizeof(FDECountEnc) + 537ddf7d87SPrem Chintalapudi sizeof(TableEnc) + 547ddf7d87SPrem Chintalapudi (absolute ? sizeof(uint64_t) : sizeof(EHFrameRelocation))); 557ddf7d87SPrem Chintalapudi std::string HeaderContent(HeaderSize, '\0'); 567ddf7d87SPrem Chintalapudi BinaryStreamWriter Writer( 577ddf7d87SPrem Chintalapudi MutableArrayRef<uint8_t>( 587ddf7d87SPrem Chintalapudi reinterpret_cast<uint8_t *>(HeaderContent.data()), HeaderSize), 597ddf7d87SPrem Chintalapudi endianness); 607ddf7d87SPrem Chintalapudi if (auto Err = Writer.writeInteger(Version)) 617ddf7d87SPrem Chintalapudi return std::move(Err); 627ddf7d87SPrem Chintalapudi if (auto Err = Writer.writeInteger(EhFramePtrEnc)) 637ddf7d87SPrem Chintalapudi return std::move(Err); 647ddf7d87SPrem Chintalapudi if (auto Err = Writer.writeInteger(FDECountEnc)) 657ddf7d87SPrem Chintalapudi return std::move(Err); 667ddf7d87SPrem Chintalapudi if (auto Err = Writer.writeInteger(TableEnc)) 677ddf7d87SPrem Chintalapudi return std::move(Err); 687ddf7d87SPrem Chintalapudi if (absolute) { 697ddf7d87SPrem Chintalapudi uint64_t EHFrameAddr = SectionRange(EHFrame).getStart().getValue(); 707ddf7d87SPrem Chintalapudi if (auto Err = Writer.writeInteger(EHFrameAddr)) 717ddf7d87SPrem Chintalapudi return std::move(Err); 727ddf7d87SPrem Chintalapudi } else { 737ddf7d87SPrem Chintalapudi if (auto Err = Writer.writeInteger(EHFrameRelocation)) 747ddf7d87SPrem Chintalapudi return std::move(Err); 757ddf7d87SPrem Chintalapudi } 767ddf7d87SPrem Chintalapudi return HeaderContent; 777ddf7d87SPrem Chintalapudi } 787ddf7d87SPrem Chintalapudi 797ddf7d87SPrem Chintalapudi constexpr StringRef RegisterPerfStartSymbolName = 807ddf7d87SPrem Chintalapudi "llvm_orc_registerJITLoaderPerfStart"; 817ddf7d87SPrem Chintalapudi constexpr StringRef RegisterPerfEndSymbolName = 827ddf7d87SPrem Chintalapudi "llvm_orc_registerJITLoaderPerfEnd"; 837ddf7d87SPrem Chintalapudi constexpr StringRef RegisterPerfImplSymbolName = 847ddf7d87SPrem Chintalapudi "llvm_orc_registerJITLoaderPerfImpl"; 857ddf7d87SPrem Chintalapudi 867ddf7d87SPrem Chintalapudi static PerfJITCodeLoadRecord 877ddf7d87SPrem Chintalapudi getCodeLoadRecord(const Symbol &Sym, std::atomic<uint64_t> &CodeIndex) { 887ddf7d87SPrem Chintalapudi PerfJITCodeLoadRecord Record; 89*2ccf7ed2SJared Wyles auto Name = *Sym.getName(); 907ddf7d87SPrem Chintalapudi auto Addr = Sym.getAddress(); 917ddf7d87SPrem Chintalapudi auto Size = Sym.getSize(); 927ddf7d87SPrem Chintalapudi Record.Prefix.Id = PerfJITRecordType::JIT_CODE_LOAD; 937ddf7d87SPrem Chintalapudi // Runtime sets PID 947ddf7d87SPrem Chintalapudi Record.Pid = 0; 957ddf7d87SPrem Chintalapudi // Runtime sets TID 967ddf7d87SPrem Chintalapudi Record.Tid = 0; 977ddf7d87SPrem Chintalapudi Record.Vma = Addr.getValue(); 987ddf7d87SPrem Chintalapudi Record.CodeAddr = Addr.getValue(); 997ddf7d87SPrem Chintalapudi Record.CodeSize = Size; 1007ddf7d87SPrem Chintalapudi Record.CodeIndex = CodeIndex++; 1017ddf7d87SPrem Chintalapudi Record.Name = Name.str(); 1027ddf7d87SPrem Chintalapudi // Initialize last, once all the other fields are filled 1037ddf7d87SPrem Chintalapudi Record.Prefix.TotalSize = 1047ddf7d87SPrem Chintalapudi (2 * sizeof(uint32_t) // id, total_size 1057ddf7d87SPrem Chintalapudi + sizeof(uint64_t) // timestamp 1067ddf7d87SPrem Chintalapudi + 2 * sizeof(uint32_t) // pid, tid 1077ddf7d87SPrem Chintalapudi + 4 * sizeof(uint64_t) // vma, code_addr, code_size, code_index 1087ddf7d87SPrem Chintalapudi + Name.size() + 1 // symbol name 1097ddf7d87SPrem Chintalapudi + Record.CodeSize // code 1107ddf7d87SPrem Chintalapudi ); 1117ddf7d87SPrem Chintalapudi return Record; 1127ddf7d87SPrem Chintalapudi } 1137ddf7d87SPrem Chintalapudi 1147ddf7d87SPrem Chintalapudi static std::optional<PerfJITDebugInfoRecord> 1157ddf7d87SPrem Chintalapudi getDebugInfoRecord(const Symbol &Sym, DWARFContext &DC) { 1167ddf7d87SPrem Chintalapudi auto &Section = Sym.getBlock().getSection(); 1177ddf7d87SPrem Chintalapudi auto Addr = Sym.getAddress(); 1187ddf7d87SPrem Chintalapudi auto Size = Sym.getSize(); 1197ddf7d87SPrem Chintalapudi auto SAddr = object::SectionedAddress{Addr.getValue(), Section.getOrdinal()}; 1207ddf7d87SPrem Chintalapudi LLVM_DEBUG(dbgs() << "Getting debug info for symbol " << Sym.getName() 1217ddf7d87SPrem Chintalapudi << " at address " << Addr.getValue() << " with size " 1227ddf7d87SPrem Chintalapudi << Size << "\n" 1237ddf7d87SPrem Chintalapudi << "Section ordinal: " << Section.getOrdinal() << "\n"); 1247ddf7d87SPrem Chintalapudi auto LInfo = DC.getLineInfoForAddressRange( 1257ddf7d87SPrem Chintalapudi SAddr, Size, DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); 1267ddf7d87SPrem Chintalapudi if (LInfo.empty()) { 1277ddf7d87SPrem Chintalapudi // No line info available 1287ddf7d87SPrem Chintalapudi LLVM_DEBUG(dbgs() << "No line info available\n"); 1297ddf7d87SPrem Chintalapudi return std::nullopt; 1307ddf7d87SPrem Chintalapudi } 1317ddf7d87SPrem Chintalapudi PerfJITDebugInfoRecord Record; 1327ddf7d87SPrem Chintalapudi Record.Prefix.Id = PerfJITRecordType::JIT_CODE_DEBUG_INFO; 1337ddf7d87SPrem Chintalapudi Record.CodeAddr = Addr.getValue(); 1347ddf7d87SPrem Chintalapudi for (const auto &Entry : LInfo) { 1357ddf7d87SPrem Chintalapudi auto Addr = Entry.first; 1367ddf7d87SPrem Chintalapudi // The function re-created by perf is preceded by a elf 1377ddf7d87SPrem Chintalapudi // header. Need to adjust for that, otherwise the results are 1387ddf7d87SPrem Chintalapudi // wrong. 1397ddf7d87SPrem Chintalapudi Addr += 0x40; 1407ddf7d87SPrem Chintalapudi Record.Entries.push_back({Addr, Entry.second.Line, 1417ddf7d87SPrem Chintalapudi Entry.second.Discriminator, 1427ddf7d87SPrem Chintalapudi Entry.second.FileName}); 1437ddf7d87SPrem Chintalapudi } 1447ddf7d87SPrem Chintalapudi size_t EntriesBytes = (2 // record header 1457ddf7d87SPrem Chintalapudi + 2 // record fields 1467ddf7d87SPrem Chintalapudi ) * 1477ddf7d87SPrem Chintalapudi sizeof(uint64_t); 1487ddf7d87SPrem Chintalapudi for (const auto &Entry : Record.Entries) { 1497ddf7d87SPrem Chintalapudi EntriesBytes += 1507ddf7d87SPrem Chintalapudi sizeof(uint64_t) + 2 * sizeof(uint32_t); // Addr, Line/Discrim 1517ddf7d87SPrem Chintalapudi EntriesBytes += Entry.Name.size() + 1; // Name 1527ddf7d87SPrem Chintalapudi } 1537ddf7d87SPrem Chintalapudi Record.Prefix.TotalSize = EntriesBytes; 1547ddf7d87SPrem Chintalapudi LLVM_DEBUG(dbgs() << "Created debug info record\n" 1557ddf7d87SPrem Chintalapudi << "Total size: " << Record.Prefix.TotalSize << "\n" 1567ddf7d87SPrem Chintalapudi << "Nr entries: " << Record.Entries.size() << "\n"); 1577ddf7d87SPrem Chintalapudi return Record; 1587ddf7d87SPrem Chintalapudi } 1597ddf7d87SPrem Chintalapudi 1607ddf7d87SPrem Chintalapudi static Expected<PerfJITCodeUnwindingInfoRecord> 1617ddf7d87SPrem Chintalapudi getUnwindingRecord(LinkGraph &G) { 1627ddf7d87SPrem Chintalapudi PerfJITCodeUnwindingInfoRecord Record; 1637ddf7d87SPrem Chintalapudi Record.Prefix.Id = PerfJITRecordType::JIT_CODE_UNWINDING_INFO; 1647ddf7d87SPrem Chintalapudi Record.Prefix.TotalSize = 0; 1657ddf7d87SPrem Chintalapudi auto Eh_frame = G.findSectionByName(".eh_frame"); 1667ddf7d87SPrem Chintalapudi if (!Eh_frame) { 1677ddf7d87SPrem Chintalapudi LLVM_DEBUG(dbgs() << "No .eh_frame section found\n"); 1687ddf7d87SPrem Chintalapudi return Record; 1697ddf7d87SPrem Chintalapudi } 1707ddf7d87SPrem Chintalapudi if (!G.getTargetTriple().isOSBinFormatELF()) { 1717ddf7d87SPrem Chintalapudi LLVM_DEBUG(dbgs() << "Not an ELF file, will not emit unwinding info\n"); 1727ddf7d87SPrem Chintalapudi return Record; 1737ddf7d87SPrem Chintalapudi } 1747ddf7d87SPrem Chintalapudi auto SR = SectionRange(*Eh_frame); 1757ddf7d87SPrem Chintalapudi auto EHFrameSize = SR.getSize(); 1767ddf7d87SPrem Chintalapudi auto Eh_frame_hdr = G.findSectionByName(".eh_frame_hdr"); 1777ddf7d87SPrem Chintalapudi if (!Eh_frame_hdr) { 1787ddf7d87SPrem Chintalapudi if (G.getTargetTriple().getArch() == Triple::x86_64) { 1797ddf7d87SPrem Chintalapudi auto Hdr = createX64EHFrameHeader(*Eh_frame, G.getEndianness(), true); 1807ddf7d87SPrem Chintalapudi if (!Hdr) 1817ddf7d87SPrem Chintalapudi return Hdr.takeError(); 1827ddf7d87SPrem Chintalapudi Record.EHFrameHdr = std::move(*Hdr); 1837ddf7d87SPrem Chintalapudi } else { 1847ddf7d87SPrem Chintalapudi LLVM_DEBUG(dbgs() << "No .eh_frame_hdr section found\n"); 1857ddf7d87SPrem Chintalapudi return Record; 1867ddf7d87SPrem Chintalapudi } 1877ddf7d87SPrem Chintalapudi Record.EHFrameHdrAddr = 0; 1887ddf7d87SPrem Chintalapudi Record.EHFrameHdrSize = Record.EHFrameHdr.size(); 1897ddf7d87SPrem Chintalapudi Record.UnwindDataSize = EHFrameSize + Record.EHFrameHdrSize; 1907ddf7d87SPrem Chintalapudi Record.MappedSize = 0; // Because the EHFrame header was not mapped 1917ddf7d87SPrem Chintalapudi } else { 1927ddf7d87SPrem Chintalapudi auto SR = SectionRange(*Eh_frame_hdr); 1937ddf7d87SPrem Chintalapudi Record.EHFrameHdrAddr = SR.getStart().getValue(); 1947ddf7d87SPrem Chintalapudi Record.EHFrameHdrSize = SR.getSize(); 1957ddf7d87SPrem Chintalapudi Record.UnwindDataSize = EHFrameSize + Record.EHFrameHdrSize; 1967ddf7d87SPrem Chintalapudi Record.MappedSize = Record.UnwindDataSize; 1977ddf7d87SPrem Chintalapudi } 1987ddf7d87SPrem Chintalapudi Record.EHFrameAddr = SR.getStart().getValue(); 1997ddf7d87SPrem Chintalapudi Record.Prefix.TotalSize = 2007ddf7d87SPrem Chintalapudi (2 * sizeof(uint32_t) // id, total_size 2017ddf7d87SPrem Chintalapudi + sizeof(uint64_t) // timestamp 2027ddf7d87SPrem Chintalapudi + 2037ddf7d87SPrem Chintalapudi 3 * sizeof(uint64_t) // unwind_data_size, eh_frame_hdr_size, mapped_size 2047ddf7d87SPrem Chintalapudi + Record.UnwindDataSize // eh_frame_hdr, eh_frame 2057ddf7d87SPrem Chintalapudi ); 2067ddf7d87SPrem Chintalapudi LLVM_DEBUG(dbgs() << "Created unwind record\n" 2077ddf7d87SPrem Chintalapudi << "Total size: " << Record.Prefix.TotalSize << "\n" 2087ddf7d87SPrem Chintalapudi << "Unwind size: " << Record.UnwindDataSize << "\n" 2097ddf7d87SPrem Chintalapudi << "EHFrame size: " << EHFrameSize << "\n" 2107ddf7d87SPrem Chintalapudi << "EHFrameHdr size: " << Record.EHFrameHdrSize << "\n"); 2117ddf7d87SPrem Chintalapudi return Record; 2127ddf7d87SPrem Chintalapudi } 2137ddf7d87SPrem Chintalapudi 2147ddf7d87SPrem Chintalapudi static PerfJITRecordBatch getRecords(ExecutionSession &ES, LinkGraph &G, 2157ddf7d87SPrem Chintalapudi std::atomic<uint64_t> &CodeIndex, 2167ddf7d87SPrem Chintalapudi bool EmitDebugInfo, bool EmitUnwindInfo) { 2177ddf7d87SPrem Chintalapudi std::unique_ptr<DWARFContext> DC; 2187ddf7d87SPrem Chintalapudi StringMap<std::unique_ptr<MemoryBuffer>> DCBacking; 2197ddf7d87SPrem Chintalapudi if (EmitDebugInfo) { 2207ddf7d87SPrem Chintalapudi auto EDC = createDWARFContext(G); 2217ddf7d87SPrem Chintalapudi if (!EDC) { 2227ddf7d87SPrem Chintalapudi ES.reportError(EDC.takeError()); 2237ddf7d87SPrem Chintalapudi EmitDebugInfo = false; 2247ddf7d87SPrem Chintalapudi } else { 2257ddf7d87SPrem Chintalapudi DC = std::move(EDC->first); 2267ddf7d87SPrem Chintalapudi DCBacking = std::move(EDC->second); 2277ddf7d87SPrem Chintalapudi } 2287ddf7d87SPrem Chintalapudi } 2297ddf7d87SPrem Chintalapudi PerfJITRecordBatch Batch; 2307ddf7d87SPrem Chintalapudi for (auto Sym : G.defined_symbols()) { 2317ddf7d87SPrem Chintalapudi if (!Sym->hasName() || !Sym->isCallable()) 2327ddf7d87SPrem Chintalapudi continue; 2337ddf7d87SPrem Chintalapudi if (EmitDebugInfo) { 2347ddf7d87SPrem Chintalapudi auto DebugInfo = getDebugInfoRecord(*Sym, *DC); 2357ddf7d87SPrem Chintalapudi if (DebugInfo) 2367ddf7d87SPrem Chintalapudi Batch.DebugInfoRecords.push_back(std::move(*DebugInfo)); 2377ddf7d87SPrem Chintalapudi } 2387ddf7d87SPrem Chintalapudi Batch.CodeLoadRecords.push_back(getCodeLoadRecord(*Sym, CodeIndex)); 2397ddf7d87SPrem Chintalapudi } 2407ddf7d87SPrem Chintalapudi if (EmitUnwindInfo) { 2417ddf7d87SPrem Chintalapudi auto UWR = getUnwindingRecord(G); 2427ddf7d87SPrem Chintalapudi if (!UWR) { 2437ddf7d87SPrem Chintalapudi ES.reportError(UWR.takeError()); 2447ddf7d87SPrem Chintalapudi } else { 2457ddf7d87SPrem Chintalapudi Batch.UnwindingRecord = std::move(*UWR); 2467ddf7d87SPrem Chintalapudi } 2477ddf7d87SPrem Chintalapudi } else { 2487ddf7d87SPrem Chintalapudi Batch.UnwindingRecord.Prefix.TotalSize = 0; 2497ddf7d87SPrem Chintalapudi } 2507ddf7d87SPrem Chintalapudi return Batch; 2517ddf7d87SPrem Chintalapudi } 2527ddf7d87SPrem Chintalapudi } // namespace 2537ddf7d87SPrem Chintalapudi 2547ddf7d87SPrem Chintalapudi PerfSupportPlugin::PerfSupportPlugin(ExecutorProcessControl &EPC, 2557ddf7d87SPrem Chintalapudi ExecutorAddr RegisterPerfStartAddr, 2567ddf7d87SPrem Chintalapudi ExecutorAddr RegisterPerfEndAddr, 2577ddf7d87SPrem Chintalapudi ExecutorAddr RegisterPerfImplAddr, 2587ddf7d87SPrem Chintalapudi bool EmitDebugInfo, bool EmitUnwindInfo) 2597ddf7d87SPrem Chintalapudi : EPC(EPC), RegisterPerfStartAddr(RegisterPerfStartAddr), 2607ddf7d87SPrem Chintalapudi RegisterPerfEndAddr(RegisterPerfEndAddr), 2617ddf7d87SPrem Chintalapudi RegisterPerfImplAddr(RegisterPerfImplAddr), CodeIndex(0), 2627ddf7d87SPrem Chintalapudi EmitDebugInfo(EmitDebugInfo), EmitUnwindInfo(EmitUnwindInfo) { 2637ddf7d87SPrem Chintalapudi cantFail(EPC.callSPSWrapper<void()>(RegisterPerfStartAddr)); 2647ddf7d87SPrem Chintalapudi } 2657ddf7d87SPrem Chintalapudi PerfSupportPlugin::~PerfSupportPlugin() { 2667ddf7d87SPrem Chintalapudi cantFail(EPC.callSPSWrapper<void()>(RegisterPerfEndAddr)); 2677ddf7d87SPrem Chintalapudi } 2687ddf7d87SPrem Chintalapudi 2697ddf7d87SPrem Chintalapudi void PerfSupportPlugin::modifyPassConfig(MaterializationResponsibility &MR, 2707ddf7d87SPrem Chintalapudi LinkGraph &G, 2717ddf7d87SPrem Chintalapudi PassConfiguration &Config) { 2727ddf7d87SPrem Chintalapudi Config.PostFixupPasses.push_back([this](LinkGraph &G) { 2737ddf7d87SPrem Chintalapudi auto Batch = getRecords(EPC.getExecutionSession(), G, CodeIndex, 2747ddf7d87SPrem Chintalapudi EmitDebugInfo, EmitUnwindInfo); 2757ddf7d87SPrem Chintalapudi G.allocActions().push_back( 2767ddf7d87SPrem Chintalapudi {cantFail(shared::WrapperFunctionCall::Create< 2777ddf7d87SPrem Chintalapudi shared::SPSArgList<shared::SPSPerfJITRecordBatch>>( 2787ddf7d87SPrem Chintalapudi RegisterPerfImplAddr, Batch)), 2797ddf7d87SPrem Chintalapudi {}}); 2807ddf7d87SPrem Chintalapudi return Error::success(); 2817ddf7d87SPrem Chintalapudi }); 2827ddf7d87SPrem Chintalapudi } 2837ddf7d87SPrem Chintalapudi 2847ddf7d87SPrem Chintalapudi Expected<std::unique_ptr<PerfSupportPlugin>> 2857ddf7d87SPrem Chintalapudi PerfSupportPlugin::Create(ExecutorProcessControl &EPC, JITDylib &JD, 2867ddf7d87SPrem Chintalapudi bool EmitDebugInfo, bool EmitUnwindInfo) { 2877ddf7d87SPrem Chintalapudi if (!EPC.getTargetTriple().isOSBinFormatELF()) { 2887ddf7d87SPrem Chintalapudi return make_error<StringError>( 2897ddf7d87SPrem Chintalapudi "Perf support only available for ELF LinkGraphs!", 2907ddf7d87SPrem Chintalapudi inconvertibleErrorCode()); 2917ddf7d87SPrem Chintalapudi } 2927ddf7d87SPrem Chintalapudi auto &ES = EPC.getExecutionSession(); 2937ddf7d87SPrem Chintalapudi ExecutorAddr StartAddr, EndAddr, ImplAddr; 2947ddf7d87SPrem Chintalapudi if (auto Err = lookupAndRecordAddrs( 2957ddf7d87SPrem Chintalapudi ES, LookupKind::Static, makeJITDylibSearchOrder({&JD}), 2967ddf7d87SPrem Chintalapudi {{ES.intern(RegisterPerfStartSymbolName), &StartAddr}, 2977ddf7d87SPrem Chintalapudi {ES.intern(RegisterPerfEndSymbolName), &EndAddr}, 2987ddf7d87SPrem Chintalapudi {ES.intern(RegisterPerfImplSymbolName), &ImplAddr}})) 2997ddf7d87SPrem Chintalapudi return std::move(Err); 3007ddf7d87SPrem Chintalapudi return std::make_unique<PerfSupportPlugin>(EPC, StartAddr, EndAddr, ImplAddr, 3017ddf7d87SPrem Chintalapudi EmitDebugInfo, EmitUnwindInfo); 3027ddf7d87SPrem Chintalapudi } 303