1579a0246616d76bc536de0e41edf069d091604beNick Lewycky//===-- AppleObjCTrampolineHandler.cpp ----------------------------*- C++ -*-===//
2579a0246616d76bc536de0e41edf069d091604beNick Lewycky//
3579a0246616d76bc536de0e41edf069d091604beNick Lewycky//                     The LLVM Compiler Infrastructure
4579a0246616d76bc536de0e41edf069d091604beNick Lewycky//
5579a0246616d76bc536de0e41edf069d091604beNick Lewycky// This file is distributed under the University of Illinois Open Source
6579a0246616d76bc536de0e41edf069d091604beNick Lewycky// License. See LICENSE.TXT for details.
7579a0246616d76bc536de0e41edf069d091604beNick Lewycky//
8579a0246616d76bc536de0e41edf069d091604beNick Lewycky//===----------------------------------------------------------------------===//
9579a0246616d76bc536de0e41edf069d091604beNick Lewycky
10579a0246616d76bc536de0e41edf069d091604beNick Lewycky#include "lldb/lldb-python.h"
11579a0246616d76bc536de0e41edf069d091604beNick Lewycky
12cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "AppleObjCTrampolineHandler.h"
13cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
14cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// C Includes
15cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// C++ Includes
16cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// Other libraries and framework includes
17cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines// Project includes
18cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "AppleThreadPlanStepThroughObjCTrampoline.h"
19cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
20cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "lldb/Breakpoint/StoppointCallbackContext.h"
21cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "lldb/Core/ConstString.h"
22579a0246616d76bc536de0e41edf069d091604beNick Lewycky#include "lldb/Core/Debugger.h"
23cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "lldb/Core/Log.h"
24cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "lldb/Core/Module.h"
25cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "lldb/Core/Value.h"
26cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "lldb/Expression/ClangExpression.h"
27cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "lldb/Expression/ClangFunction.h"
28cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "lldb/Expression/ClangUtilityFunction.h"
29cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines#include "lldb/Host/FileSpec.h"
30579a0246616d76bc536de0e41edf069d091604beNick Lewycky#include "lldb/Symbol/ClangASTContext.h"
3133ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky#include "lldb/Symbol/Symbol.h"
3233ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky#include "lldb/Target/ObjCLanguageRuntime.h"
3333ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky#include "lldb/Target/Process.h"
34579a0246616d76bc536de0e41edf069d091604beNick Lewycky#include "lldb/Target/RegisterContext.h"
35579a0246616d76bc536de0e41edf069d091604beNick Lewycky#include "lldb/Target/Target.h"
36579a0246616d76bc536de0e41edf069d091604beNick Lewycky#include "lldb/Target/Thread.h"
37579a0246616d76bc536de0e41edf069d091604beNick Lewycky#include "lldb/Target/ExecutionContext.h"
38579a0246616d76bc536de0e41edf069d091604beNick Lewycky#include "lldb/Target/ThreadPlanRunToAddress.h"
39579a0246616d76bc536de0e41edf069d091604beNick Lewycky
40579a0246616d76bc536de0e41edf069d091604beNick Lewycky#include "llvm/ADT/STLExtras.h"
41579a0246616d76bc536de0e41edf069d091604beNick Lewycky
42579a0246616d76bc536de0e41edf069d091604beNick Lewyckyusing namespace lldb;
43be04fdeb6c46e92fdeda7535c5912d072eff008cNick Lewyckyusing namespace lldb_private;
44579a0246616d76bc536de0e41edf069d091604beNick Lewycky
45be04fdeb6c46e92fdeda7535c5912d072eff008cNick Lewyckyconst char *AppleObjCTrampolineHandler::g_lookup_implementation_function_name = "__lldb_objc_find_implementation_for_selector";
4633ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewyckyconst char *AppleObjCTrampolineHandler::g_lookup_implementation_function_code = NULL;
4733ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewyckyconst char *AppleObjCTrampolineHandler::g_lookup_implementation_with_stret_function_code = "                               \n\
4833ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewyckyextern \"C\"                                                                                                    \n\
4933ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky{                                                                                                               \n\
50be04fdeb6c46e92fdeda7535c5912d072eff008cNick Lewycky    extern void *class_getMethodImplementation(void *objc_class, void *sel);                                    \n\
5133ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky    extern void *class_getMethodImplementation_stret(void *objc_class, void *sel);                              \n\
52cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    extern void * sel_getUid(char *name);                                                                       \n\
53cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    extern int printf(const char *format, ...);                                                                 \n\
54cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}                                                                                                               \n\
55cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesextern \"C\" void * __lldb_objc_find_implementation_for_selector (void *object,                                 \n\
56cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                                    void *sel,                                                  \n\
57cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                                    int is_stret,                                               \n\
58cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                                    int is_super,                                               \n\
59cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                                    int is_super2,                                              \n\
60cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                                    int is_fixup,                                               \n\
61cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                                    int is_fixed,                                               \n\
62cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                                    int debug)                                                  \n\
63cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines{                                                                                                               \n\
64cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    struct __lldb_imp_return_struct                                                                             \n\
65cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    {                                                                                                           \n\
66cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        void *class_addr;                                                                                       \n\
67cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        void *sel_addr;                                                                                         \n\
68cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        void *impl_addr;                                                                                        \n\
69cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    };                                                                                                          \n\
70cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                                                                                                \n\
71cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    struct __lldb_objc_class {                                                                                  \n\
72cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        void *isa;                                                                                              \n\
73cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        void *super_ptr;                                                                                        \n\
74cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    };                                                                                                          \n\
75cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    struct __lldb_objc_super {                                                                                  \n\
76cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        void *reciever;                                                                                         \n\
77cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        struct __lldb_objc_class *class_ptr;                                                                    \n\
78cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    };                                                                                                          \n\
79cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    struct __lldb_msg_ref {                                                                                     \n\
80cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        void *dont_know;                                                                                        \n\
81cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        void *sel;                                                                                              \n\
82579a0246616d76bc536de0e41edf069d091604beNick Lewycky    };                                                                                                          \n\
83579a0246616d76bc536de0e41edf069d091604beNick Lewycky                                                                                                                \n\
84579a0246616d76bc536de0e41edf069d091604beNick Lewycky    struct __lldb_imp_return_struct return_struct;                                                              \n\
85d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth                                                                                                                \n\
86d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth    if (debug)                                                                                                  \n\
87d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth        printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \"                          \n\
88d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth                \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\",                                               \n\
89d04a8d4b33ff316ca4cf961e06c9e312eff8e64fChandler Carruth                 object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed);                               \n\
9036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (is_super)                                                                                               \n\
910b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth    {                                                                                                           \n\
920b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth        if (is_super2)                                                                                          \n\
930b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth        {                                                                                                       \n\
940b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth            return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr;                    \n\
950b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth        }                                                                                                       \n\
960b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth        else                                                                                                    \n\
970b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth        {                                                                                                       \n\
980b8c9a80f20772c3793201ab5b251d3520b9cea3Chandler Carruth            return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr;                               \n\
9936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        }                                                                                                       \n\
100579a0246616d76bc536de0e41edf069d091604beNick Lewycky    }                                                                                                           \n\
101cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    else                                                                                                        \n\
102579a0246616d76bc536de0e41edf069d091604beNick Lewycky    {                                                                                                           \n\
103c25e7581b9b8088910da31702d4ca21c4734c6d7Torok Edwin        void *class_ptr = (void *) [(id) object class];                                                         \n\
104ce63ffb52f249b62cdf2d250c128007b13f27e71Daniel Dunbar        if (class_ptr == object)                                                                                \n\
10565a0af3855c7003fa57d41eeb6586b20eefa8cfdNick Lewycky        {                                                                                                       \n\
106579a0246616d76bc536de0e41edf069d091604beNick Lewycky            struct __lldb_objc_class *class_as_class_struct = (struct __lldb_objc_class *) class_ptr;           \n\
107579a0246616d76bc536de0e41edf069d091604beNick Lewycky            if (debug)                                                                                          \n\
108dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                printf (\"Found a class object, need to return the meta class 0x%p -> 0x%p\\n\",                \n\
109dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                        class_ptr, class_as_class_struct->isa);                                                 \n\
110579a0246616d76bc536de0e41edf069d091604beNick Lewycky            return_struct.class_addr = class_as_class_struct->isa;                                              \n\
1112b6c01b40b75e363e46b3ad7c598113eb98f34fbNick Lewycky        }                                                                                                       \n\
112b38824f866447ccf8dd0c76656755b05bcede1b1Nick Lewycky        else                                                                                                    \n\
1132b6c01b40b75e363e46b3ad7c598113eb98f34fbNick Lewycky        {                                                                                                       \n\
114579a0246616d76bc536de0e41edf069d091604beNick Lewycky            if (debug)                                                                                          \n\
115cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                printf (\"[object class] returned: 0x%p.\\n\", class_ptr);                                      \n\
116cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            return_struct.class_addr = class_ptr;                                                               \n\
117cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        }                                                                                                       \n\
118cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }                                                                                                           \n\
119cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                                                                                                \n\
120cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    if (is_fixup)                                                                                               \n\
121b0e17779ba401feae32cdd1dd4096d49c1746153Nick Lewycky    {                                                                                                           \n\
122b0e17779ba401feae32cdd1dd4096d49c1746153Nick Lewycky        if (is_fixed)                                                                                           \n\
123b0e17779ba401feae32cdd1dd4096d49c1746153Nick Lewycky        {                                                                                                       \n\
124be04fdeb6c46e92fdeda7535c5912d072eff008cNick Lewycky            return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel;                                             \n\
1253574eca1b02600bac4e625297f4ecf745f4c4f32Micah Villmow        }                                                                                                       \n\
126be04fdeb6c46e92fdeda7535c5912d072eff008cNick Lewycky        else                                                                                                    \n\
127be04fdeb6c46e92fdeda7535c5912d072eff008cNick Lewycky        {                                                                                                       \n\
12878d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky            char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel;                                            \n\
12978d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky            return_struct.sel_addr = sel_getUid (sel_name);                                                     \n\
13036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            if (debug)                                                                                          \n\
131f53de86cba33b63ecd54e16dcea735939c5b0e4aNick Lewycky                printf (\"\\n*** Got fixed up selector: 0x%p for name %s.\\n\",                                 \n\
132cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                        return_struct.sel_addr, sel_name);                                                      \n\
13378d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky        }                                                                                                       \n\
134468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky    }                                                                                                           \n\
135cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    else                                                                                                        \n\
13678d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky    {                                                                                                           \n\
13778d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky        return_struct.sel_addr = sel;                                                                           \n\
138468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky    }                                                                                                           \n\
139cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                                                                                                                \n\
14078d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky    if (is_stret)                                                                                               \n\
141dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {                                                                                                           \n\
142dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        return_struct.impl_addr = class_getMethodImplementation_stret (return_struct.class_addr,                \n\
143dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                       return_struct.sel_addr);                 \n\
144dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }                                                                                                           \n\
145dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    else                                                                                                        \n\
146dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {                                                                                                           \n\
147dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        return_struct.impl_addr = class_getMethodImplementation (return_struct.class_addr,                      \n\
148dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                       return_struct.sel_addr);                 \n\
149dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }                                                                                                           \n\
150dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (debug)                                                                                                  \n\
151dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        printf (\"\\n*** Returning implementation: 0x%p.\\n\", return_struct.impl_addr);                        \n\
152dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                                                                \n\
153dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return return_struct.impl_addr;                                                                             \n\
154dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}                                                                                                               \n\
155dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines";
156dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesconst char *AppleObjCTrampolineHandler::g_lookup_implementation_no_stret_function_code = "                      \n\
157dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesextern \"C\"                                                                                                    \n\
158dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{                                                                                                               \n\
159dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    extern void *class_getMethodImplementation(void *objc_class, void *sel);                                    \n\
160dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    extern void * sel_getUid(char *name);                                                                       \n\
161dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    extern int printf(const char *format, ...);                                                                 \n\
162dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}                                                                                                               \n\
163dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesextern \"C\" void * __lldb_objc_find_implementation_for_selector (void *object,                                 \n\
164dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                    void *sel,                                                  \n\
165dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                    int is_stret,                                               \n\
166dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                    int is_super,                                               \n\
167dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                    int is_super2,                                              \n\
168dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                    int is_fixup,                                               \n\
169dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                    int is_fixed,                                               \n\
170dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                    int debug)                                                  \n\
171dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{                                                                                                               \n\
172dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    struct __lldb_imp_return_struct                                                                             \n\
173dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {                                                                                                           \n\
174dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        void *class_addr;                                                                                       \n\
175dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        void *sel_addr;                                                                                         \n\
176dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        void *impl_addr;                                                                                        \n\
177dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    };                                                                                                          \n\
178dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                                                                \n\
179dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    struct __lldb_objc_class {                                                                                  \n\
180dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        void *isa;                                                                                              \n\
181dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        void *super_ptr;                                                                                        \n\
182dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    };                                                                                                          \n\
183dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    struct __lldb_objc_super {                                                                                  \n\
184dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        void *reciever;                                                                                         \n\
185dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        struct __lldb_objc_class *class_ptr;                                                                    \n\
186dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    };                                                                                                          \n\
187dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    struct __lldb_msg_ref {                                                                                     \n\
188dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        void *dont_know;                                                                                        \n\
189dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        void *sel;                                                                                              \n\
190dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    };                                                                                                          \n\
191dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                                                                \n\
192dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    struct __lldb_imp_return_struct return_struct;                                                              \n\
193dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                                                                \n\
194dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (debug)                                                                                                  \n\
195dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        printf (\"\\n*** Called with obj: 0x%p sel: 0x%p is_stret: %d is_super: %d, \"                          \n\
196dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                \"is_super2: %d, is_fixup: %d, is_fixed: %d\\n\",                                               \n\
197dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                 object, sel, is_stret, is_super, is_super2, is_fixup, is_fixed);                               \n\
198dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (is_super)                                                                                               \n\
199dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {                                                                                                           \n\
200dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (is_super2)                                                                                          \n\
201dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {                                                                                                       \n\
202dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr->super_ptr;                    \n\
203dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }                                                                                                       \n\
204dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        else                                                                                                    \n\
205dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {                                                                                                       \n\
206dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            return_struct.class_addr = ((__lldb_objc_super *) object)->class_ptr;                               \n\
207dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }                                                                                                       \n\
208dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }                                                                                                           \n\
209dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    else                                                                                                        \n\
210dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {                                                                                                           \n\
211dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        void *class_ptr = (void *) [(id) object class];                                                         \n\
212dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (class_ptr == object)                                                                                \n\
213dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {                                                                                                       \n\
214dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            struct __lldb_objc_class *class_as_class_struct = (struct __lldb_objc_class *) class_ptr;           \n\
215dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            if (debug)                                                                                          \n\
216dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                printf (\"Found a class object, need to return the meta class 0x%p -> 0x%p\\n\",                \n\
217dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                        class_ptr, class_as_class_struct->isa);                                                 \n\
218dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            return_struct.class_addr = class_as_class_struct->isa;                                              \n\
219dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }                                                                                                       \n\
220dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        else                                                                                                    \n\
221dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {                                                                                                       \n\
222dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            if (debug)                                                                                          \n\
223dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                printf (\"[object class] returned: 0x%p.\\n\", class_ptr);                                      \n\
224dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            return_struct.class_addr = class_ptr;                                                               \n\
225dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }                                                                                                       \n\
226dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }                                                                                                           \n\
227dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                                                                \n\
228dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (is_fixup)                                                                                               \n\
229dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {                                                                                                           \n\
230dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (is_fixed)                                                                                           \n\
231dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {                                                                                                       \n\
232dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            return_struct.sel_addr = ((__lldb_msg_ref *) sel)->sel;                                             \n\
233dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }                                                                                                       \n\
234dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        else                                                                                                    \n\
235dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {                                                                                                       \n\
236dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            char *sel_name = (char *) ((__lldb_msg_ref *) sel)->sel;                                            \n\
237dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            return_struct.sel_addr = sel_getUid (sel_name);                                                     \n\
238dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            if (debug)                                                                                          \n\
239dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                printf (\"\\n*** Got fixed up selector: 0x%p for name %s.\\n\",                                 \n\
240dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                        return_struct.sel_addr, sel_name);                                                      \n\
241dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }                                                                                                       \n\
242dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }                                                                                                           \n\
243dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    else                                                                                                        \n\
244dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {                                                                                                           \n\
245468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky        return_struct.sel_addr = sel;                                                                           \n\
246468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky    }                                                                                                           \n\
247468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky                                                                                                                \n\
248dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return_struct.impl_addr = class_getMethodImplementation (return_struct.class_addr,                          \n\
249dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                             return_struct.sel_addr);                           \n\
250dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (debug)                                                                                                  \n\
251dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        printf (\"\\n*** Returning implementation: 0x%p.\\n\", return_struct.impl_addr);                        \n\
252dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                                                                \n\
253dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return return_struct.impl_addr;                                                                             \n\
254dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}                                                                                                               \n\
255dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines";
256dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
257dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr) :
258dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    m_valid (true),
259dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    m_owner(owner),
260dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    m_header_addr (header_addr),
261dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    m_code_start_addr(0),
262dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    m_code_end_addr (0),
263dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    m_next_region (0)
264dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{
265468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky    SetUpRegion ();
266468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky}
267be04fdeb6c46e92fdeda7535c5912d072eff008cNick Lewycky
268dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAppleObjCTrampolineHandler::~AppleObjCTrampolineHandler()
269dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{
270dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
271dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
272dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesvoid
273dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::SetUpRegion()
274dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{
275dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // The header looks like:
276dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    //
277dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    //   uint16_t headerSize
278dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    //   uint16_t descSize
279dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    //   uint32_t descCount
280dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    //   void * next
281dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    //
282dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // First read in the header:
283dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
284dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    char memory_buffer[16];
285dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Process *process = m_owner->GetProcess();
286cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    DataExtractor data(memory_buffer, sizeof(memory_buffer),
287dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                       process->GetByteOrder(),
288dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                       process->GetAddressByteSize());
289dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    size_t actual_size = 8 + process->GetAddressByteSize();
290dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Error error;
291468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky    size_t bytes_read = process->ReadMemory (m_header_addr, memory_buffer, actual_size, error);
292dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (bytes_read != actual_size)
293dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {
294dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        m_valid = false;
295dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        return;
296dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
297dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
298dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    lldb::offset_t offset = 0;
299dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const uint16_t header_size = data.GetU16(&offset);
300dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const uint16_t descriptor_size = data.GetU16(&offset);
301dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const size_t num_descriptors = data.GetU32(&offset);
302dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
303dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    m_next_region = data.GetPointer(&offset);
304dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
30536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // If the header size is 0, that means we've come in too early before this data is set up.
30636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Set ourselves as not valid, and continue.
30736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (header_size == 0 || num_descriptors == 0)
30836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {
30936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        m_valid = false;
31036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return;
31136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
31236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
31336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Now read in all the descriptors:
31436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // The descriptor looks like:
31536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    //
31636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // uint32_t offset
31736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // uint32_t flags
31836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    //
31936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Where offset is either 0 - in which case it is unused, or
32036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // it is the offset of the vtable code from the beginning of the descriptor record.
32136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Below, we'll convert that into an absolute code address, since I don't want to have
32236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // to compute it over and over.
32336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
32436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Ingest the whole descriptor array:
32536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const lldb::addr_t desc_ptr = m_header_addr + header_size;
32636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    const size_t desc_array_size = num_descriptors * descriptor_size;
32736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    DataBufferSP data_sp(new DataBufferHeap (desc_array_size, '\0'));
32836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    uint8_t* dst = (uint8_t*)data_sp->GetBytes();
32936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
33036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    DataExtractor desc_extractor (dst, desc_array_size,
33136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                  process->GetByteOrder(),
33236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                  process->GetAddressByteSize());
33336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    bytes_read = process->ReadMemory(desc_ptr, dst, desc_array_size, error);
33436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (bytes_read != desc_array_size)
33536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {
33636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        m_valid = false;
33736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        return;
33836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
33936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
34036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // The actual code for the vtables will be laid out consecutively, so I also
34136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // compute the start and end of the whole code block.
34236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
34336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    offset = 0;
34436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    m_code_start_addr = 0;
34536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    m_code_end_addr = 0;
34636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
34736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (size_t i = 0; i < num_descriptors; i++)
34878d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky    {
349dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        lldb::addr_t start_offset = offset;
350dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        uint32_t voffset = desc_extractor.GetU32 (&offset);
351dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        uint32_t flags  = desc_extractor.GetU32 (&offset);
352dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        lldb::addr_t code_addr = desc_ptr + start_offset + voffset;
353dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        m_descriptors.push_back (VTableDescriptor(flags, code_addr));
35478d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky
355cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (m_code_start_addr == 0 || code_addr < m_code_start_addr)
35678d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky            m_code_start_addr = code_addr;
35736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        if (code_addr > m_code_end_addr)
35878d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky            m_code_end_addr = code_addr;
359dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
360dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        offset = start_offset + descriptor_size;
361dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
362dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // Finally, a little bird told me that all the vtable code blocks are the same size.
363dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // Let's compute the blocks and if they are all the same add the size to the code end address:
364dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    lldb::addr_t code_size = 0;
365dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    bool all_the_same = true;
366dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (size_t i = 0; i < num_descriptors - 1; i++)
367dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {
368dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        lldb::addr_t this_size = m_descriptors[i + 1].code_start - m_descriptors[i].code_start;
369dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (code_size == 0)
370dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            code_size = this_size;
371dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        else
372dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {
373dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            if (this_size != code_size)
374dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                all_the_same = false;
375dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            if (this_size > code_size)
376dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                code_size = this_size;
377dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }
378dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
379dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (all_the_same)
380dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        m_code_end_addr += code_size;
381dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
382dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
383dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool
384dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::AddressInRegion (lldb::addr_t addr, uint32_t &flags)
385dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{
386dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (!IsValid())
387dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        return false;
388dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
389dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (addr < m_code_start_addr || addr > m_code_end_addr)
390dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        return false;
391dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
392dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    std::vector<VTableDescriptor>::iterator pos, end = m_descriptors.end();
39378d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky    for (pos = m_descriptors.begin(); pos != end; pos++)
394285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky    {
395cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (addr <= (*pos).code_start)
396cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        {
397cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            flags = (*pos).flags;
398cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            return true;
399cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        }
400cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
401cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return false;
402cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
403cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
404cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hinesvoid
405cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesAppleObjCTrampolineHandler::AppleObjCVTables::VTableRegion::Dump (Stream &s)
406cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines{
40778d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky    s.Printf ("Header addr: 0x%" PRIx64 " Code start: 0x%" PRIx64 " Code End: 0x%" PRIx64 " Next: 0x%" PRIx64 "\n",
40878d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky              m_header_addr, m_code_start_addr, m_code_end_addr, m_next_region);
40936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    size_t num_elements = m_descriptors.size();
41036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    for (size_t i = 0; i < num_elements; i++)
41136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {
41236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        s.Indent();
41336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        s.Printf ("Code start: 0x%" PRIx64 " Flags: %d\n", m_descriptors[i].code_start, m_descriptors[i].flags);
414fcb80cc5656e4672702e3150bfe425f4a58b7a65Bill Wendling    }
415dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
416dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
417dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAppleObjCTrampolineHandler::AppleObjCVTables::AppleObjCVTables (const ProcessSP &process_sp,
418dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                const ModuleSP &objc_module_sp) :
419dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    m_process_sp (process_sp),
420dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    m_trampoline_header (LLDB_INVALID_ADDRESS),
421dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    m_trampolines_changed_bp_id (LLDB_INVALID_BREAK_ID),
422dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    m_objc_module_sp (objc_module_sp)
423dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{
424dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
425dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
426dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
427dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAppleObjCTrampolineHandler::AppleObjCVTables::~AppleObjCVTables()
428dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{
429dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (m_trampolines_changed_bp_id != LLDB_INVALID_BREAK_ID)
430dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        m_process_sp->GetTarget().RemoveBreakpointByID (m_trampolines_changed_bp_id);
431dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
432dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
433dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool
434dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAppleObjCTrampolineHandler::AppleObjCVTables::InitializeVTableSymbols ()
435dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{
436dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (m_trampoline_header != LLDB_INVALID_ADDRESS)
437dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        return true;
438dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Target &target = m_process_sp->GetTarget();
439dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
440dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    const ModuleList &target_modules = target.GetImages();
441dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Mutex::Locker modules_locker(target_modules.GetMutex());
442dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    size_t num_modules = target_modules.GetSize();
443dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (!m_objc_module_sp)
444dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {
445dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        for (size_t i = 0; i < num_modules; i++)
446dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {
447dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            if (m_process_sp->GetObjCLanguageRuntime()->IsModuleObjCLibrary (target_modules.GetModuleAtIndexUnlocked(i)))
448dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            {
449dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                m_objc_module_sp = target_modules.GetModuleAtIndexUnlocked(i);
450dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                break;
451dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            }
452dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }
453dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
454dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
455dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (m_objc_module_sp)
456dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {
457dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        ConstString trampoline_name ("gdb_objc_trampolines");
458dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        const Symbol *trampoline_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (trampoline_name,
459dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                                            eSymbolTypeData);
460dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (trampoline_symbol != NULL)
461dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {
462dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            if (!trampoline_symbol->GetAddress().IsValid())
463dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                return false;
464dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
465dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            m_trampoline_header = trampoline_symbol->GetAddress().GetLoadAddress(&target);
466dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            if (m_trampoline_header == LLDB_INVALID_ADDRESS)
467dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                return false;
468dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
469dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            // Next look up the "changed" symbol and set a breakpoint on that...
470dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            ConstString changed_name ("gdb_objc_trampolines_changed");
471dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            const Symbol *changed_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (changed_name,
472dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                                             eSymbolTypeCode);
473dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            if (changed_symbol != NULL)
474dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            {
475dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                if (!changed_symbol->GetAddress().IsValid())
476dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                    return false;
477dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
478dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                lldb::addr_t changed_addr = changed_symbol->GetAddress().GetOpcodeLoadAddress (&target);
479dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                if (changed_addr != LLDB_INVALID_ADDRESS)
480dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                {
481dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                    BreakpointSP trampolines_changed_bp_sp = target.CreateBreakpoint (changed_addr, true);
482dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                    if (trampolines_changed_bp_sp)
483dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                    {
484dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                        m_trampolines_changed_bp_id = trampolines_changed_bp_sp->GetID();
485dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                        trampolines_changed_bp_sp->SetCallback (RefreshTrampolines, this, true);
486dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                        trampolines_changed_bp_sp->SetBreakpointKind ("objc-trampolines-changed");
487dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                        return true;
488dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                    }
489dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                }
490dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            }
491dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }
492dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
493dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
494dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return false;
495dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
496dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
497dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool
498dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAppleObjCTrampolineHandler::AppleObjCVTables::RefreshTrampolines (void *baton,
499dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                  StoppointCallbackContext *context,
500dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                  lldb::user_id_t break_id,
501dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                  lldb::user_id_t break_loc_id)
502dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{
503dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    AppleObjCVTables *vtable_handler = (AppleObjCVTables *) baton;
504dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (vtable_handler->InitializeVTableSymbols())
505dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {
506dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        // The Update function is called with the address of an added region.  So we grab that address, and
507dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        // feed it into ReadRegions.  Of course, our friend the ABI will get the values for us.
508dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        ExecutionContext exe_ctx (context->exe_ctx_ref);
509dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        Process *process = exe_ctx.GetProcessPtr();
510dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        const ABI *abi = process->GetABI().get();
511dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
512dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        ClangASTContext *clang_ast_context = process->GetTarget().GetScratchClangASTContext();
513dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        ValueList argument_values;
514dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        Value input_value;
515dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
516dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
517dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        input_value.SetValueType (Value::eValueTypeScalar);
518dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        //input_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
519dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        input_value.SetClangType (clang_void_ptr_type);
520dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        argument_values.PushValue(input_value);
521dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
522dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        bool success = abi->GetArgumentValues (exe_ctx.GetThreadRef(), argument_values);
523dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (!success)
524dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            return false;
525dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
526dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        // Now get a pointer value from the zeroth argument.
527dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        Error error;
528dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        DataExtractor data;
529dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        error = argument_values.GetValueAtIndex(0)->GetValueAsData (&exe_ctx,
530dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                    data,
531dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                    0,
532dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                                    NULL);
533dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        lldb::offset_t offset = 0;
534dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        lldb::addr_t region_addr = data.GetPointer(&offset);
535dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
536dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (region_addr != 0)
537dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            vtable_handler->ReadRegions(region_addr);
538dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
539dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return false;
540dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
541dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
542dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool
543dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions ()
544dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{
545dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // The no argument version reads the start region from the value of the gdb_regions_header, and
546dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // gets started from there.
547dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
548dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    m_regions.clear();
549dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (!InitializeVTableSymbols())
550dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        return false;
551dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Error error;
552dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    lldb::addr_t region_addr = m_process_sp->ReadPointerFromMemory (m_trampoline_header, error);
553dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (error.Success())
554dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        return ReadRegions (region_addr);
555dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return false;
556dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
557dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
558dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool
559dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAppleObjCTrampolineHandler::AppleObjCVTables::ReadRegions (lldb::addr_t region_addr)
560dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{
561dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (!m_process_sp)
562dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        return false;
563dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
564dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
565dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
566dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // We aren't starting at the trampoline symbol.
567dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    InitializeVTableSymbols ();
568dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    lldb::addr_t next_region = region_addr;
569dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
570dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // Read in the sizes of the headers.
571dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    while (next_region != 0)
572dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {
573dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        m_regions.push_back (VTableRegion(this, next_region));
574dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (!m_regions.back().IsValid())
575dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {
576dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            m_regions.clear();
577dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            return false;
578dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }
579dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (log)
580dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {
581dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            StreamString s;
582dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            m_regions.back().Dump(s);
583dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            log->Printf("Read vtable region: \n%s", s.GetData());
584dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }
585dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
586dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        next_region = m_regions.back().GetNextRegionAddr();
587dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
588dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
589dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return true;
590dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
591dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
592dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesbool
593dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAppleObjCTrampolineHandler::AppleObjCVTables::IsAddressInVTables (lldb::addr_t addr, uint32_t &flags)
594dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{
595dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    region_collection::iterator pos, end = m_regions.end();
596dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    for (pos = m_regions.begin(); pos != end; pos++)
597dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {
598dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if ((*pos).AddressInRegion (addr, flags))
599dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            return true;
600dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
601dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return false;
602dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
603dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
604dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hinesconst AppleObjCTrampolineHandler::DispatchFunction
605dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAppleObjCTrampolineHandler::g_dispatch_functions[] =
606dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{
607dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // NAME                              STRET  SUPER  SUPER2  FIXUP TYPE
608dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {"objc_msgSend",                     false, false, false, DispatchFunction::eFixUpNone    },
609dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {"objc_msgSend_fixup",               false, false, false, DispatchFunction::eFixUpToFix   },
610dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {"objc_msgSend_fixedup",             false, false, false, DispatchFunction::eFixUpFixed   },
611dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {"objc_msgSend_stret",               true,  false, false, DispatchFunction::eFixUpNone    },
612dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {"objc_msgSend_stret_fixup",         true,  false, false, DispatchFunction::eFixUpToFix   },
613dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {"objc_msgSend_stret_fixedup",       true,  false, false, DispatchFunction::eFixUpFixed   },
614dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {"objc_msgSend_fpret",               false, false, false, DispatchFunction::eFixUpNone    },
61536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {"objc_msgSend_fpret_fixup",         false, false, false, DispatchFunction::eFixUpToFix   },
61636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {"objc_msgSend_fpret_fixedup",       false, false, false, DispatchFunction::eFixUpFixed   },
61736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {"objc_msgSend_fp2ret",              false, false,  true, DispatchFunction::eFixUpNone    },
61836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {"objc_msgSend_fp2ret_fixup",        false, false,  true, DispatchFunction::eFixUpToFix   },
619fcb80cc5656e4672702e3150bfe425f4a58b7a65Bill Wendling    {"objc_msgSend_fp2ret_fixedup",      false, false,  true, DispatchFunction::eFixUpFixed   },
62036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {"objc_msgSendSuper",                false, true,  false, DispatchFunction::eFixUpNone    },
62136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {"objc_msgSendSuper_stret",          true,  true,  false, DispatchFunction::eFixUpNone    },
62236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {"objc_msgSendSuper2",               false, true,   true, DispatchFunction::eFixUpNone    },
62336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {"objc_msgSendSuper2_fixup",         false, true,   true, DispatchFunction::eFixUpToFix   },
62436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {"objc_msgSendSuper2_fixedup",       false, true,   true, DispatchFunction::eFixUpFixed   },
62536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {"objc_msgSendSuper2_stret",         true,  true,   true, DispatchFunction::eFixUpNone    },
626fcb80cc5656e4672702e3150bfe425f4a58b7a65Bill Wendling    {"objc_msgSendSuper2_stret_fixup",   true,  true,   true, DispatchFunction::eFixUpToFix   },
627fcb80cc5656e4672702e3150bfe425f4a58b7a65Bill Wendling    {"objc_msgSendSuper2_stret_fixedup", true,  true,   true, DispatchFunction::eFixUpFixed   },
62836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines};
62936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
630432bdf65719c521206daaf90970505bea027c944Matt ArsenaultAppleObjCTrampolineHandler::AppleObjCTrampolineHandler (const ProcessSP &process_sp,
63136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                                        const ModuleSP &objc_module_sp) :
63236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    m_process_sp (process_sp),
633287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    m_objc_module_sp (objc_module_sp),
63436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    m_impl_fn_addr (LLDB_INVALID_ADDRESS),
63533ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky    m_impl_stret_fn_addr (LLDB_INVALID_ADDRESS),
63633ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky    m_msg_forward_addr (LLDB_INVALID_ADDRESS)
6378246adc1f0e2d28374da3aeab864aee5ff03f3ffDuncan Sands{
63833ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky    // Look up the known resolution functions:
639388f4918fbd8349a6c5b8403e31f65aa3408add6Nick Lewycky
64036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    ConstString get_impl_name("class_getMethodImplementation");
64136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    ConstString get_impl_stret_name("class_getMethodImplementation_stret");
64233ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky    ConstString msg_forward_name("_objc_msgForward");
643287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    ConstString msg_forward_stret_name("_objc_msgForward_stret");
644287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky
645287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    Target *target = m_process_sp ? &m_process_sp->GetTarget() : NULL;
646287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    const Symbol *class_getMethodImplementation = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_name, eSymbolTypeCode);
647287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    const Symbol *class_getMethodImplementation_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (get_impl_stret_name, eSymbolTypeCode);
648287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    const Symbol *msg_forward = m_objc_module_sp->FindFirstSymbolWithNameAndType (msg_forward_name, eSymbolTypeCode);
649287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    const Symbol *msg_forward_stret = m_objc_module_sp->FindFirstSymbolWithNameAndType (msg_forward_stret_name, eSymbolTypeCode);
650287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky
65136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (class_getMethodImplementation)
652287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky        m_impl_fn_addr = class_getMethodImplementation->GetAddress().GetOpcodeLoadAddress (target);
653287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    if  (class_getMethodImplementation_stret)
65436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        m_impl_stret_fn_addr = class_getMethodImplementation_stret->GetAddress().GetOpcodeLoadAddress (target);
65536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (msg_forward)
656287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky        m_msg_forward_addr = msg_forward->GetAddress().GetOpcodeLoadAddress(target);
657287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    if  (msg_forward_stret)
658287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky        m_msg_forward_stret_addr = msg_forward_stret->GetAddress().GetOpcodeLoadAddress(target);
65936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
66036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // FIXME: Do some kind of logging here.
66136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    if (m_impl_fn_addr == LLDB_INVALID_ADDRESS)
66236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {
66336b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        // If we can't even find the ordinary get method implementation function, then we aren't going to be able to
66436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        // step through any method dispatches.  Warn to that effect and get out of here.
66536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        if (process_sp->CanJIT())
66636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        {
66736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            process_sp->GetTarget().GetDebugger().GetErrorStream().Printf("Could not find implementation lookup function \"%s\""
66836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                                                          " step in through ObjC method dispatch will not work.\n",
66936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines                                                                          get_impl_name.AsCString());
67036b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        }
671287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky        return;
67236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
673287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    else if (m_impl_stret_fn_addr == LLDB_INVALID_ADDRESS)
674287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    {
675287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky        // It there is no stret return lookup function, assume that it is the same as the straight lookup:
67636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        m_impl_stret_fn_addr = m_impl_fn_addr;
67736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        // Also we will use the version of the lookup code that doesn't rely on the stret version of the function.
67836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        g_lookup_implementation_function_code = g_lookup_implementation_no_stret_function_code;
67936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    }
680287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    else
68136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {
68236b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        g_lookup_implementation_function_code = g_lookup_implementation_with_stret_function_code;
683287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    }
68436b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
68536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Look up the addresses for the objc dispatch functions and cache them.  For now I'm inspecting the symbol
68636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // names dynamically to figure out how to dispatch to them.  If it becomes more complicated than this we can
68736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // turn the g_dispatch_functions char * array into a template table, and populate the DispatchFunction map
68836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // from there.
68936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
690287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    for (size_t i = 0; i != llvm::array_lengthof(g_dispatch_functions); i++)
69136b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    {
692287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky        ConstString name_const_str(g_dispatch_functions[i].name);
693287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky        const Symbol *msgSend_symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType (name_const_str, eSymbolTypeCode);
694394ce41b7fcb64a35d5cd1c1fefc0e2225ebfc01Nick Lewycky        if (msgSend_symbol)
69536b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines        {
69636b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            // FixMe: Make g_dispatch_functions static table of DispatchFunctions, and have the map be address->index.
69736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            // Problem is we also need to lookup the dispatch function.  For now we could have a side table of stret & non-stret
69836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            // dispatch functions.  If that's as complex as it gets, we're fine.
69936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines
700287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky            lldb::addr_t sym_addr = msgSend_symbol->GetAddress().GetOpcodeLoadAddress(target);
701287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky
702287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky            m_msgSend_map.insert(std::pair<lldb::addr_t, int>(sym_addr, i));
703287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky        }
704468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky    }
705468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky
706468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky    // Build our vtable dispatch handler here:
707dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    m_vtables_ap.reset(new AppleObjCVTables(process_sp, m_objc_module_sp));
708dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (m_vtables_ap.get())
709dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        m_vtables_ap->ReadRegions();
71039c33e3b6344be1d1cc35ad9fb1b647fd8adfe65Nick Lewycky}
71139c33e3b6344be1d1cc35ad9fb1b647fd8adfe65Nick Lewycky
71239c33e3b6344be1d1cc35ad9fb1b647fd8adfe65Nick Lewyckylldb::addr_t
71339c33e3b6344be1d1cc35ad9fb1b647fd8adfe65Nick LewyckyAppleObjCTrampolineHandler::SetupDispatchFunction (Thread &thread, ValueList &dispatch_values)
714dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{
715dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    ExecutionContext exe_ctx (thread.shared_from_this());
716dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Address impl_code_address;
717dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    StreamString errors;
718dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
719dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    lldb::addr_t args_addr = LLDB_INVALID_ADDRESS;
720dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
721dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // Scope for mutex locker:
722dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {
723dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        Mutex::Locker locker(m_impl_function_mutex);
724dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
725dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        // First stage is to make the ClangUtility to hold our injected function:
726287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky
727287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky    #define USE_BUILTIN_FUNCTION 0  // Define this to 1 and we will use the get_implementation function found in the target.
728287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky                        // This is useful for debugging additions to the get_impl function 'cause you don't have
729dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                        // to bother with string-ifying the code into g_lookup_implementation_function_code.
730dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
731dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (USE_BUILTIN_FUNCTION)
732dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {
733dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            ConstString our_utility_function_name("__lldb_objc_find_implementation_for_selector");
734287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky            SymbolContextList sc_list;
735287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky
736dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            exe_ctx.GetTargetRef().GetImages().FindSymbolsWithNameAndType (our_utility_function_name, eSymbolTypeCode, sc_list);
737dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            if (sc_list.GetSize() == 1)
738dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            {
739dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                SymbolContext sc;
740dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                sc_list.GetContextAtIndex(0, sc);
741dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                if (sc.symbol != NULL)
742dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                    impl_code_address = sc.symbol->GetAddress();
743dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
744dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                //lldb::addr_t addr = impl_code_address.GetOpcodeLoadAddress (exe_ctx.GetTargetPtr());
745cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                //printf ("Getting address for our_utility_function: 0x%" PRIx64 ".\n", addr);
746cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            }
747cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            else
748cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            {
749cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                //printf ("Could not find implementation function address.\n");
750dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                return args_addr;
751dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            }
752dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }
753dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        else if (!m_impl_code.get())
754dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {
755dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            if (g_lookup_implementation_function_code != NULL)
756dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            {
757dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                m_impl_code.reset (new ClangUtilityFunction (g_lookup_implementation_function_code,
758dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                             g_lookup_implementation_function_name));
759dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                if (!m_impl_code->Install(errors, exe_ctx))
760dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                {
761dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                    if (log)
762dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                        log->Printf ("Failed to install implementation lookup: %s.", errors.GetData());
763dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                    m_impl_code.reset();
764dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                    return args_addr;
765dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                }
766dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            }
767dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            else
768dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            {
769dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                if (log)
770dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                    log->Printf("No method lookup implementation code.");
771dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                errors.Printf ("No method lookup implementation code found.");
772dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                return LLDB_INVALID_ADDRESS;
773dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            }
774dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
775dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            impl_code_address.Clear();
776dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            impl_code_address.SetOffset(m_impl_code->StartAddress());
777dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }
778dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        else
779dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {
780dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            impl_code_address.Clear();
781dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            impl_code_address.SetOffset(m_impl_code->StartAddress());
782dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }
783dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
784dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        // Next make the runner function for our implementation utility function.
785dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (!m_impl_function.get())
786dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {
787dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            ClangASTContext *clang_ast_context = thread.GetProcess()->GetTarget().GetScratchClangASTContext();
788dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
789dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            m_impl_function.reset(new ClangFunction (thread,
790dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                     clang_void_ptr_type,
791dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                     impl_code_address,
792dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                                                     dispatch_values));
793dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
794dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            errors.Clear();
795dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            unsigned num_errors = m_impl_function->CompileFunction(errors);
796dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            if (num_errors)
797dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            {
798dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                if (log)
799dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                    log->Printf ("Error compiling function: \"%s\".", errors.GetData());
800dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                return args_addr;
801dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            }
802dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
803287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky            errors.Clear();
804dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            if (!m_impl_function->WriteFunctionWrapper(exe_ctx, errors))
805dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            {
806dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                if (log)
807dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                    log->Printf ("Error Inserting function: \"%s\".", errors.GetData());
808cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                return args_addr;
809cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            }
810cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        }
811dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
812dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
813dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    errors.Clear();
814dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
815dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // Now write down the argument values for this particular call.  This looks like it might be a race condition
816dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // if other threads were calling into here, but actually it isn't because we allocate a new args structure for
817dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // this call by passing args_addr = LLDB_INVALID_ADDRESS...
818dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
819dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (!m_impl_function->WriteFunctionArguments (exe_ctx, args_addr, impl_code_address, dispatch_values, errors))
820dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {
821dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (log)
822dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            log->Printf ("Error writing function arguments: \"%s\".", errors.GetData());
823dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        return args_addr;
824dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
825dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
826dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    return args_addr;
827dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines}
828dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
829dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesThreadPlanSP
830dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen HinesAppleObjCTrampolineHandler::GetStepThroughDispatchPlan (Thread &thread, bool stop_others)
831dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines{
832dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    ThreadPlanSP ret_plan_sp;
833dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    lldb::addr_t curr_pc = thread.GetRegisterContext()->GetPC();
834579a0246616d76bc536de0e41edf069d091604beNick Lewycky
835579a0246616d76bc536de0e41edf069d091604beNick Lewycky    DispatchFunction this_dispatch;
836468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky    bool found_it = false;
837dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
838dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // First step is to look and see if we are in one of the known ObjC dispatch functions.  We've already compiled
839dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    // a table of same, so consult it.
840dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
841dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    MsgsendMap::iterator pos;
842dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    pos = m_msgSend_map.find (curr_pc);
843432bdf65719c521206daaf90970505bea027c944Matt Arsenault    if (pos != m_msgSend_map.end())
844dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {
845dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        this_dispatch = g_dispatch_functions[(*pos).second];
846dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        found_it = true;
847dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    }
848dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
84936b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines    // Next check to see if we are in a vtable region:
850dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
851dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (!found_it)
852dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    {
853dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        uint32_t flags;
854dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (m_vtables_ap.get())
85533ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky        {
856579a0246616d76bc536de0e41edf069d091604beNick Lewycky            found_it = m_vtables_ap->IsAddressInVTables (curr_pc, flags);
857dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            if (found_it)
858dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            {
859dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                this_dispatch.name = "vtable";
860579a0246616d76bc536de0e41edf069d091604beNick Lewycky                this_dispatch.stret_return
861dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                        = (flags & AppleObjCVTables::eOBJC_TRAMPOLINE_STRET) == AppleObjCVTables::eOBJC_TRAMPOLINE_STRET;
862dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                this_dispatch.is_super = false;
863579a0246616d76bc536de0e41edf069d091604beNick Lewycky                this_dispatch.is_super2 = false;
864dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                this_dispatch.fixedup = DispatchFunction::eFixUpFixed;
865dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            }
866dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }
867579a0246616d76bc536de0e41edf069d091604beNick Lewycky    }
868579a0246616d76bc536de0e41edf069d091604beNick Lewycky
869dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines    if (found_it)
870579a0246616d76bc536de0e41edf069d091604beNick Lewycky    {
871579a0246616d76bc536de0e41edf069d091604beNick Lewycky        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_STEP));
872dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
873dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        // We are decoding a method dispatch.
874dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        // First job is to pull the arguments out:
875dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
876dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        lldb::StackFrameSP thread_cur_frame = thread.GetStackFrameAtIndex(0);
877dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
878cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        const ABI *abi = NULL;
879cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        ProcessSP process_sp (thread.CalculateProcess());
880dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (process_sp)
881dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            abi = process_sp->GetABI().get();
882dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (abi == NULL)
883cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            return ret_plan_sp;
884cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
885dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        TargetSP target_sp (thread.CalculateTarget());
886dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
887dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        ClangASTContext *clang_ast_context = target_sp->GetScratchClangASTContext();
888579a0246616d76bc536de0e41edf069d091604beNick Lewycky        ValueList argument_values;
889dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        Value void_ptr_value;
890dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        ClangASTType clang_void_ptr_type = clang_ast_context->GetBasicType(eBasicTypeVoid).GetPointerType();
891dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        void_ptr_value.SetValueType (Value::eValueTypeScalar);
892dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        //void_ptr_value.SetContext (Value::eContextTypeClangType, clang_void_ptr_type);
893dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        void_ptr_value.SetClangType (clang_void_ptr_type);
894dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
895dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        int obj_index;
896dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        int sel_index;
897dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
898dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        // If this is a struct return dispatch, then the first argument is the
899dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        // return struct pointer, and the object is the second, and the selector is the third.
900dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        // Otherwise the object is the first and the selector the second.
901dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        if (this_dispatch.stret_return)
902dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {
903dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            obj_index = 1;
904dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            sel_index = 2;
905dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            argument_values.PushValue(void_ptr_value);
906dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            argument_values.PushValue(void_ptr_value);
907dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            argument_values.PushValue(void_ptr_value);
908dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }
909dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        else
910dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        {
911dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            obj_index = 0;
912dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            sel_index = 1;
913dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines            argument_values.PushValue(void_ptr_value);
91433ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky            argument_values.PushValue(void_ptr_value);
915dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines        }
916dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines
917468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky
918cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        bool success = abi->GetArgumentValues (thread, argument_values);
919cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (!success)
920cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            return ret_plan_sp;
921579a0246616d76bc536de0e41edf069d091604beNick Lewycky
92233ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky        lldb::addr_t obj_addr = argument_values.GetValueAtIndex(obj_index)->GetScalar().ULongLong();
923cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (obj_addr == 0x0)
924cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        {
925579a0246616d76bc536de0e41edf069d091604beNick Lewycky            if (log)
926cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                log->Printf("Asked to step to dispatch to nil object, returning empty plan.");
927cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            return ret_plan_sp;
928579a0246616d76bc536de0e41edf069d091604beNick Lewycky        }
929cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
930cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        ExecutionContext exe_ctx (thread.shared_from_this());
931cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        Process *process = exe_ctx.GetProcessPtr();
932cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        // isa_addr will store the class pointer that the method is being dispatched to - so either the class
933579a0246616d76bc536de0e41edf069d091604beNick Lewycky        // directly or the super class if this is one of the objc_msgSendSuper flavors.  That's mostly used to
934cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        // look up the class/selector pair in our cache.
935cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
936cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        lldb::addr_t isa_addr = LLDB_INVALID_ADDRESS;
937cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        lldb::addr_t sel_addr = argument_values.GetValueAtIndex(sel_index)->GetScalar().ULongLong();
938cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
939cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        // Figure out the class this is being dispatched to and see if we've already cached this method call,
94033ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky        // If so we can push a run-to-address plan directly.  Otherwise we have to figure out where
941cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        // the implementation lives.
942cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
943cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (this_dispatch.is_super)
94433ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky        {
945cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            if (this_dispatch.is_super2)
946cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            {
947cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines               // In the objc_msgSendSuper2 case, we don't get the object directly, we get a structure containing
948cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines               // the object and the class to which the super message is being sent.  So we need to dig the super
949cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines               // out of the class and use that.
950cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
951cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
952cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                super_value.GetScalar() += process->GetAddressByteSize();
953cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                super_value.ResolveValue (&exe_ctx);
954cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
955579a0246616d76bc536de0e41edf069d091604beNick Lewycky                if (super_value.GetScalar().IsValid())
956579a0246616d76bc536de0e41edf069d091604beNick Lewycky                {
957579a0246616d76bc536de0e41edf069d091604beNick Lewycky
958cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                    // isa_value now holds the class pointer.  The second word of the class pointer is the super-class pointer:
959cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                    super_value.GetScalar() += process->GetAddressByteSize();
960579a0246616d76bc536de0e41edf069d091604beNick Lewycky                    super_value.ResolveValue (&exe_ctx);
961cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                    if (super_value.GetScalar().IsValid())
962cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                        isa_addr = super_value.GetScalar().ULongLong();
963cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                    else
964cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                    {
965cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                       if (log)
966579a0246616d76bc536de0e41edf069d091604beNick Lewycky                        log->Printf("Failed to extract the super class value from the class in objc_super.");
967579a0246616d76bc536de0e41edf069d091604beNick Lewycky                    }
968468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky                }
969cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                else
970579a0246616d76bc536de0e41edf069d091604beNick Lewycky                {
971dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                   if (log)
972dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                    log->Printf("Failed to extract the class value from objc_super.");
973dce4a407a24b04eebc6a376f8e62b41aaa7b071fStephen Hines                }
974cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            }
975cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            else
976579a0246616d76bc536de0e41edf069d091604beNick Lewycky            {
977cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines               // In the objc_msgSendSuper case, we don't get the object directly, we get a two element structure containing
978cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines               // the object and the super class to which the super message is being sent.  So the class we want is
979579a0246616d76bc536de0e41edf069d091604beNick Lewycky               // the second element of this structure.
980cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
981cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                Value super_value(*(argument_values.GetValueAtIndex(obj_index)));
982cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                super_value.GetScalar() += process->GetAddressByteSize();
983cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                super_value.ResolveValue (&exe_ctx);
984579a0246616d76bc536de0e41edf069d091604beNick Lewycky
985cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                if (super_value.GetScalar().IsValid())
986cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                {
987579a0246616d76bc536de0e41edf069d091604beNick Lewycky                    isa_addr = super_value.GetScalar().ULongLong();
988cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                }
989cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                else
990cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                {
991cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                   if (log)
992579a0246616d76bc536de0e41edf069d091604beNick Lewycky                    log->Printf("Failed to extract the class value from objc_super.");
993cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                }
994cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            }
995287de607dc3e05aa287edf4e3b6aa29e6c4517c9Nick Lewycky        }
996579a0246616d76bc536de0e41edf069d091604beNick Lewycky        else
997579a0246616d76bc536de0e41edf069d091604beNick Lewycky        {
998cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            // In the direct dispatch case, the object->isa is the class pointer we want.
999cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
1000579a0246616d76bc536de0e41edf069d091604beNick Lewycky            // This is a little cheesy, but since object->isa is the first field,
1001cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            // making the object value a load address value and resolving it will get
1002cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            // the pointer sized data pointed to by that value...
1003579a0246616d76bc536de0e41edf069d091604beNick Lewycky
1004cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            // Note, it isn't a fatal error not to be able to get the address from the object, since this might
10052b6c01b40b75e363e46b3ad7c598113eb98f34fbNick Lewycky            // be a "tagged pointer" which isn't a real object, but rather some word length encoded dingus.
1006579a0246616d76bc536de0e41edf069d091604beNick Lewycky
100733ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky            Value isa_value(*(argument_values.GetValueAtIndex(obj_index)));
100833ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky
1009cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            isa_value.SetValueType(Value::eValueTypeLoadAddress);
1010cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            isa_value.ResolveValue(&exe_ctx);
1011cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            if (isa_value.GetScalar().IsValid())
1012cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            {
1013cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                isa_addr = isa_value.GetScalar().ULongLong();
10142b6c01b40b75e363e46b3ad7c598113eb98f34fbNick Lewycky            }
101533ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky            else
1016579a0246616d76bc536de0e41edf069d091604beNick Lewycky            {
1017be04fdeb6c46e92fdeda7535c5912d072eff008cNick Lewycky               if (log)
1018be04fdeb6c46e92fdeda7535c5912d072eff008cNick Lewycky                log->Printf("Failed to extract the isa value from object.");
101978d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky            }
102078d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky
1021cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        }
102278d4330fd83a94707b345e19f5277e7a46892689Nick Lewycky
1023c9dcbed6a39f3aa2562de070bb15670d81c38650Nick Lewycky        // Okay, we've got the address of the class for which we're resolving this, let's see if it's in our cache:
1024cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        lldb::addr_t impl_addr = LLDB_INVALID_ADDRESS;
1025cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
1026c9dcbed6a39f3aa2562de070bb15670d81c38650Nick Lewycky        if (isa_addr != LLDB_INVALID_ADDRESS)
1027cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        {
1028cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            if (log)
1029cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            {
1030cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                log->Printf("Resolving call for class - 0x%" PRIx64 " and selector - 0x%" PRIx64,
1031c9dcbed6a39f3aa2562de070bb15670d81c38650Nick Lewycky                            isa_addr, sel_addr);
1032cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            }
1033cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            ObjCLanguageRuntime *objc_runtime = m_process_sp->GetObjCLanguageRuntime ();
1034cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            assert(objc_runtime != NULL);
1035cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
1036cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            impl_addr = objc_runtime->LookupInMethodCache (isa_addr, sel_addr);
1037c9dcbed6a39f3aa2562de070bb15670d81c38650Nick Lewycky        }
1038cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
1039cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        if (impl_addr != LLDB_INVALID_ADDRESS)
1040c9dcbed6a39f3aa2562de070bb15670d81c38650Nick Lewycky        {
1041cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            // Yup, it was in the cache, so we can run to that address directly.
1042cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
1043cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            if (log)
1044911ae391e85ead1bb11895562a6bbdb2c0f8ebd2Nick Lewycky                log->Printf ("Found implementation address in cache: 0x%" PRIx64, impl_addr);
1045c9dcbed6a39f3aa2562de070bb15670d81c38650Nick Lewycky
1046cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            ret_plan_sp.reset (new ThreadPlanRunToAddress (thread, impl_addr, stop_others));
1047cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        }
104833ab0b15689abd32f72a5417cd104bde19f4b4aaNick Lewycky        else
1049579a0246616d76bc536de0e41edf069d091604beNick Lewycky        {
1050cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            // We haven't seen this class/selector pair yet.  Look it up.
1051579a0246616d76bc536de0e41edf069d091604beNick Lewycky            StreamString errors;
1052579a0246616d76bc536de0e41edf069d091604beNick Lewycky            Address impl_code_address;
1053285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky
1054285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            ValueList dispatch_values;
1055285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky
1056285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            // We've will inject a little function in the target that takes the object, selector and some flags,
1057285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            // and figures out the implementation.  Looks like:
1058285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            //      void *__lldb_objc_find_implementation_for_selector (void *object,
1059285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            //                                                          void *sel,
1060285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            //                                                          int is_stret,
1061285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            //                                                          int is_super,
1062285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            //                                                          int is_super2,
1063285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            //                                                          int is_fixup,
1064285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            //                                                          int is_fixed,
1065285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            //                                                          int debug)
1066285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            // So set up the arguments for that call.
1067285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky
106836b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            dispatch_values.PushValue (*(argument_values.GetValueAtIndex(obj_index)));
1069285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            dispatch_values.PushValue (*(argument_values.GetValueAtIndex(sel_index)));
1070285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky
1071cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            Value flag_value;
1072285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            ClangASTType clang_int_type = clang_ast_context->GetBuiltinTypeForEncodingAndBitSize(lldb::eEncodingSint, 32);
1073285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            flag_value.SetValueType (Value::eValueTypeScalar);
1074285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            //flag_value.SetContext (Value::eContextTypeClangType, clang_int_type);
1075285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            flag_value.SetClangType (clang_int_type);
1076285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky
1077cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            if (this_dispatch.stret_return)
1078cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                flag_value.GetScalar() = 1;
1079cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            else
1080cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                flag_value.GetScalar() = 0;
1081cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            dispatch_values.PushValue (flag_value);
1082285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky
1083cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            if (this_dispatch.is_super)
1084285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky                flag_value.GetScalar() = 1;
1085cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            else
1086285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky                flag_value.GetScalar() = 0;
1087468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky            dispatch_values.PushValue (flag_value);
1088285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky
1089cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            if (this_dispatch.is_super2)
1090285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky                flag_value.GetScalar() = 1;
1091468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky            else
1092285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky                flag_value.GetScalar() = 0;
1093285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            dispatch_values.PushValue (flag_value);
1094285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky
1095285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            switch (this_dispatch.fixedup)
1096285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            {
1097468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky              case DispatchFunction::eFixUpNone:
1098468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky                 flag_value.GetScalar() = 0;
1099468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky                 dispatch_values.PushValue (flag_value);
1100468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky                 dispatch_values.PushValue (flag_value);
1101285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky                 break;
1102468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky              case DispatchFunction::eFixUpFixed:
1103468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky                 flag_value.GetScalar() = 1;
1104285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky                 dispatch_values.PushValue (flag_value);
1105468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky                 flag_value.GetScalar() = 1;
1106468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky                 dispatch_values.PushValue (flag_value);
1107468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky                 break;
1108285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky              case DispatchFunction::eFixUpToFix:
1109468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky                 flag_value.GetScalar() = 1;
1110468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky                 dispatch_values.PushValue (flag_value);
1111285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky                 flag_value.GetScalar() = 0;
1112468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky                 dispatch_values.PushValue (flag_value);
1113468ee0a90db9ee7367bd163fcc3cb5b867753385Nick Lewycky                 break;
1114cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            }
1115285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            if (log && log->GetVerbose())
11163574eca1b02600bac4e625297f4ecf745f4c4f32Micah Villmow                flag_value.GetScalar() = 1;
111736b56886974eae4f9c5ebc96befd3e7bfe5de338Stephen Hines            else
1118285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky                flag_value.GetScalar() = 0;  // FIXME - Set to 0 when debugging is done.
1119285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            dispatch_values.PushValue (flag_value);
1120285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky
1121285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky
1122285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            // The step through code might have to fill in the cache, so it is not safe to run only one thread.
1123285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            // So we override the stop_others value passed in to us here:
1124285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            const bool trampoline_stop_others = false;
1125285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            ret_plan_sp.reset (new AppleThreadPlanStepThroughObjCTrampoline (thread,
1126285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky                                                                             this,
1127285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky                                                                             dispatch_values,
1128285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky                                                                             isa_addr,
1129285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky                                                                             sel_addr,
1130285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky                                                                             trampoline_stop_others));
1131285cf8040da6245d5dbc9ebfac8a8caf3647caf4Nick Lewycky            if (log)
1132cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            {
1133cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                StreamString s;
1134cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                ret_plan_sp->GetDescription(&s, eDescriptionLevelFull);
1135cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines                log->Printf("Using ObjC step plan: %s.\n", s.GetData());
1136cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines            }
1137cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines        }
1138cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    }
1139cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
1140cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return ret_plan_sp;
1141cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
1142cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines
1143cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesClangFunction *
1144cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen HinesAppleObjCTrampolineHandler::GetLookupImplementationWrapperFunction ()
1145cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines{
1146cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines    return m_impl_function.get();
1147cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines}
1148cd81d94322a39503e4a3e87b6ee03d4fcb3465fbStephen Hines