LLDB  mainline
AppleObjCClassDescriptorV2.h
Go to the documentation of this file.
1 //===-- AppleObjCClassDescriptorV2.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 liblldb_AppleObjCClassDescriptorV2_h_
10 #define liblldb_AppleObjCClassDescriptorV2_h_
11 
12 #include <mutex>
13 
14 #include "AppleObjCRuntimeV2.h"
16 #include "lldb/lldb-private.h"
17 
18 namespace lldb_private {
19 
21 public:
23 
24  ~ClassDescriptorV2() override = default;
25 
26  ConstString GetClassName() override;
27 
29 
31 
32  bool IsValid() override {
33  return true; // any Objective-C v2 runtime class descriptor we vend is valid
34  }
35 
36  // a custom descriptor is used for tagged pointers
37  bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,
38  uint64_t *value_bits = nullptr,
39  uint64_t *payload = nullptr) override {
40  return false;
41  }
42 
43  uint64_t GetInstanceSize() override;
44 
45  ObjCLanguageRuntime::ObjCISA GetISA() override { return m_objc_class_ptr; }
46 
47  bool Describe(
48  std::function<void(ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
49  std::function<bool(const char *, const char *)> const
50  &instance_method_func,
51  std::function<bool(const char *, const char *)> const &class_method_func,
52  std::function<bool(const char *, const char *, lldb::addr_t,
53  uint64_t)> const &ivar_func) const override;
54 
55  size_t GetNumIVars() override {
57  return m_ivars_storage.size();
58  }
59 
60  iVarDescriptor GetIVarAtIndex(size_t idx) override {
61  if (idx >= GetNumIVars())
62  return iVarDescriptor();
63  return m_ivars_storage[idx];
64  }
65 
66 protected:
67  void GetIVarInformation();
68 
69 private:
70  static const uint32_t RW_REALIZED = (1 << 31);
71 
72  struct objc_class_t {
73  ObjCLanguageRuntime::ObjCISA m_isa; // The class's metaclass.
74  ObjCLanguageRuntime::ObjCISA m_superclass;
75  lldb::addr_t m_cache_ptr;
76  lldb::addr_t m_vtable_ptr;
77  lldb::addr_t m_data_ptr;
78  uint8_t m_flags;
79 
80  objc_class_t()
81  : m_isa(0), m_superclass(0), m_cache_ptr(0), m_vtable_ptr(0),
82  m_data_ptr(0), m_flags(0) {}
83 
84  void Clear() {
85  m_isa = 0;
86  m_superclass = 0;
87  m_cache_ptr = 0;
88  m_vtable_ptr = 0;
89  m_data_ptr = 0;
90  m_flags = 0;
91  }
92 
93  bool Read(Process *process, lldb::addr_t addr);
94  };
95 
96  struct class_ro_t {
97  uint32_t m_flags;
98  uint32_t m_instanceStart;
99  uint32_t m_instanceSize;
100  uint32_t m_reserved;
101 
102  lldb::addr_t m_ivarLayout_ptr;
103  lldb::addr_t m_name_ptr;
104  lldb::addr_t m_baseMethods_ptr;
105  lldb::addr_t m_baseProtocols_ptr;
106  lldb::addr_t m_ivars_ptr;
107 
108  lldb::addr_t m_weakIvarLayout_ptr;
109  lldb::addr_t m_baseProperties_ptr;
110 
111  std::string m_name;
112 
113  bool Read(Process *process, lldb::addr_t addr);
114  };
115 
116  struct class_rw_t {
117  uint32_t m_flags;
118  uint32_t m_version;
119 
120  lldb::addr_t m_ro_ptr;
121  union {
122  lldb::addr_t m_method_list_ptr;
123  lldb::addr_t m_method_lists_ptr;
124  };
125  lldb::addr_t m_properties_ptr;
126  lldb::addr_t m_protocols_ptr;
127 
128  ObjCLanguageRuntime::ObjCISA m_firstSubclass;
129  ObjCLanguageRuntime::ObjCISA m_nextSiblingClass;
130 
131  bool Read(Process *process, lldb::addr_t addr);
132  };
133 
134  struct method_list_t {
135  uint32_t m_entsize;
136  uint32_t m_count;
137  lldb::addr_t m_first_ptr;
138 
139  bool Read(Process *process, lldb::addr_t addr);
140  };
141 
142  struct method_t {
143  lldb::addr_t m_name_ptr;
144  lldb::addr_t m_types_ptr;
145  lldb::addr_t m_imp_ptr;
146 
147  std::string m_name;
148  std::string m_types;
149 
150  static size_t GetSize(Process *process) {
151  size_t ptr_size = process->GetAddressByteSize();
152 
153  return ptr_size // SEL name;
154  + ptr_size // const char *types;
155  + ptr_size; // IMP imp;
156  }
157 
158  bool Read(Process *process, lldb::addr_t addr);
159  };
160 
161  struct ivar_list_t {
162  uint32_t m_entsize;
163  uint32_t m_count;
164  lldb::addr_t m_first_ptr;
165 
166  bool Read(Process *process, lldb::addr_t addr);
167  };
168 
169  struct ivar_t {
170  lldb::addr_t m_offset_ptr;
171  lldb::addr_t m_name_ptr;
172  lldb::addr_t m_type_ptr;
173  uint32_t m_alignment;
174  uint32_t m_size;
175 
176  std::string m_name;
177  std::string m_type;
178 
179  static size_t GetSize(Process *process) {
180  size_t ptr_size = process->GetAddressByteSize();
181 
182  return ptr_size // uintptr_t *offset;
183  + ptr_size // const char *name;
184  + ptr_size // const char *type;
185  + sizeof(uint32_t) // uint32_t alignment;
186  + sizeof(uint32_t); // uint32_t size;
187  }
188 
189  bool Read(Process *process, lldb::addr_t addr);
190  };
191 
192  class iVarsStorage {
193  public:
194  iVarsStorage();
195 
196  size_t size();
197 
198  iVarDescriptor &operator[](size_t idx);
199 
200  void fill(AppleObjCRuntimeV2 &runtime, ClassDescriptorV2 &descriptor);
201 
202  private:
203  bool m_filled;
204  std::vector<iVarDescriptor> m_ivars;
205  std::recursive_mutex m_mutex;
206  };
207 
208  // The constructor should only be invoked by the runtime as it builds its
209  // caches
210  // or populates them. A ClassDescriptorV2 should only ever exist in a cache.
212  ObjCLanguageRuntime::ObjCISA isa, const char *name)
213  : m_runtime(runtime), m_objc_class_ptr(isa), m_name(name),
214  m_ivars_storage() {}
215 
216  bool Read_objc_class(Process *process,
217  std::unique_ptr<objc_class_t> &objc_class) const;
218 
219  bool Read_class_row(Process *process, const objc_class_t &objc_class,
220  std::unique_ptr<class_ro_t> &class_ro,
221  std::unique_ptr<class_rw_t> &class_rw) const;
222 
224  &m_runtime; // The runtime, so we can read information lazily.
225  lldb::addr_t m_objc_class_ptr; // The address of the objc_class_t. (I.e.,
226  // objects of this class type have this as
227  // their ISA)
228  ConstString m_name; // May be NULL
229  iVarsStorage m_ivars_storage;
230 };
231 
232 // tagged pointer descriptor
234 public:
235  ClassDescriptorV2Tagged(ConstString class_name, uint64_t payload) {
236  m_name = class_name;
237  if (!m_name) {
238  m_valid = false;
239  return;
240  }
241  m_valid = true;
242  m_payload = payload;
243  m_info_bits = (m_payload & 0xF0ULL) >> 4;
244  m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
245  }
246 
249  uint64_t payload) {
250  if (!actual_class_sp) {
251  m_valid = false;
252  return;
253  }
254  m_name = actual_class_sp->GetClassName();
255  if (!m_name) {
256  m_valid = false;
257  return;
258  }
259  m_valid = true;
260  m_payload = payload;
261  m_info_bits = (m_payload & 0x0FULL);
262  m_value_bits = (m_payload & ~0x0FULL) >> 4;
263  }
264 
265  ~ClassDescriptorV2Tagged() override = default;
266 
267  ConstString GetClassName() override { return m_name; }
268 
270  // tagged pointers can represent a class that has a superclass, but since
271  // that information is not
272  // stored in the object itself, we would have to query the runtime to
273  // discover the hierarchy
274  // for the time being, we skip this step in the interest of static discovery
276  }
277 
280  }
281 
282  bool IsValid() override { return m_valid; }
283 
284  bool IsKVO() override {
285  return false; // tagged pointers are not KVO'ed
286  }
287 
288  bool IsCFType() override {
289  return false; // tagged pointers are not CF objects
290  }
291 
292  bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,
293  uint64_t *value_bits = nullptr,
294  uint64_t *payload = nullptr) override {
295  if (info_bits)
296  *info_bits = GetInfoBits();
297  if (value_bits)
298  *value_bits = GetValueBits();
299  if (payload)
300  *payload = GetPayload();
301  return true;
302  }
303 
304  uint64_t GetInstanceSize() override {
305  return (IsValid() ? m_pointer_size : 0);
306  }
307 
309  return 0; // tagged pointers have no ISA
310  }
311 
312  // these calls are not part of any formal tagged pointers specification
313  virtual uint64_t GetValueBits() { return (IsValid() ? m_value_bits : 0); }
314 
315  virtual uint64_t GetInfoBits() { return (IsValid() ? m_info_bits : 0); }
316 
317  virtual uint64_t GetPayload() { return (IsValid() ? m_payload : 0); }
318 
319 private:
320  ConstString m_name;
321  uint8_t m_pointer_size;
322  bool m_valid;
323  uint64_t m_info_bits;
324  uint64_t m_value_bits;
325  uint64_t m_payload;
326 };
327 
328 } // namespace lldb_private
329 
330 #endif // liblldb_AppleObjCClassDescriptorV2_h_
ClassDescriptorV2Tagged(ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp, uint64_t payload)
Enumerations for broadcasting.
Definition: SBLaunchInfo.h:14
iVarDescriptor GetIVarAtIndex(size_t idx) override
ObjCLanguageRuntime::ObjCISA GetISA() override
bool GetTaggedPointerInfo(uint64_t *info_bits=nullptr, uint64_t *value_bits=nullptr, uint64_t *payload=nullptr) override
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
ObjCLanguageRuntime::ClassDescriptorSP GetSuperclass() override
uint32_t GetAddressByteSize() const
Definition: Process.cpp:3370
A plug-in interface definition class for debugging a process.
Definition: Process.h:353
bool GetTaggedPointerInfo(uint64_t *info_bits=nullptr, uint64_t *value_bits=nullptr, uint64_t *payload=nullptr) override
ObjCLanguageRuntime::ClassDescriptorSP GetMetaclass() const override
~ClassDescriptorV2() override=default
bool Describe(std::function< void(ObjCLanguageRuntime::ObjCISA)> const &superclass_func, std::function< bool(const char *, const char *)> const &instance_method_func, std::function< bool(const char *, const char *)> const &class_method_func, std::function< bool(const char *, const char *, lldb::addr_t, uint64_t)> const &ivar_func) const override
ClassDescriptorV2Tagged(ConstString class_name, uint64_t payload)
uint64_t addr_t
Definition: lldb-types.h:83
A uniqued constant string class.
Definition: ConstString.h:38
ObjCLanguageRuntime::ClassDescriptorSP GetMetaclass() const override
ObjCLanguageRuntime::ObjCISA GetISA() override
ObjCLanguageRuntime::ClassDescriptorSP GetSuperclass() override