diff options
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) { |