diff options
Diffstat (limited to 'source/Commands')
32 files changed, 3263 insertions, 3203 deletions
diff --git a/source/Commands/CommandCompletions.cpp b/source/Commands/CommandCompletions.cpp index 5d2fb3d67f57..469a6bbbadf6 100644 --- a/source/Commands/CommandCompletions.cpp +++ b/source/Commands/CommandCompletions.cpp @@ -71,10 +71,9 @@ bool CommandCompletions::InvokeCommonCompletionCallbacks( return handled; } -int CommandCompletions::SourceFiles(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - request.SetWordComplete(true); +void CommandCompletions::SourceFiles(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { // Find some way to switch "include support files..." SourceFileCompleter completer(interpreter, false, request); @@ -85,20 +84,18 @@ int CommandCompletions::SourceFiles(CommandInterpreter &interpreter, } else { completer.DoCompletion(searcher); } - return request.GetNumberOfMatches(); } -static int DiskFilesOrDirectories(const llvm::Twine &partial_name, - bool only_directories, StringList &matches, - TildeExpressionResolver &Resolver) { - matches.Clear(); - +static void DiskFilesOrDirectories(const llvm::Twine &partial_name, + bool only_directories, + CompletionRequest &request, + TildeExpressionResolver &Resolver) { llvm::SmallString<256> CompletionBuffer; llvm::SmallString<256> Storage; partial_name.toVector(CompletionBuffer); if (CompletionBuffer.size() >= PATH_MAX) - return matches.GetSize(); + return; namespace path = llvm::sys::path; @@ -126,10 +123,10 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name, for (const auto &S : MatchSet) { Resolved = S.getKey(); path::append(Resolved, path::get_separator()); - matches.AppendString(Resolved); + request.AddCompletion(Resolved, "", CompletionMode::Partial); } } - return matches.GetSize(); + return; } // If there was no trailing slash, then we're done as soon as we resolve @@ -138,8 +135,8 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name, if (FirstSep == llvm::StringRef::npos) { // Make sure it ends with a separator. path::append(CompletionBuffer, path::get_separator()); - matches.AppendString(CompletionBuffer); - return matches.GetSize(); + request.AddCompletion(CompletionBuffer, "", CompletionMode::Partial); + return; } // We want to keep the form the user typed, so we special case this to @@ -219,51 +216,56 @@ static int DiskFilesOrDirectories(const llvm::Twine &partial_name, path::append(CompletionBuffer, path::get_separator()); } - matches.AppendString(CompletionBuffer); + CompletionMode mode = + is_dir ? CompletionMode::Partial : CompletionMode::Normal; + request.AddCompletion(CompletionBuffer, "", mode); } +} - return matches.GetSize(); +static void DiskFilesOrDirectories(const llvm::Twine &partial_name, + bool only_directories, StringList &matches, + TildeExpressionResolver &Resolver) { + CompletionResult result; + std::string partial_name_str = partial_name.str(); + CompletionRequest request(partial_name_str, partial_name_str.size(), result); + DiskFilesOrDirectories(partial_name, only_directories, request, Resolver); + result.GetMatches(matches); } -static int DiskFilesOrDirectories(CompletionRequest &request, - bool only_directories) { - request.SetWordComplete(false); +static void DiskFilesOrDirectories(CompletionRequest &request, + bool only_directories) { StandardTildeExpressionResolver resolver; - StringList matches; DiskFilesOrDirectories(request.GetCursorArgumentPrefix(), only_directories, - matches, resolver); - request.AddCompletions(matches); - return request.GetNumberOfMatches(); + request, resolver); } -int CommandCompletions::DiskFiles(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - return DiskFilesOrDirectories(request, /*only_dirs*/ false); +void CommandCompletions::DiskFiles(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + DiskFilesOrDirectories(request, /*only_dirs*/ false); } -int CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name, - StringList &matches, - TildeExpressionResolver &Resolver) { - return DiskFilesOrDirectories(partial_file_name, false, matches, Resolver); +void CommandCompletions::DiskFiles(const llvm::Twine &partial_file_name, + StringList &matches, + TildeExpressionResolver &Resolver) { + DiskFilesOrDirectories(partial_file_name, false, matches, Resolver); } -int CommandCompletions::DiskDirectories(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - return DiskFilesOrDirectories(request, /*only_dirs*/ true); +void CommandCompletions::DiskDirectories(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + DiskFilesOrDirectories(request, /*only_dirs*/ true); } -int CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name, - StringList &matches, - TildeExpressionResolver &Resolver) { - return DiskFilesOrDirectories(partial_file_name, true, matches, Resolver); +void CommandCompletions::DiskDirectories(const llvm::Twine &partial_file_name, + StringList &matches, + TildeExpressionResolver &Resolver) { + DiskFilesOrDirectories(partial_file_name, true, matches, Resolver); } -int CommandCompletions::Modules(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - request.SetWordComplete(true); +void CommandCompletions::Modules(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { ModuleCompleter completer(interpreter, request); if (searcher == nullptr) { @@ -273,13 +275,11 @@ int CommandCompletions::Modules(CommandInterpreter &interpreter, } else { completer.DoCompletion(searcher); } - return request.GetNumberOfMatches(); } -int CommandCompletions::Symbols(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - request.SetWordComplete(true); +void CommandCompletions::Symbols(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { SymbolCompleter completer(interpreter, request); if (searcher == nullptr) { @@ -289,12 +289,11 @@ int CommandCompletions::Symbols(CommandInterpreter &interpreter, } else { completer.DoCompletion(searcher); } - return request.GetNumberOfMatches(); } -int CommandCompletions::SettingsNames(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { +void CommandCompletions::SettingsNames(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { // Cache the full setting name list static StringList g_property_names; if (g_property_names.GetSize() == 0) { @@ -309,38 +308,27 @@ int CommandCompletions::SettingsNames(CommandInterpreter &interpreter, } } - size_t exact_matches_idx = SIZE_MAX; - StringList matches; - g_property_names.AutoComplete(request.GetCursorArgumentPrefix(), matches, - exact_matches_idx); - request.SetWordComplete(exact_matches_idx != SIZE_MAX); - request.AddCompletions(matches); - return request.GetNumberOfMatches(); + for (const std::string &s : g_property_names) + request.TryCompleteCurrentArg(s); } -int CommandCompletions::PlatformPluginNames(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - StringList new_matches; - std::size_t num_matches = PluginManager::AutoCompletePlatformName( - request.GetCursorArgumentPrefix(), new_matches); - request.SetWordComplete(num_matches == 1); - request.AddCompletions(new_matches); - return request.GetNumberOfMatches(); +void CommandCompletions::PlatformPluginNames(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + PluginManager::AutoCompletePlatformName(request.GetCursorArgumentPrefix(), + request); } -int CommandCompletions::ArchitectureNames(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - const uint32_t num_matches = ArchSpec::AutoComplete(request); - request.SetWordComplete(num_matches == 1); - return num_matches; +void CommandCompletions::ArchitectureNames(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + ArchSpec::AutoComplete(request); } -int CommandCompletions::VariablePath(CommandInterpreter &interpreter, - CompletionRequest &request, - SearchFilter *searcher) { - return Variable::AutoComplete(interpreter.GetExecutionContext(), request); +void CommandCompletions::VariablePath(CommandInterpreter &interpreter, + CompletionRequest &request, + SearchFilter *searcher) { + Variable::AutoComplete(interpreter.GetExecutionContext(), request); } CommandCompletions::Completer::Completer(CommandInterpreter &interpreter, @@ -368,8 +356,7 @@ lldb::SearchDepth CommandCompletions::SourceFileCompleter::GetDepth() { Searcher::CallbackReturn CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter, SymbolContext &context, - Address *addr, - bool complete) { + Address *addr) { if (context.comp_unit != nullptr) { if (m_include_support_files) { FileSpecList supporting_files = context.comp_unit->GetSupportFiles(); @@ -411,15 +398,14 @@ CommandCompletions::SourceFileCompleter::SearchCallback(SearchFilter &filter, return Searcher::eCallbackReturnContinue; } -size_t -CommandCompletions::SourceFileCompleter::DoCompletion(SearchFilter *filter) { +void CommandCompletions::SourceFileCompleter::DoCompletion( + SearchFilter *filter) { filter->Search(*this); // Now convert the filelist to completions: for (size_t i = 0; i < m_matching_files.GetSize(); i++) { m_request.AddCompletion( m_matching_files.GetFileSpecAtIndex(i).GetFilename().GetCString()); } - return m_request.GetNumberOfMatches(); } // SymbolCompleter @@ -448,7 +434,7 @@ CommandCompletions::SymbolCompleter::SymbolCompleter( pos = regex_str.insert(pos, '\\'); pos = find_if(pos + 2, regex_str.end(), regex_chars); } - m_regex.Compile(regex_str); + m_regex = RegularExpression(regex_str); } lldb::SearchDepth CommandCompletions::SymbolCompleter::GetDepth() { @@ -456,22 +442,24 @@ lldb::SearchDepth CommandCompletions::SymbolCompleter::GetDepth() { } Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback( - SearchFilter &filter, SymbolContext &context, Address *addr, - bool complete) { + SearchFilter &filter, SymbolContext &context, Address *addr) { if (context.module_sp) { SymbolContextList sc_list; const bool include_symbols = true; const bool include_inlines = true; - const bool append = true; context.module_sp->FindFunctions(m_regex, include_symbols, include_inlines, - append, sc_list); + sc_list); SymbolContext sc; // Now add the functions & symbols to the list - only add if unique: for (uint32_t i = 0; i < sc_list.GetSize(); i++) { if (sc_list.GetContextAtIndex(i, sc)) { ConstString func_name = sc.GetFunctionName(Mangled::ePreferDemangled); - if (!func_name.IsEmpty()) + // Ensure that the function name matches the regex. This is more than a + // sanity check. It is possible that the demangled function name does + // not start with the prefix, for example when it's in an anonymous + // namespace. + if (!func_name.IsEmpty() && m_regex.Execute(func_name.GetStringRef())) m_match_set.insert(func_name); } } @@ -479,13 +467,11 @@ Searcher::CallbackReturn CommandCompletions::SymbolCompleter::SearchCallback( return Searcher::eCallbackReturnContinue; } -size_t CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) { +void CommandCompletions::SymbolCompleter::DoCompletion(SearchFilter *filter) { filter->Search(*this); collection::iterator pos = m_match_set.begin(), end = m_match_set.end(); for (pos = m_match_set.begin(); pos != end; pos++) m_request.AddCompletion((*pos).GetCString()); - - return m_request.GetNumberOfMatches(); } // ModuleCompleter @@ -502,8 +488,7 @@ lldb::SearchDepth CommandCompletions::ModuleCompleter::GetDepth() { } Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback( - SearchFilter &filter, SymbolContext &context, Address *addr, - bool complete) { + SearchFilter &filter, SymbolContext &context, Address *addr) { if (context.module_sp) { const char *cur_file_name = context.module_sp->GetFileSpec().GetFilename().GetCString(); @@ -526,7 +511,6 @@ Searcher::CallbackReturn CommandCompletions::ModuleCompleter::SearchCallback( return Searcher::eCallbackReturnContinue; } -size_t CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) { +void CommandCompletions::ModuleCompleter::DoCompletion(SearchFilter *filter) { filter->Search(*this); - return m_request.GetNumberOfMatches(); } diff --git a/source/Commands/CommandObjectApropos.cpp b/source/Commands/CommandObjectApropos.cpp index 957de475569c..7ba0b250fbd5 100644 --- a/source/Commands/CommandObjectApropos.cpp +++ b/source/Commands/CommandObjectApropos.cpp @@ -44,7 +44,7 @@ bool CommandObjectApropos::DoExecute(Args &args, CommandReturnObject &result) { const size_t argc = args.GetArgumentCount(); if (argc == 1) { - auto search_word = args[0].ref; + auto search_word = args[0].ref(); if (!search_word.empty()) { // The bulk of the work must be done inside the Command Interpreter, // since the command dictionary is private. @@ -63,13 +63,7 @@ bool CommandObjectApropos::DoExecute(Args &args, CommandReturnObject &result) { if (commands_found.GetSize() > 0) { result.AppendMessageWithFormat( "The following commands may relate to '%s':\n", args[0].c_str()); - size_t max_len = 0; - - for (size_t i = 0; i < commands_found.GetSize(); ++i) { - size_t len = strlen(commands_found.GetStringAtIndex(i)); - if (len > max_len) - max_len = len; - } + const size_t max_len = commands_found.GetMaxStringLength(); for (size_t i = 0; i < commands_found.GetSize(); ++i) m_interpreter.OutputFormattedHelpText( @@ -85,7 +79,7 @@ bool CommandObjectApropos::DoExecute(Args &args, CommandReturnObject &result) { const bool dump_qualified_name = true; result.AppendMessageWithFormatv( "\nThe following settings variables may relate to '{0}': \n\n", - args[0].ref); + args[0].ref()); for (size_t i = 0; i < num_properties; ++i) properties[i]->DumpDescription( m_interpreter, result.GetOutputStream(), 0, dump_qualified_name); diff --git a/source/Commands/CommandObjectBreakpoint.cpp b/source/Commands/CommandObjectBreakpoint.cpp index c33f3834cb13..ad699975b507 100644 --- a/source/Commands/CommandObjectBreakpoint.cpp +++ b/source/Commands/CommandObjectBreakpoint.cpp @@ -16,6 +16,7 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" +#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" #include "lldb/Interpreter/OptionValueBoolean.h" #include "lldb/Interpreter/OptionValueString.h" #include "lldb/Interpreter/OptionValueUInt64.h" @@ -44,21 +45,9 @@ static void AddBreakpointDescription(Stream *s, Breakpoint *bp, // Modifiable Breakpoint Options #pragma mark Modify::CommandOptions -static constexpr OptionDefinition g_breakpoint_modify_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "ignore-count", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Set the number of times this breakpoint is skipped before stopping." }, - { LLDB_OPT_SET_1, false, "one-shot", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint is deleted the first time it stop causes a stop." }, - { LLDB_OPT_SET_1, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "The breakpoint stops only for the thread whose index matches this argument." }, - { LLDB_OPT_SET_1, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID, "The breakpoint stops only for the thread whose TID matches this argument." }, - { LLDB_OPT_SET_1, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName, "The breakpoint stops only for the thread whose thread name matches this argument." }, - { LLDB_OPT_SET_1, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName, "The breakpoint stops only for threads in the queue whose name is given by this argument." }, - { LLDB_OPT_SET_1, false, "condition", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "The breakpoint stops only if this condition expression evaluates to true." }, - { LLDB_OPT_SET_1, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." }, - { LLDB_OPT_SET_2, false, "enable", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable the breakpoint." }, - { LLDB_OPT_SET_3, false, "disable", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disable the breakpoint." }, - { LLDB_OPT_SET_4, false, "command", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCommand, "A command to run when the breakpoint is hit, can be provided more than once, the commands will get run in order left to right." }, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_modify +#include "CommandOptions.inc" + class lldb_private::BreakpointOptionGroup : public OptionGroup { public: @@ -153,9 +142,7 @@ public: } break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -171,7 +158,7 @@ public: { if (!m_commands.empty()) { - auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>(); + auto cmd_data = std::make_unique<BreakpointOptions::CommandData>(); for (std::string &str : m_commands) cmd_data->user_source.AppendString(str); @@ -192,12 +179,9 @@ public: BreakpointOptions m_bp_opts; }; -static constexpr OptionDefinition g_breakpoint_dummy_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Act on Dummy breakpoints - i.e. breakpoints set before a file is provided, " - "which prime new targets." }, - // clang-format on -}; + +#define LLDB_OPTIONS_breakpoint_dummy +#include "CommandOptions.inc" class BreakpointDummyOptionGroup : public OptionGroup { @@ -221,9 +205,7 @@ public: m_use_dummy = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -237,88 +219,8 @@ public: }; -// If an additional option set beyond LLDB_OPTION_SET_10 is added, make sure to -// update the numbers passed to LLDB_OPT_SET_FROM_TO(...) appropriately. -#define LLDB_OPT_NOT_10 (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_10) -#define LLDB_OPT_SKIP_PROLOGUE (LLDB_OPT_SET_1 | LLDB_OPT_SET_FROM_TO(3, 8)) -#define LLDB_OPT_FILE (LLDB_OPT_SET_FROM_TO(1, 11) & ~LLDB_OPT_SET_2 & ~LLDB_OPT_SET_10) -#define LLDB_OPT_OFFSET_APPLIES (LLDB_OPT_SET_FROM_TO(1, 8) & ~LLDB_OPT_SET_2) -#define LLDB_OPT_MOVE_TO_NEAREST_CODE (LLDB_OPT_SET_1 | LLDB_OPT_SET_9) -#define LLDB_OPT_EXPR_LANGUAGE (LLDB_OPT_SET_FROM_TO(3, 8)) - -static constexpr OptionDefinition g_breakpoint_set_options[] = { - // clang-format off - { LLDB_OPT_NOT_10, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the breakpoint only in this shared library. Can repeat this option " - "multiple times to specify multiple shared libraries." }, - { LLDB_OPT_SET_ALL, false, "hardware", 'H', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Require the breakpoint to use hardware breakpoints." }, - { LLDB_OPT_FILE, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specifies the source file in which to set this breakpoint. Note, by default " - "lldb only looks for files that are #included if they use the standard include " - "file extensions. To set breakpoints on .c/.cpp/.m/.mm files that are " - "#included, set target.inline-breakpoint-strategy to \"always\"." }, - { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specifies the line number on which to set this breakpoint." }, - - // Comment out this option for the moment, as we don't actually use it, but - // will in the future. This way users won't see it, but the infrastructure is - // left in place. - // { 0, false, "column", 'C', OptionParser::eRequiredArgument, nullptr, "<column>", - // "Set the breakpoint by source location at this particular column."}, - - { LLDB_OPT_SET_2, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Set the breakpoint at the specified address. If the address maps uniquely to " - "a particular binary, then the address will be converted to a \"file\" " - "address, so that the breakpoint will track that binary+offset no matter where " - "the binary eventually loads. Alternately, if you also specify the module - " - "with the -s option - then the address will be treated as a file address in " - "that module, and resolved accordingly. Again, this will allow lldb to track " - "that offset on subsequent reloads. The module need not have been loaded at " - "the time you specify this breakpoint, and will get resolved when the module " - "is loaded." }, - { LLDB_OPT_SET_3, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function name. Can be repeated multiple times to make " - "one breakpoint for multiple names" }, - { LLDB_OPT_SET_9, false, "source-regexp-function", 'X', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "When used with '-p' limits the source regex to source contained in the named " - "functions. Can be repeated multiple times." }, - { LLDB_OPT_SET_4, true, "fullname", 'F', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFullName, "Set the breakpoint by fully qualified function names. For C++ this means " - "namespaces and all arguments, and for Objective-C this means a full function " - "prototype with class and selector. Can be repeated multiple times to make " - "one breakpoint for multiple names." }, - { LLDB_OPT_SET_5, true, "selector", 'S', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSelector, "Set the breakpoint by ObjC selector name. Can be repeated multiple times to " - "make one breakpoint for multiple Selectors." }, - { LLDB_OPT_SET_6, true, "method", 'M', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeMethod, "Set the breakpoint by C++ method names. Can be repeated multiple times to " - "make one breakpoint for multiple methods." }, - { LLDB_OPT_SET_7, true, "func-regex", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by function name, evaluating a regular-expression to find " - "the function name(s)." }, - { LLDB_OPT_SET_8, true, "basename", 'b', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the breakpoint by function basename (C++ namespaces and arguments will be " - "ignored). Can be repeated multiple times to make one breakpoint for multiple " - "symbols." }, - { LLDB_OPT_SET_9, true, "source-pattern-regexp", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Set the breakpoint by specifying a regular expression which is matched " - "against the source text in a source file or files specified with the -f " - "option. The -f option can be specified more than once. If no source files " - "are specified, uses the current \"default source file\". If you want to " - "match against all source files, pass the \"--all-files\" option." }, - { LLDB_OPT_SET_9, false, "all-files", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "All files are searched for source pattern matches." }, - { LLDB_OPT_SET_11, true, "python-class", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "The name of the class that implement a scripted breakpoint." }, - { LLDB_OPT_SET_11, false, "python-class-key", 'k', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The key for a key/value pair passed to the class that implements a scripted breakpoint. Can be specified more than once." }, - { LLDB_OPT_SET_11, false, "python-class-value", 'v', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The value for the previous key in the pair passed to the class that implements a scripted breakpoint. Can be specified more than once." }, - { LLDB_OPT_SET_10, true, "language-exception", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Set the breakpoint on exceptions thrown by the specified language (without " - "options, on throw but not catch.)" }, - { LLDB_OPT_SET_10, false, "on-throw", 'w', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception throW." }, - { LLDB_OPT_SET_10, false, "on-catch", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Set the breakpoint on exception catcH." }, - - // Don't add this option till it actually does something useful... - // { LLDB_OPT_SET_10, false, "exception-typename", 'O', OptionParser::eRequiredArgument, nullptr, nullptr, 0, eArgTypeTypeName, - // "The breakpoint will only stop if an exception Object of this type is thrown. Can be repeated multiple times to stop for multiple object types" }, - - { LLDB_OPT_EXPR_LANGUAGE, false, "language", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when interpreting the breakpoint's expression " - "(note: currently only implemented for setting breakpoints on identifiers). " - "If not set the target.language setting is used." }, - { LLDB_OPT_SKIP_PROLOGUE, false, "skip-prologue", 'K', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "sKip the prologue if the breakpoint is at the beginning of a function. " - "If not set the target.skip-prologue setting is used." }, - { LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Adds this to the list of names for this breakpoint." }, - { LLDB_OPT_OFFSET_APPLIES, false, "address-slide", 'R', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddress, "Add the specified offset to whatever address(es) the breakpoint resolves to. " - "At present this applies the offset directly as given, and doesn't try to align it to instruction boundaries." }, - { LLDB_OPT_MOVE_TO_NEAREST_CODE, false, "move-to-nearest-code", 'm', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Move breakpoints to nearest code. If not set the target.move-to-nearest-code " - "setting is used." }, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_set +#include "CommandOptions.inc" // CommandObjectBreakpointSet @@ -340,15 +242,18 @@ public: interpreter, "breakpoint set", "Sets a breakpoint or set of breakpoints in the executable.", "breakpoint set <cmd-options>"), - m_bp_opts(), m_options() { - // We're picking up all the normal options, commands and disable. - m_all_options.Append(&m_bp_opts, - LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4, - LLDB_OPT_SET_ALL); - m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); - m_all_options.Append(&m_options); - m_all_options.Finalize(); - } + m_bp_opts(), m_python_class_options("scripted breakpoint", 'P'), + m_options() { + // We're picking up all the normal options, commands and disable. + m_all_options.Append(&m_python_class_options, LLDB_OPT_SET_1, + LLDB_OPT_SET_11); + m_all_options.Append(&m_bp_opts, + LLDB_OPT_SET_1 | LLDB_OPT_SET_3 | LLDB_OPT_SET_4, + LLDB_OPT_SET_ALL); + m_all_options.Append(&m_dummy_options, LLDB_OPT_SET_1, LLDB_OPT_SET_ALL); + m_all_options.Append(&m_options); + m_all_options.Finalize(); + } ~CommandObjectBreakpointSet() override = default; @@ -451,14 +356,6 @@ public: m_hardware = true; break; - case 'k': { - if (m_current_key.empty()) - m_current_key.assign(option_arg); - else - error.SetErrorStringWithFormat("Key: %s missing value.", - m_current_key.c_str()); - - } break; case 'K': { bool success; bool value; @@ -540,10 +437,6 @@ public: m_source_text_regexp.assign(option_arg); break; - case 'P': - m_python_class.assign(option_arg); - break; - case 'r': m_func_regexp.assign(option_arg); break; @@ -557,16 +450,6 @@ public: m_func_name_type_mask |= eFunctionNameTypeSelector; break; - case 'v': { - if (!m_current_key.empty()) { - m_extra_args_sp->AddStringItem(m_current_key, option_arg); - m_current_key.clear(); - } - else - error.SetErrorStringWithFormat("Value \"%s\" missing matching key.", - option_arg.str().c_str()); - } break; - case 'w': { bool success; m_throw_bp = OptionArgParser::ToBoolean(option_arg, true, &success); @@ -581,9 +464,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -611,8 +492,6 @@ public: m_exception_extra_args.Clear(); m_move_to_nearest_code = eLazyBoolCalculate; m_source_regex_func_names.clear(); - m_python_class.clear(); - m_extra_args_sp = std::make_shared<StructuredData::Dictionary>(); m_current_key.clear(); } @@ -644,21 +523,12 @@ public: Args m_exception_extra_args; LazyBool m_move_to_nearest_code; std::unordered_set<std::string> m_source_regex_func_names; - std::string m_python_class; - StructuredData::DictionarySP m_extra_args_sp; std::string m_current_key; }; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); - - if (target == nullptr) { - result.AppendError("Invalid target. Must set target before setting " - "breakpoints (see 'target create' command)."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(m_dummy_options.m_use_dummy); // The following are the various types of breakpoints that could be set: // 1). -f -l -p [-s -g] (setting breakpoint by source location) @@ -673,7 +543,7 @@ protected: BreakpointSetType break_type = eSetTypeInvalid; - if (!m_options.m_python_class.empty()) + if (!m_python_class_options.GetClassName().empty()) break_type = eSetTypeScripted; else if (m_options.m_line_num != 0) break_type = eSetTypeFileAndLine; @@ -720,16 +590,11 @@ protected: // Only check for inline functions if LazyBool check_inlines = eLazyBoolCalculate; - bp_sp = target->CreateBreakpoint(&(m_options.m_modules), - file, - m_options.m_line_num, - m_options.m_column, - m_options.m_offset_addr, - check_inlines, - m_options.m_skip_prologue, - internal, - m_options.m_hardware, - m_options.m_move_to_nearest_code); + bp_sp = target.CreateBreakpoint( + &(m_options.m_modules), file, m_options.m_line_num, + m_options.m_column, m_options.m_offset_addr, check_inlines, + m_options.m_skip_prologue, internal, m_options.m_hardware, + m_options.m_move_to_nearest_code); } break; case eSetTypeAddress: // Breakpoint by address @@ -741,12 +606,11 @@ protected: if (num_modules_specified == 1) { const FileSpec *file_spec = m_options.m_modules.GetFileSpecPointerAtIndex(0); - bp_sp = target->CreateAddressInModuleBreakpoint(m_options.m_load_addr, - internal, file_spec, - m_options.m_hardware); + bp_sp = target.CreateAddressInModuleBreakpoint( + m_options.m_load_addr, internal, file_spec, m_options.m_hardware); } else if (num_modules_specified == 0) { - bp_sp = target->CreateBreakpoint(m_options.m_load_addr, internal, - m_options.m_hardware); + bp_sp = target.CreateBreakpoint(m_options.m_load_addr, internal, + m_options.m_hardware); } else { result.AppendError("Only one shared library can be specified for " "address breakpoints."); @@ -762,38 +626,29 @@ protected: if (name_type_mask == 0) name_type_mask = eFunctionNameTypeAuto; - bp_sp = target->CreateBreakpoint(&(m_options.m_modules), - &(m_options.m_filenames), - m_options.m_func_names, - name_type_mask, - m_options.m_language, - m_options.m_offset_addr, - m_options.m_skip_prologue, - internal, - m_options.m_hardware); + bp_sp = target.CreateBreakpoint( + &(m_options.m_modules), &(m_options.m_filenames), + m_options.m_func_names, name_type_mask, m_options.m_language, + m_options.m_offset_addr, m_options.m_skip_prologue, internal, + m_options.m_hardware); } break; case eSetTypeFunctionRegexp: // Breakpoint by regular expression function // name { RegularExpression regexp(m_options.m_func_regexp); - if (!regexp.IsValid()) { - char err_str[1024]; - regexp.GetErrorAsCString(err_str, sizeof(err_str)); + if (llvm::Error err = regexp.GetError()) { result.AppendErrorWithFormat( "Function name regular expression could not be compiled: \"%s\"", - err_str); + llvm::toString(std::move(err)).c_str()); result.SetStatus(eReturnStatusFailed); return false; } - bp_sp = target->CreateFuncRegexBreakpoint(&(m_options.m_modules), - &(m_options.m_filenames), - regexp, - m_options.m_language, - m_options.m_skip_prologue, - internal, - m_options.m_hardware); + bp_sp = target.CreateFuncRegexBreakpoint( + &(m_options.m_modules), &(m_options.m_filenames), std::move(regexp), + m_options.m_language, m_options.m_skip_prologue, internal, + m_options.m_hardware); } break; case eSetTypeSourceRegexp: // Breakpoint by regexp on source text. @@ -813,39 +668,29 @@ protected: } RegularExpression regexp(m_options.m_source_text_regexp); - if (!regexp.IsValid()) { - char err_str[1024]; - regexp.GetErrorAsCString(err_str, sizeof(err_str)); + if (llvm::Error err = regexp.GetError()) { result.AppendErrorWithFormat( "Source text regular expression could not be compiled: \"%s\"", - err_str); + llvm::toString(std::move(err)).c_str()); result.SetStatus(eReturnStatusFailed); return false; } - bp_sp = - target->CreateSourceRegexBreakpoint(&(m_options.m_modules), - &(m_options.m_filenames), - m_options - .m_source_regex_func_names, - regexp, - internal, - m_options.m_hardware, - m_options.m_move_to_nearest_code); + bp_sp = target.CreateSourceRegexBreakpoint( + &(m_options.m_modules), &(m_options.m_filenames), + m_options.m_source_regex_func_names, std::move(regexp), internal, + m_options.m_hardware, m_options.m_move_to_nearest_code); } break; case eSetTypeException: { Status precond_error; - bp_sp = target->CreateExceptionBreakpoint(m_options.m_exception_language, - m_options.m_catch_bp, - m_options.m_throw_bp, - internal, - &m_options - .m_exception_extra_args, - &precond_error); + bp_sp = target.CreateExceptionBreakpoint( + m_options.m_exception_language, m_options.m_catch_bp, + m_options.m_throw_bp, internal, &m_options.m_exception_extra_args, + &precond_error); if (precond_error.Fail()) { result.AppendErrorWithFormat( "Error setting extra exception arguments: %s", precond_error.AsCString()); - target->RemoveBreakpointByID(bp_sp->GetID()); + target.RemoveBreakpointByID(bp_sp->GetID()); result.SetStatus(eReturnStatusFailed); return false; } @@ -853,18 +698,15 @@ protected: case eSetTypeScripted: { Status error; - bp_sp = target->CreateScriptedBreakpoint(m_options.m_python_class, - &(m_options.m_modules), - &(m_options.m_filenames), - false, - m_options.m_hardware, - m_options.m_extra_args_sp, - &error); + bp_sp = target.CreateScriptedBreakpoint( + m_python_class_options.GetClassName().c_str(), &(m_options.m_modules), + &(m_options.m_filenames), false, m_options.m_hardware, + m_python_class_options.GetStructuredData(), &error); if (error.Fail()) { result.AppendErrorWithFormat( "Error setting extra exception arguments: %s", error.AsCString()); - target->RemoveBreakpointByID(bp_sp->GetID()); + target.RemoveBreakpointByID(bp_sp->GetID()); result.SetStatus(eReturnStatusFailed); return false; } @@ -880,11 +722,11 @@ protected: if (!m_options.m_breakpoint_names.empty()) { Status name_error; for (auto name : m_options.m_breakpoint_names) { - target->AddNameToBreakpoint(bp_sp, name.c_str(), name_error); + target.AddNameToBreakpoint(bp_sp, name.c_str(), name_error); if (name_error.Fail()) { result.AppendErrorWithFormat("Invalid breakpoint name: %s", name.c_str()); - target->RemoveBreakpointByID(bp_sp->GetID()); + target.RemoveBreakpointByID(bp_sp->GetID()); result.SetStatus(eReturnStatusFailed); return false; } @@ -897,7 +739,7 @@ protected: const bool show_locations = false; bp_sp->GetDescription(&output_stream, lldb::eDescriptionLevelInitial, show_locations); - if (target == GetDebugger().GetDummyTarget()) + if (&target == &GetDummyTarget()) output_stream.Printf("Breakpoint set in dummy target, will get copied " "into future targets.\n"); else { @@ -919,12 +761,12 @@ protected: } private: - bool GetDefaultFile(Target *target, FileSpec &file, + bool GetDefaultFile(Target &target, FileSpec &file, CommandReturnObject &result) { uint32_t default_line; // First use the Source Manager's default file. Then use the current stack // frame's file. - if (!target->GetSourceManager().GetDefaultFileAndLine(file, default_line)) { + if (!target.GetSourceManager().GetDefaultFileAndLine(file, default_line)) { StackFrame *cur_frame = m_exe_ctx.GetFramePtr(); if (cur_frame == nullptr) { result.AppendError( @@ -954,6 +796,7 @@ private: BreakpointOptionGroup m_bp_opts; BreakpointDummyOptionGroup m_dummy_options; + OptionGroupPythonClassWithDict m_python_class_options; CommandOptions m_options; OptionGroupOptions m_all_options; }; @@ -993,20 +836,15 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(m_dummy_opts.m_use_dummy); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::disablePerm); if (result.Succeeded()) { @@ -1016,7 +854,7 @@ protected: if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { Breakpoint *bp = - target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { BreakpointLocation *location = bp->FindLocationByID(cur_bp_id.GetLocationID()).get(); @@ -1062,17 +900,12 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); @@ -1084,7 +917,7 @@ protected: if (command.empty()) { // No breakpoint selected; enable all currently set breakpoints. - target->EnableAllowedBreakpoints(); + target.EnableAllowedBreakpoints(); result.AppendMessageWithFormat("All breakpoints enabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints); @@ -1093,7 +926,7 @@ protected: // Particular breakpoint selected; enable that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::disablePerm); if (result.Succeeded()) { @@ -1105,7 +938,7 @@ protected: if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { Breakpoint *breakpoint = - target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { BreakpointLocation *location = breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); @@ -1175,17 +1008,11 @@ the second re-enables the first location."); protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } - + Target &target = GetSelectedOrDummyTarget(); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) { @@ -1196,7 +1023,7 @@ protected: if (command.empty()) { // No breakpoint selected; disable all currently set breakpoints. - target->DisableAllowedBreakpoints(); + target.DisableAllowedBreakpoints(); result.AppendMessageWithFormat("All breakpoints disabled. (%" PRIu64 " breakpoints)\n", (uint64_t)num_breakpoints); @@ -1206,7 +1033,7 @@ protected: BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::disablePerm); if (result.Succeeded()) { @@ -1218,7 +1045,7 @@ protected: if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { Breakpoint *breakpoint = - target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { BreakpointLocation *location = breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); @@ -1245,12 +1072,8 @@ protected: // CommandObjectBreakpointList #pragma mark List::CommandOptions -static constexpr OptionDefinition g_breakpoint_list_options[] = { - // FIXME: We need to add an "internal" command, and then add this sort of - // thing to it. But I need to see it for now, and don't want to wait. #define LLDB_OPTIONS_breakpoint_list #include "CommandOptions.inc" -}; #pragma mark List @@ -1311,9 +1134,7 @@ public: m_internal = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1339,18 +1160,12 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - - if (target == nullptr) { - result.AppendError("Invalid target. No current target or breakpoints."); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; - } + Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); const BreakpointList &breakpoints = - target->GetBreakpointList(m_options.m_internal); + target.GetBreakpointList(m_options.m_internal); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList(m_options.m_internal).GetListMutex(lock); + target.GetBreakpointList(m_options.m_internal).GetListMutex(lock); size_t num_breakpoints = breakpoints.GetSize(); @@ -1376,14 +1191,14 @@ protected: // Particular breakpoints selected; show info about that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::listPerm); if (result.Succeeded()) { for (size_t i = 0; i < valid_bp_ids.GetSize(); ++i) { BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); Breakpoint *breakpoint = - target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); AddBreakpointDescription(&output_stream, breakpoint, m_options.m_level); } @@ -1404,12 +1219,8 @@ private: // CommandObjectBreakpointClear #pragma mark Clear::CommandOptions -static constexpr OptionDefinition g_breakpoint_clear_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the breakpoint by source location in this particular file." }, - { LLDB_OPT_SET_1, true, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Specify the breakpoint by source location at this particular line." } - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_clear +#include "CommandOptions.inc" #pragma mark Clear @@ -1449,9 +1260,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1474,12 +1283,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(); // The following are the various types of breakpoints that could be // cleared: @@ -1491,9 +1295,9 @@ protected: break_type = eClearTypeFileAndLine; std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); - BreakpointList &breakpoints = target->GetBreakpointList(); + BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); // Early return if there's no breakpoint at all. @@ -1527,7 +1331,7 @@ protected: if (loc_coll.GetSize() == 0) { bp->GetDescription(&ss, lldb::eDescriptionLevelBrief); ss.EOL(); - target->RemoveBreakpointByID(bp->GetID()); + target.RemoveBreakpointByID(bp->GetID()); ++num_cleared; } } @@ -1557,12 +1361,8 @@ private: }; // CommandObjectBreakpointDelete -static constexpr OptionDefinition g_breakpoint_delete_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "force", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete all breakpoints without querying for confirmation." }, - { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_delete +#include "CommandOptions.inc" #pragma mark Delete @@ -1607,9 +1407,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1631,18 +1429,12 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); @@ -1659,7 +1451,7 @@ protected: true)) { result.AppendMessage("Operation cancelled..."); } else { - target->RemoveAllowedBreakpoints(); + target.RemoveAllowedBreakpoints(); result.AppendMessageWithFormat( "All breakpoints removed. (%" PRIu64 " breakpoint%s)\n", (uint64_t)num_breakpoints, num_breakpoints > 1 ? "s" : ""); @@ -1669,7 +1461,7 @@ protected: // Particular breakpoint selected; disable that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::deletePerm); if (result.Succeeded()) { @@ -1682,7 +1474,7 @@ protected: if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { Breakpoint *breakpoint = - target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); BreakpointLocation *location = breakpoint->FindLocationByID(cur_bp_id.GetLocationID()).get(); // It makes no sense to try to delete individual locations, so we @@ -1692,7 +1484,7 @@ protected: ++disable_count; } } else { - target->RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); + target.RemoveBreakpointByID(cur_bp_id.GetBreakpointID()); ++delete_count; } } @@ -1711,15 +1503,9 @@ private: }; // CommandObjectBreakpointName +#define LLDB_OPTIONS_breakpoint_name +#include "CommandOptions.inc" -static constexpr OptionDefinition g_breakpoint_name_options[] = { - // clang-format off - {LLDB_OPT_SET_1, false, "name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Specifies a breakpoint name to use."}, - {LLDB_OPT_SET_2, false, "breakpoint-id", 'B', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointID, "Specify a breakpoint ID to use."}, - {LLDB_OPT_SET_3, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Operate on Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets."}, - {LLDB_OPT_SET_4, false, "help-string", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A help string describing the purpose of this name."}, - // clang-format on -}; class BreakpointNameOptionGroup : public OptionGroup { public: BreakpointNameOptionGroup() @@ -1760,9 +1546,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -1781,13 +1565,8 @@ public: OptionValueString m_help_string; }; -static constexpr OptionDefinition g_breakpoint_access_options[] = { - // clang-format off - {LLDB_OPT_SET_1, false, "allow-list", 'L', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint will show up in break list if not referred to explicitly."}, - {LLDB_OPT_SET_2, false, "allow-disable", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be disabled by name or when all breakpoints are disabled."}, - {LLDB_OPT_SET_3, false, "allow-delete", 'D', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Determines whether the breakpoint can be deleted by name or when all breakpoints are deleted."}, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_access +#include "CommandOptions.inc" class BreakpointAccessOptionGroup : public OptionGroup { public: @@ -1835,7 +1614,8 @@ public: "invalid boolean value '%s' passed for -L option", option_arg.str().c_str()); } break; - + default: + llvm_unreachable("Unimplemented option"); } return error; @@ -1897,23 +1677,16 @@ protected: result.SetStatus(eReturnStatusFailed); return false; } - - Target *target = - GetSelectedOrDummyTarget(false); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(false); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); // Make a pass through first to see that all the names are legal. for (auto &entry : command.entries()) { Status error; - if (!BreakpointID::StringIsBreakpointName(entry.ref, error)) + if (!BreakpointID::StringIsBreakpointName(entry.ref(), error)) { result.AppendErrorWithFormat("Invalid breakpoint name: %s - %s", entry.c_str(), error.AsCString()); @@ -1927,7 +1700,7 @@ protected: if (m_bp_id.m_breakpoint.OptionWasSet()) { lldb::break_id_t bp_id = m_bp_id.m_breakpoint.GetUInt64Value(); - bp_sp = target->GetBreakpointByID(bp_id); + bp_sp = target.GetBreakpointByID(bp_id); if (!bp_sp) { result.AppendErrorWithFormatv("Could not find specified breakpoint {0}", @@ -1940,18 +1713,17 @@ protected: Status error; for (auto &entry : command.entries()) { ConstString name(entry.c_str()); - BreakpointName *bp_name = target->FindBreakpointName(name, true, error); + BreakpointName *bp_name = target.FindBreakpointName(name, true, error); if (!bp_name) continue; if (m_bp_id.m_help_string.OptionWasSet()) bp_name->SetHelp(m_bp_id.m_help_string.GetStringValue().str().c_str()); if (bp_sp) - target->ConfigureBreakpointName(*bp_name, - *bp_sp->GetOptions(), + target.ConfigureBreakpointName(*bp_name, *bp_sp->GetOptions(), m_access_options.GetPermissions()); else - target->ConfigureBreakpointName(*bp_name, + target.ConfigureBreakpointName(*bp_name, m_bp_opts.GetBreakpointOptions(), m_access_options.GetPermissions()); } @@ -1996,19 +1768,13 @@ protected: return false; } - Target *target = + Target &target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } - std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) { @@ -2020,7 +1786,7 @@ protected: // Particular breakpoint selected; disable that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::listPerm); if (result.Succeeded()) { @@ -2037,7 +1803,7 @@ protected: lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); - target->AddNameToBreakpoint(bp_sp, bp_name, error); + target.AddNameToBreakpoint(bp_sp, bp_name, error); } } @@ -2081,19 +1847,13 @@ protected: return false; } - Target *target = + Target &target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } - std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) { @@ -2105,7 +1865,7 @@ protected: // Particular breakpoint selected; disable that breakpoint. BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::deletePerm); if (result.Succeeded()) { @@ -2120,7 +1880,7 @@ protected: lldb::break_id_t bp_id = valid_bp_ids.GetBreakpointIDAtIndex(index).GetBreakpointID(); BreakpointSP bp_sp = breakpoints.FindBreakpointByID(bp_id); - target->RemoveNameFromBreakpoint(bp_sp, bp_name); + target.RemoveNameFromBreakpoint(bp_sp, bp_name); } } @@ -2151,19 +1911,12 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = + Target &target = GetSelectedOrDummyTarget(m_name_options.m_use_dummy.GetCurrentValue()); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } - - std::vector<std::string> name_list; if (command.empty()) { - target->GetBreakpointNames(name_list); + target.GetBreakpointNames(name_list); } else { for (const Args::ArgEntry &arg : command) { @@ -2178,9 +1931,8 @@ protected: const char *name = name_str.c_str(); // First print out the options for the name: Status error; - BreakpointName *bp_name = target->FindBreakpointName(ConstString(name), - false, - error); + BreakpointName *bp_name = + target.FindBreakpointName(ConstString(name), false, error); if (bp_name) { StreamString s; @@ -2191,9 +1943,9 @@ protected: } std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); - BreakpointList &breakpoints = target->GetBreakpointList(); + BreakpointList &breakpoints = target.GetBreakpointList(); bool any_set = false; for (BreakpointSP bp_sp : breakpoints.Breakpoints()) { if (bp_sp->MatchesName(name)) { @@ -2246,12 +1998,8 @@ public: // CommandObjectBreakpointRead #pragma mark Read::CommandOptions -static constexpr OptionDefinition g_breakpoint_read_options[] = { - // clang-format off - {LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file from which to read the breakpoints." }, - {LLDB_OPT_SET_ALL, false, "breakpoint-name", 'N', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBreakpointName, "Only read in breakpoints with this name."}, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_read +#include "CommandOptions.inc" #pragma mark Read @@ -2301,9 +2049,7 @@ public: break; } default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -2326,21 +2072,16 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); FileSpec input_spec(m_options.m_filename); FileSystem::Instance().Resolve(input_spec); BreakpointIDList new_bps; - Status error = target->CreateBreakpointsFromFile( - input_spec, m_options.m_names, new_bps); + Status error = target.CreateBreakpointsFromFile(input_spec, + m_options.m_names, new_bps); if (!error.Success()) { result.AppendError(error.AsCString()); @@ -2358,7 +2099,7 @@ protected: result.AppendMessage("New breakpoints:"); for (size_t i = 0; i < num_breakpoints; ++i) { BreakpointID bp_id = new_bps.GetBreakpointIDAtIndex(i); - Breakpoint *bp = target->GetBreakpointList() + Breakpoint *bp = target.GetBreakpointList() .FindBreakpointByID(bp_id.GetBreakpointID()) .get(); if (bp) @@ -2375,12 +2116,8 @@ private: // CommandObjectBreakpointWrite #pragma mark Write::CommandOptions -static constexpr OptionDefinition g_breakpoint_write_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eDiskFileCompletion, eArgTypeFilename, "The file into which to write the breakpoints." }, - { LLDB_OPT_SET_ALL, false, "append",'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to saved breakpoints file if it exists."}, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_write +#include "CommandOptions.inc" #pragma mark Write class CommandObjectBreakpointWrite : public CommandObjectParsed { @@ -2423,9 +2160,7 @@ public: m_append = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -2448,20 +2183,15 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or breakpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(); std::unique_lock<std::recursive_mutex> lock; - target->GetBreakpointList().GetListMutex(lock); + target.GetBreakpointList().GetListMutex(lock); BreakpointIDList valid_bp_ids; if (!command.empty()) { CommandObjectMultiwordBreakpoint::VerifyBreakpointIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::listPerm); if (!result.Succeeded()) { @@ -2471,8 +2201,8 @@ protected: } FileSpec file_spec(m_options.m_filename); FileSystem::Instance().Resolve(file_spec); - Status error = target->SerializeBreakpointsToFile(file_spec, valid_bp_ids, - m_options.m_append); + Status error = target.SerializeBreakpointsToFile(file_spec, valid_bp_ids, + m_options.m_append); if (!error.Success()) { result.AppendErrorWithFormat("error serializing breakpoints: %s.", error.AsCString()); diff --git a/source/Commands/CommandObjectBreakpointCommand.cpp b/source/Commands/CommandObjectBreakpointCommand.cpp index 3f9d83cd86a8..a6bcd1d8dc32 100644 --- a/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/source/Commands/CommandObjectBreakpointCommand.cpp @@ -26,33 +26,33 @@ using namespace lldb; using namespace lldb_private; -// CommandObjectBreakpointCommandAdd - // FIXME: "script-type" needs to have its contents determined dynamically, so -// somebody can add a new scripting -// language to lldb and have it pickable here without having to change this -// enumeration by hand and rebuild lldb proper. - +// somebody can add a new scripting language to lldb and have it pickable here +// without having to change this enumeration by hand and rebuild lldb proper. static constexpr OptionEnumValueElement g_script_option_enumeration[] = { - {eScriptLanguageNone, "command", - "Commands are in the lldb command interpreter language"}, - {eScriptLanguagePython, "python", "Commands are in the Python language."}, - {eSortOrderByName, "default-script", - "Commands are in the default scripting language."} }; + { + eScriptLanguageNone, + "command", + "Commands are in the lldb command interpreter language", + }, + { + eScriptLanguagePython, + "python", + "Commands are in the Python language.", + }, + { + eSortOrderByName, + "default-script", + "Commands are in the default scripting language.", + }, +}; static constexpr OptionEnumValues ScriptOptionEnum() { return OptionEnumValues(g_script_option_enumeration); } -static constexpr OptionDefinition g_breakpoint_add_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner, "Specify a one-line breakpoint command inline. Be sure to surround it with quotes." }, - { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Specify whether breakpoint command execution should terminate on error." }, - { LLDB_OPT_SET_ALL, false, "script-type", 's', OptionParser::eRequiredArgument, nullptr, ScriptOptionEnum(), 0, eArgTypeNone, "Specify the language for the commands - if none is specified, the lldb command interpreter will be used." }, - { LLDB_OPT_SET_2, false, "python-function", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonFunction, "Give the name of a Python function to run as command for this breakpoint. Be sure to give a module name if appropriate." }, - { LLDB_OPT_SET_ALL, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Sets Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_command_add +#include "CommandOptions.inc" class CommandObjectBreakpointCommandAdd : public CommandObjectParsed, public IOHandlerDelegateMultiline { @@ -221,7 +221,7 @@ are no syntax errors may indicate that a function was declared but never called. Options *GetOptions() override { return &m_options; } void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString(g_reader_instructions); output_sp->Flush(); @@ -238,7 +238,7 @@ are no syntax errors may indicate that a function was declared but never called. if (!bp_options) continue; - auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>(); + auto cmd_data = std::make_unique<BreakpointOptions::CommandData>(); cmd_data->user_source.SplitIntoLines(line.c_str(), line.size()); bp_options->SetCommandDataCallback(cmd_data); } @@ -260,7 +260,7 @@ are no syntax errors may indicate that a function was declared but never called. SetBreakpointCommandCallback(std::vector<BreakpointOptions *> &bp_options_vec, const char *oneliner) { for (auto bp_options : bp_options_vec) { - auto cmd_data = llvm::make_unique<BreakpointOptions::CommandData>(); + auto cmd_data = std::make_unique<BreakpointOptions::CommandData>(); cmd_data->user_source.AppendString(oneliner); cmd_data->stop_on_error = m_options.m_stop_on_error; @@ -291,7 +291,8 @@ are no syntax errors may indicate that a function was declared but never called. case 's': m_script_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum( - option_arg, g_breakpoint_add_options[option_idx].enum_values, + option_arg, + g_breakpoint_command_add_options[option_idx].enum_values, eScriptLanguageNone, error); if (m_script_language == eScriptLanguagePython || @@ -323,7 +324,7 @@ are no syntax errors may indicate that a function was declared but never called. break; default: - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -341,7 +342,7 @@ are no syntax errors may indicate that a function was declared but never called. } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_add_options); + return llvm::makeArrayRef(g_breakpoint_command_add_options); } // Instance variables to hold the values for command options. @@ -360,16 +361,9 @@ are no syntax errors may indicate that a function was declared but never called. protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); + Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - if (target == nullptr) { - result.AppendError("There is not a current executable; there are no " - "breakpoints to which to add commands"); - result.SetStatus(eReturnStatusFailed); - return false; - } - - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) { @@ -388,7 +382,7 @@ protected: BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::listPerm); m_bp_options_vec.clear(); @@ -400,7 +394,7 @@ protected: BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { Breakpoint *bp = - target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); BreakpointOptions *bp_options = nullptr; if (cur_bp_id.GetLocationID() == LLDB_INVALID_BREAK_ID) { // This breakpoint does not have an associated location. @@ -469,11 +463,8 @@ const char *CommandObjectBreakpointCommandAdd::g_reader_instructions = // CommandObjectBreakpointCommandDelete -static constexpr OptionDefinition g_breakpoint_delete_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "dummy-breakpoints", 'D', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Delete commands from Dummy breakpoints - i.e. breakpoints set before a file is provided, which prime new targets." }, - // clang-format on -}; +#define LLDB_OPTIONS_breakpoint_command_delete +#include "CommandOptions.inc" class CommandObjectBreakpointCommandDelete : public CommandObjectParsed { public: @@ -518,9 +509,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -531,7 +520,7 @@ public: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_breakpoint_delete_options); + return llvm::makeArrayRef(g_breakpoint_command_delete_options); } // Instance variables to hold the values for command options. @@ -540,16 +529,9 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - - if (target == nullptr) { - result.AppendError("There is not a current executable; there are no " - "breakpoints from which to delete commands"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target &target = GetSelectedOrDummyTarget(m_options.m_use_dummy); - const BreakpointList &breakpoints = target->GetBreakpointList(); + const BreakpointList &breakpoints = target.GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); if (num_breakpoints == 0) { @@ -567,7 +549,7 @@ protected: BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, &target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::listPerm); if (result.Succeeded()) { @@ -576,7 +558,7 @@ protected: BreakpointID cur_bp_id = valid_bp_ids.GetBreakpointIDAtIndex(i); if (cur_bp_id.GetBreakpointID() != LLDB_INVALID_BREAK_ID) { Breakpoint *bp = - target->GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); + target.GetBreakpointByID(cur_bp_id.GetBreakpointID()).get(); if (cur_bp_id.GetLocationID() != LLDB_INVALID_BREAK_ID) { BreakpointLocationSP bp_loc_sp( bp->FindLocationByID(cur_bp_id.GetLocationID())); @@ -607,10 +589,10 @@ private: class CommandObjectBreakpointCommandList : public CommandObjectParsed { public: CommandObjectBreakpointCommandList(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "list", "List the script or set of " - "commands to be executed when " - "the breakpoint is hit.", - nullptr) { + : CommandObjectParsed(interpreter, "list", + "List the script or set of commands to be " + "executed when the breakpoint is hit.", + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandArgumentData bp_id_arg; @@ -630,14 +612,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - - if (target == nullptr) { - result.AppendError("There is not a current executable; there are no " - "breakpoints for which to list commands"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); const BreakpointList &breakpoints = target->GetBreakpointList(); size_t num_breakpoints = breakpoints.GetSize(); @@ -657,7 +632,7 @@ protected: BreakpointIDList valid_bp_ids; CommandObjectMultiwordBreakpoint::VerifyBreakpointOrLocationIDs( - command, target, result, &valid_bp_ids, + command, target, result, &valid_bp_ids, BreakpointName::Permissions::PermissionKinds::listPerm); if (result.Succeeded()) { diff --git a/source/Commands/CommandObjectBugreport.cpp b/source/Commands/CommandObjectBugreport.cpp deleted file mode 100644 index 515cc9a113b1..000000000000 --- a/source/Commands/CommandObjectBugreport.cpp +++ /dev/null @@ -1,124 +0,0 @@ -//===-- CommandObjectBugreport.cpp ------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#include "CommandObjectBugreport.h" - -#include <cstdio> - - -#include "lldb/Interpreter/CommandInterpreter.h" -#include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Interpreter/OptionGroupOutputFile.h" -#include "lldb/Target/Thread.h" - -using namespace lldb; -using namespace lldb_private; - -// "bugreport unwind" - -class CommandObjectBugreportUnwind : public CommandObjectParsed { -public: - CommandObjectBugreportUnwind(CommandInterpreter &interpreter) - : CommandObjectParsed( - interpreter, "bugreport unwind", - "Create a bugreport for a bug in the stack unwinding code.", - nullptr), - m_option_group(), m_outfile_options() { - m_option_group.Append(&m_outfile_options, LLDB_OPT_SET_ALL, - LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | LLDB_OPT_SET_3); - m_option_group.Finalize(); - } - - ~CommandObjectBugreportUnwind() override {} - - Options *GetOptions() override { return &m_option_group; } - -protected: - bool DoExecute(Args &command, CommandReturnObject &result) override { - StringList commands; - commands.AppendString("thread backtrace"); - - Thread *thread = m_exe_ctx.GetThreadPtr(); - if (thread) { - char command_buffer[256]; - - uint32_t frame_count = thread->GetStackFrameCount(); - for (uint32_t i = 0; i < frame_count; ++i) { - StackFrameSP frame = thread->GetStackFrameAtIndex(i); - lldb::addr_t pc = frame->GetStackID().GetPC(); - - snprintf(command_buffer, sizeof(command_buffer), - "disassemble --bytes --address 0x%" PRIx64, pc); - commands.AppendString(command_buffer); - - snprintf(command_buffer, sizeof(command_buffer), - "image show-unwind --address 0x%" PRIx64, pc); - commands.AppendString(command_buffer); - } - } - - const FileSpec &outfile_spec = - m_outfile_options.GetFile().GetCurrentValue(); - if (outfile_spec) { - - uint32_t open_options = - File::eOpenOptionWrite | File::eOpenOptionCanCreate | - File::eOpenOptionAppend | File::eOpenOptionCloseOnExec; - - const bool append = m_outfile_options.GetAppend().GetCurrentValue(); - if (!append) - open_options |= File::eOpenOptionTruncate; - - StreamFileSP outfile_stream = std::make_shared<StreamFile>(); - File &file = outfile_stream->GetFile(); - Status error = - FileSystem::Instance().Open(file, outfile_spec, open_options); - if (error.Fail()) { - auto path = outfile_spec.GetPath(); - result.AppendErrorWithFormat("Failed to open file '%s' for %s: %s\n", - path.c_str(), append ? "append" : "write", - error.AsCString()); - result.SetStatus(eReturnStatusFailed); - return false; - } - - result.SetImmediateOutputStream(outfile_stream); - } - - CommandInterpreterRunOptions options; - options.SetStopOnError(false); - options.SetEchoCommands(true); - options.SetPrintResults(true); - options.SetPrintErrors(true); - options.SetAddToHistory(false); - m_interpreter.HandleCommands(commands, &m_exe_ctx, options, result); - - return result.Succeeded(); - } - -private: - OptionGroupOptions m_option_group; - OptionGroupOutputFile m_outfile_options; -}; - -#pragma mark CommandObjectMultiwordBugreport - -// CommandObjectMultiwordBugreport - -CommandObjectMultiwordBugreport::CommandObjectMultiwordBugreport( - CommandInterpreter &interpreter) - : CommandObjectMultiword( - interpreter, "bugreport", - "Commands for creating domain-specific bug reports.", - "bugreport <subcommand> [<subcommand-options>]") { - - LoadSubCommand( - "unwind", CommandObjectSP(new CommandObjectBugreportUnwind(interpreter))); -} - -CommandObjectMultiwordBugreport::~CommandObjectMultiwordBugreport() {} diff --git a/source/Commands/CommandObjectBugreport.h b/source/Commands/CommandObjectBugreport.h deleted file mode 100644 index 24ce6d237d56..000000000000 --- a/source/Commands/CommandObjectBugreport.h +++ /dev/null @@ -1,27 +0,0 @@ -//===-- CommandObjectBugreport.h --------------------------------*- C++ -*-===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -#ifndef liblldb_CommandObjectBugreport_h_ -#define liblldb_CommandObjectBugreport_h_ - -#include "lldb/Interpreter/CommandObjectMultiword.h" - -namespace lldb_private { - -// CommandObjectMultiwordBugreport - -class CommandObjectMultiwordBugreport : public CommandObjectMultiword { -public: - CommandObjectMultiwordBugreport(CommandInterpreter &interpreter); - - ~CommandObjectMultiwordBugreport() override; -}; - -} // namespace lldb_private - -#endif // liblldb_CommandObjectBugreport_h_ diff --git a/source/Commands/CommandObjectCommands.cpp b/source/Commands/CommandObjectCommands.cpp index 4092e76be6ac..259affbe6e0a 100644 --- a/source/Commands/CommandObjectCommands.cpp +++ b/source/Commands/CommandObjectCommands.cpp @@ -31,14 +31,8 @@ using namespace lldb_private; // CommandObjectCommandsSource -static constexpr OptionDefinition g_history_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "How many history commands to print." }, - { 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)." }, - { LLDB_OPT_SET_1, false, "end-index", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Index at which to stop printing history commands." }, - { LLDB_OPT_SET_2, false, "clear", 'C', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeBoolean, "Clears the current command history." }, - // clang-format on -}; +#define LLDB_OPTIONS_history +#include "CommandOptions.inc" class CommandObjectCommandsHistory : public CommandObjectParsed { public: @@ -91,9 +85,7 @@ protected: m_clear.SetOptionWasSet(); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -188,13 +180,8 @@ protected: // CommandObjectCommandsSource -static constexpr OptionDefinition g_source_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "stop-on-error", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, stop executing commands on error." }, - { LLDB_OPT_SET_ALL, false, "stop-on-continue", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true, stop executing commands on continue." }, - { LLDB_OPT_SET_ALL, false, "silent-run", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "If true don't echo commands while executing." }, - // clang-format on -}; +#define LLDB_OPTIONS_source +#include "CommandOptions.inc" class CommandObjectCommandsSource : public CommandObjectParsed { public: @@ -226,13 +213,12 @@ public: return ""; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } Options *GetOptions() override { return &m_options; } @@ -265,9 +251,7 @@ protected: break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -299,7 +283,7 @@ protected: return false; } - FileSpec cmd_file(command[0].ref); + FileSpec cmd_file(command[0].ref()); FileSystem::Instance().Resolve(cmd_file); ExecutionContext *exe_ctx = nullptr; // Just use the default context. @@ -343,12 +327,8 @@ protected: #pragma mark CommandObjectCommandsAlias // CommandObjectCommandsAlias -static constexpr OptionDefinition g_alias_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "help", 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "Help text for this command" }, - { LLDB_OPT_SET_ALL, false, "long-help", 'H', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "Long help text for this command" }, - // clang-format on -}; +#define LLDB_OPTIONS_alias +#include "CommandOptions.inc" static const char *g_python_command_instructions = "Enter your Python command(s). Type 'DONE' to end.\n" @@ -386,9 +366,7 @@ protected: break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -568,7 +546,7 @@ protected: // Get the alias command. - auto alias_command = args[0].ref; + auto alias_command = args[0].ref(); if (alias_command.startswith("-")) { result.AppendError("aliases starting with a dash are not supported"); if (alias_command == "--help" || alias_command == "--long-help") { @@ -675,8 +653,8 @@ protected: } // Save these in std::strings since we're going to shift them off. - const std::string alias_command(args[0].ref); - const std::string actual_command(args[1].ref); + const std::string alias_command(args[0].ref()); + const std::string actual_command(args[1].ref()); args.Shift(); // Shift the alias command word off the argument vector. args.Shift(); // Shift the old command word off the argument vector. @@ -708,7 +686,7 @@ protected: OptionArgVectorSP(new OptionArgVector); while (cmd_obj->IsMultiwordObject() && !args.empty()) { - auto sub_command = args[0].ref; + auto sub_command = args[0].ref(); assert(!sub_command.empty()); subcommand_obj_sp = cmd_obj->GetSubcommandSP(sub_command); if (!subcommand_obj_sp) { @@ -802,7 +780,7 @@ protected: return false; } - auto command_name = args[0].ref; + auto command_name = args[0].ref(); cmd_obj = m_interpreter.GetCommandObject(command_name); if (!cmd_obj) { result.AppendErrorWithFormat( @@ -881,9 +859,10 @@ protected: "defined regular expression command names", GetCommandName().str().c_str()); result.SetStatus(eReturnStatusFailed); + return false; } - auto command_name = args[0].ref; + auto command_name = args[0].ref(); if (!m_interpreter.CommandExists(command_name)) { StreamString error_msg_stream; const bool generate_upropos = true; @@ -911,12 +890,8 @@ protected: // CommandObjectCommandsAddRegex -static constexpr OptionDefinition g_regex_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The help text to display for this command." }, - { LLDB_OPT_SET_1, false, "syntax", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "A syntax string showing the typical usage syntax." }, - // clang-format on -}; +#define LLDB_OPTIONS_regex +#include "CommandOptions.inc" #pragma mark CommandObjectCommandsAddRegex @@ -970,7 +945,7 @@ a number follows 'f':" protected: void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString("Enter one or more sed substitution commands in " "the form: 's/<regex>/<subst>/'.\nTerminate the " @@ -985,11 +960,9 @@ protected: if (m_regex_cmd_up) { StringList lines; if (lines.SplitIntoLines(data)) { - const size_t num_lines = lines.GetSize(); bool check_only = false; - for (size_t i = 0; i < num_lines; ++i) { - llvm::StringRef bytes_strref(lines[i]); - Status error = AppendRegexSubstitution(bytes_strref, check_only); + for (const std::string &line : lines) { + Status error = AppendRegexSubstitution(line, check_only); if (error.Fail()) { if (!GetDebugger().GetCommandInterpreter().GetBatchCommandMode()) { StreamSP out_stream = GetDebugger().GetAsyncOutputStream(); @@ -1015,8 +988,8 @@ protected: } Status error; - auto name = command[0].ref; - m_regex_cmd_up = llvm::make_unique<CommandObjectRegexCommand>( + auto name = command[0].ref(); + m_regex_cmd_up = std::make_unique<CommandObjectRegexCommand>( m_interpreter, name, m_options.GetHelp(), m_options.GetSyntax(), 10, 0, true); @@ -1040,7 +1013,7 @@ protected: } else { for (auto &entry : command.entries().drop_front()) { bool check_only = false; - error = AppendRegexSubstitution(entry.ref, check_only); + error = AppendRegexSubstitution(entry.ref(), check_only); if (error.Fail()) break; } @@ -1183,9 +1156,7 @@ private: m_syntax.assign(option_arg); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1315,8 +1286,6 @@ public: bool IsRemovable() const override { return true; } - StructuredData::GenericSP GetImplementingObject() { return m_cmd_obj_sp; } - ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } llvm::StringRef GetHelp() override { @@ -1385,12 +1354,8 @@ private: }; // CommandObjectCommandsScriptImport - -static constexpr OptionDefinition g_script_import_options[] = { - // clang-format off - { 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." }, - // clang-format on -}; +#define LLDB_OPTIONS_script_import +#include "CommandOptions.inc" class CommandObjectCommandsScriptImport : public CommandObjectParsed { public: @@ -1415,13 +1380,12 @@ public: ~CommandObjectCommandsScriptImport() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } Options *GetOptions() override { return &m_options; } @@ -1443,9 +1407,7 @@ protected: m_allow_reload = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1509,25 +1471,29 @@ protected: // CommandObjectCommandsScriptAdd static constexpr OptionEnumValueElement g_script_synchro_type[] = { - {eScriptedCommandSynchronicitySynchronous, "synchronous", - "Run synchronous"}, - {eScriptedCommandSynchronicityAsynchronous, "asynchronous", - "Run asynchronous"}, - {eScriptedCommandSynchronicityCurrentValue, "current", - "Do not alter current setting"} }; + { + eScriptedCommandSynchronicitySynchronous, + "synchronous", + "Run synchronous", + }, + { + eScriptedCommandSynchronicityAsynchronous, + "asynchronous", + "Run asynchronous", + }, + { + eScriptedCommandSynchronicityCurrentValue, + "current", + "Do not alter current setting", + }, +}; static constexpr OptionEnumValues ScriptSynchroType() { return OptionEnumValues(g_script_synchro_type); } -static constexpr OptionDefinition g_script_add_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "function", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonFunction, "Name of the Python function to bind to this command name." }, - { LLDB_OPT_SET_2, false, "class", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "Name of the Python class to bind to this command name." }, - { LLDB_OPT_SET_1, false, "help" , 'h', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeHelpText, "The help text to display for this command." }, - { 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." }, - // clang-format on -}; +#define LLDB_OPTIONS_script_add +#include "CommandOptions.inc" class CommandObjectCommandsScriptAdd : public CommandObjectParsed, public IOHandlerDelegateMultiline { @@ -1593,9 +1559,7 @@ protected: option_arg.str().c_str()); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1621,7 +1585,7 @@ protected: }; void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString(g_python_command_instructions); output_sp->Flush(); @@ -1630,7 +1594,7 @@ protected: void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); + StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); if (interpreter) { @@ -1692,7 +1656,7 @@ protected: } // Store the options in case we get multi-line input - m_cmd_name = command[0].ref; + m_cmd_name = command[0].ref(); m_short_help.assign(m_options.m_short_help); m_synchronicity = m_options.m_synchronicity; @@ -1761,6 +1725,12 @@ public: ~CommandObjectCommandsScriptList() override = default; bool DoExecute(Args &command, CommandReturnObject &result) override { + if (command.GetArgumentCount() != 0) { + result.AppendError("'command script list' doesn't take any arguments"); + result.SetStatus(eReturnStatusFailed); + return false; + } + m_interpreter.GetHelp(result, CommandInterpreter::eCommandTypesUserDef); result.SetStatus(eReturnStatusSuccessFinishResult); @@ -1781,6 +1751,12 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { + if (command.GetArgumentCount() != 0) { + result.AppendError("'command script clear' doesn't take any arguments"); + result.SetStatus(eReturnStatusFailed); + return false; + } + m_interpreter.RemoveAllUser(); result.SetStatus(eReturnStatusSuccessFinishResult); @@ -1822,7 +1798,7 @@ protected: return false; } - auto cmd_name = command[0].ref; + auto cmd_name = command[0].ref(); if (cmd_name.empty() || !m_interpreter.HasUserCommands() || !m_interpreter.UserCommandExists(cmd_name)) { diff --git a/source/Commands/CommandObjectDisassemble.cpp b/source/Commands/CommandObjectDisassemble.cpp index 5972555b2499..69e2d757b5fe 100644 --- a/source/Commands/CommandObjectDisassemble.cpp +++ b/source/Commands/CommandObjectDisassemble.cpp @@ -30,32 +30,8 @@ using namespace lldb; using namespace lldb_private; -static constexpr OptionDefinition g_disassemble_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "bytes", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show opcode bytes when disassembling." }, - { LLDB_OPT_SET_ALL, false, "context", 'C', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNumLines, "Number of context lines of source to show." }, - { LLDB_OPT_SET_ALL, false, "mixed", 'm', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable mixed source and assembly display." }, - { LLDB_OPT_SET_ALL, false, "raw", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Print raw disassembly with no symbol information." }, - { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the disassembler plugin you want to use." }, - { LLDB_OPT_SET_ALL, false, "flavor", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeDisassemblyFlavor, "Name of the disassembly flavor you want to use. " - "Currently the only valid options are default, and for Intel " - "architectures, att and intel." }, - { LLDB_OPT_SET_ALL, false, "arch", 'A', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeArchitecture, "Specify the architecture to use from cross disassembly." }, - { LLDB_OPT_SET_1 | - LLDB_OPT_SET_2, true, "start-address", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Address at which to start disassembling." }, - { LLDB_OPT_SET_1, false, "end-address", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Address at which to end disassembling." }, - { LLDB_OPT_SET_2 | - LLDB_OPT_SET_3 | - LLDB_OPT_SET_4 | - LLDB_OPT_SET_5, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNumLines, "Number of instructions to display." }, - { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Disassemble entire contents of the given function name." }, - { LLDB_OPT_SET_4, false, "frame", 'f', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disassemble from the start of the current frame's function." }, - { LLDB_OPT_SET_5, false, "pc", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disassemble around the current pc." }, - { LLDB_OPT_SET_6, false, "line", 'l', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Disassemble the current frame's current source line instructions if there is debug line " - "table information, else disassemble around the pc." }, - { LLDB_OPT_SET_7, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Disassemble function containing this address." }, - // clang-format on -}; +#define LLDB_OPTIONS_disassemble +#include "CommandOptions.inc" CommandObjectDisassemble::CommandOptions::CommandOptions() : Options(), num_lines_context(0), num_instructions(0), func_name(), @@ -171,9 +147,7 @@ Status CommandObjectDisassemble::CommandOptions::SetOptionValue( } break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -238,20 +212,15 @@ CommandObjectDisassemble::CommandObjectDisassemble( "Disassemble specified instructions in the current target. " "Defaults to the current function for the current thread and " "stack frame.", - "disassemble [<cmd-options>]"), + "disassemble [<cmd-options>]", eCommandRequiresTarget), m_options() {} CommandObjectDisassemble::~CommandObjectDisassemble() = default; bool CommandObjectDisassemble::DoExecute(Args &command, CommandReturnObject &result) { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); + if (!m_options.arch.IsValid()) m_options.arch = target->GetArchitecture(); @@ -541,7 +510,7 @@ bool CommandObjectDisassemble::DoExecute(Args &command, } else { result.AppendErrorWithFormat( "Failed to disassemble memory at 0x%8.8" PRIx64 ".\n", - m_options.start_addr); + cur_range.GetBaseAddress().GetLoadAddress(target)); result.SetStatus(eReturnStatusFailed); } if (print_sc_header) diff --git a/source/Commands/CommandObjectExpression.cpp b/source/Commands/CommandObjectExpression.cpp index 29e4ab695522..9bafdc149804 100644 --- a/source/Commands/CommandObjectExpression.cpp +++ b/source/Commands/CommandObjectExpression.cpp @@ -38,34 +38,24 @@ CommandObjectExpression::CommandOptions::CommandOptions() : OptionGroup() {} CommandObjectExpression::CommandOptions::~CommandOptions() = default; static constexpr OptionEnumValueElement g_description_verbosity_type[] = { - {eLanguageRuntimeDescriptionDisplayVerbosityCompact, "compact", - "Only show the description string"}, - {eLanguageRuntimeDescriptionDisplayVerbosityFull, "full", - "Show the full output, including persistent variable's name and type"} }; + { + eLanguageRuntimeDescriptionDisplayVerbosityCompact, + "compact", + "Only show the description string", + }, + { + eLanguageRuntimeDescriptionDisplayVerbosityFull, + "full", + "Show the full output, including persistent variable's name and type", + }, +}; static constexpr OptionEnumValues DescriptionVerbosityTypes() { return OptionEnumValues(g_description_verbosity_type); } -static constexpr OptionDefinition g_expression_options[] = { - // clang-format off - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "all-threads", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Should we run all threads if the execution doesn't complete on one thread."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "ignore-breakpoints", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Ignore breakpoint hits while running expressions"}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Timeout value (in microseconds) for running the expression."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "unwind-on-error", 'u', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Clean up program state if the expression causes a crash, or raises a signal. " - "Note, unlike gdb hitting a breakpoint is controlled by another option (-i)."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "debug", 'g', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "When specified, debug the JIT code by setting a breakpoint on the first instruction " - "and forcing breakpoints to not be ignored (-i0) and no unwinding to happen on error (-u0)."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "language", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "Specifies the Language to use when parsing the expression. If not set the target.language " - "setting is used." }, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "apply-fixits", 'X', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "If true, simple fix-it hints will be automatically applied to the expression." }, - {LLDB_OPT_SET_1, false, "description-verbosity", 'v', OptionParser::eOptionalArgument, nullptr, DescriptionVerbosityTypes(), 0, eArgTypeDescriptionVerbosity, "How verbose should the output of this expression be, if the object description is asked for."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "top-level", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Interpret the expression as a complete translation unit, without injecting it into the local " - "context. Allows declaration of persistent, top-level entities without a $ prefix."}, - {LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "allow-jit", 'j', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Controls whether the expression can fall back to being JITted if it's not supported by " - "the interpreter (defaults to true)."} - // clang-format on -}; +#define LLDB_OPTIONS_expression +#include "CommandOptions.inc" Status CommandObjectExpression::CommandOptions::SetOptionValue( uint32_t option_idx, llvm::StringRef option_arg, @@ -176,9 +166,7 @@ Status CommandObjectExpression::CommandOptions::SetOptionValue( } default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -304,7 +292,7 @@ CommandObjectExpression::~CommandObjectExpression() = default; Options *CommandObjectExpression::GetOptions() { return &m_option_group; } -int CommandObjectExpression::HandleCompletion(CompletionRequest &request) { +void CommandObjectExpression::HandleCompletion(CompletionRequest &request) { EvaluateExpressionOptions options; options.SetCoerceToId(m_varobj_options.use_objc); options.SetLanguage(m_command_options.language); @@ -321,17 +309,14 @@ int CommandObjectExpression::HandleCompletion(CompletionRequest &request) { // This didn't work, so let's get out before we start doing things that // expect a valid frame pointer. if (m_interpreter.GetExecutionContext().GetFramePtr() == nullptr) - return 0; + return; ExecutionContext exe_ctx(m_interpreter.GetExecutionContext()); Target *target = exe_ctx.GetTargetPtr(); if (!target) - target = GetDummyTarget(); - - if (!target) - return 0; + target = &GetDummyTarget(); unsigned cursor_pos = request.GetRawCursorPos(); llvm::StringRef code = request.GetRawLine(); @@ -351,7 +336,7 @@ int CommandObjectExpression::HandleCompletion(CompletionRequest &request) { // exit. // FIXME: We should complete the options here. if (cursor_pos < raw_start) - return 0; + return; // Make the cursor_pos again relative to the start of the code string. assert(cursor_pos >= raw_start); @@ -364,10 +349,9 @@ int CommandObjectExpression::HandleCompletion(CompletionRequest &request) { code, llvm::StringRef(), language, UserExpression::eResultTypeAny, options, nullptr, error)); if (error.Fail()) - return 0; + return; expr->Complete(exe_ctx, request, cursor_pos); - return request.GetNumberOfMatches(); } static lldb_private::Status @@ -393,123 +377,116 @@ bool CommandObjectExpression::EvaluateExpression(llvm::StringRef expr, Target *target = exe_ctx.GetTargetPtr(); if (!target) - target = GetDummyTarget(); - - if (target) { - lldb::ValueObjectSP result_valobj_sp; - bool keep_in_memory = true; - StackFrame *frame = exe_ctx.GetFramePtr(); - - EvaluateExpressionOptions options; - options.SetCoerceToId(m_varobj_options.use_objc); - options.SetUnwindOnError(m_command_options.unwind_on_error); - options.SetIgnoreBreakpoints(m_command_options.ignore_breakpoints); - options.SetKeepInMemory(keep_in_memory); - options.SetUseDynamic(m_varobj_options.use_dynamic); - options.SetTryAllThreads(m_command_options.try_all_threads); - options.SetDebug(m_command_options.debug); - options.SetLanguage(m_command_options.language); - options.SetExecutionPolicy( - m_command_options.allow_jit - ? EvaluateExpressionOptions::default_execution_policy - : lldb_private::eExecutionPolicyNever); - - bool auto_apply_fixits; - if (m_command_options.auto_apply_fixits == eLazyBoolCalculate) - auto_apply_fixits = target->GetEnableAutoApplyFixIts(); - else - auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes; + target = &GetDummyTarget(); - options.SetAutoApplyFixIts(auto_apply_fixits); + lldb::ValueObjectSP result_valobj_sp; + bool keep_in_memory = true; + StackFrame *frame = exe_ctx.GetFramePtr(); + + EvaluateExpressionOptions options; + options.SetCoerceToId(m_varobj_options.use_objc); + options.SetUnwindOnError(m_command_options.unwind_on_error); + options.SetIgnoreBreakpoints(m_command_options.ignore_breakpoints); + options.SetKeepInMemory(keep_in_memory); + options.SetUseDynamic(m_varobj_options.use_dynamic); + options.SetTryAllThreads(m_command_options.try_all_threads); + options.SetDebug(m_command_options.debug); + options.SetLanguage(m_command_options.language); + options.SetExecutionPolicy( + m_command_options.allow_jit + ? EvaluateExpressionOptions::default_execution_policy + : lldb_private::eExecutionPolicyNever); + + bool auto_apply_fixits; + if (m_command_options.auto_apply_fixits == eLazyBoolCalculate) + auto_apply_fixits = target->GetEnableAutoApplyFixIts(); + else + auto_apply_fixits = m_command_options.auto_apply_fixits == eLazyBoolYes; - if (m_command_options.top_level) - options.SetExecutionPolicy(eExecutionPolicyTopLevel); + options.SetAutoApplyFixIts(auto_apply_fixits); - // If there is any chance we are going to stop and want to see what went - // wrong with our expression, we should generate debug info - if (!m_command_options.ignore_breakpoints || - !m_command_options.unwind_on_error) - options.SetGenerateDebugInfo(true); + if (m_command_options.top_level) + options.SetExecutionPolicy(eExecutionPolicyTopLevel); - if (m_command_options.timeout > 0) - options.SetTimeout(std::chrono::microseconds(m_command_options.timeout)); - else - options.SetTimeout(llvm::None); - - ExpressionResults success = target->EvaluateExpression( - expr, frame, result_valobj_sp, options, &m_fixed_expression); - - // We only tell you about the FixIt if we applied it. The compiler errors - // will suggest the FixIt if it parsed. - if (error_stream && !m_fixed_expression.empty() && - target->GetEnableNotifyAboutFixIts()) { - if (success == eExpressionCompleted) - error_stream->Printf( - " Fix-it applied, fixed expression was: \n %s\n", - m_fixed_expression.c_str()); - } + // If there is any chance we are going to stop and want to see what went + // wrong with our expression, we should generate debug info + if (!m_command_options.ignore_breakpoints || + !m_command_options.unwind_on_error) + options.SetGenerateDebugInfo(true); - if (result_valobj_sp) { - Format format = m_format_options.GetFormat(); - - if (result_valobj_sp->GetError().Success()) { - if (format != eFormatVoid) { - if (format != eFormatDefault) - result_valobj_sp->SetFormat(format); - - if (m_varobj_options.elem_count > 0) { - Status error(CanBeUsedForElementCountPrinting(*result_valobj_sp)); - if (error.Fail()) { - result->AppendErrorWithFormat( - "expression cannot be used with --element-count %s\n", - error.AsCString("")); - result->SetStatus(eReturnStatusFailed); - return false; - } + if (m_command_options.timeout > 0) + options.SetTimeout(std::chrono::microseconds(m_command_options.timeout)); + else + options.SetTimeout(llvm::None); + + ExpressionResults success = target->EvaluateExpression( + expr, frame, result_valobj_sp, options, &m_fixed_expression); + + // We only tell you about the FixIt if we applied it. The compiler errors + // will suggest the FixIt if it parsed. + if (error_stream && !m_fixed_expression.empty() && + target->GetEnableNotifyAboutFixIts()) { + if (success == eExpressionCompleted) + error_stream->Printf(" Fix-it applied, fixed expression was: \n %s\n", + m_fixed_expression.c_str()); + } + + if (result_valobj_sp) { + Format format = m_format_options.GetFormat(); + + if (result_valobj_sp->GetError().Success()) { + if (format != eFormatVoid) { + if (format != eFormatDefault) + result_valobj_sp->SetFormat(format); + + if (m_varobj_options.elem_count > 0) { + Status error(CanBeUsedForElementCountPrinting(*result_valobj_sp)); + if (error.Fail()) { + result->AppendErrorWithFormat( + "expression cannot be used with --element-count %s\n", + error.AsCString("")); + result->SetStatus(eReturnStatusFailed); + return false; } + } - DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions( - m_command_options.m_verbosity, format)); - options.SetVariableFormatDisplayLanguage( - result_valobj_sp->GetPreferredDisplayLanguage()); + DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions( + m_command_options.m_verbosity, format)); + options.SetVariableFormatDisplayLanguage( + result_valobj_sp->GetPreferredDisplayLanguage()); - result_valobj_sp->Dump(*output_stream, options); + result_valobj_sp->Dump(*output_stream, options); - if (result) - result->SetStatus(eReturnStatusSuccessFinishResult); + if (result) + result->SetStatus(eReturnStatusSuccessFinishResult); + } + } else { + if (result_valobj_sp->GetError().GetError() == + UserExpression::kNoResult) { + if (format != eFormatVoid && GetDebugger().GetNotifyVoid()) { + error_stream->PutCString("(void)\n"); } - } else { - if (result_valobj_sp->GetError().GetError() == - UserExpression::kNoResult) { - if (format != eFormatVoid && GetDebugger().GetNotifyVoid()) { - error_stream->PutCString("(void)\n"); - } - if (result) - result->SetStatus(eReturnStatusSuccessFinishResult); + if (result) + result->SetStatus(eReturnStatusSuccessFinishResult); + } else { + const char *error_cstr = result_valobj_sp->GetError().AsCString(); + if (error_cstr && error_cstr[0]) { + const size_t error_cstr_len = strlen(error_cstr); + const bool ends_with_newline = error_cstr[error_cstr_len - 1] == '\n'; + if (strstr(error_cstr, "error:") != error_cstr) + error_stream->PutCString("error: "); + error_stream->Write(error_cstr, error_cstr_len); + if (!ends_with_newline) + error_stream->EOL(); } else { - const char *error_cstr = result_valobj_sp->GetError().AsCString(); - if (error_cstr && error_cstr[0]) { - const size_t error_cstr_len = strlen(error_cstr); - const bool ends_with_newline = - error_cstr[error_cstr_len - 1] == '\n'; - if (strstr(error_cstr, "error:") != error_cstr) - error_stream->PutCString("error: "); - error_stream->Write(error_cstr, error_cstr_len); - if (!ends_with_newline) - error_stream->EOL(); - } else { - error_stream->PutCString("error: unknown error\n"); - } - - if (result) - result->SetStatus(eReturnStatusFailed); + error_stream->PutCString("error: unknown error\n"); } + + if (result) + result->SetStatus(eReturnStatusFailed); } } - } else { - error_stream->Printf("error: invalid execution context for expression\n"); - return false; } return true; @@ -521,8 +498,8 @@ void CommandObjectExpression::IOHandlerInputComplete(IOHandler &io_handler, // StreamSP output_stream = // io_handler.GetDebugger().GetAsyncOutputStream(); // StreamSP error_stream = io_handler.GetDebugger().GetAsyncErrorStream(); - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); - StreamFileSP error_sp(io_handler.GetErrorStreamFile()); + StreamFileSP output_sp = io_handler.GetOutputStreamFileSP(); + StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); EvaluateExpression(line.c_str(), output_sp.get(), error_sp.get()); if (output_sp) @@ -560,7 +537,7 @@ void CommandObjectExpression::GetMultilineExpression() { 1, // Show line numbers starting at 1 *this, nullptr)); - StreamFileSP output_sp(io_handler_sp->GetOutputStreamFile()); + StreamFileSP output_sp = io_handler_sp->GetOutputStreamFileSP(); if (output_sp) { output_sp->PutCString( "Enter expressions, then terminate with an empty line to evaluate:\n"); @@ -675,11 +652,11 @@ bool CommandObjectExpression::DoExecute(llvm::StringRef command, } } - Target *target = GetSelectedOrDummyTarget(); + Target &target = GetSelectedOrDummyTarget(); if (EvaluateExpression(expr, &(result.GetOutputStream()), &(result.GetErrorStream()), &result)) { - if (!m_fixed_expression.empty() && target->GetEnableNotifyAboutFixIts()) { + if (!m_fixed_expression.empty() && target.GetEnableNotifyAboutFixIts()) { CommandHistory &history = m_interpreter.GetCommandHistory(); // FIXME: Can we figure out what the user actually typed (e.g. some alias // for expr???) @@ -694,12 +671,12 @@ bool CommandObjectExpression::DoExecute(llvm::StringRef command, history.AppendString(fixed_command); } // Increment statistics to record this expression evaluation success. - target->IncrementStats(StatisticKind::ExpressionSuccessful); + target.IncrementStats(StatisticKind::ExpressionSuccessful); return true; } // Increment statistics to record this expression evaluation failure. - target->IncrementStats(StatisticKind::ExpressionFailure); + target.IncrementStats(StatisticKind::ExpressionFailure); result.SetStatus(eReturnStatusFailed); return false; } diff --git a/source/Commands/CommandObjectExpression.h b/source/Commands/CommandObjectExpression.h index 89c8e1dbeceb..8ef764239069 100644 --- a/source/Commands/CommandObjectExpression.h +++ b/source/Commands/CommandObjectExpression.h @@ -54,7 +54,7 @@ public: Options *GetOptions() override; - int HandleCompletion(CompletionRequest &request) override; + void HandleCompletion(CompletionRequest &request) override; protected: // IOHandler::Delegate functions diff --git a/source/Commands/CommandObjectFrame.cpp b/source/Commands/CommandObjectFrame.cpp index ab6a07952f19..6a7facdaff35 100644 --- a/source/Commands/CommandObjectFrame.cpp +++ b/source/Commands/CommandObjectFrame.cpp @@ -23,7 +23,6 @@ #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" #include "lldb/Interpreter/OptionGroupVariable.h" #include "lldb/Interpreter/Options.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompilerType.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" @@ -54,13 +53,8 @@ using namespace lldb_private; // CommandObjectFrameDiagnose -static constexpr OptionDefinition g_frame_diag_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "register", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegisterName, "A register to diagnose." }, - { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddress, "An address to diagnose." }, - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "An optional offset. Requires --register." } - // clang-format on -}; +#define LLDB_OPTIONS_frame_diag +#include "CommandOptions.inc" class CommandObjectFrameDiagnose : public CommandObjectParsed { public: @@ -98,9 +92,7 @@ public: } break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -238,11 +230,8 @@ protected: // CommandObjectFrameSelect -static OptionDefinition g_frame_select_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "relative", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "A relative frame index offset from the current frame index." }, - // clang-format on -}; +#define LLDB_OPTIONS_frame_select +#include "CommandOptions.inc" class CommandObjectFrameSelect : public CommandObjectParsed { public: @@ -257,32 +246,32 @@ public: Status error; const int short_option = m_getopt_table[option_idx].val; switch (short_option) { - case 'r': - if (option_arg.getAsInteger(0, relative_frame_offset)) { - relative_frame_offset = INT32_MIN; + case 'r': { + int32_t offset = 0; + if (option_arg.getAsInteger(0, offset) || offset == INT32_MIN) { error.SetErrorStringWithFormat("invalid frame offset argument '%s'", option_arg.str().c_str()); - } + } else + relative_frame_offset = offset; break; + } default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } void OptionParsingStarting(ExecutionContext *execution_context) override { - relative_frame_offset = INT32_MIN; + relative_frame_offset.reset(); } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { return llvm::makeArrayRef(g_frame_select_options); } - int32_t relative_frame_offset; + llvm::Optional<int32_t> relative_frame_offset; }; CommandObjectFrameSelect(CommandInterpreter &interpreter) @@ -320,15 +309,16 @@ protected: Thread *thread = m_exe_ctx.GetThreadPtr(); uint32_t frame_idx = UINT32_MAX; - if (m_options.relative_frame_offset != INT32_MIN) { + if (m_options.relative_frame_offset.hasValue()) { // The one and only argument is a signed relative frame index frame_idx = thread->GetSelectedFrameIndex(); if (frame_idx == UINT32_MAX) frame_idx = 0; - if (m_options.relative_frame_offset < 0) { - if (static_cast<int32_t>(frame_idx) >= -m_options.relative_frame_offset) - frame_idx += m_options.relative_frame_offset; + if (*m_options.relative_frame_offset < 0) { + if (static_cast<int32_t>(frame_idx) >= + -*m_options.relative_frame_offset) + frame_idx += *m_options.relative_frame_offset; else { if (frame_idx == 0) { // If you are already at the bottom of the stack, then just warn @@ -339,15 +329,15 @@ protected: } else frame_idx = 0; } - } else if (m_options.relative_frame_offset > 0) { + } else if (*m_options.relative_frame_offset > 0) { // I don't want "up 20" where "20" takes you past the top of the stack // to produce // an error, but rather to just go to the top. So I have to count the // stack here... const uint32_t num_frames = thread->GetStackFrameCount(); if (static_cast<int32_t>(num_frames - frame_idx) > - m_options.relative_frame_offset) - frame_idx += m_options.relative_frame_offset; + *m_options.relative_frame_offset) + frame_idx += *m_options.relative_frame_offset; else { if (frame_idx == num_frames - 1) { // If we are already at the top of the stack, just warn and don't @@ -371,7 +361,7 @@ protected: } if (command.GetArgumentCount() == 1) { - if (command[0].ref.getAsInteger(0, frame_idx)) { + if (command[0].ref().getAsInteger(0, frame_idx)) { result.AppendErrorWithFormat("invalid frame index argument '%s'.", command[0].c_str()); result.SetStatus(eReturnStatusFailed); @@ -460,14 +450,13 @@ public: Options *GetOptions() override { return &m_option_group; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { // Arguments are the standard source file completer. CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eVariablePathCompletion, request, nullptr); - return request.GetNumberOfMatches(); } protected: @@ -541,9 +530,9 @@ protected: for (auto &entry : command) { if (m_option_variable.use_regex) { const size_t regex_start_index = regex_var_list.GetSize(); - llvm::StringRef name_str = entry.ref; + llvm::StringRef name_str = entry.ref(); RegularExpression regex(name_str); - if (regex.Compile(name_str)) { + if (regex.IsValid()) { size_t num_matches = 0; const size_t num_new_regex_vars = variable_list->AppendVariablesIfUnique(regex, regex_var_list, @@ -582,9 +571,9 @@ protected: entry.c_str()); } } else { - char regex_error[1024]; - if (regex.GetErrorAsCString(regex_error, sizeof(regex_error))) - result.GetErrorStream().Printf("error: %s\n", regex_error); + if (llvm::Error err = regex.GetError()) + result.GetErrorStream().Printf( + "error: %s\n", llvm::toString(std::move(err)).c_str()); else result.GetErrorStream().Printf( "error: unknown regex error when compiling '%s'\n", @@ -600,7 +589,7 @@ protected: StackFrame::eExpressionPathOptionsInspectAnonymousUnions; lldb::VariableSP var_sp; valobj_sp = frame->GetValueForVariableExpressionPath( - entry.ref, m_varobj_options.use_dynamic, expr_path_options, + entry.ref(), m_varobj_options.use_dynamic, expr_path_options, var_sp, error); if (valobj_sp) { std::string scope_string; @@ -727,11 +716,11 @@ protected: // Increment statistics. bool res = result.Succeeded(); - Target *target = GetSelectedOrDummyTarget(); + Target &target = GetSelectedOrDummyTarget(); if (res) - target->IncrementStats(StatisticKind::FrameVarSuccess); + target.IncrementStats(StatisticKind::FrameVarSuccess); else - target->IncrementStats(StatisticKind::FrameVarFailure); + target.IncrementStats(StatisticKind::FrameVarFailure); return res; } @@ -744,14 +733,8 @@ protected: #pragma mark CommandObjectFrameRecognizer -static OptionDefinition g_frame_recognizer_add_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Name of the module or shared library that this recognizer applies to." }, - { LLDB_OPT_SET_ALL, false, "function", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeName, "Name of the function that this recognizer applies to." }, - { LLDB_OPT_SET_2, false, "python-class", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePythonClass, "Give the name of a Python class to use for this frame recognizer." }, - { LLDB_OPT_SET_ALL, false, "regex", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Function name and module name are actually regular expressions." } - // clang-format on -}; +#define LLDB_OPTIONS_frame_recognizer_add +#include "CommandOptions.inc" class CommandObjectFrameRecognizerAdd : public CommandObjectParsed { private: @@ -779,9 +762,7 @@ private: m_regex = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Commands/CommandObjectGUI.cpp b/source/Commands/CommandObjectGUI.cpp index 21ed510d1264..fac2e9627783 100644 --- a/source/Commands/CommandObjectGUI.cpp +++ b/source/Commands/CommandObjectGUI.cpp @@ -28,9 +28,10 @@ bool CommandObjectGUI::DoExecute(Args &args, CommandReturnObject &result) { if (args.GetArgumentCount() == 0) { Debugger &debugger = GetDebugger(); - lldb::StreamFileSP input_sp = debugger.GetInputFile(); - if (input_sp && input_sp->GetFile().GetIsRealTerminal() && - input_sp->GetFile().GetIsInteractive()) { + File &input = debugger.GetInputFile(); + File &output = debugger.GetOutputFile(); + if (input.GetStream() && output.GetStream() && input.GetIsRealTerminal() && + input.GetIsInteractive()) { IOHandlerSP io_handler_sp(new IOHandlerCursesGUI(debugger)); if (io_handler_sp) debugger.PushIOHandler(io_handler_sp); diff --git a/source/Commands/CommandObjectHelp.cpp b/source/Commands/CommandObjectHelp.cpp index ab557919d0a0..c02a583bf9df 100644 --- a/source/Commands/CommandObjectHelp.cpp +++ b/source/Commands/CommandObjectHelp.cpp @@ -65,10 +65,8 @@ CommandObjectHelp::CommandObjectHelp(CommandInterpreter &interpreter) CommandObjectHelp::~CommandObjectHelp() = default; -static constexpr OptionDefinition g_help_options[] = { #define LLDB_OPTIONS_help #include "CommandOptions.inc" -}; llvm::ArrayRef<OptionDefinition> CommandObjectHelp::CommandOptions::GetDefinitions() { @@ -98,7 +96,7 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) { // Get command object for the first command argument. Only search built-in // command dictionary. StringList matches; - auto command_name = command[0].ref; + auto command_name = command[0].ref(); cmd_obj = m_interpreter.GetCommandObject(command_name, &matches); if (cmd_obj != nullptr) { @@ -109,7 +107,7 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) { // object that corresponds to the help command entered. std::string sub_command; for (auto &entry : command.entries().drop_front()) { - sub_command = entry.ref; + sub_command = entry.ref(); matches.Clear(); if (sub_cmd_obj->IsAlias()) sub_cmd_obj = @@ -203,24 +201,23 @@ bool CommandObjectHelp::DoExecute(Args &command, CommandReturnObject &result) { return result.Succeeded(); } -int CommandObjectHelp::HandleCompletion(CompletionRequest &request) { +void CommandObjectHelp::HandleCompletion(CompletionRequest &request) { // Return the completions of the commands in the help system: if (request.GetCursorIndex() == 0) { - return m_interpreter.HandleCompletionMatches(request); - } else { - CommandObject *cmd_obj = - m_interpreter.GetCommandObject(request.GetParsedLine()[0].ref); + m_interpreter.HandleCompletionMatches(request); + return; + } + CommandObject *cmd_obj = + m_interpreter.GetCommandObject(request.GetParsedLine()[0].ref()); - // The command that they are getting help on might be ambiguous, in which - // case we should complete that, otherwise complete with the command the - // user is getting help on... + // The command that they are getting help on might be ambiguous, in which + // case we should complete that, otherwise complete with the command the + // user is getting help on... - if (cmd_obj) { - request.GetParsedLine().Shift(); - request.SetCursorIndex(request.GetCursorIndex() - 1); - return cmd_obj->HandleCompletion(request); - } else { - return m_interpreter.HandleCompletionMatches(request); - } + if (cmd_obj) { + request.ShiftArguments(); + cmd_obj->HandleCompletion(request); + return; } + m_interpreter.HandleCompletionMatches(request); } diff --git a/source/Commands/CommandObjectHelp.h b/source/Commands/CommandObjectHelp.h index a641b19a46d0..52a00ac79ff9 100644 --- a/source/Commands/CommandObjectHelp.h +++ b/source/Commands/CommandObjectHelp.h @@ -23,7 +23,7 @@ public: ~CommandObjectHelp() override; - int HandleCompletion(CompletionRequest &request) override; + void HandleCompletion(CompletionRequest &request) override; static void GenerateAdditionalHelpAvenuesMessage( Stream *s, llvm::StringRef command, llvm::StringRef prefix, @@ -52,9 +52,7 @@ public: m_show_hidden = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Commands/CommandObjectLog.cpp b/source/Commands/CommandObjectLog.cpp index 2ad61de1a3e9..31a876c3430e 100644 --- a/source/Commands/CommandObjectLog.cpp +++ b/source/Commands/CommandObjectLog.cpp @@ -31,20 +31,23 @@ using namespace lldb; using namespace lldb_private; -static constexpr OptionDefinition g_log_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFilename, "Set the destination file to log to." }, - { LLDB_OPT_SET_1, false, "threadsafe", 't', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable thread safe logging to avoid interweaved log lines." }, - { LLDB_OPT_SET_1, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable verbose logging." }, - { LLDB_OPT_SET_1, false, "sequence", 's', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend all log lines with an increasing integer sequence id." }, - { LLDB_OPT_SET_1, false, "timestamp", 'T', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend all log lines with a timestamp." }, - { LLDB_OPT_SET_1, false, "pid-tid", 'p', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend all log lines with the process and thread ID that generates the log line." }, - { LLDB_OPT_SET_1, false, "thread-name",'n', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend all log lines with the thread name for the thread that generates the log line." }, - { LLDB_OPT_SET_1, false, "stack", 'S', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append a stack backtrace to each log line." }, - { LLDB_OPT_SET_1, false, "append", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Append to the log file instead of overwriting." }, - { LLDB_OPT_SET_1, false, "file-function",'F',OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Prepend the names of files and function that generate the logs." }, - // clang-format on -}; +#define LLDB_OPTIONS_log +#include "CommandOptions.inc" + +/// Common completion logic for log enable/disable. +static void CompleteEnableDisable(CompletionRequest &request) { + size_t arg_index = request.GetCursorIndex(); + if (arg_index == 0) { // We got: log enable/disable x[tab] + for (llvm::StringRef channel : Log::ListChannels()) + request.TryCompleteCurrentArg(channel); + } else if (arg_index >= 1) { // We got: log enable/disable channel x[tab] + llvm::StringRef channel = request.GetParsedLine().GetArgumentAtIndex(0); + Log::ForEachChannelCategory( + channel, [&request](llvm::StringRef name, llvm::StringRef desc) { + request.TryCompleteCurrentArg(name, desc); + }); + } +} class CommandObjectLogEnable : public CommandObjectParsed { public: @@ -125,9 +128,7 @@ public: log_options |= LLDB_LOG_OPTION_PREPEND_FILE_FUNCTION; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -148,17 +149,24 @@ public: uint32_t log_options; }; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + CompleteEnableDisable(request); + } + protected: bool DoExecute(Args &args, CommandReturnObject &result) override { if (args.GetArgumentCount() < 2) { result.AppendErrorWithFormat( "%s takes a log channel and one or more log types.\n", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); return false; } // Store into a std::string since we're about to shift the channel off. - const std::string channel = args[0].ref; + const std::string channel = args[0].ref(); args.Shift(); // Shift off the channel char log_file[PATH_MAX]; if (m_options.log_file) @@ -215,16 +223,23 @@ public: ~CommandObjectLogDisable() override = default; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + CompleteEnableDisable(request); + } + protected: bool DoExecute(Args &args, CommandReturnObject &result) override { if (args.empty()) { result.AppendErrorWithFormat( "%s takes a log channel and one or more log types.\n", m_cmd_name.c_str()); + result.SetStatus(eReturnStatusFailed); return false; } - const std::string channel = args[0].ref; + const std::string channel = args[0].ref(); args.Shift(); // Shift off the channel if (channel == "all") { Log::DisableAllLogChannels(); @@ -266,6 +281,13 @@ public: ~CommandObjectLogList() override = default; + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { + for (llvm::StringRef channel : Log::ListChannels()) + request.TryCompleteCurrentArg(channel); + } + protected: bool DoExecute(Args &args, CommandReturnObject &result) override { std::string output; @@ -277,7 +299,7 @@ protected: bool success = true; for (const auto &entry : args.entries()) success = - success && Log::ListChannelCategories(entry.ref, output_stream); + success && Log::ListChannelCategories(entry.ref(), output_stream); if (success) result.SetStatus(eReturnStatusSuccessFinishResult); } @@ -303,7 +325,7 @@ protected: result.SetStatus(eReturnStatusFailed); if (args.GetArgumentCount() == 1) { - auto sub_command = args[0].ref; + auto sub_command = args[0].ref(); if (sub_command.equals_lower("enable")) { Timer::SetDisplayDepth(UINT32_MAX); @@ -320,8 +342,8 @@ protected: result.SetStatus(eReturnStatusSuccessFinishResult); } } else if (args.GetArgumentCount() == 2) { - auto sub_command = args[0].ref; - auto param = args[1].ref; + auto sub_command = args[0].ref(); + auto param = args[1].ref(); if (sub_command.equals_lower("enable")) { uint32_t depth; diff --git a/source/Commands/CommandObjectMemory.cpp b/source/Commands/CommandObjectMemory.cpp index 1afcac71318d..38bd3d179096 100644 --- a/source/Commands/CommandObjectMemory.cpp +++ b/source/Commands/CommandObjectMemory.cpp @@ -46,20 +46,8 @@ using namespace lldb; using namespace lldb_private; -static constexpr OptionDefinition g_read_memory_options[] = { - // clang-format off - {LLDB_OPT_SET_1, false, "num-per-line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNumberPerLine, "The number of items per line to display." }, - {LLDB_OPT_SET_2, false, "binary", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that " - "uses the format, size, count and number per line settings." }, - {LLDB_OPT_SET_3 | - LLDB_OPT_SET_4, true , "type", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "The name of a type to view memory as." }, - {LLDB_OPT_SET_4, false, "language", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "The language of the type to view memory as."}, - {LLDB_OPT_SET_3, false, "offset", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "How many elements of the specified type to skip before starting to display data." }, - {LLDB_OPT_SET_1 | - LLDB_OPT_SET_2 | - LLDB_OPT_SET_3, false, "force", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Necessary if reading over target.max-memory-read-size bytes." }, - // clang-format on -}; +#define LLDB_OPTIONS_memory_read +#include "CommandOptions.inc" class OptionGroupReadMemory : public OptionGroup { public: @@ -70,13 +58,13 @@ public: ~OptionGroupReadMemory() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_read_memory_options); + return llvm::makeArrayRef(g_memory_read_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, ExecutionContext *execution_context) override { Status error; - const int short_option = g_read_memory_options[option_idx].short_option; + const int short_option = g_memory_read_options[option_idx].short_option; switch (short_option) { case 'l': @@ -108,9 +96,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -175,6 +161,7 @@ public: case eFormatOctal: case eFormatDecimal: case eFormatEnum: + case eFormatUnicode8: case eFormatUnicode16: case eFormatUnicode32: case eFormatUnsigned: @@ -606,7 +593,7 @@ protected: } if (argc > 0) - addr = OptionArgParser::ToAddress(&m_exe_ctx, command[0].ref, + addr = OptionArgParser::ToAddress(&m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error); if (addr == LLDB_INVALID_ADDRESS) { @@ -618,7 +605,7 @@ protected: if (argc == 2) { lldb::addr_t end_addr = OptionArgParser::ToAddress( - &m_exe_ctx, command[1].ref, LLDB_INVALID_ADDRESS, nullptr); + &m_exe_ctx, command[1].ref(), LLDB_INVALID_ADDRESS, nullptr); if (end_addr == LLDB_INVALID_ADDRESS) { result.AppendError("invalid end address expression."); result.AppendError(error.AsCString()); @@ -778,26 +765,27 @@ protected: m_prev_varobj_options = m_varobj_options; m_prev_compiler_type = compiler_type; - StreamFile outfile_stream; - Stream *output_stream = nullptr; + std::unique_ptr<Stream> output_stream_storage; + Stream *output_stream_p = nullptr; const FileSpec &outfile_spec = m_outfile_options.GetFile().GetCurrentValue(); std::string path = outfile_spec.GetPath(); if (outfile_spec) { - uint32_t open_options = - File::eOpenOptionWrite | File::eOpenOptionCanCreate; + auto open_options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; const bool append = m_outfile_options.GetAppend().GetCurrentValue(); if (append) open_options |= File::eOpenOptionAppend; - Status error = FileSystem::Instance().Open(outfile_stream.GetFile(), - outfile_spec, open_options); - if (error.Success()) { + auto outfile = FileSystem::Instance().Open(outfile_spec, open_options); + + if (outfile) { + auto outfile_stream_up = + std::make_unique<StreamFile>(std::move(outfile.get())); if (m_memory_options.m_output_as_binary) { const size_t bytes_written = - outfile_stream.Write(data_sp->GetBytes(), bytes_read); + outfile_stream_up->Write(data_sp->GetBytes(), bytes_read); if (bytes_written > 0) { result.GetOutputStream().Printf( "%zi bytes %s to '%s'\n", bytes_written, @@ -813,16 +801,19 @@ protected: } else { // We are going to write ASCII to the file just point the // output_stream to our outfile_stream... - output_stream = &outfile_stream; + output_stream_storage = std::move(outfile_stream_up); + output_stream_p = output_stream_storage.get(); } } else { - result.AppendErrorWithFormat("Failed to open file '%s' for %s.\n", + result.AppendErrorWithFormat("Failed to open file '%s' for %s:\n", path.c_str(), append ? "append" : "write"); + + result.AppendError(llvm::toString(outfile.takeError())); result.SetStatus(eReturnStatusFailed); return false; } } else { - output_stream = &result.GetOutputStream(); + output_stream_p = &result.GetOutputStream(); } ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); @@ -842,7 +833,7 @@ protected: DumpValueObjectOptions options(m_varobj_options.GetAsDumpOptions( eLanguageRuntimeDescriptionDisplayVerbosityFull, format)); - valobj_sp->Dump(*output_stream, options); + valobj_sp->Dump(*output_stream_p, options); } else { result.AppendErrorWithFormat( "failed to create a value object for: (%s) %s\n", @@ -882,13 +873,13 @@ protected: } } - assert(output_stream); + assert(output_stream_p); size_t bytes_dumped = DumpDataExtractor( - data, output_stream, 0, format, item_byte_size, item_count, + data, output_stream_p, 0, format, item_byte_size, item_count, num_per_line / target->GetArchitecture().GetDataByteSize(), addr, 0, 0, exe_scope); m_next_addr = addr + bytes_dumped; - output_stream->EOL(); + output_stream_p->EOL(); return true; } @@ -906,14 +897,8 @@ protected: CompilerType m_prev_compiler_type; }; -static constexpr OptionDefinition g_memory_find_option_table[] = { - // clang-format off - {LLDB_OPT_SET_1, true, "expression", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeExpression, "Evaluate an expression to obtain a byte pattern."}, - {LLDB_OPT_SET_2, true, "string", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Use text to find a byte pattern."}, - {LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "How many times to perform the search."}, - {LLDB_OPT_SET_ALL, false, "dump-offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "When dumping memory for a match, an offset from the match location to start dumping from."}, - // clang-format on -}; +#define LLDB_OPTIONS_memory_find +#include "CommandOptions.inc" // Find the specified data in memory class CommandObjectMemoryFind : public CommandObjectParsed { @@ -925,14 +910,13 @@ public: ~OptionGroupFindMemory() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_memory_find_option_table); + return llvm::makeArrayRef(g_memory_find_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, ExecutionContext *execution_context) override { Status error; - const int short_option = - g_memory_find_option_table[option_idx].short_option; + const int short_option = g_memory_find_options[option_idx].short_option; switch (short_option) { case 'e': @@ -954,9 +938,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -1056,13 +1038,13 @@ protected: Status error; lldb::addr_t low_addr = OptionArgParser::ToAddress( - &m_exe_ctx, command[0].ref, LLDB_INVALID_ADDRESS, &error); + &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error); if (low_addr == LLDB_INVALID_ADDRESS || error.Fail()) { result.AppendError("invalid low address"); return false; } lldb::addr_t high_addr = OptionArgParser::ToAddress( - &m_exe_ctx, command[1].ref, LLDB_INVALID_ADDRESS, &error); + &m_exe_ctx, command[1].ref(), LLDB_INVALID_ADDRESS, &error); if (high_addr == LLDB_INVALID_ADDRESS || error.Fail()) { result.AppendError("invalid high address"); return false; @@ -1203,12 +1185,8 @@ protected: OptionGroupFindMemory m_memory_options; }; -static constexpr OptionDefinition g_memory_write_option_table[] = { - // clang-format off - {LLDB_OPT_SET_1, true, "infile", 'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFilename, "Write memory using the contents of a file."}, - {LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "Start writing bytes from an offset within the input file."}, - // clang-format on -}; +#define LLDB_OPTIONS_memory_write +#include "CommandOptions.inc" // Write memory to the inferior process class CommandObjectMemoryWrite : public CommandObjectParsed { @@ -1220,14 +1198,13 @@ public: ~OptionGroupWriteMemory() override = default; llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_memory_write_option_table); + return llvm::makeArrayRef(g_memory_write_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, ExecutionContext *execution_context) override { Status error; - const int short_option = - g_memory_write_option_table[option_idx].short_option; + const int short_option = g_memory_write_options[option_idx].short_option; switch (short_option) { case 'i': @@ -1249,9 +1226,7 @@ public: } break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -1368,7 +1343,7 @@ protected: Status error; lldb::addr_t addr = OptionArgParser::ToAddress( - &m_exe_ctx, command[0].ref, LLDB_INVALID_ADDRESS, &error); + &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error); if (addr == LLDB_INVALID_ADDRESS) { result.AppendError("invalid address expression\n"); @@ -1435,6 +1410,7 @@ protected: case eFormatBytesWithASCII: case eFormatComplex: case eFormatEnum: + case eFormatUnicode8: case eFormatUnicode16: case eFormatUnicode32: case eFormatVectorOfChar: @@ -1470,10 +1446,10 @@ protected: // Be careful, getAsInteger with a radix of 16 rejects "0xab" so we // have to special case that: bool success = false; - if (entry.ref.startswith("0x")) - success = !entry.ref.getAsInteger(0, uval64); + if (entry.ref().startswith("0x")) + success = !entry.ref().getAsInteger(0, uval64); if (!success) - success = !entry.ref.getAsInteger(16, uval64); + success = !entry.ref().getAsInteger(16, uval64); if (!success) { result.AppendErrorWithFormat( "'%s' is not a valid hex string value.\n", entry.c_str()); @@ -1491,7 +1467,7 @@ protected: break; } case eFormatBoolean: - uval64 = OptionArgParser::ToBoolean(entry.ref, false, &success); + uval64 = OptionArgParser::ToBoolean(entry.ref(), false, &success); if (!success) { result.AppendErrorWithFormat( "'%s' is not a valid boolean string value.\n", entry.c_str()); @@ -1502,7 +1478,7 @@ protected: break; case eFormatBinary: - if (entry.ref.getAsInteger(2, uval64)) { + if (entry.ref().getAsInteger(2, uval64)) { result.AppendErrorWithFormat( "'%s' is not a valid binary string value.\n", entry.c_str()); result.SetStatus(eReturnStatusFailed); @@ -1521,10 +1497,10 @@ protected: case eFormatCharArray: case eFormatChar: case eFormatCString: { - if (entry.ref.empty()) + if (entry.ref().empty()) break; - size_t len = entry.ref.size(); + size_t len = entry.ref().size(); // Include the NULL for C strings... if (m_format_options.GetFormat() == eFormatCString) ++len; @@ -1541,7 +1517,7 @@ protected: break; } case eFormatDecimal: - if (entry.ref.getAsInteger(0, sval64)) { + if (entry.ref().getAsInteger(0, sval64)) { result.AppendErrorWithFormat( "'%s' is not a valid signed decimal value.\n", entry.c_str()); result.SetStatus(eReturnStatusFailed); @@ -1559,7 +1535,7 @@ protected: case eFormatUnsigned: - if (!entry.ref.getAsInteger(0, uval64)) { + if (!entry.ref().getAsInteger(0, uval64)) { result.AppendErrorWithFormat( "'%s' is not a valid unsigned decimal string value.\n", entry.c_str()); @@ -1577,7 +1553,7 @@ protected: break; case eFormatOctal: - if (entry.ref.getAsInteger(8, uval64)) { + if (entry.ref().getAsInteger(8, uval64)) { result.AppendErrorWithFormat( "'%s' is not a valid octal string value.\n", entry.c_str()); result.SetStatus(eReturnStatusFailed); @@ -1663,7 +1639,7 @@ protected: Status error; lldb::addr_t addr = OptionArgParser::ToAddress( - &m_exe_ctx, command[0].ref, LLDB_INVALID_ADDRESS, &error); + &m_exe_ctx, command[0].ref(), LLDB_INVALID_ADDRESS, &error); if (addr == LLDB_INVALID_ADDRESS) { result.AppendError("invalid address expression"); @@ -1728,7 +1704,7 @@ protected: result.SetStatus(eReturnStatusFailed); } else { if (command.GetArgumentCount() == 1) { - auto load_addr_str = command[0].ref; + auto load_addr_str = command[0].ref(); load_addr = OptionArgParser::ToAddress(&m_exe_ctx, load_addr_str, LLDB_INVALID_ADDRESS, &error); if (error.Fail() || load_addr == LLDB_INVALID_ADDRESS) { diff --git a/source/Commands/CommandObjectMultiword.cpp b/source/Commands/CommandObjectMultiword.cpp index 4011cceb8a26..03a3770d8df7 100644 --- a/source/Commands/CommandObjectMultiword.cpp +++ b/source/Commands/CommandObjectMultiword.cpp @@ -93,9 +93,11 @@ bool CommandObjectMultiword::Execute(const char *args_string, return result.Succeeded(); } - auto sub_command = args[0].ref; - if (sub_command.empty()) + auto sub_command = args[0].ref(); + if (sub_command.empty()) { + result.AppendError("Need to specify a non-empty subcommand."); return result.Succeeded(); + } if (sub_command.equals_lower("help")) { this->CommandObject::GenerateHelpText(result); @@ -136,9 +138,9 @@ bool CommandObjectMultiword::Execute(const char *args_string, if (num_subcmd_matches > 0) { error_msg.append(" Possible completions:"); - for (size_t i = 0; i < matches.GetSize(); i++) { + for (const std::string &match : matches) { error_msg.append("\n\t"); - error_msg.append(matches.GetStringAtIndex(i)); + error_msg.append(match); } } error_msg.append("\n"); @@ -179,12 +181,8 @@ void CommandObjectMultiword::GenerateHelpText(Stream &output_stream) { "'help <command> <subcommand>'.\n"); } -int CommandObjectMultiword::HandleCompletion(CompletionRequest &request) { - // Any of the command matches will provide a complete word, otherwise the - // individual completers will override this. - request.SetWordComplete(true); - - auto arg0 = request.GetParsedLine()[0].ref; +void CommandObjectMultiword::HandleCompletion(CompletionRequest &request) { + auto arg0 = request.GetParsedLine()[0].ref(); if (request.GetCursorIndex() == 0) { StringList new_matches, descriptions; AddNamesMatchingPartialString(m_subcommand_dict, arg0, new_matches, @@ -197,32 +195,28 @@ int CommandObjectMultiword::HandleCompletion(CompletionRequest &request) { StringList temp_matches; CommandObject *cmd_obj = GetSubcommandObject(arg0, &temp_matches); if (cmd_obj != nullptr) { - if (request.GetParsedLine().GetArgumentCount() == 1) { - request.SetWordComplete(true); - } else { + if (request.GetParsedLine().GetArgumentCount() != 1) { request.GetParsedLine().Shift(); - request.SetCursorCharPosition(0); - request.GetParsedLine().AppendArgument(llvm::StringRef()); - return cmd_obj->HandleCompletion(request); + request.AppendEmptyArgument(); + cmd_obj->HandleCompletion(request); } } } - return new_matches.GetSize(); - } else { - StringList new_matches; - CommandObject *sub_command_object = GetSubcommandObject(arg0, &new_matches); - if (sub_command_object == nullptr) { - request.AddCompletions(new_matches); - return request.GetNumberOfMatches(); - } else { - // Remove the one match that we got from calling GetSubcommandObject. - new_matches.DeleteStringAtIndex(0); - request.AddCompletions(new_matches); - request.GetParsedLine().Shift(); - request.SetCursorIndex(request.GetCursorIndex() - 1); - return sub_command_object->HandleCompletion(request); - } + return; } + + StringList new_matches; + CommandObject *sub_command_object = GetSubcommandObject(arg0, &new_matches); + if (sub_command_object == nullptr) { + request.AddCompletions(new_matches); + return; + } + + // Remove the one match that we got from calling GetSubcommandObject. + new_matches.DeleteStringAtIndex(0); + request.AddCompletions(new_matches); + request.ShiftArguments(); + sub_command_object->HandleCompletion(request); } const char *CommandObjectMultiword::GetRepeatCommand(Args ¤t_command_args, @@ -231,7 +225,7 @@ const char *CommandObjectMultiword::GetRepeatCommand(Args ¤t_command_args, if (current_command_args.GetArgumentCount() <= index) return nullptr; CommandObject *sub_command_object = - GetSubcommandObject(current_command_args[index].ref); + GetSubcommandObject(current_command_args[index].ref()); if (sub_command_object == nullptr) return nullptr; return sub_command_object->GetRepeatCommand(current_command_args, index); @@ -360,19 +354,17 @@ Options *CommandObjectProxy::GetOptions() { return nullptr; } -int CommandObjectProxy::HandleCompletion(CompletionRequest &request) { +void CommandObjectProxy::HandleCompletion(CompletionRequest &request) { CommandObject *proxy_command = GetProxyCommandObject(); if (proxy_command) - return proxy_command->HandleCompletion(request); - return 0; + proxy_command->HandleCompletion(request); } -int CommandObjectProxy::HandleArgumentCompletion( +void CommandObjectProxy::HandleArgumentCompletion( CompletionRequest &request, OptionElementVector &opt_element_vector) { CommandObject *proxy_command = GetProxyCommandObject(); if (proxy_command) - return proxy_command->HandleArgumentCompletion(request, opt_element_vector); - return 0; + proxy_command->HandleArgumentCompletion(request, opt_element_vector); } const char *CommandObjectProxy::GetRepeatCommand(Args ¤t_command_args, diff --git a/source/Commands/CommandObjectPlatform.cpp b/source/Commands/CommandObjectPlatform.cpp index 53549cdeee32..fbd13aa37bda 100644 --- a/source/Commands/CommandObjectPlatform.cpp +++ b/source/Commands/CommandObjectPlatform.cpp @@ -58,21 +58,8 @@ static mode_t ParsePermissionString(llvm::StringRef permissions) { return user | group | world; } -static constexpr OptionDefinition g_permissions_options[] = { - // clang-format off - {LLDB_OPT_SET_ALL, false, "permissions-value", 'v', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePermissionsNumber, "Give out the numeric value for permissions (e.g. 757)"}, - {LLDB_OPT_SET_ALL, false, "permissions-string", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePermissionsString, "Give out the string value for permissions (e.g. rwxr-xr--)."}, - {LLDB_OPT_SET_ALL, false, "user-read", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to read."}, - {LLDB_OPT_SET_ALL, false, "user-write", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to write."}, - {LLDB_OPT_SET_ALL, false, "user-exec", 'x', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow user to execute."}, - {LLDB_OPT_SET_ALL, false, "group-read", 'R', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to read."}, - {LLDB_OPT_SET_ALL, false, "group-write", 'W', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to write."}, - {LLDB_OPT_SET_ALL, false, "group-exec", 'X', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow group to execute."}, - {LLDB_OPT_SET_ALL, false, "world-read", 'd', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to read."}, - {LLDB_OPT_SET_ALL, false, "world-write", 't', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to write."}, - {LLDB_OPT_SET_ALL, false, "world-exec", 'e', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Allow world to execute."}, - // clang-format on -}; +#define LLDB_OPTIONS_permissions +#include "CommandOptions.inc" class OptionPermissions : public OptionGroup { public: @@ -130,8 +117,7 @@ public: m_permissions |= lldb::eFilePermissionsWorldExecute; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -171,10 +157,9 @@ public: ~CommandObjectPlatformSelect() override = default; - int HandleCompletion(CompletionRequest &request) override { + void HandleCompletion(CompletionRequest &request) override { CommandCompletions::PlatformPluginNames(GetCommandInterpreter(), request, nullptr); - return request.GetNumberOfMatches(); } Options *GetOptions() override { return &m_option_group; } @@ -585,12 +570,8 @@ public: // "platform fread" -static constexpr OptionDefinition g_platform_fread_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeIndex, "Offset into the file at which to start reading." }, - { LLDB_OPT_SET_1, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "Number of bytes to read from the file." }, - // clang-format on -}; +#define LLDB_OPTIONS_platform_fread +#include "CommandOptions.inc" class CommandObjectPlatformFRead : public CommandObjectParsed { public: @@ -650,9 +631,7 @@ protected: option_arg.str().c_str()); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -678,12 +657,8 @@ protected: // "platform fwrite" -static constexpr OptionDefinition g_platform_fwrite_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeIndex, "Offset into the file at which to start reading." }, - { LLDB_OPT_SET_1, false, "data", 'd', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeValue, "Text to write to the file." }, - // clang-format on -}; +#define LLDB_OPTIONS_platform_fwrite +#include "CommandOptions.inc" class CommandObjectPlatformFWrite : public CommandObjectParsed { public: @@ -740,9 +715,7 @@ protected: m_data.assign(option_arg); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1056,24 +1029,9 @@ protected: // "platform process list" -static OptionDefinition g_platform_process_list_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "List the process info for a specific process ID." }, - { LLDB_OPT_SET_2, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that match a string." }, - { LLDB_OPT_SET_3, true, "ends-with", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that end with a string." }, - { LLDB_OPT_SET_4, true, "starts-with", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that start with a string." }, - { LLDB_OPT_SET_5, true, "contains", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "Find processes with executable basenames that contain a string." }, - { LLDB_OPT_SET_6, true, "regex", 'r', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeRegularExpression, "Find processes with executable basenames that match a regular expression." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "parent", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "Find processes that have a matching parent process ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "uid", 'u', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching user ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "euid", 'U', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective user ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "gid", 'g', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching group ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "egid", 'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Find processes that have a matching effective group ID." }, - { LLDB_OPT_SET_FROM_TO(2, 6), false, "arch", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeArchitecture, "Find processes that have a matching architecture." }, - { LLDB_OPT_SET_FROM_TO(1, 6), false, "show-args", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show process arguments instead of the process executable basename." }, - { LLDB_OPT_SET_FROM_TO(1, 6), false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable verbose output." }, - // clang-format on -}; +static PosixPlatformCommandOptionValidator posix_validator; +#define LLDB_OPTIONS_platform_process_list +#include "CommandOptions.inc" class CommandObjectPlatformProcessList : public CommandObjectParsed { public: @@ -1195,23 +1153,6 @@ protected: public: CommandOptions() : Options(), match_info(), show_args(false), verbose(false) { - static llvm::once_flag g_once_flag; - llvm::call_once(g_once_flag, []() { - PosixPlatformCommandOptionValidator *posix_validator = - new PosixPlatformCommandOptionValidator(); - for (auto &Option : g_platform_process_list_options) { - switch (Option.short_option) { - case 'u': - case 'U': - case 'g': - case 'G': - Option.validator = posix_validator; - break; - default: - break; - } - } - }); } ~CommandOptions() override = default; @@ -1323,10 +1264,12 @@ protected: verbose = true; break; - default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); + case 'x': + match_info.SetMatchAllUsers(true); break; + + default: + llvm_unreachable("Unimplemented option"); } return error; @@ -1397,9 +1340,9 @@ protected: Stream &ostrm = result.GetOutputStream(); for (auto &entry : args.entries()) { lldb::pid_t pid; - if (entry.ref.getAsInteger(0, pid)) { + if (entry.ref().getAsInteger(0, pid)) { result.AppendErrorWithFormat("invalid process ID argument '%s'", - entry.ref.str().c_str()); + entry.ref().str().c_str()); result.SetStatus(eReturnStatusFailed); break; } else { @@ -1436,14 +1379,8 @@ protected: } }; -static constexpr OptionDefinition g_platform_process_attach_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, - { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "The process ID of an existing process to attach to." }, - { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "The name of the process to attach to." }, - { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Wait for the process with <process-name> to launch." }, - // clang-format on -}; +#define LLDB_OPTIONS_platform_process_attach +#include "CommandOptions.inc" class CommandObjectPlatformProcessAttach : public CommandObjectParsed { public: @@ -1486,9 +1423,7 @@ public: break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -1501,7 +1436,7 @@ public: return llvm::makeArrayRef(g_platform_process_attach_options); } - bool HandleOptionArgumentCompletion( + void HandleOptionArgumentCompletion( CompletionRequest &request, OptionElementVector &opt_element_vector, int opt_element_index, CommandInterpreter &interpreter) override { int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; @@ -1509,37 +1444,36 @@ public: // We are only completing the name option for now... - if (GetDefinitions()[opt_defs_index].short_option == 'n') { - // Are we in the name? + // Are we in the name? + if (GetDefinitions()[opt_defs_index].short_option != 'n') + return; - // Look to see if there is a -P argument provided, and if so use that - // plugin, otherwise use the default plugin. + // Look to see if there is a -P argument provided, and if so use that + // plugin, otherwise use the default plugin. - const char *partial_name = nullptr; - partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos); + const char *partial_name = nullptr; + partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos); - PlatformSP platform_sp(interpreter.GetPlatform(true)); - if (platform_sp) { - ProcessInstanceInfoList process_infos; - ProcessInstanceInfoMatch match_info; - if (partial_name) { - match_info.GetProcessInfo().GetExecutableFile().SetFile( - partial_name, FileSpec::Style::native); - match_info.SetNameMatchType(NameMatch::StartsWith); - } - platform_sp->FindProcesses(match_info, process_infos); - const uint32_t num_matches = process_infos.GetSize(); - if (num_matches > 0) { - for (uint32_t i = 0; i < num_matches; ++i) { - request.AddCompletion(llvm::StringRef( - process_infos.GetProcessNameAtIndex(i), - process_infos.GetProcessNameLengthAtIndex(i))); - } - } - } + PlatformSP platform_sp(interpreter.GetPlatform(true)); + if (!platform_sp) + return; + + ProcessInstanceInfoList process_infos; + ProcessInstanceInfoMatch match_info; + if (partial_name) { + match_info.GetProcessInfo().GetExecutableFile().SetFile( + partial_name, FileSpec::Style::native); + match_info.SetNameMatchType(NameMatch::StartsWith); } + platform_sp->FindProcesses(match_info, process_infos); + const uint32_t num_matches = process_infos.GetSize(); + if (num_matches == 0) + return; - return false; + for (uint32_t i = 0; i < num_matches; ++i) { + request.AddCompletion(process_infos.GetProcessNameAtIndex(i)); + } + return; } // Options table: Required for subclasses of Options. @@ -1615,11 +1549,8 @@ private: }; // "platform shell" -static constexpr OptionDefinition g_platform_shell_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "timeout", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeValue, "Seconds to wait for the remote host to finish running the command." }, - // clang-format on -}; +#define LLDB_OPTIONS_platform_shell +#include "CommandOptions.inc" class CommandObjectPlatformShell : public CommandObjectRaw { public: @@ -1650,9 +1581,7 @@ public: timeout = std::chrono::seconds(timeout_sec); break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Commands/CommandObjectPlugin.cpp b/source/Commands/CommandObjectPlugin.cpp index 89e01ba52027..b70885061385 100644 --- a/source/Commands/CommandObjectPlugin.cpp +++ b/source/Commands/CommandObjectPlugin.cpp @@ -37,13 +37,12 @@ public: ~CommandObjectPluginLoad() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } protected: @@ -58,7 +57,7 @@ protected: Status error; - FileSpec dylib_fspec(command[0].ref); + FileSpec dylib_fspec(command[0].ref()); FileSystem::Instance().Resolve(dylib_fspec); if (GetDebugger().LoadPlugin(dylib_fspec, error)) diff --git a/source/Commands/CommandObjectProcess.cpp b/source/Commands/CommandObjectProcess.cpp index b20a2d533332..e5aa78afabb3 100644 --- a/source/Commands/CommandObjectProcess.cpp +++ b/source/Commands/CommandObjectProcess.cpp @@ -127,14 +127,13 @@ public: ~CommandObjectProcessLaunch() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } Options *GetOptions() override { return &m_options; } @@ -255,16 +254,8 @@ protected: ProcessLaunchCommandOptions m_options; }; -static constexpr OptionDefinition g_process_attach_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "continue", 'c', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Immediately continue the process once attached." }, - { LLDB_OPT_SET_ALL, false, "plugin", 'P', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, - { LLDB_OPT_SET_1, false, "pid", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePid, "The process ID of an existing process to attach to." }, - { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeProcessName, "The name of the process to attach to." }, - { LLDB_OPT_SET_2, false, "include-existing", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Include existing processes when doing attach -w." }, - { LLDB_OPT_SET_2, false, "waitfor", 'w', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Wait for the process with <process-name> to launch." }, - // clang-format on -}; +#define LLDB_OPTIONS_process_attach +#include "CommandOptions.inc" #pragma mark CommandObjectProcessAttach class CommandObjectProcessAttach : public CommandObjectProcessLaunchOrAttach { @@ -316,9 +307,7 @@ public: break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -331,7 +320,7 @@ public: return llvm::makeArrayRef(g_process_attach_options); } - bool HandleOptionArgumentCompletion( + void HandleOptionArgumentCompletion( CompletionRequest &request, OptionElementVector &opt_element_vector, int opt_element_index, CommandInterpreter &interpreter) override { int opt_arg_pos = opt_element_vector[opt_element_index].opt_arg_pos; @@ -339,37 +328,33 @@ public: // We are only completing the name option for now... - if (GetDefinitions()[opt_defs_index].short_option == 'n') { - // Are we in the name? - - // Look to see if there is a -P argument provided, and if so use that - // plugin, otherwise use the default plugin. - - const char *partial_name = nullptr; - partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos); - - PlatformSP platform_sp(interpreter.GetPlatform(true)); - if (platform_sp) { - ProcessInstanceInfoList process_infos; - ProcessInstanceInfoMatch match_info; - if (partial_name) { - match_info.GetProcessInfo().GetExecutableFile().SetFile( - partial_name, FileSpec::Style::native); - match_info.SetNameMatchType(NameMatch::StartsWith); - } - platform_sp->FindProcesses(match_info, process_infos); - const size_t num_matches = process_infos.GetSize(); - if (num_matches > 0) { - for (size_t i = 0; i < num_matches; ++i) { - request.AddCompletion(llvm::StringRef( - process_infos.GetProcessNameAtIndex(i), - process_infos.GetProcessNameLengthAtIndex(i))); - } - } - } + // Are we in the name? + if (GetDefinitions()[opt_defs_index].short_option != 'n') + return; + + // Look to see if there is a -P argument provided, and if so use that + // plugin, otherwise use the default plugin. + + const char *partial_name = nullptr; + partial_name = request.GetParsedLine().GetArgumentAtIndex(opt_arg_pos); + + PlatformSP platform_sp(interpreter.GetPlatform(true)); + if (!platform_sp) + return; + ProcessInstanceInfoList process_infos; + ProcessInstanceInfoMatch match_info; + if (partial_name) { + match_info.GetProcessInfo().GetExecutableFile().SetFile( + partial_name, FileSpec::Style::native); + match_info.SetNameMatchType(NameMatch::StartsWith); + } + platform_sp->FindProcesses(match_info, process_infos); + const size_t num_matches = process_infos.GetSize(); + if (num_matches == 0) + return; + for (size_t i = 0; i < num_matches; ++i) { + request.AddCompletion(process_infos.GetProcessNameAtIndex(i)); } - - return false; } // Instance variables to hold the values for command options. @@ -444,7 +429,6 @@ protected: result.AppendMessage(stream.GetString()); result.SetStatus(eReturnStatusSuccessFinishNoResult); result.SetDidChangeProcessState(true); - result.SetAbnormalStopWasExpected(true); } else { result.AppendError( "no error returned from Target::Attach, and target has no process"); @@ -505,11 +489,8 @@ protected: // CommandObjectProcessContinue -static constexpr OptionDefinition g_process_continue_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "ignore-count",'i', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeUnsignedInteger, "Ignore <N> crossings of the breakpoint (if it exists) for the currently selected thread." } - // clang-format on -}; +#define LLDB_OPTIONS_process_continue +#include "CommandOptions.inc" #pragma mark CommandObjectProcessContinue @@ -550,9 +531,7 @@ protected: break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -666,11 +645,8 @@ protected: }; // CommandObjectProcessDetach -static constexpr OptionDefinition g_process_detach_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "keep-stopped", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the process should be kept stopped on detach (if possible)." }, - // clang-format on -}; +#define LLDB_OPTIONS_process_detach +#include "CommandOptions.inc" #pragma mark CommandObjectProcessDetach @@ -703,9 +679,7 @@ public: } break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -762,12 +736,8 @@ protected: }; // CommandObjectProcessConnect - -static constexpr OptionDefinition g_process_connect_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "plugin", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypePlugin, "Name of the process plugin you want to use." }, - // clang-format on -}; +#define LLDB_OPTIONS_process_connect +#include "CommandOptions.inc" #pragma mark CommandObjectProcessConnect @@ -794,9 +764,7 @@ public: break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -887,12 +855,8 @@ public: }; // CommandObjectProcessLoad - -static constexpr OptionDefinition g_process_load_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "install", 'i', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypePath, "Install the shared library to the target. If specified without an argument then the library will installed in the current working directory." }, - // clang-format on -}; +#define LLDB_OPTIONS_process_load +#include "CommandOptions.inc" #pragma mark CommandObjectProcessLoad @@ -919,9 +883,7 @@ public: install_path.SetFile(option_arg, FileSpec::Style::native); break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -960,7 +922,7 @@ protected: for (auto &entry : command.entries()) { Status error; PlatformSP platform = process->GetTarget().GetPlatform(); - llvm::StringRef image_path = entry.ref; + llvm::StringRef image_path = entry.ref(); uint32_t image_token = LLDB_INVALID_IMAGE_TOKEN; if (!m_options.do_install) { @@ -1022,9 +984,9 @@ protected: for (auto &entry : command.entries()) { uint32_t image_token; - if (entry.ref.getAsInteger(0, image_token)) { + if (entry.ref().getAsInteger(0, image_token)) { result.AppendErrorWithFormat("invalid image index argument '%s'", - entry.ref.str().c_str()); + entry.ref().str().c_str()); result.SetStatus(eReturnStatusFailed); break; } else { @@ -1271,14 +1233,8 @@ public: }; // CommandObjectProcessHandle - -static constexpr OptionDefinition g_process_handle_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "stop", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the process should be stopped if the signal is received." }, - { LLDB_OPT_SET_1, false, "notify", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the debugger should notify the user if the signal is received." }, - { LLDB_OPT_SET_1, false, "pass", 'p', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "Whether or not the signal should be passed to the process." } - // clang-format on -}; +#define LLDB_OPTIONS_process_handle +#include "CommandOptions.inc" #pragma mark CommandObjectProcessHandle @@ -1306,9 +1262,7 @@ public: pass = option_arg; break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -1335,7 +1289,7 @@ public: "Manage LLDB handling of OS signals for the " "current target process. Defaults to showing " "current policy.", - nullptr), + nullptr, eCommandRequiresTarget), m_options() { SetHelpLong("\nIf no signals are specified, update them all. If no update " "option is specified, list the current values."); @@ -1420,15 +1374,7 @@ public: protected: bool DoExecute(Args &signal_args, CommandReturnObject &result) override { - TargetSP target_sp = GetDebugger().GetSelectedTarget(); - - if (!target_sp) { - result.AppendError("No current target;" - " cannot handle signals until you have a valid target " - "and process.\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target_sp = &GetSelectedTarget(); ProcessSP process_sp = target_sp->GetProcessSP(); diff --git a/source/Commands/CommandObjectRegister.cpp b/source/Commands/CommandObjectRegister.cpp index 34482a8b1e4f..13266f8fce35 100644 --- a/source/Commands/CommandObjectRegister.cpp +++ b/source/Commands/CommandObjectRegister.cpp @@ -32,14 +32,8 @@ using namespace lldb; using namespace lldb_private; // "register read" - -static constexpr OptionDefinition g_register_read_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "alternate", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display register names using the alternate register name if there is one." }, - { LLDB_OPT_SET_1, false, "set", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeIndex, "Specify which register sets to dump by index." }, - { LLDB_OPT_SET_2, false, "all", 'a', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show all register sets." }, - // clang-format on -}; +#define LLDB_OPTIONS_register_read +#include "CommandOptions.inc" class CommandObjectRegisterRead : public CommandObjectParsed { public: @@ -212,7 +206,7 @@ protected: // consistent towards the user and allow them to say reg read $rbx - // internally, however, we should be strict and not allow ourselves // to call our registers $rbx in our own API - auto arg_str = entry.ref; + auto arg_str = entry.ref(); arg_str.consume_front("$"); reg_info = reg_ctx->GetRegisterInfoByName(arg_str); @@ -278,9 +272,7 @@ protected: break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -343,8 +335,8 @@ protected: "register write takes exactly 2 arguments: <reg-name> <value>"); result.SetStatus(eReturnStatusFailed); } else { - auto reg_name = command[0].ref; - auto value_str = command[1].ref; + auto reg_name = command[0].ref(); + auto value_str = command[1].ref(); // in most LLDB commands we accept $rbx as the name for register RBX - // and here we would reject it and non-existant. we should be more diff --git a/source/Commands/CommandObjectReproducer.cpp b/source/Commands/CommandObjectReproducer.cpp index 4b0e9e36d202..dc4579c20fc2 100644 --- a/source/Commands/CommandObjectReproducer.cpp +++ b/source/Commands/CommandObjectReproducer.cpp @@ -8,6 +8,8 @@ #include "CommandObjectReproducer.h" +#include "lldb/Host/OptionParser.h" +#include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/Reproducer.h" #include "lldb/Interpreter/CommandInterpreter.h" @@ -16,7 +18,58 @@ #include "lldb/Interpreter/OptionGroupBoolean.h" using namespace lldb; +using namespace llvm; using namespace lldb_private; +using namespace lldb_private::repro; + +enum ReproducerProvider { + eReproducerProviderCommands, + eReproducerProviderFiles, + eReproducerProviderGDB, + eReproducerProviderVersion, + eReproducerProviderWorkingDirectory, + eReproducerProviderNone +}; + +static constexpr OptionEnumValueElement g_reproducer_provider_type[] = { + { + eReproducerProviderCommands, + "commands", + "Command Interpreter Commands", + }, + { + eReproducerProviderFiles, + "files", + "Files", + }, + { + eReproducerProviderGDB, + "gdb", + "GDB Remote Packets", + }, + { + eReproducerProviderVersion, + "version", + "Version", + }, + { + eReproducerProviderWorkingDirectory, + "cwd", + "Working Directory", + }, + { + eReproducerProviderNone, + "none", + "None", + }, +}; + +static constexpr OptionEnumValues ReproducerProviderType() { + return OptionEnumValues(g_reproducer_provider_type); +} + +#define LLDB_OPTIONS_reproducer +#include "CommandOptions.inc" class CommandObjectReproducerGenerate : public CommandObjectParsed { public: @@ -38,10 +91,10 @@ protected: return false; } - auto &r = repro::Reproducer::Instance(); + auto &r = Reproducer::Instance(); if (auto generator = r.GetGenerator()) { generator->Keep(); - } else if (r.GetLoader()) { + } else if (r.IsReplaying()) { // Make this operation a NOP in replay mode. result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); @@ -84,10 +137,10 @@ protected: return false; } - auto &r = repro::Reproducer::Instance(); - if (r.GetGenerator()) { + auto &r = Reproducer::Instance(); + if (r.IsCapturing()) { result.GetOutputStream() << "Reproducer is in capture mode.\n"; - } else if (r.GetLoader()) { + } else if (r.IsReplaying()) { result.GetOutputStream() << "Reproducer is in replay mode.\n"; } else { result.GetOutputStream() << "Reproducer is off.\n"; @@ -98,17 +151,235 @@ protected: } }; +static void SetError(CommandReturnObject &result, Error err) { + result.GetErrorStream().Printf("error: %s\n", + toString(std::move(err)).c_str()); + result.SetStatus(eReturnStatusFailed); +} + +class CommandObjectReproducerDump : public CommandObjectParsed { +public: + CommandObjectReproducerDump(CommandInterpreter &interpreter) + : CommandObjectParsed(interpreter, "reproducer dump", + "Dump the information contained in a reproducer. " + "If no reproducer is specified during replay, it " + "dumps the content of the current reproducer.", + nullptr) {} + + ~CommandObjectReproducerDump() override = default; + + Options *GetOptions() override { return &m_options; } + + class CommandOptions : public Options { + public: + CommandOptions() : Options(), file() {} + + ~CommandOptions() override = default; + + Status SetOptionValue(uint32_t option_idx, StringRef option_arg, + ExecutionContext *execution_context) override { + Status error; + const int short_option = m_getopt_table[option_idx].val; + + switch (short_option) { + case 'f': + file.SetFile(option_arg, FileSpec::Style::native); + FileSystem::Instance().Resolve(file); + break; + case 'p': + provider = (ReproducerProvider)OptionArgParser::ToOptionEnum( + option_arg, GetDefinitions()[option_idx].enum_values, 0, error); + if (!error.Success()) + error.SetErrorStringWithFormat("unrecognized value for provider '%s'", + option_arg.str().c_str()); + break; + default: + llvm_unreachable("Unimplemented option"); + } + + return error; + } + + void OptionParsingStarting(ExecutionContext *execution_context) override { + file.Clear(); + provider = eReproducerProviderNone; + } + + ArrayRef<OptionDefinition> GetDefinitions() override { + return makeArrayRef(g_reproducer_options); + } + + FileSpec file; + ReproducerProvider provider = eReproducerProviderNone; + }; + +protected: + bool DoExecute(Args &command, CommandReturnObject &result) override { + if (!command.empty()) { + result.AppendErrorWithFormat("'%s' takes no arguments", + m_cmd_name.c_str()); + return false; + } + + // If no reproducer path is specified, use the loader currently used for + // replay. Otherwise create a new loader just for dumping. + llvm::Optional<Loader> loader_storage; + Loader *loader = nullptr; + if (!m_options.file) { + loader = Reproducer::Instance().GetLoader(); + if (loader == nullptr) { + result.SetError( + "Not specifying a reproducer is only support during replay."); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return false; + } + } else { + loader_storage.emplace(m_options.file); + loader = &(*loader_storage); + if (Error err = loader->LoadIndex()) { + SetError(result, std::move(err)); + return false; + } + } + + // If we get here we should have a valid loader. + assert(loader); + + switch (m_options.provider) { + case eReproducerProviderFiles: { + FileSpec vfs_mapping = loader->GetFile<FileProvider::Info>(); + + // Read the VFS mapping. + ErrorOr<std::unique_ptr<MemoryBuffer>> buffer = + vfs::getRealFileSystem()->getBufferForFile(vfs_mapping.GetPath()); + if (!buffer) { + SetError(result, errorCodeToError(buffer.getError())); + return false; + } + + // Initialize a VFS from the given mapping. + IntrusiveRefCntPtr<vfs::FileSystem> vfs = vfs::getVFSFromYAML( + std::move(buffer.get()), nullptr, vfs_mapping.GetPath()); + + // Dump the VFS to a buffer. + std::string str; + raw_string_ostream os(str); + static_cast<vfs::RedirectingFileSystem &>(*vfs).dump(os); + os.flush(); + + // Return the string. + result.AppendMessage(str); + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + case eReproducerProviderVersion: { + Expected<std::string> version = loader->LoadBuffer<VersionProvider>(); + if (!version) { + SetError(result, version.takeError()); + return false; + } + result.AppendMessage(*version); + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + case eReproducerProviderWorkingDirectory: { + Expected<std::string> cwd = + loader->LoadBuffer<WorkingDirectoryProvider>(); + if (!cwd) { + SetError(result, cwd.takeError()); + return false; + } + result.AppendMessage(*cwd); + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + case eReproducerProviderCommands: { + // Create a new command loader. + std::unique_ptr<repro::CommandLoader> command_loader = + repro::CommandLoader::Create(loader); + if (!command_loader) { + SetError(result, + make_error<StringError>(llvm::inconvertibleErrorCode(), + "Unable to create command loader.")); + return false; + } + + // Iterate over the command files and dump them. + while (true) { + llvm::Optional<std::string> command_file = + command_loader->GetNextFile(); + if (!command_file) + break; + + auto command_buffer = llvm::MemoryBuffer::getFile(*command_file); + if (auto err = command_buffer.getError()) { + SetError(result, errorCodeToError(err)); + return false; + } + result.AppendMessage((*command_buffer)->getBuffer()); + } + + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + case eReproducerProviderGDB: { + FileSpec gdb_file = loader->GetFile<ProcessGDBRemoteProvider::Info>(); + auto error_or_file = MemoryBuffer::getFile(gdb_file.GetPath()); + if (auto err = error_or_file.getError()) { + SetError(result, errorCodeToError(err)); + return false; + } + + std::vector<GDBRemotePacket> packets; + yaml::Input yin((*error_or_file)->getBuffer()); + yin >> packets; + + if (auto err = yin.error()) { + SetError(result, errorCodeToError(err)); + return false; + } + + for (GDBRemotePacket &packet : packets) { + packet.Dump(result.GetOutputStream()); + } + + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; + } + case eReproducerProviderNone: + result.SetError("No valid provider specified."); + return false; + } + + result.SetStatus(eReturnStatusSuccessFinishNoResult); + return result.Succeeded(); + } + +private: + CommandOptions m_options; +}; + CommandObjectReproducer::CommandObjectReproducer( CommandInterpreter &interpreter) : CommandObjectMultiword( interpreter, "reproducer", - "Commands to inspect and manipulate the reproducer functionality.", - "log <subcommand> [<command-options>]") { + "Commands for manipulating reproducers. Reproducers make it possible " + "to capture full debug sessions with all its dependencies. The " + "resulting reproducer is used to replay the debug session while " + "debugging the debugger.\n" + "Because reproducers need the whole the debug session from " + "beginning to end, you need to launch the debugger in capture or " + "replay mode, commonly though the command line driver.\n" + "Reproducers are unrelated record-replay debugging, as you cannot " + "interact with the debugger during replay.\n", + "reproducer <subcommand> [<subcommand-options>]") { LoadSubCommand( "generate", CommandObjectSP(new CommandObjectReproducerGenerate(interpreter))); LoadSubCommand("status", CommandObjectSP( new CommandObjectReproducerStatus(interpreter))); + LoadSubCommand("dump", + CommandObjectSP(new CommandObjectReproducerDump(interpreter))); } CommandObjectReproducer::~CommandObjectReproducer() = default; diff --git a/source/Commands/CommandObjectSettings.cpp b/source/Commands/CommandObjectSettings.cpp index 55a0002c5997..248a04613d7a 100644 --- a/source/Commands/CommandObjectSettings.cpp +++ b/source/Commands/CommandObjectSettings.cpp @@ -20,11 +20,8 @@ using namespace lldb; using namespace lldb_private; // CommandObjectSettingsSet - -static constexpr OptionDefinition g_settings_set_options[] = { #define LLDB_OPTIONS_settings_set #include "CommandOptions.inc" -}; class CommandObjectSettingsSet : public CommandObjectRaw { public: @@ -107,9 +104,7 @@ insert-before or insert-after."); m_global = true; break; default: - error.SetErrorStringWithFormat("unrecognized options '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -129,15 +124,14 @@ insert-before or insert-after."); bool m_force; }; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { const size_t argc = request.GetParsedLine().GetArgumentCount(); const char *arg = nullptr; - int setting_var_idx; - for (setting_var_idx = 0; setting_var_idx < static_cast<int>(argc); - ++setting_var_idx) { + size_t setting_var_idx; + for (setting_var_idx = 0; setting_var_idx < argc; ++setting_var_idx) { arg = request.GetParsedLine().GetArgumentAtIndex(setting_var_idx); if (arg && arg[0] != '-') break; // We found our setting variable name index @@ -147,27 +141,27 @@ insert-before or insert-after."); CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - } else { + return; + } arg = request.GetParsedLine().GetArgumentAtIndex(request.GetCursorIndex()); - if (arg) { - if (arg[0] == '-') { - // Complete option name - } else { - // Complete setting value - const char *setting_var_name = - request.GetParsedLine().GetArgumentAtIndex(setting_var_idx); - Status error; - lldb::OptionValueSP value_sp(GetDebugger().GetPropertyValue( - &m_exe_ctx, setting_var_name, false, error)); - if (value_sp) { - value_sp->AutoComplete(m_interpreter, request); - } - } - } - } - return request.GetNumberOfMatches(); + if (!arg) + return; + + // Complete option name + if (arg[0] != '-') + return; + + // Complete setting value + const char *setting_var_name = + request.GetParsedLine().GetArgumentAtIndex(setting_var_idx); + Status error; + lldb::OptionValueSP value_sp(GetDebugger().GetPropertyValue( + &m_exe_ctx, setting_var_name, false, error)); + if (!value_sp) + return; + value_sp->AutoComplete(m_interpreter, request); } protected: @@ -210,16 +204,13 @@ protected: } // Split the raw command into var_name and value pair. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = - Args::StripSpaces(var_value_string, true, false, false); + llvm::StringRef var_value(command); + var_value = var_value.split(var_name).second.ltrim(); Status error; - if (m_options.m_global) { + if (m_options.m_global) error = GetDebugger().SetPropertyValue(nullptr, eVarSetOperationAssign, - var_name, var_value_cstr); - } + var_name, var_value); if (error.Success()) { // FIXME this is the same issue as the one in commands script import @@ -230,7 +221,7 @@ protected: ExecutionContext exe_ctx(m_exe_ctx); m_exe_ctx.Clear(); error = GetDebugger().SetPropertyValue(&exe_ctx, eVarSetOperationAssign, - var_name, var_value_cstr); + var_name, var_value); } if (error.Fail()) { @@ -274,13 +265,12 @@ public: ~CommandObjectSettingsShow() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - return request.GetNumberOfMatches(); } protected: @@ -290,7 +280,7 @@ protected: if (!args.empty()) { for (const auto &arg : args) { Status error(GetDebugger().DumpPropertyValue( - &m_exe_ctx, result.GetOutputStream(), arg.ref, + &m_exe_ctx, result.GetOutputStream(), arg.ref(), OptionValue::eDumpGroupValue)); if (error.Success()) { result.GetOutputStream().EOL(); @@ -309,11 +299,8 @@ protected: }; // CommandObjectSettingsWrite -- Write settings to file - -static constexpr OptionDefinition g_settings_write_options[] = { #define LLDB_OPTIONS_settings_write #include "CommandOptions.inc" -}; class CommandObjectSettingsWrite : public CommandObjectParsed { public: @@ -363,9 +350,7 @@ public: m_append = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -390,12 +375,11 @@ protected: FileSpec file_spec(m_options.m_filename); FileSystem::Instance().Resolve(file_spec); std::string path(file_spec.GetPath()); - uint32_t options = File::OpenOptions::eOpenOptionWrite | - File::OpenOptions::eOpenOptionCanCreate; + auto options = File::eOpenOptionWrite | File::eOpenOptionCanCreate; if (m_options.m_append) - options |= File::OpenOptions::eOpenOptionAppend; + options |= File::eOpenOptionAppend; else - options |= File::OpenOptions::eOpenOptionTruncate; + options |= File::eOpenOptionTruncate; StreamFile out_file(path.c_str(), options, lldb::eFilePermissionsFileDefault); @@ -417,7 +401,7 @@ protected: for (const auto &arg : args) { Status error(GetDebugger().DumpPropertyValue( - &clean_ctx, out_file, arg.ref, OptionValue::eDumpGroupExport)); + &clean_ctx, out_file, arg.ref(), OptionValue::eDumpGroupExport)); if (!error.Success()) { result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); @@ -432,11 +416,8 @@ private: }; // CommandObjectSettingsRead -- Read settings from file - -static constexpr OptionDefinition g_settings_read_options[] = { #define LLDB_OPTIONS_settings_read #include "CommandOptions.inc" -}; class CommandObjectSettingsRead : public CommandObjectParsed { public: @@ -467,9 +448,7 @@ public: m_filename.assign(option_arg); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -536,13 +515,12 @@ public: ~CommandObjectSettingsList() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - return request.GetNumberOfMatches(); } protected: @@ -622,14 +600,15 @@ public: ~CommandObjectSettingsRemove() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + bool WantsCompletion() override { return true; } + + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { if (request.GetCursorIndex() < 2) CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - return request.GetNumberOfMatches(); } protected: @@ -645,8 +624,8 @@ protected: const size_t argc = cmd_args.GetArgumentCount(); if (argc == 0) { - result.AppendError("'settings set' takes an array or dictionary item, or " - "an array followed by one or more indexes, or a " + result.AppendError("'settings remove' takes an array or dictionary item, " + "or an array followed by one or more indexes, or a " "dictionary followed by one or more key names to " "remove"); result.SetStatus(eReturnStatusFailed); @@ -656,19 +635,17 @@ protected: const char *var_name = cmd_args.GetArgumentAtIndex(0); if ((var_name == nullptr) || (var_name[0] == '\0')) { result.AppendError( - "'settings set' command requires a valid variable name"); + "'settings remove' command requires a valid variable name"); result.SetStatus(eReturnStatusFailed); return false; } // Split the raw command into var_name and value pair. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = - Args::StripSpaces(var_value_string, true, true, false); + llvm::StringRef var_value(command); + var_value = var_value.split(var_name).second.trim(); Status error(GetDebugger().SetPropertyValue( - &m_exe_ctx, eVarSetOperationRemove, var_name, var_value_cstr)); + &m_exe_ctx, eVarSetOperationRemove, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); @@ -735,16 +712,14 @@ public: // !WantsRawCommandString. bool WantsCompletion() override { return true; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - - return request.GetNumberOfMatches(); } protected: @@ -762,13 +737,11 @@ protected: } // Split the raw command into var_name, index_value, and value triple. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = - Args::StripSpaces(var_value_string, true, true, false); + llvm::StringRef var_value(command); + var_value = var_value.split(var_name).second.trim(); Status error(GetDebugger().SetPropertyValue( - &m_exe_ctx, eVarSetOperationReplace, var_name, var_value_cstr)); + &m_exe_ctx, eVarSetOperationReplace, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); @@ -833,16 +806,14 @@ public: // !WantsRawCommandString. bool WantsCompletion() override { return true; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - - return request.GetNumberOfMatches(); } protected: @@ -868,13 +839,11 @@ protected: } // Split the raw command into var_name, index_value, and value triple. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = - Args::StripSpaces(var_value_string, true, true, false); + llvm::StringRef var_value(command); + var_value = var_value.split(var_name).second.trim(); Status error(GetDebugger().SetPropertyValue( - &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value_cstr)); + &m_exe_ctx, eVarSetOperationInsertBefore, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); @@ -936,16 +905,14 @@ public: // !WantsRawCommandString. bool WantsCompletion() override { return true; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - - return request.GetNumberOfMatches(); } protected: @@ -971,13 +938,11 @@ protected: } // Split the raw command into var_name, index_value, and value triple. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = - Args::StripSpaces(var_value_string, true, true, false); + llvm::StringRef var_value(command); + var_value = var_value.split(var_name).second.trim(); Status error(GetDebugger().SetPropertyValue( - &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value_cstr)); + &m_exe_ctx, eVarSetOperationInsertAfter, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); @@ -1028,16 +993,14 @@ public: // !WantsRawCommandString. bool WantsCompletion() override { return true; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - - return request.GetNumberOfMatches(); } protected: @@ -1065,13 +1028,11 @@ protected: // character string later on. // Split the raw command into var_name and value pair. - llvm::StringRef raw_str(command); - std::string var_value_string = raw_str.split(var_name).second.str(); - const char *var_value_cstr = - Args::StripSpaces(var_value_string, true, true, false); + llvm::StringRef var_value(command); + var_value = var_value.split(var_name).second.trim(); Status error(GetDebugger().SetPropertyValue( - &m_exe_ctx, eVarSetOperationAppend, var_name, var_value_cstr)); + &m_exe_ctx, eVarSetOperationAppend, var_name, var_value)); if (error.Fail()) { result.AppendError(error.AsCString()); result.SetStatus(eReturnStatusFailed); @@ -1107,16 +1068,14 @@ public: ~CommandObjectSettingsClear() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { // Attempting to complete variable name if (request.GetCursorIndex() < 2) CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSettingsNameCompletion, request, nullptr); - - return request.GetNumberOfMatches(); } protected: diff --git a/source/Commands/CommandObjectSource.cpp b/source/Commands/CommandObjectSource.cpp index 1b515d0f1099..78c8bc811926 100644 --- a/source/Commands/CommandObjectSource.cpp +++ b/source/Commands/CommandObjectSource.cpp @@ -33,18 +33,8 @@ using namespace lldb_private; #pragma mark CommandObjectSourceInfo // CommandObjectSourceInfo - debug line entries dumping command - -static constexpr OptionDefinition g_source_info_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "The number of line entries to display." }, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source in the given module or shared library (can be specified more than once)." }, - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source." }, - { LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "The line number at which to start the displaying lines." }, - { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "The line number at which to stop displaying lines." }, - { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display." }, - { LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line." }, - // clang-format on -}; +#define LLDB_OPTIONS_source_info +#include "CommandOptions.inc" class CommandObjectSourceInfo : public CommandObjectParsed { class CommandOptions : public Options { @@ -92,9 +82,7 @@ class CommandObjectSourceInfo : public CommandObjectParsed { modules.push_back(std::string(option_arg)); break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -404,17 +392,18 @@ protected: // const. ModuleList module_list = (m_module_list.GetSize() > 0) ? m_module_list : target->GetImages(); - size_t num_matches = - module_list.FindFunctions(name, eFunctionNameTypeAuto, - /*include_symbols=*/false, - /*include_inlines=*/true, - /*append=*/true, sc_list_funcs); + module_list.FindFunctions(name, eFunctionNameTypeAuto, + /*include_symbols=*/false, + /*include_inlines=*/true, sc_list_funcs); + size_t num_matches = sc_list_funcs.GetSize(); + if (!num_matches) { // If we didn't find any functions with that name, try searching for // symbols that line up exactly with function addresses. SymbolContextList sc_list_symbols; - size_t num_symbol_matches = module_list.FindFunctionSymbols( + module_list.FindFunctionSymbols( name, eFunctionNameTypeAuto, sc_list_symbols); + size_t num_symbol_matches = sc_list_symbols.GetSize(); for (size_t i = 0; i < num_symbol_matches; i++) { SymbolContext sc; sc_list_symbols.GetContextAtIndex(i, sc); @@ -592,7 +581,8 @@ protected: FileSpec module_file_spec(m_options.modules[i]); if (module_file_spec) { ModuleSpec module_spec(module_file_spec); - if (target->GetImages().FindModules(module_spec, m_module_list) == 0) + target->GetImages().FindModules(module_spec, m_module_list); + if (m_module_list.IsEmpty()) result.AppendWarningWithFormat("No module found for '%s'.\n", m_options.modules[i].c_str()); } @@ -643,19 +633,8 @@ protected: #pragma mark CommandObjectSourceList // CommandObjectSourceList - -static constexpr OptionDefinition g_source_list_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "count", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "The number of source lines to display." }, - { LLDB_OPT_SET_1 | LLDB_OPT_SET_2, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Look up the source file in the given shared library." }, - { LLDB_OPT_SET_ALL, false, "show-breakpoints", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Show the line table locations from the debug information that indicate valid places to set source level breakpoints." }, - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "The file from which to display source." }, - { LLDB_OPT_SET_1, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "The line number at which to start the display source." }, - { LLDB_OPT_SET_2, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeSymbol, "The name of a function whose source to display." }, - { LLDB_OPT_SET_3, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup the address and display the source information for the corresponding file and line." }, - { LLDB_OPT_SET_4, false, "reverse", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Reverse the listing to look backwards from the last displayed block of source." }, - // clang-format on -}; +#define LLDB_OPTIONS_source_list +#include "CommandOptions.inc" class CommandObjectSourceList : public CommandObjectParsed { class CommandOptions : public Options { @@ -704,9 +683,7 @@ class CommandObjectSourceList : public CommandObjectParsed { reverse = true; break; default: - error.SetErrorStringWithFormat("unrecognized short option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -759,7 +736,7 @@ public: // the arguments directly. auto iter = llvm::find_if(current_command_args, [](const Args::ArgEntry &e) { - return e.ref == "-r" || e.ref == "--reverse"; + return e.ref() == "-r" || e.ref() == "--reverse"; }); if (iter == current_command_args.end()) return m_cmd_name.c_str(); @@ -897,13 +874,11 @@ protected: // these somewhere, there should probably be a module-filter-list that can be // passed to the various ModuleList::Find* calls, which would either be a // vector of string names or a ModuleSpecList. - size_t FindMatchingFunctions(Target *target, ConstString name, + void FindMatchingFunctions(Target *target, ConstString name, SymbolContextList &sc_list) { // Displaying the source for a symbol: bool include_inlines = true; - bool append = true; bool include_symbols = false; - size_t num_matches = 0; if (m_options.num_lines == 0) m_options.num_lines = 10; @@ -917,22 +892,20 @@ protected: ModuleSpec module_spec(module_file_spec); matching_modules.Clear(); target->GetImages().FindModules(module_spec, matching_modules); - num_matches += matching_modules.FindFunctions( + matching_modules.FindFunctions( name, eFunctionNameTypeAuto, include_symbols, include_inlines, - append, sc_list); + sc_list); } } } else { - num_matches = target->GetImages().FindFunctions( - name, eFunctionNameTypeAuto, include_symbols, include_inlines, append, - sc_list); + target->GetImages().FindFunctions(name, eFunctionNameTypeAuto, + include_symbols, include_inlines, + sc_list); } - return num_matches; } - size_t FindMatchingFunctionSymbols(Target *target, ConstString name, - SymbolContextList &sc_list) { - size_t num_matches = 0; + void FindMatchingFunctionSymbols(Target *target, ConstString name, + SymbolContextList &sc_list) { const size_t num_modules = m_options.modules.size(); if (num_modules > 0) { ModuleList matching_modules; @@ -942,15 +915,14 @@ protected: ModuleSpec module_spec(module_file_spec); matching_modules.Clear(); target->GetImages().FindModules(module_spec, matching_modules); - num_matches += matching_modules.FindFunctionSymbols( - name, eFunctionNameTypeAuto, sc_list); + matching_modules.FindFunctionSymbols(name, eFunctionNameTypeAuto, + sc_list); } } } else { - num_matches = target->GetImages().FindFunctionSymbols( - name, eFunctionNameTypeAuto, sc_list); + target->GetImages().FindFunctionSymbols(name, eFunctionNameTypeAuto, + sc_list); } - return num_matches; } bool DoExecute(Args &command, CommandReturnObject &result) override { @@ -970,13 +942,15 @@ protected: ConstString name(m_options.symbol_name.c_str()); // Displaying the source for a symbol. Search for function named name. - size_t num_matches = FindMatchingFunctions(target, name, sc_list); + FindMatchingFunctions(target, name, sc_list); + size_t num_matches = sc_list.GetSize(); if (!num_matches) { // If we didn't find any functions with that name, try searching for // symbols that line up exactly with function addresses. SymbolContextList sc_list_symbols; - size_t num_symbol_matches = - FindMatchingFunctionSymbols(target, name, sc_list_symbols); + FindMatchingFunctionSymbols(target, name, sc_list_symbols); + size_t num_symbol_matches =sc_list_symbols.GetSize(); + for (size_t i = 0; i < num_symbol_matches; i++) { SymbolContext sc; sc_list_symbols.GetContextAtIndex(i, sc); diff --git a/source/Commands/CommandObjectStats.cpp b/source/Commands/CommandObjectStats.cpp index a73c2a8e0409..e3a1f9433662 100644 --- a/source/Commands/CommandObjectStats.cpp +++ b/source/Commands/CommandObjectStats.cpp @@ -26,15 +26,15 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); + Target &target = GetSelectedOrDummyTarget(); - if (target->GetCollectingStats()) { + if (target.GetCollectingStats()) { result.AppendError("statistics already enabled"); result.SetStatus(eReturnStatusFailed); return false; } - target->SetCollectingStats(true); + target.SetCollectingStats(true); result.SetStatus(eReturnStatusSuccessFinishResult); return true; } @@ -51,15 +51,15 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); + Target &target = GetSelectedOrDummyTarget(); - if (!target->GetCollectingStats()) { + if (!target.GetCollectingStats()) { result.AppendError("need to enable statistics before disabling them"); result.SetStatus(eReturnStatusFailed); return false; } - target->SetCollectingStats(false); + target.SetCollectingStats(false); result.SetStatus(eReturnStatusSuccessFinishResult); return true; } @@ -75,10 +75,10 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); + Target &target = GetSelectedOrDummyTarget(); uint32_t i = 0; - for (auto &stat : target->GetStatistics()) { + for (auto &stat : target.GetStatistics()) { result.AppendMessageWithFormat( "%s : %u\n", lldb_private::GetStatDescription(static_cast<lldb_private::StatisticKind>(i)) diff --git a/source/Commands/CommandObjectTarget.cpp b/source/Commands/CommandObjectTarget.cpp index e913a28501f2..abf7895a7384 100644 --- a/source/Commands/CommandObjectTarget.cpp +++ b/source/Commands/CommandObjectTarget.cpp @@ -37,7 +37,6 @@ #include "lldb/Symbol/LocateSymbolFile.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolFile.h" -#include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/UnwindPlan.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ABI.h" @@ -135,22 +134,27 @@ static uint32_t DumpTargetList(TargetList &target_list, } // Note that the negation in the argument name causes a slightly confusing -// mapping of the enum values, +// mapping of the enum values. static constexpr OptionEnumValueElement g_dependents_enumaration[] = { - {eLoadDependentsDefault, "default", - "Only load dependents when the target is an executable."}, - {eLoadDependentsNo, "true", - "Don't load dependents, even if the target is an executable."}, - {eLoadDependentsYes, "false", - "Load dependents, even if the target is not an executable."}}; - -static constexpr OptionDefinition g_dependents_options[] = { - {LLDB_OPT_SET_1, false, "no-dependents", 'd', - OptionParser::eOptionalArgument, nullptr, - OptionEnumValues(g_dependents_enumaration), 0, eArgTypeValue, - "Whether or not to load dependents when creating a target. If the option " - "is not specified, the value is implicitly 'default'. If the option is " - "specified but without a value, the value is implicitly 'true'."}}; + { + eLoadDependentsDefault, + "default", + "Only load dependents when the target is an executable.", + }, + { + eLoadDependentsNo, + "true", + "Don't load dependents, even if the target is an executable.", + }, + { + eLoadDependentsYes, + "false", + "Load dependents, even if the target is not an executable.", + }, +}; + +#define LLDB_OPTIONS_target_dependents +#include "CommandOptions.inc" class OptionGroupDependents : public OptionGroup { public: @@ -159,7 +163,7 @@ public: ~OptionGroupDependents() override {} llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_dependents_options); + return llvm::makeArrayRef(g_target_dependents_options); } Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_value, @@ -172,11 +176,13 @@ public: return error; } - const char short_option = g_dependents_options[option_idx].short_option; + const char short_option = + g_target_dependents_options[option_idx].short_option; if (short_option == 'd') { LoadDependentFiles tmp_load_dependents; tmp_load_dependents = (LoadDependentFiles)OptionArgParser::ToOptionEnum( - option_value, g_dependents_options[option_idx].enum_values, 0, error); + option_value, g_target_dependents_options[option_idx].enum_values, 0, + error); if (error.Success()) m_load_dependent_files = tmp_load_dependents; } else { @@ -252,13 +258,12 @@ public: Options *GetOptions() override { return &m_option_group; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } protected: @@ -444,7 +449,8 @@ protected: } } else { result.AppendMessageWithFormat( - "Current executable set to '%s' (%s).\n", file_path, + "Current executable set to '%s' (%s).\n", + file_spec.GetPath().c_str(), target_sp->GetArchitecture().GetArchitectureName()); result.SetStatus(eReturnStatusSuccessFinishNoResult); } @@ -619,7 +625,7 @@ protected: for (auto &entry : args.entries()) { uint32_t target_idx; - if (entry.ref.getAsInteger(0, target_idx)) { + if (entry.ref().getAsInteger(0, target_idx)) { result.AppendErrorWithFormat("invalid target index '%s'\n", entry.c_str()); result.SetStatus(eReturnStatusFailed); @@ -792,12 +798,12 @@ public: static size_t GetVariableCallback(void *baton, const char *name, VariableList &variable_list) { + size_t old_size = variable_list.GetSize(); Target *target = static_cast<Target *>(baton); - if (target) { - return target->GetImages().FindGlobalVariables(ConstString(name), - UINT32_MAX, variable_list); - } - return 0; + if (target) + target->GetImages().FindGlobalVariables(ConstString(name), UINT32_MAX, + variable_list); + return variable_list.GetSize() - old_size; } Options *GetOptions() override { return &m_option_group; } @@ -860,8 +866,9 @@ protected: return false; } use_var_name = true; - matches = target->GetImages().FindGlobalVariables(regex, UINT32_MAX, - variable_list); + target->GetImages().FindGlobalVariables(regex, UINT32_MAX, + variable_list); + matches = variable_list.GetSize(); } else { Status error(Variable::GetValuesForVariableExpressionPath( arg, m_exe_ctx.GetBestExecutionContextScope(), @@ -936,7 +943,6 @@ protected: } } else { SymbolContextList sc_list; - const bool append = true; // We have one or more compile unit or shlib if (num_shlibs > 0) { for (size_t shlib_idx = 0; shlib_idx < num_shlibs; ++shlib_idx) { @@ -949,8 +955,7 @@ protected: if (num_compile_units > 0) { for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) module_sp->FindCompileUnits( - compile_units.GetFileSpecAtIndex(cu_idx), append, - sc_list); + compile_units.GetFileSpecAtIndex(cu_idx), sc_list); } else { SymbolContext sc; sc.module_sp = module_sp; @@ -968,7 +973,7 @@ protected: // units files that were specified for (size_t cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) target->GetImages().FindCompileUnits( - compile_units.GetFileSpecAtIndex(cu_idx), append, sc_list); + compile_units.GetFileSpecAtIndex(cu_idx), sc_list); } const uint32_t num_scs = sc_list.GetSize(); @@ -1024,7 +1029,7 @@ public: : CommandObjectParsed(interpreter, "target modules search-paths add", "Add new image search paths substitution pairs to " "the current target.", - nullptr) { + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandArgumentData old_prefix_arg; CommandArgumentData new_prefix_arg; @@ -1053,41 +1058,37 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target) { - const size_t argc = command.GetArgumentCount(); - if (argc & 1) { - result.AppendError("add requires an even number of arguments\n"); - result.SetStatus(eReturnStatusFailed); - } else { - for (size_t i = 0; i < argc; i += 2) { - const char *from = command.GetArgumentAtIndex(i); - const char *to = command.GetArgumentAtIndex(i + 1); - - if (from[0] && to[0]) { - Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); - if (log) { - log->Printf("target modules search path adding ImageSearchPath " - "pair: '%s' -> '%s'", - from, to); - } - bool last_pair = ((argc - i) == 2); - target->GetImageSearchPathList().Append( - ConstString(from), ConstString(to), - last_pair); // Notify if this is the last pair - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } else { - if (from[0]) - result.AppendError("<path-prefix> can't be empty\n"); - else - result.AppendError("<new-path-prefix> can't be empty\n"); - result.SetStatus(eReturnStatusFailed); + Target *target = &GetSelectedTarget(); + const size_t argc = command.GetArgumentCount(); + if (argc & 1) { + result.AppendError("add requires an even number of arguments\n"); + result.SetStatus(eReturnStatusFailed); + } else { + for (size_t i = 0; i < argc; i += 2) { + const char *from = command.GetArgumentAtIndex(i); + const char *to = command.GetArgumentAtIndex(i + 1); + + if (from[0] && to[0]) { + Log *log = lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_HOST); + if (log) { + LLDB_LOGF(log, + "target modules search path adding ImageSearchPath " + "pair: '%s' -> '%s'", + from, to); } + bool last_pair = ((argc - i) == 2); + target->GetImageSearchPathList().Append( + ConstString(from), ConstString(to), + last_pair); // Notify if this is the last pair + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + if (from[0]) + result.AppendError("<path-prefix> can't be empty\n"); + else + result.AppendError("<new-path-prefix> can't be empty\n"); + result.SetStatus(eReturnStatusFailed); } } - } else { - result.AppendError("invalid target\n"); - result.SetStatus(eReturnStatusFailed); } return result.Succeeded(); } @@ -1101,21 +1102,17 @@ public: : CommandObjectParsed(interpreter, "target modules search-paths clear", "Clear all current image search path substitution " "pairs from the current target.", - "target modules search-paths clear") {} + "target modules search-paths clear", + eCommandRequiresTarget) {} ~CommandObjectTargetModulesSearchPathsClear() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target) { - bool notify = true; - target->GetImageSearchPathList().Clear(notify); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } else { - result.AppendError("invalid target\n"); - result.SetStatus(eReturnStatusFailed); - } + Target *target = &GetSelectedTarget(); + bool notify = true; + target->GetImageSearchPathList().Clear(notify); + result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); } }; @@ -1128,7 +1125,7 @@ public: : CommandObjectParsed(interpreter, "target modules search-paths insert", "Insert a new image search path substitution pair " "into the current target at the specified index.", - nullptr) { + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg1; CommandArgumentEntry arg2; CommandArgumentData index_arg; @@ -1168,55 +1165,49 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target) { - size_t argc = command.GetArgumentCount(); - // check for at least 3 arguments and an odd number of parameters - if (argc >= 3 && argc & 1) { - bool success = false; + Target *target = &GetSelectedTarget(); + size_t argc = command.GetArgumentCount(); + // check for at least 3 arguments and an odd number of parameters + if (argc >= 3 && argc & 1) { + bool success = false; - uint32_t insert_idx = StringConvert::ToUInt32( - command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success); + uint32_t insert_idx = StringConvert::ToUInt32( + command.GetArgumentAtIndex(0), UINT32_MAX, 0, &success); - if (!success) { - result.AppendErrorWithFormat( - "<index> parameter is not an integer: '%s'.\n", - command.GetArgumentAtIndex(0)); - result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); - } + if (!success) { + result.AppendErrorWithFormat( + "<index> parameter is not an integer: '%s'.\n", + command.GetArgumentAtIndex(0)); + result.SetStatus(eReturnStatusFailed); + return result.Succeeded(); + } - // shift off the index - command.Shift(); - argc = command.GetArgumentCount(); + // shift off the index + command.Shift(); + argc = command.GetArgumentCount(); - for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) { - const char *from = command.GetArgumentAtIndex(i); - const char *to = command.GetArgumentAtIndex(i + 1); + for (uint32_t i = 0; i < argc; i += 2, ++insert_idx) { + const char *from = command.GetArgumentAtIndex(i); + const char *to = command.GetArgumentAtIndex(i + 1); - if (from[0] && to[0]) { - bool last_pair = ((argc - i) == 2); - target->GetImageSearchPathList().Insert( - ConstString(from), ConstString(to), insert_idx, last_pair); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } else { - if (from[0]) - result.AppendError("<path-prefix> can't be empty\n"); - else - result.AppendError("<new-path-prefix> can't be empty\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } + if (from[0] && to[0]) { + bool last_pair = ((argc - i) == 2); + target->GetImageSearchPathList().Insert( + ConstString(from), ConstString(to), insert_idx, last_pair); + result.SetStatus(eReturnStatusSuccessFinishNoResult); + } else { + if (from[0]) + result.AppendError("<path-prefix> can't be empty\n"); + else + result.AppendError("<new-path-prefix> can't be empty\n"); + result.SetStatus(eReturnStatusFailed); + return false; } - } else { - result.AppendError("insert requires at least three arguments\n"); - result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); } - } else { - result.AppendError("invalid target\n"); + result.AppendError("insert requires at least three arguments\n"); result.SetStatus(eReturnStatusFailed); + return result.Succeeded(); } return result.Succeeded(); } @@ -1230,26 +1221,22 @@ public: : CommandObjectParsed(interpreter, "target modules search-paths list", "List all current image search path substitution " "pairs in the current target.", - "target modules search-paths list") {} + "target modules search-paths list", + eCommandRequiresTarget) {} ~CommandObjectTargetModulesSearchPathsList() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target) { - if (command.GetArgumentCount() != 0) { - result.AppendError("list takes no arguments\n"); - result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); - } - - target->GetImageSearchPathList().Dump(&result.GetOutputStream()); - result.SetStatus(eReturnStatusSuccessFinishResult); - } else { - result.AppendError("invalid target\n"); + Target *target = &GetSelectedTarget(); + if (command.GetArgumentCount() != 0) { + result.AppendError("list takes no arguments\n"); result.SetStatus(eReturnStatusFailed); + return result.Succeeded(); } + + target->GetImageSearchPathList().Dump(&result.GetOutputStream()); + result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); } }; @@ -1262,7 +1249,7 @@ public: : CommandObjectParsed( interpreter, "target modules search-paths query", "Transform a path using the first applicable image search path.", - nullptr) { + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandArgumentData path_arg; @@ -1282,26 +1269,21 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target) { - if (command.GetArgumentCount() != 1) { - result.AppendError("query requires one argument\n"); - result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); - } - - ConstString orig(command.GetArgumentAtIndex(0)); - ConstString transformed; - if (target->GetImageSearchPathList().RemapPath(orig, transformed)) - result.GetOutputStream().Printf("%s\n", transformed.GetCString()); - else - result.GetOutputStream().Printf("%s\n", orig.GetCString()); - - result.SetStatus(eReturnStatusSuccessFinishResult); - } else { - result.AppendError("invalid target\n"); + Target *target = &GetSelectedTarget(); + if (command.GetArgumentCount() != 1) { + result.AppendError("query requires one argument\n"); result.SetStatus(eReturnStatusFailed); + return result.Succeeded(); } + + ConstString orig(command.GetArgumentAtIndex(0)); + ConstString transformed; + if (target->GetImageSearchPathList().RemapPath(orig, transformed)) + result.GetOutputStream().Printf("%s\n", transformed.GetCString()); + else + result.GetOutputStream().Printf("%s\n", orig.GetCString()); + + result.SetStatus(eReturnStatusSuccessFinishResult); return result.Succeeded(); } }; @@ -1439,15 +1421,11 @@ static size_t DumpModuleObjfileHeaders(Stream &strm, ModuleList &module_list) { static void DumpModuleSymtab(CommandInterpreter &interpreter, Stream &strm, Module *module, SortOrder sort_order) { - if (module) { - SymbolVendor *sym_vendor = module->GetSymbolVendor(); - if (sym_vendor) { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) - symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), - sort_order); - } - } + if (!module) + return; + if (Symtab *symtab = module->GetSymtab()) + symtab->Dump(&strm, interpreter.GetExecutionContext().GetTargetPtr(), + sort_order); } static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm, @@ -1467,11 +1445,10 @@ static void DumpModuleSections(CommandInterpreter &interpreter, Stream &strm, } } -static bool DumpModuleSymbolVendor(Stream &strm, Module *module) { +static bool DumpModuleSymbolFile(Stream &strm, Module *module) { if (module) { - SymbolVendor *symbol_vendor = module->GetSymbolVendor(true); - if (symbol_vendor) { - symbol_vendor->Dump(&strm); + if (SymbolFile *symbol_file = module->GetSymbolFile(true)) { + symbol_file->Dump(strm); return true; } } @@ -1553,47 +1530,44 @@ static uint32_t LookupSymbolInModule(CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name, bool name_is_regex, bool verbose) { - if (module) { - SymbolContext sc; + if (!module) + return 0; - SymbolVendor *sym_vendor = module->GetSymbolVendor(); - if (sym_vendor) { - Symtab *symtab = sym_vendor->GetSymtab(); - if (symtab) { - std::vector<uint32_t> match_indexes; - ConstString symbol_name(name); - uint32_t num_matches = 0; - if (name_is_regex) { - RegularExpression name_regexp(symbol_name.GetStringRef()); - num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType( - name_regexp, eSymbolTypeAny, match_indexes); - } else { - num_matches = - symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes); - } + Symtab *symtab = module->GetSymtab(); + if (!symtab) + return 0; - if (num_matches > 0) { - strm.Indent(); - strm.Printf("%u symbols match %s'%s' in ", num_matches, - name_is_regex ? "the regular expression " : "", name); - DumpFullpath(strm, &module->GetFileSpec(), 0); - strm.PutCString(":\n"); - strm.IndentMore(); - for (uint32_t i = 0; i < num_matches; ++i) { - Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]); - if (symbol && symbol->ValueIsAddress()) { - DumpAddress(interpreter.GetExecutionContext() - .GetBestExecutionContextScope(), - symbol->GetAddressRef(), verbose, strm); - } - } - strm.IndentLess(); - return num_matches; - } + SymbolContext sc; + std::vector<uint32_t> match_indexes; + ConstString symbol_name(name); + uint32_t num_matches = 0; + if (name_is_regex) { + RegularExpression name_regexp(symbol_name.GetStringRef()); + num_matches = symtab->AppendSymbolIndexesMatchingRegExAndType( + name_regexp, eSymbolTypeAny, match_indexes); + } else { + num_matches = + symtab->AppendSymbolIndexesWithName(symbol_name, match_indexes); + } + + if (num_matches > 0) { + strm.Indent(); + strm.Printf("%u symbols match %s'%s' in ", num_matches, + name_is_regex ? "the regular expression " : "", name); + DumpFullpath(strm, &module->GetFileSpec(), 0); + strm.PutCString(":\n"); + strm.IndentMore(); + for (uint32_t i = 0; i < num_matches; ++i) { + Symbol *symbol = symtab->SymbolAtIndex(match_indexes[i]); + if (symbol && symbol->ValueIsAddress()) { + DumpAddress( + interpreter.GetExecutionContext().GetBestExecutionContextScope(), + symbol->GetAddressRef(), verbose, strm); } } + strm.IndentLess(); } - return 0; + return num_matches; } static void DumpSymbolContextList(ExecutionContextScope *exe_scope, @@ -1623,19 +1597,17 @@ static size_t LookupFunctionInModule(CommandInterpreter &interpreter, bool verbose) { if (module && name && name[0]) { SymbolContextList sc_list; - const bool append = true; size_t num_matches = 0; if (name_is_regex) { RegularExpression function_name_regex((llvm::StringRef(name))); - num_matches = module->FindFunctions(function_name_regex, include_symbols, - include_inlines, append, sc_list); + module->FindFunctions(function_name_regex, include_symbols, + include_inlines, sc_list); } else { ConstString function_name(name); - num_matches = module->FindFunctions( - function_name, nullptr, eFunctionNameTypeAuto, include_symbols, - include_inlines, append, sc_list); + module->FindFunctions(function_name, nullptr, eFunctionNameTypeAuto, + include_symbols, include_inlines, sc_list); } - + num_matches = sc_list.GetSize(); if (num_matches) { strm.Indent(); strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches, @@ -1654,75 +1626,30 @@ static size_t LookupFunctionInModule(CommandInterpreter &interpreter, static size_t LookupTypeInModule(CommandInterpreter &interpreter, Stream &strm, Module *module, const char *name_cstr, bool name_is_regex) { + TypeList type_list; if (module && name_cstr && name_cstr[0]) { - TypeList type_list; const uint32_t max_num_matches = UINT32_MAX; size_t num_matches = 0; bool name_is_fully_qualified = false; ConstString name(name_cstr); llvm::DenseSet<lldb_private::SymbolFile *> searched_symbol_files; - num_matches = - module->FindTypes(name, name_is_fully_qualified, max_num_matches, - searched_symbol_files, type_list); + module->FindTypes(name, name_is_fully_qualified, max_num_matches, + searched_symbol_files, type_list); - if (num_matches) { - strm.Indent(); - strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches, - num_matches > 1 ? "es" : ""); - DumpFullpath(strm, &module->GetFileSpec(), 0); - strm.PutCString(":\n"); - for (TypeSP type_sp : type_list.Types()) { - if (type_sp) { - // Resolve the clang type so that any forward references to types - // that haven't yet been parsed will get parsed. - type_sp->GetFullCompilerType(); - type_sp->GetDescription(&strm, eDescriptionLevelFull, true); - // Print all typedef chains - TypeSP typedef_type_sp(type_sp); - TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType()); - while (typedefed_type_sp) { - strm.EOL(); - strm.Printf(" typedef '%s': ", - typedef_type_sp->GetName().GetCString()); - typedefed_type_sp->GetFullCompilerType(); - typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, - true); - typedef_type_sp = typedefed_type_sp; - typedefed_type_sp = typedef_type_sp->GetTypedefType(); - } - } - strm.EOL(); - } - } - return num_matches; - } - return 0; -} - -static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm, - Module &module, const char *name_cstr, - bool name_is_regex) { - TypeList type_list; - const uint32_t max_num_matches = UINT32_MAX; - size_t num_matches = 1; - bool name_is_fully_qualified = false; + if (type_list.Empty()) + return 0; - ConstString name(name_cstr); - llvm::DenseSet<SymbolFile *> searched_symbol_files; - num_matches = module.FindTypes(name, name_is_fully_qualified, max_num_matches, - searched_symbol_files, type_list); - - if (num_matches) { strm.Indent(); - strm.PutCString("Best match found in "); - DumpFullpath(strm, &module.GetFileSpec(), 0); + strm.Printf("%" PRIu64 " match%s found in ", (uint64_t)num_matches, + num_matches > 1 ? "es" : ""); + DumpFullpath(strm, &module->GetFileSpec(), 0); strm.PutCString(":\n"); - - TypeSP type_sp(type_list.GetTypeAtIndex(0)); - if (type_sp) { - // Resolve the clang type so that any forward references to types that - // haven't yet been parsed will get parsed. + for (TypeSP type_sp : type_list.Types()) { + if (!type_sp) + continue; + // Resolve the clang type so that any forward references to types + // that haven't yet been parsed will get parsed. type_sp->GetFullCompilerType(); type_sp->GetDescription(&strm, eDescriptionLevelFull, true); // Print all typedef chains @@ -1740,7 +1667,50 @@ static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm, } strm.EOL(); } - return num_matches; + return type_list.GetSize(); +} + +static size_t LookupTypeHere(CommandInterpreter &interpreter, Stream &strm, + Module &module, const char *name_cstr, + bool name_is_regex) { + TypeList type_list; + const uint32_t max_num_matches = UINT32_MAX; + bool name_is_fully_qualified = false; + + ConstString name(name_cstr); + llvm::DenseSet<SymbolFile *> searched_symbol_files; + module.FindTypes(name, name_is_fully_qualified, max_num_matches, + searched_symbol_files, type_list); + + if (type_list.Empty()) + return 0; + + strm.Indent(); + strm.PutCString("Best match found in "); + DumpFullpath(strm, &module.GetFileSpec(), 0); + strm.PutCString(":\n"); + + TypeSP type_sp(type_list.GetTypeAtIndex(0)); + if (type_sp) { + // Resolve the clang type so that any forward references to types that + // haven't yet been parsed will get parsed. + type_sp->GetFullCompilerType(); + type_sp->GetDescription(&strm, eDescriptionLevelFull, true); + // Print all typedef chains + TypeSP typedef_type_sp(type_sp); + TypeSP typedefed_type_sp(typedef_type_sp->GetTypedefType()); + while (typedefed_type_sp) { + strm.EOL(); + strm.Printf(" typedef '%s': ", + typedef_type_sp->GetName().GetCString()); + typedefed_type_sp->GetFullCompilerType(); + typedefed_type_sp->GetDescription(&strm, eDescriptionLevelFull, true); + typedef_type_sp = typedefed_type_sp; + typedefed_type_sp = typedef_type_sp->GetTypedefType(); + } + } + strm.EOL(); + return type_list.GetSize(); } static uint32_t LookupFileAndLineInModule(CommandInterpreter &interpreter, @@ -1797,8 +1767,8 @@ static size_t FindModulesByName(Target *target, const char *module_name, } } else { if (target) { - const size_t num_matches = - target->GetImages().FindModules(module_spec, module_list); + target->GetImages().FindModules(module_spec, module_list); + const size_t num_matches = module_list.GetSize(); // Not found in our module list for our target, check the main shared // module list in case it is a extra file used somewhere else @@ -1825,8 +1795,9 @@ public: CommandObjectTargetModulesModuleAutoComplete(CommandInterpreter &interpreter, const char *name, const char *help, - const char *syntax) - : CommandObjectParsed(interpreter, name, help, syntax) { + const char *syntax, + uint32_t flags = 0) + : CommandObjectParsed(interpreter, name, help, syntax, flags) { CommandArgumentEntry arg; CommandArgumentData file_arg; @@ -1844,13 +1815,12 @@ public: ~CommandObjectTargetModulesModuleAutoComplete() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eModuleCompletion, request, nullptr); - return request.GetNumberOfMatches(); } }; @@ -1883,13 +1853,12 @@ public: ~CommandObjectTargetModulesSourceFileAutoComplete() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eSourceFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } }; @@ -1902,19 +1871,13 @@ public: : CommandObjectTargetModulesModuleAutoComplete( interpreter, "target modules dump objfile", "Dump the object file headers from one or more target modules.", - nullptr) {} + nullptr, eCommandRequiresTarget) {} ~CommandObjectTargetModulesDumpObjfile() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); result.GetOutputStream().SetAddressByteSize(addr_byte_size); @@ -1961,15 +1924,25 @@ protected: #pragma mark CommandObjectTargetModulesDumpSymtab static constexpr OptionEnumValueElement g_sort_option_enumeration[] = { - {eSortOrderNone, "none", - "No sorting, use the original symbol table order."}, - {eSortOrderByAddress, "address", "Sort output by symbol address."}, - {eSortOrderByName, "name", "Sort output by symbol name."} }; + { + eSortOrderNone, + "none", + "No sorting, use the original symbol table order.", + }, + { + eSortOrderByAddress, + "address", + "Sort output by symbol address.", + }, + { + eSortOrderByName, + "name", + "Sort output by symbol name.", + }, +}; -static constexpr OptionDefinition g_target_modules_dump_symtab_options[] = { #define LLDB_OPTIONS_target_modules_dump_symtab #include "CommandOptions.inc" -}; class CommandObjectTargetModulesDumpSymtab : public CommandObjectTargetModulesModuleAutoComplete { @@ -1977,7 +1950,8 @@ public: CommandObjectTargetModulesDumpSymtab(CommandInterpreter &interpreter) : CommandObjectTargetModulesModuleAutoComplete( interpreter, "target modules dump symtab", - "Dump the symbol table from one or more target modules.", nullptr), + "Dump the symbol table from one or more target modules.", nullptr, + eCommandRequiresTarget), m_options() {} ~CommandObjectTargetModulesDumpSymtab() override = default; @@ -2003,9 +1977,7 @@ public: break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -2023,82 +1995,75 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - uint32_t num_dumped = 0; + Target *target = &GetSelectedTarget(); + uint32_t num_dumped = 0; - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); - if (command.GetArgumentCount() == 0) { - // Dump all sections for all modules images - std::lock_guard<std::recursive_mutex> guard( - target->GetImages().GetMutex()); - const size_t num_modules = target->GetImages().GetSize(); - if (num_modules > 0) { - result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64 - " modules.\n", - (uint64_t)num_modules); - for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { - if (num_dumped > 0) { - result.GetOutputStream().EOL(); - result.GetOutputStream().EOL(); - } - if (m_interpreter.WasInterrupted()) - break; - num_dumped++; - DumpModuleSymtab( - m_interpreter, result.GetOutputStream(), - target->GetImages().GetModulePointerAtIndexUnlocked(image_idx), - m_options.m_sort_order); + if (command.GetArgumentCount() == 0) { + // Dump all sections for all modules images + std::lock_guard<std::recursive_mutex> guard( + target->GetImages().GetMutex()); + const size_t num_modules = target->GetImages().GetSize(); + if (num_modules > 0) { + result.GetOutputStream().Printf("Dumping symbol table for %" PRIu64 + " modules.\n", + (uint64_t)num_modules); + for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { + if (num_dumped > 0) { + result.GetOutputStream().EOL(); + result.GetOutputStream().EOL(); } - } else { - result.AppendError("the target has no associated executable images"); - result.SetStatus(eReturnStatusFailed); - return false; + if (m_interpreter.WasInterrupted()) + break; + num_dumped++; + DumpModuleSymtab( + m_interpreter, result.GetOutputStream(), + target->GetImages().GetModulePointerAtIndexUnlocked(image_idx), + m_options.m_sort_order); } } else { - // Dump specified images (by basename or fullpath) - const char *arg_cstr; - for (int arg_idx = 0; - (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; - ++arg_idx) { - ModuleList module_list; - const size_t num_matches = - FindModulesByName(target, arg_cstr, module_list, true); - if (num_matches > 0) { - for (size_t i = 0; i < num_matches; ++i) { - Module *module = module_list.GetModulePointerAtIndex(i); - if (module) { - if (num_dumped > 0) { - result.GetOutputStream().EOL(); - result.GetOutputStream().EOL(); - } - if (m_interpreter.WasInterrupted()) - break; - num_dumped++; - DumpModuleSymtab(m_interpreter, result.GetOutputStream(), - module, m_options.m_sort_order); + result.AppendError("the target has no associated executable images"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + // Dump specified images (by basename or fullpath) + const char *arg_cstr; + for (int arg_idx = 0; + (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; + ++arg_idx) { + ModuleList module_list; + const size_t num_matches = + FindModulesByName(target, arg_cstr, module_list, true); + if (num_matches > 0) { + for (size_t i = 0; i < num_matches; ++i) { + Module *module = module_list.GetModulePointerAtIndex(i); + if (module) { + if (num_dumped > 0) { + result.GetOutputStream().EOL(); + result.GetOutputStream().EOL(); } + if (m_interpreter.WasInterrupted()) + break; + num_dumped++; + DumpModuleSymtab(m_interpreter, result.GetOutputStream(), module, + m_options.m_sort_order); } - } else - result.AppendWarningWithFormat( - "Unable to find an image that matches '%s'.\n", arg_cstr); - } + } + } else + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg_cstr); } + } - if (num_dumped > 0) - result.SetStatus(eReturnStatusSuccessFinishResult); - else { - result.AppendError("no matching executable images found"); - result.SetStatus(eReturnStatusFailed); - } + if (num_dumped > 0) + result.SetStatus(eReturnStatusSuccessFinishResult); + else { + result.AppendError("no matching executable images found"); + result.SetStatus(eReturnStatusFailed); } return result.Succeeded(); } @@ -2118,82 +2083,75 @@ public: interpreter, "target modules dump sections", "Dump the sections from one or more target modules.", //"target modules dump sections [<file1> ...]") - nullptr) {} + nullptr, eCommandRequiresTarget) {} ~CommandObjectTargetModulesDumpSections() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - uint32_t num_dumped = 0; + Target *target = &GetSelectedTarget(); + uint32_t num_dumped = 0; - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); - if (command.GetArgumentCount() == 0) { - // Dump all sections for all modules images - const size_t num_modules = target->GetImages().GetSize(); - if (num_modules > 0) { - result.GetOutputStream().Printf("Dumping sections for %" PRIu64 - " modules.\n", - (uint64_t)num_modules); - for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { + if (command.GetArgumentCount() == 0) { + // Dump all sections for all modules images + const size_t num_modules = target->GetImages().GetSize(); + if (num_modules > 0) { + result.GetOutputStream().Printf("Dumping sections for %" PRIu64 + " modules.\n", + (uint64_t)num_modules); + for (size_t image_idx = 0; image_idx < num_modules; ++image_idx) { + if (m_interpreter.WasInterrupted()) + break; + num_dumped++; + DumpModuleSections( + m_interpreter, result.GetOutputStream(), + target->GetImages().GetModulePointerAtIndex(image_idx)); + } + } else { + result.AppendError("the target has no associated executable images"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + // Dump specified images (by basename or fullpath) + const char *arg_cstr; + for (int arg_idx = 0; + (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; + ++arg_idx) { + ModuleList module_list; + const size_t num_matches = + FindModulesByName(target, arg_cstr, module_list, true); + if (num_matches > 0) { + for (size_t i = 0; i < num_matches; ++i) { if (m_interpreter.WasInterrupted()) break; - num_dumped++; - DumpModuleSections( - m_interpreter, result.GetOutputStream(), - target->GetImages().GetModulePointerAtIndex(image_idx)); + Module *module = module_list.GetModulePointerAtIndex(i); + if (module) { + num_dumped++; + DumpModuleSections(m_interpreter, result.GetOutputStream(), + module); + } } } else { - result.AppendError("the target has no associated executable images"); - result.SetStatus(eReturnStatusFailed); - return false; - } - } else { - // Dump specified images (by basename or fullpath) - const char *arg_cstr; - for (int arg_idx = 0; - (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; - ++arg_idx) { - ModuleList module_list; - const size_t num_matches = - FindModulesByName(target, arg_cstr, module_list, true); - if (num_matches > 0) { - for (size_t i = 0; i < num_matches; ++i) { - if (m_interpreter.WasInterrupted()) - break; - Module *module = module_list.GetModulePointerAtIndex(i); - if (module) { - num_dumped++; - DumpModuleSections(m_interpreter, result.GetOutputStream(), - module); - } - } - } else { - // Check the global list - std::lock_guard<std::recursive_mutex> guard( - Module::GetAllocationModuleCollectionMutex()); + // Check the global list + std::lock_guard<std::recursive_mutex> guard( + Module::GetAllocationModuleCollectionMutex()); - result.AppendWarningWithFormat( - "Unable to find an image that matches '%s'.\n", arg_cstr); - } + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg_cstr); } } + } - if (num_dumped > 0) - result.SetStatus(eReturnStatusSuccessFinishResult); - else { - result.AppendError("no matching executable images found"); - result.SetStatus(eReturnStatusFailed); - } + if (num_dumped > 0) + result.SetStatus(eReturnStatusSuccessFinishResult); + else { + result.AppendError("no matching executable images found"); + result.SetStatus(eReturnStatusFailed); } return result.Succeeded(); } @@ -2211,19 +2169,13 @@ public: interpreter, "target modules dump ast", "Dump the clang ast for a given module's symbol file.", //"target modules dump ast [<file1> ...]") - nullptr) {} + nullptr, eCommandRequiresTarget) {} ~CommandObjectTargetModulesDumpClangAST() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); const size_t num_modules = target->GetImages().GetSize(); if (num_modules == 0) { @@ -2241,8 +2193,8 @@ protected: if (m_interpreter.WasInterrupted()) break; Module *m = target->GetImages().GetModulePointerAtIndex(image_idx); - SymbolFile *sf = m->GetSymbolVendor()->GetSymbolFile(); - sf->DumpClangAST(result.GetOutputStream()); + if (SymbolFile *sf = m->GetSymbolFile()) + sf->DumpClangAST(result.GetOutputStream()); } result.SetStatus(eReturnStatusSuccessFinishResult); return true; @@ -2267,8 +2219,8 @@ protected: if (m_interpreter.WasInterrupted()) break; Module *m = module_list.GetModulePointerAtIndex(i); - SymbolFile *sf = m->GetSymbolVendor()->GetSymbolFile(); - sf->DumpClangAST(result.GetOutputStream()); + if (SymbolFile *sf = m->GetSymbolFile()) + sf->DumpClangAST(result.GetOutputStream()); } } result.SetStatus(eReturnStatusSuccessFinishResult); @@ -2288,84 +2240,79 @@ public: interpreter, "target modules dump symfile", "Dump the debug symbol file for one or more target modules.", //"target modules dump symfile [<file1> ...]") - nullptr) {} + nullptr, eCommandRequiresTarget) {} ~CommandObjectTargetModulesDumpSymfile() override = default; protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - uint32_t num_dumped = 0; + Target *target = &GetSelectedTarget(); + uint32_t num_dumped = 0; - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); - if (command.GetArgumentCount() == 0) { - // Dump all sections for all modules images - const ModuleList &target_modules = target->GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); - const size_t num_modules = target_modules.GetSize(); - if (num_modules > 0) { - result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64 - " modules.\n", - (uint64_t)num_modules); - for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) { - if (m_interpreter.WasInterrupted()) - break; - if (DumpModuleSymbolVendor( - result.GetOutputStream(), - target_modules.GetModulePointerAtIndexUnlocked(image_idx))) - num_dumped++; - } - } else { - result.AppendError("the target has no associated executable images"); - result.SetStatus(eReturnStatusFailed); - return false; + if (command.GetArgumentCount() == 0) { + // Dump all sections for all modules images + const ModuleList &target_modules = target->GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); + const size_t num_modules = target_modules.GetSize(); + if (num_modules > 0) { + result.GetOutputStream().Printf("Dumping debug symbols for %" PRIu64 + " modules.\n", + (uint64_t)num_modules); + for (uint32_t image_idx = 0; image_idx < num_modules; ++image_idx) { + if (m_interpreter.WasInterrupted()) + break; + if (DumpModuleSymbolFile( + result.GetOutputStream(), + target_modules.GetModulePointerAtIndexUnlocked(image_idx))) + num_dumped++; } } else { - // Dump specified images (by basename or fullpath) - const char *arg_cstr; - for (int arg_idx = 0; - (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; - ++arg_idx) { - ModuleList module_list; - const size_t num_matches = - FindModulesByName(target, arg_cstr, module_list, true); - if (num_matches > 0) { - for (size_t i = 0; i < num_matches; ++i) { - if (m_interpreter.WasInterrupted()) - break; - Module *module = module_list.GetModulePointerAtIndex(i); - if (module) { - if (DumpModuleSymbolVendor(result.GetOutputStream(), module)) - num_dumped++; - } + result.AppendError("the target has no associated executable images"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + // Dump specified images (by basename or fullpath) + const char *arg_cstr; + for (int arg_idx = 0; + (arg_cstr = command.GetArgumentAtIndex(arg_idx)) != nullptr; + ++arg_idx) { + ModuleList module_list; + const size_t num_matches = + FindModulesByName(target, arg_cstr, module_list, true); + if (num_matches > 0) { + for (size_t i = 0; i < num_matches; ++i) { + if (m_interpreter.WasInterrupted()) + break; + Module *module = module_list.GetModulePointerAtIndex(i); + if (module) { + if (DumpModuleSymbolFile(result.GetOutputStream(), module)) + num_dumped++; } - } else - result.AppendWarningWithFormat( - "Unable to find an image that matches '%s'.\n", arg_cstr); - } + } + } else + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg_cstr); } + } - if (num_dumped > 0) - result.SetStatus(eReturnStatusSuccessFinishResult); - else { - result.AppendError("no matching executable images found"); - result.SetStatus(eReturnStatusFailed); - } + if (num_dumped > 0) + result.SetStatus(eReturnStatusSuccessFinishResult); + else { + result.AppendError("no matching executable images found"); + result.SetStatus(eReturnStatusFailed); } return result.Succeeded(); } }; #pragma mark CommandObjectTargetModulesDumpLineTable +#define LLDB_OPTIONS_target_modules_dump +#include "CommandOptions.inc" // Image debug line table dumping command @@ -2454,19 +2401,7 @@ protected: } llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - static constexpr OptionDefinition g_options[] = { - {LLDB_OPT_SET_ALL, - false, - "verbose", - 'v', - OptionParser::eNoArgument, - nullptr, - {}, - 0, - eArgTypeNone, - "Enable verbose dump."}, - }; - return llvm::makeArrayRef(g_options); + return llvm::makeArrayRef(g_target_modules_dump_options); } bool m_verbose; @@ -2518,10 +2453,11 @@ public: CommandObjectTargetModulesAdd(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "target modules add", "Add a new module to the current target's modules.", - "target modules add [<module>]"), - m_option_group(), - m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', 0, - eArgTypeFilename, "Fullpath to a stand alone debug " + "target modules add [<module>]", + eCommandRequiresTarget), + m_option_group(), m_symbol_file(LLDB_OPT_SET_1, false, "symfile", 's', + 0, eArgTypeFilename, + "Fullpath to a stand alone debug " "symbols file for when debug symbols " "are not in the executable.") { m_option_group.Append(&m_uuid_option_group, LLDB_OPT_SET_ALL, @@ -2534,13 +2470,12 @@ public: Options *GetOptions() override { return &m_option_group; } - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } protected: @@ -2549,125 +2484,117 @@ protected: OptionGroupFile m_symbol_file; bool DoExecute(Args &args, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - bool flush = false; + Target *target = &GetSelectedTarget(); + bool flush = false; - const size_t argc = args.GetArgumentCount(); - if (argc == 0) { - if (m_uuid_option_group.GetOptionValue().OptionWasSet()) { - // We are given a UUID only, go locate the file - ModuleSpec module_spec; - module_spec.GetUUID() = - m_uuid_option_group.GetOptionValue().GetCurrentValue(); - if (m_symbol_file.GetOptionValue().OptionWasSet()) - module_spec.GetSymbolFileSpec() = - m_symbol_file.GetOptionValue().GetCurrentValue(); - if (Symbols::DownloadObjectAndSymbolFile(module_spec)) { - ModuleSP module_sp(target->GetOrCreateModule(module_spec, - true /* notify */)); - if (module_sp) { - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } else { - StreamString strm; - module_spec.GetUUID().Dump(&strm); - if (module_spec.GetFileSpec()) { - if (module_spec.GetSymbolFileSpec()) { - result.AppendErrorWithFormat( - "Unable to create the executable or symbol file with " - "UUID %s with path %s and symbol file %s", - strm.GetData(), - module_spec.GetFileSpec().GetPath().c_str(), - module_spec.GetSymbolFileSpec().GetPath().c_str()); - } else { - result.AppendErrorWithFormat( - "Unable to create the executable or symbol file with " - "UUID %s with path %s", - strm.GetData(), - module_spec.GetFileSpec().GetPath().c_str()); - } - } else { - result.AppendErrorWithFormat("Unable to create the executable " - "or symbol file with UUID %s", - strm.GetData()); - } - result.SetStatus(eReturnStatusFailed); - return false; - } + const size_t argc = args.GetArgumentCount(); + if (argc == 0) { + if (m_uuid_option_group.GetOptionValue().OptionWasSet()) { + // We are given a UUID only, go locate the file + ModuleSpec module_spec; + module_spec.GetUUID() = + m_uuid_option_group.GetOptionValue().GetCurrentValue(); + if (m_symbol_file.GetOptionValue().OptionWasSet()) + module_spec.GetSymbolFileSpec() = + m_symbol_file.GetOptionValue().GetCurrentValue(); + if (Symbols::DownloadObjectAndSymbolFile(module_spec)) { + ModuleSP module_sp( + target->GetOrCreateModule(module_spec, true /* notify */)); + if (module_sp) { + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; } else { StreamString strm; module_spec.GetUUID().Dump(&strm); - result.AppendErrorWithFormat( - "Unable to locate the executable or symbol file with UUID %s", - strm.GetData()); + if (module_spec.GetFileSpec()) { + if (module_spec.GetSymbolFileSpec()) { + result.AppendErrorWithFormat( + "Unable to create the executable or symbol file with " + "UUID %s with path %s and symbol file %s", + strm.GetData(), module_spec.GetFileSpec().GetPath().c_str(), + module_spec.GetSymbolFileSpec().GetPath().c_str()); + } else { + result.AppendErrorWithFormat( + "Unable to create the executable or symbol file with " + "UUID %s with path %s", + strm.GetData(), + module_spec.GetFileSpec().GetPath().c_str()); + } + } else { + result.AppendErrorWithFormat("Unable to create the executable " + "or symbol file with UUID %s", + strm.GetData()); + } result.SetStatus(eReturnStatusFailed); return false; } } else { - result.AppendError( - "one or more executable image paths must be specified"); + StreamString strm; + module_spec.GetUUID().Dump(&strm); + result.AppendErrorWithFormat( + "Unable to locate the executable or symbol file with UUID %s", + strm.GetData()); result.SetStatus(eReturnStatusFailed); return false; } } else { - for (auto &entry : args.entries()) { - if (entry.ref.empty()) - continue; + result.AppendError( + "one or more executable image paths must be specified"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + for (auto &entry : args.entries()) { + if (entry.ref().empty()) + continue; - FileSpec file_spec(entry.ref); - if (FileSystem::Instance().Exists(file_spec)) { - ModuleSpec module_spec(file_spec); - if (m_uuid_option_group.GetOptionValue().OptionWasSet()) - module_spec.GetUUID() = - m_uuid_option_group.GetOptionValue().GetCurrentValue(); - if (m_symbol_file.GetOptionValue().OptionWasSet()) - module_spec.GetSymbolFileSpec() = - m_symbol_file.GetOptionValue().GetCurrentValue(); - if (!module_spec.GetArchitecture().IsValid()) - module_spec.GetArchitecture() = target->GetArchitecture(); - Status error; - ModuleSP module_sp(target->GetOrCreateModule(module_spec, - true /* notify */, &error)); - if (!module_sp) { - const char *error_cstr = error.AsCString(); - if (error_cstr) - result.AppendError(error_cstr); - else - result.AppendErrorWithFormat("unsupported module: %s", - entry.c_str()); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - flush = true; - } - result.SetStatus(eReturnStatusSuccessFinishResult); - } else { - std::string resolved_path = file_spec.GetPath(); + FileSpec file_spec(entry.ref()); + if (FileSystem::Instance().Exists(file_spec)) { + ModuleSpec module_spec(file_spec); + if (m_uuid_option_group.GetOptionValue().OptionWasSet()) + module_spec.GetUUID() = + m_uuid_option_group.GetOptionValue().GetCurrentValue(); + if (m_symbol_file.GetOptionValue().OptionWasSet()) + module_spec.GetSymbolFileSpec() = + m_symbol_file.GetOptionValue().GetCurrentValue(); + if (!module_spec.GetArchitecture().IsValid()) + module_spec.GetArchitecture() = target->GetArchitecture(); + Status error; + ModuleSP module_sp(target->GetOrCreateModule( + module_spec, true /* notify */, &error)); + if (!module_sp) { + const char *error_cstr = error.AsCString(); + if (error_cstr) + result.AppendError(error_cstr); + else + result.AppendErrorWithFormat("unsupported module: %s", + entry.c_str()); result.SetStatus(eReturnStatusFailed); - if (resolved_path != entry.ref) { - result.AppendErrorWithFormat( - "invalid module path '%s' with resolved path '%s'\n", - entry.ref.str().c_str(), resolved_path.c_str()); - break; - } - result.AppendErrorWithFormat("invalid module path '%s'\n", - entry.c_str()); + return false; + } else { + flush = true; + } + result.SetStatus(eReturnStatusSuccessFinishResult); + } else { + std::string resolved_path = file_spec.GetPath(); + result.SetStatus(eReturnStatusFailed); + if (resolved_path != entry.ref()) { + result.AppendErrorWithFormat( + "invalid module path '%s' with resolved path '%s'\n", + entry.ref().str().c_str(), resolved_path.c_str()); break; } + result.AppendErrorWithFormat("invalid module path '%s'\n", + entry.c_str()); + break; } } + } - if (flush) { - ProcessSP process = target->GetProcessSP(); - if (process) - process->Flush(); - } + if (flush) { + ProcessSP process = target->GetProcessSP(); + if (process) + process->Flush(); } return result.Succeeded(); @@ -2679,11 +2606,12 @@ class CommandObjectTargetModulesLoad public: CommandObjectTargetModulesLoad(CommandInterpreter &interpreter) : CommandObjectTargetModulesModuleAutoComplete( - interpreter, "target modules load", "Set the load addresses for " - "one or more sections in a " - "target module.", + interpreter, "target modules load", + "Set the load addresses for one or more sections in a target " + "module.", "target modules load [--file <module> --uuid <uuid>] <sect-name> " - "<address> [<sect-name> <address> ....]"), + "<address> [<sect-name> <address> ....]", + eCommandRequiresTarget), m_option_group(), m_file_option(LLDB_OPT_SET_1, false, "file", 'f', 0, eArgTypeName, "Fullpath or basename for module to load.", ""), @@ -2712,249 +2640,241 @@ public: protected: bool DoExecute(Args &args, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); + Target *target = &GetSelectedTarget(); const bool load = m_load_option.GetOptionValue().GetCurrentValue(); const bool set_pc = m_pc_option.GetOptionValue().GetCurrentValue(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - const size_t argc = args.GetArgumentCount(); - ModuleSpec module_spec; - bool search_using_module_spec = false; - - // Allow "load" option to work without --file or --uuid option. - if (load) { - if (!m_file_option.GetOptionValue().OptionWasSet() && - !m_uuid_option_group.GetOptionValue().OptionWasSet()) { - ModuleList &module_list = target->GetImages(); - if (module_list.GetSize() == 1) { - search_using_module_spec = true; - module_spec.GetFileSpec() = - module_list.GetModuleAtIndex(0)->GetFileSpec(); - } - } - } - if (m_file_option.GetOptionValue().OptionWasSet()) { - search_using_module_spec = true; - const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue(); - const bool use_global_module_list = true; - ModuleList module_list; - const size_t num_matches = FindModulesByName( - target, arg_cstr, module_list, use_global_module_list); - if (num_matches == 1) { + const size_t argc = args.GetArgumentCount(); + ModuleSpec module_spec; + bool search_using_module_spec = false; + + // Allow "load" option to work without --file or --uuid option. + if (load) { + if (!m_file_option.GetOptionValue().OptionWasSet() && + !m_uuid_option_group.GetOptionValue().OptionWasSet()) { + ModuleList &module_list = target->GetImages(); + if (module_list.GetSize() == 1) { + search_using_module_spec = true; module_spec.GetFileSpec() = module_list.GetModuleAtIndex(0)->GetFileSpec(); - } else if (num_matches > 1) { - search_using_module_spec = false; - result.AppendErrorWithFormat( - "more than 1 module matched by name '%s'\n", arg_cstr); - result.SetStatus(eReturnStatusFailed); - } else { - search_using_module_spec = false; - result.AppendErrorWithFormat("no object file for module '%s'\n", - arg_cstr); - result.SetStatus(eReturnStatusFailed); } } + } - if (m_uuid_option_group.GetOptionValue().OptionWasSet()) { - search_using_module_spec = true; - module_spec.GetUUID() = - m_uuid_option_group.GetOptionValue().GetCurrentValue(); + if (m_file_option.GetOptionValue().OptionWasSet()) { + search_using_module_spec = true; + const char *arg_cstr = m_file_option.GetOptionValue().GetCurrentValue(); + const bool use_global_module_list = true; + ModuleList module_list; + const size_t num_matches = FindModulesByName( + target, arg_cstr, module_list, use_global_module_list); + if (num_matches == 1) { + module_spec.GetFileSpec() = + module_list.GetModuleAtIndex(0)->GetFileSpec(); + } else if (num_matches > 1) { + search_using_module_spec = false; + result.AppendErrorWithFormat( + "more than 1 module matched by name '%s'\n", arg_cstr); + result.SetStatus(eReturnStatusFailed); + } else { + search_using_module_spec = false; + result.AppendErrorWithFormat("no object file for module '%s'\n", + arg_cstr); + result.SetStatus(eReturnStatusFailed); } + } - if (search_using_module_spec) { - ModuleList matching_modules; - const size_t num_matches = - target->GetImages().FindModules(module_spec, matching_modules); - - char path[PATH_MAX]; - if (num_matches == 1) { - Module *module = matching_modules.GetModulePointerAtIndex(0); - if (module) { - ObjectFile *objfile = module->GetObjectFile(); - if (objfile) { - SectionList *section_list = module->GetSectionList(); - if (section_list) { - bool changed = false; - if (argc == 0) { - if (m_slide_option.GetOptionValue().OptionWasSet()) { - const addr_t slide = - m_slide_option.GetOptionValue().GetCurrentValue(); - const bool slide_is_offset = true; - module->SetLoadAddress(*target, slide, slide_is_offset, - changed); - } else { - result.AppendError("one or more section name + load " - "address pair must be specified"); - result.SetStatus(eReturnStatusFailed); - return false; - } + if (m_uuid_option_group.GetOptionValue().OptionWasSet()) { + search_using_module_spec = true; + module_spec.GetUUID() = + m_uuid_option_group.GetOptionValue().GetCurrentValue(); + } + + if (search_using_module_spec) { + ModuleList matching_modules; + target->GetImages().FindModules(module_spec, matching_modules); + const size_t num_matches = matching_modules.GetSize(); + + char path[PATH_MAX]; + if (num_matches == 1) { + Module *module = matching_modules.GetModulePointerAtIndex(0); + if (module) { + ObjectFile *objfile = module->GetObjectFile(); + if (objfile) { + SectionList *section_list = module->GetSectionList(); + if (section_list) { + bool changed = false; + if (argc == 0) { + if (m_slide_option.GetOptionValue().OptionWasSet()) { + const addr_t slide = + m_slide_option.GetOptionValue().GetCurrentValue(); + const bool slide_is_offset = true; + module->SetLoadAddress(*target, slide, slide_is_offset, + changed); } else { - if (m_slide_option.GetOptionValue().OptionWasSet()) { - result.AppendError("The \"--slide <offset>\" option can't " - "be used in conjunction with setting " - "section load addresses.\n"); - result.SetStatus(eReturnStatusFailed); - return false; - } + result.AppendError("one or more section name + load " + "address pair must be specified"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + if (m_slide_option.GetOptionValue().OptionWasSet()) { + result.AppendError("The \"--slide <offset>\" option can't " + "be used in conjunction with setting " + "section load addresses.\n"); + result.SetStatus(eReturnStatusFailed); + return false; + } - for (size_t i = 0; i < argc; i += 2) { - const char *sect_name = args.GetArgumentAtIndex(i); - const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1); - if (sect_name && load_addr_cstr) { - ConstString const_sect_name(sect_name); - bool success = false; - addr_t load_addr = StringConvert::ToUInt64( - load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success); - if (success) { - SectionSP section_sp( - section_list->FindSectionByName(const_sect_name)); - if (section_sp) { - if (section_sp->IsThreadSpecific()) { - result.AppendErrorWithFormat( - "thread specific sections are not yet " - "supported (section '%s')\n", - sect_name); - result.SetStatus(eReturnStatusFailed); - break; - } else { - if (target->GetSectionLoadList() - .SetSectionLoadAddress(section_sp, - load_addr)) - changed = true; - result.AppendMessageWithFormat( - "section '%s' loaded at 0x%" PRIx64 "\n", - sect_name, load_addr); - } - } else { - result.AppendErrorWithFormat("no section found that " - "matches the section " - "name '%s'\n", - sect_name); + for (size_t i = 0; i < argc; i += 2) { + const char *sect_name = args.GetArgumentAtIndex(i); + const char *load_addr_cstr = args.GetArgumentAtIndex(i + 1); + if (sect_name && load_addr_cstr) { + ConstString const_sect_name(sect_name); + bool success = false; + addr_t load_addr = StringConvert::ToUInt64( + load_addr_cstr, LLDB_INVALID_ADDRESS, 0, &success); + if (success) { + SectionSP section_sp( + section_list->FindSectionByName(const_sect_name)); + if (section_sp) { + if (section_sp->IsThreadSpecific()) { + result.AppendErrorWithFormat( + "thread specific sections are not yet " + "supported (section '%s')\n", + sect_name); result.SetStatus(eReturnStatusFailed); break; + } else { + if (target->GetSectionLoadList() + .SetSectionLoadAddress(section_sp, load_addr)) + changed = true; + result.AppendMessageWithFormat( + "section '%s' loaded at 0x%" PRIx64 "\n", + sect_name, load_addr); } } else { - result.AppendErrorWithFormat( - "invalid load address string '%s'\n", - load_addr_cstr); + result.AppendErrorWithFormat("no section found that " + "matches the section " + "name '%s'\n", + sect_name); result.SetStatus(eReturnStatusFailed); break; } } else { - if (sect_name) - result.AppendError("section names must be followed by " - "a load address.\n"); - else - result.AppendError("one or more section name + load " - "address pair must be specified.\n"); + result.AppendErrorWithFormat( + "invalid load address string '%s'\n", load_addr_cstr); result.SetStatus(eReturnStatusFailed); break; } + } else { + if (sect_name) + result.AppendError("section names must be followed by " + "a load address.\n"); + else + result.AppendError("one or more section name + load " + "address pair must be specified.\n"); + result.SetStatus(eReturnStatusFailed); + break; } } + } - if (changed) { - target->ModulesDidLoad(matching_modules); - Process *process = m_exe_ctx.GetProcessPtr(); - if (process) - process->Flush(); + if (changed) { + target->ModulesDidLoad(matching_modules); + Process *process = m_exe_ctx.GetProcessPtr(); + if (process) + process->Flush(); + } + if (load) { + ProcessSP process = target->CalculateProcess(); + Address file_entry = objfile->GetEntryPointAddress(); + if (!process) { + result.AppendError("No process"); + return false; } - if (load) { - ProcessSP process = target->CalculateProcess(); - Address file_entry = objfile->GetEntryPointAddress(); - if (!process) { - result.AppendError("No process"); - return false; - } - if (set_pc && !file_entry.IsValid()) { - result.AppendError("No entry address in object file"); - return false; - } - std::vector<ObjectFile::LoadableData> loadables( - objfile->GetLoadableData(*target)); - if (loadables.size() == 0) { - result.AppendError("No loadable sections"); - return false; - } - Status error = process->WriteObjectFile(std::move(loadables)); - if (error.Fail()) { - result.AppendError(error.AsCString()); - return false; - } - if (set_pc) { - ThreadList &thread_list = process->GetThreadList(); - RegisterContextSP reg_context( - thread_list.GetSelectedThread()->GetRegisterContext()); - addr_t file_entry_addr = file_entry.GetLoadAddress(target); - if (!reg_context->SetPC(file_entry_addr)) { - result.AppendErrorWithFormat("failed to set PC value to " - "0x%" PRIx64 "\n", - file_entry_addr); - result.SetStatus(eReturnStatusFailed); - } + if (set_pc && !file_entry.IsValid()) { + result.AppendError("No entry address in object file"); + return false; + } + std::vector<ObjectFile::LoadableData> loadables( + objfile->GetLoadableData(*target)); + if (loadables.size() == 0) { + result.AppendError("No loadable sections"); + return false; + } + Status error = process->WriteObjectFile(std::move(loadables)); + if (error.Fail()) { + result.AppendError(error.AsCString()); + return false; + } + if (set_pc) { + ThreadList &thread_list = process->GetThreadList(); + RegisterContextSP reg_context( + thread_list.GetSelectedThread()->GetRegisterContext()); + addr_t file_entry_addr = file_entry.GetLoadAddress(target); + if (!reg_context->SetPC(file_entry_addr)) { + result.AppendErrorWithFormat("failed to set PC value to " + "0x%" PRIx64 "\n", + file_entry_addr); + result.SetStatus(eReturnStatusFailed); } } - } else { - module->GetFileSpec().GetPath(path, sizeof(path)); - result.AppendErrorWithFormat( - "no sections in object file '%s'\n", path); - result.SetStatus(eReturnStatusFailed); } } else { module->GetFileSpec().GetPath(path, sizeof(path)); - result.AppendErrorWithFormat("no object file for module '%s'\n", + result.AppendErrorWithFormat("no sections in object file '%s'\n", path); result.SetStatus(eReturnStatusFailed); } } else { - FileSpec *module_spec_file = module_spec.GetFileSpecPtr(); - if (module_spec_file) { - module_spec_file->GetPath(path, sizeof(path)); - result.AppendErrorWithFormat("invalid module '%s'.\n", path); - } else - result.AppendError("no module spec"); + module->GetFileSpec().GetPath(path, sizeof(path)); + result.AppendErrorWithFormat("no object file for module '%s'\n", + path); result.SetStatus(eReturnStatusFailed); } } else { - std::string uuid_str; + FileSpec *module_spec_file = module_spec.GetFileSpecPtr(); + if (module_spec_file) { + module_spec_file->GetPath(path, sizeof(path)); + result.AppendErrorWithFormat("invalid module '%s'.\n", path); + } else + result.AppendError("no module spec"); + result.SetStatus(eReturnStatusFailed); + } + } else { + std::string uuid_str; - if (module_spec.GetFileSpec()) - module_spec.GetFileSpec().GetPath(path, sizeof(path)); - else - path[0] = '\0'; + if (module_spec.GetFileSpec()) + module_spec.GetFileSpec().GetPath(path, sizeof(path)); + else + path[0] = '\0'; - if (module_spec.GetUUIDPtr()) - uuid_str = module_spec.GetUUID().GetAsString(); - if (num_matches > 1) { - result.AppendErrorWithFormat( - "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "", - path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str()); - for (size_t i = 0; i < num_matches; ++i) { - if (matching_modules.GetModulePointerAtIndex(i) - ->GetFileSpec() - .GetPath(path, sizeof(path))) - result.AppendMessageWithFormat("%s\n", path); - } - } else { - result.AppendErrorWithFormat( - "no modules were found that match%s%s%s%s.\n", - path[0] ? " file=" : "", path, - !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str()); + if (module_spec.GetUUIDPtr()) + uuid_str = module_spec.GetUUID().GetAsString(); + if (num_matches > 1) { + result.AppendErrorWithFormat( + "multiple modules match%s%s%s%s:\n", path[0] ? " file=" : "", + path, !uuid_str.empty() ? " uuid=" : "", uuid_str.c_str()); + for (size_t i = 0; i < num_matches; ++i) { + if (matching_modules.GetModulePointerAtIndex(i) + ->GetFileSpec() + .GetPath(path, sizeof(path))) + result.AppendMessageWithFormat("%s\n", path); } - result.SetStatus(eReturnStatusFailed); + } else { + result.AppendErrorWithFormat( + "no modules were found that match%s%s%s%s.\n", + path[0] ? " file=" : "", path, !uuid_str.empty() ? " uuid=" : "", + uuid_str.c_str()); } - } else { - result.AppendError("either the \"--file <module>\" or the \"--uuid " - "<uuid>\" option must be specified.\n"); result.SetStatus(eReturnStatusFailed); - return false; } + } else { + result.AppendError("either the \"--file <module>\" or the \"--uuid " + "<uuid>\" option must be specified.\n"); + result.SetStatus(eReturnStatusFailed); + return false; } return result.Succeeded(); } @@ -2968,26 +2888,8 @@ protected: }; // List images with associated information - -static constexpr OptionDefinition g_target_modules_list_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Display the image at this address." }, - { LLDB_OPT_SET_1, false, "arch", 'A', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the architecture when listing images." }, - { LLDB_OPT_SET_1, false, "triple", 't', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the triple when listing images." }, - { LLDB_OPT_SET_1, false, "header", 'h', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the image base address as a load address if debugging, a file address otherwise." }, - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the image load address offset from the base file address (the slide amount)." }, - { LLDB_OPT_SET_1, false, "uuid", 'u', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the UUID when listing images." }, - { LLDB_OPT_SET_1, false, "fullpath", 'f', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the fullpath to the image object file." }, - { LLDB_OPT_SET_1, false, "directory", 'd', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the directory with optional width for the image object file." }, - { LLDB_OPT_SET_1, false, "basename", 'b', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the basename with optional width for the image object file." }, - { LLDB_OPT_SET_1, false, "symfile", 's', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the fullpath to the image symbol file with optional width." }, - { LLDB_OPT_SET_1, false, "symfile-unique", 'S', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the symbol file with optional width only if it is different from the executable object file." }, - { LLDB_OPT_SET_1, false, "mod-time", 'm', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the modification time with optional width of the module." }, - { LLDB_OPT_SET_1, false, "ref-count", 'r', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeWidth, "Display the reference count if the module is still in the shared module cache." }, - { LLDB_OPT_SET_1, false, "pointer", 'p', OptionParser::eOptionalArgument, nullptr, {}, 0, eArgTypeNone, "Display the module pointer." }, - { LLDB_OPT_SET_1, false, "global", 'g', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Display the modules from the global module list, not just the current target." } - // clang-format on -}; +#define LLDB_OPTIONS_target_modules_list +#include "CommandOptions.inc" class CommandObjectTargetModulesList : public CommandObjectParsed { public: @@ -3282,9 +3184,9 @@ protected: case 's': case 'S': { - const SymbolVendor *symbol_vendor = module->GetSymbolVendor(); - if (symbol_vendor) { - const FileSpec symfile_spec = symbol_vendor->GetMainFileSpec(); + if (const SymbolFile *symbol_file = module->GetSymbolFile()) { + const FileSpec symfile_spec = + symbol_file->GetObjectFile()->GetFileSpec(); if (format_char == 'S') { // Dump symbol file only if different from module file if (!symfile_spec || symfile_spec == module->GetFileSpec()) { @@ -3332,13 +3234,8 @@ protected: #pragma mark CommandObjectTargetModulesShowUnwind // Lookup unwind information in images - -static constexpr OptionDefinition g_target_modules_show_unwind_options[] = { - // clang-format off - { LLDB_OPT_SET_1, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionName, "Show unwind instructions for a function or symbol name." }, - { LLDB_OPT_SET_2, false, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Show unwind instructions for a function or symbol containing an address" } - // clang-format on -}; +#define LLDB_OPTIONS_target_modules_show_unwind +#include "CommandOptions.inc" class CommandObjectTargetModulesShowUnwind : public CommandObjectParsed { public: @@ -3383,8 +3280,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized option %c.", short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -3453,7 +3349,7 @@ protected: if (m_options.m_type == eLookupTypeFunctionOrSymbol) { ConstString function_name(m_options.m_str.c_str()); target->GetImages().FindFunctions(function_name, eFunctionNameTypeAuto, - true, false, true, sc_list); + true, false, sc_list); } else if (m_options.m_type == eLookupTypeAddress && target) { Address addr; if (target->GetSectionLoadList().ResolveLoadAddress(m_options.m_addr, @@ -3546,6 +3442,25 @@ protected: result.GetOutputStream().Printf("\n"); } + UnwindPlanSP of_unwind_sp = + func_unwinders_sp->GetObjectFileUnwindPlan(*target); + if (of_unwind_sp) { + result.GetOutputStream().Printf("object file UnwindPlan:\n"); + of_unwind_sp->Dump(result.GetOutputStream(), thread.get(), + LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + + UnwindPlanSP of_unwind_augmented_sp = + func_unwinders_sp->GetObjectFileAugmentedUnwindPlan(*target, + *thread); + if (of_unwind_augmented_sp) { + result.GetOutputStream().Printf("object file augmented UnwindPlan:\n"); + of_unwind_augmented_sp->Dump(result.GetOutputStream(), thread.get(), + LLDB_INVALID_ADDRESS); + result.GetOutputStream().Printf("\n"); + } + UnwindPlanSP ehframe_sp = func_unwinders_sp->GetEHFrameUnwindPlan(*target); if (ehframe_sp) { @@ -3643,24 +3558,8 @@ protected: }; // Lookup information in images - -static constexpr OptionDefinition g_target_modules_lookup_options[] = { - // clang-format off - { LLDB_OPT_SET_1, true, "address", 'a', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeAddressOrExpression, "Lookup an address in one or more target modules." }, - { LLDB_OPT_SET_1, false, "offset", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOffset, "When looking up an address subtract <offset> from any addresses before doing the lookup." }, - /* FIXME: re-enable regex for types when the LookupTypeInModule actually uses the regex option: | LLDB_OPT_SET_6 */ - { LLDB_OPT_SET_2 | LLDB_OPT_SET_4 | LLDB_OPT_SET_5, false, "regex", 'r', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "The <name> argument for name lookups are regular expressions." }, - { LLDB_OPT_SET_2, true, "symbol", 's', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeSymbol, "Lookup a symbol by name in the symbol tables in one or more target modules." }, - { LLDB_OPT_SET_3, true, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFilename, "Lookup a file by fullpath or basename in one or more target modules." }, - { LLDB_OPT_SET_3, false, "line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Lookup a line number in a file (must be used in conjunction with --file)." }, - { LLDB_OPT_SET_FROM_TO(3,5), false, "no-inlines", 'i', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Ignore inline entries (must be used in conjunction with --file or --function)." }, - { LLDB_OPT_SET_4, true, "function", 'F', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionName, "Lookup a function by name in the debug symbols in one or more target modules." }, - { LLDB_OPT_SET_5, true, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeFunctionOrSymbol, "Lookup a function or symbol by name in one or more target modules." }, - { LLDB_OPT_SET_6, true, "type", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "Lookup a type by name in the debug symbols in one or more target modules." }, - { LLDB_OPT_SET_ALL, false, "verbose", 'v', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Enable verbose lookup information." }, - { LLDB_OPT_SET_ALL, false, "all", 'A', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "Print all matches, not just the best match, if a best match is available." }, - // clang-format on -}; +#define LLDB_OPTIONS_target_modules_lookup +#include "CommandOptions.inc" class CommandObjectTargetModulesLookup : public CommandObjectParsed { public: @@ -3749,6 +3648,8 @@ public: case 'r': m_use_regex = true; break; + default: + llvm_unreachable("Unimplemented option"); } return error; @@ -3935,91 +3836,82 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } else { - bool syntax_error = false; - uint32_t i; - uint32_t num_successful_lookups = 0; - uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); - result.GetOutputStream().SetAddressByteSize(addr_byte_size); - result.GetErrorStream().SetAddressByteSize(addr_byte_size); - // Dump all sections for all modules images - - if (command.GetArgumentCount() == 0) { - ModuleSP current_module; + Target *target = &GetSelectedTarget(); + bool syntax_error = false; + uint32_t i; + uint32_t num_successful_lookups = 0; + uint32_t addr_byte_size = target->GetArchitecture().GetAddressByteSize(); + result.GetOutputStream().SetAddressByteSize(addr_byte_size); + result.GetErrorStream().SetAddressByteSize(addr_byte_size); + // Dump all sections for all modules images - // Where it is possible to look in the current symbol context first, - // try that. If this search was successful and --all was not passed, - // don't print anything else. - if (LookupHere(m_interpreter, result, syntax_error)) { - result.GetOutputStream().EOL(); - num_successful_lookups++; - if (!m_options.m_print_all) { - result.SetStatus(eReturnStatusSuccessFinishResult); - return result.Succeeded(); - } + if (command.GetArgumentCount() == 0) { + ModuleSP current_module; + + // Where it is possible to look in the current symbol context first, + // try that. If this search was successful and --all was not passed, + // don't print anything else. + if (LookupHere(m_interpreter, result, syntax_error)) { + result.GetOutputStream().EOL(); + num_successful_lookups++; + if (!m_options.m_print_all) { + result.SetStatus(eReturnStatusSuccessFinishResult); + return result.Succeeded(); } + } - // Dump all sections for all other modules + // Dump all sections for all other modules - const ModuleList &target_modules = target->GetImages(); - std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); - const size_t num_modules = target_modules.GetSize(); - if (num_modules > 0) { - for (i = 0; i < num_modules && !syntax_error; ++i) { - Module *module_pointer = - target_modules.GetModulePointerAtIndexUnlocked(i); - - if (module_pointer != current_module.get() && - LookupInModule( - m_interpreter, - target_modules.GetModulePointerAtIndexUnlocked(i), result, - syntax_error)) { - result.GetOutputStream().EOL(); - num_successful_lookups++; - } + const ModuleList &target_modules = target->GetImages(); + std::lock_guard<std::recursive_mutex> guard(target_modules.GetMutex()); + const size_t num_modules = target_modules.GetSize(); + if (num_modules > 0) { + for (i = 0; i < num_modules && !syntax_error; ++i) { + Module *module_pointer = + target_modules.GetModulePointerAtIndexUnlocked(i); + + if (module_pointer != current_module.get() && + LookupInModule(m_interpreter, + target_modules.GetModulePointerAtIndexUnlocked(i), + result, syntax_error)) { + result.GetOutputStream().EOL(); + num_successful_lookups++; } - } else { - result.AppendError("the target has no associated executable images"); - result.SetStatus(eReturnStatusFailed); - return false; } } else { - // Dump specified images (by basename or fullpath) - const char *arg_cstr; - for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr && - !syntax_error; - ++i) { - ModuleList module_list; - const size_t num_matches = - FindModulesByName(target, arg_cstr, module_list, false); - if (num_matches > 0) { - for (size_t j = 0; j < num_matches; ++j) { - Module *module = module_list.GetModulePointerAtIndex(j); - if (module) { - if (LookupInModule(m_interpreter, module, result, - syntax_error)) { - result.GetOutputStream().EOL(); - num_successful_lookups++; - } + result.AppendError("the target has no associated executable images"); + result.SetStatus(eReturnStatusFailed); + return false; + } + } else { + // Dump specified images (by basename or fullpath) + const char *arg_cstr; + for (i = 0; (arg_cstr = command.GetArgumentAtIndex(i)) != nullptr && + !syntax_error; + ++i) { + ModuleList module_list; + const size_t num_matches = + FindModulesByName(target, arg_cstr, module_list, false); + if (num_matches > 0) { + for (size_t j = 0; j < num_matches; ++j) { + Module *module = module_list.GetModulePointerAtIndex(j); + if (module) { + if (LookupInModule(m_interpreter, module, result, syntax_error)) { + result.GetOutputStream().EOL(); + num_successful_lookups++; } } - } else - result.AppendWarningWithFormat( - "Unable to find an image that matches '%s'.\n", arg_cstr); - } + } + } else + result.AppendWarningWithFormat( + "Unable to find an image that matches '%s'.\n", arg_cstr); } - - if (num_successful_lookups > 0) - result.SetStatus(eReturnStatusSuccessFinishResult); - else - result.SetStatus(eReturnStatusFailed); } + + if (num_successful_lookups > 0) + result.SetStatus(eReturnStatusSuccessFinishResult); + else + result.SetStatus(eReturnStatusFailed); return result.Succeeded(); } @@ -4129,13 +4021,12 @@ public: ~CommandObjectTargetSymbolsAdd() override = default; - int HandleArgumentCompletion( - CompletionRequest &request, - OptionElementVector &opt_element_vector) override { + void + HandleArgumentCompletion(CompletionRequest &request, + OptionElementVector &opt_element_vector) override { CommandCompletions::InvokeCommonCompletionCallbacks( GetCommandInterpreter(), CommandCompletions::eDiskFileCompletion, request, nullptr); - return request.GetNumberOfMatches(); } Options *GetOptions() override { return &m_option_group; } @@ -4173,8 +4064,9 @@ protected: // It has a UUID, look for this UUID in the target modules ModuleSpec symfile_uuid_module_spec; symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID(); - num_matches = target->GetImages().FindModules( - symfile_uuid_module_spec, matching_module_list); + target->GetImages().FindModules(symfile_uuid_module_spec, + matching_module_list); + num_matches = matching_module_list.GetSize(); } } @@ -4192,8 +4084,9 @@ protected: ModuleSpec symfile_uuid_module_spec; symfile_uuid_module_spec.GetUUID() = symfile_module_spec.GetUUID(); - num_matches = target->GetImages().FindModules( - symfile_uuid_module_spec, matching_module_list); + target->GetImages().FindModules(symfile_uuid_module_spec, + matching_module_list); + num_matches = matching_module_list.GetSize(); } } } @@ -4202,9 +4095,10 @@ protected: // Just try to match up the file by basename if we have no matches at // this point - if (num_matches == 0) - num_matches = - target->GetImages().FindModules(module_spec, matching_module_list); + if (num_matches == 0) { + target->GetImages().FindModules(module_spec, matching_module_list); + num_matches = matching_module_list.GetSize(); + } while (num_matches == 0) { ConstString filename_no_extension( @@ -4221,8 +4115,8 @@ protected: // Replace basename with one less extension module_spec.GetFileSpec().GetFilename() = filename_no_extension; - num_matches = - target->GetImages().FindModules(module_spec, matching_module_list); + target->GetImages().FindModules(module_spec, matching_module_list); + num_matches = matching_module_list.GetSize(); } if (num_matches > 1) { @@ -4238,48 +4132,44 @@ protected: // decides to create it! module_sp->SetSymbolFileFileSpec(symbol_fspec); - SymbolVendor *symbol_vendor = - module_sp->GetSymbolVendor(true, &result.GetErrorStream()); - if (symbol_vendor) { - SymbolFile *symbol_file = symbol_vendor->GetSymbolFile(); - - if (symbol_file) { - ObjectFile *object_file = symbol_file->GetObjectFile(); - - if (object_file && object_file->GetFileSpec() == symbol_fspec) { - // Provide feedback that the symfile has been successfully added. - const FileSpec &module_fs = module_sp->GetFileSpec(); - result.AppendMessageWithFormat( - "symbol file '%s' has been added to '%s'\n", symfile_path, - module_fs.GetPath().c_str()); - - // Let clients know something changed in the module if it is - // currently loaded - ModuleList module_list; - module_list.Append(module_sp); - target->SymbolsDidLoad(module_list); - - // Make sure we load any scripting resources that may be embedded - // in the debug info files in case the platform supports that. - Status error; - StreamString feedback_stream; - module_sp->LoadScriptingResourceInTarget(target, error, - &feedback_stream); - if (error.Fail() && error.AsCString()) - result.AppendWarningWithFormat( - "unable to load scripting data for module %s - error " - "reported was %s", - module_sp->GetFileSpec() - .GetFileNameStrippingExtension() - .GetCString(), - error.AsCString()); - else if (feedback_stream.GetSize()) - result.AppendWarningWithFormat("%s", feedback_stream.GetData()); - - flush = true; - result.SetStatus(eReturnStatusSuccessFinishResult); - return true; - } + SymbolFile *symbol_file = + module_sp->GetSymbolFile(true, &result.GetErrorStream()); + if (symbol_file) { + ObjectFile *object_file = symbol_file->GetObjectFile(); + + if (object_file && object_file->GetFileSpec() == symbol_fspec) { + // Provide feedback that the symfile has been successfully added. + const FileSpec &module_fs = module_sp->GetFileSpec(); + result.AppendMessageWithFormat( + "symbol file '%s' has been added to '%s'\n", symfile_path, + module_fs.GetPath().c_str()); + + // Let clients know something changed in the module if it is + // currently loaded + ModuleList module_list; + module_list.Append(module_sp); + target->SymbolsDidLoad(module_list); + + // Make sure we load any scripting resources that may be embedded + // in the debug info files in case the platform supports that. + Status error; + StreamString feedback_stream; + module_sp->LoadScriptingResourceInTarget(target, error, + &feedback_stream); + if (error.Fail() && error.AsCString()) + result.AppendWarningWithFormat( + "unable to load scripting data for module %s - error " + "reported was %s", + module_sp->GetFileSpec() + .GetFileNameStrippingExtension() + .GetCString(), + error.AsCString()); + else if (feedback_stream.GetSize()) + result.AppendWarningWithFormat("%s", feedback_stream.GetData()); + + flush = true; + result.SetStatus(eReturnStatusSuccessFinishResult); + return true; } } // Clear the symbol file spec if anything went wrong @@ -4430,9 +4320,9 @@ protected: PlatformSP platform_sp(target->GetPlatform()); for (auto &entry : args.entries()) { - if (!entry.ref.empty()) { + if (!entry.ref().empty()) { auto &symbol_file_spec = module_spec.GetSymbolFileSpec(); - symbol_file_spec.SetFile(entry.ref, FileSpec::Style::native); + symbol_file_spec.SetFile(entry.ref(), FileSpec::Style::native); FileSystem::Instance().Resolve(symbol_file_spec); if (file_option_set) { module_spec.GetFileSpec() = @@ -4456,7 +4346,7 @@ protected: } else { std::string resolved_symfile_path = module_spec.GetSymbolFileSpec().GetPath(); - if (resolved_symfile_path != entry.ref) { + if (resolved_symfile_path != entry.ref()) { result.AppendErrorWithFormat( "invalid module path '%s' with resolved path '%s'\n", entry.c_str(), resolved_symfile_path.c_str()); @@ -4511,23 +4401,8 @@ private: #pragma mark CommandObjectTargetStopHookAdd // CommandObjectTargetStopHookAdd - -static constexpr OptionDefinition g_target_stop_hook_add_options[] = { - // clang-format off - { LLDB_OPT_SET_ALL, false, "one-liner", 'o', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeOneLiner, "Add a command for the stop hook. Can be specified more than once, and commands will be run in the order they appear." }, - { LLDB_OPT_SET_ALL, false, "shlib", 's', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eModuleCompletion, eArgTypeShlibName, "Set the module within which the stop-hook is to be run." }, - { LLDB_OPT_SET_ALL, false, "thread-index", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadIndex, "The stop hook is run only for the thread whose index matches this argument." }, - { LLDB_OPT_SET_ALL, false, "thread-id", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadID, "The stop hook is run only for the thread whose TID matches this argument." }, - { LLDB_OPT_SET_ALL, false, "thread-name", 'T', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeThreadName, "The stop hook is run only for the thread whose thread name matches this argument." }, - { LLDB_OPT_SET_ALL, false, "queue-name", 'q', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeQueueName, "The stop hook is run only for threads in the queue whose name is given by this argument." }, - { LLDB_OPT_SET_1, false, "file", 'f', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSourceFileCompletion, eArgTypeFilename, "Specify the source file within which the stop-hook is to be run." }, - { LLDB_OPT_SET_1, false, "start-line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Set the start of the line range for which the stop-hook is to be run." }, - { LLDB_OPT_SET_1, false, "end-line", 'e', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLineNum, "Set the end of the line range for which the stop-hook is to be run." }, - { LLDB_OPT_SET_2, false, "classname", 'c', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeClassName, "Specify the class within which the stop-hook is to be run." }, - { LLDB_OPT_SET_3, false, "name", 'n', OptionParser::eRequiredArgument, nullptr, {}, CommandCompletions::eSymbolCompletion, eArgTypeFunctionName, "Set the function name within which the stop hook will be run." }, - { LLDB_OPT_SET_ALL, false, "auto-continue",'G', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeBoolean, "The breakpoint will auto-continue after running its commands." }, - // clang-format on -}; +#define LLDB_OPTIONS_target_stop_hook_add +#include "CommandOptions.inc" class CommandObjectTargetStopHookAdd : public CommandObjectParsed, public IOHandlerDelegateMultiline { @@ -4636,8 +4511,7 @@ public: break; default: - error.SetErrorStringWithFormat("unrecognized option %c.", short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -4698,7 +4572,7 @@ public: protected: void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString( "Enter your stop hook command(s). Type 'DONE' to end.\n"); @@ -4710,7 +4584,7 @@ protected: std::string &line) override { if (m_stop_hook_sp) { if (line.empty()) { - StreamFileSP error_sp(io_handler.GetErrorStreamFile()); + StreamFileSP error_sp(io_handler.GetErrorStreamFileSP()); if (error_sp) { error_sp->Printf("error: stop hook #%" PRIu64 " aborted, no commands.\n", @@ -4722,7 +4596,7 @@ protected: target->RemoveStopHookByID(m_stop_hook_sp->GetID()); } else { m_stop_hook_sp->GetCommandPointer()->SplitIntoLines(line); - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp) { output_sp->Printf("Stop hook #%" PRIu64 " added.\n", m_stop_hook_sp->GetID()); @@ -4737,52 +4611,50 @@ protected: bool DoExecute(Args &command, CommandReturnObject &result) override { m_stop_hook_sp.reset(); - Target *target = GetSelectedOrDummyTarget(); - if (target) { - Target::StopHookSP new_hook_sp = target->CreateStopHook(); - - // First step, make the specifier. - std::unique_ptr<SymbolContextSpecifier> specifier_up; - if (m_options.m_sym_ctx_specified) { - specifier_up.reset( - new SymbolContextSpecifier(GetDebugger().GetSelectedTarget())); - - if (!m_options.m_module_name.empty()) { - specifier_up->AddSpecification( - m_options.m_module_name.c_str(), - SymbolContextSpecifier::eModuleSpecified); - } + Target &target = GetSelectedOrDummyTarget(); + Target::StopHookSP new_hook_sp = target.CreateStopHook(); - if (!m_options.m_class_name.empty()) { - specifier_up->AddSpecification( - m_options.m_class_name.c_str(), - SymbolContextSpecifier::eClassOrNamespaceSpecified); - } + // First step, make the specifier. + std::unique_ptr<SymbolContextSpecifier> specifier_up; + if (m_options.m_sym_ctx_specified) { + specifier_up.reset( + new SymbolContextSpecifier(GetDebugger().GetSelectedTarget())); - if (!m_options.m_file_name.empty()) { - specifier_up->AddSpecification( - m_options.m_file_name.c_str(), - SymbolContextSpecifier::eFileSpecified); - } + if (!m_options.m_module_name.empty()) { + specifier_up->AddSpecification( + m_options.m_module_name.c_str(), + SymbolContextSpecifier::eModuleSpecified); + } - if (m_options.m_line_start != 0) { - specifier_up->AddLineSpecification( - m_options.m_line_start, - SymbolContextSpecifier::eLineStartSpecified); - } + if (!m_options.m_class_name.empty()) { + specifier_up->AddSpecification( + m_options.m_class_name.c_str(), + SymbolContextSpecifier::eClassOrNamespaceSpecified); + } - if (m_options.m_line_end != UINT_MAX) { - specifier_up->AddLineSpecification( - m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified); - } + if (!m_options.m_file_name.empty()) { + specifier_up->AddSpecification(m_options.m_file_name.c_str(), + SymbolContextSpecifier::eFileSpecified); + } - if (!m_options.m_function_name.empty()) { - specifier_up->AddSpecification( - m_options.m_function_name.c_str(), - SymbolContextSpecifier::eFunctionSpecified); - } + if (m_options.m_line_start != 0) { + specifier_up->AddLineSpecification( + m_options.m_line_start, + SymbolContextSpecifier::eLineStartSpecified); } + if (m_options.m_line_end != UINT_MAX) { + specifier_up->AddLineSpecification( + m_options.m_line_end, SymbolContextSpecifier::eLineEndSpecified); + } + + if (!m_options.m_function_name.empty()) { + specifier_up->AddSpecification( + m_options.m_function_name.c_str(), + SymbolContextSpecifier::eFunctionSpecified); + } + } + if (specifier_up) new_hook_sp->SetSpecifier(specifier_up.release()); @@ -4825,10 +4697,6 @@ protected: // into our IOHandlerDelegate functions } result.SetStatus(eReturnStatusSuccessFinishNoResult); - } else { - result.AppendError("invalid target\n"); - result.SetStatus(eReturnStatusFailed); - } return result.Succeeded(); } @@ -4853,43 +4721,37 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (target) { - // FIXME: see if we can use the breakpoint id style parser? - size_t num_args = command.GetArgumentCount(); - if (num_args == 0) { - if (!m_interpreter.Confirm("Delete all stop hooks?", true)) { + Target &target = GetSelectedOrDummyTarget(); + // FIXME: see if we can use the breakpoint id style parser? + size_t num_args = command.GetArgumentCount(); + if (num_args == 0) { + if (!m_interpreter.Confirm("Delete all stop hooks?", true)) { + result.SetStatus(eReturnStatusFailed); + return false; + } else { + target.RemoveAllStopHooks(); + } + } else { + bool success; + for (size_t i = 0; i < num_args; i++) { + lldb::user_id_t user_id = StringConvert::ToUInt32( + command.GetArgumentAtIndex(i), 0, 0, &success); + if (!success) { + result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n", + command.GetArgumentAtIndex(i)); result.SetStatus(eReturnStatusFailed); return false; - } else { - target->RemoveAllStopHooks(); } - } else { - bool success; - for (size_t i = 0; i < num_args; i++) { - lldb::user_id_t user_id = StringConvert::ToUInt32( - command.GetArgumentAtIndex(i), 0, 0, &success); - if (!success) { - result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n", - command.GetArgumentAtIndex(i)); - result.SetStatus(eReturnStatusFailed); - return false; - } - success = target->RemoveStopHookByID(user_id); - if (!success) { - result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n", - command.GetArgumentAtIndex(i)); - result.SetStatus(eReturnStatusFailed); - return false; - } + success = target.RemoveStopHookByID(user_id); + if (!success) { + result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n", + command.GetArgumentAtIndex(i)); + result.SetStatus(eReturnStatusFailed); + return false; } } - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } else { - result.AppendError("invalid target\n"); - result.SetStatus(eReturnStatusFailed); } - + result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); } }; @@ -4910,38 +4772,33 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (target) { - // FIXME: see if we can use the breakpoint id style parser? - size_t num_args = command.GetArgumentCount(); - bool success; + Target &target = GetSelectedOrDummyTarget(); + // FIXME: see if we can use the breakpoint id style parser? + size_t num_args = command.GetArgumentCount(); + bool success; - if (num_args == 0) { - target->SetAllStopHooksActiveState(m_enable); - } else { - for (size_t i = 0; i < num_args; i++) { - lldb::user_id_t user_id = StringConvert::ToUInt32( - command.GetArgumentAtIndex(i), 0, 0, &success); - if (!success) { - result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n", - command.GetArgumentAtIndex(i)); - result.SetStatus(eReturnStatusFailed); - return false; - } - success = target->SetStopHookActiveStateByID(user_id, m_enable); - if (!success) { - result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n", - command.GetArgumentAtIndex(i)); - result.SetStatus(eReturnStatusFailed); - return false; - } + if (num_args == 0) { + target.SetAllStopHooksActiveState(m_enable); + } else { + for (size_t i = 0; i < num_args; i++) { + lldb::user_id_t user_id = StringConvert::ToUInt32( + command.GetArgumentAtIndex(i), 0, 0, &success); + if (!success) { + result.AppendErrorWithFormat("invalid stop hook id: \"%s\".\n", + command.GetArgumentAtIndex(i)); + result.SetStatus(eReturnStatusFailed); + return false; + } + success = target.SetStopHookActiveStateByID(user_id, m_enable); + if (!success) { + result.AppendErrorWithFormat("unknown stop hook id: \"%s\".\n", + command.GetArgumentAtIndex(i)); + result.SetStatus(eReturnStatusFailed); + return false; } } - result.SetStatus(eReturnStatusSuccessFinishNoResult); - } else { - result.AppendError("invalid target\n"); - result.SetStatus(eReturnStatusFailed); } + result.SetStatus(eReturnStatusSuccessFinishNoResult); return result.Succeeded(); } @@ -4964,19 +4821,14 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetSelectedOrDummyTarget(); - if (!target) { - result.AppendError("invalid target\n"); - result.SetStatus(eReturnStatusFailed); - return result.Succeeded(); - } + Target &target = GetSelectedOrDummyTarget(); - size_t num_hooks = target->GetNumStopHooks(); + size_t num_hooks = target.GetNumStopHooks(); if (num_hooks == 0) { result.GetOutputStream().PutCString("No stop hooks.\n"); } else { for (size_t i = 0; i < num_hooks; i++) { - Target::StopHookSP this_hook = target->GetStopHookAtIndex(i); + Target::StopHookSP this_hook = target.GetStopHookAtIndex(i); if (i > 0) result.GetOutputStream().PutCString("\n"); this_hook->GetDescription(&(result.GetOutputStream()), diff --git a/source/Commands/CommandObjectThread.cpp b/source/Commands/CommandObjectThread.cpp index ed7cf0a1a48d..8c5274553902 100644 --- a/source/Commands/CommandObjectThread.cpp +++ b/source/Commands/CommandObjectThread.cpp @@ -16,6 +16,7 @@ #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" +#include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" #include "lldb/Interpreter/Options.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Function.h" @@ -237,11 +238,8 @@ protected: }; // CommandObjectThreadBacktrace - -static constexpr OptionDefinition g_thread_backtrace_options[] = { #define LLDB_OPTIONS_thread_backtrace #include "CommandOptions.inc" -}; class CommandObjectThreadBacktrace : public CommandObjectIterateOverThreads { public: @@ -284,9 +282,7 @@ public: "invalid boolean value for option '%c'", short_option); } break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -403,134 +399,125 @@ static constexpr OptionEnumValues TriRunningModes() { return OptionEnumValues(g_tri_running_mode); } -static constexpr OptionDefinition g_thread_step_scope_options[] = { #define LLDB_OPTIONS_thread_step_scope #include "CommandOptions.inc" -}; -class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed { +class ThreadStepScopeOptionGroup : public OptionGroup { public: - class CommandOptions : public Options { - public: - CommandOptions() : Options() { - // Keep default values of all options in one place: OptionParsingStarting - // () - OptionParsingStarting(nullptr); - } - - ~CommandOptions() override = default; - - Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, - ExecutionContext *execution_context) override { - Status error; - const int short_option = m_getopt_table[option_idx].val; - - switch (short_option) { - case 'a': { - bool success; - bool avoid_no_debug = - OptionArgParser::ToBoolean(option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat( - "invalid boolean value for option '%c'", short_option); - else { - m_step_in_avoid_no_debug = - avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; - } - } break; - - case 'A': { - bool success; - bool avoid_no_debug = - OptionArgParser::ToBoolean(option_arg, true, &success); - if (!success) - error.SetErrorStringWithFormat( - "invalid boolean value for option '%c'", short_option); - else { - m_step_out_avoid_no_debug = - avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; - } - } break; - - case 'c': - if (option_arg.getAsInteger(0, m_step_count)) - error.SetErrorStringWithFormat("invalid step count '%s'", - option_arg.str().c_str()); - break; - - case 'C': - m_class_name.clear(); - m_class_name.assign(option_arg); - break; - - case 'm': { - auto enum_values = GetDefinitions()[option_idx].enum_values; - m_run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum( - option_arg, enum_values, eOnlyDuringStepping, error); - } break; - - case 'e': - if (option_arg == "block") { - m_end_line_is_block_end = true; - break; - } - if (option_arg.getAsInteger(0, m_end_line)) - error.SetErrorStringWithFormat("invalid end line number '%s'", - option_arg.str().c_str()); - break; + ThreadStepScopeOptionGroup() : OptionGroup() { + // Keep default values of all options in one place: OptionParsingStarting + // () + OptionParsingStarting(nullptr); + } - case 'r': - m_avoid_regexp.clear(); - m_avoid_regexp.assign(option_arg); - break; + ~ThreadStepScopeOptionGroup() override = default; - case 't': - m_step_in_target.clear(); - m_step_in_target.assign(option_arg); - break; + llvm::ArrayRef<OptionDefinition> GetDefinitions() override { + return llvm::makeArrayRef(g_thread_step_scope_options); + } - default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); + Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg, + ExecutionContext *execution_context) override { + Status error; + const int short_option + = g_thread_step_scope_options[option_idx].short_option; + + switch (short_option) { + case 'a': { + bool success; + bool avoid_no_debug = + OptionArgParser::ToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat( + "invalid boolean value for option '%c'", short_option); + else { + m_step_in_avoid_no_debug = + avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; + } + } break; + + case 'A': { + bool success; + bool avoid_no_debug = + OptionArgParser::ToBoolean(option_arg, true, &success); + if (!success) + error.SetErrorStringWithFormat( + "invalid boolean value for option '%c'", short_option); + else { + m_step_out_avoid_no_debug = + avoid_no_debug ? eLazyBoolYes : eLazyBoolNo; + } + } break; + + case 'c': + if (option_arg.getAsInteger(0, m_step_count)) + error.SetErrorStringWithFormat("invalid step count '%s'", + option_arg.str().c_str()); + break; + + case 'm': { + auto enum_values = GetDefinitions()[option_idx].enum_values; + m_run_mode = (lldb::RunMode)OptionArgParser::ToOptionEnum( + option_arg, enum_values, eOnlyDuringStepping, error); + } break; + + case 'e': + if (option_arg == "block") { + m_end_line_is_block_end = true; break; } - return error; - } - - void OptionParsingStarting(ExecutionContext *execution_context) override { - m_step_in_avoid_no_debug = eLazyBoolCalculate; - m_step_out_avoid_no_debug = eLazyBoolCalculate; - m_run_mode = eOnlyDuringStepping; - - // Check if we are in Non-Stop mode - TargetSP target_sp = - execution_context ? execution_context->GetTargetSP() : TargetSP(); - if (target_sp && target_sp->GetNonStopModeEnabled()) - m_run_mode = eOnlyThisThread; + if (option_arg.getAsInteger(0, m_end_line)) + error.SetErrorStringWithFormat("invalid end line number '%s'", + option_arg.str().c_str()); + break; + case 'r': m_avoid_regexp.clear(); + m_avoid_regexp.assign(option_arg); + break; + + case 't': m_step_in_target.clear(); - m_class_name.clear(); - m_step_count = 1; - m_end_line = LLDB_INVALID_LINE_NUMBER; - m_end_line_is_block_end = false; - } + m_step_in_target.assign(option_arg); + break; - llvm::ArrayRef<OptionDefinition> GetDefinitions() override { - return llvm::makeArrayRef(g_thread_step_scope_options); + default: + llvm_unreachable("Unimplemented option"); } + return error; + } - // Instance variables to hold the values for command options. - LazyBool m_step_in_avoid_no_debug; - LazyBool m_step_out_avoid_no_debug; - RunMode m_run_mode; - std::string m_avoid_regexp; - std::string m_step_in_target; - std::string m_class_name; - uint32_t m_step_count; - uint32_t m_end_line; - bool m_end_line_is_block_end; - }; + void OptionParsingStarting(ExecutionContext *execution_context) override { + m_step_in_avoid_no_debug = eLazyBoolCalculate; + m_step_out_avoid_no_debug = eLazyBoolCalculate; + m_run_mode = eOnlyDuringStepping; + + // Check if we are in Non-Stop mode + TargetSP target_sp = + execution_context ? execution_context->GetTargetSP() : TargetSP(); + if (target_sp && target_sp->GetNonStopModeEnabled()) + m_run_mode = eOnlyThisThread; + + m_avoid_regexp.clear(); + m_step_in_target.clear(); + m_step_count = 1; + m_end_line = LLDB_INVALID_LINE_NUMBER; + m_end_line_is_block_end = false; + } + + // Instance variables to hold the values for command options. + LazyBool m_step_in_avoid_no_debug; + LazyBool m_step_out_avoid_no_debug; + RunMode m_run_mode; + std::string m_avoid_regexp; + std::string m_step_in_target; + uint32_t m_step_count; + uint32_t m_end_line; + bool m_end_line_is_block_end; +}; + +class CommandObjectThreadStepWithTypeAndScope : public CommandObjectParsed { +public: CommandObjectThreadStepWithTypeAndScope(CommandInterpreter &interpreter, const char *name, const char *help, @@ -542,7 +529,8 @@ public: eCommandTryTargetAPILock | eCommandProcessMustBeLaunched | eCommandProcessMustBePaused), - m_step_type(step_type), m_step_scope(step_scope), m_options() { + m_step_type(step_type), m_step_scope(step_scope), m_options(), + m_class_options("scripted step", 'C') { CommandArgumentEntry arg; CommandArgumentData thread_id_arg; @@ -556,11 +544,19 @@ public: // Push the data for the first argument into the m_arguments vector. m_arguments.push_back(arg); + + if (step_type == eStepTypeScripted) { + m_all_options.Append(&m_class_options, LLDB_OPT_SET_1, LLDB_OPT_SET_1); + } + m_all_options.Append(&m_options); + m_all_options.Finalize(); } ~CommandObjectThreadStepWithTypeAndScope() override = default; - Options *GetOptions() override { return &m_options; } + Options *GetOptions() override { + return &m_all_options; + } protected: bool DoExecute(Args &command, CommandReturnObject &result) override { @@ -600,15 +596,15 @@ protected: } if (m_step_type == eStepTypeScripted) { - if (m_options.m_class_name.empty()) { + if (m_class_options.GetClassName().empty()) { result.AppendErrorWithFormat("empty class name for scripted step."); result.SetStatus(eReturnStatusFailed); return false; } else if (!GetDebugger().GetScriptInterpreter()->CheckObjectExists( - m_options.m_class_name.c_str())) { + m_class_options.GetClassName().c_str())) { result.AppendErrorWithFormat( "class for scripted step: \"%s\" does not exist.", - m_options.m_class_name.c_str()); + m_class_options.GetClassName().c_str()); result.SetStatus(eReturnStatusFailed); return false; } @@ -724,7 +720,8 @@ protected: m_options.m_step_out_avoid_no_debug); } else if (m_step_type == eStepTypeScripted) { new_plan_sp = thread->QueueThreadPlanForStepScripted( - abort_other_plans, m_options.m_class_name.c_str(), + abort_other_plans, m_class_options.GetClassName().c_str(), + m_class_options.GetStructuredData(), bool_stop_other_threads, new_plan_status); } else { result.AppendError("step type is not supported"); @@ -792,7 +789,9 @@ protected: protected: StepType m_step_type; StepScope m_step_scope; - CommandOptions m_options; + ThreadStepScopeOptionGroup m_options; + OptionGroupPythonClassWithDict m_class_options; + OptionGroupOptions m_all_options; }; // CommandObjectThreadContinue @@ -828,13 +827,6 @@ public: bool DoExecute(Args &command, CommandReturnObject &result) override { bool synchronous_execution = m_interpreter.GetSynchronous(); - if (!GetDebugger().GetSelectedTarget()) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } - Process *process = m_exe_ctx.GetProcessPtr(); if (process == nullptr) { result.AppendError("no process exists. Cannot continue"); @@ -856,7 +848,7 @@ public: std::vector<Thread *> resume_threads; for (auto &entry : command.entries()) { uint32_t thread_idx; - if (entry.ref.getAsInteger(0, thread_idx)) { + if (entry.ref().getAsInteger(0, thread_idx)) { result.AppendErrorWithFormat( "invalid thread index argument: \"%s\".\n", entry.c_str()); result.SetStatus(eReturnStatusFailed); @@ -983,10 +975,8 @@ static constexpr OptionEnumValues DuoRunningModes() { return OptionEnumValues(g_duo_running_mode); } -static constexpr OptionDefinition g_thread_until_options[] = { #define LLDB_OPTIONS_thread_until #include "CommandOptions.inc" -}; class CommandObjectThreadUntil : public CommandObjectParsed { public: @@ -1044,9 +1034,7 @@ public: } } break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -1104,13 +1092,7 @@ protected: bool DoExecute(Args &command, CommandReturnObject &result) override { bool synchronous_execution = m_interpreter.GetSynchronous(); - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("invalid target, create a debug target using the " - "'target create' command"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); Process *process = m_exe_ctx.GetProcessPtr(); if (process == nullptr) { @@ -1402,11 +1384,8 @@ protected: }; // CommandObjectThreadInfo - -static constexpr OptionDefinition g_thread_info_options[] = { #define LLDB_OPTIONS_thread_info #include "CommandOptions.inc" -}; class CommandObjectThreadInfo : public CommandObjectIterateOverThreads { public: @@ -1436,7 +1415,7 @@ public: break; default: - return Status("invalid short option character '%c'", short_option); + llvm_unreachable("Unimplemented option"); } return error; } @@ -1536,11 +1515,8 @@ class CommandObjectThreadException : public CommandObjectIterateOverThreads { }; // CommandObjectThreadReturn - -static constexpr OptionDefinition g_thread_return_options[] = { #define LLDB_OPTIONS_thread_return #include "CommandOptions.inc" -}; class CommandObjectThreadReturn : public CommandObjectRaw { public: @@ -1573,9 +1549,7 @@ public: } } break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -1711,11 +1685,8 @@ protected: }; // CommandObjectThreadJump - -static constexpr OptionDefinition g_thread_jump_options[] = { #define LLDB_OPTIONS_thread_jump #include "CommandOptions.inc" -}; class CommandObjectThreadJump : public CommandObjectParsed { public: @@ -1760,7 +1731,7 @@ public: m_force = true; break; default: - return Status("invalid short option character '%c'", short_option); + llvm_unreachable("Unimplemented option"); } return error; } @@ -1854,11 +1825,8 @@ protected: // Next are the subcommands of CommandObjectMultiwordThreadPlan // CommandObjectThreadPlanList - -static constexpr OptionDefinition g_thread_plan_list_options[] = { #define LLDB_OPTIONS_thread_plan_list #include "CommandOptions.inc" -}; class CommandObjectThreadPlanList : public CommandObjectIterateOverThreads { public: @@ -1885,9 +1853,7 @@ public: m_verbose = true; break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -2102,7 +2068,11 @@ CommandObjectMultiwordThread::CommandObjectMultiwordThread( "step-scripted", CommandObjectSP(new CommandObjectThreadStepWithTypeAndScope( interpreter, "thread step-scripted", - "Step as instructed by the script class passed in the -C option.", + "Step as instructed by the script class passed in the -C option. " + "You can also specify a dictionary of key (-k) and value (-v) pairs " + "that will be used to populate an SBStructuredData Dictionary, which " + "will be passed to the constructor of the class implementing the " + "scripted step. See the Python Reference for more details.", nullptr, eStepTypeScripted, eStepScopeSource))); LoadSubCommand("plan", CommandObjectSP(new CommandObjectMultiwordThreadPlan( diff --git a/source/Commands/CommandObjectType.cpp b/source/Commands/CommandObjectType.cpp index 98a43f50b1b1..5e31fd5e8bce 100644 --- a/source/Commands/CommandObjectType.cpp +++ b/source/Commands/CommandObjectType.cpp @@ -80,9 +80,9 @@ static bool WarnOnPotentialUnquotedUnsignedType(Args &command, return false; for (auto entry : llvm::enumerate(command.entries().drop_back())) { - if (entry.value().ref != "unsigned") + if (entry.value().ref() != "unsigned") continue; - auto next = command.entries()[entry.index() + 1].ref; + auto next = command.entries()[entry.index() + 1].ref(); if (next == "int" || next == "short" || next == "char" || next == "long") { result.AppendWarningWithFormat( "unsigned %s being treated as two types. if you meant the combined " @@ -95,10 +95,8 @@ static bool WarnOnPotentialUnquotedUnsignedType(Args &command, return false; } -static constexpr OptionDefinition g_type_summary_add_options[] = { #define LLDB_OPTIONS_type_summary_add #include "CommandOptions.inc" -}; class CommandObjectTypeSummaryAdd : public CommandObjectParsed, public IOHandlerDelegateMultiline { @@ -153,7 +151,7 @@ public: "for\n" " internal_dict: an LLDB support object not to be used\"\"\"\n"; - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString(g_summary_addreader_instructions); output_sp->Flush(); @@ -162,7 +160,7 @@ public: void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); + StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); #ifndef LLDB_DISABLE_PYTHON ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); @@ -197,9 +195,7 @@ public: Status error; - for (size_t i = 0; i < options->m_target_types.GetSize(); i++) { - const char *type_name = - options->m_target_types.GetStringAtIndex(i); + for (const std::string &type_name : options->m_target_types) { CommandObjectTypeSummaryAdd::AddSummary( ConstString(type_name), script_format, (options->m_regex @@ -282,10 +278,8 @@ static const char *g_synth_addreader_instructions = " '''Optional'''\n" "class synthProvider:\n"; -static constexpr OptionDefinition g_type_synth_add_options[] = { #define LLDB_OPTIONS_type_synth_add #include "CommandOptions.inc" -}; class CommandObjectTypeSynthAdd : public CommandObjectParsed, public IOHandlerDelegateMultiline { @@ -329,9 +323,7 @@ private: m_regex = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -391,7 +383,7 @@ protected: } void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString(g_synth_addreader_instructions); output_sp->Flush(); @@ -400,7 +392,7 @@ protected: void IOHandlerInputComplete(IOHandler &io_handler, std::string &data) override { - StreamFileSP error_sp = io_handler.GetErrorStreamFile(); + StreamFileSP error_sp = io_handler.GetErrorStreamFileSP(); #ifndef LLDB_DISABLE_PYTHON ScriptInterpreter *interpreter = GetDebugger().GetScriptInterpreter(); @@ -441,13 +433,10 @@ protected: Status error; - for (size_t i = 0; i < options->m_target_types.GetSize(); i++) { - const char *type_name = - options->m_target_types.GetStringAtIndex(i); - ConstString const_type_name(type_name); - if (const_type_name) { + for (const std::string &type_name : options->m_target_types) { + if (!type_name.empty()) { if (!CommandObjectTypeSynthAdd::AddSynth( - const_type_name, synth_provider, + ConstString(type_name), synth_provider, options->m_regex ? CommandObjectTypeSynthAdd::eRegexSynth : CommandObjectTypeSynthAdd::eRegularSynth, @@ -503,10 +492,8 @@ public: // CommandObjectTypeFormatAdd -static constexpr OptionDefinition g_type_format_add_options[] = { #define LLDB_OPTIONS_type_format_add #include "CommandOptions.inc" -}; class CommandObjectTypeFormatAdd : public CommandObjectParsed { private: @@ -559,9 +546,7 @@ private: m_custom_type_name.assign(option_value); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -694,25 +679,26 @@ protected: WarnOnPotentialUnquotedUnsignedType(command, result); for (auto &arg_entry : command.entries()) { - if (arg_entry.ref.empty()) { + if (arg_entry.ref().empty()) { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } - ConstString typeCS(arg_entry.ref); + ConstString typeCS(arg_entry.ref()); if (m_command_options.m_regex) { - RegularExpressionSP typeRX(new RegularExpression()); - if (!typeRX->Compile(arg_entry.ref)) { + RegularExpression typeRX(arg_entry.ref()); + if (!typeRX.IsValid()) { result.AppendError( "regex format error (maybe this is not really a regex?)"); result.SetStatus(eReturnStatusFailed); return false; } category_sp->GetRegexTypeSummariesContainer()->Delete(typeCS); - category_sp->GetRegexTypeFormatsContainer()->Add(typeRX, entry); + category_sp->GetRegexTypeFormatsContainer()->Add(std::move(typeRX), + entry); } else - category_sp->GetTypeFormatsContainer()->Add(typeCS, entry); + category_sp->GetTypeFormatsContainer()->Add(std::move(typeCS), entry); } result.SetStatus(eReturnStatusSuccessFinishNoResult); @@ -720,10 +706,8 @@ protected: } }; -static constexpr OptionDefinition g_type_formatter_delete_options[] = { #define LLDB_OPTIONS_type_formatter_delete #include "CommandOptions.inc" -}; class CommandObjectTypeFormatterDelete : public CommandObjectParsed { protected: @@ -749,9 +733,7 @@ protected: m_language = Language::GetLanguageTypeFromString(option_arg); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -859,10 +841,8 @@ protected: } }; -static constexpr OptionDefinition g_type_formatter_clear_options[] = { #define LLDB_OPTIONS_type_formatter_clear #include "CommandOptions.inc" -}; class CommandObjectTypeFormatterClear : public CommandObjectParsed { private: @@ -882,9 +862,7 @@ private: m_delete_all = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -971,11 +949,8 @@ public: "type format clear", "Delete all existing format styles.") {} }; - -static constexpr OptionDefinition g_type_formatter_list_options[] = { #define LLDB_OPTIONS_type_formatter_list #include "CommandOptions.inc" -}; template <typename FormatterType> class CommandObjectTypeFormatterList : public CommandObjectParsed { @@ -1005,9 +980,7 @@ class CommandObjectTypeFormatterList : public CommandObjectParsed { m_category_language.SetOptionWasSet(); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1061,9 +1034,9 @@ protected: std::unique_ptr<RegularExpression> formatter_regex; if (m_options.m_category_regex.OptionWasSet()) { - category_regex.reset(new RegularExpression()); - if (!category_regex->Compile( - m_options.m_category_regex.GetCurrentValueAsRef())) { + category_regex.reset(new RegularExpression( + m_options.m_category_regex.GetCurrentValueAsRef())); + if (!category_regex->IsValid()) { result.AppendErrorWithFormat( "syntax error in category regular expression '%s'", m_options.m_category_regex.GetCurrentValueAsRef().str().c_str()); @@ -1074,8 +1047,9 @@ protected: if (argc == 1) { const char *arg = command.GetArgumentAtIndex(0); - formatter_regex.reset(new RegularExpression()); - if (!formatter_regex->Compile(llvm::StringRef::withNullAsEmpty(arg))) { + formatter_regex.reset( + new RegularExpression(llvm::StringRef::withNullAsEmpty(arg))); + if (!formatter_regex->IsValid()) { result.AppendErrorWithFormat("syntax error in regular expression '%s'", arg); result.SetStatus(eReturnStatusFailed); @@ -1116,13 +1090,13 @@ protected: foreach .SetWithRegex([&result, &formatter_regex, &any_printed]( - RegularExpressionSP regex_sp, + const RegularExpression ®ex, const FormatterSharedPointer &format_sp) -> bool { if (formatter_regex) { bool escape = true; - if (regex_sp->GetText() == formatter_regex->GetText()) { + if (regex.GetText() == formatter_regex->GetText()) { escape = false; - } else if (formatter_regex->Execute(regex_sp->GetText())) { + } else if (formatter_regex->Execute(regex.GetText())) { escape = false; } @@ -1132,7 +1106,7 @@ protected: any_printed = true; result.GetOutputStream().Printf("%s: %s\n", - regex_sp->GetText().str().c_str(), + regex.GetText().str().c_str(), format_sp->GetDescription().c_str()); return true; }); @@ -1257,8 +1231,7 @@ Status CommandObjectTypeSummaryAdd::CommandOptions::SetOptionValue( m_flags.SetHideItemNames(true); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1355,13 +1328,13 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary( m_options.m_name, m_options.m_category); for (auto &entry : command.entries()) { - if (entry.ref.empty()) { + if (entry.ref().empty()) { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } - options->m_target_types << entry.ref; + options->m_target_types << entry.ref(); } m_interpreter.GetPythonCommandsFromIOHandler( @@ -1382,7 +1355,7 @@ bool CommandObjectTypeSummaryAdd::Execute_ScriptSummary( for (auto &entry : command.entries()) { CommandObjectTypeSummaryAdd::AddSummary( - ConstString(entry.ref), script_format, + ConstString(entry.ref()), script_format, (m_options.m_regex ? eRegexSummary : eRegularSummary), m_options.m_category, &error); if (error.Fail()) { @@ -1455,12 +1428,12 @@ bool CommandObjectTypeSummaryAdd::Execute_StringSummary( // now I have a valid format, let's add it to every type Status error; for (auto &arg_entry : command.entries()) { - if (arg_entry.ref.empty()) { + if (arg_entry.ref().empty()) { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } - ConstString typeCS(arg_entry.ref); + ConstString typeCS(arg_entry.ref()); AddSummary(typeCS, entry, (m_options.m_regex ? eRegexSummary : eRegularSummary), @@ -1647,8 +1620,8 @@ bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, } if (type == eRegexSummary) { - RegularExpressionSP typeRX(new RegularExpression()); - if (!typeRX->Compile(type_name.GetStringRef())) { + RegularExpression typeRX(type_name.GetStringRef()); + if (!typeRX.IsValid()) { if (error) error->SetErrorString( "regex format error (maybe this is not really a regex?)"); @@ -1656,7 +1629,7 @@ bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, } category->GetRegexTypeSummariesContainer()->Delete(type_name); - category->GetRegexTypeSummariesContainer()->Add(typeRX, entry); + category->GetRegexTypeSummariesContainer()->Add(std::move(typeRX), entry); return true; } else if (type == eNamedSummary) { @@ -1664,7 +1637,7 @@ bool CommandObjectTypeSummaryAdd::AddSummary(ConstString type_name, DataVisualization::NamedSummaryFormats::Add(type_name, entry); return true; } else { - category->GetTypeSummariesContainer()->Add(type_name, entry); + category->GetTypeSummariesContainer()->Add(std::move(type_name), entry); return true; } } @@ -1731,11 +1704,8 @@ protected: }; // CommandObjectTypeCategoryDefine - -static constexpr OptionDefinition g_type_category_define_options[] = { #define LLDB_OPTIONS_type_category_define #include "CommandOptions.inc" -}; class CommandObjectTypeCategoryDefine : public CommandObjectParsed { class CommandOptions : public Options { @@ -1759,9 +1729,7 @@ class CommandObjectTypeCategoryDefine : public CommandObjectParsed { error = m_cate_language.SetValueFromString(option_arg); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -1818,7 +1786,7 @@ protected: for (auto &entry : command.entries()) { TypeCategoryImplSP category_sp; - if (DataVisualization::Categories::GetCategory(ConstString(entry.ref), + if (DataVisualization::Categories::GetCategory(ConstString(entry.ref()), category_sp) && category_sp) { category_sp->AddLanguage(m_options.m_cate_language.GetCurrentValue()); @@ -1834,11 +1802,8 @@ protected: }; // CommandObjectTypeCategoryEnable - -static constexpr OptionDefinition g_type_category_enable_options[] = { #define LLDB_OPTIONS_type_category_enable #include "CommandOptions.inc" -}; class CommandObjectTypeCategoryEnable : public CommandObjectParsed { class CommandOptions : public Options { @@ -1862,9 +1827,7 @@ class CommandObjectTypeCategoryEnable : public CommandObjectParsed { } break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -2006,11 +1969,8 @@ protected: }; // CommandObjectTypeCategoryDisable - -OptionDefinition constexpr g_type_category_disable_options[] = { #define LLDB_OPTIONS_type_category_disable #include "CommandOptions.inc" -}; class CommandObjectTypeCategoryDisable : public CommandObjectParsed { class CommandOptions : public Options { @@ -2034,9 +1994,7 @@ class CommandObjectTypeCategoryDisable : public CommandObjectParsed { } break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -2142,9 +2100,9 @@ protected: std::unique_ptr<RegularExpression> regex; if (argc == 1) { - regex.reset(new RegularExpression()); const char *arg = command.GetArgumentAtIndex(0); - if (!regex->Compile(llvm::StringRef::withNullAsEmpty(arg))) { + regex.reset(new RegularExpression(llvm::StringRef::withNullAsEmpty(arg))); + if (!regex->IsValid()) { result.AppendErrorWithFormat( "syntax error in category regular expression '%s'", arg); result.SetStatus(eReturnStatusFailed); @@ -2270,13 +2228,13 @@ bool CommandObjectTypeSynthAdd::Execute_HandwritePython( m_options.m_cascade, m_options.m_regex, m_options.m_category); for (auto &entry : command.entries()) { - if (entry.ref.empty()) { + if (entry.ref().empty()) { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } - options->m_target_types << entry.ref; + options->m_target_types << entry.ref(); } m_interpreter.GetPythonCommandsFromIOHandler( @@ -2335,13 +2293,13 @@ bool CommandObjectTypeSynthAdd::Execute_PythonClass( Status error; for (auto &arg_entry : command.entries()) { - if (arg_entry.ref.empty()) { + if (arg_entry.ref().empty()) { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } - ConstString typeCS(arg_entry.ref); + ConstString typeCS(arg_entry.ref()); if (!AddSynth(typeCS, entry, m_options.m_regex ? eRegexSynth : eRegularSynth, m_options.m_category, &error)) { @@ -2396,8 +2354,8 @@ bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, } if (type == eRegexSynth) { - RegularExpressionSP typeRX(new RegularExpression()); - if (!typeRX->Compile(type_name.GetStringRef())) { + RegularExpression typeRX(type_name.GetStringRef()); + if (!typeRX.IsValid()) { if (error) error->SetErrorString( "regex format error (maybe this is not really a regex?)"); @@ -2405,21 +2363,18 @@ bool CommandObjectTypeSynthAdd::AddSynth(ConstString type_name, } category->GetRegexTypeSyntheticsContainer()->Delete(type_name); - category->GetRegexTypeSyntheticsContainer()->Add(typeRX, entry); + category->GetRegexTypeSyntheticsContainer()->Add(std::move(typeRX), entry); return true; } else { - category->GetTypeSyntheticsContainer()->Add(type_name, entry); + category->GetTypeSyntheticsContainer()->Add(std::move(type_name), entry); return true; } } #endif // LLDB_DISABLE_PYTHON - -static constexpr OptionDefinition g_type_filter_add_options[] = { #define LLDB_OPTIONS_type_filter_add #include "CommandOptions.inc" -}; class CommandObjectTypeFilterAdd : public CommandObjectParsed { private: @@ -2461,9 +2416,7 @@ private: m_regex = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -2527,8 +2480,8 @@ private: } if (type == eRegexFilter) { - RegularExpressionSP typeRX(new RegularExpression()); - if (!typeRX->Compile(type_name.GetStringRef())) { + RegularExpression typeRX(type_name.GetStringRef()); + if (!typeRX.IsValid()) { if (error) error->SetErrorString( "regex format error (maybe this is not really a regex?)"); @@ -2536,11 +2489,11 @@ private: } category->GetRegexTypeFiltersContainer()->Delete(type_name); - category->GetRegexTypeFiltersContainer()->Add(typeRX, entry); + category->GetRegexTypeFiltersContainer()->Add(std::move(typeRX), entry); return true; } else { - category->GetTypeFiltersContainer()->Add(type_name, entry); + category->GetTypeFiltersContainer()->Add(std::move(type_name), entry); return true; } } @@ -2641,13 +2594,13 @@ protected: WarnOnPotentialUnquotedUnsignedType(command, result); for (auto &arg_entry : command.entries()) { - if (arg_entry.ref.empty()) { + if (arg_entry.ref().empty()) { result.AppendError("empty typenames not allowed"); result.SetStatus(eReturnStatusFailed); return false; } - ConstString typeCS(arg_entry.ref); + ConstString typeCS(arg_entry.ref()); if (!AddFilter(typeCS, entry, m_options.m_regex ? eRegexFilter : eRegularFilter, m_options.m_category, &error)) { @@ -2663,10 +2616,8 @@ protected: }; // "type lookup" -static constexpr OptionDefinition g_type_lookup_options[] = { #define LLDB_OPTIONS_type_lookup #include "CommandOptions.inc" -}; class CommandObjectTypeLookup : public CommandObjectRaw { protected: @@ -2717,9 +2668,7 @@ protected: break; default: - error.SetErrorStringWithFormat("invalid short option character '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; diff --git a/source/Commands/CommandObjectWatchpoint.cpp b/source/Commands/CommandObjectWatchpoint.cpp index 98e758b7ef6a..44dfb29b19b5 100644 --- a/source/Commands/CommandObjectWatchpoint.cpp +++ b/source/Commands/CommandObjectWatchpoint.cpp @@ -40,11 +40,6 @@ static void AddWatchpointDescription(Stream *s, Watchpoint *wp, static bool CheckTargetForWatchpointOperations(Target *target, CommandReturnObject &result) { - if (target == nullptr) { - result.AppendError("Invalid target. No existing target or watchpoints."); - result.SetStatus(eReturnStatusFailed); - return false; - } bool process_is_valid = target->GetProcessSP() && target->GetProcessSP()->IsAlive(); if (!process_is_valid) { @@ -94,12 +89,12 @@ bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( // Go through the arguments and make a canonical form of arg list containing // only numbers with possible "-" in between. for (auto &entry : args.entries()) { - if ((idx = WithRSAIndex(entry.ref)) == -1) { - StrRefArgs.push_back(entry.ref); + if ((idx = WithRSAIndex(entry.ref())) == -1) { + StrRefArgs.push_back(entry.ref()); continue; } // The Arg contains the range specifier, split it, then. - std::tie(first, second) = entry.ref.split(RSA[idx]); + std::tie(first, second) = entry.ref().split(RSA[idx]); if (!first.empty()) StrRefArgs.push_back(first); StrRefArgs.push_back(Minus); @@ -146,11 +141,8 @@ bool CommandObjectMultiwordWatchpoint::VerifyWatchpointIDs( // CommandObjectWatchpointList::Options #pragma mark List::CommandOptions - -static constexpr OptionDefinition g_watchpoint_list_options[] = { #define LLDB_OPTIONS_watchpoint_list #include "CommandOptions.inc" -}; #pragma mark List @@ -159,7 +151,8 @@ public: CommandObjectWatchpointList(CommandInterpreter &interpreter) : CommandObjectParsed( interpreter, "watchpoint list", - "List all watchpoints at configurable levels of detail.", nullptr), + "List all watchpoints at configurable levels of detail.", nullptr, + eCommandRequiresTarget), m_options() { CommandArgumentEntry arg; CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, @@ -199,9 +192,7 @@ public: m_level = lldb::eDescriptionLevelVerbose; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -222,12 +213,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - if (target == nullptr) { - result.AppendError("Invalid target. No current target or watchpoints."); - result.SetStatus(eReturnStatusSuccessFinishNoResult); - return true; - } + Target *target = &GetSelectedTarget(); if (target->GetProcessSP() && target->GetProcessSP()->IsAlive()) { uint32_t num_supported_hardware_watchpoints; @@ -297,7 +283,7 @@ public: : CommandObjectParsed(interpreter, "enable", "Enable the specified disabled watchpoint(s). If " "no watchpoints are specified, enable all of them.", - nullptr) { + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); @@ -310,7 +296,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); + Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) return false; @@ -367,7 +353,7 @@ public: "Disable the specified watchpoint(s) without " "removing it/them. If no watchpoints are " "specified, disable them all.", - nullptr) { + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); @@ -380,7 +366,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); + Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) return false; @@ -439,7 +425,7 @@ public: : CommandObjectParsed(interpreter, "watchpoint delete", "Delete the specified watchpoint(s). If no " "watchpoints are specified, delete them all.", - nullptr) { + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, eArgTypeWatchpointIDRange); @@ -452,7 +438,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); + Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) return false; @@ -507,10 +493,8 @@ protected: // CommandObjectWatchpointIgnore #pragma mark Ignore::CommandOptions -static constexpr OptionDefinition g_watchpoint_ignore_options[] = { #define LLDB_OPTIONS_watchpoint_ignore #include "CommandOptions.inc" -}; class CommandObjectWatchpointIgnore : public CommandObjectParsed { public: @@ -518,7 +502,7 @@ public: : CommandObjectParsed(interpreter, "watchpoint ignore", "Set ignore count on the specified watchpoint(s). " "If no watchpoints are specified, set them all.", - nullptr), + nullptr, eCommandRequiresTarget), m_options() { CommandArgumentEntry arg; CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, @@ -550,9 +534,7 @@ public: option_arg.str().c_str()); break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -573,7 +555,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); + Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) return false; @@ -625,11 +607,8 @@ private: // CommandObjectWatchpointModify #pragma mark Modify::CommandOptions - -static constexpr OptionDefinition g_watchpoint_modify_options[] = { #define LLDB_OPTIONS_watchpoint_modify #include "CommandOptions.inc" -}; #pragma mark Modify @@ -643,7 +622,7 @@ public: "If no watchpoint is specified, act on the last created " "watchpoint. " "Passing an empty argument clears the modification.", - nullptr), + nullptr, eCommandRequiresTarget), m_options() { CommandArgumentEntry arg; CommandObject::AddIDsArgumentData(arg, eArgTypeWatchpointID, @@ -674,9 +653,7 @@ public: m_condition_passed = true; break; default: - error.SetErrorStringWithFormat("unrecognized option '%c'", - short_option); - break; + llvm_unreachable("Unimplemented option"); } return error; @@ -699,7 +676,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); + Target *target = &GetSelectedTarget(); if (!CheckTargetForWatchpointOperations(target, result)) return false; @@ -808,12 +785,12 @@ corresponding to the byte size of the data type."); protected: static size_t GetVariableCallback(void *baton, const char *name, VariableList &variable_list) { + size_t old_size = variable_list.GetSize(); Target *target = static_cast<Target *>(baton); - if (target) { - return target->GetImages().FindGlobalVariables(ConstString(name), - UINT32_MAX, variable_list); - } - return 0; + if (target) + target->GetImages().FindGlobalVariables(ConstString(name), UINT32_MAX, + variable_list); + return variable_list.GetSize() - old_size; } bool DoExecute(Args &command, CommandReturnObject &result) override { diff --git a/source/Commands/CommandObjectWatchpointCommand.cpp b/source/Commands/CommandObjectWatchpointCommand.cpp index 2be0b5b154e0..5683381efc85 100644 --- a/source/Commands/CommandObjectWatchpointCommand.cpp +++ b/source/Commands/CommandObjectWatchpointCommand.cpp @@ -24,28 +24,33 @@ using namespace lldb; using namespace lldb_private; -// CommandObjectWatchpointCommandAdd - // FIXME: "script-type" needs to have its contents determined dynamically, so -// somebody can add a new scripting -// language to lldb and have it pickable here without having to change this -// enumeration by hand and rebuild lldb proper. - +// somebody can add a new scripting language to lldb and have it pickable here +// without having to change this enumeration by hand and rebuild lldb proper. static constexpr OptionEnumValueElement g_script_option_enumeration[] = { - {eScriptLanguageNone, "command", - "Commands are in the lldb command interpreter language"}, - {eScriptLanguagePython, "python", "Commands are in the Python language."}, - {eSortOrderByName, "default-script", - "Commands are in the default scripting language."} }; + { + eScriptLanguageNone, + "command", + "Commands are in the lldb command interpreter language", + }, + { + eScriptLanguagePython, + "python", + "Commands are in the Python language.", + }, + { + eSortOrderByName, + "default-script", + "Commands are in the default scripting language.", + }, +}; static constexpr OptionEnumValues ScriptOptionEnum() { return OptionEnumValues(g_script_option_enumeration); } -static constexpr OptionDefinition g_watchpoint_command_add_options[] = { #define LLDB_OPTIONS_watchpoint_command_add #include "CommandOptions.inc" -}; class CommandObjectWatchpointCommandAdd : public CommandObjectParsed, public IOHandlerDelegateMultiline { @@ -54,7 +59,7 @@ public: : CommandObjectParsed(interpreter, "add", "Add a set of LLDB commands to a watchpoint, to be " "executed whenever the watchpoint is hit.", - nullptr), + nullptr, eCommandRequiresTarget), IOHandlerDelegateMultiline("DONE", IOHandlerDelegate::Completion::LLDBCommand), m_options() { @@ -202,7 +207,7 @@ are no syntax errors may indicate that a function was declared but never called. Options *GetOptions() override { return &m_options; } void IOHandlerActivated(IOHandler &io_handler, bool interactive) override { - StreamFileSP output_sp(io_handler.GetOutputStreamFile()); + StreamFileSP output_sp(io_handler.GetOutputStreamFileSP()); if (output_sp && interactive) { output_sp->PutCString( "Enter your debugger command(s). Type 'DONE' to end.\n"); @@ -349,7 +354,7 @@ are no syntax errors may indicate that a function was declared but never called. break; default: - break; + llvm_unreachable("Unimplemented option"); } return error; } @@ -384,14 +389,7 @@ are no syntax errors may indicate that a function was declared but never called. protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - - if (target == nullptr) { - result.AppendError("There is not a current executable; there are no " - "watchpoints to which to add commands"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); const WatchpointList &watchpoints = target->GetWatchpointList(); size_t num_watchpoints = watchpoints.GetSize(); @@ -481,7 +479,7 @@ public: CommandObjectWatchpointCommandDelete(CommandInterpreter &interpreter) : CommandObjectParsed(interpreter, "delete", "Delete the set of commands from a watchpoint.", - nullptr) { + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandArgumentData wp_id_arg; @@ -501,14 +499,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - - if (target == nullptr) { - result.AppendError("There is not a current executable; there are no " - "watchpoints from which to delete commands"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); const WatchpointList &watchpoints = target->GetWatchpointList(); size_t num_watchpoints = watchpoints.GetSize(); @@ -557,10 +548,10 @@ protected: class CommandObjectWatchpointCommandList : public CommandObjectParsed { public: CommandObjectWatchpointCommandList(CommandInterpreter &interpreter) - : CommandObjectParsed(interpreter, "list", "List the script or set of " - "commands to be executed when " - "the watchpoint is hit.", - nullptr) { + : CommandObjectParsed(interpreter, "list", + "List the script or set of commands to be executed " + "when the watchpoint is hit.", + nullptr, eCommandRequiresTarget) { CommandArgumentEntry arg; CommandArgumentData wp_id_arg; @@ -580,14 +571,7 @@ public: protected: bool DoExecute(Args &command, CommandReturnObject &result) override { - Target *target = GetDebugger().GetSelectedTarget().get(); - - if (target == nullptr) { - result.AppendError("There is not a current executable; there are no " - "watchpoints for which to list commands"); - result.SetStatus(eReturnStatusFailed); - return false; - } + Target *target = &GetSelectedTarget(); const WatchpointList &watchpoints = target->GetWatchpointList(); size_t num_watchpoints = watchpoints.GetSize(); diff --git a/source/Commands/Options.td b/source/Commands/Options.td index 9cfbcd2d4ebf..87f5506c305f 100644 --- a/source/Commands/Options.td +++ b/source/Commands/Options.td @@ -38,6 +38,8 @@ let Command = "settings read" in { } let Command = "breakpoint list" in { + // FIXME: We need to add an "internal" command, and then add this sort of + // thing to it. But I need to see it for now, and don't want to wait. def blist_internal : Option<"internal", "i">, Desc<"Show debugger internal breakpoints">; def blist_brief : Option<"brief", "b">, Group<1>, @@ -52,6 +54,823 @@ let Command = "breakpoint list" in { "provided, which prime new targets.">; } +let Command = "breakpoint modify" in { + def breakpoint_modify_ignore_count : Option<"ignore-count", "i">, Group<1>, + Arg<"Count">, + Desc<"Set the number of times this breakpoint is skipped before stopping.">; + def breakpoint_modify_one_shot : Option<"one-shot", "o">, Group<1>, + Arg<"Boolean">, + Desc<"The breakpoint is deleted the first time it stop causes a stop.">; + def breakpoint_modify_thread_index : Option<"thread-index", "x">, Group<1>, + Arg<"ThreadIndex">, Desc<"The breakpoint stops only for the thread whose " + "index matches this argument.">; + def breakpoint_modify_thread_id : Option<"thread-id", "t">, Group<1>, + Arg<"ThreadID">, Desc<"The breakpoint stops only for the thread whose TID " + "matches this argument.">; + def breakpoint_modify_thread_name : Option<"thread-name", "T">, Group<1>, + Arg<"ThreadName">, Desc<"The breakpoint stops only for the thread whose " + "thread name matches this argument.">; + def breakpoint_modify_queue_name : Option<"queue-name", "q">, Group<1>, + Arg<"QueueName">, Desc<"The breakpoint stops only for threads in the queue " + "whose name is given by this argument.">; + def breakpoint_modify_condition : Option<"condition", "c">, Group<1>, + Arg<"Expression">, Desc<"The breakpoint stops only if this condition " + "expression evaluates to true.">; + def breakpoint_modify_auto_continue : Option<"auto-continue", "G">, Group<1>, + Arg<"Boolean">, + Desc<"The breakpoint will auto-continue after running its commands.">; + def breakpoint_modify_enable : Option<"enable", "e">, Group<2>, + Desc<"Enable the breakpoint.">; + def breakpoint_modify_disable : Option<"disable", "d">, Group<3>, + Desc<"Disable the breakpoint.">; + def breakpoint_modify_command : Option<"command", "C">, Group<4>, + Arg<"Command">, + Desc<"A command to run when the breakpoint is hit, can be provided more " + "than once, the commands will get run in order left to right.">; +} + +let Command = "breakpoint dummy" in { + def breakpoint_dummy_options_dummy_breakpoints : + Option<"dummy-breakpoints", "D">, Group<1>, + Desc<"Act on Dummy breakpoints - i.e. breakpoints set before a file is " + "provided, which prime new targets.">; +} + +let Command = "breakpoint set" in { + def breakpoint_set_shlib : Option<"shlib", "s">, Arg<"ShlibName">, + Completion<"Module">, Groups<[1,2,3,4,5,6,7,8,9,11]>, // *not* in group 10 + Desc<"Set the breakpoint only in this shared library. Can repeat this " + "option multiple times to specify multiple shared libraries.">; + def breakpoint_set_hardware : Option<"hardware", "H">, + Desc<"Require the breakpoint to use hardware breakpoints.">; + def breakpoint_set_file : Option<"file", "f">, Arg<"Filename">, + Completion<"SourceFile">, Groups<[1,3,4,5,6,7,8,9,11]>, + Desc<"Specifies the source file in which to set this breakpoint. Note, by " + "default lldb only looks for files that are #included if they use the " + "standard include file extensions. To set breakpoints on .c/.cpp/.m/.mm " + "files that are #included, set target.inline-breakpoint-strategy to " + "\"always\".">; + def breakpoint_set_line : Option<"line", "l">, Group<1>, Arg<"LineNum">, + Required, + Desc<"Specifies the line number on which to set this breakpoint.">; + def breakpoint_set_address : Option<"address", "a">, Group<2>, + Arg<"AddressOrExpression">, Required, + Desc<"Set the breakpoint at the specified address. If the address maps " + "uniquely toa particular binary, then the address will be converted to " + "a \"file\"address, so that the breakpoint will track that binary+offset " + "no matter where the binary eventually loads. Alternately, if you also " + "specify the module - with the -s option - then the address will be " + "treated as a file address in that module, and resolved accordingly. " + "Again, this will allow lldb to track that offset on subsequent reloads. " + " The module need not have been loaded at the time you specify this " + "breakpoint, and will get resolved when the module is loaded.">; + def breakpoint_set_name : Option<"name", "n">, Group<3>, Arg<"FunctionName">, + Completion<"Symbol">, Required, + Desc<"Set the breakpoint by function name. Can be repeated multiple times " + "to makeone breakpoint for multiple names">; + def breakpoint_set_source_regexp_function : + Option<"source-regexp-function", "X">, Group<9>, Arg<"FunctionName">, + Completion<"Symbol">, + Desc<"When used with '-p' limits the source regex to source contained in " + "the namedfunctions. Can be repeated multiple times.">; + def breakpoint_set_fullname : Option<"fullname", "F">, Group<4>, + Arg<"FullName">, Required, Completion<"Symbol">, + Desc<"Set the breakpoint by fully qualified function names. For C++ this " + "means namespaces and all arguments, and for Objective-C this means a full " + "functionprototype with class and selector. Can be repeated multiple times" + " to make one breakpoint for multiple names.">; + def breakpoint_set_selector : Option<"selector", "S">, Group<5>, + Arg<"Selector">, Required, + Desc<"Set the breakpoint by ObjC selector name. Can be repeated multiple " + "times tomake one breakpoint for multiple Selectors.">; + def breakpoint_set_method : Option<"method", "M">, Group<6>, Arg<"Method">, + Required, Desc<"Set the breakpoint by C++ method names. Can be repeated " + "multiple times tomake one breakpoint for multiple methods.">; + def breakpoint_set_func_regex : Option<"func-regex", "r">, Group<7>, + Arg<"RegularExpression">, Required, Desc<"Set the breakpoint by function " + "name, evaluating a regular-expression to findthe function name(s).">; + def breakpoint_set_basename : Option<"basename", "b">, Group<8>, + Arg<"FunctionName">, Required, Completion<"Symbol">, + Desc<"Set the breakpoint by function basename (C++ namespaces and arguments" + " will beignored). Can be repeated multiple times to make one breakpoint " + "for multiplesymbols.">; + def breakpoint_set_source_pattern_regexp : + Option<"source-pattern-regexp", "p">, Group<9>, Arg<"RegularExpression">, + Required, Desc<"Set the breakpoint by specifying a regular expression which" + " is matched against the source text in a source file or files specified " + "with the -f can be specified more than once. If no source files " + "are specified, uses the current \"default source file\". If you want to " + "match against all source files, pass the \"--all-files\" option.">; + def breakpoint_set_all_files : Option<"all-files", "A">, Group<9>, + Desc<"All files are searched for source pattern matches.">; + def breakpoint_set_language_exception : Option<"language-exception", "E">, + Group<10>, Arg<"Language">, Required, + Desc<"Set the breakpoint on exceptions thrown by the specified language " + "(without options, on throw but not catch.)">; + def breakpoint_set_on_throw : Option<"on-throw", "w">, Group<10>, + Arg<"Boolean">, Desc<"Set the breakpoint on exception throW.">; + def breakpoint_set_on_catch : Option<"on-catch", "h">, Group<10>, + Arg<"Boolean">, Desc<"Set the breakpoint on exception catcH.">; + def breakpoint_set_language : Option<"language", "L">, GroupRange<3, 8>, + Arg<"Language">, + Desc<"Specifies the Language to use when interpreting the breakpoint's " + "expression (note: currently only implemented for setting breakpoints on " + "identifiers). If not set the target.language setting is used.">; + def breakpoint_set_skip_prologue : Option<"skip-prologue", "K">, + Arg<"Boolean">, Groups<[1,3,4,5,6,7,8]>, + Desc<"sKip the prologue if the breakpoint is at the beginning of a " + "function. If not set the target.skip-prologue setting is used.">; + def breakpoint_set_breakpoint_name : Option<"breakpoint-name", "N">, + Arg<"BreakpointName">, + Desc<"Adds this to the list of names for this breakpoint.">; + def breakpoint_set_address_slide : Option<"address-slide", "R">, + Arg<"Address">, Groups<[1,3,4,5,6,7,8]>, + Desc<"Add the specified offset to whatever address(es) the breakpoint " + "resolves to. At present this applies the offset directly as given, and " + "doesn't try to align it to instruction boundaries.">; + def breakpoint_set_move_to_nearest_code : Option<"move-to-nearest-code", "m">, + Groups<[1, 9]>, Arg<"Boolean">, + Desc<"Move breakpoints to nearest code. If not set the " + "target.move-to-nearest-codesetting is used.">; + /* Don't add this option till it actually does something useful... + def breakpoint_set_exception_typename : Option<"exception-typename", "O">, + Arg<"TypeName">, Desc<"The breakpoint will only stop if an " + "exception Object of this type is thrown. Can be repeated multiple times " + "to stop for multiple object types">; + */ +} + +let Command = "breakpoint clear" in { + def breakpoint_clear_file : Option<"file", "f">, Group<1>, Arg<"Filename">, + Completion<"SourceFile">, + Desc<"Specify the breakpoint by source location in this particular file.">; + def breakpoint_clear_line : Option<"line", "l">, Group<1>, Arg<"LineNum">, + Required, + Desc<"Specify the breakpoint by source location at this particular line.">; +} + +let Command = "breakpoint delete" in { + def breakpoint_delete_force : Option<"force", "f">, Group<1>, + Desc<"Delete all breakpoints without querying for confirmation.">; + def breakpoint_delete_dummy_breakpoints : Option<"dummy-breakpoints", "D">, + Group<1>, Desc<"Delete Dummy breakpoints - i.e. breakpoints set before a " + "file is provided, which prime new targets.">; +} + +let Command = "breakpoint name" in { + def breakpoint_name_name : Option<"name", "N">, Group<1>, + Arg<"BreakpointName">, Desc<"Specifies a breakpoint name to use.">; + def breakpoint_name_breakpoint_id : Option<"breakpoint-id", "B">, Group<2>, + Arg<"BreakpointID">, Desc<"Specify a breakpoint ID to use.">; + def breakpoint_name_dummy_breakpoints : Option<"dummy-breakpoints", "D">, + Group<3>, Desc<"Operate on Dummy breakpoints - i.e. breakpoints set before " + "a file is provided, which prime new targets.">; + def breakpoint_name_help_string : Option<"help-string", "H">, Group<4>, + Arg<"None">, Desc<"A help string describing the purpose of this name.">; +} + +let Command = "breakpoint access" in { + def breakpoint_access_allow_list : Option<"allow-list", "L">, Group<1>, + Arg<"Boolean">, Desc<"Determines whether the breakpoint will show up in " + "break list if not referred to explicitly.">; + def breakpoint_access_allow_disable : Option<"allow-disable", "A">, Group<2>, + Arg<"Boolean">, Desc<"Determines whether the breakpoint can be disabled by " + "name or when all breakpoints are disabled.">; + def breakpoint_access_allow_delete : Option<"allow-delete", "D">, Group<3>, + Arg<"Boolean">, Desc<"Determines whether the breakpoint can be deleted by " + "name or when all breakpoints are deleted.">; +} + +let Command = "breakpoint read" in { + def breakpoint_read_file : Option<"file", "f">, Arg<"Filename">, Required, + Completion<"DiskFile">, + Desc<"The file from which to read the breakpoints.">; + def breakpoint_read_breakpoint_name : Option<"breakpoint-name", "N">, + Arg<"BreakpointName">, Desc<"Only read in breakpoints with this name.">; +} + +let Command = "breakpoint write" in { + def breakpoint_write_file : Option<"file", "f">, Arg<"Filename">, Required, + Completion<"DiskFile">, + Desc<"The file into which to write the breakpoints.">; + def breakpoint_write_append : Option<"append", "a">, + Desc<"Append to saved breakpoints file if it exists.">; +} + +let Command = "breakpoint command add" in { + def breakpoint_add_one_liner : Option<"one-liner", "o">, Group<1>, + Arg<"OneLiner">, Desc<"Specify a one-line breakpoint command inline. Be " + "sure to surround it with quotes.">; + def breakpoint_add_stop_on_error : Option<"stop-on-error", "e">, + Arg<"Boolean">, Desc<"Specify whether breakpoint command execution should " + "terminate on error.">; + def breakpoint_add_script_type : Option<"script-type", "s">, + EnumArg<"None", "ScriptOptionEnum()">, + Desc<"Specify the language for the commands - if none is specified, the " + "lldb command interpreter will be used.">; + def breakpoint_add_python_function : Option<"python-function", "F">, + Group<2>, Arg<"PythonFunction">, + Desc<"Give the name of a Python function to run as command for this " + "breakpoint. Be sure to give a module name if appropriate.">; + def breakpoint_add_dummy_breakpoints : Option<"dummy-breakpoints", "D">, + Desc<"Sets Dummy breakpoints - i.e. breakpoints set before a file is " + "provided, which prime new targets.">; +} + +let Command = "breakpoint command delete" in { + def breakpoint_command_delete_dummy_breakpoints : + Option<"dummy-breakpoints", "D">, Group<1>, + Desc<"Delete commands from Dummy breakpoints - i.e. breakpoints set before " + "a file is provided, which prime new targets.">; +} + +let Command = "disassemble" in { + def disassemble_options_bytes : Option<"bytes", "b">, + Desc<"Show opcode bytes when disassembling.">; + def disassemble_options_context : Option<"context", "C">, Arg<"NumLines">, + Desc<"Number of context lines of source to show.">; + def disassemble_options_mixed : Option<"mixed", "m">, + Desc<"Enable mixed source and assembly display.">; + def disassemble_options_raw : Option<"raw", "r">, + Desc<"Print raw disassembly with no symbol information.">; + def disassemble_options_plugin : Option<"plugin", "P">, Arg<"Plugin">, + Desc<"Name of the disassembler plugin you want to use.">; + def disassemble_options_flavor : Option<"flavor", "F">, + Arg<"DisassemblyFlavor">, Desc<"Name of the disassembly flavor you want to " + "use. Currently the only valid options are default, and for Intel " + "architectures, att and intel.">; + def disassemble_options_arch : Option<"arch", "A">, Arg<"Architecture">, + Desc<"Specify the architecture to use from cross disassembly.">; + def disassemble_options_start_address : Option<"start-address", "s">, + Groups<[1,2]>, Arg<"AddressOrExpression">, Required, + Desc<"Address at which to start disassembling.">; + def disassemble_options_end_address : Option<"end-address", "e">, Group<1>, + Arg<"AddressOrExpression">, Desc<"Address at which to end disassembling.">; + def disassemble_options_count : Option<"count", "c">, Groups<[2,3,4,5]>, + Arg<"NumLines">, Desc<"Number of instructions to display.">; + def disassemble_options_name : Option<"name", "n">, Group<3>, + Arg<"FunctionName">, Completion<"Symbol">, + Desc<"Disassemble entire contents of the given function name.">; + def disassemble_options_frame : Option<"frame", "f">, Group<4>, + Desc<"Disassemble from the start of the current frame's function.">; + def disassemble_options_pc : Option<"pc", "p">, Group<5>, + Desc<"Disassemble around the current pc.">; + def disassemble_options_line : Option<"line", "l">, Group<6>, + Desc<"Disassemble the current frame's current source line instructions if" + "there is debug line table information, else disassemble around the pc.">; + def disassemble_options_address : Option<"address", "a">, Group<7>, + Arg<"AddressOrExpression">, + Desc<"Disassemble function containing this address.">; +} + +let Command = "expression" in { + def expression_options_all_threads : Option<"all-threads", "a">, + Groups<[1,2]>, Arg<"Boolean">, Desc<"Should we run all threads if the " + "execution doesn't complete on one thread.">; + def expression_options_ignore_breakpoints : Option<"ignore-breakpoints", "i">, + Groups<[1,2]>, Arg<"Boolean">, + Desc<"Ignore breakpoint hits while running expressions">; + def expression_options_timeout : Option<"timeout", "t">, Groups<[1,2]>, + Arg<"UnsignedInteger">, + Desc<"Timeout value (in microseconds) for running the expression.">; + def expression_options_unwind_on_error : Option<"unwind-on-error", "u">, + Groups<[1,2]>, Arg<"Boolean">, + Desc<"Clean up program state if the expression causes a crash, or raises a " + "signal. Note, unlike gdb hitting a breakpoint is controlled by another " + "option (-i).">; + def expression_options_debug : Option<"debug", "g">, Groups<[1,2]>, + Desc<"When specified, debug the JIT code by setting a breakpoint on the " + "first instruction and forcing breakpoints to not be ignored (-i0) and no " + "unwinding to happen on error (-u0).">; + def expression_options_language : Option<"language", "l">, Groups<[1,2]>, + Arg<"Language">, Desc<"Specifies the Language to use when parsing the " + "expression. If not set the target.language setting is used.">; + def expression_options_apply_fixits : Option<"apply-fixits", "X">, + Groups<[1,2]>, Arg<"Language">, Desc<"If true, simple fix-it hints will be " + "automatically applied to the expression.">; + def expression_options_description_verbosity : + Option<"description-verbosity", "v">, Group<1>, + OptionalEnumArg<"DescriptionVerbosity", "DescriptionVerbosityTypes()">, + Desc<"How verbose should the output of this expression be, if the object " + "description is asked for.">; + def expression_options_top_level : Option<"top-level", "p">, Groups<[1,2]>, + Desc<"Interpret the expression as a complete translation unit, without " + "injecting it into the local context. Allows declaration of persistent, " + "top-level entities without a $ prefix.">; + def expression_options_allow_jit : Option<"allow-jit", "j">, Groups<[1,2]>, + Arg<"Boolean">, + Desc<"Controls whether the expression can fall back to being JITted if it's" + "not supported by the interpreter (defaults to true).">; +} + +let Command = "frame diag" in { + def frame_diag_register : Option<"register", "r">, Group<1>, + Arg<"RegisterName">, Desc<"A register to diagnose.">; + def frame_diag_address : Option<"address", "a">, Group<1>, Arg<"Address">, + Desc<"An address to diagnose.">; + def frame_diag_offset : Option<"offset", "o">, Group<1>, Arg<"Offset">, + Desc<"An optional offset. Requires --register.">; +} + +let Command = "frame select" in { + def frame_select_relative : Option<"relative", "r">, Group<1>, Arg<"Offset">, + Desc<"A relative frame index offset from the current frame index.">; +} + +let Command = "frame recognizer add" in { + def frame_recognizer_shlib : Option<"shlib", "s">, Arg<"ShlibName">, + Completion<"Module">, + Desc<"Name of the module or shared library that this recognizer applies " + "to.">; + def frame_recognizer_function : Option<"function", "n">, Arg<"Name">, + Completion<"Symbol">, + Desc<"Name of the function that this recognizer applies to.">; + def frame_recognizer_python_class : Option<"python-class", "l">, Group<2>, + Arg<"PythonClass">, + Desc<"Give the name of a Python class to use for this frame recognizer.">; + def frame_recognizer_regex : Option<"regex", "x">, + Desc<"Function name and module name are actually regular expressions.">; +} + +let Command = "history" in { + def history_count : Option<"count", "c">, Group<1>, Arg<"UnsignedInteger">, + Desc<"How many history commands to print.">; + def history_start_index : Option<"start-index", "s">, Group<1>, + Arg<"UnsignedInteger">, Desc<"Index at which to start printing history " + "commands (or end to mean tail mode).">; + def history_end_index : Option<"end-index", "e">, Group<1>, + Arg<"UnsignedInteger">, + Desc<"Index at which to stop printing history commands.">; + def history_clear : Option<"clear", "C">, Group<2>, + Desc<"Clears the current command history.">; +} + +let Command = "log" in { + def log_file : Option<"file", "f">, Group<1>, Arg<"Filename">, + Desc<"Set the destination file to log to.">; + def log_threadsafe : Option<"threadsafe", "t">, Group<1>, + Desc<"Enable thread safe logging to avoid interweaved log lines.">; + def log_verbose : Option<"verbose", "v">, Group<1>, + Desc<"Enable verbose logging.">; + def log_sequence : Option<"sequence", "s">, Group<1>, + Desc<"Prepend all log lines with an increasing integer sequence id.">; + def log_timestamp : Option<"timestamp", "T">, Group<1>, + Desc<"Prepend all log lines with a timestamp.">; + def log_pid_tid : Option<"pid-tid", "p">, Group<1>, + Desc<"Prepend all log lines with the process and thread ID that generates " + "the log line.">; + def log_thread_name : Option<"thread-name", "n">, Group<1>, + Desc<"Prepend all log lines with the thread name for the thread that " + "generates the log line.">; + + def log_stack : Option<"stack", "S">, Group<1>, + Desc<"Append a stack backtrace to each log line.">; + def log_append : Option<"append", "a">, Group<1>, + Desc<"Append to the log file instead of overwriting.">; + def log_file_function : Option<"file-function", "F">, Group<1>, + Desc<"Prepend the names of files and function that generate the logs.">; +} + +let Command = "reproducer" in { + def reproducer_provider : Option<"provider", "p">, Group<1>, + EnumArg<"None", "ReproducerProviderType()">, + Required, Desc<"The reproducer provider to dump.">; + def reproducer_file : Option<"file", "f">, Group<1>, Arg<"Filename">, + Desc<"The reproducer path. If a reproducer is replayed and no path is " + "provided, that reproducer is dumped.">; +} + +let Command = "memory read" in { + def memory_read_num_per_line : Option<"num-per-line", "l">, Group<1>, + Arg<"NumberPerLine">, Desc<"The number of items per line to display.">; + def memory_read_binary : Option<"binary", "b">, Group<2>, + Desc<"If true, memory will be saved as binary. If false, the memory is " + "saved save as an ASCII dump that uses the format, size, count and number " + "per line settings.">; + def memory_read_type : Option<"type", "t">, Groups<[3,4]>, Arg<"Name">, + Required, Desc<"The name of a type to view memory as.">; + def memory_read_language : Option<"language", "x">, Group<4>, Arg<"Language">, + Desc<"The language of the type to view memory as.">; + def memory_read_offset : Option<"offset", "E">, Group<3>, Arg<"Count">, + Desc<"How many elements of the specified type to skip before starting to " + "display data.">; + def memory_read_force : Option<"force", "r">, Groups<[1,2,3]>, + Desc<"Necessary if reading over target.max-memory-read-size bytes.">; +} + +let Command = "memory find" in { + def memory_find_expression : Option<"expression", "e">, Group<1>, + Arg<"Expression">, Required, + Desc<"Evaluate an expression to obtain a byte pattern.">; + def memory_find_string : Option<"string", "s">, Group<2>, Arg<"Name">, + Required, Desc<"Use text to find a byte pattern.">; + def memory_find_count : Option<"count", "c">, Arg<"Count">, + Desc<"How many times to perform the search.">; + def memory_find_dump_offset : Option<"dump-offset", "o">, Arg<"Offset">, + Desc<"When dumping memory for a match, an offset from the match location to" + " start dumping from.">; +} + +let Command = "memory write" in { + def memory_write_infile : Option<"infile", "i">, Group<1>, Arg<"Filename">, + Required, Desc<"Write memory using the contents of a file.">; + def memory_write_offset : Option<"offset", "o">, Group<1>, Arg<"Offset">, + Desc<"Start writing bytes from an offset within the input file.">; +} + +let Command = "register read" in { + def register_read_alternate : Option<"alternate", "A">, + Desc<"Display register names using the alternate register name if there " + "is one.">; + def register_read_set : Option<"set", "s">, Group<1>, Arg<"Index">, + Desc<"Specify which register sets to dump by index.">; + def register_read_all : Option<"all", "a">, Group<2>, + Desc<"Show all register sets.">; +} + +let Command = "source" in { + def source_stop_on_error : Option<"stop-on-error", "e">, Arg<"Boolean">, + Desc<"If true, stop executing commands on error.">; + def source_stop_on_continue : Option<"stop-on-continue", "c">, Arg<"Boolean">, + Desc<"If true, stop executing commands on continue.">; + def source_silent_run : Option<"silent-run", "s">, Arg<"Boolean">, + Desc<"If true don't echo commands while executing.">; +} + +let Command = "alias" in { + def alias_help : Option<"help", "h">, Arg<"HelpText">, + Desc<"Help text for this command">; + def alias_long_help : Option<"long-help", "H">, Arg<"HelpText">, + Desc<"Long help text for this command">; +} + +let Command = "regex" in { + def regex_help : Option<"help", "h">, Group<1>, Arg<"None">, + Desc<"The help text to display for this command.">; + def regex_syntax : Option<"syntax", "s">, Group<1>, Arg<"None">, + Desc<"A syntax string showing the typical usage syntax.">; +} + +let Command = "permissions" in { + def permissions_permissions_value : Option<"permissions-value", "v">, + Arg<"PermissionsNumber">, + Desc<"Give out the numeric value for permissions (e.g. 757)">; + def permissions_permissions_string : Option<"permissions-string", "s">, + Arg<"PermissionsString">, + Desc<"Give out the string value for permissions (e.g. rwxr-xr--).">; + def permissions_user_read : Option<"user-read", "r">, + Desc<"Allow user to read.">; + def permissions_user_write : Option<"user-write", "w">, + Desc<"Allow user to write.">; + def permissions_user_exec : Option<"user-exec", "x">, + Desc<"Allow user to execute.">; + def permissions_group_read : Option<"group-read", "R">, + Desc<"Allow group to read.">; + def permissions_group_write : Option<"group-write", "W">, + Desc<"Allow group to write.">; + def permissions_group_exec : Option<"group-exec", "X">, + Desc<"Allow group to execute.">; + def permissions_world_read : Option<"world-read", "d">, + Desc<"Allow world to read.">; + def permissions_world_write : Option<"world-write", "t">, + Desc<"Allow world to write.">; + def permissions_world_exec : Option<"world-exec", "e">, + Desc<"Allow world to execute.">; +} + +let Command = "platform fread" in { + def platform_fread_offset : Option<"offset", "o">, Group<1>, Arg<"Index">, + Desc<"Offset into the file at which to start reading.">; + def platform_fread_count : Option<"count", "c">, Group<1>, Arg<"Count">, + Desc<"Number of bytes to read from the file.">; +} + +let Command = "platform fwrite" in { + def platform_fwrite_offset : Option<"offset", "o">, Group<1>, Arg<"Index">, + Desc<"Offset into the file at which to start reading.">; + def platform_fwrite_data : Option<"data", "d">, Group<1>, Arg<"Value">, + Desc<"Text to write to the file.">; +} + +let Command = "platform process list" in { + def platform_process_list_pid : Option<"pid", "p">, Group<1>, Arg<"Pid">, + Desc<"List the process info for a specific process ID.">; + def platform_process_list_name : Option<"name", "n">, Group<2>, + Arg<"ProcessName">, Required, + Desc<"Find processes with executable basenames that match a string.">; + def platform_process_list_ends_with : Option<"ends-with", "e">, Group<3>, + Arg<"ProcessName">, Required, + Desc<"Find processes with executable basenames that end with a string.">; + def platform_process_list_starts_with : Option<"starts-with", "s">, Group<4>, + Arg<"ProcessName">, Required, + Desc<"Find processes with executable basenames that start with a string.">; + def platform_process_list_contains : Option<"contains", "c">, Group<5>, + Arg<"ProcessName">, Required, + Desc<"Find processes with executable basenames that contain a string.">; + def platform_process_list_regex : Option<"regex", "r">, Group<6>, + Arg<"RegularExpression">, Required, + Desc<"Find processes with executable basenames that match a regular " + "expression.">; + def platform_process_list_parent : Option<"parent", "P">, GroupRange<2, 6>, + Arg<"Pid">, Desc<"Find processes that have a matching parent process ID.">; + def platform_process_list_uid : Option<"uid", "u">, GroupRange<2, 6>, + Arg<"UnsignedInteger">, Validator<"&posix_validator">, + Desc<"Find processes that have a matching user ID.">; + def platform_process_list_euid : Option<"euid", "U">, GroupRange<2, 6>, + Arg<"UnsignedInteger">, Validator<"&posix_validator">, + Desc<"Find processes that have a matching effective user ID.">; + def platform_process_list_gid : Option<"gid", "g">, GroupRange<2, 6>, + Arg<"UnsignedInteger">, Validator<"&posix_validator">, + Desc<"Find processes that have a matching group ID.">; + def platform_process_list_egid : Option<"egid", "G">, GroupRange<2, 6>, + Arg<"UnsignedInteger">, Validator<"&posix_validator">, + Desc<"Find processes that have a matching effective group ID.">; + def platform_process_list_arch : Option<"arch", "a">, GroupRange<2, 6>, + Arg<"Architecture">, + Desc<"Find processes that have a matching architecture.">; + def platform_process_list_show_args : Option<"show-args", "A">, + GroupRange<1, 6>, + Desc<"Show process arguments instead of the process executable basename.">; + def platform_process_list_all_users: Option<"all-users", "x">, + GroupRange<1,6>, + Desc<"Show processes matching all user IDs.">; + def platform_process_list_verbose : Option<"verbose", "v">, GroupRange<1, 6>, + Desc<"Enable verbose output.">; +} + +let Command = "platform process attach" in { + def platform_process_attach_plugin : Option<"plugin", "P">, Arg<"Plugin">, + Desc<"Name of the process plugin you want to use.">; + def platform_process_attach_pid : Option<"pid", "p">, Group<1>, Arg<"Pid">, + Desc<"The process ID of an existing process to attach to.">; + def platform_process_attach_name : Option<"name", "n">, Group<2>, + Arg<"ProcessName">, Desc<"The name of the process to attach to.">; + def platform_process_attach_waitfor : Option<"waitfor", "w">, Group<2>, + Desc<"Wait for the process with <process-name> to launch.">; +} + +let Command = "platform shell" in { + def platform_shell_timeout : Option<"timeout", "t">, Arg<"Value">, + Desc<"Seconds to wait for the remote host to finish running the command.">; +} + +let Command = "process attach" in { + def process_attach_continue : Option<"continue", "c">, + Desc<"Immediately continue the process once attached.">; + def process_attach_plugin : Option<"plugin", "P">, Arg<"Plugin">, + Desc<"Name of the process plugin you want to use.">; + def process_attach_pid : Option<"pid", "p">, Group<1>, Arg<"Pid">, + Desc<"The process ID of an existing process to attach to.">; + def process_attach_name : Option<"name", "n">, Group<2>, Arg<"ProcessName">, + Desc<"The name of the process to attach to.">; + def process_attach_include_existing : Option<"include-existing", "i">, + Group<2>, Desc<"Include existing processes when doing attach -w.">; + def process_attach_waitfor : Option<"waitfor", "w">, Group<2>, + Desc<"Wait for the process with <process-name> to launch.">; +} + +let Command = "process continue" in { + def process_continue_ignore_count : Option<"ignore-count", "i">, + Arg<"UnsignedInteger">, Desc<"Ignore <N> crossings of the breakpoint (if it" + " exists) for the currently selected thread.">; +} + +let Command = "process detach" in { + def process_detach_keep_stopped : Option<"keep-stopped", "s">, Group<1>, + Arg<"Boolean">, Desc<"Whether or not the process should be kept stopped on" + " detach (if possible).">; +} + +let Command = "process connect" in { + def process_connect_plugin : Option<"plugin", "p">, Arg<"Plugin">, + Desc<"Name of the process plugin you want to use.">; +} + +let Command = "process load" in { + def process_load_install : Option<"install", "i">, OptionalArg<"Path">, + Desc<"Install the shared library to the target. If specified without an " + "argument then the library will installed in the current working " + "directory.">; +} + +let Command = "process handle" in { + def process_handle_stop : Option<"stop", "s">, Group<1>, Arg<"Boolean">, + Desc<"Whether or not the process should be stopped if the signal is " + "received.">; + def process_handle_notify : Option<"notify", "n">, Group<1>, Arg<"Boolean">, + Desc<"Whether or not the debugger should notify the user if the signal is " + "received.">; + def process_handle_pass : Option<"pass", "p">, Group<1>, Arg<"Boolean">, + Desc<"Whether or not the signal should be passed to the process.">; +} + +let Command = "script import" in { + def script_import_allow_reload : Option<"allow-reload", "r">, Group<1>, + Desc<"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.">; +} + +let Command = "script add" in { + def script_add_function : Option<"function", "f">, Group<1>, + Arg<"PythonFunction">, + Desc<"Name of the Python function to bind to this command name.">; + def script_add_class : Option<"class", "c">, Group<2>, Arg<"PythonClass">, + Desc<"Name of the Python class to bind to this command name.">; + def script_add_help : Option<"help", "h">, Group<1>, Arg<"HelpText">, + Desc<"The help text to display for this command.">; + def script_add_synchronicity : Option<"synchronicity", "s">, + EnumArg<"ScriptedCommandSynchronicity", "ScriptSynchroType()">, + Desc<"Set the synchronicity of this command's executions with regard to " + "LLDB event system.">; +} +let Command = "source info" in { + def source_info_count : Option<"count", "c">, Arg<"Count">, + Desc<"The number of line entries to display.">; + def source_info_shlib : Option<"shlib", "s">, Groups<[1,2]>, Arg<"ShlibName">, + Completion<"Module">, Desc<"Look up the source in the given module or " + "shared library (can be specified more than once).">; + def source_info_file : Option<"file", "f">, Group<1>, Arg<"Filename">, + Completion<"SourceFile">, Desc<"The file from which to display source.">; + def source_info_line : Option<"line", "l">, Group<1>, Arg<"LineNum">, + Desc<"The line number at which to start the displaying lines.">; + def source_info_end_line : Option<"end-line", "e">, Group<1>, Arg<"LineNum">, + Desc<"The line number at which to stop displaying lines.">; + def source_info_name : Option<"name", "n">, Group<2>, Arg<"Symbol">, + Completion<"Symbol">, + Desc<"The name of a function whose source to display.">; + def source_info_address : Option<"address", "a">, Group<3>, + Arg<"AddressOrExpression">, Desc<"Lookup the address and display the source" + " information for the corresponding file and line.">; +} + +let Command = "source list" in { + def source_list_count : Option<"count", "c">, Arg<"Count">, + Desc<"The number of source lines to display.">; + def source_list_shlib : Option<"shlib", "s">, Groups<[1,2]>, Arg<"ShlibName">, + Completion<"Module">, + Desc<"Look up the source file in the given shared library.">; + def source_list_show_breakpoints : Option<"show-breakpoints", "b">, + Desc<"Show the line table locations from the debug information that " + "indicate valid places to set source level breakpoints.">; + def source_list_file : Option<"file", "f">, Group<1>, Arg<"Filename">, + Completion<"SourceFile">, Desc<"The file from which to display source.">; + def source_list_line : Option<"line", "l">, Group<1>, Arg<"LineNum">, + Desc<"The line number at which to start the display source.">; + def source_list_name : Option<"name", "n">, Group<2>, Arg<"Symbol">, + Completion<"Symbol">, + Desc<"The name of a function whose source to display.">; + def source_list_address : Option<"address", "a">, Group<3>, + Arg<"AddressOrExpression">, Desc<"Lookup the address and display the source" + " information for the corresponding file and line.">; + def source_list_reverse : Option<"reverse", "r">, Group<4>, Desc<"Reverse the" + " listing to look backwards from the last displayed block of source.">; +} + +let Command = "target dependents" in { + def dependents_no_dependents : Option<"no-dependents", "d">, Group<1>, + OptionalEnumArg<"Value", "OptionEnumValues(g_dependents_enumaration)">, + Desc<"Whether or not to load dependents when creating a target. If the " + "option is not specified, the value is implicitly 'default'. If the " + "option is specified but without a value, the value is implicitly " + "'true'.">; +} + +let Command = "target modules dump" in { + def target_modules_dump_verbose : Option<"verbose", "v">, + Desc<"Enable verbose dump.">; +} + +let Command = "target modules list" in { + def target_modules_list_address : Option<"address", "a">, Group<1>, + Arg<"AddressOrExpression">, Desc<"Display the image at this address.">; + def target_modules_list_arch : Option<"arch", "A">, Group<1>, + OptionalArg<"Width">, Desc<"Display the architecture when listing images.">; + def target_modules_list_triple : Option<"triple", "t">, Group<1>, + OptionalArg<"Width">, Desc<"Display the triple when listing images.">; + def target_modules_list_header : Option<"header", "h">, Group<1>, + Desc<"Display the image base address as a load address if debugging, a file" + " address otherwise.">; + def target_modules_list_offset : Option<"offset", "o">, Group<1>, + Desc<"Display the image load address offset from the base file address " + "(the slide amount).">; + def target_modules_list_uuid : Option<"uuid", "u">, Group<1>, + Desc<"Display the UUID when listing images.">; + def target_modules_list_fullpath : Option<"fullpath", "f">, Group<1>, + OptionalArg<"Width">, + Desc<"Display the fullpath to the image object file.">; + def target_modules_list_directory : Option<"directory", "d">, Group<1>, + OptionalArg<"Width">, Desc<"Display the directory with optional width for " + "the image object file.">; + def target_modules_list_basename : Option<"basename", "b">, Group<1>, + OptionalArg<"Width">, Desc<"Display the basename with optional width for " + "the image object file.">; + def target_modules_list_symfile : Option<"symfile", "s">, Group<1>, + OptionalArg<"Width">, Desc<"Display the fullpath to the image symbol file " + "with optional width.">; + def target_modules_list_symfile_unique : Option<"symfile-unique", "S">, + Group<1>, OptionalArg<"Width">, Desc<"Display the symbol file with optional" + " width only if it is different from the executable object file.">; + def target_modules_list_mod_time : Option<"mod-time", "m">, Group<1>, + OptionalArg<"Width">, Desc<"Display the modification time with optional " + "width of the module.">; + def target_modules_list_ref_count : Option<"ref-count", "r">, Group<1>, + OptionalArg<"Width">, Desc<"Display the reference count if the module is " + "still in the shared module cache.">; + def target_modules_list_pointer : Option<"pointer", "p">, Group<1>, + OptionalArg<"None">, Desc<"Display the module pointer.">; + def target_modules_list_global : Option<"global", "g">, Group<1>, + Desc<"Display the modules from the global module list, not just the " + "current target.">; +} + +let Command = "target modules show unwind" in { + def target_modules_show_unwind_name : Option<"name", "n">, Group<1>, + Arg<"FunctionName">, + Desc<"Show unwind instructions for a function or symbol name.">; + def target_modules_show_unwind_address : Option<"address", "a">, Group<2>, + Arg<"AddressOrExpression">, Desc<"Show unwind instructions for a function " + "or symbol containing an address">; +} + +let Command = "target modules lookup" in { + def target_modules_lookup_address : Option<"address", "a">, Group<1>, + Arg<"AddressOrExpression">, Required, Desc<"Lookup an address in one or " + "more target modules.">; + def target_modules_lookup_offset : Option<"offset", "o">, Group<1>, + Arg<"Offset">, Desc<"When looking up an address subtract <offset> from any " + "addresses before doing the lookup.">; + // FIXME: re-enable regex for types when the LookupTypeInModule actually uses + // the regex option by adding to group 6. + def target_modules_lookup_regex : Option<"regex", "r">, Groups<[2,4,5]>, + Desc<"The <name> argument for name lookups are regular expressions.">; + def target_modules_lookup_symbol : Option<"symbol", "s">, Group<2>, + Arg<"Symbol">, Required, Desc<"Lookup a symbol by name in the symbol tables" + " in one or more target modules.">; + def target_modules_lookup_file : Option<"file", "f">, Group<3>, + Arg<"Filename">, Required, Desc<"Lookup a file by fullpath or basename in " + "one or more target modules.">; + def target_modules_lookup_line : Option<"line", "l">, Group<3>, + Arg<"LineNum">, Desc<"Lookup a line number in a file (must be used in " + "conjunction with --file).">; + def target_modules_lookup_no_inlines : Option<"no-inlines", "i">, + GroupRange<3,5>, + Desc<"Ignore inline entries (must be used in conjunction with --file or " + "--function).">; + def target_modules_lookup_function : Option<"function", "F">, Group<4>, + Arg<"FunctionName">, Required, Desc<"Lookup a function by name in the debug" + " symbols in one or more target modules.">; + def target_modules_lookup_name : Option<"name", "n">, Group<5>, + Arg<"FunctionOrSymbol">, Required, Desc<"Lookup a function or symbol by " + "name in one or more target modules.">; + def target_modules_lookup_type : Option<"type", "t">, Group<6>, Arg<"Name">, + Required, Desc<"Lookup a type by name in the debug symbols in one or more " + "target modules.">; + def target_modules_lookup_verbose : Option<"verbose", "v">, + Desc<"Enable verbose lookup information.">; + def target_modules_lookup_all : Option<"all", "A">, Desc<"Print all matches, " + "not just the best match, if a best match is available.">; +} + +let Command = "target stop hook add" in { + def target_stop_hook_add_one_liner : Option<"one-liner", "o">, + Arg<"OneLiner">, Desc<"Add a command for the stop hook. Can be specified " + "more than once, and commands will be run in the order they appear.">; + def target_stop_hook_add_shlib : Option<"shlib", "s">, Arg<"ShlibName">, + Completion<"Module">, + Desc<"Set the module within which the stop-hook is to be run.">; + def target_stop_hook_add_thread_index : Option<"thread-index", "x">, + Arg<"ThreadIndex">, Desc<"The stop hook is run only for the thread whose " + "index matches this argument.">; + def target_stop_hook_add_thread_id : Option<"thread-id", "t">, + Arg<"ThreadID">, Desc<"The stop hook is run only for the thread whose TID " + "matches this argument.">; + def target_stop_hook_add_thread_name : Option<"thread-name", "T">, + Arg<"ThreadName">, Desc<"The stop hook is run only for the thread whose " + "thread name matches this argument.">; + def target_stop_hook_add_queue_name : Option<"queue-name", "q">, + Arg<"QueueName">, Desc<"The stop hook is run only for threads in the queue " + "whose name is given by this argument.">; + def target_stop_hook_add_file : Option<"file", "f">, Group<1>, + Arg<"Filename">, Desc<"Specify the source file within which the stop-hook " + "is to be run.">, Completion<"SourceFile">; + def target_stop_hook_add_start_line : Option<"start-line", "l">, Group<1>, + Arg<"LineNum">, Desc<"Set the start of the line range for which the " + "stop-hook is to be run.">; + def target_stop_hook_add_end_line : Option<"end-line", "e">, Group<1>, + Arg<"LineNum">, Desc<"Set the end of the line range for which the stop-hook" + " is to be run.">; + def target_stop_hook_add_classname : Option<"classname", "c">, Group<2>, + Arg<"ClassName">, + Desc<"Specify the class within which the stop-hook is to be run.">; + def target_stop_hook_add_name : Option<"name", "n">, Group<3>, + Arg<"FunctionName">, Desc<"Set the function name within which the stop hook" + " will be run.">, Completion<"Symbol">; + def target_stop_hook_add_auto_continue : Option<"auto-continue", "G">, + Arg<"Boolean">, Desc<"The breakpoint will auto-continue after running its" + " commands.">; +} + let Command = "thread backtrace" in { def thread_backtrace_count : Option<"count", "c">, Group<1>, Arg<"Count">, Desc<"How many frames to display (-1 for all)">; diff --git a/source/Commands/OptionsBase.td b/source/Commands/OptionsBase.td index a81563ed28c2..f6967f067bf4 100644 --- a/source/Commands/OptionsBase.td +++ b/source/Commands/OptionsBase.td @@ -41,15 +41,19 @@ // - `OptionalArg`: Sets the argument type and marks it as optional. // - `Arg`: Sets the argument type and marks it as required. // - `EnumArg`: Sets the argument type to an enum and marks it as required. +// - `OptionalEnumArg`: Same as EnumArg but marks it as optional. // See argument_type field for more info. //////////////////////////////////////////////////////////////////////////////// // Field: validator // Default value: 0 (No validator for option) -// Set by: Nothing. This is currently only set after initialization in LLDB. +// Set by: +// - `Validator`: Sets the value to a given validator (which has to exist in +// the surrounding code. //////////////////////////////////////////////////////////////////////////////// // Field: enum_values // Default value: {} (No enum associated with this option) // Set by: +// - `OptionalEnumArg`: // - `EnumArg`: Sets the argument type and assigns it a enum holding the valid // values. The enum needs to be a variable in the including code. // Marks the option as required (see option_has_arg). @@ -82,12 +86,14 @@ // Example: def foo : Option<"foo", "f">, Arg<"Pid">; // Sets the argument type to eArgTypePid and marks option as // required (see option_has_arg). +// - `OptionalEnumArg`: // - `EnumArg`: Sets the argument type and assigns it a enum holding the valid // values. The enum needs to be a variable in the including code. // Marks the option as required (see option_has_arg). // Example: def foo : Option<"foo", "f">, // EnumArg<"SortOrder", // "OptionEnumValues(g_sort_option_enumeration)">; +// Use `OptionalEnumArg` for having an option enum argument. //////////////////////////////////////////////////////////////////////////////// // Field: usage_text // Default value: "" @@ -150,6 +156,13 @@ class EnumArg<string type, string enum> { string ArgEnum = enum; } +// Gives the option an required argument. +class OptionalEnumArg<string type, string enum> { + string ArgType = type; + string ArgEnum = enum; + bit OptionalArg = 1; +} + // Sets the available completions for the given option. class Completions<list<string> completions> { list<string> Completions = completions; @@ -158,3 +171,8 @@ class Completions<list<string> completions> { class Completion<string completion> { list<string> Completions = [completion]; } + +// Sets the validator for a given option. +class Validator<string validator> { + string Validator = validator; +} |