//===-- ProcessorTrace.h -------------------------------------- -*- 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 // //===----------------------------------------------------------------------===// #ifndef liblldb_ProcessorTrace_H_ #define liblldb_ProcessorTrace_H_ #include "lldb/Utility/Status.h" #include "lldb/Utility/TraceOptions.h" #include "lldb/lldb-types.h" #include "llvm/ADT/DenseMap.h" #include "llvm/ADT/DenseSet.h" #include #include #include namespace lldb_private { namespace process_linux { // This class keeps track of one tracing instance of // Intel(R) Processor Trace on Linux OS. There is a map keeping track // of different tracing instances on each thread, which enables trace // gathering on a per thread level. // // The tracing instance is linked with a trace id. The trace id acts like // a key to the tracing instance and trace manipulations could be // performed using the trace id. // // The trace id could map to trace instances for a group of threads // (spanning to all the threads in the process) or a single thread. // The kernel interface for us is the perf_event_open. class ProcessorTraceMonitor; typedef std::unique_ptr ProcessorTraceMonitorUP; class ProcessorTraceMonitor { class munmap_delete { size_t m_length; public: munmap_delete(size_t length) : m_length(length) {} void operator()(void *ptr) { if (m_length) munmap(ptr, m_length); } }; class file_close { public: file_close() = default; void operator()(int *ptr) { if (ptr == nullptr) return; if (*ptr == -1) return; close(*ptr); std::default_delete()(ptr); } }; std::unique_ptr m_mmap_meta; std::unique_ptr m_mmap_aux; std::unique_ptr m_fd; // perf_event_mmap_page *m_mmap_base; lldb::user_id_t m_traceid; lldb::tid_t m_thread_id; // Counter to track trace instances. static lldb::user_id_t m_trace_num; void SetTraceID(lldb::user_id_t traceid) { m_traceid = traceid; } Status StartTrace(lldb::pid_t pid, lldb::tid_t tid, const TraceOptions &config); llvm::MutableArrayRef GetAuxBuffer(); llvm::MutableArrayRef GetDataBuffer(); ProcessorTraceMonitor() : m_mmap_meta(nullptr, munmap_delete(0)), m_mmap_aux(nullptr, munmap_delete(0)), m_fd(nullptr, file_close()), m_traceid(LLDB_INVALID_UID), m_thread_id(LLDB_INVALID_THREAD_ID){}; void SetThreadID(lldb::tid_t tid) { m_thread_id = tid; } public: static llvm::Expected GetOSEventType(); static bool IsSupported(); static Status GetCPUType(TraceOptions &config); static llvm::Expected Create(lldb::pid_t pid, lldb::tid_t tid, const TraceOptions &config, bool useProcessSettings); Status ReadPerfTraceAux(llvm::MutableArrayRef &buffer, size_t offset = 0); Status ReadPerfTraceData(llvm::MutableArrayRef &buffer, size_t offset = 0); ~ProcessorTraceMonitor() = default; lldb::tid_t GetThreadID() const { return m_thread_id; } lldb::user_id_t GetTraceID() const { return m_traceid; } Status GetTraceConfig(TraceOptions &config) const; /// Read data from a cyclic buffer /// /// \param[in] [out] buf /// Destination buffer, the buffer will be truncated to written size. /// /// \param[in] src /// Source buffer which must be a cyclic buffer. /// /// \param[in] src_cyc_index /// The index pointer (start of the valid data in the cyclic /// buffer). /// /// \param[in] offset /// The offset to begin reading the data in the cyclic buffer. static void ReadCyclicBuffer(llvm::MutableArrayRef &dst, llvm::MutableArrayRef src, size_t src_cyc_index, size_t offset); }; } // namespace process_linux } // namespace lldb_private #endif