1 //===-- IntelPTSingleBufferTrace.h ---------------------------- -*- C++ -*-===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #ifndef liblldb_IntelPTSingleBufferTrace_H_
10 #define liblldb_IntelPTSingleBufferTrace_H_
11 
12 #include "Perf.h"
13 
14 #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h"
15 #include "lldb/lldb-types.h"
16 
17 #include "llvm/Support/Error.h"
18 
19 #include <memory>
20 
21 namespace lldb_private {
22 namespace process_linux {
23 
24 llvm::Expected<uint32_t> GetIntelPTOSEventType();
25 
26 class IntelPTSingleBufferTrace;
27 
28 using IntelPTSingleBufferTraceUP = std::unique_ptr<IntelPTSingleBufferTrace>;
29 
30 enum class TraceCollectionState {
31   Running,
32   Paused,
33 };
34 
35 /// This class wraps a single perf event collecting intel pt data in a single
36 /// buffer.
37 class IntelPTSingleBufferTrace {
38 public:
39   /// Start tracing using a single Intel PT trace buffer.
40   ///
41   /// \param[in] request
42   ///     Intel PT configuration parameters.
43   ///
44   /// \param[in] tid
45   ///     The tid of the thread to be traced. If \b None, then this traces all
46   ///     threads of all processes.
47   ///
48   /// \param[in] core_id
49   ///     The CPU core id where to trace. If \b None, then this traces all CPUs.
50   ///
51   /// \param[in] initial_state
52   ///     The initial trace collection state.
53   ///
54   /// \return
55   ///   A \a IntelPTSingleBufferTrace instance if tracing was successful, or
56   ///   an \a llvm::Error otherwise.
57   static llvm::Expected<IntelPTSingleBufferTraceUP>
58   Start(const TraceIntelPTStartRequest &request,
59         llvm::Optional<lldb::tid_t> tid,
60         llvm::Optional<lldb::core_id_t> core_id,
61         TraceCollectionState initial_state);
62 
63   /// \return
64   ///    The bytes requested by a jLLDBTraceGetBinaryData packet that was routed
65   ///    to this trace instace.
66   llvm::Expected<std::vector<uint8_t>>
67   GetBinaryData(const TraceGetBinaryDataRequest &request) const;
68 
69   /// Read the trace buffer managed by this trace instance. To ensure that the
70   /// data is up-to-date and is not corrupted by read-write race conditions, the
71   /// underlying perf_event is paused during read, and later it's returned to
72   /// its initial state.
73   ///
74   /// \param[in] offset
75   ///     Offset of the data to read.
76   ///
77   /// \param[in] size
78   ///     Number of bytes to read.
79   ///
80   /// \return
81   ///     A vector with the requested binary data. The vector will have the
82   ///     size of the requested \a size. Non-available positions will be
83   ///     filled with zeroes.
84   llvm::Expected<std::vector<uint8_t>> GetTraceBuffer(size_t offset,
85                                                       size_t size);
86 
87   /// \return
88   ///     The total the size in bytes used by the trace buffer managed by this
89   ///     trace instance.
90   size_t GetTraceBufferSize() const;
91 
92   /// Change the collection state for this trace.
93   ///
94   /// This is a no-op if \p state is the same as the current state.
95   ///
96   /// \param[in] state
97   ///     The new state.
98   ///
99   /// \return
100   ///     An error if the state couldn't be changed.
101   llvm::Error ChangeCollectionState(TraceCollectionState state);
102 
103 private:
104   /// Construct new \a IntelPTSingleBufferThreadTrace. Users are supposed to
105   /// create instances of this class via the \a Start() method and not invoke
106   /// this one directly.
107   ///
108   /// \param[in] perf_event
109   ///   perf event configured for IntelPT.
110   ///
111   /// \param[in] collection_state
112   ///   The initial collection state for the provided perf_event.
113   IntelPTSingleBufferTrace(PerfEvent &&perf_event,
114                            TraceCollectionState collection_state)
115       : m_perf_event(std::move(perf_event)),
116         m_collection_state(collection_state) {}
117 
118   /// perf event configured for IntelPT.
119   PerfEvent m_perf_event;
120 
121   /// The initial state is stopped because tracing can only start when the
122   /// process is paused.
123   TraceCollectionState m_collection_state;
124 };
125 
126 } // namespace process_linux
127 } // namespace lldb_private
128 
129 #endif // liblldb_IntelPTSingleBufferTrace_H_
130