| 536 | } |
| 537 | |
| 538 | void ObjCProcessor::LoadCategories(ObjCReader* reader, Ref<Section> classPtrSection) |
| 539 | { |
| 540 | if (!classPtrSection) |
| 541 | return; |
| 542 | auto size = classPtrSection->GetEnd() - classPtrSection->GetStart(); |
| 543 | if (size == 0) |
| 544 | return; |
| 545 | auto ptrSize = m_data->GetAddressSize(); |
| 546 | |
| 547 | auto classPtrSectionStart = classPtrSection->GetStart(); |
| 548 | auto classPtrSectionEnd = classPtrSection->GetEnd(); |
| 549 | |
| 550 | auto catType = Type::NamedType(m_data, m_typeNames.category); |
| 551 | auto ptrType = Type::PointerType(m_data->GetDefaultArchitecture(), catType); |
| 552 | for (size_t i = classPtrSectionStart; i < classPtrSectionEnd; i += ptrSize) |
| 553 | { |
| 554 | Class category; |
| 555 | category_t cat; |
| 556 | |
| 557 | reader->Seek(i); |
| 558 | auto catLocation = ReadPointerAccountingForRelocations(reader); |
| 559 | reader->Seek(catLocation); |
| 560 | |
| 561 | try |
| 562 | { |
| 563 | cat.name = ReadPointerAccountingForRelocations(reader); |
| 564 | cat.cls = ReadPointerAccountingForRelocations(reader); |
| 565 | cat.instanceMethods = ReadPointerAccountingForRelocations(reader); |
| 566 | cat.classMethods = ReadPointerAccountingForRelocations(reader); |
| 567 | cat.protocols = ReadPointerAccountingForRelocations(reader); |
| 568 | cat.instanceProperties = ReadPointerAccountingForRelocations(reader); |
| 569 | } |
| 570 | catch (...) |
| 571 | { |
| 572 | m_logger->LogError("Failed to read category pointed to by 0x%llx", i); |
| 573 | continue; |
| 574 | } |
| 575 | |
| 576 | std::string categoryAdditionsName; |
| 577 | std::string categoryBaseClassName; |
| 578 | |
| 579 | if (const auto& it = m_classes.find(cat.cls); it != m_classes.end()) |
| 580 | { |
| 581 | categoryBaseClassName = it->second.name; |
| 582 | category.associatedName = it->second.associatedName; |
| 583 | } |
| 584 | else if (const auto symbol = GetSymbol(cat.cls)) |
| 585 | { |
| 586 | if (symbol->GetType() == ImportedDataSymbol || symbol->GetType() == ImportAddressSymbol || symbol->GetType() == DataSymbol) |
| 587 | { |
| 588 | // Symbols named `_OBJC_CLASS_$_` are references to external classes. |
| 589 | // Symbols named `cls_` are classes defined in a loaded image other than |
| 590 | // the image currently being analyzed. Classes from the current image |
| 591 | // are found via `m_classes`. |
| 592 | const std::string_view symbolName = symbol->GetFullNameRef(); |
| 593 | if (symbolName.size() > 14 && symbolName.rfind("_OBJC_CLASS_$_", 0) == 0) |
| 594 | categoryBaseClassName = symbolName.substr(14); |
| 595 | else if (symbolName.size() > 4 && symbolName.rfind("cls_", 0) == 0) |
nothing calls this directly
no test coverage detected