1 //===-- CommandObjectCommands.cpp -------------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "llvm/ADT/StringRef.h" 10 11 #include "CommandObjectCommands.h" 12 #include "CommandObjectHelp.h" 13 #include "lldb/Core/Debugger.h" 14 #include "lldb/Core/IOHandler.h" 15 #include "lldb/Host/OptionParser.h" 16 #include "lldb/Interpreter/CommandHistory.h" 17 #include "lldb/Interpreter/CommandInterpreter.h" 18 #include "lldb/Interpreter/CommandObjectRegexCommand.h" 19 #include "lldb/Interpreter/CommandReturnObject.h" 20 #include "lldb/Interpreter/OptionArgParser.h" 21 #include "lldb/Interpreter/OptionValueBoolean.h" 22 #include "lldb/Interpreter/OptionValueString.h" 23 #include "lldb/Interpreter/OptionValueUInt64.h" 24 #include "lldb/Interpreter/Options.h" 25 #include "lldb/Interpreter/ScriptInterpreter.h" 26 #include "lldb/Utility/Args.h" 27 #include "lldb/Utility/StringList.h" 28 29 using namespace lldb; 30 using namespace lldb_private; 31 32 // CommandObjectCommandsSource 33 34 static constexpr OptionDefinition g_history_options[] = { 35 // clang-format off 36 { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "How many history commands to print." }, 37 { LLDB_OPT_SET_1, false, "start-index", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Index at which to start printing history commands (or end to mean tail mode)." }, 38 { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." }, 39 { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeBoolean, "Clears the current command history." }, 40 // clang-format on 41 }; 42 43 class CommandObjectCommandsHistory : public CommandObjectParsed { 44 public: 45 CommandObjectCommandsHistory(CommandInterpreter &interpreter) 46 : CommandObjectParsed(interpreter, "command history", 47 "Dump the history of commands in this session.\n" 48 "Commands in the history list can be run again " 49 "using \"!<INDEX>\". \"!-<OFFSET>\" will re-run " 50 "the command that is <OFFSET> commands from the end" 51 " of the list (counting the current command).", 52 nullptr), 53 m_options() {} 54 55 ~CommandObjectCommandsHistory() override = default; 56 57 Options *GetOptions() override { return &m_options; } 58 59 protected: 60 class CommandOptions : public Options { 61 public: 62 CommandOptions() 63 : Options(), m_start_idx(0), m_stop_idx(0), m_count(0), m_clear(false) { 64 } 65 66 ~CommandOptions() override = default; 67 68 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 69 ExecutionContext *execution_context) override { 70 Status error; 71 const int short_option = m_getopt_table[option_idx].val; 72 73 switch (short_option) { 74 case 'c': 75 error = m_count.SetValueFromString(option_arg, eVarSetOperationAssign); 76 break; 77 case 's': 78 if (option_arg == "end") { 79 m_start_idx.SetCurrentValue(UINT64_MAX); 80 m_start_idx.SetOptionWasSet(); 81 } else 82 error = m_start_idx.SetValueFromString(option_arg, 83 eVarSetOperationAssign); 84 break; 85 case 'e': 86 error = 87 m_stop_idx.SetValueFromString(option_arg, eVarSetOperationAssign); 88 break; 89 case 'C': 90 m_clear.SetCurrentValue(true); 91 m_clear.SetOptionWasSet(); 92 break; 93 default: 94 error.SetErrorStringWithFormat("unrecognized option '%c'", 95 short_option); 96 break; 97 } 98 99 return error; 100 } 101 102 void OptionParsingStarting(ExecutionContext *execution_context) override { 103 m_start_idx.Clear(); 104 m_stop_idx.Clear(); 105 m_count.Clear(); 106 m_clear.Clear(); 107 } 108 109 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 110 return llvm::makeArrayRef(g_history_options); 111 } 112 113 // Instance variables to hold the values for command options. 114 115 OptionValueUInt64 m_start_idx; 116 OptionValueUInt64 m_stop_idx; 117 OptionValueUInt64 m_count; 118 OptionValueBoolean m_clear; 119 }; 120 121 bool DoExecute(Args &command, CommandReturnObject &result) override { 122 if (m_options.m_clear.GetCurrentValue() && 123 m_options.m_clear.OptionWasSet()) { 124 m_interpreter.GetCommandHistory().Clear(); 125 result.SetStatus(lldb::eReturnStatusSuccessFinishNoResult); 126 } else { 127 if (m_options.m_start_idx.OptionWasSet() && 128 m_options.m_stop_idx.OptionWasSet() && 129 m_options.m_count.OptionWasSet()) { 130 result.AppendError("--count, --start-index and --end-index cannot be " 131 "all specified in the same invocation"); 132 result.SetStatus(lldb::eReturnStatusFailed); 133 } else { 134 std::pair<bool, uint64_t> start_idx( 135 m_options.m_start_idx.OptionWasSet(), 136 m_options.m_start_idx.GetCurrentValue()); 137 std::pair<bool, uint64_t> stop_idx( 138 m_options.m_stop_idx.OptionWasSet(), 139 m_options.m_stop_idx.GetCurrentValue()); 140 std::pair<bool, uint64_t> count(m_options.m_count.OptionWasSet(), 141 m_options.m_count.GetCurrentValue()); 142 143 const CommandHistory &history(m_interpreter.GetCommandHistory()); 144 145 if (start_idx.first && start_idx.second == UINT64_MAX) { 146 if (count.first) { 147 start_idx.second = history.GetSize() - count.second; 148 stop_idx.second = history.GetSize() - 1; 149 } else if (stop_idx.first) { 150 start_idx.second = stop_idx.second; 151 stop_idx.second = history.GetSize() - 1; 152 } else { 153 start_idx.second = 0; 154 stop_idx.second = history.GetSize() - 1; 155 } 156 } else { 157 if (!start_idx.first && !stop_idx.first && !count.first) { 158 start_idx.second = 0; 159 stop_idx.second = history.GetSize() - 1; 160 } else if (start_idx.first) { 161 if (count.first) { 162 stop_idx.second = start_idx.second + count.second - 1; 163 } else if (!stop_idx.first) { 164 stop_idx.second = history.GetSize() - 1; 165 } 166 } else if (stop_idx.first) { 167 if (count.first) { 168 if (stop_idx.second >= count.second) 169 start_idx.second = stop_idx.second - count.second + 1; 170 else 171 start_idx.second = 0; 172 } 173 } else /* if (count.first) */ 174 { 175 start_idx.second = 0; 176 stop_idx.second = count.second - 1; 177 } 178 } 179 history.Dump(result.GetOutputStream(), start_idx.second, 180 stop_idx.second); 181 } 182 } 183 return result.Succeeded(); 184 } 185 186 CommandOptions m_options; 187 }; 188 189 // CommandObjectCommandsSource 190 191 static constexpr OptionDefinition g_source_options[] = { 192 // clang-format off 193 { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, stop executing commands on error." }, 194 { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, stop executing commands on continue." }, 195 { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true don't echo commands while executing." }, 196 // clang-format on 197 }; 198 199 class CommandObjectCommandsSource : public CommandObjectParsed { 200 public: 201 CommandObjectCommandsSource(CommandInterpreter &interpreter) 202 : CommandObjectParsed( 203 interpreter, "command source", 204 "Read and execute LLDB commands from the file <filename>.", 205 nullptr), 206 m_options() { 207 CommandArgumentEntry arg; 208 CommandArgumentData file_arg; 209 210 // Define the first (and only) variant of this arg. 211 file_arg.arg_type = eArgTypeFilename; 212 file_arg.arg_repetition = eArgRepeatPlain; 213 214 // There is only one variant this argument could be; put it into the 215 // argument entry. 216 arg.push_back(file_arg); 217 218 // Push the data for the first argument into the m_arguments vector. 219 m_arguments.push_back(arg); 220 } 221 222 ~CommandObjectCommandsSource() override = default; 223 224 const char *GetRepeatCommand(Args ¤t_command_args, 225 uint32_t index) override { 226 return ""; 227 } 228 229 int HandleArgumentCompletion( 230 CompletionRequest &request, 231 OptionElementVector &opt_element_vector) override { 232 CommandCompletions::InvokeCommonCompletionCallbacks( 233 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 234 request, nullptr); 235 return request.GetNumberOfMatches(); 236 } 237 238 Options *GetOptions() override { return &m_options; } 239 240 protected: 241 class CommandOptions : public Options { 242 public: 243 CommandOptions() 244 : Options(), m_stop_on_error(true), m_silent_run(false), 245 m_stop_on_continue(true) {} 246 247 ~CommandOptions() override = default; 248 249 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 250 ExecutionContext *execution_context) override { 251 Status error; 252 const int short_option = m_getopt_table[option_idx].val; 253 254 switch (short_option) { 255 case 'e': 256 error = m_stop_on_error.SetValueFromString(option_arg); 257 break; 258 259 case 'c': 260 error = m_stop_on_continue.SetValueFromString(option_arg); 261 break; 262 263 case 's': 264 error = m_silent_run.SetValueFromString(option_arg); 265 break; 266 267 default: 268 error.SetErrorStringWithFormat("unrecognized option '%c'", 269 short_option); 270 break; 271 } 272 273 return error; 274 } 275 276 void OptionParsingStarting(ExecutionContext *execution_context) override { 277 m_stop_on_error.Clear(); 278 m_silent_run.Clear(); 279 m_stop_on_continue.Clear(); 280 } 281 282 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 283 return llvm::makeArrayRef(g_source_options); 284 } 285 286 // Instance variables to hold the values for command options. 287 288 OptionValueBoolean m_stop_on_error; 289 OptionValueBoolean m_silent_run; 290 OptionValueBoolean m_stop_on_continue; 291 }; 292 293 bool DoExecute(Args &command, CommandReturnObject &result) override { 294 if (command.GetArgumentCount() != 1) { 295 result.AppendErrorWithFormat( 296 "'%s' takes exactly one executable filename argument.\n", 297 GetCommandName().str().c_str()); 298 result.SetStatus(eReturnStatusFailed); 299 return false; 300 } 301 302 FileSpec cmd_file(command[0].ref); 303 FileSystem::Instance().Resolve(cmd_file); 304 ExecutionContext *exe_ctx = nullptr; // Just use the default context. 305 306 // If any options were set, then use them 307 if (m_options.m_stop_on_error.OptionWasSet() || 308 m_options.m_silent_run.OptionWasSet() || 309 m_options.m_stop_on_continue.OptionWasSet()) { 310 // Use user set settings 311 CommandInterpreterRunOptions options; 312 313 if (m_options.m_stop_on_continue.OptionWasSet()) 314 options.SetStopOnContinue( 315 m_options.m_stop_on_continue.GetCurrentValue()); 316 317 if (m_options.m_stop_on_error.OptionWasSet()) 318 options.SetStopOnError(m_options.m_stop_on_error.GetCurrentValue()); 319 320 // Individual silent setting is override for global command echo settings. 321 if (m_options.m_silent_run.GetCurrentValue()) { 322 options.SetSilent(true); 323 } else { 324 options.SetPrintResults(true); 325 options.SetEchoCommands(m_interpreter.GetEchoCommands()); 326 options.SetEchoCommentCommands(m_interpreter.GetEchoCommentCommands()); 327 } 328 329 m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result); 330 } else { 331 // No options were set, inherit any settings from nested "command source" 332 // commands, or set to sane default settings... 333 CommandInterpreterRunOptions options; 334 m_interpreter.HandleCommandsFromFile(cmd_file, exe_ctx, options, result); 335 } 336 return result.Succeeded(); 337 } 338 339 CommandOptions m_options; 340 }; 341 342 #pragma mark CommandObjectCommandsAlias 343 // CommandObjectCommandsAlias 344 345 static constexpr OptionDefinition g_alias_options[] = { 346 // clang-format off 347 { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "Help text for this command" }, 348 { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "Long help text for this command" }, 349 // clang-format on 350 }; 351 352 static const char *g_python_command_instructions = 353 "Enter your Python command(s). Type 'DONE' to end.\n" 354 "You must define a Python function with this signature:\n" 355 "def my_command_impl(debugger, args, result, internal_dict):\n"; 356 357 class CommandObjectCommandsAlias : public CommandObjectRaw { 358 protected: 359 class CommandOptions : public OptionGroup { 360 public: 361 CommandOptions() : OptionGroup(), m_help(), m_long_help() {} 362 363 ~CommandOptions() override = default; 364 365 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 366 return llvm::makeArrayRef(g_alias_options); 367 } 368 369 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, 370 ExecutionContext *execution_context) override { 371 Status error; 372 373 const int short_option = GetDefinitions()[option_idx].short_option; 374 std::string option_str(option_value); 375 376 switch (short_option) { 377 case 'h': 378 m_help.SetCurrentValue(option_str); 379 m_help.SetOptionWasSet(); 380 break; 381 382 case 'H': 383 m_long_help.SetCurrentValue(option_str); 384 m_long_help.SetOptionWasSet(); 385 break; 386 387 default: 388 error.SetErrorStringWithFormat("invalid short option character '%c'", 389 short_option); 390 break; 391 } 392 393 return error; 394 } 395 396 void OptionParsingStarting(ExecutionContext *execution_context) override { 397 m_help.Clear(); 398 m_long_help.Clear(); 399 } 400 401 OptionValueString m_help; 402 OptionValueString m_long_help; 403 }; 404 405 OptionGroupOptions m_option_group; 406 CommandOptions m_command_options; 407 408 public: 409 Options *GetOptions() override { return &m_option_group; } 410 411 CommandObjectCommandsAlias(CommandInterpreter &interpreter) 412 : CommandObjectRaw( 413 interpreter, "command alias", 414 "Define a custom command in terms of an existing command."), 415 m_option_group(), m_command_options() { 416 m_option_group.Append(&m_command_options); 417 m_option_group.Finalize(); 418 419 SetHelpLong( 420 "'alias' allows the user to create a short-cut or abbreviation for long \ 421 commands, multi-word commands, and commands that take particular options. \ 422 Below are some simple examples of how one might use the 'alias' command:" 423 R"( 424 425 (lldb) command alias sc script 426 427 Creates the abbreviation 'sc' for the 'script' command. 428 429 (lldb) command alias bp breakpoint 430 431 )" 432 " Creates the abbreviation 'bp' for the 'breakpoint' command. Since \ 433 breakpoint commands are two-word commands, the user would still need to \ 434 enter the second word after 'bp', e.g. 'bp enable' or 'bp delete'." 435 R"( 436 437 (lldb) command alias bpl breakpoint list 438 439 Creates the abbreviation 'bpl' for the two-word command 'breakpoint list'. 440 441 )" 442 "An alias can include some options for the command, with the values either \ 443 filled in at the time the alias is created, or specified as positional \ 444 arguments, to be filled in when the alias is invoked. The following example \ 445 shows how to create aliases with options:" 446 R"( 447 448 (lldb) command alias bfl breakpoint set -f %1 -l %2 449 450 )" 451 " Creates the abbreviation 'bfl' (for break-file-line), with the -f and -l \ 452 options already part of the alias. So if the user wants to set a breakpoint \ 453 by file and line without explicitly having to use the -f and -l options, the \ 454 user can now use 'bfl' instead. The '%1' and '%2' are positional placeholders \ 455 for the actual arguments that will be passed when the alias command is used. \ 456 The number in the placeholder refers to the position/order the actual value \ 457 occupies when the alias is used. All the occurrences of '%1' in the alias \ 458 will be replaced with the first argument, all the occurrences of '%2' in the \ 459 alias will be replaced with the second argument, and so on. This also allows \ 460 actual arguments to be used multiple times within an alias (see 'process \ 461 launch' example below)." 462 R"( 463 464 )" 465 "Note: the positional arguments must substitute as whole words in the resultant \ 466 command, so you can't at present do something like this to append the file extension \ 467 \".cpp\":" 468 R"( 469 470 (lldb) command alias bcppfl breakpoint set -f %1.cpp -l %2 471 472 )" 473 "For more complex aliasing, use the \"command regex\" command instead. In the \ 474 'bfl' case above, the actual file value will be filled in with the first argument \ 475 following 'bfl' and the actual line number value will be filled in with the second \ 476 argument. The user would use this alias as follows:" 477 R"( 478 479 (lldb) command alias bfl breakpoint set -f %1 -l %2 480 (lldb) bfl my-file.c 137 481 482 This would be the same as if the user had entered 'breakpoint set -f my-file.c -l 137'. 483 484 Another example: 485 486 (lldb) command alias pltty process launch -s -o %1 -e %1 487 (lldb) pltty /dev/tty0 488 489 Interpreted as 'process launch -s -o /dev/tty0 -e /dev/tty0' 490 491 )" 492 "If the user always wanted to pass the same value to a particular option, the \ 493 alias could be defined with that value directly in the alias as a constant, \ 494 rather than using a positional placeholder:" 495 R"( 496 497 (lldb) command alias bl3 breakpoint set -f %1 -l 3 498 499 Always sets a breakpoint on line 3 of whatever file is indicated.)"); 500 501 CommandArgumentEntry arg1; 502 CommandArgumentEntry arg2; 503 CommandArgumentEntry arg3; 504 CommandArgumentData alias_arg; 505 CommandArgumentData cmd_arg; 506 CommandArgumentData options_arg; 507 508 // Define the first (and only) variant of this arg. 509 alias_arg.arg_type = eArgTypeAliasName; 510 alias_arg.arg_repetition = eArgRepeatPlain; 511 512 // There is only one variant this argument could be; put it into the 513 // argument entry. 514 arg1.push_back(alias_arg); 515 516 // Define the first (and only) variant of this arg. 517 cmd_arg.arg_type = eArgTypeCommandName; 518 cmd_arg.arg_repetition = eArgRepeatPlain; 519 520 // There is only one variant this argument could be; put it into the 521 // argument entry. 522 arg2.push_back(cmd_arg); 523 524 // Define the first (and only) variant of this arg. 525 options_arg.arg_type = eArgTypeAliasOptions; 526 options_arg.arg_repetition = eArgRepeatOptional; 527 528 // There is only one variant this argument could be; put it into the 529 // argument entry. 530 arg3.push_back(options_arg); 531 532 // Push the data for the first argument into the m_arguments vector. 533 m_arguments.push_back(arg1); 534 m_arguments.push_back(arg2); 535 m_arguments.push_back(arg3); 536 } 537 538 ~CommandObjectCommandsAlias() override = default; 539 540 protected: 541 bool DoExecute(llvm::StringRef raw_command_line, 542 CommandReturnObject &result) override { 543 if (raw_command_line.empty()) { 544 result.AppendError("'command alias' requires at least two arguments"); 545 return false; 546 } 547 548 ExecutionContext exe_ctx = GetCommandInterpreter().GetExecutionContext(); 549 m_option_group.NotifyOptionParsingStarting(&exe_ctx); 550 551 OptionsWithRaw args_with_suffix(raw_command_line); 552 const char *remainder = args_with_suffix.GetRawPart().c_str(); 553 554 if (args_with_suffix.HasArgs()) 555 if (!ParseOptionsAndNotify(args_with_suffix.GetArgs(), result, 556 m_option_group, exe_ctx)) 557 return false; 558 559 llvm::StringRef raw_command_string(remainder); 560 Args args(raw_command_string); 561 562 if (args.GetArgumentCount() < 2) { 563 result.AppendError("'command alias' requires at least two arguments"); 564 result.SetStatus(eReturnStatusFailed); 565 return false; 566 } 567 568 // Get the alias command. 569 570 auto alias_command = args[0].ref; 571 if (alias_command.startswith("-")) { 572 result.AppendError("aliases starting with a dash are not supported"); 573 if (alias_command == "--help" || alias_command == "--long-help") { 574 result.AppendWarning("if trying to pass options to 'command alias' add " 575 "a -- at the end of the options"); 576 } 577 result.SetStatus(eReturnStatusFailed); 578 return false; 579 } 580 581 // Strip the new alias name off 'raw_command_string' (leave it on args, 582 // which gets passed to 'Execute', which does the stripping itself. 583 size_t pos = raw_command_string.find(alias_command); 584 if (pos == 0) { 585 raw_command_string = raw_command_string.substr(alias_command.size()); 586 pos = raw_command_string.find_first_not_of(' '); 587 if ((pos != std::string::npos) && (pos > 0)) 588 raw_command_string = raw_command_string.substr(pos); 589 } else { 590 result.AppendError("Error parsing command string. No alias created."); 591 result.SetStatus(eReturnStatusFailed); 592 return false; 593 } 594 595 // Verify that the command is alias-able. 596 if (m_interpreter.CommandExists(alias_command)) { 597 result.AppendErrorWithFormat( 598 "'%s' is a permanent debugger command and cannot be redefined.\n", 599 args[0].c_str()); 600 result.SetStatus(eReturnStatusFailed); 601 return false; 602 } 603 604 // Get CommandObject that is being aliased. The command name is read from 605 // the front of raw_command_string. raw_command_string is returned with the 606 // name of the command object stripped off the front. 607 llvm::StringRef original_raw_command_string = raw_command_string; 608 CommandObject *cmd_obj = 609 m_interpreter.GetCommandObjectForCommand(raw_command_string); 610 611 if (!cmd_obj) { 612 result.AppendErrorWithFormat("invalid command given to 'command alias'. " 613 "'%s' does not begin with a valid command." 614 " No alias created.", 615 original_raw_command_string.str().c_str()); 616 result.SetStatus(eReturnStatusFailed); 617 return false; 618 } else if (!cmd_obj->WantsRawCommandString()) { 619 // Note that args was initialized with the original command, and has not 620 // been updated to this point. Therefore can we pass it to the version of 621 // Execute that does not need/expect raw input in the alias. 622 return HandleAliasingNormalCommand(args, result); 623 } else { 624 return HandleAliasingRawCommand(alias_command, raw_command_string, 625 *cmd_obj, result); 626 } 627 return result.Succeeded(); 628 } 629 630 bool HandleAliasingRawCommand(llvm::StringRef alias_command, 631 llvm::StringRef raw_command_string, 632 CommandObject &cmd_obj, 633 CommandReturnObject &result) { 634 // Verify & handle any options/arguments passed to the alias command 635 636 OptionArgVectorSP option_arg_vector_sp = 637 OptionArgVectorSP(new OptionArgVector); 638 639 if (CommandObjectSP cmd_obj_sp = 640 m_interpreter.GetCommandSPExact(cmd_obj.GetCommandName(), false)) { 641 if (m_interpreter.AliasExists(alias_command) || 642 m_interpreter.UserCommandExists(alias_command)) { 643 result.AppendWarningWithFormat( 644 "Overwriting existing definition for '%s'.\n", 645 alias_command.str().c_str()); 646 } 647 if (CommandAlias *alias = m_interpreter.AddAlias( 648 alias_command, cmd_obj_sp, raw_command_string)) { 649 if (m_command_options.m_help.OptionWasSet()) 650 alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 651 if (m_command_options.m_long_help.OptionWasSet()) 652 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 653 result.SetStatus(eReturnStatusSuccessFinishNoResult); 654 } else { 655 result.AppendError("Unable to create requested alias.\n"); 656 result.SetStatus(eReturnStatusFailed); 657 } 658 659 } else { 660 result.AppendError("Unable to create requested alias.\n"); 661 result.SetStatus(eReturnStatusFailed); 662 } 663 664 return result.Succeeded(); 665 } 666 667 bool HandleAliasingNormalCommand(Args &args, CommandReturnObject &result) { 668 size_t argc = args.GetArgumentCount(); 669 670 if (argc < 2) { 671 result.AppendError("'command alias' requires at least two arguments"); 672 result.SetStatus(eReturnStatusFailed); 673 return false; 674 } 675 676 // Save these in std::strings since we're going to shift them off. 677 const std::string alias_command(args[0].ref); 678 const std::string actual_command(args[1].ref); 679 680 args.Shift(); // Shift the alias command word off the argument vector. 681 args.Shift(); // Shift the old command word off the argument vector. 682 683 // Verify that the command is alias'able, and get the appropriate command 684 // object. 685 686 if (m_interpreter.CommandExists(alias_command)) { 687 result.AppendErrorWithFormat( 688 "'%s' is a permanent debugger command and cannot be redefined.\n", 689 alias_command.c_str()); 690 result.SetStatus(eReturnStatusFailed); 691 return false; 692 } 693 694 CommandObjectSP command_obj_sp( 695 m_interpreter.GetCommandSPExact(actual_command, true)); 696 CommandObjectSP subcommand_obj_sp; 697 bool use_subcommand = false; 698 if (!command_obj_sp) { 699 result.AppendErrorWithFormat("'%s' is not an existing command.\n", 700 actual_command.c_str()); 701 result.SetStatus(eReturnStatusFailed); 702 return false; 703 } 704 CommandObject *cmd_obj = command_obj_sp.get(); 705 CommandObject *sub_cmd_obj = nullptr; 706 OptionArgVectorSP option_arg_vector_sp = 707 OptionArgVectorSP(new OptionArgVector); 708 709 while (cmd_obj->IsMultiwordObject() && !args.empty()) { 710 auto sub_command = args[0].ref; 711 assert(!sub_command.empty()); 712 subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command); 713 if (!subcommand_obj_sp) { 714 result.AppendErrorWithFormat( 715 "'%s' is not a valid sub-command of '%s'. " 716 "Unable to create alias.\n", 717 args[0].c_str(), actual_command.c_str()); 718 result.SetStatus(eReturnStatusFailed); 719 return false; 720 } 721 722 sub_cmd_obj = subcommand_obj_sp.get(); 723 use_subcommand = true; 724 args.Shift(); // Shift the sub_command word off the argument vector. 725 cmd_obj = sub_cmd_obj; 726 } 727 728 // Verify & handle any options/arguments passed to the alias command 729 730 std::string args_string; 731 732 if (!args.empty()) { 733 CommandObjectSP tmp_sp = 734 m_interpreter.GetCommandSPExact(cmd_obj->GetCommandName(), false); 735 if (use_subcommand) 736 tmp_sp = m_interpreter.GetCommandSPExact(sub_cmd_obj->GetCommandName(), 737 false); 738 739 args.GetCommandString(args_string); 740 } 741 742 if (m_interpreter.AliasExists(alias_command) || 743 m_interpreter.UserCommandExists(alias_command)) { 744 result.AppendWarningWithFormat( 745 "Overwriting existing definition for '%s'.\n", alias_command.c_str()); 746 } 747 748 if (CommandAlias *alias = m_interpreter.AddAlias( 749 alias_command, use_subcommand ? subcommand_obj_sp : command_obj_sp, 750 args_string)) { 751 if (m_command_options.m_help.OptionWasSet()) 752 alias->SetHelp(m_command_options.m_help.GetCurrentValue()); 753 if (m_command_options.m_long_help.OptionWasSet()) 754 alias->SetHelpLong(m_command_options.m_long_help.GetCurrentValue()); 755 result.SetStatus(eReturnStatusSuccessFinishNoResult); 756 } else { 757 result.AppendError("Unable to create requested alias.\n"); 758 result.SetStatus(eReturnStatusFailed); 759 return false; 760 } 761 762 return result.Succeeded(); 763 } 764 }; 765 766 #pragma mark CommandObjectCommandsUnalias 767 // CommandObjectCommandsUnalias 768 769 class CommandObjectCommandsUnalias : public CommandObjectParsed { 770 public: 771 CommandObjectCommandsUnalias(CommandInterpreter &interpreter) 772 : CommandObjectParsed( 773 interpreter, "command unalias", 774 "Delete one or more custom commands defined by 'command alias'.", 775 nullptr) { 776 CommandArgumentEntry arg; 777 CommandArgumentData alias_arg; 778 779 // Define the first (and only) variant of this arg. 780 alias_arg.arg_type = eArgTypeAliasName; 781 alias_arg.arg_repetition = eArgRepeatPlain; 782 783 // There is only one variant this argument could be; put it into the 784 // argument entry. 785 arg.push_back(alias_arg); 786 787 // Push the data for the first argument into the m_arguments vector. 788 m_arguments.push_back(arg); 789 } 790 791 ~CommandObjectCommandsUnalias() override = default; 792 793 protected: 794 bool DoExecute(Args &args, CommandReturnObject &result) override { 795 CommandObject::CommandMap::iterator pos; 796 CommandObject *cmd_obj; 797 798 if (args.empty()) { 799 result.AppendError("must call 'unalias' with a valid alias"); 800 result.SetStatus(eReturnStatusFailed); 801 return false; 802 } 803 804 auto command_name = args[0].ref; 805 cmd_obj = m_interpreter.GetCommandObject(command_name); 806 if (!cmd_obj) { 807 result.AppendErrorWithFormat( 808 "'%s' is not a known command.\nTry 'help' to see a " 809 "current list of commands.\n", 810 args[0].c_str()); 811 result.SetStatus(eReturnStatusFailed); 812 return false; 813 } 814 815 if (m_interpreter.CommandExists(command_name)) { 816 if (cmd_obj->IsRemovable()) { 817 result.AppendErrorWithFormat( 818 "'%s' is not an alias, it is a debugger command which can be " 819 "removed using the 'command delete' command.\n", 820 args[0].c_str()); 821 } else { 822 result.AppendErrorWithFormat( 823 "'%s' is a permanent debugger command and cannot be removed.\n", 824 args[0].c_str()); 825 } 826 result.SetStatus(eReturnStatusFailed); 827 return false; 828 } 829 830 if (!m_interpreter.RemoveAlias(command_name)) { 831 if (m_interpreter.AliasExists(command_name)) 832 result.AppendErrorWithFormat( 833 "Error occurred while attempting to unalias '%s'.\n", 834 args[0].c_str()); 835 else 836 result.AppendErrorWithFormat("'%s' is not an existing alias.\n", 837 args[0].c_str()); 838 result.SetStatus(eReturnStatusFailed); 839 return false; 840 } 841 842 result.SetStatus(eReturnStatusSuccessFinishNoResult); 843 return result.Succeeded(); 844 } 845 }; 846 847 #pragma mark CommandObjectCommandsDelete 848 // CommandObjectCommandsDelete 849 850 class CommandObjectCommandsDelete : public CommandObjectParsed { 851 public: 852 CommandObjectCommandsDelete(CommandInterpreter &interpreter) 853 : CommandObjectParsed( 854 interpreter, "command delete", 855 "Delete one or more custom commands defined by 'command regex'.", 856 nullptr) { 857 CommandArgumentEntry arg; 858 CommandArgumentData alias_arg; 859 860 // Define the first (and only) variant of this arg. 861 alias_arg.arg_type = eArgTypeCommandName; 862 alias_arg.arg_repetition = eArgRepeatPlain; 863 864 // There is only one variant this argument could be; put it into the 865 // argument entry. 866 arg.push_back(alias_arg); 867 868 // Push the data for the first argument into the m_arguments vector. 869 m_arguments.push_back(arg); 870 } 871 872 ~CommandObjectCommandsDelete() override = default; 873 874 protected: 875 bool DoExecute(Args &args, CommandReturnObject &result) override { 876 CommandObject::CommandMap::iterator pos; 877 878 if (args.empty()) { 879 result.AppendErrorWithFormat("must call '%s' with one or more valid user " 880 "defined regular expression command names", 881 GetCommandName().str().c_str()); 882 result.SetStatus(eReturnStatusFailed); 883 } 884 885 auto command_name = args[0].ref; 886 if (!m_interpreter.CommandExists(command_name)) { 887 StreamString error_msg_stream; 888 const bool generate_upropos = true; 889 const bool generate_type_lookup = false; 890 CommandObjectHelp::GenerateAdditionalHelpAvenuesMessage( 891 &error_msg_stream, command_name, llvm::StringRef(), llvm::StringRef(), 892 generate_upropos, generate_type_lookup); 893 result.AppendError(error_msg_stream.GetString()); 894 result.SetStatus(eReturnStatusFailed); 895 return false; 896 } 897 898 if (!m_interpreter.RemoveCommand(command_name)) { 899 result.AppendErrorWithFormat( 900 "'%s' is a permanent debugger command and cannot be removed.\n", 901 args[0].c_str()); 902 result.SetStatus(eReturnStatusFailed); 903 return false; 904 } 905 906 result.SetStatus(eReturnStatusSuccessFinishNoResult); 907 return true; 908 } 909 }; 910 911 // CommandObjectCommandsAddRegex 912 913 static constexpr OptionDefinition g_regex_options[] = { 914 // clang-format off 915 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The help text to display for this command." }, 916 { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." }, 917 // clang-format on 918 }; 919 920 #pragma mark CommandObjectCommandsAddRegex 921 922 class CommandObjectCommandsAddRegex : public CommandObjectParsed, 923 public IOHandlerDelegateMultiline { 924 public: 925 CommandObjectCommandsAddRegex(CommandInterpreter &interpreter) 926 : CommandObjectParsed( 927 interpreter, "command regex", "Define a custom command in terms of " 928 "existing commands by matching " 929 "regular expressions.", 930 "command regex <cmd-name> [s/<regex>/<subst>/ ...]"), 931 IOHandlerDelegateMultiline("", 932 IOHandlerDelegate::Completion::LLDBCommand), 933 m_options() { 934 SetHelpLong( 935 R"( 936 )" 937 "This command allows the user to create powerful regular expression commands \ 938 with substitutions. The regular expressions and substitutions are specified \ 939 using the regular expression substitution format of:" 940 R"( 941 942 s/<regex>/<subst>/ 943 944 )" 945 "<regex> is a regular expression that can use parenthesis to capture regular \ 946 expression input and substitute the captured matches in the output using %1 \ 947 for the first match, %2 for the second, and so on." 948 R"( 949 950 )" 951 "The regular expressions can all be specified on the command line if more than \ 952 one argument is provided. If just the command name is provided on the command \ 953 line, then the regular expressions and substitutions can be entered on separate \ 954 lines, followed by an empty line to terminate the command definition." 955 R"( 956 957 EXAMPLES 958 959 )" 960 "The following example will define a regular expression command named 'f' that \ 961 will call 'finish' if there are no arguments, or 'frame select <frame-idx>' if \ 962 a number follows 'f':" 963 R"( 964 965 (lldb) command regex f s/^$/finish/ 's/([0-9]+)/frame select %1/')"); 966 } 967 968 ~CommandObjectCommandsAddRegex() override = default; 969 970 protected: 971 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 972 StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 973 if (output_sp && interactive) { 974 output_sp->PutCString("Enter one or more sed substitution commands in " 975 "the form: 's/<regex>/<subst>/'.\nTerminate the " 976 "substitution list with an empty line.\n"); 977 output_sp->Flush(); 978 } 979 } 980 981 void IOHandlerInputComplete(IOHandler &io_handler, 982 std::string &data) override { 983 io_handler.SetIsDone(true); 984 if (m_regex_cmd_up) { 985 StringList lines; 986 if (lines.SplitIntoLines(data)) { 987 const size_t num_lines = lines.GetSize(); 988 bool check_only = false; 989 for (size_t i = 0; i < num_lines; ++i) { 990 llvm::StringRef bytes_strref(lines[i]); 991 Status error = AppendRegexSubstitution(bytes_strref, check_only); 992 if (error.Fail()) { 993 if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) { 994 StreamSP out_stream = GetDebugger().GetAsyncOutputStream(); 995 out_stream->Printf("error: %s\n", error.AsCString()); 996 } 997 } 998 } 999 } 1000 if (m_regex_cmd_up->HasRegexEntries()) { 1001 CommandObjectSP cmd_sp(m_regex_cmd_up.release()); 1002 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 1003 } 1004 } 1005 } 1006 1007 bool DoExecute(Args &command, CommandReturnObject &result) override { 1008 const size_t argc = command.GetArgumentCount(); 1009 if (argc == 0) { 1010 result.AppendError("usage: 'command regex <command-name> " 1011 "[s/<regex1>/<subst1>/ s/<regex2>/<subst2>/ ...]'\n"); 1012 result.SetStatus(eReturnStatusFailed); 1013 return false; 1014 } 1015 1016 Status error; 1017 auto name = command[0].ref; 1018 m_regex_cmd_up = llvm::make_unique<CommandObjectRegexCommand>( 1019 m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0, 1020 true); 1021 1022 if (argc == 1) { 1023 Debugger &debugger = GetDebugger(); 1024 bool color_prompt = debugger.GetUseColor(); 1025 const bool multiple_lines = true; // Get multiple lines 1026 IOHandlerSP io_handler_sp(new IOHandlerEditline( 1027 debugger, IOHandler::Type::Other, 1028 "lldb-regex", // Name of input reader for history 1029 llvm::StringRef("> "), // Prompt 1030 llvm::StringRef(), // Continuation prompt 1031 multiple_lines, color_prompt, 1032 0, // Don't show line numbers 1033 *this, nullptr)); 1034 1035 if (io_handler_sp) { 1036 debugger.PushIOHandler(io_handler_sp); 1037 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1038 } 1039 } else { 1040 for (auto &entry : command.entries().drop_front()) { 1041 bool check_only = false; 1042 error = AppendRegexSubstitution(entry.ref, check_only); 1043 if (error.Fail()) 1044 break; 1045 } 1046 1047 if (error.Success()) { 1048 AddRegexCommandToInterpreter(); 1049 } 1050 } 1051 if (error.Fail()) { 1052 result.AppendError(error.AsCString()); 1053 result.SetStatus(eReturnStatusFailed); 1054 } 1055 1056 return result.Succeeded(); 1057 } 1058 1059 Status AppendRegexSubstitution(const llvm::StringRef ®ex_sed, 1060 bool check_only) { 1061 Status error; 1062 1063 if (!m_regex_cmd_up) { 1064 error.SetErrorStringWithFormat( 1065 "invalid regular expression command object for: '%.*s'", 1066 (int)regex_sed.size(), regex_sed.data()); 1067 return error; 1068 } 1069 1070 size_t regex_sed_size = regex_sed.size(); 1071 1072 if (regex_sed_size <= 1) { 1073 error.SetErrorStringWithFormat( 1074 "regular expression substitution string is too short: '%.*s'", 1075 (int)regex_sed.size(), regex_sed.data()); 1076 return error; 1077 } 1078 1079 if (regex_sed[0] != 's') { 1080 error.SetErrorStringWithFormat("regular expression substitution string " 1081 "doesn't start with 's': '%.*s'", 1082 (int)regex_sed.size(), regex_sed.data()); 1083 return error; 1084 } 1085 const size_t first_separator_char_pos = 1; 1086 // use the char that follows 's' as the regex separator character so we can 1087 // have "s/<regex>/<subst>/" or "s|<regex>|<subst>|" 1088 const char separator_char = regex_sed[first_separator_char_pos]; 1089 const size_t second_separator_char_pos = 1090 regex_sed.find(separator_char, first_separator_char_pos + 1); 1091 1092 if (second_separator_char_pos == std::string::npos) { 1093 error.SetErrorStringWithFormat( 1094 "missing second '%c' separator char after '%.*s' in '%.*s'", 1095 separator_char, 1096 (int)(regex_sed.size() - first_separator_char_pos - 1), 1097 regex_sed.data() + (first_separator_char_pos + 1), 1098 (int)regex_sed.size(), regex_sed.data()); 1099 return error; 1100 } 1101 1102 const size_t third_separator_char_pos = 1103 regex_sed.find(separator_char, second_separator_char_pos + 1); 1104 1105 if (third_separator_char_pos == std::string::npos) { 1106 error.SetErrorStringWithFormat( 1107 "missing third '%c' separator char after '%.*s' in '%.*s'", 1108 separator_char, 1109 (int)(regex_sed.size() - second_separator_char_pos - 1), 1110 regex_sed.data() + (second_separator_char_pos + 1), 1111 (int)regex_sed.size(), regex_sed.data()); 1112 return error; 1113 } 1114 1115 if (third_separator_char_pos != regex_sed_size - 1) { 1116 // Make sure that everything that follows the last regex separator char 1117 if (regex_sed.find_first_not_of("\t\n\v\f\r ", 1118 third_separator_char_pos + 1) != 1119 std::string::npos) { 1120 error.SetErrorStringWithFormat( 1121 "extra data found after the '%.*s' regular expression substitution " 1122 "string: '%.*s'", 1123 (int)third_separator_char_pos + 1, regex_sed.data(), 1124 (int)(regex_sed.size() - third_separator_char_pos - 1), 1125 regex_sed.data() + (third_separator_char_pos + 1)); 1126 return error; 1127 } 1128 } else if (first_separator_char_pos + 1 == second_separator_char_pos) { 1129 error.SetErrorStringWithFormat( 1130 "<regex> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 1131 separator_char, separator_char, separator_char, (int)regex_sed.size(), 1132 regex_sed.data()); 1133 return error; 1134 } else if (second_separator_char_pos + 1 == third_separator_char_pos) { 1135 error.SetErrorStringWithFormat( 1136 "<subst> can't be empty in 's%c<regex>%c<subst>%c' string: '%.*s'", 1137 separator_char, separator_char, separator_char, (int)regex_sed.size(), 1138 regex_sed.data()); 1139 return error; 1140 } 1141 1142 if (!check_only) { 1143 std::string regex(regex_sed.substr(first_separator_char_pos + 1, 1144 second_separator_char_pos - 1145 first_separator_char_pos - 1)); 1146 std::string subst(regex_sed.substr(second_separator_char_pos + 1, 1147 third_separator_char_pos - 1148 second_separator_char_pos - 1)); 1149 m_regex_cmd_up->AddRegexCommand(regex.c_str(), subst.c_str()); 1150 } 1151 return error; 1152 } 1153 1154 void AddRegexCommandToInterpreter() { 1155 if (m_regex_cmd_up) { 1156 if (m_regex_cmd_up->HasRegexEntries()) { 1157 CommandObjectSP cmd_sp(m_regex_cmd_up.release()); 1158 m_interpreter.AddCommand(cmd_sp->GetCommandName(), cmd_sp, true); 1159 } 1160 } 1161 } 1162 1163 private: 1164 std::unique_ptr<CommandObjectRegexCommand> m_regex_cmd_up; 1165 1166 class CommandOptions : public Options { 1167 public: 1168 CommandOptions() : Options() {} 1169 1170 ~CommandOptions() override = default; 1171 1172 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1173 ExecutionContext *execution_context) override { 1174 Status error; 1175 const int short_option = m_getopt_table[option_idx].val; 1176 1177 switch (short_option) { 1178 case 'h': 1179 m_help.assign(option_arg); 1180 break; 1181 case 's': 1182 m_syntax.assign(option_arg); 1183 break; 1184 default: 1185 error.SetErrorStringWithFormat("unrecognized option '%c'", 1186 short_option); 1187 break; 1188 } 1189 1190 return error; 1191 } 1192 1193 void OptionParsingStarting(ExecutionContext *execution_context) override { 1194 m_help.clear(); 1195 m_syntax.clear(); 1196 } 1197 1198 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1199 return llvm::makeArrayRef(g_regex_options); 1200 } 1201 1202 // TODO: Convert these functions to return StringRefs. 1203 const char *GetHelp() { 1204 return (m_help.empty() ? nullptr : m_help.c_str()); 1205 } 1206 1207 const char *GetSyntax() { 1208 return (m_syntax.empty() ? nullptr : m_syntax.c_str()); 1209 } 1210 1211 protected: 1212 // Instance variables to hold the values for command options. 1213 1214 std::string m_help; 1215 std::string m_syntax; 1216 }; 1217 1218 Options *GetOptions() override { return &m_options; } 1219 1220 CommandOptions m_options; 1221 }; 1222 1223 class CommandObjectPythonFunction : public CommandObjectRaw { 1224 public: 1225 CommandObjectPythonFunction(CommandInterpreter &interpreter, std::string name, 1226 std::string funct, std::string help, 1227 ScriptedCommandSynchronicity synch) 1228 : CommandObjectRaw(interpreter, name), 1229 m_function_name(funct), m_synchro(synch), m_fetched_help_long(false) { 1230 if (!help.empty()) 1231 SetHelp(help); 1232 else { 1233 StreamString stream; 1234 stream.Printf("For more information run 'help %s'", name.c_str()); 1235 SetHelp(stream.GetString()); 1236 } 1237 } 1238 1239 ~CommandObjectPythonFunction() override = default; 1240 1241 bool IsRemovable() const override { return true; } 1242 1243 const std::string &GetFunctionName() { return m_function_name; } 1244 1245 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 1246 1247 llvm::StringRef GetHelpLong() override { 1248 if (m_fetched_help_long) 1249 return CommandObjectRaw::GetHelpLong(); 1250 1251 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1252 if (!scripter) 1253 return CommandObjectRaw::GetHelpLong(); 1254 1255 std::string docstring; 1256 m_fetched_help_long = 1257 scripter->GetDocumentationForItem(m_function_name.c_str(), docstring); 1258 if (!docstring.empty()) 1259 SetHelpLong(docstring); 1260 return CommandObjectRaw::GetHelpLong(); 1261 } 1262 1263 protected: 1264 bool DoExecute(llvm::StringRef raw_command_line, 1265 CommandReturnObject &result) override { 1266 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1267 1268 Status error; 1269 1270 result.SetStatus(eReturnStatusInvalid); 1271 1272 if (!scripter || 1273 !scripter->RunScriptBasedCommand(m_function_name.c_str(), 1274 raw_command_line, m_synchro, result, 1275 error, m_exe_ctx)) { 1276 result.AppendError(error.AsCString()); 1277 result.SetStatus(eReturnStatusFailed); 1278 } else { 1279 // Don't change the status if the command already set it... 1280 if (result.GetStatus() == eReturnStatusInvalid) { 1281 if (result.GetOutputData().empty()) 1282 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1283 else 1284 result.SetStatus(eReturnStatusSuccessFinishResult); 1285 } 1286 } 1287 1288 return result.Succeeded(); 1289 } 1290 1291 private: 1292 std::string m_function_name; 1293 ScriptedCommandSynchronicity m_synchro; 1294 bool m_fetched_help_long; 1295 }; 1296 1297 class CommandObjectScriptingObject : public CommandObjectRaw { 1298 public: 1299 CommandObjectScriptingObject(CommandInterpreter &interpreter, 1300 std::string name, 1301 StructuredData::GenericSP cmd_obj_sp, 1302 ScriptedCommandSynchronicity synch) 1303 : CommandObjectRaw(interpreter, name), 1304 m_cmd_obj_sp(cmd_obj_sp), m_synchro(synch), m_fetched_help_short(false), 1305 m_fetched_help_long(false) { 1306 StreamString stream; 1307 stream.Printf("For more information run 'help %s'", name.c_str()); 1308 SetHelp(stream.GetString()); 1309 if (ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter()) 1310 GetFlags().Set(scripter->GetFlagsForCommandObject(cmd_obj_sp)); 1311 } 1312 1313 ~CommandObjectScriptingObject() override = default; 1314 1315 bool IsRemovable() const override { return true; } 1316 1317 StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; } 1318 1319 ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } 1320 1321 llvm::StringRef GetHelp() override { 1322 if (m_fetched_help_short) 1323 return CommandObjectRaw::GetHelp(); 1324 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1325 if (!scripter) 1326 return CommandObjectRaw::GetHelp(); 1327 std::string docstring; 1328 m_fetched_help_short = 1329 scripter->GetShortHelpForCommandObject(m_cmd_obj_sp, docstring); 1330 if (!docstring.empty()) 1331 SetHelp(docstring); 1332 1333 return CommandObjectRaw::GetHelp(); 1334 } 1335 1336 llvm::StringRef GetHelpLong() override { 1337 if (m_fetched_help_long) 1338 return CommandObjectRaw::GetHelpLong(); 1339 1340 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1341 if (!scripter) 1342 return CommandObjectRaw::GetHelpLong(); 1343 1344 std::string docstring; 1345 m_fetched_help_long = 1346 scripter->GetLongHelpForCommandObject(m_cmd_obj_sp, docstring); 1347 if (!docstring.empty()) 1348 SetHelpLong(docstring); 1349 return CommandObjectRaw::GetHelpLong(); 1350 } 1351 1352 protected: 1353 bool DoExecute(llvm::StringRef raw_command_line, 1354 CommandReturnObject &result) override { 1355 ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); 1356 1357 Status error; 1358 1359 result.SetStatus(eReturnStatusInvalid); 1360 1361 if (!scripter || 1362 !scripter->RunScriptBasedCommand(m_cmd_obj_sp, raw_command_line, 1363 m_synchro, result, error, m_exe_ctx)) { 1364 result.AppendError(error.AsCString()); 1365 result.SetStatus(eReturnStatusFailed); 1366 } else { 1367 // Don't change the status if the command already set it... 1368 if (result.GetStatus() == eReturnStatusInvalid) { 1369 if (result.GetOutputData().empty()) 1370 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1371 else 1372 result.SetStatus(eReturnStatusSuccessFinishResult); 1373 } 1374 } 1375 1376 return result.Succeeded(); 1377 } 1378 1379 private: 1380 StructuredData::GenericSP m_cmd_obj_sp; 1381 ScriptedCommandSynchronicity m_synchro; 1382 bool m_fetched_help_short : 1; 1383 bool m_fetched_help_long : 1; 1384 }; 1385 1386 // CommandObjectCommandsScriptImport 1387 1388 static constexpr OptionDefinition g_script_import_options[] = { 1389 // clang-format off 1390 { LLDB_OPT_SET_1, false, "allow-reload", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow the script to be loaded even if it was already loaded before. This argument exists for backwards compatibility, but reloading is always allowed, whether you specify it or not." }, 1391 // clang-format on 1392 }; 1393 1394 class CommandObjectCommandsScriptImport : public CommandObjectParsed { 1395 public: 1396 CommandObjectCommandsScriptImport(CommandInterpreter &interpreter) 1397 : CommandObjectParsed(interpreter, "command script import", 1398 "Import a scripting module in LLDB.", nullptr), 1399 m_options() { 1400 CommandArgumentEntry arg1; 1401 CommandArgumentData cmd_arg; 1402 1403 // Define the first (and only) variant of this arg. 1404 cmd_arg.arg_type = eArgTypeFilename; 1405 cmd_arg.arg_repetition = eArgRepeatPlus; 1406 1407 // There is only one variant this argument could be; put it into the 1408 // argument entry. 1409 arg1.push_back(cmd_arg); 1410 1411 // Push the data for the first argument into the m_arguments vector. 1412 m_arguments.push_back(arg1); 1413 } 1414 1415 ~CommandObjectCommandsScriptImport() override = default; 1416 1417 int HandleArgumentCompletion( 1418 CompletionRequest &request, 1419 OptionElementVector &opt_element_vector) override { 1420 CommandCompletions::InvokeCommonCompletionCallbacks( 1421 GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, 1422 request, nullptr); 1423 return request.GetNumberOfMatches(); 1424 } 1425 1426 Options *GetOptions() override { return &m_options; } 1427 1428 protected: 1429 class CommandOptions : public Options { 1430 public: 1431 CommandOptions() : Options() {} 1432 1433 ~CommandOptions() override = default; 1434 1435 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1436 ExecutionContext *execution_context) override { 1437 Status error; 1438 const int short_option = m_getopt_table[option_idx].val; 1439 1440 switch (short_option) { 1441 case 'r': 1442 m_allow_reload = true; 1443 break; 1444 default: 1445 error.SetErrorStringWithFormat("unrecognized option '%c'", 1446 short_option); 1447 break; 1448 } 1449 1450 return error; 1451 } 1452 1453 void OptionParsingStarting(ExecutionContext *execution_context) override { 1454 m_allow_reload = true; 1455 } 1456 1457 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1458 return llvm::makeArrayRef(g_script_import_options); 1459 } 1460 1461 // Instance variables to hold the values for command options. 1462 1463 bool m_allow_reload; 1464 }; 1465 1466 bool DoExecute(Args &command, CommandReturnObject &result) override { 1467 if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) { 1468 result.AppendError("only scripting language supported for module " 1469 "importing is currently Python"); 1470 result.SetStatus(eReturnStatusFailed); 1471 return false; 1472 } 1473 1474 if (command.empty()) { 1475 result.AppendError("command script import needs one or more arguments"); 1476 result.SetStatus(eReturnStatusFailed); 1477 return false; 1478 } 1479 1480 for (auto &entry : command.entries()) { 1481 Status error; 1482 1483 const bool init_session = true; 1484 // FIXME: this is necessary because CommandObject::CheckRequirements() 1485 // assumes that commands won't ever be recursively invoked, but it's 1486 // actually possible to craft a Python script that does other "command 1487 // script imports" in __lldb_init_module the real fix is to have 1488 // recursive commands possible with a CommandInvocation object separate 1489 // from the CommandObject itself, so that recursive command invocations 1490 // won't stomp on each other (wrt to execution contents, options, and 1491 // more) 1492 m_exe_ctx.Clear(); 1493 if (GetDebugger().GetScriptInterpreter()->LoadScriptingModule( 1494 entry.c_str(), m_options.m_allow_reload, init_session, error)) { 1495 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1496 } else { 1497 result.AppendErrorWithFormat("module importing failed: %s", 1498 error.AsCString()); 1499 result.SetStatus(eReturnStatusFailed); 1500 } 1501 } 1502 1503 return result.Succeeded(); 1504 } 1505 1506 CommandOptions m_options; 1507 }; 1508 1509 // CommandObjectCommandsScriptAdd 1510 static constexpr OptionEnumValueElement g_script_synchro_type[] = { 1511 {eScriptedCommandSynchronicitySynchronous, "synchronous", 1512 "Run synchronous"}, 1513 {eScriptedCommandSynchronicityAsynchronous, "asynchronous", 1514 "Run asynchronous"}, 1515 {eScriptedCommandSynchronicityCurrentValue, "current", 1516 "Do not alter current setting"} }; 1517 1518 static constexpr OptionEnumValues ScriptSynchroType() { 1519 return OptionEnumValues(g_script_synchro_type); 1520 } 1521 1522 static constexpr OptionDefinition g_script_add_options[] = { 1523 // clang-format off 1524 { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name." }, 1525 { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name." }, 1526 { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "The help text to display for this command." }, 1527 { LLDB_OPT_SET_ALL, false, "synchronicity", 's', OptionParser::eRequiredArgument, nullptr, ScriptSynchroType(), 0, eArgTypeScriptedCommandSynchronicity, "Set the synchronicity of this command's executions with regard to LLDB event system." }, 1528 // clang-format on 1529 }; 1530 1531 class CommandObjectCommandsScriptAdd : public CommandObjectParsed, 1532 public IOHandlerDelegateMultiline { 1533 public: 1534 CommandObjectCommandsScriptAdd(CommandInterpreter &interpreter) 1535 : CommandObjectParsed(interpreter, "command script add", 1536 "Add a scripted function as an LLDB command.", 1537 nullptr), 1538 IOHandlerDelegateMultiline("DONE"), m_options() { 1539 CommandArgumentEntry arg1; 1540 CommandArgumentData cmd_arg; 1541 1542 // Define the first (and only) variant of this arg. 1543 cmd_arg.arg_type = eArgTypeCommandName; 1544 cmd_arg.arg_repetition = eArgRepeatPlain; 1545 1546 // There is only one variant this argument could be; put it into the 1547 // argument entry. 1548 arg1.push_back(cmd_arg); 1549 1550 // Push the data for the first argument into the m_arguments vector. 1551 m_arguments.push_back(arg1); 1552 } 1553 1554 ~CommandObjectCommandsScriptAdd() override = default; 1555 1556 Options *GetOptions() override { return &m_options; } 1557 1558 protected: 1559 class CommandOptions : public Options { 1560 public: 1561 CommandOptions() 1562 : Options(), m_class_name(), m_funct_name(), m_short_help(), 1563 m_synchronicity(eScriptedCommandSynchronicitySynchronous) {} 1564 1565 ~CommandOptions() override = default; 1566 1567 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, 1568 ExecutionContext *execution_context) override { 1569 Status error; 1570 const int short_option = m_getopt_table[option_idx].val; 1571 1572 switch (short_option) { 1573 case 'f': 1574 if (!option_arg.empty()) 1575 m_funct_name = option_arg; 1576 break; 1577 case 'c': 1578 if (!option_arg.empty()) 1579 m_class_name = option_arg; 1580 break; 1581 case 'h': 1582 if (!option_arg.empty()) 1583 m_short_help = option_arg; 1584 break; 1585 case 's': 1586 m_synchronicity = 1587 (ScriptedCommandSynchronicity)OptionArgParser::ToOptionEnum( 1588 option_arg, GetDefinitions()[option_idx].enum_values, 0, error); 1589 if (!error.Success()) 1590 error.SetErrorStringWithFormat( 1591 "unrecognized value for synchronicity '%s'", 1592 option_arg.str().c_str()); 1593 break; 1594 default: 1595 error.SetErrorStringWithFormat("unrecognized option '%c'", 1596 short_option); 1597 break; 1598 } 1599 1600 return error; 1601 } 1602 1603 void OptionParsingStarting(ExecutionContext *execution_context) override { 1604 m_class_name.clear(); 1605 m_funct_name.clear(); 1606 m_short_help.clear(); 1607 m_synchronicity = eScriptedCommandSynchronicitySynchronous; 1608 } 1609 1610 llvm::ArrayRef<OptionDefinition> GetDefinitions() override { 1611 return llvm::makeArrayRef(g_script_add_options); 1612 } 1613 1614 // Instance variables to hold the values for command options. 1615 1616 std::string m_class_name; 1617 std::string m_funct_name; 1618 std::string m_short_help; 1619 ScriptedCommandSynchronicity m_synchronicity; 1620 }; 1621 1622 void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { 1623 StreamFileSP output_sp(io_handler.GetOutputStreamFile()); 1624 if (output_sp && interactive) { 1625 output_sp->PutCString(g_python_command_instructions); 1626 output_sp->Flush(); 1627 } 1628 } 1629 1630 void IOHandlerInputComplete(IOHandler &io_handler, 1631 std::string &data) override { 1632 StreamFileSP error_sp = io_handler.GetErrorStreamFile(); 1633 1634 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1635 if (interpreter) { 1636 1637 StringList lines; 1638 lines.SplitIntoLines(data); 1639 if (lines.GetSize() > 0) { 1640 std::string funct_name_str; 1641 if (interpreter->GenerateScriptAliasFunction(lines, funct_name_str)) { 1642 if (funct_name_str.empty()) { 1643 error_sp->Printf("error: unable to obtain a function name, didn't " 1644 "add python command.\n"); 1645 error_sp->Flush(); 1646 } else { 1647 // everything should be fine now, let's add this alias 1648 1649 CommandObjectSP command_obj_sp(new CommandObjectPythonFunction( 1650 m_interpreter, m_cmd_name, funct_name_str, m_short_help, 1651 m_synchronicity)); 1652 1653 if (!m_interpreter.AddUserCommand(m_cmd_name, command_obj_sp, 1654 true)) { 1655 error_sp->Printf("error: unable to add selected command, didn't " 1656 "add python command.\n"); 1657 error_sp->Flush(); 1658 } 1659 } 1660 } else { 1661 error_sp->Printf( 1662 "error: unable to create function, didn't add python command.\n"); 1663 error_sp->Flush(); 1664 } 1665 } else { 1666 error_sp->Printf("error: empty function, didn't add python command.\n"); 1667 error_sp->Flush(); 1668 } 1669 } else { 1670 error_sp->Printf( 1671 "error: script interpreter missing, didn't add python command.\n"); 1672 error_sp->Flush(); 1673 } 1674 1675 io_handler.SetIsDone(true); 1676 } 1677 1678 protected: 1679 bool DoExecute(Args &command, CommandReturnObject &result) override { 1680 if (GetDebugger().GetScriptLanguage() != lldb::eScriptLanguagePython) { 1681 result.AppendError("only scripting language supported for scripted " 1682 "commands is currently Python"); 1683 result.SetStatus(eReturnStatusFailed); 1684 return false; 1685 } 1686 1687 if (command.GetArgumentCount() != 1) { 1688 result.AppendError("'command script add' requires one argument"); 1689 result.SetStatus(eReturnStatusFailed); 1690 return false; 1691 } 1692 1693 // Store the options in case we get multi-line input 1694 m_cmd_name = command[0].ref; 1695 m_short_help.assign(m_options.m_short_help); 1696 m_synchronicity = m_options.m_synchronicity; 1697 1698 if (m_options.m_class_name.empty()) { 1699 if (m_options.m_funct_name.empty()) { 1700 m_interpreter.GetPythonCommandsFromIOHandler( 1701 " ", // Prompt 1702 *this, // IOHandlerDelegate 1703 true, // Run IOHandler in async mode 1704 nullptr); // Baton for the "io_handler" that will be passed back 1705 // into our IOHandlerDelegate functions 1706 } else { 1707 CommandObjectSP new_cmd(new CommandObjectPythonFunction( 1708 m_interpreter, m_cmd_name, m_options.m_funct_name, 1709 m_options.m_short_help, m_synchronicity)); 1710 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { 1711 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1712 } else { 1713 result.AppendError("cannot add command"); 1714 result.SetStatus(eReturnStatusFailed); 1715 } 1716 } 1717 } else { 1718 ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); 1719 if (!interpreter) { 1720 result.AppendError("cannot find ScriptInterpreter"); 1721 result.SetStatus(eReturnStatusFailed); 1722 return false; 1723 } 1724 1725 auto cmd_obj_sp = interpreter->CreateScriptCommandObject( 1726 m_options.m_class_name.c_str()); 1727 if (!cmd_obj_sp) { 1728 result.AppendError("cannot create helper object"); 1729 result.SetStatus(eReturnStatusFailed); 1730 return false; 1731 } 1732 1733 CommandObjectSP new_cmd(new CommandObjectScriptingObject( 1734 m_interpreter, m_cmd_name, cmd_obj_sp, m_synchronicity)); 1735 if (m_interpreter.AddUserCommand(m_cmd_name, new_cmd, true)) { 1736 result.SetStatus(eReturnStatusSuccessFinishNoResult); 1737 } else { 1738 result.AppendError("cannot add command"); 1739 result.SetStatus(eReturnStatusFailed); 1740 } 1741 } 1742 1743 return result.Succeeded(); 1744 } 1745 1746 CommandOptions m_options; 1747 std::string m_cmd_name; 1748 std::string m_short_help; 1749 ScriptedCommandSynchronicity m_synchronicity; 1750 }; 1751 1752 // CommandObjectCommandsScriptList 1753 1754 class CommandObjectCommandsScriptList : public CommandObjectParsed { 1755 public: 1756 CommandObjectCommandsScriptList(CommandInterpreter &interpreter) 1757 : CommandObjectParsed(interpreter, "command script list", 1758 "List defined scripted commands.", nullptr) {} 1759 1760 ~CommandObjectCommandsScriptList() override = default; 1761 1762 bool DoExecute(Args &command, CommandReturnObject &result) override { 1763 m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef); 1764 1765 result.SetStatus(eReturnStatusSuccessFinishResult); 1766 1767 return true; 1768 } 1769 }; 1770 1771 // CommandObjectCommandsScriptClear 1772 1773 class CommandObjectCommandsScriptClear : public CommandObjectParsed { 1774 public: 1775 CommandObjectCommandsScriptClear(CommandInterpreter &interpreter) 1776 : CommandObjectParsed(interpreter, "command script clear", 1777 "Delete all scripted commands.", nullptr) {} 1778 1779 ~CommandObjectCommandsScriptClear() override = default; 1780 1781 protected: 1782 bool DoExecute(Args &command, CommandReturnObject &result) override { 1783 m_interpreter.RemoveAllUser(); 1784 1785 result.SetStatus(eReturnStatusSuccessFinishResult); 1786 1787 return true; 1788 } 1789 }; 1790 1791 // CommandObjectCommandsScriptDelete 1792 1793 class CommandObjectCommandsScriptDelete : public CommandObjectParsed { 1794 public: 1795 CommandObjectCommandsScriptDelete(CommandInterpreter &interpreter) 1796 : CommandObjectParsed(interpreter, "command script delete", 1797 "Delete a scripted command.", nullptr) { 1798 CommandArgumentEntry arg1; 1799 CommandArgumentData cmd_arg; 1800 1801 // Define the first (and only) variant of this arg. 1802 cmd_arg.arg_type = eArgTypeCommandName; 1803 cmd_arg.arg_repetition = eArgRepeatPlain; 1804 1805 // There is only one variant this argument could be; put it into the 1806 // argument entry. 1807 arg1.push_back(cmd_arg); 1808 1809 // Push the data for the first argument into the m_arguments vector. 1810 m_arguments.push_back(arg1); 1811 } 1812 1813 ~CommandObjectCommandsScriptDelete() override = default; 1814 1815 protected: 1816 bool DoExecute(Args &command, CommandReturnObject &result) override { 1817 1818 if (command.GetArgumentCount() != 1) { 1819 result.AppendError("'command script delete' requires one argument"); 1820 result.SetStatus(eReturnStatusFailed); 1821 return false; 1822 } 1823 1824 auto cmd_name = command[0].ref; 1825 1826 if (cmd_name.empty() || !m_interpreter.HasUserCommands() || 1827 !m_interpreter.UserCommandExists(cmd_name)) { 1828 result.AppendErrorWithFormat("command %s not found", command[0].c_str()); 1829 result.SetStatus(eReturnStatusFailed); 1830 return false; 1831 } 1832 1833 m_interpreter.RemoveUser(cmd_name); 1834 result.SetStatus(eReturnStatusSuccessFinishResult); 1835 return true; 1836 } 1837 }; 1838 1839 #pragma mark CommandObjectMultiwordCommandsScript 1840 1841 // CommandObjectMultiwordCommandsScript 1842 1843 class CommandObjectMultiwordCommandsScript : public CommandObjectMultiword { 1844 public: 1845 CommandObjectMultiwordCommandsScript(CommandInterpreter &interpreter) 1846 : CommandObjectMultiword( 1847 interpreter, "command script", "Commands for managing custom " 1848 "commands implemented by " 1849 "interpreter scripts.", 1850 "command script <subcommand> [<subcommand-options>]") { 1851 LoadSubCommand("add", CommandObjectSP( 1852 new CommandObjectCommandsScriptAdd(interpreter))); 1853 LoadSubCommand( 1854 "delete", 1855 CommandObjectSP(new CommandObjectCommandsScriptDelete(interpreter))); 1856 LoadSubCommand( 1857 "clear", 1858 CommandObjectSP(new CommandObjectCommandsScriptClear(interpreter))); 1859 LoadSubCommand("list", CommandObjectSP(new CommandObjectCommandsScriptList( 1860 interpreter))); 1861 LoadSubCommand( 1862 "import", 1863 CommandObjectSP(new CommandObjectCommandsScriptImport(interpreter))); 1864 } 1865 1866 ~CommandObjectMultiwordCommandsScript() override = default; 1867 }; 1868 1869 #pragma mark CommandObjectMultiwordCommands 1870 1871 // CommandObjectMultiwordCommands 1872 1873 CommandObjectMultiwordCommands::CommandObjectMultiwordCommands( 1874 CommandInterpreter &interpreter) 1875 : CommandObjectMultiword(interpreter, "command", 1876 "Commands for managing custom LLDB commands.", 1877 "command <subcommand> [<subcommand-options>]") { 1878 LoadSubCommand("source", 1879 CommandObjectSP(new CommandObjectCommandsSource(interpreter))); 1880 LoadSubCommand("alias", 1881 CommandObjectSP(new CommandObjectCommandsAlias(interpreter))); 1882 LoadSubCommand("unalias", CommandObjectSP( 1883 new CommandObjectCommandsUnalias(interpreter))); 1884 LoadSubCommand("delete", 1885 CommandObjectSP(new CommandObjectCommandsDelete(interpreter))); 1886 LoadSubCommand( 1887 "regex", CommandObjectSP(new CommandObjectCommandsAddRegex(interpreter))); 1888 LoadSubCommand("history", CommandObjectSP( 1889 new CommandObjectCommandsHistory(interpreter))); 1890 LoadSubCommand( 1891 "script", 1892 CommandObjectSP(new CommandObjectMultiwordCommandsScript(interpreter))); 1893 } 1894 1895 CommandObjectMultiwordCommands::~CommandObjectMultiwordCommands() = default; 1896