1fb19f11eSWalter Erquinigo //===-- CommandObjectTraceStartIntelPT.cpp --------------------------------===//
2fb19f11eSWalter Erquinigo //
3fb19f11eSWalter Erquinigo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4fb19f11eSWalter Erquinigo // See https://llvm.org/LICENSE.txt for license information.
5fb19f11eSWalter Erquinigo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6fb19f11eSWalter Erquinigo //
7fb19f11eSWalter Erquinigo //===----------------------------------------------------------------------===//
8fb19f11eSWalter Erquinigo
9fb19f11eSWalter Erquinigo #include "CommandObjectTraceStartIntelPT.h"
10fb19f11eSWalter Erquinigo
110b697561SWalter Erquinigo #include "TraceIntelPT.h"
12bf9f21a2SWalter Erquinigo #include "TraceIntelPTConstants.h"
13fb19f11eSWalter Erquinigo #include "lldb/Host/OptionParser.h"
14*7ced9fffSJonas Devlieghere #include "lldb/Interpreter/CommandOptionArgumentTable.h"
150b697561SWalter Erquinigo #include "lldb/Target/Process.h"
16fb19f11eSWalter Erquinigo #include "lldb/Target/Trace.h"
17fb19f11eSWalter Erquinigo
18fb19f11eSWalter Erquinigo using namespace lldb;
19fb19f11eSWalter Erquinigo using namespace lldb_private;
20fb19f11eSWalter Erquinigo using namespace lldb_private::trace_intel_pt;
21fb19f11eSWalter Erquinigo using namespace llvm;
22fb19f11eSWalter Erquinigo
230b697561SWalter Erquinigo // CommandObjectThreadTraceStartIntelPT
240b697561SWalter Erquinigo
25fb19f11eSWalter Erquinigo #define LLDB_OPTIONS_thread_trace_start_intel_pt
26fb19f11eSWalter Erquinigo #include "TraceIntelPTCommandOptions.inc"
27fb19f11eSWalter Erquinigo
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)280b697561SWalter Erquinigo Status CommandObjectThreadTraceStartIntelPT::CommandOptions::SetOptionValue(
29fb19f11eSWalter Erquinigo uint32_t option_idx, llvm::StringRef option_arg,
30fb19f11eSWalter Erquinigo ExecutionContext *execution_context) {
31fb19f11eSWalter Erquinigo Status error;
32fb19f11eSWalter Erquinigo const int short_option = m_getopt_table[option_idx].val;
33fb19f11eSWalter Erquinigo
34fb19f11eSWalter Erquinigo switch (short_option) {
35fb19f11eSWalter Erquinigo case 's': {
36db73a52dSrnofenko if (Optional<uint64_t> bytes =
37db73a52dSrnofenko ParsingUtils::ParseUserFriendlySizeExpression(option_arg))
38db73a52dSrnofenko m_ipt_trace_size = *bytes;
39fb19f11eSWalter Erquinigo else
40db73a52dSrnofenko error.SetErrorStringWithFormat("invalid bytes expression for '%s'",
41db73a52dSrnofenko option_arg.str().c_str());
42fb19f11eSWalter Erquinigo break;
43fb19f11eSWalter Erquinigo }
4404195843SWalter Erquinigo case 't': {
4504195843SWalter Erquinigo m_enable_tsc = true;
4604195843SWalter Erquinigo break;
4704195843SWalter Erquinigo }
4804195843SWalter Erquinigo case 'p': {
4904195843SWalter Erquinigo int64_t psb_period;
5004195843SWalter Erquinigo if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||
5104195843SWalter Erquinigo psb_period < 0)
5204195843SWalter Erquinigo error.SetErrorStringWithFormat("invalid integer value for option '%s'",
5304195843SWalter Erquinigo option_arg.str().c_str());
5404195843SWalter Erquinigo else
5504195843SWalter Erquinigo m_psb_period = psb_period;
5604195843SWalter Erquinigo break;
5704195843SWalter Erquinigo }
58fb19f11eSWalter Erquinigo default:
59fb19f11eSWalter Erquinigo llvm_unreachable("Unimplemented option");
60fb19f11eSWalter Erquinigo }
61fb19f11eSWalter Erquinigo return error;
62fb19f11eSWalter Erquinigo }
63fb19f11eSWalter Erquinigo
640b697561SWalter Erquinigo void CommandObjectThreadTraceStartIntelPT::CommandOptions::
OptionParsingStarting(ExecutionContext * execution_context)650b697561SWalter Erquinigo OptionParsingStarting(ExecutionContext *execution_context) {
666a5355e8SWalter Erquinigo m_ipt_trace_size = kDefaultIptTraceSize;
6704195843SWalter Erquinigo m_enable_tsc = kDefaultEnableTscValue;
6804195843SWalter Erquinigo m_psb_period = kDefaultPsbPeriod;
69fb19f11eSWalter Erquinigo }
70fb19f11eSWalter Erquinigo
71fb19f11eSWalter Erquinigo llvm::ArrayRef<OptionDefinition>
GetDefinitions()720b697561SWalter Erquinigo CommandObjectThreadTraceStartIntelPT::CommandOptions::GetDefinitions() {
73fb19f11eSWalter Erquinigo return llvm::makeArrayRef(g_thread_trace_start_intel_pt_options);
74fb19f11eSWalter Erquinigo }
75fb19f11eSWalter Erquinigo
DoExecuteOnThreads(Args & command,CommandReturnObject & result,llvm::ArrayRef<lldb::tid_t> tids)760b697561SWalter Erquinigo bool CommandObjectThreadTraceStartIntelPT::DoExecuteOnThreads(
770b697561SWalter Erquinigo Args &command, CommandReturnObject &result,
78bf9f21a2SWalter Erquinigo llvm::ArrayRef<lldb::tid_t> tids) {
796a5355e8SWalter Erquinigo if (Error err = m_trace.Start(tids, m_options.m_ipt_trace_size,
8004195843SWalter Erquinigo m_options.m_enable_tsc, m_options.m_psb_period))
812aa1dd1cSWalter Erquinigo result.SetError(Status(std::move(err)));
820b697561SWalter Erquinigo else
83fb19f11eSWalter Erquinigo result.SetStatus(eReturnStatusSuccessFinishResult);
840b697561SWalter Erquinigo
850b697561SWalter Erquinigo return result.Succeeded();
860b697561SWalter Erquinigo }
870b697561SWalter Erquinigo
880b697561SWalter Erquinigo /// CommandObjectProcessTraceStartIntelPT
890b697561SWalter Erquinigo
900b697561SWalter Erquinigo #define LLDB_OPTIONS_process_trace_start_intel_pt
910b697561SWalter Erquinigo #include "TraceIntelPTCommandOptions.inc"
920b697561SWalter Erquinigo
SetOptionValue(uint32_t option_idx,llvm::StringRef option_arg,ExecutionContext * execution_context)930b697561SWalter Erquinigo Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue(
940b697561SWalter Erquinigo uint32_t option_idx, llvm::StringRef option_arg,
950b697561SWalter Erquinigo ExecutionContext *execution_context) {
960b697561SWalter Erquinigo Status error;
970b697561SWalter Erquinigo const int short_option = m_getopt_table[option_idx].val;
980b697561SWalter Erquinigo
990b697561SWalter Erquinigo switch (short_option) {
1000b697561SWalter Erquinigo case 's': {
101db73a52dSrnofenko if (Optional<uint64_t> bytes =
102db73a52dSrnofenko ParsingUtils::ParseUserFriendlySizeExpression(option_arg))
103db73a52dSrnofenko m_ipt_trace_size = *bytes;
1040b697561SWalter Erquinigo else
105db73a52dSrnofenko error.SetErrorStringWithFormat("invalid bytes expression for '%s'",
106db73a52dSrnofenko option_arg.str().c_str());
1070b697561SWalter Erquinigo break;
1080b697561SWalter Erquinigo }
1090b697561SWalter Erquinigo case 'l': {
110db73a52dSrnofenko if (Optional<uint64_t> bytes =
111db73a52dSrnofenko ParsingUtils::ParseUserFriendlySizeExpression(option_arg))
112db73a52dSrnofenko m_process_buffer_size_limit = *bytes;
1130b697561SWalter Erquinigo else
114db73a52dSrnofenko error.SetErrorStringWithFormat("invalid bytes expression for '%s'",
115db73a52dSrnofenko option_arg.str().c_str());
1160b697561SWalter Erquinigo break;
1170b697561SWalter Erquinigo }
11804195843SWalter Erquinigo case 't': {
11904195843SWalter Erquinigo m_enable_tsc = true;
12004195843SWalter Erquinigo break;
12104195843SWalter Erquinigo }
122b8d1776fSWalter Erquinigo case 'c': {
1236a5355e8SWalter Erquinigo m_per_cpu_tracing = true;
124b8d1776fSWalter Erquinigo break;
125b8d1776fSWalter Erquinigo }
126d30fd5c3SGaurav Gaur case 'd': {
127d30fd5c3SGaurav Gaur m_disable_cgroup_filtering = true;
128d30fd5c3SGaurav Gaur break;
129d30fd5c3SGaurav Gaur }
13004195843SWalter Erquinigo case 'p': {
13104195843SWalter Erquinigo int64_t psb_period;
13204195843SWalter Erquinigo if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||
13304195843SWalter Erquinigo psb_period < 0)
13404195843SWalter Erquinigo error.SetErrorStringWithFormat("invalid integer value for option '%s'",
13504195843SWalter Erquinigo option_arg.str().c_str());
13604195843SWalter Erquinigo else
13704195843SWalter Erquinigo m_psb_period = psb_period;
13804195843SWalter Erquinigo break;
13904195843SWalter Erquinigo }
1400b697561SWalter Erquinigo default:
1410b697561SWalter Erquinigo llvm_unreachable("Unimplemented option");
1420b697561SWalter Erquinigo }
1430b697561SWalter Erquinigo return error;
1440b697561SWalter Erquinigo }
1450b697561SWalter Erquinigo
1460b697561SWalter Erquinigo void CommandObjectProcessTraceStartIntelPT::CommandOptions::
OptionParsingStarting(ExecutionContext * execution_context)1470b697561SWalter Erquinigo OptionParsingStarting(ExecutionContext *execution_context) {
1486a5355e8SWalter Erquinigo m_ipt_trace_size = kDefaultIptTraceSize;
14904195843SWalter Erquinigo m_process_buffer_size_limit = kDefaultProcessBufferSizeLimit;
15004195843SWalter Erquinigo m_enable_tsc = kDefaultEnableTscValue;
15104195843SWalter Erquinigo m_psb_period = kDefaultPsbPeriod;
1526a5355e8SWalter Erquinigo m_per_cpu_tracing = kDefaultPerCpuTracing;
153d30fd5c3SGaurav Gaur m_disable_cgroup_filtering = kDefaultDisableCgroupFiltering;
1540b697561SWalter Erquinigo }
1550b697561SWalter Erquinigo
1560b697561SWalter Erquinigo llvm::ArrayRef<OptionDefinition>
GetDefinitions()1570b697561SWalter Erquinigo CommandObjectProcessTraceStartIntelPT::CommandOptions::GetDefinitions() {
1580b697561SWalter Erquinigo return llvm::makeArrayRef(g_process_trace_start_intel_pt_options);
1590b697561SWalter Erquinigo }
1600b697561SWalter Erquinigo
DoExecute(Args & command,CommandReturnObject & result)1610b697561SWalter Erquinigo bool CommandObjectProcessTraceStartIntelPT::DoExecute(
1620b697561SWalter Erquinigo Args &command, CommandReturnObject &result) {
163d30fd5c3SGaurav Gaur if (Error err = m_trace.Start(
164d30fd5c3SGaurav Gaur m_options.m_ipt_trace_size, m_options.m_process_buffer_size_limit,
165b8d1776fSWalter Erquinigo m_options.m_enable_tsc, m_options.m_psb_period,
166d30fd5c3SGaurav Gaur m_options.m_per_cpu_tracing, m_options.m_disable_cgroup_filtering))
1672aa1dd1cSWalter Erquinigo result.SetError(Status(std::move(err)));
1680b697561SWalter Erquinigo else
1690b697561SWalter Erquinigo result.SetStatus(eReturnStatusSuccessFinishResult);
1700b697561SWalter Erquinigo
171fb19f11eSWalter Erquinigo return result.Succeeded();
172fb19f11eSWalter Erquinigo }
173db73a52dSrnofenko
174db73a52dSrnofenko Optional<uint64_t>
ParseUserFriendlySizeExpression(llvm::StringRef size_expression)175db73a52dSrnofenko ParsingUtils::ParseUserFriendlySizeExpression(llvm::StringRef size_expression) {
176db73a52dSrnofenko if (size_expression.empty()) {
177db73a52dSrnofenko return llvm::None;
178db73a52dSrnofenko }
179db73a52dSrnofenko const uint64_t kBytesMultiplier = 1;
180db73a52dSrnofenko const uint64_t kKibiBytesMultiplier = 1024;
181db73a52dSrnofenko const uint64_t kMebiBytesMultiplier = 1024 * 1024;
182db73a52dSrnofenko
183db73a52dSrnofenko DenseMap<StringRef, uint64_t> multipliers = {
184db73a52dSrnofenko {"mib", kMebiBytesMultiplier}, {"mb", kMebiBytesMultiplier},
185db73a52dSrnofenko {"m", kMebiBytesMultiplier}, {"kib", kKibiBytesMultiplier},
186db73a52dSrnofenko {"kb", kKibiBytesMultiplier}, {"k", kKibiBytesMultiplier},
187db73a52dSrnofenko {"b", kBytesMultiplier}, {"", kBytesMultiplier}};
188db73a52dSrnofenko
189db73a52dSrnofenko const auto non_digit_index = size_expression.find_first_not_of("0123456789");
190db73a52dSrnofenko if (non_digit_index == 0) { // expression starts from from non-digit char.
191db73a52dSrnofenko return llvm::None;
192db73a52dSrnofenko }
193db73a52dSrnofenko
194db73a52dSrnofenko const llvm::StringRef number_part =
195db73a52dSrnofenko non_digit_index == llvm::StringRef::npos
196db73a52dSrnofenko ? size_expression
197db73a52dSrnofenko : size_expression.substr(0, non_digit_index);
198db73a52dSrnofenko uint64_t parsed_number;
199db73a52dSrnofenko if (number_part.getAsInteger(10, parsed_number)) {
200db73a52dSrnofenko return llvm::None;
201db73a52dSrnofenko }
202db73a52dSrnofenko
203db73a52dSrnofenko if (non_digit_index != llvm::StringRef::npos) { // if expression has units.
204db73a52dSrnofenko const auto multiplier = size_expression.substr(non_digit_index).lower();
205db73a52dSrnofenko
206db73a52dSrnofenko auto it = multipliers.find(multiplier);
207db73a52dSrnofenko if (it == multipliers.end())
208db73a52dSrnofenko return llvm::None;
209db73a52dSrnofenko
210db73a52dSrnofenko return parsed_number * it->second;
211db73a52dSrnofenko } else {
212db73a52dSrnofenko return parsed_number;
213db73a52dSrnofenko }
214db73a52dSrnofenko }
215