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