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