Coverage Report

Created: 2023-09-30 09:22

/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCTrampolineHandler.h
Line
Count
Source (jump to first uncovered line)
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_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCTRAMPOLINEHANDLER_H
10
#define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_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
19
namespace lldb_private {
20
21
class AppleObjCTrampolineHandler {
22
public:
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
27
  bool AddrIsMsgForward(lldb::addr_t addr) const {
34
27
    return (addr == m_msg_forward_addr || addr == m_msg_forward_stret_addr);
35
27
  }
36
37
  struct DispatchFunction {
38
  public:
39
    enum FixUpState { eFixUpNone, eFixUpFixed, eFixUpToFix };
40
41
    const char *name = nullptr;
42
    bool stret_return = false;
43
    bool is_super = false;
44
    bool is_super2 = false;
45
    FixUpState fixedup = eFixUpNone;
46
  };
47
48
  lldb::addr_t SetupDispatchFunction(Thread &thread,
49
                                     ValueList &dispatch_values);
50
  const DispatchFunction *FindDispatchFunction(lldb::addr_t addr);
51
  void ForEachDispatchFunction(std::function<void(lldb::addr_t, 
52
                                                  const DispatchFunction &)>);
53
54
private:
55
  /// These hold the code for the function that finds the implementation of
56
  /// an ObjC message send given the class & selector and the kind of dispatch.
57
  /// There are two variants depending on whether the platform uses a separate
58
  /// _stret passing convention (e.g. Intel) or not (e.g. ARM).  The difference
59
  /// is only at the very end of the function, so the code is broken into the
60
  /// common prefix and the suffix, which get composed appropriately before
61
  /// the function gets compiled.
62
  /// \{
63
  static const char *g_lookup_implementation_function_name;
64
  static const char *g_lookup_implementation_function_common_code;
65
  static const char *g_lookup_implementation_with_stret_function_code;
66
  static const char *g_lookup_implementation_no_stret_function_code;
67
  /// \}
68
69
  class AppleObjCVTables {
70
  public:
71
    // These come from objc-gdb.h.
72
    enum VTableFlags {
73
      eOBJC_TRAMPOLINE_MESSAGE = (1 << 0), // trampoline acts like objc_msgSend
74
      eOBJC_TRAMPOLINE_STRET = (1 << 1),   // trampoline is struct-returning
75
      eOBJC_TRAMPOLINE_VTABLE = (1 << 2)   // trampoline is vtable dispatcher
76
    };
77
78
  private:
79
    struct VTableDescriptor {
80
      VTableDescriptor(uint32_t in_flags, lldb::addr_t in_code_start)
81
0
          : flags(in_flags), code_start(in_code_start) {}
82
83
      uint32_t flags;
84
      lldb::addr_t code_start;
85
    };
86
87
    class VTableRegion {
88
    public:
89
      VTableRegion() = default;
90
91
      VTableRegion(AppleObjCVTables *owner, lldb::addr_t header_addr);
92
93
      void SetUpRegion();
94
95
0
      lldb::addr_t GetNextRegionAddr() { return m_next_region; }
96
97
0
      lldb::addr_t GetCodeStart() { return m_code_start_addr; }
98
99
0
      lldb::addr_t GetCodeEnd() { return m_code_end_addr; }
100
101
0
      uint32_t GetFlagsForVTableAtAddress(lldb::addr_t address) { return 0; }
102
103
0
      bool IsValid() { return m_valid; }
104
105
      bool AddressInRegion(lldb::addr_t addr, uint32_t &flags);
106
107
      void Dump(Stream &s);
108
109
      bool m_valid = false;
110
      AppleObjCVTables *m_owner = nullptr;
111
      lldb::addr_t m_header_addr = LLDB_INVALID_ADDRESS;
112
      lldb::addr_t m_code_start_addr = 0;
113
      lldb::addr_t m_code_end_addr = 0;
114
      std::vector<VTableDescriptor> m_descriptors;
115
      lldb::addr_t m_next_region = 0;
116
    };
117
118
  public:
119
    AppleObjCVTables(const lldb::ProcessSP &process_sp,
120
                     const lldb::ModuleSP &objc_module_sp);
121
122
    ~AppleObjCVTables();
123
124
    bool InitializeVTableSymbols();
125
126
    static bool RefreshTrampolines(void *baton,
127
                                   StoppointCallbackContext *context,
128
                                   lldb::user_id_t break_id,
129
                                   lldb::user_id_t break_loc_id);
130
    bool ReadRegions();
131
132
    bool ReadRegions(lldb::addr_t region_addr);
133
134
    bool IsAddressInVTables(lldb::addr_t addr, uint32_t &flags);
135
136
4.22k
    lldb::ProcessSP GetProcessSP() { return m_process_wp.lock(); }
137
138
  private:
139
    lldb::ProcessWP m_process_wp;
140
    typedef std::vector<VTableRegion> region_collection;
141
    lldb::addr_t m_trampoline_header;
142
    lldb::break_id_t m_trampolines_changed_bp_id;
143
    region_collection m_regions;
144
    lldb::ModuleSP m_objc_module_sp;
145
  };
146
147
  static const DispatchFunction g_dispatch_functions[];
148
  static const char *g_opt_dispatch_names[];
149
150
  using MsgsendMap = std::map<lldb::addr_t, int>; // This table maps an dispatch
151
                                                  // fn address to the index in
152
                                                  // g_dispatch_functions
153
  MsgsendMap m_msgSend_map;
154
  MsgsendMap m_opt_dispatch_map;
155
  lldb::ProcessWP m_process_wp;
156
  lldb::ModuleSP m_objc_module_sp;
157
  std::string m_lookup_implementation_function_code;
158
  std::unique_ptr<UtilityFunction> m_impl_code;
159
  std::mutex m_impl_function_mutex;
160
  lldb::addr_t m_impl_fn_addr;
161
  lldb::addr_t m_impl_stret_fn_addr;
162
  lldb::addr_t m_msg_forward_addr;
163
  lldb::addr_t m_msg_forward_stret_addr;
164
  std::unique_ptr<AppleObjCVTables> m_vtables_up;
165
};
166
167
} // namespace lldb_private
168
169
#endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCTRAMPOLINEHANDLER_H