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