1 //===-- AppleObjCRuntimeV2.cpp --------------------------------------------===//
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 #include "Plugins/LanguageRuntime/ObjC/ObjCLanguageRuntime.h"
10 #include "Plugins/TypeSystem/Clang/TypeSystemClang.h"
11 
12 #include "lldb/Core/Debugger.h"
13 #include "lldb/Core/DebuggerEvents.h"
14 #include "lldb/Core/Module.h"
15 #include "lldb/Core/PluginManager.h"
16 #include "lldb/Core/Section.h"
17 #include "lldb/Core/ValueObjectConstResult.h"
18 #include "lldb/Core/ValueObjectVariable.h"
19 #include "lldb/Expression/DiagnosticManager.h"
20 #include "lldb/Expression/FunctionCaller.h"
21 #include "lldb/Expression/UtilityFunction.h"
22 #include "lldb/Host/OptionParser.h"
23 #include "lldb/Interpreter/CommandObject.h"
24 #include "lldb/Interpreter/CommandObjectMultiword.h"
25 #include "lldb/Interpreter/CommandReturnObject.h"
26 #include "lldb/Interpreter/OptionArgParser.h"
27 #include "lldb/Interpreter/OptionValueBoolean.h"
28 #include "lldb/Symbol/CompilerType.h"
29 #include "lldb/Symbol/ObjectFile.h"
30 #include "lldb/Symbol/Symbol.h"
31 #include "lldb/Symbol/TypeList.h"
32 #include "lldb/Symbol/VariableList.h"
33 #include "lldb/Target/ABI.h"
34 #include "lldb/Target/DynamicLoader.h"
35 #include "lldb/Target/ExecutionContext.h"
36 #include "lldb/Target/LanguageRuntime.h"
37 #include "lldb/Target/Platform.h"
38 #include "lldb/Target/Process.h"
39 #include "lldb/Target/RegisterContext.h"
40 #include "lldb/Target/StackFrameRecognizer.h"
41 #include "lldb/Target/Target.h"
42 #include "lldb/Target/Thread.h"
43 #include "lldb/Utility/ConstString.h"
44 #include "lldb/Utility/LLDBLog.h"
45 #include "lldb/Utility/Log.h"
46 #include "lldb/Utility/Scalar.h"
47 #include "lldb/Utility/Status.h"
48 #include "lldb/Utility/Stream.h"
49 #include "lldb/Utility/StreamString.h"
50 #include "lldb/Utility/Timer.h"
51 #include "lldb/lldb-enumerations.h"
52 
53 #include "AppleObjCClassDescriptorV2.h"
54 #include "AppleObjCDeclVendor.h"
55 #include "AppleObjCRuntimeV2.h"
56 #include "AppleObjCTrampolineHandler.h"
57 #include "AppleObjCTypeEncodingParser.h"
58 
59 #include "clang/AST/ASTContext.h"
60 #include "clang/AST/DeclObjC.h"
61 #include "clang/Basic/TargetInfo.h"
62 #include "llvm/ADT/ScopeExit.h"
63 
64 #include <cstdint>
65 #include <memory>
66 #include <string>
67 #include <vector>
68 
69 using namespace lldb;
70 using namespace lldb_private;
71 
72 char AppleObjCRuntimeV2::ID = 0;
73 
74 static const char *g_get_dynamic_class_info_name =
75     "__lldb_apple_objc_v2_get_dynamic_class_info";
76 
77 static const char *g_get_dynamic_class_info_body = R"(
78 
79 extern "C"
80 {
81     size_t strlen(const char *);
82     char *strncpy (char * s1, const char * s2, size_t n);
83     int printf(const char * format, ...);
84 }
85 #define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__)
86 
87 typedef struct _NXMapTable {
88     void *prototype;
89     unsigned num_classes;
90     unsigned num_buckets_minus_one;
91     void *buckets;
92 } NXMapTable;
93 
94 #define NX_MAPNOTAKEY   ((void *)(-1))
95 
96 typedef struct BucketInfo
97 {
98     const char *name_ptr;
99     Class isa;
100 } BucketInfo;
101 
102 struct ClassInfo
103 {
104     Class isa;
105     uint32_t hash;
106 } __attribute__((__packed__));
107 
108 uint32_t
109 __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr,
110                                              void *class_infos_ptr,
111                                              uint32_t class_infos_byte_size,
112                                              uint32_t should_log)
113 {
114     DEBUG_PRINTF ("gdb_objc_realized_classes_ptr = %p\n", gdb_objc_realized_classes_ptr);
115     DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
116     DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size);
117     const NXMapTable *grc = (const NXMapTable *)gdb_objc_realized_classes_ptr;
118     if (grc)
119     {
120         const unsigned num_classes = grc->num_classes;
121         DEBUG_PRINTF ("num_classes = %u\n", grc->num_classes);
122         if (class_infos_ptr)
123         {
124             const unsigned num_buckets_minus_one = grc->num_buckets_minus_one;
125             DEBUG_PRINTF ("num_buckets_minus_one = %u\n", num_buckets_minus_one);
126 
127             const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
128             DEBUG_PRINTF ("max_class_infos = %u\n", max_class_infos);
129 
130             ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
131             BucketInfo *buckets = (BucketInfo *)grc->buckets;
132 
133             uint32_t idx = 0;
134             for (unsigned i=0; i<=num_buckets_minus_one; ++i)
135             {
136                 if (buckets[i].name_ptr != NX_MAPNOTAKEY)
137                 {
138                     if (idx < max_class_infos)
139                     {
140                         const char *s = buckets[i].name_ptr;
141                         uint32_t h = 5381;
142                         for (unsigned char c = *s; c; c = *++s)
143                             h = ((h << 5) + h) + c;
144                         class_infos[idx].hash = h;
145                         class_infos[idx].isa = buckets[i].isa;
146                         DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, buckets[i].name_ptr);
147                     }
148                     ++idx;
149                 }
150             }
151             if (idx < max_class_infos)
152             {
153                 class_infos[idx].isa = NULL;
154                 class_infos[idx].hash = 0;
155             }
156         }
157         return num_classes;
158     }
159     return 0;
160 }
161 
162 )";
163 
164 static const char *g_get_dynamic_class_info2_name =
165     "__lldb_apple_objc_v2_get_dynamic_class_info2";
166 
167 static const char *g_get_dynamic_class_info2_body = R"(
168 
169 extern "C" {
170     int printf(const char * format, ...);
171     void free(void *ptr);
172     Class* objc_copyRealizedClassList_nolock(unsigned int *outCount);
173     const char* objc_debug_class_getNameRaw(Class cls);
174 }
175 
176 #define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__)
177 
178 struct ClassInfo
179 {
180     Class isa;
181     uint32_t hash;
182 } __attribute__((__packed__));
183 
184 uint32_t
185 __lldb_apple_objc_v2_get_dynamic_class_info2(void *gdb_objc_realized_classes_ptr,
186                                              void *class_infos_ptr,
187                                              uint32_t class_infos_byte_size,
188                                              uint32_t should_log)
189 {
190     DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
191     DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size);
192 
193     const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
194     DEBUG_PRINTF ("max_class_infos = %u\n", max_class_infos);
195 
196     ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
197 
198     uint32_t count = 0;
199     Class* realized_class_list = objc_copyRealizedClassList_nolock(&count);
200     DEBUG_PRINTF ("count = %u\n", count);
201 
202     uint32_t idx = 0;
203     for (uint32_t i=0; i<count; ++i)
204     {
205         if (idx < max_class_infos)
206         {
207             Class isa = realized_class_list[i];
208             const char *name_ptr = objc_debug_class_getNameRaw(isa);
209             if (!name_ptr)
210                 continue;
211             const char *s = name_ptr;
212             uint32_t h = 5381;
213             for (unsigned char c = *s; c; c = *++s)
214                 h = ((h << 5) + h) + c;
215             class_infos[idx].hash = h;
216             class_infos[idx].isa = isa;
217             DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name_ptr);
218         }
219         idx++;
220     }
221 
222     if (idx < max_class_infos)
223     {
224         class_infos[idx].isa = NULL;
225         class_infos[idx].hash = 0;
226     }
227 
228     free(realized_class_list);
229     return count;
230 }
231 )";
232 
233 static const char *g_get_dynamic_class_info3_name =
234     "__lldb_apple_objc_v2_get_dynamic_class_info3";
235 
236 static const char *g_get_dynamic_class_info3_body = R"(
237 
238 extern "C" {
239     int printf(const char * format, ...);
240     void free(void *ptr);
241     size_t objc_getRealizedClassList_trylock(Class *buffer, size_t len);
242     const char* objc_debug_class_getNameRaw(Class cls);
243     const char* class_getName(Class cls);
244 }
245 
246 #define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__)
247 
248 struct ClassInfo
249 {
250     Class isa;
251     uint32_t hash;
252 } __attribute__((__packed__));
253 
254 uint32_t
255 __lldb_apple_objc_v2_get_dynamic_class_info3(void *gdb_objc_realized_classes_ptr,
256                                              void *class_infos_ptr,
257                                              uint32_t class_infos_byte_size,
258                                              void *class_buffer,
259                                              uint32_t class_buffer_len,
260                                              uint32_t should_log)
261 {
262     DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
263     DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size);
264 
265     const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
266     DEBUG_PRINTF ("max_class_infos = %u\n", max_class_infos);
267 
268     ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
269 
270     Class *realized_class_list = (Class*)class_buffer;
271 
272     uint32_t count = objc_getRealizedClassList_trylock(realized_class_list,
273                                                        class_buffer_len);
274     DEBUG_PRINTF ("count = %u\n", count);
275 
276     uint32_t idx = 0;
277     for (uint32_t i=0; i<count; ++i)
278     {
279         if (idx < max_class_infos)
280         {
281             Class isa = realized_class_list[i];
282             const char *name_ptr = objc_debug_class_getNameRaw(isa);
283             if (!name_ptr) {
284                class_getName(isa); // Realize name of lazy classes.
285                name_ptr = objc_debug_class_getNameRaw(isa);
286             }
287             if (!name_ptr)
288                 continue;
289             const char *s = name_ptr;
290             uint32_t h = 5381;
291             for (unsigned char c = *s; c; c = *++s)
292                 h = ((h << 5) + h) + c;
293             class_infos[idx].hash = h;
294             class_infos[idx].isa = isa;
295             DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name_ptr);
296         }
297         idx++;
298     }
299 
300     if (idx < max_class_infos)
301     {
302         class_infos[idx].isa = NULL;
303         class_infos[idx].hash = 0;
304     }
305 
306     return count;
307 }
308 )";
309 
310 // We'll substitute in class_getName or class_getNameRaw depending
311 // on which is present.
312 static const char *g_shared_cache_class_name_funcptr = R"(
313 extern "C"
314 {
315     const char *%s(void *objc_class);
316     const char *(*class_name_lookup_func)(void *) = %s;
317 }
318 )";
319 
320 static const char *g_get_shared_cache_class_info_name =
321     "__lldb_apple_objc_v2_get_shared_cache_class_info";
322 
323 static const char *g_get_shared_cache_class_info_body = R"(
324 
325 extern "C"
326 {
327     size_t strlen(const char *);
328     char *strncpy (char * s1, const char * s2, size_t n);
329     int printf(const char * format, ...);
330 }
331 
332 #define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__)
333 
334 
335 struct objc_classheader_t {
336     int32_t clsOffset;
337     int32_t hiOffset;
338 };
339 
340 struct objc_classheader_v16_t {
341     uint64_t isDuplicate       : 1,
342              objectCacheOffset : 47, // Offset from the shared cache base
343              dylibObjCIndex    : 16;
344 };
345 
346 struct objc_clsopt_t {
347     uint32_t capacity;
348     uint32_t occupied;
349     uint32_t shift;
350     uint32_t mask;
351     uint32_t zero;
352     uint32_t unused;
353     uint64_t salt;
354     uint32_t scramble[256];
355     uint8_t tab[0]; // tab[mask+1]
356     //  uint8_t checkbytes[capacity];
357     //  int32_t offset[capacity];
358     //  objc_classheader_t clsOffsets[capacity];
359     //  uint32_t duplicateCount;
360     //  objc_classheader_t duplicateOffsets[duplicateCount];
361 };
362 
363 struct objc_clsopt_v16_t {
364    uint32_t version;
365    uint32_t capacity;
366    uint32_t occupied;
367    uint32_t shift;
368    uint32_t mask;
369    uint32_t zero;
370    uint64_t salt;
371    uint32_t scramble[256];
372    uint8_t  tab[0]; // tab[mask+1]
373    //  uint8_t checkbytes[capacity];
374    //  int32_t offset[capacity];
375    //  objc_classheader_t clsOffsets[capacity];
376    //  uint32_t duplicateCount;
377    //  objc_classheader_t duplicateOffsets[duplicateCount];
378 };
379 
380 struct objc_opt_t {
381     uint32_t version;
382     int32_t selopt_offset;
383     int32_t headeropt_offset;
384     int32_t clsopt_offset;
385 };
386 
387 struct objc_opt_v14_t {
388     uint32_t version;
389     uint32_t flags;
390     int32_t selopt_offset;
391     int32_t headeropt_offset;
392     int32_t clsopt_offset;
393 };
394 
395 struct objc_opt_v16_t {
396     uint32_t version;
397     uint32_t flags;
398     int32_t selopt_offset;
399     int32_t headeropt_ro_offset;
400     int32_t unused_clsopt_offset;
401     int32_t unused_protocolopt_offset;
402     int32_t headeropt_rw_offset;
403     int32_t unused_protocolopt2_offset;
404     int32_t largeSharedCachesClassOffset;
405     int32_t largeSharedCachesProtocolOffset;
406     uint64_t relativeMethodSelectorBaseAddressCacheOffset;
407 };
408 
409 struct ClassInfo
410 {
411     Class isa;
412     uint32_t hash;
413 }  __attribute__((__packed__));
414 
415 uint32_t
416 __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
417                                                   void *shared_cache_base_ptr,
418                                                   void *class_infos_ptr,
419                                                   uint64_t *relative_selector_offset,
420                                                   uint32_t class_infos_byte_size,
421                                                   uint32_t should_log)
422 {
423     *relative_selector_offset = 0;
424     uint32_t idx = 0;
425     DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr);
426     DEBUG_PRINTF ("shared_cache_base_ptr = %p\n", shared_cache_base_ptr);
427     DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
428     DEBUG_PRINTF ("class_infos_byte_size = %u (%llu class infos)\n", class_infos_byte_size, (uint64_t)(class_infos_byte_size/sizeof(ClassInfo)));
429     if (objc_opt_ro_ptr)
430     {
431         const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr;
432         const objc_opt_v14_t* objc_opt_v14 = (objc_opt_v14_t*)objc_opt_ro_ptr;
433         const objc_opt_v16_t* objc_opt_v16 = (objc_opt_v16_t*)objc_opt_ro_ptr;
434         if (objc_opt->version >= 16)
435         {
436             *relative_selector_offset = objc_opt_v16->relativeMethodSelectorBaseAddressCacheOffset;
437             DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v16->version);
438             DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v16->flags);
439             DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt_v16->selopt_offset);
440             DEBUG_PRINTF ("objc_opt->headeropt_ro_offset = %d\n", objc_opt_v16->headeropt_ro_offset);
441             DEBUG_PRINTF ("objc_opt->relativeMethodSelectorBaseAddressCacheOffset = %d\n", *relative_selector_offset);
442         }
443         else if (objc_opt->version >= 14)
444         {
445             DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v14->version);
446             DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v14->flags);
447             DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt_v14->selopt_offset);
448             DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt_v14->headeropt_offset);
449             DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt_v14->clsopt_offset);
450         }
451         else
452         {
453             DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt->version);
454             DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt->selopt_offset);
455             DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset);
456             DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset);
457         }
458 
459         if (objc_opt->version == 16)
460         {
461             const objc_clsopt_v16_t* clsopt = (const objc_clsopt_v16_t*)((uint8_t *)objc_opt + objc_opt_v16->largeSharedCachesClassOffset);
462             const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
463 
464             DEBUG_PRINTF("max_class_infos = %llu\n", (uint64_t)max_class_infos);
465 
466             ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
467 
468             const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1];
469             const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity);
470             const objc_classheader_v16_t *classOffsets = (const objc_classheader_v16_t *)(offsets + clsopt->capacity);
471 
472             DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity);
473             DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask);
474             DEBUG_PRINTF ("classOffsets = %p\n", classOffsets);
475 
476             for (uint32_t i=0; i<clsopt->capacity; ++i)
477             {
478                 const uint64_t objectCacheOffset = classOffsets[i].objectCacheOffset;
479                 DEBUG_PRINTF("objectCacheOffset[%u] = %u\n", i, objectCacheOffset);
480 
481                 if (classOffsets[i].isDuplicate) {
482                     DEBUG_PRINTF("isDuplicate = true\n");
483                     continue; // duplicate
484                 }
485 
486                 if (objectCacheOffset == 0) {
487                     DEBUG_PRINTF("objectCacheOffset == invalidEntryOffset\n");
488                     continue; // invalid offset
489                 }
490 
491                 if (class_infos && idx < max_class_infos)
492                 {
493                     class_infos[idx].isa = (Class)((uint8_t *)shared_cache_base_ptr + objectCacheOffset);
494 
495                     // Lookup the class name.
496                     const char *name = class_name_lookup_func(class_infos[idx].isa);
497                     DEBUG_PRINTF("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
498 
499                     // Hash the class name so we don't have to read it.
500                     const char *s = name;
501                     uint32_t h = 5381;
502                     for (unsigned char c = *s; c; c = *++s)
503                     {
504                         // class_getName demangles swift names and the hash must
505                         // be calculated on the mangled name.  hash==0 means lldb
506                         // will fetch the mangled name and compute the hash in
507                         // ParseClassInfoArray.
508                         if (c == '.')
509                         {
510                             h = 0;
511                             break;
512                         }
513                         h = ((h << 5) + h) + c;
514                     }
515                     class_infos[idx].hash = h;
516                 }
517                 else
518                 {
519                     DEBUG_PRINTF("not(class_infos && idx < max_class_infos)\n");
520                 }
521                 ++idx;
522             }
523 
524             const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
525             const uint32_t duplicate_count = *duplicate_count_ptr;
526             const objc_classheader_v16_t *duplicateClassOffsets = (const objc_classheader_v16_t *)(&duplicate_count_ptr[1]);
527 
528             DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count);
529             DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets);
530 
531             for (uint32_t i=0; i<duplicate_count; ++i)
532             {
533                 const uint64_t objectCacheOffset = classOffsets[i].objectCacheOffset;
534                 DEBUG_PRINTF("objectCacheOffset[%u] = %u\n", i, objectCacheOffset);
535 
536                 if (classOffsets[i].isDuplicate) {
537                     DEBUG_PRINTF("isDuplicate = true\n");
538                     continue; // duplicate
539                 }
540 
541                 if (objectCacheOffset == 0) {
542                     DEBUG_PRINTF("objectCacheOffset == invalidEntryOffset\n");
543                     continue; // invalid offset
544                 }
545 
546                 if (class_infos && idx < max_class_infos)
547                 {
548                     class_infos[idx].isa = (Class)((uint8_t *)shared_cache_base_ptr + objectCacheOffset);
549 
550                     // Lookup the class name.
551                     const char *name = class_name_lookup_func(class_infos[idx].isa);
552                     DEBUG_PRINTF("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
553 
554                     // Hash the class name so we don't have to read it.
555                     const char *s = name;
556                     uint32_t h = 5381;
557                     for (unsigned char c = *s; c; c = *++s)
558                     {
559                         // class_getName demangles swift names and the hash must
560                         // be calculated on the mangled name.  hash==0 means lldb
561                         // will fetch the mangled name and compute the hash in
562                         // ParseClassInfoArray.
563                         if (c == '.')
564                         {
565                             h = 0;
566                             break;
567                         }
568                         h = ((h << 5) + h) + c;
569                     }
570                     class_infos[idx].hash = h;
571                 }
572             }
573         }
574         else if (objc_opt->version >= 12 && objc_opt->version <= 15)
575         {
576             const objc_clsopt_t* clsopt = NULL;
577             if (objc_opt->version >= 14)
578                 clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt_v14 + objc_opt_v14->clsopt_offset);
579             else
580                 clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset);
581             const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
582             DEBUG_PRINTF("max_class_infos = %llu\n", (uint64_t)max_class_infos);
583             ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
584             int32_t invalidEntryOffset = 0;
585             // this is safe to do because the version field order is invariant
586             if (objc_opt->version == 12)
587                 invalidEntryOffset = 16;
588             const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1];
589             const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity);
590             const objc_classheader_t *classOffsets = (const objc_classheader_t *)(offsets + clsopt->capacity);
591             DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity);
592             DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask);
593             DEBUG_PRINTF ("classOffsets = %p\n", classOffsets);
594             DEBUG_PRINTF("invalidEntryOffset = %d\n", invalidEntryOffset);
595             for (uint32_t i=0; i<clsopt->capacity; ++i)
596             {
597                 const int32_t clsOffset = classOffsets[i].clsOffset;
598                 DEBUG_PRINTF("clsOffset[%u] = %u\n", i, clsOffset);
599                 if (clsOffset & 1)
600                 {
601                     DEBUG_PRINTF("clsOffset & 1\n");
602                     continue; // duplicate
603                 }
604                 else if (clsOffset == invalidEntryOffset)
605                 {
606                     DEBUG_PRINTF("clsOffset == invalidEntryOffset\n");
607                     continue; // invalid offset
608                 }
609 
610                 if (class_infos && idx < max_class_infos)
611                 {
612                     class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
613                     const char *name = class_name_lookup_func (class_infos[idx].isa);
614                     DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
615                     // Hash the class name so we don't have to read it
616                     const char *s = name;
617                     uint32_t h = 5381;
618                     for (unsigned char c = *s; c; c = *++s)
619                     {
620                         // class_getName demangles swift names and the hash must
621                         // be calculated on the mangled name.  hash==0 means lldb
622                         // will fetch the mangled name and compute the hash in
623                         // ParseClassInfoArray.
624                         if (c == '.')
625                         {
626                             h = 0;
627                             break;
628                         }
629                         h = ((h << 5) + h) + c;
630                     }
631                     class_infos[idx].hash = h;
632                 }
633                 else
634                 {
635                     DEBUG_PRINTF("not(class_infos && idx < max_class_infos)\n");
636                 }
637                 ++idx;
638             }
639 
640             const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
641             const uint32_t duplicate_count = *duplicate_count_ptr;
642             const objc_classheader_t *duplicateClassOffsets = (const objc_classheader_t *)(&duplicate_count_ptr[1]);
643             DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count);
644             DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets);
645             for (uint32_t i=0; i<duplicate_count; ++i)
646             {
647                 const int32_t clsOffset = duplicateClassOffsets[i].clsOffset;
648                 if (clsOffset & 1)
649                     continue; // duplicate
650                 else if (clsOffset == invalidEntryOffset)
651                     continue; // invalid offset
652 
653                 if (class_infos && idx < max_class_infos)
654                 {
655                     class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
656                     const char *name = class_name_lookup_func (class_infos[idx].isa);
657                     DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
658                     // Hash the class name so we don't have to read it
659                     const char *s = name;
660                     uint32_t h = 5381;
661                     for (unsigned char c = *s; c; c = *++s)
662                     {
663                         // class_getName demangles swift names and the hash must
664                         // be calculated on the mangled name.  hash==0 means lldb
665                         // will fetch the mangled name and compute the hash in
666                         // ParseClassInfoArray.
667                         if (c == '.')
668                         {
669                             h = 0;
670                             break;
671                         }
672                         h = ((h << 5) + h) + c;
673                     }
674                     class_infos[idx].hash = h;
675                 }
676                 ++idx;
677             }
678         }
679         DEBUG_PRINTF ("%u class_infos\n", idx);
680         DEBUG_PRINTF ("done\n");
681     }
682     return idx;
683 }
684 
685 
686 )";
687 
688 static uint64_t
689 ExtractRuntimeGlobalSymbol(Process *process, ConstString name,
690                            const ModuleSP &module_sp, Status &error,
691                            bool read_value = true, uint8_t byte_size = 0,
692                            uint64_t default_value = LLDB_INVALID_ADDRESS,
693                            SymbolType sym_type = lldb::eSymbolTypeData) {
694   if (!process) {
695     error.SetErrorString("no process");
696     return default_value;
697   }
698 
699   if (!module_sp) {
700     error.SetErrorString("no module");
701     return default_value;
702   }
703 
704   if (!byte_size)
705     byte_size = process->GetAddressByteSize();
706   const Symbol *symbol =
707       module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData);
708 
709   if (!symbol || !symbol->ValueIsAddress()) {
710     error.SetErrorString("no symbol");
711     return default_value;
712   }
713 
714   lldb::addr_t symbol_load_addr =
715       symbol->GetAddressRef().GetLoadAddress(&process->GetTarget());
716   if (symbol_load_addr == LLDB_INVALID_ADDRESS) {
717     error.SetErrorString("symbol address invalid");
718     return default_value;
719   }
720 
721   if (read_value)
722     return process->ReadUnsignedIntegerFromMemory(symbol_load_addr, byte_size,
723                                                   default_value, error);
724   return symbol_load_addr;
725 }
726 
727 static void RegisterObjCExceptionRecognizer(Process *process);
728 
729 AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process,
730                                        const ModuleSP &objc_module_sp)
731     : AppleObjCRuntime(process), m_objc_module_sp(objc_module_sp),
732       m_dynamic_class_info_extractor(*this),
733       m_shared_cache_class_info_extractor(*this), m_decl_vendor_up(),
734       m_tagged_pointer_obfuscator(LLDB_INVALID_ADDRESS),
735       m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS),
736       m_relative_selector_base(LLDB_INVALID_ADDRESS), m_hash_signature(),
737       m_has_object_getClass(false), m_has_objc_copyRealizedClassList(false),
738       m_has_objc_getRealizedClassList_trylock(false), m_loaded_objc_opt(false),
739       m_non_pointer_isa_cache_up(),
740       m_tagged_pointer_vendor_up(
741           TaggedPointerVendorV2::CreateInstance(*this, objc_module_sp)),
742       m_encoding_to_type_sp(), m_CFBoolean_values(),
743       m_realized_class_generation_count(0) {
744   static const ConstString g_gdb_object_getClass("gdb_object_getClass");
745   m_has_object_getClass = HasSymbol(g_gdb_object_getClass);
746   static const ConstString g_objc_copyRealizedClassList(
747       "_ZL33objc_copyRealizedClassList_nolockPj");
748   static const ConstString g_objc_getRealizedClassList_trylock(
749       "_objc_getRealizedClassList_trylock");
750   m_has_objc_copyRealizedClassList = HasSymbol(g_objc_copyRealizedClassList);
751   m_has_objc_getRealizedClassList_trylock =
752       HasSymbol(g_objc_getRealizedClassList_trylock);
753   WarnIfNoExpandedSharedCache();
754   RegisterObjCExceptionRecognizer(process);
755 }
756 
757 LanguageRuntime *
758 AppleObjCRuntimeV2::GetPreferredLanguageRuntime(ValueObject &in_value) {
759   if (auto process_sp = in_value.GetProcessSP()) {
760     assert(process_sp.get() == m_process);
761     if (auto descriptor_sp = GetNonKVOClassDescriptor(in_value)) {
762       LanguageType impl_lang = descriptor_sp->GetImplementationLanguage();
763       if (impl_lang != eLanguageTypeUnknown)
764         return process_sp->GetLanguageRuntime(impl_lang);
765     }
766   }
767   return nullptr;
768 }
769 
770 bool AppleObjCRuntimeV2::GetDynamicTypeAndAddress(
771     ValueObject &in_value, lldb::DynamicValueType use_dynamic,
772     TypeAndOrName &class_type_or_name, Address &address,
773     Value::ValueType &value_type) {
774   // We should never get here with a null process...
775   assert(m_process != nullptr);
776 
777   // The Runtime is attached to a particular process, you shouldn't pass in a
778   // value from another process. Note, however, the process might be NULL (e.g.
779   // if the value was made with SBTarget::EvaluateExpression...) in which case
780   // it is sufficient if the target's match:
781 
782   Process *process = in_value.GetProcessSP().get();
783   if (process)
784     assert(process == m_process);
785   else
786     assert(in_value.GetTargetSP().get() == m_process->CalculateTarget().get());
787 
788   class_type_or_name.Clear();
789   value_type = Value::ValueType::Scalar;
790 
791   // Make sure we can have a dynamic value before starting...
792   if (CouldHaveDynamicValue(in_value)) {
793     // First job, pull out the address at 0 offset from the object  That will
794     // be the ISA pointer.
795     ClassDescriptorSP objc_class_sp(GetNonKVOClassDescriptor(in_value));
796     if (objc_class_sp) {
797       const addr_t object_ptr = in_value.GetPointerValue();
798       address.SetRawAddress(object_ptr);
799 
800       ConstString class_name(objc_class_sp->GetClassName());
801       class_type_or_name.SetName(class_name);
802       TypeSP type_sp(objc_class_sp->GetType());
803       if (type_sp)
804         class_type_or_name.SetTypeSP(type_sp);
805       else {
806         type_sp = LookupInCompleteClassCache(class_name);
807         if (type_sp) {
808           objc_class_sp->SetType(type_sp);
809           class_type_or_name.SetTypeSP(type_sp);
810         } else {
811           // try to go for a CompilerType at least
812           if (auto *vendor = GetDeclVendor()) {
813             auto types = vendor->FindTypes(class_name, /*max_matches*/ 1);
814             if (!types.empty())
815               class_type_or_name.SetCompilerType(types.front());
816           }
817         }
818       }
819     }
820   }
821   return !class_type_or_name.IsEmpty();
822 }
823 
824 // Static Functions
825 LanguageRuntime *AppleObjCRuntimeV2::CreateInstance(Process *process,
826                                                     LanguageType language) {
827   // FIXME: This should be a MacOS or iOS process, and we need to look for the
828   // OBJC section to make
829   // sure we aren't using the V1 runtime.
830   if (language == eLanguageTypeObjC) {
831     ModuleSP objc_module_sp;
832 
833     if (AppleObjCRuntime::GetObjCVersion(process, objc_module_sp) ==
834         ObjCRuntimeVersions::eAppleObjC_V2)
835       return new AppleObjCRuntimeV2(process, objc_module_sp);
836     return nullptr;
837   }
838   return nullptr;
839 }
840 
841 static constexpr OptionDefinition g_objc_classtable_dump_options[] = {
842     {LLDB_OPT_SET_ALL,
843      false,
844      "verbose",
845      'v',
846      OptionParser::eNoArgument,
847      nullptr,
848      {},
849      0,
850      eArgTypeNone,
851      "Print ivar and method information in detail"}};
852 
853 class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed {
854 public:
855   class CommandOptions : public Options {
856   public:
857     CommandOptions() : Options(), m_verbose(false, false) {}
858 
859     ~CommandOptions() override = default;
860 
861     Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
862                           ExecutionContext *execution_context) override {
863       Status error;
864       const int short_option = m_getopt_table[option_idx].val;
865       switch (short_option) {
866       case 'v':
867         m_verbose.SetCurrentValue(true);
868         m_verbose.SetOptionWasSet();
869         break;
870 
871       default:
872         error.SetErrorStringWithFormat("unrecognized short option '%c'",
873                                        short_option);
874         break;
875       }
876 
877       return error;
878     }
879 
880     void OptionParsingStarting(ExecutionContext *execution_context) override {
881       m_verbose.Clear();
882     }
883 
884     llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
885       return llvm::ArrayRef(g_objc_classtable_dump_options);
886     }
887 
888     OptionValueBoolean m_verbose;
889   };
890 
891   CommandObjectObjC_ClassTable_Dump(CommandInterpreter &interpreter)
892       : CommandObjectParsed(interpreter, "dump",
893                             "Dump information on Objective-C classes "
894                             "known to the current process.",
895                             "language objc class-table dump",
896                             eCommandRequiresProcess |
897                                 eCommandProcessMustBeLaunched |
898                                 eCommandProcessMustBePaused),
899         m_options() {
900     CommandArgumentEntry arg;
901     CommandArgumentData index_arg;
902 
903     // Define the first (and only) variant of this arg.
904     index_arg.arg_type = eArgTypeRegularExpression;
905     index_arg.arg_repetition = eArgRepeatOptional;
906 
907     // There is only one variant this argument could be; put it into the
908     // argument entry.
909     arg.push_back(index_arg);
910 
911     // Push the data for the first argument into the m_arguments vector.
912     m_arguments.push_back(arg);
913   }
914 
915   ~CommandObjectObjC_ClassTable_Dump() override = default;
916 
917   Options *GetOptions() override { return &m_options; }
918 
919 protected:
920   bool DoExecute(Args &command, CommandReturnObject &result) override {
921     std::unique_ptr<RegularExpression> regex_up;
922     switch (command.GetArgumentCount()) {
923     case 0:
924       break;
925     case 1: {
926       regex_up =
927           std::make_unique<RegularExpression>(command.GetArgumentAtIndex(0));
928       if (!regex_up->IsValid()) {
929         result.AppendError(
930             "invalid argument - please provide a valid regular expression");
931         result.SetStatus(lldb::eReturnStatusFailed);
932         return false;
933       }
934       break;
935     }
936     default: {
937       result.AppendError("please provide 0 or 1 arguments");
938       result.SetStatus(lldb::eReturnStatusFailed);
939       return false;
940     }
941     }
942 
943     Process *process = m_exe_ctx.GetProcessPtr();
944     ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process);
945     if (objc_runtime) {
946       auto iterators_pair = objc_runtime->GetDescriptorIteratorPair();
947       auto iterator = iterators_pair.first;
948       auto &std_out = result.GetOutputStream();
949       for (; iterator != iterators_pair.second; iterator++) {
950         if (iterator->second) {
951           const char *class_name =
952               iterator->second->GetClassName().AsCString("<unknown>");
953           if (regex_up && class_name &&
954               !regex_up->Execute(llvm::StringRef(class_name)))
955             continue;
956           std_out.Printf("isa = 0x%" PRIx64, iterator->first);
957           std_out.Printf(" name = %s", class_name);
958           std_out.Printf(" instance size = %" PRIu64,
959                          iterator->second->GetInstanceSize());
960           std_out.Printf(" num ivars = %" PRIuPTR,
961                          (uintptr_t)iterator->second->GetNumIVars());
962           if (auto superclass = iterator->second->GetSuperclass()) {
963             std_out.Printf(" superclass = %s",
964                            superclass->GetClassName().AsCString("<unknown>"));
965           }
966           std_out.Printf("\n");
967           if (m_options.m_verbose) {
968             for (size_t i = 0; i < iterator->second->GetNumIVars(); i++) {
969               auto ivar = iterator->second->GetIVarAtIndex(i);
970               std_out.Printf(
971                   "  ivar name = %s type = %s size = %" PRIu64
972                   " offset = %" PRId32 "\n",
973                   ivar.m_name.AsCString("<unknown>"),
974                   ivar.m_type.GetDisplayTypeName().AsCString("<unknown>"),
975                   ivar.m_size, ivar.m_offset);
976             }
977 
978             iterator->second->Describe(
979                 nullptr,
980                 [&std_out](const char *name, const char *type) -> bool {
981                   std_out.Printf("  instance method name = %s type = %s\n",
982                                  name, type);
983                   return false;
984                 },
985                 [&std_out](const char *name, const char *type) -> bool {
986                   std_out.Printf("  class method name = %s type = %s\n", name,
987                                  type);
988                   return false;
989                 },
990                 nullptr);
991           }
992         } else {
993           if (regex_up && !regex_up->Execute(llvm::StringRef()))
994             continue;
995           std_out.Printf("isa = 0x%" PRIx64 " has no associated class.\n",
996                          iterator->first);
997         }
998       }
999       result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1000       return true;
1001     }
1002     result.AppendError("current process has no Objective-C runtime loaded");
1003     result.SetStatus(lldb::eReturnStatusFailed);
1004     return false;
1005   }
1006 
1007   CommandOptions m_options;
1008 };
1009 
1010 class CommandObjectMultiwordObjC_TaggedPointer_Info
1011     : public CommandObjectParsed {
1012 public:
1013   CommandObjectMultiwordObjC_TaggedPointer_Info(CommandInterpreter &interpreter)
1014       : CommandObjectParsed(
1015             interpreter, "info", "Dump information on a tagged pointer.",
1016             "language objc tagged-pointer info",
1017             eCommandRequiresProcess | eCommandProcessMustBeLaunched |
1018                 eCommandProcessMustBePaused) {
1019     CommandArgumentEntry arg;
1020     CommandArgumentData index_arg;
1021 
1022     // Define the first (and only) variant of this arg.
1023     index_arg.arg_type = eArgTypeAddress;
1024     index_arg.arg_repetition = eArgRepeatPlus;
1025 
1026     // There is only one variant this argument could be; put it into the
1027     // argument entry.
1028     arg.push_back(index_arg);
1029 
1030     // Push the data for the first argument into the m_arguments vector.
1031     m_arguments.push_back(arg);
1032   }
1033 
1034   ~CommandObjectMultiwordObjC_TaggedPointer_Info() override = default;
1035 
1036 protected:
1037   bool DoExecute(Args &command, CommandReturnObject &result) override {
1038     if (command.GetArgumentCount() == 0) {
1039       result.AppendError("this command requires arguments");
1040       result.SetStatus(lldb::eReturnStatusFailed);
1041       return false;
1042     }
1043 
1044     Process *process = m_exe_ctx.GetProcessPtr();
1045     ExecutionContext exe_ctx(process);
1046 
1047     ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process);
1048     if (!objc_runtime) {
1049       result.AppendError("current process has no Objective-C runtime loaded");
1050       result.SetStatus(lldb::eReturnStatusFailed);
1051       return false;
1052     }
1053 
1054     ObjCLanguageRuntime::TaggedPointerVendor *tagged_ptr_vendor =
1055         objc_runtime->GetTaggedPointerVendor();
1056     if (!tagged_ptr_vendor) {
1057       result.AppendError("current process has no tagged pointer support");
1058       result.SetStatus(lldb::eReturnStatusFailed);
1059       return false;
1060     }
1061 
1062     for (size_t i = 0; i < command.GetArgumentCount(); i++) {
1063       const char *arg_str = command.GetArgumentAtIndex(i);
1064       if (!arg_str)
1065         continue;
1066 
1067       Status error;
1068       lldb::addr_t arg_addr = OptionArgParser::ToAddress(
1069           &exe_ctx, arg_str, LLDB_INVALID_ADDRESS, &error);
1070       if (arg_addr == 0 || arg_addr == LLDB_INVALID_ADDRESS || error.Fail()) {
1071         result.AppendErrorWithFormatv(
1072             "could not convert '{0}' to a valid address\n", arg_str);
1073         result.SetStatus(lldb::eReturnStatusFailed);
1074         return false;
1075       }
1076 
1077       if (!tagged_ptr_vendor->IsPossibleTaggedPointer(arg_addr)) {
1078         result.GetOutputStream().Format("{0:x16} is not tagged\n", arg_addr);
1079         continue;
1080       }
1081 
1082       auto descriptor_sp = tagged_ptr_vendor->GetClassDescriptor(arg_addr);
1083       if (!descriptor_sp) {
1084         result.AppendErrorWithFormatv(
1085             "could not get class descriptor for {0:x16}\n", arg_addr);
1086         result.SetStatus(lldb::eReturnStatusFailed);
1087         return false;
1088       }
1089 
1090       uint64_t info_bits = 0;
1091       uint64_t value_bits = 0;
1092       uint64_t payload = 0;
1093       if (descriptor_sp->GetTaggedPointerInfo(&info_bits, &value_bits,
1094                                               &payload)) {
1095         result.GetOutputStream().Format(
1096             "{0:x} is tagged\n"
1097             "\tpayload = {1:x16}\n"
1098             "\tvalue = {2:x16}\n"
1099             "\tinfo bits = {3:x16}\n"
1100             "\tclass = {4}\n",
1101             arg_addr, payload, value_bits, info_bits,
1102             descriptor_sp->GetClassName().AsCString("<unknown>"));
1103       } else {
1104         result.GetOutputStream().Format("{0:x16} is not tagged\n", arg_addr);
1105       }
1106     }
1107 
1108     result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1109     return true;
1110   }
1111 };
1112 
1113 class CommandObjectMultiwordObjC_ClassTable : public CommandObjectMultiword {
1114 public:
1115   CommandObjectMultiwordObjC_ClassTable(CommandInterpreter &interpreter)
1116       : CommandObjectMultiword(
1117             interpreter, "class-table",
1118             "Commands for operating on the Objective-C class table.",
1119             "class-table <subcommand> [<subcommand-options>]") {
1120     LoadSubCommand(
1121         "dump",
1122         CommandObjectSP(new CommandObjectObjC_ClassTable_Dump(interpreter)));
1123   }
1124 
1125   ~CommandObjectMultiwordObjC_ClassTable() override = default;
1126 };
1127 
1128 class CommandObjectMultiwordObjC_TaggedPointer : public CommandObjectMultiword {
1129 public:
1130   CommandObjectMultiwordObjC_TaggedPointer(CommandInterpreter &interpreter)
1131       : CommandObjectMultiword(
1132             interpreter, "tagged-pointer",
1133             "Commands for operating on Objective-C tagged pointers.",
1134             "class-table <subcommand> [<subcommand-options>]") {
1135     LoadSubCommand(
1136         "info",
1137         CommandObjectSP(
1138             new CommandObjectMultiwordObjC_TaggedPointer_Info(interpreter)));
1139   }
1140 
1141   ~CommandObjectMultiwordObjC_TaggedPointer() override = default;
1142 };
1143 
1144 class CommandObjectMultiwordObjC : public CommandObjectMultiword {
1145 public:
1146   CommandObjectMultiwordObjC(CommandInterpreter &interpreter)
1147       : CommandObjectMultiword(
1148             interpreter, "objc",
1149             "Commands for operating on the Objective-C language runtime.",
1150             "objc <subcommand> [<subcommand-options>]") {
1151     LoadSubCommand("class-table",
1152                    CommandObjectSP(
1153                        new CommandObjectMultiwordObjC_ClassTable(interpreter)));
1154     LoadSubCommand("tagged-pointer",
1155                    CommandObjectSP(new CommandObjectMultiwordObjC_TaggedPointer(
1156                        interpreter)));
1157   }
1158 
1159   ~CommandObjectMultiwordObjC() override = default;
1160 };
1161 
1162 void AppleObjCRuntimeV2::Initialize() {
1163   PluginManager::RegisterPlugin(
1164       GetPluginNameStatic(), "Apple Objective-C Language Runtime - Version 2",
1165       CreateInstance,
1166       [](CommandInterpreter &interpreter) -> lldb::CommandObjectSP {
1167         return CommandObjectSP(new CommandObjectMultiwordObjC(interpreter));
1168       },
1169       GetBreakpointExceptionPrecondition);
1170 }
1171 
1172 void AppleObjCRuntimeV2::Terminate() {
1173   PluginManager::UnregisterPlugin(CreateInstance);
1174 }
1175 
1176 BreakpointResolverSP
1177 AppleObjCRuntimeV2::CreateExceptionResolver(const BreakpointSP &bkpt,
1178                                             bool catch_bp, bool throw_bp) {
1179   BreakpointResolverSP resolver_sp;
1180 
1181   if (throw_bp)
1182     resolver_sp = std::make_shared<BreakpointResolverName>(
1183         bkpt, std::get<1>(GetExceptionThrowLocation()).AsCString(),
1184         eFunctionNameTypeBase, eLanguageTypeUnknown, Breakpoint::Exact, 0,
1185         eLazyBoolNo);
1186   // FIXME: We don't do catch breakpoints for ObjC yet.
1187   // Should there be some way for the runtime to specify what it can do in this
1188   // regard?
1189   return resolver_sp;
1190 }
1191 
1192 llvm::Expected<std::unique_ptr<UtilityFunction>>
1193 AppleObjCRuntimeV2::CreateObjectChecker(std::string name,
1194                                         ExecutionContext &exe_ctx) {
1195   char check_function_code[2048];
1196 
1197   int len = 0;
1198   if (m_has_object_getClass) {
1199     len = ::snprintf(check_function_code, sizeof(check_function_code), R"(
1200                      extern "C" void *gdb_object_getClass(void *);
1201                      extern "C" int printf(const char *format, ...);
1202                      extern "C" void
1203                      %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) {
1204                        if ($__lldb_arg_obj == (void *)0)
1205                          return; // nil is ok
1206                        if (!gdb_object_getClass($__lldb_arg_obj)) {
1207                          *((volatile int *)0) = 'ocgc';
1208                        } else if ($__lldb_arg_selector != (void *)0) {
1209                          signed char $responds = (signed char)
1210                              [(id)$__lldb_arg_obj respondsToSelector:
1211                                  (void *) $__lldb_arg_selector];
1212                          if ($responds == (signed char) 0)
1213                            *((volatile int *)0) = 'ocgc';
1214                        }
1215                      })",
1216                      name.c_str());
1217   } else {
1218     len = ::snprintf(check_function_code, sizeof(check_function_code), R"(
1219                      extern "C" void *gdb_class_getClass(void *);
1220                      extern "C" int printf(const char *format, ...);
1221                      extern "C" void
1222                      %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) {
1223                        if ($__lldb_arg_obj == (void *)0)
1224                          return; // nil is ok
1225                        void **$isa_ptr = (void **)$__lldb_arg_obj;
1226                        if (*$isa_ptr == (void *)0 ||
1227                            !gdb_class_getClass(*$isa_ptr))
1228                          *((volatile int *)0) = 'ocgc';
1229                        else if ($__lldb_arg_selector != (void *)0) {
1230                          signed char $responds = (signed char)
1231                              [(id)$__lldb_arg_obj respondsToSelector:
1232                                  (void *) $__lldb_arg_selector];
1233                          if ($responds == (signed char) 0)
1234                            *((volatile int *)0) = 'ocgc';
1235                        }
1236                      })",
1237                      name.c_str());
1238   }
1239 
1240   assert(len < (int)sizeof(check_function_code));
1241   UNUSED_IF_ASSERT_DISABLED(len);
1242 
1243   return GetTargetRef().CreateUtilityFunction(check_function_code, name,
1244                                               eLanguageTypeC, exe_ctx);
1245 }
1246 
1247 size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type,
1248                                                 const char *ivar_name) {
1249   uint32_t ivar_offset = LLDB_INVALID_IVAR_OFFSET;
1250 
1251   ConstString class_name = parent_ast_type.GetTypeName();
1252   if (!class_name.IsEmpty() && ivar_name && ivar_name[0]) {
1253     // Make the objective C V2 mangled name for the ivar offset from the class
1254     // name and ivar name
1255     std::string buffer("OBJC_IVAR_$_");
1256     buffer.append(class_name.AsCString());
1257     buffer.push_back('.');
1258     buffer.append(ivar_name);
1259     ConstString ivar_const_str(buffer.c_str());
1260 
1261     // Try to get the ivar offset address from the symbol table first using the
1262     // name we created above
1263     SymbolContextList sc_list;
1264     Target &target = m_process->GetTarget();
1265     target.GetImages().FindSymbolsWithNameAndType(ivar_const_str,
1266                                                   eSymbolTypeObjCIVar, sc_list);
1267 
1268     addr_t ivar_offset_address = LLDB_INVALID_ADDRESS;
1269 
1270     Status error;
1271     SymbolContext ivar_offset_symbol;
1272     if (sc_list.GetSize() == 1 &&
1273         sc_list.GetContextAtIndex(0, ivar_offset_symbol)) {
1274       if (ivar_offset_symbol.symbol)
1275         ivar_offset_address =
1276             ivar_offset_symbol.symbol->GetLoadAddress(&target);
1277     }
1278 
1279     // If we didn't get the ivar offset address from the symbol table, fall
1280     // back to getting it from the runtime
1281     if (ivar_offset_address == LLDB_INVALID_ADDRESS)
1282       ivar_offset_address = LookupRuntimeSymbol(ivar_const_str);
1283 
1284     if (ivar_offset_address != LLDB_INVALID_ADDRESS)
1285       ivar_offset = m_process->ReadUnsignedIntegerFromMemory(
1286           ivar_offset_address, 4, LLDB_INVALID_IVAR_OFFSET, error);
1287   }
1288   return ivar_offset;
1289 }
1290 
1291 // tagged pointers are special not-a-real-pointer values that contain both type
1292 // and value information this routine attempts to check with as little
1293 // computational effort as possible whether something could possibly be a
1294 // tagged pointer - false positives are possible but false negatives shouldn't
1295 bool AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr) {
1296   if (!m_tagged_pointer_vendor_up)
1297     return false;
1298   return m_tagged_pointer_vendor_up->IsPossibleTaggedPointer(ptr);
1299 }
1300 
1301 class RemoteNXMapTable {
1302 public:
1303   RemoteNXMapTable() : m_end_iterator(*this, -1) {}
1304 
1305   void Dump() {
1306     printf("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr);
1307     printf("RemoteNXMapTable.m_count = %u\n", m_count);
1308     printf("RemoteNXMapTable.m_num_buckets_minus_one = %u\n",
1309            m_num_buckets_minus_one);
1310     printf("RemoteNXMapTable.m_buckets_ptr = 0x%" PRIX64 "\n", m_buckets_ptr);
1311   }
1312 
1313   bool ParseHeader(Process *process, lldb::addr_t load_addr) {
1314     m_process = process;
1315     m_load_addr = load_addr;
1316     m_map_pair_size = m_process->GetAddressByteSize() * 2;
1317     m_invalid_key =
1318         m_process->GetAddressByteSize() == 8 ? UINT64_MAX : UINT32_MAX;
1319     Status err;
1320 
1321     // This currently holds true for all platforms we support, but we might
1322     // need to change this to use get the actually byte size of "unsigned" from
1323     // the target AST...
1324     const uint32_t unsigned_byte_size = sizeof(uint32_t);
1325     // Skip the prototype as we don't need it (const struct
1326     // +NXMapTablePrototype *prototype)
1327 
1328     bool success = true;
1329     if (load_addr == LLDB_INVALID_ADDRESS)
1330       success = false;
1331     else {
1332       lldb::addr_t cursor = load_addr + m_process->GetAddressByteSize();
1333 
1334       // unsigned count;
1335       m_count = m_process->ReadUnsignedIntegerFromMemory(
1336           cursor, unsigned_byte_size, 0, err);
1337       if (m_count) {
1338         cursor += unsigned_byte_size;
1339 
1340         // unsigned nbBucketsMinusOne;
1341         m_num_buckets_minus_one = m_process->ReadUnsignedIntegerFromMemory(
1342             cursor, unsigned_byte_size, 0, err);
1343         cursor += unsigned_byte_size;
1344 
1345         // void *buckets;
1346         m_buckets_ptr = m_process->ReadPointerFromMemory(cursor, err);
1347 
1348         success = m_count > 0 && m_buckets_ptr != LLDB_INVALID_ADDRESS;
1349       }
1350     }
1351 
1352     if (!success) {
1353       m_count = 0;
1354       m_num_buckets_minus_one = 0;
1355       m_buckets_ptr = LLDB_INVALID_ADDRESS;
1356     }
1357     return success;
1358   }
1359 
1360   // const_iterator mimics NXMapState and its code comes from NXInitMapState
1361   // and NXNextMapState.
1362   typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element;
1363 
1364   friend class const_iterator;
1365   class const_iterator {
1366   public:
1367     const_iterator(RemoteNXMapTable &parent, int index)
1368         : m_parent(parent), m_index(index) {
1369       AdvanceToValidIndex();
1370     }
1371 
1372     const_iterator(const const_iterator &rhs)
1373         : m_parent(rhs.m_parent), m_index(rhs.m_index) {
1374       // AdvanceToValidIndex() has been called by rhs already.
1375     }
1376 
1377     const_iterator &operator=(const const_iterator &rhs) {
1378       // AdvanceToValidIndex() has been called by rhs already.
1379       assert(&m_parent == &rhs.m_parent);
1380       m_index = rhs.m_index;
1381       return *this;
1382     }
1383 
1384     bool operator==(const const_iterator &rhs) const {
1385       if (&m_parent != &rhs.m_parent)
1386         return false;
1387       if (m_index != rhs.m_index)
1388         return false;
1389 
1390       return true;
1391     }
1392 
1393     bool operator!=(const const_iterator &rhs) const {
1394       return !(operator==(rhs));
1395     }
1396 
1397     const_iterator &operator++() {
1398       AdvanceToValidIndex();
1399       return *this;
1400     }
1401 
1402     const element operator*() const {
1403       if (m_index == -1) {
1404         // TODO find a way to make this an error, but not an assert
1405         return element();
1406       }
1407 
1408       lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
1409       size_t map_pair_size = m_parent.m_map_pair_size;
1410       lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
1411 
1412       Status err;
1413 
1414       lldb::addr_t key =
1415           m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
1416       if (!err.Success())
1417         return element();
1418       lldb::addr_t value = m_parent.m_process->ReadPointerFromMemory(
1419           pair_ptr + m_parent.m_process->GetAddressByteSize(), err);
1420       if (!err.Success())
1421         return element();
1422 
1423       std::string key_string;
1424 
1425       m_parent.m_process->ReadCStringFromMemory(key, key_string, err);
1426       if (!err.Success())
1427         return element();
1428 
1429       return element(ConstString(key_string.c_str()),
1430                      (ObjCLanguageRuntime::ObjCISA)value);
1431     }
1432 
1433   private:
1434     void AdvanceToValidIndex() {
1435       if (m_index == -1)
1436         return;
1437 
1438       const lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
1439       const size_t map_pair_size = m_parent.m_map_pair_size;
1440       const lldb::addr_t invalid_key = m_parent.m_invalid_key;
1441       Status err;
1442 
1443       while (m_index--) {
1444         lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
1445         lldb::addr_t key =
1446             m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
1447 
1448         if (!err.Success()) {
1449           m_index = -1;
1450           return;
1451         }
1452 
1453         if (key != invalid_key)
1454           return;
1455       }
1456     }
1457     RemoteNXMapTable &m_parent;
1458     int m_index;
1459   };
1460 
1461   const_iterator begin() {
1462     return const_iterator(*this, m_num_buckets_minus_one + 1);
1463   }
1464 
1465   const_iterator end() { return m_end_iterator; }
1466 
1467   uint32_t GetCount() const { return m_count; }
1468 
1469   uint32_t GetBucketCount() const { return m_num_buckets_minus_one; }
1470 
1471   lldb::addr_t GetBucketDataPointer() const { return m_buckets_ptr; }
1472 
1473   lldb::addr_t GetTableLoadAddress() const { return m_load_addr; }
1474 
1475 private:
1476   // contents of _NXMapTable struct
1477   uint32_t m_count = 0;
1478   uint32_t m_num_buckets_minus_one = 0;
1479   lldb::addr_t m_buckets_ptr = LLDB_INVALID_ADDRESS;
1480   lldb_private::Process *m_process = nullptr;
1481   const_iterator m_end_iterator;
1482   lldb::addr_t m_load_addr = LLDB_INVALID_ADDRESS;
1483   size_t m_map_pair_size = 0;
1484   lldb::addr_t m_invalid_key = 0;
1485 };
1486 
1487 AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() = default;
1488 
1489 void AppleObjCRuntimeV2::HashTableSignature::UpdateSignature(
1490     const RemoteNXMapTable &hash_table) {
1491   m_count = hash_table.GetCount();
1492   m_num_buckets = hash_table.GetBucketCount();
1493   m_buckets_ptr = hash_table.GetBucketDataPointer();
1494 }
1495 
1496 bool AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate(
1497     Process *process, AppleObjCRuntimeV2 *runtime,
1498     RemoteNXMapTable &hash_table) {
1499   if (!hash_table.ParseHeader(process, runtime->GetISAHashTablePointer())) {
1500     return false; // Failed to parse the header, no need to update anything
1501   }
1502 
1503   // Check with out current signature and return true if the count, number of
1504   // buckets or the hash table address changes.
1505   if (m_count == hash_table.GetCount() &&
1506       m_num_buckets == hash_table.GetBucketCount() &&
1507       m_buckets_ptr == hash_table.GetBucketDataPointer()) {
1508     // Hash table hasn't changed
1509     return false;
1510   }
1511   // Hash table data has changed, we need to update
1512   return true;
1513 }
1514 
1515 ObjCLanguageRuntime::ClassDescriptorSP
1516 AppleObjCRuntimeV2::GetClassDescriptorFromISA(ObjCISA isa) {
1517   ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp;
1518   if (auto *non_pointer_isa_cache = GetNonPointerIsaCache())
1519     class_descriptor_sp = non_pointer_isa_cache->GetClassDescriptor(isa);
1520   if (!class_descriptor_sp)
1521     class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa);
1522   return class_descriptor_sp;
1523 }
1524 
1525 ObjCLanguageRuntime::ClassDescriptorSP
1526 AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) {
1527   ClassDescriptorSP objc_class_sp;
1528   if (valobj.IsBaseClass()) {
1529     ValueObject *parent = valobj.GetParent();
1530     // if I am my own parent, bail out of here fast..
1531     if (parent && parent != &valobj) {
1532       ClassDescriptorSP parent_descriptor_sp = GetClassDescriptor(*parent);
1533       if (parent_descriptor_sp)
1534         return parent_descriptor_sp->GetSuperclass();
1535     }
1536     return nullptr;
1537   }
1538   // if we get an invalid VO (which might still happen when playing around with
1539   // pointers returned by the expression parser, don't consider this a valid
1540   // ObjC object)
1541   if (!valobj.GetCompilerType().IsValid())
1542     return objc_class_sp;
1543   addr_t isa_pointer = valobj.GetPointerValue();
1544 
1545   // tagged pointer
1546   if (IsTaggedPointer(isa_pointer))
1547     return m_tagged_pointer_vendor_up->GetClassDescriptor(isa_pointer);
1548   ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1549 
1550   Process *process = exe_ctx.GetProcessPtr();
1551   if (!process)
1552     return objc_class_sp;
1553 
1554   Status error;
1555   ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
1556   if (isa == LLDB_INVALID_ADDRESS)
1557     return objc_class_sp;
1558 
1559   objc_class_sp = GetClassDescriptorFromISA(isa);
1560   if (!objc_class_sp) {
1561     if (ABISP abi_sp = process->GetABI())
1562       isa = abi_sp->FixCodeAddress(isa);
1563     objc_class_sp = GetClassDescriptorFromISA(isa);
1564   }
1565 
1566   if (isa && !objc_class_sp) {
1567     Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
1568     LLDB_LOGF(log,
1569               "0x%" PRIx64 ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was "
1570               "not in class descriptor cache 0x%" PRIx64,
1571               isa_pointer, isa);
1572   }
1573   return objc_class_sp;
1574 }
1575 
1576 lldb::addr_t AppleObjCRuntimeV2::GetTaggedPointerObfuscator() {
1577   if (m_tagged_pointer_obfuscator != LLDB_INVALID_ADDRESS)
1578     return m_tagged_pointer_obfuscator;
1579 
1580   Process *process = GetProcess();
1581   ModuleSP objc_module_sp(GetObjCModule());
1582 
1583   if (!objc_module_sp)
1584     return LLDB_INVALID_ADDRESS;
1585 
1586   static ConstString g_gdb_objc_obfuscator(
1587       "objc_debug_taggedpointer_obfuscator");
1588 
1589   const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
1590       g_gdb_objc_obfuscator, lldb::eSymbolTypeAny);
1591   if (symbol) {
1592     lldb::addr_t g_gdb_obj_obfuscator_ptr =
1593         symbol->GetLoadAddress(&process->GetTarget());
1594 
1595     if (g_gdb_obj_obfuscator_ptr != LLDB_INVALID_ADDRESS) {
1596       Status error;
1597       m_tagged_pointer_obfuscator =
1598           process->ReadPointerFromMemory(g_gdb_obj_obfuscator_ptr, error);
1599     }
1600   }
1601   // If we don't have a correct value at this point, there must be no
1602   // obfuscation.
1603   if (m_tagged_pointer_obfuscator == LLDB_INVALID_ADDRESS)
1604     m_tagged_pointer_obfuscator = 0;
1605 
1606   return m_tagged_pointer_obfuscator;
1607 }
1608 
1609 lldb::addr_t AppleObjCRuntimeV2::GetISAHashTablePointer() {
1610   if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS) {
1611     Process *process = GetProcess();
1612 
1613     ModuleSP objc_module_sp(GetObjCModule());
1614 
1615     if (!objc_module_sp)
1616       return LLDB_INVALID_ADDRESS;
1617 
1618     static ConstString g_gdb_objc_realized_classes("gdb_objc_realized_classes");
1619 
1620     const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
1621         g_gdb_objc_realized_classes, lldb::eSymbolTypeAny);
1622     if (symbol) {
1623       lldb::addr_t gdb_objc_realized_classes_ptr =
1624           symbol->GetLoadAddress(&process->GetTarget());
1625 
1626       if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS) {
1627         Status error;
1628         m_isa_hash_table_ptr = process->ReadPointerFromMemory(
1629             gdb_objc_realized_classes_ptr, error);
1630       }
1631     }
1632   }
1633   return m_isa_hash_table_ptr;
1634 }
1635 
1636 std::unique_ptr<AppleObjCRuntimeV2::SharedCacheImageHeaders>
1637 AppleObjCRuntimeV2::SharedCacheImageHeaders::CreateSharedCacheImageHeaders(
1638     AppleObjCRuntimeV2 &runtime) {
1639   Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
1640   Process *process = runtime.GetProcess();
1641   ModuleSP objc_module_sp(runtime.GetObjCModule());
1642   if (!objc_module_sp || !process)
1643     return nullptr;
1644 
1645   const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
1646       ConstString("objc_debug_headerInfoRWs"), lldb::eSymbolTypeAny);
1647   if (!symbol) {
1648     LLDB_LOG(log, "Symbol 'objc_debug_headerInfoRWs' unavailable. Some "
1649                   "information concerning the shared cache may be unavailable");
1650     return nullptr;
1651   }
1652 
1653   lldb::addr_t objc_debug_headerInfoRWs_addr =
1654       symbol->GetLoadAddress(&process->GetTarget());
1655   if (objc_debug_headerInfoRWs_addr == LLDB_INVALID_ADDRESS) {
1656     LLDB_LOG(log, "Symbol 'objc_debug_headerInfoRWs' was found but we were "
1657                   "unable to get its load address");
1658     return nullptr;
1659   }
1660 
1661   Status error;
1662   lldb::addr_t objc_debug_headerInfoRWs_ptr =
1663       process->ReadPointerFromMemory(objc_debug_headerInfoRWs_addr, error);
1664   if (error.Fail()) {
1665     LLDB_LOG(log,
1666              "Failed to read address of 'objc_debug_headerInfoRWs' at {0:x}",
1667              objc_debug_headerInfoRWs_addr);
1668     return nullptr;
1669   }
1670 
1671   const size_t metadata_size =
1672       sizeof(uint32_t) + sizeof(uint32_t); // count + entsize
1673   DataBufferHeap metadata_buffer(metadata_size, '\0');
1674   process->ReadMemory(objc_debug_headerInfoRWs_ptr, metadata_buffer.GetBytes(),
1675                       metadata_size, error);
1676   if (error.Fail()) {
1677     LLDB_LOG(log,
1678              "Unable to read metadata for 'objc_debug_headerInfoRWs' at {0:x}",
1679              objc_debug_headerInfoRWs_ptr);
1680     return nullptr;
1681   }
1682 
1683   DataExtractor metadata_extractor(metadata_buffer.GetBytes(), metadata_size,
1684                                    process->GetByteOrder(),
1685                                    process->GetAddressByteSize());
1686   lldb::offset_t cursor = 0;
1687   uint32_t count = metadata_extractor.GetU32_unchecked(&cursor);
1688   uint32_t entsize = metadata_extractor.GetU32_unchecked(&cursor);
1689   if (count == 0 || entsize == 0) {
1690     LLDB_LOG(log,
1691              "'objc_debug_headerInfoRWs' had count {0} with entsize {1}. These "
1692              "should both be non-zero.",
1693              count, entsize);
1694     return nullptr;
1695   }
1696 
1697   std::unique_ptr<SharedCacheImageHeaders> shared_cache_image_headers(
1698       new SharedCacheImageHeaders(runtime, objc_debug_headerInfoRWs_ptr, count,
1699                                   entsize));
1700   if (auto Err = shared_cache_image_headers->UpdateIfNeeded()) {
1701     LLDB_LOG_ERROR(log, std::move(Err),
1702                    "Failed to update SharedCacheImageHeaders: {0}");
1703     return nullptr;
1704   }
1705 
1706   return shared_cache_image_headers;
1707 }
1708 
1709 llvm::Error AppleObjCRuntimeV2::SharedCacheImageHeaders::UpdateIfNeeded() {
1710   if (!m_needs_update)
1711     return llvm::Error::success();
1712 
1713   Process *process = m_runtime.GetProcess();
1714   constexpr lldb::addr_t metadata_size =
1715       sizeof(uint32_t) + sizeof(uint32_t); // count + entsize
1716 
1717   Status error;
1718   const lldb::addr_t first_header_addr = m_headerInfoRWs_ptr + metadata_size;
1719   DataBufferHeap header_buffer(m_entsize, '\0');
1720   lldb::offset_t cursor = 0;
1721   for (uint32_t i = 0; i < m_count; i++) {
1722     const lldb::addr_t header_addr = first_header_addr + (i * m_entsize);
1723     process->ReadMemory(header_addr, header_buffer.GetBytes(), m_entsize,
1724                         error);
1725     if (error.Fail())
1726       return llvm::createStringError(llvm::inconvertibleErrorCode(),
1727                                      "Failed to read memory from inferior when "
1728                                      "populating SharedCacheImageHeaders");
1729 
1730     DataExtractor header_extractor(header_buffer.GetBytes(), m_entsize,
1731                                    process->GetByteOrder(),
1732                                    process->GetAddressByteSize());
1733     cursor = 0;
1734     bool is_loaded = false;
1735     if (m_entsize == 4) {
1736       uint32_t header = header_extractor.GetU32_unchecked(&cursor);
1737       if (header & 1)
1738         is_loaded = true;
1739     } else {
1740       uint64_t header = header_extractor.GetU64_unchecked(&cursor);
1741       if (header & 1)
1742         is_loaded = true;
1743     }
1744 
1745     if (is_loaded)
1746       m_loaded_images.set(i);
1747     else
1748       m_loaded_images.reset(i);
1749   }
1750   m_needs_update = false;
1751   m_version++;
1752   return llvm::Error::success();
1753 }
1754 
1755 bool AppleObjCRuntimeV2::SharedCacheImageHeaders::IsImageLoaded(
1756     uint16_t image_index) {
1757   if (image_index >= m_count)
1758     return false;
1759   if (auto Err = UpdateIfNeeded()) {
1760     Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
1761     LLDB_LOG_ERROR(log, std::move(Err),
1762                    "Failed to update SharedCacheImageHeaders: {0}");
1763   }
1764   return m_loaded_images.test(image_index);
1765 }
1766 
1767 uint64_t AppleObjCRuntimeV2::SharedCacheImageHeaders::GetVersion() {
1768   if (auto Err = UpdateIfNeeded()) {
1769     Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
1770     LLDB_LOG_ERROR(log, std::move(Err),
1771                    "Failed to update SharedCacheImageHeaders: {0}");
1772   }
1773   return m_version;
1774 }
1775 
1776 std::unique_ptr<UtilityFunction>
1777 AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoUtilityFunctionImpl(
1778     ExecutionContext &exe_ctx, Helper helper, std::string code,
1779     std::string name) {
1780   Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
1781 
1782   LLDB_LOG(log, "Creating utility function {0}", name);
1783 
1784   TypeSystemClangSP scratch_ts_sp =
1785       ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef());
1786   if (!scratch_ts_sp)
1787     return {};
1788 
1789   auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
1790       std::move(code), std::move(name), eLanguageTypeC, exe_ctx);
1791   if (!utility_fn_or_error) {
1792     LLDB_LOG_ERROR(
1793         log, utility_fn_or_error.takeError(),
1794         "Failed to get utility function for dynamic info extractor: {0}");
1795     return {};
1796   }
1797 
1798   // Make some types for our arguments.
1799   CompilerType clang_uint32_t_type =
1800       scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
1801   CompilerType clang_void_pointer_type =
1802       scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();
1803 
1804   // Make the runner function for our implementation utility function.
1805   ValueList arguments;
1806   Value value;
1807   value.SetValueType(Value::ValueType::Scalar);
1808   value.SetCompilerType(clang_void_pointer_type);
1809   arguments.PushValue(value);
1810   arguments.PushValue(value);
1811   value.SetValueType(Value::ValueType::Scalar);
1812   value.SetCompilerType(clang_uint32_t_type);
1813   arguments.PushValue(value);
1814 
1815   // objc_getRealizedClassList_trylock takes an additional buffer and length.
1816   if (helper == Helper::objc_getRealizedClassList_trylock) {
1817     value.SetCompilerType(clang_void_pointer_type);
1818     arguments.PushValue(value);
1819     value.SetCompilerType(clang_uint32_t_type);
1820     arguments.PushValue(value);
1821   }
1822 
1823   arguments.PushValue(value);
1824 
1825   std::unique_ptr<UtilityFunction> utility_fn = std::move(*utility_fn_or_error);
1826 
1827   Status error;
1828   utility_fn->MakeFunctionCaller(clang_uint32_t_type, arguments,
1829                                  exe_ctx.GetThreadSP(), error);
1830 
1831   if (error.Fail()) {
1832     LLDB_LOG(log,
1833              "Failed to make function caller for implementation lookup: {0}.",
1834              error.AsCString());
1835     return {};
1836   }
1837 
1838   return utility_fn;
1839 }
1840 
1841 UtilityFunction *
1842 AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoUtilityFunction(
1843     ExecutionContext &exe_ctx, Helper helper) {
1844   switch (helper) {
1845   case gdb_objc_realized_classes: {
1846     if (!m_gdb_objc_realized_classes_helper.utility_function)
1847       m_gdb_objc_realized_classes_helper.utility_function =
1848           GetClassInfoUtilityFunctionImpl(exe_ctx, helper,
1849                                           g_get_dynamic_class_info_body,
1850                                           g_get_dynamic_class_info_name);
1851     return m_gdb_objc_realized_classes_helper.utility_function.get();
1852   }
1853   case objc_copyRealizedClassList: {
1854     if (!m_objc_copyRealizedClassList_helper.utility_function)
1855       m_objc_copyRealizedClassList_helper.utility_function =
1856           GetClassInfoUtilityFunctionImpl(exe_ctx, helper,
1857                                           g_get_dynamic_class_info2_body,
1858                                           g_get_dynamic_class_info2_name);
1859     return m_objc_copyRealizedClassList_helper.utility_function.get();
1860   }
1861   case objc_getRealizedClassList_trylock: {
1862     if (!m_objc_getRealizedClassList_trylock_helper.utility_function)
1863       m_objc_getRealizedClassList_trylock_helper.utility_function =
1864           GetClassInfoUtilityFunctionImpl(exe_ctx, helper,
1865                                           g_get_dynamic_class_info3_body,
1866                                           g_get_dynamic_class_info3_name);
1867     return m_objc_getRealizedClassList_trylock_helper.utility_function.get();
1868   }
1869   }
1870   llvm_unreachable("Unexpected helper");
1871 }
1872 
1873 lldb::addr_t &
1874 AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoArgs(Helper helper) {
1875   switch (helper) {
1876   case gdb_objc_realized_classes:
1877     return m_gdb_objc_realized_classes_helper.args;
1878   case objc_copyRealizedClassList:
1879     return m_objc_copyRealizedClassList_helper.args;
1880   case objc_getRealizedClassList_trylock:
1881     return m_objc_getRealizedClassList_trylock_helper.args;
1882   }
1883   llvm_unreachable("Unexpected helper");
1884 }
1885 
1886 AppleObjCRuntimeV2::DynamicClassInfoExtractor::Helper
1887 AppleObjCRuntimeV2::DynamicClassInfoExtractor::ComputeHelper(
1888     ExecutionContext &exe_ctx) const {
1889   if (!m_runtime.m_has_objc_copyRealizedClassList &&
1890       !m_runtime.m_has_objc_getRealizedClassList_trylock)
1891     return DynamicClassInfoExtractor::gdb_objc_realized_classes;
1892 
1893   if (Process *process = m_runtime.GetProcess()) {
1894     if (DynamicLoader *loader = process->GetDynamicLoader()) {
1895       if (loader->IsFullyInitialized()) {
1896         switch (exe_ctx.GetTargetRef().GetDynamicClassInfoHelper()) {
1897         case eDynamicClassInfoHelperAuto:
1898           [[clang::fallthrough]];
1899         case eDynamicClassInfoHelperGetRealizedClassList:
1900           if (m_runtime.m_has_objc_getRealizedClassList_trylock)
1901             return DynamicClassInfoExtractor::objc_getRealizedClassList_trylock;
1902           [[clang::fallthrough]];
1903         case eDynamicClassInfoHelperCopyRealizedClassList:
1904           if (m_runtime.m_has_objc_copyRealizedClassList)
1905             return DynamicClassInfoExtractor::objc_copyRealizedClassList;
1906           [[clang::fallthrough]];
1907         case eDynamicClassInfoHelperRealizedClassesStruct:
1908           return DynamicClassInfoExtractor::gdb_objc_realized_classes;
1909         }
1910       }
1911     }
1912   }
1913 
1914   return DynamicClassInfoExtractor::gdb_objc_realized_classes;
1915 }
1916 
1917 std::unique_ptr<UtilityFunction>
1918 AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::
1919     GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx) {
1920   Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
1921 
1922   LLDB_LOG(log, "Creating utility function {0}",
1923            g_get_shared_cache_class_info_name);
1924 
1925   TypeSystemClangSP scratch_ts_sp =
1926       ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef());
1927   if (!scratch_ts_sp)
1928     return {};
1929 
1930   // If the inferior objc.dylib has the class_getNameRaw function, use that in
1931   // our jitted expression.  Else fall back to the old class_getName.
1932   static ConstString g_class_getName_symbol_name("class_getName");
1933   static ConstString g_class_getNameRaw_symbol_name(
1934       "objc_debug_class_getNameRaw");
1935 
1936   ConstString class_name_getter_function_name =
1937       m_runtime.HasSymbol(g_class_getNameRaw_symbol_name)
1938           ? g_class_getNameRaw_symbol_name
1939           : g_class_getName_symbol_name;
1940 
1941   // Substitute in the correct class_getName / class_getNameRaw function name,
1942   // concatenate the two parts of our expression text.  The format string has
1943   // two %s's, so provide the name twice.
1944   std::string shared_class_expression;
1945   llvm::raw_string_ostream(shared_class_expression)
1946       << llvm::format(g_shared_cache_class_name_funcptr,
1947                       class_name_getter_function_name.AsCString(),
1948                       class_name_getter_function_name.AsCString());
1949 
1950   shared_class_expression += g_get_shared_cache_class_info_body;
1951 
1952   auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
1953       std::move(shared_class_expression), g_get_shared_cache_class_info_name,
1954       eLanguageTypeC, exe_ctx);
1955 
1956   if (!utility_fn_or_error) {
1957     LLDB_LOG_ERROR(
1958         log, utility_fn_or_error.takeError(),
1959         "Failed to get utility function for shared class info extractor: {0}");
1960     return nullptr;
1961   }
1962 
1963   // Make some types for our arguments.
1964   CompilerType clang_uint32_t_type =
1965       scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
1966   CompilerType clang_void_pointer_type =
1967       scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();
1968   CompilerType clang_uint64_t_pointer_type =
1969       scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 64)
1970           .GetPointerType();
1971 
1972   // Next make the function caller for our implementation utility function.
1973   ValueList arguments;
1974   Value value;
1975   value.SetValueType(Value::ValueType::Scalar);
1976   value.SetCompilerType(clang_void_pointer_type);
1977   arguments.PushValue(value);
1978   arguments.PushValue(value);
1979   arguments.PushValue(value);
1980 
1981   value.SetValueType(Value::ValueType::Scalar);
1982   value.SetCompilerType(clang_uint64_t_pointer_type);
1983   arguments.PushValue(value);
1984 
1985   value.SetValueType(Value::ValueType::Scalar);
1986   value.SetCompilerType(clang_uint32_t_type);
1987   arguments.PushValue(value);
1988   arguments.PushValue(value);
1989 
1990   std::unique_ptr<UtilityFunction> utility_fn = std::move(*utility_fn_or_error);
1991 
1992   Status error;
1993   utility_fn->MakeFunctionCaller(clang_uint32_t_type, arguments,
1994                                  exe_ctx.GetThreadSP(), error);
1995 
1996   if (error.Fail()) {
1997     LLDB_LOG(log,
1998              "Failed to make function caller for implementation lookup: {0}.",
1999              error.AsCString());
2000     return {};
2001   }
2002 
2003   return utility_fn;
2004 }
2005 
2006 UtilityFunction *
2007 AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::GetClassInfoUtilityFunction(
2008     ExecutionContext &exe_ctx) {
2009   if (!m_utility_function)
2010     m_utility_function = GetClassInfoUtilityFunctionImpl(exe_ctx);
2011   return m_utility_function.get();
2012 }
2013 
2014 AppleObjCRuntimeV2::DescriptorMapUpdateResult
2015 AppleObjCRuntimeV2::DynamicClassInfoExtractor::UpdateISAToDescriptorMap(
2016     RemoteNXMapTable &hash_table) {
2017   Process *process = m_runtime.GetProcess();
2018   if (process == nullptr)
2019     return DescriptorMapUpdateResult::Fail();
2020 
2021   uint32_t num_class_infos = 0;
2022 
2023   Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
2024 
2025   ExecutionContext exe_ctx;
2026 
2027   ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
2028 
2029   if (!thread_sp)
2030     return DescriptorMapUpdateResult::Fail();
2031 
2032   if (!thread_sp->SafeToCallFunctions())
2033     return DescriptorMapUpdateResult::Retry();
2034 
2035   thread_sp->CalculateExecutionContext(exe_ctx);
2036   TypeSystemClangSP scratch_ts_sp =
2037       ScratchTypeSystemClang::GetForTarget(process->GetTarget());
2038 
2039   if (!scratch_ts_sp)
2040     return DescriptorMapUpdateResult::Fail();
2041 
2042   Address function_address;
2043 
2044   const uint32_t addr_size = process->GetAddressByteSize();
2045 
2046   Status err;
2047 
2048   // Compute which helper we're going to use for this update.
2049   const DynamicClassInfoExtractor::Helper helper = ComputeHelper(exe_ctx);
2050 
2051   // Read the total number of classes from the hash table
2052   const uint32_t num_classes =
2053       helper == DynamicClassInfoExtractor::gdb_objc_realized_classes
2054           ? hash_table.GetCount()
2055           : m_runtime.m_realized_class_generation_count;
2056   if (num_classes == 0) {
2057     LLDB_LOGF(log, "No dynamic classes found.");
2058     return DescriptorMapUpdateResult::Success(0);
2059   }
2060 
2061   UtilityFunction *get_class_info_code =
2062       GetClassInfoUtilityFunction(exe_ctx, helper);
2063   if (!get_class_info_code) {
2064     // The callee will have already logged a useful error message.
2065     return DescriptorMapUpdateResult::Fail();
2066   }
2067 
2068   FunctionCaller *get_class_info_function =
2069       get_class_info_code->GetFunctionCaller();
2070 
2071   if (!get_class_info_function) {
2072     LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
2073     return DescriptorMapUpdateResult::Fail();
2074   }
2075 
2076   ValueList arguments = get_class_info_function->GetArgumentValues();
2077 
2078   DiagnosticManager diagnostics;
2079 
2080   const uint32_t class_info_byte_size = addr_size + 4;
2081   const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
2082   lldb::addr_t class_infos_addr = process->AllocateMemory(
2083       class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);
2084 
2085   if (class_infos_addr == LLDB_INVALID_ADDRESS) {
2086     LLDB_LOGF(log,
2087               "unable to allocate %" PRIu32
2088               " bytes in process for shared cache read",
2089               class_infos_byte_size);
2090     return DescriptorMapUpdateResult::Fail();
2091   }
2092 
2093   auto deallocate_class_infos = llvm::make_scope_exit([&] {
2094     // Deallocate the memory we allocated for the ClassInfo array
2095     if (class_infos_addr != LLDB_INVALID_ADDRESS)
2096       process->DeallocateMemory(class_infos_addr);
2097   });
2098 
2099   lldb::addr_t class_buffer_addr = LLDB_INVALID_ADDRESS;
2100   const uint32_t class_byte_size = addr_size;
2101   const uint32_t class_buffer_len = num_classes;
2102   const uint32_t class_buffer_byte_size = class_buffer_len * class_byte_size;
2103   if (helper == Helper::objc_getRealizedClassList_trylock) {
2104     class_buffer_addr = process->AllocateMemory(
2105         class_buffer_byte_size, ePermissionsReadable | ePermissionsWritable,
2106         err);
2107     if (class_buffer_addr == LLDB_INVALID_ADDRESS) {
2108       LLDB_LOGF(log,
2109                 "unable to allocate %" PRIu32
2110                 " bytes in process for shared cache read",
2111                 class_buffer_byte_size);
2112       return DescriptorMapUpdateResult::Fail();
2113     }
2114   }
2115 
2116   auto deallocate_class_buffer = llvm::make_scope_exit([&] {
2117     // Deallocate the memory we allocated for the Class array
2118     if (class_buffer_addr != LLDB_INVALID_ADDRESS)
2119       process->DeallocateMemory(class_buffer_addr);
2120   });
2121 
2122   std::lock_guard<std::mutex> guard(m_mutex);
2123 
2124   // Fill in our function argument values
2125   uint32_t index = 0;
2126   arguments.GetValueAtIndex(index++)->GetScalar() =
2127       hash_table.GetTableLoadAddress();
2128   arguments.GetValueAtIndex(index++)->GetScalar() = class_infos_addr;
2129   arguments.GetValueAtIndex(index++)->GetScalar() = class_infos_byte_size;
2130 
2131   if (class_buffer_addr != LLDB_INVALID_ADDRESS) {
2132     arguments.GetValueAtIndex(index++)->GetScalar() = class_buffer_addr;
2133     arguments.GetValueAtIndex(index++)->GetScalar() = class_buffer_byte_size;
2134   }
2135 
2136   // Only dump the runtime classes from the expression evaluation if the log is
2137   // verbose:
2138   Log *type_log = GetLog(LLDBLog::Types);
2139   bool dump_log = type_log && type_log->GetVerbose();
2140 
2141   arguments.GetValueAtIndex(index++)->GetScalar() = dump_log ? 1 : 0;
2142 
2143   bool success = false;
2144 
2145   diagnostics.Clear();
2146 
2147   // Write our function arguments into the process so we can run our function
2148   if (get_class_info_function->WriteFunctionArguments(
2149           exe_ctx, GetClassInfoArgs(helper), arguments, diagnostics)) {
2150     EvaluateExpressionOptions options;
2151     options.SetUnwindOnError(true);
2152     options.SetTryAllThreads(false);
2153     options.SetStopOthers(true);
2154     options.SetIgnoreBreakpoints(true);
2155     options.SetTimeout(process->GetUtilityExpressionTimeout());
2156     options.SetIsForUtilityExpr(true);
2157 
2158     CompilerType clang_uint32_t_type =
2159         scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
2160 
2161     Value return_value;
2162     return_value.SetValueType(Value::ValueType::Scalar);
2163     return_value.SetCompilerType(clang_uint32_t_type);
2164     return_value.GetScalar() = 0;
2165 
2166     diagnostics.Clear();
2167 
2168     // Run the function
2169     ExpressionResults results = get_class_info_function->ExecuteFunction(
2170         exe_ctx, &GetClassInfoArgs(helper), options, diagnostics, return_value);
2171 
2172     if (results == eExpressionCompleted) {
2173       // The result is the number of ClassInfo structures that were filled in
2174       num_class_infos = return_value.GetScalar().ULong();
2175       LLDB_LOG(log, "Discovered {0} Objective-C classes", num_class_infos);
2176       if (num_class_infos > 0) {
2177         // Read the ClassInfo structures
2178         DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0);
2179         if (process->ReadMemory(class_infos_addr, buffer.GetBytes(),
2180                                 buffer.GetByteSize(),
2181                                 err) == buffer.GetByteSize()) {
2182           DataExtractor class_infos_data(buffer.GetBytes(),
2183                                          buffer.GetByteSize(),
2184                                          process->GetByteOrder(), addr_size);
2185           m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos);
2186         }
2187       }
2188       success = true;
2189     } else {
2190       if (log) {
2191         LLDB_LOGF(log, "Error evaluating our find class name function.");
2192         diagnostics.Dump(log);
2193       }
2194     }
2195   } else {
2196     if (log) {
2197       LLDB_LOGF(log, "Error writing function arguments.");
2198       diagnostics.Dump(log);
2199     }
2200   }
2201 
2202   return DescriptorMapUpdateResult(success, false, num_class_infos);
2203 }
2204 
2205 uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data,
2206                                                  uint32_t num_class_infos) {
2207   // Parses an array of "num_class_infos" packed ClassInfo structures:
2208   //
2209   //    struct ClassInfo
2210   //    {
2211   //        Class isa;
2212   //        uint32_t hash;
2213   //    } __attribute__((__packed__));
2214 
2215   Log *log = GetLog(LLDBLog::Types);
2216   bool should_log = log && log->GetVerbose();
2217 
2218   uint32_t num_parsed = 0;
2219 
2220   // Iterate through all ClassInfo structures
2221   lldb::offset_t offset = 0;
2222   for (uint32_t i = 0; i < num_class_infos; ++i) {
2223     ObjCISA isa = data.GetAddress(&offset);
2224 
2225     if (isa == 0) {
2226       if (should_log)
2227         LLDB_LOGF(
2228             log, "AppleObjCRuntimeV2 found NULL isa, ignoring this class info");
2229       continue;
2230     }
2231     // Check if we already know about this ISA, if we do, the info will never
2232     // change, so we can just skip it.
2233     if (ISAIsCached(isa)) {
2234       if (should_log)
2235         LLDB_LOGF(log,
2236                   "AppleObjCRuntimeV2 found cached isa=0x%" PRIx64
2237                   ", ignoring this class info",
2238                   isa);
2239       offset += 4;
2240     } else {
2241       // Read the 32 bit hash for the class name
2242       const uint32_t name_hash = data.GetU32(&offset);
2243       ClassDescriptorSP descriptor_sp(
2244           new ClassDescriptorV2(*this, isa, nullptr));
2245 
2246       // The code in g_get_shared_cache_class_info_body sets the value of the
2247       // hash to 0 to signal a demangled symbol. We use class_getName() in that
2248       // code to find the class name, but this returns a demangled name for
2249       // Swift symbols. For those symbols, recompute the hash here by reading
2250       // their name from the runtime.
2251       if (name_hash)
2252         AddClass(isa, descriptor_sp, name_hash);
2253       else
2254         AddClass(isa, descriptor_sp,
2255                  descriptor_sp->GetClassName().AsCString(nullptr));
2256       num_parsed++;
2257       if (should_log)
2258         LLDB_LOGF(log,
2259                   "AppleObjCRuntimeV2 added isa=0x%" PRIx64
2260                   ", hash=0x%8.8x, name=%s",
2261                   isa, name_hash,
2262                   descriptor_sp->GetClassName().AsCString("<unknown>"));
2263     }
2264   }
2265   if (should_log)
2266     LLDB_LOGF(log, "AppleObjCRuntimeV2 parsed %" PRIu32 " class infos",
2267               num_parsed);
2268   return num_parsed;
2269 }
2270 
2271 bool AppleObjCRuntimeV2::HasSymbol(ConstString Name) {
2272   if (!m_objc_module_sp)
2273     return false;
2274   if (const Symbol *symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType(
2275           Name, lldb::eSymbolTypeCode)) {
2276     if (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())
2277       return true;
2278   }
2279   return false;
2280 }
2281 
2282 AppleObjCRuntimeV2::DescriptorMapUpdateResult
2283 AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::UpdateISAToDescriptorMap() {
2284   Process *process = m_runtime.GetProcess();
2285   if (process == nullptr)
2286     return DescriptorMapUpdateResult::Fail();
2287 
2288   Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
2289 
2290   ExecutionContext exe_ctx;
2291 
2292   ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
2293 
2294   if (!thread_sp)
2295     return DescriptorMapUpdateResult::Fail();
2296 
2297   if (!thread_sp->SafeToCallFunctions())
2298     return DescriptorMapUpdateResult::Retry();
2299 
2300   thread_sp->CalculateExecutionContext(exe_ctx);
2301   TypeSystemClangSP scratch_ts_sp =
2302       ScratchTypeSystemClang::GetForTarget(process->GetTarget());
2303 
2304   if (!scratch_ts_sp)
2305     return DescriptorMapUpdateResult::Fail();
2306 
2307   Address function_address;
2308 
2309   const uint32_t addr_size = process->GetAddressByteSize();
2310 
2311   Status err;
2312 
2313   uint32_t num_class_infos = 0;
2314 
2315   const lldb::addr_t objc_opt_ptr = m_runtime.GetSharedCacheReadOnlyAddress();
2316   const lldb::addr_t shared_cache_base_addr =
2317       m_runtime.GetSharedCacheBaseAddress();
2318 
2319   if (objc_opt_ptr == LLDB_INVALID_ADDRESS ||
2320       shared_cache_base_addr == LLDB_INVALID_ADDRESS)
2321     return DescriptorMapUpdateResult::Fail();
2322 
2323   // The number of entries to pre-allocate room for.
2324   // Each entry is (addrsize + 4) bytes
2325   // FIXME: It is not sustainable to continue incrementing this value every time
2326   // the shared cache grows. This is because it requires allocating memory in
2327   // the inferior process and some inferior processes have small memory limits.
2328   const uint32_t max_num_classes = 212992;
2329 
2330   UtilityFunction *get_class_info_code = GetClassInfoUtilityFunction(exe_ctx);
2331   if (!get_class_info_code) {
2332     // The callee will have already logged a useful error message.
2333     return DescriptorMapUpdateResult::Fail();
2334   }
2335 
2336   FunctionCaller *get_shared_cache_class_info_function =
2337       get_class_info_code->GetFunctionCaller();
2338 
2339   if (!get_shared_cache_class_info_function) {
2340     LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
2341     return DescriptorMapUpdateResult::Fail();
2342   }
2343 
2344   ValueList arguments =
2345       get_shared_cache_class_info_function->GetArgumentValues();
2346 
2347   DiagnosticManager diagnostics;
2348 
2349   const uint32_t class_info_byte_size = addr_size + 4;
2350   const uint32_t class_infos_byte_size = max_num_classes * class_info_byte_size;
2351   lldb::addr_t class_infos_addr = process->AllocateMemory(
2352       class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);
2353   const uint32_t relative_selector_offset_addr_size = 64;
2354   lldb::addr_t relative_selector_offset_addr =
2355       process->AllocateMemory(relative_selector_offset_addr_size,
2356                               ePermissionsReadable | ePermissionsWritable, err);
2357 
2358   if (class_infos_addr == LLDB_INVALID_ADDRESS) {
2359     LLDB_LOGF(log,
2360               "unable to allocate %" PRIu32
2361               " bytes in process for shared cache read",
2362               class_infos_byte_size);
2363     return DescriptorMapUpdateResult::Fail();
2364   }
2365 
2366   std::lock_guard<std::mutex> guard(m_mutex);
2367 
2368   // Fill in our function argument values
2369   arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
2370   arguments.GetValueAtIndex(1)->GetScalar() = shared_cache_base_addr;
2371   arguments.GetValueAtIndex(2)->GetScalar() = class_infos_addr;
2372   arguments.GetValueAtIndex(3)->GetScalar() = relative_selector_offset_addr;
2373   arguments.GetValueAtIndex(4)->GetScalar() = class_infos_byte_size;
2374   // Only dump the runtime classes from the expression evaluation if the log is
2375   // verbose:
2376   Log *type_log = GetLog(LLDBLog::Types);
2377   bool dump_log = type_log && type_log->GetVerbose();
2378 
2379   arguments.GetValueAtIndex(5)->GetScalar() = dump_log ? 1 : 0;
2380 
2381   bool success = false;
2382 
2383   diagnostics.Clear();
2384 
2385   // Write our function arguments into the process so we can run our function
2386   if (get_shared_cache_class_info_function->WriteFunctionArguments(
2387           exe_ctx, m_args, arguments, diagnostics)) {
2388     EvaluateExpressionOptions options;
2389     options.SetUnwindOnError(true);
2390     options.SetTryAllThreads(false);
2391     options.SetStopOthers(true);
2392     options.SetIgnoreBreakpoints(true);
2393     options.SetTimeout(process->GetUtilityExpressionTimeout());
2394     options.SetIsForUtilityExpr(true);
2395 
2396     CompilerType clang_uint32_t_type =
2397         scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
2398 
2399     Value return_value;
2400     return_value.SetValueType(Value::ValueType::Scalar);
2401     return_value.SetCompilerType(clang_uint32_t_type);
2402     return_value.GetScalar() = 0;
2403 
2404     diagnostics.Clear();
2405 
2406     // Run the function
2407     ExpressionResults results =
2408         get_shared_cache_class_info_function->ExecuteFunction(
2409             exe_ctx, &m_args, options, diagnostics, return_value);
2410 
2411     if (results == eExpressionCompleted) {
2412       // The result is the number of ClassInfo structures that were filled in
2413       num_class_infos = return_value.GetScalar().ULong();
2414       LLDB_LOG(log, "Discovered {0} Objective-C classes in the shared cache",
2415                num_class_infos);
2416       // Assert if there were more classes than we pre-allocated
2417       // room for.
2418       assert(num_class_infos <= max_num_classes);
2419       if (num_class_infos > 0) {
2420         if (num_class_infos > max_num_classes) {
2421           num_class_infos = max_num_classes;
2422 
2423           success = false;
2424         } else {
2425           success = true;
2426         }
2427 
2428         // Read the relative selector offset.
2429         DataBufferHeap relative_selector_offset_buffer(64, 0);
2430         if (process->ReadMemory(relative_selector_offset_addr,
2431                                 relative_selector_offset_buffer.GetBytes(),
2432                                 relative_selector_offset_buffer.GetByteSize(),
2433                                 err) ==
2434             relative_selector_offset_buffer.GetByteSize()) {
2435           DataExtractor relative_selector_offset_data(
2436               relative_selector_offset_buffer.GetBytes(),
2437               relative_selector_offset_buffer.GetByteSize(),
2438               process->GetByteOrder(), addr_size);
2439           lldb::offset_t offset = 0;
2440           uint64_t relative_selector_offset =
2441               relative_selector_offset_data.GetU64(&offset);
2442           if (relative_selector_offset > 0) {
2443             // The offset is relative to the objc_opt struct.
2444             m_runtime.SetRelativeSelectorBaseAddr(objc_opt_ptr +
2445                                                   relative_selector_offset);
2446           }
2447         }
2448 
2449         // Read the ClassInfo structures
2450         DataBufferHeap class_infos_buffer(
2451             num_class_infos * class_info_byte_size, 0);
2452         if (process->ReadMemory(class_infos_addr, class_infos_buffer.GetBytes(),
2453                                 class_infos_buffer.GetByteSize(),
2454                                 err) == class_infos_buffer.GetByteSize()) {
2455           DataExtractor class_infos_data(class_infos_buffer.GetBytes(),
2456                                          class_infos_buffer.GetByteSize(),
2457                                          process->GetByteOrder(), addr_size);
2458 
2459           m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos);
2460         }
2461       } else {
2462         success = true;
2463       }
2464     } else {
2465       if (log) {
2466         LLDB_LOGF(log, "Error evaluating our find class name function.");
2467         diagnostics.Dump(log);
2468       }
2469     }
2470   } else {
2471     if (log) {
2472       LLDB_LOGF(log, "Error writing function arguments.");
2473       diagnostics.Dump(log);
2474     }
2475   }
2476 
2477   // Deallocate the memory we allocated for the ClassInfo array
2478   process->DeallocateMemory(class_infos_addr);
2479 
2480   return DescriptorMapUpdateResult(success, false, num_class_infos);
2481 }
2482 
2483 lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() {
2484   Process *process = GetProcess();
2485 
2486   if (process) {
2487     ModuleSP objc_module_sp(GetObjCModule());
2488 
2489     if (objc_module_sp) {
2490       ObjectFile *objc_object = objc_module_sp->GetObjectFile();
2491 
2492       if (objc_object) {
2493         SectionList *section_list = objc_module_sp->GetSectionList();
2494 
2495         if (section_list) {
2496           SectionSP text_segment_sp(
2497               section_list->FindSectionByName(ConstString("__TEXT")));
2498 
2499           if (text_segment_sp) {
2500             SectionSP objc_opt_section_sp(
2501                 text_segment_sp->GetChildren().FindSectionByName(
2502                     ConstString("__objc_opt_ro")));
2503 
2504             if (objc_opt_section_sp) {
2505               return objc_opt_section_sp->GetLoadBaseAddress(
2506                   &process->GetTarget());
2507             }
2508           }
2509         }
2510       }
2511     }
2512   }
2513   return LLDB_INVALID_ADDRESS;
2514 }
2515 
2516 lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheBaseAddress() {
2517   StructuredData::ObjectSP info = m_process->GetSharedCacheInfo();
2518   if (!info)
2519     return LLDB_INVALID_ADDRESS;
2520 
2521   StructuredData::Dictionary *info_dict = info->GetAsDictionary();
2522   if (!info_dict)
2523     return LLDB_INVALID_ADDRESS;
2524 
2525   StructuredData::ObjectSP value =
2526       info_dict->GetValueForKey("shared_cache_base_address");
2527   if (!value)
2528     return LLDB_INVALID_ADDRESS;
2529 
2530   return value->GetUnsignedIntegerValue(LLDB_INVALID_ADDRESS);
2531 }
2532 
2533 void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
2534   LLDB_SCOPED_TIMER();
2535 
2536   Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
2537 
2538   // Else we need to check with our process to see when the map was updated.
2539   Process *process = GetProcess();
2540 
2541   if (process) {
2542     RemoteNXMapTable hash_table;
2543 
2544     // Update the process stop ID that indicates the last time we updated the
2545     // map, whether it was successful or not.
2546     m_isa_to_descriptor_stop_id = process->GetStopID();
2547 
2548     // Ask the runtime is the realized class generation count changed. Unlike
2549     // the hash table, this accounts for lazily named classes.
2550     const bool class_count_changed = RealizedClassGenerationCountChanged();
2551 
2552     if (!m_hash_signature.NeedsUpdate(process, this, hash_table) &&
2553         !class_count_changed)
2554       return;
2555 
2556     m_hash_signature.UpdateSignature(hash_table);
2557 
2558     // Grab the dynamically loaded Objective-C classes from memory.
2559     DescriptorMapUpdateResult dynamic_update_result =
2560         m_dynamic_class_info_extractor.UpdateISAToDescriptorMap(hash_table);
2561 
2562     // Now get the objc classes that are baked into the Objective-C runtime in
2563     // the shared cache, but only once per process as this data never changes
2564     if (!m_loaded_objc_opt) {
2565       // it is legitimately possible for the shared cache to be empty - in that
2566       // case, the dynamic hash table will contain all the class information we
2567       // need; the situation we're trying to detect is one where we aren't
2568       // seeing class information from the runtime - in order to detect that
2569       // vs. just the shared cache being empty or sparsely populated, we set an
2570       // arbitrary (very low) threshold for the number of classes that we want
2571       // to see in a "good" scenario - anything below that is suspicious
2572       // (Foundation alone has thousands of classes)
2573       const uint32_t num_classes_to_warn_at = 500;
2574 
2575       DescriptorMapUpdateResult shared_cache_update_result =
2576           m_shared_cache_class_info_extractor.UpdateISAToDescriptorMap();
2577 
2578       LLDB_LOGF(log,
2579                 "attempted to read objc class data - results: "
2580                 "[dynamic_update]: ran: %s, retry: %s, count: %" PRIu32
2581                 " [shared_cache_update]: ran: %s, retry: %s, count: %" PRIu32,
2582                 dynamic_update_result.m_update_ran ? "yes" : "no",
2583                 dynamic_update_result.m_retry_update ? "yes" : "no",
2584                 dynamic_update_result.m_num_found,
2585                 shared_cache_update_result.m_update_ran ? "yes" : "no",
2586                 shared_cache_update_result.m_retry_update ? "yes" : "no",
2587                 shared_cache_update_result.m_num_found);
2588 
2589       // warn if:
2590       // - we could not run either expression
2591       // - we found fewer than num_classes_to_warn_at classes total
2592       if (dynamic_update_result.m_retry_update ||
2593           shared_cache_update_result.m_retry_update)
2594         WarnIfNoClassesCached(SharedCacheWarningReason::eExpressionUnableToRun);
2595       else if ((!shared_cache_update_result.m_update_ran) ||
2596                (!dynamic_update_result.m_update_ran))
2597         WarnIfNoClassesCached(
2598             SharedCacheWarningReason::eExpressionExecutionFailure);
2599       else if (dynamic_update_result.m_num_found +
2600                    shared_cache_update_result.m_num_found <
2601                num_classes_to_warn_at)
2602         WarnIfNoClassesCached(SharedCacheWarningReason::eNotEnoughClassesRead);
2603       else
2604         m_loaded_objc_opt = true;
2605     }
2606   } else {
2607     m_isa_to_descriptor_stop_id = UINT32_MAX;
2608   }
2609 }
2610 
2611 bool AppleObjCRuntimeV2::RealizedClassGenerationCountChanged() {
2612   Process *process = GetProcess();
2613   if (!process)
2614     return false;
2615 
2616   Status error;
2617   uint64_t objc_debug_realized_class_generation_count =
2618       ExtractRuntimeGlobalSymbol(
2619           process, ConstString("objc_debug_realized_class_generation_count"),
2620           GetObjCModule(), error);
2621   if (error.Fail())
2622     return false;
2623 
2624   if (m_realized_class_generation_count ==
2625       objc_debug_realized_class_generation_count)
2626     return false;
2627 
2628   Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
2629   LLDB_LOG(log,
2630            "objc_debug_realized_class_generation_count changed from {0} to {1}",
2631            m_realized_class_generation_count,
2632            objc_debug_realized_class_generation_count);
2633 
2634   m_realized_class_generation_count =
2635       objc_debug_realized_class_generation_count;
2636 
2637   return true;
2638 }
2639 
2640 static bool DoesProcessHaveSharedCache(Process &process) {
2641   PlatformSP platform_sp = process.GetTarget().GetPlatform();
2642   if (!platform_sp)
2643     return true; // this should not happen
2644 
2645   llvm::StringRef platform_plugin_name_sr = platform_sp->GetPluginName();
2646   if (platform_plugin_name_sr.endswith("-simulator"))
2647     return false;
2648 
2649   return true;
2650 }
2651 
2652 void AppleObjCRuntimeV2::WarnIfNoClassesCached(
2653     SharedCacheWarningReason reason) {
2654   if (GetProcess() && !DoesProcessHaveSharedCache(*GetProcess())) {
2655     // Simulators do not have the objc_opt_ro class table so don't actually
2656     // complain to the user
2657     return;
2658   }
2659 
2660   Debugger &debugger(GetProcess()->GetTarget().GetDebugger());
2661   switch (reason) {
2662   case SharedCacheWarningReason::eNotEnoughClassesRead:
2663     Debugger::ReportWarning("could not find Objective-C class data in "
2664                             "the process. This may reduce the quality of type "
2665                             "information available.\n",
2666                             debugger.GetID(), &m_no_classes_cached_warning);
2667     break;
2668   case SharedCacheWarningReason::eExpressionExecutionFailure:
2669     Debugger::ReportWarning(
2670         "could not execute support code to read "
2671         "Objective-C class data in the process. This may "
2672         "reduce the quality of type information available.\n",
2673         debugger.GetID(), &m_no_classes_cached_warning);
2674     break;
2675   case SharedCacheWarningReason::eExpressionUnableToRun:
2676     Debugger::ReportWarning(
2677         "could not execute support code to read Objective-C class data because "
2678         "it's not yet safe to do so, and will be retried later.\n",
2679         debugger.GetID(), nullptr);
2680     break;
2681   }
2682 }
2683 
2684 void AppleObjCRuntimeV2::WarnIfNoExpandedSharedCache() {
2685   if (!m_objc_module_sp)
2686     return;
2687 
2688   ObjectFile *object_file = m_objc_module_sp->GetObjectFile();
2689   if (!object_file)
2690     return;
2691 
2692   if (!object_file->IsInMemory())
2693     return;
2694 
2695   Target &target = GetProcess()->GetTarget();
2696   Debugger &debugger = target.GetDebugger();
2697 
2698   std::string buffer;
2699   llvm::raw_string_ostream os(buffer);
2700 
2701   os << "libobjc.A.dylib is being read from process memory. This "
2702         "indicates that LLDB could not ";
2703   if (PlatformSP platform_sp = target.GetPlatform()) {
2704     if (platform_sp->IsHost()) {
2705       os << "read from the host's in-memory shared cache";
2706     } else {
2707       os << "find the on-disk shared cache for this device";
2708     }
2709   } else {
2710     os << "read from the shared cache";
2711   }
2712   os << ". This will likely reduce debugging performance.\n";
2713 
2714   Debugger::ReportWarning(os.str(), debugger.GetID(),
2715                           &m_no_expanded_cache_warning);
2716 }
2717 
2718 DeclVendor *AppleObjCRuntimeV2::GetDeclVendor() {
2719   if (!m_decl_vendor_up)
2720     m_decl_vendor_up = std::make_unique<AppleObjCDeclVendor>(*this);
2721 
2722   return m_decl_vendor_up.get();
2723 }
2724 
2725 lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(ConstString name) {
2726   lldb::addr_t ret = LLDB_INVALID_ADDRESS;
2727 
2728   const char *name_cstr = name.AsCString();
2729 
2730   if (name_cstr) {
2731     llvm::StringRef name_strref(name_cstr);
2732 
2733     llvm::StringRef ivar_prefix("OBJC_IVAR_$_");
2734     llvm::StringRef class_prefix("OBJC_CLASS_$_");
2735 
2736     if (name_strref.startswith(ivar_prefix)) {
2737       llvm::StringRef ivar_skipped_prefix =
2738           name_strref.substr(ivar_prefix.size());
2739       std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar =
2740           ivar_skipped_prefix.split('.');
2741 
2742       if (class_and_ivar.first.size() && class_and_ivar.second.size()) {
2743         const ConstString class_name_cs(class_and_ivar.first);
2744         ClassDescriptorSP descriptor =
2745             ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs);
2746 
2747         if (descriptor) {
2748           const ConstString ivar_name_cs(class_and_ivar.second);
2749           const char *ivar_name_cstr = ivar_name_cs.AsCString();
2750 
2751           auto ivar_func = [&ret,
2752                             ivar_name_cstr](const char *name, const char *type,
2753                                             lldb::addr_t offset_addr,
2754                                             uint64_t size) -> lldb::addr_t {
2755             if (!strcmp(name, ivar_name_cstr)) {
2756               ret = offset_addr;
2757               return true;
2758             }
2759             return false;
2760           };
2761 
2762           descriptor->Describe(
2763               std::function<void(ObjCISA)>(nullptr),
2764               std::function<bool(const char *, const char *)>(nullptr),
2765               std::function<bool(const char *, const char *)>(nullptr),
2766               ivar_func);
2767         }
2768       }
2769     } else if (name_strref.startswith(class_prefix)) {
2770       llvm::StringRef class_skipped_prefix =
2771           name_strref.substr(class_prefix.size());
2772       const ConstString class_name_cs(class_skipped_prefix);
2773       ClassDescriptorSP descriptor =
2774           GetClassDescriptorFromClassName(class_name_cs);
2775 
2776       if (descriptor)
2777         ret = descriptor->GetISA();
2778     }
2779   }
2780 
2781   return ret;
2782 }
2783 
2784 AppleObjCRuntimeV2::NonPointerISACache *
2785 AppleObjCRuntimeV2::NonPointerISACache::CreateInstance(
2786     AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp) {
2787   Process *process(runtime.GetProcess());
2788 
2789   Status error;
2790 
2791   Log *log = GetLog(LLDBLog::Types);
2792 
2793   auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(
2794       process, ConstString("objc_debug_isa_magic_mask"), objc_module_sp, error);
2795   if (error.Fail())
2796     return nullptr;
2797 
2798   auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(
2799       process, ConstString("objc_debug_isa_magic_value"), objc_module_sp,
2800       error);
2801   if (error.Fail())
2802     return nullptr;
2803 
2804   auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol(
2805       process, ConstString("objc_debug_isa_class_mask"), objc_module_sp, error);
2806   if (error.Fail())
2807     return nullptr;
2808 
2809   if (log)
2810     log->PutCString("AOCRT::NPI: Found all the non-indexed ISA masks");
2811 
2812   bool foundError = false;
2813   auto objc_debug_indexed_isa_magic_mask = ExtractRuntimeGlobalSymbol(
2814       process, ConstString("objc_debug_indexed_isa_magic_mask"), objc_module_sp,
2815       error);
2816   foundError |= error.Fail();
2817 
2818   auto objc_debug_indexed_isa_magic_value = ExtractRuntimeGlobalSymbol(
2819       process, ConstString("objc_debug_indexed_isa_magic_value"),
2820       objc_module_sp, error);
2821   foundError |= error.Fail();
2822 
2823   auto objc_debug_indexed_isa_index_mask = ExtractRuntimeGlobalSymbol(
2824       process, ConstString("objc_debug_indexed_isa_index_mask"), objc_module_sp,
2825       error);
2826   foundError |= error.Fail();
2827 
2828   auto objc_debug_indexed_isa_index_shift = ExtractRuntimeGlobalSymbol(
2829       process, ConstString("objc_debug_indexed_isa_index_shift"),
2830       objc_module_sp, error);
2831   foundError |= error.Fail();
2832 
2833   auto objc_indexed_classes =
2834       ExtractRuntimeGlobalSymbol(process, ConstString("objc_indexed_classes"),
2835                                  objc_module_sp, error, false);
2836   foundError |= error.Fail();
2837 
2838   if (log)
2839     log->PutCString("AOCRT::NPI: Found all the indexed ISA masks");
2840 
2841   // we might want to have some rules to outlaw these other values (e.g if the
2842   // mask is zero but the value is non-zero, ...)
2843 
2844   return new NonPointerISACache(
2845       runtime, objc_module_sp, objc_debug_isa_class_mask,
2846       objc_debug_isa_magic_mask, objc_debug_isa_magic_value,
2847       objc_debug_indexed_isa_magic_mask, objc_debug_indexed_isa_magic_value,
2848       objc_debug_indexed_isa_index_mask, objc_debug_indexed_isa_index_shift,
2849       foundError ? 0 : objc_indexed_classes);
2850 }
2851 
2852 AppleObjCRuntimeV2::TaggedPointerVendorV2 *
2853 AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance(
2854     AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp) {
2855   Process *process(runtime.GetProcess());
2856 
2857   Status error;
2858 
2859   auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol(
2860       process, ConstString("objc_debug_taggedpointer_mask"), objc_module_sp,
2861       error);
2862   if (error.Fail())
2863     return new TaggedPointerVendorLegacy(runtime);
2864 
2865   auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol(
2866       process, ConstString("objc_debug_taggedpointer_slot_shift"),
2867       objc_module_sp, error, true, 4);
2868   if (error.Fail())
2869     return new TaggedPointerVendorLegacy(runtime);
2870 
2871   auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol(
2872       process, ConstString("objc_debug_taggedpointer_slot_mask"),
2873       objc_module_sp, error, true, 4);
2874   if (error.Fail())
2875     return new TaggedPointerVendorLegacy(runtime);
2876 
2877   auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol(
2878       process, ConstString("objc_debug_taggedpointer_payload_lshift"),
2879       objc_module_sp, error, true, 4);
2880   if (error.Fail())
2881     return new TaggedPointerVendorLegacy(runtime);
2882 
2883   auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol(
2884       process, ConstString("objc_debug_taggedpointer_payload_rshift"),
2885       objc_module_sp, error, true, 4);
2886   if (error.Fail())
2887     return new TaggedPointerVendorLegacy(runtime);
2888 
2889   auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol(
2890       process, ConstString("objc_debug_taggedpointer_classes"), objc_module_sp,
2891       error, false);
2892   if (error.Fail())
2893     return new TaggedPointerVendorLegacy(runtime);
2894 
2895   // try to detect the "extended tagged pointer" variables - if any are
2896   // missing, use the non-extended vendor
2897   do {
2898     auto objc_debug_taggedpointer_ext_mask = ExtractRuntimeGlobalSymbol(
2899         process, ConstString("objc_debug_taggedpointer_ext_mask"),
2900         objc_module_sp, error);
2901     if (error.Fail())
2902       break;
2903 
2904     auto objc_debug_taggedpointer_ext_slot_shift = ExtractRuntimeGlobalSymbol(
2905         process, ConstString("objc_debug_taggedpointer_ext_slot_shift"),
2906         objc_module_sp, error, true, 4);
2907     if (error.Fail())
2908       break;
2909 
2910     auto objc_debug_taggedpointer_ext_slot_mask = ExtractRuntimeGlobalSymbol(
2911         process, ConstString("objc_debug_taggedpointer_ext_slot_mask"),
2912         objc_module_sp, error, true, 4);
2913     if (error.Fail())
2914       break;
2915 
2916     auto objc_debug_taggedpointer_ext_classes = ExtractRuntimeGlobalSymbol(
2917         process, ConstString("objc_debug_taggedpointer_ext_classes"),
2918         objc_module_sp, error, false);
2919     if (error.Fail())
2920       break;
2921 
2922     auto objc_debug_taggedpointer_ext_payload_lshift =
2923         ExtractRuntimeGlobalSymbol(
2924             process, ConstString("objc_debug_taggedpointer_ext_payload_lshift"),
2925             objc_module_sp, error, true, 4);
2926     if (error.Fail())
2927       break;
2928 
2929     auto objc_debug_taggedpointer_ext_payload_rshift =
2930         ExtractRuntimeGlobalSymbol(
2931             process, ConstString("objc_debug_taggedpointer_ext_payload_rshift"),
2932             objc_module_sp, error, true, 4);
2933     if (error.Fail())
2934       break;
2935 
2936     return new TaggedPointerVendorExtended(
2937         runtime, objc_debug_taggedpointer_mask,
2938         objc_debug_taggedpointer_ext_mask, objc_debug_taggedpointer_slot_shift,
2939         objc_debug_taggedpointer_ext_slot_shift,
2940         objc_debug_taggedpointer_slot_mask,
2941         objc_debug_taggedpointer_ext_slot_mask,
2942         objc_debug_taggedpointer_payload_lshift,
2943         objc_debug_taggedpointer_payload_rshift,
2944         objc_debug_taggedpointer_ext_payload_lshift,
2945         objc_debug_taggedpointer_ext_payload_rshift,
2946         objc_debug_taggedpointer_classes, objc_debug_taggedpointer_ext_classes);
2947   } while (false);
2948 
2949   // we might want to have some rules to outlaw these values (e.g if the
2950   // table's address is zero)
2951 
2952   return new TaggedPointerVendorRuntimeAssisted(
2953       runtime, objc_debug_taggedpointer_mask,
2954       objc_debug_taggedpointer_slot_shift, objc_debug_taggedpointer_slot_mask,
2955       objc_debug_taggedpointer_payload_lshift,
2956       objc_debug_taggedpointer_payload_rshift,
2957       objc_debug_taggedpointer_classes);
2958 }
2959 
2960 bool AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer(
2961     lldb::addr_t ptr) {
2962   return (ptr & 1);
2963 }
2964 
2965 ObjCLanguageRuntime::ClassDescriptorSP
2966 AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor(
2967     lldb::addr_t ptr) {
2968   if (!IsPossibleTaggedPointer(ptr))
2969     return ObjCLanguageRuntime::ClassDescriptorSP();
2970 
2971   uint32_t foundation_version = m_runtime.GetFoundationVersion();
2972 
2973   if (foundation_version == LLDB_INVALID_MODULE_VERSION)
2974     return ObjCLanguageRuntime::ClassDescriptorSP();
2975 
2976   uint64_t class_bits = (ptr & 0xE) >> 1;
2977   ConstString name;
2978 
2979   static ConstString g_NSAtom("NSAtom");
2980   static ConstString g_NSNumber("NSNumber");
2981   static ConstString g_NSDateTS("NSDateTS");
2982   static ConstString g_NSManagedObject("NSManagedObject");
2983   static ConstString g_NSDate("NSDate");
2984 
2985   if (foundation_version >= 900) {
2986     switch (class_bits) {
2987     case 0:
2988       name = g_NSAtom;
2989       break;
2990     case 3:
2991       name = g_NSNumber;
2992       break;
2993     case 4:
2994       name = g_NSDateTS;
2995       break;
2996     case 5:
2997       name = g_NSManagedObject;
2998       break;
2999     case 6:
3000       name = g_NSDate;
3001       break;
3002     default:
3003       return ObjCLanguageRuntime::ClassDescriptorSP();
3004     }
3005   } else {
3006     switch (class_bits) {
3007     case 1:
3008       name = g_NSNumber;
3009       break;
3010     case 5:
3011       name = g_NSManagedObject;
3012       break;
3013     case 6:
3014       name = g_NSDate;
3015       break;
3016     case 7:
3017       name = g_NSDateTS;
3018       break;
3019     default:
3020       return ObjCLanguageRuntime::ClassDescriptorSP();
3021     }
3022   }
3023 
3024   lldb::addr_t unobfuscated = ptr ^ m_runtime.GetTaggedPointerObfuscator();
3025   return ClassDescriptorSP(new ClassDescriptorV2Tagged(name, unobfuscated));
3026 }
3027 
3028 AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::
3029     TaggedPointerVendorRuntimeAssisted(
3030         AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,
3031         uint32_t objc_debug_taggedpointer_slot_shift,
3032         uint32_t objc_debug_taggedpointer_slot_mask,
3033         uint32_t objc_debug_taggedpointer_payload_lshift,
3034         uint32_t objc_debug_taggedpointer_payload_rshift,
3035         lldb::addr_t objc_debug_taggedpointer_classes)
3036     : TaggedPointerVendorV2(runtime), m_cache(),
3037       m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask),
3038       m_objc_debug_taggedpointer_slot_shift(
3039           objc_debug_taggedpointer_slot_shift),
3040       m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask),
3041       m_objc_debug_taggedpointer_payload_lshift(
3042           objc_debug_taggedpointer_payload_lshift),
3043       m_objc_debug_taggedpointer_payload_rshift(
3044           objc_debug_taggedpointer_payload_rshift),
3045       m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes) {}
3046 
3047 bool AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::
3048     IsPossibleTaggedPointer(lldb::addr_t ptr) {
3049   return (ptr & m_objc_debug_taggedpointer_mask) != 0;
3050 }
3051 
3052 ObjCLanguageRuntime::ClassDescriptorSP
3053 AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(
3054     lldb::addr_t ptr) {
3055   ClassDescriptorSP actual_class_descriptor_sp;
3056   uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
3057 
3058   if (!IsPossibleTaggedPointer(unobfuscated))
3059     return ObjCLanguageRuntime::ClassDescriptorSP();
3060 
3061   uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) &
3062                    m_objc_debug_taggedpointer_slot_mask;
3063 
3064   CacheIterator iterator = m_cache.find(slot), end = m_cache.end();
3065   if (iterator != end) {
3066     actual_class_descriptor_sp = iterator->second;
3067   } else {
3068     Process *process(m_runtime.GetProcess());
3069     uintptr_t slot_ptr = slot * process->GetAddressByteSize() +
3070                          m_objc_debug_taggedpointer_classes;
3071     Status error;
3072     uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
3073     if (error.Fail() || slot_data == 0 ||
3074         slot_data == uintptr_t(LLDB_INVALID_ADDRESS))
3075       return nullptr;
3076     actual_class_descriptor_sp =
3077         m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data);
3078     if (!actual_class_descriptor_sp) {
3079       if (ABISP abi_sp = process->GetABI()) {
3080         ObjCISA fixed_isa = abi_sp->FixCodeAddress((ObjCISA)slot_data);
3081         actual_class_descriptor_sp =
3082             m_runtime.GetClassDescriptorFromISA(fixed_isa);
3083       }
3084     }
3085     if (!actual_class_descriptor_sp)
3086       return ObjCLanguageRuntime::ClassDescriptorSP();
3087     m_cache[slot] = actual_class_descriptor_sp;
3088   }
3089 
3090   uint64_t data_payload =
3091       ((unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >>
3092        m_objc_debug_taggedpointer_payload_rshift);
3093   int64_t data_payload_signed =
3094       ((int64_t)(unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >>
3095        m_objc_debug_taggedpointer_payload_rshift);
3096   return ClassDescriptorSP(new ClassDescriptorV2Tagged(
3097       actual_class_descriptor_sp, data_payload, data_payload_signed));
3098 }
3099 
3100 AppleObjCRuntimeV2::TaggedPointerVendorExtended::TaggedPointerVendorExtended(
3101     AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,
3102     uint64_t objc_debug_taggedpointer_ext_mask,
3103     uint32_t objc_debug_taggedpointer_slot_shift,
3104     uint32_t objc_debug_taggedpointer_ext_slot_shift,
3105     uint32_t objc_debug_taggedpointer_slot_mask,
3106     uint32_t objc_debug_taggedpointer_ext_slot_mask,
3107     uint32_t objc_debug_taggedpointer_payload_lshift,
3108     uint32_t objc_debug_taggedpointer_payload_rshift,
3109     uint32_t objc_debug_taggedpointer_ext_payload_lshift,
3110     uint32_t objc_debug_taggedpointer_ext_payload_rshift,
3111     lldb::addr_t objc_debug_taggedpointer_classes,
3112     lldb::addr_t objc_debug_taggedpointer_ext_classes)
3113     : TaggedPointerVendorRuntimeAssisted(
3114           runtime, objc_debug_taggedpointer_mask,
3115           objc_debug_taggedpointer_slot_shift,
3116           objc_debug_taggedpointer_slot_mask,
3117           objc_debug_taggedpointer_payload_lshift,
3118           objc_debug_taggedpointer_payload_rshift,
3119           objc_debug_taggedpointer_classes),
3120       m_ext_cache(),
3121       m_objc_debug_taggedpointer_ext_mask(objc_debug_taggedpointer_ext_mask),
3122       m_objc_debug_taggedpointer_ext_slot_shift(
3123           objc_debug_taggedpointer_ext_slot_shift),
3124       m_objc_debug_taggedpointer_ext_slot_mask(
3125           objc_debug_taggedpointer_ext_slot_mask),
3126       m_objc_debug_taggedpointer_ext_payload_lshift(
3127           objc_debug_taggedpointer_ext_payload_lshift),
3128       m_objc_debug_taggedpointer_ext_payload_rshift(
3129           objc_debug_taggedpointer_ext_payload_rshift),
3130       m_objc_debug_taggedpointer_ext_classes(
3131           objc_debug_taggedpointer_ext_classes) {}
3132 
3133 bool AppleObjCRuntimeV2::TaggedPointerVendorExtended::
3134     IsPossibleExtendedTaggedPointer(lldb::addr_t ptr) {
3135   if (!IsPossibleTaggedPointer(ptr))
3136     return false;
3137 
3138   if (m_objc_debug_taggedpointer_ext_mask == 0)
3139     return false;
3140 
3141   return ((ptr & m_objc_debug_taggedpointer_ext_mask) ==
3142           m_objc_debug_taggedpointer_ext_mask);
3143 }
3144 
3145 ObjCLanguageRuntime::ClassDescriptorSP
3146 AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor(
3147     lldb::addr_t ptr) {
3148   ClassDescriptorSP actual_class_descriptor_sp;
3149   uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
3150 
3151   if (!IsPossibleTaggedPointer(unobfuscated))
3152     return ObjCLanguageRuntime::ClassDescriptorSP();
3153 
3154   if (!IsPossibleExtendedTaggedPointer(unobfuscated))
3155     return this->TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(ptr);
3156 
3157   uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_ext_slot_shift) &
3158                    m_objc_debug_taggedpointer_ext_slot_mask;
3159 
3160   CacheIterator iterator = m_ext_cache.find(slot), end = m_ext_cache.end();
3161   if (iterator != end) {
3162     actual_class_descriptor_sp = iterator->second;
3163   } else {
3164     Process *process(m_runtime.GetProcess());
3165     uintptr_t slot_ptr = slot * process->GetAddressByteSize() +
3166                          m_objc_debug_taggedpointer_ext_classes;
3167     Status error;
3168     uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
3169     if (error.Fail() || slot_data == 0 ||
3170         slot_data == uintptr_t(LLDB_INVALID_ADDRESS))
3171       return nullptr;
3172     actual_class_descriptor_sp =
3173         m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data);
3174     if (!actual_class_descriptor_sp)
3175       return ObjCLanguageRuntime::ClassDescriptorSP();
3176     m_ext_cache[slot] = actual_class_descriptor_sp;
3177   }
3178 
3179   uint64_t data_payload = (((uint64_t)unobfuscated
3180                             << m_objc_debug_taggedpointer_ext_payload_lshift) >>
3181                            m_objc_debug_taggedpointer_ext_payload_rshift);
3182   int64_t data_payload_signed =
3183       ((int64_t)((int64_t)unobfuscated
3184                  << m_objc_debug_taggedpointer_ext_payload_lshift) >>
3185        m_objc_debug_taggedpointer_ext_payload_rshift);
3186 
3187   return ClassDescriptorSP(new ClassDescriptorV2Tagged(
3188       actual_class_descriptor_sp, data_payload, data_payload_signed));
3189 }
3190 
3191 AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache(
3192     AppleObjCRuntimeV2 &runtime, const ModuleSP &objc_module_sp,
3193     uint64_t objc_debug_isa_class_mask, uint64_t objc_debug_isa_magic_mask,
3194     uint64_t objc_debug_isa_magic_value,
3195     uint64_t objc_debug_indexed_isa_magic_mask,
3196     uint64_t objc_debug_indexed_isa_magic_value,
3197     uint64_t objc_debug_indexed_isa_index_mask,
3198     uint64_t objc_debug_indexed_isa_index_shift,
3199     lldb::addr_t objc_indexed_classes)
3200     : m_runtime(runtime), m_cache(), m_objc_module_wp(objc_module_sp),
3201       m_objc_debug_isa_class_mask(objc_debug_isa_class_mask),
3202       m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask),
3203       m_objc_debug_isa_magic_value(objc_debug_isa_magic_value),
3204       m_objc_debug_indexed_isa_magic_mask(objc_debug_indexed_isa_magic_mask),
3205       m_objc_debug_indexed_isa_magic_value(objc_debug_indexed_isa_magic_value),
3206       m_objc_debug_indexed_isa_index_mask(objc_debug_indexed_isa_index_mask),
3207       m_objc_debug_indexed_isa_index_shift(objc_debug_indexed_isa_index_shift),
3208       m_objc_indexed_classes(objc_indexed_classes), m_indexed_isa_cache() {}
3209 
3210 ObjCLanguageRuntime::ClassDescriptorSP
3211 AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor(ObjCISA isa) {
3212   ObjCISA real_isa = 0;
3213   if (!EvaluateNonPointerISA(isa, real_isa))
3214     return ObjCLanguageRuntime::ClassDescriptorSP();
3215   auto cache_iter = m_cache.find(real_isa);
3216   if (cache_iter != m_cache.end())
3217     return cache_iter->second;
3218   auto descriptor_sp =
3219       m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa);
3220   if (descriptor_sp) // cache only positive matches since the table might grow
3221     m_cache[real_isa] = descriptor_sp;
3222   return descriptor_sp;
3223 }
3224 
3225 bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
3226     ObjCISA isa, ObjCISA &ret_isa) {
3227   Log *log = GetLog(LLDBLog::Types);
3228 
3229   LLDB_LOGF(log, "AOCRT::NPI Evaluate(isa = 0x%" PRIx64 ")", (uint64_t)isa);
3230 
3231   if ((isa & ~m_objc_debug_isa_class_mask) == 0)
3232     return false;
3233 
3234   // If all of the indexed ISA variables are set, then its possible that this
3235   // ISA is indexed, and we should first try to get its value using the index.
3236   // Note, we check these variables first as the ObjC runtime will set at least
3237   // one of their values to 0 if they aren't needed.
3238   if (m_objc_debug_indexed_isa_magic_mask &&
3239       m_objc_debug_indexed_isa_magic_value &&
3240       m_objc_debug_indexed_isa_index_mask &&
3241       m_objc_debug_indexed_isa_index_shift && m_objc_indexed_classes) {
3242     if ((isa & ~m_objc_debug_indexed_isa_index_mask) == 0)
3243       return false;
3244 
3245     if ((isa & m_objc_debug_indexed_isa_magic_mask) ==
3246         m_objc_debug_indexed_isa_magic_value) {
3247       // Magic bits are correct, so try extract the index.
3248       uintptr_t index = (isa & m_objc_debug_indexed_isa_index_mask) >>
3249                         m_objc_debug_indexed_isa_index_shift;
3250       // If the index is out of bounds of the length of the array then check if
3251       // the array has been updated.  If that is the case then we should try
3252       // read the count again, and update the cache if the count has been
3253       // updated.
3254       if (index > m_indexed_isa_cache.size()) {
3255         LLDB_LOGF(log,
3256                   "AOCRT::NPI (index = %" PRIu64
3257                   ") exceeds cache (size = %" PRIu64 ")",
3258                   (uint64_t)index, (uint64_t)m_indexed_isa_cache.size());
3259 
3260         Process *process(m_runtime.GetProcess());
3261 
3262         ModuleSP objc_module_sp(m_objc_module_wp.lock());
3263         if (!objc_module_sp)
3264           return false;
3265 
3266         Status error;
3267         auto objc_indexed_classes_count = ExtractRuntimeGlobalSymbol(
3268             process, ConstString("objc_indexed_classes_count"), objc_module_sp,
3269             error);
3270         if (error.Fail())
3271           return false;
3272 
3273         LLDB_LOGF(log, "AOCRT::NPI (new class count = %" PRIu64 ")",
3274                   (uint64_t)objc_indexed_classes_count);
3275 
3276         if (objc_indexed_classes_count > m_indexed_isa_cache.size()) {
3277           // Read the class entries we don't have.  We should just read all of
3278           // them instead of just the one we need as then we can cache those we
3279           // may need later.
3280           auto num_new_classes =
3281               objc_indexed_classes_count - m_indexed_isa_cache.size();
3282           const uint32_t addr_size = process->GetAddressByteSize();
3283           DataBufferHeap buffer(num_new_classes * addr_size, 0);
3284 
3285           lldb::addr_t last_read_class =
3286               m_objc_indexed_classes + (m_indexed_isa_cache.size() * addr_size);
3287           size_t bytes_read = process->ReadMemory(
3288               last_read_class, buffer.GetBytes(), buffer.GetByteSize(), error);
3289           if (error.Fail() || bytes_read != buffer.GetByteSize())
3290             return false;
3291 
3292           LLDB_LOGF(log, "AOCRT::NPI (read new classes count = %" PRIu64 ")",
3293                     (uint64_t)num_new_classes);
3294 
3295           // Append the new entries to the existing cache.
3296           DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(),
3297                              process->GetByteOrder(),
3298                              process->GetAddressByteSize());
3299 
3300           lldb::offset_t offset = 0;
3301           for (unsigned i = 0; i != num_new_classes; ++i)
3302             m_indexed_isa_cache.push_back(data.GetAddress(&offset));
3303         }
3304       }
3305 
3306       // If the index is still out of range then this isn't a pointer.
3307       if (index > m_indexed_isa_cache.size())
3308         return false;
3309 
3310       LLDB_LOGF(log, "AOCRT::NPI Evaluate(ret_isa = 0x%" PRIx64 ")",
3311                 (uint64_t)m_indexed_isa_cache[index]);
3312 
3313       ret_isa = m_indexed_isa_cache[index];
3314       return (ret_isa != 0); // this is a pointer so 0 is not a valid value
3315     }
3316 
3317     return false;
3318   }
3319 
3320   // Definitely not an indexed ISA, so try to use a mask to extract the pointer
3321   // from the ISA.
3322   if ((isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value) {
3323     ret_isa = isa & m_objc_debug_isa_class_mask;
3324     return (ret_isa != 0); // this is a pointer so 0 is not a valid value
3325   }
3326   return false;
3327 }
3328 
3329 ObjCLanguageRuntime::EncodingToTypeSP AppleObjCRuntimeV2::GetEncodingToType() {
3330   if (!m_encoding_to_type_sp)
3331     m_encoding_to_type_sp =
3332         std::make_shared<AppleObjCTypeEncodingParser>(*this);
3333   return m_encoding_to_type_sp;
3334 }
3335 
3336 lldb_private::AppleObjCRuntime::ObjCISA
3337 AppleObjCRuntimeV2::GetPointerISA(ObjCISA isa) {
3338   ObjCISA ret = isa;
3339 
3340   if (auto *non_pointer_isa_cache = GetNonPointerIsaCache())
3341     non_pointer_isa_cache->EvaluateNonPointerISA(isa, ret);
3342 
3343   return ret;
3344 }
3345 
3346 bool AppleObjCRuntimeV2::GetCFBooleanValuesIfNeeded() {
3347   if (m_CFBoolean_values)
3348     return true;
3349 
3350   static ConstString g_dunder_kCFBooleanFalse("__kCFBooleanFalse");
3351   static ConstString g_dunder_kCFBooleanTrue("__kCFBooleanTrue");
3352   static ConstString g_kCFBooleanFalse("kCFBooleanFalse");
3353   static ConstString g_kCFBooleanTrue("kCFBooleanTrue");
3354 
3355   std::function<lldb::addr_t(ConstString, ConstString)> get_symbol =
3356       [this](ConstString sym, ConstString real_sym) -> lldb::addr_t {
3357     SymbolContextList sc_list;
3358     GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType(
3359         sym, lldb::eSymbolTypeData, sc_list);
3360     if (sc_list.GetSize() == 1) {
3361       SymbolContext sc;
3362       sc_list.GetContextAtIndex(0, sc);
3363       if (sc.symbol)
3364         return sc.symbol->GetLoadAddress(&GetProcess()->GetTarget());
3365     }
3366     GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType(
3367         real_sym, lldb::eSymbolTypeData, sc_list);
3368     if (sc_list.GetSize() != 1)
3369       return LLDB_INVALID_ADDRESS;
3370 
3371     SymbolContext sc;
3372     sc_list.GetContextAtIndex(0, sc);
3373     if (!sc.symbol)
3374       return LLDB_INVALID_ADDRESS;
3375 
3376     lldb::addr_t addr = sc.symbol->GetLoadAddress(&GetProcess()->GetTarget());
3377     Status error;
3378     addr = GetProcess()->ReadPointerFromMemory(addr, error);
3379     if (error.Fail())
3380       return LLDB_INVALID_ADDRESS;
3381     return addr;
3382   };
3383 
3384   lldb::addr_t false_addr = get_symbol(g_dunder_kCFBooleanFalse, g_kCFBooleanFalse);
3385   lldb::addr_t true_addr = get_symbol(g_dunder_kCFBooleanTrue, g_kCFBooleanTrue);
3386 
3387   return (m_CFBoolean_values = {false_addr, true_addr}).operator bool();
3388 }
3389 
3390 void AppleObjCRuntimeV2::GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
3391                                                       lldb::addr_t &cf_false) {
3392   if (GetCFBooleanValuesIfNeeded()) {
3393     cf_true = m_CFBoolean_values->second;
3394     cf_false = m_CFBoolean_values->first;
3395   } else
3396     this->AppleObjCRuntime::GetValuesForGlobalCFBooleans(cf_true, cf_false);
3397 }
3398 
3399 void AppleObjCRuntimeV2::ModulesDidLoad(const ModuleList &module_list) {
3400   AppleObjCRuntime::ModulesDidLoad(module_list);
3401   if (HasReadObjCLibrary() && m_shared_cache_image_headers_up)
3402     m_shared_cache_image_headers_up->SetNeedsUpdate();
3403 }
3404 
3405 bool AppleObjCRuntimeV2::IsSharedCacheImageLoaded(uint16_t image_index) {
3406   if (!m_shared_cache_image_headers_up) {
3407     m_shared_cache_image_headers_up =
3408         SharedCacheImageHeaders::CreateSharedCacheImageHeaders(*this);
3409   }
3410   if (m_shared_cache_image_headers_up)
3411     return m_shared_cache_image_headers_up->IsImageLoaded(image_index);
3412 
3413   return false;
3414 }
3415 
3416 std::optional<uint64_t> AppleObjCRuntimeV2::GetSharedCacheImageHeaderVersion() {
3417   if (!m_shared_cache_image_headers_up) {
3418     m_shared_cache_image_headers_up =
3419         SharedCacheImageHeaders::CreateSharedCacheImageHeaders(*this);
3420   }
3421   if (m_shared_cache_image_headers_up)
3422     return m_shared_cache_image_headers_up->GetVersion();
3423 
3424   return std::nullopt;
3425 }
3426 
3427 #pragma mark Frame recognizers
3428 
3429 class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame {
3430 public:
3431   ObjCExceptionRecognizedStackFrame(StackFrameSP frame_sp) {
3432     ThreadSP thread_sp = frame_sp->GetThread();
3433     ProcessSP process_sp = thread_sp->GetProcess();
3434 
3435     const lldb::ABISP &abi = process_sp->GetABI();
3436     if (!abi)
3437       return;
3438 
3439     TypeSystemClangSP scratch_ts_sp =
3440         ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget());
3441     if (!scratch_ts_sp)
3442       return;
3443     CompilerType voidstar =
3444         scratch_ts_sp->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
3445 
3446     ValueList args;
3447     Value input_value;
3448     input_value.SetCompilerType(voidstar);
3449     args.PushValue(input_value);
3450 
3451     if (!abi->GetArgumentValues(*thread_sp, args))
3452       return;
3453 
3454     addr_t exception_addr = args.GetValueAtIndex(0)->GetScalar().ULongLong();
3455 
3456     Value value(exception_addr);
3457     value.SetCompilerType(voidstar);
3458     exception = ValueObjectConstResult::Create(frame_sp.get(), value,
3459                                                ConstString("exception"));
3460     exception = ValueObjectRecognizerSynthesizedValue::Create(
3461         *exception, eValueTypeVariableArgument);
3462     exception = exception->GetDynamicValue(eDynamicDontRunTarget);
3463 
3464     m_arguments = ValueObjectListSP(new ValueObjectList());
3465     m_arguments->Append(exception);
3466 
3467     m_stop_desc = "hit Objective-C exception";
3468   }
3469 
3470   ValueObjectSP exception;
3471 
3472   lldb::ValueObjectSP GetExceptionObject() override { return exception; }
3473 };
3474 
3475 class ObjCExceptionThrowFrameRecognizer : public StackFrameRecognizer {
3476   lldb::RecognizedStackFrameSP
3477   RecognizeFrame(lldb::StackFrameSP frame) override {
3478     return lldb::RecognizedStackFrameSP(
3479         new ObjCExceptionRecognizedStackFrame(frame));
3480   };
3481   std::string GetName() override {
3482     return "ObjC Exception Throw StackFrame Recognizer";
3483   }
3484 };
3485 
3486 static void RegisterObjCExceptionRecognizer(Process *process) {
3487   FileSpec module;
3488   ConstString function;
3489   std::tie(module, function) = AppleObjCRuntime::GetExceptionThrowLocation();
3490   std::vector<ConstString> symbols = {function};
3491 
3492   process->GetTarget().GetFrameRecognizerManager().AddRecognizer(
3493       StackFrameRecognizerSP(new ObjCExceptionThrowFrameRecognizer()),
3494       module.GetFilename(), symbols,
3495       /*first_instruction_only*/ true);
3496 }
3497