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