1 //===-- SBCommandInterpreter.cpp ------------------------------------------===// 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/Utility/StructuredData.h" 10 #include "lldb/lldb-types.h" 11 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/Instrumentation.h" 17 #include "lldb/Utility/Listener.h" 18 19 #include "lldb/API/SBBroadcaster.h" 20 #include "lldb/API/SBCommandInterpreter.h" 21 #include "lldb/API/SBCommandInterpreterRunOptions.h" 22 #include "lldb/API/SBCommandReturnObject.h" 23 #include "lldb/API/SBEvent.h" 24 #include "lldb/API/SBExecutionContext.h" 25 #include "lldb/API/SBListener.h" 26 #include "lldb/API/SBProcess.h" 27 #include "lldb/API/SBStream.h" 28 #include "lldb/API/SBStringList.h" 29 #include "lldb/API/SBTarget.h" 30 31 #include <memory> 32 #include <optional> 33 34 using namespace lldb; 35 using namespace lldb_private; 36 37 namespace lldb_private { 38 class CommandPluginInterfaceImplementation : public CommandObjectParsed { 39 public: CommandPluginInterfaceImplementation(CommandInterpreter & interpreter,const char * name,lldb::SBCommandPluginInterface * backend,const char * help=nullptr,const char * syntax=nullptr,uint32_t flags=0,const char * auto_repeat_command="")40 CommandPluginInterfaceImplementation(CommandInterpreter &interpreter, 41 const char *name, 42 lldb::SBCommandPluginInterface *backend, 43 const char *help = nullptr, 44 const char *syntax = nullptr, 45 uint32_t flags = 0, 46 const char *auto_repeat_command = "") 47 : CommandObjectParsed(interpreter, name, help, syntax, flags), 48 m_backend(backend) { 49 m_auto_repeat_command = 50 auto_repeat_command == nullptr 51 ? std::nullopt 52 : std::optional<std::string>(auto_repeat_command); 53 // We don't know whether any given command coming from this interface takes 54 // arguments or not so here we're just disabling the basic args check. 55 CommandArgumentData none_arg{eArgTypeNone, eArgRepeatStar}; 56 m_arguments.push_back({none_arg}); 57 } 58 IsRemovable() const59 bool IsRemovable() const override { return true; } 60 61 /// More documentation is available in lldb::CommandObject::GetRepeatCommand, 62 /// but in short, if std::nullopt is returned, the previous command will be 63 /// repeated, and if an empty string is returned, no commands will be 64 /// executed. GetRepeatCommand(Args & current_command_args,uint32_t index)65 std::optional<std::string> GetRepeatCommand(Args ¤t_command_args, 66 uint32_t index) override { 67 if (!m_auto_repeat_command) 68 return std::nullopt; 69 else 70 return m_auto_repeat_command; 71 } 72 73 protected: DoExecute(Args & command,CommandReturnObject & result)74 void DoExecute(Args &command, CommandReturnObject &result) override { 75 SBCommandReturnObject sb_return(result); 76 SBCommandInterpreter sb_interpreter(&m_interpreter); 77 SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this()); 78 m_backend->DoExecute(debugger_sb, command.GetArgumentVector(), sb_return); 79 } 80 std::shared_ptr<lldb::SBCommandPluginInterface> m_backend; 81 std::optional<std::string> m_auto_repeat_command; 82 }; 83 } // namespace lldb_private 84 SBCommandInterpreter()85 SBCommandInterpreter::SBCommandInterpreter() : m_opaque_ptr() { 86 LLDB_INSTRUMENT_VA(this); 87 } 88 SBCommandInterpreter(CommandInterpreter * interpreter)89 SBCommandInterpreter::SBCommandInterpreter(CommandInterpreter *interpreter) 90 : m_opaque_ptr(interpreter) { 91 LLDB_INSTRUMENT_VA(this, interpreter); 92 } 93 SBCommandInterpreter(const SBCommandInterpreter & rhs)94 SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs) 95 : m_opaque_ptr(rhs.m_opaque_ptr) { 96 LLDB_INSTRUMENT_VA(this, rhs); 97 } 98 99 SBCommandInterpreter::~SBCommandInterpreter() = default; 100 101 const SBCommandInterpreter &SBCommandInterpreter:: operator =(const SBCommandInterpreter & rhs)102 operator=(const SBCommandInterpreter &rhs) { 103 LLDB_INSTRUMENT_VA(this, rhs); 104 105 m_opaque_ptr = rhs.m_opaque_ptr; 106 return *this; 107 } 108 IsValid() const109 bool SBCommandInterpreter::IsValid() const { 110 LLDB_INSTRUMENT_VA(this); 111 return this->operator bool(); 112 } operator bool() const113 SBCommandInterpreter::operator bool() const { 114 LLDB_INSTRUMENT_VA(this); 115 116 return m_opaque_ptr != nullptr; 117 } 118 CommandExists(const char * cmd)119 bool SBCommandInterpreter::CommandExists(const char *cmd) { 120 LLDB_INSTRUMENT_VA(this, cmd); 121 122 return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->CommandExists(cmd) 123 : false); 124 } 125 UserCommandExists(const char * cmd)126 bool SBCommandInterpreter::UserCommandExists(const char *cmd) { 127 LLDB_INSTRUMENT_VA(this, cmd); 128 129 return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->UserCommandExists(cmd) 130 : false); 131 } 132 AliasExists(const char * cmd)133 bool SBCommandInterpreter::AliasExists(const char *cmd) { 134 LLDB_INSTRUMENT_VA(this, cmd); 135 136 return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->AliasExists(cmd) 137 : false); 138 } 139 IsActive()140 bool SBCommandInterpreter::IsActive() { 141 LLDB_INSTRUMENT_VA(this); 142 143 return (IsValid() ? m_opaque_ptr->IsActive() : false); 144 } 145 WasInterrupted() const146 bool SBCommandInterpreter::WasInterrupted() const { 147 LLDB_INSTRUMENT_VA(this); 148 149 return (IsValid() ? m_opaque_ptr->GetDebugger().InterruptRequested() : false); 150 } 151 InterruptCommand()152 bool SBCommandInterpreter::InterruptCommand() { 153 LLDB_INSTRUMENT_VA(this); 154 155 return (IsValid() ? m_opaque_ptr->InterruptCommand() : false); 156 } 157 GetIOHandlerControlSequence(char ch)158 const char *SBCommandInterpreter::GetIOHandlerControlSequence(char ch) { 159 LLDB_INSTRUMENT_VA(this, ch); 160 161 if (!IsValid()) 162 return nullptr; 163 164 return ConstString( 165 m_opaque_ptr->GetDebugger().GetTopIOHandlerControlSequence(ch)) 166 .GetCString(); 167 } 168 169 lldb::ReturnStatus HandleCommand(const char * command_line,SBCommandReturnObject & result,bool add_to_history)170 SBCommandInterpreter::HandleCommand(const char *command_line, 171 SBCommandReturnObject &result, 172 bool add_to_history) { 173 LLDB_INSTRUMENT_VA(this, command_line, result, add_to_history); 174 175 SBExecutionContext sb_exe_ctx; 176 return HandleCommand(command_line, sb_exe_ctx, result, add_to_history); 177 } 178 HandleCommand(const char * command_line,SBExecutionContext & override_context,SBCommandReturnObject & result,bool add_to_history)179 lldb::ReturnStatus SBCommandInterpreter::HandleCommand( 180 const char *command_line, SBExecutionContext &override_context, 181 SBCommandReturnObject &result, bool add_to_history) { 182 LLDB_INSTRUMENT_VA(this, command_line, override_context, result, 183 add_to_history); 184 185 result.Clear(); 186 if (command_line && IsValid()) { 187 result.ref().SetInteractive(false); 188 auto do_add_to_history = add_to_history ? eLazyBoolYes : eLazyBoolNo; 189 if (override_context.get()) 190 m_opaque_ptr->HandleCommand(command_line, do_add_to_history, 191 override_context.get()->Lock(true), 192 result.ref()); 193 else 194 m_opaque_ptr->HandleCommand(command_line, do_add_to_history, 195 result.ref()); 196 } else { 197 result->AppendError( 198 "SBCommandInterpreter or the command line is not valid"); 199 } 200 201 return result.GetStatus(); 202 } 203 HandleCommandsFromFile(lldb::SBFileSpec & file,lldb::SBExecutionContext & override_context,lldb::SBCommandInterpreterRunOptions & options,lldb::SBCommandReturnObject result)204 void SBCommandInterpreter::HandleCommandsFromFile( 205 lldb::SBFileSpec &file, lldb::SBExecutionContext &override_context, 206 lldb::SBCommandInterpreterRunOptions &options, 207 lldb::SBCommandReturnObject result) { 208 LLDB_INSTRUMENT_VA(this, file, override_context, options, result); 209 210 if (!IsValid()) { 211 result->AppendError("SBCommandInterpreter is not valid."); 212 return; 213 } 214 215 if (!file.IsValid()) { 216 SBStream s; 217 file.GetDescription(s); 218 result->AppendErrorWithFormat("File is not valid: %s.", s.GetData()); 219 } 220 221 FileSpec tmp_spec = file.ref(); 222 if (override_context.get()) 223 m_opaque_ptr->HandleCommandsFromFile(tmp_spec, 224 override_context.get()->Lock(true), 225 options.ref(), 226 result.ref()); 227 228 else 229 m_opaque_ptr->HandleCommandsFromFile(tmp_spec, options.ref(), result.ref()); 230 } 231 HandleCompletion(const char * current_line,const char * cursor,const char * last_char,int match_start_point,int max_return_elements,SBStringList & matches)232 int SBCommandInterpreter::HandleCompletion( 233 const char *current_line, const char *cursor, const char *last_char, 234 int match_start_point, int max_return_elements, SBStringList &matches) { 235 LLDB_INSTRUMENT_VA(this, current_line, cursor, last_char, match_start_point, 236 max_return_elements, matches); 237 238 SBStringList dummy_descriptions; 239 return HandleCompletionWithDescriptions( 240 current_line, cursor, last_char, match_start_point, max_return_elements, 241 matches, dummy_descriptions); 242 } 243 HandleCompletionWithDescriptions(const char * current_line,const char * cursor,const char * last_char,int match_start_point,int max_return_elements,SBStringList & matches,SBStringList & descriptions)244 int SBCommandInterpreter::HandleCompletionWithDescriptions( 245 const char *current_line, const char *cursor, const char *last_char, 246 int match_start_point, int max_return_elements, SBStringList &matches, 247 SBStringList &descriptions) { 248 LLDB_INSTRUMENT_VA(this, current_line, cursor, last_char, match_start_point, 249 max_return_elements, matches, descriptions); 250 251 // Sanity check the arguments that are passed in: cursor & last_char have to 252 // be within the current_line. 253 if (current_line == nullptr || cursor == nullptr || last_char == nullptr) 254 return 0; 255 256 if (cursor < current_line || last_char < current_line) 257 return 0; 258 259 size_t current_line_size = strlen(current_line); 260 if (cursor - current_line > static_cast<ptrdiff_t>(current_line_size) || 261 last_char - current_line > static_cast<ptrdiff_t>(current_line_size)) 262 return 0; 263 264 if (!IsValid()) 265 return 0; 266 267 lldb_private::StringList lldb_matches, lldb_descriptions; 268 CompletionResult result; 269 CompletionRequest request(current_line, cursor - current_line, result); 270 m_opaque_ptr->HandleCompletion(request); 271 result.GetMatches(lldb_matches); 272 result.GetDescriptions(lldb_descriptions); 273 274 // Make the result array indexed from 1 again by adding the 'common prefix' 275 // of all completions as element 0. This is done to emulate the old API. 276 if (request.GetParsedLine().GetArgumentCount() == 0) { 277 // If we got an empty string, insert nothing. 278 lldb_matches.InsertStringAtIndex(0, ""); 279 lldb_descriptions.InsertStringAtIndex(0, ""); 280 } else { 281 // Now figure out if there is a common substring, and if so put that in 282 // element 0, otherwise put an empty string in element 0. 283 std::string command_partial_str = request.GetCursorArgumentPrefix().str(); 284 285 std::string common_prefix = lldb_matches.LongestCommonPrefix(); 286 const size_t partial_name_len = command_partial_str.size(); 287 common_prefix.erase(0, partial_name_len); 288 289 // If we matched a unique single command, add a space... Only do this if 290 // the completer told us this was a complete word, however... 291 if (lldb_matches.GetSize() == 1) { 292 char quote_char = request.GetParsedArg().GetQuoteChar(); 293 common_prefix = 294 Args::EscapeLLDBCommandArgument(common_prefix, quote_char); 295 if (request.GetParsedArg().IsQuoted()) 296 common_prefix.push_back(quote_char); 297 common_prefix.push_back(' '); 298 } 299 lldb_matches.InsertStringAtIndex(0, common_prefix.c_str()); 300 lldb_descriptions.InsertStringAtIndex(0, ""); 301 } 302 303 SBStringList temp_matches_list(&lldb_matches); 304 matches.AppendList(temp_matches_list); 305 SBStringList temp_descriptions_list(&lldb_descriptions); 306 descriptions.AppendList(temp_descriptions_list); 307 return result.GetNumberOfResults(); 308 } 309 HandleCompletionWithDescriptions(const char * current_line,uint32_t cursor_pos,int match_start_point,int max_return_elements,SBStringList & matches,SBStringList & descriptions)310 int SBCommandInterpreter::HandleCompletionWithDescriptions( 311 const char *current_line, uint32_t cursor_pos, int match_start_point, 312 int max_return_elements, SBStringList &matches, 313 SBStringList &descriptions) { 314 LLDB_INSTRUMENT_VA(this, current_line, cursor_pos, match_start_point, 315 max_return_elements, matches, descriptions); 316 317 const char *cursor = current_line + cursor_pos; 318 const char *last_char = current_line + strlen(current_line); 319 return HandleCompletionWithDescriptions( 320 current_line, cursor, last_char, match_start_point, max_return_elements, 321 matches, descriptions); 322 } 323 HandleCompletion(const char * current_line,uint32_t cursor_pos,int match_start_point,int max_return_elements,lldb::SBStringList & matches)324 int SBCommandInterpreter::HandleCompletion(const char *current_line, 325 uint32_t cursor_pos, 326 int match_start_point, 327 int max_return_elements, 328 lldb::SBStringList &matches) { 329 LLDB_INSTRUMENT_VA(this, current_line, cursor_pos, match_start_point, 330 max_return_elements, matches); 331 332 const char *cursor = current_line + cursor_pos; 333 const char *last_char = current_line + strlen(current_line); 334 return HandleCompletion(current_line, cursor, last_char, match_start_point, 335 max_return_elements, matches); 336 } 337 HasCommands()338 bool SBCommandInterpreter::HasCommands() { 339 LLDB_INSTRUMENT_VA(this); 340 341 return (IsValid() ? m_opaque_ptr->HasCommands() : false); 342 } 343 HasAliases()344 bool SBCommandInterpreter::HasAliases() { 345 LLDB_INSTRUMENT_VA(this); 346 347 return (IsValid() ? m_opaque_ptr->HasAliases() : false); 348 } 349 HasAliasOptions()350 bool SBCommandInterpreter::HasAliasOptions() { 351 LLDB_INSTRUMENT_VA(this); 352 353 return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false); 354 } 355 IsInteractive()356 bool SBCommandInterpreter::IsInteractive() { 357 LLDB_INSTRUMENT_VA(this); 358 359 return (IsValid() ? m_opaque_ptr->IsInteractive() : false); 360 } 361 GetProcess()362 SBProcess SBCommandInterpreter::GetProcess() { 363 LLDB_INSTRUMENT_VA(this); 364 365 SBProcess sb_process; 366 ProcessSP process_sp; 367 if (IsValid()) { 368 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 369 if (target_sp) { 370 std::lock_guard<std::recursive_mutex> guard(target_sp->GetAPIMutex()); 371 process_sp = target_sp->GetProcessSP(); 372 sb_process.SetSP(process_sp); 373 } 374 } 375 376 return sb_process; 377 } 378 GetDebugger()379 SBDebugger SBCommandInterpreter::GetDebugger() { 380 LLDB_INSTRUMENT_VA(this); 381 382 SBDebugger sb_debugger; 383 if (IsValid()) 384 sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this()); 385 386 return sb_debugger; 387 } 388 GetPromptOnQuit()389 bool SBCommandInterpreter::GetPromptOnQuit() { 390 LLDB_INSTRUMENT_VA(this); 391 392 return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false); 393 } 394 SetPromptOnQuit(bool b)395 void SBCommandInterpreter::SetPromptOnQuit(bool b) { 396 LLDB_INSTRUMENT_VA(this, b); 397 398 if (IsValid()) 399 m_opaque_ptr->SetPromptOnQuit(b); 400 } 401 AllowExitCodeOnQuit(bool allow)402 void SBCommandInterpreter::AllowExitCodeOnQuit(bool allow) { 403 LLDB_INSTRUMENT_VA(this, allow); 404 405 if (m_opaque_ptr) 406 m_opaque_ptr->AllowExitCodeOnQuit(allow); 407 } 408 HasCustomQuitExitCode()409 bool SBCommandInterpreter::HasCustomQuitExitCode() { 410 LLDB_INSTRUMENT_VA(this); 411 412 bool exited = false; 413 if (m_opaque_ptr) 414 m_opaque_ptr->GetQuitExitCode(exited); 415 return exited; 416 } 417 GetQuitStatus()418 int SBCommandInterpreter::GetQuitStatus() { 419 LLDB_INSTRUMENT_VA(this); 420 421 bool exited = false; 422 return (m_opaque_ptr ? m_opaque_ptr->GetQuitExitCode(exited) : 0); 423 } 424 ResolveCommand(const char * command_line,SBCommandReturnObject & result)425 void SBCommandInterpreter::ResolveCommand(const char *command_line, 426 SBCommandReturnObject &result) { 427 LLDB_INSTRUMENT_VA(this, command_line, result); 428 429 result.Clear(); 430 if (command_line && IsValid()) { 431 m_opaque_ptr->ResolveCommand(command_line, result.ref()); 432 } else { 433 result->AppendError( 434 "SBCommandInterpreter or the command line is not valid"); 435 } 436 } 437 get()438 CommandInterpreter *SBCommandInterpreter::get() { return m_opaque_ptr; } 439 ref()440 CommandInterpreter &SBCommandInterpreter::ref() { 441 assert(m_opaque_ptr); 442 return *m_opaque_ptr; 443 } 444 reset(lldb_private::CommandInterpreter * interpreter)445 void SBCommandInterpreter::reset( 446 lldb_private::CommandInterpreter *interpreter) { 447 m_opaque_ptr = interpreter; 448 } 449 SourceInitFileInGlobalDirectory(SBCommandReturnObject & result)450 void SBCommandInterpreter::SourceInitFileInGlobalDirectory( 451 SBCommandReturnObject &result) { 452 LLDB_INSTRUMENT_VA(this, result); 453 454 result.Clear(); 455 if (IsValid()) { 456 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 457 std::unique_lock<std::recursive_mutex> lock; 458 if (target_sp) 459 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 460 m_opaque_ptr->SourceInitFileGlobal(result.ref()); 461 } else { 462 result->AppendError("SBCommandInterpreter is not valid"); 463 } 464 } 465 SourceInitFileInHomeDirectory(SBCommandReturnObject & result)466 void SBCommandInterpreter::SourceInitFileInHomeDirectory( 467 SBCommandReturnObject &result) { 468 LLDB_INSTRUMENT_VA(this, result); 469 470 SourceInitFileInHomeDirectory(result, /*is_repl=*/false); 471 } 472 SourceInitFileInHomeDirectory(SBCommandReturnObject & result,bool is_repl)473 void SBCommandInterpreter::SourceInitFileInHomeDirectory( 474 SBCommandReturnObject &result, bool is_repl) { 475 LLDB_INSTRUMENT_VA(this, result, is_repl); 476 477 result.Clear(); 478 if (IsValid()) { 479 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 480 std::unique_lock<std::recursive_mutex> lock; 481 if (target_sp) 482 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 483 m_opaque_ptr->SourceInitFileHome(result.ref(), is_repl); 484 } else { 485 result->AppendError("SBCommandInterpreter is not valid"); 486 } 487 } 488 SourceInitFileInCurrentWorkingDirectory(SBCommandReturnObject & result)489 void SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory( 490 SBCommandReturnObject &result) { 491 LLDB_INSTRUMENT_VA(this, result); 492 493 result.Clear(); 494 if (IsValid()) { 495 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 496 std::unique_lock<std::recursive_mutex> lock; 497 if (target_sp) 498 lock = std::unique_lock<std::recursive_mutex>(target_sp->GetAPIMutex()); 499 m_opaque_ptr->SourceInitFileCwd(result.ref()); 500 } else { 501 result->AppendError("SBCommandInterpreter is not valid"); 502 } 503 } 504 GetBroadcaster()505 SBBroadcaster SBCommandInterpreter::GetBroadcaster() { 506 LLDB_INSTRUMENT_VA(this); 507 508 SBBroadcaster broadcaster(m_opaque_ptr, false); 509 510 return broadcaster; 511 } 512 GetBroadcasterClass()513 const char *SBCommandInterpreter::GetBroadcasterClass() { 514 LLDB_INSTRUMENT(); 515 516 return ConstString(CommandInterpreter::GetStaticBroadcasterClass()) 517 .AsCString(); 518 } 519 GetArgumentTypeAsCString(const lldb::CommandArgumentType arg_type)520 const char *SBCommandInterpreter::GetArgumentTypeAsCString( 521 const lldb::CommandArgumentType arg_type) { 522 LLDB_INSTRUMENT_VA(arg_type); 523 524 return ConstString(CommandObject::GetArgumentTypeAsCString(arg_type)) 525 .GetCString(); 526 } 527 GetArgumentDescriptionAsCString(const lldb::CommandArgumentType arg_type)528 const char *SBCommandInterpreter::GetArgumentDescriptionAsCString( 529 const lldb::CommandArgumentType arg_type) { 530 LLDB_INSTRUMENT_VA(arg_type); 531 532 return ConstString(CommandObject::GetArgumentDescriptionAsCString(arg_type)) 533 .GetCString(); 534 } 535 EventIsCommandInterpreterEvent(const lldb::SBEvent & event)536 bool SBCommandInterpreter::EventIsCommandInterpreterEvent( 537 const lldb::SBEvent &event) { 538 LLDB_INSTRUMENT_VA(event); 539 540 return event.GetBroadcasterClass() == 541 SBCommandInterpreter::GetBroadcasterClass(); 542 } 543 SetCommandOverrideCallback(const char * command_name,lldb::CommandOverrideCallback callback,void * baton)544 bool SBCommandInterpreter::SetCommandOverrideCallback( 545 const char *command_name, lldb::CommandOverrideCallback callback, 546 void *baton) { 547 LLDB_INSTRUMENT_VA(this, command_name, callback, baton); 548 549 if (command_name && command_name[0] && IsValid()) { 550 llvm::StringRef command_name_str = command_name; 551 CommandObject *cmd_obj = 552 m_opaque_ptr->GetCommandObjectForCommand(command_name_str); 553 if (cmd_obj) { 554 assert(command_name_str.empty()); 555 cmd_obj->SetOverrideCallback(callback, baton); 556 return true; 557 } 558 } 559 return false; 560 } 561 GetStatistics()562 SBStructuredData SBCommandInterpreter::GetStatistics() { 563 LLDB_INSTRUMENT_VA(this); 564 565 SBStructuredData data; 566 if (!IsValid()) 567 return data; 568 569 std::string json_str = 570 llvm::formatv("{0:2}", m_opaque_ptr->GetStatistics()).str(); 571 data.m_impl_up->SetObjectSP(StructuredData::ParseJSON(json_str)); 572 return data; 573 } 574 GetTranscript()575 SBStructuredData SBCommandInterpreter::GetTranscript() { 576 LLDB_INSTRUMENT_VA(this); 577 578 SBStructuredData data; 579 if (IsValid()) 580 // A deep copy is performed by `std::make_shared` on the 581 // `StructuredData::Array`, via its implicitly-declared copy constructor. 582 // This ensures thread-safety between the user changing the returned 583 // `SBStructuredData` and the `CommandInterpreter` changing its internal 584 // `m_transcript`. 585 data.m_impl_up->SetObjectSP( 586 std::make_shared<StructuredData::Array>(m_opaque_ptr->GetTranscript())); 587 return data; 588 } 589 AddMultiwordCommand(const char * name,const char * help)590 lldb::SBCommand SBCommandInterpreter::AddMultiwordCommand(const char *name, 591 const char *help) { 592 LLDB_INSTRUMENT_VA(this, name, help); 593 594 lldb::CommandObjectSP new_command_sp( 595 new CommandObjectMultiword(*m_opaque_ptr, name, help)); 596 new_command_sp->GetAsMultiwordCommand()->SetRemovable(true); 597 Status add_error = m_opaque_ptr->AddUserCommand(name, new_command_sp, true); 598 if (add_error.Success()) 599 return lldb::SBCommand(new_command_sp); 600 return lldb::SBCommand(); 601 } 602 AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help)603 lldb::SBCommand SBCommandInterpreter::AddCommand( 604 const char *name, lldb::SBCommandPluginInterface *impl, const char *help) { 605 LLDB_INSTRUMENT_VA(this, name, impl, help); 606 607 return AddCommand(name, impl, help, /*syntax=*/nullptr, 608 /*auto_repeat_command=*/""); 609 } 610 611 lldb::SBCommand AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help,const char * syntax)612 SBCommandInterpreter::AddCommand(const char *name, 613 lldb::SBCommandPluginInterface *impl, 614 const char *help, const char *syntax) { 615 LLDB_INSTRUMENT_VA(this, name, impl, help, syntax); 616 return AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/""); 617 } 618 AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help,const char * syntax,const char * auto_repeat_command)619 lldb::SBCommand SBCommandInterpreter::AddCommand( 620 const char *name, lldb::SBCommandPluginInterface *impl, const char *help, 621 const char *syntax, const char *auto_repeat_command) { 622 LLDB_INSTRUMENT_VA(this, name, impl, help, syntax, auto_repeat_command); 623 624 lldb::CommandObjectSP new_command_sp; 625 new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>( 626 *m_opaque_ptr, name, impl, help, syntax, /*flags=*/0, 627 auto_repeat_command); 628 629 Status add_error = m_opaque_ptr->AddUserCommand(name, new_command_sp, true); 630 if (add_error.Success()) 631 return lldb::SBCommand(new_command_sp); 632 return lldb::SBCommand(); 633 } 634 SBCommand()635 SBCommand::SBCommand() { LLDB_INSTRUMENT_VA(this); } 636 SBCommand(lldb::CommandObjectSP cmd_sp)637 SBCommand::SBCommand(lldb::CommandObjectSP cmd_sp) : m_opaque_sp(cmd_sp) {} 638 IsValid()639 bool SBCommand::IsValid() { 640 LLDB_INSTRUMENT_VA(this); 641 return this->operator bool(); 642 } operator bool() const643 SBCommand::operator bool() const { 644 LLDB_INSTRUMENT_VA(this); 645 646 return m_opaque_sp.get() != nullptr; 647 } 648 GetName()649 const char *SBCommand::GetName() { 650 LLDB_INSTRUMENT_VA(this); 651 652 return (IsValid() ? ConstString(m_opaque_sp->GetCommandName()).AsCString() : nullptr); 653 } 654 GetHelp()655 const char *SBCommand::GetHelp() { 656 LLDB_INSTRUMENT_VA(this); 657 658 return (IsValid() ? ConstString(m_opaque_sp->GetHelp()).AsCString() 659 : nullptr); 660 } 661 GetHelpLong()662 const char *SBCommand::GetHelpLong() { 663 LLDB_INSTRUMENT_VA(this); 664 665 return (IsValid() ? ConstString(m_opaque_sp->GetHelpLong()).AsCString() 666 : nullptr); 667 } 668 SetHelp(const char * help)669 void SBCommand::SetHelp(const char *help) { 670 LLDB_INSTRUMENT_VA(this, help); 671 672 if (IsValid()) 673 m_opaque_sp->SetHelp(help); 674 } 675 SetHelpLong(const char * help)676 void SBCommand::SetHelpLong(const char *help) { 677 LLDB_INSTRUMENT_VA(this, help); 678 679 if (IsValid()) 680 m_opaque_sp->SetHelpLong(help); 681 } 682 AddMultiwordCommand(const char * name,const char * help)683 lldb::SBCommand SBCommand::AddMultiwordCommand(const char *name, 684 const char *help) { 685 LLDB_INSTRUMENT_VA(this, name, help); 686 687 if (!IsValid()) 688 return lldb::SBCommand(); 689 if (!m_opaque_sp->IsMultiwordObject()) 690 return lldb::SBCommand(); 691 CommandObjectMultiword *new_command = new CommandObjectMultiword( 692 m_opaque_sp->GetCommandInterpreter(), name, help); 693 new_command->SetRemovable(true); 694 lldb::CommandObjectSP new_command_sp(new_command); 695 if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp)) 696 return lldb::SBCommand(new_command_sp); 697 return lldb::SBCommand(); 698 } 699 AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help)700 lldb::SBCommand SBCommand::AddCommand(const char *name, 701 lldb::SBCommandPluginInterface *impl, 702 const char *help) { 703 LLDB_INSTRUMENT_VA(this, name, impl, help); 704 return AddCommand(name, impl, help, /*syntax=*/nullptr, 705 /*auto_repeat_command=*/""); 706 } 707 AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help,const char * syntax)708 lldb::SBCommand SBCommand::AddCommand(const char *name, 709 lldb::SBCommandPluginInterface *impl, 710 const char *help, const char *syntax) { 711 LLDB_INSTRUMENT_VA(this, name, impl, help, syntax); 712 return AddCommand(name, impl, help, syntax, /*auto_repeat_command=*/""); 713 } 714 AddCommand(const char * name,lldb::SBCommandPluginInterface * impl,const char * help,const char * syntax,const char * auto_repeat_command)715 lldb::SBCommand SBCommand::AddCommand(const char *name, 716 lldb::SBCommandPluginInterface *impl, 717 const char *help, const char *syntax, 718 const char *auto_repeat_command) { 719 LLDB_INSTRUMENT_VA(this, name, impl, help, syntax, auto_repeat_command); 720 721 if (!IsValid()) 722 return lldb::SBCommand(); 723 if (!m_opaque_sp->IsMultiwordObject()) 724 return lldb::SBCommand(); 725 lldb::CommandObjectSP new_command_sp; 726 new_command_sp = std::make_shared<CommandPluginInterfaceImplementation>( 727 m_opaque_sp->GetCommandInterpreter(), name, impl, help, syntax, 728 /*flags=*/0, auto_repeat_command); 729 if (new_command_sp && m_opaque_sp->LoadSubCommand(name, new_command_sp)) 730 return lldb::SBCommand(new_command_sp); 731 return lldb::SBCommand(); 732 } 733 GetFlags()734 uint32_t SBCommand::GetFlags() { 735 LLDB_INSTRUMENT_VA(this); 736 737 return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0); 738 } 739 SetFlags(uint32_t flags)740 void SBCommand::SetFlags(uint32_t flags) { 741 LLDB_INSTRUMENT_VA(this, flags); 742 743 if (IsValid()) 744 m_opaque_sp->GetFlags().Set(flags); 745 } 746