diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:51:52 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-08-20 20:51:52 +0000 |
commit | 5f29bb8a675e8f96452b632e7129113f7dec850e (patch) | |
tree | 3d3f2a0d3ad10872a4dcaba8ec8d1d20c87ab147 /include/lldb/Expression | |
parent | 88c643b6fec27eec436c8d138fee6346e92337d6 (diff) |
Notes
Diffstat (limited to 'include/lldb/Expression')
-rw-r--r-- | include/lldb/Expression/DWARFExpression.h | 224 | ||||
-rw-r--r-- | include/lldb/Expression/DiagnosticManager.h | 7 | ||||
-rw-r--r-- | include/lldb/Expression/DynamicCheckerFunctions.h | 62 | ||||
-rw-r--r-- | include/lldb/Expression/Expression.h | 54 | ||||
-rw-r--r-- | include/lldb/Expression/ExpressionParser.h | 59 | ||||
-rw-r--r-- | include/lldb/Expression/ExpressionSourceCode.h | 34 | ||||
-rw-r--r-- | include/lldb/Expression/ExpressionTypeSystemHelper.h | 11 | ||||
-rw-r--r-- | include/lldb/Expression/ExpressionVariable.h | 38 | ||||
-rw-r--r-- | include/lldb/Expression/FunctionCaller.h | 138 | ||||
-rw-r--r-- | include/lldb/Expression/IRDynamicChecks.h | 171 | ||||
-rw-r--r-- | include/lldb/Expression/IRExecutionUnit.h | 133 | ||||
-rw-r--r-- | include/lldb/Expression/IRInterpreter.h | 11 | ||||
-rw-r--r-- | include/lldb/Expression/IRMemoryMap.h | 13 | ||||
-rw-r--r-- | include/lldb/Expression/LLVMUserExpression.h | 27 | ||||
-rw-r--r-- | include/lldb/Expression/Materializer.h | 7 | ||||
-rw-r--r-- | include/lldb/Expression/REPL.h | 39 | ||||
-rw-r--r-- | include/lldb/Expression/UserExpression.h | 134 | ||||
-rw-r--r-- | include/lldb/Expression/UtilityFunction.h | 48 |
18 files changed, 416 insertions, 794 deletions
diff --git a/include/lldb/Expression/DWARFExpression.h b/include/lldb/Expression/DWARFExpression.h index cdede56d86d9d..21830a5628004 100644 --- a/include/lldb/Expression/DWARFExpression.h +++ b/include/lldb/Expression/DWARFExpression.h @@ -1,9 +1,8 @@ //===-- DWARFExpression.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -22,8 +21,7 @@ class DWARFUnit; namespace lldb_private { -//---------------------------------------------------------------------- -/// @class DWARFExpression DWARFExpression.h +/// \class DWARFExpression DWARFExpression.h /// "lldb/Expression/DWARFExpression.h" Encapsulates a DWARF location /// expression and interprets it. /// @@ -34,7 +32,6 @@ namespace lldb_private { /// overhead from copying JIT-compiled code into the target is too high or /// where the target cannot be run. This class encapsulates a single DWARF /// location expression or a location list and interprets it. -//---------------------------------------------------------------------- class DWARFExpression { public: enum LocationListFormat : uint8_t { @@ -46,84 +43,64 @@ public: // (.debug_loclists/.debug_loclists.dwo). }; - //------------------------------------------------------------------ - /// Constructor - //------------------------------------------------------------------ - explicit DWARFExpression(DWARFUnit *dwarf_cu); + DWARFExpression(); - //------------------------------------------------------------------ /// Constructor /// - /// @param[in] data + /// \param[in] data /// A data extractor configured to read the DWARF location expression's /// bytecode. /// - /// @param[in] data_offset + /// \param[in] data_offset /// The offset of the location expression in the extractor. /// - /// @param[in] data_length + /// \param[in] data_length /// The byte length of the location expression. - //------------------------------------------------------------------ DWARFExpression(lldb::ModuleSP module, const DataExtractor &data, - DWARFUnit *dwarf_cu, lldb::offset_t data_offset, + const DWARFUnit *dwarf_cu, lldb::offset_t data_offset, lldb::offset_t data_length); - //------------------------------------------------------------------ - /// Copy constructor - //------------------------------------------------------------------ - DWARFExpression(const DWARFExpression &rhs); - - //------------------------------------------------------------------ /// Destructor - //------------------------------------------------------------------ virtual ~DWARFExpression(); - //------------------------------------------------------------------ /// Print the description of the expression to a stream /// - /// @param[in] s + /// \param[in] s /// The stream to print to. /// - /// @param[in] level + /// \param[in] level /// The level of verbosity to use. /// - /// @param[in] location_list_base_addr + /// \param[in] location_list_base_addr /// If this is a location list based expression, this is the /// address of the object that owns it. NOTE: this value is /// different from the DWARF version of the location list base /// address which is compile unit relative. This base address /// is the address of the object that owns the location list. /// - /// @param[in] abi + /// \param[in] abi /// An optional ABI plug-in that can be used to resolve register /// names. - //------------------------------------------------------------------ void GetDescription(Stream *s, lldb::DescriptionLevel level, lldb::addr_t location_list_base_addr, ABI *abi) const; - //------------------------------------------------------------------ /// Return true if the location expression contains data - //------------------------------------------------------------------ bool IsValid() const; - //------------------------------------------------------------------ /// Return true if a location list was provided - //------------------------------------------------------------------ bool IsLocationList() const; - //------------------------------------------------------------------ /// Search for a load address in the location list /// - /// @param[in] process + /// \param[in] process /// The process to use when resolving the load address /// - /// @param[in] addr + /// \param[in] addr /// The address to resolve /// - /// @return + /// \return /// True if IsLocationList() is true and the address was found; /// false otherwise. - //------------------------------------------------------------------ // bool // LocationListContainsLoadAddress (Process* process, const Address &addr) // const; @@ -131,7 +108,6 @@ public: bool LocationListContainsAddress(lldb::addr_t loclist_base_addr, lldb::addr_t addr) const; - //------------------------------------------------------------------ /// If a location is not a location list, return true if the location /// contains a DW_OP_addr () opcode in the stream that matches \a file_addr. /// If file_addr is LLDB_INVALID_ADDRESS, the this function will return true @@ -140,22 +116,24 @@ public: /// static variable since there is no other indication from DWARF debug /// info. /// - /// @param[in] op_addr_idx + /// \param[in] op_addr_idx /// The DW_OP_addr index to retrieve in case there is more than /// one DW_OP_addr opcode in the location byte stream. /// - /// @param[out] error + /// \param[out] error /// If the location stream contains unknown DW_OP opcodes or the /// data is missing, \a error will be set to \b true. /// - /// @return + /// \return /// LLDB_INVALID_ADDRESS if the location doesn't contain a /// DW_OP_addr for \a op_addr_idx, otherwise a valid file address - //------------------------------------------------------------------ lldb::addr_t GetLocation_DW_OP_addr(uint32_t op_addr_idx, bool &error) const; bool Update_DW_OP_addr(lldb::addr_t file_addr); + void UpdateValue(uint64_t const_value, lldb::offset_t const_value_byte_size, + uint8_t addr_byte_size); + void SetModule(const lldb::ModuleSP &module) { m_module_wp = module; } bool ContainsThreadLocalStorage() const; @@ -165,178 +143,100 @@ public: std::function<lldb::addr_t(lldb::addr_t file_addr)> const &link_address_callback); - //------------------------------------------------------------------ - /// Make the expression parser read its location information from a given - /// data source. Does not change the offset and length - /// - /// @param[in] data - /// A data extractor configured to read the DWARF location expression's - /// bytecode. - //------------------------------------------------------------------ - void SetOpcodeData(const DataExtractor &data); - - //------------------------------------------------------------------ - /// Make the expression parser read its location information from a given - /// data source - /// - /// @param[in] module_sp - /// The module that defines the DWARF expression. - /// - /// @param[in] data - /// A data extractor configured to read the DWARF location expression's - /// bytecode. - /// - /// @param[in] data_offset - /// The offset of the location expression in the extractor. - /// - /// @param[in] data_length - /// The byte length of the location expression. - //------------------------------------------------------------------ - void SetOpcodeData(lldb::ModuleSP module_sp, const DataExtractor &data, - lldb::offset_t data_offset, lldb::offset_t data_length); - - //------------------------------------------------------------------ - /// Copy the DWARF location expression into a local buffer. - /// - /// It is a good idea to copy the data so we don't keep the entire object - /// file worth of data around just for a few bytes of location expression. - /// LLDB typically will mmap the entire contents of debug information files, - /// and if we use SetOpcodeData, it will get a shared reference to all of - /// this data for the and cause the object file to have to stay around. Even - /// worse, a very very large ".a" that contains one or more .o files could - /// end up being referenced. Location lists are typically small so even - /// though we are copying the data, it shouldn't amount to that much for the - /// variables we end up parsing. - /// - /// @param[in] module_sp - /// The module that defines the DWARF expression. - /// - /// @param[in] data - /// A data extractor configured to read and copy the DWARF - /// location expression's bytecode. - /// - /// @param[in] data_offset - /// The offset of the location expression in the extractor. - /// - /// @param[in] data_length - /// The byte length of the location expression. - //------------------------------------------------------------------ - void CopyOpcodeData(lldb::ModuleSP module_sp, const DataExtractor &data, - lldb::offset_t data_offset, lldb::offset_t data_length); - - void CopyOpcodeData(const void *data, lldb::offset_t data_length, - lldb::ByteOrder byte_order, uint8_t addr_byte_size); - - void CopyOpcodeData(uint64_t const_value, - lldb::offset_t const_value_byte_size, - uint8_t addr_byte_size); - - //------------------------------------------------------------------ /// Tells the expression that it refers to a location list. /// - /// @param[in] slide + /// \param[in] slide /// This value should be a slide that is applied to any values /// in the location list data so the values become zero based /// offsets into the object that owns the location list. We need /// to make location lists relative to the objects that own them /// so we can relink addresses on the fly. - //------------------------------------------------------------------ void SetLocationListSlide(lldb::addr_t slide); - //------------------------------------------------------------------ /// Return the call-frame-info style register kind - //------------------------------------------------------------------ int GetRegisterKind(); - //------------------------------------------------------------------ /// Set the call-frame-info style register kind /// - /// @param[in] reg_kind + /// \param[in] reg_kind /// The register kind. - //------------------------------------------------------------------ void SetRegisterKind(lldb::RegisterKind reg_kind); - //------------------------------------------------------------------ /// Wrapper for the static evaluate function that accepts an /// ExecutionContextScope instead of an ExecutionContext and uses member /// variables to populate many operands - //------------------------------------------------------------------ bool Evaluate(ExecutionContextScope *exe_scope, lldb::addr_t loclist_base_load_addr, const Value *initial_value_ptr, const Value *object_address_ptr, Value &result, Status *error_ptr) const; - //------------------------------------------------------------------ /// Wrapper for the static evaluate function that uses member variables to /// populate many operands - //------------------------------------------------------------------ bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, lldb::addr_t loclist_base_load_addr, const Value *initial_value_ptr, const Value *object_address_ptr, Value &result, Status *error_ptr) const; - //------------------------------------------------------------------ /// Evaluate a DWARF location expression in a particular context /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context in which to evaluate the location /// expression. The location expression may access the target's /// memory, especially if it comes from the expression parser. /// - /// @param[in] opcode_ctx + /// \param[in] opcode_ctx /// The module which defined the expression. /// - /// @param[in] opcodes + /// \param[in] opcodes /// This is a static method so the opcodes need to be provided /// explicitly. /// - /// @param[in] expr_locals + /// \param[in] expr_locals /// If the location expression was produced by the expression parser, /// the list of local variables referenced by the DWARF expression. /// This list should already have been populated during parsing; /// the DWARF expression refers to variables by index. Can be NULL if /// the location expression uses no locals. /// - /// @param[in] decl_map + /// \param[in] decl_map /// If the location expression was produced by the expression parser, /// the list of external variables referenced by the location /// expression. Can be NULL if the location expression uses no /// external variables. /// - /// @param[in] reg_ctx + /// \param[in] reg_ctx /// An optional parameter which provides a RegisterContext for use /// when evaluating the expression (i.e. for fetching register values). /// Normally this will come from the ExecutionContext's StackFrame but /// in the case where an expression needs to be evaluated while building /// the stack frame list, this short-cut is available. /// - /// @param[in] offset + /// \param[in] offset /// The offset of the location expression in the data extractor. /// - /// @param[in] length + /// \param[in] length /// The length in bytes of the location expression. /// - /// @param[in] reg_set + /// \param[in] reg_set /// The call-frame-info style register kind. /// - /// @param[in] initial_value_ptr + /// \param[in] initial_value_ptr /// A value to put on top of the interpreter stack before evaluating /// the expression, if the expression is parametrized. Can be NULL. /// - /// @param[in] result + /// \param[in] result /// A value into which the result of evaluating the expression is /// to be placed. /// - /// @param[in] error_ptr + /// \param[in] error_ptr /// If non-NULL, used to report errors in expression evaluation. /// - /// @return + /// \return /// True on success; false otherwise. If error_ptr is non-NULL, /// details of the failure are provided through it. - //------------------------------------------------------------------ static bool Evaluate(ExecutionContext *exe_ctx, RegisterContext *reg_ctx, lldb::ModuleSP opcode_ctx, const DataExtractor &opcodes, - DWARFUnit *dwarf_cu, const lldb::offset_t offset, + const DWARFUnit *dwarf_cu, const lldb::offset_t offset, const lldb::offset_t length, const lldb::RegisterKind reg_set, const Value *initial_value_ptr, @@ -366,26 +266,24 @@ public: bool MatchesOperand(StackFrame &frame, const Instruction::Operand &op); -protected: - //------------------------------------------------------------------ +private: /// Pretty-prints the location expression to a stream /// - /// @param[in] stream + /// \param[in] stream /// The stream to use for pretty-printing. /// - /// @param[in] offset + /// \param[in] offset /// The offset into the data buffer of the opcodes to be printed. /// - /// @param[in] length + /// \param[in] length /// The length in bytes of the opcodes to be printed. /// - /// @param[in] level + /// \param[in] level /// The level of detail to use in pretty-printing. /// - /// @param[in] abi + /// \param[in] abi /// An optional ABI plug-in that can be used to resolve register /// names. - //------------------------------------------------------------------ void DumpLocation(Stream *s, lldb::offset_t offset, lldb::offset_t length, lldb::DescriptionLevel level, ABI *abi) const; @@ -399,22 +297,24 @@ protected: bool GetOpAndEndOffsets(StackFrame &frame, lldb::offset_t &op_offset, lldb::offset_t &end_offset); - //------------------------------------------------------------------ - /// Classes that inherit from DWARFExpression can see and modify these - //------------------------------------------------------------------ - - lldb::ModuleWP m_module_wp; ///< Module which defined this expression. - DataExtractor m_data; ///< A data extractor capable of reading opcode bytes - DWARFUnit *m_dwarf_cu; ///< The DWARF compile unit this expression - ///belongs to. It is used - ///< to evaluate values indexing into the .debug_addr section (e.g. - ///< DW_OP_GNU_addr_index, DW_OP_GNU_const_index) - lldb::RegisterKind - m_reg_kind; ///< One of the defines that starts with LLDB_REGKIND_ - lldb::addr_t m_loclist_slide; ///< A value used to slide the location list - ///offsets so that - ///< they are relative to the object that owns the location list - ///< (the function for frame base and variable location lists) + /// Module which defined this expression. + lldb::ModuleWP m_module_wp; + + /// A data extractor capable of reading opcode bytes + DataExtractor m_data; + + /// The DWARF compile unit this expression belongs to. It is used to evaluate + /// values indexing into the .debug_addr section (e.g. DW_OP_GNU_addr_index, + /// DW_OP_GNU_const_index) + const DWARFUnit *m_dwarf_cu; + + /// One of the defines that starts with LLDB_REGKIND_ + lldb::RegisterKind m_reg_kind; + + /// A value used to slide the location list offsets so that m_c they are + /// relative to the object that owns the location list (the function for + /// frame base and variable location lists) + lldb::addr_t m_loclist_slide; }; } // namespace lldb_private diff --git a/include/lldb/Expression/DiagnosticManager.h b/include/lldb/Expression/DiagnosticManager.h index 83e67df2649ab..7e3e2bb8606a1 100644 --- a/include/lldb/Expression/DiagnosticManager.h +++ b/include/lldb/Expression/DiagnosticManager.h @@ -1,9 +1,8 @@ //===-- DiagnosticManager.h -------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/include/lldb/Expression/DynamicCheckerFunctions.h b/include/lldb/Expression/DynamicCheckerFunctions.h new file mode 100644 index 0000000000000..7be24b6ea962b --- /dev/null +++ b/include/lldb/Expression/DynamicCheckerFunctions.h @@ -0,0 +1,62 @@ +//===-- DynamicCheckerFunctions.h -------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_DynamicCheckerFunctions_h_ +#define liblldb_DynamicCheckerFunctions_h_ + +#include "lldb/lldb-types.h" + +namespace lldb_private { + +class DiagnosticManager; +class ExecutionContext; + +/// Encapsulates dynamic check functions used by expressions. +/// +/// Each of the utility functions encapsulated in this class is responsible +/// for validating some data that an expression is about to use. Examples +/// are: +/// +/// a = *b; // check that b is a valid pointer +/// [b init]; // check that b is a valid object to send "init" to +/// +/// The class installs each checker function into the target process and makes +/// it available to IRDynamicChecks to use. +class DynamicCheckerFunctions { +public: + enum DynamicCheckerFunctionsKind { + DCF_Clang, + }; + + DynamicCheckerFunctions(DynamicCheckerFunctionsKind kind) : m_kind(kind) {} + virtual ~DynamicCheckerFunctions() = default; + + /// Install the utility functions into a process. This binds the instance + /// of DynamicCheckerFunctions to that process. + /// + /// \param[in] diagnostic_manager + /// A diagnostic manager to report errors to. + /// + /// \param[in] exe_ctx + /// The execution context to install the functions into. + /// + /// \return + /// True on success; false on failure, or if the functions have + /// already been installed. + virtual bool Install(DiagnosticManager &diagnostic_manager, + ExecutionContext &exe_ctx) = 0; + virtual bool DoCheckersExplainStop(lldb::addr_t addr, Stream &message) = 0; + + DynamicCheckerFunctionsKind GetKind() const { return m_kind; } + +private: + const DynamicCheckerFunctionsKind m_kind; +}; +} // namespace lldb_private + +#endif // liblldb_DynamicCheckerFunctions_h_ diff --git a/include/lldb/Expression/Expression.h b/include/lldb/Expression/Expression.h index 162dcd3e4672e..2f0183cf269b7 100644 --- a/include/lldb/Expression/Expression.h +++ b/include/lldb/Expression/Expression.h @@ -1,9 +1,8 @@ //===-- Expression.h --------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -23,8 +22,7 @@ namespace lldb_private { class RecordingMemoryManager; -//---------------------------------------------------------------------- -/// @class Expression Expression.h "lldb/Expression/Expression.h" Encapsulates +/// \class Expression Expression.h "lldb/Expression/Expression.h" Encapsulates /// a single expression for use in lldb /// /// LLDB uses expressions for various purposes, notably to call functions @@ -32,78 +30,72 @@ class RecordingMemoryManager; /// objects needed to parse and interpret or JIT an expression. It uses the /// expression parser appropriate to the language of the expression to produce /// LLVM IR from the expression. -//---------------------------------------------------------------------- class Expression { public: + /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.) + enum ExpressionKind { + eKindFunctionCaller, + eKindClangFunctionCaller, + eKindUserExpression, + eKindLLVMUserExpression, + eKindClangUserExpression, + eKindUtilityFunction, + eKindClangUtilityFunction, + }; + enum ResultType { eResultTypeAny, eResultTypeId }; - Expression(Target &target); + Expression(Target &target, ExpressionKind kind); - Expression(ExecutionContextScope &exe_scope); + Expression(ExecutionContextScope &exe_scope, ExpressionKind kind); - //------------------------------------------------------------------ /// Destructor - //------------------------------------------------------------------ virtual ~Expression() {} - //------------------------------------------------------------------ /// Return the string that the parser should parse. Must be a full /// translation unit. - //------------------------------------------------------------------ virtual const char *Text() = 0; - //------------------------------------------------------------------ /// Return the function name that should be used for executing the /// expression. Text() should contain the definition of this function. - //------------------------------------------------------------------ virtual const char *FunctionName() = 0; - //------------------------------------------------------------------ /// Return the language that should be used when parsing. To use the /// default, return eLanguageTypeUnknown. - //------------------------------------------------------------------ virtual lldb::LanguageType Language() { return lldb::eLanguageTypeUnknown; } - //------------------------------------------------------------------ /// Return the desired result type of the function, or eResultTypeAny if /// indifferent. - //------------------------------------------------------------------ virtual ResultType DesiredResultType() { return eResultTypeAny; } - //------------------------------------------------------------------ /// Flags - //------------------------------------------------------------------ - //------------------------------------------------------------------ /// Return true if validation code should be inserted into the expression. - //------------------------------------------------------------------ virtual bool NeedsValidation() = 0; - //------------------------------------------------------------------ /// Return true if external variables in the expression should be resolved. - //------------------------------------------------------------------ virtual bool NeedsVariableResolution() = 0; virtual EvaluateExpressionOptions *GetOptions() { return nullptr; }; - //------------------------------------------------------------------ /// Return the address of the function's JIT-compiled code, or /// LLDB_INVALID_ADDRESS if the function is not JIT compiled - //------------------------------------------------------------------ lldb::addr_t StartAddress() { return m_jit_start_addr; } - //------------------------------------------------------------------ /// Called to notify the expression that it is about to be executed. - //------------------------------------------------------------------ virtual void WillStartExecuting() {} - //------------------------------------------------------------------ /// Called to notify the expression that its execution has finished. - //------------------------------------------------------------------ virtual void DidFinishExecuting() {} virtual ExpressionTypeSystemHelper *GetTypeSystemHelper() { return nullptr; } + /// LLVM-style RTTI support. + ExpressionKind getKind() const { return m_kind; } + +private: + /// LLVM-style RTTI support. + const ExpressionKind m_kind; protected: lldb::TargetWP m_target_wp; /// Expression's always have to have a target... lldb::ProcessWP m_jit_process_wp; /// An expression might have a process, but diff --git a/include/lldb/Expression/ExpressionParser.h b/include/lldb/Expression/ExpressionParser.h index 7d337bd00ca63..59f7c1592e83d 100644 --- a/include/lldb/Expression/ExpressionParser.h +++ b/include/lldb/Expression/ExpressionParser.h @@ -1,9 +1,8 @@ //===-- ExpressionParser.h --------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -19,58 +18,51 @@ namespace lldb_private { class IRExecutionUnit; -//---------------------------------------------------------------------- -/// @class ExpressionParser ExpressionParser.h +/// \class ExpressionParser ExpressionParser.h /// "lldb/Expression/ExpressionParser.h" Encapsulates an instance of a /// compiler that can parse expressions. /// /// ExpressionParser is the base class for llvm based Expression parsers. -//---------------------------------------------------------------------- class ExpressionParser { public: - //------------------------------------------------------------------ /// Constructor /// /// Initializes class variables. /// - /// @param[in] exe_scope, + /// \param[in] exe_scope, /// If non-NULL, an execution context scope that can help to /// correctly create an expression with a valid process for /// optional tuning Objective-C runtime support. Can be NULL. /// - /// @param[in] expr + /// \param[in] expr /// The expression to be parsed. - //------------------------------------------------------------------ ExpressionParser(ExecutionContextScope *exe_scope, Expression &expr, bool generate_debug_info) : m_expr(expr), m_generate_debug_info(generate_debug_info) {} - //------------------------------------------------------------------ /// Destructor - //------------------------------------------------------------------ virtual ~ExpressionParser(){}; - //------------------------------------------------------------------ /// Attempts to find possible command line completions for the given /// expression. /// - /// @param[out] request + /// \param[out] request /// The completion request to fill out. The completion should be a string /// that would complete the current token at the cursor position. /// Note that the string in the list replaces the current token /// in the command line. /// - /// @param[in] line + /// \param[in] line /// The line with the completion cursor inside the expression as a string. /// The first line in the expression has the number 0. /// - /// @param[in] pos + /// \param[in] pos /// The character position in the line with the completion cursor. /// If the value is 0, then the cursor is on top of the first character /// in the line (i.e. the user has requested completion from the start of /// the expression). /// - /// @param[in] typed_pos + /// \param[in] typed_pos /// The cursor position in the line as typed by the user. If the user /// expression has not been transformed in some form (e.g. wrapping it /// in a function body for C languages), then this is equal to the @@ -78,73 +70,66 @@ public: /// 'pos' (e.g. a value of 0 means the cursor is at start of the /// expression). /// - /// @return + /// \return /// True if we added any completion results to the output; /// false otherwise. - //------------------------------------------------------------------ virtual bool Complete(CompletionRequest &request, unsigned line, unsigned pos, unsigned typed_pos) = 0; - //------------------------------------------------------------------ /// Parse a single expression and convert it to IR using Clang. Don't wrap /// the expression in anything at all. /// - /// @param[in] diagnostic_manager + /// \param[in] diagnostic_manager /// The diagnostic manager in which to store the errors and warnings. /// - /// @return + /// \return /// The number of errors encountered during parsing. 0 means /// success. - //------------------------------------------------------------------ virtual unsigned Parse(DiagnosticManager &diagnostic_manager) = 0; - //------------------------------------------------------------------ /// Try to use the FixIts in the diagnostic_manager to rewrite the /// expression. If successful, the rewritten expression is stored in the /// diagnostic_manager, get it out with GetFixedExpression. /// - /// @param[in] diagnostic_manager + /// \param[in] diagnostic_manager /// The diagnostic manager containing fixit's to apply. /// - /// @return + /// \return /// \b true if the rewrite was successful, \b false otherwise. - //------------------------------------------------------------------ virtual bool RewriteExpression(DiagnosticManager &diagnostic_manager) { return false; } - //------------------------------------------------------------------ /// Ready an already-parsed expression for execution, possibly evaluating it /// statically. /// - /// @param[out] func_addr + /// \param[out] func_addr /// The address to which the function has been written. /// - /// @param[out] func_end + /// \param[out] func_end /// The end of the function's allocated memory region. (func_addr /// and func_end do not delimit an allocated region; the allocated /// region may begin before func_addr.) /// - /// @param[in] execution_unit_sp + /// \param[in] execution_unit_sp /// After parsing, ownership of the execution unit for /// for the expression is handed to this shared pointer. /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context to write the function into. /// - /// @param[out] can_interpret + /// \param[out] can_interpret /// Set to true if the expression could be interpreted statically; /// untouched otherwise. /// - /// @param[in] execution_policy + /// \param[in] execution_policy /// Determines whether the expression must be JIT-compiled, must be /// evaluated statically, or whether this decision may be made /// opportunistically. /// - /// @return + /// \return /// An error code indicating the success or failure of the operation. /// Test with Success(). - //------------------------------------------------------------------ virtual Status PrepareForExecution(lldb::addr_t &func_addr, lldb::addr_t &func_end, std::shared_ptr<IRExecutionUnit> &execution_unit_sp, diff --git a/include/lldb/Expression/ExpressionSourceCode.h b/include/lldb/Expression/ExpressionSourceCode.h index b5a6187bf3c5f..d0d01b5f9b596 100644 --- a/include/lldb/Expression/ExpressionSourceCode.h +++ b/include/lldb/Expression/ExpressionSourceCode.h @@ -1,9 +1,8 @@ //===-- ExpressionSourceCode.h ----------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -11,42 +10,19 @@ #define liblldb_ExpressionSourceCode_h #include "lldb/lldb-enumerations.h" +#include "llvm/ADT/ArrayRef.h" #include <string> namespace lldb_private { -class ExecutionContext; - class ExpressionSourceCode { public: - static const char *g_expression_prefix; - - static ExpressionSourceCode *CreateWrapped(const char *prefix, - const char *body) { - return new ExpressionSourceCode("$__lldb_expr", prefix, body, true); - } - - static ExpressionSourceCode *CreateUnwrapped(const char *name, - const char *body) { - return new ExpressionSourceCode(name, "", body, false); - } - bool NeedsWrapping() const { return m_wrap; } const char *GetName() const { return m_name.c_str(); } - bool GetText(std::string &text, lldb::LanguageType wrapping_language, - bool static_method, ExecutionContext &exe_ctx) const; - - // Given a string returned by GetText, find the beginning and end of the body - // passed to CreateWrapped. Return true if the bounds could be found. This - // will also work on text with FixItHints applied. - static bool GetOriginalBodyBounds(std::string transformed_text, - lldb::LanguageType wrapping_language, - size_t &start_loc, size_t &end_loc); - -private: +protected: ExpressionSourceCode(const char *name, const char *prefix, const char *body, bool wrap) : m_name(name), m_prefix(prefix), m_body(body), m_wrap(wrap) {} diff --git a/include/lldb/Expression/ExpressionTypeSystemHelper.h b/include/lldb/Expression/ExpressionTypeSystemHelper.h index ffcad54fb9f9b..9c645532cdc19 100644 --- a/include/lldb/Expression/ExpressionTypeSystemHelper.h +++ b/include/lldb/Expression/ExpressionTypeSystemHelper.h @@ -1,10 +1,9 @@ //===-- ExpressionTypeSystemHelper.h ---------------------------------*- C++ //-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -15,8 +14,7 @@ namespace lldb_private { -//---------------------------------------------------------------------- -/// @class ExpressionTypeSystemHelper ExpressionTypeSystemHelper.h +/// \class ExpressionTypeSystemHelper ExpressionTypeSystemHelper.h /// "lldb/Expression/ExpressionTypeSystemHelper.h" /// A helper object that the Expression can pass to its ExpressionParser /// to provide generic information that @@ -24,7 +22,6 @@ namespace lldb_private { /// dyn_cast so that the expression parser can cast it back to the requisite /// specific type. /// -//---------------------------------------------------------------------- class ExpressionTypeSystemHelper { public: diff --git a/include/lldb/Expression/ExpressionVariable.h b/include/lldb/Expression/ExpressionVariable.h index 01e9c416e7c01..08c987270bfe7 100644 --- a/include/lldb/Expression/ExpressionVariable.h +++ b/include/lldb/Expression/ExpressionVariable.h @@ -1,9 +1,8 @@ //===-- ExpressionVariable.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -21,14 +20,10 @@ namespace lldb_private { -class ClangExpressionVariable; - class ExpressionVariable : public std::enable_shared_from_this<ExpressionVariable> { public: - //---------------------------------------------------------------------- // See TypeSystem.h for how to add subclasses to this. - //---------------------------------------------------------------------- enum LLVMCastKind { eKindClang, eKindSwift, eKindGo, kNumKinds }; LLVMCastKind getKind() const { return m_kind; } @@ -39,7 +34,7 @@ public: size_t GetByteSize() { return m_frozen_sp->GetByteSize(); } - const ConstString &GetName() { return m_frozen_sp->GetName(); } + ConstString GetName() { return m_frozen_sp->GetName(); } lldb::ValueObjectSP GetValueObject() { return m_frozen_sp; } @@ -62,7 +57,7 @@ public: m_frozen_sp->GetValue().SetCompilerType(compiler_type); } - void SetName(const ConstString &name) { m_frozen_sp->SetName(name); } + void SetName(ConstString name) { m_frozen_sp->SetName(name); } // this function is used to copy the address-of m_live_sp into m_frozen_sp // this is necessary because the results of certain cast and pointer- @@ -119,18 +114,14 @@ public: LLVMCastKind m_kind; }; -//---------------------------------------------------------------------- -/// @class ExpressionVariableList ExpressionVariable.h +/// \class ExpressionVariableList ExpressionVariable.h /// "lldb/Expression/ExpressionVariable.h" /// A list of variable references. /// /// This class stores variables internally, acting as the permanent store. -//---------------------------------------------------------------------- class ExpressionVariableList { public: - //---------------------------------------------------------------------- /// Implementation of methods in ExpressionVariableListBase - //---------------------------------------------------------------------- size_t GetSize() { return m_variables.size(); } lldb::ExpressionVariableSP GetVariableAtIndex(size_t index) { @@ -161,17 +152,15 @@ public: return false; } - //---------------------------------------------------------------------- /// Finds a variable by name in the list. /// - /// @param[in] name + /// \param[in] name /// The name of the requested variable. /// - /// @return + /// \return /// The variable requested, or nullptr if that variable is not in the /// list. - //---------------------------------------------------------------------- - lldb::ExpressionVariableSP GetVariable(const ConstString &name) { + lldb::ExpressionVariableSP GetVariable(ConstString name) { lldb::ExpressionVariableSP var_sp; for (size_t index = 0, size = GetSize(); index < size; ++index) { var_sp = GetVariableAtIndex(index); @@ -215,9 +204,7 @@ private: class PersistentExpressionState : public ExpressionVariableList { public: - //---------------------------------------------------------------------- // See TypeSystem.h for how to add subclasses to this. - //---------------------------------------------------------------------- enum LLVMCastKind { eKindClang, eKindSwift, eKindGo, kNumKinds }; LLVMCastKind getKind() const { return m_kind; } @@ -231,7 +218,7 @@ public: virtual lldb::ExpressionVariableSP CreatePersistentVariable(ExecutionContextScope *exe_scope, - const ConstString &name, const CompilerType &type, + ConstString name, const CompilerType &type, lldb::ByteOrder byte_order, uint32_t addr_byte_size) = 0; @@ -245,7 +232,10 @@ public: virtual void RemovePersistentVariable(lldb::ExpressionVariableSP variable) = 0; - virtual lldb::addr_t LookupSymbol(const ConstString &name); + virtual llvm::Optional<CompilerType> + GetCompilerTypeFromPersistentDecl(ConstString type_name) = 0; + + virtual lldb::addr_t LookupSymbol(ConstString name); void RegisterExecutionUnit(lldb::IRExecutionUnitSP &execution_unit_sp); diff --git a/include/lldb/Expression/FunctionCaller.h b/include/lldb/Expression/FunctionCaller.h index 0ec7e202dac9b..ea9d0205bf867 100644 --- a/include/lldb/Expression/FunctionCaller.h +++ b/include/lldb/Expression/FunctionCaller.h @@ -1,9 +1,8 @@ //===-- FunctionCaller.h ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -23,8 +22,7 @@ namespace lldb_private { -//---------------------------------------------------------------------- -/// @class FunctionCaller FunctionCaller.h "lldb/Expression/FunctionCaller.h" +/// \class FunctionCaller FunctionCaller.h "lldb/Expression/FunctionCaller.h" /// Encapsulates a function that can be called. /// /// A given FunctionCaller object can handle a single function signature. @@ -55,152 +53,141 @@ namespace lldb_private { /// /// Any of the methods that take arg_addr_ptr can be passed nullptr, and the /// argument space will be managed for you. -//---------------------------------------------------------------------- class FunctionCaller : public Expression { public: - //------------------------------------------------------------------ + /// LLVM-style RTTI support. + static bool classof(const Expression *E) { + return E->getKind() == eKindFunctionCaller; + } + /// Constructor /// - /// @param[in] exe_scope + /// \param[in] exe_scope /// An execution context scope that gets us at least a target and /// process. /// - /// @param[in] ast_context + /// \param[in] ast_context /// The AST context to evaluate argument types in. /// - /// @param[in] return_qualtype + /// \param[in] return_qualtype /// An opaque Clang QualType for the function result. Should be /// defined in ast_context. /// - /// @param[in] function_address + /// \param[in] function_address /// The address of the function to call. /// - /// @param[in] arg_value_list + /// \param[in] arg_value_list /// The default values to use when calling this function. Can /// be overridden using WriteFunctionArguments(). - //------------------------------------------------------------------ FunctionCaller(ExecutionContextScope &exe_scope, const CompilerType &return_type, const Address &function_address, const ValueList &arg_value_list, const char *name); - //------------------------------------------------------------------ /// Destructor - //------------------------------------------------------------------ ~FunctionCaller() override; - //------------------------------------------------------------------ /// Compile the wrapper function /// - /// @param[in] thread_to_use_sp + /// \param[in] thread_to_use_sp /// Compilation might end up calling functions. Pass in the thread you /// want the compilation to use. If you pass in an empty ThreadSP it will /// use the currently selected thread. /// - /// @param[in] diagnostic_manager + /// \param[in] diagnostic_manager /// The diagnostic manager to report parser errors to. /// - /// @return + /// \return /// The number of errors. - //------------------------------------------------------------------ virtual unsigned CompileFunction(lldb::ThreadSP thread_to_use_sp, DiagnosticManager &diagnostic_manager) = 0; - //------------------------------------------------------------------ /// Insert the default function wrapper and its default argument struct /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context to insert the function and its arguments /// into. /// - /// @param[in,out] args_addr_ref + /// \param[in,out] args_addr_ref /// The address of the structure to write the arguments into. May /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated /// and args_addr_ref is pointed to it. /// - /// @param[in] diagnostic_manager + /// \param[in] diagnostic_manager /// The diagnostic manager to report errors to. /// - /// @return + /// \return /// True on success; false otherwise. - //------------------------------------------------------------------ bool InsertFunction(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, DiagnosticManager &diagnostic_manager); - //------------------------------------------------------------------ /// Insert the default function wrapper (using the JIT) /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context to insert the function and its arguments /// into. /// - /// @param[in] diagnostic_manager + /// \param[in] diagnostic_manager /// The diagnostic manager to report errors to. /// - /// @return + /// \return /// True on success; false otherwise. - //------------------------------------------------------------------ bool WriteFunctionWrapper(ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager); - //------------------------------------------------------------------ /// Insert the default function argument struct /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context to insert the function and its arguments /// into. /// - /// @param[in,out] args_addr_ref + /// \param[in,out] args_addr_ref /// The address of the structure to write the arguments into. May /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated /// and args_addr_ref is pointed to it. /// - /// @param[in] diagnostic_manager + /// \param[in] diagnostic_manager /// The diagnostic manager to report errors to. /// - /// @return + /// \return /// True on success; false otherwise. - //------------------------------------------------------------------ bool WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, DiagnosticManager &diagnostic_manager); - //------------------------------------------------------------------ /// Insert an argument struct with a non-default function address and non- /// default argument values /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context to insert the function and its arguments /// into. /// - /// @param[in,out] args_addr_ref + /// \param[in,out] args_addr_ref /// The address of the structure to write the arguments into. May /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated /// and args_addr_ref is pointed at it. /// - /// @param[in] arg_values + /// \param[in] arg_values /// The values of the function's arguments. /// - /// @param[in] diagnostic_manager + /// \param[in] diagnostic_manager /// The diagnostic manager to report errors to. /// - /// @return + /// \return /// True on success; false otherwise. - //------------------------------------------------------------------ bool WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, ValueList &arg_values, DiagnosticManager &diagnostic_manager); - //------------------------------------------------------------------ /// Run the function this FunctionCaller was created with. /// /// This is the full version. /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The thread & process in which this function will run. /// - /// @param[in] args_addr_ptr + /// \param[in] args_addr_ptr /// If nullptr, the function will take care of allocating & deallocating /// the wrapper /// args structure. Otherwise, if set to LLDB_INVALID_ADDRESS, a new @@ -212,118 +199,99 @@ public: /// this should point to an already allocated structure with the values /// already written. /// - /// @param[in] diagnostic_manager + /// \param[in] diagnostic_manager /// The diagnostic manager to report errors to. /// - /// @param[in] options + /// \param[in] options /// The options for this expression execution. /// - /// @param[out] results + /// \param[out] results /// The result value will be put here after running the function. /// - /// @return + /// \return /// Returns one of the ExpressionResults enum indicating function call /// status. - //------------------------------------------------------------------ lldb::ExpressionResults ExecuteFunction(ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr, const EvaluateExpressionOptions &options, DiagnosticManager &diagnostic_manager, Value &results); - //------------------------------------------------------------------ /// Get a thread plan to run the function this FunctionCaller was created /// with. /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context to insert the function and its arguments /// into. /// - /// @param[in] func_addr + /// \param[in] func_addr /// The address of the function in the target process. /// - /// @param[in] args_addr + /// \param[in] args_addr /// The address of the argument struct. /// - /// @param[in] diagnostic_manager + /// \param[in] diagnostic_manager /// The diagnostic manager to report errors to. /// - /// @param[in] stop_others + /// \param[in] stop_others /// True if other threads should pause during execution. /// - /// @param[in] unwind_on_error + /// \param[in] unwind_on_error /// True if the thread plan may simply be discarded if an error occurs. /// - /// @return + /// \return /// A ThreadPlan shared pointer for executing the function. - //------------------------------------------------------------------ lldb::ThreadPlanSP GetThreadPlanToCallFunction(ExecutionContext &exe_ctx, lldb::addr_t args_addr, const EvaluateExpressionOptions &options, DiagnosticManager &diagnostic_manager); - //------------------------------------------------------------------ /// Get the result of the function from its struct /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context to retrieve the result from. /// - /// @param[in] args_addr + /// \param[in] args_addr /// The address of the argument struct. /// - /// @param[out] ret_value + /// \param[out] ret_value /// The value returned by the function. /// - /// @return + /// \return /// True on success; false otherwise. - //------------------------------------------------------------------ bool FetchFunctionResults(ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value); - //------------------------------------------------------------------ /// Deallocate the arguments structure /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context to insert the function and its arguments /// into. /// - /// @param[in] args_addr + /// \param[in] args_addr /// The address of the argument struct. - //------------------------------------------------------------------ void DeallocateFunctionResults(ExecutionContext &exe_ctx, lldb::addr_t args_addr); - //------------------------------------------------------------------ /// Interface for ClangExpression - //------------------------------------------------------------------ - //------------------------------------------------------------------ /// Return the string that the parser should parse. Must be a full /// translation unit. - //------------------------------------------------------------------ const char *Text() override { return m_wrapper_function_text.c_str(); } - //------------------------------------------------------------------ /// Return the function name that should be used for executing the /// expression. Text() should contain the definition of this function. - //------------------------------------------------------------------ const char *FunctionName() override { return m_wrapper_function_name.c_str(); } - //------------------------------------------------------------------ /// Return the object that the parser should use when registering local /// variables. May be nullptr if the Expression doesn't care. - //------------------------------------------------------------------ ExpressionVariableList *LocalVariables() { return nullptr; } - //------------------------------------------------------------------ /// Return true if validation code should be inserted into the expression. - //------------------------------------------------------------------ bool NeedsValidation() override { return false; } - //------------------------------------------------------------------ /// Return true if external variables in the expression should be resolved. - //------------------------------------------------------------------ bool NeedsVariableResolution() override { return false; } ValueList GetArgumentValues() const { return m_arg_values; } @@ -362,7 +330,6 @@ protected: bool m_struct_valid; ///< True if the ASTStructExtractor has populated the ///variables below. - //------------------------------------------------------------------ /// These values are populated by the ASTStructExtractor size_t m_struct_size; ///< The size of the argument struct, in bytes. std::vector<uint64_t> @@ -370,7 +337,6 @@ protected: uint64_t m_return_size; ///< The size of the result variable, in bytes. uint64_t m_return_offset; ///< The offset of the result variable in the ///struct, in bytes. - //------------------------------------------------------------------ ValueList m_arg_values; ///< The default values of the arguments. diff --git a/include/lldb/Expression/IRDynamicChecks.h b/include/lldb/Expression/IRDynamicChecks.h deleted file mode 100644 index f31c03cfb9efa..0000000000000 --- a/include/lldb/Expression/IRDynamicChecks.h +++ /dev/null @@ -1,171 +0,0 @@ -//===-- IRDynamicChecks.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_IRDynamicChecks_h_ -#define liblldb_IRDynamicChecks_h_ - -#include "lldb/lldb-types.h" -#include "llvm/Pass.h" - -namespace llvm { -class BasicBlock; -class CallInst; -class Constant; -class Function; -class Instruction; -class Module; -class DataLayout; -class Value; -} - -namespace lldb_private { - -class ClangExpressionDeclMap; -class ExecutionContext; -class Stream; - -//---------------------------------------------------------------------- -/// @class DynamicCheckerFunctions IRDynamicChecks.h -/// "lldb/Expression/IRDynamicChecks.h" Encapsulates dynamic check functions -/// used by expressions. -/// -/// Each of the utility functions encapsulated in this class is responsible -/// for validating some data that an expression is about to use. Examples -/// are: -/// -/// a = *b; // check that b is a valid pointer [b init]; // check that b -/// is a valid object to send "init" to -/// -/// The class installs each checker function into the target process and makes -/// it available to IRDynamicChecks to use. -//---------------------------------------------------------------------- -class DynamicCheckerFunctions { -public: - //------------------------------------------------------------------ - /// Constructor - //------------------------------------------------------------------ - DynamicCheckerFunctions(); - - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - ~DynamicCheckerFunctions(); - - //------------------------------------------------------------------ - /// Install the utility functions into a process. This binds the instance - /// of DynamicCheckerFunctions to that process. - /// - /// @param[in] diagnostic_manager - /// A diagnostic manager to report errors to. - /// - /// @param[in] exe_ctx - /// The execution context to install the functions into. - /// - /// @return - /// True on success; false on failure, or if the functions have - /// already been installed. - //------------------------------------------------------------------ - bool Install(DiagnosticManager &diagnostic_manager, - ExecutionContext &exe_ctx); - - bool DoCheckersExplainStop(lldb::addr_t addr, Stream &message); - - std::unique_ptr<UtilityFunction> m_valid_pointer_check; - std::unique_ptr<UtilityFunction> m_objc_object_check; -}; - -//---------------------------------------------------------------------- -/// @class IRDynamicChecks IRDynamicChecks.h -/// "lldb/Expression/IRDynamicChecks.h" Adds dynamic checks to a user-entered -/// expression to reduce its likelihood of crashing -/// -/// When an IR function is executed in the target process, it may cause -/// crashes or hangs by dereferencing NULL pointers, trying to call -/// Objective-C methods on objects that do not respond to them, and so forth. -/// -/// IRDynamicChecks adds calls to the functions in DynamicCheckerFunctions to -/// appropriate locations in an expression's IR. -//---------------------------------------------------------------------- -class IRDynamicChecks : public llvm::ModulePass { -public: - //------------------------------------------------------------------ - /// Constructor - /// - /// @param[in] checker_functions - /// The checker functions for the target process. - /// - /// @param[in] func_name - /// The name of the function to prepare for execution in the target. - /// - /// @param[in] decl_map - /// The mapping used to look up entities in the target process. In - /// this case, used to find objc_msgSend - //------------------------------------------------------------------ - IRDynamicChecks(DynamicCheckerFunctions &checker_functions, - const char *func_name = "$__lldb_expr"); - - //------------------------------------------------------------------ - /// Destructor - //------------------------------------------------------------------ - ~IRDynamicChecks() override; - - //------------------------------------------------------------------ - /// Run this IR transformer on a single module - /// - /// @param[in] M - /// The module to run on. This module is searched for the function - /// $__lldb_expr, and that function is passed to the passes one by - /// one. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool runOnModule(llvm::Module &M) override; - - //------------------------------------------------------------------ - /// Interface stub - //------------------------------------------------------------------ - void assignPassManager( - llvm::PMStack &PMS, - llvm::PassManagerType T = llvm::PMT_ModulePassManager) override; - - //------------------------------------------------------------------ - /// Returns PMT_ModulePassManager - //------------------------------------------------------------------ - llvm::PassManagerType getPotentialPassManagerType() const override; - -private: - //------------------------------------------------------------------ - /// A basic block-level pass to find all pointer dereferences and - /// validate them before use. - //------------------------------------------------------------------ - - //------------------------------------------------------------------ - /// The top-level pass implementation - /// - /// @param[in] M - /// The module currently being processed. - /// - /// @param[in] BB - /// The basic block currently being processed. - /// - /// @return - /// True on success; false otherwise - //------------------------------------------------------------------ - bool FindDataLoads(llvm::Module &M, llvm::BasicBlock &BB); - - std::string m_func_name; ///< The name of the function to add checks to - DynamicCheckerFunctions - &m_checker_functions; ///< The checker functions for the process -}; - -} // namespace lldb_private - -#endif // liblldb_IRDynamicChecks_h_ diff --git a/include/lldb/Expression/IRExecutionUnit.h b/include/lldb/Expression/IRExecutionUnit.h index b966d135deabc..beff44db9d5ed 100644 --- a/include/lldb/Expression/IRExecutionUnit.h +++ b/include/lldb/Expression/IRExecutionUnit.h @@ -1,9 +1,8 @@ //===-- IRExecutionUnit.h ---------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -37,8 +36,7 @@ namespace lldb_private { class Status; -//---------------------------------------------------------------------- -/// @class IRExecutionUnit IRExecutionUnit.h +/// \class IRExecutionUnit IRExecutionUnit.h /// "lldb/Expression/IRExecutionUnit.h" Contains the IR and, optionally, JIT- /// compiled code for a module. /// @@ -55,22 +53,17 @@ class Status; /// is how the JIT emits code. Because LLDB needs to move JIT-compiled code /// into the target process, the IRExecutionUnit knows how to copy the emitted /// code into the target process. -//---------------------------------------------------------------------- class IRExecutionUnit : public std::enable_shared_from_this<IRExecutionUnit>, public IRMemoryMap, public ObjectFileJITDelegate { public: - //------------------------------------------------------------------ /// Constructor - //------------------------------------------------------------------ - IRExecutionUnit(std::unique_ptr<llvm::LLVMContext> &context_ap, - std::unique_ptr<llvm::Module> &module_ap, ConstString &name, + IRExecutionUnit(std::unique_ptr<llvm::LLVMContext> &context_up, + std::unique_ptr<llvm::Module> &module_up, ConstString &name, const lldb::TargetSP &target_sp, const SymbolContext &sym_ctx, std::vector<std::string> &cpu_features); - //------------------------------------------------------------------ /// Destructor - //------------------------------------------------------------------ ~IRExecutionUnit() override; ConstString GetFunctionName() { return m_name; } @@ -85,19 +78,15 @@ public: void GetRunnableInfo(Status &error, lldb::addr_t &func_addr, lldb::addr_t &func_end); - //------------------------------------------------------------------ /// Accessors for IRForTarget and other clients that may want binary data /// placed on their behalf. The binary data is owned by the IRExecutionUnit /// unless the client explicitly chooses to free it. - //------------------------------------------------------------------ lldb::addr_t WriteNow(const uint8_t *bytes, size_t size, Status &error); void FreeNow(lldb::addr_t allocation); - //------------------------------------------------------------------ /// ObjectFileJITDelegate overrides - //------------------------------------------------------------------ lldb::ByteOrder GetByteOrder() const override; uint32_t GetAddressByteSize() const override; @@ -112,41 +101,37 @@ public: lldb::ModuleSP GetJITModule(); - lldb::addr_t FindSymbol(const ConstString &name); + lldb::addr_t FindSymbol(ConstString name, bool &missing_weak); void GetStaticInitializers(std::vector<lldb::addr_t> &static_initializers); - //---------------------------------------------------------------------- - /// @class JittedFunction IRExecutionUnit.h + /// \class JittedFunction IRExecutionUnit.h /// "lldb/Expression/IRExecutionUnit.h" /// Encapsulates a single function that has been generated by the JIT. /// /// Functions that have been generated by the JIT are first resident in the /// local process, and then placed in the target process. JittedFunction /// represents a function possibly resident in both. - //---------------------------------------------------------------------- struct JittedEntity { ConstString m_name; ///< The function's name lldb::addr_t m_local_addr; ///< The address of the function in LLDB's memory lldb::addr_t m_remote_addr; ///< The address of the function in the target's memory - //------------------------------------------------------------------ /// Constructor /// /// Initializes class variabes. /// - /// @param[in] name + /// \param[in] name /// The name of the function. /// - /// @param[in] local_addr + /// \param[in] local_addr /// The address of the function in LLDB, or LLDB_INVALID_ADDRESS if /// it is not present in LLDB's memory. /// - /// @param[in] remote_addr + /// \param[in] remote_addr /// The address of the function in the target, or LLDB_INVALID_ADDRESS /// if it is not present in the target's memory. - //------------------------------------------------------------------ JittedEntity(const char *name, lldb::addr_t local_addr = LLDB_INVALID_ADDRESS, lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) @@ -177,63 +162,53 @@ public: } private: - //------------------------------------------------------------------ /// Look up the object in m_address_map that contains a given address, find /// where it was copied to, and return the remote address at the same offset /// into the copied entity /// - /// @param[in] local_address + /// \param[in] local_address /// The address in the debugger. /// - /// @return + /// \return /// The address in the target process. - //------------------------------------------------------------------ lldb::addr_t GetRemoteAddressForLocal(lldb::addr_t local_address); - //------------------------------------------------------------------ /// Look up the object in m_address_map that contains a given address, find /// where it was copied to, and return its address range in the target /// process /// - /// @param[in] local_address + /// \param[in] local_address /// The address in the debugger. /// - /// @return + /// \return /// The range of the containing object in the target process. - //------------------------------------------------------------------ typedef std::pair<lldb::addr_t, uintptr_t> AddrRange; AddrRange GetRemoteRangeForLocal(lldb::addr_t local_address); - //------------------------------------------------------------------ /// Commit all allocations to the process and record where they were stored. /// - /// @param[in] process + /// \param[in] process /// The process to allocate memory in. /// - /// @return + /// \return /// True <=> all allocations were performed successfully. /// This method will attempt to free allocated memory if the /// operation fails. - //------------------------------------------------------------------ bool CommitAllocations(lldb::ProcessSP &process_sp); - //------------------------------------------------------------------ /// Report all committed allocations to the execution engine. /// - /// @param[in] engine + /// \param[in] engine /// The execution engine to notify. - //------------------------------------------------------------------ void ReportAllocations(llvm::ExecutionEngine &engine); - //------------------------------------------------------------------ /// Write the contents of all allocations to the process. /// - /// @param[in] local_address + /// \param[in] local_address /// The process containing the allocations. /// - /// @return + /// \return /// True <=> all allocations were performed successfully. - //------------------------------------------------------------------ bool WriteData(lldb::ProcessSP &process_sp); Status DisassembleFunction(Stream &stream, lldb::ProcessSP &process_sp); @@ -241,7 +216,7 @@ private: struct SearchSpec; void CollectCandidateCNames(std::vector<SearchSpec> &C_specs, - const ConstString &name); + ConstString name); void CollectCandidateCPlusPlusNames(std::vector<SearchSpec> &CPP_specs, const std::vector<SearchSpec> &C_specs, @@ -251,7 +226,8 @@ private: const std::vector<SearchSpec> &C_specs); lldb::addr_t FindInSymbols(const std::vector<SearchSpec> &specs, - const lldb_private::SymbolContext &sc); + const lldb_private::SymbolContext &sc, + bool &symbol_was_missing_weak); lldb::addr_t FindInRuntimes(const std::vector<SearchSpec> &specs, const lldb_private::SymbolContext &sc); @@ -259,7 +235,7 @@ private: lldb::addr_t FindInUserDefinedSymbols(const std::vector<SearchSpec> &specs, const lldb_private::SymbolContext &sc); - void ReportSymbolLookupError(const ConstString &name); + void ReportSymbolLookupError(ConstString name); class MemoryManager : public llvm::SectionMemoryManager { public: @@ -267,59 +243,53 @@ private: ~MemoryManager() override; - //------------------------------------------------------------------ /// Allocate space for executable code, and add it to the m_spaceBlocks /// map /// - /// @param[in] Size + /// \param[in] Size /// The size of the area. /// - /// @param[in] Alignment + /// \param[in] Alignment /// The required alignment of the area. /// - /// @param[in] SectionID + /// \param[in] SectionID /// A unique identifier for the section. /// - /// @return + /// \return /// Allocated space. - //------------------------------------------------------------------ uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName) override; - //------------------------------------------------------------------ /// Allocate space for data, and add it to the m_spaceBlocks map /// - /// @param[in] Size + /// \param[in] Size /// The size of the area. /// - /// @param[in] Alignment + /// \param[in] Alignment /// The required alignment of the area. /// - /// @param[in] SectionID + /// \param[in] SectionID /// A unique identifier for the section. /// - /// @param[in] IsReadOnly + /// \param[in] IsReadOnly /// Flag indicating the section is read-only. /// - /// @return + /// \return /// Allocated space. - //------------------------------------------------------------------ uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, llvm::StringRef SectionName, bool IsReadOnly) override; - //------------------------------------------------------------------ /// Called when object loading is complete and section page permissions /// can be applied. Currently unimplemented for LLDB. /// - /// @param[out] ErrMsg + /// \param[out] ErrMsg /// The error that prevented the page protection from succeeding. /// - /// @return + /// \return /// True in case of failure, false in case of success. - //------------------------------------------------------------------ bool finalizeMemory(std::string *ErrMsg) override { // TODO: Ensure that the instruction cache is flushed because // relocations are updated by dy-load. See: @@ -332,31 +302,36 @@ private: size_t Size) override {} uint64_t getSymbolAddress(const std::string &Name) override; + + // Find the address of the symbol Name. If Name is a missing weak symbol + // then missing_weak will be true. + uint64_t GetSymbolAddressAndPresence(const std::string &Name, + bool &missing_weak); + + llvm::JITSymbol findSymbol(const std::string &Name) override; void *getPointerToNamedFunction(const std::string &Name, bool AbortOnFailure = true) override; private: - std::unique_ptr<SectionMemoryManager> m_default_mm_ap; ///< The memory - ///allocator to use - ///in actually - ///creating space. - ///All calls are - ///passed through to - ///it. + std::unique_ptr<SectionMemoryManager> m_default_mm_up; ///< The memory + /// allocator to use + /// in actually + /// creating space. + /// All calls are + /// passed through to + /// it. IRExecutionUnit &m_parent; ///< The execution unit this is a proxy for. }; static const unsigned eSectionIDInvalid = (unsigned)-1; - //---------------------------------------------------------------------- - /// @class AllocationRecord IRExecutionUnit.h + /// \class AllocationRecord IRExecutionUnit.h /// "lldb/Expression/IRExecutionUnit.h" Encapsulates a single allocation /// request made by the JIT. /// /// Allocations made by the JIT are first queued up and then applied in bulk /// to the underlying process. - //---------------------------------------------------------------------- enum class AllocationKind { Stub, Code, Data, Global, Bytes }; static lldb::SectionType @@ -393,11 +368,11 @@ private: typedef std::vector<AllocationRecord> RecordVector; RecordVector m_records; - std::unique_ptr<llvm::LLVMContext> m_context_ap; - std::unique_ptr<llvm::ExecutionEngine> m_execution_engine_ap; - std::unique_ptr<llvm::ObjectCache> m_object_cache_ap; + std::unique_ptr<llvm::LLVMContext> m_context_up; + std::unique_ptr<llvm::ExecutionEngine> m_execution_engine_up; + std::unique_ptr<llvm::ObjectCache> m_object_cache_up; std::unique_ptr<llvm::Module> - m_module_ap; ///< Holder for the module until it's been handed off + m_module_up; ///< Holder for the module until it's been handed off llvm::Module *m_module; ///< Owned by the execution engine std::vector<std::string> m_cpu_features; std::vector<JittedFunction> m_jitted_functions; ///< A vector of all functions diff --git a/include/lldb/Expression/IRInterpreter.h b/include/lldb/Expression/IRInterpreter.h index 2d87346b70663..6148093e718ff 100644 --- a/include/lldb/Expression/IRInterpreter.h +++ b/include/lldb/Expression/IRInterpreter.h @@ -1,9 +1,8 @@ //===-- IRInterpreter.h -----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -27,15 +26,13 @@ class ClangExpressionDeclMap; class IRMemoryMap; } -//---------------------------------------------------------------------- -/// @class IRInterpreter IRInterpreter.h "lldb/Expression/IRInterpreter.h" +/// \class IRInterpreter IRInterpreter.h "lldb/Expression/IRInterpreter.h" /// Attempt to interpret the function's code if it does not require /// running the target. /// /// In some cases, the IR for an expression can be evaluated entirely in the /// debugger, manipulating variables but not executing any code in the target. /// The IRInterpreter attempts to do this. -//---------------------------------------------------------------------- class IRInterpreter { public: static bool CanInterpret(llvm::Module &module, llvm::Function &function, diff --git a/include/lldb/Expression/IRMemoryMap.h b/include/lldb/Expression/IRMemoryMap.h index 026ca6b981106..d6a17a9848fb6 100644 --- a/include/lldb/Expression/IRMemoryMap.h +++ b/include/lldb/Expression/IRMemoryMap.h @@ -1,9 +1,8 @@ -//===-- IRExecutionUnit.h ---------------------------------------*- C++ -*-===// +//===-- IRMemoryMap.h -------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -18,8 +17,7 @@ namespace lldb_private { -//---------------------------------------------------------------------- -/// @class IRMemoryMap IRMemoryMap.h "lldb/Expression/IRMemoryMap.h" +/// \class IRMemoryMap IRMemoryMap.h "lldb/Expression/IRMemoryMap.h" /// Encapsulates memory that may exist in the process but must /// also be available in the host process. /// @@ -33,7 +31,6 @@ namespace lldb_private { /// address in the tar at which they reside. If the inferior does not exist, /// allocations still get made-up addresses. If an inferior appears at some /// point, then those addresses need to be re-mapped. -//---------------------------------------------------------------------- class IRMemoryMap { public: IRMemoryMap(lldb::TargetSP target_sp); diff --git a/include/lldb/Expression/LLVMUserExpression.h b/include/lldb/Expression/LLVMUserExpression.h index 1ba822265fcaa..c2af7239951b5 100644 --- a/include/lldb/Expression/LLVMUserExpression.h +++ b/include/lldb/Expression/LLVMUserExpression.h @@ -1,9 +1,8 @@ //===-- LLVMUserExpression.h ------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -20,8 +19,7 @@ namespace lldb_private { -//---------------------------------------------------------------------- -/// @class LLVMUserExpression LLVMUserExpression.h +/// \class LLVMUserExpression LLVMUserExpression.h /// "lldb/Expression/LLVMUserExpression.h" Encapsulates a one-time expression /// for use in lldb. /// @@ -31,9 +29,13 @@ namespace lldb_private { /// expression. The actual parsing part will be provided by the specific /// implementations of LLVMUserExpression - which will be vended through the /// appropriate TypeSystem. -//---------------------------------------------------------------------- class LLVMUserExpression : public UserExpression { public: + /// LLVM-style RTTI support. + static bool classof(const Expression *E) { + return E->getKind() == eKindLLVMUserExpression; + } + // The IRPasses struct is filled in by a runtime after an expression is // compiled and can be used to to run fixups/analysis passes as required. // EarlyPasses are run on the generated module before lldb runs its own IR @@ -49,7 +51,8 @@ public: LLVMUserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language, ResultType desired_type, - const EvaluateExpressionOptions &options); + const EvaluateExpressionOptions &options, + ExpressionKind kind); ~LLVMUserExpression() override; bool FinalizeJITExecution( @@ -60,10 +63,8 @@ public: bool CanInterpret() override { return m_can_interpret; } - //------------------------------------------------------------------ /// Return the string that the parser should parse. Must be a full /// translation unit. - //------------------------------------------------------------------ const char *Text() override { return m_transformed_text.c_str(); } lldb::ModuleSP GetJITModule() override; @@ -98,9 +99,9 @@ protected: std::shared_ptr<IRExecutionUnit> m_execution_unit_sp; ///< The execution unit the expression is stored in. - std::unique_ptr<Materializer> m_materializer_ap; ///< The materializer to use - ///when running the - ///expression. + std::unique_ptr<Materializer> m_materializer_up; ///< The materializer to use + /// when running the + /// expression. lldb::ModuleWP m_jit_module_wp; bool m_enforce_valid_object; ///< True if the expression parser should enforce ///the presence of a valid class pointer diff --git a/include/lldb/Expression/Materializer.h b/include/lldb/Expression/Materializer.h index 0bdfd372e9214..603b4e0066cd4 100644 --- a/include/lldb/Expression/Materializer.h +++ b/include/lldb/Expression/Materializer.h @@ -1,9 +1,8 @@ //===-- Materializer.h ------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// diff --git a/include/lldb/Expression/REPL.h b/include/lldb/Expression/REPL.h index f7780772cbeac..850d2f6f961a9 100644 --- a/include/lldb/Expression/REPL.h +++ b/include/lldb/Expression/REPL.h @@ -1,9 +1,8 @@ //===-- REPL.h --------------------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -12,17 +11,16 @@ #include <string> -#include "lldb/../../source/Commands/CommandObjectExpression.h" +#include "lldb/Core/IOHandler.h" #include "lldb/Interpreter/OptionGroupFormat.h" #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" +#include "lldb/Target/Target.h" namespace lldb_private { class REPL : public IOHandlerDelegate { public: - //---------------------------------------------------------------------- // See TypeSystem.h for how to add subclasses to this. - //---------------------------------------------------------------------- enum LLVMCastKind { eKindClang, eKindSwift, eKindGo, kNumKinds }; LLVMCastKind getKind() const { return m_kind; } @@ -31,31 +29,29 @@ public: ~REPL() override; - //------------------------------------------------------------------ /// Get a REPL with an existing target (or, failing that, a debugger to use), /// and (optional) extra arguments for the compiler. /// - /// @param[out] error + /// \param[out] error /// If this language is supported but the REPL couldn't be created, this /// error is populated with the reason. /// - /// @param[in] language + /// \param[in] language /// The language to create a REPL for. /// - /// @param[in] debugger + /// \param[in] debugger /// If provided, and target is nullptr, the debugger to use when setting /// up a top-level REPL. /// - /// @param[in] target + /// \param[in] target /// If provided, the target to put the REPL inside. /// - /// @param[in] repl_options + /// \param[in] repl_options /// If provided, additional options for the compiler when parsing REPL /// expressions. /// - /// @return + /// \return /// The range of the containing object in the target process. - //------------------------------------------------------------------ static lldb::REPLSP Create(Status &Status, lldb::LanguageType language, Debugger *debugger, Target *target, const char *repl_options); @@ -69,9 +65,8 @@ public: m_varobj_options = options; } - void - SetCommandOptions(const CommandObjectExpression::CommandOptions &options) { - m_command_options = options; + void SetEvaluateOptions(const EvaluateExpressionOptions &options) { + m_expr_options = options; } void SetCompilerOptions(const char *options) { @@ -83,10 +78,8 @@ public: Status RunLoop(); - //------------------------------------------------------------------ // IOHandler::Delegate functions - //------------------------------------------------------------------ - void IOHandlerActivated(IOHandler &io_handler) override; + void IOHandlerActivated(IOHandler &io_handler, bool interactive) override; bool IOHandlerInterrupt(IOHandler &io_handler) override; @@ -118,9 +111,7 @@ public: protected: static int CalculateActualIndentation(const StringList &lines); - //---------------------------------------------------------------------- // Subclasses should override these functions to implement a functional REPL. - //---------------------------------------------------------------------- virtual Status DoInitialization() = 0; @@ -146,7 +137,7 @@ protected: OptionGroupFormat m_format_options = OptionGroupFormat(lldb::eFormatDefault); OptionGroupValueObjectDisplay m_varobj_options; - CommandObjectExpression::CommandOptions m_command_options; + EvaluateExpressionOptions m_expr_options; std::string m_compiler_options; bool m_enable_auto_indent = true; diff --git a/include/lldb/Expression/UserExpression.h b/include/lldb/Expression/UserExpression.h index 812d7e9a0eacc..b1d52f8ddd55d 100644 --- a/include/lldb/Expression/UserExpression.h +++ b/include/lldb/Expression/UserExpression.h @@ -1,9 +1,8 @@ //===-- UserExpression.h ----------------------------------------*- C++ -*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -24,8 +23,7 @@ namespace lldb_private { -//---------------------------------------------------------------------- -/// @class UserExpression UserExpression.h "lldb/Expression/UserExpression.h" +/// \class UserExpression UserExpression.h "lldb/Expression/UserExpression.h" /// Encapsulates a one-time expression for use in lldb. /// /// LLDB uses expressions for various purposes, notably to call functions @@ -34,89 +32,86 @@ namespace lldb_private { /// JIT an expression. The actual parsing part will be provided by the specific /// implementations of UserExpression - which will be vended through the /// appropriate TypeSystem. -//---------------------------------------------------------------------- class UserExpression : public Expression { public: + /// LLVM-style RTTI support. + static bool classof(const Expression *E) { + return E->getKind() == eKindUserExpression; + } + enum { kDefaultTimeout = 500000u }; - //------------------------------------------------------------------ /// Constructor /// - /// @param[in] expr + /// \param[in] expr /// The expression to parse. /// - /// @param[in] expr_prefix + /// \param[in] expr_prefix /// If non-nullptr, a C string containing translation-unit level /// definitions to be included when the expression is parsed. /// - /// @param[in] language + /// \param[in] language /// If not eLanguageTypeUnknown, a language to use when parsing /// the expression. Currently restricted to those languages /// supported by Clang. /// - /// @param[in] desired_type + /// \param[in] desired_type /// If not eResultTypeAny, the type to use for the expression /// result. - //------------------------------------------------------------------ UserExpression(ExecutionContextScope &exe_scope, llvm::StringRef expr, llvm::StringRef prefix, lldb::LanguageType language, ResultType desired_type, - const EvaluateExpressionOptions &options); + const EvaluateExpressionOptions &options, + ExpressionKind kind); - //------------------------------------------------------------------ /// Destructor - //------------------------------------------------------------------ ~UserExpression() override; - //------------------------------------------------------------------ /// Parse the expression /// - /// @param[in] diagnostic_manager + /// \param[in] diagnostic_manager /// A diagnostic manager to report parse errors and warnings to. /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context to use when looking up entities that /// are needed for parsing (locations of functions, types of /// variables, persistent variables, etc.) /// - /// @param[in] execution_policy + /// \param[in] execution_policy /// Determines whether interpretation is possible or mandatory. /// - /// @param[in] keep_result_in_memory + /// \param[in] keep_result_in_memory /// True if the resulting persistent variable should reside in /// target memory, if applicable. /// - /// @return + /// \return /// True on success (no errors); false otherwise. - //------------------------------------------------------------------ virtual bool Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, bool generate_debug_info) = 0; - //------------------------------------------------------------------ /// Attempts to find possible command line completions for the given /// (possible incomplete) user expression. /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context to use when looking up entities that /// are needed for parsing and completing (locations of functions, types /// of variables, persistent variables, etc.) /// - /// @param[out] request + /// \param[out] request /// The completion request to fill out. The completion should be a string /// that would complete the current token at the cursor position. /// Note that the string in the list replaces the current token /// in the command line. /// - /// @param[in] complete_pos + /// \param[in] complete_pos /// The position of the cursor inside the user expression string. /// The completion process starts on the token that the cursor is in. /// - /// @return + /// \return /// True if we added any completion results to the output; /// false otherwise. - //------------------------------------------------------------------ virtual bool Complete(ExecutionContext &exe_ctx, CompletionRequest &request, unsigned complete_pos) { return false; @@ -126,105 +121,87 @@ public: bool MatchesContext(ExecutionContext &exe_ctx); - //------------------------------------------------------------------ /// Execute the parsed expression by callinng the derived class's DoExecute /// method. /// - /// @param[in] diagnostic_manager + /// \param[in] diagnostic_manager /// A diagnostic manager to report errors to. /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context to use when looking up entities that /// are needed for parsing (locations of variables, etc.) /// - /// @param[in] options + /// \param[in] options /// Expression evaluation options. /// - /// @param[in] shared_ptr_to_me + /// \param[in] shared_ptr_to_me /// This is a shared pointer to this UserExpression. This is /// needed because Execute can push a thread plan that will hold onto /// the UserExpression for an unbounded period of time. So you /// need to give the thread plan a reference to this object that can /// keep it alive. /// - /// @param[in] result + /// \param[in] result /// A pointer to direct at the persistent variable in which the /// expression's result is stored. /// - /// @return + /// \return /// A Process::Execution results value. - //------------------------------------------------------------------ lldb::ExpressionResults Execute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result); - //------------------------------------------------------------------ /// Apply the side effects of the function to program state. /// - /// @param[in] diagnostic_manager + /// \param[in] diagnostic_manager /// A diagnostic manager to report errors to. /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context to use when looking up entities that /// are needed for parsing (locations of variables, etc.) /// - /// @param[in] result + /// \param[in] result /// A pointer to direct at the persistent variable in which the /// expression's result is stored. /// - /// @param[in] function_stack_pointer + /// \param[in] function_stack_pointer /// A pointer to the base of the function's stack frame. This /// is used to determine whether the expression result resides in /// memory that will still be valid, or whether it needs to be /// treated as homeless for the purpose of future expressions. /// - /// @return + /// \return /// A Process::Execution results value. - //------------------------------------------------------------------ virtual bool FinalizeJITExecution( DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS, lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) = 0; - //------------------------------------------------------------------ /// Return the string that the parser should parse. - //------------------------------------------------------------------ const char *Text() override { return m_expr_text.c_str(); } - //------------------------------------------------------------------ /// Return the string that the user typed. - //------------------------------------------------------------------ const char *GetUserText() { return m_expr_text.c_str(); } - //------------------------------------------------------------------ /// Return the function name that should be used for executing the /// expression. Text() should contain the definition of this function. - //------------------------------------------------------------------ const char *FunctionName() override { return "$__lldb_expr"; } - //------------------------------------------------------------------ /// Return the language that should be used when parsing. To use the /// default, return eLanguageTypeUnknown. - //------------------------------------------------------------------ lldb::LanguageType Language() override { return m_language; } - //------------------------------------------------------------------ /// Return the desired result type of the function, or eResultTypeAny if /// indifferent. - //------------------------------------------------------------------ ResultType DesiredResultType() override { return m_desired_type; } - //------------------------------------------------------------------ /// Return true if validation code should be inserted into the expression. - //------------------------------------------------------------------ bool NeedsValidation() override { return true; } - //------------------------------------------------------------------ /// Return true if external variables in the expression should be resolved. - //------------------------------------------------------------------ bool NeedsVariableResolution() override { return true; } EvaluateExpressionOptions *GetOptions() override { return &m_options; } @@ -236,53 +213,58 @@ public: virtual lldb::ModuleSP GetJITModule() { return lldb::ModuleSP(); } - //------------------------------------------------------------------ /// Evaluate one expression in the scratch context of the target passed in /// the exe_ctx and return its result. /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context to use when evaluating the expression. /// - /// @param[in] options + /// \param[in] options /// Expression evaluation options. N.B. The language in the /// evaluation options will be used to determine the language used for /// expression evaluation. /// - /// @param[in] expr_cstr + /// \param[in] expr_cstr /// A C string containing the expression to be evaluated. /// - /// @param[in] expr_prefix + /// \param[in] expr_prefix /// If non-nullptr, a C string containing translation-unit level /// definitions to be included when the expression is parsed. /// - /// @param[in,out] result_valobj_sp + /// \param[in,out] result_valobj_sp /// If execution is successful, the result valobj is placed here. /// - /// @param[out] error + /// \param[out] error /// Filled in with an error in case the expression evaluation /// fails to parse, run, or evaluated. /// - /// @param[in] line_offset - /// The offset of the first line of the expression from the "beginning" of - /// a virtual source file used for error reporting and debug info. - /// - /// @param[out] fixed_expression + /// \param[out] fixed_expression /// If non-nullptr, the fixed expression is copied into the provided /// string. /// - /// @param[out] jit_module_sp_ptr + /// \param[out] jit_module_sp_ptr /// If non-nullptr, used to persist the generated IR module. /// - /// @result + /// \param[in] ctx_obj + /// If specified, then the expression will be evaluated in the context of + /// this object. It means that the context object's address will be + /// treated as `this` for the expression (the expression will be + /// evaluated as if it was inside of a method of the context object's + /// class, and its `this` parameter were pointing to the context object). + /// The parameter makes sense for class and union types only. + /// Currently there is a limitation: the context object must be located + /// in the debuggee process' memory (and have the load address). + /// + /// \result /// A Process::ExpressionResults value. eExpressionCompleted for /// success. - //------------------------------------------------------------------ static lldb::ExpressionResults Evaluate(ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, llvm::StringRef expr_cstr, llvm::StringRef expr_prefix, lldb::ValueObjectSP &result_valobj_sp, Status &error, - uint32_t line_offset = 0, std::string *fixed_expression = nullptr, - lldb::ModuleSP *jit_module_sp_ptr = nullptr); + std::string *fixed_expression = nullptr, + lldb::ModuleSP *jit_module_sp_ptr = nullptr, + ValueObject *ctx_obj = nullptr); static const Status::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result @@ -304,10 +286,8 @@ protected: static lldb::addr_t GetObjectPointer(lldb::StackFrameSP frame_sp, ConstString &object_name, Status &err); - //------------------------------------------------------------------ /// Populate m_in_cplusplus_method and m_in_objectivec_method based on the /// environment. - //------------------------------------------------------------------ void InstallContext(ExecutionContext &exe_ctx); diff --git a/include/lldb/Expression/UtilityFunction.h b/include/lldb/Expression/UtilityFunction.h index 4c87f4d104796..26da081ddced0 100644 --- a/include/lldb/Expression/UtilityFunction.h +++ b/include/lldb/Expression/UtilityFunction.h @@ -1,10 +1,9 @@ //===-- UtilityFunction.h ----------------------------------------*- C++ //-*-===// // -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// @@ -20,8 +19,7 @@ namespace lldb_private { -//---------------------------------------------------------------------- -/// @class UtilityFunction UtilityFunction.h +/// \class UtilityFunction UtilityFunction.h /// "lldb/Expression/UtilityFunction.h" Encapsulates a bit of source code that /// provides a function that is callable /// @@ -29,83 +27,71 @@ namespace lldb_private { /// and as a backend for the expr command. UtilityFunction encapsulates a /// self-contained function meant to be used from other code. Utility /// functions can perform error-checking for ClangUserExpressions, -//---------------------------------------------------------------------- class UtilityFunction : public Expression { public: - //------------------------------------------------------------------ + /// LLVM-style RTTI support. + static bool classof(const Expression *E) { + return E->getKind() == eKindUtilityFunction; + } + /// Constructor /// - /// @param[in] text + /// \param[in] text /// The text of the function. Must be a full translation unit. /// - /// @param[in] name + /// \param[in] name /// The name of the function, as used in the text. - //------------------------------------------------------------------ UtilityFunction(ExecutionContextScope &exe_scope, const char *text, - const char *name); + const char *name, ExpressionKind kind); ~UtilityFunction() override; - //------------------------------------------------------------------ /// Install the utility function into a process /// - /// @param[in] diagnostic_manager + /// \param[in] diagnostic_manager /// A diagnostic manager to print parse errors and warnings to. /// - /// @param[in] exe_ctx + /// \param[in] exe_ctx /// The execution context to install the utility function to. /// - /// @return + /// \return /// True on success (no errors); false otherwise. - //------------------------------------------------------------------ virtual bool Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) = 0; - //------------------------------------------------------------------ /// Check whether the given PC is inside the function /// /// Especially useful if the function dereferences nullptr to indicate a /// failed assert. /// - /// @param[in] pc + /// \param[in] pc /// The program counter to check. /// - /// @return + /// \return /// True if the program counter falls within the function's bounds; /// false if not (or the function is not JIT compiled) - //------------------------------------------------------------------ bool ContainsAddress(lldb::addr_t address) { // nothing is both >= LLDB_INVALID_ADDRESS and < LLDB_INVALID_ADDRESS, so // this always returns false if the function is not JIT compiled yet return (address >= m_jit_start_addr && address < m_jit_end_addr); } - //------------------------------------------------------------------ /// Return the string that the parser should parse. Must be a full /// translation unit. - //------------------------------------------------------------------ const char *Text() override { return m_function_text.c_str(); } - //------------------------------------------------------------------ /// Return the function name that should be used for executing the /// expression. Text() should contain the definition of this function. - //------------------------------------------------------------------ const char *FunctionName() override { return m_function_name.c_str(); } - //------------------------------------------------------------------ /// Return the object that the parser should use when registering local /// variables. May be nullptr if the Expression doesn't care. - //------------------------------------------------------------------ ExpressionVariableList *LocalVariables() { return nullptr; } - //------------------------------------------------------------------ /// Return true if validation code should be inserted into the expression. - //------------------------------------------------------------------ bool NeedsValidation() override { return false; } - //------------------------------------------------------------------ /// Return true if external variables in the expression should be resolved. - //------------------------------------------------------------------ bool NeedsVariableResolution() override { return false; } // This makes the function caller function. Pass in the ThreadSP if you have |