15 #include "clang/AST/ASTContext.h"
16 #include "clang/AST/DeclObjC.h"
66 #include "clang/AST/ASTContext.h"
67 #include "clang/AST/DeclObjC.h"
68 #include "clang/Basic/TargetInfo.h"
80 "__lldb_apple_objc_v2_get_dynamic_class_info";
86 size_t strlen(const char *);
87 char *strncpy (char * s1, const char * s2, size_t n);
88 int printf(const char * format, ...);
90 #define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__)
92 typedef struct _NXMapTable {
95 unsigned num_buckets_minus_one;
99 #define NX_MAPNOTAKEY ((void *)(-1))
101 typedef struct BucketInfo
103 const char *name_ptr;
111 } __attribute__((__packed__));
114 __lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr,
115 void *class_infos_ptr,
116 uint32_t class_infos_byte_size,
119 DEBUG_PRINTF ("gdb_objc_realized_classes_ptr = %p\n", gdb_objc_realized_classes_ptr);
120 DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
121 DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size);
122 const NXMapTable *grc = (const NXMapTable *)gdb_objc_realized_classes_ptr;
125 const unsigned num_classes = grc->num_classes;
126 DEBUG_PRINTF ("num_classes = %u\n", grc->num_classes);
129 const unsigned num_buckets_minus_one = grc->num_buckets_minus_one;
130 DEBUG_PRINTF ("num_buckets_minus_one = %u\n", num_buckets_minus_one);
132 const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
133 DEBUG_PRINTF ("max_class_infos = %u\n", max_class_infos);
135 ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
136 BucketInfo *buckets = (BucketInfo *)grc->buckets;
139 for (unsigned i=0; i<=num_buckets_minus_one; ++i)
141 if (buckets[i].name_ptr != NX_MAPNOTAKEY)
143 if (idx < max_class_infos)
145 const char *s = buckets[i].name_ptr;
147 for (unsigned char c = *s; c; c = *++s)
148 h = ((h << 5) + h) + c;
149 class_infos[idx].hash = h;
150 class_infos[idx].isa = buckets[i].isa;
151 DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, buckets[i].name_ptr);
156 if (idx < max_class_infos)
158 class_infos[idx].isa = NULL;
159 class_infos[idx].hash = 0;
170 "__lldb_apple_objc_v2_get_dynamic_class_info2";
175 int printf(const char * format, ...);
176 void free(void *ptr);
177 Class* objc_copyRealizedClassList_nolock(unsigned int *outCount);
178 const char* objc_debug_class_getNameRaw(Class cls);
181 #define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__)
187 } __attribute__((__packed__));
190 __lldb_apple_objc_v2_get_dynamic_class_info2(void *gdb_objc_realized_classes_ptr,
191 void *class_infos_ptr,
192 uint32_t class_infos_byte_size,
195 DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
196 DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size);
198 const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
199 DEBUG_PRINTF ("max_class_infos = %u\n", max_class_infos);
201 ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
204 Class* realized_class_list = objc_copyRealizedClassList_nolock(&count);
205 DEBUG_PRINTF ("count = %u\n", count);
208 for (uint32_t i=0; i<=count; ++i)
210 if (idx < max_class_infos)
212 Class isa = realized_class_list[i];
213 const char *name_ptr = objc_debug_class_getNameRaw(isa);
214 if (name_ptr == NULL)
216 const char *s = name_ptr;
218 for (unsigned char c = *s; c; c = *++s)
219 h = ((h << 5) + h) + c;
220 class_infos[idx].hash = h;
221 class_infos[idx].isa = isa;
222 DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name_ptr);
227 if (idx < max_class_infos)
229 class_infos[idx].isa = NULL;
230 class_infos[idx].hash = 0;
233 free(realized_class_list);
243 const char *%s(void *objc_class);
244 const char *(*class_name_lookup_func)(void *) = %s;
249 "__lldb_apple_objc_v2_get_shared_cache_class_info";
255 size_t strlen(const char *);
256 char *strncpy (char * s1, const char * s2, size_t n);
257 int printf(const char * format, ...);
260 #define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__)
263 struct objc_classheader_t {
268 struct objc_classheader_v16_t {
269 uint64_t isDuplicate : 1,
270 objectCacheOffset : 47, // Offset from the shared cache base
274 struct objc_clsopt_t {
282 uint32_t scramble[256];
283 uint8_t tab[0]; // tab[mask+1]
284 // uint8_t checkbytes[capacity];
285 // int32_t offset[capacity];
286 // objc_classheader_t clsOffsets[capacity];
287 // uint32_t duplicateCount;
288 // objc_classheader_t duplicateOffsets[duplicateCount];
291 struct objc_clsopt_v16_t {
299 uint32_t scramble[256];
300 uint8_t tab[0]; // tab[mask+1]
301 // uint8_t checkbytes[capacity];
302 // int32_t offset[capacity];
303 // objc_classheader_t clsOffsets[capacity];
304 // uint32_t duplicateCount;
305 // objc_classheader_t duplicateOffsets[duplicateCount];
310 int32_t selopt_offset;
311 int32_t headeropt_offset;
312 int32_t clsopt_offset;
315 struct objc_opt_v14_t {
318 int32_t selopt_offset;
319 int32_t headeropt_offset;
320 int32_t clsopt_offset;
323 struct objc_opt_v16_t {
326 int32_t selopt_offset;
327 int32_t headeropt_ro_offset;
328 int32_t unused_clsopt_offset;
329 int32_t unused_protocolopt_offset;
330 int32_t headeropt_rw_offset;
331 int32_t unused_protocolopt2_offset;
332 int32_t largeSharedCachesClassOffset;
333 int32_t largeSharedCachesProtocolOffset;
334 uint64_t relativeMethodSelectorBaseAddressCacheOffset;
341 } __attribute__((__packed__));
344 __lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr,
345 void *shared_cache_base_ptr,
346 void *class_infos_ptr,
347 uint64_t *relative_selector_offset,
348 uint32_t class_infos_byte_size,
351 *relative_selector_offset = 0;
353 DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr);
354 DEBUG_PRINTF ("shared_cache_base_ptr = %p\n", shared_cache_base_ptr);
355 DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr);
356 DEBUG_PRINTF ("class_infos_byte_size = %u (%llu class infos)\n", class_infos_byte_size, (uint64_t)(class_infos_byte_size/sizeof(ClassInfo)));
359 const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr;
360 const objc_opt_v14_t* objc_opt_v14 = (objc_opt_v14_t*)objc_opt_ro_ptr;
361 const objc_opt_v16_t* objc_opt_v16 = (objc_opt_v16_t*)objc_opt_ro_ptr;
362 if (objc_opt->version >= 16)
364 *relative_selector_offset = objc_opt_v16->relativeMethodSelectorBaseAddressCacheOffset;
365 DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v16->version);
366 DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v16->flags);
367 DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt_v16->selopt_offset);
368 DEBUG_PRINTF ("objc_opt->headeropt_ro_offset = %d\n", objc_opt_v16->headeropt_ro_offset);
369 DEBUG_PRINTF ("objc_opt->relativeMethodSelectorBaseAddressCacheOffset = %d\n", *relative_selector_offset);
371 else if (objc_opt->version >= 14)
373 DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v14->version);
374 DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v14->flags);
375 DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt_v14->selopt_offset);
376 DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt_v14->headeropt_offset);
377 DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt_v14->clsopt_offset);
381 DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt->version);
382 DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt->selopt_offset);
383 DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset);
384 DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset);
387 if (objc_opt->version == 16)
389 const objc_clsopt_v16_t* clsopt = (const objc_clsopt_v16_t*)((uint8_t *)objc_opt + objc_opt_v16->largeSharedCachesClassOffset);
390 const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
392 DEBUG_PRINTF("max_class_infos = %llu\n", (uint64_t)max_class_infos);
394 ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
396 const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1];
397 const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity);
398 const objc_classheader_v16_t *classOffsets = (const objc_classheader_v16_t *)(offsets + clsopt->capacity);
400 DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity);
401 DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask);
402 DEBUG_PRINTF ("classOffsets = %p\n", classOffsets);
404 for (uint32_t i=0; i<clsopt->capacity; ++i)
406 const uint64_t objectCacheOffset = classOffsets[i].objectCacheOffset;
407 DEBUG_PRINTF("objectCacheOffset[%u] = %u\n", i, objectCacheOffset);
409 if (classOffsets[i].isDuplicate) {
410 DEBUG_PRINTF("isDuplicate = true\n");
411 continue; // duplicate
414 if (objectCacheOffset == 0) {
415 DEBUG_PRINTF("objectCacheOffset == invalidEntryOffset\n");
416 continue; // invalid offset
419 if (class_infos && idx < max_class_infos)
421 class_infos[idx].isa = (Class)((uint8_t *)shared_cache_base_ptr + objectCacheOffset);
423 // Lookup the class name.
424 const char *name = class_name_lookup_func(class_infos[idx].isa);
425 DEBUG_PRINTF("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
427 // Hash the class name so we don't have to read it.
428 const char *s = name;
430 for (unsigned char c = *s; c; c = *++s)
432 // class_getName demangles swift names and the hash must
433 // be calculated on the mangled name. hash==0 means lldb
434 // will fetch the mangled name and compute the hash in
435 // ParseClassInfoArray.
441 h = ((h << 5) + h) + c;
443 class_infos[idx].hash = h;
447 DEBUG_PRINTF("not(class_infos && idx < max_class_infos)\n");
452 const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
453 const uint32_t duplicate_count = *duplicate_count_ptr;
454 const objc_classheader_v16_t *duplicateClassOffsets = (const objc_classheader_v16_t *)(&duplicate_count_ptr[1]);
456 DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count);
457 DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets);
459 for (uint32_t i=0; i<duplicate_count; ++i)
461 const uint64_t objectCacheOffset = classOffsets[i].objectCacheOffset;
462 DEBUG_PRINTF("objectCacheOffset[%u] = %u\n", i, objectCacheOffset);
464 if (classOffsets[i].isDuplicate) {
465 DEBUG_PRINTF("isDuplicate = true\n");
466 continue; // duplicate
469 if (objectCacheOffset == 0) {
470 DEBUG_PRINTF("objectCacheOffset == invalidEntryOffset\n");
471 continue; // invalid offset
474 if (class_infos && idx < max_class_infos)
476 class_infos[idx].isa = (Class)((uint8_t *)shared_cache_base_ptr + objectCacheOffset);
478 // Lookup the class name.
479 const char *name = class_name_lookup_func(class_infos[idx].isa);
480 DEBUG_PRINTF("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
482 // Hash the class name so we don't have to read it.
483 const char *s = name;
485 for (unsigned char c = *s; c; c = *++s)
487 // class_getName demangles swift names and the hash must
488 // be calculated on the mangled name. hash==0 means lldb
489 // will fetch the mangled name and compute the hash in
490 // ParseClassInfoArray.
496 h = ((h << 5) + h) + c;
498 class_infos[idx].hash = h;
502 else if (objc_opt->version >= 12 && objc_opt->version <= 15)
504 const objc_clsopt_t* clsopt = NULL;
505 if (objc_opt->version >= 14)
506 clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt_v14 + objc_opt_v14->clsopt_offset);
508 clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset);
509 const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo);
510 DEBUG_PRINTF("max_class_infos = %llu\n", (uint64_t)max_class_infos);
511 ClassInfo *class_infos = (ClassInfo *)class_infos_ptr;
512 int32_t invalidEntryOffset = 0;
513 // this is safe to do because the version field order is invariant
514 if (objc_opt->version == 12)
515 invalidEntryOffset = 16;
516 const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1];
517 const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity);
518 const objc_classheader_t *classOffsets = (const objc_classheader_t *)(offsets + clsopt->capacity);
519 DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity);
520 DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask);
521 DEBUG_PRINTF ("classOffsets = %p\n", classOffsets);
522 DEBUG_PRINTF("invalidEntryOffset = %d\n", invalidEntryOffset);
523 for (uint32_t i=0; i<clsopt->capacity; ++i)
525 const int32_t clsOffset = classOffsets[i].clsOffset;
526 DEBUG_PRINTF("clsOffset[%u] = %u\n", i, clsOffset);
529 DEBUG_PRINTF("clsOffset & 1\n");
530 continue; // duplicate
532 else if (clsOffset == invalidEntryOffset)
534 DEBUG_PRINTF("clsOffset == invalidEntryOffset\n");
535 continue; // invalid offset
538 if (class_infos && idx < max_class_infos)
540 class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
541 const char *name = class_name_lookup_func (class_infos[idx].isa);
542 DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
543 // Hash the class name so we don't have to read it
544 const char *s = name;
546 for (unsigned char c = *s; c; c = *++s)
548 // class_getName demangles swift names and the hash must
549 // be calculated on the mangled name. hash==0 means lldb
550 // will fetch the mangled name and compute the hash in
551 // ParseClassInfoArray.
557 h = ((h << 5) + h) + c;
559 class_infos[idx].hash = h;
563 DEBUG_PRINTF("not(class_infos && idx < max_class_infos)\n");
568 const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity];
569 const uint32_t duplicate_count = *duplicate_count_ptr;
570 const objc_classheader_t *duplicateClassOffsets = (const objc_classheader_t *)(&duplicate_count_ptr[1]);
571 DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count);
572 DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets);
573 for (uint32_t i=0; i<duplicate_count; ++i)
575 const int32_t clsOffset = duplicateClassOffsets[i].clsOffset;
577 continue; // duplicate
578 else if (clsOffset == invalidEntryOffset)
579 continue; // invalid offset
581 if (class_infos && idx < max_class_infos)
583 class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset);
584 const char *name = class_name_lookup_func (class_infos[idx].isa);
585 DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name);
586 // Hash the class name so we don't have to read it
587 const char *s = name;
589 for (unsigned char c = *s; c; c = *++s)
591 // class_getName demangles swift names and the hash must
592 // be calculated on the mangled name. hash==0 means lldb
593 // will fetch the mangled name and compute the hash in
594 // ParseClassInfoArray.
600 h = ((h << 5) + h) + c;
602 class_infos[idx].hash = h;
607 DEBUG_PRINTF ("%u class_infos\n", idx);
608 DEBUG_PRINTF ("done\n");
619 bool read_value =
true, uint8_t byte_size = 0,
623 error.SetErrorString(
"no process");
624 return default_value;
628 error.SetErrorString(
"no module");
629 return default_value;
638 error.SetErrorString(
"no symbol");
639 return default_value;
645 error.SetErrorString(
"symbol address invalid");
646 return default_value;
651 default_value,
error);
652 return symbol_load_addr;
657 AppleObjCRuntimeV2::AppleObjCRuntimeV2(
Process *process,
658 const ModuleSP &objc_module_sp)
660 m_dynamic_class_info_extractor(*this),
661 m_shared_cache_class_info_extractor(*this), m_decl_vendor_up(),
665 m_has_object_getClass(false), m_has_objc_copyRealizedClassList(false),
666 m_loaded_objc_opt(false), m_non_pointer_isa_cache_up(),
667 m_tagged_pointer_vendor_up(
669 m_encoding_to_type_sp(), m_CFBoolean_values(),
670 m_realized_class_generation_count(0) {
671 static const ConstString g_gdb_object_getClass(
"gdb_object_getClass");
673 static const ConstString g_objc_copyRealizedClassList(
674 "_ZL33objc_copyRealizedClassList_nolockPj");
698 class_type_or_name.
Clear();
710 ConstString class_name(objc_class_sp->GetClassName());
711 class_type_or_name.
SetName(class_name);
712 TypeSP type_sp(objc_class_sp->GetType());
718 objc_class_sp->SetType(type_sp);
723 auto types = vendor->FindTypes(class_name, 1);
731 return !class_type_or_name.
IsEmpty();
741 ModuleSP objc_module_sp;
761 "Print ivar and method information in detail"}};
774 const int short_option = m_getopt_table[option_idx].val;
775 switch (short_option) {
777 m_verbose.SetCurrentValue(
true);
778 m_verbose.SetOptionWasSet();
782 error.SetErrorStringWithFormat(
"unrecognized short option '%c'",
803 "Dump information on Objective-C classes "
804 "known to the current process.",
805 "language objc class-table dump",
806 eCommandRequiresProcess |
807 eCommandProcessMustBeLaunched |
808 eCommandProcessMustBePaused),
819 arg.push_back(index_arg);
822 m_arguments.push_back(arg);
831 std::unique_ptr<RegularExpression> regex_up;
838 if (!regex_up->IsValid()) {
840 "invalid argument - please provide a valid regular expression");
847 result.
AppendError(
"please provide 0 or 1 arguments");
853 Process *process = m_exe_ctx.GetProcessPtr();
857 auto iterator = iterators_pair.first;
859 for (; iterator != iterators_pair.second; iterator++) {
860 if (iterator->second) {
861 const char *class_name =
862 iterator->second->GetClassName().AsCString(
"<unknown>");
863 if (regex_up && class_name &&
864 !regex_up->Execute(llvm::StringRef(class_name)))
866 std_out.
Printf(
"isa = 0x%" PRIx64, iterator->first);
867 std_out.Printf(
" name = %s", class_name);
868 std_out.Printf(
" instance size = %" PRIu64,
869 iterator->second->GetInstanceSize());
870 std_out.Printf(
" num ivars = %" PRIuPTR,
871 (uintptr_t)iterator->second->GetNumIVars());
872 if (
auto superclass = iterator->second->GetSuperclass()) {
873 std_out.Printf(
" superclass = %s",
874 superclass->GetClassName().AsCString(
"<unknown>"));
876 std_out.Printf(
"\n");
877 if (m_options.m_verbose) {
878 for (
size_t i = 0; i < iterator->second->GetNumIVars(); i++) {
879 auto ivar = iterator->second->GetIVarAtIndex(i);
881 " ivar name = %s type = %s size = %" PRIu64
882 " offset = %" PRId32
"\n",
883 ivar.m_name.AsCString(
"<unknown>"),
884 ivar.m_type.GetDisplayTypeName().AsCString(
"<unknown>"),
885 ivar.m_size, ivar.m_offset);
888 iterator->second->Describe(
890 [&std_out](
const char *name,
const char *type) ->
bool {
891 std_out.Printf(
" instance method name = %s type = %s\n",
895 [&std_out](
const char *name,
const char *type) ->
bool {
896 std_out.Printf(
" class method name = %s type = %s\n", name,
903 if (regex_up && !regex_up->Execute(llvm::StringRef()))
905 std_out.Printf(
"isa = 0x%" PRIx64
" has no associated class.\n",
912 result.
AppendError(
"current process has no Objective-C runtime loaded");
925 interpreter,
"info",
"Dump information on a tagged pointer.",
926 "language objc tagged-pointer info",
927 eCommandRequiresProcess | eCommandProcessMustBeLaunched |
928 eCommandProcessMustBePaused) {
938 arg.push_back(index_arg);
941 m_arguments.push_back(arg);
949 result.
AppendError(
"this command requires arguments");
954 Process *process = m_exe_ctx.GetProcessPtr();
959 result.
AppendError(
"current process has no Objective-C runtime loaded");
966 if (!tagged_ptr_vendor) {
967 result.
AppendError(
"current process has no tagged pointer support");
982 "could not convert '{0}' to a valid address\n", arg_str);
993 if (!descriptor_sp) {
995 "could not get class descriptor for {0:x16}\n", arg_addr);
1000 uint64_t info_bits = 0;
1001 uint64_t value_bits = 0;
1002 uint64_t payload = 0;
1003 if (descriptor_sp->GetTaggedPointerInfo(&info_bits, &value_bits,
1007 "\tpayload = {1:x16}\n"
1008 "\tvalue = {2:x16}\n"
1009 "\tinfo bits = {3:x16}\n"
1011 arg_addr, payload, value_bits, info_bits,
1012 descriptor_sp->GetClassName().AsCString(
"<unknown>"));
1027 interpreter,
"class-table",
1028 "Commands for operating on the Objective-C class table.",
1029 "class-table <subcommand> [<subcommand-options>]") {
1042 interpreter,
"tagged-pointer",
1043 "Commands for operating on Objective-C tagged pointers.",
1044 "class-table <subcommand> [<subcommand-options>]") {
1058 interpreter,
"objc",
1059 "Commands for operating on the Objective-C language runtime.",
1060 "objc <subcommand> [<subcommand-options>]") {
1061 LoadSubCommand(
"class-table",
1064 LoadSubCommand(
"tagged-pointer",
1086 BreakpointResolverSP
1088 bool catch_bp,
bool throw_bp) {
1089 BreakpointResolverSP resolver_sp;
1092 resolver_sp = std::make_shared<BreakpointResolverName>(
1102 llvm::Expected<std::unique_ptr<UtilityFunction>>
1105 char check_function_code[2048];
1109 len = ::snprintf(check_function_code,
sizeof(check_function_code), R
"(
1110 extern "C" void *gdb_object_getClass(void *);
1111 extern "C" int printf(const char *format, ...);
1113 %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) {
1114 if ($__lldb_arg_obj == (void *)0)
1115 return; // nil is ok
1116 if (!gdb_object_getClass($__lldb_arg_obj)) {
1117 *((volatile int *)0) = 'ocgc';
1118 } else if ($__lldb_arg_selector != (void *)0) {
1119 signed char $responds = (signed char)
1120 [(id)$__lldb_arg_obj respondsToSelector:
1121 (void *) $__lldb_arg_selector];
1122 if ($responds == (signed char) 0)
1123 *((volatile int *)0) = 'ocgc';
1128 len = ::snprintf(check_function_code,
sizeof(check_function_code), R
"(
1129 extern "C" void *gdb_class_getClass(void *);
1130 extern "C" int printf(const char *format, ...);
1132 %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) {
1133 if ($__lldb_arg_obj == (void *)0)
1134 return; // nil is ok
1135 void **$isa_ptr = (void **)$__lldb_arg_obj;
1136 if (*$isa_ptr == (void *)0 ||
1137 !gdb_class_getClass(*$isa_ptr))
1138 *((volatile int *)0) = 'ocgc';
1139 else if ($__lldb_arg_selector != (void *)0) {
1140 signed char $responds = (signed char)
1141 [(id)$__lldb_arg_obj respondsToSelector:
1142 (void *) $__lldb_arg_selector];
1143 if ($responds == (signed char) 0)
1144 *((volatile int *)0) = 'ocgc';
1150 assert(len < (int)
sizeof(check_function_code));
1158 const char *ivar_name) {
1162 if (!class_name.
IsEmpty() && ivar_name && ivar_name[0]) {
1167 buffer.push_back(
'.');
1168 buffer.append(ivar_name);
1184 if (ivar_offset_symbol.
symbol)
1185 ivar_offset_address =
1216 printf(
"RemoteNXMapTable.m_load_addr = 0x%" PRIx64
"\n", m_load_addr);
1217 printf(
"RemoteNXMapTable.m_count = %u\n", m_count);
1218 printf(
"RemoteNXMapTable.m_num_buckets_minus_one = %u\n",
1219 m_num_buckets_minus_one);
1220 printf(
"RemoteNXMapTable.m_buckets_ptr = 0x%" PRIX64
"\n", m_buckets_ptr);
1224 m_process = process;
1225 m_load_addr = load_addr;
1238 bool success =
true;
1242 lldb::addr_t cursor = load_addr + m_process->GetAddressByteSize();
1245 m_count = m_process->ReadUnsignedIntegerFromMemory(
1246 cursor, unsigned_byte_size, 0, err);
1248 cursor += unsigned_byte_size;
1251 m_num_buckets_minus_one = m_process->ReadUnsignedIntegerFromMemory(
1252 cursor, unsigned_byte_size, 0, err);
1253 cursor += unsigned_byte_size;
1256 m_buckets_ptr = m_process->ReadPointerFromMemory(cursor, err);
1264 m_num_buckets_minus_one = 0;
1272 typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA>
element;
1278 : m_parent(parent), m_index(index) {
1279 AdvanceToValidIndex();
1283 : m_parent(rhs.m_parent), m_index(rhs.m_index) {
1289 assert(&m_parent == &rhs.
m_parent);
1308 AdvanceToValidIndex();
1313 if (m_index == -1) {
1319 size_t map_pair_size = m_parent.m_map_pair_size;
1320 lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
1325 m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
1328 lldb::addr_t value = m_parent.m_process->ReadPointerFromMemory(
1329 pair_ptr + m_parent.m_process->GetAddressByteSize(), err);
1335 m_parent.m_process->ReadCStringFromMemory(key, key_string, err);
1349 const size_t map_pair_size = m_parent.m_map_pair_size;
1350 const lldb::addr_t invalid_key = m_parent.m_invalid_key;
1354 lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size);
1356 m_parent.m_process->ReadPointerFromMemory(pair_ptr, err);
1363 if (key != invalid_key)
1393 size_t m_map_pair_size = 0;
1415 if (m_count == hash_table.
GetCount() &&
1429 class_descriptor_sp = non_pointer_isa_cache->GetClassDescriptor(isa);
1430 if (!class_descriptor_sp)
1432 return class_descriptor_sp;
1441 if (parent && parent != &valobj) {
1443 if (parent_descriptor_sp)
1444 return parent_descriptor_sp->GetSuperclass();
1452 return objc_class_sp;
1462 return objc_class_sp;
1467 return objc_class_sp;
1470 if (isa && !objc_class_sp) {
1473 "0x%" PRIx64
": AppleObjCRuntimeV2::GetClassDescriptor() ISA was "
1474 "not in class descriptor cache 0x%" PRIx64,
1477 return objc_class_sp;
1487 if (!objc_module_sp)
1491 "objc_debug_taggedpointer_obfuscator");
1493 const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
1519 if (!objc_module_sp)
1522 static ConstString g_gdb_objc_realized_classes(
"gdb_objc_realized_classes");
1524 const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(
1533 gdb_objc_realized_classes_ptr,
error);
1540 std::unique_ptr<UtilityFunction>
1545 LLDB_LOG(log,
"Creating utility function {0}", name);
1554 if (!utility_fn_or_error) {
1556 log, utility_fn_or_error.takeError(),
1557 "Failed to get utility function for dynamic info extractor: {0}");
1579 std::unique_ptr<UtilityFunction> utility_fn = std::move(*utility_fn_or_error);
1582 utility_fn->MakeFunctionCaller(clang_uint32_t_type, arguments,
1587 "Failed to make function caller for implementation lookup: {0}.",
1599 case gdb_objc_realized_classes: {
1600 if (!m_gdb_objc_realized_classes_helper.utility_function)
1601 m_gdb_objc_realized_classes_helper.utility_function =
1602 GetClassInfoUtilityFunctionImpl(exe_ctx,
1605 return m_gdb_objc_realized_classes_helper.utility_function.get();
1607 case objc_copyRealizedClassList: {
1608 if (!m_objc_copyRealizedClassList_helper.utility_function)
1609 m_objc_copyRealizedClassList_helper.utility_function =
1610 GetClassInfoUtilityFunctionImpl(exe_ctx,
1613 return m_objc_copyRealizedClassList_helper.utility_function.get();
1616 llvm_unreachable(
"Unexpected helper");
1622 case gdb_objc_realized_classes:
1623 return m_gdb_objc_realized_classes_helper.args;
1624 case objc_copyRealizedClassList:
1625 return m_objc_copyRealizedClassList_helper.args;
1627 llvm_unreachable(
"Unexpected helper");
1632 if (!m_runtime.m_has_objc_copyRealizedClassList)
1635 if (
Process *process = m_runtime.GetProcess()) {
1637 if (loader->IsFullyInitialized())
1645 std::unique_ptr<UtilityFunction>
1650 LLDB_LOG(log,
"Creating utility function {0}",
1660 static ConstString g_class_getName_symbol_name(
"class_getName");
1661 static ConstString g_class_getNameRaw_symbol_name(
1662 "objc_debug_class_getNameRaw");
1665 m_runtime.HasSymbol(g_class_getNameRaw_symbol_name)
1666 ? g_class_getNameRaw_symbol_name
1667 : g_class_getName_symbol_name;
1673 llvm::raw_string_ostream(shared_class_expression)
1675 class_name_getter_function_name.
AsCString(),
1676 class_name_getter_function_name.
AsCString());
1684 if (!utility_fn_or_error) {
1686 log, utility_fn_or_error.takeError(),
1687 "Failed to get utility function for shared class info extractor: {0}");
1718 std::unique_ptr<UtilityFunction> utility_fn = std::move(*utility_fn_or_error);
1721 utility_fn->MakeFunctionCaller(clang_uint32_t_type, arguments,
1726 "Failed to make function caller for implementation lookup: {0}.",
1737 if (!m_utility_function)
1738 m_utility_function = GetClassInfoUtilityFunctionImpl(exe_ctx);
1739 return m_utility_function.get();
1745 Process *process = m_runtime.GetProcess();
1746 if (process ==
nullptr)
1760 thread_sp->CalculateExecutionContext(exe_ctx);
1780 : m_runtime.m_realized_class_generation_count;
1781 if (num_classes == 0) {
1782 LLDB_LOGF(log,
"No dynamic classes found.");
1787 GetClassInfoUtilityFunction(exe_ctx, helper);
1788 if (!get_class_info_code) {
1796 if (!get_class_info_function) {
1797 LLDB_LOGF(log,
"Failed to get implementation lookup function caller.");
1805 const uint32_t class_info_byte_size = addr_size + 4;
1806 const uint32_t class_infos_byte_size = num_classes * class_info_byte_size;
1808 class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);
1812 "unable to allocate %" PRIu32
1813 " bytes in process for shared cache read",
1814 class_infos_byte_size);
1818 std::lock_guard<std::mutex> guard(m_mutex);
1828 bool dump_log = type_log && type_log->
GetVerbose();
1832 bool success =
false;
1834 diagnostics.
Clear();
1838 exe_ctx, GetClassInfoArgs(helper), arguments, diagnostics)) {
1855 diagnostics.
Clear();
1859 exe_ctx, &GetClassInfoArgs(helper), options, diagnostics, return_value);
1864 LLDB_LOG(log,
"Discovered {0} Objective-C classes", num_class_infos);
1865 if (num_class_infos > 0) {
1867 DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0);
1868 if (process->
ReadMemory(class_infos_addr, buffer.GetBytes(),
1874 m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos);
1880 LLDB_LOGF(log,
"Error evaluating our find class name function.");
1881 diagnostics.
Dump(log);
1886 LLDB_LOGF(log,
"Error writing function arguments.");
1887 diagnostics.
Dump(log);
1914 for (
uint32_t i = 0; i < num_class_infos; ++i) {
1920 log,
"AppleObjCRuntimeV2 found NULL isa, ignoring this class info");
1928 "AppleObjCRuntimeV2 found cached isa=0x%" PRIx64
1929 ", ignoring this class info",
1944 AddClass(isa, descriptor_sp, name_hash);
1947 descriptor_sp->GetClassName().AsCString(
nullptr));
1951 "AppleObjCRuntimeV2 added isa=0x%" PRIx64
1952 ", hash=0x%8.8x, name=%s",
1954 descriptor_sp->GetClassName().AsCString(
"<unknown>"));
1958 LLDB_LOGF(log,
"AppleObjCRuntimeV2 parsed %" PRIu32
" class infos",
1968 if (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())
1976 Process *process = m_runtime.GetProcess();
1977 if (process ==
nullptr)
1989 thread_sp->CalculateExecutionContext(exe_ctx);
2004 const lldb::addr_t objc_opt_ptr = m_runtime.GetSharedCacheReadOnlyAddress();
2006 m_runtime.GetSharedCacheBaseAddress();
2014 const uint32_t max_num_classes = 163840;
2016 UtilityFunction *get_class_info_code = GetClassInfoUtilityFunction(exe_ctx);
2017 if (!get_class_info_code) {
2025 if (!get_shared_cache_class_info_function) {
2026 LLDB_LOGF(log,
"Failed to get implementation lookup function caller.");
2035 const uint32_t class_info_byte_size = addr_size + 4;
2036 const uint32_t class_infos_byte_size = max_num_classes * class_info_byte_size;
2038 class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err);
2039 const uint32_t relative_selector_offset_addr_size = 64;
2042 ePermissionsReadable | ePermissionsWritable, err);
2046 "unable to allocate %" PRIu32
2047 " bytes in process for shared cache read",
2048 class_infos_byte_size);
2052 std::lock_guard<std::mutex> guard(m_mutex);
2063 bool dump_log = type_log && type_log->
GetVerbose();
2067 bool success =
false;
2069 diagnostics.
Clear();
2073 exe_ctx, m_args, arguments, diagnostics)) {
2090 diagnostics.
Clear();
2095 exe_ctx, &m_args, options, diagnostics, return_value);
2100 LLDB_LOG(log,
"Discovered {0} Objective-C classes in the shared cache",
2104 assert(num_class_infos <= max_num_classes);
2105 if (num_class_infos > 0) {
2106 if (num_class_infos > max_num_classes) {
2107 num_class_infos = max_num_classes;
2116 if (process->
ReadMemory(relative_selector_offset_addr,
2117 relative_selector_offset_buffer.GetBytes(),
2122 relative_selector_offset_buffer.GetBytes(),
2126 uint64_t relative_selector_offset =
2127 relative_selector_offset_data.
GetU64(&offset);
2128 if (relative_selector_offset > 0) {
2130 m_runtime.SetRelativeSelectorBaseAddr(objc_opt_ptr +
2131 relative_selector_offset);
2137 num_class_infos * class_info_byte_size, 0);
2138 if (process->
ReadMemory(class_infos_addr, class_infos_buffer.GetBytes(),
2141 DataExtractor class_infos_data(class_infos_buffer.GetBytes(),
2145 m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos);
2152 LLDB_LOGF(log,
"Error evaluating our find class name function.");
2153 diagnostics.
Dump(log);
2158 LLDB_LOGF(log,
"Error writing function arguments.");
2159 diagnostics.
Dump(log);
2175 if (objc_module_sp) {
2176 ObjectFile *objc_object = objc_module_sp->GetObjectFile();
2179 SectionList *section_list = objc_module_sp->GetSectionList();
2182 SectionSP text_segment_sp(
2185 if (text_segment_sp) {
2186 SectionSP objc_opt_section_sp(
2187 text_segment_sp->GetChildren().FindSectionByName(
2190 if (objc_opt_section_sp) {
2191 return objc_opt_section_sp->GetLoadBaseAddress(
2239 !class_count_changed)
2259 const uint32_t num_classes_to_warn_at = 500;
2265 "attempted to read objc class data - results: "
2266 "[dynamic_update]: ran: %s, count: %" PRIu32
2267 " [shared_cache_update]: ran: %s, count: %" PRIu32,
2270 shared_cache_update_result.
m_update_ran ?
"yes" :
"no",
2282 num_classes_to_warn_at)
2298 uint64_t objc_debug_realized_class_generation_count =
2300 process,
ConstString(
"objc_debug_realized_class_generation_count"),
2306 objc_debug_realized_class_generation_count)
2311 "objc_debug_realized_class_generation_count changed from {0} to {1}",
2313 objc_debug_realized_class_generation_count);
2316 objc_debug_realized_class_generation_count;
2326 llvm::StringRef platform_plugin_name_sr = platform_sp->GetPluginName();
2327 if (platform_plugin_name_sr.endswith(
"-simulator"))
2345 "the process. This may reduce the quality of type "
2346 "information available.\n",
2351 "could not execute support code to read "
2352 "Objective-C class data in the process. This may "
2353 "reduce the quality of type information available.\n",
2374 llvm::raw_string_ostream os(buffer);
2376 os <<
"libobjc.A.dylib is being read from process memory. This "
2377 "indicates that LLDB could not ";
2378 if (PlatformSP platform_sp = target.
GetPlatform()) {
2379 if (platform_sp->IsHost()) {
2380 os <<
"read from the host's in-memory shared cache";
2382 os <<
"find the on-disk shared cache for this device";
2385 os <<
"read from the shared cache";
2387 os <<
". This will likely reduce debugging performance.\n";
2403 const char *name_cstr = name.
AsCString();
2406 llvm::StringRef name_strref(name_cstr);
2408 llvm::StringRef ivar_prefix(
"OBJC_IVAR_$_");
2409 llvm::StringRef class_prefix(
"OBJC_CLASS_$_");
2411 if (name_strref.startswith(ivar_prefix)) {
2412 llvm::StringRef ivar_skipped_prefix =
2413 name_strref.substr(ivar_prefix.size());
2414 std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar =
2415 ivar_skipped_prefix.split(
'.');
2417 if (class_and_ivar.first.size() && class_and_ivar.second.size()) {
2418 const ConstString class_name_cs(class_and_ivar.first);
2423 const ConstString ivar_name_cs(class_and_ivar.second);
2424 const char *ivar_name_cstr = ivar_name_cs.
AsCString();
2426 auto ivar_func = [&ret,
2427 ivar_name_cstr](
const char *name,
const char *type,
2430 if (!strcmp(name, ivar_name_cstr)) {
2437 descriptor->Describe(
2438 std::function<
void(
ObjCISA)>(
nullptr),
2439 std::function<
bool(
const char *,
const char *)>(
nullptr),
2440 std::function<
bool(
const char *,
const char *)>(
nullptr),
2444 }
else if (name_strref.startswith(class_prefix)) {
2445 llvm::StringRef class_skipped_prefix =
2446 name_strref.substr(class_prefix.size());
2447 const ConstString class_name_cs(class_skipped_prefix);
2452 ret = descriptor->GetISA();
2474 process,
ConstString(
"objc_debug_isa_magic_value"), objc_module_sp,
2485 log->
PutCString(
"AOCRT::NPI: Found all the non-indexed ISA masks");
2487 bool foundError =
false;
2489 process,
ConstString(
"objc_debug_indexed_isa_magic_mask"), objc_module_sp,
2491 foundError |=
error.Fail();
2494 process,
ConstString(
"objc_debug_indexed_isa_magic_value"),
2495 objc_module_sp,
error);
2496 foundError |=
error.Fail();
2499 process,
ConstString(
"objc_debug_indexed_isa_index_mask"), objc_module_sp,
2501 foundError |=
error.Fail();
2504 process,
ConstString(
"objc_debug_indexed_isa_index_shift"),
2505 objc_module_sp,
error);
2506 foundError |=
error.Fail();
2508 auto objc_indexed_classes =
2510 objc_module_sp,
error,
false);
2511 foundError |=
error.Fail();
2514 log->
PutCString(
"AOCRT::NPI: Found all the indexed ISA masks");
2520 runtime, objc_module_sp, objc_debug_isa_class_mask,
2521 objc_debug_isa_magic_mask, objc_debug_isa_magic_value,
2522 objc_debug_indexed_isa_magic_mask, objc_debug_indexed_isa_magic_value,
2523 objc_debug_indexed_isa_index_mask, objc_debug_indexed_isa_index_shift,
2524 foundError ? 0 : objc_indexed_classes);
2535 process,
ConstString(
"objc_debug_taggedpointer_mask"), objc_module_sp,
2541 process,
ConstString(
"objc_debug_taggedpointer_slot_shift"),
2542 objc_module_sp,
error,
true, 4);
2547 process,
ConstString(
"objc_debug_taggedpointer_slot_mask"),
2548 objc_module_sp,
error,
true, 4);
2553 process,
ConstString(
"objc_debug_taggedpointer_payload_lshift"),
2554 objc_module_sp,
error,
true, 4);
2559 process,
ConstString(
"objc_debug_taggedpointer_payload_rshift"),
2560 objc_module_sp,
error,
true, 4);
2565 process,
ConstString(
"objc_debug_taggedpointer_classes"), objc_module_sp,
2574 process,
ConstString(
"objc_debug_taggedpointer_ext_mask"),
2575 objc_module_sp,
error);
2580 process,
ConstString(
"objc_debug_taggedpointer_ext_slot_shift"),
2581 objc_module_sp,
error,
true, 4);
2586 process,
ConstString(
"objc_debug_taggedpointer_ext_slot_mask"),
2587 objc_module_sp,
error,
true, 4);
2592 process,
ConstString(
"objc_debug_taggedpointer_ext_classes"),
2593 objc_module_sp,
error,
false);
2597 auto objc_debug_taggedpointer_ext_payload_lshift =
2599 process,
ConstString(
"objc_debug_taggedpointer_ext_payload_lshift"),
2600 objc_module_sp,
error,
true, 4);
2604 auto objc_debug_taggedpointer_ext_payload_rshift =
2606 process,
ConstString(
"objc_debug_taggedpointer_ext_payload_rshift"),
2607 objc_module_sp,
error,
true, 4);
2612 runtime, objc_debug_taggedpointer_mask,
2613 objc_debug_taggedpointer_ext_mask, objc_debug_taggedpointer_slot_shift,
2614 objc_debug_taggedpointer_ext_slot_shift,
2615 objc_debug_taggedpointer_slot_mask,
2616 objc_debug_taggedpointer_ext_slot_mask,
2617 objc_debug_taggedpointer_payload_lshift,
2618 objc_debug_taggedpointer_payload_rshift,
2619 objc_debug_taggedpointer_ext_payload_lshift,
2620 objc_debug_taggedpointer_ext_payload_rshift,
2621 objc_debug_taggedpointer_classes, objc_debug_taggedpointer_ext_classes);
2628 runtime, objc_debug_taggedpointer_mask,
2629 objc_debug_taggedpointer_slot_shift, objc_debug_taggedpointer_slot_mask,
2630 objc_debug_taggedpointer_payload_lshift,
2631 objc_debug_taggedpointer_payload_rshift,
2632 objc_debug_taggedpointer_classes);
2643 if (!IsPossibleTaggedPointer(ptr))
2646 uint32_t foundation_version = m_runtime.GetFoundationVersion();
2651 uint64_t class_bits = (ptr & 0xE) >> 1;
2657 static ConstString g_NSManagedObject(
"NSManagedObject");
2660 if (foundation_version >= 900) {
2661 switch (class_bits) {
2672 name = g_NSManagedObject;
2681 switch (class_bits) {
2686 name = g_NSManagedObject;
2699 lldb::addr_t unobfuscated = ptr ^ m_runtime.GetTaggedPointerObfuscator();
2706 uint32_t objc_debug_taggedpointer_slot_shift,
2707 uint32_t objc_debug_taggedpointer_slot_mask,
2708 uint32_t objc_debug_taggedpointer_payload_lshift,
2709 uint32_t objc_debug_taggedpointer_payload_rshift,
2712 m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask),
2713 m_objc_debug_taggedpointer_slot_shift(
2714 objc_debug_taggedpointer_slot_shift),
2715 m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask),
2716 m_objc_debug_taggedpointer_payload_lshift(
2717 objc_debug_taggedpointer_payload_lshift),
2718 m_objc_debug_taggedpointer_payload_rshift(
2719 objc_debug_taggedpointer_payload_rshift),
2720 m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes) {}
2724 return (ptr & m_objc_debug_taggedpointer_mask) != 0;
2731 uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
2733 if (!IsPossibleTaggedPointer(unobfuscated))
2736 uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) &
2737 m_objc_debug_taggedpointer_slot_mask;
2739 CacheIterator iterator = m_cache.find(slot), end = m_cache.end();
2740 if (iterator != end) {
2741 actual_class_descriptor_sp = iterator->second;
2743 Process *process(m_runtime.GetProcess());
2745 m_objc_debug_taggedpointer_classes;
2748 if (
error.Fail() || slot_data == 0 ||
2751 actual_class_descriptor_sp =
2752 m_runtime.GetClassDescriptorFromISA((
ObjCISA)slot_data);
2753 if (!actual_class_descriptor_sp) {
2754 if (ABISP abi_sp = process->
GetABI()) {
2756 actual_class_descriptor_sp =
2757 m_runtime.GetClassDescriptorFromISA(fixed_isa);
2760 if (!actual_class_descriptor_sp)
2762 m_cache[slot] = actual_class_descriptor_sp;
2765 uint64_t data_payload =
2766 ((unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >>
2767 m_objc_debug_taggedpointer_payload_rshift);
2768 int64_t data_payload_signed =
2769 ((int64_t)(unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >>
2770 m_objc_debug_taggedpointer_payload_rshift);
2772 actual_class_descriptor_sp, data_payload, data_payload_signed));
2777 uint64_t objc_debug_taggedpointer_ext_mask,
2778 uint32_t objc_debug_taggedpointer_slot_shift,
2779 uint32_t objc_debug_taggedpointer_ext_slot_shift,
2780 uint32_t objc_debug_taggedpointer_slot_mask,
2781 uint32_t objc_debug_taggedpointer_ext_slot_mask,
2782 uint32_t objc_debug_taggedpointer_payload_lshift,
2783 uint32_t objc_debug_taggedpointer_payload_rshift,
2784 uint32_t objc_debug_taggedpointer_ext_payload_lshift,
2785 uint32_t objc_debug_taggedpointer_ext_payload_rshift,
2789 runtime, objc_debug_taggedpointer_mask,
2790 objc_debug_taggedpointer_slot_shift,
2791 objc_debug_taggedpointer_slot_mask,
2792 objc_debug_taggedpointer_payload_lshift,
2793 objc_debug_taggedpointer_payload_rshift,
2794 objc_debug_taggedpointer_classes),
2796 m_objc_debug_taggedpointer_ext_mask(objc_debug_taggedpointer_ext_mask),
2797 m_objc_debug_taggedpointer_ext_slot_shift(
2798 objc_debug_taggedpointer_ext_slot_shift),
2799 m_objc_debug_taggedpointer_ext_slot_mask(
2800 objc_debug_taggedpointer_ext_slot_mask),
2801 m_objc_debug_taggedpointer_ext_payload_lshift(
2802 objc_debug_taggedpointer_ext_payload_lshift),
2803 m_objc_debug_taggedpointer_ext_payload_rshift(
2804 objc_debug_taggedpointer_ext_payload_rshift),
2805 m_objc_debug_taggedpointer_ext_classes(
2806 objc_debug_taggedpointer_ext_classes) {}
2810 if (!IsPossibleTaggedPointer(ptr))
2813 if (m_objc_debug_taggedpointer_ext_mask == 0)
2816 return ((ptr & m_objc_debug_taggedpointer_ext_mask) ==
2817 m_objc_debug_taggedpointer_ext_mask);
2824 uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator();
2826 if (!IsPossibleTaggedPointer(unobfuscated))
2829 if (!IsPossibleExtendedTaggedPointer(unobfuscated))
2832 uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_ext_slot_shift) &
2833 m_objc_debug_taggedpointer_ext_slot_mask;
2835 CacheIterator iterator = m_ext_cache.find(slot), end = m_ext_cache.end();
2836 if (iterator != end) {
2837 actual_class_descriptor_sp = iterator->second;
2839 Process *process(m_runtime.GetProcess());
2841 m_objc_debug_taggedpointer_ext_classes;
2844 if (
error.Fail() || slot_data == 0 ||
2847 actual_class_descriptor_sp =
2848 m_runtime.GetClassDescriptorFromISA((
ObjCISA)slot_data);
2849 if (!actual_class_descriptor_sp)
2851 m_ext_cache[slot] = actual_class_descriptor_sp;
2854 uint64_t data_payload = (((uint64_t)unobfuscated
2855 << m_objc_debug_taggedpointer_ext_payload_lshift) >>
2856 m_objc_debug_taggedpointer_ext_payload_rshift);
2857 int64_t data_payload_signed =
2858 ((int64_t)((int64_t)unobfuscated
2859 << m_objc_debug_taggedpointer_ext_payload_lshift) >>
2860 m_objc_debug_taggedpointer_ext_payload_rshift);
2863 actual_class_descriptor_sp, data_payload, data_payload_signed));
2868 uint64_t objc_debug_isa_class_mask, uint64_t objc_debug_isa_magic_mask,
2869 uint64_t objc_debug_isa_magic_value,
2870 uint64_t objc_debug_indexed_isa_magic_mask,
2871 uint64_t objc_debug_indexed_isa_magic_value,
2872 uint64_t objc_debug_indexed_isa_index_mask,
2873 uint64_t objc_debug_indexed_isa_index_shift,
2876 m_objc_debug_isa_class_mask(objc_debug_isa_class_mask),
2877 m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask),
2878 m_objc_debug_isa_magic_value(objc_debug_isa_magic_value),
2879 m_objc_debug_indexed_isa_magic_mask(objc_debug_indexed_isa_magic_mask),
2880 m_objc_debug_indexed_isa_magic_value(objc_debug_indexed_isa_magic_value),
2881 m_objc_debug_indexed_isa_index_mask(objc_debug_indexed_isa_index_mask),
2882 m_objc_debug_indexed_isa_index_shift(objc_debug_indexed_isa_index_shift),
2883 m_objc_indexed_classes(objc_indexed_classes), m_indexed_isa_cache() {}
2888 if (!EvaluateNonPointerISA(isa, real_isa))
2890 auto cache_iter = m_cache.find(real_isa);
2891 if (cache_iter != m_cache.end())
2892 return cache_iter->second;
2893 auto descriptor_sp =
2894 m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa);
2896 m_cache[real_isa] = descriptor_sp;
2897 return descriptor_sp;
2904 LLDB_LOGF(log,
"AOCRT::NPI Evaluate(isa = 0x%" PRIx64
")", (uint64_t)isa);
2906 if ((isa & ~m_objc_debug_isa_class_mask) == 0)
2913 if (m_objc_debug_indexed_isa_magic_mask &&
2914 m_objc_debug_indexed_isa_magic_value &&
2915 m_objc_debug_indexed_isa_index_mask &&
2916 m_objc_debug_indexed_isa_index_shift && m_objc_indexed_classes) {
2917 if ((isa & ~m_objc_debug_indexed_isa_index_mask) == 0)
2920 if ((isa & m_objc_debug_indexed_isa_magic_mask) ==
2921 m_objc_debug_indexed_isa_magic_value) {
2923 uintptr_t index = (isa & m_objc_debug_indexed_isa_index_mask) >>
2924 m_objc_debug_indexed_isa_index_shift;
2929 if (index > m_indexed_isa_cache.size()) {
2931 "AOCRT::NPI (index = %" PRIu64
2932 ") exceeds cache (size = %" PRIu64
")",
2933 (uint64_t)index, (uint64_t)m_indexed_isa_cache.size());
2935 Process *process(m_runtime.GetProcess());
2938 if (!objc_module_sp)
2943 process,
ConstString(
"objc_indexed_classes_count"), objc_module_sp,
2948 LLDB_LOGF(log,
"AOCRT::NPI (new class count = %" PRIu64
")",
2949 (uint64_t)objc_indexed_classes_count);
2951 if (objc_indexed_classes_count > m_indexed_isa_cache.size()) {
2955 auto num_new_classes =
2956 objc_indexed_classes_count - m_indexed_isa_cache.size();
2961 m_objc_indexed_classes + (m_indexed_isa_cache.size() * addr_size);
2967 LLDB_LOGF(log,
"AOCRT::NPI (read new classes count = %" PRIu64
")",
2968 (uint64_t)num_new_classes);
2976 for (
unsigned i = 0; i != num_new_classes; ++i)
2977 m_indexed_isa_cache.push_back(data.
GetAddress(&offset));
2982 if (index > m_indexed_isa_cache.size())
2985 LLDB_LOGF(log,
"AOCRT::NPI Evaluate(ret_isa = 0x%" PRIx64
")",
2986 (uint64_t)m_indexed_isa_cache[index]);
2988 ret_isa = m_indexed_isa_cache[index];
2989 return (ret_isa != 0);
2997 if ((isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value) {
2998 ret_isa = isa & m_objc_debug_isa_class_mask;
2999 return (ret_isa != 0);
3007 std::make_shared<AppleObjCTypeEncodingParser>(*
this);
3016 non_pointer_isa_cache->EvaluateNonPointerISA(isa, ret);
3025 static ConstString g_dunder_kCFBooleanFalse(
"__kCFBooleanFalse");
3026 static ConstString g_dunder_kCFBooleanTrue(
"__kCFBooleanTrue");
3027 static ConstString g_kCFBooleanFalse(
"kCFBooleanFalse");
3028 static ConstString g_kCFBooleanTrue(
"kCFBooleanTrue");
3059 lldb::addr_t false_addr = get_symbol(g_dunder_kCFBooleanFalse, g_kCFBooleanFalse);
3060 lldb::addr_t true_addr = get_symbol(g_dunder_kCFBooleanTrue, g_kCFBooleanTrue);
3074 #pragma mark Frame recognizers
3079 ThreadSP thread_sp = frame_sp->GetThread();
3080 ProcessSP process_sp = thread_sp->GetProcess();
3082 const lldb::ABISP &abi = process_sp->GetABI();
3088 if (!clang_ast_context)
3098 if (!abi->GetArgumentValues(*thread_sp, args))
3103 Value value(exception_addr);
3112 m_arguments->Append(exception);
3114 m_stop_desc =
"hit Objective-C exception";
3123 lldb::RecognizedStackFrameSP
3125 return lldb::RecognizedStackFrameSP(
3129 return "ObjC Exception Throw StackFrame Recognizer";
3137 std::vector<ConstString> symbols = {
function};