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