diff options
Diffstat (limited to 'lldb')
114 files changed, 1925 insertions, 1132 deletions
diff --git a/lldb/include/lldb/Core/EmulateInstruction.h b/lldb/include/lldb/Core/EmulateInstruction.h index f50fee095a8b..e5421e5e91d1 100644 --- a/lldb/include/lldb/Core/EmulateInstruction.h +++ b/lldb/include/lldb/Core/EmulateInstruction.h @@ -179,7 +179,7 @@ public: eInfoTypeISAAndImmediateSigned, eInfoTypeISA, eInfoTypeNoArgs - } InfoType; + }; struct Context { ContextType type = eContextInvalid; diff --git a/lldb/include/lldb/DataFormatters/TypeCategory.h b/lldb/include/lldb/DataFormatters/TypeCategory.h index 2c9305901837..16255f9488bd 100644 --- a/lldb/include/lldb/DataFormatters/TypeCategory.h +++ b/lldb/include/lldb/DataFormatters/TypeCategory.h @@ -331,7 +331,7 @@ private: std::vector<lldb::LanguageType> m_languages; - uint32_t m_enabled_position; + uint32_t m_enabled_position = 0; void Enable(bool value, uint32_t position); diff --git a/lldb/include/lldb/DataFormatters/TypeSynthetic.h b/lldb/include/lldb/DataFormatters/TypeSynthetic.h index 3f58297a529b..890a6eb4f448 100644 --- a/lldb/include/lldb/DataFormatters/TypeSynthetic.h +++ b/lldb/include/lldb/DataFormatters/TypeSynthetic.h @@ -266,7 +266,7 @@ public: uint32_t &GetRevision() { return m_my_revision; } protected: - uint32_t m_my_revision; + uint32_t m_my_revision = 0; Flags m_flags; private: diff --git a/lldb/include/lldb/Expression/Materializer.h b/lldb/include/lldb/Expression/Materializer.h index 25cf22a8b5b0..aae94f86a71e 100644 --- a/lldb/include/lldb/Expression/Materializer.h +++ b/lldb/include/lldb/Expression/Materializer.h @@ -78,6 +78,28 @@ public: AddPersistentVariable(lldb::ExpressionVariableSP &persistent_variable_sp, PersistentVariableDelegate *delegate, Status &err); uint32_t AddVariable(lldb::VariableSP &variable_sp, Status &err); + + /// Create entity from supplied ValueObject and count it as a member + /// of the materialized struct. + /// + /// Behaviour is undefined if 'valobj_provider' is empty. + /// + /// \param[in] name Name of variable to materialize + /// + /// \param[in] valobj_provider When materializing values multiple + /// times, this callback gets used to fetch a fresh + /// ValueObject corresponding to the supplied frame. + /// This is mainly used for conditional breakpoints + /// that re-apply an expression whatever the frame + /// happens to be when the breakpoint got hit. + /// + /// \param[out] err Error status that gets set on error. + /// + /// \returns Offset in bytes of the member we just added to the + /// materialized struct. + uint32_t AddValueObject(ConstString name, + ValueObjectProviderTy valobj_provider, Status &err); + uint32_t AddResultVariable(const CompilerType &type, bool is_lvalue, bool keep_in_memory, PersistentVariableDelegate *delegate, Status &err); diff --git a/lldb/include/lldb/Expression/UserExpression.h b/lldb/include/lldb/Expression/UserExpression.h index 3874a60e06f0..2d62fa37a24c 100644 --- a/lldb/include/lldb/Expression/UserExpression.h +++ b/lldb/include/lldb/Expression/UserExpression.h @@ -280,6 +280,23 @@ protected: static lldb::addr_t GetObjectPointer(lldb::StackFrameSP frame_sp, ConstString &object_name, Status &err); + /// Return ValueObject for a given variable name in the current stack frame + /// + /// \param[in] frame Current stack frame. When passed a 'nullptr', this + /// function returns an empty ValueObjectSP. + /// + /// \param[in] object_name Name of the variable in the current stack frame + /// for which we want the ValueObjectSP. + /// + /// \param[out] err Status object which will get set on error. + /// + /// \returns On success returns a ValueObjectSP corresponding to the variable + /// with 'object_name' in the current 'frame'. Otherwise, returns + /// 'nullptr' (and sets the error status parameter 'err'). + static lldb::ValueObjectSP + GetObjectPointerValueObject(lldb::StackFrameSP frame, + ConstString const &object_name, Status &err); + /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the /// environment. diff --git a/lldb/include/lldb/Interpreter/CommandObject.h b/lldb/include/lldb/Interpreter/CommandObject.h index 0fc1c61bdb92..ad5884e207a1 100644 --- a/lldb/include/lldb/Interpreter/CommandObject.h +++ b/lldb/include/lldb/Interpreter/CommandObject.h @@ -77,17 +77,18 @@ public: explicit operator bool() const { return (help_callback != nullptr); } }; - struct ArgumentTableEntry // Entries in the main argument information table - { + /// Entries in the main argument information table. + struct ArgumentTableEntry { lldb::CommandArgumentType arg_type; const char *arg_name; CommandCompletions::CommonCompletionTypes completion_type; + OptionEnumValues enum_values; ArgumentHelpCallback help_function; const char *help_text; }; - struct CommandArgumentData // Used to build individual command argument lists - { + /// Used to build individual command argument lists. + struct CommandArgumentData { lldb::CommandArgumentType arg_type; ArgumentRepetitionType arg_repetition; /// This arg might be associated only with some particular option set(s). By @@ -199,8 +200,6 @@ public: virtual Options *GetOptions(); - static const ArgumentTableEntry *GetArgumentTable(); - static lldb::CommandArgumentType LookupArgumentName(llvm::StringRef arg_name); static const ArgumentTableEntry * diff --git a/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h b/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h new file mode 100644 index 000000000000..c8ec3b941831 --- /dev/null +++ b/lldb/include/lldb/Interpreter/CommandOptionArgumentTable.h @@ -0,0 +1,334 @@ +//===-- CommandOptionArgumentTable.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 LLDB_INTERPRETER_COMMANDOPTIONARGUMENTTABLE_H +#define LLDB_INTERPRETER_COMMANDOPTIONARGUMENTTABLE_H + +#include "lldb/Interpreter/CommandObject.h" + +namespace lldb_private { + +static constexpr OptionEnumValueElement g_corefile_save_style[] = { + {lldb::eSaveCoreFull, "full", "Create a core file with all memory saved"}, + {lldb::eSaveCoreDirtyOnly, "modified-memory", + "Create a corefile with only modified memory saved"}, + {lldb::eSaveCoreStackOnly, "stack", + "Create a corefile with only stack memory saved"}, +}; + +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", + }, +}; + +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.", + }, +}; + +// Note that the negation in the argument name causes a slightly confusing +// mapping of the enum values. +static constexpr OptionEnumValueElement g_dependents_enumeration[] = { + { + 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.", + }, +}; + +// 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. +static constexpr OptionEnumValueElement g_script_option_enumeration[] = { + { + lldb::eScriptLanguageNone, + "command", + "Commands are in the lldb command interpreter language", + }, + { + lldb::eScriptLanguagePython, + "python", + "Commands are in the Python language.", + }, + { + lldb::eScriptLanguageLua, + "lua", + "Commands are in the Lua language.", + }, + { + lldb::eScriptLanguageNone, + "default", + "Commands are in the default scripting language.", + }, +}; + +static constexpr OptionEnumValueElement g_log_handler_type[] = { + { + eLogHandlerDefault, + "default", + "Use the default (stream) log handler", + }, + { + eLogHandlerStream, + "stream", + "Write log messages to the debugger output stream or to a file if one " + "is specified. A buffer size (in bytes) can be specified with -b. If " + "no buffer size is specified the output is unbuffered.", + }, + { + eLogHandlerCircular, + "circular", + "Write log messages to a fixed size circular buffer. A buffer size " + "(number of messages) must be specified with -b.", + }, + { + eLogHandlerSystem, + "os", + "Write log messages to the operating system log.", + }, +}; + +static constexpr OptionEnumValueElement g_reproducer_provider_type[] = { + { + eReproducerProviderCommands, + "commands", + "Command Interpreter Commands", + }, + { + eReproducerProviderFiles, + "files", + "Files", + }, + { + eReproducerProviderSymbolFiles, + "symbol-files", + "Symbol Files", + }, + { + eReproducerProviderGDB, + "gdb", + "GDB Remote Packets", + }, + { + eReproducerProviderProcessInfo, + "processes", + "Process Info", + }, + { + eReproducerProviderVersion, + "version", + "Version", + }, + { + eReproducerProviderWorkingDirectory, + "cwd", + "Working Directory", + }, + { + eReproducerProviderHomeDirectory, + "home", + "Home Directory", + }, + { + eReproducerProviderNone, + "none", + "None", + }, +}; + +static constexpr OptionEnumValueElement g_reproducer_signaltype[] = { + { + eReproducerCrashSigill, + "SIGILL", + "Illegal instruction", + }, + { + eReproducerCrashSigsegv, + "SIGSEGV", + "Segmentation fault", + }, +}; + +static constexpr OptionEnumValueElement g_script_synchro_type[] = { + { + eScriptedCommandSynchronicitySynchronous, + "synchronous", + "Run synchronous", + }, + { + eScriptedCommandSynchronicityAsynchronous, + "asynchronous", + "Run asynchronous", + }, + { + eScriptedCommandSynchronicityCurrentValue, + "current", + "Do not alter current setting", + }, +}; + +static constexpr OptionEnumValueElement g_running_mode[] = { + {lldb::eOnlyThisThread, "this-thread", "Run only this thread"}, + {lldb::eAllThreads, "all-threads", "Run all threads"}, + {lldb::eOnlyDuringStepping, "while-stepping", + "Run only this thread while stepping"}, +}; + +llvm::StringRef RegisterNameHelpTextCallback(); +llvm::StringRef BreakpointIDHelpTextCallback(); +llvm::StringRef BreakpointIDRangeHelpTextCallback(); +llvm::StringRef BreakpointNameHelpTextCallback(); +llvm::StringRef GDBFormatHelpTextCallback(); +llvm::StringRef FormatHelpTextCallback(); +llvm::StringRef LanguageTypeHelpTextCallback(); +llvm::StringRef SummaryStringHelpTextCallback(); +llvm::StringRef ExprPathHelpTextCallback(); +llvm::StringRef arch_helper(); + +static constexpr CommandObject::ArgumentTableEntry g_argument_table[] = { + // clang-format off + { lldb::eArgTypeAddress, "address", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A valid address in the target program's execution space." }, + { lldb::eArgTypeAddressOrExpression, "address-expression", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "An expression that resolves to an address." }, + { lldb::eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of an abbreviation (alias) for a debugger command." }, + { lldb::eArgTypeAliasOptions, "options-for-aliased-command", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Command options to be used as part of an alias (abbreviation) definition. (See 'help commands alias' for more information.)" }, + { lldb::eArgTypeArchitecture, "arch", CommandCompletions::eArchitectureCompletion, {}, { arch_helper, true }, "The architecture name, e.g. i386 or x86_64." }, + { lldb::eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A Boolean value: 'true' or 'false'" }, + { lldb::eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, {}, { BreakpointIDHelpTextCallback, false }, nullptr }, + { lldb::eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, {}, { BreakpointIDRangeHelpTextCallback, false }, nullptr }, + { lldb::eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eBreakpointNameCompletion, {}, { BreakpointNameHelpTextCallback, false }, nullptr }, + { lldb::eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Number of bytes to use." }, + { lldb::eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Then name of a class from the debug information in the program." }, + { lldb::eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A debugger command (may be multiple words), without any options or arguments." }, + { lldb::eArgTypeCount, "count", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "An unsigned integer." }, + { lldb::eArgTypeDescriptionVerbosity, "description-verbosity", CommandCompletions::eNoCompletion, g_description_verbosity_type, { nullptr, false }, "How verbose the output of 'po' should be." }, + { lldb::eArgTypeDirectoryName, "directory", CommandCompletions::eDiskDirectoryCompletion, {}, { nullptr, false }, "A directory name." }, + { lldb::eArgTypeDisassemblyFlavor, "disassembly-flavor", CommandCompletions::eDisassemblyFlavorCompletion, {}, { nullptr, false }, "A disassembly flavor recognized by your disassembly plugin. Currently the only valid options are \"att\" and \"intel\" for Intel targets" }, + { lldb::eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, {}, { ExprPathHelpTextCallback, true }, nullptr }, + { lldb::eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" }, + { lldb::eArgTypeFileLineColumn, "linespec", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A source specifier in the form file:line[:column]" }, + { lldb::eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, {}, { nullptr, false }, "The name of a file (can include path)." }, + { lldb::eArgTypeFormat, "format", CommandCompletions::eNoCompletion, {}, { FormatHelpTextCallback, true }, nullptr }, + { lldb::eArgTypeFrameIndex, "frame-index", CommandCompletions::eFrameIndexCompletion, {}, { nullptr, false }, "Index into a thread's list of frames." }, + { lldb::eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a function." }, + { lldb::eArgTypeFunctionOrSymbol, "function-or-symbol", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a function or symbol." }, + { lldb::eArgTypeGDBFormat, "gdb-format", CommandCompletions::eNoCompletion, {}, { GDBFormatHelpTextCallback, true }, nullptr }, + { lldb::eArgTypeHelpText, "help-text", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Text to be used as help for some other entity in LLDB" }, + { lldb::eArgTypeIndex, "index", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "An index into a list." }, + { lldb::eArgTypeLanguage, "source-language", CommandCompletions::eTypeLanguageCompletion, {}, { LanguageTypeHelpTextCallback, true }, nullptr }, + { lldb::eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Line number in a source file." }, + { lldb::eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a category within a log channel, e.g. all (try \"log list\" to see a list of all channels and their categories." }, + { lldb::eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." }, + { lldb::eArgTypeMethod, "method", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A C++ method name." }, + { lldb::eArgTypeName, "name", CommandCompletions::eTypeCategoryNameCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The number of lines to use." }, + { lldb::eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The number of items per line to display." }, + { lldb::eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeOneLiner, "one-line-command", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A command that is entered as a single line of text." }, + { lldb::eArgTypePath, "path", CommandCompletions::eDiskFileCompletion, {}, { nullptr, false }, "Path." }, + { lldb::eArgTypePermissionsNumber, "perms-numeric", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Permissions given as an octal number (e.g. 755)." }, + { lldb::eArgTypePermissionsString, "perms=string", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Permissions given as a string value (e.g. rw-r-xr--)." }, + { lldb::eArgTypePid, "pid", CommandCompletions::eProcessIDCompletion, {}, { nullptr, false }, "The process ID number." }, + { lldb::eArgTypePlugin, "plugin", CommandCompletions::eProcessPluginCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeProcessName, "process-name", CommandCompletions::eProcessNameCompletion, {}, { nullptr, false }, "The name of the process." }, + { lldb::eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a Python class." }, + { lldb::eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a Python function." }, + { lldb::eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Source code written in Python." }, + { lldb::eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of the thread queue." }, + { lldb::eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, {}, { RegisterNameHelpTextCallback, true }, nullptr }, + { lldb::eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A POSIX-compliant extended regular expression." }, + { lldb::eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Arguments to be passed to the target program when it starts executing." }, + { lldb::eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, g_running_mode, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeScriptedCommandSynchronicity, "script-cmd-synchronicity", CommandCompletions::eNoCompletion, g_script_synchro_type, { nullptr, false }, "The synchronicity to use to run scripted commands with regard to LLDB event system." }, + { lldb::eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, g_script_option_enumeration, { nullptr, false }, "The scripting language to be used for script-based commands. Supported languages are python and lua." }, + { lldb::eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Any word of interest for search purposes." }, + { lldb::eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "An Objective-C selector name." }, + { lldb::eArgTypeSettingIndex, "setting-index", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "An index into a settings variable that is an array (try 'settings list' to see all the possible settings variables and their types)." }, + { lldb::eArgTypeSettingKey, "setting-key", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A key into a settings variables that is a dictionary (try 'settings list' to see all the possible settings variables and their types)." }, + { lldb::eArgTypeSettingPrefix, "setting-prefix", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a settable internal debugger variable up to a dot ('.'), e.g. 'target.process.'" }, + { lldb::eArgTypeSettingVariableName, "setting-variable-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a settable internal debugger variable. Type 'settings list' to see a complete list of such variables." }, + { lldb::eArgTypeShlibName, "shlib-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The name of a shared library." }, + { lldb::eArgTypeSourceFile, "source-file", CommandCompletions::eSourceFileCompletion, {}, { nullptr, false }, "The name of a source file.." }, + { lldb::eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, g_sort_option_enumeration, { nullptr, false }, "Specify a sort order when dumping lists." }, + { lldb::eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeSummaryString, "summary-string", CommandCompletions::eNoCompletion, {}, { SummaryStringHelpTextCallback, true }, nullptr }, + { lldb::eArgTypeSymbol, "symbol", CommandCompletions::eSymbolCompletion, {}, { nullptr, false }, "Any symbol name (function name, variable, argument, etc.)" }, + { lldb::eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Thread ID number." }, + { lldb::eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Index into the process' list of threads." }, + { lldb::eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The thread's name." }, + { lldb::eArgTypeTypeName, "type-name", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A type name." }, + { lldb::eArgTypeUnsignedInteger, "unsigned-integer", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "An unsigned integer." }, + { lldb::eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." }, + { lldb::eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, {} ,{ nullptr, false }, "The name of a variable in your program." }, + { lldb::eArgTypeValue, "value", CommandCompletions::eNoCompletion, g_dependents_enumeration, { nullptr, false }, "A value could be anything, depending on where and how it is used." }, + { lldb::eArgTypeWidth, "width", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Help text goes here." }, + { lldb::eArgTypeNone, "none", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "No help available for this." }, + { lldb::eArgTypePlatform, "platform-name", CommandCompletions::ePlatformPluginCompletion, {}, { nullptr, false }, "The name of an installed platform plug-in . Type 'platform list' to see a complete list of installed platforms." }, + { lldb::eArgTypeWatchpointID, "watchpt-id", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Watchpoint IDs are positive integers." }, + { lldb::eArgTypeWatchpointIDRange, "watchpt-id-list", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "For example, '1-3' or '1 to 3'." }, + { lldb::eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Specify the type for a watchpoint." }, + { lldb::eArgRawInput, "raw-input", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Free-form text passed to a command without prior interpretation, allowing spaces without requiring quotes. To pass arguments and free form text put two dashes ' -- ' between the last argument and any raw input." }, + { lldb::eArgTypeCommand, "command", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "An LLDB Command line command element." }, + { lldb::eArgTypeColumnNum, "column", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "Column number in a source file." }, + { lldb::eArgTypeModuleUUID, "module-uuid", CommandCompletions::eModuleUUIDCompletion, {}, { nullptr, false }, "A module UUID value." }, + { lldb::eArgTypeSaveCoreStyle, "corefile-style", CommandCompletions::eNoCompletion, g_corefile_save_style, { nullptr, false }, "The type of corefile that lldb will try to create, dependant on this target's capabilities." }, + { lldb::eArgTypeLogHandler, "log-handler", CommandCompletions::eNoCompletion, g_log_handler_type ,{ nullptr, false }, "The log handle that will be used to write out log messages." }, + { lldb::eArgTypeSEDStylePair, "substitution-pair", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A sed-style pattern and target pair." }, + { lldb::eArgTypeRecognizerID, "frame-recognizer-id", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The ID for a stack frame recognizer." }, + { lldb::eArgTypeConnectURL, "process-connect-url", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "A URL-style specification for a remote connection." }, + { lldb::eArgTypeTargetID, "target-id", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The index ID for an lldb Target." }, + { lldb::eArgTypeStopHookID, "stop-hook-id", CommandCompletions::eNoCompletion, {}, { nullptr, false }, "The ID you receive when you create a stop-hook." }, + { lldb::eArgTypeReproducerProvider, "reproducer-provider", CommandCompletions::eNoCompletion, g_reproducer_provider_type, { nullptr, false }, "The reproducer provider." }, + { lldb::eArgTypeReproducerSignal, "reproducer-signal", CommandCompletions::eNoCompletion, g_reproducer_signaltype, { nullptr, false }, "The signal used to emulate a reproducer crash." }, + // clang-format on +}; + +static_assert((sizeof(g_argument_table) / + sizeof(CommandObject::ArgumentTableEntry)) == + lldb::eArgTypeLastArg, + "number of elements in g_argument_table doesn't match " + "CommandArgumentType enumeration"); + +} // namespace lldb_private + +#endif // LLDB_INTERPRETER_COMMANDOPTIONARGUMENTTABLE_H diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index 1470b96f2491..ed0de1b5bce6 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -132,7 +132,7 @@ public: /// Specify debug info should be loaded. /// /// It will be no-op for most implementations except SymbolFileOnDemand. - virtual void SetLoadDebugInfoEnabled() { return; } + virtual void SetLoadDebugInfoEnabled() {} // Compile Unit function calls // Approach 1 - iterator diff --git a/lldb/include/lldb/Target/MemoryRegionInfo.h b/lldb/include/lldb/Target/MemoryRegionInfo.h index 3ef66b403e14..cf38b6ea3345 100644 --- a/lldb/include/lldb/Target/MemoryRegionInfo.h +++ b/lldb/include/lldb/Target/MemoryRegionInfo.h @@ -132,7 +132,7 @@ public: void SetDirtyPageList(std::vector<lldb::addr_t> pagelist) { if (m_dirty_pages) - m_dirty_pages.getValue().clear(); + m_dirty_pages.value().clear(); m_dirty_pages = std::move(pagelist); } diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index 93ea8504f8ba..294fd96bc313 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -59,12 +59,6 @@ enum LoadCWDlldbinitFile { eLoadCWDlldbinitWarn }; -enum LoadDependentFiles { - eLoadDependentsDefault, - eLoadDependentsYes, - eLoadDependentsNo, -}; - enum ImportStdModule { eImportStdModuleFalse, eImportStdModuleFallback, diff --git a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h index c32ce0389116..d869950ab6dd 100644 --- a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h +++ b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h @@ -179,6 +179,7 @@ public: eServerPacketType_QNonStop, eServerPacketType_vStopped, eServerPacketType_vCtrlC, + eServerPacketType_vStdio, }; ServerPacketType GetServerPacketType() const; diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index ad03f7e43056..974cc293709e 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -608,6 +608,8 @@ enum CommandArgumentType { eArgTypeConnectURL, eArgTypeTargetID, eArgTypeStopHookID, + eArgTypeReproducerProvider, + eArgTypeReproducerSignal, eArgTypeLastArg // Always keep this entry as the last entry in this // enumeration!! }; diff --git a/lldb/include/lldb/lldb-private-enumerations.h b/lldb/include/lldb/lldb-private-enumerations.h index 2d13e6ef65e1..310058495882 100644 --- a/lldb/include/lldb/lldb-private-enumerations.h +++ b/lldb/include/lldb/lldb-private-enumerations.h @@ -231,6 +231,29 @@ enum LogHandlerKind { eLogHandlerDefault = eLogHandlerStream, }; +enum ReproducerProvider { + eReproducerProviderCommands, + eReproducerProviderFiles, + eReproducerProviderSymbolFiles, + eReproducerProviderGDB, + eReproducerProviderProcessInfo, + eReproducerProviderVersion, + eReproducerProviderWorkingDirectory, + eReproducerProviderHomeDirectory, + eReproducerProviderNone, +}; + +enum ReproducerCrashSignal { + eReproducerCrashSigill, + eReproducerCrashSigsegv, +}; + +enum LoadDependentFiles { + eLoadDependentsDefault, + eLoadDependentsYes, + eLoadDependentsNo, +}; + inline std::string GetStatDescription(lldb_private::StatisticKind K) { switch (K) { case StatisticKind::ExpressionSuccessful: diff --git a/lldb/include/lldb/lldb-private-types.h b/lldb/include/lldb/lldb-private-types.h index 3be7003cd0fb..1b0d263e2073 100644 --- a/lldb/include/lldb/lldb-private-types.h +++ b/lldb/include/lldb/lldb-private-types.h @@ -106,6 +106,12 @@ struct OptionValidator { typedef struct type128 { uint64_t x[2]; } type128; typedef struct type256 { uint64_t x[4]; } type256; +/// Functor that returns a ValueObjectSP for a variable given its name +/// and the StackFrame of interest. Used primarily in the Materializer +/// to refetch a ValueObject when the ExecutionContextScope changes. +using ValueObjectProviderTy = + std::function<lldb::ValueObjectSP(ConstString, StackFrame *)>; + } // namespace lldb_private #endif // #if defined(__cplusplus) diff --git a/lldb/source/API/SBBreakpoint.cpp b/lldb/source/API/SBBreakpoint.cpp index 5fe8f7fe0583..19b2a4376cf8 100644 --- a/lldb/source/API/SBBreakpoint.cpp +++ b/lldb/source/API/SBBreakpoint.cpp @@ -835,8 +835,7 @@ public: if (bkpt->GetTargetSP() != target_sp) return false; lldb::break_id_t bp_id = bkpt->GetID(); - if (find(m_break_ids.begin(), m_break_ids.end(), bp_id) == - m_break_ids.end()) + if (!llvm::is_contained(m_break_ids, bp_id)) return false; m_break_ids.push_back(bkpt->GetID()); diff --git a/lldb/source/API/SBMemoryRegionInfo.cpp b/lldb/source/API/SBMemoryRegionInfo.cpp index e811bf31c722..23d22fbe86c8 100644 --- a/lldb/source/API/SBMemoryRegionInfo.cpp +++ b/lldb/source/API/SBMemoryRegionInfo.cpp @@ -136,7 +136,7 @@ uint32_t SBMemoryRegionInfo::GetNumDirtyPages() { const llvm::Optional<std::vector<addr_t>> &dirty_page_list = m_opaque_up->GetDirtyPageList(); if (dirty_page_list) - num_dirty_pages = dirty_page_list.getValue().size(); + num_dirty_pages = dirty_page_list.value().size(); return num_dirty_pages; } @@ -147,8 +147,8 @@ addr_t SBMemoryRegionInfo::GetDirtyPageAddressAtIndex(uint32_t idx) { addr_t dirty_page_addr = LLDB_INVALID_ADDRESS; const llvm::Optional<std::vector<addr_t>> &dirty_page_list = m_opaque_up->GetDirtyPageList(); - if (dirty_page_list && idx < dirty_page_list.getValue().size()) - dirty_page_addr = dirty_page_list.getValue()[idx]; + if (dirty_page_list && idx < dirty_page_list.value().size()) + dirty_page_addr = dirty_page_list.value()[idx]; return dirty_page_addr; } diff --git a/lldb/source/Commands/CommandObjectBreakpoint.cpp b/lldb/source/Commands/CommandObjectBreakpoint.cpp index 755cf6c61f26..5d2141d767cb 100644 --- a/lldb/source/Commands/CommandObjectBreakpoint.cpp +++ b/lldb/source/Commands/CommandObjectBreakpoint.cpp @@ -13,6 +13,7 @@ #include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" diff --git a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp index bf0cae51d733..499bc550af45 100644 --- a/lldb/source/Commands/CommandObjectBreakpointCommand.cpp +++ b/lldb/source/Commands/CommandObjectBreakpointCommand.cpp @@ -14,6 +14,7 @@ #include "lldb/Core/IOHandler.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" @@ -22,36 +23,6 @@ using namespace lldb; using namespace lldb_private; -// 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. -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.", - }, - { - eScriptLanguageLua, - "lua", - "Commands are in the Lua language.", - }, - { - eScriptLanguageDefault, - "default-script", - "Commands are in the default scripting language.", - }, -}; - -static constexpr OptionEnumValues ScriptOptionEnum() { - return OptionEnumValues(g_script_option_enumeration); -} - #define LLDB_OPTIONS_breakpoint_command_add #include "CommandOptions.inc" diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index 39c7207bbdbe..97a883314917 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/IOHandler.h" #include "lldb/Interpreter/CommandHistory.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionValueBoolean.h" @@ -1354,29 +1355,6 @@ protected: CommandOptions m_options; }; -// CommandObjectCommandsScriptAdd -static constexpr OptionEnumValueElement g_script_synchro_type[] = { - { - 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); -} - #define LLDB_OPTIONS_script_add #include "CommandOptions.inc" diff --git a/lldb/source/Commands/CommandObjectDisassemble.cpp b/lldb/source/Commands/CommandObjectDisassemble.cpp index 6c33edc8a3a8..a11e2b719727 100644 --- a/lldb/source/Commands/CommandObjectDisassemble.cpp +++ b/lldb/source/Commands/CommandObjectDisassemble.cpp @@ -12,6 +12,7 @@ #include "lldb/Core/Module.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/Options.h" diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 59c2cdb0938c..0fb50420f70f 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -14,6 +14,7 @@ #include "lldb/Expression/UserExpression.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Target/Language.h" @@ -28,23 +29,6 @@ CommandObjectExpression::CommandOptions::CommandOptions() = default; 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", - }, -}; - -static constexpr OptionEnumValues DescriptionVerbosityTypes() { - return OptionEnumValues(g_description_verbosity_type); -} - #define LLDB_OPTIONS_expression #include "CommandOptions.inc" diff --git a/lldb/source/Commands/CommandObjectFrame.cpp b/lldb/source/Commands/CommandObjectFrame.cpp index 9f2c79d84ad4..23954dd3c9fd 100644 --- a/lldb/source/Commands/CommandObjectFrame.cpp +++ b/lldb/source/Commands/CommandObjectFrame.cpp @@ -13,6 +13,7 @@ #include "lldb/Host/Config.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupFormat.h" @@ -143,10 +144,10 @@ protected: "`frame diagnose --address` is incompatible with other arguments."); return false; } - valobj_sp = frame_sp->GuessValueForAddress(m_options.address.getValue()); + valobj_sp = frame_sp->GuessValueForAddress(m_options.address.value()); } else if (m_options.reg) { valobj_sp = frame_sp->GuessValueForRegisterAndOffset( - m_options.reg.getValue(), m_options.offset.value_or(0)); + m_options.reg.value(), m_options.offset.value_or(0)); } else { StopInfoSP stop_info_sp = thread->GetStopInfo(); if (!stop_info_sp) { diff --git a/lldb/source/Commands/CommandObjectHelp.cpp b/lldb/source/Commands/CommandObjectHelp.cpp index a2f682049ae0..c7a3bce1408b 100644 --- a/lldb/source/Commands/CommandObjectHelp.cpp +++ b/lldb/source/Commands/CommandObjectHelp.cpp @@ -8,6 +8,7 @@ #include "CommandObjectHelp.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" using namespace lldb; diff --git a/lldb/source/Commands/CommandObjectLog.cpp b/lldb/source/Commands/CommandObjectLog.cpp index 684cb35da1cc..89bc3e0f1b7d 100644 --- a/lldb/source/Commands/CommandObjectLog.cpp +++ b/lldb/source/Commands/CommandObjectLog.cpp @@ -9,6 +9,7 @@ #include "CommandObjectLog.h" #include "lldb/Core/Debugger.h" #include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionValueEnumeration.h" @@ -23,36 +24,6 @@ using namespace lldb; using namespace lldb_private; -static constexpr OptionEnumValueElement g_log_handler_type[] = { - { - eLogHandlerDefault, - "default", - "Use the default (stream) log handler", - }, - { - eLogHandlerStream, - "stream", - "Write log messages to the debugger output stream or to a file if one " - "is specified. A buffer size (in bytes) can be specified with -b. If " - "no buffer size is specified the output is unbuffered.", - }, - { - eLogHandlerCircular, - "circular", - "Write log messages to a fixed size circular buffer. A buffer size " - "(number of messages) must be specified with -b.", - }, - { - eLogHandlerSystem, - "os", - "Write log messages to the operating system log.", - }, -}; - -static constexpr OptionEnumValues LogHandlerType() { - return OptionEnumValues(g_log_handler_type); -} - #define LLDB_OPTIONS_log_enable #include "CommandOptions.inc" diff --git a/lldb/source/Commands/CommandObjectMemory.cpp b/lldb/source/Commands/CommandObjectMemory.cpp index 98fa38f25635..ca0384cf9453 100644 --- a/lldb/source/Commands/CommandObjectMemory.cpp +++ b/lldb/source/Commands/CommandObjectMemory.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/ValueObjectMemory.h" #include "lldb/Expression/ExpressionVariable.h" #include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupFormat.h" @@ -274,7 +275,7 @@ public: OptionValueUInt64 m_num_per_line; bool m_output_as_binary = false; OptionValueString m_view_as_type; - bool m_force; + bool m_force = false; OptionValueUInt64 m_offset; OptionValueLanguage m_language_for_type; }; @@ -1738,7 +1739,7 @@ protected: const llvm::Optional<std::vector<addr_t>> &dirty_page_list = range_info.GetDirtyPageList(); if (dirty_page_list) { - const size_t page_count = dirty_page_list.getValue().size(); + const size_t page_count = dirty_page_list.value().size(); result.AppendMessageWithFormat( "Modified memory (dirty) page list provided, %zu entries.\n", page_count); diff --git a/lldb/source/Commands/CommandObjectMemoryTag.cpp b/lldb/source/Commands/CommandObjectMemoryTag.cpp index 67461cac5a29..98ab6201711d 100644 --- a/lldb/source/Commands/CommandObjectMemoryTag.cpp +++ b/lldb/source/Commands/CommandObjectMemoryTag.cpp @@ -8,6 +8,7 @@ #include "CommandObjectMemoryTag.h" #include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupFormat.h" diff --git a/lldb/source/Commands/CommandObjectPlatform.cpp b/lldb/source/Commands/CommandObjectPlatform.cpp index 42b19db5efc4..98c6a3b2dd30 100644 --- a/lldb/source/Commands/CommandObjectPlatform.cpp +++ b/lldb/source/Commands/CommandObjectPlatform.cpp @@ -13,6 +13,7 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandOptionValidators.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionGroupFile.h" diff --git a/lldb/source/Commands/CommandObjectProcess.cpp b/lldb/source/Commands/CommandObjectProcess.cpp index d36a574aba7d..28a99ea3d94a 100644 --- a/lldb/source/Commands/CommandObjectProcess.cpp +++ b/lldb/source/Commands/CommandObjectProcess.cpp @@ -7,8 +7,8 @@ //===----------------------------------------------------------------------===// #include "CommandObjectProcess.h" -#include "CommandObjectTrace.h" #include "CommandObjectBreakpoint.h" +#include "CommandObjectTrace.h" #include "CommandOptionsProcessLaunch.h" #include "lldb/Breakpoint/Breakpoint.h" #include "lldb/Breakpoint/BreakpointIDList.h" @@ -19,6 +19,7 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" @@ -1332,20 +1333,6 @@ protected: } }; -// CommandObjectProcessSaveCore -#pragma mark CommandObjectProcessSaveCore - -static constexpr OptionEnumValueElement g_corefile_save_style[] = { - {eSaveCoreFull, "full", "Create a core file with all memory saved"}, - {eSaveCoreDirtyOnly, "modified-memory", - "Create a corefile with only modified memory saved"}, - {eSaveCoreStackOnly, "stack", - "Create a corefile with only stack memory saved"}}; - -static constexpr OptionEnumValues SaveCoreStyles() { - return OptionEnumValues(g_corefile_save_style); -} - #define LLDB_OPTIONS_process_save_core #include "CommandOptions.inc" diff --git a/lldb/source/Commands/CommandObjectRegister.cpp b/lldb/source/Commands/CommandObjectRegister.cpp index 933c243dedd5..56cbacbebec5 100644 --- a/lldb/source/Commands/CommandObjectRegister.cpp +++ b/lldb/source/Commands/CommandObjectRegister.cpp @@ -10,6 +10,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/DumpRegisterValue.h" #include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionGroupFormat.h" #include "lldb/Interpreter/OptionValueArray.h" diff --git a/lldb/source/Commands/CommandObjectReproducer.cpp b/lldb/source/Commands/CommandObjectReproducer.cpp index 8d12decba974..6160a83b4d09 100644 --- a/lldb/source/Commands/CommandObjectReproducer.cpp +++ b/lldb/source/Commands/CommandObjectReproducer.cpp @@ -11,6 +11,7 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Utility/GDBRemote.h" @@ -24,95 +25,9 @@ using namespace llvm; using namespace lldb_private; using namespace lldb_private::repro; -enum ReproducerProvider { - eReproducerProviderCommands, - eReproducerProviderFiles, - eReproducerProviderSymbolFiles, - eReproducerProviderGDB, - eReproducerProviderProcessInfo, - eReproducerProviderVersion, - eReproducerProviderWorkingDirectory, - eReproducerProviderHomeDirectory, - eReproducerProviderNone -}; - -static constexpr OptionEnumValueElement g_reproducer_provider_type[] = { - { - eReproducerProviderCommands, - "commands", - "Command Interpreter Commands", - }, - { - eReproducerProviderFiles, - "files", - "Files", - }, - { - eReproducerProviderSymbolFiles, - "symbol-files", - "Symbol Files", - }, - { - eReproducerProviderGDB, - "gdb", - "GDB Remote Packets", - }, - { - eReproducerProviderProcessInfo, - "processes", - "Process Info", - }, - { - eReproducerProviderVersion, - "version", - "Version", - }, - { - eReproducerProviderWorkingDirectory, - "cwd", - "Working Directory", - }, - { - eReproducerProviderHomeDirectory, - "home", - "Home Directory", - }, - { - eReproducerProviderNone, - "none", - "None", - }, -}; - -static constexpr OptionEnumValues ReproducerProviderType() { - return OptionEnumValues(g_reproducer_provider_type); -} - #define LLDB_OPTIONS_reproducer_dump #include "CommandOptions.inc" -enum ReproducerCrashSignal { - eReproducerCrashSigill, - eReproducerCrashSigsegv, -}; - -static constexpr OptionEnumValueElement g_reproducer_signaltype[] = { - { - eReproducerCrashSigill, - "SIGILL", - "Illegal instruction", - }, - { - eReproducerCrashSigsegv, - "SIGSEGV", - "Segmentation fault", - }, -}; - -static constexpr OptionEnumValues ReproducerSignalType() { - return OptionEnumValues(g_reproducer_signaltype); -} - #define LLDB_OPTIONS_reproducer_xcrash #include "CommandOptions.inc" diff --git a/lldb/source/Commands/CommandObjectScript.cpp b/lldb/source/Commands/CommandObjectScript.cpp index f53d6540bc04..2ed03e85b2d7 100644 --- a/lldb/source/Commands/CommandObjectScript.cpp +++ b/lldb/source/Commands/CommandObjectScript.cpp @@ -12,6 +12,7 @@ #include "lldb/Host/Config.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/ScriptInterpreter.h" @@ -20,28 +21,6 @@ using namespace lldb; using namespace lldb_private; -static constexpr OptionEnumValueElement g_script_option_enumeration[] = { - { - eScriptLanguagePython, - "python", - "Python", - }, - { - eScriptLanguageLua, - "lua", - "Lua", - }, - { - eScriptLanguageNone, - "default", - "The default scripting language.", - }, -}; - -static constexpr OptionEnumValues ScriptOptionEnum() { - return OptionEnumValues(g_script_option_enumeration); -} - #define LLDB_OPTIONS_script #include "CommandOptions.inc" diff --git a/lldb/source/Commands/CommandObjectSession.cpp b/lldb/source/Commands/CommandObjectSession.cpp index c11839a48de0..f9ef1eb93443 100644 --- a/lldb/source/Commands/CommandObjectSession.cpp +++ b/lldb/source/Commands/CommandObjectSession.cpp @@ -1,6 +1,7 @@ #include "CommandObjectSession.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionValue.h" diff --git a/lldb/source/Commands/CommandObjectSettings.cpp b/lldb/source/Commands/CommandObjectSettings.cpp index e4162e56dc2c..86194664bf5d 100644 --- a/lldb/source/Commands/CommandObjectSettings.cpp +++ b/lldb/source/Commands/CommandObjectSettings.cpp @@ -13,6 +13,7 @@ #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandCompletions.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionValueProperties.h" diff --git a/lldb/source/Commands/CommandObjectSource.cpp b/lldb/source/Commands/CommandObjectSource.cpp index f87981859844..fd028d4f62f2 100644 --- a/lldb/source/Commands/CommandObjectSource.cpp +++ b/lldb/source/Commands/CommandObjectSource.cpp @@ -14,6 +14,7 @@ #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/SourceManager.h" #include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionValueFileColonLine.h" diff --git a/lldb/source/Commands/CommandObjectStats.cpp b/lldb/source/Commands/CommandObjectStats.cpp index 63aa36b39f4d..c0f8ff4b0b58 100644 --- a/lldb/source/Commands/CommandObjectStats.cpp +++ b/lldb/source/Commands/CommandObjectStats.cpp @@ -9,6 +9,7 @@ #include "CommandObjectStats.h" #include "lldb/Core/Debugger.h" #include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Target/Target.h" diff --git a/lldb/source/Commands/CommandObjectTarget.cpp b/lldb/source/Commands/CommandObjectTarget.cpp index 51978878c8b9..3dcb35557bfe 100644 --- a/lldb/source/Commands/CommandObjectTarget.cpp +++ b/lldb/source/Commands/CommandObjectTarget.cpp @@ -17,6 +17,7 @@ #include "lldb/DataFormatters/ValueObjectPrinter.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupArchitecture.h" @@ -142,26 +143,6 @@ static uint32_t DumpTargetList(TargetList &target_list, return num_targets; } -// Note that the negation in the argument name causes a slightly confusing -// mapping of the enum values. -static constexpr OptionEnumValueElement g_dependents_enumeration[] = { - { - 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" @@ -1923,26 +1904,6 @@ 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.", - }, -}; - #define LLDB_OPTIONS_target_modules_dump_symtab #include "CommandOptions.inc" @@ -4655,7 +4616,7 @@ public: m_class_name.clear(); m_function_name.clear(); m_line_start = 0; - m_line_end = UINT_MAX; + m_line_end = LLDB_INVALID_LINE_NUMBER; m_file_name.clear(); m_module_name.clear(); m_func_name_type_mask = eFunctionNameTypeAuto; @@ -4676,23 +4637,23 @@ public: std::string m_class_name; std::string m_function_name; uint32_t m_line_start = 0; - uint32_t m_line_end; + uint32_t m_line_end = LLDB_INVALID_LINE_NUMBER; std::string m_file_name; std::string m_module_name; uint32_t m_func_name_type_mask = eFunctionNameTypeAuto; // A pick from lldb::FunctionNameType. - lldb::tid_t m_thread_id; - uint32_t m_thread_index; + lldb::tid_t m_thread_id = LLDB_INVALID_THREAD_ID; + uint32_t m_thread_index = UINT32_MAX; std::string m_thread_name; std::string m_queue_name; bool m_sym_ctx_specified = false; - bool m_no_inlines; + bool m_no_inlines = false; bool m_thread_specified = false; // Instance variables to hold the values for one_liner options. bool m_use_one_liner = false; std::vector<std::string> m_one_liner; - bool m_auto_continue; + bool m_auto_continue = false; }; CommandObjectTargetStopHookAdd(CommandInterpreter &interpreter) diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index ad49d27bb9a7..1371b9dbda1e 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -17,6 +17,7 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupPythonClassWithDict.h" @@ -239,16 +240,6 @@ protected: enum StepScope { eStepScopeSource, eStepScopeInstruction }; -static constexpr OptionEnumValueElement g_tri_running_mode[] = { - {eOnlyThisThread, "this-thread", "Run only this thread"}, - {eAllThreads, "all-threads", "Run all threads"}, - {eOnlyDuringStepping, "while-stepping", - "Run only this thread while stepping"}}; - -static constexpr OptionEnumValues TriRunningModes() { - return OptionEnumValues(g_tri_running_mode); -} - #define LLDB_OPTIONS_thread_step_scope #include "CommandOptions.inc" @@ -813,14 +804,6 @@ public: // CommandObjectThreadUntil -static constexpr OptionEnumValueElement g_duo_running_mode[] = { - {eOnlyThisThread, "this-thread", "Run only this thread"}, - {eAllThreads, "all-threads", "Run all threads"}}; - -static constexpr OptionEnumValues DuoRunningModes() { - return OptionEnumValues(g_duo_running_mode); -} - #define LLDB_OPTIONS_thread_until #include "CommandOptions.inc" @@ -894,8 +877,8 @@ public: return llvm::makeArrayRef(g_thread_until_options); } - uint32_t m_step_thread_idx; - bool m_stop_others; + uint32_t m_step_thread_idx = LLDB_INVALID_THREAD_ID; + bool m_stop_others = false; std::vector<lldb::addr_t> m_until_addrs; // Instance variables to hold the values for command options. diff --git a/lldb/source/Commands/CommandObjectTrace.cpp b/lldb/source/Commands/CommandObjectTrace.cpp index 227de2de7065..eaf99a46b5c2 100644 --- a/lldb/source/Commands/CommandObjectTrace.cpp +++ b/lldb/source/Commands/CommandObjectTrace.cpp @@ -16,6 +16,7 @@ #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandObject.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupFormat.h" diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp index 3ad3571b390c..11acbb5c627f 100644 --- a/lldb/source/Commands/CommandObjectType.cpp +++ b/lldb/source/Commands/CommandObjectType.cpp @@ -15,6 +15,7 @@ #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandObject.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Interpreter/OptionGroupFormat.h" @@ -119,12 +120,12 @@ private: // Instance variables to hold the values for command options. TypeSummaryImpl::Flags m_flags; - bool m_regex; + bool m_regex = false; std::string m_format_string; ConstString m_name; std::string m_python_script; std::string m_python_function; - bool m_is_add_script; + bool m_is_add_script = false; std::string m_category; }; @@ -1054,6 +1055,15 @@ protected: return false; } + static bool ShouldListItem(llvm::StringRef s, RegularExpression *regex) { + // If we have a regex, it can match two kinds of results: + // - An item created with that same regex string (exact string match), so + // the user can list it using the same string it used at creation time. + // - Items that match the regex. + // No regex means list everything. + return regex == nullptr || s == regex->GetText() || regex->Execute(s); + } + bool DoExecute(Args &command, CommandReturnObject &result) override { const size_t argc = command.GetArgumentCount(); @@ -1095,24 +1105,13 @@ protected: .SetExact([&result, &formatter_regex, &any_printed]( const TypeMatcher &type_matcher, const FormatterSharedPointer &format_sp) -> bool { - if (formatter_regex) { - bool escape = true; - if (type_matcher.CreatedBySameMatchString( - ConstString(formatter_regex->GetText()))) { - escape = false; - } else if (formatter_regex->Execute( - type_matcher.GetMatchString().GetStringRef())) { - escape = false; - } - - if (escape) - return true; + if (ShouldListItem(type_matcher.GetMatchString().GetStringRef(), + formatter_regex.get())) { + any_printed = true; + result.GetOutputStream().Printf( + "%s: %s\n", type_matcher.GetMatchString().GetCString(), + format_sp->GetDescription().c_str()); } - - any_printed = true; - result.GetOutputStream().Printf( - "%s: %s\n", type_matcher.GetMatchString().GetCString(), - format_sp->GetDescription().c_str()); return true; }); @@ -1120,24 +1119,13 @@ protected: .SetWithRegex([&result, &formatter_regex, &any_printed]( const TypeMatcher &type_matcher, const FormatterSharedPointer &format_sp) -> bool { - if (formatter_regex) { - bool escape = true; - if (type_matcher.CreatedBySameMatchString( - ConstString(formatter_regex->GetText()))) { - escape = false; - } else if (formatter_regex->Execute( - type_matcher.GetMatchString().GetStringRef())) { - escape = false; - } - - if (escape) - return true; + if (ShouldListItem(type_matcher.GetMatchString().GetStringRef(), + formatter_regex.get())) { + any_printed = true; + result.GetOutputStream().Printf( + "%s: %s\n", type_matcher.GetMatchString().GetCString(), + format_sp->GetDescription().c_str()); } - - any_printed = true; - result.GetOutputStream().Printf( - "%s: %s\n", type_matcher.GetMatchString().GetCString(), - format_sp->GetDescription().c_str()); return true; }); @@ -1154,20 +1142,9 @@ protected: DataVisualization::Categories::ForEach( [&category_regex, &category_closure]( const lldb::TypeCategoryImplSP &category) -> bool { - if (category_regex) { - bool escape = true; - if (category->GetName() == category_regex->GetText()) { - escape = false; - } else if (category_regex->Execute(category->GetName())) { - escape = false; - } - - if (escape) - return true; + if (ShouldListItem(category->GetName(), category_regex.get())) { + category_closure(category); } - - category_closure(category); - return true; }); diff --git a/lldb/source/Commands/CommandObjectWatchpoint.cpp b/lldb/source/Commands/CommandObjectWatchpoint.cpp index 6805ff7f50ae..f87a171daca6 100644 --- a/lldb/source/Commands/CommandObjectWatchpoint.cpp +++ b/lldb/source/Commands/CommandObjectWatchpoint.cpp @@ -18,6 +18,7 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/Variable.h" #include "lldb/Symbol/VariableList.h" diff --git a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp index 0cc83275d7ae..3264813b3d53 100644 --- a/lldb/source/Commands/CommandObjectWatchpointCommand.cpp +++ b/lldb/source/Commands/CommandObjectWatchpointCommand.cpp @@ -15,6 +15,7 @@ #include "lldb/Core/IOHandler.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Target/Target.h" @@ -22,36 +23,6 @@ using namespace lldb; using namespace lldb_private; -// 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. -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.", - }, - { - eScriptLanguageLua, - "lua", - "Commands are in the Lua language.", - }, - { - eSortOrderByName, - "default-script", - "Commands are in the default scripting language.", - }, -}; - -static constexpr OptionEnumValues ScriptOptionEnum() { - return OptionEnumValues(g_script_option_enumeration); -} - #define LLDB_OPTIONS_watchpoint_command_add #include "CommandOptions.inc" diff --git a/lldb/source/Commands/CommandOptionArgumentTable.cpp b/lldb/source/Commands/CommandOptionArgumentTable.cpp new file mode 100644 index 000000000000..e8e9307b6291 --- /dev/null +++ b/lldb/source/Commands/CommandOptionArgumentTable.cpp @@ -0,0 +1,313 @@ +//===-- CommandOptionArgumentTable.cpp ------------------------------------===// +// +// 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 "lldb/Interpreter/CommandOptionArgumentTable.h" +#include "lldb/DataFormatters/FormatManager.h" +#include "lldb/Target/Language.h" +#include "lldb/Utility/StreamString.h" + +using namespace lldb; +using namespace lldb_private; + +namespace lldb_private { +llvm::StringRef RegisterNameHelpTextCallback() { + return "Register names can be specified using the architecture specific " + "names. " + "They can also be specified using generic names. Not all generic " + "entities have " + "registers backing them on all architectures. When they don't the " + "generic name " + "will return an error.\n" + "The generic names defined in lldb are:\n" + "\n" + "pc - program counter register\n" + "ra - return address register\n" + "fp - frame pointer register\n" + "sp - stack pointer register\n" + "flags - the flags register\n" + "arg{1-6} - integer argument passing registers.\n"; +} + +llvm::StringRef BreakpointIDHelpTextCallback() { + return "Breakpoints are identified using major and minor numbers; the major " + "number corresponds to the single entity that was created with a " + "'breakpoint " + "set' command; the minor numbers correspond to all the locations that " + "were " + "actually found/set based on the major breakpoint. A full breakpoint " + "ID might " + "look like 3.14, meaning the 14th location set for the 3rd " + "breakpoint. You " + "can specify all the locations of a breakpoint by just indicating the " + "major " + "breakpoint number. A valid breakpoint ID consists either of just the " + "major " + "number, or the major number followed by a dot and the location " + "number (e.g. " + "3 or 3.2 could both be valid breakpoint IDs.)"; +} + +llvm::StringRef BreakpointIDRangeHelpTextCallback() { + return "A 'breakpoint ID list' is a manner of specifying multiple " + "breakpoints. " + "This can be done through several mechanisms. The easiest way is to " + "just " + "enter a space-separated list of breakpoint IDs. To specify all the " + "breakpoint locations under a major breakpoint, you can use the major " + "breakpoint number followed by '.*', eg. '5.*' means all the " + "locations under " + "breakpoint 5. You can also indicate a range of breakpoints by using " + "<start-bp-id> - <end-bp-id>. The start-bp-id and end-bp-id for a " + "range can " + "be any valid breakpoint IDs. It is not legal, however, to specify a " + "range " + "using specific locations that cross major breakpoint numbers. I.e. " + "3.2 - 3.7" + " is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal."; +} + +llvm::StringRef BreakpointNameHelpTextCallback() { + return "A name that can be added to a breakpoint when it is created, or " + "later " + "on with the \"breakpoint name add\" command. " + "Breakpoint names can be used to specify breakpoints in all the " + "places breakpoint IDs " + "and breakpoint ID ranges can be used. As such they provide a " + "convenient way to group breakpoints, " + "and to operate on breakpoints you create without having to track the " + "breakpoint number. " + "Note, the attributes you set when using a breakpoint name in a " + "breakpoint command don't " + "adhere to the name, but instead are set individually on all the " + "breakpoints currently tagged with that " + "name. Future breakpoints " + "tagged with that name will not pick up the attributes previously " + "given using that name. " + "In order to distinguish breakpoint names from breakpoint IDs and " + "ranges, " + "names must start with a letter from a-z or A-Z and cannot contain " + "spaces, \".\" or \"-\". " + "Also, breakpoint names can only be applied to breakpoints, not to " + "breakpoint locations."; +} + +llvm::StringRef GDBFormatHelpTextCallback() { + return "A GDB format consists of a repeat count, a format letter and a size " + "letter. " + "The repeat count is optional and defaults to 1. The format letter is " + "optional " + "and defaults to the previous format that was used. The size letter " + "is optional " + "and defaults to the previous size that was used.\n" + "\n" + "Format letters include:\n" + "o - octal\n" + "x - hexadecimal\n" + "d - decimal\n" + "u - unsigned decimal\n" + "t - binary\n" + "f - float\n" + "a - address\n" + "i - instruction\n" + "c - char\n" + "s - string\n" + "T - OSType\n" + "A - float as hex\n" + "\n" + "Size letters include:\n" + "b - 1 byte (byte)\n" + "h - 2 bytes (halfword)\n" + "w - 4 bytes (word)\n" + "g - 8 bytes (giant)\n" + "\n" + "Example formats:\n" + "32xb - show 32 1 byte hexadecimal integer values\n" + "16xh - show 16 2 byte hexadecimal integer values\n" + "64 - show 64 2 byte hexadecimal integer values (format and size " + "from the last format)\n" + "dw - show 1 4 byte decimal integer value\n"; +} + +llvm::StringRef FormatHelpTextCallback() { + static std::string help_text; + + if (!help_text.empty()) + return help_text; + + StreamString sstr; + sstr << "One of the format names (or one-character names) that can be used " + "to show a variable's value:\n"; + for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) { + if (f != eFormatDefault) + sstr.PutChar('\n'); + + char format_char = FormatManager::GetFormatAsFormatChar(f); + if (format_char) + sstr.Printf("'%c' or ", format_char); + + sstr.Printf("\"%s\"", FormatManager::GetFormatAsCString(f)); + } + + sstr.Flush(); + + help_text = std::string(sstr.GetString()); + + return help_text; +} + +llvm::StringRef LanguageTypeHelpTextCallback() { + static std::string help_text; + + if (!help_text.empty()) + return help_text; + + StreamString sstr; + sstr << "One of the following languages:\n"; + + Language::PrintAllLanguages(sstr, " ", "\n"); + + sstr.Flush(); + + help_text = std::string(sstr.GetString()); + + return help_text; +} + +llvm::StringRef SummaryStringHelpTextCallback() { + return "A summary string is a way to extract information from variables in " + "order to present them using a summary.\n" + "Summary strings contain static text, variables, scopes and control " + "sequences:\n" + " - Static text can be any sequence of non-special characters, i.e. " + "anything but '{', '}', '$', or '\\'.\n" + " - Variables are sequences of characters beginning with ${, ending " + "with } and that contain symbols in the format described below.\n" + " - Scopes are any sequence of text between { and }. Anything " + "included in a scope will only appear in the output summary if there " + "were no errors.\n" + " - Control sequences are the usual C/C++ '\\a', '\\n', ..., plus " + "'\\$', '\\{' and '\\}'.\n" + "A summary string works by copying static text verbatim, turning " + "control sequences into their character counterpart, expanding " + "variables and trying to expand scopes.\n" + "A variable is expanded by giving it a value other than its textual " + "representation, and the way this is done depends on what comes after " + "the ${ marker.\n" + "The most common sequence if ${var followed by an expression path, " + "which is the text one would type to access a member of an aggregate " + "types, given a variable of that type" + " (e.g. if type T has a member named x, which has a member named y, " + "and if t is of type T, the expression path would be .x.y and the way " + "to fit that into a summary string would be" + " ${var.x.y}). You can also use ${*var followed by an expression path " + "and in that case the object referred by the path will be " + "dereferenced before being displayed." + " If the object is not a pointer, doing so will cause an error. For " + "additional details on expression paths, you can type 'help " + "expr-path'. \n" + "By default, summary strings attempt to display the summary for any " + "variable they reference, and if that fails the value. If neither can " + "be shown, nothing is displayed." + "In a summary string, you can also use an array index [n], or a " + "slice-like range [n-m]. This can have two different meanings " + "depending on what kind of object the expression" + " path refers to:\n" + " - if it is a scalar type (any basic type like int, float, ...) the " + "expression is a bitfield, i.e. the bits indicated by the indexing " + "operator are extracted out of the number" + " and displayed as an individual variable\n" + " - if it is an array or pointer the array items indicated by the " + "indexing operator are shown as the result of the variable. if the " + "expression is an array, real array items are" + " printed; if it is a pointer, the pointer-as-array syntax is used to " + "obtain the values (this means, the latter case can have no range " + "checking)\n" + "If you are trying to display an array for which the size is known, " + "you can also use [] instead of giving an exact range. This has the " + "effect of showing items 0 thru size - 1.\n" + "Additionally, a variable can contain an (optional) format code, as " + "in ${var.x.y%code}, where code can be any of the valid formats " + "described in 'help format', or one of the" + " special symbols only allowed as part of a variable:\n" + " %V: show the value of the object by default\n" + " %S: show the summary of the object by default\n" + " %@: show the runtime-provided object description (for " + "Objective-C, it calls NSPrintForDebugger; for C/C++ it does " + "nothing)\n" + " %L: show the location of the object (memory address or a " + "register name)\n" + " %#: show the number of children of the object\n" + " %T: show the type of the object\n" + "Another variable that you can use in summary strings is ${svar . " + "This sequence works exactly like ${var, including the fact that " + "${*svar is an allowed sequence, but uses" + " the object's synthetic children provider instead of the actual " + "objects. For instance, if you are using STL synthetic children " + "providers, the following summary string would" + " count the number of actual elements stored in an std::list:\n" + "type summary add -s \"${svar%#}\" -x \"std::list<\""; +} + +llvm::StringRef ExprPathHelpTextCallback() { + return "An expression path is the sequence of symbols that is used in C/C++ " + "to access a member variable of an aggregate object (class).\n" + "For instance, given a class:\n" + " class foo {\n" + " int a;\n" + " int b; .\n" + " foo* next;\n" + " };\n" + "the expression to read item b in the item pointed to by next for foo " + "aFoo would be aFoo.next->b.\n" + "Given that aFoo could just be any object of type foo, the string " + "'.next->b' is the expression path, because it can be attached to any " + "foo instance to achieve the effect.\n" + "Expression paths in LLDB include dot (.) and arrow (->) operators, " + "and most commands using expression paths have ways to also accept " + "the star (*) operator.\n" + "The meaning of these operators is the same as the usual one given to " + "them by the C/C++ standards.\n" + "LLDB also has support for indexing ([ ]) in expression paths, and " + "extends the traditional meaning of the square brackets operator to " + "allow bitfield extraction:\n" + "for objects of native types (int, float, char, ...) saying '[n-m]' " + "as an expression path (where n and m are any positive integers, e.g. " + "[3-5]) causes LLDB to extract" + " bits n thru m from the value of the variable. If n == m, [n] is " + "also allowed as a shortcut syntax. For arrays and pointers, " + "expression paths can only contain one index" + " and the meaning of the operation is the same as the one defined by " + "C/C++ (item extraction). Some commands extend bitfield-like syntax " + "for arrays and pointers with the" + " meaning of array slicing (taking elements n thru m inside the array " + "or pointed-to memory)."; +} + +llvm::StringRef arch_helper() { + static StreamString g_archs_help; + if (g_archs_help.Empty()) { + StringList archs; + + ArchSpec::ListSupportedArchNames(archs); + g_archs_help.Printf("These are the supported architecture names:\n"); + archs.Join("\n", g_archs_help); + } + return g_archs_help.GetString(); +} + +template <int I> struct TableValidator : TableValidator<I + 1> { + static_assert( + g_argument_table[I].arg_type == I, + "g_argument_table order doesn't match CommandArgumentType enumeration"); +}; + +template <> struct TableValidator<eArgTypeLastArg> {}; + +TableValidator<0> validator; + +} // namespace lldb_private diff --git a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp index a618796156a6..3c7f4b6c7585 100644 --- a/lldb/source/Commands/CommandOptionsProcessLaunch.cpp +++ b/lldb/source/Commands/CommandOptionsProcessLaunch.cpp @@ -12,6 +12,8 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandCompletions.h" +#include "lldb/Interpreter/CommandObject.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/OptionArgParser.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Platform.h" diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td index 7981917fd8b5..78221db18e65 100644 --- a/lldb/source/Commands/Options.td +++ b/lldb/source/Commands/Options.td @@ -3,7 +3,7 @@ include "OptionsBase.td" let Command = "target modules dump symtab" in { def tm_sort : Option<"sort", "s">, Group<1>, Desc<"Supply a sort order when dumping the symbol table.">, - EnumArg<"SortOrder", "OptionEnumValues(g_sort_option_enumeration)">; + EnumArg<"SortOrder">; def tm_smn : Option<"show-mangled-names", "m">, Group<1>, Desc<"Do not demangle symbol names before showing them.">; } @@ -282,7 +282,7 @@ let Command = "breakpoint command add" in { Arg<"Boolean">, Desc<"Specify whether breakpoint command execution should " "terminate on error.">; def breakpoint_add_script_type : Option<"script-type", "s">, - EnumArg<"None", "ScriptOptionEnum()">, + EnumArg<"ScriptLang">, Desc<"Specify the language for the commands - if none is specified, the " "lldb command interpreter will be used.">; def breakpoint_add_dummy_breakpoints : Option<"dummy-breakpoints", "D">, @@ -370,7 +370,7 @@ let Command = "expression" in { "automatically applied to the expression.">; def expression_options_description_verbosity : Option<"description-verbosity", "v">, Group<1>, - OptionalEnumArg<"DescriptionVerbosity", "DescriptionVerbosityTypes()">, + OptionalEnumArg<"DescriptionVerbosity">, 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]>, @@ -437,7 +437,7 @@ let Command = "log enable" in { def log_file : Option<"file", "f">, Group<1>, Arg<"Filename">, Desc<"Set the destination file to log to.">; def log_handler : Option<"log-handler", "h">, Group<1>, - EnumArg<"LogHandler", "LogHandlerType()">, Desc<"Specify a log handler which determines where log messages are written.">; + EnumArg<"LogHandler">, Desc<"Specify a log handler which determines where log messages are written.">; def log_buffer_size : Option<"buffer", "b">, Group<1>, Arg<"UnsignedInteger">, Desc<"Set the log to be buffered, using the specified buffer size, if supported by the log handler.">; def log_verbose : Option<"verbose", "v">, Group<1>, @@ -468,7 +468,7 @@ let Command = "log dump" in { let Command = "reproducer dump" in { def reproducer_provider : Option<"provider", "p">, Group<1>, - EnumArg<"None", "ReproducerProviderType()">, + EnumArg<"ReproducerProvider">, 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 " @@ -483,7 +483,7 @@ let Command = "reproducer verify" in { let Command = "reproducer xcrash" in { def reproducer_signal : Option<"signal", "s">, Group<1>, - EnumArg<"None", "ReproducerSignalType()">, + EnumArg<"ReproducerSignal">, Required, Desc<"The signal to crash the debugger.">; } @@ -781,7 +781,7 @@ let Command = "process status" in { let Command = "process save_core" in { def process_save_core_style : Option<"style", "s">, Group<1>, - EnumArg<"SaveCoreStyle", "SaveCoreStyles()">, Desc<"Request a specific style " + EnumArg<"SaveCoreStyle">, Desc<"Request a specific style " "of corefile to be saved.">; def process_save_core_plugin_name : Option<"plugin-name", "p">, OptionalArg<"Plugin">, Desc<"Specify a plugin name to create the core file." @@ -812,7 +812,7 @@ let Command = "script add" in { def script_add_overwrite : Option<"overwrite", "o">, Groups<[1,2]>, Desc<"Overwrite an existing command at this node.">; def script_add_synchronicity : Option<"synchronicity", "s">, - EnumArg<"ScriptedCommandSynchronicity", "ScriptSynchroType()">, + EnumArg<"ScriptedCommandSynchronicity">, Desc<"Set the synchronicity of this command's executions with regard to " "LLDB event system.">; } @@ -828,7 +828,7 @@ let Command = "container add" in { let Command = "script" in { def script_language : Option<"language", "l">, - EnumArg<"ScriptLang", "ScriptOptionEnum()">, Desc<"Specify the scripting " + EnumArg<"ScriptLang">, Desc<"Specify the scripting " " language. If none is specific the default scripting language is used.">; } @@ -881,7 +881,7 @@ let Command = "source list" in { let Command = "target dependents" in { def dependents_no_dependents : Option<"no-dependents", "d">, Group<1>, - OptionalEnumArg<"Value", "OptionEnumValues(g_dependents_enumeration)">, + OptionalEnumArg<"Value">, 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 " @@ -1054,7 +1054,7 @@ let Command = "thread step scope" in { " block. This is particularly use in conjunction with --step-target to" " step through a complex calling sequence.">; def thread_step_scope_run_mode : Option<"run-mode", "m">, Group<1>, - EnumArg<"RunMode", "TriRunningModes()">, Desc<"Determine how to run other " + EnumArg<"RunMode">, Desc<"Determine how to run other " "threads while stepping the current thread.">; def thread_step_scope_step_over_regexp : Option<"step-over-regexp", "r">, Group<1>, Arg<"RegularExpression">, Desc<"A regular expression that defines " @@ -1070,7 +1070,7 @@ let Command = "thread until" in { def thread_until_thread : Option<"thread", "t">, Group<1>, Arg<"ThreadIndex">, Desc<"Thread index for the thread for until operation">; def thread_until_run_mode : Option<"run-mode", "m">, Group<1>, - EnumArg<"RunMode", "DuoRunningModes()">, Desc<"Determine how to run other " + EnumArg<"RunMode">, Desc<"Determine how to run other " "threads while stepping this one">; def thread_until_address : Option<"address", "a">, Group<1>, Arg<"AddressOrExpression">, Desc<"Run until we reach the specified address, " @@ -1333,7 +1333,7 @@ let Command = "watchpoint command add" in { Arg<"Boolean">, Desc<"Specify whether watchpoint command execution should " "terminate on error.">; def watchpoint_command_add_script_type : Option<"script-type", "s">, - EnumArg<"None", "ScriptOptionEnum()">, Desc<"Specify the language for the" + EnumArg<"ScriptLang">, Desc<"Specify the language for the" " commands - if none is specified, the lldb command interpreter will be " "used.">; def watchpoint_command_add_python_function : Option<"python-function", "F">, diff --git a/lldb/source/Commands/OptionsBase.td b/lldb/source/Commands/OptionsBase.td index f6967f067bf4..9612cc130334 100644 --- a/lldb/source/Commands/OptionsBase.td +++ b/lldb/source/Commands/OptionsBase.td @@ -151,15 +151,13 @@ class Arg<string type> { } // Gives the option an required argument. -class EnumArg<string type, string enum> { +class EnumArg<string type> { string ArgType = type; - string ArgEnum = enum; } // Gives the option an required argument. -class OptionalEnumArg<string type, string enum> { +class OptionalEnumArg<string type> { string ArgType = type; - string ArgEnum = enum; bit OptionalArg = 1; } diff --git a/lldb/source/Core/DumpDataExtractor.cpp b/lldb/source/Core/DumpDataExtractor.cpp index dc96a3454b72..c48250b07d16 100644 --- a/lldb/source/Core/DumpDataExtractor.cpp +++ b/lldb/source/Core/DumpDataExtractor.cpp @@ -119,7 +119,7 @@ static lldb::offset_t DumpAPInt(Stream *s, const DataExtractor &data, bool is_signed, unsigned radix) { llvm::Optional<llvm::APInt> apint = GetAPInt(data, &offset, byte_size); if (apint) { - std::string apint_str = toString(apint.getValue(), radix, is_signed); + std::string apint_str = toString(apint.value(), radix, is_signed); switch (radix) { case 2: s->Write("0b", 2); @@ -672,7 +672,7 @@ lldb::offset_t lldb_private::DumpDataExtractor( llvm::Optional<llvm::APInt> apint = GetAPInt(DE, &offset, semantics_byte_size); if (apint) { - llvm::APFloat apfloat(semantics, apint.getValue()); + llvm::APFloat apfloat(semantics, apint.value()); apfloat.toString(sv, format_precision, format_max_padding); if (!sv.empty()) { s->Printf("%*.*s", (int)sv.size(), (int)sv.size(), sv.data()); diff --git a/lldb/source/Core/ValueObjectChild.cpp b/lldb/source/Core/ValueObjectChild.cpp index d61d2021c318..ec29c029c174 100644 --- a/lldb/source/Core/ValueObjectChild.cpp +++ b/lldb/source/Core/ValueObjectChild.cpp @@ -83,7 +83,7 @@ ConstString ValueObjectChild::GetDisplayTypeName() { LazyBool ValueObjectChild::CanUpdateWithInvalidExecutionContext() { if (m_can_update_with_invalid_exe_ctx) - return m_can_update_with_invalid_exe_ctx.getValue(); + return m_can_update_with_invalid_exe_ctx.value(); if (m_parent) { ValueObject *opinionated_parent = m_parent->FollowParentChain([](ValueObject *valobj) -> bool { @@ -93,11 +93,11 @@ LazyBool ValueObjectChild::CanUpdateWithInvalidExecutionContext() { if (opinionated_parent) return (m_can_update_with_invalid_exe_ctx = opinionated_parent->CanUpdateWithInvalidExecutionContext()) - .getValue(); + .value(); } return (m_can_update_with_invalid_exe_ctx = this->ValueObject::CanUpdateWithInvalidExecutionContext()) - .getValue(); + .value(); } bool ValueObjectChild::UpdateValue() { diff --git a/lldb/source/Expression/DWARFExpression.cpp b/lldb/source/Expression/DWARFExpression.cpp index 9e6b21fc25ea..25f6a46d805b 100644 --- a/lldb/source/Expression/DWARFExpression.cpp +++ b/lldb/source/Expression/DWARFExpression.cpp @@ -1655,11 +1655,16 @@ bool DWARFExpression::Evaluate( case DW_OP_skip: { int16_t skip_offset = (int16_t)opcodes.GetU16(&offset); lldb::offset_t new_offset = offset + skip_offset; - if (opcodes.ValidOffset(new_offset)) + // New offset can point at the end of the data, in this case we should + // terminate the DWARF expression evaluation (will happen in the loop + // condition). + if (new_offset <= opcodes.GetByteSize()) offset = new_offset; else { if (error_ptr) - error_ptr->SetErrorString("Invalid opcode offset in DW_OP_skip."); + error_ptr->SetErrorStringWithFormatv( + "Invalid opcode offset in DW_OP_skip: {0}+({1}) > {2}", offset, + skip_offset, opcodes.GetByteSize()); return false; } } break; @@ -1684,11 +1689,16 @@ bool DWARFExpression::Evaluate( Scalar zero(0); if (tmp.ResolveValue(exe_ctx) != zero) { lldb::offset_t new_offset = offset + bra_offset; - if (opcodes.ValidOffset(new_offset)) + // New offset can point at the end of the data, in this case we should + // terminate the DWARF expression evaluation (will happen in the loop + // condition). + if (new_offset <= opcodes.GetByteSize()) offset = new_offset; else { if (error_ptr) - error_ptr->SetErrorString("Invalid opcode offset in DW_OP_bra."); + error_ptr->SetErrorStringWithFormatv( + "Invalid opcode offset in DW_OP_bra: {0}+({1}) > {2}", offset, + bra_offset, opcodes.GetByteSize()); return false; } } diff --git a/lldb/source/Expression/Materializer.cpp b/lldb/source/Expression/Materializer.cpp index 965a96b7f909..946ae10d69c2 100644 --- a/lldb/source/Expression/Materializer.cpp +++ b/lldb/source/Expression/Materializer.cpp @@ -22,11 +22,20 @@ #include "lldb/Utility/LLDBLog.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" +#include "lldb/lldb-forward.h" #include <memory> using namespace lldb_private; +// FIXME: these should be retrieved from the target +// instead of being hard-coded. Currently we +// assume that persistent vars are materialized +// as references, and thus pick the size of a +// 64-bit pointer. +static constexpr uint32_t g_default_var_alignment = 8; +static constexpr uint32_t g_default_var_byte_size = 8; + uint32_t Materializer::AddStructMember(Entity &entity) { uint32_t size = entity.GetSize(); uint32_t alignment = entity.GetAlignment(); @@ -54,8 +63,8 @@ public: m_delegate(delegate) { // Hard-coding to maximum size of a pointer since persistent variables are // materialized by reference - m_size = 8; - m_alignment = 8; + m_size = g_default_var_byte_size; + m_alignment = g_default_var_alignment; } void MakeAllocation(IRMemoryMap &map, Status &err) { @@ -412,16 +421,19 @@ uint32_t Materializer::AddPersistentVariable( return ret; } -class EntityVariable : public Materializer::Entity { +/// Base class for materialization of Variables and ValueObjects. +/// +/// Subclasses specify how to obtain the Value which is to be +/// materialized. +class EntityVariableBase : public Materializer::Entity { public: - EntityVariable(lldb::VariableSP &variable_sp) - : Entity(), m_variable_sp(variable_sp) { + virtual ~EntityVariableBase() = default; + + EntityVariableBase() { // Hard-coding to maximum size of a pointer since all variables are // materialized by reference - m_size = 8; - m_alignment = 8; - m_is_reference = - m_variable_sp->GetType()->GetForwardCompilerType().IsReferenceType(); + m_size = g_default_var_byte_size; + m_alignment = g_default_var_alignment; } void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, @@ -433,7 +445,7 @@ public: LLDB_LOGF(log, "EntityVariable::Materialize [address = 0x%" PRIx64 ", m_variable_sp = %s]", - (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); + (uint64_t)load_addr, GetName().GetCString()); } ExecutionContextScope *scope = frame_sp.get(); @@ -441,13 +453,11 @@ public: if (!scope) scope = map.GetBestExecutionContextScope(); - lldb::ValueObjectSP valobj_sp = - ValueObjectVariable::Create(scope, m_variable_sp); + lldb::ValueObjectSP valobj_sp = SetupValueObject(scope); if (!valobj_sp) { err.SetErrorStringWithFormat( - "couldn't get a value object for variable %s", - m_variable_sp->GetName().AsCString()); + "couldn't get a value object for variable %s", GetName().AsCString()); return; } @@ -455,7 +465,7 @@ public: if (valobj_error.Fail()) { err.SetErrorStringWithFormat("couldn't get the value of variable %s: %s", - m_variable_sp->GetName().AsCString(), + GetName().AsCString(), valobj_error.AsCString()); return; } @@ -468,7 +478,7 @@ public: if (!extract_error.Success()) { err.SetErrorStringWithFormat( "couldn't read contents of reference variable %s: %s", - m_variable_sp->GetName().AsCString(), extract_error.AsCString()); + GetName().AsCString(), extract_error.AsCString()); return; } @@ -481,7 +491,7 @@ public: if (!write_error.Success()) { err.SetErrorStringWithFormat("couldn't write the contents of reference " "variable %s to memory: %s", - m_variable_sp->GetName().AsCString(), + GetName().AsCString(), write_error.AsCString()); return; } @@ -497,7 +507,7 @@ public: if (!write_error.Success()) { err.SetErrorStringWithFormat( "couldn't write the address of variable %s to memory: %s", - m_variable_sp->GetName().AsCString(), write_error.AsCString()); + GetName().AsCString(), write_error.AsCString()); return; } } else { @@ -506,7 +516,7 @@ public: valobj_sp->GetData(data, extract_error); if (!extract_error.Success()) { err.SetErrorStringWithFormat("couldn't get the value of %s: %s", - m_variable_sp->GetName().AsCString(), + GetName().AsCString(), extract_error.AsCString()); return; } @@ -514,32 +524,29 @@ public: if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { err.SetErrorStringWithFormat( "trying to create a temporary region for %s but one exists", - m_variable_sp->GetName().AsCString()); + GetName().AsCString()); return; } - if (data.GetByteSize() < m_variable_sp->GetType()->GetByteSize(scope)) { - if (data.GetByteSize() == 0 && - !m_variable_sp->LocationExpressionList().IsValid()) { + if (data.GetByteSize() < GetByteSize(scope)) { + if (data.GetByteSize() == 0 && !LocationExpressionIsValid()) { err.SetErrorStringWithFormat("the variable '%s' has no location, " "it may have been optimized out", - m_variable_sp->GetName().AsCString()); + GetName().AsCString()); } else { err.SetErrorStringWithFormat( "size of variable %s (%" PRIu64 ") is larger than the ValueObject's size (%" PRIu64 ")", - m_variable_sp->GetName().AsCString(), - m_variable_sp->GetType()->GetByteSize(scope).value_or(0), + GetName().AsCString(), GetByteSize(scope).value_or(0), data.GetByteSize()); } return; } - llvm::Optional<size_t> opt_bit_align = - m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign(scope); + llvm::Optional<size_t> opt_bit_align = GetTypeBitAlign(scope); if (!opt_bit_align) { err.SetErrorStringWithFormat("can't get the type alignment for %s", - m_variable_sp->GetName().AsCString()); + GetName().AsCString()); return; } @@ -561,7 +568,7 @@ public: if (!alloc_error.Success()) { err.SetErrorStringWithFormat( "couldn't allocate a temporary region for %s: %s", - m_variable_sp->GetName().AsCString(), alloc_error.AsCString()); + GetName().AsCString(), alloc_error.AsCString()); return; } @@ -573,7 +580,7 @@ public: if (!write_error.Success()) { err.SetErrorStringWithFormat( "couldn't write to the temporary region for %s: %s", - m_variable_sp->GetName().AsCString(), write_error.AsCString()); + GetName().AsCString(), write_error.AsCString()); return; } @@ -585,8 +592,7 @@ public: if (!pointer_write_error.Success()) { err.SetErrorStringWithFormat( "couldn't write the address of the temporary region for %s: %s", - m_variable_sp->GetName().AsCString(), - pointer_write_error.AsCString()); + GetName().AsCString(), pointer_write_error.AsCString()); } } } @@ -602,7 +608,7 @@ public: LLDB_LOGF(log, "EntityVariable::Dematerialize [address = 0x%" PRIx64 ", m_variable_sp = %s]", - (uint64_t)load_addr, m_variable_sp->GetName().AsCString()); + (uint64_t)load_addr, GetName().AsCString()); } if (m_temporary_allocation != LLDB_INVALID_ADDRESS) { @@ -611,13 +617,12 @@ public: if (!scope) scope = map.GetBestExecutionContextScope(); - lldb::ValueObjectSP valobj_sp = - ValueObjectVariable::Create(scope, m_variable_sp); + lldb::ValueObjectSP valobj_sp = SetupValueObject(scope); if (!valobj_sp) { err.SetErrorStringWithFormat( "couldn't get a value object for variable %s", - m_variable_sp->GetName().AsCString()); + GetName().AsCString()); return; } @@ -630,7 +635,7 @@ public: if (!extract_error.Success()) { err.SetErrorStringWithFormat("couldn't get the data for variable %s", - m_variable_sp->GetName().AsCString()); + GetName().AsCString()); return; } @@ -652,7 +657,7 @@ public: if (!set_error.Success()) { err.SetErrorStringWithFormat( "couldn't write the new contents of %s back into the variable", - m_variable_sp->GetName().AsCString()); + GetName().AsCString()); return; } } @@ -664,7 +669,7 @@ public: if (!free_error.Success()) { err.SetErrorStringWithFormat( "couldn't free the temporary region for %s: %s", - m_variable_sp->GetName().AsCString(), free_error.AsCString()); + GetName().AsCString(), free_error.AsCString()); return; } @@ -748,13 +753,140 @@ public: } private: - lldb::VariableSP m_variable_sp; + virtual ConstString GetName() const = 0; + + /// Creates and returns ValueObject tied to this variable + /// and prepares Entity for materialization. + /// + /// Called each time the Materializer (de)materializes a + /// variable. We re-create the ValueObject based on the + /// current ExecutionContextScope since clients such as + /// conditional breakpoints may materialize the same + /// EntityVariable multiple times with different frames. + /// + /// Each subsequent use of the EntityVariableBase interface + /// will query the newly created ValueObject until this + /// function is called again. + virtual lldb::ValueObjectSP + SetupValueObject(ExecutionContextScope *scope) = 0; + + /// Returns size in bytes of the type associated with this variable + /// + /// \returns On success, returns byte size of the type associated + /// with this variable. Returns NoneType otherwise. + virtual llvm::Optional<uint64_t> + GetByteSize(ExecutionContextScope *scope) const = 0; + + /// Returns 'true' if the location expression associated with this variable + /// is valid. + virtual bool LocationExpressionIsValid() const = 0; + + /// Returns alignment of the type associated with this variable in bits. + /// + /// \returns On success, returns alignment in bits for the type associated + /// with this variable. Returns NoneType otherwise. + virtual llvm::Optional<size_t> + GetTypeBitAlign(ExecutionContextScope *scope) const = 0; + +protected: bool m_is_reference = false; lldb::addr_t m_temporary_allocation = LLDB_INVALID_ADDRESS; size_t m_temporary_allocation_size = 0; lldb::DataBufferSP m_original_data; }; +/// Represents an Entity constructed from a VariableSP. +/// +/// This class is used for materialization of variables for which +/// the user has a VariableSP on hand. The ValueObject is then +/// derived from the associated DWARF location expression when needed +/// by the Materializer. +class EntityVariable : public EntityVariableBase { +public: + EntityVariable(lldb::VariableSP &variable_sp) : m_variable_sp(variable_sp) { + m_is_reference = + m_variable_sp->GetType()->GetForwardCompilerType().IsReferenceType(); + } + + ConstString GetName() const override { return m_variable_sp->GetName(); } + + lldb::ValueObjectSP SetupValueObject(ExecutionContextScope *scope) override { + assert(m_variable_sp != nullptr); + return ValueObjectVariable::Create(scope, m_variable_sp); + } + + llvm::Optional<uint64_t> + GetByteSize(ExecutionContextScope *scope) const override { + return m_variable_sp->GetType()->GetByteSize(scope); + } + + bool LocationExpressionIsValid() const override { + return m_variable_sp->LocationExpressionList().IsValid(); + } + + llvm::Optional<size_t> + GetTypeBitAlign(ExecutionContextScope *scope) const override { + return m_variable_sp->GetType()->GetLayoutCompilerType().GetTypeBitAlign( + scope); + } + +private: + lldb::VariableSP m_variable_sp; ///< Variable that this entity is based on. +}; + +/// Represents an Entity constructed from a VariableSP. +/// +/// This class is used for materialization of variables for +/// which the user does not have a VariableSP available (e.g., +/// when materializing ivars). +class EntityValueObject : public EntityVariableBase { +public: + EntityValueObject(ConstString name, ValueObjectProviderTy provider) + : m_name(name), m_valobj_provider(std::move(provider)) { + assert(m_valobj_provider); + } + + ConstString GetName() const override { return m_name; } + + lldb::ValueObjectSP SetupValueObject(ExecutionContextScope *scope) override { + m_valobj_sp = + m_valobj_provider(GetName(), scope->CalculateStackFrame().get()); + + if (m_valobj_sp) + m_is_reference = m_valobj_sp->GetCompilerType().IsReferenceType(); + + return m_valobj_sp; + } + + llvm::Optional<uint64_t> + GetByteSize(ExecutionContextScope *scope) const override { + if (m_valobj_sp) + return m_valobj_sp->GetCompilerType().GetByteSize(scope); + + return {}; + } + + bool LocationExpressionIsValid() const override { + if (m_valobj_sp) + return m_valobj_sp->GetError().Success(); + + return false; + } + + llvm::Optional<size_t> + GetTypeBitAlign(ExecutionContextScope *scope) const override { + if (m_valobj_sp) + return m_valobj_sp->GetCompilerType().GetTypeBitAlign(scope); + + return {}; + } + +private: + ConstString m_name; + lldb::ValueObjectSP m_valobj_sp; + ValueObjectProviderTy m_valobj_provider; +}; + uint32_t Materializer::AddVariable(lldb::VariableSP &variable_sp, Status &err) { EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); *iter = std::make_unique<EntityVariable>(variable_sp); @@ -763,6 +895,17 @@ uint32_t Materializer::AddVariable(lldb::VariableSP &variable_sp, Status &err) { return ret; } +uint32_t Materializer::AddValueObject(ConstString name, + ValueObjectProviderTy valobj_provider, + Status &err) { + assert(valobj_provider); + EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP()); + *iter = std::make_unique<EntityValueObject>(name, std::move(valobj_provider)); + uint32_t ret = AddStructMember(**iter); + (*iter)->SetOffset(ret); + return ret; +} + class EntityResultVariable : public Materializer::Entity { public: EntityResultVariable(const CompilerType &type, bool is_program_reference, @@ -772,8 +915,8 @@ public: m_keep_in_memory(keep_in_memory), m_delegate(delegate) { // Hard-coding to maximum size of a pointer since all results are // materialized by reference - m_size = 8; - m_alignment = 8; + m_size = g_default_var_byte_size; + m_alignment = g_default_var_alignment; } void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, @@ -1050,8 +1193,8 @@ class EntitySymbol : public Materializer::Entity { public: EntitySymbol(const Symbol &symbol) : Entity(), m_symbol(symbol) { // Hard-coding to maximum size of a symbol - m_size = 8; - m_alignment = 8; + m_size = g_default_var_byte_size; + m_alignment = g_default_var_alignment; } void Materialize(lldb::StackFrameSP &frame_sp, IRMemoryMap &map, diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp index f821603f03e5..186e414e6879 100644 --- a/lldb/source/Expression/UserExpression.cpp +++ b/lldb/source/Expression/UserExpression.cpp @@ -98,28 +98,34 @@ bool UserExpression::MatchesContext(ExecutionContext &exe_ctx) { return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp); } -lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp, - ConstString &object_name, - Status &err) { +lldb::ValueObjectSP UserExpression::GetObjectPointerValueObject( + lldb::StackFrameSP frame_sp, ConstString const &object_name, Status &err) { err.Clear(); if (!frame_sp) { err.SetErrorStringWithFormat( "Couldn't load '%s' because the context is incomplete", object_name.AsCString()); - return LLDB_INVALID_ADDRESS; + return {}; } lldb::VariableSP var_sp; lldb::ValueObjectSP valobj_sp; - valobj_sp = frame_sp->GetValueForVariableExpressionPath( + return frame_sp->GetValueForVariableExpressionPath( object_name.GetStringRef(), lldb::eNoDynamicValues, StackFrame::eExpressionPathOptionCheckPtrVsMember | StackFrame::eExpressionPathOptionsNoFragileObjcIvar | StackFrame::eExpressionPathOptionsNoSyntheticChildren | StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, var_sp, err); +} + +lldb::addr_t UserExpression::GetObjectPointer(lldb::StackFrameSP frame_sp, + ConstString &object_name, + Status &err) { + auto valobj_sp = + GetObjectPointerValueObject(std::move(frame_sp), object_name, err); if (!err.Success() || !valobj_sp.get()) return LLDB_INVALID_ADDRESS; diff --git a/lldb/source/Host/common/File.cpp b/lldb/source/Host/common/File.cpp index 760fb98fb496..ce5283a61375 100644 --- a/lldb/source/Host/common/File.cpp +++ b/lldb/source/Host/common/File.cpp @@ -833,22 +833,20 @@ SerialPort::Create(int fd, OpenOptions options, Options serial_options, if (llvm::Error error = term.SetRaw()) return std::move(error); if (serial_options.BaudRate) { - if (llvm::Error error = - term.SetBaudRate(serial_options.BaudRate.getValue())) + if (llvm::Error error = term.SetBaudRate(serial_options.BaudRate.value())) return std::move(error); } if (serial_options.Parity) { - if (llvm::Error error = term.SetParity(serial_options.Parity.getValue())) + if (llvm::Error error = term.SetParity(serial_options.Parity.value())) return std::move(error); } if (serial_options.ParityCheck) { if (llvm::Error error = - term.SetParityCheck(serial_options.ParityCheck.getValue())) + term.SetParityCheck(serial_options.ParityCheck.value())) return std::move(error); } if (serial_options.StopBits) { - if (llvm::Error error = - term.SetStopBits(serial_options.StopBits.getValue())) + if (llvm::Error error = term.SetStopBits(serial_options.StopBits.value())) return std::move(error); } diff --git a/lldb/source/Host/common/Terminal.cpp b/lldb/source/Host/common/Terminal.cpp index 831e9dff4eb1..5da5ee8f1468 100644 --- a/lldb/source/Host/common/Terminal.cpp +++ b/lldb/source/Host/common/Terminal.cpp @@ -281,11 +281,11 @@ llvm::Error Terminal::SetBaudRate(unsigned int baud_rate) { return llvm::createStringError(llvm::inconvertibleErrorCode(), "baud rate %d unsupported by the platform", baud_rate); - if (::cfsetispeed(&fd_termios, val.getValue()) != 0) + if (::cfsetispeed(&fd_termios, val.value()) != 0) return llvm::createStringError( std::error_code(errno, std::generic_category()), "setting input baud rate failed"); - if (::cfsetospeed(&fd_termios, val.getValue()) != 0) + if (::cfsetospeed(&fd_termios, val.value()) != 0) return llvm::createStringError( std::error_code(errno, std::generic_category()), "setting output baud rate failed"); diff --git a/lldb/source/Interpreter/CommandObject.cpp b/lldb/source/Interpreter/CommandObject.cpp index 910d740625e9..719cfbc9e802 100644 --- a/lldb/source/Interpreter/CommandObject.cpp +++ b/lldb/source/Interpreter/CommandObject.cpp @@ -16,6 +16,7 @@ #include <cstdlib> #include "lldb/Core/Address.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/Options.h" #include "lldb/Utility/ArchSpec.h" #include "llvm/ADT/ScopeExit.h" @@ -31,6 +32,7 @@ #include "lldb/Target/Language.h" #include "lldb/Interpreter/CommandInterpreter.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Interpreter/CommandReturnObject.h" using namespace lldb; @@ -365,19 +367,16 @@ CommandObject::GetArgumentEntryAtIndex(int idx) { const CommandObject::ArgumentTableEntry * CommandObject::FindArgumentDataByType(CommandArgumentType arg_type) { - const ArgumentTableEntry *table = CommandObject::GetArgumentTable(); - for (int i = 0; i < eArgTypeLastArg; ++i) - if (table[i].arg_type == arg_type) - return &(table[i]); + if (g_argument_table[i].arg_type == arg_type) + return &(g_argument_table[i]); return nullptr; } void CommandObject::GetArgumentHelp(Stream &str, CommandArgumentType arg_type, CommandInterpreter &interpreter) { - const ArgumentTableEntry *table = CommandObject::GetArgumentTable(); - const ArgumentTableEntry *entry = &(table[arg_type]); + const ArgumentTableEntry *entry = &(g_argument_table[arg_type]); // The table is *supposed* to be kept in arg_type order, but someone *could* // have messed it up... @@ -400,14 +399,32 @@ void CommandObject::GetArgumentHelp(Stream &str, CommandArgumentType arg_type, interpreter.OutputHelpText(str, name_str.GetString(), "--", help_text, name_str.GetSize()); } - } else + } else { interpreter.OutputFormattedHelpText(str, name_str.GetString(), "--", entry->help_text, name_str.GetSize()); + + // Print enum values and their description if any. + OptionEnumValues enum_values = g_argument_table[arg_type].enum_values; + if (!enum_values.empty()) { + str.EOL(); + size_t longest = 0; + for (const OptionEnumValueElement &element : enum_values) + longest = + std::max(longest, llvm::StringRef(element.string_value).size()); + str.IndentMore(5); + for (const OptionEnumValueElement &element : enum_values) { + str.Indent(); + interpreter.OutputHelpText(str, element.string_value, ":", + element.usage, longest); + } + str.IndentLess(5); + str.EOL(); + } + } } const char *CommandObject::GetArgumentName(CommandArgumentType arg_type) { - const ArgumentTableEntry *entry = - &(CommandObject::GetArgumentTable()[arg_type]); + const ArgumentTableEntry *entry = &(g_argument_table[arg_type]); // The table is *supposed* to be kept in arg_type order, but someone *could* // have messed it up... @@ -544,287 +561,13 @@ CommandObject::LookupArgumentName(llvm::StringRef arg_name) { arg_name = arg_name.ltrim('<').rtrim('>'); - const ArgumentTableEntry *table = GetArgumentTable(); for (int i = 0; i < eArgTypeLastArg; ++i) - if (arg_name == table[i].arg_name) - return_type = GetArgumentTable()[i].arg_type; + if (arg_name == g_argument_table[i].arg_name) + return_type = g_argument_table[i].arg_type; return return_type; } -static llvm::StringRef RegisterNameHelpTextCallback() { - return "Register names can be specified using the architecture specific " - "names. " - "They can also be specified using generic names. Not all generic " - "entities have " - "registers backing them on all architectures. When they don't the " - "generic name " - "will return an error.\n" - "The generic names defined in lldb are:\n" - "\n" - "pc - program counter register\n" - "ra - return address register\n" - "fp - frame pointer register\n" - "sp - stack pointer register\n" - "flags - the flags register\n" - "arg{1-6} - integer argument passing registers.\n"; -} - -static llvm::StringRef BreakpointIDHelpTextCallback() { - return "Breakpoints are identified using major and minor numbers; the major " - "number corresponds to the single entity that was created with a " - "'breakpoint " - "set' command; the minor numbers correspond to all the locations that " - "were " - "actually found/set based on the major breakpoint. A full breakpoint " - "ID might " - "look like 3.14, meaning the 14th location set for the 3rd " - "breakpoint. You " - "can specify all the locations of a breakpoint by just indicating the " - "major " - "breakpoint number. A valid breakpoint ID consists either of just the " - "major " - "number, or the major number followed by a dot and the location " - "number (e.g. " - "3 or 3.2 could both be valid breakpoint IDs.)"; -} - -static llvm::StringRef BreakpointIDRangeHelpTextCallback() { - return "A 'breakpoint ID list' is a manner of specifying multiple " - "breakpoints. " - "This can be done through several mechanisms. The easiest way is to " - "just " - "enter a space-separated list of breakpoint IDs. To specify all the " - "breakpoint locations under a major breakpoint, you can use the major " - "breakpoint number followed by '.*', eg. '5.*' means all the " - "locations under " - "breakpoint 5. You can also indicate a range of breakpoints by using " - "<start-bp-id> - <end-bp-id>. The start-bp-id and end-bp-id for a " - "range can " - "be any valid breakpoint IDs. It is not legal, however, to specify a " - "range " - "using specific locations that cross major breakpoint numbers. I.e. " - "3.2 - 3.7" - " is legal; 2 - 5 is legal; but 3.2 - 4.4 is not legal."; -} - -static llvm::StringRef BreakpointNameHelpTextCallback() { - return "A name that can be added to a breakpoint when it is created, or " - "later " - "on with the \"breakpoint name add\" command. " - "Breakpoint names can be used to specify breakpoints in all the " - "places breakpoint IDs " - "and breakpoint ID ranges can be used. As such they provide a " - "convenient way to group breakpoints, " - "and to operate on breakpoints you create without having to track the " - "breakpoint number. " - "Note, the attributes you set when using a breakpoint name in a " - "breakpoint command don't " - "adhere to the name, but instead are set individually on all the " - "breakpoints currently tagged with that " - "name. Future breakpoints " - "tagged with that name will not pick up the attributes previously " - "given using that name. " - "In order to distinguish breakpoint names from breakpoint IDs and " - "ranges, " - "names must start with a letter from a-z or A-Z and cannot contain " - "spaces, \".\" or \"-\". " - "Also, breakpoint names can only be applied to breakpoints, not to " - "breakpoint locations."; -} - -static llvm::StringRef GDBFormatHelpTextCallback() { - return "A GDB format consists of a repeat count, a format letter and a size " - "letter. " - "The repeat count is optional and defaults to 1. The format letter is " - "optional " - "and defaults to the previous format that was used. The size letter " - "is optional " - "and defaults to the previous size that was used.\n" - "\n" - "Format letters include:\n" - "o - octal\n" - "x - hexadecimal\n" - "d - decimal\n" - "u - unsigned decimal\n" - "t - binary\n" - "f - float\n" - "a - address\n" - "i - instruction\n" - "c - char\n" - "s - string\n" - "T - OSType\n" - "A - float as hex\n" - "\n" - "Size letters include:\n" - "b - 1 byte (byte)\n" - "h - 2 bytes (halfword)\n" - "w - 4 bytes (word)\n" - "g - 8 bytes (giant)\n" - "\n" - "Example formats:\n" - "32xb - show 32 1 byte hexadecimal integer values\n" - "16xh - show 16 2 byte hexadecimal integer values\n" - "64 - show 64 2 byte hexadecimal integer values (format and size " - "from the last format)\n" - "dw - show 1 4 byte decimal integer value\n"; -} - -static llvm::StringRef FormatHelpTextCallback() { - static std::string help_text; - - if (!help_text.empty()) - return help_text; - - StreamString sstr; - sstr << "One of the format names (or one-character names) that can be used " - "to show a variable's value:\n"; - for (Format f = eFormatDefault; f < kNumFormats; f = Format(f + 1)) { - if (f != eFormatDefault) - sstr.PutChar('\n'); - - char format_char = FormatManager::GetFormatAsFormatChar(f); - if (format_char) - sstr.Printf("'%c' or ", format_char); - - sstr.Printf("\"%s\"", FormatManager::GetFormatAsCString(f)); - } - - sstr.Flush(); - - help_text = std::string(sstr.GetString()); - - return help_text; -} - -static llvm::StringRef LanguageTypeHelpTextCallback() { - static std::string help_text; - - if (!help_text.empty()) - return help_text; - - StreamString sstr; - sstr << "One of the following languages:\n"; - - Language::PrintAllLanguages(sstr, " ", "\n"); - - sstr.Flush(); - - help_text = std::string(sstr.GetString()); - - return help_text; -} - -static llvm::StringRef SummaryStringHelpTextCallback() { - return "A summary string is a way to extract information from variables in " - "order to present them using a summary.\n" - "Summary strings contain static text, variables, scopes and control " - "sequences:\n" - " - Static text can be any sequence of non-special characters, i.e. " - "anything but '{', '}', '$', or '\\'.\n" - " - Variables are sequences of characters beginning with ${, ending " - "with } and that contain symbols in the format described below.\n" - " - Scopes are any sequence of text between { and }. Anything " - "included in a scope will only appear in the output summary if there " - "were no errors.\n" - " - Control sequences are the usual C/C++ '\\a', '\\n', ..., plus " - "'\\$', '\\{' and '\\}'.\n" - "A summary string works by copying static text verbatim, turning " - "control sequences into their character counterpart, expanding " - "variables and trying to expand scopes.\n" - "A variable is expanded by giving it a value other than its textual " - "representation, and the way this is done depends on what comes after " - "the ${ marker.\n" - "The most common sequence if ${var followed by an expression path, " - "which is the text one would type to access a member of an aggregate " - "types, given a variable of that type" - " (e.g. if type T has a member named x, which has a member named y, " - "and if t is of type T, the expression path would be .x.y and the way " - "to fit that into a summary string would be" - " ${var.x.y}). You can also use ${*var followed by an expression path " - "and in that case the object referred by the path will be " - "dereferenced before being displayed." - " If the object is not a pointer, doing so will cause an error. For " - "additional details on expression paths, you can type 'help " - "expr-path'. \n" - "By default, summary strings attempt to display the summary for any " - "variable they reference, and if that fails the value. If neither can " - "be shown, nothing is displayed." - "In a summary string, you can also use an array index [n], or a " - "slice-like range [n-m]. This can have two different meanings " - "depending on what kind of object the expression" - " path refers to:\n" - " - if it is a scalar type (any basic type like int, float, ...) the " - "expression is a bitfield, i.e. the bits indicated by the indexing " - "operator are extracted out of the number" - " and displayed as an individual variable\n" - " - if it is an array or pointer the array items indicated by the " - "indexing operator are shown as the result of the variable. if the " - "expression is an array, real array items are" - " printed; if it is a pointer, the pointer-as-array syntax is used to " - "obtain the values (this means, the latter case can have no range " - "checking)\n" - "If you are trying to display an array for which the size is known, " - "you can also use [] instead of giving an exact range. This has the " - "effect of showing items 0 thru size - 1.\n" - "Additionally, a variable can contain an (optional) format code, as " - "in ${var.x.y%code}, where code can be any of the valid formats " - "described in 'help format', or one of the" - " special symbols only allowed as part of a variable:\n" - " %V: show the value of the object by default\n" - " %S: show the summary of the object by default\n" - " %@: show the runtime-provided object description (for " - "Objective-C, it calls NSPrintForDebugger; for C/C++ it does " - "nothing)\n" - " %L: show the location of the object (memory address or a " - "register name)\n" - " %#: show the number of children of the object\n" - " %T: show the type of the object\n" - "Another variable that you can use in summary strings is ${svar . " - "This sequence works exactly like ${var, including the fact that " - "${*svar is an allowed sequence, but uses" - " the object's synthetic children provider instead of the actual " - "objects. For instance, if you are using STL synthetic children " - "providers, the following summary string would" - " count the number of actual elements stored in an std::list:\n" - "type summary add -s \"${svar%#}\" -x \"std::list<\""; -} - -static llvm::StringRef ExprPathHelpTextCallback() { - return "An expression path is the sequence of symbols that is used in C/C++ " - "to access a member variable of an aggregate object (class).\n" - "For instance, given a class:\n" - " class foo {\n" - " int a;\n" - " int b; .\n" - " foo* next;\n" - " };\n" - "the expression to read item b in the item pointed to by next for foo " - "aFoo would be aFoo.next->b.\n" - "Given that aFoo could just be any object of type foo, the string " - "'.next->b' is the expression path, because it can be attached to any " - "foo instance to achieve the effect.\n" - "Expression paths in LLDB include dot (.) and arrow (->) operators, " - "and most commands using expression paths have ways to also accept " - "the star (*) operator.\n" - "The meaning of these operators is the same as the usual one given to " - "them by the C/C++ standards.\n" - "LLDB also has support for indexing ([ ]) in expression paths, and " - "extends the traditional meaning of the square brackets operator to " - "allow bitfield extraction:\n" - "for objects of native types (int, float, char, ...) saying '[n-m]' " - "as an expression path (where n and m are any positive integers, e.g. " - "[3-5]) causes LLDB to extract" - " bits n thru m from the value of the variable. If n == m, [n] is " - "also allowed as a shortcut syntax. For arrays and pointers, " - "expression paths can only contain one index" - " and the meaning of the operation is the same as the one defined by " - "C/C++ (item extraction). Some commands extend bitfield-like syntax " - "for arrays and pointers with the" - " meaning of array slicing (taking elements n thru m inside the array " - "or pointed-to memory)."; -} - void CommandObject::FormatLongHelpText(Stream &output_strm, llvm::StringRef long_help) { CommandInterpreter &interpreter = GetCommandInterpreter(); @@ -924,14 +667,14 @@ const char *CommandObject::GetArgumentTypeAsCString( const lldb::CommandArgumentType arg_type) { assert(arg_type < eArgTypeLastArg && "Invalid argument type passed to GetArgumentTypeAsCString"); - return GetArgumentTable()[arg_type].arg_name; + return g_argument_table[arg_type].arg_name; } const char *CommandObject::GetArgumentDescriptionAsCString( const lldb::CommandArgumentType arg_type) { assert(arg_type < eArgTypeLastArg && "Invalid argument type passed to GetArgumentDescriptionAsCString"); - return GetArgumentTable()[arg_type].help_text; + return g_argument_table[arg_type].help_text; } Target &CommandObject::GetDummyTarget() { @@ -1028,124 +771,3 @@ bool CommandObjectRaw::Execute(const char *args_string, } return handled; } - -static llvm::StringRef arch_helper() { - static StreamString g_archs_help; - if (g_archs_help.Empty()) { - StringList archs; - - ArchSpec::ListSupportedArchNames(archs); - g_archs_help.Printf("These are the supported architecture names:\n"); - archs.Join("\n", g_archs_help); - } - return g_archs_help.GetString(); -} - -static constexpr CommandObject::ArgumentTableEntry g_arguments_data[] = { - // clang-format off - { eArgTypeAddress, "address", CommandCompletions::eNoCompletion, { nullptr, false }, "A valid address in the target program's execution space." }, - { eArgTypeAddressOrExpression, "address-expression", CommandCompletions::eNoCompletion, { nullptr, false }, "An expression that resolves to an address." }, - { eArgTypeAliasName, "alias-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of an abbreviation (alias) for a debugger command." }, - { eArgTypeAliasOptions, "options-for-aliased-command", CommandCompletions::eNoCompletion, { nullptr, false }, "Command options to be used as part of an alias (abbreviation) definition. (See 'help commands alias' for more information.)" }, - { eArgTypeArchitecture, "arch", CommandCompletions::eArchitectureCompletion, { arch_helper, true }, "The architecture name, e.g. i386 or x86_64." }, - { eArgTypeBoolean, "boolean", CommandCompletions::eNoCompletion, { nullptr, false }, "A Boolean value: 'true' or 'false'" }, - { eArgTypeBreakpointID, "breakpt-id", CommandCompletions::eNoCompletion, { BreakpointIDHelpTextCallback, false }, nullptr }, - { eArgTypeBreakpointIDRange, "breakpt-id-list", CommandCompletions::eNoCompletion, { BreakpointIDRangeHelpTextCallback, false }, nullptr }, - { eArgTypeBreakpointName, "breakpoint-name", CommandCompletions::eBreakpointNameCompletion, { BreakpointNameHelpTextCallback, false }, nullptr }, - { eArgTypeByteSize, "byte-size", CommandCompletions::eNoCompletion, { nullptr, false }, "Number of bytes to use." }, - { eArgTypeClassName, "class-name", CommandCompletions::eNoCompletion, { nullptr, false }, "Then name of a class from the debug information in the program." }, - { eArgTypeCommandName, "cmd-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A debugger command (may be multiple words), without any options or arguments." }, - { eArgTypeCount, "count", CommandCompletions::eNoCompletion, { nullptr, false }, "An unsigned integer." }, - { eArgTypeDirectoryName, "directory", CommandCompletions::eDiskDirectoryCompletion, { nullptr, false }, "A directory name." }, - { eArgTypeDisassemblyFlavor, "disassembly-flavor", CommandCompletions::eDisassemblyFlavorCompletion, { nullptr, false }, "A disassembly flavor recognized by your disassembly plugin. Currently the only valid options are \"att\" and \"intel\" for Intel targets" }, - { eArgTypeDescriptionVerbosity, "description-verbosity", CommandCompletions::eNoCompletion, { nullptr, false }, "How verbose the output of 'po' should be." }, - { eArgTypeEndAddress, "end-address", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, - { eArgTypeExpression, "expr", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, - { eArgTypeExpressionPath, "expr-path", CommandCompletions::eNoCompletion, { ExprPathHelpTextCallback, true }, nullptr }, - { eArgTypeExprFormat, "expression-format", CommandCompletions::eNoCompletion, { nullptr, false }, "[ [bool|b] | [bin] | [char|c] | [oct|o] | [dec|i|d|u] | [hex|x] | [float|f] | [cstr|s] ]" }, - { eArgTypeFilename, "filename", CommandCompletions::eDiskFileCompletion, { nullptr, false }, "The name of a file (can include path)." }, - { eArgTypeFormat, "format", CommandCompletions::eNoCompletion, { FormatHelpTextCallback, true }, nullptr }, - { eArgTypeFrameIndex, "frame-index", CommandCompletions::eFrameIndexCompletion, { nullptr, false }, "Index into a thread's list of frames." }, - { eArgTypeFullName, "fullname", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, - { eArgTypeFunctionName, "function-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a function." }, - { eArgTypeFunctionOrSymbol, "function-or-symbol", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a function or symbol." }, - { eArgTypeGDBFormat, "gdb-format", CommandCompletions::eNoCompletion, { GDBFormatHelpTextCallback, true }, nullptr }, - { eArgTypeHelpText, "help-text", CommandCompletions::eNoCompletion, { nullptr, false }, "Text to be used as help for some other entity in LLDB" }, - { eArgTypeIndex, "index", CommandCompletions::eNoCompletion, { nullptr, false }, "An index into a list." }, - { eArgTypeLanguage, "source-language", CommandCompletions::eTypeLanguageCompletion, { LanguageTypeHelpTextCallback, true }, nullptr }, - { eArgTypeLineNum, "linenum", CommandCompletions::eNoCompletion, { nullptr, false }, "Line number in a source file." }, - { eArgTypeFileLineColumn, "linespec", CommandCompletions::eNoCompletion, { nullptr, false }, "A source specifier in the form file:line[:column]" }, - { eArgTypeLogCategory, "log-category", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a category within a log channel, e.g. all (try \"log list\" to see a list of all channels and their categories." }, - { eArgTypeLogChannel, "log-channel", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a log channel, e.g. process.gdb-remote (try \"log list\" to see a list of all channels and their categories)." }, - { eArgTypeMethod, "method", CommandCompletions::eNoCompletion, { nullptr, false }, "A C++ method name." }, - { eArgTypeName, "name", CommandCompletions::eTypeCategoryNameCompletion, { nullptr, false }, "Help text goes here." }, - { eArgTypeNewPathPrefix, "new-path-prefix", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, - { eArgTypeNumLines, "num-lines", CommandCompletions::eNoCompletion, { nullptr, false }, "The number of lines to use." }, - { eArgTypeNumberPerLine, "number-per-line", CommandCompletions::eNoCompletion, { nullptr, false }, "The number of items per line to display." }, - { eArgTypeOffset, "offset", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, - { eArgTypeOldPathPrefix, "old-path-prefix", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, - { eArgTypeOneLiner, "one-line-command", CommandCompletions::eNoCompletion, { nullptr, false }, "A command that is entered as a single line of text." }, - { eArgTypePath, "path", CommandCompletions::eDiskFileCompletion, { nullptr, false }, "Path." }, - { eArgTypePermissionsNumber, "perms-numeric", CommandCompletions::eNoCompletion, { nullptr, false }, "Permissions given as an octal number (e.g. 755)." }, - { eArgTypePermissionsString, "perms=string", CommandCompletions::eNoCompletion, { nullptr, false }, "Permissions given as a string value (e.g. rw-r-xr--)." }, - { eArgTypePid, "pid", CommandCompletions::eProcessIDCompletion, { nullptr, false }, "The process ID number." }, - { eArgTypePlugin, "plugin", CommandCompletions::eProcessPluginCompletion, { nullptr, false }, "Help text goes here." }, - { eArgTypeProcessName, "process-name", CommandCompletions::eProcessNameCompletion, { nullptr, false }, "The name of the process." }, - { eArgTypePythonClass, "python-class", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a Python class." }, - { eArgTypePythonFunction, "python-function", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a Python function." }, - { eArgTypePythonScript, "python-script", CommandCompletions::eNoCompletion, { nullptr, false }, "Source code written in Python." }, - { eArgTypeQueueName, "queue-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of the thread queue." }, - { eArgTypeRegisterName, "register-name", CommandCompletions::eNoCompletion, { RegisterNameHelpTextCallback, true }, nullptr }, - { eArgTypeRegularExpression, "regular-expression", CommandCompletions::eNoCompletion, { nullptr, false }, "A POSIX-compliant extended regular expression." }, - { eArgTypeRunArgs, "run-args", CommandCompletions::eNoCompletion, { nullptr, false }, "Arguments to be passed to the target program when it starts executing." }, - { eArgTypeRunMode, "run-mode", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, - { eArgTypeScriptedCommandSynchronicity, "script-cmd-synchronicity", CommandCompletions::eNoCompletion, { nullptr, false }, "The synchronicity to use to run scripted commands with regard to LLDB event system." }, - { eArgTypeScriptLang, "script-language", CommandCompletions::eNoCompletion, { nullptr, false }, "The scripting language to be used for script-based commands. Supported languages are python and lua." }, - { eArgTypeSearchWord, "search-word", CommandCompletions::eNoCompletion, { nullptr, false }, "Any word of interest for search purposes." }, - { eArgTypeSelector, "selector", CommandCompletions::eNoCompletion, { nullptr, false }, "An Objective-C selector name." }, - { eArgTypeSettingIndex, "setting-index", CommandCompletions::eNoCompletion, { nullptr, false }, "An index into a settings variable that is an array (try 'settings list' to see all the possible settings variables and their types)." }, - { eArgTypeSettingKey, "setting-key", CommandCompletions::eNoCompletion, { nullptr, false }, "A key into a settings variables that is a dictionary (try 'settings list' to see all the possible settings variables and their types)." }, - { eArgTypeSettingPrefix, "setting-prefix", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a settable internal debugger variable up to a dot ('.'), e.g. 'target.process.'" }, - { eArgTypeSettingVariableName, "setting-variable-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a settable internal debugger variable. Type 'settings list' to see a complete list of such variables." }, - { eArgTypeShlibName, "shlib-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a shared library." }, - { eArgTypeSourceFile, "source-file", CommandCompletions::eSourceFileCompletion, { nullptr, false }, "The name of a source file.." }, - { eArgTypeSortOrder, "sort-order", CommandCompletions::eNoCompletion, { nullptr, false }, "Specify a sort order when dumping lists." }, - { eArgTypeStartAddress, "start-address", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, - { eArgTypeSummaryString, "summary-string", CommandCompletions::eNoCompletion, { SummaryStringHelpTextCallback, true }, nullptr }, - { eArgTypeSymbol, "symbol", CommandCompletions::eSymbolCompletion, { nullptr, false }, "Any symbol name (function name, variable, argument, etc.)" }, - { eArgTypeThreadID, "thread-id", CommandCompletions::eNoCompletion, { nullptr, false }, "Thread ID number." }, - { eArgTypeThreadIndex, "thread-index", CommandCompletions::eNoCompletion, { nullptr, false }, "Index into the process' list of threads." }, - { eArgTypeThreadName, "thread-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The thread's name." }, - { eArgTypeTypeName, "type-name", CommandCompletions::eNoCompletion, { nullptr, false }, "A type name." }, - { eArgTypeUnsignedInteger, "unsigned-integer", CommandCompletions::eNoCompletion, { nullptr, false }, "An unsigned integer." }, - { eArgTypeUnixSignal, "unix-signal", CommandCompletions::eNoCompletion, { nullptr, false }, "A valid Unix signal name or number (e.g. SIGKILL, KILL or 9)." }, - { eArgTypeVarName, "variable-name", CommandCompletions::eNoCompletion, { nullptr, false }, "The name of a variable in your program." }, - { eArgTypeValue, "value", CommandCompletions::eNoCompletion, { nullptr, false }, "A value could be anything, depending on where and how it is used." }, - { eArgTypeWidth, "width", CommandCompletions::eNoCompletion, { nullptr, false }, "Help text goes here." }, - { eArgTypeNone, "none", CommandCompletions::eNoCompletion, { nullptr, false }, "No help available for this." }, - { eArgTypePlatform, "platform-name", CommandCompletions::ePlatformPluginCompletion, { nullptr, false }, "The name of an installed platform plug-in . Type 'platform list' to see a complete list of installed platforms." }, - { eArgTypeWatchpointID, "watchpt-id", CommandCompletions::eNoCompletion, { nullptr, false }, "Watchpoint IDs are positive integers." }, - { eArgTypeWatchpointIDRange, "watchpt-id-list", CommandCompletions::eNoCompletion, { nullptr, false }, "For example, '1-3' or '1 to 3'." }, - { eArgTypeWatchType, "watch-type", CommandCompletions::eNoCompletion, { nullptr, false }, "Specify the type for a watchpoint." }, - { eArgRawInput, "raw-input", CommandCompletions::eNoCompletion, { nullptr, false }, "Free-form text passed to a command without prior interpretation, allowing spaces without requiring quotes. To pass arguments and free form text put two dashes ' -- ' between the last argument and any raw input." }, - { eArgTypeCommand, "command", CommandCompletions::eNoCompletion, { nullptr, false }, "An LLDB Command line command element." }, - { eArgTypeColumnNum, "column", CommandCompletions::eNoCompletion, { nullptr, false }, "Column number in a source file." }, - { eArgTypeModuleUUID, "module-uuid", CommandCompletions::eModuleUUIDCompletion, { nullptr, false }, "A module UUID value." }, - { eArgTypeSaveCoreStyle, "corefile-style", CommandCompletions::eNoCompletion, { nullptr, false }, "The type of corefile that lldb will try to create, dependant on this target's capabilities." }, - { eArgTypeLogHandler, "log-handler", CommandCompletions::eNoCompletion, { nullptr, false }, "The log handle that will be used to write out log messages." }, - { eArgTypeSEDStylePair, "substitution-pair", CommandCompletions::eNoCompletion, { nullptr, false }, "A sed-style pattern and target pair." }, - { eArgTypeRecognizerID, "frame-recognizer-id", CommandCompletions::eNoCompletion, { nullptr, false }, "The ID for a stack frame recognizer." }, - { eArgTypeConnectURL, "process-connect-url", CommandCompletions::eNoCompletion, { nullptr, false }, "A URL-style specification for a remote connection." }, - { eArgTypeTargetID, "target-id", CommandCompletions::eNoCompletion, { nullptr, false }, "The index ID for an lldb Target." }, - { eArgTypeStopHookID, "stop-hook-id", CommandCompletions::eNoCompletion, { nullptr, false }, "The ID you receive when you create a stop-hook." } - // clang-format on -}; - -static_assert( - (sizeof(g_arguments_data) / sizeof(CommandObject::ArgumentTableEntry)) == - eArgTypeLastArg, - "g_arguments_data out of sync with CommandArgumentType enumeration"); - -const CommandObject::ArgumentTableEntry *CommandObject::GetArgumentTable() { - return g_arguments_data; -} diff --git a/lldb/source/Interpreter/OptionValueArray.cpp b/lldb/source/Interpreter/OptionValueArray.cpp index 4468fe57702e..c202a188fe2a 100644 --- a/lldb/source/Interpreter/OptionValueArray.cpp +++ b/lldb/source/Interpreter/OptionValueArray.cpp @@ -218,7 +218,7 @@ Status OptionValueArray::SetArgs(const Args &args, VarSetOperationType op) { if (num_remove_indexes) { // Sort and then erase in reverse so indexes are always valid if (num_remove_indexes > 1) { - llvm::sort(remove_indexes.begin(), remove_indexes.end()); + llvm::sort(remove_indexes); for (std::vector<int>::const_reverse_iterator pos = remove_indexes.rbegin(), end = remove_indexes.rend(); diff --git a/lldb/source/Interpreter/OptionValueFileSpecList.cpp b/lldb/source/Interpreter/OptionValueFileSpecList.cpp index 6566eee09d73..9b4114e2ceb2 100644 --- a/lldb/source/Interpreter/OptionValueFileSpecList.cpp +++ b/lldb/source/Interpreter/OptionValueFileSpecList.cpp @@ -137,7 +137,7 @@ Status OptionValueFileSpecList::SetValueFromString(llvm::StringRef value, size_t num_remove_indexes = remove_indexes.size(); if (num_remove_indexes) { // Sort and then erase in reverse so indexes are always valid - llvm::sort(remove_indexes.begin(), remove_indexes.end()); + llvm::sort(remove_indexes); for (size_t j = num_remove_indexes - 1; j < num_remove_indexes; ++j) { m_current_value.Remove(j); } diff --git a/lldb/source/Interpreter/OptionValuePathMappings.cpp b/lldb/source/Interpreter/OptionValuePathMappings.cpp index 543b0e1b8ea8..6096f4564629 100644 --- a/lldb/source/Interpreter/OptionValuePathMappings.cpp +++ b/lldb/source/Interpreter/OptionValuePathMappings.cpp @@ -174,7 +174,7 @@ Status OptionValuePathMappings::SetValueFromString(llvm::StringRef value, } // Sort and then erase in reverse so indexes are always valid - llvm::sort(remove_indexes.begin(), remove_indexes.end()); + llvm::sort(remove_indexes); for (auto index : llvm::reverse(remove_indexes)) m_path_mappings.Remove(index, m_notify_changes); NotifyValueChanged(); diff --git a/lldb/source/Plugins/ABI/X86/ABIX86.cpp b/lldb/source/Plugins/ABI/X86/ABIX86.cpp index 2cd653fe2c5e..ee568310d387 100644 --- a/lldb/source/Plugins/ABI/X86/ABIX86.cpp +++ b/lldb/source/Plugins/ABI/X86/ABIX86.cpp @@ -100,8 +100,8 @@ addCombinedRegisters(std::vector<DynamicRegisterInfo::Register> ®s, if (regdata1->subreg_name != regdata2->subreg_name) continue; - uint32_t base_index1 = regdata1->base_index.getValue(); - uint32_t base_index2 = regdata2->base_index.getValue(); + uint32_t base_index1 = regdata1->base_index.value(); + uint32_t base_index2 = regdata2->base_index.value(); if (regs[base_index1].byte_size != base_size || regs[base_index2].byte_size != base_size) continue; diff --git a/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp b/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp index a774d5b61cfe..fb404e985f80 100644 --- a/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp +++ b/lldb/source/Plugins/Disassembler/LLVMC/DisassemblerLLVMC.cpp @@ -1379,13 +1379,13 @@ const char *DisassemblerLLVMC::SymbolLookup(uint64_t value, uint64_t *type_ptr, // then this is a pc-relative address calculation. if (*type_ptr == LLVMDisassembler_ReferenceType_In_ARM64_ADDXri && m_adrp_insn && m_adrp_address == pc - 4 && - (m_adrp_insn.getValue() & 0x1f) == ((value >> 5) & 0x1f)) { + (m_adrp_insn.value() & 0x1f) == ((value >> 5) & 0x1f)) { uint32_t addxri_inst; uint64_t adrp_imm, addxri_imm; // Get immlo and immhi bits, OR them together to get the ADRP imm // value. - adrp_imm = ((m_adrp_insn.getValue() & 0x00ffffe0) >> 3) | - ((m_adrp_insn.getValue() >> 29) & 0x3); + adrp_imm = ((m_adrp_insn.value() & 0x00ffffe0) >> 3) | + ((m_adrp_insn.value() >> 29) & 0x3); // if high bit of immhi after right-shifting set, sign extend if (adrp_imm & (1ULL << 20)) adrp_imm |= ~((1ULL << 21) - 1); diff --git a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp index 5e2a866adb22..5dbbd209bd9b 100644 --- a/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp +++ b/lldb/source/Plugins/DynamicLoader/Hexagon-DYLD/HexagonDYLDRendezvous.cpp @@ -49,6 +49,10 @@ HexagonDYLDRendezvous::HexagonDYLDRendezvous(Process *process) : m_process(process), m_rendezvous_addr(LLDB_INVALID_ADDRESS), m_current(), m_previous(), m_soentries(), m_added_soentries(), m_removed_soentries() { m_thread_info.valid = false; + m_thread_info.dtv_offset = 0; + m_thread_info.dtv_slot_size = 0; + m_thread_info.modid_offset = 0; + m_thread_info.tls_offset = 0; // Cache a copy of the executable path if (m_process) { diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp index 7a1ac7870547..799ae29e2841 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ASTResultSynthesizer.cpp @@ -197,6 +197,27 @@ bool ASTResultSynthesizer::SynthesizeObjCMethodResult( return ret; } +/// Returns true if LLDB can take the address of the given lvalue for the sake +/// of capturing the expression result. Returns false if LLDB should instead +/// store the expression result in a result variable. +static bool CanTakeAddressOfLValue(const Expr *lvalue_expr) { + assert(lvalue_expr->getValueKind() == VK_LValue && + "lvalue_expr not a lvalue"); + + QualType qt = lvalue_expr->getType(); + // If the lvalue has const-qualified non-volatile integral or enum type, then + // the underlying value might come from a const static data member as + // described in C++11 [class.static.data]p3. If that's the case, then the + // value might not have an address if the user didn't also define the member + // in a namespace scope. Taking the address would cause that LLDB later fails + // to link the expression, so those lvalues should be stored in a result + // variable. + if (qt->isIntegralOrEnumerationType() && qt.isConstQualified() && + !qt.isVolatileQualified()) + return false; + return true; +} + bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, DeclContext *DC) { Log *log = GetLog(LLDBLog::Expressions); @@ -265,6 +286,10 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, // - During dematerialization, $0 is marked up as a load address with value // equal to the contents of the structure entry. // + // - Note: if we cannot take an address of the resulting Lvalue (e.g. it's + // a static const member without an out-of-class definition), then we + // follow the Rvalue route. + // // For Rvalues // // - In AST result synthesis the expression E is transformed into an @@ -304,7 +329,7 @@ bool ASTResultSynthesizer::SynthesizeBodyResult(CompoundStmt *Body, clang::VarDecl *result_decl = nullptr; - if (is_lvalue) { + if (is_lvalue && CanTakeAddressOfLValue(last_expr)) { IdentifierInfo *result_ptr_id; if (expr_type->isFunctionType()) diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp index 1bf29efb0bee..f8443d608ac3 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangASTSource.cpp @@ -1430,10 +1430,9 @@ static bool ImportOffsetMap(llvm::DenseMap<const D *, O> &destination_map, std::vector<PairType> sorted_items; sorted_items.reserve(source_map.size()); sorted_items.assign(source_map.begin(), source_map.end()); - llvm::sort(sorted_items.begin(), sorted_items.end(), - [](const PairType &lhs, const PairType &rhs) { - return lhs.second < rhs.second; - }); + llvm::sort(sorted_items, [](const PairType &lhs, const PairType &rhs) { + return lhs.second < rhs.second; + }); for (const auto &item : sorted_items) { DeclFromUser<D> user_decl(const_cast<D *>(item.first)); diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp index 4305a9982343..6ba03dad98d1 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.cpp @@ -9,10 +9,13 @@ #include "ClangExpressionDeclMap.h" #include "ClangASTSource.h" +#include "ClangExpressionUtil.h" +#include "ClangExpressionVariable.h" #include "ClangModulesDeclVendor.h" #include "ClangPersistentVariables.h" #include "ClangUtil.h" +#include "NameSearchContext.h" #include "Plugins/TypeSystem/Clang/TypeSystemClang.h" #include "lldb/Core/Address.h" #include "lldb/Core/Module.h" @@ -44,6 +47,7 @@ #include "lldb/Utility/Log.h" #include "lldb/Utility/RegisterValue.h" #include "lldb/Utility/Status.h" +#include "lldb/lldb-private-types.h" #include "lldb/lldb-private.h" #include "clang/AST/ASTConsumer.h" #include "clang/AST/ASTContext.h" @@ -62,6 +66,24 @@ using namespace clang; static const char *g_lldb_local_vars_namespace_cstr = "$__lldb_local_vars"; +namespace { +/// A lambda is represented by Clang as an artifical class whose +/// members are the lambda captures. If we capture a 'this' pointer, +/// the artifical class will contain a member variable named 'this'. +/// The function returns a ValueObject for the captured 'this' if such +/// member exists. If no 'this' was captured, return a nullptr. +lldb::ValueObjectSP GetCapturedThisValueObject(StackFrame *frame) { + assert(frame); + + if (auto thisValSP = frame->FindVariable(ConstString("this"))) + if (auto thisThisValSP = + thisValSP->GetChildMemberWithName(ConstString("this"), true)) + return thisThisValSP; + + return nullptr; +} +} // namespace + ClangExpressionDeclMap::ClangExpressionDeclMap( bool keep_result_in_memory, Materializer::PersistentVariableDelegate *result_delegate, @@ -394,6 +416,10 @@ bool ClangExpressionDeclMap::AddValueToStruct(const NamedDecl *decl, else if (parser_vars->m_lldb_var) offset = m_parser_vars->m_materializer->AddVariable( parser_vars->m_lldb_var, err); + else if (parser_vars->m_lldb_valobj_provider) { + offset = m_parser_vars->m_materializer->AddValueObject( + name, parser_vars->m_lldb_valobj_provider, err); + } } if (!err.Success()) @@ -795,6 +821,28 @@ void ClangExpressionDeclMap::LookUpLldbClass(NameSearchContext &context) { TypeSystemClang::DeclContextGetAsCXXMethodDecl(function_decl_ctx); if (method_decl) { + if (auto capturedThis = GetCapturedThisValueObject(frame)) { + // We're inside a lambda and we captured a 'this'. + // Import the outer class's AST instead of the + // (unnamed) lambda structure AST so unqualified + // member lookups are understood by the Clang parser. + // + // If we're in a lambda which didn't capture 'this', + // $__lldb_class will correspond to the lambda closure + // AST and references to captures will resolve like + // regular member varaiable accesses do. + TypeFromUser pointee_type = + capturedThis->GetCompilerType().GetPointeeType(); + + LLDB_LOG(log, + " CEDM::FEVD Adding captured type ({0} for" + " $__lldb_class: {1}", + capturedThis->GetTypeName(), capturedThis->GetName()); + + AddContextClassType(context, pointee_type); + return; + } + clang::CXXRecordDecl *class_decl = method_decl->getParent(); QualType class_qual_type(class_decl->getTypeForDecl(), 0); @@ -1053,6 +1101,30 @@ bool ClangExpressionDeclMap::LookupLocalVariable( context.m_found_variable = true; } } + + // We're in a local_var_lookup but haven't found any local variables + // so far. When performing a variable lookup from within the context of + // a lambda, we count the lambda captures as local variables. Thus, + // see if we captured any variables with the requested 'name'. + if (!variable_found) { + auto find_capture = [](ConstString varname, + StackFrame *frame) -> ValueObjectSP { + if (auto lambda = ClangExpressionUtil::GetLambdaValueObject(frame)) { + if (auto capture = lambda->GetChildMemberWithName(varname, true)) { + return capture; + } + } + + return nullptr; + }; + + if (auto capture = find_capture(name, frame)) { + variable_found = true; + context.m_found_variable = true; + AddOneVariable(context, std::move(capture), std::move(find_capture)); + } + } + return variable_found; } @@ -1493,25 +1565,15 @@ bool ClangExpressionDeclMap::GetVariableValue(VariableSP &var, return true; } -void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, - VariableSP var, - ValueObjectSP valobj) { - assert(m_parser_vars.get()); - - Log *log = GetLog(LLDBLog::Expressions); - - TypeFromUser ut; - TypeFromParser pt; - Value var_location; - - if (!GetVariableValue(var, var_location, &ut, &pt)) - return; - +ClangExpressionVariable::ParserVars * +ClangExpressionDeclMap::AddExpressionVariable(NameSearchContext &context, + TypeFromParser const &pt, + ValueObjectSP valobj) { clang::QualType parser_opaque_type = QualType::getFromOpaquePtr(pt.GetOpaqueQualType()); if (parser_opaque_type.isNull()) - return; + return nullptr; if (const clang::Type *parser_type = parser_opaque_type.getTypePtr()) { if (const TagType *tag_type = dyn_cast<TagType>(parser_type)) @@ -1538,16 +1600,89 @@ void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, entity->EnableParserVars(GetParserID()); ClangExpressionVariable::ParserVars *parser_vars = entity->GetParserVars(GetParserID()); + parser_vars->m_named_decl = var_decl; - parser_vars->m_llvm_value = nullptr; - parser_vars->m_lldb_value = var_location; - parser_vars->m_lldb_var = var; if (is_reference) entity->m_flags |= ClangExpressionVariable::EVTypeIsReference; + return parser_vars; +} + +void ClangExpressionDeclMap::AddOneVariable( + NameSearchContext &context, ValueObjectSP valobj, + ValueObjectProviderTy valobj_provider) { + assert(m_parser_vars.get()); + assert(valobj); + + Log *log = GetLog(LLDBLog::Expressions); + + Value var_location = valobj->GetValue(); + + TypeFromUser user_type = valobj->GetCompilerType(); + + TypeSystemClang *clang_ast = + llvm::dyn_cast_or_null<TypeSystemClang>(user_type.GetTypeSystem()); + + if (!clang_ast) { + LLDB_LOG(log, "Skipped a definition because it has no Clang AST"); + return; + } + + TypeFromParser parser_type = GuardedCopyType(user_type); + + if (!parser_type) { + LLDB_LOG(log, + "Couldn't copy a variable's type into the parser's AST context"); + + return; + } + + if (var_location.GetContextType() == Value::ContextType::Invalid) + var_location.SetCompilerType(parser_type); + + ClangExpressionVariable::ParserVars *parser_vars = + AddExpressionVariable(context, parser_type, valobj); + + if (!parser_vars) + return; + LLDB_LOG(log, " CEDM::FEVD Found variable {0}, returned\n{1} (original {2})", - decl_name, ClangUtil::DumpDecl(var_decl), ClangUtil::ToString(ut)); + context.m_decl_name, ClangUtil::DumpDecl(parser_vars->m_named_decl), + ClangUtil::ToString(user_type)); + + parser_vars->m_llvm_value = nullptr; + parser_vars->m_lldb_value = std::move(var_location); + parser_vars->m_lldb_valobj_provider = std::move(valobj_provider); +} + +void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, + VariableSP var, + ValueObjectSP valobj) { + assert(m_parser_vars.get()); + + Log *log = GetLog(LLDBLog::Expressions); + + TypeFromUser ut; + TypeFromParser pt; + Value var_location; + + if (!GetVariableValue(var, var_location, &ut, &pt)) + return; + + ClangExpressionVariable::ParserVars *parser_vars = + AddExpressionVariable(context, pt, std::move(valobj)); + + if (!parser_vars) + return; + + LLDB_LOG(log, " CEDM::FEVD Found variable {0}, returned\n{1} (original {2})", + context.m_decl_name, ClangUtil::DumpDecl(parser_vars->m_named_decl), + ClangUtil::ToString(ut)); + + parser_vars->m_llvm_value = nullptr; + parser_vars->m_lldb_value = var_location; + parser_vars->m_lldb_var = var; } void ClangExpressionDeclMap::AddOneVariable(NameSearchContext &context, diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h index f968f859cc72..bf7646ccaedf 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionDeclMap.h @@ -531,6 +531,23 @@ private: TypeFromParser *parser_type = nullptr); /// Use the NameSearchContext to generate a Decl for the given LLDB + /// ValueObject, and put it in the list of found entities. + /// + /// Helper function used by the other AddOneVariable APIs. + /// + /// \param[in,out] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// \param[in] pt + /// The CompilerType of the variable we're adding a Decl for. + /// + /// \param[in] var + /// The LLDB ValueObject that needs a Decl. + ClangExpressionVariable::ParserVars * + AddExpressionVariable(NameSearchContext &context, TypeFromParser const &pt, + lldb::ValueObjectSP valobj); + + /// Use the NameSearchContext to generate a Decl for the given LLDB /// Variable, and put it in the Tuple list. /// /// \param[in] context @@ -544,6 +561,20 @@ private: void AddOneVariable(NameSearchContext &context, lldb::VariableSP var, lldb::ValueObjectSP valobj); + /// Use the NameSearchContext to generate a Decl for the given ValueObject + /// and put it in the list of found entities. + /// + /// \param[in,out] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// \param[in] valobj + /// The ValueObject that needs a Decl. + /// + /// \param[in] valobj_provider Callback that fetches a ValueObjectSP + /// from the specified frame + void AddOneVariable(NameSearchContext &context, lldb::ValueObjectSP valobj, + ValueObjectProviderTy valobj_provider); + /// Use the NameSearchContext to generate a Decl for the given persistent /// variable, and put it in the list of found entities. /// diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp index 5168f637c443..56c00b35ba11 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.cpp @@ -8,6 +8,8 @@ #include "ClangExpressionSourceCode.h" +#include "ClangExpressionUtil.h" + #include "clang/Basic/CharInfo.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceManager.h" @@ -27,6 +29,7 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Utility/StreamString.h" +#include "lldb/lldb-forward.h" using namespace lldb_private; @@ -200,6 +203,34 @@ public: return m_tokens.find(token) != m_tokens.end(); } }; + +// If we're evaluating from inside a lambda that captures a 'this' pointer, +// add a "using" declaration to 'stream' for each capture used in the +// expression (tokenized by 'verifier'). +// +// If no 'this' capture exists, generate no using declarations. Instead +// capture lookups will get resolved by the same mechanism as class member +// variable lookup. That's because Clang generates an unnamed structure +// representing the lambda closure whose members are the captured variables. +void AddLambdaCaptureDecls(StreamString &stream, StackFrame *frame, + TokenVerifier const &verifier) { + assert(frame); + + if (auto thisValSP = ClangExpressionUtil::GetLambdaValueObject(frame)) { + uint32_t numChildren = thisValSP->GetNumChildren(); + for (uint32_t i = 0; i < numChildren; ++i) { + auto childVal = thisValSP->GetChildAtIndex(i, true); + ConstString childName(childVal ? childVal->GetName() : ConstString("")); + + if (!childName.IsEmpty() && verifier.hasToken(childName.GetStringRef()) && + childName != "this") { + stream.Printf("using $__lldb_local_vars::%s;\n", + childName.GetCString()); + } + } + } +} + } // namespace TokenVerifier::TokenVerifier(std::string body) { @@ -264,16 +295,24 @@ TokenVerifier::TokenVerifier(std::string body) { } } -void ClangExpressionSourceCode::AddLocalVariableDecls( - const lldb::VariableListSP &var_list_sp, StreamString &stream, - const std::string &expr) const { +void ClangExpressionSourceCode::AddLocalVariableDecls(StreamString &stream, + const std::string &expr, + StackFrame *frame) const { + assert(frame); TokenVerifier tokens(expr); + lldb::VariableListSP var_list_sp = frame->GetInScopeVariableList(false, true); + for (size_t i = 0; i < var_list_sp->GetSize(); i++) { lldb::VariableSP var_sp = var_list_sp->GetVariableAtIndex(i); ConstString var_name = var_sp->GetName(); + if (var_name == "this" && m_wrap_kind == WrapKind::CppMemberFunction) { + AddLambdaCaptureDecls(stream, frame, tokens); + + continue; + } // We can check for .block_descriptor w/o checking for langauge since this // is not a valid identifier in either C or C++. @@ -288,9 +327,6 @@ void ClangExpressionSourceCode::AddLocalVariableDecls( if ((var_name == "self" || var_name == "_cmd") && is_objc) continue; - if (var_name == "this" && m_wrap_kind == WrapKind::CppMemberFunction) - continue; - stream.Printf("using $__lldb_local_vars::%s;\n", var_name.AsCString()); } } @@ -376,10 +412,8 @@ bool ClangExpressionSourceCode::GetText( if (add_locals) if (target->GetInjectLocalVariables(&exe_ctx)) { - lldb::VariableListSP var_list_sp = - frame->GetInScopeVariableList(false, true); - AddLocalVariableDecls(var_list_sp, lldb_local_var_decls, - force_add_all_locals ? "" : m_body); + AddLocalVariableDecls(lldb_local_var_decls, + force_add_all_locals ? "" : m_body, frame); } } diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h index 54ae837fb30f..f721bb2f319e 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionSourceCode.h @@ -78,9 +78,19 @@ protected: Wrapping wrap, WrapKind wrap_kind); private: - void AddLocalVariableDecls(const lldb::VariableListSP &var_list_sp, - StreamString &stream, - const std::string &expr) const; + /// Writes "using" declarations for local variables into the specified stream. + /// + /// Behaviour is undefined if 'frame == nullptr'. + /// + /// \param[out] stream Stream that this function generates "using" + /// declarations into. + /// + /// \param[in] expr Expression source that we're evaluating. + /// + /// \param[in] frame StackFrame which carries information about the local + /// variables that we're generating "using" declarations for. + void AddLocalVariableDecls(StreamString &stream, const std::string &expr, + StackFrame *frame) const; /// String marking the start of the user expression. std::string m_start_marker; diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionUtil.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionUtil.cpp new file mode 100644 index 000000000000..9b490e1c036e --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionUtil.cpp @@ -0,0 +1,27 @@ +//===-- ClangExpressionUtil.cpp -------------------------------------------===// +// +// 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 "ClangExpressionUtil.h" + +#include "lldb/Core/ValueObject.h" +#include "lldb/Target/StackFrame.h" +#include "lldb/Utility/ConstString.h" + +namespace lldb_private { +namespace ClangExpressionUtil { +lldb::ValueObjectSP GetLambdaValueObject(StackFrame *frame) { + assert(frame); + + if (auto this_val_sp = frame->FindVariable(ConstString("this"))) + if (this_val_sp->GetChildMemberWithName(ConstString("this"), true)) + return this_val_sp; + + return nullptr; +} +} // namespace ClangExpressionUtil +} // namespace lldb_private diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionUtil.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionUtil.h new file mode 100644 index 000000000000..fb8b857256c0 --- /dev/null +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionUtil.h @@ -0,0 +1,30 @@ +//===-- ClangExpressionUtil.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 LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONUTIL_H +#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONUTIL_H + +#include "lldb/lldb-private.h" + +namespace lldb_private { +namespace ClangExpressionUtil { +/// Returns a ValueObject for the lambda class in the current frame +/// +/// To represent a lambda, Clang generates an artificial class +/// whose members are the captures and whose operator() is the +/// lambda implementation. If we capture a 'this' pointer, +/// the artifical class will contain a member variable named 'this'. +/// +/// This method returns the 'this' pointer to the artificial lambda +/// class if a real 'this' was captured. Otherwise, returns nullptr. +lldb::ValueObjectSP GetLambdaValueObject(StackFrame *frame); + +} // namespace ClangExpressionUtil +} // namespace lldb_private + +#endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONHELPER_H diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h index 7bb68e78373f..c7d9e05269fa 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangExpressionVariable.h @@ -116,7 +116,7 @@ public: /// The following values should not live beyond parsing class ParserVars { public: - ParserVars() : m_lldb_value(), m_lldb_var() {} + ParserVars() = default; const clang::NamedDecl *m_named_decl = nullptr; ///< The Decl corresponding to this variable @@ -129,6 +129,12 @@ public: const lldb_private::Symbol *m_lldb_sym = nullptr; ///< The original symbol for this /// variable, if it was a symbol + + /// Callback that provides a ValueObject for the + /// specified frame. Used by the materializer for + /// re-fetching ValueObjects when materializing + /// ivars. + ValueObjectProviderTy m_lldb_valobj_provider; }; private: diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp index 78b8bf11220a..7145e7804e68 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -872,6 +872,34 @@ bool ClangUserExpression::Complete(ExecutionContext &exe_ctx, return true; } +lldb::addr_t ClangUserExpression::GetCppObjectPointer( + lldb::StackFrameSP frame_sp, ConstString &object_name, Status &err) { + auto valobj_sp = + GetObjectPointerValueObject(std::move(frame_sp), object_name, err); + + // We're inside a C++ class method. This could potentially be an unnamed + // lambda structure. If the lambda captured a "this", that should be + // the object pointer. + if (auto thisChildSP = + valobj_sp->GetChildMemberWithName(ConstString("this"), true)) { + valobj_sp = thisChildSP; + } + + if (!err.Success() || !valobj_sp.get()) + return LLDB_INVALID_ADDRESS; + + lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + + if (ret == LLDB_INVALID_ADDRESS) { + err.SetErrorStringWithFormat( + "Couldn't load '%s' because its value couldn't be evaluated", + object_name.AsCString()); + return LLDB_INVALID_ADDRESS; + } + + return ret; +} + bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx, std::vector<lldb::addr_t> &args, lldb::addr_t struct_address, @@ -906,8 +934,14 @@ bool ClangUserExpression::AddArguments(ExecutionContext &exe_ctx, address_type != eAddressTypeLoad) object_ptr_error.SetErrorString("Can't get context object's " "debuggee address"); - } else - object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error); + } else { + if (m_in_cplusplus_method) { + object_ptr = + GetCppObjectPointer(frame_sp, object_name, object_ptr_error); + } else { + object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error); + } + } if (!object_ptr_error.Success()) { exe_ctx.GetTargetRef().GetDebugger().GetAsyncOutputStream()->Printf( diff --git a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h index 30cdd2f3e990..4d5458f1807d 100644 --- a/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ b/lldb/source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -198,6 +198,10 @@ private: ExecutionContext &exe_ctx, std::vector<std::string> modules_to_import, bool for_completion); + + lldb::addr_t GetCppObjectPointer(lldb::StackFrameSP frame, + ConstString &object_name, Status &err); + /// Defines how the current expression should be wrapped. ClangExpressionSourceCode::WrapKind GetWrapKind() const; bool SetupPersistentState(DiagnosticManager &diagnostic_manager, diff --git a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h index 8b167dd347ad..c877724a9d30 100644 --- a/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h +++ b/lldb/source/Plugins/Instruction/ARM/EmulateInstructionARM.h @@ -91,7 +91,8 @@ public: EmulateInstructionARM(const ArchSpec &arch) : EmulateInstruction(arch), m_arm_isa(0), m_opcode_mode(eModeInvalid), - m_opcode_cpsr(0), m_it_session(), m_ignore_conditions(false) { + m_opcode_cpsr(0), m_new_inst_cpsr(0), m_it_session(), + m_ignore_conditions(false) { SetArchitecture(arch); } diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp index 89bee3e000c0..23ce1654fb83 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.cpp @@ -218,10 +218,10 @@ void CPlusPlusLanguage::MethodName::Parse() { } else { CPlusPlusNameParser parser(m_full.GetStringRef()); if (auto function = parser.ParseAsFunctionDefinition()) { - m_basename = function.getValue().name.basename; - m_context = function.getValue().name.context; - m_arguments = function.getValue().arguments; - m_qualifiers = function.getValue().qualifiers; + m_basename = function.value().name.basename; + m_context = function.value().name.context; + m_arguments = function.value().arguments; + m_qualifiers = function.value().qualifiers; m_parse_error = false; } else { m_parse_error = true; @@ -329,8 +329,8 @@ bool CPlusPlusLanguage::ExtractContextAndIdentifier( CPlusPlusNameParser parser(name); if (auto full_name = parser.ParseAsFullName()) { - identifier = full_name.getValue().basename; - context = full_name.getValue().context; + identifier = full_name.value().basename; + context = full_name.value().context; return true; } return false; @@ -409,12 +409,12 @@ protected: private: /// Input character until which we have constructed the respective output /// already. - const char *Written; + const char *Written = ""; llvm::SmallString<128> Result; /// Whether we have performed any substitutions. - bool Substituted; + bool Substituted = false; const char *currentParserPos() const { return this->First; } @@ -909,7 +909,7 @@ static void LoadLibCxxFormatters(lldb::TypeCategoryImplSP cpp_category_sp) { cpp_category_sp, lldb_private::formatters::LibCxxMapIteratorSyntheticFrontEndCreator, "std::map iterator synthetic children", - ConstString("^std::__[[:alnum:]]+::__map_iterator<.+>$"), stl_synth_flags, + ConstString("^std::__[[:alnum:]]+::__map_(const_)?iterator<.+>$"), stl_synth_flags, true); AddCXXSynthetic( diff --git a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp index eca36fff18f8..a9a4e98775d9 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/CPlusPlusNameParser.cpp @@ -55,8 +55,8 @@ Optional<ParsedName> CPlusPlusNameParser::ParseAsFullName() { if (HasMoreTokens()) return None; ParsedName result; - result.basename = GetTextForRange(name_ranges.getValue().basename_range); - result.context = GetTextForRange(name_ranges.getValue().context_range); + result.basename = GetTextForRange(name_ranges.value().basename_range); + result.context = GetTextForRange(name_ranges.value().context_range); return result; } @@ -125,8 +125,8 @@ CPlusPlusNameParser::ParseFunctionImpl(bool expect_return_type) { size_t end_position = GetCurrentPosition(); ParsedFunction result; - result.name.basename = GetTextForRange(maybe_name.getValue().basename_range); - result.name.context = GetTextForRange(maybe_name.getValue().context_range); + result.name.basename = GetTextForRange(maybe_name.value().basename_range); + result.name.context = GetTextForRange(maybe_name.value().context_range); result.arguments = GetTextForRange(Range(argument_start, qualifiers_start)); result.qualifiers = GetTextForRange(Range(qualifiers_start, end_position)); start_position.Remove(); @@ -617,9 +617,9 @@ CPlusPlusNameParser::ParseFullNameImpl() { ParsedNameRanges result; if (last_coloncolon_position) { result.context_range = Range(start_position.GetSavedPosition(), - last_coloncolon_position.getValue()); + last_coloncolon_position.value()); result.basename_range = - Range(last_coloncolon_position.getValue() + 1, GetCurrentPosition()); + Range(last_coloncolon_position.value() + 1, GetCurrentPosition()); } else { result.basename_range = Range(start_position.GetSavedPosition(), GetCurrentPosition()); diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp index 9f5624de4e63..a1953a1c7a22 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxList.cpp @@ -119,16 +119,16 @@ protected: AbstractListFrontEnd(ValueObject &valobj) : SyntheticChildrenFrontEnd(valobj) {} - size_t m_count; - ValueObject *m_head; + size_t m_count = 0; + ValueObject *m_head = nullptr; static constexpr bool g_use_loop_detect = true; - size_t m_loop_detected; // The number of elements that have had loop detection - // run over them. + size_t m_loop_detected = 0; // The number of elements that have had loop + // detection run over them. ListEntry m_slow_runner; // Used for loop detection ListEntry m_fast_runner; // Used for loop detection - size_t m_list_capping_size; + size_t m_list_capping_size = 0; CompilerType m_element_type; std::map<size_t, ListIterator> m_iterators; diff --git a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp index 4aae524e3701..ca6f92d003ad 100644 --- a/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp +++ b/lldb/source/Plugins/Language/CPlusPlus/LibCxxMap.cpp @@ -165,8 +165,8 @@ private: } MapEntry m_entry; - size_t m_max_depth; - bool m_error; + size_t m_max_depth = 0; + bool m_error = false; }; namespace lldb_private { diff --git a/lldb/source/Plugins/Language/ObjC/CFBasicHash.h b/lldb/source/Plugins/Language/ObjC/CFBasicHash.h index fd30f5f7845f..f850c50342a3 100644 --- a/lldb/source/Plugins/Language/ObjC/CFBasicHash.h +++ b/lldb/source/Plugins/Language/ObjC/CFBasicHash.h @@ -68,7 +68,7 @@ private: ExecutionContextRef m_exe_ctx_ref; bool m_mutable = true; bool m_multi = false; - HashType m_type; + HashType m_type = HashType::set; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp index 2c6998451ad6..e5e62b534560 100644 --- a/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp +++ b/lldb/source/Plugins/Language/ObjC/NSDictionary.cpp @@ -137,7 +137,7 @@ private: lldb::ByteOrder m_order = lldb::eByteOrderInvalid; DataDescriptor_32 *m_data_32 = nullptr; DataDescriptor_64 *m_data_64 = nullptr; - lldb::addr_t m_data_ptr; + lldb::addr_t m_data_ptr = LLDB_INVALID_ADDRESS; CompilerType m_pair_type; std::vector<DictionaryItemDescriptor> m_children; }; diff --git a/lldb/source/Plugins/Language/ObjC/NSError.cpp b/lldb/source/Plugins/Language/ObjC/NSError.cpp index 937c7204d3c4..4f237824c4b0 100644 --- a/lldb/source/Plugins/Language/ObjC/NSError.cpp +++ b/lldb/source/Plugins/Language/ObjC/NSError.cpp @@ -177,7 +177,7 @@ private: // values to leak if the latter, then I need to store a SharedPointer to it - // so that it only goes away when everyone else in the cluster goes away oh // joy! - ValueObject *m_child_ptr; + ValueObject *m_child_ptr = nullptr; ValueObjectSP m_child_sp; }; diff --git a/lldb/source/Plugins/Language/ObjC/NSSet.cpp b/lldb/source/Plugins/Language/ObjC/NSSet.cpp index 0a6b445d97c8..b5c8e849abcc 100644 --- a/lldb/source/Plugins/Language/ObjC/NSSet.cpp +++ b/lldb/source/Plugins/Language/ObjC/NSSet.cpp @@ -76,7 +76,7 @@ private: uint8_t m_ptr_size = 8; DataDescriptor_32 *m_data_32 = nullptr; DataDescriptor_64 *m_data_64 = nullptr; - lldb::addr_t m_data_ptr; + lldb::addr_t m_data_ptr = LLDB_INVALID_ADDRESS; std::vector<SetItemDescriptor> m_children; }; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h index 7ba957940ae7..0c6eccab9f27 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.h @@ -347,12 +347,12 @@ public: private: ConstString m_name; - uint8_t m_pointer_size; - bool m_valid; - uint64_t m_info_bits; - uint64_t m_value_bits; - int64_t m_value_bits_signed; - uint64_t m_payload; + uint8_t m_pointer_size = 0; + bool m_valid = false; + uint64_t m_info_bits = 0; + uint64_t m_value_bits = 0; + int64_t m_value_bits_signed = 0; + uint64_t m_payload = 0; }; } // namespace lldb_private diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp index f9ccaf0115a2..18e1d12ef980 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -578,7 +578,8 @@ AppleObjCTrampolineHandler::AppleObjCTrampolineHandler( : m_process_wp(), m_objc_module_sp(objc_module_sp), m_impl_fn_addr(LLDB_INVALID_ADDRESS), m_impl_stret_fn_addr(LLDB_INVALID_ADDRESS), - m_msg_forward_addr(LLDB_INVALID_ADDRESS) { + m_msg_forward_addr(LLDB_INVALID_ADDRESS), + m_msg_forward_stret_addr(LLDB_INVALID_ADDRESS) { if (process_sp) m_process_wp = process_sp; // Look up the known resolution functions: @@ -780,10 +781,8 @@ AppleObjCTrampolineHandler::FindDispatchFunction(lldb::addr_t addr) { return nullptr; } -void -AppleObjCTrampolineHandler::ForEachDispatchFunction( - std::function<void(lldb::addr_t, - const DispatchFunction &)> callback) { +void AppleObjCTrampolineHandler::ForEachDispatchFunction( + std::function<void(lldb::addr_t, const DispatchFunction &)> callback) { for (auto elem : m_msgSend_map) { callback(elem.first, g_dispatch_functions[elem.second]); } diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp index bc8e43764af6..0c032f8a7c88 100644 --- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.cpp @@ -4163,7 +4163,7 @@ public: int m_kernel_types = RSReduceBreakpointResolver::eKernelTypeAll; llvm::StringRef m_reduce_name; RSCoordinate m_coord; - bool m_have_coord; + bool m_have_coord = false; }; Options *GetOptions() override { return &m_options; } @@ -4268,7 +4268,7 @@ public: } RSCoordinate m_coord; - bool m_have_coord; + bool m_have_coord = false; }; bool DoExecute(Args &command, CommandReturnObject &result) override { diff --git a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h index 4ddf996dedb2..bc460706fd29 100644 --- a/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/RenderScript/RenderScriptRuntime/RenderScriptRuntime.h @@ -171,7 +171,8 @@ struct RSReductionDescriptor { llvm::StringRef halter_name = ".") : m_module(module), m_reduce_name(name), m_init_name(init_name), m_accum_name(accum_name), m_comb_name(comb_name), - m_outc_name(outc_name), m_halter_name(halter_name) { + m_outc_name(outc_name), m_halter_name(halter_name), m_accum_sig(0), + m_accum_data_size(0), m_comb_name_generated(false) { // TODO Check whether the combiner is an autogenerated name, and track // this } diff --git a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp index f9fb36890d5a..122298d87bf8 100644 --- a/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp +++ b/lldb/source/Plugins/ObjectFile/ELF/ObjectFileELF.cpp @@ -1607,7 +1607,7 @@ lldb::user_id_t ObjectFileELF::GetSectionIndexByName(const char *name) { } static SectionType GetSectionTypeFromName(llvm::StringRef Name) { - if (Name.consume_front(".debug_") || Name.consume_front(".zdebug_")) { + if (Name.consume_front(".debug_")) { return llvm::StringSwitch<SectionType>(Name) .Case("abbrev", eSectionTypeDWARFDebugAbbrev) .Case("abbrev.dwo", eSectionTypeDWARFDebugAbbrevDwo) @@ -3365,8 +3365,7 @@ size_t ObjectFileELF::ReadSectionData(Section *section, return section->GetObjectFile()->ReadSectionData(section, section_data); size_t result = ObjectFile::ReadSectionData(section, section_data); - if (result == 0 || !llvm::object::Decompressor::isCompressedELFSection( - section->Get(), section->GetName().GetStringRef())) + if (result == 0 || !(section->Get() & llvm::ELF::SHF_COMPRESSED)) return result; auto Decompressor = llvm::object::Decompressor::create( diff --git a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp index 516bcb21b019..acb131b8a775 100644 --- a/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp +++ b/lldb/source/Plugins/ObjectFile/Minidump/MinidumpFileBuilder.cpp @@ -349,6 +349,7 @@ llvm::support::ulittle64_t read_register_u64(RegisterContext *reg_ctx, lldb_private::minidump::MinidumpContext_x86_64 GetThreadContext_64(RegisterContext *reg_ctx) { lldb_private::minidump::MinidumpContext_x86_64 thread_context; + thread_context.p1_home = {}; thread_context.context_flags = static_cast<uint32_t>( lldb_private::minidump::MinidumpContext_x86_64_Flags::x86_64_Flag | lldb_private::minidump::MinidumpContext_x86_64_Flags::Control | diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp index 67e03ff1ea39..40f70e8a0a75 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_x86.cpp @@ -444,6 +444,7 @@ RegisterContextPOSIX_x86::RegisterContextPOSIX_x86( } ::memset(&m_fpr, 0, sizeof(FPR)); + ::memset(&m_ymm_set, 0, sizeof(YMM)); m_fpr_type = eNotValid; } diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp index 579ac6e36d0b..4db7abe603d4 100644 --- a/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp +++ b/lldb/source/Plugins/Process/Utility/RegisterInfoPOSIX_arm64.cpp @@ -396,15 +396,11 @@ bool RegisterInfoPOSIX_arm64::IsSVERegVG(unsigned reg) const { } bool RegisterInfoPOSIX_arm64::IsPAuthReg(unsigned reg) const { - return std::find(pauth_regnum_collection.begin(), - pauth_regnum_collection.end(), - reg) != pauth_regnum_collection.end(); + return llvm::is_contained(pauth_regnum_collection, reg); } bool RegisterInfoPOSIX_arm64::IsMTEReg(unsigned reg) const { - return std::find(m_mte_regnum_collection.begin(), - m_mte_regnum_collection.end(), - reg) != m_mte_regnum_collection.end(); + return llvm::is_contained(m_mte_regnum_collection, reg); } uint32_t RegisterInfoPOSIX_arm64::GetRegNumSVEZ0() const { return sve_z0; } diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index e5461c1899ec..755b8220c49e 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -67,8 +67,8 @@ GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, m_packet_timeout(1), #endif m_echo_number(0), m_supports_qEcho(eLazyBoolCalculate), m_history(512), - m_send_acks(true), m_compression_type(CompressionType::None), - m_listen_url() { + m_send_acks(true), m_is_platform(false), + m_compression_type(CompressionType::None), m_listen_url() { } // Destructor @@ -1266,7 +1266,7 @@ GDBRemoteCommunication::ConnectLocally(GDBRemoteCommunication &client, GDBRemoteCommunication::ScopedTimeout::ScopedTimeout( GDBRemoteCommunication &gdb_comm, std::chrono::seconds timeout) - : m_gdb_comm(gdb_comm), m_timeout_modified(false) { + : m_gdb_comm(gdb_comm), m_saved_timeout(0), m_timeout_modified(false) { auto curr_timeout = gdb_comm.GetPacketTimeout(); // Only update the timeout if the timeout is greater than the current // timeout. If the current timeout is larger, then just use that. diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 63174ef55219..5804c13fe7b6 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -246,6 +246,9 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { StringExtractorGDBRemote::eServerPacketType_QNonStop, &GDBRemoteCommunicationServerLLGS::Handle_QNonStop); RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_vStdio, + &GDBRemoteCommunicationServerLLGS::Handle_vStdio); + RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_vStopped, &GDBRemoteCommunicationServerLLGS::Handle_vStopped); RegisterMemberFunctionHandler( @@ -290,7 +293,9 @@ Status GDBRemoteCommunicationServerLLGS::LaunchProcess() { if (!process_or) return Status(process_or.takeError()); m_continue_process = m_current_process = process_or->get(); - m_debugged_processes[m_current_process->GetID()] = std::move(*process_or); + m_debugged_processes.emplace( + m_current_process->GetID(), + DebuggedProcess{std::move(*process_or), DebuggedProcess::Flag{}}); } SetEnabledExtensions(*m_current_process); @@ -361,7 +366,9 @@ Status GDBRemoteCommunicationServerLLGS::AttachToProcess(lldb::pid_t pid) { return status; } m_continue_process = m_current_process = process_or->get(); - m_debugged_processes[m_current_process->GetID()] = std::move(*process_or); + m_debugged_processes.emplace( + m_current_process->GetID(), + DebuggedProcess{std::move(*process_or), DebuggedProcess::Flag{}}); SetEnabledExtensions(*m_current_process); // Setup stdout/stderr mapping from inferior. @@ -489,12 +496,14 @@ GDBRemoteCommunicationServerLLGS::SendWResponse( *wait_status); // If the process was killed through vKill, return "OK". - if (m_vkilled_processes.find(process->GetID()) != m_vkilled_processes.end()) + if (bool(m_debugged_processes.at(process->GetID()).flags & + DebuggedProcess::Flag::vkilled)) return SendOKResponse(); StreamGDBRemote response; response.Format("{0:g}", *wait_status); - if (bool(m_extensions_supported & NativeProcessProtocol::Extension::multiprocess)) + if (bool(m_extensions_supported & + NativeProcessProtocol::Extension::multiprocess)) response.Format(";process:{0:x-}", process->GetID()); if (m_non_stop) return SendNotificationPacketNoLock("Stop", m_stop_notification_queue, @@ -1016,9 +1025,11 @@ void GDBRemoteCommunicationServerLLGS::EnqueueStopReplyPackets( return; for (NativeThreadProtocol &listed_thread : m_current_process->Threads()) { - if (listed_thread.GetID() != thread_to_skip) - m_stop_notification_queue.push_back( - PrepareStopReplyPacketForThread(listed_thread).GetString().str()); + if (listed_thread.GetID() != thread_to_skip) { + StreamString stop_reply = PrepareStopReplyPacketForThread(listed_thread); + if (!stop_reply.Empty()) + m_stop_notification_queue.push_back(stop_reply.GetString().str()); + } } } @@ -1045,14 +1056,14 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Exited( lldb::pid_t pid = process->GetID(); m_mainloop.AddPendingCallback([this, pid](MainLoopBase &loop) { - m_debugged_processes.erase(pid); - auto vkill_it = m_vkilled_processes.find(pid); - if (vkill_it != m_vkilled_processes.end()) - m_vkilled_processes.erase(vkill_it); + auto find_it = m_debugged_processes.find(pid); + assert(find_it != m_debugged_processes.end()); + bool vkilled = bool(find_it->second.flags & DebuggedProcess::Flag::vkilled); + m_debugged_processes.erase(find_it); // Terminate the main loop only if vKill has not been used. // When running in non-stop mode, wait for the vStopped to clear // the notification queue. - else if (m_debugged_processes.empty() && !m_non_stop) { + if (m_debugged_processes.empty() && !m_non_stop && !vkilled) { // Close the pipe to the inferior terminal i/o if we launched it and set // one up. MaybeCloseInferiorTerminalConnection(); @@ -1071,23 +1082,13 @@ void GDBRemoteCommunicationServerLLGS::HandleInferiorState_Stopped( Log *log = GetLog(LLDBLog::Process); LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); - // Send the stop reason unless this is the stop after the launch or attach. - switch (m_inferior_prev_state) { - case eStateLaunching: - case eStateAttaching: - // Don't send anything per debugserver behavior. - break; - default: - // In all other cases, send the stop reason. - PacketResult result = SendStopReasonForState( - *process, StateType::eStateStopped, /*force_synchronous=*/false); - if (result != PacketResult::Success) { - LLDB_LOGF(log, - "GDBRemoteCommunicationServerLLGS::%s failed to send stop " - "notification for PID %" PRIu64 ", state: eStateExited", - __FUNCTION__, process->GetID()); - } - break; + PacketResult result = SendStopReasonForState( + *process, StateType::eStateStopped, /*force_synchronous=*/false); + if (result != PacketResult::Success) { + LLDB_LOGF(log, + "GDBRemoteCommunicationServerLLGS::%s failed to send stop " + "notification for PID %" PRIu64 ", state: eStateExited", + __FUNCTION__, process->GetID()); } } @@ -1112,14 +1113,16 @@ void GDBRemoteCommunicationServerLLGS::ProcessStateChanged( SendProcessOutput(); // Then stop the forwarding, so that any late output (see llvm.org/pr25652) // does not interfere with our protocol. - StopSTDIOForwarding(); + if (!m_non_stop) + StopSTDIOForwarding(); HandleInferiorState_Stopped(process); break; case StateType::eStateExited: // Same as above SendProcessOutput(); - StopSTDIOForwarding(); + if (!m_non_stop) + StopSTDIOForwarding(); HandleInferiorState_Exited(process); break; @@ -1132,9 +1135,6 @@ void GDBRemoteCommunicationServerLLGS::ProcessStateChanged( } break; } - - // Remember the previous state reported to us. - m_inferior_prev_state = state; } void GDBRemoteCommunicationServerLLGS::DidExec(NativeProcessProtocol *process) { @@ -1147,7 +1147,9 @@ void GDBRemoteCommunicationServerLLGS::NewSubprocess( lldb::pid_t child_pid = child_process->GetID(); assert(child_pid != LLDB_INVALID_PROCESS_ID); assert(m_debugged_processes.find(child_pid) == m_debugged_processes.end()); - m_debugged_processes[child_pid] = std::move(child_process); + m_debugged_processes.emplace( + child_pid, + DebuggedProcess{std::move(child_process), DebuggedProcess::Flag{}}); } void GDBRemoteCommunicationServerLLGS::DataAvailableCallback() { @@ -1197,6 +1199,9 @@ GDBRemoteCommunicationServerLLGS::SendONotification(const char *buffer, response.PutChar('O'); response.PutBytesAsRawHex8(buffer, len); + if (m_non_stop) + return SendNotificationPacketNoLock("Stdio", m_stdio_notification_queue, + response.GetString()); return SendPacketNoLock(response.GetString()); } @@ -1422,7 +1427,8 @@ GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) { Log *log = GetLog(LLDBLog::Process); - StopSTDIOForwarding(); + if (!m_non_stop) + StopSTDIOForwarding(); if (m_debugged_processes.empty()) { LLDB_LOG(log, "No debugged process found."); @@ -1432,7 +1438,7 @@ GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) { for (auto it = m_debugged_processes.begin(); it != m_debugged_processes.end(); ++it) { LLDB_LOG(log, "Killing process {0}", it->first); - Status error = it->second->Kill(); + Status error = it->second.process_up->Kill(); if (error.Fail()) LLDB_LOG(log, "Failed to kill debugged process {0}: {1}", it->first, error); @@ -1448,7 +1454,8 @@ GDBRemoteCommunicationServerLLGS::Handle_k(StringExtractorGDBRemote &packet) { GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_vKill( StringExtractorGDBRemote &packet) { - StopSTDIOForwarding(); + if (!m_non_stop) + StopSTDIOForwarding(); packet.SetFilePos(6); // vKill; uint32_t pid = packet.GetU32(LLDB_INVALID_PROCESS_ID, 16); @@ -1460,12 +1467,12 @@ GDBRemoteCommunicationServerLLGS::Handle_vKill( if (it == m_debugged_processes.end()) return SendErrorResponse(42); - Status error = it->second->Kill(); + Status error = it->second.process_up->Kill(); if (error.Fail()) return SendErrorResponse(error.ToError()); // OK response is sent when the process dies. - m_vkilled_processes.insert(pid); + it->second.flags |= DebuggedProcess::Flag::vkilled; return PacketResult::Success; } @@ -1518,6 +1525,30 @@ GDBRemoteCommunicationServerLLGS::Handle_QListThreadsInStopReply( } GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::ResumeProcess( + NativeProcessProtocol &process, const ResumeActionList &actions) { + Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); + + // In non-stop protocol mode, the process could be running already. + // We do not support resuming threads independently, so just error out. + if (!process.CanResume()) { + LLDB_LOG(log, "process {0} cannot be resumed (state={1})", process.GetID(), + process.GetState()); + return SendErrorResponse(0x37); + } + + Status error = process.Resume(actions); + if (error.Fail()) { + LLDB_LOG(log, "process {0} failed to resume: {1}", process.GetID(), error); + return SendErrorResponse(GDBRemoteServerError::eErrorResume); + } + + LLDB_LOG(log, "process {0} resumed", process.GetID()); + + return PacketResult::Success; +} + +GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { Log *log = GetLog(LLDBLog::Process | LLDBLog::Thread); LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s called", __FUNCTION__); @@ -1552,6 +1583,14 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { packet, "unexpected content after $C{signal-number}"); } + // In non-stop protocol mode, the process could be running already. + // We do not support resuming threads independently, so just error out. + if (!m_continue_process->CanResume()) { + LLDB_LOG(log, "process cannot be resumed (state={0})", + m_continue_process->GetState()); + return SendErrorResponse(0x37); + } + ResumeActionList resume_actions(StateType::eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); Status error; @@ -1585,14 +1624,11 @@ GDBRemoteCommunicationServerLLGS::Handle_C(StringExtractorGDBRemote &packet) { } } - // Resume the threads. - error = m_continue_process->Resume(resume_actions); - if (error.Fail()) { - LLDB_LOG(log, "failed to resume threads for process {0}: {1}", - m_continue_process->GetID(), error); - - return SendErrorResponse(0x38); - } + // NB: this checks CanResume() twice but using a single code path for + // resuming still seems worth it. + PacketResult resume_res = ResumeProcess(*m_continue_process, resume_actions); + if (resume_res != PacketResult::Success) + return resume_res; // Don't send an "OK" packet, except in non-stop mode; // otherwise, the response is the stopped/exited message. @@ -1627,14 +1663,9 @@ GDBRemoteCommunicationServerLLGS::Handle_c(StringExtractorGDBRemote &packet) { ResumeActionList actions(StateType::eStateRunning, LLDB_INVALID_SIGNAL_NUMBER); - Status error = m_continue_process->Resume(actions); - if (error.Fail()) { - LLDB_LOG(log, "c failed for process {0}: {1}", m_continue_process->GetID(), - error); - return SendErrorResponse(GDBRemoteServerError::eErrorResume); - } - - LLDB_LOG(log, "continued process {0}", m_continue_process->GetID()); + PacketResult resume_res = ResumeProcess(*m_continue_process, actions); + if (resume_res != PacketResult::Success) + return resume_res; return SendContinueSuccessResponse(); } @@ -1648,6 +1679,18 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont_actions( return SendPacketNoLock(response.GetString()); } +static bool ResumeActionListStopsAllThreads(ResumeActionList &actions) { + // We're doing a stop-all if and only if our only action is a "t" for all + // threads. + if (const ResumeAction *default_action = + actions.GetActionForThread(LLDB_INVALID_THREAD_ID, false)) { + if (default_action->state == eStateSuspended && actions.GetSize() == 1) + return true; + } + + return false; +} + GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_vCont( StringExtractorGDBRemote &packet) { @@ -1669,9 +1712,6 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( // Move past the ';', then do a simple 's'. packet.SetFilePos(packet.GetFilePos() + 1); return Handle_s(packet); - } else if (m_non_stop && ::strcmp(packet.Peek(), ";t") == 0) { - // TODO: add full support for "t" action - return SendOKResponse(); } std::unordered_map<lldb::pid_t, ResumeActionList> thread_actions; @@ -1738,6 +1778,12 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( tid = pid_tid->second; } + if (thread_action.state == eStateSuspended && + tid != StringExtractorGDBRemote::AllThreads) { + return SendIllFormedResponse( + packet, "'t' action not supported for individual threads"); + } + if (pid == StringExtractorGDBRemote::AllProcesses) { if (m_debugged_processes.size() > 1) return SendIllFormedResponse( @@ -1770,13 +1816,43 @@ GDBRemoteCommunicationServerLLGS::Handle_vCont( return SendErrorResponse(GDBRemoteServerError::eErrorResume); } - Status error = process_it->second->Resume(x.second); - if (error.Fail()) { - LLDB_LOG(log, "vCont failed for process {0}: {1}", x.first, error); - return SendErrorResponse(GDBRemoteServerError::eErrorResume); - } + // There are four possible scenarios here. These are: + // 1. vCont on a stopped process that resumes at least one thread. + // In this case, we call Resume(). + // 2. vCont on a stopped process that leaves all threads suspended. + // A no-op. + // 3. vCont on a running process that requests suspending all + // running threads. In this case, we call Interrupt(). + // 4. vCont on a running process that requests suspending a subset + // of running threads or resuming a subset of suspended threads. + // Since we do not support full nonstop mode, this is unsupported + // and we return an error. + + assert(process_it->second.process_up); + if (ResumeActionListStopsAllThreads(x.second)) { + if (process_it->second.process_up->IsRunning()) { + assert(m_non_stop); + + Status error = process_it->second.process_up->Interrupt(); + if (error.Fail()) { + LLDB_LOG(log, "vCont failed to halt process {0}: {1}", x.first, + error); + return SendErrorResponse(GDBRemoteServerError::eErrorResume); + } + + LLDB_LOG(log, "halted process {0}", x.first); - LLDB_LOG(log, "continued process {0}", x.first); + // hack to avoid enabling stdio forwarding after stop + // TODO: remove this when we improve stdio forwarding for nonstop + assert(thread_actions.size() == 1); + return SendOKResponse(); + } + } else { + PacketResult resume_res = + ResumeProcess(*process_it->second.process_up, x.second); + if (resume_res != PacketResult::Success) + return resume_res; + } } return SendContinueSuccessResponse(); @@ -1815,9 +1891,11 @@ GDBRemoteCommunicationServerLLGS::Handle_stop_reason( // the current thread (for clients that don't actually support multiple // stop reasons). NativeThreadProtocol *thread = m_current_process->GetCurrentThread(); - if (thread) - m_stop_notification_queue.push_back( - PrepareStopReplyPacketForThread(*thread).GetString().str()); + if (thread) { + StreamString stop_reply = PrepareStopReplyPacketForThread(*thread); + if (!stop_reply.Empty()) + m_stop_notification_queue.push_back(stop_reply.GetString().str()); + } EnqueueStopReplyPackets(thread ? thread->GetID() : LLDB_INVALID_THREAD_ID); } @@ -1845,6 +1923,20 @@ GDBRemoteCommunicationServerLLGS::SendStopReasonForState( bool force_synchronous) { Log *log = GetLog(LLDBLog::Process); + if (m_disabling_non_stop) { + // Check if we are waiting for any more processes to stop. If we are, + // do not send the OK response yet. + for (const auto &it : m_debugged_processes) { + if (it.second.process_up->IsRunning()) + return PacketResult::Success; + } + + // If all expected processes were stopped after a QNonStop:0 request, + // send the OK response. + m_disabling_non_stop = false; + return SendOKResponse(); + } + switch (process_state) { case eStateAttaching: case eStateLaunching: @@ -1998,7 +2090,7 @@ GDBRemoteCommunicationServerLLGS::Handle_qfThreadInfo( StreamGDBRemote response; for (auto &pid_ptr : m_debugged_processes) - AddProcessThreads(response, *pid_ptr.second, had_any); + AddProcessThreads(response, *pid_ptr.second.process_up, had_any); if (!had_any) return SendOKResponse(); @@ -2284,7 +2376,8 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { // Ensure we have the given thread when not specifying -1 (all threads) or 0 // (any thread). if (tid != LLDB_INVALID_THREAD_ID && tid != 0) { - NativeThreadProtocol *thread = new_process_it->second->GetThreadByID(tid); + NativeThreadProtocol *thread = + new_process_it->second.process_up->GetThreadByID(tid); if (!thread) { LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s failed, tid %" PRIu64 @@ -2297,12 +2390,12 @@ GDBRemoteCommunicationServerLLGS::Handle_H(StringExtractorGDBRemote &packet) { // Now switch the given process and thread type. switch (h_variant) { case 'g': - m_current_process = new_process_it->second.get(); + m_current_process = new_process_it->second.process_up.get(); SetCurrentThreadID(tid); break; case 'c': - m_continue_process = new_process_it->second.get(); + m_continue_process = new_process_it->second.process_up.get(); SetContinueThreadID(tid); break; @@ -2944,15 +3037,10 @@ GDBRemoteCommunicationServerLLGS::Handle_s(StringExtractorGDBRemote &packet) { // All other threads stop while we're single stepping a thread. actions.SetDefaultThreadActionIfNeeded(eStateStopped, 0); - Status error = m_continue_process->Resume(actions); - if (error.Fail()) { - LLDB_LOGF(log, - "GDBRemoteCommunicationServerLLGS::%s pid %" PRIu64 - " tid %" PRIu64 " Resume() failed with error: %s", - __FUNCTION__, m_continue_process->GetID(), tid, - error.AsCString()); - return SendErrorResponse(0x49); - } + + PacketResult resume_res = ResumeProcess(*m_continue_process, actions); + if (resume_res != PacketResult::Success) + return resume_res; // No response here, unless in non-stop mode. // Otherwise, the stop or exit will come from the resulting action. @@ -3440,7 +3528,8 @@ GDBRemoteCommunicationServerLLGS::Handle_vRun( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { Log *log = GetLog(LLDBLog::Process); - StopSTDIOForwarding(); + if (!m_non_stop) + StopSTDIOForwarding(); lldb::pid_t pid = LLDB_INVALID_PROCESS_ID; @@ -3466,12 +3555,12 @@ GDBRemoteCommunicationServerLLGS::Handle_D(StringExtractorGDBRemote &packet) { LLDB_LOGF(log, "GDBRemoteCommunicationServerLLGS::%s detaching %" PRId64, __FUNCTION__, it->first); - if (llvm::Error e = it->second->Detach().ToError()) + if (llvm::Error e = it->second.process_up->Detach().ToError()) detach_error = llvm::joinErrors(std::move(detach_error), std::move(e)); else { - if (it->second.get() == m_current_process) + if (it->second.process_up.get() == m_current_process) m_current_process = nullptr; - if (it->second.get() == m_continue_process) + if (it->second.process_up.get() == m_continue_process) m_continue_process = nullptr; it = m_debugged_processes.erase(it); detached = true; @@ -3833,13 +3922,38 @@ GDBRemoteCommunicationServerLLGS::Handle_qSaveCore( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_QNonStop( StringExtractorGDBRemote &packet) { + Log *log = GetLog(LLDBLog::Process); + StringRef packet_str{packet.GetStringRef()}; assert(packet_str.startswith("QNonStop:")); packet_str.consume_front("QNonStop:"); if (packet_str == "0") { + if (m_non_stop) + StopSTDIOForwarding(); + for (auto &process_it : m_debugged_processes) { + if (process_it.second.process_up->IsRunning()) { + assert(m_non_stop); + Status error = process_it.second.process_up->Interrupt(); + if (error.Fail()) { + LLDB_LOG(log, + "while disabling nonstop, failed to halt process {0}: {1}", + process_it.first, error); + return SendErrorResponse(0x41); + } + // we must not send stop reasons after QNonStop + m_disabling_non_stop = true; + } + } + m_stdio_notification_queue.clear(); + m_stop_notification_queue.clear(); m_non_stop = false; - // TODO: stop all threads + // If we are stopping anything, defer sending the OK response until we're + // done. + if (m_disabling_non_stop) + return PacketResult::Success; } else if (packet_str == "1") { + if (!m_non_stop) + StartSTDIOForwarding(); m_non_stop = true; } else return SendErrorResponse(Status("Invalid QNonStop packet")); @@ -3847,26 +3961,38 @@ GDBRemoteCommunicationServerLLGS::Handle_QNonStop( } GDBRemoteCommunication::PacketResult -GDBRemoteCommunicationServerLLGS::Handle_vStopped( - StringExtractorGDBRemote &packet) { +GDBRemoteCommunicationServerLLGS::HandleNotificationAck( + std::deque<std::string> &queue) { // Per the protocol, the first message put into the queue is sent - // immediately. However, it remains the queue until the client ACKs - // it via vStopped -- then we pop it and send the next message. - // The process repeats until the last message in the queue is ACK-ed, - // in which case the vStopped packet sends an OK response. - - if (m_stop_notification_queue.empty()) + // immediately. However, it remains the queue until the client ACKs it -- + // then we pop it and send the next message. The process repeats until + // the last message in the queue is ACK-ed, in which case the packet sends + // an OK response. + if (queue.empty()) return SendErrorResponse(Status("No pending notification to ack")); - m_stop_notification_queue.pop_front(); - if (!m_stop_notification_queue.empty()) - return SendPacketNoLock(m_stop_notification_queue.front()); + queue.pop_front(); + if (!queue.empty()) + return SendPacketNoLock(queue.front()); + return SendOKResponse(); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_vStdio( + StringExtractorGDBRemote &packet) { + return HandleNotificationAck(m_stdio_notification_queue); +} + +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_vStopped( + StringExtractorGDBRemote &packet) { + PacketResult ret = HandleNotificationAck(m_stop_notification_queue); // If this was the last notification and all the processes exited, // terminate the server. - if (m_debugged_processes.empty()) { + if (m_stop_notification_queue.empty() && m_debugged_processes.empty()) { m_exit_now = true; m_mainloop.RequestTermination(); } - return SendOKResponse(); + return ret; } GDBRemoteCommunication::PacketResult @@ -3907,7 +4033,7 @@ GDBRemoteCommunicationServerLLGS::Handle_T(StringExtractorGDBRemote &packet) { return SendErrorResponse(1); // Check the thread ID - if (!new_process_it->second->GetThreadByID(tid)) + if (!new_process_it->second.process_up->GetThreadByID(tid)) return SendErrorResponse(2); return SendOKResponse(); @@ -4108,7 +4234,7 @@ std::vector<std::string> GDBRemoteCommunicationServerLLGS::HandleFeatures( ret.push_back("vfork-events+"); for (auto &x : m_debugged_processes) - SetEnabledExtensions(*x.second); + SetEnabledExtensions(*x.second.process_up); return ret; } @@ -4121,9 +4247,10 @@ void GDBRemoteCommunicationServerLLGS::SetEnabledExtensions( GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::SendContinueSuccessResponse() { - // TODO: how to handle forwarding in non-stop mode? + if (m_non_stop) + return SendOKResponse(); StartSTDIOForwarding(); - return m_non_stop ? SendOKResponse() : PacketResult::Success; + return PacketResult::Success; } void GDBRemoteCommunicationServerLLGS::AppendThreadIDToResponse( diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index 5187a953f957..1165b60ac762 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -85,6 +85,17 @@ public: Status InitializeConnection(std::unique_ptr<Connection> connection); + struct DebuggedProcess { + enum class Flag { + vkilled = (1u << 0), + + LLVM_MARK_AS_BITMASK_ENUM(vkilled) + }; + + std::unique_ptr<NativeProcessProtocol> process_up; + Flag flags; + }; + protected: MainLoop &m_mainloop; MainLoop::ReadHandleUP m_network_handle_up; @@ -94,14 +105,11 @@ protected: NativeProcessProtocol *m_current_process; NativeProcessProtocol *m_continue_process; std::recursive_mutex m_debugged_process_mutex; - std::unordered_map<lldb::pid_t, std::unique_ptr<NativeProcessProtocol>> - m_debugged_processes; - std::unordered_set<lldb::pid_t> m_vkilled_processes; + std::unordered_map<lldb::pid_t, DebuggedProcess> m_debugged_processes; Communication m_stdio_communication; MainLoop::ReadHandleUP m_stdio_handle_up; - lldb::StateType m_inferior_prev_state = lldb::StateType::eStateInvalid; llvm::StringMap<std::unique_ptr<llvm::MemoryBuffer>> m_xfer_buffer_map; std::mutex m_saved_registers_mutex; std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map; @@ -109,6 +117,8 @@ protected: bool m_thread_suffix_supported = false; bool m_list_threads_in_stop_reply = false; bool m_non_stop = false; + bool m_disabling_non_stop = false; + std::deque<std::string> m_stdio_notification_queue; std::deque<std::string> m_stop_notification_queue; NativeProcessProtocol::Extension m_extensions_supported = {}; @@ -147,6 +157,9 @@ protected: PacketResult Handle_QListThreadsInStopReply(StringExtractorGDBRemote &packet); + PacketResult ResumeProcess(NativeProcessProtocol &process, + const ResumeActionList &actions); + PacketResult Handle_C(StringExtractorGDBRemote &packet); PacketResult Handle_c(StringExtractorGDBRemote &packet); @@ -236,6 +249,10 @@ protected: PacketResult Handle_QNonStop(StringExtractorGDBRemote &packet); + PacketResult HandleNotificationAck(std::deque<std::string> &queue); + + PacketResult Handle_vStdio(StringExtractorGDBRemote &packet); + PacketResult Handle_vStopped(StringExtractorGDBRemote &packet); PacketResult Handle_vCtrlC(StringExtractorGDBRemote &packet); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index fe6a3f9ed6c1..5f18706f67e5 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -5307,8 +5307,11 @@ void ProcessGDBRemote::DidFork(lldb::pid_t child_pid, lldb::tid_t child_tid) { // Hardware breakpoints/watchpoints are not inherited implicitly, // so we need to readd them if we're following child. - if (GetFollowForkMode() == eFollowChild) + if (GetFollowForkMode() == eFollowChild) { DidForkSwitchHardwareTraps(true); + // Update our PID + SetID(child_pid); + } } void ProcessGDBRemote::DidVFork(lldb::pid_t child_pid, lldb::tid_t child_tid) { @@ -5361,6 +5364,11 @@ void ProcessGDBRemote::DidVFork(lldb::pid_t child_pid, lldb::tid_t child_tid) { error.AsCString() ? error.AsCString() : "<unknown error>"); return; } + + if (GetFollowForkMode() == eFollowChild) { + // Update our PID + SetID(child_pid); + } } void ProcessGDBRemote::DidVForkDone() { diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 53e2bcaccafb..a21adcfbdbd6 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -2637,7 +2637,7 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( .SetSetLLDBGlobals(false); if (!pathname || !pathname[0]) { - error.SetErrorString("invalid pathname"); + error.SetErrorString("empty path"); return false; } @@ -2707,14 +2707,14 @@ bool ScriptInterpreterPythonImpl::LoadScriptingModule( // if not a valid file of any sort, check if it might be a filename still // dot can't be used but / and \ can, and if either is found, reject if (strchr(pathname, '\\') || strchr(pathname, '/')) { - error.SetErrorString("invalid pathname"); + error.SetErrorStringWithFormatv("invalid pathname '{0}'", pathname); return false; } // Not a filename, probably a package of some sort, let it go through. possible_package = true; } else if (is_directory(st) || is_regular_file(st)) { if (module_file.GetDirectory().IsEmpty()) { - error.SetErrorString("invalid directory name"); + error.SetErrorStringWithFormatv("invalid directory name '{0}'", pathname); return false; } if (llvm::Error e = diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp index 4b9354371bda..10dc8d1fb7c3 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.cpp @@ -2390,6 +2390,7 @@ struct MemberAttributes { uint64_t data_bit_offset = UINT64_MAX; AccessType accessibility = eAccessNone; llvm::Optional<uint64_t> byte_size; + llvm::Optional<DWARFFormValue> const_value_form; DWARFFormValue encoding_form; /// Indicates the byte offset of the word from the base address of the /// structure. @@ -2436,6 +2437,9 @@ MemberAttributes::MemberAttributes(const DWARFDIE &die, case DW_AT_byte_size: byte_size = form_value.Unsigned(); break; + case DW_AT_const_value: + const_value_form = form_value; + break; case DW_AT_data_bit_offset: data_bit_offset = form_value.Unsigned(); break; @@ -2587,12 +2591,65 @@ void DWARFASTParserClang::ParseObjCProperty( propAttrs.prop_getter_name, propAttrs.prop_attributes, &metadata)); } +llvm::Expected<llvm::APInt> DWARFASTParserClang::ExtractIntFromFormValue( + const CompilerType &int_type, const DWARFFormValue &form_value) const { + clang::QualType qt = ClangUtil::GetQualType(int_type); + assert(qt->isIntegralOrEnumerationType()); + TypeSystemClang &ts = *llvm::cast<TypeSystemClang>(int_type.GetTypeSystem()); + clang::ASTContext &ast = ts.getASTContext(); + + const unsigned type_bits = ast.getIntWidth(qt); + const bool is_unsigned = qt->isUnsignedIntegerType(); + + // The maximum int size supported at the moment by this function. Limited + // by the uint64_t return type of DWARFFormValue::Signed/Unsigned. + constexpr std::size_t max_bit_size = 64; + + // For values bigger than 64 bit (e.g. __int128_t values), + // DWARFFormValue's Signed/Unsigned functions will return wrong results so + // emit an error for now. + if (type_bits > max_bit_size) { + auto msg = llvm::formatv("Can only parse integers with up to {0} bits, but " + "given integer has {1} bits.", + max_bit_size, type_bits); + return llvm::createStringError(llvm::inconvertibleErrorCode(), msg.str()); + } + + // Construct an APInt with the maximum bit size and the given integer. + llvm::APInt result(max_bit_size, form_value.Unsigned(), !is_unsigned); + + // Calculate how many bits are required to represent the input value. + // For unsigned types, take the number of active bits in the APInt. + // For signed types, ask APInt how many bits are required to represent the + // signed integer. + const unsigned required_bits = + is_unsigned ? result.getActiveBits() : result.getMinSignedBits(); + + // If the input value doesn't fit into the integer type, return an error. + if (required_bits > type_bits) { + std::string value_as_str = is_unsigned + ? std::to_string(form_value.Unsigned()) + : std::to_string(form_value.Signed()); + auto msg = llvm::formatv("Can't store {0} value {1} in integer with {2} " + "bits.", + (is_unsigned ? "unsigned" : "signed"), + value_as_str, type_bits); + return llvm::createStringError(llvm::inconvertibleErrorCode(), msg.str()); + } + + // Trim the result to the bit width our the int type. + if (result.getBitWidth() > type_bits) + result = result.trunc(type_bits); + return result; +} + void DWARFASTParserClang::ParseSingleMember( const DWARFDIE &die, const DWARFDIE &parent_die, const lldb_private::CompilerType &class_clang_type, lldb::AccessType default_accessibility, lldb_private::ClangASTImporter::LayoutInfo &layout_info, FieldInfo &last_field_info) { + Log *log = GetLog(DWARFLog::TypeCompletion | DWARFLog::Lookups); // This function can only parse DW_TAG_member. assert(die.Tag() == DW_TAG_member); @@ -2623,9 +2680,27 @@ void DWARFASTParserClang::ParseSingleMember( if (var_type) { if (attrs.accessibility == eAccessNone) attrs.accessibility = eAccessPublic; - TypeSystemClang::AddVariableToRecordType( - class_clang_type, attrs.name, var_type->GetForwardCompilerType(), - attrs.accessibility); + CompilerType ct = var_type->GetForwardCompilerType(); + clang::VarDecl *v = TypeSystemClang::AddVariableToRecordType( + class_clang_type, attrs.name, ct, attrs.accessibility); + if (!v) { + LLDB_LOG(log, "Failed to add variable to the record type"); + return; + } + + bool unused; + // TODO: Support float/double static members as well. + if (!attrs.const_value_form || !ct.IsIntegerOrEnumerationType(unused)) + return; + llvm::Expected<llvm::APInt> const_value_or_err = + ExtractIntFromFormValue(ct, *attrs.const_value_form); + if (!const_value_or_err) { + LLDB_LOG_ERROR(log, const_value_or_err.takeError(), + "Failed to add const value to variable {1}: {0}", + v->getQualifiedNameAsString()); + return; + } + TypeSystemClang::SetIntegerInitializerForVariable(v, *const_value_or_err); } return; } diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h index f97c0c470ab0..733ffa230f1e 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserClang.h @@ -68,6 +68,22 @@ public: lldb_private::ClangASTImporter &GetClangASTImporter(); + /// Extracts an value for a given Clang integer type from a DWARFFormValue. + /// + /// \param int_type The Clang type that defines the bit size and signedness + /// of the integer that should be extracted. Has to be either + /// an integer type or an enum type. For enum types the + /// underlying integer type will be considered as the + /// expected integer type that should be extracted. + /// \param form_value The DWARFFormValue that contains the integer value. + /// \return An APInt containing the same integer value as the given + /// DWARFFormValue with the bit width of the given integer type. + /// Returns an error if the value in the DWARFFormValue does not fit + /// into the given integer type or the integer type isn't supported. + llvm::Expected<llvm::APInt> + ExtractIntFromFormValue(const lldb_private::CompilerType &int_type, + const DWARFFormValue &form_value) const; + protected: /// Protected typedefs and members. /// @{ diff --git a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp index cbc24b1550c7..8ee709db9cdb 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/SymbolFileDWARF.cpp @@ -3475,10 +3475,9 @@ VariableSP SymbolFileDWARF::ParseVariableDIE(const SymbolContext &sc, if (use_type_size_for_value && type_sp->GetType()) { DWARFExpression *location = location_list.GetMutableExpressionAtAddress(); - location->UpdateValue( - const_value_form.Unsigned(), - type_sp->GetType()->GetByteSize(nullptr).getValueOr(0), - die.GetCU()->GetAddressByteSize()); + location->UpdateValue(const_value_form.Unsigned(), + type_sp->GetType()->GetByteSize(nullptr).value_or(0), + die.GetCU()->GetAddressByteSize()); } return std::make_shared<Variable>( diff --git a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp index 6dcce738b79f..25425f914088 100644 --- a/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp +++ b/lldb/source/Plugins/SymbolFile/NativePDB/PdbAstBuilder.cpp @@ -816,6 +816,40 @@ clang::QualType PdbAstBuilder::CreatePointerType(const PointerRecord &pointer) { clang::QualType class_type = GetOrCreateType(mpi.ContainingType); if (class_type.isNull()) return {}; + if (clang::TagDecl *tag = class_type->getAsTagDecl()) { + clang::MSInheritanceAttr::Spelling spelling; + switch (mpi.Representation) { + case llvm::codeview::PointerToMemberRepresentation::SingleInheritanceData: + case llvm::codeview::PointerToMemberRepresentation:: + SingleInheritanceFunction: + spelling = + clang::MSInheritanceAttr::Spelling::Keyword_single_inheritance; + break; + case llvm::codeview::PointerToMemberRepresentation:: + MultipleInheritanceData: + case llvm::codeview::PointerToMemberRepresentation:: + MultipleInheritanceFunction: + spelling = + clang::MSInheritanceAttr::Spelling::Keyword_multiple_inheritance; + break; + case llvm::codeview::PointerToMemberRepresentation:: + VirtualInheritanceData: + case llvm::codeview::PointerToMemberRepresentation:: + VirtualInheritanceFunction: + spelling = + clang::MSInheritanceAttr::Spelling::Keyword_virtual_inheritance; + break; + case llvm::codeview::PointerToMemberRepresentation::Unknown: + spelling = + clang::MSInheritanceAttr::Spelling::Keyword_unspecified_inheritance; + break; + default: + spelling = clang::MSInheritanceAttr::Spelling::SpellingNotCalculated; + break; + } + tag->addAttr(clang::MSInheritanceAttr::CreateImplicit( + m_clang.getASTContext(), spelling)); + } return m_clang.getASTContext().getMemberPointerType( pointee_type, class_type.getTypePtr()); } diff --git a/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp b/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp index 91eafdaa11bc..dd28292c1daf 100644 --- a/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp +++ b/lldb/source/Plugins/Trace/intel-pt/CommandObjectTraceStartIntelPT.cpp @@ -11,6 +11,7 @@ #include "TraceIntelPT.h" #include "TraceIntelPTConstants.h" #include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Target/Process.h" #include "lldb/Target/Trace.h" diff --git a/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp b/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp index 194cc7459027..384abd2166df 100644 --- a/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp +++ b/lldb/source/Plugins/TraceExporter/ctf/CommandObjectThreadTraceExportCTF.cpp @@ -10,6 +10,7 @@ #include "../common/TraceHTR.h" #include "lldb/Host/OptionParser.h" +#include "lldb/Interpreter/CommandOptionArgumentTable.h" #include "lldb/Target/Process.h" #include "lldb/Target/Trace.h" diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp index e0f646b15641..c6eb693bba6b 100644 --- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp +++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp @@ -7538,7 +7538,7 @@ void TypeSystemClang::SetIntegerInitializerForVariable( "only integer or enum types supported"); // If the variable is an enum type, take the underlying integer type as // the type of the integer literal. - if (const EnumType *enum_type = llvm::dyn_cast<EnumType>(qt.getTypePtr())) { + if (const EnumType *enum_type = qt->getAs<EnumType>()) { const EnumDecl *enum_decl = enum_type->getDecl(); qt = enum_decl->getIntegerType(); } diff --git a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h index 97cb04e51408..796e7e50a8b9 100644 --- a/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h +++ b/lldb/source/Plugins/UnwindAssembly/InstEmulation/UnwindAssemblyInstEmulation.h @@ -64,8 +64,8 @@ private: lldb_private::EmulateInstruction *inst_emulator) : UnwindAssembly(arch), m_inst_emulator_up(inst_emulator), m_range_ptr(nullptr), m_unwind_plan_ptr(nullptr), m_curr_row(), - m_cfa_reg_info(), m_fp_is_cfa(false), m_register_values(), - m_pushed_regs(), m_curr_row_modified(false), + m_initial_sp(0), m_cfa_reg_info(), m_fp_is_cfa(false), + m_register_values(), m_pushed_regs(), m_curr_row_modified(false), m_forward_branch_offset(0) { if (m_inst_emulator_up.get()) { m_inst_emulator_up->SetBaton(this); diff --git a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp index 36e7b90cad24..92eec139e07c 100644 --- a/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp +++ b/lldb/source/Plugins/UnwindAssembly/x86/x86AssemblyInspectionEngine.cpp @@ -24,11 +24,12 @@ x86AssemblyInspectionEngine::x86AssemblyInspectionEngine(const ArchSpec &arch) : m_cur_insn(nullptr), m_machine_ip_regnum(LLDB_INVALID_REGNUM), m_machine_sp_regnum(LLDB_INVALID_REGNUM), m_machine_fp_regnum(LLDB_INVALID_REGNUM), + m_machine_alt_fp_regnum(LLDB_INVALID_REGNUM), m_lldb_ip_regnum(LLDB_INVALID_REGNUM), m_lldb_sp_regnum(LLDB_INVALID_REGNUM), m_lldb_fp_regnum(LLDB_INVALID_REGNUM), - - m_reg_map(), m_arch(arch), m_cpu(k_cpu_unspecified), m_wordsize(-1), + m_lldb_alt_fp_regnum(LLDB_INVALID_REGNUM), m_reg_map(), m_arch(arch), + m_cpu(k_cpu_unspecified), m_wordsize(-1), m_register_map_initialized(false), m_disasm_context() { m_disasm_context = ::LLVMCreateDisasm(arch.GetTriple().getTriple().c_str(), nullptr, diff --git a/lldb/source/Symbol/ArmUnwindInfo.cpp b/lldb/source/Symbol/ArmUnwindInfo.cpp index 07852485f44e..ae6cddfbc463 100644 --- a/lldb/source/Symbol/ArmUnwindInfo.cpp +++ b/lldb/source/Symbol/ArmUnwindInfo.cpp @@ -65,7 +65,7 @@ ArmUnwindInfo::ArmUnwindInfo(ObjectFile &objfile, SectionSP &arm_exidx, // Sort the entries in the exidx section. The entries should be sorted inside // the section but some old compiler isn't sorted them. - llvm::sort(m_exidx_entries.begin(), m_exidx_entries.end()); + llvm::sort(m_exidx_entries); } ArmUnwindInfo::~ArmUnwindInfo() = default; diff --git a/lldb/source/Symbol/CompileUnit.cpp b/lldb/source/Symbol/CompileUnit.cpp index cacb78de2426..2bae08c8b930 100644 --- a/lldb/source/Symbol/CompileUnit.cpp +++ b/lldb/source/Symbol/CompileUnit.cpp @@ -63,7 +63,7 @@ void CompileUnit::ForeachFunction( sorted_functions.reserve(m_functions_by_uid.size()); for (auto &p : m_functions_by_uid) sorted_functions.push_back(p.second); - llvm::sort(sorted_functions.begin(), sorted_functions.end(), + llvm::sort(sorted_functions, [](const lldb::FunctionSP &a, const lldb::FunctionSP &b) { return a->GetID() < b->GetID(); }); diff --git a/lldb/source/Symbol/Symtab.cpp b/lldb/source/Symbol/Symtab.cpp index eb2447efbad1..936ee04ed492 100644 --- a/lldb/source/Symbol/Symtab.cpp +++ b/lldb/source/Symbol/Symtab.cpp @@ -1137,7 +1137,7 @@ void Symtab::FindFunctionSymbols(ConstString name, uint32_t name_type_mask, } if (!symbol_indexes.empty()) { - llvm::sort(symbol_indexes.begin(), symbol_indexes.end()); + llvm::sort(symbol_indexes); symbol_indexes.erase( std::unique(symbol_indexes.begin(), symbol_indexes.end()), symbol_indexes.end()); diff --git a/lldb/source/Target/DynamicRegisterInfo.cpp b/lldb/source/Target/DynamicRegisterInfo.cpp index e2962b02ed7f..14c3faae38df 100644 --- a/lldb/source/Target/DynamicRegisterInfo.cpp +++ b/lldb/source/Target/DynamicRegisterInfo.cpp @@ -483,7 +483,7 @@ void DynamicRegisterInfo::Finalize(const ArchSpec &arch) { end = m_invalidate_regs_map.end(); pos != end; ++pos) { if (pos->second.size() > 1) { - llvm::sort(pos->second.begin(), pos->second.end()); + llvm::sort(pos->second); reg_num_collection::iterator unique_end = std::unique(pos->second.begin(), pos->second.end()); if (unique_end != pos->second.end()) diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index 65064ecf75b1..f16fc6b5da85 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -776,7 +776,7 @@ void Target::GetBreakpointNames(std::vector<std::string> &names) { for (auto bp_name : m_breakpoint_names) { names.push_back(bp_name.first.AsCString()); } - llvm::sort(names.begin(), names.end()); + llvm::sort(names); } bool Target::ProcessIsValid() { diff --git a/lldb/source/Target/TargetList.cpp b/lldb/source/Target/TargetList.cpp index 214e98ee91ed..829036976a21 100644 --- a/lldb/source/Target/TargetList.cpp +++ b/lldb/source/Target/TargetList.cpp @@ -509,8 +509,7 @@ uint32_t TargetList::GetIndexOfTarget(lldb::TargetSP target_sp) const { } void TargetList::AddTargetInternal(TargetSP target_sp, bool do_select) { - lldbassert(std::find(m_target_list.begin(), m_target_list.end(), target_sp) == - m_target_list.end() && + lldbassert(!llvm::is_contained(m_target_list, target_sp) && "target already exists it the list"); m_target_list.push_back(std::move(target_sp)); if (do_select) diff --git a/lldb/source/Target/Thread.cpp b/lldb/source/Target/Thread.cpp index 3803748be297..f63b57fd4e62 100644 --- a/lldb/source/Target/Thread.cpp +++ b/lldb/source/Target/Thread.cpp @@ -2022,7 +2022,8 @@ lldb::ValueObjectSP Thread::GetSiginfoValue() { llvm::Optional<uint64_t> type_size = type.GetByteSize(nullptr); assert(type_size); - llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> data = GetSiginfo(type_size.getValue()); + llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> data = + GetSiginfo(type_size.value()); if (!data) return ValueObjectConstResult::Create(&target, Status(data.takeError())); diff --git a/lldb/source/Target/UnixSignals.cpp b/lldb/source/Target/UnixSignals.cpp index 4ae848a98edd..3ece3ee24cbe 100644 --- a/lldb/source/Target/UnixSignals.cpp +++ b/lldb/source/Target/UnixSignals.cpp @@ -300,14 +300,13 @@ UnixSignals::GetFilteredSignals(llvm::Optional<bool> should_suppress, // If any of filtering conditions are not met, we move on to the next // signal. - if (should_suppress && - signal_suppress != should_suppress.getValue()) + if (should_suppress && signal_suppress != should_suppress.value()) continue; - if (should_stop && signal_stop != should_stop.getValue()) + if (should_stop && signal_stop != should_stop.value()) continue; - if (should_notify && signal_notify != should_notify.getValue()) + if (should_notify && signal_notify != should_notify.value()) continue; result.push_back(signo); diff --git a/lldb/source/Utility/ReproducerProvider.cpp b/lldb/source/Utility/ReproducerProvider.cpp index 0d1581abda64..44f24e44f38d 100644 --- a/lldb/source/Utility/ReproducerProvider.cpp +++ b/lldb/source/Utility/ReproducerProvider.cpp @@ -131,7 +131,7 @@ void SymbolFileProvider::Keep() { return; // Remove duplicates. - llvm::sort(m_symbol_files.begin(), m_symbol_files.end()); + llvm::sort(m_symbol_files); m_symbol_files.erase( std::unique(m_symbol_files.begin(), m_symbol_files.end()), m_symbol_files.end()); diff --git a/lldb/source/Utility/SelectHelper.cpp b/lldb/source/Utility/SelectHelper.cpp index a25bdfdaee8e..05dbd1cce09d 100644 --- a/lldb/source/Utility/SelectHelper.cpp +++ b/lldb/source/Utility/SelectHelper.cpp @@ -197,8 +197,8 @@ lldb_private::Status SelectHelper::Select() { // Setup out relative timeout based on the end time if we have one if (m_end_time) { tv_ptr = &tv; - const auto remaining_dur = duration_cast<microseconds>( - m_end_time.getValue() - steady_clock::now()); + const auto remaining_dur = + duration_cast<microseconds>(m_end_time.value() - steady_clock::now()); if (remaining_dur.count() > 0) { // Wait for a specific amount of time const auto dur_secs = duration_cast<seconds>(remaining_dur); diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp index 07954408f6d0..fc740615dd05 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.cpp +++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp @@ -380,6 +380,8 @@ StringExtractorGDBRemote::GetServerPacketType() const { return eServerPacketType_vStopped; if (PACKET_MATCHES("vCtrlC")) return eServerPacketType_vCtrlC; + if (PACKET_MATCHES("vStdio")) + return eServerPacketType_vStdio; break; } diff --git a/lldb/source/Utility/Timer.cpp b/lldb/source/Utility/Timer.cpp index b190f35007d5..477541d7bb3d 100644 --- a/lldb/source/Utility/Timer.cpp +++ b/lldb/source/Utility/Timer.cpp @@ -150,7 +150,7 @@ void Timer::DumpCategoryTimes(Stream *s) { return; // Later code will break without any elements. // Sort by time - llvm::sort(sorted.begin(), sorted.end(), CategoryMapIteratorSortCriterion); + llvm::sort(sorted, CategoryMapIteratorSortCriterion); for (const auto &stats : sorted) s->Printf("%.9f sec (total: %.3fs; child: %.3fs; count: %" PRIu64 diff --git a/lldb/utils/TableGen/LLDBOptionDefEmitter.cpp b/lldb/utils/TableGen/LLDBOptionDefEmitter.cpp index ccf48275f42c..d73f0a2914c1 100644 --- a/lldb/utils/TableGen/LLDBOptionDefEmitter.cpp +++ b/lldb/utils/TableGen/LLDBOptionDefEmitter.cpp @@ -31,7 +31,6 @@ struct CommandOption { std::string ArgType; bool OptionalArg = false; std::string Validator; - std::string ArgEnum; std::vector<StringRef> Completions; std::string Description; @@ -65,9 +64,6 @@ struct CommandOption { if (Option->getValue("Validator")) Validator = std::string(Option->getValueAsString("Validator")); - if (Option->getValue("ArgEnum")) - ArgEnum = std::string(Option->getValueAsString("ArgEnum")); - if (Option->getValue("Completions")) Completions = Option->getValueAsListOfStrings("Completions"); @@ -114,8 +110,8 @@ static void emitOption(const CommandOption &O, raw_ostream &OS) { OS << "nullptr"; OS << ", "; - if (!O.ArgEnum.empty()) - OS << O.ArgEnum; + if (!O.ArgType.empty()) + OS << "g_argument_table[eArgType" << O.ArgType << "].enum_values"; else OS << "{}"; OS << ", "; |