Added support for generating expressions that have

access to the members of the Objective-C self object.

The approach we take is to generate the method as a
@category on top of the self object, and to pass the
"self" pointer to it.  (_cmd is currently NULL.)

Most changes are in ClangExpressionDeclMap, but the
change that adds support to the ABIs to pass _cmd
touches a fair amount of code.

llvm-svn: 121722
This commit is contained in:
Sean Callanan 2010-12-13 22:46:15 +00:00
parent 4efa445f3c
commit 1782783095
21 changed files with 420 additions and 70 deletions

View File

@ -34,6 +34,7 @@ namespace clang
class CodeGenOptions;
class CodeGenerator;
class CompilerInstance;
class CompoundStmt;
class CXXBaseSpecifier;
class CXXBoolLiteralExpr;
class CXXFunctionalCastExpr;

View File

@ -122,13 +122,32 @@ private:
//----------------------------------------------------------------------
void TransformTopLevelDecl(clang::Decl *D);
//----------------------------------------------------------------------
/// Process an Objective-C method and produce the result variable and
/// initialization
///
/// @param[in] MethodDecl
/// The method to process.
//----------------------------------------------------------------------
bool SynthesizeObjCMethodResult(clang::ObjCMethodDecl *MethodDecl);
//----------------------------------------------------------------------
/// Process a function and produce the result variable and initialization
///
/// @param[in] FunDecl
/// The function to process.
//----------------------------------------------------------------------
bool SynthesizeResult(clang::FunctionDecl *FunDecl);
bool SynthesizeFunctionResult(clang::FunctionDecl *FunDecl);
//----------------------------------------------------------------------
/// Process a functionbody and produce the result variable and
/// initialization
///
/// @param[in] Body
/// The body of the function.
//----------------------------------------------------------------------
bool SynthesizeBodyResult(clang::CompoundStmt *Body,
clang::DeclContext *DC);
clang::ASTContext *m_ast_context; ///< The AST context to use for identifiers and types.
clang::ASTConsumer *m_passthrough; ///< The ASTConsumer down the chain, for passthrough. NULL if it's a SemaConsumer.

View File

@ -291,6 +291,10 @@ public:
/// @param[out] object_ptr
/// The this pointer.
///
/// @param[in] object_name
/// The name of the object pointer -- "this," "self," or similar
/// depending on language
///
/// @param[in] exe_ctx
/// The execution context at which to dump the struct.
///
@ -302,6 +306,7 @@ public:
/// True on success; false otherwise.
//------------------------------------------------------------------
bool GetObjectPointer(lldb::addr_t &object_ptr,
ConstString &object_name,
ExecutionContext &exe_ctx,
Error &error);

View File

@ -423,8 +423,13 @@ public:
/// True if the thread plan may simply be discarded if an error occurs.
///
/// @param[in] this_arg
/// If non-NULL, the function is invoked like a C++ method, with the
/// value pointed to by the pointer as its 'this' argument.
/// If non-NULL (and cmd_arg is NULL), the function is invoked like a C++
/// method, with the value pointed to by the pointer as its 'this'
/// argument.
///
/// @param[in] cmd_arg
/// If non-NULL, the function is invoked like an Objective-C method, with
/// this_arg in the 'self' slot and cmd_arg in the '_cmd' slot
///
/// @return
/// A ThreadPlan for executing the function.
@ -436,7 +441,8 @@ public:
Stream &errors,
bool stop_others,
bool discard_on_error,
lldb::addr_t *this_arg = 0);
lldb::addr_t *this_arg = 0,
lldb::addr_t *cmd_arg = 0);
//------------------------------------------------------------------
/// Get a thread plan to run the function this ClangFunction was created with.

View File

@ -162,6 +162,12 @@ public:
DumpTypeDescription (clang::ASTContext *ast_context,
lldb::clang_type_t opaque_clang_qual_type,
Stream *s);
void DumpTypeCode (Stream *s);
static void
DumpTypeCode (void *type,
Stream *s);
lldb::Encoding
GetEncoding (uint32_t &count);

View File

@ -35,7 +35,8 @@ public:
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg) const = 0;
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const = 0;
virtual bool
GetArgumentValues (Thread &thread,

View File

@ -28,7 +28,8 @@ public:
lldb::addr_t arg,
bool stop_other_threads,
bool discard_on_error = true,
lldb::addr_t *this_arg = 0);
lldb::addr_t *this_arg = 0,
lldb::addr_t *cmd_arg = 0);
virtual
~ThreadPlanCallFunction ();

View File

@ -31,6 +31,7 @@ public:
bool stop_other_threads,
bool discard_on_error,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg,
ClangUserExpression::ClangUserExpressionSP &user_expression_sp);
virtual

View File

@ -12,6 +12,7 @@
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclGroup.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/Expr.h"
#include "clang/AST/Stmt.h"
#include "clang/Parse/Parser.h"
@ -54,9 +55,23 @@ ASTResultSynthesizer::Initialize(ASTContext &Context)
void
ASTResultSynthesizer::TransformTopLevelDecl(Decl* D)
{
LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D);
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (NamedDecl *named_decl = dyn_cast<NamedDecl>(D))
{
if (log)
{
if (named_decl->getIdentifier())
log->Printf("TransformTopLevelDecl(%s)", named_decl->getIdentifier()->getNameStart());
else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
log->Printf("TransformTopLevelDecl(%s)", method_decl->getSelector().getAsString().c_str());
else
log->Printf("TransformTopLevelDecl(<complex>)");
}
}
if (linkage_spec_decl)
if (LinkageSpecDecl *linkage_spec_decl = dyn_cast<LinkageSpecDecl>(D))
{
RecordDecl::decl_iterator decl_iterator;
@ -67,14 +82,21 @@ ASTResultSynthesizer::TransformTopLevelDecl(Decl* D)
TransformTopLevelDecl(*decl_iterator);
}
}
FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D);
if (m_ast_context &&
function_decl &&
!function_decl->getNameInfo().getAsString().compare("$__lldb_expr"))
else if (ObjCMethodDecl *method_decl = dyn_cast<ObjCMethodDecl>(D))
{
SynthesizeResult(function_decl);
if (m_ast_context &&
!method_decl->getSelector().getAsString().compare("$__lldb_expr:"))
{
SynthesizeObjCMethodResult(method_decl);
}
}
else if (FunctionDecl *function_decl = dyn_cast<FunctionDecl>(D))
{
if (m_ast_context &&
!function_decl->getNameInfo().getAsString().compare("$__lldb_expr"))
{
SynthesizeFunctionResult(function_decl);
}
}
}
@ -97,15 +119,15 @@ ASTResultSynthesizer::HandleTopLevelDecl(DeclGroupRef D)
}
bool
ASTResultSynthesizer::SynthesizeResult (FunctionDecl *FunDecl)
ASTResultSynthesizer::SynthesizeFunctionResult (FunctionDecl *FunDecl)
{
ASTContext &Ctx(*m_ast_context);
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
ASTContext &Ctx(*m_ast_context);
if (!m_sema)
return false;
FunctionDecl *function_decl = FunDecl;
if (!function_decl)
@ -126,6 +148,80 @@ ASTResultSynthesizer::SynthesizeResult (FunctionDecl *FunDecl)
Stmt *function_body = function_decl->getBody();
CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(function_body);
bool ret = SynthesizeBodyResult (compound_stmt,
function_decl);
if (log)
{
std::string s;
raw_string_ostream os(s);
function_decl->print(os);
os.flush();
log->Printf("Transformed function AST:\n%s", s.c_str());
}
return ret;
}
bool
ASTResultSynthesizer::SynthesizeObjCMethodResult (ObjCMethodDecl *MethodDecl)
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
ASTContext &Ctx(*m_ast_context);
if (!m_sema)
return false;
if (!MethodDecl)
return false;
if (log)
{
std::string s;
raw_string_ostream os(s);
Ctx.getTranslationUnitDecl()->print(os);
os.flush();
log->Printf("AST context before transforming:\n%s", s.c_str());
}
Stmt *method_body = MethodDecl->getBody();
CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(method_body);
bool ret = SynthesizeBodyResult (compound_stmt,
MethodDecl);
if (log)
{
std::string s;
raw_string_ostream os(s);
MethodDecl->print(os);
os.flush();
log->Printf("Transformed function AST:\n%s", s.c_str());
}
return ret;
}
bool
ASTResultSynthesizer::SynthesizeBodyResult (CompoundStmt *Body,
DeclContext *DC)
{
lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
ASTContext &Ctx(*m_ast_context);
CompoundStmt *compound_stmt = dyn_cast<CompoundStmt>(Body);
if (!compound_stmt)
return false;
@ -169,7 +265,7 @@ ASTResultSynthesizer::SynthesizeResult (FunctionDecl *FunDecl)
IdentifierInfo &result_id = Ctx.Idents.get("$__lldb_expr_result");
clang::VarDecl *result_decl = VarDecl::Create(Ctx,
function_decl,
DC,
SourceLocation(),
&result_id,
expr_qual_type,
@ -180,7 +276,7 @@ ASTResultSynthesizer::SynthesizeResult (FunctionDecl *FunDecl)
if (!result_decl)
return false;
function_decl->addDecl(result_decl);
DC->addDecl(result_decl);
///////////////////////////////
// call AddInitializerToDecl
@ -210,18 +306,6 @@ ASTResultSynthesizer::SynthesizeResult (FunctionDecl *FunDecl)
*last_stmt_ptr = reinterpret_cast<Stmt*>(result_initialization_stmt_result.take());
if (log)
{
std::string s;
raw_string_ostream os(s);
function_decl->print(os);
os.flush();
log->Printf("Transformed function AST:\n%s", s.c_str());
}
return true;
}

View File

@ -227,6 +227,14 @@ clang::NamedDecl *NameSearchContext::AddTypeDecl(void *type)
return tag_decl;
}
else if (ObjCObjectType *objc_object_type = dyn_cast<clang::ObjCObjectType>(qual_type))
{
ObjCInterfaceDecl *interface_decl = objc_object_type->getInterface();
m_decls.push_back((NamedDecl*)interface_decl);
return (NamedDecl*)interface_decl;
}
else
{
return NULL;

View File

@ -371,6 +371,7 @@ bool
ClangExpressionDeclMap::GetObjectPointer
(
lldb::addr_t &object_ptr,
ConstString &object_name,
ExecutionContext &exe_ctx,
Error &err
)
@ -389,12 +390,11 @@ ClangExpressionDeclMap::GetObjectPointer
return false;
}
static ConstString g_this_const_str ("this");
Variable *object_ptr_var = FindVariableInScope (*exe_ctx.frame, g_this_const_str, &m_struct_vars->m_object_pointer_type);
Variable *object_ptr_var = FindVariableInScope (*exe_ctx.frame, object_name, &m_struct_vars->m_object_pointer_type);
if (!object_ptr_var)
{
err.SetErrorString("Couldn't find 'this' with appropriate type in scope");
err.SetErrorStringWithFormat("Couldn't find '%s' with appropriate type in scope", object_name.GetCString());
return false;
}
@ -404,7 +404,7 @@ ClangExpressionDeclMap::GetObjectPointer
if (!location_value.get())
{
err.SetErrorString("Couldn't get the location for 'this'");
err.SetErrorStringWithFormat("Couldn't get the location for '%s'", object_name.GetCString());
return false;
}
@ -417,7 +417,7 @@ ClangExpressionDeclMap::GetObjectPointer
if (ClangASTType::GetClangTypeBitWidth(m_struct_vars->m_object_pointer_type.GetASTContext(),
m_struct_vars->m_object_pointer_type.GetOpaqueQualType()) != address_byte_size * 8)
{
err.SetErrorStringWithFormat("'this' is not of an expected pointer size");
err.SetErrorStringWithFormat("'%s' is not of an expected pointer size", object_name.GetCString());
return false;
}
@ -427,7 +427,7 @@ ClangExpressionDeclMap::GetObjectPointer
if (exe_ctx.process->ReadMemory (value_addr, data.GetBytes(), address_byte_size, read_error) != address_byte_size)
{
err.SetErrorStringWithFormat("Coldn't read 'this' from the target: %s", read_error.AsCString());
err.SetErrorStringWithFormat("Coldn't read '%s' from the target: %s", object_name.GetCString(), read_error.AsCString());
return false;
}
@ -441,7 +441,7 @@ ClangExpressionDeclMap::GetObjectPointer
}
else
{
err.SetErrorString("'this' is not in memory; LLDB must be extended to handle registers");
err.SetErrorStringWithFormat("'%s' is not in memory; LLDB must be extended to handle registers", object_name.GetCString());
return false;
}
}
@ -1250,11 +1250,66 @@ ClangExpressionDeclMap::GetDecls (NameSearchContext &context, const ConstString
TypeFromUser class_user_type(pointer_target_type,
this_type->GetClangAST());
if (log)
{
StreamString type_stream;
class_user_type.DumpTypeCode(&type_stream);
type_stream.Flush();
log->Printf("Adding type for $__lldb_class: %s", type_stream.GetString().c_str());
}
AddOneType(context, class_user_type, true);
return;
}
static ConstString g_lldb_objc_class_name ("$__lldb_objc_class");
if (name == g_lldb_objc_class_name)
{
// Clang is looking for the type of "*self"
VariableList *vars = m_parser_vars->m_exe_ctx->frame->GetVariableList(false);
if (!vars)
return;
lldb::VariableSP self_var = vars->FindVariable(ConstString("self"));
if (!self_var)
return;
Type *self_type = self_var->GetType();
if (!self_type)
return;
TypeFromUser self_user_type(self_type->GetClangType(),
self_type->GetClangAST());
m_struct_vars->m_object_pointer_type = self_user_type;
void *pointer_target_type;
if (!ClangASTContext::IsPointerType(self_user_type.GetOpaqueQualType(),
&pointer_target_type))
return;
TypeFromUser class_user_type(pointer_target_type,
self_type->GetClangAST());
if (log)
{
StreamString type_stream;
class_user_type.DumpTypeCode(&type_stream);
type_stream.Flush();
log->Printf("Adding type for $__lldb_objc_class: %s", type_stream.GetString().c_str());
}
AddOneType(context, class_user_type, false);
return;
}
ClangExpressionVariable *pvar(m_parser_vars->m_persistent_vars->GetVariable(name));
if (pvar)

View File

@ -372,7 +372,8 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
Stream &errors,
bool stop_others,
bool discard_on_error,
lldb::addr_t *this_arg)
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg)
{
// FIXME: Use the errors Stream for better error reporting.
@ -388,11 +389,12 @@ ClangFunction::GetThreadPlanToCallFunction (ExecutionContext &exe_ctx,
Address wrapper_address (NULL, func_addr);
ThreadPlan *new_plan = new ThreadPlanCallFunction (*exe_ctx.thread,
wrapper_address,
args_addr,
stop_others,
discard_on_error,
this_arg);
wrapper_address,
args_addr,
stop_others,
discard_on_error,
this_arg,
cmd_arg);
return new_plan;
}

View File

@ -174,6 +174,27 @@ ClangUserExpression::Parse (Stream &error_stream,
m_needs_object_ptr = true;
}
else if(m_objectivec)
{
const char *function_name = FunctionName();
m_transformed_stream.Printf("%s \n"
"@interface $__lldb_objc_class ($__lldb_category) \n"
"-(void)%s:(void *)$__lldb_arg; \n"
"@end \n"
"@implementation $__lldb_objc_class ($__lldb_category) \n"
"-(void)%s:(void *)$__lldb_arg \n"
"{ \n"
" %s; \n"
"} \n"
"@end \n",
m_expr_prefix.c_str(),
function_name,
function_name,
m_expr_text.c_str());
m_needs_object_ptr = true;
}
else
{
m_transformed_stream.Printf("%s \n"
@ -297,14 +318,31 @@ ClangUserExpression::PrepareToExecuteJITExpression (Stream &error_stream,
if (m_jit_addr != LLDB_INVALID_ADDRESS)
{
Error materialize_error;
if (m_needs_object_ptr && !(m_expr_decl_map->GetObjectPointer(object_ptr, exe_ctx, materialize_error)))
if (m_needs_object_ptr)
{
error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
return false;
ConstString object_name;
if (m_cplusplus)
{
object_name.SetCString("this");
}
else if (m_objectivec)
{
object_name.SetCString("self");
}
else
{
error_stream.Printf("Need object pointer but don't know the language\n");
return false;
}
if (!(m_expr_decl_map->GetObjectPointer(object_ptr, object_name, exe_ctx, materialize_error)))
{
error_stream.Printf("Couldn't get required object pointer: %s\n", materialize_error.AsCString());
return false;
}
}
if (!m_expr_decl_map->Materialize(exe_ctx, struct_address, materialize_error))
@ -351,19 +389,22 @@ ClangUserExpression::GetThreadPlanToExecuteJITExpression (Stream &error_stream,
lldb::addr_t struct_address;
lldb::addr_t object_ptr = NULL;
lldb::addr_t cmd_ptr = NULL;
PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr);
// FIXME: This should really return a ThreadPlanCallUserExpression, in order to make sure that we don't release the
// ClangUserExpression resources before the thread plan finishes execution in the target. But because we are
// forcing unwind_on_error to be true here, in practical terms that can't happen.
// forcing unwind_on_error to be true here, in practical terms that can't happen.
return ClangFunction::GetThreadPlanToCallFunction (exe_ctx,
m_jit_addr,
struct_address,
error_stream,
true,
true,
(m_needs_object_ptr ? &object_ptr : NULL));
(m_needs_object_ptr ? &object_ptr : NULL),
(m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL);
}
bool
@ -423,17 +464,24 @@ ClangUserExpression::Execute (Stream &error_stream,
lldb::addr_t struct_address;
lldb::addr_t object_ptr = NULL;
lldb::addr_t cmd_ptr = NULL;
PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr);
if (!PrepareToExecuteJITExpression (error_stream, exe_ctx, struct_address, object_ptr))
return Process::eExecutionSetupError;
const bool stop_others = true;
const bool try_all_threads = true;
Address wrapper_address (NULL, m_jit_addr);
lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (*(exe_ctx.thread), wrapper_address, struct_address,
stop_others, discard_on_error,
(m_needs_object_ptr ? &object_ptr : NULL),
shared_ptr_to_me));
lldb::ThreadPlanSP call_plan_sp(new ThreadPlanCallUserExpression (*(exe_ctx.thread),
wrapper_address,
struct_address,
stop_others,
discard_on_error,
(m_needs_object_ptr ? &object_ptr : NULL),
((m_needs_object_ptr && m_objectivec) ? &cmd_ptr : NULL),
shared_ptr_to_me));
if (call_plan_sp == NULL || !call_plan_sp->ValidatePlan (NULL))
return Process::eExecutionSetupError;

View File

@ -899,7 +899,7 @@ IRForTarget::MaybeHandleVariable (Module &llvm_module, Value *llvm_value_ptr)
size_t value_size = (ast_context->getTypeSize(qual_type) + 7) / 8;
off_t value_alignment = (ast_context->getTypeAlign(qual_type) + 7) / 8;
if (log)
log->Printf("Type of \"%s\" is [clang \"%s\", lldb \"%s\"] [size %d, align %d]",
name.c_str(),
@ -907,7 +907,7 @@ IRForTarget::MaybeHandleVariable (Module &llvm_module, Value *llvm_value_ptr)
PrintType(value_type).c_str(),
value_size,
value_alignment);
if (named_decl && !m_decl_map->AddValueToStruct(named_decl,
lldb_private::ConstString (name.c_str()),
@ -1353,6 +1353,23 @@ IRForTarget::ReplaceVariables (Module &llvm_module, Function &llvm_function)
argument = iter;
}
else if (argument->getName().equals("self"))
{
++iter;
if (iter == llvm_function.getArgumentList().end())
return false;
if (!iter->getName().equals("_cmd"))
return false;
++iter;
if (iter == llvm_function.getArgumentList().end())
return false;
argument = iter;
}
if (!argument->getName().equals("$__lldb_arg"))
return false;
@ -1430,7 +1447,11 @@ IRForTarget::runOnModule (Module &llvm_module)
//
if (!CreateResultVariable(llvm_module, *function))
{
if (log)
log->Printf("CreateResultVariable() failed");
return false;
}
///////////////////////////////////////////////////////////////////////////////
// Fix all Objective-C constant strings to use NSStringWithCString:encoding:
@ -1449,7 +1470,11 @@ IRForTarget::runOnModule (Module &llvm_module)
}
if (!RewriteObjCConstStrings(llvm_module, *function))
{
if (log)
log->Printf("RewriteObjCConstStrings() failed");
return false;
}
if (log)
{
@ -1472,16 +1497,32 @@ IRForTarget::runOnModule (Module &llvm_module)
++bbi)
{
if (!RemoveGuards(llvm_module, *bbi))
{
if (log)
log->Printf("RemoveGuards() failed");
return false;
}
if (!RewritePersistentAllocs(llvm_module, *bbi))
{
if (log)
log->Printf("RewritePersistentAllocs() failed");
return false;
}
if (!RewriteObjCSelectors(llvm_module, *bbi))
{
if (log)
log->Printf("RewriteObjCSelectors() failed");
return false;
}
if (!ResolveCalls(llvm_module, *bbi))
{
if (log)
log->Printf("ResolveCalls() failed");
return false;
}
}
///////////////////////////////
@ -1489,10 +1530,18 @@ IRForTarget::runOnModule (Module &llvm_module)
//
if (!ResolveExternals(llvm_module, *function))
{
if (log)
log->Printf("ResolveExternals() failed");
return false;
}
if (!ReplaceVariables(llvm_module, *function))
{
if (log)
log->Printf("ReplaceVariables() failed");
return false;
}
if (log)
{

View File

@ -58,7 +58,8 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg) const
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const
{
RegisterContext *reg_ctx = thread.GetRegisterContext();
if (!reg_ctx)
@ -73,7 +74,9 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread,
// Make room for the argument(s) on the stack
if (this_arg)
if (this_arg && cmd_arg)
sp -= 12;
else if (this_arg)
sp -= 8;
else
sp -= 4;
@ -86,6 +89,19 @@ ABIMacOSX_i386::PrepareTrivialCall (Thread &thread,
Error error;
if (this_arg && cmd_arg)
{
uint32_t cmd_argU32 = *cmd_arg & 0xffffffffull;
uint32_t this_argU32 = *this_arg & 0xffffffffull;
uint32_t argU32 = arg & 0xffffffffull;
if (thread.GetProcess().WriteMemory(sp, &this_argU32, sizeof(this_argU32), error) != sizeof(this_argU32))
return false;
if (thread.GetProcess().WriteMemory(sp, &cmd_argU32, sizeof(cmd_argU32), error) != sizeof(cmd_argU32))
return false;
if (thread.GetProcess().WriteMemory(sp + 4, &argU32, sizeof(argU32), error) != sizeof(argU32))
return false;
}
if (this_arg)
{
uint32_t this_argU32 = *this_arg & 0xffffffffull;

View File

@ -35,7 +35,8 @@ namespace lldb_private {
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg) const;
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const;
virtual bool
PrepareNormalCall (Thread &thread,

View File

@ -59,18 +59,22 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg) const
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const
{
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
log->Printf("ABISysV_x86_64::PrepareTrivialCall\n(\n thread = %p\n sp = 0x%llx\n functionAddress = 0x%llx\n returnAddress = 0x%llx\n arg = 0x%llx\n this_arg = %p(0x%llx)\n)",
log->Printf("ABISysV_x86_64::PrepareTrivialCall\n(\n thread = %p\n sp = 0x%llx\n functionAddress = 0x%llx\n returnAddress = 0x%llx\n arg = 0x%llx\n this_arg = %p(0x%llx)\n cmd_arg = %p(0x%llx)\n)",
(void*)&thread,
(uint64_t)sp,
(uint64_t)functionAddress,
(uint64_t)returnAddress,
(void*)arg,
this_arg ? (uint64_t)*this_arg : (uint64_t)0);
this_arg,
this_arg ? (uint64_t)*this_arg : (uint64_t)0,
cmd_arg,
cmd_arg ? (uint64_t)*cmd_arg : (uint64_t)0);
RegisterContext *reg_ctx = thread.GetRegisterContext();
if (!reg_ctx)
@ -88,6 +92,31 @@ ABISysV_x86_64::PrepareTrivialCall (Thread &thread,
// The argument is in %rdi, and not on the stack.
if (cmd_arg)
{
if (log)
log->PutCString("The trivial call has a self and a _cmd pointer");
uint32_t rsiID = reg_ctx->GetRegisterInfoByName("rsi", 0)->kinds[eRegisterKindLLDB];
uint32_t rdxID = reg_ctx->GetRegisterInfoByName("rdx", 0)->kinds[eRegisterKindLLDB];
if (log)
log->Printf("About to write 'self' (0x%llx) into RDI", (uint64_t)*this_arg);
if (!reg_ctx->WriteRegisterFromUnsigned(rdiID, *this_arg))
return false;
if (log)
log->Printf("About to write '_cmd' (0x%llx) into RSI", (uint64_t)*cmd_arg);
if (!reg_ctx->WriteRegisterFromUnsigned(rsiID, *this_arg))
return false;
if (log)
log->Printf("About to write the argument (0x%llx) into RDX", (uint64_t)arg);
if (!reg_ctx->WriteRegisterFromUnsigned(rdxID, arg))
return false; }
if (this_arg)
{
if (log)

View File

@ -34,7 +34,8 @@ public:
lldb::addr_t functionAddress,
lldb::addr_t returnAddress,
lldb::addr_t arg,
lldb::addr_t *this_arg) const;
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) const;
virtual bool
PrepareNormalCall (Thread &thread,

View File

@ -928,6 +928,20 @@ ClangASTType::DumpTypeDescription (clang::ASTContext *ast_context, clang_type_t
}
}
void
ClangASTType::DumpTypeCode (Stream *s)
{
DumpTypeCode(m_type, s);
}
void
ClangASTType::DumpTypeCode (void *type,
Stream *s)
{
clang::QualType qual_type(clang::QualType::getFromOpaquePtr(type));
s->PutCString(qual_type.getAsString().c_str());
}
bool
ClangASTType::GetValueAsScalar
(

View File

@ -40,7 +40,8 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
lldb::addr_t arg,
bool stop_other_threads,
bool discard_on_error,
lldb::addr_t *this_arg) :
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg) :
ThreadPlan (ThreadPlan::eKindCallFunction, "Call function plan", thread, eVoteNoOpinion, eVoteNoOpinion),
m_valid (false),
m_stop_other_threads (stop_other_threads),
@ -86,7 +87,8 @@ ThreadPlanCallFunction::ThreadPlanCallFunction (Thread &thread,
FunctionLoadAddr,
StartLoadAddr,
m_arg_addr,
this_arg))
this_arg,
cmd_arg))
return;
LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));

View File

@ -42,8 +42,9 @@ ThreadPlanCallUserExpression::ThreadPlanCallUserExpression (Thread &thread,
bool stop_other_threads,
bool discard_on_error,
lldb::addr_t *this_arg,
lldb::addr_t *cmd_arg,
ClangUserExpression::ClangUserExpressionSP &user_expression_sp) :
ThreadPlanCallFunction (thread, function, arg, stop_other_threads, discard_on_error, this_arg),
ThreadPlanCallFunction (thread, function, arg, stop_other_threads, discard_on_error, this_arg, cmd_arg),
m_user_expression_sp (user_expression_sp)
{
}