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"
16#include "lldb/lldb-private.h"
17
19
20namespace lldb_private {
21
23public:
25
26 ~ClassDescriptorV2() override = default;
27
28 ConstString GetClassName() override;
29
31
33
34 bool IsValid() override {
35 return true; // any Objective-C v2 runtime class descriptor we vend is valid
36 }
37
39
40 // a custom descriptor is used for tagged pointers
41 bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,
42 uint64_t *value_bits = nullptr,
43 uint64_t *payload = nullptr) override {
44 return false;
45 }
46
47 bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
48 int64_t *value_bits = nullptr,
49 uint64_t *payload = nullptr) override {
50 return false;
51 }
52
53 uint64_t GetInstanceSize() override;
54
56
57 bool Describe(
58 std::function<void(ObjCLanguageRuntime::ObjCISA)> const &superclass_func,
59 std::function<bool(const char *, const char *)> const
60 &instance_method_func,
61 std::function<bool(const char *, const char *)> const &class_method_func,
62 std::function<bool(const char *, const char *, lldb::addr_t,
63 uint64_t)> const &ivar_func) const override;
64
65 size_t GetNumIVars() override {
67 return m_ivars_storage.size();
68 }
69
70 iVarDescriptor GetIVarAtIndex(size_t idx) override {
71 if (idx >= GetNumIVars())
72 return iVarDescriptor();
73 return m_ivars_storage[idx];
74 }
75
76protected:
77 void GetIVarInformation();
78
79private:
80 static const uint32_t RW_REALIZED = (1u << 31);
81
82 struct objc_class_t {
83 ObjCLanguageRuntime::ObjCISA m_isa = 0; // The class's metaclass.
88 uint8_t m_flags = 0;
89
90 objc_class_t() = default;
91
92 void Clear() {
93 m_isa = 0;
94 m_superclass = 0;
95 m_cache_ptr = 0;
96 m_vtable_ptr = 0;
97 m_data_ptr = 0;
98 m_flags = 0;
99 }
100
101 bool Read(Process *process, lldb::addr_t addr);
102 };
103
123
138
149
150 std::optional<method_list_t>
151 GetMethodList(Process *process, lldb::addr_t method_list_ptr) const;
152
153 struct method_t {
157
158 std::string m_name;
159 std::string m_types;
160
161 static size_t GetSize(Process *process, bool is_small) {
162 size_t field_size;
163 if (is_small)
164 field_size = 4; // uint32_t relative indirect fields
165 else
166 field_size = process->GetAddressByteSize();
167
168 return field_size // SEL name;
169 + field_size // const char *types;
170 + field_size; // IMP imp;
171 }
172
173 bool Read(DataExtractor &extractor, Process *process, lldb::addr_t addr,
174 lldb::addr_t relative_string_base_addr, bool is_small,
175 bool has_direct_sel, bool has_relative_types);
176
177 /// Fill in `m_name` and `m_types` efficiently by batching read requests.
178 static void ReadNames(llvm::MutableArrayRef<method_t> methods,
179 Process &process);
180 };
181
182 llvm::SmallVector<method_t, 0>
183 ReadMethods(llvm::ArrayRef<lldb::addr_t> addresses,
184 lldb::addr_t relative_string_base_addr, bool is_small,
185 bool has_direct_sel, bool has_relative_types) const;
186
187 struct ivar_list_t {
188 uint32_t m_entsize;
189 uint32_t m_count;
191
192 bool Read(Process *process, lldb::addr_t addr);
193 };
194
195 struct ivar_t {
199 uint32_t m_alignment;
200 uint32_t m_size;
201
202 std::string m_name;
203 std::string m_type;
204
205 static size_t GetSize(Process *process) {
206 size_t ptr_size = process->GetAddressByteSize();
207
208 return ptr_size // uintptr_t *offset;
209 + ptr_size // const char *name;
210 + ptr_size // const char *type;
211 + sizeof(uint32_t) // uint32_t alignment;
212 + sizeof(uint32_t); // uint32_t size;
213 }
214
215 bool Read(Process *process, lldb::addr_t addr);
216 };
217
221
222 bool Read(Process *process, lldb::addr_t addr);
223 };
224
226 uint32_t m_entsize;
227 uint32_t m_count;
229
230 bool Read(Process *process, lldb::addr_t addr);
231 };
232
234 public:
235 iVarsStorage();
236
237 size_t size();
238
239 iVarDescriptor &operator[](size_t idx);
240
241 void fill(AppleObjCRuntimeV2 &runtime, ClassDescriptorV2 &descriptor);
242
243 private:
244 bool m_filled = false;
245 std::vector<iVarDescriptor> m_ivars;
246 std::recursive_mutex m_mutex;
247 };
248
249 // The constructor should only be invoked by the runtime as it builds its
250 // caches
251 // or populates them. A ClassDescriptorV2 should only ever exist in a cache.
257
258 bool Read_objc_class(Process *process,
259 std::unique_ptr<objc_class_t> &objc_class) const;
260
261 bool Read_class_row(Process *process, const objc_class_t &objc_class,
262 std::unique_ptr<class_ro_t> &class_ro,
263 std::unique_ptr<class_rw_t> &class_rw) const;
264
265 bool ProcessMethodList(std::function<bool(const char *, const char *)> const
266 &instance_method_func,
267 method_list_t &method_list) const;
268
270 std::function<bool(const char *, const char *)> const
271 &instance_method_func,
272 lldb::addr_t relative_method_list_ptr) const;
273
275 &m_runtime; // The runtime, so we can read information lazily.
276 lldb::addr_t m_objc_class_ptr; // The address of the objc_class_t. (I.e.,
277 // objects of this class type have this as
278 // their ISA)
279 ConstString m_name; // May be NULL
281
282 mutable std::map<uint16_t, std::vector<method_list_t>>
284 mutable std::optional<uint64_t> m_last_version_updated;
285};
286
287// tagged pointer descriptor
289public:
290 ClassDescriptorV2Tagged(ConstString class_name, uint64_t payload) {
291 m_name = class_name;
292 if (!m_name) {
293 m_valid = false;
294 return;
295 }
296 m_valid = true;
297 m_payload = payload;
298 m_info_bits = (m_payload & 0xF0ULL) >> 4;
299 m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
300 }
301
304 uint64_t u_payload, int64_t s_payload) {
305 if (!actual_class_sp) {
306 m_valid = false;
307 return;
308 }
309 m_name = actual_class_sp->GetClassName();
310 if (!m_name) {
311 m_valid = false;
312 return;
313 }
314 m_valid = true;
315 m_payload = u_payload;
316 m_info_bits = (m_payload & 0x0FULL);
317 m_value_bits = (m_payload & ~0x0FULL) >> 4;
318 m_value_bits_signed = (s_payload & ~0x0FLL) >> 4;
319 }
320
321 ~ClassDescriptorV2Tagged() override = default;
322
323 ConstString GetClassName() override { return m_name; }
324
326 // tagged pointers can represent a class that has a superclass, but since
327 // that information is not
328 // stored in the object itself, we would have to query the runtime to
329 // discover the hierarchy
330 // for the time being, we skip this step in the interest of static discovery
332 }
333
337
338 bool IsValid() override { return m_valid; }
339
340 bool IsKVO() override {
341 return false; // tagged pointers are not KVO'ed
342 }
343
344 bool IsCFType() override {
345 return false; // tagged pointers are not CF objects
346 }
347
348 bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,
349 uint64_t *value_bits = nullptr,
350 uint64_t *payload = nullptr) override {
351 if (info_bits)
352 *info_bits = GetInfoBits();
353 if (value_bits)
354 *value_bits = GetValueBits();
355 if (payload)
356 *payload = GetPayload();
357 return true;
358 }
359
360 bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
361 int64_t *value_bits = nullptr,
362 uint64_t *payload = nullptr) override {
363 if (info_bits)
364 *info_bits = GetInfoBits();
365 if (value_bits)
366 *value_bits = GetValueBitsSigned();
367 if (payload)
368 *payload = GetPayload();
369 return true;
370 }
371
372 uint64_t GetInstanceSize() override {
373 return (IsValid() ? m_pointer_size : 0);
374 }
375
377 return 0; // tagged pointers have no ISA
378 }
379
380 // these calls are not part of any formal tagged pointers specification
381 virtual uint64_t GetValueBits() { return (IsValid() ? m_value_bits : 0); }
382
383 virtual int64_t GetValueBitsSigned() {
384 return (IsValid() ? m_value_bits_signed : 0);
385 }
386
387 virtual uint64_t GetInfoBits() { return (IsValid() ? m_info_bits : 0); }
388
389 virtual uint64_t GetPayload() { return (IsValid() ? m_payload : 0); }
390
391private:
393 uint8_t m_pointer_size = 0;
394 bool m_valid = false;
395 uint64_t m_info_bits = 0;
396 uint64_t m_value_bits = 0;
398 uint64_t m_payload = 0;
399};
400
401} // namespace lldb_private
402
403#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
llvm::SmallVector< method_t, 0 > ReadMethods(llvm::ArrayRef< lldb::addr_t > addresses, lldb::addr_t relative_string_base_addr, bool is_small, bool has_direct_sel, bool has_relative_types) const
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
friend class lldb_private::AppleObjCRuntimeV2
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
bool ProcessRelativeMethodLists(std::function< bool(const char *, const char *)> const &instance_method_func, lldb::addr_t relative_method_list_ptr) const
ClassDescriptorV2(AppleObjCRuntimeV2 &runtime, ObjCLanguageRuntime::ObjCISA isa, const char *name)
bool ProcessMethodList(std::function< bool(const char *, const char *)> const &instance_method_func, method_list_t &method_list) const
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
std::optional< uint64_t > m_last_version_updated
std::map< uint16_t, std::vector< method_list_t > > m_image_to_method_lists
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...
lldb::LanguageType GetImplementationLanguage() const override
Determine whether this class is implemented in Swift.
std::optional< method_list_t > GetMethodList(Process *process, lldb::addr_t method_list_ptr) const
A uniqued constant string class.
Definition ConstString.h:40
An data extractor class.
std::shared_ptr< ClassDescriptor > ClassDescriptorSP
A plug-in interface definition class for debugging a process.
Definition Process.h:354
uint32_t GetAddressByteSize() const
Definition Process.cpp:3720
A class that represents a running process on the host machine.
LanguageType
Programming language type.
uint64_t addr_t
Definition lldb-types.h:80
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)
static size_t GetSize(Process *process, bool is_small)
static void ReadNames(llvm::MutableArrayRef< method_t > methods, Process &process)
Fill in m_name and m_types efficiently by batching read requests.
bool Read(DataExtractor &extractor, Process *process, lldb::addr_t addr, lldb::addr_t relative_string_base_addr, bool is_small, bool has_direct_sel, bool has_relative_types)
bool Read(Process *process, lldb::addr_t addr)
uint16_t m_image_index
int64_t m_list_offset
bool Read(Process *process, lldb::addr_t addr)