diff options
-rw-r--r-- | lldb/include/lldb/Expression/ClangExpressionDeclMap.h | 2 | ||||
-rw-r--r-- | lldb/include/lldb/Expression/ClangFunction.h | 12 | ||||
-rw-r--r-- | lldb/include/lldb/Symbol/TaggedASTType.h | 43 | ||||
-rw-r--r-- | lldb/lldb.xcodeproj/project.pbxproj | 10 | ||||
-rw-r--r-- | lldb/source/Commands/CommandObjectExpression.cpp | 207 | ||||
-rw-r--r-- | lldb/source/Expression/ClangExpressionDeclMap.cpp | 19 | ||||
-rw-r--r-- | lldb/source/Expression/ClangFunction.cpp | 184 |
7 files changed, 323 insertions, 154 deletions
diff --git a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h index 366067ff859..abe21710e59 100644 --- a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h +++ b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h @@ -21,7 +21,7 @@ // Project includes #include "lldb/Core/ClangForward.h" #include "lldb/Core/Value.h" -#include "lldb/Symbol/ClangASTType.h" +#include "lldb/Symbol/TaggedASTType.h" namespace llvm { class Value; diff --git a/lldb/include/lldb/Expression/ClangFunction.h b/lldb/include/lldb/Expression/ClangFunction.h index f0555bc916a..1ee55a79c81 100644 --- a/lldb/include/lldb/Expression/ClangFunction.h +++ b/lldb/include/lldb/Expression/ClangFunction.h @@ -91,6 +91,9 @@ public: // This variant writes down function_address and arg_value. bool WriteFunctionArguments (ExecutionContext &exc_context, lldb::addr_t &args_addr_ref, Address function_address, ValueList &arg_values, Stream &errors); + // Run a function at a particular address, with a given address passed on the stack. + static ExecutionResults ExecuteFunction (ExecutionContext &exe_ctx, lldb::addr_t function_address, lldb::addr_t &void_arg, bool stop_others, bool try_all_threads, uint32_t single_thread_timeout_usec, Stream &errors); + //------------------------------------------------------------------ /// Run the function this ClangFunction was created with. /// @@ -198,7 +201,14 @@ public: ExecutionResults ExecuteFunction(ExecutionContext &context, lldb::addr_t *args_addr_ptr, Stream &errors, bool stop_others, uint32_t single_thread_timeout_usec, bool try_all_threads, Value &results); ExecutionResults ExecuteFunctionWithABI(ExecutionContext &context, Stream &errors, Value &results); - ThreadPlan *GetThreadPlanToCallFunction (ExecutionContext &exc_context, lldb::addr_t &args_addr_ref, Stream &errors, bool stop_others, bool discard_on_error = true); + static ThreadPlan * + GetThreadPlanToCallFunction (ExecutionContext &exc_context, lldb::addr_t func_addr, lldb::addr_t &args_addr_ref, Stream &errors, bool stop_others, bool discard_on_error = true); + + ThreadPlan * + GetThreadPlanToCallFunction (ExecutionContext &exc_context, lldb::addr_t &args_addr_ref, Stream &errors, bool stop_others, bool discard_on_error = true) + { + return ClangFunction::GetThreadPlanToCallFunction (exc_context, m_wrapper_function_addr, args_addr_ref, errors, stop_others, discard_on_error); + } bool FetchFunctionResults (ExecutionContext &exc_context, lldb::addr_t args_addr, Value &ret_value); void DeallocateFunctionResults (ExecutionContext &exc_context, lldb::addr_t args_addr); diff --git a/lldb/include/lldb/Symbol/TaggedASTType.h b/lldb/include/lldb/Symbol/TaggedASTType.h new file mode 100644 index 00000000000..6a5061dbf05 --- /dev/null +++ b/lldb/include/lldb/Symbol/TaggedASTType.h @@ -0,0 +1,43 @@ +//===-- TaggedASTType.h -----------------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef liblldb_TaggedASTType_h_ +#define liblldb_TaggedASTType_h_ + +#include "lldb/Symbol/ClangASTType.h" + +namespace lldb_private +{ + +// For cases in which there are multiple classes of types that are not +// interchangeable, to allow static type checking. +template <unsigned int C> class TaggedASTType : public ClangASTType +{ +public: + TaggedASTType (void *type, clang::ASTContext *ast_context) : + ClangASTType(type, ast_context) { } + + TaggedASTType (const TaggedASTType<C> &tw) : + ClangASTType(tw) { } + + TaggedASTType () : + ClangASTType() { } + + ~TaggedASTType() { } + + TaggedASTType<C> &operator= (const TaggedASTType<C> &tw) + { + ClangASTType::operator= (tw); + return *this; + } +}; + +} + +#endif diff --git a/lldb/lldb.xcodeproj/project.pbxproj b/lldb/lldb.xcodeproj/project.pbxproj index 6c8863448c2..7de6d01eef2 100644 --- a/lldb/lldb.xcodeproj/project.pbxproj +++ b/lldb/lldb.xcodeproj/project.pbxproj @@ -331,6 +331,7 @@ 49307AB211DEA4F20081F992 /* IRForTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 49307AB111DEA4F20081F992 /* IRForTarget.h */; }; 49A8A3A011D568A300AD3B68 /* ClangResultSynthesizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49A8A39F11D568A300AD3B68 /* ClangResultSynthesizer.cpp */; }; 49A8A3A411D568BF00AD3B68 /* ClangResultSynthesizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 49A8A3A311D568BF00AD3B68 /* ClangResultSynthesizer.h */; }; + 49BB309611F79450001A4197 /* TaggedASTType.h in Headers */ = {isa = PBXBuildFile; fileRef = 49BB309511F79450001A4197 /* TaggedASTType.h */; }; 49D7072711B5AD03001AD875 /* ClangASTSource.h in Headers */ = {isa = PBXBuildFile; fileRef = 49D7072611B5AD03001AD875 /* ClangASTSource.h */; }; 49D7072911B5AD11001AD875 /* ClangASTSource.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49D7072811B5AD11001AD875 /* ClangASTSource.cpp */; settings = {COMPILER_FLAGS = "-fno-rtti"; }; }; 49DA743011DE6A5A006AEF7E /* IRToDWARF.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49DA742F11DE6A5A006AEF7E /* IRToDWARF.cpp */; }; @@ -906,6 +907,7 @@ 499F381F11A5B3F300F5CE02 /* CommandObjectArgs.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = CommandObjectArgs.cpp; path = source/Commands/CommandObjectArgs.cpp; sourceTree = "<group>"; }; 49A8A39F11D568A300AD3B68 /* ClangResultSynthesizer.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ClangResultSynthesizer.cpp; path = source/Expression/ClangResultSynthesizer.cpp; sourceTree = "<group>"; }; 49A8A3A311D568BF00AD3B68 /* ClangResultSynthesizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangResultSynthesizer.h; path = include/lldb/Expression/ClangResultSynthesizer.h; sourceTree = "<group>"; }; + 49BB309511F79450001A4197 /* TaggedASTType.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TaggedASTType.h; path = include/lldb/Symbol/TaggedASTType.h; sourceTree = "<group>"; }; 49BF48DC11ADF356008863BD /* ObjCObjectPrinter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ObjCObjectPrinter.cpp; path = source/Target/ObjCObjectPrinter.cpp; sourceTree = "<group>"; }; 49BF48E011ADF37D008863BD /* ObjCObjectPrinter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ObjCObjectPrinter.h; path = include/lldb/Target/ObjCObjectPrinter.h; sourceTree = "<group>"; }; 49D7072611B5AD03001AD875 /* ClangASTSource.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = ClangASTSource.h; path = include/lldb/Expression/ClangASTSource.h; sourceTree = "<group>"; }; @@ -1700,6 +1702,7 @@ 26BC7C6310F1B6E900F91463 /* SymbolVendor.h */, 26BC7C6410F1B6E900F91463 /* Symtab.h */, 26BC7F1F10F1B8EC00F91463 /* Symtab.cpp */, + 49BB309511F79450001A4197 /* TaggedASTType.h */, 26BC7C6510F1B6E900F91463 /* Type.h */, 26BC7F2010F1B8EC00F91463 /* Type.cpp */, 26BC7C6610F1B6E900F91463 /* TypeList.h */, @@ -2202,6 +2205,7 @@ 4C5DBBC911E3FEC60035160F /* CommandObjectCommands.h in Headers */, 26D27CA011ED3A4E0024D721 /* ELFHeader.h in Headers */, 49E45FAA11F660DC008F7B28 /* ClangASTType.h in Headers */, + 49BB309611F79450001A4197 /* TaggedASTType.h in Headers */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -2764,7 +2768,7 @@ "$(LLVM_BUILD_DIR)", ); LLVM_BUILD_DIR = "$(SRCROOT)/llvm"; - LLVM_CONFIGURATION = Release; + LLVM_CONFIGURATION = "Debug+Asserts"; OTHER_CFLAGS = ( "-DFOR_DYLD=0", "-DSUPPORT_REMOTE_UNWINDING", @@ -2817,7 +2821,7 @@ "$(LLVM_BUILD_DIR)", ); LLVM_BUILD_DIR = "$(SRCROOT)/llvm"; - LLVM_CONFIGURATION = Release; + LLVM_CONFIGURATION = "Debug+Asserts"; OTHER_CFLAGS = ( "-DFOR_DYLD=0", "-DSUPPORT_REMOTE_UNWINDING", @@ -2927,7 +2931,7 @@ "$(LLVM_BUILD_DIR)", ); LLVM_BUILD_DIR = "$(DERIVED_FILE_DIR)/llvm.build"; - LLVM_CONFIGURATION = Release; + LLVM_CONFIGURATION = "Debug+Asserts"; OTHER_CFLAGS = ( "-DFOR_DYLD=0", "-DSUPPORT_REMOTE_UNWINDING", diff --git a/lldb/source/Commands/CommandObjectExpression.cpp b/lldb/source/Commands/CommandObjectExpression.cpp index 4135ed82cc0..303ca17cc56 100644 --- a/lldb/source/Commands/CommandObjectExpression.cpp +++ b/lldb/source/Commands/CommandObjectExpression.cpp @@ -12,26 +12,25 @@ // C Includes // C++ Includes // Other libraries and framework includes -#include "llvm/ADT/StringRef.h" - // Project includes -#include "lldb/Core/Debugger.h" +#include "lldb/Interpreter/Args.h" #include "lldb/Core/Value.h" #include "lldb/Core/InputReader.h" #include "lldb/Expression/ClangExpression.h" #include "lldb/Expression/ClangExpressionDeclMap.h" #include "lldb/Expression/ClangExpressionVariable.h" +#include "lldb/Expression/CLangFunction.h" #include "lldb/Expression/DWARFExpression.h" #include "lldb/Host/Host.h" -#include "lldb/Interpreter/Args.h" +#include "lldb/Core/Debugger.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" -#include "lldb/Symbol/ClangASTType.h" #include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/Variable.h" #include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" #include "lldb/Target/Target.h" +#include "llvm/ADT/StringRef.h" using namespace lldb; using namespace lldb_private; @@ -256,6 +255,10 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream bool success; bool canInterpret = false; + clang::ASTContext *ast_context = clang_expr.GetASTContext (); + Value expr_result; + Error expr_error; + if (m_options.use_ir) { canInterpret = clang_expr.ConvertIRToDWARF (expr_local_vars, dwarf_opcodes); @@ -306,21 +309,56 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream return false; } - Error err; lldb::addr_t struct_address; - if (!expr_decl_map.Materialize(&m_exe_ctx, struct_address, err)) + if (!expr_decl_map.Materialize(&m_exe_ctx, struct_address, expr_error)) { - error_stream.Printf ("Couldn't materialize struct: %s\n", err.AsCString("unknown error")); + error_stream.Printf ("Couldn't materialize struct: %s\n", expr_error.AsCString("unknown error")); return false; } - log->Printf("Function address : 0x%llx", (uint64_t)function_address); - log->Printf("Structure address : 0x%llx", (uint64_t)struct_address); + if (log) + { + log->Printf("Function address : 0x%llx", (uint64_t)function_address); + log->Printf("Structure address : 0x%llx", (uint64_t)struct_address); + } + + ClangFunction::ExecutionResults execution_result = + ClangFunction::ExecuteFunction (m_exe_ctx, function_address, struct_address, true, true, 10000, error_stream); + + if (execution_result != ClangFunction::eExecutionCompleted) + { + const char *result_name; + + switch (execution_result) + { + case ClangFunction::eExecutionCompleted: + result_name = "eExecutionCompleted"; + break; + case ClangFunction::eExecutionDiscarded: + result_name = "eExecutionDiscarded"; + break; + case ClangFunction::eExecutionInterrupted: + result_name = "eExecutionInterrupted"; + break; + case ClangFunction::eExecutionSetupError: + result_name = "eExecutionSetupError"; + break; + case ClangFunction::eExecutionTimedOut: + result_name = "eExecutionTimedOut"; + break; + } + + error_stream.Printf ("Couldn't execute function; result was %s\n", result_name); + return false; + } + + if (!expr_decl_map.Dematerialize(&m_exe_ctx, expr_result, expr_error)) + { + error_stream.Printf ("Couldn't dematerialize struct: %s\n", expr_error.AsCString("unknown error")); + return false; + } } - - return true; - } else { @@ -356,9 +394,6 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream log->PutCString (stream_string.GetString ().c_str ()); } - clang::ASTContext *ast_context = clang_expr.GetASTContext (); - Value expr_result; - Error expr_error; success = dwarf_expr.Evaluate (&m_exe_ctx, ast_context, NULL, expr_result, &expr_error); if (!success) @@ -366,81 +401,77 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream error_stream.Printf ("error: couldn't evaluate DWARF expression: %s\n", expr_error.AsCString ()); return false; } + } - /////////////////////////////////////// - // Interpret the result and print it - // - - lldb::Format format = m_options.format; - - // Resolve any values that are possible - expr_result.ResolveValue (&m_exe_ctx, ast_context); - - if (expr_result.GetContextType () == Value::eContextTypeInvalid && - expr_result.GetValueType () == Value::eValueTypeScalar && - format == eFormatDefault) - { - // The expression result is just a scalar with no special formatting - expr_result.GetScalar ().GetValue (&output_stream, m_options.show_types); - output_stream.EOL (); - return true; - } - - // The expression result is more complext and requires special handling - DataExtractor data; - expr_error = expr_result.GetValueAsData (&m_exe_ctx, ast_context, data, 0); - - if (!expr_error.Success ()) - { - error_stream.Printf ("error: couldn't resolve result value: %s\n", expr_error.AsCString ()); - return false; - } - - if (format == eFormatDefault) - format = expr_result.GetValueDefaultFormat (); - - void *clang_type = expr_result.GetValueOpaqueClangQualType (); - - if (clang_type) - { - if (m_options.show_types) - { - ConstString type_name(ClangASTType::GetClangTypeName (clang_type)); - if (type_name) - output_stream.Printf("(%s) ", type_name.AsCString("<invalid>")); - } - - ClangASTType::DumpValue (ast_context, // The ASTContext that the clang type belongs to - clang_type, // The opaque clang type we want to dump that value of - &m_exe_ctx, // The execution context for memory and variable access - &output_stream, // Stream to dump to - format, // Format to use when dumping - data, // A buffer containing the bytes for the clang type - 0, // Byte offset within "data" where value is - data.GetByteSize (), // Size in bytes of the value we are dumping - 0, // Bitfield bit size - 0, // Bitfield bit offset - m_options.show_types, // Show types? - m_options.show_summary, // Show summary? - m_options.debug, // Debug logging output? - UINT32_MAX); // Depth to dump in case this is an aggregate type - } - else - { - data.Dump (&output_stream, // Stream to dump to - 0, // Byte offset within "data" - format, // Format to use when dumping - data.GetByteSize (), // Size in bytes of each item we are dumping - 1, // Number of items to dump - UINT32_MAX, // Number of items per line - LLDB_INVALID_ADDRESS, // Invalid address, don't show any offset/address context - 0, // Bitfield bit size - 0); // Bitfield bit offset - } - output_stream.EOL(); - + /////////////////////////////////////// + // Interpret the result and print it + // + + lldb::Format format = m_options.format; + + // Resolve any values that are possible + expr_result.ResolveValue (&m_exe_ctx, ast_context); + + if (expr_result.GetContextType () == Value::eContextTypeInvalid && + expr_result.GetValueType () == Value::eValueTypeScalar && + format == eFormatDefault) + { + // The expression result is just a scalar with no special formatting + expr_result.GetScalar ().GetValue (&output_stream, m_options.show_types); + output_stream.EOL (); return true; } + + // The expression result is more complext and requires special handling + DataExtractor data; + expr_error = expr_result.GetValueAsData (&m_exe_ctx, ast_context, data, 0); + + if (!expr_error.Success ()) + { + error_stream.Printf ("error: couldn't resolve result value: %s\n", expr_error.AsCString ()); + return false; + } + + if (format == eFormatDefault) + format = expr_result.GetValueDefaultFormat (); + + void *clang_type = expr_result.GetValueOpaqueClangQualType (); + + if (clang_type) + { + if (m_options.show_types) + output_stream.PutCString(ClangASTType::GetClangTypeName (clang_type).GetCString()); + + ClangASTType::DumpValue (ast_context, // The ASTContext that the clang type belongs to + clang_type, // The opaque clang type we want to dump that value of + &m_exe_ctx, // The execution context for memory and variable access + &output_stream, // Stream to dump to + format, // Format to use when dumping + data, // A buffer containing the bytes for the clang type + 0, // Byte offset within "data" where value is + data.GetByteSize (), // Size in bytes of the value we are dumping + 0, // Bitfield bit size + 0, // Bitfield bit offset + m_options.show_types, // Show types? + m_options.show_summary, // Show summary? + m_options.debug, // Debug logging output? + UINT32_MAX); // Depth to dump in case this is an aggregate type + } + else + { + data.Dump (&output_stream, // Stream to dump to + 0, // Byte offset within "data" + format, // Format to use when dumping + data.GetByteSize (), // Size in bytes of each item we are dumping + 1, // Number of items to dump + UINT32_MAX, // Number of items per line + LLDB_INVALID_ADDRESS, // Invalid address, don't show any offset/address context + 0, // Bitfield bit size + 0); // Bitfield bit offset + } + output_stream.EOL(); + + return true; } bool diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp index 54bfad5772a..1a9e57f0aa7 100644 --- a/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp @@ -295,8 +295,10 @@ ClangExpressionDeclMap::DoMaterialize (bool dematerialize, iter->m_parser_type.GetOpaqueQualType()), context); - result_value->SetContext(Value::eContextTypeOpaqueClangQualType, - copied_type.GetOpaqueQualType()); + result_value->SetContext(Value::eContextTypeOpaqueClangQualType, copied_type.GetOpaqueQualType()); + + result_value->SetValueType(Value::eValueTypeLoadAddress); + result_value->GetScalar() = (uintptr_t)m_materialized_location + iter->m_offset; } continue; @@ -330,10 +332,8 @@ ClangExpressionDeclMap::DoMaterializeOneVariable(bool dematerialize, return false; } - log->Printf("%s %s with type %p", - (dematerialize ? "Dematerializing" : "Materializing"), - name, - type.GetOpaqueQualType()); + if (log) + log->Printf("%s %s with type %p", (dematerialize ? "Dematerializing" : "Materializing"), name, type.GetOpaqueQualType()); std::auto_ptr<lldb_private::Value> location_value(GetVariableValue(exe_ctx, var, @@ -349,8 +349,7 @@ ClangExpressionDeclMap::DoMaterializeOneVariable(bool dematerialize, { lldb::addr_t value_addr = location_value->GetScalar().ULongLong(); - size_t bit_size = ClangASTContext::GetTypeBitSize (type.GetASTContext(), - type.GetOpaqueQualType()); + size_t bit_size = ClangASTContext::GetTypeBitSize(type.GetASTContext(), type.GetOpaqueQualType()); size_t byte_size = bit_size % 8 ? ((bit_size + 8) / 8) : (bit_size / 8); DataBufferHeap data; @@ -493,9 +492,7 @@ ClangExpressionDeclMap::FindVariableInScope(const SymbolContext &sym_ctx, if (type->GetASTContext() == var->GetType()->GetClangAST()) { - if (!ClangASTContext::AreTypesSame(type->GetASTContext(), - type->GetOpaqueQualType(), - var->GetType()->GetOpaqueClangQualType())) + if (!ClangASTContext::AreTypesSame(type->GetASTContext(), type->GetOpaqueQualType(), var->GetType()->GetOpaqueClangQualType())) return NULL; } else diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/ClangFunction.cpp index 7e1160dfbef..b5a580c5935 100644 --- a/lldb/source/Expression/ClangFunction.cpp +++ b/lldb/source/Expression/ClangFunction.cpp @@ -32,6 +32,7 @@ #include "lldb/Symbol/Function.h" #include "lldb/Target/ExecutionContext.h" #include "lldb/Target/Process.h" +#include "lldb/Target/RegisterContext.h" #include "lldb/Target/Thread.h" #include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlanCallFunction.h" @@ -385,7 +386,7 @@ ClangFunction::InsertFunction (ExecutionContext &exc_context, lldb::addr_t &args } ThreadPlan * -ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exc_context, lldb::addr_t &args_addr, Stream &errors, bool stop_others, bool discard_on_error) +ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exc_context, lldb::addr_t func_addr, lldb::addr_t &args_addr, Stream &errors, bool stop_others, bool discard_on_error) { // FIXME: Use the errors Stream for better error reporting. @@ -399,7 +400,7 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exc_context, lldb: // Okay, now run the function: - Address wrapper_address (NULL, m_wrapper_function_addr); + Address wrapper_address (NULL, func_addr); ThreadPlan *new_plan = new ThreadPlanCallFunction (*exc_context.thread, wrapper_address, args_addr, @@ -473,86 +474,68 @@ ClangFunction::ExecuteFunction( return ExecuteFunction (exc_context, NULL, errors, true, single_thread_timeout_usec, try_all_threads, results); } -ClangFunction::ExecutionResults -ClangFunction::ExecuteFunction( +// This is the static function +ClangFunction::ExecutionResults +ClangFunction::ExecuteFunction ( ExecutionContext &exc_context, - lldb::addr_t *args_addr_ptr, - Stream &errors, - bool stop_others, - uint32_t single_thread_timeout_usec, - bool try_all_threads, - Value &results) + lldb::addr_t function_address, + lldb::addr_t &void_arg, + bool stop_others, + bool try_all_threads, + uint32_t single_thread_timeout_usec, + Stream &errors) { - using namespace clang; - ExecutionResults return_value = eExecutionSetupError; - Process *process = exc_context.process; - - lldb::addr_t args_addr; - - if (args_addr_ptr != NULL) - args_addr = *args_addr_ptr; - else - args_addr = LLDB_INVALID_ADDRESS; - - if (CompileFunction(errors) != 0) - return eExecutionSetupError; - - if (args_addr == LLDB_INVALID_ADDRESS) - { - if (!InsertFunction(exc_context, args_addr, errors)) - return eExecutionSetupError; - } - + ClangFunction::ExecutionResults return_value = eExecutionSetupError; - lldb::ThreadPlanSP call_plan_sp(GetThreadPlanToCallFunction(exc_context, args_addr, errors, stop_others, false)); + lldb::ThreadPlanSP call_plan_sp(ClangFunction::GetThreadPlanToCallFunction(exc_context, function_address, void_arg, errors, stop_others, false)); ThreadPlanCallFunction *call_plan_ptr = static_cast<ThreadPlanCallFunction *> (call_plan_sp.get()); - if (args_addr_ptr != NULL) - *args_addr_ptr = args_addr; - if (call_plan_sp == NULL) - return return_value; - + return eExecutionSetupError; + call_plan_sp->SetPrivate(true); exc_context.thread->QueueThreadPlan(call_plan_sp, true); - + // We need to call the function synchronously, so spin waiting for it to return. // If we get interrupted while executing, we're going to lose our context, and // won't be able to gather the result at this point. - + TimeValue* timeout_ptr = NULL; TimeValue real_timeout; + if (single_thread_timeout_usec != 0) { real_timeout = TimeValue::Now(); real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec); timeout_ptr = &real_timeout; } - process->Resume (); - + + exc_context.process->Resume (); + + Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); while (1) { lldb::EventSP event_sp; - + // Now wait for the process to stop again: // FIXME: Probably want a time out. - lldb::StateType stop_state = process->WaitForStateChangedEvents (timeout_ptr, event_sp); + lldb::StateType stop_state = exc_context.process->WaitForStateChangedEvents (timeout_ptr, event_sp); + if (stop_state == lldb::eStateInvalid && timeout_ptr != NULL) { // Right now this is the only way to tell we've timed out... // We should interrupt the process here... // Not really sure what to do if Halt fails here... - Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); if (log) log->Printf ("Running function with timeout: %d timed out, trying with all threads enabled.", single_thread_timeout_usec); - - if (process->Halt().Success()) + + if (exc_context.process->Halt().Success()) { timeout_ptr = NULL; - stop_state = process->WaitForStateChangedEvents (timeout_ptr, event_sp); + stop_state = exc_context.process->WaitForStateChangedEvents (timeout_ptr, event_sp); if (stop_state == lldb::eStateInvalid) { errors.Printf ("Got an invalid stop state after halt."); @@ -574,10 +557,9 @@ ClangFunction::ExecuteFunction( return_value = eExecutionCompleted; break; } - - + call_plan_ptr->SetStopOthers (false); - process->Resume(); + exc_context.process->Resume(); continue; } else @@ -586,7 +568,7 @@ ClangFunction::ExecuteFunction( } if (stop_state == lldb::eStateRunning || stop_state == lldb::eStateStepping) continue; - + if (exc_context.thread->IsThreadPlanDone (call_plan_sp.get())) { return_value = eExecutionCompleted; @@ -599,12 +581,114 @@ ClangFunction::ExecuteFunction( } else { + if (log) + { + StreamString s; + event_sp->Dump (&s); + StreamString ts; + + const char *event_explanation; + + do + { + const Process::ProcessEventData *event_data = Process::ProcessEventData::GetEventDataFromEvent (event_sp.get()); + + if (!event_data) + { + event_explanation = "<no event data>"; + break; + } + + Process *process = event_data->GetProcessSP().get(); + + if (!process) + { + event_explanation = "<no process>"; + break; + } + + ThreadList &thread_list = process->GetThreadList(); + + uint32_t num_threads = thread_list.GetSize(); + uint32_t thread_index; + + ts.Printf("<%u threads> ", num_threads); + + for (thread_index = 0; + thread_index < num_threads; + ++thread_index) + { + Thread *thread = thread_list.GetThreadAtIndex(thread_index).get(); + + if (!thread) + { + ts.Printf("<?> "); + continue; + } + + Thread::StopInfo stop_info; + thread->GetStopInfo(&stop_info); + + ts.Printf("<"); + RegisterContext *register_context = thread->GetRegisterContext(); + + if (register_context) + ts.Printf("[ip 0x%llx] ", register_context->GetPC()); + else + ts.Printf("[ip unknown] "); + + stop_info.Dump(&ts); + ts.Printf(">"); + } + + event_explanation = ts.GetData(); + } while (0); + + log->Printf("Execution interrupted: %s %s", s.GetData(), event_explanation); + } + return_value = eExecutionInterrupted; break; } + } + + return return_value; +} +ClangFunction::ExecutionResults +ClangFunction::ExecuteFunction( + ExecutionContext &exc_context, + lldb::addr_t *args_addr_ptr, + Stream &errors, + bool stop_others, + uint32_t single_thread_timeout_usec, + bool try_all_threads, + Value &results) +{ + using namespace clang; + ExecutionResults return_value = eExecutionSetupError; + + lldb::addr_t args_addr; + + if (args_addr_ptr != NULL) + args_addr = *args_addr_ptr; + else + args_addr = LLDB_INVALID_ADDRESS; + + if (CompileFunction(errors) != 0) + return eExecutionSetupError; + + if (args_addr == LLDB_INVALID_ADDRESS) + { + if (!InsertFunction(exc_context, args_addr, errors)) + return eExecutionSetupError; } + + return_value = ClangFunction::ExecuteFunction(exc_context, m_wrapper_function_addr, args_addr, stop_others, try_all_threads, single_thread_timeout_usec, errors); + if (args_addr_ptr != NULL) + *args_addr_ptr = args_addr; + if (return_value != eExecutionCompleted) return return_value; |