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   void 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;
933       }
934       break;
935     }
936     default: {
937       result.AppendError("please provide 0 or 1 arguments");
938       result.SetStatus(lldb::eReturnStatusFailed);
939       return;
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;
1001     }
1002     result.AppendError("current process has no Objective-C runtime loaded");
1003     result.SetStatus(lldb::eReturnStatusFailed);
1004   }
1005 
1006   CommandOptions m_options;
1007 };
1008 
1009 class CommandObjectMultiwordObjC_TaggedPointer_Info
1010     : public CommandObjectParsed {
1011 public:
1012   CommandObjectMultiwordObjC_TaggedPointer_Info(CommandInterpreter &interpreter)
1013       : CommandObjectParsed(
1014             interpreter, "info", "Dump information on a tagged pointer.",
1015             "language objc tagged-pointer info",
1016             eCommandRequiresProcess | eCommandProcessMustBeLaunched |
1017                 eCommandProcessMustBePaused) {
1018     CommandArgumentEntry arg;
1019     CommandArgumentData index_arg;
1020 
1021     // Define the first (and only) variant of this arg.
1022     index_arg.arg_type = eArgTypeAddress;
1023     index_arg.arg_repetition = eArgRepeatPlus;
1024 
1025     // There is only one variant this argument could be; put it into the
1026     // argument entry.
1027     arg.push_back(index_arg);
1028 
1029     // Push the data for the first argument into the m_arguments vector.
1030     m_arguments.push_back(arg);
1031   }
1032 
1033   ~CommandObjectMultiwordObjC_TaggedPointer_Info() override = default;
1034 
1035 protected:
1036   void DoExecute(Args &command, CommandReturnObject &result) override {
1037     if (command.GetArgumentCount() == 0) {
1038       result.AppendError("this command requires arguments");
1039       result.SetStatus(lldb::eReturnStatusFailed);
1040       return;
1041     }
1042 
1043     Process *process = m_exe_ctx.GetProcessPtr();
1044     ExecutionContext exe_ctx(process);
1045 
1046     ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process);
1047     if (!objc_runtime) {
1048       result.AppendError("current process has no Objective-C runtime loaded");
1049       result.SetStatus(lldb::eReturnStatusFailed);
1050       return;
1051     }
1052 
1053     ObjCLanguageRuntime::TaggedPointerVendor *tagged_ptr_vendor =
1054         objc_runtime->GetTaggedPointerVendor();
1055     if (!tagged_ptr_vendor) {
1056       result.AppendError("current process has no tagged pointer support");
1057       result.SetStatus(lldb::eReturnStatusFailed);
1058       return;
1059     }
1060 
1061     for (size_t i = 0; i < command.GetArgumentCount(); i++) {
1062       const char *arg_str = command.GetArgumentAtIndex(i);
1063       if (!arg_str)
1064         continue;
1065 
1066       Status error;
1067       lldb::addr_t arg_addr = OptionArgParser::ToAddress(
1068           &exe_ctx, arg_str, LLDB_INVALID_ADDRESS, &error);
1069       if (arg_addr == 0 || arg_addr == LLDB_INVALID_ADDRESS || error.Fail()) {
1070         result.AppendErrorWithFormatv(
1071             "could not convert '{0}' to a valid address\n", arg_str);
1072         result.SetStatus(lldb::eReturnStatusFailed);
1073         return;
1074       }
1075 
1076       if (!tagged_ptr_vendor->IsPossibleTaggedPointer(arg_addr)) {
1077         result.GetOutputStream().Format("{0:x16} is not tagged\n", arg_addr);
1078         continue;
1079       }
1080 
1081       auto descriptor_sp = tagged_ptr_vendor->GetClassDescriptor(arg_addr);
1082       if (!descriptor_sp) {
1083         result.AppendErrorWithFormatv(
1084             "could not get class descriptor for {0:x16}\n", arg_addr);
1085         result.SetStatus(lldb::eReturnStatusFailed);
1086         return;
1087       }
1088 
1089       uint64_t info_bits = 0;
1090       uint64_t value_bits = 0;
1091       uint64_t payload = 0;
1092       if (descriptor_sp->GetTaggedPointerInfo(&info_bits, &value_bits,
1093                                               &payload)) {
1094         result.GetOutputStream().Format(
1095             "{0:x} is tagged\n"
1096             "\tpayload = {1:x16}\n"
1097             "\tvalue = {2:x16}\n"
1098             "\tinfo bits = {3:x16}\n"
1099             "\tclass = {4}\n",
1100             arg_addr, payload, value_bits, info_bits,
1101             descriptor_sp->GetClassName().AsCString("<unknown>"));
1102       } else {
1103         result.GetOutputStream().Format("{0:x16} is not tagged\n", arg_addr);
1104       }
1105     }
1106 
1107     result.SetStatus(lldb::eReturnStatusSuccessFinishResult);
1108   }
1109 };
1110 
1111 class CommandObjectMultiwordObjC_ClassTable : public CommandObjectMultiword {
1112 public:
1113   CommandObjectMultiwordObjC_ClassTable(CommandInterpreter &interpreter)
1114       : CommandObjectMultiword(
1115             interpreter, "class-table",
1116             "Commands for operating on the Objective-C class table.",
1117             "class-table <subcommand> [<subcommand-options>]") {
1118     LoadSubCommand(
1119         "dump",
1120         CommandObjectSP(new CommandObjectObjC_ClassTable_Dump(interpreter)));
1121   }
1122 
1123   ~CommandObjectMultiwordObjC_ClassTable() override = default;
1124 };
1125 
1126 class CommandObjectMultiwordObjC_TaggedPointer : public CommandObjectMultiword {
1127 public:
1128   CommandObjectMultiwordObjC_TaggedPointer(CommandInterpreter &interpreter)
1129       : CommandObjectMultiword(
1130             interpreter, "tagged-pointer",
1131             "Commands for operating on Objective-C tagged pointers.",
1132             "class-table <subcommand> [<subcommand-options>]") {
1133     LoadSubCommand(
1134         "info",
1135         CommandObjectSP(
1136             new CommandObjectMultiwordObjC_TaggedPointer_Info(interpreter)));
1137   }
1138 
1139   ~CommandObjectMultiwordObjC_TaggedPointer() override = default;
1140 };
1141 
1142 class CommandObjectMultiwordObjC : public CommandObjectMultiword {
1143 public:
1144   CommandObjectMultiwordObjC(CommandInterpreter &interpreter)
1145       : CommandObjectMultiword(
1146             interpreter, "objc",
1147             "Commands for operating on the Objective-C language runtime.",
1148             "objc <subcommand> [<subcommand-options>]") {
1149     LoadSubCommand("class-table",
1150                    CommandObjectSP(
1151                        new CommandObjectMultiwordObjC_ClassTable(interpreter)));
1152     LoadSubCommand("tagged-pointer",
1153                    CommandObjectSP(new CommandObjectMultiwordObjC_TaggedPointer(
1154                        interpreter)));
1155   }
1156 
1157   ~CommandObjectMultiwordObjC() override = default;
1158 };
1159 
1160 void AppleObjCRuntimeV2::Initialize() {
1161   PluginManager::RegisterPlugin(
1162       GetPluginNameStatic(), "Apple Objective-C Language Runtime - Version 2",
1163       CreateInstance,
1164       [](CommandInterpreter &interpreter) -> lldb::CommandObjectSP {
1165         return CommandObjectSP(new CommandObjectMultiwordObjC(interpreter));
1166       },
1167       GetBreakpointExceptionPrecondition);
1168 }
1169 
1170 void AppleObjCRuntimeV2::Terminate() {
1171   PluginManager::UnregisterPlugin(CreateInstance);
1172 }
1173 
1174 BreakpointResolverSP
1175 AppleObjCRuntimeV2::CreateExceptionResolver(const BreakpointSP &bkpt,
1176                                             bool catch_bp, bool throw_bp) {
1177   BreakpointResolverSP resolver_sp;
1178 
1179   if (throw_bp)
1180     resolver_sp = std::make_shared<BreakpointResolverName>(
1181         bkpt, std::get<1>(GetExceptionThrowLocation()).AsCString(),
1182         eFunctionNameTypeBase, eLanguageTypeUnknown, Breakpoint::Exact, 0,
1183         eLazyBoolNo);
1184   // FIXME: We don't do catch breakpoints for ObjC yet.
1185   // Should there be some way for the runtime to specify what it can do in this
1186   // regard?
1187   return resolver_sp;
1188 }
1189 
1190 llvm::Expected<std::unique_ptr<UtilityFunction>>
1191 AppleObjCRuntimeV2::CreateObjectChecker(std::string name,
1192                                         ExecutionContext &exe_ctx) {
1193   char check_function_code[2048];
1194 
1195   int len = 0;
1196   if (m_has_object_getClass) {
1197     len = ::snprintf(check_function_code, sizeof(check_function_code), R"(
1198                      extern "C" void *gdb_object_getClass(void *);
1199                      extern "C" int printf(const char *format, ...);
1200                      extern "C" void
1201                      %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) {
1202                        if ($__lldb_arg_obj == (void *)0)
1203                          return; // nil is ok
1204                        if (!gdb_object_getClass($__lldb_arg_obj)) {
1205                          *((volatile int *)0) = 'ocgc';
1206                        } else if ($__lldb_arg_selector != (void *)0) {
1207                          signed char $responds = (signed char)
1208                              [(id)$__lldb_arg_obj respondsToSelector:
1209                                  (void *) $__lldb_arg_selector];
1210                          if ($responds == (signed char) 0)
1211                            *((volatile int *)0) = 'ocgc';
1212                        }
1213                      })",
1214                      name.c_str());
1215   } else {
1216     len = ::snprintf(check_function_code, sizeof(check_function_code), R"(
1217                      extern "C" void *gdb_class_getClass(void *);
1218                      extern "C" int printf(const char *format, ...);
1219                      extern "C" void
1220                      %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) {
1221                        if ($__lldb_arg_obj == (void *)0)
1222                          return; // nil is ok
1223                        void **$isa_ptr = (void **)$__lldb_arg_obj;
1224                        if (*$isa_ptr == (void *)0 ||
1225                            !gdb_class_getClass(*$isa_ptr))
1226                          *((volatile int *)0) = 'ocgc';
1227                        else if ($__lldb_arg_selector != (void *)0) {
1228                          signed char $responds = (signed char)
1229                              [(id)$__lldb_arg_obj respondsToSelector:
1230                                  (void *) $__lldb_arg_selector];
1231                          if ($responds == (signed char) 0)
1232                            *((volatile int *)0) = 'ocgc';
1233                        }
1234                      })",
1235                      name.c_str());
1236   }
1237 
1238   assert(len < (int)sizeof(check_function_code));
1239   UNUSED_IF_ASSERT_DISABLED(len);
1240 
1241   return GetTargetRef().CreateUtilityFunction(check_function_code, name,
1242                                               eLanguageTypeC, exe_ctx);
1243 }
1244 
1245 size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type,
1246                                                 const char *ivar_name) {
1247   uint32_t ivar_offset = LLDB_INVALID_IVAR_OFFSET;
1248 
1249   ConstString class_name = parent_ast_type.GetTypeName();
1250   if (!class_name.IsEmpty() && ivar_name && ivar_name[0]) {
1251     // Make the objective C V2 mangled name for the ivar offset from the class
1252     // name and ivar name
1253     std::string buffer("OBJC_IVAR_$_");
1254     buffer.append(class_name.AsCString());
1255     buffer.push_back('.');
1256     buffer.append(ivar_name);
1257     ConstString ivar_const_str(buffer.c_str());
1258 
1259     // Try to get the ivar offset address from the symbol table first using the
1260     // name we created above
1261     SymbolContextList sc_list;
1262     Target &target = m_process->GetTarget();
1263     target.GetImages().FindSymbolsWithNameAndType(ivar_const_str,
1264                                                   eSymbolTypeObjCIVar, sc_list);
1265 
1266     addr_t ivar_offset_address = LLDB_INVALID_ADDRESS;
1267 
1268     Status error;
1269     SymbolContext ivar_offset_symbol;
1270     if (sc_list.GetSize() == 1 &&
1271         sc_list.GetContextAtIndex(0, ivar_offset_symbol)) {
1272       if (ivar_offset_symbol.symbol)
1273         ivar_offset_address =
1274             ivar_offset_symbol.symbol->GetLoadAddress(&target);
1275     }
1276 
1277     // If we didn't get the ivar offset address from the symbol table, fall
1278     // back to getting it from the runtime
1279     if (ivar_offset_address == LLDB_INVALID_ADDRESS)
1280       ivar_offset_address = LookupRuntimeSymbol(ivar_const_str);
1281 
1282     if (ivar_offset_address != LLDB_INVALID_ADDRESS)
1283       ivar_offset = m_process->ReadUnsignedIntegerFromMemory(
1284           ivar_offset_address, 4, LLDB_INVALID_IVAR_OFFSET, error);
1285   }
1286   return ivar_offset;
1287 }
1288 
1289 // tagged pointers are special not-a-real-pointer values that contain both type
1290 // and value information this routine attempts to check with as little
1291 // computational effort as possible whether something could possibly be a
1292 // tagged pointer - false positives are possible but false negatives shouldn't
1293 bool AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr) {
1294   if (!m_tagged_pointer_vendor_up)
1295     return false;
1296   return m_tagged_pointer_vendor_up->IsPossibleTaggedPointer(ptr);
1297 }
1298 
1299 class RemoteNXMapTable {
1300 public:
1301   RemoteNXMapTable() : m_end_iterator(*this, -1) {}
1302 
1303   void Dump() {
1304     printf("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr);
1305     printf("RemoteNXMapTable.m_count = %u\n", m_count);
1306     printf("RemoteNXMapTable.m_num_buckets_minus_one = %u\n",
1307            m_num_buckets_minus_one);
1308     printf("RemoteNXMapTable.m_buckets_ptr = 0x%" PRIX64 "\n", m_buckets_ptr);
1309   }
1310 
1311   bool ParseHeader(Process *process, lldb::addr_t load_addr) {
1312     m_process = process;
1313     m_load_addr = load_addr;
1314     m_map_pair_size = m_process->GetAddressByteSize() * 2;
1315     m_invalid_key =
1316         m_process->GetAddressByteSize() == 8 ? UINT64_MAX : UINT32_MAX;
1317     Status err;
1318 
1319     // This currently holds true for all platforms we support, but we might
1320     // need to change this to use get the actually byte size of "unsigned" from
1321     // the target AST...
1322     const uint32_t unsigned_byte_size = sizeof(uint32_t);
1323     // Skip the prototype as we don't need it (const struct
1324     // +NXMapTablePrototype *prototype)
1325 
1326     bool success = true;
1327     if (load_addr == LLDB_INVALID_ADDRESS)
1328       success = false;
1329     else {
1330       lldb::addr_t cursor = load_addr + m_process->GetAddressByteSize();
1331 
1332       // unsigned count;
1333       m_count = m_process->ReadUnsignedIntegerFromMemory(
1334           cursor, unsigned_byte_size, 0, err);
1335       if (m_count) {
1336         cursor += unsigned_byte_size;
1337 
1338         // unsigned nbBucketsMinusOne;
1339         m_num_buckets_minus_one = m_process->ReadUnsignedIntegerFromMemory(
1340             cursor, unsigned_byte_size, 0, err);
1341         cursor += unsigned_byte_size;
1342 
1343         // void *buckets;
1344         m_buckets_ptr = m_process->ReadPointerFromMemory(cursor, err);
1345 
1346         success = m_count > 0 && m_buckets_ptr != LLDB_INVALID_ADDRESS;
1347       }
1348     }
1349 
1350     if (!success) {
1351       m_count = 0;
1352       m_num_buckets_minus_one = 0;
1353       m_buckets_ptr = LLDB_INVALID_ADDRESS;
1354     }
1355     return success;
1356   }
1357 
1358   // const_iterator mimics NXMapState and its code comes from NXInitMapState
1359   // and NXNextMapState.
1360   typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element;
1361 
1362   friend class const_iterator;
1363   class const_iterator {
1364   public:
1365     const_iterator(RemoteNXMapTable &parent, int index)
1366         : m_parent(parent), m_index(index) {
1367       AdvanceToValidIndex();
1368     }
1369 
1370     const_iterator(const const_iterator &rhs)
1371         : m_parent(rhs.m_parent), m_index(rhs.m_index) {
1372       // AdvanceToValidIndex() has been called by rhs already.
1373     }
1374 
1375     const_iterator &operator=(const const_iterator &rhs) {
1376       // AdvanceToValidIndex() has been called by rhs already.
1377       assert(&m_parent == &rhs.m_parent);
1378       m_index = rhs.m_index;
1379       return *this;
1380     }
1381 
1382     bool operator==(const const_iterator &rhs) const {
1383       if (&m_parent != &rhs.m_parent)
1384         return false;
1385       if (m_index != rhs.m_index)
1386         return false;
1387 
1388       return true;
1389     }
1390 
1391     bool operator!=(const const_iterator &rhs) const {
1392       return !(operator==(rhs));
1393     }
1394 
1395     const_iterator &operator++() {
1396       AdvanceToValidIndex();
1397       return *this;
1398     }
1399 
1400     element operator*() const {
1401       if (m_index == -1) {
1402         // TODO find a way to make this an error, but not an assert
1403         return element();
1404       }
1405 
1406       lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
1407       size_t map_pair_size = m_parent.m_map_pair_size;
1408       lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
1409 
1410       Status err;
1411 
1412       lldb::addr_t key =
1413           m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
1414       if (!err.Success())
1415         return element();
1416       lldb::addr_t value = m_parent.m_process->ReadPointerFromMemory(
1417           pair_ptr + m_parent.m_process->GetAddressByteSize(), err);
1418       if (!err.Success())
1419         return element();
1420 
1421       std::string key_string;
1422 
1423       m_parent.m_process->ReadCStringFromMemory(key, key_string, err);
1424       if (!err.Success())
1425         return element();
1426 
1427       return element(ConstString(key_string.c_str()),
1428                      (ObjCLanguageRuntime::ObjCISA)value);
1429     }
1430 
1431   private:
1432     void AdvanceToValidIndex() {
1433       if (m_index == -1)
1434         return;
1435 
1436       const lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr;
1437       const size_t map_pair_size = m_parent.m_map_pair_size;
1438       const lldb::addr_t invalid_key = m_parent.m_invalid_key;
1439       Status err;
1440 
1441       while (m_index--) {
1442         lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
1443         lldb::addr_t key =
1444             m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
1445 
1446         if (!err.Success()) {
1447           m_index = -1;
1448           return;
1449         }
1450 
1451         if (key != invalid_key)
1452           return;
1453       }
1454     }
1455     RemoteNXMapTable &m_parent;
1456     int m_index;
1457   };
1458 
1459   const_iterator begin() {
1460     return const_iterator(*this, m_num_buckets_minus_one + 1);
1461   }
1462 
1463   const_iterator end() { return m_end_iterator; }
1464 
1465   uint32_t GetCount() const { return m_count; }
1466 
1467   uint32_t GetBucketCount() const { return m_num_buckets_minus_one; }
1468 
1469   lldb::addr_t GetBucketDataPointer() const { return m_buckets_ptr; }
1470 
1471   lldb::addr_t GetTableLoadAddress() const { return m_load_addr; }
1472 
1473 private:
1474   // contents of _NXMapTable struct
1475   uint32_t m_count = 0;
1476   uint32_t m_num_buckets_minus_one = 0;
1477   lldb::addr_t m_buckets_ptr = LLDB_INVALID_ADDRESS;
1478   lldb_private::Process *m_process = nullptr;
1479   const_iterator m_end_iterator;
1480   lldb::addr_t m_load_addr = LLDB_INVALID_ADDRESS;
1481   size_t m_map_pair_size = 0;
1482   lldb::addr_t m_invalid_key = 0;
1483 };
1484 
1485 AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() = default;
1486 
1487 void AppleObjCRuntimeV2::HashTableSignature::UpdateSignature(
1488     const RemoteNXMapTable &hash_table) {
1489   m_count = hash_table.GetCount();
1490   m_num_buckets = hash_table.GetBucketCount();
1491   m_buckets_ptr = hash_table.GetBucketDataPointer();
1492 }
1493 
1494 bool AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate(
1495     Process *process, AppleObjCRuntimeV2 *runtime,
1496     RemoteNXMapTable &hash_table) {
1497   if (!hash_table.ParseHeader(process, runtime->GetISAHashTablePointer())) {
1498     return false; // Failed to parse the header, no need to update anything
1499   }
1500 
1501   // Check with out current signature and return true if the count, number of
1502   // buckets or the hash table address changes.
1503   if (m_count == hash_table.GetCount() &&
1504       m_num_buckets == hash_table.GetBucketCount() &&
1505       m_buckets_ptr == hash_table.GetBucketDataPointer()) {
1506     // Hash table hasn't changed
1507     return false;
1508   }
1509   // Hash table data has changed, we need to update
1510   return true;
1511 }
1512 
1513 ObjCLanguageRuntime::ClassDescriptorSP
1514 AppleObjCRuntimeV2::GetClassDescriptorFromISA(ObjCISA isa) {
1515   ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp;
1516   if (auto *non_pointer_isa_cache = GetNonPointerIsaCache())
1517     class_descriptor_sp = non_pointer_isa_cache->GetClassDescriptor(isa);
1518   if (!class_descriptor_sp)
1519     class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa);
1520   return class_descriptor_sp;
1521 }
1522 
1523 ObjCLanguageRuntime::ClassDescriptorSP
1524 AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) {
1525   ClassDescriptorSP objc_class_sp;
1526   if (valobj.IsBaseClass()) {
1527     ValueObject *parent = valobj.GetParent();
1528     // if I am my own parent, bail out of here fast..
1529     if (parent && parent != &valobj) {
1530       ClassDescriptorSP parent_descriptor_sp = GetClassDescriptor(*parent);
1531       if (parent_descriptor_sp)
1532         return parent_descriptor_sp->GetSuperclass();
1533     }
1534     return nullptr;
1535   }
1536   // if we get an invalid VO (which might still happen when playing around with
1537   // pointers returned by the expression parser, don't consider this a valid
1538   // ObjC object)
1539   if (!valobj.GetCompilerType().IsValid())
1540     return objc_class_sp;
1541   addr_t isa_pointer = valobj.GetPointerValue();
1542 
1543   // tagged pointer
1544   if (IsTaggedPointer(isa_pointer))
1545     return m_tagged_pointer_vendor_up->GetClassDescriptor(isa_pointer);
1546   ExecutionContext exe_ctx(valobj.GetExecutionContextRef());
1547 
1548   Process *process = exe_ctx.GetProcessPtr();
1549   if (!process)
1550     return objc_class_sp;
1551 
1552   Status error;
1553   ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error);
1554   if (isa == LLDB_INVALID_ADDRESS)
1555     return objc_class_sp;
1556 
1557   objc_class_sp = GetClassDescriptorFromISA(isa);
1558   if (!objc_class_sp) {
1559     if (ABISP abi_sp = process->GetABI())
1560       isa = abi_sp->FixCodeAddress(isa);
1561     objc_class_sp = GetClassDescriptorFromISA(isa);
1562   }
1563 
1564   if (isa && !objc_class_sp) {
1565     Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
1566     LLDB_LOGF(log,
1567               "0x%" PRIx64 ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was "
1568               "not in class descriptor cache 0x%" PRIx64,
1569               isa_pointer, isa);
1570   }
1571   return objc_class_sp;
1572 }
1573 
1574 lldb::addr_t AppleObjCRuntimeV2::GetTaggedPointerObfuscator() {
1575   if (m_tagged_pointer_obfuscator != LLDB_INVALID_ADDRESS)
1576     return m_tagged_pointer_obfuscator;
1577 
1578   Process *process = GetProcess();
1579   ModuleSP objc_module_sp(GetObjCModule());
1580 
1581   if (!objc_module_sp)
1582     return LLDB_INVALID_ADDRESS;
1583 
1584   static ConstString g_gdb_objc_obfuscator(
1585       "objc_debug_taggedpointer_obfuscator");
1586 
1587   const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
1588       g_gdb_objc_obfuscator, lldb::eSymbolTypeAny);
1589   if (symbol) {
1590     lldb::addr_t g_gdb_obj_obfuscator_ptr =
1591         symbol->GetLoadAddress(&process->GetTarget());
1592 
1593     if (g_gdb_obj_obfuscator_ptr != LLDB_INVALID_ADDRESS) {
1594       Status error;
1595       m_tagged_pointer_obfuscator =
1596           process->ReadPointerFromMemory(g_gdb_obj_obfuscator_ptr, error);
1597     }
1598   }
1599   // If we don't have a correct value at this point, there must be no
1600   // obfuscation.
1601   if (m_tagged_pointer_obfuscator == LLDB_INVALID_ADDRESS)
1602     m_tagged_pointer_obfuscator = 0;
1603 
1604   return m_tagged_pointer_obfuscator;
1605 }
1606 
1607 lldb::addr_t AppleObjCRuntimeV2::GetISAHashTablePointer() {
1608   if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS) {
1609     Process *process = GetProcess();
1610 
1611     ModuleSP objc_module_sp(GetObjCModule());
1612 
1613     if (!objc_module_sp)
1614       return LLDB_INVALID_ADDRESS;
1615 
1616     static ConstString g_gdb_objc_realized_classes("gdb_objc_realized_classes");
1617 
1618     const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
1619         g_gdb_objc_realized_classes, lldb::eSymbolTypeAny);
1620     if (symbol) {
1621       lldb::addr_t gdb_objc_realized_classes_ptr =
1622           symbol->GetLoadAddress(&process->GetTarget());
1623 
1624       if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS) {
1625         Status error;
1626         m_isa_hash_table_ptr = process->ReadPointerFromMemory(
1627             gdb_objc_realized_classes_ptr, error);
1628       }
1629     }
1630   }
1631   return m_isa_hash_table_ptr;
1632 }
1633 
1634 std::unique_ptr<AppleObjCRuntimeV2::SharedCacheImageHeaders>
1635 AppleObjCRuntimeV2::SharedCacheImageHeaders::CreateSharedCacheImageHeaders(
1636     AppleObjCRuntimeV2 &runtime) {
1637   Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
1638   Process *process = runtime.GetProcess();
1639   ModuleSP objc_module_sp(runtime.GetObjCModule());
1640   if (!objc_module_sp || !process)
1641     return nullptr;
1642 
1643   const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
1644       ConstString("objc_debug_headerInfoRWs"), lldb::eSymbolTypeAny);
1645   if (!symbol) {
1646     LLDB_LOG(log, "Symbol 'objc_debug_headerInfoRWs' unavailable. Some "
1647                   "information concerning the shared cache may be unavailable");
1648     return nullptr;
1649   }
1650 
1651   lldb::addr_t objc_debug_headerInfoRWs_addr =
1652       symbol->GetLoadAddress(&process->GetTarget());
1653   if (objc_debug_headerInfoRWs_addr == LLDB_INVALID_ADDRESS) {
1654     LLDB_LOG(log, "Symbol 'objc_debug_headerInfoRWs' was found but we were "
1655                   "unable to get its load address");
1656     return nullptr;
1657   }
1658 
1659   Status error;
1660   lldb::addr_t objc_debug_headerInfoRWs_ptr =
1661       process->ReadPointerFromMemory(objc_debug_headerInfoRWs_addr, error);
1662   if (error.Fail()) {
1663     LLDB_LOG(log,
1664              "Failed to read address of 'objc_debug_headerInfoRWs' at {0:x}",
1665              objc_debug_headerInfoRWs_addr);
1666     return nullptr;
1667   }
1668 
1669   const size_t metadata_size =
1670       sizeof(uint32_t) + sizeof(uint32_t); // count + entsize
1671   DataBufferHeap metadata_buffer(metadata_size, '\0');
1672   process->ReadMemory(objc_debug_headerInfoRWs_ptr, metadata_buffer.GetBytes(),
1673                       metadata_size, error);
1674   if (error.Fail()) {
1675     LLDB_LOG(log,
1676              "Unable to read metadata for 'objc_debug_headerInfoRWs' at {0:x}",
1677              objc_debug_headerInfoRWs_ptr);
1678     return nullptr;
1679   }
1680 
1681   DataExtractor metadata_extractor(metadata_buffer.GetBytes(), metadata_size,
1682                                    process->GetByteOrder(),
1683                                    process->GetAddressByteSize());
1684   lldb::offset_t cursor = 0;
1685   uint32_t count = metadata_extractor.GetU32_unchecked(&cursor);
1686   uint32_t entsize = metadata_extractor.GetU32_unchecked(&cursor);
1687   if (count == 0 || entsize == 0) {
1688     LLDB_LOG(log,
1689              "'objc_debug_headerInfoRWs' had count {0} with entsize {1}. These "
1690              "should both be non-zero.",
1691              count, entsize);
1692     return nullptr;
1693   }
1694 
1695   std::unique_ptr<SharedCacheImageHeaders> shared_cache_image_headers(
1696       new SharedCacheImageHeaders(runtime, objc_debug_headerInfoRWs_ptr, count,
1697                                   entsize));
1698   if (auto Err = shared_cache_image_headers->UpdateIfNeeded()) {
1699     LLDB_LOG_ERROR(log, std::move(Err),
1700                    "Failed to update SharedCacheImageHeaders: {0}");
1701     return nullptr;
1702   }
1703 
1704   return shared_cache_image_headers;
1705 }
1706 
1707 llvm::Error AppleObjCRuntimeV2::SharedCacheImageHeaders::UpdateIfNeeded() {
1708   if (!m_needs_update)
1709     return llvm::Error::success();
1710 
1711   Process *process = m_runtime.GetProcess();
1712   constexpr lldb::addr_t metadata_size =
1713       sizeof(uint32_t) + sizeof(uint32_t); // count + entsize
1714 
1715   Status error;
1716   const lldb::addr_t first_header_addr = m_headerInfoRWs_ptr + metadata_size;
1717   DataBufferHeap header_buffer(m_entsize, '\0');
1718   lldb::offset_t cursor = 0;
1719   for (uint32_t i = 0; i < m_count; i++) {
1720     const lldb::addr_t header_addr = first_header_addr + (i * m_entsize);
1721     process->ReadMemory(header_addr, header_buffer.GetBytes(), m_entsize,
1722                         error);
1723     if (error.Fail())
1724       return llvm::createStringError(llvm::inconvertibleErrorCode(),
1725                                      "Failed to read memory from inferior when "
1726                                      "populating SharedCacheImageHeaders");
1727 
1728     DataExtractor header_extractor(header_buffer.GetBytes(), m_entsize,
1729                                    process->GetByteOrder(),
1730                                    process->GetAddressByteSize());
1731     cursor = 0;
1732     bool is_loaded = false;
1733     if (m_entsize == 4) {
1734       uint32_t header = header_extractor.GetU32_unchecked(&cursor);
1735       if (header & 1)
1736         is_loaded = true;
1737     } else {
1738       uint64_t header = header_extractor.GetU64_unchecked(&cursor);
1739       if (header & 1)
1740         is_loaded = true;
1741     }
1742 
1743     if (is_loaded)
1744       m_loaded_images.set(i);
1745     else
1746       m_loaded_images.reset(i);
1747   }
1748   m_needs_update = false;
1749   m_version++;
1750   return llvm::Error::success();
1751 }
1752 
1753 bool AppleObjCRuntimeV2::SharedCacheImageHeaders::IsImageLoaded(
1754     uint16_t image_index) {
1755   if (image_index >= m_count)
1756     return false;
1757   if (auto Err = UpdateIfNeeded()) {
1758     Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
1759     LLDB_LOG_ERROR(log, std::move(Err),
1760                    "Failed to update SharedCacheImageHeaders: {0}");
1761   }
1762   return m_loaded_images.test(image_index);
1763 }
1764 
1765 uint64_t AppleObjCRuntimeV2::SharedCacheImageHeaders::GetVersion() {
1766   if (auto Err = UpdateIfNeeded()) {
1767     Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
1768     LLDB_LOG_ERROR(log, std::move(Err),
1769                    "Failed to update SharedCacheImageHeaders: {0}");
1770   }
1771   return m_version;
1772 }
1773 
1774 std::unique_ptr<UtilityFunction>
1775 AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoUtilityFunctionImpl(
1776     ExecutionContext &exe_ctx, Helper helper, std::string code,
1777     std::string name) {
1778   Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
1779 
1780   LLDB_LOG(log, "Creating utility function {0}", name);
1781 
1782   TypeSystemClangSP scratch_ts_sp =
1783       ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef());
1784   if (!scratch_ts_sp)
1785     return {};
1786 
1787   auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
1788       std::move(code), std::move(name), eLanguageTypeC, exe_ctx);
1789   if (!utility_fn_or_error) {
1790     LLDB_LOG_ERROR(
1791         log, utility_fn_or_error.takeError(),
1792         "Failed to get utility function for dynamic info extractor: {0}");
1793     return {};
1794   }
1795 
1796   // Make some types for our arguments.
1797   CompilerType clang_uint32_t_type =
1798       scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
1799   CompilerType clang_void_pointer_type =
1800       scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();
1801 
1802   // Make the runner function for our implementation utility function.
1803   ValueList arguments;
1804   Value value;
1805   value.SetValueType(Value::ValueType::Scalar);
1806   value.SetCompilerType(clang_void_pointer_type);
1807   arguments.PushValue(value);
1808   arguments.PushValue(value);
1809   value.SetValueType(Value::ValueType::Scalar);
1810   value.SetCompilerType(clang_uint32_t_type);
1811   arguments.PushValue(value);
1812 
1813   // objc_getRealizedClassList_trylock takes an additional buffer and length.
1814   if (helper == Helper::objc_getRealizedClassList_trylock) {
1815     value.SetCompilerType(clang_void_pointer_type);
1816     arguments.PushValue(value);
1817     value.SetCompilerType(clang_uint32_t_type);
1818     arguments.PushValue(value);
1819   }
1820 
1821   arguments.PushValue(value);
1822 
1823   std::unique_ptr<UtilityFunction> utility_fn = std::move(*utility_fn_or_error);
1824 
1825   Status error;
1826   utility_fn->MakeFunctionCaller(clang_uint32_t_type, arguments,
1827                                  exe_ctx.GetThreadSP(), error);
1828 
1829   if (error.Fail()) {
1830     LLDB_LOG(log,
1831              "Failed to make function caller for implementation lookup: {0}.",
1832              error.AsCString());
1833     return {};
1834   }
1835 
1836   return utility_fn;
1837 }
1838 
1839 UtilityFunction *
1840 AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoUtilityFunction(
1841     ExecutionContext &exe_ctx, Helper helper) {
1842   switch (helper) {
1843   case gdb_objc_realized_classes: {
1844     if (!m_gdb_objc_realized_classes_helper.utility_function)
1845       m_gdb_objc_realized_classes_helper.utility_function =
1846           GetClassInfoUtilityFunctionImpl(exe_ctx, helper,
1847                                           g_get_dynamic_class_info_body,
1848                                           g_get_dynamic_class_info_name);
1849     return m_gdb_objc_realized_classes_helper.utility_function.get();
1850   }
1851   case objc_copyRealizedClassList: {
1852     if (!m_objc_copyRealizedClassList_helper.utility_function)
1853       m_objc_copyRealizedClassList_helper.utility_function =
1854           GetClassInfoUtilityFunctionImpl(exe_ctx, helper,
1855                                           g_get_dynamic_class_info2_body,
1856                                           g_get_dynamic_class_info2_name);
1857     return m_objc_copyRealizedClassList_helper.utility_function.get();
1858   }
1859   case objc_getRealizedClassList_trylock: {
1860     if (!m_objc_getRealizedClassList_trylock_helper.utility_function)
1861       m_objc_getRealizedClassList_trylock_helper.utility_function =
1862           GetClassInfoUtilityFunctionImpl(exe_ctx, helper,
1863                                           g_get_dynamic_class_info3_body,
1864                                           g_get_dynamic_class_info3_name);
1865     return m_objc_getRealizedClassList_trylock_helper.utility_function.get();
1866   }
1867   }
1868   llvm_unreachable("Unexpected helper");
1869 }
1870 
1871 lldb::addr_t &
1872 AppleObjCRuntimeV2::DynamicClassInfoExtractor::GetClassInfoArgs(Helper helper) {
1873   switch (helper) {
1874   case gdb_objc_realized_classes:
1875     return m_gdb_objc_realized_classes_helper.args;
1876   case objc_copyRealizedClassList:
1877     return m_objc_copyRealizedClassList_helper.args;
1878   case objc_getRealizedClassList_trylock:
1879     return m_objc_getRealizedClassList_trylock_helper.args;
1880   }
1881   llvm_unreachable("Unexpected helper");
1882 }
1883 
1884 AppleObjCRuntimeV2::DynamicClassInfoExtractor::Helper
1885 AppleObjCRuntimeV2::DynamicClassInfoExtractor::ComputeHelper(
1886     ExecutionContext &exe_ctx) const {
1887   if (!m_runtime.m_has_objc_copyRealizedClassList &&
1888       !m_runtime.m_has_objc_getRealizedClassList_trylock)
1889     return DynamicClassInfoExtractor::gdb_objc_realized_classes;
1890 
1891   if (Process *process = m_runtime.GetProcess()) {
1892     if (DynamicLoader *loader = process->GetDynamicLoader()) {
1893       if (loader->IsFullyInitialized()) {
1894         switch (exe_ctx.GetTargetRef().GetDynamicClassInfoHelper()) {
1895         case eDynamicClassInfoHelperAuto:
1896           [[clang::fallthrough]];
1897         case eDynamicClassInfoHelperGetRealizedClassList:
1898           if (m_runtime.m_has_objc_getRealizedClassList_trylock)
1899             return DynamicClassInfoExtractor::objc_getRealizedClassList_trylock;
1900           [[clang::fallthrough]];
1901         case eDynamicClassInfoHelperCopyRealizedClassList:
1902           if (m_runtime.m_has_objc_copyRealizedClassList)
1903             return DynamicClassInfoExtractor::objc_copyRealizedClassList;
1904           [[clang::fallthrough]];
1905         case eDynamicClassInfoHelperRealizedClassesStruct:
1906           return DynamicClassInfoExtractor::gdb_objc_realized_classes;
1907         }
1908       }
1909     }
1910   }
1911 
1912   return DynamicClassInfoExtractor::gdb_objc_realized_classes;
1913 }
1914 
1915 std::unique_ptr<UtilityFunction>
1916 AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::
1917     GetClassInfoUtilityFunctionImpl(ExecutionContext &exe_ctx) {
1918   Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
1919 
1920   LLDB_LOG(log, "Creating utility function {0}",
1921            g_get_shared_cache_class_info_name);
1922 
1923   TypeSystemClangSP scratch_ts_sp =
1924       ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef());
1925   if (!scratch_ts_sp)
1926     return {};
1927 
1928   // If the inferior objc.dylib has the class_getNameRaw function, use that in
1929   // our jitted expression.  Else fall back to the old class_getName.
1930   static ConstString g_class_getName_symbol_name("class_getName");
1931   static ConstString g_class_getNameRaw_symbol_name(
1932       "objc_debug_class_getNameRaw");
1933 
1934   ConstString class_name_getter_function_name =
1935       m_runtime.HasSymbol(g_class_getNameRaw_symbol_name)
1936           ? g_class_getNameRaw_symbol_name
1937           : g_class_getName_symbol_name;
1938 
1939   // Substitute in the correct class_getName / class_getNameRaw function name,
1940   // concatenate the two parts of our expression text.  The format string has
1941   // two %s's, so provide the name twice.
1942   std::string shared_class_expression;
1943   llvm::raw_string_ostream(shared_class_expression)
1944       << llvm::format(g_shared_cache_class_name_funcptr,
1945                       class_name_getter_function_name.AsCString(),
1946                       class_name_getter_function_name.AsCString());
1947 
1948   shared_class_expression += g_get_shared_cache_class_info_body;
1949 
1950   auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction(
1951       std::move(shared_class_expression), g_get_shared_cache_class_info_name,
1952       eLanguageTypeC, exe_ctx);
1953 
1954   if (!utility_fn_or_error) {
1955     LLDB_LOG_ERROR(
1956         log, utility_fn_or_error.takeError(),
1957         "Failed to get utility function for shared class info extractor: {0}");
1958     return nullptr;
1959   }
1960 
1961   // Make some types for our arguments.
1962   CompilerType clang_uint32_t_type =
1963       scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
1964   CompilerType clang_void_pointer_type =
1965       scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();
1966   CompilerType clang_uint64_t_pointer_type =
1967       scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 64)
1968           .GetPointerType();
1969 
1970   // Next make the function caller for our implementation utility function.
1971   ValueList arguments;
1972   Value value;
1973   value.SetValueType(Value::ValueType::Scalar);
1974   value.SetCompilerType(clang_void_pointer_type);
1975   arguments.PushValue(value);
1976   arguments.PushValue(value);
1977   arguments.PushValue(value);
1978 
1979   value.SetValueType(Value::ValueType::Scalar);
1980   value.SetCompilerType(clang_uint64_t_pointer_type);
1981   arguments.PushValue(value);
1982 
1983   value.SetValueType(Value::ValueType::Scalar);
1984   value.SetCompilerType(clang_uint32_t_type);
1985   arguments.PushValue(value);
1986   arguments.PushValue(value);
1987 
1988   std::unique_ptr<UtilityFunction> utility_fn = std::move(*utility_fn_or_error);
1989 
1990   Status error;
1991   utility_fn->MakeFunctionCaller(clang_uint32_t_type, arguments,
1992                                  exe_ctx.GetThreadSP(), error);
1993 
1994   if (error.Fail()) {
1995     LLDB_LOG(log,
1996              "Failed to make function caller for implementation lookup: {0}.",
1997              error.AsCString());
1998     return {};
1999   }
2000 
2001   return utility_fn;
2002 }
2003 
2004 UtilityFunction *
2005 AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::GetClassInfoUtilityFunction(
2006     ExecutionContext &exe_ctx) {
2007   if (!m_utility_function)
2008     m_utility_function = GetClassInfoUtilityFunctionImpl(exe_ctx);
2009   return m_utility_function.get();
2010 }
2011 
2012 AppleObjCRuntimeV2::DescriptorMapUpdateResult
2013 AppleObjCRuntimeV2::DynamicClassInfoExtractor::UpdateISAToDescriptorMap(
2014     RemoteNXMapTable &hash_table) {
2015   Process *process = m_runtime.GetProcess();
2016   if (process == nullptr)
2017     return DescriptorMapUpdateResult::Fail();
2018 
2019   uint32_t num_class_infos = 0;
2020 
2021   Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
2022 
2023   ExecutionContext exe_ctx;
2024 
2025   ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
2026 
2027   if (!thread_sp)
2028     return DescriptorMapUpdateResult::Fail();
2029 
2030   if (!thread_sp->SafeToCallFunctions())
2031     return DescriptorMapUpdateResult::Retry();
2032 
2033   thread_sp->CalculateExecutionContext(exe_ctx);
2034   TypeSystemClangSP scratch_ts_sp =
2035       ScratchTypeSystemClang::GetForTarget(process->GetTarget());
2036 
2037   if (!scratch_ts_sp)
2038     return DescriptorMapUpdateResult::Fail();
2039 
2040   Address function_address;
2041 
2042   const uint32_t addr_size = process->GetAddressByteSize();
2043 
2044   Status err;
2045 
2046   // Compute which helper we're going to use for this update.
2047   const DynamicClassInfoExtractor::Helper helper = ComputeHelper(exe_ctx);
2048 
2049   // Read the total number of classes from the hash table
2050   const uint32_t num_classes =
2051       helper == DynamicClassInfoExtractor::gdb_objc_realized_classes
2052           ? hash_table.GetCount()
2053           : m_runtime.m_realized_class_generation_count;
2054   if (num_classes == 0) {
2055     LLDB_LOGF(log, "No dynamic classes found.");
2056     return DescriptorMapUpdateResult::Success(0);
2057   }
2058 
2059   UtilityFunction *get_class_info_code =
2060       GetClassInfoUtilityFunction(exe_ctx, helper);
2061   if (!get_class_info_code) {
2062     // The callee will have already logged a useful error message.
2063     return DescriptorMapUpdateResult::Fail();
2064   }
2065 
2066   FunctionCaller *get_class_info_function =
2067       get_class_info_code->GetFunctionCaller();
2068 
2069   if (!get_class_info_function) {
2070     LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
2071     return DescriptorMapUpdateResult::Fail();
2072   }
2073 
2074   ValueList arguments = get_class_info_function->GetArgumentValues();
2075 
2076   DiagnosticManager diagnostics;
2077 
2078   const uint32_t class_info_byte_size = addr_size + 4;
2079   const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
2080   lldb::addr_t class_infos_addr = process->AllocateMemory(
2081       class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);
2082 
2083   if (class_infos_addr == LLDB_INVALID_ADDRESS) {
2084     LLDB_LOGF(log,
2085               "unable to allocate %" PRIu32
2086               " bytes in process for shared cache read",
2087               class_infos_byte_size);
2088     return DescriptorMapUpdateResult::Fail();
2089   }
2090 
2091   auto deallocate_class_infos = llvm::make_scope_exit([&] {
2092     // Deallocate the memory we allocated for the ClassInfo array
2093     if (class_infos_addr != LLDB_INVALID_ADDRESS)
2094       process->DeallocateMemory(class_infos_addr);
2095   });
2096 
2097   lldb::addr_t class_buffer_addr = LLDB_INVALID_ADDRESS;
2098   const uint32_t class_byte_size = addr_size;
2099   const uint32_t class_buffer_len = num_classes;
2100   const uint32_t class_buffer_byte_size = class_buffer_len * class_byte_size;
2101   if (helper == Helper::objc_getRealizedClassList_trylock) {
2102     class_buffer_addr = process->AllocateMemory(
2103         class_buffer_byte_size, ePermissionsReadable | ePermissionsWritable,
2104         err);
2105     if (class_buffer_addr == LLDB_INVALID_ADDRESS) {
2106       LLDB_LOGF(log,
2107                 "unable to allocate %" PRIu32
2108                 " bytes in process for shared cache read",
2109                 class_buffer_byte_size);
2110       return DescriptorMapUpdateResult::Fail();
2111     }
2112   }
2113 
2114   auto deallocate_class_buffer = llvm::make_scope_exit([&] {
2115     // Deallocate the memory we allocated for the Class array
2116     if (class_buffer_addr != LLDB_INVALID_ADDRESS)
2117       process->DeallocateMemory(class_buffer_addr);
2118   });
2119 
2120   std::lock_guard<std::mutex> guard(m_mutex);
2121 
2122   // Fill in our function argument values
2123   uint32_t index = 0;
2124   arguments.GetValueAtIndex(index++)->GetScalar() =
2125       hash_table.GetTableLoadAddress();
2126   arguments.GetValueAtIndex(index++)->GetScalar() = class_infos_addr;
2127   arguments.GetValueAtIndex(index++)->GetScalar() = class_infos_byte_size;
2128 
2129   if (class_buffer_addr != LLDB_INVALID_ADDRESS) {
2130     arguments.GetValueAtIndex(index++)->GetScalar() = class_buffer_addr;
2131     arguments.GetValueAtIndex(index++)->GetScalar() = class_buffer_byte_size;
2132   }
2133 
2134   // Only dump the runtime classes from the expression evaluation if the log is
2135   // verbose:
2136   Log *type_log = GetLog(LLDBLog::Types);
2137   bool dump_log = type_log && type_log->GetVerbose();
2138 
2139   arguments.GetValueAtIndex(index++)->GetScalar() = dump_log ? 1 : 0;
2140 
2141   bool success = false;
2142 
2143   diagnostics.Clear();
2144 
2145   // Write our function arguments into the process so we can run our function
2146   if (get_class_info_function->WriteFunctionArguments(
2147           exe_ctx, GetClassInfoArgs(helper), arguments, diagnostics)) {
2148     EvaluateExpressionOptions options;
2149     options.SetUnwindOnError(true);
2150     options.SetTryAllThreads(false);
2151     options.SetStopOthers(true);
2152     options.SetIgnoreBreakpoints(true);
2153     options.SetTimeout(process->GetUtilityExpressionTimeout());
2154     options.SetIsForUtilityExpr(true);
2155 
2156     CompilerType clang_uint32_t_type =
2157         scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
2158 
2159     Value return_value;
2160     return_value.SetValueType(Value::ValueType::Scalar);
2161     return_value.SetCompilerType(clang_uint32_t_type);
2162     return_value.GetScalar() = 0;
2163 
2164     diagnostics.Clear();
2165 
2166     // Run the function
2167     ExpressionResults results = get_class_info_function->ExecuteFunction(
2168         exe_ctx, &GetClassInfoArgs(helper), options, diagnostics, return_value);
2169 
2170     if (results == eExpressionCompleted) {
2171       // The result is the number of ClassInfo structures that were filled in
2172       num_class_infos = return_value.GetScalar().ULong();
2173       LLDB_LOG(log, "Discovered {0} Objective-C classes", num_class_infos);
2174       if (num_class_infos > 0) {
2175         // Read the ClassInfo structures
2176         DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0);
2177         if (process->ReadMemory(class_infos_addr, buffer.GetBytes(),
2178                                 buffer.GetByteSize(),
2179                                 err) == buffer.GetByteSize()) {
2180           DataExtractor class_infos_data(buffer.GetBytes(),
2181                                          buffer.GetByteSize(),
2182                                          process->GetByteOrder(), addr_size);
2183           m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos);
2184         }
2185       }
2186       success = true;
2187     } else {
2188       if (log) {
2189         LLDB_LOGF(log, "Error evaluating our find class name function.");
2190         diagnostics.Dump(log);
2191       }
2192     }
2193   } else {
2194     if (log) {
2195       LLDB_LOGF(log, "Error writing function arguments.");
2196       diagnostics.Dump(log);
2197     }
2198   }
2199 
2200   return DescriptorMapUpdateResult(success, false, num_class_infos);
2201 }
2202 
2203 uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data,
2204                                                  uint32_t num_class_infos) {
2205   // Parses an array of "num_class_infos" packed ClassInfo structures:
2206   //
2207   //    struct ClassInfo
2208   //    {
2209   //        Class isa;
2210   //        uint32_t hash;
2211   //    } __attribute__((__packed__));
2212 
2213   Log *log = GetLog(LLDBLog::Types);
2214   bool should_log = log && log->GetVerbose();
2215 
2216   uint32_t num_parsed = 0;
2217 
2218   // Iterate through all ClassInfo structures
2219   lldb::offset_t offset = 0;
2220   for (uint32_t i = 0; i < num_class_infos; ++i) {
2221     ObjCISA isa = data.GetAddress(&offset);
2222 
2223     if (isa == 0) {
2224       if (should_log)
2225         LLDB_LOGF(
2226             log, "AppleObjCRuntimeV2 found NULL isa, ignoring this class info");
2227       continue;
2228     }
2229     // Check if we already know about this ISA, if we do, the info will never
2230     // change, so we can just skip it.
2231     if (ISAIsCached(isa)) {
2232       if (should_log)
2233         LLDB_LOGF(log,
2234                   "AppleObjCRuntimeV2 found cached isa=0x%" PRIx64
2235                   ", ignoring this class info",
2236                   isa);
2237       offset += 4;
2238     } else {
2239       // Read the 32 bit hash for the class name
2240       const uint32_t name_hash = data.GetU32(&offset);
2241       ClassDescriptorSP descriptor_sp(
2242           new ClassDescriptorV2(*this, isa, nullptr));
2243 
2244       // The code in g_get_shared_cache_class_info_body sets the value of the
2245       // hash to 0 to signal a demangled symbol. We use class_getName() in that
2246       // code to find the class name, but this returns a demangled name for
2247       // Swift symbols. For those symbols, recompute the hash here by reading
2248       // their name from the runtime.
2249       if (name_hash)
2250         AddClass(isa, descriptor_sp, name_hash);
2251       else
2252         AddClass(isa, descriptor_sp,
2253                  descriptor_sp->GetClassName().AsCString(nullptr));
2254       num_parsed++;
2255       if (should_log)
2256         LLDB_LOGF(log,
2257                   "AppleObjCRuntimeV2 added isa=0x%" PRIx64
2258                   ", hash=0x%8.8x, name=%s",
2259                   isa, name_hash,
2260                   descriptor_sp->GetClassName().AsCString("<unknown>"));
2261     }
2262   }
2263   if (should_log)
2264     LLDB_LOGF(log, "AppleObjCRuntimeV2 parsed %" PRIu32 " class infos",
2265               num_parsed);
2266   return num_parsed;
2267 }
2268 
2269 bool AppleObjCRuntimeV2::HasSymbol(ConstString Name) {
2270   if (!m_objc_module_sp)
2271     return false;
2272   if (const Symbol *symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType(
2273           Name, lldb::eSymbolTypeCode)) {
2274     if (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())
2275       return true;
2276   }
2277   return false;
2278 }
2279 
2280 AppleObjCRuntimeV2::DescriptorMapUpdateResult
2281 AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::UpdateISAToDescriptorMap() {
2282   Process *process = m_runtime.GetProcess();
2283   if (process == nullptr)
2284     return DescriptorMapUpdateResult::Fail();
2285 
2286   Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
2287 
2288   ExecutionContext exe_ctx;
2289 
2290   ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
2291 
2292   if (!thread_sp)
2293     return DescriptorMapUpdateResult::Fail();
2294 
2295   if (!thread_sp->SafeToCallFunctions())
2296     return DescriptorMapUpdateResult::Retry();
2297 
2298   thread_sp->CalculateExecutionContext(exe_ctx);
2299   TypeSystemClangSP scratch_ts_sp =
2300       ScratchTypeSystemClang::GetForTarget(process->GetTarget());
2301 
2302   if (!scratch_ts_sp)
2303     return DescriptorMapUpdateResult::Fail();
2304 
2305   Address function_address;
2306 
2307   const uint32_t addr_size = process->GetAddressByteSize();
2308 
2309   Status err;
2310 
2311   uint32_t num_class_infos = 0;
2312 
2313   const lldb::addr_t objc_opt_ptr = m_runtime.GetSharedCacheReadOnlyAddress();
2314   const lldb::addr_t shared_cache_base_addr =
2315       m_runtime.GetSharedCacheBaseAddress();
2316 
2317   if (objc_opt_ptr == LLDB_INVALID_ADDRESS ||
2318       shared_cache_base_addr == LLDB_INVALID_ADDRESS)
2319     return DescriptorMapUpdateResult::Fail();
2320 
2321   // The number of entries to pre-allocate room for.
2322   // Each entry is (addrsize + 4) bytes
2323   // FIXME: It is not sustainable to continue incrementing this value every time
2324   // the shared cache grows. This is because it requires allocating memory in
2325   // the inferior process and some inferior processes have small memory limits.
2326   const uint32_t max_num_classes = 212992;
2327 
2328   UtilityFunction *get_class_info_code = GetClassInfoUtilityFunction(exe_ctx);
2329   if (!get_class_info_code) {
2330     // The callee will have already logged a useful error message.
2331     return DescriptorMapUpdateResult::Fail();
2332   }
2333 
2334   FunctionCaller *get_shared_cache_class_info_function =
2335       get_class_info_code->GetFunctionCaller();
2336 
2337   if (!get_shared_cache_class_info_function) {
2338     LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
2339     return DescriptorMapUpdateResult::Fail();
2340   }
2341 
2342   ValueList arguments =
2343       get_shared_cache_class_info_function->GetArgumentValues();
2344 
2345   DiagnosticManager diagnostics;
2346 
2347   const uint32_t class_info_byte_size = addr_size + 4;
2348   const uint32_t class_infos_byte_size = max_num_classes * class_info_byte_size;
2349   lldb::addr_t class_infos_addr = process->AllocateMemory(
2350       class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);
2351   const uint32_t relative_selector_offset_addr_size = 64;
2352   lldb::addr_t relative_selector_offset_addr =
2353       process->AllocateMemory(relative_selector_offset_addr_size,
2354                               ePermissionsReadable | ePermissionsWritable, err);
2355 
2356   if (class_infos_addr == LLDB_INVALID_ADDRESS) {
2357     LLDB_LOGF(log,
2358               "unable to allocate %" PRIu32
2359               " bytes in process for shared cache read",
2360               class_infos_byte_size);
2361     return DescriptorMapUpdateResult::Fail();
2362   }
2363 
2364   std::lock_guard<std::mutex> guard(m_mutex);
2365 
2366   // Fill in our function argument values
2367   arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
2368   arguments.GetValueAtIndex(1)->GetScalar() = shared_cache_base_addr;
2369   arguments.GetValueAtIndex(2)->GetScalar() = class_infos_addr;
2370   arguments.GetValueAtIndex(3)->GetScalar() = relative_selector_offset_addr;
2371   arguments.GetValueAtIndex(4)->GetScalar() = class_infos_byte_size;
2372   // Only dump the runtime classes from the expression evaluation if the log is
2373   // verbose:
2374   Log *type_log = GetLog(LLDBLog::Types);
2375   bool dump_log = type_log && type_log->GetVerbose();
2376 
2377   arguments.GetValueAtIndex(5)->GetScalar() = dump_log ? 1 : 0;
2378 
2379   bool success = false;
2380 
2381   diagnostics.Clear();
2382 
2383   // Write our function arguments into the process so we can run our function
2384   if (get_shared_cache_class_info_function->WriteFunctionArguments(
2385           exe_ctx, m_args, arguments, diagnostics)) {
2386     EvaluateExpressionOptions options;
2387     options.SetUnwindOnError(true);
2388     options.SetTryAllThreads(false);
2389     options.SetStopOthers(true);
2390     options.SetIgnoreBreakpoints(true);
2391     options.SetTimeout(process->GetUtilityExpressionTimeout());
2392     options.SetIsForUtilityExpr(true);
2393 
2394     CompilerType clang_uint32_t_type =
2395         scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
2396 
2397     Value return_value;
2398     return_value.SetValueType(Value::ValueType::Scalar);
2399     return_value.SetCompilerType(clang_uint32_t_type);
2400     return_value.GetScalar() = 0;
2401 
2402     diagnostics.Clear();
2403 
2404     // Run the function
2405     ExpressionResults results =
2406         get_shared_cache_class_info_function->ExecuteFunction(
2407             exe_ctx, &m_args, options, diagnostics, return_value);
2408 
2409     if (results == eExpressionCompleted) {
2410       // The result is the number of ClassInfo structures that were filled in
2411       num_class_infos = return_value.GetScalar().ULong();
2412       LLDB_LOG(log, "Discovered {0} Objective-C classes in the shared cache",
2413                num_class_infos);
2414       // Assert if there were more classes than we pre-allocated
2415       // room for.
2416       assert(num_class_infos <= max_num_classes);
2417       if (num_class_infos > 0) {
2418         if (num_class_infos > max_num_classes) {
2419           num_class_infos = max_num_classes;
2420 
2421           success = false;
2422         } else {
2423           success = true;
2424         }
2425 
2426         // Read the relative selector offset.
2427         DataBufferHeap relative_selector_offset_buffer(64, 0);
2428         if (process->ReadMemory(relative_selector_offset_addr,
2429                                 relative_selector_offset_buffer.GetBytes(),
2430                                 relative_selector_offset_buffer.GetByteSize(),
2431                                 err) ==
2432             relative_selector_offset_buffer.GetByteSize()) {
2433           DataExtractor relative_selector_offset_data(
2434               relative_selector_offset_buffer.GetBytes(),
2435               relative_selector_offset_buffer.GetByteSize(),
2436               process->GetByteOrder(), addr_size);
2437           lldb::offset_t offset = 0;
2438           uint64_t relative_selector_offset =
2439               relative_selector_offset_data.GetU64(&offset);
2440           if (relative_selector_offset > 0) {
2441             // The offset is relative to the objc_opt struct.
2442             m_runtime.SetRelativeSelectorBaseAddr(objc_opt_ptr +
2443                                                   relative_selector_offset);
2444           }
2445         }
2446 
2447         // Read the ClassInfo structures
2448         DataBufferHeap class_infos_buffer(
2449             num_class_infos * class_info_byte_size, 0);
2450         if (process->ReadMemory(class_infos_addr, class_infos_buffer.GetBytes(),
2451                                 class_infos_buffer.GetByteSize(),
2452                                 err) == class_infos_buffer.GetByteSize()) {
2453           DataExtractor class_infos_data(class_infos_buffer.GetBytes(),
2454                                          class_infos_buffer.GetByteSize(),
2455                                          process->GetByteOrder(), addr_size);
2456 
2457           m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos);
2458         }
2459       } else {
2460         success = true;
2461       }
2462     } else {
2463       if (log) {
2464         LLDB_LOGF(log, "Error evaluating our find class name function.");
2465         diagnostics.Dump(log);
2466       }
2467     }
2468   } else {
2469     if (log) {
2470       LLDB_LOGF(log, "Error writing function arguments.");
2471       diagnostics.Dump(log);
2472     }
2473   }
2474 
2475   // Deallocate the memory we allocated for the ClassInfo array
2476   process->DeallocateMemory(class_infos_addr);
2477 
2478   return DescriptorMapUpdateResult(success, false, num_class_infos);
2479 }
2480 
2481 lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() {
2482   Process *process = GetProcess();
2483 
2484   if (process) {
2485     ModuleSP objc_module_sp(GetObjCModule());
2486 
2487     if (objc_module_sp) {
2488       ObjectFile *objc_object = objc_module_sp->GetObjectFile();
2489 
2490       if (objc_object) {
2491         SectionList *section_list = objc_module_sp->GetSectionList();
2492 
2493         if (section_list) {
2494           SectionSP text_segment_sp(
2495               section_list->FindSectionByName(ConstString("__TEXT")));
2496 
2497           if (text_segment_sp) {
2498             SectionSP objc_opt_section_sp(
2499                 text_segment_sp->GetChildren().FindSectionByName(
2500                     ConstString("__objc_opt_ro")));
2501 
2502             if (objc_opt_section_sp) {
2503               return objc_opt_section_sp->GetLoadBaseAddress(
2504                   &process->GetTarget());
2505             }
2506           }
2507         }
2508       }
2509     }
2510   }
2511   return LLDB_INVALID_ADDRESS;
2512 }
2513 
2514 lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheBaseAddress() {
2515   StructuredData::ObjectSP info = m_process->GetSharedCacheInfo();
2516   if (!info)
2517     return LLDB_INVALID_ADDRESS;
2518 
2519   StructuredData::Dictionary *info_dict = info->GetAsDictionary();
2520   if (!info_dict)
2521     return LLDB_INVALID_ADDRESS;
2522 
2523   StructuredData::ObjectSP value =
2524       info_dict->GetValueForKey("shared_cache_base_address");
2525   if (!value)
2526     return LLDB_INVALID_ADDRESS;
2527 
2528   return value->GetUnsignedIntegerValue(LLDB_INVALID_ADDRESS);
2529 }
2530 
2531 void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
2532   LLDB_SCOPED_TIMER();
2533 
2534   Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
2535 
2536   // Else we need to check with our process to see when the map was updated.
2537   Process *process = GetProcess();
2538 
2539   if (process) {
2540     RemoteNXMapTable hash_table;
2541 
2542     // Update the process stop ID that indicates the last time we updated the
2543     // map, whether it was successful or not.
2544     m_isa_to_descriptor_stop_id = process->GetStopID();
2545 
2546     // Ask the runtime is the realized class generation count changed. Unlike
2547     // the hash table, this accounts for lazily named classes.
2548     const bool class_count_changed = RealizedClassGenerationCountChanged();
2549 
2550     if (!m_hash_signature.NeedsUpdate(process, this, hash_table) &&
2551         !class_count_changed)
2552       return;
2553 
2554     m_hash_signature.UpdateSignature(hash_table);
2555 
2556     // Grab the dynamically loaded Objective-C classes from memory.
2557     DescriptorMapUpdateResult dynamic_update_result =
2558         m_dynamic_class_info_extractor.UpdateISAToDescriptorMap(hash_table);
2559 
2560     // Now get the objc classes that are baked into the Objective-C runtime in
2561     // the shared cache, but only once per process as this data never changes
2562     if (!m_loaded_objc_opt) {
2563       // it is legitimately possible for the shared cache to be empty - in that
2564       // case, the dynamic hash table will contain all the class information we
2565       // need; the situation we're trying to detect is one where we aren't
2566       // seeing class information from the runtime - in order to detect that
2567       // vs. just the shared cache being empty or sparsely populated, we set an
2568       // arbitrary (very low) threshold for the number of classes that we want
2569       // to see in a "good" scenario - anything below that is suspicious
2570       // (Foundation alone has thousands of classes)
2571       const uint32_t num_classes_to_warn_at = 500;
2572 
2573       DescriptorMapUpdateResult shared_cache_update_result =
2574           m_shared_cache_class_info_extractor.UpdateISAToDescriptorMap();
2575 
2576       LLDB_LOGF(log,
2577                 "attempted to read objc class data - results: "
2578                 "[dynamic_update]: ran: %s, retry: %s, count: %" PRIu32
2579                 " [shared_cache_update]: ran: %s, retry: %s, count: %" PRIu32,
2580                 dynamic_update_result.m_update_ran ? "yes" : "no",
2581                 dynamic_update_result.m_retry_update ? "yes" : "no",
2582                 dynamic_update_result.m_num_found,
2583                 shared_cache_update_result.m_update_ran ? "yes" : "no",
2584                 shared_cache_update_result.m_retry_update ? "yes" : "no",
2585                 shared_cache_update_result.m_num_found);
2586 
2587       // warn if:
2588       // - we could not run either expression
2589       // - we found fewer than num_classes_to_warn_at classes total
2590       if (dynamic_update_result.m_retry_update ||
2591           shared_cache_update_result.m_retry_update)
2592         WarnIfNoClassesCached(SharedCacheWarningReason::eExpressionUnableToRun);
2593       else if ((!shared_cache_update_result.m_update_ran) ||
2594                (!dynamic_update_result.m_update_ran))
2595         WarnIfNoClassesCached(
2596             SharedCacheWarningReason::eExpressionExecutionFailure);
2597       else if (dynamic_update_result.m_num_found +
2598                    shared_cache_update_result.m_num_found <
2599                num_classes_to_warn_at)
2600         WarnIfNoClassesCached(SharedCacheWarningReason::eNotEnoughClassesRead);
2601       else
2602         m_loaded_objc_opt = true;
2603     }
2604   } else {
2605     m_isa_to_descriptor_stop_id = UINT32_MAX;
2606   }
2607 }
2608 
2609 bool AppleObjCRuntimeV2::RealizedClassGenerationCountChanged() {
2610   Process *process = GetProcess();
2611   if (!process)
2612     return false;
2613 
2614   Status error;
2615   uint64_t objc_debug_realized_class_generation_count =
2616       ExtractRuntimeGlobalSymbol(
2617           process, ConstString("objc_debug_realized_class_generation_count"),
2618           GetObjCModule(), error);
2619   if (error.Fail())
2620     return false;
2621 
2622   if (m_realized_class_generation_count ==
2623       objc_debug_realized_class_generation_count)
2624     return false;
2625 
2626   Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
2627   LLDB_LOG(log,
2628            "objc_debug_realized_class_generation_count changed from {0} to {1}",
2629            m_realized_class_generation_count,
2630            objc_debug_realized_class_generation_count);
2631 
2632   m_realized_class_generation_count =
2633       objc_debug_realized_class_generation_count;
2634 
2635   return true;
2636 }
2637 
2638 static bool DoesProcessHaveSharedCache(Process &process) {
2639   PlatformSP platform_sp = process.GetTarget().GetPlatform();
2640   if (!platform_sp)
2641     return true; // this should not happen
2642 
2643   llvm::StringRef platform_plugin_name_sr = platform_sp->GetPluginName();
2644   if (platform_plugin_name_sr.ends_with("-simulator"))
2645     return false;
2646 
2647   return true;
2648 }
2649 
2650 void AppleObjCRuntimeV2::WarnIfNoClassesCached(
2651     SharedCacheWarningReason reason) {
2652   if (GetProcess() && !DoesProcessHaveSharedCache(*GetProcess())) {
2653     // Simulators do not have the objc_opt_ro class table so don't actually
2654     // complain to the user
2655     return;
2656   }
2657 
2658   Debugger &debugger(GetProcess()->GetTarget().GetDebugger());
2659   switch (reason) {
2660   case SharedCacheWarningReason::eNotEnoughClassesRead:
2661     Debugger::ReportWarning("could not find Objective-C class data in "
2662                             "the process. This may reduce the quality of type "
2663                             "information available.\n",
2664                             debugger.GetID(), &m_no_classes_cached_warning);
2665     break;
2666   case SharedCacheWarningReason::eExpressionExecutionFailure:
2667     Debugger::ReportWarning(
2668         "could not execute support code to read "
2669         "Objective-C class data in the process. This may "
2670         "reduce the quality of type information available.\n",
2671         debugger.GetID(), &m_no_classes_cached_warning);
2672     break;
2673   case SharedCacheWarningReason::eExpressionUnableToRun:
2674     Debugger::ReportWarning(
2675         "could not execute support code to read Objective-C class data because "
2676         "it's not yet safe to do so, and will be retried later.\n",
2677         debugger.GetID(), nullptr);
2678     break;
2679   }
2680 }
2681 
2682 void AppleObjCRuntimeV2::WarnIfNoExpandedSharedCache() {
2683   if (!m_objc_module_sp)
2684     return;
2685 
2686   ObjectFile *object_file = m_objc_module_sp->GetObjectFile();
2687   if (!object_file)
2688     return;
2689 
2690   if (!object_file->IsInMemory())
2691     return;
2692 
2693   Target &target = GetProcess()->GetTarget();
2694   Debugger &debugger = target.GetDebugger();
2695 
2696   std::string buffer;
2697   llvm::raw_string_ostream os(buffer);
2698 
2699   os << "libobjc.A.dylib is being read from process memory. This "
2700         "indicates that LLDB could not ";
2701   if (PlatformSP platform_sp = target.GetPlatform()) {
2702     if (platform_sp->IsHost()) {
2703       os << "read from the host's in-memory shared cache";
2704     } else {
2705       os << "find the on-disk shared cache for this device";
2706     }
2707   } else {
2708     os << "read from the shared cache";
2709   }
2710   os << ". This will likely reduce debugging performance.\n";
2711 
2712   Debugger::ReportWarning(os.str(), debugger.GetID(),
2713                           &m_no_expanded_cache_warning);
2714 }
2715 
2716 DeclVendor *AppleObjCRuntimeV2::GetDeclVendor() {
2717   if (!m_decl_vendor_up)
2718     m_decl_vendor_up = std::make_unique<AppleObjCDeclVendor>(*this);
2719 
2720   return m_decl_vendor_up.get();
2721 }
2722 
2723 lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(ConstString name) {
2724   lldb::addr_t ret = LLDB_INVALID_ADDRESS;
2725 
2726   const char *name_cstr = name.AsCString();
2727 
2728   if (name_cstr) {
2729     llvm::StringRef name_strref(name_cstr);
2730 
2731     llvm::StringRef ivar_prefix("OBJC_IVAR_$_");
2732     llvm::StringRef class_prefix("OBJC_CLASS_$_");
2733 
2734     if (name_strref.starts_with(ivar_prefix)) {
2735       llvm::StringRef ivar_skipped_prefix =
2736           name_strref.substr(ivar_prefix.size());
2737       std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar =
2738           ivar_skipped_prefix.split('.');
2739 
2740       if (!class_and_ivar.first.empty() && !class_and_ivar.second.empty()) {
2741         const ConstString class_name_cs(class_and_ivar.first);
2742         ClassDescriptorSP descriptor =
2743             ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs);
2744 
2745         if (descriptor) {
2746           const ConstString ivar_name_cs(class_and_ivar.second);
2747           const char *ivar_name_cstr = ivar_name_cs.AsCString();
2748 
2749           auto ivar_func = [&ret,
2750                             ivar_name_cstr](const char *name, const char *type,
2751                                             lldb::addr_t offset_addr,
2752                                             uint64_t size) -> lldb::addr_t {
2753             if (!strcmp(name, ivar_name_cstr)) {
2754               ret = offset_addr;
2755               return true;
2756             }
2757             return false;
2758           };
2759 
2760           descriptor->Describe(
2761               std::function<void(ObjCISA)>(nullptr),
2762               std::function<bool(const char *, const char *)>(nullptr),
2763               std::function<bool(const char *, const char *)>(nullptr),
2764               ivar_func);
2765         }
2766       }
2767     } else if (name_strref.starts_with(class_prefix)) {
2768       llvm::StringRef class_skipped_prefix =
2769           name_strref.substr(class_prefix.size());
2770       const ConstString class_name_cs(class_skipped_prefix);
2771       ClassDescriptorSP descriptor =
2772           GetClassDescriptorFromClassName(class_name_cs);
2773 
2774       if (descriptor)
2775         ret = descriptor->GetISA();
2776     }
2777   }
2778 
2779   return ret;
2780 }
2781 
2782 AppleObjCRuntimeV2::NonPointerISACache *
2783 AppleObjCRuntimeV2::NonPointerISACache::CreateInstance(
2784     AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp) {
2785   Process *process(runtime.GetProcess());
2786 
2787   Status error;
2788 
2789   Log *log = GetLog(LLDBLog::Types);
2790 
2791   auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(
2792       process, ConstString("objc_debug_isa_magic_mask"), objc_module_sp, error);
2793   if (error.Fail())
2794     return nullptr;
2795 
2796   auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(
2797       process, ConstString("objc_debug_isa_magic_value"), objc_module_sp,
2798       error);
2799   if (error.Fail())
2800     return nullptr;
2801 
2802   auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol(
2803       process, ConstString("objc_debug_isa_class_mask"), objc_module_sp, error);
2804   if (error.Fail())
2805     return nullptr;
2806 
2807   if (log)
2808     log->PutCString("AOCRT::NPI: Found all the non-indexed ISA masks");
2809 
2810   bool foundError = false;
2811   auto objc_debug_indexed_isa_magic_mask = ExtractRuntimeGlobalSymbol(
2812       process, ConstString("objc_debug_indexed_isa_magic_mask"), objc_module_sp,
2813       error);
2814   foundError |= error.Fail();
2815 
2816   auto objc_debug_indexed_isa_magic_value = ExtractRuntimeGlobalSymbol(
2817       process, ConstString("objc_debug_indexed_isa_magic_value"),
2818       objc_module_sp, error);
2819   foundError |= error.Fail();
2820 
2821   auto objc_debug_indexed_isa_index_mask = ExtractRuntimeGlobalSymbol(
2822       process, ConstString("objc_debug_indexed_isa_index_mask"), objc_module_sp,
2823       error);
2824   foundError |= error.Fail();
2825 
2826   auto objc_debug_indexed_isa_index_shift = ExtractRuntimeGlobalSymbol(
2827       process, ConstString("objc_debug_indexed_isa_index_shift"),
2828       objc_module_sp, error);
2829   foundError |= error.Fail();
2830 
2831   auto objc_indexed_classes =
2832       ExtractRuntimeGlobalSymbol(process, ConstString("objc_indexed_classes"),
2833                                  objc_module_sp, error, false);
2834   foundError |= error.Fail();
2835 
2836   if (log)
2837     log->PutCString("AOCRT::NPI: Found all the indexed ISA masks");
2838 
2839   // we might want to have some rules to outlaw these other values (e.g if the
2840   // mask is zero but the value is non-zero, ...)
2841 
2842   return new NonPointerISACache(
2843       runtime, objc_module_sp, objc_debug_isa_class_mask,
2844       objc_debug_isa_magic_mask, objc_debug_isa_magic_value,
2845       objc_debug_indexed_isa_magic_mask, objc_debug_indexed_isa_magic_value,
2846       objc_debug_indexed_isa_index_mask, objc_debug_indexed_isa_index_shift,
2847       foundError ? 0 : objc_indexed_classes);
2848 }
2849 
2850 AppleObjCRuntimeV2::TaggedPointerVendorV2 *
2851 AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance(
2852     AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp) {
2853   Process *process(runtime.GetProcess());
2854 
2855   Status error;
2856 
2857   auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol(
2858       process, ConstString("objc_debug_taggedpointer_mask"), objc_module_sp,
2859       error);
2860   if (error.Fail())
2861     return new TaggedPointerVendorLegacy(runtime);
2862 
2863   auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol(
2864       process, ConstString("objc_debug_taggedpointer_slot_shift"),
2865       objc_module_sp, error, true, 4);
2866   if (error.Fail())
2867     return new TaggedPointerVendorLegacy(runtime);
2868 
2869   auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol(
2870       process, ConstString("objc_debug_taggedpointer_slot_mask"),
2871       objc_module_sp, error, true, 4);
2872   if (error.Fail())
2873     return new TaggedPointerVendorLegacy(runtime);
2874 
2875   auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol(
2876       process, ConstString("objc_debug_taggedpointer_payload_lshift"),
2877       objc_module_sp, error, true, 4);
2878   if (error.Fail())
2879     return new TaggedPointerVendorLegacy(runtime);
2880 
2881   auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol(
2882       process, ConstString("objc_debug_taggedpointer_payload_rshift"),
2883       objc_module_sp, error, true, 4);
2884   if (error.Fail())
2885     return new TaggedPointerVendorLegacy(runtime);
2886 
2887   auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol(
2888       process, ConstString("objc_debug_taggedpointer_classes"), objc_module_sp,
2889       error, false);
2890   if (error.Fail())
2891     return new TaggedPointerVendorLegacy(runtime);
2892 
2893   // try to detect the "extended tagged pointer" variables - if any are
2894   // missing, use the non-extended vendor
2895   do {
2896     auto objc_debug_taggedpointer_ext_mask = ExtractRuntimeGlobalSymbol(
2897         process, ConstString("objc_debug_taggedpointer_ext_mask"),
2898         objc_module_sp, error);
2899     if (error.Fail())
2900       break;
2901 
2902     auto objc_debug_taggedpointer_ext_slot_shift = ExtractRuntimeGlobalSymbol(
2903         process, ConstString("objc_debug_taggedpointer_ext_slot_shift"),
2904         objc_module_sp, error, true, 4);
2905     if (error.Fail())
2906       break;
2907 
2908     auto objc_debug_taggedpointer_ext_slot_mask = ExtractRuntimeGlobalSymbol(
2909         process, ConstString("objc_debug_taggedpointer_ext_slot_mask"),
2910         objc_module_sp, error, true, 4);
2911     if (error.Fail())
2912       break;
2913 
2914     auto objc_debug_taggedpointer_ext_classes = ExtractRuntimeGlobalSymbol(
2915         process, ConstString("objc_debug_taggedpointer_ext_classes"),
2916         objc_module_sp, error, false);
2917     if (error.Fail())
2918       break;
2919 
2920     auto objc_debug_taggedpointer_ext_payload_lshift =
2921         ExtractRuntimeGlobalSymbol(
2922             process, ConstString("objc_debug_taggedpointer_ext_payload_lshift"),
2923             objc_module_sp, error, true, 4);
2924     if (error.Fail())
2925       break;
2926 
2927     auto objc_debug_taggedpointer_ext_payload_rshift =
2928         ExtractRuntimeGlobalSymbol(
2929             process, ConstString("objc_debug_taggedpointer_ext_payload_rshift"),
2930             objc_module_sp, error, true, 4);
2931     if (error.Fail())
2932       break;
2933 
2934     return new TaggedPointerVendorExtended(
2935         runtime, objc_debug_taggedpointer_mask,
2936         objc_debug_taggedpointer_ext_mask, objc_debug_taggedpointer_slot_shift,
2937         objc_debug_taggedpointer_ext_slot_shift,
2938         objc_debug_taggedpointer_slot_mask,
2939         objc_debug_taggedpointer_ext_slot_mask,
2940         objc_debug_taggedpointer_payload_lshift,
2941         objc_debug_taggedpointer_payload_rshift,
2942         objc_debug_taggedpointer_ext_payload_lshift,
2943         objc_debug_taggedpointer_ext_payload_rshift,
2944         objc_debug_taggedpointer_classes, objc_debug_taggedpointer_ext_classes);
2945   } while (false);
2946 
2947   // we might want to have some rules to outlaw these values (e.g if the
2948   // table's address is zero)
2949 
2950   return new TaggedPointerVendorRuntimeAssisted(
2951       runtime, objc_debug_taggedpointer_mask,
2952       objc_debug_taggedpointer_slot_shift, objc_debug_taggedpointer_slot_mask,
2953       objc_debug_taggedpointer_payload_lshift,
2954       objc_debug_taggedpointer_payload_rshift,
2955       objc_debug_taggedpointer_classes);
2956 }
2957 
2958 bool AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer(
2959     lldb::addr_t ptr) {
2960   return (ptr & 1);
2961 }
2962 
2963 ObjCLanguageRuntime::ClassDescriptorSP
2964 AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor(
2965     lldb::addr_t ptr) {
2966   if (!IsPossibleTaggedPointer(ptr))
2967     return ObjCLanguageRuntime::ClassDescriptorSP();
2968 
2969   uint32_t foundation_version = m_runtime.GetFoundationVersion();
2970 
2971   if (foundation_version == LLDB_INVALID_MODULE_VERSION)
2972     return ObjCLanguageRuntime::ClassDescriptorSP();
2973 
2974   uint64_t class_bits = (ptr & 0xE) >> 1;
2975   ConstString name;
2976 
2977   static ConstString g_NSAtom("NSAtom");
2978   static ConstString g_NSNumber("NSNumber");
2979   static ConstString g_NSDateTS("NSDateTS");
2980   static ConstString g_NSManagedObject("NSManagedObject");
2981   static ConstString g_NSDate("NSDate");
2982 
2983   if (foundation_version >= 900) {
2984     switch (class_bits) {
2985     case 0:
2986       name = g_NSAtom;
2987       break;
2988     case 3:
2989       name = g_NSNumber;
2990       break;
2991     case 4:
2992       name = g_NSDateTS;
2993       break;
2994     case 5:
2995       name = g_NSManagedObject;
2996       break;
2997     case 6:
2998       name = g_NSDate;
2999       break;
3000     default:
3001       return ObjCLanguageRuntime::ClassDescriptorSP();
3002     }
3003   } else {
3004     switch (class_bits) {
3005     case 1:
3006       name = g_NSNumber;
3007       break;
3008     case 5:
3009       name = g_NSManagedObject;
3010       break;
3011     case 6:
3012       name = g_NSDate;
3013       break;
3014     case 7:
3015       name = g_NSDateTS;
3016       break;
3017     default:
3018       return ObjCLanguageRuntime::ClassDescriptorSP();
3019     }
3020   }
3021 
3022   lldb::addr_t unobfuscated = ptr ^ m_runtime.GetTaggedPointerObfuscator();
3023   return ClassDescriptorSP(new ClassDescriptorV2Tagged(name, unobfuscated));
3024 }
3025 
3026 AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::
3027     TaggedPointerVendorRuntimeAssisted(
3028         AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,
3029         uint32_t objc_debug_taggedpointer_slot_shift,
3030         uint32_t objc_debug_taggedpointer_slot_mask,
3031         uint32_t objc_debug_taggedpointer_payload_lshift,
3032         uint32_t objc_debug_taggedpointer_payload_rshift,
3033         lldb::addr_t objc_debug_taggedpointer_classes)
3034     : TaggedPointerVendorV2(runtime), m_cache(),
3035       m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask),
3036       m_objc_debug_taggedpointer_slot_shift(
3037           objc_debug_taggedpointer_slot_shift),
3038       m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask),
3039       m_objc_debug_taggedpointer_payload_lshift(
3040           objc_debug_taggedpointer_payload_lshift),
3041       m_objc_debug_taggedpointer_payload_rshift(
3042           objc_debug_taggedpointer_payload_rshift),
3043       m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes) {}
3044 
3045 bool AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::
3046     IsPossibleTaggedPointer(lldb::addr_t ptr) {
3047   return (ptr & m_objc_debug_taggedpointer_mask) != 0;
3048 }
3049 
3050 ObjCLanguageRuntime::ClassDescriptorSP
3051 AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(
3052     lldb::addr_t ptr) {
3053   ClassDescriptorSP actual_class_descriptor_sp;
3054   uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
3055 
3056   if (!IsPossibleTaggedPointer(unobfuscated))
3057     return ObjCLanguageRuntime::ClassDescriptorSP();
3058 
3059   uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) &
3060                    m_objc_debug_taggedpointer_slot_mask;
3061 
3062   CacheIterator iterator = m_cache.find(slot), end = m_cache.end();
3063   if (iterator != end) {
3064     actual_class_descriptor_sp = iterator->second;
3065   } else {
3066     Process *process(m_runtime.GetProcess());
3067     uintptr_t slot_ptr = slot * process->GetAddressByteSize() +
3068                          m_objc_debug_taggedpointer_classes;
3069     Status error;
3070     uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
3071     if (error.Fail() || slot_data == 0 ||
3072         slot_data == uintptr_t(LLDB_INVALID_ADDRESS))
3073       return nullptr;
3074     actual_class_descriptor_sp =
3075         m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data);
3076     if (!actual_class_descriptor_sp) {
3077       if (ABISP abi_sp = process->GetABI()) {
3078         ObjCISA fixed_isa = abi_sp->FixCodeAddress((ObjCISA)slot_data);
3079         actual_class_descriptor_sp =
3080             m_runtime.GetClassDescriptorFromISA(fixed_isa);
3081       }
3082     }
3083     if (!actual_class_descriptor_sp)
3084       return ObjCLanguageRuntime::ClassDescriptorSP();
3085     m_cache[slot] = actual_class_descriptor_sp;
3086   }
3087 
3088   uint64_t data_payload =
3089       ((unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >>
3090        m_objc_debug_taggedpointer_payload_rshift);
3091   int64_t data_payload_signed =
3092       ((int64_t)(unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >>
3093        m_objc_debug_taggedpointer_payload_rshift);
3094   return ClassDescriptorSP(new ClassDescriptorV2Tagged(
3095       actual_class_descriptor_sp, data_payload, data_payload_signed));
3096 }
3097 
3098 AppleObjCRuntimeV2::TaggedPointerVendorExtended::TaggedPointerVendorExtended(
3099     AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,
3100     uint64_t objc_debug_taggedpointer_ext_mask,
3101     uint32_t objc_debug_taggedpointer_slot_shift,
3102     uint32_t objc_debug_taggedpointer_ext_slot_shift,
3103     uint32_t objc_debug_taggedpointer_slot_mask,
3104     uint32_t objc_debug_taggedpointer_ext_slot_mask,
3105     uint32_t objc_debug_taggedpointer_payload_lshift,
3106     uint32_t objc_debug_taggedpointer_payload_rshift,
3107     uint32_t objc_debug_taggedpointer_ext_payload_lshift,
3108     uint32_t objc_debug_taggedpointer_ext_payload_rshift,
3109     lldb::addr_t objc_debug_taggedpointer_classes,
3110     lldb::addr_t objc_debug_taggedpointer_ext_classes)
3111     : TaggedPointerVendorRuntimeAssisted(
3112           runtime, objc_debug_taggedpointer_mask,
3113           objc_debug_taggedpointer_slot_shift,
3114           objc_debug_taggedpointer_slot_mask,
3115           objc_debug_taggedpointer_payload_lshift,
3116           objc_debug_taggedpointer_payload_rshift,
3117           objc_debug_taggedpointer_classes),
3118       m_ext_cache(),
3119       m_objc_debug_taggedpointer_ext_mask(objc_debug_taggedpointer_ext_mask),
3120       m_objc_debug_taggedpointer_ext_slot_shift(
3121           objc_debug_taggedpointer_ext_slot_shift),
3122       m_objc_debug_taggedpointer_ext_slot_mask(
3123           objc_debug_taggedpointer_ext_slot_mask),
3124       m_objc_debug_taggedpointer_ext_payload_lshift(
3125           objc_debug_taggedpointer_ext_payload_lshift),
3126       m_objc_debug_taggedpointer_ext_payload_rshift(
3127           objc_debug_taggedpointer_ext_payload_rshift),
3128       m_objc_debug_taggedpointer_ext_classes(
3129           objc_debug_taggedpointer_ext_classes) {}
3130 
3131 bool AppleObjCRuntimeV2::TaggedPointerVendorExtended::
3132     IsPossibleExtendedTaggedPointer(lldb::addr_t ptr) {
3133   if (!IsPossibleTaggedPointer(ptr))
3134     return false;
3135 
3136   if (m_objc_debug_taggedpointer_ext_mask == 0)
3137     return false;
3138 
3139   return ((ptr & m_objc_debug_taggedpointer_ext_mask) ==
3140           m_objc_debug_taggedpointer_ext_mask);
3141 }
3142 
3143 ObjCLanguageRuntime::ClassDescriptorSP
3144 AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor(
3145     lldb::addr_t ptr) {
3146   ClassDescriptorSP actual_class_descriptor_sp;
3147   uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
3148 
3149   if (!IsPossibleTaggedPointer(unobfuscated))
3150     return ObjCLanguageRuntime::ClassDescriptorSP();
3151 
3152   if (!IsPossibleExtendedTaggedPointer(unobfuscated))
3153     return this->TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(ptr);
3154 
3155   uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_ext_slot_shift) &
3156                    m_objc_debug_taggedpointer_ext_slot_mask;
3157 
3158   CacheIterator iterator = m_ext_cache.find(slot), end = m_ext_cache.end();
3159   if (iterator != end) {
3160     actual_class_descriptor_sp = iterator->second;
3161   } else {
3162     Process *process(m_runtime.GetProcess());
3163     uintptr_t slot_ptr = slot * process->GetAddressByteSize() +
3164                          m_objc_debug_taggedpointer_ext_classes;
3165     Status error;
3166     uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
3167     if (error.Fail() || slot_data == 0 ||
3168         slot_data == uintptr_t(LLDB_INVALID_ADDRESS))
3169       return nullptr;
3170     actual_class_descriptor_sp =
3171         m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data);
3172     if (!actual_class_descriptor_sp)
3173       return ObjCLanguageRuntime::ClassDescriptorSP();
3174     m_ext_cache[slot] = actual_class_descriptor_sp;
3175   }
3176 
3177   uint64_t data_payload = (((uint64_t)unobfuscated
3178                             << m_objc_debug_taggedpointer_ext_payload_lshift) >>
3179                            m_objc_debug_taggedpointer_ext_payload_rshift);
3180   int64_t data_payload_signed =
3181       ((int64_t)((int64_t)unobfuscated
3182                  << m_objc_debug_taggedpointer_ext_payload_lshift) >>
3183        m_objc_debug_taggedpointer_ext_payload_rshift);
3184 
3185   return ClassDescriptorSP(new ClassDescriptorV2Tagged(
3186       actual_class_descriptor_sp, data_payload, data_payload_signed));
3187 }
3188 
3189 AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache(
3190     AppleObjCRuntimeV2 &runtime, const ModuleSP &objc_module_sp,
3191     uint64_t objc_debug_isa_class_mask, uint64_t objc_debug_isa_magic_mask,
3192     uint64_t objc_debug_isa_magic_value,
3193     uint64_t objc_debug_indexed_isa_magic_mask,
3194     uint64_t objc_debug_indexed_isa_magic_value,
3195     uint64_t objc_debug_indexed_isa_index_mask,
3196     uint64_t objc_debug_indexed_isa_index_shift,
3197     lldb::addr_t objc_indexed_classes)
3198     : m_runtime(runtime), m_cache(), m_objc_module_wp(objc_module_sp),
3199       m_objc_debug_isa_class_mask(objc_debug_isa_class_mask),
3200       m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask),
3201       m_objc_debug_isa_magic_value(objc_debug_isa_magic_value),
3202       m_objc_debug_indexed_isa_magic_mask(objc_debug_indexed_isa_magic_mask),
3203       m_objc_debug_indexed_isa_magic_value(objc_debug_indexed_isa_magic_value),
3204       m_objc_debug_indexed_isa_index_mask(objc_debug_indexed_isa_index_mask),
3205       m_objc_debug_indexed_isa_index_shift(objc_debug_indexed_isa_index_shift),
3206       m_objc_indexed_classes(objc_indexed_classes), m_indexed_isa_cache() {}
3207 
3208 ObjCLanguageRuntime::ClassDescriptorSP
3209 AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor(ObjCISA isa) {
3210   ObjCISA real_isa = 0;
3211   if (!EvaluateNonPointerISA(isa, real_isa))
3212     return ObjCLanguageRuntime::ClassDescriptorSP();
3213   auto cache_iter = m_cache.find(real_isa);
3214   if (cache_iter != m_cache.end())
3215     return cache_iter->second;
3216   auto descriptor_sp =
3217       m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa);
3218   if (descriptor_sp) // cache only positive matches since the table might grow
3219     m_cache[real_isa] = descriptor_sp;
3220   return descriptor_sp;
3221 }
3222 
3223 bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
3224     ObjCISA isa, ObjCISA &ret_isa) {
3225   Log *log = GetLog(LLDBLog::Types);
3226 
3227   LLDB_LOGF(log, "AOCRT::NPI Evaluate(isa = 0x%" PRIx64 ")", (uint64_t)isa);
3228 
3229   if ((isa & ~m_objc_debug_isa_class_mask) == 0)
3230     return false;
3231 
3232   // If all of the indexed ISA variables are set, then its possible that this
3233   // ISA is indexed, and we should first try to get its value using the index.
3234   // Note, we check these variables first as the ObjC runtime will set at least
3235   // one of their values to 0 if they aren't needed.
3236   if (m_objc_debug_indexed_isa_magic_mask &&
3237       m_objc_debug_indexed_isa_magic_value &&
3238       m_objc_debug_indexed_isa_index_mask &&
3239       m_objc_debug_indexed_isa_index_shift && m_objc_indexed_classes) {
3240     if ((isa & ~m_objc_debug_indexed_isa_index_mask) == 0)
3241       return false;
3242 
3243     if ((isa & m_objc_debug_indexed_isa_magic_mask) ==
3244         m_objc_debug_indexed_isa_magic_value) {
3245       // Magic bits are correct, so try extract the index.
3246       uintptr_t index = (isa & m_objc_debug_indexed_isa_index_mask) >>
3247                         m_objc_debug_indexed_isa_index_shift;
3248       // If the index is out of bounds of the length of the array then check if
3249       // the array has been updated.  If that is the case then we should try
3250       // read the count again, and update the cache if the count has been
3251       // updated.
3252       if (index > m_indexed_isa_cache.size()) {
3253         LLDB_LOGF(log,
3254                   "AOCRT::NPI (index = %" PRIu64
3255                   ") exceeds cache (size = %" PRIu64 ")",
3256                   (uint64_t)index, (uint64_t)m_indexed_isa_cache.size());
3257 
3258         Process *process(m_runtime.GetProcess());
3259 
3260         ModuleSP objc_module_sp(m_objc_module_wp.lock());
3261         if (!objc_module_sp)
3262           return false;
3263 
3264         Status error;
3265         auto objc_indexed_classes_count = ExtractRuntimeGlobalSymbol(
3266             process, ConstString("objc_indexed_classes_count"), objc_module_sp,
3267             error);
3268         if (error.Fail())
3269           return false;
3270 
3271         LLDB_LOGF(log, "AOCRT::NPI (new class count = %" PRIu64 ")",
3272                   (uint64_t)objc_indexed_classes_count);
3273 
3274         if (objc_indexed_classes_count > m_indexed_isa_cache.size()) {
3275           // Read the class entries we don't have.  We should just read all of
3276           // them instead of just the one we need as then we can cache those we
3277           // may need later.
3278           auto num_new_classes =
3279               objc_indexed_classes_count - m_indexed_isa_cache.size();
3280           const uint32_t addr_size = process->GetAddressByteSize();
3281           DataBufferHeap buffer(num_new_classes * addr_size, 0);
3282 
3283           lldb::addr_t last_read_class =
3284               m_objc_indexed_classes + (m_indexed_isa_cache.size() * addr_size);
3285           size_t bytes_read = process->ReadMemory(
3286               last_read_class, buffer.GetBytes(), buffer.GetByteSize(), error);
3287           if (error.Fail() || bytes_read != buffer.GetByteSize())
3288             return false;
3289 
3290           LLDB_LOGF(log, "AOCRT::NPI (read new classes count = %" PRIu64 ")",
3291                     (uint64_t)num_new_classes);
3292 
3293           // Append the new entries to the existing cache.
3294           DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(),
3295                              process->GetByteOrder(),
3296                              process->GetAddressByteSize());
3297 
3298           lldb::offset_t offset = 0;
3299           for (unsigned i = 0; i != num_new_classes; ++i)
3300             m_indexed_isa_cache.push_back(data.GetAddress(&offset));
3301         }
3302       }
3303 
3304       // If the index is still out of range then this isn't a pointer.
3305       if (index > m_indexed_isa_cache.size())
3306         return false;
3307 
3308       LLDB_LOGF(log, "AOCRT::NPI Evaluate(ret_isa = 0x%" PRIx64 ")",
3309                 (uint64_t)m_indexed_isa_cache[index]);
3310 
3311       ret_isa = m_indexed_isa_cache[index];
3312       return (ret_isa != 0); // this is a pointer so 0 is not a valid value
3313     }
3314 
3315     return false;
3316   }
3317 
3318   // Definitely not an indexed ISA, so try to use a mask to extract the pointer
3319   // from the ISA.
3320   if ((isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value) {
3321     ret_isa = isa & m_objc_debug_isa_class_mask;
3322     return (ret_isa != 0); // this is a pointer so 0 is not a valid value
3323   }
3324   return false;
3325 }
3326 
3327 ObjCLanguageRuntime::EncodingToTypeSP AppleObjCRuntimeV2::GetEncodingToType() {
3328   if (!m_encoding_to_type_sp)
3329     m_encoding_to_type_sp =
3330         std::make_shared<AppleObjCTypeEncodingParser>(*this);
3331   return m_encoding_to_type_sp;
3332 }
3333 
3334 lldb_private::AppleObjCRuntime::ObjCISA
3335 AppleObjCRuntimeV2::GetPointerISA(ObjCISA isa) {
3336   ObjCISA ret = isa;
3337 
3338   if (auto *non_pointer_isa_cache = GetNonPointerIsaCache())
3339     non_pointer_isa_cache->EvaluateNonPointerISA(isa, ret);
3340 
3341   return ret;
3342 }
3343 
3344 bool AppleObjCRuntimeV2::GetCFBooleanValuesIfNeeded() {
3345   if (m_CFBoolean_values)
3346     return true;
3347 
3348   static ConstString g_dunder_kCFBooleanFalse("__kCFBooleanFalse");
3349   static ConstString g_dunder_kCFBooleanTrue("__kCFBooleanTrue");
3350   static ConstString g_kCFBooleanFalse("kCFBooleanFalse");
3351   static ConstString g_kCFBooleanTrue("kCFBooleanTrue");
3352 
3353   std::function<lldb::addr_t(ConstString, ConstString)> get_symbol =
3354       [this](ConstString sym, ConstString real_sym) -> lldb::addr_t {
3355     SymbolContextList sc_list;
3356     GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType(
3357         sym, lldb::eSymbolTypeData, sc_list);
3358     if (sc_list.GetSize() == 1) {
3359       SymbolContext sc;
3360       sc_list.GetContextAtIndex(0, sc);
3361       if (sc.symbol)
3362         return sc.symbol->GetLoadAddress(&GetProcess()->GetTarget());
3363     }
3364     GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType(
3365         real_sym, lldb::eSymbolTypeData, sc_list);
3366     if (sc_list.GetSize() != 1)
3367       return LLDB_INVALID_ADDRESS;
3368 
3369     SymbolContext sc;
3370     sc_list.GetContextAtIndex(0, sc);
3371     if (!sc.symbol)
3372       return LLDB_INVALID_ADDRESS;
3373 
3374     lldb::addr_t addr = sc.symbol->GetLoadAddress(&GetProcess()->GetTarget());
3375     Status error;
3376     addr = GetProcess()->ReadPointerFromMemory(addr, error);
3377     if (error.Fail())
3378       return LLDB_INVALID_ADDRESS;
3379     return addr;
3380   };
3381 
3382   lldb::addr_t false_addr = get_symbol(g_dunder_kCFBooleanFalse, g_kCFBooleanFalse);
3383   lldb::addr_t true_addr = get_symbol(g_dunder_kCFBooleanTrue, g_kCFBooleanTrue);
3384 
3385   return (m_CFBoolean_values = {false_addr, true_addr}).operator bool();
3386 }
3387 
3388 void AppleObjCRuntimeV2::GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
3389                                                       lldb::addr_t &cf_false) {
3390   if (GetCFBooleanValuesIfNeeded()) {
3391     cf_true = m_CFBoolean_values->second;
3392     cf_false = m_CFBoolean_values->first;
3393   } else
3394     this->AppleObjCRuntime::GetValuesForGlobalCFBooleans(cf_true, cf_false);
3395 }
3396 
3397 void AppleObjCRuntimeV2::ModulesDidLoad(const ModuleList &module_list) {
3398   AppleObjCRuntime::ModulesDidLoad(module_list);
3399   if (HasReadObjCLibrary() && m_shared_cache_image_headers_up)
3400     m_shared_cache_image_headers_up->SetNeedsUpdate();
3401 }
3402 
3403 bool AppleObjCRuntimeV2::IsSharedCacheImageLoaded(uint16_t image_index) {
3404   if (!m_shared_cache_image_headers_up) {
3405     m_shared_cache_image_headers_up =
3406         SharedCacheImageHeaders::CreateSharedCacheImageHeaders(*this);
3407   }
3408   if (m_shared_cache_image_headers_up)
3409     return m_shared_cache_image_headers_up->IsImageLoaded(image_index);
3410 
3411   return false;
3412 }
3413 
3414 std::optional<uint64_t> AppleObjCRuntimeV2::GetSharedCacheImageHeaderVersion() {
3415   if (!m_shared_cache_image_headers_up) {
3416     m_shared_cache_image_headers_up =
3417         SharedCacheImageHeaders::CreateSharedCacheImageHeaders(*this);
3418   }
3419   if (m_shared_cache_image_headers_up)
3420     return m_shared_cache_image_headers_up->GetVersion();
3421 
3422   return std::nullopt;
3423 }
3424 
3425 #pragma mark Frame recognizers
3426 
3427 class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame {
3428 public:
3429   ObjCExceptionRecognizedStackFrame(StackFrameSP frame_sp) {
3430     ThreadSP thread_sp = frame_sp->GetThread();
3431     ProcessSP process_sp = thread_sp->GetProcess();
3432 
3433     const lldb::ABISP &abi = process_sp->GetABI();
3434     if (!abi)
3435       return;
3436 
3437     TypeSystemClangSP scratch_ts_sp =
3438         ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget());
3439     if (!scratch_ts_sp)
3440       return;
3441     CompilerType voidstar =
3442         scratch_ts_sp->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
3443 
3444     ValueList args;
3445     Value input_value;
3446     input_value.SetCompilerType(voidstar);
3447     args.PushValue(input_value);
3448 
3449     if (!abi->GetArgumentValues(*thread_sp, args))
3450       return;
3451 
3452     addr_t exception_addr = args.GetValueAtIndex(0)->GetScalar().ULongLong();
3453 
3454     Value value(exception_addr);
3455     value.SetCompilerType(voidstar);
3456     exception = ValueObjectConstResult::Create(frame_sp.get(), value,
3457                                                ConstString("exception"));
3458     exception = ValueObjectRecognizerSynthesizedValue::Create(
3459         *exception, eValueTypeVariableArgument);
3460     exception = exception->GetDynamicValue(eDynamicDontRunTarget);
3461 
3462     m_arguments = ValueObjectListSP(new ValueObjectList());
3463     m_arguments->Append(exception);
3464 
3465     m_stop_desc = "hit Objective-C exception";
3466   }
3467 
3468   ValueObjectSP exception;
3469 
3470   lldb::ValueObjectSP GetExceptionObject() override { return exception; }
3471 };
3472 
3473 class ObjCExceptionThrowFrameRecognizer : public StackFrameRecognizer {
3474   lldb::RecognizedStackFrameSP
3475   RecognizeFrame(lldb::StackFrameSP frame) override {
3476     return lldb::RecognizedStackFrameSP(
3477         new ObjCExceptionRecognizedStackFrame(frame));
3478   };
3479   std::string GetName() override {
3480     return "ObjC Exception Throw StackFrame Recognizer";
3481   }
3482 };
3483 
3484 static void RegisterObjCExceptionRecognizer(Process *process) {
3485   FileSpec module;
3486   ConstString function;
3487   std::tie(module, function) = AppleObjCRuntime::GetExceptionThrowLocation();
3488   std::vector<ConstString> symbols = {function};
3489 
3490   process->GetTarget().GetFrameRecognizerManager().AddRecognizer(
3491       StackFrameRecognizerSP(new ObjCExceptionThrowFrameRecognizer()),
3492       module.GetFilename(), symbols,
3493       /*first_instruction_only*/ true);
3494 }
3495