forked from OSchip/llvm-project
				
			
		
			
				
	
	
		
			141 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			141 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===-- ProcessorTrace.h -------------------------------------- -*- C++ -*-===//
 | |
| //
 | |
| //                     The LLVM Compiler Infrastructure
 | |
| //
 | |
| // This file is distributed under the University of Illinois Open Source
 | |
| // License. See LICENSE.TXT for details.
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #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 <linux/perf_event.h>
 | |
| #include <sys/mman.h>
 | |
| 
 | |
| 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 traace 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<ProcessorTraceMonitor> 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<int>()(ptr);
 | |
|     }
 | |
|   };
 | |
| 
 | |
|   std::unique_ptr<perf_event_mmap_page, munmap_delete> m_mmap_meta;
 | |
|   std::unique_ptr<uint8_t, munmap_delete> m_mmap_aux;
 | |
|   std::unique_ptr<int, file_close> 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<uint8_t> GetAuxBuffer();
 | |
|   llvm::MutableArrayRef<uint8_t> 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 Status GetCPUType(TraceOptions &config);
 | |
| 
 | |
|   static llvm::Expected<ProcessorTraceMonitorUP>
 | |
|   Create(lldb::pid_t pid, lldb::tid_t tid, const TraceOptions &config,
 | |
|          bool useProcessSettings);
 | |
| 
 | |
|   Status ReadPerfTraceAux(llvm::MutableArrayRef<uint8_t> &buffer,
 | |
|                           size_t offset = 0);
 | |
| 
 | |
|   Status ReadPerfTraceData(llvm::MutableArrayRef<uint8_t> &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<uint8_t> &dst,
 | |
|                                llvm::MutableArrayRef<uint8_t> src,
 | |
|                                size_t src_cyc_index, size_t offset);
 | |
| };
 | |
| } // namespace process_linux
 | |
| } // namespace lldb_private
 | |
| #endif
 |