diff options
author | Ed Maste <emaste@FreeBSD.org> | 2013-08-23 17:46:38 +0000 |
---|---|---|
committer | Ed Maste <emaste@FreeBSD.org> | 2013-08-23 17:46:38 +0000 |
commit | f034231a6a1fd5d6395206c1651de8cd9402cca3 (patch) | |
tree | f561dabc721ad515599172c16da3a4400b7f4aec /include/lldb/Symbol | |
download | src-f034231a6a1fd5d6395206c1651de8cd9402cca3.tar.gz src-f034231a6a1fd5d6395206c1651de8cd9402cca3.zip |
Import lldb as of SVN r188801
(A number of files not required for the FreeBSD build have been removed.)
Sponsored by: DARPA, AFRL
Notes
Notes:
svn path=/vendor/lldb/dist/; revision=254721
Diffstat (limited to 'include/lldb/Symbol')
31 files changed, 8808 insertions, 0 deletions
diff --git a/include/lldb/Symbol/Block.h b/include/lldb/Symbol/Block.h new file mode 100644 index 000000000000..a2d703b9069c --- /dev/null +++ b/include/lldb/Symbol/Block.h @@ -0,0 +1,496 @@ +//===-- Block.h -------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Block_h_ +#define liblldb_Block_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Core/RangeMap.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/UserID.h" +#include "lldb/Symbol/LineEntry.h" +#include "lldb/Symbol/SymbolContext.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Block Block.h "lldb/Symbol/Block.h" +/// @brief A class that describes a single lexical block. +/// +/// A Function object owns a BlockList object which owns one or more +/// Block objects. The BlockList object contains a section offset +/// address range, and Block objects contain one or more ranges +/// which are offsets into that range. Blocks are can have discontiguous +/// ranges within the BlockList adress range, and each block can +/// contain child blocks each with their own sets of ranges. +/// +/// Each block has a variable list that represents local, argument, and +/// static variables that are scoped to the block. +/// +/// Inlined functions are representated by attaching a +/// InlineFunctionInfo shared pointer object to a block. Inlined +/// functions are represented as named blocks. +//---------------------------------------------------------------------- +class Block : + public UserID, + public SymbolContextScope +{ +public: + typedef RangeArray<uint32_t, uint32_t, 1> RangeList; + typedef RangeList::Entry Range; + + //------------------------------------------------------------------ + /// Construct with a User ID \a uid, \a depth. + /// + /// Initialize this block with the specified UID \a uid. The + /// \a depth in the \a block_list is used to represent the parent, + /// sibling, and child block information and also allows for partial + /// parsing at the block level. + /// + /// @param[in] uid + /// The UID for a given block. This value is given by the + /// SymbolFile plug-in and can be any value that helps the + /// SymbolFile plug-in to match this block back to the debug + /// information data that it parses for further or more in + /// depth parsing. Common values would be the index into a + /// table, or an offset into the debug information. + /// + /// @param[in] depth + /// The integer depth of this block in the block list hierarchy. + /// + /// @param[in] block_list + /// The block list that this object belongs to. + /// + /// @see BlockList + //------------------------------------------------------------------ + Block (lldb::user_id_t uid); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + virtual ~Block (); + + //------------------------------------------------------------------ + /// Add a child to this object. + /// + /// @param[in] child_block_sp + /// A shared pointer to a child block that will get added to + /// this block. + //------------------------------------------------------------------ + void + AddChild (const lldb::BlockSP &child_block_sp); + + //------------------------------------------------------------------ + /// Add a new offset range to this block. + /// + /// @param[in] start_offset + /// An offset into this Function's address range that + /// describes the start address of a range for this block. + /// + /// @param[in] end_offset + /// An offset into this Function's address range that + /// describes the end address of a range for this block. + //------------------------------------------------------------------ + void + AddRange (const Range& range); + + void + FinalizeRanges (); + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + CalculateSymbolContext(SymbolContext* sc); + + virtual lldb::ModuleSP + CalculateSymbolContextModule (); + + virtual CompileUnit * + CalculateSymbolContextCompileUnit (); + + virtual Function * + CalculateSymbolContextFunction (); + + virtual Block * + CalculateSymbolContextBlock (); + + //------------------------------------------------------------------ + /// Check if an offset is in one of the block offset ranges. + /// + /// @param[in] range_offset + /// An offset into the Function's address range. + /// + /// @return + /// Returns \b true if \a range_offset falls in one of this + /// block's ranges, \b false otherwise. + //------------------------------------------------------------------ + bool + Contains (lldb::addr_t range_offset) const; + + //------------------------------------------------------------------ + /// Check if a offset range is in one of the block offset ranges. + /// + /// @param[in] range + /// An offset range into the Function's address range. + /// + /// @return + /// Returns \b true if \a range falls in one of this + /// block's ranges, \b false otherwise. + //------------------------------------------------------------------ + bool + Contains (const Range& range) const; + + //------------------------------------------------------------------ + /// Check if this object contains "block" as a child block at any + /// depth. + /// + /// @param[in] block + /// A potential child block. + /// + /// @return + /// Returns \b true if \a block is a child of this block, \b + /// false otherwise. + //------------------------------------------------------------------ + bool + Contains (const Block *block) const; + + //------------------------------------------------------------------ + /// Dump the block contents. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] base_addr + /// The resolved start address of the Function's address + /// range. This should be resolved as the file or load address + /// prior to passing the value into this function for dumping. + /// + /// @param[in] depth + /// Limit the number of levels deep that this function should + /// print as this block can contain child blocks. Specify + /// INT_MAX to dump all child blocks. + /// + /// @param[in] show_context + /// If \b true, variables will dump their context information. + //------------------------------------------------------------------ + void + Dump (Stream *s, lldb::addr_t base_addr, int32_t depth, bool show_context) const; + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::DumpSymbolContext(Stream*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + DumpSymbolContext(Stream *s); + + void + DumpAddressRanges (Stream *s, + lldb::addr_t base_addr); + + void + GetDescription (Stream *s, + Function *function, + lldb::DescriptionLevel level, + Target *target) const; + + //------------------------------------------------------------------ + /// Get the parent block. + /// + /// @return + /// The parent block pointer, or NULL if this block has no + /// parent. + //------------------------------------------------------------------ + Block * + GetParent () const; + + + //------------------------------------------------------------------ + /// Get the inlined block that contains this block. + /// + /// @return + /// If this block contains inlined function info, it will return + /// this block, else parent blocks will be searched to see if + /// any contain this block. NULL will be returned if this block + /// nor any parent blocks are inlined function blocks. + //------------------------------------------------------------------ + Block * + GetContainingInlinedBlock (); + + //------------------------------------------------------------------ + /// Get the inlined parent block for this block. + /// + /// @return + /// The parent block pointer, or NULL if this block has no + /// parent. + //------------------------------------------------------------------ + Block * + GetInlinedParent (); + + //------------------------------------------------------------------ + /// Get the sibling block for this block. + /// + /// @return + /// The sibling block pointer, or NULL if this block has no + /// sibling. + //------------------------------------------------------------------ + Block * + GetSibling () const; + + //------------------------------------------------------------------ + /// Get the first child block. + /// + /// @return + /// The first child block pointer, or NULL if this block has no + /// children. + //------------------------------------------------------------------ + Block * + GetFirstChild () const + { + if (m_children.empty()) + return NULL; + return m_children.front().get(); + } + + //------------------------------------------------------------------ + /// Get the variable list for this block only. + /// + /// @param[in] can_create + /// If \b true, the variables can be parsed if they already + /// haven't been, else the current state of the block will be + /// returned. + /// + /// @return + /// A variable list shared pointer that contains all variables + /// for this block. + //------------------------------------------------------------------ + lldb::VariableListSP + GetBlockVariableList (bool can_create); + + + //------------------------------------------------------------------ + /// Get the variable list for this block and optionally all child + /// blocks if \a get_child_variables is \b true. + /// + /// @param[in] get_child_variables + /// If \b true, all variables from all child blocks will be + /// added to the variable list. + /// + /// @param[in] can_create + /// If \b true, the variables can be parsed if they already + /// haven't been, else the current state of the block will be + /// returned. Passing \b true for this parameter can be used + /// to see the current state of what has been parsed up to this + /// point. + /// + /// @param[in] add_inline_child_block_variables + /// If this is \b false, no child variables of child blocks + /// that are inlined functions will be gotten. If \b true then + /// all child variables will be added regardless of whether they + /// come from inlined functions or not. + /// + /// @return + /// A variable list shared pointer that contains all variables + /// for this block. + //------------------------------------------------------------------ + uint32_t + AppendBlockVariables (bool can_create, + bool get_child_block_variables, + bool stop_if_child_block_is_inlined_function, + VariableList *variable_list); + + //------------------------------------------------------------------ + /// Appends the variables from this block, and optionally from all + /// parent blocks, to \a variable_list. + /// + /// @param[in] can_create + /// If \b true, the variables can be parsed if they already + /// haven't been, else the current state of the block will be + /// returned. Passing \b true for this parameter can be used + /// to see the current state of what has been parsed up to this + /// point. + /// + /// @param[in] get_parent_variables + /// If \b true, all variables from all parent blocks will be + /// added to the variable list. + /// + /// @param[in] stop_if_block_is_inlined_function + /// If \b true, all variables from all parent blocks will be + /// added to the variable list until there are no parent blocks + /// or the parent block has inlined function info. + /// + /// @param[in/out] variable_list + /// All variables in this block, and optionally all parent + /// blocks will be added to this list. + /// + /// @return + /// The number of variable that were appended to \a + /// variable_list. + //------------------------------------------------------------------ + uint32_t + AppendVariables (bool can_create, + bool get_parent_variables, + bool stop_if_block_is_inlined_function, + VariableList *variable_list); + + //------------------------------------------------------------------ + /// Get const accessor for any inlined function information. + /// + /// @return + /// A comst pointer to any inlined function information, or NULL + /// if this is a regular block. + //------------------------------------------------------------------ + const InlineFunctionInfo* + GetInlinedFunctionInfo () const + { + return m_inlineInfoSP.get(); + } + + clang::DeclContext * + GetClangDeclContext(); + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// Returns the cost of this object plus any owned objects from the + /// ranges, variables, and inline function information. + /// + /// @return + /// The number of bytes that this object occupies in memory. + //------------------------------------------------------------------ + size_t + MemorySize() const; + + //------------------------------------------------------------------ + /// Set accessor for any inlined function information. + /// + /// @param[in] name + /// The method name for the inlined function. This value should + /// not be NULL. + /// + /// @param[in] mangled + /// The mangled method name for the inlined function. This can + /// be NULL if there is no mangled name for an inlined function + /// or if the name is the same as \a name. + /// + /// @param[in] decl_ptr + /// A optional pointer to declaration information for the + /// inlined function information. This value can be NULL to + /// indicate that no declaration information is available. + /// + /// @param[in] call_decl_ptr + /// Optional calling location declaration information that + /// describes from where this inlined function was called. + //------------------------------------------------------------------ + void + SetInlinedFunctionInfo (const char *name, + const char *mangled, + const Declaration *decl_ptr, + const Declaration *call_decl_ptr); + + + void + SetParentScope (SymbolContextScope *parent_scope) + { + m_parent_scope = parent_scope; + } + + //------------------------------------------------------------------ + /// Set accessor for the variable list. + /// + /// Called by the SymbolFile plug-ins after they have parsed the + /// variable lists and are ready to hand ownership of the list over + /// to this object. + /// + /// @param[in] variable_list_sp + /// A shared pointer to a VariableList. + //------------------------------------------------------------------ + void + SetVariableList (lldb::VariableListSP& variable_list_sp) + { + m_variable_list_sp = variable_list_sp; + } + + + + bool + BlockInfoHasBeenParsed() const + { + return m_parsed_block_info; + } + + void + SetBlockInfoHasBeenParsed (bool b, bool set_children); + + Block * + FindBlockByID (lldb::user_id_t block_id); + + size_t + GetNumRanges () const + { + return m_ranges.GetSize(); + } + + bool + GetRangeContainingOffset (const lldb::addr_t offset, Range &range); + + bool + GetRangeContainingAddress (const Address& addr, AddressRange &range); + + bool + GetRangeContainingLoadAddress (lldb::addr_t load_addr, Target &target, AddressRange &range); + + uint32_t + GetRangeIndexContainingAddress (const Address& addr); + + //------------------------------------------------------------------ + // Since blocks might have multiple discontiguous addresss ranges, + // we need to be able to get at any of the address ranges in a block. + //------------------------------------------------------------------ + bool + GetRangeAtIndex (uint32_t range_idx, + AddressRange &range); + + bool + GetStartAddress (Address &addr); + + void + SetDidParseVariables (bool b, bool set_children); + +protected: + typedef std::vector<lldb::BlockSP> collection; + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + SymbolContextScope *m_parent_scope; + collection m_children; + RangeList m_ranges; + lldb::InlineFunctionInfoSP m_inlineInfoSP; ///< Inlined function information. + lldb::VariableListSP m_variable_list_sp; ///< The variable list for all local, static and paramter variables scoped to this block. + bool m_parsed_block_info:1, ///< Set to true if this block and it's children have all been parsed + m_parsed_block_variables:1, + m_parsed_child_blocks:1; + + // A parent of child blocks can be asked to find a sibling block given + // one of its child blocks + Block * + GetSiblingForChild (const Block *child_block) const; + +private: + DISALLOW_COPY_AND_ASSIGN (Block); +}; + + +} // namespace lldb_private + +#endif // liblldb_Block_h_ diff --git a/include/lldb/Symbol/ClangASTContext.h b/include/lldb/Symbol/ClangASTContext.h new file mode 100644 index 000000000000..75fc07b480e1 --- /dev/null +++ b/include/lldb/Symbol/ClangASTContext.h @@ -0,0 +1,441 @@ +//===-- ClangASTContext.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangASTContext_h_ +#define liblldb_ClangASTContext_h_ + +// C Includes +#include <stdint.h> + +// C++ Includes +#include <string> +#include <vector> + +// Other libraries and framework includes +#include "llvm/ADT/OwningPtr.h" +#include "llvm/ADT/SmallVector.h" +#include "clang/AST/TemplateBase.h" + + +// Project includes +#include "lldb/lldb-enumerations.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Symbol/ClangASTType.h" + +namespace lldb_private { + +class Declaration; + +class ClangASTContext +{ +public: + typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *); + typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton, clang::ObjCInterfaceDecl *); + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + ClangASTContext (const char *triple = NULL); + + ~ClangASTContext(); + + clang::ASTContext * + getASTContext(); + + clang::Builtin::Context * + getBuiltinContext(); + + clang::IdentifierTable * + getIdentifierTable(); + + clang::LangOptions * + getLanguageOptions(); + + clang::SelectorTable * + getSelectorTable(); + + clang::FileManager * + getFileManager(); + + clang::SourceManager * + getSourceManager(); + + clang::DiagnosticsEngine * + getDiagnosticsEngine(); + + clang::DiagnosticConsumer * + getDiagnosticConsumer(); + + clang::TargetOptions * + getTargetOptions(); + + clang::TargetInfo * + getTargetInfo(); + + void + Clear(); + + const char * + GetTargetTriple (); + + void + SetTargetTriple (const char *target_triple); + + void + SetArchitecture (const ArchSpec &arch); + + bool + HasExternalSource (); + + void + SetExternalSource (llvm::OwningPtr<clang::ExternalASTSource> &ast_source_ap); + + void + RemoveExternalSource (); + + bool + GetCompleteDecl (clang::Decl *decl) + { + return ClangASTContext::GetCompleteDecl(getASTContext(), decl); + } + + static bool + GetCompleteDecl (clang::ASTContext *ast, + clang::Decl *decl); + + void SetMetadataAsUserID (const void *object, + lldb::user_id_t user_id); + + void SetMetadata (const void *object, + ClangASTMetadata &meta_data) + { + SetMetadata(getASTContext(), object, meta_data); + } + + static void + SetMetadata (clang::ASTContext *ast, + const void *object, + ClangASTMetadata &meta_data); + + ClangASTMetadata * + GetMetadata (const void *object) + { + return GetMetadata(getASTContext(), object); + } + + static ClangASTMetadata * + GetMetadata (clang::ASTContext *ast, + const void *object); + + //------------------------------------------------------------------ + // Basic Types + //------------------------------------------------------------------ + ClangASTType + GetBuiltinTypeForEncodingAndBitSize (lldb::Encoding encoding, + uint32_t bit_size); + + static ClangASTType + GetBuiltinTypeForEncodingAndBitSize (clang::ASTContext *ast, + lldb::Encoding encoding, + uint32_t bit_size); + + ClangASTType + GetBasicType (lldb::BasicType type); + + static ClangASTType + GetBasicType (clang::ASTContext *ast, lldb::BasicType type); + + static ClangASTType + GetBasicType (clang::ASTContext *ast, const ConstString &name); + + static lldb::BasicType + GetBasicTypeEnumeration (const ConstString &name); + + ClangASTType + GetBuiltinTypeForDWARFEncodingAndBitSize ( + const char *type_name, + uint32_t dw_ate, + uint32_t bit_size); + + ClangASTType + GetCStringType(bool is_const); + + static ClangASTType + GetUnknownAnyType(clang::ASTContext *ast); + + ClangASTType + GetUnknownAnyType() + { + return ClangASTContext::GetUnknownAnyType(getASTContext()); + } + + uint32_t + GetPointerByteSize (); + + static clang::DeclContext * + GetTranslationUnitDecl (clang::ASTContext *ast); + + clang::DeclContext * + GetTranslationUnitDecl () + { + return GetTranslationUnitDecl (getASTContext()); + } + + static bool + GetClassMethodInfoForDeclContext (clang::DeclContext *decl_ctx, + lldb::LanguageType &language, + bool &is_instance_method, + ConstString &language_object_name); + + static ClangASTType + CopyType(clang::ASTContext *dest_context, + ClangASTType source_type); + + static clang::Decl * + CopyDecl (clang::ASTContext *dest_context, + clang::ASTContext *source_context, + clang::Decl *source_decl); + + static bool + AreTypesSame(ClangASTType type1, + ClangASTType type2, + bool ignore_qualifiers = false); + + ClangASTType + GetTypeForDecl (clang::TagDecl *decl); + + ClangASTType + GetTypeForDecl (clang::ObjCInterfaceDecl *objc_decl); + + //------------------------------------------------------------------ + // Structure, Unions, Classes + //------------------------------------------------------------------ + + static clang::AccessSpecifier + ConvertAccessTypeToAccessSpecifier (lldb::AccessType access); + + static clang::AccessSpecifier + UnifyAccessSpecifiers (clang::AccessSpecifier lhs, clang::AccessSpecifier rhs); + + static uint32_t + GetNumBaseClasses (const clang::CXXRecordDecl *cxx_record_decl, + bool omit_empty_base_classes); + + static uint32_t + GetIndexForRecordBase (const clang::RecordDecl *record_decl, + const clang::CXXBaseSpecifier *base_spec, + bool omit_empty_base_classes); + + ClangASTType + CreateRecordType (clang::DeclContext *decl_ctx, + lldb::AccessType access_type, + const char *name, + int kind, + lldb::LanguageType language, + ClangASTMetadata *metadata = NULL); + + class TemplateParameterInfos + { + public: + bool + IsValid() const + { + if (args.empty()) + return false; + return args.size() == names.size(); + } + + size_t + GetSize () const + { + if (IsValid()) + return args.size(); + return 0; + } + + llvm::SmallVector<const char *, 8> names; + llvm::SmallVector<clang::TemplateArgument, 8> args; + }; + + clang::FunctionTemplateDecl * + CreateFunctionTemplateDecl (clang::DeclContext *decl_ctx, + clang::FunctionDecl *func_decl, + const char *name, + const TemplateParameterInfos &infos); + + void + CreateFunctionTemplateSpecializationInfo (clang::FunctionDecl *func_decl, + clang::FunctionTemplateDecl *Template, + const TemplateParameterInfos &infos); + + clang::ClassTemplateDecl * + CreateClassTemplateDecl (clang::DeclContext *decl_ctx, + lldb::AccessType access_type, + const char *class_name, + int kind, + const TemplateParameterInfos &infos); + + clang::ClassTemplateSpecializationDecl * + CreateClassTemplateSpecializationDecl (clang::DeclContext *decl_ctx, + clang::ClassTemplateDecl *class_template_decl, + int kind, + const TemplateParameterInfos &infos); + + ClangASTType + CreateClassTemplateSpecializationType (clang::ClassTemplateSpecializationDecl *class_template_specialization_decl); + + static clang::DeclContext * + GetAsDeclContext (clang::CXXMethodDecl *cxx_method_decl); + + static clang::DeclContext * + GetAsDeclContext (clang::ObjCMethodDecl *objc_method_decl); + + + static bool + CheckOverloadedOperatorKindParameterCount (uint32_t op_kind, + uint32_t num_params); + + bool + FieldIsBitfield (clang::FieldDecl* field, + uint32_t& bitfield_bit_size); + + static bool + FieldIsBitfield (clang::ASTContext *ast, + clang::FieldDecl* field, + uint32_t& bitfield_bit_size); + + static bool + RecordHasFields (const clang::RecordDecl *record_decl); + + + ClangASTType + CreateObjCClass (const char *name, + clang::DeclContext *decl_ctx, + bool isForwardDecl, + bool isInternal, + ClangASTMetadata *metadata = NULL); + + // Returns a mask containing bits from the ClangASTContext::eTypeXXX enumerations + + + //------------------------------------------------------------------ + // Namespace Declarations + //------------------------------------------------------------------ + + clang::NamespaceDecl * + GetUniqueNamespaceDeclaration (const char *name, + clang::DeclContext *decl_ctx); + + //------------------------------------------------------------------ + // Function Types + //------------------------------------------------------------------ + + clang::FunctionDecl * + CreateFunctionDeclaration (clang::DeclContext *decl_ctx, + const char *name, + const ClangASTType &function_Type, + int storage, + bool is_inline); + + static ClangASTType + CreateFunctionType (clang::ASTContext *ast, + const ClangASTType &result_type, + const ClangASTType *args, + unsigned num_args, + bool is_variadic, + unsigned type_quals); + + ClangASTType + CreateFunctionType (const ClangASTType &result_type, + const ClangASTType *args, + unsigned num_args, + bool is_variadic, + unsigned type_quals) + { + return ClangASTContext::CreateFunctionType(getASTContext(), + result_type, + args, + num_args, + is_variadic, + type_quals); + } + + clang::ParmVarDecl * + CreateParameterDeclaration (const char *name, + const ClangASTType ¶m_type, + int storage); + + void + SetFunctionParameters (clang::FunctionDecl *function_decl, + clang::ParmVarDecl **params, + unsigned num_params); + + //------------------------------------------------------------------ + // Array Types + //------------------------------------------------------------------ + + ClangASTType + CreateArrayType (const ClangASTType &element_type, + size_t element_count, + bool is_vector); + + //------------------------------------------------------------------ + // Enumeration Types + //------------------------------------------------------------------ + ClangASTType + CreateEnumerationType (const char *name, + clang::DeclContext *decl_ctx, + const Declaration &decl, + const ClangASTType &integer_qual_type); + + //------------------------------------------------------------------ + // Floating point functions + //------------------------------------------------------------------ + + ClangASTType + GetFloatTypeFromBitSize (size_t bit_size) + { + return GetFloatTypeFromBitSize (getASTContext(), bit_size); + } + + static ClangASTType + GetFloatTypeFromBitSize (clang::ASTContext *ast, + size_t bit_size); +protected: + //------------------------------------------------------------------ + // Classes that inherit from ClangASTContext can see and modify these + //------------------------------------------------------------------ + std::string m_target_triple; + std::unique_ptr<clang::ASTContext> m_ast_ap; + std::unique_ptr<clang::LangOptions> m_language_options_ap; + std::unique_ptr<clang::FileManager> m_file_manager_ap; + std::unique_ptr<clang::FileSystemOptions> m_file_system_options_ap; + std::unique_ptr<clang::SourceManager> m_source_manager_ap; + std::unique_ptr<clang::DiagnosticsEngine> m_diagnostics_engine_ap; + std::unique_ptr<clang::DiagnosticConsumer> m_diagnostic_consumer_ap; + llvm::IntrusiveRefCntPtr<clang::TargetOptions> m_target_options_rp; + std::unique_ptr<clang::TargetInfo> m_target_info_ap; + std::unique_ptr<clang::IdentifierTable> m_identifier_table_ap; + std::unique_ptr<clang::SelectorTable> m_selector_table_ap; + std::unique_ptr<clang::Builtin::Context> m_builtins_ap; + CompleteTagDeclCallback m_callback_tag_decl; + CompleteObjCInterfaceDeclCallback m_callback_objc_decl; + void * m_callback_baton; + uint32_t m_pointer_byte_size; +private: + //------------------------------------------------------------------ + // For ClangASTContext only + //------------------------------------------------------------------ + ClangASTContext(const ClangASTContext&); + const ClangASTContext& operator=(const ClangASTContext&); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangASTContext_h_ diff --git a/include/lldb/Symbol/ClangASTImporter.h b/include/lldb/Symbol/ClangASTImporter.h new file mode 100644 index 000000000000..10df7da893a8 --- /dev/null +++ b/include/lldb/Symbol/ClangASTImporter.h @@ -0,0 +1,371 @@ +//===-- ClangASTImporter.h --------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangASTImporter_h_ +#define liblldb_ClangASTImporter_h_ + +#include <map> +#include <set> + +#include "lldb/lldb-types.h" +#include "clang/AST/ASTImporter.h" +#include "clang/Basic/FileManager.h" +#include "clang/Basic/FileSystemOptions.h" +#include "lldb/Symbol/ClangNamespaceDecl.h" + +namespace lldb_private { + +class ClangASTMetrics +{ +public: + static void DumpCounters (Log *log); + static void ClearLocalCounters () + { + local_counters = { 0, 0, 0, 0, 0, 0 }; + } + + static void RegisterVisibleQuery () + { + ++global_counters.m_visible_query_count; + ++local_counters.m_visible_query_count; + } + + static void RegisterLexicalQuery () + { + ++global_counters.m_lexical_query_count; + ++local_counters.m_lexical_query_count; + } + + static void RegisterLLDBImport () + { + ++global_counters.m_lldb_import_count; + ++local_counters.m_lldb_import_count; + } + + static void RegisterClangImport () + { + ++global_counters.m_clang_import_count; + ++local_counters.m_clang_import_count; + } + + static void RegisterDeclCompletion () + { + ++global_counters.m_decls_completed_count; + ++local_counters.m_decls_completed_count; + } + + static void RegisterRecordLayout () + { + ++global_counters.m_record_layout_count; + ++local_counters.m_record_layout_count; + } + +private: + struct Counters + { + uint64_t m_visible_query_count; + uint64_t m_lexical_query_count; + uint64_t m_lldb_import_count; + uint64_t m_clang_import_count; + uint64_t m_decls_completed_count; + uint64_t m_record_layout_count; + }; + + static Counters global_counters; + static Counters local_counters; + + static void DumpCounters (Log *log, Counters &counters); +}; + +class ClangASTImporter +{ +public: + ClangASTImporter () : + m_file_manager(clang::FileSystemOptions()) + { + } + + clang::QualType + CopyType (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + clang::QualType type); + + lldb::clang_type_t + CopyType (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + lldb::clang_type_t type); + + clang::Decl * + CopyDecl (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + clang::Decl *decl); + + lldb::clang_type_t + DeportType (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + lldb::clang_type_t type); + + clang::Decl * + DeportDecl (clang::ASTContext *dst_ctx, + clang::ASTContext *src_ctx, + clang::Decl *decl); + + void + CompleteDecl (clang::Decl *decl); + + bool + CompleteTagDecl (clang::TagDecl *decl); + + bool + CompleteTagDeclWithOrigin (clang::TagDecl *decl, clang::TagDecl *origin); + + bool + CompleteObjCInterfaceDecl (clang::ObjCInterfaceDecl *interface_decl); + + bool + RequireCompleteType (clang::QualType type); + + bool + ResolveDeclOrigin (const clang::Decl *decl, clang::Decl **original_decl, clang::ASTContext **original_ctx) + { + DeclOrigin origin = GetDeclOrigin(decl); + + if (original_decl) + *original_decl = origin.decl; + + if (original_ctx) + *original_ctx = origin.ctx; + + return origin.Valid(); + } + + void + SetDeclOrigin (const clang::Decl *decl, clang::Decl *original_decl); + + ClangASTMetadata * + GetDeclMetadata (const clang::Decl *decl); + + // + // Namespace maps + // + + typedef std::vector < std::pair<lldb::ModuleSP, ClangNamespaceDecl> > NamespaceMap; + typedef std::shared_ptr<NamespaceMap> NamespaceMapSP; + + void RegisterNamespaceMap (const clang::NamespaceDecl *decl, + NamespaceMapSP &namespace_map); + + NamespaceMapSP GetNamespaceMap (const clang::NamespaceDecl *decl); + + void BuildNamespaceMap (const clang::NamespaceDecl *decl); + + // + // Comleters for maps + // + + class MapCompleter + { + public: + virtual ~MapCompleter (); + + virtual void CompleteNamespaceMap (NamespaceMapSP &namespace_map, + const ConstString &name, + NamespaceMapSP &parent_map) const = 0; + }; + + void InstallMapCompleter (clang::ASTContext *dst_ctx, MapCompleter &completer) + { + ASTContextMetadataSP context_md; + ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); + + if (context_md_iter == m_metadata_map.end()) + { + context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx)); + m_metadata_map[dst_ctx] = context_md; + } + else + { + context_md = context_md_iter->second; + } + + context_md->m_map_completer = &completer; + } + + void ForgetDestination (clang::ASTContext *dst_ctx); + void ForgetSource (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx); +private: + struct DeclOrigin + { + DeclOrigin () : + ctx(NULL), + decl(NULL) + { + } + + DeclOrigin (clang::ASTContext *_ctx, + clang::Decl *_decl) : + ctx(_ctx), + decl(_decl) + { + } + + DeclOrigin (const DeclOrigin &rhs) + { + ctx = rhs.ctx; + decl = rhs.decl; + } + + void operator= (const DeclOrigin &rhs) + { + ctx = rhs.ctx; + decl = rhs.decl; + } + + bool + Valid () + { + return (ctx != NULL || decl != NULL); + } + + clang::ASTContext *ctx; + clang::Decl *decl; + }; + + typedef std::map<const clang::Decl *, DeclOrigin> OriginMap; + + class Minion : public clang::ASTImporter + { + public: + Minion (ClangASTImporter &master, + clang::ASTContext *target_ctx, + clang::ASTContext *source_ctx) : + clang::ASTImporter(*target_ctx, + master.m_file_manager, + *source_ctx, + master.m_file_manager, + true /*minimal*/), + m_decls_to_deport(NULL), + m_decls_already_deported(NULL), + m_master(master), + m_source_ctx(source_ctx) + { + } + + // A call to "InitDeportWorkQueues" puts the minion into deport mode. + // In deport mode, every copied Decl that could require completion is + // recorded and placed into the decls_to_deport set. + // + // A call to "ExecuteDeportWorkQueues" completes all the Decls that + // are in decls_to_deport, adding any Decls it sees along the way that + // it hasn't already deported. It proceeds until decls_to_deport is + // empty. + // + // These calls must be paired. Leaving a minion in deport mode or + // trying to start deport minion with a new pair of queues will result + // in an assertion failure. + + void InitDeportWorkQueues (std::set<clang::NamedDecl *> *decls_to_deport, + std::set<clang::NamedDecl *> *decls_already_deported); + void ExecuteDeportWorkQueues (); + + void ImportDefinitionTo (clang::Decl *to, clang::Decl *from); + + clang::Decl *Imported (clang::Decl *from, clang::Decl *to); + + std::set<clang::NamedDecl *> *m_decls_to_deport; + std::set<clang::NamedDecl *> *m_decls_already_deported; + ClangASTImporter &m_master; + clang::ASTContext *m_source_ctx; + }; + + typedef std::shared_ptr<Minion> MinionSP; + typedef std::map<clang::ASTContext *, MinionSP> MinionMap; + typedef std::map<const clang::NamespaceDecl *, NamespaceMapSP> NamespaceMetaMap; + + struct ASTContextMetadata + { + ASTContextMetadata(clang::ASTContext *dst_ctx) : + m_dst_ctx (dst_ctx), + m_minions (), + m_origins (), + m_namespace_maps (), + m_map_completer (NULL) + { + } + + clang::ASTContext *m_dst_ctx; + MinionMap m_minions; + OriginMap m_origins; + + NamespaceMetaMap m_namespace_maps; + MapCompleter *m_map_completer; + }; + + typedef std::shared_ptr<ASTContextMetadata> ASTContextMetadataSP; + typedef std::map<const clang::ASTContext *, ASTContextMetadataSP> ContextMetadataMap; + + ContextMetadataMap m_metadata_map; + + ASTContextMetadataSP + GetContextMetadata (clang::ASTContext *dst_ctx) + { + ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); + + if (context_md_iter == m_metadata_map.end()) + { + ASTContextMetadataSP context_md = ASTContextMetadataSP(new ASTContextMetadata(dst_ctx)); + m_metadata_map[dst_ctx] = context_md; + return context_md; + } + else + { + return context_md_iter->second; + } + } + + ASTContextMetadataSP + MaybeGetContextMetadata (clang::ASTContext *dst_ctx) + { + ContextMetadataMap::iterator context_md_iter = m_metadata_map.find(dst_ctx); + + if (context_md_iter != m_metadata_map.end()) + return context_md_iter->second; + else + return ASTContextMetadataSP(); + } + + MinionSP + GetMinion (clang::ASTContext *dst_ctx, clang::ASTContext *src_ctx) + { + ASTContextMetadataSP context_md = GetContextMetadata(dst_ctx); + + MinionMap &minions = context_md->m_minions; + MinionMap::iterator minion_iter = minions.find(src_ctx); + + if (minion_iter == minions.end()) + { + MinionSP minion = MinionSP(new Minion(*this, dst_ctx, src_ctx)); + minions[src_ctx] = minion; + return minion; + } + else + { + return minion_iter->second; + } + } + + DeclOrigin + GetDeclOrigin (const clang::Decl *decl); + + clang::FileManager m_file_manager; +}; + +} + +#endif diff --git a/include/lldb/Symbol/ClangASTType.h b/include/lldb/Symbol/ClangASTType.h new file mode 100644 index 000000000000..d9e754e8ceb9 --- /dev/null +++ b/include/lldb/Symbol/ClangASTType.h @@ -0,0 +1,679 @@ +//===-- ClangASTType.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangASTType_h_ +#define liblldb_ClangASTType_h_ + +#include <string> +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "clang/AST/Type.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// A class that can carry around a clang ASTContext and a opaque clang +// QualType. A clang::QualType can be easily reconstructed from an +// opaque clang type and often the ASTContext is needed when doing +// various type related tasks, so this class allows both items to travel +// in a single very lightweight class that can be used. There are many +// static equivalents of the member functions that allow the ASTContext +// and the opaque clang QualType to be specified for ease of use and +// to avoid code duplication. +//---------------------------------------------------------------------- +class ClangASTType +{ +public: + enum { + eTypeHasChildren = (1u << 0), + eTypeHasValue = (1u << 1), + eTypeIsArray = (1u << 2), + eTypeIsBlock = (1u << 3), + eTypeIsBuiltIn = (1u << 4), + eTypeIsClass = (1u << 5), + eTypeIsCPlusPlus = (1u << 6), + eTypeIsEnumeration = (1u << 7), + eTypeIsFuncPrototype = (1u << 8), + eTypeIsMember = (1u << 9), + eTypeIsObjC = (1u << 10), + eTypeIsPointer = (1u << 11), + eTypeIsReference = (1u << 12), + eTypeIsStructUnion = (1u << 13), + eTypeIsTemplate = (1u << 14), + eTypeIsTypedef = (1u << 15), + eTypeIsVector = (1u << 16), + eTypeIsScalar = (1u << 17), + eTypeIsInteger = (1u << 18), + eTypeIsFloat = (1u << 19), + eTypeIsComplex = (1u << 20), + eTypeIsSigned = (1u << 21) + }; + + + //---------------------------------------------------------------------- + // Constructors and Destructors + //---------------------------------------------------------------------- + ClangASTType (clang::ASTContext *ast_context, lldb::clang_type_t type) : + m_type (type), + m_ast (ast_context) + { + } + + ClangASTType (clang::ASTContext *ast_context, clang::QualType qual_type); + + ClangASTType (const ClangASTType &rhs) : + m_type (rhs.m_type), + m_ast (rhs.m_ast) + { + } + + ClangASTType () : + m_type (0), + m_ast (0) + { + } + + ~ClangASTType(); + + //---------------------------------------------------------------------- + // Operators + //---------------------------------------------------------------------- + + const ClangASTType & + operator= (const ClangASTType &rhs) + { + m_type = rhs.m_type; + m_ast = rhs.m_ast; + return *this; + } + + + //---------------------------------------------------------------------- + // Tests + //---------------------------------------------------------------------- + + operator bool () const + { + return m_type != NULL && m_ast != NULL; + } + + bool + operator < (const ClangASTType &rhs) const + { + if (m_ast == rhs.m_ast) + return m_type < rhs.m_type; + return m_ast < rhs.m_ast; + } + + bool + IsValid () const + { + return m_type != NULL && m_ast != NULL; + } + + bool + IsArrayType (ClangASTType *element_type, + uint64_t *size, + bool *is_incomplete) const; + + bool + IsArrayOfScalarType () const; + + bool + IsAggregateType () const; + + bool + IsBeingDefined () const; + + bool + IsCharType () const; + + bool + IsCompleteType () const; + + bool + IsConst() const; + + bool + IsCStringType (uint32_t &length) const; + + bool + IsCXXClassType () const; + + bool + IsDefined() const; + + bool + IsFloatingPointType (uint32_t &count, bool &is_complex) const; + + bool + IsFunctionType (bool *is_variadic_ptr = NULL) const; + + bool + IsVariadicFunctionType () const; + + bool + IsFunctionPointerType () const; + + bool + IsIntegerType (bool &is_signed) const; + + bool + IsObjCClassType () const; + + bool + IsObjCClassTypeAndHasIVars (bool check_superclass) const; + + bool + IsObjCObjectOrInterfaceType () const; + + bool + IsObjCObjectPointerType (ClangASTType *target_type = NULL); + + bool + IsPolymorphicClass () const; + + bool + IsPossibleCPlusPlusDynamicType (ClangASTType *target_type = NULL) const + { + return IsPossibleDynamicType (target_type, true, false); + } + + bool + IsPossibleDynamicType (ClangASTType *target_type, // Can pass NULL + bool check_cplusplus, + bool check_objc) const; + + + bool + IsPointerToScalarType () const; + + bool + IsPointerType (ClangASTType *pointee_type = NULL) const; + + bool + IsPointerOrReferenceType (ClangASTType *pointee_type = NULL) const; + + bool + IsReferenceType (ClangASTType *pointee_type = NULL) const; + + bool + IsScalarType () const; + + bool + IsTypedefType () const; + + bool + IsVoidType () const; + + bool + GetCXXClassName (std::string &class_name) const; + + bool + GetObjCClassName (std::string &class_name); + + + //---------------------------------------------------------------------- + // Type Completion + //---------------------------------------------------------------------- + + bool + GetCompleteType () const; + + //---------------------------------------------------------------------- + // AST related queries + //---------------------------------------------------------------------- + + size_t + GetPointerByteSize () const; + + //---------------------------------------------------------------------- + // Accessors + //---------------------------------------------------------------------- + + clang::ASTContext * + GetASTContext() const + { + return m_ast; + } + + ConstString + GetConstQualifiedTypeName () const; + + ConstString + GetConstTypeName () const; + + std::string + GetTypeName () const; + + uint32_t + GetTypeInfo (ClangASTType *pointee_or_element_clang_type = NULL) const; + + lldb::LanguageType + GetMinimumLanguage (); + + lldb::clang_type_t + GetOpaqueQualType() const + { + return m_type; + } + + lldb::TypeClass + GetTypeClass () const; + + void + SetClangType (clang::ASTContext *ast, lldb::clang_type_t type) + { + m_ast = ast; + m_type = type; + } + + void + SetClangType (clang::ASTContext *ast, clang::QualType qual_type); + + unsigned + GetTypeQualifiers() const; + + //---------------------------------------------------------------------- + // Creating related types + //---------------------------------------------------------------------- + + ClangASTType + AddConstModifier () const; + + ClangASTType + AddRestrictModifier () const; + + ClangASTType + AddVolatileModifier () const; + + // Using the current type, create a new typedef to that type using "typedef_name" + // as the name and "decl_ctx" as the decl context. + ClangASTType + CreateTypedefType (const char *typedef_name, + clang::DeclContext *decl_ctx) const; + + ClangASTType + GetArrayElementType (uint64_t& stride) const; + + ClangASTType + GetCanonicalType () const; + + ClangASTType + GetFullyUnqualifiedType () const; + + // Returns -1 if this isn't a function of if the fucntion doesn't have a prototype + // Returns a value >= 0 if there is a prototype. + int + GetFunctionArgumentCount () const; + + ClangASTType + GetFunctionArgumentTypeAtIndex (size_t idx); + + ClangASTType + GetFunctionReturnType () const; + + ClangASTType + GetLValueReferenceType () const; + + ClangASTType + GetNonReferenceType () const; + + ClangASTType + GetPointeeType () const; + + ClangASTType + GetPointerType () const; + + ClangASTType + GetRValueReferenceType () const; + + // If the current object represents a typedef type, get the underlying type + ClangASTType + GetTypedefedType () const; + + ClangASTType + RemoveFastQualifiers () const; + + //---------------------------------------------------------------------- + // Create related types using the current type's AST + //---------------------------------------------------------------------- + ClangASTType + GetBasicTypeFromAST (lldb::BasicType basic_type) const; + + //---------------------------------------------------------------------- + // Exploring the type + //---------------------------------------------------------------------- + + uint64_t + GetByteSize () const; + + uint64_t + GetBitSize () const; + + lldb::Encoding + GetEncoding (uint64_t &count) const; + + lldb::Format + GetFormat () const; + + size_t + GetTypeBitAlign () const; + + uint32_t + GetNumChildren (bool omit_empty_base_classes) const; + + lldb::BasicType + GetBasicTypeEnumeration () const; + + static lldb::BasicType + GetBasicTypeEnumeration (const ConstString &name); + + uint32_t + GetNumDirectBaseClasses () const; + + uint32_t + GetNumVirtualBaseClasses () const; + + uint32_t + GetNumFields () const; + + ClangASTType + GetDirectBaseClassAtIndex (size_t idx, + uint32_t *bit_offset_ptr) const; + + ClangASTType + GetVirtualBaseClassAtIndex (size_t idx, + uint32_t *bit_offset_ptr) const; + + ClangASTType + GetFieldAtIndex (size_t idx, + std::string& name, + uint64_t *bit_offset_ptr, + uint32_t *bitfield_bit_size_ptr, + bool *is_bitfield_ptr) const; + + uint32_t + GetIndexOfFieldWithName (const char* name, + ClangASTType* field_clang_type = NULL, + uint64_t *bit_offset_ptr = NULL, + uint32_t *bitfield_bit_size_ptr = NULL, + bool *is_bitfield_ptr = NULL) const; + + uint32_t + GetNumPointeeChildren () const; + + ClangASTType + GetChildClangTypeAtIndex (ExecutionContext *exe_ctx, + const char *parent_name, + size_t idx, + bool transparent_pointers, + bool omit_empty_base_classes, + bool ignore_array_bounds, + std::string& child_name, + uint32_t &child_byte_size, + int32_t &child_byte_offset, + uint32_t &child_bitfield_bit_size, + uint32_t &child_bitfield_bit_offset, + bool &child_is_base_class, + bool &child_is_deref_of_parent) const; + + // Lookup a child given a name. This function will match base class names + // and member member names in "clang_type" only, not descendants. + uint32_t + GetIndexOfChildWithName (const char *name, + bool omit_empty_base_classes) const; + + // Lookup a child member given a name. This function will match member names + // only and will descend into "clang_type" children in search for the first + // member in this class, or any base class that matches "name". + // TODO: Return all matches for a given name by returning a vector<vector<uint32_t>> + // so we catch all names that match a given child name, not just the first. + size_t + GetIndexOfChildMemberWithName (const char *name, + bool omit_empty_base_classes, + std::vector<uint32_t>& child_indexes) const; + + size_t + GetNumTemplateArguments () const; + + ClangASTType + GetTemplateArgument (size_t idx, + lldb::TemplateArgumentKind &kind) const; + + + //---------------------------------------------------------------------- + // Modifying RecordType + //---------------------------------------------------------------------- + clang::FieldDecl * + AddFieldToRecordType (const char *name, + const ClangASTType &field_type, + lldb::AccessType access, + uint32_t bitfield_bit_size); + + void + BuildIndirectFields (); + + clang::VarDecl * + AddVariableToRecordType (const char *name, + const ClangASTType &var_type, + lldb::AccessType access); + + clang::CXXMethodDecl * + AddMethodToCXXRecordType (const char *name, + const ClangASTType &method_type, + lldb::AccessType access, + bool is_virtual, + bool is_static, + bool is_inline, + bool is_explicit, + bool is_attr_used, + bool is_artificial); + + // C++ Base Classes + clang::CXXBaseSpecifier * + CreateBaseClassSpecifier (lldb::AccessType access, + bool is_virtual, + bool base_of_class); + + static void + DeleteBaseClassSpecifiers (clang::CXXBaseSpecifier **base_classes, + unsigned num_base_classes); + + bool + SetBaseClassesForClassType (clang::CXXBaseSpecifier const * const *base_classes, + unsigned num_base_classes); + + + bool + SetObjCSuperClass (const ClangASTType &superclass_clang_type); + + bool + AddObjCClassProperty (const char *property_name, + const ClangASTType &property_clang_type, + clang::ObjCIvarDecl *ivar_decl, + const char *property_setter_name, + const char *property_getter_name, + uint32_t property_attributes, + ClangASTMetadata *metadata); + + clang::ObjCMethodDecl * + AddMethodToObjCObjectType (const char *name, // the full symbol name as seen in the symbol table ("-[NString stringWithCString:]") + const ClangASTType &method_clang_type, + lldb::AccessType access, + bool is_artificial); + + clang::DeclContext * + GetDeclContextForType () const; + + + bool + SetDefaultAccessForRecordFields (int default_accessibility, + int *assigned_accessibilities, + size_t num_assigned_accessibilities); + + bool + SetHasExternalStorage (bool has_extern); + + + //------------------------------------------------------------------ + // clang::TagType + //------------------------------------------------------------------ + + bool + SetTagTypeKind (int kind) const; + + //------------------------------------------------------------------ + // Tag Declarations + //------------------------------------------------------------------ + bool + StartTagDeclarationDefinition (); + + bool + CompleteTagDeclarationDefinition (); + + //---------------------------------------------------------------------- + // Modifying Enumeration types + //---------------------------------------------------------------------- + bool + AddEnumerationValueToEnumerationType (const ClangASTType &enumerator_qual_type, + const Declaration &decl, + const char *name, + int64_t enum_value, + uint32_t enum_value_bit_size); + + + + ClangASTType + GetEnumerationIntegerType () const; + + + //------------------------------------------------------------------ + // Pointers & References + //------------------------------------------------------------------ + + // Call this function using the class type when you want to make a + // member pointer type to pointee_type. + ClangASTType + CreateMemberPointerType (const ClangASTType &pointee_type) const; + + + // Converts "s" to a floating point value and place resulting floating + // point bytes in the "dst" buffer. + size_t + ConvertStringToFloatValue (const char *s, + uint8_t *dst, + size_t dst_size) const; + //---------------------------------------------------------------------- + // Dumping types + //---------------------------------------------------------------------- + void + DumpValue (ExecutionContext *exe_ctx, + Stream *s, + lldb::Format format, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + bool show_types, + bool show_summary, + bool verbose, + uint32_t depth); + + bool + DumpTypeValue (Stream *s, + lldb::Format format, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size, + uint32_t bitfield_bit_size, + uint32_t bitfield_bit_offset, + ExecutionContextScope *exe_scope); + + void + DumpSummary (ExecutionContext *exe_ctx, + Stream *s, + const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size); + + void + DumpTypeDescription () const; // Dump to stdout + + void + DumpTypeDescription (Stream *s) const; + + bool + GetValueAsScalar (const DataExtractor &data, + lldb::offset_t data_offset, + size_t data_byte_size, + Scalar &value) const; + + bool + SetValueFromScalar (const Scalar &value, + Stream &strm); + + bool + ReadFromMemory (ExecutionContext *exe_ctx, + lldb::addr_t addr, + AddressType address_type, + DataExtractor &data); + + bool + WriteToMemory (ExecutionContext *exe_ctx, + lldb::addr_t addr, + AddressType address_type, + StreamString &new_value); + + + clang::RecordDecl * + GetAsRecordDecl () const; + + clang::CXXRecordDecl * + GetAsCXXRecordDecl () const; + + clang::ObjCInterfaceDecl * + GetAsObjCInterfaceDecl () const; + + void + Clear() + { + m_type = NULL; + m_ast = NULL; + } + + clang::QualType + GetQualType () const + { + if (m_type) + return clang::QualType::getFromOpaquePtr(m_type); + return clang::QualType(); + } + clang::QualType + GetCanonicalQualType () const + { + if (m_type) + return clang::QualType::getFromOpaquePtr(m_type).getCanonicalType(); + return clang::QualType(); + } + +private: + lldb::clang_type_t m_type; + clang::ASTContext *m_ast; + +}; + +bool operator == (const ClangASTType &lhs, const ClangASTType &rhs); +bool operator != (const ClangASTType &lhs, const ClangASTType &rhs); + + +} // namespace lldb_private + +#endif // #ifndef liblldb_ClangASTType_h_ diff --git a/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h b/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h new file mode 100644 index 000000000000..0c8121135ef0 --- /dev/null +++ b/include/lldb/Symbol/ClangExternalASTSourceCallbacks.h @@ -0,0 +1,171 @@ +//===-- ClangExternalASTSourceCallbacks.h -----------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangExternalASTSourceCallbacks_h_ +#define liblldb_ClangExternalASTSourceCallbacks_h_ + +// C Includes +// C++ Includes +#include <string> +#include <vector> +#include <stdint.h> + +// Other libraries and framework includes +#include "clang/AST/CharUnits.h" + +// Project includes +#include "lldb/lldb-enumerations.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" + +namespace lldb_private { + +class ClangExternalASTSourceCallbacks : public ClangExternalASTSourceCommon +{ +public: + + typedef void (*CompleteTagDeclCallback)(void *baton, clang::TagDecl *); + typedef void (*CompleteObjCInterfaceDeclCallback)(void *baton, clang::ObjCInterfaceDecl *); + typedef void (*FindExternalVisibleDeclsByNameCallback)(void *baton, const clang::DeclContext *DC, clang::DeclarationName Name, llvm::SmallVectorImpl <clang::NamedDecl *> *results); + typedef bool (*LayoutRecordTypeCallback)(void *baton, + const clang::RecordDecl *Record, + uint64_t &Size, + uint64_t &Alignment, + llvm::DenseMap <const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets); + + ClangExternalASTSourceCallbacks (CompleteTagDeclCallback tag_decl_callback, + CompleteObjCInterfaceDeclCallback objc_decl_callback, + FindExternalVisibleDeclsByNameCallback find_by_name_callback, + LayoutRecordTypeCallback layout_record_type_callback, + void *callback_baton) : + m_callback_tag_decl (tag_decl_callback), + m_callback_objc_decl (objc_decl_callback), + m_callback_find_by_name (find_by_name_callback), + m_callback_layout_record_type (layout_record_type_callback), + m_callback_baton (callback_baton) + { + } + + //------------------------------------------------------------------ + // clang::ExternalASTSource + //------------------------------------------------------------------ + + virtual clang::Decl * + GetExternalDecl (uint32_t ID) + { + // This method only needs to be implemented if the AST source ever + // passes back decl sets as VisibleDeclaration objects. + return 0; + } + + virtual clang::Stmt * + GetExternalDeclStmt (uint64_t Offset) + { + // This operation is meant to be used via a LazyOffsetPtr. It only + // needs to be implemented if the AST source uses methods like + // FunctionDecl::setLazyBody when building decls. + return 0; + } + + virtual clang::Selector + GetExternalSelector (uint32_t ID) + { + // This operation only needs to be implemented if the AST source + // returns non-zero for GetNumKnownSelectors(). + return clang::Selector(); + } + + virtual uint32_t + GetNumExternalSelectors() + { + return 0; + } + + virtual clang::CXXBaseSpecifier * + GetExternalCXXBaseSpecifiers(uint64_t Offset) + { + return NULL; + } + + virtual void + MaterializeVisibleDecls (const clang::DeclContext *decl_ctx) + { + return; + } + + virtual clang::ExternalLoadResult + FindExternalLexicalDecls (const clang::DeclContext *decl_ctx, + bool (*isKindWeWant)(clang::Decl::Kind), + llvm::SmallVectorImpl<clang::Decl*> &decls) + { + // This is used to support iterating through an entire lexical context, + // which isn't something the debugger should ever need to do. + return clang::ELR_Failure; + } + + virtual bool + FindExternalVisibleDeclsByName (const clang::DeclContext *decl_ctx, + clang::DeclarationName decl_name); + + virtual void + CompleteType (clang::TagDecl *tag_decl); + + virtual void + CompleteType (clang::ObjCInterfaceDecl *objc_decl); + + bool + layoutRecordType(const clang::RecordDecl *Record, + uint64_t &Size, + uint64_t &Alignment, + llvm::DenseMap <const clang::FieldDecl *, uint64_t> &FieldOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &BaseOffsets, + llvm::DenseMap <const clang::CXXRecordDecl *, clang::CharUnits> &VirtualBaseOffsets); + void + SetExternalSourceCallbacks (CompleteTagDeclCallback tag_decl_callback, + CompleteObjCInterfaceDeclCallback objc_decl_callback, + FindExternalVisibleDeclsByNameCallback find_by_name_callback, + LayoutRecordTypeCallback layout_record_type_callback, + void *callback_baton) + { + m_callback_tag_decl = tag_decl_callback; + m_callback_objc_decl = objc_decl_callback; + m_callback_find_by_name = find_by_name_callback; + m_callback_layout_record_type = layout_record_type_callback; + m_callback_baton = callback_baton; + } + + void + RemoveExternalSourceCallbacks (void *callback_baton) + { + if (callback_baton == m_callback_baton) + { + m_callback_tag_decl = NULL; + m_callback_objc_decl = NULL; + m_callback_find_by_name = NULL; + m_callback_layout_record_type = NULL; + } + } + +protected: + //------------------------------------------------------------------ + // Classes that inherit from ClangExternalASTSourceCallbacks can see and modify these + //------------------------------------------------------------------ + CompleteTagDeclCallback m_callback_tag_decl; + CompleteObjCInterfaceDeclCallback m_callback_objc_decl; + FindExternalVisibleDeclsByNameCallback m_callback_find_by_name; + LayoutRecordTypeCallback m_callback_layout_record_type; + void * m_callback_baton; +}; + +} // namespace lldb_private + +#endif // liblldb_ClangExternalASTSourceCallbacks_h_ diff --git a/include/lldb/Symbol/ClangExternalASTSourceCommon.h b/include/lldb/Symbol/ClangExternalASTSourceCommon.h new file mode 100644 index 000000000000..72d77e74ca90 --- /dev/null +++ b/include/lldb/Symbol/ClangExternalASTSourceCommon.h @@ -0,0 +1,188 @@ +//===-- ClangExternalASTSourceCommon.h --------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangExternalASTSourceCommon_h +#define liblldb_ClangExternalASTSourceCommon_h + +// Clang headers like to use NDEBUG inside of them to enable/disable debug +// releated features using "#ifndef NDEBUG" preprocessor blocks to do one thing +// or another. This is bad because it means that if clang was built in release +// mode, it assumes that you are building in release mode which is not always +// the case. You can end up with functions that are defined as empty in header +// files when NDEBUG is not defined, and this can cause link errors with the +// clang .a files that you have since you might be missing functions in the .a +// file. So we have to define NDEBUG when including clang headers to avoid any +// mismatches. This is covered by rdar://problem/8691220 + +#if !defined(NDEBUG) && !defined(LLVM_NDEBUG_OFF) +#define LLDB_DEFINED_NDEBUG_FOR_CLANG +#define NDEBUG +// Need to include assert.h so it is as clang would expect it to be (disabled) +#include <assert.h> +#endif + +#include "clang/AST/ExternalASTSource.h" + +#ifdef LLDB_DEFINED_NDEBUG_FOR_CLANG +#undef NDEBUG +#undef LLDB_DEFINED_NDEBUG_FOR_CLANG +// Need to re-include assert.h so it is as _we_ would expect it to be (enabled) +#include <assert.h> +#endif + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/Core/dwarf.h" + +namespace lldb_private { + +class ClangASTMetadata +{ +public: + ClangASTMetadata () : + m_user_id(0), + m_union_is_user_id(false), + m_union_is_isa_ptr(false), + m_has_object_ptr(false), + m_is_self (false), + m_is_dynamic_cxx (true) + { + } + + bool + GetIsDynamicCXXType () const + { + return m_is_dynamic_cxx; + } + + void + SetIsDynamicCXXType (bool b) + { + m_is_dynamic_cxx = b; + } + + void + SetUserID (lldb::user_id_t user_id) + { + m_user_id = user_id; + m_union_is_user_id = true; + m_union_is_isa_ptr = false; + } + + lldb::user_id_t + GetUserID () const + { + if (m_union_is_user_id) + return m_user_id; + else + return LLDB_INVALID_UID; + } + + void + SetISAPtr (uint64_t isa_ptr) + { + m_isa_ptr = isa_ptr; + m_union_is_user_id = false; + m_union_is_isa_ptr = true; + } + + uint64_t + GetISAPtr () const + { + if (m_union_is_isa_ptr) + return m_isa_ptr; + else + return 0; + } + + void + SetObjectPtrName(const char *name) + { + m_has_object_ptr = true; + if (strcmp (name, "self") == 0) + m_is_self = true; + else if (strcmp (name, "this") == 0) + m_is_self = false; + else + m_has_object_ptr = false; + } + + lldb::LanguageType + GetObjectPtrLanguage () const + { + if (m_has_object_ptr) + { + if (m_is_self) + return lldb::eLanguageTypeObjC; + else + return lldb::eLanguageTypeC_plus_plus; + } + return lldb::eLanguageTypeUnknown; + + } + const char * + GetObjectPtrName() const + { + if (m_has_object_ptr) + { + if (m_is_self) + return "self"; + else + return "this"; + } + else + return NULL; + } + + bool + HasObjectPtr() const + { + return m_has_object_ptr; + } + + void + Dump (Stream *s); + +private: + union + { + lldb::user_id_t m_user_id; + uint64_t m_isa_ptr; + }; + bool m_union_is_user_id : 1, + m_union_is_isa_ptr : 1, + m_has_object_ptr : 1, + m_is_self : 1, + m_is_dynamic_cxx : 1; + +}; + +class ClangExternalASTSourceCommon : public clang::ExternalASTSource +{ +public: + ClangExternalASTSourceCommon(); + ~ClangExternalASTSourceCommon(); + + virtual ClangASTMetadata *GetMetadata(const void *object); + virtual void SetMetadata(const void *object, ClangASTMetadata &metadata); + virtual bool HasMetadata(const void *object); +private: + typedef llvm::DenseMap<const void *, ClangASTMetadata> MetadataMap; + + MetadataMap m_metadata; + uint64_t m_magic; ///< Because we don't have RTTI, we must take it + ///< on faith that any valid ExternalASTSource that + ///< we try to use the *Metadata APIs on inherits + ///< from ClangExternalASTSourceCommon. This magic + ///< number exists to enforce that. +}; + +} + +#endif diff --git a/include/lldb/Symbol/ClangNamespaceDecl.h b/include/lldb/Symbol/ClangNamespaceDecl.h new file mode 100644 index 000000000000..d10ab2a29665 --- /dev/null +++ b/include/lldb/Symbol/ClangNamespaceDecl.h @@ -0,0 +1,103 @@ +//===-- ClangNamespaceDecl.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ClangNamespaceDecl_h_ +#define liblldb_ClangNamespaceDecl_h_ + +#include "lldb/lldb-public.h" +#include "lldb/Core/ClangForward.h" + +namespace lldb_private { + +class ClangNamespaceDecl +{ +public: + ClangNamespaceDecl () : + m_ast (NULL), + m_namespace_decl (NULL) + { + } + + ClangNamespaceDecl (clang::ASTContext *ast, clang::NamespaceDecl *namespace_decl) : + m_ast (ast), + m_namespace_decl (namespace_decl) + { + } + + ClangNamespaceDecl (const ClangNamespaceDecl &rhs) : + m_ast (rhs.m_ast), + m_namespace_decl (rhs.m_namespace_decl) + { + } + + const ClangNamespaceDecl & + operator = (const ClangNamespaceDecl &rhs) + { + m_ast = rhs.m_ast; + m_namespace_decl = rhs.m_namespace_decl; + return *this; + } + + //------------------------------------------------------------------ + /// Convert to bool operator. + /// + /// This allows code to check a ClangNamespaceDecl object to see if + /// it contains a valid namespace decl using code such as: + /// + /// @code + /// ClangNamespaceDecl ns_decl(...); + /// if (ns_decl) + /// { ... + /// @endcode + /// + /// @return + /// /b True this object contains a valid namespace decl, \b + /// false otherwise. + //------------------------------------------------------------------ + operator bool() const + { + return m_ast != NULL && m_namespace_decl != NULL; + } + + clang::ASTContext * + GetASTContext() const + { + return m_ast; + } + + void + SetASTContext (clang::ASTContext *ast) + { + m_ast = ast; + } + + clang::NamespaceDecl * + GetNamespaceDecl () const + { + return m_namespace_decl; + } + + void + SetNamespaceDecl (clang::NamespaceDecl *namespace_decl) + { + m_namespace_decl = namespace_decl; + } + + std::string + GetQualifiedName () const; + +protected: + clang::ASTContext *m_ast; + clang::NamespaceDecl *m_namespace_decl; +}; + + +} // namespace lldb_private + +#endif // #ifndef liblldb_ClangNamespaceDecl_h_ diff --git a/include/lldb/Symbol/CompileUnit.h b/include/lldb/Symbol/CompileUnit.h new file mode 100644 index 000000000000..5de93670c5a7 --- /dev/null +++ b/include/lldb/Symbol/CompileUnit.h @@ -0,0 +1,422 @@ +//===-- CompileUnit.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_CompUnit_h_ +#define liblldb_CompUnit_h_ + +#include "lldb/lldb-enumerations.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Core/FileSpecList.h" +#include "lldb/Core/ModuleChild.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/UserID.h" + +namespace lldb_private { +//---------------------------------------------------------------------- +/// @class CompileUnit CompileUnit.h "lldb/Symbol/CompileUnit.h" +/// @brief A class that describes a compilation unit. +/// +/// A representation of a compilation unit, or compiled source file. +/// The UserID of the compile unit is specified by the SymbolFile +/// plug-in and can have any value as long as the value is unique +/// within the Module that owns this compile units. +/// +/// Each compile unit has a list of functions, global and static +/// variables, support file list (include files and inlined source +/// files), and a line table. +//---------------------------------------------------------------------- +class CompileUnit : + public std::enable_shared_from_this<CompileUnit>, + public ModuleChild, + public FileSpec, + public UserID, + public SymbolContextScope +{ +public: + //------------------------------------------------------------------ + /// Construct with a module, path, UID and language. + /// + /// Initialize the compile unit given the owning \a module, a path + /// to convert into a FileSpec, the SymbolFile plug-in supplied + /// \a uid, and the source language type. + /// + /// @param[in] module + /// The parent module that owns this compile unit. This value + /// must be a valid pointer value. + /// + /// @param[in] user_data + /// User data where the SymbolFile parser can store data. + /// + /// @param[in] pathname + /// The path to the source file for this compile unit. + /// + /// @param[in] uid + /// The user ID of the compile unit. This value is supplied by + /// the SymbolFile plug-in and should be a value that allows + /// the SymbolFile plug-in to easily locate and parse additional + /// information for the compile unit. + /// + /// @param[in] language + /// A language enumeration type that describes the main language + /// of this compile unit. + /// + /// @see lldb::LanguageType + //------------------------------------------------------------------ + CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const char *pathname, lldb::user_id_t uid, lldb::LanguageType language); + + //------------------------------------------------------------------ + /// Construct with a module, file spec, UID and language. + /// + /// Initialize the compile unit given the owning \a module, a path + /// to convert into a FileSpec, the SymbolFile plug-in supplied + /// \a uid, and the source language type. + /// + /// @param[in] module + /// The parent module that owns this compile unit. This value + /// must be a valid pointer value. + /// + /// @param[in] user_data + /// User data where the SymbolFile parser can store data. + /// + /// @param[in] file_spec + /// The file specification for the source file of this compile + /// unit. + /// + /// @param[in] uid + /// The user ID of the compile unit. This value is supplied by + /// the SymbolFile plug-in and should be a value that allows + /// the plug-in to easily locate and parse + /// additional information for the compile unit. + /// + /// @param[in] language + /// A language enumeration type that describes the main language + /// of this compile unit. + /// + /// @see lldb::LanguageType + //------------------------------------------------------------------ + CompileUnit(const lldb::ModuleSP &module_sp, void *user_data, const FileSpec &file_spec, lldb::user_id_t uid, lldb::LanguageType language); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + virtual + ~CompileUnit(); + + //------------------------------------------------------------------ + /// Add a function to this compile unit. + /// + /// Typically called by the SymbolFile plug-ins as they partially + /// parse the debug information. + /// + /// @param[in] function_sp + /// A shared pointer to the a Function object. + //------------------------------------------------------------------ + void + AddFunction(lldb::FunctionSP& function_sp); + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + CalculateSymbolContext(SymbolContext* sc); + + virtual lldb::ModuleSP + CalculateSymbolContextModule (); + + virtual CompileUnit * + CalculateSymbolContextCompileUnit (); + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::DumpSymbolContext(Stream*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + DumpSymbolContext(Stream *s); + + lldb::LanguageType + GetLanguage(); + + void + SetLanguage(lldb::LanguageType language) + { + m_flags.Set(flagsParsedLanguage); + m_language = language; + } + + void + GetDescription(Stream *s, lldb::DescriptionLevel level) const; + + //------------------------------------------------------------------ + /// Get a shared pointer to a function in this compile unit by + /// index. + /// + /// Typically called when iterating though all functions in a + /// compile unit after all functions have been parsed. This provides + /// raw access to the function shared pointer list and will not + /// cause the SymbolFile plug-in to parse any unparsed functions. + /// + /// @param[in] idx + /// An index into the function list. + /// + /// @return + /// A shared pointer to a function that might contain a NULL + /// Function class pointer. + //------------------------------------------------------------------ + lldb::FunctionSP + GetFunctionAtIndex (size_t idx); + + //------------------------------------------------------------------ + /// Dump the compile unit contents to the stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] show_context + /// If \b true, variables will dump their symbol context + /// information. + //------------------------------------------------------------------ + void + Dump (Stream *s, bool show_context) const; + + //------------------------------------------------------------------ + /// Find the line entry by line and optional inlined file spec. + /// + /// Finds the first line entry that has an index greater than + /// \a start_idx that matches \a line. If \a file_spec_ptr + /// is NULL, then the search matches line entries whose file matches + /// the file for the compile unit. If \a file_spec_ptr is + /// not NULL, line entries must match the specified file spec (for + /// inlined line table entries). + /// + /// Multiple calls to this function can find all entries that match + /// a given file and line by starting with \a start_idx equal to zero, + /// and calling this function back with the return valeu + 1. + /// + /// @param[in] start_idx + /// The zero based index at which to start looking for matches. + /// + /// @param[in] line + /// The line number to search for. + /// + /// @param[in] file_spec_ptr + /// If non-NULL search for entries that match this file spec, + /// else if NULL, search for line entries that match the compile + /// unit file. + /// + /// @param[in] exact + /// If \btrue match only if there is a line table entry for this line number. + /// If \bfalse, find the line table entry equal to or after this line number. + /// + /// @param[out] line_entry + /// If non-NULL, a copy of the line entry that was found. + /// + /// @return + /// The zero based index of a matching line entry, or UINT32_MAX + /// if no matching line entry is found. + //------------------------------------------------------------------ + uint32_t + FindLineEntry (uint32_t start_idx, + uint32_t line, + const FileSpec* file_spec_ptr, + bool exact, + LineEntry *line_entry); + + //------------------------------------------------------------------ + /// Get the line table for the compile unit. + /// + /// Called by clients and the SymbolFile plug-in. The SymbolFile + /// plug-ins use this function to determine if the line table has + /// be parsed yet. Clients use this function to get the line table + /// from a compile unit. + /// + /// @return + /// The line table object pointer, or NULL if this line table + /// hasn't been parsed yet. + //------------------------------------------------------------------ + LineTable* + GetLineTable (); + + //------------------------------------------------------------------ + /// Get the compile unit's support file list. + /// + /// The support file list is used by the line table, and any objects + /// that have valid Declaration objects. + /// + /// @return + /// A support file list object. + //------------------------------------------------------------------ + FileSpecList& + GetSupportFiles (); + + //------------------------------------------------------------------ + /// Get the SymbolFile plug-in user data. + /// + /// SymbolFile plug-ins can store user data to internal state or + /// objects to quickly allow them to parse more information for a + /// given object. + /// + /// @return + /// The user data stored with the CompileUnit when it was + /// constructed. + //------------------------------------------------------------------ + void * + GetUserData () const; + + //------------------------------------------------------------------ + /// Get the variable list for a compile unit. + /// + /// Called by clients to get the variable list for a compile unit. + /// The variable list will contain all global and static variables + /// that were defined at the compile unit level. + /// + /// @param[in] can_create + /// If \b true, the variable list will be parsed on demand. If + /// \b false, the current variable list will be returned even + /// if it contains a NULL VariableList object (typically + /// called by dumping routines that want to display only what + /// has currently been parsed). + /// + /// @return + /// A shared pointer to a variable list, that can contain NULL + /// VariableList pointer if there are no global or static + /// variables. + //------------------------------------------------------------------ + lldb::VariableListSP + GetVariableList (bool can_create); + + //------------------------------------------------------------------ + /// Finds a function by user ID. + /// + /// Typically used by SymbolFile plug-ins when partially parsing + /// the debug information to see if the function has been parsed + /// yet. + /// + /// @param[in] uid + /// The user ID of the function to find. This value is supplied + /// by the SymbolFile plug-in and should be a value that + /// allows the plug-in to easily locate and parse additional + /// information in the function. + /// + /// @return + /// A shared pointer to the function object that might contain + /// a NULL Function pointer. + //------------------------------------------------------------------ + lldb::FunctionSP + FindFunctionByUID (lldb::user_id_t uid); + + //------------------------------------------------------------------ + /// Set the line table for the compile unit. + /// + /// Called by the SymbolFile plug-in when if first parses the line + /// table and hands ownership of the line table to this object. The + /// compile unit owns the line table object and will delete the + /// object when it is deleted. + /// + /// @param[in] line_table + /// A line table object pointer that this object now owns. + //------------------------------------------------------------------ + void + SetLineTable(LineTable* line_table); + + //------------------------------------------------------------------ + /// Set accessor for the variable list. + /// + /// Called by the SymbolFile plug-ins after they have parsed the + /// variable lists and are ready to hand ownership of the list over + /// to this object. + /// + /// @param[in] variable_list_sp + /// A shared pointer to a VariableList. + //------------------------------------------------------------------ + void + SetVariableList (lldb::VariableListSP& variable_list_sp); + + //------------------------------------------------------------------ + /// Resolve symbol contexts by file and line. + /// + /// Given a file in \a file_spec, and a line number, find all + /// instances and append them to the supplied symbol context list + /// \a sc_list. + /// + /// @param[in] file_spec + /// A file specification. If \a file_spec contains no directory + /// information, only the basename will be used when matching + /// contexts. If the directory in \a file_spec is valid, a + /// complete file specification match will be performed. + /// + /// @param[in] line + /// The line number to match against the compile unit's line + /// tables. + /// + /// @param[in] check_inlines + /// If \b true this function will also match any inline + /// file and line matches. If \b false, the compile unit's + /// file specification must match \a file_spec for any matches + /// to be returned. + /// + /// @param[in] exact + /// If true, only resolve the context if \a line exists in the line table. + /// If false, resolve the context to the closest line greater than \a line + /// in the line table. + /// + /// @param[in] resolve_scope + /// For each matching line entry, this bitfield indicates what + /// values within each SymbolContext that gets added to \a + /// sc_list will be resolved. See the SymbolContext::Scope + /// enumeration for a list of all available bits that can be + /// resolved. Only SymbolContext entries that can be resolved + /// using a LineEntry base address will be able to be resolved. + /// + /// @param[out] sc_list + /// A SymbolContext list class that willl get any matching + /// entries appended to. + /// + /// @return + /// The number of new matches that were added to \a sc_list. + /// + /// @see enum SymbolContext::Scope + //------------------------------------------------------------------ + uint32_t + ResolveSymbolContext (const FileSpec& file_spec, + uint32_t line, + bool check_inlines, + bool exact, + uint32_t resolve_scope, + SymbolContextList &sc_list); + + +protected: + void *m_user_data; ///< User data for the SymbolFile parser to store information into. + lldb::LanguageType m_language; ///< The programming language enumeration value. + Flags m_flags; ///< Compile unit flags that help with partial parsing. + std::vector<lldb::FunctionSP> m_functions; ///< The sparsely populated list of shared pointers to functions + ///< that gets populated as functions get partially parsed. + FileSpecList m_support_files; ///< Files associated with this compile unit's line table and declarations. + std::unique_ptr<LineTable> m_line_table_ap; ///< Line table that will get parsed on demand. + lldb::VariableListSP m_variables; ///< Global and static variable list that will get parsed on demand. + +private: + enum + { + flagsParsedAllFunctions = (1u << 0), ///< Have we already parsed all our functions + flagsParsedVariables = (1u << 1), ///< Have we already parsed globals and statics? + flagsParsedSupportFiles = (1u << 2), ///< Have we already parsed the support files for this compile unit? + flagsParsedLineTable = (1u << 3), ///< Have we parsed the line table already? + flagsParsedLanguage = (1u << 4) ///< Have we parsed the line table already? + }; + + DISALLOW_COPY_AND_ASSIGN (CompileUnit); +}; + +} // namespace lldb_private + +#endif // liblldb_CompUnit_h_ diff --git a/include/lldb/Symbol/DWARFCallFrameInfo.h b/include/lldb/Symbol/DWARFCallFrameInfo.h new file mode 100644 index 000000000000..13a14f8c4041 --- /dev/null +++ b/include/lldb/Symbol/DWARFCallFrameInfo.h @@ -0,0 +1,150 @@ +//===-- DWARFCallFrameInfo.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_DWARFCallFrameInfo_h_ +#define liblldb_DWARFCallFrameInfo_h_ + +#include <map> + +#include "lldb/Core/AddressRange.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Core/Flags.h" +#include "lldb/Core/RangeMap.h" +#include "lldb/Core/VMRange.h" +#include "lldb/Core/dwarf.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/UnwindPlan.h" +#include "lldb/lldb-private.h" + +namespace lldb_private { + +// DWARFCallFrameInfo is a class which can read eh_frame and DWARF +// Call Frame Information FDEs. It stores little information internally. +// Only two APIs are exported - one to find the high/low pc values +// of a function given a text address via the information in the +// eh_frame / debug_frame, and one to generate an UnwindPlan based +// on the FDE in the eh_frame / debug_frame section. + +class DWARFCallFrameInfo +{ +public: + + DWARFCallFrameInfo (ObjectFile& objfile, + lldb::SectionSP& section, + lldb::RegisterKind reg_kind, + bool is_eh_frame); + + ~DWARFCallFrameInfo(); + + // Locate an AddressRange that includes the provided Address in this + // object's eh_frame/debug_info + // Returns true if a range is found to cover that address. + bool + GetAddressRange (Address addr, AddressRange &range); + + // Return an UnwindPlan based on the call frame information encoded + // in the FDE of this DWARFCallFrameInfo section. + bool + GetUnwindPlan (Address addr, UnwindPlan& unwind_plan); + + typedef RangeVector<lldb::addr_t, uint32_t> FunctionAddressAndSizeVector; + + //------------------------------------------------------------------ + // Build a vector of file address and size for all functions in this Module + // based on the eh_frame FDE entries. + // + // The eh_frame information can be a useful source of file address and size of + // the functions in a Module. Often a binary's non-exported symbols are stripped + // before shipping so lldb won't know the start addr / size of many functions + // in the Module. But the eh_frame can help to give the addresses of these + // stripped symbols, at least. + // + // @param[out] function_info + // A vector provided by the caller is filled out. May be empty if no FDEs/no eh_frame + // is present in this Module. + + void + GetFunctionAddressAndSizeVector (FunctionAddressAndSizeVector &function_info); + +private: + enum + { + CFI_AUG_MAX_SIZE = 8, + CFI_HEADER_SIZE = 8 + }; + + struct CIE + { + dw_offset_t cie_offset; + uint8_t version; + char augmentation[CFI_AUG_MAX_SIZE]; // This is typically empty or very short. + uint32_t code_align; + int32_t data_align; + uint32_t return_addr_reg_num; + dw_offset_t inst_offset; // offset of CIE instructions in mCFIData + uint32_t inst_length; // length of CIE instructions in mCFIData + uint8_t ptr_encoding; + lldb_private::UnwindPlan::Row initial_row; + + CIE(dw_offset_t offset) : cie_offset(offset), version (-1), code_align (0), + data_align (0), return_addr_reg_num (LLDB_INVALID_REGNUM), inst_offset (0), + inst_length (0), ptr_encoding (0), initial_row() {} + }; + + typedef std::shared_ptr<CIE> CIESP; + + typedef std::map<off_t, CIESP> cie_map_t; + + // Start address (file address), size, offset of FDE location + // used for finding an FDE for a given File address; the start address field is + // an offset into an individual Module. + typedef RangeDataVector<lldb::addr_t, uint32_t, dw_offset_t> FDEEntryMap; + + bool + IsEHFrame() const; + + bool + GetFDEEntryByFileAddress (lldb::addr_t file_offset, FDEEntryMap::Entry& fde_entry); + + void + GetFDEIndex (); + + bool + FDEToUnwindPlan (uint32_t offset, Address startaddr, UnwindPlan& unwind_plan); + + const CIE* + GetCIE(dw_offset_t cie_offset); + + void + GetCFIData(); + + ObjectFile& m_objfile; + lldb::SectionSP m_section_sp; + lldb::RegisterKind m_reg_kind; + Flags m_flags; + cie_map_t m_cie_map; + + DataExtractor m_cfi_data; + bool m_cfi_data_initialized; // only copy the section into the DE once + + FDEEntryMap m_fde_index; + bool m_fde_index_initialized; // only scan the section for FDEs once + Mutex m_fde_index_mutex; // and isolate the thread that does it + + bool m_is_eh_frame; + + CIESP + ParseCIE (const uint32_t cie_offset); + +}; + +} // namespace lldb_private + +#endif // liblldb_DWARFCallFrameInfo_h_ diff --git a/include/lldb/Symbol/Declaration.h b/include/lldb/Symbol/Declaration.h new file mode 100644 index 000000000000..f014571595f0 --- /dev/null +++ b/include/lldb/Symbol/Declaration.h @@ -0,0 +1,278 @@ +//===-- Declaration.h -------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Declaration_h_ +#define liblldb_Declaration_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Host/FileSpec.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class Declaration Declaration.h "lldb/Symbol/Declaration.h" +/// @brief A class that describes the declaration location of a +/// lldb object. +/// +/// The declarations include the file specification, line number, and +/// the column info and can help track where functions, blocks, inlined +/// functions, types, variables, any many other debug core objects were +/// declared. +//---------------------------------------------------------------------- +class Declaration +{ +public: + //------------------------------------------------------------------ + /// Default constructor. + //------------------------------------------------------------------ + Declaration () : + m_file (), + m_line (0) +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + ,m_column (0) +#endif + { + } + + + //------------------------------------------------------------------ + /// Construct with file specification, and optional line and column. + /// + /// @param[in] file_spec + /// The file specification that describes where this was + /// declared. + /// + /// @param[in] line + /// The line number that describes where this was declared. Set + /// to zero if there is no line number information. + /// + /// @param[in] column + /// The column number that describes where this was declared. + /// Set to zero if there is no column number information. + //------------------------------------------------------------------ + Declaration (const FileSpec& file_spec, uint32_t line = 0, uint32_t column = 0) : + m_file (file_spec), + m_line (line) +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + ,m_column (column) +#endif + { + } + + //------------------------------------------------------------------ + /// Construct with a reference to another Declaration object. + //------------------------------------------------------------------ + Declaration (const Declaration& rhs) : + m_file (rhs.m_file), + m_line (rhs.m_line) +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + ,m_column (rhs.m_column) +#endif + { + + } + + //------------------------------------------------------------------ + /// Construct with a pointer to another Declaration object. + //------------------------------------------------------------------ + Declaration(const Declaration* decl_ptr) : + m_file(), + m_line(0) +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + ,m_column(0) +#endif + { + if (decl_ptr) + *this = *decl_ptr; + } + + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Sets the file specification to be empty, and the line and column + /// to zero. + //------------------------------------------------------------------ + void + Clear () + { + m_file.Clear(); + m_line= 0; +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + m_column = 0; +#endif + } + + //------------------------------------------------------------------ + /// Compare two declaration objects. + /// + /// Compares the two file specifications from \a lhs and \a rhs. If + /// the file specifications are equal, then continue to compare the + /// line number and column numbers respectively. + /// + /// @param[in] lhs + /// The Left Hand Side const Declaration object reference. + /// + /// @param[in] rhs + /// The Right Hand Side const Declaration object reference. + /// + /// @return + /// @li -1 if lhs < rhs + /// @li 0 if lhs == rhs + /// @li 1 if lhs > rhs + //------------------------------------------------------------------ + static int + Compare (const Declaration& lhs, const Declaration& rhs); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + void + Dump (Stream *s, bool show_fullpaths) const; + + bool + DumpStopContext (Stream *s, bool show_fullpaths) const; + //------------------------------------------------------------------ + /// Get accessor for the declaration column number. + /// + /// @return + /// Non-zero indicates a valid column number, zero indicates no + /// column information is available. + //------------------------------------------------------------------ + uint32_t + GetColumn () const + { +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + return m_column; +#else + return 0; +#endif + } + + //------------------------------------------------------------------ + /// Get accessor for file specification. + /// + /// @return + /// A reference to the file specification object. + //------------------------------------------------------------------ + FileSpec& + GetFile () + { + return m_file; + } + + //------------------------------------------------------------------ + /// Get const accessor for file specification. + /// + /// @return + /// A const reference to the file specification object. + //------------------------------------------------------------------ + const FileSpec& + GetFile () const + { + return m_file; + } + + //------------------------------------------------------------------ + /// Get accessor for the declaration line number. + /// + /// @return + /// Non-zero indicates a valid line number, zero indicates no + /// line information is available. + //------------------------------------------------------------------ + uint32_t + GetLine () const + { + return m_line; + } + + + bool + IsValid() const + { + return m_file && m_line != 0; + } + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// @return + /// The number of bytes that this object occupies in memory. + /// The returned value does not include the bytes for any + /// shared string values. + /// + /// @see ConstString::StaticMemorySize () + //------------------------------------------------------------------ + size_t + MemorySize () const; + + //------------------------------------------------------------------ + /// Set accessor for the declaration column number. + /// + /// @param[in] column + /// Non-zero indicates a valid column number, zero indicates no + /// column information is available. + //------------------------------------------------------------------ + void + SetColumn (uint32_t column) + { +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + m_column = col; +#endif + } + + //------------------------------------------------------------------ + /// Set accessor for the declaration file specification. + /// + /// @param[in] file_spec + /// The new declaration file specifciation. + //------------------------------------------------------------------ + void + SetFile (const FileSpec& file_spec) + { + m_file = file_spec; + } + + //------------------------------------------------------------------ + /// Set accessor for the declaration line number. + /// + /// @param[in] line + /// Non-zero indicates a valid line number, zero indicates no + /// line information is available. + //------------------------------------------------------------------ + void + SetLine (uint32_t line) + { + m_line = line; + } +protected: + //------------------------------------------------------------------ + /// Member variables. + //------------------------------------------------------------------ + FileSpec m_file; ///< The file specification that points to the + ///< source file where the declaration occurred. + uint32_t m_line; ///< Non-zero values indicates a valid line number, + ///< zero indicates no line number information is available. +#ifdef LLDB_ENABLE_DECLARATION_COLUMNS + uint32_t m_column; ///< Non-zero values indicates a valid column number, + ///< zero indicates no column information is available. +#endif +}; + +bool +operator == (const Declaration &lhs, const Declaration &rhs); + +} // namespace lldb_private + +#endif // liblldb_Declaration_h_ diff --git a/include/lldb/Symbol/FuncUnwinders.h b/include/lldb/Symbol/FuncUnwinders.h new file mode 100644 index 000000000000..fa48dc27e123 --- /dev/null +++ b/include/lldb/Symbol/FuncUnwinders.h @@ -0,0 +1,106 @@ +#ifndef liblldb_FuncUnwinders_h +#define liblldb_FuncUnwinders_h + +#include "lldb/Core/AddressRange.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Host/Mutex.h" + +namespace lldb_private { + +class UnwindTable; + +class FuncUnwinders +{ +public: + // FuncUnwinders objects are used to track UnwindPlans for a function + // (named or not - really just an address range) + + // We'll record three different UnwindPlans for each address range: + // 1. Unwinding from a call site (a valid exception throw location) + // This is often sourced from the eh_frame exception handling info + // 2. Unwinding from a non-call site (any location in the function) + // This is often done by analyzing the function prologue assembly + // langauge instructions + // 3. A fast unwind method for this function which only retrieves a + // limited set of registers necessary to walk the stack + // 4. An architectural default unwind plan when none of the above are + // available for some reason. + + // Additionally, FuncUnwinds object can be asked where the prologue + // instructions are finished for migrating breakpoints past the + // stack frame setup instructions when we don't have line table information. + + FuncUnwinders (lldb_private::UnwindTable& unwind_table, lldb_private::UnwindAssembly *assembly_profiler, AddressRange range); + + ~FuncUnwinders (); + + // current_offset is the byte offset into the function. + // 0 means no instructions have executed yet. -1 means the offset is unknown. + // On architectures where the pc points to the next instruction that will execute, this + // offset value will have already been decremented by 1 to stay within the bounds of the + // correct function body. + lldb::UnwindPlanSP + GetUnwindPlanAtCallSite (int current_offset); + + lldb::UnwindPlanSP + GetUnwindPlanAtNonCallSite (lldb_private::Thread& thread); + + lldb::UnwindPlanSP + GetUnwindPlanFastUnwind (lldb_private::Thread& Thread); + + lldb::UnwindPlanSP + GetUnwindPlanArchitectureDefault (lldb_private::Thread& thread); + + lldb::UnwindPlanSP + GetUnwindPlanArchitectureDefaultAtFunctionEntry (lldb_private::Thread& thread); + + Address& + GetFirstNonPrologueInsn (Target& target); + + const Address& + GetFunctionStartAddress () const; + + bool + ContainsAddress (const Address& addr) const + { + return m_range.ContainsFileAddress (addr); + } + + // When we're doing an unwind using the UnwindPlanAtNonCallSite and we find an + // impossible unwind condition, we know that the UnwindPlan is invalid. Calling + // this method on the FuncUnwinder will tell it to replace that UnwindPlan with + // the architectural default UnwindPlan so hopefully our stack walk will get past + // this frame. + void + InvalidateNonCallSiteUnwindPlan (lldb_private::Thread& Thread); + +private: + UnwindTable& m_unwind_table; + UnwindAssembly *m_assembly_profiler; + AddressRange m_range; + + Mutex m_mutex; + lldb::UnwindPlanSP m_unwind_plan_call_site_sp; + lldb::UnwindPlanSP m_unwind_plan_non_call_site_sp; + lldb::UnwindPlanSP m_unwind_plan_fast_sp; + lldb::UnwindPlanSP m_unwind_plan_arch_default_sp; + lldb::UnwindPlanSP m_unwind_plan_arch_default_at_func_entry_sp; + + bool m_tried_unwind_at_call_site:1, + m_tried_unwind_at_non_call_site:1, + m_tried_unwind_fast:1, + m_tried_unwind_arch_default:1, + m_tried_unwind_arch_default_at_func_entry:1; + + + Address m_first_non_prologue_insn; + + DISALLOW_COPY_AND_ASSIGN (FuncUnwinders); + +}; // class FuncUnwinders + +} // namespace lldb_private + + +#endif //liblldb_FuncUnwinders_h diff --git a/include/lldb/Symbol/Function.h b/include/lldb/Symbol/Function.h new file mode 100644 index 000000000000..787f81c5ad27 --- /dev/null +++ b/include/lldb/Symbol/Function.h @@ -0,0 +1,638 @@ +//===-- Function.h ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Function_h_ +#define liblldb_Function_h_ + +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Symbol/Block.h" +#include "lldb/Symbol/Declaration.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Core/Mangled.h" +#include "lldb/Core/UserID.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class FunctionInfo Function.h "lldb/Symbol/Function.h" +/// @brief A class that contains generic function information. +/// +/// This provides generic function information that gets resused between +/// inline functions and function types. +//---------------------------------------------------------------------- +class FunctionInfo +{ +public: + //------------------------------------------------------------------ + /// Construct with the function method name and optional declaration + /// information. + /// + /// @param[in] name + /// A C string name for the method name for this function. This + /// value should not be the mangled named, but the simple method + /// name. + /// + /// @param[in] decl_ptr + /// Optional declaration information that describes where the + /// function was declared. This can be NULL. + //------------------------------------------------------------------ + FunctionInfo (const char *name, const Declaration *decl_ptr); + + //------------------------------------------------------------------ + /// Construct with the function method name and optional declaration + /// information. + /// + /// @param[in] name + /// A name for the method name for this function. This value + /// should not be the mangled named, but the simple method name. + /// + /// @param[in] decl_ptr + /// Optional declaration information that describes where the + /// function was declared. This can be NULL. + //------------------------------------------------------------------ + FunctionInfo (const ConstString& name, const Declaration *decl_ptr); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual since classes inherit from this class. + //------------------------------------------------------------------ + virtual + ~FunctionInfo (); + + //------------------------------------------------------------------ + /// Compare two function information objects. + /// + /// First compares the method names, and if equal, then compares + /// the declaration information. + /// + /// @param[in] lhs + /// The Left Hand Side const FunctionInfo object reference. + /// + /// @param[in] rhs + /// The Right Hand Side const FunctionInfo object reference. + /// + /// @return + /// @li -1 if lhs < rhs + /// @li 0 if lhs == rhs + /// @li 1 if lhs > rhs + //------------------------------------------------------------------ + static int + Compare (const FunctionInfo& lhs, const FunctionInfo& rhs); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + void + Dump (Stream *s, bool show_fullpaths) const; + + //------------------------------------------------------------------ + /// Get accessor for the declaration information. + /// + /// @return + /// A reference to the declaration object. + //------------------------------------------------------------------ + Declaration& + GetDeclaration (); + + //------------------------------------------------------------------ + /// Get const accessor for the declaration information. + /// + /// @return + /// A const reference to the declaration object. + //------------------------------------------------------------------ + const Declaration& + GetDeclaration () const; + + //------------------------------------------------------------------ + /// Get accessor for the method name. + /// + /// @return + /// A const reference to the method name object. + //------------------------------------------------------------------ + const ConstString& + GetName () const; + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// @return + /// The number of bytes that this object occupies in memory. + /// The returned value does not include the bytes for any + /// shared string values. + /// + /// @see ConstString::StaticMemorySize () + //------------------------------------------------------------------ + virtual size_t + MemorySize () const; + +protected: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + ConstString m_name; ///< Function method name (not a mangled name). + Declaration m_declaration; ///< Information describing where this function information was defined. +}; + + +//---------------------------------------------------------------------- +/// @class InlineFunctionInfo Function.h "lldb/Symbol/Function.h" +/// @brief A class that describes information for an inlined function. +//---------------------------------------------------------------------- +class InlineFunctionInfo : public FunctionInfo +{ +public: + //------------------------------------------------------------------ + /// Construct with the function method name, mangled name, and + /// optional declaration information. + /// + /// @param[in] name + /// A C string name for the method name for this function. This + /// value should not be the mangled named, but the simple method + /// name. + /// + /// @param[in] mangled + /// A C string name for the mangled name for this function. This + /// value can be NULL if there is no mangled information. + /// + /// @param[in] decl_ptr + /// Optional declaration information that describes where the + /// function was declared. This can be NULL. + /// + /// @param[in] call_decl_ptr + /// Optional calling location declaration information that + /// describes from where this inlined function was called. + //------------------------------------------------------------------ + InlineFunctionInfo(const char *name, const char *mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr); + + //------------------------------------------------------------------ + /// Construct with the function method name, mangled name, and + /// optional declaration information. + /// + /// @param[in] name + /// A name for the method name for this function. This value + /// should not be the mangled named, but the simple method name. + /// + /// @param[in] mangled + /// A name for the mangled name for this function. This value + /// can be empty if there is no mangled information. + /// + /// @param[in] decl_ptr + /// Optional declaration information that describes where the + /// function was declared. This can be NULL. + /// + /// @param[in] call_decl_ptr + /// Optional calling location declaration information that + /// describes from where this inlined function was called. + //------------------------------------------------------------------ + InlineFunctionInfo(const ConstString& name, const Mangled &mangled, const Declaration *decl_ptr, const Declaration *call_decl_ptr); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~InlineFunctionInfo(); + + //------------------------------------------------------------------ + /// Compare two inlined function information objects. + /// + /// First compares the FunctionInfo objects, and if equal, + /// compares the mangled names. + /// + /// @param[in] lhs + /// The Left Hand Side const InlineFunctionInfo object + /// reference. + /// + /// @param[in] rhs + /// The Right Hand Side const InlineFunctionInfo object + /// reference. + /// + /// @return + /// @li -1 if lhs < rhs + /// @li 0 if lhs == rhs + /// @li 1 if lhs > rhs + //------------------------------------------------------------------ + int + Compare(const InlineFunctionInfo& lhs, const InlineFunctionInfo& rhs); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + void + Dump(Stream *s, bool show_fullpaths) const; + + void + DumpStopContext (Stream *s) const; + + const ConstString & + GetName () const; + + //------------------------------------------------------------------ + /// Get accessor for the call site declaration information. + /// + /// @return + /// A reference to the declaration object. + //------------------------------------------------------------------ + Declaration& + GetCallSite (); + + //------------------------------------------------------------------ + /// Get const accessor for the call site declaration information. + /// + /// @return + /// A const reference to the declaration object. + //------------------------------------------------------------------ + const Declaration& + GetCallSite () const; + + //------------------------------------------------------------------ + /// Get accessor for the mangled name object. + /// + /// @return + /// A reference to the mangled name object. + //------------------------------------------------------------------ + Mangled& + GetMangled(); + + //------------------------------------------------------------------ + /// Get const accessor for the mangled name object. + /// + /// @return + /// A const reference to the mangled name object. + //------------------------------------------------------------------ + const Mangled& + GetMangled() const; + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// @return + /// The number of bytes that this object occupies in memory. + /// The returned value does not include the bytes for any + /// shared string values. + /// + /// @see ConstString::StaticMemorySize () + //------------------------------------------------------------------ + virtual size_t + MemorySize() const; + +private: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + Mangled m_mangled; ///< Mangled inlined function name (can be empty if there is no mangled information). + Declaration m_call_decl; +}; + +//---------------------------------------------------------------------- +/// @class Function Function.h "lldb/Symbol/Function.h" +/// @brief A class that describes a function. +/// +/// Functions belong to CompileUnit objects (Function::m_comp_unit), +/// have unique user IDs (Function::UserID), know how to reconstruct +/// their symbol context (Function::SymbolContextScope), have a +/// specific function type (Function::m_type_uid), have a simple +/// method name (FunctionInfo::m_name), be declared at a specific +/// location (FunctionInfo::m_declaration), possibly have mangled +/// names (Function::m_mangled), an optional return type +/// (Function::m_type), and contains lexical blocks +/// (Function::m_blocks). +/// +/// The function inforation is split into a few pieces: +/// @li The concrete instance information +/// @li The abstract information +/// +/// The abstract information is found in the function type (Type) that +/// describes a function information, return type and parameter types. +/// +/// The concreate information is the address range information and +/// specific locations for an instance of this function. +//---------------------------------------------------------------------- +class Function : + public UserID, + public SymbolContextScope +{ +public: + //------------------------------------------------------------------ + /// Construct with a compile unit, function UID, function type UID, + /// optional mangled name, function type, and a section offset + /// based address range. + /// + /// @param[in] comp_unit + /// The compile unit to which this function belongs. + /// + /// @param[in] func_uid + /// The UID for this function. This value is provided by the + /// SymbolFile plug-in and can be any value that allows + /// the plug-in to quickly find and parse more detailed + /// information when and if more information is needed. + /// + /// @param[in] func_type_uid + /// The type UID for the function Type to allow for lazy type + /// parsing from the debug information. + /// + /// @param[in] mangled + /// The optional mangled name for this function. If empty, there + /// is no mangled information. + /// + /// @param[in] func_type + /// The optional function type. If NULL, the function type will + /// be parsed on demand when accessed using the + /// Function::GetType() function by asking the SymbolFile + /// plug-in to get the type for \a func_type_uid. + /// + /// @param[in] range + /// The section offset based address for this function. + //------------------------------------------------------------------ + Function ( + CompileUnit *comp_unit, + lldb::user_id_t func_uid, + lldb::user_id_t func_type_uid, + const Mangled &mangled, + Type * func_type, + const AddressRange& range); + + //------------------------------------------------------------------ + /// Construct with a compile unit, function UID, function type UID, + /// optional mangled name, function type, and a section offset + /// based address range. + /// + /// @param[in] comp_unit + /// The compile unit to which this function belongs. + /// + /// @param[in] func_uid + /// The UID for this function. This value is provided by the + /// SymbolFile plug-in and can be any value that allows + /// the plug-in to quickly find and parse more detailed + /// information when and if more information is needed. + /// + /// @param[in] func_type_uid + /// The type UID for the function Type to allow for lazy type + /// parsing from the debug information. + /// + /// @param[in] mangled + /// The optional mangled name for this function. If empty, there + /// is no mangled information. + /// + /// @param[in] func_type + /// The optional function type. If NULL, the function type will + /// be parsed on demand when accessed using the + /// Function::GetType() function by asking the SymbolFile + /// plug-in to get the type for \a func_type_uid. + /// + /// @param[in] range + /// The section offset based address for this function. + //------------------------------------------------------------------ + Function ( + CompileUnit *comp_unit, + lldb::user_id_t func_uid, + lldb::user_id_t func_type_uid, + const char *mangled, + Type * func_type, + const AddressRange& range); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~Function (); + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + CalculateSymbolContext(SymbolContext* sc); + + virtual lldb::ModuleSP + CalculateSymbolContextModule (); + + virtual CompileUnit * + CalculateSymbolContextCompileUnit (); + + virtual Function * + CalculateSymbolContextFunction (); + + const AddressRange & + GetAddressRange() + { + return m_range; + } + + //------------------------------------------------------------------ + /// Find the file and line number of the source location of the start + /// of the function. This will use the declaration if present and fall + /// back on the line table if that fails. So there may NOT be a line + /// table entry for this source file/line combo. + /// + /// @param[out] source_file + /// The source file. + /// + /// @param[out] line_no + /// The line number. + //------------------------------------------------------------------ + void + GetStartLineSourceInfo (FileSpec &source_file, uint32_t &line_no); + + //------------------------------------------------------------------ + /// Find the file and line number of the source location of the end + /// of the function. + /// + /// + /// @param[out] source_file + /// The source file. + /// + /// @param[out] line_no + /// The line number. + //------------------------------------------------------------------ + void + GetEndLineSourceInfo (FileSpec &source_file, uint32_t &line_no); + + //------------------------------------------------------------------ + /// Get accessor for the block list. + /// + /// @return + /// The block list object that describes all lexical blocks + /// in the function. + /// + /// @see BlockList + //------------------------------------------------------------------ + Block& + GetBlock (bool can_create); + + //------------------------------------------------------------------ + /// Get accessor for the compile unit that owns this function. + /// + /// @return + /// A compile unit object pointer. + //------------------------------------------------------------------ + CompileUnit* + GetCompileUnit(); + + //------------------------------------------------------------------ + /// Get const accessor for the compile unit that owns this function. + /// + /// @return + /// A const compile unit object pointer. + //------------------------------------------------------------------ + const CompileUnit* + GetCompileUnit() const; + + void + GetDescription(Stream *s, lldb::DescriptionLevel level, Target *target); + + //------------------------------------------------------------------ + /// Get accessor for the frame base location. + /// + /// @return + /// A location expression that describes the function frame + /// base. + //------------------------------------------------------------------ + DWARFExpression & + GetFrameBaseExpression() + { + return m_frame_base; + } + + //------------------------------------------------------------------ + /// Get const accessor for the frame base location. + /// + /// @return + /// A const compile unit object pointer. + //------------------------------------------------------------------ + const DWARFExpression & + GetFrameBaseExpression() const + { + return m_frame_base; + } + + const ConstString & + GetName() const + { + return m_mangled.GetName(); + } + + const Mangled & + GetMangled() const + { + return m_mangled; + } + + //------------------------------------------------------------------ + /// Get the DeclContext for this function, if available. + /// + /// @return + /// The DeclContext, or NULL if none exists. + //------------------------------------------------------------------ + clang::DeclContext * + GetClangDeclContext(); + + //------------------------------------------------------------------ + /// Get accessor for the type that describes the function + /// return value type, and paramter types. + /// + /// @return + /// A type object pointer. + //------------------------------------------------------------------ + Type* + GetType(); + + //------------------------------------------------------------------ + /// Get const accessor for the type that describes the function + /// return value type, and paramter types. + /// + /// @return + /// A const type object pointer. + //------------------------------------------------------------------ + const Type* + GetType() const; + + ClangASTType + GetClangType (); + + uint32_t + GetPrologueByteSize (); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] show_context + /// If \b true, variables will dump their symbol context + /// information. + //------------------------------------------------------------------ + void + Dump(Stream *s, bool show_context) const; + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::DumpSymbolContext(Stream*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + DumpSymbolContext(Stream *s); + + //------------------------------------------------------------------ + /// Get the memory cost of this object. + /// + /// @return + /// The number of bytes that this object occupies in memory. + /// The returned value does not include the bytes for any + /// shared string values. + /// + /// @see ConstString::StaticMemorySize () + //------------------------------------------------------------------ + size_t + MemorySize () const; + +protected: + + enum + { + flagsCalculatedPrologueSize = (1 << 0) ///< Have we already tried to calculate the prologue size? + }; + + + + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + CompileUnit *m_comp_unit; ///< The compile unit that owns this function. + lldb::user_id_t m_type_uid; ///< The user ID of for the prototype Type for this function. + Type * m_type; ///< The function prototype type for this function that include the function info (FunctionInfo), return type and parameters. + Mangled m_mangled; ///< The mangled function name if any, if empty, there is no mangled information. + Block m_block; ///< All lexical blocks contained in this function. + AddressRange m_range; ///< The function address range that covers the widest range needed to contain all blocks + DWARFExpression m_frame_base; ///< The frame base expression for variables that are relative to the frame pointer. + Flags m_flags; + uint32_t m_prologue_byte_size; ///< Compute the prologue size once and cache it +private: + DISALLOW_COPY_AND_ASSIGN(Function); +}; + +} // namespace lldb_private + +#endif // liblldb_Function_h_ diff --git a/include/lldb/Symbol/LineEntry.h b/include/lldb/Symbol/LineEntry.h new file mode 100644 index 000000000000..d7750cd34916 --- /dev/null +++ b/include/lldb/Symbol/LineEntry.h @@ -0,0 +1,174 @@ +//===-- LineEntry.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_LineEntry_h_ +#define liblldb_LineEntry_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Host/FileSpec.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class LineEntry LineEntry.h "lldb/Symbol/LineEntry.h" +/// @brief A line table entry class. +//---------------------------------------------------------------------- +struct LineEntry +{ + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Initialize all member variables to invalid values. + //------------------------------------------------------------------ + LineEntry (); + + LineEntry + ( + const lldb::SectionSP §ion_sp, + lldb::addr_t section_offset, + lldb::addr_t byte_size, + const FileSpec &file, + uint32_t _line, + uint16_t _column, + bool _is_start_of_statement, + bool _is_start_of_basic_block, + bool _is_prologue_end, + bool _is_epilogue_begin, + bool _is_terminal_entry + ); + + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Clears all member variables to invalid values. + //------------------------------------------------------------------ + void + Clear (); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] comp_unit + /// The compile unit object that contains the support file + /// list so the line entry can dump the file name (since this + /// object contains a file index into the support file list). + /// + /// @param[in] show_file + /// If \b true, display the filename with the line entry which + /// requires that the compile unit object \a comp_unit be a + /// valid pointer. + /// + /// @param[in] style + /// The display style for the section offset address. + /// + /// @return + /// Returns \b true if the address was able to be displayed + /// using \a style. File and load addresses may be unresolved + /// and it may not be possible to display a valid address value. + /// Returns \b false if the address was not able to be properly + /// dumped. + /// + /// @see Address::DumpStyle + //------------------------------------------------------------------ + bool + Dump (Stream *s, Target *target, bool show_file, Address::DumpStyle style, Address::DumpStyle fallback_style, bool show_range) const; + + bool + GetDescription (Stream *s, + lldb::DescriptionLevel level, + CompileUnit* cu, + Target *target, + bool show_address_only) const; + + //------------------------------------------------------------------ + /// Dumps information specific to a process that stops at this + /// line entry to the supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] comp_unit + /// The compile unit object that contains the support file + /// list so the line entry can dump the file name (since this + /// object contains a file index into the support file list). + /// + /// @return + /// Returns \b true if the file and line were properly dumped, + /// \b false otherwise. + //------------------------------------------------------------------ + bool + DumpStopContext (Stream *s, bool show_fullpaths) const; + + //------------------------------------------------------------------ + /// Check if a line entry object is valid. + /// + /// @return + /// Returns \b true if the line entry contains a valid section + /// offset address, file index, and line number, \b false + /// otherwise. + //------------------------------------------------------------------ + bool + IsValid () const; + + //------------------------------------------------------------------ + /// Compare two LineEntry objects. + /// + /// @param[in] lhs + /// The Left Hand Side const LineEntry object reference. + /// + /// @param[in] rhs + /// The Right Hand Side const LineEntry object reference. + /// + /// @return + /// @li -1 if lhs < rhs + /// @li 0 if lhs == rhs + /// @li 1 if lhs > rhs + //------------------------------------------------------------------ + static int + Compare (const LineEntry& lhs, const LineEntry& rhs); + + + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + AddressRange range; ///< The section offset address range for this line entry. + FileSpec file; + uint32_t line; ///< The source line number, or zero if there is no line number information. + uint16_t column; ///< The column number of the source line, or zero if there is no column information. + uint16_t is_start_of_statement:1, ///< Indicates this entry is the beginning of a statement. + is_start_of_basic_block:1, ///< Indicates this entry is the beginning of a basic block. + is_prologue_end:1, ///< Indicates this entry is one (of possibly many) where execution should be suspended for an entry breakpoint of a function. + is_epilogue_begin:1, ///< Indicates this entry is one (of possibly many) where execution should be suspended for an exit breakpoint of a function. + is_terminal_entry:1; ///< Indicates this entry is that of the first byte after the end of a sequence of target machine instructions. +}; + +//------------------------------------------------------------------ +/// Less than operator. +/// +/// @param[in] lhs +/// The Left Hand Side const LineEntry object reference. +/// +/// @param[in] rhs +/// The Right Hand Side const LineEntry object reference. +/// +/// @return +/// Returns \b true if lhs < rhs, false otherwise. +//------------------------------------------------------------------ +bool operator<(const LineEntry& lhs, const LineEntry& rhs); + +} // namespace lldb_private + +#endif // liblldb_LineEntry_h_ diff --git a/include/lldb/Symbol/LineTable.h b/include/lldb/Symbol/LineTable.h new file mode 100644 index 000000000000..477c8455ded8 --- /dev/null +++ b/include/lldb/Symbol/LineTable.h @@ -0,0 +1,422 @@ +//===-- LineTable.h ---------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_LineTable_h_ +#define liblldb_LineTable_h_ + +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/Symbol/LineEntry.h" +#include "lldb/Core/ModuleChild.h" +#include "lldb/Core/Section.h" +#include "lldb/Core/RangeMap.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class LineSequence LineTable.h "lldb/Symbol/LineTable.h" +/// @brief An abstract base class used during symbol table creation. +//---------------------------------------------------------------------- +class LineSequence +{ +public: + LineSequence (); + + virtual + ~LineSequence() {} + + virtual void + Clear() = 0; + +private: + DISALLOW_COPY_AND_ASSIGN (LineSequence); +}; + +//---------------------------------------------------------------------- +/// @class LineTable LineTable.h "lldb/Symbol/LineTable.h" +/// @brief A line table class. +//---------------------------------------------------------------------- +class LineTable +{ +public: + //------------------------------------------------------------------ + /// Construct with compile unit. + /// + /// @param[in] comp_unit + /// The compile unit to which this line table belongs. + //------------------------------------------------------------------ + LineTable (CompileUnit* comp_unit); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~LineTable (); + + //------------------------------------------------------------------ + /// Adds a new line entry to this line table. + /// + /// All line entries are maintained in file address order. + /// + /// @param[in] line_entry + /// A const reference to a new line_entry to add to this line + /// table. + /// + /// @see Address::DumpStyle + //------------------------------------------------------------------ +// void +// AddLineEntry (const LineEntry& line_entry); + + // Called when you can't guarantee the addresses are in increasing order + void + InsertLineEntry (lldb::addr_t file_addr, + uint32_t line, + uint16_t column, + uint16_t file_idx, + bool is_start_of_statement, + bool is_start_of_basic_block, + bool is_prologue_end, + bool is_epilogue_begin, + bool is_terminal_entry); + + // Used to instantiate the LineSequence helper classw + LineSequence* + CreateLineSequenceContainer (); + + // Append an entry to a caller-provided collection that will later be + // inserted in this line table. + void + AppendLineEntryToSequence (LineSequence* sequence, + lldb::addr_t file_addr, + uint32_t line, + uint16_t column, + uint16_t file_idx, + bool is_start_of_statement, + bool is_start_of_basic_block, + bool is_prologue_end, + bool is_epilogue_begin, + bool is_terminal_entry); + + // Insert a sequence of entries into this line table. + void + InsertSequence (LineSequence* sequence); + + //------------------------------------------------------------------ + /// Dump all line entries in this line table to the stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] style + /// The display style for the address. + /// + /// @see Address::DumpStyle + //------------------------------------------------------------------ + void + Dump (Stream *s, Target *target, + Address::DumpStyle style, + Address::DumpStyle fallback_style, + bool show_line_ranges); + + void + GetDescription (Stream *s, + Target *target, + lldb::DescriptionLevel level); + + //------------------------------------------------------------------ + /// Find a line entry that contains the section offset address \a + /// so_addr. + /// + /// @param[in] so_addr + /// A section offset address object containing the address we + /// are searching for. + /// + /// @param[out] line_entry + /// A copy of the line entry that was found if \b true is + /// returned, otherwise \a entry is left unmodified. + /// + /// @param[out] index_ptr + /// A pointer to a 32 bit integer that will get the actual line + /// entry index if it is not NULL. + /// + /// @return + /// Returns \b true if \a so_addr is contained in a line entry + /// in this line table, \b false otherwise. + //------------------------------------------------------------------ + bool + FindLineEntryByAddress (const Address &so_addr, LineEntry& line_entry, uint32_t *index_ptr = NULL); + + //------------------------------------------------------------------ + /// Find a line entry index that has a matching file index and + /// source line number. + /// + /// Finds the next line entry that has a matching \a file_idx and + /// source line number \a line starting at the \a start_idx entries + /// into the line entry collection. + /// + /// @param[in] start_idx + /// The number of entries to skip when starting the search. + /// + /// @param[out] file_idx + /// The file index to search for that should be found prior + /// to calling this function using the following functions: + /// CompileUnit::GetSupportFiles() + /// FileSpecList::FindFileIndex (uint32_t, const FileSpec &) const + /// + /// @param[in] line + /// The source line to match. + /// + /// @param[in] exact + /// If true, match only if you find a line entry exactly matching \a line. + /// If false, return the closest line entry greater than \a line. + /// + /// @param[out] line_entry + /// A reference to a line entry object that will get a copy of + /// the line entry if \b true is returned, otherwise \a + /// line_entry is left untouched. + /// + /// @return + /// Returns \b true if a matching line entry is found in this + /// line table, \b false otherwise. + /// + /// @see CompileUnit::GetSupportFiles() + /// @see FileSpecList::FindFileIndex (uint32_t, const FileSpec &) const + //------------------------------------------------------------------ + uint32_t + FindLineEntryIndexByFileIndex (uint32_t start_idx, + uint32_t file_idx, + uint32_t line, + bool exact, + LineEntry* line_entry_ptr); + + uint32_t + FindLineEntryIndexByFileIndex (uint32_t start_idx, + const std::vector<uint32_t> &file_indexes, + uint32_t line, + bool exact, + LineEntry* line_entry_ptr); + + size_t + FineLineEntriesForFileIndex (uint32_t file_idx, + bool append, + SymbolContextList &sc_list); + + //------------------------------------------------------------------ + /// Get the line entry from the line table at index \a idx. + /// + /// @param[in] idx + /// An index into the line table entry collection. + /// + /// @return + /// A valid line entry if \a idx is a valid index, or an invalid + /// line entry if \a idx is not valid. + /// + /// @see LineTable::GetSize() + /// @see LineEntry::IsValid() const + //------------------------------------------------------------------ + bool + GetLineEntryAtIndex(uint32_t idx, LineEntry& line_entry); + + //------------------------------------------------------------------ + /// Gets the size of the line table in number of line table entries. + /// + /// @return + /// The number of line table entries in this line table. + //------------------------------------------------------------------ + uint32_t + GetSize () const; + + typedef lldb_private::RangeArray<lldb::addr_t, lldb::addr_t, 32> FileAddressRanges; + + //------------------------------------------------------------------ + /// Gets all contiguous file address ranges for the entire line table. + /// + /// @param[out] file_ranges + /// A collection of file address ranges that will be filled in + /// by this function. + /// + /// @param[out] append + /// If \b true, then append to \a file_ranges, otherwise clear + /// \a file_ranges prior to adding any ranges. + /// + /// @return + /// The number of address ranges added to \a file_ranges + //------------------------------------------------------------------ + size_t + GetContiguousFileAddressRanges (FileAddressRanges &file_ranges, bool append); + + //------------------------------------------------------------------ + /// Given a file range link map, relink the current line table + /// and return a fixed up line table. + /// + /// @param[out] file_range_map + /// A collection of file ranges that maps to new file ranges + /// that will be used when linking the line table. + /// + /// @return + /// A new line table if at least one line table entry was able + /// to be mapped. + //------------------------------------------------------------------ + typedef RangeDataVector<lldb::addr_t, lldb::addr_t, lldb::addr_t> FileRangeMap; + + LineTable * + LinkLineTable (const FileRangeMap &file_range_map); + +protected: + + struct Entry + { + Entry () : + file_addr (LLDB_INVALID_ADDRESS), + line (0), + column (0), + file_idx (0), + is_start_of_statement (false), + is_start_of_basic_block (false), + is_prologue_end (false), + is_epilogue_begin (false), + is_terminal_entry (false) + { + } + + Entry ( lldb::addr_t _file_addr, + uint32_t _line, + uint16_t _column, + uint16_t _file_idx, + bool _is_start_of_statement, + bool _is_start_of_basic_block, + bool _is_prologue_end, + bool _is_epilogue_begin, + bool _is_terminal_entry) : + file_addr (_file_addr), + line (_line), + column (_column), + file_idx (_file_idx), + is_start_of_statement (_is_start_of_statement), + is_start_of_basic_block (_is_start_of_basic_block), + is_prologue_end (_is_prologue_end), + is_epilogue_begin (_is_epilogue_begin), + is_terminal_entry (_is_terminal_entry) + { + } + + int + bsearch_compare (const void *key, const void *arrmem); + + void + Clear () + { + file_addr = LLDB_INVALID_ADDRESS; + line = 0; + column = 0; + file_idx = 0; + is_start_of_statement = false; + is_start_of_basic_block = false; + is_prologue_end = false; + is_epilogue_begin = false; + is_terminal_entry = false; + } + + static int + Compare (const Entry& lhs, const Entry& rhs) + { + // Compare the sections before calling + #define SCALAR_COMPARE(a,b) if (a < b) return -1; if (a > b) return +1 + SCALAR_COMPARE (lhs.file_addr, rhs.file_addr); + SCALAR_COMPARE (lhs.line, rhs.line); + SCALAR_COMPARE (lhs.column, rhs.column); + SCALAR_COMPARE (lhs.is_start_of_statement, rhs.is_start_of_statement); + SCALAR_COMPARE (lhs.is_start_of_basic_block, rhs.is_start_of_basic_block); + // rhs and lhs reversed on purpose below. + SCALAR_COMPARE (rhs.is_prologue_end, lhs.is_prologue_end); + SCALAR_COMPARE (lhs.is_epilogue_begin, rhs.is_epilogue_begin); + // rhs and lhs reversed on purpose below. + SCALAR_COMPARE (rhs.is_terminal_entry, lhs.is_terminal_entry); + SCALAR_COMPARE (lhs.file_idx, rhs.file_idx); + #undef SCALAR_COMPARE + return 0; + } + + + class LessThanBinaryPredicate + { + public: + LessThanBinaryPredicate(LineTable *line_table); + bool operator() (const LineTable::Entry&, const LineTable::Entry&) const; + protected: + LineTable *m_line_table; + }; + + static bool EntryAddressLessThan (const Entry& lhs, const Entry& rhs) + { + return lhs.file_addr < rhs.file_addr; + } + + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + lldb::addr_t file_addr; ///< The file address for this line entry + uint32_t line; ///< The source line number, or zero if there is no line number information. + uint16_t column; ///< The column number of the source line, or zero if there is no column information. + uint16_t file_idx:11, ///< The file index into CompileUnit's file table, or zero if there is no file information. + is_start_of_statement:1, ///< Indicates this entry is the beginning of a statement. + is_start_of_basic_block:1, ///< Indicates this entry is the beginning of a basic block. + is_prologue_end:1, ///< Indicates this entry is one (of possibly many) where execution should be suspended for an entry breakpoint of a function. + is_epilogue_begin:1, ///< Indicates this entry is one (of possibly many) where execution should be suspended for an exit breakpoint of a function. + is_terminal_entry:1; ///< Indicates this entry is that of the first byte after the end of a sequence of target machine instructions. + }; + + struct EntrySearchInfo + { + LineTable* line_table; + lldb_private::Section *a_section; + Entry *a_entry; + }; + + //------------------------------------------------------------------ + // Types + //------------------------------------------------------------------ + typedef std::vector<lldb_private::Section*> section_collection; ///< The collection type for the sections. + typedef std::vector<Entry> entry_collection; ///< The collection type for the line entries. + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + CompileUnit* m_comp_unit; ///< The compile unit that this line table belongs to. + entry_collection m_entries; ///< The collection of line entries in this line table. + + //------------------------------------------------------------------ + // Helper class + //------------------------------------------------------------------ + class LineSequenceImpl : public LineSequence + { + public: + LineSequenceImpl() : + LineSequence() + {} + + virtual + ~LineSequenceImpl() + {} + + virtual void + Clear(); + + entry_collection m_entries; ///< The collection of line entries in this sequence. + }; + + bool + ConvertEntryAtIndexToLineEntry (uint32_t idx, LineEntry &line_entry); + +private: + DISALLOW_COPY_AND_ASSIGN (LineTable); +}; + +} // namespace lldb_private + +#endif // liblldb_LineTable_h_ diff --git a/include/lldb/Symbol/ObjectContainer.h b/include/lldb/Symbol/ObjectContainer.h new file mode 100644 index 000000000000..7fb686245057 --- /dev/null +++ b/include/lldb/Symbol/ObjectContainer.h @@ -0,0 +1,236 @@ +//===-- ObjectContainer.h ---------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ObjectContainer_h_ +#define liblldb_ObjectContainer_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes + +#include "lldb/lldb-private.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Core/ModuleChild.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Host/Endian.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ObjectContainer ObjectContainer.h "lldb/Symbol/ObjectContainer.h" +/// @brief A plug-in interface definition class for object containers. +/// +/// Object containers contain object files from one or more +/// architectures, and also can contain one or more named objects. +/// +/// Typical object containers are static libraries (.a files) that +/// contain multiple named object files, and universal files that contain +/// multiple architectures. +//---------------------------------------------------------------------- +class ObjectContainer : + public PluginInterface, + public ModuleChild +{ +public: + //------------------------------------------------------------------ + /// Construct with a parent module, offset, and header data. + /// + /// Object files belong to modules and a valid module must be + /// supplied upon construction. The at an offset within a file for + /// objects that contain more than one architecture or object. + //------------------------------------------------------------------ + ObjectContainer (const lldb::ModuleSP &module_sp, + const FileSpec *file, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset) : + ModuleChild (module_sp), + m_file (), // This file can be different than the module's file spec + m_offset (file_offset), + m_length (length), + m_data () + { + if (file) + m_file = *file; + if (data_sp) + m_data.SetData (data_sp, data_offset, length); + } + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual since this class is designed to be + /// inherited from by the plug-in instance. + //------------------------------------------------------------------ + virtual + ~ObjectContainer() + { + } + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the current contents of this object + /// to the supplied stream \a s. The dumping should include the + /// section list if it has been parsed, and the symbol table + /// if it has been parsed. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + virtual void + Dump (Stream *s) const = 0; + + //------------------------------------------------------------------ + /// Gets the architecture given an index. + /// + /// Copies the architecture specification for index \a idx. + /// + /// @param[in] idx + /// The architecture index to extract. + /// + /// @param[out] arch + /// A architecture object that will be filled in if \a idx is a + /// architecture valid index. + /// + /// @return + /// Returns \b true if \a idx is valid and \a arch has been + /// filled in, \b false otherwise. + /// + /// @see ObjectContainer::GetNumArchitectures() const + //------------------------------------------------------------------ + virtual bool + GetArchitectureAtIndex (uint32_t idx, ArchSpec& arch) const + { + return false; + } + + //------------------------------------------------------------------ + /// Returns the offset into a file at which this object resides. + /// + /// Some files contain many object files, and this function allows + /// access to an object's offset within the file. + /// + /// @return + /// The offset in bytes into the file. Defaults to zero for + /// simple object files that a represented by an entire file. + //------------------------------------------------------------------ + virtual lldb::addr_t + GetOffset () const + { return m_offset; } + + virtual lldb::addr_t + GetByteSize () const + { return m_length; } + + //------------------------------------------------------------------ + /// Get the number of objects within this object file (archives). + /// + /// @return + /// Zero for object files that are not archives, or the number + /// of objects contained in the archive. + //------------------------------------------------------------------ + virtual size_t + GetNumObjects () const + { return 0; } + + //------------------------------------------------------------------ + /// Get the number of architectures in this object file. + /// + /// The default implementation returns 1 as for object files that + /// contain a single architecture. ObjectContainer instances that + /// contain more than one architecture should override this function + /// and return an appropriate value. + /// + /// @return + /// The number of architectures contained in this object file. + //------------------------------------------------------------------ + virtual size_t + GetNumArchitectures () const + { return 0; } + + //------------------------------------------------------------------ + /// Attempts to parse the object header. + /// + /// This function is used as a test to see if a given plug-in + /// instance can parse the header data already contained in + /// ObjectContainer::m_data. If an object file parser does not + /// recognize that magic bytes in a header, false should be returned + /// and the next plug-in can attempt to parse an object file. + /// + /// @return + /// Returns \b true if the header was parsed succesfully, \b + /// false otherwise. + //------------------------------------------------------------------ + virtual bool + ParseHeader () = 0; + + //------------------------------------------------------------------ + /// Selects an architecture in an object file. + /// + /// Object files that contain a single architecture should verify + /// that the specified \a arch matches the architecture in in + /// object file and return \b true or \b false accordingly. + /// + /// Object files that contain more than one architecture should + /// attempt to select that architecture, and if successful, clear + /// out any previous state from any previously selected architecture + /// and prepare to return information for the new architecture. + /// + /// @return + /// Returns a pointer to the object file of the requested \a + /// arch and optional \a name. Returns NULL of no such object + /// file exists in the container. + //------------------------------------------------------------------ + virtual lldb::ObjectFileSP + GetObjectFile (const FileSpec *file) = 0; + + virtual bool + ObjectAtIndexIsContainer (uint32_t object_idx) + { + return false; + } + + virtual ObjectFile * + GetObjectFileAtIndex (uint32_t object_idx) + { + return NULL; + } + + virtual ObjectContainer * + GetObjectContainerAtIndex (uint32_t object_idx) + { + return NULL; + } + + virtual const char * + GetObjectNameAtIndex (uint32_t object_idx) const + { + return NULL; + } + +protected: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + FileSpec m_file; ///< The file that represents this container objects (which can be different from the module's file). + lldb::addr_t m_offset; ///< The offset in bytes into the file, or the address in memory + lldb::addr_t m_length; ///< The size in bytes if known (can be zero). + DataExtractor m_data; ///< The data for this object file so things can be parsed lazily. + +private: + DISALLOW_COPY_AND_ASSIGN (ObjectContainer); +}; + +} // namespace lldb_private + +#endif // liblldb_ObjectContainer_h_ diff --git a/include/lldb/Symbol/ObjectFile.h b/include/lldb/Symbol/ObjectFile.h new file mode 100644 index 000000000000..8934c31bb988 --- /dev/null +++ b/include/lldb/Symbol/ObjectFile.h @@ -0,0 +1,706 @@ +//===-- ObjectFile.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_ObjectFile_h_ +#define liblldb_ObjectFile_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/DataExtractor.h" +#include "lldb/Host/FileSpec.h" +#include "lldb/Core/FileSpecList.h" +#include "lldb/Core/ModuleChild.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Host/Endian.h" +#include "lldb/Symbol/Symtab.h" +#include "lldb/Symbol/UnwindTable.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ObjectFile ObjectFile.h "lldb/Symbol/ObjectFile.h" +/// @brief A plug-in interface definition class for object file parsers. +/// +/// Object files belong to Module objects and know how to extract +/// information from executable, shared library, and object (.o) files +/// used by operating system runtime. The symbol table and section list +/// for an object file. +/// +/// Object files can be represented by the entire file, or by part of a +/// file. Examples of object files that are part of a file include +/// object files that contain information for multiple architectures in +/// the same file, or archive files that contain multiple objects +/// (ranlib archives) (possibly for multiple architectures as well). +/// +/// Object archive files (e.g. ranlib archives) can contain +/// multiple .o (object) files that must be selected by index or by name. +/// The number of objects that an ObjectFile contains can be determined +/// using the ObjectFile::GetNumObjects() const +/// function, and followed by a call to +/// ObjectFile::SelectObjectAtIndex (uint32_t) to change the currently +/// selected object. Objects can also be selected by name using the +/// ObjectFile::SelectObject(const char *) function. +/// +/// Once an architecture is selected (and an object is selected for +/// for archives), the object file information can be extracted from +/// this abstract class. +//---------------------------------------------------------------------- +class ObjectFile: + public std::enable_shared_from_this<ObjectFile>, + public PluginInterface, + public ModuleChild +{ +friend class lldb_private::Module; + +public: + typedef enum + { + eTypeInvalid = 0, + eTypeCoreFile, /// A core file that has a checkpoint of a program's execution state + eTypeExecutable, /// A normal executable + eTypeDebugInfo, /// An object file that contains only debug information + eTypeDynamicLinker, /// The platform's dynamic linker executable + eTypeObjectFile, /// An intermediate object file + eTypeSharedLibrary, /// A shared library that can be used during execution + eTypeStubLibrary, /// A library that can be linked against but not used for execution + eTypeUnknown + } Type; + + typedef enum + { + eStrataInvalid = 0, + eStrataUnknown, + eStrataUser, + eStrataKernel, + eStrataRawImage + } Strata; + + //------------------------------------------------------------------ + /// Construct with a parent module, offset, and header data. + /// + /// Object files belong to modules and a valid module must be + /// supplied upon construction. The at an offset within a file for + /// objects that contain more than one architecture or object. + //------------------------------------------------------------------ + ObjectFile (const lldb::ModuleSP &module_sp, + const FileSpec *file_spec_ptr, + lldb::offset_t file_offset, + lldb::offset_t length, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset); + + ObjectFile (const lldb::ModuleSP &module_sp, + const lldb::ProcessSP &process_sp, + lldb::addr_t header_addr, + lldb::DataBufferSP& data_sp); + + //------------------------------------------------------------------ + /// Destructor. + /// + /// The destructor is virtual since this class is designed to be + /// inherited from by the plug-in instance. + //------------------------------------------------------------------ + virtual + ~ObjectFile(); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the current contents of this object + /// to the supplied stream \a s. The dumping should include the + /// section list if it has been parsed, and the symbol table + /// if it has been parsed. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + virtual void + Dump (Stream *s) = 0; + + //------------------------------------------------------------------ + /// Find a ObjectFile plug-in that can parse \a file_spec. + /// + /// Scans all loaded plug-in interfaces that implement versions of + /// the ObjectFile plug-in interface and returns the first + /// instance that can parse the file. + /// + /// @param[in] module + /// The parent module that owns this object file. + /// + /// @param[in] file_spec + /// A file specification that indicates which file to use as the + /// object file. + /// + /// @param[in] file_offset + /// The offset into the file at which to start parsing the + /// object. This is for files that contain multiple + /// architectures or objects. + /// + /// @param[in] file_size + /// The size of the current object file if it can be determined + /// or if it is known. This can be zero. + /// + /// @see ObjectFile::ParseHeader() + //------------------------------------------------------------------ + static lldb::ObjectFileSP + FindPlugin (const lldb::ModuleSP &module_sp, + const FileSpec* file_spec, + lldb::offset_t file_offset, + lldb::offset_t file_size, + lldb::DataBufferSP &data_sp, + lldb::offset_t &data_offset); + + //------------------------------------------------------------------ + /// Find a ObjectFile plug-in that can parse a file in memory. + /// + /// Scans all loaded plug-in interfaces that implement versions of + /// the ObjectFile plug-in interface and returns the first + /// instance that can parse the file. + /// + /// @param[in] module + /// The parent module that owns this object file. + /// + /// @param[in] process_sp + /// A shared pointer to the process whose memory space contains + /// an object file. This will be stored as a std::weak_ptr. + /// + /// @param[in] header_addr + /// The address of the header for the object file in memory. + //------------------------------------------------------------------ + static lldb::ObjectFileSP + FindPlugin (const lldb::ModuleSP &module_sp, + const lldb::ProcessSP &process_sp, + lldb::addr_t header_addr, + lldb::DataBufferSP &file_data_sp); + + + static size_t + GetModuleSpecifications (const FileSpec &file, + lldb::offset_t file_offset, + lldb::offset_t file_size, + ModuleSpecList &specs); + + static size_t + GetModuleSpecifications (const lldb_private::FileSpec& file, + lldb::DataBufferSP& data_sp, + lldb::offset_t data_offset, + lldb::offset_t file_offset, + lldb::offset_t file_size, + lldb_private::ModuleSpecList &specs); + //------------------------------------------------------------------ + /// Split a path into a file path with object name. + /// + /// For paths like "/tmp/foo.a(bar.o)" we often need to split a path + /// up into the actual path name and into the object name so we can + /// make a valid object file from it. + /// + /// @param[in] path_with_object + /// A path that might contain an archive path with a .o file + /// specified in parens in the basename of the path. + /// + /// @param[out] archive_file + /// If \b true is returned, \a file_spec will be filled in with + /// the path to the archive. + /// + /// @param[out] archive_object + /// If \b true is returned, \a object will be filled in with + /// the name of the object inside the archive. + /// + /// @return + /// \b true if the path matches the pattern of archive + object + /// and \a archive_file and \a archive_object are modified, + /// \b false otherwise and \a archive_file and \a archive_object + /// are guaranteed to be remain unchanged. + //------------------------------------------------------------------ + static bool + SplitArchivePathWithObject (const char *path_with_object, + lldb_private::FileSpec &archive_file, + lldb_private::ConstString &archive_object, + bool must_exist); + + //------------------------------------------------------------------ + /// Gets the address size in bytes for the current object file. + /// + /// @return + /// The size of an address in bytes for the currently selected + /// architecture (and object for archives). Returns zero if no + /// architecture or object has been selected. + //------------------------------------------------------------------ + virtual uint32_t + GetAddressByteSize () const = 0; + + //------------------------------------------------------------------ + /// Get the address type given a file address in an object file. + /// + /// Many binary file formats know what kinds + /// This is primarily for ARM binaries, though it can be applied to + /// any executable file format that supports different opcode types + /// within the same binary. ARM binaries support having both ARM and + /// Thumb within the same executable container. We need to be able + /// to get + /// @return + /// The size of an address in bytes for the currently selected + /// architecture (and object for archives). Returns zero if no + /// architecture or object has been selected. + //------------------------------------------------------------------ + virtual lldb::AddressClass + GetAddressClass (lldb::addr_t file_addr); + + //------------------------------------------------------------------ + /// Extract the dependent modules from an object file. + /// + /// If an object file has information about which other images it + /// depends on (such as shared libraries), this function will + /// provide the list. Since many executables or shared libraries + /// may depend on the same files, + /// FileSpecList::AppendIfUnique(const FileSpec &) should be + /// used to make sure any files that are added are not already in + /// the list. + /// + /// @param[out] file_list + /// A list of file specification objects that gets dependent + /// files appended to. + /// + /// @return + /// The number of new files that were appended to \a file_list. + /// + /// @see FileSpecList::AppendIfUnique(const FileSpec &) + //------------------------------------------------------------------ + virtual uint32_t + GetDependentModules (FileSpecList& file_list) = 0; + + //------------------------------------------------------------------ + /// Tells whether this object file is capable of being the main executable + /// for a process. + /// + /// @return + /// \b true if it is, \b false otherwise. + //------------------------------------------------------------------ + virtual bool + IsExecutable () const = 0; + + //------------------------------------------------------------------ + /// Returns the offset into a file at which this object resides. + /// + /// Some files contain many object files, and this function allows + /// access to an object's offset within the file. + /// + /// @return + /// The offset in bytes into the file. Defaults to zero for + /// simple object files that a represented by an entire file. + //------------------------------------------------------------------ + virtual lldb::addr_t + GetFileOffset () const + { return m_file_offset; } + + virtual lldb::addr_t + GetByteSize () const + { return m_length; } + + //------------------------------------------------------------------ + /// Get accessor to the object file specification. + /// + /// @return + /// The file specification object pointer if there is one, or + /// NULL if this object is only from memory. + //------------------------------------------------------------------ + virtual FileSpec& + GetFileSpec() { return m_file; } + + //------------------------------------------------------------------ + /// Get const accessor to the object file specification. + /// + /// @return + /// The const file specification object pointer if there is one, + /// or NULL if this object is only from memory. + //------------------------------------------------------------------ + virtual const FileSpec& + GetFileSpec() const { return m_file; } + + //------------------------------------------------------------------ + /// Get the name of the cpu, vendor and OS for this object file. + /// + /// This value is a string that represents the target triple where + /// the cpu type, the vendor and the OS are encoded into a string. + /// + /// @param[out] target_triple + /// The string value of the target triple. + /// + /// @return + /// \b True if the target triple was able to be computed, \b + /// false otherwise. + //------------------------------------------------------------------ + virtual bool + GetArchitecture (ArchSpec &arch) = 0; + + //------------------------------------------------------------------ + /// Gets the section list for the currently selected architecture + /// (and object for archives). + /// + /// Section list parsing can be deferred by ObjectFile instances + /// until this accessor is called the first time. + /// + /// @return + /// The list of sections contained in this object file. + //------------------------------------------------------------------ + virtual SectionList * + GetSectionList (); + + virtual void + CreateSections (SectionList &unified_section_list) = 0; + + //------------------------------------------------------------------ + /// Gets the symbol table for the currently selected architecture + /// (and object for archives). + /// + /// Symbol table parsing can be deferred by ObjectFile instances + /// until this accessor is called the first time. + /// + /// @return + /// The symbol table for this object file. + //------------------------------------------------------------------ + virtual Symtab * + GetSymtab () = 0; + + //------------------------------------------------------------------ + /// Detect if this object file has been stripped of local symbols. + /// + /// @return + /// Return \b true if the object file has been stripped of local + /// symbols. + //------------------------------------------------------------------ + virtual bool + IsStripped () = 0; + + //------------------------------------------------------------------ + /// Frees the symbol table. + /// + /// This function should only be used when an object file is + /// + /// @param[in] flags + /// eSymtabFromUnifiedSectionList: Whether to clear symbol table + /// for unified module section list, or object file. + /// + /// @return + /// The symbol table for this object file. + //------------------------------------------------------------------ + virtual void + ClearSymtab (); + + //------------------------------------------------------------------ + /// Gets the UUID for this object file. + /// + /// If the object file format contains a UUID, the value should be + /// returned. Else ObjectFile instances should return the MD5 + /// checksum of all of the bytes for the object file (or memory for + /// memory based object files). + /// + /// @return + /// Returns \b true if a UUID was successfully extracted into + /// \a uuid, \b false otherwise. + //------------------------------------------------------------------ + virtual bool + GetUUID (lldb_private::UUID* uuid) = 0; + + //------------------------------------------------------------------ + /// Gets the symbol file spec list for this object file. + /// + /// If the object file format contains a debug symbol file link, + /// the values will be return in the FileSpecList. + /// + /// @return + /// Returns filespeclist. + //------------------------------------------------------------------ + virtual lldb_private::FileSpecList + GetDebugSymbolFilePaths() + { + return FileSpecList(); + } + + //------------------------------------------------------------------ + /// Gets whether endian swapping should occur when extracting data + /// from this object file. + /// + /// @return + /// Returns \b true if endian swapping is needed, \b false + /// otherwise. + //------------------------------------------------------------------ + virtual lldb::ByteOrder + GetByteOrder () const = 0; + + //------------------------------------------------------------------ + /// Attempts to parse the object header. + /// + /// This function is used as a test to see if a given plug-in + /// instance can parse the header data already contained in + /// ObjectFile::m_data. If an object file parser does not + /// recognize that magic bytes in a header, false should be returned + /// and the next plug-in can attempt to parse an object file. + /// + /// @return + /// Returns \b true if the header was parsed succesfully, \b + /// false otherwise. + //------------------------------------------------------------------ + virtual bool + ParseHeader () = 0; + + //------------------------------------------------------------------ + /// Returns a reference to the UnwindTable for this ObjectFile + /// + /// The UnwindTable contains FuncUnwinders objects for any function in + /// this ObjectFile. 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 object file. + //------------------------------------------------------------------ + virtual lldb_private::UnwindTable& + GetUnwindTable () { return m_unwind_table; } + + //------------------------------------------------------------------ + /// Similar to Process::GetImageInfoAddress(). + /// + /// Some platforms embed auxiliary structures useful to debuggers in the + /// address space of the inferior process. This method returns the address + /// of such a structure if the information can be resolved via entries in + /// the object file. ELF, for example, provides a means to hook into the + /// runtime linker so that a debugger may monitor the loading and unloading + /// of shared libraries. + /// + /// @return + /// The address of any auxiliary tables, or an invalid address if this + /// object file format does not support or contain such information. + virtual lldb_private::Address + GetImageInfoAddress () { return Address(); } + + //------------------------------------------------------------------ + /// Returns the address of the Entry Point in this object file - if + /// the object file doesn't have an entry point (because it is not an + /// executable file) then an invalid address is returned. + /// + /// @return + /// Returns the entry address for this module. + //------------------------------------------------------------------ + virtual lldb_private::Address + GetEntryPointAddress () { return Address();} + + //------------------------------------------------------------------ + /// Returns the address that represents the header of this object + /// file. + /// + /// The header address is defined as where the header for the object + /// file is that describes the content of the file. If the header + /// doesn't appear in a section that is defined in the object file, + /// an address with no section is returned that has the file offset + /// set in the m_file_offset member of the lldb_private::Address object. + /// + /// @return + /// Returns the entry address for this module. + //------------------------------------------------------------------ + virtual lldb_private::Address + GetHeaderAddress () { return Address(m_memory_addr);} + + + virtual uint32_t + GetNumThreadContexts () + { + return 0; + } + + virtual lldb::RegisterContextSP + GetThreadContextAtIndex (uint32_t idx, lldb_private::Thread &thread) + { + return lldb::RegisterContextSP(); + } + + //------------------------------------------------------------------ + /// The object file should be able to calculate its type by looking + /// at its file header and possibly the sections or other data in + /// the object file. The file type is used in the debugger to help + /// select the correct plug-ins for the job at hand, so this is + /// important to get right. If any eTypeXXX definitions do not match + /// up with the type of file you are loading, please feel free to + /// add a new enumeration value. + /// + /// @return + /// The calculated file type for the current object file. + //------------------------------------------------------------------ + virtual Type + CalculateType() = 0; + + //------------------------------------------------------------------ + /// In cases where the type can't be calculated (elf files), this + /// routine allows someone to explicitly set it. As an example, + /// SymbolVendorELF uses this routine to set eTypeDebugInfo when + /// loading debug link files. + virtual void + SetType (Type type) + { + m_type = type; + } + + //------------------------------------------------------------------ + /// The object file should be able to calculate the strata of the + /// object file. + /// + /// Many object files for platforms might be for either user space + /// debugging or for kernel debugging. If your object file subclass + /// can figure this out, it will help with debugger plug-in selection + /// when it comes time to debug. + /// + /// @return + /// The calculated object file strata for the current object + /// file. + //------------------------------------------------------------------ + virtual Strata + CalculateStrata() = 0; + + //------------------------------------------------------------------ + /// Get the object file version numbers. + /// + /// Many object files have a set of version numbers that describe + /// the version of the executable or shared library. Typically there + /// are major, minor and build, but there may be more. This function + /// will extract the versions from object files if they are available. + /// + /// If \a versions is NULL, or if \a num_versions is 0, the return + /// value will indicate how many version numbers are available in + /// this object file. Then a subsequent call can be made to this + /// function with a value of \a versions and \a num_versions that + /// has enough storage to store some or all version numbers. + /// + /// @param[out] versions + /// A pointer to an array of uint32_t types that is \a num_versions + /// long. If this value is NULL, the return value will indicate + /// how many version numbers are required for a subsequent call + /// to this function so that all versions can be retrieved. If + /// the value is non-NULL, then at most \a num_versions of the + /// existing versions numbers will be filled into \a versions. + /// If there is no version information available, \a versions + /// will be filled with \a num_versions UINT32_MAX values + /// and zero will be returned. + /// + /// @param[in] num_versions + /// The maximum number of entries to fill into \a versions. If + /// this value is zero, then the return value will indicate + /// how many version numbers there are in total so another call + /// to this function can be make with adequate storage in + /// \a versions to get all of the version numbers. If \a + /// num_versions is less than the actual number of version + /// numbers in this object file, only \a num_versions will be + /// filled into \a versions (if \a versions is non-NULL). + /// + /// @return + /// This function always returns the number of version numbers + /// that this object file has regardless of the number of + /// version numbers that were copied into \a versions. + //------------------------------------------------------------------ + virtual uint32_t + GetVersion (uint32_t *versions, uint32_t num_versions) + { + if (versions && num_versions) + { + for (uint32_t i=0; i<num_versions; ++i) + versions[i] = UINT32_MAX; + } + return 0; + } + + //------------------------------------------------------------------ + // Member Functions + //------------------------------------------------------------------ + Type + GetType () + { + if (m_type == eTypeInvalid) + m_type = CalculateType(); + return m_type; + } + + Strata + GetStrata () + { + if (m_strata == eStrataInvalid) + m_strata = CalculateStrata(); + return m_strata; + } + + // When an object file is in memory, subclasses should try and lock + // the process weak pointer. If the process weak pointer produces a + // valid ProcessSP, then subclasses can call this function to read + // memory. + static lldb::DataBufferSP + ReadMemory (const lldb::ProcessSP &process_sp, + lldb::addr_t addr, + size_t byte_size); + + size_t + GetData (off_t offset, size_t length, DataExtractor &data) const; + + size_t + CopyData (off_t offset, size_t length, void *dst) const; + + size_t + ReadSectionData (const Section *section, + off_t section_offset, + void *dst, + size_t dst_len) const; + size_t + ReadSectionData (const Section *section, + DataExtractor& section_data) const; + + size_t + MemoryMapSectionData (const Section *section, + DataExtractor& section_data) const; + + bool + IsInMemory () const + { + return m_memory_addr != LLDB_INVALID_ADDRESS; + } + +protected: + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + FileSpec m_file; + Type m_type; + Strata m_strata; + lldb::addr_t m_file_offset; ///< The offset in bytes into the file, or the address in memory + lldb::addr_t m_length; ///< The length of this object file if it is known (can be zero if length is unknown or can't be determined). + DataExtractor m_data; ///< The data for this object file so things can be parsed lazily. + lldb_private::UnwindTable m_unwind_table; /// < Table of FuncUnwinders objects created for this ObjectFile's functions + lldb::ProcessWP m_process_wp; + const lldb::addr_t m_memory_addr; + std::unique_ptr<lldb_private::SectionList> m_sections_ap; + std::unique_ptr<lldb_private::Symtab> m_symtab_ap; + + //------------------------------------------------------------------ + /// Sets the architecture for a module. At present the architecture + /// can only be set if it is invalid. It is not allowed to switch from + /// one concrete architecture to another. + /// + /// @param[in] new_arch + /// The architecture this module will be set to. + /// + /// @return + /// Returns \b true if the architecture was changed, \b + /// false otherwise. + //------------------------------------------------------------------ + bool SetModulesArchitecture (const ArchSpec &new_arch); + +private: + DISALLOW_COPY_AND_ASSIGN (ObjectFile); +}; + +} // namespace lldb_private + +#endif // liblldb_ObjectFile_h_ + diff --git a/include/lldb/Symbol/Symbol.h b/include/lldb/Symbol/Symbol.h new file mode 100644 index 000000000000..11c1cc7af9ab --- /dev/null +++ b/include/lldb/Symbol/Symbol.h @@ -0,0 +1,317 @@ +//===-- Symbol.h ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Symbol_h_ +#define liblldb_Symbol_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Core/Mangled.h" +#include "lldb/Core/UserID.h" +#include "lldb/Symbol/SymbolContextScope.h" + +namespace lldb_private { + +class Symbol : + public SymbolContextScope +{ +public: + // ObjectFile readers can classify their symbol table entries and searches can be made + // on specific types where the symbol values will have drastically different meanings + // and sorting requirements. + Symbol(); + + Symbol (uint32_t symID, + const char *name, + bool name_is_mangled, + lldb::SymbolType type, + bool external, + bool is_debug, + bool is_trampoline, + bool is_artificial, + const lldb::SectionSP §ion_sp, + lldb::addr_t value, + lldb::addr_t size, + bool size_is_valid, + uint32_t flags); + + Symbol (uint32_t symID, + const char *name, + bool name_is_mangled, + lldb::SymbolType type, + bool external, + bool is_debug, + bool is_trampoline, + bool is_artificial, + const AddressRange &range, + bool size_is_valid, + uint32_t flags); + + Symbol (const Symbol& rhs); + + const Symbol& + operator= (const Symbol& rhs); + + void + Clear(); + + bool + Compare (const ConstString& name, lldb::SymbolType type) const; + + void + Dump (Stream *s, Target *target, uint32_t index) const; + + bool + ValueIsAddress() const; + + //------------------------------------------------------------------ + // Access the address value. Do NOT hand out the AddressRange as an + // object as the byte size of the address range may not be filled in + // and it should be accessed via GetByteSize(). + //------------------------------------------------------------------ + Address & + GetAddress() + { + return m_addr_range.GetBaseAddress(); + } + + //------------------------------------------------------------------ + // Access the address value. Do NOT hand out the AddressRange as an + // object as the byte size of the address range may not be filled in + // and it should be accessed via GetByteSize(). + //------------------------------------------------------------------ + const Address & + GetAddress() const + { + return m_addr_range.GetBaseAddress(); + } + + const ConstString & + GetName () const + { + return m_mangled.GetName(); + } + + uint32_t + GetID() const + { + return m_uid; + } + + void + SetID(uint32_t uid) + { + m_uid = uid; + } + + Mangled& + GetMangled () + { + return m_mangled; + } + + const Mangled& + GetMangled () const + { + return m_mangled; + } + + uint32_t + GetSiblingIndex () const; + + lldb::SymbolType + GetType () const + { + return (lldb::SymbolType)m_type; + } + + void + SetType (lldb::SymbolType type) + { + m_type = (lldb::SymbolType)type; + } + + const char * + GetTypeAsString () const; + + uint32_t + GetFlags () const + { + return m_flags; + } + + void + SetFlags (uint32_t flags) + { + m_flags = flags; + } + + void + GetDescription (Stream *s, lldb::DescriptionLevel level, Target *target) const; + + bool + IsSynthetic () const + { + return m_is_synthetic; + } + + void + SetIsSynthetic (bool b) + { + m_is_synthetic = b; + } + + + bool + GetSizeIsSynthesized() const + { + return m_size_is_synthesized; + } + + void + SetSizeIsSynthesized(bool b) + { + m_size_is_synthesized = b; + } + + bool + IsDebug () const + { + return m_is_debug; + } + + void + SetDebug (bool b) + { + m_is_debug = b; + } + + bool + IsExternal () const + { + return m_is_external; + } + + void + SetExternal (bool b) + { + m_is_external = b; + } + + bool + IsTrampoline () const; + + bool + IsIndirect () const; + + bool + GetByteSizeIsValid () const + { + return m_size_is_valid; + } + + lldb::addr_t + GetByteSize () const; + + void + SetByteSize (lldb::addr_t size) + { + m_size_is_valid = size > 0; + m_addr_range.SetByteSize(size); + } + + bool + GetSizeIsSibling () const + { + return m_size_is_sibling; + } + + void + SetSizeIsSibling (bool b) + { + m_size_is_sibling = b; + } + +// void +// SetValue (Address &value) +// { +// m_addr_range.GetBaseAddress() = value; +// } +// +// void +// SetValue (const AddressRange &range) +// { +// m_addr_range = range; +// } +// +// void +// SetValue (lldb::addr_t value); +// { +// m_addr_range.GetBaseAddress().SetRawAddress(value); +// } + + // If m_type is "Code" or "Function" then this will return the prologue size + // in bytes, else it will return zero. + uint32_t + GetPrologueByteSize (); + + bool + GetDemangledNameIsSynthesized() const + { + return m_demangled_is_synthesized; + } + void + SetDemangledNameIsSynthesized(bool b) + { + m_demangled_is_synthesized = b; + } + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::CalculateSymbolContext(SymbolContext*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + CalculateSymbolContext (SymbolContext *sc); + + virtual lldb::ModuleSP + CalculateSymbolContextModule (); + + virtual Symbol * + CalculateSymbolContextSymbol (); + + //------------------------------------------------------------------ + /// @copydoc SymbolContextScope::DumpSymbolContext(Stream*) + /// + /// @see SymbolContextScope + //------------------------------------------------------------------ + virtual void + DumpSymbolContext (Stream *s); + +protected: + + uint32_t m_uid; // User ID (usually the original symbol table index) + uint16_t m_type_data; // data specific to m_type + uint16_t m_type_data_resolved:1, // True if the data in m_type_data has already been calculated + m_is_synthetic:1, // non-zero if this symbol is not actually in the symbol table, but synthesized from other info in the object file. + m_is_debug:1, // non-zero if this symbol is debug information in a symbol + m_is_external:1, // non-zero if this symbol is globally visible + m_size_is_sibling:1, // m_size contains the index of this symbol's sibling + m_size_is_synthesized:1,// non-zero if this symbol's size was calculated using a delta between this symbol and the next + m_size_is_valid:1, + m_demangled_is_synthesized:1, // The demangled name was created should not be used for expressions or other lookups + m_type:8; + Mangled m_mangled; // uniqued symbol name/mangled name pair + AddressRange m_addr_range; // Contains the value, or the section offset address when the value is an address in a section, and the size (if any) + uint32_t m_flags; // A copy of the flags from the original symbol table, the ObjectFile plug-in can interpret these +}; + +} // namespace lldb_private + +#endif // liblldb_Symbol_h_ diff --git a/include/lldb/Symbol/SymbolContext.h b/include/lldb/Symbol/SymbolContext.h new file mode 100644 index 000000000000..5b12adebf5f5 --- /dev/null +++ b/include/lldb/Symbol/SymbolContext.h @@ -0,0 +1,566 @@ +//===-- SymbolContext.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef liblldb_SymbolContext_h_ +#define liblldb_SymbolContext_h_ + +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/Core/Address.h" +#include "lldb/Core/Mangled.h" +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/LineEntry.h" + +namespace lldb_private { + +class SymbolContextScope; +//---------------------------------------------------------------------- +/// @class SymbolContext SymbolContext.h "lldb/Symbol/SymbolContext.h" +/// @brief Defines a symbol context baton that can be handed other debug +/// core functions. +/// +/// Many debugger functions require a context when doing lookups. This +/// class provides a common structure that can be used as the result +/// of a query that can contain a single result. Examples of such +/// queries include +/// @li Looking up a load address. +//---------------------------------------------------------------------- +class SymbolContext +{ +public: + + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Initialize all pointer members to NULL and all struct members + /// to their default state. + //------------------------------------------------------------------ + SymbolContext (); + + //------------------------------------------------------------------ + /// Construct with an object that knows how to reconstruct its + /// symbol context. + /// + /// @param[in] sc_scope + /// A symbol context scope object that knows how to reconstruct + /// it's context. + //------------------------------------------------------------------ + explicit + SymbolContext (SymbolContextScope *sc_scope); + + //------------------------------------------------------------------ + /// Construct with module, and optional compile unit, function, + /// block, line table, line entry and symbol. + /// + /// Initialize all pointer to the specified values. + /// + /// @param[in] module + /// A Module pointer to the module for this context. + /// + /// @param[in] comp_unit + /// A CompileUnit pointer to the compile unit for this context. + /// + /// @param[in] function + /// A Function pointer to the function for this context. + /// + /// @param[in] block + /// A Block pointer to the deepest block for this context. + /// + /// @param[in] line_entry + /// A LineEntry pointer to the line entry for this context. + /// + /// @param[in] symbol + /// A Symbol pointer to the symbol for this context. + //------------------------------------------------------------------ + explicit + SymbolContext (const lldb::TargetSP &target_sp, + const lldb::ModuleSP &module_sp, + CompileUnit *comp_unit = NULL, + Function *function = NULL, + Block *block = NULL, + LineEntry *line_entry = NULL, + Symbol *symbol = NULL); + + // This version sets the target to a NULL TargetSP if you don't know it. + explicit + SymbolContext (const lldb::ModuleSP &module_sp, + CompileUnit *comp_unit = NULL, + Function *function = NULL, + Block *block = NULL, + LineEntry *line_entry = NULL, + Symbol *symbol = NULL); + + ~SymbolContext (); + //------------------------------------------------------------------ + /// Copy constructor + /// + /// Makes a copy of the another SymbolContext object \a rhs. + /// + /// @param[in] rhs + /// A const SymbolContext object reference to copy. + //------------------------------------------------------------------ + SymbolContext (const SymbolContext& rhs); + + //------------------------------------------------------------------ + /// Assignment operator. + /// + /// Copies the address value from another SymbolContext object \a + /// rhs into \a this object. + /// + /// @param[in] rhs + /// A const SymbolContext object reference to copy. + /// + /// @return + /// A const SymbolContext object reference to \a this. + //------------------------------------------------------------------ + const SymbolContext& + operator= (const SymbolContext& rhs); + + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Resets all pointer members to NULL, and clears any class objects + /// to their default state. + //------------------------------------------------------------------ + void + Clear (bool clear_target); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of this object to the + /// supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + void + Dump (Stream *s, Target *target) const; + + //------------------------------------------------------------------ + /// Dump the stop context in this object to a Stream. + /// + /// Dump the best description of this object to the stream. The + /// information displayed depends on the amount and quality of the + /// information in this context. If a module, function, file and + /// line number are available, they will be dumped. If only a + /// module and function or symbol name with offset is available, + /// that will be output. Else just the address at which the target + /// was stopped will be displayed. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + /// + /// @param[in] so_addr + /// The resolved section offset address. + //------------------------------------------------------------------ + bool + DumpStopContext (Stream *s, + ExecutionContextScope *exe_scope, + const Address &so_addr, + bool show_fullpaths, + bool show_module, + bool show_inlined_frames) const; + + //------------------------------------------------------------------ + /// Get the address range contained within a symbol context. + /// + /// Address range priority is as follows: + /// - line_entry address range if line_entry is valid and eSymbolContextLineEntry is set in \a scope + /// - block address range if block is not NULL and eSymbolContextBlock is set in \a scope + /// - function address range if function is not NULL and eSymbolContextFunction is set in \a scope + /// - symbol address range if symbol is not NULL and eSymbolContextSymbol is set in \a scope + /// + /// @param[in] scope + /// A mask of symbol context bits telling this function which + /// address ranges it can use when trying to extract one from + /// the valid (non-NULL) symbol context classes. + /// + /// @param[in] range_idx + /// The address range index to grab. Since many functions and + /// blocks are not always contiguous, they may have more than + /// one address range. + /// + /// @param[in] use_inline_block_range + /// If \a scope has the eSymbolContextBlock bit set, and there + /// is a valid block in the symbol context, return the block + /// address range for the containing inline function block, not + /// the deepest most block. This allows us to extract information + /// for the address range of the inlined function block, not + /// the deepest lexical block. + /// + /// @param[out] range + /// An address range object that will be filled in if \b true + /// is returned. + /// + /// @return + /// \b True if this symbol context contains items that describe + /// an address range, \b false otherwise. + //------------------------------------------------------------------ + bool + GetAddressRange (uint32_t scope, + uint32_t range_idx, + bool use_inline_block_range, + AddressRange &range) const; + + + void + GetDescription(Stream *s, + lldb::DescriptionLevel level, + Target *target) const; + + uint32_t + GetResolvedMask () const; + + + //------------------------------------------------------------------ + /// Find a block that defines the function represented by this + /// symbol context. + /// + /// If this symbol context points to a block that is an inlined + /// function, or is contained within an inlined function, the block + /// that defines the inlined function is returned. + /// + /// If this symbol context has no block in it, or the block is not + /// itself an inlined function block or contained within one, we + /// return the top level function block. + /// + /// This is a handy function to call when you want to get the block + /// whose variable list will include the arguments for the function + /// that is represented by this symbol context (whether the function + /// is an inline function or not). + /// + /// @return + /// The block object pointer that defines the function that is + /// represented by this symbol context object, NULL otherwise. + //------------------------------------------------------------------ + Block * + GetFunctionBlock (); + + + //------------------------------------------------------------------ + /// If this symbol context represents a function that is a method, + /// return true and provide information about the method. + /// + /// @param[out] language + /// If \b true is returned, the language for the method. + /// + /// @param[out] is_instance_method + /// If \b true is returned, \b true if this is a instance method, + /// \b false if this is a static/class function. + /// + /// @param[out] language_object_name + /// If \b true is returned, the name of the artificial variable + /// for the language ("this" for C++, "self" for ObjC). + /// + /// @return + /// \b True if this symbol context represents a function that + /// is a method of a class, \b false otherwise. + //------------------------------------------------------------------ + bool + GetFunctionMethodInfo (lldb::LanguageType &language, + bool &is_instance_method, + ConstString &language_object_name); + + //------------------------------------------------------------------ + /// Find a name of the innermost function for the symbol context. + /// + /// For instance, if the symbol context contains an inlined block, + /// it will return the inlined function name. + /// + /// @param[in] prefer_mangled + /// if \btrue, then the mangled name will be returned if there + /// is one. Otherwise the unmangled name will be returned if it + /// is available. + /// + /// @return + /// The name of the function represented by this symbol context. + //------------------------------------------------------------------ + ConstString + GetFunctionName (Mangled::NamePreference preference = Mangled::ePreferDemangled) const; + + + //------------------------------------------------------------------ + /// Get the line entry that corresponds to the function. + /// + /// If the symbol context contains an inlined block, the line entry + /// for the start address of the inlined function will be returned, + /// otherwise the line entry for the start address of the function + /// will be returned. This can be used after doing a + /// Module::FindFunctions(...) or ModuleList::FindFunctions(...) + /// call in order to get the correct line table information for + /// the symbol context. + /// it will return the inlined function name. + /// + /// @param[in] prefer_mangled + /// if \btrue, then the mangled name will be returned if there + /// is one. Otherwise the unmangled name will be returned if it + /// is available. + /// + /// @return + /// The name of the function represented by this symbol context. + //------------------------------------------------------------------ + LineEntry + GetFunctionStartLineEntry () const; + + //------------------------------------------------------------------ + /// Find the block containing the inlined block that contains this block. + /// + /// For instance, if the symbol context contains an inlined block, + /// it will return the inlined function name. + /// + /// @param[in] curr_frame_pc + /// The address within the block of this object. + /// + /// @param[out] next_frame_sc + /// A new symbol context that does what the title says it does. + /// + /// @param[out] next_frame_addr + /// This is what you should report as the PC in \a next_frame_sc. + /// + /// @return + /// \b true if this SymbolContext specifies a block contained in an + /// inlined block. If this returns \b true, \a next_frame_sc and + /// \a next_frame_addr will be filled in correctly. + //------------------------------------------------------------------ + bool + GetParentOfInlinedScope (const Address &curr_frame_pc, + SymbolContext &next_frame_sc, + Address &inlined_frame_addr) const; + + //------------------------------------------------------------------ + // Member variables + //------------------------------------------------------------------ + lldb::TargetSP target_sp; ///< The Target for a given query + lldb::ModuleSP module_sp; ///< The Module for a given query + CompileUnit * comp_unit; ///< The CompileUnit for a given query + Function * function; ///< The Function for a given query + Block * block; ///< The Block for a given query + LineEntry line_entry; ///< The LineEntry for a given query + Symbol * symbol; ///< The Symbol for a given query +}; + + +class SymbolContextSpecifier +{ +public: + typedef enum SpecificationType + { + eNothingSpecified = 0, + eModuleSpecified = 1 << 0, + eFileSpecified = 1 << 1, + eLineStartSpecified = 1 << 2, + eLineEndSpecified = 1 << 3, + eFunctionSpecified = 1 << 4, + eClassOrNamespaceSpecified = 1 << 5, + eAddressRangeSpecified = 1 << 6 + } SpecificationType; + + // This one produces a specifier that matches everything... + SymbolContextSpecifier (const lldb::TargetSP& target_sp); + + ~SymbolContextSpecifier(); + + bool + AddSpecification (const char *spec_string, SpecificationType type); + + bool + AddLineSpecification (uint32_t line_no, SpecificationType type); + + void + Clear(); + + bool + SymbolContextMatches(SymbolContext &sc); + + bool + AddressMatches(lldb::addr_t addr); + + void + GetDescription (Stream *s, lldb::DescriptionLevel level) const; + +private: + lldb::TargetSP m_target_sp; + std::string m_module_spec; + lldb::ModuleSP m_module_sp; + std::unique_ptr<FileSpec> m_file_spec_ap; + size_t m_start_line; + size_t m_end_line; + std::string m_function_spec; + std::string m_class_name; + std::unique_ptr<AddressRange> m_address_range_ap; + uint32_t m_type; // Or'ed bits from SpecificationType + +}; + +//---------------------------------------------------------------------- +/// @class SymbolContextList SymbolContext.h "lldb/Symbol/SymbolContext.h" +/// @brief Defines a list of symbol context objects. +/// +/// This class provides a common structure that can be used to contain +/// the result of a query that can contain a multiple results. Examples +/// of such queries include: +/// @li Looking up a function by name. +/// @li Finding all addressses for a specified file and line number. +//---------------------------------------------------------------------- +class SymbolContextList +{ +public: + //------------------------------------------------------------------ + /// Default constructor. + /// + /// Initialize with an empty list. + //------------------------------------------------------------------ + SymbolContextList (); + + //------------------------------------------------------------------ + /// Destructor. + //------------------------------------------------------------------ + ~SymbolContextList (); + + //------------------------------------------------------------------ + /// Append a new symbol context to the list. + /// + /// @param[in] sc + /// A symbol context to append to the list. + //------------------------------------------------------------------ + void + Append (const SymbolContext& sc); + + void + Append (const SymbolContextList& sc_list); + + bool + AppendIfUnique (const SymbolContext& sc, + bool merge_symbol_into_function); + + bool + MergeSymbolContextIntoFunctionContext (const SymbolContext& symbol_sc, + uint32_t start_idx = 0, + uint32_t stop_idx = UINT32_MAX); + + uint32_t + AppendIfUnique (const SymbolContextList& sc_list, + bool merge_symbol_into_function); + //------------------------------------------------------------------ + /// Clear the object's state. + /// + /// Clears the symbol context list. + //------------------------------------------------------------------ + void + Clear(); + + //------------------------------------------------------------------ + /// Dump a description of this object to a Stream. + /// + /// Dump a description of the contents of each symbol context in + /// the list to the supplied stream \a s. + /// + /// @param[in] s + /// The stream to which to dump the object descripton. + //------------------------------------------------------------------ + void + Dump(Stream *s, Target *target) const; + + //------------------------------------------------------------------ + /// Get accessor for a symbol context at index \a idx. + /// + /// Dump a description of the contents of each symbol context in + /// the list to the supplied stream \a s. + /// + /// @param[in] idx + /// The zero based index into the symbol context list. + /// + /// @param[out] sc + /// A reference to the symbol context to fill in. + /// + /// @return + /// Returns \b true if \a idx was a valid index into this + /// symbol context list and \a sc was filled in, \b false + /// otherwise. + //------------------------------------------------------------------ + bool + GetContextAtIndex(size_t idx, SymbolContext& sc) const; + + //------------------------------------------------------------------ + /// Direct reference accessor for a symbol context at index \a idx. + /// + /// The index \a idx must be a valid index, no error checking will + /// be done to ensure that it is valid. + /// + /// @param[in] idx + /// The zero based index into the symbol context list. + /// + /// @return + /// A const reference to the symbol context to fill in. + //------------------------------------------------------------------ + SymbolContext& + operator [] (size_t idx) + { + return m_symbol_contexts[idx]; + } + + const SymbolContext& + operator [] (size_t idx) const + { + return m_symbol_contexts[idx]; + } + + //------------------------------------------------------------------ + /// Get accessor for the last symbol context in the list. + /// + /// @param[out] sc + /// A reference to the symbol context to fill in. + /// + /// @return + /// Returns \b true if \a sc was filled in, \b false if the + /// list is empty. + //------------------------------------------------------------------ + bool + GetLastContext(SymbolContext& sc) const; + + bool + RemoveContextAtIndex (size_t idx); + //------------------------------------------------------------------ + /// Get accessor for a symbol context list size. + /// + /// @return + /// Returns the number of symbol context objects in the list. + //------------------------------------------------------------------ + uint32_t + GetSize() const; + + uint32_t + NumLineEntriesWithLine (uint32_t line) const; + + void + GetDescription(Stream *s, + lldb::DescriptionLevel level, + Target *target) const; + +protected: + typedef std::vector<SymbolContext> collection; ///< The collection type for the list. + + //------------------------------------------------------------------ + // Member variables. + //------------------------------------------------------------------ + collection m_symbol_contexts; ///< The list of symbol contexts. +}; + +bool operator== (const SymbolContext& lhs, const SymbolContext& rhs); +bool operator!= (const SymbolContext& lhs, const SymbolContext& rhs); + +bool operator== (const SymbolContextList& lhs, const SymbolContextList& rhs); +bool operator!= (const SymbolContextList& lhs, const SymbolContextList& rhs); + +} // namespace lldb_private + +#endif // liblldb_SymbolContext_h_ diff --git a/include/lldb/Symbol/SymbolContextScope.h b/include/lldb/Symbol/SymbolContextScope.h new file mode 100644 index 000000000000..693cc0131e27 --- /dev/null +++ b/include/lldb/Symbol/SymbolContextScope.h @@ -0,0 +1,137 @@ +//===-- SymbolContextScope.h ------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_SymbolContextScope_h_ +#define liblldb_SymbolContextScope_h_ + +// C Includes +// C++ Includes +// Other libraries and framework includes +// Project includes +#include "lldb/lldb-private.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class SymbolContextScope SymbolContextScope.h "lldb/Symbol/SymbolContextScope.h" +/// @brief Inherit from this if your object is part of a symbol context +/// and can reconstruct its symbol context. +/// +/// Many objects that are part of a symbol context that have pointers +/// back to parent objects that own them. Any members of a symbol +/// context that, once they are built, will not go away, can inherit +/// from this pure virtual class and can then reconstruct their symbol +/// context without having to keep a complete SymbolContext object in +/// the object. +/// +/// Examples of these objects include: +/// @li Module +/// @li CompileUnit +/// @li Function +/// @li Block +/// @li Symbol +/// +/// Other objects can store a "SymbolContextScope *" using any pointers +/// to one of the above objects. This allows clients to hold onto a +/// pointer that uniquely will identify a symbol context. Those clients +/// can then always reconstruct the symbol context using the pointer, or +/// use it to uniquely identify a symbol context for an object. +/// +/// Example objects include that currently use "SymbolContextScope *" +/// objects include: +/// @li Variable objects that can reconstruct where they are scoped +/// by making sure the SymbolContextScope * comes from the scope +/// in which the variable was declared. If a variable is a global, +/// the appropriate CompileUnit * will be used when creating the +/// variable. A static function variables, can the Block scope +/// in which the variable is defined. Function arguments can use +/// the Function object as their scope. The SymbolFile parsers +/// will set these correctly as the variables are parsed. +/// @li Type objects that know exactly in which scope they +/// originated much like the variables above. +/// @li StackID objects that are able to know that if the CFA +/// (stack pointer at the beginning of a function) and the +/// start PC for the function/symbol and the SymbolContextScope +/// pointer (a unique pointer that identifies a symbol context +/// location) match within the same thread, that the stack +/// frame is the same as the previous stack frame. +/// +/// Objects that adhere to this protocol can reconstruct enough of a +/// symbol context to allow functions that take a symbol context to be +/// called. Lists can also be created using a SymbolContextScope* and +/// and object pairs that allow large collections of objects to be +/// passed around with minimal overhead. +//---------------------------------------------------------------------- +class SymbolContextScope +{ +public: + virtual + ~SymbolContextScope () {} + + //------------------------------------------------------------------ + /// Reconstruct the object's symbolc context into \a sc. + /// + /// The object should fill in as much of the SymbolContext as it + /// can so function calls that require a symbol context can be made + /// for the given object. + /// + /// @param[out] sc + /// A symbol context object pointer that gets filled in. + //------------------------------------------------------------------ + virtual void + CalculateSymbolContext (SymbolContext *sc) = 0; + + + virtual lldb::ModuleSP + CalculateSymbolContextModule () + { + return lldb::ModuleSP(); + } + + virtual CompileUnit * + CalculateSymbolContextCompileUnit () + { + return NULL; + } + + virtual Function * + CalculateSymbolContextFunction () + { + return NULL; + } + + virtual Block * + CalculateSymbolContextBlock () + { + return NULL; + } + + virtual Symbol * + CalculateSymbolContextSymbol () + { + return NULL; + } + + //------------------------------------------------------------------ + /// Dump the object's symbolc context to the stream \a s. + /// + /// The object should dump its symbol context to the stream \a s. + /// This function is widely used in the DumpDebug and verbose output + /// for lldb objets. + /// + /// @param[in] s + /// The stream to which to dump the object's symbol context. + //------------------------------------------------------------------ + virtual void + DumpSymbolContext (Stream *s) = 0; +}; + +} // namespace lldb_private + +#endif // liblldb_SymbolContextScope_h_ diff --git a/include/lldb/Symbol/SymbolFile.h b/include/lldb/Symbol/SymbolFile.h new file mode 100644 index 000000000000..5b774e3a7d13 --- /dev/null +++ b/include/lldb/Symbol/SymbolFile.h @@ -0,0 +1,167 @@ +//===-- SymbolFile.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_SymbolFile_h_ +#define liblldb_SymbolFile_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/ClangNamespaceDecl.h" +#include "lldb/Symbol/Type.h" + +namespace lldb_private { + +class SymbolFile : + public PluginInterface +{ +public: + //------------------------------------------------------------------ + // Symbol file ability bits. + // + // Each symbol file can claim to support one or more symbol file + // abilities. These get returned from SymbolFile::GetAbilities(). + // These help us to determine which plug-in will be best to load + // the debug information found in files. + //------------------------------------------------------------------ + enum Abilities + { + CompileUnits = (1u << 0), + LineTables = (1u << 1), + Functions = (1u << 2), + Blocks = (1u << 3), + GlobalVariables = (1u << 4), + LocalVariables = (1u << 5), + VariableTypes = (1u << 6), + kAllAbilities =((1u << 7) - 1u) + }; + + static SymbolFile * + FindPlugin (ObjectFile* obj_file); + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + SymbolFile(ObjectFile* obj_file) : + m_obj_file(obj_file), + m_abilities(0), + m_calculated_abilities(false) + { + } + + virtual + ~SymbolFile() + { + } + + //------------------------------------------------------------------ + /// Get a mask of what this symbol file supports for the object file + /// that it was constructed with. + /// + /// Each symbol file gets to respond with a mask of abilities that + /// it supports for each object file. This happens when we are + /// trying to figure out which symbol file plug-in will get used + /// for a given object file. The plug-in that resoonds with the + /// best mix of "SymbolFile::Abilities" bits set, will get chosen to + /// be the symbol file parser. This allows each plug-in to check for + /// sections that contain data a symbol file plug-in would need. For + /// example the DWARF plug-in requires DWARF sections in a file that + /// contain debug information. If the DWARF plug-in doesn't find + /// these sections, it won't respond with many ability bits set, and + /// we will probably fall back to the symbol table SymbolFile plug-in + /// which uses any information in the symbol table. Also, plug-ins + /// might check for some specific symbols in a symbol table in the + /// case where the symbol table contains debug information (STABS + /// and COFF). Not a lot of work should happen in these functions + /// as the plug-in might not get selected due to another plug-in + /// having more abilities. Any initialization work should be saved + /// for "void SymbolFile::InitializeObject()" which will get called + /// on the SymbolFile object with the best set of abilities. + /// + /// @return + /// A uint32_t mask containing bits from the SymbolFile::Abilities + /// enumeration. Any bits that are set represent an ability that + /// this symbol plug-in can parse from the object file. + ///------------------------------------------------------------------ + uint32_t GetAbilities () + { + if (!m_calculated_abilities) + { + m_abilities = CalculateAbilities(); + m_calculated_abilities = true; + } + + return m_abilities; + } + + virtual uint32_t CalculateAbilities() = 0; + + //------------------------------------------------------------------ + /// Initialize the SymbolFile object. + /// + /// The SymbolFile object with the best set of abilities (detected + /// in "uint32_t SymbolFile::GetAbilities()) will have this function + /// called if it is chosen to parse an object file. More complete + /// initialization can happen in this function which will get called + /// prior to any other functions in the SymbolFile protocol. + //------------------------------------------------------------------ + virtual void InitializeObject() {} + + //------------------------------------------------------------------ + // Compile Unit function calls + //------------------------------------------------------------------ + // Approach 1 - iterator + virtual uint32_t GetNumCompileUnits() = 0; + virtual lldb::CompUnitSP ParseCompileUnitAtIndex(uint32_t index) = 0; + + virtual lldb::LanguageType ParseCompileUnitLanguage (const SymbolContext& sc) = 0; + virtual size_t ParseCompileUnitFunctions (const SymbolContext& sc) = 0; + virtual bool ParseCompileUnitLineTable (const SymbolContext& sc) = 0; + virtual bool ParseCompileUnitSupportFiles (const SymbolContext& sc, FileSpecList& support_files) = 0; + virtual size_t ParseFunctionBlocks (const SymbolContext& sc) = 0; + virtual size_t ParseTypes (const SymbolContext& sc) = 0; + virtual size_t ParseVariablesForContext (const SymbolContext& sc) = 0; + virtual Type* ResolveTypeUID (lldb::user_id_t type_uid) = 0; + virtual bool ResolveClangOpaqueTypeDefinition (ClangASTType &clang_type) = 0; + virtual clang::DeclContext* GetClangDeclContextForTypeUID (const lldb_private::SymbolContext &sc, lldb::user_id_t type_uid) { return NULL; } + virtual clang::DeclContext* GetClangDeclContextContainingTypeUID (lldb::user_id_t type_uid) { return NULL; } + virtual uint32_t ResolveSymbolContext (const Address& so_addr, uint32_t resolve_scope, SymbolContext& sc) = 0; + virtual uint32_t ResolveSymbolContext (const FileSpec& file_spec, uint32_t line, bool check_inlines, uint32_t resolve_scope, SymbolContextList& sc_list) = 0; + virtual uint32_t FindGlobalVariables (const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, VariableList& variables) = 0; + virtual uint32_t FindGlobalVariables (const RegularExpression& regex, bool append, uint32_t max_matches, VariableList& variables) = 0; + virtual uint32_t FindFunctions (const ConstString &name, const ClangNamespaceDecl *namespace_decl, uint32_t name_type_mask, bool include_inlines, bool append, SymbolContextList& sc_list) = 0; + virtual uint32_t FindFunctions (const RegularExpression& regex, bool include_inlines, bool append, SymbolContextList& sc_list) = 0; + virtual uint32_t FindTypes (const SymbolContext& sc, const ConstString &name, const ClangNamespaceDecl *namespace_decl, bool append, uint32_t max_matches, TypeList& types) = 0; +// virtual uint32_t FindTypes (const SymbolContext& sc, const RegularExpression& regex, bool append, uint32_t max_matches, TypeList& types) = 0; + virtual TypeList * GetTypeList (); + virtual size_t GetTypes (lldb_private::SymbolContextScope *sc_scope, + uint32_t type_mask, + lldb_private::TypeList &type_list) = 0; + virtual ClangASTContext & + GetClangASTContext (); + virtual ClangNamespaceDecl + FindNamespace (const SymbolContext& sc, + const ConstString &name, + const ClangNamespaceDecl *parent_namespace_decl) = 0; + + ObjectFile* GetObjectFile() { return m_obj_file; } + const ObjectFile* GetObjectFile() const { return m_obj_file; } + +protected: + ObjectFile* m_obj_file; // The object file that symbols can be extracted from. + uint32_t m_abilities; + bool m_calculated_abilities; +private: + DISALLOW_COPY_AND_ASSIGN (SymbolFile); +}; + + +} // namespace lldb_private + +#endif // liblldb_SymbolFile_h_ diff --git a/include/lldb/Symbol/SymbolVendor.h b/include/lldb/Symbol/SymbolVendor.h new file mode 100644 index 000000000000..0eeea4eb466b --- /dev/null +++ b/include/lldb/Symbol/SymbolVendor.h @@ -0,0 +1,207 @@ +//===-- SymbolVendor.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_SymbolVendor_h_ +#define liblldb_SymbolVendor_h_ + +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/Core/ModuleChild.h" +#include "lldb/Core/PluginInterface.h" +#include "lldb/Symbol/ClangNamespaceDecl.h" +#include "lldb/Symbol/TypeList.h" + + +namespace lldb_private { + +//---------------------------------------------------------------------- +// The symbol vendor class is designed to abstract the process of +// searching for debug information for a given module. Platforms can +// subclass this class and provide extra ways to find debug information. +// Examples would be a subclass that would allow for locating a stand +// alone debug file, parsing debug maps, or runtime data in the object +// files. A symbol vendor can use multiple sources (SymbolFile +// objects) to provide the information and only parse as deep as needed +// in order to provide the information that is requested. +//---------------------------------------------------------------------- +class SymbolVendor : + public ModuleChild, + public PluginInterface +{ +public: + static SymbolVendor* + FindPlugin (const lldb::ModuleSP &module_sp, + Stream *feedback_strm); + + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + SymbolVendor(const lldb::ModuleSP &module_sp); + + virtual + ~SymbolVendor(); + + void + AddSymbolFileRepresentation(const lldb::ObjectFileSP &objfile_sp); + + virtual void + Dump(Stream *s); + + virtual lldb::LanguageType + ParseCompileUnitLanguage (const SymbolContext& sc); + + virtual size_t + ParseCompileUnitFunctions (const SymbolContext& sc); + + virtual bool + ParseCompileUnitLineTable (const SymbolContext& sc); + + virtual bool + ParseCompileUnitSupportFiles (const SymbolContext& sc, + FileSpecList& support_files); + + virtual size_t + ParseFunctionBlocks (const SymbolContext& sc); + + virtual size_t + ParseTypes (const SymbolContext& sc); + + virtual size_t + ParseVariablesForContext (const SymbolContext& sc); + + virtual Type* + ResolveTypeUID(lldb::user_id_t type_uid); + + virtual uint32_t + ResolveSymbolContext (const Address& so_addr, + uint32_t resolve_scope, + SymbolContext& sc); + + virtual uint32_t + ResolveSymbolContext (const FileSpec& file_spec, + uint32_t line, + bool check_inlines, + uint32_t resolve_scope, + SymbolContextList& sc_list); + + virtual size_t + FindGlobalVariables (const ConstString &name, + const ClangNamespaceDecl *namespace_decl, + bool append, + size_t max_matches, + VariableList& variables); + + virtual size_t + FindGlobalVariables (const RegularExpression& regex, + bool append, + size_t max_matches, + VariableList& variables); + + virtual size_t + FindFunctions (const ConstString &name, + const ClangNamespaceDecl *namespace_decl, + uint32_t name_type_mask, + bool include_inlines, + bool append, + SymbolContextList& sc_list); + + virtual size_t + FindFunctions (const RegularExpression& regex, + bool include_inlines, + bool append, + SymbolContextList& sc_list); + + virtual size_t + FindTypes (const SymbolContext& sc, + const ConstString &name, + const ClangNamespaceDecl *namespace_decl, + bool append, + size_t max_matches, + TypeList& types); + + virtual ClangNamespaceDecl + FindNamespace (const SymbolContext& sc, + const ConstString &name, + const ClangNamespaceDecl *parent_namespace_decl); + + virtual size_t + GetNumCompileUnits(); + + virtual bool + SetCompileUnitAtIndex (size_t cu_idx, + const lldb::CompUnitSP &cu_sp); + + virtual lldb::CompUnitSP + GetCompileUnitAtIndex(size_t idx); + + TypeList& + GetTypeList() + { + return m_type_list; + } + + const TypeList& + GetTypeList() const + { + return m_type_list; + } + + virtual size_t + GetTypes (SymbolContextScope *sc_scope, + uint32_t type_mask, + TypeList &type_list); + + SymbolFile * + GetSymbolFile() + { + return m_sym_file_ap.get(); + } + + // Get module unified section list symbol table. + virtual Symtab * + GetSymtab (); + + // Clear module unified section list symbol table. + virtual void + ClearSymtab (); + + //------------------------------------------------------------------ + // PluginInterface protocol + //------------------------------------------------------------------ + virtual ConstString + GetPluginName(); + + virtual uint32_t + GetPluginVersion(); + +protected: + //------------------------------------------------------------------ + // Classes that inherit from SymbolVendor can see and modify these + //------------------------------------------------------------------ + typedef std::vector<lldb::CompUnitSP> CompileUnits; + typedef CompileUnits::iterator CompileUnitIter; + typedef CompileUnits::const_iterator CompileUnitConstIter; + + TypeList m_type_list; // Uniqued types for all parsers owned by this module + CompileUnits m_compile_units; // The current compile units + lldb::ObjectFileSP m_objfile_sp; // Keep a reference to the object file in case it isn't the same as the module object file (debug symbols in a separate file) + std::unique_ptr<SymbolFile> m_sym_file_ap; // A single symbol file. Subclasses can add more of these if needed. + +private: + //------------------------------------------------------------------ + // For SymbolVendor only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (SymbolVendor); +}; + + +} // namespace lldb_private + +#endif // liblldb_SymbolVendor_h_ diff --git a/include/lldb/Symbol/Symtab.h b/include/lldb/Symbol/Symtab.h new file mode 100644 index 000000000000..666c3b5686b9 --- /dev/null +++ b/include/lldb/Symbol/Symtab.h @@ -0,0 +1,160 @@ +//===-- Symtab.h ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef liblldb_Symtab_h_ +#define liblldb_Symtab_h_ + +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/Core/RangeMap.h" +#include "lldb/Core/UniqueCStringMap.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Symbol/Symbol.h" + +namespace lldb_private { + +class Symtab +{ +public: + typedef std::vector<uint32_t> IndexCollection; + typedef UniqueCStringMap<uint32_t> NameToIndexMap; + + typedef enum Debug { + eDebugNo, // Not a debug symbol + eDebugYes, // A debug symbol + eDebugAny + } Debug; + + typedef enum Visibility { + eVisibilityAny, + eVisibilityExtern, + eVisibilityPrivate + } Visibility; + + Symtab(ObjectFile *objfile); + ~Symtab(); + + void Reserve (size_t count); + Symbol * Resize (size_t count); + uint32_t AddSymbol(const Symbol& symbol); + size_t GetNumSymbols() const; + void Dump(Stream *s, Target *target, SortOrder sort_type); + void Dump(Stream *s, Target *target, std::vector<uint32_t>& indexes) const; + uint32_t GetIndexForSymbol (const Symbol *symbol) const; + Mutex & GetMutex () + { + return m_mutex; + } + Symbol * FindSymbolByID (lldb::user_id_t uid) const; + Symbol * SymbolAtIndex (size_t idx); + const Symbol * SymbolAtIndex (size_t idx) const; + Symbol * FindSymbolWithType (lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, uint32_t &start_idx); + uint32_t AppendSymbolIndexesWithType (lldb::SymbolType symbol_type, std::vector<uint32_t>& indexes, uint32_t start_idx = 0, uint32_t end_index = UINT32_MAX) const; + uint32_t AppendSymbolIndexesWithTypeAndFlagsValue (lldb::SymbolType symbol_type, uint32_t flags_value, std::vector<uint32_t>& indexes, uint32_t start_idx = 0, uint32_t end_index = UINT32_MAX) const; + uint32_t AppendSymbolIndexesWithType (lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& matches, uint32_t start_idx = 0, uint32_t end_index = UINT32_MAX) const; + uint32_t AppendSymbolIndexesWithName (const ConstString& symbol_name, std::vector<uint32_t>& matches); + uint32_t AppendSymbolIndexesWithName (const ConstString& symbol_name, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& matches); + uint32_t AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, lldb::SymbolType symbol_type, std::vector<uint32_t>& matches); + uint32_t AppendSymbolIndexesWithNameAndType (const ConstString& symbol_name, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& matches); + uint32_t AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®ex, lldb::SymbolType symbol_type, std::vector<uint32_t>& indexes); + uint32_t AppendSymbolIndexesMatchingRegExAndType (const RegularExpression ®ex, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& indexes); + size_t FindAllSymbolsWithNameAndType (const ConstString &name, lldb::SymbolType symbol_type, std::vector<uint32_t>& symbol_indexes); + size_t FindAllSymbolsWithNameAndType (const ConstString &name, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes); + size_t FindAllSymbolsMatchingRexExAndType (const RegularExpression ®ex, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility, std::vector<uint32_t>& symbol_indexes); + Symbol * FindFirstSymbolWithNameAndType (const ConstString &name, lldb::SymbolType symbol_type, Debug symbol_debug_type, Visibility symbol_visibility); + Symbol * FindSymbolContainingFileAddress (lldb::addr_t file_addr, const uint32_t* indexes, uint32_t num_indexes); + Symbol * FindSymbolContainingFileAddress (lldb::addr_t file_addr); + size_t FindFunctionSymbols (const ConstString &name, uint32_t name_type_mask, SymbolContextList& sc_list); + void CalculateSymbolSizes (); + + void SortSymbolIndexesByValue (std::vector<uint32_t>& indexes, bool remove_duplicates) const; + + static void DumpSymbolHeader (Stream *s); + + + void Finalize () + { + // Shrink to fit the symbols so we don't waste memory + if (m_symbols.capacity() > m_symbols.size()) + { + collection new_symbols (m_symbols.begin(), m_symbols.end()); + m_symbols.swap (new_symbols); + } + } + + void AppendSymbolNamesToMap (const IndexCollection &indexes, + bool add_demangled, + bool add_mangled, + NameToIndexMap &name_to_index_map) const; + +protected: + typedef std::vector<Symbol> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + typedef RangeDataVector<lldb::addr_t, lldb::addr_t, uint32_t> FileRangeToIndexMap; + void InitNameIndexes (); + void InitAddressIndexes (); + + ObjectFile * m_objfile; + collection m_symbols; + FileRangeToIndexMap m_file_addr_to_index; + UniqueCStringMap<uint32_t> m_name_to_index; + UniqueCStringMap<uint32_t> m_basename_to_index; + UniqueCStringMap<uint32_t> m_method_to_index; + UniqueCStringMap<uint32_t> m_selector_to_index; + mutable Mutex m_mutex; // Provide thread safety for this symbol table + bool m_file_addr_to_index_computed:1, + m_name_indexes_computed:1; +private: + + bool + CheckSymbolAtIndex (size_t idx, Debug symbol_debug_type, Visibility symbol_visibility) const + { + switch (symbol_debug_type) + { + case eDebugNo: + if (m_symbols[idx].IsDebug() == true) + return false; + break; + + case eDebugYes: + if (m_symbols[idx].IsDebug() == false) + return false; + break; + + case eDebugAny: + break; + } + + switch (symbol_visibility) + { + case eVisibilityAny: + return true; + + case eVisibilityExtern: + return m_symbols[idx].IsExternal(); + + case eVisibilityPrivate: + return !m_symbols[idx].IsExternal(); + } + return false; + } + + void + SymbolIndicesToSymbolContextList (std::vector<uint32_t> &symbol_indexes, + SymbolContextList &sc_list); + + DISALLOW_COPY_AND_ASSIGN (Symtab); +}; + +} // namespace lldb_private + +#endif // liblldb_Symtab_h_ diff --git a/include/lldb/Symbol/TaggedASTType.h b/include/lldb/Symbol/TaggedASTType.h new file mode 100644 index 000000000000..c44a5356f86d --- /dev/null +++ b/include/lldb/Symbol/TaggedASTType.h @@ -0,0 +1,61 @@ +//===-- TaggedASTType.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_TaggedASTType_h_ +#define liblldb_TaggedASTType_h_ + +#include "lldb/Symbol/ClangASTType.h" + +namespace lldb_private +{ + +// For cases in which there are multiple classes of types that are not +// interchangeable, to allow static type checking. +template <unsigned int C> class TaggedASTType : public ClangASTType +{ +public: + TaggedASTType (const ClangASTType &clang_type) : + ClangASTType(clang_type) + { + } + + TaggedASTType (lldb::clang_type_t type, clang::ASTContext *ast_context) : + ClangASTType(ast_context, type) + { + } + + TaggedASTType (const TaggedASTType<C> &tw) : + ClangASTType(tw) + { + } + + TaggedASTType () : + ClangASTType() + { + } + + virtual + ~TaggedASTType() + { + } + + TaggedASTType<C> &operator= (const TaggedASTType<C> &tw) + { + ClangASTType::operator= (tw); + return *this; + } +}; + +// Commonly-used tagged types, so code using them is interoperable +typedef TaggedASTType<0> TypeFromParser; +typedef TaggedASTType<1> TypeFromUser; + +} + +#endif diff --git a/include/lldb/Symbol/Type.h b/include/lldb/Symbol/Type.h new file mode 100644 index 000000000000..50b22fe96b9d --- /dev/null +++ b/include/lldb/Symbol/Type.h @@ -0,0 +1,596 @@ +//===-- Type.h --------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Type_h_ +#define liblldb_Type_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/ConstString.h" +#include "lldb/Core/UserID.h" +#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/Declaration.h" + +#include <set> + +namespace lldb_private { + +class SymbolFileType : + public std::enable_shared_from_this<SymbolFileType>, + public UserID + { + public: + SymbolFileType (SymbolFile &symbol_file, lldb::user_id_t uid) : + UserID (uid), + m_symbol_file (symbol_file) + { + } + + ~SymbolFileType () + { + } + + Type * + operator->() + { + return GetType (); + } + + Type * + GetType (); + + protected: + SymbolFile &m_symbol_file; + lldb::TypeSP m_type_sp; + }; + +class Type : + public std::enable_shared_from_this<Type>, + public UserID +{ +public: + typedef enum EncodingDataTypeTag + { + eEncodingInvalid, + eEncodingIsUID, ///< This type is the type whose UID is m_encoding_uid + eEncodingIsConstUID, ///< This type is the type whose UID is m_encoding_uid with the const qualifier added + eEncodingIsRestrictUID, ///< This type is the type whose UID is m_encoding_uid with the restrict qualifier added + eEncodingIsVolatileUID, ///< This type is the type whose UID is m_encoding_uid with the volatile qualifier added + eEncodingIsTypedefUID, ///< This type is pointer to a type whose UID is m_encoding_uid + eEncodingIsPointerUID, ///< This type is pointer to a type whose UID is m_encoding_uid + eEncodingIsLValueReferenceUID, ///< This type is L value reference to a type whose UID is m_encoding_uid + eEncodingIsRValueReferenceUID, ///< This type is R value reference to a type whose UID is m_encoding_uid + eEncodingIsSyntheticUID + } EncodingDataType; + + typedef enum ResolveStateTag + { + eResolveStateUnresolved = 0, + eResolveStateForward = 1, + eResolveStateLayout = 2, + eResolveStateFull = 3 + } ResolveState; + + Type (lldb::user_id_t uid, + SymbolFile* symbol_file, + const ConstString &name, + uint64_t byte_size, + SymbolContextScope *context, + lldb::user_id_t encoding_uid, + EncodingDataType encoding_uid_type, + const Declaration& decl, + const ClangASTType &clang_qual_type, + ResolveState clang_type_resolve_state); + + // This makes an invalid type. Used for functions that return a Type when they + // get an error. + Type(); + + Type (const Type &rhs); + + const Type& + operator= (const Type& rhs); + + void + Dump(Stream *s, bool show_context); + + void + DumpTypeName(Stream *s); + + + void + GetDescription (Stream *s, lldb::DescriptionLevel level, bool show_name); + + SymbolFile * + GetSymbolFile() + { + return m_symbol_file; + } + const SymbolFile * + GetSymbolFile() const + { + return m_symbol_file; + } + + TypeList* + GetTypeList(); + + const ConstString& + GetName(); + + uint64_t + GetByteSize(); + + uint32_t + GetNumChildren (bool omit_empty_base_classes); + + bool + IsAggregateType (); + + bool + IsValidType () + { + return m_encoding_uid_type != eEncodingInvalid; + } + + bool + IsTypedef () + { + return m_encoding_uid_type == eEncodingIsTypedefUID; + } + + lldb::TypeSP + GetTypedefType(); + + const ConstString & + GetName () const + { + return m_name; + } + + ConstString + GetQualifiedName (); + + void + DumpValue(ExecutionContext *exe_ctx, + Stream *s, + const DataExtractor &data, + uint32_t data_offset, + bool show_type, + bool show_summary, + bool verbose, + lldb::Format format = lldb::eFormatDefault); + + bool + DumpValueInMemory(ExecutionContext *exe_ctx, + Stream *s, + lldb::addr_t address, + AddressType address_type, + bool show_types, + bool show_summary, + bool verbose); + + bool + ReadFromMemory (ExecutionContext *exe_ctx, + lldb::addr_t address, + AddressType address_type, + DataExtractor &data); + + bool + WriteToMemory (ExecutionContext *exe_ctx, + lldb::addr_t address, + AddressType address_type, + DataExtractor &data); + + bool + GetIsDeclaration() const; + + void + SetIsDeclaration(bool b); + + bool + GetIsExternal() const; + + void + SetIsExternal(bool b); + + lldb::Format + GetFormat (); + + lldb::Encoding + GetEncoding (uint64_t &count); + + SymbolContextScope * + GetSymbolContextScope() + { + return m_context; + } + const SymbolContextScope * + GetSymbolContextScope() const + { + return m_context; + } + void + SetSymbolContextScope(SymbolContextScope *context) + { + m_context = context; + } + + const lldb_private::Declaration & + GetDeclaration () const; + + // Get the clang type, and resolve definitions for any + // class/struct/union/enum types completely. + ClangASTType + GetClangFullType (); + + // Get the clang type, and resolve definitions enough so that the type could + // have layout performed. This allows ptrs and refs to class/struct/union/enum + // types remain forward declarations. + ClangASTType + GetClangLayoutType (); + + // Get the clang type and leave class/struct/union/enum types as forward + // declarations if they haven't already been fully defined. + ClangASTType + GetClangForwardType (); + + ClangASTContext & + GetClangASTContext (); + + static int + Compare(const Type &a, const Type &b); + + // From a fully qualified typename, split the type into the type basename + // and the remaining type scope (namespaces/classes). + static bool + GetTypeScopeAndBasename (const char* &name_cstr, + std::string &scope, + std::string &basename, + lldb::TypeClass &type_class); + void + SetEncodingType (Type *encoding_type) + { + m_encoding_type = encoding_type; + } + + uint32_t + GetEncodingMask (); + + ClangASTType + CreateClangTypedefType (Type *typedef_type, Type *base_type); + + bool + IsRealObjCClass(); + + bool + IsCompleteObjCClass() + { + return m_flags.is_complete_objc_class; + } + + void + SetIsCompleteObjCClass(bool is_complete_objc_class) + { + m_flags.is_complete_objc_class = is_complete_objc_class; + } + +protected: + ConstString m_name; + SymbolFile *m_symbol_file; + SymbolContextScope *m_context; // The symbol context in which this type is defined + Type *m_encoding_type; + lldb::user_id_t m_encoding_uid; + EncodingDataType m_encoding_uid_type; + uint64_t m_byte_size; + Declaration m_decl; + ClangASTType m_clang_type; + + struct Flags { + ResolveState clang_type_resolve_state : 2; + bool is_complete_objc_class : 1; + } m_flags; + + Type * + GetEncodingType (); + + bool + ResolveClangType (ResolveState clang_type_resolve_state); +}; + + +/// +/// Sometimes you can find the name of the type corresponding to an object, but we don't have debug +/// information for it. If that is the case, you can return one of these objects, and then if it +/// has a full type, you can use that, but if not at least you can print the name for informational +/// purposes. +/// + +class TypeAndOrName +{ +public: + TypeAndOrName (); + TypeAndOrName (lldb::TypeSP &type_sp); + TypeAndOrName (const char *type_str); + TypeAndOrName (const TypeAndOrName &rhs); + TypeAndOrName (ConstString &type_const_string); + + TypeAndOrName & + operator= (const TypeAndOrName &rhs); + + bool + operator==(const TypeAndOrName &other) const; + + bool + operator!=(const TypeAndOrName &other) const; + + ConstString GetName () const; + + lldb::TypeSP + GetTypeSP () const + { + return m_type_sp; + } + + void + SetName (const ConstString &type_name); + + void + SetName (const char *type_name_cstr); + + void + SetTypeSP (lldb::TypeSP type_sp); + + bool + IsEmpty (); + + bool + HasName (); + + bool + HasTypeSP (); + + void + Clear (); + + operator + bool () + { + return !IsEmpty(); + } + +private: + lldb::TypeSP m_type_sp; + ConstString m_type_name; +}; + +// the two classes here are used by the public API as a backend to +// the SBType and SBTypeList classes + +class TypeImpl +{ +public: + + TypeImpl() : + m_clang_ast_type(), + m_type_sp() + { + } + + TypeImpl(const TypeImpl& rhs) : + m_clang_ast_type(rhs.m_clang_ast_type), + m_type_sp(rhs.m_type_sp) + { + } + + TypeImpl(const lldb_private::ClangASTType& type); + + TypeImpl(const lldb::TypeSP& type); + + TypeImpl& + operator = (const TypeImpl& rhs); + + bool + operator == (const TypeImpl& rhs) + { + return m_clang_ast_type == rhs.m_clang_ast_type && m_type_sp.get() == rhs.m_type_sp.get(); + } + + bool + operator != (const TypeImpl& rhs) + { + return m_clang_ast_type != rhs.m_clang_ast_type || m_type_sp.get() != rhs.m_type_sp.get(); + } + + bool + IsValid() + { + return m_type_sp.get() != NULL || m_clang_ast_type.IsValid(); + } + + const lldb_private::ClangASTType & + GetClangASTType() const + { + return m_clang_ast_type; + } + + clang::ASTContext* + GetASTContext(); + + lldb::clang_type_t + GetOpaqueQualType(); + + lldb::TypeSP + GetTypeSP () + { + return m_type_sp; + } + + ConstString + GetName (); + + bool + GetDescription (lldb_private::Stream &strm, + lldb::DescriptionLevel description_level); + + void + SetType (const lldb::TypeSP &type_sp); + +private: + ClangASTType m_clang_ast_type; + lldb::TypeSP m_type_sp; +}; + +class TypeListImpl +{ +public: + TypeListImpl() : + m_content() + { + } + + void + Append (const lldb::TypeImplSP& type) + { + m_content.push_back(type); + } + + class AppendVisitor + { + public: + AppendVisitor(TypeListImpl &type_list) : + m_type_list(type_list) + { + } + + void + operator() (const lldb::TypeImplSP& type) + { + m_type_list.Append(type); + } + + private: + TypeListImpl &m_type_list; + }; + + void + Append (const lldb_private::TypeList &type_list); + + lldb::TypeImplSP + GetTypeAtIndex(size_t idx) + { + lldb::TypeImplSP type_sp; + if (idx < GetSize()) + type_sp = m_content[idx]; + return type_sp; + } + + size_t + GetSize() + { + return m_content.size(); + } + +private: + std::vector<lldb::TypeImplSP> m_content; +}; + +class TypeMemberImpl +{ +public: + TypeMemberImpl () : + m_type_impl_sp (), + m_bit_offset (0), + m_name (), + m_bitfield_bit_size (0), + m_is_bitfield (false) + + { + } + + TypeMemberImpl (const lldb::TypeImplSP &type_impl_sp, + uint64_t bit_offset, + const ConstString &name, + uint32_t bitfield_bit_size = 0, + bool is_bitfield = false) : + m_type_impl_sp (type_impl_sp), + m_bit_offset (bit_offset), + m_name (name), + m_bitfield_bit_size (bitfield_bit_size), + m_is_bitfield (is_bitfield) + { + } + + TypeMemberImpl (const lldb::TypeImplSP &type_impl_sp, + uint64_t bit_offset): + m_type_impl_sp (type_impl_sp), + m_bit_offset (bit_offset), + m_name (), + m_bitfield_bit_size (0), + m_is_bitfield (false) + { + if (m_type_impl_sp) + m_name = m_type_impl_sp->GetName(); + } + + const lldb::TypeImplSP & + GetTypeImpl () + { + return m_type_impl_sp; + } + + const ConstString & + GetName () const + { + return m_name; + } + + uint64_t + GetBitOffset () const + { + return m_bit_offset; + } + + uint32_t + GetBitfieldBitSize () const + { + return m_bitfield_bit_size; + } + + void + SetBitfieldBitSize (uint32_t bitfield_bit_size) + { + m_bitfield_bit_size = bitfield_bit_size; + } + + bool + GetIsBitfield () const + { + return m_is_bitfield; + } + + void + SetIsBitfield (bool is_bitfield) + { + m_is_bitfield = is_bitfield; + } + +protected: + lldb::TypeImplSP m_type_impl_sp; + uint64_t m_bit_offset; + ConstString m_name; + uint32_t m_bitfield_bit_size; // Bit size for bitfield members only + bool m_is_bitfield; +}; + + +} // namespace lldb_private + +#endif // liblldb_Type_h_ + diff --git a/include/lldb/Symbol/TypeList.h b/include/lldb/Symbol/TypeList.h new file mode 100644 index 000000000000..9c74db6bf1f4 --- /dev/null +++ b/include/lldb/Symbol/TypeList.h @@ -0,0 +1,88 @@ +//===-- TypeList.h ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_TypeList_h_ +#define liblldb_TypeList_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Symbol/Type.h" +#include <map> + +namespace lldb_private { + +class TypeList +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + TypeList(); + + virtual + ~TypeList(); + + void + Clear(); + + void + Dump(Stream *s, bool show_context); + +// lldb::TypeSP +// FindType(lldb::user_id_t uid); + + TypeList + FindTypes(const ConstString &name); + + void + Insert (const lldb::TypeSP& type); + + bool + InsertUnique (const lldb::TypeSP& type); + + uint32_t + GetSize() const; + + lldb::TypeSP + GetTypeAtIndex(uint32_t idx); + + void + ForEach (std::function <bool(const lldb::TypeSP &type_sp)> const &callback) const; + + void + ForEach (std::function <bool(lldb::TypeSP &type_sp)> const &callback); + + bool + RemoveTypeWithUID (lldb::user_id_t uid); + + void + RemoveMismatchedTypes (const char *qualified_typename, + bool exact_match); + + void + RemoveMismatchedTypes (const std::string &type_scope, + const std::string &type_basename, + lldb::TypeClass type_class, + bool exact_match); + + void + RemoveMismatchedTypes (lldb::TypeClass type_class); + +private: + typedef std::multimap<lldb::user_id_t, lldb::TypeSP> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + collection m_types; + + DISALLOW_COPY_AND_ASSIGN (TypeList); +}; + +} // namespace lldb_private + +#endif // liblldb_TypeList_h_ diff --git a/include/lldb/Symbol/TypeVendor.h b/include/lldb/Symbol/TypeVendor.h new file mode 100644 index 000000000000..559b21eeb95a --- /dev/null +++ b/include/lldb/Symbol/TypeVendor.h @@ -0,0 +1,61 @@ +//===-- TypeVendor.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_TypeVendor_h_ +#define liblldb_TypeVendor_h_ + +#include "lldb/Core/ClangForward.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +// The type vendor class is intended as a generic interface to search +// for Clang types that are not necessarily backed by a specific symbol +// file. +//---------------------------------------------------------------------- +class TypeVendor +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + TypeVendor() + { + } + + virtual + ~TypeVendor() + { + } + + virtual uint32_t + FindTypes (const ConstString &name, + bool append, + uint32_t max_matches, + std::vector <ClangASTType> &types) = 0; + + virtual clang::ASTContext * + GetClangASTContext () = 0; + +protected: + //------------------------------------------------------------------ + // Classes that inherit from TypeVendor can see and modify these + //------------------------------------------------------------------ + +private: + //------------------------------------------------------------------ + // For TypeVendor only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (TypeVendor); +}; + + +} // namespace lldb_private + +#endif diff --git a/include/lldb/Symbol/UnwindPlan.h b/include/lldb/Symbol/UnwindPlan.h new file mode 100644 index 000000000000..6fc5ce042357 --- /dev/null +++ b/include/lldb/Symbol/UnwindPlan.h @@ -0,0 +1,499 @@ +#ifndef liblldb_UnwindPlan_h +#define liblldb_UnwindPlan_h + +#include "lldb/lldb-private.h" +#include "lldb/Core/AddressRange.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/ConstString.h" + +#include <map> +#include <vector> + +namespace lldb_private { + +// The UnwindPlan object specifies how to unwind out of a function - where +// this function saves the caller's register values before modifying them +// (for non-volatile aka saved registers) and how to find this frame's +// Canonical Frame Address (CFA). + +// Most commonly, registers are saved on the stack, offset some bytes from +// the Canonical Frame Address, or CFA, which is the starting address of +// this function's stack frame (the CFA is same as the eh_frame's CFA, +// whatever that may be on a given architecture). +// The CFA address for the stack frame does not change during +// the lifetime of the function. + +// Internally, the UnwindPlan is structured as a vector of register locations +// organized by code address in the function, showing which registers have been +// saved at that point and where they are saved. +// It can be thought of as the expanded table form of the DWARF CFI +// encoded information. + +// Other unwind information sources will be converted into UnwindPlans before +// being added to a FuncUnwinders object. The unwind source may be +// an eh_frame FDE, a DWARF debug_frame FDE, or assembly language based +// prologue analysis. +// The UnwindPlan is the canonical form of this information that the unwinder +// code will use when walking the stack. + +class UnwindPlan { +public: + + class Row { + public: + class RegisterLocation + { + public: + + enum RestoreType + { + unspecified, // not specified, we may be able to assume this + // is the same register. gcc doesn't specify all + // initial values so we really don't know... + undefined, // reg is not available, e.g. volatile reg + same, // reg is unchanged + atCFAPlusOffset, // reg = deref(CFA + offset) + isCFAPlusOffset, // reg = CFA + offset + inOtherRegister, // reg = other reg + atDWARFExpression, // reg = deref(eval(dwarf_expr)) + isDWARFExpression // reg = eval(dwarf_expr) + }; + + RegisterLocation() : + m_type(unspecified), + m_location() + { + } + + bool + operator == (const RegisterLocation& rhs) const; + + bool + operator != (const RegisterLocation &rhs) const + { + return !(*this == rhs); + } + + void + SetUnspecified() + { + m_type = unspecified; + } + + void + SetUndefined() + { + m_type = undefined; + } + + void + SetSame() + { + m_type = same; + } + + bool + IsSame () const + { + return m_type == same; + } + + bool + IsUnspecified () const + { + return m_type == unspecified; + } + + bool + IsCFAPlusOffset () const + { + return m_type == isCFAPlusOffset; + } + + bool + IsAtCFAPlusOffset () const + { + return m_type == atCFAPlusOffset; + } + + bool + IsInOtherRegister () const + { + return m_type == inOtherRegister; + } + + bool + IsAtDWARFExpression () const + { + return m_type == atDWARFExpression; + } + + bool + IsDWARFExpression () const + { + return m_type == isDWARFExpression; + } + + void + SetAtCFAPlusOffset (int32_t offset) + { + m_type = atCFAPlusOffset; + m_location.offset = offset; + } + + void + SetIsCFAPlusOffset (int32_t offset) + { + m_type = isCFAPlusOffset; + m_location.offset = offset; + } + + void + SetInRegister (uint32_t reg_num) + { + m_type = inOtherRegister; + m_location.reg_num = reg_num; + } + + uint32_t + GetRegisterNumber () const + { + if (m_type == inOtherRegister) + return m_location.reg_num; + return LLDB_INVALID_REGNUM; + } + + RestoreType + GetLocationType () const + { + return m_type; + } + + int32_t + GetOffset () const + { + if (m_type == atCFAPlusOffset || m_type == isCFAPlusOffset) + return m_location.offset; + return 0; + } + + void + GetDWARFExpr (const uint8_t **opcodes, uint16_t& len) const + { + if (m_type == atDWARFExpression || m_type == isDWARFExpression) + { + *opcodes = m_location.expr.opcodes; + len = m_location.expr.length; + } + else + { + *opcodes = NULL; + len = 0; + } + } + + void + SetAtDWARFExpression (const uint8_t *opcodes, uint32_t len); + + void + SetIsDWARFExpression (const uint8_t *opcodes, uint32_t len); + + const uint8_t * + GetDWARFExpressionBytes () + { + if (m_type == atDWARFExpression || m_type == isDWARFExpression) + return m_location.expr.opcodes; + return NULL; + } + + int + GetDWARFExpressionLength () + { + if (m_type == atDWARFExpression || m_type == isDWARFExpression) + return m_location.expr.length; + return 0; + } + + void + Dump (Stream &s, + const UnwindPlan* unwind_plan, + const UnwindPlan::Row* row, + Thread* thread, + bool verbose) const; + + private: + RestoreType m_type; // How do we locate this register? + union + { + // For m_type == atCFAPlusOffset or m_type == isCFAPlusOffset + int32_t offset; + // For m_type == inOtherRegister + uint32_t reg_num; // The register number + // For m_type == atDWARFExpression or m_type == isDWARFExpression + struct { + const uint8_t *opcodes; + uint16_t length; + } expr; + } m_location; + }; + + public: + Row (); + + Row (const UnwindPlan::Row& rhs) : + m_offset (rhs.m_offset), + m_cfa_reg_num (rhs.m_cfa_reg_num), + m_cfa_offset (rhs.m_cfa_offset), + m_register_locations (rhs.m_register_locations) + { + } + + bool + operator == (const Row &rhs) const; + + bool + GetRegisterInfo (uint32_t reg_num, RegisterLocation& register_location) const; + + void + SetRegisterInfo (uint32_t reg_num, const RegisterLocation register_location); + + lldb::addr_t + GetOffset() const + { + return m_offset; + } + + void + SetOffset(lldb::addr_t offset) + { + m_offset = offset; + } + + void + SlideOffset(lldb::addr_t offset) + { + m_offset += offset; + } + + uint32_t + GetCFARegister () const + { + return m_cfa_reg_num; + } + + bool + SetRegisterLocationToAtCFAPlusOffset (uint32_t reg_num, + int32_t offset, + bool can_replace); + + bool + SetRegisterLocationToIsCFAPlusOffset (uint32_t reg_num, + int32_t offset, + bool can_replace); + + bool + SetRegisterLocationToUndefined (uint32_t reg_num, + bool can_replace, + bool can_replace_only_if_unspecified); + + bool + SetRegisterLocationToUnspecified (uint32_t reg_num, + bool can_replace); + + bool + SetRegisterLocationToRegister (uint32_t reg_num, + uint32_t other_reg_num, + bool can_replace); + + bool + SetRegisterLocationToSame (uint32_t reg_num, + bool must_replace); + + + + void + SetCFARegister (uint32_t reg_num); + + int32_t + GetCFAOffset () const + { + return m_cfa_offset; + } + + void + SetCFAOffset (int32_t offset) + { + m_cfa_offset = offset; + } + + void + Clear (); + + void + Dump (Stream& s, const UnwindPlan* unwind_plan, Thread* thread, lldb::addr_t base_addr) const; + + protected: + typedef std::map<uint32_t, RegisterLocation> collection; + lldb::addr_t m_offset; // Offset into the function for this row + uint32_t m_cfa_reg_num; // The Call Frame Address register number + int32_t m_cfa_offset; // The offset from the CFA for this row + collection m_register_locations; + }; // class Row + +public: + + typedef std::shared_ptr<Row> RowSP; + + UnwindPlan (lldb::RegisterKind reg_kind) : + m_row_list (), + m_plan_valid_address_range (), + m_register_kind (reg_kind), + m_return_addr_register (LLDB_INVALID_REGNUM), + m_source_name (), + m_plan_is_sourced_from_compiler (eLazyBoolCalculate), + m_plan_is_valid_at_all_instruction_locations (eLazyBoolCalculate) + { + } + + ~UnwindPlan () + { + } + + void + Dump (Stream& s, Thread* thread, lldb::addr_t base_addr) const; + + void + AppendRow (const RowSP& row_sp); + + // Returns a pointer to the best row for the given offset into the function's instructions. + // If offset is -1 it indicates that the function start is unknown - the final row in the UnwindPlan is returned. + // In practice, the UnwindPlan for a function with no known start address will be the architectural default + // UnwindPlan which will only have one row. + UnwindPlan::RowSP + GetRowForFunctionOffset (int offset) const; + + lldb::RegisterKind + GetRegisterKind () const + { + return m_register_kind; + } + + void + SetRegisterKind (lldb::RegisterKind kind) + { + m_register_kind = kind; + } + + void + SetReturnAddressRegister (uint32_t regnum) + { + m_return_addr_register = regnum; + } + + uint32_t + GetReturnAddressRegister (void) + { + return m_return_addr_register; + } + + uint32_t + GetInitialCFARegister () const + { + if (m_row_list.empty()) + return LLDB_INVALID_REGNUM; + return m_row_list.front()->GetCFARegister(); + } + + // This UnwindPlan may not be valid at every address of the function span. + // For instance, a FastUnwindPlan will not be valid at the prologue setup + // instructions - only in the body of the function. + void + SetPlanValidAddressRange (const AddressRange& range); + + const AddressRange & + GetAddressRange () const + { + return m_plan_valid_address_range; + } + + bool + PlanValidAtAddress (Address addr); + + bool + IsValidRowIndex (uint32_t idx) const; + + const UnwindPlan::RowSP + GetRowAtIndex (uint32_t idx) const; + + const UnwindPlan::RowSP + GetLastRow () const; + + lldb_private::ConstString + GetSourceName () const; + + void + SetSourceName (const char *); + + // Was this UnwindPlan emitted by a compiler? + lldb_private::LazyBool + GetSourcedFromCompiler () const + { + return m_plan_is_sourced_from_compiler; + } + + // Was this UnwindPlan emitted by a compiler? + void + SetSourcedFromCompiler (lldb_private::LazyBool from_compiler) + { + m_plan_is_sourced_from_compiler = from_compiler; + } + + // Is this UnwindPlan valid at all instructions? If not, then it is assumed valid at call sites, + // e.g. for exception handling. + lldb_private::LazyBool + GetUnwindPlanValidAtAllInstructions () const + { + return m_plan_is_valid_at_all_instruction_locations; + } + + // Is this UnwindPlan valid at all instructions? If not, then it is assumed valid at call sites, + // e.g. for exception handling. + void + SetUnwindPlanValidAtAllInstructions (lldb_private::LazyBool valid_at_all_insn) + { + m_plan_is_valid_at_all_instruction_locations = valid_at_all_insn; + } + + int + GetRowCount () const; + + void + Clear() + { + m_row_list.clear(); + m_plan_valid_address_range.Clear(); + m_register_kind = lldb::eRegisterKindDWARF; + m_source_name.Clear(); + } + + const RegisterInfo * + GetRegisterInfo (Thread* thread, uint32_t reg_num) const; + +private: + + + typedef std::vector<RowSP> collection; + collection m_row_list; + AddressRange m_plan_valid_address_range; + lldb::RegisterKind m_register_kind; // The RegisterKind these register numbers are in terms of - will need to be + // translated to lldb native reg nums at unwind time + uint32_t m_return_addr_register; // The register that has the return address for the caller frame + // e.g. the lr on arm + lldb_private::ConstString m_source_name; // for logging, where this UnwindPlan originated from + lldb_private::LazyBool m_plan_is_sourced_from_compiler; + lldb_private::LazyBool m_plan_is_valid_at_all_instruction_locations; +}; // class UnwindPlan + +} // namespace lldb_private + +#endif //liblldb_UnwindPlan_h diff --git a/include/lldb/Symbol/UnwindTable.h b/include/lldb/Symbol/UnwindTable.h new file mode 100644 index 000000000000..cefb91eb371a --- /dev/null +++ b/include/lldb/Symbol/UnwindTable.h @@ -0,0 +1,69 @@ +//===-- Symtab.h ------------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +#ifndef liblldb_UnwindTable_h +#define liblldb_UnwindTable_h + +#include <map> + +#include "lldb/lldb-private.h" + +namespace lldb_private { + +// A class which holds all the FuncUnwinders objects for a given ObjectFile. +// The UnwindTable is populated with FuncUnwinders objects lazily during +// the debug session. + +class UnwindTable +{ +public: + UnwindTable(ObjectFile& objfile); + ~UnwindTable(); + + lldb_private::DWARFCallFrameInfo * + GetEHFrameInfo (); + + lldb::FuncUnwindersSP + GetFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc); + +// Normally when we create a new FuncUnwinders object we track it in this UnwindTable so it can +// be reused later. But for the target modules show-unwind we want to create brand new +// UnwindPlans for the function of interest - so ignore any existing FuncUnwinders for that +// function and don't add this new one to our UnwindTable. +// This FuncUnwinders object does have a reference to the UnwindTable but the lifetime of this +// uncached FuncUnwinders is expected to be short so in practice this will not be a problem. + lldb::FuncUnwindersSP + GetUncachedFuncUnwindersContainingAddress (const Address& addr, SymbolContext &sc); + +private: + void + Dump (Stream &s); + + void Initialize (); + + typedef std::map<lldb::addr_t, lldb::FuncUnwindersSP> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + ObjectFile& m_object_file; + collection m_unwinds; + + bool m_initialized; // delay some initialization until ObjectFile is set up + + UnwindAssembly* m_assembly_profiler; + + DWARFCallFrameInfo* m_eh_frame; + + DISALLOW_COPY_AND_ASSIGN (UnwindTable); +}; + +} // namespace lldb_private + +#endif // liblldb_UnwindTable_h diff --git a/include/lldb/Symbol/Variable.h b/include/lldb/Symbol/Variable.h new file mode 100644 index 000000000000..07295d090ee6 --- /dev/null +++ b/include/lldb/Symbol/Variable.h @@ -0,0 +1,184 @@ +//===-- Variable.h ----------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_Variable_h_ +#define liblldb_Variable_h_ + +#include <vector> + +#include "lldb/lldb-private.h" +#include "lldb/lldb-enumerations.h" +#include "lldb/Core/Mangled.h" +#include "lldb/Core/UserID.h" +#include "lldb/Expression/DWARFExpression.h" +#include "lldb/Symbol/Declaration.h" + +namespace lldb_private { + +class Variable : public UserID +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ + Variable (lldb::user_id_t uid, + const char *name, + const char *mangled, // The mangled variable name for variables in namespaces + const lldb::SymbolFileTypeSP &symfile_type_sp, + lldb::ValueType scope, + SymbolContextScope *owner_scope, + Declaration* decl, + const DWARFExpression& location, + bool external, + bool artificial); + + virtual + ~Variable(); + + void + Dump(Stream *s, bool show_context) const; + + bool + DumpDeclaration (Stream *s, + bool show_fullpaths, + bool show_module); + + const Declaration& + GetDeclaration() const + { + return m_declaration; + } + + const ConstString& + GetName() const; + + SymbolContextScope * + GetSymbolContextScope() const + { + return m_owner_scope; + } + + // Since a variable can have a basename "i" and also a mangled + // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name + // "(anonymous namespace)::i", this function will allow a generic match + // function that can be called by commands and expression parsers to make + // sure we match anything we come across. + bool + NameMatches (const ConstString &name) const + { + if (m_name == name) + return true; + return m_mangled.NameMatches (name); + } + + bool + NameMatches (const RegularExpression& regex) const; + + Type * + GetType(); + + lldb::ValueType + GetScope() const + { + return m_scope; + } + + bool + IsExternal() const + { + return m_external; + } + + bool + IsArtificial() const + { + return m_artificial; + } + + DWARFExpression & + LocationExpression() + { + return m_location; + } + + const DWARFExpression & + LocationExpression() const + { + return m_location; + } + + bool + DumpLocationForAddress (Stream *s, + const Address &address); + + size_t + MemorySize() const; + + void + CalculateSymbolContext (SymbolContext *sc); + + bool + IsInScope (StackFrame *frame); + + bool + LocationIsValidForFrame (StackFrame *frame); + + bool + LocationIsValidForAddress (const Address &address); + + bool + GetLocationIsConstantValueData () const + { + return m_loc_is_const_data; + } + + void + SetLocationIsConstantValueData (bool b) + { + m_loc_is_const_data = b; + } + + typedef size_t (*GetVariableCallback) (void *baton, + const char *name, + VariableList &var_list); + + + static Error + GetValuesForVariableExpressionPath (const char *variable_expr_path, + ExecutionContextScope *scope, + GetVariableCallback callback, + void *baton, + VariableList &variable_list, + ValueObjectList &valobj_list); + + static size_t + AutoComplete (const ExecutionContext &exe_ctx, + const char *name, + StringList &matches, + bool &word_complete); + +protected: + ConstString m_name; // The basename of the variable (no namespaces) + Mangled m_mangled; // The mangled name of the variable + lldb::SymbolFileTypeSP m_symfile_type_sp; // The type pointer of the variable (int, struct, class, etc) + lldb::ValueType m_scope; // global, parameter, local + SymbolContextScope *m_owner_scope; // The symbol file scope that this variable was defined in + Declaration m_declaration; // Declaration location for this item. + DWARFExpression m_location; // The location of this variable that can be fed to DWARFExpression::Evaluate() + uint8_t m_external:1, // Visible outside the containing compile unit? + m_artificial:1, // Non-zero if the variable is not explicitly declared in source + m_loc_is_const_data:1; // The m_location expression contains the constant variable value data, not a DWARF location +private: + Variable(const Variable& rhs); + Variable& operator=(const Variable& rhs); +}; + +} // namespace lldb_private + +#endif // liblldb_Variable_h_ diff --git a/include/lldb/Symbol/VariableList.h b/include/lldb/Symbol/VariableList.h new file mode 100644 index 000000000000..2ce6146f4627 --- /dev/null +++ b/include/lldb/Symbol/VariableList.h @@ -0,0 +1,95 @@ +//===-- VariableList.h ------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_VariableList_h_ +#define liblldb_VariableList_h_ + +#include "lldb/lldb-private.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Symbol/Variable.h" + +namespace lldb_private { + +class VariableList +{ +public: + //------------------------------------------------------------------ + // Constructors and Destructors + //------------------------------------------------------------------ +// VariableList(const SymbolContext &symbol_context); + VariableList(); + virtual ~VariableList(); + + void + AddVariable (const lldb::VariableSP &var_sp); + + bool + AddVariableIfUnique (const lldb::VariableSP &var_sp); + + void + AddVariables (VariableList *variable_list); + + void + Clear(); + + void + Dump(Stream *s, bool show_context) const; + + lldb::VariableSP + GetVariableAtIndex(size_t idx) const; + + lldb::VariableSP + RemoveVariableAtIndex (size_t idx); + + lldb::VariableSP + FindVariable (const ConstString& name); + + uint32_t + FindVariableIndex (const lldb::VariableSP &var_sp); + + // Returns the actual number of unique variables that were added to the + // list. "total_matches" will get updated with the actualy number of + // matches that were found regardless of whether they were unique or not + // to allow for error conditions when nothing is found, versus conditions + // where any varaibles that match "regex" were already in "var_list". + size_t + AppendVariablesIfUnique (const RegularExpression& regex, + VariableList &var_list, + size_t& total_matches); + + size_t + AppendVariablesWithScope (lldb::ValueType type, + VariableList &var_list, + bool if_unique = true); + + uint32_t + FindIndexForVariable (Variable* variable); + + size_t + MemorySize() const; + + size_t + GetSize() const; + +protected: + typedef std::vector<lldb::VariableSP> collection; + typedef collection::iterator iterator; + typedef collection::const_iterator const_iterator; + + collection m_variables; +private: + //------------------------------------------------------------------ + // For VariableList only + //------------------------------------------------------------------ + DISALLOW_COPY_AND_ASSIGN (VariableList); +}; + +} // namespace lldb_private + +#endif // liblldb_VariableList_h_ diff --git a/include/lldb/Symbol/VerifyDecl.h b/include/lldb/Symbol/VerifyDecl.h new file mode 100644 index 000000000000..228e635652e6 --- /dev/null +++ b/include/lldb/Symbol/VerifyDecl.h @@ -0,0 +1,20 @@ +//===-- VerifyDecl.h --------------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_VariableList_h_ +#define lldb_VariableList_h_ + +#include "lldb/Core/ClangForward.h" + +namespace lldb_private +{ + void VerifyDecl (clang::Decl *decl); +} + +#endif |