Path: blob/main/contrib/llvm-project/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp
39645 views
//===-- CommandObjectTraceStartIntelPT.cpp --------------------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "CommandObjectTraceStartIntelPT.h"9#include "TraceIntelPT.h"10#include "TraceIntelPTConstants.h"11#include "lldb/Host/OptionParser.h"12#include "lldb/Interpreter/CommandOptionArgumentTable.h"13#include "lldb/Target/Process.h"14#include "lldb/Target/Trace.h"15#include <optional>1617using namespace lldb;18using namespace lldb_private;19using namespace lldb_private::trace_intel_pt;20using namespace llvm;2122// CommandObjectThreadTraceStartIntelPT2324#define LLDB_OPTIONS_thread_trace_start_intel_pt25#include "TraceIntelPTCommandOptions.inc"2627Status CommandObjectThreadTraceStartIntelPT::CommandOptions::SetOptionValue(28uint32_t option_idx, llvm::StringRef option_arg,29ExecutionContext *execution_context) {30Status error;31const int short_option = m_getopt_table[option_idx].val;3233switch (short_option) {34case 's': {35if (std::optional<uint64_t> bytes =36ParsingUtils::ParseUserFriendlySizeExpression(option_arg))37m_ipt_trace_size = *bytes;38else39error.SetErrorStringWithFormat("invalid bytes expression for '%s'",40option_arg.str().c_str());41break;42}43case 't': {44m_enable_tsc = true;45break;46}47case 'p': {48int64_t psb_period;49if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||50psb_period < 0)51error.SetErrorStringWithFormat("invalid integer value for option '%s'",52option_arg.str().c_str());53else54m_psb_period = psb_period;55break;56}57default:58llvm_unreachable("Unimplemented option");59}60return error;61}6263void CommandObjectThreadTraceStartIntelPT::CommandOptions::64OptionParsingStarting(ExecutionContext *execution_context) {65m_ipt_trace_size = kDefaultIptTraceSize;66m_enable_tsc = kDefaultEnableTscValue;67m_psb_period = kDefaultPsbPeriod;68}6970llvm::ArrayRef<OptionDefinition>71CommandObjectThreadTraceStartIntelPT::CommandOptions::GetDefinitions() {72return llvm::ArrayRef(g_thread_trace_start_intel_pt_options);73}7475bool CommandObjectThreadTraceStartIntelPT::DoExecuteOnThreads(76Args &command, CommandReturnObject &result,77llvm::ArrayRef<lldb::tid_t> tids) {78if (Error err = m_trace.Start(tids, m_options.m_ipt_trace_size,79m_options.m_enable_tsc, m_options.m_psb_period))80result.SetError(Status(std::move(err)));81else82result.SetStatus(eReturnStatusSuccessFinishResult);8384return result.Succeeded();85}8687/// CommandObjectProcessTraceStartIntelPT8889#define LLDB_OPTIONS_process_trace_start_intel_pt90#include "TraceIntelPTCommandOptions.inc"9192Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue(93uint32_t option_idx, llvm::StringRef option_arg,94ExecutionContext *execution_context) {95Status error;96const int short_option = m_getopt_table[option_idx].val;9798switch (short_option) {99case 's': {100if (std::optional<uint64_t> bytes =101ParsingUtils::ParseUserFriendlySizeExpression(option_arg))102m_ipt_trace_size = *bytes;103else104error.SetErrorStringWithFormat("invalid bytes expression for '%s'",105option_arg.str().c_str());106break;107}108case 'l': {109if (std::optional<uint64_t> bytes =110ParsingUtils::ParseUserFriendlySizeExpression(option_arg))111m_process_buffer_size_limit = *bytes;112else113error.SetErrorStringWithFormat("invalid bytes expression for '%s'",114option_arg.str().c_str());115break;116}117case 't': {118m_enable_tsc = true;119break;120}121case 'c': {122m_per_cpu_tracing = true;123break;124}125case 'd': {126m_disable_cgroup_filtering = true;127break;128}129case 'p': {130int64_t psb_period;131if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||132psb_period < 0)133error.SetErrorStringWithFormat("invalid integer value for option '%s'",134option_arg.str().c_str());135else136m_psb_period = psb_period;137break;138}139default:140llvm_unreachable("Unimplemented option");141}142return error;143}144145void CommandObjectProcessTraceStartIntelPT::CommandOptions::146OptionParsingStarting(ExecutionContext *execution_context) {147m_ipt_trace_size = kDefaultIptTraceSize;148m_process_buffer_size_limit = kDefaultProcessBufferSizeLimit;149m_enable_tsc = kDefaultEnableTscValue;150m_psb_period = kDefaultPsbPeriod;151m_per_cpu_tracing = kDefaultPerCpuTracing;152m_disable_cgroup_filtering = kDefaultDisableCgroupFiltering;153}154155llvm::ArrayRef<OptionDefinition>156CommandObjectProcessTraceStartIntelPT::CommandOptions::GetDefinitions() {157return llvm::ArrayRef(g_process_trace_start_intel_pt_options);158}159160void CommandObjectProcessTraceStartIntelPT::DoExecute(161Args &command, CommandReturnObject &result) {162if (Error err = m_trace.Start(163m_options.m_ipt_trace_size, m_options.m_process_buffer_size_limit,164m_options.m_enable_tsc, m_options.m_psb_period,165m_options.m_per_cpu_tracing, m_options.m_disable_cgroup_filtering))166result.SetError(Status(std::move(err)));167else168result.SetStatus(eReturnStatusSuccessFinishResult);169}170171std::optional<uint64_t>172ParsingUtils::ParseUserFriendlySizeExpression(llvm::StringRef size_expression) {173if (size_expression.empty()) {174return std::nullopt;175}176const uint64_t kBytesMultiplier = 1;177const uint64_t kKibiBytesMultiplier = 1024;178const uint64_t kMebiBytesMultiplier = 1024 * 1024;179180DenseMap<StringRef, uint64_t> multipliers = {181{"mib", kMebiBytesMultiplier}, {"mb", kMebiBytesMultiplier},182{"m", kMebiBytesMultiplier}, {"kib", kKibiBytesMultiplier},183{"kb", kKibiBytesMultiplier}, {"k", kKibiBytesMultiplier},184{"b", kBytesMultiplier}, {"", kBytesMultiplier}};185186const auto non_digit_index = size_expression.find_first_not_of("0123456789");187if (non_digit_index == 0) { // expression starts from from non-digit char.188return std::nullopt;189}190191const llvm::StringRef number_part =192non_digit_index == llvm::StringRef::npos193? size_expression194: size_expression.substr(0, non_digit_index);195uint64_t parsed_number;196if (number_part.getAsInteger(10, parsed_number)) {197return std::nullopt;198}199200if (non_digit_index != llvm::StringRef::npos) { // if expression has units.201const auto multiplier = size_expression.substr(non_digit_index).lower();202203auto it = multipliers.find(multiplier);204if (it == multipliers.end())205return std::nullopt;206207return parsed_number * it->second;208} else {209return parsed_number;210}211}212213214