13#include "llvm/Support/MemoryBuffer.h" 
   14#include "llvm/TargetParser/Host.h" 
   15#include <linux/perf_event.h> 
   17#include <sys/syscall.h> 
   26    "/sys/bus/event_source/devices/intel_pt/type";
 
   29    "/sys/bus/event_source/devices/intel_pt/caps/psb_cyc";
 
   32    "/sys/bus/event_source/devices/intel_pt/caps/psb_periods";
 
   35    "/sys/bus/event_source/devices/intel_pt/format/psb_period";
 
   38    "/sys/bus/event_source/devices/intel_pt/format/tsc";
 
   53  ErrorOr<std::unique_ptr<MemoryBuffer>> stream =
 
   54      MemoryBuffer::getFileAsStream(file);
 
   58                             "Can't open the file '%s'", file);
 
   61  StringRef text_buffer = stream.get()->getBuffer();
 
   64    const char *prefix = 
"config:";
 
   65    if (!text_buffer.starts_with(prefix))
 
   67                               "The file '%s' contents doesn't start with '%s'",
 
   69    text_buffer = text_buffer.substr(strlen(prefix));
 
   72  auto getRadix = [&]() {
 
   81    llvm_unreachable(
"Fully covered switch above!");
 
   84  auto createError = [&](
const char *expected_value_message) {
 
   86        inconvertibleErrorCode(),
 
   87        "The file '%s' has an invalid value. It should be %s.", file,
 
   88        expected_value_message);
 
   91  if (text_buffer.trim().consumeInteger(getRadix(), value) ||
 
   92      (type == 
ZeroOne && value != 0 && value != 1)) {
 
   95      return createError(
"an unsigned hexadecimal int");
 
   97      return createError(
"0 or 1");
 
  100      return createError(
"an unsigned decimal int");
 
 
  113  Expected<uint32_t> cap =
 
  116    return cap.takeError();
 
  119                             "psb_period is unsupported in the system.");
 
  124    return valid_values.takeError();
 
  126  if (valid_values.get() & (1 << psb_period))
 
  127    return Error::success();
 
  129  std::ostringstream 
error;
 
  131  error << 
"Invalid psb_period. Valid values are: 0";
 
  132  uint32_t mask = valid_values.get();
 
  134    int index = __builtin_ctz(mask);
 
  136      error << 
", " << index;
 
 
  144#ifdef PERF_ATTR_SIZE_VER5 
  145static Expected<uint64_t>
 
  146GeneratePerfEventConfigValue(
bool enable_tsc,
 
  147                             std::optional<uint64_t> psb_period) {
 
  153      config |= 1 << *offset;
 
  155      return offset.takeError();
 
  159      return std::move(
error);
 
  163      config |= *psb_period << *offset;
 
  165      return offset.takeError();
 
  176static Expected<perf_event_attr>
 
  177CreateIntelPTPerfEventConfiguration(
bool enable_tsc,
 
  178                                    std::optional<uint64_t> psb_period) {
 
  179  perf_event_attr attr;
 
  180  memset(&attr, 0, 
sizeof(attr));
 
  181  attr.size = 
sizeof(attr);
 
  182  attr.exclude_kernel = 1;
 
  184  attr.exclude_idle = 1;
 
  186  if (Expected<uint64_t> config_value =
 
  187          GeneratePerfEventConfigValue(enable_tsc, psb_period))
 
  188    attr.config = *config_value;
 
  190    return config_value.takeError();
 
  193    attr.type = *intel_pt_type;
 
  195    return intel_pt_type.takeError();
 
  231Expected<IntelPTSingleBufferTrace>
 
  233                                std::optional<lldb::tid_t> tid,
 
  234                                std::optional<cpu_id_t> cpu_id, 
bool disabled,
 
  235                                std::optional<int> cgroup_fd) {
 
  236#ifndef PERF_ATTR_SIZE_VER5 
  238                           "Intel PT Linux perf event not supported");
 
  242  LLDB_LOG(log, 
"Will start tracing thread id {0} and cpu id {1}", tid, cpu_id);
 
  247        inconvertibleErrorCode(),
 
  248        "The intel pt trace size must be a power of 2 greater than or equal to " 
  249        "4096 (2^12) bytes. It was %" PRIu64 
".",
 
  252  uint64_t page_size = getpagesize();
 
  253  uint64_t aux_buffer_numpages = 
static_cast<uint64_t
>(llvm::bit_floor(
 
  256  Expected<perf_event_attr> attr = CreateIntelPTPerfEventConfiguration(
 
  258      llvm::transformOptional(request.
psb_period, [](
int value) {
 
  259        return static_cast<uint64_t>(value);
 
  262    return attr.takeError();
 
  263  attr->disabled = disabled;
 
  265  LLDB_LOG(log, 
"Will create intel pt trace buffer of size {0}",
 
  267  unsigned long flags = 0;
 
  270    flags |= PERF_FLAG_PID_CGROUP;
 
  273  if (Expected<PerfEvent> perf_event =
 
  275    if (Error mmap_err = perf_event->MmapMetadataAndBuffers(
 
  276            0, aux_buffer_numpages,
 
  278      return std::move(mmap_err);
 
  282    return perf_event.takeError();
 
 
static llvm::raw_ostream & error(Stream &strm)
static Error CheckPsbPeriod(size_t psb_period)
const char kTSCBitOffsetFile[]
static Expected< uint32_t > ReadIntelPTConfigFile(const char *file, IntelPTConfigFileType type)
const char kPSBPeriodValidValuesFile[]
const char kPSBPeriodBitOffsetFile[]
const char kPSBPeriodCapFile[]
const char kOSEventIntelPTTypeFile[]
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
static llvm::Error createStringError(const char *format, Args &&...args)
static llvm::Expected< IntelPTSingleBufferTrace > Start(const TraceIntelPTStartRequest &request, std::optional< lldb::tid_t > tid, std::optional< lldb::cpu_id_t > cpu_id=std::nullopt, bool disabled=false, std::optional< int > cgroup_fd=std::nullopt)
Start tracing using a single Intel PT trace buffer.
PerfEvent m_perf_event
perf event configured for IntelPT.
const PerfEvent & GetPerfEvent() const
llvm::Error Resume()
Resume the collection of this trace.
IntelPTSingleBufferTrace(PerfEvent &&perf_event)
Construct new IntelPTSingleBufferThreadTrace.
llvm::Error Pause()
Pause the collection of this trace.
llvm::Expected< std::vector< uint8_t > > GetIptTrace()
Read the intel pt trace buffer managed by this trace instance.
size_t GetIptTraceSize() const
Thin wrapper of the perf_event_open API.
static llvm::Expected< PerfEvent > Init(perf_event_attr &attr, std::optional< lldb::pid_t > pid, std::optional< lldb::cpu_id_t > cpu, std::optional< long > group_fd, unsigned long flags)
Create a new performance monitoring event via the perf_event_open syscall.
llvm::Expected< uint32_t > GetIntelPTOSEventType()
Return the Linux perf event type for Intel PT.
A class that represents a running process on the host machine.
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
jLLDBTraceStart gdb-remote packet
bool enable_tsc
Whether to enable TSC.
std::optional< uint64_t > psb_period
PSB packet period.
uint64_t ipt_trace_size
Size in bytes to use for each thread's trace buffer.