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