1 //===-- IntelPTMultiCoreTrace.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_IntelPTMultiCoreTrace_H_
10 #define liblldb_IntelPTMultiCoreTrace_H_
11 
12 #include "IntelPTProcessTrace.h"
13 #include "IntelPTSingleBufferTrace.h"
14 
15 #include "lldb/Host/common/NativeProcessProtocol.h"
16 #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h"
17 #include "lldb/lldb-types.h"
18 
19 #include "llvm/Support/Error.h"
20 
21 #include <memory>
22 
23 namespace lldb_private {
24 namespace process_linux {
25 
26 class IntelPTMultiCoreTrace : public IntelPTProcessTrace {
27   using ContextSwitchTrace = PerfEvent;
28 
29 public:
30   /// Start tracing all CPU cores.
31   ///
32   /// \param[in] request
33   ///   Intel PT configuration parameters.
34   ///
35   /// \param[in] process
36   ///   The process being debugged.
37   ///
38   /// \return
39   ///   An \a IntelPTMultiCoreTrace instance if tracing was successful, or
40   ///   an \a llvm::Error otherwise.
41   static llvm::Expected<std::unique_ptr<IntelPTMultiCoreTrace>>
42   StartOnAllCores(const TraceIntelPTStartRequest &request,
43                   NativeProcessProtocol &process);
44 
45   /// Execute the provided callback on each core that is being traced.
46   ///
47   /// \param[in] callback.cpu_id
48   ///   The core id that is being traced.
49   ///
50   /// \param[in] callback.core_trace
51   ///   The single-buffer trace instance for the given core.
52   void ForEachCore(std::function<void(lldb::cpu_id_t cpu_id,
53                                       IntelPTSingleBufferTrace &core_trace)>
54                        callback);
55 
56   /// Execute the provided callback on each core that is being traced.
57   ///
58   /// \param[in] callback.cpu_id
59   ///   The core id that is being traced.
60   ///
61   /// \param[in] callback.intelpt_trace
62   ///   The single-buffer intel pt trace instance for the given core.
63   ///
64   /// \param[in] callback.context_switch_trace
65   ///   The perf event collecting context switches for the given core.
66   void ForEachCore(std::function<void(lldb::cpu_id_t cpu_id,
67                                       IntelPTSingleBufferTrace &intelpt_trace,
68                                       ContextSwitchTrace &context_switch_trace)>
69                        callback);
70 
71   void ProcessDidStop() override;
72 
73   void ProcessWillResume() override;
74 
75   TraceIntelPTGetStateResponse GetState() override;
76 
77   bool TracesThread(lldb::tid_t tid) const override;
78 
79   llvm::Error TraceStart(lldb::tid_t tid) override;
80 
81   llvm::Error TraceStop(lldb::tid_t tid) override;
82 
83   llvm::Expected<llvm::Optional<std::vector<uint8_t>>>
84   TryGetBinaryData(const TraceGetBinaryDataRequest &request) override;
85 
86 private:
87   /// This assumes that all underlying perf_events for each core are part of the
88   /// same perf event group.
89   IntelPTMultiCoreTrace(
90       llvm::DenseMap<lldb::cpu_id_t,
91                      std::pair<IntelPTSingleBufferTrace, ContextSwitchTrace>>
92           &&traces_per_core,
93       NativeProcessProtocol &process)
94       : m_traces_per_core(std::move(traces_per_core)), m_process(process) {}
95 
96   llvm::DenseMap<lldb::cpu_id_t,
97                  std::pair<IntelPTSingleBufferTrace, ContextSwitchTrace>>
98       m_traces_per_core;
99 
100   /// The target process.
101   NativeProcessProtocol &m_process;
102 };
103 
104 } // namespace process_linux
105 } // namespace lldb_private
106 
107 #endif // liblldb_IntelPTMultiCoreTrace_H_
108