Index: include/lldb/Expression/DiagnosticManager.h =================================================================== --- include/lldb/Expression/DiagnosticManager.h +++ include/lldb/Expression/DiagnosticManager.h @@ -0,0 +1,103 @@ +//===-- 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-types.h" + +#include +#include + +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; + +struct Diagnostic +{ + std::string message; + uint32_t origin; // from DiagnosticOrigin + uint32_t compiler_id; // Compiler-specific diagnostic ID + DiagnosticSeverity severity; +}; + +typedef std::vector DiagnosticList; + +class DiagnosticManager +{ +public: + void + Clear() + { + m_diagnostics.clear(); + } + + const DiagnosticList & + Diagnostics() + { + return m_diagnostics; + } + + void + AddDiagnostic(const char *message, DiagnosticSeverity severity, DiagnosticOrigin origin, + uint32_t compiler_id = LLDB_INVALID_COMPILER_ID) + { + m_diagnostics.push_back({std::string(message), origin, compiler_id, severity}); + } + + 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().message.push_back('\n'); + m_diagnostics.back().message.append(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); + +private: + DiagnosticList m_diagnostics; +}; +} + +#endif /* lldb_DiagnosticManager_h */ Index: include/lldb/Expression/ExpressionParser.h =================================================================== --- include/lldb/Expression/ExpressionParser.h +++ include/lldb/Expression/ExpressionParser.h @@ -57,7 +57,7 @@ /// Parse a single expression and convert it to IR using Clang. Don't /// wrap the expression in anything at all. /// - /// @param[in] stream + /// @param[in] diagnostic_manager /// The stream to print errors to. /// /// @return @@ -65,8 +65,8 @@ /// success. //------------------------------------------------------------------ virtual unsigned - Parse (Stream &stream) = 0; - + Parse(DiagnosticManager &diagnostic_manager) = 0; + //------------------------------------------------------------------ /// Ready an already-parsed expression for execution, possibly /// evaluating it statically. Index: include/lldb/Expression/FunctionCaller.h =================================================================== --- include/lldb/Expression/FunctionCaller.h +++ include/lldb/Expression/FunctionCaller.h @@ -99,17 +99,17 @@ //------------------------------------------------------------------ /// Compile the wrapper function /// - /// @param[in] errors - /// The stream to print parser errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report parser errors to. /// /// @return /// The number of errors. //------------------------------------------------------------------ virtual unsigned - CompileFunction (Stream &errors) = 0; - + CompileFunction(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 +120,14 @@ /// 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 +136,17 @@ /// 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 +157,16 @@ /// 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 +183,15 @@ /// @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 +208,8 @@ /// 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 +221,9 @@ /// 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 +237,8 @@ /// @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 +250,9 @@ /// 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 /// Index: include/lldb/Expression/IRDynamicChecks.h =================================================================== --- include/lldb/Expression/IRDynamicChecks.h +++ include/lldb/Expression/IRDynamicChecks.h @@ -61,8 +61,8 @@ /// 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 @@ /// 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 m_valid_pointer_check; std::unique_ptr m_objc_object_check; }; Index: include/lldb/Expression/LLVMUserExpression.h =================================================================== --- include/lldb/Expression/LLVMUserExpression.h +++ include/lldb/Expression/LLVMUserExpression.h @@ -35,30 +35,26 @@ class LLVMUserExpression : public UserExpression { public: - LLVMUserExpression(ExecutionContextScope &exe_scope, - const char *expr, - const char *expr_prefix, - lldb::LanguageType language, - ResultType desired_type, - const EvaluateExpressionOptions &options); - ~LLVMUserExpression() override; + 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; + lldb::ExpressionResults + Execute(DiagnosticManager &diagnostic_manager, 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 - { - return m_can_interpret; + bool + CanInterpret() override + { + return m_can_interpret; } //------------------------------------------------------------------ @@ -73,18 +69,18 @@ lldb::ModuleSP GetJITModule() override; - protected: - virtual void ScanContext(ExecutionContext &exe_ctx, lldb_private::Error &err) = 0; +protected: + virtual void + ScanContext(ExecutionContext &exe_ctx, lldb_private::Error &err) = 0; - bool PrepareToExecuteJITExpression(Stream &error_stream, ExecutionContext &exe_ctx, lldb::addr_t &struct_address); + bool + PrepareToExecuteJITExpression(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + lldb::addr_t &struct_address); virtual bool - AddArguments (ExecutionContext &exe_ctx, - std::vector &args, - lldb::addr_t struct_address, - Stream &error_stream) = 0; + AddArguments(ExecutionContext &exe_ctx, std::vector &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. Index: include/lldb/Expression/UserExpression.h =================================================================== --- include/lldb/Expression/UserExpression.h +++ include/lldb/Expression/UserExpression.h @@ -79,8 +79,8 @@ //------------------------------------------------------------------ /// 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 @@ /// 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; @@ -112,8 +109,8 @@ //------------------------------------------------------------------ /// Execute the parsed expression /// - /// @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 +133,15 @@ /// @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; + virtual lldb::ExpressionResults + Execute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, + lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) = 0; //------------------------------------------------------------------ /// 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 +160,10 @@ /// @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. Index: include/lldb/Expression/UtilityFunction.h =================================================================== --- include/lldb/Expression/UtilityFunction.h +++ include/lldb/Expression/UtilityFunction.h @@ -54,8 +54,8 @@ //------------------------------------------------------------------ /// 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 @@ /// 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 /// Index: include/lldb/Target/Process.h =================================================================== --- include/lldb/Target/Process.h +++ include/lldb/Target/Process.h @@ -1887,15 +1887,13 @@ //------------------------------------------------------------------ lldb::StateType GetState (); - + lldb::ExpressionResults - RunThreadPlan (ExecutionContext &exe_ctx, - lldb::ThreadPlanSP &thread_plan_sp, - const EvaluateExpressionOptions &options, - Stream &errors); + RunThreadPlan(ExecutionContext &exe_ctx, lldb::ThreadPlanSP &thread_plan_sp, + const EvaluateExpressionOptions &options, DiagnosticManager &diagnostic_manager); static const char * - ExecutionResultAsCString (lldb::ExpressionResults result); + ExecutionResultAsCString(lldb::ExpressionResults result); void GetStatus (Stream &ostrm); Index: include/lldb/lldb-forward.h =================================================================== --- include/lldb/lldb-forward.h +++ include/lldb/lldb-forward.h @@ -79,6 +79,7 @@ class DataExtractor; class Debugger; class Declaration; +class DiagnosticManager; class Disassembler; class DumpValueObjectOptions; class DynamicCheckerFunctions; Index: packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py =================================================================== --- packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py +++ packages/Python/lldbsuite/test/tools/lldb-mi/variable/TestMiVar.py @@ -36,9 +36,9 @@ # Print non-existant variable self.runCmd("-var-create var1 * undef") - self.expect("\^error,msg=\"error: error: use of undeclared identifier \'undef\'\\\\nerror: 1 errors parsing expression\\\\n\"") + self.expect("\^error,msg=\"error: use of undeclared identifier \'undef\'\\\\nerror: 1 error parsing expression\\\\n\"") self.runCmd("-data-evaluate-expression undef") - self.expect("\^error,msg=\"error: use of undeclared identifier \'undef\'\\\\nerror: 1 errors parsing expression\\\\n\"") + self.expect("\^error,msg=\"use of undeclared identifier \'undef\'\\\\nerror: 1 error parsing expression\\\\n\"") # Print global "g_MyVar", modify, delete and create again self.runCmd("-data-evaluate-expression g_MyVar") Index: source/Breakpoint/BreakpointLocation.cpp =================================================================== --- source/Breakpoint/BreakpointLocation.cpp +++ source/Breakpoint/BreakpointLocation.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionVariable.h" #include "lldb/Expression/UserExpression.h" #include "lldb/Symbol/CompileUnit.h" @@ -277,10 +278,10 @@ m_user_expression_sp.reset(); return false; } - - if (condition_hash != m_condition_hash || - !m_user_expression_sp || - !m_user_expression_sp->MatchesContext(exe_ctx)) + + DiagnosticManager diagnostics; + + if (condition_hash != m_condition_hash || !m_user_expression_sp || !m_user_expression_sp->MatchesContext(exe_ctx)) { LanguageType language = eLanguageTypeUnknown; // See if we can figure out the language from the frame, otherwise use the default language: @@ -303,20 +304,14 @@ return true; } - StreamString errors; - - if (!m_user_expression_sp->Parse(errors, - exe_ctx, - eExecutionPolicyOnlyWhenNeeded, - true, - false)) + if (!m_user_expression_sp->Parse(diagnostics, exe_ctx, eExecutionPolicyOnlyWhenNeeded, true, false)) { error.SetErrorStringWithFormat("Couldn't parse conditional expression:\n%s", - errors.GetData()); + diagnostics.GetString().c_str()); m_user_expression_sp.reset(); return false; } - + m_condition_hash = condition_hash; } @@ -329,20 +324,16 @@ options.SetUnwindOnError(true); options.SetIgnoreBreakpoints(true); options.SetTryAllThreads(true); - + Error expr_error; - - StreamString execution_errors; - + + diagnostics.Clear(); + ExpressionVariableSP result_variable_sp; - + ExpressionResults result_code = - m_user_expression_sp->Execute(execution_errors, - exe_ctx, - options, - m_user_expression_sp, - result_variable_sp); - + m_user_expression_sp->Execute(diagnostics, exe_ctx, options, m_user_expression_sp, result_variable_sp); + bool ret; if (result_code == eExpressionCompleted) @@ -382,9 +373,9 @@ else { ret = false; - error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", execution_errors.GetData()); + error.SetErrorStringWithFormat("Couldn't execute expression:\n%s", diagnostics.GetString().c_str()); } - + return ret; } Index: source/Expression/DiagnosticManager.cpp =================================================================== --- source/Expression/DiagnosticManager.cpp +++ source/Expression/DiagnosticManager.cpp @@ -0,0 +1,87 @@ +//===-- DiagnosticManager.cpp -----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/StreamString.h" + +using namespace lldb_private; + +void +DiagnosticManager::Dump(Log *log) +{ + if (!log) + return; + + std::string str = GetString(); + + // GetString() puts a separator after each diagnostic. + // We want to remove the last '\n' because log->PutCString will add one for us. + + if (str.size() && str.back() == '\n') + { + str.pop_back(); + } + + log->PutCString(str.c_str()); +} + +static const char * +StringForSeverity(DiagnosticSeverity severity) +{ + switch (severity) + { + // this should be exhaustive + case lldb_private::eDiagnosticSeverityError: + return "error: "; + case lldb_private::eDiagnosticSeverityWarning: + return "warning: "; + case lldb_private::eDiagnosticSeverityRemark: + return ""; + } +} + +std::string +DiagnosticManager::GetString(char separator) +{ + std::string ret; + + for (const Diagnostic &diagnostic : Diagnostics()) + { + ret.append(StringForSeverity(diagnostic.severity)); + ret.append(diagnostic.message); + ret.push_back(separator); + } + + return ret; +} + +size_t +DiagnosticManager::Printf(DiagnosticSeverity severity, const char *format, ...) +{ + StreamString ss; + + va_list args; + va_start(args, format); + size_t result = ss.PrintfVarArg(format, args); + va_end(args); + + AddDiagnostic(ss.GetData(), severity, eDiagnosticOriginLLDB); + + return result; +} + +size_t +DiagnosticManager::PutCString(DiagnosticSeverity severity, const char *cstr) +{ + if (!cstr) + return 0; + AddDiagnostic(cstr, severity, eDiagnosticOriginLLDB); + return strlen(cstr); +} Index: source/Expression/FunctionCaller.cpp =================================================================== --- source/Expression/FunctionCaller.cpp +++ source/Expression/FunctionCaller.cpp @@ -13,13 +13,14 @@ // Other libraries and framework includes // Project includes +#include "lldb/Expression/FunctionCaller.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/State.h" #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectList.h" -#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/Function.h" @@ -76,11 +77,11 @@ lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock()); if (jit_module_sp) process_sp->GetTarget().GetImages().Remove(jit_module_sp); - } + } } bool -FunctionCaller::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors) +FunctionCaller::WriteFunctionWrapper(ExecutionContext &exe_ctx, DiagnosticManager &diagnostic_manager) { Process *process = exe_ctx.GetProcessPtr(); @@ -133,27 +134,28 @@ } bool -FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors) +FunctionCaller::WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, + DiagnosticManager &diagnostic_manager) { - return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, errors); + return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, diagnostic_manager); } // FIXME: Assure that the ValueList we were passed in is consistent with the one that defined this function. bool -FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, - lldb::addr_t &args_addr_ref, - ValueList &arg_values, - Stream &errors) +FunctionCaller::WriteFunctionArguments(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, ValueList &arg_values, + DiagnosticManager &diagnostic_manager) { // All the information to reconstruct the struct is provided by the // StructExtractor. if (!m_struct_valid) { - errors.Printf("Argument information was not correctly parsed, so the function cannot be called."); + diagnostic_manager.PutCString( + eDiagnosticSeverityError, + "Argument information was not correctly parsed, so the function cannot be called."); return false; } - + Error error; lldb::ExpressionResults return_value = lldb::eExpressionSetupError; @@ -191,14 +193,16 @@ // FIXME: We will need to extend this for Variadic functions. Error value_error; - + size_t num_args = arg_values.GetSize(); if (num_args != m_arg_values.GetSize()) { - errors.Printf ("Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "", (uint64_t)num_args, (uint64_t)m_arg_values.GetSize()); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "Wrong number of arguments - was: %" PRIu64 " should be: %" PRIu64 "", + (uint64_t)num_args, (uint64_t)m_arg_values.GetSize()); return false; } - + for (size_t i = 0; i < num_args; i++) { // FIXME: We should sanity check sizes. @@ -225,16 +229,17 @@ } bool -FunctionCaller::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors) +FunctionCaller::InsertFunction(ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, + DiagnosticManager &diagnostic_manager) { - if (CompileFunction(errors) != 0) + if (CompileFunction(diagnostic_manager) != 0) return false; - if (!WriteFunctionWrapper(exe_ctx, errors)) + if (!WriteFunctionWrapper(exe_ctx, diagnostic_manager)) return false; - if (!WriteFunctionArguments(exe_ctx, args_addr_ref, errors)) + if (!WriteFunctionArguments(exe_ctx, args_addr_ref, diagnostic_manager)) return false; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); if (log) log->Printf ("Call Address: 0x%" PRIx64 " Struct Address: 0x%" PRIx64 ".\n", m_jit_start_addr, args_addr_ref); @@ -242,13 +247,12 @@ } lldb::ThreadPlanSP -FunctionCaller::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, - lldb::addr_t args_addr, +FunctionCaller::GetThreadPlanToCallFunction(ExecutionContext &exe_ctx, lldb::addr_t args_addr, const EvaluateExpressionOptions &options, - Stream &errors) + DiagnosticManager &diagnostic_manager) { - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - + Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); + if (log) log->Printf("-- [FunctionCaller::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str()); @@ -256,7 +260,7 @@ Thread *thread = exe_ctx.GetThreadPtr(); if (thread == NULL) { - errors.Printf("Can't call a function without a valid thread."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "Can't call a function without a valid thread."); return NULL; } @@ -322,15 +326,12 @@ } lldb::ExpressionResults -FunctionCaller::ExecuteFunction( - ExecutionContext &exe_ctx, - lldb::addr_t *args_addr_ptr, - const EvaluateExpressionOptions &options, - Stream &errors, - Value &results) +FunctionCaller::ExecuteFunction(ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr, + const EvaluateExpressionOptions &options, DiagnosticManager &diagnostic_manager, + Value &results) { lldb::ExpressionResults return_value = lldb::eExpressionSetupError; - + // FunctionCaller::ExecuteFunction execution is always just to get the result. Do make sure we ignore // breakpoints, unwind on error, and don't try to debug it. EvaluateExpressionOptions real_options = options; @@ -344,13 +345,13 @@ args_addr = *args_addr_ptr; else args_addr = LLDB_INVALID_ADDRESS; - - if (CompileFunction(errors) != 0) + + if (CompileFunction(diagnostic_manager) != 0) return lldb::eExpressionSetupError; - + if (args_addr == LLDB_INVALID_ADDRESS) { - if (!InsertFunction(exe_ctx, args_addr, errors)) + if (!InsertFunction(exe_ctx, args_addr, diagnostic_manager)) return lldb::eExpressionSetupError; } @@ -358,24 +359,18 @@ if (log) log->Printf("== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str()); - - lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx, - args_addr, - real_options, - errors); + + lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction(exe_ctx, args_addr, real_options, diagnostic_manager); if (!call_plan_sp) return lldb::eExpressionSetupError; - + // We need to make sure we record the fact that we are running an expression here // otherwise this fact will fail to be recorded when fetching an Objective-C object description if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); - - return_value = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, - call_plan_sp, - real_options, - errors); - + + return_value = exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, real_options, diagnostic_manager); + if (log) { if (return_value != lldb::eExpressionCompleted) Index: source/Expression/IRDynamicChecks.cpp =================================================================== --- source/Expression/IRDynamicChecks.cpp +++ source/Expression/IRDynamicChecks.cpp @@ -50,8 +50,7 @@ DynamicCheckerFunctions::~DynamicCheckerFunctions() = default; bool -DynamicCheckerFunctions::Install(Stream &error_stream, - ExecutionContext &exe_ctx) +DynamicCheckerFunctions::Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) { Error error; m_valid_pointer_check.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_valid_pointer_check_text, @@ -60,8 +59,8 @@ error)); if (error.Fail()) return false; - - if (!m_valid_pointer_check->Install(error_stream, exe_ctx)) + + if (!m_valid_pointer_check->Install(diagnostic_manager, exe_ctx)) return false; Process *process = exe_ctx.GetProcessPtr(); @@ -74,7 +73,7 @@ { m_objc_object_check.reset(objc_language_runtime->CreateObjectChecker(VALID_OBJC_OBJECT_CHECK_NAME)); - if (!m_objc_object_check->Install(error_stream, exe_ctx)) + if (!m_objc_object_check->Install(diagnostic_manager, exe_ctx)) return false; } } Index: source/Expression/IRInterpreter.cpp =================================================================== --- source/Expression/IRInterpreter.cpp +++ source/Expression/IRInterpreter.cpp @@ -7,18 +7,19 @@ // //===----------------------------------------------------------------------===// +#include "lldb/Expression/IRInterpreter.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/DataExtractor.h" #include "lldb/Core/Error.h" #include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" -#include "lldb/Core/Module.h" #include "lldb/Core/Scalar.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRMemoryMap.h" -#include "lldb/Expression/IRInterpreter.h" #include "lldb/Host/Endian.h" #include "lldb/Target/ABI.h" @@ -1596,7 +1597,7 @@ } lldb_private::Address funcAddr(I.ULongLong(LLDB_INVALID_ADDRESS)); - lldb_private::StreamString error_stream; + lldb_private::DiagnosticManager diagnostics; lldb_private::EvaluateExpressionOptions options; // We generally receive a function pointer which we must dereference @@ -1701,31 +1702,24 @@ llvm::ArrayRef args(rawArgs, numArgs); // Setup a thread plan to call the target function - lldb::ThreadPlanSP call_plan_sp - ( - new lldb_private::ThreadPlanCallFunctionUsingABI - ( - exe_ctx.GetThreadRef(), - funcAddr, - *prototype, - *returnType, - args, - options - ) - ); + lldb::ThreadPlanSP call_plan_sp(new lldb_private::ThreadPlanCallFunctionUsingABI( + exe_ctx.GetThreadRef(), funcAddr, *prototype, *returnType, args, options)); // Check if the plan is valid - if (!call_plan_sp || !call_plan_sp->ValidatePlan(&error_stream)) + lldb_private::StreamString ss; + if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) { error.SetErrorToGenericError(); - error.SetErrorStringWithFormat("unable to make ThreadPlanCallFunctionUsingABI for 0x%llx", I.ULongLong()); + error.SetErrorStringWithFormat("unable to make ThreadPlanCallFunctionUsingABI for 0x%llx", + I.ULongLong()); return false; } exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); // Execute the actual function call thread plan - lldb::ExpressionResults res = exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, error_stream); + lldb::ExpressionResults res = + exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); // Check that the thread plan completed successfully if (res != lldb::ExpressionResults::eExpressionCompleted) Index: source/Expression/LLVMUserExpression.cpp =================================================================== --- source/Expression/LLVMUserExpression.cpp +++ source/Expression/LLVMUserExpression.cpp @@ -18,6 +18,7 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" @@ -25,11 +26,11 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Symbol/Type.h" -#include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" @@ -76,8 +77,9 @@ } lldb::ExpressionResults -LLVMUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, - lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) +LLVMUserExpression::Execute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, + lldb::ExpressionVariableSP &result) { // The expression log is quite verbose, and if you're just tracking the execution of the // expression, it's quite convenient to have these logs come out with the STEP log as well. @@ -87,9 +89,10 @@ { lldb::addr_t struct_address = LLDB_INVALID_ADDRESS; - if (!PrepareToExecuteJITExpression(error_stream, exe_ctx, struct_address)) + if (!PrepareToExecuteJITExpression(diagnostic_manager, exe_ctx, struct_address)) { - error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); return lldb::eExpressionSetupError; } @@ -103,7 +106,7 @@ if (!module || !function) { - error_stream.Printf("Supposed to interpret, but nothing is there"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "supposed to interpret, but nothing is there"); return lldb::eExpressionSetupError; } @@ -111,9 +114,10 @@ std::vector args; - if (!AddArguments(exe_ctx, args, struct_address, error_stream)) + if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) { - error_stream.Printf("Errored out in %s, couldn't AddArguments", __FUNCTION__); + diagnostic_manager.Printf(eDiagnosticSeverityError, "errored out in %s, couldn't AddArguments", + __FUNCTION__); return lldb::eExpressionSetupError; } @@ -125,7 +129,8 @@ if (!interpreter_error.Success()) { - error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString()); + diagnostic_manager.Printf(eDiagnosticSeverityError, "supposed to interpret, but failed: %s", + interpreter_error.AsCString()); return lldb::eExpressionDiscarded; } } @@ -133,7 +138,7 @@ { if (!exe_ctx.HasThreadScope()) { - error_stream.Printf("UserExpression::Execute called with no thread selected."); + diagnostic_manager.Printf(eDiagnosticSeverityError, "%s called with no thread selected", __FUNCTION__); return lldb::eExpressionSetupError; } @@ -141,17 +146,22 @@ std::vector args; - if (!AddArguments(exe_ctx, args, struct_address, error_stream)) + if (!AddArguments(exe_ctx, args, struct_address, diagnostic_manager)) { - error_stream.Printf("Errored out in %s, couldn't AddArguments", __FUNCTION__); + diagnostic_manager.Printf(eDiagnosticSeverityError, "errored out in %s, couldn't AddArguments", + __FUNCTION__); return lldb::eExpressionSetupError; } lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression(exe_ctx.GetThreadRef(), wrapper_address, args, options, shared_ptr_to_me)); - if (!call_plan_sp || !call_plan_sp->ValidatePlan(&error_stream)) + StreamString ss; + if (!call_plan_sp || !call_plan_sp->ValidatePlan(&ss)) + { + diagnostic_manager.PutCString(eDiagnosticSeverityError, ss.GetData()); return lldb::eExpressionSetupError; + } ThreadPlanCallUserExpression *user_expression_plan = static_cast(call_plan_sp.get()); @@ -168,7 +178,7 @@ exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); lldb::ExpressionResults execution_result = - exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, error_stream); + exe_ctx.GetProcessRef().RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostic_manager); if (exe_ctx.GetProcessPtr()) exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); @@ -187,20 +197,21 @@ error_desc = real_stop_info_sp->GetDescription(); } if (error_desc) - error_stream.Printf("Execution was interrupted, reason: %s.", error_desc); + diagnostic_manager.Printf(eDiagnosticSeverityError, "Execution was interrupted, reason: %s.", + error_desc); else - error_stream.PutCString("Execution was interrupted."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "Execution was interrupted."); if ((execution_result == lldb::eExpressionInterrupted && options.DoesUnwindOnError()) || (execution_result == lldb::eExpressionHitBreakpoint && options.DoesIgnoreBreakpoints())) - error_stream.PutCString( - "\nThe process has been returned to the state before expression evaluation."); + diagnostic_manager.AppendMessageToDiagnostic( + "The process has been returned to the state before expression evaluation."); else { if (execution_result == lldb::eExpressionHitBreakpoint) user_expression_plan->TransferExpressionOwnership(); - error_stream.PutCString( - "\nThe process has been left at the point where it was interrupted, " + diagnostic_manager.AppendMessageToDiagnostic( + "The process has been left at the point where it was interrupted, " "use \"thread return -x\" to return to the state before expression evaluation."); } @@ -208,7 +219,8 @@ } else if (execution_result == lldb::eExpressionStoppedForDebug) { - error_stream.PutCString( + diagnostic_manager.PutCString( + eDiagnosticSeverityRemark, "Execution was halted at the first instruction of the expression " "function because \"debug\" was requested.\n" "Use \"thread return -x\" to return to the state before expression evaluation."); @@ -216,13 +228,13 @@ } else if (execution_result != lldb::eExpressionCompleted) { - error_stream.Printf("Couldn't execute function; result was %s\n", - Process::ExecutionResultAsCString(execution_result)); + diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't execute function; result was %s", + Process::ExecutionResultAsCString(execution_result)); return execution_result; } } - if (FinalizeJITExecution(error_stream, exe_ctx, result, function_stack_bottom, function_stack_top)) + if (FinalizeJITExecution(diagnostic_manager, exe_ctx, result, function_stack_bottom, function_stack_top)) { return lldb::eExpressionCompleted; } @@ -233,13 +245,14 @@ } else { - error_stream.Printf("Expression can't be run, because there is no JIT compiled function"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "Expression can't be run, because there is no JIT compiled function"); return lldb::eExpressionSetupError; } } bool -LLVMUserExpression::FinalizeJITExecution(Stream &error_stream, ExecutionContext &exe_ctx, +LLVMUserExpression::FinalizeJITExecution(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb::ExpressionVariableSP &result, lldb::addr_t function_stack_bottom, lldb::addr_t function_stack_top) { @@ -250,7 +263,8 @@ if (!m_dematerializer_sp) { - error_stream.Printf("Couldn't apply expression side effects : no dematerializer is present"); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "Couldn't apply expression side effects : no dematerializer is present"); return false; } @@ -260,8 +274,8 @@ if (!dematerialize_error.Success()) { - error_stream.Printf("Couldn't apply expression side effects : %s\n", - dematerialize_error.AsCString("unknown error")); + diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't apply expression side effects : %s", + dematerialize_error.AsCString("unknown error")); return false; } @@ -276,7 +290,7 @@ } bool -LLVMUserExpression::PrepareToExecuteJITExpression(Stream &error_stream, ExecutionContext &exe_ctx, +LLVMUserExpression::PrepareToExecuteJITExpression(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, lldb::addr_t &struct_address) { lldb::TargetSP target; @@ -285,7 +299,8 @@ if (!LockAndCheckContext(exe_ctx, target, process, frame)) { - error_stream.Printf("The context has changed before we could JIT the expression!\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "The context has changed before we could JIT the expression!"); return false; } @@ -309,7 +324,9 @@ if (!alloc_error.Success()) { - error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString()); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "Couldn't allocate space for materialized struct: %s", + alloc_error.AsCString()); return false; } } @@ -335,7 +352,8 @@ if (!alloc_error.Success()) { - error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString()); + diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't allocate space for the stack frame: %s", + alloc_error.AsCString()); return false; } } @@ -347,7 +365,8 @@ if (!materialize_error.Success()) { - error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString()); + diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't materialize: %s", + materialize_error.AsCString()); return false; } } Index: source/Expression/UserExpression.cpp =================================================================== --- source/Expression/UserExpression.cpp +++ source/Expression/UserExpression.cpp @@ -16,18 +16,19 @@ #include #include +#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectConstResult.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Expression/Materializer.h" #include "lldb/Expression/UserExpression.h" -#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Function.h" @@ -232,8 +233,6 @@ log->Printf ("== [UserExpression::Evaluate] Getting expression: %s ==", error.AsCString()); return lldb::eExpressionSetupError; } - - StreamString error_stream; if (log) log->Printf("== [UserExpression::Evaluate] Parsing expression %s ==", expr_cstr); @@ -244,21 +243,20 @@ if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse)) { error.SetErrorString ("expression interrupted by callback before parse"); - result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); + result_valobj_sp = ValueObjectConstResult::Create(exe_ctx.GetBestExecutionContextScope(), error); return lldb::eExpressionInterrupted; } - if (!user_expression_sp->Parse (error_stream, - exe_ctx, - execution_policy, - keep_expression_in_memory, - generate_debug_info)) + DiagnosticManager diagnostic_manager; + + if (!user_expression_sp->Parse(diagnostic_manager, exe_ctx, execution_policy, keep_expression_in_memory, + generate_debug_info)) { execution_results = lldb::eExpressionParseError; - if (error_stream.GetString().empty()) - error.SetExpressionError (execution_results, "expression failed to parse, unknown error"); + if (!diagnostic_manager.Diagnostics().size()) + error.SetExpressionError(execution_results, "expression failed to parse, unknown error"); else - error.SetExpressionError (execution_results, error_stream.GetString().c_str()); + error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str()); } else { @@ -274,8 +272,8 @@ if (log) log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); - if (error_stream.GetString().empty()) - error.SetExpressionError (lldb::eExpressionSetupError, "expression needed to run but couldn't"); + if (!diagnostic_manager.Diagnostics().size()) + error.SetExpressionError(lldb::eExpressionSetupError, "expression needed to run but couldn't"); } else { @@ -286,16 +284,13 @@ return lldb::eExpressionInterrupted; } - error_stream.GetString().clear(); + diagnostic_manager.Clear(); if (log) log->Printf("== [UserExpression::Evaluate] Executing expression =="); - execution_results = user_expression_sp->Execute (error_stream, - exe_ctx, - options, - user_expression_sp, - expr_result); + execution_results = + user_expression_sp->Execute(diagnostic_manager, exe_ctx, options, user_expression_sp, expr_result); if (options.GetResultIsInternal() && expr_result && process) { @@ -307,10 +302,10 @@ if (log) log->Printf("== [UserExpression::Evaluate] Execution completed abnormally =="); - if (error_stream.GetString().empty()) - error.SetExpressionError (execution_results, "expression failed to execute, unknown error"); + if (!diagnostic_manager.Diagnostics().size()) + error.SetExpressionError(execution_results, "expression failed to execute, unknown error"); else - error.SetExpressionError (execution_results, error_stream.GetString().c_str()); + error.SetExpressionError(execution_results, diagnostic_manager.GetString().c_str()); } else { Index: source/Expression/UtilityFunction.cpp =================================================================== --- source/Expression/UtilityFunction.cpp +++ source/Expression/UtilityFunction.cpp @@ -20,10 +20,11 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Expression/ExpressionSourceCode.h" #include "lldb/Expression/FunctionCaller.h" +#include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Expression/UtilityFunction.h" -#include "lldb/Expression/ExpressionSourceCode.h" -#include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Host/Host.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" @@ -96,26 +97,24 @@ } if (m_caller_up) { - StreamString errors; - errors.Clear(); - unsigned num_errors = m_caller_up->CompileFunction(errors); + DiagnosticManager diagnostics; + + unsigned num_errors = m_caller_up->CompileFunction(diagnostics); if (num_errors) { - error.SetErrorStringWithFormat ("Error compiling %s caller function: \"%s\".", - m_function_name.c_str(), - errors.GetData()); + error.SetErrorStringWithFormat("Error compiling %s caller function: \"%s\".", m_function_name.c_str(), + diagnostics.GetString().c_str()); m_caller_up.reset(); return nullptr; } - - errors.Clear(); + + diagnostics.Clear(); ExecutionContext exe_ctx(process_sp); - - if (!m_caller_up->WriteFunctionWrapper(exe_ctx, errors)) + + if (!m_caller_up->WriteFunctionWrapper(exe_ctx, diagnostics)) { - error.SetErrorStringWithFormat ("Error inserting caller function for %s: \"%s\".", - m_function_name.c_str(), - errors.GetData()); + error.SetErrorStringWithFormat("Error inserting caller function for %s: \"%s\".", m_function_name.c_str(), + diagnostics.GetString().c_str()); m_caller_up.reset(); return nullptr; } Index: source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h +++ source/Plugins/ExpressionParser/Clang/ClangExpressionParser.h @@ -10,11 +10,12 @@ #ifndef liblldb_ClangExpressionParser_h_ #define liblldb_ClangExpressionParser_h_ -#include "lldb/lldb-public.h" #include "lldb/Core/ArchSpec.h" #include "lldb/Core/ClangForward.h" #include "lldb/Core/Error.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionParser.h" +#include "lldb/lldb-public.h" #include #include @@ -63,16 +64,16 @@ /// 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 to report errors to. /// /// @return /// The number of errors encountered during parsing. 0 means /// success. //------------------------------------------------------------------ unsigned - Parse (Stream &stream) override; - + Parse(DiagnosticManager &diagnostic_manager) override; + //------------------------------------------------------------------ /// Ready an already-parsed expression for execution, possibly /// evaluating it statically. @@ -98,7 +99,7 @@ /// /// @param[out] const_result /// If the result of the expression is constant, and the - /// expression has no side effects, this is set to the result of the + /// expression has no side effects, this is set to the result of the /// expression. /// /// @param[in] execution_policy Index: source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp +++ source/Plugins/ExpressionParser/Clang/ClangExpressionParser.cpp @@ -11,7 +11,9 @@ // C++ Includes // Other libraries and framework includes #include "clang/AST/ASTContext.h" +#include "clang/AST/ASTDiagnostic.h" #include "clang/AST/ExternalASTSource.h" +#include "clang/Basic/DiagnosticIDs.h" #include "clang/Basic/FileManager.h" #include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" @@ -64,20 +66,21 @@ #include "lldb/Core/Module.h" #include "lldb/Core/Stream.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Core/StreamString.h" #include "lldb/Core/StringList.h" -#include "lldb/Core/StreamString.h" +#include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Expression/IRExecutionUnit.h" -#include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Expression/IRInterpreter.h" #include "lldb/Host/File.h" #include "lldb/Host/HostInfo.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/SymbolVendor.h" #include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Language.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" -#include "lldb/Target/Language.h" +#include "lldb/Utility/LLDBAssert.h" using namespace clang; using namespace llvm; @@ -141,6 +144,76 @@ } }; +class ClangDiagnosticManagerAdapter : public clang::DiagnosticConsumer +{ +public: + ClangDiagnosticManagerAdapter() : m_passthrough(new clang::TextDiagnosticBuffer) {} + + ClangDiagnosticManagerAdapter(const std::shared_ptr &passthrough) + : m_passthrough(passthrough) + { + } + + void + ResetManager(DiagnosticManager *manager = nullptr) + { + m_manager = manager; + } + + void + HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &Info) + { + if (m_manager) + { + llvm::SmallVector diag_str; + Info.FormatDiagnostic(diag_str); + diag_str.push_back('\0'); + const char *data = diag_str.data(); + + switch (DiagLevel) + { + case DiagnosticsEngine::Level::Fatal: + case DiagnosticsEngine::Level::Error: + m_manager->AddDiagnostic(data, eDiagnosticSeverityError, eDiagnosticOriginClang, Info.getID()); + break; + case DiagnosticsEngine::Level::Warning: + m_manager->AddDiagnostic(data, eDiagnosticSeverityWarning, eDiagnosticOriginClang, Info.getID()); + break; + case DiagnosticsEngine::Level::Remark: + case DiagnosticsEngine::Level::Ignored: + m_manager->AddDiagnostic(data, eDiagnosticSeverityRemark, eDiagnosticOriginClang, Info.getID()); + break; + case DiagnosticsEngine::Level::Note: + m_manager->AppendMessageToDiagnostic(data); + } + } + + m_passthrough->HandleDiagnostic(DiagLevel, Info); + } + + void + FlushDiagnostics(DiagnosticsEngine &Diags) + { + m_passthrough->FlushDiagnostics(Diags); + } + + DiagnosticConsumer * + clone(DiagnosticsEngine &Diags) const + { + return new ClangDiagnosticManagerAdapter(m_passthrough); + } + + clang::TextDiagnosticBuffer * + GetPassthrough() + { + return m_passthrough.get(); + } + +private: + DiagnosticManager *m_manager = nullptr; + std::shared_ptr m_passthrough; +}; + //===----------------------------------------------------------------------===// // Implementation of ClangExpressionParser //===----------------------------------------------------------------------===// @@ -371,7 +444,7 @@ // 6. Set up the diagnostic buffer for reporting errors - m_compiler->getDiagnostics().setClient(new clang::TextDiagnosticBuffer); + m_compiler->getDiagnostics().setClient(new ClangDiagnosticManagerAdapter); // 7. Set up the source management objects inside the compiler @@ -435,11 +508,15 @@ } unsigned -ClangExpressionParser::Parse(Stream &stream) +ClangExpressionParser::Parse(DiagnosticManager &diagnostic_manager) { - TextDiagnosticBuffer *diag_buf = static_cast(m_compiler->getDiagnostics().getClient()); + ClangDiagnosticManagerAdapter *adapter = + static_cast(m_compiler->getDiagnostics().getClient()); + clang::TextDiagnosticBuffer *diag_buf = adapter->GetPassthrough(); diag_buf->FlushDiagnostics(m_compiler->getDiagnostics()); + adapter->ResetManager(&diagnostic_manager); + const char *expr_text = m_expr.Text(); clang::SourceManager &source_mgr = m_compiler->getSourceManager(); @@ -511,30 +588,21 @@ if (m_pp_callbacks && m_pp_callbacks->hasErrors()) { num_errors++; - stream.PutCString(m_pp_callbacks->getErrorString().c_str()); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "while importing modules:"); + diagnostic_manager.AppendMessageToDiagnostic(m_pp_callbacks->getErrorString().c_str()); } - for (TextDiagnosticBuffer::const_iterator warn = diag_buf->warn_begin(), warn_end = diag_buf->warn_end(); - warn != warn_end; ++warn) - stream.Printf("warning: %s\n", warn->second.c_str()); - - for (TextDiagnosticBuffer::const_iterator err = diag_buf->err_begin(), err_end = diag_buf->err_end(); - err != err_end; ++err) - stream.Printf("error: %s\n", err->second.c_str()); - - for (TextDiagnosticBuffer::const_iterator note = diag_buf->note_begin(), note_end = diag_buf->note_end(); - note != note_end; ++note) - stream.Printf("note: %s\n", note->second.c_str()); - if (!num_errors) { if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes()) { - stream.Printf("error: Couldn't infer the type of a variable\n"); + diagnostic_manager.Printf(eDiagnosticSeverityError, "Couldn't infer the type of a variable"); num_errors++; } } + adapter->ResetManager(); + return num_errors; } @@ -663,14 +731,14 @@ { DynamicCheckerFunctions *dynamic_checkers = new DynamicCheckerFunctions(); - StreamString install_errors; + DiagnosticManager install_diagnostics; - if (!dynamic_checkers->Install(install_errors, exe_ctx)) + if (!dynamic_checkers->Install(install_diagnostics, exe_ctx)) { - if (install_errors.GetString().empty()) - err.SetErrorString ("couldn't install checkers, unknown error"); + if (install_diagnostics.Diagnostics().size()) + err.SetErrorString("couldn't install checkers, unknown error"); else - err.SetErrorString (install_errors.GetString().c_str()); + err.SetErrorString(install_diagnostics.GetString().c_str()); return err; } Index: source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h +++ source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.h @@ -137,17 +137,17 @@ //------------------------------------------------------------------ /// Compile the wrapper function /// - /// @param[in] errors - /// The stream to print parser errors to. + /// @param[in] diagnostic_manager + /// The diagnostic manager to report parser errors to. /// /// @return /// The number of errors. //------------------------------------------------------------------ unsigned - CompileFunction (Stream &errors) override; - + CompileFunction(DiagnosticManager &diagnostic_manager) override; + ExpressionTypeSystemHelper * - GetTypeSystemHelper () override + GetTypeSystemHelper() override { return &m_type_system_helper; } Index: source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp +++ source/Plugins/ExpressionParser/Clang/ClangFunctionCaller.cpp @@ -74,11 +74,11 @@ } unsigned -ClangFunctionCaller::CompileFunction (Stream &errors) +ClangFunctionCaller::CompileFunction(DiagnosticManager &diagnostic_manager) { if (m_compiled) return 0; - + // FIXME: How does clang tell us there's no return value? We need to handle that case. unsigned num_errors = 0; @@ -143,8 +143,9 @@ type_name = clang_qual_type.GetTypeName().AsCString(""); } else - { - errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i); + { + diagnostic_manager.Printf(eDiagnosticSeverityError, + "Could not determine type of input value %" PRIu64 ".", (uint64_t)i); return 1; } } @@ -195,15 +196,15 @@ { const bool generate_debug_info = true; m_parser.reset(new ClangExpressionParser(jit_process_sp.get(), *this, generate_debug_info)); - - num_errors = m_parser->Parse (errors); + + num_errors = m_parser->Parse(diagnostic_manager); } else { - errors.Printf("no process - unable to inject function"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "no process - unable to inject function"); num_errors = 1; } - + m_compiled = (num_errors == 0); if (!m_compiled) Index: source/Plugins/ExpressionParser/Clang/ClangUserExpression.h =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangUserExpression.h +++ source/Plugins/ExpressionParser/Clang/ClangUserExpression.h @@ -126,8 +126,8 @@ //------------------------------------------------------------------ /// 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 @@ -145,11 +145,9 @@ /// True on success (no errors); false otherwise. //------------------------------------------------------------------ bool - Parse (Stream &error_stream, - ExecutionContext &exe_ctx, - lldb_private::ExecutionPolicy execution_policy, - bool keep_result_in_memory, - bool generate_debug_info) override; + Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, + bool generate_debug_info) override; ExpressionTypeSystemHelper * GetTypeSystemHelper () override @@ -188,13 +186,11 @@ lldb_private::Error &err) override; bool - AddArguments (ExecutionContext &exe_ctx, - std::vector &args, - lldb::addr_t struct_address, - Stream &error_stream) override; - - ClangUserExpressionHelper m_type_system_helper; - + AddArguments(ExecutionContext &exe_ctx, std::vector &args, lldb::addr_t struct_address, + DiagnosticManager &diagnostic_manager) override; + + ClangUserExpressionHelper m_type_system_helper; + class ResultDelegate : public Materializer::PersistentVariableDelegate { public: Index: source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp +++ source/Plugins/ExpressionParser/Clang/ClangUserExpression.cpp @@ -326,11 +326,9 @@ } bool -ClangUserExpression::Parse (Stream &error_stream, - ExecutionContext &exe_ctx, - lldb_private::ExecutionPolicy execution_policy, - bool keep_result_in_memory, - bool generate_debug_info) +ClangUserExpression::Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, + bool generate_debug_info) { Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); @@ -346,13 +344,13 @@ } else { - error_stream.PutCString ("error: couldn't start parsing (no persistent data)"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't start parsing (no persistent data)"); return false; } } else { - error_stream.PutCString ("error: couldn't start parsing (no target)"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "error: couldn't start parsing (no target)"); return false; } @@ -360,7 +358,7 @@ if (!err.Success()) { - error_stream.Printf("warning: %s\n", err.AsCString()); + diagnostic_manager.PutCString(eDiagnosticSeverityWarning, err.AsCString()); } StreamString m_transformed_stream; @@ -418,7 +416,7 @@ if (!source_code->GetText(m_transformed_text, lang_type, m_const_object, m_in_static_method, exe_ctx)) { - error_stream.PutCString ("error: couldn't construct expression body"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "couldn't construct expression body"); return false; } @@ -433,7 +431,7 @@ if (!target) { - error_stream.PutCString ("error: invalid target\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target"); return false; } @@ -467,7 +465,8 @@ if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) { - error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "current process state is unsuitable for expression parsing"); ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. @@ -482,11 +481,12 @@ ClangExpressionParser parser(exe_scope, *this, generate_debug_info); - unsigned num_errors = parser.Parse (error_stream); + unsigned num_errors = parser.Parse(diagnostic_manager); if (num_errors) { - error_stream.Printf ("error: %d errors parsing expression\n", num_errors); + diagnostic_manager.Printf(eDiagnosticSeverityError, "%u error%s parsing expression", num_errors, + num_errors == 1 ? "" : "s"); ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. @@ -547,22 +547,20 @@ { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) - error_stream.Printf ("error: %s\n", error_cstr); + diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr); else - error_stream.Printf ("error: expression can't be interpreted or run\n"); + diagnostic_manager.Printf(eDiagnosticSeverityError, "expression can't be interpreted or run"); return false; } } bool -ClangUserExpression::AddArguments (ExecutionContext &exe_ctx, - std::vector &args, - lldb::addr_t struct_address, - Stream &error_stream) +ClangUserExpression::AddArguments(ExecutionContext &exe_ctx, std::vector &args, + lldb::addr_t struct_address, DiagnosticManager &diagnostic_manager) { lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS; - lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS; - + lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS; + if (m_needs_object_ptr) { lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); @@ -581,7 +579,7 @@ } else { - error_stream.Printf("Need object pointer but don't know the language\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "need object pointer but don't know the language"); return false; } @@ -591,7 +589,9 @@ if (!object_ptr_error.Success()) { - error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); + diagnostic_manager.Printf(eDiagnosticSeverityWarning, + "couldn't get required object pointer (substituting NULL): %s", + object_ptr_error.AsCString()); object_ptr = 0; } @@ -603,7 +603,9 @@ if (!object_ptr_error.Success()) { - error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); + diagnostic_manager.Printf(eDiagnosticSeverityWarning, + "couldn't get cmd pointer (substituting NULL): %s", + object_ptr_error.AsCString()); cmd_ptr = 0; } } Index: source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h +++ source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.h @@ -124,12 +124,12 @@ { m_type_system_helper.ResetDeclMap(exe_ctx, keep_result_in_memory); } - + bool - Install (Stream &error_stream, ExecutionContext &exe_ctx) override; - + Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) override; + private: - ClangUtilityFunctionHelper m_type_system_helper; ///< The map to use when parsing and materializing the expression. + ClangUtilityFunctionHelper m_type_system_helper; ///< The map to use when parsing and materializing the expression. }; } // namespace lldb_private Index: source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp =================================================================== --- source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp +++ source/Plugins/ExpressionParser/Clang/ClangUtilityFunction.cpp @@ -55,8 +55,8 @@ //------------------------------------------------------------------ /// 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 report errors and warnings to. /// /// @param[in] exe_ctx /// The execution context to install the utility function to. @@ -65,35 +65,34 @@ /// True on success (no errors); false otherwise. //------------------------------------------------------------------ bool -ClangUtilityFunction::Install (Stream &error_stream, - ExecutionContext &exe_ctx) +ClangUtilityFunction::Install(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx) { if (m_jit_start_addr != LLDB_INVALID_ADDRESS) { - error_stream.PutCString("error: already installed\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityWarning, "already installed"); return false; } - + //////////////////////////////////// // Set up the target and compiler // Target *target = exe_ctx.GetTargetPtr(); - + if (!target) { - error_stream.PutCString ("error: invalid target\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid target"); return false; } - + Process *process = exe_ctx.GetProcessPtr(); - + if (!process) { - error_stream.PutCString ("error: invalid process\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "invalid process"); return false; } - + ////////////////////////// // Parse the expression // @@ -101,24 +100,26 @@ bool keep_result_in_memory = false; ResetDeclMap(exe_ctx, keep_result_in_memory); - + if (!DeclMap()->WillParse(exe_ctx, NULL)) { - error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "current process state is unsuitable for expression parsing"); return false; } - + const bool generate_debug_info = true; ClangExpressionParser parser(exe_ctx.GetBestExecutionContextScope(), *this, generate_debug_info); - - unsigned num_errors = parser.Parse (error_stream); - + + unsigned num_errors = parser.Parse(diagnostic_manager); + if (num_errors) { - error_stream.Printf ("error: %d errors parsing expression\n", num_errors); - + diagnostic_manager.Printf(eDiagnosticSeverityError, "%d error%s parsing expression", num_errors, + num_errors == 1 ? "" : "s"); + ResetDeclMap(); - + return false; } @@ -175,9 +176,13 @@ { const char *error_cstr = jit_error.AsCString(); if (error_cstr && error_cstr[0]) - error_stream.Printf ("error: %s\n", error_cstr); + { + diagnostic_manager.Printf(eDiagnosticSeverityError, "%s", error_cstr); + } else - error_stream.Printf ("error: expression can't be interpreted or run\n"); + { + diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run"); + } return false; } } Index: source/Plugins/ExpressionParser/Go/GoUserExpression.h =================================================================== --- source/Plugins/ExpressionParser/Go/GoUserExpression.h +++ source/Plugins/ExpressionParser/Go/GoUserExpression.h @@ -62,31 +62,32 @@ class GoUserExpression : public UserExpression { public: - GoUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix, - lldb::LanguageType language, ResultType desired_type, const EvaluateExpressionOptions &options); + GoUserExpression(ExecutionContextScope &exe_scope, const char *expr, const char *expr_prefix, + lldb::LanguageType language, ResultType desired_type, const EvaluateExpressionOptions &options); - bool - Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, - bool keep_result_in_memory, bool generate_debug_info) override; + bool + Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, + bool generate_debug_info) override; - lldb::ExpressionResults - Execute(Stream &error_stream, ExecutionContext &exe_ctx, - const EvaluateExpressionOptions &options, - lldb::UserExpressionSP &shared_ptr_to_me, - lldb::ExpressionVariableSP &result) override; + lldb::ExpressionResults + Execute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, + lldb::ExpressionVariableSP &result) override; - bool - CanInterpret() override - { - return true; + bool + CanInterpret() override + { + return true; + } + 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 + { + return true; } - 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 - { - return true; - } private: class GoInterpreter; Index: source/Plugins/ExpressionParser/Go/GoUserExpression.cpp =================================================================== --- source/Plugins/ExpressionParser/Go/GoUserExpression.cpp +++ source/Plugins/ExpressionParser/Go/GoUserExpression.cpp @@ -26,7 +26,6 @@ // Project includes #include "GoUserExpression.h" -#include "lldb/lldb-private.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/DataEncoder.h" @@ -37,10 +36,11 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/Core/ValueObjectRegister.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/ExpressionVariable.h" -#include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/GoASTContext.h" #include "lldb/Symbol/SymbolFile.h" +#include "lldb/Symbol/TypeList.h" #include "lldb/Symbol/VariableList.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" @@ -49,6 +49,7 @@ #include "lldb/Target/Target.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanCallUserExpression.h" +#include "lldb/lldb-private.h" #include "Plugins/ExpressionParser/Go/GoAST.h" #include "Plugins/ExpressionParser/Go/GoParser.h" @@ -247,8 +248,9 @@ } bool -GoUserExpression::Parse(Stream &error_stream, ExecutionContext &exe_ctx, lldb_private::ExecutionPolicy execution_policy, - bool keep_result_in_memory, bool generate_debug_info) +GoUserExpression::Parse(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + lldb_private::ExecutionPolicy execution_policy, bool keep_result_in_memory, + bool generate_debug_info) { InstallContext(exe_ctx); m_interpreter.reset(new GoInterpreter(exe_ctx, GetUserText())); @@ -256,15 +258,16 @@ return true; const char *error_cstr = m_interpreter->error().AsCString(); if (error_cstr && error_cstr[0]) - error_stream.Printf("error: %s\n", error_cstr); + diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr); else - error_stream.Printf("error: expression can't be interpreted or run\n"); + diagnostic_manager.Printf(eDiagnosticSeverityError, "expression can't be interpreted or run"); return false; } lldb::ExpressionResults -GoUserExpression::Execute(Stream &error_stream, ExecutionContext &exe_ctx, const EvaluateExpressionOptions &options, - lldb::UserExpressionSP &shared_ptr_to_me, lldb::ExpressionVariableSP &result) +GoUserExpression::Execute(DiagnosticManager &diagnostic_manager, ExecutionContext &exe_ctx, + const EvaluateExpressionOptions &options, lldb::UserExpressionSP &shared_ptr_to_me, + lldb::ExpressionVariableSP &result) { Log *log(lldb_private::GetLogIfAnyCategoriesSet(LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); @@ -281,7 +284,7 @@ if (log) log->Printf("== [GoUserExpression::Evaluate] Expression may not run, but is not constant =="); - error_stream.Printf("expression needed to run but couldn't"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression needed to run but couldn't"); return execution_results; } @@ -296,9 +299,9 @@ { const char *error_cstr = err.AsCString(); if (error_cstr && error_cstr[0]) - error_stream.Printf("error: %s\n", error_cstr); + diagnostic_manager.PutCString(eDiagnosticSeverityError, error_cstr); else - error_stream.Printf("error: expression can't be interpreted or run\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "expression can't be interpreted or run"); return lldb::eExpressionDiscarded; } result.reset(new ExpressionVariable(ExpressionVariable::eKindGo)); Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp =================================================================== --- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -23,6 +23,7 @@ #include "lldb/Core/Section.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" @@ -151,10 +152,10 @@ exe_ctx.SetFrameSP(thread->GetSelectedFrame()); } } - + // Now we're ready to call the function: - - StreamString error_stream; + + DiagnosticManager diagnostics; lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS; if (!m_print_object_caller_up) @@ -172,30 +173,22 @@ strm.Printf("Could not get function runner to call print for debugger function: %s.", error.AsCString()); return false; } - m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr, error_stream); + m_print_object_caller_up->InsertFunction(exe_ctx, wrapper_struct_addr, diagnostics); } else { - m_print_object_caller_up->WriteFunctionArguments(exe_ctx, - wrapper_struct_addr, - arg_value_list, - error_stream); + m_print_object_caller_up->WriteFunctionArguments(exe_ctx, wrapper_struct_addr, arg_value_list, diagnostics); } - - EvaluateExpressionOptions options; options.SetUnwindOnError(true); options.SetTryAllThreads(true); options.SetStopOthers(true); options.SetIgnoreBreakpoints(true); options.SetTimeoutUsec(PO_FUNCTION_TIMEOUT_USEC); - - ExpressionResults results = m_print_object_caller_up->ExecuteFunction (exe_ctx, - &wrapper_struct_addr, - options, - error_stream, - ret); + + ExpressionResults results = + m_print_object_caller_up->ExecuteFunction(exe_ctx, &wrapper_struct_addr, options, diagnostics, ret); if (results != eExpressionCompleted) { strm.Printf("Error evaluating Print Object function: %d.\n", results); Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp =================================================================== --- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -36,6 +36,7 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" #include "lldb/Core/ValueObjectVariable.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Host/StringConvert.h" @@ -1239,13 +1240,13 @@ if (!ast) return false; - + Address function_address; - - StreamString errors; - + + DiagnosticManager diagnostics; + const uint32_t addr_size = process->GetAddressByteSize(); - + Error err; // Read the total number of classes from the hash table @@ -1279,12 +1280,15 @@ } else { - errors.Clear(); - - if (!m_get_class_info_code->Install(errors, exe_ctx)) + diagnostics.Clear(); + + if (!m_get_class_info_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + { + log->Printf("Failed to install implementation lookup"); + diagnostics.Dump(log); + } m_get_class_info_code.reset(); } } @@ -1319,14 +1323,18 @@ if (!get_class_info_function) { if (log) - log->Printf ("Failed to get implementation lookup function caller: %s.", errors.GetData()); + { + log->Printf("Failed to get implementation lookup function caller."); + diagnostics.Dump(log); + } + return false; } arguments = get_class_info_function->GetArgumentValues(); } - errors.Clear(); - + diagnostics.Clear(); + const uint32_t class_info_byte_size = addr_size + 4; const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; lldb::addr_t class_infos_addr = process->AllocateMemory(class_infos_byte_size, @@ -1342,16 +1350,13 @@ arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress(); arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr; arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size; - + bool success = false; - - errors.Clear(); - + + diagnostics.Clear(); + // Write our function arguments into the process so we can run our function - if (get_class_info_function->WriteFunctionArguments (exe_ctx, - m_get_class_info_args, - arguments, - errors)) + if (get_class_info_function->WriteFunctionArguments(exe_ctx, m_get_class_info_args, arguments, diagnostics)) { EvaluateExpressionOptions options; options.SetUnwindOnError(true); @@ -1363,18 +1368,15 @@ Value return_value; return_value.SetValueType (Value::eValueTypeScalar); //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type); - return_value.SetCompilerType (clang_uint32_t_type); + return_value.SetCompilerType(clang_uint32_t_type); return_value.GetScalar() = 0; - - errors.Clear(); - + + diagnostics.Clear(); + // Run the function - ExpressionResults results = get_class_info_function->ExecuteFunction (exe_ctx, - &m_get_class_info_args, - options, - errors, - return_value); - + ExpressionResults results = get_class_info_function->ExecuteFunction(exe_ctx, &m_get_class_info_args, options, + diagnostics, return_value); + if (results == eExpressionCompleted) { // The result is the number of ClassInfo structures that were filled in @@ -1399,15 +1401,21 @@ else { if (log) - log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData()); + { + log->Printf("Error evaluating our find class name function."); + diagnostics.Dump(log); + } } } else { if (log) - log->Printf ("Error writing function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing function arguments."); + diagnostics.Dump(log); + } } - + // Deallocate the memory we allocated for the ClassInfo array process->DeallocateMemory(class_infos_addr); @@ -1483,13 +1491,13 @@ if (!ast) return DescriptorMapUpdateResult::Fail(); - + Address function_address; - - StreamString errors; - + + DiagnosticManager diagnostics; + const uint32_t addr_size = process->GetAddressByteSize(); - + Error err; const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress(); @@ -1528,16 +1536,19 @@ } else { - errors.Clear(); - - if (!m_get_shared_cache_class_info_code->Install(errors, exe_ctx)) + diagnostics.Clear(); + + if (!m_get_shared_cache_class_info_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + { + log->Printf("Failed to install implementation lookup."); + diagnostics.Dump(log); + } m_get_shared_cache_class_info_code.reset(); } } - + if (!m_get_shared_cache_class_info_code.get()) return DescriptorMapUpdateResult::Fail(); @@ -1569,9 +1580,9 @@ return DescriptorMapUpdateResult::Fail(); arguments = get_shared_cache_class_info_function->GetArgumentValues(); } - - errors.Clear(); - + + diagnostics.Clear(); + const uint32_t class_info_byte_size = addr_size + 4; const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; lldb::addr_t class_infos_addr = process->AllocateMemory (class_infos_byte_size, @@ -1587,17 +1598,15 @@ arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr; arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr; arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size; - + bool success = false; bool any_found = false; - - errors.Clear(); - + + diagnostics.Clear(); + // Write our function arguments into the process so we can run our function - if (get_shared_cache_class_info_function->WriteFunctionArguments (exe_ctx, - m_get_shared_cache_class_info_args, - arguments, - errors)) + if (get_shared_cache_class_info_function->WriteFunctionArguments(exe_ctx, m_get_shared_cache_class_info_args, + arguments, diagnostics)) { EvaluateExpressionOptions options; options.SetUnwindOnError(true); @@ -1609,18 +1618,15 @@ Value return_value; return_value.SetValueType (Value::eValueTypeScalar); //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type); - return_value.SetCompilerType (clang_uint32_t_type); + return_value.SetCompilerType(clang_uint32_t_type); return_value.GetScalar() = 0; - - errors.Clear(); - + + diagnostics.Clear(); + // Run the function - ExpressionResults results = get_shared_cache_class_info_function->ExecuteFunction (exe_ctx, - &m_get_shared_cache_class_info_args, - options, - errors, - return_value); - + ExpressionResults results = get_shared_cache_class_info_function->ExecuteFunction( + exe_ctx, &m_get_shared_cache_class_info_args, options, diagnostics, return_value); + if (results == eExpressionCompleted) { // The result is the number of ClassInfo structures that were filled in @@ -1666,15 +1672,21 @@ else { if (log) - log->Printf("Error evaluating our find class name function: %s.\n", errors.GetData()); + { + log->Printf("Error evaluating our find class name function."); + diagnostics.Dump(log); + } } } else { if (log) - log->Printf ("Error writing function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing function arguments."); + diagnostics.Dump(log); + } } - + // Deallocate the memory we allocated for the ClassInfo array process->DeallocateMemory(class_infos_addr); Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp =================================================================== --- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -22,19 +22,20 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UserExpression.h" -#include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Host/FileSpec.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/ABI.h" +#include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" -#include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ThreadPlanRunToAddress.h" #include "llvm/ADT/STLExtras.h" @@ -738,11 +739,11 @@ } lldb::addr_t -AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &dispatch_values) +AppleObjCTrampolineHandler::SetupDispatchFunction(Thread &thread, ValueList &dispatch_values) { - ExecutionContext exe_ctx (thread.shared_from_this()); - StreamString errors; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); + ExecutionContext exe_ctx(thread.shared_from_this()); + DiagnosticManager diagnostics; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_STEP)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; FunctionCaller *impl_function_caller = nullptr; @@ -768,11 +769,14 @@ m_impl_code.reset(); return args_addr; } - - if (!m_impl_code->Install(errors, exe_ctx)) + + if (!m_impl_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + { + log->Printf("Failed to install implementation lookup."); + diagnostics.Dump(log); + } m_impl_code.reset(); return args_addr; } @@ -781,10 +785,8 @@ { if (log) log->Printf("No method lookup implementation code."); - errors.Printf ("No method lookup implementation code found."); return LLDB_INVALID_ADDRESS; } - // Next make the runner function for our implementation utility function. ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext(); @@ -806,20 +808,23 @@ impl_function_caller = m_impl_code->GetFunctionCaller(); } } - - errors.Clear(); - + + diagnostics.Clear(); + // Now write down the argument values for this particular call. This looks like it might be a race condition // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (impl_function_caller->WriteFunctionArguments (exe_ctx, args_addr, dispatch_values, errors)) + if (impl_function_caller->WriteFunctionArguments(exe_ctx, args_addr, dispatch_values, diagnostics)) { if (log) - log->Printf ("Error writing function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing function arguments."); + diagnostics.Dump(log); + } return args_addr; } - + return args_addr; } Index: source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp =================================================================== --- source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp +++ source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp @@ -13,17 +13,17 @@ // Project includes #include "AppleThreadPlanStepThroughObjCTrampoline.h" #include "AppleObjCTrampolineHandler.h" -#include "lldb/Target/Process.h" -#include "lldb/Target/Thread.h" +#include "lldb/Core/Log.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlanRunToAddress.h" #include "lldb/Target/ThreadPlanStepOut.h" -#include "lldb/Core/Log.h" - using namespace lldb; using namespace lldb_private; @@ -75,9 +75,9 @@ { if (!m_func_sp) { - StreamString errors; + DiagnosticManager diagnostics; m_args_addr = m_trampoline_handler->SetupDispatchFunction(m_thread, m_input_values); - + if (m_args_addr == LLDB_INVALID_ADDRESS) { return false; @@ -89,12 +89,9 @@ options.SetIgnoreBreakpoints(true); options.SetStopOthers(m_stop_others); m_thread.CalculateExecutionContext(exc_ctx); - m_func_sp = m_impl_function->GetThreadPlanToCallFunction (exc_ctx, - m_args_addr, - options, - errors); + m_func_sp = m_impl_function->GetThreadPlanToCallFunction(exc_ctx, m_args_addr, options, diagnostics); m_func_sp->SetOkayToDiscard(true); - m_thread.QueueThreadPlan (m_func_sp, false); + m_thread.QueueThreadPlan(m_func_sp, false); } return true; } Index: source/Plugins/Process/Utility/InferiorCallPOSIX.cpp =================================================================== --- source/Plugins/Process/Utility/InferiorCallPOSIX.cpp +++ source/Plugins/Process/Utility/InferiorCallPOSIX.cpp @@ -11,6 +11,8 @@ #include "lldb/Core/Address.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/ValueObject.h" +#include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Host/Config.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/SymbolContext.h" #include "lldb/Target/ExecutionContext.h" @@ -18,7 +20,6 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadPlanCallFunction.h" -#include "lldb/Host/Config.h" #ifndef LLDB_DISABLE_POSIX #include @@ -96,27 +97,21 @@ ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); lldb::addr_t args[] = { addr, length, prot_arg, flags_arg, fd, offset }; - lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, - mmap_range.GetBaseAddress(), - clang_void_ptr_type, - args, - options)); + lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallFunction(*thread, mmap_range.GetBaseAddress(), + clang_void_ptr_type, args, options)); if (call_plan_sp) { - StreamFile error_strm; - - StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); + DiagnosticManager diagnostics; + + StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); if (frame) { ExecutionContext exe_ctx; frame->CalculateExecutionContext (exe_ctx); - ExpressionResults result = process->RunThreadPlan (exe_ctx, - call_plan_sp, - options, - error_strm); + ExpressionResults result = process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); if (result == eExpressionCompleted) { - + allocated_addr = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); if (process->GetAddressByteSize() == 4) { @@ -179,24 +174,18 @@ if (sc.GetAddressRange(range_scope, 0, use_inline_block_range, munmap_range)) { lldb::addr_t args[] = { addr, length }; - lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, - munmap_range.GetBaseAddress(), - CompilerType(), - args, - options)); + lldb::ThreadPlanSP call_plan_sp( + new ThreadPlanCallFunction(*thread, munmap_range.GetBaseAddress(), CompilerType(), args, options)); if (call_plan_sp) { - StreamFile error_strm; - - StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); + DiagnosticManager diagnostics; + + StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); if (frame) { ExecutionContext exe_ctx; frame->CalculateExecutionContext (exe_ctx); - ExpressionResults result = process->RunThreadPlan (exe_ctx, - call_plan_sp, - options, - error_strm); + ExpressionResults result = process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); if (result == eExpressionCompleted) { return true; @@ -234,24 +223,18 @@ ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext(); CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - lldb::ThreadPlanSP call_plan_sp (new ThreadPlanCallFunction (*thread, - *address, - clang_void_ptr_type, - llvm::ArrayRef(), - options)); + lldb::ThreadPlanSP call_plan_sp( + new ThreadPlanCallFunction(*thread, *address, clang_void_ptr_type, llvm::ArrayRef(), options)); if (call_plan_sp) { - StreamString error_strm; + DiagnosticManager diagnostics; - StackFrame *frame = thread->GetStackFrameAtIndex (0).get(); + StackFrame *frame = thread->GetStackFrameAtIndex(0).get(); if (frame) { ExecutionContext exe_ctx; frame->CalculateExecutionContext (exe_ctx); - ExpressionResults result = process->RunThreadPlan (exe_ctx, - call_plan_sp, - options, - error_strm); + ExpressionResults result = process->RunThreadPlan(exe_ctx, call_plan_sp, options, diagnostics); if (result == eExpressionCompleted) { returned_func = call_plan_sp->GetReturnValueObject()->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); Index: source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp =================================================================== --- source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp +++ source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" @@ -132,11 +133,11 @@ // make the function call. lldb::addr_t -AppleGetItemInfoHandler::SetupGetItemInfoFunction (Thread &thread, ValueList &get_item_info_arglist) +AppleGetItemInfoHandler::SetupGetItemInfoFunction(Thread &thread, ValueList &get_item_info_arglist) { - ExecutionContext exe_ctx (thread.shared_from_this()); - StreamString errors; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); + ExecutionContext exe_ctx(thread.shared_from_this()); + DiagnosticManager diagnostics; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; FunctionCaller *get_item_info_caller = nullptr; @@ -161,11 +162,14 @@ log->Printf ("Failed to get utility function: %s.", error.AsCString()); return args_addr; } - - if (!m_get_item_info_impl_code->Install(errors, exe_ctx)) + + if (!m_get_item_info_impl_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install get-item-info introspection: %s.", errors.GetData()); + { + log->Printf("Failed to install get-item-info introspection."); + diagnostics.Dump(log); + } m_get_item_info_impl_code.reset(); return args_addr; } @@ -174,7 +178,6 @@ { if (log) log->Printf("No get-item-info introspection code found."); - errors.Printf ("No get-item-info introspection code found."); return LLDB_INVALID_ADDRESS; } @@ -207,20 +210,24 @@ } } } - - errors.Clear(); - + + diagnostics.Clear(); + // Now write down the argument values for this particular call. This looks like it might be a race condition // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (!get_item_info_caller->WriteFunctionArguments (exe_ctx, args_addr, get_item_info_arglist, errors)) + if (!get_item_info_caller->WriteFunctionArguments(exe_ctx, args_addr, get_item_info_arglist, diagnostics)) { if (log) - log->Printf ("Error writing get-item-info function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing get-item-info function arguments."); + diagnostics.Dump(log); + } + return args_addr; } - + return args_addr; } @@ -322,12 +329,12 @@ page_to_free_size_value.GetScalar() = page_to_free_size; argument_values.PushValue (page_to_free_size_value); - addr_t args_addr = SetupGetItemInfoFunction (thread, argument_values); + addr_t args_addr = SetupGetItemInfoFunction(thread, argument_values); - StreamString errors; + DiagnosticManager diagnostics; ExecutionContext exe_ctx; EvaluateExpressionOptions options; - options.SetUnwindOnError (true); + options.SetUnwindOnError(true); options.SetIgnoreBreakpoints (true); options.SetStopOthers (true); options.SetTimeoutUsec(500000); @@ -351,8 +358,8 @@ error.SetErrorString("Could not retrieve function caller for __introspection_dispatch_queue_item_get_info."); return return_value; } - - func_call_ret = func_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + + func_call_ret = func_caller->ExecuteFunction(exe_ctx, &args_addr, options, diagnostics, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) Index: source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp =================================================================== --- source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp +++ source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp @@ -19,6 +19,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" @@ -136,14 +137,14 @@ // make the function call. lldb::addr_t -AppleGetPendingItemsHandler::SetupGetPendingItemsFunction (Thread &thread, ValueList &get_pending_items_arglist) +AppleGetPendingItemsHandler::SetupGetPendingItemsFunction(Thread &thread, ValueList &get_pending_items_arglist) { - ExecutionContext exe_ctx (thread.shared_from_this()); - StreamString errors; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); + ExecutionContext exe_ctx(thread.shared_from_this()); + DiagnosticManager diagnostics; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; FunctionCaller *get_pending_items_caller = nullptr; - + // Scope for mutex locker: { Mutex::Locker locker(m_get_pending_items_function_mutex); @@ -165,11 +166,14 @@ log->Printf ("Failed to get UtilityFunction for pending-items introspection: %s.", error.AsCString()); return args_addr; } - - if (!m_get_pending_items_impl_code->Install(errors, exe_ctx)) + + if (!m_get_pending_items_impl_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install pending-items introspection: %s.", errors.GetData()); + { + log->Printf("Failed to install pending-items introspection."); + diagnostics.Dump(log); + } m_get_pending_items_impl_code.reset(); return args_addr; } @@ -196,11 +200,10 @@ return args_addr; } } + } - } - - errors.Clear(); - + diagnostics.Clear(); + if (get_pending_items_caller == nullptr) { if (log) @@ -212,13 +215,17 @@ // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (!get_pending_items_caller->WriteFunctionArguments (exe_ctx, args_addr, get_pending_items_arglist, errors)) + if (!get_pending_items_caller->WriteFunctionArguments(exe_ctx, args_addr, get_pending_items_arglist, diagnostics)) { if (log) - log->Printf ("Error writing pending-items function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing pending-items function arguments."); + diagnostics.Dump(log); + } + return args_addr; } - + return args_addr; } @@ -322,12 +329,12 @@ page_to_free_size_value.GetScalar() = page_to_free_size; argument_values.PushValue (page_to_free_size_value); - addr_t args_addr = SetupGetPendingItemsFunction (thread, argument_values); + addr_t args_addr = SetupGetPendingItemsFunction(thread, argument_values); - StreamString errors; + DiagnosticManager diagnostics; ExecutionContext exe_ctx; FunctionCaller *get_pending_items_caller = m_get_pending_items_impl_code->GetFunctionCaller(); - + EvaluateExpressionOptions options; options.SetUnwindOnError (true); options.SetIgnoreBreakpoints (true); @@ -342,10 +349,9 @@ return return_value; } - ExpressionResults func_call_ret; Value results; - func_call_ret = get_pending_items_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + func_call_ret = get_pending_items_caller->ExecuteFunction(exe_ctx, &args_addr, options, diagnostics, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) Index: source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp =================================================================== --- source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp +++ source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp @@ -18,6 +18,7 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" @@ -146,12 +147,12 @@ lldb::addr_t AppleGetQueuesHandler::SetupGetQueuesFunction (Thread &thread, ValueList &get_queues_arglist) { - ExecutionContext exe_ctx (thread.shared_from_this()); + ExecutionContext exe_ctx(thread.shared_from_this()); Address impl_code_address; - StreamString errors; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); + DiagnosticManager diagnostics; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; - + FunctionCaller *get_queues_caller = nullptr; // Scope for mutex locker: @@ -175,11 +176,14 @@ log->Printf ("Failed to get UtilityFunction for queues introspection: %s.", error.AsCString()); return args_addr; } - - if (!m_get_queues_impl_code_up->Install(errors, exe_ctx)) + + if (!m_get_queues_impl_code_up->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install queues introspection: %s.", errors.GetData()); + { + log->Printf("Failed to install queues introspection"); + diagnostics.Dump(log); + } m_get_queues_impl_code_up.reset(); return args_addr; } @@ -187,12 +191,14 @@ else { if (log) + { log->Printf("No queues introspection code found."); - errors.Printf ("No queues introspection code found."); + diagnostics.Dump(log); + } return LLDB_INVALID_ADDRESS; } } - + // Next make the runner function for our implementation utility function. ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext(); CompilerType get_queues_return_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); @@ -207,20 +213,23 @@ return args_addr; } } - - errors.Clear(); - + + diagnostics.Clear(); + // Now write down the argument values for this particular call. This looks like it might be a race condition // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (!get_queues_caller->WriteFunctionArguments (exe_ctx, args_addr, get_queues_arglist, errors)) + if (!get_queues_caller->WriteFunctionArguments(exe_ctx, args_addr, get_queues_arglist, diagnostics)) { if (log) - log->Printf ("Error writing get-queues function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing get-queues function arguments."); + diagnostics.Dump(log); + } return args_addr; } - + return args_addr; } @@ -332,10 +341,10 @@ return return_value; } - StreamString errors; + DiagnosticManager diagnostics; ExecutionContext exe_ctx; EvaluateExpressionOptions options; - options.SetUnwindOnError (true); + options.SetUnwindOnError(true); options.SetIgnoreBreakpoints (true); options.SetStopOthers (true); options.SetTimeoutUsec(500000); @@ -344,7 +353,7 @@ ExpressionResults func_call_ret; Value results; - func_call_ret = get_queues_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + func_call_ret = get_queues_caller->ExecuteFunction(exe_ctx, &args_addr, options, diagnostics, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) Index: source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp =================================================================== --- source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp +++ source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp @@ -14,12 +14,12 @@ // Other libraries and framework includes // Project includes -#include "lldb/lldb-private.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" +#include "lldb/Expression/DiagnosticManager.h" #include "lldb/Expression/Expression.h" #include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/UtilityFunction.h" @@ -30,6 +30,7 @@ #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" +#include "lldb/lldb-private.h" using namespace lldb; using namespace lldb_private; @@ -141,10 +142,10 @@ lldb::addr_t AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction (Thread &thread, ValueList &get_thread_item_info_arglist) { - ExecutionContext exe_ctx (thread.shared_from_this()); + ExecutionContext exe_ctx(thread.shared_from_this()); Address impl_code_address; - StreamString errors; - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); + DiagnosticManager diagnostics; + Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_SYSTEM_RUNTIME)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; FunctionCaller *get_thread_item_info_caller = nullptr; @@ -171,11 +172,15 @@ m_get_thread_item_info_impl_code.reset(); return args_addr; } - - if (!m_get_thread_item_info_impl_code->Install(errors, exe_ctx)) + + if (!m_get_thread_item_info_impl_code->Install(diagnostics, exe_ctx)) { if (log) - log->Printf ("Failed to install get-thread-item-info introspection: %s.", errors.GetData()); + { + log->Printf("Failed to install get-thread-item-info introspection."); + diagnostics.Dump(log); + } + m_get_thread_item_info_impl_code.reset(); return args_addr; } @@ -184,10 +189,9 @@ { if (log) log->Printf("No get-thread-item-info introspection code found."); - errors.Printf ("No get-thread-item-info introspection code found."); return LLDB_INVALID_ADDRESS; } - + // Also make the FunctionCaller for this UtilityFunction: ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext(); @@ -210,20 +214,24 @@ get_thread_item_info_caller = m_get_thread_item_info_impl_code->GetFunctionCaller(); } } - - errors.Clear(); - + + diagnostics.Clear(); + // Now write down the argument values for this particular call. This looks like it might be a race condition // if other threads were calling into here, but actually it isn't because we allocate a new args structure for // this call by passing args_addr = LLDB_INVALID_ADDRESS... - if (!get_thread_item_info_caller->WriteFunctionArguments (exe_ctx, args_addr, get_thread_item_info_arglist, errors)) + if (!get_thread_item_info_caller->WriteFunctionArguments(exe_ctx, args_addr, get_thread_item_info_arglist, + diagnostics)) { if (log) - log->Printf ("Error writing get-thread-item-info function arguments: \"%s\".", errors.GetData()); + { + log->Printf("Error writing get-thread-item-info function arguments"); + diagnostics.Dump(log); + } return args_addr; } - + return args_addr; } @@ -324,13 +332,13 @@ page_to_free_size_value.GetScalar() = page_to_free_size; argument_values.PushValue (page_to_free_size_value); - addr_t args_addr = SetupGetThreadItemInfoFunction (thread, argument_values); + addr_t args_addr = SetupGetThreadItemInfoFunction(thread, argument_values); - StreamString errors; + DiagnosticManager diagnostics; ExecutionContext exe_ctx; EvaluateExpressionOptions options; FunctionCaller *get_thread_item_info_caller = nullptr; - + options.SetUnwindOnError (true); options.SetIgnoreBreakpoints (true); options.SetStopOthers (true); @@ -354,7 +362,7 @@ ExpressionResults func_call_ret; Value results; - func_call_ret = get_thread_item_info_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + func_call_ret = get_thread_item_info_caller->ExecuteFunction(exe_ctx, &args_addr, options, diagnostics, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) Index: source/Symbol/ClangASTContext.cpp =================================================================== --- source/Symbol/ClangASTContext.cpp +++ source/Symbol/ClangASTContext.cpp @@ -685,8 +685,9 @@ { m_log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS); } - - void HandleDiagnostic (DiagnosticsEngine::Level DiagLevel, const Diagnostic &info) + + void + HandleDiagnostic(DiagnosticsEngine::Level DiagLevel, const clang::Diagnostic &info) { if (m_log) { Index: source/Target/Process.cpp =================================================================== --- source/Target/Process.cpp +++ source/Target/Process.cpp @@ -14,19 +14,20 @@ // Other libraries and framework includes // Project includes -#include "lldb/Target/Process.h" +#include "Plugins/Process/Utility/InferiorCallPOSIX.h" +#include "lldb/Breakpoint/BreakpointLocation.h" #include "lldb/Breakpoint/StoppointCallbackContext.h" -#include "lldb/Breakpoint/BreakpointLocation.h" +#include "lldb/Core/Debugger.h" #include "lldb/Core/Event.h" -#include "lldb/Core/Debugger.h" #include "lldb/Core/Log.h" #include "lldb/Core/Module.h" #include "lldb/Core/ModuleSpec.h" #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamFile.h" +#include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Expression/UserExpression.h" -#include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/FileSystem.h" #include "lldb/Host/Host.h" @@ -39,17 +40,18 @@ #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/ABI.h" +#include "lldb/Target/CPPLanguageRuntime.h" #include "lldb/Target/DynamicLoader.h" #include "lldb/Target/InstrumentationRuntime.h" #include "lldb/Target/JITLoader.h" #include "lldb/Target/JITLoaderList.h" +#include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/MemoryHistory.h" #include "lldb/Target/MemoryRegionInfo.h" +#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/OperatingSystem.h" -#include "lldb/Target/LanguageRuntime.h" -#include "lldb/Target/CPPLanguageRuntime.h" -#include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Platform.h" +#include "lldb/Target/Process.h" #include "lldb/Target/RegisterContext.h" #include "lldb/Target/StopInfo.h" #include "lldb/Target/SystemRuntime.h" @@ -60,7 +62,6 @@ #include "lldb/Target/ThreadPlanBase.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/NameMatches.h" -#include "Plugins/Process/Utility/InferiorCallPOSIX.h" using namespace lldb; using namespace lldb_private; @@ -5194,35 +5195,33 @@ } // anonymous namespace ExpressionResults -Process::RunThreadPlan (ExecutionContext &exe_ctx, - lldb::ThreadPlanSP &thread_plan_sp, - const EvaluateExpressionOptions &options, - Stream &errors) +Process::RunThreadPlan(ExecutionContext &exe_ctx, lldb::ThreadPlanSP &thread_plan_sp, + const EvaluateExpressionOptions &options, DiagnosticManager &diagnostic_manager) { ExpressionResults return_value = eExpressionSetupError; if (!thread_plan_sp) { - errors.Printf("RunThreadPlan called with empty thread plan."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "RunThreadPlan called with empty thread plan."); return eExpressionSetupError; } if (!thread_plan_sp->ValidatePlan(nullptr)) { - errors.Printf ("RunThreadPlan called with an invalid thread plan."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "RunThreadPlan called with an invalid thread plan."); return eExpressionSetupError; } if (exe_ctx.GetProcessPtr() != this) { - errors.Printf("RunThreadPlan called on wrong process."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "RunThreadPlan called on wrong process."); return eExpressionSetupError; } Thread *thread = exe_ctx.GetThreadPtr(); if (thread == nullptr) { - errors.Printf("RunThreadPlan called with invalid thread."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, "RunThreadPlan called with invalid thread."); return eExpressionSetupError; } @@ -5245,7 +5244,8 @@ if (m_private_state.GetValue() != eStateStopped) { - errors.Printf ("RunThreadPlan called while the private state was not stopped."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "RunThreadPlan called while the private state was not stopped."); return eExpressionSetupError; } @@ -5258,7 +5258,8 @@ selected_frame_sp = thread->GetSelectedFrame(); if (!selected_frame_sp) { - errors.Printf("RunThreadPlan called without a selected frame on thread %d", thread_idx_id); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "RunThreadPlan called without a selected frame on thread %d", thread_idx_id); return eExpressionSetupError; } } @@ -5400,7 +5401,9 @@ { if (timeout_usec < option_one_thread_timeout) { - errors.Printf("RunThreadPlan called without one thread timeout greater than total timeout"); + diagnostic_manager.PutCString( + eDiagnosticSeverityError, + "RunThreadPlan called without one thread timeout greater than total timeout"); return eExpressionSetupError; } computed_one_thread_timeout = option_one_thread_timeout; @@ -5431,7 +5434,8 @@ Event *other_events = listener_sp->PeekAtNextEvent(); if (other_events != nullptr) { - errors.Printf("Calling RunThreadPlan with pending events on the queue."); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "RunThreadPlan called with pending events on the queue."); return eExpressionSetupError; } @@ -5473,12 +5477,12 @@ if (do_resume) { num_resumes++; - Error resume_error = PrivateResume (); + Error resume_error = PrivateResume(); if (!resume_error.Success()) { - errors.Printf("Error resuming inferior the %d time: \"%s\".\n", - num_resumes, - resume_error.AsCString()); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "couldn't resume inferior the %d time: \"%s\".", num_resumes, + resume_error.AsCString()); return_value = eExpressionSetupError; break; } @@ -5491,10 +5495,11 @@ if (!got_event) { if (log) - log->Printf ("Process::RunThreadPlan(): didn't get any event after resume %d, exiting.", - num_resumes); + log->Printf("Process::RunThreadPlan(): didn't get any event after resume %" PRIu32 ", exiting.", + num_resumes); - errors.Printf("Didn't get any event after resume %d, exiting.", num_resumes); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "didn't get any event after resume %" PRIu32 ", exiting.", num_resumes); return_value = eExpressionSetupError; break; } @@ -5527,8 +5532,9 @@ Halt(clear_thread_plans, use_run_lock); } - errors.Printf("Didn't get running event after initial resume, got %s instead.", - StateAsCString(stop_state)); + diagnostic_manager.Printf(eDiagnosticSeverityError, + "didn't get running event after initial resume, got %s instead.", + StateAsCString(stop_state)); return_value = eExpressionSetupError; break; } @@ -5622,9 +5628,10 @@ const bool use_run_lock = false; Halt(clear_thread_plans, use_run_lock); return_value = eExpressionInterrupted; - errors.Printf ("Execution halted by user interrupt."); + diagnostic_manager.PutCString(eDiagnosticSeverityRemark, "execution halted by user interrupt."); if (log) - log->Printf ("Process::RunThreadPlan(): Got interrupted by eBroadcastBitInterrupted, exiting."); + log->Printf( + "Process::RunThreadPlan(): Got interrupted by eBroadcastBitInterrupted, exiting."); break; } else @@ -5727,7 +5734,8 @@ if (stop_state == eStateExited) event_to_broadcast_sp = event_sp; - errors.Printf ("Execution stopped with unexpected state.\n"); + diagnostic_manager.PutCString(eDiagnosticSeverityError, + "execution stopped with unexpected state."); return_value = eExpressionInterrupted; break; } Index: source/Target/ThreadPlanCallUserExpression.cpp =================================================================== --- source/Target/ThreadPlanCallUserExpression.cpp +++ source/Target/ThreadPlanCallUserExpression.cpp @@ -19,8 +19,9 @@ #include "lldb/Core/Address.h" #include "lldb/Core/Log.h" #include "lldb/Core/Stream.h" +#include "lldb/Expression/DiagnosticManager.h" +#include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Expression/UserExpression.h" -#include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Host/HostInfo.h" #include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/Process.h" @@ -90,15 +91,16 @@ function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); function_stack_top = function_stack_pointer; - - StreamString error_stream; - + + DiagnosticManager diagnostics; + ExecutionContext exe_ctx(GetThread()); - m_user_expression_sp->FinalizeJITExecution(error_stream, exe_ctx, m_result_var_sp, function_stack_bottom, function_stack_top); + m_user_expression_sp->FinalizeJITExecution(diagnostics, exe_ctx, m_result_var_sp, function_stack_bottom, + function_stack_top); } - - ThreadPlan::MischiefManaged (); + + ThreadPlan::MischiefManaged(); return true; } else