1 //===-- CommandInterpreter.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 #include <string> 11 #include <vector> 12 #include <stdlib.h> 13 14 #include "CommandObjectScript.h" 15 #include "lldb/Interpreter/CommandObjectRegexCommand.h" 16 17 #include "../Commands/CommandObjectApropos.h" 18 #include "../Commands/CommandObjectArgs.h" 19 #include "../Commands/CommandObjectBreakpoint.h" 20 #include "../Commands/CommandObjectBugreport.h" 21 #include "../Commands/CommandObjectDisassemble.h" 22 #include "../Commands/CommandObjectExpression.h" 23 #include "../Commands/CommandObjectFrame.h" 24 #include "../Commands/CommandObjectGUI.h" 25 #include "../Commands/CommandObjectHelp.h" 26 #include "../Commands/CommandObjectLog.h" 27 #include "../Commands/CommandObjectMemory.h" 28 #include "../Commands/CommandObjectPlatform.h" 29 #include "../Commands/CommandObjectPlugin.h" 30 #include "../Commands/CommandObjectProcess.h" 31 #include "../Commands/CommandObjectQuit.h" 32 #include "../Commands/CommandObjectRegister.h" 33 #include "../Commands/CommandObjectSettings.h" 34 #include "../Commands/CommandObjectSource.h" 35 #include "../Commands/CommandObjectCommands.h" 36 #include "../Commands/CommandObjectSyntax.h" 37 #include "../Commands/CommandObjectTarget.h" 38 #include "../Commands/CommandObjectThread.h" 39 #include "../Commands/CommandObjectType.h" 40 #include "../Commands/CommandObjectVersion.h" 41 #include "../Commands/CommandObjectWatchpoint.h" 42 #include "../Commands/CommandObjectLanguage.h" 43 44 #include "lldb/Core/Debugger.h" 45 #include "lldb/Core/Log.h" 46 #include "lldb/Core/PluginManager.h" 47 #include "lldb/Core/State.h" 48 #include "lldb/Core/Stream.h" 49 #include "lldb/Core/StreamFile.h" 50 #include "lldb/Core/Timer.h" 51 52 #ifndef LLDB_DISABLE_LIBEDIT 53 #include "lldb/Host/Editline.h" 54 #endif 55 #include "lldb/Host/Host.h" 56 #include "lldb/Host/HostInfo.h" 57 58 #include "lldb/Interpreter/Args.h" 59 #include "lldb/Interpreter/CommandCompletions.h" 60 #include "lldb/Interpreter/CommandInterpreter.h" 61 #include "lldb/Interpreter/CommandReturnObject.h" 62 #include "lldb/Interpreter/Options.h" 63 #include "lldb/Interpreter/OptionValueProperties.h" 64 #include "lldb/Interpreter/Property.h" 65 66 67 #include "lldb/Target/Process.h" 68 #include "lldb/Target/Thread.h" 69 #include "lldb/Target/TargetList.h" 70 71 #include "lldb/Utility/CleanUp.h" 72 73 #include "llvm/ADT/SmallString.h" 74 #include "llvm/ADT/STLExtras.h" 75 #include "llvm/Support/Path.h" 76 77 using namespace lldb; 78 using namespace lldb_private; 79 80 static const char *k_white_space = " \t\v"; 81 82 static PropertyDefinition 83 g_properties[] = 84 { 85 { "expand-regex-aliases", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, regular expression alias commands will show the expanded command that will be executed. This can be used to debug new regular expression alias commands." }, 86 { "prompt-on-quit", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will prompt you before quitting if there are any live processes being debugged. If false, LLDB will quit without asking in any case." }, 87 { "stop-command-source-on-error", OptionValue::eTypeBoolean, true, true, nullptr, nullptr, "If true, LLDB will stop running a 'command source' script upon encountering an error." }, 88 { "space-repl-prompts", OptionValue::eTypeBoolean, true, false, nullptr, nullptr, "If true, blank lines will be printed between between REPL submissions." }, 89 { nullptr , OptionValue::eTypeInvalid, true, 0 , nullptr, nullptr, nullptr } 90 }; 91 92 enum 93 { 94 ePropertyExpandRegexAliases = 0, 95 ePropertyPromptOnQuit = 1, 96 ePropertyStopCmdSourceOnError = 2, 97 eSpaceReplPrompts = 3 98 }; 99 100 CommandInterpreter::CommandAlias::CommandAlias (lldb::CommandObjectSP cmd_sp, 101 OptionArgVectorSP args_sp) : 102 m_underlying_command_sp(cmd_sp), 103 m_option_args_sp(args_sp) 104 { 105 } 106 107 void 108 CommandInterpreter::CommandAlias::GetAliasHelp (StreamString &help_string) 109 { 110 const char* command_name = m_underlying_command_sp->GetCommandName(); 111 help_string.Printf ("'%s", command_name); 112 113 if (m_option_args_sp) 114 { 115 OptionArgVector *options = m_option_args_sp.get(); 116 for (size_t i = 0; i < options->size(); ++i) 117 { 118 OptionArgPair cur_option = (*options)[i]; 119 std::string opt = cur_option.first; 120 OptionArgValue value_pair = cur_option.second; 121 std::string value = value_pair.second; 122 if (opt.compare("<argument>") == 0) 123 { 124 help_string.Printf (" %s", value.c_str()); 125 } 126 else 127 { 128 help_string.Printf (" %s", opt.c_str()); 129 if ((value.compare ("<no-argument>") != 0) 130 && (value.compare ("<need-argument") != 0)) 131 { 132 help_string.Printf (" %s", value.c_str()); 133 } 134 } 135 } 136 } 137 138 help_string.Printf ("'"); 139 } 140 141 bool 142 CommandInterpreter::CommandAlias::ProcessAliasOptionsArgs (lldb::CommandObjectSP &cmd_obj_sp, 143 const char *options_args, 144 OptionArgVectorSP &option_arg_vector_sp) 145 { 146 bool success = true; 147 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 148 149 if (!options_args || (strlen (options_args) < 1)) 150 return true; 151 152 std::string options_string (options_args); 153 Args args (options_args); 154 CommandReturnObject result; 155 // Check to see if the command being aliased can take any command options. 156 Options *options = cmd_obj_sp->GetOptions (); 157 if (options) 158 { 159 // See if any options were specified as part of the alias; if so, handle them appropriately. 160 options->NotifyOptionParsingStarting (); 161 args.Unshift ("dummy_arg"); 162 args.ParseAliasOptions (*options, result, option_arg_vector, options_string); 163 args.Shift (); 164 if (result.Succeeded()) 165 options->VerifyPartialOptions (result); 166 if (!result.Succeeded() && result.GetStatus() != lldb::eReturnStatusStarted) 167 { 168 result.AppendError ("Unable to create requested alias.\n"); 169 return false; 170 } 171 } 172 173 if (!options_string.empty()) 174 { 175 if (cmd_obj_sp->WantsRawCommandString ()) 176 option_arg_vector->push_back (OptionArgPair ("<argument>", 177 OptionArgValue (-1, 178 options_string))); 179 else 180 { 181 const size_t argc = args.GetArgumentCount(); 182 for (size_t i = 0; i < argc; ++i) 183 if (strcmp (args.GetArgumentAtIndex (i), "") != 0) 184 option_arg_vector->push_back 185 (OptionArgPair ("<argument>", 186 OptionArgValue (-1, 187 std::string (args.GetArgumentAtIndex (i))))); 188 } 189 } 190 191 return success; 192 } 193 194 ConstString & 195 CommandInterpreter::GetStaticBroadcasterClass () 196 { 197 static ConstString class_name ("lldb.commandInterpreter"); 198 return class_name; 199 } 200 201 CommandInterpreter::CommandInterpreter(Debugger &debugger, ScriptLanguage script_language, bool synchronous_execution) 202 : Broadcaster(debugger.GetBroadcasterManager(), CommandInterpreter::GetStaticBroadcasterClass().AsCString()), 203 Properties(OptionValuePropertiesSP(new OptionValueProperties(ConstString("interpreter")))), 204 IOHandlerDelegate(IOHandlerDelegate::Completion::LLDBCommand), 205 m_debugger(debugger), 206 m_synchronous_execution(synchronous_execution), 207 m_skip_lldbinit_files(false), 208 m_skip_app_init_files(false), 209 m_script_interpreter_sp(), 210 m_command_io_handler_sp(), 211 m_comment_char('#'), 212 m_batch_command_mode(false), 213 m_truncation_warning(eNoTruncation), 214 m_command_source_depth(0), 215 m_num_errors(0), 216 m_quit_requested(false), 217 m_stopped_for_crash(false) 218 { 219 debugger.SetScriptLanguage (script_language); 220 SetEventName (eBroadcastBitThreadShouldExit, "thread-should-exit"); 221 SetEventName (eBroadcastBitResetPrompt, "reset-prompt"); 222 SetEventName (eBroadcastBitQuitCommandReceived, "quit"); 223 CheckInWithManager (); 224 m_collection_sp->Initialize (g_properties); 225 } 226 227 bool 228 CommandInterpreter::GetExpandRegexAliases () const 229 { 230 const uint32_t idx = ePropertyExpandRegexAliases; 231 return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); 232 } 233 234 bool 235 CommandInterpreter::GetPromptOnQuit () const 236 { 237 const uint32_t idx = ePropertyPromptOnQuit; 238 return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); 239 } 240 241 void 242 CommandInterpreter::SetPromptOnQuit (bool b) 243 { 244 const uint32_t idx = ePropertyPromptOnQuit; 245 m_collection_sp->SetPropertyAtIndexAsBoolean (nullptr, idx, b); 246 } 247 248 void 249 CommandInterpreter::ResolveCommand(const char *command_line, CommandReturnObject &result) 250 { 251 std::string command = command_line; 252 if (ResolveCommandImpl(command, result) != nullptr) { 253 result.AppendMessageWithFormat("%s", command.c_str()); 254 result.SetStatus(eReturnStatusSuccessFinishResult); 255 } 256 } 257 258 259 bool 260 CommandInterpreter::GetStopCmdSourceOnError () const 261 { 262 const uint32_t idx = ePropertyStopCmdSourceOnError; 263 return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); 264 } 265 266 bool 267 CommandInterpreter::GetSpaceReplPrompts () const 268 { 269 const uint32_t idx = eSpaceReplPrompts; 270 return m_collection_sp->GetPropertyAtIndexAsBoolean (nullptr, idx, g_properties[idx].default_uint_value != 0); 271 } 272 273 void 274 CommandInterpreter::Initialize () 275 { 276 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 277 278 CommandReturnObject result; 279 280 LoadCommandDictionary (); 281 282 // An alias arguments vector to reuse - reset it before use... 283 OptionArgVectorSP alias_arguments_vector_sp (new OptionArgVector); 284 285 // Set up some initial aliases. 286 CommandObjectSP cmd_obj_sp = GetCommandSPExact ("quit", false); 287 if (cmd_obj_sp) 288 { 289 AddAlias ("q", cmd_obj_sp); 290 AddAlias ("exit", cmd_obj_sp); 291 } 292 293 cmd_obj_sp = GetCommandSPExact ("_regexp-attach",false); 294 if (cmd_obj_sp) 295 { 296 AddAlias ("attach", cmd_obj_sp); 297 } 298 299 cmd_obj_sp = GetCommandSPExact ("process detach",false); 300 if (cmd_obj_sp) 301 { 302 AddAlias ("detach", cmd_obj_sp); 303 } 304 305 cmd_obj_sp = GetCommandSPExact ("process continue", false); 306 if (cmd_obj_sp) 307 { 308 AddAlias ("c", cmd_obj_sp); 309 AddAlias ("continue", cmd_obj_sp); 310 } 311 312 cmd_obj_sp = GetCommandSPExact ("_regexp-break",false); 313 if (cmd_obj_sp) 314 AddAlias ("b", cmd_obj_sp); 315 316 cmd_obj_sp = GetCommandSPExact ("_regexp-tbreak",false); 317 if (cmd_obj_sp) 318 AddAlias ("tbreak", cmd_obj_sp); 319 320 cmd_obj_sp = GetCommandSPExact ("thread step-inst", false); 321 if (cmd_obj_sp) 322 { 323 AddAlias ("stepi", cmd_obj_sp); 324 AddAlias ("si", cmd_obj_sp); 325 } 326 327 cmd_obj_sp = GetCommandSPExact ("thread step-inst-over", false); 328 if (cmd_obj_sp) 329 { 330 AddAlias ("nexti", cmd_obj_sp); 331 AddAlias ("ni", cmd_obj_sp); 332 } 333 334 cmd_obj_sp = GetCommandSPExact ("thread step-in", false); 335 if (cmd_obj_sp) 336 { 337 AddAlias ("s", cmd_obj_sp); 338 AddAlias ("step", cmd_obj_sp); 339 AddAlias ("sif", cmd_obj_sp, "--end-linenumber block --step-in-target %1"); 340 } 341 342 cmd_obj_sp = GetCommandSPExact ("thread step-over", false); 343 if (cmd_obj_sp) 344 { 345 AddAlias ("n", cmd_obj_sp); 346 AddAlias ("next", cmd_obj_sp); 347 } 348 349 cmd_obj_sp = GetCommandSPExact ("thread step-out", false); 350 if (cmd_obj_sp) 351 { 352 AddAlias ("finish", cmd_obj_sp); 353 } 354 355 cmd_obj_sp = GetCommandSPExact ("frame select", false); 356 if (cmd_obj_sp) 357 { 358 AddAlias ("f", cmd_obj_sp); 359 } 360 361 cmd_obj_sp = GetCommandSPExact ("thread select", false); 362 if (cmd_obj_sp) 363 { 364 AddAlias ("t", cmd_obj_sp); 365 } 366 367 cmd_obj_sp = GetCommandSPExact ("_regexp-jump",false); 368 if (cmd_obj_sp) 369 { 370 AddAlias ("j", cmd_obj_sp); 371 AddAlias ("jump", cmd_obj_sp); 372 } 373 374 cmd_obj_sp = GetCommandSPExact ("_regexp-list", false); 375 if (cmd_obj_sp) 376 { 377 AddAlias ("l", cmd_obj_sp); 378 AddAlias ("list", cmd_obj_sp); 379 } 380 381 cmd_obj_sp = GetCommandSPExact ("_regexp-env", false); 382 if (cmd_obj_sp) 383 { 384 AddAlias ("env", cmd_obj_sp); 385 } 386 387 cmd_obj_sp = GetCommandSPExact ("memory read", false); 388 if (cmd_obj_sp) 389 AddAlias ("x", cmd_obj_sp); 390 391 cmd_obj_sp = GetCommandSPExact ("_regexp-up", false); 392 if (cmd_obj_sp) 393 AddAlias ("up", cmd_obj_sp); 394 395 cmd_obj_sp = GetCommandSPExact ("_regexp-down", false); 396 if (cmd_obj_sp) 397 AddAlias ("down", cmd_obj_sp); 398 399 cmd_obj_sp = GetCommandSPExact ("_regexp-display", false); 400 if (cmd_obj_sp) 401 AddAlias ("display", cmd_obj_sp); 402 403 cmd_obj_sp = GetCommandSPExact ("disassemble", false); 404 if (cmd_obj_sp) 405 AddAlias ("dis", cmd_obj_sp); 406 407 cmd_obj_sp = GetCommandSPExact ("disassemble", false); 408 if (cmd_obj_sp) 409 AddAlias ("di", cmd_obj_sp); 410 411 412 413 cmd_obj_sp = GetCommandSPExact ("_regexp-undisplay", false); 414 if (cmd_obj_sp) 415 AddAlias ("undisplay", cmd_obj_sp); 416 417 cmd_obj_sp = GetCommandSPExact ("_regexp-bt", false); 418 if (cmd_obj_sp) 419 AddAlias ("bt", cmd_obj_sp); 420 421 cmd_obj_sp = GetCommandSPExact ("target create", false); 422 if (cmd_obj_sp) 423 AddAlias ("file", cmd_obj_sp); 424 425 cmd_obj_sp = GetCommandSPExact ("target modules", false); 426 if (cmd_obj_sp) 427 AddAlias ("image", cmd_obj_sp); 428 429 430 alias_arguments_vector_sp.reset(new OptionArgVector); 431 432 cmd_obj_sp = GetCommandSPExact ("expression", false); 433 if (cmd_obj_sp) 434 { 435 AddAlias ("p", cmd_obj_sp, "--"); 436 AddAlias ("print", cmd_obj_sp, "--"); 437 AddAlias ("call", cmd_obj_sp, "--"); 438 AddAlias ("po", cmd_obj_sp, "-O --"); 439 } 440 441 cmd_obj_sp = GetCommandSPExact ("process kill", false); 442 if (cmd_obj_sp) 443 { 444 AddAlias ("kill", cmd_obj_sp); 445 } 446 447 cmd_obj_sp = GetCommandSPExact ("process launch", false); 448 if (cmd_obj_sp) 449 { 450 alias_arguments_vector_sp.reset (new OptionArgVector); 451 #if defined (__arm__) || defined (__arm64__) || defined (__aarch64__) 452 AddAlias ("r", cmd_obj_sp, "--"); 453 AddAlias ("run", cmd_obj_sp, "--"); 454 #else 455 #if defined(__APPLE__) 456 std::string shell_option; 457 shell_option.append("--shell-expand-args"); 458 shell_option.append(" true"); 459 shell_option.append(" --"); 460 AddAlias ("r", cmd_obj_sp, "--shell-expand-args true --"); 461 AddAlias ("run", cmd_obj_sp, "--shell-expand-args true --"); 462 #else 463 StreamString defaultshell; 464 defaultshell.Printf("--shell=%s --", HostInfo::GetDefaultShell().GetPath().c_str()); 465 AddAlias ("r", cmd_obj_sp, defaultshell.GetData()); 466 AddAlias ("run", cmd_obj_sp, defaultshell.GetData()); 467 #endif 468 #endif 469 } 470 471 cmd_obj_sp = GetCommandSPExact ("target symbols add", false); 472 if (cmd_obj_sp) 473 { 474 AddAlias ("add-dsym", cmd_obj_sp); 475 } 476 477 cmd_obj_sp = GetCommandSPExact ("breakpoint set", false); 478 if (cmd_obj_sp) 479 { 480 AddAlias ("rbreak", cmd_obj_sp, "--func-regex %1"); 481 } 482 } 483 484 void 485 CommandInterpreter::Clear() 486 { 487 m_command_io_handler_sp.reset(); 488 489 if (m_script_interpreter_sp) 490 m_script_interpreter_sp->Clear(); 491 } 492 493 const char * 494 CommandInterpreter::ProcessEmbeddedScriptCommands (const char *arg) 495 { 496 // This function has not yet been implemented. 497 498 // Look for any embedded script command 499 // If found, 500 // get interpreter object from the command dictionary, 501 // call execute_one_command on it, 502 // get the results as a string, 503 // substitute that string for current stuff. 504 505 return arg; 506 } 507 508 509 void 510 CommandInterpreter::LoadCommandDictionary () 511 { 512 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 513 514 lldb::ScriptLanguage script_language = m_debugger.GetScriptLanguage(); 515 516 m_command_dict["apropos"] = CommandObjectSP (new CommandObjectApropos (*this)); 517 m_command_dict["breakpoint"]= CommandObjectSP (new CommandObjectMultiwordBreakpoint (*this)); 518 m_command_dict["bugreport"] = CommandObjectSP (new CommandObjectMultiwordBugreport (*this)); 519 m_command_dict["command"] = CommandObjectSP (new CommandObjectMultiwordCommands (*this)); 520 m_command_dict["disassemble"] = CommandObjectSP (new CommandObjectDisassemble (*this)); 521 m_command_dict["expression"]= CommandObjectSP (new CommandObjectExpression (*this)); 522 m_command_dict["frame"] = CommandObjectSP (new CommandObjectMultiwordFrame (*this)); 523 m_command_dict["gui"] = CommandObjectSP (new CommandObjectGUI (*this)); 524 m_command_dict["help"] = CommandObjectSP (new CommandObjectHelp (*this)); 525 m_command_dict["log"] = CommandObjectSP (new CommandObjectLog (*this)); 526 m_command_dict["memory"] = CommandObjectSP (new CommandObjectMemory (*this)); 527 m_command_dict["platform"] = CommandObjectSP (new CommandObjectPlatform (*this)); 528 m_command_dict["plugin"] = CommandObjectSP (new CommandObjectPlugin (*this)); 529 m_command_dict["process"] = CommandObjectSP (new CommandObjectMultiwordProcess (*this)); 530 m_command_dict["quit"] = CommandObjectSP (new CommandObjectQuit (*this)); 531 m_command_dict["register"] = CommandObjectSP (new CommandObjectRegister (*this)); 532 m_command_dict["script"] = CommandObjectSP (new CommandObjectScript (*this, script_language)); 533 m_command_dict["settings"] = CommandObjectSP (new CommandObjectMultiwordSettings (*this)); 534 m_command_dict["source"] = CommandObjectSP (new CommandObjectMultiwordSource (*this)); 535 m_command_dict["target"] = CommandObjectSP (new CommandObjectMultiwordTarget (*this)); 536 m_command_dict["thread"] = CommandObjectSP (new CommandObjectMultiwordThread (*this)); 537 m_command_dict["type"] = CommandObjectSP (new CommandObjectType (*this)); 538 m_command_dict["version"] = CommandObjectSP (new CommandObjectVersion (*this)); 539 m_command_dict["watchpoint"]= CommandObjectSP (new CommandObjectMultiwordWatchpoint (*this)); 540 m_command_dict["language"] = CommandObjectSP (new CommandObjectLanguage(*this)); 541 542 const char *break_regexes[][2] = {{"^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "breakpoint set --file '%1' --line %2"}, 543 {"^/([^/]+)/$", "breakpoint set --source-pattern-regexp '%1'"}, 544 {"^([[:digit:]]+)[[:space:]]*$", "breakpoint set --line %1"}, 545 {"^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "breakpoint set --address %1"}, 546 {"^[\"']?([-+]?\\[.*\\])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}, 547 {"^(-.*)$", "breakpoint set %1"}, 548 {"^(.*[^[:space:]])`(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%2' --shlib '%1'"}, 549 {"^\\&(.*[^[:space:]])[[:space:]]*$", "breakpoint set --name '%1' --skip-prologue=0"}, 550 {"^[\"']?(.*[^[:space:]\"'])[\"']?[[:space:]]*$", "breakpoint set --name '%1'"}}; 551 552 size_t num_regexes = llvm::array_lengthof(break_regexes); 553 554 std::unique_ptr<CommandObjectRegexCommand> 555 break_regex_cmd_ap(new CommandObjectRegexCommand (*this, 556 "_regexp-break", 557 "Set a breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.\n", 558 "\n_regexp-break <filename>:<linenum> # _regexp-break main.c:12 // Break on line 12 of main.c\n" 559 "_regexp-break <linenum> # _regexp-break 12 // Break on line 12 of current file\n" 560 "_regexp-break <address> # _regexp-break 0x1234000 // Break on address 0x1234000\n" 561 "_regexp-break <name> # _regexp-break main // Break in 'main' after the prologue\n" 562 "_regexp-break &<name> # _regexp-break &main // Break on the first instruction in 'main'\n" 563 "_regexp-break <module>`<name> # _regexp-break libc.so`malloc // Break in 'malloc' only in the 'libc.so' shared library\n" 564 "_regexp-break /<source-regex>/ # _regexp-break /break here/ // Break on all lines that match the regular expression 'break here' in the current file.\n", 565 2, 566 CommandCompletions::eSymbolCompletion | 567 CommandCompletions::eSourceFileCompletion, 568 false)); 569 570 if (break_regex_cmd_ap.get()) 571 { 572 bool success = true; 573 for (size_t i = 0; i < num_regexes; i++) 574 { 575 success = break_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], break_regexes[i][1]); 576 if (!success) 577 break; 578 } 579 success = break_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full"); 580 581 if (success) 582 { 583 CommandObjectSP break_regex_cmd_sp(break_regex_cmd_ap.release()); 584 m_command_dict[break_regex_cmd_sp->GetCommandName ()] = break_regex_cmd_sp; 585 } 586 } 587 588 std::unique_ptr<CommandObjectRegexCommand> 589 tbreak_regex_cmd_ap(new CommandObjectRegexCommand (*this, 590 "_regexp-tbreak", 591 "Set a one shot breakpoint using a regular expression to specify the location, where <linenum> is in decimal and <address> is in hex.", 592 "_regexp-tbreak [<filename>:<linenum>]\n_regexp-break [<linenum>]\n_regexp-break [<address>]\n_regexp-break <...>", 593 2, 594 CommandCompletions::eSymbolCompletion | 595 CommandCompletions::eSourceFileCompletion, 596 false)); 597 598 if (tbreak_regex_cmd_ap.get()) 599 { 600 bool success = true; 601 for (size_t i = 0; i < num_regexes; i++) 602 { 603 // If you add a resultant command string longer than 1024 characters be sure to increase the size of this buffer. 604 char buffer[1024]; 605 int num_printed = snprintf(buffer, 1024, "%s %s", break_regexes[i][1], "-o"); 606 assert (num_printed < 1024); 607 UNUSED_IF_ASSERT_DISABLED(num_printed); 608 success = tbreak_regex_cmd_ap->AddRegexCommand (break_regexes[i][0], buffer); 609 if (!success) 610 break; 611 } 612 success = tbreak_regex_cmd_ap->AddRegexCommand("^$", "breakpoint list --full"); 613 614 if (success) 615 { 616 CommandObjectSP tbreak_regex_cmd_sp(tbreak_regex_cmd_ap.release()); 617 m_command_dict[tbreak_regex_cmd_sp->GetCommandName ()] = tbreak_regex_cmd_sp; 618 } 619 } 620 621 std::unique_ptr<CommandObjectRegexCommand> 622 attach_regex_cmd_ap(new CommandObjectRegexCommand (*this, 623 "_regexp-attach", 624 "Attach to a process id if in decimal, otherwise treat the argument as a process name to attach to.", 625 "_regexp-attach [<pid>]\n_regexp-attach [<process-name>]", 626 2, 627 0, 628 false)); 629 if (attach_regex_cmd_ap.get()) 630 { 631 if (attach_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "process attach --pid %1") && 632 attach_regex_cmd_ap->AddRegexCommand("^(-.*|.* -.*)$", "process attach %1") && // Any options that are specified get passed to 'process attach' 633 attach_regex_cmd_ap->AddRegexCommand("^(.+)$", "process attach --name '%1'") && 634 attach_regex_cmd_ap->AddRegexCommand("^$", "process attach")) 635 { 636 CommandObjectSP attach_regex_cmd_sp(attach_regex_cmd_ap.release()); 637 m_command_dict[attach_regex_cmd_sp->GetCommandName ()] = attach_regex_cmd_sp; 638 } 639 } 640 641 std::unique_ptr<CommandObjectRegexCommand> 642 down_regex_cmd_ap(new CommandObjectRegexCommand (*this, 643 "_regexp-down", 644 "Go down \"n\" frames in the stack (1 frame by default).", 645 "_regexp-down [n]", 646 2, 647 0, 648 false)); 649 if (down_regex_cmd_ap.get()) 650 { 651 if (down_regex_cmd_ap->AddRegexCommand("^$", "frame select -r -1") && 652 down_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r -%1")) 653 { 654 CommandObjectSP down_regex_cmd_sp(down_regex_cmd_ap.release()); 655 m_command_dict[down_regex_cmd_sp->GetCommandName ()] = down_regex_cmd_sp; 656 } 657 } 658 659 std::unique_ptr<CommandObjectRegexCommand> 660 up_regex_cmd_ap(new CommandObjectRegexCommand (*this, 661 "_regexp-up", 662 "Go up \"n\" frames in the stack (1 frame by default).", 663 "_regexp-up [n]", 664 2, 665 0, 666 false)); 667 if (up_regex_cmd_ap.get()) 668 { 669 if (up_regex_cmd_ap->AddRegexCommand("^$", "frame select -r 1") && 670 up_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "frame select -r %1")) 671 { 672 CommandObjectSP up_regex_cmd_sp(up_regex_cmd_ap.release()); 673 m_command_dict[up_regex_cmd_sp->GetCommandName ()] = up_regex_cmd_sp; 674 } 675 } 676 677 std::unique_ptr<CommandObjectRegexCommand> 678 display_regex_cmd_ap(new CommandObjectRegexCommand (*this, 679 "_regexp-display", 680 "Add an expression evaluation stop-hook.", 681 "_regexp-display expression", 682 2, 683 0, 684 false)); 685 if (display_regex_cmd_ap.get()) 686 { 687 if (display_regex_cmd_ap->AddRegexCommand("^(.+)$", "target stop-hook add -o \"expr -- %1\"")) 688 { 689 CommandObjectSP display_regex_cmd_sp(display_regex_cmd_ap.release()); 690 m_command_dict[display_regex_cmd_sp->GetCommandName ()] = display_regex_cmd_sp; 691 } 692 } 693 694 std::unique_ptr<CommandObjectRegexCommand> 695 undisplay_regex_cmd_ap(new CommandObjectRegexCommand (*this, 696 "_regexp-undisplay", 697 "Remove an expression evaluation stop-hook.", 698 "_regexp-undisplay stop-hook-number", 699 2, 700 0, 701 false)); 702 if (undisplay_regex_cmd_ap.get()) 703 { 704 if (undisplay_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "target stop-hook delete %1")) 705 { 706 CommandObjectSP undisplay_regex_cmd_sp(undisplay_regex_cmd_ap.release()); 707 m_command_dict[undisplay_regex_cmd_sp->GetCommandName ()] = undisplay_regex_cmd_sp; 708 } 709 } 710 711 std::unique_ptr<CommandObjectRegexCommand> 712 connect_gdb_remote_cmd_ap(new CommandObjectRegexCommand (*this, 713 "gdb-remote", 714 "Connect to a remote GDB server. If no hostname is provided, localhost is assumed.", 715 "gdb-remote [<hostname>:]<portnum>", 716 2, 717 0, 718 false)); 719 if (connect_gdb_remote_cmd_ap.get()) 720 { 721 if (connect_gdb_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin gdb-remote connect://%1") && 722 connect_gdb_remote_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "process connect --plugin gdb-remote connect://localhost:%1")) 723 { 724 CommandObjectSP command_sp(connect_gdb_remote_cmd_ap.release()); 725 m_command_dict[command_sp->GetCommandName ()] = command_sp; 726 } 727 } 728 729 std::unique_ptr<CommandObjectRegexCommand> 730 connect_kdp_remote_cmd_ap(new CommandObjectRegexCommand (*this, 731 "kdp-remote", 732 "Connect to a remote KDP server. udp port 41139 is the default port number.", 733 "kdp-remote <hostname>[:<portnum>]", 734 2, 735 0, 736 false)); 737 if (connect_kdp_remote_cmd_ap.get()) 738 { 739 if (connect_kdp_remote_cmd_ap->AddRegexCommand("^([^:]+:[[:digit:]]+)$", "process connect --plugin kdp-remote udp://%1") && 740 connect_kdp_remote_cmd_ap->AddRegexCommand("^(.+)$", "process connect --plugin kdp-remote udp://%1:41139")) 741 { 742 CommandObjectSP command_sp(connect_kdp_remote_cmd_ap.release()); 743 m_command_dict[command_sp->GetCommandName ()] = command_sp; 744 } 745 } 746 747 std::unique_ptr<CommandObjectRegexCommand> 748 bt_regex_cmd_ap(new CommandObjectRegexCommand (*this, 749 "_regexp-bt", 750 "Show a backtrace. An optional argument is accepted; if that argument is a number, it specifies the number of frames to display. If that argument is 'all', full backtraces of all threads are displayed.", 751 "bt [<digit>|all]", 752 2, 753 0, 754 false)); 755 if (bt_regex_cmd_ap.get()) 756 { 757 // accept but don't document "bt -c <number>" -- before bt was a regex command if you wanted to backtrace 758 // three frames you would do "bt -c 3" but the intention is to have this emulate the gdb "bt" command and 759 // so now "bt 3" is the preferred form, in line with gdb. 760 if (bt_regex_cmd_ap->AddRegexCommand("^([[:digit:]]+)$", "thread backtrace -c %1") && 761 bt_regex_cmd_ap->AddRegexCommand("^-c ([[:digit:]]+)$", "thread backtrace -c %1") && 762 bt_regex_cmd_ap->AddRegexCommand("^all$", "thread backtrace all") && 763 bt_regex_cmd_ap->AddRegexCommand("^$", "thread backtrace")) 764 { 765 CommandObjectSP command_sp(bt_regex_cmd_ap.release()); 766 m_command_dict[command_sp->GetCommandName ()] = command_sp; 767 } 768 } 769 770 std::unique_ptr<CommandObjectRegexCommand> 771 list_regex_cmd_ap(new CommandObjectRegexCommand (*this, 772 "_regexp-list", 773 "Implements the GDB 'list' command in all of its forms except FILE:FUNCTION and maps them to the appropriate 'source list' commands.", 774 "_regexp-list [<line>]\n_regexp-list [<file>:<line>]\n_regexp-list [<file>:<line>]", 775 2, 776 CommandCompletions::eSourceFileCompletion, 777 false)); 778 if (list_regex_cmd_ap.get()) 779 { 780 if (list_regex_cmd_ap->AddRegexCommand("^([0-9]+)[[:space:]]*$", "source list --line %1") && 781 list_regex_cmd_ap->AddRegexCommand("^(.*[^[:space:]])[[:space:]]*:[[:space:]]*([[:digit:]]+)[[:space:]]*$", "source list --file '%1' --line %2") && 782 list_regex_cmd_ap->AddRegexCommand("^\\*?(0x[[:xdigit:]]+)[[:space:]]*$", "source list --address %1") && 783 list_regex_cmd_ap->AddRegexCommand("^-[[:space:]]*$", "source list --reverse") && 784 list_regex_cmd_ap->AddRegexCommand("^-([[:digit:]]+)[[:space:]]*$", "source list --reverse --count %1") && 785 list_regex_cmd_ap->AddRegexCommand("^(.+)$", "source list --name \"%1\"") && 786 list_regex_cmd_ap->AddRegexCommand("^$", "source list")) 787 { 788 CommandObjectSP list_regex_cmd_sp(list_regex_cmd_ap.release()); 789 m_command_dict[list_regex_cmd_sp->GetCommandName ()] = list_regex_cmd_sp; 790 } 791 } 792 793 std::unique_ptr<CommandObjectRegexCommand> 794 env_regex_cmd_ap(new CommandObjectRegexCommand (*this, 795 "_regexp-env", 796 "Implements a shortcut to viewing and setting environment variables.", 797 "_regexp-env\n_regexp-env FOO=BAR", 798 2, 799 0, 800 false)); 801 if (env_regex_cmd_ap.get()) 802 { 803 if (env_regex_cmd_ap->AddRegexCommand("^$", "settings show target.env-vars") && 804 env_regex_cmd_ap->AddRegexCommand("^([A-Za-z_][A-Za-z_0-9]*=.*)$", "settings set target.env-vars %1")) 805 { 806 CommandObjectSP env_regex_cmd_sp(env_regex_cmd_ap.release()); 807 m_command_dict[env_regex_cmd_sp->GetCommandName ()] = env_regex_cmd_sp; 808 } 809 } 810 811 std::unique_ptr<CommandObjectRegexCommand> 812 jump_regex_cmd_ap(new CommandObjectRegexCommand (*this, 813 "_regexp-jump", 814 "Sets the program counter to a new address.", 815 "_regexp-jump [<line>]\n" 816 "_regexp-jump [<+-lineoffset>]\n" 817 "_regexp-jump [<file>:<line>]\n" 818 "_regexp-jump [*<addr>]\n", 819 2, 820 0, 821 false)); 822 if (jump_regex_cmd_ap.get()) 823 { 824 if (jump_regex_cmd_ap->AddRegexCommand("^\\*(.*)$", "thread jump --addr %1") && 825 jump_regex_cmd_ap->AddRegexCommand("^([0-9]+)$", "thread jump --line %1") && 826 jump_regex_cmd_ap->AddRegexCommand("^([^:]+):([0-9]+)$", "thread jump --file %1 --line %2") && 827 jump_regex_cmd_ap->AddRegexCommand("^([+\\-][0-9]+)$", "thread jump --by %1")) 828 { 829 CommandObjectSP jump_regex_cmd_sp(jump_regex_cmd_ap.release()); 830 m_command_dict[jump_regex_cmd_sp->GetCommandName ()] = jump_regex_cmd_sp; 831 } 832 } 833 834 } 835 836 int 837 CommandInterpreter::GetCommandNamesMatchingPartialString (const char *cmd_str, bool include_aliases, 838 StringList &matches) 839 { 840 AddNamesMatchingPartialString (m_command_dict, cmd_str, matches); 841 842 if (include_aliases) 843 { 844 AddNamesMatchingPartialString (m_alias_dict, cmd_str, matches); 845 } 846 847 return matches.GetSize(); 848 } 849 850 CommandObjectSP 851 CommandInterpreter::GetCommandSP (const char *cmd_cstr, bool include_aliases, bool exact, StringList *matches) 852 { 853 CommandObject::CommandMap::iterator pos; 854 CommandObjectSP command_sp; 855 856 std::string cmd(cmd_cstr); 857 858 if (HasCommands()) 859 { 860 pos = m_command_dict.find(cmd); 861 if (pos != m_command_dict.end()) 862 command_sp = pos->second; 863 } 864 865 if (include_aliases && HasAliases()) 866 { 867 CommandAliasMap::iterator alias_pos = m_alias_dict.find(cmd); 868 if (alias_pos != m_alias_dict.end()) 869 command_sp = alias_pos->second.m_underlying_command_sp; 870 } 871 872 if (HasUserCommands()) 873 { 874 pos = m_user_dict.find(cmd); 875 if (pos != m_user_dict.end()) 876 command_sp = pos->second; 877 } 878 879 if (!exact && !command_sp) 880 { 881 // We will only get into here if we didn't find any exact matches. 882 883 CommandObjectSP user_match_sp, alias_match_sp, real_match_sp; 884 885 StringList local_matches; 886 if (matches == nullptr) 887 matches = &local_matches; 888 889 unsigned int num_cmd_matches = 0; 890 unsigned int num_alias_matches = 0; 891 unsigned int num_user_matches = 0; 892 893 // Look through the command dictionaries one by one, and if we get only one match from any of 894 // them in toto, then return that, otherwise return an empty CommandObjectSP and the list of matches. 895 896 if (HasCommands()) 897 { 898 num_cmd_matches = AddNamesMatchingPartialString (m_command_dict, cmd_cstr, *matches); 899 } 900 901 if (num_cmd_matches == 1) 902 { 903 cmd.assign(matches->GetStringAtIndex(0)); 904 pos = m_command_dict.find(cmd); 905 if (pos != m_command_dict.end()) 906 real_match_sp = pos->second; 907 } 908 909 if (include_aliases && HasAliases()) 910 { 911 num_alias_matches = AddNamesMatchingPartialString (m_alias_dict, cmd_cstr, *matches); 912 913 } 914 915 if (num_alias_matches == 1) 916 { 917 cmd.assign(matches->GetStringAtIndex (num_cmd_matches)); 918 CommandAliasMap::iterator alias_pos = m_alias_dict.find(cmd); 919 if (alias_pos != m_alias_dict.end()) 920 alias_match_sp = alias_pos->second.m_underlying_command_sp; 921 } 922 923 if (HasUserCommands()) 924 { 925 num_user_matches = AddNamesMatchingPartialString (m_user_dict, cmd_cstr, *matches); 926 } 927 928 if (num_user_matches == 1) 929 { 930 cmd.assign (matches->GetStringAtIndex (num_cmd_matches + num_alias_matches)); 931 932 pos = m_user_dict.find (cmd); 933 if (pos != m_user_dict.end()) 934 user_match_sp = pos->second; 935 } 936 937 // If we got exactly one match, return that, otherwise return the match list. 938 939 if (num_user_matches + num_cmd_matches + num_alias_matches == 1) 940 { 941 if (num_cmd_matches) 942 return real_match_sp; 943 else if (num_alias_matches) 944 return alias_match_sp; 945 else 946 return user_match_sp; 947 } 948 } 949 else if (matches && command_sp) 950 { 951 matches->AppendString (cmd_cstr); 952 } 953 954 955 return command_sp; 956 } 957 958 bool 959 CommandInterpreter::AddCommand (const char *name, const lldb::CommandObjectSP &cmd_sp, bool can_replace) 960 { 961 if (cmd_sp.get()) 962 assert((this == &cmd_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter"); 963 964 if (name && name[0]) 965 { 966 std::string name_sstr(name); 967 bool found = (m_command_dict.find (name_sstr) != m_command_dict.end()); 968 if (found && !can_replace) 969 return false; 970 if (found && m_command_dict[name_sstr]->IsRemovable() == false) 971 return false; 972 m_command_dict[name_sstr] = cmd_sp; 973 return true; 974 } 975 return false; 976 } 977 978 bool 979 CommandInterpreter::AddUserCommand (std::string name, 980 const lldb::CommandObjectSP &cmd_sp, 981 bool can_replace) 982 { 983 if (cmd_sp.get()) 984 assert((this == &cmd_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter"); 985 986 if (!name.empty()) 987 { 988 const char* name_cstr = name.c_str(); 989 990 // do not allow replacement of internal commands 991 if (CommandExists(name_cstr)) 992 { 993 if (can_replace == false) 994 return false; 995 if (m_command_dict[name]->IsRemovable() == false) 996 return false; 997 } 998 999 if (UserCommandExists(name_cstr)) 1000 { 1001 if (can_replace == false) 1002 return false; 1003 if (m_user_dict[name]->IsRemovable() == false) 1004 return false; 1005 } 1006 1007 m_user_dict[name] = cmd_sp; 1008 return true; 1009 } 1010 return false; 1011 } 1012 1013 CommandObjectSP 1014 CommandInterpreter::GetCommandSPExact (const char *cmd_cstr, bool include_aliases) 1015 { 1016 Args cmd_words (cmd_cstr); // Break up the command string into words, in case it's a multi-word command. 1017 CommandObjectSP ret_val; // Possibly empty return value. 1018 1019 if (cmd_cstr == nullptr) 1020 return ret_val; 1021 1022 if (cmd_words.GetArgumentCount() == 1) 1023 return GetCommandSP(cmd_cstr, include_aliases, true, nullptr); 1024 else 1025 { 1026 // We have a multi-word command (seemingly), so we need to do more work. 1027 // First, get the cmd_obj_sp for the first word in the command. 1028 CommandObjectSP cmd_obj_sp = GetCommandSP (cmd_words.GetArgumentAtIndex (0), include_aliases, true, nullptr); 1029 if (cmd_obj_sp.get() != nullptr) 1030 { 1031 // Loop through the rest of the words in the command (everything passed in was supposed to be part of a 1032 // command name), and find the appropriate sub-command SP for each command word.... 1033 size_t end = cmd_words.GetArgumentCount(); 1034 for (size_t j= 1; j < end; ++j) 1035 { 1036 if (cmd_obj_sp->IsMultiwordObject()) 1037 { 1038 cmd_obj_sp = cmd_obj_sp->GetSubcommandSP (cmd_words.GetArgumentAtIndex (j)); 1039 if (cmd_obj_sp.get() == nullptr) 1040 // The sub-command name was invalid. Fail and return the empty 'ret_val'. 1041 return ret_val; 1042 } 1043 else 1044 // We have more words in the command name, but we don't have a multiword object. Fail and return 1045 // empty 'ret_val'. 1046 return ret_val; 1047 } 1048 // We successfully looped through all the command words and got valid command objects for them. Assign the 1049 // last object retrieved to 'ret_val'. 1050 ret_val = cmd_obj_sp; 1051 } 1052 } 1053 return ret_val; 1054 } 1055 1056 CommandObject * 1057 CommandInterpreter::GetCommandObjectExact (const char *cmd_cstr, bool include_aliases) 1058 { 1059 return GetCommandSPExact (cmd_cstr, include_aliases).get(); 1060 } 1061 1062 CommandObject * 1063 CommandInterpreter::GetCommandObject (const char *cmd_cstr, StringList *matches) 1064 { 1065 CommandObject *command_obj = GetCommandSP (cmd_cstr, false, true, matches).get(); 1066 1067 // If we didn't find an exact match to the command string in the commands, look in 1068 // the aliases. 1069 1070 if (command_obj) 1071 return command_obj; 1072 1073 command_obj = GetCommandSP (cmd_cstr, true, true, matches).get(); 1074 1075 if (command_obj) 1076 return command_obj; 1077 1078 // If there wasn't an exact match then look for an inexact one in just the commands 1079 command_obj = GetCommandSP(cmd_cstr, false, false, nullptr).get(); 1080 1081 // Finally, if there wasn't an inexact match among the commands, look for an inexact 1082 // match in both the commands and aliases. 1083 1084 if (command_obj) 1085 { 1086 if (matches) 1087 matches->AppendString(command_obj->GetCommandName()); 1088 return command_obj; 1089 } 1090 1091 return GetCommandSP(cmd_cstr, true, false, matches).get(); 1092 } 1093 1094 bool 1095 CommandInterpreter::CommandExists (const char *cmd) 1096 { 1097 return m_command_dict.find(cmd) != m_command_dict.end(); 1098 } 1099 1100 bool 1101 CommandInterpreter::GetAliasFullName (const char *cmd, std::string &full_name) 1102 { 1103 bool exact_match = (m_alias_dict.find(cmd) != m_alias_dict.end()); 1104 if (exact_match) 1105 { 1106 full_name.assign(cmd); 1107 return exact_match; 1108 } 1109 else 1110 { 1111 StringList matches; 1112 size_t num_alias_matches; 1113 num_alias_matches = AddNamesMatchingPartialString (m_alias_dict, cmd, matches); 1114 if (num_alias_matches == 1) 1115 { 1116 // Make sure this isn't shadowing a command in the regular command space: 1117 StringList regular_matches; 1118 const bool include_aliases = false; 1119 const bool exact = false; 1120 CommandObjectSP cmd_obj_sp(GetCommandSP (cmd, include_aliases, exact, ®ular_matches)); 1121 if (cmd_obj_sp || regular_matches.GetSize() > 0) 1122 return false; 1123 else 1124 { 1125 full_name.assign (matches.GetStringAtIndex(0)); 1126 return true; 1127 } 1128 } 1129 else 1130 return false; 1131 } 1132 } 1133 1134 bool 1135 CommandInterpreter::AliasExists (const char *cmd) 1136 { 1137 return m_alias_dict.find(cmd) != m_alias_dict.end(); 1138 } 1139 1140 bool 1141 CommandInterpreter::UserCommandExists (const char *cmd) 1142 { 1143 return m_user_dict.find(cmd) != m_user_dict.end(); 1144 } 1145 1146 bool 1147 CommandInterpreter::AddAlias (const char *alias_name, 1148 lldb::CommandObjectSP& command_obj_sp, 1149 const char *args_string) 1150 { 1151 if (command_obj_sp.get()) 1152 assert((this == &command_obj_sp->GetCommandInterpreter()) && "tried to add a CommandObject from a different interpreter"); 1153 1154 OptionArgVectorSP args_sp(new OptionArgVector); 1155 if (CommandAlias::ProcessAliasOptionsArgs(command_obj_sp, args_string, args_sp)) 1156 { 1157 m_alias_dict[alias_name] = CommandAlias(command_obj_sp,args_sp); 1158 return true; 1159 } 1160 return false; 1161 } 1162 1163 bool 1164 CommandInterpreter::RemoveAlias (const char *alias_name) 1165 { 1166 auto pos = m_alias_dict.find(alias_name); 1167 if (pos != m_alias_dict.end()) 1168 { 1169 m_alias_dict.erase(pos); 1170 return true; 1171 } 1172 return false; 1173 } 1174 1175 bool 1176 CommandInterpreter::RemoveCommand (const char *cmd) 1177 { 1178 auto pos = m_command_dict.find(cmd); 1179 if (pos != m_command_dict.end()) 1180 { 1181 if (pos->second->IsRemovable()) 1182 { 1183 // Only regular expression objects or python commands are removable 1184 m_command_dict.erase(pos); 1185 return true; 1186 } 1187 } 1188 return false; 1189 } 1190 bool 1191 CommandInterpreter::RemoveUser (const char *alias_name) 1192 { 1193 CommandObject::CommandMap::iterator pos = m_user_dict.find(alias_name); 1194 if (pos != m_user_dict.end()) 1195 { 1196 m_user_dict.erase(pos); 1197 return true; 1198 } 1199 return false; 1200 } 1201 1202 void 1203 CommandInterpreter::GetHelp (CommandReturnObject &result, 1204 uint32_t cmd_types) 1205 { 1206 const char * help_prologue = GetDebugger().GetIOHandlerHelpPrologue(); 1207 if (help_prologue != NULL) 1208 { 1209 OutputFormattedHelpText(result.GetOutputStream(), NULL, help_prologue); 1210 } 1211 1212 CommandObject::CommandMap::const_iterator pos; 1213 size_t max_len = FindLongestCommandWord (m_command_dict); 1214 1215 if ( (cmd_types & eCommandTypesBuiltin) == eCommandTypesBuiltin ) 1216 { 1217 result.AppendMessage("Debugger commands:"); 1218 result.AppendMessage(""); 1219 1220 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) 1221 { 1222 if (!(cmd_types & eCommandTypesHidden) && (pos->first.compare(0, 1, "_") == 0)) 1223 continue; 1224 1225 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(), 1226 max_len); 1227 } 1228 result.AppendMessage(""); 1229 1230 } 1231 1232 if (!m_alias_dict.empty() && ( (cmd_types & eCommandTypesAliases) == eCommandTypesAliases )) 1233 { 1234 result.AppendMessageWithFormat("Current command abbreviations " 1235 "(type '%shelp command alias' for more info):\n", 1236 GetCommandPrefix()); 1237 result.AppendMessage(""); 1238 max_len = FindLongestCommandWord (m_alias_dict); 1239 1240 for (auto alias_pos = m_alias_dict.begin(); alias_pos != m_alias_dict.end(); ++alias_pos) 1241 { 1242 StreamString sstr; 1243 StreamString translation_and_help; 1244 std::string entry_name = alias_pos->first; 1245 std::string second_entry = alias_pos->second.m_underlying_command_sp->GetCommandName(); 1246 alias_pos->second.GetAliasHelp(sstr); 1247 1248 translation_and_help.Printf ("(%s) %s", sstr.GetData(), alias_pos->second.m_underlying_command_sp->GetHelp()); 1249 OutputFormattedHelpText (result.GetOutputStream(), alias_pos->first.c_str(), "--", 1250 translation_and_help.GetData(), max_len); 1251 } 1252 result.AppendMessage(""); 1253 } 1254 1255 if (!m_user_dict.empty() && ( (cmd_types & eCommandTypesUserDef) == eCommandTypesUserDef )) 1256 { 1257 result.AppendMessage ("Current user-defined commands:"); 1258 result.AppendMessage(""); 1259 max_len = FindLongestCommandWord (m_user_dict); 1260 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) 1261 { 1262 OutputFormattedHelpText (result.GetOutputStream(), pos->first.c_str(), "--", pos->second->GetHelp(), 1263 max_len); 1264 } 1265 result.AppendMessage(""); 1266 } 1267 1268 result.AppendMessageWithFormat("For more information on any command, type '%shelp <command-name>'.\n", 1269 GetCommandPrefix()); 1270 } 1271 1272 CommandObject * 1273 CommandInterpreter::GetCommandObjectForCommand (std::string &command_string) 1274 { 1275 // This function finds the final, lowest-level, alias-resolved command object whose 'Execute' function will 1276 // eventually be invoked by the given command line. 1277 1278 CommandObject *cmd_obj = nullptr; 1279 size_t start = command_string.find_first_not_of (k_white_space); 1280 size_t end = 0; 1281 bool done = false; 1282 while (!done) 1283 { 1284 if (start != std::string::npos) 1285 { 1286 // Get the next word from command_string. 1287 end = command_string.find_first_of (k_white_space, start); 1288 if (end == std::string::npos) 1289 end = command_string.size(); 1290 std::string cmd_word = command_string.substr (start, end - start); 1291 1292 if (cmd_obj == nullptr) 1293 // Since cmd_obj is NULL we are on our first time through this loop. Check to see if cmd_word is a valid 1294 // command or alias. 1295 cmd_obj = GetCommandObject (cmd_word.c_str()); 1296 else if (cmd_obj->IsMultiwordObject ()) 1297 { 1298 // Our current object is a multi-word object; see if the cmd_word is a valid sub-command for our object. 1299 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject (cmd_word.c_str()); 1300 if (sub_cmd_obj) 1301 cmd_obj = sub_cmd_obj; 1302 else // cmd_word was not a valid sub-command word, so we are done 1303 done = true; 1304 } 1305 else 1306 // We have a cmd_obj and it is not a multi-word object, so we are done. 1307 done = true; 1308 1309 // If we didn't find a valid command object, or our command object is not a multi-word object, or 1310 // we are at the end of the command_string, then we are done. Otherwise, find the start of the 1311 // next word. 1312 1313 if (!cmd_obj || !cmd_obj->IsMultiwordObject() || end >= command_string.size()) 1314 done = true; 1315 else 1316 start = command_string.find_first_not_of (k_white_space, end); 1317 } 1318 else 1319 // Unable to find any more words. 1320 done = true; 1321 } 1322 1323 if (end == command_string.size()) 1324 command_string.clear(); 1325 else 1326 command_string = command_string.substr(end); 1327 1328 return cmd_obj; 1329 } 1330 1331 static const char *k_valid_command_chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_"; 1332 static void 1333 StripLeadingSpaces (std::string &s) 1334 { 1335 if (!s.empty()) 1336 { 1337 size_t pos = s.find_first_not_of (k_white_space); 1338 if (pos == std::string::npos) 1339 s.clear(); 1340 else if (pos == 0) 1341 return; 1342 s.erase (0, pos); 1343 } 1344 } 1345 1346 static size_t 1347 FindArgumentTerminator (const std::string &s) 1348 { 1349 const size_t s_len = s.size(); 1350 size_t offset = 0; 1351 while (offset < s_len) 1352 { 1353 size_t pos = s.find ("--", offset); 1354 if (pos == std::string::npos) 1355 break; 1356 if (pos > 0) 1357 { 1358 if (isspace(s[pos-1])) 1359 { 1360 // Check if the string ends "\s--" (where \s is a space character) 1361 // or if we have "\s--\s". 1362 if ((pos + 2 >= s_len) || isspace(s[pos+2])) 1363 { 1364 return pos; 1365 } 1366 } 1367 } 1368 offset = pos + 2; 1369 } 1370 return std::string::npos; 1371 } 1372 1373 static bool 1374 ExtractCommand (std::string &command_string, std::string &command, std::string &suffix, char "e_char) 1375 { 1376 command.clear(); 1377 suffix.clear(); 1378 StripLeadingSpaces (command_string); 1379 1380 bool result = false; 1381 quote_char = '\0'; 1382 1383 if (!command_string.empty()) 1384 { 1385 const char first_char = command_string[0]; 1386 if (first_char == '\'' || first_char == '"') 1387 { 1388 quote_char = first_char; 1389 const size_t end_quote_pos = command_string.find (quote_char, 1); 1390 if (end_quote_pos == std::string::npos) 1391 { 1392 command.swap (command_string); 1393 command_string.erase (); 1394 } 1395 else 1396 { 1397 command.assign (command_string, 1, end_quote_pos - 1); 1398 if (end_quote_pos + 1 < command_string.size()) 1399 command_string.erase (0, command_string.find_first_not_of (k_white_space, end_quote_pos + 1)); 1400 else 1401 command_string.erase (); 1402 } 1403 } 1404 else 1405 { 1406 const size_t first_space_pos = command_string.find_first_of (k_white_space); 1407 if (first_space_pos == std::string::npos) 1408 { 1409 command.swap (command_string); 1410 command_string.erase(); 1411 } 1412 else 1413 { 1414 command.assign (command_string, 0, first_space_pos); 1415 command_string.erase(0, command_string.find_first_not_of (k_white_space, first_space_pos)); 1416 } 1417 } 1418 result = true; 1419 } 1420 1421 1422 if (!command.empty()) 1423 { 1424 // actual commands can't start with '-' or '_' 1425 if (command[0] != '-' && command[0] != '_') 1426 { 1427 size_t pos = command.find_first_not_of(k_valid_command_chars); 1428 if (pos > 0 && pos != std::string::npos) 1429 { 1430 suffix.assign (command.begin() + pos, command.end()); 1431 command.erase (pos); 1432 } 1433 } 1434 } 1435 1436 return result; 1437 } 1438 1439 CommandObject * 1440 CommandInterpreter::BuildAliasResult (const char *alias_name, 1441 std::string &raw_input_string, 1442 std::string &alias_result, 1443 CommandReturnObject &result) 1444 { 1445 CommandObject *alias_cmd_obj = nullptr; 1446 Args cmd_args (raw_input_string); 1447 alias_cmd_obj = GetCommandObject (alias_name); 1448 StreamString result_str; 1449 1450 if (alias_cmd_obj) 1451 { 1452 std::string alias_name_str = alias_name; 1453 if ((cmd_args.GetArgumentCount() == 0) 1454 || (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0)) 1455 cmd_args.Unshift (alias_name); 1456 1457 result_str.Printf ("%s", alias_cmd_obj->GetCommandName ()); 1458 OptionArgVectorSP option_arg_vector_sp = GetAlias(alias_name).m_option_args_sp; 1459 1460 if (option_arg_vector_sp.get()) 1461 { 1462 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 1463 1464 for (size_t i = 0; i < option_arg_vector->size(); ++i) 1465 { 1466 OptionArgPair option_pair = (*option_arg_vector)[i]; 1467 OptionArgValue value_pair = option_pair.second; 1468 int value_type = value_pair.first; 1469 std::string option = option_pair.first; 1470 std::string value = value_pair.second; 1471 if (option.compare ("<argument>") == 0) 1472 result_str.Printf (" %s", value.c_str()); 1473 else 1474 { 1475 result_str.Printf (" %s", option.c_str()); 1476 if (value_type != OptionParser::eNoArgument) 1477 { 1478 if (value_type != OptionParser::eOptionalArgument) 1479 result_str.Printf (" "); 1480 int index = GetOptionArgumentPosition (value.c_str()); 1481 if (index == 0) 1482 result_str.Printf ("%s", value.c_str()); 1483 else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount()) 1484 { 1485 1486 result.AppendErrorWithFormat 1487 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", 1488 index); 1489 result.SetStatus (eReturnStatusFailed); 1490 return nullptr; 1491 } 1492 else 1493 { 1494 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index)); 1495 if (strpos != std::string::npos) 1496 raw_input_string = raw_input_string.erase (strpos, 1497 strlen (cmd_args.GetArgumentAtIndex (index))); 1498 result_str.Printf ("%s", cmd_args.GetArgumentAtIndex (index)); 1499 } 1500 } 1501 } 1502 } 1503 } 1504 1505 alias_result = result_str.GetData(); 1506 } 1507 return alias_cmd_obj; 1508 } 1509 1510 Error 1511 CommandInterpreter::PreprocessCommand (std::string &command) 1512 { 1513 // The command preprocessor needs to do things to the command 1514 // line before any parsing of arguments or anything else is done. 1515 // The only current stuff that gets preprocessed is anything enclosed 1516 // in backtick ('`') characters is evaluated as an expression and 1517 // the result of the expression must be a scalar that can be substituted 1518 // into the command. An example would be: 1519 // (lldb) memory read `$rsp + 20` 1520 Error error; // Error for any expressions that might not evaluate 1521 size_t start_backtick; 1522 size_t pos = 0; 1523 while ((start_backtick = command.find ('`', pos)) != std::string::npos) 1524 { 1525 if (start_backtick > 0 && command[start_backtick-1] == '\\') 1526 { 1527 // The backtick was preceded by a '\' character, remove the slash 1528 // and don't treat the backtick as the start of an expression 1529 command.erase(start_backtick-1, 1); 1530 // No need to add one to start_backtick since we just deleted a char 1531 pos = start_backtick; 1532 } 1533 else 1534 { 1535 const size_t expr_content_start = start_backtick + 1; 1536 const size_t end_backtick = command.find ('`', expr_content_start); 1537 if (end_backtick == std::string::npos) 1538 return error; 1539 else if (end_backtick == expr_content_start) 1540 { 1541 // Empty expression (two backticks in a row) 1542 command.erase (start_backtick, 2); 1543 } 1544 else 1545 { 1546 std::string expr_str (command, expr_content_start, end_backtick - expr_content_start); 1547 1548 ExecutionContext exe_ctx(GetExecutionContext()); 1549 Target *target = exe_ctx.GetTargetPtr(); 1550 // Get a dummy target to allow for calculator mode while processing backticks. 1551 // This also helps break the infinite loop caused when target is null. 1552 if (!target) 1553 target = m_debugger.GetDummyTarget(); 1554 if (target) 1555 { 1556 ValueObjectSP expr_result_valobj_sp; 1557 1558 EvaluateExpressionOptions options; 1559 options.SetCoerceToId(false); 1560 options.SetUnwindOnError(true); 1561 options.SetIgnoreBreakpoints(true); 1562 options.SetKeepInMemory(false); 1563 options.SetTryAllThreads(true); 1564 options.SetTimeoutUsec(0); 1565 1566 ExpressionResults expr_result = target->EvaluateExpression (expr_str.c_str(), 1567 exe_ctx.GetFramePtr(), 1568 expr_result_valobj_sp, 1569 options); 1570 1571 if (expr_result == eExpressionCompleted) 1572 { 1573 Scalar scalar; 1574 if (expr_result_valobj_sp) 1575 expr_result_valobj_sp = expr_result_valobj_sp->GetQualifiedRepresentationIfAvailable(expr_result_valobj_sp->GetDynamicValueType(), true); 1576 if (expr_result_valobj_sp->ResolveValue (scalar)) 1577 { 1578 command.erase (start_backtick, end_backtick - start_backtick + 1); 1579 StreamString value_strm; 1580 const bool show_type = false; 1581 scalar.GetValue (&value_strm, show_type); 1582 size_t value_string_size = value_strm.GetSize(); 1583 if (value_string_size) 1584 { 1585 command.insert (start_backtick, value_strm.GetData(), value_string_size); 1586 pos = start_backtick + value_string_size; 1587 continue; 1588 } 1589 else 1590 { 1591 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str()); 1592 } 1593 } 1594 else 1595 { 1596 error.SetErrorStringWithFormat("expression value didn't result in a scalar value for the expression '%s'", expr_str.c_str()); 1597 } 1598 } 1599 else 1600 { 1601 if (expr_result_valobj_sp) 1602 error = expr_result_valobj_sp->GetError(); 1603 if (error.Success()) 1604 { 1605 1606 switch (expr_result) 1607 { 1608 case eExpressionSetupError: 1609 error.SetErrorStringWithFormat("expression setup error for the expression '%s'", expr_str.c_str()); 1610 break; 1611 case eExpressionParseError: 1612 error.SetErrorStringWithFormat ("expression parse error for the expression '%s'", expr_str.c_str()); 1613 break; 1614 case eExpressionResultUnavailable: 1615 error.SetErrorStringWithFormat ("expression error fetching result for the expression '%s'", expr_str.c_str()); 1616 break; 1617 case eExpressionCompleted: 1618 break; 1619 case eExpressionDiscarded: 1620 error.SetErrorStringWithFormat("expression discarded for the expression '%s'", expr_str.c_str()); 1621 break; 1622 case eExpressionInterrupted: 1623 error.SetErrorStringWithFormat("expression interrupted for the expression '%s'", expr_str.c_str()); 1624 break; 1625 case eExpressionHitBreakpoint: 1626 error.SetErrorStringWithFormat("expression hit breakpoint for the expression '%s'", expr_str.c_str()); 1627 break; 1628 case eExpressionTimedOut: 1629 error.SetErrorStringWithFormat("expression timed out for the expression '%s'", expr_str.c_str()); 1630 break; 1631 case eExpressionStoppedForDebug: 1632 error.SetErrorStringWithFormat("expression stop at entry point for debugging for the expression '%s'", expr_str.c_str()); 1633 break; 1634 } 1635 } 1636 } 1637 } 1638 } 1639 if (error.Fail()) 1640 break; 1641 } 1642 } 1643 return error; 1644 } 1645 1646 1647 bool 1648 CommandInterpreter::HandleCommand (const char *command_line, 1649 LazyBool lazy_add_to_history, 1650 CommandReturnObject &result, 1651 ExecutionContext *override_context, 1652 bool repeat_on_empty_command, 1653 bool no_context_switching) 1654 1655 { 1656 1657 std::string command_string (command_line); 1658 std::string original_command_string (command_line); 1659 1660 Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_COMMANDS)); 1661 Host::SetCrashDescriptionWithFormat ("HandleCommand(command = \"%s\")", command_line); 1662 1663 // Make a scoped cleanup object that will clear the crash description string 1664 // on exit of this function. 1665 lldb_utility::CleanUp <const char *> crash_description_cleanup(nullptr, Host::SetCrashDescription); 1666 1667 if (log) 1668 log->Printf ("Processing command: %s", command_line); 1669 1670 Timer scoped_timer (__PRETTY_FUNCTION__, "Handling command: %s.", command_line); 1671 1672 if (!no_context_switching) 1673 UpdateExecutionContext (override_context); 1674 1675 bool add_to_history; 1676 if (lazy_add_to_history == eLazyBoolCalculate) 1677 add_to_history = (m_command_source_depth == 0); 1678 else 1679 add_to_history = (lazy_add_to_history == eLazyBoolYes); 1680 1681 bool empty_command = false; 1682 bool comment_command = false; 1683 if (command_string.empty()) 1684 empty_command = true; 1685 else 1686 { 1687 const char *k_space_characters = "\t\n\v\f\r "; 1688 1689 size_t non_space = command_string.find_first_not_of (k_space_characters); 1690 // Check for empty line or comment line (lines whose first 1691 // non-space character is the comment character for this interpreter) 1692 if (non_space == std::string::npos) 1693 empty_command = true; 1694 else if (command_string[non_space] == m_comment_char) 1695 comment_command = true; 1696 else if (command_string[non_space] == CommandHistory::g_repeat_char) 1697 { 1698 const char *history_string = m_command_history.FindString(command_string.c_str() + non_space); 1699 if (history_string == nullptr) 1700 { 1701 result.AppendErrorWithFormat ("Could not find entry: %s in history", command_string.c_str()); 1702 result.SetStatus(eReturnStatusFailed); 1703 return false; 1704 } 1705 add_to_history = false; 1706 command_string = history_string; 1707 original_command_string = history_string; 1708 } 1709 } 1710 1711 if (empty_command) 1712 { 1713 if (repeat_on_empty_command) 1714 { 1715 if (m_command_history.IsEmpty()) 1716 { 1717 result.AppendError ("empty command"); 1718 result.SetStatus(eReturnStatusFailed); 1719 return false; 1720 } 1721 else 1722 { 1723 command_line = m_repeat_command.c_str(); 1724 command_string = command_line; 1725 original_command_string = command_line; 1726 if (m_repeat_command.empty()) 1727 { 1728 result.AppendErrorWithFormat("No auto repeat.\n"); 1729 result.SetStatus (eReturnStatusFailed); 1730 return false; 1731 } 1732 } 1733 add_to_history = false; 1734 } 1735 else 1736 { 1737 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1738 return true; 1739 } 1740 } 1741 else if (comment_command) 1742 { 1743 result.SetStatus (eReturnStatusSuccessFinishNoResult); 1744 return true; 1745 } 1746 1747 1748 Error error (PreprocessCommand (command_string)); 1749 1750 if (error.Fail()) 1751 { 1752 result.AppendError (error.AsCString()); 1753 result.SetStatus(eReturnStatusFailed); 1754 return false; 1755 } 1756 1757 // Phase 1. 1758 1759 // Before we do ANY kind of argument processing, we need to figure out what 1760 // the real/final command object is for the specified command. This gets 1761 // complicated by the fact that the user could have specified an alias, and, 1762 // in translating the alias, there may also be command options and/or even 1763 // data (including raw text strings) that need to be found and inserted into 1764 // the command line as part of the translation. So this first step is plain 1765 // look-up and replacement, resulting in: 1766 // 1. the command object whose Execute method will actually be called 1767 // 2. a revised command string, with all substitutions and replacements 1768 // taken care of 1769 // From 1 above, we can determine whether the Execute function wants raw 1770 // input or not. 1771 1772 CommandObject *cmd_obj = ResolveCommandImpl(command_string, result); 1773 1774 // Although the user may have abbreviated the command, the command_string now 1775 // has the command expanded to the full name. For example, if the input 1776 // was "br s -n main", command_string is now "breakpoint set -n main". 1777 1778 if (log) 1779 { 1780 log->Printf("HandleCommand, cmd_obj : '%s'", cmd_obj ? cmd_obj->GetCommandName() : "<not found>"); 1781 log->Printf("HandleCommand, (revised) command_string: '%s'", command_string.c_str()); 1782 const bool wants_raw_input = (cmd_obj != NULL) ? cmd_obj->WantsRawCommandString() : false; 1783 log->Printf("HandleCommand, wants_raw_input:'%s'", wants_raw_input ? "True" : "False"); 1784 } 1785 1786 // Phase 2. 1787 // Take care of things like setting up the history command & calling the appropriate Execute method on the 1788 // CommandObject, with the appropriate arguments. 1789 1790 if (cmd_obj != nullptr) 1791 { 1792 if (add_to_history) 1793 { 1794 Args command_args (command_string); 1795 const char *repeat_command = cmd_obj->GetRepeatCommand(command_args, 0); 1796 if (repeat_command != nullptr) 1797 m_repeat_command.assign(repeat_command); 1798 else 1799 m_repeat_command.assign(original_command_string.c_str()); 1800 1801 m_command_history.AppendString (original_command_string); 1802 } 1803 1804 std::string remainder; 1805 const std::size_t actual_cmd_name_len = strlen (cmd_obj->GetCommandName()); 1806 if (actual_cmd_name_len < command_string.length()) 1807 remainder = command_string.substr (actual_cmd_name_len); 1808 1809 // Remove any initial spaces 1810 size_t pos = remainder.find_first_not_of (k_white_space); 1811 if (pos != 0 && pos != std::string::npos) 1812 remainder.erase(0, pos); 1813 1814 if (log) 1815 log->Printf ("HandleCommand, command line after removing command name(s): '%s'", remainder.c_str()); 1816 1817 cmd_obj->Execute (remainder.c_str(), result); 1818 } 1819 else 1820 { 1821 // We didn't find the first command object, so complete the first argument. 1822 Args command_args (command_string); 1823 StringList matches; 1824 int num_matches; 1825 int cursor_index = 0; 1826 int cursor_char_position = strlen (command_args.GetArgumentAtIndex(0)); 1827 bool word_complete; 1828 num_matches = HandleCompletionMatches (command_args, 1829 cursor_index, 1830 cursor_char_position, 1831 0, 1832 -1, 1833 word_complete, 1834 matches); 1835 1836 if (num_matches > 0) 1837 { 1838 std::string error_msg; 1839 error_msg.assign ("ambiguous command '"); 1840 error_msg.append(command_args.GetArgumentAtIndex(0)); 1841 error_msg.append ("'."); 1842 1843 error_msg.append (" Possible completions:"); 1844 for (int i = 0; i < num_matches; i++) 1845 { 1846 error_msg.append ("\n\t"); 1847 error_msg.append (matches.GetStringAtIndex (i)); 1848 } 1849 error_msg.append ("\n"); 1850 result.AppendRawError (error_msg.c_str()); 1851 } 1852 else 1853 result.AppendErrorWithFormat ("Unrecognized command '%s'.\n", command_args.GetArgumentAtIndex (0)); 1854 1855 result.SetStatus (eReturnStatusFailed); 1856 } 1857 1858 if (log) 1859 log->Printf ("HandleCommand, command %s", (result.Succeeded() ? "succeeded" : "did not succeed")); 1860 1861 return result.Succeeded(); 1862 } 1863 1864 int 1865 CommandInterpreter::HandleCompletionMatches (Args &parsed_line, 1866 int &cursor_index, 1867 int &cursor_char_position, 1868 int match_start_point, 1869 int max_return_elements, 1870 bool &word_complete, 1871 StringList &matches) 1872 { 1873 int num_command_matches = 0; 1874 bool look_for_subcommand = false; 1875 1876 // For any of the command completions a unique match will be a complete word. 1877 word_complete = true; 1878 1879 if (cursor_index == -1) 1880 { 1881 // We got nothing on the command line, so return the list of commands 1882 bool include_aliases = true; 1883 num_command_matches = GetCommandNamesMatchingPartialString ("", include_aliases, matches); 1884 } 1885 else if (cursor_index == 0) 1886 { 1887 // The cursor is in the first argument, so just do a lookup in the dictionary. 1888 CommandObject *cmd_obj = GetCommandObject (parsed_line.GetArgumentAtIndex(0), &matches); 1889 num_command_matches = matches.GetSize(); 1890 1891 if (num_command_matches == 1 1892 && cmd_obj && cmd_obj->IsMultiwordObject() 1893 && matches.GetStringAtIndex(0) != nullptr 1894 && strcmp (parsed_line.GetArgumentAtIndex(0), matches.GetStringAtIndex(0)) == 0) 1895 { 1896 if (parsed_line.GetArgumentCount() == 1) 1897 { 1898 word_complete = true; 1899 } 1900 else 1901 { 1902 look_for_subcommand = true; 1903 num_command_matches = 0; 1904 matches.DeleteStringAtIndex(0); 1905 parsed_line.AppendArgument (""); 1906 cursor_index++; 1907 cursor_char_position = 0; 1908 } 1909 } 1910 } 1911 1912 if (cursor_index > 0 || look_for_subcommand) 1913 { 1914 // We are completing further on into a commands arguments, so find the command and tell it 1915 // to complete the command. 1916 // First see if there is a matching initial command: 1917 CommandObject *command_object = GetCommandObject (parsed_line.GetArgumentAtIndex(0)); 1918 if (command_object == nullptr) 1919 { 1920 return 0; 1921 } 1922 else 1923 { 1924 parsed_line.Shift(); 1925 cursor_index--; 1926 num_command_matches = command_object->HandleCompletion (parsed_line, 1927 cursor_index, 1928 cursor_char_position, 1929 match_start_point, 1930 max_return_elements, 1931 word_complete, 1932 matches); 1933 } 1934 } 1935 1936 return num_command_matches; 1937 1938 } 1939 1940 int 1941 CommandInterpreter::HandleCompletion (const char *current_line, 1942 const char *cursor, 1943 const char *last_char, 1944 int match_start_point, 1945 int max_return_elements, 1946 StringList &matches) 1947 { 1948 // We parse the argument up to the cursor, so the last argument in parsed_line is 1949 // the one containing the cursor, and the cursor is after the last character. 1950 1951 Args parsed_line(llvm::StringRef(current_line, last_char - current_line)); 1952 Args partial_parsed_line(llvm::StringRef(current_line, cursor - current_line)); 1953 1954 // Don't complete comments, and if the line we are completing is just the history repeat character, 1955 // substitute the appropriate history line. 1956 const char *first_arg = parsed_line.GetArgumentAtIndex(0); 1957 if (first_arg) 1958 { 1959 if (first_arg[0] == m_comment_char) 1960 return 0; 1961 else if (first_arg[0] == CommandHistory::g_repeat_char) 1962 { 1963 const char *history_string = m_command_history.FindString (first_arg); 1964 if (history_string != nullptr) 1965 { 1966 matches.Clear(); 1967 matches.InsertStringAtIndex(0, history_string); 1968 return -2; 1969 } 1970 else 1971 return 0; 1972 1973 } 1974 } 1975 1976 1977 int num_args = partial_parsed_line.GetArgumentCount(); 1978 int cursor_index = partial_parsed_line.GetArgumentCount() - 1; 1979 int cursor_char_position; 1980 1981 if (cursor_index == -1) 1982 cursor_char_position = 0; 1983 else 1984 cursor_char_position = strlen (partial_parsed_line.GetArgumentAtIndex(cursor_index)); 1985 1986 if (cursor > current_line && cursor[-1] == ' ') 1987 { 1988 // We are just after a space. If we are in an argument, then we will continue 1989 // parsing, but if we are between arguments, then we have to complete whatever the next 1990 // element would be. 1991 // We can distinguish the two cases because if we are in an argument (e.g. because the space is 1992 // protected by a quote) then the space will also be in the parsed argument... 1993 1994 const char *current_elem = partial_parsed_line.GetArgumentAtIndex(cursor_index); 1995 if (cursor_char_position == 0 || current_elem[cursor_char_position - 1] != ' ') 1996 { 1997 parsed_line.InsertArgumentAtIndex(cursor_index + 1, "", '\0'); 1998 cursor_index++; 1999 cursor_char_position = 0; 2000 } 2001 } 2002 2003 int num_command_matches; 2004 2005 matches.Clear(); 2006 2007 // Only max_return_elements == -1 is supported at present: 2008 assert (max_return_elements == -1); 2009 bool word_complete; 2010 num_command_matches = HandleCompletionMatches (parsed_line, 2011 cursor_index, 2012 cursor_char_position, 2013 match_start_point, 2014 max_return_elements, 2015 word_complete, 2016 matches); 2017 2018 if (num_command_matches <= 0) 2019 return num_command_matches; 2020 2021 if (num_args == 0) 2022 { 2023 // If we got an empty string, insert nothing. 2024 matches.InsertStringAtIndex(0, ""); 2025 } 2026 else 2027 { 2028 // Now figure out if there is a common substring, and if so put that in element 0, otherwise 2029 // put an empty string in element 0. 2030 std::string command_partial_str; 2031 if (cursor_index >= 0) 2032 command_partial_str.assign(parsed_line.GetArgumentAtIndex(cursor_index), 2033 parsed_line.GetArgumentAtIndex(cursor_index) + cursor_char_position); 2034 2035 std::string common_prefix; 2036 matches.LongestCommonPrefix (common_prefix); 2037 const size_t partial_name_len = command_partial_str.size(); 2038 common_prefix.erase (0, partial_name_len); 2039 2040 // If we matched a unique single command, add a space... 2041 // Only do this if the completer told us this was a complete word, however... 2042 if (num_command_matches == 1 && word_complete) 2043 { 2044 char quote_char = parsed_line.GetArgumentQuoteCharAtIndex(cursor_index); 2045 common_prefix = Args::EscapeLLDBCommandArgument(common_prefix, quote_char); 2046 if (quote_char != '\0') 2047 common_prefix.push_back(quote_char); 2048 common_prefix.push_back(' '); 2049 } 2050 matches.InsertStringAtIndex(0, common_prefix.c_str()); 2051 } 2052 return num_command_matches; 2053 } 2054 2055 2056 CommandInterpreter::~CommandInterpreter () 2057 { 2058 } 2059 2060 void 2061 CommandInterpreter::UpdatePrompt (const char *new_prompt) 2062 { 2063 EventSP prompt_change_event_sp (new Event(eBroadcastBitResetPrompt, new EventDataBytes (new_prompt)));; 2064 BroadcastEvent (prompt_change_event_sp); 2065 if (m_command_io_handler_sp) 2066 m_command_io_handler_sp->SetPrompt(new_prompt); 2067 } 2068 2069 2070 bool 2071 CommandInterpreter::Confirm (const char *message, bool default_answer) 2072 { 2073 // Check AutoConfirm first: 2074 if (m_debugger.GetAutoConfirm()) 2075 return default_answer; 2076 2077 IOHandlerConfirm *confirm = new IOHandlerConfirm(m_debugger, 2078 message, 2079 default_answer); 2080 IOHandlerSP io_handler_sp (confirm); 2081 m_debugger.RunIOHandler (io_handler_sp); 2082 return confirm->GetResponse(); 2083 } 2084 2085 CommandInterpreter::CommandAlias 2086 CommandInterpreter::GetAlias (const char *alias_name) 2087 { 2088 OptionArgVectorSP ret_val; 2089 2090 std::string alias (alias_name); 2091 2092 auto pos = m_alias_dict.find(alias); 2093 if (pos != m_alias_dict.end()) 2094 return pos->second; 2095 2096 return CommandInterpreter::CommandAlias(); 2097 } 2098 2099 bool 2100 CommandInterpreter::HasCommands () 2101 { 2102 return (!m_command_dict.empty()); 2103 } 2104 2105 bool 2106 CommandInterpreter::HasAliases () 2107 { 2108 return (!m_alias_dict.empty()); 2109 } 2110 2111 bool 2112 CommandInterpreter::HasUserCommands () 2113 { 2114 return (!m_user_dict.empty()); 2115 } 2116 2117 bool 2118 CommandInterpreter::HasAliasOptions () 2119 { 2120 return HasAliases(); 2121 } 2122 2123 void 2124 CommandInterpreter::BuildAliasCommandArgs (CommandObject *alias_cmd_obj, 2125 const char *alias_name, 2126 Args &cmd_args, 2127 std::string &raw_input_string, 2128 CommandReturnObject &result) 2129 { 2130 OptionArgVectorSP option_arg_vector_sp = GetAlias(alias_name).m_option_args_sp; 2131 2132 bool wants_raw_input = alias_cmd_obj->WantsRawCommandString(); 2133 2134 // Make sure that the alias name is the 0th element in cmd_args 2135 std::string alias_name_str = alias_name; 2136 if (alias_name_str.compare (cmd_args.GetArgumentAtIndex(0)) != 0) 2137 cmd_args.Unshift (alias_name); 2138 2139 Args new_args (alias_cmd_obj->GetCommandName()); 2140 if (new_args.GetArgumentCount() == 2) 2141 new_args.Shift(); 2142 2143 if (option_arg_vector_sp.get()) 2144 { 2145 if (wants_raw_input) 2146 { 2147 // We have a command that both has command options and takes raw input. Make *sure* it has a 2148 // " -- " in the right place in the raw_input_string. 2149 size_t pos = raw_input_string.find(" -- "); 2150 if (pos == std::string::npos) 2151 { 2152 // None found; assume it goes at the beginning of the raw input string 2153 raw_input_string.insert (0, " -- "); 2154 } 2155 } 2156 2157 OptionArgVector *option_arg_vector = option_arg_vector_sp.get(); 2158 const size_t old_size = cmd_args.GetArgumentCount(); 2159 std::vector<bool> used (old_size + 1, false); 2160 2161 used[0] = true; 2162 2163 for (size_t i = 0; i < option_arg_vector->size(); ++i) 2164 { 2165 OptionArgPair option_pair = (*option_arg_vector)[i]; 2166 OptionArgValue value_pair = option_pair.second; 2167 int value_type = value_pair.first; 2168 std::string option = option_pair.first; 2169 std::string value = value_pair.second; 2170 if (option.compare ("<argument>") == 0) 2171 { 2172 if (!wants_raw_input 2173 || (value.compare("--") != 0)) // Since we inserted this above, make sure we don't insert it twice 2174 new_args.AppendArgument (value.c_str()); 2175 } 2176 else 2177 { 2178 if (value_type != OptionParser::eOptionalArgument) 2179 new_args.AppendArgument (option.c_str()); 2180 if (value.compare ("<no-argument>") != 0) 2181 { 2182 int index = GetOptionArgumentPosition (value.c_str()); 2183 if (index == 0) 2184 { 2185 // value was NOT a positional argument; must be a real value 2186 if (value_type != OptionParser::eOptionalArgument) 2187 new_args.AppendArgument (value.c_str()); 2188 else 2189 { 2190 char buffer[255]; 2191 ::snprintf (buffer, sizeof (buffer), "%s%s", option.c_str(), value.c_str()); 2192 new_args.AppendArgument (buffer); 2193 } 2194 2195 } 2196 else if (static_cast<size_t>(index) >= cmd_args.GetArgumentCount()) 2197 { 2198 result.AppendErrorWithFormat 2199 ("Not enough arguments provided; you need at least %d arguments to use this alias.\n", 2200 index); 2201 result.SetStatus (eReturnStatusFailed); 2202 return; 2203 } 2204 else 2205 { 2206 // Find and remove cmd_args.GetArgumentAtIndex(i) from raw_input_string 2207 size_t strpos = raw_input_string.find (cmd_args.GetArgumentAtIndex (index)); 2208 if (strpos != std::string::npos) 2209 { 2210 raw_input_string = raw_input_string.erase (strpos, strlen (cmd_args.GetArgumentAtIndex (index))); 2211 } 2212 2213 if (value_type != OptionParser::eOptionalArgument) 2214 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (index)); 2215 else 2216 { 2217 char buffer[255]; 2218 ::snprintf (buffer, sizeof(buffer), "%s%s", option.c_str(), 2219 cmd_args.GetArgumentAtIndex (index)); 2220 new_args.AppendArgument (buffer); 2221 } 2222 used[index] = true; 2223 } 2224 } 2225 } 2226 } 2227 2228 for (size_t j = 0; j < cmd_args.GetArgumentCount(); ++j) 2229 { 2230 if (!used[j] && !wants_raw_input) 2231 new_args.AppendArgument (cmd_args.GetArgumentAtIndex (j)); 2232 } 2233 2234 cmd_args.Clear(); 2235 cmd_args.SetArguments (new_args.GetArgumentCount(), new_args.GetConstArgumentVector()); 2236 } 2237 else 2238 { 2239 result.SetStatus (eReturnStatusSuccessFinishNoResult); 2240 // This alias was not created with any options; nothing further needs to be done, unless it is a command that 2241 // wants raw input, in which case we need to clear the rest of the data from cmd_args, since its in the raw 2242 // input string. 2243 if (wants_raw_input) 2244 { 2245 cmd_args.Clear(); 2246 cmd_args.SetArguments (new_args.GetArgumentCount(), new_args.GetConstArgumentVector()); 2247 } 2248 return; 2249 } 2250 2251 result.SetStatus (eReturnStatusSuccessFinishNoResult); 2252 return; 2253 } 2254 2255 2256 int 2257 CommandInterpreter::GetOptionArgumentPosition (const char *in_string) 2258 { 2259 int position = 0; // Any string that isn't an argument position, i.e. '%' followed by an integer, gets a position 2260 // of zero. 2261 2262 const char *cptr = in_string; 2263 2264 // Does it start with '%' 2265 if (cptr[0] == '%') 2266 { 2267 ++cptr; 2268 2269 // Is the rest of it entirely digits? 2270 if (isdigit (cptr[0])) 2271 { 2272 const char *start = cptr; 2273 while (isdigit (cptr[0])) 2274 ++cptr; 2275 2276 // We've gotten to the end of the digits; are we at the end of the string? 2277 if (cptr[0] == '\0') 2278 position = atoi (start); 2279 } 2280 } 2281 2282 return position; 2283 } 2284 2285 void 2286 CommandInterpreter::SourceInitFile (bool in_cwd, CommandReturnObject &result) 2287 { 2288 FileSpec init_file; 2289 if (in_cwd) 2290 { 2291 ExecutionContext exe_ctx(GetExecutionContext()); 2292 Target *target = exe_ctx.GetTargetPtr(); 2293 if (target) 2294 { 2295 // In the current working directory we don't load any program specific 2296 // .lldbinit files, we only look for a ".lldbinit" file. 2297 if (m_skip_lldbinit_files) 2298 return; 2299 2300 LoadCWDlldbinitFile should_load = target->TargetProperties::GetLoadCWDlldbinitFile (); 2301 if (should_load == eLoadCWDlldbinitWarn) 2302 { 2303 FileSpec dot_lldb (".lldbinit", true); 2304 llvm::SmallString<64> home_dir_path; 2305 llvm::sys::path::home_directory (home_dir_path); 2306 FileSpec homedir_dot_lldb (home_dir_path.c_str(), false); 2307 homedir_dot_lldb.AppendPathComponent (".lldbinit"); 2308 homedir_dot_lldb.ResolvePath (); 2309 if (dot_lldb.Exists () 2310 && dot_lldb.GetDirectory() != homedir_dot_lldb.GetDirectory()) 2311 { 2312 result.AppendErrorWithFormat ( 2313 "There is a .lldbinit file in the current directory which is not being read.\n" 2314 "To silence this warning without sourcing in the local .lldbinit,\n" 2315 "add the following to the lldbinit file in your home directory:\n" 2316 " settings set target.load-cwd-lldbinit false\n" 2317 "To allow lldb to source .lldbinit files in the current working directory,\n" 2318 "set the value of this variable to true. Only do so if you understand and\n" 2319 "accept the security risk."); 2320 result.SetStatus (eReturnStatusFailed); 2321 return; 2322 } 2323 } 2324 else if (should_load == eLoadCWDlldbinitTrue) 2325 { 2326 init_file.SetFile ("./.lldbinit", true); 2327 } 2328 } 2329 } 2330 else 2331 { 2332 // If we aren't looking in the current working directory we are looking 2333 // in the home directory. We will first see if there is an application 2334 // specific ".lldbinit" file whose name is "~/.lldbinit" followed by a 2335 // "-" and the name of the program. If this file doesn't exist, we fall 2336 // back to just the "~/.lldbinit" file. We also obey any requests to not 2337 // load the init files. 2338 llvm::SmallString<64> home_dir_path; 2339 llvm::sys::path::home_directory(home_dir_path); 2340 FileSpec profilePath(home_dir_path.c_str(), false); 2341 profilePath.AppendPathComponent(".lldbinit"); 2342 std::string init_file_path = profilePath.GetPath(); 2343 2344 if (m_skip_app_init_files == false) 2345 { 2346 FileSpec program_file_spec(HostInfo::GetProgramFileSpec()); 2347 const char *program_name = program_file_spec.GetFilename().AsCString(); 2348 2349 if (program_name) 2350 { 2351 char program_init_file_name[PATH_MAX]; 2352 ::snprintf (program_init_file_name, sizeof(program_init_file_name), "%s-%s", init_file_path.c_str(), program_name); 2353 init_file.SetFile (program_init_file_name, true); 2354 if (!init_file.Exists()) 2355 init_file.Clear(); 2356 } 2357 } 2358 2359 if (!init_file && !m_skip_lldbinit_files) 2360 init_file.SetFile (init_file_path.c_str(), false); 2361 } 2362 2363 // If the file exists, tell HandleCommand to 'source' it; this will do the actual broadcasting 2364 // of the commands back to any appropriate listener (see CommandObjectSource::Execute for more details). 2365 2366 if (init_file.Exists()) 2367 { 2368 const bool saved_batch = SetBatchCommandMode (true); 2369 CommandInterpreterRunOptions options; 2370 options.SetSilent (true); 2371 options.SetStopOnError (false); 2372 options.SetStopOnContinue (true); 2373 2374 HandleCommandsFromFile (init_file, 2375 nullptr, // Execution context 2376 options, 2377 result); 2378 SetBatchCommandMode (saved_batch); 2379 } 2380 else 2381 { 2382 // nothing to be done if the file doesn't exist 2383 result.SetStatus(eReturnStatusSuccessFinishNoResult); 2384 } 2385 } 2386 2387 const char * 2388 CommandInterpreter::GetCommandPrefix() 2389 { 2390 const char * prefix = GetDebugger().GetIOHandlerCommandPrefix(); 2391 return prefix == NULL ? "" : prefix; 2392 } 2393 2394 PlatformSP 2395 CommandInterpreter::GetPlatform (bool prefer_target_platform) 2396 { 2397 PlatformSP platform_sp; 2398 if (prefer_target_platform) 2399 { 2400 ExecutionContext exe_ctx(GetExecutionContext()); 2401 Target *target = exe_ctx.GetTargetPtr(); 2402 if (target) 2403 platform_sp = target->GetPlatform(); 2404 } 2405 2406 if (!platform_sp) 2407 platform_sp = m_debugger.GetPlatformList().GetSelectedPlatform(); 2408 return platform_sp; 2409 } 2410 2411 void 2412 CommandInterpreter::HandleCommands (const StringList &commands, 2413 ExecutionContext *override_context, 2414 CommandInterpreterRunOptions &options, 2415 CommandReturnObject &result) 2416 { 2417 size_t num_lines = commands.GetSize(); 2418 2419 // If we are going to continue past a "continue" then we need to run the commands synchronously. 2420 // Make sure you reset this value anywhere you return from the function. 2421 2422 bool old_async_execution = m_debugger.GetAsyncExecution(); 2423 2424 // If we've been given an execution context, set it at the start, but don't keep resetting it or we will 2425 // cause series of commands that change the context, then do an operation that relies on that context to fail. 2426 2427 if (override_context != nullptr) 2428 UpdateExecutionContext (override_context); 2429 2430 if (!options.GetStopOnContinue()) 2431 { 2432 m_debugger.SetAsyncExecution (false); 2433 } 2434 2435 for (size_t idx = 0; idx < num_lines; idx++) 2436 { 2437 const char *cmd = commands.GetStringAtIndex(idx); 2438 if (cmd[0] == '\0') 2439 continue; 2440 2441 if (options.GetEchoCommands()) 2442 { 2443 result.AppendMessageWithFormat ("%s %s\n", 2444 m_debugger.GetPrompt(), 2445 cmd); 2446 } 2447 2448 CommandReturnObject tmp_result; 2449 // If override_context is not NULL, pass no_context_switching = true for 2450 // HandleCommand() since we updated our context already. 2451 2452 // We might call into a regex or alias command, in which case the add_to_history will get lost. This 2453 // m_command_source_depth dingus is the way we turn off adding to the history in that case, so set it up here. 2454 if (!options.GetAddToHistory()) 2455 m_command_source_depth++; 2456 bool success = HandleCommand(cmd, options.m_add_to_history, tmp_result, 2457 nullptr, /* override_context */ 2458 true, /* repeat_on_empty_command */ 2459 override_context != nullptr /* no_context_switching */); 2460 if (!options.GetAddToHistory()) 2461 m_command_source_depth--; 2462 2463 if (options.GetPrintResults()) 2464 { 2465 if (tmp_result.Succeeded()) 2466 result.AppendMessageWithFormat("%s", tmp_result.GetOutputData()); 2467 } 2468 2469 if (!success || !tmp_result.Succeeded()) 2470 { 2471 const char *error_msg = tmp_result.GetErrorData(); 2472 if (error_msg == nullptr || error_msg[0] == '\0') 2473 error_msg = "<unknown error>.\n"; 2474 if (options.GetStopOnError()) 2475 { 2476 result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' failed with %s", 2477 (uint64_t)idx, cmd, error_msg); 2478 result.SetStatus (eReturnStatusFailed); 2479 m_debugger.SetAsyncExecution (old_async_execution); 2480 return; 2481 } 2482 else if (options.GetPrintResults()) 2483 { 2484 result.AppendMessageWithFormat ("Command #%" PRIu64 " '%s' failed with %s", 2485 (uint64_t)idx + 1, 2486 cmd, 2487 error_msg); 2488 } 2489 } 2490 2491 if (result.GetImmediateOutputStream()) 2492 result.GetImmediateOutputStream()->Flush(); 2493 2494 if (result.GetImmediateErrorStream()) 2495 result.GetImmediateErrorStream()->Flush(); 2496 2497 // N.B. Can't depend on DidChangeProcessState, because the state coming into the command execution 2498 // could be running (for instance in Breakpoint Commands. 2499 // So we check the return value to see if it is has running in it. 2500 if ((tmp_result.GetStatus() == eReturnStatusSuccessContinuingNoResult) 2501 || (tmp_result.GetStatus() == eReturnStatusSuccessContinuingResult)) 2502 { 2503 if (options.GetStopOnContinue()) 2504 { 2505 // If we caused the target to proceed, and we're going to stop in that case, set the 2506 // status in our real result before returning. This is an error if the continue was not the 2507 // last command in the set of commands to be run. 2508 if (idx != num_lines - 1) 2509 result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' continued the target.\n", 2510 (uint64_t)idx + 1, cmd); 2511 else 2512 result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' continued the target.\n", (uint64_t)idx + 1, cmd); 2513 2514 result.SetStatus(tmp_result.GetStatus()); 2515 m_debugger.SetAsyncExecution (old_async_execution); 2516 2517 return; 2518 } 2519 } 2520 2521 // Also check for "stop on crash here: 2522 bool should_stop = false; 2523 if (tmp_result.GetDidChangeProcessState() && options.GetStopOnCrash()) 2524 { 2525 TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); 2526 if (target_sp) 2527 { 2528 ProcessSP process_sp (target_sp->GetProcessSP()); 2529 if (process_sp) 2530 { 2531 for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) 2532 { 2533 StopReason reason = thread_sp->GetStopReason(); 2534 if (reason == eStopReasonSignal || reason == eStopReasonException || reason == eStopReasonInstrumentation) 2535 { 2536 should_stop = true; 2537 break; 2538 } 2539 } 2540 } 2541 } 2542 if (should_stop) 2543 { 2544 if (idx != num_lines - 1) 2545 result.AppendErrorWithFormat("Aborting reading of commands after command #%" PRIu64 ": '%s' stopped with a signal or exception.\n", 2546 (uint64_t)idx + 1, cmd); 2547 else 2548 result.AppendMessageWithFormat("Command #%" PRIu64 " '%s' stopped with a signal or exception.\n", (uint64_t)idx + 1, cmd); 2549 2550 result.SetStatus(tmp_result.GetStatus()); 2551 m_debugger.SetAsyncExecution (old_async_execution); 2552 2553 return; 2554 } 2555 } 2556 2557 } 2558 2559 result.SetStatus (eReturnStatusSuccessFinishResult); 2560 m_debugger.SetAsyncExecution (old_async_execution); 2561 2562 return; 2563 } 2564 2565 // Make flags that we can pass into the IOHandler so our delegates can do the right thing 2566 enum { 2567 eHandleCommandFlagStopOnContinue = (1u << 0), 2568 eHandleCommandFlagStopOnError = (1u << 1), 2569 eHandleCommandFlagEchoCommand = (1u << 2), 2570 eHandleCommandFlagPrintResult = (1u << 3), 2571 eHandleCommandFlagStopOnCrash = (1u << 4) 2572 }; 2573 2574 void 2575 CommandInterpreter::HandleCommandsFromFile (FileSpec &cmd_file, 2576 ExecutionContext *context, 2577 CommandInterpreterRunOptions &options, 2578 CommandReturnObject &result) 2579 { 2580 if (cmd_file.Exists()) 2581 { 2582 StreamFileSP input_file_sp (new StreamFile()); 2583 2584 std::string cmd_file_path = cmd_file.GetPath(); 2585 Error error = input_file_sp->GetFile().Open(cmd_file_path.c_str(), File::eOpenOptionRead); 2586 2587 if (error.Success()) 2588 { 2589 Debugger &debugger = GetDebugger(); 2590 2591 uint32_t flags = 0; 2592 2593 if (options.m_stop_on_continue == eLazyBoolCalculate) 2594 { 2595 if (m_command_source_flags.empty()) 2596 { 2597 // Stop on continue by default 2598 flags |= eHandleCommandFlagStopOnContinue; 2599 } 2600 else if (m_command_source_flags.back() & eHandleCommandFlagStopOnContinue) 2601 { 2602 flags |= eHandleCommandFlagStopOnContinue; 2603 } 2604 } 2605 else if (options.m_stop_on_continue == eLazyBoolYes) 2606 { 2607 flags |= eHandleCommandFlagStopOnContinue; 2608 } 2609 2610 if (options.m_stop_on_error == eLazyBoolCalculate) 2611 { 2612 if (m_command_source_flags.empty()) 2613 { 2614 if (GetStopCmdSourceOnError()) 2615 flags |= eHandleCommandFlagStopOnError; 2616 } 2617 else if (m_command_source_flags.back() & eHandleCommandFlagStopOnError) 2618 { 2619 flags |= eHandleCommandFlagStopOnError; 2620 } 2621 } 2622 else if (options.m_stop_on_error == eLazyBoolYes) 2623 { 2624 flags |= eHandleCommandFlagStopOnError; 2625 } 2626 2627 if (options.GetStopOnCrash()) 2628 { 2629 if (m_command_source_flags.empty()) 2630 { 2631 // Echo command by default 2632 flags |= eHandleCommandFlagStopOnCrash; 2633 } 2634 else if (m_command_source_flags.back() & eHandleCommandFlagStopOnCrash) 2635 { 2636 flags |= eHandleCommandFlagStopOnCrash; 2637 } 2638 } 2639 2640 if (options.m_echo_commands == eLazyBoolCalculate) 2641 { 2642 if (m_command_source_flags.empty()) 2643 { 2644 // Echo command by default 2645 flags |= eHandleCommandFlagEchoCommand; 2646 } 2647 else if (m_command_source_flags.back() & eHandleCommandFlagEchoCommand) 2648 { 2649 flags |= eHandleCommandFlagEchoCommand; 2650 } 2651 } 2652 else if (options.m_echo_commands == eLazyBoolYes) 2653 { 2654 flags |= eHandleCommandFlagEchoCommand; 2655 } 2656 2657 if (options.m_print_results == eLazyBoolCalculate) 2658 { 2659 if (m_command_source_flags.empty()) 2660 { 2661 // Print output by default 2662 flags |= eHandleCommandFlagPrintResult; 2663 } 2664 else if (m_command_source_flags.back() & eHandleCommandFlagPrintResult) 2665 { 2666 flags |= eHandleCommandFlagPrintResult; 2667 } 2668 } 2669 else if (options.m_print_results == eLazyBoolYes) 2670 { 2671 flags |= eHandleCommandFlagPrintResult; 2672 } 2673 2674 if (flags & eHandleCommandFlagPrintResult) 2675 { 2676 debugger.GetOutputFile()->Printf("Executing commands in '%s'.\n", cmd_file_path.c_str()); 2677 } 2678 2679 // Used for inheriting the right settings when "command source" might have 2680 // nested "command source" commands 2681 lldb::StreamFileSP empty_stream_sp; 2682 m_command_source_flags.push_back(flags); 2683 IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, 2684 IOHandler::Type::CommandInterpreter, 2685 input_file_sp, 2686 empty_stream_sp, // Pass in an empty stream so we inherit the top input reader output stream 2687 empty_stream_sp, // Pass in an empty stream so we inherit the top input reader error stream 2688 flags, 2689 nullptr, // Pass in NULL for "editline_name" so no history is saved, or written 2690 debugger.GetPrompt(), 2691 NULL, 2692 false, // Not multi-line 2693 debugger.GetUseColor(), 2694 0, 2695 *this)); 2696 const bool old_async_execution = debugger.GetAsyncExecution(); 2697 2698 // Set synchronous execution if we are not stopping on continue 2699 if ((flags & eHandleCommandFlagStopOnContinue) == 0) 2700 debugger.SetAsyncExecution (false); 2701 2702 m_command_source_depth++; 2703 2704 debugger.RunIOHandler(io_handler_sp); 2705 if (!m_command_source_flags.empty()) 2706 m_command_source_flags.pop_back(); 2707 m_command_source_depth--; 2708 result.SetStatus (eReturnStatusSuccessFinishNoResult); 2709 debugger.SetAsyncExecution (old_async_execution); 2710 } 2711 else 2712 { 2713 result.AppendErrorWithFormat ("error: an error occurred read file '%s': %s\n", cmd_file_path.c_str(), error.AsCString()); 2714 result.SetStatus (eReturnStatusFailed); 2715 } 2716 2717 2718 } 2719 else 2720 { 2721 result.AppendErrorWithFormat ("Error reading commands from file %s - file not found.\n", 2722 cmd_file.GetFilename().AsCString("<Unknown>")); 2723 result.SetStatus (eReturnStatusFailed); 2724 return; 2725 } 2726 } 2727 2728 ScriptInterpreter * 2729 CommandInterpreter::GetScriptInterpreter(bool can_create) 2730 { 2731 if (m_script_interpreter_sp) 2732 return m_script_interpreter_sp.get(); 2733 2734 if (!can_create) 2735 return nullptr; 2736 2737 lldb::ScriptLanguage script_lang = GetDebugger().GetScriptLanguage(); 2738 m_script_interpreter_sp = PluginManager::GetScriptInterpreterForLanguage(script_lang, *this); 2739 return m_script_interpreter_sp.get(); 2740 } 2741 2742 bool 2743 CommandInterpreter::GetSynchronous () 2744 { 2745 return m_synchronous_execution; 2746 } 2747 2748 void 2749 CommandInterpreter::SetSynchronous (bool value) 2750 { 2751 m_synchronous_execution = value; 2752 } 2753 2754 void 2755 CommandInterpreter::OutputFormattedHelpText (Stream &strm, 2756 const char *prefix, 2757 const char *help_text) 2758 { 2759 const uint32_t max_columns = m_debugger.GetTerminalWidth(); 2760 if (prefix == NULL) 2761 prefix = ""; 2762 2763 size_t prefix_width = strlen(prefix); 2764 size_t line_width_max = max_columns - prefix_width; 2765 const char *help_text_end = help_text + strlen(help_text); 2766 const char *line_start = help_text; 2767 if (line_width_max < 16) 2768 line_width_max = help_text_end - help_text + prefix_width; 2769 2770 strm.IndentMore (prefix_width); 2771 while (line_start < help_text_end) 2772 { 2773 // Break each line at the first newline or last space/tab before 2774 // the maximum number of characters that fit on a line. Lines with no 2775 // natural break are left unbroken to wrap. 2776 const char *line_end = help_text_end; 2777 const char *line_scan = line_start; 2778 const char *line_scan_end = help_text_end; 2779 while (line_scan < line_scan_end) 2780 { 2781 char next = *line_scan; 2782 if (next == '\t' || next == ' ') 2783 { 2784 line_end = line_scan; 2785 line_scan_end = line_start + line_width_max; 2786 } 2787 else if (next == '\n' || next == '\0') 2788 { 2789 line_end = line_scan; 2790 break; 2791 } 2792 ++line_scan; 2793 } 2794 2795 // Prefix the first line, indent subsequent lines to line up 2796 if (line_start == help_text) 2797 strm.Write (prefix, prefix_width); 2798 else 2799 strm.Indent(); 2800 strm.Write (line_start, line_end - line_start); 2801 strm.EOL(); 2802 2803 // When a line breaks at whitespace consume it before continuing 2804 line_start = line_end; 2805 char next = *line_start; 2806 if (next == '\n') 2807 ++line_start; 2808 else while (next == ' ' || next == '\t') 2809 next = *(++line_start); 2810 } 2811 strm.IndentLess (prefix_width); 2812 } 2813 2814 void 2815 CommandInterpreter::OutputFormattedHelpText (Stream &strm, 2816 const char *word_text, 2817 const char *separator, 2818 const char *help_text, 2819 size_t max_word_len) 2820 { 2821 StreamString prefix_stream; 2822 prefix_stream.Printf (" %-*s %s ", (int)max_word_len, word_text, separator); 2823 OutputFormattedHelpText (strm, prefix_stream.GetData(), help_text); 2824 } 2825 2826 void 2827 CommandInterpreter::OutputHelpText (Stream &strm, 2828 const char *word_text, 2829 const char *separator, 2830 const char *help_text, 2831 uint32_t max_word_len) 2832 { 2833 int indent_size = max_word_len + strlen (separator) + 2; 2834 2835 strm.IndentMore (indent_size); 2836 2837 StreamString text_strm; 2838 text_strm.Printf ("%-*s %s %s", max_word_len, word_text, separator, help_text); 2839 2840 const uint32_t max_columns = m_debugger.GetTerminalWidth(); 2841 2842 size_t len = text_strm.GetSize(); 2843 const char *text = text_strm.GetData(); 2844 2845 uint32_t chars_left = max_columns; 2846 2847 for (uint32_t i = 0; i < len; i++) 2848 { 2849 if ((text[i] == ' ' && ::strchr((text+i+1), ' ') && chars_left < ::strchr((text+i+1), ' ')-(text+i)) || text[i] == '\n') 2850 { 2851 chars_left = max_columns - indent_size; 2852 strm.EOL(); 2853 strm.Indent(); 2854 } 2855 else 2856 { 2857 strm.PutChar(text[i]); 2858 chars_left--; 2859 } 2860 2861 } 2862 2863 strm.EOL(); 2864 strm.IndentLess(indent_size); 2865 } 2866 2867 void 2868 CommandInterpreter::FindCommandsForApropos (const char *search_word, StringList &commands_found, 2869 StringList &commands_help, bool search_builtin_commands, bool search_user_commands) 2870 { 2871 CommandObject::CommandMap::const_iterator pos; 2872 2873 if (search_builtin_commands) 2874 { 2875 for (pos = m_command_dict.begin(); pos != m_command_dict.end(); ++pos) 2876 { 2877 const char *command_name = pos->first.c_str(); 2878 CommandObject *cmd_obj = pos->second.get(); 2879 2880 if (cmd_obj->HelpTextContainsWord (search_word)) 2881 { 2882 commands_found.AppendString (command_name); 2883 commands_help.AppendString (cmd_obj->GetHelp()); 2884 } 2885 2886 if (cmd_obj->IsMultiwordObject()) 2887 cmd_obj->AproposAllSubCommands (command_name, 2888 search_word, 2889 commands_found, 2890 commands_help); 2891 2892 } 2893 } 2894 2895 if (search_user_commands) 2896 { 2897 for (pos = m_user_dict.begin(); pos != m_user_dict.end(); ++pos) 2898 { 2899 const char *command_name = pos->first.c_str(); 2900 CommandObject *cmd_obj = pos->second.get(); 2901 2902 if (cmd_obj->HelpTextContainsWord (search_word)) 2903 { 2904 commands_found.AppendString (command_name); 2905 commands_help.AppendString (cmd_obj->GetHelp()); 2906 } 2907 2908 if (cmd_obj->IsMultiwordObject()) 2909 cmd_obj->AproposAllSubCommands (command_name, 2910 search_word, 2911 commands_found, 2912 commands_help); 2913 2914 } 2915 } 2916 } 2917 2918 void 2919 CommandInterpreter::UpdateExecutionContext (ExecutionContext *override_context) 2920 { 2921 if (override_context != nullptr) 2922 { 2923 m_exe_ctx_ref = *override_context; 2924 } 2925 else 2926 { 2927 const bool adopt_selected = true; 2928 m_exe_ctx_ref.SetTargetPtr (m_debugger.GetSelectedTarget().get(), adopt_selected); 2929 } 2930 } 2931 2932 2933 size_t 2934 CommandInterpreter::GetProcessOutput () 2935 { 2936 // The process has stuff waiting for stderr; get it and write it out to the appropriate place. 2937 char stdio_buffer[1024]; 2938 size_t len; 2939 size_t total_bytes = 0; 2940 Error error; 2941 TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); 2942 if (target_sp) 2943 { 2944 ProcessSP process_sp (target_sp->GetProcessSP()); 2945 if (process_sp) 2946 { 2947 while ((len = process_sp->GetSTDOUT (stdio_buffer, sizeof (stdio_buffer), error)) > 0) 2948 { 2949 size_t bytes_written = len; 2950 m_debugger.GetOutputFile()->Write (stdio_buffer, bytes_written); 2951 total_bytes += len; 2952 } 2953 while ((len = process_sp->GetSTDERR (stdio_buffer, sizeof (stdio_buffer), error)) > 0) 2954 { 2955 size_t bytes_written = len; 2956 m_debugger.GetErrorFile()->Write (stdio_buffer, bytes_written); 2957 total_bytes += len; 2958 } 2959 } 2960 } 2961 return total_bytes; 2962 } 2963 2964 void 2965 CommandInterpreter::IOHandlerInputComplete (IOHandler &io_handler, std::string &line) 2966 { 2967 const bool is_interactive = io_handler.GetIsInteractive(); 2968 if (is_interactive == false) 2969 { 2970 // When we are not interactive, don't execute blank lines. This will happen 2971 // sourcing a commands file. We don't want blank lines to repeat the previous 2972 // command and cause any errors to occur (like redefining an alias, get an error 2973 // and stop parsing the commands file). 2974 if (line.empty()) 2975 return; 2976 2977 // When using a non-interactive file handle (like when sourcing commands from a file) 2978 // we need to echo the command out so we don't just see the command output and no 2979 // command... 2980 if (io_handler.GetFlags().Test(eHandleCommandFlagEchoCommand)) 2981 io_handler.GetOutputStreamFile()->Printf("%s%s\n", io_handler.GetPrompt(), line.c_str()); 2982 } 2983 2984 lldb_private::CommandReturnObject result; 2985 HandleCommand(line.c_str(), eLazyBoolCalculate, result); 2986 2987 // Now emit the command output text from the command we just executed 2988 if (io_handler.GetFlags().Test(eHandleCommandFlagPrintResult)) 2989 { 2990 // Display any STDOUT/STDERR _prior_ to emitting the command result text 2991 GetProcessOutput (); 2992 2993 if (!result.GetImmediateOutputStream()) 2994 { 2995 const char *output = result.GetOutputData(); 2996 if (output && output[0]) 2997 io_handler.GetOutputStreamFile()->PutCString(output); 2998 } 2999 3000 // Now emit the command error text from the command we just executed 3001 if (!result.GetImmediateErrorStream()) 3002 { 3003 const char *error = result.GetErrorData(); 3004 if (error && error[0]) 3005 io_handler.GetErrorStreamFile()->PutCString(error); 3006 } 3007 } 3008 3009 switch (result.GetStatus()) 3010 { 3011 case eReturnStatusInvalid: 3012 case eReturnStatusSuccessFinishNoResult: 3013 case eReturnStatusSuccessFinishResult: 3014 case eReturnStatusStarted: 3015 break; 3016 3017 case eReturnStatusSuccessContinuingNoResult: 3018 case eReturnStatusSuccessContinuingResult: 3019 if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnContinue)) 3020 io_handler.SetIsDone(true); 3021 break; 3022 3023 case eReturnStatusFailed: 3024 m_num_errors++; 3025 if (io_handler.GetFlags().Test(eHandleCommandFlagStopOnError)) 3026 io_handler.SetIsDone(true); 3027 break; 3028 3029 case eReturnStatusQuit: 3030 m_quit_requested = true; 3031 io_handler.SetIsDone(true); 3032 break; 3033 } 3034 3035 // Finally, if we're going to stop on crash, check that here: 3036 if (!m_quit_requested 3037 && result.GetDidChangeProcessState() 3038 && io_handler.GetFlags().Test(eHandleCommandFlagStopOnCrash)) 3039 { 3040 bool should_stop = false; 3041 TargetSP target_sp (m_debugger.GetTargetList().GetSelectedTarget()); 3042 if (target_sp) 3043 { 3044 ProcessSP process_sp (target_sp->GetProcessSP()); 3045 if (process_sp) 3046 { 3047 for (ThreadSP thread_sp : process_sp->GetThreadList().Threads()) 3048 { 3049 StopReason reason = thread_sp->GetStopReason(); 3050 if ((reason == eStopReasonSignal 3051 || reason == eStopReasonException 3052 || reason == eStopReasonInstrumentation) 3053 && !result.GetAbnormalStopWasExpected()) 3054 { 3055 should_stop = true; 3056 break; 3057 } 3058 } 3059 } 3060 } 3061 if (should_stop) 3062 { 3063 io_handler.SetIsDone(true); 3064 m_stopped_for_crash = true; 3065 } 3066 } 3067 } 3068 3069 bool 3070 CommandInterpreter::IOHandlerInterrupt (IOHandler &io_handler) 3071 { 3072 ExecutionContext exe_ctx (GetExecutionContext()); 3073 Process *process = exe_ctx.GetProcessPtr(); 3074 3075 if (process) 3076 { 3077 StateType state = process->GetState(); 3078 if (StateIsRunningState(state)) 3079 { 3080 process->Halt(); 3081 return true; // Don't do any updating when we are running 3082 } 3083 } 3084 3085 ScriptInterpreter *script_interpreter = GetScriptInterpreter (false); 3086 if (script_interpreter) 3087 { 3088 if (script_interpreter->Interrupt()) 3089 return true; 3090 } 3091 return false; 3092 } 3093 3094 void 3095 CommandInterpreter::GetLLDBCommandsFromIOHandler (const char *prompt, 3096 IOHandlerDelegate &delegate, 3097 bool asynchronously, 3098 void *baton) 3099 { 3100 Debugger &debugger = GetDebugger(); 3101 IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, 3102 IOHandler::Type::CommandList, 3103 "lldb", // Name of input reader for history 3104 prompt, // Prompt 3105 NULL, // Continuation prompt 3106 true, // Get multiple lines 3107 debugger.GetUseColor(), 3108 0, // Don't show line numbers 3109 delegate)); // IOHandlerDelegate 3110 3111 if (io_handler_sp) 3112 { 3113 io_handler_sp->SetUserData (baton); 3114 if (asynchronously) 3115 debugger.PushIOHandler(io_handler_sp); 3116 else 3117 debugger.RunIOHandler(io_handler_sp); 3118 } 3119 3120 } 3121 3122 3123 void 3124 CommandInterpreter::GetPythonCommandsFromIOHandler (const char *prompt, 3125 IOHandlerDelegate &delegate, 3126 bool asynchronously, 3127 void *baton) 3128 { 3129 Debugger &debugger = GetDebugger(); 3130 IOHandlerSP io_handler_sp (new IOHandlerEditline (debugger, 3131 IOHandler::Type::PythonCode, 3132 "lldb-python", // Name of input reader for history 3133 prompt, // Prompt 3134 NULL, // Continuation prompt 3135 true, // Get multiple lines 3136 debugger.GetUseColor(), 3137 0, // Don't show line numbers 3138 delegate)); // IOHandlerDelegate 3139 3140 if (io_handler_sp) 3141 { 3142 io_handler_sp->SetUserData (baton); 3143 if (asynchronously) 3144 debugger.PushIOHandler(io_handler_sp); 3145 else 3146 debugger.RunIOHandler(io_handler_sp); 3147 } 3148 3149 } 3150 3151 bool 3152 CommandInterpreter::IsActive () 3153 { 3154 return m_debugger.IsTopIOHandler (m_command_io_handler_sp); 3155 } 3156 3157 lldb::IOHandlerSP 3158 CommandInterpreter::GetIOHandler(bool force_create, CommandInterpreterRunOptions *options) 3159 { 3160 // Always re-create the IOHandlerEditline in case the input 3161 // changed. The old instance might have had a non-interactive 3162 // input and now it does or vice versa. 3163 if (force_create || !m_command_io_handler_sp) 3164 { 3165 // Always re-create the IOHandlerEditline in case the input 3166 // changed. The old instance might have had a non-interactive 3167 // input and now it does or vice versa. 3168 uint32_t flags = 0; 3169 3170 if (options) 3171 { 3172 if (options->m_stop_on_continue == eLazyBoolYes) 3173 flags |= eHandleCommandFlagStopOnContinue; 3174 if (options->m_stop_on_error == eLazyBoolYes) 3175 flags |= eHandleCommandFlagStopOnError; 3176 if (options->m_stop_on_crash == eLazyBoolYes) 3177 flags |= eHandleCommandFlagStopOnCrash; 3178 if (options->m_echo_commands != eLazyBoolNo) 3179 flags |= eHandleCommandFlagEchoCommand; 3180 if (options->m_print_results != eLazyBoolNo) 3181 flags |= eHandleCommandFlagPrintResult; 3182 } 3183 else 3184 { 3185 flags = eHandleCommandFlagEchoCommand | eHandleCommandFlagPrintResult; 3186 } 3187 3188 m_command_io_handler_sp.reset(new IOHandlerEditline (m_debugger, 3189 IOHandler::Type::CommandInterpreter, 3190 m_debugger.GetInputFile(), 3191 m_debugger.GetOutputFile(), 3192 m_debugger.GetErrorFile(), 3193 flags, 3194 "lldb", 3195 m_debugger.GetPrompt(), 3196 NULL, // Continuation prompt 3197 false, // Don't enable multiple line input, just single line commands 3198 m_debugger.GetUseColor(), 3199 0, // Don't show line numbers 3200 *this)); 3201 } 3202 return m_command_io_handler_sp; 3203 } 3204 3205 void 3206 CommandInterpreter::RunCommandInterpreter(bool auto_handle_events, 3207 bool spawn_thread, 3208 CommandInterpreterRunOptions &options) 3209 { 3210 // Always re-create the command interpreter when we run it in case 3211 // any file handles have changed. 3212 bool force_create = true; 3213 m_debugger.PushIOHandler(GetIOHandler(force_create, &options)); 3214 m_stopped_for_crash = false; 3215 3216 if (auto_handle_events) 3217 m_debugger.StartEventHandlerThread(); 3218 3219 if (spawn_thread) 3220 { 3221 m_debugger.StartIOHandlerThread(); 3222 } 3223 else 3224 { 3225 m_debugger.ExecuteIOHandlers(); 3226 3227 if (auto_handle_events) 3228 m_debugger.StopEventHandlerThread(); 3229 } 3230 3231 } 3232 3233 CommandObject * 3234 CommandInterpreter::ResolveCommandImpl(std::string &command_line, CommandReturnObject &result) 3235 { 3236 std::string scratch_command(command_line); // working copy so we don't modify command_line unless we succeed 3237 CommandObject *cmd_obj = nullptr; 3238 StreamString revised_command_line; 3239 bool wants_raw_input = false; 3240 size_t actual_cmd_name_len = 0; 3241 std::string next_word; 3242 StringList matches; 3243 bool done = false; 3244 while (!done) 3245 { 3246 char quote_char = '\0'; 3247 std::string suffix; 3248 ExtractCommand(scratch_command, next_word, suffix, quote_char); 3249 if (cmd_obj == nullptr) 3250 { 3251 std::string full_name; 3252 if (GetAliasFullName(next_word.c_str(), full_name)) 3253 { 3254 std::string alias_result; 3255 cmd_obj = BuildAliasResult(full_name.c_str(), scratch_command, alias_result, result); 3256 revised_command_line.Printf("%s", alias_result.c_str()); 3257 if (cmd_obj) 3258 { 3259 wants_raw_input = cmd_obj->WantsRawCommandString(); 3260 actual_cmd_name_len = strlen(cmd_obj->GetCommandName()); 3261 } 3262 } 3263 else 3264 { 3265 cmd_obj = GetCommandObject(next_word.c_str(), &matches); 3266 if (cmd_obj) 3267 { 3268 actual_cmd_name_len += strlen(cmd_obj->GetCommandName()); 3269 revised_command_line.Printf("%s", cmd_obj->GetCommandName()); 3270 wants_raw_input = cmd_obj->WantsRawCommandString(); 3271 } 3272 else 3273 { 3274 revised_command_line.Printf ("%s", next_word.c_str()); 3275 } 3276 } 3277 } 3278 else 3279 { 3280 if (cmd_obj->IsMultiwordObject ()) 3281 { 3282 CommandObject *sub_cmd_obj = cmd_obj->GetSubcommandObject(next_word.c_str()); 3283 if (sub_cmd_obj) 3284 { 3285 // The subcommand's name includes the parent command's name, 3286 // so restart rather than append to the revised_command_line. 3287 actual_cmd_name_len = strlen(sub_cmd_obj->GetCommandName()) + 1; 3288 revised_command_line.Clear(); 3289 revised_command_line.Printf("%s", sub_cmd_obj->GetCommandName()); 3290 cmd_obj = sub_cmd_obj; 3291 wants_raw_input = cmd_obj->WantsRawCommandString(); 3292 } 3293 else 3294 { 3295 if (quote_char) 3296 revised_command_line.Printf(" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char); 3297 else 3298 revised_command_line.Printf(" %s%s", next_word.c_str(), suffix.c_str()); 3299 done = true; 3300 } 3301 } 3302 else 3303 { 3304 if (quote_char) 3305 revised_command_line.Printf(" %c%s%s%c", quote_char, next_word.c_str(), suffix.c_str(), quote_char); 3306 else 3307 revised_command_line.Printf(" %s%s", next_word.c_str(), suffix.c_str()); 3308 done = true; 3309 } 3310 } 3311 3312 if (cmd_obj == nullptr) 3313 { 3314 const size_t num_matches = matches.GetSize(); 3315 if (matches.GetSize() > 1) { 3316 StreamString error_msg; 3317 error_msg.Printf("Ambiguous command '%s'. Possible matches:\n", next_word.c_str()); 3318 3319 for (uint32_t i = 0; i < num_matches; ++i) { 3320 error_msg.Printf("\t%s\n", matches.GetStringAtIndex(i)); 3321 } 3322 result.AppendRawError(error_msg.GetString().c_str()); 3323 } else { 3324 // We didn't have only one match, otherwise we wouldn't get here. 3325 assert(num_matches == 0); 3326 result.AppendErrorWithFormat("'%s' is not a valid command.\n", next_word.c_str()); 3327 } 3328 result.SetStatus(eReturnStatusFailed); 3329 return nullptr; 3330 } 3331 3332 if (cmd_obj->IsMultiwordObject()) 3333 { 3334 if (!suffix.empty()) 3335 { 3336 result.AppendErrorWithFormat("command '%s' did not recognize '%s%s%s' as valid (subcommand might be invalid).\n", 3337 cmd_obj->GetCommandName(), 3338 next_word.empty() ? "" : next_word.c_str(), 3339 next_word.empty() ? " -- " : " ", 3340 suffix.c_str()); 3341 result.SetStatus(eReturnStatusFailed); 3342 return nullptr; 3343 } 3344 } 3345 else 3346 { 3347 // If we found a normal command, we are done 3348 done = true; 3349 if (!suffix.empty()) 3350 { 3351 switch (suffix[0]) 3352 { 3353 case '/': 3354 // GDB format suffixes 3355 { 3356 Options *command_options = cmd_obj->GetOptions(); 3357 if (command_options && command_options->SupportsLongOption("gdb-format")) 3358 { 3359 std::string gdb_format_option("--gdb-format="); 3360 gdb_format_option += (suffix.c_str() + 1); 3361 3362 bool inserted = false; 3363 std::string &cmd = revised_command_line.GetString(); 3364 size_t arg_terminator_idx = FindArgumentTerminator(cmd); 3365 if (arg_terminator_idx != std::string::npos) 3366 { 3367 // Insert the gdb format option before the "--" that terminates options 3368 gdb_format_option.append(1,' '); 3369 cmd.insert(arg_terminator_idx, gdb_format_option); 3370 inserted = true; 3371 } 3372 3373 if (!inserted) 3374 revised_command_line.Printf(" %s", gdb_format_option.c_str()); 3375 3376 if (wants_raw_input && FindArgumentTerminator(cmd) == std::string::npos) 3377 revised_command_line.PutCString(" --"); 3378 } 3379 else 3380 { 3381 result.AppendErrorWithFormat("the '%s' command doesn't support the --gdb-format option\n", 3382 cmd_obj->GetCommandName()); 3383 result.SetStatus(eReturnStatusFailed); 3384 return nullptr; 3385 } 3386 } 3387 break; 3388 3389 default: 3390 result.AppendErrorWithFormat("unknown command shorthand suffix: '%s'\n", 3391 suffix.c_str()); 3392 result.SetStatus(eReturnStatusFailed); 3393 return nullptr; 3394 } 3395 } 3396 } 3397 if (scratch_command.empty()) 3398 done = true; 3399 } 3400 3401 if (!scratch_command.empty()) 3402 revised_command_line.Printf(" %s", scratch_command.c_str()); 3403 3404 if (cmd_obj != NULL) 3405 command_line = revised_command_line.GetData(); 3406 3407 return cmd_obj; 3408 } 3409