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:
Sean Callanan 2010-07-23 00:16:21 +00:00
parent e29e389678
commit ebf7707e53
7 changed files with 324 additions and 155 deletions

View File

@ -21,7 +21,7 @@
// Project includes // Project includes
#include "lldb/Core/ClangForward.h" #include "lldb/Core/ClangForward.h"
#include "lldb/Core/Value.h" #include "lldb/Core/Value.h"
#include "lldb/Symbol/ClangASTType.h" #include "lldb/Symbol/TaggedASTType.h"
namespace llvm { namespace llvm {
class Value; class Value;

View File

@ -91,6 +91,9 @@ public:
// This variant writes down function_address and arg_value. // 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); 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. /// 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 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); 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); bool FetchFunctionResults (ExecutionContext &exc_context, lldb::addr_t args_addr, Value &ret_value);
void DeallocateFunctionResults (ExecutionContext &exc_context, lldb::addr_t args_addr); void DeallocateFunctionResults (ExecutionContext &exc_context, lldb::addr_t args_addr);

View File

@ -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

View File

@ -331,6 +331,7 @@
49307AB211DEA4F20081F992 /* IRForTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 49307AB111DEA4F20081F992 /* IRForTarget.h */; }; 49307AB211DEA4F20081F992 /* IRForTarget.h in Headers */ = {isa = PBXBuildFile; fileRef = 49307AB111DEA4F20081F992 /* IRForTarget.h */; };
49A8A3A011D568A300AD3B68 /* ClangResultSynthesizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49A8A39F11D568A300AD3B68 /* ClangResultSynthesizer.cpp */; }; 49A8A3A011D568A300AD3B68 /* ClangResultSynthesizer.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 49A8A39F11D568A300AD3B68 /* ClangResultSynthesizer.cpp */; };
49A8A3A411D568BF00AD3B68 /* ClangResultSynthesizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 49A8A3A311D568BF00AD3B68 /* ClangResultSynthesizer.h */; }; 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 */; }; 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"; }; }; 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 */; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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>"; }; 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 */, 26BC7C6310F1B6E900F91463 /* SymbolVendor.h */,
26BC7C6410F1B6E900F91463 /* Symtab.h */, 26BC7C6410F1B6E900F91463 /* Symtab.h */,
26BC7F1F10F1B8EC00F91463 /* Symtab.cpp */, 26BC7F1F10F1B8EC00F91463 /* Symtab.cpp */,
49BB309511F79450001A4197 /* TaggedASTType.h */,
26BC7C6510F1B6E900F91463 /* Type.h */, 26BC7C6510F1B6E900F91463 /* Type.h */,
26BC7F2010F1B8EC00F91463 /* Type.cpp */, 26BC7F2010F1B8EC00F91463 /* Type.cpp */,
26BC7C6610F1B6E900F91463 /* TypeList.h */, 26BC7C6610F1B6E900F91463 /* TypeList.h */,
@ -2202,6 +2205,7 @@
4C5DBBC911E3FEC60035160F /* CommandObjectCommands.h in Headers */, 4C5DBBC911E3FEC60035160F /* CommandObjectCommands.h in Headers */,
26D27CA011ED3A4E0024D721 /* ELFHeader.h in Headers */, 26D27CA011ED3A4E0024D721 /* ELFHeader.h in Headers */,
49E45FAA11F660DC008F7B28 /* ClangASTType.h in Headers */, 49E45FAA11F660DC008F7B28 /* ClangASTType.h in Headers */,
49BB309611F79450001A4197 /* TaggedASTType.h in Headers */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
@ -2764,7 +2768,7 @@
"$(LLVM_BUILD_DIR)", "$(LLVM_BUILD_DIR)",
); );
LLVM_BUILD_DIR = "$(SRCROOT)/llvm"; LLVM_BUILD_DIR = "$(SRCROOT)/llvm";
LLVM_CONFIGURATION = Release; LLVM_CONFIGURATION = "Debug+Asserts";
OTHER_CFLAGS = ( OTHER_CFLAGS = (
"-DFOR_DYLD=0", "-DFOR_DYLD=0",
"-DSUPPORT_REMOTE_UNWINDING", "-DSUPPORT_REMOTE_UNWINDING",
@ -2817,7 +2821,7 @@
"$(LLVM_BUILD_DIR)", "$(LLVM_BUILD_DIR)",
); );
LLVM_BUILD_DIR = "$(SRCROOT)/llvm"; LLVM_BUILD_DIR = "$(SRCROOT)/llvm";
LLVM_CONFIGURATION = Release; LLVM_CONFIGURATION = "Debug+Asserts";
OTHER_CFLAGS = ( OTHER_CFLAGS = (
"-DFOR_DYLD=0", "-DFOR_DYLD=0",
"-DSUPPORT_REMOTE_UNWINDING", "-DSUPPORT_REMOTE_UNWINDING",
@ -2927,7 +2931,7 @@
"$(LLVM_BUILD_DIR)", "$(LLVM_BUILD_DIR)",
); );
LLVM_BUILD_DIR = "$(DERIVED_FILE_DIR)/llvm.build"; LLVM_BUILD_DIR = "$(DERIVED_FILE_DIR)/llvm.build";
LLVM_CONFIGURATION = Release; LLVM_CONFIGURATION = "Debug+Asserts";
OTHER_CFLAGS = ( OTHER_CFLAGS = (
"-DFOR_DYLD=0", "-DFOR_DYLD=0",
"-DSUPPORT_REMOTE_UNWINDING", "-DSUPPORT_REMOTE_UNWINDING",

View File

@ -12,26 +12,25 @@
// C Includes // C Includes
// C++ Includes // C++ Includes
// Other libraries and framework includes // Other libraries and framework includes
#include "llvm/ADT/StringRef.h"
// Project includes // Project includes
#include "lldb/Core/Debugger.h" #include "lldb/Interpreter/Args.h"
#include "lldb/Core/Value.h" #include "lldb/Core/Value.h"
#include "lldb/Core/InputReader.h" #include "lldb/Core/InputReader.h"
#include "lldb/Expression/ClangExpression.h" #include "lldb/Expression/ClangExpression.h"
#include "lldb/Expression/ClangExpressionDeclMap.h" #include "lldb/Expression/ClangExpressionDeclMap.h"
#include "lldb/Expression/ClangExpressionVariable.h" #include "lldb/Expression/ClangExpressionVariable.h"
#include "lldb/Expression/CLangFunction.h"
#include "lldb/Expression/DWARFExpression.h" #include "lldb/Expression/DWARFExpression.h"
#include "lldb/Host/Host.h" #include "lldb/Host/Host.h"
#include "lldb/Interpreter/Args.h" #include "lldb/Core/Debugger.h"
#include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandInterpreter.h"
#include "lldb/Interpreter/CommandReturnObject.h" #include "lldb/Interpreter/CommandReturnObject.h"
#include "lldb/Symbol/ClangASTType.h"
#include "lldb/Symbol/ObjectFile.h" #include "lldb/Symbol/ObjectFile.h"
#include "lldb/Symbol/Variable.h" #include "lldb/Symbol/Variable.h"
#include "lldb/Target/Process.h" #include "lldb/Target/Process.h"
#include "lldb/Target/StackFrame.h" #include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h" #include "lldb/Target/Target.h"
#include "llvm/ADT/StringRef.h"
using namespace lldb; using namespace lldb;
using namespace lldb_private; using namespace lldb_private;
@ -256,6 +255,10 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream
bool success; bool success;
bool canInterpret = false; bool canInterpret = false;
clang::ASTContext *ast_context = clang_expr.GetASTContext ();
Value expr_result;
Error expr_error;
if (m_options.use_ir) if (m_options.use_ir)
{ {
canInterpret = clang_expr.ConvertIRToDWARF (expr_local_vars, dwarf_opcodes); canInterpret = clang_expr.ConvertIRToDWARF (expr_local_vars, dwarf_opcodes);
@ -306,21 +309,56 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream
return false; return false;
} }
Error err;
lldb::addr_t struct_address; 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; return false;
} }
log->Printf("Function address : 0x%llx", (uint64_t)function_address); if (log)
log->Printf("Structure address : 0x%llx", (uint64_t)struct_address); {
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 else
{ {
@ -356,9 +394,6 @@ CommandObjectExpression::EvaluateExpression (const char *expr, bool bare, Stream
log->PutCString (stream_string.GetString ().c_str ()); 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); success = dwarf_expr.Evaluate (&m_exe_ctx, ast_context, NULL, expr_result, &expr_error);
if (!success) 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 ()); error_stream.Printf ("error: couldn't evaluate DWARF expression: %s\n", expr_error.AsCString ());
return false; return false;
} }
}
/////////////////////////////////////// ///////////////////////////////////////
// Interpret the result and print it // Interpret the result and print it
// //
lldb::Format format = m_options.format; lldb::Format format = m_options.format;
// Resolve any values that are possible // Resolve any values that are possible
expr_result.ResolveValue (&m_exe_ctx, ast_context); expr_result.ResolveValue (&m_exe_ctx, ast_context);
if (expr_result.GetContextType () == Value::eContextTypeInvalid && if (expr_result.GetContextType () == Value::eContextTypeInvalid &&
expr_result.GetValueType () == Value::eValueTypeScalar && expr_result.GetValueType () == Value::eValueTypeScalar &&
format == eFormatDefault) format == eFormatDefault)
{ {
// The expression result is just a scalar with no special formatting // The expression result is just a scalar with no special formatting
expr_result.GetScalar ().GetValue (&output_stream, m_options.show_types); expr_result.GetScalar ().GetValue (&output_stream, m_options.show_types);
output_stream.EOL (); 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();
return true; 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 bool

View File

@ -295,8 +295,10 @@ ClangExpressionDeclMap::DoMaterialize (bool dematerialize,
iter->m_parser_type.GetOpaqueQualType()), iter->m_parser_type.GetOpaqueQualType()),
context); context);
result_value->SetContext(Value::eContextTypeOpaqueClangQualType, result_value->SetContext(Value::eContextTypeOpaqueClangQualType, copied_type.GetOpaqueQualType());
copied_type.GetOpaqueQualType());
result_value->SetValueType(Value::eValueTypeLoadAddress);
result_value->GetScalar() = (uintptr_t)m_materialized_location + iter->m_offset;
} }
continue; continue;
@ -330,10 +332,8 @@ ClangExpressionDeclMap::DoMaterializeOneVariable(bool dematerialize,
return false; return false;
} }
log->Printf("%s %s with type %p", if (log)
(dematerialize ? "Dematerializing" : "Materializing"), log->Printf("%s %s with type %p", (dematerialize ? "Dematerializing" : "Materializing"), name, type.GetOpaqueQualType());
name,
type.GetOpaqueQualType());
std::auto_ptr<lldb_private::Value> location_value(GetVariableValue(exe_ctx, std::auto_ptr<lldb_private::Value> location_value(GetVariableValue(exe_ctx,
var, var,
@ -349,8 +349,7 @@ ClangExpressionDeclMap::DoMaterializeOneVariable(bool dematerialize,
{ {
lldb::addr_t value_addr = location_value->GetScalar().ULongLong(); lldb::addr_t value_addr = location_value->GetScalar().ULongLong();
size_t bit_size = ClangASTContext::GetTypeBitSize (type.GetASTContext(), size_t bit_size = ClangASTContext::GetTypeBitSize(type.GetASTContext(), type.GetOpaqueQualType());
type.GetOpaqueQualType());
size_t byte_size = bit_size % 8 ? ((bit_size + 8) / 8) : (bit_size / 8); size_t byte_size = bit_size % 8 ? ((bit_size + 8) / 8) : (bit_size / 8);
DataBufferHeap data; DataBufferHeap data;
@ -493,9 +492,7 @@ ClangExpressionDeclMap::FindVariableInScope(const SymbolContext &sym_ctx,
if (type->GetASTContext() == var->GetType()->GetClangAST()) if (type->GetASTContext() == var->GetType()->GetClangAST())
{ {
if (!ClangASTContext::AreTypesSame(type->GetASTContext(), if (!ClangASTContext::AreTypesSame(type->GetASTContext(), type->GetOpaqueQualType(), var->GetType()->GetOpaqueClangQualType()))
type->GetOpaqueQualType(),
var->GetType()->GetOpaqueClangQualType()))
return NULL; return NULL;
} }
else else

View File

@ -32,6 +32,7 @@
#include "lldb/Symbol/Function.h" #include "lldb/Symbol/Function.h"
#include "lldb/Target/ExecutionContext.h" #include "lldb/Target/ExecutionContext.h"
#include "lldb/Target/Process.h" #include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/Thread.h" #include "lldb/Target/Thread.h"
#include "lldb/Target/ThreadPlan.h" #include "lldb/Target/ThreadPlan.h"
#include "lldb/Target/ThreadPlanCallFunction.h" #include "lldb/Target/ThreadPlanCallFunction.h"
@ -385,7 +386,7 @@ ClangFunction::InsertFunction (ExecutionContext &exc_context, lldb::addr_t &args
} }
ThreadPlan * 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. // FIXME: Use the errors Stream for better error reporting.
@ -399,7 +400,7 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exc_context, lldb:
// Okay, now run the function: // 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, ThreadPlan *new_plan = new ThreadPlanCallFunction (*exc_context.thread,
wrapper_address, wrapper_address,
args_addr, args_addr,
@ -473,86 +474,68 @@ ClangFunction::ExecuteFunction(
return ExecuteFunction (exc_context, NULL, errors, true, single_thread_timeout_usec, try_all_threads, results); return ExecuteFunction (exc_context, NULL, errors, true, single_thread_timeout_usec, try_all_threads, results);
} }
ClangFunction::ExecutionResults // This is the static function
ClangFunction::ExecuteFunction( ClangFunction::ExecutionResults
ClangFunction::ExecuteFunction (
ExecutionContext &exc_context, ExecutionContext &exc_context,
lldb::addr_t *args_addr_ptr, lldb::addr_t function_address,
Stream &errors, lldb::addr_t &void_arg,
bool stop_others, bool stop_others,
uint32_t single_thread_timeout_usec, bool try_all_threads,
bool try_all_threads, uint32_t single_thread_timeout_usec,
Value &results) Stream &errors)
{ {
using namespace clang; ClangFunction::ExecutionResults return_value = eExecutionSetupError;
ExecutionResults return_value = eExecutionSetupError;
Process *process = exc_context.process;
lldb::addr_t args_addr; lldb::ThreadPlanSP call_plan_sp(ClangFunction::GetThreadPlanToCallFunction(exc_context, function_address, void_arg, errors, stop_others, false));
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));
ThreadPlanCallFunction *call_plan_ptr = static_cast<ThreadPlanCallFunction *> (call_plan_sp.get()); 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) if (call_plan_sp == NULL)
return return_value; return eExecutionSetupError;
call_plan_sp->SetPrivate(true); call_plan_sp->SetPrivate(true);
exc_context.thread->QueueThreadPlan(call_plan_sp, true); exc_context.thread->QueueThreadPlan(call_plan_sp, true);
// We need to call the function synchronously, so spin waiting for it to return. // 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 // 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. // won't be able to gather the result at this point.
TimeValue* timeout_ptr = NULL; TimeValue* timeout_ptr = NULL;
TimeValue real_timeout; TimeValue real_timeout;
if (single_thread_timeout_usec != 0) if (single_thread_timeout_usec != 0)
{ {
real_timeout = TimeValue::Now(); real_timeout = TimeValue::Now();
real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec); real_timeout.OffsetWithMicroSeconds(single_thread_timeout_usec);
timeout_ptr = &real_timeout; timeout_ptr = &real_timeout;
} }
process->Resume ();
exc_context.process->Resume ();
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
while (1) while (1)
{ {
lldb::EventSP event_sp; lldb::EventSP event_sp;
// Now wait for the process to stop again: // Now wait for the process to stop again:
// FIXME: Probably want a time out. // 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) if (stop_state == lldb::eStateInvalid && timeout_ptr != NULL)
{ {
// Right now this is the only way to tell we've timed out... // Right now this is the only way to tell we've timed out...
// We should interrupt the process here... // We should interrupt the process here...
// Not really sure what to do if Halt fails here... // Not really sure what to do if Halt fails here...
Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP);
if (log) if (log)
log->Printf ("Running function with timeout: %d timed out, trying with all threads enabled.", single_thread_timeout_usec); 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; 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) if (stop_state == lldb::eStateInvalid)
{ {
errors.Printf ("Got an invalid stop state after halt."); errors.Printf ("Got an invalid stop state after halt.");
@ -574,10 +557,9 @@ ClangFunction::ExecuteFunction(
return_value = eExecutionCompleted; return_value = eExecutionCompleted;
break; break;
} }
call_plan_ptr->SetStopOthers (false); call_plan_ptr->SetStopOthers (false);
process->Resume(); exc_context.process->Resume();
continue; continue;
} }
else else
@ -586,7 +568,7 @@ ClangFunction::ExecuteFunction(
} }
if (stop_state == lldb::eStateRunning || stop_state == lldb::eStateStepping) if (stop_state == lldb::eStateRunning || stop_state == lldb::eStateStepping)
continue; continue;
if (exc_context.thread->IsThreadPlanDone (call_plan_sp.get())) if (exc_context.thread->IsThreadPlanDone (call_plan_sp.get()))
{ {
return_value = eExecutionCompleted; return_value = eExecutionCompleted;
@ -599,12 +581,114 @@ ClangFunction::ExecuteFunction(
} }
else 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; return_value = eExecutionInterrupted;
break; 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) if (return_value != eExecutionCompleted)
return return_value; return return_value;