diff options
Diffstat (limited to 'contrib/llvm-project/lldb/include/lldb/Core')
61 files changed, 12726 insertions, 0 deletions
diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Address.h b/contrib/llvm-project/lldb/include/lldb/Core/Address.h new file mode 100644 index 000000000000..07bb450d6092 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/Address.h @@ -0,0 +1,508 @@ +//===-- Address.h -----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Address_h_ +#define liblldb_Address_h_ + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private-enumerations.h" +#include "lldb/lldb-types.h" + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class Block; +class CompileUnit; +class ExecutionContextScope; +class Function; +class SectionList; +class Stream; +class Symbol; +class SymbolContext; +class Target; +struct LineEntry; + +/// \class Address Address.h "lldb/Core/Address.h" +/// A section + offset based address class. +/// +/// The Address class allows addresses to be relative to a section that can +/// move during runtime due to images (executables, shared libraries, bundles, +/// frameworks) being loaded at different addresses than the addresses found +/// in the object file that represents them on disk. There are currently two +/// types of addresses for a section: +/// \li file addresses +/// \li load addresses +/// +/// File addresses represent the virtual addresses that are in the "on disk" +/// object files. These virtual addresses are converted to be relative to +/// unique sections scoped to the object file so that when/if the addresses +/// slide when the images are loaded/unloaded in memory, we can easily track +/// these changes without having to update every object (compile unit ranges, +/// line tables, function address ranges, lexical block and inlined subroutine +/// address ranges, global and static variables) each time an image is loaded +/// or unloaded. +/// +/// Load addresses represent the virtual addresses where each section ends up +/// getting loaded at runtime. Before executing a program, it is common for +/// all of the load addresses to be unresolved. When a DynamicLoader plug-in +/// receives notification that shared libraries have been loaded/unloaded, the +/// load addresses of the main executable and any images (shared libraries) +/// will be resolved/unresolved. When this happens, breakpoints that are in +/// one of these sections can be set/cleared. +class Address { +public: + /// Dump styles allow the Address::Dump(Stream *,DumpStyle) const function + /// to display Address contents in a variety of ways. + enum DumpStyle { + DumpStyleInvalid, ///< Invalid dump style + DumpStyleSectionNameOffset, ///< Display as the section name + offset. + ///< \code + /// // address for printf in libSystem.B.dylib as a section name + offset + /// libSystem.B.dylib.__TEXT.__text + 0x0005cfdf \endcode + DumpStyleSectionPointerOffset, ///< Display as the section pointer + offset + ///(debug output). + ///< \code + /// // address for printf in libSystem.B.dylib as a section pointer + + /// offset (lldb::Section *)0x35cc50 + 0x000000000005cfdf \endcode + DumpStyleFileAddress, ///< Display as the file address (if any). + ///< \code + /// // address for printf in libSystem.B.dylib as a file address + /// 0x000000000005dcff \endcode + DumpStyleModuleWithFileAddress, ///< Display as the file address with the + /// module name prepended (if any). + ///< \code + /// // address for printf in libSystem.B.dylib as a file address + /// libSystem.B.dylib[0x000000000005dcff] \endcode + DumpStyleLoadAddress, ///< Display as the load address (if resolved). + ///< \code + /// // address for printf in libSystem.B.dylib as a load address + /// 0x00007fff8306bcff \endcode + DumpStyleResolvedDescription, ///< Display the details about what an address + /// resolves to. This can + ///< be anything from a symbol context summary (module, function/symbol, + ///< and file and line), to information about what the pointer points to + ///< if the address is in a section (section of pointers, c strings, etc). + DumpStyleResolvedDescriptionNoModule, + DumpStyleResolvedDescriptionNoFunctionArguments, + DumpStyleNoFunctionName, ///< Elide the function name; display an offset + /// into the current function. + ///< Used primarily in disassembly symbolication + DumpStyleDetailedSymbolContext, ///< Detailed symbol context information for + /// an address for all symbol + ///< context members. + DumpStyleResolvedPointerDescription ///< Dereference a pointer at the + /// current address and then lookup the + ///< dereferenced address using DumpStyleResolvedDescription + }; + + /// Default constructor. + /// + /// Initialize with a invalid section (NULL) and an invalid offset + /// (LLDB_INVALID_ADDRESS). + Address() : m_section_wp(), m_offset(LLDB_INVALID_ADDRESS) {} + + /// Copy constructor + /// + /// Makes a copy of the another Address object \a rhs. + /// + /// \param[in] rhs + /// A const Address object reference to copy. + Address(const Address &rhs) + : m_section_wp(rhs.m_section_wp), m_offset(rhs.m_offset) {} + + /// Construct with a section pointer and offset. + /// + /// Initialize the address with the supplied \a section and \a offset. + /// + /// \param[in] section + /// A section pointer to a valid lldb::Section, or NULL if the + /// address doesn't have a section or will get resolved later. + /// + /// \param[in] offset + /// The offset in bytes into \a section. + Address(const lldb::SectionSP §ion_sp, lldb::addr_t offset) + : m_section_wp(), // Don't init with section_sp in case section_sp is + // invalid (the weak_ptr will throw) + m_offset(offset) { + if (section_sp) + m_section_wp = section_sp; + } + + /// Construct with a virtual address and section list. + /// + /// Initialize and resolve the address with the supplied virtual address \a + /// file_addr. + /// + /// \param[in] file_addr + /// A virtual file address. + /// + /// \param[in] section_list + /// A list of sections, one of which may contain the \a file_addr. + Address(lldb::addr_t file_addr, const SectionList *section_list); + + Address(lldb::addr_t abs_addr); + +/// Assignment operator. +/// +/// Copies the address value from another Address object \a rhs into \a this +/// object. +/// +/// \param[in] rhs +/// A const Address object reference to copy. +/// +/// \return +/// A const Address object reference to \a this. + const Address &operator=(const Address &rhs); + + /// Clear the object's state. + /// + /// Sets the section to an invalid value (NULL) and an invalid offset + /// (LLDB_INVALID_ADDRESS). + void Clear() { + m_section_wp.reset(); + m_offset = LLDB_INVALID_ADDRESS; + } + + /// Compare two Address objects. + /// + /// \param[in] lhs + /// The Left Hand Side const Address object reference. + /// + /// \param[in] rhs + /// The Right Hand Side const Address object reference. + /// + /// \return + /// \li -1 if lhs < rhs + /// \li 0 if lhs == rhs + /// \li 1 if lhs > rhs + static int CompareFileAddress(const Address &lhs, const Address &rhs); + + static int CompareLoadAddress(const Address &lhs, const Address &rhs, + Target *target); + + static int CompareModulePointerAndOffset(const Address &lhs, + const Address &rhs); + + // For use with std::map, std::multi_map + class ModulePointerAndOffsetLessThanFunctionObject { + public: + ModulePointerAndOffsetLessThanFunctionObject() = default; + + bool operator()(const Address &a, const Address &b) const { + return Address::CompareModulePointerAndOffset(a, b) < 0; + } + }; + + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the supplied stream + /// \a s. There are many ways to display a section offset based address, and + /// \a style lets the user choose. + /// + /// \param[in] s + /// The stream to which to dump the object description. + /// + /// \param[in] style + /// The display style for the address. + /// + /// \param[in] fallback_style + /// The display style for the address. + /// + /// \return + /// Returns \b true if the address was able to be displayed. + /// File and load addresses may be unresolved and it may not be + /// possible to display a valid value, \b false will be returned + /// in such cases. + /// + /// \see Address::DumpStyle + bool Dump(Stream *s, ExecutionContextScope *exe_scope, DumpStyle style, + DumpStyle fallback_style = DumpStyleInvalid, + uint32_t addr_byte_size = UINT32_MAX) const; + + AddressClass GetAddressClass() const; + + /// Get the file address. + /// + /// If an address comes from a file on disk that has section relative + /// addresses, then it has a virtual address that is relative to unique + /// section in the object file. + /// + /// \return + /// The valid file virtual address, or LLDB_INVALID_ADDRESS if + /// the address doesn't have a file virtual address (image is + /// from memory only with no representation on disk). + lldb::addr_t GetFileAddress() const; + + /// Get the load address. + /// + /// If an address comes from a file on disk that has section relative + /// addresses, then it has a virtual address that is relative to unique + /// section in the object file. Sections get resolved at runtime by + /// DynamicLoader plug-ins as images (executables and shared libraries) get + /// loaded/unloaded. If a section is loaded, then the load address can be + /// resolved. + /// + /// \return + /// The valid load virtual address, or LLDB_INVALID_ADDRESS if + /// the address is currently not loaded. + lldb::addr_t GetLoadAddress(Target *target) const; + + /// Get the load address as a callable code load address. + /// + /// This function will first resolve its address to a load address. Then, if + /// the address turns out to be in code address, return the load address + /// that would be required to call or return to. The address might have + /// extra bits set (bit zero will be set to Thumb functions for an ARM + /// target) that are required when changing the program counter to setting a + /// return address. + /// + /// \return + /// The valid load virtual address, or LLDB_INVALID_ADDRESS if + /// the address is currently not loaded. + lldb::addr_t GetCallableLoadAddress(Target *target, + bool is_indirect = false) const; + + /// Get the load address as an opcode load address. + /// + /// This function will first resolve its address to a load address. Then, if + /// the address turns out to be in code address, return the load address for + /// an opcode. This address object might have extra bits set (bit zero will + /// be set to Thumb functions for an + /// ARM target) that are required for changing the program counter + /// and this function will remove any bits that are intended for these + /// special purposes. The result of this function can be used to safely + /// write a software breakpoint trap to memory. + /// + /// \return + /// The valid load virtual address with extra callable bits + /// removed, or LLDB_INVALID_ADDRESS if the address is currently + /// not loaded. + lldb::addr_t GetOpcodeLoadAddress( + Target *target, + AddressClass addr_class = AddressClass::eInvalid) const; + + /// Get the section relative offset value. + /// + /// \return + /// The current offset, or LLDB_INVALID_ADDRESS if this address + /// doesn't contain a valid offset. + lldb::addr_t GetOffset() const { return m_offset; } + + /// Check if an address is section offset. + /// + /// When converting a virtual file or load address into a section offset + /// based address, we often need to know if, given a section list, if the + /// address was able to be converted to section offset. This function + /// returns true if the current value contained in this object is section + /// offset based. + /// + /// \return + /// Returns \b true if the address has a valid section and + /// offset, \b false otherwise. + bool IsSectionOffset() const { + return IsValid() && (GetSection().get() != nullptr); + } + + /// Check if the object state is valid. + /// + /// A valid Address object contains either a section pointer and + /// offset (for section offset based addresses), or just a valid offset + /// (for absolute addresses that have no section). + /// + /// \return + /// Returns \b true if the offset is valid, \b false + /// otherwise. + bool IsValid() const { return m_offset != LLDB_INVALID_ADDRESS; } + + /// Get the memory cost of this object. + /// + /// \return + /// The number of bytes that this object occupies in memory. + size_t MemorySize() const; + + /// Resolve a file virtual address using a section list. + /// + /// Given a list of sections, attempt to resolve \a addr as an offset into + /// one of the file sections. + /// + /// \return + /// Returns \b true if \a addr was able to be resolved, \b false + /// otherwise. + bool ResolveAddressUsingFileSections(lldb::addr_t addr, + const SectionList *sections); + + /// Resolve this address to its containing function and optionally get + /// that function's address range. + /// + /// \param[out] sym_ctx + /// The symbol context describing the function in which this address lies + /// + /// \parm[out] addr_range_ptr + /// Pointer to the AddressRange to fill in with the function's address + /// range. Caller may pass null if they don't need the address range. + /// + /// \return + /// Returns \b false if the function/symbol could not be resolved + /// or if the address range was requested and could not be resolved; + /// returns \b true otherwise. + bool ResolveFunctionScope(lldb_private::SymbolContext &sym_ctx, + lldb_private::AddressRange *addr_range_ptr = nullptr); + + /// Set the address to represent \a load_addr. + /// + /// The address will attempt to find a loaded section within \a target that + /// contains \a load_addr. If successful, this address object will have a + /// valid section and offset. Else this address object will have no section + /// (NULL) and the offset will be \a load_addr. + /// + /// \param[in] load_addr + /// A load address from a current process. + /// + /// \param[in] target + /// The target to use when trying resolve the address into + /// a section + offset. The Target's SectionLoadList object + /// is used to resolve the address. + /// + /// \param[in] allow_section_end + /// If true, treat an address pointing to the end of the module as + /// belonging to that module. + /// + /// \return + /// Returns \b true if the load address was resolved to be + /// section/offset, \b false otherwise. It is often ok for an + /// address to not resolve to a section in a module, this often + /// happens for JIT'ed code, or any load addresses on the stack + /// or heap. + bool SetLoadAddress(lldb::addr_t load_addr, Target *target, + bool allow_section_end = false); + + bool SetOpcodeLoadAddress( + lldb::addr_t load_addr, Target *target, + AddressClass addr_class = AddressClass::eInvalid, + bool allow_section_end = false); + + bool SetCallableLoadAddress(lldb::addr_t load_addr, Target *target); + + /// Get accessor for the module for this address. + /// + /// \return + /// Returns the Module pointer that this address is an offset + /// in, or NULL if this address doesn't belong in a module, or + /// isn't resolved yet. + lldb::ModuleSP GetModule() const; + + /// Get const accessor for the section. + /// + /// \return + /// Returns the const lldb::Section pointer that this address is an + /// offset in, or NULL if this address is absolute. + lldb::SectionSP GetSection() const { return m_section_wp.lock(); } + + /// Set accessor for the offset. + /// + /// \param[in] offset + /// A new offset value for this object. + /// + /// \return + /// Returns \b true if the offset changed, \b false otherwise. + bool SetOffset(lldb::addr_t offset) { + bool changed = m_offset != offset; + m_offset = offset; + return changed; + } + + void SetRawAddress(lldb::addr_t addr) { + m_section_wp.reset(); + m_offset = addr; + } + + bool Slide(int64_t offset) { + if (m_offset != LLDB_INVALID_ADDRESS) { + m_offset += offset; + return true; + } + return false; + } + + /// Set accessor for the section. + /// + /// \param[in] section + /// A new lldb::Section pointer to use as the section base. Can + /// be NULL for absolute addresses that are not relative to + /// any section. + void SetSection(const lldb::SectionSP §ion_sp) { + m_section_wp = section_sp; + } + + void ClearSection() { m_section_wp.reset(); } + + /// Reconstruct a symbol context from an address. + /// + /// This class doesn't inherit from SymbolContextScope because many address + /// objects have short lifespans. Address objects that are section offset + /// can reconstruct their symbol context by looking up the address in the + /// module found in the section. + /// + /// \see SymbolContextScope::CalculateSymbolContext(SymbolContext*) + uint32_t CalculateSymbolContext(SymbolContext *sc, + lldb::SymbolContextItem resolve_scope = + lldb::eSymbolContextEverything) const; + + lldb::ModuleSP CalculateSymbolContextModule() const; + + CompileUnit *CalculateSymbolContextCompileUnit() const; + + Function *CalculateSymbolContextFunction() const; + + Block *CalculateSymbolContextBlock() const; + + Symbol *CalculateSymbolContextSymbol() const; + + bool CalculateSymbolContextLineEntry(LineEntry &line_entry) const; + + // Returns true if the section should be valid, but isn't because the shared + // pointer to the section can't be reconstructed from a weak pointer that + // contains a valid weak reference to a section. Returns false if the section + // weak pointer has no reference to a section, or if the section is still + // valid + bool SectionWasDeleted() const; + +protected: + // Member variables. + lldb::SectionWP m_section_wp; ///< The section for the address, can be NULL. + lldb::addr_t m_offset; ///< Offset into section if \a m_section_wp is valid... + + // Returns true if the m_section_wp once had a reference to a valid section + // shared pointer, but no longer does. This can happen if we have an address + // from a module that gets unloaded and deleted. This function should only be + // called if GetSection() returns an empty shared pointer and you want to + // know if this address used to have a valid section. + bool SectionWasDeletedPrivate() const; +}; + +// NOTE: Be careful using this operator. It can correctly compare two +// addresses from the same Module correctly. It can't compare two addresses +// from different modules in any meaningful way, but it will compare the module +// pointers. +// +// To sum things up: +// - works great for addresses within the same module - it works for addresses +// across multiple modules, but don't expect the +// address results to make much sense +// +// This basically lets Address objects be used in ordered collection classes. +bool operator<(const Address &lhs, const Address &rhs); +bool operator>(const Address &lhs, const Address &rhs); +bool operator==(const Address &lhs, const Address &rhs); +bool operator!=(const Address &lhs, const Address &rhs); + +} // namespace lldb_private + +#endif // liblldb_Address_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/AddressRange.h b/contrib/llvm-project/lldb/include/lldb/Core/AddressRange.h new file mode 100644 index 000000000000..4a019bfcfc3f --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/AddressRange.h @@ -0,0 +1,253 @@ +//===-- AddressRange.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_AddressRange_h_ +#define liblldb_AddressRange_h_ + +#include "lldb/Core/Address.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-types.h" + +#include <stddef.h> + +namespace lldb_private { +class SectionList; +class Stream; +class Target; + +/// \class AddressRange AddressRange.h "lldb/Core/AddressRange.h" +/// A section + offset based address range class. +class AddressRange { +public: + /// Default constructor. + /// + /// Initialize with a invalid section (NULL), an invalid offset + /// (LLDB_INVALID_ADDRESS), and zero byte size. + AddressRange(); + + /// Construct with a section pointer, offset, and byte_size. + /// + /// Initialize the address with the supplied \a section, \a offset and \a + /// byte_size. + /// + /// \param[in] section + /// A section pointer to a valid lldb::Section, or NULL if the + /// address doesn't have a section or will get resolved later. + /// + /// \param[in] offset + /// The offset in bytes into \a section. + /// + /// \param[in] byte_size + /// The size in bytes of the address range. + AddressRange(const lldb::SectionSP §ion, lldb::addr_t offset, + lldb::addr_t byte_size); + + /// Construct with a virtual address, section list and byte size. + /// + /// Initialize and resolve the address with the supplied virtual address \a + /// file_addr, and byte size \a byte_size. + /// + /// \param[in] file_addr + /// A virtual address. + /// + /// \param[in] byte_size + /// The size in bytes of the address range. + /// + /// \param[in] section_list + /// A list of sections, one of which may contain the \a vaddr. + AddressRange(lldb::addr_t file_addr, lldb::addr_t byte_size, + const SectionList *section_list = nullptr); + + /// Construct with a Address object address and byte size. + /// + /// Initialize by copying the section offset address in \a so_addr, and + /// setting the byte size to \a byte_size. + /// + /// \param[in] so_addr + /// A section offset address object. + /// + /// \param[in] byte_size + /// The size in bytes of the address range. + AddressRange(const Address &so_addr, lldb::addr_t byte_size); + + /// Destructor. + /// + /// The destructor is virtual in case this class is subclassed. + ~AddressRange(); + + /// Clear the object's state. + /// + /// Sets the section to an invalid value (NULL), an invalid offset + /// (LLDB_INVALID_ADDRESS) and a zero byte size. + void Clear(); + + /// Check if a section offset address is contained in this range. + /// + /// \param[in] so_addr + /// A section offset address object reference. + /// + /// \return + /// Returns \b true if \a so_addr is contained in this range, + /// \b false otherwise. + // bool + // Contains (const Address &so_addr) const; + + /// Check if a section offset address is contained in this range. + /// + /// \param[in] so_addr_ptr + /// A section offset address object pointer. + /// + /// \return + /// Returns \b true if \a so_addr is contained in this range, + /// \b false otherwise. + // bool + // Contains (const Address *so_addr_ptr) const; + + /// Check if a section offset \a so_addr when represented as a file address + /// is contained within this object's file address range. + /// + /// \param[in] so_addr + /// A section offset address object reference. + /// + /// \return + /// Returns \b true if both \a this and \a so_addr have + /// resolvable file address values and \a so_addr is contained + /// in the address range, \b false otherwise. + bool ContainsFileAddress(const Address &so_addr) const; + + /// Check if the resolved file address \a file_addr is contained within this + /// object's file address range. + /// + /// \param[in] so_addr + /// A section offset address object reference. + /// + /// \return + /// Returns \b true if both \a this has a resolvable file + /// address value and \a so_addr is contained in the address + /// range, \b false otherwise. + bool ContainsFileAddress(lldb::addr_t file_addr) const; + + /// Check if a section offset \a so_addr when represented as a load address + /// is contained within this object's load address range. + /// + /// \param[in] so_addr + /// A section offset address object reference. + /// + /// \return + /// Returns \b true if both \a this and \a so_addr have + /// resolvable load address values and \a so_addr is contained + /// in the address range, \b false otherwise. + bool ContainsLoadAddress(const Address &so_addr, Target *target) const; + + /// Check if the resolved load address \a load_addr is contained within this + /// object's load address range. + /// + /// \param[in] so_addr + /// A section offset address object reference. + /// + /// \return + /// Returns \b true if both \a this has a resolvable load + /// address value and \a so_addr is contained in the address + /// range, \b false otherwise. + bool ContainsLoadAddress(lldb::addr_t load_addr, Target *target) const; + + //------------------------------------------------------------------ + /// Extends this range with \b rhs_range if it overlaps this range on the + /// right side. The range overlaps on the right side if the base address + /// of \b rhs_range lies within this range or if it's contiguous on its + /// right side. + /// + /// @param[in] rhs_range + /// The range to extend at the right side. + /// + /// @return + /// Returns \b true if this range was extended, \b false otherwise. + //------------------------------------------------------------------ + bool Extend(const AddressRange &rhs_range); + + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the supplied stream + /// \a s. There are many ways to display a section offset based address + /// range, and \a style lets the user choose how the base address gets + /// displayed. + /// + /// \param[in] s + /// The stream to which to dump the object description. + /// + /// \param[in] style + /// The display style for the address. + /// + /// \return + /// Returns \b true if the address was able to be displayed. + /// File and load addresses may be unresolved and it may not be + /// possible to display a valid value, \b false will be returned + /// in such cases. + /// + /// \see Address::DumpStyle + bool + Dump(Stream *s, Target *target, Address::DumpStyle style, + Address::DumpStyle fallback_style = Address::DumpStyleInvalid) const; + + /// Dump a debug description of this object to a Stream. + /// + /// Dump a debug description of the contents of this object to the supplied + /// stream \a s. + /// + /// The debug description contains verbose internal state such and pointer + /// values, reference counts, etc. + /// + /// \param[in] s + /// The stream to which to dump the object description. + void DumpDebug(Stream *s) const; + + /// Get accessor for the base address of the range. + /// + /// \return + /// A reference to the base address object. + Address &GetBaseAddress() { return m_base_addr; } + + /// Get const accessor for the base address of the range. + /// + /// \return + /// A const reference to the base address object. + const Address &GetBaseAddress() const { return m_base_addr; } + + /// Get accessor for the byte size of this range. + /// + /// \return + /// The size in bytes of this address range. + lldb::addr_t GetByteSize() const { return m_byte_size; } + + /// Get the memory cost of this object. + /// + /// \return + /// The number of bytes that this object occupies in memory. + size_t MemorySize() const { + // Noting special for the memory size of a single AddressRange object, it + // is just the size of itself. + return sizeof(AddressRange); + } + + /// Set accessor for the byte size of this range. + /// + /// \param[in] byte_size + /// The new size in bytes of this address range. + void SetByteSize(lldb::addr_t byte_size) { m_byte_size = byte_size; } + +protected: + // Member variables + Address m_base_addr; ///< The section offset base address of this range. + lldb::addr_t m_byte_size; ///< The size in bytes of this address range. +}; + +// bool operator== (const AddressRange& lhs, const AddressRange& rhs); + +} // namespace lldb_private + +#endif // liblldb_AddressRange_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/AddressResolver.h b/contrib/llvm-project/lldb/include/lldb/Core/AddressResolver.h new file mode 100644 index 000000000000..cd95c7c31cd6 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/AddressResolver.h @@ -0,0 +1,63 @@ +//===-- AddressResolver.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_AddressResolver_h_ +#define liblldb_AddressResolver_h_ + +#include "lldb/Core/AddressRange.h" +#include "lldb/Core/SearchFilter.h" +#include "lldb/lldb-defines.h" + +#include <stddef.h> +#include <vector> + +namespace lldb_private { +class ModuleList; +class Stream; + +/// \class AddressResolver AddressResolver.h "lldb/Core/AddressResolver.h" +/// This class works with SearchFilter to resolve function names and source +/// file locations to their concrete addresses. + +/// General Outline: +/// The AddressResolver is a Searcher. In that protocol, the SearchFilter +/// asks the question "At what depth of the symbol context descent do you want +/// your callback to get called?" of the filter. The resolver answers this +/// question (in the GetDepth method) and provides the resolution callback. + +class AddressResolver : public Searcher { +public: + enum MatchType { Exact, Regexp, Glob }; + + AddressResolver(); + + ~AddressResolver() override; + + virtual void ResolveAddress(SearchFilter &filter); + + virtual void ResolveAddressInModules(SearchFilter &filter, + ModuleList &modules); + + void GetDescription(Stream *s) override = 0; + + std::vector<AddressRange> &GetAddressRanges(); + + size_t GetNumberOfAddresses(); + + AddressRange &GetAddressRangeAtIndex(size_t idx); + +protected: + std::vector<AddressRange> m_address_ranges; + +private: + DISALLOW_COPY_AND_ASSIGN(AddressResolver); +}; + +} // namespace lldb_private + +#endif // liblldb_AddressResolver_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/AddressResolverFileLine.h b/contrib/llvm-project/lldb/include/lldb/Core/AddressResolverFileLine.h new file mode 100644 index 000000000000..efbe3de1f294 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/AddressResolverFileLine.h @@ -0,0 +1,56 @@ +//===-- AddressResolverFileLine.h -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_AddressResolverFileLine_h_ +#define liblldb_AddressResolverFileLine_h_ + +#include "lldb/Core/AddressResolver.h" +#include "lldb/Core/SearchFilter.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/lldb-defines.h" + +#include <stdint.h> + +namespace lldb_private { +class Address; +class Stream; +class SymbolContext; + +/// \class AddressResolverFileLine AddressResolverFileLine.h +/// "lldb/Core/AddressResolverFileLine.h" This class finds address for source +/// file and line. Optionally, it will look for inlined instances of the file +/// and line specification. + +class AddressResolverFileLine : public AddressResolver { +public: + AddressResolverFileLine(const FileSpec &resolver, uint32_t line_no, + bool check_inlines); + + ~AddressResolverFileLine() override; + + Searcher::CallbackReturn SearchCallback(SearchFilter &filter, + SymbolContext &context, + Address *addr) override; + + lldb::SearchDepth GetDepth() override; + + void GetDescription(Stream *s) override; + +protected: + FileSpec m_file_spec; // This is the file spec we are looking for. + uint32_t m_line_number; // This is the line number that we are looking for. + bool m_inlines; // This determines whether the resolver looks for inlined + // functions or not. + +private: + DISALLOW_COPY_AND_ASSIGN(AddressResolverFileLine); +}; + +} // namespace lldb_private + +#endif // liblldb_AddressResolverFileLine_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/AddressResolverName.h b/contrib/llvm-project/lldb/include/lldb/Core/AddressResolverName.h new file mode 100644 index 000000000000..8a039f9e1d92 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/AddressResolverName.h @@ -0,0 +1,62 @@ +//===-- AddressResolverName.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_AddressResolverName_h_ +#define liblldb_AddressResolverName_h_ + +#include "lldb/Core/AddressResolver.h" +#include "lldb/Core/SearchFilter.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/RegularExpression.h" +#include "lldb/lldb-defines.h" + +namespace lldb_private { +class Address; +class Stream; +class SymbolContext; + +/// \class AddressResolverName AddressResolverName.h +/// "lldb/Core/AddressResolverName.h" This class finds addresses for a given +/// function name, either by exact match or by regular expression. + +class AddressResolverName : public AddressResolver { +public: + AddressResolverName(const char *func_name, + AddressResolver::MatchType type = Exact); + + // Creates a function breakpoint by regular expression. Takes over control + // of the lifespan of func_regex. + AddressResolverName(RegularExpression func_regex); + + AddressResolverName(const char *class_name, const char *method, + AddressResolver::MatchType type); + + ~AddressResolverName() override; + + Searcher::CallbackReturn SearchCallback(SearchFilter &filter, + SymbolContext &context, + Address *addr) override; + + lldb::SearchDepth GetDepth() override; + + void GetDescription(Stream *s) override; + +protected: + ConstString m_func_name; + ConstString m_class_name; // FIXME: Not used yet. The idea would be to stop + // on methods of this class. + RegularExpression m_regex; + AddressResolver::MatchType m_match_type; + +private: + DISALLOW_COPY_AND_ASSIGN(AddressResolverName); +}; + +} // namespace lldb_private + +#endif // liblldb_AddressResolverName_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Architecture.h b/contrib/llvm-project/lldb/include/lldb/Core/Architecture.h new file mode 100644 index 000000000000..d8dbbb4f540f --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/Architecture.h @@ -0,0 +1,111 @@ +//===-- Architecture.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_CORE_ARCHITECTURE_H +#define LLDB_CORE_ARCHITECTURE_H + +#include "lldb/Core/PluginInterface.h" + +namespace lldb_private { + +class Architecture : public PluginInterface { +public: + Architecture() = default; + ~Architecture() override = default; + + /// This is currently intended to handle cases where a + /// program stops at an instruction that won't get executed and it + /// allows the stop reason, like "breakpoint hit", to be replaced + /// with a different stop reason like "no stop reason". + /// + /// This is specifically used for ARM in Thumb code when we stop in + /// an IT instruction (if/then/else) where the instruction won't get + /// executed and therefore it wouldn't be correct to show the program + /// stopped at the current PC. The code is generic and applies to all + /// ARM CPUs. + virtual void OverrideStopInfo(Thread &thread) const = 0; + + /// This method is used to get the number of bytes that should be + /// skipped, from function start address, to reach the first + /// instruction after the prologue. If overrode, it must return + /// non-zero only if the current address matches one of the known + /// function entry points. + /// + /// This method is called only if the standard platform-independent + /// code fails to get the number of bytes to skip, giving the plugin + /// a chance to try to find the missing info. + /// + /// This is specifically used for PPC64, where functions may have + /// more than one entry point, global and local, so both should + /// be compared with current address, in order to find out the + /// number of bytes that should be skipped, in case we are stopped + /// at either function entry point. + virtual size_t GetBytesToSkip(Symbol &func, const Address &curr_addr) const { + return 0; + } + + /// Adjust function breakpoint address, if needed. In some cases, + /// the function start address is not the right place to set the + /// breakpoint, specially in functions with multiple entry points. + /// + /// This is specifically used for PPC64, for functions that have + /// both a global and a local entry point. In this case, the + /// breakpoint is adjusted to the first function address reached + /// by both entry points. + virtual void AdjustBreakpointAddress(const Symbol &func, + Address &addr) const {} + + + /// Get \a load_addr as a callable code load address for this target + /// + /// Take \a load_addr and potentially add any address bits that are + /// needed to make the address callable. For ARM this can set bit + /// zero (if it already isn't) if \a load_addr is a thumb function. + /// If \a addr_class is set to AddressClass::eInvalid, then the address + /// adjustment will always happen. If it is set to an address class + /// that doesn't have code in it, LLDB_INVALID_ADDRESS will be + /// returned. + virtual lldb::addr_t GetCallableLoadAddress( + lldb::addr_t addr, AddressClass addr_class = AddressClass::eInvalid) const { + return addr; + } + + /// Get \a load_addr as an opcode for this target. + /// + /// Take \a load_addr and potentially strip any address bits that are + /// needed to make the address point to an opcode. For ARM this can + /// clear bit zero (if it already isn't) if \a load_addr is a + /// thumb function and load_addr is in code. + /// If \a addr_class is set to AddressClass::eInvalid, then the address + /// adjustment will always happen. If it is set to an address class + /// that doesn't have code in it, LLDB_INVALID_ADDRESS will be + /// returned. + + virtual lldb::addr_t GetOpcodeLoadAddress( + lldb::addr_t addr, AddressClass addr_class = AddressClass::eInvalid) const { + return addr; + } + + // Get load_addr as breakable load address for this target. Take a addr and + // check if for any reason there is a better address than this to put a + // breakpoint on. If there is then return that address. For MIPS, if + // instruction at addr is a delay slot instruction then this method will find + // the address of its previous instruction and return that address. + virtual lldb::addr_t GetBreakableLoadAddress(lldb::addr_t addr, + Target &target) const { + return addr; + } + +private: + Architecture(const Architecture &) = delete; + void operator=(const Architecture &) = delete; +}; + +} // namespace lldb_private + +#endif // LLDB_CORE_ARCHITECTURE_H diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ClangForward.h b/contrib/llvm-project/lldb/include/lldb/Core/ClangForward.h new file mode 100644 index 000000000000..6b24b47c8a96 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ClangForward.h @@ -0,0 +1,134 @@ +//===-- ClangForward.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangForward_h_ +#define liblldb_ClangForward_h_ + + +#if defined(__cplusplus) + +namespace clang { +namespace Builtin { +class Context; +} + +class Action; +class ASTConsumer; +class ASTContext; +class ASTRecordLayout; +class AddrLabelExpr; +class AnalyzerOptions; +class BinaryOperator; +class ClassTemplateDecl; +class ClassTemplateSpecializationDecl; +class CodeGenOptions; +class CodeGenerator; +class CompilerInstance; +class CompoundStmt; +class CXXBaseSpecifier; +class CXXBoolLiteralExpr; +class CXXFunctionalCastExpr; +class CXXMethodDecl; +class CXXNamedCastExpr; +class CXXRecordDecl; +class CXXThisExpr; +class CharacterLiteral; +class CompoundAssignOperator; +class Decl; +class DeclarationName; +class DeclaratorDecl; +class DeclContext; +class DeclRefExpr; +class DeclStmt; +class DependencyOutputOptions; +class Diagnostic; +class DiagnosticConsumer; +class DiagnosticsEngine; +class DiagnosticOptions; +class EnumDecl; +class EnumConstantDecl; +class Expr; +class ExternalASTSource; +class ExtVectorElementExpr; +class FieldDecl; +class FileManager; +class FileSystemOptions; +class FloatingLiteral; +class FrontendOptions; +class FunctionDecl; +class FunctionTemplateDecl; +class FunctionTemplateSpecializationInfo; +class GotoStmt; +class HeaderSearchOptions; +class IdentifierInfo; +class IdentifierTable; +class IntegerLiteral; +class LabelStmt; +class LangOptions; +class MacroDirective; +class MemberExpr; +class Module; +class NamedDecl; +class NamespaceDecl; +class NonTypeTemplateParmDecl; +class ObjCEncodeExpr; +class ObjCImplicitSetterGetterRefExpr; +class ObjCInterfaceDecl; +class ObjCIvarDecl; +class ObjCIvarRefExpr; +class ObjCMessageExpr; +class ObjCMethodDecl; +class ObjCPropertyRefExpr; +class ObjCProtocolDecl; +class ObjCProtocolExpr; +class ObjCSelectorExpr; +class ObjCSuperExpr; +class ParenExpr; +class ParmVarDecl; +class PredefinedExpr; +class PreprocessorOptions; +class PreprocessorOutputOptions; +class QualType; +class QualifiedNameType; +class RecordDecl; +class SelectorTable; +class SizeOfAlignOfExpr; +class SourceLocation; +class SourceManager; +class Stmt; +class StmtIteratorBase; +class StringLiteral; +class TagDecl; +class TargetInfo; +class TargetOptions; +class TemplateArgument; +class TemplateDecl; +class TemplateParameterList; +class TemplateTemplateParmDecl; +class TemplateTypeParmDecl; +class TextDiagnosticBuffer; +class TranslationUnitDecl; +class Type; +class TypeDecl; +class TypedefDecl; +class TypesCompatibleExpr; +class UnaryOperator; +class ValueDecl; +class VarDecl; +struct PrintingPolicy; +} + +namespace llvm { +class APInt; +class APSInt; +class LLVMContext; +class ExecutionEngine; +} + +#endif // #if defined(__cplusplus) +#endif // liblldb_ClangForward_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Communication.h b/contrib/llvm-project/lldb/include/lldb/Core/Communication.h new file mode 100644 index 000000000000..901b8fdb8c8b --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/Communication.h @@ -0,0 +1,367 @@ +//===-- Communication.h -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Communication_h_ +#define liblldb_Communication_h_ + +#include "lldb/Host/HostThread.h" +#include "lldb/Utility/Broadcaster.h" +#include "lldb/Utility/Timeout.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-types.h" + +#include <atomic> +#include <mutex> +#include <ratio> +#include <string> + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class Connection; +class ConstString; +class Status; + +/// \class Communication Communication.h "lldb/Core/Communication.h" An +/// abstract communications class. +/// +/// Communication is an class that handles data communication between two data +/// sources. It uses a Connection class to do the real communication. This +/// approach has a couple of advantages: it allows a single instance of this +/// class to be used even though its connection can change. Connections could +/// negotiate for different connections based on abilities like starting with +/// Bluetooth and negotiating up to WiFi if available. It also allows this +/// class to be subclassed by any interfaces that don't want to give bytes but +/// want to validate and give out packets. This can be done by overriding: +/// +/// AppendBytesToCache (const uint8_t *src, size_t src_len, bool broadcast); +/// +/// Communication inherits from Broadcaster which means it can be used in +/// conjunction with Listener to wait for multiple broadcaster objects and +/// multiple events from each of those objects. Communication defines a set of +/// pre-defined event bits (see enumerations definitions that start with +/// "eBroadcastBit" below). +/// +/// There are two modes in which communications can occur: +/// \li single-threaded +/// \li multi-threaded +/// +/// In single-threaded mode, all reads and writes happen synchronously on the +/// calling thread. +/// +/// In multi-threaded mode, a read thread is spawned that continually reads +/// data and caches any received bytes. To start the read thread clients call: +/// +/// bool Communication::StartReadThread (Status *); +/// +/// If true is returned a read thread has been spawned that will continually +/// execute a call to the pure virtual DoRead function: +/// +/// size_t Communication::ReadFromConnection (void *, size_t, uint32_t); +/// +/// When bytes are received the data gets cached in \a m_bytes and this class +/// will broadcast a \b eBroadcastBitReadThreadGotBytes event. Clients that +/// want packet based communication should override AppendBytesToCache. The +/// subclasses can choose to call the built in AppendBytesToCache with the \a +/// broadcast parameter set to false. This will cause the \b +/// eBroadcastBitReadThreadGotBytes event not get broadcast, and then the +/// subclass can post a \b eBroadcastBitPacketAvailable event when a full +/// packet of data has been received. +/// +/// If the connection is disconnected a \b eBroadcastBitDisconnected event +/// gets broadcast. If the read thread exits a \b +/// eBroadcastBitReadThreadDidExit event will be broadcast. Clients can also +/// post a \b eBroadcastBitReadThreadShouldExit event to this object which +/// will cause the read thread to exit. +class Communication : public Broadcaster { +public: + FLAGS_ANONYMOUS_ENUM(){ + eBroadcastBitDisconnected = + (1u << 0), ///< Sent when the communications connection is lost. + eBroadcastBitReadThreadGotBytes = + (1u << 1), ///< Sent by the read thread when bytes become available. + eBroadcastBitReadThreadDidExit = + (1u + << 2), ///< Sent by the read thread when it exits to inform clients. + eBroadcastBitReadThreadShouldExit = + (1u << 3), ///< Sent by clients that need to cancel the read thread. + eBroadcastBitPacketAvailable = + (1u << 4), ///< Sent when data received makes a complete packet. + eBroadcastBitNoMorePendingInput = (1u << 5), ///< Sent by the read thread + ///to indicate all pending + ///input has been processed. + kLoUserBroadcastBit = + (1u << 16), ///< Subclasses can used bits 31:16 for any needed events. + kHiUserBroadcastBit = (1u << 31), + eAllEventBits = 0xffffffff}; + + typedef void (*ReadThreadBytesReceived)(void *baton, const void *src, + size_t src_len); + + /// Construct the Communication object with the specified name for the + /// Broadcaster that this object inherits from. + /// + /// \param[in] broadcaster_name + /// The name of the broadcaster object. This name should be as + /// complete as possible to uniquely identify this object. The + /// broadcaster name can be updated after the connect function + /// is called. + Communication(const char *broadcaster_name); + + /// Destructor. + /// + /// The destructor is virtual since this class gets subclassed. + ~Communication() override; + + void Clear(); + + /// Connect using the current connection by passing \a url to its connect + /// function. string. + /// + /// \param[in] url + /// A string that contains all information needed by the + /// subclass to connect to another client. + /// + /// \return + /// \b True if the connect succeeded, \b false otherwise. The + /// internal error object should be filled in with an + /// appropriate value based on the result of this function. + /// + /// \see Status& Communication::GetError (); + /// \see bool Connection::Connect (const char *url); + lldb::ConnectionStatus Connect(const char *url, Status *error_ptr); + + /// Disconnect the communications connection if one is currently connected. + /// + /// \return + /// \b True if the disconnect succeeded, \b false otherwise. The + /// internal error object should be filled in with an + /// appropriate value based on the result of this function. + /// + /// \see Status& Communication::GetError (); + /// \see bool Connection::Disconnect (); + lldb::ConnectionStatus Disconnect(Status *error_ptr = nullptr); + + /// Check if the connection is valid. + /// + /// \return + /// \b True if this object is currently connected, \b false + /// otherwise. + bool IsConnected() const; + + bool HasConnection() const; + + lldb_private::Connection *GetConnection() { return m_connection_sp.get(); } + + /// Read bytes from the current connection. + /// + /// If no read thread is running, this function call the connection's + /// Connection::Read(...) function to get any available. + /// + /// If a read thread has been started, this function will check for any + /// cached bytes that have already been read and return any currently + /// available bytes. If no bytes are cached, it will wait for the bytes to + /// become available by listening for the \a eBroadcastBitReadThreadGotBytes + /// event. If this function consumes all of the bytes in the cache, it will + /// reset the \a eBroadcastBitReadThreadGotBytes event bit. + /// + /// \param[in] dst + /// A destination buffer that must be at least \a dst_len bytes + /// long. + /// + /// \param[in] dst_len + /// The number of bytes to attempt to read, and also the max + /// number of bytes that can be placed into \a dst. + /// + /// \param[in] timeout + /// A timeout value or llvm::None for no timeout. + /// + /// \return + /// The number of bytes actually read. + /// + /// \see size_t Connection::Read (void *, size_t); + size_t Read(void *dst, size_t dst_len, const Timeout<std::micro> &timeout, + lldb::ConnectionStatus &status, Status *error_ptr); + + /// The actual write function that attempts to write to the communications + /// protocol. + /// + /// Subclasses must override this function. + /// + /// \param[in] src + /// A source buffer that must be at least \a src_len bytes + /// long. + /// + /// \param[in] src_len + /// The number of bytes to attempt to write, and also the + /// number of bytes are currently available in \a src. + /// + /// \return + /// The number of bytes actually Written. + size_t Write(const void *src, size_t src_len, lldb::ConnectionStatus &status, + Status *error_ptr); + + /// Sets the connection that it to be used by this class. + /// + /// By making a communication class that uses different connections it + /// allows a single communication interface to negotiate and change its + /// connection without any interruption to the client. It also allows the + /// Communication class to be subclassed for packet based communication. + /// + /// \param[in] connection + /// A connection that this class will own and destroy. + /// + /// \see + /// class Connection + void SetConnection(Connection *connection); + + /// Starts a read thread whose sole purpose it to read bytes from the + /// current connection. This function will call connection's read function: + /// + /// size_t Connection::Read (void *, size_t); + /// + /// When bytes are read and cached, this function will call: + /// + /// Communication::AppendBytesToCache (const uint8_t * bytes, size_t len, + /// bool + /// broadcast); + /// + /// Subclasses should override this function if they wish to override the + /// default action of caching the bytes and broadcasting a \b + /// eBroadcastBitReadThreadGotBytes event. + /// + /// \return + /// \b True if the read thread was successfully started, \b + /// false otherwise. + /// + /// \see size_t Connection::Read (void *, size_t); + /// \see void Communication::AppendBytesToCache (const uint8_t * bytes, + /// size_t len, bool broadcast); + virtual bool StartReadThread(Status *error_ptr = nullptr); + + /// Stops the read thread by cancelling it. + /// + /// \return + /// \b True if the read thread was successfully canceled, \b + /// false otherwise. + virtual bool StopReadThread(Status *error_ptr = nullptr); + + virtual bool JoinReadThread(Status *error_ptr = nullptr); + /// Checks if there is a currently running read thread. + /// + /// \return + /// \b True if the read thread is running, \b false otherwise. + bool ReadThreadIsRunning(); + + /// The static read thread function. This function will call the "DoRead" + /// function continuously and wait for data to become available. When data + /// is received it will append the available data to the internal cache and + /// broadcast a \b eBroadcastBitReadThreadGotBytes event. + /// + /// \param[in] comm_ptr + /// A pointer to an instance of this class. + /// + /// \return + /// \b NULL. + /// + /// \see void Communication::ReadThreadGotBytes (const uint8_t *, size_t); + static lldb::thread_result_t ReadThread(lldb::thread_arg_t comm_ptr); + + void SetReadThreadBytesReceivedCallback(ReadThreadBytesReceived callback, + void *callback_baton); + + /// Wait for the read thread to process all outstanding data. + /// + /// After this function returns, the read thread has processed all data that + /// has been waiting in the Connection queue. + /// + void SynchronizeWithReadThread(); + + static const char *ConnectionStatusAsCString(lldb::ConnectionStatus status); + + bool GetCloseOnEOF() const { return m_close_on_eof; } + + void SetCloseOnEOF(bool b) { m_close_on_eof = b; } + + static ConstString &GetStaticBroadcasterClass(); + + ConstString &GetBroadcasterClass() const override { + return GetStaticBroadcasterClass(); + } + +protected: + lldb::ConnectionSP m_connection_sp; ///< The connection that is current in use + ///by this communications class. + HostThread m_read_thread; ///< The read thread handle in case we need to + ///cancel the thread. + std::atomic<bool> m_read_thread_enabled; + std::atomic<bool> m_read_thread_did_exit; + std::string + m_bytes; ///< A buffer to cache bytes read in the ReadThread function. + std::recursive_mutex m_bytes_mutex; ///< A mutex to protect multi-threaded + ///access to the cached bytes. + std::mutex + m_write_mutex; ///< Don't let multiple threads write at the same time... + std::mutex m_synchronize_mutex; + ReadThreadBytesReceived m_callback; + void *m_callback_baton; + bool m_close_on_eof; + + size_t ReadFromConnection(void *dst, size_t dst_len, + const Timeout<std::micro> &timeout, + lldb::ConnectionStatus &status, Status *error_ptr); + + /// Append new bytes that get read from the read thread into the internal + /// object byte cache. This will cause a \b eBroadcastBitReadThreadGotBytes + /// event to be broadcast if \a broadcast is true. + /// + /// Subclasses can override this function in order to inspect the received + /// data and check if a packet is available. + /// + /// Subclasses can also still call this function from the overridden method + /// to allow the caching to correctly happen and suppress the broadcasting + /// of the \a eBroadcastBitReadThreadGotBytes event by setting \a broadcast + /// to false. + /// + /// \param[in] src + /// A source buffer that must be at least \a src_len bytes + /// long. + /// + /// \param[in] src_len + /// The number of bytes to append to the cache. + virtual void AppendBytesToCache(const uint8_t *src, size_t src_len, + bool broadcast, + lldb::ConnectionStatus status); + + /// Get any available bytes from our data cache. If this call empties the + /// data cache, the \b eBroadcastBitReadThreadGotBytes event will be reset + /// to signify no more bytes are available. + /// + /// \param[in] dst + /// A destination buffer that must be at least \a dst_len bytes + /// long. + /// + /// \param[in] dst_len + /// The number of bytes to attempt to read from the cache, + /// and also the max number of bytes that can be placed into + /// \a dst. + /// + /// \return + /// The number of bytes extracted from the data cache. + size_t GetCachedBytes(void *dst, size_t dst_len); + +private: + DISALLOW_COPY_AND_ASSIGN(Communication); +}; + +} // namespace lldb_private + +#endif // liblldb_Communication_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Debugger.h b/contrib/llvm-project/lldb/include/lldb/Core/Debugger.h new file mode 100644 index 000000000000..b2f696c22834 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/Debugger.h @@ -0,0 +1,431 @@ +//===-- Debugger.h ----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Debugger_h_ +#define liblldb_Debugger_h_ + +#include <stdint.h> + +#include <memory> +#include <vector> + +#include "lldb/Core/FormatEntity.h" +#include "lldb/Core/IOHandler.h" +#include "lldb/Core/SourceManager.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Core/UserSettingsController.h" +#include "lldb/Host/HostThread.h" +#include "lldb/Host/Terminal.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Platform.h" +#include "lldb/Target/TargetList.h" +#include "lldb/Utility/Broadcaster.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/UserID.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private-enumerations.h" +#include "lldb/lldb-private-types.h" +#include "lldb/lldb-types.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/StringMap.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/DynamicLibrary.h" +#include "llvm/Support/Threading.h" + +#include <assert.h> +#include <stddef.h> +#include <stdio.h> + +namespace llvm { +class raw_ostream; +} + +namespace lldb_private { +class Address; +class CommandInterpreter; +class Process; +class Stream; +class SymbolContext; +class Target; + +namespace repro { +class DataRecorder; +} + +/// \class Debugger Debugger.h "lldb/Core/Debugger.h" +/// A class to manage flag bits. +/// +/// Provides a global root objects for the debugger core. + +class Debugger : public std::enable_shared_from_this<Debugger>, + public UserID, + public Properties { + friend class SourceManager; // For GetSourceFileCache. + +public: + ~Debugger() override; + + static lldb::DebuggerSP + CreateInstance(lldb::LogOutputCallback log_callback = nullptr, + void *baton = nullptr); + + static lldb::TargetSP FindTargetWithProcessID(lldb::pid_t pid); + + static lldb::TargetSP FindTargetWithProcess(Process *process); + + static void Initialize(LoadPluginCallbackType load_plugin_callback); + + static void Terminate(); + + static void SettingsInitialize(); + + static void SettingsTerminate(); + + static void Destroy(lldb::DebuggerSP &debugger_sp); + + static lldb::DebuggerSP FindDebuggerWithID(lldb::user_id_t id); + + static lldb::DebuggerSP + FindDebuggerWithInstanceName(ConstString instance_name); + + static size_t GetNumDebuggers(); + + static lldb::DebuggerSP GetDebuggerAtIndex(size_t index); + + static bool FormatDisassemblerAddress(const FormatEntity::Entry *format, + const SymbolContext *sc, + const SymbolContext *prev_sc, + const ExecutionContext *exe_ctx, + const Address *addr, Stream &s); + + void Clear(); + + bool GetAsyncExecution(); + + void SetAsyncExecution(bool async); + + lldb::FileSP GetInputFileSP() { return m_input_file_sp; } + + lldb::StreamFileSP GetOutputStreamSP() { return m_output_stream_sp; } + + lldb::StreamFileSP GetErrorStreamSP() { return m_error_stream_sp; } + + File &GetInputFile() { return *m_input_file_sp; } + + File &GetOutputFile() { return m_output_stream_sp->GetFile(); } + + File &GetErrorFile() { return m_error_stream_sp->GetFile(); } + + StreamFile &GetOutputStream() { return *m_output_stream_sp; } + + StreamFile &GetErrorStream() { return *m_error_stream_sp; } + + repro::DataRecorder *GetInputRecorder(); + + void SetInputFile(lldb::FileSP file, repro::DataRecorder *recorder = nullptr); + + void SetOutputFile(lldb::FileSP file); + + void SetErrorFile(lldb::FileSP file); + + void SaveInputTerminalState(); + + void RestoreInputTerminalState(); + + lldb::StreamSP GetAsyncOutputStream(); + + lldb::StreamSP GetAsyncErrorStream(); + + CommandInterpreter &GetCommandInterpreter() { + assert(m_command_interpreter_up.get()); + return *m_command_interpreter_up; + } + + ScriptInterpreter *GetScriptInterpreter(bool can_create = true); + + lldb::ListenerSP GetListener() { return m_listener_sp; } + + // This returns the Debugger's scratch source manager. It won't be able to + // look up files in debug information, but it can look up files by absolute + // path and display them to you. To get the target's source manager, call + // GetSourceManager on the target instead. + SourceManager &GetSourceManager(); + + lldb::TargetSP GetSelectedTarget() { + return m_target_list.GetSelectedTarget(); + } + + ExecutionContext GetSelectedExecutionContext(); + /// Get accessor for the target list. + /// + /// The target list is part of the global debugger object. This the single + /// debugger shared instance to control where targets get created and to + /// allow for tracking and searching for targets based on certain criteria. + /// + /// \return + /// A global shared target list. + TargetList &GetTargetList() { return m_target_list; } + + PlatformList &GetPlatformList() { return m_platform_list; } + + void DispatchInputInterrupt(); + + void DispatchInputEndOfFile(); + + // If any of the streams are not set, set them to the in/out/err stream of + // the top most input reader to ensure they at least have something + void AdoptTopIOHandlerFilesIfInvalid(lldb::FileSP &in, + lldb::StreamFileSP &out, + lldb::StreamFileSP &err); + + void PushIOHandler(const lldb::IOHandlerSP &reader_sp, + bool cancel_top_handler = true); + + bool PopIOHandler(const lldb::IOHandlerSP &reader_sp); + + // Synchronously run an input reader until it is done + void RunIOHandler(const lldb::IOHandlerSP &reader_sp); + + bool IsTopIOHandler(const lldb::IOHandlerSP &reader_sp); + + bool CheckTopIOHandlerTypes(IOHandler::Type top_type, + IOHandler::Type second_top_type); + + void PrintAsync(const char *s, size_t len, bool is_stdout); + + ConstString GetTopIOHandlerControlSequence(char ch); + + const char *GetIOHandlerCommandPrefix(); + + const char *GetIOHandlerHelpPrologue(); + + void ClearIOHandlers(); + + bool GetCloseInputOnEOF() const; + + void SetCloseInputOnEOF(bool b); + + bool EnableLog(llvm::StringRef channel, + llvm::ArrayRef<const char *> categories, + llvm::StringRef log_file, uint32_t log_options, + llvm::raw_ostream &error_stream); + + void SetLoggingCallback(lldb::LogOutputCallback log_callback, void *baton); + + // Properties Functions + enum StopDisassemblyType { + eStopDisassemblyTypeNever = 0, + eStopDisassemblyTypeNoDebugInfo, + eStopDisassemblyTypeNoSource, + eStopDisassemblyTypeAlways + }; + + Status SetPropertyValue(const ExecutionContext *exe_ctx, + VarSetOperationType op, llvm::StringRef property_path, + llvm::StringRef value) override; + + bool GetAutoConfirm() const; + + const FormatEntity::Entry *GetDisassemblyFormat() const; + + const FormatEntity::Entry *GetFrameFormat() const; + + const FormatEntity::Entry *GetFrameFormatUnique() const; + + const FormatEntity::Entry *GetThreadFormat() const; + + const FormatEntity::Entry *GetThreadStopFormat() const; + + lldb::ScriptLanguage GetScriptLanguage() const; + + bool SetScriptLanguage(lldb::ScriptLanguage script_lang); + + uint32_t GetTerminalWidth() const; + + bool SetTerminalWidth(uint32_t term_width); + + llvm::StringRef GetPrompt() const; + + void SetPrompt(llvm::StringRef p); + void SetPrompt(const char *) = delete; + + llvm::StringRef GetReproducerPath() const; + + bool GetUseExternalEditor() const; + + bool SetUseExternalEditor(bool use_external_editor_p); + + bool GetUseColor() const; + + bool SetUseColor(bool use_color); + + bool GetHighlightSource() const; + + lldb::StopShowColumn GetStopShowColumn() const; + + llvm::StringRef GetStopShowColumnAnsiPrefix() const; + + llvm::StringRef GetStopShowColumnAnsiSuffix() const; + + uint32_t GetStopSourceLineCount(bool before) const; + + StopDisassemblyType GetStopDisassemblyDisplay() const; + + uint32_t GetDisassemblyLineCount() const; + + bool GetAutoOneLineSummaries() const; + + bool GetAutoIndent() const; + + bool SetAutoIndent(bool b); + + bool GetPrintDecls() const; + + bool SetPrintDecls(bool b); + + uint32_t GetTabSize() const; + + bool SetTabSize(uint32_t tab_size); + + bool GetEscapeNonPrintables() const; + + bool GetNotifyVoid() const; + + ConstString GetInstanceName() { return m_instance_name; } + + bool LoadPlugin(const FileSpec &spec, Status &error); + + void ExecuteIOHandlers(); + + bool IsForwardingEvents(); + + void EnableForwardEvents(const lldb::ListenerSP &listener_sp); + + void CancelForwardEvents(const lldb::ListenerSP &listener_sp); + + bool IsHandlingEvents() const { return m_event_handler_thread.IsJoinable(); } + + Status RunREPL(lldb::LanguageType language, const char *repl_options); + + // This is for use in the command interpreter, when you either want the + // selected target, or if no target is present you want to prime the dummy + // target with entities that will be copied over to new targets. + Target *GetSelectedOrDummyTarget(bool prefer_dummy = false); + Target *GetDummyTarget() { return m_dummy_target_sp.get(); } + + lldb::BroadcasterManagerSP GetBroadcasterManager() { + return m_broadcaster_manager_sp; + } + +protected: + friend class CommandInterpreter; + friend class REPL; + + bool StartEventHandlerThread(); + + void StopEventHandlerThread(); + + static lldb::thread_result_t EventHandlerThread(lldb::thread_arg_t arg); + + bool HasIOHandlerThread(); + + bool StartIOHandlerThread(); + + void StopIOHandlerThread(); + + void JoinIOHandlerThread(); + + static lldb::thread_result_t IOHandlerThread(lldb::thread_arg_t arg); + + void DefaultEventHandler(); + + void HandleBreakpointEvent(const lldb::EventSP &event_sp); + + void HandleProcessEvent(const lldb::EventSP &event_sp); + + void HandleThreadEvent(const lldb::EventSP &event_sp); + + // Ensures two threads don't attempt to flush process output in parallel. + std::mutex m_output_flush_mutex; + void FlushProcessOutput(Process &process, bool flush_stdout, + bool flush_stderr); + + SourceManager::SourceFileCache &GetSourceFileCache() { + return m_source_file_cache; + } + + void InstanceInitialize(); + + // these should never be NULL + lldb::FileSP m_input_file_sp; + lldb::StreamFileSP m_output_stream_sp; + lldb::StreamFileSP m_error_stream_sp; + + /// Used for shadowing the input file when capturing a reproducer. + repro::DataRecorder *m_input_recorder; + + lldb::BroadcasterManagerSP m_broadcaster_manager_sp; // The debugger acts as a + // broadcaster manager of + // last resort. + // It needs to get constructed before the target_list or any other member + // that might want to broadcast through the debugger. + + TerminalState m_terminal_state; + TargetList m_target_list; + + PlatformList m_platform_list; + lldb::ListenerSP m_listener_sp; + std::unique_ptr<SourceManager> m_source_manager_up; // This is a scratch + // source manager that we + // return if we have no + // targets. + SourceManager::SourceFileCache m_source_file_cache; // All the source managers + // for targets created in + // this debugger used this + // shared + // source file cache. + std::unique_ptr<CommandInterpreter> m_command_interpreter_up; + + lldb::ScriptInterpreterSP m_script_interpreter_sp; + std::recursive_mutex m_script_interpreter_mutex; + + IOHandlerStack m_input_reader_stack; + llvm::StringMap<std::weak_ptr<llvm::raw_ostream>> m_log_streams; + std::shared_ptr<llvm::raw_ostream> m_log_callback_stream_sp; + ConstString m_instance_name; + static LoadPluginCallbackType g_load_plugin_callback; + typedef std::vector<llvm::sys::DynamicLibrary> LoadedPluginsList; + LoadedPluginsList m_loaded_plugins; + HostThread m_event_handler_thread; + HostThread m_io_handler_thread; + Broadcaster m_sync_broadcaster; + lldb::ListenerSP m_forward_listener_sp; + llvm::once_flag m_clear_once; + lldb::TargetSP m_dummy_target_sp; + + // Events for m_sync_broadcaster + enum { + eBroadcastBitEventThreadIsListening = (1 << 0), + }; + +private: + // Use Debugger::CreateInstance() to get a shared pointer to a new debugger + // object + Debugger(lldb::LogOutputCallback m_log_callback, void *baton); + + DISALLOW_COPY_AND_ASSIGN(Debugger); +}; + +} // namespace lldb_private + +#endif // liblldb_Debugger_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Disassembler.h b/contrib/llvm-project/lldb/include/lldb/Core/Disassembler.h new file mode 100644 index 000000000000..ba9ca87832f6 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/Disassembler.h @@ -0,0 +1,551 @@ +//===-- Disassembler.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Disassembler_h_ +#define liblldb_Disassembler_h_ + +#include "lldb/Core/Address.h" +#include "lldb/Core/EmulateInstruction.h" +#include "lldb/Core/FormatEntity.h" +#include "lldb/Core/Opcode.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Interpreter/OptionValue.h" +#include "lldb/Symbol/LineEntry.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private-enumerations.h" +#include "lldb/lldb-types.h" + +#include "llvm/ADT/StringRef.h" + +#include <functional> +#include <map> +#include <memory> +#include <set> +#include <string> +#include <vector> + +#include <stddef.h> +#include <stdint.h> +#include <stdio.h> + +namespace llvm { +template <typename T> class SmallVectorImpl; +} + +namespace lldb_private { +class AddressRange; +class DataExtractor; +class Debugger; +class Disassembler; +class Module; +class Stream; +class SymbolContext; +class SymbolContextList; +class Target; +struct RegisterInfo; + +class Instruction { +public: + Instruction(const Address &address, + AddressClass addr_class = AddressClass::eInvalid); + + virtual ~Instruction(); + + const Address &GetAddress() const { return m_address; } + + const char *GetMnemonic(const ExecutionContext *exe_ctx) { + CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); + return m_opcode_name.c_str(); + } + + const char *GetOperands(const ExecutionContext *exe_ctx) { + CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); + return m_mnemonics.c_str(); + } + + const char *GetComment(const ExecutionContext *exe_ctx) { + CalculateMnemonicOperandsAndCommentIfNeeded(exe_ctx); + return m_comment.c_str(); + } + + virtual void + CalculateMnemonicOperandsAndComment(const ExecutionContext *exe_ctx) = 0; + + AddressClass GetAddressClass(); + + void SetAddress(const Address &addr) { + // Invalidate the address class to lazily discover it if we need to. + m_address_class = AddressClass::eInvalid; + m_address = addr; + } + + /// Dump the text representation of this Instruction to a Stream + /// + /// Print the (optional) address, (optional) bytes, opcode, + /// operands, and instruction comments to a stream. + /// + /// \param[in] s + /// The Stream to add the text to. + /// + /// \param[in] show_address + /// Whether the address (using disassembly_addr_format_spec formatting) + /// should be printed. + /// + /// \param[in] show_bytes + /// Whether the bytes of the assembly instruction should be printed. + /// + /// \param[in] max_opcode_byte_size + /// The size (in bytes) of the largest instruction in the list that + /// we are printing (for text justification/alignment purposes) + /// Only needed if show_bytes is true. + /// + /// \param[in] exe_ctx + /// The current execution context, if available. May be used in + /// the assembling of the operands+comments for this instruction. + /// Pass NULL if not applicable. + /// + /// \param[in] sym_ctx + /// The SymbolContext for this instruction. + /// Pass NULL if not available/computed. + /// Only needed if show_address is true. + /// + /// \param[in] prev_sym_ctx + /// The SymbolContext for the previous instruction. Depending on + /// the disassembly address format specification, a change in + /// Symbol / Function may mean that a line is printed with the new + /// symbol/function name. + /// Pass NULL if unavailable, or if this is the first instruction of + /// the InstructionList. + /// Only needed if show_address is true. + /// + /// \param[in] disassembly_addr_format + /// The format specification for how addresses are printed. + /// Only needed if show_address is true. + /// + /// \param[in] max_address_text_size + /// The length of the longest address string at the start of the + /// disassembly line that will be printed (the + /// Debugger::FormatDisassemblerAddress() string) + /// so this method can properly align the instruction opcodes. + /// May be 0 to indicate no indentation/alignment of the opcodes. + virtual void Dump(Stream *s, uint32_t max_opcode_byte_size, bool show_address, + bool show_bytes, const ExecutionContext *exe_ctx, + const SymbolContext *sym_ctx, + const SymbolContext *prev_sym_ctx, + const FormatEntity::Entry *disassembly_addr_format, + size_t max_address_text_size); + + virtual bool DoesBranch() = 0; + + virtual bool HasDelaySlot(); + + bool CanSetBreakpoint (); + + virtual size_t Decode(const Disassembler &disassembler, + const DataExtractor &data, + lldb::offset_t data_offset) = 0; + + virtual void SetDescription(llvm::StringRef) { + } // May be overridden in sub-classes that have descriptions. + + lldb::OptionValueSP ReadArray(FILE *in_file, Stream *out_stream, + OptionValue::Type data_type); + + lldb::OptionValueSP ReadDictionary(FILE *in_file, Stream *out_stream); + + bool DumpEmulation(const ArchSpec &arch); + + virtual bool TestEmulation(Stream *stream, const char *test_file_name); + + bool Emulate(const ArchSpec &arch, uint32_t evaluate_options, void *baton, + EmulateInstruction::ReadMemoryCallback read_mem_callback, + EmulateInstruction::WriteMemoryCallback write_mem_calback, + EmulateInstruction::ReadRegisterCallback read_reg_callback, + EmulateInstruction::WriteRegisterCallback write_reg_callback); + + const Opcode &GetOpcode() const { return m_opcode; } + + uint32_t GetData(DataExtractor &data); + + struct Operand { + enum class Type { + Invalid = 0, + Register, + Immediate, + Dereference, + Sum, + Product + } m_type = Type::Invalid; + std::vector<Operand> m_children; + lldb::addr_t m_immediate = 0; + ConstString m_register; + bool m_negative = false; + bool m_clobbered = false; + + bool IsValid() { return m_type != Type::Invalid; } + + static Operand BuildRegister(ConstString &r); + static Operand BuildImmediate(lldb::addr_t imm, bool neg); + static Operand BuildImmediate(int64_t imm); + static Operand BuildDereference(const Operand &ref); + static Operand BuildSum(const Operand &lhs, const Operand &rhs); + static Operand BuildProduct(const Operand &lhs, const Operand &rhs); + }; + + virtual bool ParseOperands(llvm::SmallVectorImpl<Operand> &operands) { + return false; + } + + virtual bool IsCall() { return false; } + +protected: + Address m_address; // The section offset address of this instruction + // We include an address class in the Instruction class to + // allow the instruction specify the + // AddressClass::eCodeAlternateISA (currently used for + // thumb), and also to specify data (AddressClass::eData). + // The usual value will be AddressClass::eCode, but often + // when disassembling memory, you might run into data. + // This can help us to disassemble appropriately. +private: + AddressClass m_address_class; // Use GetAddressClass () accessor function! + +protected: + Opcode m_opcode; // The opcode for this instruction + std::string m_opcode_name; + std::string m_mnemonics; + std::string m_comment; + bool m_calculated_strings; + + void + CalculateMnemonicOperandsAndCommentIfNeeded(const ExecutionContext *exe_ctx) { + if (!m_calculated_strings) { + m_calculated_strings = true; + CalculateMnemonicOperandsAndComment(exe_ctx); + } + } +}; + +namespace OperandMatchers { +std::function<bool(const Instruction::Operand &)> +MatchBinaryOp(std::function<bool(const Instruction::Operand &)> base, + std::function<bool(const Instruction::Operand &)> left, + std::function<bool(const Instruction::Operand &)> right); + +std::function<bool(const Instruction::Operand &)> +MatchUnaryOp(std::function<bool(const Instruction::Operand &)> base, + std::function<bool(const Instruction::Operand &)> child); + +std::function<bool(const Instruction::Operand &)> +MatchRegOp(const RegisterInfo &info); + +std::function<bool(const Instruction::Operand &)> FetchRegOp(ConstString ®); + +std::function<bool(const Instruction::Operand &)> MatchImmOp(int64_t imm); + +std::function<bool(const Instruction::Operand &)> FetchImmOp(int64_t &imm); + +std::function<bool(const Instruction::Operand &)> +MatchOpType(Instruction::Operand::Type type); +} + +class InstructionList { +public: + InstructionList(); + ~InstructionList(); + + size_t GetSize() const; + + uint32_t GetMaxOpcocdeByteSize() const; + + lldb::InstructionSP GetInstructionAtIndex(size_t idx) const; + + //------------------------------------------------------------------ + /// Get the index of the next branch instruction. + /// + /// Given a list of instructions, find the next branch instruction + /// in the list by returning an index. + /// + /// @param[in] start + /// The instruction index of the first instruction to check. + /// + /// @param[in] target + /// A LLDB target object that is used to resolve addresses. + /// + /// @param[in] ignore_calls + /// It true, then fine the first branch instruction that isn't + /// a function call (a branch that calls and returns to the next + /// instruction). If false, find the instruction index of any + /// branch in the list. + /// + /// @return + /// The instruction index of the first branch that is at or past + /// \a start. Returns UINT32_MAX if no matching branches are + /// found. + //------------------------------------------------------------------ + uint32_t GetIndexOfNextBranchInstruction(uint32_t start, + Target &target, + bool ignore_calls) const; + + uint32_t GetIndexOfInstructionAtLoadAddress(lldb::addr_t load_addr, + Target &target); + + uint32_t GetIndexOfInstructionAtAddress(const Address &addr); + + void Clear(); + + void Append(lldb::InstructionSP &inst_sp); + + void Dump(Stream *s, bool show_address, bool show_bytes, + const ExecutionContext *exe_ctx); + +private: + typedef std::vector<lldb::InstructionSP> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + collection m_instructions; +}; + +class PseudoInstruction : public Instruction { +public: + PseudoInstruction(); + + ~PseudoInstruction() override; + + bool DoesBranch() override; + + bool HasDelaySlot() override; + + void CalculateMnemonicOperandsAndComment( + const ExecutionContext *exe_ctx) override { + // TODO: fill this in and put opcode name into Instruction::m_opcode_name, + // mnemonic into Instruction::m_mnemonics, and any comment into + // Instruction::m_comment + } + + size_t Decode(const Disassembler &disassembler, const DataExtractor &data, + lldb::offset_t data_offset) override; + + void SetOpcode(size_t opcode_size, void *opcode_data); + + void SetDescription(llvm::StringRef description) override; + +protected: + std::string m_description; + + DISALLOW_COPY_AND_ASSIGN(PseudoInstruction); +}; + +class Disassembler : public std::enable_shared_from_this<Disassembler>, + public PluginInterface { +public: + enum { + eOptionNone = 0u, + eOptionShowBytes = (1u << 0), + eOptionRawOuput = (1u << 1), + eOptionMarkPCSourceLine = (1u << 2), // Mark the source line that contains + // the current PC (mixed mode only) + eOptionMarkPCAddress = + (1u << 3) // Mark the disassembly line the contains the PC + }; + + enum HexImmediateStyle { + eHexStyleC, + eHexStyleAsm, + }; + + // FindPlugin should be lax about the flavor string (it is too annoying to + // have various internal uses of the disassembler fail because the global + // flavor string gets set wrong. Instead, if you get a flavor string you + // don't understand, use the default. Folks who care to check can use the + // FlavorValidForArchSpec method on the disassembler they got back. + static lldb::DisassemblerSP + FindPlugin(const ArchSpec &arch, const char *flavor, const char *plugin_name); + + // This version will use the value in the Target settings if flavor is NULL; + static lldb::DisassemblerSP + FindPluginForTarget(const lldb::TargetSP target_sp, const ArchSpec &arch, + const char *flavor, const char *plugin_name); + + static lldb::DisassemblerSP + DisassembleRange(const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, + const AddressRange &disasm_range, bool prefer_file_cache); + + static lldb::DisassemblerSP + DisassembleBytes(const ArchSpec &arch, const char *plugin_name, + const char *flavor, const Address &start, const void *bytes, + size_t length, uint32_t max_num_instructions, + bool data_from_file); + + static bool Disassemble(Debugger &debugger, const ArchSpec &arch, + const char *plugin_name, const char *flavor, + const ExecutionContext &exe_ctx, + const AddressRange &range, uint32_t num_instructions, + bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, uint32_t options, + Stream &strm); + + static bool Disassemble(Debugger &debugger, const ArchSpec &arch, + const char *plugin_name, const char *flavor, + const ExecutionContext &exe_ctx, const Address &start, + uint32_t num_instructions, + bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, uint32_t options, + Stream &strm); + + static size_t + Disassemble(Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, + SymbolContextList &sc_list, uint32_t num_instructions, + bool mixed_source_and_assembly, uint32_t num_mixed_context_lines, + uint32_t options, Stream &strm); + + static bool + Disassemble(Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, + ConstString name, Module *module, + uint32_t num_instructions, bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, uint32_t options, Stream &strm); + + static bool + Disassemble(Debugger &debugger, const ArchSpec &arch, const char *plugin_name, + const char *flavor, const ExecutionContext &exe_ctx, + uint32_t num_instructions, bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, uint32_t options, Stream &strm); + + // Constructors and Destructors + Disassembler(const ArchSpec &arch, const char *flavor); + ~Disassembler() override; + + typedef const char *(*SummaryCallback)(const Instruction &inst, + ExecutionContext *exe_context, + void *user_data); + + static bool PrintInstructions(Disassembler *disasm_ptr, Debugger &debugger, + const ArchSpec &arch, + const ExecutionContext &exe_ctx, + uint32_t num_instructions, + bool mixed_source_and_assembly, + uint32_t num_mixed_context_lines, + uint32_t options, Stream &strm); + + size_t ParseInstructions(const ExecutionContext *exe_ctx, + const AddressRange &range, Stream *error_strm_ptr, + bool prefer_file_cache); + + size_t ParseInstructions(const ExecutionContext *exe_ctx, + const Address &range, uint32_t num_instructions, + bool prefer_file_cache); + + virtual size_t DecodeInstructions(const Address &base_addr, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t num_instructions, bool append, + bool data_from_file) = 0; + + InstructionList &GetInstructionList(); + + const InstructionList &GetInstructionList() const; + + const ArchSpec &GetArchitecture() const { return m_arch; } + + const char *GetFlavor() const { return m_flavor.c_str(); } + + virtual bool FlavorValidForArchSpec(const lldb_private::ArchSpec &arch, + const char *flavor) = 0; + +protected: + // SourceLine and SourceLinesToDisplay structures are only used in the mixed + // source and assembly display methods internal to this class. + + struct SourceLine { + FileSpec file; + uint32_t line; + uint32_t column; + + SourceLine() : file(), line(LLDB_INVALID_LINE_NUMBER), column(0) {} + + bool operator==(const SourceLine &rhs) const { + return file == rhs.file && line == rhs.line && rhs.column == column; + } + + bool operator!=(const SourceLine &rhs) const { + return file != rhs.file || line != rhs.line || column != rhs.column; + } + + bool IsValid() const { return line != LLDB_INVALID_LINE_NUMBER; } + }; + + struct SourceLinesToDisplay { + std::vector<SourceLine> lines; + + // index of the "current" source line, if we want to highlight that when + // displaying the source lines. (as opposed to the surrounding source + // lines provided to give context) + size_t current_source_line; + + // Whether to print a blank line at the end of the source lines. + bool print_source_context_end_eol; + + SourceLinesToDisplay() + : lines(), current_source_line(-1), print_source_context_end_eol(true) { + } + }; + + // Get the function's declaration line number, hopefully a line number + // earlier than the opening curly brace at the start of the function body. + static SourceLine GetFunctionDeclLineEntry(const SymbolContext &sc); + + // Add the provided SourceLine to the map of filenames-to-source-lines-seen. + static void AddLineToSourceLineTables( + SourceLine &line, + std::map<FileSpec, std::set<uint32_t>> &source_lines_seen); + + // Given a source line, determine if we should print it when we're doing + // mixed source & assembly output. We're currently using the + // target.process.thread.step-avoid-regexp setting (which is used for + // stepping over inlined STL functions by default) to determine what source + // lines to avoid showing. + // + // Returns true if this source line should be elided (if the source line + // should not be displayed). + static bool + ElideMixedSourceAndDisassemblyLine(const ExecutionContext &exe_ctx, + const SymbolContext &sc, SourceLine &line); + + static bool + ElideMixedSourceAndDisassemblyLine(const ExecutionContext &exe_ctx, + const SymbolContext &sc, LineEntry &line) { + SourceLine sl; + sl.file = line.file; + sl.line = line.line; + sl.column = line.column; + return ElideMixedSourceAndDisassemblyLine(exe_ctx, sc, sl); + }; + + // Classes that inherit from Disassembler can see and modify these + ArchSpec m_arch; + InstructionList m_instruction_list; + lldb::addr_t m_base_addr; + std::string m_flavor; + +private: + // For Disassembler only + DISALLOW_COPY_AND_ASSIGN(Disassembler); +}; + +} // namespace lldb_private + +#endif // liblldb_Disassembler_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/DumpDataExtractor.h b/contrib/llvm-project/lldb/include/lldb/Core/DumpDataExtractor.h new file mode 100644 index 000000000000..2a9d778e0a6a --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/DumpDataExtractor.h @@ -0,0 +1,92 @@ +//===-- DumpDataExtractor.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_CORE_DUMPDATAEXTRACTOR_H +#define LLDB_CORE_DUMPDATAEXTRACTOR_H + +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-types.h" + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class DataExtractor; +class ExecutionContextScope; +class Stream; + +/// Dumps \a item_count objects into the stream \a s. +/// +/// Dumps \a item_count objects using \a item_format, each of which +/// are \a item_byte_size bytes long starting at offset \a offset +/// bytes into the contained data, into the stream \a s. \a +/// num_per_line objects will be dumped on each line before a new +/// line will be output. If \a base_addr is a valid address, then +/// each new line of output will be preceded by the address value +/// plus appropriate offset, and a colon and space. Bitfield values +/// can be dumped by calling this function multiple times with the +/// same start offset, format and size, yet differing \a +/// item_bit_size and \a item_bit_offset values. +/// +/// \param[in] s +/// The stream to dump the output to. This value can not be nullptr. +/// +/// \param[in] offset +/// The offset into the data at which to start dumping. +/// +/// \param[in] item_format +/// The format to use when dumping each item. +/// +/// \param[in] item_byte_size +/// The byte size of each item. +/// +/// \param[in] item_count +/// The number of items to dump. +/// +/// \param[in] num_per_line +/// The number of items to display on each line. +/// +/// \param[in] base_addr +/// The base address that gets added to the offset displayed on +/// each line if the value is valid. Is \a base_addr is +/// LLDB_INVALID_ADDRESS then no address values will be prepended +/// to any lines. +/// +/// \param[in] item_bit_size +/// If the value to display is a bitfield, this value should +/// be the number of bits that the bitfield item has within the +/// item's byte size value. This function will need to be called +/// multiple times with identical \a offset and \a item_byte_size +/// values in order to display multiple bitfield values that +/// exist within the same integer value. If the items being +/// displayed are not bitfields, this value should be zero. +/// +/// \param[in] item_bit_offset +/// If the value to display is a bitfield, this value should +/// be the offset in bits, or shift right amount, that the +/// bitfield item occupies within the item's byte size value. +/// This function will need to be called multiple times with +/// identical \a offset and \a item_byte_size values in order +/// to display multiple bitfield values that exist within the +/// same integer value. If the items being displayed are not +/// bitfields, this value should be zero. +/// +/// \return +/// The offset at which dumping ended. +lldb::offset_t +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); + +void DumpHexBytes(Stream *s, const void *src, size_t src_len, + uint32_t bytes_per_line, lldb::addr_t base_addr); +} + +#endif diff --git a/contrib/llvm-project/lldb/include/lldb/Core/DumpRegisterValue.h b/contrib/llvm-project/lldb/include/lldb/Core/DumpRegisterValue.h new file mode 100644 index 000000000000..443fdb34266a --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/DumpRegisterValue.h @@ -0,0 +1,30 @@ +//===-- DumpRegisterValue.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_CORE_DUMPREGISTERVALUE_H +#define LLDB_CORE_DUMPREGISTERVALUE_H + +#include "lldb/lldb-enumerations.h" +#include <cstdint> + +namespace lldb_private { + +class RegisterValue; +struct RegisterInfo; +class Stream; + +// The default value of 0 for reg_name_right_align_at means no alignment at +// all. +bool DumpRegisterValue(const RegisterValue ®_val, Stream *s, + const RegisterInfo *reg_info, bool prefix_with_name, + bool prefix_with_alt_name, lldb::Format format, + uint32_t reg_name_right_align_at = 0); + +} // namespace lldb_private + +#endif // LLDB_CORE_DUMPREGISTERVALUE_H diff --git a/contrib/llvm-project/lldb/include/lldb/Core/EmulateInstruction.h b/contrib/llvm-project/lldb/include/lldb/Core/EmulateInstruction.h new file mode 100644 index 000000000000..6b19c17e5491 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/EmulateInstruction.h @@ -0,0 +1,507 @@ +//===-- EmulateInstruction.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_EmulateInstruction_h_ +#define lldb_EmulateInstruction_h_ + +#include <string> + +#include "lldb/Core/Address.h" +#include "lldb/Core/Opcode.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-private-enumerations.h" +#include "lldb/lldb-private-types.h" +#include "lldb/lldb-types.h" + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class OptionValueDictionary; +class RegisterContext; +class RegisterValue; +class Stream; +class Target; +class UnwindPlan; + +/// \class EmulateInstruction EmulateInstruction.h +/// "lldb/Core/EmulateInstruction.h" +/// A class that allows emulation of CPU opcodes. +/// +/// This class is a plug-in interface that is accessed through the standard +/// static FindPlugin function call in the EmulateInstruction class. The +/// FindPlugin takes a target triple and returns a new object if there is a +/// plug-in that supports the architecture and OS. Four callbacks and a baton +/// are provided. The four callbacks are read register, write register, read +/// memory and write memory. +/// +/// This class is currently designed for these main use cases: - Auto +/// generation of Call Frame Information (CFI) from assembly code - Predicting +/// single step breakpoint locations - Emulating instructions for breakpoint +/// traps +/// +/// Objects can be asked to read an instruction which will cause a call to the +/// read register callback to get the PC, followed by a read memory call to +/// read the opcode. If ReadInstruction () returns true, then a call to +/// EmulateInstruction::EvaluateInstruction () can be made. At this point the +/// EmulateInstruction subclass will use all of the callbacks to emulate an +/// instruction. +/// +/// Clients that provide the callbacks can either do the read/write +/// registers/memory to actually emulate the instruction on a real or virtual +/// CPU, or watch for the EmulateInstruction::Context which is context for the +/// read/write register/memory which explains why the callback is being +/// called. Examples of a context are: "pushing register 3 onto the stack at +/// offset -12", or "adjusting stack pointer by -16". This extra context +/// allows the generation of +/// CFI information from assembly code without having to actually do +/// the read/write register/memory. +/// +/// Clients must be prepared that not all instructions for an Instruction Set +/// Architecture (ISA) will be emulated. +/// +/// Subclasses at the very least should implement the instructions that save +/// and restore registers onto the stack and adjustment to the stack pointer. +/// By just implementing a few instructions for an ISA that are the typical +/// prologue opcodes, you can then generate CFI using a class that will soon +/// be available. +/// +/// Implementing all of the instructions that affect the PC can then allow +/// single step prediction support. +/// +/// Implementing all of the instructions allows for emulation of opcodes for +/// breakpoint traps and will pave the way for "thread centric" debugging. The +/// current debugging model is "process centric" where all threads must be +/// stopped when any thread is stopped; when hitting software breakpoints we +/// must disable the breakpoint by restoring the original breakpoint opcode, +/// single stepping and restoring the breakpoint trap. If all threads were +/// allowed to run then other threads could miss the breakpoint. +/// +/// This class centralizes the code that usually is done in separate code +/// paths in a debugger (single step prediction, finding save restore +/// locations of registers for unwinding stack frame variables) and emulating +/// the instruction is just a bonus. + +class EmulateInstruction : public PluginInterface { +public: + static EmulateInstruction *FindPlugin(const ArchSpec &arch, + InstructionType supported_inst_type, + const char *plugin_name); + + enum ContextType { + eContextInvalid = 0, + // Read an instruction opcode from memory + eContextReadOpcode, + + // Usually used for writing a register value whose source value is an + // immediate + eContextImmediate, + + // Exclusively used when saving a register to the stack as part of the + // prologue + eContextPushRegisterOnStack, + + // Exclusively used when restoring a register off the stack as part of the + // epilogue + eContextPopRegisterOffStack, + + // Add or subtract a value from the stack + eContextAdjustStackPointer, + + // Adjust the frame pointer for the current frame + eContextSetFramePointer, + + // Typically in an epilogue sequence. Copy the frame pointer back into the + // stack pointer, use SP for CFA calculations again. + eContextRestoreStackPointer, + + // Add or subtract a value from a base address register (other than SP) + eContextAdjustBaseRegister, + + // Add or subtract a value from the PC or store a value to the PC. + eContextAdjustPC, + + // Used in WriteRegister callbacks to indicate where the + eContextRegisterPlusOffset, + + // Used in WriteMemory callback to indicate where the data came from + eContextRegisterStore, + + eContextRegisterLoad, + + // Used when performing a PC-relative branch where the + eContextRelativeBranchImmediate, + + // Used when performing an absolute branch where the + eContextAbsoluteBranchRegister, + + // Used when performing a supervisor call to an operating system to provide + // a service: + eContextSupervisorCall, + + // Used when performing a MemU operation to read the PC-relative offset + // from an address. + eContextTableBranchReadMemory, + + // Used when random bits are written into a register + eContextWriteRegisterRandomBits, + + // Used when random bits are written to memory + eContextWriteMemoryRandomBits, + + eContextArithmetic, + + eContextAdvancePC, + + eContextReturnFromException + }; + + enum InfoType { + eInfoTypeRegisterPlusOffset, + eInfoTypeRegisterPlusIndirectOffset, + eInfoTypeRegisterToRegisterPlusOffset, + eInfoTypeRegisterToRegisterPlusIndirectOffset, + eInfoTypeRegisterRegisterOperands, + eInfoTypeOffset, + eInfoTypeRegister, + eInfoTypeImmediate, + eInfoTypeImmediateSigned, + eInfoTypeAddress, + eInfoTypeISAAndImmediate, + eInfoTypeISAAndImmediateSigned, + eInfoTypeISA, + eInfoTypeNoArgs + } InfoType; + + struct Context { + ContextType type; + enum InfoType info_type; + union { + struct RegisterPlusOffset { + RegisterInfo reg; // base register + int64_t signed_offset; // signed offset added to base register + } RegisterPlusOffset; + + struct RegisterPlusIndirectOffset { + RegisterInfo base_reg; // base register number + RegisterInfo offset_reg; // offset register kind + } RegisterPlusIndirectOffset; + + struct RegisterToRegisterPlusOffset { + RegisterInfo data_reg; // source/target register for data + RegisterInfo base_reg; // base register for address calculation + int64_t offset; // offset for address calculation + } RegisterToRegisterPlusOffset; + + struct RegisterToRegisterPlusIndirectOffset { + RegisterInfo base_reg; // base register for address calculation + RegisterInfo offset_reg; // offset register for address calculation + RegisterInfo data_reg; // source/target register for data + } RegisterToRegisterPlusIndirectOffset; + + struct RegisterRegisterOperands { + RegisterInfo + operand1; // register containing first operand for binary op + RegisterInfo + operand2; // register containing second operand for binary op + } RegisterRegisterOperands; + + int64_t signed_offset; // signed offset by which to adjust self (for + // registers only) + + RegisterInfo reg; // plain register + + uint64_t unsigned_immediate; // unsigned immediate value + int64_t signed_immediate; // signed immediate value + + lldb::addr_t address; // direct address + + struct ISAAndImmediate { + uint32_t isa; + uint32_t unsigned_data32; // immediate data + } ISAAndImmediate; + + struct ISAAndImmediateSigned { + uint32_t isa; + int32_t signed_data32; // signed immediate data + } ISAAndImmediateSigned; + + uint32_t isa; + } info; + + Context() : type(eContextInvalid), info_type(eInfoTypeNoArgs) {} + + void SetRegisterPlusOffset(RegisterInfo base_reg, int64_t signed_offset) { + info_type = eInfoTypeRegisterPlusOffset; + info.RegisterPlusOffset.reg = base_reg; + info.RegisterPlusOffset.signed_offset = signed_offset; + } + + void SetRegisterPlusIndirectOffset(RegisterInfo base_reg, + RegisterInfo offset_reg) { + info_type = eInfoTypeRegisterPlusIndirectOffset; + info.RegisterPlusIndirectOffset.base_reg = base_reg; + info.RegisterPlusIndirectOffset.offset_reg = offset_reg; + } + + void SetRegisterToRegisterPlusOffset(RegisterInfo data_reg, + RegisterInfo base_reg, + int64_t offset) { + info_type = eInfoTypeRegisterToRegisterPlusOffset; + info.RegisterToRegisterPlusOffset.data_reg = data_reg; + info.RegisterToRegisterPlusOffset.base_reg = base_reg; + info.RegisterToRegisterPlusOffset.offset = offset; + } + + void SetRegisterToRegisterPlusIndirectOffset(RegisterInfo base_reg, + RegisterInfo offset_reg, + RegisterInfo data_reg) { + info_type = eInfoTypeRegisterToRegisterPlusIndirectOffset; + info.RegisterToRegisterPlusIndirectOffset.base_reg = base_reg; + info.RegisterToRegisterPlusIndirectOffset.offset_reg = offset_reg; + info.RegisterToRegisterPlusIndirectOffset.data_reg = data_reg; + } + + void SetRegisterRegisterOperands(RegisterInfo op1_reg, + RegisterInfo op2_reg) { + info_type = eInfoTypeRegisterRegisterOperands; + info.RegisterRegisterOperands.operand1 = op1_reg; + info.RegisterRegisterOperands.operand2 = op2_reg; + } + + void SetOffset(int64_t signed_offset) { + info_type = eInfoTypeOffset; + info.signed_offset = signed_offset; + } + + void SetRegister(RegisterInfo reg) { + info_type = eInfoTypeRegister; + info.reg = reg; + } + + void SetImmediate(uint64_t immediate) { + info_type = eInfoTypeImmediate; + info.unsigned_immediate = immediate; + } + + void SetImmediateSigned(int64_t signed_immediate) { + info_type = eInfoTypeImmediateSigned; + info.signed_immediate = signed_immediate; + } + + void SetAddress(lldb::addr_t address) { + info_type = eInfoTypeAddress; + info.address = address; + } + void SetISAAndImmediate(uint32_t isa, uint32_t data) { + info_type = eInfoTypeISAAndImmediate; + info.ISAAndImmediate.isa = isa; + info.ISAAndImmediate.unsigned_data32 = data; + } + + void SetISAAndImmediateSigned(uint32_t isa, int32_t data) { + info_type = eInfoTypeISAAndImmediateSigned; + info.ISAAndImmediateSigned.isa = isa; + info.ISAAndImmediateSigned.signed_data32 = data; + } + + void SetISA(uint32_t isa) { + info_type = eInfoTypeISA; + info.isa = isa; + } + + void SetNoArgs() { info_type = eInfoTypeNoArgs; } + + void Dump(Stream &s, EmulateInstruction *instruction) const; + }; + + typedef size_t (*ReadMemoryCallback)(EmulateInstruction *instruction, + void *baton, const Context &context, + lldb::addr_t addr, void *dst, + size_t length); + + typedef size_t (*WriteMemoryCallback)(EmulateInstruction *instruction, + void *baton, const Context &context, + lldb::addr_t addr, const void *dst, + size_t length); + + typedef bool (*ReadRegisterCallback)(EmulateInstruction *instruction, + void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value); + + typedef bool (*WriteRegisterCallback)(EmulateInstruction *instruction, + void *baton, const Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value); + + // Type to represent the condition of an instruction. The UINT32 value is + // reserved for the unconditional case and all other value can be used in an + // architecture dependent way. + typedef uint32_t InstructionCondition; + static const InstructionCondition UnconditionalCondition = UINT32_MAX; + + EmulateInstruction(const ArchSpec &arch); + + ~EmulateInstruction() override = default; + + // Mandatory overrides + virtual bool + SupportsEmulatingInstructionsOfType(InstructionType inst_type) = 0; + + virtual bool SetTargetTriple(const ArchSpec &arch) = 0; + + virtual bool ReadInstruction() = 0; + + virtual bool EvaluateInstruction(uint32_t evaluate_options) = 0; + + virtual InstructionCondition GetInstructionCondition() { + return UnconditionalCondition; + } + + virtual bool TestEmulation(Stream *out_stream, ArchSpec &arch, + OptionValueDictionary *test_data) = 0; + + virtual bool GetRegisterInfo(lldb::RegisterKind reg_kind, uint32_t reg_num, + RegisterInfo ®_info) = 0; + + // Optional overrides + virtual bool SetInstruction(const Opcode &insn_opcode, + const Address &inst_addr, Target *target); + + virtual bool CreateFunctionEntryUnwind(UnwindPlan &unwind_plan); + + static const char *TranslateRegister(lldb::RegisterKind reg_kind, + uint32_t reg_num, std::string ®_name); + + // RegisterInfo variants + bool ReadRegister(const RegisterInfo *reg_info, RegisterValue ®_value); + + uint64_t ReadRegisterUnsigned(const RegisterInfo *reg_info, + uint64_t fail_value, bool *success_ptr); + + bool WriteRegister(const Context &context, const RegisterInfo *ref_info, + const RegisterValue ®_value); + + bool WriteRegisterUnsigned(const Context &context, + const RegisterInfo *reg_info, uint64_t reg_value); + + // Register kind and number variants + bool ReadRegister(lldb::RegisterKind reg_kind, uint32_t reg_num, + RegisterValue ®_value); + + bool WriteRegister(const Context &context, lldb::RegisterKind reg_kind, + uint32_t reg_num, const RegisterValue ®_value); + + uint64_t ReadRegisterUnsigned(lldb::RegisterKind reg_kind, uint32_t reg_num, + uint64_t fail_value, bool *success_ptr); + + bool WriteRegisterUnsigned(const Context &context, + lldb::RegisterKind reg_kind, uint32_t reg_num, + uint64_t reg_value); + + size_t ReadMemory(const Context &context, lldb::addr_t addr, void *dst, + size_t dst_len); + + uint64_t ReadMemoryUnsigned(const Context &context, lldb::addr_t addr, + size_t byte_size, uint64_t fail_value, + bool *success_ptr); + + bool WriteMemory(const Context &context, lldb::addr_t addr, const void *src, + size_t src_len); + + bool WriteMemoryUnsigned(const Context &context, lldb::addr_t addr, + uint64_t uval, size_t uval_byte_size); + + uint32_t GetAddressByteSize() const { return m_arch.GetAddressByteSize(); } + + lldb::ByteOrder GetByteOrder() const { return m_arch.GetByteOrder(); } + + const Opcode &GetOpcode() const { return m_opcode; } + + lldb::addr_t GetAddress() const { return m_addr; } + + const ArchSpec &GetArchitecture() const { return m_arch; } + + static size_t ReadMemoryFrame(EmulateInstruction *instruction, void *baton, + const Context &context, lldb::addr_t addr, + void *dst, size_t length); + + static size_t WriteMemoryFrame(EmulateInstruction *instruction, void *baton, + const Context &context, lldb::addr_t addr, + const void *dst, size_t length); + + static bool ReadRegisterFrame(EmulateInstruction *instruction, void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value); + + static bool WriteRegisterFrame(EmulateInstruction *instruction, void *baton, + const Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value); + + static size_t ReadMemoryDefault(EmulateInstruction *instruction, void *baton, + const Context &context, lldb::addr_t addr, + void *dst, size_t length); + + static size_t WriteMemoryDefault(EmulateInstruction *instruction, void *baton, + const Context &context, lldb::addr_t addr, + const void *dst, size_t length); + + static bool ReadRegisterDefault(EmulateInstruction *instruction, void *baton, + const RegisterInfo *reg_info, + RegisterValue ®_value); + + static bool WriteRegisterDefault(EmulateInstruction *instruction, void *baton, + const Context &context, + const RegisterInfo *reg_info, + const RegisterValue ®_value); + + void SetBaton(void *baton); + + void SetCallbacks(ReadMemoryCallback read_mem_callback, + WriteMemoryCallback write_mem_callback, + ReadRegisterCallback read_reg_callback, + WriteRegisterCallback write_reg_callback); + + void SetReadMemCallback(ReadMemoryCallback read_mem_callback); + + void SetWriteMemCallback(WriteMemoryCallback write_mem_callback); + + void SetReadRegCallback(ReadRegisterCallback read_reg_callback); + + void SetWriteRegCallback(WriteRegisterCallback write_reg_callback); + + static bool GetBestRegisterKindAndNumber(const RegisterInfo *reg_info, + lldb::RegisterKind ®_kind, + uint32_t ®_num); + + static uint32_t GetInternalRegisterNumber(RegisterContext *reg_ctx, + const RegisterInfo ®_info); + +protected: + ArchSpec m_arch; + void *m_baton = nullptr; + ReadMemoryCallback m_read_mem_callback = &ReadMemoryDefault; + WriteMemoryCallback m_write_mem_callback = &WriteMemoryDefault; + ReadRegisterCallback m_read_reg_callback = &ReadRegisterDefault; + WriteRegisterCallback m_write_reg_callback = &WriteRegisterDefault; + lldb::addr_t m_addr = LLDB_INVALID_ADDRESS; + Opcode m_opcode; + +private: + // For EmulateInstruction only + DISALLOW_COPY_AND_ASSIGN(EmulateInstruction); +}; + +} // namespace lldb_private + +#endif // lldb_EmulateInstruction_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/FileLineResolver.h b/contrib/llvm-project/lldb/include/lldb/Core/FileLineResolver.h new file mode 100644 index 000000000000..d6525b71bfdf --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/FileLineResolver.h @@ -0,0 +1,66 @@ +//===-- FileLineResolver.h --------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_FileLineResolver_h_ +#define liblldb_FileLineResolver_h_ + +#include "lldb/Core/SearchFilter.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/lldb-defines.h" + +#include <stdint.h> + +namespace lldb_private { +class Address; +class Stream; + +/// \class FileLineResolver FileLineResolver.h "lldb/Core/FileLineResolver.h" +/// This class finds address for source file and line. Optionally, it will +/// look for inlined instances of the file and line specification. + +class FileLineResolver : public Searcher { +public: + FileLineResolver() + : m_file_spec(), + m_line_number(UINT32_MAX), // Set this to zero for all lines in a file + m_sc_list(), m_inlines(true) {} + + FileLineResolver(const FileSpec &resolver, uint32_t line_no, + bool check_inlines); + + ~FileLineResolver() override; + + Searcher::CallbackReturn SearchCallback(SearchFilter &filter, + SymbolContext &context, + Address *addr) override; + + lldb::SearchDepth GetDepth() override; + + void GetDescription(Stream *s) override; + + const SymbolContextList &GetFileLineMatches() { return m_sc_list; } + + void Clear(); + + void Reset(const FileSpec &file_spec, uint32_t line, bool check_inlines); + +protected: + FileSpec m_file_spec; // This is the file spec we are looking for. + uint32_t m_line_number; // This is the line number that we are looking for. + SymbolContextList m_sc_list; + bool m_inlines; // This determines whether the resolver looks for inlined + // functions or not. + +private: + DISALLOW_COPY_AND_ASSIGN(FileLineResolver); +}; + +} // namespace lldb_private + +#endif // liblldb_FileLineResolver_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/FileSpecList.h b/contrib/llvm-project/lldb/include/lldb/Core/FileSpecList.h new file mode 100644 index 000000000000..8edc3280b01b --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/FileSpecList.h @@ -0,0 +1,207 @@ +//===-- FileSpecList.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_FileSpecList_h_ +#define liblldb_FileSpecList_h_ +#if defined(__cplusplus) + +#include "lldb/Utility/FileSpec.h" + +#include <vector> + +#include <stddef.h> + +namespace lldb_private { +class Stream; + +/// \class FileSpecList FileSpecList.h "lldb/Core/FileSpecList.h" +/// A file collection class. +/// +/// A class that contains a mutable list of FileSpec objects. +class FileSpecList { +public: + typedef std::vector<FileSpec> collection; + typedef collection::const_iterator const_iterator; + + /// Default constructor. + /// + /// Initialize this object with an empty file list. + FileSpecList(); + + /// Copy constructor. + FileSpecList(const FileSpecList &rhs) = default; + + /// Move constructor + FileSpecList(FileSpecList &&rhs) = default; + + /// Initialize this object from a vector of FileSpecs + FileSpecList(std::vector<FileSpec> &&rhs) : m_files(std::move(rhs)) {} + + /// Destructor. + ~FileSpecList(); + + /// Assignment operator. + /// + /// Replace the file list in this object with the file list from \a rhs. + /// + /// \param[in] rhs + /// A file list object to copy. + /// + /// \return + /// A const reference to this object. + FileSpecList &operator=(const FileSpecList &rhs) = default; + + /// Move-assignment operator. + FileSpecList &operator=(FileSpecList &&rhs) = default; + + /// Append a FileSpec object to the list. + /// + /// Appends \a file to the end of the file list. + /// + /// \param[in] file + /// A new file to append to this file list. + void Append(const FileSpec &file); + + /// Append a FileSpec object if unique. + /// + /// Appends \a file to the end of the file list if it doesn't already exist + /// in the file list. + /// + /// \param[in] file + /// A new file to append to this file list. + /// + /// \return + /// \b true if the file was appended, \b false otherwise. + bool AppendIfUnique(const FileSpec &file); + + /// Inserts a new FileSpec into the FileSpecList constructed in-place with + /// the given arguments. + /// + /// \param[in] args + /// Arguments to create the FileSpec + template <class... Args> void EmplaceBack(Args &&... args) { + m_files.emplace_back(std::forward<Args>(args)...); + } + + /// Clears the file list. + void Clear(); + + /// Dumps the file list to the supplied stream pointer "s". + /// + /// \param[in] s + /// The stream that will be used to dump the object description. + void Dump(Stream *s, const char *separator_cstr = "\n") const; + + /// Find a file index. + /// + /// Find the index of the file in the file spec list that matches \a file + /// starting \a idx entries into the file spec list. + /// + /// \param[in] idx + /// An index into the file list. + /// + /// \param[in] file + /// The file specification to search for. + /// + /// \param[in] full + /// Should FileSpec::Equal be called with "full" true or false. + /// + /// \return + /// The index of the file that matches \a file if it is found, + /// else UINT32_MAX is returned. + size_t FindFileIndex(size_t idx, const FileSpec &file, bool full) const; + + /// Get file at index. + /// + /// Gets a file from the file list. If \a idx is not a valid index, an empty + /// FileSpec object will be returned. The file objects that are returned can + /// be tested using FileSpec::operator void*(). + /// + /// \param[in] idx + /// An index into the file list. + /// + /// \return + /// A copy of the FileSpec object at index \a idx. If \a idx + /// is out of range, then an empty FileSpec object will be + /// returned. + const FileSpec &GetFileSpecAtIndex(size_t idx) const; + + /// Get file specification pointer at index. + /// + /// Gets a file from the file list. The file objects that are returned can + /// be tested using FileSpec::operator void*(). + /// + /// \param[in] idx + /// An index into the file list. + /// + /// \return + /// A pointer to a contained FileSpec object at index \a idx. + /// If \a idx is out of range, then an NULL is returned. + const FileSpec *GetFileSpecPointerAtIndex(size_t idx) const; + + /// Get the memory cost of this object. + /// + /// Return the size in bytes that this object takes in memory. This returns + /// the size in bytes of this object, not any shared string values it may + /// refer to. + /// + /// \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(); } + + /// Get the number of files in the file list. + /// + /// \return + /// The number of files in the file spec list. + size_t GetSize() const; + + bool Insert(size_t idx, const FileSpec &file) { + if (idx < m_files.size()) { + m_files.insert(m_files.begin() + idx, file); + return true; + } else if (idx == m_files.size()) { + m_files.push_back(file); + return true; + } + return false; + } + + bool Replace(size_t idx, const FileSpec &file) { + if (idx < m_files.size()) { + m_files[idx] = file; + return true; + } + return false; + } + + bool Remove(size_t idx) { + if (idx < m_files.size()) { + m_files.erase(m_files.begin() + idx); + return true; + } + return false; + } + + static size_t GetFilesMatchingPartialPath(const char *path, bool dir_okay, + FileSpecList &matches); + + const_iterator begin() const { return m_files.begin(); } + const_iterator end() const { return m_files.end(); } + +protected: + collection m_files; ///< A collection of FileSpec objects. +}; + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_FileSpecList_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/FormatEntity.h b/contrib/llvm-project/lldb/include/lldb/Core/FormatEntity.h new file mode 100644 index 000000000000..ae6c402a45be --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/FormatEntity.h @@ -0,0 +1,220 @@ +//===-- FormatEntity.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_FormatEntity_h_ +#define liblldb_FormatEntity_h_ + +#include "lldb/Utility/CompletionRequest.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Status.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-types.h" +#include <algorithm> +#include <stddef.h> +#include <stdint.h> + +#include <string> +#include <vector> + +namespace lldb_private { +class Address; +class ExecutionContext; +class Stream; +class StringList; +class SymbolContext; +class ValueObject; +} +namespace llvm { +class StringRef; +} + +namespace lldb_private { +class FormatEntity { +public: + struct Entry { + enum class Type { + Invalid, + ParentNumber, + ParentString, + EscapeCode, + Root, + String, + Scope, + Variable, + VariableSynthetic, + ScriptVariable, + ScriptVariableSynthetic, + AddressLoad, + AddressFile, + AddressLoadOrFile, + ProcessID, + ProcessFile, + ScriptProcess, + ThreadID, + ThreadProtocolID, + ThreadIndexID, + ThreadName, + ThreadQueue, + ThreadStopReason, + ThreadReturnValue, + ThreadCompletedExpression, + ScriptThread, + ThreadInfo, + TargetArch, + ScriptTarget, + ModuleFile, + File, + Lang, + FrameIndex, + FrameNoDebug, + FrameRegisterPC, + FrameRegisterSP, + FrameRegisterFP, + FrameRegisterFlags, + FrameRegisterByName, + FrameIsArtificial, + ScriptFrame, + FunctionID, + FunctionDidChange, + FunctionInitialFunction, + FunctionName, + FunctionNameWithArgs, + FunctionNameNoArgs, + FunctionAddrOffset, + FunctionAddrOffsetConcrete, + FunctionLineOffset, + FunctionPCOffset, + FunctionInitial, + FunctionChanged, + FunctionIsOptimized, + LineEntryFile, + LineEntryLineNumber, + LineEntryColumn, + LineEntryStartAddress, + LineEntryEndAddress, + CurrentPCArrow + }; + + struct Definition { + const char *name; + const char *string; // Insert this exact string into the output + Entry::Type type; + uint64_t data; + uint32_t num_children; + Definition *children; // An array of "num_children" Definition entries, + bool keep_separator; + }; + + Entry(Type t = Type::Invalid, const char *s = nullptr, + const char *f = nullptr) + : string(s ? s : ""), printf_format(f ? f : ""), children(), + definition(nullptr), type(t), fmt(lldb::eFormatDefault), number(0), + deref(false) {} + + Entry(llvm::StringRef s); + Entry(char ch); + + void AppendChar(char ch); + + void AppendText(const llvm::StringRef &s); + + void AppendText(const char *cstr); + + void AppendEntry(const Entry &&entry) { children.push_back(entry); } + + void Clear() { + string.clear(); + printf_format.clear(); + children.clear(); + definition = nullptr; + type = Type::Invalid; + fmt = lldb::eFormatDefault; + number = 0; + deref = false; + } + + static const char *TypeToCString(Type t); + + void Dump(Stream &s, int depth = 0) const; + + bool operator==(const Entry &rhs) const { + if (string != rhs.string) + return false; + if (printf_format != rhs.printf_format) + return false; + const size_t n = children.size(); + const size_t m = rhs.children.size(); + for (size_t i = 0; i < std::min<size_t>(n, m); ++i) { + if (!(children[i] == rhs.children[i])) + return false; + } + if (children != rhs.children) + return false; + if (definition != rhs.definition) + return false; + if (type != rhs.type) + return false; + if (fmt != rhs.fmt) + return false; + if (deref != rhs.deref) + return false; + return true; + } + + std::string string; + std::string printf_format; + std::vector<Entry> children; + Definition *definition; + Type type; + lldb::Format fmt; + lldb::addr_t number; + bool deref; + }; + + static bool Format(const Entry &entry, Stream &s, const SymbolContext *sc, + const ExecutionContext *exe_ctx, const Address *addr, + ValueObject *valobj, bool function_changed, + bool initial_function); + + static bool FormatStringRef(const llvm::StringRef &format, Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const Address *addr, ValueObject *valobj, + bool function_changed, bool initial_function); + + static bool FormatCString(const char *format, Stream &s, + const SymbolContext *sc, + const ExecutionContext *exe_ctx, + const Address *addr, ValueObject *valobj, + bool function_changed, bool initial_function); + + static Status Parse(const llvm::StringRef &format, Entry &entry); + + static Status ExtractVariableInfo(llvm::StringRef &format_str, + llvm::StringRef &variable_name, + llvm::StringRef &variable_format); + + static void AutoComplete(lldb_private::CompletionRequest &request); + + // Format the current elements into the stream \a s. + // + // The root element will be stripped off and the format str passed in will be + // either an empty string (print a description of this object), or contain a + // `.`-separated series like a domain name that identifies further + // sub-elements to display. + static bool FormatFileSpec(const FileSpec &file, Stream &s, + llvm::StringRef elements, + llvm::StringRef element_format); + +protected: + static Status ParseInternal(llvm::StringRef &format, Entry &parent_entry, + uint32_t depth); +}; +} // namespace lldb_private + +#endif // liblldb_FormatEntity_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Highlighter.h b/contrib/llvm-project/lldb/include/lldb/Core/Highlighter.h new file mode 100644 index 000000000000..88d3bb3a3cd1 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/Highlighter.h @@ -0,0 +1,156 @@ +//===-- Highlighter.h -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Highlighter_h_ +#define liblldb_Highlighter_h_ + +#include <utility> +#include <vector> + +#include "lldb/Utility/Stream.h" +#include "lldb/lldb-enumerations.h" +#include "llvm/ADT/StringRef.h" + +namespace lldb_private { + +/// Represents style that the highlighter should apply to the given source code. +/// Stores information about how every kind of token should be annotated. +struct HighlightStyle { + + /// A pair of strings that should be placed around a certain token. Usually + /// stores color codes in these strings (the suffix string is often used for + /// resetting the terminal attributes back to normal). + class ColorStyle { + std::string m_prefix; + std::string m_suffix; + + public: + ColorStyle() = default; + ColorStyle(llvm::StringRef prefix, llvm::StringRef suffix) { + Set(prefix, suffix); + } + + /// Applies this style to the given value. + /// \param s + /// The stream to which the result should be appended. + /// \param value + /// The value that we should place our strings around. + void Apply(Stream &s, llvm::StringRef value) const; + + /// Sets the prefix and suffix strings. + /// \param prefix + /// \param suffix + void Set(llvm::StringRef prefix, llvm::StringRef suffix); + }; + + /// The style for the token which is below the cursor of the user. Note that + /// this style is overwritten by the SourceManager with the values of + /// stop-show-column-ansi-prefix/stop-show-column-ansi-suffix. + ColorStyle selected; + + /// Matches identifiers to variable or functions. + ColorStyle identifier; + /// Matches any string or character literals in the language: "foo" or 'f' + ColorStyle string_literal; + /// Matches scalar value literals like '42' or '0.1'. + ColorStyle scalar_literal; + /// Matches all reserved keywords in the language. + ColorStyle keyword; + /// Matches any comments in the language. + ColorStyle comment; + /// Matches commas: ',' + ColorStyle comma; + /// Matches one colon: ':' + ColorStyle colon; + /// Matches any semicolon: ';' + ColorStyle semicolons; + /// Matches operators like '+', '-', '%', '&', '=' + ColorStyle operators; + + /// Matches '{' or '}' + ColorStyle braces; + /// Matches '[' or ']' + ColorStyle square_brackets; + /// Matches '(' or ')' + ColorStyle parentheses; + + // C language specific options + + /// Matches directives to a preprocessor (if the language has any). + ColorStyle pp_directive; + + /// Returns a HighlightStyle that is based on vim's default highlight style. + static HighlightStyle MakeVimStyle(); +}; + +/// Annotates source code with color attributes. +class Highlighter { +public: + Highlighter() = default; + virtual ~Highlighter() = default; + DISALLOW_COPY_AND_ASSIGN(Highlighter); + + /// Returns a human readable name for the selected highlighter. + virtual llvm::StringRef GetName() const = 0; + + /// Highlights the given line + /// \param options + /// \param line + /// The user supplied line that needs to be highlighted. + /// \param cursor_pos + /// The cursor position of the user in this line, starting at 0 (which + /// means the cursor is on the first character in 'line'). + /// \param previous_lines + /// Any previous lines the user has written which we should only use + /// for getting the context of the Highlighting right. + /// \param s + /// The stream to which the highlighted version of the user string should + /// be written. + virtual void Highlight(const HighlightStyle &options, llvm::StringRef line, + llvm::Optional<size_t> cursor_pos, + llvm::StringRef previous_lines, Stream &s) const = 0; + + /// Utility method for calling Highlight without a stream. + std::string Highlight(const HighlightStyle &options, llvm::StringRef line, + llvm::Optional<size_t> cursor_pos, + llvm::StringRef previous_lines = "") const; +}; + +/// A default highlighter that only highlights the user cursor, but doesn't +/// do any other highlighting. +class DefaultHighlighter : public Highlighter { +public: + llvm::StringRef GetName() const override { return "none"; } + + void Highlight(const HighlightStyle &options, llvm::StringRef line, + llvm::Optional<size_t> cursor_pos, + llvm::StringRef previous_lines, Stream &s) const override; +}; + +/// Manages the available highlighters. +class HighlighterManager { + DefaultHighlighter m_default; + +public: + /// Queries all known highlighter for one that can highlight some source code. + /// \param language_type + /// The language type that the caller thinks the source code was given in. + /// \param path + /// The path to the file the source code is from. Used as a fallback when + /// the user can't provide a language. + /// \return + /// The highlighter that wants to highlight the source code. Could be an + /// empty highlighter that does nothing. + const Highlighter &getHighlighterFor(lldb::LanguageType language_type, + llvm::StringRef path) const; + const Highlighter &getDefaultHighlighter() const { return m_default; } +}; + +} // namespace lldb_private + +#endif // liblldb_Highlighter_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/IOHandler.h b/contrib/llvm-project/lldb/include/lldb/Core/IOHandler.h new file mode 100644 index 000000000000..37142a5a8396 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/IOHandler.h @@ -0,0 +1,585 @@ +//===-- IOHandler.h ---------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_IOHandler_h_ +#define liblldb_IOHandler_h_ + +#include "lldb/Core/ValueObjectList.h" +#include "lldb/Utility/CompletionRequest.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Flags.h" +#include "lldb/Utility/Predicate.h" +#include "lldb/Utility/Reproducer.h" +#include "lldb/Utility/Stream.h" +#include "lldb/Utility/StringList.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-forward.h" +#include "llvm/ADT/StringRef.h" + +#include <memory> +#include <mutex> +#include <string> +#include <vector> + +#include <stdint.h> +#include <stdio.h> + +namespace lldb_private { +class Debugger; +} + +namespace curses { +class Application; +typedef std::unique_ptr<Application> ApplicationAP; +} // namespace curses + +namespace lldb_private { + +class IOHandler { +public: + enum class Type { + CommandInterpreter, + CommandList, + Confirm, + Curses, + Expression, + REPL, + ProcessIO, + PythonInterpreter, + PythonCode, + Other + }; + + IOHandler(Debugger &debugger, IOHandler::Type type); + + IOHandler(Debugger &debugger, IOHandler::Type type, + const lldb::FileSP &input_sp, const lldb::StreamFileSP &output_sp, + const lldb::StreamFileSP &error_sp, uint32_t flags, + repro::DataRecorder *data_recorder); + + virtual ~IOHandler(); + + // Each IOHandler gets to run until it is done. It should read data from the + // "in" and place output into "out" and "err and return when done. + virtual void Run() = 0; + + // Called when an input reader should relinquish its control so another can + // be pushed onto the IO handler stack, or so the current IO handler can pop + // itself off the stack + + virtual void Cancel() = 0; + + // Called when CTRL+C is pressed which usually causes + // Debugger::DispatchInputInterrupt to be called. + + virtual bool Interrupt() = 0; + + virtual void GotEOF() = 0; + + virtual bool IsActive() { return m_active && !m_done; } + + virtual void SetIsDone(bool b) { m_done = b; } + + virtual bool GetIsDone() { return m_done; } + + Type GetType() const { return m_type; } + + virtual void Activate() { m_active = true; } + + virtual void Deactivate() { m_active = false; } + + virtual const char *GetPrompt() { + // Prompt support isn't mandatory + return nullptr; + } + + virtual bool SetPrompt(llvm::StringRef prompt) { + // Prompt support isn't mandatory + return false; + } + bool SetPrompt(const char *) = delete; + + virtual ConstString GetControlSequence(char ch) { return ConstString(); } + + virtual const char *GetCommandPrefix() { return nullptr; } + + virtual const char *GetHelpPrologue() { return nullptr; } + + int GetInputFD(); + + int GetOutputFD(); + + int GetErrorFD(); + + FILE *GetInputFILE(); + + FILE *GetOutputFILE(); + + FILE *GetErrorFILE(); + + lldb::FileSP &GetInputFileSP(); + + lldb::StreamFileSP &GetOutputStreamFileSP(); + + lldb::StreamFileSP &GetErrorStreamFileSP(); + + Debugger &GetDebugger() { return m_debugger; } + + void *GetUserData() { return m_user_data; } + + void SetUserData(void *user_data) { m_user_data = user_data; } + + Flags &GetFlags() { return m_flags; } + + const Flags &GetFlags() const { return m_flags; } + + /// Check if the input is being supplied interactively by a user + /// + /// This will return true if the input stream is a terminal (tty or + /// pty) and can cause IO handlers to do different things (like + /// for a confirmation when deleting all breakpoints). + bool GetIsInteractive(); + + /// Check if the input is coming from a real terminal. + /// + /// A real terminal has a valid size with a certain number of rows + /// and columns. If this function returns true, then terminal escape + /// sequences are expected to work (cursor movement escape sequences, + /// clearing lines, etc). + bool GetIsRealTerminal(); + + void SetPopped(bool b); + + void WaitForPop(); + + virtual void PrintAsync(Stream *stream, const char *s, size_t len) { + stream->Write(s, len); + stream->Flush(); + } + +protected: + Debugger &m_debugger; + lldb::FileSP m_input_sp; + lldb::StreamFileSP m_output_sp; + lldb::StreamFileSP m_error_sp; + repro::DataRecorder *m_data_recorder; + Predicate<bool> m_popped; + Flags m_flags; + Type m_type; + void *m_user_data; + bool m_done; + bool m_active; + +private: + DISALLOW_COPY_AND_ASSIGN(IOHandler); +}; + +/// A delegate class for use with IOHandler subclasses. +/// +/// The IOHandler delegate is designed to be mixed into classes so +/// they can use an IOHandler subclass to fetch input and notify the +/// object that inherits from this delegate class when a token is +/// received. +class IOHandlerDelegate { +public: + enum class Completion { None, LLDBCommand, Expression }; + + IOHandlerDelegate(Completion completion = Completion::None) + : m_completion(completion) {} + + virtual ~IOHandlerDelegate() = default; + + virtual void IOHandlerActivated(IOHandler &io_handler, bool interactive) {} + + virtual void IOHandlerDeactivated(IOHandler &io_handler) {} + + virtual void IOHandlerComplete(IOHandler &io_handler, + CompletionRequest &request); + + virtual const char *IOHandlerGetFixIndentationCharacters() { return nullptr; } + + /// Called when a new line is created or one of an identified set of + /// indentation characters is typed. + /// + /// This function determines how much indentation should be added + /// or removed to match the recommended amount for the final line. + /// + /// \param[in] io_handler + /// The IOHandler that responsible for input. + /// + /// \param[in] lines + /// The current input up to the line to be corrected. Lines + /// following the line containing the cursor are not included. + /// + /// \param[in] cursor_position + /// The number of characters preceding the cursor on the final + /// line at the time. + /// + /// \return + /// Returns an integer describing the number of spaces needed + /// to correct the indentation level. Positive values indicate + /// that spaces should be added, while negative values represent + /// spaces that should be removed. + virtual int IOHandlerFixIndentation(IOHandler &io_handler, + const StringList &lines, + int cursor_position) { + return 0; + } + + /// Called when a line or lines have been retrieved. + /// + /// This function can handle the current line and possibly call + /// IOHandler::SetIsDone(true) when the IO handler is done like when + /// "quit" is entered as a command, of when an empty line is + /// received. It is up to the delegate to determine when a line + /// should cause a IOHandler to exit. + virtual void IOHandlerInputComplete(IOHandler &io_handler, + std::string &data) = 0; + + virtual void IOHandlerInputInterrupted(IOHandler &io_handler, + std::string &data) {} + + /// Called to determine whether typing enter after the last line in + /// \a lines should end input. This function will not be called on + /// IOHandler objects that are getting single lines. + /// \param[in] io_handler + /// The IOHandler that responsible for updating the lines. + /// + /// \param[in] lines + /// The current multi-line content. May be altered to provide + /// alternative input when complete. + /// + /// \return + /// Return an boolean to indicate whether input is complete, + /// true indicates that no additional input is necessary, while + /// false indicates that more input is required. + virtual bool IOHandlerIsInputComplete(IOHandler &io_handler, + StringList &lines) { + // Impose no requirements for input to be considered complete. subclasses + // should do something more intelligent. + return true; + } + + virtual ConstString IOHandlerGetControlSequence(char ch) { + return ConstString(); + } + + virtual const char *IOHandlerGetCommandPrefix() { return nullptr; } + + virtual const char *IOHandlerGetHelpPrologue() { return nullptr; } + + // Intercept the IOHandler::Interrupt() calls and do something. + // + // Return true if the interrupt was handled, false if the IOHandler should + // continue to try handle the interrupt itself. + virtual bool IOHandlerInterrupt(IOHandler &io_handler) { return false; } + +protected: + Completion m_completion; // Support for common builtin completions +}; + +// IOHandlerDelegateMultiline +// +// A IOHandlerDelegate that handles terminating multi-line input when +// the last line is equal to "end_line" which is specified in the constructor. +class IOHandlerDelegateMultiline : public IOHandlerDelegate { +public: + IOHandlerDelegateMultiline(const char *end_line, + Completion completion = Completion::None) + : IOHandlerDelegate(completion), + m_end_line((end_line && end_line[0]) ? end_line : "") {} + + ~IOHandlerDelegateMultiline() override = default; + + ConstString IOHandlerGetControlSequence(char ch) override { + if (ch == 'd') + return ConstString(m_end_line + "\n"); + return ConstString(); + } + + bool IOHandlerIsInputComplete(IOHandler &io_handler, + StringList &lines) override { + // Determine whether the end of input signal has been entered + const size_t num_lines = lines.GetSize(); + if (num_lines > 0 && lines[num_lines - 1] == m_end_line) { + // Remove the terminal line from "lines" so it doesn't appear in the + // resulting input and return true to indicate we are done getting lines + lines.PopBack(); + return true; + } + return false; + } + +protected: + const std::string m_end_line; +}; + +class IOHandlerEditline : public IOHandler { +public: + IOHandlerEditline(Debugger &debugger, IOHandler::Type type, + const char *editline_name, // Used for saving history files + llvm::StringRef prompt, llvm::StringRef continuation_prompt, + bool multi_line, bool color_prompts, + uint32_t line_number_start, // If non-zero show line numbers + // starting at + // 'line_number_start' + IOHandlerDelegate &delegate, + repro::DataRecorder *data_recorder); + + IOHandlerEditline(Debugger &debugger, IOHandler::Type type, + const lldb::FileSP &input_sp, + const lldb::StreamFileSP &output_sp, + const lldb::StreamFileSP &error_sp, uint32_t flags, + const char *editline_name, // Used for saving history files + llvm::StringRef prompt, llvm::StringRef continuation_prompt, + bool multi_line, bool color_prompts, + uint32_t line_number_start, // If non-zero show line numbers + // starting at + // 'line_number_start' + IOHandlerDelegate &delegate, + repro::DataRecorder *data_recorder); + + IOHandlerEditline(Debugger &, IOHandler::Type, const char *, const char *, + const char *, bool, bool, uint32_t, + IOHandlerDelegate &) = delete; + + IOHandlerEditline(Debugger &, IOHandler::Type, const lldb::FileSP &, + const lldb::StreamFileSP &, const lldb::StreamFileSP &, + uint32_t, const char *, const char *, const char *, bool, + bool, uint32_t, IOHandlerDelegate &) = delete; + + ~IOHandlerEditline() override; + + void Run() override; + + void Cancel() override; + + bool Interrupt() override; + + void GotEOF() override; + + void Activate() override; + + void Deactivate() override; + + ConstString GetControlSequence(char ch) override { + return m_delegate.IOHandlerGetControlSequence(ch); + } + + const char *GetCommandPrefix() override { + return m_delegate.IOHandlerGetCommandPrefix(); + } + + const char *GetHelpPrologue() override { + return m_delegate.IOHandlerGetHelpPrologue(); + } + + const char *GetPrompt() override; + + bool SetPrompt(llvm::StringRef prompt) override; + bool SetPrompt(const char *prompt) = delete; + + const char *GetContinuationPrompt(); + + void SetContinuationPrompt(llvm::StringRef prompt); + void SetContinuationPrompt(const char *) = delete; + + bool GetLine(std::string &line, bool &interrupted); + + bool GetLines(StringList &lines, bool &interrupted); + + void SetBaseLineNumber(uint32_t line); + + bool GetInterruptExits() { return m_interrupt_exits; } + + void SetInterruptExits(bool b) { m_interrupt_exits = b; } + + const StringList *GetCurrentLines() const { return m_current_lines_ptr; } + + uint32_t GetCurrentLineIndex() const; + + void PrintAsync(Stream *stream, const char *s, size_t len) override; + +private: +#ifndef LLDB_DISABLE_LIBEDIT + static bool IsInputCompleteCallback(Editline *editline, StringList &lines, + void *baton); + + static int FixIndentationCallback(Editline *editline, const StringList &lines, + int cursor_position, void *baton); + + static void AutoCompleteCallback(CompletionRequest &request, void *baton); +#endif + +protected: +#ifndef LLDB_DISABLE_LIBEDIT + std::unique_ptr<Editline> m_editline_up; +#endif + IOHandlerDelegate &m_delegate; + std::string m_prompt; + std::string m_continuation_prompt; + StringList *m_current_lines_ptr; + uint32_t m_base_line_number; // If non-zero, then show line numbers in prompt + uint32_t m_curr_line_idx; + bool m_multi_line; + bool m_color_prompts; + bool m_interrupt_exits; + bool m_editing; // Set to true when fetching a line manually (not using + // libedit) + std::string m_line_buffer; +}; + +// The order of base classes is important. Look at the constructor of +// IOHandlerConfirm to see how. +class IOHandlerConfirm : public IOHandlerDelegate, public IOHandlerEditline { +public: + IOHandlerConfirm(Debugger &debugger, llvm::StringRef prompt, + bool default_response); + + ~IOHandlerConfirm() override; + + bool GetResponse() const { return m_user_response; } + + void IOHandlerComplete(IOHandler &io_handler, + CompletionRequest &request) override; + + void IOHandlerInputComplete(IOHandler &io_handler, + std::string &data) override; + +protected: + const bool m_default_response; + bool m_user_response; +}; + +class IOHandlerCursesGUI : public IOHandler { +public: + IOHandlerCursesGUI(Debugger &debugger); + + ~IOHandlerCursesGUI() override; + + void Run() override; + + void Cancel() override; + + bool Interrupt() override; + + void GotEOF() override; + + void Activate() override; + + void Deactivate() override; + +protected: + curses::ApplicationAP m_app_ap; +}; + +class IOHandlerCursesValueObjectList : public IOHandler { +public: + IOHandlerCursesValueObjectList(Debugger &debugger, + ValueObjectList &valobj_list); + + ~IOHandlerCursesValueObjectList() override; + + void Run() override; + + void GotEOF() override; + +protected: + ValueObjectList m_valobj_list; +}; + +class IOHandlerStack { +public: + IOHandlerStack() : m_stack(), m_mutex(), m_top(nullptr) {} + + ~IOHandlerStack() = default; + + size_t GetSize() const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_stack.size(); + } + + void Push(const lldb::IOHandlerSP &sp) { + if (sp) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + sp->SetPopped(false); + m_stack.push_back(sp); + // Set m_top the non-locking IsTop() call + m_top = sp.get(); + } + } + + bool IsEmpty() const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_stack.empty(); + } + + lldb::IOHandlerSP Top() { + lldb::IOHandlerSP sp; + { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + if (!m_stack.empty()) + sp = m_stack.back(); + } + return sp; + } + + void Pop() { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + if (!m_stack.empty()) { + lldb::IOHandlerSP sp(m_stack.back()); + m_stack.pop_back(); + sp->SetPopped(true); + } + // Set m_top the non-locking IsTop() call + + m_top = (m_stack.empty() ? nullptr : m_stack.back().get()); + } + + std::recursive_mutex &GetMutex() { return m_mutex; } + + bool IsTop(const lldb::IOHandlerSP &io_handler_sp) const { + return m_top == io_handler_sp.get(); + } + + bool CheckTopIOHandlerTypes(IOHandler::Type top_type, + IOHandler::Type second_top_type) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + const size_t num_io_handlers = m_stack.size(); + return (num_io_handlers >= 2 && + m_stack[num_io_handlers - 1]->GetType() == top_type && + m_stack[num_io_handlers - 2]->GetType() == second_top_type); + } + + ConstString GetTopIOHandlerControlSequence(char ch) { + return ((m_top != nullptr) ? m_top->GetControlSequence(ch) : ConstString()); + } + + const char *GetTopIOHandlerCommandPrefix() { + return ((m_top != nullptr) ? m_top->GetCommandPrefix() : nullptr); + } + + const char *GetTopIOHandlerHelpPrologue() { + return ((m_top != nullptr) ? m_top->GetHelpPrologue() : nullptr); + } + + void PrintAsync(Stream *stream, const char *s, size_t len); + +protected: + typedef std::vector<lldb::IOHandlerSP> collection; + collection m_stack; + mutable std::recursive_mutex m_mutex; + IOHandler *m_top; + +private: + DISALLOW_COPY_AND_ASSIGN(IOHandlerStack); +}; + +} // namespace lldb_private + +#endif // liblldb_IOHandler_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/IOStreamMacros.h b/contrib/llvm-project/lldb/include/lldb/Core/IOStreamMacros.h new file mode 100644 index 000000000000..45bde88f9441 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/IOStreamMacros.h @@ -0,0 +1,41 @@ +//===-- IOStreamMacros.h ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_IOStreamMacros_h_ +#define liblldb_IOStreamMacros_h_ +#if defined(__cplusplus) + +#include <iomanip> + +#define RAW_HEXBASE std::setfill('0') << std::hex << std::right +#define HEXBASE '0' << 'x' << RAW_HEXBASE +#define RAWHEX8(x) RAW_HEXBASE << std::setw(2) << ((uint32_t)(x)) +#define RAWHEX16 RAW_HEXBASE << std::setw(4) +#define RAWHEX32 RAW_HEXBASE << std::setw(8) +#define RAWHEX64 RAW_HEXBASE << std::setw(16) +#define HEX8(x) HEXBASE << std::setw(2) << ((uint32_t)(x)) +#define HEX16 HEXBASE << std::setw(4) +#define HEX32 HEXBASE << std::setw(8) +#define HEX64 HEXBASE << std::setw(16) +#define RAW_HEX(x) RAW_HEXBASE << std::setw(sizeof(x) * 2) << (x) +#define HEX(x) HEXBASE << std::setw(sizeof(x) * 2) << (x) +#define HEX_SIZE(x, sz) HEXBASE << std::setw((sz)) << (x) +#define STRING_WIDTH(w) std::setfill(' ') << std::setw(w) +#define LEFT_STRING_WIDTH(s, w) \ + std::left << std::setfill(' ') << std::setw(w) << (s) << std::right +#define DECIMAL std::dec << std::setfill(' ') +#define DECIMAL_WIDTH(w) DECIMAL << std::setw(w) +//#define FLOAT(n, d) std::setfill(' ') << std::setw((n)+(d)+1) << +//std::setprecision(d) << std::showpoint << std::fixed +#define INDENT_WITH_SPACES(iword_idx) \ + std::setfill(' ') << std::setw((iword_idx)) << "" +#define INDENT_WITH_TABS(iword_idx) \ + std::setfill('\t') << std::setw((iword_idx)) << "" + +#endif // #if defined(__cplusplus) +#endif // liblldb_IOStreamMacros_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/LoadedModuleInfoList.h b/contrib/llvm-project/lldb/include/lldb/Core/LoadedModuleInfoList.h new file mode 100644 index 000000000000..04e58fcdf313 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/LoadedModuleInfoList.h @@ -0,0 +1,116 @@ +//===-- LoadedModuleInfoList.h ----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_LoadedModuleInfoList_h_ +#define liblldb_LoadedModuleInfoList_h_ + + +#include <cassert> +#include <string> +#include <vector> + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-private-forward.h" +#include "lldb/lldb-types.h" + +namespace lldb_private { +class LoadedModuleInfoList { +public: + class LoadedModuleInfo { + public: + enum e_data_point { + e_has_name = 0, + e_has_base, + e_has_dynamic, + e_has_link_map, + e_num + }; + + LoadedModuleInfo() { + for (uint32_t i = 0; i < e_num; ++i) + m_has[i] = false; + }; + + void set_name(const std::string &name) { + m_name = name; + m_has[e_has_name] = true; + } + bool get_name(std::string &out) const { + out = m_name; + return m_has[e_has_name]; + } + + void set_base(const lldb::addr_t base) { + m_base = base; + m_has[e_has_base] = true; + } + bool get_base(lldb::addr_t &out) const { + out = m_base; + return m_has[e_has_base]; + } + + void set_base_is_offset(bool is_offset) { m_base_is_offset = is_offset; } + bool get_base_is_offset(bool &out) const { + out = m_base_is_offset; + return m_has[e_has_base]; + } + + void set_link_map(const lldb::addr_t addr) { + m_link_map = addr; + m_has[e_has_link_map] = true; + } + bool get_link_map(lldb::addr_t &out) const { + out = m_link_map; + return m_has[e_has_link_map]; + } + + void set_dynamic(const lldb::addr_t addr) { + m_dynamic = addr; + m_has[e_has_dynamic] = true; + } + bool get_dynamic(lldb::addr_t &out) const { + out = m_dynamic; + return m_has[e_has_dynamic]; + } + + bool has_info(e_data_point datum) const { + assert(datum < e_num); + return m_has[datum]; + } + + bool operator==(LoadedModuleInfo const &rhs) const { + for (size_t i = 0; i < e_num; ++i) { + if (m_has[i] != rhs.m_has[i]) + return false; + } + + return (m_base == rhs.m_base) && (m_link_map == rhs.m_link_map) && + (m_dynamic == rhs.m_dynamic) && (m_name == rhs.m_name); + } + + protected: + bool m_has[e_num]; + std::string m_name; + lldb::addr_t m_link_map; + lldb::addr_t m_base; + bool m_base_is_offset; + lldb::addr_t m_dynamic; + }; + + LoadedModuleInfoList() : m_list(), m_link_map(LLDB_INVALID_ADDRESS) {} + + void add(const LoadedModuleInfo &mod) { m_list.push_back(mod); } + + void clear() { m_list.clear(); } + + std::vector<LoadedModuleInfo> m_list; + lldb::addr_t m_link_map; +}; +} // namespace lldb_private + +#endif // liblldb_LoadedModuleInfoList_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Mangled.h b/contrib/llvm-project/lldb/include/lldb/Core/Mangled.h new file mode 100644 index 000000000000..63fa0f618dae --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/Mangled.h @@ -0,0 +1,276 @@ +//===-- Mangled.h -----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Mangled_h_ +#define liblldb_Mangled_h_ +#if defined(__cplusplus) + +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" + +#include "lldb/Utility/ConstString.h" + +#include "llvm/ADT/StringRef.h" + +#include <memory> +#include <stddef.h> + +namespace lldb_private { + +/// \class Mangled Mangled.h "lldb/Core/Mangled.h" +/// A class that handles mangled names. +/// +/// Designed to handle mangled names. The demangled version of any names will +/// be computed when the demangled name is accessed through the Demangled() +/// acccessor. This class can also tokenize the demangled version of the name +/// for powerful searches. Functions and symbols could make instances of this +/// class for their mangled names. Uniqued string pools are used for the +/// mangled, demangled, and token string values to allow for faster +/// comparisons and for efficient memory use. +class Mangled { +public: + enum NamePreference { + ePreferMangled, + ePreferDemangled, + ePreferDemangledWithoutArguments + }; + + enum ManglingScheme { + eManglingSchemeNone = 0, + eManglingSchemeMSVC, + eManglingSchemeItanium + }; + + /// Default constructor. + /// + /// Initialize with both mangled and demangled names empty. + Mangled() = default; + + /// Construct with name. + /// + /// Constructor with an optional string and auto-detect if \a name is + /// mangled or not. + /// + /// \param[in] name + /// The already const name to copy into this object. + explicit Mangled(ConstString name); + + explicit Mangled(llvm::StringRef name); + + /// Convert to pointer operator. + /// + /// This allows code to check a Mangled object to see if it contains a valid + /// mangled name using code such as: + /// + /// \code + /// Mangled mangled(...); + /// if (mangled) + /// { ... + /// \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; + + /// Clear the mangled and demangled values. + void Clear(); + + /// Compare the mangled string values + /// + /// Compares the Mangled::GetName() string in \a lhs and \a rhs. + /// + /// \param[in] lhs + /// A const reference to the Left Hand Side object to compare. + /// + /// \param[in] rhs + /// A const reference to the Right Hand Side object to compare. + /// + /// \return + /// \li -1 if \a lhs is less than \a rhs + /// \li 0 if \a lhs is equal to \a rhs + /// \li 1 if \a lhs is greater than \a rhs + static int Compare(const Mangled &lhs, const Mangled &rhs); + + /// Dump a description of this object to a Stream \a s. + /// + /// Dump a Mangled object to stream \a s. We don't force our demangled name + /// to be computed currently (we don't use the accessor). + /// + /// \param[in] s + /// The stream to which to dump the object description. + void Dump(Stream *s) const; + + /// Dump a debug description of this object to a Stream \a s. + /// + /// \param[in] s + /// The stream to which to dump the object description. + void DumpDebug(Stream *s) const; + + /// Demangled name get accessor. + /// + /// \return + /// A const reference to the demangled name string object. + ConstString GetDemangledName(lldb::LanguageType language) const; + + /// Display demangled name get accessor. + /// + /// \return + /// A const reference to the display demangled name string object. + ConstString GetDisplayDemangledName(lldb::LanguageType language) const; + + void SetDemangledName(ConstString name) { m_demangled = name; } + + void SetMangledName(ConstString name) { m_mangled = name; } + + /// Mangled name get accessor. + /// + /// \return + /// A reference to the mangled name string object. + ConstString &GetMangledName() { return m_mangled; } + + /// Mangled name get accessor. + /// + /// \return + /// A const reference to the mangled name string object. + ConstString GetMangledName() const { return m_mangled; } + + /// Best name get accessor. + /// + /// \param[in] preference + /// Which name would you prefer to get? + /// + /// \return + /// A const reference to the preferred name string object if this + /// object has a valid name of that kind, else a const reference to the + /// other name is returned. + ConstString GetName(lldb::LanguageType language, + NamePreference preference = ePreferDemangled) const; + + /// Check if "name" matches either the mangled or demangled name. + /// + /// \param[in] name + /// A name to match against both strings. + /// + /// \return + /// \b True if \a name matches either name, \b false otherwise. + bool NameMatches(ConstString name, lldb::LanguageType language) const { + if (m_mangled == name) + return true; + return GetDemangledName(language) == name; + } + bool NameMatches(const RegularExpression ®ex, + lldb::LanguageType language) const; + + /// Get the memory cost of this object. + /// + /// Return the size in bytes that this object takes in memory. This returns + /// the size in bytes of this object, not any shared string values it may + /// refer to. + /// + /// \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. + /// + /// If \a is_mangled is \b true, then the mangled named is set to \a name, + /// else the demangled name is set to \a name. + /// + /// \param[in] name + /// The already const version of the name for this object. + /// + /// \param[in] is_mangled + /// If \b true then \a name is a mangled name, if \b false then + /// \a name is demangled. + void SetValue(ConstString name, bool is_mangled); + + /// Set the string value in this object. + /// + /// This version auto detects if the string is mangled by inspecting the + /// string value and looking for common mangling prefixes. + /// + /// \param[in] name + /// The already const version of the name for this object. + void SetValue(ConstString name); + + /// Try to guess the language from the mangling. + /// + /// For a mangled name to have a language it must have both a mangled and a + /// demangled name and it can be guessed from the mangling what the language + /// is. Note: this will return C++ for any language that uses Itanium ABI + /// mangling. + /// + /// Standard C function names will return eLanguageTypeUnknown because they + /// aren't mangled and it isn't clear what language the name represents + /// (there will be no mangled name). + /// + /// \return + /// The language for the mangled/demangled name, eLanguageTypeUnknown + /// if there is no mangled or demangled counterpart. + lldb::LanguageType GuessLanguage() const; + + /// Function signature for filtering mangled names. + using SkipMangledNameFn = bool(llvm::StringRef, ManglingScheme); + + /// Trigger explicit demangling to obtain rich mangling information. This is + /// optimized for batch processing while populating a name index. To get the + /// pure demangled name string for a single entity, use GetDemangledName() + /// instead. + /// + /// For names that match the Itanium mangling scheme, this uses LLVM's + /// ItaniumPartialDemangler. All other names fall back to LLDB's builtin + /// parser currently. + /// + /// This function is thread-safe when used with different \a context + /// instances in different threads. + /// + /// \param[in] context + /// The context for this function. A single instance can be stack- + /// allocated in the caller's frame and used for multiple calls. + /// + /// \param[in] skip_mangled_name + /// A filtering function for skipping entities based on name and mangling + /// scheme. This can be null if unused. + /// + /// \return + /// True on success, false otherwise. + bool DemangleWithRichManglingInfo(RichManglingContext &context, + SkipMangledNameFn *skip_mangled_name); + +private: + /// Mangled member variables. + ConstString m_mangled; ///< The mangled version of the name + mutable ConstString m_demangled; ///< Mutable so we can get it on demand with + ///a const version of this object +}; + +Stream &operator<<(Stream &s, const Mangled &obj); + +} // namespace lldb_private + +#endif // #if defined(__cplusplus) +#endif // liblldb_Mangled_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/MappedHash.h b/contrib/llvm-project/lldb/include/lldb/Core/MappedHash.h new file mode 100644 index 000000000000..7dc9b5be3465 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/MappedHash.h @@ -0,0 +1,310 @@ +//===-- MappedHash.h --------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_MappedHash_h_ +#define liblldb_MappedHash_h_ + +#include <assert.h> +#include <stdint.h> + +#include <algorithm> +#include <functional> +#include <map> +#include <vector> + +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/Stream.h" +#include "llvm/Support/DJB.h" + +class MappedHash { +public: + enum HashFunctionType { + eHashFunctionDJB = 0u // Daniel J Bernstein hash function that is also used + // by the ELF GNU_HASH sections + }; + + static uint32_t HashString(uint32_t hash_function, llvm::StringRef s) { + switch (hash_function) { + case MappedHash::eHashFunctionDJB: + return llvm::djbHash(s); + + default: + break; + } + llvm_unreachable("Invalid hash function index"); + } + + static const uint32_t HASH_MAGIC = 0x48415348u; + static const uint32_t HASH_CIGAM = 0x48534148u; + + template <typename T> struct Header { + typedef T HeaderData; + + uint32_t + magic; // HASH_MAGIC or HASH_CIGAM magic value to allow endian detection + uint16_t version; // Version number + uint16_t hash_function; // The hash function enumeration that was used + uint32_t bucket_count; // The number of buckets in this hash table + uint32_t hashes_count; // The total number of unique hash values and hash + // data offsets in this table + uint32_t header_data_len; // The size in bytes of the "header_data" template + // member below + HeaderData header_data; // + + Header() + : magic(HASH_MAGIC), version(1), hash_function(eHashFunctionDJB), + bucket_count(0), hashes_count(0), header_data_len(sizeof(T)), + header_data() {} + + virtual ~Header() = default; + + size_t GetByteSize() const { + return sizeof(magic) + sizeof(version) + sizeof(hash_function) + + sizeof(bucket_count) + sizeof(hashes_count) + + sizeof(header_data_len) + header_data_len; + } + + virtual size_t GetByteSize(const HeaderData &header_data) = 0; + + void SetHeaderDataByteSize(uint32_t header_data_byte_size) { + header_data_len = header_data_byte_size; + } + + void Dump(lldb_private::Stream &s) { + s.Printf("header.magic = 0x%8.8x\n", magic); + s.Printf("header.version = 0x%4.4x\n", version); + s.Printf("header.hash_function = 0x%4.4x\n", hash_function); + s.Printf("header.bucket_count = 0x%8.8x %u\n", bucket_count, + bucket_count); + s.Printf("header.hashes_count = 0x%8.8x %u\n", hashes_count, + hashes_count); + s.Printf("header.header_data_len = 0x%8.8x %u\n", header_data_len, + header_data_len); + } + + virtual lldb::offset_t Read(lldb_private::DataExtractor &data, + lldb::offset_t offset) { + if (data.ValidOffsetForDataOfSize( + offset, sizeof(magic) + sizeof(version) + sizeof(hash_function) + + sizeof(bucket_count) + sizeof(hashes_count) + + sizeof(header_data_len))) { + magic = data.GetU32(&offset); + if (magic != HASH_MAGIC) { + if (magic == HASH_CIGAM) { + switch (data.GetByteOrder()) { + case lldb::eByteOrderBig: + data.SetByteOrder(lldb::eByteOrderLittle); + break; + case lldb::eByteOrderLittle: + data.SetByteOrder(lldb::eByteOrderBig); + break; + default: + return LLDB_INVALID_OFFSET; + } + } else { + // Magic bytes didn't match + version = 0; + return LLDB_INVALID_OFFSET; + } + } + + version = data.GetU16(&offset); + if (version != 1) { + // Unsupported version + return LLDB_INVALID_OFFSET; + } + hash_function = data.GetU16(&offset); + if (hash_function == 4) + hash_function = 0; // Deal with pre-release version of this table... + bucket_count = data.GetU32(&offset); + hashes_count = data.GetU32(&offset); + header_data_len = data.GetU32(&offset); + return offset; + } + return LLDB_INVALID_OFFSET; + } + // + // // Returns a buffer that contains a serialized version of this + // table + // // that must be freed with free(). + // virtual void * + // Write (int fd); + }; + + // A class for reading and using a saved hash table from a block of data + // in memory + template <typename __KeyType, class __HeaderType, class __HashData> + class MemoryTable { + public: + typedef __HeaderType HeaderType; + typedef __KeyType KeyType; + typedef __HashData HashData; + + enum Result { + eResultKeyMatch = 0u, // The entry was found, key matched and "pair" was + // filled in successfully + eResultKeyMismatch = + 1u, // Bucket hash data collision, but key didn't match + eResultEndOfHashData = 2u, // The chain of items for this hash data in + // this bucket is terminated, search no more + eResultError = 3u // Status parsing the hash data, abort + }; + + struct Pair { + KeyType key; + HashData value; + }; + + MemoryTable(lldb_private::DataExtractor &data) + : m_header(), m_hash_indexes(nullptr), m_hash_values(nullptr), + m_hash_offsets(nullptr) { + lldb::offset_t offset = m_header.Read(data, 0); + if (offset != LLDB_INVALID_OFFSET && IsValid()) { + m_hash_indexes = (const uint32_t *)data.GetData( + &offset, m_header.bucket_count * sizeof(uint32_t)); + m_hash_values = (const uint32_t *)data.GetData( + &offset, m_header.hashes_count * sizeof(uint32_t)); + m_hash_offsets = (const uint32_t *)data.GetData( + &offset, m_header.hashes_count * sizeof(uint32_t)); + } + } + + virtual ~MemoryTable() = default; + + bool IsValid() const { + return m_header.version == 1 && + m_header.hash_function == eHashFunctionDJB && + m_header.bucket_count > 0; + } + + uint32_t GetHashIndex(uint32_t bucket_idx) const { + uint32_t result = UINT32_MAX; + if (m_hash_indexes && bucket_idx < m_header.bucket_count) + memcpy(&result, m_hash_indexes + bucket_idx, sizeof(uint32_t)); + return result; + } + + uint32_t GetHashValue(uint32_t hash_idx) const { + uint32_t result = UINT32_MAX; + if (m_hash_values && hash_idx < m_header.hashes_count) + memcpy(&result, m_hash_values + hash_idx, sizeof(uint32_t)); + return result; + } + + uint32_t GetHashDataOffset(uint32_t hash_idx) const { + uint32_t result = UINT32_MAX; + if (m_hash_offsets && hash_idx < m_header.hashes_count) + memcpy(&result, m_hash_offsets + hash_idx, sizeof(uint32_t)); + return result; + } + + bool Find(llvm::StringRef name, Pair &pair) const { + if (name.empty()) + return false; + + if (IsValid()) { + const uint32_t bucket_count = m_header.bucket_count; + const uint32_t hash_count = m_header.hashes_count; + const uint32_t hash_value = + MappedHash::HashString(m_header.hash_function, name); + const uint32_t bucket_idx = hash_value % bucket_count; + uint32_t hash_idx = GetHashIndex(bucket_idx); + if (hash_idx < hash_count) { + for (; hash_idx < hash_count; ++hash_idx) { + const uint32_t curr_hash_value = GetHashValue(hash_idx); + if (curr_hash_value == hash_value) { + lldb::offset_t hash_data_offset = GetHashDataOffset(hash_idx); + while (hash_data_offset != UINT32_MAX) { + const lldb::offset_t prev_hash_data_offset = hash_data_offset; + Result hash_result = + GetHashDataForName(name, &hash_data_offset, pair); + // Check the result of getting our hash data + switch (hash_result) { + case eResultKeyMatch: + return true; + + case eResultKeyMismatch: + if (prev_hash_data_offset == hash_data_offset) + return false; + break; + + case eResultEndOfHashData: + // The last HashData for this key has been reached, stop + // searching + return false; + case eResultError: + // Status parsing the hash data, abort + return false; + } + } + } + if ((curr_hash_value % bucket_count) != bucket_idx) + break; + } + } + } + return false; + } + + // This method must be implemented in any subclasses. The KeyType is user + // specified and must somehow result in a string value. For example, the + // KeyType might be a string offset in a string table and subclasses can + // store their string table as a member of the subclass and return a valie + // "const char *" given a "key". The value could also be a C string + // pointer, in which case just returning "key" will suffice. + virtual const char *GetStringForKeyType(KeyType key) const = 0; + + virtual bool ReadHashData(uint32_t hash_data_offset, + HashData &hash_data) const = 0; + + // This method must be implemented in any subclasses and it must try to + // read one "Pair" at the offset pointed to by the "hash_data_offset_ptr" + // parameter. This offset should be updated as bytes are consumed and a + // value "Result" enum should be returned. If the "name" matches the full + // name for the "pair.key" (which must be filled in by this call), then the + // HashData in the pair ("pair.value") should be extracted and filled in + // and "eResultKeyMatch" should be returned. If "name" doesn't match this + // string for the key, then "eResultKeyMismatch" should be returned and all + // data for the current HashData must be consumed or skipped and the + // "hash_data_offset_ptr" offset needs to be updated to point to the next + // HashData. If the end of the HashData objects for a given hash value have + // been reached, then "eResultEndOfHashData" should be returned. If + // anything else goes wrong during parsing, return "eResultError" and the + // corresponding "Find()" function will be canceled and return false. + virtual Result GetHashDataForName(llvm::StringRef name, + lldb::offset_t *hash_data_offset_ptr, + Pair &pair) const = 0; + + const HeaderType &GetHeader() { return m_header; } + + void ForEach( + std::function<bool(const HashData &hash_data)> const &callback) const { + const size_t num_hash_offsets = m_header.hashes_count; + for (size_t i = 0; i < num_hash_offsets; ++i) { + uint32_t hash_data_offset = GetHashDataOffset(i); + if (hash_data_offset != UINT32_MAX) { + HashData hash_data; + if (ReadHashData(hash_data_offset, hash_data)) { + // If the callback returns false, then we are done and should stop + if (callback(hash_data) == false) + return; + } + } + } + } + + protected: + // Implementation agnostic information + HeaderType m_header; + const uint32_t *m_hash_indexes; + const uint32_t *m_hash_values; + const uint32_t *m_hash_offsets; + }; +}; + +#endif // liblldb_MappedHash_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Module.h b/contrib/llvm-project/lldb/include/lldb/Core/Module.h new file mode 100644 index 000000000000..89b731427e3f --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/Module.h @@ -0,0 +1,1056 @@ +//===-- Module.h ------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Module_h_ +#define liblldb_Module_h_ + +#include "lldb/Core/Address.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContextScope.h" +#include "lldb/Symbol/TypeSystem.h" +#include "lldb/Target/PathMappingList.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/UUID.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-types.h" + +#include "llvm/ADT/DenseSet.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/Chrono.h" + +#include <atomic> +#include <memory> +#include <mutex> +#include <stddef.h> +#include <stdint.h> +#include <string> +#include <vector> + +namespace lldb_private { +class CompilerDeclContext; +class Function; +class Log; +class ObjectFile; +class RegularExpression; +class SectionList; +class Stream; +class Symbol; +class SymbolContext; +class SymbolContextList; +class SymbolFile; +class Symtab; +class Target; +class TypeList; +class TypeMap; +class VariableList; + +/// \class Module Module.h "lldb/Core/Module.h" +/// A class that describes an executable image and its associated +/// object and symbol files. +/// +/// The module is designed to be able to select a single slice of an +/// executable image as it would appear on disk and during program execution. +/// +/// Modules control when and if information is parsed according to which +/// accessors are called. For example the object file (ObjectFile) +/// representation will only be parsed if the object file is requested using +/// the Module::GetObjectFile() is called. The debug symbols will only be +/// parsed if the symbol file (SymbolFile) is requested using the +/// Module::GetSymbolFile() method. +/// +/// The module will parse more detailed information as more queries are made. +class Module : public std::enable_shared_from_this<Module>, + public SymbolContextScope { +public: + // Static functions that can track the lifetime of module objects. This is + // handy because we might have Module objects that are in shared pointers + // that aren't in the global module list (from ModuleList). If this is the + // case we need to know about it. The modules in the global list maintained + // by these functions can be viewed using the "target modules list" command + // using the "--global" (-g for short). + static size_t GetNumberAllocatedModules(); + + static Module *GetAllocatedModuleAtIndex(size_t idx); + + static std::recursive_mutex &GetAllocationModuleCollectionMutex(); + + /// Construct with file specification and architecture. + /// + /// Clients that wish to share modules with other targets should use + /// ModuleList::GetSharedModule(). + /// + /// \param[in] file_spec + /// The file specification for the on disk representation of + /// this executable image. + /// + /// \param[in] arch + /// The architecture to set as the current architecture in + /// this module. + /// + /// \param[in] object_name + /// The name of an object in a module used to extract a module + /// within a module (.a files and modules that contain multiple + /// architectures). + /// + /// \param[in] object_offset + /// The offset within an existing module used to extract a + /// module within a module (.a files and modules that contain + /// multiple architectures). + Module( + const FileSpec &file_spec, const ArchSpec &arch, + const ConstString *object_name = nullptr, + lldb::offset_t object_offset = 0, + const llvm::sys::TimePoint<> &object_mod_time = llvm::sys::TimePoint<>()); + + Module(const ModuleSpec &module_spec); + + template <typename ObjFilePlugin, typename... Args> + static lldb::ModuleSP CreateModuleFromObjectFile(Args &&... args) { + // Must create a module and place it into a shared pointer before we can + // create an object file since it has a std::weak_ptr back to the module, + // so we need to control the creation carefully in this static function + lldb::ModuleSP module_sp(new Module()); + module_sp->m_objfile_sp = + std::make_shared<ObjFilePlugin>(module_sp, std::forward<Args>(args)...); + module_sp->m_did_load_objfile.store(true, std::memory_order_relaxed); + + // Once we get the object file, set module ArchSpec to the one we get from + // the object file. If the object file does not have an architecture, we + // consider the creation a failure. + ArchSpec arch = module_sp->m_objfile_sp->GetArchitecture(); + if (!arch) + return nullptr; + module_sp->m_arch = arch; + + // Also copy the object file's FileSpec. + module_sp->m_file = module_sp->m_objfile_sp->GetFileSpec(); + return module_sp; + } + + /// Destructor. + ~Module() override; + + bool MatchesModuleSpec(const ModuleSpec &module_ref); + + /// Set the load address for all sections in a module to be the file address + /// plus \a slide. + /// + /// Many times a module will be loaded in a target with a constant offset + /// applied to all top level sections. This function can set the load + /// address for all top level sections to be the section file address + + /// offset. + /// + /// \param[in] target + /// The target in which to apply the section load addresses. + /// + /// \param[in] value + /// if \a value_is_offset is true, then value is the offset to + /// apply to all file addresses for all top level sections in + /// the object file as each section load address is being set. + /// If \a value_is_offset is false, then "value" is the new + /// absolute base address for the image. + /// + /// \param[in] value_is_offset + /// If \b true, then \a value is an offset to apply to each + /// file address of each top level section. + /// If \b false, then \a value is the image base address that + /// will be used to rigidly slide all loadable sections. + /// + /// \param[out] changed + /// If any section load addresses were changed in \a target, + /// then \a changed will be set to \b true. Else \a changed + /// will be set to false. This allows this function to be + /// called multiple times on the same module for the same + /// target. If the module hasn't moved, then \a changed will + /// be false and no module updated notification will need to + /// be sent out. + /// + /// \return + /// /b True if any sections were successfully loaded in \a target, + /// /b false otherwise. + bool SetLoadAddress(Target &target, lldb::addr_t value, bool value_is_offset, + bool &changed); + + /// \copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) + /// + /// \see SymbolContextScope + void CalculateSymbolContext(SymbolContext *sc) override; + + lldb::ModuleSP CalculateSymbolContextModule() override; + + void + GetDescription(Stream *s, + lldb::DescriptionLevel level = lldb::eDescriptionLevelFull); + + /// Get the module path and object name. + /// + /// Modules can refer to object files. In this case the specification is + /// simple and would return the path to the file: + /// + /// "/usr/lib/foo.dylib" + /// + /// Modules can be .o files inside of a BSD archive (.a file). In this case, + /// the object specification will look like: + /// + /// "/usr/lib/foo.a(bar.o)" + /// + /// There are many places where logging wants to log this fully qualified + /// specification, so we centralize this functionality here. + /// + /// \return + /// The object path + object name if there is one. + std::string GetSpecificationDescription() const; + + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the supplied stream + /// \a s. The dumped content will be only what has been loaded or parsed up + /// to this point at which this function is called, so this is a good way to + /// see what has been parsed in a module. + /// + /// \param[in] s + /// The stream to which to dump the object description. + void Dump(Stream *s); + + /// \copydoc SymbolContextScope::DumpSymbolContext(Stream*) + /// + /// \see SymbolContextScope + void DumpSymbolContext(Stream *s) override; + + /// Find a symbol in the object file's symbol table. + /// + /// \param[in] name + /// The name of the symbol that we are looking for. + /// + /// \param[in] symbol_type + /// If set to eSymbolTypeAny, find a symbol of any type that + /// has a name that matches \a name. If set to any other valid + /// SymbolType enumeration value, then search only for + /// symbols that match \a symbol_type. + /// + /// \return + /// Returns a valid symbol pointer if a symbol was found, + /// nullptr otherwise. + const Symbol *FindFirstSymbolWithNameAndType( + ConstString name, + lldb::SymbolType symbol_type = lldb::eSymbolTypeAny); + + void FindSymbolsWithNameAndType(ConstString name, + lldb::SymbolType symbol_type, + SymbolContextList &sc_list); + + void FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, + lldb::SymbolType symbol_type, + SymbolContextList &sc_list); + + /// Find a function symbols in the object file's symbol table. + /// + /// \param[in] name + /// The name of the symbol that we are looking for. + /// + /// \param[in] name_type_mask + /// A mask that has one or more bitwise OR'ed values from the + /// lldb::FunctionNameType enumeration type that indicate what + /// kind of names we are looking for. + /// + /// \param[out] sc_list + /// A list to append any matching symbol contexts to. + void FindFunctionSymbols(ConstString name, uint32_t name_type_mask, + SymbolContextList &sc_list); + + /// Find compile units by partial or full path. + /// + /// Finds all compile units that match \a path in all of the modules and + /// returns the results in \a sc_list. + /// + /// \param[in] path + /// The name of the function we are looking for. + /// + /// \param[out] sc_list + /// A symbol context list that gets filled in with all of the + /// matches. + void FindCompileUnits(const FileSpec &path, SymbolContextList &sc_list); + + /// Find functions by name. + /// + /// If the function is an inlined function, it will have a block, + /// representing the inlined function, and the function will be the + /// containing function. If it is not inlined, then the block will be NULL. + /// + /// \param[in] name + /// The name of the compile unit we are looking for. + /// + /// \param[in] namespace_decl + /// If valid, a namespace to search in. + /// + /// \param[in] name_type_mask + /// A bit mask of bits that indicate what kind of names should + /// be used when doing the lookup. Bits include fully qualified + /// names, base names, C++ methods, or ObjC selectors. + /// See FunctionNameType for more details. + /// + /// \param[out] sc_list + /// A symbol context list that gets filled in with all of the + /// matches. + void FindFunctions(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + lldb::FunctionNameType name_type_mask, bool symbols_ok, + bool inlines_ok, SymbolContextList &sc_list); + + /// Find functions by name. + /// + /// If the function is an inlined function, it will have a block, + /// representing the inlined function, and the function will be the + /// containing function. If it is not inlined, then the block will be NULL. + /// + /// \param[in] regex + /// A regular expression to use when matching the name. + /// + /// \param[in] append + /// If \b true, any matches will be appended to \a sc_list, else + /// matches replace the contents of \a sc_list. + /// + /// \param[out] sc_list + /// A symbol context list that gets filled in with all of the + /// matches. + void FindFunctions(const RegularExpression ®ex, bool symbols_ok, + bool inlines_ok, SymbolContextList &sc_list); + + /// Find addresses by file/line + /// + /// \param[in] target_sp + /// The target the addresses are desired for. + /// + /// \param[in] file + /// Source file to locate. + /// + /// \param[in] line + /// Source line to locate. + /// + /// \param[in] function + /// Optional filter function. Addresses within this function will be + /// added to the 'local' list. All others will be added to the 'extern' + /// list. + /// + /// \param[out] output_local + /// All matching addresses within 'function' + /// + /// \param[out] output_extern + /// All matching addresses not within 'function' + void FindAddressesForLine(const lldb::TargetSP target_sp, + const FileSpec &file, uint32_t line, + Function *function, + std::vector<Address> &output_local, + std::vector<Address> &output_extern); + + /// Find global and static variables by name. + /// + /// \param[in] name + /// The name of the global or static variable we are looking + /// for. + /// + /// \param[in] parent_decl_ctx + /// If valid, a decl context that results must exist within + /// + /// \param[in] max_matches + /// Allow the number of matches to be limited to \a + /// max_matches. Specify UINT32_MAX to get all possible matches. + /// + /// \param[in] variable_list + /// A list of variables that gets the matches appended to. + /// + void FindGlobalVariables(ConstString name, + const CompilerDeclContext *parent_decl_ctx, + size_t max_matches, VariableList &variable_list); + + /// Find global and static variables by regular expression. + /// + /// \param[in] regex + /// A regular expression to use when matching the name. + /// + /// \param[in] max_matches + /// Allow the number of matches to be limited to \a + /// max_matches. Specify UINT32_MAX to get all possible matches. + /// + /// \param[in] variable_list + /// A list of variables that gets the matches appended to. + /// + void FindGlobalVariables(const RegularExpression ®ex, size_t max_matches, + VariableList &variable_list); + + /// Find types by name. + /// + /// Type lookups in modules go through the SymbolFile. The SymbolFile needs to + /// be able to lookup types by basename and not the fully qualified typename. + /// This allows the type accelerator tables to stay small, even with heavily + /// templatized C++. The type search will then narrow down the search + /// results. If "exact_match" is true, then the type search will only match + /// exact type name matches. If "exact_match" is false, the type will match + /// as long as the base typename matches and as long as any immediate + /// containing namespaces/class scopes that are specified match. So to + /// search for a type "d" in "b::c", the name "b::c::d" can be specified and + /// it will match any class/namespace "b" which contains a class/namespace + /// "c" which contains type "d". We do this to allow users to not always + /// have to specify complete scoping on all expressions, but it also allows + /// for exact matching when required. + /// + /// \param[in] type_name + /// The name of the type we are looking for that is a fully + /// or partially qualified type name. + /// + /// \param[in] exact_match + /// If \b true, \a type_name is fully qualified and must match + /// exactly. If \b false, \a type_name is a partially qualified + /// name where the leading namespaces or classes can be + /// omitted to make finding types that a user may type + /// easier. + /// + /// \param[out] type_list + /// A type list gets populated with any matches. + /// + void + FindTypes(ConstString type_name, bool exact_match, size_t max_matches, + llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, + TypeList &types); + + /// Find types by name. + /// + /// This behaves like the other FindTypes method but allows to + /// specify a DeclContext and a language for the type being searched + /// for. + void FindTypes(llvm::ArrayRef<CompilerContext> pattern, LanguageSet languages, + TypeMap &types); + + lldb::TypeSP FindFirstType(const SymbolContext &sc, + ConstString type_name, bool exact_match); + + /// Find types by name that are in a namespace. This function is used by the + /// expression parser when searches need to happen in an exact namespace + /// scope. + /// + /// \param[in] type_name + /// The name of a type within a namespace that should not include + /// any qualifying namespaces (just a type basename). + /// + /// \param[in] namespace_decl + /// The namespace declaration that this type must exist in. + /// + /// \param[out] type_list + /// A type list gets populated with any matches. + /// + void FindTypesInNamespace(ConstString type_name, + const CompilerDeclContext *parent_decl_ctx, + size_t max_matches, TypeList &type_list); + + /// Get const accessor for the module architecture. + /// + /// \return + /// A const reference to the architecture object. + const ArchSpec &GetArchitecture() const; + + /// Get const accessor for the module file specification. + /// + /// This function returns the file for the module on the host system that is + /// running LLDB. This can differ from the path on the platform since we + /// might be doing remote debugging. + /// + /// \return + /// A const reference to the file specification object. + const FileSpec &GetFileSpec() const { return m_file; } + + /// Get accessor for the module platform file specification. + /// + /// Platform file refers to the path of the module as it is known on the + /// remote system on which it is being debugged. For local debugging this is + /// always the same as Module::GetFileSpec(). But remote debugging might + /// mention a file "/usr/lib/liba.dylib" which might be locally downloaded + /// and cached. In this case the platform file could be something like: + /// "/tmp/lldb/platform-cache/remote.host.computer/usr/lib/liba.dylib" The + /// file could also be cached in a local developer kit directory. + /// + /// \return + /// A const reference to the file specification object. + const FileSpec &GetPlatformFileSpec() const { + if (m_platform_file) + return m_platform_file; + return m_file; + } + + void SetPlatformFileSpec(const FileSpec &file) { m_platform_file = file; } + + const FileSpec &GetRemoteInstallFileSpec() const { + return m_remote_install_file; + } + + void SetRemoteInstallFileSpec(const FileSpec &file) { + m_remote_install_file = file; + } + + const FileSpec &GetSymbolFileFileSpec() const { return m_symfile_spec; } + + void PreloadSymbols(); + + void SetSymbolFileFileSpec(const FileSpec &file); + + const llvm::sys::TimePoint<> &GetModificationTime() const { + return m_mod_time; + } + + const llvm::sys::TimePoint<> &GetObjectModificationTime() const { + return m_object_mod_time; + } + + void SetObjectModificationTime(const llvm::sys::TimePoint<> &mod_time) { + m_mod_time = mod_time; + } + + /// Tells whether this module is capable of being the main executable for a + /// process. + /// + /// \return + /// \b true if it is, \b false otherwise. + bool IsExecutable(); + + /// Tells whether this module has been loaded in the target passed in. This + /// call doesn't distinguish between whether the module is loaded by the + /// dynamic loader, or by a "target module add" type call. + /// + /// \param[in] target + /// The target to check whether this is loaded in. + /// + /// \return + /// \b true if it is, \b false otherwise. + bool IsLoadedInTarget(Target *target); + + bool LoadScriptingResourceInTarget(Target *target, Status &error, + Stream *feedback_stream = nullptr); + + /// Get the number of compile units for this module. + /// + /// \return + /// The number of compile units that the symbol vendor plug-in + /// finds. + size_t GetNumCompileUnits(); + + lldb::CompUnitSP GetCompileUnitAtIndex(size_t idx); + + ConstString GetObjectName() const; + + uint64_t GetObjectOffset() const { return m_object_offset; } + + /// Get the object file representation for the current architecture. + /// + /// If the object file has not been located or parsed yet, this function + /// will find the best ObjectFile plug-in that can parse Module::m_file. + /// + /// \return + /// If Module::m_file does not exist, or no plug-in was found + /// that can parse the file, or the object file doesn't contain + /// the current architecture in Module::m_arch, nullptr will be + /// returned, else a valid object file interface will be + /// returned. The returned pointer is owned by this object and + /// remains valid as long as the object is around. + virtual ObjectFile *GetObjectFile(); + + /// Get the unified section list for the module. This is the section list + /// created by the module's object file and any debug info and symbol files + /// created by the symbol vendor. + /// + /// If the symbol vendor has not been loaded yet, this function will return + /// the section list for the object file. + /// + /// \return + /// Unified module section list. + virtual SectionList *GetSectionList(); + + /// Notify the module that the file addresses for the Sections have been + /// updated. + /// + /// If the Section file addresses for a module are updated, this method + /// should be called. Any parts of the module, object file, or symbol file + /// that has cached those file addresses must invalidate or update its + /// cache. + virtual void SectionFileAddressesChanged(); + + /// Returns a reference to the UnwindTable for this Module + /// + /// The UnwindTable contains FuncUnwinders objects for any function in this + /// Module. If a FuncUnwinders object hasn't been created yet (i.e. the + /// function has yet to be unwound in a stack walk), it will be created when + /// requested. Specifically, we do not create FuncUnwinders objects for + /// functions until they are needed. + /// + /// \return + /// Returns the unwind table for this module. If this object has no + /// associated object file, an empty UnwindTable is returned. + UnwindTable &GetUnwindTable(); + + llvm::VersionTuple GetVersion(); + + /// Load an object file from memory. + /// + /// If available, the size of the object file in memory may be passed to + /// avoid additional round trips to process memory. If the size is not + /// provided, a default value is used. This value should be large enough to + /// enable the ObjectFile plugins to read the header of the object file + /// without going back to the process. + /// + /// \return + /// The object file loaded from memory or nullptr, if the operation + /// failed (see the `error` for more information in that case). + ObjectFile *GetMemoryObjectFile(const lldb::ProcessSP &process_sp, + lldb::addr_t header_addr, Status &error, + size_t size_to_read = 512); + + /// Get the module's symbol file + /// + /// If the symbol file has already been loaded, this function returns it. All + /// arguments are ignored. If the symbol file has not been located yet, and + /// the can_create argument is false, the function returns nullptr. If + /// can_create is true, this function will find the best SymbolFile plug-in + /// that can use the current object file. feedback_strm, if not null, is used + /// to report the details of the search process. + virtual SymbolFile *GetSymbolFile(bool can_create = true, + Stream *feedback_strm = nullptr); + + Symtab *GetSymtab(); + + /// Get a reference to the UUID value contained in this object. + /// + /// If the executable image file doesn't not have a UUID value built into + /// the file format, an MD5 checksum of the entire file, or slice of the + /// file for the current architecture should be used. + /// + /// \return + /// A const pointer to the internal copy of the UUID value in + /// this module if this module has a valid UUID value, NULL + /// otherwise. + const lldb_private::UUID &GetUUID(); + + /// A debugging function that will cause everything in a module to + /// be parsed. + /// + /// All compile units will be parsed, along with all globals and static + /// variables and all functions for those compile units. All types, scopes, + /// local variables, static variables, global variables, and line tables + /// will be parsed. This can be used prior to dumping a module to see a + /// complete list of the resulting debug information that gets parsed, or as + /// a debug function to ensure that the module can consume all of the debug + /// data the symbol vendor provides. + void ParseAllDebugSymbols(); + + bool ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr); + + /// Resolve the symbol context for the given address. + /// + /// Tries to resolve the matching symbol context based on a lookup from the + /// current symbol vendor. If the lazy lookup fails, an attempt is made to + /// parse the eh_frame section to handle stripped symbols. If this fails, + /// an attempt is made to resolve the symbol to the previous address to + /// handle the case of a function with a tail call. + /// + /// Use properties of the modified SymbolContext to inspect any resolved + /// target, module, compilation unit, symbol, function, function block or + /// line entry. Use the return value to determine which of these properties + /// have been modified. + /// + /// \param[in] so_addr + /// A load address to resolve. + /// + /// \param[in] resolve_scope + /// The scope that should be resolved (see SymbolContext::Scope). + /// A combination of flags from the enumeration SymbolContextItem + /// requesting a resolution depth. Note that the flags that are + /// actually resolved may be a superset of the requested flags. + /// For instance, eSymbolContextSymbol requires resolution of + /// eSymbolContextModule, and eSymbolContextFunction requires + /// eSymbolContextSymbol. + /// + /// \param[out] sc + /// The SymbolContext that is modified based on symbol resolution. + /// + /// \param[in] resolve_tail_call_address + /// Determines if so_addr should resolve to a symbol in the case + /// of a function whose last instruction is a call. In this case, + /// the PC can be one past the address range of the function. + /// + /// \return + /// The scope that has been resolved (see SymbolContext::Scope). + /// + /// \see SymbolContext::Scope + uint32_t ResolveSymbolContextForAddress( + const Address &so_addr, lldb::SymbolContextItem resolve_scope, + SymbolContext &sc, bool resolve_tail_call_address = false); + + /// Resolve items in the symbol context for a given file and line. + /// + /// Tries to resolve \a file_path and \a line to a list of matching symbol + /// contexts. + /// + /// The line table entries contains addresses that can be used to further + /// resolve the values in each match: the function, block, symbol. Care + /// should be taken to minimize the amount of information that is requested + /// to only what is needed -- typically the module, compile unit, line table + /// and line table entry are sufficient. + /// + /// \param[in] file_path + /// A path to a source file to match. If \a file_path does not + /// specify a directory, then this query will match all files + /// whose base filename matches. If \a file_path does specify + /// a directory, the fullpath to the file must match. + /// + /// \param[in] line + /// The source line to match, or zero if just the compile unit + /// should be resolved. + /// + /// \param[in] check_inlines + /// Check for inline file and line number matches. This option + /// should be used sparingly as it will cause all line tables + /// for every compile unit to be parsed and searched for + /// matching inline file entries. + /// + /// \param[in] resolve_scope + /// The scope that should be resolved (see + /// SymbolContext::Scope). + /// + /// \param[out] sc_list + /// A symbol context list that gets matching symbols contexts + /// appended to. + /// + /// \return + /// The number of matches that were added to \a sc_list. + /// + /// \see SymbolContext::Scope + uint32_t ResolveSymbolContextForFilePath( + const char *file_path, uint32_t line, bool check_inlines, + lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list); + + /// Resolve items in the symbol context for a given file and line. + /// + /// Tries to resolve \a file_spec and \a line to a list of matching symbol + /// contexts. + /// + /// The line table entries contains addresses that can be used to further + /// resolve the values in each match: the function, block, symbol. Care + /// should be taken to minimize the amount of information that is requested + /// to only what is needed -- typically the module, compile unit, line table + /// and line table entry are sufficient. + /// + /// \param[in] file_spec + /// A file spec to a source file to match. If \a file_path does + /// not specify a directory, then this query will match all + /// files whose base filename matches. If \a file_path does + /// specify a directory, the fullpath to the file must match. + /// + /// \param[in] line + /// The source line to match, or zero if just the compile unit + /// should be resolved. + /// + /// \param[in] check_inlines + /// Check for inline file and line number matches. This option + /// should be used sparingly as it will cause all line tables + /// for every compile unit to be parsed and searched for + /// matching inline file entries. + /// + /// \param[in] resolve_scope + /// The scope that should be resolved (see + /// SymbolContext::Scope). + /// + /// \param[out] sc_list + /// A symbol context list that gets filled in with all of the + /// matches. + /// + /// \return + /// A integer that contains SymbolContext::Scope bits set for + /// each item that was successfully resolved. + /// + /// \see SymbolContext::Scope + uint32_t ResolveSymbolContextsForFileSpec( + const FileSpec &file_spec, uint32_t line, bool check_inlines, + lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list); + + void SetFileSpecAndObjectName(const FileSpec &file, + ConstString object_name); + + bool GetIsDynamicLinkEditor(); + + llvm::Expected<TypeSystem &> + GetTypeSystemForLanguage(lldb::LanguageType language); + + // Special error functions that can do printf style formatting that will + // prepend the message with something appropriate for this module (like the + // architecture, path and object name (if any)). This centralizes code so + // that everyone doesn't need to format their error and log messages on their + // own and keeps the output a bit more consistent. + void LogMessage(Log *log, const char *format, ...) + __attribute__((format(printf, 3, 4))); + + void LogMessageVerboseBacktrace(Log *log, const char *format, ...) + __attribute__((format(printf, 3, 4))); + + void ReportWarning(const char *format, ...) + __attribute__((format(printf, 2, 3))); + + void ReportError(const char *format, ...) + __attribute__((format(printf, 2, 3))); + + // Only report an error once when the module is first detected to be modified + // so we don't spam the console with many messages. + void ReportErrorIfModifyDetected(const char *format, ...) + __attribute__((format(printf, 2, 3))); + + // Return true if the file backing this module has changed since the module + // was originally created since we saved the initial file modification time + // when the module first gets created. + bool FileHasChanged() const; + + // SymbolFile and ObjectFile member objects should lock the + // module mutex to avoid deadlocks. + std::recursive_mutex &GetMutex() const { return m_mutex; } + + PathMappingList &GetSourceMappingList() { return m_source_mappings; } + + const PathMappingList &GetSourceMappingList() const { + return m_source_mappings; + } + + /// Finds a source file given a file spec using the module source path + /// remappings (if any). + /// + /// Tries to resolve \a orig_spec by checking the module source path + /// remappings. It makes sure the file exists, so this call can be expensive + /// if the remappings are on a network file system, so use this function + /// sparingly (not in a tight debug info parsing loop). + /// + /// \param[in] orig_spec + /// The original source file path to try and remap. + /// + /// \param[out] new_spec + /// The newly remapped filespec that is guaranteed to exist. + /// + /// \return + /// /b true if \a orig_spec was successfully located and + /// \a new_spec is filled in with an existing file spec, + /// \b false otherwise. + bool FindSourceFile(const FileSpec &orig_spec, FileSpec &new_spec) const; + + /// Remaps a source file given \a path into \a new_path. + /// + /// Remaps \a path if any source remappings match. This function does NOT + /// stat the file system so it can be used in tight loops where debug info + /// is being parsed. + /// + /// \param[in] path + /// The original source file path to try and remap. + /// + /// \param[out] new_path + /// The newly remapped filespec that is may or may not exist. + /// + /// \return + /// /b true if \a path was successfully located and \a new_path + /// is filled in with a new source path, \b false otherwise. + bool RemapSourceFile(llvm::StringRef path, std::string &new_path) const; + bool RemapSourceFile(const char *, std::string &) const = delete; + + /// Update the ArchSpec to a more specific variant. + bool MergeArchitecture(const ArchSpec &arch_spec); + + /// \class LookupInfo Module.h "lldb/Core/Module.h" + /// A class that encapsulates name lookup information. + /// + /// Users can type a wide variety of partial names when setting breakpoints + /// by name or when looking for functions by name. The SymbolFile object is + /// only required to implement name lookup for function basenames and for + /// fully mangled names. This means if the user types in a partial name, we + /// must reduce this to a name lookup that will work with all SymbolFile + /// objects. So we might reduce a name lookup to look for a basename, and then + /// prune out any results that don't match. + /// + /// The "m_name" member variable represents the name as it was typed by the + /// user. "m_lookup_name" will be the name we actually search for through + /// the symbol or objects files. Lanaguage is included in case we need to + /// filter results by language at a later date. The "m_name_type_mask" + /// member variable tells us what kinds of names we are looking for and can + /// help us prune out unwanted results. + /// + /// Function lookups are done in Module.cpp, ModuleList.cpp and in + /// BreakpointResolverName.cpp and they all now use this class to do lookups + /// correctly. + class LookupInfo { + public: + LookupInfo() + : m_name(), m_lookup_name(), m_language(lldb::eLanguageTypeUnknown), + m_name_type_mask(lldb::eFunctionNameTypeNone), + m_match_name_after_lookup(false) {} + + LookupInfo(ConstString name, lldb::FunctionNameType name_type_mask, + lldb::LanguageType language); + + ConstString GetName() const { return m_name; } + + void SetName(ConstString name) { m_name = name; } + + ConstString GetLookupName() const { return m_lookup_name; } + + void SetLookupName(ConstString name) { m_lookup_name = name; } + + lldb::FunctionNameType GetNameTypeMask() const { return m_name_type_mask; } + + void SetNameTypeMask(lldb::FunctionNameType mask) { + m_name_type_mask = mask; + } + + void Prune(SymbolContextList &sc_list, size_t start_idx) const; + + protected: + /// What the user originally typed + ConstString m_name; + + /// The actual name will lookup when calling in the object or symbol file + ConstString m_lookup_name; + + /// Limit matches to only be for this language + lldb::LanguageType m_language; + + /// One or more bits from lldb::FunctionNameType that indicate what kind of + /// names we are looking for + lldb::FunctionNameType m_name_type_mask; + + ///< If \b true, then demangled names that match will need to contain + ///< "m_name" in order to be considered a match + bool m_match_name_after_lookup; + }; + +protected: + // Member Variables + mutable std::recursive_mutex m_mutex; ///< A mutex to keep this object happy + ///in multi-threaded environments. + + /// The modification time for this module when it was created. + llvm::sys::TimePoint<> m_mod_time; + + ArchSpec m_arch; ///< The architecture for this module. + UUID m_uuid; ///< Each module is assumed to have a unique identifier to help + ///match it up to debug symbols. + FileSpec m_file; ///< The file representation on disk for this module (if + ///there is one). + FileSpec m_platform_file; ///< The path to the module on the platform on which + ///it is being debugged + FileSpec m_remote_install_file; ///< If set when debugging on remote + ///platforms, this module will be installed at + ///this location + FileSpec m_symfile_spec; ///< If this path is valid, then this is the file + ///that _will_ be used as the symbol file for this + ///module + ConstString m_object_name; ///< The name an object within this module that is + ///selected, or empty of the module is represented + ///by \a m_file. + uint64_t m_object_offset; + llvm::sys::TimePoint<> m_object_mod_time; + lldb::ObjectFileSP m_objfile_sp; ///< A shared pointer to the object file + ///parser for this module as it may or may + ///not be shared with the SymbolFile + llvm::Optional<UnwindTable> m_unwind_table; ///< Table of FuncUnwinders + /// objects created for this + /// Module's functions + lldb::SymbolVendorUP + m_symfile_up; ///< A pointer to the symbol vendor for this module. + std::vector<lldb::SymbolVendorUP> + m_old_symfiles; ///< If anyone calls Module::SetSymbolFileFileSpec() and + ///changes the symbol file, + ///< we need to keep all old symbol files around in case anyone has type + ///references to them + TypeSystemMap m_type_system_map; ///< A map of any type systems associated + ///with this module + PathMappingList m_source_mappings; ///< Module specific source remappings for + ///when you have debug info for a module + ///that doesn't match where the sources + ///currently are + lldb::SectionListUP m_sections_up; ///< Unified section list for module that + /// is used by the ObjectFile and and + /// ObjectFile instances for the debug info + + std::atomic<bool> m_did_load_objfile{false}; + std::atomic<bool> m_did_load_symfile{false}; + std::atomic<bool> m_did_set_uuid{false}; + mutable bool m_file_has_changed : 1, + m_first_file_changed_log : 1; /// See if the module was modified after it + /// was initially opened. + + /// Resolve a file or load virtual address. + /// + /// Tries to resolve \a vm_addr as a file address (if \a + /// vm_addr_is_file_addr is true) or as a load address if \a + /// vm_addr_is_file_addr is false) in the symbol vendor. \a resolve_scope + /// indicates what clients wish to resolve and can be used to limit the + /// scope of what is parsed. + /// + /// \param[in] vm_addr + /// The load virtual address to resolve. + /// + /// \param[in] vm_addr_is_file_addr + /// If \b true, \a vm_addr is a file address, else \a vm_addr + /// if a load address. + /// + /// \param[in] resolve_scope + /// The scope that should be resolved (see + /// SymbolContext::Scope). + /// + /// \param[out] so_addr + /// The section offset based address that got resolved if + /// any bits are returned. + /// + /// \param[out] sc + // The symbol context that has objects filled in. Each bit + /// in the \a resolve_scope pertains to a member in the \a sc. + /// + /// \return + /// A integer that contains SymbolContext::Scope bits set for + /// each item that was successfully resolved. + /// + /// \see SymbolContext::Scope + uint32_t ResolveSymbolContextForAddress(lldb::addr_t vm_addr, + bool vm_addr_is_file_addr, + lldb::SymbolContextItem resolve_scope, + Address &so_addr, SymbolContext &sc); + + void SymbolIndicesToSymbolContextList(Symtab *symtab, + std::vector<uint32_t> &symbol_indexes, + SymbolContextList &sc_list); + + bool SetArchitecture(const ArchSpec &new_arch); + + void SetUUID(const lldb_private::UUID &uuid); + + SectionList *GetUnifiedSectionList(); + + friend class ModuleList; + friend class ObjectFile; + friend class SymbolFile; + +private: + Module(); // Only used internally by CreateJITModule () + + void FindTypes_Impl( + ConstString name, const CompilerDeclContext *parent_decl_ctx, + size_t max_matches, + llvm::DenseSet<lldb_private::SymbolFile *> &searched_symbol_files, + TypeMap &types); + + DISALLOW_COPY_AND_ASSIGN(Module); +}; + +} // namespace lldb_private + +#endif // liblldb_Module_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ModuleChild.h b/contrib/llvm-project/lldb/include/lldb/Core/ModuleChild.h new file mode 100644 index 000000000000..8a81c1a6cf8a --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ModuleChild.h @@ -0,0 +1,62 @@ +//===-- ModuleChild.h -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ModuleChild_h_ +#define liblldb_ModuleChild_h_ + +#include "lldb/lldb-forward.h" + +namespace lldb_private { + +/// \class ModuleChild ModuleChild.h "lldb/Core/ModuleChild.h" +/// A mix in class that contains a pointer back to the module +/// that owns the object which inherits from it. +class ModuleChild { +public: + /// Construct with owning module. + /// + /// \param[in] module + /// The module that owns the object that inherits from this + /// class. + ModuleChild(const lldb::ModuleSP &module_sp); + + /// Destructor. + ~ModuleChild(); + + /// Assignment operator. + /// + /// \param[in] rhs + /// A const ModuleChild class reference to copy. + /// + /// \return + /// A const reference to this object. + const ModuleChild &operator=(const ModuleChild &rhs); + + /// Get const accessor for the module pointer. + /// + /// \return + /// A const pointer to the module that owns the object that + /// inherits from this class. + lldb::ModuleSP GetModule() const; + + /// Set accessor for the module pointer. + /// + /// \param[in] module + /// A new module that owns the object that inherits from this + /// class. + void SetModule(const lldb::ModuleSP &module_sp); + +protected: + // Member variables + lldb::ModuleWP m_module_wp; ///< The Module that owns the object that inherits + ///< from this class. +}; + +} // namespace lldb_private + +#endif // liblldb_ModuleChild_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ModuleList.h b/contrib/llvm-project/lldb/include/lldb/Core/ModuleList.h new file mode 100644 index 000000000000..e21655551b61 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ModuleList.h @@ -0,0 +1,519 @@ +//===-- ModuleList.h --------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ModuleList_h_ +#define liblldb_ModuleList_h_ + +#include "lldb/Core/Address.h" +#include "lldb/Core/ModuleSpec.h" +#include "lldb/Core/UserSettingsController.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Iterable.h" +#include "lldb/Utility/Status.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-types.h" + +#include "llvm/ADT/DenseSet.h" + +#include <functional> +#include <list> +#include <mutex> +#include <vector> + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class ConstString; +class FileSpecList; +class Function; +class Log; +class Module; +class RegularExpression; +class Stream; +class SymbolContext; +class SymbolContextList; +class SymbolFile; +class Target; +class TypeList; +class UUID; +class VariableList; + +class ModuleListProperties : public Properties { +public: + ModuleListProperties(); + + FileSpec GetClangModulesCachePath() const; + bool SetClangModulesCachePath(llvm::StringRef path); + bool GetEnableExternalLookup() const; + bool SetEnableExternalLookup(bool new_value); +}; + +/// \class ModuleList ModuleList.h "lldb/Core/ModuleList.h" +/// A collection class for Module objects. +/// +/// Modules in the module collection class are stored as reference counted +/// shared pointers to Module objects. +class ModuleList { +public: + class Notifier { + public: + virtual ~Notifier() = default; + + virtual void NotifyModuleAdded(const ModuleList &module_list, + const lldb::ModuleSP &module_sp) = 0; + virtual void NotifyModuleRemoved(const ModuleList &module_list, + const lldb::ModuleSP &module_sp) = 0; + virtual void NotifyModuleUpdated(const ModuleList &module_list, + const lldb::ModuleSP &old_module_sp, + const lldb::ModuleSP &new_module_sp) = 0; + virtual void NotifyWillClearList(const ModuleList &module_list) = 0; + + virtual void NotifyModulesRemoved(lldb_private::ModuleList &module_list) = 0; + }; + + /// Default constructor. + /// + /// Creates an empty list of Module objects. + ModuleList(); + + /// Copy Constructor. + /// + /// Creates a new module list object with a copy of the modules from \a rhs. + /// + /// \param[in] rhs + /// Another module list object. + ModuleList(const ModuleList &rhs); + + ModuleList(ModuleList::Notifier *notifier); + + /// Destructor. + ~ModuleList(); + + /// Assignment operator. + /// + /// Copies the module list from \a rhs into this list. + /// + /// \param[in] rhs + /// Another module list object. + /// + /// \return + /// A const reference to this object. + const ModuleList &operator=(const ModuleList &rhs); + + /// Append a module to the module list. + /// + /// \param[in] module_sp + /// A shared pointer to a module to add to this collection. + /// + /// \param[in] notify + /// If true, and a notifier function is set, the notifier function + /// will be called. Defaults to true. + /// + /// When this ModuleList is the Target's ModuleList, the notifier + /// function is Target::ModulesDidLoad -- the call to + /// ModulesDidLoad may be deferred when adding multiple Modules + /// to the Target, but it must be called at the end, + /// before resuming execution. + void Append(const lldb::ModuleSP &module_sp, bool notify = true); + + /// Append a module to the module list and remove any equivalent modules. + /// Equivalent modules are ones whose file, platform file and architecture + /// matches. + /// + /// Replaces the module to the collection. + /// + /// \param[in] module_sp + /// A shared pointer to a module to replace in this collection. + void ReplaceEquivalent(const lldb::ModuleSP &module_sp); + + /// Append a module to the module list, if it is not already there. + /// + /// \param[in] module_sp + /// + /// \param[in] notify + /// If true, and a notifier function is set, the notifier function + /// will be called. Defaults to true. + /// + /// When this ModuleList is the Target's ModuleList, the notifier + /// function is Target::ModulesDidLoad -- the call to + /// ModulesDidLoad may be deferred when adding multiple Modules + /// to the Target, but it must be called at the end, + /// before resuming execution. + bool AppendIfNeeded(const lldb::ModuleSP &module_sp, bool notify = true); + + void Append(const ModuleList &module_list); + + bool AppendIfNeeded(const ModuleList &module_list); + + bool ReplaceModule(const lldb::ModuleSP &old_module_sp, + const lldb::ModuleSP &new_module_sp); + + /// Clear the object's state. + /// + /// Clears the list of modules and releases a reference to each module + /// object and if the reference count goes to zero, the module will be + /// deleted. + void Clear(); + + /// Clear the object's state. + /// + /// Clears the list of modules and releases a reference to each module + /// object and if the reference count goes to zero, the module will be + /// deleted. Also release all memory that might be held by any collection + /// classes (like std::vector) + void Destroy(); + + /// Dump the description of each module contained in this list. + /// + /// Dump the description of each module contained in this list to the + /// supplied stream \a s. + /// + /// \param[in] s + /// The stream to which to dump the object description. + /// + /// \see Module::Dump(Stream *) const + void Dump(Stream *s) const; + + void LogUUIDAndPaths(Log *log, const char *prefix_cstr); + + std::recursive_mutex &GetMutex() const { return m_modules_mutex; } + + size_t GetIndexForModule(const Module *module) const; + + /// Get the module shared pointer for the module at index \a idx. + /// + /// \param[in] idx + /// An index into this module collection. + /// + /// \return + /// A shared pointer to a Module which can contain NULL if + /// \a idx is out of range. + /// + /// \see ModuleList::GetSize() + lldb::ModuleSP GetModuleAtIndex(size_t idx) const; + + /// Get the module shared pointer for the module at index \a idx without + /// acquiring the ModuleList mutex. This MUST already have been acquired + /// with ModuleList::GetMutex and locked for this call to be safe. + /// + /// \param[in] idx + /// An index into this module collection. + /// + /// \return + /// A shared pointer to a Module which can contain NULL if + /// \a idx is out of range. + /// + /// \see ModuleList::GetSize() + lldb::ModuleSP GetModuleAtIndexUnlocked(size_t idx) const; + + /// Get the module pointer for the module at index \a idx. + /// + /// \param[in] idx + /// An index into this module collection. + /// + /// \return + /// A pointer to a Module which can by nullptr if \a idx is out + /// of range. + /// + /// \see ModuleList::GetSize() + Module *GetModulePointerAtIndex(size_t idx) const; + + /// Get the module pointer for the module at index \a idx without acquiring + /// the ModuleList mutex. This MUST already have been acquired with + /// ModuleList::GetMutex and locked for this call to be safe. + /// + /// \param[in] idx + /// An index into this module collection. + /// + /// \return + /// A pointer to a Module which can by nullptr if \a idx is out + /// of range. + /// + /// \see ModuleList::GetSize() + Module *GetModulePointerAtIndexUnlocked(size_t idx) const; + + /// Find compile units by partial or full path. + /// + /// Finds all compile units that match \a path in all of the modules and + /// returns the results in \a sc_list. + /// + /// \param[in] path + /// The name of the compile unit we are looking for. + /// + /// \param[out] sc_list + /// A symbol context list that gets filled in with all of the + /// matches. + void FindCompileUnits(const FileSpec &path, SymbolContextList &sc_list) const; + + /// \see Module::FindFunctions () + void FindFunctions(ConstString name, lldb::FunctionNameType name_type_mask, + bool include_symbols, bool include_inlines, + SymbolContextList &sc_list) const; + + /// \see Module::FindFunctionSymbols () + void FindFunctionSymbols(ConstString name, + lldb::FunctionNameType name_type_mask, + SymbolContextList &sc_list); + + /// \see Module::FindFunctions () + void FindFunctions(const RegularExpression &name, bool include_symbols, + bool include_inlines, SymbolContextList &sc_list); + + /// Find global and static variables by name. + /// + /// \param[in] name + /// The name of the global or static variable we are looking + /// for. + /// + /// \param[in] max_matches + /// Allow the number of matches to be limited to \a + /// max_matches. Specify UINT32_MAX to get all possible matches. + /// + /// \param[in] variable_list + /// A list of variables that gets the matches appended to. + void FindGlobalVariables(ConstString name, size_t max_matches, + VariableList &variable_list) const; + + /// Find global and static variables by regular expression. + /// + /// \param[in] regex + /// A regular expression to use when matching the name. + /// + /// \param[in] max_matches + /// Allow the number of matches to be limited to \a + /// max_matches. Specify UINT32_MAX to get all possible matches. + /// + /// \param[in] variable_list + /// A list of variables that gets the matches appended to. + void FindGlobalVariables(const RegularExpression ®ex, size_t max_matches, + VariableList &variable_list) const; + + /// Finds the first module whose file specification matches \a file_spec. + /// + /// \param[in] file_spec_ptr + /// A file specification object to match against the Module's + /// file specifications. If \a file_spec does not have + /// directory information, matches will occur by matching only + /// the basename of any modules in this list. If this value is + /// NULL, then file specifications won't be compared when + /// searching for matching modules. + /// + /// \param[in] arch_ptr + /// The architecture to search for if non-NULL. If this value + /// is NULL no architecture matching will be performed. + /// + /// \param[in] uuid_ptr + /// The uuid to search for if non-NULL. If this value is NULL + /// no uuid matching will be performed. + /// + /// \param[in] object_name + /// An optional object name that must match as well. This value + /// can be NULL. + /// + /// \param[out] matching_module_list + /// A module list that gets filled in with any modules that + /// match the search criteria. + void FindModules(const ModuleSpec &module_spec, + ModuleList &matching_module_list) const; + + lldb::ModuleSP FindModule(const Module *module_ptr) const; + + // Find a module by UUID + // + // The UUID value for a module is extracted from the ObjectFile and is the + // MD5 checksum, or a smarter object file equivalent, so finding modules by + // UUID values is very efficient and accurate. + lldb::ModuleSP FindModule(const UUID &uuid) const; + + lldb::ModuleSP FindFirstModule(const ModuleSpec &module_spec) const; + + void FindSymbolsWithNameAndType(ConstString name, + lldb::SymbolType symbol_type, + SymbolContextList &sc_list) const; + + void FindSymbolsMatchingRegExAndType(const RegularExpression ®ex, + lldb::SymbolType symbol_type, + SymbolContextList &sc_list) const; + + /// Find types by name. + /// + /// \param[in] search_first + /// If non-null, this module will be searched before any other + /// modules. + /// + /// \param[in] name + /// The name of the type we are looking for. + /// + /// \param[in] append + /// If \b true, any matches will be appended to \a + /// variable_list, else matches replace the contents of + /// \a variable_list. + /// + /// \param[in] max_matches + /// Allow the number of matches to be limited to \a + /// max_matches. Specify UINT32_MAX to get all possible matches. + /// + /// \param[in] encoding + /// Limit the search to specific types, or get all types if + /// set to Type::invalid. + /// + /// \param[in] udt_name + /// If the encoding is a user defined type, specify the name + /// of the user defined type ("struct", "union", "class", etc). + /// + /// \param[out] type_list + /// A type list gets populated with any matches. + /// + void FindTypes(Module *search_first, ConstString name, + bool name_is_fully_qualified, size_t max_matches, + llvm::DenseSet<SymbolFile *> &searched_symbol_files, + TypeList &types) const; + + bool FindSourceFile(const FileSpec &orig_spec, FileSpec &new_spec) const; + + /// Find addresses by file/line + /// + /// \param[in] target_sp + /// The target the addresses are desired for. + /// + /// \param[in] file + /// Source file to locate. + /// + /// \param[in] line + /// Source line to locate. + /// + /// \param[in] function + /// Optional filter function. Addresses within this function will be + /// added to the 'local' list. All others will be added to the 'extern' + /// list. + /// + /// \param[out] output_local + /// All matching addresses within 'function' + /// + /// \param[out] output_extern + /// All matching addresses not within 'function' + void FindAddressesForLine(const lldb::TargetSP target_sp, + const FileSpec &file, uint32_t line, + Function *function, + std::vector<Address> &output_local, + std::vector<Address> &output_extern); + + /// Remove a module from the module list. + /// + /// \param[in] module_sp + /// A shared pointer to a module to remove from this collection. + /// + /// \param[in] notify + /// If true, and a notifier function is set, the notifier function + /// will be called. Defaults to true. + /// + /// When this ModuleList is the Target's ModuleList, the notifier + /// function is Target::ModulesDidUnload -- the call to + /// ModulesDidUnload may be deferred when removing multiple Modules + /// from the Target, but it must be called at the end, + /// before resuming execution. + bool Remove(const lldb::ModuleSP &module_sp, bool notify = true); + + size_t Remove(ModuleList &module_list); + + bool RemoveIfOrphaned(const Module *module_ptr); + + size_t RemoveOrphans(bool mandatory); + + bool ResolveFileAddress(lldb::addr_t vm_addr, Address &so_addr) const; + + /// \copydoc Module::ResolveSymbolContextForAddress (const Address + /// &,uint32_t,SymbolContext&) + uint32_t ResolveSymbolContextForAddress(const Address &so_addr, + lldb::SymbolContextItem resolve_scope, + SymbolContext &sc) const; + + /// \copydoc Module::ResolveSymbolContextForFilePath (const char + /// *,uint32_t,bool,uint32_t,SymbolContextList&) + uint32_t ResolveSymbolContextForFilePath( + const char *file_path, uint32_t line, bool check_inlines, + lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) const; + + /// \copydoc Module::ResolveSymbolContextsForFileSpec (const FileSpec + /// &,uint32_t,bool,uint32_t,SymbolContextList&) + uint32_t ResolveSymbolContextsForFileSpec( + const FileSpec &file_spec, uint32_t line, bool check_inlines, + lldb::SymbolContextItem resolve_scope, SymbolContextList &sc_list) const; + + /// Gets the size of the module list. + /// + /// \return + /// The number of modules in the module list. + size_t GetSize() const; + bool IsEmpty() const { return !GetSize(); } + + bool LoadScriptingResourcesInTarget(Target *target, std::list<Status> &errors, + Stream *feedback_stream = nullptr, + bool continue_on_error = true); + + static ModuleListProperties &GetGlobalModuleListProperties(); + + static bool ModuleIsInCache(const Module *module_ptr); + + static Status GetSharedModule(const ModuleSpec &module_spec, + lldb::ModuleSP &module_sp, + const FileSpecList *module_search_paths_ptr, + lldb::ModuleSP *old_module_sp_ptr, + bool *did_create_ptr, + bool always_create = false); + + static bool RemoveSharedModule(lldb::ModuleSP &module_sp); + + static void FindSharedModules(const ModuleSpec &module_spec, + ModuleList &matching_module_list); + + static size_t RemoveOrphanSharedModules(bool mandatory); + + static bool RemoveSharedModuleIfOrphaned(const Module *module_ptr); + + void ForEach(std::function<bool(const lldb::ModuleSP &module_sp)> const + &callback) const; + +protected: + // Class typedefs. + typedef std::vector<lldb::ModuleSP> + collection; ///< The module collection type. + + void AppendImpl(const lldb::ModuleSP &module_sp, bool use_notifier = true); + + bool RemoveImpl(const lldb::ModuleSP &module_sp, bool use_notifier = true); + + collection::iterator RemoveImpl(collection::iterator pos, + bool use_notifier = true); + + void ClearImpl(bool use_notifier = true); + + // Member variables. + collection m_modules; ///< The collection of modules. + mutable std::recursive_mutex m_modules_mutex; + + Notifier *m_notifier; + +public: + typedef LockingAdaptedIterable<collection, lldb::ModuleSP, vector_adapter, + std::recursive_mutex> + ModuleIterable; + ModuleIterable Modules() { return ModuleIterable(m_modules, GetMutex()); } + + typedef AdaptedIterable<collection, lldb::ModuleSP, vector_adapter> + ModuleIterableNoLocking; + ModuleIterableNoLocking ModulesNoLocking() { + return ModuleIterableNoLocking(m_modules); + } +}; + +} // namespace lldb_private + +#endif // liblldb_ModuleList_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ModuleSpec.h b/contrib/llvm-project/lldb/include/lldb/Core/ModuleSpec.h new file mode 100644 index 000000000000..651d0dc869bc --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ModuleSpec.h @@ -0,0 +1,424 @@ +//===-- ModuleSpec.h --------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ModuleSpec_h_ +#define liblldb_ModuleSpec_h_ + +#include "lldb/Host/FileSystem.h" +#include "lldb/Target/PathMappingList.h" +#include "lldb/Utility/ArchSpec.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Stream.h" +#include "lldb/Utility/UUID.h" + +#include "llvm/Support/Chrono.h" + +#include <mutex> +#include <vector> + +namespace lldb_private { + +class ModuleSpec { +public: + ModuleSpec() + : m_file(), m_platform_file(), m_symbol_file(), m_arch(), m_uuid(), + m_object_name(), m_object_offset(0), m_object_size(0), + m_source_mappings() {} + + ModuleSpec(const FileSpec &file_spec, const UUID &uuid = UUID()) + : m_file(file_spec), m_platform_file(), m_symbol_file(), m_arch(), + m_uuid(uuid), m_object_name(), m_object_offset(0), + m_object_size(FileSystem::Instance().GetByteSize(file_spec)), + m_source_mappings() {} + + 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() {} + + ModuleSpec(const ModuleSpec &rhs) + : m_file(rhs.m_file), m_platform_file(rhs.m_platform_file), + m_symbol_file(rhs.m_symbol_file), m_arch(rhs.m_arch), + m_uuid(rhs.m_uuid), m_object_name(rhs.m_object_name), + m_object_offset(rhs.m_object_offset), m_object_size(rhs.m_object_size), + m_object_mod_time(rhs.m_object_mod_time), + m_source_mappings(rhs.m_source_mappings) {} + + ModuleSpec &operator=(const ModuleSpec &rhs) { + if (this != &rhs) { + m_file = rhs.m_file; + m_platform_file = rhs.m_platform_file; + m_symbol_file = rhs.m_symbol_file; + m_arch = rhs.m_arch; + m_uuid = rhs.m_uuid; + m_object_name = rhs.m_object_name; + m_object_offset = rhs.m_object_offset; + m_object_size = rhs.m_object_size; + m_object_mod_time = rhs.m_object_mod_time; + m_source_mappings = rhs.m_source_mappings; + } + return *this; + } + + FileSpec *GetFileSpecPtr() { return (m_file ? &m_file : nullptr); } + + const FileSpec *GetFileSpecPtr() const { + return (m_file ? &m_file : nullptr); + } + + FileSpec &GetFileSpec() { return m_file; } + + const FileSpec &GetFileSpec() const { return m_file; } + + FileSpec *GetPlatformFileSpecPtr() { + return (m_platform_file ? &m_platform_file : nullptr); + } + + const FileSpec *GetPlatformFileSpecPtr() const { + return (m_platform_file ? &m_platform_file : nullptr); + } + + FileSpec &GetPlatformFileSpec() { return m_platform_file; } + + const FileSpec &GetPlatformFileSpec() const { return m_platform_file; } + + FileSpec *GetSymbolFileSpecPtr() { + return (m_symbol_file ? &m_symbol_file : nullptr); + } + + const FileSpec *GetSymbolFileSpecPtr() const { + return (m_symbol_file ? &m_symbol_file : nullptr); + } + + FileSpec &GetSymbolFileSpec() { return m_symbol_file; } + + const FileSpec &GetSymbolFileSpec() const { return m_symbol_file; } + + ArchSpec *GetArchitecturePtr() { + return (m_arch.IsValid() ? &m_arch : nullptr); + } + + const ArchSpec *GetArchitecturePtr() const { + return (m_arch.IsValid() ? &m_arch : nullptr); + } + + ArchSpec &GetArchitecture() { return m_arch; } + + const ArchSpec &GetArchitecture() const { return m_arch; } + + UUID *GetUUIDPtr() { return (m_uuid.IsValid() ? &m_uuid : nullptr); } + + const UUID *GetUUIDPtr() const { + return (m_uuid.IsValid() ? &m_uuid : nullptr); + } + + UUID &GetUUID() { return m_uuid; } + + const UUID &GetUUID() const { return m_uuid; } + + ConstString &GetObjectName() { return m_object_name; } + + ConstString GetObjectName() const { return m_object_name; } + + uint64_t GetObjectOffset() const { return m_object_offset; } + + void SetObjectOffset(uint64_t object_offset) { + m_object_offset = object_offset; + } + + uint64_t GetObjectSize() const { return m_object_size; } + + void SetObjectSize(uint64_t object_size) { m_object_size = object_size; } + + llvm::sys::TimePoint<> &GetObjectModificationTime() { + return m_object_mod_time; + } + + const llvm::sys::TimePoint<> &GetObjectModificationTime() const { + return m_object_mod_time; + } + + PathMappingList &GetSourceMappingList() const { return m_source_mappings; } + + void Clear() { + m_file.Clear(); + m_platform_file.Clear(); + m_symbol_file.Clear(); + m_arch.Clear(); + m_uuid.Clear(); + m_object_name.Clear(); + m_object_offset = 0; + m_object_size = 0; + m_source_mappings.Clear(false); + m_object_mod_time = llvm::sys::TimePoint<>(); + } + + explicit operator bool() const { + if (m_file) + return true; + if (m_platform_file) + return true; + if (m_symbol_file) + return true; + if (m_arch.IsValid()) + return true; + if (m_uuid.IsValid()) + return true; + if (m_object_name) + return true; + if (m_object_size) + return true; + if (m_object_mod_time != llvm::sys::TimePoint<>()) + return true; + return false; + } + + void Dump(Stream &strm) const { + bool dumped_something = false; + if (m_file) { + strm.PutCString("file = '"); + strm << m_file; + strm.PutCString("'"); + dumped_something = true; + } + if (m_platform_file) { + if (dumped_something) + strm.PutCString(", "); + strm.PutCString("platform_file = '"); + strm << m_platform_file; + strm.PutCString("'"); + dumped_something = true; + } + if (m_symbol_file) { + if (dumped_something) + strm.PutCString(", "); + strm.PutCString("symbol_file = '"); + strm << m_symbol_file; + strm.PutCString("'"); + dumped_something = true; + } + if (m_arch.IsValid()) { + if (dumped_something) + strm.PutCString(", "); + strm.Printf("arch = "); + m_arch.DumpTriple(strm); + dumped_something = true; + } + if (m_uuid.IsValid()) { + if (dumped_something) + strm.PutCString(", "); + strm.PutCString("uuid = "); + m_uuid.Dump(&strm); + dumped_something = true; + } + if (m_object_name) { + if (dumped_something) + strm.PutCString(", "); + strm.Printf("object_name = %s", m_object_name.GetCString()); + dumped_something = true; + } + if (m_object_offset > 0) { + if (dumped_something) + strm.PutCString(", "); + strm.Printf("object_offset = %" PRIu64, m_object_offset); + dumped_something = true; + } + if (m_object_size > 0) { + if (dumped_something) + strm.PutCString(", "); + strm.Printf("object size = %" PRIu64, m_object_size); + dumped_something = true; + } + if (m_object_mod_time != llvm::sys::TimePoint<>()) { + if (dumped_something) + strm.PutCString(", "); + strm.Format("object_mod_time = {0:x+}", + uint64_t(llvm::sys::toTimeT(m_object_mod_time))); + } + } + + bool Matches(const ModuleSpec &match_module_spec, + bool exact_arch_match) const { + if (match_module_spec.GetUUIDPtr() && + match_module_spec.GetUUID() != GetUUID()) + return false; + if (match_module_spec.GetObjectName() && + match_module_spec.GetObjectName() != GetObjectName()) + return false; + if (match_module_spec.GetFileSpecPtr()) { + const FileSpec &fspec = match_module_spec.GetFileSpec(); + if (!FileSpec::Equal(fspec, GetFileSpec(), + !fspec.GetDirectory().IsEmpty())) + return false; + } + if (GetPlatformFileSpec() && match_module_spec.GetPlatformFileSpecPtr()) { + const FileSpec &fspec = match_module_spec.GetPlatformFileSpec(); + if (!FileSpec::Equal(fspec, GetPlatformFileSpec(), + !fspec.GetDirectory().IsEmpty())) + return false; + } + // Only match the symbol file spec if there is one in this ModuleSpec + if (GetSymbolFileSpec() && match_module_spec.GetSymbolFileSpecPtr()) { + const FileSpec &fspec = match_module_spec.GetSymbolFileSpec(); + if (!FileSpec::Equal(fspec, GetSymbolFileSpec(), + !fspec.GetDirectory().IsEmpty())) + return false; + } + if (match_module_spec.GetArchitecturePtr()) { + if (exact_arch_match) { + if (!GetArchitecture().IsExactMatch( + match_module_spec.GetArchitecture())) + return false; + } else { + if (!GetArchitecture().IsCompatibleMatch( + match_module_spec.GetArchitecture())) + return false; + } + } + return true; + } + +protected: + FileSpec m_file; + FileSpec m_platform_file; + FileSpec m_symbol_file; + ArchSpec m_arch; + UUID m_uuid; + ConstString m_object_name; + uint64_t m_object_offset; + uint64_t m_object_size; + llvm::sys::TimePoint<> m_object_mod_time; + mutable PathMappingList m_source_mappings; +}; + +class ModuleSpecList { +public: + ModuleSpecList() : m_specs(), m_mutex() {} + + ModuleSpecList(const ModuleSpecList &rhs) : m_specs(), m_mutex() { + 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; + } + + ~ModuleSpecList() = default; + + ModuleSpecList &operator=(const ModuleSpecList &rhs) { + if (this != &rhs) { + std::lock(m_mutex, rhs.m_mutex); + std::lock_guard<std::recursive_mutex> lhs_guard(m_mutex, std::adopt_lock); + std::lock_guard<std::recursive_mutex> rhs_guard(rhs.m_mutex, + std::adopt_lock); + m_specs = rhs.m_specs; + } + return *this; + } + + size_t GetSize() const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_specs.size(); + } + + void Clear() { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_specs.clear(); + } + + void Append(const ModuleSpec &spec) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_specs.push_back(spec); + } + + void Append(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.insert(m_specs.end(), rhs.m_specs.begin(), rhs.m_specs.end()); + } + + // The index "i" must be valid and this can't be used in multi-threaded code + // as no mutex lock is taken. + ModuleSpec &GetModuleSpecRefAtIndex(size_t i) { return m_specs[i]; } + + bool GetModuleSpecAtIndex(size_t i, ModuleSpec &module_spec) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + if (i < m_specs.size()) { + module_spec = m_specs[i]; + return true; + } + module_spec.Clear(); + return false; + } + + bool FindMatchingModuleSpec(const ModuleSpec &module_spec, + ModuleSpec &match_module_spec) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + bool exact_arch_match = true; + for (auto spec : m_specs) { + if (spec.Matches(module_spec, exact_arch_match)) { + match_module_spec = spec; + return true; + } + } + + // If there was an architecture, retry with a compatible arch + if (module_spec.GetArchitecturePtr()) { + exact_arch_match = false; + for (auto spec : m_specs) { + if (spec.Matches(module_spec, exact_arch_match)) { + match_module_spec = spec; + return true; + } + } + } + match_module_spec.Clear(); + return false; + } + + void FindMatchingModuleSpecs(const ModuleSpec &module_spec, + ModuleSpecList &matching_list) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + bool exact_arch_match = true; + const size_t initial_match_count = matching_list.GetSize(); + for (auto spec : m_specs) { + if (spec.Matches(module_spec, exact_arch_match)) + matching_list.Append(spec); + } + + // If there was an architecture, retry with a compatible arch if no matches + // were found + if (module_spec.GetArchitecturePtr() && + (initial_match_count == matching_list.GetSize())) { + exact_arch_match = false; + for (auto spec : m_specs) { + if (spec.Matches(module_spec, exact_arch_match)) + matching_list.Append(spec); + } + } + } + + void Dump(Stream &strm) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + uint32_t idx = 0; + for (auto spec : m_specs) { + strm.Printf("[%u] ", idx); + spec.Dump(strm); + strm.EOL(); + ++idx; + } + } + +protected: + typedef std::vector<ModuleSpec> collection; ///< The module collection type. + collection m_specs; ///< The collection of modules. + mutable std::recursive_mutex m_mutex; +}; + +} // namespace lldb_private + +#endif // liblldb_ModuleSpec_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Opcode.h b/contrib/llvm-project/lldb/include/lldb/Core/Opcode.h new file mode 100644 index 000000000000..1a30ce4834ac --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/Opcode.h @@ -0,0 +1,273 @@ +//===-- Opcode.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_Opcode_h +#define lldb_Opcode_h + +#include "lldb/Utility/Endian.h" +#include "lldb/lldb-enumerations.h" + +#include "llvm/Support/MathExtras.h" + +#include <assert.h> +#include <stdint.h> +#include <string.h> + +namespace lldb { +class SBInstruction; +} + +namespace lldb_private { +class DataExtractor; +class Stream; + +class Opcode { +public: + enum Type { + eTypeInvalid, + eType8, + eType16, + eType16_2, // a 32-bit Thumb instruction, made up of two words + eType32, + eType64, + eTypeBytes + }; + + Opcode() : m_byte_order(lldb::eByteOrderInvalid), m_type(eTypeInvalid) {} + + Opcode(uint8_t inst, lldb::ByteOrder order) + : m_byte_order(order), m_type(eType8) { + m_data.inst8 = inst; + } + + Opcode(uint16_t inst, lldb::ByteOrder order) + : m_byte_order(order), m_type(eType16) { + m_data.inst16 = inst; + } + + Opcode(uint32_t inst, lldb::ByteOrder order) + : m_byte_order(order), m_type(eType32) { + m_data.inst32 = inst; + } + + Opcode(uint64_t inst, lldb::ByteOrder order) + : m_byte_order(order), m_type(eType64) { + m_data.inst64 = inst; + } + + Opcode(uint8_t *bytes, size_t length) + : m_byte_order(lldb::eByteOrderInvalid) { + SetOpcodeBytes(bytes, length); + } + + void Clear() { + m_byte_order = lldb::eByteOrderInvalid; + m_type = Opcode::eTypeInvalid; + } + + Opcode::Type GetType() const { return m_type; } + + uint8_t GetOpcode8(uint8_t invalid_opcode = UINT8_MAX) const { + switch (m_type) { + case Opcode::eTypeInvalid: + break; + case Opcode::eType8: + return m_data.inst8; + case Opcode::eType16: + break; + case Opcode::eType16_2: + break; + case Opcode::eType32: + break; + case Opcode::eType64: + break; + case Opcode::eTypeBytes: + break; + } + return invalid_opcode; + } + + uint16_t GetOpcode16(uint16_t invalid_opcode = UINT16_MAX) const { + switch (m_type) { + case Opcode::eTypeInvalid: + break; + case Opcode::eType8: + return m_data.inst8; + case Opcode::eType16: + return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; + case Opcode::eType16_2: + break; + case Opcode::eType32: + break; + case Opcode::eType64: + break; + case Opcode::eTypeBytes: + break; + } + return invalid_opcode; + } + + uint32_t GetOpcode32(uint32_t invalid_opcode = UINT32_MAX) const { + switch (m_type) { + case Opcode::eTypeInvalid: + break; + case Opcode::eType8: + return m_data.inst8; + case Opcode::eType16: + return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; + case Opcode::eType16_2: // passthrough + case Opcode::eType32: + return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32; + case Opcode::eType64: + break; + case Opcode::eTypeBytes: + break; + } + return invalid_opcode; + } + + uint64_t GetOpcode64(uint64_t invalid_opcode = UINT64_MAX) const { + switch (m_type) { + case Opcode::eTypeInvalid: + break; + case Opcode::eType8: + return m_data.inst8; + case Opcode::eType16: + return GetEndianSwap() ? llvm::ByteSwap_16(m_data.inst16) : m_data.inst16; + case Opcode::eType16_2: // passthrough + case Opcode::eType32: + return GetEndianSwap() ? llvm::ByteSwap_32(m_data.inst32) : m_data.inst32; + case Opcode::eType64: + return GetEndianSwap() ? llvm::ByteSwap_64(m_data.inst64) : m_data.inst64; + case Opcode::eTypeBytes: + break; + } + return invalid_opcode; + } + + void SetOpcode8(uint8_t inst, lldb::ByteOrder order) { + m_type = eType8; + m_data.inst8 = inst; + m_byte_order = order; + } + + void SetOpcode16(uint16_t inst, lldb::ByteOrder order) { + m_type = eType16; + m_data.inst16 = inst; + m_byte_order = order; + } + + void SetOpcode16_2(uint32_t inst, lldb::ByteOrder order) { + m_type = eType16_2; + m_data.inst32 = inst; + m_byte_order = order; + } + + void SetOpcode32(uint32_t inst, lldb::ByteOrder order) { + m_type = eType32; + m_data.inst32 = inst; + m_byte_order = order; + } + + void SetOpcode64(uint64_t inst, lldb::ByteOrder order) { + m_type = eType64; + m_data.inst64 = inst; + m_byte_order = order; + } + + void SetOpcodeBytes(const void *bytes, size_t length) { + if (bytes != nullptr && length > 0) { + m_type = eTypeBytes; + m_data.inst.length = length; + assert(length < sizeof(m_data.inst.bytes)); + memcpy(m_data.inst.bytes, bytes, length); + m_byte_order = lldb::eByteOrderInvalid; + } else { + m_type = eTypeInvalid; + m_data.inst.length = 0; + } + } + + int Dump(Stream *s, uint32_t min_byte_width); + + const void *GetOpcodeBytes() const { + return ((m_type == Opcode::eTypeBytes) ? m_data.inst.bytes : nullptr); + } + + uint32_t GetByteSize() const { + switch (m_type) { + case Opcode::eTypeInvalid: + break; + case Opcode::eType8: + return sizeof(m_data.inst8); + case Opcode::eType16: + return sizeof(m_data.inst16); + case Opcode::eType16_2: // passthrough + case Opcode::eType32: + return sizeof(m_data.inst32); + case Opcode::eType64: + return sizeof(m_data.inst64); + case Opcode::eTypeBytes: + return m_data.inst.length; + } + return 0; + } + + // Get the opcode exactly as it would be laid out in memory. + uint32_t GetData(DataExtractor &data) const; + +protected: + friend class lldb::SBInstruction; + + const void *GetOpcodeDataBytes() const { + switch (m_type) { + case Opcode::eTypeInvalid: + break; + case Opcode::eType8: + return &m_data.inst8; + case Opcode::eType16: + return &m_data.inst16; + case Opcode::eType16_2: // passthrough + case Opcode::eType32: + return &m_data.inst32; + case Opcode::eType64: + return &m_data.inst64; + case Opcode::eTypeBytes: + return m_data.inst.bytes; + } + return nullptr; + } + + lldb::ByteOrder GetDataByteOrder() const; + + bool GetEndianSwap() const { + return (m_byte_order == lldb::eByteOrderBig && + endian::InlHostByteOrder() == lldb::eByteOrderLittle) || + (m_byte_order == lldb::eByteOrderLittle && + endian::InlHostByteOrder() == lldb::eByteOrderBig); + } + + lldb::ByteOrder m_byte_order; + + Opcode::Type m_type; + union { + uint8_t inst8; + uint16_t inst16; + uint32_t inst32; + uint64_t inst64; + struct { + uint8_t bytes[16]; // This must be big enough to handle any opcode for any + // supported target. + uint8_t length; + } inst; + } m_data; +}; + +} // namespace lldb_private + +#endif // lldb_Opcode_h diff --git a/contrib/llvm-project/lldb/include/lldb/Core/PluginInterface.h b/contrib/llvm-project/lldb/include/lldb/Core/PluginInterface.h new file mode 100644 index 000000000000..6e625a605917 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/PluginInterface.h @@ -0,0 +1,27 @@ +//===-- PluginInterface.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_PluginInterface_h_ +#define liblldb_PluginInterface_h_ + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +class PluginInterface { +public: + virtual ~PluginInterface() {} + + virtual ConstString GetPluginName() = 0; + + virtual uint32_t GetPluginVersion() = 0; +}; + +} // namespace lldb_private + +#endif // liblldb_PluginInterface_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/PluginManager.h b/contrib/llvm-project/lldb/include/lldb/Core/PluginManager.h new file mode 100644 index 000000000000..5b859752b3c7 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/PluginManager.h @@ -0,0 +1,481 @@ +//===-- PluginManager.h -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_PluginManager_h_ +#define liblldb_PluginManager_h_ + +#include "lldb/Core/Architecture.h" +#include "lldb/Symbol/TypeSystem.h" +#include "lldb/Utility/CompletionRequest.h" +#include "lldb/Utility/FileSpec.h" +#include "lldb/Utility/Status.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private-interfaces.h" +#include "llvm/ADT/StringRef.h" + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class CommandInterpreter; +class ConstString; +class Debugger; +class StringList; + +class PluginManager { +public: + static void Initialize(); + + static void Terminate(); + + // ABI + static bool RegisterPlugin(ConstString name, const char *description, + ABICreateInstance create_callback); + + static bool UnregisterPlugin(ABICreateInstance create_callback); + + static ABICreateInstance GetABICreateCallbackAtIndex(uint32_t idx); + + static ABICreateInstance + GetABICreateCallbackForPluginName(ConstString name); + + // Architecture + using ArchitectureCreateInstance = + std::unique_ptr<Architecture> (*)(const ArchSpec &); + + static void RegisterPlugin(ConstString name, + llvm::StringRef description, + ArchitectureCreateInstance create_callback); + + static void UnregisterPlugin(ArchitectureCreateInstance create_callback); + + static std::unique_ptr<Architecture> + CreateArchitectureInstance(const ArchSpec &arch); + + // Disassembler + static bool RegisterPlugin(ConstString name, const char *description, + DisassemblerCreateInstance create_callback); + + static bool UnregisterPlugin(DisassemblerCreateInstance create_callback); + + static DisassemblerCreateInstance + GetDisassemblerCreateCallbackAtIndex(uint32_t idx); + + static DisassemblerCreateInstance + GetDisassemblerCreateCallbackForPluginName(ConstString name); + + // DynamicLoader + static bool + RegisterPlugin(ConstString name, const char *description, + DynamicLoaderCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = nullptr); + + static bool UnregisterPlugin(DynamicLoaderCreateInstance create_callback); + + static DynamicLoaderCreateInstance + GetDynamicLoaderCreateCallbackAtIndex(uint32_t idx); + + static DynamicLoaderCreateInstance + GetDynamicLoaderCreateCallbackForPluginName(ConstString name); + + // JITLoader + static bool + RegisterPlugin(ConstString name, const char *description, + JITLoaderCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = nullptr); + + static bool UnregisterPlugin(JITLoaderCreateInstance create_callback); + + static JITLoaderCreateInstance + GetJITLoaderCreateCallbackAtIndex(uint32_t idx); + + static JITLoaderCreateInstance + GetJITLoaderCreateCallbackForPluginName(ConstString name); + + // EmulateInstruction + static bool RegisterPlugin(ConstString name, const char *description, + EmulateInstructionCreateInstance create_callback); + + static bool + UnregisterPlugin(EmulateInstructionCreateInstance create_callback); + + static EmulateInstructionCreateInstance + GetEmulateInstructionCreateCallbackAtIndex(uint32_t idx); + + static EmulateInstructionCreateInstance + GetEmulateInstructionCreateCallbackForPluginName(ConstString name); + + // OperatingSystem + static bool RegisterPlugin(ConstString name, const char *description, + OperatingSystemCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback); + + static bool UnregisterPlugin(OperatingSystemCreateInstance create_callback); + + static OperatingSystemCreateInstance + GetOperatingSystemCreateCallbackAtIndex(uint32_t idx); + + static OperatingSystemCreateInstance + GetOperatingSystemCreateCallbackForPluginName(ConstString name); + + // Language + static bool RegisterPlugin(ConstString name, const char *description, + LanguageCreateInstance create_callback); + + static bool UnregisterPlugin(LanguageCreateInstance create_callback); + + static LanguageCreateInstance GetLanguageCreateCallbackAtIndex(uint32_t idx); + + static LanguageCreateInstance + GetLanguageCreateCallbackForPluginName(ConstString name); + + // LanguageRuntime + static bool RegisterPlugin( + ConstString name, const char *description, + LanguageRuntimeCreateInstance create_callback, + LanguageRuntimeGetCommandObject command_callback = nullptr, + LanguageRuntimeGetExceptionPrecondition precondition_callback = nullptr); + + static bool UnregisterPlugin(LanguageRuntimeCreateInstance create_callback); + + static LanguageRuntimeCreateInstance + GetLanguageRuntimeCreateCallbackAtIndex(uint32_t idx); + + static LanguageRuntimeGetCommandObject + GetLanguageRuntimeGetCommandObjectAtIndex(uint32_t idx); + + static LanguageRuntimeGetExceptionPrecondition + GetLanguageRuntimeGetExceptionPreconditionAtIndex(uint32_t idx); + + static LanguageRuntimeCreateInstance + GetLanguageRuntimeCreateCallbackForPluginName(ConstString name); + + // SystemRuntime + static bool RegisterPlugin(ConstString name, const char *description, + SystemRuntimeCreateInstance create_callback); + + static bool UnregisterPlugin(SystemRuntimeCreateInstance create_callback); + + static SystemRuntimeCreateInstance + GetSystemRuntimeCreateCallbackAtIndex(uint32_t idx); + + static SystemRuntimeCreateInstance + GetSystemRuntimeCreateCallbackForPluginName(ConstString name); + + // ObjectFile + static bool + RegisterPlugin(ConstString name, const char *description, + ObjectFileCreateInstance create_callback, + ObjectFileCreateMemoryInstance create_memory_callback, + ObjectFileGetModuleSpecifications get_module_specifications, + ObjectFileSaveCore save_core = nullptr); + + static bool UnregisterPlugin(ObjectFileCreateInstance create_callback); + + static ObjectFileCreateInstance + GetObjectFileCreateCallbackAtIndex(uint32_t idx); + + static ObjectFileCreateMemoryInstance + GetObjectFileCreateMemoryCallbackAtIndex(uint32_t idx); + + static ObjectFileGetModuleSpecifications + GetObjectFileGetModuleSpecificationsCallbackAtIndex(uint32_t idx); + + static ObjectFileCreateInstance + GetObjectFileCreateCallbackForPluginName(ConstString name); + + static ObjectFileCreateMemoryInstance + GetObjectFileCreateMemoryCallbackForPluginName(ConstString name); + + static Status SaveCore(const lldb::ProcessSP &process_sp, + const FileSpec &outfile); + + // ObjectContainer + static bool + RegisterPlugin(ConstString name, const char *description, + ObjectContainerCreateInstance create_callback, + ObjectFileGetModuleSpecifications get_module_specifications); + + static bool UnregisterPlugin(ObjectContainerCreateInstance create_callback); + + static ObjectContainerCreateInstance + GetObjectContainerCreateCallbackAtIndex(uint32_t idx); + + static ObjectContainerCreateInstance + GetObjectContainerCreateCallbackForPluginName(ConstString name); + + static ObjectFileGetModuleSpecifications + GetObjectContainerGetModuleSpecificationsCallbackAtIndex(uint32_t idx); + + // Platform + static bool + RegisterPlugin(ConstString name, const char *description, + PlatformCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = nullptr); + + static bool UnregisterPlugin(PlatformCreateInstance create_callback); + + static PlatformCreateInstance GetPlatformCreateCallbackAtIndex(uint32_t idx); + + static PlatformCreateInstance + GetPlatformCreateCallbackForPluginName(ConstString name); + + static const char *GetPlatformPluginNameAtIndex(uint32_t idx); + + static const char *GetPlatformPluginDescriptionAtIndex(uint32_t idx); + + static void AutoCompletePlatformName(llvm::StringRef partial_name, + CompletionRequest &request); + // Process + static bool + RegisterPlugin(ConstString name, const char *description, + ProcessCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = nullptr); + + static bool UnregisterPlugin(ProcessCreateInstance create_callback); + + static ProcessCreateInstance GetProcessCreateCallbackAtIndex(uint32_t idx); + + static ProcessCreateInstance + GetProcessCreateCallbackForPluginName(ConstString name); + + static const char *GetProcessPluginNameAtIndex(uint32_t idx); + + static const char *GetProcessPluginDescriptionAtIndex(uint32_t idx); + + // ScriptInterpreter + static bool RegisterPlugin(ConstString name, const char *description, + lldb::ScriptLanguage script_lang, + ScriptInterpreterCreateInstance create_callback); + + static bool UnregisterPlugin(ScriptInterpreterCreateInstance create_callback); + + static ScriptInterpreterCreateInstance + GetScriptInterpreterCreateCallbackAtIndex(uint32_t idx); + + static lldb::ScriptInterpreterSP + GetScriptInterpreterForLanguage(lldb::ScriptLanguage script_lang, + Debugger &debugger); + + // StructuredDataPlugin + + /// Register a StructuredDataPlugin class along with optional + /// callbacks for debugger initialization and Process launch info + /// filtering and manipulation. + /// + /// \param[in] name + /// The name of the plugin. + /// + /// \param[in] description + /// A description string for the plugin. + /// + /// \param[in] create_callback + /// The callback that will be invoked to create an instance of + /// the callback. This may not be nullptr. + /// + /// \param[in] debugger_init_callback + /// An optional callback that will be made when a Debugger + /// instance is initialized. + /// + /// \param[in] filter_callback + /// An optional callback that will be invoked before LLDB + /// launches a process for debugging. The callback must + /// do the following: + /// 1. Only do something if the plugin's behavior is enabled. + /// 2. Only make changes for processes that are relevant to the + /// plugin. The callback gets a pointer to the Target, which + /// can be inspected as needed. The ProcessLaunchInfo is + /// provided in read-write mode, and may be modified by the + /// plugin if, for instance, additional environment variables + /// are needed to support the feature when enabled. + /// + /// \return + /// Returns true upon success; otherwise, false. + static bool + RegisterPlugin(ConstString name, const char *description, + StructuredDataPluginCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = nullptr, + StructuredDataFilterLaunchInfo filter_callback = nullptr); + + static bool + UnregisterPlugin(StructuredDataPluginCreateInstance create_callback); + + static StructuredDataPluginCreateInstance + GetStructuredDataPluginCreateCallbackAtIndex(uint32_t idx); + + static StructuredDataPluginCreateInstance + GetStructuredDataPluginCreateCallbackForPluginName(ConstString name); + + static StructuredDataFilterLaunchInfo + GetStructuredDataFilterCallbackAtIndex(uint32_t idx, + bool &iteration_complete); + + // SymbolFile + static bool + RegisterPlugin(ConstString name, const char *description, + SymbolFileCreateInstance create_callback, + DebuggerInitializeCallback debugger_init_callback = nullptr); + + static bool UnregisterPlugin(SymbolFileCreateInstance create_callback); + + static SymbolFileCreateInstance + GetSymbolFileCreateCallbackAtIndex(uint32_t idx); + + static SymbolFileCreateInstance + GetSymbolFileCreateCallbackForPluginName(ConstString name); + + // SymbolVendor + static bool RegisterPlugin(ConstString name, const char *description, + SymbolVendorCreateInstance create_callback); + + static bool UnregisterPlugin(SymbolVendorCreateInstance create_callback); + + static SymbolVendorCreateInstance + GetSymbolVendorCreateCallbackAtIndex(uint32_t idx); + + static SymbolVendorCreateInstance + GetSymbolVendorCreateCallbackForPluginName(ConstString name); + + // UnwindAssembly + static bool RegisterPlugin(ConstString name, const char *description, + UnwindAssemblyCreateInstance create_callback); + + static bool UnregisterPlugin(UnwindAssemblyCreateInstance create_callback); + + static UnwindAssemblyCreateInstance + GetUnwindAssemblyCreateCallbackAtIndex(uint32_t idx); + + static UnwindAssemblyCreateInstance + GetUnwindAssemblyCreateCallbackForPluginName(ConstString name); + + // MemoryHistory + static bool RegisterPlugin(ConstString name, const char *description, + MemoryHistoryCreateInstance create_callback); + + static bool UnregisterPlugin(MemoryHistoryCreateInstance create_callback); + + static MemoryHistoryCreateInstance + GetMemoryHistoryCreateCallbackAtIndex(uint32_t idx); + + static MemoryHistoryCreateInstance + GetMemoryHistoryCreateCallbackForPluginName(ConstString name); + + // InstrumentationRuntime + static bool + RegisterPlugin(ConstString name, const char *description, + InstrumentationRuntimeCreateInstance create_callback, + InstrumentationRuntimeGetType get_type_callback); + + static bool + UnregisterPlugin(InstrumentationRuntimeCreateInstance create_callback); + + static InstrumentationRuntimeGetType + GetInstrumentationRuntimeGetTypeCallbackAtIndex(uint32_t idx); + + static InstrumentationRuntimeCreateInstance + GetInstrumentationRuntimeCreateCallbackAtIndex(uint32_t idx); + + static InstrumentationRuntimeCreateInstance + GetInstrumentationRuntimeCreateCallbackForPluginName(ConstString name); + + // TypeSystem + static bool RegisterPlugin(ConstString name, const char *description, + TypeSystemCreateInstance create_callback, + LanguageSet supported_languages_for_types, + LanguageSet supported_languages_for_expressions); + + static bool UnregisterPlugin(TypeSystemCreateInstance create_callback); + + static TypeSystemCreateInstance + GetTypeSystemCreateCallbackAtIndex(uint32_t idx); + + static TypeSystemCreateInstance + GetTypeSystemCreateCallbackForPluginName(ConstString name); + + static LanguageSet GetAllTypeSystemSupportedLanguagesForTypes(); + + static LanguageSet GetAllTypeSystemSupportedLanguagesForExpressions(); + + // REPL + static bool RegisterPlugin(ConstString name, const char *description, + REPLCreateInstance create_callback, + LanguageSet supported_languages); + + static bool UnregisterPlugin(REPLCreateInstance create_callback); + + static REPLCreateInstance GetREPLCreateCallbackAtIndex(uint32_t idx); + + static REPLCreateInstance + GetREPLCreateCallbackForPluginName(ConstString name); + + static LanguageSet GetREPLAllTypeSystemSupportedLanguages(); + + // Some plug-ins might register a DebuggerInitializeCallback callback when + // registering the plug-in. After a new Debugger instance is created, this + // DebuggerInitialize function will get called. This allows plug-ins to + // install Properties and do any other initialization that requires a + // debugger instance. + static void DebuggerInitialize(Debugger &debugger); + + static lldb::OptionValuePropertiesSP + GetSettingForDynamicLoaderPlugin(Debugger &debugger, + ConstString setting_name); + + static bool CreateSettingForDynamicLoaderPlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + ConstString description, bool is_global_property); + + static lldb::OptionValuePropertiesSP + GetSettingForPlatformPlugin(Debugger &debugger, ConstString setting_name); + + static bool CreateSettingForPlatformPlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + ConstString description, bool is_global_property); + + static lldb::OptionValuePropertiesSP + GetSettingForProcessPlugin(Debugger &debugger, ConstString setting_name); + + static bool CreateSettingForProcessPlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + ConstString description, bool is_global_property); + + static lldb::OptionValuePropertiesSP + GetSettingForSymbolFilePlugin(Debugger &debugger, ConstString setting_name); + + static bool CreateSettingForSymbolFilePlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + ConstString description, bool is_global_property); + + static lldb::OptionValuePropertiesSP + GetSettingForJITLoaderPlugin(Debugger &debugger, ConstString setting_name); + + static bool CreateSettingForJITLoaderPlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + ConstString description, bool is_global_property); + + static lldb::OptionValuePropertiesSP + GetSettingForOperatingSystemPlugin(Debugger &debugger, + ConstString setting_name); + + static bool CreateSettingForOperatingSystemPlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + ConstString description, bool is_global_property); + + static lldb::OptionValuePropertiesSP + GetSettingForStructuredDataPlugin(Debugger &debugger, + ConstString setting_name); + + static bool CreateSettingForStructuredDataPlugin( + Debugger &debugger, const lldb::OptionValuePropertiesSP &properties_sp, + ConstString description, bool is_global_property); +}; + +} // namespace lldb_private + +#endif // liblldb_PluginManager_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/PropertiesBase.td b/contrib/llvm-project/lldb/include/lldb/Core/PropertiesBase.td new file mode 100644 index 000000000000..be97d44ae8e4 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/PropertiesBase.td @@ -0,0 +1,49 @@ +// Base class for all options. +class Property<string name, string type> { + string Name = name; + string Type = type; + string Definition; +} + +// Sets the description for the property that should be displayed to the user. +class Desc<string description> { + string Description = description; +} + +// Marks the property as global. +class Global { + bit Global = 1; +} + +class DefaultTrue { + int DefaultUnsignedValue = 1; + bit HasDefaultUnsignedValue = 1; +} + +class DefaultFalse { + int DefaultUnsignedValue = 0; + bit HasDefaultUnsignedValue = 1; +} + +// Gives the property a default string value. +class DefaultStringValue<string value> { + string DefaultStringValue = value; + bit HasDefaultStringValue = 1; +} + +// Gives the property a default enum value. +class DefaultEnumValue<string value> { + string DefaultEnumValue = value; + bit HasDefaultEnumValue = 1; +} + +// Gives the property a default string value. +class DefaultUnsignedValue<int value> { + int DefaultUnsignedValue = value; + bit HasDefaultUnsignedValue = 1; +} + +// Gives the property enum values. +class EnumValues<string enum> { + string EnumValues = enum; +} diff --git a/contrib/llvm-project/lldb/include/lldb/Core/RichManglingContext.h b/contrib/llvm-project/lldb/include/lldb/Core/RichManglingContext.h new file mode 100644 index 000000000000..e6fa2599e55a --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/RichManglingContext.h @@ -0,0 +1,107 @@ +//===-- RichManglingContext.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_RichManglingContext_h_ +#define liblldb_RichManglingContext_h_ + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private.h" + +#include "lldb/Utility/ConstString.h" + +#include "llvm/ADT/Any.h" +#include "llvm/ADT/SmallString.h" +#include "llvm/Demangle/Demangle.h" + +namespace lldb_private { + +/// Uniform wrapper for access to rich mangling information from different +/// providers. See Mangled::DemangleWithRichManglingInfo() +class RichManglingContext { +public: + RichManglingContext() : m_provider(None), m_ipd_buf_size(2048) { + m_ipd_buf = static_cast<char *>(std::malloc(m_ipd_buf_size)); + m_ipd_buf[0] = '\0'; + } + + ~RichManglingContext() { std::free(m_ipd_buf); } + + /// Use the ItaniumPartialDemangler to obtain rich mangling information from + /// the given mangled name. + bool FromItaniumName(ConstString mangled); + + /// Use the legacy language parser implementation to obtain rich mangling + /// information from the given demangled name. + bool FromCxxMethodName(ConstString demangled); + + /// If this symbol describes a constructor or destructor. + bool IsCtorOrDtor() const; + + /// If this symbol describes a function. + bool IsFunction() const; + + /// Get the base name of a function. This doesn't include trailing template + /// arguments, ie "a::b<int>" gives "b". The result will overwrite the + /// internal buffer. It can be obtained via GetBufferRef(). + void ParseFunctionBaseName(); + + /// Get the context name for a function. For "a::b::c", this function returns + /// "a::b". The result will overwrite the internal buffer. It can be obtained + /// via GetBufferRef(). + void ParseFunctionDeclContextName(); + + /// Get the entire demangled name. The result will overwrite the internal + /// buffer. It can be obtained via GetBufferRef(). + void ParseFullName(); + + /// Obtain a StringRef to the internal buffer that holds the result of the + /// most recent ParseXy() operation. The next ParseXy() call invalidates it. + llvm::StringRef GetBufferRef() const { + assert(m_provider != None && "Initialize a provider first"); + return m_buffer; + } + +private: + enum InfoProvider { None, ItaniumPartialDemangler, PluginCxxLanguage }; + + /// Selects the rich mangling info provider. + InfoProvider m_provider; + + /// Reference to the buffer used for results of ParseXy() operations. + llvm::StringRef m_buffer; + + /// Members for ItaniumPartialDemangler + llvm::ItaniumPartialDemangler m_ipd; + char *m_ipd_buf; + size_t m_ipd_buf_size; + + /// Members for PluginCxxLanguage + /// Cannot forward declare inner class CPlusPlusLanguage::MethodName. The + /// respective header is in Plugins and including it from here causes cyclic + /// dependency. Instead keep a llvm::Any and cast it on-access in the cpp. + llvm::Any m_cxx_method_parser; + + /// Clean up memory and set a new info provider for this instance. + void ResetProvider(InfoProvider new_provider); + + /// Uniform handling of string buffers for ItaniumPartialDemangler. + void processIPDStrResult(char *ipd_res, size_t res_len); + + /// Cast the given parser to the given type. Ideally we would have a type + /// trait to deduce \a ParserT from a given InfoProvider, but unfortunately we + /// can't access CPlusPlusLanguage::MethodName from within the header. + template <class ParserT> static ParserT *get(llvm::Any parser) { + assert(parser.hasValue()); + assert(llvm::any_isa<ParserT *>(parser)); + return llvm::any_cast<ParserT *>(parser); + } +}; + +} // namespace lldb_private + +#endif diff --git a/contrib/llvm-project/lldb/include/lldb/Core/STLUtils.h b/contrib/llvm-project/lldb/include/lldb/Core/STLUtils.h new file mode 100644 index 000000000000..830aca36a116 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/STLUtils.h @@ -0,0 +1,74 @@ +//===-- STLUtils.h ----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_STLUtils_h_ +#define liblldb_STLUtils_h_ + +#include <string.h> + +#include <map> +#include <ostream> +#include <vector> + + +// C string less than compare function object +struct CStringCompareFunctionObject { + bool operator()(const char *s1, const char *s2) const { + return strcmp(s1, s2) < 0; + } +}; + +// C string equality function object (binary predicate). +struct CStringEqualBinaryPredicate { + bool operator()(const char *s1, const char *s2) const { + return strcmp(s1, s2) == 0; + } +}; + +// Templated type for finding an entry in a std::map<F,S> whose value is equal +// to something +template <class F, class S> class ValueEquals { +public: + ValueEquals(const S &val) : second_value(val) {} + + // Compare the second item + bool operator()(std::pair<const F, S> elem) { + return elem.second == second_value; + } + +private: + S second_value; +}; + +template <class T> +inline void PrintAllCollectionElements(std::ostream &s, const T &coll, + const char *header_cstr = nullptr, + const char *separator_cstr = " ") { + typename T::const_iterator pos; + + if (header_cstr) + s << header_cstr; + for (pos = coll.begin(); pos != coll.end(); ++pos) { + s << *pos << separator_cstr; + } + s << std::endl; +} + +// The function object below can be used to delete a STL container that +// contains C++ object pointers. +// +// Usage: std::for_each(vector.begin(), vector.end(), for_each_delete()); + +struct for_each_cplusplus_delete { + template <typename T> void operator()(T *ptr) { delete ptr; } +}; + +typedef std::vector<std::string> STLStringArray; +typedef std::vector<const char *> CStringArray; + +#endif // liblldb_STLUtils_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/SearchFilter.h b/contrib/llvm-project/lldb/include/lldb/Core/SearchFilter.h new file mode 100644 index 000000000000..6823daf9e3ed --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/SearchFilter.h @@ -0,0 +1,456 @@ +//===-- SearchFilter.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_SearchFilter_h_ +#define liblldb_SearchFilter_h_ + +#include "lldb/Core/FileSpecList.h" +#include "lldb/Utility/StructuredData.h" + +#include "lldb/Utility/FileSpec.h" +#include "lldb/lldb-forward.h" + +#include <stdint.h> + +namespace lldb_private { +class Address; +class Breakpoint; +class CompileUnit; +class Status; +class Function; +class ModuleList; +class SearchFilter; +class Stream; +class SymbolContext; +class Target; +} + +namespace lldb_private { + +/// \class Searcher SearchFilter.h "lldb/Core/SearchFilter.h" Class that is +/// driven by the SearchFilter to search the SymbolContext space of the target +/// program. + +/// General Outline: +/// Provides the callback and search depth for the SearchFilter search. + +class Searcher { +public: + enum CallbackReturn { + eCallbackReturnStop = 0, // Stop the iteration + eCallbackReturnContinue, // Continue the iteration + eCallbackReturnPop // Pop one level up and continue iterating + }; + + Searcher(); + + virtual ~Searcher(); + + virtual CallbackReturn SearchCallback(SearchFilter &filter, + SymbolContext &context, + Address *addr) = 0; + + virtual lldb::SearchDepth GetDepth() = 0; + + /// Prints a canonical description for the searcher to the stream \a s. + /// + /// \param[in] s + /// Stream to which the output is copied. + virtual void GetDescription(Stream *s); +}; + +/// \class SearchFilter SearchFilter.h "lldb/Core/SearchFilter.h" Class +/// descends through the SymbolContext space of the target, applying a filter +/// at each stage till it reaches the depth specified by the GetDepth method +/// of the searcher, and calls its callback at that point. + +/// General Outline: +/// Provides the callback and search depth for the SearchFilter search. +/// +/// The search is done by cooperation between the search filter and the +/// searcher. The search filter does the heavy work of recursing through the +/// SymbolContext space of the target program's symbol space. The Searcher +/// specifies the depth at which it wants its callback to be invoked. Note +/// that since the resolution of the Searcher may be greater than that of the +/// SearchFilter, before the Searcher qualifies an address it should pass it +/// to "AddressPasses." The default implementation is "Everything Passes." + +class SearchFilter { +public: + /// The basic constructor takes a Target, which gives the space to search. + /// + /// \param[in] target + /// The Target that provides the module list to search. + SearchFilter(const lldb::TargetSP &target_sp); + + SearchFilter(const lldb::TargetSP &target_sp, unsigned char filterType); + + virtual ~SearchFilter(); + + /// Call this method with a file spec to see if that spec passes the filter. + /// + /// \param[in] spec + /// The file spec to check against the filter. + /// \return + /// \b true if \a spec passes, and \b false otherwise. + virtual bool ModulePasses(const FileSpec &spec); + + /// Call this method with a Module to see if that module passes the filter. + /// + /// \param[in] module + /// The Module to check against the filter. + /// + /// \return + /// \b true if \a module passes, and \b false otherwise. + virtual bool ModulePasses(const lldb::ModuleSP &module_sp); + + /// Call this method with a Address to see if \a address passes the filter. + /// + /// \param[in] addr + /// The address to check against the filter. + /// + /// \return + /// \b true if \a address passes, and \b false otherwise. + virtual bool AddressPasses(Address &addr); + + /// Call this method with a FileSpec to see if \a file spec passes the + /// filter as the name of a compilation unit. + /// + /// \param[in] fileSpec + /// The file spec to check against the filter. + /// + /// \return + /// \b true if \a file spec passes, and \b false otherwise. + virtual bool CompUnitPasses(FileSpec &fileSpec); + + /// Call this method with a CompileUnit to see if \a comp unit passes the + /// filter. + /// + /// \param[in] compUnit + /// The CompileUnit to check against the filter. + /// + /// \return + /// \b true if \a Comp Unit passes, and \b false otherwise. + virtual bool CompUnitPasses(CompileUnit &compUnit); + + /// Call this method with a Function to see if \a function passes the + /// filter. + /// + /// \param[in] function + /// The Functions to check against the filter. + /// + /// \return + /// \b true if \a function passes, and \b false otherwise. + virtual bool FunctionPasses(Function &function); + + /// Call this method to do the search using the Searcher. + /// + /// \param[in] searcher + /// The searcher to drive with this search. + /// + virtual void Search(Searcher &searcher); + + /// Call this method to do the search using the Searcher in the module list + /// \a modules. + /// + /// \param[in] searcher + /// The searcher to drive with this search. + /// + /// \param[in] modules + /// The module list within which to restrict the search. + /// + virtual void SearchInModuleList(Searcher &searcher, ModuleList &modules); + + /// This determines which items are REQUIRED for the filter to pass. For + /// instance, if you are filtering by Compilation Unit, obviously symbols + /// that have no compilation unit can't pass So return eSymbolContextCU and + /// search callbacks can then short cut the search to avoid looking at + /// things that obviously won't pass. + /// + /// \return + /// The required elements for the search, which is an or'ed together + /// set of lldb:SearchContextItem enum's. + /// + virtual uint32_t GetFilterRequiredItems(); + + /// Prints a canonical description for the search filter to the stream \a s. + /// + /// \param[in] s + /// Stream to which the output is copied. + virtual void GetDescription(Stream *s); + + /// Standard "Dump" method. At present it does nothing. + virtual void Dump(Stream *s) const; + + lldb::SearchFilterSP CopyForBreakpoint(Breakpoint &breakpoint); + + static lldb::SearchFilterSP + CreateFromStructuredData(Target &target, + const StructuredData::Dictionary &data_dict, + Status &error); + + virtual StructuredData::ObjectSP SerializeToStructuredData() { + return StructuredData::ObjectSP(); + } + + static const char *GetSerializationKey() { return "SearchFilter"; } + + static const char *GetSerializationSubclassKey() { return "Type"; } + + static const char *GetSerializationSubclassOptionsKey() { return "Options"; } + + enum FilterTy { + Unconstrained = 0, + Exception, + ByModule, + ByModules, + ByModulesAndCU, + LastKnownFilterType = ByModulesAndCU, + UnknownFilter + }; + + static const char *g_ty_to_name[LastKnownFilterType + 2]; + + enum FilterTy GetFilterTy() { + if (SubclassID > FilterTy::LastKnownFilterType) + return FilterTy::UnknownFilter; + else + return (enum FilterTy)SubclassID; + } + + const char *GetFilterName() { return FilterTyToName(GetFilterTy()); } + + static const char *FilterTyToName(enum FilterTy); + + static FilterTy NameToFilterTy(llvm::StringRef name); + +protected: + // Serialization of SearchFilter options: + enum OptionNames { ModList = 0, CUList, LanguageName, LastOptionName }; + static const char *g_option_names[LastOptionName]; + + static const char *GetKey(enum OptionNames enum_value) { + return g_option_names[enum_value]; + } + + StructuredData::DictionarySP + WrapOptionsDict(StructuredData::DictionarySP options_dict_sp); + + void SerializeFileSpecList(StructuredData::DictionarySP &options_dict_sp, + OptionNames name, FileSpecList &file_list); + + // These are utility functions to assist with the search iteration. They are + // used by the default Search method. + + Searcher::CallbackReturn DoModuleIteration(const SymbolContext &context, + Searcher &searcher); + + Searcher::CallbackReturn DoModuleIteration(const lldb::ModuleSP &module_sp, + Searcher &searcher); + + Searcher::CallbackReturn DoCUIteration(const lldb::ModuleSP &module_sp, + const SymbolContext &context, + Searcher &searcher); + + Searcher::CallbackReturn DoFunctionIteration(Function *function, + const SymbolContext &context, + Searcher &searcher); + + virtual lldb::SearchFilterSP DoCopyForBreakpoint(Breakpoint &breakpoint) = 0; + + void SetTarget(lldb::TargetSP &target_sp) { m_target_sp = target_sp; } + + lldb::TargetSP + m_target_sp; // Every filter has to be associated with a target for + // now since you need a starting place for the search. +private: + unsigned char SubclassID; +}; + +/// \class SearchFilterForUnconstrainedSearches SearchFilter.h +/// "lldb/Core/SearchFilter.h" This is a SearchFilter that searches through +/// all modules. It also consults the +/// Target::ModuleIsExcludedForUnconstrainedSearches. +class SearchFilterForUnconstrainedSearches : public SearchFilter { +public: + SearchFilterForUnconstrainedSearches(const lldb::TargetSP &target_sp) + : SearchFilter(target_sp, FilterTy::Unconstrained) {} + + ~SearchFilterForUnconstrainedSearches() override = default; + + bool ModulePasses(const FileSpec &module_spec) override; + + bool ModulePasses(const lldb::ModuleSP &module_sp) override; + + static lldb::SearchFilterSP + CreateFromStructuredData(Target &target, + const StructuredData::Dictionary &data_dict, + Status &error); + + StructuredData::ObjectSP SerializeToStructuredData() override; + +protected: + lldb::SearchFilterSP DoCopyForBreakpoint(Breakpoint &breakpoint) override; +}; + +/// \class SearchFilterByModule SearchFilter.h "lldb/Core/SearchFilter.h" This +/// is a SearchFilter that restricts the search to a given module. + +class SearchFilterByModule : public SearchFilter { +public: + /// The basic constructor takes a Target, which gives the space to search, + /// and the module to restrict the search to. + /// + /// \param[in] target + /// The Target that provides the module list to search. + /// + /// \param[in] module + /// The Module that limits the search. + SearchFilterByModule(const lldb::TargetSP &targetSP, const FileSpec &module); + + ~SearchFilterByModule() override; + + bool ModulePasses(const lldb::ModuleSP &module_sp) override; + + bool ModulePasses(const FileSpec &spec) override; + + bool AddressPasses(Address &address) override; + + bool CompUnitPasses(FileSpec &fileSpec) override; + + bool CompUnitPasses(CompileUnit &compUnit) override; + + void GetDescription(Stream *s) override; + + uint32_t GetFilterRequiredItems() override; + + void Dump(Stream *s) const override; + + void Search(Searcher &searcher) override; + + static lldb::SearchFilterSP + CreateFromStructuredData(Target &target, + const StructuredData::Dictionary &data_dict, + Status &error); + + StructuredData::ObjectSP SerializeToStructuredData() override; + +protected: + lldb::SearchFilterSP DoCopyForBreakpoint(Breakpoint &breakpoint) override; + +private: + FileSpec m_module_spec; +}; + +class SearchFilterByModuleList : public SearchFilter { +public: + /// The basic constructor takes a Target, which gives the space to search, + /// and the module list to restrict the search to. + /// + /// \param[in] target + /// The Target that provides the module list to search. + /// + /// \param[in] module + /// The Module that limits the search. + SearchFilterByModuleList(const lldb::TargetSP &targetSP, + const FileSpecList &module_list); + + SearchFilterByModuleList(const lldb::TargetSP &targetSP, + const FileSpecList &module_list, + enum FilterTy filter_ty); + + ~SearchFilterByModuleList() override; + + SearchFilterByModuleList &operator=(const SearchFilterByModuleList &rhs); + + bool ModulePasses(const lldb::ModuleSP &module_sp) override; + + bool ModulePasses(const FileSpec &spec) override; + + bool AddressPasses(Address &address) override; + + bool CompUnitPasses(FileSpec &fileSpec) override; + + bool CompUnitPasses(CompileUnit &compUnit) override; + + void GetDescription(Stream *s) override; + + uint32_t GetFilterRequiredItems() override; + + void Dump(Stream *s) const override; + + void Search(Searcher &searcher) override; + + static lldb::SearchFilterSP + CreateFromStructuredData(Target &target, + const StructuredData::Dictionary &data_dict, + Status &error); + + StructuredData::ObjectSP SerializeToStructuredData() override; + + void SerializeUnwrapped(StructuredData::DictionarySP &options_dict_sp); + +protected: + lldb::SearchFilterSP DoCopyForBreakpoint(Breakpoint &breakpoint) override; + +protected: + FileSpecList m_module_spec_list; +}; + +class SearchFilterByModuleListAndCU : public SearchFilterByModuleList { +public: + /// The basic constructor takes a Target, which gives the space to search, + /// and the module list to restrict the search to. + /// + /// \param[in] target + /// The Target that provides the module list to search. + /// + /// \param[in] module + /// The Module that limits the search. + SearchFilterByModuleListAndCU(const lldb::TargetSP &targetSP, + const FileSpecList &module_list, + const FileSpecList &cu_list); + + SearchFilterByModuleListAndCU(const SearchFilterByModuleListAndCU &rhs); + + ~SearchFilterByModuleListAndCU() override; + + SearchFilterByModuleListAndCU & + operator=(const SearchFilterByModuleListAndCU &rhs); + + bool AddressPasses(Address &address) override; + + bool CompUnitPasses(FileSpec &fileSpec) override; + + bool CompUnitPasses(CompileUnit &compUnit) override; + + void GetDescription(Stream *s) override; + + uint32_t GetFilterRequiredItems() override; + + void Dump(Stream *s) const override; + + void Search(Searcher &searcher) override; + + static lldb::SearchFilterSP + CreateFromStructuredData(Target &target, + const StructuredData::Dictionary &data_dict, + Status &error); + + StructuredData::ObjectSP SerializeToStructuredData() override; + +protected: + lldb::SearchFilterSP DoCopyForBreakpoint(Breakpoint &breakpoint) override; + +private: + FileSpecList m_cu_spec_list; +}; + +} // namespace lldb_private + +#endif // liblldb_SearchFilter_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Section.h b/contrib/llvm-project/lldb/include/lldb/Core/Section.h new file mode 100644 index 000000000000..509a0767be1d --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/Section.h @@ -0,0 +1,275 @@ +//===-- Section.h -----------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Section_h_ +#define liblldb_Section_h_ + +#include "lldb/Core/ModuleChild.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Flags.h" +#include "lldb/Utility/UserID.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-types.h" + +#include <memory> +#include <vector> + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class Address; +class DataExtractor; +class ObjectFile; +class Section; +class Stream; +class Target; + +class SectionList { +public: + typedef std::vector<lldb::SectionSP> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + const_iterator begin() const { return m_sections.begin(); } + const_iterator end() const { return m_sections.end(); } + const_iterator begin() { return m_sections.begin(); } + const_iterator end() { return m_sections.end(); } + + /// Create an empty list. + SectionList() = default; + + SectionList &operator=(const SectionList &rhs); + + size_t AddSection(const lldb::SectionSP §ion_sp); + + size_t AddUniqueSection(const lldb::SectionSP §ion_sp); + + size_t FindSectionIndex(const Section *sect); + + bool ContainsSection(lldb::user_id_t sect_id) const; + + void Dump(Stream *s, Target *target, bool show_header, uint32_t depth) const; + + lldb::SectionSP FindSectionByName(ConstString section_dstr) const; + + lldb::SectionSP FindSectionByID(lldb::user_id_t sect_id) const; + + lldb::SectionSP FindSectionByType(lldb::SectionType sect_type, + bool check_children, + size_t start_idx = 0) const; + + lldb::SectionSP + FindSectionContainingFileAddress(lldb::addr_t addr, + uint32_t depth = UINT32_MAX) const; + + // Get the number of sections in this list only + size_t GetSize() const { return m_sections.size(); } + + // Get the number of sections in this list, and any contained child sections + size_t GetNumSections(uint32_t depth) const; + + bool ReplaceSection(lldb::user_id_t sect_id, + const lldb::SectionSP §ion_sp, + uint32_t depth = UINT32_MAX); + + // Warning, this can be slow as it's removing items from a std::vector. + bool DeleteSection(size_t idx); + + lldb::SectionSP GetSectionAtIndex(size_t idx) const; + + size_t Slide(lldb::addr_t slide_amount, bool slide_children); + + void Clear() { m_sections.clear(); } + +protected: + collection m_sections; +}; + +class Section : public std::enable_shared_from_this<Section>, + public ModuleChild, + public UserID, + public Flags { +public: + // Create a root section (one that has no parent) + Section(const lldb::ModuleSP &module_sp, ObjectFile *obj_file, + lldb::user_id_t sect_id, ConstString name, + lldb::SectionType sect_type, lldb::addr_t file_vm_addr, + lldb::addr_t vm_size, lldb::offset_t file_offset, + lldb::offset_t file_size, uint32_t log2align, uint32_t flags, + uint32_t target_byte_size = 1); + + // Create a section that is a child of parent_section_sp + Section(const lldb::SectionSP &parent_section_sp, // NULL for top level + // sections, non-NULL for + // child sections + const lldb::ModuleSP &module_sp, ObjectFile *obj_file, + lldb::user_id_t sect_id, ConstString name, + lldb::SectionType sect_type, lldb::addr_t file_vm_addr, + lldb::addr_t vm_size, lldb::offset_t file_offset, + lldb::offset_t file_size, uint32_t log2align, uint32_t flags, + uint32_t target_byte_size = 1); + + ~Section(); + + static int Compare(const Section &a, const Section &b); + + bool ContainsFileAddress(lldb::addr_t vm_addr) const; + + SectionList &GetChildren() { return m_children; } + + const SectionList &GetChildren() const { return m_children; } + + void Dump(Stream *s, Target *target, uint32_t depth) const; + + void DumpName(Stream *s) const; + + lldb::addr_t GetLoadBaseAddress(Target *target) const; + + bool ResolveContainedAddress(lldb::addr_t offset, Address &so_addr, + bool allow_section_end = false) const; + + lldb::offset_t GetFileOffset() const { return m_file_offset; } + + void SetFileOffset(lldb::offset_t file_offset) { + m_file_offset = file_offset; + } + + lldb::offset_t GetFileSize() const { return m_file_size; } + + void SetFileSize(lldb::offset_t file_size) { m_file_size = file_size; } + + lldb::addr_t GetFileAddress() const; + + bool SetFileAddress(lldb::addr_t file_addr); + + lldb::addr_t GetOffset() const; + + lldb::addr_t GetByteSize() const { return m_byte_size; } + + void SetByteSize(lldb::addr_t byte_size) { m_byte_size = byte_size; } + + bool IsFake() const { return m_fake; } + + void SetIsFake(bool fake) { m_fake = fake; } + + bool IsEncrypted() const { return m_encrypted; } + + void SetIsEncrypted(bool b) { m_encrypted = b; } + + bool IsDescendant(const Section *section); + + ConstString GetName() const { return m_name; } + + bool Slide(lldb::addr_t slide_amount, bool slide_children); + + lldb::SectionType GetType() const { return m_type; } + + const char *GetTypeAsCString() const; + + lldb::SectionSP GetParent() const { return m_parent_wp.lock(); } + + bool IsThreadSpecific() const { return m_thread_specific; } + + void SetIsThreadSpecific(bool b) { m_thread_specific = b; } + + /// Get the permissions as OR'ed bits from lldb::Permissions + uint32_t GetPermissions() const; + + /// Set the permissions using bits OR'ed from lldb::Permissions + void SetPermissions(uint32_t permissions); + + ObjectFile *GetObjectFile() { return m_obj_file; } + const ObjectFile *GetObjectFile() const { return m_obj_file; } + + /// Read the section data from the object file that the section + /// resides in. + /// + /// \param[in] dst + /// Where to place the data + /// + /// \param[in] dst_len + /// How many bytes of section data to read + /// + /// \param[in] offset + /// The offset in bytes within this section's data at which to + /// start copying data from. + /// + /// \return + /// The number of bytes read from the section, or zero if the + /// section has no data or \a offset is not a valid offset + /// in this section. + lldb::offset_t GetSectionData(void *dst, lldb::offset_t dst_len, + lldb::offset_t offset = 0); + + /// Get the shared reference to the section data from the object + /// file that the section resides in. No copies of the data will be + /// make unless the object file has been read from memory. If the + /// object file is on disk, it will shared the mmap data for the + /// entire object file. + /// + /// \param[in] data + /// Where to place the data, address byte size, and byte order + /// + /// \return + /// The number of bytes read from the section, or zero if the + /// section has no data or \a offset is not a valid offset + /// in this section. + lldb::offset_t GetSectionData(DataExtractor &data); + + uint32_t GetLog2Align() { return m_log2align; } + + void SetLog2Align(uint32_t align) { m_log2align = align; } + + // Get the number of host bytes required to hold a target byte + uint32_t GetTargetByteSize() const { return m_target_byte_size; } + + bool IsRelocated() const { return m_relocated; } + + void SetIsRelocated(bool b) { m_relocated = b; } + +protected: + ObjectFile *m_obj_file; // The object file that data for this section should + // be read from + lldb::SectionType m_type; // The type of this section + lldb::SectionWP m_parent_wp; // Weak pointer to parent section + ConstString m_name; // Name of this section + lldb::addr_t m_file_addr; // The absolute file virtual address range of this + // section if m_parent == NULL, + // offset from parent file virtual address if m_parent != NULL + lldb::addr_t m_byte_size; // Size in bytes that this section will occupy in + // memory at runtime + lldb::offset_t m_file_offset; // Object file offset (if any) + lldb::offset_t m_file_size; // Object file size (can be smaller than + // m_byte_size for zero filled sections...) + uint32_t m_log2align; // log_2(align) of the section (i.e. section has to be + // aligned to 2^m_log2align) + SectionList m_children; // Child sections + bool m_fake : 1, // If true, then this section only can contain the address if + // one of its + // children contains an address. This allows for gaps between the + // children that are contained in the address range for this section, but + // do not produce hits unless the children contain the address. + m_encrypted : 1, // Set to true if the contents are encrypted + m_thread_specific : 1, // This section is thread specific + m_readable : 1, // If this section has read permissions + m_writable : 1, // If this section has write permissions + m_executable : 1, // If this section has executable permissions + m_relocated : 1; // If this section has had relocations applied + uint32_t m_target_byte_size; // Some architectures have non-8-bit byte size. + // This is specified as + // as a multiple number of a host bytes +private: + DISALLOW_COPY_AND_ASSIGN(Section); +}; + +} // namespace lldb_private + +#endif // liblldb_Section_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/SourceManager.h b/contrib/llvm-project/lldb/include/lldb/Core/SourceManager.h new file mode 100644 index 000000000000..bca817750d8d --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/SourceManager.h @@ -0,0 +1,167 @@ +//===-- SourceManager.h -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_SourceManager_h_ +#define liblldb_SourceManager_h_ + +#include "lldb/Utility/FileSpec.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-forward.h" + +#include "llvm/Support/Chrono.h" + +#include <cstdint> +#include <map> +#include <memory> +#include <stddef.h> +#include <string> +#include <vector> + +namespace lldb_private { +class RegularExpression; +class Stream; +class SymbolContextList; +class Target; + +class SourceManager { +public: + class File { + friend bool operator==(const SourceManager::File &lhs, + const SourceManager::File &rhs); + + public: + File(const FileSpec &file_spec, Target *target); + File(const FileSpec &file_spec, lldb::DebuggerSP debugger_sp); + ~File() = default; + + void UpdateIfNeeded(); + + size_t DisplaySourceLines(uint32_t line, llvm::Optional<size_t> column, + uint32_t context_before, uint32_t context_after, + Stream *s); + void FindLinesMatchingRegex(RegularExpression ®ex, uint32_t start_line, + uint32_t end_line, + std::vector<uint32_t> &match_lines); + + bool GetLine(uint32_t line_no, std::string &buffer); + + uint32_t GetLineOffset(uint32_t line); + + bool LineIsValid(uint32_t line); + + bool FileSpecMatches(const FileSpec &file_spec); + + const FileSpec &GetFileSpec() { return m_file_spec; } + + uint32_t GetSourceMapModificationID() const { return m_source_map_mod_id; } + + const char *PeekLineData(uint32_t line); + + uint32_t GetLineLength(uint32_t line, bool include_newline_chars); + + uint32_t GetNumLines(); + + protected: + bool CalculateLineOffsets(uint32_t line = UINT32_MAX); + + FileSpec m_file_spec_orig; // The original file spec that was used (can be + // different from m_file_spec) + FileSpec m_file_spec; // The actually file spec being used (if the target + // has source mappings, this might be different from + // m_file_spec_orig) + + // Keep the modification time that this file data is valid for + llvm::sys::TimePoint<> m_mod_time; + + // If the target uses path remappings, be sure to clear our notion of a + // source file if the path modification ID changes + uint32_t m_source_map_mod_id = 0; + lldb::DataBufferSP m_data_sp; + typedef std::vector<uint32_t> LineOffsets; + LineOffsets m_offsets; + lldb::DebuggerWP m_debugger_wp; + + private: + void CommonInitializer(const FileSpec &file_spec, Target *target); + }; + + typedef std::shared_ptr<File> FileSP; + + // The SourceFileCache class separates the source manager from the cache of + // source files, so the cache can be stored in the Debugger, but the source + // managers can be per target. + class SourceFileCache { + public: + SourceFileCache() = default; + ~SourceFileCache() = default; + + void AddSourceFile(const FileSP &file_sp); + FileSP FindSourceFile(const FileSpec &file_spec) const; + + protected: + typedef std::map<FileSpec, FileSP> FileCache; + FileCache m_file_cache; + }; + + // Constructors and Destructors + // A source manager can be made with a non-null target, in which case it can + // use the path remappings to find + // source files that are not in their build locations. With no target it + // won't be able to do this. + SourceManager(const lldb::DebuggerSP &debugger_sp); + SourceManager(const lldb::TargetSP &target_sp); + + ~SourceManager(); + + FileSP GetLastFile() { return m_last_file_sp; } + + size_t + DisplaySourceLinesWithLineNumbers(const FileSpec &file, uint32_t line, + uint32_t column, uint32_t context_before, + uint32_t context_after, + const char *current_line_cstr, Stream *s, + const SymbolContextList *bp_locs = nullptr); + + // This variant uses the last file we visited. + size_t DisplaySourceLinesWithLineNumbersUsingLastFile( + uint32_t start_line, uint32_t count, uint32_t curr_line, uint32_t column, + const char *current_line_cstr, Stream *s, + const SymbolContextList *bp_locs = nullptr); + + size_t DisplayMoreWithLineNumbers(Stream *s, uint32_t count, bool reverse, + const SymbolContextList *bp_locs = nullptr); + + bool SetDefaultFileAndLine(const FileSpec &file_spec, uint32_t line); + + bool GetDefaultFileAndLine(FileSpec &file_spec, uint32_t &line); + + bool DefaultFileAndLineSet() { return (m_last_file_sp.get() != nullptr); } + + void FindLinesMatchingRegex(FileSpec &file_spec, RegularExpression ®ex, + uint32_t start_line, uint32_t end_line, + std::vector<uint32_t> &match_lines); + + FileSP GetFile(const FileSpec &file_spec); + +protected: + FileSP m_last_file_sp; + uint32_t m_last_line; + uint32_t m_last_count; + bool m_default_set; + lldb::TargetWP m_target_wp; + lldb::DebuggerWP m_debugger_wp; + +private: + DISALLOW_COPY_AND_ASSIGN(SourceManager); +}; + +bool operator==(const SourceManager::File &lhs, const SourceManager::File &rhs); + +} // namespace lldb_private + +#endif // liblldb_SourceManager_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/StreamAsynchronousIO.h b/contrib/llvm-project/lldb/include/lldb/Core/StreamAsynchronousIO.h new file mode 100644 index 000000000000..6237e12b7d1e --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/StreamAsynchronousIO.h @@ -0,0 +1,40 @@ +//===-- StreamAsynchronousIO.h -----------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_StreamAsynchronousIO_h_ +#define liblldb_StreamAsynchronousIO_h_ + +#include "lldb/Utility/Stream.h" + +#include <string> + +#include <stddef.h> + +namespace lldb_private { +class Debugger; + +class StreamAsynchronousIO : public Stream { +public: + StreamAsynchronousIO(Debugger &debugger, bool for_stdout); + + ~StreamAsynchronousIO() override; + + void Flush() override; + +protected: + size_t WriteImpl(const void *src, size_t src_len) override; + +private: + Debugger &m_debugger; + std::string m_data; + bool m_for_stdout; +}; + +} // namespace lldb_private + +#endif // liblldb_StreamAsynchronousIO_h diff --git a/contrib/llvm-project/lldb/include/lldb/Core/StreamBuffer.h b/contrib/llvm-project/lldb/include/lldb/Core/StreamBuffer.h new file mode 100644 index 000000000000..6c516519781f --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/StreamBuffer.h @@ -0,0 +1,54 @@ +//===-- StreamBuffer.h ------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_StreamBuffer_h_ +#define liblldb_StreamBuffer_h_ + +#include "lldb/Utility/Stream.h" +#include "llvm/ADT/SmallVector.h" +#include <stdio.h> +#include <string> + +namespace lldb_private { + +template <unsigned N> class StreamBuffer : public Stream { +public: + StreamBuffer() : Stream(0, 4, lldb::eByteOrderBig), m_packet() {} + + StreamBuffer(uint32_t flags, uint32_t addr_size, lldb::ByteOrder byte_order) + : Stream(flags, addr_size, byte_order), m_packet() {} + + ~StreamBuffer() override {} + + void Flush() override { + // Nothing to do when flushing a buffer based stream... + } + + void Clear() { m_packet.clear(); } + + // Beware, this might not be NULL terminated as you can expect from + // StringString as there may be random bits in the llvm::SmallVector. If you + // are using this class to create a C string, be sure the call PutChar ('\0') + // after you have created your string, or use StreamString. + const char *GetData() const { return m_packet.data(); } + + size_t GetSize() const { return m_packet.size(); } + +protected: + llvm::SmallVector<char, N> m_packet; + + size_t WriteImpl(const void *s, size_t length) override { + if (s && length) + m_packet.append((const char *)s, ((const char *)s) + length); + return length; + } +}; + +} // namespace lldb_private + +#endif // #ifndef liblldb_StreamBuffer_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/StreamFile.h b/contrib/llvm-project/lldb/include/lldb/Core/StreamFile.h new file mode 100644 index 000000000000..712b289aa8d9 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/StreamFile.h @@ -0,0 +1,62 @@ +//===-- StreamFile.h --------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_StreamFile_h_ +#define liblldb_StreamFile_h_ + +#include "lldb/Host/File.h" +#include "lldb/Utility/Stream.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" + +#include <stdint.h> +#include <stdio.h> + +namespace lldb_private { + +class StreamFile : public Stream { +public: + // Constructors and Destructors + StreamFile(); + + StreamFile(uint32_t flags, uint32_t addr_size, lldb::ByteOrder byte_order); + + StreamFile(int fd, bool transfer_ownership); + + StreamFile(const char *path); + + StreamFile(const char *path, File::OpenOptions options, + uint32_t permissions = lldb::eFilePermissionsFileDefault); + + StreamFile(FILE *fh, bool transfer_ownership); + + StreamFile(std::shared_ptr<File> file) : m_file_sp(file) { assert(file); }; + + ~StreamFile() override; + + File &GetFile() { return *m_file_sp; } + + const File &GetFile() const { return *m_file_sp; } + + std::shared_ptr<File> GetFileSP() { return m_file_sp; } + + void Flush() override; + + +protected: + // Classes that inherit from StreamFile can see and modify these + std::shared_ptr<File> m_file_sp; // never NULL + size_t WriteImpl(const void *s, size_t length) override; + +private: + DISALLOW_COPY_AND_ASSIGN(StreamFile); +}; + +} // namespace lldb_private + +#endif // liblldb_StreamFile_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/StructuredDataImpl.h b/contrib/llvm-project/lldb/include/lldb/Core/StructuredDataImpl.h new file mode 100644 index 000000000000..c66e4736dc26 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/StructuredDataImpl.h @@ -0,0 +1,156 @@ +//===-- StructuredDataImpl.h ------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_StructuredDataImpl_h_ +#define liblldb_StructuredDataImpl_h_ + +#include "lldb/Target/StructuredDataPlugin.h" +#include "lldb/Utility/Event.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/Stream.h" +#include "lldb/Utility/StructuredData.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "llvm/ADT/StringRef.h" + +#pragma mark-- +#pragma mark StructuredDataImpl + +namespace lldb_private { + +class StructuredDataImpl { +public: + StructuredDataImpl() : m_plugin_wp(), m_data_sp() {} + + StructuredDataImpl(const StructuredDataImpl &rhs) = default; + + StructuredDataImpl(const lldb::EventSP &event_sp) + : m_plugin_wp( + EventDataStructuredData::GetPluginFromEvent(event_sp.get())), + m_data_sp(EventDataStructuredData::GetObjectFromEvent(event_sp.get())) { + } + + ~StructuredDataImpl() = default; + + StructuredDataImpl &operator=(const StructuredDataImpl &rhs) = default; + + bool IsValid() const { return m_data_sp.get() != nullptr; } + + void Clear() { + m_plugin_wp.reset(); + m_data_sp.reset(); + } + + Status GetAsJSON(Stream &stream) const { + Status error; + + if (!m_data_sp) { + error.SetErrorString("No structured data."); + return error; + } + + llvm::json::OStream s(stream.AsRawOstream()); + m_data_sp->Serialize(s); + return error; + } + + Status GetDescription(Stream &stream) const { + Status error; + + if (!m_data_sp) { + error.SetErrorString("Cannot pretty print structured data: " + "no data to print."); + return error; + } + + // Grab the plugin. + auto plugin_sp = lldb::StructuredDataPluginSP(m_plugin_wp); + if (!plugin_sp) { + error.SetErrorString("Cannot pretty print structured data: " + "plugin doesn't exist."); + return error; + } + + // Get the data's description. + return plugin_sp->GetDescription(m_data_sp, stream); + } + + StructuredData::ObjectSP GetObjectSP() { return m_data_sp; } + + void SetObjectSP(const StructuredData::ObjectSP &obj) { m_data_sp = obj; } + + lldb::StructuredDataType GetType() const { + return (m_data_sp ? m_data_sp->GetType() : + lldb::eStructuredDataTypeInvalid); + } + + size_t GetSize() const { + if (!m_data_sp) + return 0; + + if (m_data_sp->GetType() == lldb::eStructuredDataTypeDictionary) { + auto dict = m_data_sp->GetAsDictionary(); + return (dict->GetSize()); + } else if (m_data_sp->GetType() == lldb::eStructuredDataTypeArray) { + auto array = m_data_sp->GetAsArray(); + return (array->GetSize()); + } else + return 0; + } + + StructuredData::ObjectSP GetValueForKey(const char *key) const { + if (m_data_sp) { + auto dict = m_data_sp->GetAsDictionary(); + if (dict) + return dict->GetValueForKey(llvm::StringRef(key)); + } + return StructuredData::ObjectSP(); + } + + StructuredData::ObjectSP GetItemAtIndex(size_t idx) const { + if (m_data_sp) { + auto array = m_data_sp->GetAsArray(); + if (array) + return array->GetItemAtIndex(idx); + } + return StructuredData::ObjectSP(); + } + + uint64_t GetIntegerValue(uint64_t fail_value = 0) const { + return (m_data_sp ? m_data_sp->GetIntegerValue(fail_value) : fail_value); + } + + double GetFloatValue(double fail_value = 0.0) const { + return (m_data_sp ? m_data_sp->GetFloatValue(fail_value) : fail_value); + } + + bool GetBooleanValue(bool fail_value = false) const { + return (m_data_sp ? m_data_sp->GetBooleanValue(fail_value) : fail_value); + } + + size_t GetStringValue(char *dst, size_t dst_len) const { + if (!m_data_sp) + return 0; + + llvm::StringRef result = m_data_sp->GetStringValue(); + if (result.empty()) + return 0; + + if (!dst || !dst_len) { + char s[1]; + return (::snprintf(s, 1, "%s", result.data())); + } + return (::snprintf(dst, dst_len, "%s", result.data())); + } + +private: + lldb::StructuredDataPluginWP m_plugin_wp; + StructuredData::ObjectSP m_data_sp; +}; +} // namespace lldb_private +#endif diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeDenseMap.h b/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeDenseMap.h new file mode 100644 index 000000000000..c485b91acb47 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeDenseMap.h @@ -0,0 +1,65 @@ +//===-- ThreadSafeDenseMap.h ------------------------------------------*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ThreadSafeDenseMap_h_ +#define liblldb_ThreadSafeDenseMap_h_ + +#include <mutex> + +#include "llvm/ADT/DenseMap.h" + + +namespace lldb_private { + +template <typename _KeyType, typename _ValueType, + typename _MutexType = std::mutex> +class ThreadSafeDenseMap { +public: + typedef llvm::DenseMap<_KeyType, _ValueType> LLVMMapType; + + ThreadSafeDenseMap(unsigned map_initial_capacity = 0) + : m_map(map_initial_capacity), m_mutex() {} + + void Insert(_KeyType k, _ValueType v) { + std::lock_guard<_MutexType> guard(m_mutex); + m_map.insert(std::make_pair(k, v)); + } + + void Erase(_KeyType k) { + std::lock_guard<_MutexType> guard(m_mutex); + m_map.erase(k); + } + + _ValueType Lookup(_KeyType k) { + std::lock_guard<_MutexType> guard(m_mutex); + return m_map.lookup(k); + } + + bool Lookup(_KeyType k, _ValueType &v) { + std::lock_guard<_MutexType> guard(m_mutex); + auto iter = m_map.find(k), end = m_map.end(); + if (iter == end) + return false; + v = iter->second; + return true; + } + + void Clear() { + std::lock_guard<_MutexType> guard(m_mutex); + m_map.clear(); + } + +protected: + LLVMMapType m_map; + _MutexType m_mutex; +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadSafeSTLMap_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeDenseSet.h b/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeDenseSet.h new file mode 100644 index 000000000000..fbc8d3fb02f8 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeDenseSet.h @@ -0,0 +1,55 @@ +//===-- ThreadSafeDenseSet.h ------------------------------------------*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ThreadSafeDenseSet_h_ +#define liblldb_ThreadSafeDenseSet_h_ + +#include <mutex> + +#include "llvm/ADT/DenseSet.h" + + +namespace lldb_private { + +template <typename _ElementType, typename _MutexType = std::mutex> +class ThreadSafeDenseSet { +public: + typedef llvm::DenseSet<_ElementType> LLVMSetType; + + ThreadSafeDenseSet(unsigned set_initial_capacity = 0) + : m_set(set_initial_capacity), m_mutex() {} + + void Insert(_ElementType e) { + std::lock_guard<_MutexType> guard(m_mutex); + m_set.insert(e); + } + + void Erase(_ElementType e) { + std::lock_guard<_MutexType> guard(m_mutex); + m_set.erase(e); + } + + bool Lookup(_ElementType e) { + std::lock_guard<_MutexType> guard(m_mutex); + return (m_set.count(e) > 0); + } + + void Clear() { + std::lock_guard<_MutexType> guard(m_mutex); + m_set.clear(); + } + +protected: + LLVMSetType m_set; + _MutexType m_mutex; +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadSafeDenseSet_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeSTLMap.h b/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeSTLMap.h new file mode 100644 index 000000000000..df0208cd49b3 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeSTLMap.h @@ -0,0 +1,128 @@ +//===-- ThreadSafeSTLMap.h --------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ThreadSafeSTLMap_h_ +#define liblldb_ThreadSafeSTLMap_h_ + +#include <map> +#include <mutex> + +#include "lldb/lldb-defines.h" + +namespace lldb_private { + +template <typename _Key, typename _Tp> class ThreadSafeSTLMap { +public: + typedef std::map<_Key, _Tp> collection; + typedef typename collection::iterator iterator; + typedef typename collection::const_iterator const_iterator; + // Constructors and Destructors + ThreadSafeSTLMap() : m_collection(), m_mutex() {} + + ~ThreadSafeSTLMap() {} + + bool IsEmpty() const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_collection.empty(); + } + + void Clear() { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_collection.clear(); + } + + size_t Erase(const _Key &key) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return EraseNoLock(key); + } + + size_t EraseNoLock(const _Key &key) { return m_collection.erase(key); } + + bool GetValueForKey(const _Key &key, _Tp &value) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return GetValueForKeyNoLock(key, value); + } + + // Call this if you have already manually locked the mutex using the + // GetMutex() accessor + bool GetValueForKeyNoLock(const _Key &key, _Tp &value) const { + const_iterator pos = m_collection.find(key); + if (pos != m_collection.end()) { + value = pos->second; + return true; + } + return false; + } + + bool GetFirstKeyForValue(const _Tp &value, _Key &key) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return GetFirstKeyForValueNoLock(value, key); + } + + bool GetFirstKeyForValueNoLock(const _Tp &value, _Key &key) const { + const_iterator pos, end = m_collection.end(); + for (pos = m_collection.begin(); pos != end; ++pos) { + if (pos->second == value) { + key = pos->first; + return true; + } + } + return false; + } + + bool LowerBound(const _Key &key, _Key &match_key, _Tp &match_value, + bool decrement_if_not_equal) const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return LowerBoundNoLock(key, match_key, match_value, + decrement_if_not_equal); + } + + bool LowerBoundNoLock(const _Key &key, _Key &match_key, _Tp &match_value, + bool decrement_if_not_equal) const { + const_iterator pos = m_collection.lower_bound(key); + if (pos != m_collection.end()) { + match_key = pos->first; + if (decrement_if_not_equal && key != match_key && + pos != m_collection.begin()) { + --pos; + match_key = pos->first; + } + match_value = pos->second; + return true; + } + return false; + } + + iterator lower_bound_unsafe(const _Key &key) { + return m_collection.lower_bound(key); + } + + void SetValueForKey(const _Key &key, const _Tp &value) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + SetValueForKeyNoLock(key, value); + } + + // Call this if you have already manually locked the mutex using the + // GetMutex() accessor + void SetValueForKeyNoLock(const _Key &key, const _Tp &value) { + m_collection[key] = value; + } + + std::recursive_mutex &GetMutex() { return m_mutex; } + +private: + collection m_collection; + mutable std::recursive_mutex m_mutex; + + // For ThreadSafeSTLMap only + DISALLOW_COPY_AND_ASSIGN(ThreadSafeSTLMap); +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadSafeSTLMap_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeSTLVector.h b/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeSTLVector.h new file mode 100644 index 000000000000..e1666a69ef7e --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeSTLVector.h @@ -0,0 +1,72 @@ +//===-- ThreadSafeSTLVector.h ------------------------------------*- C++ +//-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ThreadSafeSTLVector_h_ +#define liblldb_ThreadSafeSTLVector_h_ + +#include <mutex> +#include <vector> + +#include "lldb/lldb-defines.h" + +namespace lldb_private { + +template <typename _Object> class ThreadSafeSTLVector { +public: + typedef std::vector<_Object> collection; + typedef typename collection::iterator iterator; + typedef typename collection::const_iterator const_iterator; + // Constructors and Destructors + ThreadSafeSTLVector() : m_collection(), m_mutex() {} + + ~ThreadSafeSTLVector() = default; + + bool IsEmpty() const { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_collection.empty(); + } + + void Clear() { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_collection.clear(); + } + + size_t GetCount() { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_collection.size(); + } + + void AppendObject(_Object &object) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_collection.push_back(object); + } + + _Object GetObject(size_t index) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return m_collection.at(index); + } + + void SetObject(size_t index, const _Object &object) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_collection.at(index) = object; + } + + std::recursive_mutex &GetMutex() { return m_mutex; } + +private: + collection m_collection; + mutable std::recursive_mutex m_mutex; + + // For ThreadSafeSTLVector only + DISALLOW_COPY_AND_ASSIGN(ThreadSafeSTLVector); +}; + +} // namespace lldb_private + +#endif // liblldb_ThreadSafeSTLVector_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeValue.h b/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeValue.h new file mode 100644 index 000000000000..91f96814363f --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ThreadSafeValue.h @@ -0,0 +1,61 @@ +//===-- ThreadSafeValue.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ThreadSafeValue_h_ +#define liblldb_ThreadSafeValue_h_ + + +#include <mutex> + +#include "lldb/lldb-defines.h" + +namespace lldb_private { + +template <class T> class ThreadSafeValue { +public: + // Constructors and Destructors + ThreadSafeValue() : m_value(), m_mutex() {} + + ThreadSafeValue(const T &value) : m_value(value), m_mutex() {} + + ~ThreadSafeValue() {} + + T GetValue() const { + T value; + { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + value = m_value; + } + return value; + } + + // Call this if you have already manually locked the mutex using the + // GetMutex() accessor + const T &GetValueNoLock() const { return m_value; } + + void SetValue(const T &value) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_value = value; + } + + // Call this if you have already manually locked the mutex using the + // GetMutex() accessor + void SetValueNoLock(const T &value) { m_value = value; } + + std::recursive_mutex &GetMutex() { return m_mutex; } + +private: + T m_value; + mutable std::recursive_mutex m_mutex; + + // For ThreadSafeValue only + DISALLOW_COPY_AND_ASSIGN(ThreadSafeValue); +}; + +} // namespace lldb_private +#endif // liblldb_ThreadSafeValue_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/UniqueCStringMap.h b/contrib/llvm-project/lldb/include/lldb/Core/UniqueCStringMap.h new file mode 100644 index 000000000000..9949bd45f4fa --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/UniqueCStringMap.h @@ -0,0 +1,207 @@ +//===-- UniqueCStringMap.h --------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_UniqueCStringMap_h_ +#define liblldb_UniqueCStringMap_h_ + +#include <algorithm> +#include <vector> + +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/RegularExpression.h" + +namespace lldb_private { + +// Templatized uniqued string map. +// +// This map is useful for mapping unique C string names to values of type T. +// Each "const char *" name added must be unique for a given +// C string value. ConstString::GetCString() can provide such strings. +// Any other string table that has guaranteed unique values can also be used. +template <typename T> class UniqueCStringMap { +public: + struct Entry { + Entry(ConstString cstr, const T &v) : cstring(cstr), value(v) {} + + ConstString cstring; + T value; + }; + + // Call this function multiple times to add a bunch of entries to this map, + // then later call UniqueCStringMap<T>::Sort() before doing any searches by + // name. + void Append(ConstString unique_cstr, const T &value) { + m_map.push_back(typename UniqueCStringMap<T>::Entry(unique_cstr, value)); + } + + void Append(const Entry &e) { m_map.push_back(e); } + + void Clear() { m_map.clear(); } + + // Get an entries by index in a variety of forms. + // + // The caller is responsible for ensuring that the collection does not change + // during while using the returned values. + bool GetValueAtIndex(uint32_t idx, T &value) const { + if (idx < m_map.size()) { + value = m_map[idx].value; + return true; + } + return false; + } + + ConstString GetCStringAtIndexUnchecked(uint32_t idx) const { + return m_map[idx].cstring; + } + + // Use this function if you have simple types in your map that you can easily + // copy when accessing values by index. + T GetValueAtIndexUnchecked(uint32_t idx) const { return m_map[idx].value; } + + // Use this function if you have complex types in your map that you don't + // want to copy when accessing values by index. + const T &GetValueRefAtIndexUnchecked(uint32_t idx) const { + return m_map[idx].value; + } + + ConstString GetCStringAtIndex(uint32_t idx) const { + return ((idx < m_map.size()) ? m_map[idx].cstring : ConstString()); + } + + // Find the value for the unique string in the map. + // + // Return the value for \a unique_cstr if one is found, return \a fail_value + // otherwise. This method works well for simple type + // T values and only if there is a sensible failure value that can + // be returned and that won't match any existing values. + T Find(ConstString unique_cstr, T fail_value) const { + auto pos = llvm::lower_bound(m_map, unique_cstr, Compare()); + if (pos != m_map.end() && pos->cstring == unique_cstr) + return pos->value; + return fail_value; + } + + // Get a pointer to the first entry that matches "name". nullptr will be + // returned if there is no entry that matches "name". + // + // The caller is responsible for ensuring that the collection does not change + // during while using the returned pointer. + const Entry *FindFirstValueForName(ConstString unique_cstr) const { + auto pos = llvm::lower_bound(m_map, unique_cstr, Compare()); + if (pos != m_map.end() && pos->cstring == unique_cstr) + return &(*pos); + return nullptr; + } + + // Get a pointer to the next entry that matches "name" from a previously + // returned Entry pointer. nullptr will be returned if there is no subsequent + // entry that matches "name". + // + // The caller is responsible for ensuring that the collection does not change + // during while using the returned pointer. + const Entry *FindNextValueForName(const Entry *entry_ptr) const { + if (!m_map.empty()) { + const Entry *first_entry = &m_map[0]; + const Entry *after_last_entry = first_entry + m_map.size(); + const Entry *next_entry = entry_ptr + 1; + if (first_entry <= next_entry && next_entry < after_last_entry) { + if (next_entry->cstring == entry_ptr->cstring) + return next_entry; + } + } + return nullptr; + } + + size_t GetValues(ConstString unique_cstr, std::vector<T> &values) const { + const size_t start_size = values.size(); + + for (const Entry &entry : llvm::make_range(std::equal_range( + m_map.begin(), m_map.end(), unique_cstr, Compare()))) + values.push_back(entry.value); + + return values.size() - start_size; + } + + size_t GetValues(const RegularExpression ®ex, + std::vector<T> &values) const { + const size_t start_size = values.size(); + + const_iterator pos, end = m_map.end(); + for (pos = m_map.begin(); pos != end; ++pos) { + if (regex.Execute(pos->cstring.GetCString())) + values.push_back(pos->value); + } + + return values.size() - start_size; + } + + // Get the total number of entries in this map. + size_t GetSize() const { return m_map.size(); } + + // Returns true if this map is empty. + bool IsEmpty() const { return m_map.empty(); } + + // Reserve memory for at least "n" entries in the map. This is useful to call + // when you know you will be adding a lot of entries using + // UniqueCStringMap::Append() (which should be followed by a call to + // UniqueCStringMap::Sort()) or to UniqueCStringMap::Insert(). + void Reserve(size_t n) { m_map.reserve(n); } + + // Sort the unsorted contents in this map. A typical code flow would be: + // size_t approximate_num_entries = .... + // UniqueCStringMap<uint32_t> my_map; + // my_map.Reserve (approximate_num_entries); + // for (...) + // { + // my_map.Append (UniqueCStringMap::Entry(GetName(...), GetValue(...))); + // } + // my_map.Sort(); + void Sort() { llvm::sort(m_map.begin(), m_map.end(), Compare()); } + + // 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 + // keep a UniqueCStringMap around and have a lot of entries in the map, you + // will want to call this function to create a new vector and copy _only_ the + // exact size needed as part of the finalization of the string map. + void SizeToFit() { + if (m_map.size() < m_map.capacity()) { + collection temp(m_map.begin(), m_map.end()); + m_map.swap(temp); + } + } + +protected: + struct Compare { + bool operator()(const Entry &lhs, const Entry &rhs) { + return operator()(lhs.cstring, rhs.cstring); + } + + bool operator()(const Entry &lhs, ConstString rhs) { + return operator()(lhs.cstring, rhs); + } + + bool operator()(ConstString lhs, const Entry &rhs) { + return operator()(lhs, rhs.cstring); + } + + // 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()); + } + }; + typedef std::vector<Entry> collection; + typedef typename collection::iterator iterator; + typedef typename collection::const_iterator const_iterator; + collection m_map; +}; + +} // namespace lldb_private + +#endif // liblldb_UniqueCStringMap_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/UserSettingsController.h b/contrib/llvm-project/lldb/include/lldb/Core/UserSettingsController.h new file mode 100644 index 000000000000..6ae3bdec1665 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/UserSettingsController.h @@ -0,0 +1,91 @@ +//====-- UserSettingsController.h --------------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_UserSettingsController_h_ +#define liblldb_UserSettingsController_h_ + +#include "lldb/Utility/Status.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private-enumerations.h" + +#include "llvm/ADT/StringRef.h" + +#include <vector> + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class CommandInterpreter; +class ConstString; +class ExecutionContext; +class Property; +class Stream; +} + +namespace lldb_private { + +class Properties { +public: + Properties() : m_collection_sp() {} + + Properties(const lldb::OptionValuePropertiesSP &collection_sp) + : m_collection_sp(collection_sp) {} + + virtual ~Properties() {} + + virtual lldb::OptionValuePropertiesSP GetValueProperties() const { + // This function is virtual in case subclasses want to lazily implement + // creating the properties. + return m_collection_sp; + } + + virtual lldb::OptionValueSP GetPropertyValue(const ExecutionContext *exe_ctx, + llvm::StringRef property_path, + bool will_modify, + Status &error) const; + + virtual Status SetPropertyValue(const ExecutionContext *exe_ctx, + VarSetOperationType op, + llvm::StringRef property_path, + llvm::StringRef value); + + virtual Status DumpPropertyValue(const ExecutionContext *exe_ctx, + Stream &strm, llvm::StringRef property_path, + uint32_t dump_mask); + + virtual void DumpAllPropertyValues(const ExecutionContext *exe_ctx, + Stream &strm, uint32_t dump_mask); + + virtual void DumpAllDescriptions(CommandInterpreter &interpreter, + Stream &strm) const; + + size_t Apropos(llvm::StringRef keyword, + std::vector<const Property *> &matching_properties) const; + + lldb::OptionValuePropertiesSP GetSubProperty(const ExecutionContext *exe_ctx, + ConstString name); + + // We sometimes need to introduce a setting to enable experimental features, + // but then we don't want the setting for these to cause errors when the + // setting goes away. Add a sub-topic of the settings using this + // experimental name, and two things will happen. One is that settings that + // don't find the name will not be treated as errors. Also, if you decide to + // keep the settings just move them into the containing properties, and we + // will auto-forward the experimental settings to the real one. + static const char *GetExperimentalSettingsName(); + + static bool IsSettingExperimental(llvm::StringRef setting); + +protected: + lldb::OptionValuePropertiesSP m_collection_sp; +}; + +} // namespace lldb_private + +#endif // liblldb_UserSettingsController_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/Value.h b/contrib/llvm-project/lldb/include/lldb/Core/Value.h new file mode 100644 index 000000000000..7b4cc3b71c28 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/Value.h @@ -0,0 +1,261 @@ +//===-- Value.h -------------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Value_h_ +#define liblldb_Value_h_ + +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Utility/DataBufferHeap.h" +#include "lldb/Utility/Scalar.h" +#include "lldb/Utility/Status.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-private-enumerations.h" +#include "lldb/lldb-private-types.h" + +#include "llvm/ADT/APInt.h" + +#include <vector> + +#include <stdint.h> +#include <string.h> + +namespace lldb_private { +class DataExtractor; +class ExecutionContext; +class Module; +class Stream; +class Type; +class Variable; +} + +namespace lldb_private { + +class Value { +public: + // Values Less than zero are an error, greater than or equal to zero returns + // what the Scalar result is. + enum ValueType { + // m_value contains... + // ============================ + eValueTypeScalar, // raw scalar value + eValueTypeVector, // byte array of m_vector.length with endianness of + // m_vector.byte_order + eValueTypeFileAddress, // file address value + eValueTypeLoadAddress, // load address value + eValueTypeHostAddress // host address value (for memory in the process that + // is using liblldb) + }; + + enum ContextType // Type that describes Value::m_context + { + // m_context contains... + // ==================== + eContextTypeInvalid, // undefined + eContextTypeRegisterInfo, // RegisterInfo * (can be a scalar or a vector + // register) + eContextTypeLLDBType, // lldb_private::Type * + eContextTypeVariable // lldb_private::Variable * + }; + + const static size_t kMaxByteSize = 32u; + + struct Vector { + // The byte array must be big enough to hold vector registers for any + // supported target. + uint8_t bytes[kMaxByteSize]; + size_t length; + lldb::ByteOrder byte_order; + + Vector() : length(0), byte_order(lldb::eByteOrderInvalid) {} + + Vector(const Vector &vector) { *this = vector; } + const Vector &operator=(const Vector &vector) { + SetBytes(vector.bytes, vector.length, vector.byte_order); + return *this; + } + + void Clear() { length = 0; } + + bool SetBytes(const void *bytes, size_t length, + lldb::ByteOrder byte_order) { + this->length = length; + this->byte_order = byte_order; + if (length) + ::memcpy(this->bytes, bytes, + length < kMaxByteSize ? length : kMaxByteSize); + return IsValid(); + } + + bool IsValid() const { + return (length > 0 && length < kMaxByteSize && + byte_order != lldb::eByteOrderInvalid); + } + // Casts a vector, if valid, to an unsigned int of matching or largest + // supported size. Truncates to the beginning of the vector if required. + // Returns a default constructed Scalar if the Vector data is internally + // inconsistent. + llvm::APInt rhs = llvm::APInt(BITWIDTH_INT128, NUM_OF_WORDS_INT128, + ((type128 *)bytes)->x); + Scalar GetAsScalar() const { + Scalar scalar; + if (IsValid()) { + if (length == 1) + scalar = *(const uint8_t *)bytes; + else if (length == 2) + scalar = *(const uint16_t *)bytes; + else if (length == 4) + scalar = *(const uint32_t *)bytes; + else if (length == 8) + scalar = *(const uint64_t *)bytes; + else if (length >= 16) + scalar = rhs; + } + return scalar; + } + }; + + Value(); + Value(const Scalar &scalar); + Value(const Vector &vector); + Value(const void *bytes, int len); + Value(const Value &rhs); + + void SetBytes(const void *bytes, int len); + + void AppendBytes(const void *bytes, int len); + + Value &operator=(const Value &rhs); + + const CompilerType &GetCompilerType(); + + void SetCompilerType(const CompilerType &compiler_type); + + ValueType GetValueType() const; + + AddressType GetValueAddressType() const; + + ContextType GetContextType() const { return m_context_type; } + + void SetValueType(ValueType value_type) { m_value_type = value_type; } + + void ClearContext() { + m_context = nullptr; + m_context_type = eContextTypeInvalid; + } + + void SetContext(ContextType context_type, void *p) { + m_context_type = context_type; + m_context = p; + if (m_context_type == eContextTypeRegisterInfo) { + RegisterInfo *reg_info = GetRegisterInfo(); + if (reg_info->encoding == lldb::eEncodingVector && + m_vector.byte_order != lldb::eByteOrderInvalid) + SetValueType(eValueTypeScalar); + } + } + + RegisterInfo *GetRegisterInfo() const; + + Type *GetType(); + + Scalar &ResolveValue(ExecutionContext *exe_ctx); + + const Scalar &GetScalar() const { return m_value; } + + const Vector &GetVector() const { return m_vector; } + + Scalar &GetScalar() { return m_value; } + + Vector &GetVector() { return m_vector; } + + bool SetVectorBytes(const Vector &vector) { + m_vector = vector; + return m_vector.IsValid(); + } + + bool SetVectorBytes(uint8_t *bytes, size_t length, + lldb::ByteOrder byte_order) { + return m_vector.SetBytes(bytes, length, byte_order); + } + + bool SetScalarFromVector() { + if (m_vector.IsValid()) { + m_value = m_vector.GetAsScalar(); + return true; + } + return false; + } + + size_t ResizeData(size_t len); + + size_t AppendDataToHostBuffer(const Value &rhs); + + DataBufferHeap &GetBuffer() { return m_data_buffer; } + + const DataBufferHeap &GetBuffer() const { return m_data_buffer; } + + bool ValueOf(ExecutionContext *exe_ctx); + + Variable *GetVariable(); + + void Dump(Stream *strm); + + lldb::Format GetValueDefaultFormat(); + + uint64_t GetValueByteSize(Status *error_ptr, ExecutionContext *exe_ctx); + + Status GetValueAsData(ExecutionContext *exe_ctx, DataExtractor &data, + Module *module); // Can be nullptr + + static const char *GetValueTypeAsCString(ValueType context_type); + + static const char *GetContextTypeAsCString(ContextType context_type); + + /// Convert this value's file address to a load address, if possible. + void ConvertToLoadAddress(Module *module, Target *target); + + bool GetData(DataExtractor &data); + + void Clear(); + +protected: + Scalar m_value; + Vector m_vector; + CompilerType m_compiler_type; + void *m_context; + ValueType m_value_type; + ContextType m_context_type; + DataBufferHeap m_data_buffer; +}; + +class ValueList { +public: + ValueList() : m_values() {} + + ValueList(const ValueList &rhs); + + ~ValueList() = default; + + const ValueList &operator=(const ValueList &rhs); + + // void InsertValue (Value *value, size_t idx); + void PushValue(const Value &value); + + size_t GetSize(); + Value *GetValueAtIndex(size_t idx); + void Clear(); + +private: + typedef std::vector<Value> collection; + + collection m_values; +}; + +} // namespace lldb_private + +#endif // liblldb_Value_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObject.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObject.h new file mode 100644 index 000000000000..0808b86c67a1 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObject.h @@ -0,0 +1,1042 @@ +//===-- ValueObject.h -------------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObject_h_ +#define liblldb_ValueObject_h_ + +#include "lldb/Core/Value.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/DataExtractor.h" +#include "lldb/Utility/SharedCluster.h" +#include "lldb/Utility/Status.h" +#include "lldb/Utility/UserID.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private-enumerations.h" +#include "lldb/lldb-types.h" + +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/Optional.h" +#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/StringRef.h" + +#include <functional> +#include <initializer_list> +#include <map> +#include <mutex> +#include <string> +#include <utility> + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class Declaration; +class DumpValueObjectOptions; +class EvaluateExpressionOptions; +class ExecutionContextScope; +class Log; +class Scalar; +class Stream; +class SymbolContextScope; +class TypeFormatImpl; +class TypeSummaryImpl; +class TypeSummaryOptions; + +/// ValueObject: +/// +/// This abstract class provides an interface to a particular value, be it a +/// register, a local or global variable, +/// that is evaluated in some particular scope. The ValueObject also has the +/// capability of being the "child" of +/// some other variable object, and in turn of having children. +/// If a ValueObject is a root variable object - having no parent - then it must +/// be constructed with respect to some +/// particular ExecutionContextScope. If it is a child, it inherits the +/// ExecutionContextScope from its parent. +/// The ValueObject will update itself if necessary before fetching its value, +/// summary, object description, etc. +/// But it will always update itself in the ExecutionContextScope with which it +/// was originally created. + +/// A brief note on life cycle management for ValueObjects. This is a little +/// tricky because a ValueObject can contain +/// various other ValueObjects - the Dynamic Value, its children, the +/// dereference value, etc. Any one of these can be +/// handed out as a shared pointer, but for that contained value object to be +/// valid, the root object and potentially other +/// of the value objects need to stay around. +/// We solve this problem by handing out shared pointers to the Value Object and +/// any of its dependents using a shared +/// ClusterManager. This treats each shared pointer handed out for the entire +/// cluster as a reference to the whole +/// cluster. The whole cluster will stay around until the last reference is +/// released. +/// +/// The ValueObject mostly handle this automatically, if a value object is made +/// with a Parent ValueObject, then it adds +/// itself to the ClusterManager of the parent. + +/// It does mean that external to the ValueObjects we should only ever make +/// available ValueObjectSP's, never ValueObjects +/// or pointers to them. So all the "Root level" ValueObject derived +/// constructors should be private, and +/// should implement a Create function that new's up object and returns a Shared +/// Pointer that it gets from the GetSP() method. +/// +/// However, if you are making an derived ValueObject that will be contained in +/// a parent value object, you should just +/// hold onto a pointer to it internally, and by virtue of passing the parent +/// ValueObject into its constructor, it will +/// be added to the ClusterManager for the parent. Then if you ever hand out a +/// Shared Pointer to the contained ValueObject, +/// just do so by calling GetSP() on the contained object. + +class ValueObject : public UserID { +public: + enum GetExpressionPathFormat { + eGetExpressionPathFormatDereferencePointers = 1, + eGetExpressionPathFormatHonorPointers + }; + + enum ValueObjectRepresentationStyle { + eValueObjectRepresentationStyleValue = 1, + eValueObjectRepresentationStyleSummary, + eValueObjectRepresentationStyleLanguageSpecific, + eValueObjectRepresentationStyleLocation, + eValueObjectRepresentationStyleChildrenCount, + eValueObjectRepresentationStyleType, + eValueObjectRepresentationStyleName, + eValueObjectRepresentationStyleExpressionPath + }; + + enum ExpressionPathScanEndReason { + eExpressionPathScanEndReasonEndOfString = 1, // out of data to parse + eExpressionPathScanEndReasonNoSuchChild, // child element not found + eExpressionPathScanEndReasonNoSuchSyntheticChild, // (synthetic) child + // element not found + eExpressionPathScanEndReasonEmptyRangeNotAllowed, // [] only allowed for + // arrays + eExpressionPathScanEndReasonDotInsteadOfArrow, // . used when -> should be + // used + eExpressionPathScanEndReasonArrowInsteadOfDot, // -> used when . should be + // used + eExpressionPathScanEndReasonFragileIVarNotAllowed, // ObjC ivar expansion + // not allowed + eExpressionPathScanEndReasonRangeOperatorNotAllowed, // [] not allowed by + // options + eExpressionPathScanEndReasonRangeOperatorInvalid, // [] not valid on objects + // other than scalars, + // pointers or arrays + eExpressionPathScanEndReasonArrayRangeOperatorMet, // [] is good for arrays, + // but I cannot parse it + eExpressionPathScanEndReasonBitfieldRangeOperatorMet, // [] is good for + // bitfields, but I + // cannot parse after + // it + eExpressionPathScanEndReasonUnexpectedSymbol, // something is malformed in + // the expression + eExpressionPathScanEndReasonTakingAddressFailed, // impossible to apply & + // operator + eExpressionPathScanEndReasonDereferencingFailed, // impossible to apply * + // operator + eExpressionPathScanEndReasonRangeOperatorExpanded, // [] was expanded into a + // VOList + eExpressionPathScanEndReasonSyntheticValueMissing, // getting the synthetic + // children failed + eExpressionPathScanEndReasonUnknown = 0xFFFF + }; + + enum ExpressionPathEndResultType { + eExpressionPathEndResultTypePlain = 1, // anything but... + eExpressionPathEndResultTypeBitfield, // a bitfield + eExpressionPathEndResultTypeBoundedRange, // a range [low-high] + eExpressionPathEndResultTypeUnboundedRange, // a range [] + eExpressionPathEndResultTypeValueObjectList, // several items in a VOList + eExpressionPathEndResultTypeInvalid = 0xFFFF + }; + + enum ExpressionPathAftermath { + eExpressionPathAftermathNothing = 1, // just return it + eExpressionPathAftermathDereference, // dereference the target + eExpressionPathAftermathTakeAddress // take target's address + }; + + enum ClearUserVisibleDataItems { + eClearUserVisibleDataItemsNothing = 1u << 0, + eClearUserVisibleDataItemsValue = 1u << 1, + eClearUserVisibleDataItemsSummary = 1u << 2, + eClearUserVisibleDataItemsLocation = 1u << 3, + eClearUserVisibleDataItemsDescription = 1u << 4, + eClearUserVisibleDataItemsSyntheticChildren = 1u << 5, + eClearUserVisibleDataItemsValidator = 1u << 6, + eClearUserVisibleDataItemsAllStrings = + eClearUserVisibleDataItemsValue | eClearUserVisibleDataItemsSummary | + eClearUserVisibleDataItemsLocation | + eClearUserVisibleDataItemsDescription, + eClearUserVisibleDataItemsAll = 0xFFFF + }; + + struct GetValueForExpressionPathOptions { + enum class SyntheticChildrenTraversal { + None, + ToSynthetic, + FromSynthetic, + Both + }; + + bool m_check_dot_vs_arrow_syntax; + bool m_no_fragile_ivar; + bool m_allow_bitfields_syntax; + SyntheticChildrenTraversal m_synthetic_children_traversal; + + GetValueForExpressionPathOptions( + bool dot = false, bool no_ivar = false, bool bitfield = true, + SyntheticChildrenTraversal synth_traverse = + SyntheticChildrenTraversal::ToSynthetic) + : m_check_dot_vs_arrow_syntax(dot), m_no_fragile_ivar(no_ivar), + m_allow_bitfields_syntax(bitfield), + m_synthetic_children_traversal(synth_traverse) {} + + GetValueForExpressionPathOptions &DoCheckDotVsArrowSyntax() { + m_check_dot_vs_arrow_syntax = true; + return *this; + } + + GetValueForExpressionPathOptions &DontCheckDotVsArrowSyntax() { + m_check_dot_vs_arrow_syntax = false; + return *this; + } + + GetValueForExpressionPathOptions &DoAllowFragileIVar() { + m_no_fragile_ivar = false; + return *this; + } + + GetValueForExpressionPathOptions &DontAllowFragileIVar() { + m_no_fragile_ivar = true; + return *this; + } + + GetValueForExpressionPathOptions &DoAllowBitfieldSyntax() { + m_allow_bitfields_syntax = true; + return *this; + } + + GetValueForExpressionPathOptions &DontAllowBitfieldSyntax() { + m_allow_bitfields_syntax = false; + return *this; + } + + GetValueForExpressionPathOptions & + SetSyntheticChildrenTraversal(SyntheticChildrenTraversal traverse) { + m_synthetic_children_traversal = traverse; + return *this; + } + + static const GetValueForExpressionPathOptions DefaultOptions() { + static GetValueForExpressionPathOptions g_default_options; + + return g_default_options; + } + }; + + class EvaluationPoint { + public: + EvaluationPoint(); + + EvaluationPoint(ExecutionContextScope *exe_scope, + bool use_selected = false); + + EvaluationPoint(const EvaluationPoint &rhs); + + ~EvaluationPoint(); + + const ExecutionContextRef &GetExecutionContextRef() const { + return m_exe_ctx_ref; + } + + // Set the EvaluationPoint to the values in exe_scope, Return true if the + // Evaluation Point changed. Since the ExecutionContextScope is always + // going to be valid currently, the Updated Context will also always be + // valid. + + // bool + // SetContext (ExecutionContextScope *exe_scope); + + void SetIsConstant() { + SetUpdated(); + m_mod_id.SetInvalid(); + } + + bool IsConstant() const { return !m_mod_id.IsValid(); } + + ProcessModID GetModID() const { return m_mod_id; } + + void SetUpdateID(ProcessModID new_id) { m_mod_id = new_id; } + + void SetNeedsUpdate() { m_needs_update = true; } + + void SetUpdated(); + + bool NeedsUpdating(bool accept_invalid_exe_ctx) { + SyncWithProcessState(accept_invalid_exe_ctx); + return m_needs_update; + } + + bool IsValid() { + const bool accept_invalid_exe_ctx = false; + if (!m_mod_id.IsValid()) + return false; + else if (SyncWithProcessState(accept_invalid_exe_ctx)) { + if (!m_mod_id.IsValid()) + return false; + } + return true; + } + + void SetInvalid() { + // Use the stop id to mark us as invalid, leave the thread id and the + // stack id around for logging and history purposes. + m_mod_id.SetInvalid(); + + // Can't update an invalid state. + m_needs_update = false; + } + + private: + bool SyncWithProcessState(bool accept_invalid_exe_ctx); + + ProcessModID m_mod_id; // This is the stop id when this ValueObject was last + // evaluated. + ExecutionContextRef m_exe_ctx_ref; + bool m_needs_update; + }; + + virtual ~ValueObject(); + + const EvaluationPoint &GetUpdatePoint() const { return m_update_point; } + + EvaluationPoint &GetUpdatePoint() { return m_update_point; } + + const ExecutionContextRef &GetExecutionContextRef() const { + return m_update_point.GetExecutionContextRef(); + } + + lldb::TargetSP GetTargetSP() const { + return m_update_point.GetExecutionContextRef().GetTargetSP(); + } + + lldb::ProcessSP GetProcessSP() const { + return m_update_point.GetExecutionContextRef().GetProcessSP(); + } + + lldb::ThreadSP GetThreadSP() const { + return m_update_point.GetExecutionContextRef().GetThreadSP(); + } + + lldb::StackFrameSP GetFrameSP() const { + return m_update_point.GetExecutionContextRef().GetFrameSP(); + } + + void SetNeedsUpdate(); + + CompilerType GetCompilerType(); + + // this vends a TypeImpl that is useful at the SB API layer + virtual TypeImpl GetTypeImpl(); + + virtual bool CanProvideValue(); + + // Subclasses must implement the functions below. + virtual uint64_t GetByteSize() = 0; + + virtual lldb::ValueType GetValueType() const = 0; + + // Subclasses can implement the functions below. + virtual ConstString GetTypeName(); + + virtual ConstString GetDisplayTypeName(); + + virtual ConstString GetQualifiedTypeName(); + + virtual lldb::LanguageType GetObjectRuntimeLanguage(); + + virtual uint32_t + GetTypeInfo(CompilerType *pointee_or_element_compiler_type = nullptr); + + virtual bool IsPointerType(); + + virtual bool IsArrayType(); + + virtual bool IsScalarType(); + + virtual bool IsPointerOrReferenceType(); + + virtual bool IsPossibleDynamicType(); + + bool IsNilReference(); + + bool IsUninitializedReference(); + + virtual bool IsBaseClass() { return false; } + + bool IsBaseClass(uint32_t &depth); + + virtual bool IsDereferenceOfParent() { return false; } + + bool IsIntegerType(bool &is_signed); + + virtual bool GetBaseClassPath(Stream &s); + + virtual void GetExpressionPath( + Stream &s, bool qualify_cxx_base_classes, + GetExpressionPathFormat = eGetExpressionPathFormatDereferencePointers); + + lldb::ValueObjectSP GetValueForExpressionPath( + llvm::StringRef expression, + ExpressionPathScanEndReason *reason_to_stop = nullptr, + ExpressionPathEndResultType *final_value_type = nullptr, + const GetValueForExpressionPathOptions &options = + GetValueForExpressionPathOptions::DefaultOptions(), + ExpressionPathAftermath *final_task_on_target = nullptr); + + virtual bool IsInScope() { return true; } + + virtual lldb::offset_t GetByteOffset() { return 0; } + + virtual uint32_t GetBitfieldBitSize() { return 0; } + + virtual uint32_t GetBitfieldBitOffset() { return 0; } + + bool IsBitfield() { + return (GetBitfieldBitSize() != 0) || (GetBitfieldBitOffset() != 0); + } + + virtual bool IsArrayItemForPointer() { return m_is_array_item_for_pointer; } + + virtual const char *GetValueAsCString(); + + virtual bool GetValueAsCString(const lldb_private::TypeFormatImpl &format, + std::string &destination); + + bool GetValueAsCString(lldb::Format format, std::string &destination); + + virtual uint64_t GetValueAsUnsigned(uint64_t fail_value, + bool *success = nullptr); + + virtual int64_t GetValueAsSigned(int64_t fail_value, bool *success = nullptr); + + virtual bool SetValueFromCString(const char *value_str, Status &error); + + // Return the module associated with this value object in case the value is + // from an executable file and might have its data in sections of the file. + // This can be used for variables. + virtual lldb::ModuleSP GetModule(); + + ValueObject *GetRoot(); + + // Given a ValueObject, loop over itself and its parent, and its parent's + // parent, .. until either the given callback returns false, or you end up at + // a null pointer + ValueObject *FollowParentChain(std::function<bool(ValueObject *)>); + + virtual bool GetDeclaration(Declaration &decl); + + // The functions below should NOT be modified by subclasses + const Status &GetError(); + + ConstString GetName() const; + + virtual lldb::ValueObjectSP GetChildAtIndex(size_t idx, bool can_create); + + // this will always create the children if necessary + lldb::ValueObjectSP GetChildAtIndexPath(llvm::ArrayRef<size_t> idxs, + size_t *index_of_error = nullptr); + + lldb::ValueObjectSP + GetChildAtIndexPath(llvm::ArrayRef<std::pair<size_t, bool>> idxs, + size_t *index_of_error = nullptr); + + // this will always create the children if necessary + lldb::ValueObjectSP GetChildAtNamePath(llvm::ArrayRef<ConstString> names, + ConstString *name_of_error = nullptr); + + lldb::ValueObjectSP + GetChildAtNamePath(llvm::ArrayRef<std::pair<ConstString, bool>> names, + ConstString *name_of_error = nullptr); + + virtual lldb::ValueObjectSP GetChildMemberWithName(ConstString name, + bool can_create); + + virtual size_t GetIndexOfChildWithName(ConstString name); + + size_t GetNumChildren(uint32_t max = UINT32_MAX); + + const Value &GetValue() const; + + Value &GetValue(); + + virtual bool ResolveValue(Scalar &scalar); + + // return 'false' whenever you set the error, otherwise callers may assume + // true means everything is OK - this will break breakpoint conditions among + // potentially a few others + virtual bool IsLogicalTrue(Status &error); + + virtual const char *GetLocationAsCString(); + + const char * + GetSummaryAsCString(lldb::LanguageType lang = lldb::eLanguageTypeUnknown); + + bool + GetSummaryAsCString(TypeSummaryImpl *summary_ptr, std::string &destination, + lldb::LanguageType lang = lldb::eLanguageTypeUnknown); + + bool GetSummaryAsCString(std::string &destination, + const TypeSummaryOptions &options); + + bool GetSummaryAsCString(TypeSummaryImpl *summary_ptr, + std::string &destination, + const TypeSummaryOptions &options); + + std::pair<TypeValidatorResult, std::string> GetValidationStatus(); + + const char *GetObjectDescription(); + + bool HasSpecialPrintableRepresentation( + ValueObjectRepresentationStyle val_obj_display, + lldb::Format custom_format); + + enum class PrintableRepresentationSpecialCases : bool { + eDisable = false, + eAllow = true + }; + + bool + DumpPrintableRepresentation(Stream &s, + ValueObjectRepresentationStyle val_obj_display = + eValueObjectRepresentationStyleSummary, + lldb::Format custom_format = lldb::eFormatInvalid, + PrintableRepresentationSpecialCases special = + PrintableRepresentationSpecialCases::eAllow, + bool do_dump_error = true); + bool GetValueIsValid() const; + + // If you call this on a newly created ValueObject, it will always return + // false. + bool GetValueDidChange(); + + bool UpdateValueIfNeeded(bool update_format = true); + + bool UpdateFormatsIfNeeded(); + + lldb::ValueObjectSP GetSP() { return m_manager->GetSharedPointer(this); } + + // Change the name of the current ValueObject. Should *not* be used from a + // synthetic child provider as it would change the name of the non synthetic + // child as well. + void SetName(ConstString name); + + virtual lldb::addr_t GetAddressOf(bool scalar_is_load_address = true, + AddressType *address_type = nullptr); + + lldb::addr_t GetPointerValue(AddressType *address_type = nullptr); + + lldb::ValueObjectSP GetSyntheticChild(ConstString key) const; + + lldb::ValueObjectSP GetSyntheticArrayMember(size_t index, bool can_create); + + lldb::ValueObjectSP GetSyntheticBitFieldChild(uint32_t from, uint32_t to, + bool can_create); + + lldb::ValueObjectSP GetSyntheticExpressionPathChild(const char *expression, + bool can_create); + + virtual lldb::ValueObjectSP + GetSyntheticChildAtOffset(uint32_t offset, const CompilerType &type, + bool can_create, + ConstString name_const_str = ConstString()); + + virtual lldb::ValueObjectSP + GetSyntheticBase(uint32_t offset, const CompilerType &type, bool can_create, + ConstString name_const_str = ConstString()); + + virtual lldb::ValueObjectSP GetDynamicValue(lldb::DynamicValueType valueType); + + lldb::DynamicValueType GetDynamicValueType(); + + virtual lldb::ValueObjectSP GetStaticValue(); + + virtual lldb::ValueObjectSP GetNonSyntheticValue(); + + lldb::ValueObjectSP GetSyntheticValue(bool use_synthetic = true); + + virtual bool HasSyntheticValue(); + + virtual bool IsSynthetic() { return false; } + + lldb::ValueObjectSP + GetQualifiedRepresentationIfAvailable(lldb::DynamicValueType dynValue, + bool synthValue); + + virtual lldb::ValueObjectSP CreateConstantValue(ConstString name); + + virtual lldb::ValueObjectSP Dereference(Status &error); + + // Creates a copy of the ValueObject with a new name and setting the current + // ValueObject as its parent. It should be used when we want to change the + // name of a ValueObject without modifying the actual ValueObject itself + // (e.g. sythetic child provider). + virtual lldb::ValueObjectSP Clone(ConstString new_name); + + virtual lldb::ValueObjectSP AddressOf(Status &error); + + virtual lldb::addr_t GetLiveAddress() { return LLDB_INVALID_ADDRESS; } + + virtual void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS, + AddressType address_type = eAddressTypeLoad) {} + + virtual lldb::ValueObjectSP Cast(const CompilerType &compiler_type); + + virtual lldb::ValueObjectSP CastPointerType(const char *name, + CompilerType &ast_type); + + virtual lldb::ValueObjectSP CastPointerType(const char *name, + lldb::TypeSP &type_sp); + + // The backing bits of this value object were updated, clear any descriptive + // string, so we know we have to refetch them + virtual void ValueUpdated() { + ClearUserVisibleData(eClearUserVisibleDataItemsValue | + eClearUserVisibleDataItemsSummary | + eClearUserVisibleDataItemsDescription); + } + + virtual bool IsDynamic() { return false; } + + virtual bool DoesProvideSyntheticValue() { return false; } + + virtual bool IsSyntheticChildrenGenerated(); + + virtual void SetSyntheticChildrenGenerated(bool b); + + virtual SymbolContextScope *GetSymbolContextScope(); + + void Dump(Stream &s); + + void Dump(Stream &s, const DumpValueObjectOptions &options); + + static lldb::ValueObjectSP + CreateValueObjectFromExpression(llvm::StringRef name, + llvm::StringRef expression, + const ExecutionContext &exe_ctx); + + static lldb::ValueObjectSP + CreateValueObjectFromExpression(llvm::StringRef name, + llvm::StringRef expression, + const ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options); + + static lldb::ValueObjectSP + CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address, + const ExecutionContext &exe_ctx, + CompilerType type); + + static lldb::ValueObjectSP + CreateValueObjectFromData(llvm::StringRef name, const DataExtractor &data, + const ExecutionContext &exe_ctx, CompilerType type); + + void LogValueObject(Log *log); + + void LogValueObject(Log *log, const DumpValueObjectOptions &options); + + lldb::ValueObjectSP Persist(); + + // returns true if this is a char* or a char[] if it is a char* and + // check_pointer is true, it also checks that the pointer is valid + bool IsCStringContainer(bool check_pointer = false); + + std::pair<size_t, bool> + ReadPointedString(lldb::DataBufferSP &buffer_sp, Status &error, + uint32_t max_length = 0, bool honor_array = true, + lldb::Format item_format = lldb::eFormatCharArray); + + virtual size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0, + uint32_t item_count = 1); + + virtual uint64_t GetData(DataExtractor &data, Status &error); + + virtual bool SetData(DataExtractor &data, Status &error); + + virtual bool GetIsConstant() const { return m_update_point.IsConstant(); } + + bool NeedsUpdating() { + const bool accept_invalid_exe_ctx = + (CanUpdateWithInvalidExecutionContext() == eLazyBoolYes); + return m_update_point.NeedsUpdating(accept_invalid_exe_ctx); + } + + void SetIsConstant() { m_update_point.SetIsConstant(); } + + lldb::Format GetFormat() const; + + virtual void SetFormat(lldb::Format format) { + if (format != m_format) + ClearUserVisibleData(eClearUserVisibleDataItemsValue); + m_format = format; + } + + virtual lldb::LanguageType GetPreferredDisplayLanguage(); + + void SetPreferredDisplayLanguage(lldb::LanguageType); + + lldb::TypeSummaryImplSP GetSummaryFormat() { + UpdateFormatsIfNeeded(); + return m_type_summary_sp; + } + + void SetSummaryFormat(lldb::TypeSummaryImplSP format) { + m_type_summary_sp = format; + ClearUserVisibleData(eClearUserVisibleDataItemsSummary); + } + + lldb::TypeValidatorImplSP GetValidator() { + UpdateFormatsIfNeeded(); + return m_type_validator_sp; + } + + void SetValidator(lldb::TypeValidatorImplSP format) { + m_type_validator_sp = format; + ClearUserVisibleData(eClearUserVisibleDataItemsValidator); + } + + void SetValueFormat(lldb::TypeFormatImplSP format) { + m_type_format_sp = format; + ClearUserVisibleData(eClearUserVisibleDataItemsValue); + } + + lldb::TypeFormatImplSP GetValueFormat() { + UpdateFormatsIfNeeded(); + return m_type_format_sp; + } + + void SetSyntheticChildren(const lldb::SyntheticChildrenSP &synth_sp) { + if (synth_sp.get() == m_synthetic_children_sp.get()) + return; + ClearUserVisibleData(eClearUserVisibleDataItemsSyntheticChildren); + m_synthetic_children_sp = synth_sp; + } + + lldb::SyntheticChildrenSP GetSyntheticChildren() { + UpdateFormatsIfNeeded(); + return m_synthetic_children_sp; + } + + // Use GetParent for display purposes, but if you want to tell the parent to + // update itself then use m_parent. The ValueObjectDynamicValue's parent is + // not the correct parent for displaying, they are really siblings, so for + // display it needs to route through to its grandparent. + virtual ValueObject *GetParent() { return m_parent; } + + virtual const ValueObject *GetParent() const { return m_parent; } + + ValueObject *GetNonBaseClassParent(); + + void SetAddressTypeOfChildren(AddressType at) { + m_address_type_of_ptr_or_ref_children = at; + } + + AddressType GetAddressTypeOfChildren(); + + void SetHasCompleteType() { m_did_calculate_complete_objc_class_type = true; } + + /// Find out if a ValueObject might have children. + /// + /// This call is much more efficient than CalculateNumChildren() as + /// it doesn't need to complete the underlying type. This is designed + /// to be used in a UI environment in order to detect if the + /// disclosure triangle should be displayed or not. + /// + /// This function returns true for class, union, structure, + /// pointers, references, arrays and more. Again, it does so without + /// doing any expensive type completion. + /// + /// \return + /// Returns \b true if the ValueObject might have children, or \b + /// false otherwise. + virtual bool MightHaveChildren(); + + virtual lldb::VariableSP GetVariable() { return nullptr; } + + virtual bool IsRuntimeSupportValue(); + + virtual uint64_t GetLanguageFlags(); + + virtual void SetLanguageFlags(uint64_t flags); + +protected: + typedef ClusterManager<ValueObject> ValueObjectManager; + + class ChildrenManager { + public: + ChildrenManager() : m_mutex(), m_children(), m_children_count(0) {} + + bool HasChildAtIndex(size_t idx) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + return (m_children.find(idx) != m_children.end()); + } + + ValueObject *GetChildAtIndex(size_t idx) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + const auto iter = m_children.find(idx); + return ((iter == m_children.end()) ? nullptr : iter->second); + } + + void SetChildAtIndex(size_t idx, ValueObject *valobj) { + // we do not need to be mutex-protected to make a pair + ChildrenPair pair(idx, valobj); + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_children.insert(pair); + } + + void SetChildrenCount(size_t count) { Clear(count); } + + size_t GetChildrenCount() { return m_children_count; } + + void Clear(size_t new_count = 0) { + std::lock_guard<std::recursive_mutex> guard(m_mutex); + m_children_count = new_count; + m_children.clear(); + } + + private: + typedef std::map<size_t, ValueObject *> ChildrenMap; + typedef ChildrenMap::iterator ChildrenIterator; + typedef ChildrenMap::value_type ChildrenPair; + std::recursive_mutex m_mutex; + ChildrenMap m_children; + size_t m_children_count; + }; + + // Classes that inherit from ValueObject can see and modify these + ValueObject + *m_parent; // The parent value object, or nullptr if this has no parent + ValueObject *m_root; // The root of the hierarchy for this ValueObject (or + // nullptr if never calculated) + EvaluationPoint m_update_point; // Stores both the stop id and the full + // context at which this value was last + // updated. When we are asked to update the value object, we check whether + // the context & stop id are the same before updating. + ConstString m_name; // The name of this object + DataExtractor + m_data; // A data extractor that can be used to extract the value. + Value m_value; + Status + m_error; // An error object that can describe any errors that occur when + // updating values. + std::string m_value_str; // Cached value string that will get cleared if/when + // the value is updated. + std::string m_old_value_str; // Cached old value string from the last time the + // value was gotten + std::string m_location_str; // Cached location string that will get cleared + // if/when the value is updated. + std::string m_summary_str; // Cached summary string that will get cleared + // if/when the value is updated. + std::string m_object_desc_str; // Cached result of the "object printer". This + // differs from the summary + // in that the summary is consed up by us, the object_desc_string is builtin. + + llvm::Optional<std::pair<TypeValidatorResult, std::string>> + m_validation_result; + + CompilerType m_override_type; // If the type of the value object should be + // overridden, the type to impose. + + ValueObjectManager *m_manager; // This object is managed by the root object + // (any ValueObject that gets created + // without a parent.) The manager gets passed through all the generations of + // dependent objects, and will keep the whole cluster of objects alive as + // long as a shared pointer to any of them has been handed out. Shared + // pointers to value objects must always be made with the GetSP method. + + ChildrenManager m_children; + std::map<ConstString, ValueObject *> m_synthetic_children; + + ValueObject *m_dynamic_value; + ValueObject *m_synthetic_value; + ValueObject *m_deref_valobj; + + lldb::ValueObjectSP m_addr_of_valobj_sp; // We have to hold onto a shared + // pointer to this one because it is + // created + // as an independent ValueObjectConstResult, which isn't managed by us. + + lldb::Format m_format; + lldb::Format m_last_format; + uint32_t m_last_format_mgr_revision; + lldb::TypeSummaryImplSP m_type_summary_sp; + lldb::TypeFormatImplSP m_type_format_sp; + lldb::SyntheticChildrenSP m_synthetic_children_sp; + lldb::TypeValidatorImplSP m_type_validator_sp; + ProcessModID m_user_id_of_forced_summary; + AddressType m_address_type_of_ptr_or_ref_children; + + llvm::SmallVector<uint8_t, 16> m_value_checksum; + + lldb::LanguageType m_preferred_display_language; + + uint64_t m_language_flags; + + bool m_value_is_valid : 1, m_value_did_change : 1, m_children_count_valid : 1, + m_old_value_valid : 1, m_is_deref_of_parent : 1, + m_is_array_item_for_pointer : 1, m_is_bitfield_for_scalar : 1, + m_is_child_at_offset : 1, m_is_getting_summary : 1, + m_did_calculate_complete_objc_class_type : 1, + m_is_synthetic_children_generated : 1; + + friend class ValueObjectChild; + friend class ClangExpressionDeclMap; // For GetValue + friend class ExpressionVariable; // For SetName + friend class Target; // For SetName + friend class ValueObjectConstResultImpl; + friend class ValueObjectSynthetic; // For ClearUserVisibleData + + // Constructors and Destructors + + // Use the no-argument constructor to make a constant variable object (with + // no ExecutionContextScope.) + + ValueObject(); + + // Use this constructor to create a "root variable object". The ValueObject + // will be locked to this context through-out its lifespan. + + ValueObject(ExecutionContextScope *exe_scope, + AddressType child_ptr_or_ref_addr_type = eAddressTypeLoad); + + // Use this constructor to create a ValueObject owned by another ValueObject. + // It will inherit the ExecutionContext of its parent. + + ValueObject(ValueObject &parent); + + ValueObjectManager *GetManager() { return m_manager; } + + virtual bool UpdateValue() = 0; + + virtual LazyBool CanUpdateWithInvalidExecutionContext() { + return eLazyBoolCalculate; + } + + virtual void CalculateDynamicValue(lldb::DynamicValueType use_dynamic); + + virtual lldb::DynamicValueType GetDynamicValueTypeImpl() { + return lldb::eNoDynamicValues; + } + + virtual bool HasDynamicValueTypeInfo() { return false; } + + virtual void CalculateSyntheticValue(bool use_synthetic = true); + + // Should only be called by ValueObject::GetChildAtIndex() Returns a + // ValueObject managed by this ValueObject's manager. + virtual ValueObject *CreateChildAtIndex(size_t idx, + bool synthetic_array_member, + int32_t synthetic_index); + + // Should only be called by ValueObject::GetNumChildren() + virtual size_t CalculateNumChildren(uint32_t max = UINT32_MAX) = 0; + + void SetNumChildren(size_t num_children); + + void SetValueDidChange(bool value_changed); + + void SetValueIsValid(bool valid); + + void ClearUserVisibleData( + uint32_t items = ValueObject::eClearUserVisibleDataItemsAllStrings); + + void AddSyntheticChild(ConstString key, ValueObject *valobj); + + DataExtractor &GetDataExtractor(); + + void ClearDynamicTypeInformation(); + + // Subclasses must implement the functions below. + + virtual CompilerType GetCompilerTypeImpl() = 0; + + const char *GetLocationAsCStringImpl(const Value &value, + const DataExtractor &data); + + bool IsChecksumEmpty(); + + void SetPreferredDisplayLanguageIfNeeded(lldb::LanguageType); + +private: + virtual CompilerType MaybeCalculateCompleteType(); + + lldb::ValueObjectSP GetValueForExpressionPath_Impl( + llvm::StringRef expression_cstr, + ExpressionPathScanEndReason *reason_to_stop, + ExpressionPathEndResultType *final_value_type, + const GetValueForExpressionPathOptions &options, + ExpressionPathAftermath *final_task_on_target); + + DISALLOW_COPY_AND_ASSIGN(ValueObject); +}; + +// A value object manager class that is seeded with the static variable value +// and it vends the user facing value object. If the type is dynamic it can +// vend the dynamic type. If this user type also has a synthetic type +// associated with it, it will vend the synthetic type. The class watches the +// process' stop +// ID and will update the user type when needed. +class ValueObjectManager { + // The root value object is the static typed variable object. + lldb::ValueObjectSP m_root_valobj_sp; + // The user value object is the value object the user wants to see. + lldb::ValueObjectSP m_user_valobj_sp; + lldb::DynamicValueType m_use_dynamic; + uint32_t m_stop_id; // The stop ID that m_user_valobj_sp is valid for. + bool m_use_synthetic; + +public: + ValueObjectManager() {} + + ValueObjectManager(lldb::ValueObjectSP in_valobj_sp, + lldb::DynamicValueType use_dynamic, bool use_synthetic); + + bool IsValid() const; + + lldb::ValueObjectSP GetRootSP() const { return m_root_valobj_sp; } + + // Gets the correct value object from the root object for a given process + // stop ID. If dynamic values are enabled, or if synthetic children are + // enabled, the value object that the user wants to see might change while + // debugging. + lldb::ValueObjectSP GetSP(); + + void SetUseDynamic(lldb::DynamicValueType use_dynamic); + void SetUseSynthetic(bool use_synthetic); + lldb::DynamicValueType GetUseDynamic() const { return m_use_dynamic; } + bool GetUseSynthetic() const { return m_use_synthetic; } + lldb::TargetSP GetTargetSP() const; + lldb::ProcessSP GetProcessSP() const; + lldb::ThreadSP GetThreadSP() const; + lldb::StackFrameSP GetFrameSP() const; +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObject_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectCast.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectCast.h new file mode 100644 index 000000000000..feee493dfafb --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectCast.h @@ -0,0 +1,65 @@ +//===-- ValueObjectCast.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObjectCast_h_ +#define liblldb_ValueObjectCast_h_ + +#include "lldb/Core/ValueObject.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class ConstString; + +// A ValueObject that represents a given value represented as a different type. +class ValueObjectCast : public ValueObject { +public: + ~ValueObjectCast() override; + + static lldb::ValueObjectSP Create(ValueObject &parent, + ConstString name, + const CompilerType &cast_type); + + uint64_t GetByteSize() override; + + size_t CalculateNumChildren(uint32_t max) override; + + lldb::ValueType GetValueType() const override; + + bool IsInScope() override; + + ValueObject *GetParent() override { + return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr); + } + + const ValueObject *GetParent() const override { + return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr); + } + +protected: + ValueObjectCast(ValueObject &parent, ConstString name, + const CompilerType &cast_type); + + bool UpdateValue() override; + + CompilerType GetCompilerTypeImpl() override; + + CompilerType m_cast_type; + +private: + DISALLOW_COPY_AND_ASSIGN(ValueObjectCast); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectCast_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectChild.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectChild.h new file mode 100644 index 000000000000..76209a22ec20 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectChild.h @@ -0,0 +1,96 @@ +//===-- ValueObjectChild.h --------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObjectChild_h_ +#define liblldb_ValueObjectChild_h_ + +#include "lldb/Core/ValueObject.h" + +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-private-enumerations.h" +#include "lldb/lldb-types.h" + +#include "llvm/ADT/Optional.h" + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { + +// A child of another ValueObject. +class ValueObjectChild : public ValueObject { +public: + ~ValueObjectChild() override; + + uint64_t GetByteSize() override { return m_byte_size; } + + lldb::offset_t GetByteOffset() override { return m_byte_offset; } + + uint32_t GetBitfieldBitSize() override { return m_bitfield_bit_size; } + + uint32_t GetBitfieldBitOffset() override { return m_bitfield_bit_offset; } + + lldb::ValueType GetValueType() const override; + + size_t CalculateNumChildren(uint32_t max) override; + + ConstString GetTypeName() override; + + ConstString GetQualifiedTypeName() override; + + ConstString GetDisplayTypeName() override; + + bool IsInScope() override; + + bool IsBaseClass() override { return m_is_base_class; } + + bool IsDereferenceOfParent() override { return m_is_deref_of_parent; } + +protected: + bool UpdateValue() override; + + LazyBool CanUpdateWithInvalidExecutionContext() override; + + CompilerType GetCompilerTypeImpl() override { return m_compiler_type; } + + CompilerType m_compiler_type; + ConstString m_type_name; + uint64_t m_byte_size; + int32_t m_byte_offset; + uint8_t m_bitfield_bit_size; + uint8_t m_bitfield_bit_offset; + bool m_is_base_class; + bool m_is_deref_of_parent; + llvm::Optional<LazyBool> m_can_update_with_invalid_exe_ctx; + + // + // void + // ReadValueFromMemory (ValueObject* parent, lldb::addr_t address); + +protected: + friend class ValueObject; + friend class ValueObjectConstResult; + friend class ValueObjectConstResultImpl; + + ValueObjectChild(ValueObject &parent, const CompilerType &compiler_type, + ConstString name, uint64_t byte_size, + int32_t byte_offset, uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, bool is_base_class, + bool is_deref_of_parent, + AddressType child_ptr_or_ref_addr_type, + uint64_t language_flags); + + DISALLOW_COPY_AND_ASSIGN(ValueObjectChild); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectChild_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResult.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResult.h new file mode 100644 index 000000000000..3bc957ef2b84 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResult.h @@ -0,0 +1,154 @@ +//===-- ValueObjectConstResult.h --------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObjectConstResult_h_ +#define liblldb_ValueObjectConstResult_h_ + +#include "lldb/Core/Value.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Core/ValueObjectConstResultImpl.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/Status.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private-enumerations.h" +#include "lldb/lldb-types.h" + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class DataExtractor; +class ExecutionContextScope; +class Module; + +// A frozen ValueObject copied into host memory +class ValueObjectConstResult : public ValueObject { +public: + ~ValueObjectConstResult() override; + + static lldb::ValueObjectSP + Create(ExecutionContextScope *exe_scope, lldb::ByteOrder byte_order, + uint32_t addr_byte_size, lldb::addr_t address = LLDB_INVALID_ADDRESS); + + static lldb::ValueObjectSP + Create(ExecutionContextScope *exe_scope, const CompilerType &compiler_type, + ConstString name, const DataExtractor &data, + lldb::addr_t address = LLDB_INVALID_ADDRESS); + + static lldb::ValueObjectSP + Create(ExecutionContextScope *exe_scope, const CompilerType &compiler_type, + ConstString name, const lldb::DataBufferSP &result_data_sp, + lldb::ByteOrder byte_order, uint32_t addr_size, + lldb::addr_t address = LLDB_INVALID_ADDRESS); + + static lldb::ValueObjectSP + Create(ExecutionContextScope *exe_scope, const CompilerType &compiler_type, + ConstString name, lldb::addr_t address, + AddressType address_type, uint32_t addr_byte_size); + + static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, + Value &value, ConstString name, + Module *module = nullptr); + + // When an expression fails to evaluate, we return an error + static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, + const Status &error); + + uint64_t GetByteSize() override; + + lldb::ValueType GetValueType() const override; + + size_t CalculateNumChildren(uint32_t max) override; + + ConstString GetTypeName() override; + + ConstString GetDisplayTypeName() override; + + bool IsInScope() override; + + void SetByteSize(size_t size); + + lldb::ValueObjectSP Dereference(Status &error) override; + + ValueObject *CreateChildAtIndex(size_t idx, bool synthetic_array_member, + int32_t synthetic_index) override; + + lldb::ValueObjectSP GetSyntheticChildAtOffset( + uint32_t offset, const CompilerType &type, bool can_create, + ConstString name_const_str = ConstString()) override; + + lldb::ValueObjectSP AddressOf(Status &error) override; + + lldb::addr_t GetAddressOf(bool scalar_is_load_address = true, + AddressType *address_type = nullptr) override; + + size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0, + uint32_t item_count = 1) override; + + lldb::addr_t GetLiveAddress() override { return m_impl.GetLiveAddress(); } + + void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS, + AddressType address_type = eAddressTypeLoad) override { + m_impl.SetLiveAddress(addr, address_type); + } + + lldb::ValueObjectSP + GetDynamicValue(lldb::DynamicValueType valueType) override; + + lldb::LanguageType GetPreferredDisplayLanguage() override; + + lldb::ValueObjectSP Cast(const CompilerType &compiler_type) override; + +protected: + bool UpdateValue() override; + + CompilerType GetCompilerTypeImpl() override; + + ConstString m_type_name; + uint64_t m_byte_size; + + ValueObjectConstResultImpl m_impl; + +private: + friend class ValueObjectConstResultImpl; + + ValueObjectConstResult(ExecutionContextScope *exe_scope, + lldb::ByteOrder byte_order, uint32_t addr_byte_size, + lldb::addr_t address); + + ValueObjectConstResult(ExecutionContextScope *exe_scope, + const CompilerType &compiler_type, + ConstString name, const DataExtractor &data, + lldb::addr_t address); + + ValueObjectConstResult(ExecutionContextScope *exe_scope, + const CompilerType &compiler_type, + ConstString name, + const lldb::DataBufferSP &result_data_sp, + lldb::ByteOrder byte_order, uint32_t addr_size, + lldb::addr_t address); + + ValueObjectConstResult(ExecutionContextScope *exe_scope, + const CompilerType &compiler_type, + ConstString name, lldb::addr_t address, + AddressType address_type, uint32_t addr_byte_size); + + ValueObjectConstResult(ExecutionContextScope *exe_scope, const Value &value, + ConstString name, Module *module = nullptr); + + ValueObjectConstResult(ExecutionContextScope *exe_scope, const Status &error); + + DISALLOW_COPY_AND_ASSIGN(ValueObjectConstResult); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectConstResult_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResultCast.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResultCast.h new file mode 100644 index 000000000000..be9b12b4b57c --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResultCast.h @@ -0,0 +1,69 @@ +//===-- ValueObjectConstResultCast.h ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObjectConstResultCast_h_ +#define liblldb_ValueObjectConstResultCast_h_ + +#include "lldb/Core/ValueObjectCast.h" +#include "lldb/Core/ValueObjectConstResultImpl.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-types.h" + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class DataExtractor; +class Status; +class ValueObject; + +class ValueObjectConstResultCast : public ValueObjectCast { +public: + ValueObjectConstResultCast(ValueObject &parent, ConstString name, + const CompilerType &cast_type, + lldb::addr_t live_address = LLDB_INVALID_ADDRESS); + + ~ValueObjectConstResultCast() override; + + lldb::ValueObjectSP Dereference(Status &error) override; + + ValueObject *CreateChildAtIndex(size_t idx, bool synthetic_array_member, + int32_t synthetic_index) override; + + virtual CompilerType GetCompilerType() { + return ValueObjectCast::GetCompilerType(); + } + + lldb::ValueObjectSP GetSyntheticChildAtOffset( + uint32_t offset, const CompilerType &type, bool can_create, + ConstString name_const_str = ConstString()) override; + + lldb::ValueObjectSP AddressOf(Status &error) override; + + size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0, + uint32_t item_count = 1) override; + + lldb::ValueObjectSP Cast(const CompilerType &compiler_type) override; + +protected: + ValueObjectConstResultImpl m_impl; + +private: + friend class ValueObject; + friend class ValueObjectConstResult; + friend class ValueObjectConstResultImpl; + + DISALLOW_COPY_AND_ASSIGN(ValueObjectConstResultCast); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectConstResultCast_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResultChild.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResultChild.h new file mode 100644 index 000000000000..16fa74f71ed5 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResultChild.h @@ -0,0 +1,78 @@ +//===-- ValueObjectConstResultChild.h ----------------------------*- C++-*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObjectConstResultChild_h_ +#define liblldb_ValueObjectConstResultChild_h_ + +#include "lldb/Core/ValueObjectChild.h" +#include "lldb/Core/ValueObjectConstResultImpl.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-types.h" + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class DataExtractor; +class Status; +class ValueObject; + +// A child of a ValueObjectConstResult. +class ValueObjectConstResultChild : public ValueObjectChild { +public: + ValueObjectConstResultChild(ValueObject &parent, + const CompilerType &compiler_type, + ConstString name, uint32_t byte_size, + int32_t byte_offset, uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, bool is_base_class, + bool is_deref_of_parent, + lldb::addr_t live_address, + uint64_t language_flags); + + ~ValueObjectConstResultChild() override; + + lldb::ValueObjectSP Dereference(Status &error) override; + + ValueObject *CreateChildAtIndex(size_t idx, bool synthetic_array_member, + int32_t synthetic_index) override; + + virtual CompilerType GetCompilerType() { + return ValueObjectChild::GetCompilerType(); + } + + lldb::ValueObjectSP GetSyntheticChildAtOffset( + uint32_t offset, const CompilerType &type, bool can_create, + ConstString name_const_str = ConstString()) override; + + lldb::ValueObjectSP AddressOf(Status &error) override; + + lldb::addr_t GetAddressOf(bool scalar_is_load_address = true, + AddressType *address_type = nullptr) override; + + size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0, + uint32_t item_count = 1) override; + + lldb::ValueObjectSP Cast(const CompilerType &compiler_type) override; + +protected: + ValueObjectConstResultImpl m_impl; + +private: + friend class ValueObject; + friend class ValueObjectConstResult; + friend class ValueObjectConstResultImpl; + + DISALLOW_COPY_AND_ASSIGN(ValueObjectConstResultChild); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectConstResultChild_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResultImpl.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResultImpl.h new file mode 100644 index 000000000000..ffac98e12e61 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectConstResultImpl.h @@ -0,0 +1,79 @@ +//===-- ValueObjectConstResultImpl.h ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObjectConstResultImpl_h_ +#define liblldb_ValueObjectConstResultImpl_h_ + +#include "lldb/Utility/ConstString.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private-enumerations.h" +#include "lldb/lldb-types.h" + +#include <stddef.h> +#include <stdint.h> +namespace lldb_private { +class CompilerType; +class DataExtractor; +class Status; +class ValueObject; +} + +namespace lldb_private { + +// A class wrapping common implementation details for operations in +// ValueObjectConstResult ( & Child ) that may need to jump from the host +// memory space into the target's memory space +class ValueObjectConstResultImpl { +public: + ValueObjectConstResultImpl(ValueObject *valobj, + lldb::addr_t live_address = LLDB_INVALID_ADDRESS); + + virtual ~ValueObjectConstResultImpl() = default; + + lldb::ValueObjectSP Dereference(Status &error); + + ValueObject *CreateChildAtIndex(size_t idx, bool synthetic_array_member, + int32_t synthetic_index); + + lldb::ValueObjectSP + GetSyntheticChildAtOffset(uint32_t offset, const CompilerType &type, + bool can_create, + ConstString name_const_str = ConstString()); + + lldb::ValueObjectSP AddressOf(Status &error); + + lldb::addr_t GetLiveAddress() { return m_live_address; } + + lldb::ValueObjectSP Cast(const CompilerType &compiler_type); + + void SetLiveAddress(lldb::addr_t addr = LLDB_INVALID_ADDRESS, + AddressType address_type = eAddressTypeLoad) { + m_live_address = addr; + m_live_address_type = address_type; + } + + virtual lldb::addr_t GetAddressOf(bool scalar_is_load_address = true, + AddressType *address_type = nullptr); + + virtual size_t GetPointeeData(DataExtractor &data, uint32_t item_idx = 0, + uint32_t item_count = 1); + +private: + ValueObject *m_impl_backend; + lldb::addr_t m_live_address; + AddressType m_live_address_type; + lldb::ValueObjectSP m_load_addr_backend; + lldb::ValueObjectSP m_address_of_backend; + + DISALLOW_COPY_AND_ASSIGN(ValueObjectConstResultImpl); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectConstResultImpl_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectDynamicValue.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectDynamicValue.h new file mode 100644 index 000000000000..f656d42e9a97 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectDynamicValue.h @@ -0,0 +1,136 @@ +//===-- ValueObjectDynamicValue.h -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObjectDynamicValue_h_ +#define liblldb_ValueObjectDynamicValue_h_ + +#include "lldb/Core/Address.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/SharingPtr.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private-enumerations.h" + +#include <assert.h> +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class DataExtractor; +class Declaration; +class Status; + +// A ValueObject that represents memory at a given address, viewed as some +// set lldb type. +class ValueObjectDynamicValue : public ValueObject { +public: + ~ValueObjectDynamicValue() override; + + uint64_t GetByteSize() override; + + ConstString GetTypeName() override; + + ConstString GetQualifiedTypeName() override; + + ConstString GetDisplayTypeName() override; + + size_t CalculateNumChildren(uint32_t max) override; + + lldb::ValueType GetValueType() const override; + + bool IsInScope() override; + + bool IsDynamic() override { return true; } + + bool IsBaseClass() override { + if (m_parent) + return m_parent->IsBaseClass(); + return false; + } + + bool GetIsConstant() const override { return false; } + + ValueObject *GetParent() override { + return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr); + } + + const ValueObject *GetParent() const override { + return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr); + } + + lldb::ValueObjectSP GetStaticValue() override { return m_parent->GetSP(); } + + void SetOwningSP(lldb::ValueObjectSP &owning_sp) { + if (m_owning_valobj_sp == owning_sp) + return; + + assert(m_owning_valobj_sp.get() == nullptr); + m_owning_valobj_sp = owning_sp; + } + + bool SetValueFromCString(const char *value_str, Status &error) override; + + bool SetData(DataExtractor &data, Status &error) override; + + TypeImpl GetTypeImpl() override; + + lldb::VariableSP GetVariable() override { + return m_parent ? m_parent->GetVariable() : nullptr; + } + + lldb::LanguageType GetPreferredDisplayLanguage() override; + + void SetPreferredDisplayLanguage(lldb::LanguageType); + + bool IsSyntheticChildrenGenerated() override; + + void SetSyntheticChildrenGenerated(bool b) override; + + bool GetDeclaration(Declaration &decl) override; + + uint64_t GetLanguageFlags() override; + + void SetLanguageFlags(uint64_t flags) override; + +protected: + bool UpdateValue() override; + + LazyBool CanUpdateWithInvalidExecutionContext() override { + return eLazyBoolYes; + } + + lldb::DynamicValueType GetDynamicValueTypeImpl() override { + return m_use_dynamic; + } + + bool HasDynamicValueTypeInfo() override { return true; } + + CompilerType GetCompilerTypeImpl() override; + + Address m_address; ///< The variable that this value object is based upon + TypeAndOrName m_dynamic_type_info; // We can have a type_sp or just a name + lldb::ValueObjectSP m_owning_valobj_sp; + lldb::DynamicValueType m_use_dynamic; + TypeImpl m_type_impl; + +private: + friend class ValueObject; + friend class ValueObjectConstResult; + ValueObjectDynamicValue(ValueObject &parent, + lldb::DynamicValueType use_dynamic); + + DISALLOW_COPY_AND_ASSIGN(ValueObjectDynamicValue); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectDynamicValue_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectList.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectList.h new file mode 100644 index 000000000000..42d19676d5d3 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectList.h @@ -0,0 +1,62 @@ +//===-- ValueObjectList.h ---------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObjectList_h_ +#define liblldb_ValueObjectList_h_ + +#include "lldb/lldb-forward.h" +#include "lldb/lldb-types.h" + +#include <vector> + +#include <stddef.h> + +namespace lldb_private { +class ValueObject; + +// A collection of ValueObject values that +class ValueObjectList { +public: + const ValueObjectList &operator=(const ValueObjectList &rhs); + + void Append(const lldb::ValueObjectSP &val_obj_sp); + + void Append(const ValueObjectList &valobj_list); + + lldb::ValueObjectSP FindValueObjectByPointer(ValueObject *valobj); + + size_t GetSize() const; + + void Resize(size_t size); + + lldb::ValueObjectSP GetValueObjectAtIndex(size_t idx); + + lldb::ValueObjectSP RemoveValueObjectAtIndex(size_t idx); + + void SetValueObjectAtIndex(size_t idx, const lldb::ValueObjectSP &valobj_sp); + + lldb::ValueObjectSP FindValueObjectByValueName(const char *name); + + lldb::ValueObjectSP FindValueObjectByUID(lldb::user_id_t uid); + + void Swap(ValueObjectList &value_object_list); + + void Clear() { m_value_objects.clear(); } + + const std::vector<lldb::ValueObjectSP> &GetObjects() const { + return m_value_objects; + } +protected: + typedef std::vector<lldb::ValueObjectSP> collection; + // Classes that inherit from ValueObjectList can see and modify these + collection m_value_objects; +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectList_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectMemory.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectMemory.h new file mode 100644 index 000000000000..df3557f14989 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectMemory.h @@ -0,0 +1,78 @@ +//===-- ValueObjectMemory.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObjectMemory_h_ +#define liblldb_ValueObjectMemory_h_ + +#include "lldb/Core/Address.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "llvm/ADT/StringRef.h" + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class ExecutionContextScope; + +// A ValueObject that represents memory at a given address, viewed as some +// set lldb type. +class ValueObjectMemory : public ValueObject { +public: + ~ValueObjectMemory() override; + + static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, + llvm::StringRef name, + const Address &address, + lldb::TypeSP &type_sp); + + static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, + llvm::StringRef name, + const Address &address, + const CompilerType &ast_type); + + uint64_t GetByteSize() override; + + ConstString GetTypeName() override; + + ConstString GetDisplayTypeName() override; + + size_t CalculateNumChildren(uint32_t max) override; + + lldb::ValueType GetValueType() const override; + + bool IsInScope() override; + + lldb::ModuleSP GetModule() override; + +protected: + bool UpdateValue() override; + + CompilerType GetCompilerTypeImpl() override; + + Address m_address; ///< The variable that this value object is based upon + lldb::TypeSP m_type_sp; + CompilerType m_compiler_type; + +private: + ValueObjectMemory(ExecutionContextScope *exe_scope, llvm::StringRef name, + const Address &address, lldb::TypeSP &type_sp); + + ValueObjectMemory(ExecutionContextScope *exe_scope, llvm::StringRef name, + const Address &address, const CompilerType &ast_type); + // For ValueObject only + DISALLOW_COPY_AND_ASSIGN(ValueObjectMemory); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectMemory_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectRegister.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectRegister.h new file mode 100644 index 000000000000..e584be6e6057 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectRegister.h @@ -0,0 +1,171 @@ +//===-- ValueObjectRegister.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObjectRegister_h_ +#define liblldb_ValueObjectRegister_h_ + +#include "lldb/Core/ValueObject.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/Utility/RegisterValue.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private-types.h" + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class DataExtractor; +class Status; +class ExecutionContextScope; +class Scalar; +class Stream; + +// A ValueObject that contains a root variable that may or may not +// have children. +class ValueObjectRegisterContext : public ValueObject { +public: + ~ValueObjectRegisterContext() override; + + uint64_t GetByteSize() override; + + lldb::ValueType GetValueType() const override { + return lldb::eValueTypeRegisterSet; + } + + ConstString GetTypeName() override; + + ConstString GetQualifiedTypeName() override; + + ConstString GetDisplayTypeName() override; + + size_t CalculateNumChildren(uint32_t max) override; + + ValueObject *CreateChildAtIndex(size_t idx, bool synthetic_array_member, + int32_t synthetic_index) override; + +protected: + bool UpdateValue() override; + + CompilerType GetCompilerTypeImpl() override; + + lldb::RegisterContextSP m_reg_ctx_sp; + +private: + ValueObjectRegisterContext(ValueObject &parent, + lldb::RegisterContextSP ®_ctx_sp); + // For ValueObject only + DISALLOW_COPY_AND_ASSIGN(ValueObjectRegisterContext); +}; + +class ValueObjectRegisterSet : public ValueObject { +public: + ~ValueObjectRegisterSet() override; + + static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, + lldb::RegisterContextSP ®_ctx_sp, + uint32_t set_idx); + + uint64_t GetByteSize() override; + + lldb::ValueType GetValueType() const override { + return lldb::eValueTypeRegisterSet; + } + + ConstString GetTypeName() override; + + ConstString GetQualifiedTypeName() override; + + size_t CalculateNumChildren(uint32_t max) override; + + ValueObject *CreateChildAtIndex(size_t idx, bool synthetic_array_member, + int32_t synthetic_index) override; + + lldb::ValueObjectSP GetChildMemberWithName(ConstString name, + bool can_create) override; + + size_t GetIndexOfChildWithName(ConstString name) override; + +protected: + bool UpdateValue() override; + + CompilerType GetCompilerTypeImpl() override; + + lldb::RegisterContextSP m_reg_ctx_sp; + const RegisterSet *m_reg_set; + uint32_t m_reg_set_idx; + +private: + friend class ValueObjectRegisterContext; + + ValueObjectRegisterSet(ExecutionContextScope *exe_scope, + lldb::RegisterContextSP ®_ctx_sp, uint32_t set_idx); + + // For ValueObject only + DISALLOW_COPY_AND_ASSIGN(ValueObjectRegisterSet); +}; + +class ValueObjectRegister : public ValueObject { +public: + ~ValueObjectRegister() override; + + static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, + lldb::RegisterContextSP ®_ctx_sp, + uint32_t reg_num); + + uint64_t GetByteSize() override; + + lldb::ValueType GetValueType() const override { + return lldb::eValueTypeRegister; + } + + ConstString GetTypeName() override; + + size_t CalculateNumChildren(uint32_t max) override; + + bool SetValueFromCString(const char *value_str, Status &error) override; + + bool SetData(DataExtractor &data, Status &error) override; + + bool ResolveValue(Scalar &scalar) override; + + void + GetExpressionPath(Stream &s, bool qualify_cxx_base_classes, + GetExpressionPathFormat epformat = + eGetExpressionPathFormatDereferencePointers) override; + +protected: + bool UpdateValue() override; + + CompilerType GetCompilerTypeImpl() override; + + lldb::RegisterContextSP m_reg_ctx_sp; + RegisterInfo m_reg_info; + RegisterValue m_reg_value; + ConstString m_type_name; + CompilerType m_compiler_type; + +private: + void ConstructObject(uint32_t reg_num); + + friend class ValueObjectRegisterSet; + + ValueObjectRegister(ValueObject &parent, lldb::RegisterContextSP ®_ctx_sp, + uint32_t reg_num); + ValueObjectRegister(ExecutionContextScope *exe_scope, + lldb::RegisterContextSP ®_ctx_sp, uint32_t reg_num); + + // For ValueObject only + DISALLOW_COPY_AND_ASSIGN(ValueObjectRegister); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectRegister_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h new file mode 100644 index 000000000000..3b14a3e9f388 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectSyntheticFilter.h @@ -0,0 +1,169 @@ +//===-- ValueObjectSyntheticFilter.h ----------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObjectSyntheticFilter_h_ +#define liblldb_ValueObjectSyntheticFilter_h_ + +#include "lldb/Core/ThreadSafeSTLMap.h" +#include "lldb/Core/ThreadSafeSTLVector.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" +#include "lldb/lldb-private-enumerations.h" + +#include <cstdint> +#include <memory> + +#include <stddef.h> + +namespace lldb_private { +class Declaration; +class Status; +class SyntheticChildrenFrontEnd; + +// A ValueObject that obtains its children from some source other than +// real information +// This is currently used to implement Python-based children and filters but +// you can bind it to any source of synthetic information and have it behave +// accordingly +class ValueObjectSynthetic : public ValueObject { +public: + ~ValueObjectSynthetic() override; + + uint64_t GetByteSize() override; + + ConstString GetTypeName() override; + + ConstString GetQualifiedTypeName() override; + + ConstString GetDisplayTypeName() override; + + bool MightHaveChildren() override; + + size_t CalculateNumChildren(uint32_t max) override; + + lldb::ValueType GetValueType() const override; + + lldb::ValueObjectSP GetChildAtIndex(size_t idx, bool can_create) override; + + lldb::ValueObjectSP GetChildMemberWithName(ConstString name, + bool can_create) override; + + size_t GetIndexOfChildWithName(ConstString name) override; + + lldb::ValueObjectSP + GetDynamicValue(lldb::DynamicValueType valueType) override; + + bool IsInScope() override; + + bool HasSyntheticValue() override { return false; } + + bool IsSynthetic() override { return true; } + + void CalculateSyntheticValue(bool use_synthetic) override {} + + bool IsDynamic() override { + return ((m_parent != nullptr) ? m_parent->IsDynamic() : false); + } + + lldb::ValueObjectSP GetStaticValue() override { + return ((m_parent != nullptr) ? m_parent->GetStaticValue() : GetSP()); + } + + virtual lldb::DynamicValueType GetDynamicValueType() { + return ((m_parent != nullptr) ? m_parent->GetDynamicValueType() + : lldb::eNoDynamicValues); + } + + ValueObject *GetParent() override { + return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr); + } + + const ValueObject *GetParent() const override { + return ((m_parent != nullptr) ? m_parent->GetParent() : nullptr); + } + + lldb::ValueObjectSP GetNonSyntheticValue() override; + + bool CanProvideValue() override; + + bool DoesProvideSyntheticValue() override { + return (UpdateValueIfNeeded(), m_provides_value == eLazyBoolYes); + } + + bool GetIsConstant() const override { return false; } + + bool SetValueFromCString(const char *value_str, Status &error) override; + + void SetFormat(lldb::Format format) override; + + lldb::LanguageType GetPreferredDisplayLanguage() override; + + void SetPreferredDisplayLanguage(lldb::LanguageType); + + bool IsSyntheticChildrenGenerated() override; + + void SetSyntheticChildrenGenerated(bool b) override; + + bool GetDeclaration(Declaration &decl) override; + + uint64_t GetLanguageFlags() override; + + void SetLanguageFlags(uint64_t flags) override; + +protected: + bool UpdateValue() override; + + LazyBool CanUpdateWithInvalidExecutionContext() override { + return eLazyBoolYes; + } + + CompilerType GetCompilerTypeImpl() override; + + virtual void CreateSynthFilter(); + + // we need to hold on to the SyntheticChildren because someone might delete + // the type binding while we are alive + lldb::SyntheticChildrenSP m_synth_sp; + std::unique_ptr<SyntheticChildrenFrontEnd> m_synth_filter_up; + + typedef ThreadSafeSTLMap<uint32_t, ValueObject *> ByIndexMap; + typedef ThreadSafeSTLMap<const char *, uint32_t> NameToIndexMap; + typedef ThreadSafeSTLVector<lldb::ValueObjectSP> SyntheticChildrenCache; + + typedef ByIndexMap::iterator ByIndexIterator; + typedef NameToIndexMap::iterator NameToIndexIterator; + + ByIndexMap m_children_byindex; + NameToIndexMap m_name_toindex; + uint32_t m_synthetic_children_count; // FIXME use the ValueObject's + // ChildrenManager instead of a special + // purpose solution + SyntheticChildrenCache m_synthetic_children_cache; + + ConstString m_parent_type_name; + + LazyBool m_might_have_children; + + LazyBool m_provides_value; + +private: + friend class ValueObject; + ValueObjectSynthetic(ValueObject &parent, lldb::SyntheticChildrenSP filter); + + void CopyValueData(ValueObject *source); + + DISALLOW_COPY_AND_ASSIGN(ValueObjectSynthetic); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectSyntheticFilter_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectVariable.h b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectVariable.h new file mode 100644 index 000000000000..86bb8ef90070 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/ValueObjectVariable.h @@ -0,0 +1,87 @@ +//===-- ValueObjectVariable.h -----------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ValueObjectVariable_h_ +#define liblldb_ValueObjectVariable_h_ + +#include "lldb/Core/ValueObject.h" + +#include "lldb/Core/Value.h" +#include "lldb/Symbol/CompilerType.h" +#include "lldb/Utility/ConstString.h" +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/lldb-forward.h" + +#include <stddef.h> +#include <stdint.h> + +namespace lldb_private { +class DataExtractor; +class Declaration; +class Status; +class ExecutionContextScope; +class SymbolContextScope; + +// A ValueObject that contains a root variable that may or may not +// have children. +class ValueObjectVariable : public ValueObject { +public: + ~ValueObjectVariable() override; + + static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, + const lldb::VariableSP &var_sp); + + uint64_t GetByteSize() override; + + ConstString GetTypeName() override; + + ConstString GetQualifiedTypeName() override; + + ConstString GetDisplayTypeName() override; + + size_t CalculateNumChildren(uint32_t max) override; + + lldb::ValueType GetValueType() const override; + + bool IsInScope() override; + + lldb::ModuleSP GetModule() override; + + SymbolContextScope *GetSymbolContextScope() override; + + bool GetDeclaration(Declaration &decl) override; + + const char *GetLocationAsCString() override; + + bool SetValueFromCString(const char *value_str, Status &error) override; + + bool SetData(DataExtractor &data, Status &error) override; + + lldb::VariableSP GetVariable() override { return m_variable_sp; } + +protected: + bool UpdateValue() override; + + CompilerType GetCompilerTypeImpl() override; + + lldb::VariableSP + m_variable_sp; ///< The variable that this value object is based upon + Value m_resolved_value; ///< The value that DWARFExpression resolves this + ///variable to before we patch it up + +private: + ValueObjectVariable(ExecutionContextScope *exe_scope, + const lldb::VariableSP &var_sp); + // For ValueObject only + DISALLOW_COPY_AND_ASSIGN(ValueObjectVariable); +}; + +} // namespace lldb_private + +#endif // liblldb_ValueObjectVariable_h_ diff --git a/contrib/llvm-project/lldb/include/lldb/Core/dwarf.h b/contrib/llvm-project/lldb/include/lldb/Core/dwarf.h new file mode 100644 index 000000000000..832109e55c70 --- /dev/null +++ b/contrib/llvm-project/lldb/include/lldb/Core/dwarf.h @@ -0,0 +1,76 @@ +//===-- dwarf.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 DebugBase_dwarf_h_ +#define DebugBase_dwarf_h_ + +#include "lldb/Utility/RangeMap.h" +#include <stdint.h> + +// Get the DWARF constant definitions from llvm +#include "llvm/BinaryFormat/Dwarf.h" + +// and stuff them in our default namespace +using namespace llvm::dwarf; + +typedef uint32_t dw_uleb128_t; +typedef int32_t dw_sleb128_t; +typedef uint16_t dw_attr_t; +typedef uint16_t dw_form_t; +typedef llvm::dwarf::Tag dw_tag_t; +typedef uint64_t dw_addr_t; // Dwarf address define that must be big enough for + // any addresses in the compile units that get + // parsed + +typedef uint32_t dw_offset_t; // Dwarf Debug Information Entry offset for any + // offset into the file + +/* Constants */ +#define DW_INVALID_OFFSET (~(dw_offset_t)0) +#define DW_INVALID_INDEX 0xFFFFFFFFul + +// #define DW_ADDR_none 0x0 + +#define DW_EH_PE_MASK_ENCODING 0x0F + +//// The following are used only internally within lldb - don't +//// document them in the llvm Dwarf.h header file, we won't see +//// them in executable files anywhere. +//// These constants fit between DW_OP_lo_user (0xe0) and DW_OP_hi_user (0xff). +// +//#define DW_OP_APPLE_array_ref 0xEE // first pops index, then pops array; +//pushes array[index] +//#define DW_OP_APPLE_extern 0xEF // ULEB128 index of external object +//(i.e., an entity from the program that was used in the expression) +#define DW_OP_APPLE_uninit \ + 0xF0 // This is actually generated by some apple compilers in locations lists +//#define DW_OP_APPLE_assign 0xF1 // pops value off and assigns it to +//second item on stack (2nd item must have assignable context) +//#define DW_OP_APPLE_address_of 0xF2 // gets the address of the top stack +//item (top item must be a variable, or have value_type that is an address +//already) +//#define DW_OP_APPLE_value_of 0xF3 // pops the value off the stack and +//pushes the value of that object (top item must be a variable, or expression +//local) +//#define DW_OP_APPLE_deref_type 0xF4 // gets the address of the top stack +//item (top item must be a variable, or a clang type) +//#define DW_OP_APPLE_expr_local 0xF5 // ULEB128 expression local index +//#define DW_OP_APPLE_constf 0xF6 // 1 byte float size, followed by +//constant float data +//#define DW_OP_APPLE_scalar_cast 0xF7 // Cast top of stack to 2nd in stack's +//type leaving all items in place +//#define DW_OP_APPLE_clang_cast 0xF8 // pointer size clang::Type * off the +//stack and cast top stack item to this type +//#define DW_OP_APPLE_clear 0xFE // clears the entire expression stack, +//ok if the stack is empty +//#define DW_OP_APPLE_error 0xFF // Stops expression evaluation and +//returns an error (no args) + +typedef lldb_private::RangeArray<dw_addr_t, dw_addr_t, 2> DWARFRangeList; + +#endif // DebugBase_dwarf_h_ |