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