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(Process *process); 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(process); 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 llvm::Expected<std::unique_ptr<UtilityFunction>> 844 AppleObjCRuntimeV2::CreateObjectChecker(std::string name, 845 ExecutionContext &exe_ctx) { 846 char check_function_code[2048]; 847 848 int len = 0; 849 if (m_has_object_getClass) { 850 len = ::snprintf(check_function_code, sizeof(check_function_code), R"( 851 extern "C" void *gdb_object_getClass(void *); 852 extern "C" int printf(const char *format, ...); 853 extern "C" void 854 %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) { 855 if ($__lldb_arg_obj == (void *)0) 856 return; // nil is ok 857 if (!gdb_object_getClass($__lldb_arg_obj)) { 858 *((volatile int *)0) = 'ocgc'; 859 } else if ($__lldb_arg_selector != (void *)0) { 860 signed char $responds = (signed char) 861 [(id)$__lldb_arg_obj respondsToSelector: 862 (void *) $__lldb_arg_selector]; 863 if ($responds == (signed char) 0) 864 *((volatile int *)0) = 'ocgc'; 865 } 866 })", 867 name.c_str()); 868 } else { 869 len = ::snprintf(check_function_code, sizeof(check_function_code), R"( 870 extern "C" void *gdb_class_getClass(void *); 871 extern "C" int printf(const char *format, ...); 872 extern "C" void 873 %s(void *$__lldb_arg_obj, void *$__lldb_arg_selector) { 874 if ($__lldb_arg_obj == (void *)0) 875 return; // nil is ok 876 void **$isa_ptr = (void **)$__lldb_arg_obj; 877 if (*$isa_ptr == (void *)0 || 878 !gdb_class_getClass(*$isa_ptr)) 879 *((volatile int *)0) = 'ocgc'; 880 else if ($__lldb_arg_selector != (void *)0) { 881 signed char $responds = (signed char) 882 [(id)$__lldb_arg_obj respondsToSelector: 883 (void *) $__lldb_arg_selector]; 884 if ($responds == (signed char) 0) 885 *((volatile int *)0) = 'ocgc'; 886 } 887 })", 888 name.c_str()); 889 } 890 891 assert(len < (int)sizeof(check_function_code)); 892 UNUSED_IF_ASSERT_DISABLED(len); 893 894 return GetTargetRef().CreateUtilityFunction(check_function_code, name, 895 eLanguageTypeC, exe_ctx); 896 } 897 898 size_t AppleObjCRuntimeV2::GetByteOffsetForIvar(CompilerType &parent_ast_type, 899 const char *ivar_name) { 900 uint32_t ivar_offset = LLDB_INVALID_IVAR_OFFSET; 901 902 ConstString class_name = parent_ast_type.GetTypeName(); 903 if (!class_name.IsEmpty() && ivar_name && ivar_name[0]) { 904 // Make the objective C V2 mangled name for the ivar offset from the class 905 // name and ivar name 906 std::string buffer("OBJC_IVAR_$_"); 907 buffer.append(class_name.AsCString()); 908 buffer.push_back('.'); 909 buffer.append(ivar_name); 910 ConstString ivar_const_str(buffer.c_str()); 911 912 // Try to get the ivar offset address from the symbol table first using the 913 // name we created above 914 SymbolContextList sc_list; 915 Target &target = m_process->GetTarget(); 916 target.GetImages().FindSymbolsWithNameAndType(ivar_const_str, 917 eSymbolTypeObjCIVar, sc_list); 918 919 addr_t ivar_offset_address = LLDB_INVALID_ADDRESS; 920 921 Status error; 922 SymbolContext ivar_offset_symbol; 923 if (sc_list.GetSize() == 1 && 924 sc_list.GetContextAtIndex(0, ivar_offset_symbol)) { 925 if (ivar_offset_symbol.symbol) 926 ivar_offset_address = 927 ivar_offset_symbol.symbol->GetLoadAddress(&target); 928 } 929 930 // If we didn't get the ivar offset address from the symbol table, fall 931 // back to getting it from the runtime 932 if (ivar_offset_address == LLDB_INVALID_ADDRESS) 933 ivar_offset_address = LookupRuntimeSymbol(ivar_const_str); 934 935 if (ivar_offset_address != LLDB_INVALID_ADDRESS) 936 ivar_offset = m_process->ReadUnsignedIntegerFromMemory( 937 ivar_offset_address, 4, LLDB_INVALID_IVAR_OFFSET, error); 938 } 939 return ivar_offset; 940 } 941 942 // tagged pointers are special not-a-real-pointer values that contain both type 943 // and value information this routine attempts to check with as little 944 // computational effort as possible whether something could possibly be a 945 // tagged pointer - false positives are possible but false negatives shouldn't 946 bool AppleObjCRuntimeV2::IsTaggedPointer(addr_t ptr) { 947 if (!m_tagged_pointer_vendor_up) 948 return false; 949 return m_tagged_pointer_vendor_up->IsPossibleTaggedPointer(ptr); 950 } 951 952 class RemoteNXMapTable { 953 public: 954 RemoteNXMapTable() 955 : m_count(0), m_num_buckets_minus_one(0), 956 m_buckets_ptr(LLDB_INVALID_ADDRESS), m_process(nullptr), 957 m_end_iterator(*this, -1), m_load_addr(LLDB_INVALID_ADDRESS), 958 m_map_pair_size(0), m_invalid_key(0) {} 959 960 void Dump() { 961 printf("RemoteNXMapTable.m_load_addr = 0x%" PRIx64 "\n", m_load_addr); 962 printf("RemoteNXMapTable.m_count = %u\n", m_count); 963 printf("RemoteNXMapTable.m_num_buckets_minus_one = %u\n", 964 m_num_buckets_minus_one); 965 printf("RemoteNXMapTable.m_buckets_ptr = 0x%" PRIX64 "\n", m_buckets_ptr); 966 } 967 968 bool ParseHeader(Process *process, lldb::addr_t load_addr) { 969 m_process = process; 970 m_load_addr = load_addr; 971 m_map_pair_size = m_process->GetAddressByteSize() * 2; 972 m_invalid_key = 973 m_process->GetAddressByteSize() == 8 ? UINT64_MAX : UINT32_MAX; 974 Status err; 975 976 // This currently holds true for all platforms we support, but we might 977 // need to change this to use get the actually byte size of "unsigned" from 978 // the target AST... 979 const uint32_t unsigned_byte_size = sizeof(uint32_t); 980 // Skip the prototype as we don't need it (const struct 981 // +NXMapTablePrototype *prototype) 982 983 bool success = true; 984 if (load_addr == LLDB_INVALID_ADDRESS) 985 success = false; 986 else { 987 lldb::addr_t cursor = load_addr + m_process->GetAddressByteSize(); 988 989 // unsigned count; 990 m_count = m_process->ReadUnsignedIntegerFromMemory( 991 cursor, unsigned_byte_size, 0, err); 992 if (m_count) { 993 cursor += unsigned_byte_size; 994 995 // unsigned nbBucketsMinusOne; 996 m_num_buckets_minus_one = m_process->ReadUnsignedIntegerFromMemory( 997 cursor, unsigned_byte_size, 0, err); 998 cursor += unsigned_byte_size; 999 1000 // void *buckets; 1001 m_buckets_ptr = m_process->ReadPointerFromMemory(cursor, err); 1002 1003 success = m_count > 0 && m_buckets_ptr != LLDB_INVALID_ADDRESS; 1004 } 1005 } 1006 1007 if (!success) { 1008 m_count = 0; 1009 m_num_buckets_minus_one = 0; 1010 m_buckets_ptr = LLDB_INVALID_ADDRESS; 1011 } 1012 return success; 1013 } 1014 1015 // const_iterator mimics NXMapState and its code comes from NXInitMapState 1016 // and NXNextMapState. 1017 typedef std::pair<ConstString, ObjCLanguageRuntime::ObjCISA> element; 1018 1019 friend class const_iterator; 1020 class const_iterator { 1021 public: 1022 const_iterator(RemoteNXMapTable &parent, int index) 1023 : m_parent(parent), m_index(index) { 1024 AdvanceToValidIndex(); 1025 } 1026 1027 const_iterator(const const_iterator &rhs) 1028 : m_parent(rhs.m_parent), m_index(rhs.m_index) { 1029 // AdvanceToValidIndex() has been called by rhs already. 1030 } 1031 1032 const_iterator &operator=(const const_iterator &rhs) { 1033 // AdvanceToValidIndex() has been called by rhs already. 1034 assert(&m_parent == &rhs.m_parent); 1035 m_index = rhs.m_index; 1036 return *this; 1037 } 1038 1039 bool operator==(const const_iterator &rhs) const { 1040 if (&m_parent != &rhs.m_parent) 1041 return false; 1042 if (m_index != rhs.m_index) 1043 return false; 1044 1045 return true; 1046 } 1047 1048 bool operator!=(const const_iterator &rhs) const { 1049 return !(operator==(rhs)); 1050 } 1051 1052 const_iterator &operator++() { 1053 AdvanceToValidIndex(); 1054 return *this; 1055 } 1056 1057 const element operator*() const { 1058 if (m_index == -1) { 1059 // TODO find a way to make this an error, but not an assert 1060 return element(); 1061 } 1062 1063 lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr; 1064 size_t map_pair_size = m_parent.m_map_pair_size; 1065 lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size); 1066 1067 Status err; 1068 1069 lldb::addr_t key = 1070 m_parent.m_process->ReadPointerFromMemory(pair_ptr, err); 1071 if (!err.Success()) 1072 return element(); 1073 lldb::addr_t value = m_parent.m_process->ReadPointerFromMemory( 1074 pair_ptr + m_parent.m_process->GetAddressByteSize(), err); 1075 if (!err.Success()) 1076 return element(); 1077 1078 std::string key_string; 1079 1080 m_parent.m_process->ReadCStringFromMemory(key, key_string, err); 1081 if (!err.Success()) 1082 return element(); 1083 1084 return element(ConstString(key_string.c_str()), 1085 (ObjCLanguageRuntime::ObjCISA)value); 1086 } 1087 1088 private: 1089 void AdvanceToValidIndex() { 1090 if (m_index == -1) 1091 return; 1092 1093 const lldb::addr_t pairs_ptr = m_parent.m_buckets_ptr; 1094 const size_t map_pair_size = m_parent.m_map_pair_size; 1095 const lldb::addr_t invalid_key = m_parent.m_invalid_key; 1096 Status err; 1097 1098 while (m_index--) { 1099 lldb::addr_t pair_ptr = pairs_ptr + (m_index * map_pair_size); 1100 lldb::addr_t key = 1101 m_parent.m_process->ReadPointerFromMemory(pair_ptr, err); 1102 1103 if (!err.Success()) { 1104 m_index = -1; 1105 return; 1106 } 1107 1108 if (key != invalid_key) 1109 return; 1110 } 1111 } 1112 RemoteNXMapTable &m_parent; 1113 int m_index; 1114 }; 1115 1116 const_iterator begin() { 1117 return const_iterator(*this, m_num_buckets_minus_one + 1); 1118 } 1119 1120 const_iterator end() { return m_end_iterator; } 1121 1122 uint32_t GetCount() const { return m_count; } 1123 1124 uint32_t GetBucketCount() const { return m_num_buckets_minus_one; } 1125 1126 lldb::addr_t GetBucketDataPointer() const { return m_buckets_ptr; } 1127 1128 lldb::addr_t GetTableLoadAddress() const { return m_load_addr; } 1129 1130 private: 1131 // contents of _NXMapTable struct 1132 uint32_t m_count; 1133 uint32_t m_num_buckets_minus_one; 1134 lldb::addr_t m_buckets_ptr; 1135 lldb_private::Process *m_process; 1136 const_iterator m_end_iterator; 1137 lldb::addr_t m_load_addr; 1138 size_t m_map_pair_size; 1139 lldb::addr_t m_invalid_key; 1140 }; 1141 1142 AppleObjCRuntimeV2::HashTableSignature::HashTableSignature() 1143 : m_count(0), m_num_buckets(0), m_buckets_ptr(0) {} 1144 1145 void AppleObjCRuntimeV2::HashTableSignature::UpdateSignature( 1146 const RemoteNXMapTable &hash_table) { 1147 m_count = hash_table.GetCount(); 1148 m_num_buckets = hash_table.GetBucketCount(); 1149 m_buckets_ptr = hash_table.GetBucketDataPointer(); 1150 } 1151 1152 bool AppleObjCRuntimeV2::HashTableSignature::NeedsUpdate( 1153 Process *process, AppleObjCRuntimeV2 *runtime, 1154 RemoteNXMapTable &hash_table) { 1155 if (!hash_table.ParseHeader(process, runtime->GetISAHashTablePointer())) { 1156 return false; // Failed to parse the header, no need to update anything 1157 } 1158 1159 // Check with out current signature and return true if the count, number of 1160 // buckets or the hash table address changes. 1161 if (m_count == hash_table.GetCount() && 1162 m_num_buckets == hash_table.GetBucketCount() && 1163 m_buckets_ptr == hash_table.GetBucketDataPointer()) { 1164 // Hash table hasn't changed 1165 return false; 1166 } 1167 // Hash table data has changed, we need to update 1168 return true; 1169 } 1170 1171 ObjCLanguageRuntime::ClassDescriptorSP 1172 AppleObjCRuntimeV2::GetClassDescriptorFromISA(ObjCISA isa) { 1173 ObjCLanguageRuntime::ClassDescriptorSP class_descriptor_sp; 1174 if (m_non_pointer_isa_cache_up) 1175 class_descriptor_sp = m_non_pointer_isa_cache_up->GetClassDescriptor(isa); 1176 if (!class_descriptor_sp) 1177 class_descriptor_sp = ObjCLanguageRuntime::GetClassDescriptorFromISA(isa); 1178 return class_descriptor_sp; 1179 } 1180 1181 ObjCLanguageRuntime::ClassDescriptorSP 1182 AppleObjCRuntimeV2::GetClassDescriptor(ValueObject &valobj) { 1183 ClassDescriptorSP objc_class_sp; 1184 if (valobj.IsBaseClass()) { 1185 ValueObject *parent = valobj.GetParent(); 1186 // if I am my own parent, bail out of here fast.. 1187 if (parent && parent != &valobj) { 1188 ClassDescriptorSP parent_descriptor_sp = GetClassDescriptor(*parent); 1189 if (parent_descriptor_sp) 1190 return parent_descriptor_sp->GetSuperclass(); 1191 } 1192 return nullptr; 1193 } 1194 // if we get an invalid VO (which might still happen when playing around with 1195 // pointers returned by the expression parser, don't consider this a valid 1196 // ObjC object) 1197 if (!valobj.GetCompilerType().IsValid()) 1198 return objc_class_sp; 1199 addr_t isa_pointer = valobj.GetPointerValue(); 1200 1201 // tagged pointer 1202 if (IsTaggedPointer(isa_pointer)) 1203 return m_tagged_pointer_vendor_up->GetClassDescriptor(isa_pointer); 1204 ExecutionContext exe_ctx(valobj.GetExecutionContextRef()); 1205 1206 Process *process = exe_ctx.GetProcessPtr(); 1207 if (!process) 1208 return objc_class_sp; 1209 1210 Status error; 1211 ObjCISA isa = process->ReadPointerFromMemory(isa_pointer, error); 1212 if (isa == LLDB_INVALID_ADDRESS) 1213 return objc_class_sp; 1214 1215 objc_class_sp = GetClassDescriptorFromISA(isa); 1216 if (isa && !objc_class_sp) { 1217 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_PROCESS | 1218 LIBLLDB_LOG_TYPES)); 1219 LLDB_LOGF(log, 1220 "0x%" PRIx64 1221 ": AppleObjCRuntimeV2::GetClassDescriptor() ISA was " 1222 "not in class descriptor cache 0x%" PRIx64, 1223 isa_pointer, isa); 1224 } 1225 return objc_class_sp; 1226 } 1227 1228 lldb::addr_t AppleObjCRuntimeV2::GetTaggedPointerObfuscator() { 1229 if (m_tagged_pointer_obfuscator != LLDB_INVALID_ADDRESS) 1230 return m_tagged_pointer_obfuscator; 1231 1232 1233 Process *process = GetProcess(); 1234 ModuleSP objc_module_sp(GetObjCModule()); 1235 1236 if (!objc_module_sp) 1237 return LLDB_INVALID_ADDRESS; 1238 1239 static ConstString g_gdb_objc_obfuscator("objc_debug_taggedpointer_obfuscator"); 1240 1241 const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType( 1242 g_gdb_objc_obfuscator, lldb::eSymbolTypeAny); 1243 if (symbol) { 1244 lldb::addr_t g_gdb_obj_obfuscator_ptr = 1245 symbol->GetLoadAddress(&process->GetTarget()); 1246 1247 if (g_gdb_obj_obfuscator_ptr != LLDB_INVALID_ADDRESS) { 1248 Status error; 1249 m_tagged_pointer_obfuscator = process->ReadPointerFromMemory( 1250 g_gdb_obj_obfuscator_ptr, error); 1251 } 1252 } 1253 // If we don't have a correct value at this point, there must be no obfuscation. 1254 if (m_tagged_pointer_obfuscator == LLDB_INVALID_ADDRESS) 1255 m_tagged_pointer_obfuscator = 0; 1256 1257 return m_tagged_pointer_obfuscator; 1258 } 1259 1260 lldb::addr_t AppleObjCRuntimeV2::GetISAHashTablePointer() { 1261 if (m_isa_hash_table_ptr == LLDB_INVALID_ADDRESS) { 1262 Process *process = GetProcess(); 1263 1264 ModuleSP objc_module_sp(GetObjCModule()); 1265 1266 if (!objc_module_sp) 1267 return LLDB_INVALID_ADDRESS; 1268 1269 static ConstString g_gdb_objc_realized_classes("gdb_objc_realized_classes"); 1270 1271 const Symbol *symbol = objc_module_sp->FindFirstSymbolWithNameAndType( 1272 g_gdb_objc_realized_classes, lldb::eSymbolTypeAny); 1273 if (symbol) { 1274 lldb::addr_t gdb_objc_realized_classes_ptr = 1275 symbol->GetLoadAddress(&process->GetTarget()); 1276 1277 if (gdb_objc_realized_classes_ptr != LLDB_INVALID_ADDRESS) { 1278 Status error; 1279 m_isa_hash_table_ptr = process->ReadPointerFromMemory( 1280 gdb_objc_realized_classes_ptr, error); 1281 } 1282 } 1283 } 1284 return m_isa_hash_table_ptr; 1285 } 1286 1287 AppleObjCRuntimeV2::DescriptorMapUpdateResult 1288 AppleObjCRuntimeV2::UpdateISAToDescriptorMapDynamic( 1289 RemoteNXMapTable &hash_table) { 1290 Process *process = GetProcess(); 1291 1292 if (process == nullptr) 1293 return DescriptorMapUpdateResult::Fail(); 1294 1295 uint32_t num_class_infos = 0; 1296 1297 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES)); 1298 1299 ExecutionContext exe_ctx; 1300 1301 ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread(); 1302 1303 if (!thread_sp) 1304 return DescriptorMapUpdateResult::Fail(); 1305 1306 thread_sp->CalculateExecutionContext(exe_ctx); 1307 TypeSystemClang *ast = 1308 ScratchTypeSystemClang::GetForTarget(process->GetTarget()); 1309 1310 if (!ast) 1311 return DescriptorMapUpdateResult::Fail(); 1312 1313 Address function_address; 1314 1315 const uint32_t addr_size = process->GetAddressByteSize(); 1316 1317 Status err; 1318 1319 // Read the total number of classes from the hash table 1320 const uint32_t num_classes = hash_table.GetCount(); 1321 if (num_classes == 0) { 1322 LLDB_LOGF(log, "No dynamic classes found in gdb_objc_realized_classes."); 1323 return DescriptorMapUpdateResult::Success(0); 1324 } 1325 1326 // Make some types for our arguments 1327 CompilerType clang_uint32_t_type = 1328 ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); 1329 CompilerType clang_void_pointer_type = 1330 ast->GetBasicType(eBasicTypeVoid).GetPointerType(); 1331 1332 ValueList arguments; 1333 FunctionCaller *get_class_info_function = nullptr; 1334 1335 if (!m_get_class_info_code) { 1336 auto utility_fn_or_error = GetTargetRef().CreateUtilityFunction( 1337 g_get_dynamic_class_info_body, g_get_dynamic_class_info_name, 1338 eLanguageTypeC, exe_ctx); 1339 if (!utility_fn_or_error) { 1340 LLDB_LOG_ERROR( 1341 log, utility_fn_or_error.takeError(), 1342 "Failed to get utility function for implementation lookup: {0}"); 1343 return DescriptorMapUpdateResult::Fail(); 1344 } 1345 m_get_class_info_code = std::move(*utility_fn_or_error); 1346 1347 // Next make the runner function for our implementation utility function. 1348 Value value; 1349 value.SetValueType(Value::eValueTypeScalar); 1350 value.SetCompilerType(clang_void_pointer_type); 1351 arguments.PushValue(value); 1352 arguments.PushValue(value); 1353 1354 value.SetValueType(Value::eValueTypeScalar); 1355 value.SetCompilerType(clang_uint32_t_type); 1356 arguments.PushValue(value); 1357 arguments.PushValue(value); 1358 1359 Status error; 1360 get_class_info_function = m_get_class_info_code->MakeFunctionCaller( 1361 clang_uint32_t_type, arguments, thread_sp, error); 1362 1363 if (error.Fail()) { 1364 LLDB_LOGF(log, 1365 "Failed to make function caller for implementation lookup: %s.", 1366 error.AsCString()); 1367 return DescriptorMapUpdateResult::Fail(); 1368 } 1369 } else { 1370 get_class_info_function = m_get_class_info_code->GetFunctionCaller(); 1371 if (!get_class_info_function) { 1372 LLDB_LOGF(log, "Failed to get implementation lookup function caller."); 1373 return DescriptorMapUpdateResult::Fail(); 1374 } 1375 arguments = get_class_info_function->GetArgumentValues(); 1376 } 1377 1378 DiagnosticManager diagnostics; 1379 1380 const uint32_t class_info_byte_size = addr_size + 4; 1381 const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; 1382 lldb::addr_t class_infos_addr = process->AllocateMemory( 1383 class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err); 1384 1385 if (class_infos_addr == LLDB_INVALID_ADDRESS) { 1386 LLDB_LOGF(log, 1387 "unable to allocate %" PRIu32 1388 " bytes in process for shared cache read", 1389 class_infos_byte_size); 1390 return DescriptorMapUpdateResult::Fail(); 1391 } 1392 1393 std::lock_guard<std::mutex> guard(m_get_class_info_args_mutex); 1394 1395 // Fill in our function argument values 1396 arguments.GetValueAtIndex(0)->GetScalar() = hash_table.GetTableLoadAddress(); 1397 arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr; 1398 arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size; 1399 1400 // Only dump the runtime classes from the expression evaluation if the log is 1401 // verbose: 1402 Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES); 1403 bool dump_log = type_log && type_log->GetVerbose(); 1404 1405 arguments.GetValueAtIndex(3)->GetScalar() = dump_log ? 1 : 0; 1406 1407 bool success = false; 1408 1409 diagnostics.Clear(); 1410 1411 // Write our function arguments into the process so we can run our function 1412 if (get_class_info_function->WriteFunctionArguments( 1413 exe_ctx, m_get_class_info_args, arguments, diagnostics)) { 1414 EvaluateExpressionOptions options; 1415 options.SetUnwindOnError(true); 1416 options.SetTryAllThreads(false); 1417 options.SetStopOthers(true); 1418 options.SetIgnoreBreakpoints(true); 1419 options.SetTimeout(process->GetUtilityExpressionTimeout()); 1420 options.SetIsForUtilityExpr(true); 1421 1422 Value return_value; 1423 return_value.SetValueType(Value::eValueTypeScalar); 1424 return_value.SetCompilerType(clang_uint32_t_type); 1425 return_value.GetScalar() = 0; 1426 1427 diagnostics.Clear(); 1428 1429 // Run the function 1430 ExpressionResults results = get_class_info_function->ExecuteFunction( 1431 exe_ctx, &m_get_class_info_args, options, diagnostics, return_value); 1432 1433 if (results == eExpressionCompleted) { 1434 // The result is the number of ClassInfo structures that were filled in 1435 num_class_infos = return_value.GetScalar().ULong(); 1436 LLDB_LOGF(log, "Discovered %u ObjC classes\n", num_class_infos); 1437 if (num_class_infos > 0) { 1438 // Read the ClassInfo structures 1439 DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0); 1440 if (process->ReadMemory(class_infos_addr, buffer.GetBytes(), 1441 buffer.GetByteSize(), 1442 err) == buffer.GetByteSize()) { 1443 DataExtractor class_infos_data(buffer.GetBytes(), 1444 buffer.GetByteSize(), 1445 process->GetByteOrder(), addr_size); 1446 ParseClassInfoArray(class_infos_data, num_class_infos); 1447 } 1448 } 1449 success = true; 1450 } else { 1451 if (log) { 1452 LLDB_LOGF(log, "Error evaluating our find class name function."); 1453 diagnostics.Dump(log); 1454 } 1455 } 1456 } else { 1457 if (log) { 1458 LLDB_LOGF(log, "Error writing function arguments."); 1459 diagnostics.Dump(log); 1460 } 1461 } 1462 1463 // Deallocate the memory we allocated for the ClassInfo array 1464 process->DeallocateMemory(class_infos_addr); 1465 1466 return DescriptorMapUpdateResult(success, num_class_infos); 1467 } 1468 1469 uint32_t AppleObjCRuntimeV2::ParseClassInfoArray(const DataExtractor &data, 1470 uint32_t num_class_infos) { 1471 // Parses an array of "num_class_infos" packed ClassInfo structures: 1472 // 1473 // struct ClassInfo 1474 // { 1475 // Class isa; 1476 // uint32_t hash; 1477 // } __attribute__((__packed__)); 1478 1479 Log *log(GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); 1480 bool should_log = log && log->GetVerbose(); 1481 1482 uint32_t num_parsed = 0; 1483 1484 // Iterate through all ClassInfo structures 1485 lldb::offset_t offset = 0; 1486 for (uint32_t i = 0; i < num_class_infos; ++i) { 1487 ObjCISA isa = data.GetAddress(&offset); 1488 1489 if (isa == 0) { 1490 if (should_log) 1491 LLDB_LOGF( 1492 log, "AppleObjCRuntimeV2 found NULL isa, ignoring this class info"); 1493 continue; 1494 } 1495 // Check if we already know about this ISA, if we do, the info will never 1496 // change, so we can just skip it. 1497 if (ISAIsCached(isa)) { 1498 if (should_log) 1499 LLDB_LOGF(log, 1500 "AppleObjCRuntimeV2 found cached isa=0x%" PRIx64 1501 ", ignoring this class info", 1502 isa); 1503 offset += 4; 1504 } else { 1505 // Read the 32 bit hash for the class name 1506 const uint32_t name_hash = data.GetU32(&offset); 1507 ClassDescriptorSP descriptor_sp( 1508 new ClassDescriptorV2(*this, isa, nullptr)); 1509 1510 // The code in g_get_shared_cache_class_info_body sets the value of the hash 1511 // to 0 to signal a demangled symbol. We use class_getName() in that code to 1512 // find the class name, but this returns a demangled name for Swift symbols. 1513 // For those symbols, recompute the hash here by reading their name from the 1514 // runtime. 1515 if (name_hash) 1516 AddClass(isa, descriptor_sp, name_hash); 1517 else 1518 AddClass(isa, descriptor_sp, descriptor_sp->GetClassName().AsCString(nullptr)); 1519 num_parsed++; 1520 if (should_log) 1521 LLDB_LOGF(log, 1522 "AppleObjCRuntimeV2 added isa=0x%" PRIx64 1523 ", hash=0x%8.8x, name=%s", 1524 isa, name_hash, 1525 descriptor_sp->GetClassName().AsCString("<unknown>")); 1526 } 1527 } 1528 if (should_log) 1529 LLDB_LOGF(log, "AppleObjCRuntimeV2 parsed %" PRIu32 " class infos", 1530 num_parsed); 1531 return num_parsed; 1532 } 1533 1534 AppleObjCRuntimeV2::DescriptorMapUpdateResult 1535 AppleObjCRuntimeV2::UpdateISAToDescriptorMapSharedCache() { 1536 Process *process = GetProcess(); 1537 1538 if (process == nullptr) 1539 return DescriptorMapUpdateResult::Fail(); 1540 1541 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES)); 1542 1543 ExecutionContext exe_ctx; 1544 1545 ThreadSP thread_sp = process->GetThreadList().GetExpressionExecutionThread(); 1546 1547 if (!thread_sp) 1548 return DescriptorMapUpdateResult::Fail(); 1549 1550 thread_sp->CalculateExecutionContext(exe_ctx); 1551 TypeSystemClang *ast = 1552 ScratchTypeSystemClang::GetForTarget(process->GetTarget()); 1553 1554 if (!ast) 1555 return DescriptorMapUpdateResult::Fail(); 1556 1557 Address function_address; 1558 1559 const uint32_t addr_size = process->GetAddressByteSize(); 1560 1561 Status err; 1562 1563 uint32_t num_class_infos = 0; 1564 1565 const lldb::addr_t objc_opt_ptr = GetSharedCacheReadOnlyAddress(); 1566 1567 if (objc_opt_ptr == LLDB_INVALID_ADDRESS) 1568 return DescriptorMapUpdateResult::Fail(); 1569 1570 const uint32_t num_classes = 128 * 1024; 1571 1572 // Make some types for our arguments 1573 CompilerType clang_uint32_t_type = 1574 ast->GetBuiltinTypeForEncodingAndBitSize(eEncodingUint, 32); 1575 CompilerType clang_void_pointer_type = 1576 ast->GetBasicType(eBasicTypeVoid).GetPointerType(); 1577 1578 ValueList arguments; 1579 FunctionCaller *get_shared_cache_class_info_function = nullptr; 1580 1581 if (!m_get_shared_cache_class_info_code) { 1582 Status error; 1583 1584 // If the inferior objc.dylib has the class_getNameRaw function, 1585 // use that in our jitted expression. Else fall back to the old 1586 // class_getName. 1587 static ConstString g_class_getName_symbol_name("class_getName"); 1588 static ConstString g_class_getNameRaw_symbol_name("objc_debug_class_getNameRaw"); 1589 ConstString class_name_getter_function_name = g_class_getName_symbol_name; 1590 1591 ObjCLanguageRuntime *objc_runtime = ObjCLanguageRuntime::Get(*process); 1592 if (objc_runtime) { 1593 for (lldb::ModuleSP mod_sp : process->GetTarget().GetImages().Modules()) { 1594 if (objc_runtime->IsModuleObjCLibrary(mod_sp)) { 1595 const Symbol *symbol = 1596 mod_sp->FindFirstSymbolWithNameAndType(g_class_getNameRaw_symbol_name, 1597 lldb::eSymbolTypeCode); 1598 if (symbol && 1599 (symbol->ValueIsAddress() || symbol->GetAddressRef().IsValid())) { 1600 class_name_getter_function_name = g_class_getNameRaw_symbol_name; 1601 } 1602 } 1603 } 1604 } 1605 1606 // Substitute in the correct class_getName / class_getNameRaw function name, 1607 // concatenate the two parts of our expression text. The format string 1608 // has two %s's, so provide the name twice. 1609 std::string shared_class_expression; 1610 llvm::raw_string_ostream(shared_class_expression) << llvm::format( 1611 g_shared_cache_class_name_funcptr, 1612 class_name_getter_function_name.AsCString(), 1613 class_name_getter_function_name.AsCString()); 1614 1615 shared_class_expression += g_get_shared_cache_class_info_body; 1616 1617 auto utility_fn_or_error = exe_ctx.GetTargetRef().CreateUtilityFunction( 1618 std::move(shared_class_expression), g_get_shared_cache_class_info_name, 1619 eLanguageTypeC, exe_ctx); 1620 if (!utility_fn_or_error) { 1621 LLDB_LOG_ERROR( 1622 log, utility_fn_or_error.takeError(), 1623 "Failed to get utility function for implementation lookup: {0}"); 1624 return DescriptorMapUpdateResult::Fail(); 1625 } 1626 1627 m_get_shared_cache_class_info_code = std::move(*utility_fn_or_error); 1628 1629 // Next make the function caller for our implementation utility function. 1630 Value value; 1631 value.SetValueType(Value::eValueTypeScalar); 1632 value.SetCompilerType(clang_void_pointer_type); 1633 arguments.PushValue(value); 1634 arguments.PushValue(value); 1635 1636 value.SetValueType(Value::eValueTypeScalar); 1637 value.SetCompilerType(clang_uint32_t_type); 1638 arguments.PushValue(value); 1639 arguments.PushValue(value); 1640 1641 get_shared_cache_class_info_function = 1642 m_get_shared_cache_class_info_code->MakeFunctionCaller( 1643 clang_uint32_t_type, arguments, thread_sp, error); 1644 1645 if (get_shared_cache_class_info_function == nullptr) 1646 return DescriptorMapUpdateResult::Fail(); 1647 1648 } else { 1649 get_shared_cache_class_info_function = 1650 m_get_shared_cache_class_info_code->GetFunctionCaller(); 1651 if (get_shared_cache_class_info_function == nullptr) 1652 return DescriptorMapUpdateResult::Fail(); 1653 arguments = get_shared_cache_class_info_function->GetArgumentValues(); 1654 } 1655 1656 DiagnosticManager diagnostics; 1657 1658 const uint32_t class_info_byte_size = addr_size + 4; 1659 const uint32_t class_infos_byte_size = num_classes * class_info_byte_size; 1660 lldb::addr_t class_infos_addr = process->AllocateMemory( 1661 class_infos_byte_size, ePermissionsReadable | ePermissionsWritable, err); 1662 1663 if (class_infos_addr == LLDB_INVALID_ADDRESS) { 1664 LLDB_LOGF(log, 1665 "unable to allocate %" PRIu32 1666 " bytes in process for shared cache read", 1667 class_infos_byte_size); 1668 return DescriptorMapUpdateResult::Fail(); 1669 } 1670 1671 std::lock_guard<std::mutex> guard(m_get_shared_cache_class_info_args_mutex); 1672 1673 // Fill in our function argument values 1674 arguments.GetValueAtIndex(0)->GetScalar() = objc_opt_ptr; 1675 arguments.GetValueAtIndex(1)->GetScalar() = class_infos_addr; 1676 arguments.GetValueAtIndex(2)->GetScalar() = class_infos_byte_size; 1677 // Only dump the runtime classes from the expression evaluation if the log is 1678 // verbose: 1679 Log *type_log = GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES); 1680 bool dump_log = type_log && type_log->GetVerbose(); 1681 1682 arguments.GetValueAtIndex(3)->GetScalar() = dump_log ? 1 : 0; 1683 1684 bool success = false; 1685 1686 diagnostics.Clear(); 1687 1688 // Write our function arguments into the process so we can run our function 1689 if (get_shared_cache_class_info_function->WriteFunctionArguments( 1690 exe_ctx, m_get_shared_cache_class_info_args, arguments, 1691 diagnostics)) { 1692 EvaluateExpressionOptions options; 1693 options.SetUnwindOnError(true); 1694 options.SetTryAllThreads(false); 1695 options.SetStopOthers(true); 1696 options.SetIgnoreBreakpoints(true); 1697 options.SetTimeout(process->GetUtilityExpressionTimeout()); 1698 options.SetIsForUtilityExpr(true); 1699 1700 Value return_value; 1701 return_value.SetValueType(Value::eValueTypeScalar); 1702 return_value.SetCompilerType(clang_uint32_t_type); 1703 return_value.GetScalar() = 0; 1704 1705 diagnostics.Clear(); 1706 1707 // Run the function 1708 ExpressionResults results = 1709 get_shared_cache_class_info_function->ExecuteFunction( 1710 exe_ctx, &m_get_shared_cache_class_info_args, options, diagnostics, 1711 return_value); 1712 1713 if (results == eExpressionCompleted) { 1714 // The result is the number of ClassInfo structures that were filled in 1715 num_class_infos = return_value.GetScalar().ULong(); 1716 LLDB_LOGF(log, "Discovered %u ObjC classes in shared cache\n", 1717 num_class_infos); 1718 assert(num_class_infos <= num_classes); 1719 if (num_class_infos > 0) { 1720 if (num_class_infos > num_classes) { 1721 num_class_infos = num_classes; 1722 1723 success = false; 1724 } else { 1725 success = true; 1726 } 1727 1728 // Read the ClassInfo structures 1729 DataBufferHeap buffer(num_class_infos * class_info_byte_size, 0); 1730 if (process->ReadMemory(class_infos_addr, buffer.GetBytes(), 1731 buffer.GetByteSize(), 1732 err) == buffer.GetByteSize()) { 1733 DataExtractor class_infos_data(buffer.GetBytes(), 1734 buffer.GetByteSize(), 1735 process->GetByteOrder(), addr_size); 1736 1737 ParseClassInfoArray(class_infos_data, num_class_infos); 1738 } 1739 } else { 1740 success = true; 1741 } 1742 } else { 1743 if (log) { 1744 LLDB_LOGF(log, "Error evaluating our find class name function."); 1745 diagnostics.Dump(log); 1746 } 1747 } 1748 } else { 1749 if (log) { 1750 LLDB_LOGF(log, "Error writing function arguments."); 1751 diagnostics.Dump(log); 1752 } 1753 } 1754 1755 // Deallocate the memory we allocated for the ClassInfo array 1756 process->DeallocateMemory(class_infos_addr); 1757 1758 return DescriptorMapUpdateResult(success, num_class_infos); 1759 } 1760 1761 bool AppleObjCRuntimeV2::UpdateISAToDescriptorMapFromMemory( 1762 RemoteNXMapTable &hash_table) { 1763 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES)); 1764 1765 Process *process = GetProcess(); 1766 1767 if (process == nullptr) 1768 return false; 1769 1770 uint32_t num_map_table_isas = 0; 1771 1772 ModuleSP objc_module_sp(GetObjCModule()); 1773 1774 if (objc_module_sp) { 1775 for (RemoteNXMapTable::element elt : hash_table) { 1776 ++num_map_table_isas; 1777 1778 if (ISAIsCached(elt.second)) 1779 continue; 1780 1781 ClassDescriptorSP descriptor_sp = ClassDescriptorSP( 1782 new ClassDescriptorV2(*this, elt.second, elt.first.AsCString())); 1783 1784 if (log && log->GetVerbose()) 1785 LLDB_LOGF(log, 1786 "AppleObjCRuntimeV2 added (ObjCISA)0x%" PRIx64 1787 " (%s) from dynamic table to isa->descriptor cache", 1788 elt.second, elt.first.AsCString()); 1789 1790 AddClass(elt.second, descriptor_sp, elt.first.AsCString()); 1791 } 1792 } 1793 1794 return num_map_table_isas > 0; 1795 } 1796 1797 lldb::addr_t AppleObjCRuntimeV2::GetSharedCacheReadOnlyAddress() { 1798 Process *process = GetProcess(); 1799 1800 if (process) { 1801 ModuleSP objc_module_sp(GetObjCModule()); 1802 1803 if (objc_module_sp) { 1804 ObjectFile *objc_object = objc_module_sp->GetObjectFile(); 1805 1806 if (objc_object) { 1807 SectionList *section_list = objc_module_sp->GetSectionList(); 1808 1809 if (section_list) { 1810 SectionSP text_segment_sp( 1811 section_list->FindSectionByName(ConstString("__TEXT"))); 1812 1813 if (text_segment_sp) { 1814 SectionSP objc_opt_section_sp( 1815 text_segment_sp->GetChildren().FindSectionByName( 1816 ConstString("__objc_opt_ro"))); 1817 1818 if (objc_opt_section_sp) { 1819 return objc_opt_section_sp->GetLoadBaseAddress( 1820 &process->GetTarget()); 1821 } 1822 } 1823 } 1824 } 1825 } 1826 } 1827 return LLDB_INVALID_ADDRESS; 1828 } 1829 1830 void AppleObjCRuntimeV2::UpdateISAToDescriptorMapIfNeeded() { 1831 LLDB_SCOPED_TIMER(); 1832 1833 Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS | LIBLLDB_LOG_TYPES)); 1834 1835 // Else we need to check with our process to see when the map was updated. 1836 Process *process = GetProcess(); 1837 1838 if (process) { 1839 RemoteNXMapTable hash_table; 1840 1841 // Update the process stop ID that indicates the last time we updated the 1842 // map, whether it was successful or not. 1843 m_isa_to_descriptor_stop_id = process->GetStopID(); 1844 1845 if (!m_hash_signature.NeedsUpdate(process, this, hash_table)) 1846 return; 1847 1848 m_hash_signature.UpdateSignature(hash_table); 1849 1850 // Grab the dynamically loaded objc classes from the hash table in memory 1851 DescriptorMapUpdateResult dynamic_update_result = 1852 UpdateISAToDescriptorMapDynamic(hash_table); 1853 1854 // Now get the objc classes that are baked into the Objective-C runtime in 1855 // the shared cache, but only once per process as this data never changes 1856 if (!m_loaded_objc_opt) { 1857 // it is legitimately possible for the shared cache to be empty - in that 1858 // case, the dynamic hash table will contain all the class information we 1859 // need; the situation we're trying to detect is one where we aren't 1860 // seeing class information from the runtime - in order to detect that 1861 // vs. just the shared cache being empty or sparsely populated, we set an 1862 // arbitrary (very low) threshold for the number of classes that we want 1863 // to see in a "good" scenario - anything below that is suspicious 1864 // (Foundation alone has thousands of classes) 1865 const uint32_t num_classes_to_warn_at = 500; 1866 1867 DescriptorMapUpdateResult shared_cache_update_result = 1868 UpdateISAToDescriptorMapSharedCache(); 1869 1870 LLDB_LOGF(log, 1871 "attempted to read objc class data - results: " 1872 "[dynamic_update]: ran: %s, count: %" PRIu32 1873 " [shared_cache_update]: ran: %s, count: %" PRIu32, 1874 dynamic_update_result.m_update_ran ? "yes" : "no", 1875 dynamic_update_result.m_num_found, 1876 shared_cache_update_result.m_update_ran ? "yes" : "no", 1877 shared_cache_update_result.m_num_found); 1878 1879 // warn if: 1880 // - we could not run either expression 1881 // - we found fewer than num_classes_to_warn_at classes total 1882 if ((!shared_cache_update_result.m_update_ran) || 1883 (!dynamic_update_result.m_update_ran)) 1884 WarnIfNoClassesCached( 1885 SharedCacheWarningReason::eExpressionExecutionFailure); 1886 else if (dynamic_update_result.m_num_found + 1887 shared_cache_update_result.m_num_found < 1888 num_classes_to_warn_at) 1889 WarnIfNoClassesCached(SharedCacheWarningReason::eNotEnoughClassesRead); 1890 else 1891 m_loaded_objc_opt = true; 1892 } 1893 } else { 1894 m_isa_to_descriptor_stop_id = UINT32_MAX; 1895 } 1896 } 1897 1898 static bool DoesProcessHaveSharedCache(Process &process) { 1899 PlatformSP platform_sp = process.GetTarget().GetPlatform(); 1900 if (!platform_sp) 1901 return true; // this should not happen 1902 1903 ConstString platform_plugin_name = platform_sp->GetPluginName(); 1904 if (platform_plugin_name) { 1905 llvm::StringRef platform_plugin_name_sr = 1906 platform_plugin_name.GetStringRef(); 1907 if (platform_plugin_name_sr.endswith("-simulator")) 1908 return false; 1909 } 1910 1911 return true; 1912 } 1913 1914 void AppleObjCRuntimeV2::WarnIfNoClassesCached( 1915 SharedCacheWarningReason reason) { 1916 if (m_noclasses_warning_emitted) 1917 return; 1918 1919 if (GetProcess() && !DoesProcessHaveSharedCache(*GetProcess())) { 1920 // Simulators do not have the objc_opt_ro class table so don't actually 1921 // complain to the user 1922 m_noclasses_warning_emitted = true; 1923 return; 1924 } 1925 1926 Debugger &debugger(GetProcess()->GetTarget().GetDebugger()); 1927 if (auto stream = debugger.GetAsyncOutputStream()) { 1928 switch (reason) { 1929 case SharedCacheWarningReason::eNotEnoughClassesRead: 1930 stream->PutCString("warning: could not find Objective-C class data in " 1931 "the process. This may reduce the quality of type " 1932 "information available.\n"); 1933 m_noclasses_warning_emitted = true; 1934 break; 1935 case SharedCacheWarningReason::eExpressionExecutionFailure: 1936 stream->PutCString("warning: could not execute support code to read " 1937 "Objective-C class data in the process. This may " 1938 "reduce the quality of type information available.\n"); 1939 m_noclasses_warning_emitted = true; 1940 break; 1941 } 1942 } 1943 } 1944 1945 DeclVendor *AppleObjCRuntimeV2::GetDeclVendor() { 1946 if (!m_decl_vendor_up) 1947 m_decl_vendor_up = std::make_unique<AppleObjCDeclVendor>(*this); 1948 1949 return m_decl_vendor_up.get(); 1950 } 1951 1952 lldb::addr_t AppleObjCRuntimeV2::LookupRuntimeSymbol(ConstString name) { 1953 lldb::addr_t ret = LLDB_INVALID_ADDRESS; 1954 1955 const char *name_cstr = name.AsCString(); 1956 1957 if (name_cstr) { 1958 llvm::StringRef name_strref(name_cstr); 1959 1960 llvm::StringRef ivar_prefix("OBJC_IVAR_$_"); 1961 llvm::StringRef class_prefix("OBJC_CLASS_$_"); 1962 1963 if (name_strref.startswith(ivar_prefix)) { 1964 llvm::StringRef ivar_skipped_prefix = 1965 name_strref.substr(ivar_prefix.size()); 1966 std::pair<llvm::StringRef, llvm::StringRef> class_and_ivar = 1967 ivar_skipped_prefix.split('.'); 1968 1969 if (class_and_ivar.first.size() && class_and_ivar.second.size()) { 1970 const ConstString class_name_cs(class_and_ivar.first); 1971 ClassDescriptorSP descriptor = 1972 ObjCLanguageRuntime::GetClassDescriptorFromClassName(class_name_cs); 1973 1974 if (descriptor) { 1975 const ConstString ivar_name_cs(class_and_ivar.second); 1976 const char *ivar_name_cstr = ivar_name_cs.AsCString(); 1977 1978 auto ivar_func = [&ret, ivar_name_cstr]( 1979 const char *name, const char *type, lldb::addr_t offset_addr, 1980 uint64_t size) -> lldb::addr_t { 1981 if (!strcmp(name, ivar_name_cstr)) { 1982 ret = offset_addr; 1983 return true; 1984 } 1985 return false; 1986 }; 1987 1988 descriptor->Describe( 1989 std::function<void(ObjCISA)>(nullptr), 1990 std::function<bool(const char *, const char *)>(nullptr), 1991 std::function<bool(const char *, const char *)>(nullptr), 1992 ivar_func); 1993 } 1994 } 1995 } else if (name_strref.startswith(class_prefix)) { 1996 llvm::StringRef class_skipped_prefix = 1997 name_strref.substr(class_prefix.size()); 1998 const ConstString class_name_cs(class_skipped_prefix); 1999 ClassDescriptorSP descriptor = 2000 GetClassDescriptorFromClassName(class_name_cs); 2001 2002 if (descriptor) 2003 ret = descriptor->GetISA(); 2004 } 2005 } 2006 2007 return ret; 2008 } 2009 2010 AppleObjCRuntimeV2::NonPointerISACache * 2011 AppleObjCRuntimeV2::NonPointerISACache::CreateInstance( 2012 AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp) { 2013 Process *process(runtime.GetProcess()); 2014 2015 Status error; 2016 2017 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); 2018 2019 auto objc_debug_isa_magic_mask = ExtractRuntimeGlobalSymbol( 2020 process, ConstString("objc_debug_isa_magic_mask"), objc_module_sp, error); 2021 if (error.Fail()) 2022 return nullptr; 2023 2024 auto objc_debug_isa_magic_value = ExtractRuntimeGlobalSymbol( 2025 process, ConstString("objc_debug_isa_magic_value"), objc_module_sp, 2026 error); 2027 if (error.Fail()) 2028 return nullptr; 2029 2030 auto objc_debug_isa_class_mask = ExtractRuntimeGlobalSymbol( 2031 process, ConstString("objc_debug_isa_class_mask"), objc_module_sp, error); 2032 if (error.Fail()) 2033 return nullptr; 2034 2035 if (log) 2036 log->PutCString("AOCRT::NPI: Found all the non-indexed ISA masks"); 2037 2038 bool foundError = false; 2039 auto objc_debug_indexed_isa_magic_mask = ExtractRuntimeGlobalSymbol( 2040 process, ConstString("objc_debug_indexed_isa_magic_mask"), objc_module_sp, 2041 error); 2042 foundError |= error.Fail(); 2043 2044 auto objc_debug_indexed_isa_magic_value = ExtractRuntimeGlobalSymbol( 2045 process, ConstString("objc_debug_indexed_isa_magic_value"), 2046 objc_module_sp, error); 2047 foundError |= error.Fail(); 2048 2049 auto objc_debug_indexed_isa_index_mask = ExtractRuntimeGlobalSymbol( 2050 process, ConstString("objc_debug_indexed_isa_index_mask"), objc_module_sp, 2051 error); 2052 foundError |= error.Fail(); 2053 2054 auto objc_debug_indexed_isa_index_shift = ExtractRuntimeGlobalSymbol( 2055 process, ConstString("objc_debug_indexed_isa_index_shift"), 2056 objc_module_sp, error); 2057 foundError |= error.Fail(); 2058 2059 auto objc_indexed_classes = 2060 ExtractRuntimeGlobalSymbol(process, ConstString("objc_indexed_classes"), 2061 objc_module_sp, error, false); 2062 foundError |= error.Fail(); 2063 2064 if (log) 2065 log->PutCString("AOCRT::NPI: Found all the indexed ISA masks"); 2066 2067 // we might want to have some rules to outlaw these other values (e.g if the 2068 // mask is zero but the value is non-zero, ...) 2069 2070 return new NonPointerISACache( 2071 runtime, objc_module_sp, objc_debug_isa_class_mask, 2072 objc_debug_isa_magic_mask, objc_debug_isa_magic_value, 2073 objc_debug_indexed_isa_magic_mask, objc_debug_indexed_isa_magic_value, 2074 objc_debug_indexed_isa_index_mask, objc_debug_indexed_isa_index_shift, 2075 foundError ? 0 : objc_indexed_classes); 2076 } 2077 2078 AppleObjCRuntimeV2::TaggedPointerVendorV2 * 2079 AppleObjCRuntimeV2::TaggedPointerVendorV2::CreateInstance( 2080 AppleObjCRuntimeV2 &runtime, const lldb::ModuleSP &objc_module_sp) { 2081 Process *process(runtime.GetProcess()); 2082 2083 Status error; 2084 2085 auto objc_debug_taggedpointer_mask = ExtractRuntimeGlobalSymbol( 2086 process, ConstString("objc_debug_taggedpointer_mask"), objc_module_sp, 2087 error); 2088 if (error.Fail()) 2089 return new TaggedPointerVendorLegacy(runtime); 2090 2091 auto objc_debug_taggedpointer_slot_shift = ExtractRuntimeGlobalSymbol( 2092 process, ConstString("objc_debug_taggedpointer_slot_shift"), 2093 objc_module_sp, error, true, 4); 2094 if (error.Fail()) 2095 return new TaggedPointerVendorLegacy(runtime); 2096 2097 auto objc_debug_taggedpointer_slot_mask = ExtractRuntimeGlobalSymbol( 2098 process, ConstString("objc_debug_taggedpointer_slot_mask"), 2099 objc_module_sp, error, true, 4); 2100 if (error.Fail()) 2101 return new TaggedPointerVendorLegacy(runtime); 2102 2103 auto objc_debug_taggedpointer_payload_lshift = ExtractRuntimeGlobalSymbol( 2104 process, ConstString("objc_debug_taggedpointer_payload_lshift"), 2105 objc_module_sp, error, true, 4); 2106 if (error.Fail()) 2107 return new TaggedPointerVendorLegacy(runtime); 2108 2109 auto objc_debug_taggedpointer_payload_rshift = ExtractRuntimeGlobalSymbol( 2110 process, ConstString("objc_debug_taggedpointer_payload_rshift"), 2111 objc_module_sp, error, true, 4); 2112 if (error.Fail()) 2113 return new TaggedPointerVendorLegacy(runtime); 2114 2115 auto objc_debug_taggedpointer_classes = ExtractRuntimeGlobalSymbol( 2116 process, ConstString("objc_debug_taggedpointer_classes"), objc_module_sp, 2117 error, false); 2118 if (error.Fail()) 2119 return new TaggedPointerVendorLegacy(runtime); 2120 2121 // try to detect the "extended tagged pointer" variables - if any are 2122 // missing, use the non-extended vendor 2123 do { 2124 auto objc_debug_taggedpointer_ext_mask = ExtractRuntimeGlobalSymbol( 2125 process, ConstString("objc_debug_taggedpointer_ext_mask"), 2126 objc_module_sp, error); 2127 if (error.Fail()) 2128 break; 2129 2130 auto objc_debug_taggedpointer_ext_slot_shift = ExtractRuntimeGlobalSymbol( 2131 process, ConstString("objc_debug_taggedpointer_ext_slot_shift"), 2132 objc_module_sp, error, true, 4); 2133 if (error.Fail()) 2134 break; 2135 2136 auto objc_debug_taggedpointer_ext_slot_mask = ExtractRuntimeGlobalSymbol( 2137 process, ConstString("objc_debug_taggedpointer_ext_slot_mask"), 2138 objc_module_sp, error, true, 4); 2139 if (error.Fail()) 2140 break; 2141 2142 auto objc_debug_taggedpointer_ext_classes = ExtractRuntimeGlobalSymbol( 2143 process, ConstString("objc_debug_taggedpointer_ext_classes"), 2144 objc_module_sp, error, false); 2145 if (error.Fail()) 2146 break; 2147 2148 auto objc_debug_taggedpointer_ext_payload_lshift = 2149 ExtractRuntimeGlobalSymbol( 2150 process, ConstString("objc_debug_taggedpointer_ext_payload_lshift"), 2151 objc_module_sp, error, true, 4); 2152 if (error.Fail()) 2153 break; 2154 2155 auto objc_debug_taggedpointer_ext_payload_rshift = 2156 ExtractRuntimeGlobalSymbol( 2157 process, ConstString("objc_debug_taggedpointer_ext_payload_rshift"), 2158 objc_module_sp, error, true, 4); 2159 if (error.Fail()) 2160 break; 2161 2162 return new TaggedPointerVendorExtended( 2163 runtime, objc_debug_taggedpointer_mask, 2164 objc_debug_taggedpointer_ext_mask, objc_debug_taggedpointer_slot_shift, 2165 objc_debug_taggedpointer_ext_slot_shift, 2166 objc_debug_taggedpointer_slot_mask, 2167 objc_debug_taggedpointer_ext_slot_mask, 2168 objc_debug_taggedpointer_payload_lshift, 2169 objc_debug_taggedpointer_payload_rshift, 2170 objc_debug_taggedpointer_ext_payload_lshift, 2171 objc_debug_taggedpointer_ext_payload_rshift, 2172 objc_debug_taggedpointer_classes, objc_debug_taggedpointer_ext_classes); 2173 } while (false); 2174 2175 // we might want to have some rules to outlaw these values (e.g if the 2176 // table's address is zero) 2177 2178 return new TaggedPointerVendorRuntimeAssisted( 2179 runtime, objc_debug_taggedpointer_mask, 2180 objc_debug_taggedpointer_slot_shift, objc_debug_taggedpointer_slot_mask, 2181 objc_debug_taggedpointer_payload_lshift, 2182 objc_debug_taggedpointer_payload_rshift, 2183 objc_debug_taggedpointer_classes); 2184 } 2185 2186 bool AppleObjCRuntimeV2::TaggedPointerVendorLegacy::IsPossibleTaggedPointer( 2187 lldb::addr_t ptr) { 2188 return (ptr & 1); 2189 } 2190 2191 ObjCLanguageRuntime::ClassDescriptorSP 2192 AppleObjCRuntimeV2::TaggedPointerVendorLegacy::GetClassDescriptor( 2193 lldb::addr_t ptr) { 2194 if (!IsPossibleTaggedPointer(ptr)) 2195 return ObjCLanguageRuntime::ClassDescriptorSP(); 2196 2197 uint32_t foundation_version = m_runtime.GetFoundationVersion(); 2198 2199 if (foundation_version == LLDB_INVALID_MODULE_VERSION) 2200 return ObjCLanguageRuntime::ClassDescriptorSP(); 2201 2202 uint64_t class_bits = (ptr & 0xE) >> 1; 2203 ConstString name; 2204 2205 static ConstString g_NSAtom("NSAtom"); 2206 static ConstString g_NSNumber("NSNumber"); 2207 static ConstString g_NSDateTS("NSDateTS"); 2208 static ConstString g_NSManagedObject("NSManagedObject"); 2209 static ConstString g_NSDate("NSDate"); 2210 2211 if (foundation_version >= 900) { 2212 switch (class_bits) { 2213 case 0: 2214 name = g_NSAtom; 2215 break; 2216 case 3: 2217 name = g_NSNumber; 2218 break; 2219 case 4: 2220 name = g_NSDateTS; 2221 break; 2222 case 5: 2223 name = g_NSManagedObject; 2224 break; 2225 case 6: 2226 name = g_NSDate; 2227 break; 2228 default: 2229 return ObjCLanguageRuntime::ClassDescriptorSP(); 2230 } 2231 } else { 2232 switch (class_bits) { 2233 case 1: 2234 name = g_NSNumber; 2235 break; 2236 case 5: 2237 name = g_NSManagedObject; 2238 break; 2239 case 6: 2240 name = g_NSDate; 2241 break; 2242 case 7: 2243 name = g_NSDateTS; 2244 break; 2245 default: 2246 return ObjCLanguageRuntime::ClassDescriptorSP(); 2247 } 2248 } 2249 2250 lldb::addr_t unobfuscated = ptr ^ m_runtime.GetTaggedPointerObfuscator(); 2251 return ClassDescriptorSP(new ClassDescriptorV2Tagged(name, unobfuscated)); 2252 } 2253 2254 AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted:: 2255 TaggedPointerVendorRuntimeAssisted( 2256 AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask, 2257 uint32_t objc_debug_taggedpointer_slot_shift, 2258 uint32_t objc_debug_taggedpointer_slot_mask, 2259 uint32_t objc_debug_taggedpointer_payload_lshift, 2260 uint32_t objc_debug_taggedpointer_payload_rshift, 2261 lldb::addr_t objc_debug_taggedpointer_classes) 2262 : TaggedPointerVendorV2(runtime), m_cache(), 2263 m_objc_debug_taggedpointer_mask(objc_debug_taggedpointer_mask), 2264 m_objc_debug_taggedpointer_slot_shift( 2265 objc_debug_taggedpointer_slot_shift), 2266 m_objc_debug_taggedpointer_slot_mask(objc_debug_taggedpointer_slot_mask), 2267 m_objc_debug_taggedpointer_payload_lshift( 2268 objc_debug_taggedpointer_payload_lshift), 2269 m_objc_debug_taggedpointer_payload_rshift( 2270 objc_debug_taggedpointer_payload_rshift), 2271 m_objc_debug_taggedpointer_classes(objc_debug_taggedpointer_classes) {} 2272 2273 bool AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted:: 2274 IsPossibleTaggedPointer(lldb::addr_t ptr) { 2275 return (ptr & m_objc_debug_taggedpointer_mask) != 0; 2276 } 2277 2278 ObjCLanguageRuntime::ClassDescriptorSP 2279 AppleObjCRuntimeV2::TaggedPointerVendorRuntimeAssisted::GetClassDescriptor( 2280 lldb::addr_t ptr) { 2281 ClassDescriptorSP actual_class_descriptor_sp; 2282 uint64_t data_payload; 2283 uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator(); 2284 2285 if (!IsPossibleTaggedPointer(unobfuscated)) 2286 return ObjCLanguageRuntime::ClassDescriptorSP(); 2287 2288 uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_slot_shift) & 2289 m_objc_debug_taggedpointer_slot_mask; 2290 2291 CacheIterator iterator = m_cache.find(slot), end = m_cache.end(); 2292 if (iterator != end) { 2293 actual_class_descriptor_sp = iterator->second; 2294 } else { 2295 Process *process(m_runtime.GetProcess()); 2296 uintptr_t slot_ptr = slot * process->GetAddressByteSize() + 2297 m_objc_debug_taggedpointer_classes; 2298 Status error; 2299 uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error); 2300 if (error.Fail() || slot_data == 0 || 2301 slot_data == uintptr_t(LLDB_INVALID_ADDRESS)) 2302 return nullptr; 2303 actual_class_descriptor_sp = 2304 m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data); 2305 if (!actual_class_descriptor_sp) 2306 return ObjCLanguageRuntime::ClassDescriptorSP(); 2307 m_cache[slot] = actual_class_descriptor_sp; 2308 } 2309 2310 data_payload = 2311 (((uint64_t)unobfuscated << m_objc_debug_taggedpointer_payload_lshift) >> 2312 m_objc_debug_taggedpointer_payload_rshift); 2313 2314 return ClassDescriptorSP( 2315 new ClassDescriptorV2Tagged(actual_class_descriptor_sp, data_payload)); 2316 } 2317 2318 AppleObjCRuntimeV2::TaggedPointerVendorExtended::TaggedPointerVendorExtended( 2319 AppleObjCRuntimeV2 &runtime, uint64_t objc_debug_taggedpointer_mask, 2320 uint64_t objc_debug_taggedpointer_ext_mask, 2321 uint32_t objc_debug_taggedpointer_slot_shift, 2322 uint32_t objc_debug_taggedpointer_ext_slot_shift, 2323 uint32_t objc_debug_taggedpointer_slot_mask, 2324 uint32_t objc_debug_taggedpointer_ext_slot_mask, 2325 uint32_t objc_debug_taggedpointer_payload_lshift, 2326 uint32_t objc_debug_taggedpointer_payload_rshift, 2327 uint32_t objc_debug_taggedpointer_ext_payload_lshift, 2328 uint32_t objc_debug_taggedpointer_ext_payload_rshift, 2329 lldb::addr_t objc_debug_taggedpointer_classes, 2330 lldb::addr_t objc_debug_taggedpointer_ext_classes) 2331 : TaggedPointerVendorRuntimeAssisted( 2332 runtime, objc_debug_taggedpointer_mask, 2333 objc_debug_taggedpointer_slot_shift, 2334 objc_debug_taggedpointer_slot_mask, 2335 objc_debug_taggedpointer_payload_lshift, 2336 objc_debug_taggedpointer_payload_rshift, 2337 objc_debug_taggedpointer_classes), 2338 m_ext_cache(), 2339 m_objc_debug_taggedpointer_ext_mask(objc_debug_taggedpointer_ext_mask), 2340 m_objc_debug_taggedpointer_ext_slot_shift( 2341 objc_debug_taggedpointer_ext_slot_shift), 2342 m_objc_debug_taggedpointer_ext_slot_mask( 2343 objc_debug_taggedpointer_ext_slot_mask), 2344 m_objc_debug_taggedpointer_ext_payload_lshift( 2345 objc_debug_taggedpointer_ext_payload_lshift), 2346 m_objc_debug_taggedpointer_ext_payload_rshift( 2347 objc_debug_taggedpointer_ext_payload_rshift), 2348 m_objc_debug_taggedpointer_ext_classes( 2349 objc_debug_taggedpointer_ext_classes) {} 2350 2351 bool AppleObjCRuntimeV2::TaggedPointerVendorExtended:: 2352 IsPossibleExtendedTaggedPointer(lldb::addr_t ptr) { 2353 if (!IsPossibleTaggedPointer(ptr)) 2354 return false; 2355 2356 if (m_objc_debug_taggedpointer_ext_mask == 0) 2357 return false; 2358 2359 return ((ptr & m_objc_debug_taggedpointer_ext_mask) == 2360 m_objc_debug_taggedpointer_ext_mask); 2361 } 2362 2363 ObjCLanguageRuntime::ClassDescriptorSP 2364 AppleObjCRuntimeV2::TaggedPointerVendorExtended::GetClassDescriptor( 2365 lldb::addr_t ptr) { 2366 ClassDescriptorSP actual_class_descriptor_sp; 2367 uint64_t data_payload; 2368 uint64_t unobfuscated = (ptr) ^ m_runtime.GetTaggedPointerObfuscator(); 2369 2370 if (!IsPossibleTaggedPointer(unobfuscated)) 2371 return ObjCLanguageRuntime::ClassDescriptorSP(); 2372 2373 if (!IsPossibleExtendedTaggedPointer(unobfuscated)) 2374 return this->TaggedPointerVendorRuntimeAssisted::GetClassDescriptor(ptr); 2375 2376 uintptr_t slot = (ptr >> m_objc_debug_taggedpointer_ext_slot_shift) & 2377 m_objc_debug_taggedpointer_ext_slot_mask; 2378 2379 CacheIterator iterator = m_ext_cache.find(slot), end = m_ext_cache.end(); 2380 if (iterator != end) { 2381 actual_class_descriptor_sp = iterator->second; 2382 } else { 2383 Process *process(m_runtime.GetProcess()); 2384 uintptr_t slot_ptr = slot * process->GetAddressByteSize() + 2385 m_objc_debug_taggedpointer_ext_classes; 2386 Status error; 2387 uintptr_t slot_data = process->ReadPointerFromMemory(slot_ptr, error); 2388 if (error.Fail() || slot_data == 0 || 2389 slot_data == uintptr_t(LLDB_INVALID_ADDRESS)) 2390 return nullptr; 2391 actual_class_descriptor_sp = 2392 m_runtime.GetClassDescriptorFromISA((ObjCISA)slot_data); 2393 if (!actual_class_descriptor_sp) 2394 return ObjCLanguageRuntime::ClassDescriptorSP(); 2395 m_ext_cache[slot] = actual_class_descriptor_sp; 2396 } 2397 2398 data_payload = 2399 (((uint64_t)unobfuscated << m_objc_debug_taggedpointer_ext_payload_lshift) >> 2400 m_objc_debug_taggedpointer_ext_payload_rshift); 2401 2402 return ClassDescriptorSP( 2403 new ClassDescriptorV2Tagged(actual_class_descriptor_sp, data_payload)); 2404 } 2405 2406 AppleObjCRuntimeV2::NonPointerISACache::NonPointerISACache( 2407 AppleObjCRuntimeV2 &runtime, const ModuleSP &objc_module_sp, 2408 uint64_t objc_debug_isa_class_mask, uint64_t objc_debug_isa_magic_mask, 2409 uint64_t objc_debug_isa_magic_value, 2410 uint64_t objc_debug_indexed_isa_magic_mask, 2411 uint64_t objc_debug_indexed_isa_magic_value, 2412 uint64_t objc_debug_indexed_isa_index_mask, 2413 uint64_t objc_debug_indexed_isa_index_shift, 2414 lldb::addr_t objc_indexed_classes) 2415 : m_runtime(runtime), m_cache(), m_objc_module_wp(objc_module_sp), 2416 m_objc_debug_isa_class_mask(objc_debug_isa_class_mask), 2417 m_objc_debug_isa_magic_mask(objc_debug_isa_magic_mask), 2418 m_objc_debug_isa_magic_value(objc_debug_isa_magic_value), 2419 m_objc_debug_indexed_isa_magic_mask(objc_debug_indexed_isa_magic_mask), 2420 m_objc_debug_indexed_isa_magic_value(objc_debug_indexed_isa_magic_value), 2421 m_objc_debug_indexed_isa_index_mask(objc_debug_indexed_isa_index_mask), 2422 m_objc_debug_indexed_isa_index_shift(objc_debug_indexed_isa_index_shift), 2423 m_objc_indexed_classes(objc_indexed_classes), m_indexed_isa_cache() {} 2424 2425 ObjCLanguageRuntime::ClassDescriptorSP 2426 AppleObjCRuntimeV2::NonPointerISACache::GetClassDescriptor(ObjCISA isa) { 2427 ObjCISA real_isa = 0; 2428 if (!EvaluateNonPointerISA(isa, real_isa)) 2429 return ObjCLanguageRuntime::ClassDescriptorSP(); 2430 auto cache_iter = m_cache.find(real_isa); 2431 if (cache_iter != m_cache.end()) 2432 return cache_iter->second; 2433 auto descriptor_sp = 2434 m_runtime.ObjCLanguageRuntime::GetClassDescriptorFromISA(real_isa); 2435 if (descriptor_sp) // cache only positive matches since the table might grow 2436 m_cache[real_isa] = descriptor_sp; 2437 return descriptor_sp; 2438 } 2439 2440 bool AppleObjCRuntimeV2::NonPointerISACache::EvaluateNonPointerISA( 2441 ObjCISA isa, ObjCISA &ret_isa) { 2442 Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_TYPES)); 2443 2444 LLDB_LOGF(log, "AOCRT::NPI Evaluate(isa = 0x%" PRIx64 ")", (uint64_t)isa); 2445 2446 if ((isa & ~m_objc_debug_isa_class_mask) == 0) 2447 return false; 2448 2449 // If all of the indexed ISA variables are set, then its possible that this 2450 // ISA is indexed, and we should first try to get its value using the index. 2451 // Note, we check these variables first as the ObjC runtime will set at least 2452 // one of their values to 0 if they aren't needed. 2453 if (m_objc_debug_indexed_isa_magic_mask && 2454 m_objc_debug_indexed_isa_magic_value && 2455 m_objc_debug_indexed_isa_index_mask && 2456 m_objc_debug_indexed_isa_index_shift && m_objc_indexed_classes) { 2457 if ((isa & ~m_objc_debug_indexed_isa_index_mask) == 0) 2458 return false; 2459 2460 if ((isa & m_objc_debug_indexed_isa_magic_mask) == 2461 m_objc_debug_indexed_isa_magic_value) { 2462 // Magic bits are correct, so try extract the index. 2463 uintptr_t index = (isa & m_objc_debug_indexed_isa_index_mask) >> 2464 m_objc_debug_indexed_isa_index_shift; 2465 // If the index is out of bounds of the length of the array then check if 2466 // the array has been updated. If that is the case then we should try 2467 // read the count again, and update the cache if the count has been 2468 // updated. 2469 if (index > m_indexed_isa_cache.size()) { 2470 LLDB_LOGF(log, 2471 "AOCRT::NPI (index = %" PRIu64 2472 ") exceeds cache (size = %" PRIu64 ")", 2473 (uint64_t)index, (uint64_t)m_indexed_isa_cache.size()); 2474 2475 Process *process(m_runtime.GetProcess()); 2476 2477 ModuleSP objc_module_sp(m_objc_module_wp.lock()); 2478 if (!objc_module_sp) 2479 return false; 2480 2481 Status error; 2482 auto objc_indexed_classes_count = ExtractRuntimeGlobalSymbol( 2483 process, ConstString("objc_indexed_classes_count"), objc_module_sp, 2484 error); 2485 if (error.Fail()) 2486 return false; 2487 2488 LLDB_LOGF(log, "AOCRT::NPI (new class count = %" PRIu64 ")", 2489 (uint64_t)objc_indexed_classes_count); 2490 2491 if (objc_indexed_classes_count > m_indexed_isa_cache.size()) { 2492 // Read the class entries we don't have. We should just read all of 2493 // them instead of just the one we need as then we can cache those we 2494 // may need later. 2495 auto num_new_classes = 2496 objc_indexed_classes_count - m_indexed_isa_cache.size(); 2497 const uint32_t addr_size = process->GetAddressByteSize(); 2498 DataBufferHeap buffer(num_new_classes * addr_size, 0); 2499 2500 lldb::addr_t last_read_class = 2501 m_objc_indexed_classes + (m_indexed_isa_cache.size() * addr_size); 2502 size_t bytes_read = process->ReadMemory( 2503 last_read_class, buffer.GetBytes(), buffer.GetByteSize(), error); 2504 if (error.Fail() || bytes_read != buffer.GetByteSize()) 2505 return false; 2506 2507 LLDB_LOGF(log, "AOCRT::NPI (read new classes count = %" PRIu64 ")", 2508 (uint64_t)num_new_classes); 2509 2510 // Append the new entries to the existing cache. 2511 DataExtractor data(buffer.GetBytes(), buffer.GetByteSize(), 2512 process->GetByteOrder(), 2513 process->GetAddressByteSize()); 2514 2515 lldb::offset_t offset = 0; 2516 for (unsigned i = 0; i != num_new_classes; ++i) 2517 m_indexed_isa_cache.push_back(data.GetAddress(&offset)); 2518 } 2519 } 2520 2521 // If the index is still out of range then this isn't a pointer. 2522 if (index > m_indexed_isa_cache.size()) 2523 return false; 2524 2525 LLDB_LOGF(log, "AOCRT::NPI Evaluate(ret_isa = 0x%" PRIx64 ")", 2526 (uint64_t)m_indexed_isa_cache[index]); 2527 2528 ret_isa = m_indexed_isa_cache[index]; 2529 return (ret_isa != 0); // this is a pointer so 0 is not a valid value 2530 } 2531 2532 return false; 2533 } 2534 2535 // Definitely not an indexed ISA, so try to use a mask to extract the pointer 2536 // from the ISA. 2537 if ((isa & m_objc_debug_isa_magic_mask) == m_objc_debug_isa_magic_value) { 2538 ret_isa = isa & m_objc_debug_isa_class_mask; 2539 return (ret_isa != 0); // this is a pointer so 0 is not a valid value 2540 } 2541 return false; 2542 } 2543 2544 ObjCLanguageRuntime::EncodingToTypeSP AppleObjCRuntimeV2::GetEncodingToType() { 2545 if (!m_encoding_to_type_sp) 2546 m_encoding_to_type_sp = 2547 std::make_shared<AppleObjCTypeEncodingParser>(*this); 2548 return m_encoding_to_type_sp; 2549 } 2550 2551 lldb_private::AppleObjCRuntime::ObjCISA 2552 AppleObjCRuntimeV2::GetPointerISA(ObjCISA isa) { 2553 ObjCISA ret = isa; 2554 2555 if (m_non_pointer_isa_cache_up) 2556 m_non_pointer_isa_cache_up->EvaluateNonPointerISA(isa, ret); 2557 2558 return ret; 2559 } 2560 2561 bool AppleObjCRuntimeV2::GetCFBooleanValuesIfNeeded() { 2562 if (m_CFBoolean_values) 2563 return true; 2564 2565 static ConstString g_kCFBooleanFalse("__kCFBooleanFalse"); 2566 static ConstString g_kCFBooleanTrue("__kCFBooleanTrue"); 2567 2568 std::function<lldb::addr_t(ConstString)> get_symbol = 2569 [this](ConstString sym) -> lldb::addr_t { 2570 SymbolContextList sc_list; 2571 GetProcess()->GetTarget().GetImages().FindSymbolsWithNameAndType( 2572 sym, lldb::eSymbolTypeData, sc_list); 2573 if (sc_list.GetSize() == 1) { 2574 SymbolContext sc; 2575 sc_list.GetContextAtIndex(0, sc); 2576 if (sc.symbol) 2577 return sc.symbol->GetLoadAddress(&GetProcess()->GetTarget()); 2578 } 2579 2580 return LLDB_INVALID_ADDRESS; 2581 }; 2582 2583 lldb::addr_t false_addr = get_symbol(g_kCFBooleanFalse); 2584 lldb::addr_t true_addr = get_symbol(g_kCFBooleanTrue); 2585 2586 return (m_CFBoolean_values = {false_addr, true_addr}).operator bool(); 2587 } 2588 2589 void AppleObjCRuntimeV2::GetValuesForGlobalCFBooleans(lldb::addr_t &cf_true, 2590 lldb::addr_t &cf_false) { 2591 if (GetCFBooleanValuesIfNeeded()) { 2592 cf_true = m_CFBoolean_values->second; 2593 cf_false = m_CFBoolean_values->first; 2594 } else 2595 this->AppleObjCRuntime::GetValuesForGlobalCFBooleans(cf_true, cf_false); 2596 } 2597 2598 #pragma mark Frame recognizers 2599 2600 class ObjCExceptionRecognizedStackFrame : public RecognizedStackFrame { 2601 public: 2602 ObjCExceptionRecognizedStackFrame(StackFrameSP frame_sp) { 2603 ThreadSP thread_sp = frame_sp->GetThread(); 2604 ProcessSP process_sp = thread_sp->GetProcess(); 2605 2606 const lldb::ABISP &abi = process_sp->GetABI(); 2607 if (!abi) return; 2608 2609 TypeSystemClang *clang_ast_context = 2610 ScratchTypeSystemClang::GetForTarget(process_sp->GetTarget()); 2611 if (!clang_ast_context) 2612 return; 2613 CompilerType voidstar = 2614 clang_ast_context->GetBasicType(lldb::eBasicTypeVoid).GetPointerType(); 2615 2616 ValueList args; 2617 Value input_value; 2618 input_value.SetCompilerType(voidstar); 2619 args.PushValue(input_value); 2620 2621 if (!abi->GetArgumentValues(*thread_sp, args)) return; 2622 2623 addr_t exception_addr = args.GetValueAtIndex(0)->GetScalar().ULongLong(); 2624 2625 Value value(exception_addr); 2626 value.SetCompilerType(voidstar); 2627 exception = ValueObjectConstResult::Create(frame_sp.get(), value, 2628 ConstString("exception")); 2629 exception = ValueObjectRecognizerSynthesizedValue::Create( 2630 *exception, eValueTypeVariableArgument); 2631 exception = exception->GetDynamicValue(eDynamicDontRunTarget); 2632 2633 m_arguments = ValueObjectListSP(new ValueObjectList()); 2634 m_arguments->Append(exception); 2635 2636 m_stop_desc = "hit Objective-C exception"; 2637 } 2638 2639 ValueObjectSP exception; 2640 2641 lldb::ValueObjectSP GetExceptionObject() override { return exception; } 2642 }; 2643 2644 class ObjCExceptionThrowFrameRecognizer : public StackFrameRecognizer { 2645 lldb::RecognizedStackFrameSP 2646 RecognizeFrame(lldb::StackFrameSP frame) override { 2647 return lldb::RecognizedStackFrameSP( 2648 new ObjCExceptionRecognizedStackFrame(frame)); 2649 }; 2650 std::string GetName() override { 2651 return "ObjC Exception Throw StackFrame Recognizer"; 2652 } 2653 }; 2654 2655 static void RegisterObjCExceptionRecognizer(Process *process) { 2656 FileSpec module; 2657 ConstString function; 2658 std::tie(module, function) = AppleObjCRuntime::GetExceptionThrowLocation(); 2659 std::vector<ConstString> symbols = {function}; 2660 2661 process->GetTarget().GetFrameRecognizerManager().AddRecognizer( 2662 StackFrameRecognizerSP(new ObjCExceptionThrowFrameRecognizer()), 2663 module.GetFilename(), symbols, 2664 /*first_instruction_only*/ true); 2665 } 2666