#include <map>
#include <sstream>
+#include "ld.hpp"
#include "Options.h"
#include "Architectures.hpp"
#include "MachOFileAbstraction.hpp"
Options::Options(int argc, const char* argv[])
- : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable),
- fHasPreferredSubType(false), fArchSupportsThumb2(false), fPrebind(false), fBindAtLoad(false), fKeepPrivateExterns(false),
- fNeedsModuleTable(false), fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
+ : fOutputFile("a.out"), fArchitecture(0), fSubArchitecture(0),
+ fFallbackArchitecture(0), fFallbackSubArchitecture(0), fArchitectureName("unknown"), fOutputKind(kDynamicExecutable),
+ fHasPreferredSubType(false), fArchSupportsThumb2(false), fBindAtLoad(false), fKeepPrivateExterns(false),
+ fIgnoreOtherArchFiles(false), fErrorOnOtherArchFiles(false), fForceSubtypeAll(false),
fInterposeMode(kInterposeNone), fDeadStrip(false), fNameSpace(kTwoLevelNameSpace),
- fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName(NULL),
- fBaseAddress(0), fMaxAddress(0x7FFFFFFFFFFFFFFFLL),
- fBaseWritableAddress(0), fSplitSegs(false),
+ fDylibCompatVersion(0), fDylibCurrentVersion(0), fDylibInstallName(NULL), fFinalName(NULL), fEntryName(NULL),
+ fBaseAddress(0), fMaxAddress(0xFFFFFFFFFFFFFFFFULL),
+ fBaseWritableAddress(0),
fExportMode(kExportDefault), fLibrarySearchMode(kSearchDylibAndArchiveInEachDir),
fUndefinedTreatment(kUndefinedError), fMessagesPrefixedWithArchitecture(true),
fWeakReferenceMismatchTreatment(kWeakReferenceMismatchNonWeak),
fClientName(NULL),
fUmbrellaName(NULL), fInitFunctionName(NULL), fDotOutputFile(NULL), fExecutablePath(NULL),
- fBundleLoader(NULL), fDtraceScriptName(NULL), fSegAddrTablePath(NULL), fMapPath(NULL),
+ fBundleLoader(NULL), fDtraceScriptName(NULL), fMapPath(NULL),
fDyldInstallPath("/usr/lib/dyld"), fLtoCachePath(NULL), fTempLtoObjectPath(NULL), fOverridePathlibLTO(NULL), fLtoCpu(NULL),
+ fKextObjectsEnable(-1),fKextObjectsDirPath(NULL),fToolchainPath(NULL),
fZeroPageSize(ULLONG_MAX), fStackSize(0), fStackAddr(0), fSourceVersion(0), fSDKVersion(0), fExecutableStack(false),
fNonExecutableHeap(false), fDisableNonExecutableHeap(false),
fMinimumHeaderPad(32), fSegmentAlignment(4096),
fDeadStripDylibs(false), fAllowTextRelocs(false), fWarnTextRelocs(false), fKextsUseStubs(false),
fUsingLazyDylibLinking(false), fEncryptable(true), fEncryptableForceOn(false), fEncryptableForceOff(false),
fOrderData(true), fMarkDeadStrippableDylib(false),
- fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false), fNoEHLabels(false),
+ fMakeCompressedDyldInfo(true), fMakeCompressedDyldInfoForceOff(false),
+ fMakeThreadedStartsSection(false), fNoEHLabels(false),
fAllowCpuSubtypeMismatches(false), fEnforceDylibSubtypesMatch(false),
fWarnOnSwiftABIVersionMismatches(false), fUseSimplifiedDylibReExports(false),
fObjCABIVersion2Override(false), fObjCABIVersion1Override(false), fCanUseUpwardDylib(false),
fObjcGcCompaction(false), fObjCGc(false), fObjCGcOnly(false),
fDemangle(false), fTLVSupport(false),
fVersionLoadCommand(false), fVersionLoadCommandForcedOn(false),
- fVersionLoadCommandForcedOff(false), fBuildVersionLoadCommand(false), fFunctionStartsLoadCommand(false),
+ fVersionLoadCommandForcedOff(false), fFunctionStartsLoadCommand(false),
fFunctionStartsForcedOn(false), fFunctionStartsForcedOff(false),
fDataInCodeInfoLoadCommand(false), fDataInCodeInfoLoadCommandForcedOn(false), fDataInCodeInfoLoadCommandForcedOff(false),
fCanReExportSymbols(false), fObjcCategoryMerging(true), fPageAlignDataAtoms(false),
fNeedsThreadLoadCommand(false), fEntryPointLoadCommand(false),
- fEntryPointLoadCommandForceOn(false), fEntryPointLoadCommandForceOff(false),
- fSourceVersionLoadCommand(false),
+ fSourceVersionLoadCommand(false),
fSourceVersionLoadCommandForceOn(false), fSourceVersionLoadCommandForceOff(false),
- fTargetIOSSimulator(false), fExportDynamic(false), fAbsoluteSymbols(false),
+ fExportDynamic(false), fAbsoluteSymbols(false),
fAllowSimulatorToLinkWithMacOSX(false), fKeepDwarfUnwind(true),
fKeepDwarfUnwindForcedOn(false), fKeepDwarfUnwindForcedOff(false),
fVerboseOptimizationHints(false), fIgnoreOptimizationHints(false),
fUseDataConstSegmentForceOn(false), fUseDataConstSegmentForceOff(false), fUseTextExecSegment(false),
fBundleBitcode(false), fHideSymbols(false), fVerifyBitcode(false),
fReverseMapUUIDRename(false), fDeDupe(true), fVerboseDeDupe(false),
+ fUseLinkedListBinding(false), fNoLazyBinding(false), fDebugVariant(false),
fReverseMapPath(NULL), fLTOCodegenOnly(false),
fIgnoreAutoLink(false), fAllowDeadDups(false), fAllowWeakImports(true), fInitializersTreatment(Options::kInvalid),
fZeroModTimeInDebugMap(false), fBitcodeKind(kBitcodeProcess),
- fPlatform(kPlatformUnknown), fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL),
- fMacVersionMin(ld::macVersionUnset), fIOSVersionMin(ld::iOSVersionUnset), fWatchOSVersionMin(ld::wOSVersionUnset),
- fSaveTempFiles(false), fSnapshotRequested(false), fPipelineFifo(NULL),
- fDependencyInfoPath(NULL), fTraceFileDescriptor(-1), fMaxDefaultCommonAlign(0),
+ fDebugInfoStripping(kDebugInfoMinimal), fTraceOutputFile(NULL),
+ fSaveTempFiles(false), fLinkSnapshot(this), fSnapshotRequested(false), fPipelineFifo(NULL),
+ fDependencyInfoPath(NULL), fBuildContextName(NULL), fTraceFileDescriptor(-1), fMaxDefaultCommonAlign(0),
fUnalignedPointerTreatment(kUnalignedPointerIgnore)
{
this->checkForClassic(argc, argv);
{
// iPhoneOS always uses same protection for max and initial
// <rdar://problem/11663436> simulator apps need to use MacOSX max-prot
- if ( (fPlatform != kPlatformOSX) && !fTargetIOSSimulator )
+ if ( (platforms().contains(ld::kPlatform_macOS) == 0) && !targetIOSSimulator() )
return initialSegProtection(segName);
for(std::vector<Options::SegmentProtect>::const_iterator it = fCustomSegmentProtections.begin(); it != fCustomSegmentProtections.end(); ++it) {
return NULL;
}
-uint32_t Options::minOSversion() const
-{
- switch (fPlatform) {
- case kPlatformiOS:
- return iOSVersionMin();
- case kPlatformOSX:
- return macosxVersionMin();
- case kPlatformWatchOS:
- return watchOSVersionMin();
-#if SUPPORT_APPLE_TV
- case Options::kPlatform_tvOS:
- return iOSVersionMin();
-#endif
- case kPlatform_bridgeOS:
- return iOSVersionMin();
- case kPlatformUnknown:
- return 0;
- }
- return 0;
-}
-
-void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype, Options::Platform platform)
+void Options::setArchitecture(cpu_type_t type, cpu_subtype_t subtype, ld::Platform platform, uint32_t minOsVers)
{
for (const ArchInfo* t=archInfoArray; t->archName != NULL; ++t) {
if ( (type == t->cpuType) && (subtype == t->cpuSubType) ) {
fArchitectureName = t->archName;
fHasPreferredSubType = t->isSubType;
fArchSupportsThumb2 = t->supportsThumb2;
- if ( fPlatform == kPlatformUnknown)
- fPlatform = platform;
+ if ( platforms().empty() && (platform != ld::kPlatform_unknown) )
+ fPlatforms.add({platform, minOsVers});
switch ( type ) {
case CPU_TYPE_I386:
case CPU_TYPE_X86_64:
- if ( (fPlatform == kPlatformOSX) && (fOutputKind != Options::kObjectFile) && (fMacVersionMin == ld::macVersionUnset) ) {
+ if ( platforms().contains(ld::kPlatform_macOS) && (fOutputKind != Options::kObjectFile) && (platforms().minOS(ld::kPlatform_macOS) == 0) ) {
#ifdef DEFAULT_MACOSX_MIN_VERSION
warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION);
- setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
+ setVersionMin(ld::kPlatform_macOS, DEFAULT_MACOSX_MIN_VERSION);
#else
warning("-macosx_version_min not specified, assuming 10.6");
- fMacVersionMin = ld::mac10_6;
- #endif
+ setVersionMin(ld::kPlatform_macOS, "10.6");
+ #endif
}
break;
case CPU_TYPE_ARM:
case CPU_TYPE_ARM64:
- if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fOutputKind != Options::kObjectFile) ) {
+ if ( platforms().contains(ld::kPlatform_iOS) && (platforms().minOS(ld::kPlatform_iOS) == 0) && (fOutputKind != Options::kObjectFile) ) {
#if defined(DEFAULT_IPHONEOS_MIN_VERSION)
warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
- setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
+ setVersionMin(ld::kPlatformiOS, DEFAULT_IPHONEOS_MIN_VERSION);
#else
warning("-ios_version_min not specified, assuming 6.0");
- setIOSVersionMin("6.0");
+ setVersionMin(ld::kPlatform_iOS, "6.0");
#endif
}
+#if SUPPORT_ARCH_arm64e
+ if ( (fArchitecture == CPU_TYPE_ARM64) && (fSubArchitecture == CPU_SUBTYPE_ARM64_E) ) {
+ fSupportsAuthenticatedPointers = true;
+ }
+#endif
break;
}
fLinkSnapshot.recordArch(fArchitectureName);
// only use compressed LINKEDIT for:
// Mac OS X 10.6 or later
// iOS 3.1 or later
- if ( !fMakeCompressedDyldInfo && minOS(ld::mac10_6, ld::iOS_3_1) && !fMakeCompressedDyldInfoForceOff )
+ if ( !fMakeCompressedDyldInfo && platforms().minOS(ld::version2009) && !fMakeCompressedDyldInfoForceOff )
fMakeCompressedDyldInfo = true;
// Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
- if ( minOS(ld::mac10_5, ld::iOS_2_0) )
+ if ( platforms().minOS(ld::version2008) )
fUseSimplifiedDylibReExports = true;
return;
}
return ( (fArchitecture == CPU_TYPE_ARM) && (fSubArchitecture == CPU_SUBTYPE_ARM_V7K) );
}
+void Options::selectFallbackArch(const char *arch)
+{
+ // Should have the format "desired_arch:fallback_arch", for example "arm64_32:armv7k" to allow an armv7k
+ // slice to substitute for arm64_32 if the latter isn't present.
+ if (const char* fallbackEnv = getenv("LD_DYLIB_ARCH_FALLBACK") ) {
+ std::string fallback(fallbackEnv);
+ auto delimPos = fallback.find(':');
+
+ // Check we've got a potentially valid fallback string and that it's this architecture we're falling back from.
+ if ( delimPos == std::string::npos || fallback.substr(0, delimPos) != arch )
+ return;
+
+ std::string fallbackTo = fallback.substr(delimPos + 1);
+ for (const ArchInfo *t = archInfoArray; t->archName != nullptr; ++t) {
+ if ( fallbackTo == t->archName ) {
+ fFallbackArchitecture = t->cpuType;
+ fFallbackSubArchitecture = t->cpuSubType;
+ }
+ }
+ }
+ else {
+ // <rdar://problem/39797337> let x86_64h fallback and use x86_64 slice
+ if ( (fArchitecture == CPU_TYPE_X86_64) && (fSubArchitecture == CPU_SUBTYPE_X86_64_H) ) {
+ fFallbackArchitecture = CPU_TYPE_X86_64;
+ fFallbackSubArchitecture = CPU_SUBTYPE_X86_ALL;
+ }
+ }
+}
+
void Options::parseArch(const char* arch)
{
if ( arch == NULL )
fSubArchitecture = t->cpuSubType;
fHasPreferredSubType = t->isSubType;
fArchSupportsThumb2 = t->supportsThumb2;
+ selectFallbackArch(arch);
return;
}
}
return result;
}
-void Options::addTAPIInterface(tapi::LinkerInterfaceFile *interface, const char *path) const {
+void Options::addTAPIInterface(tapi::LinkerInterfaceFile* interface, const char *path) const {
#if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 3) || (TAPI_API_VERSION_MAJOR > 1))
if (tapi::APIVersion::isAtLeast(1, 3)) {
for (auto &name : interface->inlinedFrameworkNames()) {
return false;
}
-std::unique_ptr<tapi::LinkerInterfaceFile> Options::findTAPIFile(const std::string &path) const
+tapi::LinkerInterfaceFile* Options::findTAPIFile(const std::string &path) const
{
- std::unique_ptr<tapi::LinkerInterfaceFile> interface;
+#if ((TAPI_API_VERSION_MAJOR == 1 && TAPI_API_VERSION_MINOR >= 3) || (TAPI_API_VERSION_MAJOR > 1))
+ tapi::LinkerInterfaceFile* interface = nullptr;
std::string TBDPath;
// create parsing options.
if (!allowWeakImports())
flags |= tapi::ParsingFlags::DisallowWeakImports;
-
+
+ __block uint32_t linkMinOSVersion = 0;
+ //FIXME handle this correctly once we have multi-platform TAPI.
+ platforms().forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+ if (linkMinOSVersion == 0)
+ linkMinOSVersion = version;
+ if (platform == ld::kPlatform_macOS)
+ linkMinOSVersion = version;
+ });
+
// Search through all the inlined framework.
for (const auto &dylib : fTAPIFiles) {
if (dylib.getInstallName() == path) {
// If the install name matches, parse the framework.
std::string errorMessage;
auto file = dylib.getInterfaceFile()->getInlinedFramework(path.c_str(), architecture(), subArchitecture(),
- flags, tapi::PackedVersion32(minOSversion()), errorMessage);
+ flags, tapi::PackedVersion32(linkMinOSVersion), errorMessage);
if (!file)
throw strdup(errorMessage.c_str());
if (!interface) {
// If this is the first inlined framework found, record the information.
- interface.reset(file);
+ interface = file;
TBDPath = dylib.getTAPIFilePath();
} else {
// If we found other inlined framework already, check to see if their versions are the same.
warning("Inlined framework/dylib mismatch: %s (%s and %s)", path.c_str(),
TBDPath.c_str(), dylib.getTAPIFilePath().c_str());
if (interface->getCurrentVersion() < file->getCurrentVersion()) {
- interface.reset(file);
+ interface = file;
TBDPath = dylib.getTAPIFilePath();
}
}
}
}
return interface;
+#else
+ return nullptr;
+#endif
}
// search for indirect dylib first using -F and -L paths first
return findFile(installName, fromDylib);
}
-
-
-void Options::parseSegAddrTable(const char* segAddrPath, const char* installPth)
-{
- FILE* file = fopen(segAddrPath, "r");
- if ( file == NULL ) {
- warning("-seg_addr_table file cannot be read: %s", segAddrPath);
- return;
- }
-
- char path[PATH_MAX];
- uint64_t firstColumAddress = 0;
- uint64_t secondColumAddress = 0;
- bool hasSecondColumn = false;
- while ( fgets(path, PATH_MAX, file) != NULL ) {
- path[PATH_MAX-1] = '\0';
- char* eol = strchr(path, '\n');
- if ( eol != NULL )
- *eol = '\0';
- // ignore lines not starting with 0x number
- if ( (path[0] == '0') && (path[1] == 'x') ) {
- char* p;
- firstColumAddress = strtoull(path, &p, 16);
- while ( isspace(*p) )
- ++p;
- // see if second column is a number
- if ( (p[0] == '0') && (p[1] == 'x') ) {
- secondColumAddress = strtoull(p, &p, 16);
- hasSecondColumn = true;
- while ( isspace(*p) )
- ++p;
- }
- while ( isspace(*p) )
- ++p;
- if ( p[0] == '/' ) {
- // remove any trailing whitespace
- for(char* end = eol-1; (end > p) && isspace(*end); --end)
- *end = '\0';
- // see if this line is for the dylib being linked
- if ( strcmp(p, installPth) == 0 ) {
- fBaseAddress = firstColumAddress;
- if ( hasSecondColumn ) {
- fBaseWritableAddress = secondColumAddress;
- fSplitSegs = true;
- }
- break; // out of while loop
- }
- }
- }
- }
-
- fclose(file);
-}
-
void Options::loadFileList(const char* fileOfPaths, ld::File::Ordinal baseOrdinal)
{
FILE* file;
return kInvalid;
}
-void Options::setMacOSXVersionMin(const char* version)
-{
- uint32_t value;
- if ( !parsePackedVersion32(version, value) ) {
- throwf("-macosx_version_min value malformed: '%s'", version);
- }
- fMacVersionMin = (ld::MacVersionMin)value;
- fPlatform = kPlatformOSX;
-}
-
-void Options::setIOSVersionMin(const char* version)
-{
- uint32_t value;
- if ( !parsePackedVersion32(version, value) ) {
- throwf("-ios_version_min value malformed: '%s'", version);
- }
- fIOSVersionMin = (ld::IOSVersionMin)value;
- fPlatform = kPlatformiOS;
-}
-
-
-void Options::setWatchOSVersionMin(const char* version)
-{
- uint32_t value;
- if ( !parsePackedVersion32(version, value) ) {
- throwf("-watchos_version_min value malformed: '%s'", version);
- }
- fWatchOSVersionMin = (ld::WatchOSVersionMin)value;
- fPlatform = kPlatformWatchOS;
-}
-
-
-bool Options::minOS(ld::MacVersionMin requiredMacMin, ld::IOSVersionMin requirediPhoneOSMin)
-{
- if ( fMacVersionMin != ld::macVersionUnset ) {
- return ( fMacVersionMin >= requiredMacMin );
- }
- else {
- return min_iOS(requirediPhoneOSMin);
- }
-}
-
-bool Options::min_iOS(ld::IOSVersionMin requirediOSMin)
-{
- if ( fWatchOSVersionMin != ld::wOSVersionUnset ) {
- // Hack until we fully track watch and ios versions seperately
- return ( (fWatchOSVersionMin + 0x00070000) >= requirediOSMin);
- }
- else if ( fPlatform == Options::kPlatform_bridgeOS ) {
- // Hack until we fully track bridge and ios versions seperately
- return ( (fIOSVersionMin + 0x00090000) >= requirediOSMin);
- }
- else {
- return ( fIOSVersionMin >= requirediOSMin );
- }
+void Options::setVersionMin(const ld::Platform& platform, const char *version) {
+ auto checkAndParse = [&](const char *errorFlag) {
+ if ( version == NULL )
+ throwf("%s missing version argument", errorFlag);
+ uint32_t value;
+ if ( !parsePackedVersion32(version, value) ) {
+ throwf("%s value malformed: '%s'", errorFlag, version);
+ }
+ fPlatforms.add({platform, value});
+ };
+
+ switch(platform) {
+ case ld::kPlatform_macOS: checkAndParse("-macosx_version_min"); break;
+ case ld::kPlatform_iOS: checkAndParse("-ios_version_min"); break;
+ case ld::kPlatform_tvOS: checkAndParse("-tvos_version_min"); break;
+ case ld::kPlatform_watchOS: checkAndParse("-watchos_version_min"); break;
+ case ld::kPlatform_bridgeOS: checkAndParse("-bridgeos_version_min"); break;
+ case ld::kPlatform_iOSSimulator: checkAndParse("-ios_simulator_version_min"); break;
+ case ld::kPlatform_tvOSSimulator: checkAndParse("-tvos_simulator_version_min"); break;
+ case ld::kPlatform_watchOSSimulator: checkAndParse("-watchos_simulator_version_min"); break;
+ case ld::kPlatform_unknown: throw "kPlatformUnknown is an invalid argument to setVersionMin()";
+ case ld::kPlatform_iOSMac: checkAndParse("-iosmac_version_min"); break;
+ };
}
void Options::setWeakReferenceMismatchTreatment(const char* treatment)
return false;
}
+bool Options::moveAXMethodList(const char* className) const
+{
+ for (const SymbolsMove& sm : fSymbolsMovesAXMethodLists) {
+ bool wildcard;
+ if ( sm.symbols.containsWithPrefix(className, NULL, wildcard) )
+ return true;
+ }
+ return false;
+}
+
bool Options::moveRoSymbol(const char* symName, const char* filePath, const char*& seg, bool& wildCardMatch) const
{
for (std::vector<SymbolsMove>::const_iterator it=fSymbolsMovesCode.begin(); it != fSymbolsMovesCode.end(); ++it) {
return false;
}
- result = (majorValue << 16) | (minorValue << 8) | microValue;
+ result = (uint32_t)((majorValue << 16) | (minorValue << 8) | microValue);
return true;
}
return getVersionString32(fSDKVersion);
}
-std::string Options::getPlatformStr() const
-{
- switch (fPlatform) {
- case Options::kPlatformOSX:
- return "MacOSX";
- case Options::kPlatformiOS:
- if (targetIOSSimulator())
- return "iPhoneSimulator";
- else
- return "iPhoneOS";
- case Options::kPlatformWatchOS:
- if (targetIOSSimulator())
- return "watchOS Simulator";
- else
- return "watchOS";
-#if SUPPORT_APPLE_TV
- case Options::kPlatform_tvOS:
- if (targetIOSSimulator())
- return "AppleTVSimulator";
- else
- return "AppleTVOS";
- break;
-#endif
- case Options::kPlatform_bridgeOS:
- return "bridgeOS";
- case Options::kPlatformUnknown:
- return "Unknown";
- }
-}
-
std::vector<std::string> Options::writeBitcodeLinkOptions() const
{
- std::vector<std::string> linkCommand;
+ __block std::vector<std::string> linkCommand;
switch ( fOutputKind ) {
case Options::kDynamicLibrary:
linkCommand.push_back("-dylib");
// Add deployment target.
// Platform is allowed to be unknown for "ld -r".
- switch (fPlatform) {
- case Options::kPlatformOSX:
- linkCommand.push_back("-macosx_version_min");
- linkCommand.push_back(getVersionString32((unsigned)fMacVersionMin));
- break;
- case Options::kPlatformiOS:
- if (targetIOSSimulator())
- linkCommand.push_back("-ios_simulator_version_min");
- else
+
+ platforms().forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+ switch (platform) {
+ case ld::kPlatform_macOS:
+ linkCommand.push_back("-macosx_version_min");
+ linkCommand.push_back(getVersionString32(version));
+ break;
+ case ld::kPlatform_iOS:
linkCommand.push_back("-ios_version_min");
- linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
- break;
- case Options::kPlatformWatchOS:
- if (targetIOSSimulator())
- linkCommand.push_back("-watchos_simulator_version_min");
- else
+ linkCommand.push_back(getVersionString32(version));
+ break;
+ case ld::kPlatform_iOSSimulator:
+ linkCommand.push_back("-ios_simulator_version_min");
+ linkCommand.push_back(getVersionString32(version));
+ break;
+ case ld::kPlatform_watchOS:
linkCommand.push_back("-watchos_version_min");
- linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
- break;
-#if SUPPORT_APPLE_TV
- case Options::kPlatform_tvOS:
- if (targetIOSSimulator())
- linkCommand.push_back("-tvos_simulator_version_min");
- else
+ linkCommand.push_back(getVersionString32(version));
+ break;
+ case ld::kPlatform_watchOSSimulator:
+ linkCommand.push_back("-watchos_simulator_version_min");
+ linkCommand.push_back(getVersionString32(version));
+ break;
+ case ld::kPlatform_tvOS:
linkCommand.push_back("-tvos_version_min");
- linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
- break;
-#endif
- case Options::kPlatform_bridgeOS:
- linkCommand.push_back("-bridgeos_version_min");
- linkCommand.push_back(getVersionString32((unsigned)fIOSVersionMin));
- break;
- case Options::kPlatformUnknown:
- if ( fOutputKind != Options::kObjectFile ) {
- throwf("platform is unknown for final bitcode bundle,"
- "deployment target and min version is required for -bitcode_bundle");
- }
- break;
- }
+ linkCommand.push_back(getVersionString32(version));
+ break;
+ case ld::kPlatform_tvOSSimulator:
+ linkCommand.push_back("-tvos_simulator_version_min");
+ linkCommand.push_back(getVersionString32(version));
+ break;
+ case ld::kPlatform_bridgeOS:
+ linkCommand.push_back("-bridgeos_version_min");
+ linkCommand.push_back(getVersionString32(version));
+ break;
+ case ld::kPlatform_iOSMac:
+ linkCommand.push_back("-iosmac_version_min");
+ linkCommand.push_back(getVersionString32(version));
+ break;
+ case ld::kPlatform_unknown:
+ if ( fOutputKind != Options::kObjectFile ) {
+ throwf("platform is unknown for final bitcode bundle,"
+ "deployment target and min version is required for -bitcode_bundle");
+ }
+ break;
+ }
+ });
// entry name
return linkCommand;
}
+const char* Options::checkForNullArgument(const char* argument_name, const char* arg) const
+{
+ if ( arg == NULL )
+ throwf("missing argument for %s", argument_name);
+ return arg;
+}
+
+const char* Options::checkForNullVersionArgument(const char* argument_name, const char* arg) const
+{
+ if ( arg == NULL )
+ throwf("%s missing version argument", argument_name);
+ return arg;
+}
+
//
// Process all command line arguments.
//
exit (0);
}
else if ( strcmp(arg, "-arch") == 0 ) {
- parseArch(argv[++i]);
+ const char* arch = argv[++i];
+ parseArch(arch);
+ fLinkSnapshot.recordArch(arch);
}
else if ( strcmp(arg, "-dynamic") == 0 ) {
// default
fOutputKind = kKextBundle;
cannotBeUsedWithBitcode(arg);
}
+ else if ( strcmp(arg, "-kext_objects_dir") == 0 ) {
+ fKextObjectsDirPath = argv[++i];
+ if ( fKextObjectsDirPath == NULL )
+ throw "missing argument to -kext_objects_dir";
+ fKextObjectsEnable = 1;
+ }
+ else if ( strcmp(arg, "-no_kext_objects") == 0 ) {
+ fKextObjectsEnable = 0;
+ }
else if ( strcmp(arg, "-o") == 0 ) {
- snapshotArgCount = 0;
- fOutputFile = argv[++i];
- fLinkSnapshot.setSnapshotName(fOutputFile);
+ snapshotArgCount = 0;
+ fOutputFile = checkForNullArgument(arg, argv[++i]);
+ fLinkSnapshot.setOutputPath(fOutputFile);
}
else if ( strncmp(arg, "-lazy-l", 7) == 0 ) {
snapshotArgCount = 0;
if ( value == NULL )
throw "missing argument to -prune_interval_lto";
char* endptr;
+ fLtoPruneIntervalOverwrite = true;
fLtoPruneInterval = strtoul(value, &endptr, 10);
if ( *endptr != '\0')
throw "invalid argument for -prune_interval_lto";
}
// Similar to -all_load, but for the following archive only.
else if ( strcmp(arg, "-force_load") == 0 ) {
- FileInfo info = findFile(argv[++i]);
+ const char* path = checkForNullArgument(arg, argv[++i]);
+ FileInfo info = findFile(path);
info.options.fForceLoad = true;
info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
addLibrary(info);
if ( fExportMode == kDontExportSome )
throw "can't use -exported_symbol and -unexported_symbols";
fExportMode = kExportSome;
- fExportSymbols.insert(argv[++i]);
+ const char* symbol = checkForNullArgument(arg, argv[++i]);
+ fExportSymbols.insert(symbol);
}
else if ( strcmp(arg, "-unexported_symbol") == 0 ) {
if ( fExportMode == kExportSome )
throw "can't use -unexported_symbol and -exported_symbol";
fExportMode = kDontExportSome;
- fDontExportSymbols.insert(argv[++i]);
+ const char* symbol = checkForNullArgument(arg, argv[++i]);
+ fDontExportSymbols.insert(symbol);
}
else if ( strcmp(arg, "-non_global_symbols_no_strip_list") == 0 ) {
snapshotFileArgIndex = 1;
else if ( strcmp(arg, "-weak_library") == 0 ) {
// SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
snapshotArgCount = 0;
- FileInfo info = findFile(argv[++i]);
+ const char* path = checkForNullArgument(arg, argv[++i]);
+ FileInfo info = findFile(path);
info.options.fWeakImport = true;
info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
addLibrary(info);
else if ( strcmp(arg, "-lazy_library") == 0 ) {
// SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
snapshotArgCount = 0;
- FileInfo info = findFile(argv[++i]);
+ const char* path = checkForNullArgument(arg, argv[++i]);
+ FileInfo info = findFile(path);
info.options.fLazyLoad = true;
info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
addLibrary(info);
// are prebound. This can then be fixed up by update_prebinding
// later. Prebinding is less useful on 10.4 and greater.
else if ( strcmp(arg, "-prebind") == 0 ) {
- fPrebind = true;
+ warnObsolete(arg);
cannotBeUsedWithBitcode(arg);
}
else if ( strcmp(arg, "-noprebind") == 0 ) {
warnObsolete(arg);
- fPrebind = false;
}
else if ( strcmp(arg, "-prebind_allow_overlap") == 0 ) {
warnObsolete(arg);
}
// ??? Deprecate when we deprecate split-seg.
else if ( strcmp(arg, "-segs_read_only_addr") == 0 ) {
- fBaseAddress = parseAddress(argv[++i]);
+ warnObsolete(arg);
+ ++i;
cannotBeUsedWithBitcode(arg);
}
// ??? Deprecate when we deprecate split-seg.
else if ( strcmp(arg, "-segs_read_write_addr") == 0 ) {
- fBaseWritableAddress = parseAddress(argv[++i]);
- fSplitSegs = true;
+ warnObsolete(arg);
+ ++i;
cannotBeUsedWithBitcode(arg);
}
// ??? Deprecate when we get rid of basing at build time.
else if ( strcmp(arg, "-seg_addr_table") == 0 ) {
+ warnObsolete(arg);
snapshotFileArgIndex = 1;
const char* name = argv[++i];
if ( name == NULL )
throw "-seg_addr_table missing argument";
- fSegAddrTablePath = name;
cannotBeUsedWithBitcode(arg);
}
else if ( strcmp(arg, "-seg_addr_table_filename") == 0 ) {
}
// Use this flag to set default behavior for deployement targets.
else if ( strcmp(arg, "-macosx_version_min") == 0 ) {
- const char* macVers = argv[++i];
- if ( macVers == NULL )
- throw "-macosx_version_min missing version argument";
+ const char* macVers = checkForNullVersionArgument(arg, argv[++i]);
const char* envMacVers = getenv("MACOSX_DEPLOYMENT_TARGET");
const char* enviPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
if ( (envMacVers != NULL) && (enviPhoneVers != NULL) ) {
const char* sysrootPath = fSDKPaths.back();
const char* lastSlash = strrchr(sysrootPath, '/');
if ( strstr(lastSlash, "Simulator") != NULL )
- setIOSVersionMin(enviPhoneVers);
+ setVersionMin(ld::kPlatform_iOS, enviPhoneVers);
else
- setMacOSXVersionMin(macVers);
+ setVersionMin(ld::kPlatform_macOS, macVers);
}
else {
- setMacOSXVersionMin(macVers);
+ setVersionMin(ld::kPlatform_macOS, macVers);
}
}
else {
- setMacOSXVersionMin(macVers);
+ setVersionMin(ld::kPlatform_macOS, macVers);
}
}
else if ( (strcmp(arg, "-ios_version_min") == 0) || (strcmp(arg, "-iphoneos_version_min") == 0) ) {
- const char* vers = argv[++i];
- if ( vers == NULL )
- throw "-ios_version_min missing version argument";
- setIOSVersionMin(vers);
+ const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+ setVersionMin(ld::kPlatform_iOS, vers);
}
else if ( strcmp(arg, "-ios_simulator_version_min") == 0 ) {
- const char* vers = argv[++i];
- if ( vers == NULL )
- throw "-ios_simulator_version_min missing version argument";
- setIOSVersionMin(vers);
- fTargetIOSSimulator = true;
+ const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+ setVersionMin(ld::kPlatform_iOSSimulator, vers);
}
else if ( strcmp(arg, "-watchos_version_min") == 0 ) {
- const char* vers = argv[++i];
- if ( vers == NULL )
- throw "-watchos_version_min missing version argument";
- setWatchOSVersionMin(vers);
+ const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+ setVersionMin(ld::kPlatform_watchOS, vers);
}
else if ( strcmp(arg, "-watchos_simulator_version_min") == 0 ) {
- const char* vers = argv[++i];
- if ( vers == NULL )
- throw "-watchos_simulator_version_min missing version argument";
- setWatchOSVersionMin(vers);
- fTargetIOSSimulator = true;
+ const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+ setVersionMin(ld::kPlatform_watchOSSimulator, vers);
}
- #if SUPPORT_APPLE_TV
else if ( strcmp(arg, "-tvos_version_min") == 0 ) {
- const char* vers = argv[++i];
- if ( vers == NULL )
- throw "-tvos_version_min missing version argument";
- setIOSVersionMin(vers);
- fPlatform = kPlatform_tvOS;
+ const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+ setVersionMin(ld::kPlatform_tvOS, vers);
}
else if ( strcmp(arg, "-tvos_simulator_version_min") == 0 ) {
- const char* vers = argv[++i];
- if ( vers == NULL )
- throw "-tvos_simulator_version_min missing version argument";
- setIOSVersionMin(vers);
- fPlatform = kPlatform_tvOS;
- fTargetIOSSimulator = true;
- }
- #endif
+ const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+ setVersionMin(ld::kPlatform_tvOSSimulator, vers);
+ }
else if ( strcmp(arg, "-bridgeos_version_min") == 0 ) {
- const char* vers = argv[++i];
- if ( vers == NULL )
- throw "-bridgeos_version_min missing version argument";
- setIOSVersionMin(vers);
- fPlatform = kPlatform_bridgeOS;
+ const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+ setVersionMin(ld::kPlatform_bridgeOS, vers);
+ }
+ else if ( strcmp(arg, "-iosmac_version_min") == 0 ) {
+ const char* vers = checkForNullVersionArgument(arg, argv[++i]);
+ setVersionMin(ld::kPlatform_iOSMac, vers);
}
else if ( strcmp(arg, "-multiply_defined") == 0 ) {
//warnObsolete(arg);
}
else if ( strcmp(arg, "-alias") == 0 ) {
Options::AliasPair pair;
- pair.realName = argv[++i];
- if ( pair.realName == NULL )
- throw "missing argument to -alias";
- pair.alias = argv[++i];
- if ( pair.alias == NULL )
- throw "missing argument to -alias";
+ pair.realName = checkForNullArgument(arg, argv[++i]);
+ pair.alias = checkForNullArgument(arg, argv[++i]);
fAliases.push_back(pair);
cannotBeUsedWithBitcode(arg);
}
fVerifyBitcode = true;
}
else if ( strcmp(arg, "-bitcode_symbol_map") == 0) {
- fReverseMapPath = argv[++i];
- if ( fReverseMapPath == NULL )
- throw "missing argument to -bitcode_symbol_map";
+ fReverseMapPath = checkForNullArgument(arg, argv[++i]);
struct stat statbuf;
int ret = ::stat(fReverseMapPath, &statbuf);
if ( ret == 0 && S_ISDIR(statbuf.st_mode)) {
} else
fReverseMapTempPath = std::string(fReverseMapPath);
}
- else if ( strcmp(argv[i], "-flto-codegen-only") == 0) {
+ else if ( strcmp(arg, "-flto-codegen-only") == 0) {
fLTOCodegenOnly = true;
}
- else if ( strcmp(argv[i], "-ignore_auto_link") == 0) {
+ else if ( strcmp(arg, "-ignore_auto_link") == 0) {
fIgnoreAutoLink = true;
}
- else if ( strcmp(argv[i], "-allow_dead_duplicates") == 0) {
+ else if ( strcmp(arg, "-allow_dead_duplicates") == 0) {
fAllowDeadDups = true;
}
- else if ( strcmp(argv[i], "-bitcode_process_mode") == 0 ) {
- const char* bitcode_type = argv[++i];
- if ( bitcode_type == NULL )
- throw "missing argument to -bitcode_process_mode";
- else if ( strcmp(bitcode_type, "strip") == 0 )
+ else if ( strcmp(arg, "-bitcode_process_mode") == 0 ) {
+ const char* bitcode_type = checkForNullArgument(arg, argv[++i]);
+ if ( strcmp(bitcode_type, "strip") == 0 )
fBitcodeKind = kBitcodeStrip;
else if ( strcmp(bitcode_type, "marker") == 0 )
fBitcodeKind = kBitcodeMarker;
throw "unknown argument to -bitcode_process_mode {strip,marker,data,bitcode}";
}
else if ( strcmp(arg, "-rpath") == 0 ) {
- const char* path = argv[++i];
- if ( path == NULL )
- throw "missing argument to -rpath";
+ const char* path = checkForNullArgument(arg, argv[++i]);
fRPaths.push_back(path);
}
else if ( strcmp(arg, "-read_only_stubs") == 0 ) {
warnObsolete(arg);
}
else if ( strcmp(arg, "-map") == 0 ) {
- fMapPath = argv[++i];
- if ( fMapPath == NULL )
- throw "missing argument to -map";
+ fMapPath = checkForNullArgument(arg, argv[++i]);
}
else if ( strcmp(arg, "-pie") == 0 ) {
fPositionIndependentExecutable = true;
else if ( strcmp(arg, "-reexport_library") == 0 ) {
// SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
snapshotArgCount = 0;
- FileInfo info = findFile(argv[++i]);
+ const char* path = checkForNullArgument(arg, argv[++i]);
+ FileInfo info = findFile(path);
info.options.fReExport = true;
info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
addLibrary(info);
else if ( strcmp(arg, "-upward_library") == 0 ) {
// SNAPSHOT FIXME: what should we do for link snapshots? (ignore for now)
snapshotArgCount = 0;
- FileInfo info = findFile(argv[++i]);
+ const char* path = checkForNullArgument(arg, argv[++i]);
+ FileInfo info = findFile(path);
info.options.fUpward = true;
info.ordinal = ld::File::Ordinal::makeArgOrdinal((uint16_t)i);
addLibrary(info);
cannotBeUsedWithBitcode(arg);
}
else if ( strcmp(arg, "-mllvm") == 0 ) {
- const char* opts = argv[++i];
- if ( opts == NULL )
- throw "missing argument to -mllvm";
+ const char* opts = checkForNullArgument(arg, argv[++i]);
fLLVMOptions.push_back(opts);
cannotBeUsedWithBitcode(arg);
}
else if ( strcmp(arg, "-mcpu") == 0 ) {
- const char* cpu = argv[++i];
- if ( cpu == NULL )
- throw "missing argument to -mcpu";
+ const char* cpu = checkForNullArgument(arg, argv[++i]);
fLtoCpu = cpu;
cannotBeUsedWithBitcode(arg);
}
cannotBeUsedWithBitcode(arg);
}
else if ( strcmp(arg, "-objc_abi_version") == 0 ) {
- const char* version = argv[++i];
- if ( version == NULL )
- throw "-objc_abi_version missing version number";
+ const char* version = checkForNullVersionArgument(arg, argv[++i]);
if ( strcmp(version, "2") == 0 ) {
fObjCABIVersion1Override = false;
fObjCABIVersion2Override = true;
}
else if ( strcmp(arg, "-objc_gc") == 0 ) {
fObjCGc = true;
- if ( fObjCGcOnly ) {
+ if ( fObjCGcOnly ) {
warning("-objc_gc overriding -objc_gc_only");
- fObjCGcOnly = false;
+ fObjCGcOnly = false;
}
cannotBeUsedWithBitcode(arg);
}
else if ( strcmp(arg, "-objc_gc_only") == 0 ) {
fObjCGcOnly = true;
- if ( fObjCGc ) {
+ if ( fObjCGc ) {
warning("-objc_gc_only overriding -objc_gc");
- fObjCGc = false;
+ fObjCGc = false;
}
cannotBeUsedWithBitcode(arg);
}
fVersionLoadCommandForcedOn = true;
fVersionLoadCommandForcedOff = false;
}
- else if ( strcmp(arg, "-no_version_load_command") == 0 ) {
- fVersionLoadCommandForcedOff = true;
- fVersionLoadCommandForcedOn = false;
- cannotBeUsedWithBitcode(arg);
- }
else if ( strcmp(arg, "-function_starts") == 0 ) {
fFunctionStartsForcedOn = true;
fFunctionStartsForcedOff = false;
fDataInCodeInfoLoadCommandForcedOff = false;
}
else if ( strcmp(arg, "-object_path_lto") == 0 ) {
- fTempLtoObjectPath = argv[++i];
- if ( fTempLtoObjectPath == NULL )
- throw "missing argument to -object_path_lto";
+ fTempLtoObjectPath = checkForNullArgument(arg, argv[++i]);
}
else if ( strcmp(arg, "-no_objc_category_merging") == 0 ) {
fObjcCategoryMerging = false;
fSnapshotRequested = true;
cannotBeUsedWithBitcode(arg);
}
- else if ( strcmp(arg, "-new_main") == 0 ) {
- fEntryPointLoadCommandForceOn = true;
- cannotBeUsedWithBitcode(arg);
- }
- else if ( strcmp(arg, "-no_new_main") == 0 ) {
- fEntryPointLoadCommandForceOff = true;
- cannotBeUsedWithBitcode(arg);
- }
else if ( strcmp(arg, "-source_version") == 0 ) {
const char* vers = argv[++i];
if ( vers == NULL )
fKextsUseStubs = true;
cannotBeUsedWithBitcode(arg);
}
- else if ( strcmp(argv[i], "-dependency_info") == 0 ) {
+ else if ( strcmp(arg, "-dependency_info") == 0 ) {
snapshotArgCount = 0;
++i;
// previously handled by buildSearchPaths()
}
fMaxDefaultCommonAlign = alignment;
}
- else if ( strcmp(argv[i], "-no_weak_imports") == 0 ) {
+ else if ( strcmp(arg, "-no_weak_imports") == 0 ) {
fAllowWeakImports = false;
}
- else if ( strcmp(argv[i], "-no_inits") == 0 ) {
+ else if ( strcmp(arg, "-no_inits") == 0 ) {
fInitializersTreatment = Options::kError;
}
- else if ( strcmp(argv[i], "-no_warn_inits") == 0 ) {
+ else if ( strcmp(arg, "-no_warn_inits") == 0 ) {
fInitializersTreatment = Options::kSuppress;
}
+ else if ( strcmp(arg, "-threaded_starts_section") == 0 ) {
+ fMakeThreadedStartsSection = true;
+ }
+ else if (strcmp(arg, "-debug_variant") == 0) {
+ fDebugVariant = true;
+ }
+ else if (strcmp(arg, "-no_new_main") == 0) {
+ // HACK until 39514191 is fixed
+ }
// put this last so that it does not interfer with other options starting with 'i'
else if ( strncmp(arg, "-i", 2) == 0 ) {
const char* colon = strchr(arg, ':');
if (fSnapshotRequested)
fLinkSnapshot.createSnapshot();
-}
-
+ if ( kKextBundle == fOutputKind ) {
+ if ( fKextObjectsEnable < 0 )
+ fKextObjectsEnable = ((fArchitecture == CPU_TYPE_ARM64) || (fArchitecture == CPU_TYPE_ARM));
+
+ if (fKextObjectsEnable > 0) {
+ if ( !fKextObjectsDirPath ) {
+ const char* dstroot;
+ const char* objdir = getenv("LD_KEXT_OBJECTS_DIR");
+ if ( objdir )
+ fKextObjectsDirPath = strdup(objdir);
+ else if ( (dstroot = getenv("DSTROOT")) )
+ asprintf((char **)&fKextObjectsDirPath, "%s/AppleInternal/KextObjects", dstroot);
+ }
+ fLinkSnapshot.setSnapshotMode(Snapshot::SNAPSHOT_KEXT);
+ fLinkSnapshot.createSnapshot();
+ }
+ }
+}
//
// -syslibroot <path> is used for SDK support.
fVerbose = true;
extern const char ldVersionString[];
fprintf(stderr, "%s", ldVersionString);
+ fprintf(stderr, "BUILD " __TIME__ " " __DATE__"\n");
fprintf(stderr, "configured to support archs: %s\n", ALL_SUPPORTED_ARCHS);
// if only -v specified, exit cleanly
if ( argc == 2 ) {
if (getenv("LD_PRINT_ORDER_FILE_STATISTICS") != NULL)
fPrintOrderFileStatistics = true;
- if (getenv("LD_SPLITSEGS_NEW_LIBRARIES") != NULL)
- fSplitSegs = true;
-
if (getenv("LD_NO_ENCRYPT") != NULL) {
fEncryptable = false;
fMarkAppExtensionSafe = true; // temporary
// <rdar://problem/30746905> [Reproducible Builds] If env ZERO_AR_DATE is set, zero out timestamp in N_OSO stab
if ( getenv("ZERO_AR_DATE") != NULL )
fZeroModTimeInDebugMap = true;
+
+ char rawPath[PATH_MAX];
+ char path[PATH_MAX];
+ char *base;
+ uint32_t bufSize = PATH_MAX;
+ if ( _NSGetExecutablePath(rawPath, &bufSize) != -1 ) {
+ if ( realpath(rawPath, path) != NULL ) {
+#define TOOLCHAINBASEPATH "/Developer/Toolchains/"
+ if ( (base = strstr(path, TOOLCHAINBASEPATH)) )
+ fToolchainPath = strndup(path, base - path + strlen(TOOLCHAINBASEPATH));
+ }
+ }
+
+ // <rdar://problem/38679559> ld64 should consider RC_RELEASE when calculating a binary's UUID
+ fBuildContextName = getenv("RC_RELEASE");
}
fExecutablePath = fOutputFile;
}
- // allow build system to set default seg_addr_table
- if ( fSegAddrTablePath == NULL )
- fSegAddrTablePath = getenv("LD_SEG_ADDR_TABLE");
-
- // allow build system to turn on prebinding
- if ( !fPrebind ) {
- fPrebind = ( getenv("LD_PREBIND") != NULL );
- }
-
// allow build system to force on dead-code-stripping
if ( !fDeadStrip ) {
if ( getenv("LD_DEAD_STRIP") != NULL ) {
}
// set default min OS version
- if ( (fMacVersionMin == ld::macVersionUnset) && (fIOSVersionMin == ld::iOSVersionUnset) && (fWatchOSVersionMin == ld::wOSVersionUnset) ) {
+ if ( platforms().empty() ) {
// if neither -macosx_version_min nor -iphoneos_version_min used, try environment variables
+ if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) )
+ warning("No version-min specified on command line");
const char* macVers = getenv("MACOSX_DEPLOYMENT_TARGET");
const char* iPhoneVers = getenv("IPHONEOS_DEPLOYMENT_TARGET");
const char* iOSVers = getenv("IOS_DEPLOYMENT_TARGET");
const char* wOSVers = getenv("WATCHOS_DEPLOYMENT_TARGET");
if ( macVers != NULL )
- setMacOSXVersionMin(macVers);
+ setVersionMin(ld::kPlatform_macOS, macVers);
else if ( iPhoneVers != NULL )
- setIOSVersionMin(iPhoneVers);
+ setVersionMin(ld::kPlatform_iOS, iPhoneVers);
else if ( iOSVers != NULL )
- setIOSVersionMin(iOSVers);
+ setVersionMin(ld::kPlatform_iOS, iOSVers);
else if ( wOSVers != NULL )
- setWatchOSVersionMin(wOSVers);
+ setVersionMin(ld::kPlatform_watchOS, wOSVers);
else {
// if still nothing, set default based on architecture
switch ( fArchitecture ) {
if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
#ifdef DEFAULT_MACOSX_MIN_VERSION
warning("-macosx_version_min not specified, assuming " DEFAULT_MACOSX_MIN_VERSION);
- setMacOSXVersionMin(DEFAULT_MACOSX_MIN_VERSION);
+ setVersionMin(ld::kPlatform_macOS, DEFAULT_MACOSX_MIN_VERSION);
#else
warning("-macosx_version_min not specified, assuming 10.6");
- setMacOSXVersionMin("10.6");
- #endif
+ setVersionMin(ld::kPlatform_macOS, "10.6");
+ #endif
}
break;
case CPU_TYPE_ARM:
if ( (fOutputKind != Options::kObjectFile) && (fOutputKind != Options::kPreload) ) {
#if defined(DEFAULT_IPHONEOS_MIN_VERSION)
warning("-ios_version_min not specified, assuming " DEFAULT_IPHONEOS_MIN_VERSION);
- setIOSVersionMin(DEFAULT_IPHONEOS_MIN_VERSION);
+ setVersionMin(ld::kPlatformiOS, DEFAULT_IPHONEOS_MIN_VERSION);
#else
if ( fSubArchitecture == CPU_SUBTYPE_ARM_V7K ) {
warning("-watchos_version_min not specified, assuming 2.0");
- setWatchOSVersionMin("2.0");
+ setVersionMin(ld::kPlatform_watchOS, "2.0");
}
else {
warning("-ios_version_min not specified, assuming 6.0");
- setIOSVersionMin("6.0");
+ setVersionMin(ld::kPlatform_iOS, "6.0");
}
#endif
}
}
}
-
+ __block ld::VersionSet platformOverrides;
// adjust min based on architecture
- switch ( fArchitecture ) {
- case CPU_TYPE_I386:
- if ( (fPlatform == kPlatformOSX) && (fMacVersionMin < ld::mac10_4) ) {
- //warning("-macosx_version_min should be 10.4 or later for i386");
- fMacVersionMin = ld::mac10_4;
- }
- break;
- case CPU_TYPE_X86_64:
- if ( (fPlatform == kPlatformOSX) && (fMacVersionMin < ld::mac10_4) ) {
- //warning("-macosx_version_min should be 10.4 or later for x86_64");
- fMacVersionMin = ld::mac10_4;
- }
- break;
- case CPU_TYPE_ARM64:
- if ( (fPlatform == kPlatformiOS) && (fIOSVersionMin < ld::iOS_7_0) ) {
- //warning("-mios_version_min should be 7.0 or later for arm64");
- fIOSVersionMin = ld::iOS_7_0;
- }
- break;
- }
-
+ platforms().forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+ if ( (fArchitecture == CPU_TYPE_I386 || fArchitecture == CPU_TYPE_X86_64)
+ && platform == ld::kPlatform_macOS && !platforms().minOS(ld::mac10_4) ) {
+ platformOverrides.add(ld::mac10_4);
+ } else if (fArchitecture == CPU_TYPE_ARM64 && platform == ld::kPlatform_iOS
+ && !platforms().minOS(ld::iOS_7_0)) {
+ platformOverrides.add(ld::iOS_7_0);
+ }
+ });
+
+ // Insert the overrides into fPlatfroms
+ platformOverrides.forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+ fPlatforms.add({platform, version});
+ });
+
// default to adding functions start for dynamic code, static code must opt-in
switch ( fOutputKind ) {
case Options::kPreload:
fUndefinedTreatment = kUndefinedDynamicLookup;
break;
case CPU_TYPE_ARM:
- if ( min_iOS(ld::iOS_5_0) ) {
- // iOS 5.0 and later use new MH_KEXT_BUNDLE type
- fMakeCompressedDyldInfo = false;
- fMakeCompressedDyldInfoForceOff = true;
- // kexts are PIC in iOS 6.0 and later
- fAllowTextRelocs = !min_iOS(ld::iOS_6_0);
- fKextsUseStubs = !fAllowTextRelocs;
- fUndefinedTreatment = kUndefinedDynamicLookup;
- break;
- }
- // else use object file
+ fMakeCompressedDyldInfo = false;
+ fMakeCompressedDyldInfoForceOff = true;
+ fAllowTextRelocs = false;
+ fKextsUseStubs = !fAllowTextRelocs;
+ fUndefinedTreatment = kUndefinedDynamicLookup;
+ break;
case CPU_TYPE_I386:
// use .o files
fOutputKind = kObjectFile;
// disable implicit dylibs when targeting 10.3
// <rdar://problem/5451987> add option to disable implicit load commands for indirectly used public dylibs
- if ( !minOS(ld::mac10_4, ld::iOS_2_0) )
+ if ( !platforms().minOS(ld::version2007) )
fImplicitlyLinkPublicDylibs = false;
-
- // allow build system to force linker to ignore -prebind
- if ( getenv("LD_FORCE_NO_PREBIND") != NULL )
- fPrebind = false;
-
- // allow build system to force linker to ignore -seg_addr_table
- if ( getenv("LD_FORCE_NO_SEG_ADDR_TABLE") != NULL )
- fSegAddrTablePath = NULL;
-
- // check for base address specified externally
- if ( (fSegAddrTablePath != NULL) && (fOutputKind == Options::kDynamicLibrary) ) {
- parseSegAddrTable(fSegAddrTablePath, this->installPath());
- // HACK to support seg_addr_table entries that are physical paths instead of install paths
- if ( fBaseAddress == 0 ) {
- if ( strcmp(this->installPath(), "/usr/lib/libstdc++.6.dylib") == 0 ) {
- parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.4.dylib");
- if ( fBaseAddress == 0 )
- parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libstdc++.6.0.9.dylib");
- }
-
- else if ( strcmp(this->installPath(), "/usr/lib/libz.1.dylib") == 0 )
- parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libz.1.2.3.dylib");
-
- else if ( strcmp(this->installPath(), "/usr/lib/libutil.dylib") == 0 )
- parseSegAddrTable(fSegAddrTablePath, "/usr/lib/libutil1.0.dylib");
- }
- }
-
- // split segs only allowed for dylibs
- if ( fSplitSegs ) {
- // split seg only supported for i386, and arm.
- switch ( fArchitecture ) {
- case CPU_TYPE_I386:
- if ( fOutputKind != Options::kDynamicLibrary )
- fSplitSegs = false;
- // make sure read and write segments are proper distance apart
- if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x10000000) )
- fBaseWritableAddress = fBaseAddress + 0x10000000;
- break;
- case CPU_TYPE_ARM:
- if ( fOutputKind != Options::kDynamicLibrary ) {
- fSplitSegs = false;
- }
- else {
- // make sure read and write segments are proper distance apart
- if ( fSplitSegs && (fBaseWritableAddress-fBaseAddress != 0x08000000) )
- fBaseWritableAddress = fBaseAddress + 0x08000000;
- }
- break;
- default:
- fSplitSegs = false;
- fBaseAddress = 0;
- fBaseWritableAddress = 0;
- }
- }
-
// set too-large size
switch ( fArchitecture ) {
case CPU_TYPE_I386:
break;
}
- // <rdar://problem/6138961> -r implies no prebinding for all architectures
- if ( fOutputKind == Options::kObjectFile )
- fPrebind = false;
-
- // disable prebinding depending on arch and min OS version
- if ( fPrebind ) {
- switch ( fArchitecture ) {
- case CPU_TYPE_I386:
- if ( fMacVersionMin == ld::mac10_4 ) {
- // in 10.4 only split seg dylibs are prebound
- if ( (fOutputKind != Options::kDynamicLibrary) || ! fSplitSegs )
- fPrebind = false;
- }
- else if ( fMacVersionMin >= ld::mac10_5 ) {
- // in 10.5 nothing is prebound
- fPrebind = false;
- }
- else if ( fIOSVersionMin != ld::iOSVersionUnset ) {
- // nothing in simulator is prebound
- fPrebind = false;
- }
- else {
- // in 10.3 and earlier only dylibs and main executables could be prebound
- switch ( fOutputKind ) {
- case Options::kDynamicExecutable:
- case Options::kDynamicLibrary:
- // only main executables and dylibs can be prebound
- break;
- case Options::kStaticExecutable:
- case Options::kDynamicBundle:
- case Options::kObjectFile:
- case Options::kDyld:
- case Options::kPreload:
- case Options::kKextBundle:
- // disable prebinding for everything else
- fPrebind = false;
- break;
- }
- }
- break;
- case CPU_TYPE_X86_64:
- fPrebind = false;
- break;
- case CPU_TYPE_ARM:
- switch ( fOutputKind ) {
- case Options::kDynamicExecutable:
- case Options::kDynamicLibrary:
- // only main executables and dylibs can be prebound
- break;
- case Options::kStaticExecutable:
- case Options::kDynamicBundle:
- case Options::kObjectFile:
- case Options::kDyld:
- case Options::kPreload:
- case Options::kKextBundle:
- // disable prebinding for everything else
- fPrebind = false;
- break;
- }
- break;
- }
- }
-
- // only prebound images can be split-seg
- if ( fSplitSegs && !fPrebind )
- fSplitSegs = false;
-
// determine if info for shared region should be added
if ( fOutputKind == Options::kDynamicLibrary ) {
- if ( minOS(ld::mac10_5, ld::iOS_3_1) )
- if ( !fPrebind && !fSharedRegionEligibleForceOff )
+ if ( platforms().minOS(ld::version2008Fall) )
+ if ( !fSharedRegionEligibleForceOff )
if ( sharedCacheEligiblePath(this->installPath()) )
fSharedRegionEligible = true;
}
fSharedRegionEligible = true;
}
- // automatically use __DATA_CONST in iOS dylibs
- if ( fSharedRegionEligible && minOS(ld::mac10_Future, ld::iOS_9_0) && !fUseDataConstSegmentForceOff && !fTargetIOSSimulator) {
+ // automatically use __DATA_CONST in dylibs on all platforms except macOS
+ if ( fSharedRegionEligible && !fUseDataConstSegmentForceOff
+ && !platforms().contains(ld::kPlatform_macOS) && !targetIOSSimulator()) {
fUseDataConstSegment = true;
}
if ( fUseDataConstSegmentForceOn ) {
fUseDataConstSegment = true;
}
// A -kext for iOS 10 ==> -data_const, -text_exec, -add_split_seg_info
- if ( (fOutputKind == Options::kKextBundle) && minOS(ld::mac10_Future, ld::iOS_10_0) && (fArchitecture == CPU_TYPE_ARM64) ) {
+ if ( (fOutputKind == Options::kKextBundle) && (fArchitecture == CPU_TYPE_ARM64) ) {
fUseDataConstSegment = true;
fUseTextExecSegment = true;
fSharedRegionEligible = true;
}
if ( fUseDataConstSegment ) {
addSectionRename("__DATA", "__got", "__DATA_CONST", "__got");
+
+#if SUPPORT_ARCH_arm64e
+ addSectionRename("__DATA", "__auth_got", "__DATA_CONST", "__auth_got");
+#endif
addSectionRename("__DATA", "__la_symbol_ptr", "__DATA_CONST", "__la_symbol_ptr");
addSectionRename("__DATA", "__nl_symbol_ptr", "__DATA_CONST", "__nl_symbol_ptr");
addSectionRename("__DATA", "__const", "__DATA_CONST", "__const");
}
// Use V2 shared cache info when targetting newer OSs
- if ( fSharedRegionEligible && minOS(ld::mac10_12, ld::iOS_9_0)) {
+ if ( fSharedRegionEligible && platforms().minOS(ld::supportsSplitSegV2)) {
fSharedRegionEncodingV2 = true;
- if ( fPlatform == kPlatformOSX ) {
+ if ( platforms().contains(ld::kPlatform_macOS) ) {
fSharedRegionEncodingV2 = false;
// <rdar://problem/24772435> only use v2 for Swift dylibs on Mac OS X
if ( strncmp(this->installPath(), "/System/Library/PrivateFrameworks/Swift/", 40) == 0 )
fIgnoreOptimizationHints = true;
}
- // figure out if module table is needed for compatibility with old ld/dyld
- if ( fOutputKind == Options::kDynamicLibrary ) {
- switch ( fArchitecture ) {
- case CPU_TYPE_I386:
- if ( fIOSVersionMin != ld::iOSVersionUnset ) // simulator never needs modules
- break;
- case CPU_TYPE_ARM:
- if ( fPrebind )
- fNeedsModuleTable = true; // redo_prebinding requires a module table
- break;
- }
- }
-
// <rdar://problem/5366363> -r -x implies -S
if ( (fOutputKind == Options::kObjectFile) && (fLocalSymbolHandling == kLocalSymbolsNone) )
fDebugInfoStripping = Options::kDebugInfoNone;
case Options::kDynamicLibrary:
case Options::kDynamicBundle:
// <rdar://problem/16293398> Add LC_ENCRYPTION_INFO load command to bundled frameworks
- if ( !min_iOS(ld::iOS_7_0) )
+ if ( !platforms().minOS(ld::version2013) )
fEncryptable = false;
break;
}
case Options::kDynamicLibrary:
case Options::kDynamicBundle:
break;
+ case Options::kDyld:
+ // arm64e has support for compressed LINKEDIT.
+ if ( (fArchitecture == CPU_TYPE_ARM64) && (fSubArchitecture == CPU_SUBTYPE_ARM64_E) )
+ break;
case Options::kPreload:
case Options::kStaticExecutable:
case Options::kObjectFile:
- case Options::kDyld:
case Options::kKextBundle:
fMakeCompressedDyldInfoForceOff = true;
break;
}
- if ( fMakeCompressedDyldInfoForceOff )
- fMakeCompressedDyldInfo = false;
-
- // only use compressed LINKEDIT for:
- // Mac OS X 10.6 or later
- // iOS 3.1 or later
- if ( fMakeCompressedDyldInfo ) {
- if ( !minOS(ld::mac10_6, ld::iOS_3_1) )
- fMakeCompressedDyldInfo = false;
- }
+ // only use legacy LINKEDIT if compressed LINKEDIT is forced off of:
+ // macOS before 10.6
+ // iOS before 3.1
+ if ( fMakeCompressedDyldInfoForceOff || !platforms().minOS(ld::version2009) )
+ fMakeCompressedDyldInfo = false;
// only ARM and x86_64 enforces that cpu-sub-types must match
switch ( fArchitecture ) {
case CPU_TYPE_ARM:
+ case CPU_TYPE_ARM64:
break;
case CPU_TYPE_X86_64:
fEnforceDylibSubtypesMatch = false;
break;
case CPU_TYPE_I386:
- case CPU_TYPE_ARM64:
fEnforceDylibSubtypesMatch = false;
break;
}
}
// Mac OS X 10.5 and iPhoneOS 2.0 support LC_REEXPORT_DYLIB
- if ( minOS(ld::mac10_5, ld::iOS_2_0) )
+ if ( platforms().minOS(ld::version2008) )
fUseSimplifiedDylibReExports = true;
// Mac OS X 10.7 and iOS 4.2 support LC_LOAD_UPWARD_DYLIB
- if ( minOS(ld::mac10_7, ld::iOS_4_2) && (fOutputKind == kDynamicLibrary) )
+ if ( platforms().minOS(ld::version2010) && (fOutputKind == kDynamicLibrary) )
fCanUseUpwardDylib = true;
-
+
+ if (fArchitecture == CPU_TYPE_ARM64) {
+#if SUPPORT_ARCH_arm64e
+ if (fSubArchitecture == CPU_SUBTYPE_ARM64_E)
+ {
+ // FIXME: Move some of these to arm64
+ fNoLazyBinding = true;
+ switch ( fOutputKind ) {
+ case Options::kDynamicExecutable:
+ case Options::kDynamicLibrary:
+ case Options::kDynamicBundle:
+ case Options::kDyld:
+ fUseLinkedListBinding = true;
+ fUseAuthenticatedStubs = true;
+ break;
+ case Options::kPreload:
+ case Options::kStaticExecutable:
+ case Options::kObjectFile:
+ case Options::kKextBundle:
+ break;
+ }
+ switch ( fOutputKind ) {
+ case Options::kDynamicExecutable:
+ case Options::kDyld:
+ case Options::kDynamicLibrary:
+ case Options::kObjectFile:
+ case Options::kDynamicBundle:
+ case Options::kKextBundle:
+ fSupportsAuthenticatedPointers = true;
+ break;
+ case Options::kStaticExecutable:
+ case Options::kPreload:
+ fSupportsAuthenticatedPointers = false;
+ break;
+ }
+ }
+#endif
+ }
+
+ if ( fMakeThreadedStartsSection && (fArchitecture != CPU_TYPE_ARM64) ) {
+ // Threaded starts isn't valid here so ignore it.
+ warning("-threaded_starts_section ignored ignored for non-arm64");
+ fMakeThreadedStartsSection = false;
+ }
+
+ if (fMakeThreadedStartsSection) {
+ switch ( fOutputKind ) {
+ case Options::kDynamicExecutable:
+ case Options::kDyld:
+ case Options::kDynamicLibrary:
+ case Options::kObjectFile:
+ case Options::kDynamicBundle:
+ case Options::kKextBundle:
+ // Threaded starts isn't valid here so ignore it.
+ warning("-threaded_starts_section ignored for binaries other than -static or -preload");
+ fMakeThreadedStartsSection = false;
+ break;
+ case Options::kStaticExecutable:
+ case Options::kPreload:
+ fUseLinkedListBinding = true;
+ fNoLazyBinding = true;
+#if SUPPORT_ARCH_arm64e
+ if ( (fArchitecture == CPU_TYPE_ARM64) && (fSubArchitecture == CPU_SUBTYPE_ARM64_E) )
+ fSupportsAuthenticatedPointers = true;
+#endif
+ break;
+ }
+ }
+
+ // Weak binding requires that if we want to use linked list binding, we must
+ // also be using no lazy binding.
+ if ( fUseLinkedListBinding )
+ assert(fNoLazyBinding);
+
// MacOSX 10.7 defaults to PIE
if ( (fArchitecture == CPU_TYPE_I386)
&& (fOutputKind == kDynamicExecutable)
- && (fMacVersionMin >= ld::mac10_7) ) {
+ && platforms().minOS(ld::mac10_7) ) {
fPositionIndependentExecutable = true;
}
// armv7 for iOS4.3 defaults to PIE
if ( (fArchitecture == CPU_TYPE_ARM)
&& fArchSupportsThumb2
- && (fOutputKind == kDynamicExecutable)
- && min_iOS(ld::iOS_4_3) ) {
+ && (fOutputKind == kDynamicExecutable)
+ && (platforms().contains(ld::kPlatform_watchOS) || platforms().minOS(ld::iOS_4_3)) ) {
fPositionIndependentExecutable = true;
}
- // <rdar://problem/24535196> x86_64 defaults PIE (regardless of minOS version)
- if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind == kDynamicExecutable) && (fMacVersionMin >= ld::mac10_6) )
+ // <rdar://problem/24535196> x86_64 defaults PIE (for 10.6 and later)
+ if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind == kDynamicExecutable) && (platforms().minOS(ld::mac10_6) || platforms().contains(ld::kPlatform_iOSMac)) )
fPositionIndependentExecutable = true;
// Simulator defaults to PIE
- if ( fTargetIOSSimulator && (fOutputKind == kDynamicExecutable) )
+ if ( targetIOSSimulator() && (fOutputKind == kDynamicExecutable) )
fPositionIndependentExecutable = true;
// -no_pie anywhere on command line disable PIE
break;
}
- // let linker know if thread local variables are supported
- if ( fMacVersionMin >= ld::mac10_7 ) {
- fTLVSupport = true;
- }
- else if ( ((fArchitecture == CPU_TYPE_ARM64)
- )
- && min_iOS(ld::iOS_8_0) ) {
- fTLVSupport = true;
- }
- else if ( (fArchitecture == CPU_TYPE_ARM) && min_iOS(ld::iOS_9_0) ) {
- fTLVSupport = true;
- }
- else if ( fTargetIOSSimulator && (fArchitecture == CPU_TYPE_X86_64) && min_iOS(ld::iOS_8_0) ) {
- fTLVSupport = true;
- }
- else if ( fTargetIOSSimulator && (fArchitecture == CPU_TYPE_I386) && min_iOS(ld::iOS_9_0) ) {
+ // Let linker know if thread local variables are supported
+ // This is more complex than normal version checks since
+ // runtime support varies by architecture
+ if (platforms().minOS(ld::supportsTLV)
+ || ((fArchitecture == CPU_TYPE_ARM64) && platforms().minOS(ld::iOS_8_0))
+ || ((fArchitecture == CPU_TYPE_X86_64) && platforms().minOS(ld::iOS_9_0))) {
fTLVSupport = true;
}
}
// support re-export of individual symbols in MacOSX 10.7 and iOS 4.2
- if ( (fOutputKind == kDynamicLibrary) && minOS(ld::mac10_7, ld::iOS_4_2) )
+ if ( (fOutputKind == kDynamicLibrary) && platforms().minOS(ld::version2010) )
fCanReExportSymbols = true;
// ObjC optimization is only in dynamic final linked images
// Use LC_MAIN instead of LC_UNIXTHREAD for newer OSs
switch ( fOutputKind ) {
case Options::kDynamicExecutable:
- if ( fEntryPointLoadCommandForceOn ) {
+ // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
+ if ( platforms().minOS(ld::version2012) ) {
fEntryPointLoadCommand = true;
- if ( fEntryName == NULL )
+ if ( fEntryName == NULL )
fEntryName = "_main";
+ if ( strcmp(fEntryName, "start") == 0 ) {
+ warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version");
+ fEntryName = "_main";
+ }
}
- else if ( fEntryPointLoadCommandForceOff ) {
+ else {
fNeedsThreadLoadCommand = true;
- if ( fEntryName == NULL )
+ if ( fEntryName == NULL )
fEntryName = "start";
}
- else {
- // <rdar://problem/16310363> Linker should look for "_main" not "start" when building for sim regardless of min OS
- if ( minOS(ld::mac10_8, ld::iOS_6_0) || fTargetIOSSimulator ) {
- fEntryPointLoadCommand = true;
- if ( fEntryName == NULL )
- fEntryName = "_main";
- if ( strcmp(fEntryName, "start") == 0 ) {
- warning("Ignoring '-e start' because entry point 'start' is not used for the targeted OS version");
- fEntryName = "_main";
- }
- }
- else {
- fNeedsThreadLoadCommand = true;
- if ( fEntryName == NULL )
- fEntryName = "start";
- }
- }
break;
case Options::kObjectFile:
case Options::kKextBundle:
fSourceVersionLoadCommand = false;
}
else {
- if ( minOS(ld::mac10_8, ld::iOS_6_0) ) {
+ if ( platforms().minOS(ld::version2012) ) {
fSourceVersionLoadCommand = true;
}
else
fSDKVersion = parseVersionNumber32(sdkVersionStr);
}
}
-
+
// if -sdk_version and -syslibroot not used, but targeting MacOSX, use current OS version
- if ( (fSDKVersion == 0) && (fMacVersionMin != ld::macVersionUnset) ) {
+ if ( (fSDKVersion == 0) && platforms().contains(ld::kPlatform_macOS) ) {
// special case if RC_ProjectName and MACOSX_DEPLOYMENT_TARGET are both set that sdkversion=minos
if ( getenv("RC_ProjectName") && getenv("MACOSX_DEPLOYMENT_TARGET") ) {
- fSDKVersion = fMacVersionMin;
+ fSDKVersion = platforms().minOS(ld::kPlatform_macOS);
}
else {
int mib[2] = { CTL_KERN, KERN_OSRELEASE };
// allow trie based absolute symbols if targeting new enough OS
if ( fMakeCompressedDyldInfo ) {
- if ( minOS(ld::mac10_9, ld::iOS_7_0) ) {
+ if ( platforms().minOS(ld::version2013) ) {
fAbsoluteSymbols = true;
}
}
-
- // <rdar://problem/12959510> iOS main executables now default to 16KB page size
- if ( (fIOSVersionMin != ld::iOSVersionUnset) && (fOutputKind == Options::kDynamicExecutable) ) {
- // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
- if ( fEncryptable ) {
- if ( fSegmentAlignment == 4096 )
- fSegmentAlignment = 4096*4;
- }
+
+ // <rdar://problem/13070042> Only third party apps should have 16KB page segments by default
+ if ( fEncryptable ) {
+ if ( fSegmentAlignment == 4096 )
+ fSegmentAlignment = 4096*4;
}
// <rdar://problem/12258065> ARM64 needs 16KB page size for user land code
case Options::kDynamicLibrary:
case Options::kDynamicBundle:
case Options::kDyld:
- if ( ((fArchitecture == CPU_TYPE_ARM64)
- )
- || ((fArchitecture == CPU_TYPE_ARM) && min_iOS(ld::iOS_7_0)) ) {
+ // <rdar://problem/14676611> 16KB segments for arm64 kexts
+ if ( (fArchitecture == CPU_TYPE_ARM64)
+ || (fArchitecture == CPU_TYPE_ARM) ) {
fSegmentAlignment = 4096*4;
}
break;
case Options::kStaticExecutable:
case Options::kKextBundle:
// <rdar://problem/14676611> 16KB segments for arm64 kexts
- if ( ((fArchitecture == CPU_TYPE_ARM64)
- )
- && min_iOS(ld::iOS_9_0) ) {
+ if ( (fArchitecture == CPU_TYPE_ARM64)
+ ) {
fSegmentAlignment = 4096*4;
}
break;
fKeepDwarfUnwind = false;
}
else {
- if ( minOS(ld::mac10_9, ld::iOS_7_0) )
+ if ( platforms().minOS(ld::version2013) )
fKeepDwarfUnwind = false;
else
fKeepDwarfUnwind = true;
}
+ // Look in $SDKROOT/AppleInternal/AccessibilityLinkerSymbols/<dylib>.axsymbols for objc-class names
+ if ( fUseDataConstSegment && (fDylibInstallName != NULL) && !fSDKPaths.empty() ) {
+ const char* dylibLeaf = strrchr(fDylibInstallName, '/');
+ if ( dylibLeaf ) {
+ char path[PATH_MAX];
+ strlcpy(path , fSDKPaths.front(), sizeof(path));
+ strlcat(path , "/AppleInternal/AccessibilityLinkerSymbols", sizeof(path));
+ strlcat(path , dylibLeaf, sizeof(path));
+ strlcat(path , ".axsymbols", sizeof(path));
+ FileInfo info;
+ if ( info.checkFileExists(*this, path) ) {
+ SymbolsMove tmp;
+ fSymbolsMovesAXMethodLists.push_back(tmp);
+ loadExportFile(path, ".axsymbols", fSymbolsMovesAXMethodLists.back().symbols);
+ }
+ }
+ }
+
// <rdar://problem/32138080> Automatically use OrderFiles found in the AppleInternal SDK
if ( (fFinalName != NULL) && fOrderedSymbols.empty() && !fSDKPaths.empty() ) {
char path[PATH_MAX];
}
// Add warnings for issues likely to cause OS verification issues
- if ( fSharedRegionEligible && !fRPaths.empty() ) {
+ if ( fSharedRegionEligible && !fRPaths.empty() && !fDebugVariant ) {
// <rdar://problem/18719327> warn if -rpath is used with OS dylibs
warning("OS dylibs should not add rpaths (linker option: -rpath) (Xcode build setting: LD_RUNPATH_SEARCH_PATHS)");
}
- if ( (fOutputKind == Options::kDynamicLibrary) && (fDylibInstallName != NULL) && (fFinalName != NULL) && sharedCacheEligiblePath(fFinalName) ) {
+ if ( (fOutputKind == Options::kDynamicLibrary) && (fDylibInstallName != NULL) && (fFinalName != NULL) && sharedCacheEligiblePath(fFinalName) && !fDebugVariant ) {
if ( strncmp(fDylibInstallName, "@rpath", 6) == 0 )
warning("OS dylibs should not use @rpath for -install_name. Use absolute path instead");
if ( strcmp(fDylibInstallName, fFinalName) != 0 ) {
}
// set if unaligned pointers are warnings or errors
- if ( fMacVersionMin >= ld::mac10_12 ) {
+ if ( platforms().minOS(ld::mac10_12) ) {
// ignore unaligned pointers when targeting older macOS versions
if ( fSharedRegionEligible )
fUnalignedPointerTreatment = Options::kUnalignedPointerWarning;
else
fUnalignedPointerTreatment = Options::kUnalignedPointerIgnore;
}
- else if ( min_iOS(ld::iOS_10_0) ) {
- fUnalignedPointerTreatment = Options::kUnalignedPointerWarning;
+ else if ( platforms().minOS(ld::iOS_10_0) ) {
+#if SUPPORT_ARCH_arm64e
+ if ( (fArchitecture == CPU_TYPE_ARM64) && (fSubArchitecture == CPU_SUBTYPE_ARM64_E) ) {
+ fUnalignedPointerTreatment = Options::kUnalignedPointerError;
+ } else
+#endif
+ fUnalignedPointerTreatment = Options::kUnalignedPointerWarning;
}
else {
fUnalignedPointerTreatment = Options::kUnalignedPointerIgnore;
// warn by default for OS dylibs
if ( fInitializersTreatment == Options::kInvalid ) {
- if ( fSharedRegionEligible && (fOutputKind == Options::kDynamicLibrary) ) {
+ if ( fSharedRegionEligible && (fOutputKind == Options::kDynamicLibrary) && !fDebugVariant ) {
fInitializersTreatment = Options::kWarning;
- // TEMP HACK
- if ( (fOutputKind == Options::kDynamicLibrary) && (fDylibInstallName != NULL) && (strstr(fDylibInstallName, "EmbeddedAcousticRecognition.framework") != NULL) && !fNoWeakExports )
- fInitializersTreatment = Options::kSuppress;
}
else
fInitializersTreatment = Options::kSuppress;
case kUndefinedError:
// always legal
break;
- case kUndefinedDynamicLookup:
- switch (fPlatform) {
- case kPlatformOSX:
- break;
- case kPlatformiOS:
- case kPlatformWatchOS:
- case kPlatform_bridgeOS:
- #if SUPPORT_APPLE_TV
- case kPlatform_tvOS:
- #endif
- if ( fOutputKind != kKextBundle )
- warning("-undefined dynamic_lookup is deprecated on %s", platformName(fPlatform));
- break;
- default:
- break;
- }
- break;
+ case kUndefinedDynamicLookup: {
+ platforms().forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+ switch (platform) {
+ case ld::kPlatform_macOS:
+ case ld::kPlatform_iOSMac:
+ case ld::kPlatform_unknown:
+ break;
+ case ld::kPlatform_iOS:
+ case ld::kPlatform_iOSSimulator:
+ case ld::kPlatform_watchOS:
+ case ld::kPlatform_watchOSSimulator:
+ case ld::kPlatform_bridgeOS:
+ case ld::kPlatform_tvOS:
+ case ld::kPlatform_tvOSSimulator:
+ if ( fOutputKind != kKextBundle )
+ warning("-undefined dynamic_lookup is deprecated on %s", platformName(platform));
+ break;
+ }
+ });
+ } break;
case kUndefinedWarning:
case kUndefinedSuppress:
// requires flat namespace
// sync reader options
if ( fNameSpace != kTwoLevelNameSpace ) {
fFlatNamespace = true;
- switch (fPlatform) {
- case kPlatformOSX:
- break;
- case kPlatformiOS:
- case kPlatformWatchOS:
- case kPlatform_bridgeOS:
- #if SUPPORT_APPLE_TV
- case Options::kPlatform_tvOS:
- #endif
- warning("-flat_namespace is deprecated on %s", platformName(fPlatform));
- break;
- default:
- break;
- }
+ platforms().forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+ switch (platform) {
+ case ld::kPlatform_unknown:
+ case ld::kPlatform_macOS:
+ case ld::kPlatform_iOSMac:
+ break;
+ case ld::kPlatform_iOS:
+ case ld::kPlatform_iOSSimulator:
+ case ld::kPlatform_watchOS:
+ case ld::kPlatform_watchOSSimulator:
+ case ld::kPlatform_bridgeOS:
+ case ld::kPlatform_tvOS:
+ case ld::kPlatform_tvOSSimulator:
+ warning("-flat_namespace is deprecated on %s", platformName(platform));
+ break;
+ }
+ });
+
}
if ( fStackSize != 0 ) {
switch (fArchitecture) {
case CPU_TYPE_I386:
- if ( fPlatform == kPlatformOSX ) {
+ if ( platforms().contains(ld::kPlatform_macOS) ) {
if ( fStackSize > 0xFFFFFFFF )
throw "-stack_size must be < 4GB for 32-bit processes";
if ( fStackAddr == 0 )
throw "-stack_addr must be < 0x20000000 for arm";
break;
case CPU_TYPE_X86_64:
- if ( fPlatform == kPlatformOSX ) {
+ if ( platforms().contains(ld::kPlatform_macOS) ) {
if ( fStackSize > 0x10000000000 )
throw "-stack_size must be <= 1TB";
if ( fStackAddr == 0 ) {
throw "-setuid_safe cannot be used with -r";
// <rdar://problem/12781832> compiler driver no longer uses -objc_abi_version, it uses -ios_simulator_version_min instead
- if ( !fObjCABIVersion1Override && !fObjCABIVersion2Override && fTargetIOSSimulator )
+ if ( !fObjCABIVersion1Override && !fObjCABIVersion2Override && targetIOSSimulator() )
fObjCABIVersion2Override = true;
// rdar://problem/4718189 map ObjC class names to new runtime names
// can't use -rpath unless targeting 10.5 or later
if ( fRPaths.size() > 0 ) {
- if ( !minOS(ld::mac10_5, ld::iOS_2_0) )
+ if ( !platforms().minOS(ld::version2008) )
throw "-rpath can only be used when targeting Mac OS X 10.5 or later";
switch ( fOutputKind ) {
case Options::kDynamicExecutable:
switch ( fOutputKind ) {
case Options::kDynamicExecutable:
// check -pie is only used when building a dynamic main executable for 10.5
- if ( !minOS(ld::mac10_5, ld::iOS_4_2) ) {
- if ( fIOSVersionMin == ld::iOSVersionUnset )
- throw "-pie can only be used when targeting Mac OS X 10.5 or later";
- else
- throw "-pie can only be used when targeting iOS 4.2 or later";
+ if ( !platforms().minOS(ld::supportsPIE) ) {
+ throw "-pie requires targetting a newer minimum version";
}
break;
case Options::kStaticExecutable:
}
}
- // check -read_only_relocs is not used with x86_64
+ // check -read_only_relocs is not used with x86_64 or arm64
if ( fAllowTextRelocs ) {
if ( (fArchitecture == CPU_TYPE_X86_64) && (fOutputKind != kKextBundle) ) {
warning("-read_only_relocs cannot be used with x86_64");
fAllowTextRelocs = false;
}
+ else if ( fArchitecture == CPU_TYPE_ARM64 ) {
+ warning("-read_only_relocs cannot be used with arm64");
+ }
}
// check -mark_auto_dead_strip is only used with dylibs
if ( !fReExportSymbols.empty() ) {
if ( fOutputKind != Options::kDynamicLibrary )
throw "-reexported_symbols_list can only used used when created dynamic libraries";
- if ( !minOS(ld::mac10_7, ld::iOS_4_2) )
+ if ( !platforms().minOS(ld::version2010) )
throw "targeted OS version does not support -reexported_symbols_list";
}
// <rdar://problem/17598404> warn if building an embedded iOS dylib for pre-iOS 8
// <rdar://problem/18935714> How can we suppress "ld: warning: embedded dylibs/frameworks only run on iOS 8 or later" when building XCTest?
- if ( (fOutputKind == Options::kDynamicLibrary) && (fIOSVersionMin != ld::iOSVersionUnset) && (fDylibInstallName != NULL) ) {
- if ( !min_iOS(ld::iOS_8_0) && (fDylibInstallName[0] == '@') && !fEncryptableForceOff )
+ if ( (fOutputKind == Options::kDynamicLibrary) && (fDylibInstallName != NULL) ) {
+ if ( platforms().contains(ld::kPlatform_iOS) && !platforms().minOS(ld::iOS_8_0) && (fDylibInstallName[0] == '@') && !fEncryptableForceOff )
warning("embedded dylibs/frameworks only run on iOS 8 or later");
}
- // bridgeOS always generates new load command
- if ( fVersionLoadCommand && (fPlatform == kPlatform_bridgeOS) ) {
- fBuildVersionLoadCommand = true;
- }
-
// produce nicer error when no input
if ( fInputFiles.empty() ) {
throw "no object files specified";
}
-}
+
+ // Check zippered combinations.
+ if (platforms().count() > 2) {
+ throw "Illegal platform count. Only 2 platforms at a maximum can be specified";
+ }
+
+ // Convert from -ios_version_min to -ios_simulator_version_min for now until clang has been updated
+ if (architecture() == CPU_TYPE_X86_64 || architecture() == CPU_TYPE_X86) {
+ if (platforms().contains(ld::kPlatform_iOS)) {
+ uint32_t version = platforms().minOS(ld::kPlatform_iOS);
+ fPlatforms.erase(ld::kPlatform_iOS);
+ // HACK infer the build environment from the SDK path
+ bool macOSSDK = false;
+ for (const auto& sdkPath : fSDKPaths) {
+ if (strstr(sdkPath, "MacOSX10") != 0) {
+ macOSSDK = true;
+ break;
+ }
+ }
+ if (macOSSDK) {
+ fPlatforms.add({ ld::kPlatform_iOSMac, version });
+ warning("URGENT: -ios_version_min is invalid for architecture x86/x86_64, inferring -iosmac_version_min. "
+ "This will be an error in the future.");
+ } else {
+ fPlatforms.add({ ld::kPlatform_iOSSimulator, version });
+ warning("URGENT: -ios_version_min is invalid for architecture x86/x86_64, inferring -ios_simulator_version_min. "
+ "This will be an error in the future.");
+ }
+ }
+ }
+
+ if (platforms().count() == 2) {
+ if (!platforms().minOS(ld::mac10_14))
+ throw "Zippered macOS version platform must be at least 10.14";
+ if (!platforms().minOS(ld::iOS_12_0))
+ throw "Zippered iosmac version platform must be at least 12.0";
+ }
+
+ if (platforms().contains(ld::kPlatform_iOSMac) && !platforms().minOS(ld::iOS_12_0)) {
+ throw "iosmac platform version must be at least 12.0";
+ }
+
+ // <rdar://problem/38155581> ld64 shouldn't allow final executables to have more than one version load command
+ if ( platforms().contains(ld::kPlatform_iOSMac) && platforms().contains(ld::kPlatform_macOS) ) {
+ if ( (fOutputKind != Options::kDynamicLibrary) && (fOutputKind != Options::kDynamicBundle) ) {
+ warning("Only dylibs and bundles can be zippered, changing output to be macOS only.");
+ fPlatforms.erase(ld::kPlatform_iOSMac);
+ }
+ }
+
+ // <rdar://problem/39095109> Linker warning for i386 macOS binaries
+ if ( (architecture() == CPU_TYPE_I386) && platforms().contains(ld::kPlatform_macOS) ) {
+ bool internalSDK = false;
+ for (const char* sdkPath : fSDKPaths) {
+ std::string possiblePath = std::string(sdkPath) + "/AppleInternal/";
+ struct stat statBuffer;
+ if ( stat(possiblePath.c_str(), &statBuffer) == 0 ) {
+ internalSDK = true;
+ break;
+ }
+ }
+ if ( !internalSDK )
+ warning("The i386 architecture is deprecated for macOS (remove from the Xcode build setting: ARCHS)");
+ }
+}
void Options::checkForClassic(int argc, const char* argv[])
#if DEMANGLE_SWIFT
// only try to demangle symbols that look like Swift symbols
- if ( strncmp(sym, "__T", 3) == 0 ) {
+ if ( strncmp(sym, "_$", 2) == 0 ) {
size_t demangledSize = fnd_get_demangled_name(&sym[1], buff, size);
if ( demangledSize > size ) {
size = demangledSize+2;