1e8d8bef9SDimitry Andric //===-- CommandObjectTraceStartIntelPT.cpp --------------------------------===//
2e8d8bef9SDimitry Andric //
3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e8d8bef9SDimitry Andric //
7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8e8d8bef9SDimitry Andric 
9e8d8bef9SDimitry Andric #include "CommandObjectTraceStartIntelPT.h"
10e8d8bef9SDimitry Andric 
11fe6060f1SDimitry Andric #include "TraceIntelPT.h"
12fe6060f1SDimitry Andric #include "TraceIntelPTConstants.h"
13e8d8bef9SDimitry Andric #include "lldb/Host/OptionParser.h"
14fe6060f1SDimitry Andric #include "lldb/Target/Process.h"
15e8d8bef9SDimitry Andric #include "lldb/Target/Trace.h"
16e8d8bef9SDimitry Andric 
17e8d8bef9SDimitry Andric using namespace lldb;
18e8d8bef9SDimitry Andric using namespace lldb_private;
19e8d8bef9SDimitry Andric using namespace lldb_private::trace_intel_pt;
20e8d8bef9SDimitry Andric using namespace llvm;
21e8d8bef9SDimitry Andric 
22fe6060f1SDimitry Andric // CommandObjectThreadTraceStartIntelPT
23fe6060f1SDimitry Andric 
24e8d8bef9SDimitry Andric #define LLDB_OPTIONS_thread_trace_start_intel_pt
25e8d8bef9SDimitry Andric #include "TraceIntelPTCommandOptions.inc"
26e8d8bef9SDimitry Andric 
27fe6060f1SDimitry Andric Status CommandObjectThreadTraceStartIntelPT::CommandOptions::SetOptionValue(
28e8d8bef9SDimitry Andric     uint32_t option_idx, llvm::StringRef option_arg,
29e8d8bef9SDimitry Andric     ExecutionContext *execution_context) {
30e8d8bef9SDimitry Andric   Status error;
31e8d8bef9SDimitry Andric   const int short_option = m_getopt_table[option_idx].val;
32e8d8bef9SDimitry Andric 
33e8d8bef9SDimitry Andric   switch (short_option) {
34e8d8bef9SDimitry Andric   case 's': {
35*81ad6265SDimitry Andric     int64_t ipt_trace_size;
36*81ad6265SDimitry Andric     if (option_arg.empty() || option_arg.getAsInteger(0, ipt_trace_size) ||
37*81ad6265SDimitry Andric         ipt_trace_size < 0)
38e8d8bef9SDimitry Andric       error.SetErrorStringWithFormat("invalid integer value for option '%s'",
39e8d8bef9SDimitry Andric                                      option_arg.str().c_str());
40e8d8bef9SDimitry Andric     else
41*81ad6265SDimitry Andric       m_ipt_trace_size = ipt_trace_size;
42e8d8bef9SDimitry Andric     break;
43e8d8bef9SDimitry Andric   }
44fe6060f1SDimitry Andric   case 't': {
45fe6060f1SDimitry Andric     m_enable_tsc = true;
46fe6060f1SDimitry Andric     break;
47fe6060f1SDimitry Andric   }
48fe6060f1SDimitry Andric   case 'p': {
49fe6060f1SDimitry Andric     int64_t psb_period;
50fe6060f1SDimitry Andric     if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||
51fe6060f1SDimitry Andric         psb_period < 0)
52e8d8bef9SDimitry Andric       error.SetErrorStringWithFormat("invalid integer value for option '%s'",
53e8d8bef9SDimitry Andric                                      option_arg.str().c_str());
54e8d8bef9SDimitry Andric     else
55fe6060f1SDimitry Andric       m_psb_period = psb_period;
56e8d8bef9SDimitry Andric     break;
57e8d8bef9SDimitry Andric   }
58e8d8bef9SDimitry Andric   default:
59e8d8bef9SDimitry Andric     llvm_unreachable("Unimplemented option");
60e8d8bef9SDimitry Andric   }
61e8d8bef9SDimitry Andric   return error;
62e8d8bef9SDimitry Andric }
63e8d8bef9SDimitry Andric 
64fe6060f1SDimitry Andric void CommandObjectThreadTraceStartIntelPT::CommandOptions::
65fe6060f1SDimitry Andric     OptionParsingStarting(ExecutionContext *execution_context) {
66*81ad6265SDimitry Andric   m_ipt_trace_size = kDefaultIptTraceSize;
67fe6060f1SDimitry Andric   m_enable_tsc = kDefaultEnableTscValue;
68fe6060f1SDimitry Andric   m_psb_period = kDefaultPsbPeriod;
69e8d8bef9SDimitry Andric }
70e8d8bef9SDimitry Andric 
71e8d8bef9SDimitry Andric llvm::ArrayRef<OptionDefinition>
72fe6060f1SDimitry Andric CommandObjectThreadTraceStartIntelPT::CommandOptions::GetDefinitions() {
73e8d8bef9SDimitry Andric   return llvm::makeArrayRef(g_thread_trace_start_intel_pt_options);
74e8d8bef9SDimitry Andric }
75e8d8bef9SDimitry Andric 
76fe6060f1SDimitry Andric bool CommandObjectThreadTraceStartIntelPT::DoExecuteOnThreads(
77fe6060f1SDimitry Andric     Args &command, CommandReturnObject &result,
78fe6060f1SDimitry Andric     llvm::ArrayRef<lldb::tid_t> tids) {
79*81ad6265SDimitry Andric   if (Error err = m_trace.Start(tids, m_options.m_ipt_trace_size,
80fe6060f1SDimitry Andric                                 m_options.m_enable_tsc, m_options.m_psb_period))
81fe6060f1SDimitry Andric     result.SetError(Status(std::move(err)));
82fe6060f1SDimitry Andric   else
83e8d8bef9SDimitry Andric     result.SetStatus(eReturnStatusSuccessFinishResult);
84fe6060f1SDimitry Andric 
85fe6060f1SDimitry Andric   return result.Succeeded();
86fe6060f1SDimitry Andric }
87fe6060f1SDimitry Andric 
88fe6060f1SDimitry Andric /// CommandObjectProcessTraceStartIntelPT
89fe6060f1SDimitry Andric 
90fe6060f1SDimitry Andric #define LLDB_OPTIONS_process_trace_start_intel_pt
91fe6060f1SDimitry Andric #include "TraceIntelPTCommandOptions.inc"
92fe6060f1SDimitry Andric 
93fe6060f1SDimitry Andric Status CommandObjectProcessTraceStartIntelPT::CommandOptions::SetOptionValue(
94fe6060f1SDimitry Andric     uint32_t option_idx, llvm::StringRef option_arg,
95fe6060f1SDimitry Andric     ExecutionContext *execution_context) {
96fe6060f1SDimitry Andric   Status error;
97fe6060f1SDimitry Andric   const int short_option = m_getopt_table[option_idx].val;
98fe6060f1SDimitry Andric 
99fe6060f1SDimitry Andric   switch (short_option) {
100fe6060f1SDimitry Andric   case 's': {
101*81ad6265SDimitry Andric     int64_t ipt_trace_size;
102*81ad6265SDimitry Andric     if (option_arg.empty() || option_arg.getAsInteger(0, ipt_trace_size) ||
103*81ad6265SDimitry Andric         ipt_trace_size < 0)
104fe6060f1SDimitry Andric       error.SetErrorStringWithFormat("invalid integer value for option '%s'",
105fe6060f1SDimitry Andric                                      option_arg.str().c_str());
106fe6060f1SDimitry Andric     else
107*81ad6265SDimitry Andric       m_ipt_trace_size = ipt_trace_size;
108fe6060f1SDimitry Andric     break;
109fe6060f1SDimitry Andric   }
110fe6060f1SDimitry Andric   case 'l': {
111fe6060f1SDimitry Andric     int64_t process_buffer_size_limit;
112fe6060f1SDimitry Andric     if (option_arg.empty() ||
113fe6060f1SDimitry Andric         option_arg.getAsInteger(0, process_buffer_size_limit) ||
114fe6060f1SDimitry Andric         process_buffer_size_limit < 0)
115fe6060f1SDimitry Andric       error.SetErrorStringWithFormat("invalid integer value for option '%s'",
116fe6060f1SDimitry Andric                                      option_arg.str().c_str());
117fe6060f1SDimitry Andric     else
118fe6060f1SDimitry Andric       m_process_buffer_size_limit = process_buffer_size_limit;
119fe6060f1SDimitry Andric     break;
120fe6060f1SDimitry Andric   }
121fe6060f1SDimitry Andric   case 't': {
122fe6060f1SDimitry Andric     m_enable_tsc = true;
123fe6060f1SDimitry Andric     break;
124fe6060f1SDimitry Andric   }
125*81ad6265SDimitry Andric   case 'c': {
126*81ad6265SDimitry Andric     m_per_cpu_tracing = true;
127*81ad6265SDimitry Andric     break;
128*81ad6265SDimitry Andric   }
129fe6060f1SDimitry Andric   case 'p': {
130fe6060f1SDimitry Andric     int64_t psb_period;
131fe6060f1SDimitry Andric     if (option_arg.empty() || option_arg.getAsInteger(0, psb_period) ||
132fe6060f1SDimitry Andric         psb_period < 0)
133fe6060f1SDimitry Andric       error.SetErrorStringWithFormat("invalid integer value for option '%s'",
134fe6060f1SDimitry Andric                                      option_arg.str().c_str());
135fe6060f1SDimitry Andric     else
136fe6060f1SDimitry Andric       m_psb_period = psb_period;
137fe6060f1SDimitry Andric     break;
138fe6060f1SDimitry Andric   }
139fe6060f1SDimitry Andric   default:
140fe6060f1SDimitry Andric     llvm_unreachable("Unimplemented option");
141fe6060f1SDimitry Andric   }
142fe6060f1SDimitry Andric   return error;
143fe6060f1SDimitry Andric }
144fe6060f1SDimitry Andric 
145fe6060f1SDimitry Andric void CommandObjectProcessTraceStartIntelPT::CommandOptions::
146fe6060f1SDimitry Andric     OptionParsingStarting(ExecutionContext *execution_context) {
147*81ad6265SDimitry Andric   m_ipt_trace_size = kDefaultIptTraceSize;
148fe6060f1SDimitry Andric   m_process_buffer_size_limit = kDefaultProcessBufferSizeLimit;
149fe6060f1SDimitry Andric   m_enable_tsc = kDefaultEnableTscValue;
150fe6060f1SDimitry Andric   m_psb_period = kDefaultPsbPeriod;
151*81ad6265SDimitry Andric   m_per_cpu_tracing = kDefaultPerCpuTracing;
152fe6060f1SDimitry Andric }
153fe6060f1SDimitry Andric 
154fe6060f1SDimitry Andric llvm::ArrayRef<OptionDefinition>
155fe6060f1SDimitry Andric CommandObjectProcessTraceStartIntelPT::CommandOptions::GetDefinitions() {
156fe6060f1SDimitry Andric   return llvm::makeArrayRef(g_process_trace_start_intel_pt_options);
157fe6060f1SDimitry Andric }
158fe6060f1SDimitry Andric 
159fe6060f1SDimitry Andric bool CommandObjectProcessTraceStartIntelPT::DoExecute(
160fe6060f1SDimitry Andric     Args &command, CommandReturnObject &result) {
161*81ad6265SDimitry Andric   if (Error err = m_trace.Start(m_options.m_ipt_trace_size,
162fe6060f1SDimitry Andric                                 m_options.m_process_buffer_size_limit,
163*81ad6265SDimitry Andric                                 m_options.m_enable_tsc, m_options.m_psb_period,
164*81ad6265SDimitry Andric                                 m_options.m_per_cpu_tracing))
165fe6060f1SDimitry Andric     result.SetError(Status(std::move(err)));
166fe6060f1SDimitry Andric   else
167fe6060f1SDimitry Andric     result.SetStatus(eReturnStatusSuccessFinishResult);
168fe6060f1SDimitry Andric 
169e8d8bef9SDimitry Andric   return result.Succeeded();
170e8d8bef9SDimitry Andric }
171