667 lines · c
1//===-- ClangExpressionDeclMap.h --------------------------------*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#ifndef LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONDECLMAP_H10#define LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONDECLMAP_H11 12#include <csignal>13#include <cstdint>14 15#include <memory>16#include <vector>17 18#include "ClangASTSource.h"19#include "ClangExpressionVariable.h"20 21#include "lldb/Core/Value.h"22#include "lldb/Expression/Materializer.h"23#include "lldb/Symbol/SymbolContext.h"24#include "lldb/Symbol/TaggedASTType.h"25#include "lldb/Target/ExecutionContext.h"26#include "lldb/lldb-public.h"27#include "clang/AST/Decl.h"28#include "llvm/ADT/DenseMap.h"29 30namespace lldb_private {31 32class ClangPersistentVariables;33 34/// \class ClangExpressionDeclMap ClangExpressionDeclMap.h35/// "lldb/Expression/ClangExpressionDeclMap.h" Manages named entities that are36/// defined in LLDB's debug information.37///38/// The Clang parser uses the ClangASTSource as an interface to request named39/// entities from outside an expression. The ClangASTSource reports back,40/// listing all possible objects corresponding to a particular name. But it41/// in turn relies on ClangExpressionDeclMap, which performs several important42/// functions.43///44/// First, it records what variables and functions were looked up and what45/// Decls were returned for them.46///47/// Second, it constructs a struct on behalf of IRForTarget, recording which48/// variables should be placed where and relaying this information back so49/// that IRForTarget can generate context-independent code.50///51/// Third, it "materializes" this struct on behalf of the expression command,52/// finding the current values of each variable and placing them into the53/// struct so that it can be passed to the JITted version of the IR.54///55/// Fourth and finally, it "dematerializes" the struct after the JITted code56/// has executed, placing the new values back where it found the old ones.57class ClangExpressionDeclMap : public ClangASTSource {58public:59 /// Constructor60 ///61 /// Initializes class variables.62 ///63 /// \param[in] keep_result_in_memory64 /// If true, inhibits the normal deallocation of the memory for65 /// the result persistent variable, and instead marks the variable66 /// as persisting.67 ///68 /// \param[in] result_delegate69 /// If non-NULL, use this delegate to report result values. This70 /// allows the client ClangUserExpression to report a result.71 ///72 /// \param[in] target73 /// The target to use when parsing.74 ///75 /// \param[in] importer76 /// The ClangASTImporter to use when parsing.77 ///78 /// \param[in] ctx_obj79 /// If not empty, then expression is evaluated in context of this object.80 /// See the comment to `UserExpression::Evaluate` for details.81 ClangExpressionDeclMap(82 bool keep_result_in_memory,83 Materializer::PersistentVariableDelegate *result_delegate,84 const lldb::TargetSP &target,85 const std::shared_ptr<ClangASTImporter> &importer, ValueObject *ctx_obj);86 87 /// Destructor88 ~ClangExpressionDeclMap() override;89 90 /// Enable the state needed for parsing and IR transformation.91 ///92 /// \param[in] exe_ctx93 /// The execution context to use when finding types for variables.94 /// Also used to find a "scratch" AST context to store result types.95 ///96 /// \param[in] materializer97 /// If non-NULL, the materializer to populate with information about98 /// the variables to use99 ///100 /// \return101 /// True if parsing is possible; false if it is unsafe to continue.102 bool WillParse(ExecutionContext &exe_ctx, Materializer *materializer);103 104 void InstallCodeGenerator(clang::ASTConsumer *code_gen);105 106 void InstallDiagnosticManager(DiagnosticManager &diag_manager);107 108 /// Disable the state needed for parsing and IR transformation.109 void DidParse();110 111 /// [Used by IRForTarget] Add a variable to the list of persistent112 /// variables for the process.113 ///114 /// \param[in] decl115 /// The Clang declaration for the persistent variable, used for116 /// lookup during parsing.117 ///118 /// \param[in] name119 /// The name of the persistent variable, usually $something.120 ///121 /// \param[in] type122 /// The type of the variable, in the Clang parser's context.123 ///124 /// \return125 /// True on success; false otherwise.126 bool AddPersistentVariable(const clang::NamedDecl *decl,127 ConstString name, TypeFromParser type,128 bool is_result, bool is_lvalue);129 130 /// [Used by IRForTarget] Add a variable to the struct that needs to131 /// be materialized each time the expression runs.132 ///133 /// \param[in] decl134 /// The Clang declaration for the variable.135 ///136 /// \param[in] name137 /// The name of the variable.138 ///139 /// \param[in] value140 /// The LLVM IR value for this variable.141 ///142 /// \param[in] size143 /// The size of the variable in bytes.144 ///145 /// \param[in] alignment146 /// The required alignment of the variable in bytes.147 ///148 /// \return149 /// True on success; false otherwise.150 bool AddValueToStruct(const clang::NamedDecl *decl, ConstString name,151 llvm::Value *value, size_t size,152 lldb::offset_t alignment);153 154 /// [Used by IRForTarget] Finalize the struct, laying out the position of155 /// each object in it.156 ///157 /// \return158 /// True on success; false otherwise.159 bool DoStructLayout();160 161 /// [Used by IRForTarget] Get general information about the laid-out struct162 /// after DoStructLayout() has been called.163 ///164 /// \param[out] num_elements165 /// The number of elements in the struct.166 ///167 /// \param[out] size168 /// The size of the struct, in bytes.169 ///170 /// \param[out] alignment171 /// The alignment of the struct, in bytes.172 ///173 /// \return174 /// True if the information could be retrieved; false otherwise.175 bool GetStructInfo(uint32_t &num_elements, size_t &size,176 lldb::offset_t &alignment);177 178 /// [Used by IRForTarget] Get specific information about one field of the179 /// laid-out struct after DoStructLayout() has been called.180 ///181 /// \param[out] decl182 /// The parsed Decl for the field, as generated by ClangASTSource183 /// on ClangExpressionDeclMap's behalf. In the case of the result184 /// value, this will have the name $__lldb_result even if the185 /// result value ends up having the name $1. This is an186 /// implementation detail of IRForTarget.187 ///188 /// \param[out] value189 /// The IR value for the field (usually a GlobalVariable). In190 /// the case of the result value, this will have the correct191 /// name ($1, for instance). This is an implementation detail192 /// of IRForTarget.193 ///194 /// \param[out] offset195 /// The offset of the field from the beginning of the struct.196 /// As long as the struct is aligned according to its required197 /// alignment, this offset will align the field correctly.198 ///199 /// \param[out] name200 /// The name of the field as used in materialization.201 ///202 /// \param[in] index203 /// The index of the field about which information is requested.204 ///205 /// \return206 /// True if the information could be retrieved; false otherwise.207 bool GetStructElement(const clang::NamedDecl *&decl, llvm::Value *&value,208 lldb::offset_t &offset, ConstString &name,209 uint32_t index);210 211 /// [Used by IRForTarget] Get information about a function given its Decl.212 ///213 /// \param[in] decl214 /// The parsed Decl for the Function, as generated by ClangASTSource215 /// on ClangExpressionDeclMap's behalf.216 ///217 /// \param[out] ptr218 /// The absolute address of the function in the target.219 ///220 /// \return221 /// True if the information could be retrieved; false otherwise.222 bool GetFunctionInfo(const clang::NamedDecl *decl, uint64_t &ptr);223 224 /// [Used by IRForTarget] Get the address of a symbol given nothing but its225 /// name.226 ///227 /// \param[in] target228 /// The target to find the symbol in. If not provided,229 /// then the current parsing context's Target.230 ///231 /// \param[in] process232 /// The process to use. For Objective-C symbols, the process's233 /// Objective-C language runtime may be queried if the process234 /// is non-NULL.235 ///236 /// \param[in] name237 /// The name of the symbol.238 ///239 /// \param[in] module240 /// The module to limit the search to. This can be NULL241 ///242 /// \return243 /// Valid load address for the symbol244 lldb::addr_t GetSymbolAddress(Target &target, Process *process,245 ConstString name, lldb::SymbolType symbol_type,246 Module *module = nullptr);247 248 lldb::addr_t GetSymbolAddress(ConstString name,249 lldb::SymbolType symbol_type);250 251 struct TargetInfo {252 lldb::ByteOrder byte_order = lldb::eByteOrderInvalid;253 size_t address_byte_size = 0;254 255 TargetInfo() = default;256 257 bool IsValid() {258 return (byte_order != lldb::eByteOrderInvalid && address_byte_size != 0);259 }260 };261 TargetInfo GetTargetInfo();262 263 /// [Used by ClangASTSource] Find all entities matching a given name, using264 /// a NameSearchContext to make Decls for them.265 ///266 /// \param[in] context267 /// The NameSearchContext that can construct Decls for this name.268 void FindExternalVisibleDecls(NameSearchContext &context) override;269 270 /// Find all entities matching a given name in a given module/namespace,271 /// using a NameSearchContext to make Decls for them.272 ///273 /// \param[in] context274 /// The NameSearchContext that can construct Decls for this name.275 ///276 /// \param[in] module277 /// If non-NULL, the module to query.278 ///279 /// \param[in] namespace_decl280 /// If valid and module is non-NULL, the parent namespace.281 void FindExternalVisibleDecls(NameSearchContext &context,282 lldb::ModuleSP module,283 const CompilerDeclContext &namespace_decl);284 285protected:286 /// Retrieves the declaration with the given name from the storage of287 /// persistent declarations.288 ///289 /// \return290 /// A persistent decl with the given name or a nullptr.291 virtual clang::NamedDecl *GetPersistentDecl(ConstString name);292 293private:294 ExpressionVariableList295 m_found_entities; ///< All entities that were looked up for the parser.296 ExpressionVariableList297 m_struct_members; ///< All entities that need to be placed in the struct.298 bool m_keep_result_in_memory; ///< True if result persistent variables299 ///generated by this expression should stay in300 ///memory.301 Materializer::PersistentVariableDelegate302 *m_result_delegate; ///< If non-NULL, used to report expression results to303 ///ClangUserExpression.304 ValueObject *m_ctx_obj; ///< If not empty, then expression is305 ///evaluated in context of this object.306 ///For details see the comment to307 ///`UserExpression::Evaluate`.308 309 /// The following values should not live beyond parsing310 class ParserVars {311 public:312 ParserVars() = default;313 314 Target *GetTarget() {315 if (m_exe_ctx.GetTargetPtr())316 return m_exe_ctx.GetTargetPtr();317 else if (m_sym_ctx.target_sp)318 return m_sym_ctx.target_sp.get();319 return nullptr;320 }321 322 ExecutionContext m_exe_ctx; ///< The execution context to use when parsing.323 SymbolContext m_sym_ctx; ///< The symbol context to use in finding variables324 ///and types.325 ClangPersistentVariables *m_persistent_vars =326 nullptr; ///< The persistent variables for the process.327 bool m_enable_lookups = false; ///< Set to true during parsing if we have328 ///found the first "$__lldb" name.329 TargetInfo m_target_info; ///< Basic information about the target.330 Materializer *m_materializer = nullptr; ///< If non-NULL, the materializer331 ///to use when reporting used332 ///variables.333 clang::ASTConsumer *m_code_gen = nullptr; ///< If non-NULL, a code generator334 ///that receives new top-level335 ///functions.336 DiagnosticManager *m_diagnostics = nullptr;337 338 private:339 ParserVars(const ParserVars &) = delete;340 const ParserVars &operator=(const ParserVars &) = delete;341 };342 343 std::unique_ptr<ParserVars> m_parser_vars;344 345 /// Activate parser-specific variables346 void EnableParserVars() {347 if (!m_parser_vars)348 m_parser_vars = std::make_unique<ParserVars>();349 }350 351 /// Deallocate parser-specific variables352 void DisableParserVars() { m_parser_vars.reset(); }353 354 /// The following values contain layout information for the materialized355 /// struct, but are not specific to a single materialization356 struct StructVars {357 StructVars() = default;358 359 lldb::offset_t m_struct_alignment =360 0; ///< The alignment of the struct in bytes.361 size_t m_struct_size = 0; ///< The size of the struct in bytes.362 bool m_struct_laid_out =363 false; ///< True if the struct has been laid out and the364 /// layout is valid (that is, no new fields have been365 /// added since).366 ConstString367 m_result_name; ///< The name of the result variable ($1, for example)368 };369 370 std::unique_ptr<StructVars> m_struct_vars;371 372 /// Activate struct variables373 void EnableStructVars() {374 if (!m_struct_vars)375 m_struct_vars.reset(new struct StructVars);376 }377 378 /// Deallocate struct variables379 void DisableStructVars() { m_struct_vars.reset(); }380 381 lldb::TypeSystemClangSP GetScratchContext(Target &target) {382 return ScratchTypeSystemClang::GetForTarget(target,383 m_ast_context->getLangOpts());384 }385 386 /// Get this parser's ID for use in extracting parser- and JIT-specific data387 /// from persistent variables.388 uint64_t GetParserID() { return (uint64_t) this; }389 390 /// Should be called on all copied functions.391 void MaybeRegisterFunctionBody(clang::FunctionDecl *copied_function_decl);392 393 /// Searches the persistent decls of the target for entities with the394 /// given name.395 ///396 /// \param[in] context397 /// The NameSearchContext that can construct Decls for this name.398 ///399 /// \param[in] name400 /// The name of the entities that need to be found.401 void SearchPersistenDecls(NameSearchContext &context, const ConstString name);402 403 /// Handles looking up $__lldb_class which requires special treatment.404 ///405 /// \param[in] context406 /// The NameSearchContext that can construct Decls for this name.407 void LookUpLldbClass(NameSearchContext &context);408 409 /// Handles looking up $__lldb_objc_class which requires special treatment.410 ///411 /// \param[in] context412 /// The NameSearchContext that can construct Decls for this name.413 void LookUpLldbObjCClass(NameSearchContext &context);414 415 /// Handles looking up the synthetic namespace that contains our local416 /// variables for the current frame.417 ///418 /// \param[in] sym_ctx419 /// The current SymbolContext of this frame.420 ///421 /// \param[in] name_context422 /// The NameSearchContext that can construct Decls for this name.423 void LookupLocalVarNamespace(SymbolContext &sym_ctx,424 NameSearchContext &name_context);425 426 /// Lookup entities in the ClangModulesDeclVendor.427 /// \param[in] context428 /// The NameSearchContext that can construct Decls for this name.429 ///430 /// \param[in] name431 /// The name of the entities that need to be found.432 void LookupInModulesDeclVendor(NameSearchContext &context, ConstString name);433 434 /// Looks up a local variable.435 ///436 /// \param[in] context437 /// The NameSearchContext that can construct Decls for this name.438 ///439 /// \param[in] name440 /// The name of the entities that need to be found.441 ///442 /// \param[in] sym_ctx443 /// The current SymbolContext of this frame.444 ///445 /// \param[in] namespace_decl446 /// The parent namespace if there is one.447 ///448 /// \return449 /// True iff a local variable was found.450 bool LookupLocalVariable(NameSearchContext &context, ConstString name,451 SymbolContext &sym_ctx,452 const CompilerDeclContext &namespace_decl);453 454 /// Searches for functions in the given SymbolContextList.455 ///456 /// \param[in] sc_list457 /// The SymbolContextList to search.458 ///459 /// \param[in] frame_decl_context460 /// The current DeclContext of the current frame.461 ///462 /// \return463 /// A SymbolContextList with any found functions in the front and464 /// any unknown SymbolContexts which are not functions in the back.465 /// The SymbolContexts for the functions are ordered by how close they are466 /// to the DeclContext for the given frame DeclContext.467 SymbolContextList SearchFunctionsInSymbolContexts(468 const SymbolContextList &sc_list,469 const CompilerDeclContext &frame_decl_context);470 471 /// Looks up a function.472 ///473 /// \param[in] context474 /// The NameSearchContext that can construct Decls for this name.475 ///476 /// \param[in] module_sp477 /// If non-NULL, the module to query.478 ///479 /// \param[in] name480 /// The name of the function that should be find.481 ///482 /// \param[in] namespace_decl483 /// If valid and module is non-NULL, the parent namespace.484 ///485 /// \returns Returns \c true if we successfully found a function486 /// and could create a decl with correct type-info for it.487 bool LookupFunction(NameSearchContext &context, lldb::ModuleSP module_sp,488 ConstString name,489 const CompilerDeclContext &namespace_decl);490 491 /// Given a target, find a variable that matches the given name and type.492 ///493 /// \param[in] target494 /// The target to use as a basis for finding the variable.495 ///496 /// \param[in] module497 /// If non-NULL, the module to search.498 ///499 /// \param[in] name500 /// The name as a plain C string.501 ///502 /// \param[in] namespace_decl503 /// If non-NULL and module is non-NULL, the parent namespace.504 ///505 /// \return506 /// The LLDB Variable found, or NULL if none was found.507 lldb::VariableSP508 FindGlobalVariable(Target &target, lldb::ModuleSP &module, ConstString name,509 const CompilerDeclContext &namespace_decl);510 511 /// Get the value of a variable in a given execution context and return the512 /// associated Types if needed.513 ///514 /// \param[in] var515 /// The variable to evaluate.516 ///517 /// \param[out] var_location518 /// The variable location value to fill in519 ///520 /// \param[out] found_type521 /// The type of the found value, as it was found in the user process.522 /// This is only useful when the variable is being inspected on behalf523 /// of the parser, hence the default.524 ///525 /// \param[out] parser_type526 /// The type of the found value, as it was copied into the parser's527 /// AST context. This is only useful when the variable is being528 /// inspected on behalf of the parser, hence the default.529 ///530 /// \return531 /// Return true if the value was successfully filled in.532 bool GetVariableValue(lldb::VariableSP &var,533 lldb_private::Value &var_location,534 TypeFromUser *found_type = nullptr,535 TypeFromParser *parser_type = nullptr);536 537 /// Use the NameSearchContext to generate a Decl for the given LLDB538 /// ValueObject, and put it in the list of found entities.539 ///540 /// Helper function used by the other AddOneVariable APIs.541 ///542 /// \param[in,out] context543 /// The NameSearchContext to use when constructing the Decl.544 ///545 /// \param[in] pt546 /// The CompilerType of the variable we're adding a Decl for.547 ///548 /// \param[in] var549 /// The LLDB ValueObject that needs a Decl.550 ClangExpressionVariable::ParserVars *551 AddExpressionVariable(NameSearchContext &context, TypeFromParser const &pt,552 lldb::ValueObjectSP valobj);553 554 /// Use the NameSearchContext to generate a Decl for the given LLDB555 /// Variable, and put it in the Tuple list.556 ///557 /// \param[in] context558 /// The NameSearchContext to use when constructing the Decl.559 ///560 /// \param[in] var561 /// The LLDB Variable that needs a Decl.562 ///563 /// \param[in] valobj564 /// The LLDB ValueObject for that variable.565 void AddOneVariable(NameSearchContext &context, lldb::VariableSP var,566 lldb::ValueObjectSP valobj);567 568 /// Use the NameSearchContext to generate a Decl for the given ValueObject569 /// and put it in the list of found entities.570 ///571 /// \param[in,out] context572 /// The NameSearchContext to use when constructing the Decl.573 ///574 /// \param[in] valobj575 /// The ValueObject that needs a Decl.576 ///577 /// \param[in] valobj_provider Callback that fetches a ValueObjectSP578 /// from the specified frame579 void AddOneVariable(NameSearchContext &context, lldb::ValueObjectSP valobj,580 ValueObjectProviderTy valobj_provider);581 582 /// Use the NameSearchContext to generate a Decl for the given persistent583 /// variable, and put it in the list of found entities.584 ///585 /// \param[in] context586 /// The NameSearchContext to use when constructing the Decl.587 ///588 /// \param[in] pvar_sp589 /// The persistent variable that needs a Decl.590 void AddOneVariable(NameSearchContext &context,591 lldb::ExpressionVariableSP &pvar_sp);592 593 /// Use the NameSearchContext to generate a Decl for the given LLDB symbol594 /// (treated as a variable), and put it in the list of found entities.595 void AddOneGenericVariable(NameSearchContext &context, const Symbol &symbol);596 597 /// Use the NameSearchContext to generate a Decl for the given function.598 /// (Functions are not placed in the Tuple list.) Can handle both fully599 /// typed functions and generic functions.600 ///601 /// \param[in] context602 /// The NameSearchContext to use when constructing the Decl.603 ///604 /// \param[in] fun605 /// The Function that needs to be created. If non-NULL, this is606 /// a fully-typed function.607 ///608 /// \param[in] sym609 /// The Symbol that corresponds to a function that needs to be610 /// created with generic type (unitptr_t foo(...)).611 void AddOneFunction(NameSearchContext &context, Function *fun, Symbol *sym);612 613 /// Use the NameSearchContext to generate a Decl for the given register.614 ///615 /// \param[in] context616 /// The NameSearchContext to use when constructing the Decl.617 ///618 /// \param[in] reg_info619 /// The information corresponding to that register.620 void AddOneRegister(NameSearchContext &context, const RegisterInfo *reg_info);621 622 /// Use the NameSearchContext to generate a Decl for the given type. (Types623 /// are not placed in the Tuple list.)624 ///625 /// \param[in] context626 /// The NameSearchContext to use when constructing the Decl.627 ///628 /// \param[in] type629 /// The type that needs to be created.630 void AddOneType(NameSearchContext &context, const TypeFromUser &type);631 632 /// Adds the class in which the expression is evaluated to the lookup and633 /// prepares the class to be used as a context for expression evaluation (for634 /// example, it creates a fake member function that will contain the635 /// expression LLDB is trying to evaluate).636 ///637 /// \param[in] context638 /// The NameSearchContext to which the class should be added as a lookup639 /// result.640 ///641 /// \param[in] type642 /// The type of the class that serves as the evaluation context.643 void AddContextClassType(NameSearchContext &context,644 const TypeFromUser &type);645 646 /// Move a type out of the current ASTContext into another, but make sure to647 /// export all components of the type also.648 ///649 /// \param[in] target650 /// The TypeSystemClang to move to.651 /// \param[in] source652 /// The TypeSystemClang to move from. This is assumed to be going away.653 /// \param[in] parser_type654 /// The type as it appears in the source context.655 ///656 /// \return657 /// Returns the moved type, or an empty type if there was a problem.658 TypeFromUser DeportType(TypeSystemClang &target, TypeSystemClang &source,659 TypeFromParser parser_type);660 661 TypeSystemClang *GetTypeSystemClang();662};663 664} // namespace lldb_private665 666#endif // LLDB_SOURCE_PLUGINS_EXPRESSIONPARSER_CLANG_CLANGEXPRESSIONDECLMAP_H667