AppleObjCTrampolineHandler.cpp revision b66cd074ec097b5b0a6f2ce292f5072aa1217ca6
1b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham//===-- AppleObjCTrampolineHandler.cpp ----------------------------*- C++ -*-===// 224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// The LLVM Compiler Infrastructure 424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// This file is distributed under the University of Illinois Open Source 624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// License. See LICENSE.TXT for details. 724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// 824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===----------------------------------------------------------------------===// 924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 10b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "AppleObjCTrampolineHandler.h" 1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C Includes 1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C++ Includes 1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Other libraries and framework includes 1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Project includes 16b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "AppleThreadPlanStepThroughObjCTrampoline.h" 17b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham 1824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/ConstString.h" 1924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/FileSpec.h" 20b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Core/Log.h" 21b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Core/Module.h" 2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/Value.h" 2324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Expression/ClangFunction.h" 24b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Symbol/ClangASTContext.h" 25b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/ObjCLanguageRuntime.h" 26b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/Process.h" 27b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/RegisterContext.h" 28b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/Target.h" 29b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/Thread.h" 3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/ExecutionContext.h" 3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/ThreadPlanRunToAddress.h" 3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 3324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb; 3424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb_private; 3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 36b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Inghamconst AppleObjCTrampolineHandler::DispatchFunction 37b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim InghamAppleObjCTrampolineHandler::g_dispatch_functions[] = 3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // NAME STRET SUPER FIXUP TYPE 40b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSend", false, false, AppleObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 41b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSend_fixup", false, false, AppleObjCTrampolineHandler::DispatchFunction::eFixUpToFix }, 42b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSend_fixedup", false, false, AppleObjCTrampolineHandler::DispatchFunction::eFixUpFixed }, 43b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSend_stret", true, false, AppleObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 44b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSend_stret_fixup", true, false, AppleObjCTrampolineHandler::DispatchFunction::eFixUpToFix }, 45b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSend_stret_fixedup", true, false, AppleObjCTrampolineHandler::DispatchFunction::eFixUpFixed }, 46b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSend_fpret", false, false, AppleObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 47b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSend_fpret_fixup", false, false, AppleObjCTrampolineHandler::DispatchFunction::eFixUpToFix }, 48b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSend_fpret_fixedup", false, false, AppleObjCTrampolineHandler::DispatchFunction::eFixUpFixed }, 49b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSend_fp2ret", false, false, AppleObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 50b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSend_fp2ret_fixup", false, false, AppleObjCTrampolineHandler::DispatchFunction::eFixUpToFix }, 51b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSend_fp2ret_fixedup", false, false, AppleObjCTrampolineHandler::DispatchFunction::eFixUpFixed }, 52b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSendSuper", false, true, AppleObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 53b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSendSuper_stret", true, true, AppleObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 54b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSendSuper2", false, true, AppleObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 55b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSendSuper2_fixup", false, true, AppleObjCTrampolineHandler::DispatchFunction::eFixUpToFix }, 56b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSendSuper2_fixedup", false, true, AppleObjCTrampolineHandler::DispatchFunction::eFixUpFixed }, 57b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSendSuper2_stret", true, true, AppleObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 58b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSendSuper2_stret_fixup", true, true, AppleObjCTrampolineHandler::DispatchFunction::eFixUpToFix }, 59b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham {"objc_msgSendSuper2_stret_fixedup", true, true, AppleObjCTrampolineHandler::DispatchFunction::eFixUpFixed }, 6024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {NULL} 6124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}; 6224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 6324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool 64b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim InghamAppleObjCTrampolineHandler::ModuleIsObjCLibrary (const ModuleSP &module_sp) 6524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 6624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const FileSpec &module_file_spec = module_sp->GetFileSpec(); 6724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner static ConstString ObjCName ("libobjc.A.dylib"); 6824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 6924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (module_file_spec) 7024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 7124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (module_file_spec.GetFilename() == ObjCName) 7224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return true; 7324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 7424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 7524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return false; 7624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 7724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 78b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim InghamAppleObjCTrampolineHandler::AppleObjCTrampolineHandler (ProcessSP process_sp, ModuleSP objc_module) : 7924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_process_sp (process_sp), 8024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_objc_module_sp (objc_module), 8124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_impl_fn_addr (LLDB_INVALID_ADDRESS), 8224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_impl_stret_fn_addr (LLDB_INVALID_ADDRESS) 8324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 8424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Look up the known resolution functions: 8524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 8624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ConstString get_impl_name("class_getMethodImplementation"); 8724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ConstString get_impl_stret_name("class_getMethodImplementation_stret"); 8824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 89eea264007bc5fb42c8f3239726a9d28ae42e1b7bGreg Clayton Target *target = m_process_sp ? &m_process_sp->GetTarget() : NULL; 9024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const Symbol *class_getMethodImplementation = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_name, eSymbolTypeCode); 9124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const Symbol *class_getMethodImplementation_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_stret_name, eSymbolTypeCode); 9224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 9324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (class_getMethodImplementation) 94eea264007bc5fb42c8f3239726a9d28ae42e1b7bGreg Clayton m_impl_fn_addr = class_getMethodImplementation->GetValue().GetLoadAddress(target); 9524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (class_getMethodImplementation_stret) 96eea264007bc5fb42c8f3239726a9d28ae42e1b7bGreg Clayton m_impl_stret_fn_addr = class_getMethodImplementation_stret->GetValue().GetLoadAddress(target); 9724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 9824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // FIXME: Do some kind of logging here. 9924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_impl_fn_addr == LLDB_INVALID_ADDRESS || m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS) 10024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return; 10124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 10224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Look up the addresses for the objc dispatch functions and cache them. For now I'm inspecting the symbol 10324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // names dynamically to figure out how to dispatch to them. If it becomes more complicated than this we can 10424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // turn the g_dispatch_functions char * array into a template table, and populate the DispatchFunction map 10524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // from there. 10624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 10724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner for (int i = 0; g_dispatch_functions[i].name != NULL; i++) 10824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 10924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ConstString name_const_str(g_dispatch_functions[i].name); 11024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const Symbol *msgSend_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (name_const_str, eSymbolTypeCode); 11124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (msgSend_symbol) 11224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 11324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // FixMe: Make g_dispatch_functions static table of DisptachFunctions, and have the map be address->index. 11424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Problem is we also need to lookup the dispatch function. For now we could have a side table of stret & non-stret 11524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // dispatch functions. If that's as complex as it gets, we're fine. 11624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 117eea264007bc5fb42c8f3239726a9d28ae42e1b7bGreg Clayton lldb::addr_t sym_addr = msgSend_symbol->GetValue().GetLoadAddress(target); 11824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 11924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_msgSend_map.insert(std::pair<lldb::addr_t, int>(sym_addr, i)); 12024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 12124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 12224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 12324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 12424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerThreadPlanSP 125b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim InghamAppleObjCTrampolineHandler::GetStepThroughDispatchPlan (Thread &thread, bool stop_others) 12624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 12724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ThreadPlanSP ret_plan_sp; 12824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC(); 12924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 13024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner MsgsendMap::iterator pos; 13124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner pos = m_msgSend_map.find (curr_pc); 13224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (pos != m_msgSend_map.end()) 13324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 13424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 13524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 13624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const DispatchFunction *this_dispatch = &g_dispatch_functions[(*pos).second]; 13724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 13824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); 13924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 14024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Process *process = thread.CalculateProcess(); 14124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const ABI *abi = process->GetABI(); 14224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (abi == NULL) 14324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 14424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 14524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Target *target = thread.CalculateTarget(); 14624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 14724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // FIXME: Since neither the value nor the Clang QualType know their ASTContext, 14824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // we have to make sure the type we put in our value list comes from the same ASTContext 14924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // the ABI will use to get the argument values. THis is the bottom-most frame's module. 15024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 15124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ClangASTContext *clang_ast_context = target->GetScratchClangASTContext(); 15224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ValueList argument_values; 15324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Value input_value; 15424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner void *clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false); 15524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner input_value.SetValueType (Value::eValueTypeScalar); 15624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner input_value.SetContext (Value::eContextTypeOpaqueClangQualType, clang_void_ptr_type); 15724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 15824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner int obj_index; 15924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner int sel_index; 16024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 16124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // If this is a struct return dispatch, then the first argument is the 16224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // return struct pointer, and the object is the second, and the selector is the third. 16324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Otherwise the object is the first and the selector the second. 16424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (this_dispatch->stret_return) 16524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 16624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner obj_index = 1; 16724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner sel_index = 2; 16824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner argument_values.PushValue(input_value); 16924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner argument_values.PushValue(input_value); 17024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner argument_values.PushValue(input_value); 17124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 17224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 17324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 17424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner obj_index = 0; 17524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner sel_index = 1; 17624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner argument_values.PushValue(input_value); 17724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner argument_values.PushValue(input_value); 17824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 17924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 18024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 18124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner bool success = abi->GetArgumentValues (thread, argument_values); 18224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (!success) 18324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 18424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 18524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Okay, the first value here is the object, we actually want the class of that object. 18624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // For now we're just going with the ISA. 18724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // FIXME: This should really be the return value of [object class] to properly handle KVO interposition. 18824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 18924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Value isa_value(*(argument_values.GetValueAtIndex(obj_index))); 19024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 19124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // This is a little cheesy, but since object->isa is the first field, 19224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // making the object value a load address value and resolving it will get 19324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // the pointer sized data pointed to by that value... 19424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ExecutionContext exec_ctx; 19524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner thread.Calculate (exec_ctx); 19624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 19724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner isa_value.SetValueType(Value::eValueTypeLoadAddress); 19824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner isa_value.ResolveValue(&exec_ctx, clang_ast_context->getASTContext()); 19924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 20024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (this_dispatch->fixedup == DispatchFunction::eFixUpFixed) 20124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 20224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // For the FixedUp method the Selector is actually a pointer to a 20324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // structure, the second field of which is the selector number. 20424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Value *sel_value = argument_values.GetValueAtIndex(sel_index); 20524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner sel_value->GetScalar() += process->GetAddressByteSize(); 20624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner sel_value->SetValueType(Value::eValueTypeLoadAddress); 20724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner sel_value->ResolveValue(&exec_ctx, clang_ast_context->getASTContext()); 20824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 20924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else if (this_dispatch->fixedup == DispatchFunction::eFixUpToFix) 21024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 21124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // FIXME: If the method dispatch is not "fixed up" then the selector is actually a 21224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // pointer to the string name of the selector. We need to look that up... 21324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // For now I'm going to punt on that and just return no plan. 21424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 21524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf ("Punting on stepping into un-fixed-up method dispatch."); 21624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 21724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 21824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 21924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // FIXME: If this is a dispatch to the super-class, we need to get the super-class from 22024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // the class, and disaptch to that instead. 22124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // But for now I just punt and return no plan. 22224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (this_dispatch->is_super) 22324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 22424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 22524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf ("Punting on stepping into super method dispatch."); 22624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 22724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 22824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 22924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ValueList dispatch_values; 23024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.PushValue (isa_value); 23124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.PushValue(*(argument_values.GetValueAtIndex(sel_index))); 23224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 23324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 23424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 23524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf("Resolving method call for class - 0x%llx and selector - 0x%llx", 23624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.GetValueAtIndex(0)->GetScalar().ULongLong(), 23724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.GetValueAtIndex(1)->GetScalar().ULongLong()); 23824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 239b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham ObjCLanguageRuntime *objc_runtime = m_process_sp->GetObjCLanguageRuntime (); 240b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham assert(objc_runtime != NULL); 241b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham lldb::addr_t impl_addr = objc_runtime->LookupInMethodCache (dispatch_values.GetValueAtIndex(0)->GetScalar().ULongLong(), 24224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.GetValueAtIndex(1)->GetScalar().ULongLong()); 24324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 24424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (impl_addr == LLDB_INVALID_ADDRESS) 24524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 24624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 24724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Address resolve_address(NULL, this_dispatch->stret_return ? m_impl_stret_fn_addr : m_impl_fn_addr); 24824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 24924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner StreamString errors; 25024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 25124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Scope for mutex locker: 252bef1583b89e73de77c8b0897fcf42b5b1fcabe4cGreg Clayton Mutex::Locker locker(m_impl_function_mutex); 25324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (!m_impl_function.get()) 25424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 25524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_impl_function.reset(new ClangFunction(process->GetTargetTriple().GetCString(), 25624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner clang_ast_context, 25724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner clang_void_ptr_type, 25824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner resolve_address, 25924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values)); 26024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 26124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner unsigned num_errors = m_impl_function->CompileFunction(errors); 26224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (num_errors) 26324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 26424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 26524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf ("Error compiling function: \"%s\".", errors.GetData()); 26624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 26724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 26824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 26924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner errors.Clear(); 27024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (!m_impl_function->WriteFunctionWrapper(exec_ctx, errors)) 27124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 27224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 27324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf ("Error Inserting function: \"%s\".", errors.GetData()); 27424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 27524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 27624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 27724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 27824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 27924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 28024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner errors.Clear(); 28124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 28224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Now write down the argument values for this call. 28324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; 28424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (!m_impl_function->WriteFunctionArguments (exec_ctx, args_addr, resolve_address, dispatch_values, errors)) 28524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 28624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 287b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham ret_plan_sp.reset (new AppleThreadPlanStepThroughObjCTrampoline (thread, this, args_addr, 28824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner argument_values.GetValueAtIndex(0)->GetScalar().ULongLong(), 28924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.GetValueAtIndex(0)->GetScalar().ULongLong(), 29024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.GetValueAtIndex(1)->GetScalar().ULongLong(), 29124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner stop_others)); 29224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 29324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 29424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 29524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 29624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf ("Found implementation address in cache: 0x%llx", impl_addr); 29724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 29824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ret_plan_sp.reset (new ThreadPlanRunToAddress (thread, impl_addr, stop_others)); 29924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 30024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 30124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 30224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 30324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 30424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 30524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerClangFunction * 306b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim InghamAppleObjCTrampolineHandler::GetLookupImplementationWrapperFunction () 30724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 30824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return m_impl_function.get(); 30924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 310