#include <AvailabilityMacros.h>
#include "Options.h"
-
#include "ld.hpp"
#include "Bitcode.hpp"
#include "InputFiles.h"
#include "Resolver.h"
#include "parsers/lto_file.h"
+#include "configure.h"
+
+#define VAL(x) #x
+#define STRINGIFY(x) VAL(x)
namespace ld {
namespace tool {
_internal.cpuSubType = _options.subArchitecture();
_internal.minOSVersion = _options.minOSversion();
- _internal.derivedPlatformLoadCommand = 0;
+ _internal.derivedPlatform = 0;
// In -r mode, look for -linker_option additions
if ( _options.outputKind() == Options::kObjectFile ) {
doLinkerOption(*it, "command line");
}
}
+#ifdef LD64_VERSION_NUM
+ uint32_t packedNum = Options::parseVersionNumber32(STRINGIFY(LD64_VERSION_NUM));
+ uint64_t combined = (uint64_t)TOOL_LD << 32 | packedNum;
+ _internal.toolsVersions.insert(combined);
+#endif
}
void Resolver::buildAtomList()
{
if ( linkerOption.size() == 1 ) {
const char* lo1 = linkerOption.front();
- if ( strncmp(lo1, "-l", 2) == 0 ) {
- _internal.linkerOptionLibraries.insert(&lo1[2]);
+ if ( strncmp(lo1, "-l", 2) == 0) {
+ if (_internal.linkerOptionLibraries.count(&lo1[2]) == 0) {
+ _internal.unprocessedLinkerOptionLibraries.insert(&lo1[2]);
+ }
}
else {
warning("unknown linker option from object file ignored: '%s' in %s", lo1, fileName);
else if ( linkerOption.size() == 2 ) {
const char* lo2a = linkerOption[0];
const char* lo2b = linkerOption[1];
- if ( strcmp(lo2a, "-framework") == 0 ) {
- _internal.linkerOptionFrameworks.insert(lo2b);
+ if ( strcmp(lo2a, "-framework") == 0) {
+ if (_internal.linkerOptionFrameworks.count(lo2b) == 0) {
+ _internal.unprocessedLinkerOptionFrameworks.insert(lo2b);
+ }
}
else {
warning("unknown linker option from object file ignored: '%s' '%s' from %s", lo2a, lo2b, fileName);
}
}
-static void userReadableSwiftVersion(uint8_t value, char versionString[64])
-{
- switch (value) {
- case 1:
- strcpy(versionString, "1.0");
- break;
- case 2:
- strcpy(versionString, "1.1");
- break;
- case 3:
- strcpy(versionString, "2.0");
- break;
- default:
- sprintf(versionString, "unknown ABI version 0x%02X", value);
- }
-}
void Resolver::doFile(const ld::File& file)
{
for (relocatable::File::LinkerOptionsList::const_iterator it=lo->begin(); it != lo->end(); ++it) {
this->doLinkerOption(*it, file.path());
}
+ // <rdar://problem/23053404> process any additional linker-options introduced by this new archive member being loaded
+ if ( _completedInitialObjectFiles ) {
+ _inputFiles.addLinkerOptionLibraries(_internal, *this);
+ _inputFiles.createIndirectDylibs();
+ }
}
// Resolve bitcode section in the object file
if ( _options.bundleBitcode() ) {
if ( objFile->getBitcode() == NULL ) {
- // No bitcode section, figure out if the object file comes from LTO/compiler static library
- if (objFile->sourceKind() != ld::relocatable::File::kSourceLTO &&
- objFile->sourceKind() != ld::relocatable::File::kSourceCompilerArchive ) {
+ // Handle the special case for compiler_rt objects. Add the file to the list to be process.
+ if ( objFile->sourceKind() == ld::relocatable::File::kSourceCompilerArchive ) {
+ _internal.filesFromCompilerRT.push_back(objFile);
+ } else if (objFile->sourceKind() != ld::relocatable::File::kSourceLTO ) {
+ // No bitcode section, figure out if the object file comes from LTO/compiler static library
switch ( _options.platform() ) {
case Options::kPlatformOSX:
+ case Options::kPlatform_bridgeOS:
case Options::kPlatformUnknown:
warning("all bitcode will be dropped because '%s' was built without bitcode. "
"You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target. ", file.path());
else if ( file.swiftVersion() != _internal.swiftVersion ) {
char fileVersion[64];
char otherVersion[64];
- userReadableSwiftVersion(file.swiftVersion(), fileVersion);
- userReadableSwiftVersion(_internal.swiftVersion, otherVersion);
+ Options::userReadableSwiftVersion(file.swiftVersion(), fileVersion);
+ Options::userReadableSwiftVersion(_internal.swiftVersion, otherVersion);
if ( file.swiftVersion() > _internal.swiftVersion ) {
- throwf("%s compiled with newer version of Swift language (%s) than previous files (%s)",
- file.path(), fileVersion, otherVersion);
+ if ( _options.warnOnSwiftABIVersionMismatches() ) {
+ warning("%s compiled with newer version of Swift language (%s) than previous files (%s)",
+ file.path(), fileVersion, otherVersion);
+ } else {
+ throwf("%s compiled with newer version of Swift language (%s) than previous files (%s)",
+ file.path(), fileVersion, otherVersion);
+ }
}
else {
- throwf("%s compiled with older version of Swift language (%s) than previous files (%s)",
- file.path(), fileVersion, otherVersion);
+ if ( _options.warnOnSwiftABIVersionMismatches() ) {
+ warning("%s compiled with older version of Swift language (%s) than previous files (%s)",
+ file.path(), fileVersion, otherVersion);
+ } else {
+ throwf("%s compiled with older version of Swift language (%s) than previous files (%s)",
+ file.path(), fileVersion, otherVersion);
+ }
}
}
}
// remember if any .o file did not have MH_SUBSECTIONS_VIA_SYMBOLS bit set
if ( ! objFile->canScatterAtoms() )
_internal.allObjectFilesScatterable = false;
-
+
+ // remember if building for profiling (so we don't warn about initializers)
+ if ( objFile->hasllvmProfiling() )
+ _havellvmProfiling = true;
+
// update minOSVersion off all .o files
uint32_t objMinOS = objFile->minOSVersion();
if ( !objMinOS )
_internal.objectFileFoundWithNoVersion = true;
-
- uint32_t objPlatformLC = objFile->platformLoadCommand();
- if ( (objPlatformLC != 0) && (_internal.derivedPlatformLoadCommand == 0) && (_options.outputKind() == Options::kObjectFile) )
- _internal.derivedPlatformLoadCommand = objPlatformLC;
-
if ( (_options.outputKind() == Options::kObjectFile) && (objMinOS > _internal.minOSVersion) )
_internal.minOSVersion = objMinOS;
+ uint32_t objPlatform = objFile->platform();
+ if ( (objPlatform != 0) && (_options.outputKind() == Options::kObjectFile) && (_internal.derivedPlatform == 0) )
+ _internal.derivedPlatform = objPlatform;
+
+ // update set of known tools used
+ for (const std::pair<uint32_t,uint32_t>& entry : objFile->toolVersions()) {
+ uint64_t combined = (uint64_t)entry.first << 32 | entry.second;
+ _internal.toolsVersions.insert(combined);
+ }
+
// update cpu-sub-type
cpu_subtype_t nextObjectSubType = file.cpuSubType();
switch ( _options.architecture() ) {
}
break;
+ case CPU_TYPE_ARM64:
+ if ( _options.subArchitecture() != nextObjectSubType ) {
+ if ( _options.allowSubArchitectureMismatches() ) {
+ warning("object file %s was built for different arm64 sub-type (%d) than link command line (%d)",
+ file.path(), nextObjectSubType, _options.subArchitecture());
+ }
+ else {
+ throwf("object file %s was built for different arm64 sub-type (%d) than link command line (%d)",
+ file.path(), nextObjectSubType, _options.subArchitecture());
+ }
+ }
+ break;
+
case CPU_TYPE_I386:
_internal.cpuSubType = CPU_SUBTYPE_I386_ALL;
break;
strncmp(tcLibPath, tempPath, strlen(tcLibPath)) != 0 ) {
switch ( _options.platform() ) {
case Options::kPlatformOSX:
+ case Options::kPlatform_bridgeOS:
case Options::kPlatformUnknown:
warning("all bitcode will be dropped because '%s' was built without bitcode. "
"You must rebuild it with bitcode enabled (Xcode setting ENABLE_BITCODE), obtain an updated library from the vendor, or disable bitcode for this target.", file.path());
}
break;
}
+
+ // <rdar://problem/25680358> verify dylibs use same version of Swift language
+ if ( file.swiftVersion() != 0 ) {
+ if ( _internal.swiftVersion == 0 ) {
+ _internal.swiftVersion = file.swiftVersion();
+ }
+ else if ( file.swiftVersion() != _internal.swiftVersion ) {
+ char fileVersion[64];
+ char otherVersion[64];
+ Options::userReadableSwiftVersion(file.swiftVersion(), fileVersion);
+ Options::userReadableSwiftVersion(_internal.swiftVersion, otherVersion);
+ if ( file.swiftVersion() > _internal.swiftVersion ) {
+ if ( _options.warnOnSwiftABIVersionMismatches() ) {
+ warning("%s compiled with newer version of Swift language (%s) than previous files (%s)",
+ file.path(), fileVersion, otherVersion);
+ } else {
+ throwf("%s compiled with newer version of Swift language (%s) than previous files (%s)",
+ file.path(), fileVersion, otherVersion);
+ }
+ }
+ else {
+ if ( _options.warnOnSwiftABIVersionMismatches() ) {
+ warning("%s compiled with older version of Swift language (%s) than previous files (%s)",
+ file.path(), fileVersion, otherVersion);
+ } else {
+ throwf("%s compiled with older version of Swift language (%s) than previous files (%s)",
+ file.path(), fileVersion, otherVersion);
+ }
+ }
+ }
+ }
+
if ( _options.checkDylibsAreAppExtensionSafe() && !dylibFile->appExtensionSafe() ) {
- warning("linking against dylib not safe for use in application extensions: %s", file.path());
+ warning("linking against a dylib which is not safe for use in application extensions: %s", file.path());
}
const char* depInstallName = dylibFile->installPath();
// <rdar://problem/17229513> embedded frameworks are only supported on iOS 8 and later
}
else if ( _options.outputKind() == Options::kDynamicLibrary ) {
if ( atom.file() != NULL )
- warning("target OS does not support re-exporting symbol %s from %s\n", _options.demangleSymbol(name), atom.file()->path());
+ warning("target OS does not support re-exporting symbol %s from %s\n", _options.demangleSymbol(name), atom.safeFilePath());
else
warning("target OS does not support re-exporting symbol %s\n", _options.demangleSymbol(name));
}
}
else {
if ( atom.file() != NULL )
- warning("cannot export hidden symbol %s from %s", _options.demangleSymbol(name), atom.file()->path());
+ warning("cannot export hidden symbol %s from %s", _options.demangleSymbol(name), atom.safeFilePath());
else
warning("cannot export hidden symbol %s", _options.demangleSymbol(name));
}
(const_cast<ld::Atom*>(&atom))->setScope(ld::Atom::scopeGlobal);
}
else {
- throwf("requested re-export symbol %s is not from a dylib, but from %s\n", _options.demangleSymbol(name), atom.file()->path());
+ throwf("requested re-export symbol %s is not from a dylib, but from %s\n", _options.demangleSymbol(name), atom.safeFilePath());
}
}
break;
//fprintf(stderr, "demote %s to hidden\n", name);
}
if ( _options.canReExportSymbols() && _options.shouldReExport(name) ) {
- throwf("requested re-export symbol %s is not from a dylib, but from %s\n", _options.demangleSymbol(name), atom.file()->path());
+ throwf("requested re-export symbol %s is not from a dylib, but from %s\n", _options.demangleSymbol(name), atom.safeFilePath());
}
break;
}
const std::vector<Options::AliasPair>& aliases = _options.cmdLineAliases();
for (std::vector<Options::AliasPair>::const_iterator it=aliases.begin(); it != aliases.end(); ++it) {
if ( strcmp(it->realName, atom.name()) == 0 ) {
- const AliasAtom* alias = new AliasAtom(atom, it->alias);
- _aliasesFromCmdLine.push_back(alias);
- this->doAtom(*alias);
+ if ( strcmp(it->realName, it->alias) == 0 ) {
+ warning("ignoring alias of itself '%s'", it->realName);
+ }
+ else {
+ const AliasAtom* alias = new AliasAtom(atom, it->alias);
+ _aliasesFromCmdLine.push_back(alias);
+ this->doAtom(*alias);
+ }
}
}
}
if ( atom.section().type() == ld::Section::typeTempAlias )
_haveAliases = true;
+ // error or warn about initializers
+ if ( (atom.section().type() == ld::Section::typeInitializerPointers) && !_havellvmProfiling ) {
+ switch ( _options.initializersTreatment() ) {
+ case Options::kError:
+ throwf("static initializer found in '%s'",atom.safeFilePath());
+ case Options::kWarning:
+ warning("static initializer found in '%s'. Use -no_inits to make this an error. Use -no_warn_inits to suppress warning",atom.safeFilePath());
+ break;
+ default:
+ break;
+ }
+ }
+
if ( _options.deadCodeStrip() ) {
// add to set of dead-strip-roots, all symbols that the compiler marks as don't strip
if ( atom.dontDeadStrip() )
}
}
+ // After resolving all the undefs within the linkageUnit, record all the remaining undefs and all the proxies.
+ if (_options.bundleBitcode() && _options.hideSymbols())
+ _symbolTable.mustPreserveForBitcode(_internal.allUndefProxies);
+
}
//fprintf(stderr, "markLive(%p) %s\n", &atom, atom.name());
// if -why_live cares about this symbol, then dump chain
if ( (previous->referer != NULL) && _options.printWhyLive(atom.name()) ) {
- fprintf(stderr, "%s from %s\n", atom.name(), atom.file()->path());
+ fprintf(stderr, "%s from %s\n", atom.name(), atom.safeFilePath());
int depth = 1;
for(WhyLiveBackChain* p = previous; p != NULL; p = p->previous, ++depth) {
for(int i=depth; i > 0; --i)
fprintf(stderr, " ");
- fprintf(stderr, "%s from %s\n", p->referer->name(), p->referer->file()->path());
+ fprintf(stderr, "%s from %s\n", p->referer->name(), p->referer->safeFilePath());
}
}
}
if ( _haveLLVMObjs && !force ) {
+ std::copy_if(_atoms.begin(), _atoms.end(), std::back_inserter(_internal.deadAtoms), NotLiveLTO() );
// <rdar://problem/9777977> don't remove combinable atoms, they may come back in lto output
_atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), NotLiveLTO()), _atoms.end());
_symbolTable.removeDeadAtoms();
}
else {
+ std::copy_if(_atoms.begin(), _atoms.end(), std::back_inserter(_internal.deadAtoms), NotLive() );
_atoms.erase(std::remove_if(_atoms.begin(), _atoms.end(), NotLive()), _atoms.end());
}
++foundReferenceCount;
}
else if ( atom->contentType() == ld::Atom::typeCFI ) {
- fprintf(stderr, " Dwarf Exception Unwind Info (__eh_frame) in %s\n", pathLeafName(atom->file()->path()));
+ fprintf(stderr, " Dwarf Exception Unwind Info (__eh_frame) in %s\n", pathLeafName(atom->safeFilePath()));
++foundReferenceCount;
}
else {
- fprintf(stderr, " %s in %s\n", _options.demangleSymbol(atom->name()), pathLeafName(atom->file()->path()));
+ fprintf(stderr, " %s in %s\n", _options.demangleSymbol(atom->name()), pathLeafName(atom->safeFilePath()));
++foundReferenceCount;
break; // if undefined used twice in a function, only show first
}
lto::OptimizeOptions optOpt;
optOpt.outputFilePath = _options.outputFilePath();
optOpt.tmpObjectFilePath = _options.tempLtoObjectPath();
+ optOpt.ltoCachePath = _options.ltoCachePath();
+ optOpt.ltoPruneInterval = _options.ltoPruneInterval();
+ optOpt.ltoPruneAfter = _options.ltoPruneAfter();
+ optOpt.ltoMaxCacheSize = _options.ltoMaxCacheSize();
optOpt.preserveAllGlobals = _options.allGlobalsAreDeadStripRoots() || _options.hasExportRestrictList();
optOpt.verbose = _options.verbose();
optOpt.saveTemps = _options.saveTempFiles();
optOpt.pie = _options.positionIndependentExecutable();
optOpt.mainExecutable = _options.linkingMainExecutable();;
optOpt.staticExecutable = (_options.outputKind() == Options::kStaticExecutable);
+ optOpt.preload = (_options.outputKind() == Options::kPreload);
optOpt.relocatable = (_options.outputKind() == Options::kObjectFile);
optOpt.allowTextRelocs = _options.allowTextRelocs();
optOpt.linkerDeadStripping = _options.deadCodeStrip();
optOpt.armUsesZeroCostExceptions = _options.armUsesZeroCostExceptions();
optOpt.simulator = _options.targetIOSSimulator();
optOpt.ignoreMismatchPlatform = ((_options.outputKind() == Options::kPreload) || (_options.outputKind() == Options::kStaticExecutable));
- optOpt.bitcodeBundle = _options.bundleBitcode();
+ optOpt.bitcodeBundle = (_options.bundleBitcode() && (_options.bitcodeKind() != Options::kBitcodeMarker));
+ optOpt.maxDefaultCommonAlignment = _options.maxDefaultCommonAlign();
optOpt.arch = _options.architecture();
optOpt.mcpu = _options.mcpuLTO();
optOpt.platform = _options.platform();
+ optOpt.minOSVersion = _options.minOSversion();
optOpt.llvmOptions = &_options.llvmOptions();
optOpt.initialUndefines = &_options.initialUndefines();
// if -dead_strip on command line
if ( _options.deadCodeStrip() ) {
- // clear liveness bit
+ // run through all atoms again and make live_section LTO atoms are preserved from dead_stripping if needed
+ _dontDeadStripIfReferencesLive.clear();
for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
+ const ld::Atom* atom = *it;
+ if ( atom->dontDeadStripIfReferencesLive() ) {
+ _dontDeadStripIfReferencesLive.push_back(atom);
+ }
+
+ // clear liveness bit
(const_cast<ld::Atom*>(*it))->setLive((*it)->dontDeadStrip());
}
// and re-compute dead code
this->deadStripOptimize(true);
}
-
+
// <rdar://problem/12386559> if -exported_symbols_list on command line, re-force scope
if ( _options.hasExportMaskList() ) {
for (std::vector<const ld::Atom*>::const_iterator it=_atoms.begin(); it != _atoms.end(); ++it) {
// check new code does not override some dylib
this->checkDylibSymbolCollisions();
+
+ // <rdar://problem/33853815> remove undefs from LTO objects that gets optimized away
+ std::unordered_set<const ld::Atom*> mustPreserve;
+ if ( _internal.classicBindingHelper != NULL )
+ mustPreserve.insert(_internal.classicBindingHelper);
+ if ( _internal.compressedFastBinderProxy != NULL )
+ mustPreserve.insert(_internal.compressedFastBinderProxy);
+ if ( _internal.lazyBindingHelper != NULL )
+ mustPreserve.insert(_internal.lazyBindingHelper);
+ if ( const ld::Atom* entry = this->entryPoint(true) )
+ mustPreserve.insert(entry);
+ for (Options::UndefinesIterator uit=_options.initialUndefinesBegin(); uit != _options.initialUndefinesEnd(); ++uit) {
+ SymbolTable::IndirectBindingSlot slot = _symbolTable.findSlotForName(*uit);
+ if ( _internal.indirectBindingTable[slot] != NULL )
+ mustPreserve.insert(_internal.indirectBindingTable[slot]);
+ }
+ _symbolTable.removeDeadUndefs(_atoms, mustPreserve);
}
}
}
}
+void Resolver::buildArchivesList()
+{
+ // Determine which archives were linked and update the internal state.
+ _inputFiles.archives(_internal);
+}
+
void Resolver::dumpAtoms()
{
fprintf(stderr, "Resolver all atoms:\n");
this->fillInInternalState();
this->tweakWeakness();
_symbolTable.checkDuplicateSymbols();
+ this->buildArchivesList();
}