Loading...
--- dyld/dyld-1162/common/MachOFile.cpp
+++ dyld/dyld-1235.2/common/MachOFile.cpp
@@ -52,17 +52,30 @@
}
#endif
+
+
+
#include "Defines.h"
#include <mach-o/nlist.h>
+
+#if !BUILDING_DYLD
+ #include <vector>
+#endif // !BUILDING_DYLD
#include "Array.h"
#include "MachOFile.h"
#include "SupportedArchs.h"
#include "CodeSigningTypes.h"
+#include "ObjC.h"
+
#if (BUILDING_DYLD || BUILDING_LIBDYLD) && !TARGET_OS_EXCLAVEKIT
#include <subsystem.h>
+#endif
+
+#if !BUILDING_DYLD
+#include "ObjCVisitor.h"
#endif
namespace dyld3 {
@@ -295,7 +308,6 @@
#define GRADE_arm64e CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64E, false
#define GRADE_arm64e_pb CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64E, true
#define GRADE_arm64_32 CPU_TYPE_ARM64_32, CPU_SUBTYPE_ARM64_32_V8, false
-
const GradedArchs GradedArchs::i386 = GradedArchs({GRADE_i386, 1});
const GradedArchs GradedArchs::x86_64 = GradedArchs({GRADE_x86_64, 1});
const GradedArchs GradedArchs::x86_64h = GradedArchs({GRADE_x86_64h, 2}, {GRADE_x86_64, 1});
@@ -316,6 +328,7 @@
#if SUPPORT_ARCH_arm64_32
const GradedArchs GradedArchs::arm64_32 = GradedArchs({GRADE_arm64_32, 1});
#endif
+
#if BUILDING_LIBDYLD || BUILDING_UNIT_TESTS
const GradedArchs GradedArchs::launch_AS = GradedArchs({GRADE_arm64e, 3}, {GRADE_arm64, 2}, {GRADE_x86_64, 1});
const GradedArchs GradedArchs::launch_AS_Sim = GradedArchs({GRADE_arm64, 2}, {GRADE_x86_64, 1});
@@ -395,20 +408,12 @@
return arm64_32;
#elif __arm64__
return arm64;
-#elif __ARM_ARCH_7K__
- return armv7k;
-#elif __ARM_ARCH_7S__
- return armv7s;
-#elif __ARM_ARCH_7A__
- return armv7;
#elif __x86_64__
#if TARGET_OS_SIMULATOR
return x86_64;
#else
return isHaswell() ? x86_64h : x86_64;
#endif
-#elif __i386__
- return i386;
#else
#error unknown platform
#endif
@@ -504,8 +509,15 @@
{ "tvOS-sim", Platform::tvOS_simulator, LC_BUILD_VERSION },
{ "watchOS-sim", Platform::watchOS_simulator, LC_BUILD_VERSION },
{ "driverKit", Platform::driverKit, LC_BUILD_VERSION },
- { "xrOS", Platform::xrOS, LC_BUILD_VERSION },
- { "xrOS-sim", Platform::xrOS_simulator, LC_BUILD_VERSION },
+ { "visionOS", Platform::visionOS, LC_BUILD_VERSION },
+ { "visionOS-sim", Platform::visionOS_simulator, LC_BUILD_VERSION },
+ { "macOSExclaveCore", Platform::macOSExclaveCore, LC_BUILD_VERSION },
+ { "macOSExclaveKit", Platform::macOSExclaveKit, LC_BUILD_VERSION },
+ { "iOSExclaveCore", Platform::iOSExclaveCore, LC_BUILD_VERSION },
+ { "iOSExclaveKit", Platform::iOSExclaveKit, LC_BUILD_VERSION },
+ { "tvOSExclaveCore", Platform::tvOSExclaveCore, LC_BUILD_VERSION },
+ { "tvOSExclaveKit", Platform::tvOSExclaveKit, LC_BUILD_VERSION },
+
};
@@ -685,6 +697,14 @@
return true;
#endif
+ // allow iOS executables to use visionOS dylibs
+ if ( (processPlatform == Platform::iOS) && this->builtForPlatform(Platform::visionOS, true) )
+ return true;
+
+ // allow iOS_Sim executables to use visionOS_Sim dylibs
+ if ( (processPlatform == Platform::iOS_simulator) && this->builtForPlatform(Platform::visionOS_simulator, true) )
+ return true;
+
bool iOSonMac = (processPlatform == Platform::iOSMac);
#if (TARGET_OS_OSX && TARGET_CPU_ARM64)
@@ -727,7 +747,9 @@
return Platform::watchOS_simulator;
#elif TARGET_OS_TV
return Platform::tvOS_simulator;
- #else
+ #elif TARGET_OS_VISION
+ return Platform::visionOS_simulator;
+ #elif TARGET_OS_IOS
return Platform::iOS_simulator;
#endif
#elif TARGET_OS_BRIDGE
@@ -742,8 +764,32 @@
return Platform::macOS;
#elif TARGET_OS_DRIVERKIT
return Platform::driverKit;
+#elif TARGET_OS_VISION
+ return Platform::visionOS;
#else
- #error unknown platform
+ #if TARGET_OS_EXCLAVECORE
+ #if __is_target_os(macos)
+ return Platform::macOSExclaveCore
+ #elif __is_target_os(ios)
+ return Platform::iOSExclaveCore;
+ #elif __is_target_os(tvos)
+ return Platform::tvOSExclaveCore;
+ #else
+ #error unknown platform
+ #endif
+ #elif TARGET_OS_EXCLAVEKIT
+ #if __is_target_os(macos)
+ return Platform::macOSExclaveKit;
+ #elif __is_target_os(ios)
+ return Platform::iOSExclaveKit;
+ #elif __is_target_os(tvos)
+ return Platform::tvOSExclaveKit;
+ #else
+ #error unknown platform
+ #endif
+ #else
+ #error unknown platform
+ #endif
#endif
}
@@ -760,20 +806,24 @@
case Platform::tvOS_simulator: return Platform::tvOS;
case Platform::watchOS_simulator: return Platform::watchOS;
case Platform::driverKit: return Platform::driverKit;
- default: return Platform::unknown;
+ case Platform::visionOS: return Platform::visionOS;
+ case Platform::visionOS_simulator: return Platform::visionOS;
+ case Platform::macOSExclaveCore: return Platform::macOSExclaveCore;
+ case Platform::macOSExclaveKit: return Platform::macOSExclaveKit;
+ case Platform::iOSExclaveCore: return Platform::iOSExclaveCore;
+ case Platform::iOSExclaveKit: return Platform::iOSExclaveKit;
+ case Platform::tvOSExclaveCore: return Platform::tvOSExclaveCore;
+ case Platform::tvOSExclaveKit: return Platform::tvOSExclaveKit;
+
+
+ default: return reqPlatform;
}
}
const char* MachOFile::currentArchName()
{
-#if __ARM_ARCH_7K__
- return "armv7k";
-#elif __ARM_ARCH_7A__
- return "armv7";
-#elif __ARM_ARCH_7S__
- return "armv7s";
-#elif __arm64e__
+#if __arm64e__
return "arm64e";
#elif __arm64__
#if __LP64__
@@ -783,8 +833,6 @@
#endif
#elif __x86_64__
return isHaswell() ? "x86_64h" : "x86_64";
-#elif __i386__
- return "i386";
#else
#error unknown arch
#endif
@@ -825,6 +873,10 @@
if ( basePlatform )
*basePlatform = Platform::tvOS;
return true;
+ case Platform::visionOS_simulator:
+ if ( basePlatform )
+ *basePlatform = Platform::visionOS;
+ return true;
default:
return false;
}
@@ -838,6 +890,7 @@
case Platform::iOS_simulator:
case Platform::watchOS_simulator:
case Platform::tvOS_simulator:
+ case Platform::visionOS_simulator:
result = true;
break;
default:
@@ -1261,6 +1314,8 @@
break;
}
});
+ (void)count;
+ (void)stopped;
#if !BUILDING_SHARED_CACHE_UTIL && !BUILDING_DYLDINFO && !BUILDING_UNIT_TESTS
// everything must link with something
if ( (count == 0) && !stopped ) {
@@ -1274,6 +1329,12 @@
if ( !this->isDylib() || (strncmp(this->installName(), "/System/DriverKit/usr/lib/system/", 33) != 0) )
callback("/System/DriverKit/usr/lib/libSystem.B.dylib", false, false, false, 0x00010000, 0x00010000, stopped);
}
+ else if ( this->builtForPlatform(Platform::macOSExclaveKit, true)
+ || this->builtForPlatform(Platform::iOSExclaveKit, true)
+ || this->builtForPlatform(Platform::tvOSExclaveKit, true) ) {
+ // do nothing for ExclaveKit dylibs
+ // FIXME: only allow this behavior on internal builds
+ }
else {
if ( !this->isDylib() || (strncmp(this->installName(), "/usr/lib/system/", 16) != 0) )
callback("/usr/lib/libSystem.B.dylib", false, false, false, 0x00010000, 0x00010000, stopped);
@@ -1291,7 +1352,7 @@
if ( cmd->cmd == LC_DYLD_ENVIRONMENT ) {
const dylinker_command* envCmd = (dylinker_command*)cmd;
const char* keyEqualsValue = (char*)envCmd + envCmd->name.offset;
- // only process variables that start with DYLD_ and end in _PATH
+ // only process variables that start with DYLD_
if ( (strncmp(keyEqualsValue, "DYLD_", 5) == 0) ) {
const char* equals = strchr(keyEqualsValue, '=');
if ( equals != NULL ) {
@@ -1332,6 +1393,20 @@
case Platform::iOSMac:
result = false;
break;
+ case Platform::visionOS:
+ case Platform::visionOS_simulator:
+ result = false;
+ break;
+ case Platform::macOSExclaveCore:
+ case Platform::macOSExclaveKit:
+ case Platform::iOSExclaveCore:
+ case Platform::iOSExclaveKit:
+ case Platform::tvOSExclaveCore:
+ case Platform::tvOSExclaveKit:
+ result = false;
+ break;
+
+
case Platform::unknown:
break;
}
@@ -1658,7 +1733,7 @@
return (this->flags & MH_HAS_TLV_DESCRIPTORS);
}
-#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
+#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS || BUILDING_UNIT_TESTS || BUILDING_DYLD_SYMBOLS_CACHE
static bool endsWith(const char* str, const char* suffix)
{
size_t strLen = strlen(str);
@@ -1739,6 +1814,113 @@
return platformExcludesSharedCache_iOS(installName);
}
+#if !BUILDING_DYLD
+
+bool MachOFile::addendsExceedPatchTableLimit(Diagnostics& diag, mach_o::Fixups fixups) const
+{
+ // rdar://122906481 (Shared cache builder - explicitly model dylibs without a need for a patch table)
+ if ( strcmp(installName(), "/usr/lib/libswiftPrespecialized.dylib") == 0 )
+ return false;
+
+ const bool is64bit = is64();
+ const uint64_t tooLargeRegularAddend = 1 << 23;
+ const uint64_t tooLargeAuthAddend = 1 << 5;
+ __block bool addendTooLarge = false;
+ if ( this->hasChainedFixups() ) {
+
+ // with chained fixups, addends can be in the import table or embedded in a bind pointer
+ __block std::vector<uint64_t> targetAddends;
+ fixups.forEachChainedFixupTarget(diag, ^(int libOrdinal, const char* symbolName, uint64_t addend, bool weakImport, bool& stop) {
+ if ( is64bit )
+ addend &= 0x00FFFFFFFFFFFFFF; // ignore TBI
+ targetAddends.push_back(addend);
+ });
+ // check each pointer for embedded addend
+ fixups.withChainStarts(diag, ^(const dyld_chained_starts_in_image* starts) {
+ fixups.forEachFixupInAllChains(diag, starts, false, ^(mach_o::ChainedFixupPointerOnDisk* fixupLoc, uint64_t fixupSegmentOffset, const dyld_chained_starts_in_segment* segInfo, bool& stop) {
+ switch (segInfo->pointer_format) {
+ case DYLD_CHAINED_PTR_ARM64E:
+ case DYLD_CHAINED_PTR_ARM64E_USERLAND:
+ if ( fixupLoc->arm64e.bind.bind ) {
+ uint64_t ordinal = fixupLoc->arm64e.bind.ordinal;
+ uint64_t addend = (ordinal < targetAddends.size()) ? targetAddends[ordinal] : 0;
+ if ( fixupLoc->arm64e.bind.auth ) {
+ if ( addend >= tooLargeAuthAddend ) {
+ addendTooLarge = true;
+ stop = true;
+ }
+ } else {
+ addend += fixupLoc->arm64e.signExtendedAddend();
+ if ( addend >= tooLargeRegularAddend ) {
+ addendTooLarge = true;
+ stop = true;
+ }
+ }
+ }
+ break;
+ case DYLD_CHAINED_PTR_ARM64E_USERLAND24:
+ if ( fixupLoc->arm64e.bind24.bind ) {
+ uint64_t ordinal = fixupLoc->arm64e.bind24.ordinal;
+ uint64_t addend = (ordinal < targetAddends.size()) ? targetAddends[ordinal] : 0;
+ if ( fixupLoc->arm64e.bind24.auth ) {
+ if ( addend >= tooLargeAuthAddend ) {
+ addendTooLarge = true;
+ stop = true;
+ }
+ } else {
+ addend += fixupLoc->arm64e.signExtendedAddend();
+ if ( addend >= tooLargeRegularAddend ) {
+ addendTooLarge = true;
+ stop = true;
+ }
+ }
+ }
+ break;
+ case DYLD_CHAINED_PTR_64:
+ case DYLD_CHAINED_PTR_64_OFFSET: {
+ if ( fixupLoc->generic64.rebase.bind ) {
+ uint64_t ordinal = fixupLoc->generic64.bind.ordinal;
+ uint64_t addend = (ordinal < targetAddends.size()) ? targetAddends[ordinal] : 0;
+ addend += fixupLoc->generic64.bind.addend;
+ if ( addend >= tooLargeRegularAddend ) {
+ addendTooLarge = true;
+ stop = true;
+ }
+ }
+ break;
+ }
+ case DYLD_CHAINED_PTR_32:
+ if ( fixupLoc->generic32.bind.bind ) {
+ uint64_t ordinal = fixupLoc->generic32.bind.ordinal;
+ uint64_t addend = (ordinal < targetAddends.size()) ? targetAddends[ordinal] : 0;
+ addend += fixupLoc->generic32.bind.addend;
+ if ( addend >= tooLargeRegularAddend ) {
+ addendTooLarge = true;
+ stop = true;
+ }
+ }
+ break;
+ }
+ });
+ });
+ }
+ else {
+ // scan bind opcodes for large addend
+ auto handler = ^(const mach_o::Fixups::BindTargetInfo &info, bool &stop) {
+ uint64_t addend = info.addend;
+ if ( is64bit )
+ addend &= 0x00FFFFFFFFFFFFFF; // ignore TBI
+ if ( addend >= tooLargeRegularAddend ) {
+ addendTooLarge = true;
+ stop = true;
+ }
+ };
+ fixups.forEachBindTarget_Opcodes(diag, true, handler, handler);
+ }
+
+ return addendTooLarge;
+}
+
bool MachOFile::canBePlacedInDyldCache(const char* path, void (^failureReason)(const char* format, ...)) const
{
if ( !isSharedCacheEligiblePath(path) ) {
@@ -1801,12 +1983,18 @@
// dylib must have extra info for moving DATA and TEXT segments apart
__block bool hasExtraInfo = false;
+ __block bool hasSplitSegMarker = false;
__block bool hasDyldInfo = false;
__block bool hasExportTrie = false;
__block Diagnostics diag;
forEachLoadCommand(diag, ^(const load_command* cmd, bool& stop) {
- if ( cmd->cmd == LC_SEGMENT_SPLIT_INFO )
- hasExtraInfo = true;
+ if ( cmd->cmd == LC_SEGMENT_SPLIT_INFO ) {
+ const linkedit_data_command* sigCmd = (linkedit_data_command*)cmd;
+ if ( sigCmd->datasize == 0 )
+ hasSplitSegMarker = true;
+ else
+ hasExtraInfo = true;
+ }
if ( cmd->cmd == LC_DYLD_INFO_ONLY )
hasDyldInfo = true;
if ( cmd->cmd == LC_DYLD_EXPORTS_TRIE )
@@ -1821,7 +2009,10 @@
if ( ignorePath == path )
return false;
}
- failureReason("Missing split seg info");
+ if ( hasSplitSegMarker )
+ failureReason("Dylib explicitly linked with '-not_for_dyld_shared_cache'");
+ else
+ failureReason("Missing split seg info");
return false;
}
if ( !hasDyldInfo && !hasExportTrie ) {
@@ -1879,6 +2070,16 @@
if ( layout.isSwiftLibrary() && splitSeg.isV1() )
return;
+ // arm64e requires signed class ROs
+ if ( isArch("arm64e") ) {
+ if ( std::optional<uint32_t> flags = layout.getObjcInfoFlags(); flags.has_value() ) {
+ if ( (flags.value() & mach_o::ObjCImageInfo::OBJC_IMAGE_SIGNED_CLASS_RO) == 0 ) {
+ failureReason("arm64e binaries must have signed Objective-C class_ro_t pointers");
+ return;
+ }
+ }
+ }
+
if ( splitSeg.isV1() ) {
// Split seg v1 can only support 1 __DATA, and no other writable segments
__block bool foundBadSegment = false;
@@ -1899,101 +2100,7 @@
// <rdar://problem/57769033> dyld_cache_patchable_location only supports addend in range 0..31
// rdar://96164956 (dyld needs to support arbitrary addends in cache patch table)
- const bool is64bit = is64();
- __block bool addendTooLarge = false;
- const uint64_t tooLargeRegularAddend = 1 << 23;
- const uint64_t tooLargeAuthAddend = 1 << 5;
- if ( this->hasChainedFixups() ) {
-
- // with chained fixups, addends can be in the import table or embedded in a bind pointer
- __block std::vector<uint64_t> targetAddends;
- fixups.forEachChainedFixupTarget(diag, ^(int libOrdinal, const char* symbolName, uint64_t addend, bool weakImport, bool& stop) {
- if ( is64bit )
- addend &= 0x00FFFFFFFFFFFFFF; // ignore TBI
- targetAddends.push_back(addend);
- });
- // check each pointer for embedded addend
- fixups.withChainStarts(diag, ^(const dyld_chained_starts_in_image* starts) {
- fixups.forEachFixupInAllChains(diag, starts, false, ^(mach_o::ChainedFixupPointerOnDisk* fixupLoc, uint64_t fixupSegmentOffset, const dyld_chained_starts_in_segment* segInfo, bool& stop) {
- switch (segInfo->pointer_format) {
- case DYLD_CHAINED_PTR_ARM64E:
- case DYLD_CHAINED_PTR_ARM64E_USERLAND:
- if ( fixupLoc->arm64e.bind.bind ) {
- uint64_t ordinal = fixupLoc->arm64e.bind.ordinal;
- uint64_t addend = (ordinal < targetAddends.size()) ? targetAddends[ordinal] : 0;
- if ( fixupLoc->arm64e.bind.auth ) {
- if ( addend >= tooLargeAuthAddend ) {
- addendTooLarge = true;
- stop = true;
- }
- } else {
- addend += fixupLoc->arm64e.signExtendedAddend();
- if ( addend >= tooLargeRegularAddend ) {
- addendTooLarge = true;
- stop = true;
- }
- }
- }
- break;
- case DYLD_CHAINED_PTR_ARM64E_USERLAND24:
- if ( fixupLoc->arm64e.bind24.bind ) {
- uint64_t ordinal = fixupLoc->arm64e.bind24.ordinal;
- uint64_t addend = (ordinal < targetAddends.size()) ? targetAddends[ordinal] : 0;
- if ( fixupLoc->arm64e.bind24.auth ) {
- if ( addend >= tooLargeAuthAddend ) {
- addendTooLarge = true;
- stop = true;
- }
- } else {
- addend += fixupLoc->arm64e.signExtendedAddend();
- if ( addend >= tooLargeRegularAddend ) {
- addendTooLarge = true;
- stop = true;
- }
- }
- }
- break;
- case DYLD_CHAINED_PTR_64:
- case DYLD_CHAINED_PTR_64_OFFSET: {
- if ( fixupLoc->generic64.rebase.bind ) {
- uint64_t ordinal = fixupLoc->generic64.bind.ordinal;
- uint64_t addend = (ordinal < targetAddends.size()) ? targetAddends[ordinal] : 0;
- addend += fixupLoc->generic64.bind.addend;
- if ( addend >= tooLargeRegularAddend ) {
- addendTooLarge = true;
- stop = true;
- }
- }
- break;
- }
- case DYLD_CHAINED_PTR_32:
- if ( fixupLoc->generic32.bind.bind ) {
- uint64_t ordinal = fixupLoc->generic32.bind.ordinal;
- uint64_t addend = (ordinal < targetAddends.size()) ? targetAddends[ordinal] : 0;
- addend += fixupLoc->generic32.bind.addend;
- if ( addend >= tooLargeRegularAddend ) {
- addendTooLarge = true;
- stop = true;
- }
- }
- break;
- }
- });
- });
- }
- else {
- // scan bind opcodes for large addend
- auto handler = ^(const mach_o::Fixups::BindTargetInfo &info, bool &stop) {
- uint64_t addend = info.addend;
- if ( is64bit )
- addend &= 0x00FFFFFFFFFFFFFF; // ignore TBI
- if ( addend >= tooLargeRegularAddend ) {
- addendTooLarge = true;
- stop = true;
- }
- };
- fixups.forEachBindTarget_Opcodes(diag, true, handler, handler);
- }
+ bool addendTooLarge = addendsExceedPatchTableLimit(diag, fixups);
if ( addendTooLarge ) {
failureReason("bind addend too large");
return;
@@ -2081,8 +2188,144 @@
passedLinkeditChecks = true;
});
- return passedLinkeditChecks;
-}
+ if ( !passedLinkeditChecks )
+ return false;
+
+ // Check there are no pointer based objc method lists in CONST segments
+#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
+ {
+ typedef std::pair<VMAddress, VMAddress> Range;
+ __block std::vector<Range> constRanges;
+ this->forEachSegment(^(const SegmentInfo& info, bool& stop) {
+ if ( info.vmSize == 0 )
+ return;
+ if ( !strcmp(info.segName, "__DATA_CONST") || !strcmp(info.segName, "__AUTH_CONST") )
+ constRanges.push_back({ VMAddress(info.vmAddr), VMAddress(info.vmAddr + info.vmSize) });
+ });
+
+ if ( !constRanges.empty() ) {
+ __block objc_visitor::Visitor objcVisitor = this->makeObjCVisitor(diag);
+ if ( diag.hasError() )
+ return false;
+
+ // Returns true if the method list is bad, ie, a pointer based method list in _CONST segment
+ auto isConstPointerBasedMethodList = ^(const objc_visitor::MethodList& methodList) {
+ if ( (methodList.numMethods() == 0) || methodList.usesRelativeOffsets() )
+ return false;
+
+ VMAddress methodListVMAddr = methodList.getVMAddress().value();
+ for ( const Range& range : constRanges ) {
+ if ( (methodListVMAddr >= range.first) && (methodListVMAddr < range.second) )
+ return true;
+ }
+
+ return false;
+ };
+
+ __block bool hasPointerMethodList = false;
+ objcVisitor.forEachClassAndMetaClass(^(const objc_visitor::Class& objcClass, bool& stopClass) {
+ if ( isConstPointerBasedMethodList(objcClass.getBaseMethods(objcVisitor)) ) {
+ failureReason("has pointer based objc class method list in _CONST segment");
+ hasPointerMethodList = true;
+ stopClass = true;
+ }
+ });
+ if ( hasPointerMethodList )
+ return false;
+
+ objcVisitor.forEachCategory(^(const objc_visitor::Category& objcCategory, bool& stopCategory) {
+ if ( isConstPointerBasedMethodList(objcCategory.getInstanceMethods(objcVisitor)) ) {
+ failureReason("has pointer based objc category instance method list in _CONST segment");
+ hasPointerMethodList = true;
+ stopCategory = true;
+ }
+ if ( isConstPointerBasedMethodList(objcCategory.getClassMethods(objcVisitor)) ) {
+ failureReason("has pointer based objc category class method list in _CONST segment");
+ hasPointerMethodList = true;
+ stopCategory = true;
+ }
+ });
+ if ( hasPointerMethodList )
+ return false;
+ }
+ }
+#endif // BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
+
+ return true;
+}
+
+#if BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
+objc_visitor::Visitor MachOFile::makeObjCVisitor(Diagnostics& diag) const
+{
+ VMAddress dylibBaseAddress(this->preferredLoadAddress());
+
+ __block std::vector<metadata_visitor::Segment> segments;
+ __block std::vector<uint64_t> bindTargets;
+ this->withFileLayout(diag, ^(const mach_o::Layout &layout) {
+ for ( uint32_t segIndex = 0; segIndex != layout.segments.size(); ++segIndex ) {
+ const auto& layoutSegment = layout.segments[segIndex];
+ metadata_visitor::Segment segment {
+ .startVMAddr = VMAddress(layoutSegment.vmAddr),
+ .endVMAddr = VMAddress(layoutSegment.vmAddr + layoutSegment.vmSize),
+ .bufferStart = (uint8_t*)layoutSegment.buffer,
+ .onDiskDylibChainedPointerFormat = 0,
+ .segIndex = segIndex
+ };
+ segments.push_back(std::move(segment));
+ }
+
+ // Add chained fixup info to each segment, if we have it
+ if ( this->hasChainedFixups() ) {
+ mach_o::Fixups fixups(layout);
+ fixups.withChainStarts(diag, ^(const dyld_chained_starts_in_image* starts) {
+ mach_o::Fixups::forEachFixupChainSegment(diag, starts,
+ ^(const dyld_chained_starts_in_segment *segInfo, uint32_t segIndex, bool &stop) {
+ segments[segIndex].onDiskDylibChainedPointerFormat = segInfo->pointer_format;
+ });
+ });
+ }
+
+ // ObjC patching needs the bind targets for interposable references to the classes
+ // build targets table
+ if ( this->hasChainedFixupsLoadCommand() ) {
+ mach_o::Fixups fixups(layout);
+ fixups.forEachBindTarget_ChainedFixups(diag, ^(const mach_o::Fixups::BindTargetInfo &info, bool &stop) {
+ if ( info.libOrdinal != BIND_SPECIAL_DYLIB_SELF ) {
+ bindTargets.push_back(0);
+ return;
+ }
+
+ mach_o::Layout::FoundSymbol foundInfo;
+ if ( !layout.findExportedSymbol(diag, info.symbolName, info.weakImport, foundInfo) ) {
+ bindTargets.push_back(0);
+ return;
+ }
+
+ // We only support header offsets in this dylib, as we are looking for self binds
+ // which are likely only to classes
+ if ( (foundInfo.kind != mach_o::Layout::FoundSymbol::Kind::headerOffset)
+ || (foundInfo.foundInDylib.value() != this) ) {
+ bindTargets.push_back(0);
+ return;
+ }
+
+ uint64_t vmAddr = layout.textUnslidVMAddr() + foundInfo.value;
+ bindTargets.push_back(vmAddr);
+ });
+ }
+ });
+
+ std::optional<VMAddress> selectorStringsBaseAddress;
+ objc_visitor::Visitor objcVisitor(dylibBaseAddress, this,
+ std::move(segments), selectorStringsBaseAddress,
+ std::move(bindTargets));
+
+ return objcVisitor;
+}
+#endif // BUILDING_CACHE_BUILDER || BUILDING_CACHE_BUILDER_UNIT_TESTS
+
+#endif // !BUILDING_DYLD
+
// Returns true if the executable path is eligible for a PrebuiltLoader on the given platform.
bool MachOFile::canHavePrebuiltExecutableLoader(dyld3::Platform platform, const std::string_view& path,
@@ -2122,12 +2365,6 @@
if ( !inSearchDir ) {
failureReason("path not eligible");
- return false;
- }
- } else {
- // On embedded, only staged apps are excluded. They will run from a different location at runtime
- if ( path.find("/staged_system_apps/") != std::string::npos ) {
- // Dont spam the user with an error about paths when we know these are never eligible.
return false;
}
}
@@ -2717,7 +2954,7 @@
});
}
-const MachOFile* MachOFile::compatibleSlice(Diagnostics& diag, const void* fileContent, size_t contentSize, const char* path, Platform platform, bool isOSBinary, const GradedArchs& archs, bool internalInstall)
+const MachOFile* MachOFile::compatibleSlice(Diagnostics& diag, uint64_t& sliceLenOut, const void* fileContent, size_t contentSize, const char* path, Platform platform, bool isOSBinary, const GradedArchs& archs, bool internalInstall)
{
const MachOFile* mf = nullptr;
if ( const dyld3::FatFile* ff = dyld3::FatFile::isFatFile(fileContent) ) {
@@ -2726,6 +2963,7 @@
bool missingSlice;
if ( ff->isFatFileWithSlice(diag, contentSize, archs, isOSBinary, sliceOffset, sliceLen, missingSlice) ) {
mf = (MachOFile*)((long)fileContent + sliceOffset);
+ sliceLenOut = sliceLen;
}
else {
BLOCK_ACCCESSIBLE_ARRAY(char, gradedArchsBuf, 256);
@@ -2738,6 +2976,7 @@
}
else {
mf = (MachOFile*)fileContent;
+ sliceLenOut = contentSize;
}
if ( !mf->hasMachOMagic() || !mf->isMachO(diag, contentSize) ) {
@@ -3384,7 +3623,7 @@
&& (this->usesAddrDiversity == other.usesAddrDiversity);
}
-#if !SUPPORT_VM_LAYOUT
+#if !SUPPORT_VM_LAYOUT || BUILDING_UNIT_TESTS || BUILDING_DYLD_SYMBOLS_CACHE
bool MachOFile::getLinkeditLayout(Diagnostics& diag, mach_o::LinkeditLayout& layout) const
{
// Note, in file layout all linkedit offsets are just file offsets.
@@ -3850,6 +4089,16 @@
case Platform::driverKit:
result = true;
break;
+ case Platform::visionOS:
+ case Platform::visionOS_simulator:
+ result = true; // do all checks by default
+ if ( kind == Malformed::sdkOnOrAfter2022 ) {
+ if (sdk < 0x00020000) // visionOS 2.0 FIXME
+ result = false;
+ }
+ break;
+
+
default:
result = true;
break;