1 //===-- AppleObjCTrampolineHandler.h ----------------------------*- C++ -*-===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCTRAMPOLINEHANDLER_H 10 #define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCTRAMPOLINEHANDLER_H 11 12 #include <map> 13 #include <mutex> 14 #include <vector> 15 16 #include "lldb/Expression/UtilityFunction.h" 17 #include "lldb/lldb-public.h" 18 19 namespace lldb_private { 20 21 class AppleObjCTrampolineHandler { 22 public: 23 AppleObjCTrampolineHandler(const lldb::ProcessSP &process_sp, 24 const lldb::ModuleSP &objc_module_sp); 25 26 ~AppleObjCTrampolineHandler(); 27 28 lldb::ThreadPlanSP GetStepThroughDispatchPlan(Thread &thread, 29 bool stop_others); 30 31 FunctionCaller *GetLookupImplementationFunctionCaller(); 32 AddrIsMsgForward(lldb::addr_t addr)33 bool AddrIsMsgForward(lldb::addr_t addr) const { 34 return (addr == m_msg_forward_addr || addr == m_msg_forward_stret_addr); 35 } 36 37 struct DispatchFunction { 38 public: 39 enum FixUpState { eFixUpNone, eFixUpFixed, eFixUpToFix }; 40 41 const char *name; 42 bool stret_return; 43 bool is_super; 44 bool is_super2; 45 FixUpState fixedup; 46 }; 47 48 lldb::addr_t SetupDispatchFunction(Thread &thread, 49 ValueList &dispatch_values); 50 const DispatchFunction *FindDispatchFunction(lldb::addr_t addr); 51 void ForEachDispatchFunction(std::function<void(lldb::addr_t, 52 const DispatchFunction &)>); 53 54 private: 55 static const char *g_lookup_implementation_function_name; 56 static const char *g_lookup_implementation_with_stret_function_code; 57 static const char *g_lookup_implementation_no_stret_function_code; 58 59 class AppleObjCVTables { 60 public: 61 // These come from objc-gdb.h. 62 enum VTableFlags { 63 eOBJC_TRAMPOLINE_MESSAGE = (1 << 0), // trampoline acts like objc_msgSend 64 eOBJC_TRAMPOLINE_STRET = (1 << 1), // trampoline is struct-returning 65 eOBJC_TRAMPOLINE_VTABLE = (1 << 2) // trampoline is vtable dispatcher 66 }; 67 68 private: 69 struct VTableDescriptor { VTableDescriptorVTableDescriptor70 VTableDescriptor(uint32_t in_flags, lldb::addr_t in_code_start) 71 : flags(in_flags), code_start(in_code_start) {} 72 73 uint32_t flags; 74 lldb::addr_t code_start; 75 }; 76 77 class VTableRegion { 78 public: VTableRegion()79 VTableRegion() 80 : m_valid(false), m_owner(nullptr), 81 m_header_addr(LLDB_INVALID_ADDRESS), m_code_start_addr(0), 82 m_code_end_addr(0), m_next_region(0) {} 83 84 VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr); 85 86 void SetUpRegion(); 87 GetNextRegionAddr()88 lldb::addr_t GetNextRegionAddr() { return m_next_region; } 89 GetCodeStart()90 lldb::addr_t GetCodeStart() { return m_code_start_addr; } 91 GetCodeEnd()92 lldb::addr_t GetCodeEnd() { return m_code_end_addr; } 93 GetFlagsForVTableAtAddress(lldb::addr_t address)94 uint32_t GetFlagsForVTableAtAddress(lldb::addr_t address) { return 0; } 95 IsValid()96 bool IsValid() { return m_valid; } 97 98 bool AddressInRegion(lldb::addr_t addr, uint32_t &flags); 99 100 void Dump(Stream &s); 101 102 bool m_valid; 103 AppleObjCVTables *m_owner; 104 lldb::addr_t m_header_addr; 105 lldb::addr_t m_code_start_addr; 106 lldb::addr_t m_code_end_addr; 107 std::vector<VTableDescriptor> m_descriptors; 108 lldb::addr_t m_next_region; 109 }; 110 111 public: 112 AppleObjCVTables(const lldb::ProcessSP &process_sp, 113 const lldb::ModuleSP &objc_module_sp); 114 115 ~AppleObjCVTables(); 116 117 bool InitializeVTableSymbols(); 118 119 static bool RefreshTrampolines(void *baton, 120 StoppointCallbackContext *context, 121 lldb::user_id_t break_id, 122 lldb::user_id_t break_loc_id); 123 bool ReadRegions(); 124 125 bool ReadRegions(lldb::addr_t region_addr); 126 127 bool IsAddressInVTables(lldb::addr_t addr, uint32_t &flags); 128 GetProcessSP()129 lldb::ProcessSP GetProcessSP() { return m_process_wp.lock(); } 130 131 private: 132 lldb::ProcessWP m_process_wp; 133 typedef std::vector<VTableRegion> region_collection; 134 lldb::addr_t m_trampoline_header; 135 lldb::break_id_t m_trampolines_changed_bp_id; 136 region_collection m_regions; 137 lldb::ModuleSP m_objc_module_sp; 138 }; 139 140 static const DispatchFunction g_dispatch_functions[]; 141 static const char *g_opt_dispatch_names[]; 142 143 using MsgsendMap = std::map<lldb::addr_t, int>; // This table maps an dispatch 144 // fn address to the index in 145 // g_dispatch_functions 146 MsgsendMap m_msgSend_map; 147 MsgsendMap m_opt_dispatch_map; 148 lldb::ProcessWP m_process_wp; 149 lldb::ModuleSP m_objc_module_sp; 150 const char *m_lookup_implementation_function_code; 151 std::unique_ptr<UtilityFunction> m_impl_code; 152 std::mutex m_impl_function_mutex; 153 lldb::addr_t m_impl_fn_addr; 154 lldb::addr_t m_impl_stret_fn_addr; 155 lldb::addr_t m_msg_forward_addr; 156 lldb::addr_t m_msg_forward_stret_addr; 157 std::unique_ptr<AppleObjCVTables> m_vtables_up; 158 }; 159 160 } // namespace lldb_private 161 162 #endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCTRAMPOLINEHANDLER_H 163