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