Loading...
--- dyld/dyld-852.2/dyld3/MachOFile.cpp
+++ dyld/dyld-732.8/dyld3/MachOFile.cpp
@@ -25,11 +25,6 @@
#include <assert.h>
#include <string.h>
#include <stdio.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <sys/errno.h>
-#include <sys/fcntl.h>
-#include <unistd.h>
#include <TargetConditionals.h>
#include <mach/host_info.h>
#include <mach/mach.h>
@@ -39,49 +34,8 @@
#include "MachOFile.h"
#include "SupportedArchs.h"
-#if BUILDING_DYLD || BUILDING_LIBDYLD
- // define away restrict until rdar://60166935 is fixed
- #define restrict
- #include <subsystem.h>
-#endif
namespace dyld3 {
-
-//////////////////////////// posix wrappers ////////////////////////////////////////
-
-// <rdar://problem/10111032> wrap calls to stat() with check for EAGAIN
-int stat(const char* path, struct stat* buf)
-{
- int result;
- do {
-#if BUILDING_DYLD || BUILDING_LIBDYLD
- result = ::stat_with_subsystem(path, buf);
-#else
- result = ::stat(path, buf);
-#endif
- } while ((result == -1) && ((errno == EAGAIN) || (errno == EINTR)));
-
- return result;
-}
-
-// <rdar://problem/13805025> dyld should retry open() if it gets an EGAIN
-int open(const char* path, int flag, int other)
-{
- int result;
- do {
-#if BUILDING_DYLD || BUILDING_LIBDYLD
- if (flag & O_CREAT)
- result = ::open(path, flag, other);
- else
- result = ::open_with_subsystem(path, flag);
-#else
- result = ::open(path, flag, other);
-#endif
- } while ((result == -1) && ((errno == EAGAIN) || (errno == EINTR)));
-
- return result;
-}
-
//////////////////////////// FatFile ////////////////////////////////////////
@@ -176,8 +130,7 @@
}
}
-bool FatFile::isFatFileWithSlice(Diagnostics& diag, uint64_t fileLen, const GradedArchs& archs, bool isOSBinary,
- uint64_t& sliceOffset, uint64_t& sliceLen, bool& missingSlice) const
+bool FatFile::isFatFileWithSlice(Diagnostics& diag, uint64_t fileLen, const GradedArchs& archs, uint64_t& sliceOffset, uint64_t& sliceLen, bool& missingSlice) const
{
missingSlice = false;
if ( (this->magic != OSSwapBigToHostInt32(FAT_MAGIC)) && (this->magic != OSSwapBigToHostInt32(FAT_MAGIC_64)) )
@@ -185,7 +138,7 @@
__block int bestGrade = 0;
forEachSlice(diag, fileLen, ^(uint32_t sliceCpuType, uint32_t sliceCpuSubType, const void* sliceStart, uint64_t sliceSize, bool& stop) {
- if (int sliceGrade = archs.grade(sliceCpuType, sliceCpuSubType, isOSBinary)) {
+ if (int sliceGrade = archs.grade(sliceCpuType, sliceCpuSubType)) {
if ( sliceGrade > bestGrade ) {
sliceOffset = (char*)sliceStart - (char*)this;
sliceLen = sliceSize;
@@ -205,47 +158,26 @@
//////////////////////////// GradedArchs ////////////////////////////////////////
-
-#define GRADE_i386 CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL, false
-#define GRADE_x86_64 CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL, false
-#define GRADE_x86_64h CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_H, false
-#define GRADE_armv7 CPU_TYPE_ARM, CPU_SUBTYPE_ARM64_ALL, false
-#define GRADE_armv7s CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7, false
-#define GRADE_armv7k CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7K, false
-#define GRADE_arm64 CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL, false
-#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 = { {{GRADE_i386, 1}} };
-const GradedArchs GradedArchs::x86_64 = { {{GRADE_x86_64, 1}} };
-const GradedArchs GradedArchs::x86_64h = { {{GRADE_x86_64h, 2}, {GRADE_x86_64, 1}} };
-const GradedArchs GradedArchs::arm64 = { {{GRADE_arm64, 1}} };
+const GradedArchs GradedArchs::i386 = { {{CPU_TYPE_I386, CPU_SUBTYPE_I386_ALL, 1}} };
+const GradedArchs GradedArchs::x86_64 = { {{CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL, 1}} };
+const GradedArchs GradedArchs::x86_64h = { {{CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_H, 2}, {CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL, 1}}, };
+const GradedArchs GradedArchs::arm64 = { {{CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL, 1}} };
#if SUPPORT_ARCH_arm64e
-const GradedArchs GradedArchs::arm64e_keysoff = { {{GRADE_arm64e, 2}, {GRADE_arm64, 1}} };
-const GradedArchs GradedArchs::arm64e_keysoff_pb = { {{GRADE_arm64e_pb, 2}, {GRADE_arm64, 1}} };
-const GradedArchs GradedArchs::arm64e = { {{GRADE_arm64e, 1}} };
-const GradedArchs GradedArchs::arm64e_pb = { {{GRADE_arm64e_pb, 1}} };
+const GradedArchs GradedArchs::arm64e_compat = { {{CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64E, 2}, {CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64_ALL, 1}} };
+const GradedArchs GradedArchs::arm64e = { {{CPU_TYPE_ARM64, CPU_SUBTYPE_ARM64E, 1}} };
#endif
-const GradedArchs GradedArchs::armv7 = { {{GRADE_armv7, 1}} };
-const GradedArchs GradedArchs::armv7s = { {{GRADE_armv7s, 2}, {GRADE_armv7, 1}} };
-const GradedArchs GradedArchs::armv7k = { {{GRADE_armv7k, 1}} };
+const GradedArchs GradedArchs::armv7k = { {{CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7K, 1}} };
+const GradedArchs GradedArchs::armv7 = { {{CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7, 1}} };
+const GradedArchs GradedArchs::armv7s = { {{CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7S, 2}, {CPU_TYPE_ARM, CPU_SUBTYPE_ARM_V7, 1}} };
#if SUPPORT_ARCH_arm64_32
-const GradedArchs GradedArchs::arm64_32 = { {{GRADE_arm64_32, 1}} };
+const GradedArchs GradedArchs::arm64_32 = { {{CPU_TYPE_ARM64_32, CPU_SUBTYPE_ARM64_32_V8, 1}} };
#endif
-int GradedArchs::grade(uint32_t cputype, uint32_t cpusubtype, bool isOSBinary) const
+int GradedArchs::grade(uint32_t cputype, uint32_t cpusubtype) const
{
for (const CpuGrade* p = _orderedCpuTypes; p->type != 0; ++p) {
- if ( (p->type == cputype) && (p->subtype == (cpusubtype & ~CPU_SUBTYPE_MASK)) ) {
- if ( p->osBinary ) {
- if ( isOSBinary )
- return p->grade;
- }
- else {
- return p->grade;
- }
- }
+ if ( (p->type == cputype) && (p->subtype == (cpusubtype & ~CPU_SUBTYPE_MASK)) )
+ return p->grade;
}
return 0;
}
@@ -274,13 +206,13 @@
}
#endif
-const GradedArchs& GradedArchs::forCurrentOS(bool keysOff, bool osBinariesOnly)
+const GradedArchs& GradedArchs::forCurrentOS(const MachOFile* mainExecutable)
{
#if __arm64e__
- if ( osBinariesOnly )
- return (keysOff ? arm64e_keysoff_pb : arm64e_pb);
+ if ( mainExecutable->cpusubtype < CPU_SUBTYPE_ARM64E )
+ return arm64e_compat;
else
- return (keysOff ? arm64e_keysoff : arm64e);
+ return arm64e;
#elif __ARM64_ARCH_8_32__
return arm64_32;
#elif __arm64__
@@ -300,7 +232,7 @@
#endif
}
-const GradedArchs& GradedArchs::forName(const char* archName, bool keysOff)
+const GradedArchs& GradedArchs::forName(const char* archName, bool forMainExecutable)
{
if (strcmp(archName, "x86_64h") == 0 )
return x86_64h;
@@ -308,7 +240,7 @@
return x86_64;
#if SUPPORT_ARCH_arm64e
else if (strcmp(archName, "arm64e") == 0 )
- return keysOff ? arm64e_keysoff : arm64e;
+ return forMainExecutable ? arm64e_compat : arm64e;
#endif
else if (strcmp(archName, "arm64") == 0 )
return arm64;
@@ -328,7 +260,6 @@
}
-
//////////////////////////// MachOFile ////////////////////////////////////////
@@ -354,7 +285,7 @@
{ "tvOS", Platform::tvOS, LC_VERSION_MIN_TVOS },
{ "watchOS", Platform::watchOS, LC_VERSION_MIN_WATCHOS },
{ "bridgeOS", Platform::bridgeOS, LC_BUILD_VERSION },
- { "MacCatalyst", Platform::iOSMac, LC_BUILD_VERSION },
+ { "UIKitForMac", Platform::iOSMac, LC_BUILD_VERSION },
{ "iOS-sim", Platform::iOS_simulator, LC_BUILD_VERSION },
{ "tvOS-sim", Platform::tvOS_simulator, LC_BUILD_VERSION },
{ "watchOS-sim", Platform::watchOS_simulator, LC_BUILD_VERSION },
@@ -372,10 +303,6 @@
return is64() ? sizeof(mach_header_64) : sizeof(mach_header);
}
-uint32_t MachOFile::maskedCpuSubtype() const
-{
- return (this->cpusubtype & ~CPU_SUBTYPE_MASK);
-}
uint32_t MachOFile::pointerSize() const
{
@@ -477,82 +404,31 @@
*s++ = '\0';
}
-bool MachOFile::builtForPlatform(Platform reqPlatform, bool onlyOnePlatform) const
+bool MachOFile::supportsPlatform(Platform reqPlatform) const
{
__block bool foundRequestedPlatform = false;
- __block bool foundOtherPlatform = false;
+ __block bool foundOtherPlatform = false;
forEachSupportedPlatform(^(Platform platform, uint32_t minOS, uint32_t sdk) {
if ( platform == reqPlatform )
foundRequestedPlatform = true;
else
foundOtherPlatform = true;
});
- // if checking that this binary is built for exactly one platform, fail if more
- if ( foundOtherPlatform && onlyOnePlatform )
- return false;
if ( foundRequestedPlatform )
return true;
+ // we did find some platform info, but not requested, so return false
+ if ( foundOtherPlatform )
+ return false;
+
// binary has no explict load command to mark platform
// could be an old macOS binary, look at arch
- if ( !foundOtherPlatform && (reqPlatform == Platform::macOS) ) {
+ if ( reqPlatform == Platform::macOS ) {
if ( this->cputype == CPU_TYPE_X86_64 )
return true;
if ( this->cputype == CPU_TYPE_I386 )
return true;
}
-
-#if BUILDING_DYLDINFO
- // Allow offline tools to analyze binaries dyld doesn't load, ie, those with platforms
- if ( !foundOtherPlatform && (reqPlatform == Platform::unknown) )
- return true;
-#endif
-
- return false;
-}
-
-bool MachOFile::loadableIntoProcess(Platform processPlatform, const char* path) const
-{
- if ( this->builtForPlatform(processPlatform) )
- return true;
-
- // Some host macOS dylibs can be loaded into simulator processes
- if ( MachOFile::isSimulatorPlatform(processPlatform) && this->builtForPlatform(Platform::macOS)) {
- static const char* macOSHost[] = {
- "/usr/lib/system/libsystem_kernel.dylib",
- "/usr/lib/system/libsystem_platform.dylib",
- "/usr/lib/system/libsystem_pthread.dylib",
- "/usr/lib/system/libsystem_platform_debug.dylib",
- "/usr/lib/system/libsystem_pthread_debug.dylib",
- "/usr/lib/system/host/liblaunch_sim.dylib",
- };
- for (const char* libPath : macOSHost) {
- if (strcmp(libPath, path) == 0)
- return true;
- }
- }
-
- // If this is being called on main executable where we expect a macOS program, Catalyst programs are also runnable
- if ( (this->filetype == MH_EXECUTE) && (processPlatform == Platform::macOS) && this->builtForPlatform(Platform::iOSMac, true) )
- return true;
-#if (TARGET_OS_OSX && TARGET_CPU_ARM64)
- if ( (this->filetype == MH_EXECUTE) && (processPlatform == Platform::macOS) && this->builtForPlatform(Platform::iOS, true) )
- return true;
-#endif
-
- bool iOSonMac = (processPlatform == Platform::iOSMac);
-#if (TARGET_OS_OSX && TARGET_CPU_ARM64)
- // allow iOS binaries in iOSApp
- if ( processPlatform == Platform::iOS ) {
- // can load Catalyst binaries into iOS process
- if ( this->builtForPlatform(Platform::iOSMac) )
- return true;
- iOSonMac = true;
- }
-#endif
- // macOS dylibs can be loaded into iOSMac processes
- if ( (iOSonMac) && this->builtForPlatform(Platform::macOS, true) )
- return true;
return false;
}
@@ -593,10 +469,8 @@
return Platform::tvOS;
#elif TARGET_OS_IOS
return Platform::iOS;
-#elif TARGET_OS_OSX
+#elif TARGET_OS_MAC
return Platform::macOS;
-#elif TARGET_OS_DRIVERKIT
- return Platform::driverKit;
#else
#error unknown platform
#endif
@@ -666,16 +540,6 @@
// static executables do not have dyld load command
return !hasLoadCommand(LC_LOAD_DYLINKER);
-}
-
-bool MachOFile::isKextBundle() const
-{
- return (this->filetype == MH_KEXT_BUNDLE);
-}
-
-bool MachOFile::isFileSet() const
-{
- return (this->filetype == MH_FILESET);
}
bool MachOFile::isPIE() const
@@ -795,52 +659,6 @@
}
}
-void MachOFile::removeLoadCommand(Diagnostics& diag, void (^callback)(const load_command* cmd, bool& remove, bool& stop))
-{
- bool stop = false;
- const load_command* startCmds = nullptr;
- if ( this->magic == MH_MAGIC_64 )
- startCmds = (load_command*)((char *)this + sizeof(mach_header_64));
- else if ( this->magic == MH_MAGIC )
- startCmds = (load_command*)((char *)this + sizeof(mach_header));
- else if ( hasMachOBigEndianMagic() )
- return; // can't process big endian mach-o
- else {
- const uint32_t* h = (uint32_t*)this;
- diag.error("file does not start with MH_MAGIC[_64]: 0x%08X 0x%08X", h[0], h [1]);
- return; // not a mach-o file
- }
- const load_command* const cmdsEnd = (load_command*)((char*)startCmds + this->sizeofcmds);
- auto cmd = (load_command*)startCmds;
- const uint32_t origNcmds = this->ncmds;
- unsigned bytesRemaining = this->sizeofcmds;
- for (uint32_t i = 0; i < origNcmds; ++i) {
- bool remove = false;
- auto nextCmd = (load_command*)((char *)cmd + cmd->cmdsize);
- if ( cmd->cmdsize < 8 ) {
- diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) too small", i, this->ncmds, cmd, this, cmd->cmdsize);
- return;
- }
- if ( (nextCmd > cmdsEnd) || (nextCmd < startCmds) ) {
- diag.error("malformed load command #%d of %d at %p with mh=%p, size (0x%X) is too large, load commands end at %p", i, this->ncmds, cmd, this, cmd->cmdsize, cmdsEnd);
- return;
- }
- callback(cmd, remove, stop);
- if ( remove ) {
- this->sizeofcmds -= cmd->cmdsize;
- ::memmove((void*)cmd, (void*)nextCmd, bytesRemaining);
- this->ncmds--;
- } else {
- bytesRemaining -= cmd->cmdsize;
- cmd = nextCmd;
- }
- if ( stop )
- break;
- }
- if ( cmd )
- ::bzero(cmd, bytesRemaining);
-}
-
const char* MachOFile::installName() const
{
const char* name;
@@ -962,48 +780,6 @@
}
});
return result;
-}
-
-const thread_command* MachOFile::unixThreadLoadCommand() const {
- Diagnostics diag;
- __block const thread_command* command = nullptr;
- forEachLoadCommand(diag, ^(const load_command* cmd, bool& stop) {
- if ( cmd->cmd == LC_UNIXTHREAD ) {
- command = (const thread_command*)cmd;
- stop = true;
- }
- });
- return command;
-}
-
-
-uint32_t MachOFile::entryAddrRegisterIndexForThreadCmd() const
-{
- switch ( this->cputype ) {
- case CPU_TYPE_I386:
- return 10; // i386_thread_state_t.eip
- case CPU_TYPE_X86_64:
- return 16; // x86_thread_state64_t.rip
- case CPU_TYPE_ARM:
- return 15; // arm_thread_state_t.pc
- case CPU_TYPE_ARM64:
- return 32; // arm_thread_state64_t.__pc
- }
- return ~0U;
-}
-
-
-uint64_t MachOFile::entryAddrFromThreadCmd(const thread_command* cmd) const
-{
- assert(cmd->cmd == LC_UNIXTHREAD);
- const uint32_t* regs32 = (uint32_t*)(((char*)cmd) + 16);
- const uint64_t* regs64 = (uint64_t*)(((char*)cmd) + 16);
-
- uint32_t index = entryAddrRegisterIndexForThreadCmd();
- if (index == ~0U)
- return 0;
-
- return is64() ? regs64[index] : regs32[index];
}
@@ -1205,94 +981,8 @@
|| (strncmp(dylibName, "/Library/Apple/System/Library/", 30) == 0) );
}
-static bool startsWith(const char* buffer, const char* valueToFind) {
- return strncmp(buffer, valueToFind, strlen(valueToFind)) == 0;
-}
-
-static bool platformExcludesSharedCache_macOS(const char* installName) {
- // Note: This function basically matches dontCache() from update dyld shared cache
-
- if ( startsWith(installName, "/usr/lib/system/introspection/") )
- return true;
- if ( startsWith(installName, "/System/Library/QuickTime/") )
- return true;
- if ( startsWith(installName, "/System/Library/Tcl/") )
- return true;
- if ( startsWith(installName, "/System/Library/Perl/") )
- return true;
- if ( startsWith(installName, "/System/Library/MonitorPanels/") )
- return true;
- if ( startsWith(installName, "/System/Library/Accessibility/") )
- return true;
- if ( startsWith(installName, "/usr/local/") )
- return true;
- if ( startsWith(installName, "/usr/lib/pam/") )
- return true;
- // We no longer support ROSP, so skip all paths which start with the special prefix
- if ( startsWith(installName, "/System/Library/Templates/Data/") )
- return true;
-
- // anything inside a .app bundle is specific to app, so should not be in shared cache
- if ( strstr(installName, ".app/") != NULL )
- return true;
-
- return false;
-}
-
-static bool platformExcludesSharedCache_iOS(const char* installName) {
- if ( strcmp(installName, "/System/Library/Caches/com.apple.xpc/sdk.dylib") == 0 )
- return true;
- if ( strcmp(installName, "/System/Library/Caches/com.apple.xpcd/xpcd_cache.dylib") == 0 )
- return true;
- return false;
-}
-
-static bool platformExcludesSharedCache_tvOS(const char* installName) {
- return platformExcludesSharedCache_iOS(installName);
-}
-
-static bool platformExcludesSharedCache_watchOS(const char* installName) {
- return platformExcludesSharedCache_iOS(installName);
-}
-
-static bool platformExcludesSharedCache_bridgeOS(const char* installName) {
- return platformExcludesSharedCache_iOS(installName);
-}
-
-// Returns true if the current platform requires that this install name be excluded from the shared cache
-// Note that this overrides any exclusion from anywhere else.
-static bool platformExcludesSharedCache(Platform platform, const char* installName) {
- switch (platform) {
- case dyld3::Platform::unknown:
- return false;
- case dyld3::Platform::macOS:
- return platformExcludesSharedCache_macOS(installName);
- case dyld3::Platform::iOS:
- return platformExcludesSharedCache_iOS(installName);
- case dyld3::Platform::tvOS:
- return platformExcludesSharedCache_tvOS(installName);
- case dyld3::Platform::watchOS:
- return platformExcludesSharedCache_watchOS(installName);
- case dyld3::Platform::bridgeOS:
- return platformExcludesSharedCache_bridgeOS(installName);
- case dyld3::Platform::iOSMac:
- return platformExcludesSharedCache_macOS(installName);
- case dyld3::Platform::iOS_simulator:
- return false;
- case dyld3::Platform::tvOS_simulator:
- return false;
- case dyld3::Platform::watchOS_simulator:
- return false;
- case dyld3::Platform::driverKit:
- return false;
- }
-}
-
-
-
bool MachOFile::canBePlacedInDyldCache(const char* path, void (^failureReason)(const char*)) const
{
-
if ( !isSharedCacheEligiblePath(path) ) {
// Dont spam the user with an error about paths when we know these are never eligible.
return false;
@@ -1316,28 +1006,6 @@
failureReason("install path does not match install name");
return false;
}
- else if ( strstr(dylibName, "//") != 0 ) {
- failureReason("install name should not include //");
- return false;
- }
- else if ( strstr(dylibName, "./") != 0 ) {
- failureReason("install name should not include ./");
- return false;
- }
-
- __block bool platformExcludedFile = false;
- forEachSupportedPlatform(^(Platform platform, uint32_t minOS, uint32_t sdk) {
- if ( platformExcludedFile )
- return;
- if ( platformExcludesSharedCache(platform, dylibName) ) {
- platformExcludedFile = true;
- return;
- }
- });
- if ( platformExcludedFile ) {
- failureReason("install name is not shared cache eligible on platform");
- return false;
- }
bool retval = true;
@@ -1357,7 +1025,6 @@
__block bool hasExtraInfo = false;
__block bool hasDyldInfo = false;
__block bool hasExportTrie = false;
- __block bool hasLazyLoad = false;
Diagnostics diag;
forEachLoadCommand(diag, ^(const load_command* cmd, bool& stop) {
if ( cmd->cmd == LC_SEGMENT_SPLIT_INFO )
@@ -1366,8 +1033,6 @@
hasDyldInfo = true;
if ( cmd->cmd == LC_DYLD_EXPORTS_TRIE )
hasExportTrie = true;
- if ( cmd->cmd == LC_LAZY_LOAD_DYLIB )
- hasLazyLoad = true;
});
if ( !hasExtraInfo ) {
retval = false;
@@ -1376,10 +1041,6 @@
if ( !hasDyldInfo && !hasExportTrie ) {
retval = false;
failureReason("Old binary, missing dyld info or export trie");
- }
- if ( hasLazyLoad ) {
- retval = false;
- failureReason("Has lazy load");
}
// dylib can only depend on other dylibs in the shared cache
@@ -1396,259 +1057,27 @@
}
// dylibs with interposing info cannot be in cache
- if ( hasInterposingTuples() ) {
- retval = false;
- failureReason("Has interposing tuples");
- }
-
- // Temporarily kick out swift binaries out of dyld cache on watchOS simulators as they have missing split seg
- if ( (this->cputype == CPU_TYPE_I386) && builtForPlatform(Platform::watchOS_simulator) ) {
- if ( strncmp(dylibName, "/usr/lib/swift/", 15) == 0 ) {
- retval = false;
- failureReason("i386 swift binary");
- }
- }
-
- return retval;
-}
-
-#if BUILDING_APP_CACHE_UTIL
-bool MachOFile::canBePlacedInKernelCollection(const char* path, void (^failureReason)(const char*)) const
-{
- // only dylibs and the kernel itself can go in cache
- if ( this->filetype == MH_EXECUTE ) {
- // xnu
- } else if ( this->isKextBundle() ) {
- // kext's
- } else {
- failureReason("Not MH_KEXT_BUNDLE");
- return false;
- }
-
- if ( this->filetype == MH_EXECUTE ) {
- // xnu
-
- // two-level namespace binaries cannot go in cache
- if ( (this->flags & MH_TWOLEVEL) != 0 ) {
- failureReason("Built with two level namespaces");
- return false;
- }
-
- // xnu kernel cannot have a page zero
- __block bool foundPageZero = false;
- forEachSegment(^(const SegmentInfo &segmentInfo, bool &stop) {
- if ( strcmp(segmentInfo.segName, "__PAGEZERO") == 0 ) {
- foundPageZero = true;
- stop = true;
- }
- });
- if (foundPageZero) {
- failureReason("Has __PAGEZERO");
- return false;
- }
-
- // xnu must have an LC_UNIXTHREAD to point to the entry point
- __block bool foundMainLC = false;
- __block bool foundUnixThreadLC = false;
- Diagnostics diag;
- forEachLoadCommand(diag, ^(const load_command* cmd, bool& stop) {
- if ( cmd->cmd == LC_MAIN ) {
- foundMainLC = true;
- stop = true;
- }
- else if ( cmd->cmd == LC_UNIXTHREAD ) {
- foundUnixThreadLC = true;
- }
- });
- if (foundMainLC) {
- failureReason("Found LC_MAIN");
- return false;
- }
- if (!foundUnixThreadLC) {
- failureReason("Expected LC_UNIXTHREAD");
- return false;
- }
-
- if (diag.hasError()) {
- failureReason("Error parsing load commands");
- return false;
- }
-
- // The kernel should be a static executable, not a dynamic one
- if ( !isStaticExecutable() ) {
- failureReason("Expected static executable");
- return false;
- }
-
- // The kernel must be built with -pie
- if ( !isPIE() ) {
- failureReason("Expected pie");
- return false;
- }
- }
-
- if ( isArch("arm64e") && isKextBundle() && !hasChainedFixups() ) {
- failureReason("Missing fixup information");
- return false;
- }
-
- // dylibs with interposing info cannot be in cache
__block bool hasInterposing = false;
forEachSection(^(const SectionInfo& info, bool malformedSectionRange, bool &stop) {
if ( ((info.sectFlags & SECTION_TYPE) == S_INTERPOSING) || ((strcmp(info.sectName, "__interpose") == 0) && (strcmp(info.segInfo.segName, "__DATA") == 0)) )
hasInterposing = true;
});
if ( hasInterposing ) {
+ retval = false;
failureReason("Has interposing tuples");
- return false;
- }
-
- // Only x86_64 is allowed to have RWX segments
- if ( !isArch("x86_64") && !isArch("x86_64h") ) {
- __block bool foundBadSegment = false;
- forEachSegment(^(const SegmentInfo &info, bool &stop) {
- if ( (info.protections & (VM_PROT_WRITE | VM_PROT_EXECUTE)) == (VM_PROT_WRITE | VM_PROT_EXECUTE) ) {
- failureReason("Segments are not allowed to be both writable and executable");
- foundBadSegment = true;
- stop = true;
- }
- });
- if ( foundBadSegment )
- return false;
- }
-
- return true;
-}
-#endif
-
-static bool platformExcludesPrebuiltClosure_macOS(const char* path) {
- // We no longer support ROSP, so skip all paths which start with the special prefix
- if ( startsWith(path, "/System/Library/Templates/Data/") )
- return true;
-
- // anything inside a .app bundle is specific to app, so should not get a prebuilt closure
- if ( strstr(path, ".app/") != NULL )
- return true;
-
- return false;
-}
-
-static bool platformExcludesPrebuiltClosure_iOS(const char* path) {
- if ( strcmp(path, "/System/Library/Caches/com.apple.xpc/sdk.dylib") == 0 )
- return true;
- if ( strcmp(path, "/System/Library/Caches/com.apple.xpcd/xpcd_cache.dylib") == 0 )
- return true;
- return false;
-}
-
-static bool platformExcludesPrebuiltClosure_tvOS(const char* path) {
- return platformExcludesPrebuiltClosure_iOS(path);
-}
-
-static bool platformExcludesPrebuiltClosure_watchOS(const char* path) {
- return platformExcludesPrebuiltClosure_iOS(path);
-}
-
-static bool platformExcludesPrebuiltClosure_bridgeOS(const char* path) {
- return platformExcludesPrebuiltClosure_iOS(path);
-}
-
-// Returns true if the current platform requires that this install name be excluded from the shared cache
-// Note that this overrides any exclusion from anywhere else.
-static bool platformExcludesPrebuiltClosure(Platform platform, const char* path) {
- switch (platform) {
- case dyld3::Platform::unknown:
- return false;
- case dyld3::Platform::macOS:
- return platformExcludesPrebuiltClosure_macOS(path);
- case dyld3::Platform::iOS:
- return platformExcludesPrebuiltClosure_iOS(path);
- case dyld3::Platform::tvOS:
- return platformExcludesPrebuiltClosure_tvOS(path);
- case dyld3::Platform::watchOS:
- return platformExcludesPrebuiltClosure_watchOS(path);
- case dyld3::Platform::bridgeOS:
- return platformExcludesPrebuiltClosure_bridgeOS(path);
- case dyld3::Platform::iOSMac:
- return platformExcludesPrebuiltClosure_macOS(path);
- case dyld3::Platform::iOS_simulator:
- return false;
- case dyld3::Platform::tvOS_simulator:
- return false;
- case dyld3::Platform::watchOS_simulator:
- return false;
- case dyld3::Platform::driverKit:
- return false;
- }
-}
-
-bool MachOFile::canHavePrecomputedDlopenClosure(const char* path, void (^failureReason)(const char*)) const
-{
- __block bool retval = true;
-
- // only dylibs can go in cache
- if ( (this->filetype != MH_DYLIB) && (this->filetype != MH_BUNDLE) ) {
- retval = false;
- failureReason("not MH_DYLIB or MH_BUNDLE");
- }
-
- // flat namespace files cannot go in cache
- if ( (this->flags & MH_TWOLEVEL) == 0 ) {
- retval = false;
- failureReason("not built with two level namespaces");
- }
-
- // can only depend on other dylibs with absolute paths
- __block bool allDepPathsAreGood = true;
- forEachDependentDylib(^(const char* loadPath, bool isWeak, bool isReExport, bool isUpward, uint32_t compatVersion, uint32_t curVersion, bool& stop) {
- if ( loadPath[0] != '/' ) {
- allDepPathsAreGood = false;
- stop = true;
- }
- });
- if ( !allDepPathsAreGood ) {
- retval = false;
- failureReason("depends on dylibs that are not absolute paths");
- }
-
- __block bool platformExcludedFile = false;
- forEachSupportedPlatform(^(Platform platform, uint32_t minOS, uint32_t sdk) {
- if ( platformExcludedFile )
- return;
- if ( platformExcludesPrebuiltClosure(platform, path) ) {
- platformExcludedFile = true;
- return;
- }
- });
- if ( platformExcludedFile ) {
- failureReason("file cannot get a prebuilt closure on this platform");
- return false;
- }
-
- // dylibs with interposing info cannot have dlopen closure pre-computed
- if ( hasInterposingTuples() ) {
- retval = false;
- failureReason("has interposing tuples");
- }
-
- // special system dylib overrides cannot have closure pre-computed
- if ( strncmp(path, "/usr/lib/system/introspection/", 30) == 0 ) {
- retval = false;
- failureReason("override of OS dylib");
+ }
+
+ // Temporarily kick out swift binaries on watchOS simulators as they have missing split seg
+ if ( supportsPlatform(Platform::watchOS_simulator) && isArch("i386") ) {
+ if ( strncmp(dylibName, "/usr/lib/swift/", 15) == 0 ) {
+ retval = false;
+ failureReason("i386 swift binary");
+ }
}
return retval;
}
-bool MachOFile::hasInterposingTuples() const
-{
- __block bool hasInterposing = false;
- forEachSection(^(const SectionInfo& info, bool malformedSectionRange, bool &stop) {
- if ( ((info.sectFlags & SECTION_TYPE) == S_INTERPOSING) || ((strcmp(info.sectName, "__interpose") == 0) && (strcmp(info.segInfo.segName, "__DATA") == 0)) )
- hasInterposing = true;
- });
- return hasInterposing;
-}
bool MachOFile::isFairPlayEncrypted(uint32_t& textOffset, uint32_t& size) const
{
@@ -1716,16 +1145,9 @@
{
#if SUPPORT_ARCH_arm64e
// arm64e always uses chained fixups
- if ( (this->cputype == CPU_TYPE_ARM64) && (this->maskedCpuSubtype() == CPU_SUBTYPE_ARM64E) ) {
- // Not all binaries have fixups at all so check for the load commands
- return hasLoadCommand(LC_DYLD_INFO_ONLY) || hasLoadCommand(LC_DYLD_CHAINED_FIXUPS);
- }
+ if ( (this->cputype == CPU_TYPE_ARM64) && (this->cpusubtype == CPU_SUBTYPE_ARM64E) )
+ return true;
#endif
- return hasLoadCommand(LC_DYLD_CHAINED_FIXUPS);
-}
-
-bool MachOFile::hasChainedFixupsLoadCommand() const
-{
return hasLoadCommand(LC_DYLD_CHAINED_FIXUPS);
}
@@ -1769,7 +1191,7 @@
bit += 7;
} while (byte & 0x80);
// sign extend negative numbers
- if ( ((byte & 0x40) != 0) && (bit < 64) )
+ if ( (byte & 0x40) != 0 )
result |= (~0ULL) << bit;
return result;
}