AppleObjCRuntimeV2.cpp revision 309124
1//===-- AppleObjCRuntimeV2.cpp ----------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10// C Includes 11#include <stdint.h> 12 13// C++ Includes 14#include <string> 15#include <vector> 16 17// Other libraries and framework includes 18#include "clang/AST/ASTContext.h" 19#include "clang/AST/DeclObjC.h" 20 21// Project includes 22#include "lldb/lldb-enumerations.h" 23#include "lldb/Core/ClangForward.h" 24#include "lldb/Symbol/CompilerType.h" 25 26#include "lldb/Core/ClangForward.h" 27#include "lldb/Core/ConstString.h" 28#include "lldb/Core/Debugger.h" 29#include "lldb/Core/Error.h" 30#include "lldb/Core/Log.h" 31#include "lldb/Core/Module.h" 32#include "lldb/Core/PluginManager.h" 33#include "lldb/Core/Scalar.h" 34#include "lldb/Core/Section.h" 35#include "lldb/Core/Stream.h" 36#include "lldb/Core/StreamString.h" 37#include "lldb/Core/Timer.h" 38#include "lldb/Core/ValueObjectVariable.h" 39#include "lldb/Expression/DiagnosticManager.h" 40#include "lldb/Expression/FunctionCaller.h" 41#include "lldb/Expression/UtilityFunction.h" 42#include "lldb/Host/StringConvert.h" 43#include "lldb/Interpreter/CommandObject.h" 44#include "lldb/Interpreter/CommandObjectMultiword.h" 45#include "lldb/Interpreter/CommandReturnObject.h" 46#include "lldb/Interpreter/OptionValueBoolean.h" 47#include "lldb/Symbol/ClangASTContext.h" 48#include "lldb/Symbol/ObjectFile.h" 49#include "lldb/Symbol/Symbol.h" 50#include "lldb/Symbol/TypeList.h" 51#include "lldb/Symbol/VariableList.h" 52#include "lldb/Target/ExecutionContext.h" 53#include "lldb/Target/Platform.h" 54#include "lldb/Target/Process.h" 55#include "lldb/Target/RegisterContext.h" 56#include "lldb/Target/Target.h" 57#include "lldb/Target/Thread.h" 58 59#include "AppleObjCRuntimeV2.h" 60#include "AppleObjCClassDescriptorV2.h" 61#include "AppleObjCTypeEncodingParser.h" 62#include "AppleObjCDeclVendor.h" 63#include "AppleObjCTrampolineHandler.h" 64 65 66using namespace lldb; 67using namespace lldb_private; 68 69// 2 second timeout when running utility functions 70#define UTILITY_FUNCTION_TIMEOUT_USEC 2*1000*1000 71 72static const char *g_get_dynamic_class_info_name = "__lldb_apple_objc_v2_get_dynamic_class_info"; 73// Testing using the new C++11 raw string literals. If this breaks GCC then we will 74// need to revert to the code above... 75static const char *g_get_dynamic_class_info_body = R"( 76 77extern "C" 78{ 79 size_t strlen(const char *); 80 char *strncpy (char * s1, const char * s2, size_t n); 81 int printf(const char * format, ...); 82} 83#define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__) 84 85typedef struct _NXMapTable { 86 void *prototype; 87 unsigned num_classes; 88 unsigned num_buckets_minus_one; 89 void *buckets; 90} NXMapTable; 91 92#define NX_MAPNOTAKEY ((void *)(-1)) 93 94typedef struct BucketInfo 95{ 96 const char *name_ptr; 97 Class isa; 98} BucketInfo; 99 100struct ClassInfo 101{ 102 Class isa; 103 uint32_t hash; 104} __attribute__((__packed__)); 105 106uint32_t 107__lldb_apple_objc_v2_get_dynamic_class_info (void *gdb_objc_realized_classes_ptr, 108 void *class_infos_ptr, 109 uint32_t class_infos_byte_size, 110 uint32_t should_log) 111{ 112 DEBUG_PRINTF ("gdb_objc_realized_classes_ptr = %p\n", gdb_objc_realized_classes_ptr); 113 DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr); 114 DEBUG_PRINTF ("class_infos_byte_size = %u\n", class_infos_byte_size); 115 const NXMapTable *grc = (const NXMapTable *)gdb_objc_realized_classes_ptr; 116 if (grc) 117 { 118 const unsigned num_classes = grc->num_classes; 119 if (class_infos_ptr) 120 { 121 const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo); 122 ClassInfo *class_infos = (ClassInfo *)class_infos_ptr; 123 BucketInfo *buckets = (BucketInfo *)grc->buckets; 124 125 uint32_t idx = 0; 126 for (unsigned i=0; i<=grc->num_buckets_minus_one; ++i) 127 { 128 if (buckets[i].name_ptr != NX_MAPNOTAKEY) 129 { 130 if (idx < max_class_infos) 131 { 132 const char *s = buckets[i].name_ptr; 133 uint32_t h = 5381; 134 for (unsigned char c = *s; c; c = *++s) 135 h = ((h << 5) + h) + c; 136 class_infos[idx].hash = h; 137 class_infos[idx].isa = buckets[i].isa; 138 } 139 ++idx; 140 } 141 } 142 if (idx < max_class_infos) 143 { 144 class_infos[idx].isa = NULL; 145 class_infos[idx].hash = 0; 146 } 147 } 148 return num_classes; 149 } 150 return 0; 151} 152 153)"; 154 155static const char *g_get_shared_cache_class_info_name = "__lldb_apple_objc_v2_get_shared_cache_class_info"; 156// Testing using the new C++11 raw string literals. If this breaks GCC then we will 157// need to revert to the code above... 158static const char *g_get_shared_cache_class_info_body = R"( 159 160extern "C" 161{ 162 const char *class_getName(void *objc_class); 163 size_t strlen(const char *); 164 char *strncpy (char * s1, const char * s2, size_t n); 165 int printf(const char * format, ...); 166} 167 168#define DEBUG_PRINTF(fmt, ...) if (should_log) printf(fmt, ## __VA_ARGS__) 169 170 171struct objc_classheader_t { 172 int32_t clsOffset; 173 int32_t hiOffset; 174}; 175 176struct objc_clsopt_t { 177 uint32_t capacity; 178 uint32_t occupied; 179 uint32_t shift; 180 uint32_t mask; 181 uint32_t zero; 182 uint32_t unused; 183 uint64_t salt; 184 uint32_t scramble[256]; 185 uint8_t tab[0]; // tab[mask+1] 186 // uint8_t checkbytes[capacity]; 187 // int32_t offset[capacity]; 188 // objc_classheader_t clsOffsets[capacity]; 189 // uint32_t duplicateCount; 190 // objc_classheader_t duplicateOffsets[duplicateCount]; 191}; 192 193struct objc_opt_t { 194 uint32_t version; 195 int32_t selopt_offset; 196 int32_t headeropt_offset; 197 int32_t clsopt_offset; 198}; 199 200struct objc_opt_v14_t { 201 uint32_t version; 202 uint32_t flags; 203 int32_t selopt_offset; 204 int32_t headeropt_offset; 205 int32_t clsopt_offset; 206}; 207 208struct ClassInfo 209{ 210 Class isa; 211 uint32_t hash; 212} __attribute__((__packed__)); 213 214uint32_t 215__lldb_apple_objc_v2_get_shared_cache_class_info (void *objc_opt_ro_ptr, 216 void *class_infos_ptr, 217 uint32_t class_infos_byte_size, 218 uint32_t should_log) 219{ 220 uint32_t idx = 0; 221 DEBUG_PRINTF ("objc_opt_ro_ptr = %p\n", objc_opt_ro_ptr); 222 DEBUG_PRINTF ("class_infos_ptr = %p\n", class_infos_ptr); 223 DEBUG_PRINTF ("class_infos_byte_size = %u (%llu class infos)\n", class_infos_byte_size, (uint64_t)(class_infos_byte_size/sizeof(ClassInfo))); 224 if (objc_opt_ro_ptr) 225 { 226 const objc_opt_t *objc_opt = (objc_opt_t *)objc_opt_ro_ptr; 227 const objc_opt_v14_t* objc_opt_v14 = (objc_opt_v14_t*)objc_opt_ro_ptr; 228 const bool is_v14_format = objc_opt->version >= 14; 229 if (is_v14_format) 230 { 231 DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt_v14->version); 232 DEBUG_PRINTF ("objc_opt->flags = %u\n", objc_opt_v14->flags); 233 DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt_v14->selopt_offset); 234 DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt_v14->headeropt_offset); 235 DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt_v14->clsopt_offset); 236 } 237 else 238 { 239 DEBUG_PRINTF ("objc_opt->version = %u\n", objc_opt->version); 240 DEBUG_PRINTF ("objc_opt->selopt_offset = %d\n", objc_opt->selopt_offset); 241 DEBUG_PRINTF ("objc_opt->headeropt_offset = %d\n", objc_opt->headeropt_offset); 242 DEBUG_PRINTF ("objc_opt->clsopt_offset = %d\n", objc_opt->clsopt_offset); 243 } 244 if (objc_opt->version == 12 || objc_opt->version == 13 || objc_opt->version == 14 || objc_opt->version == 15) 245 { 246 const objc_clsopt_t* clsopt = NULL; 247 if (is_v14_format) 248 clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt_v14 + objc_opt_v14->clsopt_offset); 249 else 250 clsopt = (const objc_clsopt_t*)((uint8_t *)objc_opt + objc_opt->clsopt_offset); 251 const size_t max_class_infos = class_infos_byte_size/sizeof(ClassInfo); 252 DEBUG_PRINTF("max_class_infos = %llu\n", (uint64_t)max_class_infos); 253 ClassInfo *class_infos = (ClassInfo *)class_infos_ptr; 254 int32_t invalidEntryOffset = 0; 255 // this is safe to do because the version field order is invariant 256 if (objc_opt->version == 12) 257 invalidEntryOffset = 16; 258 const uint8_t *checkbytes = &clsopt->tab[clsopt->mask+1]; 259 const int32_t *offsets = (const int32_t *)(checkbytes + clsopt->capacity); 260 const objc_classheader_t *classOffsets = (const objc_classheader_t *)(offsets + clsopt->capacity); 261 DEBUG_PRINTF ("clsopt->capacity = %u\n", clsopt->capacity); 262 DEBUG_PRINTF ("clsopt->mask = 0x%8.8x\n", clsopt->mask); 263 DEBUG_PRINTF ("classOffsets = %p\n", classOffsets); 264 DEBUG_PRINTF("invalidEntryOffset = %d\n", invalidEntryOffset); 265 for (uint32_t i=0; i<clsopt->capacity; ++i) 266 { 267 const int32_t clsOffset = classOffsets[i].clsOffset; 268 DEBUG_PRINTF("clsOffset[%u] = %u\n", i, clsOffset); 269 if (clsOffset & 1) 270 { 271 DEBUG_PRINTF("clsOffset & 1\n"); 272 continue; // duplicate 273 } 274 else if (clsOffset == invalidEntryOffset) 275 { 276 DEBUG_PRINTF("clsOffset == invalidEntryOffset\n"); 277 continue; // invalid offset 278 } 279 280 if (class_infos && idx < max_class_infos) 281 { 282 class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset); 283 const char *name = class_getName (class_infos[idx].isa); 284 DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name); 285 // Hash the class name so we don't have to read it 286 const char *s = name; 287 uint32_t h = 5381; 288 for (unsigned char c = *s; c; c = *++s) 289 h = ((h << 5) + h) + c; 290 class_infos[idx].hash = h; 291 } 292 else 293 { 294 DEBUG_PRINTF("not(class_infos && idx < max_class_infos)\n"); 295 } 296 ++idx; 297 } 298 299 const uint32_t *duplicate_count_ptr = (uint32_t *)&classOffsets[clsopt->capacity]; 300 const uint32_t duplicate_count = *duplicate_count_ptr; 301 const objc_classheader_t *duplicateClassOffsets = (const objc_classheader_t *)(&duplicate_count_ptr[1]); 302 DEBUG_PRINTF ("duplicate_count = %u\n", duplicate_count); 303 DEBUG_PRINTF ("duplicateClassOffsets = %p\n", duplicateClassOffsets); 304 for (uint32_t i=0; i<duplicate_count; ++i) 305 { 306 const int32_t clsOffset = duplicateClassOffsets[i].clsOffset; 307 if (clsOffset & 1) 308 continue; // duplicate 309 else if (clsOffset == invalidEntryOffset) 310 continue; // invalid offset 311 312 if (class_infos && idx < max_class_infos) 313 { 314 class_infos[idx].isa = (Class)((uint8_t *)clsopt + clsOffset); 315 const char *name = class_getName (class_infos[idx].isa); 316 DEBUG_PRINTF ("[%u] isa = %8p %s\n", idx, class_infos[idx].isa, name); 317 // Hash the class name so we don't have to read it 318 const char *s = name; 319 uint32_t h = 5381; 320 for (unsigned char c = *s; c; c = *++s) 321 h = ((h << 5) + h) + c; 322 class_infos[idx].hash = h; 323 } 324 ++idx; 325 } 326 } 327 DEBUG_PRINTF ("%u class_infos\n", idx); 328 DEBUG_PRINTF ("done\n"); 329 } 330 return idx; 331} 332 333 334)"; 335 336static uint64_t 337ExtractRuntimeGlobalSymbol (Process* process, 338 ConstString name, 339 const ModuleSP &module_sp, 340 Error& error, 341 bool read_value = true, 342 uint8_t byte_size = 0, 343 uint64_t default_value = LLDB_INVALID_ADDRESS, 344 SymbolType sym_type = lldb::eSymbolTypeData) 345{ 346 if (!process) 347 { 348 error.SetErrorString("no process"); 349 return default_value; 350 } 351 if (!module_sp) 352 { 353 error.SetErrorString("no module"); 354 return default_value; 355 } 356 if (!byte_size) 357 byte_size = process->GetAddressByteSize(); 358 const Symbol *symbol = module_sp->FindFirstSymbolWithNameAndType(name, lldb::eSymbolTypeData); 359 if (symbol && symbol->ValueIsAddress()) 360 { 361 lldb::addr_t symbol_load_addr = symbol->GetAddressRef().GetLoadAddress(&process->GetTarget()); 362 if (symbol_load_addr != LLDB_INVALID_ADDRESS) 363 { 364 if (read_value) 365 return process->ReadUnsignedIntegerFromMemory(symbol_load_addr, byte_size, default_value, error); 366 else 367 return symbol_load_addr; 368 } 369 else 370 { 371 error.SetErrorString("symbol address invalid"); 372 return default_value; 373 } 374 } 375 else 376 { 377 error.SetErrorString("no symbol"); 378 return default_value; 379 } 380} 381 382AppleObjCRuntimeV2::AppleObjCRuntimeV2(Process *process, const ModuleSP &objc_module_sp) 383 : AppleObjCRuntime(process), 384 m_get_class_info_code(), 385 m_get_class_info_args(LLDB_INVALID_ADDRESS), 386 m_get_class_info_args_mutex(), 387 m_get_shared_cache_class_info_code(), 388 m_get_shared_cache_class_info_args(LLDB_INVALID_ADDRESS), 389 m_get_shared_cache_class_info_args_mutex(), 390 m_decl_vendor_ap(), 391 m_isa_hash_table_ptr(LLDB_INVALID_ADDRESS), 392 m_hash_signature(), 393 m_has_object_getClass(false), 394 m_loaded_objc_opt(false), 395 m_non_pointer_isa_cache_ap(NonPointerISACache::CreateInstance(*this, objc_module_sp)), 396 m_tagged_pointer_vendor_ap(TaggedPointerVendorV2::CreateInstance(*this, objc_module_sp)), 397 m_encoding_to_type_sp(), 398 m_noclasses_warning_emitted(false) 399{ 400 static const ConstString g_gdb_object_getClass("gdb_object_getClass"); 401 m_has_object_getClass = 402 (objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_object_getClass, eSymbolTypeCode) != NULL); 403} 404 405bool 406AppleObjCRuntimeV2::GetDynamicTypeAndAddress (ValueObject &in_value, 407 DynamicValueType use_dynamic, 408 TypeAndOrName &class_type_or_name, 409 Address &address, 410 Value::ValueType &value_type) 411{ 412 // We should never get here with a null process... 413 assert (m_process != NULL); 414 415 // The Runtime is attached to a particular process, you shouldn't pass in a value from another process. 416 // Note, however, the process might be NULL (e.g. if the value was made with SBTarget::EvaluateExpression...) 417 // in which case it is sufficient if the target's match: 418 419 Process *process = in_value.GetProcessSP().get(); 420 if (process) 421 assert (process == m_process); 422 else 423 assert (in_value.GetTargetSP().get() == m_process->CalculateTarget().get()); 424 425 class_type_or_name.Clear(); 426 value_type = Value::ValueType::eValueTypeScalar; 427 428 // Make sure we can have a dynamic value before starting... 429 if (CouldHaveDynamicValue (in_value)) 430 { 431 // First job, pull out the address at 0 offset from the object That will be the ISA pointer. 432 ClassDescriptorSP objc_class_sp (GetNonKVOClassDescriptor (in_value)); 433 if (objc_class_sp) 434 { 435 const addr_t object_ptr = in_value.GetPointerValue(); 436 address.SetRawAddress(object_ptr); 437 438 ConstString class_name (objc_class_sp->GetClassName()); 439 class_type_or_name.SetName(class_name); 440 TypeSP type_sp (objc_class_sp->GetType()); 441 if (type_sp) 442 class_type_or_name.SetTypeSP (type_sp); 443 else 444 { 445 type_sp = LookupInCompleteClassCache (class_name); 446 if (type_sp) 447 { 448 objc_class_sp->SetType (type_sp); 449 class_type_or_name.SetTypeSP (type_sp); 450 } 451 else 452 { 453 // try to go for a CompilerType at least 454 DeclVendor* vendor = GetDeclVendor(); 455 if (vendor) 456 { 457 std::vector<clang::NamedDecl*> decls; 458 if (vendor->FindDecls(class_name, false, 1, decls) && decls.size()) 459 class_type_or_name.SetCompilerType(ClangASTContext::GetTypeForDecl(decls[0])); 460 } 461 } 462 } 463 } 464 } 465 return class_type_or_name.IsEmpty() == false; 466} 467 468//------------------------------------------------------------------ 469// Static Functions 470//------------------------------------------------------------------ 471LanguageRuntime * 472AppleObjCRuntimeV2::CreateInstance (Process *process, LanguageType language) 473{ 474 // FIXME: This should be a MacOS or iOS process, and we need to look for the OBJC section to make 475 // sure we aren't using the V1 runtime. 476 if (language == eLanguageTypeObjC) 477 { 478 ModuleSP objc_module_sp; 479 480 if (AppleObjCRuntime::GetObjCVersion (process, objc_module_sp) == ObjCRuntimeVersions::eAppleObjC_V2) 481 return new AppleObjCRuntimeV2 (process, objc_module_sp); 482 else 483 return NULL; 484 } 485 else 486 return NULL; 487} 488 489class CommandObjectObjC_ClassTable_Dump : public CommandObjectParsed 490{ 491public: 492 class CommandOptions : public Options 493 { 494 public: 495 CommandOptions (CommandInterpreter &interpreter) : 496 Options(interpreter), 497 m_verbose(false,false) 498 {} 499 500 ~CommandOptions() override = default; 501 502 Error 503 SetOptionValue(uint32_t option_idx, const char *option_arg) override 504 { 505 Error error; 506 const int short_option = m_getopt_table[option_idx].val; 507 switch (short_option) 508 { 509 case 'v': 510 m_verbose.SetCurrentValue(true); 511 m_verbose.SetOptionWasSet(); 512 break; 513 514 default: 515 error.SetErrorStringWithFormat("unrecognized short option '%c'", short_option); 516 break; 517 } 518 519 return error; 520 } 521 522 void 523 OptionParsingStarting() override 524 { 525 m_verbose.Clear(); 526 } 527 528 const OptionDefinition* 529 GetDefinitions() override 530 { 531 return g_option_table; 532 } 533 534 OptionValueBoolean m_verbose; 535 static OptionDefinition g_option_table[]; 536 }; 537 538 CommandObjectObjC_ClassTable_Dump (CommandInterpreter &interpreter) : 539 CommandObjectParsed (interpreter, 540 "dump", 541 "Dump information on Objective-C classes known to the current process.", 542 "language objc class-table dump", 543 eCommandRequiresProcess | 544 eCommandProcessMustBeLaunched | 545 eCommandProcessMustBePaused ), 546 m_options(interpreter) 547 { 548 CommandArgumentEntry arg; 549 CommandArgumentData index_arg; 550 551 // Define the first (and only) variant of this arg. 552 index_arg.arg_type = eArgTypeRegularExpression; 553 index_arg.arg_repetition = eArgRepeatOptional; 554 555 // There is only one variant this argument could be; put it into the argument entry. 556 arg.push_back (index_arg); 557 558 // Push the data for the first argument into the m_arguments vector. 559 m_arguments.push_back (arg); 560 } 561 562 ~CommandObjectObjC_ClassTable_Dump() override = default; 563 564 Options * 565 GetOptions() override 566 { 567 return &m_options; 568 } 569 570protected: 571 bool 572 DoExecute(Args& command, CommandReturnObject &result) override 573 { 574 std::unique_ptr<RegularExpression> regex_up; 575 switch(command.GetArgumentCount()) 576 { 577 case 0: 578 break; 579 case 1: 580 { 581 regex_up.reset(new RegularExpression()); 582 if (!regex_up->Compile(command.GetArgumentAtIndex(0))) 583 { 584 result.AppendError("invalid argument - please provide a valid regular expression"); 585 result.SetStatus(lldb::eReturnStatusFailed); 586 return false; 587 } 588 break; 589 } 590 default: 591 { 592 result.AppendError("please provide 0 or 1 arguments"); 593 result.SetStatus(lldb::eReturnStatusFailed); 594 return false; 595 } 596 } 597 598 Process *process = m_exe_ctx.GetProcessPtr(); 599 ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime(); 600 if (objc_runtime) 601 { 602 auto iterators_pair = objc_runtime->GetDescriptorIteratorPair(); 603 auto iterator = iterators_pair.first; 604 auto &std_out = result.GetOutputStream(); 605 for(; iterator != iterators_pair.second; iterator++) 606 { 607 if (iterator->second) 608 { 609 const char* class_name = iterator->second->GetClassName().AsCString("<unknown>"); 610 if (regex_up && class_name && !regex_up->Execute(class_name)) 611 continue; 612 std_out.Printf("isa = 0x%" PRIx64, iterator->first); 613 std_out.Printf(" name = %s", class_name); 614 std_out.Printf(" instance size = %" PRIu64, iterator->second->GetInstanceSize()); 615 std_out.Printf(" num ivars = %" PRIuPTR, (uintptr_t)iterator->second->GetNumIVars()); 616 if (auto superclass = iterator->second->GetSuperclass()) 617 { 618 std_out.Printf(" superclass = %s", superclass->GetClassName().AsCString("<unknown>")); 619 } 620 std_out.Printf("\n"); 621 if (m_options.m_verbose) 622 { 623 for(size_t i = 0; 624 i < iterator->second->GetNumIVars(); 625 i++) 626 { 627 auto ivar = iterator->second->GetIVarAtIndex(i); 628 std_out.Printf(" ivar name = %s type = %s size = %" PRIu64 " offset = %" PRId32 "\n", 629 ivar.m_name.AsCString("<unknown>"), 630 ivar.m_type.GetDisplayTypeName().AsCString("<unknown>"), 631 ivar.m_size, 632 ivar.m_offset); 633 } 634 iterator->second->Describe(nullptr, 635 [objc_runtime, &std_out] (const char* name, const char* type) -> bool { 636 std_out.Printf(" instance method name = %s type = %s\n", 637 name, 638 type); 639 return false; 640 }, 641 [objc_runtime, &std_out] (const char* name, const char* type) -> bool { 642 std_out.Printf(" class method name = %s type = %s\n", 643 name, 644 type); 645 return false; 646 }, 647 nullptr); 648 } 649 } 650 else 651 { 652 if (regex_up && !regex_up->Execute("")) 653 continue; 654 std_out.Printf("isa = 0x%" PRIx64 " has no associated class.\n", iterator->first); 655 } 656 } 657 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 658 return true; 659 } 660 else 661 { 662 result.AppendError("current process has no Objective-C runtime loaded"); 663 result.SetStatus(lldb::eReturnStatusFailed); 664 return false; 665 } 666 } 667 668 CommandOptions m_options; 669}; 670 671OptionDefinition 672CommandObjectObjC_ClassTable_Dump::CommandOptions::g_option_table[] = 673{ 674 { LLDB_OPT_SET_ALL, false, "verbose" , 'v', OptionParser::eNoArgument , nullptr, nullptr, 0, eArgTypeNone, "Print ivar and method information in detail"}, 675 { 0 , false, nullptr , 0, 0 , nullptr, nullptr, 0, eArgTypeNone, nullptr } 676}; 677 678class CommandObjectMultiwordObjC_TaggedPointer_Info : public CommandObjectParsed 679{ 680public: 681 CommandObjectMultiwordObjC_TaggedPointer_Info (CommandInterpreter &interpreter) : 682 CommandObjectParsed (interpreter, 683 "info", 684 "Dump information on a tagged pointer.", 685 "language objc tagged-pointer info", 686 eCommandRequiresProcess | 687 eCommandProcessMustBeLaunched | 688 eCommandProcessMustBePaused ) 689 { 690 CommandArgumentEntry arg; 691 CommandArgumentData index_arg; 692 693 // Define the first (and only) variant of this arg. 694 index_arg.arg_type = eArgTypeAddress; 695 index_arg.arg_repetition = eArgRepeatPlus; 696 697 // There is only one variant this argument could be; put it into the argument entry. 698 arg.push_back (index_arg); 699 700 // Push the data for the first argument into the m_arguments vector. 701 m_arguments.push_back (arg); 702 } 703 704 ~CommandObjectMultiwordObjC_TaggedPointer_Info() override = default; 705 706protected: 707 bool 708 DoExecute(Args& command, CommandReturnObject &result) override 709 { 710 if (command.GetArgumentCount() == 0) 711 { 712 result.AppendError("this command requires arguments"); 713 result.SetStatus(lldb::eReturnStatusFailed); 714 return false; 715 } 716 717 Process *process = m_exe_ctx.GetProcessPtr(); 718 ExecutionContext exe_ctx(process); 719 ObjCLanguageRuntime *objc_runtime = process->GetObjCLanguageRuntime(); 720 if (objc_runtime) 721 { 722 ObjCLanguageRuntime::TaggedPointerVendor *tagged_ptr_vendor = objc_runtime->GetTaggedPointerVendor(); 723 if (tagged_ptr_vendor) 724 { 725 for (size_t i = 0; 726 i < command.GetArgumentCount(); 727 i++) 728 { 729 const char *arg_str = command.GetArgumentAtIndex(i); 730 if (!arg_str) 731 continue; 732 Error error; 733 lldb::addr_t arg_addr = Args::StringToAddress(&exe_ctx, arg_str, LLDB_INVALID_ADDRESS, &error); 734 if (arg_addr == 0 || arg_addr == LLDB_INVALID_ADDRESS || error.Fail()) 735 continue; 736 auto descriptor_sp = tagged_ptr_vendor->GetClassDescriptor(arg_addr); 737 if (!descriptor_sp) 738 continue; 739 uint64_t info_bits = 0; 740 uint64_t value_bits = 0; 741 uint64_t payload = 0; 742 if (descriptor_sp->GetTaggedPointerInfo(&info_bits, &value_bits, &payload)) 743 { 744 result.GetOutputStream().Printf("0x%" PRIx64 " is tagged.\n\tpayload = 0x%" PRIx64 "\n\tvalue = 0x%" PRIx64 "\n\tinfo bits = 0x%" PRIx64 "\n\tclass = %s\n", 745 (uint64_t)arg_addr, 746 payload, 747 value_bits, 748 info_bits, 749 descriptor_sp->GetClassName().AsCString("<unknown>")); 750 } 751 else 752 { 753 result.GetOutputStream().Printf("0x%" PRIx64 " is not tagged.\n", (uint64_t)arg_addr); 754 } 755 } 756 } 757 else 758 { 759 result.AppendError("current process has no tagged pointer support"); 760 result.SetStatus(lldb::eReturnStatusFailed); 761 return false; 762 } 763 result.SetStatus(lldb::eReturnStatusSuccessFinishResult); 764 return true; 765 } 766 else 767 { 768 result.AppendError("current process has no Objective-C runtime loaded"); 769 result.SetStatus(lldb::eReturnStatusFailed); 770 return false; 771 } 772 } 773}; 774 775class CommandObjectMultiwordObjC_ClassTable : public CommandObjectMultiword 776{ 777public: 778 CommandObjectMultiwordObjC_ClassTable(CommandInterpreter &interpreter) 779 : CommandObjectMultiword(interpreter, "class-table", "Commands for operating on the Objective-C class table.", 780 "class-table <subcommand> [<subcommand-options>]") 781 { 782 LoadSubCommand ("dump", CommandObjectSP (new CommandObjectObjC_ClassTable_Dump (interpreter))); 783 } 784 785 ~CommandObjectMultiwordObjC_ClassTable() override = default; 786}; 787 788class CommandObjectMultiwordObjC_TaggedPointer : public CommandObjectMultiword 789{ 790public: 791 CommandObjectMultiwordObjC_TaggedPointer(CommandInterpreter &interpreter) 792 : CommandObjectMultiword(interpreter, "tagged-pointer", 793 "Commands for operating on Objective-C tagged pointers.", 794 "class-table <subcommand> [<subcommand-options>]") 795 { 796 LoadSubCommand ("info", CommandObjectSP (new CommandObjectMultiwordObjC_TaggedPointer_Info (interpreter))); 797 } 798 799 ~CommandObjectMultiwordObjC_TaggedPointer() override = default; 800}; 801 802class CommandObjectMultiwordObjC : public CommandObjectMultiword 803{ 804public: 805 CommandObjectMultiwordObjC(CommandInterpreter &interpreter) 806 : CommandObjectMultiword(interpreter, "objc", "Commands for operating on the Objective-C language runtime.", 807 "objc <subcommand> [<subcommand-options>]") 808 { 809 LoadSubCommand ("class-table", CommandObjectSP (new CommandObjectMultiwordObjC_ClassTable (interpreter))); 810 LoadSubCommand ("tagged-pointer", CommandObjectSP (new CommandObjectMultiwordObjC_TaggedPointer (interpreter))); 811 } 812 813 ~CommandObjectMultiwordObjC() override = default; 814}; 815 816void 817AppleObjCRuntimeV2::Initialize() 818{ 819 PluginManager::RegisterPlugin (GetPluginNameStatic(), 820 "Apple Objective C Language Runtime - Version 2", 821 CreateInstance, 822 [] (CommandInterpreter& interpreter) -> lldb::CommandObjectSP { 823 return CommandObjectSP(new CommandObjectMultiwordObjC(interpreter)); 824 }); 825} 826 827void 828AppleObjCRuntimeV2::Terminate() 829{ 830 PluginManager::UnregisterPlugin (CreateInstance); 831} 832 833lldb_private::ConstString 834AppleObjCRuntimeV2::GetPluginNameStatic() 835{ 836 static ConstString g_name("apple-objc-v2"); 837 return g_name; 838} 839 840//------------------------------------------------------------------ 841// PluginInterface protocol 842//------------------------------------------------------------------ 843lldb_private::ConstString 844AppleObjCRuntimeV2::GetPluginName() 845{ 846 return GetPluginNameStatic(); 847} 848 849uint32_t 850AppleObjCRuntimeV2::GetPluginVersion() 851{ 852 return 1; 853} 854 855BreakpointResolverSP 856AppleObjCRuntimeV2::CreateExceptionResolver (Breakpoint *bkpt, bool catch_bp, bool throw_bp) 857{ 858 BreakpointResolverSP resolver_sp; 859 860 if (throw_bp) 861 resolver_sp.reset (new BreakpointResolverName (bkpt, 862 "objc_exception_throw", 863 eFunctionNameTypeBase, 864 eLanguageTypeUnknown, 865 Breakpoint::Exact, 866 0, 867 eLazyBoolNo)); 868 // FIXME: We don't do catch breakpoints for ObjC yet. 869 // Should there be some way for the runtime to specify what it can do in this regard? 870 return resolver_sp; 871} 872 873UtilityFunction * 874AppleObjCRuntimeV2::CreateObjectChecker(const char *name) 875{ 876 char check_function_code[2048]; 877 878 int len = 0; 879 if (m_has_object_getClass) 880 { 881 len = ::snprintf (check_function_code, 882 sizeof(check_function_code), 883 "extern \"C\" void *gdb_object_getClass(void *); \n" 884 "extern \"C\" int printf(const char *format, ...); \n" 885 "extern \"C\" void \n" 886 "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) \n" 887 "{ \n" 888 " if ($__lldb_arg_obj == (void *)0) \n" 889 " return; // nil is ok \n" 890 " if (!gdb_object_getClass($__lldb_arg_obj)) \n" 891 " *((volatile int *)0) = 'ocgc'; \n" 892 " else if ($__lldb_arg_selector != (void *)0) \n" 893 " { \n" 894 " signed char responds = (signed char) [(id) $__lldb_arg_obj \n" 895 " respondsToSelector: \n" 896 " (struct objc_selector *) $__lldb_arg_selector]; \n" 897 " if (responds == (signed char) 0) \n" 898 " *((volatile int *)0) = 'ocgc'; \n" 899 " } \n" 900 "} \n", 901 name); 902 } 903 else 904 { 905 len = ::snprintf (check_function_code, 906 sizeof(check_function_code), 907 "extern \"C\" void *gdb_class_getClass(void *); \n" 908 "extern \"C\" int printf(const char *format, ...); \n" 909 "extern \"C\" void \n" 910 "%s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) \n" 911 "{ \n" 912 " if ($__lldb_arg_obj == (void *)0) \n" 913 " return; // nil is ok \n" 914 " void **$isa_ptr = (void **)$__lldb_arg_obj; \n" 915 " if (*$isa_ptr == (void *)0 || !gdb_class_getClass(*$isa_ptr)) \n" 916 " *((volatile int *)0) = 'ocgc'; \n" 917 " else if ($__lldb_arg_selector != (void *)0) \n" 918 " { \n" 919 " signed char responds = (signed char) [(id) $__lldb_arg_obj \n" 920 " respondsToSelector: \n" 921 " (struct objc_selector *) $__lldb_arg_selector]; \n" 922 " if (responds == (signed char) 0) \n" 923 " *((volatile int *)0) = 'ocgc'; \n" 924 " } \n" 925 "} \n", 926 name); 927 } 928 929 assert (len < (int)sizeof(check_function_code)); 930 931 Error error; 932 return GetTargetRef().GetUtilityFunctionForLanguage(check_function_code, eLanguageTypeObjC, name, error); 933} 934 935size_t 936AppleObjCRuntimeV2::GetByteOffsetForIvar (CompilerType &parent_ast_type, const char *ivar_name) 937{ 938 uint32_t ivar_offset = LLDB_INVALID_IVAR_OFFSET; 939 940 const char *class_name = parent_ast_type.GetConstTypeName().AsCString(); 941 if (class_name && class_name[0] && ivar_name && ivar_name[0]) 942 { 943 //---------------------------------------------------------------------- 944 // Make the objective C V2 mangled name for the ivar offset from the 945 // class name and ivar name 946 //---------------------------------------------------------------------- 947 std::string buffer("OBJC_IVAR_$_"); 948 buffer.append (class_name); 949 buffer.push_back ('.'); 950 buffer.append (ivar_name); 951 ConstString ivar_const_str (buffer.c_str()); 952 953 //---------------------------------------------------------------------- 954 // Try to get the ivar offset address from the symbol table first using 955 // the name we created above 956 //---------------------------------------------------------------------- 957 SymbolContextList sc_list; 958 Target &target = m_process->GetTarget(); 959 target.GetImages().FindSymbolsWithNameAndType(ivar_const_str, eSymbolTypeObjCIVar, sc_list); 960 961 addr_t ivar_offset_address = LLDB_INVALID_ADDRESS; 962 963 Error error; 964 SymbolContext ivar_offset_symbol; 965 if (sc_list.GetSize() == 1 && sc_list.GetContextAtIndex(0, ivar_offset_symbol)) 966 { 967 if (ivar_offset_symbol.symbol) 968 ivar_offset_address = ivar_offset_symbol.symbol->GetLoadAddress (&target); 969 } 970 971 //---------------------------------------------------------------------- 972 // If we didn't get the ivar offset address from the symbol table, fall 973 // back to getting it from the runtime 974 //---------------------------------------------------------------------- 975 if (ivar_offset_address == LLDB_INVALID_ADDRESS) 976 ivar_offset_address = LookupRuntimeSymbol(ivar_const_str); 977 978 if (ivar_offset_address != LLDB_INVALID_ADDRESS) 979 ivar_offset = m_process->ReadUnsignedIntegerFromMemory (ivar_offset_address, 980 4, 981 LLDB_INVALID_IVAR_OFFSET, 982 error); 983 } 984 return ivar_offset; 985} 986 987// tagged pointers are special not-a-real-pointer values that contain both type and value information 988// this routine attempts to check with as little computational effort as possible whether something 989// could possibly be a tagged pointer - false positives are possible but false negatives shouldn't 990bool 991AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr) 992{ 993 if (!m_tagged_pointer_vendor_ap) 994 return false; 995 return m_tagged_pointer_vendor_ap->IsPossibleTaggedPointer(ptr); 996} 997 998class RemoteNXMapTable 999{ 1000public: 1001 RemoteNXMapTable () : 1002 m_count (0), 1003 m_num_buckets_minus_one (0), 1004 m_buckets_ptr (LLDB_INVALID_ADDRESS), 1005 m_process (NULL), 1006 m_end_iterator (*this, -1), 1007 m_load_addr (LLDB_INVALID_ADDRESS), 1008 m_map_pair_size (0), 1009 m_invalid_key (0) 1010 { 1011 } 1012 1013 void 1014 Dump () 1015 { 1016 printf ("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr); 1017 printf ("RemoteNXMapTable.m_count = %u\n", m_count); 1018 printf ("RemoteNXMapTable.m_num_buckets_minus_one = %u\n", m_num_buckets_minus_one); 1019 printf ("RemoteNXMapTable.m_buckets_ptr = 0x%" PRIX64 "\n", m_buckets_ptr); 1020 } 1021 1022 bool 1023 ParseHeader (Process* process, lldb::addr_t load_addr) 1024 { 1025 m_process = process; 1026 m_load_addr = load_addr; 1027 m_map_pair_size = m_process->GetAddressByteSize() * 2; 1028 m_invalid_key = m_process->GetAddressByteSize() == 8 ? UINT64_MAX : UINT32_MAX; 1029 Error err; 1030 1031 // This currently holds true for all platforms we support, but we might 1032 // need to change this to use get the actually byte size of "unsigned" 1033 // from the target AST... 1034 const uint32_t unsigned_byte_size = sizeof(uint32_t); 1035 // Skip the prototype as we don't need it (const struct +NXMapTablePrototype *prototype) 1036 1037 bool success = true; 1038 if (load_addr == LLDB_INVALID_ADDRESS) 1039 success = false; 1040 else 1041 { 1042 lldb::addr_t cursor = load_addr + m_process->GetAddressByteSize(); 1043 1044 // unsigned count; 1045 m_count = m_process->ReadUnsignedIntegerFromMemory(cursor, unsigned_byte_size, 0, err); 1046 if (m_count) 1047 { 1048 cursor += unsigned_byte_size; 1049 1050 // unsigned nbBucketsMinusOne; 1051 m_num_buckets_minus_one = m_process->ReadUnsignedIntegerFromMemory(cursor, unsigned_byte_size, 0, err); 1052 cursor += unsigned_byte_size; 1053 1054 // void *buckets; 1055 m_buckets_ptr = m_process->ReadPointerFromMemory(cursor, err); 1056 1057 success = m_count > 0 && m_buckets_ptr != LLDB_INVALID_ADDRESS; 1058 } 1059 } 1060 1061 if (!success) 1062 { 1063 m_count = 0; 1064 m_num_buckets_minus_one = 0; 1065 m_buckets_ptr = LLDB_INVALID_ADDRESS; 1066 } 1067 return success; 1068 } 1069 1070 // const_iterator mimics NXMapState and its code comes from NXInitMapState and NXNextMapState. 1071 typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element; 1072 1073 friend class const_iterator; 1074 class const_iterator 1075 { 1076 public: 1077 const_iterator (RemoteNXMapTable &parent, int index) : m_parent(parent), m_index(index) 1078 { 1079 AdvanceToValidIndex(); 1080 } 1081 1082 const_iterator (const const_iterator &rhs) : m_parent(rhs.m_parent), m_index(rhs.m_index) 1083 { 1084 // AdvanceToValidIndex() has been called by rhs already. 1085 } 1086 1087 const_iterator &operator=(const const_iterator &rhs) 1088 { 1089 // AdvanceToValidIndex() has been called by rhs already. 1090 assert (&m_parent == &rhs.m_parent); 1091 m_index = rhs.m_index; 1092 return *this; 1093 } 1094 1095 bool operator==(const const_iterator &rhs) const 1096 { 1097 if (&m_parent != &rhs.m_parent) 1098 return false; 1099 if (m_index != rhs.m_index) 1100 return false; 1101 1102 return true; 1103 } 1104 1105 bool operator!=(const const_iterator &rhs) const 1106 { 1107 return !(operator==(rhs)); 1108 } 1109 1110 const_iterator &operator++() 1111 { 1112 AdvanceToValidIndex(); 1113 return *this; 1114 } 1115 1116 const element operator*() const 1117 { 1118 if (m_index == -1) 1119 { 1120 // TODO find a way to make this an error, but not an assert 1121 return element(); 1122 } 1123 1124 lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr; 1125 size_t map_pair_size = m_parent.m_map_pair_size; 1126 lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size); 1127 1128 Error err; 1129 1130 lldb::addr_t key = m_parent.m_process->ReadPointerFromMemory(pair_ptr, err); 1131 if (!err.Success()) 1132 return element(); 1133 lldb::addr_t value = m_parent.m_process->ReadPointerFromMemory(pair_ptr + m_parent.m_process->GetAddressByteSize(), err); 1134 if (!err.Success()) 1135 return element(); 1136 1137 std::string key_string; 1138 1139 m_parent.m_process->ReadCStringFromMemory(key, key_string, err); 1140 if (!err.Success()) 1141 return element(); 1142 1143 return element(ConstString(key_string.c_str()), (ObjCLanguageRuntime::ObjCISA)value); 1144 } 1145 1146 private: 1147 void AdvanceToValidIndex () 1148 { 1149 if (m_index == -1) 1150 return; 1151 1152 const lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr; 1153 const size_t map_pair_size = m_parent.m_map_pair_size; 1154 const lldb::addr_t invalid_key = m_parent.m_invalid_key; 1155 Error err; 1156 1157 while (m_index--) 1158 { 1159 lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size); 1160 lldb::addr_t key = m_parent.m_process->ReadPointerFromMemory(pair_ptr, err); 1161 1162 if (!err.Success()) 1163 { 1164 m_index = -1; 1165 return; 1166 } 1167 1168 if (key != invalid_key) 1169 return; 1170 } 1171 } 1172 RemoteNXMapTable &m_parent; 1173 int m_index; 1174 }; 1175 1176 const_iterator begin () 1177 { 1178 return const_iterator(*this, m_num_buckets_minus_one + 1); 1179 } 1180 1181 const_iterator end () 1182 { 1183 return m_end_iterator; 1184 } 1185 1186 uint32_t 1187 GetCount () const 1188 { 1189 return m_count; 1190 } 1191 1192 uint32_t 1193 GetBucketCount () const 1194 { 1195 return m_num_buckets_minus_one; 1196 } 1197 1198 lldb::addr_t 1199 GetBucketDataPointer () const 1200 { 1201 return m_buckets_ptr; 1202 } 1203 1204 lldb::addr_t 1205 GetTableLoadAddress() const 1206 { 1207 return m_load_addr; 1208 } 1209 1210private: 1211 // contents of _NXMapTable struct 1212 uint32_t m_count; 1213 uint32_t m_num_buckets_minus_one; 1214 lldb::addr_t m_buckets_ptr; 1215 lldb_private::Process *m_process; 1216 const_iterator m_end_iterator; 1217 lldb::addr_t m_load_addr; 1218 size_t m_map_pair_size; 1219 lldb::addr_t m_invalid_key; 1220}; 1221 1222AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() : 1223 m_count (0), 1224 m_num_buckets (0), 1225 m_buckets_ptr (0) 1226{ 1227} 1228 1229void 1230AppleObjCRuntimeV2::HashTableSignature::UpdateSignature (const RemoteNXMapTable &hash_table) 1231{ 1232 m_count = hash_table.GetCount(); 1233 m_num_buckets = hash_table.GetBucketCount(); 1234 m_buckets_ptr = hash_table.GetBucketDataPointer(); 1235} 1236 1237bool 1238AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate (Process *process, AppleObjCRuntimeV2 *runtime, RemoteNXMapTable &hash_table) 1239{ 1240 if (!hash_table.ParseHeader(process, runtime->GetISAHashTablePointer ())) 1241 { 1242 return false; // Failed to parse the header, no need to update anything 1243 } 1244 1245 // Check with out current signature and return true if the count, 1246 // number of buckets or the hash table address changes. 1247 if (m_count == hash_table.GetCount() && 1248 m_num_buckets == hash_table.GetBucketCount() && 1249 m_buckets_ptr == hash_table.GetBucketDataPointer()) 1250 { 1251 // Hash table hasn't changed 1252 return false; 1253 } 1254 // Hash table data has changed, we need to update 1255 return true; 1256} 1257 1258ObjCLanguageRuntime::ClassDescriptorSP 1259AppleObjCRuntimeV2::GetClassDescriptorFromISA (ObjCISA isa) 1260{ 1261 ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp; 1262 if (m_non_pointer_isa_cache_ap.get()) 1263 class_descriptor_sp = m_non_pointer_isa_cache_ap->GetClassDescriptor(isa); 1264 if (!class_descriptor_sp) 1265 class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa); 1266 return class_descriptor_sp; 1267} 1268 1269ObjCLanguageRuntime::ClassDescriptorSP 1270AppleObjCRuntimeV2::GetClassDescriptor (ValueObject& valobj) 1271{ 1272 ClassDescriptorSP objc_class_sp; 1273 if (valobj.IsBaseClass()) 1274 { 1275 ValueObject *parent = valobj.GetParent(); 1276 // if I am my own parent, bail out of here fast.. 1277 if (parent && parent != &valobj) 1278 { 1279 ClassDescriptorSP parent_descriptor_sp = GetClassDescriptor(*parent); 1280 if (parent_descriptor_sp) 1281 return parent_descriptor_sp->GetSuperclass(); 1282 } 1283 return nullptr; 1284 } 1285 // if we get an invalid VO (which might still happen when playing around 1286 // with pointers returned by the expression parser, don't consider this 1287 // a valid ObjC object) 1288 if (valobj.GetCompilerType().IsValid()) 1289 { 1290 addr_t isa_pointer = valobj.GetPointerValue(); 1291 1292 // tagged pointer 1293 if (IsTaggedPointer(isa_pointer)) 1294 { 1295 return m_tagged_pointer_vendor_ap->GetClassDescriptor(isa_pointer); 1296 } 1297 else 1298 { 1299 ExecutionContext exe_ctx (valobj.GetExecutionContextRef()); 1300 1301 Process *process = exe_ctx.GetProcessPtr(); 1302 if (process) 1303 { 1304 Error error; 1305 ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error); 1306 if (isa != LLDB_INVALID_ADDRESS) 1307 { 1308 objc_class_sp = GetClassDescriptorFromISA (isa); 1309 if (isa && !objc_class_sp) 1310 { 1311 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 1312 if (log) 1313 log->Printf("0x%" PRIx64 ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was not in class descriptor cache 0x%" PRIx64, 1314 isa_pointer, 1315 isa); 1316 } 1317 } 1318 } 1319 } 1320 } 1321 return objc_class_sp; 1322} 1323 1324lldb::addr_t 1325AppleObjCRuntimeV2::GetISAHashTablePointer () 1326{ 1327 if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS) 1328 { 1329 Process *process = GetProcess(); 1330 1331 ModuleSP objc_module_sp(GetObjCModule()); 1332 1333 if (!objc_module_sp) 1334 return LLDB_INVALID_ADDRESS; 1335 1336 static ConstString g_gdb_objc_realized_classes("gdb_objc_realized_classes"); 1337 1338 const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType(g_gdb_objc_realized_classes, lldb::eSymbolTypeAny); 1339 if (symbol) 1340 { 1341 lldb::addr_t gdb_objc_realized_classes_ptr = symbol->GetLoadAddress(&process->GetTarget()); 1342 1343 if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS) 1344 { 1345 Error error; 1346 m_isa_hash_table_ptr = process->ReadPointerFromMemory(gdb_objc_realized_classes_ptr, error); 1347 } 1348 } 1349 } 1350 return m_isa_hash_table_ptr; 1351} 1352 1353bool 1354AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic(RemoteNXMapTable &hash_table) 1355{ 1356 Process *process = GetProcess(); 1357 1358 if (process == NULL) 1359 return false; 1360 1361 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 1362 1363 ExecutionContext exe_ctx; 1364 1365 ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread(); 1366 1367 if (!thread_sp) 1368 return false; 1369 1370 thread_sp->CalculateExecutionContext(exe_ctx); 1371 ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext(); 1372 1373 if (!ast) 1374 return false; 1375 1376 Address function_address; 1377 1378 DiagnosticManager diagnostics; 1379 1380 const uint32_t addr_size = process->GetAddressByteSize(); 1381 1382 Error err; 1383 1384 // Read the total number of classes from the hash table 1385 const uint32_t num_classes = hash_table.GetCount(); 1386 if (num_classes == 0) 1387 { 1388 if (log) 1389 log->Printf ("No dynamic classes found in gdb_objc_realized_classes."); 1390 return false; 1391 } 1392 1393 // Make some types for our arguments 1394 CompilerType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); 1395 CompilerType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType(); 1396 1397 ValueList arguments; 1398 FunctionCaller *get_class_info_function = nullptr; 1399 1400 if (!m_get_class_info_code.get()) 1401 { 1402 Error error; 1403 m_get_class_info_code.reset (GetTargetRef().GetUtilityFunctionForLanguage (g_get_dynamic_class_info_body, 1404 eLanguageTypeObjC, 1405 g_get_dynamic_class_info_name, 1406 error)); 1407 if (error.Fail()) 1408 { 1409 if (log) 1410 log->Printf ("Failed to get Utility Function for implementation lookup: %s", error.AsCString()); 1411 m_get_class_info_code.reset(); 1412 } 1413 else 1414 { 1415 diagnostics.Clear(); 1416 1417 if (!m_get_class_info_code->Install(diagnostics, exe_ctx)) 1418 { 1419 if (log) 1420 { 1421 log->Printf("Failed to install implementation lookup"); 1422 diagnostics.Dump(log); 1423 } 1424 m_get_class_info_code.reset(); 1425 } 1426 } 1427 if (!m_get_class_info_code.get()) 1428 return false; 1429 1430 // Next make the runner function for our implementation utility function. 1431 Value value; 1432 value.SetValueType (Value::eValueTypeScalar); 1433 value.SetCompilerType (clang_void_pointer_type); 1434 arguments.PushValue (value); 1435 arguments.PushValue (value); 1436 1437 value.SetValueType (Value::eValueTypeScalar); 1438 value.SetCompilerType (clang_uint32_t_type); 1439 arguments.PushValue (value); 1440 arguments.PushValue (value); 1441 1442 get_class_info_function = m_get_class_info_code->MakeFunctionCaller(clang_uint32_t_type, 1443 arguments, 1444 thread_sp, 1445 error); 1446 1447 if (error.Fail()) 1448 { 1449 if (log) 1450 log->Printf("Failed to make function caller for implementation lookup: %s.", error.AsCString()); 1451 return false; 1452 } 1453 } 1454 else 1455 { 1456 get_class_info_function = m_get_class_info_code->GetFunctionCaller(); 1457 if (!get_class_info_function) 1458 { 1459 if (log) 1460 { 1461 log->Printf("Failed to get implementation lookup function caller."); 1462 diagnostics.Dump(log); 1463 } 1464 1465 return false; 1466 } 1467 arguments = get_class_info_function->GetArgumentValues(); 1468 } 1469 1470 diagnostics.Clear(); 1471 1472 const uint32_t class_info_byte_size = addr_size + 4; 1473 const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; 1474 lldb::addr_t class_infos_addr = process->AllocateMemory(class_infos_byte_size, 1475 ePermissionsReadable | ePermissionsWritable, 1476 err); 1477 1478 if (class_infos_addr == LLDB_INVALID_ADDRESS) 1479 return false; 1480 1481 std::lock_guard<std::mutex> guard(m_get_class_info_args_mutex); 1482 1483 // Fill in our function argument values 1484 arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress(); 1485 arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr; 1486 arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size; 1487 arguments.GetValueAtIndex(3)->GetScalar() = (GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES) == nullptr ? 0 : 1); 1488 1489 1490 bool success = false; 1491 1492 diagnostics.Clear(); 1493 1494 // Write our function arguments into the process so we can run our function 1495 if (get_class_info_function->WriteFunctionArguments(exe_ctx, m_get_class_info_args, arguments, diagnostics)) 1496 { 1497 EvaluateExpressionOptions options; 1498 options.SetUnwindOnError(true); 1499 options.SetTryAllThreads(false); 1500 options.SetStopOthers(true); 1501 options.SetIgnoreBreakpoints(true); 1502 options.SetTimeoutUsec(UTILITY_FUNCTION_TIMEOUT_USEC); 1503 1504 Value return_value; 1505 return_value.SetValueType (Value::eValueTypeScalar); 1506 //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type); 1507 return_value.SetCompilerType(clang_uint32_t_type); 1508 return_value.GetScalar() = 0; 1509 1510 diagnostics.Clear(); 1511 1512 // Run the function 1513 ExpressionResults results = get_class_info_function->ExecuteFunction(exe_ctx, &m_get_class_info_args, options, 1514 diagnostics, return_value); 1515 1516 if (results == eExpressionCompleted) 1517 { 1518 // The result is the number of ClassInfo structures that were filled in 1519 uint32_t num_class_infos = return_value.GetScalar().ULong(); 1520 if (log) 1521 log->Printf("Discovered %u ObjC classes\n",num_class_infos); 1522 if (num_class_infos > 0) 1523 { 1524 // Read the ClassInfo structures 1525 DataBufferHeap buffer (num_class_infos * class_info_byte_size, 0); 1526 if (process->ReadMemory(class_infos_addr, buffer.GetBytes(), buffer.GetByteSize(), err) == buffer.GetByteSize()) 1527 { 1528 DataExtractor class_infos_data (buffer.GetBytes(), 1529 buffer.GetByteSize(), 1530 process->GetByteOrder(), 1531 addr_size); 1532 ParseClassInfoArray (class_infos_data, num_class_infos); 1533 } 1534 } 1535 success = true; 1536 } 1537 else 1538 { 1539 if (log) 1540 { 1541 log->Printf("Error evaluating our find class name function."); 1542 diagnostics.Dump(log); 1543 } 1544 } 1545 } 1546 else 1547 { 1548 if (log) 1549 { 1550 log->Printf("Error writing function arguments."); 1551 diagnostics.Dump(log); 1552 } 1553 } 1554 1555 // Deallocate the memory we allocated for the ClassInfo array 1556 process->DeallocateMemory(class_infos_addr); 1557 1558 return success; 1559} 1560 1561uint32_t 1562AppleObjCRuntimeV2::ParseClassInfoArray (const DataExtractor &data, uint32_t num_class_infos) 1563{ 1564 // Parses an array of "num_class_infos" packed ClassInfo structures: 1565 // 1566 // struct ClassInfo 1567 // { 1568 // Class isa; 1569 // uint32_t hash; 1570 // } __attribute__((__packed__)); 1571 1572 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 1573 1574 uint32_t num_parsed = 0; 1575 1576 // Iterate through all ClassInfo structures 1577 lldb::offset_t offset = 0; 1578 for (uint32_t i=0; i<num_class_infos; ++i) 1579 { 1580 ObjCISA isa = data.GetPointer(&offset); 1581 1582 if (isa == 0) 1583 { 1584 if (log) 1585 log->Printf("AppleObjCRuntimeV2 found NULL isa, ignoring this class info"); 1586 continue; 1587 } 1588 // Check if we already know about this ISA, if we do, the info will 1589 // never change, so we can just skip it. 1590 if (ISAIsCached(isa)) 1591 { 1592 offset += 4; 1593 } 1594 else 1595 { 1596 // Read the 32 bit hash for the class name 1597 const uint32_t name_hash = data.GetU32(&offset); 1598 ClassDescriptorSP descriptor_sp (new ClassDescriptorV2(*this, isa, NULL)); 1599 AddClass (isa, descriptor_sp, name_hash); 1600 num_parsed++; 1601 if (log && log->GetVerbose()) 1602 log->Printf("AppleObjCRuntimeV2 added isa=0x%" PRIx64 ", hash=0x%8.8x, name=%s", isa, name_hash,descriptor_sp->GetClassName().AsCString("<unknown>")); 1603 } 1604 } 1605 return num_parsed; 1606} 1607 1608AppleObjCRuntimeV2::DescriptorMapUpdateResult 1609AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() 1610{ 1611 Process *process = GetProcess(); 1612 1613 if (process == NULL) 1614 return DescriptorMapUpdateResult::Fail(); 1615 1616 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 1617 1618 ExecutionContext exe_ctx; 1619 1620 ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread(); 1621 1622 if (!thread_sp) 1623 return DescriptorMapUpdateResult::Fail(); 1624 1625 thread_sp->CalculateExecutionContext(exe_ctx); 1626 ClangASTContext *ast = process->GetTarget().GetScratchClangASTContext(); 1627 1628 if (!ast) 1629 return DescriptorMapUpdateResult::Fail(); 1630 1631 Address function_address; 1632 1633 DiagnosticManager diagnostics; 1634 1635 const uint32_t addr_size = process->GetAddressByteSize(); 1636 1637 Error err; 1638 1639 const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress(); 1640 1641 if (objc_opt_ptr == LLDB_INVALID_ADDRESS) 1642 return DescriptorMapUpdateResult::Fail(); 1643 1644 // Read the total number of classes from the hash table 1645 const uint32_t num_classes = 128*1024; 1646 if (num_classes == 0) 1647 { 1648 if (log) 1649 log->Printf ("No dynamic classes found in gdb_objc_realized_classes_addr."); 1650 return DescriptorMapUpdateResult::Fail(); 1651 } 1652 1653 // Make some types for our arguments 1654 CompilerType clang_uint32_t_type = ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); 1655 CompilerType clang_void_pointer_type = ast->GetBasicType(eBasicTypeVoid).GetPointerType(); 1656 1657 ValueList arguments; 1658 FunctionCaller *get_shared_cache_class_info_function = nullptr; 1659 1660 if (!m_get_shared_cache_class_info_code.get()) 1661 { 1662 Error error; 1663 m_get_shared_cache_class_info_code.reset (GetTargetRef().GetUtilityFunctionForLanguage (g_get_shared_cache_class_info_body, 1664 eLanguageTypeObjC, 1665 g_get_shared_cache_class_info_name, 1666 error)); 1667 if (error.Fail()) 1668 { 1669 if (log) 1670 log->Printf ("Failed to get Utility function for implementation lookup: %s.", error.AsCString()); 1671 m_get_shared_cache_class_info_code.reset(); 1672 } 1673 else 1674 { 1675 diagnostics.Clear(); 1676 1677 if (!m_get_shared_cache_class_info_code->Install(diagnostics, exe_ctx)) 1678 { 1679 if (log) 1680 { 1681 log->Printf("Failed to install implementation lookup."); 1682 diagnostics.Dump(log); 1683 } 1684 m_get_shared_cache_class_info_code.reset(); 1685 } 1686 } 1687 1688 if (!m_get_shared_cache_class_info_code.get()) 1689 return DescriptorMapUpdateResult::Fail(); 1690 1691 // Next make the function caller for our implementation utility function. 1692 Value value; 1693 value.SetValueType (Value::eValueTypeScalar); 1694 //value.SetContext (Value::eContextTypeClangType, clang_void_pointer_type); 1695 value.SetCompilerType (clang_void_pointer_type); 1696 arguments.PushValue (value); 1697 arguments.PushValue (value); 1698 1699 value.SetValueType (Value::eValueTypeScalar); 1700 //value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type); 1701 value.SetCompilerType (clang_uint32_t_type); 1702 arguments.PushValue (value); 1703 arguments.PushValue (value); 1704 1705 get_shared_cache_class_info_function = m_get_shared_cache_class_info_code->MakeFunctionCaller(clang_uint32_t_type, 1706 arguments, 1707 thread_sp, 1708 error); 1709 1710 if (get_shared_cache_class_info_function == nullptr) 1711 return DescriptorMapUpdateResult::Fail(); 1712 1713 } 1714 else 1715 { 1716 get_shared_cache_class_info_function = m_get_shared_cache_class_info_code->GetFunctionCaller(); 1717 if (get_shared_cache_class_info_function == nullptr) 1718 return DescriptorMapUpdateResult::Fail(); 1719 arguments = get_shared_cache_class_info_function->GetArgumentValues(); 1720 } 1721 1722 diagnostics.Clear(); 1723 1724 const uint32_t class_info_byte_size = addr_size + 4; 1725 const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; 1726 lldb::addr_t class_infos_addr = process->AllocateMemory (class_infos_byte_size, 1727 ePermissionsReadable | ePermissionsWritable, 1728 err); 1729 1730 if (class_infos_addr == LLDB_INVALID_ADDRESS) 1731 return DescriptorMapUpdateResult::Fail(); 1732 1733 std::lock_guard<std::mutex> guard(m_get_shared_cache_class_info_args_mutex); 1734 1735 // Fill in our function argument values 1736 arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr; 1737 arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr; 1738 arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size; 1739 arguments.GetValueAtIndex(3)->GetScalar() = (GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES) == nullptr ? 0 : 1); 1740 1741 1742 bool success = false; 1743 bool any_found = false; 1744 1745 diagnostics.Clear(); 1746 1747 // Write our function arguments into the process so we can run our function 1748 if (get_shared_cache_class_info_function->WriteFunctionArguments(exe_ctx, m_get_shared_cache_class_info_args, 1749 arguments, diagnostics)) 1750 { 1751 EvaluateExpressionOptions options; 1752 options.SetUnwindOnError(true); 1753 options.SetTryAllThreads(false); 1754 options.SetStopOthers(true); 1755 options.SetIgnoreBreakpoints(true); 1756 options.SetTimeoutUsec(UTILITY_FUNCTION_TIMEOUT_USEC); 1757 1758 Value return_value; 1759 return_value.SetValueType (Value::eValueTypeScalar); 1760 //return_value.SetContext (Value::eContextTypeClangType, clang_uint32_t_type); 1761 return_value.SetCompilerType(clang_uint32_t_type); 1762 return_value.GetScalar() = 0; 1763 1764 diagnostics.Clear(); 1765 1766 // Run the function 1767 ExpressionResults results = get_shared_cache_class_info_function->ExecuteFunction( 1768 exe_ctx, &m_get_shared_cache_class_info_args, options, diagnostics, return_value); 1769 1770 if (results == eExpressionCompleted) 1771 { 1772 // The result is the number of ClassInfo structures that were filled in 1773 uint32_t num_class_infos = return_value.GetScalar().ULong(); 1774 if (log) 1775 log->Printf("Discovered %u ObjC classes in shared cache\n",num_class_infos); 1776#ifdef LLDB_CONFIGURATION_DEBUG 1777 assert (num_class_infos <= num_classes); 1778#endif 1779 if (num_class_infos > 0) 1780 { 1781 if (num_class_infos > num_classes) 1782 { 1783 num_class_infos = num_classes; 1784 1785 success = false; 1786 } 1787 else 1788 { 1789 success = true; 1790 } 1791 1792 // Read the ClassInfo structures 1793 DataBufferHeap buffer (num_class_infos * class_info_byte_size, 0); 1794 if (process->ReadMemory(class_infos_addr, 1795 buffer.GetBytes(), 1796 buffer.GetByteSize(), 1797 err) == buffer.GetByteSize()) 1798 { 1799 DataExtractor class_infos_data (buffer.GetBytes(), 1800 buffer.GetByteSize(), 1801 process->GetByteOrder(), 1802 addr_size); 1803 1804 any_found = (ParseClassInfoArray (class_infos_data, num_class_infos) > 0); 1805 } 1806 } 1807 else 1808 { 1809 success = true; 1810 } 1811 } 1812 else 1813 { 1814 if (log) 1815 { 1816 log->Printf("Error evaluating our find class name function."); 1817 diagnostics.Dump(log); 1818 } 1819 } 1820 } 1821 else 1822 { 1823 if (log) 1824 { 1825 log->Printf("Error writing function arguments."); 1826 diagnostics.Dump(log); 1827 } 1828 } 1829 1830 // Deallocate the memory we allocated for the ClassInfo array 1831 process->DeallocateMemory(class_infos_addr); 1832 1833 return DescriptorMapUpdateResult(success, any_found); 1834} 1835 1836bool 1837AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory (RemoteNXMapTable &hash_table) 1838{ 1839 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS)); 1840 1841 Process *process = GetProcess(); 1842 1843 if (process == NULL) 1844 return false; 1845 1846 uint32_t num_map_table_isas = 0; 1847 1848 ModuleSP objc_module_sp(GetObjCModule()); 1849 1850 if (objc_module_sp) 1851 { 1852 for (RemoteNXMapTable::element elt : hash_table) 1853 { 1854 ++num_map_table_isas; 1855 1856 if (ISAIsCached(elt.second)) 1857 continue; 1858 1859 ClassDescriptorSP descriptor_sp = ClassDescriptorSP(new ClassDescriptorV2(*this, elt.second, elt.first.AsCString())); 1860 1861 if (log && log->GetVerbose()) 1862 log->Printf("AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64 " (%s) from dynamic table to isa->descriptor cache", elt.second, elt.first.AsCString()); 1863 1864 AddClass (elt.second, descriptor_sp, elt.first.AsCString()); 1865 } 1866 } 1867 1868 return num_map_table_isas > 0; 1869} 1870 1871lldb::addr_t 1872AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() 1873{ 1874 Process *process = GetProcess(); 1875 1876 if (process) 1877 { 1878 ModuleSP objc_module_sp(GetObjCModule()); 1879 1880 if (objc_module_sp) 1881 { 1882 ObjectFile *objc_object = objc_module_sp->GetObjectFile(); 1883 1884 if (objc_object) 1885 { 1886 SectionList *section_list = objc_module_sp->GetSectionList(); 1887 1888 if (section_list) 1889 { 1890 SectionSP text_segment_sp (section_list->FindSectionByName(ConstString("__TEXT"))); 1891 1892 if (text_segment_sp) 1893 { 1894 SectionSP objc_opt_section_sp (text_segment_sp->GetChildren().FindSectionByName(ConstString("__objc_opt_ro"))); 1895 1896 if (objc_opt_section_sp) 1897 { 1898 return objc_opt_section_sp->GetLoadBaseAddress(&process->GetTarget()); 1899 } 1900 } 1901 } 1902 } 1903 } 1904 } 1905 return LLDB_INVALID_ADDRESS; 1906} 1907 1908void 1909AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() 1910{ 1911 Timer scoped_timer (__PRETTY_FUNCTION__, __PRETTY_FUNCTION__); 1912 1913 // Else we need to check with our process to see when the map was updated. 1914 Process *process = GetProcess(); 1915 1916 if (process) 1917 { 1918 RemoteNXMapTable hash_table; 1919 1920 // Update the process stop ID that indicates the last time we updated the 1921 // map, whether it was successful or not. 1922 m_isa_to_descriptor_stop_id = process->GetStopID(); 1923 1924 if (!m_hash_signature.NeedsUpdate(process, this, hash_table)) 1925 return; 1926 1927 m_hash_signature.UpdateSignature (hash_table); 1928 1929 // Grab the dynamically loaded objc classes from the hash table in memory 1930 UpdateISAToDescriptorMapDynamic(hash_table); 1931 1932 // Now get the objc classes that are baked into the Objective C runtime 1933 // in the shared cache, but only once per process as this data never 1934 // changes 1935 if (!m_loaded_objc_opt) 1936 { 1937 DescriptorMapUpdateResult shared_cache_update_result = UpdateISAToDescriptorMapSharedCache(); 1938 if (!shared_cache_update_result.any_found) 1939 WarnIfNoClassesCached (); 1940 else 1941 m_loaded_objc_opt = true; 1942 } 1943 } 1944 else 1945 { 1946 m_isa_to_descriptor_stop_id = UINT32_MAX; 1947 } 1948} 1949 1950void 1951AppleObjCRuntimeV2::WarnIfNoClassesCached () 1952{ 1953 if (m_noclasses_warning_emitted) 1954 return; 1955 1956 if (m_process && 1957 m_process->GetTarget().GetPlatform() && 1958 m_process->GetTarget().GetPlatform()->GetPluginName().GetStringRef().endswith("-simulator")) 1959 { 1960 // Simulators do not have the objc_opt_ro class table so don't actually complain to the user 1961 m_noclasses_warning_emitted = true; 1962 return; 1963 } 1964 1965 Debugger &debugger(GetProcess()->GetTarget().GetDebugger()); 1966 1967 if (debugger.GetAsyncOutputStream()) 1968 { 1969 debugger.GetAsyncOutputStream()->PutCString("warning: could not load any Objective-C class information from the dyld shared cache. This will significantly reduce the quality of type information available.\n"); 1970 m_noclasses_warning_emitted = true; 1971 } 1972} 1973 1974// TODO: should we have a transparent_kvo parameter here to say if we 1975// want to replace the KVO swizzled class with the actual user-level type? 1976ConstString 1977AppleObjCRuntimeV2::GetActualTypeName(ObjCLanguageRuntime::ObjCISA isa) 1978{ 1979 if (isa == g_objc_Tagged_ISA) 1980 { 1981 static const ConstString g_objc_tagged_isa_name ("_lldb_Tagged_ObjC_ISA"); 1982 return g_objc_tagged_isa_name; 1983 } 1984 if (isa == g_objc_Tagged_ISA_NSAtom) 1985 { 1986 static const ConstString g_objc_tagged_isa_nsatom_name ("NSAtom"); 1987 return g_objc_tagged_isa_nsatom_name; 1988 } 1989 if (isa == g_objc_Tagged_ISA_NSNumber) 1990 { 1991 static const ConstString g_objc_tagged_isa_nsnumber_name ("NSNumber"); 1992 return g_objc_tagged_isa_nsnumber_name; 1993 } 1994 if (isa == g_objc_Tagged_ISA_NSDateTS) 1995 { 1996 static const ConstString g_objc_tagged_isa_nsdatets_name ("NSDateTS"); 1997 return g_objc_tagged_isa_nsdatets_name; 1998 } 1999 if (isa == g_objc_Tagged_ISA_NSManagedObject) 2000 { 2001 static const ConstString g_objc_tagged_isa_nsmanagedobject_name ("NSManagedObject"); 2002 return g_objc_tagged_isa_nsmanagedobject_name; 2003 } 2004 if (isa == g_objc_Tagged_ISA_NSDate) 2005 { 2006 static const ConstString g_objc_tagged_isa_nsdate_name ("NSDate"); 2007 return g_objc_tagged_isa_nsdate_name; 2008 } 2009 return ObjCLanguageRuntime::GetActualTypeName(isa); 2010} 2011 2012DeclVendor * 2013AppleObjCRuntimeV2::GetDeclVendor() 2014{ 2015 if (!m_decl_vendor_ap.get()) 2016 m_decl_vendor_ap.reset(new AppleObjCDeclVendor(*this)); 2017 2018 return m_decl_vendor_ap.get(); 2019} 2020 2021lldb::addr_t 2022AppleObjCRuntimeV2::LookupRuntimeSymbol (const ConstString &name) 2023{ 2024 lldb::addr_t ret = LLDB_INVALID_ADDRESS; 2025 2026 const char *name_cstr = name.AsCString(); 2027 2028 if (name_cstr) 2029 { 2030 llvm::StringRef name_strref(name_cstr); 2031 2032 static const llvm::StringRef ivar_prefix("OBJC_IVAR_$_"); 2033 static const llvm::StringRef class_prefix("OBJC_CLASS_$_"); 2034 2035 if (name_strref.startswith(ivar_prefix)) 2036 { 2037 llvm::StringRef ivar_skipped_prefix = name_strref.substr(ivar_prefix.size()); 2038 std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar = ivar_skipped_prefix.split('.'); 2039 2040 if (class_and_ivar.first.size() && class_and_ivar.second.size()) 2041 { 2042 const ConstString class_name_cs(class_and_ivar.first); 2043 ClassDescriptorSP descriptor = ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs); 2044 2045 if (descriptor) 2046 { 2047 const ConstString ivar_name_cs(class_and_ivar.second); 2048 const char *ivar_name_cstr = ivar_name_cs.AsCString(); 2049 2050 auto ivar_func = [&ret, ivar_name_cstr](const char *name, const char *type, lldb::addr_t offset_addr, uint64_t size) -> lldb::addr_t 2051 { 2052 if (!strcmp(name, ivar_name_cstr)) 2053 { 2054 ret = offset_addr; 2055 return true; 2056 } 2057 return false; 2058 }; 2059 2060 descriptor->Describe(std::function<void (ObjCISA)>(nullptr), 2061 std::function<bool (const char *, const char *)>(nullptr), 2062 std::function<bool (const char *, const char *)>(nullptr), 2063 ivar_func); 2064 } 2065 } 2066 } 2067 else if (name_strref.startswith(class_prefix)) 2068 { 2069 llvm::StringRef class_skipped_prefix = name_strref.substr(class_prefix.size()); 2070 const ConstString class_name_cs(class_skipped_prefix); 2071 ClassDescriptorSP descriptor = GetClassDescriptorFromClassName(class_name_cs); 2072 2073 if (descriptor) 2074 ret = descriptor->GetISA(); 2075 } 2076 } 2077 2078 return ret; 2079} 2080 2081AppleObjCRuntimeV2::NonPointerISACache* 2082AppleObjCRuntimeV2::NonPointerISACache::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp) 2083{ 2084 Process* process(runtime.GetProcess()); 2085 2086 Error error; 2087 2088 auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol(process, 2089 ConstString("objc_debug_isa_magic_mask"), 2090 objc_module_sp, 2091 error); 2092 if (error.Fail()) 2093 return NULL; 2094 2095 auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol(process, 2096 ConstString("objc_debug_isa_magic_value"), 2097 objc_module_sp, 2098 error); 2099 if (error.Fail()) 2100 return NULL; 2101 2102 auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol(process, 2103 ConstString("objc_debug_isa_class_mask"), 2104 objc_module_sp, 2105 error); 2106 if (error.Fail()) 2107 return NULL; 2108 2109 // we might want to have some rules to outlaw these other values (e.g if the mask is zero but the value is non-zero, ...) 2110 2111 return new NonPointerISACache(runtime, 2112 objc_debug_isa_class_mask, 2113 objc_debug_isa_magic_mask, 2114 objc_debug_isa_magic_value); 2115} 2116 2117AppleObjCRuntimeV2::TaggedPointerVendorV2* 2118AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance (AppleObjCRuntimeV2& runtime, const lldb::ModuleSP& objc_module_sp) 2119{ 2120 Process* process(runtime.GetProcess()); 2121 2122 Error error; 2123 2124 auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol(process, 2125 ConstString("objc_debug_taggedpointer_mask"), 2126 objc_module_sp, 2127 error); 2128 if (error.Fail()) 2129 return new TaggedPointerVendorLegacy(runtime); 2130 2131 auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol(process, 2132 ConstString("objc_debug_taggedpointer_slot_shift"), 2133 objc_module_sp, 2134 error, 2135 true, 2136 4); 2137 if (error.Fail()) 2138 return new TaggedPointerVendorLegacy(runtime); 2139 2140 auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol(process, 2141 ConstString("objc_debug_taggedpointer_slot_mask"), 2142 objc_module_sp, 2143 error, 2144 true, 2145 4); 2146 if (error.Fail()) 2147 return new TaggedPointerVendorLegacy(runtime); 2148 2149 auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol(process, 2150 ConstString("objc_debug_taggedpointer_payload_lshift"), 2151 objc_module_sp, 2152 error, 2153 true, 2154 4); 2155 if (error.Fail()) 2156 return new TaggedPointerVendorLegacy(runtime); 2157 2158 auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol(process, 2159 ConstString("objc_debug_taggedpointer_payload_rshift"), 2160 objc_module_sp, 2161 error, 2162 true, 2163 4); 2164 if (error.Fail()) 2165 return new TaggedPointerVendorLegacy(runtime); 2166 2167 auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol(process, 2168 ConstString("objc_debug_taggedpointer_classes"), 2169 objc_module_sp, 2170 error, 2171 false); 2172 if (error.Fail()) 2173 return new TaggedPointerVendorLegacy(runtime); 2174 2175 // try to detect the "extended tagged pointer" variables - if any are missing, use the non-extended vendor 2176 do 2177 { 2178 auto objc_debug_taggedpointer_ext_mask = ExtractRuntimeGlobalSymbol(process, 2179 ConstString("objc_debug_taggedpointer_ext_mask"), 2180 objc_module_sp, 2181 error); 2182 if (error.Fail()) 2183 break; 2184 2185 auto objc_debug_taggedpointer_ext_slot_shift = ExtractRuntimeGlobalSymbol(process, 2186 ConstString("objc_debug_taggedpointer_ext_slot_shift"), 2187 objc_module_sp, 2188 error, 2189 true, 2190 4); 2191 if (error.Fail()) 2192 break; 2193 2194 auto objc_debug_taggedpointer_ext_slot_mask = ExtractRuntimeGlobalSymbol(process, 2195 ConstString("objc_debug_taggedpointer_ext_slot_mask"), 2196 objc_module_sp, 2197 error, 2198 true, 2199 4); 2200 if (error.Fail()) 2201 break; 2202 2203 auto objc_debug_taggedpointer_ext_classes = ExtractRuntimeGlobalSymbol(process, 2204 ConstString("objc_debug_taggedpointer_ext_classes"), 2205 objc_module_sp, 2206 error, 2207 false); 2208 if (error.Fail()) 2209 break; 2210 2211 auto objc_debug_taggedpointer_ext_payload_lshift = ExtractRuntimeGlobalSymbol(process, 2212 ConstString("objc_debug_taggedpointer_ext_payload_lshift"), 2213 objc_module_sp, 2214 error, 2215 true, 2216 4); 2217 if (error.Fail()) 2218 break; 2219 2220 auto objc_debug_taggedpointer_ext_payload_rshift = ExtractRuntimeGlobalSymbol(process, 2221 ConstString("objc_debug_taggedpointer_ext_payload_rshift"), 2222 objc_module_sp, 2223 error, 2224 true, 2225 4); 2226 if (error.Fail()) 2227 break; 2228 2229 return new TaggedPointerVendorExtended(runtime, 2230 objc_debug_taggedpointer_mask, 2231 objc_debug_taggedpointer_ext_mask, 2232 objc_debug_taggedpointer_slot_shift, 2233 objc_debug_taggedpointer_ext_slot_shift, 2234 objc_debug_taggedpointer_slot_mask, 2235 objc_debug_taggedpointer_ext_slot_mask, 2236 objc_debug_taggedpointer_payload_lshift, 2237 objc_debug_taggedpointer_payload_rshift, 2238 objc_debug_taggedpointer_ext_payload_lshift, 2239 objc_debug_taggedpointer_ext_payload_rshift, 2240 objc_debug_taggedpointer_classes, 2241 objc_debug_taggedpointer_ext_classes); 2242 } while(false); 2243 2244 // we might want to have some rules to outlaw these values (e.g if the table's address is zero) 2245 2246 return new TaggedPointerVendorRuntimeAssisted(runtime, 2247 objc_debug_taggedpointer_mask, 2248 objc_debug_taggedpointer_slot_shift, 2249 objc_debug_taggedpointer_slot_mask, 2250 objc_debug_taggedpointer_payload_lshift, 2251 objc_debug_taggedpointer_payload_rshift, 2252 objc_debug_taggedpointer_classes); 2253} 2254 2255bool 2256AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer (lldb::addr_t ptr) 2257{ 2258 return (ptr & 1); 2259} 2260 2261ObjCLanguageRuntime::ClassDescriptorSP 2262AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor (lldb::addr_t ptr) 2263{ 2264 if (!IsPossibleTaggedPointer(ptr)) 2265 return ObjCLanguageRuntime::ClassDescriptorSP(); 2266 2267 uint32_t foundation_version = m_runtime.GetFoundationVersion(); 2268 2269 if (foundation_version == LLDB_INVALID_MODULE_VERSION) 2270 return ObjCLanguageRuntime::ClassDescriptorSP(); 2271 2272 uint64_t class_bits = (ptr & 0xE) >> 1; 2273 ConstString name; 2274 2275 // TODO: make a table 2276 if (foundation_version >= 900) 2277 { 2278 switch (class_bits) 2279 { 2280 case 0: 2281 name = ConstString("NSAtom"); 2282 break; 2283 case 3: 2284 name = ConstString("NSNumber"); 2285 break; 2286 case 4: 2287 name = ConstString("NSDateTS"); 2288 break; 2289 case 5: 2290 name = ConstString("NSManagedObject"); 2291 break; 2292 case 6: 2293 name = ConstString("NSDate"); 2294 break; 2295 default: 2296 return ObjCLanguageRuntime::ClassDescriptorSP(); 2297 } 2298 } 2299 else 2300 { 2301 switch (class_bits) 2302 { 2303 case 1: 2304 name = ConstString("NSNumber"); 2305 break; 2306 case 5: 2307 name = ConstString("NSManagedObject"); 2308 break; 2309 case 6: 2310 name = ConstString("NSDate"); 2311 break; 2312 case 7: 2313 name = ConstString("NSDateTS"); 2314 break; 2315 default: 2316 return ObjCLanguageRuntime::ClassDescriptorSP(); 2317 } 2318 } 2319 return ClassDescriptorSP(new ClassDescriptorV2Tagged(name,ptr)); 2320} 2321 2322AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::TaggedPointerVendorRuntimeAssisted (AppleObjCRuntimeV2& runtime, 2323 uint64_t objc_debug_taggedpointer_mask, 2324 uint32_t objc_debug_taggedpointer_slot_shift, 2325 uint32_t objc_debug_taggedpointer_slot_mask, 2326 uint32_t objc_debug_taggedpointer_payload_lshift, 2327 uint32_t objc_debug_taggedpointer_payload_rshift, 2328 lldb::addr_t objc_debug_taggedpointer_classes) : 2329TaggedPointerVendorV2(runtime), 2330m_cache(), 2331m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask), 2332m_objc_debug_taggedpointer_slot_shift(objc_debug_taggedpointer_slot_shift), 2333m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask), 2334m_objc_debug_taggedpointer_payload_lshift(objc_debug_taggedpointer_payload_lshift), 2335m_objc_debug_taggedpointer_payload_rshift(objc_debug_taggedpointer_payload_rshift), 2336m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes) 2337{ 2338} 2339 2340bool 2341AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::IsPossibleTaggedPointer (lldb::addr_t ptr) 2342{ 2343 return (ptr & m_objc_debug_taggedpointer_mask) != 0; 2344} 2345 2346ObjCLanguageRuntime::ClassDescriptorSP 2347AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor (lldb::addr_t ptr) 2348{ 2349 ClassDescriptorSP actual_class_descriptor_sp; 2350 uint64_t data_payload; 2351 2352 if (!IsPossibleTaggedPointer(ptr)) 2353 return ObjCLanguageRuntime::ClassDescriptorSP(); 2354 2355 uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) & m_objc_debug_taggedpointer_slot_mask; 2356 2357 CacheIterator iterator = m_cache.find(slot), 2358 end = m_cache.end(); 2359 if (iterator != end) 2360 { 2361 actual_class_descriptor_sp = iterator->second; 2362 } 2363 else 2364 { 2365 Process* process(m_runtime.GetProcess()); 2366 uintptr_t slot_ptr = slot*process->GetAddressByteSize()+m_objc_debug_taggedpointer_classes; 2367 Error error; 2368 uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error); 2369 if (error.Fail() || slot_data == 0 || slot_data == uintptr_t(LLDB_INVALID_ADDRESS)) 2370 return nullptr; 2371 actual_class_descriptor_sp = m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data); 2372 if (!actual_class_descriptor_sp) 2373 return ObjCLanguageRuntime::ClassDescriptorSP(); 2374 m_cache[slot] = actual_class_descriptor_sp; 2375 } 2376 2377 data_payload = (((uint64_t)ptr << m_objc_debug_taggedpointer_payload_lshift) >> m_objc_debug_taggedpointer_payload_rshift); 2378 2379 return ClassDescriptorSP(new ClassDescriptorV2Tagged(actual_class_descriptor_sp,data_payload)); 2380} 2381 2382AppleObjCRuntimeV2::TaggedPointerVendorExtended::TaggedPointerVendorExtended (AppleObjCRuntimeV2& runtime, 2383 uint64_t objc_debug_taggedpointer_mask, 2384 uint64_t objc_debug_taggedpointer_ext_mask, 2385 uint32_t objc_debug_taggedpointer_slot_shift, 2386 uint32_t objc_debug_taggedpointer_ext_slot_shift, 2387 uint32_t objc_debug_taggedpointer_slot_mask, 2388 uint32_t objc_debug_taggedpointer_ext_slot_mask, 2389 uint32_t objc_debug_taggedpointer_payload_lshift, 2390 uint32_t objc_debug_taggedpointer_payload_rshift, 2391 uint32_t objc_debug_taggedpointer_ext_payload_lshift, 2392 uint32_t objc_debug_taggedpointer_ext_payload_rshift, 2393 lldb::addr_t objc_debug_taggedpointer_classes, 2394 lldb::addr_t objc_debug_taggedpointer_ext_classes) : 2395TaggedPointerVendorRuntimeAssisted(runtime, 2396 objc_debug_taggedpointer_mask, 2397 objc_debug_taggedpointer_slot_shift, 2398 objc_debug_taggedpointer_slot_mask, 2399 objc_debug_taggedpointer_payload_lshift, 2400 objc_debug_taggedpointer_payload_rshift, 2401 objc_debug_taggedpointer_classes), 2402m_ext_cache(), 2403m_objc_debug_taggedpointer_ext_mask(objc_debug_taggedpointer_ext_mask), 2404m_objc_debug_taggedpointer_ext_slot_shift(objc_debug_taggedpointer_ext_slot_shift), 2405m_objc_debug_taggedpointer_ext_slot_mask(objc_debug_taggedpointer_ext_slot_mask), 2406m_objc_debug_taggedpointer_ext_payload_lshift(objc_debug_taggedpointer_ext_payload_lshift), 2407m_objc_debug_taggedpointer_ext_payload_rshift(objc_debug_taggedpointer_ext_payload_rshift), 2408m_objc_debug_taggedpointer_ext_classes(objc_debug_taggedpointer_ext_classes) 2409{ 2410} 2411 2412bool 2413AppleObjCRuntimeV2::TaggedPointerVendorExtended::IsPossibleExtendedTaggedPointer (lldb::addr_t ptr) 2414{ 2415 if (!IsPossibleTaggedPointer(ptr)) 2416 return false; 2417 2418 if (m_objc_debug_taggedpointer_ext_mask == 0) 2419 return false; 2420 2421 return ((ptr & m_objc_debug_taggedpointer_ext_mask) == m_objc_debug_taggedpointer_ext_mask); 2422} 2423 2424ObjCLanguageRuntime::ClassDescriptorSP 2425AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor (lldb::addr_t ptr) 2426{ 2427 ClassDescriptorSP actual_class_descriptor_sp; 2428 uint64_t data_payload; 2429 2430 if (!IsPossibleTaggedPointer(ptr)) 2431 return ObjCLanguageRuntime::ClassDescriptorSP(); 2432 2433 if (!IsPossibleExtendedTaggedPointer(ptr)) 2434 return this->TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(ptr); 2435 2436 uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_ext_slot_shift) & m_objc_debug_taggedpointer_ext_slot_mask; 2437 2438 CacheIterator iterator = m_ext_cache.find(slot), 2439 end = m_ext_cache.end(); 2440 if (iterator != end) 2441 { 2442 actual_class_descriptor_sp = iterator->second; 2443 } 2444 else 2445 { 2446 Process* process(m_runtime.GetProcess()); 2447 uintptr_t slot_ptr = slot*process->GetAddressByteSize()+m_objc_debug_taggedpointer_ext_classes; 2448 Error error; 2449 uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error); 2450 if (error.Fail() || slot_data == 0 || slot_data == uintptr_t(LLDB_INVALID_ADDRESS)) 2451 return nullptr; 2452 actual_class_descriptor_sp = m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data); 2453 if (!actual_class_descriptor_sp) 2454 return ObjCLanguageRuntime::ClassDescriptorSP(); 2455 m_ext_cache[slot] = actual_class_descriptor_sp; 2456 } 2457 2458 data_payload = (((uint64_t)ptr << m_objc_debug_taggedpointer_ext_payload_lshift) >> m_objc_debug_taggedpointer_ext_payload_rshift); 2459 2460 return ClassDescriptorSP(new ClassDescriptorV2Tagged(actual_class_descriptor_sp,data_payload)); 2461} 2462 2463AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache (AppleObjCRuntimeV2& runtime, 2464 uint64_t objc_debug_isa_class_mask, 2465 uint64_t objc_debug_isa_magic_mask, 2466 uint64_t objc_debug_isa_magic_value) : 2467m_runtime(runtime), 2468m_cache(), 2469m_objc_debug_isa_class_mask(objc_debug_isa_class_mask), 2470m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask), 2471m_objc_debug_isa_magic_value(objc_debug_isa_magic_value) 2472{ 2473} 2474 2475ObjCLanguageRuntime::ClassDescriptorSP 2476AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor (ObjCISA isa) 2477{ 2478 ObjCISA real_isa = 0; 2479 if (EvaluateNonPointerISA(isa, real_isa) == false) 2480 return ObjCLanguageRuntime::ClassDescriptorSP(); 2481 auto cache_iter = m_cache.find(real_isa); 2482 if (cache_iter != m_cache.end()) 2483 return cache_iter->second; 2484 auto descriptor_sp = m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa); 2485 if (descriptor_sp) // cache only positive matches since the table might grow 2486 m_cache[real_isa] = descriptor_sp; 2487 return descriptor_sp; 2488} 2489 2490bool 2491AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA (ObjCISA isa, ObjCISA& ret_isa) 2492{ 2493 if ( (isa & ~m_objc_debug_isa_class_mask) == 0) 2494 return false; 2495 if ( (isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value) 2496 { 2497 ret_isa = isa & m_objc_debug_isa_class_mask; 2498 return (ret_isa != 0); // this is a pointer so 0 is not a valid value 2499 } 2500 return false; 2501} 2502 2503ObjCLanguageRuntime::EncodingToTypeSP 2504AppleObjCRuntimeV2::GetEncodingToType () 2505{ 2506 if (!m_encoding_to_type_sp) 2507 m_encoding_to_type_sp.reset(new AppleObjCTypeEncodingParser(*this)); 2508 return m_encoding_to_type_sp; 2509} 2510 2511lldb_private::AppleObjCRuntime::ObjCISA 2512AppleObjCRuntimeV2::GetPointerISA (ObjCISA isa) 2513{ 2514 ObjCISA ret = isa; 2515 2516 if (m_non_pointer_isa_cache_ap) 2517 m_non_pointer_isa_cache_ap->EvaluateNonPointerISA(isa, ret); 2518 2519 return ret; 2520} 2521