20 #include "llvm/Config/config.h" 37 #include <sys/types.h> 49 #define JIT_LANG "llvm-IR" 50 #define LLVM_PERF_JIT_MAGIC \ 51 ((uint32_t)'J' << 24 | (uint32_t)'i' << 16 | (uint32_t)'T' << 8 | \ 53 #define LLVM_PERF_JIT_VERSION 1 57 #define JITDUMP_FLAGS_ARCH_TIMESTAMP (1ULL << 0) 59 struct LLVMPerfJitHeader;
63 PerfJITEventListener();
64 ~PerfJITEventListener() {
69 void notifyObjectLoaded(ObjectKey K,
const ObjectFile &Obj,
71 void notifyFreeingObject(ObjectKey K)
override;
74 bool InitDebuggingDir();
77 static bool FillMachine(LLVMPerfJitHeader &hdr);
93 std::unique_ptr<raw_fd_ostream> Dumpstream;
99 void *MarkerAddr = NULL;
102 bool SuccessfullyInitialized =
false;
105 uint64_t CodeGeneration = 1;
113 JIT_CODE_DEBUG_INFO = 2,
115 JIT_CODE_UNWINDING_INFO = 4,
120 struct LLVMPerfJitHeader {
132 struct LLVMPerfJitRecordPrefix {
138 struct LLVMPerfJitRecordCodeLoad {
139 LLVMPerfJitRecordPrefix
Prefix;
149 struct LLVMPerfJitDebugEntry {
156 struct LLVMPerfJitRecordDebugInfo {
157 LLVMPerfJitRecordPrefix
Prefix;
164 static inline uint64_t timespec_to_ns(
const struct timespec *ts) {
165 const uint64_t NanoSecPerSec = 1000000000;
166 return ((uint64_t)ts->tv_sec * NanoSecPerSec) + ts->tv_nsec;
169 static inline uint64_t perf_get_timestamp(
void) {
173 ret = clock_gettime(CLOCK_MONOTONIC, &ts);
177 return timespec_to_ns(&ts);
180 PerfJITEventListener::PerfJITEventListener() : Pid(::getpid()) {
182 if (!perf_get_timestamp()) {
183 errs() <<
"kernel does not support CLOCK_MONOTONIC\n";
187 if (!InitDebuggingDir()) {
188 errs() <<
"could not initialize debugging directory\n";
192 std::string Filename;
194 FilenameBuf << JitPath <<
"/jit-" << Pid <<
".dump";
202 errs() <<
"could not open JIT dump file " << FilenameBuf.
str() <<
": " 203 << EC.message() <<
"\n";
207 Dumpstream = make_unique<raw_fd_ostream>(DumpFd,
true);
209 LLVMPerfJitHeader Header = {0};
210 if (!FillMachine(Header))
220 Header.TotalSize =
sizeof(Header);
222 Header.Timestamp = perf_get_timestamp();
223 Dumpstream->write(reinterpret_cast<const char *>(&Header),
sizeof(Header));
226 if (!Dumpstream->has_error())
227 SuccessfullyInitialized =
true;
230 void PerfJITEventListener::notifyObjectLoaded(
234 if (!SuccessfullyInitialized)
246 std::string SourceFileName;
269 uint64_t Addr = *AddrOrErr;
270 uint64_t
Size =
P.second;
275 Addr, Size, FileLineInfoKind::AbsoluteFilePath);
277 NotifyDebug(Addr, Lines);
278 NotifyCode(Name, Addr, Size);
284 void PerfJITEventListener::notifyFreeingObject(ObjectKey K) {
289 bool PerfJITEventListener::InitDebuggingDir() {
292 char TimeBuffer[
sizeof(
"YYYYMMDD")];
296 if (
const char *BaseDir = getenv(
"JITDUMPDIR"))
302 Path +=
"/.debug/jit/";
304 errs() <<
"could not create jit cache directory " << Path <<
": " 305 << EC.message() <<
"\n";
311 localtime_r(&Time, &LocalTime);
312 strftime(TimeBuffer,
sizeof(TimeBuffer),
"%Y%m%d", &LocalTime);
320 errs() <<
"could not create unique jit cache directory " << UniqueDebugDir
321 <<
": " << EC.message() <<
"\n";
325 JitPath = UniqueDebugDir.
str();
330 bool PerfJITEventListener::OpenMarker() {
340 MAP_PRIVATE, DumpFd, 0);
342 if (MarkerAddr == MAP_FAILED) {
343 errs() <<
"could not mmap JIT marker\n";
349 void PerfJITEventListener::CloseMarker() {
354 MarkerAddr =
nullptr;
357 bool PerfJITEventListener::FillMachine(LLVMPerfJitHeader &hdr) {
364 size_t RequiredMemory =
sizeof(id) +
sizeof(
info);
378 errs() <<
"could not open /proc/self/exe: " << EC.message() <<
"\n";
382 memcpy(&
id, (*MB)->getBufferStart(),
sizeof(id));
383 memcpy(&
info, (*MB)->getBufferStart() +
sizeof(id),
sizeof(
info));
386 if (
id[0] != 0x7f ||
id[1] !=
'E' ||
id[2] !=
'L' ||
id[3] !=
'F') {
387 errs() <<
"invalid elf signature\n";
391 hdr.ElfMach =
info.e_machine;
397 uint64_t CodeAddr, uint64_t CodeSize) {
398 assert(SuccessfullyInitialized);
404 LLVMPerfJitRecordCodeLoad rec;
405 rec.Prefix.Id = JIT_CODE_LOAD;
406 rec.Prefix.TotalSize =
sizeof(rec) +
409 rec.Prefix.Timestamp = perf_get_timestamp();
411 rec.CodeSize = CodeSize;
413 rec.CodeAddr = CodeAddr;
420 rec.CodeIndex = CodeGeneration++;
422 Dumpstream->write(reinterpret_cast<const char *>(&rec),
sizeof(rec));
423 Dumpstream->write(Symbol->data(), Symbol->size() + 1);
424 Dumpstream->write(reinterpret_cast<const char *>(CodeAddr), CodeSize);
427 void PerfJITEventListener::NotifyDebug(uint64_t CodeAddr,
429 assert(SuccessfullyInitialized);
435 LLVMPerfJitRecordDebugInfo rec;
436 rec.Prefix.Id = JIT_CODE_DEBUG_INFO;
437 rec.Prefix.TotalSize =
sizeof(rec);
438 rec.Prefix.Timestamp = perf_get_timestamp();
439 rec.CodeAddr = CodeAddr;
440 rec.NrEntry = Lines.
size();
447 rec.Prefix.TotalSize +=
sizeof(LLVMPerfJitDebugEntry);
448 rec.Prefix.TotalSize += line.
FileName.size() + 1;
462 Dumpstream->write(reinterpret_cast<const char *>(&rec),
sizeof(rec));
465 LLVMPerfJitDebugEntry LineInfo;
468 LineInfo.Addr = It->first;
472 LineInfo.Addr += 0x40;
473 LineInfo.Lineno = Line.
Line;
476 Dumpstream->write(reinterpret_cast<const char *>(&LineInfo),
490 return &*PerfListener;
Information about the loaded object.
std::error_code create_directories(const Twine &path, bool IgnoreExisting=true, perms Perms=owner_all|group_all)
Create all the non-existent directories in path.
std::error_code openFileForReadWrite(const Twine &Name, int &ResultFD, CreationDisposition Disp, OpenFlags Flags, unsigned Mode=0666)
Opens the file with the given name in a write-only or read-write mode, returning its open file descri...
Represents either an error or a value T.
raw_ostream & errs()
This returns a reference to a raw_ostream for standard error.
This class represents lattice values for constants.
Expected< StringRef > getName() const
JITEventListener - Abstract interface for use by the JIT to notify clients about significant events d...
DILineInfoSpecifier::FileLineInfoKind FileLineInfoKind
This class is the base class for all object file types.
Error takeError()
Take ownership of the stored error.
A format-neutral container for source line information.
SmartMutex< false > Mutex
Mutex - A standard, always enforced mutex.
amdgpu Simplify well known AMD library false Value Value const Twine & Name
Tagged union holding either a T or a Error.
#define LLVM_PERF_JIT_MAGIC
StringRef str() const
Explicit conversion to StringRef.
CD_CreateNew - When opening a file:
void append(in_iter S, in_iter E)
Append from an iterator pair.
Instances of this class acquire a given Mutex Lock when constructed and hold that lock until destruct...
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator begin()
std::error_code getError() const
LLVMJITEventListenerRef LLVMCreatePerfJITEventListener(void)
std::error_code openFileForWrite(const Twine &Name, int &ResultFD, CreationDisposition Disp=CD_CreateAlways, OpenFlags Flags=OF_None, unsigned Mode=0666)
Opens the file with the given name in a write-only or read-write mode, returning its open file descri...
Expected< uint64_t > getAddress() const
Returns the symbol virtual address (i.e.
void consumeError(Error Err)
Consume a Error without doing anything.
uint64_t get_threadid()
Return the current thread id, as used in various OS system calls.
std::string & str()
Flushes the stream contents to the target string and returns the string's reference.
static unsigned getPageSize()
static std::unique_ptr< DWARFContext > create(const object::ObjectFile &Obj, const LoadedObjectInfo *L=nullptr, function_ref< ErrorPolicy(Error)> HandleError=defaultErrorHandler, std::string DWPName="")
static const char *const Magic
virtual object::OwningBinary< object::ObjectFile > getObjectForDebug(const object::ObjectFile &Obj) const =0
Expected< SymbolRef::Type > getType() const
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small...
static JITEventListener * createPerfJITEventListener()
std::error_code createUniqueDirectory(const Twine &Prefix, SmallVectorImpl< char > &ResultPath)
std::vector< std::pair< SymbolRef, uint64_t > > computeSymbolSizes(const ObjectFile &O)
typename SuperClass::iterator iterator
This is a value type class that represents a single symbol in the list of symbols in the object file...
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset, bool IsVolatile=false)
Map a subrange of the specified file as a MemoryBuffer.
LLVM_ATTRIBUTE_ALWAYS_INLINE iterator end()
Provides a library for accessing information about this process and other processes on the operating ...
LLVMAttributeRef wrap(Attribute Attr)
LLVM_NODISCARD bool empty() const
#define LLVM_PERF_JIT_VERSION
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
struct LLVMOpaqueJITEventListener * LLVMJITEventListenerRef
A raw_ostream that writes to an std::string.
bool home_directory(SmallVectorImpl< char > &result)
Get the user's home directory.
ManagedStatic - This transparently changes the behavior of global statics to be lazily constructed on...