1061da546Spatrick //===-- AppleObjCTrampolineHandler.h ----------------------------*- C++ -*-===// 2061da546Spatrick // 3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information. 5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6061da546Spatrick // 7061da546Spatrick //===----------------------------------------------------------------------===// 8061da546Spatrick 9dda28197Spatrick #ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCTRAMPOLINEHANDLER_H 10dda28197Spatrick #define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCTRAMPOLINEHANDLER_H 11061da546Spatrick 12061da546Spatrick #include <map> 13061da546Spatrick #include <mutex> 14061da546Spatrick #include <vector> 15061da546Spatrick 16061da546Spatrick #include "lldb/Expression/UtilityFunction.h" 17061da546Spatrick #include "lldb/lldb-public.h" 18061da546Spatrick 19061da546Spatrick namespace lldb_private { 20061da546Spatrick 21061da546Spatrick class AppleObjCTrampolineHandler { 22061da546Spatrick public: 23061da546Spatrick AppleObjCTrampolineHandler(const lldb::ProcessSP &process_sp, 24061da546Spatrick const lldb::ModuleSP &objc_module_sp); 25061da546Spatrick 26061da546Spatrick ~AppleObjCTrampolineHandler(); 27061da546Spatrick 28061da546Spatrick lldb::ThreadPlanSP GetStepThroughDispatchPlan(Thread &thread, 29061da546Spatrick bool stop_others); 30061da546Spatrick 31061da546Spatrick FunctionCaller *GetLookupImplementationFunctionCaller(); 32061da546Spatrick AddrIsMsgForward(lldb::addr_t addr)33061da546Spatrick bool AddrIsMsgForward(lldb::addr_t addr) const { 34061da546Spatrick return (addr == m_msg_forward_addr || addr == m_msg_forward_stret_addr); 35061da546Spatrick } 36061da546Spatrick 37061da546Spatrick struct DispatchFunction { 38061da546Spatrick public: 39061da546Spatrick enum FixUpState { eFixUpNone, eFixUpFixed, eFixUpToFix }; 40061da546Spatrick 41*f6aab3d8Srobert const char *name = nullptr; 42*f6aab3d8Srobert bool stret_return = false; 43*f6aab3d8Srobert bool is_super = false; 44*f6aab3d8Srobert bool is_super2 = false; 45*f6aab3d8Srobert FixUpState fixedup = eFixUpNone; 46061da546Spatrick }; 47061da546Spatrick 48061da546Spatrick lldb::addr_t SetupDispatchFunction(Thread &thread, 49061da546Spatrick ValueList &dispatch_values); 50dda28197Spatrick const DispatchFunction *FindDispatchFunction(lldb::addr_t addr); 51dda28197Spatrick void ForEachDispatchFunction(std::function<void(lldb::addr_t, 52dda28197Spatrick const DispatchFunction &)>); 53061da546Spatrick 54061da546Spatrick private: 55*f6aab3d8Srobert /// These hold the code for the function that finds the implementation of 56*f6aab3d8Srobert /// an ObjC message send given the class & selector and the kind of dispatch. 57*f6aab3d8Srobert /// There are two variants depending on whether the platform uses a separate 58*f6aab3d8Srobert /// _stret passing convention (e.g. Intel) or not (e.g. ARM). The difference 59*f6aab3d8Srobert /// is only at the very end of the function, so the code is broken into the 60*f6aab3d8Srobert /// common prefix and the suffix, which get composed appropriately before 61*f6aab3d8Srobert /// the function gets compiled. 62*f6aab3d8Srobert /// \{ 63061da546Spatrick static const char *g_lookup_implementation_function_name; 64*f6aab3d8Srobert static const char *g_lookup_implementation_function_common_code; 65061da546Spatrick static const char *g_lookup_implementation_with_stret_function_code; 66061da546Spatrick static const char *g_lookup_implementation_no_stret_function_code; 67*f6aab3d8Srobert /// \} 68061da546Spatrick 69061da546Spatrick class AppleObjCVTables { 70061da546Spatrick public: 71061da546Spatrick // These come from objc-gdb.h. 72061da546Spatrick enum VTableFlags { 73061da546Spatrick eOBJC_TRAMPOLINE_MESSAGE = (1 << 0), // trampoline acts like objc_msgSend 74061da546Spatrick eOBJC_TRAMPOLINE_STRET = (1 << 1), // trampoline is struct-returning 75061da546Spatrick eOBJC_TRAMPOLINE_VTABLE = (1 << 2) // trampoline is vtable dispatcher 76061da546Spatrick }; 77061da546Spatrick 78061da546Spatrick private: 79061da546Spatrick struct VTableDescriptor { VTableDescriptorVTableDescriptor80061da546Spatrick VTableDescriptor(uint32_t in_flags, lldb::addr_t in_code_start) 81061da546Spatrick : flags(in_flags), code_start(in_code_start) {} 82061da546Spatrick 83061da546Spatrick uint32_t flags; 84061da546Spatrick lldb::addr_t code_start; 85061da546Spatrick }; 86061da546Spatrick 87061da546Spatrick class VTableRegion { 88061da546Spatrick public: 89be691f3bSpatrick VTableRegion() = default; 90061da546Spatrick 91061da546Spatrick VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr); 92061da546Spatrick 93061da546Spatrick void SetUpRegion(); 94061da546Spatrick GetNextRegionAddr()95061da546Spatrick lldb::addr_t GetNextRegionAddr() { return m_next_region; } 96061da546Spatrick GetCodeStart()97061da546Spatrick lldb::addr_t GetCodeStart() { return m_code_start_addr; } 98061da546Spatrick GetCodeEnd()99061da546Spatrick lldb::addr_t GetCodeEnd() { return m_code_end_addr; } 100061da546Spatrick GetFlagsForVTableAtAddress(lldb::addr_t address)101061da546Spatrick uint32_t GetFlagsForVTableAtAddress(lldb::addr_t address) { return 0; } 102061da546Spatrick IsValid()103061da546Spatrick bool IsValid() { return m_valid; } 104061da546Spatrick 105061da546Spatrick bool AddressInRegion(lldb::addr_t addr, uint32_t &flags); 106061da546Spatrick 107061da546Spatrick void Dump(Stream &s); 108061da546Spatrick 109be691f3bSpatrick bool m_valid = false; 110be691f3bSpatrick AppleObjCVTables *m_owner = nullptr; 111be691f3bSpatrick lldb::addr_t m_header_addr = LLDB_INVALID_ADDRESS; 112be691f3bSpatrick lldb::addr_t m_code_start_addr = 0; 113be691f3bSpatrick lldb::addr_t m_code_end_addr = 0; 114061da546Spatrick std::vector<VTableDescriptor> m_descriptors; 115be691f3bSpatrick lldb::addr_t m_next_region = 0; 116061da546Spatrick }; 117061da546Spatrick 118061da546Spatrick public: 119061da546Spatrick AppleObjCVTables(const lldb::ProcessSP &process_sp, 120061da546Spatrick const lldb::ModuleSP &objc_module_sp); 121061da546Spatrick 122061da546Spatrick ~AppleObjCVTables(); 123061da546Spatrick 124061da546Spatrick bool InitializeVTableSymbols(); 125061da546Spatrick 126061da546Spatrick static bool RefreshTrampolines(void *baton, 127061da546Spatrick StoppointCallbackContext *context, 128061da546Spatrick lldb::user_id_t break_id, 129061da546Spatrick lldb::user_id_t break_loc_id); 130061da546Spatrick bool ReadRegions(); 131061da546Spatrick 132061da546Spatrick bool ReadRegions(lldb::addr_t region_addr); 133061da546Spatrick 134061da546Spatrick bool IsAddressInVTables(lldb::addr_t addr, uint32_t &flags); 135061da546Spatrick GetProcessSP()136061da546Spatrick lldb::ProcessSP GetProcessSP() { return m_process_wp.lock(); } 137061da546Spatrick 138061da546Spatrick private: 139061da546Spatrick lldb::ProcessWP m_process_wp; 140061da546Spatrick typedef std::vector<VTableRegion> region_collection; 141061da546Spatrick lldb::addr_t m_trampoline_header; 142061da546Spatrick lldb::break_id_t m_trampolines_changed_bp_id; 143061da546Spatrick region_collection m_regions; 144061da546Spatrick lldb::ModuleSP m_objc_module_sp; 145061da546Spatrick }; 146061da546Spatrick 147061da546Spatrick static const DispatchFunction g_dispatch_functions[]; 148dda28197Spatrick static const char *g_opt_dispatch_names[]; 149061da546Spatrick 150dda28197Spatrick using MsgsendMap = std::map<lldb::addr_t, int>; // This table maps an dispatch 151061da546Spatrick // fn address to the index in 152061da546Spatrick // g_dispatch_functions 153061da546Spatrick MsgsendMap m_msgSend_map; 154dda28197Spatrick MsgsendMap m_opt_dispatch_map; 155061da546Spatrick lldb::ProcessWP m_process_wp; 156061da546Spatrick lldb::ModuleSP m_objc_module_sp; 157*f6aab3d8Srobert std::string m_lookup_implementation_function_code; 158061da546Spatrick std::unique_ptr<UtilityFunction> m_impl_code; 159061da546Spatrick std::mutex m_impl_function_mutex; 160061da546Spatrick lldb::addr_t m_impl_fn_addr; 161061da546Spatrick lldb::addr_t m_impl_stret_fn_addr; 162061da546Spatrick lldb::addr_t m_msg_forward_addr; 163061da546Spatrick lldb::addr_t m_msg_forward_stret_addr; 164061da546Spatrick std::unique_ptr<AppleObjCVTables> m_vtables_up; 165061da546Spatrick }; 166061da546Spatrick 167061da546Spatrick } // namespace lldb_private 168061da546Spatrick 169dda28197Spatrick #endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCTRAMPOLINEHANDLER_H 170