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