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