AppleObjCTrampolineHandler.cpp revision 24943d2ee8bfaa7cf5893e4709143924157a5c1e
124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner//===-- ObjCTrampolineHandler.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 1024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "ObjCTrampolineHandler.h" 1124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 1224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C Includes 1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C++ Includes 1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Other libraries and framework includes 1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Project includes 1624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/Module.h" 1724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/ConstString.h" 1824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/FileSpec.h" 1924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/Thread.h" 2024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/RegisterContext.h" 2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/Target.h" 2224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/Process.h" 2324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/Value.h" 2424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Symbol/ClangASTContext.h" 2524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Expression/ClangFunction.h" 2624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/Log.h" 2724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/ExecutionContext.h" 2824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "ThreadPlanStepThroughObjCTrampoline.h" 2924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/ThreadPlanRunToAddress.h" 3024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 3124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb; 3224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb_private; 3324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 3424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerconst ObjCTrampolineHandler::DispatchFunction 3524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerObjCTrampolineHandler::g_dispatch_functions[] = 3624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // NAME STRET SUPER FIXUP TYPE 3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSend", false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSend_fixup", false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpToFix }, 4024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSend_fixedup", false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpFixed }, 4124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSend_stret", true, false, ObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 4224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSend_stret_fixup", true, false, ObjCTrampolineHandler::DispatchFunction::eFixUpToFix }, 4324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSend_stret_fixedup", true, false, ObjCTrampolineHandler::DispatchFunction::eFixUpFixed }, 4424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSend_fpret", false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 4524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSend_fpret_fixup", false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpToFix }, 4624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSend_fpret_fixedup", false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpFixed }, 4724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSend_fp2ret", false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 4824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSend_fp2ret_fixup", false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpToFix }, 4924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSend_fp2ret_fixedup", false, false, ObjCTrampolineHandler::DispatchFunction::eFixUpFixed }, 5024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSendSuper", false, true, ObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 5124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSendSuper_stret", true, true, ObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 5224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSendSuper2", false, true, ObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 5324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSendSuper2_fixup", false, true, ObjCTrampolineHandler::DispatchFunction::eFixUpToFix }, 5424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSendSuper2_fixedup", false, true, ObjCTrampolineHandler::DispatchFunction::eFixUpFixed }, 5524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSendSuper2_stret", true, true, ObjCTrampolineHandler::DispatchFunction::eFixUpNone }, 5624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSendSuper2_stret_fixup", true, true, ObjCTrampolineHandler::DispatchFunction::eFixUpToFix }, 5724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {"objc_msgSendSuper2_stret_fixedup", true, true, ObjCTrampolineHandler::DispatchFunction::eFixUpFixed }, 5824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner {NULL} 5924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}; 6024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 6124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerbool 6224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerObjCTrampolineHandler::ModuleIsObjCLibrary (const ModuleSP &module_sp) 6324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 6424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const FileSpec &module_file_spec = module_sp->GetFileSpec(); 6524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner static ConstString ObjCName ("libobjc.A.dylib"); 6624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 6724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (module_file_spec) 6824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 6924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (module_file_spec.GetFilename() == ObjCName) 7024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return true; 7124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 7224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 7324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return false; 7424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 7524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 7624943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerObjCTrampolineHandler::ObjCTrampolineHandler (ProcessSP process_sp, ModuleSP objc_module) : 7724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_process_sp (process_sp), 7824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_objc_module_sp (objc_module), 7924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_impl_fn_addr (LLDB_INVALID_ADDRESS), 8024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_impl_stret_fn_addr (LLDB_INVALID_ADDRESS) 8124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 8224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Look up the known resolution functions: 8324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 8424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ConstString get_impl_name("class_getMethodImplementation"); 8524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ConstString get_impl_stret_name("class_getMethodImplementation_stret"); 8624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 8724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const Symbol *class_getMethodImplementation = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_name, eSymbolTypeCode); 8824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const Symbol *class_getMethodImplementation_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_stret_name, eSymbolTypeCode); 8924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 9024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (class_getMethodImplementation) 9124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_impl_fn_addr = class_getMethodImplementation->GetValue().GetLoadAddress(m_process_sp.get()); 9224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (class_getMethodImplementation_stret) 9324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_impl_stret_fn_addr = class_getMethodImplementation_stret->GetValue().GetLoadAddress(m_process_sp.get()); 9424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 9524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // FIXME: Do some kind of logging here. 9624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (m_impl_fn_addr == LLDB_INVALID_ADDRESS || m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS) 9724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return; 9824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 9924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Look up the addresses for the objc dispatch functions and cache them. For now I'm inspecting the symbol 10024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // names dynamically to figure out how to dispatch to them. If it becomes more complicated than this we can 10124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // turn the g_dispatch_functions char * array into a template table, and populate the DispatchFunction map 10224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // from there. 10324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 10424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner for (int i = 0; g_dispatch_functions[i].name != NULL; i++) 10524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 10624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ConstString name_const_str(g_dispatch_functions[i].name); 10724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const Symbol *msgSend_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (name_const_str, eSymbolTypeCode); 10824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (msgSend_symbol) 10924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 11024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // FixMe: Make g_dispatch_functions static table of DisptachFunctions, and have the map be address->index. 11124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Problem is we also need to lookup the dispatch function. For now we could have a side table of stret & non-stret 11224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // dispatch functions. If that's as complex as it gets, we're fine. 11324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 11424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner lldb::addr_t sym_addr = msgSend_symbol->GetValue().GetLoadAddress(m_process_sp.get()); 11524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 11624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_msgSend_map.insert(std::pair<lldb::addr_t, int>(sym_addr, i)); 11724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 11824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 11924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 12024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 12124943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerThreadPlanSP 12224943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerObjCTrampolineHandler::GetStepThroughDispatchPlan (Thread &thread, bool stop_others) 12324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 12424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ThreadPlanSP ret_plan_sp; 12524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC(); 12624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 12724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner MsgsendMap::iterator pos; 12824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner pos = m_msgSend_map.find (curr_pc); 12924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (pos != m_msgSend_map.end()) 13024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 13124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 13224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 13324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const DispatchFunction *this_dispatch = &g_dispatch_functions[(*pos).second]; 13424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 13524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0); 13624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 13724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Process *process = thread.CalculateProcess(); 13824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner const ABI *abi = process->GetABI(); 13924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (abi == NULL) 14024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 14124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 14224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Target *target = thread.CalculateTarget(); 14324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 14424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // FIXME: Since neither the value nor the Clang QualType know their ASTContext, 14524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // we have to make sure the type we put in our value list comes from the same ASTContext 14624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // the ABI will use to get the argument values. THis is the bottom-most frame's module. 14724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 14824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ClangASTContext *clang_ast_context = target->GetScratchClangASTContext(); 14924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ValueList argument_values; 15024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Value input_value; 15124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner void *clang_void_ptr_type = clang_ast_context->GetVoidPtrType(false); 15224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner input_value.SetValueType (Value::eValueTypeScalar); 15324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner input_value.SetContext (Value::eContextTypeOpaqueClangQualType, clang_void_ptr_type); 15424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 15524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner int obj_index; 15624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner int sel_index; 15724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 15824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // If this is a struct return dispatch, then the first argument is the 15924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // return struct pointer, and the object is the second, and the selector is the third. 16024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Otherwise the object is the first and the selector the second. 16124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (this_dispatch->stret_return) 16224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 16324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner obj_index = 1; 16424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner sel_index = 2; 16524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner argument_values.PushValue(input_value); 16624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner argument_values.PushValue(input_value); 16724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner argument_values.PushValue(input_value); 16824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 16924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 17024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 17124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner obj_index = 0; 17224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner sel_index = 1; 17324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner argument_values.PushValue(input_value); 17424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner argument_values.PushValue(input_value); 17524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 17624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 17724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 17824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner bool success = abi->GetArgumentValues (thread, argument_values); 17924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (!success) 18024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 18124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 18224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Okay, the first value here is the object, we actually want the class of that object. 18324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // For now we're just going with the ISA. 18424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // FIXME: This should really be the return value of [object class] to properly handle KVO interposition. 18524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 18624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Value isa_value(*(argument_values.GetValueAtIndex(obj_index))); 18724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 18824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // This is a little cheesy, but since object->isa is the first field, 18924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // making the object value a load address value and resolving it will get 19024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // the pointer sized data pointed to by that value... 19124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ExecutionContext exec_ctx; 19224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner thread.Calculate (exec_ctx); 19324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 19424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner isa_value.SetValueType(Value::eValueTypeLoadAddress); 19524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner isa_value.ResolveValue(&exec_ctx, clang_ast_context->getASTContext()); 19624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 19724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (this_dispatch->fixedup == DispatchFunction::eFixUpFixed) 19824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 19924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // For the FixedUp method the Selector is actually a pointer to a 20024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // structure, the second field of which is the selector number. 20124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Value *sel_value = argument_values.GetValueAtIndex(sel_index); 20224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner sel_value->GetScalar() += process->GetAddressByteSize(); 20324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner sel_value->SetValueType(Value::eValueTypeLoadAddress); 20424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner sel_value->ResolveValue(&exec_ctx, clang_ast_context->getASTContext()); 20524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 20624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else if (this_dispatch->fixedup == DispatchFunction::eFixUpToFix) 20724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 20824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // FIXME: If the method dispatch is not "fixed up" then the selector is actually a 20924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // pointer to the string name of the selector. We need to look that up... 21024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // For now I'm going to punt on that and just return no plan. 21124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 21224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf ("Punting on stepping into un-fixed-up method dispatch."); 21324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 21424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 21524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 21624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // FIXME: If this is a dispatch to the super-class, we need to get the super-class from 21724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // the class, and disaptch to that instead. 21824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // But for now I just punt and return no plan. 21924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (this_dispatch->is_super) 22024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 22124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 22224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf ("Punting on stepping into super method dispatch."); 22324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 22424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 22524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 22624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ValueList dispatch_values; 22724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.PushValue (isa_value); 22824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.PushValue(*(argument_values.GetValueAtIndex(sel_index))); 22924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 23024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 23124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 23224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf("Resolving method call for class - 0x%llx and selector - 0x%llx", 23324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.GetValueAtIndex(0)->GetScalar().ULongLong(), 23424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.GetValueAtIndex(1)->GetScalar().ULongLong()); 23524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 23624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 23724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner lldb::addr_t impl_addr = LookupInCache (dispatch_values.GetValueAtIndex(0)->GetScalar().ULongLong(), 23824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.GetValueAtIndex(1)->GetScalar().ULongLong()); 23924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 24024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (impl_addr == LLDB_INVALID_ADDRESS) 24124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 24224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 24324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Address resolve_address(NULL, this_dispatch->stret_return ? m_impl_stret_fn_addr : m_impl_fn_addr); 24424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 24524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner StreamString errors; 24624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 24724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Scope for mutex locker: 24824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Mutex::Locker (m_impl_function_mutex); 24924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (!m_impl_function.get()) 25024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 25124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_impl_function.reset(new ClangFunction(process->GetTargetTriple().GetCString(), 25224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner clang_ast_context, 25324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner clang_void_ptr_type, 25424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner resolve_address, 25524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values)); 25624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 25724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner unsigned num_errors = m_impl_function->CompileFunction(errors); 25824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (num_errors) 25924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 26024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 26124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 26224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf ("Error compiling function: \"%s\".", errors.GetData()); 26324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 26424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 26524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 26624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner errors.Clear(); 26724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (!m_impl_function->WriteFunctionWrapper(exec_ctx, errors)) 26824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 26924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 27024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 27124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf ("Error Inserting function: \"%s\".", errors.GetData()); 27224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 27324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 27424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 27524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 27624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 27724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 27824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner errors.Clear(); 27924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 28024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner // Now write down the argument values for this call. 28124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner lldb::addr_t args_addr = LLDB_INVALID_ADDRESS; 28224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (!m_impl_function->WriteFunctionArguments (exec_ctx, args_addr, resolve_address, dispatch_values, errors)) 28324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 28424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 28524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ret_plan_sp.reset (new ThreadPlanStepThroughObjCTrampoline (thread, this, args_addr, 28624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner argument_values.GetValueAtIndex(0)->GetScalar().ULongLong(), 28724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.GetValueAtIndex(0)->GetScalar().ULongLong(), 28824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner dispatch_values.GetValueAtIndex(1)->GetScalar().ULongLong(), 28924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner stop_others)); 29024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 29124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner else 29224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 29324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 29424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf ("Found implementation address in cache: 0x%llx", impl_addr); 29524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 29624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner ret_plan_sp.reset (new ThreadPlanRunToAddress (thread, impl_addr, stop_others)); 29724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 29824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 29924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 30024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return ret_plan_sp; 30124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 30224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 30324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnervoid 30424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerObjCTrampolineHandler::AddToCache (lldb::addr_t class_addr, lldb::addr_t selector, lldb::addr_t impl_addr) 30524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 30624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP); 30724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (log) 30824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner { 30924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner log->Printf ("Caching: class 0x%llx selector 0x%llx implementation 0x%llx.", class_addr, selector, impl_addr); 31024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner } 31124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner m_impl_cache.insert (std::pair<ClassAndSel,lldb::addr_t> (ClassAndSel(class_addr, selector), impl_addr)); 31224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 31324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 31424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerlldb::addr_t 31524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerObjCTrampolineHandler::LookupInCache (lldb::addr_t class_addr, lldb::addr_t selector) 31624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 31724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner MsgImplMap::iterator pos, end = m_impl_cache.end(); 31824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner pos = m_impl_cache.find (ClassAndSel(class_addr, selector)); 31924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner if (pos != end) 32024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return (*pos).second; 32124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return LLDB_INVALID_ADDRESS; 32224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 32324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner 32424943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerClangFunction * 32524943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerObjCTrampolineHandler::GetLookupImplementationWrapperFunction () 32624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{ 32724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner return m_impl_function.get(); 32824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner} 329