Loading...
--- dyld/dyld-1340/common/ObjCVisitor.cpp
+++ dyld/dyld-1066.8/common/ObjCVisitor.cpp
@@ -22,10 +22,6 @@
* @APPLE_LICENSE_HEADER_END@
*/
-#include <TargetConditionals.h>
-
-#if !TARGET_OS_EXCLAVEKIT
-
#include "ObjCVisitor.h"
#if SUPPORT_VM_LAYOUT
@@ -34,12 +30,10 @@
#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
#include "ASLRTracker.h"
-#include <unordered_set>
#endif
using namespace objc_visitor;
-using ResolvedValue = metadata_visitor::ResolvedValue;
-using mach_o::Header;
+using metadata_visitor::ResolvedValue;
#if !SUPPORT_VM_LAYOUT
using metadata_visitor::Segment;
@@ -148,27 +142,23 @@
}
#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
-void Class::setMethodCachePropertiesVMAddr(const Visitor& objcVisitor, VMAddress vmAddr,
- const dyld3::MachOFile::PointerMetaData& PMD)
+void Class::setMethodCachePropertiesVMAddr(const Visitor& objcVisitor, VMAddress vmAddr)
{
ResolvedValue field = objcVisitor.getField(this->classPos, this->getFieldPos(objcVisitor, Field::methodCacheProperties));
- objcVisitor.setTargetVMAddress(field, CacheVMAddress(vmAddr.rawValue()), PMD);
-}
-#endif
-
-#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS || BUILDING_SHARED_CACHE_UTIL
+ objcVisitor.updateTargetVMAddress(field, CacheVMAddress(vmAddr.rawValue()));
+}
+#endif
+
+#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
void Class::withSuperclass(const Visitor& objcVisitor,
void (^handler)(const dyld3::MachOFile::ChainedFixupPointerOnDisk* fixup, uint16_t pointerFormat)) const
{
- // HACK: The visitor classes need to be refactored to handle cache util. For now just force the caller of this method in
- // cache util to have the chain format
-#if BUILDING_SHARED_CACHE_UTIL
- uint16_t chainedPointerFormat = 0;
-#else
+ assert(objcVisitor.pointerSize == 8);
+
+ assert(objcVisitor.isOnDiskBinary());
uint16_t chainedPointerFormat = this->classPos.chainedPointerFormat().value();
-#endif
-
- const void* fieldPos = this->getFieldPos(objcVisitor, Field::superclass);
+
+ const void* fieldPos = &((const class64_t*)this->classPos.value())->superclassVMAddr;
dyld3::MachOFile::ChainedFixupPointerOnDisk* fieldFixup = (dyld3::MachOFile::ChainedFixupPointerOnDisk*)fieldPos;
handler(fieldFixup, chainedPointerFormat);
}
@@ -258,11 +248,6 @@
return ClassData(targetValue);
}
-VMAddress Class::getClassDataVMAddr(const Visitor& objcVisitor) const
-{
- return getClassData(objcVisitor).getVMAddress();
-}
-
bool Class::isRootClass(const Visitor& objcVisitor) const
{
ClassData data = getClassData(objcVisitor);
@@ -293,17 +278,6 @@
return objcVisitor.resolveOptionalRebase(field);
}
-#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
-ResolvedValue Class::setBaseMethodsVMAddr(const Visitor& objcVisitor, VMAddress vmAddr,
- const dyld3::MachOFile::PointerMetaData& PMD)
-{
- ClassData classData = getClassData(objcVisitor);
- ResolvedValue field = classData.getField(objcVisitor, ClassData::Field::baseMethods);;
- objcVisitor.setTargetVMAddress(field, CacheVMAddress(vmAddr.rawValue()), PMD);
- return field;
-}
-#endif
-
ProtocolList Class::getBaseProtocols(const Visitor& objcVisitor) const
{
ClassData classData = getClassData(objcVisitor);
@@ -311,39 +285,12 @@
return objcVisitor.resolveOptionalRebase(field);
}
-#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
-ResolvedValue Class::setBaseProtocolsVMAddr(const Visitor& objcVisitor, VMAddress vmAddr)
-{
- ClassData classData = getClassData(objcVisitor);
- ResolvedValue field = classData.getField(objcVisitor, ClassData::Field::baseProtocols);
- objcVisitor.updateTargetVMAddress(field, CacheVMAddress(vmAddr.rawValue()));
- return field;
-}
-#endif
-
IVarList Class::getIVars(const Visitor& objcVisitor) const
{
ClassData classData = getClassData(objcVisitor);
ResolvedValue field = classData.getField(objcVisitor, ClassData::Field::ivars);
return objcVisitor.resolveOptionalRebase(field);
}
-
-PropertyList Class::getBaseProperties(const Visitor& objcVisitor) const
-{
- ClassData classData = getClassData(objcVisitor);
- ResolvedValue field = classData.getField(objcVisitor, ClassData::Field::baseProperties);
- return objcVisitor.resolveOptionalRebase(field);
-}
-
-#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
-ResolvedValue Class::setBasePropertiesVMAddr(const Visitor& objcVisitor, VMAddress vmAddr)
-{
- ClassData classData = getClassData(objcVisitor);
- ResolvedValue field = classData.getField(objcVisitor, ClassData::Field::baseProperties);
- objcVisitor.updateTargetVMAddress(field, CacheVMAddress(vmAddr.rawValue()));
- return field;
-}
-#endif
uint32_t Class::getInstanceStart(const Visitor& objcVisitor) const
{
@@ -472,8 +419,6 @@
return &category32->protocolsVMAddr;
case Field::instanceProperties:
return &category32->instancePropertiesVMAddr;
- case Field::classProperties:
- return &category32->classPropertiesVMAddr;
}
} else {
const category64_t* category64 = (const category64_t*)this->categoryPos.value();
@@ -490,8 +435,6 @@
return &category64->protocolsVMAddr;
case Field::instanceProperties:
return &category64->instancePropertiesVMAddr;
- case Field::classProperties:
- return &category64->classPropertiesVMAddr;
}
}
}
@@ -502,22 +445,6 @@
return (const char*)objcVisitor.resolveRebase(field).value();
}
-VMAddress Category::getVMAddress() const
-{
- return this->categoryPos.vmAddress();
-}
-
-const void* Category::getLocation() const
-{
- return this->categoryPos.value();
-}
-
-VMAddress Category::getNameVMAddr(const Visitor& objcVisitor) const
-{
- ResolvedValue field = objcVisitor.getField(this->categoryPos, this->getFieldPos(objcVisitor, Field::name));
- return objcVisitor.resolveRebase(field).vmAddress();
-}
-
MethodList Category::getInstanceMethods(const Visitor& objcVisitor) const
{
ResolvedValue field = objcVisitor.getField(this->categoryPos, this->getFieldPos(objcVisitor, Field::instanceMethods));
@@ -536,59 +463,18 @@
return objcVisitor.resolveOptionalRebase(field);
}
-PropertyList Category::getInstanceProperties(const Visitor& objcVisitor) const
-{
- ResolvedValue field = objcVisitor.getField(this->categoryPos, this->getFieldPos(objcVisitor, Field::instanceProperties));
- return objcVisitor.resolveOptionalRebase(field);
-}
-
-PropertyList Category::getClassProperties(const Visitor& objcVisitor) const
-{
- ResolvedValue field = objcVisitor.getField(this->categoryPos, this->getFieldPos(objcVisitor, Field::classProperties));
- return objcVisitor.resolveOptionalRebase(field);
-}
-
-#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS || BUILDING_SHARED_CACHE_UTIL
+#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
void Category::withClass(const Visitor& objcVisitor,
void (^handler)(const dyld3::MachOFile::ChainedFixupPointerOnDisk* fixup, uint16_t pointerFormat)) const
{
- // HACK: The visitor classes need to be refactored to handle cache util. For now just force the caller of this method in
- // cache util to have the chain format
-#if BUILDING_SHARED_CACHE_UTIL
- uint16_t chainedPointerFormat = 0;
-#else
+ assert(objcVisitor.pointerSize == 8);
+
assert(objcVisitor.isOnDiskBinary());
uint16_t chainedPointerFormat = this->categoryPos.chainedPointerFormat().value();
-#endif
-
- const void* fieldPos = nullptr;
- if ( objcVisitor.pointerSize == 8 ) {
- fieldPos = &((const category64_t*)this->categoryPos.value())->clsVMAddr;
- } else if (objcVisitor.pointerSize == 4 ){
- fieldPos = &((const category32_t*)this->categoryPos.value())->clsVMAddr;
- }
- assert(fieldPos != nullptr);
-
+
+ const void* fieldPos = &((const category64_t*)this->categoryPos.value())->clsVMAddr;
dyld3::MachOFile::ChainedFixupPointerOnDisk* fieldFixup = (dyld3::MachOFile::ChainedFixupPointerOnDisk*)fieldPos;
handler(fieldFixup, chainedPointerFormat);
-}
-#endif
-
-uint32_t Category::getSize(bool is64)
-{
- return is64 ? sizeof(category64_t) : sizeof(category32_t);
-}
-
-
-#if BUILDING_SHARED_CACHE_UTIL
-std::optional<VMAddress> Category::getClassVMAddr(const Visitor& objcVisitor) const
-{
- ResolvedValue field = objcVisitor.getField(this->categoryPos, this->getFieldPos(objcVisitor, Field::cls));
- std::optional<ResolvedValue> targetValue = objcVisitor.resolveOptionalRebase(field);
- if ( targetValue )
- return targetValue->vmAddress();
-
- return { };
}
#endif
@@ -907,57 +793,29 @@
return methodList->getMethodCount();
}
-uint32_t MethodList::listSize() const
+bool MethodList::usesRelativeOffsets() const
{
if ( !methodListPos.has_value() )
- return 0;
+ return false;
const ResolvedValue& methodListValue = this->methodListPos.value();
const method_list_t* methodList = (const method_list_t*)methodListValue.value();
assert(methodList != nullptr);
- uint32_t size = sizeof(uint32_t) * 2;
- size += methodList->getMethodCount() * methodList->getMethodSize();
- return size;
-}
-
-uint32_t MethodList::methodSize() const
+ return methodList->usesRelativeOffsets();
+}
+
+bool MethodList::usesOffsetsFromSelectorBuffer() const
{
if ( !methodListPos.has_value() )
- return 0;
+ return false;
const ResolvedValue& methodListValue = this->methodListPos.value();
const method_list_t* methodList = (const method_list_t*)methodListValue.value();
assert(methodList != nullptr);
- return methodList->getMethodSize();
-}
-
-bool MethodList::usesRelativeOffsets() const
-{
- if ( !methodListPos.has_value() )
- return false;
-
- const ResolvedValue& methodListValue = this->methodListPos.value();
-
- const method_list_t* methodList = (const method_list_t*)methodListValue.value();
- assert(methodList != nullptr);
-
- return methodList->usesRelativeOffsets();
-}
-
-bool MethodList::usesOffsetsFromSelectorBuffer() const
-{
- if ( !methodListPos.has_value() )
- return false;
-
- const ResolvedValue& methodListValue = this->methodListPos.value();
-
- const method_list_t* methodList = (const method_list_t*)methodListValue.value();
- assert(methodList != nullptr);
-
return methodList->usesOffsetsFromSelectorBuffer();
}
@@ -987,18 +845,6 @@
methodList->setIsSorted();
}
-size_t MethodList::makeEmptyMethodList(void* buffer)
-{
- assert(buffer != nullptr);
- method_list_t* methodList = (method_list_t*)buffer;
- bzero(methodList, sizeof(method_list_t));
-
- methodList->setIsUniqued();
- methodList->setIsSorted();
-
- return sizeof(method_list_t);
-}
-
void MethodList::setUsesOffsetsFromSelectorBuffer()
{
if ( !methodListPos.has_value() )
@@ -1012,15 +858,7 @@
methodList->setUsesOffsetsFromSelectorBuffer();
}
-bool MethodList::isListOfLists() const
-{
- if ( !methodListPos.has_value() )
- return false;
-
- const ResolvedValue& methodListValue = this->methodListPos.value();
- return methodListValue.vmAddress().rawValue() & 1;
-}
-
+#if BUILDING_CACHE_BUILDER_UNIT_TESTS
const void* MethodList::getLocation() const
{
if ( !this->methodListPos.has_value() )
@@ -1030,10 +868,9 @@
std::optional<VMAddress> MethodList::getVMAddress() const
{
- if ( !this->methodListPos.has_value() )
- return { };
return this->methodListPos->vmAddress();
}
+#endif
static Method::Kind getKind(const MethodList::method_list_t* methodList)
{
@@ -1142,7 +979,7 @@
// The uint32_t name field is an offset from itself to a selref. The selref then points to the selector string
const uint8_t* fieldPos = (const uint8_t*)&((const relative_method_t*)this->methodPos.value())->nameOffset;
int32_t relativeOffsetFromField = *(int32_t*)fieldPos;
- VMOffset relativeOffsetFromMethod((uint64_t)offsetof(relative_method_t, nameOffset) + relativeOffsetFromField);
+ VMOffset relativeOffsetFromMethod((uint64_t)__offsetof(relative_method_t, nameOffset) + relativeOffsetFromField);
VMAddress methodVMAddr = this->methodPos.vmAddress();
VMAddress nameSelRefVMAddr = methodVMAddr + relativeOffsetFromMethod;
@@ -1151,17 +988,7 @@
return (const char*)objcVisitor.resolveRebase(nameSelRefValue).value();
}
case Kind::relativeDirect: {
-#if BUILDING_SHARED_CACHE_UTIL
- const uint8_t* fieldPos = (const uint8_t*)&((const relative_method_t*)this->methodPos.value())->nameOffset;
- uint32_t nameOffsetInBuffer = *(uint32_t*)fieldPos;
-
- VMAddress nameVMAddr = objcVisitor.sharedCacheSelectorStringsBaseAddress() + VMOffset((uint64_t)nameOffsetInBuffer);
- ResolvedValue nameValue = objcVisitor.getValueFor(nameVMAddr);
- return (const char*)nameValue.value();
-#else
- // dyld should never walk direct methods as the objc closure optimizations skip cache dylibs
assert(0);
-#endif
}
case Kind::pointer: {
ResolvedValue nameField = this->getNameField(objcVisitor);
@@ -1176,7 +1003,7 @@
case Kind::relativeIndirect: {
const uint8_t* fieldPos = (const uint8_t*)&((const relative_method_t*)this->methodPos.value())->typesOffset;
int32_t relativeOffsetFromField = *(int32_t*)fieldPos;
- VMOffset relativeOffsetFromMethod((uint64_t)offsetof(relative_method_t, typesOffset) + relativeOffsetFromField);
+ VMOffset relativeOffsetFromMethod((uint64_t)__offsetof(relative_method_t, typesOffset) + relativeOffsetFromField);
VMAddress methodVMAddr = this->methodPos.vmAddress();
VMAddress typeVMAddr = methodVMAddr + relativeOffsetFromMethod;
@@ -1200,7 +1027,7 @@
case Kind::relativeIndirect: {
const uint8_t* fieldPos = (const uint8_t*)&((const relative_method_t*)this->methodPos.value())->impOffset;
int32_t relativeOffsetFromField = *(int32_t*)fieldPos;
- VMOffset relativeOffsetFromMethod((uint64_t)offsetof(relative_method_t, impOffset) + relativeOffsetFromField);
+ VMOffset relativeOffsetFromMethod((uint64_t)__offsetof(relative_method_t, impOffset) + relativeOffsetFromField);
VMAddress methodVMAddr = this->methodPos.vmAddress();
VMAddress impVMAddr = methodVMAddr + relativeOffsetFromMethod;
@@ -1227,7 +1054,7 @@
// The uint32_t name field is an offset from itself to a selref. The selref then points to the selector string
const uint8_t* fieldPos = (const uint8_t*)&((const relative_method_t*)this->methodPos.value())->nameOffset;
int32_t relativeOffsetFromField = *(int32_t*)fieldPos;
- VMOffset relativeOffsetFromMethod((uint64_t)offsetof(relative_method_t, nameOffset) + relativeOffsetFromField);
+ VMOffset relativeOffsetFromMethod((uint64_t)__offsetof(relative_method_t, nameOffset) + relativeOffsetFromField);
VMAddress methodVMAddr = this->methodPos.vmAddress();
VMAddress nameSelRefVMAddr = methodVMAddr + relativeOffsetFromMethod;
@@ -1236,7 +1063,7 @@
return objcVisitor.resolveRebase(nameSelRefValue).vmAddress();
}
case Kind::relativeDirect: {
-#if BUILDING_DYLD || BUILDING_CLOSURE_UTIL || BUILDING_UNIT_TESTS
+#if BUILDING_DYLD || BUILDING_CLOSURE_UTIL || BUILDING_SHARED_CACHE_UTIL || BUILDING_UNIT_TESTS
// dyld should never walk direct methods as the objc closure optimizations skip cache dylibs
assert(0);
#else
@@ -1260,7 +1087,7 @@
case Kind::relativeDirect: {
const uint8_t* fieldPos = (const uint8_t*)&((const relative_method_t*)this->methodPos.value())->typesOffset;
int32_t relativeOffsetFromField = *(int32_t*)fieldPos;
- VMOffset relativeOffsetFromMethod((uint64_t)offsetof(relative_method_t, typesOffset) + relativeOffsetFromField);
+ VMOffset relativeOffsetFromMethod((uint64_t)__offsetof(relative_method_t, typesOffset) + relativeOffsetFromField);
VMAddress methodVMAddr = this->methodPos.vmAddress();
VMAddress typeVMAddr = methodVMAddr + relativeOffsetFromMethod;
@@ -1280,12 +1107,7 @@
case Kind::relativeDirect: {
const uint8_t* fieldPos = (const uint8_t*)&((const relative_method_t*)this->methodPos.value())->impOffset;
int32_t relativeOffsetFromField = *(int32_t*)fieldPos;
-
- // protocols have null impls
- if ( relativeOffsetFromField == 0 )
- return std::nullopt;
-
- VMOffset relativeOffsetFromMethod((uint64_t)offsetof(relative_method_t, impOffset) + relativeOffsetFromField);
+ VMOffset relativeOffsetFromMethod((uint64_t)__offsetof(relative_method_t, impOffset) + relativeOffsetFromField);
VMAddress methodVMAddr = this->methodPos.vmAddress();
VMAddress impVMAddr = methodVMAddr + relativeOffsetFromMethod;
@@ -1307,7 +1129,7 @@
// The uint32_t name field is an offset from itself to a selref. The selref then points to the selector string
const uint8_t* fieldPos = (const uint8_t*)&((const relative_method_t*)this->methodPos.value())->nameOffset;
int32_t relativeOffsetFromField = *(int32_t*)fieldPos;
- VMOffset relativeOffsetFromMethod((uint64_t)offsetof(relative_method_t, nameOffset) + relativeOffsetFromField);
+ VMOffset relativeOffsetFromMethod((uint64_t)__offsetof(relative_method_t, nameOffset) + relativeOffsetFromField);
VMAddress methodVMAddr = this->methodPos.vmAddress();
VMAddress nameSelRefVMAddr = methodVMAddr + relativeOffsetFromMethod;
@@ -1354,7 +1176,7 @@
case Kind::relativeIndirect:
case Kind::relativeDirect: {
VMAddress methodVMAddr = this->methodPos.vmAddress();
- VMAddress typesFieldVMAddr = methodVMAddr + VMOffset((uint64_t)offsetof(relative_method_t, typesOffset));
+ VMAddress typesFieldVMAddr = methodVMAddr + VMOffset((uint64_t)__offsetof(relative_method_t, typesOffset));
VMOffset typesRelativeOffset = typesVMAddr - typesFieldVMAddr;
int64_t relativeOffset = (int64_t)typesRelativeOffset.rawValue();
@@ -1376,21 +1198,18 @@
switch ( this->kind ) {
case Kind::relativeIndirect:
case Kind::relativeDirect: {
- if ( !impVMAddr.has_value() ) {
- // A NULL imp is probably a protocol, and is expected. Every other IMP in the
- // protocol is also going to be NULL, so just make sure this one matches
- assert(!this->getIMPVMAddr(objcVisitor).has_value());
- } else {
- VMAddress methodVMAddr = this->methodPos.vmAddress();
- VMAddress impFieldVMAddr = methodVMAddr + VMOffset((uint64_t)offsetof(relative_method_t, impOffset));
-
- VMOffset impRelativeOffset = impVMAddr.value() - impFieldVMAddr;
- int64_t relativeOffset = (int64_t)impRelativeOffset.rawValue();
-
- const uint8_t* fieldPos = (const uint8_t*)&((const relative_method_t*)this->methodPos.value())->impOffset;
- assert((int32_t)relativeOffset == relativeOffset);
- *(int32_t*)fieldPos = (int32_t)relativeOffset;
- }
+ // We don't support NULL imp's with relative method lists.
+ assert(impVMAddr.has_value());
+
+ VMAddress methodVMAddr = this->methodPos.vmAddress();
+ VMAddress impFieldVMAddr = methodVMAddr + VMOffset((uint64_t)__offsetof(relative_method_t, impOffset));
+
+ VMOffset impRelativeOffset = impVMAddr.value() - impFieldVMAddr;
+ int64_t relativeOffset = (int64_t)impRelativeOffset.rawValue();
+
+ const uint8_t* fieldPos = (const uint8_t*)&((const relative_method_t*)this->methodPos.value())->impOffset;
+ assert((int32_t)relativeOffset == relativeOffset);
+ *(int32_t*)fieldPos = (int32_t)relativeOffset;
break;
}
case Kind::pointer: {
@@ -1429,11 +1248,6 @@
}
}
-uint32_t Method::getSize(bool is64)
-{
- return is64 ? sizeof(method64_t) : sizeof(method32_t);
-}
-
//
// MARK: --- IVarList methods ---
//
@@ -1480,61 +1294,6 @@
return this->ivarListPos->vmAddress();
}
#endif
-
-//
-// MARK: --- PropertyList methods ---
-//
-uint32_t PropertyList::numProperties() const
-{
- if ( !this->propertyListPos.has_value() )
- return 0;
-
- const ResolvedValue& propertyListValue = this->propertyListPos.value();
-
- const property_list_t* propertyList = (const property_list_t*)propertyListValue.value();
- assert(propertyList != nullptr);
-
- return propertyList->getCount();
-}
-
-Property PropertyList::getProperty(const Visitor& objcVisitor, uint32_t i) const
-{
- assert(this->propertyListPos.has_value());
-
- const ResolvedValue& propertyListValue = this->propertyListPos.value();
-
- const property_list_t* propertyList = (const property_list_t*)propertyListValue.value();
- assert(propertyList != nullptr);
-
- const uint8_t* propertyListBase = propertyList->propertyBase();
- const uint8_t* property = propertyListBase + (i * propertyList->getElementSize());
-
- ResolvedValue propertyValue = objcVisitor.getField(propertyListValue, property);
- return Property(propertyValue);
-}
-
-const void* PropertyList::getLocation() const
-{
- if ( !this->propertyListPos.has_value() )
- return nullptr;
- return this->propertyListPos->value();
-}
-
-std::optional<VMAddress> PropertyList::getVMAddress() const
-{
- if ( !this->propertyListPos.has_value() )
- return { };
- return this->propertyListPos->vmAddress();
-}
-
-bool PropertyList::isListOfLists() const
-{
- if ( !propertyListPos.has_value() )
- return false;
-
- const ResolvedValue& propertyListValue = this->propertyListPos.value();
- return propertyListValue.vmAddress().rawValue() & 1;
-}
//
// MARK: --- ProtocolList methods ---
@@ -1590,6 +1349,7 @@
}
#endif
+#if BUILDING_CACHE_BUILDER_UNIT_TESTS
const void* ProtocolList::getLocation() const
{
if ( !this->protocolListPos.has_value() )
@@ -1599,20 +1359,9 @@
std::optional<VMAddress> ProtocolList::getVMAddress() const
{
- if ( !this->protocolListPos.has_value() )
- return { };
return this->protocolListPos->vmAddress();
}
-
-bool ProtocolList::isListOfLists() const
-{
- if ( !protocolListPos.has_value() )
- return false;
-
- const ResolvedValue& protocolListValue = this->protocolListPos.value();
- return protocolListValue.vmAddress().rawValue() & 1;
-}
-
+#endif
void ProtocolList::dump(const Visitor& objcVisitor) const
{
@@ -1708,47 +1457,10 @@
}
//
-// MARK: --- Property methods ---
-//
-
-const void* Property::getFieldPos(const Visitor& objcVisitor, Field field) const
-{
- if ( objcVisitor.pointerSize == 4 ) {
- const property32_t* property32 = (const property32_t*)this->propertyPos.value();
- switch ( field ) {
- case Field::name:
- return &property32->nameVMAddr;
- case Field::attributes:
- return &property32->attributesVMAddr;
- }
- } else {
- const property64_t* property64 = (const property64_t*)this->propertyPos.value();
- switch ( field ) {
- case Field::name:
- return &property64->nameVMAddr;
- case Field::attributes:
- return &property64->attributesVMAddr;
- }
- }
-}
-
-const char* Property::getName(const Visitor& objcVisitor) const
-{
- ResolvedValue field = objcVisitor.getField(this->propertyPos, this->getFieldPos(objcVisitor, Field::name));
- return (const char*)objcVisitor.resolveRebase(field).value();
-}
-
-const char* Property::getAttributes(const Visitor& objcVisitor) const
-{
- ResolvedValue field = objcVisitor.getField(this->propertyPos, this->getFieldPos(objcVisitor, Field::attributes));
- return (const char*)objcVisitor.resolveRebase(field).value();
-}
-
-//
-// MARK: --- Visitor::Section methods ---
-//
-
-std::optional<Visitor::Section> Visitor::findSection(std::span<const char*> altSegNames, const char *sectionName) const
+// MARK: --- Visitor::DataSection methods ---
+//
+
+std::optional<Visitor::DataSection> Visitor::findObjCDataSection(const char *sectionName) const
{
#if SUPPORT_VM_LAYOUT
const dyld3::MachOFile* mf = this->dylibMA;
@@ -1756,51 +1468,34 @@
const dyld3::MachOFile* mf = this->dylibMF;
#endif
- __block std::optional<Visitor::Section> objcDataSection;
- ((const Header*)mf)->forEachSection(^(const Header::SegmentInfo& segInfo, const Header::SectionInfo& sectInfo, bool& stop) {
- bool segMatch = std::any_of(altSegNames.begin(), altSegNames.end(), [§Info](const char* segName) {
- return sectInfo.segmentName == segName;
- });
- if ( !segMatch )
+ __block std::optional<Visitor::DataSection> objcDataSection;
+ mf->forEachSection(^(const dyld3::MachOFile::SectionInfo& sectInfo, bool malformedSectionRange, bool& stop) {
+ if ( (strcmp(sectInfo.segInfo.segName, "__DATA") != 0) &&
+ (strcmp(sectInfo.segInfo.segName, "__DATA_CONST") != 0) &&
+ (strcmp(sectInfo.segInfo.segName, "__DATA_DIRTY") != 0) )
return;
- if ( sectInfo.sectionName != sectionName )
+ if ( strcmp(sectInfo.sectName, sectionName) != 0 )
return;
#if SUPPORT_VM_LAYOUT
- const void* targetValue = (const void*)(sectInfo.address + this->dylibMA->getSlide());
- ResolvedValue target(targetValue, VMAddress(sectInfo.address));
+ const void* targetValue = (const void*)(sectInfo.sectAddr + this->dylibMA->getSlide());
+ ResolvedValue target(targetValue, VMAddress(sectInfo.sectAddr));
#else
- VMOffset offsetInSegment(sectInfo.address - segInfo.vmaddr);
- ResolvedValue target(this->segments[sectInfo.segIndex], offsetInSegment);
-#endif
- objcDataSection.emplace(std::move(target), sectInfo.size);
+ VMOffset offsetInSegment(sectInfo.sectAddr - sectInfo.segInfo.vmAddr);
+ ResolvedValue target(this->segments[sectInfo.segInfo.segIndex], offsetInSegment);
+#endif
+ objcDataSection.emplace(std::move(target), sectInfo.sectSize);
stop = true;
});
return objcDataSection;
}
-std::optional<Visitor::Section> Visitor::findObjCDataSection(const char *sectionName) const
-{
- static const char* objcDataSegments[] = {
- "__DATA", "__DATA_CONST", "__DATA_DIRTY"
- };
- return findSection(objcDataSegments, sectionName);
-}
-
-std::optional<Visitor::Section> Visitor::findObjCTextSection(const char *sectionName) const
-{
- static const char* objcTextSegments[] = {
- "__TEXT"
- };
- return findSection(objcTextSegments, sectionName);
-}
-
//
// MARK: --- Visitor methods ---
//
-void Visitor::forEachClass(bool visitMetaClasses, const Visitor::Section& classListSection,
+void Visitor::forEachClass(bool visitMetaClasses, const Visitor::DataSection& classListSection,
void (^callback)(Class& objcClass, bool isMetaClass, bool& stopClass))
{
assert((classListSection.sectSize % pointerSize) == 0);
@@ -1838,7 +1533,7 @@
void Visitor::forEachClass(bool visitMetaClasses, void (^callback)(Class& objcClass, bool isMetaClass, bool& stopClass))
{
- std::optional<Section> classListSection = this->findObjCDataSection("__objc_classlist");
+ std::optional<DataSection> classListSection = this->findObjCDataSection("__objc_classlist");
if ( !classListSection.has_value() )
return;
@@ -1879,35 +1574,32 @@
void Visitor::forEachCategory(void (^callback)(const Category& objcCategory, bool& stopCategory))
{
- for ( bool isCatlist2 : { false, true }) {
- const char* listSection = isCatlist2 ? "__objc_catlist2" : "__objc_catlist";
- std::optional<Section> categoryListSection = findObjCDataSection(listSection);
- if ( !categoryListSection.has_value() )
- continue;
-
- assert((categoryListSection->sectSize % pointerSize) == 0);
- uint64_t numCategories = categoryListSection->sectSize / pointerSize;
-
- const ResolvedValue& sectionValue = categoryListSection->sectionBase;
- const uint8_t* sectionBase = (const uint8_t*)sectionValue.value();
- for ( uint64_t categoryIndex = 0; categoryIndex != numCategories; ++categoryIndex ) {
- const uint8_t* categoryRefPos = sectionBase + (categoryIndex * pointerSize);
- ResolvedValue categoryRefValue = this->getField(sectionValue, categoryRefPos);
-
- // Follow the category reference to get to the actual category
- ResolvedValue categoryPos = resolveRebase(categoryRefValue);
- Category objcCategory(categoryPos, isCatlist2);
- bool stopCategory = false;
- callback(objcCategory, stopCategory);
- if ( stopCategory )
- break;
- }
+ std::optional<DataSection> categoryListSection = findObjCDataSection("__objc_catlist");
+ if ( !categoryListSection.has_value() )
+ return;
+
+ assert((categoryListSection->sectSize % pointerSize) == 0);
+ uint64_t numCategories = categoryListSection->sectSize / pointerSize;
+
+ const ResolvedValue& sectionValue = categoryListSection->sectionBase;
+ const uint8_t* sectionBase = (const uint8_t*)sectionValue.value();
+ for ( uint64_t categoryIndex = 0; categoryIndex != numCategories; ++categoryIndex ) {
+ const uint8_t* categoryRefPos = sectionBase + (categoryIndex * pointerSize);
+ ResolvedValue categoryRefValue = this->getField(sectionValue, categoryRefPos);
+
+ // Follow the category reference to get to the actual category
+ ResolvedValue categoryPos = resolveRebase(categoryRefValue);
+ Category objcCategory(categoryPos);
+ bool stopCategory = false;
+ callback(objcCategory, stopCategory);
+ if ( stopCategory )
+ break;
}
}
void Visitor::forEachProtocol(void (^callback)(const Protocol& objcProtocol, bool& stopProtocol))
{
- std::optional<Section> protocolListSection = findObjCDataSection("__objc_protolist");
+ std::optional<DataSection> protocolListSection = findObjCDataSection("__objc_protolist");
if ( !protocolListSection.has_value() )
return;
@@ -1932,7 +1624,7 @@
void Visitor::forEachSelectorReference(void (^callback)(ResolvedValue& value)) const
{
- std::optional<Section> selRefsSection = findObjCDataSection("__objc_selrefs");
+ std::optional<DataSection> selRefsSection = findObjCDataSection("__objc_selrefs");
if ( !selRefsSection.has_value() )
return;
@@ -1965,7 +1657,7 @@
void Visitor::forEachProtocolReference(void (^callback)(ResolvedValue& value))
{
- std::optional<Section> protocolRefsSection = findObjCDataSection("__objc_protorefs");
+ std::optional<DataSection> protocolRefsSection = findObjCDataSection("__objc_protorefs");
if ( !protocolRefsSection.has_value() )
return;
@@ -1982,126 +1674,3 @@
}
}
-#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
-void Visitor::forEachMethodList(void (^callback)(MethodList& objcMethodList, std::optional<metadata_visitor::ResolvedValue> extendedMethodTypes))
-{
- __block std::unordered_set<const void*> visitedLists;
-
- forEachClassAndMetaClass(^(const objc_visitor::Class& objcClass, bool&) {
- objc_visitor::MethodList objcMethodList = objcClass.getBaseMethods(*this);
-
- callback(objcMethodList, std::nullopt);
- visitedLists.insert(objcMethodList.getLocation());
- });
-
- forEachCategory(^(const objc_visitor::Category& objcCategory, bool&) {
- objc_visitor::MethodList instanceMethodList = objcCategory.getInstanceMethods(*this);
- objc_visitor::MethodList classMethodList = objcCategory.getClassMethods(*this);
-
- callback(instanceMethodList, std::nullopt);
- visitedLists.insert(instanceMethodList.getLocation());
-
- callback(classMethodList, std::nullopt);
- visitedLists.insert(classMethodList.getLocation());
- });
-
- forEachProtocol(^(const objc_visitor::Protocol& objcProtocol, bool&) {
- objc_visitor::MethodList instanceMethodList = objcProtocol.getInstanceMethods(*this);
- objc_visitor::MethodList classMethodList = objcProtocol.getClassMethods(*this);
- objc_visitor::MethodList optionalInstanceMethodList = objcProtocol.getOptionalInstanceMethods(*this);
- objc_visitor::MethodList optionalClassMethodList = objcProtocol.getOptionalClassMethods(*this);
-
- // This is an optional flat array with entries for all method lists.
- // Each method list of length N has N char* entries in this list, if its present
- std::optional<metadata_visitor::ResolvedValue> extendedMethodTypes = objcProtocol.getExtendedMethodTypes(*this);
- const uint8_t* currentMethodTypes = extendedMethodTypes.has_value() ? (const uint8_t*)extendedMethodTypes->value() : nullptr;
-
- callback(instanceMethodList, extendedMethodTypes);
- visitedLists.insert(instanceMethodList.getLocation());
- if ( extendedMethodTypes.has_value() ) {
- currentMethodTypes += (instanceMethodList.numMethods() * pointerSize);
- extendedMethodTypes.emplace(metadata_visitor::ResolvedValue(extendedMethodTypes.value(), currentMethodTypes));
- }
-
- callback(classMethodList, extendedMethodTypes);
- visitedLists.insert(classMethodList.getLocation());
- if ( extendedMethodTypes.has_value() ) {
- currentMethodTypes += (classMethodList.numMethods() * pointerSize);
- extendedMethodTypes.emplace(metadata_visitor::ResolvedValue(extendedMethodTypes.value(), currentMethodTypes));
- }
-
- callback(optionalInstanceMethodList, extendedMethodTypes);
- visitedLists.insert(optionalInstanceMethodList.getLocation());
- if ( extendedMethodTypes.has_value() ) {
- currentMethodTypes += (optionalInstanceMethodList.numMethods() * pointerSize);
- extendedMethodTypes.emplace(metadata_visitor::ResolvedValue(extendedMethodTypes.value(), currentMethodTypes));
- }
-
- callback(optionalClassMethodList, extendedMethodTypes);
- visitedLists.insert(optionalClassMethodList.getLocation());
- if ( extendedMethodTypes.has_value() ) {
- currentMethodTypes += (optionalClassMethodList.numMethods() * pointerSize);
- extendedMethodTypes.emplace(metadata_visitor::ResolvedValue(extendedMethodTypes.value(), currentMethodTypes));
- }
- });
-
- // rdar://129304028 (dyld cache builder support for relative method lists in Swift generic classes)
- // Also scan the entire __objc_methlist section looking for other method lists that
- // aren't referenced through the regular ObjC metadata.
- std::optional<Section> methodListSection = findObjCTextSection("__objc_methlist");
- if ( !methodListSection.has_value() )
- return;
- assert((methodListSection->sectSize % 4) == 0);
-
- const ResolvedValue& sectionValue = methodListSection->sectionBase;
- const uint8_t* sectionPos = (const uint8_t*)sectionValue.value();
- const uint8_t* sectionEnd = (const uint8_t*)sectionValue.value() + methodListSection->sectSize;
-
- while ( sectionPos < sectionEnd ) {
- ResolvedValue methodListValue = this->getField(sectionValue, sectionPos);
-
- // method lists are 8-byte alligned, a valid method list can never start
- // with a 0 because that's where the method size entry and flags are encoded
- if ( *(uint32_t*)methodListValue.value() == 0 ) {
- sectionPos += sizeof(uint32_t);
- continue;
- }
-
- MethodList methodList(methodListValue);
-
- // sanity check entry - all lists in __objc_methlist are relative and
- // a relative method list entry is 12 bytes large
- assert(methodList.usesRelativeOffsets() && methodList.methodSize() == 12
- && "not a relative method list");
-
- // skip method lists that were visited through classes etc.
- if ( !visitedLists.contains(methodList.getLocation()) ) {
- callback(methodList, std::nullopt);
- }
-
- uint32_t size = methodList.listSize();
- assert(size != 0 && "method list can't be empty");
- sectionPos += size;
- }
- assert(sectionPos == sectionEnd && "malformed __objc_methlist section");
-}
-#endif
-
-void Visitor::withImageInfo(void (^callback)(const uint32_t version, const uint32_t flags)) const
-{
- std::optional<Section> imageInfoSection = findObjCDataSection("__objc_imageinfo");
- if ( !imageInfoSection.has_value() )
- return;
-
- assert((imageInfoSection->sectSize % pointerSize) == 0);
- const ResolvedValue& sectionValue = imageInfoSection->sectionBase;
-
- struct objc_image_info {
- int32_t version;
- uint32_t flags;
- };
- const objc_image_info* sectionBase = (const objc_image_info*)sectionValue.value();
- callback(sectionBase->version, sectionBase->flags);
-}
-
-#endif // !TARGET_OS_EXCLAVEKIT