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