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 /// This class wraps a single perf event collecting intel pt data in a single
27 /// buffer.
28 class IntelPTSingleBufferTrace {
29 public:
30   /// Start tracing using a single Intel PT trace buffer.
31   ///
32   /// \param[in] request
33   ///     Intel PT configuration parameters.
34   ///
35   /// \param[in] tid
36   ///     The tid of the thread to be traced. If \b None, then this traces all
37   ///     threads of all processes.
38   ///
39   /// \param[in] cpu_id
40   ///     The CPU core id where to trace. If \b None, then this traces all CPUs.
41   ///
42   /// \param[in] disabled
43   ///     If \b true, then no data is collected until \a Resume is invoked.
44   ///     Similarly, if \b false, data is collected right away until \a Pause is
45   ///     invoked.
46   ///
47   ///  \param[in] cgroup_fd
48   ///   A file descriptor in /sys/fs associated with the cgroup of the process
49   ///   to trace. If not \a llvm::None, then the trace sesion will use cgroup
50   ///   filtering.
51   ///
52   /// \return
53   ///   A \a IntelPTSingleBufferTrace instance if tracing was successful, or
54   ///   an \a llvm::Error otherwise.
55   static llvm::Expected<IntelPTSingleBufferTrace>
56   Start(const TraceIntelPTStartRequest &request,
57         llvm::Optional<lldb::tid_t> tid,
58         llvm::Optional<lldb::cpu_id_t> cpu_id = llvm::None,
59         bool disabled = false, llvm::Optional<int> cgroup_fd = llvm::None);
60 
61   /// \return
62   ///    The bytes requested by a jLLDBTraceGetBinaryData packet that was routed
63   ///    to this trace instace.
64   llvm::Expected<std::vector<uint8_t>>
65   GetBinaryData(const TraceGetBinaryDataRequest &request) const;
66 
67   /// Read the intel pt trace buffer managed by this trace instance. To ensure
68   /// that the data is up-to-date and is not corrupted by read-write race
69   /// conditions, the underlying perf_event is paused during read, and later
70   /// it's returned to its initial state.
71   ///
72   /// \return
73   ///     A vector with the requested binary data.
74   llvm::Expected<std::vector<uint8_t>> GetIptTrace();
75 
76   /// \return
77   ///     The total the size in bytes used by the intel pt trace buffer managed
78   ///     by this trace instance.
79   size_t GetIptTraceSize() const;
80 
81   /// Resume the collection of this trace.
82   ///
83   /// \return
84   ///     An error if the trace couldn't be resumed. If the trace is already
85   ///     running, this returns \a Error::success().
86   llvm::Error Resume();
87 
88   /// Pause the collection of this trace.
89   ///
90   /// \return
91   ///     An error if the trace couldn't be paused. If the trace is already
92   ///     paused, this returns \a Error::success().
93   llvm::Error Pause();
94 
95   /// \return
96   ///     The underlying PerfEvent for this trace.
97   const PerfEvent &GetPerfEvent() const;
98 
99 private:
100   /// Construct new \a IntelPTSingleBufferThreadTrace. Users are supposed to
101   /// create instances of this class via the \a Start() method and not invoke
102   /// this one directly.
103   ///
104   /// \param[in] perf_event
105   ///   perf event configured for IntelPT.
106   ///
107   /// \param[in] collection_state
108   ///   The initial collection state for the provided perf_event.
IntelPTSingleBufferTrace(PerfEvent && perf_event)109   IntelPTSingleBufferTrace(PerfEvent &&perf_event)
110       : m_perf_event(std::move(perf_event)) {}
111 
112   /// perf event configured for IntelPT.
113   PerfEvent m_perf_event;
114 };
115 
116 } // namespace process_linux
117 } // namespace lldb_private
118 
119 #endif // liblldb_IntelPTSingleBufferTrace_H_
120