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