Path: blob/main/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
39690 views
//===-- AppleObjCTrampolineHandler.h ----------------------------*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#ifndef LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCTRAMPOLINEHANDLER_H9#define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCTRAMPOLINEHANDLER_H1011#include <map>12#include <mutex>13#include <vector>1415#include "lldb/Expression/UtilityFunction.h"16#include "lldb/lldb-public.h"1718namespace lldb_private {1920class AppleObjCTrampolineHandler {21public:22AppleObjCTrampolineHandler(const lldb::ProcessSP &process_sp,23const lldb::ModuleSP &objc_module_sp);2425~AppleObjCTrampolineHandler();2627lldb::ThreadPlanSP GetStepThroughDispatchPlan(Thread &thread,28bool stop_others);2930FunctionCaller *GetLookupImplementationFunctionCaller();3132bool AddrIsMsgForward(lldb::addr_t addr) const {33return (addr == m_msg_forward_addr || addr == m_msg_forward_stret_addr);34}3536struct DispatchFunction {37public:38enum FixUpState { eFixUpNone, eFixUpFixed, eFixUpToFix };3940const char *name = nullptr;41bool stret_return = false;42bool is_super = false;43bool is_super2 = false;44FixUpState fixedup = eFixUpNone;45};4647lldb::addr_t SetupDispatchFunction(Thread &thread,48ValueList &dispatch_values);49const DispatchFunction *FindDispatchFunction(lldb::addr_t addr);50void ForEachDispatchFunction(std::function<void(lldb::addr_t,51const DispatchFunction &)>);5253private:54/// These hold the code for the function that finds the implementation of55/// an ObjC message send given the class & selector and the kind of dispatch.56/// There are two variants depending on whether the platform uses a separate57/// _stret passing convention (e.g. Intel) or not (e.g. ARM). The difference58/// is only at the very end of the function, so the code is broken into the59/// common prefix and the suffix, which get composed appropriately before60/// the function gets compiled.61/// \{62static const char *g_lookup_implementation_function_name;63static const char *g_lookup_implementation_function_common_code;64static const char *g_lookup_implementation_with_stret_function_code;65static const char *g_lookup_implementation_no_stret_function_code;66/// \}6768class AppleObjCVTables {69public:70// These come from objc-gdb.h.71enum VTableFlags {72eOBJC_TRAMPOLINE_MESSAGE = (1 << 0), // trampoline acts like objc_msgSend73eOBJC_TRAMPOLINE_STRET = (1 << 1), // trampoline is struct-returning74eOBJC_TRAMPOLINE_VTABLE = (1 << 2) // trampoline is vtable dispatcher75};7677private:78struct VTableDescriptor {79VTableDescriptor(uint32_t in_flags, lldb::addr_t in_code_start)80: flags(in_flags), code_start(in_code_start) {}8182uint32_t flags;83lldb::addr_t code_start;84};8586class VTableRegion {87public:88VTableRegion() = default;8990VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr);9192void SetUpRegion();9394lldb::addr_t GetNextRegionAddr() { return m_next_region; }9596lldb::addr_t GetCodeStart() { return m_code_start_addr; }9798lldb::addr_t GetCodeEnd() { return m_code_end_addr; }99100uint32_t GetFlagsForVTableAtAddress(lldb::addr_t address) { return 0; }101102bool IsValid() { return m_valid; }103104bool AddressInRegion(lldb::addr_t addr, uint32_t &flags);105106void Dump(Stream &s);107108bool m_valid = false;109AppleObjCVTables *m_owner = nullptr;110lldb::addr_t m_header_addr = LLDB_INVALID_ADDRESS;111lldb::addr_t m_code_start_addr = 0;112lldb::addr_t m_code_end_addr = 0;113std::vector<VTableDescriptor> m_descriptors;114lldb::addr_t m_next_region = 0;115};116117public:118AppleObjCVTables(const lldb::ProcessSP &process_sp,119const lldb::ModuleSP &objc_module_sp);120121~AppleObjCVTables();122123bool InitializeVTableSymbols();124125static bool RefreshTrampolines(void *baton,126StoppointCallbackContext *context,127lldb::user_id_t break_id,128lldb::user_id_t break_loc_id);129bool ReadRegions();130131bool ReadRegions(lldb::addr_t region_addr);132133bool IsAddressInVTables(lldb::addr_t addr, uint32_t &flags);134135lldb::ProcessSP GetProcessSP() { return m_process_wp.lock(); }136137private:138lldb::ProcessWP m_process_wp;139typedef std::vector<VTableRegion> region_collection;140lldb::addr_t m_trampoline_header;141lldb::break_id_t m_trampolines_changed_bp_id;142region_collection m_regions;143lldb::ModuleSP m_objc_module_sp;144};145146static const DispatchFunction g_dispatch_functions[];147static const char *g_opt_dispatch_names[];148149using MsgsendMap = std::map<lldb::addr_t, int>; // This table maps an dispatch150// fn address to the index in151// g_dispatch_functions152MsgsendMap m_msgSend_map;153MsgsendMap m_opt_dispatch_map;154lldb::ProcessWP m_process_wp;155lldb::ModuleSP m_objc_module_sp;156std::string m_lookup_implementation_function_code;157std::unique_ptr<UtilityFunction> m_impl_code;158std::mutex m_impl_function_mutex;159lldb::addr_t m_impl_fn_addr;160lldb::addr_t m_impl_stret_fn_addr;161lldb::addr_t m_msg_forward_addr;162lldb::addr_t m_msg_forward_stret_addr;163std::unique_ptr<AppleObjCVTables> m_vtables_up;164};165166} // namespace lldb_private167168#endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCTRAMPOLINEHANDLER_H169170171