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