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