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