diff --git a/llvm/include/llvm/ExecutionEngine/Orc/PerfSupportPlugin.h b/llvm/include/llvm/ExecutionEngine/Orc/PerfSupportPlugin.h --- a/llvm/include/llvm/ExecutionEngine/Orc/PerfSupportPlugin.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/PerfSupportPlugin.h @@ -1,4 +1,4 @@ -//===--- PerfSupportPlugin.h -- Utils for perf support ---*- C++ -*-===// +//===----- PerfSupportPlugin.h ----- Utils for perf support -----*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. @@ -20,6 +20,9 @@ namespace llvm { namespace orc { +/// Log perf jitdump events for each object (see +/// https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/tools/perf/Documentation/jitdump-specification.txt). +/// Currently has support for dumping code load records and unwind info records. class PerfSupportPlugin : public ObjectLinkingLayer::Plugin { public: PerfSupportPlugin(ExecutorProcessControl &EPC, @@ -70,7 +73,6 @@ struct PerfJITRecordPrefix { PerfJITRecordType Id; // record type identifier, uint32_t uint32_t TotalSize; - uint64_t Timestamp; }; struct PerfJITCodeLoadRecord { PerfJITRecordPrefix Prefix; @@ -126,34 +128,25 @@ namespace shared { -using SPSPerfJITRecordPrefix = SPSTuple; +using SPSPerfJITRecordPrefix = SPSTuple; template <> class SPSSerializationTraits { public: - using ImplTupleType = std::tuple; static size_t size(const PerfJITRecordPrefix &Val) { - auto tup = std::make_tuple(static_cast(Val.Id), Val.TotalSize, - Val.Timestamp); - return SPSSerializationTraits::size( - tup); + return SPSPerfJITRecordPrefix::AsArgList::size( + static_cast(Val.Id), Val.TotalSize); } static bool deserialize(SPSInputBuffer &IB, PerfJITRecordPrefix &Val) { - ImplTupleType Tup; - if (SPSSerializationTraits::deserialize(IB, Tup)) { - Val.Id = static_cast(std::move(std::get<0>(Tup))); - Val.TotalSize = std::move(std::get<1>(Tup)); - Val.Timestamp = std::move(std::get<2>(Tup)); - return true; - } else { + uint32_t Id; + if (!SPSPerfJITRecordPrefix::AsArgList::deserialize(IB, Id, Val.TotalSize)) return false; - } + Val.Id = static_cast(Id); + return true; } static bool serialize(SPSOutputBuffer &OB, const PerfJITRecordPrefix &Val) { - return SPSSerializationTraits:: - serialize(OB, std::make_tuple(static_cast(Val.Id), - Val.TotalSize, Val.Timestamp)); + return SPSPerfJITRecordPrefix::AsArgList::serialize( + OB, static_cast(Val.Id), Val.TotalSize); } }; @@ -164,40 +157,22 @@ template <> class SPSSerializationTraits { public: - using ImplTupleType = - std::tuple; static size_t size(const PerfJITCodeLoadRecord &Val) { - auto tup = - std::make_tuple(Val.Prefix, Val.Pid, Val.Tid, Val.Vma, Val.CodeAddr, - Val.CodeSize, Val.CodeIndex, Val.Name); - return SPSSerializationTraits::size(tup); + return SPSPerfJITCodeLoadRecord::AsArgList::size( + Val.Prefix, Val.Pid, Val.Tid, Val.Vma, Val.CodeAddr, Val.CodeSize, + Val.CodeIndex, Val.Name); } static bool deserialize(SPSInputBuffer &IB, PerfJITCodeLoadRecord &Val) { - ImplTupleType Tup; - if (SPSSerializationTraits::deserialize(IB, Tup)) { - Val.Prefix = std::move(std::get<0>(Tup)); - Val.Pid = std::move(std::get<1>(Tup)); - Val.Tid = std::move(std::get<2>(Tup)); - Val.Vma = std::move(std::get<3>(Tup)); - Val.CodeAddr = std::move(std::get<4>(Tup)); - Val.CodeSize = std::move(std::get<5>(Tup)); - Val.CodeIndex = std::move(std::get<6>(Tup)); - Val.Name = std::move(std::get<7>(Tup)); - return true; - } else { - return false; - } + return SPSPerfJITCodeLoadRecord::AsArgList::deserialize( + IB, Val.Prefix, Val.Pid, Val.Tid, Val.Vma, Val.CodeAddr, Val.CodeSize, + Val.CodeIndex, Val.Name); } static bool serialize(SPSOutputBuffer &OB, const PerfJITCodeLoadRecord &Val) { - return SPSSerializationTraits:: - serialize(OB, std::make_tuple(Val.Prefix, Val.Pid, Val.Tid, Val.Vma, - Val.CodeAddr, Val.CodeSize, Val.CodeIndex, - Val.Name)); + return SPSPerfJITCodeLoadRecord::AsArgList::serialize( + OB, Val.Prefix, Val.Pid, Val.Tid, Val.Vma, Val.CodeAddr, Val.CodeSize, + Val.CodeIndex, Val.Name); } }; @@ -206,31 +181,19 @@ template <> class SPSSerializationTraits { public: - using ImplTupleType = std::tuple; static size_t size(const PerfJITDebugEntry &Val) { - auto tup = std::make_tuple(Val.Addr, Val.Lineno, Val.Discrim, Val.Name); - return SPSSerializationTraits::size( - tup); + return SPSPerfJITDebugEntry::AsArgList::size(Val.Addr, Val.Lineno, + Val.Discrim, Val.Name); } static bool deserialize(SPSInputBuffer &IB, PerfJITDebugEntry &Val) { - ImplTupleType Tup; - if (SPSSerializationTraits::deserialize(IB, Tup)) { - Val.Addr = std::move(std::get<0>(Tup)); - Val.Lineno = std::move(std::get<1>(Tup)); - Val.Discrim = std::move(std::get<2>(Tup)); - Val.Name = std::move(std::get<3>(Tup)); - return true; - } else { - return false; - } + return SPSPerfJITDebugEntry::AsArgList::deserialize( + IB, Val.Addr, Val.Lineno, Val.Discrim, Val.Name); } static bool serialize(SPSOutputBuffer &OB, const PerfJITDebugEntry &Val) { - return SPSSerializationTraits:: - serialize(OB, - std::make_tuple(Val.Addr, Val.Lineno, Val.Discrim, Val.Name)); + return SPSPerfJITDebugEntry::AsArgList::serialize(OB, Val.Addr, Val.Lineno, + Val.Discrim, Val.Name); } }; @@ -242,32 +205,18 @@ class SPSSerializationTraits { public: - using ImplTupleType = std::tuple>; static size_t size(const PerfJITDebugInfoRecord &Val) { - auto tup = - std::make_tuple(Val.Prefix, Val.CodeAddr, Val.NrEntry, Val.Entries); - return SPSSerializationTraits::size(tup); + return SPSPerfJITDebugInfoRecord::AsArgList::size(Val.Prefix, Val.CodeAddr, + Val.NrEntry, Val.Entries); } static bool deserialize(SPSInputBuffer &IB, PerfJITDebugInfoRecord &Val) { - ImplTupleType Tup; - if (SPSSerializationTraits::deserialize(IB, Tup)) { - Val.Prefix = std::move(std::get<0>(Tup)); - Val.CodeAddr = std::move(std::get<1>(Tup)); - Val.NrEntry = std::move(std::get<2>(Tup)); - Val.Entries = std::move(std::get<3>(Tup)); - return true; - } else { - return false; - } + return SPSPerfJITDebugInfoRecord::AsArgList::deserialize( + IB, Val.Prefix, Val.CodeAddr, Val.NrEntry, Val.Entries); } static bool serialize(SPSOutputBuffer &OB, const PerfJITDebugInfoRecord &Val) { - return SPSSerializationTraits:: - serialize(OB, std::make_tuple(Val.Prefix, Val.CodeAddr, Val.NrEntry, - Val.Entries)); + return SPSPerfJITDebugInfoRecord::AsArgList::serialize( + OB, Val.Prefix, Val.CodeAddr, Val.NrEntry, Val.Entries); } }; @@ -278,42 +227,22 @@ class SPSSerializationTraits { public: - using ImplTupleType = std::tuple; static size_t size(const PerfJITCodeUnwindingInfoRecord &Val) { - auto tup = std::make_tuple( + return SPSPerfJITCodeUnwindingInfoRecord::AsArgList::size( Val.Prefix, Val.UnwindDataSize, Val.EHFrameHdrSize, Val.MappedSize, Val.EHFrameHdrAddr, Val.EHFrameHdr, Val.EHFrameAddr); - return SPSSerializationTraits::size(tup); } static bool deserialize(SPSInputBuffer &IB, PerfJITCodeUnwindingInfoRecord &Val) { - ImplTupleType Tup; - if (SPSSerializationTraits::deserialize(IB, Tup)) { - Val.Prefix = std::move(std::get<0>(Tup)); - Val.UnwindDataSize = std::move(std::get<1>(Tup)); - Val.EHFrameHdrSize = std::move(std::get<2>(Tup)); - Val.MappedSize = std::move(std::get<3>(Tup)); - Val.EHFrameHdrAddr = std::move(std::get<4>(Tup)); - Val.EHFrameHdr = std::move(std::get<5>(Tup)); - Val.EHFrameAddr = std::move(std::get<6>(Tup)); - return true; - } else { - return false; - } + return SPSPerfJITCodeUnwindingInfoRecord::AsArgList::deserialize( + IB, Val.Prefix, Val.UnwindDataSize, Val.EHFrameHdrSize, Val.MappedSize, + Val.EHFrameHdrAddr, Val.EHFrameHdr, Val.EHFrameAddr); } static bool serialize(SPSOutputBuffer &OB, const PerfJITCodeUnwindingInfoRecord &Val) { - return SPSSerializationTraits< - SPSPerfJITCodeUnwindingInfoRecord, - ImplTupleType>::serialize(OB, - std::make_tuple( - Val.Prefix, Val.UnwindDataSize, - Val.EHFrameHdrSize, Val.MappedSize, - Val.EHFrameHdrAddr, Val.EHFrameHdr, - Val.EHFrameAddr)); + return SPSPerfJITCodeUnwindingInfoRecord::AsArgList::serialize( + OB, Val.Prefix, Val.UnwindDataSize, Val.EHFrameHdrSize, Val.MappedSize, + Val.EHFrameHdrAddr, Val.EHFrameHdr, Val.EHFrameAddr); } }; @@ -323,31 +252,17 @@ template <> class SPSSerializationTraits { public: - using ImplTupleType = std::tuple, - std::vector, - PerfJITCodeUnwindingInfoRecord>; static size_t size(const PerfJITRecordBatch &Val) { - auto tup = std::make_tuple(Val.CodeLoadRecords, Val.DebugInfoRecords, - Val.UnwindingRecord); - return SPSSerializationTraits::size( - tup); + return SPSPerfJITRecordBatch::AsArgList::size( + Val.CodeLoadRecords, Val.DebugInfoRecords, Val.UnwindingRecord); } static bool deserialize(SPSInputBuffer &IB, PerfJITRecordBatch &Val) { - ImplTupleType Tup; - if (SPSSerializationTraits::deserialize(IB, Tup)) { - Val.CodeLoadRecords = std::move(std::get<0>(Tup)); - Val.DebugInfoRecords = std::move(std::get<1>(Tup)); - Val.UnwindingRecord = std::move(std::get<2>(Tup)); - return true; - } else { - return false; - } + return SPSPerfJITRecordBatch::AsArgList::deserialize( + IB, Val.CodeLoadRecords, Val.DebugInfoRecords, Val.UnwindingRecord); } static bool serialize(SPSOutputBuffer &OB, const PerfJITRecordBatch &Val) { - return SPSSerializationTraits:: - serialize(OB, std::make_tuple(Val.CodeLoadRecords, Val.DebugInfoRecords, - Val.UnwindingRecord)); + return SPSPerfJITRecordBatch::AsArgList::serialize( + OB, Val.CodeLoadRecords, Val.DebugInfoRecords, Val.UnwindingRecord); } }; diff --git a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h --- a/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h +++ b/llvm/include/llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h @@ -1,3 +1,4 @@ +//===------- JITLoaderPerf.h --- Register profiler objects ------*- C++ -*-===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. diff --git a/llvm/lib/ExecutionEngine/Orc/PerfSupportPlugin.cpp b/llvm/lib/ExecutionEngine/Orc/PerfSupportPlugin.cpp --- a/llvm/lib/ExecutionEngine/Orc/PerfSupportPlugin.cpp +++ b/llvm/lib/ExecutionEngine/Orc/PerfSupportPlugin.cpp @@ -1,3 +1,15 @@ +//===----- PerfSupportPlugin.cpp --- Utils for perf support -----*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Handles support for registering code with perf +// +//===----------------------------------------------------------------------===// + #include "llvm/ExecutionEngine/Orc/PerfSupportPlugin.h" #include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h" @@ -7,11 +19,7 @@ #include "llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h" #include "llvm/ExecutionEngine/Orc/Shared/SimplePackedSerialization.h" -#ifdef __linux__ -#include // clock_gettime(), time(), localtime_r() */ -#endif - -#define DEBUG_TYPE orc +#define DEBUG_TYPE "orc" using namespace llvm; using namespace llvm::orc; @@ -19,28 +27,6 @@ namespace { -std::string serialize(LinkGraph &G) { - std::string out; - raw_string_ostream OS(out); - OS << "LinkGraph: \n"; - for (auto &S : G.sections()) { - OS << "Section: " << S.getName() << "\n"; - for (auto B : S.blocks()) { - OS << "Block: " << *B << "\n"; - for (auto &E : B->edges()) { - OS << " Edge: "; - OS << x86_64::getEdgeKindName(E.getKind()) << ": "; - OS << E.getTarget().getName() << " + " << E.getAddend() << " "; - OS << " @ " << E.getOffset() << "\n"; - } - } - for (auto Sym : S.symbols()) { - OS << "Symbol: " << *Sym << "\n"; - } - } - return out; -} - // Creates an EH frame header prepared for a 32-bit relative relocation // to the start of the .eh_frame section. Absolute injects a 64-bit absolute // address space offset 4 bytes from the start instead of 4 bytes @@ -70,17 +56,20 @@ ? sizeof(uint64_t) : sizeof(EHFrameRelocation)); std::string HeaderContent(HeaderSize, '\0'); - HeaderContent[0] = Version; - HeaderContent[1] = EhFramePtrEnc; - HeaderContent[2] = FDECountEnc; - HeaderContent[3] = TableEnc; + BinaryStreamWriter Writer( + MutableArrayRef( + reinterpret_cast(HeaderContent.data()), HeaderSize), + endianness); + Writer.writeInteger(Version); + Writer.writeInteger(EhFramePtrEnc); + Writer.writeInteger(FDECountEnc); + Writer.writeInteger(TableEnc); if (absolute) { uint64_t EHFrameAddr = support::endian::byte_swap( SectionRange(EHFrame).getStart().getValue(), endianness); - memcpy(HeaderContent.data() + 4, &EHFrameAddr, sizeof(EHFrameAddr)); + Writer.writeInteger(EHFrameAddr); } else { - memcpy(HeaderContent.data() + 4, &EHFrameRelocation, - sizeof(EHFrameRelocation)); + Writer.writeInteger(EHFrameRelocation); } return HeaderContent; } @@ -119,7 +108,6 @@ auto Addr = Sym.getAddress(); auto Size = Sym.getSize(); Record.Prefix.Id = PerfJITRecordType::JIT_CODE_LOAD; - Record.Prefix.Timestamp = perf_get_timestamp(); // Runtime sets PID Record.Pid = 0; // Runtime sets TID @@ -143,29 +131,27 @@ static std::optional getDebugInfoRecord(const Symbol &Sym, DWARFContext *DC) { - // dbgs() << "Getting debug info for symbol " << Sym.getName() << "\n"; if (!DC) { - // No debug info available - dbgs() << "No debug info available\n"; + LLVM_DEBUG(dbgs() << "No debug info available\n"); return std::nullopt; } auto &Section = Sym.getBlock().getSection(); auto Addr = Sym.getAddress(); auto Size = Sym.getSize(); auto SAddr = object::SectionedAddress{Addr.getValue(), Section.getOrdinal()}; - dbgs() << "Getting debug info for symbol " << Sym.getName() << " at address " - << Addr.getValue() << " with size " << Size << "\n"; - dbgs() << "Section ordinal: " << Section.getOrdinal() << "\n"; + LLVM_DEBUG(dbgs() << "Getting debug info for symbol " << Sym.getName() + << " at address " << Addr.getValue() << " with size " + << Size << "\n" + << "Section ordinal: " << Section.getOrdinal() << "\n"); auto LInfo = DC->getLineInfoForAddressRange( SAddr, Size, DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath); if (LInfo.empty()) { // No line info available - dbgs() << "No line info available\n"; + LLVM_DEBUG(dbgs() << "No line info available\n"); return std::nullopt; } PerfJITDebugInfoRecord Record; Record.Prefix.Id = PerfJITRecordType::JIT_CODE_DEBUG_INFO; - Record.Prefix.Timestamp = perf_get_timestamp(); Record.CodeAddr = Addr.getValue(); for (const auto &Entry : LInfo) { auto Addr = Entry.first; @@ -188,6 +174,9 @@ EntriesBytes += Entry.Name.size() + 1; // Name } Record.Prefix.TotalSize = EntriesBytes; + LLVM_DEBUG(dbgs() << "Created debug info record\n" + << "Total size: " << Record.Prefix.TotalSize << "\n" + << "Nr entries: " << Record.NrEntry << "\n"); return Record; } @@ -195,25 +184,24 @@ PerfJITCodeUnwindingInfoRecord Record; Record.Prefix.Id = PerfJITRecordType::JIT_CODE_UNWINDING_INFO; Record.Prefix.TotalSize = 0; - Record.Prefix.Timestamp = perf_get_timestamp(); auto Eh_frame = G.findSectionByName(".eh_frame"); if (!Eh_frame) { - dbgs() << "No .eh_frame section found\n"; + LLVM_DEBUG(dbgs() << "No .eh_frame section found\n"); return Record; } if (!G.getTargetTriple().isOSBinFormatELF()) { - dbgs() << "Not an ELF file, will not emit unwinding info\n"; + LLVM_DEBUG(dbgs() << "Not an ELF file, will not emit unwinding info\n"); return Record; } auto SR = SectionRange(*Eh_frame); auto EHFrameSize = SR.getSize(); auto Eh_frame_hdr = G.findSectionByName(".eh_frame_hdr"); if (!Eh_frame_hdr) { - if (G.getTargetTriple().getArch() != Triple::x86_64) { + if (G.getTargetTriple().getArch() == Triple::x86_64) { Record.EHFrameHdr = createX64EHFrameHeader(*Eh_frame, G.getEndianness(), true); } else { - dbgs() << "No .eh_frame_hdr section found\n"; + LLVM_DEBUG(dbgs() << "No .eh_frame_hdr section found\n"); return Record; } Record.EHFrameHdrAddr = 0; @@ -235,11 +223,11 @@ 3 * sizeof(uint64_t) // unwind_data_size, eh_frame_hdr_size, mapped_size + Record.UnwindDataSize // eh_frame_hdr, eh_frame ); - dbgs() << "Created unwind record\n"; - dbgs() << "Total size: " << Record.Prefix.TotalSize << "\n"; - dbgs() << "Unwind size: " << Record.UnwindDataSize << "\n"; - dbgs() << "EHFrame size: " << EHFrameSize << "\n"; - dbgs() << "EHFrameHdr size: " << Record.EHFrameHdrSize << "\n"; + LLVM_DEBUG(dbgs() << "Created unwind record\n" + << "Total size: " << Record.Prefix.TotalSize << "\n" + << "Unwind size: " << Record.UnwindDataSize << "\n" + << "EHFrame size: " << EHFrameSize << "\n" + << "EHFrameHdr size: " << Record.EHFrameHdrSize << "\n"); return Record; } @@ -248,7 +236,7 @@ bool EmitUnwindInfo) { PerfJITRecordBatch Batch; for (auto Sym : G.defined_symbols()) { - if (!Sym->hasName()) + if (!Sym->hasName() || !Sym->isCallable()) continue; auto DebugInfo = getDebugInfoRecord(*Sym, DC); if (DebugInfo) @@ -274,20 +262,15 @@ RegisterPerfImplAddr(RegisterPerfImplAddr), CodeIndex(0), EmitUnwindInfo(EmitUnwindInfo) { cantFail(EPC.callSPSWrapper(RegisterPerfStartAddr)); - dbgs() << "Created perf support plugin\n"; } PerfSupportPlugin::~PerfSupportPlugin() { - dbgs() << "Destroying perf support plugin\n"; cantFail(EPC.callSPSWrapper(RegisterPerfEndAddr)); } void PerfSupportPlugin::modifyPassConfig(MaterializationResponsibility &MR, LinkGraph &G, PassConfiguration &Config) { - dbgs() << "Modifying perf support plugin pass config\n"; Config.PostFixupPasses.push_back([this, &MR](LinkGraph &G) { - dbgs() << "Running perf support plugin post-fixup pass\n"; - dbgs() << serialize(G) << "\n"; // TODO get an actual DWARFContext for line info DWARFContext *DWC = nullptr; auto Batch = getRecords(G, DWC, CodeIndex, EmitUnwindInfo); @@ -296,8 +279,6 @@ shared::SPSArgList>( RegisterPerfImplAddr, Batch)), {}}); - dbgs() << "Registered alloc action\n"; - dbgs() << "Impl address: " << RegisterPerfImplAddr << "\n"; return Error::success(); }); } diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.cpp --- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.cpp +++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.cpp @@ -17,6 +17,8 @@ #include // for read(), close() #endif +#define DEBUG_TYPE "orc" + // language identifier (XXX: should we generate something better from debug // info?) #define JIT_LANG "llvm-IR" @@ -84,37 +86,62 @@ uint64_t MappedSize; }; +static inline uint64_t timespec_to_ns(const struct timespec *ts) { + const uint64_t NanoSecPerSec = 1000000000; + return ((uint64_t)ts->tv_sec * NanoSecPerSec) + ts->tv_nsec; +} + +static inline uint64_t perf_get_timestamp() { +#ifdef __linux__ + struct timespec ts; + int ret; + + ret = clock_gettime(CLOCK_MONOTONIC, &ts); + if (ret) + return 0; + + return timespec_to_ns(&ts); +#else + return 0; +#endif +} + static void writeDebugRecord(const PerfJITDebugInfoRecord &DebugRecord) { assert(state && "PerfState not initialized"); - dbgs() << "Writing debug record with " << DebugRecord.Entries.size() - << " entries\n"; + LLVM_DEBUG(dbgs() << "Writing debug record with " + << DebugRecord.Entries.size() << " entries\n"); + size_t Written = 0; DIR dir{RecHeader{static_cast(DebugRecord.Prefix.Id), - DebugRecord.Prefix.TotalSize, DebugRecord.Prefix.Timestamp}, + DebugRecord.Prefix.TotalSize, perf_get_timestamp()}, DebugRecord.CodeAddr, DebugRecord.NrEntry}; state->Dumpstream->write(reinterpret_cast(&dir), sizeof(dir)); + Written += sizeof(dir); for (auto &die : DebugRecord.Entries) { DIE d{die.Addr, die.Lineno, die.Discrim}; state->Dumpstream->write(reinterpret_cast(&d), sizeof(d)); state->Dumpstream->write(die.Name.data(), die.Name.size() + 1); + Written += sizeof(d) + die.Name.size() + 1; } + LLVM_DEBUG(dbgs() << "wrote " << Written << " bytes of debug info\n"); } static void writeCodeRecord(const PerfJITCodeLoadRecord &CodeRecord) { assert(state && "PerfState not initialized"); uint32_t Tid = get_threadid(); - dbgs() << "Writing code record with code size " << CodeRecord.CodeSize - << " and code index " << CodeRecord.CodeIndex << "\n"; + LLVM_DEBUG(dbgs() << "Writing code record with code size " + << CodeRecord.CodeSize << " and code index " + << CodeRecord.CodeIndex << "\n"); CLR clr{RecHeader{static_cast(CodeRecord.Prefix.Id), - CodeRecord.Prefix.TotalSize, CodeRecord.Prefix.Timestamp}, + CodeRecord.Prefix.TotalSize, perf_get_timestamp()}, state->Pid, Tid, CodeRecord.Vma, CodeRecord.CodeAddr, CodeRecord.CodeSize, CodeRecord.CodeIndex}; - dbgs() << "wrote " << sizeof(clr) << " bytes of CLR, " - << CodeRecord.Name.size() + 1 << " bytes of name, " - << CodeRecord.CodeSize << " bytes of code\n"; + LLVM_DEBUG(dbgs() << "wrote " << sizeof(clr) << " bytes of CLR, " + << CodeRecord.Name.size() + 1 << " bytes of name, " + << CodeRecord.CodeSize << " bytes of code\n"); state->Dumpstream->write(reinterpret_cast(&clr), sizeof(clr)); state->Dumpstream->write(CodeRecord.Name.data(), CodeRecord.Name.size() + 1); state->Dumpstream->write((const char *)CodeRecord.CodeAddr, @@ -129,14 +156,14 @@ << UnwindRecord.EHFrameHdrSize << " and mapped size " << UnwindRecord.MappedSize << "\n"; UWR uwr{RecHeader{static_cast(UnwindRecord.Prefix.Id), - UnwindRecord.Prefix.TotalSize, - UnwindRecord.Prefix.Timestamp}, + UnwindRecord.Prefix.TotalSize, perf_get_timestamp()}, UnwindRecord.UnwindDataSize, UnwindRecord.EHFrameHdrSize, UnwindRecord.MappedSize}; - dbgs() << "wrote " << sizeof(uwr) << " bytes of UWR, " - << UnwindRecord.EHFrameHdrSize << " bytes of EH frame header, " - << UnwindRecord.UnwindDataSize - UnwindRecord.EHFrameHdrSize - << " bytes of EH frame\n"; + LLVM_DEBUG(dbgs() << "wrote " << sizeof(uwr) << " bytes of UWR, " + << UnwindRecord.EHFrameHdrSize + << " bytes of EH frame header, " + << UnwindRecord.UnwindDataSize - UnwindRecord.EHFrameHdrSize + << " bytes of EH frame\n"); state->Dumpstream->write(reinterpret_cast(&uwr), sizeof(uwr)); if (UnwindRecord.EHFrameHdrAddr) { state->Dumpstream->write((const char *)UnwindRecord.EHFrameHdrAddr, @@ -151,7 +178,6 @@ } static Error registerJITLoaderPerfImpl(const PerfJITRecordBatch &Batch) { - dbgs() << "registerJITLoaderPerfImpl called\n"; if (!state) { return make_error("PerfState not initialized", inconvertibleErrorCode()); @@ -220,26 +246,6 @@ #endif } -static inline uint64_t timespec_to_ns(const struct timespec *ts) { - const uint64_t NanoSecPerSec = 1000000000; - return ((uint64_t)ts->tv_sec * NanoSecPerSec) + ts->tv_nsec; -} - -static inline uint64_t perf_get_timestamp() { -#ifdef __linux__ - struct timespec ts; - int ret; - - ret = clock_gettime(CLOCK_MONOTONIC, &ts); - if (ret) - return 0; - - return timespec_to_ns(&ts); -#else - return 0; -#endif -} - static Expected
FillMachine(PerfState &state) { Header hdr; hdr.Magic = LLVM_PERF_JIT_MAGIC;