diff options
author | Jim Ingham <jingham@apple.com> | 2015-09-15 21:13:50 +0000 |
---|---|---|
committer | Jim Ingham <jingham@apple.com> | 2015-09-15 21:13:50 +0000 |
commit | 151c032c86aa7de4244a9ed52d420ecb09550d0b (patch) | |
tree | 44f8d890499ac2e99bb2a4fd50975f7c986d72a8 /lldb/source | |
parent | 01fa3f96b37499e43d0d26b46151268b1b891342 (diff) | |
download | bcm5719-llvm-151c032c86aa7de4244a9ed52d420ecb09550d0b.tar.gz bcm5719-llvm-151c032c86aa7de4244a9ed52d420ecb09550d0b.zip |
This patch makes Clang-independent base classes for all the expression types that lldb currently vends.
Before we had:
ClangFunction
ClangUtilityFunction
ClangUserExpression
and code all over in lldb that explicitly made Clang-based expressions. This patch adds an Expression
base class, and three pure virtual implementations for the Expression kinds:
FunctionCaller
UtilityFunction
UserExpression
You can request one of these expression types from the Target using the Get<ExpressionType>ForLanguage.
The Target will then consult all the registered TypeSystem plugins, and if the type system that matches
the language can make an expression of that kind, it will do so and return it.
Because all of the real expression types need to communicate with their ExpressionParser in a uniform way,
I also added a ExpressionTypeSystemHelper class that expressions generically can vend, and a ClangExpressionHelper
that encapsulates the operations that the ClangExpressionParser needs to perform on the ClangExpression types.
Then each of the Clang* expression kinds constructs the appropriate helper to do what it needs.
The patch also fixes a wart in the UtilityFunction that to use it you had to create a parallel FunctionCaller
to actually call the function made by the UtilityFunction. Now the UtilityFunction can be asked to vend a
FunctionCaller that will run its function. This cleaned up a lot of boiler plate code using UtilityFunctions.
Note, in this patch all the expression types explicitly depend on the LLVM JIT and IR, and all the common
JIT running code is in the FunctionCaller etc base classes. At some point we could also abstract that dependency
but I don't see us adding another back end in the near term, so I'll leave that exercise till it is actually necessary.
llvm-svn: 247720
Diffstat (limited to 'lldb/source')
47 files changed, 1736 insertions, 1439 deletions
diff --git a/lldb/source/API/SBFrame.cpp b/lldb/source/API/SBFrame.cpp index df6cc51ed07..ee467402569 100644 --- a/lldb/source/API/SBFrame.cpp +++ b/lldb/source/API/SBFrame.cpp @@ -22,7 +22,7 @@ #include "lldb/Core/ValueObjectRegister.h" #include "lldb/Core/ValueObjectVariable.h" #include "lldb/Expression/ClangPersistentVariables.h" -#include "lldb/Expression/ClangUserExpression.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Host/Host.h" #include "lldb/Symbol/Block.h" #include "lldb/Symbol/Function.h" diff --git a/lldb/source/Breakpoint/BreakpointLocation.cpp b/lldb/source/Breakpoint/BreakpointLocation.cpp index 1d082f69416..0dab0e16bf1 100644 --- a/lldb/source/Breakpoint/BreakpointLocation.cpp +++ b/lldb/source/Breakpoint/BreakpointLocation.cpp @@ -21,9 +21,10 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObject.h" -#include "lldb/Expression/ClangUserExpression.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Symbol/CompileUnit.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Symbol/TypeSystem.h" #include "lldb/Target/Target.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" @@ -88,6 +89,12 @@ BreakpointLocation::GetBreakpoint () return m_owner; } +Target & +BreakpointLocation::GetTarget() +{ + return m_owner.GetTarget(); +} + bool BreakpointLocation::IsEnabled () const { @@ -278,10 +285,26 @@ BreakpointLocation::ConditionSaysStop (ExecutionContext &exe_ctx, Error &error) !m_user_expression_sp || !m_user_expression_sp->MatchesContext(exe_ctx)) { - m_user_expression_sp.reset(new ClangUserExpression(condition_text, - NULL, - lldb::eLanguageTypeUnknown, - ClangUserExpression::eResultTypeAny)); + LanguageType language = eLanguageTypeUnknown; + // See if we can figure out the language from the frame, otherwise use the default language: + CompileUnit *comp_unit = m_address.CalculateSymbolContextCompileUnit(); + if (comp_unit) + language = comp_unit->GetLanguage(); + + Error error; + m_user_expression_sp.reset(GetTarget().GetUserExpressionForLanguage(condition_text, + NULL, + language, + Expression::eResultTypeAny, + error)); + if (error.Fail()) + { + if (log) + log->Printf("Error getting condition expression: %s.", error.AsCString()); + m_user_expression_sp.reset(); + return true; + } + StreamString errors; diff --git a/lldb/source/Breakpoint/BreakpointOptions.cpp b/lldb/source/Breakpoint/BreakpointOptions.cpp index db76ffb8685..99a4d47a8d9 100644 --- a/lldb/source/Breakpoint/BreakpointOptions.cpp +++ b/lldb/source/Breakpoint/BreakpointOptions.cpp @@ -20,7 +20,6 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" -#include "lldb/Expression/ClangUserExpression.h" using namespace lldb; using namespace lldb_private; diff --git a/lldb/source/Breakpoint/Watchpoint.cpp b/lldb/source/Breakpoint/Watchpoint.cpp index af9cfaff6a2..41b24fd67df 100644 --- a/lldb/source/Breakpoint/Watchpoint.cpp +++ b/lldb/source/Breakpoint/Watchpoint.cpp @@ -22,7 +22,7 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" -#include "lldb/Expression/ClangUserExpression.h" +#include "lldb/Expression/UserExpression.h" using namespace lldb; using namespace lldb_private; @@ -371,7 +371,17 @@ Watchpoint::SetCondition (const char *condition) else { // Pass NULL for expr_prefix (no translation-unit level definitions). - m_condition_ap.reset(new ClangUserExpression (condition, NULL, lldb::eLanguageTypeUnknown, ClangUserExpression::eResultTypeAny)); + Error error; + m_condition_ap.reset(m_target.GetUserExpressionForLanguage (condition, + NULL, + lldb::eLanguageTypeUnknown, + UserExpression::eResultTypeAny, + error)); + if (error.Fail()) + { + // FIXME: Log something... + m_condition_ap.reset(); + } } SendWatchpointChangedEvent (eWatchpointEventTypeConditionChanged); } diff --git a/lldb/source/Breakpoint/WatchpointOptions.cpp b/lldb/source/Breakpoint/WatchpointOptions.cpp index c2c9696c4ce..d11c8f74f94 100644 --- a/lldb/source/Breakpoint/WatchpointOptions.cpp +++ b/lldb/source/Breakpoint/WatchpointOptions.cpp @@ -20,7 +20,6 @@ #include "lldb/Target/Process.h" #include "lldb/Target/Target.h" #include "lldb/Target/ThreadSpec.h" -#include "lldb/Expression/ClangUserExpression.h" using namespace lldb; using namespace lldb_private; diff --git a/lldb/source/Commands/CommandObjectArgs.cpp b/lldb/source/Commands/CommandObjectArgs.cpp index 39dcba07cca..c4db97caa6a 100644 --- a/lldb/source/Commands/CommandObjectArgs.cpp +++ b/lldb/source/Commands/CommandObjectArgs.cpp @@ -17,9 +17,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/Module.h" #include "lldb/Core/Value.h" -#include "lldb/Expression/ClangExpression.h" #include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" -#include "lldb/Expression/ClangFunction.h" #include "lldb/Host/Host.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 7e787bce8c9..96dd90e7ecc 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -17,8 +17,7 @@ #include "lldb/Core/ValueObjectVariable.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" #include "Plugins/ExpressionParser/Clang/ClangExpressionVariable.h" -#include "lldb/Expression/ClangUserExpression.h" -#include "lldb/Expression/ClangFunction.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Host/Host.h" #include "lldb/Host/StringConvert.h" @@ -345,7 +344,7 @@ CommandObjectExpression::EvaluateExpression } else { - if (result_valobj_sp->GetError().GetError() == ClangUserExpression::kNoResult) + if (result_valobj_sp->GetError().GetError() == UserExpression::kNoResult) { if (format != eFormatVoid && m_interpreter.GetDebugger().GetNotifyVoid()) { diff --git a/lldb/source/DataFormatters/VectorType.cpp b/lldb/source/DataFormatters/VectorType.cpp index faef33de909..56ca3ceac2a 100644 --- a/lldb/source/DataFormatters/VectorType.cpp +++ b/lldb/source/DataFormatters/VectorType.cpp @@ -235,7 +235,7 @@ namespace lldb_private { TargetSP target_sp(m_backend.GetTargetSP()); m_child_type = ::GetCompilerTypeForFormat(m_parent_format, element_type, - target_sp ? target_sp->GetTypeSystemForLanguage(lldb::eLanguageTypeC) : nullptr); + target_sp ? target_sp->GetScratchTypeSystemForLanguage(lldb::eLanguageTypeC) : nullptr); m_num_children = ::CalculateNumChildren(parent_type, m_child_type); m_item_format = GetItemFormatForFormat(m_parent_format, diff --git a/lldb/source/Expression/ASTStructExtractor.cpp b/lldb/source/Expression/ASTStructExtractor.cpp index 98628dbc92b..049173e32f3 100644 --- a/lldb/source/Expression/ASTStructExtractor.cpp +++ b/lldb/source/Expression/ASTStructExtractor.cpp @@ -28,7 +28,7 @@ using namespace lldb_private; ASTStructExtractor::ASTStructExtractor(ASTConsumer *passthrough, const char *struct_name, - ClangFunction &function) : + ClangFunctionCaller &function) : m_ast_context (NULL), m_passthrough (passthrough), m_passthrough_sema (NULL), diff --git a/lldb/source/Expression/CMakeLists.txt b/lldb/source/Expression/CMakeLists.txt index 92f8f0863bf..4b689da027b 100644 --- a/lldb/source/Expression/CMakeLists.txt +++ b/lldb/source/Expression/CMakeLists.txt @@ -5,18 +5,22 @@ add_lldb_library(lldbExpression ClangASTSource.cpp ClangExpressionDeclMap.cpp ClangExpressionParser.cpp - ClangFunction.cpp + ClangFunctionCaller.cpp ClangModulesDeclVendor.cpp ClangPersistentVariables.cpp ClangUserExpression.cpp ClangUtilityFunction.cpp DWARFExpression.cpp + Expression.cpp ExpressionSourceCode.cpp ExpressionVariable.cpp + FunctionCaller.cpp IRDynamicChecks.cpp IRExecutionUnit.cpp IRForTarget.cpp IRInterpreter.cpp IRMemoryMap.cpp Materializer.cpp + UserExpression.cpp + UtilityFunction.cpp ) diff --git a/lldb/source/Expression/ClangASTSource.cpp b/lldb/source/Expression/ClangASTSource.cpp index ef778a1bca4..e6ddaa7e506 100644 --- a/lldb/source/Expression/ClangASTSource.cpp +++ b/lldb/source/Expression/ClangASTSource.cpp @@ -15,7 +15,6 @@ #include "lldb/Core/ModuleList.h" #include "lldb/Expression/ASTDumper.h" #include "lldb/Expression/ClangASTSource.h" -#include "lldb/Expression/ClangExpression.h" #include "lldb/Expression/ClangModulesDeclVendor.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/CompilerDeclContext.h" diff --git a/lldb/source/Expression/ClangExpressionParser.cpp b/lldb/source/Expression/ClangExpressionParser.cpp index d5dbaf16b4a..2a4663966cf 100644 --- a/lldb/source/Expression/ClangExpressionParser.cpp +++ b/lldb/source/Expression/ClangExpressionParser.cpp @@ -19,7 +19,7 @@ #include "lldb/Core/StreamFile.h" #include "lldb/Core/StreamString.h" #include "lldb/Expression/ClangASTSource.h" -#include "lldb/Expression/ClangExpression.h" +#include "lldb/Expression/ClangExpressionHelper.h" #include "lldb/Expression/ClangExpressionDeclMap.h" #include "lldb/Expression/ClangModulesDeclVendor.h" #include "lldb/Expression/ClangPersistentVariables.h" @@ -37,6 +37,7 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/ExternalASTSource.h" #include "clang/Basic/FileManager.h" +#include "clang/Basic/SourceLocation.h" #include "clang/Basic/TargetInfo.h" #include "clang/Basic/Version.h" #include "clang/CodeGen/CodeGenAction.h" @@ -108,7 +109,7 @@ public: } virtual void moduleImport(SourceLocation import_location, - ModuleIdPath path, + clang::ModuleIdPath path, const clang::Module * /*null*/) { std::vector<ConstString> string_path; @@ -149,9 +150,9 @@ public: //===----------------------------------------------------------------------===// ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, - ClangExpression &expr, + Expression &expr, bool generate_debug_info) : - m_expr (expr), + ExpressionParser (exe_scope, expr, generate_debug_info), m_compiler (), m_code_generator (), m_pp_callbacks(nullptr) @@ -255,7 +256,7 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, m_compiler->getLangOpts().WChar = true; m_compiler->getLangOpts().Blocks = true; m_compiler->getLangOpts().DebuggerSupport = true; // Features specifically for debugger clients - if (expr.DesiredResultType() == ClangExpression::eResultTypeId) + if (expr.DesiredResultType() == Expression::eResultTypeId) m_compiler->getLangOpts().DebuggerCastResultToId = true; m_compiler->getLangOpts().CharIsSigned = @@ -346,7 +347,8 @@ ClangExpressionParser::ClangExpressionParser (ExecutionContextScope *exe_scope, ast_context->InitBuiltinTypes(m_compiler->getTarget()); - ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); + ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); + ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); if (decl_map) { @@ -430,9 +432,11 @@ ClangExpressionParser::Parse (Stream &stream) diag_buf->BeginSourceFile(m_compiler->getLangOpts(), &m_compiler->getPreprocessor()); - ASTConsumer *ast_transformer = m_expr.ASTTransformer(m_code_generator.get()); + ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); - if (ClangExpressionDeclMap *decl_map = m_expr.DeclMap()) + ASTConsumer *ast_transformer = type_system_helper->ASTTransformer(m_code_generator.get()); + + if (ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap()) decl_map->InstallCodeGenerator(m_code_generator.get()); if (ast_transformer) @@ -479,7 +483,7 @@ ClangExpressionParser::Parse (Stream &stream) if (!num_errors) { - if (m_expr.DeclMap() && !m_expr.DeclMap()->ResolveUnknownTypes()) + if (type_system_helper->DeclMap() && !type_system_helper->DeclMap()->ResolveUnknownTypes()) { stream.Printf("error: Couldn't infer the type of a variable\n"); num_errors++; @@ -552,7 +556,8 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, exe_ctx.GetTargetSP(), m_compiler->getTargetOpts().Features)); - ClangExpressionDeclMap *decl_map = m_expr.DeclMap(); // result can be NULL + ClangExpressionHelper *type_system_helper = dyn_cast<ClangExpressionHelper>(m_expr.GetTypeSystemHelper()); + ClangExpressionDeclMap *decl_map = type_system_helper->DeclMap(); // result can be NULL if (decl_map) { @@ -640,11 +645,3 @@ ClangExpressionParser::PrepareForExecution (lldb::addr_t &func_addr, return err; } - -bool -ClangExpressionParser::GetGenerateDebugInfo () const -{ - if (m_compiler) - return m_compiler->getCodeGenOpts().getDebugInfo() == CodeGenOptions::FullDebugInfo; - return false; -} diff --git a/lldb/source/Expression/ClangFunctionCaller.cpp b/lldb/source/Expression/ClangFunctionCaller.cpp new file mode 100644 index 00000000000..628952fe6b8 --- /dev/null +++ b/lldb/source/Expression/ClangFunctionCaller.cpp @@ -0,0 +1,220 @@ +//===-- ClangFunctionCallerCaller.cpp ---------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + + +// C Includes +// C++ Includes +// Other libraries and framework includes +#include "clang/AST/ASTContext.h" +#include "clang/AST/RecordLayout.h" +#include "clang/CodeGen/CodeGenAction.h" +#include "clang/CodeGen/ModuleBuilder.h" +#include "clang/Frontend/CompilerInstance.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/ADT/Triple.h" +#include "llvm/ExecutionEngine/ExecutionEngine.h" +#include "llvm/IR/Module.h" + +// Project includes +#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/ASTStructExtractor.h" +#include "lldb/Expression/ClangExpressionParser.h" +#include "lldb/Expression/ClangFunctionCaller.h" +#include "lldb/Expression/IRExecutionUnit.h" +#include "lldb/Interpreter/CommandReturnObject.h" +#include "lldb/Symbol/ClangASTContext.h" +#include "lldb/Symbol/Function.h" +#include "lldb/Symbol/Type.h" +#include "lldb/Target/ExecutionContext.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/Thread.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallFunction.h" + +using namespace lldb_private; + +//---------------------------------------------------------------------- +// ClangFunctionCaller constructor +//---------------------------------------------------------------------- +ClangFunctionCaller::ClangFunctionCaller +( + ExecutionContextScope &exe_scope, + const CompilerType &return_type, + const Address& functionAddress, + const ValueList &arg_value_list, + const char *name +) : + FunctionCaller(exe_scope, return_type, functionAddress, arg_value_list, name), + m_type_system_helper (*this) +{ + m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess()); + // Can't make a ClangFunctionCaller without a process. + assert (m_jit_process_wp.lock()); +} + +//---------------------------------------------------------------------- +// Destructor +//---------------------------------------------------------------------- +ClangFunctionCaller::~ClangFunctionCaller() +{ +} + +unsigned +ClangFunctionCaller::CompileFunction (Stream &errors) +{ + 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; + + std::string return_type_str (m_function_return_type.GetTypeName().AsCString("")); + + // Cons up the function we're going to wrap our call in, then compile it... + // We declare the function "extern "C"" because the compiler might be in C++ + // mode which would mangle the name and then we couldn't find it again... + m_wrapper_function_text.clear(); + m_wrapper_function_text.append ("extern \"C\" void "); + m_wrapper_function_text.append (m_wrapper_function_name); + m_wrapper_function_text.append (" (void *input)\n{\n struct "); + m_wrapper_function_text.append (m_wrapper_struct_name); + m_wrapper_function_text.append (" \n {\n"); + m_wrapper_function_text.append (" "); + m_wrapper_function_text.append (return_type_str); + m_wrapper_function_text.append (" (*fn_ptr) ("); + + // Get the number of arguments. If we have a function type and it is prototyped, + // trust that, otherwise use the values we were given. + + // FIXME: This will need to be extended to handle Variadic functions. We'll need + // to pull the defined arguments out of the function, then add the types from the + // arguments list for the variable arguments. + + uint32_t num_args = UINT32_MAX; + bool trust_function = false; + // GetArgumentCount returns -1 for an unprototyped function. + CompilerType function_clang_type; + if (m_function_ptr) + { + function_clang_type = m_function_ptr->GetCompilerType(); + if (function_clang_type) + { + int num_func_args = function_clang_type.GetFunctionArgumentCount(); + if (num_func_args >= 0) + { + trust_function = true; + num_args = num_func_args; + } + } + } + + if (num_args == UINT32_MAX) + num_args = m_arg_values.GetSize(); + + std::string args_buffer; // This one stores the definition of all the args in "struct caller". + std::string args_list_buffer; // This one stores the argument list called from the structure. + for (size_t i = 0; i < num_args; i++) + { + std::string type_name; + + if (trust_function) + { + type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString(""); + } + else + { + CompilerType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetCompilerType (); + if (clang_qual_type) + { + type_name = clang_qual_type.GetTypeName().AsCString(""); + } + else + { + errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i); + return 1; + } + } + + m_wrapper_function_text.append (type_name); + if (i < num_args - 1) + m_wrapper_function_text.append (", "); + + char arg_buf[32]; + args_buffer.append (" "); + args_buffer.append (type_name); + snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i); + args_buffer.push_back (' '); + args_buffer.append (arg_buf); + args_buffer.append (";\n"); + + args_list_buffer.append ("__lldb_fn_data->"); + args_list_buffer.append (arg_buf); + if (i < num_args - 1) + args_list_buffer.append (", "); + + } + m_wrapper_function_text.append (");\n"); // Close off the function calling prototype. + + m_wrapper_function_text.append (args_buffer); + + m_wrapper_function_text.append (" "); + m_wrapper_function_text.append (return_type_str); + m_wrapper_function_text.append (" return_value;"); + m_wrapper_function_text.append ("\n };\n struct "); + m_wrapper_function_text.append (m_wrapper_struct_name); + m_wrapper_function_text.append ("* __lldb_fn_data = (struct "); + m_wrapper_function_text.append (m_wrapper_struct_name); + m_wrapper_function_text.append (" *) input;\n"); + + m_wrapper_function_text.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr ("); + m_wrapper_function_text.append (args_list_buffer); + m_wrapper_function_text.append (");\n}\n"); + + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + if (log) + log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str()); + + // Okay, now compile this expression + + lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); + if (jit_process_sp) + { + 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); + } + else + { + errors.Printf("no process - unable to inject function"); + num_errors = 1; + } + + m_compiled = (num_errors == 0); + + if (!m_compiled) + return num_errors; + + return num_errors; +} + +clang::ASTConsumer * +ClangFunctionCaller::ClangFunctionCallerHelper::ASTTransformer (clang::ASTConsumer *passthrough) +{ + m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_owner.GetWrapperStructName(), m_owner)); + + return m_struct_extractor.get(); +} diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp index 9239389753e..a6e5923bf28 100644 --- a/lldb/source/Expression/ClangUserExpression.cpp +++ b/lldb/source/Expression/ClangUserExpression.cpp @@ -25,7 +25,6 @@ #include "lldb/Expression/ASTResultSynthesizer.h" #include "lldb/Expression/ClangExpressionDeclMap.h" #include "lldb/Expression/ClangExpressionParser.h" -#include "lldb/Expression/ClangFunction.h" #include "lldb/Expression/ClangModulesDeclVendor.h" #include "lldb/Expression/ClangPersistentVariables.h" #include "lldb/Expression/ClangUserExpression.h" @@ -54,32 +53,13 @@ using namespace lldb_private; -ClangUserExpression::ClangUserExpression (const char *expr, +ClangUserExpression::ClangUserExpression (ExecutionContextScope &exe_scope, + const char *expr, const char *expr_prefix, lldb::LanguageType language, ResultType desired_type) : - ClangExpression (), - m_stack_frame_bottom (LLDB_INVALID_ADDRESS), - m_stack_frame_top (LLDB_INVALID_ADDRESS), - m_expr_text (expr), - m_expr_prefix (expr_prefix ? expr_prefix : ""), - m_language (language), - m_transformed_text (), - m_desired_type (desired_type), - m_expr_decl_map(), - m_execution_unit_sp(), - m_materializer_ap(), - m_result_synthesizer(), - m_jit_module_wp(), - m_enforce_valid_object (true), - m_in_cplusplus_method (false), - m_in_objectivec_method (false), - m_in_static_method(false), - m_needs_object_ptr (false), - m_const_object (false), - m_target (NULL), - m_can_interpret (false), - m_materialized_address (LLDB_INVALID_ADDRESS) + UserExpression (exe_scope, expr, expr_prefix, language, desired_type), + m_type_system_helper(*m_target_wp.lock().get()) { switch (m_language) { @@ -99,21 +79,6 @@ ClangUserExpression::ClangUserExpression (const char *expr, ClangUserExpression::~ClangUserExpression () { - if (m_target) - { - lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock()); - if (jit_module_sp) - m_target->GetImages().Remove(jit_module_sp); - } -} - -clang::ASTConsumer * -ClangUserExpression::ASTTransformer (clang::ASTConsumer *passthrough) -{ - m_result_synthesizer.reset(new ASTResultSynthesizer(passthrough, - *m_target)); - - return m_result_synthesizer.get(); } void @@ -338,54 +303,6 @@ ClangUserExpression::ScanContext(ExecutionContext &exe_ctx, Error &err) } } -void -ClangUserExpression::InstallContext (ExecutionContext &exe_ctx) -{ - m_process_wp = exe_ctx.GetProcessSP(); - - lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); - - if (frame_sp) - m_address = frame_sp->GetFrameCodeAddress(); -} - -bool -ClangUserExpression::LockAndCheckContext (ExecutionContext &exe_ctx, - lldb::TargetSP &target_sp, - lldb::ProcessSP &process_sp, - lldb::StackFrameSP &frame_sp) -{ - lldb::ProcessSP expected_process_sp = m_process_wp.lock(); - process_sp = exe_ctx.GetProcessSP(); - - if (process_sp != expected_process_sp) - return false; - - process_sp = exe_ctx.GetProcessSP(); - target_sp = exe_ctx.GetTargetSP(); - frame_sp = exe_ctx.GetFrameSP(); - - if (m_address.IsValid()) - { - if (!frame_sp) - return false; - else - return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get())); - } - - return true; -} - -bool -ClangUserExpression::MatchesContext (ExecutionContext &exe_ctx) -{ - lldb::TargetSP target_sp; - lldb::ProcessSP process_sp; - lldb::StackFrameSP frame_sp; - - return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp); -} - // This is a really nasty hack, meant to fix Objective-C expressions of the form // (int)[myArray count]. Right now, because the type information for count is // not available, [myArray count] returns id, which can't be directly cast to @@ -405,26 +322,6 @@ ApplyObjcCastHack(std::string &expr) #undef OBJC_CAST_HACK_FROM } -// Another hack, meant to allow use of unichar despite it not being available in -// the type information. Although we could special-case it in type lookup, -// hopefully we'll figure out a way to #include the same environment as is -// present in the original source file rather than try to hack specific type -// definitions in as needed. -//static void -//ApplyUnicharHack(std::string &expr) -//{ -//#define UNICHAR_HACK_FROM "unichar" -//#define UNICHAR_HACK_TO "unsigned short" -// -// size_t from_offset; -// -// while ((from_offset = expr.find(UNICHAR_HACK_FROM)) != expr.npos) -// expr.replace(from_offset, sizeof(UNICHAR_HACK_FROM) - 1, UNICHAR_HACK_TO); -// -//#undef UNICHAR_HACK_TO -//#undef UNICHAR_HACK_FROM -//} - bool ClangUserExpression::Parse (Stream &error_stream, ExecutionContext &exe_ctx, @@ -525,7 +422,7 @@ ClangUserExpression::Parse (Stream &error_stream, m_materializer_ap.reset(new Materializer()); - m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx)); + ResetDeclMap(exe_ctx, keep_result_in_memory); class OnExit { @@ -545,13 +442,13 @@ ClangUserExpression::Parse (Stream &error_stream, Callback m_callback; }; - OnExit on_exit([this]() { m_expr_decl_map.reset(); }); + OnExit on_exit([this]() { ResetDeclMap(); }); - if (!m_expr_decl_map->WillParse(exe_ctx, m_materializer_ap.get())) + if (!DeclMap()->WillParse(exe_ctx, m_materializer_ap.get())) { error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); - m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions. + ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. return false; } @@ -570,7 +467,7 @@ ClangUserExpression::Parse (Stream &error_stream, { error_stream.Printf ("error: %d errors parsing expression\n", num_errors); - m_expr_decl_map.reset(); // We are being careful here in the case of breakpoint conditions. + ResetDeclMap(); // We are being careful here in the case of breakpoint conditions. return false; } @@ -617,7 +514,7 @@ ClangUserExpression::Parse (Stream &error_stream, // } } - m_expr_decl_map.reset(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions. + ResetDeclMap(); // Make this go away since we don't need any of its state after parsing. This also gets rid of any ClangASTImporter::Minions. if (jit_error.Success()) { @@ -636,537 +533,81 @@ ClangUserExpression::Parse (Stream &error_stream, } } -static lldb::addr_t -GetObjectPointer (lldb::StackFrameSP frame_sp, - ConstString &object_name, - Error &err) -{ - err.Clear(); - - if (!frame_sp) - { - err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString()); - return LLDB_INVALID_ADDRESS; - } - - lldb::VariableSP var_sp; - lldb::ValueObjectSP valobj_sp; - - valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(), - lldb::eNoDynamicValues, - StackFrame::eExpressionPathOptionCheckPtrVsMember | - StackFrame::eExpressionPathOptionsNoFragileObjcIvar | - StackFrame::eExpressionPathOptionsNoSyntheticChildren | - StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, - var_sp, - err); - - if (!err.Success() || !valobj_sp.get()) - return LLDB_INVALID_ADDRESS; - - lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); - - if (ret == LLDB_INVALID_ADDRESS) - { - err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString()); - return LLDB_INVALID_ADDRESS; - } - - return ret; -} - bool -ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream, - ExecutionContext &exe_ctx, - lldb::addr_t &struct_address, - lldb::addr_t &object_ptr, - lldb::addr_t &cmd_ptr) +ClangUserExpression::AddInitialArguments (ExecutionContext &exe_ctx, + std::vector<lldb::addr_t> &args, + Stream &error_stream) { - lldb::TargetSP target; - lldb::ProcessSP process; - lldb::StackFrameSP frame; - - if (!LockAndCheckContext(exe_ctx, - target, - process, - frame)) - { - error_stream.Printf("The context has changed before we could JIT the expression!\n"); - return false; - } - - if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) + lldb::addr_t object_ptr = LLDB_INVALID_ADDRESS; + lldb::addr_t cmd_ptr = LLDB_INVALID_ADDRESS; + + if (m_needs_object_ptr) { - if (m_needs_object_ptr) - { - ConstString object_name; - - if (m_in_cplusplus_method) - { - object_name.SetCString("this"); - } - else if (m_in_objectivec_method) - { - object_name.SetCString("self"); - } - else - { - error_stream.Printf("Need object pointer but don't know the language\n"); - return false; - } - - Error object_ptr_error; - - object_ptr = GetObjectPointer(frame, object_name, object_ptr_error); - - if (!object_ptr_error.Success()) - { - error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); - object_ptr = 0; - } - - if (m_in_objectivec_method) - { - ConstString cmd_name("_cmd"); - - cmd_ptr = GetObjectPointer(frame, cmd_name, object_ptr_error); - - if (!object_ptr_error.Success()) - { - error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); - cmd_ptr = 0; - } - } - } + lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); + if (!frame_sp) + return true; + + ConstString object_name; - if (m_materialized_address == LLDB_INVALID_ADDRESS) + if (m_in_cplusplus_method) { - Error alloc_error; - - IRMemoryMap::AllocationPolicy policy = m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror; - - m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(), - m_materializer_ap->GetStructAlignment(), - lldb::ePermissionsReadable | lldb::ePermissionsWritable, - policy, - alloc_error); - - if (!alloc_error.Success()) - { - error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString()); - return false; - } + object_name.SetCString("this"); } - - struct_address = m_materialized_address; - - if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS) + else if (m_in_objectivec_method) { - Error alloc_error; - - const size_t stack_frame_size = 512 * 1024; - - m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size, - 8, - lldb::ePermissionsReadable | lldb::ePermissionsWritable, - IRMemoryMap::eAllocationPolicyHostOnly, - alloc_error); - - m_stack_frame_top = m_stack_frame_bottom + stack_frame_size; - - if (!alloc_error.Success()) - { - error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString()); - return false; - } + object_name.SetCString("self"); } - - Error materialize_error; - - m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error); - - if (!materialize_error.Success()) + else { - error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString()); + error_stream.Printf("Need object pointer but don't know the language\n"); return false; } - } - return true; -} - -bool -ClangUserExpression::FinalizeJITExecution (Stream &error_stream, - ExecutionContext &exe_ctx, - lldb::ExpressionVariableSP &result, - lldb::addr_t function_stack_bottom, - lldb::addr_t function_stack_top) -{ - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - - if (log) - log->Printf("-- [ClangUserExpression::FinalizeJITExecution] Dematerializing after execution --"); - if (!m_dematerializer_sp) - { - error_stream.Printf ("Couldn't apply expression side effects : no dematerializer is present"); - return false; - } - - Error dematerialize_error; - - m_dematerializer_sp->Dematerialize(dematerialize_error, result, function_stack_bottom, function_stack_top); - - if (!dematerialize_error.Success()) - { - error_stream.Printf ("Couldn't apply expression side effects : %s\n", dematerialize_error.AsCString("unknown error")); - return false; - } - - if (result) - result->TransferAddress(); - - m_dematerializer_sp.reset(); - - return true; -} - -lldb::ExpressionResults -ClangUserExpression::Execute (Stream &error_stream, - ExecutionContext &exe_ctx, - const EvaluateExpressionOptions& options, - lldb::ClangUserExpressionSP &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. - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - - if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) - { - lldb::addr_t struct_address = LLDB_INVALID_ADDRESS; + Error object_ptr_error; - lldb::addr_t object_ptr = 0; - lldb::addr_t cmd_ptr = 0; + object_ptr = GetObjectPointer(frame_sp, object_name, object_ptr_error); - if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr, cmd_ptr)) + if (!object_ptr_error.Success()) { - error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); - return lldb::eExpressionSetupError; + error_stream.Printf("warning: couldn't get required object pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); + object_ptr = 0; } - lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS; - lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS; - - if (m_can_interpret) + if (m_in_objectivec_method) { - llvm::Module *module = m_execution_unit_sp->GetModule(); - llvm::Function *function = m_execution_unit_sp->GetFunction(); - - if (!module || !function) - { - error_stream.Printf("Supposed to interpret, but nothing is there"); - return lldb::eExpressionSetupError; - } - - Error interpreter_error; - - llvm::SmallVector <lldb::addr_t, 3> args; - - if (m_needs_object_ptr) - { - args.push_back(object_ptr); + ConstString cmd_name("_cmd"); - if (m_in_objectivec_method) - args.push_back(cmd_ptr); - } - - args.push_back(struct_address); - - function_stack_bottom = m_stack_frame_bottom; - function_stack_top = m_stack_frame_top; - - IRInterpreter::Interpret (*module, - *function, - args, - *m_execution_unit_sp.get(), - interpreter_error, - function_stack_bottom, - function_stack_top, - exe_ctx); + cmd_ptr = GetObjectPointer(frame_sp, cmd_name, object_ptr_error); - if (!interpreter_error.Success()) + if (!object_ptr_error.Success()) { - error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString()); - return lldb::eExpressionDiscarded; + error_stream.Printf("warning: couldn't get cmd pointer (substituting NULL): %s\n", object_ptr_error.AsCString()); + cmd_ptr = 0; } } - else - { - if (!exe_ctx.HasThreadScope()) - { - error_stream.Printf("ClangUserExpression::Execute called with no thread selected."); - return lldb::eExpressionSetupError; - } - - Address wrapper_address (m_jit_start_addr); - - llvm::SmallVector <lldb::addr_t, 3> args; - - if (m_needs_object_ptr) { - args.push_back(object_ptr); - if (m_in_objectivec_method) - args.push_back(cmd_ptr); - } - - args.push_back(struct_address); - - 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)) - return lldb::eExpressionSetupError; - - ThreadPlanCallUserExpression *user_expression_plan = static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get()); - - lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer(); - - function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); - function_stack_top = function_stack_pointer; - - if (log) - log->Printf("-- [ClangUserExpression::Execute] Execution of expression begins --"); - - if (exe_ctx.GetProcessPtr()) - exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); - - lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, - call_plan_sp, - options, - error_stream); - - if (exe_ctx.GetProcessPtr()) - exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); - - if (log) - log->Printf("-- [ClangUserExpression::Execute] Execution of expression completed --"); + if (object_ptr) + args.push_back(object_ptr); - if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint) - { - const char *error_desc = NULL; - - if (call_plan_sp) - { - lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo(); - if (real_stop_info_sp) - error_desc = real_stop_info_sp->GetDescription(); - } - if (error_desc) - error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc); - else - error_stream.PutCString ("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."); - 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, " - "use \"thread return -x\" to return to the state before expression evaluation."); - } + if (m_in_objectivec_method) + args.push_back(cmd_ptr); - return execution_result; - } - else if (execution_result == lldb::eExpressionStoppedForDebug) - { - error_stream.PutCString ("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."); - return execution_result; - } - else if (execution_result != lldb::eExpressionCompleted) - { - error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result)); - return execution_result; - } - } - if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top)) - { - return lldb::eExpressionCompleted; - } - else - { - return lldb::eExpressionResultUnavailable; - } - } - else - { - error_stream.Printf("Expression can't be run, because there is no JIT compiled function"); - return lldb::eExpressionSetupError; } + return true; } -lldb::ExpressionResults -ClangUserExpression::Evaluate (ExecutionContext &exe_ctx, - const EvaluateExpressionOptions& options, - const char *expr_cstr, - const char *expr_prefix, - lldb::ValueObjectSP &result_valobj_sp, - Error &error) +void +ClangUserExpression::ClangUserExpressionHelper::ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory) { - Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); - - lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); - const lldb::LanguageType language = options.GetLanguage(); - const ResultType desired_type = options.DoesCoerceToId() ? ClangUserExpression::eResultTypeId : ClangUserExpression::eResultTypeAny; - lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; - - Process *process = exe_ctx.GetProcessPtr(); - - if (process == NULL || process->GetState() != lldb::eStateStopped) - { - if (execution_policy == eExecutionPolicyAlways) - { - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Expression may not run, but is not constant =="); - - error.SetErrorString ("expression needed to run but couldn't"); - - return execution_results; - } - } - - if (process == NULL || !process->CanJIT()) - execution_policy = eExecutionPolicyNever; - - const char *full_prefix = NULL; - const char *option_prefix = options.GetPrefix(); - std::string full_prefix_storage; - if (expr_prefix && option_prefix) - { - full_prefix_storage.assign(expr_prefix); - full_prefix_storage.append(option_prefix); - if (!full_prefix_storage.empty()) - full_prefix = full_prefix_storage.c_str(); - } - else if (expr_prefix) - full_prefix = expr_prefix; - else - full_prefix = option_prefix; - - lldb::ClangUserExpressionSP user_expression_sp (new ClangUserExpression (expr_cstr, full_prefix, language, desired_type)); - - StreamString error_stream; - - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Parsing expression %s ==", expr_cstr); - - const bool keep_expression_in_memory = true; - const bool generate_debug_info = options.GetGenerateDebugInfo(); - - if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse)) - { - error.SetErrorString ("expression interrupted by callback before parse"); - 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)) - { - execution_results = lldb::eExpressionParseError; - if (error_stream.GetString().empty()) - error.SetExpressionError (execution_results, "expression failed to parse, unknown error"); - else - error.SetExpressionError (execution_results, error_stream.GetString().c_str()); - } - else - { - lldb::ExpressionVariableSP expr_result; - - if (execution_policy == eExecutionPolicyNever && - !user_expression_sp->CanInterpret()) - { - if (log) - log->Printf("== [ClangUserExpression::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"); - } - else - { - if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution)) - { - error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution"); - result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); - return lldb::eExpressionInterrupted; - } - - error_stream.GetString().clear(); - - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Executing expression =="); - - execution_results = user_expression_sp->Execute (error_stream, - exe_ctx, - options, - user_expression_sp, - expr_result); - - if (options.GetResultIsInternal() && expr_result && process) - { - process->GetTarget().GetPersistentVariables().RemovePersistentVariable (expr_result); - } - - if (execution_results != lldb::eExpressionCompleted) - { - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Execution completed abnormally =="); - - if (error_stream.GetString().empty()) - error.SetExpressionError (execution_results, "expression failed to execute, unknown error"); - else - error.SetExpressionError (execution_results, error_stream.GetString().c_str()); - } - else - { - if (expr_result) - { - result_valobj_sp = expr_result->GetValueObject(); - - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with result %s ==", - result_valobj_sp->GetValueAsCString()); - } - else - { - if (log) - log->Printf("== [ClangUserExpression::Evaluate] Execution completed normally with no result =="); - - error.SetError(ClangUserExpression::kNoResult, lldb::eErrorTypeGeneric); - } - } - } - } - - if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) - { - error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete"); - return lldb::eExpressionInterrupted; - } + m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx)); +} - if (result_valobj_sp.get() == NULL) - { - result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); - } +clang::ASTConsumer * +ClangUserExpression::ClangUserExpressionHelper::ASTTransformer (clang::ASTConsumer *passthrough) +{ + m_result_synthesizer_up.reset(new ASTResultSynthesizer(passthrough, + m_target)); - return execution_results; + return m_result_synthesizer_up.get(); } + diff --git a/lldb/source/Expression/ClangUtilityFunction.cpp b/lldb/source/Expression/ClangUtilityFunction.cpp index de5b0c1b03f..2a07a428803 100644 --- a/lldb/source/Expression/ClangUtilityFunction.cpp +++ b/lldb/source/Expression/ClangUtilityFunction.cpp @@ -40,29 +40,15 @@ using namespace lldb_private; /// @param[in] name /// The name of the function, as used in the text. //------------------------------------------------------------------ -ClangUtilityFunction::ClangUtilityFunction (const char *text, +ClangUtilityFunction::ClangUtilityFunction (ExecutionContextScope &exe_scope, + const char *text, const char *name) : - ClangExpression (), - m_expr_decl_map (), - m_execution_unit_sp (), - m_jit_module_wp (), - m_function_text (ExpressionSourceCode::g_expression_prefix), - m_function_name (name) + UtilityFunction (exe_scope, text, name) { - if (text && text[0]) - m_function_text.append (text); } ClangUtilityFunction::~ClangUtilityFunction () { - lldb::ProcessSP process_sp (m_jit_process_wp.lock()); - if (process_sp) - { - lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock()); - if (jit_module_sp) - process_sp->GetTarget().GetImages().Remove(jit_module_sp); - } - } //------------------------------------------------------------------ @@ -113,9 +99,9 @@ ClangUtilityFunction::Install (Stream &error_stream, bool keep_result_in_memory = false; - m_expr_decl_map.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx)); + ResetDeclMap(exe_ctx, keep_result_in_memory); - if (!m_expr_decl_map->WillParse(exe_ctx, NULL)) + if (!DeclMap()->WillParse(exe_ctx, NULL)) { error_stream.PutCString ("error: current process state is unsuitable for expression parsing\n"); return false; @@ -130,7 +116,7 @@ ClangUtilityFunction::Install (Stream &error_stream, { error_stream.Printf ("error: %d errors parsing expression\n", num_errors); - m_expr_decl_map.reset(); + ResetDeclMap(); return false; } @@ -176,9 +162,9 @@ ClangUtilityFunction::Install (Stream &error_stream, m_function_text.c_str()); #endif - m_expr_decl_map->DidParse(); + DeclMap()->DidParse(); - m_expr_decl_map.reset(); + ResetDeclMap(); if (jit_error.Success()) { @@ -195,4 +181,8 @@ ClangUtilityFunction::Install (Stream &error_stream, } } - +void +ClangUtilityFunction::ClangUtilityFunctionHelper::ResetDeclMap(ExecutionContext &exe_ctx, bool keep_result_in_memory) +{ + m_expr_decl_map_up.reset(new ClangExpressionDeclMap(keep_result_in_memory, exe_ctx)); +} diff --git a/lldb/source/Expression/Expression.cpp b/lldb/source/Expression/Expression.cpp new file mode 100644 index 00000000000..e5dd9c03db7 --- /dev/null +++ b/lldb/source/Expression/Expression.cpp @@ -0,0 +1,32 @@ +//===-- Expression.h ---------------------------------------*- 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/Expression.h" +#include "lldb/Target/ExecutionContextScope.h" +#include "lldb/Target/Target.h" + +using namespace lldb_private; + +Expression::Expression (Target &target) : + m_target_wp (target.shared_from_this()), + m_jit_start_addr (LLDB_INVALID_ADDRESS), + m_jit_end_addr (LLDB_INVALID_ADDRESS) +{ + // Can't make any kind of expression without a target. + assert (m_target_wp.lock()); +} + +Expression::Expression (ExecutionContextScope &exe_scope) : + m_target_wp (exe_scope.CalculateTarget()), + m_jit_start_addr (LLDB_INVALID_ADDRESS), + m_jit_end_addr (LLDB_INVALID_ADDRESS) +{ + assert (m_target_wp.lock()); +} + diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/FunctionCaller.cpp index 3798c212059..acfc71c146e 100644 --- a/lldb/source/Expression/ClangFunction.cpp +++ b/lldb/source/Expression/FunctionCaller.cpp @@ -1,4 +1,4 @@ -//===-- ClangFunction.cpp ---------------------------------------*- C++ -*-===// +//===-- FunctionCaller.cpp ---------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -30,7 +30,7 @@ #include "lldb/Core/ValueObjectList.h" #include "lldb/Expression/ASTStructExtractor.h" #include "lldb/Expression/ClangExpressionParser.h" -#include "lldb/Expression/ClangFunction.h" +#include "lldb/Expression/FunctionCaller.h" #include "lldb/Expression/IRExecutionUnit.h" #include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Symbol/ClangASTContext.h" @@ -47,9 +47,9 @@ using namespace lldb_private; //---------------------------------------------------------------------- -// ClangFunction constructor +// FunctionCaller constructor //---------------------------------------------------------------------- -ClangFunction::ClangFunction +FunctionCaller::FunctionCaller ( ExecutionContextScope &exe_scope, const CompilerType &return_type, @@ -57,6 +57,7 @@ ClangFunction::ClangFunction const ValueList &arg_value_list, const char *name ) : + Expression (exe_scope), m_execution_unit_sp(), m_parser(), m_jit_module_wp(), @@ -72,41 +73,14 @@ ClangFunction::ClangFunction m_JITted (false) { m_jit_process_wp = lldb::ProcessWP(exe_scope.CalculateProcess()); - // Can't make a ClangFunction without a process. + // Can't make a FunctionCaller without a process. assert (m_jit_process_wp.lock()); } -ClangFunction::ClangFunction -( - ExecutionContextScope &exe_scope, - Function &function, - ClangASTContext *ast_context, - const ValueList &arg_value_list, - const char *name -) : - m_name (name ? name : "<unknown>"), - m_function_ptr (&function), - m_function_addr (), - m_function_return_type (), - m_wrapper_function_name ("__lldb_function_caller"), - m_wrapper_struct_name ("__lldb_caller_struct"), - m_wrapper_args_addrs (), - m_arg_values (arg_value_list), - m_compiled (false), - m_JITted (false) -{ - m_jit_process_wp = exe_scope.CalculateProcess(); - // Can't make a ClangFunction without a process. - assert (m_jit_process_wp.lock()); - - m_function_addr = m_function_ptr->GetAddressRange().GetBaseAddress(); - m_function_return_type = m_function_ptr->GetCompilerType().GetFunctionReturnType(); -} - //---------------------------------------------------------------------- // Destructor //---------------------------------------------------------------------- -ClangFunction::~ClangFunction() +FunctionCaller::~FunctionCaller() { lldb::ProcessSP process_sp (m_jit_process_wp.lock()); if (process_sp) @@ -117,147 +91,8 @@ ClangFunction::~ClangFunction() } } -unsigned -ClangFunction::CompileFunction (Stream &errors) -{ - 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; - - std::string return_type_str (m_function_return_type.GetTypeName().AsCString("")); - - // Cons up the function we're going to wrap our call in, then compile it... - // We declare the function "extern "C"" because the compiler might be in C++ - // mode which would mangle the name and then we couldn't find it again... - m_wrapper_function_text.clear(); - m_wrapper_function_text.append ("extern \"C\" void "); - m_wrapper_function_text.append (m_wrapper_function_name); - m_wrapper_function_text.append (" (void *input)\n{\n struct "); - m_wrapper_function_text.append (m_wrapper_struct_name); - m_wrapper_function_text.append (" \n {\n"); - m_wrapper_function_text.append (" "); - m_wrapper_function_text.append (return_type_str); - m_wrapper_function_text.append (" (*fn_ptr) ("); - - // Get the number of arguments. If we have a function type and it is prototyped, - // trust that, otherwise use the values we were given. - - // FIXME: This will need to be extended to handle Variadic functions. We'll need - // to pull the defined arguments out of the function, then add the types from the - // arguments list for the variable arguments. - - uint32_t num_args = UINT32_MAX; - bool trust_function = false; - // GetArgumentCount returns -1 for an unprototyped function. - CompilerType function_clang_type; - if (m_function_ptr) - { - function_clang_type = m_function_ptr->GetCompilerType(); - if (function_clang_type) - { - int num_func_args = function_clang_type.GetFunctionArgumentCount(); - if (num_func_args >= 0) - { - trust_function = true; - num_args = num_func_args; - } - } - } - - if (num_args == UINT32_MAX) - num_args = m_arg_values.GetSize(); - - std::string args_buffer; // This one stores the definition of all the args in "struct caller". - std::string args_list_buffer; // This one stores the argument list called from the structure. - for (size_t i = 0; i < num_args; i++) - { - std::string type_name; - - if (trust_function) - { - type_name = function_clang_type.GetFunctionArgumentTypeAtIndex(i).GetTypeName().AsCString(""); - } - else - { - CompilerType clang_qual_type = m_arg_values.GetValueAtIndex(i)->GetCompilerType (); - if (clang_qual_type) - { - type_name = clang_qual_type.GetTypeName().AsCString(""); - } - else - { - errors.Printf("Could not determine type of input value %" PRIu64 ".", (uint64_t)i); - return 1; - } - } - - m_wrapper_function_text.append (type_name); - if (i < num_args - 1) - m_wrapper_function_text.append (", "); - - char arg_buf[32]; - args_buffer.append (" "); - args_buffer.append (type_name); - snprintf(arg_buf, 31, "arg_%" PRIu64, (uint64_t)i); - args_buffer.push_back (' '); - args_buffer.append (arg_buf); - args_buffer.append (";\n"); - - args_list_buffer.append ("__lldb_fn_data->"); - args_list_buffer.append (arg_buf); - if (i < num_args - 1) - args_list_buffer.append (", "); - - } - m_wrapper_function_text.append (");\n"); // Close off the function calling prototype. - - m_wrapper_function_text.append (args_buffer); - - m_wrapper_function_text.append (" "); - m_wrapper_function_text.append (return_type_str); - m_wrapper_function_text.append (" return_value;"); - m_wrapper_function_text.append ("\n };\n struct "); - m_wrapper_function_text.append (m_wrapper_struct_name); - m_wrapper_function_text.append ("* __lldb_fn_data = (struct "); - m_wrapper_function_text.append (m_wrapper_struct_name); - m_wrapper_function_text.append (" *) input;\n"); - - m_wrapper_function_text.append (" __lldb_fn_data->return_value = __lldb_fn_data->fn_ptr ("); - m_wrapper_function_text.append (args_list_buffer); - m_wrapper_function_text.append (");\n}\n"); - - Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); - if (log) - log->Printf ("Expression: \n\n%s\n\n", m_wrapper_function_text.c_str()); - - // Okay, now compile this expression - - lldb::ProcessSP jit_process_sp(m_jit_process_wp.lock()); - if (jit_process_sp) - { - 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); - } - else - { - errors.Printf("no process - unable to inject function"); - num_errors = 1; - } - - m_compiled = (num_errors == 0); - - if (!m_compiled) - return num_errors; - - return num_errors; -} - bool -ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors) +FunctionCaller::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors) { Process *process = exe_ctx.GetProcessPtr(); @@ -310,18 +145,17 @@ ClangFunction::WriteFunctionWrapper (ExecutionContext &exe_ctx, Stream &errors) } bool -ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors) +FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors) { - return WriteFunctionArguments(exe_ctx, args_addr_ref, m_function_addr, m_arg_values, errors); + return WriteFunctionArguments(exe_ctx, args_addr_ref, m_arg_values, errors); } // FIXME: Assure that the ValueList we were passed in is consistent with the one that defined this function. bool -ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, +FunctionCaller::WriteFunctionArguments (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, - Address function_address, - ValueList &arg_values, + ValueList &arg_values, Stream &errors) { // All the information to reconstruct the struct is provided by the @@ -363,7 +197,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, } // TODO: verify fun_addr needs to be a callable address - Scalar fun_addr (function_address.GetCallableLoadAddress(exe_ctx.GetTargetPtr())); + Scalar fun_addr (m_function_addr.GetCallableLoadAddress(exe_ctx.GetTargetPtr())); uint64_t first_offset = m_member_offsets[0]; process->WriteScalarToMemory(args_addr_ref + first_offset, fun_addr, process->GetAddressByteSize(), error); @@ -404,7 +238,7 @@ ClangFunction::WriteFunctionArguments (ExecutionContext &exe_ctx, } bool -ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors) +FunctionCaller::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_addr_ref, Stream &errors) { using namespace clang; @@ -423,7 +257,7 @@ ClangFunction::InsertFunction (ExecutionContext &exe_ctx, lldb::addr_t &args_add } lldb::ThreadPlanSP -ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, +FunctionCaller::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, lldb::addr_t args_addr, const EvaluateExpressionOptions &options, Stream &errors) @@ -431,7 +265,7 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); if (log) - log->Printf("-- [ClangFunction::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str()); + log->Printf("-- [FunctionCaller::GetThreadPlanToCallFunction] Creating thread plan to call function \"%s\" --", m_name.c_str()); // FIXME: Use the errors Stream for better error reporting. Thread *thread = exe_ctx.GetThreadPtr(); @@ -458,7 +292,7 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx, } bool -ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value) +FunctionCaller::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr, Value &ret_value) { // Read the return value - it is the last field in the struct: // FIXME: How does clang tell us there's no return value? We need to handle that case. @@ -468,7 +302,7 @@ ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t arg Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); if (log) - log->Printf("-- [ClangFunction::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str()); + log->Printf("-- [FunctionCaller::FetchFunctionResults] Fetching function results for \"%s\"--", m_name.c_str()); Process *process = exe_ctx.GetProcessPtr(); @@ -492,7 +326,7 @@ ClangFunction::FetchFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t arg } void -ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr) +FunctionCaller::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_t args_addr) { std::list<lldb::addr_t>::iterator pos; pos = std::find(m_wrapper_args_addrs.begin(), m_wrapper_args_addrs.end(), args_addr); @@ -503,7 +337,7 @@ ClangFunction::DeallocateFunctionResults (ExecutionContext &exe_ctx, lldb::addr_ } lldb::ExpressionResults -ClangFunction::ExecuteFunction( +FunctionCaller::ExecuteFunction( ExecutionContext &exe_ctx, lldb::addr_t *args_addr_ptr, const EvaluateExpressionOptions &options, @@ -513,7 +347,7 @@ ClangFunction::ExecuteFunction( using namespace clang; lldb::ExpressionResults return_value = lldb::eExpressionSetupError; - // ClangFunction::ExecuteFunction execution is always just to get the result. Do make sure we ignore + // 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; real_options.SetDebug(false); @@ -539,7 +373,7 @@ ClangFunction::ExecuteFunction( Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); if (log) - log->Printf("== [ClangFunction::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str()); + log->Printf("== [FunctionCaller::ExecuteFunction] Executing function \"%s\" ==", m_name.c_str()); lldb::ThreadPlanSP call_plan_sp = GetThreadPlanToCallFunction (exe_ctx, args_addr, @@ -562,11 +396,11 @@ ClangFunction::ExecuteFunction( { if (return_value != lldb::eExpressionCompleted) { - log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str()); + log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed abnormally ==", m_name.c_str()); } else { - log->Printf("== [ClangFunction::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str()); + log->Printf("== [FunctionCaller::ExecuteFunction] Execution of \"%s\" completed normally ==", m_name.c_str()); } } @@ -586,11 +420,3 @@ ClangFunction::ExecuteFunction( return lldb::eExpressionCompleted; } - -clang::ASTConsumer * -ClangFunction::ASTTransformer (clang::ASTConsumer *passthrough) -{ - m_struct_extractor.reset(new ASTStructExtractor(passthrough, m_wrapper_struct_name.c_str(), *this)); - - return m_struct_extractor.get(); -} diff --git a/lldb/source/Expression/IRDynamicChecks.cpp b/lldb/source/Expression/IRDynamicChecks.cpp index aa5d28bb8aa..5c8d0e5288b 100644 --- a/lldb/source/Expression/IRDynamicChecks.cpp +++ b/lldb/source/Expression/IRDynamicChecks.cpp @@ -11,11 +11,12 @@ #include "lldb/Core/ConstString.h" #include "lldb/Core/Log.h" -#include "lldb/Expression/ClangUtilityFunction.h" +#include "lldb/Expression/UtilityFunction.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" #include "llvm/Support/raw_ostream.h" #include "llvm/IR/Constants.h" @@ -52,8 +53,14 @@ bool DynamicCheckerFunctions::Install(Stream &error_stream, ExecutionContext &exe_ctx) { - m_valid_pointer_check.reset(new ClangUtilityFunction(g_valid_pointer_check_text, - VALID_POINTER_CHECK_NAME)); + Error error; + m_valid_pointer_check.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_valid_pointer_check_text, + lldb::eLanguageTypeC, + VALID_POINTER_CHECK_NAME, + error)); + if (error.Fail()) + return false; + if (!m_valid_pointer_check->Install(error_stream, exe_ctx)) return false; diff --git a/lldb/source/Expression/UserExpression.cpp b/lldb/source/Expression/UserExpression.cpp new file mode 100644 index 00000000000..547c02a1317 --- /dev/null +++ b/lldb/source/Expression/UserExpression.cpp @@ -0,0 +1,644 @@ +//===-- UserExpression.cpp ---------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include <stdio.h> +#if HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif + +#include <cstdlib> +#include <string> +#include <map> + +#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/ASTResultSynthesizer.h" +#include "lldb/Expression/ClangExpressionDeclMap.h" +#include "lldb/Expression/ClangExpressionParser.h" +#include "lldb/Expression/ClangModulesDeclVendor.h" +#include "lldb/Expression/ClangPersistentVariables.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 "lldb/Host/HostInfo.h" +#include "lldb/Symbol/Block.h" +#include "lldb/Symbol/ClangASTContext.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" +#include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" +#include "lldb/Target/ThreadPlan.h" +#include "lldb/Target/ThreadPlanCallUserExpression.h" + +#include "clang/AST/DeclCXX.h" +#include "clang/AST/DeclObjC.h" + +using namespace lldb_private; + +UserExpression::UserExpression (ExecutionContextScope &exe_scope, + const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + ResultType desired_type) : + Expression (exe_scope), + m_stack_frame_bottom (LLDB_INVALID_ADDRESS), + m_stack_frame_top (LLDB_INVALID_ADDRESS), + m_expr_text (expr), + m_expr_prefix (expr_prefix ? expr_prefix : ""), + m_language (language), + m_transformed_text (), + m_desired_type (desired_type), + m_execution_unit_sp(), + m_materializer_ap(), + m_jit_module_wp(), + m_enforce_valid_object (true), + m_in_cplusplus_method (false), + m_in_objectivec_method (false), + m_in_static_method(false), + m_needs_object_ptr (false), + m_const_object (false), + m_target (NULL), + m_can_interpret (false), + m_materialized_address (LLDB_INVALID_ADDRESS) +{ +} + +UserExpression::~UserExpression () +{ + if (m_target) + { + lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock()); + if (jit_module_sp) + m_target->GetImages().Remove(jit_module_sp); + } +} + +void +UserExpression::InstallContext (ExecutionContext &exe_ctx) +{ + m_jit_process_wp = exe_ctx.GetProcessSP(); + + lldb::StackFrameSP frame_sp = exe_ctx.GetFrameSP(); + + if (frame_sp) + m_address = frame_sp->GetFrameCodeAddress(); +} + +bool +UserExpression::LockAndCheckContext (ExecutionContext &exe_ctx, + lldb::TargetSP &target_sp, + lldb::ProcessSP &process_sp, + lldb::StackFrameSP &frame_sp) +{ + lldb::ProcessSP expected_process_sp = m_jit_process_wp.lock(); + process_sp = exe_ctx.GetProcessSP(); + + if (process_sp != expected_process_sp) + return false; + + process_sp = exe_ctx.GetProcessSP(); + target_sp = exe_ctx.GetTargetSP(); + frame_sp = exe_ctx.GetFrameSP(); + + if (m_address.IsValid()) + { + if (!frame_sp) + return false; + else + return (0 == Address::CompareLoadAddress(m_address, frame_sp->GetFrameCodeAddress(), target_sp.get())); + } + + return true; +} + +bool +UserExpression::MatchesContext (ExecutionContext &exe_ctx) +{ + lldb::TargetSP target_sp; + lldb::ProcessSP process_sp; + lldb::StackFrameSP frame_sp; + + return LockAndCheckContext(exe_ctx, target_sp, process_sp, frame_sp); +} + +lldb::addr_t +UserExpression::GetObjectPointer (lldb::StackFrameSP frame_sp, + ConstString &object_name, + Error &err) +{ + err.Clear(); + + if (!frame_sp) + { + err.SetErrorStringWithFormat("Couldn't load '%s' because the context is incomplete", object_name.AsCString()); + return LLDB_INVALID_ADDRESS; + } + + lldb::VariableSP var_sp; + lldb::ValueObjectSP valobj_sp; + + valobj_sp = frame_sp->GetValueForVariableExpressionPath(object_name.AsCString(), + lldb::eNoDynamicValues, + StackFrame::eExpressionPathOptionCheckPtrVsMember | + StackFrame::eExpressionPathOptionsNoFragileObjcIvar | + StackFrame::eExpressionPathOptionsNoSyntheticChildren | + StackFrame::eExpressionPathOptionsNoSyntheticArrayRange, + var_sp, + err); + + if (!err.Success() || !valobj_sp.get()) + return LLDB_INVALID_ADDRESS; + + lldb::addr_t ret = valobj_sp->GetValueAsUnsigned(LLDB_INVALID_ADDRESS); + + if (ret == LLDB_INVALID_ADDRESS) + { + err.SetErrorStringWithFormat("Couldn't load '%s' because its value couldn't be evaluated", object_name.AsCString()); + return LLDB_INVALID_ADDRESS; + } + + return ret; +} + +bool +UserExpression::PrepareToExecuteJITExpression (Stream &error_stream, + ExecutionContext &exe_ctx, + lldb::addr_t &struct_address) +{ + lldb::TargetSP target; + lldb::ProcessSP process; + lldb::StackFrameSP frame; + + if (!LockAndCheckContext(exe_ctx, + target, + process, + frame)) + { + error_stream.Printf("The context has changed before we could JIT the expression!\n"); + return false; + } + + if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) + { + if (m_materialized_address == LLDB_INVALID_ADDRESS) + { + Error alloc_error; + + IRMemoryMap::AllocationPolicy policy = m_can_interpret ? IRMemoryMap::eAllocationPolicyHostOnly : IRMemoryMap::eAllocationPolicyMirror; + + m_materialized_address = m_execution_unit_sp->Malloc(m_materializer_ap->GetStructByteSize(), + m_materializer_ap->GetStructAlignment(), + lldb::ePermissionsReadable | lldb::ePermissionsWritable, + policy, + alloc_error); + + if (!alloc_error.Success()) + { + error_stream.Printf("Couldn't allocate space for materialized struct: %s\n", alloc_error.AsCString()); + return false; + } + } + + struct_address = m_materialized_address; + + if (m_can_interpret && m_stack_frame_bottom == LLDB_INVALID_ADDRESS) + { + Error alloc_error; + + const size_t stack_frame_size = 512 * 1024; + + m_stack_frame_bottom = m_execution_unit_sp->Malloc(stack_frame_size, + 8, + lldb::ePermissionsReadable | lldb::ePermissionsWritable, + IRMemoryMap::eAllocationPolicyHostOnly, + alloc_error); + + m_stack_frame_top = m_stack_frame_bottom + stack_frame_size; + + if (!alloc_error.Success()) + { + error_stream.Printf("Couldn't allocate space for the stack frame: %s\n", alloc_error.AsCString()); + return false; + } + } + + Error materialize_error; + + m_dematerializer_sp = m_materializer_ap->Materialize(frame, *m_execution_unit_sp, struct_address, materialize_error); + + if (!materialize_error.Success()) + { + error_stream.Printf("Couldn't materialize: %s\n", materialize_error.AsCString()); + return false; + } + } + return true; +} + +bool +UserExpression::FinalizeJITExecution (Stream &error_stream, + ExecutionContext &exe_ctx, + lldb::ExpressionVariableSP &result, + lldb::addr_t function_stack_bottom, + lldb::addr_t function_stack_top) +{ + Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)); + + if (log) + log->Printf("-- [UserExpression::FinalizeJITExecution] Dematerializing after execution --"); + + if (!m_dematerializer_sp) + { + error_stream.Printf ("Couldn't apply expression side effects : no dematerializer is present"); + return false; + } + + Error dematerialize_error; + + m_dematerializer_sp->Dematerialize(dematerialize_error, result, function_stack_bottom, function_stack_top); + + if (!dematerialize_error.Success()) + { + error_stream.Printf ("Couldn't apply expression side effects : %s\n", dematerialize_error.AsCString("unknown error")); + return false; + } + + if (result) + result->TransferAddress(); + + m_dematerializer_sp.reset(); + + return true; +} + +lldb::ExpressionResults +UserExpression::Execute (Stream &error_stream, + 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. + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); + + if (m_jit_start_addr != LLDB_INVALID_ADDRESS || m_can_interpret) + { + lldb::addr_t struct_address = LLDB_INVALID_ADDRESS; + + if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address)) + { + error_stream.Printf("Errored out in %s, couldn't PrepareToExecuteJITExpression", __FUNCTION__); + return lldb::eExpressionSetupError; + } + + lldb::addr_t function_stack_bottom = LLDB_INVALID_ADDRESS; + lldb::addr_t function_stack_top = LLDB_INVALID_ADDRESS; + + if (m_can_interpret) + { + llvm::Module *module = m_execution_unit_sp->GetModule(); + llvm::Function *function = m_execution_unit_sp->GetFunction(); + + if (!module || !function) + { + error_stream.Printf("Supposed to interpret, but nothing is there"); + return lldb::eExpressionSetupError; + } + + Error interpreter_error; + + std::vector<lldb::addr_t> args; + + if (!AddInitialArguments(exe_ctx, args, error_stream)) + { + error_stream.Printf ("Errored out in %s, couldn't AddInitialArguments", __FUNCTION__); + return lldb::eExpressionSetupError; + } + + args.push_back(struct_address); + + function_stack_bottom = m_stack_frame_bottom; + function_stack_top = m_stack_frame_top; + + IRInterpreter::Interpret (*module, + *function, + args, + *m_execution_unit_sp.get(), + interpreter_error, + function_stack_bottom, + function_stack_top, + exe_ctx); + + if (!interpreter_error.Success()) + { + error_stream.Printf("Supposed to interpret, but failed: %s", interpreter_error.AsCString()); + return lldb::eExpressionDiscarded; + } + } + else + { + if (!exe_ctx.HasThreadScope()) + { + error_stream.Printf("UserExpression::Execute called with no thread selected."); + return lldb::eExpressionSetupError; + } + + Address wrapper_address (m_jit_start_addr); + + std::vector<lldb::addr_t> args; + + if (!AddInitialArguments(exe_ctx, args, error_stream)) + { + error_stream.Printf ("Errored out in %s, couldn't AddInitialArguments", __FUNCTION__); + return lldb::eExpressionSetupError; + } + + args.push_back(struct_address); + + 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)) + return lldb::eExpressionSetupError; + + ThreadPlanCallUserExpression *user_expression_plan = static_cast<ThreadPlanCallUserExpression *>(call_plan_sp.get()); + + lldb::addr_t function_stack_pointer = user_expression_plan->GetFunctionStackPointer(); + + function_stack_bottom = function_stack_pointer - HostInfo::GetPageSize(); + function_stack_top = function_stack_pointer; + + if (log) + log->Printf("-- [UserExpression::Execute] Execution of expression begins --"); + + if (exe_ctx.GetProcessPtr()) + exe_ctx.GetProcessPtr()->SetRunningUserExpression(true); + + lldb::ExpressionResults execution_result = exe_ctx.GetProcessRef().RunThreadPlan (exe_ctx, + call_plan_sp, + options, + error_stream); + + if (exe_ctx.GetProcessPtr()) + exe_ctx.GetProcessPtr()->SetRunningUserExpression(false); + + if (log) + log->Printf("-- [UserExpression::Execute] Execution of expression completed --"); + + if (execution_result == lldb::eExpressionInterrupted || execution_result == lldb::eExpressionHitBreakpoint) + { + const char *error_desc = NULL; + + if (call_plan_sp) + { + lldb::StopInfoSP real_stop_info_sp = call_plan_sp->GetRealStopInfo(); + if (real_stop_info_sp) + error_desc = real_stop_info_sp->GetDescription(); + } + if (error_desc) + error_stream.Printf ("Execution was interrupted, reason: %s.", error_desc); + else + error_stream.PutCString ("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."); + 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, " + "use \"thread return -x\" to return to the state before expression evaluation."); + } + + return execution_result; + } + else if (execution_result == lldb::eExpressionStoppedForDebug) + { + error_stream.PutCString ("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."); + return execution_result; + } + else if (execution_result != lldb::eExpressionCompleted) + { + error_stream.Printf ("Couldn't execute function; result was %s\n", Process::ExecutionResultAsCString (execution_result)); + return execution_result; + } + } + + if (FinalizeJITExecution (error_stream, exe_ctx, result, function_stack_bottom, function_stack_top)) + { + return lldb::eExpressionCompleted; + } + else + { + return lldb::eExpressionResultUnavailable; + } + } + else + { + error_stream.Printf("Expression can't be run, because there is no JIT compiled function"); + return lldb::eExpressionSetupError; + } +} + +lldb::ExpressionResults +UserExpression::Evaluate (ExecutionContext &exe_ctx, + const EvaluateExpressionOptions& options, + const char *expr_cstr, + const char *expr_prefix, + lldb::ValueObjectSP &result_valobj_sp, + Error &error) +{ + Log *log(lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_EXPRESSIONS | LIBLLDB_LOG_STEP)); + + lldb_private::ExecutionPolicy execution_policy = options.GetExecutionPolicy(); + const lldb::LanguageType language = options.GetLanguage(); + const ResultType desired_type = options.DoesCoerceToId() ? UserExpression::eResultTypeId : UserExpression::eResultTypeAny; + lldb::ExpressionResults execution_results = lldb::eExpressionSetupError; + + Target *target = exe_ctx.GetTargetPtr(); + if (!target) + { + if (log) + log->Printf("== [UserExpression::Evaluate] Passed a NULL target, can't run expressions."); + return lldb::eExpressionSetupError; + } + + Process *process = exe_ctx.GetProcessPtr(); + + if (process == NULL || process->GetState() != lldb::eStateStopped) + { + if (execution_policy == eExecutionPolicyAlways) + { + if (log) + log->Printf("== [UserExpression::Evaluate] Expression may not run, but is not constant =="); + + error.SetErrorString ("expression needed to run but couldn't"); + + return execution_results; + } + } + + if (process == NULL || !process->CanJIT()) + execution_policy = eExecutionPolicyNever; + + const char *full_prefix = NULL; + const char *option_prefix = options.GetPrefix(); + std::string full_prefix_storage; + if (expr_prefix && option_prefix) + { + full_prefix_storage.assign(expr_prefix); + full_prefix_storage.append(option_prefix); + if (!full_prefix_storage.empty()) + full_prefix = full_prefix_storage.c_str(); + } + else if (expr_prefix) + full_prefix = expr_prefix; + else + full_prefix = option_prefix; + + lldb::UserExpressionSP user_expression_sp(target->GetUserExpressionForLanguage (expr_cstr, + full_prefix, + language, + desired_type, + error)); + if (error.Fail()) + { + if (log) + 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); + + const bool keep_expression_in_memory = true; + const bool generate_debug_info = options.GetGenerateDebugInfo(); + + if (options.InvokeCancelCallback (lldb::eExpressionEvaluationParse)) + { + error.SetErrorString ("expression interrupted by callback before parse"); + 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)) + { + execution_results = lldb::eExpressionParseError; + if (error_stream.GetString().empty()) + error.SetExpressionError (execution_results, "expression failed to parse, unknown error"); + else + error.SetExpressionError (execution_results, error_stream.GetString().c_str()); + } + else + { + lldb::ExpressionVariableSP expr_result; + + if (execution_policy == eExecutionPolicyNever && + !user_expression_sp->CanInterpret()) + { + 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"); + } + else + { + if (options.InvokeCancelCallback (lldb::eExpressionEvaluationExecution)) + { + error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback before execution"); + result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); + return lldb::eExpressionInterrupted; + } + + error_stream.GetString().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); + + if (options.GetResultIsInternal() && expr_result && process) + { + process->GetTarget().GetPersistentVariables().RemovePersistentVariable (expr_result); + } + + if (execution_results != lldb::eExpressionCompleted) + { + if (log) + log->Printf("== [UserExpression::Evaluate] Execution completed abnormally =="); + + if (error_stream.GetString().empty()) + error.SetExpressionError (execution_results, "expression failed to execute, unknown error"); + else + error.SetExpressionError (execution_results, error_stream.GetString().c_str()); + } + else + { + if (expr_result) + { + result_valobj_sp = expr_result->GetValueObject(); + + if (log) + log->Printf("== [UserExpression::Evaluate] Execution completed normally with result %s ==", + result_valobj_sp->GetValueAsCString()); + } + else + { + if (log) + log->Printf("== [UserExpression::Evaluate] Execution completed normally with no result =="); + + error.SetError(UserExpression::kNoResult, lldb::eErrorTypeGeneric); + } + } + } + } + + if (options.InvokeCancelCallback(lldb::eExpressionEvaluationComplete)) + { + error.SetExpressionError (lldb::eExpressionInterrupted, "expression interrupted by callback after complete"); + return lldb::eExpressionInterrupted; + } + + if (result_valobj_sp.get() == NULL) + { + result_valobj_sp = ValueObjectConstResult::Create (exe_ctx.GetBestExecutionContextScope(), error); + } + + return execution_results; +} diff --git a/lldb/source/Expression/UtilityFunction.cpp b/lldb/source/Expression/UtilityFunction.cpp new file mode 100644 index 00000000000..fad6e2f2568 --- /dev/null +++ b/lldb/source/Expression/UtilityFunction.cpp @@ -0,0 +1,123 @@ +//===-- ClangUserExpression.cpp -------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +// C Includes +#include <stdio.h> +#if HAVE_SYS_TYPES_H +# include <sys/types.h> +#endif + +// C++ Includes + +#include "lldb/Core/ConstString.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/Module.h" +#include "lldb/Core/Stream.h" +#include "lldb/Core/StreamFile.h" +#include "lldb/Expression/FunctionCaller.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/Target.h" + +using namespace lldb_private; +using namespace lldb; + +//------------------------------------------------------------------ +/// Constructor +/// +/// @param[in] text +/// The text of the function. Must be a full translation unit. +/// +/// @param[in] name +/// The name of the function, as used in the text. +//------------------------------------------------------------------ +UtilityFunction::UtilityFunction (ExecutionContextScope &exe_scope, + const char *text, + const char *name) : + Expression (exe_scope), + m_execution_unit_sp (), + m_jit_module_wp (), + m_function_text (ExpressionSourceCode::g_expression_prefix), + m_function_name (name) +{ + if (text && text[0]) + m_function_text.append (text); +} + +UtilityFunction::~UtilityFunction () +{ + lldb::ProcessSP process_sp (m_jit_process_wp.lock()); + if (process_sp) + { + lldb::ModuleSP jit_module_sp (m_jit_module_wp.lock()); + if (jit_module_sp) + process_sp->GetTarget().GetImages().Remove(jit_module_sp); + } + +} + +// FIXME: We should check that every time this is called it is called with the same return type & arguments... + +FunctionCaller * +UtilityFunction::MakeFunctionCaller (const CompilerType &return_type, const ValueList &arg_value_list, Error &error) +{ + if (m_caller_up) + return m_caller_up.get(); + + ProcessSP process_sp = m_jit_process_wp.lock(); + if (!process_sp) + return nullptr; + + Address impl_code_address; + impl_code_address.SetOffset(StartAddress()); + std::string name(m_function_name); + name.append("-caller"); + + m_caller_up.reset (process_sp->GetTarget().GetFunctionCallerForLanguage (Language(), + return_type, + impl_code_address, + arg_value_list, + name.c_str(), + error)); + if (error.Fail()) + { + + return nullptr; + } + if (m_caller_up) + { + StreamString errors; + errors.Clear(); + unsigned num_errors = m_caller_up->CompileFunction(errors); + if (num_errors) + { + error.SetErrorStringWithFormat ("Error compiling %s caller function: \"%s\".", + m_function_name.c_str(), + errors.GetData()); + m_caller_up.reset(); + return nullptr; + } + + errors.Clear(); + ExecutionContext exe_ctx(process_sp); + + if (!m_caller_up->WriteFunctionWrapper(exe_ctx, errors)) + { + error.SetErrorStringWithFormat ("Error inserting caller function for %s: \"%s\".", + m_function_name.c_str(), + errors.GetData()); + m_caller_up.reset(); + return nullptr; + } + } + return m_caller_up.get(); +} diff --git a/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp b/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp index bc7a93314c4..14123af27ca 100644 --- a/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp +++ b/lldb/source/Plugins/Language/ObjC/CoreMedia.cpp @@ -25,7 +25,7 @@ lldb_private::formatters::CMTimeSummaryProvider (ValueObject& valobj, Stream& st if (!type.IsValid()) return false; - TypeSystem *type_system = valobj.GetExecutionContextRef().GetTargetSP()->GetTypeSystemForLanguage(lldb::eLanguageTypeC); + TypeSystem *type_system = valobj.GetExecutionContextRef().GetTargetSP()->GetScratchTypeSystemForLanguage(lldb::eLanguageTypeC); if (!type_system) return false; diff --git a/lldb/source/Plugins/Language/ObjC/NSArray.cpp b/lldb/source/Plugins/Language/ObjC/NSArray.cpp index d5466ed4c8d..c6db27e93d4 100644 --- a/lldb/source/Plugins/Language/ObjC/NSArray.cpp +++ b/lldb/source/Plugins/Language/ObjC/NSArray.cpp @@ -15,6 +15,7 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Core/ValueObjectConstResult.h" #include "lldb/DataFormatters/FormattersHelpers.h" +#include "lldb/Expression/FunctionCaller.h" #include "lldb/Host/Endian.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Target/ObjCLanguageRuntime.h" diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp index 7a519532036..925e49883b5 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCClassDescriptorV2.cpp @@ -8,7 +8,9 @@ //===----------------------------------------------------------------------===// #include "AppleObjCClassDescriptorV2.h" + #include "lldb/Core/Log.h" +#include "lldb/Expression/FunctionCaller.h" using namespace lldb; using namespace lldb_private; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp index 81ae61841ae..b4b725ea3cc 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.cpp @@ -1,4 +1,4 @@ -//===-- AppleObjCRuntime.cpp --------------------------------------*- C++ -*-===// +//===-- AppleObjCRuntime.cpp -------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // @@ -22,7 +22,8 @@ #include "lldb/Core/Scalar.h" #include "lldb/Core/Section.h" #include "lldb/Core/StreamString.h" -#include "lldb/Expression/ClangFunction.h" +#include "lldb/Core/ValueObject.h" +#include "lldb/Expression/FunctionCaller.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Target/ExecutionContext.h" @@ -39,6 +40,10 @@ using namespace lldb_private; #define PO_FUNCTION_TIMEOUT_USEC 15*1000*1000 +AppleObjCRuntime::~AppleObjCRuntime() +{ +} + AppleObjCRuntime::AppleObjCRuntime(Process *process) : ObjCLanguageRuntime (process), m_read_objc_library (false), @@ -135,16 +140,36 @@ AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionCon } // Now we're ready to call the function: - ClangFunction func (*exe_ctx.GetBestExecutionContextScope(), - return_clang_type, - *function_address, - arg_value_list, - "objc-object-description"); - - StreamString error_stream; + StreamString error_stream; lldb::addr_t wrapper_struct_addr = LLDB_INVALID_ADDRESS; - func.InsertFunction(exe_ctx, wrapper_struct_addr, error_stream); + + if (!m_print_object_caller_up) + { + Error error; + m_print_object_caller_up.reset(exe_scope->CalculateTarget()->GetFunctionCallerForLanguage (eLanguageTypeObjC, + return_clang_type, + *function_address, + arg_value_list, + "objc-object-description", + error)); + if (error.Fail()) + { + m_print_object_caller_up.reset(); + 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); + } + else + { + m_print_object_caller_up->WriteFunctionArguments(exe_ctx, + wrapper_struct_addr, + arg_value_list, + error_stream); + } + + EvaluateExpressionOptions options; options.SetUnwindOnError(true); @@ -153,11 +178,11 @@ AppleObjCRuntime::GetObjectDescription (Stream &strm, Value &value, ExecutionCon options.SetIgnoreBreakpoints(true); options.SetTimeoutUsec(PO_FUNCTION_TIMEOUT_USEC); - ExpressionResults results = func.ExecuteFunction (exe_ctx, - &wrapper_struct_addr, - options, - error_stream, - ret); + ExpressionResults results = m_print_object_caller_up->ExecuteFunction (exe_ctx, + &wrapper_struct_addr, + options, + error_stream, + ret); if (results != eExpressionCompleted) { strm.Printf("Error evaluating Print Object function: %d.\n", results); diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h index f8f73bae865..424058ee0b7 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntime.h @@ -20,7 +20,6 @@ #include "lldb/lldb-private.h" #include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/ObjCLanguageRuntime.h" -#include "lldb/Core/ValueObject.h" #include "AppleObjCTrampolineHandler.h" #include "AppleThreadPlanStepThroughObjCTrampoline.h" @@ -31,7 +30,7 @@ class AppleObjCRuntime : { public: - virtual ~AppleObjCRuntime() { } + virtual ~AppleObjCRuntime(); // These are generic runtime functions: bool @@ -127,6 +126,7 @@ protected: std::unique_ptr<lldb_private::AppleObjCTrampolineHandler> m_objc_trampoline_handler_ap; lldb::BreakpointSP m_objc_exception_bp_sp; lldb::ModuleWP m_objc_module_wp; + std::unique_ptr<FunctionCaller> m_print_object_caller_up; llvm::Optional<uint32_t> m_Foundation_major; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp index 17aa03e4a64..85729e827f5 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.cpp @@ -21,8 +21,8 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/Scalar.h" #include "lldb/Core/StreamString.h" -#include "lldb/Expression/ClangFunction.h" -#include "lldb/Expression/ClangUtilityFunction.h" +#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Expression/UtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/ExecutionContext.h" @@ -143,7 +143,7 @@ struct BufStruct { char contents[2048]; }; -ClangUtilityFunction * +UtilityFunction * AppleObjCRuntimeV1::CreateObjectChecker(const char *name) { std::unique_ptr<BufStruct> buf(new BufStruct); @@ -170,7 +170,8 @@ AppleObjCRuntimeV1::CreateObjectChecker(const char *name) "} \n", name) < (int)sizeof(buf->contents)); - return new ClangUtilityFunction(buf->contents, name); + Error error; + return GetTargetRef().GetUtilityFunctionForLanguage(buf->contents, eLanguageTypeObjC, name, error); } AppleObjCRuntimeV1::ClassDescriptorV1::ClassDescriptorV1 (ValueObject &isa_pointer) diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h index f98f065f6a7..73e8607286f 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV1.h @@ -102,7 +102,7 @@ public: TypeAndOrName &class_type_or_name, Address &address); - virtual ClangUtilityFunction * + virtual UtilityFunction * CreateObjectChecker (const char *); //------------------------------------------------------------------ diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp index 4817d57a353..ac643064415 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.cpp @@ -28,8 +28,8 @@ #include "lldb/Core/StreamString.h" #include "lldb/Core/Timer.h" #include "lldb/Core/ValueObjectVariable.h" -#include "lldb/Expression/ClangFunction.h" -#include "lldb/Expression/ClangUtilityFunction.h" +#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Expression/UtilityFunction.h" #include "lldb/Host/StringConvert.h" #include "lldb/Interpreter/CommandObject.h" #include "lldb/Interpreter/CommandObjectMultiword.h" @@ -348,11 +348,9 @@ ExtractRuntimeGlobalSymbol (Process* process, AppleObjCRuntimeV2::AppleObjCRuntimeV2 (Process *process, const ModuleSP &objc_module_sp) : AppleObjCRuntime (process), - m_get_class_info_function(), m_get_class_info_code(), m_get_class_info_args (LLDB_INVALID_ADDRESS), m_get_class_info_args_mutex (Mutex::eMutexTypeNormal), - m_get_shared_cache_class_info_function(), m_get_shared_cache_class_info_code(), m_get_shared_cache_class_info_args (LLDB_INVALID_ADDRESS), m_get_shared_cache_class_info_args_mutex (Mutex::eMutexTypeNormal), @@ -722,7 +720,7 @@ AppleObjCRuntimeV2::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bo return resolver_sp; } -ClangUtilityFunction * +UtilityFunction * AppleObjCRuntimeV2::CreateObjectChecker(const char *name) { char check_function_code[2048]; @@ -780,7 +778,8 @@ AppleObjCRuntimeV2::CreateObjectChecker(const char *name) assert (len < (int)sizeof(check_function_code)); - return new ClangUtilityFunction(check_function_code, name); + Error error; + return GetTargetRef().GetUtilityFunctionForLanguage(check_function_code, eLanguageTypeObjC, name, error); } size_t @@ -1248,75 +1247,74 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table CompilerType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); CompilerType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType(); + ValueList arguments; + FunctionCaller *get_class_info_function = nullptr; + if (!m_get_class_info_code.get()) { - m_get_class_info_code.reset (new ClangUtilityFunction (g_get_dynamic_class_info_body, - g_get_dynamic_class_info_name)); - - errors.Clear(); - - if (!m_get_class_info_code->Install(errors, exe_ctx)) + Error error; + m_get_class_info_code.reset (GetTargetRef().GetUtilityFunctionForLanguage (g_get_dynamic_class_info_body, + eLanguageTypeObjC, + g_get_dynamic_class_info_name, + error)); + if (error.Fail()) { if (log) - log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + log->Printf ("Failed to get Utility Function for implementation lookup: %s", error.AsCString()); m_get_class_info_code.reset(); } - } - - if (m_get_class_info_code.get()) - function_address.SetOffset(m_get_class_info_code->StartAddress()); - else - return false; - - ValueList arguments; - - // Next make the runner function for our implementation utility function. - if (!m_get_class_info_function.get()) - { + else + { + errors.Clear(); + + if (!m_get_class_info_code->Install(errors, exe_ctx)) + { + if (log) + log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + m_get_class_info_code.reset(); + } + } + if (!m_get_class_info_code.get()) + return false; + + // Next make the runner function for our implementation utility function. Value value; value.SetValueType (Value::eValueTypeScalar); -// value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type); value.SetCompilerType (clang_void_pointer_type); arguments.PushValue (value); arguments.PushValue (value); value.SetValueType (Value::eValueTypeScalar); -// value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type); value.SetCompilerType (clang_uint32_t_type); arguments.PushValue (value); - m_get_class_info_function.reset(new ClangFunction (*m_process, - clang_uint32_t_type, - function_address, - arguments, - "objc-v2-isa-to-descriptor")); - - if (m_get_class_info_function.get() == NULL) - return false; - - errors.Clear(); + get_class_info_function = m_get_class_info_code->MakeFunctionCaller(clang_uint32_t_type, + arguments, + error); - unsigned num_errors = m_get_class_info_function->CompileFunction(errors); - if (num_errors) + if (error.Fail()) { if (log) - log->Printf ("Error compiling function: \"%s\".", errors.GetData()); + log->Printf("Failed to make function caller for implementation lookup: %s.", error.AsCString()); return false; } - - errors.Clear(); - - if (!m_get_class_info_function->WriteFunctionWrapper(exe_ctx, errors)) + } + else + { + get_class_info_function = m_get_class_info_code->GetFunctionCaller(); + if (!get_class_info_function) { if (log) - log->Printf ("Error Inserting function: \"%s\".", errors.GetData()); + log->Printf ("Failed to get implementation lookup function caller: %s.", errors.GetData()); return false; } + arguments = get_class_info_function->GetArgumentValues(); } - else - { - arguments = m_get_class_info_function->GetArgumentValues (); - } + + + + + errors.Clear(); const uint32_t class_info_byte_size = addr_size + 4; const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; @@ -1339,9 +1337,8 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table errors.Clear(); // Write our function arguments into the process so we can run our function - if (m_get_class_info_function->WriteFunctionArguments (exe_ctx, + if (get_class_info_function->WriteFunctionArguments (exe_ctx, m_get_class_info_args, - function_address, arguments, errors)) { @@ -1361,11 +1358,11 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table errors.Clear(); // Run the function - ExpressionResults results = m_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, + errors, + return_value); if (results == eExpressionCompleted) { @@ -1502,31 +1499,38 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() CompilerType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); CompilerType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType(); + ValueList arguments; + FunctionCaller *get_shared_cache_class_info_function = nullptr; + if (!m_get_shared_cache_class_info_code.get()) { - m_get_shared_cache_class_info_code.reset (new ClangUtilityFunction (g_get_shared_cache_class_info_body, - g_get_shared_cache_class_info_name)); - - errors.Clear(); - - if (!m_get_shared_cache_class_info_code->Install(errors, exe_ctx)) + Error error; + m_get_shared_cache_class_info_code.reset (GetTargetRef().GetUtilityFunctionForLanguage (g_get_shared_cache_class_info_body, + eLanguageTypeObjC, + g_get_shared_cache_class_info_name, + error)); + if (error.Fail()) { if (log) - log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + log->Printf ("Failed to get Utility function for implementation lookup: %s.", error.AsCString()); m_get_shared_cache_class_info_code.reset(); } - } - - if (m_get_shared_cache_class_info_code.get()) - function_address.SetOffset(m_get_shared_cache_class_info_code->StartAddress()); - else - return DescriptorMapUpdateResult::Fail(); - - ValueList arguments; + else + { + errors.Clear(); + + if (!m_get_shared_cache_class_info_code->Install(errors, exe_ctx)) + { + if (log) + log->Printf ("Failed to install implementation lookup: %s.", errors.GetData()); + m_get_shared_cache_class_info_code.reset(); + } + } + + if (!m_get_shared_cache_class_info_code.get()) + return DescriptorMapUpdateResult::Fail(); - // Next make the runner function for our implementation utility function. - if (!m_get_shared_cache_class_info_function.get()) - { + // Next make the function caller for our implementation utility function. Value value; value.SetValueType (Value::eValueTypeScalar); //value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type); @@ -1539,39 +1543,24 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() value.SetCompilerType (clang_uint32_t_type); arguments.PushValue (value); - m_get_shared_cache_class_info_function.reset(new ClangFunction (*m_process, - clang_uint32_t_type, - function_address, - arguments, - "objc-isa-to-descriptor-shared-cache")); - - if (m_get_shared_cache_class_info_function.get() == NULL) - return DescriptorMapUpdateResult::Fail(); - - errors.Clear(); - - unsigned num_errors = m_get_shared_cache_class_info_function->CompileFunction(errors); - if (num_errors) - { - if (log) - log->Printf ("Error compiling function: \"%s\".", errors.GetData()); - return DescriptorMapUpdateResult::Fail(); - } - - errors.Clear(); + get_shared_cache_class_info_function = m_get_shared_cache_class_info_code->MakeFunctionCaller(clang_uint32_t_type, + arguments, + error); - if (!m_get_shared_cache_class_info_function->WriteFunctionWrapper(exe_ctx, errors)) - { - if (log) - log->Printf ("Error Inserting function: \"%s\".", errors.GetData()); + if (get_shared_cache_class_info_function == nullptr) return DescriptorMapUpdateResult::Fail(); - } + } else { - arguments = m_get_shared_cache_class_info_function->GetArgumentValues (); + get_shared_cache_class_info_function = m_get_shared_cache_class_info_code->GetFunctionCaller(); + if (get_shared_cache_class_info_function == nullptr) + return DescriptorMapUpdateResult::Fail(); + arguments = get_shared_cache_class_info_function->GetArgumentValues(); } + errors.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, @@ -1594,11 +1583,10 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() errors.Clear(); // Write our function arguments into the process so we can run our function - if (m_get_shared_cache_class_info_function->WriteFunctionArguments (exe_ctx, - m_get_shared_cache_class_info_args, - function_address, - arguments, - errors)) + if (get_shared_cache_class_info_function->WriteFunctionArguments (exe_ctx, + m_get_shared_cache_class_info_args, + arguments, + errors)) { EvaluateExpressionOptions options; options.SetUnwindOnError(true); @@ -1616,11 +1604,11 @@ AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() errors.Clear(); // Run the function - ExpressionResults results = m_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, + errors, + return_value); if (results == eExpressionCompleted) { diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h index 6d981f72d8c..feaf9d4d6f0 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h @@ -39,7 +39,7 @@ public: TypeAndOrName &class_type_or_name, Address &address); - virtual ClangUtilityFunction * + virtual UtilityFunction * CreateObjectChecker (const char *); @@ -299,22 +299,20 @@ private: friend class ClassDescriptorV2; - std::unique_ptr<ClangFunction> m_get_class_info_function; - std::unique_ptr<ClangUtilityFunction> m_get_class_info_code; + std::unique_ptr<UtilityFunction> m_get_class_info_code; lldb::addr_t m_get_class_info_args; Mutex m_get_class_info_args_mutex; - std::unique_ptr<ClangFunction> m_get_shared_cache_class_info_function; - std::unique_ptr<ClangUtilityFunction> m_get_shared_cache_class_info_code; + std::unique_ptr<UtilityFunction> m_get_shared_cache_class_info_code; lldb::addr_t m_get_shared_cache_class_info_args; Mutex m_get_shared_cache_class_info_args_mutex; - std::unique_ptr<DeclVendor> m_decl_vendor_ap; + std::unique_ptr<DeclVendor> m_decl_vendor_ap; lldb::addr_t m_isa_hash_table_ptr; HashTableSignature m_hash_signature; bool m_has_object_getClass; bool m_loaded_objc_opt; - std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_ap; + std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_ap; std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_ap; EncodingToTypeSP m_encoding_to_type_sp; bool m_noclasses_warning_emitted; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp index db5b7f0a406..d38a076ad5d 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.cpp @@ -22,9 +22,9 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamFile.h" #include "lldb/Core/Value.h" -#include "lldb/Expression/ClangExpression.h" -#include "lldb/Expression/ClangFunction.h" -#include "lldb/Expression/ClangUtilityFunction.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" @@ -741,10 +741,10 @@ lldb::addr_t AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &dispatch_values) { ExecutionContext exe_ctx (thread.shared_from_this()); - Address impl_code_address; StreamString errors; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; + FunctionCaller *impl_function_caller = nullptr; // Scope for mutex locker: { @@ -752,38 +752,23 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &di // First stage is to make the ClangUtility to hold our injected function: - #define USE_BUILTIN_FUNCTION 0 // Define this to 1 and we will use the get_implementation function found in the target. - // This is useful for debugging additions to the get_impl function 'cause you don't have - // to bother with string-ifying the code into g_lookup_implementation_function_code. - - if (USE_BUILTIN_FUNCTION) - { - ConstString our_utility_function_name("__lldb_objc_find_implementation_for_selector"); - SymbolContextList sc_list; - - exe_ctx.GetTargetRef().GetImages().FindSymbolsWithNameAndType (our_utility_function_name, eSymbolTypeCode, sc_list); - if (sc_list.GetSize() == 1) - { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - if (sc.symbol != NULL) - impl_code_address = sc.symbol->GetAddress(); - - //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr()); - //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr); - } - else - { - //printf ("Could not find implementation function address.\n"); - return args_addr; - } - } - else if (!m_impl_code.get()) + if (!m_impl_code.get()) { if (g_lookup_implementation_function_code != NULL) { - m_impl_code.reset (new ClangUtilityFunction (g_lookup_implementation_function_code, - g_lookup_implementation_function_name)); + Error error; + m_impl_code.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage (g_lookup_implementation_function_code, + eLanguageTypeObjC, + g_lookup_implementation_function_name, + error)); + if (error.Fail()) + { + if (log) + log->Printf ("Failed to get Utility Function for implementation lookup: %s.", error.AsCString()); + m_impl_code.reset(); + return args_addr; + } + if (!m_impl_code->Install(errors, exe_ctx)) { if (log) @@ -800,43 +785,26 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &di return LLDB_INVALID_ADDRESS; } - impl_code_address.Clear(); - impl_code_address.SetOffset(m_impl_code->StartAddress()); - } - else - { - impl_code_address.Clear(); - impl_code_address.SetOffset(m_impl_code->StartAddress()); - } - // Next make the runner function for our implementation utility function. - if (!m_impl_function.get()) - { + // Next make the runner function for our implementation utility function. ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext(); CompilerType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - m_impl_function.reset(new ClangFunction (thread, - clang_void_ptr_type, - impl_code_address, - dispatch_values, - "objc-dispatch-lookup")); + Error error; - errors.Clear(); - unsigned num_errors = m_impl_function->CompileFunction(errors); - if (num_errors) + impl_function_caller = m_impl_code->MakeFunctionCaller(clang_void_ptr_type, + dispatch_values, + error); + if (error.Fail()) { if (log) - log->Printf ("Error compiling function: \"%s\".", errors.GetData()); - return args_addr; - } - - errors.Clear(); - if (!m_impl_function->WriteFunctionWrapper(exe_ctx, errors)) - { - if (log) - log->Printf ("Error Inserting function: \"%s\".", errors.GetData()); + log->Printf ("Error getting function caller for dispatch lookup: \"%s\".", error.AsCString()); return args_addr; } } + else + { + impl_function_caller = m_impl_code->GetFunctionCaller(); + } } errors.Clear(); @@ -845,7 +813,7 @@ AppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &di // 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 (!m_impl_function->WriteFunctionArguments (exe_ctx, args_addr, impl_code_address, dispatch_values, errors)) + if (impl_function_caller->WriteFunctionArguments (exe_ctx, args_addr, dispatch_values, errors)) { if (log) log->Printf ("Error writing function arguments: \"%s\".", errors.GetData()); @@ -1169,8 +1137,8 @@ AppleObjCTrampolineHandler::GetStepThroughDispatchPlan (Thread &thread, bool sto return ret_plan_sp; } -ClangFunction * -AppleObjCTrampolineHandler::GetLookupImplementationWrapperFunction () +FunctionCaller * +AppleObjCTrampolineHandler::GetLookupImplementationFunctionCaller () { - return m_impl_function.get(); + return m_impl_code->GetFunctionCaller(); } diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h index c9d0e19ed2b..0ddb540439d 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h @@ -35,8 +35,8 @@ public: GetStepThroughDispatchPlan (Thread &thread, bool stop_others); - ClangFunction * - GetLookupImplementationWrapperFunction (); + FunctionCaller * + GetLookupImplementationFunctionCaller (); bool AddrIsMsgForward (lldb::addr_t addr) const @@ -198,8 +198,7 @@ private: MsgsendMap m_msgSend_map; lldb::ProcessWP m_process_wp; lldb::ModuleSP m_objc_module_sp; - std::unique_ptr<ClangFunction> m_impl_function; - std::unique_ptr<ClangUtilityFunction> m_impl_code; + std::unique_ptr<UtilityFunction> m_impl_code; Mutex m_impl_function_mutex; lldb::addr_t m_impl_fn_addr; lldb::addr_t m_impl_stret_fn_addr; diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp index fe364faefe3..285786a09db 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.cpp @@ -15,8 +15,8 @@ #include "AppleObjCTrampolineHandler.h" #include "lldb/Target/Process.h" #include "lldb/Target/Thread.h" -#include "lldb/Expression/ClangExpression.h" -#include "lldb/Expression/ClangFunction.h" +#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Expression/UtilityFunction.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/ThreadPlanRunToAddress.h" @@ -67,11 +67,11 @@ AppleThreadPlanStepThroughObjCTrampoline::DidPush () { // Setting up the memory space for the called function text might require allocations, // i.e. a nested function call. This needs to be done as a PreResumeAction. - m_thread.GetProcess()->AddPreResumeAction (PreResumeInitializeClangFunction, (void *) this); + m_thread.GetProcess()->AddPreResumeAction (PreResumeInitializeFunctionCaller, (void *) this); } bool -AppleThreadPlanStepThroughObjCTrampoline::InitializeClangFunction () +AppleThreadPlanStepThroughObjCTrampoline::InitializeFunctionCaller () { if (!m_func_sp) { @@ -82,7 +82,7 @@ AppleThreadPlanStepThroughObjCTrampoline::InitializeClangFunction () { return false; } - m_impl_function = m_trampoline_handler->GetLookupImplementationWrapperFunction(); + m_impl_function = m_trampoline_handler->GetLookupImplementationFunctionCaller(); ExecutionContext exc_ctx; EvaluateExpressionOptions options; options.SetUnwindOnError(true); @@ -100,10 +100,10 @@ AppleThreadPlanStepThroughObjCTrampoline::InitializeClangFunction () } bool -AppleThreadPlanStepThroughObjCTrampoline::PreResumeInitializeClangFunction(void *void_myself) +AppleThreadPlanStepThroughObjCTrampoline::PreResumeInitializeFunctionCaller(void *void_myself) { AppleThreadPlanStepThroughObjCTrampoline *myself = static_cast<AppleThreadPlanStepThroughObjCTrampoline *>(void_myself); - return myself->InitializeClangFunction(); + return myself->InitializeFunctionCaller(); } void diff --git a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h index 253190991ce..2ad181e553f 100644 --- a/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h +++ b/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleThreadPlanStepThroughObjCTrampoline.h @@ -66,7 +66,7 @@ public: DidPush(); static bool - PreResumeInitializeClangFunction(void *myself); + PreResumeInitializeFunctionCaller(void *myself); virtual bool WillStop(); @@ -82,7 +82,7 @@ protected: private: bool - InitializeClangFunction (); + InitializeFunctionCaller (); //------------------------------------------------------------------ // For AppleThreadPlanStepThroughObjCTrampoline only @@ -96,7 +96,7 @@ private: lldb::ThreadPlanSP m_func_sp; // This is the function call plan. We fill it at start, then set it // to NULL when this plan is done. That way we know to go to: lldb::ThreadPlanSP m_run_to_sp; // The plan that runs to the target. - ClangFunction *m_impl_function; // This is a pointer to a impl function that + FunctionCaller *m_impl_function; // This is a pointer to a impl function that // is owned by the client that pushes this plan. bool m_stop_others; }; diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp index a882b7e3e87..66b8b8bcf59 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.cpp @@ -22,9 +22,8 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" -#include "lldb/Expression/ClangExpression.h" -#include "lldb/Expression/ClangFunction.h" -#include "lldb/Expression/ClangUtilityFunction.h" +#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Expression/UtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/ExecutionContext.h" @@ -101,7 +100,6 @@ extern \"C\" AppleGetItemInfoHandler::AppleGetItemInfoHandler (Process *process) : m_process (process), - m_get_item_info_function (), m_get_item_info_impl_code (), m_get_item_info_function_mutex(), m_get_item_info_return_buffer_addr (LLDB_INVALID_ADDRESS), @@ -140,49 +138,33 @@ lldb::addr_t AppleGetItemInfoHandler::SetupGetItemInfoFunction (Thread &thread, ValueList &get_item_info_arglist) { ExecutionContext exe_ctx (thread.shared_from_this()); - Address impl_code_address; StreamString errors; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; + FunctionCaller *get_item_info_caller = nullptr; // Scope for mutex locker: { Mutex::Locker locker(m_get_item_info_function_mutex); - // First stage is to make the ClangUtility to hold our injected function: + // First stage is to make the UtilityFunction to hold our injected function: -#define USE_BUILTIN_FUNCTION 0 // Define this to 1 and we will use the get_implementation function found in the target. - // This is useful for debugging additions to the get_impl function 'cause you don't have - // to bother with string-ifying the code into g_get_item_info_function_code. - - if (USE_BUILTIN_FUNCTION) - { - ConstString our_utility_function_name("__lldb_backtrace_recording_get_item_info"); - SymbolContextList sc_list; - - exe_ctx.GetTargetRef().GetImages().FindSymbolsWithNameAndType (our_utility_function_name, eSymbolTypeCode, sc_list); - if (sc_list.GetSize() == 1) - { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - if (sc.symbol != NULL) - impl_code_address = sc.symbol->GetAddress(); - - //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr()); - //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr); - } - else - { - //printf ("Could not find queues introspection function address.\n"); - return args_addr; - } - } - else if (!m_get_item_info_impl_code.get()) + if (!m_get_item_info_impl_code.get()) { if (g_get_item_info_function_code != NULL) { - m_get_item_info_impl_code.reset (new ClangUtilityFunction (g_get_item_info_function_code, - g_get_item_info_function_name)); + Error error; + m_get_item_info_impl_code.reset(exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage (g_get_item_info_function_code, + eLanguageTypeObjC, + g_get_item_info_function_name, + error)); + if (error.Fail()) + { + if (log) + 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 (log) @@ -198,41 +180,32 @@ AppleGetItemInfoHandler::SetupGetItemInfoFunction (Thread &thread, ValueList &ge errors.Printf ("No get-item-info introspection code found."); return LLDB_INVALID_ADDRESS; } - - impl_code_address.Clear(); - impl_code_address.SetOffset(m_get_item_info_impl_code->StartAddress()); - } - else - { - impl_code_address.Clear(); - impl_code_address.SetOffset(m_get_item_info_impl_code->StartAddress()); - } - // Next make the runner function for our implementation utility function. - if (!m_get_item_info_function.get()) - { - ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext(); - CompilerType get_item_info_return_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - m_get_item_info_function.reset(new ClangFunction (thread, - get_item_info_return_type, - impl_code_address, - get_item_info_arglist, - "queue-bt-item-info")); + // Next make the runner function for our implementation utility function. + Error error; + + TypeSystem *type_system = thread.GetProcess()->GetTarget().GetScratchTypeSystemForLanguage(eLanguageTypeC); + CompilerType get_item_info_return_type = type_system->GetBasicTypeFromAST(eBasicTypeVoid).GetPointerType(); - errors.Clear(); - unsigned num_errors = m_get_item_info_function->CompileFunction(errors); - if (num_errors) + get_item_info_caller = m_get_item_info_impl_code->MakeFunctionCaller(get_item_info_return_type, + get_item_info_arglist, + error); + if (error.Fail()) { if (log) - log->Printf ("Error compiling get-item-info function: \"%s\".", errors.GetData()); + log->Printf ("Error Inserting get-item-info function: \"%s\".", error.AsCString()); return args_addr; } - - errors.Clear(); - if (!m_get_item_info_function->WriteFunctionWrapper(exe_ctx, errors)) + } + else + { + // If it's already made, then we can just retrieve the caller: + get_item_info_caller = m_get_item_info_impl_code->GetFunctionCaller(); + if (!get_item_info_caller) { if (log) - log->Printf ("Error Inserting get-item-info function: \"%s\".", errors.GetData()); + log->Printf ("Failed to get get-item-info introspection caller."); + m_get_item_info_impl_code.reset(); return args_addr; } } @@ -244,7 +217,7 @@ AppleGetItemInfoHandler::SetupGetItemInfoFunction (Thread &thread, ValueList &ge // 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 (!m_get_item_info_function->WriteFunctionArguments (exe_ctx, args_addr, impl_code_address, get_item_info_arglist, errors)) + if (!get_item_info_caller->WriteFunctionArguments (exe_ctx, args_addr, get_item_info_arglist, errors)) { if (log) log->Printf ("Error writing get-item-info function arguments: \"%s\".", errors.GetData()); @@ -364,7 +337,7 @@ AppleGetItemInfoHandler::GetItemInfo (Thread &thread, uint64_t item, addr_t page options.SetTryAllThreads (false); thread.CalculateExecutionContext (exe_ctx); - if (m_get_item_info_function == NULL) + if (!m_get_item_info_impl_code) { error.SetErrorString ("Unable to compile function to call __introspection_dispatch_queue_item_get_info"); return return_value; @@ -373,7 +346,16 @@ AppleGetItemInfoHandler::GetItemInfo (Thread &thread, uint64_t item, addr_t page ExpressionResults func_call_ret; Value results; - func_call_ret = m_get_item_info_function->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + FunctionCaller *func_caller = m_get_item_info_impl_code->GetFunctionCaller(); + if (!func_caller) + { + if (log) + log->Printf ("Could not retrieve function caller for __introspection_dispatch_queue_item_get_info."); + 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); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h index 5c086c61978..51182a62493 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetItemInfoHandler.h @@ -18,11 +18,11 @@ // Project includes #include "lldb/lldb-public.h" #include "lldb/Core/Error.h" -#include "lldb/Expression/ClangFunction.h" +#include "lldb/Expression/UtilityFunction.h" #include "lldb/Host/Mutex.h" #include "lldb/Symbol/CompilerType.h" -// This class will insert a ClangUtilityFunction into the inferior process for +// This class will insert a UtilityFunction into the inferior process for // calling libBacktraceRecording's __introspection_dispatch_queue_item_get_info() // function. The function in the inferior will return a struct by value // with these members: @@ -37,7 +37,7 @@ // space (item_buffer_size in size) which must be mach_vm_deallocate'd by // lldb. // -// The AppleGetItemInfoHandler object should persist so that the ClangUtilityFunction +// The AppleGetItemInfoHandler object should persist so that the UtilityFunction // can be reused multiple times. namespace lldb_private @@ -104,8 +104,7 @@ private: static const char *g_get_item_info_function_code; lldb_private::Process *m_process; - std::unique_ptr<ClangFunction> m_get_item_info_function; - std::unique_ptr<ClangUtilityFunction> m_get_item_info_impl_code; + std::unique_ptr<UtilityFunction> m_get_item_info_impl_code; Mutex m_get_item_info_function_mutex; lldb::addr_t m_get_item_info_return_buffer_addr; diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp index c3e68eaa0a6..3e3a2620013 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.cpp @@ -22,9 +22,8 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" -#include "lldb/Expression/ClangExpression.h" -#include "lldb/Expression/ClangFunction.h" -#include "lldb/Expression/ClangUtilityFunction.h" +#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Expression/UtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/ExecutionContext.h" @@ -105,7 +104,6 @@ extern \"C\" AppleGetPendingItemsHandler::AppleGetPendingItemsHandler (Process *process) : m_process (process), - m_get_pending_items_function (), m_get_pending_items_impl_code (), m_get_pending_items_function_mutex(), m_get_pending_items_return_buffer_addr (LLDB_INVALID_ADDRESS), @@ -144,49 +142,33 @@ lldb::addr_t AppleGetPendingItemsHandler::SetupGetPendingItemsFunction (Thread &thread, ValueList &get_pending_items_arglist) { ExecutionContext exe_ctx (thread.shared_from_this()); - Address impl_code_address; StreamString errors; 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); // First stage is to make the ClangUtility to hold our injected function: -#define USE_BUILTIN_FUNCTION 0 // Define this to 1 and we will use the get_implementation function found in the target. - // This is useful for debugging additions to the get_impl function 'cause you don't have - // to bother with string-ifying the code into g_get_pending_items_function_code. - - if (USE_BUILTIN_FUNCTION) - { - ConstString our_utility_function_name("__lldb_backtrace_recording_get_pending_items"); - SymbolContextList sc_list; - - exe_ctx.GetTargetRef().GetImages().FindSymbolsWithNameAndType (our_utility_function_name, eSymbolTypeCode, sc_list); - if (sc_list.GetSize() == 1) - { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - if (sc.symbol != NULL) - impl_code_address = sc.symbol->GetAddress(); - - //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr()); - //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr); - } - else - { - //printf ("Could not find queues introspection function address.\n"); - return args_addr; - } - } - else if (!m_get_pending_items_impl_code.get()) + if (!m_get_pending_items_impl_code.get()) { if (g_get_pending_items_function_code != NULL) { - m_get_pending_items_impl_code.reset (new ClangUtilityFunction (g_get_pending_items_function_code, - g_get_pending_items_function_name)); + Error error; + m_get_pending_items_impl_code.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_get_pending_items_function_code, + eLanguageTypeObjC, + g_get_pending_items_function_name, + error)); + if (error.Fail()) + { + if (log) + 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 (log) @@ -203,43 +185,22 @@ AppleGetPendingItemsHandler::SetupGetPendingItemsFunction (Thread &thread, Value return LLDB_INVALID_ADDRESS; } - impl_code_address.Clear(); - impl_code_address.SetOffset(m_get_pending_items_impl_code->StartAddress()); - } - else - { - impl_code_address.Clear(); - impl_code_address.SetOffset(m_get_pending_items_impl_code->StartAddress()); - } - - // Next make the runner function for our implementation utility function. - if (!m_get_pending_items_function.get()) - { + // Next make the runner function for our implementation utility function. + Error error; ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext(); CompilerType get_pending_items_return_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - m_get_pending_items_function.reset(new ClangFunction (thread, - get_pending_items_return_type, - impl_code_address, - get_pending_items_arglist, - "queue-pending-items")); - - errors.Clear(); - unsigned num_errors = m_get_pending_items_function->CompileFunction(errors); - if (num_errors) + get_pending_items_caller = m_get_pending_items_impl_code->MakeFunctionCaller (get_pending_items_return_type, + get_pending_items_arglist, + error); + if (error.Fail()) { if (log) - log->Printf ("Error compiling pending-items function: \"%s\".", errors.GetData()); - return args_addr; - } - - errors.Clear(); - if (!m_get_pending_items_function->WriteFunctionWrapper(exe_ctx, errors)) - { - if (log) - log->Printf ("Error Inserting pending-items function: \"%s\".", errors.GetData()); + log->Printf ("Failed to install pending-items introspection function caller: %s.", error.AsCString()); + m_get_pending_items_impl_code.reset(); return args_addr; } } + } errors.Clear(); @@ -248,7 +209,7 @@ AppleGetPendingItemsHandler::SetupGetPendingItemsFunction (Thread &thread, Value // 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 (!m_get_pending_items_function->WriteFunctionArguments (exe_ctx, args_addr, impl_code_address, get_pending_items_arglist, errors)) + if (!get_pending_items_caller->WriteFunctionArguments (exe_ctx, args_addr, get_pending_items_arglist, errors)) { if (log) log->Printf ("Error writing pending-items function arguments: \"%s\".", errors.GetData()); @@ -362,6 +323,8 @@ AppleGetPendingItemsHandler::GetPendingItems (Thread &thread, addr_t queue, addr StreamString errors; ExecutionContext exe_ctx; + FunctionCaller *get_pending_items_caller = m_get_pending_items_impl_code->GetFunctionCaller(); + EvaluateExpressionOptions options; options.SetUnwindOnError (true); options.SetIgnoreBreakpoints (true); @@ -370,7 +333,7 @@ AppleGetPendingItemsHandler::GetPendingItems (Thread &thread, addr_t queue, addr options.SetTryAllThreads (false); thread.CalculateExecutionContext (exe_ctx); - if (m_get_pending_items_function == NULL) + if (get_pending_items_caller == NULL) { error.SetErrorString ("Unable to compile function to call __introspection_dispatch_queue_get_pending_items"); return return_value; @@ -379,7 +342,7 @@ AppleGetPendingItemsHandler::GetPendingItems (Thread &thread, addr_t queue, addr ExpressionResults func_call_ret; Value results; - func_call_ret = m_get_pending_items_function->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + func_call_ret = get_pending_items_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h index 22ab1f6132c..445c4a0fb82 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetPendingItemsHandler.h @@ -18,11 +18,10 @@ // Project includes #include "lldb/lldb-public.h" #include "lldb/Core/Error.h" -#include "lldb/Expression/ClangFunction.h" #include "lldb/Host/Mutex.h" #include "lldb/Symbol/CompilerType.h" -// This class will insert a ClangUtilityFunction into the inferior process for +// This class will insert a UtilityFunction into the inferior process for // calling libBacktraceRecording's __introspection_dispatch_queue_get_pending_items() // function. The function in the inferior will return a struct by value // with these members: @@ -38,7 +37,7 @@ // space (items_buffer_size in size) which must be mach_vm_deallocate'd by // lldb. count is the number of items that were stored in the buffer. // -// The AppleGetPendingItemsHandler object should persist so that the ClangUtilityFunction +// The AppleGetPendingItemsHandler object should persist so that the UtilityFunction // can be reused multiple times. namespace lldb_private @@ -107,8 +106,7 @@ private: static const char *g_get_pending_items_function_code; lldb_private::Process *m_process; - std::unique_ptr<ClangFunction> m_get_pending_items_function; - std::unique_ptr<ClangUtilityFunction> m_get_pending_items_impl_code; + std::unique_ptr<UtilityFunction> m_get_pending_items_impl_code; Mutex m_get_pending_items_function_mutex; lldb::addr_t m_get_pending_items_return_buffer_addr; diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp index d5b1380e273..6d7eaf72191 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.cpp @@ -21,9 +21,8 @@ #include "lldb/Core/Module.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/Value.h" -#include "lldb/Expression/ClangExpression.h" -#include "lldb/Expression/ClangFunction.h" -#include "lldb/Expression/ClangUtilityFunction.h" +#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Expression/UtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/ExecutionContext.h" @@ -101,8 +100,7 @@ extern \"C\" AppleGetQueuesHandler::AppleGetQueuesHandler (Process *process) : m_process (process), - m_get_queues_function (), - m_get_queues_impl_code (), + m_get_queues_impl_code_up (), m_get_queues_function_mutex(), m_get_queues_return_buffer_addr (LLDB_INVALID_ADDRESS), m_get_queues_retbuffer_mutex() @@ -156,6 +154,8 @@ AppleGetQueuesHandler::SetupGetQueuesFunction (Thread &thread, ValueList &get_qu StreamString errors; 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: { @@ -163,43 +163,27 @@ AppleGetQueuesHandler::SetupGetQueuesFunction (Thread &thread, ValueList &get_qu // First stage is to make the ClangUtility to hold our injected function: -#define USE_BUILTIN_FUNCTION 0 // Define this to 1 and we will use the get_implementation function found in the target. - // This is useful for debugging additions to the get_impl function 'cause you don't have - // to bother with string-ifying the code into g_get_current_queues_function_code. - - if (USE_BUILTIN_FUNCTION) - { - ConstString our_utility_function_name("__lldb_backtrace_recording_get_current_queues"); - SymbolContextList sc_list; - - exe_ctx.GetTargetRef().GetImages().FindSymbolsWithNameAndType (our_utility_function_name, eSymbolTypeCode, sc_list); - if (sc_list.GetSize() == 1) - { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - if (sc.symbol != NULL) - impl_code_address = sc.symbol->GetAddress(); - - //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr()); - //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr); - } - else - { - //printf ("Could not find queues introspection function address.\n"); - return args_addr; - } - } - else if (!m_get_queues_impl_code.get()) + if (!m_get_queues_impl_code_up.get()) { if (g_get_current_queues_function_code != NULL) { - m_get_queues_impl_code.reset (new ClangUtilityFunction (g_get_current_queues_function_code, - g_get_current_queues_function_name)); - if (!m_get_queues_impl_code->Install(errors, exe_ctx)) + Error error; + m_get_queues_impl_code_up.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage(g_get_current_queues_function_code, + eLanguageTypeC, + g_get_current_queues_function_name, + error)); + if (error.Fail()) + { + if (log) + 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 (log) log->Printf ("Failed to install queues introspection: %s.", errors.GetData()); - m_get_queues_impl_code.reset(); + m_get_queues_impl_code_up.reset(); return args_addr; } } @@ -210,43 +194,20 @@ AppleGetQueuesHandler::SetupGetQueuesFunction (Thread &thread, ValueList &get_qu errors.Printf ("No queues introspection code found."); return LLDB_INVALID_ADDRESS; } - - impl_code_address.Clear(); - impl_code_address.SetOffset(m_get_queues_impl_code->StartAddress()); - } - else - { - impl_code_address.Clear(); - impl_code_address.SetOffset(m_get_queues_impl_code->StartAddress()); } - + // Next make the runner function for our implementation utility function. - if (!m_get_queues_function.get()) + ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext(); + CompilerType get_queues_return_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); + Error error; + get_queues_caller = m_get_queues_impl_code_up->MakeFunctionCaller (get_queues_return_type, + get_queues_arglist, + error); + if (error.Fail()) { - ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext(); - CompilerType get_queues_return_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - m_get_queues_function.reset(new ClangFunction (thread, - get_queues_return_type, - impl_code_address, - get_queues_arglist, - "queue-fetch-queues")); - - errors.Clear(); - unsigned num_errors = m_get_queues_function->CompileFunction(errors); - if (num_errors) - { - if (log) - log->Printf ("Error compiling get-queues function: \"%s\".", errors.GetData()); - return args_addr; - } - - errors.Clear(); - if (!m_get_queues_function->WriteFunctionWrapper(exe_ctx, errors)) - { - if (log) - log->Printf ("Error Inserting get-queues function: \"%s\".", errors.GetData()); - return args_addr; - } + if (log) + log->Printf ("Could not get function caller for get-queues function: %s.", error.AsCString()); + return args_addr; } } @@ -256,7 +217,7 @@ AppleGetQueuesHandler::SetupGetQueuesFunction (Thread &thread, ValueList &get_qu // 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 (!m_get_queues_function->WriteFunctionArguments (exe_ctx, args_addr, impl_code_address, get_queues_arglist, errors)) + if (!get_queues_caller->WriteFunctionArguments (exe_ctx, args_addr, get_queues_arglist, errors)) { if (log) log->Printf ("Error writing get-queues function arguments: \"%s\".", errors.GetData()); @@ -360,9 +321,17 @@ AppleGetQueuesHandler::GetCurrentQueues (Thread &thread, addr_t page_to_free, ui addr_t args_addr = SetupGetQueuesFunction (thread, argument_values); - if (m_get_queues_function == NULL) + if (!m_get_queues_impl_code_up) + { + error.SetErrorString ("Unable to compile __introspection_dispatch_get_queues."); + return return_value; + } + + FunctionCaller *get_queues_caller = m_get_queues_impl_code_up->GetFunctionCaller(); + + if (get_queues_caller == NULL) { - error.SetErrorString ("Unable to compile function to call __introspection_dispatch_get_queues"); + error.SetErrorString ("Unable to get caller for call __introspection_dispatch_get_queues"); return return_value; } @@ -378,7 +347,7 @@ AppleGetQueuesHandler::GetCurrentQueues (Thread &thread, addr_t page_to_free, ui ExpressionResults func_call_ret; Value results; - func_call_ret = m_get_queues_function->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + func_call_ret = get_queues_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h index 83730b58374..6f3df5f6280 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetQueuesHandler.h @@ -18,11 +18,10 @@ // Project includes #include "lldb/lldb-public.h" #include "lldb/Core/Error.h" -#include "lldb/Expression/ClangFunction.h" #include "lldb/Host/Mutex.h" #include "lldb/Symbol/CompilerType.h" -// This class will insert a ClangUtilityFunction into the inferior process for +// This class will insert a UtilityFunction into the inferior process for // calling libBacktraceRecording's introspection_get_dispatch_queues() // function. The function in the inferior will return a struct by value // with these members: @@ -38,7 +37,7 @@ // space (queues_buffer_size in size) which must be mach_vm_deallocate'd by // lldb. count is the number of queues that were stored in the buffer. // -// The AppleGetQueuesHandler object should persist so that the ClangUtilityFunction +// The AppleGetQueuesHandler object should persist so that the UtilityFunction // can be reused multiple times. namespace lldb_private @@ -104,8 +103,7 @@ private: static const char *g_get_current_queues_function_code; lldb_private::Process *m_process; - std::unique_ptr<ClangFunction> m_get_queues_function; - std::unique_ptr<ClangUtilityFunction> m_get_queues_impl_code; + std::unique_ptr<UtilityFunction> m_get_queues_impl_code_up; Mutex m_get_queues_function_mutex; lldb::addr_t m_get_queues_return_buffer_addr; diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp index 2509b3ba0ef..ea7014147b6 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.cpp @@ -17,18 +17,20 @@ #include "clang/AST/ASTContext.h" #include "clang/AST/DeclCXX.h" +#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/ClangExpression.h" -#include "lldb/Expression/ClangFunction.h" -#include "lldb/Expression/ClangUtilityFunction.h" +#include "lldb/Expression/Expression.h" +#include "lldb/Expression/FunctionCaller.h" +#include "lldb/Expression/UtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/Symbol.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" +#include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" @@ -105,7 +107,6 @@ extern \"C\" AppleGetThreadItemInfoHandler::AppleGetThreadItemInfoHandler (Process *process) : m_process (process), - m_get_thread_item_info_function (), m_get_thread_item_info_impl_code (), m_get_thread_item_info_function_mutex(), m_get_thread_item_info_return_buffer_addr (LLDB_INVALID_ADDRESS), @@ -148,6 +149,7 @@ AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction (Thread &thread, V StreamString errors; Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_SYSTEM_RUNTIME)); lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; + FunctionCaller *get_thread_item_info_caller = nullptr; // Scope for mutex locker: { @@ -155,38 +157,24 @@ AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction (Thread &thread, V // First stage is to make the ClangUtility to hold our injected function: -#define USE_BUILTIN_FUNCTION 0 // Define this to 1 and we will use the get_implementation function found in the target. - // This is useful for debugging additions to the get_impl function 'cause you don't have - // to bother with string-ifying the code into g_get_thread_item_info_function_code. - - if (USE_BUILTIN_FUNCTION) - { - ConstString our_utility_function_name("__lldb_backtrace_recording_get_thread_item_info"); - SymbolContextList sc_list; - - exe_ctx.GetTargetRef().GetImages().FindSymbolsWithNameAndType (our_utility_function_name, eSymbolTypeCode, sc_list); - if (sc_list.GetSize() == 1) - { - SymbolContext sc; - sc_list.GetContextAtIndex(0, sc); - if (sc.symbol != NULL) - impl_code_address = sc.symbol->GetAddress(); - - //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr()); - //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr); - } - else - { - //printf ("Could not find queues introspection function address.\n"); - return args_addr; - } - } - else if (!m_get_thread_item_info_impl_code.get()) + if (!m_get_thread_item_info_impl_code.get()) { + Error error; if (g_get_thread_item_info_function_code != NULL) { - m_get_thread_item_info_impl_code.reset (new ClangUtilityFunction (g_get_thread_item_info_function_code, - g_get_thread_item_info_function_name)); + m_get_thread_item_info_impl_code.reset (exe_ctx.GetTargetRef().GetUtilityFunctionForLanguage (g_get_thread_item_info_function_code, + eLanguageTypeC, + g_get_thread_item_info_function_name, + error)); + if (error.Fail()) + { + if (log) + log->Printf ("Failed to get UtilityFunction for get-thread-item-info introspection: %s.", + error.AsCString()); + m_get_thread_item_info_impl_code.reset(); + return args_addr; + } + if (!m_get_thread_item_info_impl_code->Install(errors, exe_ctx)) { if (log) @@ -203,42 +191,26 @@ AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction (Thread &thread, V return LLDB_INVALID_ADDRESS; } - impl_code_address.Clear(); - impl_code_address.SetOffset(m_get_thread_item_info_impl_code->StartAddress()); - } - else - { - impl_code_address.Clear(); - impl_code_address.SetOffset(m_get_thread_item_info_impl_code->StartAddress()); - } - - // Next make the runner function for our implementation utility function. - if (!m_get_thread_item_info_function.get()) - { + // Also make the FunctionCaller for this UtilityFunction: + ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext(); CompilerType get_thread_item_info_return_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType(); - m_get_thread_item_info_function.reset(new ClangFunction (thread, - get_thread_item_info_return_type, - impl_code_address, - get_thread_item_info_arglist, - "queue-thread-item-info")); - errors.Clear(); - unsigned num_errors = m_get_thread_item_info_function->CompileFunction(errors); - if (num_errors) + get_thread_item_info_caller = m_get_thread_item_info_impl_code->MakeFunctionCaller (get_thread_item_info_return_type, + get_thread_item_info_arglist, + error); + if (error.Fail()) { if (log) - log->Printf ("Error compiling get-thread-item-info function: \"%s\".", errors.GetData()); + log->Printf ("Failed to install get-thread-item-info introspection caller: %s.", error.AsCString()); + m_get_thread_item_info_impl_code.reset(); return args_addr; } - errors.Clear(); - if (!m_get_thread_item_info_function->WriteFunctionWrapper(exe_ctx, errors)) - { - if (log) - log->Printf ("Error Inserting get-thread-item-info function: \"%s\".", errors.GetData()); - return args_addr; - } + } + else + { + get_thread_item_info_caller = m_get_thread_item_info_impl_code->GetFunctionCaller(); } } @@ -248,7 +220,7 @@ AppleGetThreadItemInfoHandler::SetupGetThreadItemInfoFunction (Thread &thread, V // 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 (!m_get_thread_item_info_function->WriteFunctionArguments (exe_ctx, args_addr, impl_code_address, get_thread_item_info_arglist, errors)) + if (!get_thread_item_info_caller->WriteFunctionArguments (exe_ctx, args_addr, get_thread_item_info_arglist, errors)) { if (log) log->Printf ("Error writing get-thread-item-info function arguments: \"%s\".", errors.GetData()); @@ -360,6 +332,8 @@ AppleGetThreadItemInfoHandler::GetThreadItemInfo (Thread &thread, tid_t thread_i StreamString errors; ExecutionContext exe_ctx; EvaluateExpressionOptions options; + FunctionCaller *get_thread_item_info_caller = nullptr; + options.SetUnwindOnError (true); options.SetIgnoreBreakpoints (true); options.SetStopOthers (true); @@ -367,16 +341,23 @@ AppleGetThreadItemInfoHandler::GetThreadItemInfo (Thread &thread, tid_t thread_i options.SetTryAllThreads (false); thread.CalculateExecutionContext (exe_ctx); - if (m_get_thread_item_info_function == NULL) + if (!m_get_thread_item_info_impl_code) { error.SetErrorString ("Unable to compile function to call __introspection_dispatch_thread_get_item_info"); return return_value; } + get_thread_item_info_caller = m_get_thread_item_info_impl_code->GetFunctionCaller(); + + if (!get_thread_item_info_caller) + { + error.SetErrorString ("Unable to compile function caller for __introspection_dispatch_thread_get_item_info"); + return return_value; + } ExpressionResults func_call_ret; Value results; - func_call_ret = m_get_thread_item_info_function->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); + func_call_ret = get_thread_item_info_caller->ExecuteFunction (exe_ctx, &args_addr, options, errors, results); if (func_call_ret != eExpressionCompleted || !error.Success()) { if (log) diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h index 6ced39ae851..c1798fb515b 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/AppleGetThreadItemInfoHandler.h @@ -18,11 +18,10 @@ // Project includes #include "lldb/lldb-public.h" #include "lldb/Core/Error.h" -#include "lldb/Expression/ClangFunction.h" #include "lldb/Host/Mutex.h" #include "lldb/Symbol/CompilerType.h" -// This class will insert a ClangUtilityFunction into the inferior process for +// This class will insert a UtilityFunction into the inferior process for // calling libBacktraceRecording's __introspection_dispatch_thread_get_item_info() // function. The function in the inferior will return a struct by value // with these members: @@ -37,7 +36,7 @@ // space (item_buffer_size in size) which must be mach_vm_deallocate'd by // lldb. // -// The AppleGetThreadItemInfoHandler object should persist so that the ClangUtilityFunction +// The AppleGetThreadItemInfoHandler object should persist so that the UtilityFunction // can be reused multiple times. namespace lldb_private @@ -101,8 +100,7 @@ private: static const char *g_get_thread_item_info_function_code; lldb_private::Process *m_process; - std::unique_ptr<ClangFunction> m_get_thread_item_info_function; - std::unique_ptr<ClangUtilityFunction> m_get_thread_item_info_impl_code; + std::unique_ptr<UtilityFunction> m_get_thread_item_info_impl_code; Mutex m_get_thread_item_info_function_mutex; lldb::addr_t m_get_thread_item_info_return_buffer_addr; diff --git a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp index 90271f29c71..11b47df87d0 100644 --- a/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp +++ b/lldb/source/Plugins/SystemRuntime/MacOSX/SystemRuntimeMacOSX.cpp @@ -17,8 +17,6 @@ #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Section.h" #include "lldb/Core/StreamString.h" -#include "lldb/Expression/ClangFunction.h" -#include "lldb/Expression/ClangUtilityFunction.h" #include "lldb/Host/FileSpec.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ObjectFile.h" diff --git a/lldb/source/Symbol/ClangASTContext.cpp b/lldb/source/Symbol/ClangASTContext.cpp index b7157bd9aac..ccff1c19431 100644 --- a/lldb/source/Symbol/ClangASTContext.cpp +++ b/lldb/source/Symbol/ClangASTContext.cpp @@ -69,14 +69,20 @@ #include "lldb/Core/ThreadSafeDenseMap.h" #include "lldb/Core/UniqueCStringMap.h" #include "lldb/Expression/ASTDumper.h" +#include "lldb/Expression/ASTResultSynthesizer.h" +#include "lldb/Expression/ClangExpressionDeclMap.h" +#include "lldb/Expression/ClangUserExpression.h" +#include "lldb/Expression/ClangFunctionCaller.h" +#include "lldb/Expression/ClangUtilityFunction.h" #include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/ClangExternalASTSourceCallbacks.h" #include "lldb/Symbol/ClangExternalASTSourceCommon.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/VerifyDecl.h" #include "lldb/Target/ExecutionContext.h" -#include "lldb/Target/Process.h" #include "lldb/Target/ObjCLanguageRuntime.h" +#include "lldb/Target/Process.h" +#include "lldb/Target/Target.h" #include "Plugins/SymbolFile/DWARF/DWARFASTParserClang.h" @@ -8942,3 +8948,49 @@ ClangASTContext::DeclContextGetClangASTContext (const CompilerDeclContext &dc) return nullptr; } +ClangASTContextForExpressions::ClangASTContextForExpressions (Target &target) : + ClangASTContext (target.GetArchitecture().GetTriple().getTriple().c_str()), + m_target_wp(target.shared_from_this()) +{ +} + +UserExpression * +ClangASTContextForExpressions::GetUserExpression (const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + Expression::ResultType desired_type) +{ + TargetSP target_sp = m_target_wp.lock(); + if (!target_sp) + return nullptr; + + return new ClangUserExpression(*target_sp.get(), expr, expr_prefix, language, desired_type); +} + +FunctionCaller * +ClangASTContextForExpressions::GetFunctionCaller (const CompilerType &return_type, + const Address& function_address, + const ValueList &arg_value_list, + const char *name) +{ + TargetSP target_sp = m_target_wp.lock(); + if (!target_sp) + return nullptr; + + Process *process = target_sp->GetProcessSP().get(); + if (!process) + return nullptr; + + return new ClangFunctionCaller (*process, return_type, function_address, arg_value_list, name); +} + +UtilityFunction * +ClangASTContextForExpressions::GetUtilityFunction (const char *text, + const char *name) +{ + TargetSP target_sp = m_target_wp.lock(); + if (!target_sp) + return nullptr; + + return new ClangUtilityFunction(*target_sp.get(), text, name); +} diff --git a/lldb/source/Target/Process.cpp b/lldb/source/Target/Process.cpp index 0fd8d53a24e..e2bb2e48c41 100644 --- a/lldb/source/Target/Process.cpp +++ b/lldb/source/Target/Process.cpp @@ -18,7 +18,7 @@ #include "lldb/Core/PluginManager.h" #include "lldb/Core/State.h" #include "lldb/Core/StreamFile.h" -#include "lldb/Expression/ClangUserExpression.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Host/ConnectionFileDescriptor.h" #include "lldb/Host/Host.h" @@ -1917,6 +1917,7 @@ Process::LoadImage (const FileSpec &image_spec, Error &error) expr_options.SetIgnoreBreakpoints(true); expr_options.SetExecutionPolicy(eExecutionPolicyAlways); expr_options.SetResultIsInternal(true); + expr_options.SetLanguage(eLanguageTypeC_plus_plus); StreamString expr; expr.Printf(R"( @@ -1939,12 +1940,12 @@ Process::LoadImage (const FileSpec &image_spec, Error &error) )"; lldb::ValueObjectSP result_valobj_sp; Error expr_error; - ClangUserExpression::Evaluate (exe_ctx, - expr_options, - expr.GetData(), - prefix, - result_valobj_sp, - expr_error); + UserExpression::Evaluate (exe_ctx, + expr_options, + expr.GetData(), + prefix, + result_valobj_sp, + expr_error); if (expr_error.Success()) { error = result_valobj_sp->GetError(); @@ -2044,17 +2045,19 @@ Process::UnloadImage (uint32_t image_token) expr_options.SetUnwindOnError(true); expr_options.SetIgnoreBreakpoints(true); expr_options.SetExecutionPolicy(eExecutionPolicyAlways); + expr_options.SetLanguage(eLanguageTypeC_plus_plus); + StreamString expr; expr.Printf("dlclose ((void *)0x%" PRIx64 ")", image_addr); const char *prefix = "extern \"C\" int dlclose(void* handle);\n"; lldb::ValueObjectSP result_valobj_sp; Error expr_error; - ClangUserExpression::Evaluate (exe_ctx, - expr_options, - expr.GetData(), - prefix, - result_valobj_sp, - expr_error); + UserExpression::Evaluate (exe_ctx, + expr_options, + expr.GetData(), + prefix, + result_valobj_sp, + expr_error); if (result_valobj_sp->GetError().Success()) { Scalar scalar; diff --git a/lldb/source/Target/StopInfo.cpp b/lldb/source/Target/StopInfo.cpp index 00fd79aa8fd..fc1cb9af238 100644 --- a/lldb/source/Target/StopInfo.cpp +++ b/lldb/source/Target/StopInfo.cpp @@ -23,7 +23,7 @@ #include "lldb/Core/Debugger.h" #include "lldb/Core/StreamString.h" #include "lldb/Core/ValueObject.h" -#include "lldb/Expression/ClangUserExpression.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" @@ -770,12 +770,13 @@ protected: expr_options.SetIgnoreBreakpoints(true); ValueObjectSP result_value_sp; Error error; - result_code = ClangUserExpression::Evaluate (exe_ctx, - expr_options, - wp_sp->GetConditionText(), - NULL, - result_value_sp, - error); + result_code = UserExpression::Evaluate (exe_ctx, + expr_options, + wp_sp->GetConditionText(), + NULL, + result_value_sp, + error); + if (result_code == eExpressionCompleted) { if (result_value_sp) diff --git a/lldb/source/Target/Target.cpp b/lldb/source/Target/Target.cpp index aca6605f2af..993706fa889 100644 --- a/lldb/source/Target/Target.cpp +++ b/lldb/source/Target/Target.cpp @@ -33,7 +33,7 @@ #include "lldb/Core/ValueObject.h" #include "lldb/Expression/ClangASTSource.h" #include "lldb/Expression/ClangPersistentVariables.h" -#include "lldb/Expression/ClangUserExpression.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Expression/ClangModulesDeclVendor.h" #include "lldb/Host/FileSpec.h" #include "lldb/Host/Host.h" @@ -46,6 +46,7 @@ #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Function.h" #include "lldb/Symbol/Symbol.h" +#include "lldb/Target/Language.h" #include "lldb/Target/LanguageRuntime.h" #include "lldb/Target/ObjCLanguageRuntime.h" #include "lldb/Target/Process.h" @@ -1891,13 +1892,95 @@ Target::ImageSearchPathsChanged target->SetExecutableModule (exe_module_sp, true); } +TypeSystem * +Target::GetScratchTypeSystemForLanguage (lldb::LanguageType language, bool create_on_demand) +{ + if (Language::LanguageIsC(language) + || Language::LanguageIsObjC(language) + || Language::LanguageIsCPlusPlus(language) + || language == eLanguageTypeUnknown) + return GetScratchClangASTContext(create_on_demand); + else + return NULL; +} + +UserExpression * +Target::GetUserExpressionForLanguage(const char *expr, + const char *expr_prefix, + lldb::LanguageType language, + Expression::ResultType desired_type, + Error &error) +{ + TypeSystem *type_system = GetScratchTypeSystemForLanguage (language); + UserExpression *user_expr = nullptr; + + if (!type_system) + { + error.SetErrorStringWithFormat("Could not find type system for language: %s", Language::GetNameForLanguageType(language)); + return nullptr; + } + + user_expr = type_system->GetUserExpression(expr, expr_prefix, language, desired_type); + if (!user_expr) + error.SetErrorStringWithFormat("Could not create an expression for language %s", Language::GetNameForLanguageType(language)); + + return user_expr; +} + +FunctionCaller * +Target::GetFunctionCallerForLanguage (lldb::LanguageType language, + const CompilerType &return_type, + const Address& function_address, + const ValueList &arg_value_list, + const char *name, + Error &error) +{ + TypeSystem *type_system = GetScratchTypeSystemForLanguage (language); + FunctionCaller *persistent_fn = nullptr; + + if (!type_system) + { + error.SetErrorStringWithFormat("Could not find type system for language: %s", Language::GetNameForLanguageType(language)); + return persistent_fn; + } + + persistent_fn = type_system->GetFunctionCaller (return_type, function_address, arg_value_list, name); + if (!persistent_fn) + error.SetErrorStringWithFormat("Could not create an expression for language %s", Language::GetNameForLanguageType(language)); + + return persistent_fn; +} + +UtilityFunction * +Target::GetUtilityFunctionForLanguage (const char *text, + lldb::LanguageType language, + const char *name, + Error &error) +{ + TypeSystem *type_system = GetScratchTypeSystemForLanguage (language); + UtilityFunction *utility_fn = nullptr; + + if (!type_system) + { + error.SetErrorStringWithFormat("Could not find type system for language: %s", Language::GetNameForLanguageType(language)); + return utility_fn; + } + + utility_fn = type_system->GetUtilityFunction (text, name); + if (!utility_fn) + error.SetErrorStringWithFormat("Could not create an expression for language %s", Language::GetNameForLanguageType(language)); + + return utility_fn; +} + + ClangASTContext * Target::GetScratchClangASTContext(bool create_on_demand) { // Now see if we know the target triple, and if so, create our scratch AST context: if (m_scratch_ast_context_ap.get() == NULL && m_arch.IsValid() && create_on_demand) { - m_scratch_ast_context_ap.reset (new ClangASTContext(m_arch.GetTriple().str().c_str())); + m_scratch_ast_context_ap.reset (new ClangASTContextForExpressions(*this)); m_scratch_ast_source_ap.reset (new ClangASTSource(shared_from_this())); m_scratch_ast_source_ap->InstallASTContext(m_scratch_ast_context_ap->getASTContext()); llvm::IntrusiveRefCntPtr<clang::ExternalASTSource> proxy_ast_source(m_scratch_ast_source_ap->CreateProxy()); @@ -1906,27 +1989,6 @@ Target::GetScratchClangASTContext(bool create_on_demand) return m_scratch_ast_context_ap.get(); } -TypeSystem* -Target::GetTypeSystemForLanguage (lldb::LanguageType language) -{ - switch (language) - { - case lldb::eLanguageTypeC: - case lldb::eLanguageTypeC11: - case lldb::eLanguageTypeC89: - case lldb::eLanguageTypeC99: - case lldb::eLanguageTypeC_plus_plus: - case lldb::eLanguageTypeC_plus_plus_03: - case lldb::eLanguageTypeC_plus_plus_11: - case lldb::eLanguageTypeC_plus_plus_14: - case lldb::eLanguageTypeObjC: - case lldb::eLanguageTypeObjC_plus_plus: - return GetScratchClangASTContext(true); - default: - return nullptr; - } -} - ClangASTImporter * Target::GetClangASTImporter() { @@ -2067,12 +2129,12 @@ Target::EvaluateExpression { const char *prefix = GetExpressionPrefixContentsAsCString(); Error error; - execution_results = ClangUserExpression::Evaluate (exe_ctx, - options, - expr_cstr, - prefix, - result_valobj_sp, - error); + execution_results = UserExpression::Evaluate (exe_ctx, + options, + expr_cstr, + prefix, + result_valobj_sp, + error); } m_suppress_stop_hooks = old_suppress_value; diff --git a/lldb/source/Target/ThreadPlanCallUserExpression.cpp b/lldb/source/Target/ThreadPlanCallUserExpression.cpp index 3ec3284afb4..b24f74b10df 100644 --- a/lldb/source/Target/ThreadPlanCallUserExpression.cpp +++ b/lldb/source/Target/ThreadPlanCallUserExpression.cpp @@ -19,7 +19,7 @@ #include "lldb/Core/Address.h" #include "lldb/Core/Log.h" #include "lldb/Core/Stream.h" -#include "lldb/Expression/ClangUserExpression.h" +#include "lldb/Expression/UserExpression.h" #include "lldb/Expression/IRDynamicChecks.h" #include "lldb/Host/HostInfo.h" #include "lldb/Target/LanguageRuntime.h" @@ -41,7 +41,7 @@ ThreadPlanCallUserExpression::ThreadPlanCallUserExpression (Thread &thread, Address &function, llvm::ArrayRef<lldb::addr_t> args, const EvaluateExpressionOptions &options, - lldb::ClangUserExpressionSP &user_expression_sp) : + lldb::UserExpressionSP &user_expression_sp) : ThreadPlanCallFunction (thread, function, CompilerType(), args, options), m_user_expression_sp (user_expression_sp) { |