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 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 { 70 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: 79 VTableRegion() = default; 80 81 VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr); 82 83 void SetUpRegion(); 84 85 lldb::addr_t GetNextRegionAddr() { return m_next_region; } 86 87 lldb::addr_t GetCodeStart() { return m_code_start_addr; } 88 89 lldb::addr_t GetCodeEnd() { return m_code_end_addr; } 90 91 uint32_t GetFlagsForVTableAtAddress(lldb::addr_t address) { return 0; } 92 93 bool IsValid() { return m_valid; } 94 95 bool AddressInRegion(lldb::addr_t addr, uint32_t &flags); 96 97 void Dump(Stream &s); 98 99 bool m_valid = false; 100 AppleObjCVTables *m_owner = nullptr; 101 lldb::addr_t m_header_addr = LLDB_INVALID_ADDRESS; 102 lldb::addr_t m_code_start_addr = 0; 103 lldb::addr_t m_code_end_addr = 0; 104 std::vector<VTableDescriptor> m_descriptors; 105 lldb::addr_t m_next_region = 0; 106 }; 107 108 public: 109 AppleObjCVTables(const lldb::ProcessSP &process_sp, 110 const lldb::ModuleSP &objc_module_sp); 111 112 ~AppleObjCVTables(); 113 114 bool InitializeVTableSymbols(); 115 116 static bool RefreshTrampolines(void *baton, 117 StoppointCallbackContext *context, 118 lldb::user_id_t break_id, 119 lldb::user_id_t break_loc_id); 120 bool ReadRegions(); 121 122 bool ReadRegions(lldb::addr_t region_addr); 123 124 bool IsAddressInVTables(lldb::addr_t addr, uint32_t &flags); 125 126 lldb::ProcessSP GetProcessSP() { return m_process_wp.lock(); } 127 128 private: 129 lldb::ProcessWP m_process_wp; 130 typedef std::vector<VTableRegion> region_collection; 131 lldb::addr_t m_trampoline_header; 132 lldb::break_id_t m_trampolines_changed_bp_id; 133 region_collection m_regions; 134 lldb::ModuleSP m_objc_module_sp; 135 }; 136 137 static const DispatchFunction g_dispatch_functions[]; 138 static const char *g_opt_dispatch_names[]; 139 140 using MsgsendMap = std::map<lldb::addr_t, int>; // This table maps an dispatch 141 // fn address to the index in 142 // g_dispatch_functions 143 MsgsendMap m_msgSend_map; 144 MsgsendMap m_opt_dispatch_map; 145 lldb::ProcessWP m_process_wp; 146 lldb::ModuleSP m_objc_module_sp; 147 const char *m_lookup_implementation_function_code; 148 std::unique_ptr<UtilityFunction> m_impl_code; 149 std::mutex m_impl_function_mutex; 150 lldb::addr_t m_impl_fn_addr; 151 lldb::addr_t m_impl_stret_fn_addr; 152 lldb::addr_t m_msg_forward_addr; 153 lldb::addr_t m_msg_forward_stret_addr; 154 std::unique_ptr<AppleObjCVTables> m_vtables_up; 155 }; 156 157 } // namespace lldb_private 158 159 #endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCTRAMPOLINEHANDLER_H 160