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
10d891f9b872103235cfd2ed452c6f14a4394d9b3aDaniel Malea#include "lldb/lldb-python.h"
11d891f9b872103235cfd2ed452c6f14a4394d9b3aDaniel Malea
12b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "AppleObjCTrampolineHandler.h"
1324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C Includes
1524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// C++ Includes
1624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Other libraries and framework includes
1724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner// Project includes
18b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "AppleThreadPlanStepThroughObjCTrampoline.h"
19b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham
204f385f181467701d2c5225f2c954ed5771e0763fJim Ingham#include "lldb/Breakpoint/StoppointCallbackContext.h"
2124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/ConstString.h"
224f385f181467701d2c5225f2c954ed5771e0763fJim Ingham#include "lldb/Core/Debugger.h"
23b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Core/Log.h"
24b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Core/Module.h"
2524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Core/Value.h"
266e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton#include "lldb/Expression/ClangExpression.h"
276e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton#include "lldb/Expression/ClangFunction.h"
286e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton#include "lldb/Expression/ClangUtilityFunction.h"
2973844aa19a7360b662e2be710fc3c969d6c86606Greg Clayton#include "lldb/Host/FileSpec.h"
30b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Symbol/ClangASTContext.h"
3149ce8969d3154e1560106cfe530444c09410f217Greg Clayton#include "lldb/Symbol/Symbol.h"
32b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/ObjCLanguageRuntime.h"
33b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/Process.h"
34b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/RegisterContext.h"
35b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/Target.h"
36b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Ingham#include "lldb/Target/Thread.h"
3724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/ExecutionContext.h"
3824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner#include "lldb/Target/ThreadPlanRunToAddress.h"
3924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
40ce0575750c7180a2fdf06220d0d75c1d7dc9608bDaniel Dunbar#include "llvm/ADT/STLExtras.h"
41ce0575750c7180a2fdf06220d0d75c1d7dc9608bDaniel Dunbar
4224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb;
4324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattnerusing namespace lldb_private;
4424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
456507dd90b5d27662537caee49a3a3cc236f85a53Jim Inghamconst char *AppleObjCTrampolineHandler::g_lookup_implementation_function_name = "__lldb_objc_find_implementation_for_selector";
4612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Inghamconst char *AppleObjCTrampolineHandler::g_lookup_implementation_function_code = NULL;
4712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Inghamconst char *AppleObjCTrampolineHandler::g_lookup_implementation_with_stret_function_code = "                               \n\
486507dd90b5d27662537caee49a3a3cc236f85a53Jim Inghamextern \"C\"                                                                                                    \n\
496507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham{                                                                                                               \n\
506507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    extern void *class_getMethodImplementation(void *objc_class, void *sel);                                    \n\
516507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    extern void *class_getMethodImplementation_stret(void *objc_class, void *sel);                              \n\
526507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    extern void * sel_getUid(char *name);                                                                       \n\
536507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    extern int printf(const char *format, ...);                                                                 \n\
546507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham}                                                                                                               \n\
556507dd90b5d27662537caee49a3a3cc236f85a53Jim Inghamextern \"C\" void * __lldb_objc_find_implementation_for_selector (void *object,                                 \n\
566507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                    void *sel,                                                  \n\
576507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                    int is_stret,                                               \n\
586507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                    int is_super,                                               \n\
596507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                    int is_super2,                                              \n\
606507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                    int is_fixup,                                               \n\
616507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                    int is_fixed,                                               \n\
626507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                    int debug)                                                  \n\
636507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham{                                                                                                               \n\
646507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    struct __lldb_imp_return_struct                                                                             \n\
656507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {                                                                                                           \n\
666507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        void *class_addr;                                                                                       \n\
676507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        void *sel_addr;                                                                                         \n\
686507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        void *impl_addr;                                                                                        \n\
696507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    };                                                                                                          \n\
706507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                                                                                \n\
716507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    struct __lldb_objc_class {                                                                                  \n\
726507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        void *isa;                                                                                              \n\
736507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        void *super_ptr;                                                                                        \n\
746507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    };                                                                                                          \n\
756507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    struct __lldb_objc_super {                                                                                  \n\
766507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        void *reciever;                                                                                         \n\
776507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        struct __lldb_objc_class *class_ptr;                                                                    \n\
786507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    };                                                                                                          \n\
796507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    struct __lldb_msg_ref {                                                                                     \n\
806507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        void *dont_know;                                                                                        \n\
816507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        void *sel;                                                                                              \n\
826507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    };                                                                                                          \n\
836507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                                                                                \n\
846507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    struct __lldb_imp_return_struct return_struct;                                                              \n\
856507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                                                                                \n\
866507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    if (debug)                                                                                                  \n\
876507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \"                          \n\
886507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\",                                               \n\
896507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed);                               \n\
906507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    if (is_super)                                                                                               \n\
916507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {                                                                                                           \n\
926507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        if (is_super2)                                                                                          \n\
936507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        {                                                                                                       \n\
946507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr;                    \n\
956507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        }                                                                                                       \n\
966507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        else                                                                                                    \n\
976507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        {                                                                                                       \n\
986507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr;                               \n\
996507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        }                                                                                                       \n\
1006507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    }                                                                                                           \n\
1016507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    else                                                                                                        \n\
1026507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {                                                                                                           \n\
1036507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        void *class_ptr = (void *) [(id) object class];                                                         \n\
1046507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        if (class_ptr == object)                                                                                \n\
1056507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        {                                                                                                       \n\
1066507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            struct __lldb_objc_class *class_as_class_struct = (struct __lldb_objc_class *) class_ptr;           \n\
1076507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            if (debug)                                                                                          \n\
1086507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                printf (\"Found a class object, need to return the meta class 0x%p -> 0x%p\\n\",                \n\
1096507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                        class_ptr, class_as_class_struct->isa);                                                 \n\
1106507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            return_struct.class_addr = class_as_class_struct->isa;                                              \n\
1116507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        }                                                                                                       \n\
1126507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        else                                                                                                    \n\
1136507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        {                                                                                                       \n\
1146507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            if (debug)                                                                                          \n\
1156507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                printf (\"[object class] returned: 0x%p.\\n\", class_ptr);                                      \n\
1166507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            return_struct.class_addr = class_ptr;                                                               \n\
1176507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        }                                                                                                       \n\
1186507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    }                                                                                                           \n\
1196507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                                                                                \n\
1206507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    if (is_fixup)                                                                                               \n\
1216507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {                                                                                                           \n\
1226507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        if (is_fixed)                                                                                           \n\
1236507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        {                                                                                                       \n\
1246507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel;                                             \n\
1256507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        }                                                                                                       \n\
1266507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        else                                                                                                    \n\
1276507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        {                                                                                                       \n\
1286507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel;                                            \n\
1296507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            return_struct.sel_addr = sel_getUid (sel_name);                                                     \n\
1306507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            if (debug)                                                                                          \n\
1316507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                printf (\"\\n*** Got fixed up selector: 0x%p for name %s.\\n\",                                 \n\
1326507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                        return_struct.sel_addr, sel_name);                                                      \n\
1336507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        }                                                                                                       \n\
1346507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    }                                                                                                           \n\
1356507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    else                                                                                                        \n\
1366507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {                                                                                                           \n\
1376507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        return_struct.sel_addr = sel;                                                                           \n\
1386507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    }                                                                                                           \n\
1396507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                                                                                \n\
1406507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    if (is_stret)                                                                                               \n\
1416507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {                                                                                                           \n\
1426507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        return_struct.impl_addr = class_getMethodImplementation_stret (return_struct.class_addr,                \n\
1436507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                                       return_struct.sel_addr);                 \n\
1446507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    }                                                                                                           \n\
1456507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    else                                                                                                        \n\
1466507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {                                                                                                           \n\
1476507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        return_struct.impl_addr = class_getMethodImplementation (return_struct.class_addr,                      \n\
1486507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                                       return_struct.sel_addr);                 \n\
1496507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    }                                                                                                           \n\
1506507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    if (debug)                                                                                                  \n\
1516507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        printf (\"\\n*** Returning implementation: 0x%p.\\n\", return_struct.impl_addr);                        \n\
1526507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                                                                                                                \n\
1536507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    return return_struct.impl_addr;                                                                             \n\
1546507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham}                                                                                                               \n\
1556507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham";
15612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Inghamconst char *AppleObjCTrampolineHandler::g_lookup_implementation_no_stret_function_code = "                      \n\
15712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Inghamextern \"C\"                                                                                                    \n\
15812f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham{                                                                                                               \n\
15912f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    extern void *class_getMethodImplementation(void *objc_class, void *sel);                                    \n\
16012f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    extern void * sel_getUid(char *name);                                                                       \n\
16112f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    extern int printf(const char *format, ...);                                                                 \n\
16212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham}                                                                                                               \n\
16312f564b9273ec6c53ac118d5d66e4185ae423e8cJim Inghamextern \"C\" void * __lldb_objc_find_implementation_for_selector (void *object,                                 \n\
16412f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                    void *sel,                                                  \n\
16512f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                    int is_stret,                                               \n\
16612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                    int is_super,                                               \n\
16712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                    int is_super2,                                              \n\
16812f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                    int is_fixup,                                               \n\
16912f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                    int is_fixed,                                               \n\
17012f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                    int debug)                                                  \n\
17112f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham{                                                                                                               \n\
17212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    struct __lldb_imp_return_struct                                                                             \n\
17312f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    {                                                                                                           \n\
17412f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        void *class_addr;                                                                                       \n\
17512f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        void *sel_addr;                                                                                         \n\
17612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        void *impl_addr;                                                                                        \n\
17712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    };                                                                                                          \n\
17812f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                                                                                \n\
17912f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    struct __lldb_objc_class {                                                                                  \n\
18012f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        void *isa;                                                                                              \n\
18112f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        void *super_ptr;                                                                                        \n\
18212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    };                                                                                                          \n\
18312f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    struct __lldb_objc_super {                                                                                  \n\
18412f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        void *reciever;                                                                                         \n\
18512f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        struct __lldb_objc_class *class_ptr;                                                                    \n\
18612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    };                                                                                                          \n\
18712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    struct __lldb_msg_ref {                                                                                     \n\
18812f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        void *dont_know;                                                                                        \n\
18912f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        void *sel;                                                                                              \n\
19012f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    };                                                                                                          \n\
19112f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                                                                                \n\
19212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    struct __lldb_imp_return_struct return_struct;                                                              \n\
19312f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                                                                                \n\
19412f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    if (debug)                                                                                                  \n\
19512f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \"                          \n\
19612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\",                                               \n\
19712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                 object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed);                               \n\
19812f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    if (is_super)                                                                                               \n\
19912f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    {                                                                                                           \n\
20012f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        if (is_super2)                                                                                          \n\
20112f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        {                                                                                                       \n\
20212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr;                    \n\
20312f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        }                                                                                                       \n\
20412f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        else                                                                                                    \n\
20512f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        {                                                                                                       \n\
20612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr;                               \n\
20712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        }                                                                                                       \n\
20812f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    }                                                                                                           \n\
20912f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    else                                                                                                        \n\
21012f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    {                                                                                                           \n\
21112f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        void *class_ptr = (void *) [(id) object class];                                                         \n\
21212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        if (class_ptr == object)                                                                                \n\
21312f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        {                                                                                                       \n\
21412f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            struct __lldb_objc_class *class_as_class_struct = (struct __lldb_objc_class *) class_ptr;           \n\
21512f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            if (debug)                                                                                          \n\
21612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                printf (\"Found a class object, need to return the meta class 0x%p -> 0x%p\\n\",                \n\
21712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                        class_ptr, class_as_class_struct->isa);                                                 \n\
21812f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            return_struct.class_addr = class_as_class_struct->isa;                                              \n\
21912f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        }                                                                                                       \n\
22012f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        else                                                                                                    \n\
22112f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        {                                                                                                       \n\
22212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            if (debug)                                                                                          \n\
22312f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                printf (\"[object class] returned: 0x%p.\\n\", class_ptr);                                      \n\
22412f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            return_struct.class_addr = class_ptr;                                                               \n\
22512f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        }                                                                                                       \n\
22612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    }                                                                                                           \n\
22712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                                                                                \n\
22812f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    if (is_fixup)                                                                                               \n\
22912f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    {                                                                                                           \n\
23012f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        if (is_fixed)                                                                                           \n\
23112f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        {                                                                                                       \n\
23212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel;                                             \n\
23312f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        }                                                                                                       \n\
23412f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        else                                                                                                    \n\
23512f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        {                                                                                                       \n\
23612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel;                                            \n\
23712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            return_struct.sel_addr = sel_getUid (sel_name);                                                     \n\
23812f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            if (debug)                                                                                          \n\
23912f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                printf (\"\\n*** Got fixed up selector: 0x%p for name %s.\\n\",                                 \n\
24012f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                        return_struct.sel_addr, sel_name);                                                      \n\
24112f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        }                                                                                                       \n\
24212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    }                                                                                                           \n\
24312f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    else                                                                                                        \n\
24412f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    {                                                                                                           \n\
24512f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        return_struct.sel_addr = sel;                                                                           \n\
24612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    }                                                                                                           \n\
24712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                                                                                \n\
24812f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    return_struct.impl_addr = class_getMethodImplementation (return_struct.class_addr,                          \n\
24912f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                             return_struct.sel_addr);                           \n\
25012f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    if (debug)                                                                                                  \n\
25112f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        printf (\"\\n*** Returning implementation: 0x%p.\\n\", return_struct.impl_addr);                        \n\
25212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                                                                                \n\
25312f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    return return_struct.impl_addr;                                                                             \n\
25412f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham}                                                                                                               \n\
25512f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham";
2566507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham
2574f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr) :
2584f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    m_valid (true),
2594f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    m_owner(owner),
2604f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    m_header_addr (header_addr),
2614f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    m_code_start_addr(0),
2624f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    m_code_end_addr (0),
2634f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    m_next_region (0)
2644f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{
2654f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    SetUpRegion ();
2664f385f181467701d2c5225f2c954ed5771e0763fJim Ingham}
2674f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
2686e0101c86555a06b3bd4cb6104b35abfae0b0057Greg ClaytonAppleObjCTrampolineHandler::~AppleObjCTrampolineHandler()
2696e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton{
2706e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton}
2716e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton
2724f385f181467701d2c5225f2c954ed5771e0763fJim Inghamvoid
2734f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion()
2744f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{
2754f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // The header looks like:
2764f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    //
2774f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    //   uint16_t headerSize
2784f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    //   uint16_t descSize
2794f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    //   uint32_t descCount
2804f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    //   void * next
2814f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    //
2824f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // First read in the header:
2834f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
2844f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    char memory_buffer[16];
2854f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    Process *process = m_owner->GetProcess();
2864f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    DataExtractor data(memory_buffer, sizeof(memory_buffer),
2874f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                       process->GetByteOrder(),
2884f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                       process->GetAddressByteSize());
2894f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    size_t actual_size = 8 + process->GetAddressByteSize();
2904f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    Error error;
2914f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    size_t bytes_read = process->ReadMemory (m_header_addr, memory_buffer, actual_size, error);
2924f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (bytes_read != actual_size)
2934f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    {
2944f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        m_valid = false;
2954f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        return;
2964f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    }
2974f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
29836da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton    lldb::offset_t offset = 0;
29936da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton    const uint16_t header_size = data.GetU16(&offset);
30036da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton    const uint16_t descriptor_size = data.GetU16(&offset);
30136da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton    const size_t num_descriptors = data.GetU32(&offset);
3024f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
30336da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton    m_next_region = data.GetPointer(&offset);
3044f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
3054f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // If the header size is 0, that means we've come in too early before this data is set up.
3064f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // Set ourselves as not valid, and continue.
3076916e358c9725b75ed91f31236c147f26c9af10eGreg Clayton    if (header_size == 0 || num_descriptors == 0)
3084f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    {
3094f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        m_valid = false;
3104f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        return;
3114f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    }
3124f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
3134f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // Now read in all the descriptors:
3144f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // The descriptor looks like:
3154f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    //
3164f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // uint32_t offset
3174f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // uint32_t flags
3184f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    //
3194f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // Where offset is either 0 - in which case it is unused, or
3204f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // it is the offset of the vtable code from the beginning of the descriptor record.
3214f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // Below, we'll convert that into an absolute code address, since I don't want to have
3224f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // to compute it over and over.
3234f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
3244f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // Ingest the whole descriptor array:
3256916e358c9725b75ed91f31236c147f26c9af10eGreg Clayton    const lldb::addr_t desc_ptr = m_header_addr + header_size;
3266916e358c9725b75ed91f31236c147f26c9af10eGreg Clayton    const size_t desc_array_size = num_descriptors * descriptor_size;
3274f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    DataBufferSP data_sp(new DataBufferHeap (desc_array_size, '\0'));
3284f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    uint8_t* dst = (uint8_t*)data_sp->GetBytes();
3294f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
3304f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    DataExtractor desc_extractor (dst, desc_array_size,
3314f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                                  process->GetByteOrder(),
3324f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                                  process->GetAddressByteSize());
3334f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    bytes_read = process->ReadMemory(desc_ptr, dst, desc_array_size, error);
3344f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (bytes_read != desc_array_size)
3354f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    {
3364f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        m_valid = false;
3374f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        return;
3384f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    }
3394f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
3404f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // The actual code for the vtables will be laid out consecutively, so I also
3414f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // compute the start and end of the whole code block.
3424f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
34336da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton    offset = 0;
3444f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    m_code_start_addr = 0;
3454f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    m_code_end_addr = 0;
3464f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
3473e11c7ec050648ba865f1d451f8cb46fd39072a8Andy Gibbs    for (size_t i = 0; i < num_descriptors; i++)
3484f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    {
34936da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton        lldb::addr_t start_offset = offset;
35036da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton        uint32_t voffset = desc_extractor.GetU32 (&offset);
35136da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton        uint32_t flags  = desc_extractor.GetU32 (&offset);
35236da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton        lldb::addr_t code_addr = desc_ptr + start_offset + voffset;
3534f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        m_descriptors.push_back (VTableDescriptor(flags, code_addr));
3544f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
3554f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        if (m_code_start_addr == 0 || code_addr < m_code_start_addr)
3564f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            m_code_start_addr = code_addr;
3574f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        if (code_addr > m_code_end_addr)
3584f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            m_code_end_addr = code_addr;
3594f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
36036da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton        offset = start_offset + descriptor_size;
3614f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    }
3624f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // Finally, a little bird told me that all the vtable code blocks are the same size.
3634f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // Let's compute the blocks and if they are all the same add the size to the code end address:
3644f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    lldb::addr_t code_size = 0;
3654f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    bool all_the_same = true;
3663e11c7ec050648ba865f1d451f8cb46fd39072a8Andy Gibbs    for (size_t i = 0; i < num_descriptors - 1; i++)
3674f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    {
3684f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        lldb::addr_t this_size = m_descriptors[i + 1].code_start - m_descriptors[i].code_start;
3694f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        if (code_size == 0)
3704f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            code_size = this_size;
3714f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        else
3724f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        {
3734f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            if (this_size != code_size)
3744f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                all_the_same = false;
3754f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            if (this_size > code_size)
3764f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                code_size = this_size;
3774f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        }
3784f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    }
3794f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (all_the_same)
3804f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        m_code_end_addr += code_size;
3814f385f181467701d2c5225f2c954ed5771e0763fJim Ingham}
3824f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
3834f385f181467701d2c5225f2c954ed5771e0763fJim Inghambool
3844f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::AddressInRegion (lldb::addr_t addr, uint32_t &flags)
3854f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{
3864f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (!IsValid())
3874f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        return false;
3884f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
3894f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (addr < m_code_start_addr || addr > m_code_end_addr)
3904f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        return false;
3914f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
3924f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    std::vector<VTableDescriptor>::iterator pos, end = m_descriptors.end();
3934f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    for (pos = m_descriptors.begin(); pos != end; pos++)
3944f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    {
3954f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        if (addr <= (*pos).code_start)
3964f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        {
3974f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            flags = (*pos).flags;
3984f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            return true;
3994f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        }
4004f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    }
4014f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    return false;
4024f385f181467701d2c5225f2c954ed5771e0763fJim Ingham}
4034f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
4044f385f181467701d2c5225f2c954ed5771e0763fJim Inghamvoid
4054f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::Dump (Stream &s)
4064f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{
4075f35a4be95aed0e5b2cb36f7d785bcbfc67284aeDaniel Malea    s.Printf ("Header addr: 0x%" PRIx64 " Code start: 0x%" PRIx64 " Code End: 0x%" PRIx64 " Next: 0x%" PRIx64 "\n",
4084f385f181467701d2c5225f2c954ed5771e0763fJim Ingham              m_header_addr, m_code_start_addr, m_code_end_addr, m_next_region);
4094f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    size_t num_elements = m_descriptors.size();
4104f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    for (size_t i = 0; i < num_elements; i++)
4114f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    {
4124f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        s.Indent();
4135f35a4be95aed0e5b2cb36f7d785bcbfc67284aeDaniel Malea        s.Printf ("Code start: 0x%" PRIx64 " Flags: %d\n", m_descriptors[i].code_start, m_descriptors[i].flags);
4144f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    }
4154f385f181467701d2c5225f2c954ed5771e0763fJim Ingham}
4164f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
4176e0101c86555a06b3bd4cb6104b35abfae0b0057Greg ClaytonAppleObjCTrampolineHandler::AppleObjCVTables::AppleObjCVTables (const ProcessSP &process_sp,
4186e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton                                                                const ModuleSP &objc_module_sp) :
4196e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton    m_process_sp (process_sp),
4206e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton    m_trampoline_header (LLDB_INVALID_ADDRESS),
4216e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton    m_trampolines_changed_bp_id (LLDB_INVALID_BREAK_ID),
4226e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton    m_objc_module_sp (objc_module_sp)
4234f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{
4244f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
4254f385f181467701d2c5225f2c954ed5771e0763fJim Ingham}
4264f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
4274f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::~AppleObjCVTables()
4284f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{
4294f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (m_trampolines_changed_bp_id != LLDB_INVALID_BREAK_ID)
4304f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        m_process_sp->GetTarget().RemoveBreakpointByID (m_trampolines_changed_bp_id);
4314f385f181467701d2c5225f2c954ed5771e0763fJim Ingham}
4324f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
4334f385f181467701d2c5225f2c954ed5771e0763fJim Inghambool
4344f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols ()
4354f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{
4364f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (m_trampoline_header != LLDB_INVALID_ADDRESS)
4374f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        return true;
4384f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    Target &target = m_process_sp->GetTarget();
4394f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
440146d9522c95c0c8c5409539813b55e08b99196eeEnrico Granata    const ModuleList &target_modules = target.GetImages();
4419336790a758b8f8b87d95e6658bb8fdb34766c2fJim Ingham    Mutex::Locker modules_locker(target_modules.GetMutex());
4429336790a758b8f8b87d95e6658bb8fdb34766c2fJim Ingham    size_t num_modules = target_modules.GetSize();
4434f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (!m_objc_module_sp)
4444f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    {
4454f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        for (size_t i = 0; i < num_modules; i++)
4464f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        {
4479336790a758b8f8b87d95e6658bb8fdb34766c2fJim Ingham            if (m_process_sp->GetObjCLanguageRuntime()->IsModuleObjCLibrary (target_modules.GetModuleAtIndexUnlocked(i)))
4484f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            {
4499336790a758b8f8b87d95e6658bb8fdb34766c2fJim Ingham                m_objc_module_sp = target_modules.GetModuleAtIndexUnlocked(i);
4504f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                break;
4514f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            }
4524f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        }
4534f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    }
4544f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
4554f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (m_objc_module_sp)
4564f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    {
4574f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        ConstString trampoline_name ("gdb_objc_trampolines");
458c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton        const Symbol *trampoline_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (trampoline_name,
459c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton                                                                                            eSymbolTypeData);
4604f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        if (trampoline_symbol != NULL)
4614f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        {
4620c31d3d3a4a1d00d53346d8a23b0519f47e55d1fGreg Clayton            if (!trampoline_symbol->GetAddress().IsValid())
4634f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                return false;
4644f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
4650c31d3d3a4a1d00d53346d8a23b0519f47e55d1fGreg Clayton            m_trampoline_header = trampoline_symbol->GetAddress().GetLoadAddress(&target);
4664f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            if (m_trampoline_header == LLDB_INVALID_ADDRESS)
4674f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                return false;
4684f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
4694f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            // Next look up the "changed" symbol and set a breakpoint on that...
4704f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            ConstString changed_name ("gdb_objc_trampolines_changed");
471c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton            const Symbol *changed_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (changed_name,
472c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton                                                                                             eSymbolTypeCode);
4734f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            if (changed_symbol != NULL)
4744f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            {
4750c31d3d3a4a1d00d53346d8a23b0519f47e55d1fGreg Clayton                if (!changed_symbol->GetAddress().IsValid())
4764f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                    return false;
4774f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
4780c31d3d3a4a1d00d53346d8a23b0519f47e55d1fGreg Clayton                lldb::addr_t changed_addr = changed_symbol->GetAddress().GetOpcodeLoadAddress (&target);
4794f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                if (changed_addr != LLDB_INVALID_ADDRESS)
4804f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                {
481c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton                    BreakpointSP trampolines_changed_bp_sp = target.CreateBreakpoint (changed_addr, true);
482987c7ebe1daa425ba7abfa9643800e3237146fc0Greg Clayton                    if (trampolines_changed_bp_sp)
4834f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                    {
4844f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                        m_trampolines_changed_bp_id = trampolines_changed_bp_sp->GetID();
4854f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                        trampolines_changed_bp_sp->SetCallback (RefreshTrampolines, this, true);
486090f83176695d86197b0e86b67dee4160ec5003dJim Ingham                        trampolines_changed_bp_sp->SetBreakpointKind ("objc-trampolines-changed");
4874f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                        return true;
4884f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                    }
4894f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                }
4904f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            }
4914f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        }
4924f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    }
4934f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
4944f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    return false;
4954f385f181467701d2c5225f2c954ed5771e0763fJim Ingham}
4964f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
4974f385f181467701d2c5225f2c954ed5771e0763fJim Inghambool
4984f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines (void *baton,
4992f085c6ca2895663687dca704589478ff040b849Greg Clayton                                                                  StoppointCallbackContext *context,
5002f085c6ca2895663687dca704589478ff040b849Greg Clayton                                                                  lldb::user_id_t break_id,
5012f085c6ca2895663687dca704589478ff040b849Greg Clayton                                                                  lldb::user_id_t break_loc_id)
5024f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{
5034f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    AppleObjCVTables *vtable_handler = (AppleObjCVTables *) baton;
5044f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (vtable_handler->InitializeVTableSymbols())
5054f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    {
5064f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        // The Update function is called with the address of an added region.  So we grab that address, and
5074f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        // feed it into ReadRegions.  Of course, our friend the ABI will get the values for us.
508f4124deeb9532044a38c0774ced872f2709347daGreg Clayton        ExecutionContext exe_ctx (context->exe_ctx_ref);
509f4124deeb9532044a38c0774ced872f2709347daGreg Clayton        Process *process = exe_ctx.GetProcessPtr();
51075906e4ec98af3717e415727a8d663a4e246bb4fGreg Clayton        const ABI *abi = process->GetABI().get();
5114f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
5124f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
5134f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        ValueList argument_values;
5144f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        Value input_value;
51552f792329be5db8e38961350589e97e8f2823acdGreg Clayton        ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
51652f792329be5db8e38961350589e97e8f2823acdGreg Clayton
5174f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        input_value.SetValueType (Value::eValueTypeScalar);
51852f792329be5db8e38961350589e97e8f2823acdGreg Clayton        //input_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
51952f792329be5db8e38961350589e97e8f2823acdGreg Clayton        input_value.SetClangType (clang_void_ptr_type);
5204f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        argument_values.PushValue(input_value);
5214f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
522f4124deeb9532044a38c0774ced872f2709347daGreg Clayton        bool success = abi->GetArgumentValues (exe_ctx.GetThreadRef(), argument_values);
5234f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        if (!success)
5244f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            return false;
5254f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
5264f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        // Now get a pointer value from the zeroth argument.
5274f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        Error error;
5284f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        DataExtractor data;
529f4124deeb9532044a38c0774ced872f2709347daGreg Clayton        error = argument_values.GetValueAtIndex(0)->GetValueAsData (&exe_ctx,
530801417e453f8531ac176cd952200587bf15d9ccfGreg Clayton                                                                    data,
531801417e453f8531ac176cd952200587bf15d9ccfGreg Clayton                                                                    0,
532801417e453f8531ac176cd952200587bf15d9ccfGreg Clayton                                                                    NULL);
53336da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton        lldb::offset_t offset = 0;
53436da2aa6dc5ad9994b638ed09eb81c44cc05540bGreg Clayton        lldb::addr_t region_addr = data.GetPointer(&offset);
5354f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
5364f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        if (region_addr != 0)
5374f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            vtable_handler->ReadRegions(region_addr);
5384f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    }
5394f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    return false;
5404f385f181467701d2c5225f2c954ed5771e0763fJim Ingham}
5414f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
5424f385f181467701d2c5225f2c954ed5771e0763fJim Inghambool
5434f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions ()
5444f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{
5454f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // The no argument version reads the start region from the value of the gdb_regions_header, and
5464f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // gets started from there.
5474f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
5484f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    m_regions.clear();
5494f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (!InitializeVTableSymbols())
5504f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        return false;
5514f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    Error error;
552c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton    lldb::addr_t region_addr = m_process_sp->ReadPointerFromMemory (m_trampoline_header, error);
553c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton    if (error.Success())
554c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton        return ReadRegions (region_addr);
555c0fa53324d62a48257c092a3347d6e7236aa3152Greg Clayton    return false;
5564f385f181467701d2c5225f2c954ed5771e0763fJim Ingham}
5574f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
5584f385f181467701d2c5225f2c954ed5771e0763fJim Inghambool
5594f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions (lldb::addr_t region_addr)
5604f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{
5614f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (!m_process_sp)
5624f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        return false;
5634f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
564952e9dc874944fcdbbb224f3ec4fc2c859376f64Greg Clayton    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
5654f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
5664f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // We aren't starting at the trampoline symbol.
5674f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    InitializeVTableSymbols ();
5684f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    lldb::addr_t next_region = region_addr;
5694f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
5704f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // Read in the sizes of the headers.
5714f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    while (next_region != 0)
5724f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    {
5734f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        m_regions.push_back (VTableRegion(this, next_region));
5744f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        if (!m_regions.back().IsValid())
5754f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        {
5764f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            m_regions.clear();
5774f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            return false;
5784f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        }
5794f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        if (log)
5804f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        {
5814f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            StreamString s;
5824f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            m_regions.back().Dump(s);
5834f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            log->Printf("Read vtable region: \n%s", s.GetData());
5844f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        }
5854f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
5864f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        next_region = m_regions.back().GetNextRegionAddr();
5874f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    }
5884f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
5894f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    return true;
5904f385f181467701d2c5225f2c954ed5771e0763fJim Ingham}
5914f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
5924f385f181467701d2c5225f2c954ed5771e0763fJim Inghambool
5934f385f181467701d2c5225f2c954ed5771e0763fJim InghamAppleObjCTrampolineHandler::AppleObjCVTables::IsAddressInVTables (lldb::addr_t addr, uint32_t &flags)
5944f385f181467701d2c5225f2c954ed5771e0763fJim Ingham{
5954f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    region_collection::iterator pos, end = m_regions.end();
5964f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    for (pos = m_regions.begin(); pos != end; pos++)
5974f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    {
5984f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        if ((*pos).AddressInRegion (addr, flags))
5994f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            return true;
6004f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    }
6014f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    return false;
6024f385f181467701d2c5225f2c954ed5771e0763fJim Ingham}
6034f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
604b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim Inghamconst AppleObjCTrampolineHandler::DispatchFunction
605b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim InghamAppleObjCTrampolineHandler::g_dispatch_functions[] =
60624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
6076507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    // NAME                              STRET  SUPER  SUPER2  FIXUP TYPE
6086507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSend",                     false, false, false, DispatchFunction::eFixUpNone    },
6096507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSend_fixup",               false, false, false, DispatchFunction::eFixUpToFix   },
6106507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSend_fixedup",             false, false, false, DispatchFunction::eFixUpFixed   },
6116507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSend_stret",               true,  false, false, DispatchFunction::eFixUpNone    },
6126507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSend_stret_fixup",         true,  false, false, DispatchFunction::eFixUpToFix   },
6136507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSend_stret_fixedup",       true,  false, false, DispatchFunction::eFixUpFixed   },
6146507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSend_fpret",               false, false, false, DispatchFunction::eFixUpNone    },
6156507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSend_fpret_fixup",         false, false, false, DispatchFunction::eFixUpToFix   },
6166507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSend_fpret_fixedup",       false, false, false, DispatchFunction::eFixUpFixed   },
6176507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSend_fp2ret",              false, false,  true, DispatchFunction::eFixUpNone    },
6186507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSend_fp2ret_fixup",        false, false,  true, DispatchFunction::eFixUpToFix   },
6196507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSend_fp2ret_fixedup",      false, false,  true, DispatchFunction::eFixUpFixed   },
6206507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSendSuper",                false, true,  false, DispatchFunction::eFixUpNone    },
6216507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSendSuper_stret",          true,  true,  false, DispatchFunction::eFixUpNone    },
6226507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSendSuper2",               false, true,   true, DispatchFunction::eFixUpNone    },
6236507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSendSuper2_fixup",         false, true,   true, DispatchFunction::eFixUpToFix   },
6246507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSendSuper2_fixedup",       false, true,   true, DispatchFunction::eFixUpFixed   },
6256507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSendSuper2_stret",         true,  true,   true, DispatchFunction::eFixUpNone    },
6266507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSendSuper2_stret_fixup",   true,  true,   true, DispatchFunction::eFixUpToFix   },
6276507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    {"objc_msgSendSuper2_stret_fixedup", true,  true,   true, DispatchFunction::eFixUpFixed   },
62824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner};
62924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
6306e0101c86555a06b3bd4cb6104b35abfae0b0057Greg ClaytonAppleObjCTrampolineHandler::AppleObjCTrampolineHandler (const ProcessSP &process_sp,
6316e0101c86555a06b3bd4cb6104b35abfae0b0057Greg Clayton                                                        const ModuleSP &objc_module_sp) :
63224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_process_sp (process_sp),
6334f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    m_objc_module_sp (objc_module_sp),
63424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    m_impl_fn_addr (LLDB_INVALID_ADDRESS),
6356507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    m_impl_stret_fn_addr (LLDB_INVALID_ADDRESS),
6366507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    m_msg_forward_addr (LLDB_INVALID_ADDRESS)
63724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
63824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Look up the known resolution functions:
63924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
64024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ConstString get_impl_name("class_getMethodImplementation");
64124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ConstString get_impl_stret_name("class_getMethodImplementation_stret");
6426507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    ConstString msg_forward_name("_objc_msgForward");
6436507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    ConstString msg_forward_stret_name("_objc_msgForward_stret");
64424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
645eea264007bc5fb42c8f3239726a9d28ae42e1b7bGreg Clayton    Target *target = m_process_sp ? &m_process_sp->GetTarget() : NULL;
64624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const Symbol *class_getMethodImplementation = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_name, eSymbolTypeCode);
64724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    const Symbol *class_getMethodImplementation_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_stret_name, eSymbolTypeCode);
6486507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    const Symbol *msg_forward = m_objc_module_sp->FindFirstSymbolWithNameAndType (msg_forward_name, eSymbolTypeCode);
6496507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    const Symbol *msg_forward_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (msg_forward_stret_name, eSymbolTypeCode);
65024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
65124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (class_getMethodImplementation)
6520c31d3d3a4a1d00d53346d8a23b0519f47e55d1fGreg Clayton        m_impl_fn_addr = class_getMethodImplementation->GetAddress().GetOpcodeLoadAddress (target);
65324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if  (class_getMethodImplementation_stret)
6540c31d3d3a4a1d00d53346d8a23b0519f47e55d1fGreg Clayton        m_impl_stret_fn_addr = class_getMethodImplementation_stret->GetAddress().GetOpcodeLoadAddress (target);
6556507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    if (msg_forward)
6560c31d3d3a4a1d00d53346d8a23b0519f47e55d1fGreg Clayton        m_msg_forward_addr = msg_forward->GetAddress().GetOpcodeLoadAddress(target);
6576507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    if  (msg_forward_stret)
6580c31d3d3a4a1d00d53346d8a23b0519f47e55d1fGreg Clayton        m_msg_forward_stret_addr = msg_forward_stret->GetAddress().GetOpcodeLoadAddress(target);
65924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
66024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // FIXME: Do some kind of logging here.
66112f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    if (m_impl_fn_addr == LLDB_INVALID_ADDRESS)
66212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    {
66312f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        // If we can't even find the ordinary get method implementation function, then we aren't going to be able to
66412f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        // step through any method dispatches.  Warn to that effect and get out of here.
665ba065cab7acc8ef7fbedc27af5d18c3a694a084aJason Molenda        if (process_sp->CanJIT())
666ba065cab7acc8ef7fbedc27af5d18c3a694a084aJason Molenda        {
667ba065cab7acc8ef7fbedc27af5d18c3a694a084aJason Molenda            process_sp->GetTarget().GetDebugger().GetErrorStream().Printf("Could not find implementation lookup function \"%s\""
668ba065cab7acc8ef7fbedc27af5d18c3a694a084aJason Molenda                                                                          " step in through ObjC method dispatch will not work.\n",
669ba065cab7acc8ef7fbedc27af5d18c3a694a084aJason Molenda                                                                          get_impl_name.AsCString());
670ba065cab7acc8ef7fbedc27af5d18c3a694a084aJason Molenda        }
67124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        return;
67212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    }
67312f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    else if (m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS)
67412f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    {
67512f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        // It there is no stret return lookup function, assume that it is the same as the straight lookup:
67612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        m_impl_stret_fn_addr = m_impl_fn_addr;
67712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        // Also we will use the version of the lookup code that doesn't rely on the stret version of the function.
67812f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        g_lookup_implementation_function_code = g_lookup_implementation_no_stret_function_code;
67912f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    }
68012f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    else
68112f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    {
68212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham        g_lookup_implementation_function_code = g_lookup_implementation_with_stret_function_code;
68312f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham    }
68424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
68524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // Look up the addresses for the objc dispatch functions and cache them.  For now I'm inspecting the symbol
68624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // names dynamically to figure out how to dispatch to them.  If it becomes more complicated than this we can
68724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // turn the g_dispatch_functions char * array into a template table, and populate the DispatchFunction map
68824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    // from there.
68924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
6903e11c7ec050648ba865f1d451f8cb46fd39072a8Andy Gibbs    for (size_t i = 0; i != llvm::array_lengthof(g_dispatch_functions); i++)
69124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
69224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ConstString name_const_str(g_dispatch_functions[i].name);
69324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        const Symbol *msgSend_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (name_const_str, eSymbolTypeCode);
69424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (msgSend_symbol)
69524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
6965d187e5495ee17f6763337a6ae28c2a7b07e4945Greg Clayton            // FixMe: Make g_dispatch_functions static table of DispatchFunctions, and have the map be address->index.
69724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // Problem is we also need to lookup the dispatch function.  For now we could have a side table of stret & non-stret
69824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            // dispatch functions.  If that's as complex as it gets, we're fine.
69924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
7000c31d3d3a4a1d00d53346d8a23b0519f47e55d1fGreg Clayton            lldb::addr_t sym_addr = msgSend_symbol->GetAddress().GetOpcodeLoadAddress(target);
70124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
70224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            m_msgSend_map.insert(std::pair<lldb::addr_t, int>(sym_addr, i));
70324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
70424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
7054f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
7064f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    // Build our vtable dispatch handler here:
7074f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    m_vtables_ap.reset(new AppleObjCVTables(process_sp, m_objc_module_sp));
7084f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (m_vtables_ap.get())
7094f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        m_vtables_ap->ReadRegions();
71024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
71124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
7121831e78a6253392fca1c99e555e7adaa3f372647Jim Inghamlldb::addr_t
7131831e78a6253392fca1c99e555e7adaa3f372647Jim InghamAppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &dispatch_values)
7141831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham{
7151831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    ExecutionContext exe_ctx (thread.shared_from_this());
7161831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    Address impl_code_address;
7171831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    StreamString errors;
718952e9dc874944fcdbbb224f3ec4fc2c859376f64Greg Clayton    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
7191831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
7201831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham
7211831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    // Scope for mutex locker:
7221831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    {
7231831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        Mutex::Locker locker(m_impl_function_mutex);
7241831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham
7251831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        // First stage is to make the ClangUtility to hold our injected function:
7261831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham
7271831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    #define USE_BUILTIN_FUNCTION 0  // Define this to 1 and we will use the get_implementation function found in the target.
7281831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                        // This is useful for debugging additions to the get_impl function 'cause you don't have
7291831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                        // to bother with string-ifying the code into g_lookup_implementation_function_code.
7301831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham
7311831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        if (USE_BUILTIN_FUNCTION)
7321831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        {
7331831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            ConstString our_utility_function_name("__lldb_objc_find_implementation_for_selector");
7341831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            SymbolContextList sc_list;
7351831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham
7361831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            exe_ctx.GetTargetRef().GetImages().FindSymbolsWithNameAndType (our_utility_function_name, eSymbolTypeCode, sc_list);
7371831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            if (sc_list.GetSize() == 1)
7381831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            {
7391831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                SymbolContext sc;
7401831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                sc_list.GetContextAtIndex(0, sc);
7411831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                if (sc.symbol != NULL)
7421831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                    impl_code_address = sc.symbol->GetAddress();
7431831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham
7441831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr());
7455f35a4be95aed0e5b2cb36f7d785bcbfc67284aeDaniel Malea                //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr);
7461831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            }
7471831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            else
7481831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            {
7491831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                //printf ("Could not find implementation function address.\n");
7501831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                return args_addr;
7511831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            }
7521831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        }
7531831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        else if (!m_impl_code.get())
7541831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        {
75512f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            if (g_lookup_implementation_function_code != NULL)
75612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            {
75712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                m_impl_code.reset (new ClangUtilityFunction (g_lookup_implementation_function_code,
75812f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                                                             g_lookup_implementation_function_name));
75912f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                if (!m_impl_code->Install(errors, exe_ctx))
76012f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                {
76112f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                    if (log)
76212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                        log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
76312f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                    m_impl_code.reset();
76412f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                    return args_addr;
76512f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                }
76612f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            }
76712f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham            else
7681831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            {
7691831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                if (log)
77012f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                    log->Printf("No method lookup implementation code.");
77112f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                errors.Printf ("No method lookup implementation code found.");
77212f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham                return LLDB_INVALID_ADDRESS;
7731831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            }
77412f564b9273ec6c53ac118d5d66e4185ae423e8cJim Ingham
7751831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            impl_code_address.Clear();
7761831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            impl_code_address.SetOffset(m_impl_code->StartAddress());
7771831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        }
7781831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        else
7791831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        {
7801831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            impl_code_address.Clear();
7811831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            impl_code_address.SetOffset(m_impl_code->StartAddress());
7821831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        }
7831831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham
7841831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        // Next make the runner function for our implementation utility function.
7851831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        if (!m_impl_function.get())
7861831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        {
78752f792329be5db8e38961350589e97e8f2823acdGreg Clayton            ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext();
78852f792329be5db8e38961350589e97e8f2823acdGreg Clayton            ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
78952f792329be5db8e38961350589e97e8f2823acdGreg Clayton            m_impl_function.reset(new ClangFunction (thread,
79052f792329be5db8e38961350589e97e8f2823acdGreg Clayton                                                     clang_void_ptr_type,
79152f792329be5db8e38961350589e97e8f2823acdGreg Clayton                                                     impl_code_address,
79252f792329be5db8e38961350589e97e8f2823acdGreg Clayton                                                     dispatch_values));
7931831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham
7941831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            errors.Clear();
7951831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            unsigned num_errors = m_impl_function->CompileFunction(errors);
7961831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            if (num_errors)
7971831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            {
7981831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                if (log)
7991831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                    log->Printf ("Error compiling function: \"%s\".", errors.GetData());
8001831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                return args_addr;
8011831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            }
8021831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham
8031831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            errors.Clear();
8041831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            if (!m_impl_function->WriteFunctionWrapper(exe_ctx, errors))
8051831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            {
8061831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                if (log)
8071831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                    log->Printf ("Error Inserting function: \"%s\".", errors.GetData());
8081831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                return args_addr;
8091831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            }
8101831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        }
8111831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    }
8121831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham
8131831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    errors.Clear();
8141831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham
8151831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    // Now write down the argument values for this particular call.  This looks like it might be a race condition
8161831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    // if other threads were calling into here, but actually it isn't because we allocate a new args structure for
8171831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    // this call by passing args_addr = LLDB_INVALID_ADDRESS...
8181831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham
8191831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    if (!m_impl_function->WriteFunctionArguments (exe_ctx, args_addr, impl_code_address, dispatch_values, errors))
8201831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    {
8211831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        if (log)
8221831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
8231831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham        return args_addr;
8241831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    }
8251831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham
8261831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham    return args_addr;
8271831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham}
8281831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham
82924943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerThreadPlanSP
830b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim InghamAppleObjCTrampolineHandler::GetStepThroughDispatchPlan (Thread &thread, bool stop_others)
83124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
83224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    ThreadPlanSP ret_plan_sp;
83324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();
83424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
8354f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    DispatchFunction this_dispatch;
8364f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    bool found_it = false;
8374f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
8386507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    // First step is to look and see if we are in one of the known ObjC dispatch functions.  We've already compiled
8396507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    // a table of same, so consult it.
8406507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham
84124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    MsgsendMap::iterator pos;
84224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    pos = m_msgSend_map.find (curr_pc);
84324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    if (pos != m_msgSend_map.end())
84424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    {
8454f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        this_dispatch = g_dispatch_functions[(*pos).second];
8464f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        found_it = true;
8474f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    }
8484f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
8496507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham    // Next check to see if we are in a vtable region:
8506507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham
8514f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (!found_it)
8524f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    {
8534f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        uint32_t flags;
8544f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        if (m_vtables_ap.get())
8554f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        {
8564f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            found_it = m_vtables_ap->IsAddressInVTables (curr_pc, flags);
8574f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            if (found_it)
8584f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            {
8594f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                this_dispatch.name = "vtable";
8604f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                this_dispatch.stret_return
8614f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                        = (flags & AppleObjCVTables::eOBJC_TRAMPOLINE_STRET) == AppleObjCVTables::eOBJC_TRAMPOLINE_STRET;
8624f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                this_dispatch.is_super = false;
8630984687e72f77f5e2278ed30597cc17a2e2afb62Jim Ingham                this_dispatch.is_super2 = false;
8644f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                this_dispatch.fixedup = DispatchFunction::eFixUpFixed;
8654f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            }
8664f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        }
8674f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    }
8684f385f181467701d2c5225f2c954ed5771e0763fJim Ingham
8694f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    if (found_it)
8704f385f181467701d2c5225f2c954ed5771e0763fJim Ingham    {
871952e9dc874944fcdbbb224f3ec4fc2c859376f64Greg Clayton        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
87224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
8736507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        // We are decoding a method dispatch.
8746507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        // First job is to pull the arguments out:
87524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
87624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0);
87724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
878289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton        const ABI *abi = NULL;
879289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton        ProcessSP process_sp (thread.CalculateProcess());
880289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton        if (process_sp)
881289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton            abi = process_sp->GetABI().get();
88224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (abi == NULL)
88324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return ret_plan_sp;
88424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
885289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton        TargetSP target_sp (thread.CalculateTarget());
88624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
887289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton        ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext();
88824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        ValueList argument_values;
8896507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        Value void_ptr_value;
89052f792329be5db8e38961350589e97e8f2823acdGreg Clayton        ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
8916507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        void_ptr_value.SetValueType (Value::eValueTypeScalar);
89252f792329be5db8e38961350589e97e8f2823acdGreg Clayton        //void_ptr_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
89352f792329be5db8e38961350589e97e8f2823acdGreg Clayton        void_ptr_value.SetClangType (clang_void_ptr_type);
89424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
89524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        int obj_index;
89624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        int sel_index;
89724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
89824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // If this is a struct return dispatch, then the first argument is the
89924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // return struct pointer, and the object is the second, and the selector is the third.
90024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        // Otherwise the object is the first and the selector the second.
9014f385f181467701d2c5225f2c954ed5771e0763fJim Ingham        if (this_dispatch.stret_return)
90224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
90324943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            obj_index = 1;
90424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            sel_index = 2;
9056507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            argument_values.PushValue(void_ptr_value);
9066507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            argument_values.PushValue(void_ptr_value);
9076507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            argument_values.PushValue(void_ptr_value);
90824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
90924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        else
91024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
91124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            obj_index = 0;
91224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            sel_index = 1;
9136507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            argument_values.PushValue(void_ptr_value);
9146507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            argument_values.PushValue(void_ptr_value);
91524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
91624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
91724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
91824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        bool success = abi->GetArgumentValues (thread, argument_values);
91924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        if (!success)
92024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            return ret_plan_sp;
92123a3f0262fa997146184080a9433ff7566e23610Jim Ingham
92223a3f0262fa997146184080a9433ff7566e23610Jim Ingham        lldb::addr_t obj_addr = argument_values.GetValueAtIndex(obj_index)->GetScalar().ULongLong();
92323a3f0262fa997146184080a9433ff7566e23610Jim Ingham        if (obj_addr == 0x0)
92423a3f0262fa997146184080a9433ff7566e23610Jim Ingham        {
92523a3f0262fa997146184080a9433ff7566e23610Jim Ingham            if (log)
92623a3f0262fa997146184080a9433ff7566e23610Jim Ingham                log->Printf("Asked to step to dispatch to nil object, returning empty plan.");
92723a3f0262fa997146184080a9433ff7566e23610Jim Ingham            return ret_plan_sp;
92823a3f0262fa997146184080a9433ff7566e23610Jim Ingham        }
929008f3dc79c762b7d240b5ad6d4fb148c5cb039caJim Ingham
930289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton        ExecutionContext exe_ctx (thread.shared_from_this());
931289afcb5e26c2527a0d2e71f84e780b86bbcf90aGreg Clayton        Process *process = exe_ctx.GetProcessPtr();
932e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        // isa_addr will store the class pointer that the method is being dispatched to - so either the class
933e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        // directly or the super class if this is one of the objc_msgSendSuper flavors.  That's mostly used to
934e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        // look up the class/selector pair in our cache.
935e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
936e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        lldb::addr_t isa_addr = LLDB_INVALID_ADDRESS;
9376507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham        lldb::addr_t sel_addr = argument_values.GetValueAtIndex(sel_index)->GetScalar().ULongLong();
938e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
939e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        // Figure out the class this is being dispatched to and see if we've already cached this method call,
940e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        // If so we can push a run-to-address plan directly.  Otherwise we have to figure out where
941e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        // the implementation lives.
9426507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham
943e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        if (this_dispatch.is_super)
94424943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        {
945e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            if (this_dispatch.is_super2)
946e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            {
947e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham               // In the objc_msgSendSuper2 case, we don't get the object directly, we get a structure containing
948e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham               // the object and the class to which the super message is being sent.  So we need to dig the super
949e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham               // out of the class and use that.
950e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
951e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
952e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                super_value.GetScalar() += process->GetAddressByteSize();
95352f792329be5db8e38961350589e97e8f2823acdGreg Clayton                super_value.ResolveValue (&exe_ctx);
954e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
955e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                if (super_value.GetScalar().IsValid())
956e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                {
957e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
958e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                    // isa_value now holds the class pointer.  The second word of the class pointer is the super-class pointer:
959e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                    super_value.GetScalar() += process->GetAddressByteSize();
96052f792329be5db8e38961350589e97e8f2823acdGreg Clayton                    super_value.ResolveValue (&exe_ctx);
961e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                    if (super_value.GetScalar().IsValid())
962e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                        isa_addr = super_value.GetScalar().ULongLong();
963e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                    else
964e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                    {
965e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                       if (log)
966e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                        log->Printf("Failed to extract the super class value from the class in objc_super.");
967e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                    }
968e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                }
969e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                else
970e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                {
971e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                   if (log)
972e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                    log->Printf("Failed to extract the class value from objc_super.");
973e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                }
974e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            }
975e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            else
976e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            {
977e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham               // In the objc_msgSendSuper case, we don't get the object directly, we get a two element structure containing
978e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham               // the object and the super class to which the super message is being sent.  So the class we want is
979e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham               // the second element of this structure.
980e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
981e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
982e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                super_value.GetScalar() += process->GetAddressByteSize();
98352f792329be5db8e38961350589e97e8f2823acdGreg Clayton                super_value.ResolveValue (&exe_ctx);
984e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
985e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                if (super_value.GetScalar().IsValid())
986e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                {
987e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                    isa_addr = super_value.GetScalar().ULongLong();
988e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                }
989e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                else
990e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                {
991e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                   if (log)
992e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                    log->Printf("Failed to extract the class value from objc_super.");
993e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                }
994e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            }
99524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
996e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        else
997e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        {
998e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            // In the direct dispatch case, the object->isa is the class pointer we want.
999e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
1000e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            // This is a little cheesy, but since object->isa is the first field,
1001e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            // making the object value a load address value and resolving it will get
1002e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            // the pointer sized data pointed to by that value...
1003e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
1004e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            // Note, it isn't a fatal error not to be able to get the address from the object, since this might
1005e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            // be a "tagged pointer" which isn't a real object, but rather some word length encoded dingus.
1006e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
1007e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            Value isa_value(*(argument_values.GetValueAtIndex(obj_index)));
1008e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
1009e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            isa_value.SetValueType(Value::eValueTypeLoadAddress);
101052f792329be5db8e38961350589e97e8f2823acdGreg Clayton            isa_value.ResolveValue(&exe_ctx);
1011e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            if (isa_value.GetScalar().IsValid())
1012e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            {
1013e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                isa_addr = isa_value.GetScalar().ULongLong();
1014e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            }
1015e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            else
1016e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            {
1017e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham               if (log)
1018e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                log->Printf("Failed to extract the isa value from object.");
1019e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            }
1020e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
1021e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        }
10226507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham
1023e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        // Okay, we've got the address of the class for which we're resolving this, let's see if it's in our cache:
1024e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        lldb::addr_t impl_addr = LLDB_INVALID_ADDRESS;
1025e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
1026e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        if (isa_addr != LLDB_INVALID_ADDRESS)
1027e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        {
1028e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            if (log)
1029e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            {
10305f35a4be95aed0e5b2cb36f7d785bcbfc67284aeDaniel Malea                log->Printf("Resolving call for class - 0x%" PRIx64 " and selector - 0x%" PRIx64,
1031e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham                            isa_addr, sel_addr);
1032e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            }
1033e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            ObjCLanguageRuntime *objc_runtime = m_process_sp->GetObjCLanguageRuntime ();
1034e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            assert(objc_runtime != NULL);
1035e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
1036e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            impl_addr = objc_runtime->LookupInMethodCache (isa_addr, sel_addr);
1037e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        }
1038e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
1039e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        if (impl_addr != LLDB_INVALID_ADDRESS)
1040e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        {
1041e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            // Yup, it was in the cache, so we can run to that address directly.
1042e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
1043e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            if (log)
10445f35a4be95aed0e5b2cb36f7d785bcbfc67284aeDaniel Malea                log->Printf ("Found implementation address in cache: 0x%" PRIx64, impl_addr);
1045e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham
1046e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham            ret_plan_sp.reset (new ThreadPlanRunToAddress (thread, impl_addr, stop_others));
1047e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        }
1048e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        else
1049e258440978dce75cd921fe7bf9b8174c17004763Jim Ingham        {
10506507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            // We haven't seen this class/selector pair yet.  Look it up.
105124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner            StreamString errors;
10526507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            Address impl_code_address;
10536507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham
10546507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            ValueList dispatch_values;
10556507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham
10566507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            // We've will inject a little function in the target that takes the object, selector and some flags,
10576507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            // and figures out the implementation.  Looks like:
10586507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            //      void *__lldb_objc_find_implementation_for_selector (void *object,
10596507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            //                                                          void *sel,
10606507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            //                                                          int is_stret,
10616507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            //                                                          int is_super,
10626507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            //                                                          int is_super2,
10636507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            //                                                          int is_fixup,
10646507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            //                                                          int is_fixed,
10656507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            //                                                          int debug)
10666507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            // So set up the arguments for that call.
10676507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham
10686507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            dispatch_values.PushValue (*(argument_values.GetValueAtIndex(obj_index)));
10696507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            dispatch_values.PushValue (*(argument_values.GetValueAtIndex(sel_index)));
10706507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham
10716507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            Value flag_value;
107252f792329be5db8e38961350589e97e8f2823acdGreg Clayton            ClangASTType clang_int_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingSint, 32);
10736507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            flag_value.SetValueType (Value::eValueTypeScalar);
107452f792329be5db8e38961350589e97e8f2823acdGreg Clayton            //flag_value.SetContext (Value::eContextTypeClangType, clang_int_type);
107552f792329be5db8e38961350589e97e8f2823acdGreg Clayton            flag_value.SetClangType (clang_int_type);
10766507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham
10776507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            if (this_dispatch.stret_return)
10786507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                flag_value.GetScalar() = 1;
10796507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            else
10806507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                flag_value.GetScalar() = 0;
10816507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            dispatch_values.PushValue (flag_value);
10826507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham
10836507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            if (this_dispatch.is_super)
10846507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                flag_value.GetScalar() = 1;
10856507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            else
10866507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                flag_value.GetScalar() = 0;
10876507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            dispatch_values.PushValue (flag_value);
10886507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham
10896507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            if (this_dispatch.is_super2)
10906507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                flag_value.GetScalar() = 1;
10916507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            else
10926507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                flag_value.GetScalar() = 0;
10936507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            dispatch_values.PushValue (flag_value);
10946507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham
10956507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            switch (this_dispatch.fixedup)
10966507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            {
10976507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham              case DispatchFunction::eFixUpNone:
10986507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 flag_value.GetScalar() = 0;
10996507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 dispatch_values.PushValue (flag_value);
11006507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 dispatch_values.PushValue (flag_value);
11016507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 break;
11026507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham              case DispatchFunction::eFixUpFixed:
11036507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 flag_value.GetScalar() = 1;
11046507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 dispatch_values.PushValue (flag_value);
11056507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 flag_value.GetScalar() = 1;
11066507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 dispatch_values.PushValue (flag_value);
11076507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 break;
11086507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham              case DispatchFunction::eFixUpToFix:
11096507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 flag_value.GetScalar() = 1;
11106507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 dispatch_values.PushValue (flag_value);
11116507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 flag_value.GetScalar() = 0;
11126507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 dispatch_values.PushValue (flag_value);
11136507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                 break;
11146507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            }
111520c37084dbfb8d704b3dabcd978a0afc060cd87dJim Ingham            if (log && log->GetVerbose())
11166507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                flag_value.GetScalar() = 1;
11176507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham            else
11186507dd90b5d27662537caee49a3a3cc236f85a53Jim Ingham                flag_value.GetScalar() = 0;  // FIXME - Set to 0 when debugging is done.
11195a26910ed231503d2a7a71365a44e379a994f4e6Greg Clayton            dispatch_values.PushValue (flag_value);
112024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
1121b6b7f3e32208a9cce03aace3e05eabefd2693c2cJim Ingham
1122b6b7f3e32208a9cce03aace3e05eabefd2693c2cJim Ingham            // The step through code might have to fill in the cache, so it is not safe to run only one thread.
1123b6b7f3e32208a9cce03aace3e05eabefd2693c2cJim Ingham            // So we override the stop_others value passed in to us here:
1124b6b7f3e32208a9cce03aace3e05eabefd2693c2cJim Ingham            const bool trampoline_stop_others = false;
11251831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham            ret_plan_sp.reset (new AppleThreadPlanStepThroughObjCTrampoline (thread,
11261831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                                                                             this,
11271831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                                                                             dispatch_values,
11281831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                                                                             isa_addr,
11291831e78a6253392fca1c99e555e7adaa3f372647Jim Ingham                                                                             sel_addr,
1130b6b7f3e32208a9cce03aace3e05eabefd2693c2cJim Ingham                                                                             trampoline_stop_others));
11314f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            if (log)
11324f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            {
11334f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                StreamString s;
11344f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                ret_plan_sp->GetDescription(&s, eDescriptionLevelFull);
11354f385f181467701d2c5225f2c954ed5771e0763fJim Ingham                log->Printf("Using ObjC step plan: %s.\n", s.GetData());
11364f385f181467701d2c5225f2c954ed5771e0763fJim Ingham            }
113724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner        }
113824943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    }
113924943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
114024943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return ret_plan_sp;
114124943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
114224943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner
114324943d2ee8bfaa7cf5893e4709143924157a5c1eChris LattnerClangFunction *
1144b66cd074ec097b5b0a6f2ce292f5072aa1217ca6Jim InghamAppleObjCTrampolineHandler::GetLookupImplementationWrapperFunction ()
114524943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner{
114624943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner    return m_impl_function.get();
114724943d2ee8bfaa7cf5893e4709143924157a5c1eChris Lattner}
1148