Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
39690 views
1
//===-- AppleObjCRuntimeV2.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_APPLEOBJCRUNTIMEV2_H
10
#define LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCRUNTIMEV2_H
11
12
#include <map>
13
#include <memory>
14
#include <mutex>
15
#include <optional>
16
17
#include "AppleObjCRuntime.h"
18
#include "lldb/lldb-private.h"
19
20
#include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
21
22
#include "llvm/ADT/BitVector.h"
23
24
class RemoteNXMapTable;
25
26
namespace lldb_private {
27
28
class AppleObjCRuntimeV2 : public AppleObjCRuntime {
29
public:
30
~AppleObjCRuntimeV2() override = default;
31
32
static void Initialize();
33
34
static void Terminate();
35
36
static lldb_private::LanguageRuntime *
37
CreateInstance(Process *process, lldb::LanguageType language);
38
39
static llvm::StringRef GetPluginNameStatic() { return "apple-objc-v2"; }
40
41
LanguageRuntime *GetPreferredLanguageRuntime(ValueObject &in_value) override;
42
43
static char ID;
44
45
bool isA(const void *ClassID) const override {
46
return ClassID == &ID || AppleObjCRuntime::isA(ClassID);
47
}
48
49
static bool classof(const LanguageRuntime *runtime) {
50
return runtime->isA(&ID);
51
}
52
53
bool GetDynamicTypeAndAddress(ValueObject &in_value,
54
lldb::DynamicValueType use_dynamic,
55
TypeAndOrName &class_type_or_name,
56
Address &address,
57
Value::ValueType &value_type) override;
58
59
llvm::Expected<std::unique_ptr<UtilityFunction>>
60
CreateObjectChecker(std::string name, ExecutionContext &exe_ctx) override;
61
62
llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
63
64
ObjCRuntimeVersions GetRuntimeVersion() const override {
65
return ObjCRuntimeVersions::eAppleObjC_V2;
66
}
67
68
size_t GetByteOffsetForIvar(CompilerType &parent_ast_type,
69
const char *ivar_name) override;
70
71
void UpdateISAToDescriptorMapIfNeeded() override;
72
73
ClassDescriptorSP GetClassDescriptor(ValueObject &valobj) override;
74
75
ClassDescriptorSP GetClassDescriptorFromISA(ObjCISA isa) override;
76
77
DeclVendor *GetDeclVendor() override;
78
79
lldb::addr_t LookupRuntimeSymbol(ConstString name) override;
80
81
EncodingToTypeSP GetEncodingToType() override;
82
83
bool IsTaggedPointer(lldb::addr_t ptr) override;
84
85
TaggedPointerVendor *GetTaggedPointerVendor() override {
86
return m_tagged_pointer_vendor_up.get();
87
}
88
89
lldb::addr_t GetTaggedPointerObfuscator();
90
91
/// Returns the base address for relative method list selector strings.
92
lldb::addr_t GetRelativeSelectorBaseAddr() {
93
return m_relative_selector_base;
94
}
95
96
void SetRelativeSelectorBaseAddr(lldb::addr_t relative_selector_base) {
97
m_relative_selector_base = relative_selector_base;
98
}
99
100
void GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
101
lldb::addr_t &cf_false) override;
102
103
void ModulesDidLoad(const ModuleList &module_list) override;
104
105
bool IsSharedCacheImageLoaded(uint16_t image_index);
106
107
std::optional<uint64_t> GetSharedCacheImageHeaderVersion();
108
109
protected:
110
lldb::BreakpointResolverSP
111
CreateExceptionResolver(const lldb::BreakpointSP &bkpt, bool catch_bp,
112
bool throw_bp) override;
113
114
private:
115
class HashTableSignature {
116
public:
117
HashTableSignature();
118
119
bool NeedsUpdate(Process *process, AppleObjCRuntimeV2 *runtime,
120
RemoteNXMapTable &hash_table);
121
122
void UpdateSignature(const RemoteNXMapTable &hash_table);
123
124
protected:
125
uint32_t m_count = 0;
126
uint32_t m_num_buckets = 0;
127
lldb::addr_t m_buckets_ptr = 0;
128
};
129
130
class NonPointerISACache {
131
public:
132
static NonPointerISACache *
133
CreateInstance(AppleObjCRuntimeV2 &runtime,
134
const lldb::ModuleSP &objc_module_sp);
135
136
ObjCLanguageRuntime::ClassDescriptorSP GetClassDescriptor(ObjCISA isa);
137
138
private:
139
NonPointerISACache(AppleObjCRuntimeV2 &runtime,
140
const lldb::ModuleSP &objc_module_sp,
141
uint64_t objc_debug_isa_class_mask,
142
uint64_t objc_debug_isa_magic_mask,
143
uint64_t objc_debug_isa_magic_value,
144
uint64_t objc_debug_indexed_isa_magic_mask,
145
uint64_t objc_debug_indexed_isa_magic_value,
146
uint64_t objc_debug_indexed_isa_index_mask,
147
uint64_t objc_debug_indexed_isa_index_shift,
148
lldb::addr_t objc_indexed_classes);
149
150
bool EvaluateNonPointerISA(ObjCISA isa, ObjCISA &ret_isa);
151
152
AppleObjCRuntimeV2 &m_runtime;
153
std::map<ObjCISA, ObjCLanguageRuntime::ClassDescriptorSP> m_cache;
154
lldb::ModuleWP m_objc_module_wp;
155
uint64_t m_objc_debug_isa_class_mask;
156
uint64_t m_objc_debug_isa_magic_mask;
157
uint64_t m_objc_debug_isa_magic_value;
158
159
uint64_t m_objc_debug_indexed_isa_magic_mask;
160
uint64_t m_objc_debug_indexed_isa_magic_value;
161
uint64_t m_objc_debug_indexed_isa_index_mask;
162
uint64_t m_objc_debug_indexed_isa_index_shift;
163
lldb::addr_t m_objc_indexed_classes;
164
165
std::vector<lldb::addr_t> m_indexed_isa_cache;
166
167
friend class AppleObjCRuntimeV2;
168
169
NonPointerISACache(const NonPointerISACache &) = delete;
170
const NonPointerISACache &operator=(const NonPointerISACache &) = delete;
171
};
172
173
class TaggedPointerVendorV2
174
: public ObjCLanguageRuntime::TaggedPointerVendor {
175
public:
176
~TaggedPointerVendorV2() override = default;
177
178
static TaggedPointerVendorV2 *
179
CreateInstance(AppleObjCRuntimeV2 &runtime,
180
const lldb::ModuleSP &objc_module_sp);
181
182
protected:
183
AppleObjCRuntimeV2 &m_runtime;
184
185
TaggedPointerVendorV2(AppleObjCRuntimeV2 &runtime)
186
: TaggedPointerVendor(), m_runtime(runtime) {}
187
188
private:
189
TaggedPointerVendorV2(const TaggedPointerVendorV2 &) = delete;
190
const TaggedPointerVendorV2 &
191
operator=(const TaggedPointerVendorV2 &) = delete;
192
};
193
194
class TaggedPointerVendorRuntimeAssisted : public TaggedPointerVendorV2 {
195
public:
196
bool IsPossibleTaggedPointer(lldb::addr_t ptr) override;
197
198
ObjCLanguageRuntime::ClassDescriptorSP
199
GetClassDescriptor(lldb::addr_t ptr) override;
200
201
protected:
202
TaggedPointerVendorRuntimeAssisted(
203
AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,
204
uint32_t objc_debug_taggedpointer_slot_shift,
205
uint32_t objc_debug_taggedpointer_slot_mask,
206
uint32_t objc_debug_taggedpointer_payload_lshift,
207
uint32_t objc_debug_taggedpointer_payload_rshift,
208
lldb::addr_t objc_debug_taggedpointer_classes);
209
210
typedef std::map<uint8_t, ObjCLanguageRuntime::ClassDescriptorSP> Cache;
211
typedef Cache::iterator CacheIterator;
212
Cache m_cache;
213
uint64_t m_objc_debug_taggedpointer_mask;
214
uint32_t m_objc_debug_taggedpointer_slot_shift;
215
uint32_t m_objc_debug_taggedpointer_slot_mask;
216
uint32_t m_objc_debug_taggedpointer_payload_lshift;
217
uint32_t m_objc_debug_taggedpointer_payload_rshift;
218
lldb::addr_t m_objc_debug_taggedpointer_classes;
219
220
friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;
221
222
TaggedPointerVendorRuntimeAssisted(
223
const TaggedPointerVendorRuntimeAssisted &) = delete;
224
const TaggedPointerVendorRuntimeAssisted &
225
operator=(const TaggedPointerVendorRuntimeAssisted &) = delete;
226
};
227
228
class TaggedPointerVendorExtended
229
: public TaggedPointerVendorRuntimeAssisted {
230
public:
231
ObjCLanguageRuntime::ClassDescriptorSP
232
GetClassDescriptor(lldb::addr_t ptr) override;
233
234
protected:
235
TaggedPointerVendorExtended(
236
AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,
237
uint64_t objc_debug_taggedpointer_ext_mask,
238
uint32_t objc_debug_taggedpointer_slot_shift,
239
uint32_t objc_debug_taggedpointer_ext_slot_shift,
240
uint32_t objc_debug_taggedpointer_slot_mask,
241
uint32_t objc_debug_taggedpointer_ext_slot_mask,
242
uint32_t objc_debug_taggedpointer_payload_lshift,
243
uint32_t objc_debug_taggedpointer_payload_rshift,
244
uint32_t objc_debug_taggedpointer_ext_payload_lshift,
245
uint32_t objc_debug_taggedpointer_ext_payload_rshift,
246
lldb::addr_t objc_debug_taggedpointer_classes,
247
lldb::addr_t objc_debug_taggedpointer_ext_classes);
248
249
bool IsPossibleExtendedTaggedPointer(lldb::addr_t ptr);
250
251
typedef std::map<uint8_t, ObjCLanguageRuntime::ClassDescriptorSP> Cache;
252
typedef Cache::iterator CacheIterator;
253
Cache m_ext_cache;
254
uint64_t m_objc_debug_taggedpointer_ext_mask;
255
uint32_t m_objc_debug_taggedpointer_ext_slot_shift;
256
uint32_t m_objc_debug_taggedpointer_ext_slot_mask;
257
uint32_t m_objc_debug_taggedpointer_ext_payload_lshift;
258
uint32_t m_objc_debug_taggedpointer_ext_payload_rshift;
259
lldb::addr_t m_objc_debug_taggedpointer_ext_classes;
260
261
friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;
262
263
TaggedPointerVendorExtended(const TaggedPointerVendorExtended &) = delete;
264
const TaggedPointerVendorExtended &
265
operator=(const TaggedPointerVendorExtended &) = delete;
266
};
267
268
class TaggedPointerVendorLegacy : public TaggedPointerVendorV2 {
269
public:
270
bool IsPossibleTaggedPointer(lldb::addr_t ptr) override;
271
272
ObjCLanguageRuntime::ClassDescriptorSP
273
GetClassDescriptor(lldb::addr_t ptr) override;
274
275
protected:
276
TaggedPointerVendorLegacy(AppleObjCRuntimeV2 &runtime)
277
: TaggedPointerVendorV2(runtime) {}
278
279
friend class AppleObjCRuntimeV2::TaggedPointerVendorV2;
280
281
TaggedPointerVendorLegacy(const TaggedPointerVendorLegacy &) = delete;
282
const TaggedPointerVendorLegacy &
283
operator=(const TaggedPointerVendorLegacy &) = delete;
284
};
285
286
struct DescriptorMapUpdateResult {
287
bool m_update_ran;
288
bool m_retry_update;
289
uint32_t m_num_found;
290
291
DescriptorMapUpdateResult(bool ran, bool retry, uint32_t found) {
292
m_update_ran = ran;
293
294
m_retry_update = retry;
295
296
m_num_found = found;
297
}
298
299
static DescriptorMapUpdateResult Fail() { return {false, false, 0}; }
300
301
static DescriptorMapUpdateResult Success(uint32_t found) {
302
return {true, false, found};
303
}
304
305
static DescriptorMapUpdateResult Retry() { return {false, true, 0}; }
306
};
307
308
/// Abstraction to read the Objective-C class info.
309
class ClassInfoExtractor {
310
public:
311
ClassInfoExtractor(AppleObjCRuntimeV2 &runtime) : m_runtime(runtime) {}
312
std::mutex &GetMutex() { return m_mutex; }
313
314
protected:
315
/// The lifetime of this object is tied to that of the runtime.
316
AppleObjCRuntimeV2 &m_runtime;
317
std::mutex m_mutex;
318
};
319
320
/// We can read the class info from the Objective-C runtime using
321
/// gdb_objc_realized_classes, objc_copyRealizedClassList or
322
/// objc_getRealizedClassList_trylock. The RealizedClassList variants are
323
/// preferred because they include lazily named classes, but they are not
324
/// always available or safe to call.
325
///
326
/// We potentially need more than one helper for the same process, because we
327
/// may need to use gdb_objc_realized_classes until dyld is initialized and
328
/// then switch over to objc_copyRealizedClassList or
329
/// objc_getRealizedClassList_trylock for lazily named classes.
330
class DynamicClassInfoExtractor : public ClassInfoExtractor {
331
public:
332
DynamicClassInfoExtractor(AppleObjCRuntimeV2 &runtime)
333
: ClassInfoExtractor(runtime) {}
334
335
DescriptorMapUpdateResult
336
UpdateISAToDescriptorMap(RemoteNXMapTable &hash_table);
337
338
private:
339
enum Helper {
340
gdb_objc_realized_classes,
341
objc_copyRealizedClassList,
342
objc_getRealizedClassList_trylock
343
};
344
345
/// Compute which helper to use. If dyld is not yet fully initialized we
346
/// must use gdb_objc_realized_classes. Otherwise, we prefer
347
/// objc_getRealizedClassList_trylock and objc_copyRealizedClassList
348
/// respectively, depending on availability.
349
Helper ComputeHelper(ExecutionContext &exe_ctx) const;
350
351
UtilityFunction *GetClassInfoUtilityFunction(ExecutionContext &exe_ctx,
352
Helper helper);
353
lldb::addr_t &GetClassInfoArgs(Helper helper);
354
355
std::unique_ptr<UtilityFunction>
356
GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx, Helper helper,
357
std::string code, std::string name);
358
359
struct UtilityFunctionHelper {
360
std::unique_ptr<UtilityFunction> utility_function;
361
lldb::addr_t args = LLDB_INVALID_ADDRESS;
362
};
363
364
UtilityFunctionHelper m_gdb_objc_realized_classes_helper;
365
UtilityFunctionHelper m_objc_copyRealizedClassList_helper;
366
UtilityFunctionHelper m_objc_getRealizedClassList_trylock_helper;
367
};
368
369
/// Abstraction to read the Objective-C class info from the shared cache.
370
class SharedCacheClassInfoExtractor : public ClassInfoExtractor {
371
public:
372
SharedCacheClassInfoExtractor(AppleObjCRuntimeV2 &runtime)
373
: ClassInfoExtractor(runtime) {}
374
375
DescriptorMapUpdateResult UpdateISAToDescriptorMap();
376
377
private:
378
UtilityFunction *GetClassInfoUtilityFunction(ExecutionContext &exe_ctx);
379
380
std::unique_ptr<UtilityFunction>
381
GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx);
382
383
std::unique_ptr<UtilityFunction> m_utility_function;
384
lldb::addr_t m_args = LLDB_INVALID_ADDRESS;
385
};
386
387
class SharedCacheImageHeaders {
388
public:
389
static std::unique_ptr<SharedCacheImageHeaders>
390
CreateSharedCacheImageHeaders(AppleObjCRuntimeV2 &runtime);
391
392
void SetNeedsUpdate() { m_needs_update = true; }
393
394
bool IsImageLoaded(uint16_t image_index);
395
396
uint64_t GetVersion();
397
398
private:
399
SharedCacheImageHeaders(AppleObjCRuntimeV2 &runtime,
400
lldb::addr_t headerInfoRWs_ptr, uint32_t count,
401
uint32_t entsize)
402
: m_runtime(runtime), m_headerInfoRWs_ptr(headerInfoRWs_ptr),
403
m_loaded_images(count, false), m_version(0), m_count(count),
404
m_entsize(entsize), m_needs_update(true) {}
405
llvm::Error UpdateIfNeeded();
406
407
AppleObjCRuntimeV2 &m_runtime;
408
lldb::addr_t m_headerInfoRWs_ptr;
409
llvm::BitVector m_loaded_images;
410
uint64_t m_version;
411
uint32_t m_count;
412
uint32_t m_entsize;
413
bool m_needs_update;
414
};
415
416
AppleObjCRuntimeV2(Process *process, const lldb::ModuleSP &objc_module_sp);
417
418
ObjCISA GetPointerISA(ObjCISA isa);
419
420
lldb::addr_t GetISAHashTablePointer();
421
422
/// Update the generation count of realized classes. This is not an exact
423
/// count but rather a value that is incremented when new classes are realized
424
/// or destroyed. Unlike the count in gdb_objc_realized_classes, it will
425
/// change when lazily named classes get realized.
426
bool RealizedClassGenerationCountChanged();
427
428
uint32_t ParseClassInfoArray(const lldb_private::DataExtractor &data,
429
uint32_t num_class_infos);
430
431
enum class SharedCacheWarningReason {
432
eExpressionUnableToRun,
433
eExpressionExecutionFailure,
434
eNotEnoughClassesRead
435
};
436
437
void WarnIfNoClassesCached(SharedCacheWarningReason reason);
438
void WarnIfNoExpandedSharedCache();
439
440
lldb::addr_t GetSharedCacheReadOnlyAddress();
441
lldb::addr_t GetSharedCacheBaseAddress();
442
443
bool GetCFBooleanValuesIfNeeded();
444
445
bool HasSymbol(ConstString Name);
446
447
NonPointerISACache *GetNonPointerIsaCache() {
448
if (!m_non_pointer_isa_cache_up)
449
m_non_pointer_isa_cache_up.reset(
450
NonPointerISACache::CreateInstance(*this, m_objc_module_sp));
451
return m_non_pointer_isa_cache_up.get();
452
}
453
454
friend class ClassDescriptorV2;
455
456
lldb::ModuleSP m_objc_module_sp;
457
458
DynamicClassInfoExtractor m_dynamic_class_info_extractor;
459
SharedCacheClassInfoExtractor m_shared_cache_class_info_extractor;
460
461
std::unique_ptr<DeclVendor> m_decl_vendor_up;
462
lldb::addr_t m_tagged_pointer_obfuscator;
463
lldb::addr_t m_isa_hash_table_ptr;
464
lldb::addr_t m_relative_selector_base;
465
HashTableSignature m_hash_signature;
466
bool m_has_object_getClass;
467
bool m_has_objc_copyRealizedClassList;
468
bool m_has_objc_getRealizedClassList_trylock;
469
bool m_loaded_objc_opt;
470
std::unique_ptr<NonPointerISACache> m_non_pointer_isa_cache_up;
471
std::unique_ptr<TaggedPointerVendor> m_tagged_pointer_vendor_up;
472
EncodingToTypeSP m_encoding_to_type_sp;
473
std::once_flag m_no_classes_cached_warning;
474
std::once_flag m_no_expanded_cache_warning;
475
std::optional<std::pair<lldb::addr_t, lldb::addr_t>> m_CFBoolean_values;
476
uint64_t m_realized_class_generation_count;
477
std::unique_ptr<SharedCacheImageHeaders> m_shared_cache_image_headers_up;
478
};
479
480
} // namespace lldb_private
481
482
#endif // LLDB_SOURCE_PLUGINS_LANGUAGERUNTIME_OBJC_APPLEOBJCRUNTIME_APPLEOBJCRUNTIMEV2_H
483
484