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