/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/source/Plugins/LanguageRuntime/ObjC/AppleObjCRuntime/AppleObjCRuntimeV2.h
Line | Count | Source (jump to first uncovered line) |
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 | 2.11k | ~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 | 3.92k | static llvm::StringRef GetPluginNameStatic() { return "apple-objc-v2"; } |
40 | | |
41 | | LanguageRuntime *GetPreferredLanguageRuntime(ValueObject &in_value) override; |
42 | | |
43 | | static char ID; |
44 | | |
45 | 115k | bool isA(const void *ClassID) const override { |
46 | 115k | return ClassID == &ID || AppleObjCRuntime::isA(ClassID); |
47 | 115k | } |
48 | | |
49 | 0 | static bool classof(const LanguageRuntime *runtime) { |
50 | 0 | return runtime->isA(&ID); |
51 | 0 | } |
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 | 0 | llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); } |
63 | | |
64 | 10.9k | ObjCRuntimeVersions GetRuntimeVersion() const override { |
65 | 10.9k | return ObjCRuntimeVersions::eAppleObjC_V2; |
66 | 10.9k | } |
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 | 2 | TaggedPointerVendor *GetTaggedPointerVendor() override { |
86 | 2 | return m_tagged_pointer_vendor_up.get(); |
87 | 2 | } |
88 | | |
89 | | lldb::addr_t GetTaggedPointerObfuscator(); |
90 | | |
91 | | /// Returns the base address for relative method list selector strings. |
92 | 584 | lldb::addr_t GetRelativeSelectorBaseAddr() { |
93 | 584 | return m_relative_selector_base; |
94 | 584 | } |
95 | | |
96 | 0 | void SetRelativeSelectorBaseAddr(lldb::addr_t relative_selector_base) { |
97 | 0 | m_relative_selector_base = relative_selector_base; |
98 | 0 | } |
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 | 2.11k | ~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 | 2.11k | : 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 | 0 | : 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 | 1.94k | DescriptorMapUpdateResult(bool ran, bool retry, uint32_t found) { |
292 | 1.94k | m_update_ran = ran; |
293 | | |
294 | 1.94k | m_retry_update = retry; |
295 | | |
296 | 1.94k | m_num_found = found; |
297 | 1.94k | } |
298 | | |
299 | 0 | static DescriptorMapUpdateResult Fail() { return {false, false, 0}; } |
300 | | |
301 | 0 | static DescriptorMapUpdateResult Success(uint32_t found) { |
302 | 0 | return {true, false, found}; |
303 | 0 | } |
304 | | |
305 | 0 | static DescriptorMapUpdateResult Retry() { return {false, true, 0}; } |
306 | | }; |
307 | | |
308 | | /// Abstraction to read the Objective-C class info. |
309 | | class ClassInfoExtractor { |
310 | | public: |
311 | 4.22k | ClassInfoExtractor(AppleObjCRuntimeV2 &runtime) : m_runtime(runtime) {} |
312 | 0 | 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 | 2.11k | : 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 | 2.11k | : 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 | 0 | 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 | 0 | : m_runtime(runtime), m_headerInfoRWs_ptr(headerInfoRWs_ptr), |
403 | 0 | m_loaded_images(count, false), m_version(0), m_count(count), |
404 | 0 | 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 | 7.92k | NonPointerISACache *GetNonPointerIsaCache() { |
448 | 7.92k | if (!m_non_pointer_isa_cache_up) |
449 | 296 | m_non_pointer_isa_cache_up.reset( |
450 | 296 | NonPointerISACache::CreateInstance(*this, m_objc_module_sp)); |
451 | 7.92k | return m_non_pointer_isa_cache_up.get(); |
452 | 7.92k | } |
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 |