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