forked from OSchip/llvm-project
Modified TaggedASTType to inherit from ClangASTType
and moved it to its own header file for cleanliness. Added more logging to ClangFunction so that we can diagnose crashes in the executing expression. Added code to extract the result of the expression from the struct that is passed to the JIT-compiled code. llvm-svn: 109199
This commit is contained in:
parent
e29e389678
commit
ebf7707e53
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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",
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
ClangFunction::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;
|
||||
}
|
||||
|
||||
|
||||
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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue