diff options
Diffstat (limited to 'lldb/include')
88 files changed, 666 insertions, 1402 deletions
diff --git a/lldb/include/lldb/API/SBDebugger.h b/lldb/include/lldb/API/SBDebugger.h index 1c771330cddc..a82c147053eb 100644 --- a/lldb/include/lldb/API/SBDebugger.h +++ b/lldb/include/lldb/API/SBDebugger.h @@ -306,6 +306,10 @@ public: void SetScriptLanguage(lldb::ScriptLanguage script_lang); + lldb::LanguageType GetREPLLanguage() const; + + void SetREPLLanguage(lldb::LanguageType repl_lang); + bool GetCloseInputOnEOF() const; void SetCloseInputOnEOF(bool b); diff --git a/lldb/include/lldb/API/SBDefines.h b/lldb/include/lldb/API/SBDefines.h index 3ab10ad8e061..ecf1dc34d8c5 100644 --- a/lldb/include/lldb/API/SBDefines.h +++ b/lldb/include/lldb/API/SBDefines.h @@ -15,6 +15,18 @@ #include "lldb/lldb-types.h" #include "lldb/lldb-versioning.h" +#ifndef LLDB_API +#if defined(_WIN32) +#if defined(LLDB_IN_LIBLLDB) +#define LLDB_API __declspec(dllexport) +#else +#define LLDB_API __declspec(dllimport) +#endif +#else // defined (_WIN32) +#define LLDB_API +#endif +#endif + // Forward Declarations namespace lldb { diff --git a/lldb/include/lldb/API/SBModule.h b/lldb/include/lldb/API/SBModule.h index dd783fe4107d..7200a1ef53fd 100644 --- a/lldb/include/lldb/API/SBModule.h +++ b/lldb/include/lldb/API/SBModule.h @@ -37,6 +37,8 @@ public: void Clear(); + bool IsFileBacked() const; + /// Get const accessor for the module file specification. /// /// This function returns the file for the module on the host system diff --git a/lldb/include/lldb/API/SBPlatform.h b/lldb/include/lldb/API/SBPlatform.h index 98291f18247d..4f5d04a24e95 100644 --- a/lldb/include/lldb/API/SBPlatform.h +++ b/lldb/include/lldb/API/SBPlatform.h @@ -137,6 +137,8 @@ public: uint32_t GetOSUpdateVersion(); + void SetSDKRoot(const char *sysroot); + SBError Put(SBFileSpec &src, SBFileSpec &dst); SBError Get(SBFileSpec &src, SBFileSpec &dst); @@ -170,6 +172,7 @@ public: protected: friend class SBDebugger; friend class SBTarget; + friend class SBThread; lldb::PlatformSP GetSP() const; diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h index abd9ebf07407..9e75b5e503a8 100644 --- a/lldb/include/lldb/API/SBTarget.h +++ b/lldb/include/lldb/API/SBTarget.h @@ -875,6 +875,7 @@ protected: friend class SBSection; friend class SBSourceManager; friend class SBSymbol; + friend class SBThread; friend class SBValue; friend class SBVariablesOptions; diff --git a/lldb/include/lldb/API/SBThread.h b/lldb/include/lldb/API/SBThread.h index ac1b8407a220..76f794c25d9e 100644 --- a/lldb/include/lldb/API/SBThread.h +++ b/lldb/include/lldb/API/SBThread.h @@ -208,6 +208,8 @@ public: bool SafeToCallFunctions(); + SBValue GetSiginfo(SBError &error); + private: friend class SBBreakpoint; friend class SBBreakpointLocation; diff --git a/lldb/include/lldb/API/SBType.h b/lldb/include/lldb/API/SBType.h index 529b4d0eeffc..5885432d0624 100644 --- a/lldb/include/lldb/API/SBType.h +++ b/lldb/include/lldb/API/SBType.h @@ -225,6 +225,7 @@ protected: friend class SBFunction; friend class SBModule; friend class SBTarget; + friend class SBThread; friend class SBTypeEnumMember; friend class SBTypeEnumMemberList; friend class SBTypeNameSpecifier; diff --git a/lldb/include/lldb/Breakpoint/Breakpoint.h b/lldb/include/lldb/Breakpoint/Breakpoint.h index 40435d5c3d0f..113f8c4905e1 100644 --- a/lldb/include/lldb/Breakpoint/Breakpoint.h +++ b/lldb/include/lldb/Breakpoint/Breakpoint.h @@ -581,7 +581,7 @@ public: llvm::json::Value GetStatistics(); /// Get the time it took to resolve all locations in this breakpoint. - StatsDuration GetResolveTime() const { return m_resolve_time; } + StatsDuration::Duration GetResolveTime() const { return m_resolve_time; } protected: friend class Target; @@ -660,7 +660,7 @@ private: BreakpointName::Permissions m_permissions; - StatsDuration m_resolve_time{0.0}; + StatsDuration m_resolve_time; void SendBreakpointChangedEvent(lldb::BreakpointEventType eventKind); diff --git a/lldb/include/lldb/Breakpoint/BreakpointOptions.h b/lldb/include/lldb/Breakpoint/BreakpointOptions.h index 7b78265920a2..c2456024d919 100644 --- a/lldb/include/lldb/Breakpoint/BreakpointOptions.h +++ b/lldb/include/lldb/Breakpoint/BreakpointOptions.h @@ -43,11 +43,10 @@ public: | eCondition | eAutoContinue) }; struct CommandData { - CommandData() : user_source(), script_source() {} + CommandData() {} CommandData(const StringList &user_source, lldb::ScriptLanguage interp) - : user_source(user_source), script_source(), interpreter(interp), - stop_on_error(true) {} + : user_source(user_source), interpreter(interp), stop_on_error(true) {} virtual ~CommandData() = default; @@ -195,8 +194,8 @@ public: /// The commands will be appended to this list. /// /// \return - /// \btrue if the command callback is a command-line callback, - /// \bfalse otherwise. + /// \b true if the command callback is a command-line callback, + /// \b false otherwise. bool GetCommandLineCallbacks(StringList &command_list); /// Remove the callback from this option set. diff --git a/lldb/include/lldb/Breakpoint/WatchpointOptions.h b/lldb/include/lldb/Breakpoint/WatchpointOptions.h index fbfcb91c4249..c5ad90c334c4 100644 --- a/lldb/include/lldb/Breakpoint/WatchpointOptions.h +++ b/lldb/include/lldb/Breakpoint/WatchpointOptions.h @@ -166,7 +166,7 @@ public: lldb::user_id_t watch_id); struct CommandData { - CommandData() : user_source(), script_source() {} + CommandData() {} ~CommandData() = default; diff --git a/lldb/include/lldb/Core/Address.h b/lldb/include/lldb/Core/Address.h index dc50e27ca277..f77ffc2fd25e 100644 --- a/lldb/include/lldb/Core/Address.h +++ b/lldb/include/lldb/Core/Address.h @@ -116,7 +116,7 @@ public: /// /// Initialize with a invalid section (NULL) and an invalid offset /// (LLDB_INVALID_ADDRESS). - Address() : m_section_wp() {} + Address() {} /// Copy constructor /// diff --git a/lldb/include/lldb/Core/Debugger.h b/lldb/include/lldb/Core/Debugger.h index 1ab21bec54c9..f9a1f1eea54f 100644 --- a/lldb/include/lldb/Core/Debugger.h +++ b/lldb/include/lldb/Core/Debugger.h @@ -306,6 +306,10 @@ public: bool SetScriptLanguage(lldb::ScriptLanguage script_lang); + lldb::LanguageType GetREPLLanguage() const; + + bool SetREPLLanguage(lldb::LanguageType repl_lang); + uint32_t GetTerminalWidth() const; bool SetTerminalWidth(uint32_t term_width); diff --git a/lldb/include/lldb/Core/Declaration.h b/lldb/include/lldb/Core/Declaration.h index f81de21bc8f8..6ae21eb65eb3 100644 --- a/lldb/include/lldb/Core/Declaration.h +++ b/lldb/include/lldb/Core/Declaration.h @@ -24,7 +24,7 @@ namespace lldb_private { class Declaration { public: /// Default constructor. - Declaration() : m_file() {} + Declaration() {} /// Construct with file specification, and optional line and column. /// @@ -45,7 +45,7 @@ public: /// Construct with a pointer to another Declaration object. Declaration(const Declaration *decl_ptr) - : m_file(), m_line(0), m_column(LLDB_INVALID_COLUMN_NUMBER) { + : m_line(0), m_column(LLDB_INVALID_COLUMN_NUMBER) { if (decl_ptr) *this = *decl_ptr; } @@ -152,8 +152,6 @@ public: /// The number of bytes that this object occupies in memory. /// The returned value does not include the bytes for any /// shared string values. - /// - /// \see ConstString::StaticMemorySize () size_t MemorySize() const; /// Set accessor for the declaration file specification. diff --git a/lldb/include/lldb/Core/Disassembler.h b/lldb/include/lldb/Core/Disassembler.h index 0925bf358b9c..87979fd92584 100644 --- a/lldb/include/lldb/Core/Disassembler.h +++ b/lldb/include/lldb/Core/Disassembler.h @@ -465,7 +465,7 @@ protected: uint32_t line = LLDB_INVALID_LINE_NUMBER; uint32_t column = 0; - SourceLine() : file() {} + SourceLine() {} bool operator==(const SourceLine &rhs) const { return file == rhs.file && line == rhs.line && rhs.column == column; @@ -489,7 +489,7 @@ protected: // Whether to print a blank line at the end of the source lines. bool print_source_context_end_eol = true; - SourceLinesToDisplay() : lines() {} + SourceLinesToDisplay() {} }; // Get the function's declaration line number, hopefully a line number diff --git a/lldb/include/lldb/Core/DumpDataExtractor.h b/lldb/include/lldb/Core/DumpDataExtractor.h index 12188609e8c0..08501b512a2b 100644 --- a/lldb/include/lldb/Core/DumpDataExtractor.h +++ b/lldb/include/lldb/Core/DumpDataExtractor.h @@ -76,6 +76,15 @@ class Stream; /// same integer value. If the items being displayed are not /// bitfields, this value should be zero. /// +/// \param[in] exe_scope +/// If provided, this will be used to lookup language specific +/// information, address information and memory tags. +/// (if they are requested by the other options) +/// +/// \param[in] show_memory_tags +/// If exe_scope and base_addr are valid, include memory tags +/// in the output. This does not apply to certain formats. +/// /// \return /// The offset at which dumping ended. lldb::offset_t @@ -83,7 +92,8 @@ DumpDataExtractor(const DataExtractor &DE, Stream *s, lldb::offset_t offset, lldb::Format item_format, size_t item_byte_size, size_t item_count, size_t num_per_line, uint64_t base_addr, uint32_t item_bit_size, uint32_t item_bit_offset, - ExecutionContextScope *exe_scope = nullptr); + ExecutionContextScope *exe_scope = nullptr, + bool show_memory_tags = false); void DumpHexBytes(Stream *s, const void *src, size_t src_len, uint32_t bytes_per_line, lldb::addr_t base_addr); diff --git a/lldb/include/lldb/Core/FileSpecList.h b/lldb/include/lldb/Core/FileSpecList.h index cab8e9b9b43f..117c6b691498 100644 --- a/lldb/include/lldb/Core/FileSpecList.h +++ b/lldb/include/lldb/Core/FileSpecList.h @@ -152,8 +152,6 @@ public: /// /// \return /// The number of bytes that this object occupies in memory. - /// - /// \see ConstString::StaticMemorySize () size_t MemorySize() const; bool IsEmpty() const { return m_files.empty(); } diff --git a/lldb/include/lldb/Core/FormatEntity.h b/lldb/include/lldb/Core/FormatEntity.h index ecae8500df40..cd9019d55554 100644 --- a/lldb/include/lldb/Core/FormatEntity.h +++ b/lldb/include/lldb/Core/FormatEntity.h @@ -148,7 +148,7 @@ public: Entry(Type t = Type::Invalid, const char *s = nullptr, const char *f = nullptr) - : string(s ? s : ""), printf_format(f ? f : ""), children(), type(t) {} + : string(s ? s : ""), printf_format(f ? f : ""), type(t) {} Entry(llvm::StringRef s); Entry(char ch); diff --git a/lldb/include/lldb/Core/LoadedModuleInfoList.h b/lldb/include/lldb/Core/LoadedModuleInfoList.h index ad6da2bd7559..3f65ddc06d73 100644 --- a/lldb/include/lldb/Core/LoadedModuleInfoList.h +++ b/lldb/include/lldb/Core/LoadedModuleInfoList.h @@ -101,7 +101,7 @@ public: lldb::addr_t m_dynamic; }; - LoadedModuleInfoList() : m_list() {} + LoadedModuleInfoList() {} void add(const LoadedModuleInfo &mod) { m_list.push_back(mod); } diff --git a/lldb/include/lldb/Core/Mangled.h b/lldb/include/lldb/Core/Mangled.h index 6c92591a0881..4e4f75e18e34 100644 --- a/lldb/include/lldb/Core/Mangled.h +++ b/lldb/include/lldb/Core/Mangled.h @@ -72,10 +72,10 @@ public: return !(*this == rhs); } - /// Convert to pointer operator. + /// Convert to bool operator. /// - /// This allows code to check a Mangled object to see if it contains a valid - /// mangled name using code such as: + /// This allows code to check any Mangled objects to see if they contain + /// anything valid using code such as: /// /// \code /// Mangled mangled(...); @@ -84,25 +84,9 @@ public: /// \endcode /// /// \return - /// A pointer to this object if either the mangled or unmangled - /// name is set, NULL otherwise. - operator void *() const; - - /// Logical NOT operator. - /// - /// This allows code to check a Mangled object to see if it contains an - /// empty mangled name using code such as: - /// - /// \code - /// Mangled mangled(...); - /// if (!mangled) - /// { ... - /// \endcode - /// - /// \return - /// Returns \b true if the object has an empty mangled and - /// unmangled name, \b false otherwise. - bool operator!() const; + /// Returns \b true if either the mangled or unmangled name is set, + /// \b false if the object has an empty mangled and unmangled name. + explicit operator bool() const; /// Clear the mangled and demangled values. void Clear(); @@ -199,8 +183,6 @@ public: /// /// \return /// The number of bytes that this object occupies in memory. - /// - /// \see ConstString::StaticMemorySize () size_t MemorySize() const; /// Set the string value in this object. diff --git a/lldb/include/lldb/Core/Module.h b/lldb/include/lldb/Core/Module.h index 6b1e4f8f3704..f6c32586eda8 100644 --- a/lldb/include/lldb/Core/Module.h +++ b/lldb/include/lldb/Core/Module.h @@ -905,7 +905,7 @@ public: /// correctly. class LookupInfo { public: - LookupInfo() : m_name(), m_lookup_name() {} + LookupInfo() {} LookupInfo(ConstString name, lldb::FunctionNameType name_type_mask, lldb::LanguageType language); @@ -1047,11 +1047,11 @@ protected: /// We store a symbol table parse time duration here because we might have /// an object file and a symbol file which both have symbol tables. The parse /// time for the symbol tables can be aggregated here. - StatsDuration m_symtab_parse_time{0.0}; + StatsDuration m_symtab_parse_time; /// We store a symbol named index time duration here because we might have /// an object file and a symbol file which both have symbol tables. The parse /// time for the symbol tables can be aggregated here. - StatsDuration m_symtab_index_time{0.0}; + StatsDuration m_symtab_index_time; /// Resolve a file or load virtual address. /// diff --git a/lldb/include/lldb/Core/ModuleSpec.h b/lldb/include/lldb/Core/ModuleSpec.h index 8e5deebbab9a..bcf4ec30a673 100644 --- a/lldb/include/lldb/Core/ModuleSpec.h +++ b/lldb/include/lldb/Core/ModuleSpec.h @@ -25,18 +25,14 @@ namespace lldb_private { class ModuleSpec { public: - ModuleSpec() - : m_file(), m_platform_file(), m_symbol_file(), m_arch(), m_uuid(), - m_object_name(), m_source_mappings() {} + ModuleSpec() {} /// If the \c data argument is passed, its contents will be used /// as the module contents instead of trying to read them from /// \c file_spec . ModuleSpec(const FileSpec &file_spec, const UUID &uuid = UUID(), lldb::DataBufferSP data = lldb::DataBufferSP()) - : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(), - m_uuid(uuid), m_object_name(), m_object_offset(0), m_source_mappings(), - m_data(data) { + : m_file(file_spec), m_uuid(uuid), m_object_offset(0), m_data(data) { if (data) m_object_size = data->GetByteSize(); else if (m_file) @@ -44,10 +40,8 @@ public: } ModuleSpec(const FileSpec &file_spec, const ArchSpec &arch) - : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(arch), - m_uuid(), m_object_name(), m_object_offset(0), - m_object_size(FileSystem::Instance().GetByteSize(file_spec)), - m_source_mappings() {} + : m_file(file_spec), m_arch(arch), m_object_offset(0), + m_object_size(FileSystem::Instance().GetByteSize(file_spec)) {} FileSpec *GetFileSpecPtr() { return (m_file ? &m_file : nullptr); } @@ -279,9 +273,9 @@ protected: class ModuleSpecList { public: - ModuleSpecList() : m_specs(), m_mutex() {} + ModuleSpecList() {} - ModuleSpecList(const ModuleSpecList &rhs) : m_specs(), m_mutex() { + ModuleSpecList(const ModuleSpecList &rhs) { std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex); std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex); m_specs = rhs.m_specs; diff --git a/lldb/include/lldb/Core/StructuredDataImpl.h b/lldb/include/lldb/Core/StructuredDataImpl.h index 8930ebff8166..355aa77c4e5c 100644 --- a/lldb/include/lldb/Core/StructuredDataImpl.h +++ b/lldb/include/lldb/Core/StructuredDataImpl.h @@ -25,7 +25,7 @@ namespace lldb_private { class StructuredDataImpl { public: - StructuredDataImpl() : m_plugin_wp(), m_data_sp() {} + StructuredDataImpl() {} StructuredDataImpl(const StructuredDataImpl &rhs) = default; diff --git a/lldb/include/lldb/Core/ThreadSafeValue.h b/lldb/include/lldb/Core/ThreadSafeValue.h index 51820ec9cd9d..979f008b3170 100644 --- a/lldb/include/lldb/Core/ThreadSafeValue.h +++ b/lldb/include/lldb/Core/ThreadSafeValue.h @@ -18,7 +18,7 @@ namespace lldb_private { template <class T> class ThreadSafeValue { public: ThreadSafeValue() = default; - ThreadSafeValue(const T &value) : m_value(value), m_mutex() {} + ThreadSafeValue(const T &value) : m_value(value) {} ~ThreadSafeValue() = default; diff --git a/lldb/include/lldb/Core/UniqueCStringMap.h b/lldb/include/lldb/Core/UniqueCStringMap.h index e37027a0150a..9c8b8081d374 100644 --- a/lldb/include/lldb/Core/UniqueCStringMap.h +++ b/lldb/include/lldb/Core/UniqueCStringMap.h @@ -165,7 +165,21 @@ public: // my_map.Append (UniqueCStringMap::Entry(GetName(...), GetValue(...))); // } // my_map.Sort(); - void Sort() { llvm::sort(m_map.begin(), m_map.end(), Compare()); } + void Sort() { + Sort([](const T &, const T &) { return false; }); + } + + /// Sort contents of this map using the provided comparator to break ties for + /// entries with the same string value. + template <typename TCompare> void Sort(TCompare tc) { + Compare c; + llvm::sort(m_map, [&](const Entry &lhs, const Entry &rhs) -> bool { + int result = c.ThreeWay(lhs.cstring, rhs.cstring); + if (result == 0) + return tc(lhs.value, rhs.value); + return result < 0; + }); + } // Since we are using a vector to contain our items it will always double its // memory consumption as things are added to the vector, so if you intend to @@ -205,13 +219,24 @@ protected: return operator()(lhs, rhs.cstring); } + bool operator()(ConstString lhs, ConstString rhs) { + return ThreeWay(lhs, rhs) < 0; + } + // This is only for uniqueness, not lexicographical ordering, so we can // just compare pointers. *However*, comparing pointers from different // allocations is UB, so we need compare their integral values instead. - bool operator()(ConstString lhs, ConstString rhs) { - return uintptr_t(lhs.GetCString()) < uintptr_t(rhs.GetCString()); + int ThreeWay(ConstString lhs, ConstString rhs) { + auto lhsint = uintptr_t(lhs.GetCString()); + auto rhsint = uintptr_t(rhs.GetCString()); + if (lhsint < rhsint) + return -1; + if (lhsint > rhsint) + return 1; + return 0; } }; + collection m_map; }; diff --git a/lldb/include/lldb/Core/Value.h b/lldb/include/lldb/Core/Value.h index 1ee4fe639e6e..9f00a14251e2 100644 --- a/lldb/include/lldb/Core/Value.h +++ b/lldb/include/lldb/Core/Value.h @@ -156,7 +156,7 @@ protected: class ValueList { public: - ValueList() : m_values() {} + ValueList() {} ValueList(const ValueList &rhs); diff --git a/lldb/include/lldb/Core/ValueObject.h b/lldb/include/lldb/Core/ValueObject.h index 192149f05436..dac7aac06246 100644 --- a/lldb/include/lldb/Core/ValueObject.h +++ b/lldb/include/lldb/Core/ValueObject.h @@ -795,7 +795,7 @@ protected: class ChildrenManager { public: - ChildrenManager() : m_mutex(), m_children() {} + ChildrenManager() {} bool HasChildAtIndex(size_t idx) { std::lock_guard<std::recursive_mutex> guard(m_mutex); diff --git a/lldb/include/lldb/DataFormatters/FormatClasses.h b/lldb/include/lldb/DataFormatters/FormatClasses.h index b8540de3d740..2b47bcdf3a69 100644 --- a/lldb/include/lldb/DataFormatters/FormatClasses.h +++ b/lldb/include/lldb/DataFormatters/FormatClasses.h @@ -105,23 +105,23 @@ private: class TypeNameSpecifierImpl { public: - TypeNameSpecifierImpl() : m_type() {} + TypeNameSpecifierImpl() {} TypeNameSpecifierImpl(llvm::StringRef name, bool is_regex) - : m_is_regex(is_regex), m_type() { + : m_is_regex(is_regex) { m_type.m_type_name = std::string(name); } // if constructing with a given type, is_regex cannot be true since we are // giving an exact type to match - TypeNameSpecifierImpl(lldb::TypeSP type) : m_is_regex(false), m_type() { + TypeNameSpecifierImpl(lldb::TypeSP type) : m_is_regex(false) { if (type) { m_type.m_type_name = std::string(type->GetName().GetStringRef()); m_type.m_compiler_type = type->GetForwardCompilerType(); } } - TypeNameSpecifierImpl(CompilerType type) : m_is_regex(false), m_type() { + TypeNameSpecifierImpl(CompilerType type) : m_is_regex(false) { if (type.IsValid()) { m_type.m_type_name.assign(type.GetTypeName().GetCString()); m_type.m_compiler_type = type; diff --git a/lldb/include/lldb/DataFormatters/TypeSynthetic.h b/lldb/include/lldb/DataFormatters/TypeSynthetic.h index 24322bd51a0c..3f58297a529b 100644 --- a/lldb/include/lldb/DataFormatters/TypeSynthetic.h +++ b/lldb/include/lldb/DataFormatters/TypeSynthetic.h @@ -279,11 +279,11 @@ class TypeFilterImpl : public SyntheticChildren { public: TypeFilterImpl(const SyntheticChildren::Flags &flags) - : SyntheticChildren(flags), m_expression_paths() {} + : SyntheticChildren(flags) {} TypeFilterImpl(const SyntheticChildren::Flags &flags, const std::initializer_list<const char *> items) - : SyntheticChildren(flags), m_expression_paths() { + : SyntheticChildren(flags) { for (auto path : items) AddExpressionPath(path); } @@ -391,7 +391,7 @@ class ScriptedSyntheticChildren : public SyntheticChildren { public: ScriptedSyntheticChildren(const SyntheticChildren::Flags &flags, const char *pclass, const char *pcode = nullptr) - : SyntheticChildren(flags), m_python_class(), m_python_code() { + : SyntheticChildren(flags) { if (pclass) m_python_class = pclass; if (pcode) diff --git a/lldb/include/lldb/Expression/IRExecutionUnit.h b/lldb/include/lldb/Expression/IRExecutionUnit.h index bb43851e17c9..ef53ca512d75 100644 --- a/lldb/include/lldb/Expression/IRExecutionUnit.h +++ b/lldb/include/lldb/Expression/IRExecutionUnit.h @@ -347,10 +347,9 @@ private: AllocationRecord(uintptr_t host_address, uint32_t permissions, lldb::SectionType sect_type, size_t size, unsigned alignment, unsigned section_id, const char *name) - : m_name(), m_process_address(LLDB_INVALID_ADDRESS), - m_host_address(host_address), m_permissions(permissions), - m_sect_type(sect_type), m_size(size), m_alignment(alignment), - m_section_id(section_id) { + : m_process_address(LLDB_INVALID_ADDRESS), m_host_address(host_address), + m_permissions(permissions), m_sect_type(sect_type), m_size(size), + m_alignment(alignment), m_section_id(section_id) { if (name && name[0]) m_name = name; } diff --git a/lldb/include/lldb/Host/Debug.h b/lldb/include/lldb/Host/Debug.h index 7da59dd04a66..e4e410474c02 100644 --- a/lldb/include/lldb/Host/Debug.h +++ b/lldb/include/lldb/Host/Debug.h @@ -32,15 +32,13 @@ struct ResumeAction { // send a signal to the thread when the action is run or step. class ResumeActionList { public: - ResumeActionList() : m_actions(), m_signal_handled() {} + ResumeActionList() {} - ResumeActionList(lldb::StateType default_action, int signal) - : m_actions(), m_signal_handled() { + ResumeActionList(lldb::StateType default_action, int signal) { SetDefaultThreadActionIfNeeded(default_action, signal); } - ResumeActionList(const ResumeAction *actions, size_t num_actions) - : m_actions(), m_signal_handled() { + ResumeActionList(const ResumeAction *actions, size_t num_actions) { if (actions && num_actions) { m_actions.assign(actions, actions + num_actions); m_signal_handled.assign(num_actions, false); diff --git a/lldb/include/lldb/Host/FileSystem.h b/lldb/include/lldb/Host/FileSystem.h index 54f7ac5ddb58..9f863e8a9d7e 100644 --- a/lldb/include/lldb/Host/FileSystem.h +++ b/lldb/include/lldb/Host/FileSystem.h @@ -31,16 +31,13 @@ public: static const char *DEV_NULL; static const char *PATH_CONVERSION_ERROR; - FileSystem() - : m_fs(llvm::vfs::getRealFileSystem()), m_collector(nullptr), - m_home_directory() {} + FileSystem() : m_fs(llvm::vfs::getRealFileSystem()), m_collector(nullptr) {} FileSystem(std::shared_ptr<llvm::FileCollectorBase> collector) : m_fs(llvm::vfs::getRealFileSystem()), m_collector(std::move(collector)), - m_home_directory(), m_mapped(false) {} + m_mapped(false) {} FileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs, bool mapped = false) - : m_fs(std::move(fs)), m_collector(nullptr), m_home_directory(), - m_mapped(mapped) {} + : m_fs(std::move(fs)), m_collector(nullptr), m_mapped(mapped) {} FileSystem(const FileSystem &fs) = delete; FileSystem &operator=(const FileSystem &fs) = delete; diff --git a/lldb/include/lldb/Host/HostNativeThreadBase.h b/lldb/include/lldb/Host/HostNativeThreadBase.h index bfd70d745593..1c581c279e1e 100644 --- a/lldb/include/lldb/Host/HostNativeThreadBase.h +++ b/lldb/include/lldb/Host/HostNativeThreadBase.h @@ -46,7 +46,7 @@ protected: ThreadCreateTrampoline(lldb::thread_arg_t arg); lldb::thread_t m_thread = LLDB_INVALID_HOST_THREAD; - lldb::thread_result_t m_result = 0; + lldb::thread_result_t m_result = 0; // NOLINT(modernize-use-nullptr) }; } diff --git a/lldb/include/lldb/Host/XML.h b/lldb/include/lldb/Host/XML.h index 9edf46bf09df..da0f9cd7aa8c 100644 --- a/lldb/include/lldb/Host/XML.h +++ b/lldb/include/lldb/Host/XML.h @@ -76,8 +76,8 @@ public: XMLNode GetChild() const; - llvm::StringRef GetAttributeValue(const char *name, - const char *fail_value = nullptr) const; + std::string GetAttributeValue(const char *name, + const char *fail_value = nullptr) const; bool GetAttributeValueAsUnsigned(const char *name, uint64_t &value, uint64_t fail_value = 0, int base = 0) const; diff --git a/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/lldb/include/lldb/Host/common/NativeProcessProtocol.h index 7c3458527616..c7494ba6b195 100644 --- a/lldb/include/lldb/Host/common/NativeProcessProtocol.h +++ b/lldb/include/lldb/Host/common/NativeProcessProtocol.h @@ -204,7 +204,7 @@ public: void SetCurrentThreadID(lldb::tid_t tid) { m_current_thread_id = tid; } - lldb::tid_t GetCurrentThreadID() { return m_current_thread_id; } + lldb::tid_t GetCurrentThreadID() const { return m_current_thread_id; } NativeThreadProtocol *GetCurrentThread() { return GetThreadByID(m_current_thread_id); @@ -251,8 +251,9 @@ public: libraries_svr4 = (1u << 5), memory_tagging = (1u << 6), savecore = (1u << 7), + siginfo_read = (1u << 8), - LLVM_MARK_AS_BITMASK_ENUM(savecore) + LLVM_MARK_AS_BITMASK_ENUM(siginfo_read) }; class Factory { diff --git a/lldb/include/lldb/Host/common/NativeThreadProtocol.h b/lldb/include/lldb/Host/common/NativeThreadProtocol.h index 5cf26bd95939..35ccc48d62d8 100644 --- a/lldb/include/lldb/Host/common/NativeThreadProtocol.h +++ b/lldb/include/lldb/Host/common/NativeThreadProtocol.h @@ -12,9 +12,13 @@ #include <memory> #include "lldb/Host/Debug.h" +#include "lldb/Utility/UnimplementedError.h" #include "lldb/lldb-private-forward.h" #include "lldb/lldb-types.h" +#include "llvm/Support/Error.h" +#include "llvm/Support/MemoryBuffer.h" + namespace lldb_private { // NativeThreadProtocol class NativeThreadProtocol { @@ -47,6 +51,11 @@ public: virtual Status RemoveHardwareBreakpoint(lldb::addr_t addr) = 0; + virtual llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> + GetSiginfo() const { + return llvm::make_error<UnimplementedError>(); + } + protected: NativeProcessProtocol &m_process; lldb::tid_t m_tid; diff --git a/lldb/include/lldb/Interpreter/CommandInterpreter.h b/lldb/include/lldb/Interpreter/CommandInterpreter.h index e6f0d5f9c4d4..3efb59fc0564 100644 --- a/lldb/include/lldb/Interpreter/CommandInterpreter.h +++ b/lldb/include/lldb/Interpreter/CommandInterpreter.h @@ -649,7 +649,7 @@ private: void FindCommandsForApropos(llvm::StringRef word, StringList &commands_found, StringList &commands_help, - CommandObject::CommandMap &command_map); + const CommandObject::CommandMap &command_map); // An interruptible wrapper around the stream output void PrintCommandOutput(Stream &stream, llvm::StringRef str); diff --git a/lldb/include/lldb/Interpreter/CommandObject.h b/lldb/include/lldb/Interpreter/CommandObject.h index 89cc161993a9..bfddf559e5fe 100644 --- a/lldb/include/lldb/Interpreter/CommandObject.h +++ b/lldb/include/lldb/Interpreter/CommandObject.h @@ -172,11 +172,6 @@ public: return nullptr; } - virtual void AproposAllSubCommands(llvm::StringRef prefix, - llvm::StringRef search_word, - StringList &commands_found, - StringList &commands_help) {} - void FormatLongHelpText(Stream &output_strm, llvm::StringRef long_help); void GenerateHelpText(CommandReturnObject &result); diff --git a/lldb/include/lldb/Interpreter/CommandObjectMultiword.h b/lldb/include/lldb/Interpreter/CommandObjectMultiword.h index a0e8d163c4b6..ab580c11eb4f 100644 --- a/lldb/include/lldb/Interpreter/CommandObjectMultiword.h +++ b/lldb/include/lldb/Interpreter/CommandObjectMultiword.h @@ -51,11 +51,6 @@ public: CommandObject *GetSubcommandObject(llvm::StringRef sub_cmd, StringList *matches = nullptr) override; - void AproposAllSubCommands(llvm::StringRef prefix, - llvm::StringRef search_word, - StringList &commands_found, - StringList &commands_help) override; - bool WantsRawCommandString() override { return false; } void HandleCompletion(CompletionRequest &request) override; @@ -110,11 +105,6 @@ public: CommandObject *GetSubcommandObject(llvm::StringRef sub_cmd, StringList *matches = nullptr) override; - void AproposAllSubCommands(llvm::StringRef prefix, - llvm::StringRef search_word, - StringList &commands_found, - StringList &commands_help) override; - bool LoadSubCommand(llvm::StringRef cmd_name, const lldb::CommandObjectSP &command_obj) override; diff --git a/lldb/include/lldb/Interpreter/OptionValueArray.h b/lldb/include/lldb/Interpreter/OptionValueArray.h index 011eefc34251..af43887635e9 100644 --- a/lldb/include/lldb/Interpreter/OptionValueArray.h +++ b/lldb/include/lldb/Interpreter/OptionValueArray.h @@ -18,7 +18,7 @@ namespace lldb_private { class OptionValueArray : public Cloneable<OptionValueArray, OptionValue> { public: OptionValueArray(uint32_t type_mask = UINT32_MAX, bool raw_value_dump = false) - : m_type_mask(type_mask), m_values(), m_raw_value_dump(raw_value_dump) {} + : m_type_mask(type_mask), m_raw_value_dump(raw_value_dump) {} ~OptionValueArray() override = default; diff --git a/lldb/include/lldb/Interpreter/OptionValueProperties.h b/lldb/include/lldb/Interpreter/OptionValueProperties.h index 6fa5403ac142..3e5685b7f0bf 100644 --- a/lldb/include/lldb/Interpreter/OptionValueProperties.h +++ b/lldb/include/lldb/Interpreter/OptionValueProperties.h @@ -114,6 +114,9 @@ public: GetPropertyAtIndexAsOptionValueLanguage(const ExecutionContext *exe_ctx, uint32_t idx) const; + bool SetPropertyAtIndexAsLanguage(const ExecutionContext *exe_ctx, + uint32_t idx, lldb::LanguageType lang); + bool GetPropertyAtIndexAsArgs(const ExecutionContext *exe_ctx, uint32_t idx, Args &args) const; diff --git a/lldb/include/lldb/Interpreter/Options.h b/lldb/include/lldb/Interpreter/Options.h index 6bf5c21fe98e..5899a9edc47f 100644 --- a/lldb/include/lldb/Interpreter/Options.h +++ b/lldb/include/lldb/Interpreter/Options.h @@ -169,7 +169,7 @@ public: /// user wants returned. /// /// \return - /// \btrue if we were in an option, \bfalse otherwise. + /// \b true if we were in an option, \b false otherwise. bool HandleOptionCompletion(lldb_private::CompletionRequest &request, OptionElementVector &option_map, CommandInterpreter &interpreter); diff --git a/lldb/include/lldb/Interpreter/ScriptedInterface.h b/lldb/include/lldb/Interpreter/ScriptedInterface.h index 427fa3f4f793..9de5e60cfea3 100644 --- a/lldb/include/lldb/Interpreter/ScriptedInterface.h +++ b/lldb/include/lldb/Interpreter/ScriptedInterface.h @@ -27,12 +27,13 @@ public: virtual StructuredData::GenericSP CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, - StructuredData::DictionarySP args_sp) = 0; + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) = 0; template <typename Ret> - Ret ErrorWithMessage(llvm::StringRef caller_name, llvm::StringRef error_msg, - Status &error, - uint32_t log_caterogy = LIBLLDB_LOG_PROCESS) { + static Ret ErrorWithMessage(llvm::StringRef caller_name, + llvm::StringRef error_msg, Status &error, + LLDBLog log_caterogy = LLDBLog::Process) { LLDB_LOGF(GetLogIfAllCategoriesSet(log_caterogy), "%s ERROR = %s", caller_name.data(), error_msg.data()); error.SetErrorString(llvm::Twine(caller_name + llvm::Twine(" ERROR = ") + diff --git a/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h b/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h index 26fd956f96bb..0712b3bf4a3e 100644 --- a/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h +++ b/lldb/include/lldb/Interpreter/ScriptedProcessInterface.h @@ -23,7 +23,8 @@ class ScriptedProcessInterface : virtual public ScriptedInterface { public: StructuredData::GenericSP CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, - StructuredData::DictionarySP args_sp) override { + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override { return nullptr; } @@ -41,6 +42,8 @@ public: return {}; } + virtual StructuredData::DictionarySP GetThreadsInfo() { return nullptr; } + virtual StructuredData::DictionarySP GetThreadWithID(lldb::tid_t tid) { return nullptr; } @@ -66,18 +69,17 @@ public: protected: friend class ScriptedThread; - virtual lldb::ScriptedThreadInterfaceSP GetScriptedThreadInterface() { + virtual lldb::ScriptedThreadInterfaceSP CreateScriptedThreadInterface() { return nullptr; } - - lldb::ScriptedThreadInterfaceSP m_scripted_thread_interface_sp = nullptr; }; class ScriptedThreadInterface : virtual public ScriptedInterface { public: StructuredData::GenericSP CreatePluginObject(llvm::StringRef class_name, ExecutionContext &exe_ctx, - StructuredData::DictionarySP args_sp) override { + StructuredData::DictionarySP args_sp, + StructuredData::Generic *script_obj = nullptr) override { return nullptr; } diff --git a/lldb/include/lldb/Symbol/CompactUnwindInfo.h b/lldb/include/lldb/Symbol/CompactUnwindInfo.h index ceb501e1c05f..402155cbe08d 100644 --- a/lldb/include/lldb/Symbol/CompactUnwindInfo.h +++ b/lldb/include/lldb/Symbol/CompactUnwindInfo.h @@ -86,7 +86,7 @@ private: // valid for (start of the function) uint32_t valid_range_offset_end = 0; // the offset of the start of the next function - FunctionInfo() : lsda_address(), personality_ptr_address() {} + FunctionInfo() {} }; struct UnwindHeader { diff --git a/lldb/include/lldb/Symbol/CompileUnit.h b/lldb/include/lldb/Symbol/CompileUnit.h index 34e34e5514df..44e1d673f1fd 100644 --- a/lldb/include/lldb/Symbol/CompileUnit.h +++ b/lldb/include/lldb/Symbol/CompileUnit.h @@ -208,9 +208,9 @@ public: /// unit file. /// /// \param[in] exact - /// If \btrue match only if there is a line table entry for this line + /// If \b true match only if there is a line table entry for this line /// number. - /// If \bfalse, find the line table entry equal to or after this line + /// If \b false, find the line table entry equal to or after this line /// number. /// /// \param[out] line_entry diff --git a/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h b/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h index f85bc7e844a0..43baf4dd39a1 100644 --- a/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h +++ b/lldb/include/lldb/Symbol/DWARFCallFrameInfo.h @@ -107,7 +107,7 @@ private: : cie_offset(offset), version(-1), code_align(0), data_align(0), return_addr_reg_num(LLDB_INVALID_REGNUM), inst_offset(0), inst_length(0), ptr_encoding(0), lsda_addr_encoding(DW_EH_PE_omit), - personality_loc(LLDB_INVALID_ADDRESS), initial_row() {} + personality_loc(LLDB_INVALID_ADDRESS) {} }; typedef std::shared_ptr<CIE> CIESP; diff --git a/lldb/include/lldb/Symbol/Function.h b/lldb/include/lldb/Symbol/Function.h index b703617773ff..83f9979c3c52 100644 --- a/lldb/include/lldb/Symbol/Function.h +++ b/lldb/include/lldb/Symbol/Function.h @@ -110,8 +110,6 @@ public: /// The number of bytes that this object occupies in memory. /// The returned value does not include the bytes for any /// shared string values. - /// - /// \see ConstString::StaticMemorySize () virtual size_t MemorySize() const; protected: @@ -238,8 +236,6 @@ public: /// The number of bytes that this object occupies in memory. /// The returned value does not include the bytes for any /// shared string values. - /// - /// \see ConstString::StaticMemorySize () size_t MemorySize() const override; private: @@ -595,8 +591,6 @@ public: /// The number of bytes that this object occupies in memory. /// The returned value does not include the bytes for any /// shared string values. - /// - /// \see ConstString::StaticMemorySize () size_t MemorySize() const; /// Get whether compiler optimizations were enabled for this function diff --git a/lldb/include/lldb/Symbol/LineTable.h b/lldb/include/lldb/Symbol/LineTable.h index 5cd22bd831ee..b5121b29fe02 100644 --- a/lldb/include/lldb/Symbol/LineTable.h +++ b/lldb/include/lldb/Symbol/LineTable.h @@ -206,7 +206,6 @@ public: LineTable *LinkLineTable(const FileRangeMap &file_range_map); -protected: struct Entry { Entry() : line(0), is_start_of_statement(false), is_start_of_basic_block(false), @@ -303,6 +302,7 @@ protected: uint16_t file_idx = 0; }; +protected: struct EntrySearchInfo { LineTable *line_table; lldb_private::Section *a_section; diff --git a/lldb/include/lldb/Symbol/ObjectContainer.h b/lldb/include/lldb/Symbol/ObjectContainer.h index 1e01e93da9d2..4f0c73693295 100644 --- a/lldb/include/lldb/Symbol/ObjectContainer.h +++ b/lldb/include/lldb/Symbol/ObjectContainer.h @@ -39,7 +39,7 @@ public: lldb::DataBufferSP &data_sp, lldb::offset_t data_offset) : ModuleChild(module_sp), m_file(), // This file can be different than the module's file spec - m_offset(file_offset), m_length(length), m_data() { + m_offset(file_offset), m_length(length) { if (file) m_file = *file; if (data_sp) diff --git a/lldb/include/lldb/Symbol/SymbolFile.h b/lldb/include/lldb/Symbol/SymbolFile.h index 7c0365483c12..6cdb2bfb686b 100644 --- a/lldb/include/lldb/Symbol/SymbolFile.h +++ b/lldb/include/lldb/Symbol/SymbolFile.h @@ -67,8 +67,7 @@ public: // Constructors and Destructors SymbolFile(lldb::ObjectFileSP objfile_sp) - : m_objfile_sp(std::move(objfile_sp)), m_abilities(0), - m_calculated_abilities(false) {} + : m_objfile_sp(std::move(objfile_sp)) {} ~SymbolFile() override = default; @@ -317,14 +316,37 @@ public: /// /// \returns 0.0 if no information has been parsed or if there is /// no computational cost to parsing the debug information. - virtual StatsDuration GetDebugInfoParseTime() { return StatsDuration(0.0); } + virtual StatsDuration::Duration GetDebugInfoParseTime() { return {}; } /// Return the time it took to index the debug information in the object /// file. /// /// \returns 0.0 if the file doesn't need to be indexed or if it /// hasn't been indexed yet, or a valid duration if it has. - virtual StatsDuration GetDebugInfoIndexTime() { return StatsDuration(0.0); } + virtual StatsDuration::Duration GetDebugInfoIndexTime() { return {}; } + + /// Accessors for the bool that indicates if the debug info index was loaded + /// from, or saved to the module index cache. + /// + /// In statistics it is handy to know if a module's debug info was loaded from + /// or saved to the cache. When the debug info index is loaded from the cache + /// startup times can be faster. When the cache is enabled and the debug info + /// index is saved to the cache, debug sessions can be slower. These accessors + /// can be accessed by the statistics and emitted to help track these costs. + /// \{ + bool GetDebugInfoIndexWasLoadedFromCache() const { + return m_index_was_loaded_from_cache; + } + void SetDebugInfoIndexWasLoadedFromCache() { + m_index_was_loaded_from_cache = true; + } + bool GetDebugInfoIndexWasSavedToCache() const { + return m_index_was_saved_to_cache; + } + void SetDebugInfoIndexWasSavedToCache() { + m_index_was_saved_to_cache = true; + } + /// \} protected: void AssertModuleLock(); @@ -341,8 +363,10 @@ protected: llvm::Optional<std::vector<lldb::CompUnitSP>> m_compile_units; TypeList m_type_list; Symtab *m_symtab = nullptr; - uint32_t m_abilities; - bool m_calculated_abilities; + uint32_t m_abilities = 0; + bool m_calculated_abilities = false; + bool m_index_was_loaded_from_cache = false; + bool m_index_was_saved_to_cache = false; private: SymbolFile(const SymbolFile &) = delete; diff --git a/lldb/include/lldb/Symbol/Symtab.h b/lldb/include/lldb/Symbol/Symtab.h index fe0a82306c4f..504b49c02674 100644 --- a/lldb/include/lldb/Symbol/Symtab.h +++ b/lldb/include/lldb/Symbol/Symtab.h @@ -212,6 +212,30 @@ public: /// false if the symbol table wasn't cached or was out of date. bool LoadFromCache(); + + /// Accessors for the bool that indicates if the debug info index was loaded + /// from, or saved to the module index cache. + /// + /// In statistics it is handy to know if a module's debug info was loaded from + /// or saved to the cache. When the debug info index is loaded from the cache + /// startup times can be faster. When the cache is enabled and the debug info + /// index is saved to the cache, debug sessions can be slower. These accessors + /// can be accessed by the statistics and emitted to help track these costs. + /// \{ + bool GetWasLoadedFromCache() const { + return m_loaded_from_cache; + } + void SetWasLoadedFromCache() { + m_loaded_from_cache = true; + } + bool GetWasSavedToCache() const { + return m_saved_to_cache; + } + void SetWasSavedToCache() { + m_saved_to_cache = true; + } + /// \} + protected: typedef std::vector<Symbol> collection; typedef collection::iterator iterator; @@ -252,7 +276,8 @@ protected: m_name_to_symbol_indices; mutable std::recursive_mutex m_mutex; // Provide thread safety for this symbol table - bool m_file_addr_to_index_computed : 1, m_name_indexes_computed : 1; + bool m_file_addr_to_index_computed : 1, m_name_indexes_computed : 1, + m_loaded_from_cache : 1, m_saved_to_cache : 1; private: UniqueCStringMap<uint32_t> & diff --git a/lldb/include/lldb/Symbol/Type.h b/lldb/include/lldb/Symbol/Type.h index 7754e0299096..24b94921df94 100644 --- a/lldb/include/lldb/Symbol/Type.h +++ b/lldb/include/lldb/Symbol/Type.h @@ -314,7 +314,7 @@ private: class TypeListImpl { public: - TypeListImpl() : m_content() {} + TypeListImpl() {} void Append(const lldb::TypeImplSP &type) { m_content.push_back(type); } @@ -345,10 +345,7 @@ private: class TypeMemberImpl { public: - TypeMemberImpl() - : m_type_impl_sp(), m_name() - - {} + TypeMemberImpl() {} TypeMemberImpl(const lldb::TypeImplSP &type_impl_sp, uint64_t bit_offset, ConstString name, uint32_t bitfield_bit_size = 0, @@ -357,7 +354,7 @@ public: m_bitfield_bit_size(bitfield_bit_size), m_is_bitfield(is_bitfield) {} TypeMemberImpl(const lldb::TypeImplSP &type_impl_sp, uint64_t bit_offset) - : m_type_impl_sp(type_impl_sp), m_bit_offset(bit_offset), m_name(), + : m_type_impl_sp(type_impl_sp), m_bit_offset(bit_offset), m_bitfield_bit_size(0), m_is_bitfield(false) { if (m_type_impl_sp) m_name = m_type_impl_sp->GetName(); @@ -440,7 +437,7 @@ private: class TypeMemberFunctionImpl { public: - TypeMemberFunctionImpl() : m_type(), m_decl(), m_name() {} + TypeMemberFunctionImpl() {} TypeMemberFunctionImpl(const CompilerType &type, const CompilerDecl &decl, const std::string &name, @@ -477,7 +474,7 @@ private: class TypeEnumMemberImpl { public: - TypeEnumMemberImpl() : m_integer_type_sp(), m_name("<invalid>"), m_value() {} + TypeEnumMemberImpl() : m_name("<invalid>") {} TypeEnumMemberImpl(const lldb::TypeImplSP &integer_type_sp, ConstString name, const llvm::APSInt &value); @@ -505,7 +502,7 @@ protected: class TypeEnumMemberListImpl { public: - TypeEnumMemberListImpl() : m_content() {} + TypeEnumMemberListImpl() {} void Append(const lldb::TypeEnumMemberImplSP &type) { m_content.push_back(type); diff --git a/lldb/include/lldb/Symbol/UnwindPlan.h b/lldb/include/lldb/Symbol/UnwindPlan.h index cc2302d25831..ebb0ec421da7 100644 --- a/lldb/include/lldb/Symbol/UnwindPlan.h +++ b/lldb/include/lldb/Symbol/UnwindPlan.h @@ -395,12 +395,10 @@ public: typedef std::shared_ptr<Row> RowSP; UnwindPlan(lldb::RegisterKind reg_kind) - : m_row_list(), m_plan_valid_address_range(), m_register_kind(reg_kind), - m_return_addr_register(LLDB_INVALID_REGNUM), m_source_name(), + : m_register_kind(reg_kind), m_return_addr_register(LLDB_INVALID_REGNUM), m_plan_is_sourced_from_compiler(eLazyBoolCalculate), m_plan_is_valid_at_all_instruction_locations(eLazyBoolCalculate), - m_plan_is_for_signal_trap(eLazyBoolCalculate), - m_lsda_address(), m_personality_func_addr() {} + m_plan_is_for_signal_trap(eLazyBoolCalculate) {} // Performs a deep copy of the plan, including all the rows (expensive). UnwindPlan(const UnwindPlan &rhs) @@ -442,7 +440,7 @@ public: m_return_addr_register = regnum; } - uint32_t GetReturnAddressRegister(void) { return m_return_addr_register; } + uint32_t GetReturnAddressRegister() { return m_return_addr_register; } uint32_t GetInitialCFARegister() const { if (m_row_list.empty()) diff --git a/lldb/include/lldb/Target/InstrumentationRuntime.h b/lldb/include/lldb/Target/InstrumentationRuntime.h index eeec91f36af4..a6121c24b956 100644 --- a/lldb/include/lldb/Target/InstrumentationRuntime.h +++ b/lldb/include/lldb/Target/InstrumentationRuntime.h @@ -42,8 +42,7 @@ class InstrumentationRuntime protected: InstrumentationRuntime(const lldb::ProcessSP &process_sp) - : m_process_wp(), m_runtime_module(), m_breakpoint_id(0), - m_is_active(false) { + : m_breakpoint_id(0), m_is_active(false) { if (process_sp) m_process_wp = process_sp; } diff --git a/lldb/include/lldb/Target/Language.h b/lldb/include/lldb/Target/Language.h index 0b0891c14029..ce2d273a8277 100644 --- a/lldb/include/lldb/Target/Language.h +++ b/lldb/include/lldb/Target/Language.h @@ -57,8 +57,7 @@ public: class ImageListTypeScavenger : public TypeScavenger { class Result : public Language::TypeScavenger::Result { public: - Result(CompilerType type) - : Language::TypeScavenger::Result(), m_compiler_type(type) {} + Result(CompilerType type) : m_compiler_type(type) {} bool IsValid() override { return m_compiler_type.IsValid(); } @@ -95,7 +94,7 @@ public: template <typename... ScavengerTypes> class EitherTypeScavenger : public TypeScavenger { public: - EitherTypeScavenger() : TypeScavenger(), m_scavengers() { + EitherTypeScavenger() : TypeScavenger() { for (std::shared_ptr<TypeScavenger> scavenger : { std::shared_ptr<TypeScavenger>(new ScavengerTypes())... }) { if (scavenger) m_scavengers.push_back(scavenger); @@ -118,7 +117,7 @@ public: template <typename... ScavengerTypes> class UnionTypeScavenger : public TypeScavenger { public: - UnionTypeScavenger() : TypeScavenger(), m_scavengers() { + UnionTypeScavenger() : TypeScavenger() { for (std::shared_ptr<TypeScavenger> scavenger : { std::shared_ptr<TypeScavenger>(new ScavengerTypes())... }) { if (scavenger) m_scavengers.push_back(scavenger); diff --git a/lldb/include/lldb/Target/MemoryTagManager.h b/lldb/include/lldb/Target/MemoryTagManager.h index a5e0deba14a9..859c43cb437a 100644 --- a/lldb/include/lldb/Target/MemoryTagManager.h +++ b/lldb/include/lldb/Target/MemoryTagManager.h @@ -35,8 +35,8 @@ public: // you get will have been shifted down 56 before being returned. virtual lldb::addr_t GetLogicalTag(lldb::addr_t addr) const = 0; - // Remove non address bits from a pointer - virtual lldb::addr_t RemoveNonAddressBits(lldb::addr_t addr) const = 0; + // Remove tag bits from a pointer + virtual lldb::addr_t RemoveTagBits(lldb::addr_t addr) const = 0; // Return the difference between two addresses, ignoring any logical tags they // have. If your tags are just part of a larger set of ignored bits, this @@ -64,7 +64,7 @@ public: // (which may include one or more memory regions) // // If so, return a modified range which will have been expanded - // to be granule aligned. + // to be granule aligned. Otherwise return an error. // // Tags in the input addresses are ignored and not present // in the returned range. @@ -72,6 +72,23 @@ public: lldb::addr_t addr, lldb::addr_t end_addr, const lldb_private::MemoryRegionInfos &memory_regions) const = 0; + // Given a range addr to end_addr, check that end_addr >= addr. + // If it is not, return an error saying so. + // Otherwise, granule align it and return a set of ranges representing + // subsections of the aligned range that have memory tagging enabled. + // + // Basically a sparse version of MakeTaggedRange. Use this when you + // want to know which parts of a larger range have memory tagging. + // + // Regions in memory_regions should be sorted in ascending order and + // not overlap. (use Process GetMemoryRegions) + // + // Tags in the input addresses are ignored and not present + // in the returned ranges. + virtual llvm::Expected<std::vector<TagRange>> MakeTaggedRanges( + lldb::addr_t addr, lldb::addr_t end_addr, + const lldb_private::MemoryRegionInfos &memory_regions) const = 0; + // Return the type value to use in GDB protocol qMemTags packets to read // allocation tags. This is named "Allocation" specifically because the spec // allows for logical tags to be read the same way, though we do not use that. diff --git a/lldb/include/lldb/Target/MemoryTagMap.h b/lldb/include/lldb/Target/MemoryTagMap.h new file mode 100644 index 000000000000..acf3825bfb3f --- /dev/null +++ b/lldb/include/lldb/Target/MemoryTagMap.h @@ -0,0 +1,98 @@ +//===-- MemoryTagMap.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_TARGET_MEMORYTAGMAP_H +#define LLDB_TARGET_MEMORYTAGMAP_H + +#include "lldb/Target/MemoryTagManager.h" +#include "lldb/lldb-private.h" +#include "llvm/ADT/Optional.h" +#include <map> + +namespace lldb_private { + +/// MemoryTagMap provides a way to give a sparse read result +/// when reading memory tags for a range. This is useful when +/// you want to annotate some large memory dump that might include +/// tagged memory but you don't know that it is all tagged. +class MemoryTagMap { +public: + /// Init an empty tag map + /// + /// \param [in] manager + /// Non-null pointer to a memory tag manager. + MemoryTagMap(const MemoryTagManager *manager); + + /// Insert tags into the map starting from addr. + /// + /// \param [in] addr + /// Start address of the range to insert tags for. + /// This address should be granule aligned and have had + /// any non address bits removed. + /// (ideally you would use the base of the range you used + /// to read the tags in the first place) + /// + /// \param [in] tags + /// Vector of tags to insert. The first tag will be inserted + /// at addr, the next at addr+granule size and so on until + /// all tags have been inserted. + void InsertTags(lldb::addr_t addr, const std::vector<lldb::addr_t> tags); + + bool Empty() const; + + /// Lookup memory tags for a range of memory from addr to addr+len. + /// + /// \param [in] addr + /// The start of the range. This may include non address bits and + /// does not have to be granule aligned. + /// + /// \param [in] len + /// The length in bytes of the range to read tags for. This does + /// not need to be multiple of the granule size. + /// + /// \return + /// A vector containing the tags found for the granules in the + /// range. (which is the result of granule aligning the given range) + /// + /// Each item in the vector is an optional tag. Meaning that if + /// it is valid then the granule had a tag and if not, it didn't. + /// + /// If the range had no tags at all, the vector will be empty. + /// If some of the range was tagged it will have items and some + /// of them may be llvm::None. + /// (this saves the caller checking whether all items are llvm::None) + std::vector<llvm::Optional<lldb::addr_t>> GetTags(lldb::addr_t addr, + size_t len) const; + +private: + /// Lookup the tag for address + /// + /// \param [in] address + /// The address to lookup a tag for. This should be aligned + /// to a granule boundary. + /// + /// \return + /// The tag for the granule that address refers to, or llvm::None + /// if it has no memory tag. + llvm::Optional<lldb::addr_t> GetTag(lldb::addr_t addr) const; + + // A map of granule aligned addresses to their memory tag + std::map<lldb::addr_t, lldb::addr_t> m_addr_to_tag; + + // Memory tag manager used to align addresses and get granule size. + // Ideally this would be a const& but only certain architectures will + // have a memory tag manager class to provide here. So for a method + // returning a MemoryTagMap, Optional<MemoryTagMap> allows it to handle + // architectures without memory tagging. Optionals cannot hold references + // so we go with a pointer that we assume will be not be null. + const MemoryTagManager *m_manager; +}; + +} // namespace lldb_private + +#endif // LLDB_TARGET_MEMORYTAGMAP_H diff --git a/lldb/include/lldb/Target/Platform.h b/lldb/include/lldb/Target/Platform.h index 26127359a322..4ef6c9d82b1a 100644 --- a/lldb/include/lldb/Target/Platform.h +++ b/lldb/include/lldb/Target/Platform.h @@ -863,6 +863,8 @@ public: return nullptr; } + virtual CompilerType GetSiginfoType(const llvm::Triple &triple); + protected: /// Create a list of ArchSpecs with the given OS and a architectures. The /// vendor field is left as an "unspecified unknown". @@ -958,7 +960,7 @@ private: class PlatformList { public: - PlatformList() : m_mutex(), m_platforms(), m_selected_platform_sp() {} + PlatformList() {} ~PlatformList() = default; diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index e27cb8cbf2aa..12ed1e09227c 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -112,15 +112,12 @@ protected: class ProcessAttachInfo : public ProcessInstanceInfo { public: - ProcessAttachInfo() - : ProcessInstanceInfo(), m_listener_sp(), m_hijack_listener_sp(), - m_plugin_name() {} + ProcessAttachInfo() {} ProcessAttachInfo(const ProcessLaunchInfo &launch_info) - : ProcessInstanceInfo(), m_listener_sp(), m_hijack_listener_sp(), - m_plugin_name(), m_resume_count(0), m_wait_for_launch(false), - m_ignore_existing(true), m_continue_once_attached(false), - m_detach_on_error(true), m_async(false) { + : m_resume_count(0), m_wait_for_launch(false), m_ignore_existing(true), + m_continue_once_attached(false), m_detach_on_error(true), + m_async(false) { ProcessInfo::operator=(launch_info); SetProcessPluginName(launch_info.GetProcessPluginName()); SetResumeCount(launch_info.GetResumeCount()); @@ -1887,7 +1884,7 @@ public: /// want to deallocate. /// /// \return - /// \btrue if the memory was deallocated, \bfalse otherwise. + /// \b true if the memory was deallocated, \b false otherwise. virtual Status DoDeallocateMemory(lldb::addr_t ptr) { Status error; error.SetErrorStringWithFormatv( @@ -1906,7 +1903,7 @@ public: /// want to deallocate. /// /// \return - /// \btrue if the memory was deallocated, \bfalse otherwise. + /// \b true if the memory was deallocated, \b false otherwise. Status DeallocateMemory(lldb::addr_t ptr); /// Get any available STDOUT. diff --git a/lldb/include/lldb/Target/RegisterCheckpoint.h b/lldb/include/lldb/Target/RegisterCheckpoint.h index daf20db999b3..8681fb962801 100644 --- a/lldb/include/lldb/Target/RegisterCheckpoint.h +++ b/lldb/include/lldb/Target/RegisterCheckpoint.h @@ -31,8 +31,7 @@ public: eDataBackup }; - RegisterCheckpoint(Reason reason) - : UserID(0), m_data_sp(), m_reason(reason) {} + RegisterCheckpoint(Reason reason) : UserID(0), m_reason(reason) {} ~RegisterCheckpoint() = default; diff --git a/lldb/include/lldb/Target/SectionLoadHistory.h b/lldb/include/lldb/Target/SectionLoadHistory.h index dd024301d0cf..0240cebda85f 100644 --- a/lldb/include/lldb/Target/SectionLoadHistory.h +++ b/lldb/include/lldb/Target/SectionLoadHistory.h @@ -24,7 +24,7 @@ public: eStopIDNow = UINT32_MAX }; // Constructors and Destructors - SectionLoadHistory() : m_stop_id_to_section_load_list(), m_mutex() {} + SectionLoadHistory() {} ~SectionLoadHistory() { // Call clear since this takes a lock and clears the section load list in diff --git a/lldb/include/lldb/Target/SectionLoadList.h b/lldb/include/lldb/Target/SectionLoadList.h index e8535e7ac51a..548d44a181a7 100644 --- a/lldb/include/lldb/Target/SectionLoadList.h +++ b/lldb/include/lldb/Target/SectionLoadList.h @@ -22,7 +22,7 @@ namespace lldb_private { class SectionLoadList { public: // Constructors and Destructors - SectionLoadList() : m_addr_to_sect(), m_sect_to_addr(), m_mutex() {} + SectionLoadList() {} SectionLoadList(const SectionLoadList &rhs); diff --git a/lldb/include/lldb/Target/StackFrame.h b/lldb/include/lldb/Target/StackFrame.h index 1a9aaad1a4db..1b0485b22cac 100644 --- a/lldb/include/lldb/Target/StackFrame.h +++ b/lldb/include/lldb/Target/StackFrame.h @@ -171,7 +171,7 @@ public: /// functions looking up symbolic information for a given pc value multiple /// times. /// - /// \params [in] resolve_scope + /// \param [in] resolve_scope /// Flags from the SymbolContextItem enumerated type which specify what /// type of symbol context is needed by this caller. /// @@ -408,10 +408,10 @@ public: /// Create a ValueObject for a given Variable in this StackFrame. /// - /// \params [in] variable_sp + /// \param [in] variable_sp /// The Variable to base this ValueObject on /// - /// \params [in] use_dynamic + /// \param [in] use_dynamic /// Whether the correct dynamic type of the variable should be /// determined before creating the ValueObject, or if the static type /// is sufficient. One of the DynamicValueType enumerated values. @@ -437,7 +437,7 @@ public: /// the current instruction. The ExpressionPath should indicate how to get /// to this value using "frame variable." /// - /// \params [in] addr + /// \param [in] addr /// The raw address. /// /// \return @@ -448,10 +448,10 @@ public: /// given register plus an offset. The ExpressionPath should indicate how /// to get to this value using "frame variable." /// - /// \params [in] reg + /// \param [in] reg /// The name of the register. /// - /// \params [in] offset + /// \param [in] offset /// The offset from the register. Particularly important for sp... /// /// \return @@ -465,7 +465,7 @@ public: /// PC in the stack frame and traverse through all parent blocks stopping at /// inlined function boundaries. /// - /// \params [in] name + /// \param [in] name /// The name of the variable. /// /// \return diff --git a/lldb/include/lldb/Target/Statistics.h b/lldb/include/lldb/Target/Statistics.h index 087fbee26328..d2b8f746a38c 100644 --- a/lldb/include/lldb/Target/Statistics.h +++ b/lldb/include/lldb/Target/Statistics.h @@ -9,20 +9,41 @@ #ifndef LLDB_TARGET_STATISTICS_H #define LLDB_TARGET_STATISTICS_H -#include <chrono> -#include <string> -#include <vector> - +#include "lldb/Utility/ConstString.h" #include "lldb/Utility/Stream.h" #include "lldb/lldb-forward.h" #include "llvm/Support/JSON.h" +#include <atomic> +#include <chrono> +#include <ratio> +#include <string> +#include <vector> namespace lldb_private { using StatsClock = std::chrono::high_resolution_clock; -using StatsDuration = std::chrono::duration<double>; using StatsTimepoint = std::chrono::time_point<StatsClock>; +class StatsDuration { +public: + using Duration = std::chrono::duration<double>; + + Duration get() const { + return Duration(InternalDuration(value.load(std::memory_order_relaxed))); + } + operator Duration() const { return get(); } + + StatsDuration &operator+=(Duration dur) { + value.fetch_add(std::chrono::duration_cast<InternalDuration>(dur).count(), + std::memory_order_relaxed); + return *this; + } + +private: + using InternalDuration = std::chrono::duration<uint64_t, std::micro>; + std::atomic<uint64_t> value{0}; +}; + /// A class that measures elapsed time in an exception safe way. /// /// This is a RAII class is designed to help gather timing statistics within @@ -54,7 +75,7 @@ public: m_start_time = StatsClock::now(); } ~ElapsedTime() { - StatsDuration elapsed = StatsClock::now() - m_start_time; + StatsClock::duration elapsed = StatsClock::now() - m_start_time; m_elapsed_time += elapsed; } }; @@ -84,6 +105,15 @@ struct ModuleStats { double debug_parse_time = 0.0; double debug_index_time = 0.0; uint64_t debug_info_size = 0; + bool symtab_loaded_from_cache = false; + bool symtab_saved_to_cache = false; + bool debug_info_index_loaded_from_cache = false; + bool debug_info_index_saved_to_cache = false; +}; + +struct ConstStringStats { + llvm::json::Value ToJSON() const; + ConstString::MemoryStats stats = ConstString::GetMemoryStats(); }; /// A class that represents statistics for a since lldb_private::Target. @@ -100,7 +130,7 @@ public: StatsSuccessFail &GetFrameVariableStats() { return m_frame_var; } protected: - StatsDuration m_create_time{0.0}; + StatsDuration m_create_time; llvm::Optional<StatsTimepoint> m_launch_or_attach_time; llvm::Optional<StatsTimepoint> m_first_private_stop_time; llvm::Optional<StatsTimepoint> m_first_public_stop_time; diff --git a/lldb/include/lldb/Target/Target.h b/lldb/include/lldb/Target/Target.h index b85839c15b2f..2c8b36d1e3d9 100644 --- a/lldb/include/lldb/Target/Target.h +++ b/lldb/include/lldb/Target/Target.h @@ -991,7 +991,7 @@ public: /// manually set following this function call). /// /// \return - /// \b true if the architecture was successfully set, \bfalse otherwise. + /// \b true if the architecture was successfully set, \b false otherwise. bool SetArchitecture(const ArchSpec &arch_spec, bool set_platform = false); bool MergeArchitecture(const ArchSpec &arch_spec); diff --git a/lldb/include/lldb/Target/Thread.h b/lldb/include/lldb/Target/Thread.h index 91feed310eb9..f1d4e6c7ef01 100644 --- a/lldb/include/lldb/Target/Thread.h +++ b/lldb/include/lldb/Target/Thread.h @@ -22,6 +22,7 @@ #include "lldb/Utility/CompletionRequest.h" #include "lldb/Utility/Event.h" #include "lldb/Utility/StructuredData.h" +#include "lldb/Utility/UnimplementedError.h" #include "lldb/Utility/UserID.h" #include "lldb/lldb-private.h" @@ -1184,6 +1185,11 @@ public: lldb::ThreadSP GetCurrentExceptionBacktrace(); + virtual llvm::Expected<std::unique_ptr<llvm::MemoryBuffer>> + GetSiginfo(size_t max_size) const { + return llvm::make_error<UnimplementedError>(); + } + protected: friend class ThreadPlan; friend class ThreadList; @@ -1244,7 +1250,7 @@ protected: // the stop info was checked against // the stop info override const uint32_t m_index_id; ///< A unique 1 based index assigned to each thread - ///for easy UI/command line access. + /// for easy UI/command line access. lldb::RegisterContextSP m_reg_context_sp; ///< The register context for this ///thread's current register state. lldb::StateType m_state; ///< The state of our process. diff --git a/lldb/include/lldb/Target/Unwind.h b/lldb/include/lldb/Target/Unwind.h index 3faef139b00a..105383ddae8a 100644 --- a/lldb/include/lldb/Target/Unwind.h +++ b/lldb/include/lldb/Target/Unwind.h @@ -18,7 +18,7 @@ namespace lldb_private { class Unwind { protected: // Classes that inherit from Unwind can see and modify these - Unwind(Thread &thread) : m_thread(thread), m_unwind_mutex() {} + Unwind(Thread &thread) : m_thread(thread) {} public: virtual ~Unwind() = default; diff --git a/lldb/include/lldb/Target/UnwindLLDB.h b/lldb/include/lldb/Target/UnwindLLDB.h index f6750171c54a..939226c8c5b9 100644 --- a/lldb/include/lldb/Target/UnwindLLDB.h +++ b/lldb/include/lldb/Target/UnwindLLDB.h @@ -119,7 +119,7 @@ private: RegisterContextLLDBSP reg_ctx_lldb_sp; // These are all RegisterContextUnwind's - Cursor() : sctx(), reg_ctx_lldb_sp() {} + Cursor() {} private: Cursor(const Cursor &) = delete; diff --git a/lldb/include/lldb/Utility/ConstString.h b/lldb/include/lldb/Utility/ConstString.h index 2756f1fd7203..31887d7f6115 100644 --- a/lldb/include/lldb/Utility/ConstString.h +++ b/lldb/include/lldb/Utility/ConstString.h @@ -394,19 +394,17 @@ public: /// /// \return /// The number of bytes that this object occupies in memory. - /// - /// \see ConstString::StaticMemorySize () size_t MemorySize() const { return sizeof(ConstString); } - /// Get the size in bytes of the current global string pool. - /// - /// Reports the size in bytes of all shared C string values, containers and - /// any other values as a byte size for the entire string pool. - /// - /// \return - /// The number of bytes that the global string pool occupies - /// in memory. - static size_t StaticMemorySize(); + struct MemoryStats { + size_t GetBytesTotal() const { return bytes_total; } + size_t GetBytesUsed() const { return bytes_used; } + size_t GetBytesUnused() const { return bytes_total - bytes_used; } + size_t bytes_total = 0; + size_t bytes_used = 0; + }; + + static MemoryStats GetMemoryStats(); protected: template <typename T, typename Enable> friend struct ::llvm::DenseMapInfo; diff --git a/lldb/include/lldb/Utility/Environment.h b/lldb/include/lldb/Utility/Environment.h index 24cbee246f83..c1549a3d60a6 100644 --- a/lldb/include/lldb/Utility/Environment.h +++ b/lldb/include/lldb/Utility/Environment.h @@ -56,7 +56,7 @@ public: using Base::try_emplace; using Base::operator[]; - Environment() : Base() {} + Environment() {} Environment(const Environment &RHS) : Base(RHS) {} Environment(Environment &&RHS) : Base(std::move(RHS)) {} Environment(char *const *Env) diff --git a/lldb/include/lldb/Utility/Event.h b/lldb/include/lldb/Utility/Event.h index 4e38f98a02f3..d3176216115a 100644 --- a/lldb/include/lldb/Utility/Event.h +++ b/lldb/include/lldb/Utility/Event.h @@ -99,7 +99,7 @@ private: class EventDataReceipt : public EventData { public: - EventDataReceipt() : EventData(), m_predicate(false) {} + EventDataReceipt() : m_predicate(false) {} ~EventDataReceipt() override = default; diff --git a/lldb/include/lldb/Utility/FileSpec.h b/lldb/include/lldb/Utility/FileSpec.h index 305cd04f95c0..ec473a2afeec 100644 --- a/lldb/include/lldb/Utility/FileSpec.h +++ b/lldb/include/lldb/Utility/FileSpec.h @@ -334,8 +334,6 @@ public: /// /// \return /// The number of bytes that this object occupies in memory. - /// - /// \see ConstString::StaticMemorySize () size_t MemorySize() const; /// Change the file specified with a new path. diff --git a/lldb/include/lldb/Utility/GDBRemote.h b/lldb/include/lldb/Utility/GDBRemote.h index f658818de806..451181624c87 100644 --- a/lldb/include/lldb/Utility/GDBRemote.h +++ b/lldb/include/lldb/Utility/GDBRemote.h @@ -55,7 +55,7 @@ struct GDBRemotePacket { enum Type { ePacketTypeInvalid = 0, ePacketTypeSend, ePacketTypeRecv }; - GDBRemotePacket() : packet() {} + GDBRemotePacket() {} void Clear() { packet.data.clear(); diff --git a/lldb/include/lldb/Utility/Instrumentation.h b/lldb/include/lldb/Utility/Instrumentation.h new file mode 100644 index 000000000000..ff6591d63437 --- /dev/null +++ b/lldb/include/lldb/Utility/Instrumentation.h @@ -0,0 +1,105 @@ +//===-- Instrumentation.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_UTILITY_INSTRUMENTATION_H +#define LLDB_UTILITY_INSTRUMENTATION_H + +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Log.h" +#include "lldb/Utility/Logging.h" + +#include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/ErrorHandling.h" + +#include <map> +#include <thread> +#include <type_traits> + +namespace lldb_private { +namespace instrumentation { + +template <typename T, + typename std::enable_if<std::is_fundamental<T>::value, int>::type = 0> +inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) { + ss << t; +} + +template <typename T, typename std::enable_if<!std::is_fundamental<T>::value, + int>::type = 0> +inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) { + ss << &t; +} + +template <typename T> +inline void stringify_append(llvm::raw_string_ostream &ss, T *t) { + ss << reinterpret_cast<void *>(t); +} + +template <typename T> +inline void stringify_append(llvm::raw_string_ostream &ss, const T *t) { + ss << reinterpret_cast<const void *>(t); +} + +template <> +inline void stringify_append<char>(llvm::raw_string_ostream &ss, + const char *t) { + ss << '\"' << t << '\"'; +} + +template <> +inline void stringify_append<std::nullptr_t>(llvm::raw_string_ostream &ss, + const std::nullptr_t &t) { + ss << "\"nullptr\""; +} + +template <typename Head> +inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head) { + stringify_append(ss, head); +} + +template <typename Head, typename... Tail> +inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head, + const Tail &...tail) { + stringify_append(ss, head); + ss << ", "; + stringify_helper(ss, tail...); +} + +template <typename... Ts> inline std::string stringify_args(const Ts &...ts) { + std::string buffer; + llvm::raw_string_ostream ss(buffer); + stringify_helper(ss, ts...); + return ss.str(); +} + +/// RAII object for instrumenting LLDB API functions. +class Instrumenter { +public: + Instrumenter(llvm::StringRef pretty_func, std::string &&pretty_args = {}); + ~Instrumenter(); + +private: + void UpdateBoundary(); + + llvm::StringRef m_pretty_func; + + /// Whether this function call was the one crossing the API boundary. + bool m_local_boundary = false; +}; +} // namespace instrumentation +} // namespace lldb_private + +#define LLDB_INSTRUMENT() \ + lldb_private::instrumentation::Instrumenter _instr(LLVM_PRETTY_FUNCTION); + +#define LLDB_INSTRUMENT_VA(...) \ + lldb_private::instrumentation::Instrumenter _instr( \ + LLVM_PRETTY_FUNCTION, \ + lldb_private::instrumentation::stringify_args(__VA_ARGS__)); + +#endif // LLDB_UTILITY_INSTRUMENTATION_H diff --git a/lldb/include/lldb/Utility/Log.h b/lldb/include/lldb/Utility/Log.h index 01edec044565..09fd2cb3a7e6 100644 --- a/lldb/include/lldb/Utility/Log.h +++ b/lldb/include/lldb/Utility/Log.h @@ -10,7 +10,6 @@ #define LLDB_UTILITY_LOG_H #include "lldb/Utility/Flags.h" -#include "lldb/Utility/Logging.h" #include "lldb/lldb-defines.h" #include "llvm/ADT/ArrayRef.h" @@ -48,11 +47,31 @@ namespace lldb_private { class Log final { public: + /// The underlying type of all log channel enums. Declare them as: + /// enum class MyLog : MaskType { + /// Channel0 = Log::ChannelFlag<0>, + /// Channel1 = Log::ChannelFlag<1>, + /// ..., + /// LLVM_MARK_AS_BITMASK_ENUM(LastChannel), + /// }; + using MaskType = uint64_t; + + template <MaskType Bit> + static constexpr MaskType ChannelFlag = MaskType(1) << Bit; + // Description of a log channel category. struct Category { llvm::StringLiteral name; llvm::StringLiteral description; - uint32_t flag; + MaskType flag; + + template <typename Cat> + constexpr Category(llvm::StringLiteral name, + llvm::StringLiteral description, Cat mask) + : name(name), description(description), flag(MaskType(mask)) { + static_assert( + std::is_same<Log::MaskType, std::underlying_type_t<Cat>>::value, ""); + } }; // This class describes a log channel. It also encapsulates the behavior @@ -63,18 +82,22 @@ public: public: const llvm::ArrayRef<Category> categories; - const uint32_t default_flags; + const MaskType default_flags; + template <typename Cat> constexpr Channel(llvm::ArrayRef<Log::Category> categories, - uint32_t default_flags) + Cat default_flags) : log_ptr(nullptr), categories(categories), - default_flags(default_flags) {} + default_flags(MaskType(default_flags)) { + static_assert( + std::is_same<Log::MaskType, std::underlying_type_t<Cat>>::value, ""); + } // This function is safe to call at any time. If the channel is disabled // after (or concurrently with) this function returning a non-null Log // pointer, it is still safe to attempt to write to the Log object -- the // output will be discarded. - Log *GetLogIfAll(uint32_t mask) { + Log *GetLogIfAll(MaskType mask) { Log *log = log_ptr.load(std::memory_order_relaxed); if (log && log->GetMask().AllSet(mask)) return log; @@ -85,7 +108,7 @@ public: // after (or concurrently with) this function returning a non-null Log // pointer, it is still safe to attempt to write to the Log object -- the // output will be discarded. - Log *GetLogIfAny(uint32_t mask) { + Log *GetLogIfAny(MaskType mask) { Log *log = log_ptr.load(std::memory_order_relaxed); if (log && log->GetMask().AnySet(mask)) return log; @@ -180,7 +203,7 @@ private: std::shared_ptr<llvm::raw_ostream> m_stream_sp; std::atomic<uint32_t> m_options{0}; - std::atomic<uint32_t> m_mask{0}; + std::atomic<MaskType> m_mask{0}; void WriteHeader(llvm::raw_ostream &OS, llvm::StringRef file, llvm::StringRef function); @@ -211,12 +234,23 @@ private: static uint32_t GetFlags(llvm::raw_ostream &stream, const ChannelMap::value_type &entry, llvm::ArrayRef<const char *> categories); - static void DisableLoggingChild(); - Log(const Log &) = delete; void operator=(const Log &) = delete; }; +// Must be specialized for a particular log type. +template <typename Cat> Log::Channel &LogChannelFor() = delete; + +/// Retrieve the Log object for the channel associated with the given log enum. +/// +/// Returns a valid Log object if any of the provided categories are enabled. +/// Otherwise, returns nullptr. +template <typename Cat> Log *GetLog(Cat mask) { + static_assert(std::is_same<Log::MaskType, std::underlying_type_t<Cat>>::value, + ""); + return LogChannelFor<Cat>().GetLogIfAny(Log::MaskType(mask)); +} + } // namespace lldb_private /// The LLDB_LOG* macros defined below are the way to emit log messages. @@ -274,3 +308,6 @@ private: } while (0) #endif // LLDB_UTILITY_LOG_H + +// TODO: Remove this and fix includes everywhere. +#include "lldb/Utility/Logging.h" diff --git a/lldb/include/lldb/Utility/Logging.h b/lldb/include/lldb/Utility/Logging.h index 1a8a1022c5c0..db84da244954 100644 --- a/lldb/include/lldb/Utility/Logging.h +++ b/lldb/include/lldb/Utility/Logging.h @@ -9,57 +9,89 @@ #ifndef LLDB_UTILITY_LOGGING_H #define LLDB_UTILITY_LOGGING_H +#include "lldb/Utility/Log.h" +#include "llvm/ADT/BitmaskEnum.h" #include <cstdint> -// Log Bits specific to logging in lldb -#define LIBLLDB_LOG_PROCESS (1u << 1) -#define LIBLLDB_LOG_THREAD (1u << 2) -#define LIBLLDB_LOG_DYNAMIC_LOADER (1u << 3) -#define LIBLLDB_LOG_EVENTS (1u << 4) -#define LIBLLDB_LOG_BREAKPOINTS (1u << 5) -#define LIBLLDB_LOG_WATCHPOINTS (1u << 6) -#define LIBLLDB_LOG_STEP (1u << 7) -#define LIBLLDB_LOG_EXPRESSIONS (1u << 8) -#define LIBLLDB_LOG_TEMPORARY (1u << 9) -#define LIBLLDB_LOG_STATE (1u << 10) -#define LIBLLDB_LOG_OBJECT (1u << 11) -#define LIBLLDB_LOG_COMMUNICATION (1u << 12) -#define LIBLLDB_LOG_CONNECTION (1u << 13) -#define LIBLLDB_LOG_HOST (1u << 14) -#define LIBLLDB_LOG_UNWIND (1u << 15) -#define LIBLLDB_LOG_API (1u << 16) -#define LIBLLDB_LOG_SCRIPT (1u << 17) -#define LIBLLDB_LOG_COMMANDS (1U << 18) -#define LIBLLDB_LOG_TYPES (1u << 19) -#define LIBLLDB_LOG_SYMBOLS (1u << 20) -#define LIBLLDB_LOG_MODULES (1u << 21) -#define LIBLLDB_LOG_TARGET (1u << 22) -#define LIBLLDB_LOG_MMAP (1u << 23) -#define LIBLLDB_LOG_OS (1u << 24) -#define LIBLLDB_LOG_PLATFORM (1u << 25) -#define LIBLLDB_LOG_SYSTEM_RUNTIME (1u << 26) -#define LIBLLDB_LOG_JIT_LOADER (1u << 27) -#define LIBLLDB_LOG_LANGUAGE (1u << 28) -#define LIBLLDB_LOG_DATAFORMATTERS (1u << 29) -#define LIBLLDB_LOG_DEMANGLE (1u << 30) -#define LIBLLDB_LOG_AST (1u << 31) -#define LIBLLDB_LOG_ALL (UINT32_MAX) -#define LIBLLDB_LOG_DEFAULT \ - (LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_THREAD | LIBLLDB_LOG_DYNAMIC_LOADER | \ - LIBLLDB_LOG_BREAKPOINTS | LIBLLDB_LOG_WATCHPOINTS | LIBLLDB_LOG_STEP | \ - LIBLLDB_LOG_STATE | LIBLLDB_LOG_SYMBOLS | LIBLLDB_LOG_TARGET | \ - LIBLLDB_LOG_COMMANDS) - namespace lldb_private { -class Log; +enum class LLDBLog : Log::MaskType { + API = Log::ChannelFlag<0>, + AST = Log::ChannelFlag<1>, + Breakpoints = Log::ChannelFlag<2>, + Commands = Log::ChannelFlag<3>, + Communication = Log::ChannelFlag<4>, + Connection = Log::ChannelFlag<5>, + DataFormatters = Log::ChannelFlag<6>, + Demangle = Log::ChannelFlag<7>, + DynamicLoader = Log::ChannelFlag<8>, + Events = Log::ChannelFlag<9>, + Expressions = Log::ChannelFlag<10>, + Host = Log::ChannelFlag<11>, + JITLoader = Log::ChannelFlag<12>, + Language = Log::ChannelFlag<13>, + MMap = Log::ChannelFlag<14>, + Modules = Log::ChannelFlag<15>, + Object = Log::ChannelFlag<16>, + OS = Log::ChannelFlag<17>, + Platform = Log::ChannelFlag<18>, + Process = Log::ChannelFlag<19>, + Script = Log::ChannelFlag<20>, + State = Log::ChannelFlag<21>, + Step = Log::ChannelFlag<22>, + Symbols = Log::ChannelFlag<23>, + SystemRuntime = Log::ChannelFlag<24>, + Target = Log::ChannelFlag<25>, + Temporary = Log::ChannelFlag<26>, + Thread = Log::ChannelFlag<27>, + Types = Log::ChannelFlag<28>, + Unwind = Log::ChannelFlag<29>, + Watchpoints = Log::ChannelFlag<30>, + LLVM_MARK_AS_BITMASK_ENUM(Watchpoints), +}; + +LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); + +// Log Bits specific to logging in lldb +#define LIBLLDB_LOG_PROCESS ::lldb_private::LLDBLog::Process +#define LIBLLDB_LOG_THREAD ::lldb_private::LLDBLog::Thread +#define LIBLLDB_LOG_DYNAMIC_LOADER ::lldb_private::LLDBLog::DynamicLoader +#define LIBLLDB_LOG_EVENTS ::lldb_private::LLDBLog::Events +#define LIBLLDB_LOG_BREAKPOINTS ::lldb_private::LLDBLog::Breakpoints +#define LIBLLDB_LOG_WATCHPOINTS ::lldb_private::LLDBLog::Watchpoints +#define LIBLLDB_LOG_STEP ::lldb_private::LLDBLog::Step +#define LIBLLDB_LOG_EXPRESSIONS ::lldb_private::LLDBLog::Expressions +#define LIBLLDB_LOG_TEMPORARY ::lldb_private::LLDBLog::Temporary +#define LIBLLDB_LOG_STATE ::lldb_private::LLDBLog::State +#define LIBLLDB_LOG_OBJECT ::lldb_private::LLDBLog::Object +#define LIBLLDB_LOG_COMMUNICATION ::lldb_private::LLDBLog::Communication +#define LIBLLDB_LOG_CONNECTION ::lldb_private::LLDBLog::Connection +#define LIBLLDB_LOG_HOST ::lldb_private::LLDBLog::Host +#define LIBLLDB_LOG_UNWIND ::lldb_private::LLDBLog::Unwind +#define LIBLLDB_LOG_API ::lldb_private::LLDBLog::API +#define LIBLLDB_LOG_SCRIPT ::lldb_private::LLDBLog::Script +#define LIBLLDB_LOG_COMMANDS ::lldb_private::LLDBLog::Commands +#define LIBLLDB_LOG_TYPES ::lldb_private::LLDBLog::Types +#define LIBLLDB_LOG_SYMBOLS ::lldb_private::LLDBLog::Symbols +#define LIBLLDB_LOG_MODULES ::lldb_private::LLDBLog::Modules +#define LIBLLDB_LOG_TARGET ::lldb_private::LLDBLog::Target +#define LIBLLDB_LOG_MMAP ::lldb_private::LLDBLog::MMap +#define LIBLLDB_LOG_OS ::lldb_private::LLDBLog::OS +#define LIBLLDB_LOG_PLATFORM ::lldb_private::LLDBLog::Platform +#define LIBLLDB_LOG_SYSTEM_RUNTIME ::lldb_private::LLDBLog::SystemRuntime +#define LIBLLDB_LOG_JIT_LOADER ::lldb_private::LLDBLog::JITLoader +#define LIBLLDB_LOG_LANGUAGE ::lldb_private::LLDBLog::Language +#define LIBLLDB_LOG_DATAFORMATTERS ::lldb_private::LLDBLog::DataFormatters +#define LIBLLDB_LOG_DEMANGLE ::lldb_private::LLDBLog::Demangle +#define LIBLLDB_LOG_AST ::lldb_private::LLDBLog::AST -Log *GetLogIfAllCategoriesSet(uint32_t mask); +Log *GetLogIfAllCategoriesSet(LLDBLog mask); -Log *GetLogIfAnyCategoriesSet(uint32_t mask); +Log *GetLogIfAnyCategoriesSet(LLDBLog mask); void InitializeLldbChannel(); +template <> Log::Channel &LogChannelFor<LLDBLog>(); } // namespace lldb_private #endif // LLDB_UTILITY_LOGGING_H diff --git a/lldb/include/lldb/Utility/Predicate.h b/lldb/include/lldb/Utility/Predicate.h index af16abc1a1d3..e5d80acb11bc 100644 --- a/lldb/include/lldb/Utility/Predicate.h +++ b/lldb/include/lldb/Utility/Predicate.h @@ -44,7 +44,7 @@ public: /// /// Initializes the mutex, condition and value with their default /// constructors. - Predicate() : m_value(), m_mutex(), m_condition() {} + Predicate() : m_value() {} /// Construct with initial T value \a initial_value. /// @@ -53,8 +53,7 @@ public: /// /// \param[in] initial_value /// The initial value for our T object. - Predicate(T initial_value) - : m_value(initial_value), m_mutex(), m_condition() {} + Predicate(T initial_value) : m_value(initial_value) {} /// Destructor. /// diff --git a/lldb/include/lldb/Utility/ProcessInfo.h b/lldb/include/lldb/Utility/ProcessInfo.h index 3c5956926391..fc8b12768999 100644 --- a/lldb/include/lldb/Utility/ProcessInfo.h +++ b/lldb/include/lldb/Utility/ProcessInfo.h @@ -107,7 +107,7 @@ protected: // to that process. class ProcessInstanceInfo : public ProcessInfo { public: - ProcessInstanceInfo() : ProcessInfo() {} + ProcessInstanceInfo() {} ProcessInstanceInfo(const char *name, const ArchSpec &arch, lldb::pid_t pid) : ProcessInfo(name, arch, pid), m_euid(UINT32_MAX), m_egid(UINT32_MAX), @@ -162,12 +162,11 @@ typedef std::vector<ProcessInstanceInfo> ProcessInstanceInfoList; class ProcessInstanceInfoMatch { public: - ProcessInstanceInfoMatch() : m_match_info() {} + ProcessInstanceInfoMatch() {} ProcessInstanceInfoMatch(const char *process_name, NameMatch process_name_match_type) - : m_match_info(), m_name_match_type(process_name_match_type), - m_match_all_users(false) { + : m_name_match_type(process_name_match_type), m_match_all_users(false) { m_match_info.GetExecutableFile().SetFile(process_name, FileSpec::Style::native); } diff --git a/lldb/include/lldb/Utility/ReproducerInstrumentation.h b/lldb/include/lldb/Utility/ReproducerInstrumentation.h deleted file mode 100644 index 6c5d27879d36..000000000000 --- a/lldb/include/lldb/Utility/ReproducerInstrumentation.h +++ /dev/null @@ -1,1105 +0,0 @@ -//===-- ReproducerInstrumentation.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_UTILITY_REPRODUCERINSTRUMENTATION_H -#define LLDB_UTILITY_REPRODUCERINSTRUMENTATION_H - -#include "lldb/Utility/FileSpec.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Logging.h" - -#include "llvm/ADT/DenseMap.h" -#include "llvm/ADT/StringRef.h" -#include "llvm/Support/ErrorHandling.h" - -#include <map> -#include <thread> -#include <type_traits> - -template <typename T, - typename std::enable_if<std::is_fundamental<T>::value, int>::type = 0> -inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) { - ss << t; -} - -template <typename T, typename std::enable_if<!std::is_fundamental<T>::value, - int>::type = 0> -inline void stringify_append(llvm::raw_string_ostream &ss, const T &t) { - ss << &t; -} - -template <typename T> -inline void stringify_append(llvm::raw_string_ostream &ss, T *t) { - ss << reinterpret_cast<void *>(t); -} - -template <typename T> -inline void stringify_append(llvm::raw_string_ostream &ss, const T *t) { - ss << reinterpret_cast<const void *>(t); -} - -template <> -inline void stringify_append<char>(llvm::raw_string_ostream &ss, - const char *t) { - ss << '\"' << t << '\"'; -} - -template <> -inline void stringify_append<std::nullptr_t>(llvm::raw_string_ostream &ss, - const std::nullptr_t &t) { - ss << "\"nullptr\""; -} - -template <typename Head> -inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head) { - stringify_append(ss, head); -} - -template <typename Head, typename... Tail> -inline void stringify_helper(llvm::raw_string_ostream &ss, const Head &head, - const Tail &... tail) { - stringify_append(ss, head); - ss << ", "; - stringify_helper(ss, tail...); -} - -template <typename... Ts> inline std::string stringify_args(const Ts &... ts) { - std::string buffer; - llvm::raw_string_ostream ss(buffer); - stringify_helper(ss, ts...); - return ss.str(); -} - -// Define LLDB_REPRO_INSTR_TRACE to trace to stderr instead of LLDB's log -// infrastructure. This is useful when you need to see traces before the logger -// is initialized or enabled. -// #define LLDB_REPRO_INSTR_TRACE - -#ifdef LLDB_REPRO_INSTR_TRACE -inline llvm::raw_ostream &this_thread_id() { - size_t tid = std::hash<std::thread::id>{}(std::this_thread::get_id()); - return llvm::errs().write_hex(tid) << " :: "; -} -#endif - -#define LLDB_REGISTER_CONSTRUCTOR(Class, Signature) \ - R.Register<Class * Signature>(&construct<Class Signature>::record, "", \ - #Class, #Class, #Signature) - -#define LLDB_REGISTER_METHOD(Result, Class, Method, Signature) \ - R.Register( \ - &invoke<Result(Class::*) Signature>::method<(&Class::Method)>::record, \ - #Result, #Class, #Method, #Signature) - -#define LLDB_REGISTER_METHOD_CONST(Result, Class, Method, Signature) \ - R.Register(&invoke<Result(Class::*) \ - Signature const>::method<(&Class::Method)>::record, \ - #Result, #Class, #Method, #Signature) - -#define LLDB_REGISTER_STATIC_METHOD(Result, Class, Method, Signature) \ - R.Register(&invoke<Result(*) Signature>::method<(&Class::Method)>::record, \ - #Result, #Class, #Method, #Signature) - -#define LLDB_REGISTER_CHAR_PTR_METHOD_STATIC(Result, Class, Method) \ - R.Register( \ - &invoke<Result (*)(char *, size_t)>::method<(&Class::Method)>::record, \ - &invoke_char_ptr<Result (*)(char *, \ - size_t)>::method<(&Class::Method)>::record, \ - #Result, #Class, #Method, "(char*, size_t"); - -#define LLDB_REGISTER_CHAR_PTR_METHOD(Result, Class, Method) \ - R.Register(&invoke<Result (Class::*)(char *, size_t)>::method<( \ - &Class::Method)>::record, \ - &invoke_char_ptr<Result (Class::*)(char *, size_t)>::method<( \ - &Class::Method)>::record, \ - #Result, #Class, #Method, "(char*, size_t"); - -#define LLDB_REGISTER_CHAR_PTR_METHOD_CONST(Result, Class, Method) \ - R.Register(&invoke<Result (Class::*)(char *, size_t) \ - const>::method<(&Class::Method)>::record, \ - &invoke_char_ptr<Result (Class::*)(char *, size_t) \ - const>::method<(&Class::Method)>::record, \ - #Result, #Class, #Method, "(char*, size_t"); - -#define LLDB_CONSTRUCT_(T, Class, ...) \ - lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION); \ - lldb_private::repro::construct<T>::handle(LLDB_GET_INSTRUMENTATION_DATA(), \ - _recorder, Class, __VA_ARGS__); - -#define LLDB_RECORD_CONSTRUCTOR(Class, Signature, ...) \ - LLDB_CONSTRUCT_(Class Signature, this, __VA_ARGS__) - -#define LLDB_RECORD_CONSTRUCTOR_NO_ARGS(Class) \ - LLDB_CONSTRUCT_(Class(), this, lldb_private::repro::EmptyArg()) - -#define LLDB_RECORD_(T1, T2, ...) \ - lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION, \ - stringify_args(__VA_ARGS__)); \ - if (lldb_private::repro::InstrumentationData _data = \ - LLDB_GET_INSTRUMENTATION_DATA()) { \ - if (lldb_private::repro::Serializer *_serializer = \ - _data.GetSerializer()) { \ - _recorder.Record(*_serializer, _data.GetRegistry(), \ - &lldb_private::repro::invoke<T1>::method<T2>::record, \ - __VA_ARGS__); \ - } else if (lldb_private::repro::Deserializer *_deserializer = \ - _data.GetDeserializer()) { \ - if (_recorder.ShouldCapture()) { \ - return lldb_private::repro::invoke<T1>::method<T2>::replay( \ - _recorder, *_deserializer, _data.GetRegistry()); \ - } \ - } \ - } - -#define LLDB_RECORD_METHOD(Result, Class, Method, Signature, ...) \ - LLDB_RECORD_(Result(Class::*) Signature, (&Class::Method), this, __VA_ARGS__) - -#define LLDB_RECORD_METHOD_CONST(Result, Class, Method, Signature, ...) \ - LLDB_RECORD_(Result(Class::*) Signature const, (&Class::Method), this, \ - __VA_ARGS__) - -#define LLDB_RECORD_METHOD_NO_ARGS(Result, Class, Method) \ - LLDB_RECORD_(Result (Class::*)(), (&Class::Method), this) - -#define LLDB_RECORD_METHOD_CONST_NO_ARGS(Result, Class, Method) \ - LLDB_RECORD_(Result (Class::*)() const, (&Class::Method), this) - -#define LLDB_RECORD_STATIC_METHOD(Result, Class, Method, Signature, ...) \ - LLDB_RECORD_(Result(*) Signature, (&Class::Method), __VA_ARGS__) - -#define LLDB_RECORD_STATIC_METHOD_NO_ARGS(Result, Class, Method) \ - LLDB_RECORD_(Result (*)(), (&Class::Method), lldb_private::repro::EmptyArg()) - -#define LLDB_RECORD_CHAR_PTR_(T1, T2, StrOut, ...) \ - lldb_private::repro::Recorder _recorder(LLVM_PRETTY_FUNCTION, \ - stringify_args(__VA_ARGS__)); \ - if (lldb_private::repro::InstrumentationData _data = \ - LLDB_GET_INSTRUMENTATION_DATA()) { \ - if (lldb_private::repro::Serializer *_serializer = \ - _data.GetSerializer()) { \ - _recorder.Record(*_serializer, _data.GetRegistry(), \ - &lldb_private::repro::invoke<T1>::method<(T2)>::record, \ - __VA_ARGS__); \ - } else if (lldb_private::repro::Deserializer *_deserializer = \ - _data.GetDeserializer()) { \ - if (_recorder.ShouldCapture()) { \ - return lldb_private::repro::invoke_char_ptr<T1>::method<T2>::replay( \ - _recorder, *_deserializer, _data.GetRegistry(), StrOut); \ - } \ - } \ - } - -#define LLDB_RECORD_CHAR_PTR_METHOD(Result, Class, Method, Signature, StrOut, \ - ...) \ - LLDB_RECORD_CHAR_PTR_(Result(Class::*) Signature, (&Class::Method), StrOut, \ - this, __VA_ARGS__) - -#define LLDB_RECORD_CHAR_PTR_METHOD_CONST(Result, Class, Method, Signature, \ - StrOut, ...) \ - LLDB_RECORD_CHAR_PTR_(Result(Class::*) Signature const, (&Class::Method), \ - StrOut, this, __VA_ARGS__) - -#define LLDB_RECORD_CHAR_PTR_STATIC_METHOD(Result, Class, Method, Signature, \ - StrOut, ...) \ - LLDB_RECORD_CHAR_PTR_(Result(*) Signature, (&Class::Method), StrOut, \ - __VA_ARGS__) - -#define LLDB_RECORD_RESULT(Result) _recorder.RecordResult(Result, true); - -/// The LLDB_RECORD_DUMMY macro is special because it doesn't actually record -/// anything. It's used to track API boundaries when we cannot record for -/// technical reasons. -#define LLDB_RECORD_DUMMY(Result, Class, Method, Signature, ...) \ - lldb_private::repro::Recorder _recorder; - -#define LLDB_RECORD_DUMMY_NO_ARGS(Result, Class, Method) \ - lldb_private::repro::Recorder _recorder; - -namespace lldb_private { -namespace repro { - -template <class T> -struct is_trivially_serializable - : std::integral_constant<bool, std::is_fundamental<T>::value || - std::is_enum<T>::value> {}; - -/// Mapping between serialized indices and their corresponding objects. -/// -/// This class is used during replay to map indices back to in-memory objects. -/// -/// When objects are constructed, they are added to this mapping using -/// AddObjectForIndex. -/// -/// When an object is passed to a function, its index is deserialized and -/// AddObjectForIndex returns the corresponding object. If there is no object -/// for the given index, a nullptr is returend. The latter is valid when custom -/// replay code is in place and the actual object is ignored. -class IndexToObject { -public: - /// Returns an object as a pointer for the given index or nullptr if not - /// present in the map. - template <typename T> T *GetObjectForIndex(unsigned idx) { - assert(idx != 0 && "Cannot get object for sentinel"); - void *object = GetObjectForIndexImpl(idx); - return static_cast<T *>(object); - } - - /// Adds a pointer to an object to the mapping for the given index. - template <typename T> T *AddObjectForIndex(unsigned idx, T *object) { - AddObjectForIndexImpl( - idx, static_cast<void *>( - const_cast<typename std::remove_const<T>::type *>(object))); - return object; - } - - /// Adds a reference to an object to the mapping for the given index. - template <typename T> T &AddObjectForIndex(unsigned idx, T &object) { - AddObjectForIndexImpl( - idx, static_cast<void *>( - const_cast<typename std::remove_const<T>::type *>(&object))); - return object; - } - - /// Get all objects sorted by their index. - std::vector<void *> GetAllObjects() const; - -private: - /// Helper method that does the actual lookup. The void* result is later cast - /// by the caller. - void *GetObjectForIndexImpl(unsigned idx); - - /// Helper method that does the actual insertion. - void AddObjectForIndexImpl(unsigned idx, void *object); - - /// Keeps a mapping between indices and their corresponding object. - llvm::DenseMap<unsigned, void *> m_mapping; -}; - -/// We need to differentiate between pointers to fundamental and -/// non-fundamental types. See the corresponding Deserializer::Read method -/// for the reason why. -struct PointerTag {}; -struct ReferenceTag {}; -struct ValueTag {}; -struct FundamentalPointerTag {}; -struct FundamentalReferenceTag {}; - -/// Return the deserialization tag for the given type T. -template <class T> struct serializer_tag { - typedef typename std::conditional<std::is_trivially_copyable<T>::value, - ValueTag, ReferenceTag>::type type; -}; -template <class T> struct serializer_tag<T *> { - typedef - typename std::conditional<std::is_fundamental<T>::value, - FundamentalPointerTag, PointerTag>::type type; -}; -template <class T> struct serializer_tag<T &> { - typedef typename std::conditional<std::is_fundamental<T>::value, - FundamentalReferenceTag, ReferenceTag>::type - type; -}; - -/// Deserializes data from a buffer. It is used to deserialize function indices -/// to replay, their arguments and return values. -/// -/// Fundamental types and strings are read by value. Objects are read by their -/// index, which get translated by the IndexToObject mapping maintained in -/// this class. -/// -/// Additional bookkeeping with regards to the IndexToObject is required to -/// deserialize objects. When a constructor is run or an object is returned by -/// value, we need to capture the object and add it to the index together with -/// its index. This is the job of HandleReplayResult(Void). -class Deserializer { -public: - Deserializer(llvm::StringRef buffer) : m_buffer(buffer) {} - - /// Returns true when the buffer has unread data. - bool HasData(unsigned size) { return size <= m_buffer.size(); } - - /// Deserialize and interpret value as T. - template <typename T> T Deserialize() { - T t = Read<T>(typename serializer_tag<T>::type()); -#ifdef LLDB_REPRO_INSTR_TRACE - llvm::errs() << "Deserializing with " << LLVM_PRETTY_FUNCTION << " -> " - << stringify_args(t) << "\n"; -#endif - return t; - } - - template <typename T> const T &HandleReplayResult(const T &t) { - CheckSequence(Deserialize<unsigned>()); - unsigned result = Deserialize<unsigned>(); - if (is_trivially_serializable<T>::value) - return t; - // We need to make a copy as the original object might go out of scope. - return *m_index_to_object.AddObjectForIndex(result, new T(t)); - } - - /// Store the returned value in the index-to-object mapping. - template <typename T> T &HandleReplayResult(T &t) { - CheckSequence(Deserialize<unsigned>()); - unsigned result = Deserialize<unsigned>(); - if (is_trivially_serializable<T>::value) - return t; - // We need to make a copy as the original object might go out of scope. - return *m_index_to_object.AddObjectForIndex(result, new T(t)); - } - - /// Store the returned value in the index-to-object mapping. - template <typename T> T *HandleReplayResult(T *t) { - CheckSequence(Deserialize<unsigned>()); - unsigned result = Deserialize<unsigned>(); - if (is_trivially_serializable<T>::value) - return t; - return m_index_to_object.AddObjectForIndex(result, t); - } - - /// All returned types are recorded, even when the function returns a void. - /// The latter requires special handling. - void HandleReplayResultVoid() { - CheckSequence(Deserialize<unsigned>()); - unsigned result = Deserialize<unsigned>(); - assert(result == 0); - (void)result; - } - - std::vector<void *> GetAllObjects() const { - return m_index_to_object.GetAllObjects(); - } - - void SetExpectedSequence(unsigned sequence) { - m_expected_sequence = sequence; - } - -private: - template <typename T> T Read(ValueTag) { - assert(HasData(sizeof(T))); - T t; - std::memcpy(reinterpret_cast<char *>(&t), m_buffer.data(), sizeof(T)); - m_buffer = m_buffer.drop_front(sizeof(T)); - return t; - } - - template <typename T> T Read(PointerTag) { - typedef typename std::remove_pointer<T>::type UnderlyingT; - return m_index_to_object.template GetObjectForIndex<UnderlyingT>( - Deserialize<unsigned>()); - } - - template <typename T> T Read(ReferenceTag) { - typedef typename std::remove_reference<T>::type UnderlyingT; - // If this is a reference to a fundamental type we just read its value. - return *m_index_to_object.template GetObjectForIndex<UnderlyingT>( - Deserialize<unsigned>()); - } - - /// This method is used to parse references to fundamental types. Because - /// they're not recorded in the object table we have serialized their value. - /// We read its value, allocate a copy on the heap, and return a pointer to - /// the copy. - template <typename T> T Read(FundamentalPointerTag) { - typedef typename std::remove_pointer<T>::type UnderlyingT; - return new UnderlyingT(Deserialize<UnderlyingT>()); - } - - /// This method is used to parse references to fundamental types. Because - /// they're not recorded in the object table we have serialized their value. - /// We read its value, allocate a copy on the heap, and return a reference to - /// the copy. - template <typename T> T Read(FundamentalReferenceTag) { - // If this is a reference to a fundamental type we just read its value. - typedef typename std::remove_reference<T>::type UnderlyingT; - return *(new UnderlyingT(Deserialize<UnderlyingT>())); - } - - /// Verify that the given sequence number matches what we expect. - void CheckSequence(unsigned sequence); - - /// Mapping of indices to objects. - IndexToObject m_index_to_object; - - /// Buffer containing the serialized data. - llvm::StringRef m_buffer; - - /// The result's expected sequence number. - llvm::Optional<unsigned> m_expected_sequence; -}; - -/// Partial specialization for C-style strings. We read the string value -/// instead of treating it as pointer. -template <> const char *Deserializer::Deserialize<const char *>(); -template <> const char **Deserializer::Deserialize<const char **>(); -template <> const uint8_t *Deserializer::Deserialize<const uint8_t *>(); -template <> const void *Deserializer::Deserialize<const void *>(); -template <> char *Deserializer::Deserialize<char *>(); -template <> void *Deserializer::Deserialize<void *>(); - -/// Helpers to auto-synthesize function replay code. It deserializes the replay -/// function's arguments one by one and finally calls the corresponding -/// function. -template <typename... Remaining> struct DeserializationHelper; - -template <typename Head, typename... Tail> -struct DeserializationHelper<Head, Tail...> { - template <typename Result, typename... Deserialized> struct deserialized { - static Result doit(Deserializer &deserializer, - Result (*f)(Deserialized..., Head, Tail...), - Deserialized... d) { - return DeserializationHelper<Tail...>:: - template deserialized<Result, Deserialized..., Head>::doit( - deserializer, f, d..., deserializer.Deserialize<Head>()); - } - }; -}; - -template <> struct DeserializationHelper<> { - template <typename Result, typename... Deserialized> struct deserialized { - static Result doit(Deserializer &deserializer, Result (*f)(Deserialized...), - Deserialized... d) { - return f(d...); - } - }; -}; - -/// The replayer interface. -struct Replayer { - virtual ~Replayer() = default; - virtual void operator()(Deserializer &deserializer) const = 0; -}; - -/// The default replayer deserializes the arguments and calls the function. -template <typename Signature> struct DefaultReplayer; -template <typename Result, typename... Args> -struct DefaultReplayer<Result(Args...)> : public Replayer { - DefaultReplayer(Result (*f)(Args...)) : Replayer(), f(f) {} - - void operator()(Deserializer &deserializer) const override { - Replay(deserializer); - } - - Result Replay(Deserializer &deserializer) const { - return deserializer.HandleReplayResult( - DeserializationHelper<Args...>::template deserialized<Result>::doit( - deserializer, f)); - } - - Result (*f)(Args...); -}; - -/// Partial specialization for function returning a void type. It ignores the -/// (absent) return value. -template <typename... Args> -struct DefaultReplayer<void(Args...)> : public Replayer { - DefaultReplayer(void (*f)(Args...)) : Replayer(), f(f) {} - - void operator()(Deserializer &deserializer) const override { - Replay(deserializer); - } - - void Replay(Deserializer &deserializer) const { - DeserializationHelper<Args...>::template deserialized<void>::doit( - deserializer, f); - deserializer.HandleReplayResultVoid(); - } - - void (*f)(Args...); -}; - -/// The registry contains a unique mapping between functions and their ID. The -/// IDs can be serialized and deserialized to replay a function. Functions need -/// to be registered with the registry for this to work. -class Registry { -private: - struct SignatureStr { - SignatureStr(llvm::StringRef result = {}, llvm::StringRef scope = {}, - llvm::StringRef name = {}, llvm::StringRef args = {}) - : result(result), scope(scope), name(name), args(args) {} - - std::string ToString() const; - - llvm::StringRef result; - llvm::StringRef scope; - llvm::StringRef name; - llvm::StringRef args; - }; - -public: - Registry() = default; - virtual ~Registry() = default; - - /// Register a default replayer for a function. - template <typename Signature> - void Register(Signature *f, llvm::StringRef result = {}, - llvm::StringRef scope = {}, llvm::StringRef name = {}, - llvm::StringRef args = {}) { - DoRegister(uintptr_t(f), std::make_unique<DefaultReplayer<Signature>>(f), - SignatureStr(result, scope, name, args)); - } - - /// Register a replayer that invokes a custom function with the same - /// signature as the replayed function. - template <typename Signature> - void Register(Signature *f, Signature *g, llvm::StringRef result = {}, - llvm::StringRef scope = {}, llvm::StringRef name = {}, - llvm::StringRef args = {}) { - DoRegister(uintptr_t(f), std::make_unique<DefaultReplayer<Signature>>(g), - SignatureStr(result, scope, name, args)); - } - - /// Replay functions from a file. - bool Replay(const FileSpec &file); - - /// Replay functions from a buffer. - bool Replay(llvm::StringRef buffer); - - /// Replay functions from a deserializer. - bool Replay(Deserializer &deserializer); - - /// Returns the ID for a given function address. - unsigned GetID(uintptr_t addr); - - /// Get the replayer matching the given ID. - Replayer *GetReplayer(unsigned id); - - std::string GetSignature(unsigned id); - - void CheckID(unsigned expected, unsigned actual); - -protected: - /// Register the given replayer for a function (and the ID mapping). - void DoRegister(uintptr_t RunID, std::unique_ptr<Replayer> replayer, - SignatureStr signature); - -private: - /// Mapping of function addresses to replayers and their ID. - std::map<uintptr_t, std::pair<std::unique_ptr<Replayer>, unsigned>> - m_replayers; - - /// Mapping of IDs to replayer instances. - std::map<unsigned, std::pair<Replayer *, SignatureStr>> m_ids; -}; - -/// Maps an object to an index for serialization. Indices are unique and -/// incremented for every new object. -/// -/// Indices start at 1 in order to differentiate with an invalid index (0) in -/// the serialized buffer. -class ObjectToIndex { -public: - template <typename T> unsigned GetIndexForObject(T *t) { - return GetIndexForObjectImpl(static_cast<const void *>(t)); - } - -private: - unsigned GetIndexForObjectImpl(const void *object); - - llvm::DenseMap<const void *, unsigned> m_mapping; -}; - -/// Serializes functions, their arguments and their return type to a stream. -class Serializer { -public: - Serializer(llvm::raw_ostream &stream = llvm::outs()) : m_stream(stream) {} - - /// Recursively serialize all the given arguments. - template <typename Head, typename... Tail> - void SerializeAll(const Head &head, const Tail &... tail) { - Serialize(head); - SerializeAll(tail...); - } - - void SerializeAll() { m_stream.flush(); } - -private: - /// Serialize pointers. We need to differentiate between pointers to - /// fundamental types (in which case we serialize its value) and pointer to - /// objects (in which case we serialize their index). - template <typename T> void Serialize(T *t) { -#ifdef LLDB_REPRO_INSTR_TRACE - this_thread_id() << "Serializing with " << LLVM_PRETTY_FUNCTION << " -> " - << stringify_args(t) << "\n"; -#endif - if (std::is_fundamental<T>::value) { - Serialize(*t); - } else { - unsigned idx = m_tracker.GetIndexForObject(t); - Serialize(idx); - } - } - - /// Serialize references. We need to differentiate between references to - /// fundamental types (in which case we serialize its value) and references - /// to objects (in which case we serialize their index). - template <typename T> void Serialize(T &t) { -#ifdef LLDB_REPRO_INSTR_TRACE - this_thread_id() << "Serializing with " << LLVM_PRETTY_FUNCTION << " -> " - << stringify_args(t) << "\n"; -#endif - if (is_trivially_serializable<T>::value) { - m_stream.write(reinterpret_cast<const char *>(&t), sizeof(T)); - } else { - unsigned idx = m_tracker.GetIndexForObject(&t); - Serialize(idx); - } - } - - void Serialize(const void *v) { - // FIXME: Support void* - } - - void Serialize(void *v) { - // FIXME: Support void* - } - - void Serialize(const char *t) { -#ifdef LLDB_REPRO_INSTR_TRACE - this_thread_id() << "Serializing with " << LLVM_PRETTY_FUNCTION << " -> " - << stringify_args(t) << "\n"; -#endif - const size_t size = t ? strlen(t) : std::numeric_limits<size_t>::max(); - Serialize(size); - if (t) { - m_stream << t; - m_stream.write(0x0); - } - } - - void Serialize(const char **t) { - size_t size = 0; - if (!t) { - Serialize(size); - return; - } - - // Compute the size of the array. - const char *const *temp = t; - while (*temp++) - size++; - Serialize(size); - - // Serialize the content of the array. - while (*t) - Serialize(*t++); - } - - /// Serialization stream. - llvm::raw_ostream &m_stream; - - /// Mapping of objects to indices. - ObjectToIndex m_tracker; -}; // namespace repro - -class InstrumentationData { -public: - Serializer *GetSerializer() { return m_serializer; } - Deserializer *GetDeserializer() { return m_deserializer; } - Registry &GetRegistry() { return *m_registry; } - - operator bool() { - return (m_serializer != nullptr || m_deserializer != nullptr) && - m_registry != nullptr; - } - - static void Initialize(Serializer &serializer, Registry ®istry); - static void Initialize(Deserializer &serializer, Registry ®istry); - static InstrumentationData &Instance(); - -protected: - friend llvm::optional_detail::OptionalStorage<InstrumentationData, true>; - friend llvm::Optional<InstrumentationData>; - - InstrumentationData() = default; - InstrumentationData(Serializer &serializer, Registry ®istry) - : m_serializer(&serializer), m_deserializer(nullptr), - m_registry(®istry) {} - InstrumentationData(Deserializer &deserializer, Registry ®istry) - : m_serializer(nullptr), m_deserializer(&deserializer), - m_registry(®istry) {} - -private: - static llvm::Optional<InstrumentationData> &InstanceImpl(); - - Serializer *m_serializer = nullptr; - Deserializer *m_deserializer = nullptr; - Registry *m_registry = nullptr; -}; - -struct EmptyArg {}; - -/// RAII object that records function invocations and their return value. -/// -/// API calls are only captured when the API boundary is crossed. Once we're in -/// the API layer, and another API function is called, it doesn't need to be -/// recorded. -/// -/// When a call is recored, its result is always recorded as well, even if the -/// function returns a void. For functions that return by value, RecordResult -/// should be used. Otherwise a sentinel value (0) will be serialized. -/// -/// Because of the functional overlap between logging and recording API calls, -/// this class is also used for logging. -class Recorder { -public: - Recorder(); - Recorder(llvm::StringRef pretty_func, std::string &&pretty_args = {}); - ~Recorder(); - - /// Records a single function call. - template <typename Result, typename... FArgs, typename... RArgs> - void Record(Serializer &serializer, Registry ®istry, Result (*f)(FArgs...), - const RArgs &... args) { - m_serializer = &serializer; - if (!ShouldCapture()) - return; - - std::lock_guard<std::mutex> lock(g_mutex); - unsigned sequence = GetSequenceNumber(); - unsigned id = registry.GetID(uintptr_t(f)); - -#ifdef LLDB_REPRO_INSTR_TRACE - Log(id); -#endif - - serializer.SerializeAll(sequence); - serializer.SerializeAll(id); - serializer.SerializeAll(args...); - - if (std::is_class<typename std::remove_pointer< - typename std::remove_reference<Result>::type>::type>::value) { - m_result_recorded = false; - } else { - serializer.SerializeAll(sequence); - serializer.SerializeAll(0); - m_result_recorded = true; - } - } - - /// Records a single function call. - template <typename... Args> - void Record(Serializer &serializer, Registry ®istry, void (*f)(Args...), - const Args &... args) { - m_serializer = &serializer; - if (!ShouldCapture()) - return; - - std::lock_guard<std::mutex> lock(g_mutex); - unsigned sequence = GetSequenceNumber(); - unsigned id = registry.GetID(uintptr_t(f)); - -#ifdef LLDB_REPRO_INSTR_TRACE - Log(id); -#endif - - serializer.SerializeAll(sequence); - serializer.SerializeAll(id); - serializer.SerializeAll(args...); - - // Record result. - serializer.SerializeAll(sequence); - serializer.SerializeAll(0); - m_result_recorded = true; - } - - /// Specializations for the no-argument methods. These are passed an empty - /// dummy argument so the same variadic macro can be used. These methods - /// strip the arguments before forwarding them. - template <typename Result> - void Record(Serializer &serializer, Registry ®istry, Result (*f)(), - const EmptyArg &arg) { - Record(serializer, registry, f); - } - - /// Record the result of a function call. - template <typename Result> - Result RecordResult(Result &&r, bool update_boundary) { - // When recording the result from the LLDB_RECORD_RESULT macro, we need to - // update the boundary so we capture the copy constructor. However, when - // called to record the this pointer of the (copy) constructor, the - // boundary should not be toggled, because it is called from the - // LLDB_RECORD_CONSTRUCTOR macro, which might be followed by other API - // calls. - if (update_boundary) - UpdateBoundary(); - if (m_serializer && ShouldCapture()) { - std::lock_guard<std::mutex> lock(g_mutex); - assert(!m_result_recorded); - m_serializer->SerializeAll(GetSequenceNumber()); - m_serializer->SerializeAll(r); - m_result_recorded = true; - } - return std::forward<Result>(r); - } - - template <typename Result, typename T> - Result Replay(Deserializer &deserializer, Registry ®istry, uintptr_t addr, - bool update_boundary) { - deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>()); - unsigned actual_id = registry.GetID(addr); - unsigned id = deserializer.Deserialize<unsigned>(); - registry.CheckID(id, actual_id); - return ReplayResult<Result>( - static_cast<DefaultReplayer<T> *>(registry.GetReplayer(id)) - ->Replay(deserializer), - update_boundary); - } - - void Replay(Deserializer &deserializer, Registry ®istry, uintptr_t addr) { - deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>()); - unsigned actual_id = registry.GetID(addr); - unsigned id = deserializer.Deserialize<unsigned>(); - registry.CheckID(id, actual_id); - registry.GetReplayer(id)->operator()(deserializer); - } - - template <typename Result> - Result ReplayResult(Result &&r, bool update_boundary) { - if (update_boundary) - UpdateBoundary(); - return std::forward<Result>(r); - } - - bool ShouldCapture() { return m_local_boundary; } - - /// Mark the current thread as a private thread and pretend that everything - /// on this thread is behind happening behind the API boundary. - static void PrivateThread(); - -private: - static unsigned GetNextSequenceNumber() { return g_sequence++; } - unsigned GetSequenceNumber() const; - - template <typename T> friend struct replay; - void UpdateBoundary(); - -#ifdef LLDB_REPRO_INSTR_TRACE - void Log(unsigned id) { - this_thread_id() << "Recording " << id << ": " << m_pretty_func << " (" - << m_pretty_args << ")\n"; - } -#endif - - Serializer *m_serializer = nullptr; - - /// Pretty function for logging. - llvm::StringRef m_pretty_func; - std::string m_pretty_args; - - /// Whether this function call was the one crossing the API boundary. - bool m_local_boundary = false; - - /// Whether the return value was recorded explicitly. - bool m_result_recorded = true; - - /// The sequence number for this pair of function and result. - unsigned m_sequence; - - /// Global mutex to protect concurrent access. - static std::mutex g_mutex; - - /// Unique, monotonically increasing sequence number. - static std::atomic<unsigned> g_sequence; -}; - -/// To be used as the "Runtime ID" of a constructor. It also invokes the -/// constructor when called. -template <typename Signature> struct construct; -template <typename Class, typename... Args> struct construct<Class(Args...)> { - static Class *handle(lldb_private::repro::InstrumentationData data, - lldb_private::repro::Recorder &recorder, Class *c, - const EmptyArg &) { - return handle(data, recorder, c); - } - - static Class *handle(lldb_private::repro::InstrumentationData data, - lldb_private::repro::Recorder &recorder, Class *c, - Args... args) { - if (!data) - return nullptr; - - if (Serializer *serializer = data.GetSerializer()) { - recorder.Record(*serializer, data.GetRegistry(), &record, args...); - recorder.RecordResult(c, false); - } else if (Deserializer *deserializer = data.GetDeserializer()) { - if (recorder.ShouldCapture()) { - replay(recorder, *deserializer, data.GetRegistry()); - } - } - - return nullptr; - } - - static Class *record(Args... args) { return new Class(args...); } - - static Class *replay(Recorder &recorder, Deserializer &deserializer, - Registry ®istry) { - return recorder.Replay<Class *, Class *(Args...)>( - deserializer, registry, uintptr_t(&record), false); - } -}; - -/// To be used as the "Runtime ID" of a member function. It also invokes the -/// member function when called. -template <typename Signature> struct invoke; -template <typename Result, typename Class, typename... Args> -struct invoke<Result (Class::*)(Args...)> { - template <Result (Class::*m)(Args...)> struct method { - static Result record(Class *c, Args... args) { return (c->*m)(args...); } - - static Result replay(Recorder &recorder, Deserializer &deserializer, - Registry ®istry) { - return recorder.Replay<Result, Result(Class *, Args...)>( - deserializer, registry, uintptr_t(&record), true); - } - }; -}; - -template <typename Class, typename... Args> -struct invoke<void (Class::*)(Args...)> { - template <void (Class::*m)(Args...)> struct method { - static void record(Class *c, Args... args) { (c->*m)(args...); } - static void replay(Recorder &recorder, Deserializer &deserializer, - Registry ®istry) { - recorder.Replay(deserializer, registry, uintptr_t(&record)); - } - }; -}; - -template <typename Result, typename Class, typename... Args> -struct invoke<Result (Class::*)(Args...) const> { - template <Result (Class::*m)(Args...) const> struct method { - static Result record(Class *c, Args... args) { return (c->*m)(args...); } - static Result replay(Recorder &recorder, Deserializer &deserializer, - Registry ®istry) { - return recorder.Replay<Result, Result(Class *, Args...)>( - deserializer, registry, uintptr_t(&record), true); - } - }; -}; - -template <typename Class, typename... Args> -struct invoke<void (Class::*)(Args...) const> { - template <void (Class::*m)(Args...) const> struct method { - static void record(Class *c, Args... args) { return (c->*m)(args...); } - static void replay(Recorder &recorder, Deserializer &deserializer, - Registry ®istry) { - recorder.Replay(deserializer, registry, uintptr_t(&record)); - } - }; -}; - -template <typename Signature> struct replay; - -template <typename Result, typename Class, typename... Args> -struct replay<Result (Class::*)(Args...)> { - template <Result (Class::*m)(Args...)> struct method {}; -}; - -template <typename Result, typename... Args> -struct invoke<Result (*)(Args...)> { - template <Result (*m)(Args...)> struct method { - static Result record(Args... args) { return (*m)(args...); } - static Result replay(Recorder &recorder, Deserializer &deserializer, - Registry ®istry) { - return recorder.Replay<Result, Result(Args...)>(deserializer, registry, - uintptr_t(&record), true); - } - }; -}; - -template <typename... Args> struct invoke<void (*)(Args...)> { - template <void (*m)(Args...)> struct method { - static void record(Args... args) { return (*m)(args...); } - static void replay(Recorder &recorder, Deserializer &deserializer, - Registry ®istry) { - recorder.Replay(deserializer, registry, uintptr_t(&record)); - } - }; -}; - -/// Special handling for functions returning strings as (char*, size_t). -/// { - -/// For inline replay, we ignore the arguments and use the ones from the -/// serializer instead. This doesn't work for methods that use a char* and a -/// size to return a string. For one these functions have a custom replayer to -/// prevent override the input buffer. Furthermore, the template-generated -/// deserialization is not easy to hook into. -/// -/// The specializations below hand-implement the serialization logic for the -/// inline replay. Instead of using the function from the registry, it uses the -/// one passed into the macro. -template <typename Signature> struct invoke_char_ptr; -template <typename Result, typename Class, typename... Args> -struct invoke_char_ptr<Result (Class::*)(Args...) const> { - template <Result (Class::*m)(Args...) const> struct method { - static Result record(Class *c, char *s, size_t l) { - char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char))); - return (c->*m)(buffer, l); - } - - static Result replay(Recorder &recorder, Deserializer &deserializer, - Registry ®istry, char *str) { - deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>()); - deserializer.Deserialize<unsigned>(); - Class *c = deserializer.Deserialize<Class *>(); - deserializer.Deserialize<const char *>(); - size_t l = deserializer.Deserialize<size_t>(); - return recorder.ReplayResult( - std::move(deserializer.HandleReplayResult((c->*m)(str, l))), true); - } - }; -}; - -template <typename Signature> struct invoke_char_ptr; -template <typename Result, typename Class, typename... Args> -struct invoke_char_ptr<Result (Class::*)(Args...)> { - template <Result (Class::*m)(Args...)> struct method { - static Result record(Class *c, char *s, size_t l) { - char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char))); - return (c->*m)(buffer, l); - } - - static Result replay(Recorder &recorder, Deserializer &deserializer, - Registry ®istry, char *str) { - deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>()); - deserializer.Deserialize<unsigned>(); - Class *c = deserializer.Deserialize<Class *>(); - deserializer.Deserialize<const char *>(); - size_t l = deserializer.Deserialize<size_t>(); - return recorder.ReplayResult( - std::move(deserializer.HandleReplayResult((c->*m)(str, l))), true); - } - }; -}; - -template <typename Result, typename... Args> -struct invoke_char_ptr<Result (*)(Args...)> { - template <Result (*m)(Args...)> struct method { - static Result record(char *s, size_t l) { - char *buffer = reinterpret_cast<char *>(calloc(l, sizeof(char))); - return (*m)(buffer, l); - } - - static Result replay(Recorder &recorder, Deserializer &deserializer, - Registry ®istry, char *str) { - deserializer.SetExpectedSequence(deserializer.Deserialize<unsigned>()); - deserializer.Deserialize<unsigned>(); - deserializer.Deserialize<const char *>(); - size_t l = deserializer.Deserialize<size_t>(); - return recorder.ReplayResult( - std::move(deserializer.HandleReplayResult((*m)(str, l))), true); - } - }; -}; -/// } - -} // namespace repro -} // namespace lldb_private - -#endif // LLDB_UTILITY_REPRODUCERINSTRUMENTATION_H diff --git a/lldb/include/lldb/Utility/ReproducerProvider.h b/lldb/include/lldb/Utility/ReproducerProvider.h index db7378069a87..56aadf92369e 100644 --- a/lldb/include/lldb/Utility/ReproducerProvider.h +++ b/lldb/include/lldb/Utility/ReproducerProvider.h @@ -222,8 +222,7 @@ public: /// Provider for mapping UUIDs to symbol and executable files. class SymbolFileProvider : public Provider<SymbolFileProvider> { public: - SymbolFileProvider(const FileSpec &directory) - : Provider(directory), m_symbol_files() {} + SymbolFileProvider(const FileSpec &directory) : Provider(directory) {} void AddSymbolFile(const UUID *uuid, const FileSpec &module_path, const FileSpec &symbol_path); diff --git a/lldb/include/lldb/Utility/SharedCluster.h b/lldb/include/lldb/Utility/SharedCluster.h index 375c1c131a09..b3f41dbaa64b 100644 --- a/lldb/include/lldb/Utility/SharedCluster.h +++ b/lldb/include/lldb/Utility/SharedCluster.h @@ -48,7 +48,7 @@ public: } private: - ClusterManager() : m_objects(), m_mutex() {} + ClusterManager() : m_objects() {} llvm::SmallVector<T *, 16> m_objects; std::mutex m_mutex; diff --git a/lldb/include/lldb/Utility/StreamTee.h b/lldb/include/lldb/Utility/StreamTee.h index b5d3b9679e91..5695586171f3 100644 --- a/lldb/include/lldb/Utility/StreamTee.h +++ b/lldb/include/lldb/Utility/StreamTee.h @@ -19,18 +19,15 @@ namespace lldb_private { class StreamTee : public Stream { public: - StreamTee(bool colors = false) - : Stream(colors), m_streams_mutex(), m_streams() {} + StreamTee(bool colors = false) : Stream(colors) {} - StreamTee(lldb::StreamSP &stream_sp) - : Stream(), m_streams_mutex(), m_streams() { + StreamTee(lldb::StreamSP &stream_sp) { // No need to lock mutex during construction if (stream_sp) m_streams.push_back(stream_sp); } - StreamTee(lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp) - : Stream(), m_streams_mutex(), m_streams() { + StreamTee(lldb::StreamSP &stream_sp, lldb::StreamSP &stream_2_sp) { // No need to lock mutex during construction if (stream_sp) m_streams.push_back(stream_sp); @@ -38,8 +35,7 @@ public: m_streams.push_back(stream_2_sp); } - StreamTee(const StreamTee &rhs) - : Stream(rhs), m_streams_mutex(), m_streams() { + StreamTee(const StreamTee &rhs) : Stream(rhs) { // Don't copy until we lock down "rhs" std::lock_guard<std::recursive_mutex> guard(rhs.m_streams_mutex); m_streams = rhs.m_streams; diff --git a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h index 1712c113d396..459adae04452 100644 --- a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h +++ b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h @@ -23,7 +23,7 @@ public: typedef bool (*ResponseValidatorCallback)( void *baton, const StringExtractorGDBRemote &response); - StringExtractorGDBRemote() : StringExtractor() {} + StringExtractorGDBRemote() {} StringExtractorGDBRemote(llvm::StringRef str) : StringExtractor(str), m_validator(nullptr) {} diff --git a/lldb/include/lldb/Utility/StringList.h b/lldb/include/lldb/Utility/StringList.h index 70f4654a6ac9..1357cf17173a 100644 --- a/lldb/include/lldb/Utility/StringList.h +++ b/lldb/include/lldb/Utility/StringList.h @@ -10,6 +10,7 @@ #define LLDB_UTILITY_STRINGLIST_H #include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Twine.h" #include <cstddef> #include <string> @@ -44,6 +45,8 @@ public: void AppendString(llvm::StringRef str); + void AppendString(const llvm::Twine &str); + void AppendList(const char **strv, int strc); void AppendList(StringList strings); diff --git a/lldb/include/lldb/Utility/StructuredData.h b/lldb/include/lldb/Utility/StructuredData.h index c1d136db1c2e..11eee92f8c3b 100644 --- a/lldb/include/lldb/Utility/StructuredData.h +++ b/lldb/include/lldb/Utility/StructuredData.h @@ -351,10 +351,9 @@ public: class Dictionary : public Object { public: - Dictionary() : Object(lldb::eStructuredDataTypeDictionary), m_dict() {} + Dictionary() : Object(lldb::eStructuredDataTypeDictionary) {} - Dictionary(ObjectSP obj_sp) - : Object(lldb::eStructuredDataTypeDictionary), m_dict() { + Dictionary(ObjectSP obj_sp) : Object(lldb::eStructuredDataTypeDictionary) { if (!obj_sp || obj_sp->GetType() != lldb::eStructuredDataTypeDictionary) { SetType(lldb::eStructuredDataTypeInvalid); return; diff --git a/lldb/include/lldb/Utility/UserIDResolver.h b/lldb/include/lldb/Utility/UserIDResolver.h index e0f7b69cc075..15afafd65a1a 100644 --- a/lldb/include/lldb/Utility/UserIDResolver.h +++ b/lldb/include/lldb/Utility/UserIDResolver.h @@ -10,6 +10,7 @@ #define LLDB_UTILITY_USERIDRESOLVER_H #include "llvm/ADT/DenseMap.h" +#include "llvm/ADT/Optional.h" #include "llvm/ADT/StringRef.h" #include <mutex> diff --git a/lldb/include/lldb/lldb-defines.h b/lldb/include/lldb/lldb-defines.h index 4bf01c3f86c6..339071bbfc31 100644 --- a/lldb/include/lldb/lldb-defines.h +++ b/lldb/include/lldb/lldb-defines.h @@ -11,18 +11,6 @@ #include "lldb/lldb-types.h" -#if defined(_WIN32) -#if defined(EXPORT_LIBLLDB) -#define LLDB_API __declspec(dllexport) -#elif defined(IMPORT_LIBLLDB) -#define LLDB_API __declspec(dllimport) -#else -#define LLDB_API -#endif -#else // defined (_WIN32) -#define LLDB_API -#endif - #if !defined(INT32_MAX) #define INT32_MAX 2147483647 #endif diff --git a/lldb/include/lldb/module.modulemap b/lldb/include/lldb/module.modulemap index c0d467a6505e..303d6b15e808 100644 --- a/lldb/include/lldb/module.modulemap +++ b/lldb/include/lldb/module.modulemap @@ -2,7 +2,7 @@ module lldb_API { requires cplusplus - textual header "Utility/ReproducerInstrumentation.h" + textual header "Utility/Instrumentation.h" umbrella "API" module * { export * } |