blob: 27aebd8594dfaaeeff4d4f21fc5f72c8dbc222aa [file] [log] [blame]
//===-- 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