diff options
Diffstat (limited to 'include/lldb/Expression')
-rw-r--r-- | include/lldb/Expression/DWARFExpression.h | 15 | ||||
-rw-r--r-- | include/lldb/Expression/DiagnosticManager.h | 212 | ||||
-rw-r--r-- | include/lldb/Expression/ExpressionParser.h | 23 | ||||
-rw-r--r-- | include/lldb/Expression/ExpressionSourceCode.h | 9 | ||||
-rw-r--r-- | include/lldb/Expression/ExpressionVariable.h | 13 | ||||
-rw-r--r-- | include/lldb/Expression/FunctionCaller.h | 84 | ||||
-rw-r--r-- | include/lldb/Expression/IRDynamicChecks.h | 15 | ||||
-rw-r--r-- | include/lldb/Expression/IRExecutionUnit.h | 170 | ||||
-rw-r--r-- | include/lldb/Expression/IRInterpreter.h | 2 | ||||
-rw-r--r-- | include/lldb/Expression/IRMemoryMap.h | 2 | ||||
-rw-r--r-- | include/lldb/Expression/LLVMUserExpression.h | 60 | ||||
-rw-r--r-- | include/lldb/Expression/UserExpression.h | 54 | ||||
-rw-r--r-- | include/lldb/Expression/UtilityFunction.h | 12 |
13 files changed, 517 insertions, 154 deletions
diff --git a/include/lldb/Expression/DWARFExpression.h b/include/lldb/Expression/DWARFExpression.h index 3527c3b4b153c..d984a419c5c92 100644 --- a/include/lldb/Expression/DWARFExpression.h +++ b/include/lldb/Expression/DWARFExpression.h @@ -10,11 +10,12 @@ #ifndef liblldb_DWARFExpression_h_ #define liblldb_DWARFExpression_h_ -#include "lldb/lldb-private.h" #include "lldb/Core/Address.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" #include "lldb/Core/Scalar.h" +#include "lldb/lldb-private.h" +#include <functional> class DWARFCompileUnit; @@ -166,7 +167,14 @@ public: bool Update_DW_OP_addr (lldb::addr_t file_addr); - + + bool + ContainsThreadLocalStorage() const; + + bool + LinkThreadLocalStorage(lldb::ModuleSP new_module_sp, + 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 @@ -282,6 +290,7 @@ public: ClangExpressionDeclMap *decl_map, lldb::addr_t loclist_base_load_addr, const Value* initial_value_ptr, + const Value* object_address_ptr, Value& result, Error *error_ptr) const; @@ -296,6 +305,7 @@ public: RegisterContext *reg_ctx, lldb::addr_t loclist_base_load_addr, const Value* initial_value_ptr, + const Value* object_address_ptr, Value& result, Error *error_ptr) const; @@ -370,6 +380,7 @@ public: const lldb::offset_t length, const lldb::RegisterKind reg_set, const Value* initial_value_ptr, + const Value* object_address_ptr, Value& result, Error *error_ptr); diff --git a/include/lldb/Expression/DiagnosticManager.h b/include/lldb/Expression/DiagnosticManager.h new file mode 100644 index 0000000000000..c294bdecf2b24 --- /dev/null +++ b/include/lldb/Expression/DiagnosticManager.h @@ -0,0 +1,212 @@ +//===-- DiagnosticManager.h -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef lldb_DiagnosticManager_h +#define lldb_DiagnosticManager_h + +#include "lldb/lldb-defines.h" +#include "lldb/lldb-types.h" + +#include <string> +#include <vector> + +namespace lldb_private +{ + +enum DiagnosticOrigin +{ + eDiagnosticOriginUnknown = 0, + eDiagnosticOriginLLDB, + eDiagnosticOriginClang, + eDiagnosticOriginGo, + eDiagnosticOriginSwift, + eDiagnosticOriginLLVM +}; + +enum DiagnosticSeverity +{ + eDiagnosticSeverityError, + eDiagnosticSeverityWarning, + eDiagnosticSeverityRemark +}; + +const uint32_t LLDB_INVALID_COMPILER_ID = UINT32_MAX; + +class Diagnostic +{ +friend class DiagnosticManager; + +public: + DiagnosticOrigin getKind() const { return m_origin; } + + static bool classof(const Diagnostic *diag) + { + DiagnosticOrigin kind = diag->getKind(); + switch (kind) + { + case eDiagnosticOriginUnknown: + case eDiagnosticOriginLLDB: + case eDiagnosticOriginGo: + case eDiagnosticOriginLLVM: + return true; + case eDiagnosticOriginClang: + case eDiagnosticOriginSwift: + return false; + } + } + + Diagnostic(const char *message, DiagnosticSeverity severity, DiagnosticOrigin origin, uint32_t compiler_id) : + m_message(message), + m_severity(severity), + m_origin(origin), + m_compiler_id(compiler_id) + { + } + + Diagnostic(const Diagnostic &rhs) : + m_message(rhs.m_message), + m_severity(rhs.m_severity), + m_origin(rhs.m_origin), + m_compiler_id(rhs.m_compiler_id) + { + } + + virtual ~Diagnostic() = default; + + virtual bool HasFixIts () const { return false; } + + DiagnosticSeverity + GetSeverity() const + { + return m_severity; + } + + uint32_t + GetCompilerID() const + { + return m_compiler_id; + } + + const char * + GetMessage() const + { + return m_message.c_str(); + } + + void AppendMessage(const char *message, bool precede_with_newline = true) + { + if (precede_with_newline) + m_message.push_back('\n'); + m_message.append(message); + } + +protected: + std::string m_message; + DiagnosticSeverity m_severity; + DiagnosticOrigin m_origin; + uint32_t m_compiler_id; // Compiler-specific diagnostic ID +}; + +typedef std::vector<Diagnostic *> DiagnosticList; + +class DiagnosticManager +{ +public: + void + Clear() + { + m_diagnostics.clear(); + m_fixed_expression.clear(); + } + + // The diagnostic manager holds a list of diagnostics, which are owned by the manager. + const DiagnosticList & + Diagnostics() + { + return m_diagnostics; + } + + ~DiagnosticManager() + { + for (Diagnostic *diag : m_diagnostics) + { + delete diag; + } + } + + bool + HasFixIts() + { + for (Diagnostic *diag : m_diagnostics) + { + if (diag->HasFixIts()) + return true; + } + return false; + } + + void + AddDiagnostic(const char *message, DiagnosticSeverity severity, DiagnosticOrigin origin, + uint32_t compiler_id = LLDB_INVALID_COMPILER_ID) + { + m_diagnostics.push_back(new Diagnostic(message, severity, origin, compiler_id)); + } + + void + AddDiagnostic(Diagnostic *diagnostic) + { + m_diagnostics.push_back(diagnostic); + } + + size_t + Printf(DiagnosticSeverity severity, const char *format, ...) __attribute__((format(printf, 3, 4))); + size_t + PutCString(DiagnosticSeverity severity, const char *cstr); + + void + AppendMessageToDiagnostic(const char *cstr) + { + if (m_diagnostics.size()) + { + m_diagnostics.back()->AppendMessage(cstr); + } + } + + // Returns a string containing errors in this format: + // + // "error: error text\n + // warning: warning text\n + // remark text\n" + std::string + GetString(char separator = '\n'); + + void + Dump(Log *log); + + const std::string & + GetFixedExpression() + { + return m_fixed_expression; + } + + // Moves fixed_expression to the internal storage. + void + SetFixedExpression(std::string fixed_expression) + { + m_fixed_expression = std::move(fixed_expression); + fixed_expression.clear(); + } + +protected: + DiagnosticList m_diagnostics; + std::string m_fixed_expression; +}; +} + +#endif /* lldb_DiagnosticManager_h */ diff --git a/include/lldb/Expression/ExpressionParser.h b/include/lldb/Expression/ExpressionParser.h index 49333e79bf5ec..323e515e3bba1 100644 --- a/include/lldb/Expression/ExpressionParser.h +++ b/include/lldb/Expression/ExpressionParser.h @@ -57,17 +57,34 @@ public: /// Parse a single expression and convert it to IR using Clang. Don't /// wrap the expression in anything at all. /// - /// @param[in] stream - /// The stream to print errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager in which to store the errors and warnings. /// /// @return /// The number of errors encountered during parsing. 0 means /// success. //------------------------------------------------------------------ virtual unsigned - Parse (Stream &stream) = 0; + 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 + /// The diagnostic manager containing fixit's to apply. + /// + /// @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. /// diff --git a/include/lldb/Expression/ExpressionSourceCode.h b/include/lldb/Expression/ExpressionSourceCode.h index 2dd09378fcd2f..33ceade455582 100644 --- a/include/lldb/Expression/ExpressionSourceCode.h +++ b/include/lldb/Expression/ExpressionSourceCode.h @@ -54,10 +54,17 @@ public: bool GetText (std::string &text, lldb::LanguageType wrapping_language, - bool const_object, 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: ExpressionSourceCode (const char *name, const char *prefix, diff --git a/include/lldb/Expression/ExpressionVariable.h b/include/lldb/Expression/ExpressionVariable.h index d8030ba1c2579..451acb685bb7e 100644 --- a/include/lldb/Expression/ExpressionVariable.h +++ b/include/lldb/Expression/ExpressionVariable.h @@ -16,6 +16,8 @@ #include <vector> // Other libraries and framework includes +#include "llvm/ADT/DenseMap.h" + // Project includes #include "lldb/lldb-public.h" #include "lldb/Core/ConstString.h" @@ -309,10 +311,19 @@ public: RemovePersistentVariable (lldb::ExpressionVariableSP variable) = 0; virtual lldb::addr_t - LookupSymbol (const ConstString &name) = 0; + LookupSymbol (const ConstString &name); + + void + RegisterExecutionUnit (lldb::IRExecutionUnitSP &execution_unit_sp); private: LLVMCastKind m_kind; + + typedef std::set<lldb::IRExecutionUnitSP> ExecutionUnitSet; + ExecutionUnitSet m_execution_units; ///< The execution units that contain valuable symbols. + + typedef llvm::DenseMap<const char *, lldb::addr_t> SymbolMap; + SymbolMap m_symbol_map; ///< The addresses of the symbols in m_execution_units. }; } // namespace lldb_private diff --git a/include/lldb/Expression/FunctionCaller.h b/include/lldb/Expression/FunctionCaller.h index c9a45811670fe..3848073c654f4 100644 --- a/include/lldb/Expression/FunctionCaller.h +++ b/include/lldb/Expression/FunctionCaller.h @@ -99,17 +99,23 @@ public: //------------------------------------------------------------------ /// Compile the wrapper function /// - /// @param[in] errors - /// The stream to print parser errors to. + /// @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 + /// The diagnostic manager to report parser errors to. /// /// @return /// The number of errors. //------------------------------------------------------------------ virtual unsigned - CompileFunction (Stream &errors) = 0; - + CompileFunction (lldb::ThreadSP thread_to_use_sp, + DiagnosticManager &diagnostic_manager) = 0; + //------------------------------------------------------------------ - /// Insert the default function wrapper and its default argument struct + /// Insert the default function wrapper and its default argument struct /// /// @param[in] exe_ctx /// The execution context to insert the function and its arguments @@ -120,16 +126,14 @@ public: /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated /// and args_addr_ref is pointed to it. /// - /// @param[in] errors - /// The stream to write errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. /// /// @return /// True on success; false otherwise. //------------------------------------------------------------------ bool - InsertFunction (ExecutionContext &exe_ctx, - lldb::addr_t &args_addr_ref, - Stream &errors); + InsertFunction(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, DiagnosticManager &diagnostic_manager); //------------------------------------------------------------------ /// Insert the default function wrapper (using the JIT) @@ -138,17 +142,17 @@ public: /// The execution context to insert the function and its arguments /// into. /// - /// @param[in] errors - /// The stream to write errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. /// /// @return /// True on success; false otherwise. //------------------------------------------------------------------ - bool WriteFunctionWrapper (ExecutionContext &exe_ctx, - Stream &errors); - + bool + WriteFunctionWrapper(ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager); + //------------------------------------------------------------------ - /// Insert the default function argument struct + /// Insert the default function argument struct /// /// @param[in] exe_ctx /// The execution context to insert the function and its arguments @@ -159,16 +163,16 @@ public: /// be LLDB_INVALID_ADDRESS; if it is, a new structure is allocated /// and args_addr_ref is pointed to it. /// - /// @param[in] errors - /// The stream to write errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. /// /// @return /// True on success; false otherwise. //------------------------------------------------------------------ - bool WriteFunctionArguments (ExecutionContext &exe_ctx, - lldb::addr_t &args_addr_ref, - Stream &errors); - + 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 @@ -185,16 +189,15 @@ public: /// @param[in] arg_values /// The values of the function's arguments. /// - /// @param[in] errors - /// The stream to write errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. /// /// @return /// True on success; false otherwise. //------------------------------------------------------------------ - bool WriteFunctionArguments (ExecutionContext &exe_ctx, - lldb::addr_t &args_addr_ref, - ValueList &arg_values, - Stream &errors); + 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. @@ -211,8 +214,8 @@ public: /// for deallocating it. And if passed in with a value other than LLDB_INVALID_ADDRESS, /// this should point to an already allocated structure with the values already written. /// - /// @param[in] errors - /// Errors will be written here if there are any. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. /// /// @param[in] options /// The options for this expression execution. @@ -224,12 +227,9 @@ public: /// 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, - Stream &errors, - Value &results); - + 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. /// @@ -243,8 +243,8 @@ public: /// @param[in] args_addr /// The address of the argument struct. /// - /// @param[in] errors - /// The stream to write errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report errors to. /// /// @param[in] stop_others /// True if other threads should pause during execution. @@ -256,11 +256,9 @@ public: /// A ThreadPlan shared pointer for executing the function. //------------------------------------------------------------------ lldb::ThreadPlanSP - GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, - lldb::addr_t args_addr, - const EvaluateExpressionOptions &options, - Stream &errors); - + GetThreadPlanToCallFunction(ExecutionContext &exe_ctx, lldb::addr_t args_addr, + const EvaluateExpressionOptions &options, DiagnosticManager &diagnostic_manager); + //------------------------------------------------------------------ /// Get the result of the function from its struct /// diff --git a/include/lldb/Expression/IRDynamicChecks.h b/include/lldb/Expression/IRDynamicChecks.h index ef77d55f4b340..9f31a6eb01d63 100644 --- a/include/lldb/Expression/IRDynamicChecks.h +++ b/include/lldb/Expression/IRDynamicChecks.h @@ -61,8 +61,8 @@ public: /// Install the utility functions into a process. This binds the /// instance of DynamicCheckerFunctions to that process. /// - /// @param[in] error_stream - /// A stream to print errors on. + /// @param[in] diagnostic_manager + /// A diagnostic manager to report errors to. /// /// @param[in] exe_ctx /// The execution context to install the functions into. @@ -71,11 +71,12 @@ public: /// True on success; false on failure, or if the functions have /// already been installed. //------------------------------------------------------------------ - bool Install (Stream &error_stream, - ExecutionContext &exe_ctx); - - bool DoCheckersExplainStop (lldb::addr_t addr, Stream &message); - + 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; }; diff --git a/include/lldb/Expression/IRExecutionUnit.h b/include/lldb/Expression/IRExecutionUnit.h index 86744b7b9726e..d557a35d0b065 100644 --- a/include/lldb/Expression/IRExecutionUnit.h +++ b/include/lldb/Expression/IRExecutionUnit.h @@ -26,8 +26,8 @@ #include "lldb/lldb-private.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Expression/IRMemoryMap.h" -#include "lldb/Host/Mutex.h" #include "lldb/Symbol/ObjectFile.h" +#include "lldb/Symbol/SymbolContext.h" namespace llvm { @@ -71,13 +71,19 @@ public: std::unique_ptr<llvm::Module> &module_ap, 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; + } + llvm::Module * GetModule() { @@ -131,7 +137,83 @@ public: lldb::ModuleSP GetJITModule (); + + lldb::addr_t + FindSymbol(const ConstString &name); + void + GetStaticInitializers(std::vector <lldb::addr_t> &static_initializers); + + //---------------------------------------------------------------------- + /// @class JittedFunction IRExecutionUnit.h "lldb/Expression/IRExecutionUnit.h" + /// @brief 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 + /// The name of the function. + /// + /// @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 + /// 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) : + m_name (name), + m_local_addr (local_addr), + m_remote_addr (remote_addr) + { + } + }; + + struct JittedFunction : JittedEntity + { + bool m_external; + JittedFunction (const char *name, + bool external, + lldb::addr_t local_addr = LLDB_INVALID_ADDRESS, + lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) : + JittedEntity (name, local_addr, remote_addr), + m_external(external) + {} + }; + + struct JittedGlobalVariable : JittedEntity + { + JittedGlobalVariable (const char *name, + lldb::addr_t local_addr = LLDB_INVALID_ADDRESS, + lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) : + JittedEntity (name, local_addr, remote_addr) + {} + }; + + const std::vector<JittedFunction> &GetJittedFunctions() + { + return m_jitted_functions; + } + + const std::vector<JittedGlobalVariable> &GetJittedGlobalVariables() + { + return m_jitted_global_variables; + } + private: //------------------------------------------------------------------ /// Look up the object in m_address_map that contains a given address, @@ -201,6 +283,33 @@ private: DisassembleFunction (Stream &stream, lldb::ProcessSP &process_sp); + struct SearchSpec; + + void + CollectCandidateCNames(std::vector<SearchSpec> &C_specs, + const ConstString &name); + + void + CollectCandidateCPlusPlusNames(std::vector<SearchSpec> &CPP_specs, + const std::vector<SearchSpec> &C_specs, + const SymbolContext &sc); + + void + CollectFallbackNames(std::vector<SearchSpec> &fallback_specs, + const std::vector<SearchSpec> &C_specs); + + lldb::addr_t + FindInSymbols(const std::vector<SearchSpec> &specs, + const lldb_private::SymbolContext &sc); + + lldb::addr_t + FindInRuntimes(const std::vector<SearchSpec> &specs, + const lldb_private::SymbolContext &sc); + + lldb::addr_t + FindInUserDefinedSymbols(const std::vector<SearchSpec> &specs, + const lldb_private::SymbolContext &sc); + void ReportSymbolLookupError(const ConstString &name); @@ -275,9 +384,6 @@ private: void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, size_t Size) override { } - //------------------------------------------------------------------ - /// Passthrough interface stub - //------------------------------------------------------------------ uint64_t getSymbolAddress(const std::string &Name) override; void *getPointerToNamedFunction(const std::string &Name, @@ -288,45 +394,6 @@ private: IRExecutionUnit &m_parent; ///< The execution unit this is a proxy for. }; - //---------------------------------------------------------------------- - /// @class JittedFunction IRExecutionUnit.h "lldb/Expression/IRExecutionUnit.h" - /// @brief 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 JittedFunction { - std::string 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 variables. - /// - /// @param[in] name - /// The name of the function. - /// - /// @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 - /// The address of the function in the target, or LLDB_INVALID_ADDRESS - /// if it is not present in the target's memory. - //------------------------------------------------------------------ - JittedFunction (const char *name, - lldb::addr_t local_addr = LLDB_INVALID_ADDRESS, - lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) : - m_name (name), - m_local_addr (local_addr), - m_remote_addr (remote_addr) - { - } - }; - static const unsigned eSectionIDInvalid = (unsigned)-1; //---------------------------------------------------------------------- @@ -377,6 +444,9 @@ private: void dump (Log *log); }; + bool + CommitOneAllocation (lldb::ProcessSP &process_sp, Error &error, AllocationRecord &record); + typedef std::vector<AllocationRecord> RecordVector; RecordVector m_records; @@ -385,14 +455,24 @@ private: std::unique_ptr<llvm::Module> m_module_ap; ///< 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; - llvm::SmallVector<JittedFunction, 1> m_jitted_functions; ///< A vector of all functions that have been JITted into machine code + std::vector<JittedFunction> m_jitted_functions; ///< A vector of all functions that have been JITted into machine code + std::vector<JittedGlobalVariable> m_jitted_global_variables; ///< A vector of all functions that have been JITted into machine code const ConstString m_name; + SymbolContext m_sym_ctx; ///< Used for symbol lookups std::vector<ConstString> m_failed_lookups; std::atomic<bool> m_did_jit; lldb::addr_t m_function_load_addr; lldb::addr_t m_function_end_load_addr; + + bool m_strip_underscore; ///< True for platforms where global symbols have a _ prefix + bool m_reported_allocations; ///< True after allocations have been reported. It is possible that + ///< sections will be allocated when this is true, in which case they weren't + ///< depended on by any function. (Top-level code defining a variable, but + ///< defining no functions using that variable, would do this.) If this + ///< is true, any allocations need to be committed immediately -- no + ///< opportunity for relocation. }; } // namespace lldb_private diff --git a/include/lldb/Expression/IRInterpreter.h b/include/lldb/Expression/IRInterpreter.h index 4eb81bc68d19d..14c145b91c264 100644 --- a/include/lldb/Expression/IRInterpreter.h +++ b/include/lldb/Expression/IRInterpreter.h @@ -50,7 +50,7 @@ public: Interpret (llvm::Module &module, llvm::Function &function, llvm::ArrayRef<lldb::addr_t> args, - lldb_private::IRMemoryMap &memory_map, + lldb_private::IRExecutionUnit &execution_unit, lldb_private::Error &error, lldb::addr_t stack_frame_bottom, lldb::addr_t stack_frame_top, diff --git a/include/lldb/Expression/IRMemoryMap.h b/include/lldb/Expression/IRMemoryMap.h index 6fb718a341f7c..36631d25a742d 100644 --- a/include/lldb/Expression/IRMemoryMap.h +++ b/include/lldb/Expression/IRMemoryMap.h @@ -129,7 +129,7 @@ private: typedef std::map<lldb::addr_t, Allocation> AllocationMap; AllocationMap m_allocations; - lldb::addr_t FindSpace (size_t size, bool zero_memory = false); + lldb::addr_t FindSpace (size_t size); bool ContainsHostOnlyAllocations (); AllocationMap::iterator FindAllocation (lldb::addr_t addr, size_t size); diff --git a/include/lldb/Expression/LLVMUserExpression.h b/include/lldb/Expression/LLVMUserExpression.h index e3d17986f4b38..3762fa11ddbd7 100644 --- a/include/lldb/Expression/LLVMUserExpression.h +++ b/include/lldb/Expression/LLVMUserExpression.h @@ -16,6 +16,9 @@ #include <map> #include <vector> +// Other libraries and framework includes +#include "llvm/IR/LegacyPassManager.h" + // Project includes #include "lldb/Expression/UserExpression.h" @@ -34,26 +37,28 @@ namespace lldb_private //---------------------------------------------------------------------- class LLVMUserExpression : public UserExpression { - public: - LLVMUserExpression(ExecutionContextScope &exe_scope, - const char *expr, - const char *expr_prefix, - lldb::LanguageType language, - ResultType desired_type, +public: + // 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 + // fixups and inserts instrumentation code/pointer checks. LatePasses are run after the module has been processed by + // llvm, before the module is assembled and run in the ThreadPlan. + struct IRPasses + { + IRPasses() : EarlyPasses(nullptr), LatePasses(nullptr){}; + std::shared_ptr<llvm::legacy::PassManager> EarlyPasses; + std::shared_ptr<llvm::legacy::PassManager> LatePasses; + }; + + LLVMUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix, + lldb::LanguageType language, ResultType desired_type, const EvaluateExpressionOptions &options); ~LLVMUserExpression() override; - lldb::ExpressionResults Execute(Stream &error_stream, - ExecutionContext &exe_ctx, - const EvaluateExpressionOptions &options, - lldb::UserExpressionSP &shared_ptr_to_me, - lldb::ExpressionVariableSP &result) override; - - bool FinalizeJITExecution(Stream &error_stream, - ExecutionContext &exe_ctx, - lldb::ExpressionVariableSP &result, - lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS, - lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS) override; + 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) override; bool CanInterpret() override @@ -73,17 +78,22 @@ class LLVMUserExpression : public UserExpression lldb::ModuleSP GetJITModule() override; - protected: - virtual void ScanContext(ExecutionContext &exe_ctx, lldb_private::Error &err) = 0; +protected: + lldb::ExpressionResults + DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, + lldb::ExpressionVariableSP &result) override; - bool PrepareToExecuteJITExpression(Stream &error_stream, ExecutionContext &exe_ctx, lldb::addr_t &struct_address); + virtual void + ScanContext(ExecutionContext &exe_ctx, lldb_private::Error &err) = 0; - virtual bool - AddArguments (ExecutionContext &exe_ctx, - std::vector<lldb::addr_t> &args, - lldb::addr_t struct_address, - Stream &error_stream) = 0; + bool + PrepareToExecuteJITExpression(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + lldb::addr_t &struct_address); + virtual bool + AddArguments(ExecutionContext &exe_ctx, std::vector<lldb::addr_t> &args, lldb::addr_t struct_address, + DiagnosticManager &diagnostic_manager) = 0; lldb::addr_t m_stack_frame_bottom; ///< The bottom of the allocated stack frame. lldb::addr_t m_stack_frame_top; ///< The top of the allocated stack frame. diff --git a/include/lldb/Expression/UserExpression.h b/include/lldb/Expression/UserExpression.h index 517dfcd1dc474..2b685dc046c79 100644 --- a/include/lldb/Expression/UserExpression.h +++ b/include/lldb/Expression/UserExpression.h @@ -79,8 +79,8 @@ public: //------------------------------------------------------------------ /// Parse the expression /// - /// @param[in] error_stream - /// A stream to print parse errors and warnings to. + /// @param[in] diagnostic_manager + /// A diagnostic manager to report parse errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to use when looking up entities that @@ -98,11 +98,8 @@ public: /// True on success (no errors); false otherwise. //------------------------------------------------------------------ virtual bool - Parse (Stream &error_stream, - ExecutionContext &exe_ctx, - lldb_private::ExecutionPolicy execution_policy, - bool keep_result_in_memory, - bool generate_debug_info) = 0; + Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, bool generate_debug_info) = 0; virtual bool CanInterpret() = 0; @@ -110,10 +107,11 @@ public: MatchesContext (ExecutionContext &exe_ctx); //------------------------------------------------------------------ - /// Execute the parsed expression + /// Execute the parsed expression by callinng the derived class's + /// DoExecute method. /// - /// @param[in] error_stream - /// A stream to print errors to. + /// @param[in] diagnostic_manager + /// A diagnostic manager to report errors to. /// /// @param[in] exe_ctx /// The execution context to use when looking up entities that @@ -136,16 +134,15 @@ public: /// @return /// A Process::Execution results value. //------------------------------------------------------------------ - virtual lldb::ExpressionResults Execute(Stream &error_stream, ExecutionContext &exe_ctx, - const EvaluateExpressionOptions &options, - lldb::UserExpressionSP &shared_ptr_to_me, - lldb::ExpressionVariableSP &result) = 0; + 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] error_stream - /// A stream to print errors to. + /// @param[in] diagnostic_manager + /// A diagnostic manager to report errors to. /// /// @param[in] exe_ctx /// The execution context to use when looking up entities that @@ -164,10 +161,10 @@ public: /// @return /// A Process::Execution results value. //------------------------------------------------------------------ - virtual bool FinalizeJITExecution(Stream &error_stream, 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; + 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. @@ -285,6 +282,9 @@ public: /// @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 + /// If non-nullptr, the fixed expression is copied into the provided string. + /// /// @param[out] jit_module_sp_ptr /// If non-nullptr, used to persist the generated IR module. /// @@ -299,11 +299,24 @@ public: lldb::ValueObjectSP &result_valobj_sp, Error &error, uint32_t line_offset = 0, + std::string *fixed_expression = nullptr, lldb::ModuleSP *jit_module_sp_ptr = nullptr); static const Error::ValueType kNoResult = 0x1001; ///< ValueObject::GetError() returns this if there is no result from the expression. + + const char * + GetFixedText() + { + if (m_fixed_text.empty()) + return nullptr; + return m_fixed_text.c_str(); + } protected: + virtual lldb::ExpressionResults + DoExecute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, + lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) = 0; + static lldb::addr_t GetObjectPointer (lldb::StackFrameSP frame_sp, ConstString &object_name, @@ -325,6 +338,7 @@ protected: Address m_address; ///< The address the process is stopped in. std::string m_expr_text; ///< The text of the expression, as typed by the user std::string m_expr_prefix; ///< The text of the translation-level definitions, as provided by the user + std::string m_fixed_text; ///< The text of the expression with fix-its applied - this won't be set if the fixed text doesn't parse. lldb::LanguageType m_language; ///< The language to use when parsing (eLanguageTypeUnknown means use defaults) ResultType m_desired_type; ///< The type to coerce the expression's result to. If eResultTypeAny, inferred from the expression. EvaluateExpressionOptions m_options; ///< Additional options provided by the user. diff --git a/include/lldb/Expression/UtilityFunction.h b/include/lldb/Expression/UtilityFunction.h index bee83d8111e41..a78972082c52d 100644 --- a/include/lldb/Expression/UtilityFunction.h +++ b/include/lldb/Expression/UtilityFunction.h @@ -54,8 +54,8 @@ public: //------------------------------------------------------------------ /// Install the utility function into a process /// - /// @param[in] error_stream - /// A stream to print parse errors and warnings to. + /// @param[in] diagnostic_manager + /// A diagnostic manager to print parse errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to install the utility function to. @@ -64,8 +64,8 @@ public: /// True on success (no errors); false otherwise. //------------------------------------------------------------------ virtual bool - Install (Stream &error_stream, ExecutionContext &exe_ctx) = 0; - + Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) = 0; + //------------------------------------------------------------------ /// Check whether the given PC is inside the function /// @@ -139,8 +139,10 @@ public: } // This makes the function caller function. + // Pass in the ThreadSP if you have one available, compilation can end up calling code (e.g. to look up indirect + // functions) and we don't want this to wander onto another thread. FunctionCaller * - MakeFunctionCaller(const CompilerType &return_type, const ValueList &arg_value_list, Error &error); + MakeFunctionCaller(const CompilerType &return_type, const ValueList &arg_value_list, lldb::ThreadSP compilation_thread, Error &error); // This one retrieves the function caller that is already made. If you haven't made it yet, this returns nullptr FunctionCaller * |