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
19namespace lldb_private {
20
22public:
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 bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
45 int64_t *value_bits = nullptr,
46 uint64_t *payload = nullptr) override {
47 return false;
48 }
49
50 uint64_t GetInstanceSize() override;
51
53
54 bool Describe(
55 std::function<void(ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
56 std::function<bool(const char *, const char *)> const
57 &instance_method_func,
58 std::function<bool(const char *, const char *)> const &class_method_func,
59 std::function<bool(const char *, const char *, lldb::addr_t,
60 uint64_t)> const &ivar_func) const override;
61
62 size_t GetNumIVars() override {
64 return m_ivars_storage.size();
65 }
66
67 iVarDescriptor GetIVarAtIndex(size_t idx) override {
68 if (idx >= GetNumIVars())
69 return iVarDescriptor();
70 return m_ivars_storage[idx];
71 }
72
73protected:
74 void GetIVarInformation();
75
76private:
77 static const uint32_t RW_REALIZED = (1 << 31);
78
79 struct objc_class_t {
80 ObjCLanguageRuntime::ObjCISA m_isa = 0; // The class's metaclass.
85 uint8_t m_flags = 0;
86
87 objc_class_t() = default;
88
89 void Clear() {
90 m_isa = 0;
91 m_superclass = 0;
92 m_cache_ptr = 0;
93 m_vtable_ptr = 0;
94 m_data_ptr = 0;
95 m_flags = 0;
96 }
97
98 bool Read(Process *process, lldb::addr_t addr);
99 };
100
101 struct class_ro_t {
106
112
115
116 std::string m_name;
117
118 bool Read(Process *process, lldb::addr_t addr);
119 };
120
121 struct class_rw_t {
124
126 union {
129 };
132
135
136 bool Read(Process *process, lldb::addr_t addr);
137 };
138
145
146 bool Read(Process *process, lldb::addr_t addr);
147 };
148
149 struct method_t {
153
154 std::string m_name;
155 std::string m_types;
156
157 static size_t GetSize(Process *process, bool is_small) {
158 size_t field_size;
159 if (is_small)
160 field_size = 4; // uint32_t relative indirect fields
161 else
162 field_size = process->GetAddressByteSize();
163
164 return field_size // SEL name;
165 + field_size // const char *types;
166 + field_size; // IMP imp;
167 }
168
169 bool Read(Process *process, lldb::addr_t addr,
170 lldb::addr_t relative_method_lists_base_addr, bool, bool);
171 };
172
173 struct ivar_list_t {
177
178 bool Read(Process *process, lldb::addr_t addr);
179 };
180
181 struct ivar_t {
187
188 std::string m_name;
189 std::string m_type;
190
191 static size_t GetSize(Process *process) {
192 size_t ptr_size = process->GetAddressByteSize();
193
194 return ptr_size // uintptr_t *offset;
195 + ptr_size // const char *name;
196 + ptr_size // const char *type;
197 + sizeof(uint32_t) // uint32_t alignment;
198 + sizeof(uint32_t); // uint32_t size;
199 }
200
201 bool Read(Process *process, lldb::addr_t addr);
202 };
203
205 public:
206 iVarsStorage();
207
208 size_t size();
209
210 iVarDescriptor &operator[](size_t idx);
211
212 void fill(AppleObjCRuntimeV2 &runtime, ClassDescriptorV2 &descriptor);
213
214 private:
215 bool m_filled = false;
216 std::vector<iVarDescriptor> m_ivars;
217 std::recursive_mutex m_mutex;
218 };
219
220 // The constructor should only be invoked by the runtime as it builds its
221 // caches
222 // or populates them. A ClassDescriptorV2 should only ever exist in a cache.
224 ObjCLanguageRuntime::ObjCISA isa, const char *name)
225 : m_runtime(runtime), m_objc_class_ptr(isa), m_name(name),
226 m_ivars_storage() {}
227
228 bool Read_objc_class(Process *process,
229 std::unique_ptr<objc_class_t> &objc_class) const;
230
231 bool Read_class_row(Process *process, const objc_class_t &objc_class,
232 std::unique_ptr<class_ro_t> &class_ro,
233 std::unique_ptr<class_rw_t> &class_rw) const;
234
236 &m_runtime; // The runtime, so we can read information lazily.
237 lldb::addr_t m_objc_class_ptr; // The address of the objc_class_t. (I.e.,
238 // objects of this class type have this as
239 // their ISA)
240 ConstString m_name; // May be NULL
242};
243
244// tagged pointer descriptor
246public:
247 ClassDescriptorV2Tagged(ConstString class_name, uint64_t payload) {
248 m_name = class_name;
249 if (!m_name) {
250 m_valid = false;
251 return;
252 }
253 m_valid = true;
254 m_payload = payload;
255 m_info_bits = (m_payload & 0xF0ULL) >> 4;
256 m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
257 }
258
261 uint64_t u_payload, int64_t s_payload) {
262 if (!actual_class_sp) {
263 m_valid = false;
264 return;
265 }
266 m_name = actual_class_sp->GetClassName();
267 if (!m_name) {
268 m_valid = false;
269 return;
270 }
271 m_valid = true;
272 m_payload = u_payload;
273 m_info_bits = (m_payload & 0x0FULL);
274 m_value_bits = (m_payload & ~0x0FULL) >> 4;
275 m_value_bits_signed = (s_payload & ~0x0FLL) >> 4;
276 }
277
278 ~ClassDescriptorV2Tagged() override = default;
279
280 ConstString GetClassName() override { return m_name; }
281
283 // tagged pointers can represent a class that has a superclass, but since
284 // that information is not
285 // stored in the object itself, we would have to query the runtime to
286 // discover the hierarchy
287 // for the time being, we skip this step in the interest of static discovery
289 }
290
293 }
294
295 bool IsValid() override { return m_valid; }
296
297 bool IsKVO() override {
298 return false; // tagged pointers are not KVO'ed
299 }
300
301 bool IsCFType() override {
302 return false; // tagged pointers are not CF objects
303 }
304
305 bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,
306 uint64_t *value_bits = nullptr,
307 uint64_t *payload = nullptr) override {
308 if (info_bits)
309 *info_bits = GetInfoBits();
310 if (value_bits)
311 *value_bits = GetValueBits();
312 if (payload)
313 *payload = GetPayload();
314 return true;
315 }
316
317 bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
318 int64_t *value_bits = nullptr,
319 uint64_t *payload = nullptr) override {
320 if (info_bits)
321 *info_bits = GetInfoBits();
322 if (value_bits)
323 *value_bits = GetValueBitsSigned();
324 if (payload)
325 *payload = GetPayload();
326 return true;
327 }
328
329 uint64_t GetInstanceSize() override {
330 return (IsValid() ? m_pointer_size : 0);
331 }
332
334 return 0; // tagged pointers have no ISA
335 }
336
337 // these calls are not part of any formal tagged pointers specification
338 virtual uint64_t GetValueBits() { return (IsValid() ? m_value_bits : 0); }
339
340 virtual int64_t GetValueBitsSigned() {
341 return (IsValid() ? m_value_bits_signed : 0);
342 }
343
344 virtual uint64_t GetInfoBits() { return (IsValid() ? m_info_bits : 0); }
345
346 virtual uint64_t GetPayload() { return (IsValid() ? m_payload : 0); }
347
348private:
350 uint8_t m_pointer_size = 0;
351 bool m_valid = false;
352 uint64_t m_info_bits = 0;
353 uint64_t m_value_bits = 0;
355 uint64_t m_payload = 0;
356};
357
358} // namespace lldb_private
359
360#endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCCLASSDESCRIPTORV2_H
bool GetTaggedPointerInfoSigned(uint64_t *info_bits=nullptr, int64_t *value_bits=nullptr, uint64_t *payload=nullptr) override
~ClassDescriptorV2Tagged() override=default
ObjCLanguageRuntime::ClassDescriptorSP GetSuperclass() override
ObjCLanguageRuntime::ObjCISA GetISA() override
ClassDescriptorV2Tagged(ConstString class_name, uint64_t payload)
bool GetTaggedPointerInfo(uint64_t *info_bits=nullptr, uint64_t *value_bits=nullptr, uint64_t *payload=nullptr) override
There are two routines in the ObjC runtime that tagged pointer clients can call to get the value from...
ObjCLanguageRuntime::ClassDescriptorSP GetMetaclass() const override
ClassDescriptorV2Tagged(ObjCLanguageRuntime::ClassDescriptorSP actual_class_sp, uint64_t u_payload, int64_t s_payload)
void fill(AppleObjCRuntimeV2 &runtime, ClassDescriptorV2 &descriptor)
ObjCLanguageRuntime::ClassDescriptorSP GetSuperclass() override
ObjCLanguageRuntime::ObjCISA GetISA() override
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
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
~ClassDescriptorV2() override=default
ClassDescriptorV2(AppleObjCRuntimeV2 &runtime, ObjCLanguageRuntime::ObjCISA isa, const char *name)
bool Read_objc_class(Process *process, std::unique_ptr< objc_class_t > &objc_class) const
iVarDescriptor GetIVarAtIndex(size_t idx) override
bool GetTaggedPointerInfoSigned(uint64_t *info_bits=nullptr, int64_t *value_bits=nullptr, uint64_t *payload=nullptr) override
ObjCLanguageRuntime::ClassDescriptorSP GetMetaclass() const override
bool GetTaggedPointerInfo(uint64_t *info_bits=nullptr, uint64_t *value_bits=nullptr, uint64_t *payload=nullptr) override
There are two routines in the ObjC runtime that tagged pointer clients can call to get the value from...
A uniqued constant string class.
Definition: ConstString.h:39
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
A plug-in interface definition class for debugging a process.
Definition: Process.h:333
uint32_t GetAddressByteSize() const
Definition: Process.cpp:3392
A class that represents a running process on the host machine.
Definition: SBAttachInfo.h:14
uint64_t addr_t
Definition: lldb-types.h:79
bool Read(Process *process, lldb::addr_t addr)
bool Read(Process *process, lldb::addr_t addr)
bool Read(Process *process, lldb::addr_t addr)
bool Read(Process *process, lldb::addr_t addr)
bool Read(Process *process, lldb::addr_t addr)
bool Read(Process *process, lldb::addr_t addr, lldb::addr_t relative_method_lists_base_addr, bool, bool)
static size_t GetSize(Process *process, bool is_small)
bool Read(Process *process, lldb::addr_t addr)