diff options
21 files changed, 420 insertions, 70 deletions
diff --git a/lldb/include/lldb/Core/ClangForward.h b/lldb/include/lldb/Core/ClangForward.h index c1a9866a11b..4a324dba3e2 100644 --- a/lldb/include/lldb/Core/ClangForward.h +++ b/lldb/include/lldb/Core/ClangForward.h @@ -34,6 +34,7 @@ namespace clang class CodeGenOptions; class CodeGenerator; class CompilerInstance; + class CompoundStmt; class CXXBaseSpecifier; class CXXBoolLiteralExpr; class CXXFunctionalCastExpr; diff --git a/lldb/include/lldb/Expression/ASTResultSynthesizer.h b/lldb/include/lldb/Expression/ASTResultSynthesizer.h index a1976135e2e..9813812de40 100644 --- a/lldb/include/lldb/Expression/ASTResultSynthesizer.h +++ b/lldb/include/lldb/Expression/ASTResultSynthesizer.h @@ -123,12 +123,31 @@ 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. diff --git a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h index e089ab4c68d..e2d59c8f9ce 100644 --- a/lldb/include/lldb/Expression/ClangExpressionDeclMap.h +++ b/lldb/include/lldb/Expression/ClangExpressionDeclMap.h @@ -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); diff --git a/lldb/include/lldb/Expression/ClangFunction.h b/lldb/include/lldb/Expression/ClangFunction.h index 2e1dabe71d0..457721f060a 100644 --- a/lldb/include/lldb/Expression/ClangFunction.h +++ b/lldb/include/lldb/Expression/ClangFunction.h @@ -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. diff --git a/lldb/include/lldb/Symbol/ClangASTType.h b/lldb/include/lldb/Symbol/ClangASTType.h index b28b539cbe6..9807bf33360 100644 --- a/lldb/include/lldb/Symbol/ClangASTType.h +++ b/lldb/include/lldb/Symbol/ClangASTType.h @@ -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); diff --git a/lldb/include/lldb/Target/ABI.h b/lldb/include/lldb/Target/ABI.h index ffce3da0519..7ab92d3457c 100644 --- a/lldb/include/lldb/Target/ABI.h +++ b/lldb/include/lldb/Target/ABI.h @@ -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, diff --git a/lldb/include/lldb/Target/ThreadPlanCallFunction.h b/lldb/include/lldb/Target/ThreadPlanCallFunction.h index 1151dac9a7f..2ef39e65249 100644 --- a/lldb/include/lldb/Target/ThreadPlanCallFunction.h +++ b/lldb/include/lldb/Target/ThreadPlanCallFunction.h @@ -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 (); diff --git a/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h b/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h index 5a0f7407f97..93adfdf17d4 100644 --- a/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h +++ b/lldb/include/lldb/Target/ThreadPlanCallUserExpression.h @@ -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 diff --git a/lldb/source/Expression/ASTResultSynthesizer.cpp b/lldb/source/Expression/ASTResultSynthesizer.cpp index bcabfe3badc..36f78b3120f 100644 --- a/lldb/source/Expression/ASTResultSynthesizer.cpp +++ b/lldb/source/Expression/ASTResultSynthesizer.cpp @@ -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; } diff --git a/lldb/source/Expression/ClangASTSource.cpp b/lldb/source/Expression/ClangASTSource.cpp index 09d6ed08032..34103a6a653 100644 --- a/lldb/source/Expression/ClangASTSource.cpp +++ b/lldb/source/Expression/ClangASTSource.cpp @@ -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; diff --git a/lldb/source/Expression/ClangExpressionDeclMap.cpp b/lldb/source/Expression/ClangExpressionDeclMap.cpp index a93ff17340d..449db416fd2 100644 --- a/lldb/source/Expression/ClangExpressionDeclMap.cpp +++ b/lldb/source/Expression/ClangExpressionDeclMap.cpp @@ -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) diff --git a/lldb/source/Expression/ClangFunction.cpp b/lldb/source/Expression/ClangFunction.cpp index 3dc31ec0b09..3eac429f5c7 100644 --- a/lldb/source/Expression/ClangFunction.cpp +++ b/lldb/source/Expression/ClangFunction.cpp @@ -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; } diff --git a/lldb/source/Expression/ClangUserExpression.cpp b/lldb/source/Expression/ClangUserExpression.cpp index 366b10e6dce..86696661019 100644 --- a/lldb/source/Expression/ClangUserExpression.cpp +++ b/lldb/source/Expression/ClangUserExpression.cpp @@ -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; diff --git a/lldb/source/Expression/IRForTarget.cpp b/lldb/source/Expression/IRForTarget.cpp index 6d730d90bdf..34f146f6936 100644 --- a/lldb/source/Expression/IRForTarget.cpp +++ b/lldb/source/Expression/IRForTarget.cpp @@ -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) { diff --git a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp index e5a5db79477..eb77d332b8f 100644 --- a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp +++ b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.cpp @@ -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; diff --git a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h index 6e5bd77a8df..d4514360393 100644 --- a/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h +++ b/lldb/source/Plugins/ABI/MacOSX-i386/ABIMacOSX_i386.h @@ -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, diff --git a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp index f4045cc119d..32794f31965 100644 --- a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp +++ b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.cpp @@ -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) diff --git a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h index 67b8daf3395..f4e58e4cb2f 100644 --- a/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h +++ b/lldb/source/Plugins/ABI/SysV-x86_64/ABISysV_x86_64.h @@ -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, diff --git a/lldb/source/Symbol/ClangASTType.cpp b/lldb/source/Symbol/ClangASTType.cpp index db2ed981aaa..609ec34c709 100644 --- a/lldb/source/Symbol/ClangASTType.cpp +++ b/lldb/source/Symbol/ClangASTType.cpp @@ -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 ( diff --git a/lldb/source/Target/ThreadPlanCallFunction.cpp b/lldb/source/Target/ThreadPlanCallFunction.cpp index 4407133f1eb..165e63d1189 100644 --- a/lldb/source/Target/ThreadPlanCallFunction.cpp +++ b/lldb/source/Target/ThreadPlanCallFunction.cpp @@ -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)); diff --git a/lldb/source/Target/ThreadPlanCallUserExpression.cpp b/lldb/source/Target/ThreadPlanCallUserExpression.cpp index fd022a26d55..dc27b2be200 100644 --- a/lldb/source/Target/ThreadPlanCallUserExpression.cpp +++ b/lldb/source/Target/ThreadPlanCallUserExpression.cpp @@ -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) { } |