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