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
178 llvm::SmallVector<method_t, 0>
179 ReadMethods(llvm::ArrayRef<lldb::addr_t> addresses,
180 lldb::addr_t relative_string_base_addr, bool is_small,
181 bool has_direct_sel, bool has_relative_types) const;
182
183 struct ivar_list_t {
184 uint32_t m_entsize;
185 uint32_t m_count;
187
188 bool Read(Process *process, lldb::addr_t addr);
189 };
190
191 struct ivar_t {
195 uint32_t m_alignment;
196 uint32_t m_size;
197
198 std::string m_name;
199 std::string m_type;
200
201 static size_t GetSize(Process *process) {
202 size_t ptr_size = process->GetAddressByteSize();
203
204 return ptr_size // uintptr_t *offset;
205 + ptr_size // const char *name;
206 + ptr_size // const char *type;
207 + sizeof(uint32_t) // uint32_t alignment;
208 + sizeof(uint32_t); // uint32_t size;
209 }
210
211 bool Read(Process *process, lldb::addr_t addr);
212 };
213
217
218 bool Read(Process *process, lldb::addr_t addr);
219 };
220
222 uint32_t m_entsize;
223 uint32_t m_count;
225
226 bool Read(Process *process, lldb::addr_t addr);
227 };
228
230 public:
231 iVarsStorage();
232
233 size_t size();
234
235 iVarDescriptor &operator[](size_t idx);
236
237 void fill(AppleObjCRuntimeV2 &runtime, ClassDescriptorV2 &descriptor);
238
239 private:
240 bool m_filled = false;
241 std::vector<iVarDescriptor> m_ivars;
242 std::recursive_mutex m_mutex;
243 };
244
245 // The constructor should only be invoked by the runtime as it builds its
246 // caches
247 // or populates them. A ClassDescriptorV2 should only ever exist in a cache.
253
254 bool Read_objc_class(Process *process,
255 std::unique_ptr<objc_class_t> &objc_class) const;
256
257 bool Read_class_row(Process *process, const objc_class_t &objc_class,
258 std::unique_ptr<class_ro_t> &class_ro,
259 std::unique_ptr<class_rw_t> &class_rw) const;
260
261 bool ProcessMethodList(std::function<bool(const char *, const char *)> const
262 &instance_method_func,
263 method_list_t &method_list) const;
264
266 std::function<bool(const char *, const char *)> const
267 &instance_method_func,
268 lldb::addr_t relative_method_list_ptr) const;
269
271 &m_runtime; // The runtime, so we can read information lazily.
272 lldb::addr_t m_objc_class_ptr; // The address of the objc_class_t. (I.e.,
273 // objects of this class type have this as
274 // their ISA)
275 ConstString m_name; // May be NULL
277
278 mutable std::map<uint16_t, std::vector<method_list_t>>
280 mutable std::optional<uint64_t> m_last_version_updated;
281};
282
283// tagged pointer descriptor
285public:
286 ClassDescriptorV2Tagged(ConstString class_name, uint64_t payload) {
287 m_name = class_name;
288 if (!m_name) {
289 m_valid = false;
290 return;
291 }
292 m_valid = true;
293 m_payload = payload;
294 m_info_bits = (m_payload & 0xF0ULL) >> 4;
295 m_value_bits = (m_payload & ~0x0000000000000000FFULL) >> 8;
296 }
297
300 uint64_t u_payload, int64_t s_payload) {
301 if (!actual_class_sp) {
302 m_valid = false;
303 return;
304 }
305 m_name = actual_class_sp->GetClassName();
306 if (!m_name) {
307 m_valid = false;
308 return;
309 }
310 m_valid = true;
311 m_payload = u_payload;
312 m_info_bits = (m_payload & 0x0FULL);
313 m_value_bits = (m_payload & ~0x0FULL) >> 4;
314 m_value_bits_signed = (s_payload & ~0x0FLL) >> 4;
315 }
316
317 ~ClassDescriptorV2Tagged() override = default;
318
319 ConstString GetClassName() override { return m_name; }
320
322 // tagged pointers can represent a class that has a superclass, but since
323 // that information is not
324 // stored in the object itself, we would have to query the runtime to
325 // discover the hierarchy
326 // for the time being, we skip this step in the interest of static discovery
328 }
329
333
334 bool IsValid() override { return m_valid; }
335
336 bool IsKVO() override {
337 return false; // tagged pointers are not KVO'ed
338 }
339
340 bool IsCFType() override {
341 return false; // tagged pointers are not CF objects
342 }
343
344 bool GetTaggedPointerInfo(uint64_t *info_bits = nullptr,
345 uint64_t *value_bits = nullptr,
346 uint64_t *payload = nullptr) override {
347 if (info_bits)
348 *info_bits = GetInfoBits();
349 if (value_bits)
350 *value_bits = GetValueBits();
351 if (payload)
352 *payload = GetPayload();
353 return true;
354 }
355
356 bool GetTaggedPointerInfoSigned(uint64_t *info_bits = nullptr,
357 int64_t *value_bits = nullptr,
358 uint64_t *payload = nullptr) override {
359 if (info_bits)
360 *info_bits = GetInfoBits();
361 if (value_bits)
362 *value_bits = GetValueBitsSigned();
363 if (payload)
364 *payload = GetPayload();
365 return true;
366 }
367
368 uint64_t GetInstanceSize() override {
369 return (IsValid() ? m_pointer_size : 0);
370 }
371
373 return 0; // tagged pointers have no ISA
374 }
375
376 // these calls are not part of any formal tagged pointers specification
377 virtual uint64_t GetValueBits() { return (IsValid() ? m_value_bits : 0); }
378
379 virtual int64_t GetValueBitsSigned() {
380 return (IsValid() ? m_value_bits_signed : 0);
381 }
382
383 virtual uint64_t GetInfoBits() { return (IsValid() ? m_info_bits : 0); }
384
385 virtual uint64_t GetPayload() { return (IsValid() ? m_payload : 0); }
386
387private:
389 uint8_t m_pointer_size = 0;
390 bool m_valid = false;
391 uint64_t m_info_bits = 0;
392 uint64_t m_value_bits = 0;
394 uint64_t m_payload = 0;
395};
396
397} // namespace lldb_private
398
399#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:3664
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)
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)