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