Coverage Report

Created: 2022-01-15 10:30

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