AppleObjCTrampolineHandler.h revision 353358
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_AppleObjCTrampolineHandler_h_
10#define lldb_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
19namespace lldb_private {
20
21class AppleObjCTrampolineHandler {
22public:
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
51private:
52  static const char *g_lookup_implementation_function_name;
53  static const char *g_lookup_implementation_with_stret_function_code;
54  static const char *g_lookup_implementation_no_stret_function_code;
55
56  class AppleObjCVTables {
57  public:
58    // These come from objc-gdb.h.
59    enum VTableFlags {
60      eOBJC_TRAMPOLINE_MESSAGE = (1 << 0), // trampoline acts like objc_msgSend
61      eOBJC_TRAMPOLINE_STRET = (1 << 1),   // trampoline is struct-returning
62      eOBJC_TRAMPOLINE_VTABLE = (1 << 2)   // trampoline is vtable dispatcher
63    };
64
65  private:
66    struct VTableDescriptor {
67      VTableDescriptor(uint32_t in_flags, lldb::addr_t in_code_start)
68          : flags(in_flags), code_start(in_code_start) {}
69
70      uint32_t flags;
71      lldb::addr_t code_start;
72    };
73
74    class VTableRegion {
75    public:
76      VTableRegion()
77          : m_valid(false), m_owner(nullptr),
78            m_header_addr(LLDB_INVALID_ADDRESS), m_code_start_addr(0),
79            m_code_end_addr(0), m_next_region(0) {}
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    public:
100      bool m_valid;
101      AppleObjCVTables *m_owner;
102      lldb::addr_t m_header_addr;
103      lldb::addr_t m_code_start_addr;
104      lldb::addr_t m_code_end_addr;
105      std::vector<VTableDescriptor> m_descriptors;
106      lldb::addr_t m_next_region;
107    };
108
109  public:
110    AppleObjCVTables(const lldb::ProcessSP &process_sp,
111                     const lldb::ModuleSP &objc_module_sp);
112
113    ~AppleObjCVTables();
114
115    bool InitializeVTableSymbols();
116
117    static bool RefreshTrampolines(void *baton,
118                                   StoppointCallbackContext *context,
119                                   lldb::user_id_t break_id,
120                                   lldb::user_id_t break_loc_id);
121    bool ReadRegions();
122
123    bool ReadRegions(lldb::addr_t region_addr);
124
125    bool IsAddressInVTables(lldb::addr_t addr, uint32_t &flags);
126
127    lldb::ProcessSP GetProcessSP() { return m_process_wp.lock(); }
128
129  private:
130    lldb::ProcessWP m_process_wp;
131    typedef std::vector<VTableRegion> region_collection;
132    lldb::addr_t m_trampoline_header;
133    lldb::break_id_t m_trampolines_changed_bp_id;
134    region_collection m_regions;
135    lldb::ModuleSP m_objc_module_sp;
136  };
137
138  static const DispatchFunction g_dispatch_functions[];
139
140  typedef std::map<lldb::addr_t, int> MsgsendMap; // This table maps an dispatch
141                                                  // fn address to the index in
142                                                  // g_dispatch_functions
143  MsgsendMap m_msgSend_map;
144  lldb::ProcessWP m_process_wp;
145  lldb::ModuleSP m_objc_module_sp;
146  const char *m_lookup_implementation_function_code;
147  std::unique_ptr<UtilityFunction> m_impl_code;
148  std::mutex m_impl_function_mutex;
149  lldb::addr_t m_impl_fn_addr;
150  lldb::addr_t m_impl_stret_fn_addr;
151  lldb::addr_t m_msg_forward_addr;
152  lldb::addr_t m_msg_forward_stret_addr;
153  std::unique_ptr<AppleObjCVTables> m_vtables_up;
154};
155
156} // namespace lldb_private
157
158#endif // lldb_AppleObjCTrampolineHandler_h_
159