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