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