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
68using namespace lldb;
69using namespace lldb_private;
70
71char AppleObjCRuntimeV2::ID = 0;
72
73static const char *g_get_dynamic_class_info_name =
74    "__lldb_apple_objc_v2_get_dynamic_class_info";
75
76static const char *g_get_dynamic_class_info_body = R"(
77
78extern "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
86typedef 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
95typedef struct BucketInfo
96{
97    const char *name_ptr;
98    Class isa;
99} BucketInfo;
100
101struct ClassInfo
102{
103    Class isa;
104    uint32_t hash;
105} __attribute__((__packed__));
106
107uint32_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
163static const char *g_get_dynamic_class_info2_name =
164    "__lldb_apple_objc_v2_get_dynamic_class_info2";
165
166static const char *g_get_dynamic_class_info2_body = R"(
167
168extern "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
177struct ClassInfo
178{
179    Class isa;
180    uint32_t hash;
181} __attribute__((__packed__));
182
183uint32_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
232static const char *g_get_dynamic_class_info3_name =
233    "__lldb_apple_objc_v2_get_dynamic_class_info3";
234
235static const char *g_get_dynamic_class_info3_body = R"(
236
237extern "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
247struct ClassInfo
248{
249    Class isa;
250    uint32_t hash;
251} __attribute__((__packed__));
252
253uint32_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.
311static const char *g_shared_cache_class_name_funcptr = R"(
312extern "C"
313{
314    const char *%s(void *objc_class);
315    const char *(*class_name_lookup_func)(void *) = %s;
316}
317)";
318
319static const char *g_get_shared_cache_class_info_name =
320    "__lldb_apple_objc_v2_get_shared_cache_class_info";
321
322static const char *g_get_shared_cache_class_info_body = R"(
323
324extern "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
334struct objc_classheader_t {
335    int32_t clsOffset;
336    int32_t hiOffset;
337};
338
339struct objc_classheader_v16_t {
340    uint64_t isDuplicate       : 1,
341             objectCacheOffset : 47, // Offset from the shared cache base
342             dylibObjCIndex    : 16;
343};
344
345struct 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
362struct 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
379struct objc_opt_t {
380    uint32_t version;
381    int32_t selopt_offset;
382    int32_t headeropt_offset;
383    int32_t clsopt_offset;
384};
385
386struct 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
394struct 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
408struct ClassInfo
409{
410    Class isa;
411    uint32_t hash;
412}  __attribute__((__packed__));
413
414uint32_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
687static uint64_t
688ExtractRuntimeGlobalSymbol(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
726static void RegisterObjCExceptionRecognizer(Process *process);
727
728AppleObjCRuntimeV2::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
756bool 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
811LanguageRuntime *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
827static 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
839class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed {
840public:
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::ArrayRef(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
905protected:
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
996class CommandObjectMultiwordObjC_TaggedPointer_Info
997    : public CommandObjectParsed {
998public:
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
1022protected:
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
1099class CommandObjectMultiwordObjC_ClassTable : public CommandObjectMultiword {
1100public:
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
1114class CommandObjectMultiwordObjC_TaggedPointer : public CommandObjectMultiword {
1115public:
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
1130class CommandObjectMultiwordObjC : public CommandObjectMultiword {
1131public:
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
1148void 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
1158void AppleObjCRuntimeV2::Terminate() {
1159  PluginManager::UnregisterPlugin(CreateInstance);
1160}
1161
1162BreakpointResolverSP
1163AppleObjCRuntimeV2::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
1178llvm::Expected<std::unique_ptr<UtilityFunction>>
1179AppleObjCRuntimeV2::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
1233size_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
1281bool 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
1287class RemoteNXMapTable {
1288public:
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
1461private:
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
1473AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() = default;
1474
1475void 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
1482bool 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
1501ObjCLanguageRuntime::ClassDescriptorSP
1502AppleObjCRuntimeV2::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
1511ObjCLanguageRuntime::ClassDescriptorSP
1512AppleObjCRuntimeV2::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
1562lldb::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
1595lldb::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
1622std::unique_ptr<UtilityFunction>
1623AppleObjCRuntimeV2::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  TypeSystemClangSP scratch_ts_sp =
1631      ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef());
1632  if (!scratch_ts_sp)
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      scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
1647  CompilerType clang_void_pointer_type =
1648      scratch_ts_sp->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
1687UtilityFunction *
1688AppleObjCRuntimeV2::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
1719lldb::addr_t &
1720AppleObjCRuntimeV2::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
1732AppleObjCRuntimeV2::DynamicClassInfoExtractor::Helper
1733AppleObjCRuntimeV2::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
1763std::unique_ptr<UtilityFunction>
1764AppleObjCRuntimeV2::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  TypeSystemClangSP scratch_ts_sp =
1772      ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef());
1773  if (!scratch_ts_sp)
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      scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
1812  CompilerType clang_void_pointer_type =
1813      scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType();
1814  CompilerType clang_uint64_t_pointer_type =
1815      scratch_ts_sp->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
1852UtilityFunction *
1853AppleObjCRuntimeV2::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
1860AppleObjCRuntimeV2::DescriptorMapUpdateResult
1861AppleObjCRuntimeV2::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  if (!thread_sp->SafeToCallFunctions())
1879    return DescriptorMapUpdateResult::Retry();
1880
1881  thread_sp->CalculateExecutionContext(exe_ctx);
1882  TypeSystemClangSP scratch_ts_sp =
1883      ScratchTypeSystemClang::GetForTarget(process->GetTarget());
1884
1885  if (!scratch_ts_sp)
1886    return DescriptorMapUpdateResult::Fail();
1887
1888  Address function_address;
1889
1890  const uint32_t addr_size = process->GetAddressByteSize();
1891
1892  Status err;
1893
1894  // Compute which helper we're going to use for this update.
1895  const DynamicClassInfoExtractor::Helper helper = ComputeHelper(exe_ctx);
1896
1897  // Read the total number of classes from the hash table
1898  const uint32_t num_classes =
1899      helper == DynamicClassInfoExtractor::gdb_objc_realized_classes
1900          ? hash_table.GetCount()
1901          : m_runtime.m_realized_class_generation_count;
1902  if (num_classes == 0) {
1903    LLDB_LOGF(log, "No dynamic classes found.");
1904    return DescriptorMapUpdateResult::Success(0);
1905  }
1906
1907  UtilityFunction *get_class_info_code =
1908      GetClassInfoUtilityFunction(exe_ctx, helper);
1909  if (!get_class_info_code) {
1910    // The callee will have already logged a useful error message.
1911    return DescriptorMapUpdateResult::Fail();
1912  }
1913
1914  FunctionCaller *get_class_info_function =
1915      get_class_info_code->GetFunctionCaller();
1916
1917  if (!get_class_info_function) {
1918    LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
1919    return DescriptorMapUpdateResult::Fail();
1920  }
1921
1922  ValueList arguments = get_class_info_function->GetArgumentValues();
1923
1924  DiagnosticManager diagnostics;
1925
1926  const uint32_t class_info_byte_size = addr_size + 4;
1927  const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
1928  lldb::addr_t class_infos_addr = process->AllocateMemory(
1929      class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);
1930
1931  if (class_infos_addr == LLDB_INVALID_ADDRESS) {
1932    LLDB_LOGF(log,
1933              "unable to allocate %" PRIu32
1934              " bytes in process for shared cache read",
1935              class_infos_byte_size);
1936    return DescriptorMapUpdateResult::Fail();
1937  }
1938
1939  auto deallocate_class_infos = llvm::make_scope_exit([&] {
1940    // Deallocate the memory we allocated for the ClassInfo array
1941    if (class_infos_addr != LLDB_INVALID_ADDRESS)
1942      process->DeallocateMemory(class_infos_addr);
1943  });
1944
1945  lldb::addr_t class_buffer_addr = LLDB_INVALID_ADDRESS;
1946  const uint32_t class_byte_size = addr_size;
1947  const uint32_t class_buffer_len = num_classes;
1948  const uint32_t class_buffer_byte_size = class_buffer_len * class_byte_size;
1949  if (helper == Helper::objc_getRealizedClassList_trylock) {
1950    class_buffer_addr = process->AllocateMemory(
1951        class_buffer_byte_size, ePermissionsReadable | ePermissionsWritable,
1952        err);
1953    if (class_buffer_addr == LLDB_INVALID_ADDRESS) {
1954      LLDB_LOGF(log,
1955                "unable to allocate %" PRIu32
1956                " bytes in process for shared cache read",
1957                class_buffer_byte_size);
1958      return DescriptorMapUpdateResult::Fail();
1959    }
1960  }
1961
1962  auto deallocate_class_buffer = llvm::make_scope_exit([&] {
1963    // Deallocate the memory we allocated for the Class array
1964    if (class_buffer_addr != LLDB_INVALID_ADDRESS)
1965      process->DeallocateMemory(class_buffer_addr);
1966  });
1967
1968  std::lock_guard<std::mutex> guard(m_mutex);
1969
1970  // Fill in our function argument values
1971  uint32_t index = 0;
1972  arguments.GetValueAtIndex(index++)->GetScalar() =
1973      hash_table.GetTableLoadAddress();
1974  arguments.GetValueAtIndex(index++)->GetScalar() = class_infos_addr;
1975  arguments.GetValueAtIndex(index++)->GetScalar() = class_infos_byte_size;
1976
1977  if (class_buffer_addr != LLDB_INVALID_ADDRESS) {
1978    arguments.GetValueAtIndex(index++)->GetScalar() = class_buffer_addr;
1979    arguments.GetValueAtIndex(index++)->GetScalar() = class_buffer_byte_size;
1980  }
1981
1982  // Only dump the runtime classes from the expression evaluation if the log is
1983  // verbose:
1984  Log *type_log = GetLog(LLDBLog::Types);
1985  bool dump_log = type_log && type_log->GetVerbose();
1986
1987  arguments.GetValueAtIndex(index++)->GetScalar() = dump_log ? 1 : 0;
1988
1989  bool success = false;
1990
1991  diagnostics.Clear();
1992
1993  // Write our function arguments into the process so we can run our function
1994  if (get_class_info_function->WriteFunctionArguments(
1995          exe_ctx, GetClassInfoArgs(helper), arguments, diagnostics)) {
1996    EvaluateExpressionOptions options;
1997    options.SetUnwindOnError(true);
1998    options.SetTryAllThreads(false);
1999    options.SetStopOthers(true);
2000    options.SetIgnoreBreakpoints(true);
2001    options.SetTimeout(process->GetUtilityExpressionTimeout());
2002    options.SetIsForUtilityExpr(true);
2003
2004    CompilerType clang_uint32_t_type =
2005        scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
2006
2007    Value return_value;
2008    return_value.SetValueType(Value::ValueType::Scalar);
2009    return_value.SetCompilerType(clang_uint32_t_type);
2010    return_value.GetScalar() = 0;
2011
2012    diagnostics.Clear();
2013
2014    // Run the function
2015    ExpressionResults results = get_class_info_function->ExecuteFunction(
2016        exe_ctx, &GetClassInfoArgs(helper), options, diagnostics, return_value);
2017
2018    if (results == eExpressionCompleted) {
2019      // The result is the number of ClassInfo structures that were filled in
2020      num_class_infos = return_value.GetScalar().ULong();
2021      LLDB_LOG(log, "Discovered {0} Objective-C classes", num_class_infos);
2022      if (num_class_infos > 0) {
2023        // Read the ClassInfo structures
2024        DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0);
2025        if (process->ReadMemory(class_infos_addr, buffer.GetBytes(),
2026                                buffer.GetByteSize(),
2027                                err) == buffer.GetByteSize()) {
2028          DataExtractor class_infos_data(buffer.GetBytes(),
2029                                         buffer.GetByteSize(),
2030                                         process->GetByteOrder(), addr_size);
2031          m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos);
2032        }
2033      }
2034      success = true;
2035    } else {
2036      if (log) {
2037        LLDB_LOGF(log, "Error evaluating our find class name function.");
2038        diagnostics.Dump(log);
2039      }
2040    }
2041  } else {
2042    if (log) {
2043      LLDB_LOGF(log, "Error writing function arguments.");
2044      diagnostics.Dump(log);
2045    }
2046  }
2047
2048  return DescriptorMapUpdateResult(success, false, num_class_infos);
2049}
2050
2051uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data,
2052                                                 uint32_t num_class_infos) {
2053  // Parses an array of "num_class_infos" packed ClassInfo structures:
2054  //
2055  //    struct ClassInfo
2056  //    {
2057  //        Class isa;
2058  //        uint32_t hash;
2059  //    } __attribute__((__packed__));
2060
2061  Log *log = GetLog(LLDBLog::Types);
2062  bool should_log = log && log->GetVerbose();
2063
2064  uint32_t num_parsed = 0;
2065
2066  // Iterate through all ClassInfo structures
2067  lldb::offset_t offset = 0;
2068  for (uint32_t i = 0; i < num_class_infos; ++i) {
2069    ObjCISA isa = data.GetAddress(&offset);
2070
2071    if (isa == 0) {
2072      if (should_log)
2073        LLDB_LOGF(
2074            log, "AppleObjCRuntimeV2 found NULL isa, ignoring this class info");
2075      continue;
2076    }
2077    // Check if we already know about this ISA, if we do, the info will never
2078    // change, so we can just skip it.
2079    if (ISAIsCached(isa)) {
2080      if (should_log)
2081        LLDB_LOGF(log,
2082                  "AppleObjCRuntimeV2 found cached isa=0x%" PRIx64
2083                  ", ignoring this class info",
2084                  isa);
2085      offset += 4;
2086    } else {
2087      // Read the 32 bit hash for the class name
2088      const uint32_t name_hash = data.GetU32(&offset);
2089      ClassDescriptorSP descriptor_sp(
2090          new ClassDescriptorV2(*this, isa, nullptr));
2091
2092      // The code in g_get_shared_cache_class_info_body sets the value of the
2093      // hash to 0 to signal a demangled symbol. We use class_getName() in that
2094      // code to find the class name, but this returns a demangled name for
2095      // Swift symbols. For those symbols, recompute the hash here by reading
2096      // their name from the runtime.
2097      if (name_hash)
2098        AddClass(isa, descriptor_sp, name_hash);
2099      else
2100        AddClass(isa, descriptor_sp,
2101                 descriptor_sp->GetClassName().AsCString(nullptr));
2102      num_parsed++;
2103      if (should_log)
2104        LLDB_LOGF(log,
2105                  "AppleObjCRuntimeV2 added isa=0x%" PRIx64
2106                  ", hash=0x%8.8x, name=%s",
2107                  isa, name_hash,
2108                  descriptor_sp->GetClassName().AsCString("<unknown>"));
2109    }
2110  }
2111  if (should_log)
2112    LLDB_LOGF(log, "AppleObjCRuntimeV2 parsed %" PRIu32 " class infos",
2113              num_parsed);
2114  return num_parsed;
2115}
2116
2117bool AppleObjCRuntimeV2::HasSymbol(ConstString Name) {
2118  if (!m_objc_module_sp)
2119    return false;
2120  if (const Symbol *symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType(
2121          Name, lldb::eSymbolTypeCode)) {
2122    if (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())
2123      return true;
2124  }
2125  return false;
2126}
2127
2128AppleObjCRuntimeV2::DescriptorMapUpdateResult
2129AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::UpdateISAToDescriptorMap() {
2130  Process *process = m_runtime.GetProcess();
2131  if (process == nullptr)
2132    return DescriptorMapUpdateResult::Fail();
2133
2134  Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
2135
2136  ExecutionContext exe_ctx;
2137
2138  ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread();
2139
2140  if (!thread_sp)
2141    return DescriptorMapUpdateResult::Fail();
2142
2143  if (!thread_sp->SafeToCallFunctions())
2144    return DescriptorMapUpdateResult::Retry();
2145
2146  thread_sp->CalculateExecutionContext(exe_ctx);
2147  TypeSystemClangSP scratch_ts_sp =
2148      ScratchTypeSystemClang::GetForTarget(process->GetTarget());
2149
2150  if (!scratch_ts_sp)
2151    return DescriptorMapUpdateResult::Fail();
2152
2153  Address function_address;
2154
2155  const uint32_t addr_size = process->GetAddressByteSize();
2156
2157  Status err;
2158
2159  uint32_t num_class_infos = 0;
2160
2161  const lldb::addr_t objc_opt_ptr = m_runtime.GetSharedCacheReadOnlyAddress();
2162  const lldb::addr_t shared_cache_base_addr =
2163      m_runtime.GetSharedCacheBaseAddress();
2164
2165  if (objc_opt_ptr == LLDB_INVALID_ADDRESS ||
2166      shared_cache_base_addr == LLDB_INVALID_ADDRESS)
2167    return DescriptorMapUpdateResult::Fail();
2168
2169  // The number of entries to pre-allocate room for.
2170  // Each entry is (addrsize + 4) bytes
2171  const uint32_t max_num_classes = 163840;
2172
2173  UtilityFunction *get_class_info_code = GetClassInfoUtilityFunction(exe_ctx);
2174  if (!get_class_info_code) {
2175    // The callee will have already logged a useful error message.
2176    return DescriptorMapUpdateResult::Fail();
2177  }
2178
2179  FunctionCaller *get_shared_cache_class_info_function =
2180      get_class_info_code->GetFunctionCaller();
2181
2182  if (!get_shared_cache_class_info_function) {
2183    LLDB_LOGF(log, "Failed to get implementation lookup function caller.");
2184    return DescriptorMapUpdateResult::Fail();
2185  }
2186
2187  ValueList arguments =
2188      get_shared_cache_class_info_function->GetArgumentValues();
2189
2190  DiagnosticManager diagnostics;
2191
2192  const uint32_t class_info_byte_size = addr_size + 4;
2193  const uint32_t class_infos_byte_size = max_num_classes * class_info_byte_size;
2194  lldb::addr_t class_infos_addr = process->AllocateMemory(
2195      class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);
2196  const uint32_t relative_selector_offset_addr_size = 64;
2197  lldb::addr_t relative_selector_offset_addr =
2198      process->AllocateMemory(relative_selector_offset_addr_size,
2199                              ePermissionsReadable | ePermissionsWritable, err);
2200
2201  if (class_infos_addr == LLDB_INVALID_ADDRESS) {
2202    LLDB_LOGF(log,
2203              "unable to allocate %" PRIu32
2204              " bytes in process for shared cache read",
2205              class_infos_byte_size);
2206    return DescriptorMapUpdateResult::Fail();
2207  }
2208
2209  std::lock_guard<std::mutex> guard(m_mutex);
2210
2211  // Fill in our function argument values
2212  arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr;
2213  arguments.GetValueAtIndex(1)->GetScalar() = shared_cache_base_addr;
2214  arguments.GetValueAtIndex(2)->GetScalar() = class_infos_addr;
2215  arguments.GetValueAtIndex(3)->GetScalar() = relative_selector_offset_addr;
2216  arguments.GetValueAtIndex(4)->GetScalar() = class_infos_byte_size;
2217  // Only dump the runtime classes from the expression evaluation if the log is
2218  // verbose:
2219  Log *type_log = GetLog(LLDBLog::Types);
2220  bool dump_log = type_log && type_log->GetVerbose();
2221
2222  arguments.GetValueAtIndex(5)->GetScalar() = dump_log ? 1 : 0;
2223
2224  bool success = false;
2225
2226  diagnostics.Clear();
2227
2228  // Write our function arguments into the process so we can run our function
2229  if (get_shared_cache_class_info_function->WriteFunctionArguments(
2230          exe_ctx, m_args, arguments, diagnostics)) {
2231    EvaluateExpressionOptions options;
2232    options.SetUnwindOnError(true);
2233    options.SetTryAllThreads(false);
2234    options.SetStopOthers(true);
2235    options.SetIgnoreBreakpoints(true);
2236    options.SetTimeout(process->GetUtilityExpressionTimeout());
2237    options.SetIsForUtilityExpr(true);
2238
2239    CompilerType clang_uint32_t_type =
2240        scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32);
2241
2242    Value return_value;
2243    return_value.SetValueType(Value::ValueType::Scalar);
2244    return_value.SetCompilerType(clang_uint32_t_type);
2245    return_value.GetScalar() = 0;
2246
2247    diagnostics.Clear();
2248
2249    // Run the function
2250    ExpressionResults results =
2251        get_shared_cache_class_info_function->ExecuteFunction(
2252            exe_ctx, &m_args, options, diagnostics, return_value);
2253
2254    if (results == eExpressionCompleted) {
2255      // The result is the number of ClassInfo structures that were filled in
2256      num_class_infos = return_value.GetScalar().ULong();
2257      LLDB_LOG(log, "Discovered {0} Objective-C classes in the shared cache",
2258               num_class_infos);
2259      // Assert if there were more classes than we pre-allocated
2260      // room for.
2261      assert(num_class_infos <= max_num_classes);
2262      if (num_class_infos > 0) {
2263        if (num_class_infos > max_num_classes) {
2264          num_class_infos = max_num_classes;
2265
2266          success = false;
2267        } else {
2268          success = true;
2269        }
2270
2271        // Read the relative selector offset.
2272        DataBufferHeap relative_selector_offset_buffer(64, 0);
2273        if (process->ReadMemory(relative_selector_offset_addr,
2274                                relative_selector_offset_buffer.GetBytes(),
2275                                relative_selector_offset_buffer.GetByteSize(),
2276                                err) ==
2277            relative_selector_offset_buffer.GetByteSize()) {
2278          DataExtractor relative_selector_offset_data(
2279              relative_selector_offset_buffer.GetBytes(),
2280              relative_selector_offset_buffer.GetByteSize(),
2281              process->GetByteOrder(), addr_size);
2282          lldb::offset_t offset = 0;
2283          uint64_t relative_selector_offset =
2284              relative_selector_offset_data.GetU64(&offset);
2285          if (relative_selector_offset > 0) {
2286            // The offset is relative to the objc_opt struct.
2287            m_runtime.SetRelativeSelectorBaseAddr(objc_opt_ptr +
2288                                                  relative_selector_offset);
2289          }
2290        }
2291
2292        // Read the ClassInfo structures
2293        DataBufferHeap class_infos_buffer(
2294            num_class_infos * class_info_byte_size, 0);
2295        if (process->ReadMemory(class_infos_addr, class_infos_buffer.GetBytes(),
2296                                class_infos_buffer.GetByteSize(),
2297                                err) == class_infos_buffer.GetByteSize()) {
2298          DataExtractor class_infos_data(class_infos_buffer.GetBytes(),
2299                                         class_infos_buffer.GetByteSize(),
2300                                         process->GetByteOrder(), addr_size);
2301
2302          m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos);
2303        }
2304      } else {
2305        success = true;
2306      }
2307    } else {
2308      if (log) {
2309        LLDB_LOGF(log, "Error evaluating our find class name function.");
2310        diagnostics.Dump(log);
2311      }
2312    }
2313  } else {
2314    if (log) {
2315      LLDB_LOGF(log, "Error writing function arguments.");
2316      diagnostics.Dump(log);
2317    }
2318  }
2319
2320  // Deallocate the memory we allocated for the ClassInfo array
2321  process->DeallocateMemory(class_infos_addr);
2322
2323  return DescriptorMapUpdateResult(success, false, num_class_infos);
2324}
2325
2326lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() {
2327  Process *process = GetProcess();
2328
2329  if (process) {
2330    ModuleSP objc_module_sp(GetObjCModule());
2331
2332    if (objc_module_sp) {
2333      ObjectFile *objc_object = objc_module_sp->GetObjectFile();
2334
2335      if (objc_object) {
2336        SectionList *section_list = objc_module_sp->GetSectionList();
2337
2338        if (section_list) {
2339          SectionSP text_segment_sp(
2340              section_list->FindSectionByName(ConstString("__TEXT")));
2341
2342          if (text_segment_sp) {
2343            SectionSP objc_opt_section_sp(
2344                text_segment_sp->GetChildren().FindSectionByName(
2345                    ConstString("__objc_opt_ro")));
2346
2347            if (objc_opt_section_sp) {
2348              return objc_opt_section_sp->GetLoadBaseAddress(
2349                  &process->GetTarget());
2350            }
2351          }
2352        }
2353      }
2354    }
2355  }
2356  return LLDB_INVALID_ADDRESS;
2357}
2358
2359lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheBaseAddress() {
2360  StructuredData::ObjectSP info = m_process->GetSharedCacheInfo();
2361  if (!info)
2362    return LLDB_INVALID_ADDRESS;
2363
2364  StructuredData::Dictionary *info_dict = info->GetAsDictionary();
2365  if (!info_dict)
2366    return LLDB_INVALID_ADDRESS;
2367
2368  StructuredData::ObjectSP value =
2369      info_dict->GetValueForKey("shared_cache_base_address");
2370  if (!value)
2371    return LLDB_INVALID_ADDRESS;
2372
2373  return value->GetIntegerValue(LLDB_INVALID_ADDRESS);
2374}
2375
2376void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() {
2377  LLDB_SCOPED_TIMER();
2378
2379  Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
2380
2381  // Else we need to check with our process to see when the map was updated.
2382  Process *process = GetProcess();
2383
2384  if (process) {
2385    RemoteNXMapTable hash_table;
2386
2387    // Update the process stop ID that indicates the last time we updated the
2388    // map, whether it was successful or not.
2389    m_isa_to_descriptor_stop_id = process->GetStopID();
2390
2391    // Ask the runtime is the realized class generation count changed. Unlike
2392    // the hash table, this accounts for lazily named classes.
2393    const bool class_count_changed = RealizedClassGenerationCountChanged();
2394
2395    if (!m_hash_signature.NeedsUpdate(process, this, hash_table) &&
2396        !class_count_changed)
2397      return;
2398
2399    m_hash_signature.UpdateSignature(hash_table);
2400
2401    // Grab the dynamically loaded Objective-C classes from memory.
2402    DescriptorMapUpdateResult dynamic_update_result =
2403        m_dynamic_class_info_extractor.UpdateISAToDescriptorMap(hash_table);
2404
2405    // Now get the objc classes that are baked into the Objective-C runtime in
2406    // the shared cache, but only once per process as this data never changes
2407    if (!m_loaded_objc_opt) {
2408      // it is legitimately possible for the shared cache to be empty - in that
2409      // case, the dynamic hash table will contain all the class information we
2410      // need; the situation we're trying to detect is one where we aren't
2411      // seeing class information from the runtime - in order to detect that
2412      // vs. just the shared cache being empty or sparsely populated, we set an
2413      // arbitrary (very low) threshold for the number of classes that we want
2414      // to see in a "good" scenario - anything below that is suspicious
2415      // (Foundation alone has thousands of classes)
2416      const uint32_t num_classes_to_warn_at = 500;
2417
2418      DescriptorMapUpdateResult shared_cache_update_result =
2419          m_shared_cache_class_info_extractor.UpdateISAToDescriptorMap();
2420
2421      LLDB_LOGF(log,
2422                "attempted to read objc class data - results: "
2423                "[dynamic_update]: ran: %s, retry: %s, count: %" PRIu32
2424                " [shared_cache_update]: ran: %s, retry: %s, count: %" PRIu32,
2425                dynamic_update_result.m_update_ran ? "yes" : "no",
2426                dynamic_update_result.m_retry_update ? "yes" : "no",
2427                dynamic_update_result.m_num_found,
2428                shared_cache_update_result.m_update_ran ? "yes" : "no",
2429                shared_cache_update_result.m_retry_update ? "yes" : "no",
2430                shared_cache_update_result.m_num_found);
2431
2432      // warn if:
2433      // - we could not run either expression
2434      // - we found fewer than num_classes_to_warn_at classes total
2435      if (dynamic_update_result.m_retry_update ||
2436          shared_cache_update_result.m_retry_update)
2437        WarnIfNoClassesCached(SharedCacheWarningReason::eExpressionUnableToRun);
2438      else if ((!shared_cache_update_result.m_update_ran) ||
2439               (!dynamic_update_result.m_update_ran))
2440        WarnIfNoClassesCached(
2441            SharedCacheWarningReason::eExpressionExecutionFailure);
2442      else if (dynamic_update_result.m_num_found +
2443                   shared_cache_update_result.m_num_found <
2444               num_classes_to_warn_at)
2445        WarnIfNoClassesCached(SharedCacheWarningReason::eNotEnoughClassesRead);
2446      else
2447        m_loaded_objc_opt = true;
2448    }
2449  } else {
2450    m_isa_to_descriptor_stop_id = UINT32_MAX;
2451  }
2452}
2453
2454bool AppleObjCRuntimeV2::RealizedClassGenerationCountChanged() {
2455  Process *process = GetProcess();
2456  if (!process)
2457    return false;
2458
2459  Status error;
2460  uint64_t objc_debug_realized_class_generation_count =
2461      ExtractRuntimeGlobalSymbol(
2462          process, ConstString("objc_debug_realized_class_generation_count"),
2463          GetObjCModule(), error);
2464  if (error.Fail())
2465    return false;
2466
2467  if (m_realized_class_generation_count ==
2468      objc_debug_realized_class_generation_count)
2469    return false;
2470
2471  Log *log = GetLog(LLDBLog::Process | LLDBLog::Types);
2472  LLDB_LOG(log,
2473           "objc_debug_realized_class_generation_count changed from {0} to {1}",
2474           m_realized_class_generation_count,
2475           objc_debug_realized_class_generation_count);
2476
2477  m_realized_class_generation_count =
2478      objc_debug_realized_class_generation_count;
2479
2480  return true;
2481}
2482
2483static bool DoesProcessHaveSharedCache(Process &process) {
2484  PlatformSP platform_sp = process.GetTarget().GetPlatform();
2485  if (!platform_sp)
2486    return true; // this should not happen
2487
2488  llvm::StringRef platform_plugin_name_sr = platform_sp->GetPluginName();
2489  if (platform_plugin_name_sr.endswith("-simulator"))
2490    return false;
2491
2492  return true;
2493}
2494
2495void AppleObjCRuntimeV2::WarnIfNoClassesCached(
2496    SharedCacheWarningReason reason) {
2497  if (GetProcess() && !DoesProcessHaveSharedCache(*GetProcess())) {
2498    // Simulators do not have the objc_opt_ro class table so don't actually
2499    // complain to the user
2500    return;
2501  }
2502
2503  Debugger &debugger(GetProcess()->GetTarget().GetDebugger());
2504  switch (reason) {
2505  case SharedCacheWarningReason::eNotEnoughClassesRead:
2506    Debugger::ReportWarning("could not find Objective-C class data in "
2507                            "the process. This may reduce the quality of type "
2508                            "information available.\n",
2509                            debugger.GetID(), &m_no_classes_cached_warning);
2510    break;
2511  case SharedCacheWarningReason::eExpressionExecutionFailure:
2512    Debugger::ReportWarning(
2513        "could not execute support code to read "
2514        "Objective-C class data in the process. This may "
2515        "reduce the quality of type information available.\n",
2516        debugger.GetID(), &m_no_classes_cached_warning);
2517    break;
2518  case SharedCacheWarningReason::eExpressionUnableToRun:
2519    Debugger::ReportWarning(
2520        "could not execute support code to read Objective-C class data because "
2521        "it's not yet safe to do so, and will be retried later.\n",
2522        debugger.GetID(), nullptr);
2523    break;
2524  }
2525}
2526
2527void AppleObjCRuntimeV2::WarnIfNoExpandedSharedCache() {
2528  if (!m_objc_module_sp)
2529    return;
2530
2531  ObjectFile *object_file = m_objc_module_sp->GetObjectFile();
2532  if (!object_file)
2533    return;
2534
2535  if (!object_file->IsInMemory())
2536    return;
2537
2538  Target &target = GetProcess()->GetTarget();
2539  Debugger &debugger = target.GetDebugger();
2540
2541  std::string buffer;
2542  llvm::raw_string_ostream os(buffer);
2543
2544  os << "libobjc.A.dylib is being read from process memory. This "
2545        "indicates that LLDB could not ";
2546  if (PlatformSP platform_sp = target.GetPlatform()) {
2547    if (platform_sp->IsHost()) {
2548      os << "read from the host's in-memory shared cache";
2549    } else {
2550      os << "find the on-disk shared cache for this device";
2551    }
2552  } else {
2553    os << "read from the shared cache";
2554  }
2555  os << ". This will likely reduce debugging performance.\n";
2556
2557  Debugger::ReportWarning(os.str(), debugger.GetID(),
2558                          &m_no_expanded_cache_warning);
2559}
2560
2561DeclVendor *AppleObjCRuntimeV2::GetDeclVendor() {
2562  if (!m_decl_vendor_up)
2563    m_decl_vendor_up = std::make_unique<AppleObjCDeclVendor>(*this);
2564
2565  return m_decl_vendor_up.get();
2566}
2567
2568lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(ConstString name) {
2569  lldb::addr_t ret = LLDB_INVALID_ADDRESS;
2570
2571  const char *name_cstr = name.AsCString();
2572
2573  if (name_cstr) {
2574    llvm::StringRef name_strref(name_cstr);
2575
2576    llvm::StringRef ivar_prefix("OBJC_IVAR_$_");
2577    llvm::StringRef class_prefix("OBJC_CLASS_$_");
2578
2579    if (name_strref.startswith(ivar_prefix)) {
2580      llvm::StringRef ivar_skipped_prefix =
2581          name_strref.substr(ivar_prefix.size());
2582      std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar =
2583          ivar_skipped_prefix.split('.');
2584
2585      if (class_and_ivar.first.size() && class_and_ivar.second.size()) {
2586        const ConstString class_name_cs(class_and_ivar.first);
2587        ClassDescriptorSP descriptor =
2588            ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs);
2589
2590        if (descriptor) {
2591          const ConstString ivar_name_cs(class_and_ivar.second);
2592          const char *ivar_name_cstr = ivar_name_cs.AsCString();
2593
2594          auto ivar_func = [&ret,
2595                            ivar_name_cstr](const char *name, const char *type,
2596                                            lldb::addr_t offset_addr,
2597                                            uint64_t size) -> lldb::addr_t {
2598            if (!strcmp(name, ivar_name_cstr)) {
2599              ret = offset_addr;
2600              return true;
2601            }
2602            return false;
2603          };
2604
2605          descriptor->Describe(
2606              std::function<void(ObjCISA)>(nullptr),
2607              std::function<bool(const char *, const char *)>(nullptr),
2608              std::function<bool(const char *, const char *)>(nullptr),
2609              ivar_func);
2610        }
2611      }
2612    } else if (name_strref.startswith(class_prefix)) {
2613      llvm::StringRef class_skipped_prefix =
2614          name_strref.substr(class_prefix.size());
2615      const ConstString class_name_cs(class_skipped_prefix);
2616      ClassDescriptorSP descriptor =
2617          GetClassDescriptorFromClassName(class_name_cs);
2618
2619      if (descriptor)
2620        ret = descriptor->GetISA();
2621    }
2622  }
2623
2624  return ret;
2625}
2626
2627AppleObjCRuntimeV2::NonPointerISACache *
2628AppleObjCRuntimeV2::NonPointerISACache::CreateInstance(
2629    AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp) {
2630  Process *process(runtime.GetProcess());
2631
2632  Status error;
2633
2634  Log *log = GetLog(LLDBLog::Types);
2635
2636  auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(
2637      process, ConstString("objc_debug_isa_magic_mask"), objc_module_sp, error);
2638  if (error.Fail())
2639    return nullptr;
2640
2641  auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(
2642      process, ConstString("objc_debug_isa_magic_value"), objc_module_sp,
2643      error);
2644  if (error.Fail())
2645    return nullptr;
2646
2647  auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol(
2648      process, ConstString("objc_debug_isa_class_mask"), objc_module_sp, error);
2649  if (error.Fail())
2650    return nullptr;
2651
2652  if (log)
2653    log->PutCString("AOCRT::NPI: Found all the non-indexed ISA masks");
2654
2655  bool foundError = false;
2656  auto objc_debug_indexed_isa_magic_mask = ExtractRuntimeGlobalSymbol(
2657      process, ConstString("objc_debug_indexed_isa_magic_mask"), objc_module_sp,
2658      error);
2659  foundError |= error.Fail();
2660
2661  auto objc_debug_indexed_isa_magic_value = ExtractRuntimeGlobalSymbol(
2662      process, ConstString("objc_debug_indexed_isa_magic_value"),
2663      objc_module_sp, error);
2664  foundError |= error.Fail();
2665
2666  auto objc_debug_indexed_isa_index_mask = ExtractRuntimeGlobalSymbol(
2667      process, ConstString("objc_debug_indexed_isa_index_mask"), objc_module_sp,
2668      error);
2669  foundError |= error.Fail();
2670
2671  auto objc_debug_indexed_isa_index_shift = ExtractRuntimeGlobalSymbol(
2672      process, ConstString("objc_debug_indexed_isa_index_shift"),
2673      objc_module_sp, error);
2674  foundError |= error.Fail();
2675
2676  auto objc_indexed_classes =
2677      ExtractRuntimeGlobalSymbol(process, ConstString("objc_indexed_classes"),
2678                                 objc_module_sp, error, false);
2679  foundError |= error.Fail();
2680
2681  if (log)
2682    log->PutCString("AOCRT::NPI: Found all the indexed ISA masks");
2683
2684  // we might want to have some rules to outlaw these other values (e.g if the
2685  // mask is zero but the value is non-zero, ...)
2686
2687  return new NonPointerISACache(
2688      runtime, objc_module_sp, objc_debug_isa_class_mask,
2689      objc_debug_isa_magic_mask, objc_debug_isa_magic_value,
2690      objc_debug_indexed_isa_magic_mask, objc_debug_indexed_isa_magic_value,
2691      objc_debug_indexed_isa_index_mask, objc_debug_indexed_isa_index_shift,
2692      foundError ? 0 : objc_indexed_classes);
2693}
2694
2695AppleObjCRuntimeV2::TaggedPointerVendorV2 *
2696AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance(
2697    AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp) {
2698  Process *process(runtime.GetProcess());
2699
2700  Status error;
2701
2702  auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol(
2703      process, ConstString("objc_debug_taggedpointer_mask"), objc_module_sp,
2704      error);
2705  if (error.Fail())
2706    return new TaggedPointerVendorLegacy(runtime);
2707
2708  auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol(
2709      process, ConstString("objc_debug_taggedpointer_slot_shift"),
2710      objc_module_sp, error, true, 4);
2711  if (error.Fail())
2712    return new TaggedPointerVendorLegacy(runtime);
2713
2714  auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol(
2715      process, ConstString("objc_debug_taggedpointer_slot_mask"),
2716      objc_module_sp, error, true, 4);
2717  if (error.Fail())
2718    return new TaggedPointerVendorLegacy(runtime);
2719
2720  auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol(
2721      process, ConstString("objc_debug_taggedpointer_payload_lshift"),
2722      objc_module_sp, error, true, 4);
2723  if (error.Fail())
2724    return new TaggedPointerVendorLegacy(runtime);
2725
2726  auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol(
2727      process, ConstString("objc_debug_taggedpointer_payload_rshift"),
2728      objc_module_sp, error, true, 4);
2729  if (error.Fail())
2730    return new TaggedPointerVendorLegacy(runtime);
2731
2732  auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol(
2733      process, ConstString("objc_debug_taggedpointer_classes"), objc_module_sp,
2734      error, false);
2735  if (error.Fail())
2736    return new TaggedPointerVendorLegacy(runtime);
2737
2738  // try to detect the "extended tagged pointer" variables - if any are
2739  // missing, use the non-extended vendor
2740  do {
2741    auto objc_debug_taggedpointer_ext_mask = ExtractRuntimeGlobalSymbol(
2742        process, ConstString("objc_debug_taggedpointer_ext_mask"),
2743        objc_module_sp, error);
2744    if (error.Fail())
2745      break;
2746
2747    auto objc_debug_taggedpointer_ext_slot_shift = ExtractRuntimeGlobalSymbol(
2748        process, ConstString("objc_debug_taggedpointer_ext_slot_shift"),
2749        objc_module_sp, error, true, 4);
2750    if (error.Fail())
2751      break;
2752
2753    auto objc_debug_taggedpointer_ext_slot_mask = ExtractRuntimeGlobalSymbol(
2754        process, ConstString("objc_debug_taggedpointer_ext_slot_mask"),
2755        objc_module_sp, error, true, 4);
2756    if (error.Fail())
2757      break;
2758
2759    auto objc_debug_taggedpointer_ext_classes = ExtractRuntimeGlobalSymbol(
2760        process, ConstString("objc_debug_taggedpointer_ext_classes"),
2761        objc_module_sp, error, false);
2762    if (error.Fail())
2763      break;
2764
2765    auto objc_debug_taggedpointer_ext_payload_lshift =
2766        ExtractRuntimeGlobalSymbol(
2767            process, ConstString("objc_debug_taggedpointer_ext_payload_lshift"),
2768            objc_module_sp, error, true, 4);
2769    if (error.Fail())
2770      break;
2771
2772    auto objc_debug_taggedpointer_ext_payload_rshift =
2773        ExtractRuntimeGlobalSymbol(
2774            process, ConstString("objc_debug_taggedpointer_ext_payload_rshift"),
2775            objc_module_sp, error, true, 4);
2776    if (error.Fail())
2777      break;
2778
2779    return new TaggedPointerVendorExtended(
2780        runtime, objc_debug_taggedpointer_mask,
2781        objc_debug_taggedpointer_ext_mask, objc_debug_taggedpointer_slot_shift,
2782        objc_debug_taggedpointer_ext_slot_shift,
2783        objc_debug_taggedpointer_slot_mask,
2784        objc_debug_taggedpointer_ext_slot_mask,
2785        objc_debug_taggedpointer_payload_lshift,
2786        objc_debug_taggedpointer_payload_rshift,
2787        objc_debug_taggedpointer_ext_payload_lshift,
2788        objc_debug_taggedpointer_ext_payload_rshift,
2789        objc_debug_taggedpointer_classes, objc_debug_taggedpointer_ext_classes);
2790  } while (false);
2791
2792  // we might want to have some rules to outlaw these values (e.g if the
2793  // table's address is zero)
2794
2795  return new TaggedPointerVendorRuntimeAssisted(
2796      runtime, objc_debug_taggedpointer_mask,
2797      objc_debug_taggedpointer_slot_shift, objc_debug_taggedpointer_slot_mask,
2798      objc_debug_taggedpointer_payload_lshift,
2799      objc_debug_taggedpointer_payload_rshift,
2800      objc_debug_taggedpointer_classes);
2801}
2802
2803bool AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer(
2804    lldb::addr_t ptr) {
2805  return (ptr & 1);
2806}
2807
2808ObjCLanguageRuntime::ClassDescriptorSP
2809AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor(
2810    lldb::addr_t ptr) {
2811  if (!IsPossibleTaggedPointer(ptr))
2812    return ObjCLanguageRuntime::ClassDescriptorSP();
2813
2814  uint32_t foundation_version = m_runtime.GetFoundationVersion();
2815
2816  if (foundation_version == LLDB_INVALID_MODULE_VERSION)
2817    return ObjCLanguageRuntime::ClassDescriptorSP();
2818
2819  uint64_t class_bits = (ptr & 0xE) >> 1;
2820  ConstString name;
2821
2822  static ConstString g_NSAtom("NSAtom");
2823  static ConstString g_NSNumber("NSNumber");
2824  static ConstString g_NSDateTS("NSDateTS");
2825  static ConstString g_NSManagedObject("NSManagedObject");
2826  static ConstString g_NSDate("NSDate");
2827
2828  if (foundation_version >= 900) {
2829    switch (class_bits) {
2830    case 0:
2831      name = g_NSAtom;
2832      break;
2833    case 3:
2834      name = g_NSNumber;
2835      break;
2836    case 4:
2837      name = g_NSDateTS;
2838      break;
2839    case 5:
2840      name = g_NSManagedObject;
2841      break;
2842    case 6:
2843      name = g_NSDate;
2844      break;
2845    default:
2846      return ObjCLanguageRuntime::ClassDescriptorSP();
2847    }
2848  } else {
2849    switch (class_bits) {
2850    case 1:
2851      name = g_NSNumber;
2852      break;
2853    case 5:
2854      name = g_NSManagedObject;
2855      break;
2856    case 6:
2857      name = g_NSDate;
2858      break;
2859    case 7:
2860      name = g_NSDateTS;
2861      break;
2862    default:
2863      return ObjCLanguageRuntime::ClassDescriptorSP();
2864    }
2865  }
2866
2867  lldb::addr_t unobfuscated = ptr ^ m_runtime.GetTaggedPointerObfuscator();
2868  return ClassDescriptorSP(new ClassDescriptorV2Tagged(name, unobfuscated));
2869}
2870
2871AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::
2872    TaggedPointerVendorRuntimeAssisted(
2873        AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,
2874        uint32_t objc_debug_taggedpointer_slot_shift,
2875        uint32_t objc_debug_taggedpointer_slot_mask,
2876        uint32_t objc_debug_taggedpointer_payload_lshift,
2877        uint32_t objc_debug_taggedpointer_payload_rshift,
2878        lldb::addr_t objc_debug_taggedpointer_classes)
2879    : TaggedPointerVendorV2(runtime), m_cache(),
2880      m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask),
2881      m_objc_debug_taggedpointer_slot_shift(
2882          objc_debug_taggedpointer_slot_shift),
2883      m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask),
2884      m_objc_debug_taggedpointer_payload_lshift(
2885          objc_debug_taggedpointer_payload_lshift),
2886      m_objc_debug_taggedpointer_payload_rshift(
2887          objc_debug_taggedpointer_payload_rshift),
2888      m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes) {}
2889
2890bool AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::
2891    IsPossibleTaggedPointer(lldb::addr_t ptr) {
2892  return (ptr & m_objc_debug_taggedpointer_mask) != 0;
2893}
2894
2895ObjCLanguageRuntime::ClassDescriptorSP
2896AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(
2897    lldb::addr_t ptr) {
2898  ClassDescriptorSP actual_class_descriptor_sp;
2899  uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
2900
2901  if (!IsPossibleTaggedPointer(unobfuscated))
2902    return ObjCLanguageRuntime::ClassDescriptorSP();
2903
2904  uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) &
2905                   m_objc_debug_taggedpointer_slot_mask;
2906
2907  CacheIterator iterator = m_cache.find(slot), end = m_cache.end();
2908  if (iterator != end) {
2909    actual_class_descriptor_sp = iterator->second;
2910  } else {
2911    Process *process(m_runtime.GetProcess());
2912    uintptr_t slot_ptr = slot * process->GetAddressByteSize() +
2913                         m_objc_debug_taggedpointer_classes;
2914    Status error;
2915    uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
2916    if (error.Fail() || slot_data == 0 ||
2917        slot_data == uintptr_t(LLDB_INVALID_ADDRESS))
2918      return nullptr;
2919    actual_class_descriptor_sp =
2920        m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data);
2921    if (!actual_class_descriptor_sp) {
2922      if (ABISP abi_sp = process->GetABI()) {
2923        ObjCISA fixed_isa = abi_sp->FixCodeAddress((ObjCISA)slot_data);
2924        actual_class_descriptor_sp =
2925            m_runtime.GetClassDescriptorFromISA(fixed_isa);
2926      }
2927    }
2928    if (!actual_class_descriptor_sp)
2929      return ObjCLanguageRuntime::ClassDescriptorSP();
2930    m_cache[slot] = actual_class_descriptor_sp;
2931  }
2932
2933  uint64_t data_payload =
2934      ((unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >>
2935       m_objc_debug_taggedpointer_payload_rshift);
2936  int64_t data_payload_signed =
2937      ((int64_t)(unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >>
2938       m_objc_debug_taggedpointer_payload_rshift);
2939  return ClassDescriptorSP(new ClassDescriptorV2Tagged(
2940      actual_class_descriptor_sp, data_payload, data_payload_signed));
2941}
2942
2943AppleObjCRuntimeV2::TaggedPointerVendorExtended::TaggedPointerVendorExtended(
2944    AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask,
2945    uint64_t objc_debug_taggedpointer_ext_mask,
2946    uint32_t objc_debug_taggedpointer_slot_shift,
2947    uint32_t objc_debug_taggedpointer_ext_slot_shift,
2948    uint32_t objc_debug_taggedpointer_slot_mask,
2949    uint32_t objc_debug_taggedpointer_ext_slot_mask,
2950    uint32_t objc_debug_taggedpointer_payload_lshift,
2951    uint32_t objc_debug_taggedpointer_payload_rshift,
2952    uint32_t objc_debug_taggedpointer_ext_payload_lshift,
2953    uint32_t objc_debug_taggedpointer_ext_payload_rshift,
2954    lldb::addr_t objc_debug_taggedpointer_classes,
2955    lldb::addr_t objc_debug_taggedpointer_ext_classes)
2956    : TaggedPointerVendorRuntimeAssisted(
2957          runtime, objc_debug_taggedpointer_mask,
2958          objc_debug_taggedpointer_slot_shift,
2959          objc_debug_taggedpointer_slot_mask,
2960          objc_debug_taggedpointer_payload_lshift,
2961          objc_debug_taggedpointer_payload_rshift,
2962          objc_debug_taggedpointer_classes),
2963      m_ext_cache(),
2964      m_objc_debug_taggedpointer_ext_mask(objc_debug_taggedpointer_ext_mask),
2965      m_objc_debug_taggedpointer_ext_slot_shift(
2966          objc_debug_taggedpointer_ext_slot_shift),
2967      m_objc_debug_taggedpointer_ext_slot_mask(
2968          objc_debug_taggedpointer_ext_slot_mask),
2969      m_objc_debug_taggedpointer_ext_payload_lshift(
2970          objc_debug_taggedpointer_ext_payload_lshift),
2971      m_objc_debug_taggedpointer_ext_payload_rshift(
2972          objc_debug_taggedpointer_ext_payload_rshift),
2973      m_objc_debug_taggedpointer_ext_classes(
2974          objc_debug_taggedpointer_ext_classes) {}
2975
2976bool AppleObjCRuntimeV2::TaggedPointerVendorExtended::
2977    IsPossibleExtendedTaggedPointer(lldb::addr_t ptr) {
2978  if (!IsPossibleTaggedPointer(ptr))
2979    return false;
2980
2981  if (m_objc_debug_taggedpointer_ext_mask == 0)
2982    return false;
2983
2984  return ((ptr & m_objc_debug_taggedpointer_ext_mask) ==
2985          m_objc_debug_taggedpointer_ext_mask);
2986}
2987
2988ObjCLanguageRuntime::ClassDescriptorSP
2989AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor(
2990    lldb::addr_t ptr) {
2991  ClassDescriptorSP actual_class_descriptor_sp;
2992  uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
2993
2994  if (!IsPossibleTaggedPointer(unobfuscated))
2995    return ObjCLanguageRuntime::ClassDescriptorSP();
2996
2997  if (!IsPossibleExtendedTaggedPointer(unobfuscated))
2998    return this->TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(ptr);
2999
3000  uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_ext_slot_shift) &
3001                   m_objc_debug_taggedpointer_ext_slot_mask;
3002
3003  CacheIterator iterator = m_ext_cache.find(slot), end = m_ext_cache.end();
3004  if (iterator != end) {
3005    actual_class_descriptor_sp = iterator->second;
3006  } else {
3007    Process *process(m_runtime.GetProcess());
3008    uintptr_t slot_ptr = slot * process->GetAddressByteSize() +
3009                         m_objc_debug_taggedpointer_ext_classes;
3010    Status error;
3011    uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error);
3012    if (error.Fail() || slot_data == 0 ||
3013        slot_data == uintptr_t(LLDB_INVALID_ADDRESS))
3014      return nullptr;
3015    actual_class_descriptor_sp =
3016        m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data);
3017    if (!actual_class_descriptor_sp)
3018      return ObjCLanguageRuntime::ClassDescriptorSP();
3019    m_ext_cache[slot] = actual_class_descriptor_sp;
3020  }
3021
3022  uint64_t data_payload = (((uint64_t)unobfuscated
3023                            << m_objc_debug_taggedpointer_ext_payload_lshift) >>
3024                           m_objc_debug_taggedpointer_ext_payload_rshift);
3025  int64_t data_payload_signed =
3026      ((int64_t)((int64_t)unobfuscated
3027                 << m_objc_debug_taggedpointer_ext_payload_lshift) >>
3028       m_objc_debug_taggedpointer_ext_payload_rshift);
3029
3030  return ClassDescriptorSP(new ClassDescriptorV2Tagged(
3031      actual_class_descriptor_sp, data_payload, data_payload_signed));
3032}
3033
3034AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache(
3035    AppleObjCRuntimeV2 &runtime, const ModuleSP &objc_module_sp,
3036    uint64_t objc_debug_isa_class_mask, uint64_t objc_debug_isa_magic_mask,
3037    uint64_t objc_debug_isa_magic_value,
3038    uint64_t objc_debug_indexed_isa_magic_mask,
3039    uint64_t objc_debug_indexed_isa_magic_value,
3040    uint64_t objc_debug_indexed_isa_index_mask,
3041    uint64_t objc_debug_indexed_isa_index_shift,
3042    lldb::addr_t objc_indexed_classes)
3043    : m_runtime(runtime), m_cache(), m_objc_module_wp(objc_module_sp),
3044      m_objc_debug_isa_class_mask(objc_debug_isa_class_mask),
3045      m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask),
3046      m_objc_debug_isa_magic_value(objc_debug_isa_magic_value),
3047      m_objc_debug_indexed_isa_magic_mask(objc_debug_indexed_isa_magic_mask),
3048      m_objc_debug_indexed_isa_magic_value(objc_debug_indexed_isa_magic_value),
3049      m_objc_debug_indexed_isa_index_mask(objc_debug_indexed_isa_index_mask),
3050      m_objc_debug_indexed_isa_index_shift(objc_debug_indexed_isa_index_shift),
3051      m_objc_indexed_classes(objc_indexed_classes), m_indexed_isa_cache() {}
3052
3053ObjCLanguageRuntime::ClassDescriptorSP
3054AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor(ObjCISA isa) {
3055  ObjCISA real_isa = 0;
3056  if (!EvaluateNonPointerISA(isa, real_isa))
3057    return ObjCLanguageRuntime::ClassDescriptorSP();
3058  auto cache_iter = m_cache.find(real_isa);
3059  if (cache_iter != m_cache.end())
3060    return cache_iter->second;
3061  auto descriptor_sp =
3062      m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa);
3063  if (descriptor_sp) // cache only positive matches since the table might grow
3064    m_cache[real_isa] = descriptor_sp;
3065  return descriptor_sp;
3066}
3067
3068bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA(
3069    ObjCISA isa, ObjCISA &ret_isa) {
3070  Log *log = GetLog(LLDBLog::Types);
3071
3072  LLDB_LOGF(log, "AOCRT::NPI Evaluate(isa = 0x%" PRIx64 ")", (uint64_t)isa);
3073
3074  if ((isa & ~m_objc_debug_isa_class_mask) == 0)
3075    return false;
3076
3077  // If all of the indexed ISA variables are set, then its possible that this
3078  // ISA is indexed, and we should first try to get its value using the index.
3079  // Note, we check these variables first as the ObjC runtime will set at least
3080  // one of their values to 0 if they aren't needed.
3081  if (m_objc_debug_indexed_isa_magic_mask &&
3082      m_objc_debug_indexed_isa_magic_value &&
3083      m_objc_debug_indexed_isa_index_mask &&
3084      m_objc_debug_indexed_isa_index_shift && m_objc_indexed_classes) {
3085    if ((isa & ~m_objc_debug_indexed_isa_index_mask) == 0)
3086      return false;
3087
3088    if ((isa & m_objc_debug_indexed_isa_magic_mask) ==
3089        m_objc_debug_indexed_isa_magic_value) {
3090      // Magic bits are correct, so try extract the index.
3091      uintptr_t index = (isa & m_objc_debug_indexed_isa_index_mask) >>
3092                        m_objc_debug_indexed_isa_index_shift;
3093      // If the index is out of bounds of the length of the array then check if
3094      // the array has been updated.  If that is the case then we should try
3095      // read the count again, and update the cache if the count has been
3096      // updated.
3097      if (index > m_indexed_isa_cache.size()) {
3098        LLDB_LOGF(log,
3099                  "AOCRT::NPI (index = %" PRIu64
3100                  ") exceeds cache (size = %" PRIu64 ")",
3101                  (uint64_t)index, (uint64_t)m_indexed_isa_cache.size());
3102
3103        Process *process(m_runtime.GetProcess());
3104
3105        ModuleSP objc_module_sp(m_objc_module_wp.lock());
3106        if (!objc_module_sp)
3107          return false;
3108
3109        Status error;
3110        auto objc_indexed_classes_count = ExtractRuntimeGlobalSymbol(
3111            process, ConstString("objc_indexed_classes_count"), objc_module_sp,
3112            error);
3113        if (error.Fail())
3114          return false;
3115
3116        LLDB_LOGF(log, "AOCRT::NPI (new class count = %" PRIu64 ")",
3117                  (uint64_t)objc_indexed_classes_count);
3118
3119        if (objc_indexed_classes_count > m_indexed_isa_cache.size()) {
3120          // Read the class entries we don't have.  We should just read all of
3121          // them instead of just the one we need as then we can cache those we
3122          // may need later.
3123          auto num_new_classes =
3124              objc_indexed_classes_count - m_indexed_isa_cache.size();
3125          const uint32_t addr_size = process->GetAddressByteSize();
3126          DataBufferHeap buffer(num_new_classes * addr_size, 0);
3127
3128          lldb::addr_t last_read_class =
3129              m_objc_indexed_classes + (m_indexed_isa_cache.size() * addr_size);
3130          size_t bytes_read = process->ReadMemory(
3131              last_read_class, buffer.GetBytes(), buffer.GetByteSize(), error);
3132          if (error.Fail() || bytes_read != buffer.GetByteSize())
3133            return false;
3134
3135          LLDB_LOGF(log, "AOCRT::NPI (read new classes count = %" PRIu64 ")",
3136                    (uint64_t)num_new_classes);
3137
3138          // Append the new entries to the existing cache.
3139          DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(),
3140                             process->GetByteOrder(),
3141                             process->GetAddressByteSize());
3142
3143          lldb::offset_t offset = 0;
3144          for (unsigned i = 0; i != num_new_classes; ++i)
3145            m_indexed_isa_cache.push_back(data.GetAddress(&offset));
3146        }
3147      }
3148
3149      // If the index is still out of range then this isn't a pointer.
3150      if (index > m_indexed_isa_cache.size())
3151        return false;
3152
3153      LLDB_LOGF(log, "AOCRT::NPI Evaluate(ret_isa = 0x%" PRIx64 ")",
3154                (uint64_t)m_indexed_isa_cache[index]);
3155
3156      ret_isa = m_indexed_isa_cache[index];
3157      return (ret_isa != 0); // this is a pointer so 0 is not a valid value
3158    }
3159
3160    return false;
3161  }
3162
3163  // Definitely not an indexed ISA, so try to use a mask to extract the pointer
3164  // from the ISA.
3165  if ((isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value) {
3166    ret_isa = isa & m_objc_debug_isa_class_mask;
3167    return (ret_isa != 0); // this is a pointer so 0 is not a valid value
3168  }
3169  return false;
3170}
3171
3172ObjCLanguageRuntime::EncodingToTypeSP AppleObjCRuntimeV2::GetEncodingToType() {
3173  if (!m_encoding_to_type_sp)
3174    m_encoding_to_type_sp =
3175        std::make_shared<AppleObjCTypeEncodingParser>(*this);
3176  return m_encoding_to_type_sp;
3177}
3178
3179lldb_private::AppleObjCRuntime::ObjCISA
3180AppleObjCRuntimeV2::GetPointerISA(ObjCISA isa) {
3181  ObjCISA ret = isa;
3182
3183  if (auto *non_pointer_isa_cache = GetNonPointerIsaCache())
3184    non_pointer_isa_cache->EvaluateNonPointerISA(isa, ret);
3185
3186  return ret;
3187}
3188
3189bool AppleObjCRuntimeV2::GetCFBooleanValuesIfNeeded() {
3190  if (m_CFBoolean_values)
3191    return true;
3192
3193  static ConstString g_dunder_kCFBooleanFalse("__kCFBooleanFalse");
3194  static ConstString g_dunder_kCFBooleanTrue("__kCFBooleanTrue");
3195  static ConstString g_kCFBooleanFalse("kCFBooleanFalse");
3196  static ConstString g_kCFBooleanTrue("kCFBooleanTrue");
3197
3198  std::function<lldb::addr_t(ConstString, ConstString)> get_symbol =
3199      [this](ConstString sym, ConstString real_sym) -> lldb::addr_t {
3200    SymbolContextList sc_list;
3201    GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType(
3202        sym, lldb::eSymbolTypeData, sc_list);
3203    if (sc_list.GetSize() == 1) {
3204      SymbolContext sc;
3205      sc_list.GetContextAtIndex(0, sc);
3206      if (sc.symbol)
3207        return sc.symbol->GetLoadAddress(&GetProcess()->GetTarget());
3208    }
3209    GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType(
3210        real_sym, lldb::eSymbolTypeData, sc_list);
3211    if (sc_list.GetSize() != 1)
3212      return LLDB_INVALID_ADDRESS;
3213
3214    SymbolContext sc;
3215    sc_list.GetContextAtIndex(0, sc);
3216    if (!sc.symbol)
3217      return LLDB_INVALID_ADDRESS;
3218
3219    lldb::addr_t addr = sc.symbol->GetLoadAddress(&GetProcess()->GetTarget());
3220    Status error;
3221    addr = GetProcess()->ReadPointerFromMemory(addr, error);
3222    if (error.Fail())
3223      return LLDB_INVALID_ADDRESS;
3224    return addr;
3225  };
3226
3227  lldb::addr_t false_addr = get_symbol(g_dunder_kCFBooleanFalse, g_kCFBooleanFalse);
3228  lldb::addr_t true_addr = get_symbol(g_dunder_kCFBooleanTrue, g_kCFBooleanTrue);
3229
3230  return (m_CFBoolean_values = {false_addr, true_addr}).operator bool();
3231}
3232
3233void AppleObjCRuntimeV2::GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true,
3234                                                      lldb::addr_t &cf_false) {
3235  if (GetCFBooleanValuesIfNeeded()) {
3236    cf_true = m_CFBoolean_values->second;
3237    cf_false = m_CFBoolean_values->first;
3238  } else
3239    this->AppleObjCRuntime::GetValuesForGlobalCFBooleans(cf_true, cf_false);
3240}
3241
3242#pragma mark Frame recognizers
3243
3244class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame {
3245public:
3246  ObjCExceptionRecognizedStackFrame(StackFrameSP frame_sp) {
3247    ThreadSP thread_sp = frame_sp->GetThread();
3248    ProcessSP process_sp = thread_sp->GetProcess();
3249
3250    const lldb::ABISP &abi = process_sp->GetABI();
3251    if (!abi)
3252      return;
3253
3254    TypeSystemClangSP scratch_ts_sp =
3255        ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget());
3256    if (!scratch_ts_sp)
3257      return;
3258    CompilerType voidstar =
3259        scratch_ts_sp->GetBasicType(lldb::eBasicTypeVoid).GetPointerType();
3260
3261    ValueList args;
3262    Value input_value;
3263    input_value.SetCompilerType(voidstar);
3264    args.PushValue(input_value);
3265
3266    if (!abi->GetArgumentValues(*thread_sp, args))
3267      return;
3268
3269    addr_t exception_addr = args.GetValueAtIndex(0)->GetScalar().ULongLong();
3270
3271    Value value(exception_addr);
3272    value.SetCompilerType(voidstar);
3273    exception = ValueObjectConstResult::Create(frame_sp.get(), value,
3274                                               ConstString("exception"));
3275    exception = ValueObjectRecognizerSynthesizedValue::Create(
3276        *exception, eValueTypeVariableArgument);
3277    exception = exception->GetDynamicValue(eDynamicDontRunTarget);
3278
3279    m_arguments = ValueObjectListSP(new ValueObjectList());
3280    m_arguments->Append(exception);
3281
3282    m_stop_desc = "hit Objective-C exception";
3283  }
3284
3285  ValueObjectSP exception;
3286
3287  lldb::ValueObjectSP GetExceptionObject() override { return exception; }
3288};
3289
3290class ObjCExceptionThrowFrameRecognizer : public StackFrameRecognizer {
3291  lldb::RecognizedStackFrameSP
3292  RecognizeFrame(lldb::StackFrameSP frame) override {
3293    return lldb::RecognizedStackFrameSP(
3294        new ObjCExceptionRecognizedStackFrame(frame));
3295  };
3296  std::string GetName() override {
3297    return "ObjC Exception Throw StackFrame Recognizer";
3298  }
3299};
3300
3301static void RegisterObjCExceptionRecognizer(Process *process) {
3302  FileSpec module;
3303  ConstString function;
3304  std::tie(module, function) = AppleObjCRuntime::GetExceptionThrowLocation();
3305  std::vector<ConstString> symbols = {function};
3306
3307  process->GetTarget().GetFrameRecognizerManager().AddRecognizer(
3308      StackFrameRecognizerSP(new ObjCExceptionThrowFrameRecognizer()),
3309      module.GetFilename(), symbols,
3310      /*first_instruction_only*/ true);
3311}
3312