1 //===-- SBCommandInterpreter.cpp --------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 // C Includes 11 // C++ Includes 12 // Other libraries and framework includes 13 // Project includes 14 #include "lldb/lldb-types.h" 15 16 #include "lldb/Core/Listener.h" 17 #include "lldb/Interpreter/CommandInterpreter.h" 18 #include "lldb/Interpreter/CommandObjectMultiword.h" 19 #include "lldb/Interpreter/CommandReturnObject.h" 20 #include "lldb/Target/Target.h" 21 22 #include "lldb/API/SBBroadcaster.h" 23 #include "lldb/API/SBCommandReturnObject.h" 24 #include "lldb/API/SBCommandInterpreter.h" 25 #include "lldb/API/SBEvent.h" 26 #include "lldb/API/SBExecutionContext.h" 27 #include "lldb/API/SBProcess.h" 28 #include "lldb/API/SBTarget.h" 29 #include "lldb/API/SBListener.h" 30 #include "lldb/API/SBStream.h" 31 #include "lldb/API/SBStringList.h" 32 33 using namespace lldb; 34 using namespace lldb_private; 35 36 SBCommandInterpreterRunOptions::SBCommandInterpreterRunOptions() 37 { 38 m_opaque_up.reset(new CommandInterpreterRunOptions()); 39 } 40 41 SBCommandInterpreterRunOptions::~SBCommandInterpreterRunOptions() = default; 42 43 bool 44 SBCommandInterpreterRunOptions::GetStopOnContinue () const 45 { 46 return m_opaque_up->GetStopOnContinue(); 47 } 48 49 void 50 SBCommandInterpreterRunOptions::SetStopOnContinue (bool stop_on_continue) 51 { 52 m_opaque_up->SetStopOnContinue(stop_on_continue); 53 } 54 55 bool 56 SBCommandInterpreterRunOptions::GetStopOnError () const 57 { 58 return m_opaque_up->GetStopOnError(); 59 } 60 61 void 62 SBCommandInterpreterRunOptions::SetStopOnError (bool stop_on_error) 63 { 64 m_opaque_up->SetStopOnError(stop_on_error); 65 } 66 67 bool 68 SBCommandInterpreterRunOptions::GetStopOnCrash () const 69 { 70 return m_opaque_up->GetStopOnCrash(); 71 } 72 73 void 74 SBCommandInterpreterRunOptions::SetStopOnCrash (bool stop_on_crash) 75 { 76 m_opaque_up->SetStopOnCrash(stop_on_crash); 77 } 78 79 bool 80 SBCommandInterpreterRunOptions::GetEchoCommands () const 81 { 82 return m_opaque_up->GetEchoCommands(); 83 } 84 85 void 86 SBCommandInterpreterRunOptions::SetEchoCommands (bool echo_commands) 87 { 88 m_opaque_up->SetEchoCommands(echo_commands); 89 } 90 91 bool 92 SBCommandInterpreterRunOptions::GetPrintResults () const 93 { 94 return m_opaque_up->GetPrintResults(); 95 } 96 97 void 98 SBCommandInterpreterRunOptions::SetPrintResults (bool print_results) 99 { 100 m_opaque_up->SetPrintResults(print_results); 101 } 102 103 bool 104 SBCommandInterpreterRunOptions::GetAddToHistory () const 105 { 106 return m_opaque_up->GetAddToHistory(); 107 } 108 109 void 110 SBCommandInterpreterRunOptions::SetAddToHistory (bool add_to_history) 111 { 112 m_opaque_up->SetAddToHistory(add_to_history); 113 } 114 115 lldb_private::CommandInterpreterRunOptions * 116 SBCommandInterpreterRunOptions::get () const 117 { 118 return m_opaque_up.get(); 119 } 120 121 lldb_private::CommandInterpreterRunOptions & 122 SBCommandInterpreterRunOptions::ref () const 123 { 124 return *m_opaque_up.get(); 125 } 126 127 class CommandPluginInterfaceImplementation : public CommandObjectParsed 128 { 129 public: 130 CommandPluginInterfaceImplementation(CommandInterpreter &interpreter, 131 const char *name, 132 lldb::SBCommandPluginInterface* backend, 133 const char *help = nullptr, 134 const char *syntax = nullptr, 135 uint32_t flags = 0) : 136 CommandObjectParsed (interpreter, name, help, syntax, flags), 137 m_backend(backend) {} 138 139 bool 140 IsRemovable() const override 141 { 142 return true; 143 } 144 145 protected: 146 bool 147 DoExecute(Args& command, CommandReturnObject &result) override 148 { 149 SBCommandReturnObject sb_return(&result); 150 SBCommandInterpreter sb_interpreter(&m_interpreter); 151 SBDebugger debugger_sb(m_interpreter.GetDebugger().shared_from_this()); 152 bool ret = m_backend->DoExecute (debugger_sb,(char**)command.GetArgumentVector(), sb_return); 153 sb_return.Release(); 154 return ret; 155 } 156 lldb::SBCommandPluginInterface* m_backend; 157 }; 158 159 SBCommandInterpreter::SBCommandInterpreter (CommandInterpreter *interpreter) : 160 m_opaque_ptr (interpreter) 161 { 162 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 163 164 if (log) 165 log->Printf ("SBCommandInterpreter::SBCommandInterpreter (interpreter=%p)" 166 " => SBCommandInterpreter(%p)", 167 static_cast<void*>(interpreter), 168 static_cast<void*>(m_opaque_ptr)); 169 } 170 171 SBCommandInterpreter::SBCommandInterpreter(const SBCommandInterpreter &rhs) : 172 m_opaque_ptr (rhs.m_opaque_ptr) 173 { 174 } 175 176 SBCommandInterpreter::~SBCommandInterpreter() = default; 177 178 const SBCommandInterpreter & 179 SBCommandInterpreter::operator = (const SBCommandInterpreter &rhs) 180 { 181 m_opaque_ptr = rhs.m_opaque_ptr; 182 return *this; 183 } 184 185 bool 186 SBCommandInterpreter::IsValid() const 187 { 188 return m_opaque_ptr != nullptr; 189 } 190 191 bool 192 SBCommandInterpreter::CommandExists(const char *cmd) 193 { 194 return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->CommandExists(cmd) : false); 195 } 196 197 bool 198 SBCommandInterpreter::AliasExists (const char *cmd) 199 { 200 return (((cmd != nullptr) && IsValid()) ? m_opaque_ptr->AliasExists(cmd) : false); 201 } 202 203 bool 204 SBCommandInterpreter::IsActive() 205 { 206 return (IsValid() ? m_opaque_ptr->IsActive() : false); 207 } 208 209 const char * 210 SBCommandInterpreter::GetIOHandlerControlSequence(char ch) 211 { 212 return (IsValid() ? m_opaque_ptr->GetDebugger().GetTopIOHandlerControlSequence(ch).GetCString() : nullptr); 213 } 214 215 lldb::ReturnStatus 216 SBCommandInterpreter::HandleCommand (const char *command_line, SBCommandReturnObject &result, bool add_to_history) 217 { 218 SBExecutionContext sb_exe_ctx; 219 return HandleCommand (command_line, sb_exe_ctx, result, add_to_history); 220 } 221 222 lldb::ReturnStatus 223 SBCommandInterpreter::HandleCommand (const char *command_line, SBExecutionContext &override_context, SBCommandReturnObject &result, bool add_to_history) 224 { 225 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 226 227 if (log) 228 log->Printf ("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", SBCommandReturnObject(%p), add_to_history=%i)", 229 static_cast<void*>(m_opaque_ptr), command_line, 230 static_cast<void*>(result.get()), add_to_history); 231 232 ExecutionContext ctx, *ctx_ptr; 233 if (override_context.get()) 234 { 235 ctx = override_context.get()->Lock(true); 236 ctx_ptr = &ctx; 237 } 238 else 239 ctx_ptr = nullptr; 240 241 242 result.Clear(); 243 if (command_line && IsValid()) 244 { 245 result.ref().SetInteractive(false); 246 m_opaque_ptr->HandleCommand (command_line, add_to_history ? eLazyBoolYes : eLazyBoolNo, result.ref(), ctx_ptr); 247 } 248 else 249 { 250 result->AppendError ("SBCommandInterpreter or the command line is not valid"); 251 result->SetStatus (eReturnStatusFailed); 252 } 253 254 // We need to get the value again, in case the command disabled the log! 255 log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API); 256 if (log) 257 { 258 SBStream sstr; 259 result.GetDescription (sstr); 260 log->Printf ("SBCommandInterpreter(%p)::HandleCommand (command=\"%s\", SBCommandReturnObject(%p): %s, add_to_history=%i) => %i", 261 static_cast<void*>(m_opaque_ptr), command_line, 262 static_cast<void*>(result.get()), sstr.GetData(), 263 add_to_history, result.GetStatus()); 264 } 265 266 return result.GetStatus(); 267 } 268 269 void 270 SBCommandInterpreter::HandleCommandsFromFile (lldb::SBFileSpec &file, 271 lldb::SBExecutionContext &override_context, 272 lldb::SBCommandInterpreterRunOptions &options, 273 lldb::SBCommandReturnObject result) 274 { 275 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 276 277 if (log) 278 { 279 SBStream s; 280 file.GetDescription (s); 281 log->Printf ("SBCommandInterpreter(%p)::HandleCommandsFromFile (file=\"%s\", SBCommandReturnObject(%p))", 282 static_cast<void*>(m_opaque_ptr), s.GetData(), 283 static_cast<void*>(result.get())); 284 } 285 286 if (!IsValid()) 287 { 288 result->AppendError ("SBCommandInterpreter is not valid."); 289 result->SetStatus (eReturnStatusFailed); 290 return; 291 } 292 293 if (!file.IsValid()) 294 { 295 SBStream s; 296 file.GetDescription (s); 297 result->AppendErrorWithFormat ("File is not valid: %s.", s.GetData()); 298 result->SetStatus (eReturnStatusFailed); 299 } 300 301 FileSpec tmp_spec = file.ref(); 302 ExecutionContext ctx, *ctx_ptr; 303 if (override_context.get()) 304 { 305 ctx = override_context.get()->Lock(true); 306 ctx_ptr = &ctx; 307 } 308 else 309 ctx_ptr = nullptr; 310 311 m_opaque_ptr->HandleCommandsFromFile (tmp_spec, ctx_ptr, options.ref(), result.ref()); 312 } 313 314 int 315 SBCommandInterpreter::HandleCompletion (const char *current_line, 316 const char *cursor, 317 const char *last_char, 318 int match_start_point, 319 int max_return_elements, 320 SBStringList &matches) 321 { 322 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 323 int num_completions = 0; 324 325 // Sanity check the arguments that are passed in: 326 // cursor & last_char have to be within the current_line. 327 if (current_line == nullptr || cursor == nullptr || last_char == nullptr) 328 return 0; 329 330 if (cursor < current_line || last_char < current_line) 331 return 0; 332 333 size_t current_line_size = strlen (current_line); 334 if (cursor - current_line > static_cast<ptrdiff_t>(current_line_size) || 335 last_char - current_line > static_cast<ptrdiff_t>(current_line_size)) 336 return 0; 337 338 if (log) 339 log->Printf ("SBCommandInterpreter(%p)::HandleCompletion (current_line=\"%s\", cursor at: %" PRId64 ", last char at: %" PRId64 ", match_start_point: %d, max_return_elements: %d)", 340 static_cast<void*>(m_opaque_ptr), current_line, 341 static_cast<uint64_t>(cursor - current_line), 342 static_cast<uint64_t>(last_char - current_line), 343 match_start_point, max_return_elements); 344 345 if (IsValid()) 346 { 347 lldb_private::StringList lldb_matches; 348 num_completions = m_opaque_ptr->HandleCompletion(current_line, cursor, last_char, match_start_point, 349 max_return_elements, lldb_matches); 350 351 SBStringList temp_list (&lldb_matches); 352 matches.AppendList (temp_list); 353 } 354 if (log) 355 log->Printf ("SBCommandInterpreter(%p)::HandleCompletion - Found %d completions.", 356 static_cast<void*>(m_opaque_ptr), num_completions); 357 358 return num_completions; 359 } 360 361 int 362 SBCommandInterpreter::HandleCompletion (const char *current_line, 363 uint32_t cursor_pos, 364 int match_start_point, 365 int max_return_elements, 366 lldb::SBStringList &matches) 367 { 368 const char *cursor = current_line + cursor_pos; 369 const char *last_char = current_line + strlen (current_line); 370 return HandleCompletion (current_line, cursor, last_char, match_start_point, max_return_elements, matches); 371 } 372 373 bool 374 SBCommandInterpreter::HasCommands() 375 { 376 return (IsValid() ? m_opaque_ptr->HasCommands() : false); 377 } 378 379 bool 380 SBCommandInterpreter::HasAliases() 381 { 382 return (IsValid() ? m_opaque_ptr->HasAliases() : false); 383 } 384 385 bool 386 SBCommandInterpreter::HasAliasOptions() 387 { 388 return (IsValid() ? m_opaque_ptr->HasAliasOptions() : false); 389 } 390 391 SBProcess 392 SBCommandInterpreter::GetProcess () 393 { 394 SBProcess sb_process; 395 ProcessSP process_sp; 396 if (IsValid()) 397 { 398 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 399 if (target_sp) 400 { 401 Mutex::Locker api_locker(target_sp->GetAPIMutex()); 402 process_sp = target_sp->GetProcessSP(); 403 sb_process.SetSP(process_sp); 404 } 405 } 406 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 407 408 if (log) 409 log->Printf ("SBCommandInterpreter(%p)::GetProcess () => SBProcess(%p)", 410 static_cast<void*>(m_opaque_ptr), 411 static_cast<void*>(process_sp.get())); 412 413 return sb_process; 414 } 415 416 SBDebugger 417 SBCommandInterpreter::GetDebugger () 418 { 419 SBDebugger sb_debugger; 420 if (IsValid()) 421 sb_debugger.reset(m_opaque_ptr->GetDebugger().shared_from_this()); 422 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 423 424 if (log) 425 log->Printf ("SBCommandInterpreter(%p)::GetDebugger () => SBDebugger(%p)", 426 static_cast<void*>(m_opaque_ptr), 427 static_cast<void*>(sb_debugger.get())); 428 429 return sb_debugger; 430 } 431 432 bool 433 SBCommandInterpreter::GetPromptOnQuit() 434 { 435 return (IsValid() ? m_opaque_ptr->GetPromptOnQuit() : false); 436 } 437 438 void 439 SBCommandInterpreter::SetPromptOnQuit (bool b) 440 { 441 if (IsValid()) 442 m_opaque_ptr->SetPromptOnQuit(b); 443 } 444 445 void 446 SBCommandInterpreter::ResolveCommand(const char *command_line, SBCommandReturnObject &result) 447 { 448 result.Clear(); 449 if (command_line && IsValid()) 450 { 451 m_opaque_ptr->ResolveCommand(command_line, result.ref()); 452 } 453 else 454 { 455 result->AppendError("SBCommandInterpreter or the command line is not valid"); 456 result->SetStatus(eReturnStatusFailed); 457 } 458 } 459 460 CommandInterpreter * 461 SBCommandInterpreter::get () 462 { 463 return m_opaque_ptr; 464 } 465 466 CommandInterpreter & 467 SBCommandInterpreter::ref () 468 { 469 assert (m_opaque_ptr); 470 return *m_opaque_ptr; 471 } 472 473 void 474 SBCommandInterpreter::reset (lldb_private::CommandInterpreter *interpreter) 475 { 476 m_opaque_ptr = interpreter; 477 } 478 479 void 480 SBCommandInterpreter::SourceInitFileInHomeDirectory (SBCommandReturnObject &result) 481 { 482 result.Clear(); 483 if (IsValid()) 484 { 485 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 486 Mutex::Locker api_locker; 487 if (target_sp) 488 api_locker.Lock(target_sp->GetAPIMutex()); 489 m_opaque_ptr->SourceInitFile (false, result.ref()); 490 } 491 else 492 { 493 result->AppendError ("SBCommandInterpreter is not valid"); 494 result->SetStatus (eReturnStatusFailed); 495 } 496 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 497 498 if (log) 499 log->Printf ("SBCommandInterpreter(%p)::SourceInitFileInHomeDirectory (&SBCommandReturnObject(%p))", 500 static_cast<void*>(m_opaque_ptr), 501 static_cast<void*>(result.get())); 502 } 503 504 void 505 SBCommandInterpreter::SourceInitFileInCurrentWorkingDirectory (SBCommandReturnObject &result) 506 { 507 result.Clear(); 508 if (IsValid()) 509 { 510 TargetSP target_sp(m_opaque_ptr->GetDebugger().GetSelectedTarget()); 511 Mutex::Locker api_locker; 512 if (target_sp) 513 api_locker.Lock(target_sp->GetAPIMutex()); 514 m_opaque_ptr->SourceInitFile (true, result.ref()); 515 } 516 else 517 { 518 result->AppendError ("SBCommandInterpreter is not valid"); 519 result->SetStatus (eReturnStatusFailed); 520 } 521 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 522 523 if (log) 524 log->Printf ("SBCommandInterpreter(%p)::SourceInitFileInCurrentWorkingDirectory (&SBCommandReturnObject(%p))", 525 static_cast<void*>(m_opaque_ptr), 526 static_cast<void*>(result.get())); 527 } 528 529 SBBroadcaster 530 SBCommandInterpreter::GetBroadcaster () 531 { 532 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_API)); 533 534 SBBroadcaster broadcaster (m_opaque_ptr, false); 535 536 if (log) 537 log->Printf ("SBCommandInterpreter(%p)::GetBroadcaster() => SBBroadcaster(%p)", 538 static_cast<void*>(m_opaque_ptr), static_cast<void*>(broadcaster.get())); 539 540 return broadcaster; 541 } 542 543 const char * 544 SBCommandInterpreter::GetBroadcasterClass () 545 { 546 return CommandInterpreter::GetStaticBroadcasterClass().AsCString(); 547 } 548 549 const char * 550 SBCommandInterpreter::GetArgumentTypeAsCString (const lldb::CommandArgumentType arg_type) 551 { 552 return CommandObject::GetArgumentTypeAsCString (arg_type); 553 } 554 555 const char * 556 SBCommandInterpreter::GetArgumentDescriptionAsCString (const lldb::CommandArgumentType arg_type) 557 { 558 return CommandObject::GetArgumentDescriptionAsCString (arg_type); 559 } 560 561 bool 562 SBCommandInterpreter::EventIsCommandInterpreterEvent (const lldb::SBEvent &event) 563 { 564 return event.GetBroadcasterClass() == SBCommandInterpreter::GetBroadcasterClass(); 565 } 566 567 bool 568 SBCommandInterpreter::SetCommandOverrideCallback (const char *command_name, 569 lldb::CommandOverrideCallback callback, 570 void *baton) 571 { 572 if (command_name && command_name[0] && IsValid()) 573 { 574 std::string command_name_str (command_name); 575 CommandObject *cmd_obj = m_opaque_ptr->GetCommandObjectForCommand(command_name_str); 576 if (cmd_obj) 577 { 578 assert(command_name_str.empty()); 579 cmd_obj->SetOverrideCallback (callback, baton); 580 return true; 581 } 582 } 583 return false; 584 } 585 586 lldb::SBCommand 587 SBCommandInterpreter::AddMultiwordCommand (const char* name, const char* help) 588 { 589 CommandObjectMultiword *new_command = new CommandObjectMultiword(*m_opaque_ptr, name, help); 590 new_command->SetRemovable (true); 591 lldb::CommandObjectSP new_command_sp(new_command); 592 if (new_command_sp && m_opaque_ptr->AddUserCommand(name, new_command_sp, true)) 593 return lldb::SBCommand(new_command_sp); 594 return lldb::SBCommand(); 595 } 596 597 lldb::SBCommand 598 SBCommandInterpreter::AddCommand (const char* name, lldb::SBCommandPluginInterface* impl, const char* help) 599 { 600 lldb::CommandObjectSP new_command_sp; 601 new_command_sp.reset(new CommandPluginInterfaceImplementation(*m_opaque_ptr,name, impl, help)); 602 603 if (new_command_sp && m_opaque_ptr->AddUserCommand(name, new_command_sp, true)) 604 return lldb::SBCommand(new_command_sp); 605 return lldb::SBCommand(); 606 } 607 608 SBCommand::SBCommand() = default; 609 610 SBCommand::SBCommand (lldb::CommandObjectSP cmd_sp) : m_opaque_sp (cmd_sp) 611 {} 612 613 bool 614 SBCommand::IsValid() 615 { 616 return m_opaque_sp.get() != nullptr; 617 } 618 619 const char* 620 SBCommand::GetName() 621 { 622 return (IsValid() ? m_opaque_sp->GetCommandName() : nullptr); 623 } 624 625 const char* 626 SBCommand::GetHelp() 627 { 628 return (IsValid() ? m_opaque_sp->GetHelp() : nullptr); 629 } 630 631 const char* 632 SBCommand::GetHelpLong() 633 { 634 return (IsValid() ? m_opaque_sp->GetHelpLong() : nullptr); 635 } 636 637 void 638 SBCommand::SetHelp (const char* help) 639 { 640 if (IsValid()) 641 m_opaque_sp->SetHelp(help); 642 } 643 644 void 645 SBCommand::SetHelpLong (const char* help) 646 { 647 if (IsValid()) 648 m_opaque_sp->SetHelpLong(help); 649 } 650 651 lldb::SBCommand 652 SBCommand::AddMultiwordCommand (const char* name, const char* help) 653 { 654 if (!IsValid ()) 655 return lldb::SBCommand(); 656 if (!m_opaque_sp->IsMultiwordObject()) 657 return lldb::SBCommand(); 658 CommandObjectMultiword *new_command = new CommandObjectMultiword(m_opaque_sp->GetCommandInterpreter(),name,help); 659 new_command->SetRemovable (true); 660 lldb::CommandObjectSP new_command_sp(new_command); 661 if (new_command_sp && m_opaque_sp->LoadSubCommand(name,new_command_sp)) 662 return lldb::SBCommand(new_command_sp); 663 return lldb::SBCommand(); 664 } 665 666 lldb::SBCommand 667 SBCommand::AddCommand (const char* name, lldb::SBCommandPluginInterface *impl, const char* help) 668 { 669 if (!IsValid ()) 670 return lldb::SBCommand(); 671 if (!m_opaque_sp->IsMultiwordObject()) 672 return lldb::SBCommand(); 673 lldb::CommandObjectSP new_command_sp; 674 new_command_sp.reset(new CommandPluginInterfaceImplementation(m_opaque_sp->GetCommandInterpreter(),name,impl,help)); 675 if (new_command_sp && m_opaque_sp->LoadSubCommand(name,new_command_sp)) 676 return lldb::SBCommand(new_command_sp); 677 return lldb::SBCommand(); 678 } 679 680 uint32_t 681 SBCommand::GetFlags () 682 { 683 return (IsValid() ? m_opaque_sp->GetFlags().Get() : 0); 684 } 685 686 void 687 SBCommand::SetFlags (uint32_t flags) 688 { 689 if (IsValid()) 690 m_opaque_sp->GetFlags().Set(flags); 691 } 692