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