LLDB  mainline
IntelPTManager.cpp
Go to the documentation of this file.
1 //===-- IntelPTManager.cpp ------------------------------------------------===//
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 #include <algorithm>
10 #include <fstream>
11 #include <sstream>
12 
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/Support/Error.h"
15 #include "llvm/Support/MathExtras.h"
16 
17 #include "IntelPTManager.h"
21 
22 #include <sys/ioctl.h>
23 #include <sys/syscall.h>
24 
25 using namespace lldb;
26 using namespace lldb_private;
27 using namespace process_linux;
28 using namespace llvm;
29 
31  "/sys/bus/event_source/devices/intel_pt/type";
32 
33 const char *kPSBPeriodCapFile =
34  "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc";
35 
37  "/sys/bus/event_source/devices/intel_pt/caps/psb_periods";
38 
39 const char *kTSCBitOffsetFile =
40  "/sys/bus/event_source/devices/intel_pt/format/tsc";
41 
43  "/sys/bus/event_source/devices/intel_pt/format/psb_period";
44 
46  Hex = 0,
47  // 0 or 1
50  // a bit index file always starts with the prefix config: following by an int,
51  // which represents the offset of the perf_event_attr.config value where to
52  // store a given configuration.
54 };
55 
56 static Expected<uint32_t> ReadIntelPTConfigFile(const char *file,
57  IntelPTConfigFileType type) {
58  ErrorOr<std::unique_ptr<MemoryBuffer>> stream =
59  MemoryBuffer::getFileAsStream(file);
60 
61  if (!stream)
62  return createStringError(inconvertibleErrorCode(),
63  "Can't open the file '%s'", file);
64 
65  uint32_t value = 0;
66  StringRef text_buffer = stream.get()->getBuffer();
67 
68  if (type == BitOffset) {
69  const char *prefix = "config:";
70  if (!text_buffer.startswith(prefix))
71  return createStringError(inconvertibleErrorCode(),
72  "The file '%s' contents doesn't start with '%s'",
73  file, prefix);
74  text_buffer = text_buffer.substr(strlen(prefix));
75  }
76 
77  auto getRadix = [&]() {
78  switch (type) {
79  case Hex:
80  return 16;
81  case ZeroOne:
82  case Decimal:
83  case BitOffset:
84  return 10;
85  }
86  };
87 
88  auto createError = [&](const char *expected_value_message) {
89  return createStringError(
90  inconvertibleErrorCode(),
91  "The file '%s' has an invalid value. It should be %s.", file,
92  expected_value_message);
93  };
94 
95  if (text_buffer.trim().consumeInteger(getRadix(), value) ||
96  (type == ZeroOne && value != 0 && value != 1)) {
97  switch (type) {
98  case Hex:
99  return createError("an unsigned hexadecimal int");
100  case ZeroOne:
101  return createError("0 or 1");
102  case Decimal:
103  case BitOffset:
104  return createError("an unsigned decimal int");
105  }
106  }
107  return value;
108 }
109 /// Return the Linux perf event type for Intel PT.
110 static Expected<uint32_t> GetOSEventType() {
113 }
114 
115 static Error CheckPsbPeriod(size_t psb_period) {
116  Expected<uint32_t> cap =
118  if (!cap)
119  return cap.takeError();
120  if (*cap == 0)
121  return createStringError(inconvertibleErrorCode(),
122  "psb_period is unsupported in the system.");
123 
124  Expected<uint32_t> valid_values = ReadIntelPTConfigFile(
126  if (!valid_values)
127  return valid_values.takeError();
128 
129  if (valid_values.get() & (1 << psb_period))
130  return Error::success();
131 
132  std::ostringstream error;
133  // 0 is always a valid value
134  error << "Invalid psb_period. Valid values are: 0";
135  uint32_t mask = valid_values.get();
136  while (mask) {
137  int index = __builtin_ctz(mask);
138  if (index > 0)
139  error << ", " << index;
140  // clear the lowest bit
141  mask &= mask - 1;
142  }
143  error << ".";
144  return createStringError(inconvertibleErrorCode(), error.str().c_str());
145 }
146 
147 size_t IntelPTThreadTrace::GetTraceBufferSize() const {
148 #ifndef PERF_ATTR_SIZE_VER5
149  llvm_unreachable("Intel PT Linux perf event not supported");
150 #else
151  return m_mmap_meta->aux_size;
152 #endif
153 }
154 
155 static Expected<uint64_t>
156 GeneratePerfEventConfigValue(bool enable_tsc, Optional<size_t> psb_period) {
157  uint64_t config = 0;
158  // tsc is always supported
159  if (enable_tsc) {
160  if (Expected<uint32_t> offset = ReadIntelPTConfigFile(
162  config |= 1 << *offset;
163  else
164  return offset.takeError();
165  }
166  if (psb_period) {
167  if (Error error = CheckPsbPeriod(*psb_period))
168  return std::move(error);
169 
170  if (Expected<uint32_t> offset = ReadIntelPTConfigFile(
172  config |= *psb_period << *offset;
173  else
174  return offset.takeError();
175  }
176  return config;
177 }
178 
179 Error IntelPTThreadTrace::StartTrace(lldb::pid_t pid, lldb::tid_t tid,
180  uint64_t buffer_size, bool enable_tsc,
181  Optional<size_t> psb_period) {
182 #ifndef PERF_ATTR_SIZE_VER5
183  llvm_unreachable("Intel PT Linux perf event not supported");
184 #else
186 
187  m_tid = tid;
188  LLDB_LOG(log, "called thread id {0}", tid);
189  uint64_t page_size = getpagesize();
190 
191  if (__builtin_popcount(buffer_size) != 1 || buffer_size < 4096) {
192  return createStringError(
193  inconvertibleErrorCode(),
194  "The trace buffer size must be a power of 2 greater than or equal to "
195  "4096 (2^12) bytes. It was %" PRIu64 ".",
196  buffer_size);
197  }
198  uint64_t numpages = static_cast<uint64_t>(
199  llvm::PowerOf2Floor((buffer_size + page_size - 1) / page_size));
200  numpages = std::max<uint64_t>(1, numpages);
201  buffer_size = page_size * numpages;
202 
203  perf_event_attr attr;
204  memset(&attr, 0, sizeof(attr));
205  attr.size = sizeof(attr);
206  attr.exclude_kernel = 1;
207  attr.sample_type = PERF_SAMPLE_TIME;
208  attr.sample_id_all = 1;
209  attr.exclude_hv = 1;
210  attr.exclude_idle = 1;
211  attr.mmap = 1;
212 
213  if (Expected<uint64_t> config_value =
214  GeneratePerfEventConfigValue(enable_tsc, psb_period)) {
215  attr.config = *config_value;
216  LLDB_LOG(log, "intel pt config {0}", attr.config);
217  } else {
218  return config_value.takeError();
219  }
220 
221  if (Expected<uint32_t> intel_pt_type = GetOSEventType()) {
222  attr.type = *intel_pt_type;
223  LLDB_LOG(log, "intel pt type {0}", attr.type);
224  } else {
225  return intel_pt_type.takeError();
226  }
227 
228  LLDB_LOG(log, "buffer size {0} ", buffer_size);
229 
230  errno = 0;
231  auto fd =
232  syscall(SYS_perf_event_open, &attr, static_cast<::tid_t>(tid), -1, -1, 0);
233  if (fd == -1) {
234  LLDB_LOG(log, "syscall error {0}", errno);
235  return createStringError(inconvertibleErrorCode(),
236  "perf event syscall failed");
237  }
238 
239  m_fd = std::unique_ptr<int, file_close>(new int(fd), file_close());
240 
241  errno = 0;
242  auto base =
243  mmap(nullptr, (buffer_size + page_size), PROT_WRITE, MAP_SHARED, fd, 0);
244 
245  if (base == MAP_FAILED) {
246  LLDB_LOG(log, "mmap base error {0}", errno);
247  return createStringError(inconvertibleErrorCode(),
248  "Meta buffer allocation failed");
249  }
250 
251  m_mmap_meta = std::unique_ptr<perf_event_mmap_page, munmap_delete>(
252  reinterpret_cast<perf_event_mmap_page *>(base),
253  munmap_delete(buffer_size + page_size));
254 
255  m_mmap_meta->aux_offset = m_mmap_meta->data_offset + m_mmap_meta->data_size;
256  m_mmap_meta->aux_size = buffer_size;
257 
258  errno = 0;
259  auto mmap_aux = mmap(nullptr, buffer_size, PROT_READ, MAP_SHARED, fd,
260  static_cast<long int>(m_mmap_meta->aux_offset));
261 
262  if (mmap_aux == MAP_FAILED) {
263  LLDB_LOG(log, "second mmap done {0}", errno);
264  return createStringError(inconvertibleErrorCode(),
265  "Trace buffer allocation failed");
266  }
267  m_mmap_aux = std::unique_ptr<uint8_t, munmap_delete>(
268  reinterpret_cast<uint8_t *>(mmap_aux), munmap_delete(buffer_size));
269  return Error::success();
270 #endif
271 }
272 
273 llvm::MutableArrayRef<uint8_t> IntelPTThreadTrace::GetDataBuffer() const {
274 #ifndef PERF_ATTR_SIZE_VER5
275  llvm_unreachable("Intel PT Linux perf event not supported");
276 #else
277  return MutableArrayRef<uint8_t>(
278  (reinterpret_cast<uint8_t *>(m_mmap_meta.get()) +
279  m_mmap_meta->data_offset),
280  m_mmap_meta->data_size);
281 #endif
282 }
283 
284 llvm::MutableArrayRef<uint8_t> IntelPTThreadTrace::GetAuxBuffer() const {
285 #ifndef PERF_ATTR_SIZE_VER5
286  llvm_unreachable("Intel PT Linux perf event not supported");
287 #else
288  return MutableArrayRef<uint8_t>(m_mmap_aux.get(), m_mmap_meta->aux_size);
289 #endif
290 }
291 
292 Expected<ArrayRef<uint8_t>> IntelPTThreadTrace::GetCPUInfo() {
293  static llvm::Optional<std::vector<uint8_t>> cpu_info;
294  if (!cpu_info) {
295  auto buffer_or_error = getProcFile("cpuinfo");
296  if (!buffer_or_error)
297  return Status(buffer_or_error.getError()).ToError();
298  MemoryBuffer &buffer = **buffer_or_error;
299  cpu_info = std::vector<uint8_t>(
300  reinterpret_cast<const uint8_t *>(buffer.getBufferStart()),
301  reinterpret_cast<const uint8_t *>(buffer.getBufferEnd()));
302  }
303  return *cpu_info;
304 }
305 
306 llvm::Expected<IntelPTThreadTraceUP>
307 IntelPTThreadTrace::Create(lldb::pid_t pid, lldb::tid_t tid, size_t buffer_size,
308  bool enable_tsc, Optional<size_t> psb_period) {
309  IntelPTThreadTraceUP thread_trace_up(new IntelPTThreadTrace());
310 
311  if (llvm::Error err = thread_trace_up->StartTrace(pid, tid, buffer_size,
312  enable_tsc, psb_period))
313  return std::move(err);
314 
315  return std::move(thread_trace_up);
316 }
317 
318 Expected<std::vector<uint8_t>>
319 IntelPTThreadTrace::GetIntelPTBuffer(size_t offset, size_t size) const {
320  std::vector<uint8_t> data(size, 0);
321  MutableArrayRef<uint8_t> buffer_ref(data);
322  Status error = ReadPerfTraceAux(buffer_ref, 0);
323  if (error.Fail())
324  return error.ToError();
325  return data;
326 }
327 
328 Status
329 IntelPTThreadTrace::ReadPerfTraceAux(llvm::MutableArrayRef<uint8_t> &buffer,
330  size_t offset) const {
331 #ifndef PERF_ATTR_SIZE_VER5
332  llvm_unreachable("perf event not supported");
333 #else
334  // Disable the perf event to force a flush out of the CPU's internal buffer.
335  // Besides, we can guarantee that the CPU won't override any data as we are
336  // reading the buffer.
337  //
338  // The Intel documentation says:
339  //
340  // Packets are first buffered internally and then written out asynchronously.
341  // To collect packet output for postprocessing, a collector needs first to
342  // ensure that all packet data has been flushed from internal buffers.
343  // Software can ensure this by stopping packet generation by clearing
344  // IA32_RTIT_CTL.TraceEn (see “Disabling Packet Generation” in
345  // Section 35.2.7.2).
346  //
347  // This is achieved by the PERF_EVENT_IOC_DISABLE ioctl request, as mentioned
348  // in the man page of perf_event_open.
349  ioctl(*m_fd, PERF_EVENT_IOC_DISABLE);
350 
352  Status error;
353  uint64_t head = m_mmap_meta->aux_head;
354 
355  LLDB_LOG(log, "Aux size -{0} , Head - {1}", m_mmap_meta->aux_size, head);
356 
357  /**
358  * When configured as ring buffer, the aux buffer keeps wrapping around
359  * the buffer and its not possible to detect how many times the buffer
360  * wrapped. Initially the buffer is filled with zeros,as shown below
361  * so in order to get complete buffer we first copy firstpartsize, followed
362  * by any left over part from beginning to aux_head
363  *
364  * aux_offset [d,d,d,d,d,d,d,d,0,0,0,0,0,0,0,0,0,0,0] aux_size
365  * aux_head->||<- firstpartsize ->|
366  *
367  * */
368 
369  ReadCyclicBuffer(buffer, GetAuxBuffer(), static_cast<size_t>(head), offset);
370  LLDB_LOG(log, "ReadCyclic BUffer Done");
371 
372  // Reenable tracing now we have read the buffer
373  ioctl(*m_fd, PERF_EVENT_IOC_ENABLE);
374  return error;
375 #endif
376 }
377 
378 Status
379 IntelPTThreadTrace::ReadPerfTraceData(llvm::MutableArrayRef<uint8_t> &buffer,
380  size_t offset) const {
381 #ifndef PERF_ATTR_SIZE_VER5
382  llvm_unreachable("perf event not supported");
383 #else
385  uint64_t bytes_remaining = buffer.size();
386  Status error;
387 
388  uint64_t head = m_mmap_meta->data_head;
389 
390  /*
391  * The data buffer and aux buffer have different implementations
392  * with respect to their definition of head pointer. In the case
393  * of Aux data buffer the head always wraps around the aux buffer
394  * and we don't need to care about it, whereas the data_head keeps
395  * increasing and needs to be wrapped by modulus operator
396  */
397 
398  LLDB_LOG(log, "bytes_remaining - {0}", bytes_remaining);
399 
400  auto data_buffer = GetDataBuffer();
401 
402  if (head > data_buffer.size()) {
403  head = head % data_buffer.size();
404  LLDB_LOG(log, "Data size -{0} Head - {1}", m_mmap_meta->data_size, head);
405 
406  ReadCyclicBuffer(buffer, data_buffer, static_cast<size_t>(head), offset);
407  bytes_remaining -= buffer.size();
408  } else {
409  LLDB_LOG(log, "Head - {0}", head);
410  if (offset >= head) {
411  LLDB_LOG(log, "Invalid Offset ");
412  error.SetErrorString("invalid offset");
413  buffer = buffer.slice(buffer.size());
414  return error;
415  }
416 
417  auto data = data_buffer.slice(offset, (head - offset));
418  auto remaining = std::copy(data.begin(), data.end(), buffer.begin());
419  bytes_remaining -= (remaining - buffer.begin());
420  }
421  buffer = buffer.drop_back(bytes_remaining);
422  return error;
423 #endif
424 }
425 
426 void IntelPTThreadTrace::ReadCyclicBuffer(llvm::MutableArrayRef<uint8_t> &dst,
427  llvm::MutableArrayRef<uint8_t> src,
428  size_t src_cyc_index, size_t offset) {
429 
431 
432  if (dst.empty() || src.empty()) {
433  dst = dst.drop_back(dst.size());
434  return;
435  }
436 
437  if (dst.data() == nullptr || src.data() == nullptr) {
438  dst = dst.drop_back(dst.size());
439  return;
440  }
441 
442  if (src_cyc_index > src.size()) {
443  dst = dst.drop_back(dst.size());
444  return;
445  }
446 
447  if (offset >= src.size()) {
448  LLDB_LOG(log, "Too Big offset ");
449  dst = dst.drop_back(dst.size());
450  return;
451  }
452 
453  llvm::SmallVector<MutableArrayRef<uint8_t>, 2> parts = {
454  src.slice(src_cyc_index), src.take_front(src_cyc_index)};
455 
456  if (offset > parts[0].size()) {
457  parts[1] = parts[1].slice(offset - parts[0].size());
458  parts[0] = parts[0].drop_back(parts[0].size());
459  } else if (offset == parts[0].size()) {
460  parts[0] = parts[0].drop_back(parts[0].size());
461  } else {
462  parts[0] = parts[0].slice(offset);
463  }
464  auto next = dst.begin();
465  auto bytes_left = dst.size();
466  for (auto part : parts) {
467  size_t chunk_size = std::min(part.size(), bytes_left);
468  next = std::copy_n(part.begin(), chunk_size, next);
469  bytes_left -= chunk_size;
470  }
471  dst = dst.drop_back(bytes_left);
472 }
473 
474 TraceThreadState IntelPTThreadTrace::GetState() const {
475  return {static_cast<int64_t>(m_tid),
476  {TraceBinaryData{"threadTraceBuffer",
477  static_cast<int64_t>(GetTraceBufferSize())}}};
478 }
479 
480 /// IntelPTThreadTraceCollection
481 
482 bool IntelPTThreadTraceCollection::TracesThread(lldb::tid_t tid) const {
483  return m_thread_traces.count(tid);
484 }
485 
486 Error IntelPTThreadTraceCollection::TraceStop(lldb::tid_t tid) {
487  auto it = m_thread_traces.find(tid);
488  if (it == m_thread_traces.end())
489  return createStringError(inconvertibleErrorCode(),
490  "Thread %" PRIu64 " not currently traced", tid);
491  m_total_buffer_size -= it->second->GetTraceBufferSize();
492  m_thread_traces.erase(tid);
493  return Error::success();
494 }
495 
496 Error IntelPTThreadTraceCollection::TraceStart(
497  lldb::tid_t tid, const TraceIntelPTStartRequest &request) {
498  if (TracesThread(tid))
499  return createStringError(inconvertibleErrorCode(),
500  "Thread %" PRIu64 " already traced", tid);
501 
502  Expected<IntelPTThreadTraceUP> trace_up = IntelPTThreadTrace::Create(
503  m_pid, tid, request.threadBufferSize, request.enableTsc,
504  request.psbPeriod.map([](int64_t period) { return (size_t)period; }));
505  if (!trace_up)
506  return trace_up.takeError();
507 
508  m_total_buffer_size += (*trace_up)->GetTraceBufferSize();
509  m_thread_traces.try_emplace(tid, std::move(*trace_up));
510  return Error::success();
511 }
512 
513 size_t IntelPTThreadTraceCollection::GetTotalBufferSize() const {
514  return m_total_buffer_size;
515 }
516 
517 std::vector<TraceThreadState>
518 IntelPTThreadTraceCollection::GetThreadStates() const {
519  std::vector<TraceThreadState> states;
520  for (const auto &it : m_thread_traces)
521  states.push_back(it.second->GetState());
522  return states;
523 }
524 
525 Expected<const IntelPTThreadTrace &>
526 IntelPTThreadTraceCollection::GetTracedThread(lldb::tid_t tid) const {
527  auto it = m_thread_traces.find(tid);
528  if (it == m_thread_traces.end())
529  return createStringError(inconvertibleErrorCode(),
530  "Thread %" PRIu64 " not currently traced", tid);
531  return *it->second.get();
532 }
533 
534 void IntelPTThreadTraceCollection::Clear() {
535  m_thread_traces.clear();
536  m_total_buffer_size = 0;
537 }
538 
539 /// IntelPTProcessTrace
540 
541 bool IntelPTProcessTrace::TracesThread(lldb::tid_t tid) const {
542  return m_thread_traces.TracesThread(tid);
543 }
544 
545 Error IntelPTProcessTrace::TraceStop(lldb::tid_t tid) {
546  return m_thread_traces.TraceStop(tid);
547 }
548 
549 Error IntelPTProcessTrace::TraceStart(lldb::tid_t tid) {
550  if (m_thread_traces.GetTotalBufferSize() + m_tracing_params.threadBufferSize >
551  static_cast<size_t>(*m_tracing_params.processBufferSizeLimit))
552  return createStringError(
553  inconvertibleErrorCode(),
554  "Thread %" PRIu64 " can't be traced as the process trace size limit "
555  "has been reached. Consider retracing with a higher "
556  "limit.",
557  tid);
558 
559  return m_thread_traces.TraceStart(tid, m_tracing_params);
560 }
561 
563 IntelPTProcessTrace::GetThreadTraces() const {
564  return m_thread_traces;
565 }
566 
567 /// IntelPTManager
568 
569 Error IntelPTManager::TraceStop(lldb::tid_t tid) {
570  if (IsProcessTracingEnabled() && m_process_trace->TracesThread(tid))
571  return m_process_trace->TraceStop(tid);
572  return m_thread_traces.TraceStop(tid);
573 }
574 
575 Error IntelPTManager::TraceStop(const TraceStopRequest &request) {
576  if (request.IsProcessTracing()) {
577  Clear();
578  return Error::success();
579  } else {
580  Error error = Error::success();
581  for (int64_t tid : *request.tids)
582  error = joinErrors(std::move(error),
583  TraceStop(static_cast<lldb::tid_t>(tid)));
584  return error;
585  }
586 }
587 
588 Error IntelPTManager::TraceStart(
589  const TraceIntelPTStartRequest &request,
590  const std::vector<lldb::tid_t> &process_threads) {
591  if (request.IsProcessTracing()) {
592  if (IsProcessTracingEnabled()) {
593  return createStringError(
594  inconvertibleErrorCode(),
595  "Process currently traced. Stop process tracing first");
596  }
597  m_process_trace = IntelPTProcessTrace(m_pid, request);
598 
599  Error error = Error::success();
600  for (lldb::tid_t tid : process_threads)
601  error = joinErrors(std::move(error), m_process_trace->TraceStart(tid));
602  return error;
603  } else {
604  Error error = Error::success();
605  for (int64_t tid : *request.tids)
606  error = joinErrors(std::move(error),
607  m_thread_traces.TraceStart(tid, request));
608  return error;
609  }
610 }
611 
612 Error IntelPTManager::OnThreadCreated(lldb::tid_t tid) {
613  if (!IsProcessTracingEnabled())
614  return Error::success();
615  return m_process_trace->TraceStart(tid);
616 }
617 
618 Error IntelPTManager::OnThreadDestroyed(lldb::tid_t tid) {
619  if (IsProcessTracingEnabled() && m_process_trace->TracesThread(tid))
620  return m_process_trace->TraceStop(tid);
621  else if (m_thread_traces.TracesThread(tid))
622  return m_thread_traces.TraceStop(tid);
623  return Error::success();
624 }
625 
626 Expected<json::Value> IntelPTManager::GetState() const {
627  Expected<ArrayRef<uint8_t>> cpu_info = IntelPTThreadTrace::GetCPUInfo();
628  if (!cpu_info)
629  return cpu_info.takeError();
630 
631  TraceGetStateResponse state;
632  state.processBinaryData.push_back(
633  {"cpuInfo", static_cast<int64_t>(cpu_info->size())});
634 
635  std::vector<TraceThreadState> thread_states =
636  m_thread_traces.GetThreadStates();
637  state.tracedThreads.insert(state.tracedThreads.end(), thread_states.begin(),
638  thread_states.end());
639 
640  if (IsProcessTracingEnabled()) {
641  thread_states = m_process_trace->GetThreadTraces().GetThreadStates();
642  state.tracedThreads.insert(state.tracedThreads.end(), thread_states.begin(),
643  thread_states.end());
644  }
645  return toJSON(state);
646 }
647 
648 Expected<const IntelPTThreadTrace &>
649 IntelPTManager::GetTracedThread(lldb::tid_t tid) const {
650  if (IsProcessTracingEnabled() && m_process_trace->TracesThread(tid))
651  return m_process_trace->GetThreadTraces().GetTracedThread(tid);
652  return m_thread_traces.GetTracedThread(tid);
653 }
654 
655 Expected<std::vector<uint8_t>>
656 IntelPTManager::GetBinaryData(const TraceGetBinaryDataRequest &request) const {
657  if (request.kind == "threadTraceBuffer") {
658  if (Expected<const IntelPTThreadTrace &> trace =
659  GetTracedThread(*request.tid))
660  return trace->GetIntelPTBuffer(request.offset, request.size);
661  else
662  return trace.takeError();
663  } else if (request.kind == "cpuInfo") {
664  return IntelPTThreadTrace::GetCPUInfo();
665  }
666  return createStringError(inconvertibleErrorCode(),
667  "Unsuported trace binary data kind: %s",
668  request.kind.c_str());
669 }
670 
671 void IntelPTManager::ClearProcessTracing() { m_process_trace = None; }
672 
673 bool IntelPTManager::IsSupported() {
674  Expected<uint32_t> intel_pt_type = GetOSEventType();
675  if (!intel_pt_type) {
676  llvm::consumeError(intel_pt_type.takeError());
677  return false;
678  }
679  return true;
680 }
681 
682 bool IntelPTManager::IsProcessTracingEnabled() const {
683  return (bool)m_process_trace;
684 }
685 
686 void IntelPTManager::Clear() {
687  ClearProcessTracing();
688  m_thread_traces.Clear();
689 }
lldb_private::toJSON
llvm::json::Value toJSON(const TraceSupportedResponse &packet)
Definition: TraceGDBRemotePackets.cpp:24
lldb_private::TraceStopRequest::IsProcessTracing
bool IsProcessTracing() const
Definition: TraceGDBRemotePackets.cpp:54
lldb_private::TraceGetBinaryDataRequest::kind
std::string kind
Identifier for the data.
Definition: TraceGDBRemotePackets.h:136
llvm
Definition: Debugger.h:49
lldb_private::TraceGetBinaryDataRequest::size
int64_t size
Number of bytes to read.
Definition: TraceGDBRemotePackets.h:142
lldb_private::TraceGetBinaryDataRequest
jLLDBTraceGetBinaryData gdb-remote packet
Definition: TraceGDBRemotePackets.h:132
lldb_private::TraceGetStateResponse
Definition: TraceGDBRemotePackets.h:119
Hex
@ Hex
Definition: IntelPTManager.cpp:46
ReadIntelPTConfigFile
static Expected< uint32_t > ReadIntelPTConfigFile(const char *file, IntelPTConfigFileType type)
Definition: IntelPTManager.cpp:56
lldb_private::TraceGetStateResponse::processBinaryData
std::vector< TraceBinaryData > processBinaryData
Definition: TraceGDBRemotePackets.h:121
lldb_private::TraceIntelPTStartRequest::enableTsc
bool enableTsc
Whether to enable TSC.
Definition: TraceIntelPTGDBRemotePackets.h:24
kPSBPeriodValidValuesFile
const char * kPSBPeriodValidValuesFile
Definition: IntelPTManager.cpp:36
PROT_WRITE
#define PROT_WRITE
Definition: InferiorCallPOSIX.cpp:30
ZeroOne
@ ZeroOne
Definition: IntelPTManager.cpp:48
lldb_private::TraceGetBinaryDataRequest::tid
llvm::Optional< int64_t > tid
Optional tid if the data is related to a thread.
Definition: TraceGDBRemotePackets.h:138
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb_private::TraceStartRequest::IsProcessTracing
bool IsProcessTracing() const
jLLDBTraceStart
Definition: TraceGDBRemotePackets.cpp:32
lldb_private::process_linux::IntelPTThreadTraceCollection
Manages a list of thread traces.
Definition: IntelPTManager.h:157
lldb_private::process_linux::IntelPTProcessTrace
Manages a "process trace" instance.
Definition: IntelPTManager.h:186
GeneratePerfEventConfigValue
static Expected< uint64_t > GeneratePerfEventConfigValue(bool enable_tsc, Optional< size_t > psb_period)
Definition: IntelPTManager.cpp:156
lldb_private::TraceIntelPTStartRequest::psbPeriod
llvm::Optional< int64_t > psbPeriod
PSB packet period.
Definition: TraceIntelPTGDBRemotePackets.h:27
StreamString.h
CheckPsbPeriod
static Error CheckPsbPeriod(size_t psb_period)
Definition: IntelPTManager.cpp:115
lldb_private::TraceGetStateResponse::tracedThreads
std::vector< TraceThreadState > tracedThreads
Definition: TraceGDBRemotePackets.h:120
lldb_private::TraceIntelPTStartRequest
jLLDBTraceStart gdb-remote packet
Definition: TraceIntelPTGDBRemotePackets.h:19
lldb_private::GetLogIfAllCategoriesSet
Log * GetLogIfAllCategoriesSet(uint32_t mask)
Definition: Logging.cpp:58
ProcessPOSIXLog.h
lldb_private::TraceGetBinaryDataRequest::offset
int64_t offset
Offset in bytes from where to start reading the data.
Definition: TraceGDBRemotePackets.h:140
lldb_private::process_linux::IntelPTThreadTrace::file_close
Definition: IntelPTManager.h:46
lldb_private::TraceIntelPTStartRequest::threadBufferSize
int64_t threadBufferSize
Size in bytes to use for each thread's trace buffer.
Definition: TraceIntelPTGDBRemotePackets.h:21
PROT_READ
#define PROT_READ
Definition: InferiorCallPOSIX.cpp:29
kOSEventIntelPTTypeFile
const char * kOSEventIntelPTTypeFile
Definition: IntelPTManager.cpp:30
lldb_private::getProcFile
llvm::ErrorOr< std::unique_ptr< llvm::MemoryBuffer > > getProcFile(::pid_t pid, ::pid_t tid, const llvm::Twine &file)
Definition: Support.cpp:14
Decimal
@ Decimal
Definition: IntelPTManager.cpp:49
lldb_private::process_linux::IntelPTThreadTrace
Definition: IntelPTManager.h:33
kPSBPeriodCapFile
const char * kPSBPeriodCapFile
Definition: IntelPTManager.cpp:33
lldb_private::TraceStopRequest
jLLDBTraceStop gdb-remote packet
Definition: TraceGDBRemotePackets.h:62
IntelPTManager.h
lldb_private::Status
Definition: Status.h:44
uint32_t
lldb::pid_t
uint64_t pid_t
Definition: lldb-types.h:85
Support.h
GetOSEventType
static Expected< uint32_t > GetOSEventType()
Return the Linux perf event type for Intel PT.
Definition: IntelPTManager.cpp:110
kTSCBitOffsetFile
const char * kTSCBitOffsetFile
Definition: IntelPTManager.cpp:39
IntelPTConfigFileType
IntelPTConfigFileType
Definition: IntelPTManager.cpp:45
POSIX_LOG_PTRACE
#define POSIX_LOG_PTRACE
Definition: ProcessPOSIXLog.h:19
lldb_private::TraceStopRequest::tids
llvm::Optional< std::vector< int64_t > > tids
If llvm::None, then this stops tracing the whole process.
Definition: TraceGDBRemotePackets.h:75
LLDB_LOG
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition: Log.h:242
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::process_linux::IntelPTThreadTraceCollection::TraceStop
llvm::Error TraceStop(lldb::tid_t tid)
Definition: IntelPTManager.cpp:486
lldb_private::TraceBinaryData
Definition: TraceGDBRemotePackets.h:96
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:29
lldb_private::TraceStartRequest::tids
llvm::Optional< std::vector< int64_t > > tids
If llvm::None, then this starts tracing the whole process.
Definition: TraceGDBRemotePackets.h:47
lldb_private::process_linux::IntelPTThreadTraceUP
std::unique_ptr< IntelPTThreadTrace > IntelPTThreadTraceUP
Definition: IntelPTManager.h:30
kPSBPeriodBitOffsetFile
const char * kPSBPeriodBitOffsetFile
Definition: IntelPTManager.cpp:42
lldb_private::Status::ToError
llvm::Error ToError() const
Definition: Status.cpp:90
lldb_private::Log
Definition: Log.h:49
lldb_private::process_linux::IntelPTThreadTrace::munmap_delete
Definition: IntelPTManager.h:35
lldb
Definition: SBAddress.h:15
BitOffset
@ BitOffset
Definition: IntelPTManager.cpp:53
lldb::tid_t
uint64_t tid_t
Definition: lldb-types.h:86
lldb_private::TraceThreadState
Definition: TraceGDBRemotePackets.h:108