Loading...
common/ObjCVisitor.cpp dyld-1235.2 dyld-1335
--- dyld/dyld-1235.2/common/ObjCVisitor.cpp
+++ dyld/dyld-1335/common/ObjCVisitor.cpp
@@ -39,6 +39,7 @@
 
 using namespace objc_visitor;
 using ResolvedValue = metadata_visitor::ResolvedValue;
+using mach_o::Header;
 
 #if !SUPPORT_VM_LAYOUT
 using metadata_visitor::Segment;
@@ -1141,7 +1142,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;
@@ -1175,7 +1176,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;
@@ -1199,7 +1200,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;
@@ -1226,7 +1227,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;
@@ -1259,7 +1260,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;
@@ -1279,7 +1280,12 @@
         case Kind::relativeDirect:  {
             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);
+
+            // protocols have null impls
+            if ( relativeOffsetFromField == 0 )
+                return std::nullopt;
+
+            VMOffset relativeOffsetFromMethod((uint64_t)offsetof(relative_method_t, impOffset) + relativeOffsetFromField);
 
             VMAddress methodVMAddr = this->methodPos.vmAddress();
             VMAddress impVMAddr = methodVMAddr + relativeOffsetFromMethod;
@@ -1301,7 +1307,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;
@@ -1348,7 +1354,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();
@@ -1370,18 +1376,21 @@
     switch ( this->kind ) {
         case Kind::relativeIndirect:
         case Kind::relativeDirect: {
-            // 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;
+            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;
+            }
             break;
         }
         case Kind::pointer: {
@@ -1748,23 +1757,23 @@
 #endif
 
     __block std::optional<Visitor::Section> objcDataSection;
-    mf->forEachSection(^(const dyld3::MachOFile::SectionInfo& sectInfo, bool malformedSectionRange, bool& stop) {
+    ((const Header*)mf)->forEachSection(^(const Header::SegmentInfo& segInfo, const Header::SectionInfo& sectInfo, bool& stop) {
         bool segMatch = std::any_of(altSegNames.begin(), altSegNames.end(), [&sectInfo](const char* segName) {
-            return strncmp(sectInfo.segInfo.segName, segName, 16) == 0;
+            return sectInfo.segmentName == segName;
         });
         if ( !segMatch )
             return;
-        if ( strncmp(sectInfo.sectName, sectionName, 16) != 0 )
+        if ( sectInfo.sectionName != sectionName )
             return;
 
 #if SUPPORT_VM_LAYOUT
-        const void* targetValue = (const void*)(sectInfo.sectAddr + this->dylibMA->getSlide());
-        ResolvedValue target(targetValue, VMAddress(sectInfo.sectAddr));
+        const void* targetValue = (const void*)(sectInfo.address + this->dylibMA->getSlide());
+        ResolvedValue target(targetValue, VMAddress(sectInfo.address));
 #else
-        VMOffset offsetInSegment(sectInfo.sectAddr - sectInfo.segInfo.vmAddr);
-        ResolvedValue target(this->segments[sectInfo.segInfo.segIndex], offsetInSegment);
-#endif
-        objcDataSection.emplace(std::move(target), sectInfo.sectSize);
+        VMOffset offsetInSegment(sectInfo.address - segInfo.vmaddr);
+        ResolvedValue target(this->segments[sectInfo.segIndex], offsetInSegment);
+#endif
+        objcDataSection.emplace(std::move(target), sectInfo.size);
 
         stop = true;
     });