brintos

brintos / llvm-project-archived public Read only

0
0
Text · 6.7 KiB · ea28c32 Raw
213 lines · cpp
1//===-- CommandObjectTraceStartIntelPT.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-exception6//7//===----------------------------------------------------------------------===//8 9#include "CommandObjectTraceStartIntelPT.h"10#include "TraceIntelPT.h"11#include "TraceIntelPTConstants.h"12#include "lldb/Host/OptionParser.h"13#include "lldb/Interpreter/CommandOptionArgumentTable.h"14#include "lldb/Target/Process.h"15#include "lldb/Target/Trace.h"16#include <optional>17 18using namespace lldb;19using namespace lldb_private;20using namespace lldb_private::trace_intel_pt;21using namespace llvm;22 23// CommandObjectThreadTraceStartIntelPT24 25#define LLDB_OPTIONS_thread_trace_start_intel_pt26#include "TraceIntelPTCommandOptions.inc"27 28Status CommandObjectThreadTraceStartIntelPT::CommandOptions::SetOptionValue(29    uint32_t option_idx, llvm::StringRef option_arg,30    ExecutionContext *execution_context) {31  Status error;32  const int short_option = m_getopt_table[option_idx].val;33 34  switch (short_option) {35  case 's': {36    if (std::optional<uint64_t> bytes =37            ParsingUtils::ParseUserFriendlySizeExpression(option_arg))38      m_ipt_trace_size = *bytes;39    else40      error = Status::FromErrorStringWithFormat(41          "invalid bytes expression for '%s'", option_arg.str().c_str());42    break;43  }44  case 't': {45    m_enable_tsc = true;46    break;47  }48  case 'p': {49    int64_t psb_period;50    if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||51        psb_period < 0)52      error = Status::FromErrorStringWithFormat(53          "invalid integer value for option '%s'", option_arg.str().c_str());54    else55      m_psb_period = psb_period;56    break;57  }58  default:59    llvm_unreachable("Unimplemented option");60  }61  return error;62}63 64void CommandObjectThreadTraceStartIntelPT::CommandOptions::65    OptionParsingStarting(ExecutionContext *execution_context) {66  m_ipt_trace_size = kDefaultIptTraceSize;67  m_enable_tsc = kDefaultEnableTscValue;68  m_psb_period = kDefaultPsbPeriod;69}70 71llvm::ArrayRef<OptionDefinition>72CommandObjectThreadTraceStartIntelPT::CommandOptions::GetDefinitions() {73  return llvm::ArrayRef(g_thread_trace_start_intel_pt_options);74}75 76bool CommandObjectThreadTraceStartIntelPT::DoExecuteOnThreads(77    Args &command, CommandReturnObject &result,78    llvm::ArrayRef<lldb::tid_t> tids) {79  if (Error err = m_trace.Start(tids, m_options.m_ipt_trace_size,80                                m_options.m_enable_tsc, m_options.m_psb_period))81    result.SetError(std::move(err));82  else83    result.SetStatus(eReturnStatusSuccessFinishResult);84 85  return result.Succeeded();86}87 88/// CommandObjectProcessTraceStartIntelPT89 90#define LLDB_OPTIONS_process_trace_start_intel_pt91#include "TraceIntelPTCommandOptions.inc"92 93Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue(94    uint32_t option_idx, llvm::StringRef option_arg,95    ExecutionContext *execution_context) {96  Status error;97  const int short_option = m_getopt_table[option_idx].val;98 99  switch (short_option) {100  case 's': {101    if (std::optional<uint64_t> bytes =102            ParsingUtils::ParseUserFriendlySizeExpression(option_arg))103      m_ipt_trace_size = *bytes;104    else105      error = Status::FromErrorStringWithFormat(106          "invalid bytes expression for '%s'", option_arg.str().c_str());107    break;108  }109  case 'l': {110    if (std::optional<uint64_t> bytes =111            ParsingUtils::ParseUserFriendlySizeExpression(option_arg))112      m_process_buffer_size_limit = *bytes;113    else114      error = Status::FromErrorStringWithFormat(115          "invalid bytes expression for '%s'", option_arg.str().c_str());116    break;117  }118  case 't': {119    m_enable_tsc = true;120    break;121  }122  case 'c': {123    m_per_cpu_tracing = true;124    break;125  }126  case 'd': {127    m_disable_cgroup_filtering = true;128    break;129  }130  case 'p': {131    int64_t psb_period;132    if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||133        psb_period < 0)134      error = Status::FromErrorStringWithFormat(135          "invalid integer value for option '%s'", option_arg.str().c_str());136    else137      m_psb_period = psb_period;138    break;139  }140  default:141    llvm_unreachable("Unimplemented option");142  }143  return error;144}145 146void CommandObjectProcessTraceStartIntelPT::CommandOptions::147    OptionParsingStarting(ExecutionContext *execution_context) {148  m_ipt_trace_size = kDefaultIptTraceSize;149  m_process_buffer_size_limit = kDefaultProcessBufferSizeLimit;150  m_enable_tsc = kDefaultEnableTscValue;151  m_psb_period = kDefaultPsbPeriod;152  m_per_cpu_tracing = kDefaultPerCpuTracing;153  m_disable_cgroup_filtering = kDefaultDisableCgroupFiltering;154}155 156llvm::ArrayRef<OptionDefinition>157CommandObjectProcessTraceStartIntelPT::CommandOptions::GetDefinitions() {158  return llvm::ArrayRef(g_process_trace_start_intel_pt_options);159}160 161void CommandObjectProcessTraceStartIntelPT::DoExecute(162    Args &command, CommandReturnObject &result) {163  if (Error err = m_trace.Start(164          m_options.m_ipt_trace_size, m_options.m_process_buffer_size_limit,165          m_options.m_enable_tsc, m_options.m_psb_period,166          m_options.m_per_cpu_tracing, m_options.m_disable_cgroup_filtering))167    result.SetError(std::move(err));168  else169    result.SetStatus(eReturnStatusSuccessFinishResult);170}171 172std::optional<uint64_t>173ParsingUtils::ParseUserFriendlySizeExpression(llvm::StringRef size_expression) {174  if (size_expression.empty()) {175    return std::nullopt;176  }177  const uint64_t kBytesMultiplier = 1;178  const uint64_t kKibiBytesMultiplier = 1024;179  const uint64_t kMebiBytesMultiplier = 1024 * 1024;180 181  DenseMap<StringRef, uint64_t> multipliers = {182      {"mib", kMebiBytesMultiplier}, {"mb", kMebiBytesMultiplier},183      {"m", kMebiBytesMultiplier},   {"kib", kKibiBytesMultiplier},184      {"kb", kKibiBytesMultiplier},  {"k", kKibiBytesMultiplier},185      {"b", kBytesMultiplier},       {"", kBytesMultiplier}};186 187  const auto non_digit_index = size_expression.find_first_not_of("0123456789");188  if (non_digit_index == 0) { // expression starts from from non-digit char.189    return std::nullopt;190  }191 192  const llvm::StringRef number_part =193      non_digit_index == llvm::StringRef::npos194          ? size_expression195          : size_expression.substr(0, non_digit_index);196  uint64_t parsed_number;197  if (number_part.getAsInteger(10, parsed_number)) {198    return std::nullopt;199  }200 201  if (non_digit_index != llvm::StringRef::npos) { // if expression has units.202    const auto multiplier = size_expression.substr(non_digit_index).lower();203 204    auto it = multipliers.find(multiplier);205    if (it == multipliers.end())206      return std::nullopt;207 208    return parsed_number * it->second;209  } else {210    return parsed_number;211  }212}213