1 //===-- CommandObjectTraceStartIntelPT.cpp --------------------------------===//
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
7 //===----------------------------------------------------------------------===//
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"
19 using namespace lldb_private
;
20 using namespace lldb_private::trace_intel_pt
;
23 // CommandObjectThreadTraceStartIntelPT
25 #define LLDB_OPTIONS_thread_trace_start_intel_pt
26 #include "TraceIntelPTCommandOptions.inc"
28 Status
CommandObjectThreadTraceStartIntelPT::CommandOptions::SetOptionValue(
29 uint32_t option_idx
, llvm::StringRef option_arg
,
30 ExecutionContext
*execution_context
) {
32 const int short_option
= m_getopt_table
[option_idx
].val
;
34 switch (short_option
) {
36 if (std::optional
<uint64_t> bytes
=
37 ParsingUtils::ParseUserFriendlySizeExpression(option_arg
))
38 m_ipt_trace_size
= *bytes
;
40 error
.SetErrorStringWithFormat("invalid bytes expression for '%s'",
41 option_arg
.str().c_str());
50 if (option_arg
.empty() || option_arg
.getAsInteger(0, psb_period
) ||
52 error
.SetErrorStringWithFormat("invalid integer value for option '%s'",
53 option_arg
.str().c_str());
55 m_psb_period
= psb_period
;
59 llvm_unreachable("Unimplemented option");
64 void CommandObjectThreadTraceStartIntelPT::CommandOptions::
65 OptionParsingStarting(ExecutionContext
*execution_context
) {
66 m_ipt_trace_size
= kDefaultIptTraceSize
;
67 m_enable_tsc
= kDefaultEnableTscValue
;
68 m_psb_period
= kDefaultPsbPeriod
;
71 llvm::ArrayRef
<OptionDefinition
>
72 CommandObjectThreadTraceStartIntelPT::CommandOptions::GetDefinitions() {
73 return llvm::ArrayRef(g_thread_trace_start_intel_pt_options
);
76 bool 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(Status(std::move(err
)));
83 result
.SetStatus(eReturnStatusSuccessFinishResult
);
85 return result
.Succeeded();
88 /// CommandObjectProcessTraceStartIntelPT
90 #define LLDB_OPTIONS_process_trace_start_intel_pt
91 #include "TraceIntelPTCommandOptions.inc"
93 Status
CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue(
94 uint32_t option_idx
, llvm::StringRef option_arg
,
95 ExecutionContext
*execution_context
) {
97 const int short_option
= m_getopt_table
[option_idx
].val
;
99 switch (short_option
) {
101 if (std::optional
<uint64_t> bytes
=
102 ParsingUtils::ParseUserFriendlySizeExpression(option_arg
))
103 m_ipt_trace_size
= *bytes
;
105 error
.SetErrorStringWithFormat("invalid bytes expression for '%s'",
106 option_arg
.str().c_str());
110 if (std::optional
<uint64_t> bytes
=
111 ParsingUtils::ParseUserFriendlySizeExpression(option_arg
))
112 m_process_buffer_size_limit
= *bytes
;
114 error
.SetErrorStringWithFormat("invalid bytes expression for '%s'",
115 option_arg
.str().c_str());
123 m_per_cpu_tracing
= true;
127 m_disable_cgroup_filtering
= true;
132 if (option_arg
.empty() || option_arg
.getAsInteger(0, psb_period
) ||
134 error
.SetErrorStringWithFormat("invalid integer value for option '%s'",
135 option_arg
.str().c_str());
137 m_psb_period
= psb_period
;
141 llvm_unreachable("Unimplemented option");
146 void 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
;
156 llvm::ArrayRef
<OptionDefinition
>
157 CommandObjectProcessTraceStartIntelPT::CommandOptions::GetDefinitions() {
158 return llvm::ArrayRef(g_process_trace_start_intel_pt_options
);
161 bool 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(Status(std::move(err
)));
169 result
.SetStatus(eReturnStatusSuccessFinishResult
);
171 return result
.Succeeded();
174 std::optional
<uint64_t>
175 ParsingUtils::ParseUserFriendlySizeExpression(llvm::StringRef size_expression
) {
176 if (size_expression
.empty()) {
179 const uint64_t kBytesMultiplier
= 1;
180 const uint64_t kKibiBytesMultiplier
= 1024;
181 const uint64_t kMebiBytesMultiplier
= 1024 * 1024;
183 DenseMap
<StringRef
, uint64_t> multipliers
= {
184 {"mib", kMebiBytesMultiplier
}, {"mb", kMebiBytesMultiplier
},
185 {"m", kMebiBytesMultiplier
}, {"kib", kKibiBytesMultiplier
},
186 {"kb", kKibiBytesMultiplier
}, {"k", kKibiBytesMultiplier
},
187 {"b", kBytesMultiplier
}, {"", kBytesMultiplier
}};
189 const auto non_digit_index
= size_expression
.find_first_not_of("0123456789");
190 if (non_digit_index
== 0) { // expression starts from from non-digit char.
194 const llvm::StringRef number_part
=
195 non_digit_index
== llvm::StringRef::npos
197 : size_expression
.substr(0, non_digit_index
);
198 uint64_t parsed_number
;
199 if (number_part
.getAsInteger(10, parsed_number
)) {
203 if (non_digit_index
!= llvm::StringRef::npos
) { // if expression has units.
204 const auto multiplier
= size_expression
.substr(non_digit_index
).lower();
206 auto it
= multipliers
.find(multiplier
);
207 if (it
== multipliers
.end())
210 return parsed_number
* it
->second
;
212 return parsed_number
;