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 68using namespace lldb; 69using namespace lldb_private; 70 71char AppleObjCRuntimeV2::ID = 0; 72 73static const char *g_get_dynamic_class_info_name = 74 "__lldb_apple_objc_v2_get_dynamic_class_info"; 75 76static const char *g_get_dynamic_class_info_body = R"( 77 78extern "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 86typedef 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 95typedef struct BucketInfo 96{ 97 const char *name_ptr; 98 Class isa; 99} BucketInfo; 100 101struct ClassInfo 102{ 103 Class isa; 104 uint32_t hash; 105} __attribute__((__packed__)); 106 107uint32_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 163static const char *g_get_dynamic_class_info2_name = 164 "__lldb_apple_objc_v2_get_dynamic_class_info2"; 165 166static const char *g_get_dynamic_class_info2_body = R"( 167 168extern "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 177struct ClassInfo 178{ 179 Class isa; 180 uint32_t hash; 181} __attribute__((__packed__)); 182 183uint32_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 232static const char *g_get_dynamic_class_info3_name = 233 "__lldb_apple_objc_v2_get_dynamic_class_info3"; 234 235static const char *g_get_dynamic_class_info3_body = R"( 236 237extern "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 247struct ClassInfo 248{ 249 Class isa; 250 uint32_t hash; 251} __attribute__((__packed__)); 252 253uint32_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. 311static const char *g_shared_cache_class_name_funcptr = R"( 312extern "C" 313{ 314 const char *%s(void *objc_class); 315 const char *(*class_name_lookup_func)(void *) = %s; 316} 317)"; 318 319static const char *g_get_shared_cache_class_info_name = 320 "__lldb_apple_objc_v2_get_shared_cache_class_info"; 321 322static const char *g_get_shared_cache_class_info_body = R"( 323 324extern "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 334struct objc_classheader_t { 335 int32_t clsOffset; 336 int32_t hiOffset; 337}; 338 339struct objc_classheader_v16_t { 340 uint64_t isDuplicate : 1, 341 objectCacheOffset : 47, // Offset from the shared cache base 342 dylibObjCIndex : 16; 343}; 344 345struct 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 362struct 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 379struct objc_opt_t { 380 uint32_t version; 381 int32_t selopt_offset; 382 int32_t headeropt_offset; 383 int32_t clsopt_offset; 384}; 385 386struct 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 394struct 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 408struct ClassInfo 409{ 410 Class isa; 411 uint32_t hash; 412} __attribute__((__packed__)); 413 414uint32_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 687static uint64_t 688ExtractRuntimeGlobalSymbol(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 726static void RegisterObjCExceptionRecognizer(Process *process); 727 728AppleObjCRuntimeV2::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 756bool 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 811LanguageRuntime *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 827static 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 839class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed { 840public: 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::ArrayRef(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 905protected: 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 996class CommandObjectMultiwordObjC_TaggedPointer_Info 997 : public CommandObjectParsed { 998public: 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 1022protected: 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 1099class CommandObjectMultiwordObjC_ClassTable : public CommandObjectMultiword { 1100public: 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 1114class CommandObjectMultiwordObjC_TaggedPointer : public CommandObjectMultiword { 1115public: 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 1130class CommandObjectMultiwordObjC : public CommandObjectMultiword { 1131public: 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 1148void 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 1158void AppleObjCRuntimeV2::Terminate() { 1159 PluginManager::UnregisterPlugin(CreateInstance); 1160} 1161 1162BreakpointResolverSP 1163AppleObjCRuntimeV2::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 1178llvm::Expected<std::unique_ptr<UtilityFunction>> 1179AppleObjCRuntimeV2::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 1233size_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 1281bool 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 1287class RemoteNXMapTable { 1288public: 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 1461private: 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 1473AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() = default; 1474 1475void 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 1482bool 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 1501ObjCLanguageRuntime::ClassDescriptorSP 1502AppleObjCRuntimeV2::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 1511ObjCLanguageRuntime::ClassDescriptorSP 1512AppleObjCRuntimeV2::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 1562lldb::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 1595lldb::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 1622std::unique_ptr<UtilityFunction> 1623AppleObjCRuntimeV2::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 TypeSystemClangSP scratch_ts_sp = 1631 ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef()); 1632 if (!scratch_ts_sp) 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 scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); 1647 CompilerType clang_void_pointer_type = 1648 scratch_ts_sp->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 1687UtilityFunction * 1688AppleObjCRuntimeV2::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 1719lldb::addr_t & 1720AppleObjCRuntimeV2::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 1732AppleObjCRuntimeV2::DynamicClassInfoExtractor::Helper 1733AppleObjCRuntimeV2::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 1763std::unique_ptr<UtilityFunction> 1764AppleObjCRuntimeV2::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 TypeSystemClangSP scratch_ts_sp = 1772 ScratchTypeSystemClang::GetForTarget(exe_ctx.GetTargetRef()); 1773 if (!scratch_ts_sp) 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 scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); 1812 CompilerType clang_void_pointer_type = 1813 scratch_ts_sp->GetBasicType(eBasicTypeVoid).GetPointerType(); 1814 CompilerType clang_uint64_t_pointer_type = 1815 scratch_ts_sp->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 1852UtilityFunction * 1853AppleObjCRuntimeV2::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 1860AppleObjCRuntimeV2::DescriptorMapUpdateResult 1861AppleObjCRuntimeV2::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 if (!thread_sp->SafeToCallFunctions()) 1879 return DescriptorMapUpdateResult::Retry(); 1880 1881 thread_sp->CalculateExecutionContext(exe_ctx); 1882 TypeSystemClangSP scratch_ts_sp = 1883 ScratchTypeSystemClang::GetForTarget(process->GetTarget()); 1884 1885 if (!scratch_ts_sp) 1886 return DescriptorMapUpdateResult::Fail(); 1887 1888 Address function_address; 1889 1890 const uint32_t addr_size = process->GetAddressByteSize(); 1891 1892 Status err; 1893 1894 // Compute which helper we're going to use for this update. 1895 const DynamicClassInfoExtractor::Helper helper = ComputeHelper(exe_ctx); 1896 1897 // Read the total number of classes from the hash table 1898 const uint32_t num_classes = 1899 helper == DynamicClassInfoExtractor::gdb_objc_realized_classes 1900 ? hash_table.GetCount() 1901 : m_runtime.m_realized_class_generation_count; 1902 if (num_classes == 0) { 1903 LLDB_LOGF(log, "No dynamic classes found."); 1904 return DescriptorMapUpdateResult::Success(0); 1905 } 1906 1907 UtilityFunction *get_class_info_code = 1908 GetClassInfoUtilityFunction(exe_ctx, helper); 1909 if (!get_class_info_code) { 1910 // The callee will have already logged a useful error message. 1911 return DescriptorMapUpdateResult::Fail(); 1912 } 1913 1914 FunctionCaller *get_class_info_function = 1915 get_class_info_code->GetFunctionCaller(); 1916 1917 if (!get_class_info_function) { 1918 LLDB_LOGF(log, "Failed to get implementation lookup function caller."); 1919 return DescriptorMapUpdateResult::Fail(); 1920 } 1921 1922 ValueList arguments = get_class_info_function->GetArgumentValues(); 1923 1924 DiagnosticManager diagnostics; 1925 1926 const uint32_t class_info_byte_size = addr_size + 4; 1927 const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; 1928 lldb::addr_t class_infos_addr = process->AllocateMemory( 1929 class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err); 1930 1931 if (class_infos_addr == LLDB_INVALID_ADDRESS) { 1932 LLDB_LOGF(log, 1933 "unable to allocate %" PRIu32 1934 " bytes in process for shared cache read", 1935 class_infos_byte_size); 1936 return DescriptorMapUpdateResult::Fail(); 1937 } 1938 1939 auto deallocate_class_infos = llvm::make_scope_exit([&] { 1940 // Deallocate the memory we allocated for the ClassInfo array 1941 if (class_infos_addr != LLDB_INVALID_ADDRESS) 1942 process->DeallocateMemory(class_infos_addr); 1943 }); 1944 1945 lldb::addr_t class_buffer_addr = LLDB_INVALID_ADDRESS; 1946 const uint32_t class_byte_size = addr_size; 1947 const uint32_t class_buffer_len = num_classes; 1948 const uint32_t class_buffer_byte_size = class_buffer_len * class_byte_size; 1949 if (helper == Helper::objc_getRealizedClassList_trylock) { 1950 class_buffer_addr = process->AllocateMemory( 1951 class_buffer_byte_size, ePermissionsReadable | ePermissionsWritable, 1952 err); 1953 if (class_buffer_addr == LLDB_INVALID_ADDRESS) { 1954 LLDB_LOGF(log, 1955 "unable to allocate %" PRIu32 1956 " bytes in process for shared cache read", 1957 class_buffer_byte_size); 1958 return DescriptorMapUpdateResult::Fail(); 1959 } 1960 } 1961 1962 auto deallocate_class_buffer = llvm::make_scope_exit([&] { 1963 // Deallocate the memory we allocated for the Class array 1964 if (class_buffer_addr != LLDB_INVALID_ADDRESS) 1965 process->DeallocateMemory(class_buffer_addr); 1966 }); 1967 1968 std::lock_guard<std::mutex> guard(m_mutex); 1969 1970 // Fill in our function argument values 1971 uint32_t index = 0; 1972 arguments.GetValueAtIndex(index++)->GetScalar() = 1973 hash_table.GetTableLoadAddress(); 1974 arguments.GetValueAtIndex(index++)->GetScalar() = class_infos_addr; 1975 arguments.GetValueAtIndex(index++)->GetScalar() = class_infos_byte_size; 1976 1977 if (class_buffer_addr != LLDB_INVALID_ADDRESS) { 1978 arguments.GetValueAtIndex(index++)->GetScalar() = class_buffer_addr; 1979 arguments.GetValueAtIndex(index++)->GetScalar() = class_buffer_byte_size; 1980 } 1981 1982 // Only dump the runtime classes from the expression evaluation if the log is 1983 // verbose: 1984 Log *type_log = GetLog(LLDBLog::Types); 1985 bool dump_log = type_log && type_log->GetVerbose(); 1986 1987 arguments.GetValueAtIndex(index++)->GetScalar() = dump_log ? 1 : 0; 1988 1989 bool success = false; 1990 1991 diagnostics.Clear(); 1992 1993 // Write our function arguments into the process so we can run our function 1994 if (get_class_info_function->WriteFunctionArguments( 1995 exe_ctx, GetClassInfoArgs(helper), arguments, diagnostics)) { 1996 EvaluateExpressionOptions options; 1997 options.SetUnwindOnError(true); 1998 options.SetTryAllThreads(false); 1999 options.SetStopOthers(true); 2000 options.SetIgnoreBreakpoints(true); 2001 options.SetTimeout(process->GetUtilityExpressionTimeout()); 2002 options.SetIsForUtilityExpr(true); 2003 2004 CompilerType clang_uint32_t_type = 2005 scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); 2006 2007 Value return_value; 2008 return_value.SetValueType(Value::ValueType::Scalar); 2009 return_value.SetCompilerType(clang_uint32_t_type); 2010 return_value.GetScalar() = 0; 2011 2012 diagnostics.Clear(); 2013 2014 // Run the function 2015 ExpressionResults results = get_class_info_function->ExecuteFunction( 2016 exe_ctx, &GetClassInfoArgs(helper), options, diagnostics, return_value); 2017 2018 if (results == eExpressionCompleted) { 2019 // The result is the number of ClassInfo structures that were filled in 2020 num_class_infos = return_value.GetScalar().ULong(); 2021 LLDB_LOG(log, "Discovered {0} Objective-C classes", num_class_infos); 2022 if (num_class_infos > 0) { 2023 // Read the ClassInfo structures 2024 DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0); 2025 if (process->ReadMemory(class_infos_addr, buffer.GetBytes(), 2026 buffer.GetByteSize(), 2027 err) == buffer.GetByteSize()) { 2028 DataExtractor class_infos_data(buffer.GetBytes(), 2029 buffer.GetByteSize(), 2030 process->GetByteOrder(), addr_size); 2031 m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos); 2032 } 2033 } 2034 success = true; 2035 } else { 2036 if (log) { 2037 LLDB_LOGF(log, "Error evaluating our find class name function."); 2038 diagnostics.Dump(log); 2039 } 2040 } 2041 } else { 2042 if (log) { 2043 LLDB_LOGF(log, "Error writing function arguments."); 2044 diagnostics.Dump(log); 2045 } 2046 } 2047 2048 return DescriptorMapUpdateResult(success, false, num_class_infos); 2049} 2050 2051uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data, 2052 uint32_t num_class_infos) { 2053 // Parses an array of "num_class_infos" packed ClassInfo structures: 2054 // 2055 // struct ClassInfo 2056 // { 2057 // Class isa; 2058 // uint32_t hash; 2059 // } __attribute__((__packed__)); 2060 2061 Log *log = GetLog(LLDBLog::Types); 2062 bool should_log = log && log->GetVerbose(); 2063 2064 uint32_t num_parsed = 0; 2065 2066 // Iterate through all ClassInfo structures 2067 lldb::offset_t offset = 0; 2068 for (uint32_t i = 0; i < num_class_infos; ++i) { 2069 ObjCISA isa = data.GetAddress(&offset); 2070 2071 if (isa == 0) { 2072 if (should_log) 2073 LLDB_LOGF( 2074 log, "AppleObjCRuntimeV2 found NULL isa, ignoring this class info"); 2075 continue; 2076 } 2077 // Check if we already know about this ISA, if we do, the info will never 2078 // change, so we can just skip it. 2079 if (ISAIsCached(isa)) { 2080 if (should_log) 2081 LLDB_LOGF(log, 2082 "AppleObjCRuntimeV2 found cached isa=0x%" PRIx64 2083 ", ignoring this class info", 2084 isa); 2085 offset += 4; 2086 } else { 2087 // Read the 32 bit hash for the class name 2088 const uint32_t name_hash = data.GetU32(&offset); 2089 ClassDescriptorSP descriptor_sp( 2090 new ClassDescriptorV2(*this, isa, nullptr)); 2091 2092 // The code in g_get_shared_cache_class_info_body sets the value of the 2093 // hash to 0 to signal a demangled symbol. We use class_getName() in that 2094 // code to find the class name, but this returns a demangled name for 2095 // Swift symbols. For those symbols, recompute the hash here by reading 2096 // their name from the runtime. 2097 if (name_hash) 2098 AddClass(isa, descriptor_sp, name_hash); 2099 else 2100 AddClass(isa, descriptor_sp, 2101 descriptor_sp->GetClassName().AsCString(nullptr)); 2102 num_parsed++; 2103 if (should_log) 2104 LLDB_LOGF(log, 2105 "AppleObjCRuntimeV2 added isa=0x%" PRIx64 2106 ", hash=0x%8.8x, name=%s", 2107 isa, name_hash, 2108 descriptor_sp->GetClassName().AsCString("<unknown>")); 2109 } 2110 } 2111 if (should_log) 2112 LLDB_LOGF(log, "AppleObjCRuntimeV2 parsed %" PRIu32 " class infos", 2113 num_parsed); 2114 return num_parsed; 2115} 2116 2117bool AppleObjCRuntimeV2::HasSymbol(ConstString Name) { 2118 if (!m_objc_module_sp) 2119 return false; 2120 if (const Symbol *symbol = m_objc_module_sp->FindFirstSymbolWithNameAndType( 2121 Name, lldb::eSymbolTypeCode)) { 2122 if (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid()) 2123 return true; 2124 } 2125 return false; 2126} 2127 2128AppleObjCRuntimeV2::DescriptorMapUpdateResult 2129AppleObjCRuntimeV2::SharedCacheClassInfoExtractor::UpdateISAToDescriptorMap() { 2130 Process *process = m_runtime.GetProcess(); 2131 if (process == nullptr) 2132 return DescriptorMapUpdateResult::Fail(); 2133 2134 Log *log = GetLog(LLDBLog::Process | LLDBLog::Types); 2135 2136 ExecutionContext exe_ctx; 2137 2138 ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread(); 2139 2140 if (!thread_sp) 2141 return DescriptorMapUpdateResult::Fail(); 2142 2143 if (!thread_sp->SafeToCallFunctions()) 2144 return DescriptorMapUpdateResult::Retry(); 2145 2146 thread_sp->CalculateExecutionContext(exe_ctx); 2147 TypeSystemClangSP scratch_ts_sp = 2148 ScratchTypeSystemClang::GetForTarget(process->GetTarget()); 2149 2150 if (!scratch_ts_sp) 2151 return DescriptorMapUpdateResult::Fail(); 2152 2153 Address function_address; 2154 2155 const uint32_t addr_size = process->GetAddressByteSize(); 2156 2157 Status err; 2158 2159 uint32_t num_class_infos = 0; 2160 2161 const lldb::addr_t objc_opt_ptr = m_runtime.GetSharedCacheReadOnlyAddress(); 2162 const lldb::addr_t shared_cache_base_addr = 2163 m_runtime.GetSharedCacheBaseAddress(); 2164 2165 if (objc_opt_ptr == LLDB_INVALID_ADDRESS || 2166 shared_cache_base_addr == LLDB_INVALID_ADDRESS) 2167 return DescriptorMapUpdateResult::Fail(); 2168 2169 // The number of entries to pre-allocate room for. 2170 // Each entry is (addrsize + 4) bytes 2171 const uint32_t max_num_classes = 163840; 2172 2173 UtilityFunction *get_class_info_code = GetClassInfoUtilityFunction(exe_ctx); 2174 if (!get_class_info_code) { 2175 // The callee will have already logged a useful error message. 2176 return DescriptorMapUpdateResult::Fail(); 2177 } 2178 2179 FunctionCaller *get_shared_cache_class_info_function = 2180 get_class_info_code->GetFunctionCaller(); 2181 2182 if (!get_shared_cache_class_info_function) { 2183 LLDB_LOGF(log, "Failed to get implementation lookup function caller."); 2184 return DescriptorMapUpdateResult::Fail(); 2185 } 2186 2187 ValueList arguments = 2188 get_shared_cache_class_info_function->GetArgumentValues(); 2189 2190 DiagnosticManager diagnostics; 2191 2192 const uint32_t class_info_byte_size = addr_size + 4; 2193 const uint32_t class_infos_byte_size = max_num_classes * class_info_byte_size; 2194 lldb::addr_t class_infos_addr = process->AllocateMemory( 2195 class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err); 2196 const uint32_t relative_selector_offset_addr_size = 64; 2197 lldb::addr_t relative_selector_offset_addr = 2198 process->AllocateMemory(relative_selector_offset_addr_size, 2199 ePermissionsReadable | ePermissionsWritable, err); 2200 2201 if (class_infos_addr == LLDB_INVALID_ADDRESS) { 2202 LLDB_LOGF(log, 2203 "unable to allocate %" PRIu32 2204 " bytes in process for shared cache read", 2205 class_infos_byte_size); 2206 return DescriptorMapUpdateResult::Fail(); 2207 } 2208 2209 std::lock_guard<std::mutex> guard(m_mutex); 2210 2211 // Fill in our function argument values 2212 arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr; 2213 arguments.GetValueAtIndex(1)->GetScalar() = shared_cache_base_addr; 2214 arguments.GetValueAtIndex(2)->GetScalar() = class_infos_addr; 2215 arguments.GetValueAtIndex(3)->GetScalar() = relative_selector_offset_addr; 2216 arguments.GetValueAtIndex(4)->GetScalar() = class_infos_byte_size; 2217 // Only dump the runtime classes from the expression evaluation if the log is 2218 // verbose: 2219 Log *type_log = GetLog(LLDBLog::Types); 2220 bool dump_log = type_log && type_log->GetVerbose(); 2221 2222 arguments.GetValueAtIndex(5)->GetScalar() = dump_log ? 1 : 0; 2223 2224 bool success = false; 2225 2226 diagnostics.Clear(); 2227 2228 // Write our function arguments into the process so we can run our function 2229 if (get_shared_cache_class_info_function->WriteFunctionArguments( 2230 exe_ctx, m_args, arguments, diagnostics)) { 2231 EvaluateExpressionOptions options; 2232 options.SetUnwindOnError(true); 2233 options.SetTryAllThreads(false); 2234 options.SetStopOthers(true); 2235 options.SetIgnoreBreakpoints(true); 2236 options.SetTimeout(process->GetUtilityExpressionTimeout()); 2237 options.SetIsForUtilityExpr(true); 2238 2239 CompilerType clang_uint32_t_type = 2240 scratch_ts_sp->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); 2241 2242 Value return_value; 2243 return_value.SetValueType(Value::ValueType::Scalar); 2244 return_value.SetCompilerType(clang_uint32_t_type); 2245 return_value.GetScalar() = 0; 2246 2247 diagnostics.Clear(); 2248 2249 // Run the function 2250 ExpressionResults results = 2251 get_shared_cache_class_info_function->ExecuteFunction( 2252 exe_ctx, &m_args, options, diagnostics, return_value); 2253 2254 if (results == eExpressionCompleted) { 2255 // The result is the number of ClassInfo structures that were filled in 2256 num_class_infos = return_value.GetScalar().ULong(); 2257 LLDB_LOG(log, "Discovered {0} Objective-C classes in the shared cache", 2258 num_class_infos); 2259 // Assert if there were more classes than we pre-allocated 2260 // room for. 2261 assert(num_class_infos <= max_num_classes); 2262 if (num_class_infos > 0) { 2263 if (num_class_infos > max_num_classes) { 2264 num_class_infos = max_num_classes; 2265 2266 success = false; 2267 } else { 2268 success = true; 2269 } 2270 2271 // Read the relative selector offset. 2272 DataBufferHeap relative_selector_offset_buffer(64, 0); 2273 if (process->ReadMemory(relative_selector_offset_addr, 2274 relative_selector_offset_buffer.GetBytes(), 2275 relative_selector_offset_buffer.GetByteSize(), 2276 err) == 2277 relative_selector_offset_buffer.GetByteSize()) { 2278 DataExtractor relative_selector_offset_data( 2279 relative_selector_offset_buffer.GetBytes(), 2280 relative_selector_offset_buffer.GetByteSize(), 2281 process->GetByteOrder(), addr_size); 2282 lldb::offset_t offset = 0; 2283 uint64_t relative_selector_offset = 2284 relative_selector_offset_data.GetU64(&offset); 2285 if (relative_selector_offset > 0) { 2286 // The offset is relative to the objc_opt struct. 2287 m_runtime.SetRelativeSelectorBaseAddr(objc_opt_ptr + 2288 relative_selector_offset); 2289 } 2290 } 2291 2292 // Read the ClassInfo structures 2293 DataBufferHeap class_infos_buffer( 2294 num_class_infos * class_info_byte_size, 0); 2295 if (process->ReadMemory(class_infos_addr, class_infos_buffer.GetBytes(), 2296 class_infos_buffer.GetByteSize(), 2297 err) == class_infos_buffer.GetByteSize()) { 2298 DataExtractor class_infos_data(class_infos_buffer.GetBytes(), 2299 class_infos_buffer.GetByteSize(), 2300 process->GetByteOrder(), addr_size); 2301 2302 m_runtime.ParseClassInfoArray(class_infos_data, num_class_infos); 2303 } 2304 } else { 2305 success = true; 2306 } 2307 } else { 2308 if (log) { 2309 LLDB_LOGF(log, "Error evaluating our find class name function."); 2310 diagnostics.Dump(log); 2311 } 2312 } 2313 } else { 2314 if (log) { 2315 LLDB_LOGF(log, "Error writing function arguments."); 2316 diagnostics.Dump(log); 2317 } 2318 } 2319 2320 // Deallocate the memory we allocated for the ClassInfo array 2321 process->DeallocateMemory(class_infos_addr); 2322 2323 return DescriptorMapUpdateResult(success, false, num_class_infos); 2324} 2325 2326lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() { 2327 Process *process = GetProcess(); 2328 2329 if (process) { 2330 ModuleSP objc_module_sp(GetObjCModule()); 2331 2332 if (objc_module_sp) { 2333 ObjectFile *objc_object = objc_module_sp->GetObjectFile(); 2334 2335 if (objc_object) { 2336 SectionList *section_list = objc_module_sp->GetSectionList(); 2337 2338 if (section_list) { 2339 SectionSP text_segment_sp( 2340 section_list->FindSectionByName(ConstString("__TEXT"))); 2341 2342 if (text_segment_sp) { 2343 SectionSP objc_opt_section_sp( 2344 text_segment_sp->GetChildren().FindSectionByName( 2345 ConstString("__objc_opt_ro"))); 2346 2347 if (objc_opt_section_sp) { 2348 return objc_opt_section_sp->GetLoadBaseAddress( 2349 &process->GetTarget()); 2350 } 2351 } 2352 } 2353 } 2354 } 2355 } 2356 return LLDB_INVALID_ADDRESS; 2357} 2358 2359lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheBaseAddress() { 2360 StructuredData::ObjectSP info = m_process->GetSharedCacheInfo(); 2361 if (!info) 2362 return LLDB_INVALID_ADDRESS; 2363 2364 StructuredData::Dictionary *info_dict = info->GetAsDictionary(); 2365 if (!info_dict) 2366 return LLDB_INVALID_ADDRESS; 2367 2368 StructuredData::ObjectSP value = 2369 info_dict->GetValueForKey("shared_cache_base_address"); 2370 if (!value) 2371 return LLDB_INVALID_ADDRESS; 2372 2373 return value->GetIntegerValue(LLDB_INVALID_ADDRESS); 2374} 2375 2376void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() { 2377 LLDB_SCOPED_TIMER(); 2378 2379 Log *log = GetLog(LLDBLog::Process | LLDBLog::Types); 2380 2381 // Else we need to check with our process to see when the map was updated. 2382 Process *process = GetProcess(); 2383 2384 if (process) { 2385 RemoteNXMapTable hash_table; 2386 2387 // Update the process stop ID that indicates the last time we updated the 2388 // map, whether it was successful or not. 2389 m_isa_to_descriptor_stop_id = process->GetStopID(); 2390 2391 // Ask the runtime is the realized class generation count changed. Unlike 2392 // the hash table, this accounts for lazily named classes. 2393 const bool class_count_changed = RealizedClassGenerationCountChanged(); 2394 2395 if (!m_hash_signature.NeedsUpdate(process, this, hash_table) && 2396 !class_count_changed) 2397 return; 2398 2399 m_hash_signature.UpdateSignature(hash_table); 2400 2401 // Grab the dynamically loaded Objective-C classes from memory. 2402 DescriptorMapUpdateResult dynamic_update_result = 2403 m_dynamic_class_info_extractor.UpdateISAToDescriptorMap(hash_table); 2404 2405 // Now get the objc classes that are baked into the Objective-C runtime in 2406 // the shared cache, but only once per process as this data never changes 2407 if (!m_loaded_objc_opt) { 2408 // it is legitimately possible for the shared cache to be empty - in that 2409 // case, the dynamic hash table will contain all the class information we 2410 // need; the situation we're trying to detect is one where we aren't 2411 // seeing class information from the runtime - in order to detect that 2412 // vs. just the shared cache being empty or sparsely populated, we set an 2413 // arbitrary (very low) threshold for the number of classes that we want 2414 // to see in a "good" scenario - anything below that is suspicious 2415 // (Foundation alone has thousands of classes) 2416 const uint32_t num_classes_to_warn_at = 500; 2417 2418 DescriptorMapUpdateResult shared_cache_update_result = 2419 m_shared_cache_class_info_extractor.UpdateISAToDescriptorMap(); 2420 2421 LLDB_LOGF(log, 2422 "attempted to read objc class data - results: " 2423 "[dynamic_update]: ran: %s, retry: %s, count: %" PRIu32 2424 " [shared_cache_update]: ran: %s, retry: %s, count: %" PRIu32, 2425 dynamic_update_result.m_update_ran ? "yes" : "no", 2426 dynamic_update_result.m_retry_update ? "yes" : "no", 2427 dynamic_update_result.m_num_found, 2428 shared_cache_update_result.m_update_ran ? "yes" : "no", 2429 shared_cache_update_result.m_retry_update ? "yes" : "no", 2430 shared_cache_update_result.m_num_found); 2431 2432 // warn if: 2433 // - we could not run either expression 2434 // - we found fewer than num_classes_to_warn_at classes total 2435 if (dynamic_update_result.m_retry_update || 2436 shared_cache_update_result.m_retry_update) 2437 WarnIfNoClassesCached(SharedCacheWarningReason::eExpressionUnableToRun); 2438 else if ((!shared_cache_update_result.m_update_ran) || 2439 (!dynamic_update_result.m_update_ran)) 2440 WarnIfNoClassesCached( 2441 SharedCacheWarningReason::eExpressionExecutionFailure); 2442 else if (dynamic_update_result.m_num_found + 2443 shared_cache_update_result.m_num_found < 2444 num_classes_to_warn_at) 2445 WarnIfNoClassesCached(SharedCacheWarningReason::eNotEnoughClassesRead); 2446 else 2447 m_loaded_objc_opt = true; 2448 } 2449 } else { 2450 m_isa_to_descriptor_stop_id = UINT32_MAX; 2451 } 2452} 2453 2454bool AppleObjCRuntimeV2::RealizedClassGenerationCountChanged() { 2455 Process *process = GetProcess(); 2456 if (!process) 2457 return false; 2458 2459 Status error; 2460 uint64_t objc_debug_realized_class_generation_count = 2461 ExtractRuntimeGlobalSymbol( 2462 process, ConstString("objc_debug_realized_class_generation_count"), 2463 GetObjCModule(), error); 2464 if (error.Fail()) 2465 return false; 2466 2467 if (m_realized_class_generation_count == 2468 objc_debug_realized_class_generation_count) 2469 return false; 2470 2471 Log *log = GetLog(LLDBLog::Process | LLDBLog::Types); 2472 LLDB_LOG(log, 2473 "objc_debug_realized_class_generation_count changed from {0} to {1}", 2474 m_realized_class_generation_count, 2475 objc_debug_realized_class_generation_count); 2476 2477 m_realized_class_generation_count = 2478 objc_debug_realized_class_generation_count; 2479 2480 return true; 2481} 2482 2483static bool DoesProcessHaveSharedCache(Process &process) { 2484 PlatformSP platform_sp = process.GetTarget().GetPlatform(); 2485 if (!platform_sp) 2486 return true; // this should not happen 2487 2488 llvm::StringRef platform_plugin_name_sr = platform_sp->GetPluginName(); 2489 if (platform_plugin_name_sr.endswith("-simulator")) 2490 return false; 2491 2492 return true; 2493} 2494 2495void AppleObjCRuntimeV2::WarnIfNoClassesCached( 2496 SharedCacheWarningReason reason) { 2497 if (GetProcess() && !DoesProcessHaveSharedCache(*GetProcess())) { 2498 // Simulators do not have the objc_opt_ro class table so don't actually 2499 // complain to the user 2500 return; 2501 } 2502 2503 Debugger &debugger(GetProcess()->GetTarget().GetDebugger()); 2504 switch (reason) { 2505 case SharedCacheWarningReason::eNotEnoughClassesRead: 2506 Debugger::ReportWarning("could not find Objective-C class data in " 2507 "the process. This may reduce the quality of type " 2508 "information available.\n", 2509 debugger.GetID(), &m_no_classes_cached_warning); 2510 break; 2511 case SharedCacheWarningReason::eExpressionExecutionFailure: 2512 Debugger::ReportWarning( 2513 "could not execute support code to read " 2514 "Objective-C class data in the process. This may " 2515 "reduce the quality of type information available.\n", 2516 debugger.GetID(), &m_no_classes_cached_warning); 2517 break; 2518 case SharedCacheWarningReason::eExpressionUnableToRun: 2519 Debugger::ReportWarning( 2520 "could not execute support code to read Objective-C class data because " 2521 "it's not yet safe to do so, and will be retried later.\n", 2522 debugger.GetID(), nullptr); 2523 break; 2524 } 2525} 2526 2527void AppleObjCRuntimeV2::WarnIfNoExpandedSharedCache() { 2528 if (!m_objc_module_sp) 2529 return; 2530 2531 ObjectFile *object_file = m_objc_module_sp->GetObjectFile(); 2532 if (!object_file) 2533 return; 2534 2535 if (!object_file->IsInMemory()) 2536 return; 2537 2538 Target &target = GetProcess()->GetTarget(); 2539 Debugger &debugger = target.GetDebugger(); 2540 2541 std::string buffer; 2542 llvm::raw_string_ostream os(buffer); 2543 2544 os << "libobjc.A.dylib is being read from process memory. This " 2545 "indicates that LLDB could not "; 2546 if (PlatformSP platform_sp = target.GetPlatform()) { 2547 if (platform_sp->IsHost()) { 2548 os << "read from the host's in-memory shared cache"; 2549 } else { 2550 os << "find the on-disk shared cache for this device"; 2551 } 2552 } else { 2553 os << "read from the shared cache"; 2554 } 2555 os << ". This will likely reduce debugging performance.\n"; 2556 2557 Debugger::ReportWarning(os.str(), debugger.GetID(), 2558 &m_no_expanded_cache_warning); 2559} 2560 2561DeclVendor *AppleObjCRuntimeV2::GetDeclVendor() { 2562 if (!m_decl_vendor_up) 2563 m_decl_vendor_up = std::make_unique<AppleObjCDeclVendor>(*this); 2564 2565 return m_decl_vendor_up.get(); 2566} 2567 2568lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(ConstString name) { 2569 lldb::addr_t ret = LLDB_INVALID_ADDRESS; 2570 2571 const char *name_cstr = name.AsCString(); 2572 2573 if (name_cstr) { 2574 llvm::StringRef name_strref(name_cstr); 2575 2576 llvm::StringRef ivar_prefix("OBJC_IVAR_$_"); 2577 llvm::StringRef class_prefix("OBJC_CLASS_$_"); 2578 2579 if (name_strref.startswith(ivar_prefix)) { 2580 llvm::StringRef ivar_skipped_prefix = 2581 name_strref.substr(ivar_prefix.size()); 2582 std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar = 2583 ivar_skipped_prefix.split('.'); 2584 2585 if (class_and_ivar.first.size() && class_and_ivar.second.size()) { 2586 const ConstString class_name_cs(class_and_ivar.first); 2587 ClassDescriptorSP descriptor = 2588 ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs); 2589 2590 if (descriptor) { 2591 const ConstString ivar_name_cs(class_and_ivar.second); 2592 const char *ivar_name_cstr = ivar_name_cs.AsCString(); 2593 2594 auto ivar_func = [&ret, 2595 ivar_name_cstr](const char *name, const char *type, 2596 lldb::addr_t offset_addr, 2597 uint64_t size) -> lldb::addr_t { 2598 if (!strcmp(name, ivar_name_cstr)) { 2599 ret = offset_addr; 2600 return true; 2601 } 2602 return false; 2603 }; 2604 2605 descriptor->Describe( 2606 std::function<void(ObjCISA)>(nullptr), 2607 std::function<bool(const char *, const char *)>(nullptr), 2608 std::function<bool(const char *, const char *)>(nullptr), 2609 ivar_func); 2610 } 2611 } 2612 } else if (name_strref.startswith(class_prefix)) { 2613 llvm::StringRef class_skipped_prefix = 2614 name_strref.substr(class_prefix.size()); 2615 const ConstString class_name_cs(class_skipped_prefix); 2616 ClassDescriptorSP descriptor = 2617 GetClassDescriptorFromClassName(class_name_cs); 2618 2619 if (descriptor) 2620 ret = descriptor->GetISA(); 2621 } 2622 } 2623 2624 return ret; 2625} 2626 2627AppleObjCRuntimeV2::NonPointerISACache * 2628AppleObjCRuntimeV2::NonPointerISACache::CreateInstance( 2629 AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp) { 2630 Process *process(runtime.GetProcess()); 2631 2632 Status error; 2633 2634 Log *log = GetLog(LLDBLog::Types); 2635 2636 auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol( 2637 process, ConstString("objc_debug_isa_magic_mask"), objc_module_sp, error); 2638 if (error.Fail()) 2639 return nullptr; 2640 2641 auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol( 2642 process, ConstString("objc_debug_isa_magic_value"), objc_module_sp, 2643 error); 2644 if (error.Fail()) 2645 return nullptr; 2646 2647 auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol( 2648 process, ConstString("objc_debug_isa_class_mask"), objc_module_sp, error); 2649 if (error.Fail()) 2650 return nullptr; 2651 2652 if (log) 2653 log->PutCString("AOCRT::NPI: Found all the non-indexed ISA masks"); 2654 2655 bool foundError = false; 2656 auto objc_debug_indexed_isa_magic_mask = ExtractRuntimeGlobalSymbol( 2657 process, ConstString("objc_debug_indexed_isa_magic_mask"), objc_module_sp, 2658 error); 2659 foundError |= error.Fail(); 2660 2661 auto objc_debug_indexed_isa_magic_value = ExtractRuntimeGlobalSymbol( 2662 process, ConstString("objc_debug_indexed_isa_magic_value"), 2663 objc_module_sp, error); 2664 foundError |= error.Fail(); 2665 2666 auto objc_debug_indexed_isa_index_mask = ExtractRuntimeGlobalSymbol( 2667 process, ConstString("objc_debug_indexed_isa_index_mask"), objc_module_sp, 2668 error); 2669 foundError |= error.Fail(); 2670 2671 auto objc_debug_indexed_isa_index_shift = ExtractRuntimeGlobalSymbol( 2672 process, ConstString("objc_debug_indexed_isa_index_shift"), 2673 objc_module_sp, error); 2674 foundError |= error.Fail(); 2675 2676 auto objc_indexed_classes = 2677 ExtractRuntimeGlobalSymbol(process, ConstString("objc_indexed_classes"), 2678 objc_module_sp, error, false); 2679 foundError |= error.Fail(); 2680 2681 if (log) 2682 log->PutCString("AOCRT::NPI: Found all the indexed ISA masks"); 2683 2684 // we might want to have some rules to outlaw these other values (e.g if the 2685 // mask is zero but the value is non-zero, ...) 2686 2687 return new NonPointerISACache( 2688 runtime, objc_module_sp, objc_debug_isa_class_mask, 2689 objc_debug_isa_magic_mask, objc_debug_isa_magic_value, 2690 objc_debug_indexed_isa_magic_mask, objc_debug_indexed_isa_magic_value, 2691 objc_debug_indexed_isa_index_mask, objc_debug_indexed_isa_index_shift, 2692 foundError ? 0 : objc_indexed_classes); 2693} 2694 2695AppleObjCRuntimeV2::TaggedPointerVendorV2 * 2696AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance( 2697 AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp) { 2698 Process *process(runtime.GetProcess()); 2699 2700 Status error; 2701 2702 auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol( 2703 process, ConstString("objc_debug_taggedpointer_mask"), objc_module_sp, 2704 error); 2705 if (error.Fail()) 2706 return new TaggedPointerVendorLegacy(runtime); 2707 2708 auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol( 2709 process, ConstString("objc_debug_taggedpointer_slot_shift"), 2710 objc_module_sp, error, true, 4); 2711 if (error.Fail()) 2712 return new TaggedPointerVendorLegacy(runtime); 2713 2714 auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol( 2715 process, ConstString("objc_debug_taggedpointer_slot_mask"), 2716 objc_module_sp, error, true, 4); 2717 if (error.Fail()) 2718 return new TaggedPointerVendorLegacy(runtime); 2719 2720 auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol( 2721 process, ConstString("objc_debug_taggedpointer_payload_lshift"), 2722 objc_module_sp, error, true, 4); 2723 if (error.Fail()) 2724 return new TaggedPointerVendorLegacy(runtime); 2725 2726 auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol( 2727 process, ConstString("objc_debug_taggedpointer_payload_rshift"), 2728 objc_module_sp, error, true, 4); 2729 if (error.Fail()) 2730 return new TaggedPointerVendorLegacy(runtime); 2731 2732 auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol( 2733 process, ConstString("objc_debug_taggedpointer_classes"), objc_module_sp, 2734 error, false); 2735 if (error.Fail()) 2736 return new TaggedPointerVendorLegacy(runtime); 2737 2738 // try to detect the "extended tagged pointer" variables - if any are 2739 // missing, use the non-extended vendor 2740 do { 2741 auto objc_debug_taggedpointer_ext_mask = ExtractRuntimeGlobalSymbol( 2742 process, ConstString("objc_debug_taggedpointer_ext_mask"), 2743 objc_module_sp, error); 2744 if (error.Fail()) 2745 break; 2746 2747 auto objc_debug_taggedpointer_ext_slot_shift = ExtractRuntimeGlobalSymbol( 2748 process, ConstString("objc_debug_taggedpointer_ext_slot_shift"), 2749 objc_module_sp, error, true, 4); 2750 if (error.Fail()) 2751 break; 2752 2753 auto objc_debug_taggedpointer_ext_slot_mask = ExtractRuntimeGlobalSymbol( 2754 process, ConstString("objc_debug_taggedpointer_ext_slot_mask"), 2755 objc_module_sp, error, true, 4); 2756 if (error.Fail()) 2757 break; 2758 2759 auto objc_debug_taggedpointer_ext_classes = ExtractRuntimeGlobalSymbol( 2760 process, ConstString("objc_debug_taggedpointer_ext_classes"), 2761 objc_module_sp, error, false); 2762 if (error.Fail()) 2763 break; 2764 2765 auto objc_debug_taggedpointer_ext_payload_lshift = 2766 ExtractRuntimeGlobalSymbol( 2767 process, ConstString("objc_debug_taggedpointer_ext_payload_lshift"), 2768 objc_module_sp, error, true, 4); 2769 if (error.Fail()) 2770 break; 2771 2772 auto objc_debug_taggedpointer_ext_payload_rshift = 2773 ExtractRuntimeGlobalSymbol( 2774 process, ConstString("objc_debug_taggedpointer_ext_payload_rshift"), 2775 objc_module_sp, error, true, 4); 2776 if (error.Fail()) 2777 break; 2778 2779 return new TaggedPointerVendorExtended( 2780 runtime, objc_debug_taggedpointer_mask, 2781 objc_debug_taggedpointer_ext_mask, objc_debug_taggedpointer_slot_shift, 2782 objc_debug_taggedpointer_ext_slot_shift, 2783 objc_debug_taggedpointer_slot_mask, 2784 objc_debug_taggedpointer_ext_slot_mask, 2785 objc_debug_taggedpointer_payload_lshift, 2786 objc_debug_taggedpointer_payload_rshift, 2787 objc_debug_taggedpointer_ext_payload_lshift, 2788 objc_debug_taggedpointer_ext_payload_rshift, 2789 objc_debug_taggedpointer_classes, objc_debug_taggedpointer_ext_classes); 2790 } while (false); 2791 2792 // we might want to have some rules to outlaw these values (e.g if the 2793 // table's address is zero) 2794 2795 return new TaggedPointerVendorRuntimeAssisted( 2796 runtime, objc_debug_taggedpointer_mask, 2797 objc_debug_taggedpointer_slot_shift, objc_debug_taggedpointer_slot_mask, 2798 objc_debug_taggedpointer_payload_lshift, 2799 objc_debug_taggedpointer_payload_rshift, 2800 objc_debug_taggedpointer_classes); 2801} 2802 2803bool AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer( 2804 lldb::addr_t ptr) { 2805 return (ptr & 1); 2806} 2807 2808ObjCLanguageRuntime::ClassDescriptorSP 2809AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor( 2810 lldb::addr_t ptr) { 2811 if (!IsPossibleTaggedPointer(ptr)) 2812 return ObjCLanguageRuntime::ClassDescriptorSP(); 2813 2814 uint32_t foundation_version = m_runtime.GetFoundationVersion(); 2815 2816 if (foundation_version == LLDB_INVALID_MODULE_VERSION) 2817 return ObjCLanguageRuntime::ClassDescriptorSP(); 2818 2819 uint64_t class_bits = (ptr & 0xE) >> 1; 2820 ConstString name; 2821 2822 static ConstString g_NSAtom("NSAtom"); 2823 static ConstString g_NSNumber("NSNumber"); 2824 static ConstString g_NSDateTS("NSDateTS"); 2825 static ConstString g_NSManagedObject("NSManagedObject"); 2826 static ConstString g_NSDate("NSDate"); 2827 2828 if (foundation_version >= 900) { 2829 switch (class_bits) { 2830 case 0: 2831 name = g_NSAtom; 2832 break; 2833 case 3: 2834 name = g_NSNumber; 2835 break; 2836 case 4: 2837 name = g_NSDateTS; 2838 break; 2839 case 5: 2840 name = g_NSManagedObject; 2841 break; 2842 case 6: 2843 name = g_NSDate; 2844 break; 2845 default: 2846 return ObjCLanguageRuntime::ClassDescriptorSP(); 2847 } 2848 } else { 2849 switch (class_bits) { 2850 case 1: 2851 name = g_NSNumber; 2852 break; 2853 case 5: 2854 name = g_NSManagedObject; 2855 break; 2856 case 6: 2857 name = g_NSDate; 2858 break; 2859 case 7: 2860 name = g_NSDateTS; 2861 break; 2862 default: 2863 return ObjCLanguageRuntime::ClassDescriptorSP(); 2864 } 2865 } 2866 2867 lldb::addr_t unobfuscated = ptr ^ m_runtime.GetTaggedPointerObfuscator(); 2868 return ClassDescriptorSP(new ClassDescriptorV2Tagged(name, unobfuscated)); 2869} 2870 2871AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted:: 2872 TaggedPointerVendorRuntimeAssisted( 2873 AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask, 2874 uint32_t objc_debug_taggedpointer_slot_shift, 2875 uint32_t objc_debug_taggedpointer_slot_mask, 2876 uint32_t objc_debug_taggedpointer_payload_lshift, 2877 uint32_t objc_debug_taggedpointer_payload_rshift, 2878 lldb::addr_t objc_debug_taggedpointer_classes) 2879 : TaggedPointerVendorV2(runtime), m_cache(), 2880 m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask), 2881 m_objc_debug_taggedpointer_slot_shift( 2882 objc_debug_taggedpointer_slot_shift), 2883 m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask), 2884 m_objc_debug_taggedpointer_payload_lshift( 2885 objc_debug_taggedpointer_payload_lshift), 2886 m_objc_debug_taggedpointer_payload_rshift( 2887 objc_debug_taggedpointer_payload_rshift), 2888 m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes) {} 2889 2890bool AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted:: 2891 IsPossibleTaggedPointer(lldb::addr_t ptr) { 2892 return (ptr & m_objc_debug_taggedpointer_mask) != 0; 2893} 2894 2895ObjCLanguageRuntime::ClassDescriptorSP 2896AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor( 2897 lldb::addr_t ptr) { 2898 ClassDescriptorSP actual_class_descriptor_sp; 2899 uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator(); 2900 2901 if (!IsPossibleTaggedPointer(unobfuscated)) 2902 return ObjCLanguageRuntime::ClassDescriptorSP(); 2903 2904 uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) & 2905 m_objc_debug_taggedpointer_slot_mask; 2906 2907 CacheIterator iterator = m_cache.find(slot), end = m_cache.end(); 2908 if (iterator != end) { 2909 actual_class_descriptor_sp = iterator->second; 2910 } else { 2911 Process *process(m_runtime.GetProcess()); 2912 uintptr_t slot_ptr = slot * process->GetAddressByteSize() + 2913 m_objc_debug_taggedpointer_classes; 2914 Status error; 2915 uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error); 2916 if (error.Fail() || slot_data == 0 || 2917 slot_data == uintptr_t(LLDB_INVALID_ADDRESS)) 2918 return nullptr; 2919 actual_class_descriptor_sp = 2920 m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data); 2921 if (!actual_class_descriptor_sp) { 2922 if (ABISP abi_sp = process->GetABI()) { 2923 ObjCISA fixed_isa = abi_sp->FixCodeAddress((ObjCISA)slot_data); 2924 actual_class_descriptor_sp = 2925 m_runtime.GetClassDescriptorFromISA(fixed_isa); 2926 } 2927 } 2928 if (!actual_class_descriptor_sp) 2929 return ObjCLanguageRuntime::ClassDescriptorSP(); 2930 m_cache[slot] = actual_class_descriptor_sp; 2931 } 2932 2933 uint64_t data_payload = 2934 ((unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >> 2935 m_objc_debug_taggedpointer_payload_rshift); 2936 int64_t data_payload_signed = 2937 ((int64_t)(unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >> 2938 m_objc_debug_taggedpointer_payload_rshift); 2939 return ClassDescriptorSP(new ClassDescriptorV2Tagged( 2940 actual_class_descriptor_sp, data_payload, data_payload_signed)); 2941} 2942 2943AppleObjCRuntimeV2::TaggedPointerVendorExtended::TaggedPointerVendorExtended( 2944 AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask, 2945 uint64_t objc_debug_taggedpointer_ext_mask, 2946 uint32_t objc_debug_taggedpointer_slot_shift, 2947 uint32_t objc_debug_taggedpointer_ext_slot_shift, 2948 uint32_t objc_debug_taggedpointer_slot_mask, 2949 uint32_t objc_debug_taggedpointer_ext_slot_mask, 2950 uint32_t objc_debug_taggedpointer_payload_lshift, 2951 uint32_t objc_debug_taggedpointer_payload_rshift, 2952 uint32_t objc_debug_taggedpointer_ext_payload_lshift, 2953 uint32_t objc_debug_taggedpointer_ext_payload_rshift, 2954 lldb::addr_t objc_debug_taggedpointer_classes, 2955 lldb::addr_t objc_debug_taggedpointer_ext_classes) 2956 : TaggedPointerVendorRuntimeAssisted( 2957 runtime, objc_debug_taggedpointer_mask, 2958 objc_debug_taggedpointer_slot_shift, 2959 objc_debug_taggedpointer_slot_mask, 2960 objc_debug_taggedpointer_payload_lshift, 2961 objc_debug_taggedpointer_payload_rshift, 2962 objc_debug_taggedpointer_classes), 2963 m_ext_cache(), 2964 m_objc_debug_taggedpointer_ext_mask(objc_debug_taggedpointer_ext_mask), 2965 m_objc_debug_taggedpointer_ext_slot_shift( 2966 objc_debug_taggedpointer_ext_slot_shift), 2967 m_objc_debug_taggedpointer_ext_slot_mask( 2968 objc_debug_taggedpointer_ext_slot_mask), 2969 m_objc_debug_taggedpointer_ext_payload_lshift( 2970 objc_debug_taggedpointer_ext_payload_lshift), 2971 m_objc_debug_taggedpointer_ext_payload_rshift( 2972 objc_debug_taggedpointer_ext_payload_rshift), 2973 m_objc_debug_taggedpointer_ext_classes( 2974 objc_debug_taggedpointer_ext_classes) {} 2975 2976bool AppleObjCRuntimeV2::TaggedPointerVendorExtended:: 2977 IsPossibleExtendedTaggedPointer(lldb::addr_t ptr) { 2978 if (!IsPossibleTaggedPointer(ptr)) 2979 return false; 2980 2981 if (m_objc_debug_taggedpointer_ext_mask == 0) 2982 return false; 2983 2984 return ((ptr & m_objc_debug_taggedpointer_ext_mask) == 2985 m_objc_debug_taggedpointer_ext_mask); 2986} 2987 2988ObjCLanguageRuntime::ClassDescriptorSP 2989AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor( 2990 lldb::addr_t ptr) { 2991 ClassDescriptorSP actual_class_descriptor_sp; 2992 uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator(); 2993 2994 if (!IsPossibleTaggedPointer(unobfuscated)) 2995 return ObjCLanguageRuntime::ClassDescriptorSP(); 2996 2997 if (!IsPossibleExtendedTaggedPointer(unobfuscated)) 2998 return this->TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(ptr); 2999 3000 uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_ext_slot_shift) & 3001 m_objc_debug_taggedpointer_ext_slot_mask; 3002 3003 CacheIterator iterator = m_ext_cache.find(slot), end = m_ext_cache.end(); 3004 if (iterator != end) { 3005 actual_class_descriptor_sp = iterator->second; 3006 } else { 3007 Process *process(m_runtime.GetProcess()); 3008 uintptr_t slot_ptr = slot * process->GetAddressByteSize() + 3009 m_objc_debug_taggedpointer_ext_classes; 3010 Status error; 3011 uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error); 3012 if (error.Fail() || slot_data == 0 || 3013 slot_data == uintptr_t(LLDB_INVALID_ADDRESS)) 3014 return nullptr; 3015 actual_class_descriptor_sp = 3016 m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data); 3017 if (!actual_class_descriptor_sp) 3018 return ObjCLanguageRuntime::ClassDescriptorSP(); 3019 m_ext_cache[slot] = actual_class_descriptor_sp; 3020 } 3021 3022 uint64_t data_payload = (((uint64_t)unobfuscated 3023 << m_objc_debug_taggedpointer_ext_payload_lshift) >> 3024 m_objc_debug_taggedpointer_ext_payload_rshift); 3025 int64_t data_payload_signed = 3026 ((int64_t)((int64_t)unobfuscated 3027 << m_objc_debug_taggedpointer_ext_payload_lshift) >> 3028 m_objc_debug_taggedpointer_ext_payload_rshift); 3029 3030 return ClassDescriptorSP(new ClassDescriptorV2Tagged( 3031 actual_class_descriptor_sp, data_payload, data_payload_signed)); 3032} 3033 3034AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache( 3035 AppleObjCRuntimeV2 &runtime, const ModuleSP &objc_module_sp, 3036 uint64_t objc_debug_isa_class_mask, uint64_t objc_debug_isa_magic_mask, 3037 uint64_t objc_debug_isa_magic_value, 3038 uint64_t objc_debug_indexed_isa_magic_mask, 3039 uint64_t objc_debug_indexed_isa_magic_value, 3040 uint64_t objc_debug_indexed_isa_index_mask, 3041 uint64_t objc_debug_indexed_isa_index_shift, 3042 lldb::addr_t objc_indexed_classes) 3043 : m_runtime(runtime), m_cache(), m_objc_module_wp(objc_module_sp), 3044 m_objc_debug_isa_class_mask(objc_debug_isa_class_mask), 3045 m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask), 3046 m_objc_debug_isa_magic_value(objc_debug_isa_magic_value), 3047 m_objc_debug_indexed_isa_magic_mask(objc_debug_indexed_isa_magic_mask), 3048 m_objc_debug_indexed_isa_magic_value(objc_debug_indexed_isa_magic_value), 3049 m_objc_debug_indexed_isa_index_mask(objc_debug_indexed_isa_index_mask), 3050 m_objc_debug_indexed_isa_index_shift(objc_debug_indexed_isa_index_shift), 3051 m_objc_indexed_classes(objc_indexed_classes), m_indexed_isa_cache() {} 3052 3053ObjCLanguageRuntime::ClassDescriptorSP 3054AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor(ObjCISA isa) { 3055 ObjCISA real_isa = 0; 3056 if (!EvaluateNonPointerISA(isa, real_isa)) 3057 return ObjCLanguageRuntime::ClassDescriptorSP(); 3058 auto cache_iter = m_cache.find(real_isa); 3059 if (cache_iter != m_cache.end()) 3060 return cache_iter->second; 3061 auto descriptor_sp = 3062 m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa); 3063 if (descriptor_sp) // cache only positive matches since the table might grow 3064 m_cache[real_isa] = descriptor_sp; 3065 return descriptor_sp; 3066} 3067 3068bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( 3069 ObjCISA isa, ObjCISA &ret_isa) { 3070 Log *log = GetLog(LLDBLog::Types); 3071 3072 LLDB_LOGF(log, "AOCRT::NPI Evaluate(isa = 0x%" PRIx64 ")", (uint64_t)isa); 3073 3074 if ((isa & ~m_objc_debug_isa_class_mask) == 0) 3075 return false; 3076 3077 // If all of the indexed ISA variables are set, then its possible that this 3078 // ISA is indexed, and we should first try to get its value using the index. 3079 // Note, we check these variables first as the ObjC runtime will set at least 3080 // one of their values to 0 if they aren't needed. 3081 if (m_objc_debug_indexed_isa_magic_mask && 3082 m_objc_debug_indexed_isa_magic_value && 3083 m_objc_debug_indexed_isa_index_mask && 3084 m_objc_debug_indexed_isa_index_shift && m_objc_indexed_classes) { 3085 if ((isa & ~m_objc_debug_indexed_isa_index_mask) == 0) 3086 return false; 3087 3088 if ((isa & m_objc_debug_indexed_isa_magic_mask) == 3089 m_objc_debug_indexed_isa_magic_value) { 3090 // Magic bits are correct, so try extract the index. 3091 uintptr_t index = (isa & m_objc_debug_indexed_isa_index_mask) >> 3092 m_objc_debug_indexed_isa_index_shift; 3093 // If the index is out of bounds of the length of the array then check if 3094 // the array has been updated. If that is the case then we should try 3095 // read the count again, and update the cache if the count has been 3096 // updated. 3097 if (index > m_indexed_isa_cache.size()) { 3098 LLDB_LOGF(log, 3099 "AOCRT::NPI (index = %" PRIu64 3100 ") exceeds cache (size = %" PRIu64 ")", 3101 (uint64_t)index, (uint64_t)m_indexed_isa_cache.size()); 3102 3103 Process *process(m_runtime.GetProcess()); 3104 3105 ModuleSP objc_module_sp(m_objc_module_wp.lock()); 3106 if (!objc_module_sp) 3107 return false; 3108 3109 Status error; 3110 auto objc_indexed_classes_count = ExtractRuntimeGlobalSymbol( 3111 process, ConstString("objc_indexed_classes_count"), objc_module_sp, 3112 error); 3113 if (error.Fail()) 3114 return false; 3115 3116 LLDB_LOGF(log, "AOCRT::NPI (new class count = %" PRIu64 ")", 3117 (uint64_t)objc_indexed_classes_count); 3118 3119 if (objc_indexed_classes_count > m_indexed_isa_cache.size()) { 3120 // Read the class entries we don't have. We should just read all of 3121 // them instead of just the one we need as then we can cache those we 3122 // may need later. 3123 auto num_new_classes = 3124 objc_indexed_classes_count - m_indexed_isa_cache.size(); 3125 const uint32_t addr_size = process->GetAddressByteSize(); 3126 DataBufferHeap buffer(num_new_classes * addr_size, 0); 3127 3128 lldb::addr_t last_read_class = 3129 m_objc_indexed_classes + (m_indexed_isa_cache.size() * addr_size); 3130 size_t bytes_read = process->ReadMemory( 3131 last_read_class, buffer.GetBytes(), buffer.GetByteSize(), error); 3132 if (error.Fail() || bytes_read != buffer.GetByteSize()) 3133 return false; 3134 3135 LLDB_LOGF(log, "AOCRT::NPI (read new classes count = %" PRIu64 ")", 3136 (uint64_t)num_new_classes); 3137 3138 // Append the new entries to the existing cache. 3139 DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), 3140 process->GetByteOrder(), 3141 process->GetAddressByteSize()); 3142 3143 lldb::offset_t offset = 0; 3144 for (unsigned i = 0; i != num_new_classes; ++i) 3145 m_indexed_isa_cache.push_back(data.GetAddress(&offset)); 3146 } 3147 } 3148 3149 // If the index is still out of range then this isn't a pointer. 3150 if (index > m_indexed_isa_cache.size()) 3151 return false; 3152 3153 LLDB_LOGF(log, "AOCRT::NPI Evaluate(ret_isa = 0x%" PRIx64 ")", 3154 (uint64_t)m_indexed_isa_cache[index]); 3155 3156 ret_isa = m_indexed_isa_cache[index]; 3157 return (ret_isa != 0); // this is a pointer so 0 is not a valid value 3158 } 3159 3160 return false; 3161 } 3162 3163 // Definitely not an indexed ISA, so try to use a mask to extract the pointer 3164 // from the ISA. 3165 if ((isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value) { 3166 ret_isa = isa & m_objc_debug_isa_class_mask; 3167 return (ret_isa != 0); // this is a pointer so 0 is not a valid value 3168 } 3169 return false; 3170} 3171 3172ObjCLanguageRuntime::EncodingToTypeSP AppleObjCRuntimeV2::GetEncodingToType() { 3173 if (!m_encoding_to_type_sp) 3174 m_encoding_to_type_sp = 3175 std::make_shared<AppleObjCTypeEncodingParser>(*this); 3176 return m_encoding_to_type_sp; 3177} 3178 3179lldb_private::AppleObjCRuntime::ObjCISA 3180AppleObjCRuntimeV2::GetPointerISA(ObjCISA isa) { 3181 ObjCISA ret = isa; 3182 3183 if (auto *non_pointer_isa_cache = GetNonPointerIsaCache()) 3184 non_pointer_isa_cache->EvaluateNonPointerISA(isa, ret); 3185 3186 return ret; 3187} 3188 3189bool AppleObjCRuntimeV2::GetCFBooleanValuesIfNeeded() { 3190 if (m_CFBoolean_values) 3191 return true; 3192 3193 static ConstString g_dunder_kCFBooleanFalse("__kCFBooleanFalse"); 3194 static ConstString g_dunder_kCFBooleanTrue("__kCFBooleanTrue"); 3195 static ConstString g_kCFBooleanFalse("kCFBooleanFalse"); 3196 static ConstString g_kCFBooleanTrue("kCFBooleanTrue"); 3197 3198 std::function<lldb::addr_t(ConstString, ConstString)> get_symbol = 3199 [this](ConstString sym, ConstString real_sym) -> lldb::addr_t { 3200 SymbolContextList sc_list; 3201 GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType( 3202 sym, lldb::eSymbolTypeData, sc_list); 3203 if (sc_list.GetSize() == 1) { 3204 SymbolContext sc; 3205 sc_list.GetContextAtIndex(0, sc); 3206 if (sc.symbol) 3207 return sc.symbol->GetLoadAddress(&GetProcess()->GetTarget()); 3208 } 3209 GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType( 3210 real_sym, lldb::eSymbolTypeData, sc_list); 3211 if (sc_list.GetSize() != 1) 3212 return LLDB_INVALID_ADDRESS; 3213 3214 SymbolContext sc; 3215 sc_list.GetContextAtIndex(0, sc); 3216 if (!sc.symbol) 3217 return LLDB_INVALID_ADDRESS; 3218 3219 lldb::addr_t addr = sc.symbol->GetLoadAddress(&GetProcess()->GetTarget()); 3220 Status error; 3221 addr = GetProcess()->ReadPointerFromMemory(addr, error); 3222 if (error.Fail()) 3223 return LLDB_INVALID_ADDRESS; 3224 return addr; 3225 }; 3226 3227 lldb::addr_t false_addr = get_symbol(g_dunder_kCFBooleanFalse, g_kCFBooleanFalse); 3228 lldb::addr_t true_addr = get_symbol(g_dunder_kCFBooleanTrue, g_kCFBooleanTrue); 3229 3230 return (m_CFBoolean_values = {false_addr, true_addr}).operator bool(); 3231} 3232 3233void AppleObjCRuntimeV2::GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true, 3234 lldb::addr_t &cf_false) { 3235 if (GetCFBooleanValuesIfNeeded()) { 3236 cf_true = m_CFBoolean_values->second; 3237 cf_false = m_CFBoolean_values->first; 3238 } else 3239 this->AppleObjCRuntime::GetValuesForGlobalCFBooleans(cf_true, cf_false); 3240} 3241 3242#pragma mark Frame recognizers 3243 3244class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame { 3245public: 3246 ObjCExceptionRecognizedStackFrame(StackFrameSP frame_sp) { 3247 ThreadSP thread_sp = frame_sp->GetThread(); 3248 ProcessSP process_sp = thread_sp->GetProcess(); 3249 3250 const lldb::ABISP &abi = process_sp->GetABI(); 3251 if (!abi) 3252 return; 3253 3254 TypeSystemClangSP scratch_ts_sp = 3255 ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget()); 3256 if (!scratch_ts_sp) 3257 return; 3258 CompilerType voidstar = 3259 scratch_ts_sp->GetBasicType(lldb::eBasicTypeVoid).GetPointerType(); 3260 3261 ValueList args; 3262 Value input_value; 3263 input_value.SetCompilerType(voidstar); 3264 args.PushValue(input_value); 3265 3266 if (!abi->GetArgumentValues(*thread_sp, args)) 3267 return; 3268 3269 addr_t exception_addr = args.GetValueAtIndex(0)->GetScalar().ULongLong(); 3270 3271 Value value(exception_addr); 3272 value.SetCompilerType(voidstar); 3273 exception = ValueObjectConstResult::Create(frame_sp.get(), value, 3274 ConstString("exception")); 3275 exception = ValueObjectRecognizerSynthesizedValue::Create( 3276 *exception, eValueTypeVariableArgument); 3277 exception = exception->GetDynamicValue(eDynamicDontRunTarget); 3278 3279 m_arguments = ValueObjectListSP(new ValueObjectList()); 3280 m_arguments->Append(exception); 3281 3282 m_stop_desc = "hit Objective-C exception"; 3283 } 3284 3285 ValueObjectSP exception; 3286 3287 lldb::ValueObjectSP GetExceptionObject() override { return exception; } 3288}; 3289 3290class ObjCExceptionThrowFrameRecognizer : public StackFrameRecognizer { 3291 lldb::RecognizedStackFrameSP 3292 RecognizeFrame(lldb::StackFrameSP frame) override { 3293 return lldb::RecognizedStackFrameSP( 3294 new ObjCExceptionRecognizedStackFrame(frame)); 3295 }; 3296 std::string GetName() override { 3297 return "ObjC Exception Throw StackFrame Recognizer"; 3298 } 3299}; 3300 3301static void RegisterObjCExceptionRecognizer(Process *process) { 3302 FileSpec module; 3303 ConstString function; 3304 std::tie(module, function) = AppleObjCRuntime::GetExceptionThrowLocation(); 3305 std::vector<ConstString> symbols = {function}; 3306 3307 process->GetTarget().GetFrameRecognizerManager().AddRecognizer( 3308 StackFrameRecognizerSP(new ObjCExceptionThrowFrameRecognizer()), 3309 module.GetFilename(), symbols, 3310 /*first_instruction_only*/ true); 3311} 3312