diff options
Diffstat (limited to 'include/lldb/Expression/ClangExpressionDeclMap.h')
-rw-r--r-- | include/lldb/Expression/ClangExpressionDeclMap.h | 698 |
1 files changed, 698 insertions, 0 deletions
diff --git a/include/lldb/Expression/ClangExpressionDeclMap.h b/include/lldb/Expression/ClangExpressionDeclMap.h new file mode 100644 index 000000000000..b2a43e0ac75f --- /dev/null +++ b/include/lldb/Expression/ClangExpressionDeclMap.h @@ -0,0 +1,698 @@ +//===-- ClangExpressionDeclMap.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_ClangExpressionDeclMap_h_ +#define liblldb_ClangExpressionDeclMap_h_ + +// C Includes +#include <signal.h> +#include <stdint.h> + +// C++ Includes +#include <vector> + +// Other libraries and framework includes +// Project includes +#include "llvm/ADT/APInt.h" +#include "llvm/ADT/DenseMap.h" +#include "clang/AST/Decl.h" +#include "lldb/lldb-public.h" +#include "lldb/Core/ClangForward.h" +#include "lldb/Core/Value.h" +#include "lldb/Expression/ClangASTSource.h" +#include "lldb/Expression/ClangExpressionVariable.h" +#include "lldb/Expression/Materializer.h" +#include "lldb/Symbol/TaggedASTType.h" +#include "lldb/Symbol/SymbolContext.h" +#include "lldb/Target/ExecutionContext.h" + +namespace lldb_private { + +//---------------------------------------------------------------------- +/// @class ClangExpressionDeclMap ClangExpressionDeclMap.h "lldb/Expression/ClangExpressionDeclMap.h" +/// @brief Manages named entities that are defined in LLDB's debug information. +/// +/// The Clang parser uses the ClangASTSource as an interface to request named +/// entities from outside an expression. The ClangASTSource reports back, listing +/// all possible objects corresponding to a particular name. But it in turn +/// relies on ClangExpressionDeclMap, which performs several important functions. +/// +/// First, it records what variables and functions were looked up and what Decls +/// were returned for them. +/// +/// Second, it constructs a struct on behalf of IRForTarget, recording which +/// variables should be placed where and relaying this information back so that +/// IRForTarget can generate context-independent code. +/// +/// Third, it "materializes" this struct on behalf of the expression command, +/// finding the current values of each variable and placing them into the +/// struct so that it can be passed to the JITted version of the IR. +/// +/// Fourth and finally, it "dematerializes" the struct after the JITted code has +/// has executed, placing the new values back where it found the old ones. +//---------------------------------------------------------------------- +class ClangExpressionDeclMap : + public ClangASTSource +{ +public: + //------------------------------------------------------------------ + /// Constructor + /// + /// Initializes class variables. + /// + /// @param[in] keep_result_in_memory + /// If true, inhibits the normal deallocation of the memory for + /// the result persistent variable, and instead marks the variable + /// as persisting. + /// + /// @param[in] exe_ctx + /// The execution context to use when parsing. + //------------------------------------------------------------------ + ClangExpressionDeclMap (bool keep_result_in_memory, + ExecutionContext &exe_ctx); + + //------------------------------------------------------------------ + /// Destructor + //------------------------------------------------------------------ + ~ClangExpressionDeclMap (); + + //------------------------------------------------------------------ + /// Enable the state needed for parsing and IR transformation. + /// + /// @param[in] exe_ctx + /// The execution context to use when finding types for variables. + /// Also used to find a "scratch" AST context to store result types. + /// + /// @param[in] materializer + /// If non-NULL, the materializer to populate with information about + /// the variables to use + /// + /// @return + /// True if parsing is possible; false if it is unsafe to continue. + //------------------------------------------------------------------ + bool + WillParse (ExecutionContext &exe_ctx, + Materializer *materializer); + + //------------------------------------------------------------------ + /// [Used by ClangExpressionParser] For each variable that had an unknown + /// type at the beginning of parsing, determine its final type now. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + ResolveUnknownTypes(); + + //------------------------------------------------------------------ + /// Disable the state needed for parsing and IR transformation. + //------------------------------------------------------------------ + void + DidParse (); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Add a variable to the list of persistent + /// variables for the process. + /// + /// @param[in] decl + /// The Clang declaration for the persistent variable, used for + /// lookup during parsing. + /// + /// @param[in] name + /// The name of the persistent variable, usually $something. + /// + /// @param[in] type + /// The type of the variable, in the Clang parser's context. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + AddPersistentVariable (const clang::NamedDecl *decl, + const ConstString &name, + TypeFromParser type, + bool is_result, + bool is_lvalue); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Add a variable to the struct that needs to + /// be materialized each time the expression runs. + /// + /// @param[in] decl + /// The Clang declaration for the variable. + /// + /// @param[in] name + /// The name of the variable. + /// + /// @param[in] value + /// The LLVM IR value for this variable. + /// + /// @param[in] size + /// The size of the variable in bytes. + /// + /// @param[in] alignment + /// The required alignment of the variable in bytes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + AddValueToStruct (const clang::NamedDecl *decl, + const ConstString &name, + llvm::Value *value, + size_t size, + off_t alignment); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Finalize the struct, laying out the position + /// of each object in it. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + bool + DoStructLayout (); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get general information about the laid-out + /// struct after DoStructLayout() has been called. + /// + /// @param[out] num_elements + /// The number of elements in the struct. + /// + /// @param[out] size + /// The size of the struct, in bytes. + /// + /// @param[out] alignment + /// The alignment of the struct, in bytes. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetStructInfo (uint32_t &num_elements, + size_t &size, + off_t &alignment); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get specific information about one field + /// of the laid-out struct after DoStructLayout() has been called. + /// + /// @param[out] decl + /// The parsed Decl for the field, as generated by ClangASTSource + /// on ClangExpressionDeclMap's behalf. In the case of the result + /// value, this will have the name $__lldb_result even if the + /// result value ends up having the name $1. This is an + /// implementation detail of IRForTarget. + /// + /// @param[out] value + /// The IR value for the field (usually a GlobalVariable). In + /// the case of the result value, this will have the correct + /// name ($1, for instance). This is an implementation detail + /// of IRForTarget. + /// + /// @param[out] offset + /// The offset of the field from the beginning of the struct. + /// As long as the struct is aligned according to its required + /// alignment, this offset will align the field correctly. + /// + /// @param[out] name + /// The name of the field as used in materialization. + /// + /// @param[in] index + /// The index of the field about which information is requested. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetStructElement (const clang::NamedDecl *&decl, + llvm::Value *&value, + off_t &offset, + ConstString &name, + uint32_t index); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get information about a function given its + /// Decl. + /// + /// @param[in] decl + /// The parsed Decl for the Function, as generated by ClangASTSource + /// on ClangExpressionDeclMap's behalf. + /// + /// @param[out] ptr + /// The absolute address of the function in the target. + /// + /// @return + /// True if the information could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetFunctionInfo (const clang::NamedDecl *decl, + uint64_t &ptr); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get the address of a function given nothing + /// but its name. Some functions are needed but didn't get Decls made + /// during parsing -- specifically, sel_registerName is never called + /// in the generated IR but we need to call it nonetheless. + /// + /// @param[in] name + /// The name of the function. + /// + /// @param[out] ptr + /// The absolute address of the function in the target. + /// + /// @return + /// True if the address could be retrieved; false otherwise. + //------------------------------------------------------------------ + bool + GetFunctionAddress (const ConstString &name, + uint64_t &ptr); + + //------------------------------------------------------------------ + /// [Used by IRForTarget] Get the address of a symbol given nothing + /// but its name. + /// + /// @param[in] target + /// The target to find the symbol in. If not provided, + /// then the current parsing context's Target. + /// + /// @param[in] process + /// The process to use. For Objective-C symbols, the process's + /// Objective-C language runtime may be queried if the process + /// is non-NULL. + /// + /// @param[in] name + /// The name of the symbol. + /// + /// @return + /// Valid load address for the symbol + //------------------------------------------------------------------ + lldb::addr_t + GetSymbolAddress (Target &target, + Process *process, + const ConstString &name, + lldb::SymbolType symbol_type); + + lldb::addr_t + GetSymbolAddress (const ConstString &name, + lldb::SymbolType symbol_type); + + //------------------------------------------------------------------ + /// [Used by IRInterpreter] Get basic target information. + /// + /// @param[out] byte_order + /// The byte order of the target. + /// + /// @param[out] address_byte_size + /// The size of a pointer in bytes. + /// + /// @return + /// True if the information could be determined; false + /// otherwise. + //------------------------------------------------------------------ + struct TargetInfo + { + lldb::ByteOrder byte_order; + size_t address_byte_size; + + TargetInfo() : + byte_order(lldb::eByteOrderInvalid), + address_byte_size(0) + { + } + + bool IsValid() + { + return (byte_order != lldb::eByteOrderInvalid && + address_byte_size != 0); + } + }; + TargetInfo GetTargetInfo(); + + //------------------------------------------------------------------ + /// [Used by ClangASTSource] Find all entities matching a given name, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls (NameSearchContext &context); + + //------------------------------------------------------------------ + /// Find all entities matching a given name in a given module/namespace, + /// using a NameSearchContext to make Decls for them. + /// + /// @param[in] context + /// The NameSearchContext that can construct Decls for this name. + /// + /// @param[in] module + /// If non-NULL, the module to query. + /// + /// @param[in] namespace_decl + /// If valid and module is non-NULL, the parent namespace. + /// + /// @param[in] name + /// The name as a plain C string. The NameSearchContext contains + /// a DeclarationName for the name so at first the name may seem + /// redundant, but ClangExpressionDeclMap operates in RTTI land so + /// it can't access DeclarationName. + /// + /// @param[in] current_id + /// The ID for the current FindExternalVisibleDecls invocation, + /// for logging purposes. + /// + /// @return + /// True on success; false otherwise. + //------------------------------------------------------------------ + void + FindExternalVisibleDecls (NameSearchContext &context, + lldb::ModuleSP module, + ClangNamespaceDecl &namespace_decl, + unsigned int current_id); +private: + ClangExpressionVariableList m_found_entities; ///< All entities that were looked up for the parser. + ClangExpressionVariableList m_struct_members; ///< All entities that need to be placed in the struct. + bool m_keep_result_in_memory; ///< True if result persistent variables generated by this expression should stay in memory. + + //---------------------------------------------------------------------- + /// The following values should not live beyond parsing + //---------------------------------------------------------------------- + class ParserVars + { + public: + ParserVars(ClangExpressionDeclMap &decl_map) : + m_exe_ctx(), + m_sym_ctx(), + m_persistent_vars(NULL), + m_enable_lookups(false), + m_materializer(NULL), + m_decl_map(decl_map) + { + } + + Target * + GetTarget() + { + if (m_exe_ctx.GetTargetPtr()) + return m_exe_ctx.GetTargetPtr(); + else if (m_sym_ctx.target_sp) + m_sym_ctx.target_sp.get(); + return NULL; + } + + ExecutionContext m_exe_ctx; ///< The execution context to use when parsing. + SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables and types. + ClangPersistentVariables *m_persistent_vars; ///< The persistent variables for the process. + bool m_enable_lookups; ///< Set to true during parsing if we have found the first "$__lldb" name. + TargetInfo m_target_info; ///< Basic information about the target. + Materializer *m_materializer; ///< If non-NULL, the materializer to use when reporting used variables. + private: + ClangExpressionDeclMap &m_decl_map; + DISALLOW_COPY_AND_ASSIGN (ParserVars); + }; + + std::unique_ptr<ParserVars> m_parser_vars; + + //---------------------------------------------------------------------- + /// Activate parser-specific variables + //---------------------------------------------------------------------- + void + EnableParserVars() + { + if (!m_parser_vars.get()) + m_parser_vars.reset(new ParserVars(*this)); + } + + //---------------------------------------------------------------------- + /// Deallocate parser-specific variables + //---------------------------------------------------------------------- + void + DisableParserVars() + { + m_parser_vars.reset(); + } + + //---------------------------------------------------------------------- + /// The following values contain layout information for the materialized + /// struct, but are not specific to a single materialization + //---------------------------------------------------------------------- + struct StructVars { + StructVars() : + m_struct_alignment(0), + m_struct_size(0), + m_struct_laid_out(false), + m_result_name(), + m_object_pointer_type(NULL, NULL) + { + } + + off_t m_struct_alignment; ///< The alignment of the struct in bytes. + size_t m_struct_size; ///< The size of the struct in bytes. + bool m_struct_laid_out; ///< True if the struct has been laid out and the layout is valid (that is, no new fields have been added since). + ConstString m_result_name; ///< The name of the result variable ($1, for example) + TypeFromUser m_object_pointer_type; ///< The type of the "this" variable, if one exists + }; + + std::unique_ptr<StructVars> m_struct_vars; + + //---------------------------------------------------------------------- + /// Activate struct variables + //---------------------------------------------------------------------- + void + EnableStructVars() + { + if (!m_struct_vars.get()) + m_struct_vars.reset(new struct StructVars); + } + + //---------------------------------------------------------------------- + /// Deallocate struct variables + //---------------------------------------------------------------------- + void + DisableStructVars() + { + m_struct_vars.reset(); + } + + //---------------------------------------------------------------------- + /// Get this parser's ID for use in extracting parser- and JIT-specific + /// data from persistent variables. + //---------------------------------------------------------------------- + uint64_t + GetParserID() + { + return (uint64_t)this; + } + + //------------------------------------------------------------------ + /// Given a target, find a data symbol that has the given name. + /// + /// @param[in] target + /// The target to use as the basis for the search. + /// + /// @param[in] name + /// The name as a plain C string. + /// + /// @return + /// The LLDB Symbol found, or NULL if none was found. + //--------------------------------------------------------- + const Symbol * + FindGlobalDataSymbol (Target &target, + const ConstString &name); + + //------------------------------------------------------------------ + /// Given a target, find a variable that matches the given name and + /// type. + /// + /// @param[in] target + /// The target to use as a basis for finding the variable. + /// + /// @param[in] module + /// If non-NULL, the module to search. + /// + /// @param[in] name + /// The name as a plain C string. + /// + /// @param[in] namespace_decl + /// If non-NULL and module is non-NULL, the parent namespace. + /// + /// @param[in] type + /// The required type for the variable. This function may be called + /// during parsing, in which case we don't know its type; hence the + /// default. + /// + /// @return + /// The LLDB Variable found, or NULL if none was found. + //------------------------------------------------------------------ + lldb::VariableSP + FindGlobalVariable (Target &target, + lldb::ModuleSP &module, + const ConstString &name, + ClangNamespaceDecl *namespace_decl, + TypeFromUser *type = NULL); + + //------------------------------------------------------------------ + /// Get the value of a variable in a given execution context and return + /// the associated Types if needed. + /// + /// @param[in] var + /// The variable to evaluate. + /// + /// @param[out] var_location + /// The variable location value to fill in + /// + /// @param[out] found_type + /// The type of the found value, as it was found in the user process. + /// This is only useful when the variable is being inspected on behalf + /// of the parser, hence the default. + /// + /// @param[out] parser_type + /// The type of the found value, as it was copied into the parser's + /// AST context. This is only useful when the variable is being + /// inspected on behalf of the parser, hence the default. + /// + /// @param[in] decl + /// The Decl to be looked up. + /// + /// @return + /// Return true if the value was successfully filled in. + //------------------------------------------------------------------ + bool + GetVariableValue (lldb::VariableSP &var, + lldb_private::Value &var_location, + TypeFromUser *found_type = NULL, + TypeFromParser *parser_type = NULL); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given LLDB + /// Variable, and put it in the Tuple list. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] var + /// The LLDB Variable that needs a Decl. + /// + /// @param[in] valobj + /// The LLDB ValueObject for that variable. + //------------------------------------------------------------------ + void + AddOneVariable (NameSearchContext &context, + lldb::VariableSP var, + lldb::ValueObjectSP valobj, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// persistent variable, and put it in the list of found entities. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] pvar + /// The persistent variable that needs a Decl. + /// + /// @param[in] current_id + /// The ID of the current invocation of FindExternalVisibleDecls + /// for logging purposes. + //------------------------------------------------------------------ + void + AddOneVariable (NameSearchContext &context, + lldb::ClangExpressionVariableSP &pvar_sp, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given LLDB + /// symbol (treated as a variable), and put it in the list of found + /// entities. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] var + /// The LLDB Variable that needs a Decl. + //------------------------------------------------------------------ + void + AddOneGenericVariable (NameSearchContext &context, + const Symbol &symbol, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// function. (Functions are not placed in the Tuple list.) Can + /// handle both fully typed functions and generic functions. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] fun + /// The Function that needs to be created. If non-NULL, this is + /// a fully-typed function. + /// + /// @param[in] sym + /// The Symbol that corresponds to a function that needs to be + /// created with generic type (unitptr_t foo(...)). + //------------------------------------------------------------------ + void + AddOneFunction (NameSearchContext &context, + Function *fun, + Symbol *sym, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// register. + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] reg_info + /// The information corresponding to that register. + //------------------------------------------------------------------ + void + AddOneRegister (NameSearchContext &context, + const RegisterInfo *reg_info, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Use the NameSearchContext to generate a Decl for the given + /// type. (Types are not placed in the Tuple list.) + /// + /// @param[in] context + /// The NameSearchContext to use when constructing the Decl. + /// + /// @param[in] type + /// The type that needs to be created. + //------------------------------------------------------------------ + void + AddOneType (NameSearchContext &context, + TypeFromUser &type, + unsigned int current_id); + + //------------------------------------------------------------------ + /// Copy a C++ class type into the parser's AST context and add a + /// member function declaration to it for the expression. + /// + /// @param[in] type + /// The type that needs to be created. + //------------------------------------------------------------------ + + TypeFromParser + CopyClassType(TypeFromUser &type, + unsigned int current_id); +}; + +} // namespace lldb_private + +#endif // liblldb_ClangExpressionDeclMap_h_ |