1 //===-- SBCommandInterpreter.cpp --------------------------------*- C++ -*-===//
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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "lldb/lldb-types.h"
10 
11 #include "SBReproducerPrivate.h"
12 #include "lldb/Interpreter/CommandInterpreter.h"
13 #include "lldb/Interpreter/CommandObjectMultiword.h"
14 #include "lldb/Interpreter/CommandReturnObject.h"
15 #include "lldb/Target/Target.h"
16 #include "lldb/Utility/Listener.h"
17 
18 #include "lldb/API/SBBroadcaster.h"
19 #include "lldb/API/SBCommandInterpreter.h"
20 #include "lldb/API/SBCommandReturnObject.h"
21 #include "lldb/API/SBEvent.h"
22 #include "lldb/API/SBExecutionContext.h"
23 #include "lldb/API/SBListener.h"
24 #include "lldb/API/SBProcess.h"
25 #include "lldb/API/SBStream.h"
26 #include "lldb/API/SBStringList.h"
27 #include "lldb/API/SBTarget.h"
28 
29 #include <memory>
30 
31 using namespace lldb;
32 using namespace lldb_private;
33 
34 SBCommandInterpreterRunOptions::SBCommandInterpreterRunOptions() {
35   LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCommandInterpreterRunOptions);
36 
37   m_opaque_up.reset(new CommandInterpreterRunOptions());
38 }
39 
40 SBCommandInterpreterRunOptions::~SBCommandInterpreterRunOptions() = default;
41 
42 bool SBCommandInterpreterRunOptions::GetStopOnContinue() const {
43   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreterRunOptions,
44                                    GetStopOnContinue);
45 
46   return m_opaque_up->GetStopOnContinue();
47 }
48 
49 void SBCommandInterpreterRunOptions::SetStopOnContinue(bool stop_on_continue) {
50   LLDB_RECORD_METHOD(void, SBCommandInterpreterRunOptions, SetStopOnContinue,
51                      (bool), stop_on_continue);
52 
53   m_opaque_up->SetStopOnContinue(stop_on_continue);
54 }
55 
56 bool SBCommandInterpreterRunOptions::GetStopOnError() const {
57   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreterRunOptions,
58                                    GetStopOnError);
59 
60   return m_opaque_up->GetStopOnError();
61 }
62 
63 void SBCommandInterpreterRunOptions::SetStopOnError(bool stop_on_error) {
64   LLDB_RECORD_METHOD(void, SBCommandInterpreterRunOptions, SetStopOnError,
65                      (bool), stop_on_error);
66 
67   m_opaque_up->SetStopOnError(stop_on_error);
68 }
69 
70 bool SBCommandInterpreterRunOptions::GetStopOnCrash() const {
71   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreterRunOptions,
72                                    GetStopOnCrash);
73 
74   return m_opaque_up->GetStopOnCrash();
75 }
76 
77 void SBCommandInterpreterRunOptions::SetStopOnCrash(bool stop_on_crash) {
78   LLDB_RECORD_METHOD(void, SBCommandInterpreterRunOptions, SetStopOnCrash,
79                      (bool), stop_on_crash);
80 
81   m_opaque_up->SetStopOnCrash(stop_on_crash);
82 }
83 
84 bool SBCommandInterpreterRunOptions::GetEchoCommands() const {
85   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreterRunOptions,
86                                    GetEchoCommands);
87 
88   return m_opaque_up->GetEchoCommands();
89 }
90 
91 void SBCommandInterpreterRunOptions::SetEchoCommands(bool echo_commands) {
92   LLDB_RECORD_METHOD(void, SBCommandInterpreterRunOptions, SetEchoCommands,
93                      (bool), echo_commands);
94 
95   m_opaque_up->SetEchoCommands(echo_commands);
96 }
97 
98 bool SBCommandInterpreterRunOptions::GetEchoCommentCommands() const {
99   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreterRunOptions,
100                                    GetEchoCommentCommands);
101 
102   return m_opaque_up->GetEchoCommentCommands();
103 }
104 
105 void SBCommandInterpreterRunOptions::SetEchoCommentCommands(bool echo) {
106   LLDB_RECORD_METHOD(void, SBCommandInterpreterRunOptions,
107                      SetEchoCommentCommands, (bool), echo);
108 
109   m_opaque_up->SetEchoCommentCommands(echo);
110 }
111 
112 bool SBCommandInterpreterRunOptions::GetPrintResults() const {
113   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreterRunOptions,
114                                    GetPrintResults);
115 
116   return m_opaque_up->GetPrintResults();
117 }
118 
119 void SBCommandInterpreterRunOptions::SetPrintResults(bool print_results) {
120   LLDB_RECORD_METHOD(void, SBCommandInterpreterRunOptions, SetPrintResults,
121                      (bool), print_results);
122 
123   m_opaque_up->SetPrintResults(print_results);
124 }
125 
126 bool SBCommandInterpreterRunOptions::GetAddToHistory() const {
127   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreterRunOptions,
128                                    GetAddToHistory);
129 
130   return m_opaque_up->GetAddToHistory();
131 }
132 
133 void SBCommandInterpreterRunOptions::SetAddToHistory(bool add_to_history) {
134   LLDB_RECORD_METHOD(void, SBCommandInterpreterRunOptions, SetAddToHistory,
135                      (bool), add_to_history);
136 
137   m_opaque_up->SetAddToHistory(add_to_history);
138 }
139 
140 lldb_private::CommandInterpreterRunOptions *
141 SBCommandInterpreterRunOptions::get() const {
142   return m_opaque_up.get();
143 }
144 
145 lldb_private::CommandInterpreterRunOptions &
146 SBCommandInterpreterRunOptions::ref() const {
147   return *m_opaque_up;
148 }
149 
150 class CommandPluginInterfaceImplementation : public CommandObjectParsed {
151 public:
152   CommandPluginInterfaceImplementation(CommandInterpreter &interpreter,
153                                        const char *name,
154                                        lldb::SBCommandPluginInterface *backend,
155                                        const char *help = nullptr,
156                                        const char *syntax = nullptr,
157                                        uint32_t flags = 0)
158       : CommandObjectParsed(interpreter, name, help, syntax, flags),
159         m_backend(backend) {}
160 
161   bool IsRemovable() const override { return true; }
162 
163 protected:
164   bool DoExecute(Args &command, CommandReturnObject &result) override {
165     SBCommandReturnObject sb_return(&result);
166     SBCommandInterpreter sb_interpreter(&m_interpreter);
167     SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this());
168     bool ret = m_backend->DoExecute(
169         debugger_sb, (char **)command.GetArgumentVector(), sb_return);
170     sb_return.Release();
171     return ret;
172   }
173   std::shared_ptr<lldb::SBCommandPluginInterface> m_backend;
174 };
175 
176 SBCommandInterpreter::SBCommandInterpreter(CommandInterpreter *interpreter)
177     : m_opaque_ptr(interpreter) {
178   LLDB_RECORD_CONSTRUCTOR(SBCommandInterpreter,
179                           (lldb_private::CommandInterpreter *), interpreter);
180 
181   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
182 
183   if (log)
184     log->Printf("SBCommandInterpreter::SBCommandInterpreter (interpreter=%p)"
185                 " => SBCommandInterpreter(%p)",
186                 static_cast<void *>(interpreter),
187                 static_cast<void *>(m_opaque_ptr));
188 }
189 
190 SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs)
191     : m_opaque_ptr(rhs.m_opaque_ptr) {
192   LLDB_RECORD_CONSTRUCTOR(SBCommandInterpreter,
193                           (const lldb::SBCommandInterpreter &), rhs);
194 }
195 
196 SBCommandInterpreter::~SBCommandInterpreter() = default;
197 
198 const SBCommandInterpreter &SBCommandInterpreter::
199 operator=(const SBCommandInterpreter &rhs) {
200   LLDB_RECORD_METHOD(
201       const lldb::SBCommandInterpreter &,
202       SBCommandInterpreter, operator=,(const lldb::SBCommandInterpreter &),
203       rhs);
204 
205   m_opaque_ptr = rhs.m_opaque_ptr;
206   return *this;
207 }
208 
209 bool SBCommandInterpreter::IsValid() const {
210   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreter, IsValid);
211 
212   return m_opaque_ptr != nullptr;
213 }
214 
215 bool SBCommandInterpreter::CommandExists(const char *cmd) {
216   LLDB_RECORD_METHOD(bool, SBCommandInterpreter, CommandExists, (const char *),
217                      cmd);
218 
219   return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->CommandExists(cmd)
220                                           : false);
221 }
222 
223 bool SBCommandInterpreter::AliasExists(const char *cmd) {
224   LLDB_RECORD_METHOD(bool, SBCommandInterpreter, AliasExists, (const char *),
225                      cmd);
226 
227   return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->AliasExists(cmd)
228                                           : false);
229 }
230 
231 bool SBCommandInterpreter::IsActive() {
232   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, IsActive);
233 
234   return (IsValid() ? m_opaque_ptr->IsActive() : false);
235 }
236 
237 bool SBCommandInterpreter::WasInterrupted() const {
238   LLDB_RECORD_METHOD_CONST_NO_ARGS(bool, SBCommandInterpreter, WasInterrupted);
239 
240   return (IsValid() ? m_opaque_ptr->WasInterrupted() : false);
241 }
242 
243 const char *SBCommandInterpreter::GetIOHandlerControlSequence(char ch) {
244   LLDB_RECORD_METHOD(const char *, SBCommandInterpreter,
245                      GetIOHandlerControlSequence, (char), ch);
246 
247   return (IsValid()
248               ? m_opaque_ptr->GetDebugger()
249                     .GetTopIOHandlerControlSequence(ch)
250                     .GetCString()
251               : nullptr);
252 }
253 
254 lldb::ReturnStatus
255 SBCommandInterpreter::HandleCommand(const char *command_line,
256                                     SBCommandReturnObject &result,
257                                     bool add_to_history) {
258   LLDB_RECORD_METHOD(lldb::ReturnStatus, SBCommandInterpreter, HandleCommand,
259                      (const char *, lldb::SBCommandReturnObject &, bool),
260                      command_line, result, add_to_history);
261 
262   SBExecutionContext sb_exe_ctx;
263   return HandleCommand(command_line, sb_exe_ctx, result, add_to_history);
264 }
265 
266 lldb::ReturnStatus SBCommandInterpreter::HandleCommand(
267     const char *command_line, SBExecutionContext &override_context,
268     SBCommandReturnObject &result, bool add_to_history) {
269   LLDB_RECORD_METHOD(lldb::ReturnStatus, SBCommandInterpreter, HandleCommand,
270                      (const char *, lldb::SBExecutionContext &,
271                       lldb::SBCommandReturnObject &, bool),
272                      command_line, override_context, result, add_to_history);
273 
274   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
275 
276   if (log)
277     log->Printf("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", "
278                 "SBCommandReturnObject(%p), add_to_history=%i)",
279                 static_cast<void *>(m_opaque_ptr), command_line,
280                 static_cast<void *>(result.get()), add_to_history);
281 
282   ExecutionContext ctx, *ctx_ptr;
283   if (override_context.get()) {
284     ctx = override_context.get()->Lock(true);
285     ctx_ptr = &ctx;
286   } else
287     ctx_ptr = nullptr;
288 
289   result.Clear();
290   if (command_line && IsValid()) {
291     result.ref().SetInteractive(false);
292     m_opaque_ptr->HandleCommand(command_line,
293                                 add_to_history ? eLazyBoolYes : eLazyBoolNo,
294                                 result.ref(), ctx_ptr);
295   } else {
296     result->AppendError(
297         "SBCommandInterpreter or the command line is not valid");
298     result->SetStatus(eReturnStatusFailed);
299   }
300 
301   // We need to get the value again, in case the command disabled the log!
302   log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API);
303   if (log) {
304     SBStream sstr;
305     result.GetDescription(sstr);
306     log->Printf("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", "
307                 "SBCommandReturnObject(%p): %s, add_to_history=%i) => %i",
308                 static_cast<void *>(m_opaque_ptr), command_line,
309                 static_cast<void *>(result.get()), sstr.GetData(),
310                 add_to_history, result.GetStatus());
311   }
312 
313   return result.GetStatus();
314 }
315 
316 void SBCommandInterpreter::HandleCommandsFromFile(
317     lldb::SBFileSpec &file, lldb::SBExecutionContext &override_context,
318     lldb::SBCommandInterpreterRunOptions &options,
319     lldb::SBCommandReturnObject result) {
320   LLDB_RECORD_METHOD(void, SBCommandInterpreter, HandleCommandsFromFile,
321                      (lldb::SBFileSpec &, lldb::SBExecutionContext &,
322                       lldb::SBCommandInterpreterRunOptions &,
323                       lldb::SBCommandReturnObject),
324                      file, override_context, options, result);
325 
326   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
327 
328   if (log) {
329     SBStream s;
330     file.GetDescription(s);
331     log->Printf("SBCommandInterpreter(%p)::HandleCommandsFromFile "
332                 "(file=\"%s\", SBCommandReturnObject(%p))",
333                 static_cast<void *>(m_opaque_ptr), s.GetData(),
334                 static_cast<void *>(result.get()));
335   }
336 
337   if (!IsValid()) {
338     result->AppendError("SBCommandInterpreter is not valid.");
339     result->SetStatus(eReturnStatusFailed);
340     return;
341   }
342 
343   if (!file.IsValid()) {
344     SBStream s;
345     file.GetDescription(s);
346     result->AppendErrorWithFormat("File is not valid: %s.", s.GetData());
347     result->SetStatus(eReturnStatusFailed);
348   }
349 
350   FileSpec tmp_spec = file.ref();
351   ExecutionContext ctx, *ctx_ptr;
352   if (override_context.get()) {
353     ctx = override_context.get()->Lock(true);
354     ctx_ptr = &ctx;
355   } else
356     ctx_ptr = nullptr;
357 
358   m_opaque_ptr->HandleCommandsFromFile(tmp_spec, ctx_ptr, options.ref(),
359                                        result.ref());
360 }
361 
362 int SBCommandInterpreter::HandleCompletion(
363     const char *current_line, const char *cursor, const char *last_char,
364     int match_start_point, int max_return_elements, SBStringList &matches) {
365   LLDB_RECORD_METHOD(int, SBCommandInterpreter, HandleCompletion,
366                      (const char *, const char *, const char *, int, int,
367                       lldb::SBStringList &),
368                      current_line, cursor, last_char, match_start_point,
369                      max_return_elements, matches);
370 
371   SBStringList dummy_descriptions;
372   return HandleCompletionWithDescriptions(
373       current_line, cursor, last_char, match_start_point, max_return_elements,
374       matches, dummy_descriptions);
375 }
376 
377 int SBCommandInterpreter::HandleCompletionWithDescriptions(
378     const char *current_line, const char *cursor, const char *last_char,
379     int match_start_point, int max_return_elements, SBStringList &matches,
380     SBStringList &descriptions) {
381   LLDB_RECORD_METHOD(int, SBCommandInterpreter,
382                      HandleCompletionWithDescriptions,
383                      (const char *, const char *, const char *, int, int,
384                       lldb::SBStringList &, lldb::SBStringList &),
385                      current_line, cursor, last_char, match_start_point,
386                      max_return_elements, matches, descriptions);
387 
388   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
389   int num_completions = 0;
390 
391   // Sanity check the arguments that are passed in: cursor & last_char have to
392   // be within the current_line.
393   if (current_line == nullptr || cursor == nullptr || last_char == nullptr)
394     return 0;
395 
396   if (cursor < current_line || last_char < current_line)
397     return 0;
398 
399   size_t current_line_size = strlen(current_line);
400   if (cursor - current_line > static_cast<ptrdiff_t>(current_line_size) ||
401       last_char - current_line > static_cast<ptrdiff_t>(current_line_size))
402     return 0;
403 
404   if (log)
405     log->Printf("SBCommandInterpreter(%p)::HandleCompletion "
406                 "(current_line=\"%s\", cursor at: %" PRId64
407                 ", last char at: %" PRId64
408                 ", match_start_point: %d, max_return_elements: %d)",
409                 static_cast<void *>(m_opaque_ptr), current_line,
410                 static_cast<uint64_t>(cursor - current_line),
411                 static_cast<uint64_t>(last_char - current_line),
412                 match_start_point, max_return_elements);
413 
414   if (IsValid()) {
415     lldb_private::StringList lldb_matches, lldb_descriptions;
416     num_completions = m_opaque_ptr->HandleCompletion(
417         current_line, cursor, last_char, match_start_point, max_return_elements,
418         lldb_matches, lldb_descriptions);
419 
420     SBStringList temp_matches_list(&lldb_matches);
421     matches.AppendList(temp_matches_list);
422     SBStringList temp_descriptions_list(&lldb_descriptions);
423     descriptions.AppendList(temp_descriptions_list);
424   }
425   if (log)
426     log->Printf(
427         "SBCommandInterpreter(%p)::HandleCompletion - Found %d completions.",
428         static_cast<void *>(m_opaque_ptr), num_completions);
429 
430   return num_completions;
431 }
432 
433 int SBCommandInterpreter::HandleCompletionWithDescriptions(
434     const char *current_line, uint32_t cursor_pos, int match_start_point,
435     int max_return_elements, SBStringList &matches,
436     SBStringList &descriptions) {
437   LLDB_RECORD_METHOD(int, SBCommandInterpreter,
438                      HandleCompletionWithDescriptions,
439                      (const char *, uint32_t, int, int, lldb::SBStringList &,
440                       lldb::SBStringList &),
441                      current_line, cursor_pos, match_start_point,
442                      max_return_elements, matches, descriptions);
443 
444   const char *cursor = current_line + cursor_pos;
445   const char *last_char = current_line + strlen(current_line);
446   return HandleCompletionWithDescriptions(
447       current_line, cursor, last_char, match_start_point, max_return_elements,
448       matches, descriptions);
449 }
450 
451 int SBCommandInterpreter::HandleCompletion(const char *current_line,
452                                            uint32_t cursor_pos,
453                                            int match_start_point,
454                                            int max_return_elements,
455                                            lldb::SBStringList &matches) {
456   LLDB_RECORD_METHOD(int, SBCommandInterpreter, HandleCompletion,
457                      (const char *, uint32_t, int, int, lldb::SBStringList &),
458                      current_line, cursor_pos, match_start_point,
459                      max_return_elements, matches);
460 
461   const char *cursor = current_line + cursor_pos;
462   const char *last_char = current_line + strlen(current_line);
463   return HandleCompletion(current_line, cursor, last_char, match_start_point,
464                           max_return_elements, matches);
465 }
466 
467 bool SBCommandInterpreter::HasCommands() {
468   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, HasCommands);
469 
470   return (IsValid() ? m_opaque_ptr->HasCommands() : false);
471 }
472 
473 bool SBCommandInterpreter::HasAliases() {
474   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, HasAliases);
475 
476   return (IsValid() ? m_opaque_ptr->HasAliases() : false);
477 }
478 
479 bool SBCommandInterpreter::HasAliasOptions() {
480   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, HasAliasOptions);
481 
482   return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false);
483 }
484 
485 SBProcess SBCommandInterpreter::GetProcess() {
486   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBProcess, SBCommandInterpreter, GetProcess);
487 
488   SBProcess sb_process;
489   ProcessSP process_sp;
490   if (IsValid()) {
491     TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
492     if (target_sp) {
493       std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex());
494       process_sp = target_sp->GetProcessSP();
495       sb_process.SetSP(process_sp);
496     }
497   }
498   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
499 
500   if (log)
501     log->Printf("SBCommandInterpreter(%p)::GetProcess () => SBProcess(%p)",
502                 static_cast<void *>(m_opaque_ptr),
503                 static_cast<void *>(process_sp.get()));
504 
505   return LLDB_RECORD_RESULT(sb_process);
506 }
507 
508 SBDebugger SBCommandInterpreter::GetDebugger() {
509   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBDebugger, SBCommandInterpreter,
510                              GetDebugger);
511 
512   SBDebugger sb_debugger;
513   if (IsValid())
514     sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this());
515   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
516 
517   if (log)
518     log->Printf("SBCommandInterpreter(%p)::GetDebugger () => SBDebugger(%p)",
519                 static_cast<void *>(m_opaque_ptr),
520                 static_cast<void *>(sb_debugger.get()));
521 
522   return LLDB_RECORD_RESULT(sb_debugger);
523 }
524 
525 bool SBCommandInterpreter::GetPromptOnQuit() {
526   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, GetPromptOnQuit);
527 
528   return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false);
529 }
530 
531 void SBCommandInterpreter::SetPromptOnQuit(bool b) {
532   LLDB_RECORD_METHOD(void, SBCommandInterpreter, SetPromptOnQuit, (bool), b);
533 
534   if (IsValid())
535     m_opaque_ptr->SetPromptOnQuit(b);
536 }
537 
538 void SBCommandInterpreter::AllowExitCodeOnQuit(bool allow) {
539   LLDB_RECORD_METHOD(void, SBCommandInterpreter, AllowExitCodeOnQuit, (bool),
540                      allow);
541 
542   if (m_opaque_ptr)
543     m_opaque_ptr->AllowExitCodeOnQuit(allow);
544 }
545 
546 bool SBCommandInterpreter::HasCustomQuitExitCode() {
547   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommandInterpreter, HasCustomQuitExitCode);
548 
549   bool exited = false;
550   if (m_opaque_ptr)
551     m_opaque_ptr->GetQuitExitCode(exited);
552   return exited;
553 }
554 
555 int SBCommandInterpreter::GetQuitStatus() {
556   LLDB_RECORD_METHOD_NO_ARGS(int, SBCommandInterpreter, GetQuitStatus);
557 
558   bool exited = false;
559   return (m_opaque_ptr ? m_opaque_ptr->GetQuitExitCode(exited) : 0);
560 }
561 
562 void SBCommandInterpreter::ResolveCommand(const char *command_line,
563                                           SBCommandReturnObject &result) {
564   LLDB_RECORD_METHOD(void, SBCommandInterpreter, ResolveCommand,
565                      (const char *, lldb::SBCommandReturnObject &),
566                      command_line, result);
567 
568   result.Clear();
569   if (command_line && IsValid()) {
570     m_opaque_ptr->ResolveCommand(command_line, result.ref());
571   } else {
572     result->AppendError(
573         "SBCommandInterpreter or the command line is not valid");
574     result->SetStatus(eReturnStatusFailed);
575   }
576 }
577 
578 CommandInterpreter *SBCommandInterpreter::get() { return m_opaque_ptr; }
579 
580 CommandInterpreter &SBCommandInterpreter::ref() {
581   assert(m_opaque_ptr);
582   return *m_opaque_ptr;
583 }
584 
585 void SBCommandInterpreter::reset(
586     lldb_private::CommandInterpreter *interpreter) {
587   m_opaque_ptr = interpreter;
588 }
589 
590 void SBCommandInterpreter::SourceInitFileInHomeDirectory(
591     SBCommandReturnObject &result) {
592   LLDB_RECORD_METHOD(void, SBCommandInterpreter, SourceInitFileInHomeDirectory,
593                      (lldb::SBCommandReturnObject &), result);
594 
595   result.Clear();
596   if (IsValid()) {
597     TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
598     std::unique_lock<std::recursive_mutex> lock;
599     if (target_sp)
600       lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
601     m_opaque_ptr->SourceInitFile(false, result.ref());
602   } else {
603     result->AppendError("SBCommandInterpreter is not valid");
604     result->SetStatus(eReturnStatusFailed);
605   }
606   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
607 
608   if (log)
609     log->Printf("SBCommandInterpreter(%p)::SourceInitFileInHomeDirectory "
610                 "(&SBCommandReturnObject(%p))",
611                 static_cast<void *>(m_opaque_ptr),
612                 static_cast<void *>(result.get()));
613 }
614 
615 void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory(
616     SBCommandReturnObject &result) {
617   LLDB_RECORD_METHOD(void, SBCommandInterpreter,
618                      SourceInitFileInCurrentWorkingDirectory,
619                      (lldb::SBCommandReturnObject &), result);
620 
621   result.Clear();
622   if (IsValid()) {
623     TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget());
624     std::unique_lock<std::recursive_mutex> lock;
625     if (target_sp)
626       lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex());
627     m_opaque_ptr->SourceInitFile(true, result.ref());
628   } else {
629     result->AppendError("SBCommandInterpreter is not valid");
630     result->SetStatus(eReturnStatusFailed);
631   }
632   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
633 
634   if (log)
635     log->Printf(
636         "SBCommandInterpreter(%p)::SourceInitFileInCurrentWorkingDirectory "
637         "(&SBCommandReturnObject(%p))",
638         static_cast<void *>(m_opaque_ptr), static_cast<void *>(result.get()));
639 }
640 
641 SBBroadcaster SBCommandInterpreter::GetBroadcaster() {
642   LLDB_RECORD_METHOD_NO_ARGS(lldb::SBBroadcaster, SBCommandInterpreter,
643                              GetBroadcaster);
644 
645   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
646 
647   SBBroadcaster broadcaster(m_opaque_ptr, false);
648 
649   if (log)
650     log->Printf(
651         "SBCommandInterpreter(%p)::GetBroadcaster() => SBBroadcaster(%p)",
652         static_cast<void *>(m_opaque_ptr),
653         static_cast<void *>(broadcaster.get()));
654 
655   return LLDB_RECORD_RESULT(broadcaster);
656 }
657 
658 const char *SBCommandInterpreter::GetBroadcasterClass() {
659   LLDB_RECORD_STATIC_METHOD_NO_ARGS(const char *, SBCommandInterpreter,
660                                     GetBroadcasterClass);
661 
662   return CommandInterpreter::GetStaticBroadcasterClass().AsCString();
663 }
664 
665 const char *SBCommandInterpreter::GetArgumentTypeAsCString(
666     const lldb::CommandArgumentType arg_type) {
667   LLDB_RECORD_STATIC_METHOD(const char *, SBCommandInterpreter,
668                             GetArgumentTypeAsCString,
669                             (const lldb::CommandArgumentType), arg_type);
670 
671   return CommandObject::GetArgumentTypeAsCString(arg_type);
672 }
673 
674 const char *SBCommandInterpreter::GetArgumentDescriptionAsCString(
675     const lldb::CommandArgumentType arg_type) {
676   LLDB_RECORD_STATIC_METHOD(const char *, SBCommandInterpreter,
677                             GetArgumentDescriptionAsCString,
678                             (const lldb::CommandArgumentType), arg_type);
679 
680   return CommandObject::GetArgumentDescriptionAsCString(arg_type);
681 }
682 
683 bool SBCommandInterpreter::EventIsCommandInterpreterEvent(
684     const lldb::SBEvent &event) {
685   LLDB_RECORD_STATIC_METHOD(bool, SBCommandInterpreter,
686                             EventIsCommandInterpreterEvent,
687                             (const lldb::SBEvent &), event);
688 
689   return event.GetBroadcasterClass() ==
690          SBCommandInterpreter::GetBroadcasterClass();
691 }
692 
693 bool SBCommandInterpreter::SetCommandOverrideCallback(
694     const char *command_name, lldb::CommandOverrideCallback callback,
695     void *baton) {
696   if (command_name && command_name[0] && IsValid()) {
697     llvm::StringRef command_name_str = command_name;
698     CommandObject *cmd_obj =
699         m_opaque_ptr->GetCommandObjectForCommand(command_name_str);
700     if (cmd_obj) {
701       assert(command_name_str.empty());
702       cmd_obj->SetOverrideCallback(callback, baton);
703       return true;
704     }
705   }
706   return false;
707 }
708 
709 lldb::SBCommand SBCommandInterpreter::AddMultiwordCommand(const char *name,
710                                                           const char *help) {
711   LLDB_RECORD_METHOD(lldb::SBCommand, SBCommandInterpreter, AddMultiwordCommand,
712                      (const char *, const char *), name, help);
713 
714   CommandObjectMultiword *new_command =
715       new CommandObjectMultiword(*m_opaque_ptr, name, help);
716   new_command->SetRemovable(true);
717   lldb::CommandObjectSP new_command_sp(new_command);
718   if (new_command_sp &&
719       m_opaque_ptr->AddUserCommand(name, new_command_sp, true))
720     return LLDB_RECORD_RESULT(lldb::SBCommand(new_command_sp));
721   return LLDB_RECORD_RESULT(lldb::SBCommand());
722 }
723 
724 lldb::SBCommand SBCommandInterpreter::AddCommand(
725     const char *name, lldb::SBCommandPluginInterface *impl, const char *help) {
726   LLDB_RECORD_METHOD(
727       lldb::SBCommand, SBCommandInterpreter, AddCommand,
728       (const char *, lldb::SBCommandPluginInterface *, const char *), name,
729       impl, help);
730 
731   lldb::CommandObjectSP new_command_sp;
732   new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>(
733       *m_opaque_ptr, name, impl, help);
734 
735   if (new_command_sp &&
736       m_opaque_ptr->AddUserCommand(name, new_command_sp, true))
737     return LLDB_RECORD_RESULT(lldb::SBCommand(new_command_sp));
738   return LLDB_RECORD_RESULT(lldb::SBCommand());
739 }
740 
741 lldb::SBCommand
742 SBCommandInterpreter::AddCommand(const char *name,
743                                  lldb::SBCommandPluginInterface *impl,
744                                  const char *help, const char *syntax) {
745   LLDB_RECORD_METHOD(lldb::SBCommand, SBCommandInterpreter, AddCommand,
746                      (const char *, lldb::SBCommandPluginInterface *,
747                       const char *, const char *),
748                      name, impl, help, syntax);
749 
750   lldb::CommandObjectSP new_command_sp;
751   new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>(
752       *m_opaque_ptr, name, impl, help, syntax);
753 
754   if (new_command_sp &&
755       m_opaque_ptr->AddUserCommand(name, new_command_sp, true))
756     return LLDB_RECORD_RESULT(lldb::SBCommand(new_command_sp));
757   return LLDB_RECORD_RESULT(lldb::SBCommand());
758 }
759 
760 SBCommand::SBCommand() { LLDB_RECORD_CONSTRUCTOR_NO_ARGS(SBCommand); }
761 
762 SBCommand::SBCommand(lldb::CommandObjectSP cmd_sp) : m_opaque_sp(cmd_sp) {}
763 
764 bool SBCommand::IsValid() {
765   LLDB_RECORD_METHOD_NO_ARGS(bool, SBCommand, IsValid);
766 
767   return m_opaque_sp.get() != nullptr;
768 }
769 
770 const char *SBCommand::GetName() {
771   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommand, GetName);
772 
773   return (IsValid() ? ConstString(m_opaque_sp->GetCommandName()).AsCString() : nullptr);
774 }
775 
776 const char *SBCommand::GetHelp() {
777   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommand, GetHelp);
778 
779   return (IsValid() ? ConstString(m_opaque_sp->GetHelp()).AsCString()
780                     : nullptr);
781 }
782 
783 const char *SBCommand::GetHelpLong() {
784   LLDB_RECORD_METHOD_NO_ARGS(const char *, SBCommand, GetHelpLong);
785 
786   return (IsValid() ? ConstString(m_opaque_sp->GetHelpLong()).AsCString()
787                     : nullptr);
788 }
789 
790 void SBCommand::SetHelp(const char *help) {
791   LLDB_RECORD_METHOD(void, SBCommand, SetHelp, (const char *), help);
792 
793   if (IsValid())
794     m_opaque_sp->SetHelp(help);
795 }
796 
797 void SBCommand::SetHelpLong(const char *help) {
798   LLDB_RECORD_METHOD(void, SBCommand, SetHelpLong, (const char *), help);
799 
800   if (IsValid())
801     m_opaque_sp->SetHelpLong(help);
802 }
803 
804 lldb::SBCommand SBCommand::AddMultiwordCommand(const char *name,
805                                                const char *help) {
806   LLDB_RECORD_METHOD(lldb::SBCommand, SBCommand, AddMultiwordCommand,
807                      (const char *, const char *), name, help);
808 
809   if (!IsValid())
810     return LLDB_RECORD_RESULT(lldb::SBCommand());
811   if (!m_opaque_sp->IsMultiwordObject())
812     return LLDB_RECORD_RESULT(lldb::SBCommand());
813   CommandObjectMultiword *new_command = new CommandObjectMultiword(
814       m_opaque_sp->GetCommandInterpreter(), name, help);
815   new_command->SetRemovable(true);
816   lldb::CommandObjectSP new_command_sp(new_command);
817   if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp))
818     return LLDB_RECORD_RESULT(lldb::SBCommand(new_command_sp));
819   return LLDB_RECORD_RESULT(lldb::SBCommand());
820 }
821 
822 lldb::SBCommand SBCommand::AddCommand(const char *name,
823                                       lldb::SBCommandPluginInterface *impl,
824                                       const char *help) {
825   LLDB_RECORD_METHOD(
826       lldb::SBCommand, SBCommand, AddCommand,
827       (const char *, lldb::SBCommandPluginInterface *, const char *), name,
828       impl, help);
829 
830   if (!IsValid())
831     return LLDB_RECORD_RESULT(lldb::SBCommand());
832   if (!m_opaque_sp->IsMultiwordObject())
833     return LLDB_RECORD_RESULT(lldb::SBCommand());
834   lldb::CommandObjectSP new_command_sp;
835   new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>(
836       m_opaque_sp->GetCommandInterpreter(), name, impl, help);
837   if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp))
838     return LLDB_RECORD_RESULT(lldb::SBCommand(new_command_sp));
839   return LLDB_RECORD_RESULT(lldb::SBCommand());
840 }
841 
842 lldb::SBCommand SBCommand::AddCommand(const char *name,
843                                       lldb::SBCommandPluginInterface *impl,
844                                       const char *help, const char *syntax) {
845   LLDB_RECORD_METHOD(lldb::SBCommand, SBCommand, AddCommand,
846                      (const char *, lldb::SBCommandPluginInterface *,
847                       const char *, const char *),
848                      name, impl, help, syntax);
849 
850   if (!IsValid())
851     return LLDB_RECORD_RESULT(lldb::SBCommand());
852   if (!m_opaque_sp->IsMultiwordObject())
853     return LLDB_RECORD_RESULT(lldb::SBCommand());
854   lldb::CommandObjectSP new_command_sp;
855   new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>(
856       m_opaque_sp->GetCommandInterpreter(), name, impl, help, syntax);
857   if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp))
858     return LLDB_RECORD_RESULT(lldb::SBCommand(new_command_sp));
859   return LLDB_RECORD_RESULT(lldb::SBCommand());
860 }
861 
862 uint32_t SBCommand::GetFlags() {
863   LLDB_RECORD_METHOD_NO_ARGS(uint32_t, SBCommand, GetFlags);
864 
865   return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0);
866 }
867 
868 void SBCommand::SetFlags(uint32_t flags) {
869   LLDB_RECORD_METHOD(void, SBCommand, SetFlags, (uint32_t), flags);
870 
871   if (IsValid())
872     m_opaque_sp->GetFlags().Set(flags);
873 }
874