LLDB  mainline
Perf.h
Go to the documentation of this file.
1 //===-- Perf.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 /// \file
9 /// This file contains a thin wrapper of the perf_event_open API
10 /// and classes to handle the destruction of file descriptors
11 /// and mmap pointers.
12 ///
13 //===----------------------------------------------------------------------===//
14 
15 #ifndef LLDB_SOURCE_PLUGINS_PROCESS_LINUX_PERF_H
16 #define LLDB_SOURCE_PLUGINS_PROCESS_LINUX_PERF_H
17 
19 #include "lldb/lldb-types.h"
20 #include "llvm/Support/Error.h"
21 #include <chrono>
22 #include <cstdint>
23 #include <linux/perf_event.h>
24 
25 namespace lldb_private {
26 namespace process_linux {
27 namespace resource_handle {
28 
29 /// Custom deleter for the pointer returned by \a mmap.
30 ///
31 /// This functor type is provided to \a unique_ptr to properly
32 /// unmap the region at destruction time.
33 class MmapDeleter {
34 public:
35  /// Construct new \a MmapDeleter.
36  ///
37  /// \param[in] bytes
38  /// Size of the mmap'ed region in bytes.
39  MmapDeleter(size_t bytes = 0) : m_bytes(bytes) {}
40 
41  /// Unmap the mmap'ed region.
42  ///
43  /// If \a m_bytes==0 or \a ptr==nullptr, nothing is unmmapped.
44  ///
45  /// \param[in] ptr
46  /// pointer to the region to be unmmapped.
47  void operator()(void *ptr);
48 
49 private:
50  /// Size of the mmap'ed region, in bytes, to be unmapped.
51  size_t m_bytes;
52 };
53 
54 /// Custom deleter for a file descriptor.
55 ///
56 /// This functor type is provided to \a unique_ptr to properly release
57 /// the resources associated with the file descriptor at destruction time.
59 public:
60  /// Close and free the memory associated with the file descriptor pointer.
61  ///
62  /// Effectively a no-op if \a ptr==nullptr or \a*ptr==-1.
63  ///
64  /// \param[in] ptr
65  /// Pointer to the file descriptor.
66  void operator()(long *ptr);
67 };
68 
69 using FileDescriptorUP =
70  std::unique_ptr<long, resource_handle::FileDescriptorDeleter>;
71 using MmapUP = std::unique_ptr<void, resource_handle::MmapDeleter>;
72 
73 } // namespace resource_handle
74 
75 /// Thin wrapper of the perf_event_open API.
76 ///
77 /// Exposes the metadata page and data and aux buffers of a perf event.
78 /// Handles the management of the event's file descriptor and mmap'ed
79 /// regions.
80 class PerfEvent {
81 public:
82  /// Create a new performance monitoring event via the perf_event_open syscall.
83  ///
84  /// The parameters are directly forwarded to a perf_event_open syscall,
85  /// for additional information on the parameters visit
86  /// https://man7.org/linux/man-pages/man2/perf_event_open.2.html.
87  ///
88  /// \param[in] attr
89  /// Configuration information for the event.
90  ///
91  /// \param[in] pid
92  /// The process or thread to be monitored by the event. If \b None, then
93  /// all processes and threads are monitored.
94  ///
95  /// \param[in] cpu
96  /// The cpu to be monitored by the event. If \b None, then all cpus are
97  /// monitored.
98  ///
99  /// \param[in] group_fd
100  /// File descriptor of the group leader. If \b None, then this perf_event
101  /// doesn't belong to a preexisting group.
102  ///
103  /// \param[in] flags
104  /// Bitmask of additional configuration flags.
105  ///
106  /// \return
107  /// If the perf_event_open syscall was successful, a minimal \a PerfEvent
108  /// instance, or an \a llvm::Error otherwise.
109  static llvm::Expected<PerfEvent> Init(perf_event_attr &attr,
110  llvm::Optional<lldb::pid_t> pid,
111  llvm::Optional<lldb::cpu_id_t> cpu,
112  llvm::Optional<long> group_fd,
113  unsigned long flags);
114 
115  /// Create a new performance monitoring event via the perf_event_open syscall
116  /// with "default" values for the cpu, group_fd and flags arguments.
117  ///
118  /// Convenience method to be used when the perf event requires minimal
119  /// configuration. It handles the default values of all other arguments.
120  ///
121  /// \param[in] attr
122  /// Configuration information for the event.
123  ///
124  /// \param[in] pid
125  /// The process or thread to be monitored by the event. If \b None, then
126  /// all threads and processes are monitored.
127  static llvm::Expected<PerfEvent>
128  Init(perf_event_attr &attr, llvm::Optional<lldb::pid_t> pid,
129  llvm::Optional<lldb::cpu_id_t> core = llvm::None);
130 
131  /// Mmap the metadata page and the data and aux buffers of the perf event and
132  /// expose them through \a PerfEvent::GetMetadataPage() , \a
133  /// PerfEvent::GetDataBuffer() and \a PerfEvent::GetAuxBuffer().
134  ///
135  /// This uses mmap underneath, which means that the number of pages mmap'ed
136  /// must be less than the actual data available by the kernel. The metadata
137  /// page is always mmap'ed.
138  ///
139  /// Mmap is needed because the underlying data might be changed by the kernel
140  /// dynamically.
141  ///
142  /// \param[in] num_data_pages
143  /// Number of pages in the data buffer to mmap, must be a power of 2.
144  /// A value of 0 is useful for "dummy" events that only want to access
145  /// the metadata, \a perf_event_mmap_page, or the aux buffer.
146  ///
147  /// \param[in] num_aux_pages
148  /// Number of pages in the aux buffer to mmap, must be a power of 2.
149  /// A value of 0 effectively is a no-op and no data is mmap'ed for this
150  /// buffer.
151  ///
152  /// \param[in] data_buffer_write
153  /// Whether to mmap the data buffer with WRITE permissions. This changes
154  /// the behavior of how the kernel writes to the data buffer.
155  ///
156  /// \return
157  /// \a llvm::Error::success if the mmap operations succeeded,
158  /// or an \a llvm::Error otherwise.
159  llvm::Error MmapMetadataAndBuffers(size_t num_data_pages,
160  size_t num_aux_pages,
161  bool data_buffer_write);
162 
163  /// Get the file descriptor associated with the perf event.
164  long GetFd() const;
165 
166  /// Get the metadata page from the data section's mmap buffer.
167  ///
168  /// The metadata page is always mmap'ed, even when \a num_data_pages is 0.
169  ///
170  /// This should be called only after \a PerfEvent::MmapMetadataAndBuffers,
171  /// otherwise a failure might happen.
172  ///
173  /// \return
174  /// The data section's \a perf_event_mmap_page.
175  perf_event_mmap_page &GetMetadataPage() const;
176 
177  /// Get the data buffer from the data section's mmap buffer.
178  ///
179  /// The data buffer is the region of the data section's mmap buffer where
180  /// perf sample data is located.
181  ///
182  /// This should be called only after \a PerfEvent::MmapMetadataAndBuffers,
183  /// otherwise a failure might happen.
184  ///
185  /// \return
186  /// \a ArrayRef<uint8_t> extending \a data_size bytes from \a data_offset.
187  llvm::ArrayRef<uint8_t> GetDataBuffer() const;
188 
189  /// Get the AUX buffer.
190  ///
191  /// AUX buffer is a region for high-bandwidth data streams
192  /// such as IntelPT. This is separate from the metadata and data buffer.
193  ///
194  /// This should be called only after \a PerfEvent::MmapMetadataAndBuffers,
195  /// otherwise a failure might happen.
196  ///
197  /// \return
198  /// \a ArrayRef<uint8_t> extending \a aux_size bytes from \a aux_offset.
199  llvm::ArrayRef<uint8_t> GetAuxBuffer() const;
200 
201  /// Read the aux buffer managed by this perf event assuming it was configured
202  /// with PROT_READ permissions only, which indicates that the buffer is
203  /// automatically wrapped and overwritten by the kernel or hardware. To ensure
204  /// that the data is up-to-date and is not corrupted by read-write race
205  /// conditions, the underlying perf_event is paused during read, and later
206  /// it's returned to its initial state. The returned data will be linear, i.e.
207  /// it will fix the circular wrapping the might exist in the buffer.
208  ///
209  /// \return
210  /// A vector with the requested binary data.
211  llvm::Expected<std::vector<uint8_t>> GetReadOnlyAuxBuffer();
212 
213  /// Read the data buffer managed by this perf even assuming it was configured
214  /// with PROT_READ permissions only, which indicates that the buffer is
215  /// automatically wrapped and overwritten by the kernel or hardware. To ensure
216  /// that the data is up-to-date and is not corrupted by read-write race
217  /// conditions, the underlying perf_event is paused during read, and later
218  /// it's returned to its initial state. The returned data will be linear, i.e.
219  /// it will fix the circular wrapping the might exist int he buffer.
220  ///
221  /// \return
222  /// A vector with the requested binary data.
223  llvm::Expected<std::vector<uint8_t>> GetReadOnlyDataBuffer();
224 
225  /// Use the ioctl API to disable the perf event and all the events in its
226  /// group. This doesn't terminate the perf event.
227  ///
228  /// This is no-op if the perf event is already disabled.
229  ///
230  /// \return
231  /// An Error if the perf event couldn't be disabled.
233 
234  /// Use the ioctl API to enable the perf event and all the events in its
235  /// group.
236  ///
237  /// This is no-op if the perf event is already enabled.
238  ///
239  /// \return
240  /// An Error if the perf event couldn't be enabled.
242 
243  /// \return
244  /// The size in bytes of the section of the data buffer that has effective
245  /// data.
246  size_t GetEffectiveDataBufferSize() const;
247 
248  /// \return
249  /// \b true if and only the perf event is enabled and collecting.
250  bool IsEnabled() const;
251 
252 private:
253  /// Create new \a PerfEvent.
254  ///
255  /// \param[in] fd
256  /// File descriptor of the perf event.
257  ///
258  /// \param[in] enabled
259  /// Initial collection state configured for this perf_event.
260  PerfEvent(long fd, bool enabled)
261  : m_fd(new long(fd), resource_handle::FileDescriptorDeleter()),
262  m_enabled(enabled) {}
263 
264  /// Wrapper for \a mmap to provide custom error messages.
265  ///
266  /// The parameters are directly forwarded to a \a mmap syscall,
267  /// for information on the parameters visit
268  /// https://man7.org/linux/man-pages/man2/mmap.2.html.
269  ///
270  /// The value of \a GetFd() is passed as the \a fd argument to \a mmap.
271  llvm::Expected<resource_handle::MmapUP> DoMmap(void *addr, size_t length,
272  int prot, int flags,
273  long int offset,
274  llvm::StringRef buffer_name);
275 
276  /// Mmap the data buffer of the perf event.
277  ///
278  /// \param[in] num_data_pages
279  /// Number of pages in the data buffer to mmap, must be a power of 2.
280  /// A value of 0 is useful for "dummy" events that only want to access
281  /// the metadata, \a perf_event_mmap_page, or the aux buffer.
282  ///
283  /// \param[in] data_buffer_write
284  /// Whether to mmap the data buffer with WRITE permissions. This changes
285  /// the behavior of how the kernel writes to the data buffer.
286  llvm::Error MmapMetadataAndDataBuffer(size_t num_data_pages,
287  bool data_buffer_write);
288 
289  /// Mmap the aux buffer of the perf event.
290  ///
291  /// \param[in] num_aux_pages
292  /// Number of pages in the aux buffer to mmap, must be a power of 2.
293  /// A value of 0 effectively is a no-op and no data is mmap'ed for this
294  /// buffer.
295  llvm::Error MmapAuxBuffer(size_t num_aux_pages);
296 
297  /// The file descriptor representing the perf event.
299  /// Metadata page and data section where perf samples are stored.
301  /// AUX buffer is a separate region for high-bandwidth data streams
302  /// such as IntelPT.
304  /// The state of the underlying perf_event.
305  bool m_enabled;
306 };
307 
308 /// Create a perf event that tracks context switches on a cpu.
309 ///
310 /// \param[in] cpu_id
311 /// The core to trace.
312 ///
313 /// \param[in] parent_perf_event
314 /// An optional perf event that will be grouped with the
315 /// new perf event.
316 llvm::Expected<PerfEvent>
318  const PerfEvent *parent_perf_event = nullptr);
319 
320 /// Load \a PerfTscConversionParameters from \a perf_event_mmap_page, if
321 /// available.
322 llvm::Expected<LinuxPerfZeroTscConversion> LoadPerfTscConversionParameters();
323 
324 } // namespace process_linux
325 } // namespace lldb_private
326 
327 #endif // LLDB_SOURCE_PLUGINS_PROCESS_LINUX_PERF_H
lldb_private::process_linux::PerfEvent::GetAuxBuffer
llvm::ArrayRef< uint8_t > GetAuxBuffer() const
Get the AUX buffer.
Definition: Perf.cpp:179
lldb_private::process_linux::LoadPerfTscConversionParameters
llvm::Expected< LinuxPerfZeroTscConversion > LoadPerfTscConversionParameters()
Load PerfTscConversionParameters from perf_event_mmap_page, if available.
Definition: Perf.cpp:27
lldb_private::process_linux::PerfEvent::m_fd
resource_handle::FileDescriptorUP m_fd
The file descriptor representing the perf event.
Definition: Perf.h:298
lldb_private::process_linux::PerfEvent::IsEnabled
bool IsEnabled() const
Definition: Perf.cpp:282
lldb_private::process_linux::PerfEvent::GetEffectiveDataBufferSize
size_t GetEffectiveDataBufferSize() const
Definition: Perf.cpp:297
lldb_private::process_linux::resource_handle::MmapDeleter::MmapDeleter
MmapDeleter(size_t bytes=0)
Construct new MmapDeleter.
Definition: Perf.h:39
lldb_private::process_linux::PerfEvent::GetReadOnlyDataBuffer
llvm::Expected< std::vector< uint8_t > > GetReadOnlyDataBuffer()
Read the data buffer managed by this perf even assuming it was configured with PROT_READ permissions ...
Definition: Perf.cpp:185
lldb_private::process_linux::resource_handle::MmapDeleter
Custom deleter for the pointer returned by mmap.
Definition: Perf.h:33
lldb_private::process_linux::PerfEvent
Thin wrapper of the perf_event_open API.
Definition: Perf.h:80
lldb_private::process_linux::PerfEvent::PerfEvent
PerfEvent(long fd, bool enabled)
Create new PerfEvent.
Definition: Perf.h:260
TraceIntelPTGDBRemotePackets.h
lldb_private::process_linux::PerfEvent::EnableWithIoctl
llvm::Error EnableWithIoctl()
Use the ioctl API to enable the perf event and all the events in its group.
Definition: Perf.cpp:284
lldb_private::process_linux::PerfEvent::Init
static llvm::Expected< PerfEvent > Init(perf_event_attr &attr, llvm::Optional< lldb::pid_t > pid, llvm::Optional< lldb::cpu_id_t > cpu, llvm::Optional< long > group_fd, unsigned long flags)
Create a new performance monitoring event via the perf_event_open syscall.
lldb_private::process_linux::PerfEvent::MmapAuxBuffer
llvm::Error MmapAuxBuffer(size_t num_aux_pages)
Mmap the aux buffer of the perf event.
Definition: Perf.cpp:127
lldb_private::process_linux::PerfEvent::m_enabled
bool m_enabled
The state of the underlying perf_event.
Definition: Perf.h:305
lldb_private::process_linux::resource_handle::FileDescriptorDeleter
Custom deleter for a file descriptor.
Definition: Perf.h:58
lldb_private::process_linux::PerfEvent::MmapMetadataAndBuffers
llvm::Error MmapMetadataAndBuffers(size_t num_data_pages, size_t num_aux_pages, bool data_buffer_write)
Mmap the metadata page and the data and aux buffers of the perf event and expose them through PerfEve...
Definition: Perf.cpp:146
lldb-types.h
lldb_private::process_linux::PerfEvent::DisableWithIoctl
llvm::Error DisableWithIoctl()
Use the ioctl API to disable the perf event and all the events in its group.
Definition: Perf.cpp:269
uint32_t
lldb_private::process_linux::resource_handle::FileDescriptorDeleter::operator()
void operator()(long *ptr)
Close and free the memory associated with the file descriptor pointer.
Definition: Perf.cpp:69
lldb_private::process_linux::CreateContextSwitchTracePerfEvent
llvm::Expected< PerfEvent > CreateContextSwitchTracePerfEvent(lldb::cpu_id_t cpu_id, const PerfEvent *parent_perf_event=nullptr)
Create a perf event that tracks context switches on a cpu.
Definition: Perf.cpp:306
lldb_private::process_linux::resource_handle::MmapDeleter::operator()
void operator()(void *ptr)
Unmap the mmap'ed region.
Definition: Perf.cpp:64
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::process_linux::PerfEvent::m_aux_base
resource_handle::MmapUP m_aux_base
AUX buffer is a separate region for high-bandwidth data streams such as IntelPT.
Definition: Perf.h:303
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:30
lldb_private::process_linux::resource_handle::MmapUP
std::unique_ptr< void, resource_handle::MmapDeleter > MmapUP
Definition: Perf.h:71
lldb_private::process_linux::PerfEvent::MmapMetadataAndDataBuffer
llvm::Error MmapMetadataAndDataBuffer(size_t num_data_pages, bool data_buffer_write)
Mmap the data buffer of the perf event.
Definition: Perf.cpp:115
lldb_private::process_linux::PerfEvent::m_metadata_data_base
resource_handle::MmapUP m_metadata_data_base
Metadata page and data section where perf samples are stored.
Definition: Perf.h:300
lldb_private::process_linux::resource_handle::FileDescriptorUP
std::unique_ptr< long, resource_handle::FileDescriptorDeleter > FileDescriptorUP
Definition: Perf.h:70
lldb_private::process_linux::PerfEvent::GetReadOnlyAuxBuffer
llvm::Expected< std::vector< uint8_t > > GetReadOnlyAuxBuffer()
Read the aux buffer managed by this perf event assuming it was configured with PROT_READ permissions ...
Definition: Perf.cpp:229
lldb_private::process_linux::PerfEvent::DoMmap
llvm::Expected< resource_handle::MmapUP > DoMmap(void *addr, size_t length, int prot, int flags, long int offset, llvm::StringRef buffer_name)
Wrapper for mmap to provide custom error messages.
Definition: Perf.cpp:101
lldb_private::process_linux::PerfEvent::GetMetadataPage
perf_event_mmap_page & GetMetadataPage() const
Get the metadata page from the data section's mmap buffer.
Definition: Perf.cpp:168
lldb_private::process_linux::PerfEvent::GetFd
long GetFd() const
Get the file descriptor associated with the perf event.
Definition: Perf.cpp:166
lldb_private::process_linux::PerfEvent::GetDataBuffer
llvm::ArrayRef< uint8_t > GetDataBuffer() const
Get the data buffer from the data section's mmap buffer.
Definition: Perf.cpp:172
lldb_private::process_linux::resource_handle::MmapDeleter::m_bytes
size_t m_bytes
Size of the mmap'ed region, in bytes, to be unmapped.
Definition: Perf.h:51