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