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