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