#include <unistd.h>
#include <assert.h>
-#include <vector>
#include <set>
+#include <map>
+#include <vector>
+#include <string>
+#include <unordered_set>
+#include "configure.h"
namespace ld {
+// Forward declaration for bitcode support
+class Bitcode;
+
//
// ld::File
//
class File
{
public:
- enum ObjcConstraint { objcConstraintNone, objcConstraintRetainRelease, objcConstraintRetainReleaseOrGC, objcConstraintGC };
+ enum ObjcConstraint { objcConstraintNone, objcConstraintRetainRelease,
+ objcConstraintRetainReleaseOrGC, objcConstraintGC,
+ objcConstraintRetainReleaseForSimulator };
class AtomHandler {
public:
virtual void doFile(const class File&) = 0;
};
- File(const char* pth, time_t modTime, uint32_t ord)
- : _path(pth), _modTime(modTime), _ordinal(ord) { }
+ //
+ // ld::File::Ordinal
+ //
+ // Codifies the rules of ordering input files for symbol precedence. These are:
+ // - Input files listed on the command line are ordered according to their index in the argument list.
+ // - Input files listed in a file list are ordered first at the index of the file list argument, then
+ // by index in the file list
+ // - Input files extracted from archives are ordered using the ordinal of the archive itself plus the
+ // index of the object file within the archive
+ // - Indirect dylibs are ordered after all input files derived from the command line, in the order that
+ // they are discovered.
+ // - The LTO object file is last.
+ //
+ class Ordinal
+ {
+ private:
+ // The actual numeric ordinal. Lower values have higher precedence and a zero value is invalid.
+ // The 64 bit ordinal is broken into 4 16 bit chunks. The high 16 bits are a "partition" that
+ // is used to distinguish major ordinal groups: command line, indirect dylib, LTO.
+ // The remaining chunks are used according to the partition (see below).
+ uint64_t _ordinal;
+
+ Ordinal (uint64_t ordinal) : _ordinal(ordinal) {}
+
+ enum { kArgListPartition=0, kIndirectDylibPartition=1, kLTOPartition = 2, kLinkerOptionPartition = 3, InvalidParition=0xffff };
+ Ordinal(uint16_t partition, uint16_t majorIndex, uint16_t minorIndex, uint16_t counter) {
+ _ordinal = ((uint64_t)partition<<48) | ((uint64_t)majorIndex<<32) | ((uint64_t)minorIndex<<16) | ((uint64_t)counter<<0);
+ }
+
+ const uint16_t partition() const { return (_ordinal>>48)&0xffff; }
+ const uint16_t majorIndex() const { return (_ordinal>>32)&0xffff; }
+ const uint16_t minorIndex() const { return (_ordinal>>16)&0xffff; }
+ const uint16_t counter() const { return (_ordinal>>00)&0xffff; }
+
+ const Ordinal nextMajorIndex() const { assert(majorIndex() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<32)); }
+ const Ordinal nextMinorIndex() const { assert(minorIndex() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<16)); }
+ const Ordinal nextCounter() const { assert(counter() < 0xffff); return Ordinal(_ordinal+((uint64_t)1<<0)); }
+
+ public:
+ Ordinal() : _ordinal(0) {};
+
+ static const Ordinal NullOrdinal() { return Ordinal((uint64_t)0); }
+
+ const bool validOrdinal() const { return _ordinal != 0; }
+
+ bool operator ==(const Ordinal& rhs) const { return _ordinal == rhs._ordinal; }
+ bool operator !=(const Ordinal& rhs) const { return _ordinal != rhs._ordinal; }
+ bool operator < (const Ordinal& rhs) const { return _ordinal < rhs._ordinal; }
+ bool operator > (const Ordinal& rhs) const { return _ordinal > rhs._ordinal; }
+
+ // For ordinals derived from the command line args the partition is ArgListPartition
+ // The majorIndex is the arg index that pulls in the file, file list, or archive.
+ // The minorIndex is used for files pulled in by a file list and the value is the index of the file in the file list.
+ // The counter is used for .a files and the value is the index of the object in the archive.
+ // Thus, an object pulled in from a .a that was listed in a file list could use all three fields.
+ static const Ordinal makeArgOrdinal(uint16_t argIndex) { return Ordinal(kArgListPartition, argIndex, 0, 0); };
+ const Ordinal nextFileListOrdinal() const { return nextMinorIndex(); }
+ const Ordinal archiveOrdinalWithMemberIndex(uint16_t memberIndex) const { return Ordinal(partition(), majorIndex(), minorIndex(), memberIndex); }
+
+ // For indirect libraries the partition is IndirectDylibPartition and the counter is used or order the libraries.
+ static const ld::File::Ordinal indirectDylibBase() { return Ordinal(kIndirectDylibPartition, 0, 0, 0); }
+ const Ordinal nextIndirectDylibOrdinal() const { return nextCounter(); }
+
+ // For the LTO mach-o the partition is LTOPartition. As there is only one LTO file no other fields are needed.
+ static const ld::File::Ordinal LTOOrdinal() { return Ordinal(kLTOPartition, 0, 0, 0); }
+
+ // For linker options embedded in object files
+ static const ld::File::Ordinal linkeOptionBase() { return Ordinal(kIndirectDylibPartition, 1, 0, 0); }
+ const Ordinal nextLinkerOptionOrdinal() { return nextCounter(); };
+
+ };
+
+ typedef enum { Reloc, Dylib, Archive, Other } Type;
+
+ File(const char* pth, time_t modTime, Ordinal ord, Type type)
+ : _path(pth), _modTime(modTime), _ordinal(ord), _type(type) { }
virtual ~File() {}
const char* path() const { return _path; }
time_t modificationTime() const{ return _modTime; }
- uint32_t ordinal() const { return _ordinal; }
+ Ordinal ordinal() const { return _ordinal; }
virtual bool forEachAtom(AtomHandler&) const = 0;
virtual bool justInTimeforEachAtom(const char* name, AtomHandler&) const = 0;
virtual ObjcConstraint objCConstraint() const { return objcConstraintNone; }
+ virtual bool objcHasCategoryClassPropertiesField() const { return false; }
+ virtual uint8_t swiftVersion() const { return 0; }
virtual uint32_t cpuSubType() const { return 0; }
virtual uint32_t subFileCount() const { return 1; }
+ virtual uint32_t minOSVersion() const { return 0; }
+ virtual uint32_t platformLoadCommand() const { return 0; }
+ bool fileExists() const { return _modTime != 0; }
+ Type type() const { return _type; }
+ virtual Bitcode* getBitcode() const { return NULL; }
private:
const char* _path;
time_t _modTime;
- uint32_t _ordinal;
+ const Ordinal _ordinal;
+ const Type _type;
};
// minumum OS versions
//
enum MacVersionMin { macVersionUnset=0, mac10_4=0x000A0400, mac10_5=0x000A0500,
- mac10_6=0x000A0600, mac10_7=0x000A0700 };
+ mac10_6=0x000A0600, mac10_7=0x000A0700, mac10_8=0x000A0800,
+ mac10_9=0x000A0900, mac10_12=0x000A0C00, mac10_Future=0x10000000 };
enum IOSVersionMin { iOSVersionUnset=0, iOS_2_0=0x00020000, iOS_3_1=0x00030100,
- iOS_4_2=0x00040200, iOS_4_3=0x00040300, iOS_5_0=0x00050000 };
-
+ iOS_4_2=0x00040200, iOS_4_3=0x00040300, iOS_5_0=0x00050000,
+ iOS_6_0=0x00060000, iOS_7_0=0x00070000, iOS_8_0=0x00080000,
+ iOS_9_0=0x00090000, iOS_10_0=0x000A0000, iOS_Future=0x10000000};
+enum WatchOSVersionMin { wOSVersionUnset=0, wOS_1_0=0x00010000, wOS_2_0=0x00020000 };
+
+
namespace relocatable {
//
// ld::relocatable::File
//
// Abstract base class for object files the linker processes.
//
- // objcReplacementClasses() is reflects if the file was compiled for fix-and-continue
- //
// debugInfo() returns if the object file contains debugger information (stabs or dwarf).
//
// stabs() lazily creates a vector of Stab objects for each atom
{
public:
enum DebugInfoKind { kDebugInfoNone=0, kDebugInfoStabs=1, kDebugInfoDwarf=2, kDebugInfoStabsUUID=3 };
+ enum SourceKind { kSourceUnknown=0, kSourceObj, kSourceLTO, kSourceArchive, kSourceCompilerArchive };
struct Stab {
const class Atom* atom;
uint8_t type;
uint32_t value;
const char* string;
};
+ typedef const std::vector< std::vector<const char*> > LinkerOptionsList;
- File(const char* pth, time_t modTime, uint32_t ord)
- : ld::File(pth, modTime, ord) { }
+ File(const char* pth, time_t modTime, Ordinal ord)
+ : ld::File(pth, modTime, ord, Reloc) { }
virtual ~File() {}
- virtual bool objcReplacementClasses() const = 0;
virtual DebugInfoKind debugInfo() const = 0;
virtual const char* debugInfoPath() const { return path(); }
virtual time_t debugInfoModificationTime() const { return modificationTime(); }
virtual const std::vector<Stab>* stabs() const = 0;
virtual bool canScatterAtoms() const = 0;
virtual bool hasLongBranchStubs() { return false; }
+ virtual LinkerOptionsList* linkerOptions() const = 0;
+ virtual SourceKind sourceKind() const { return kSourceUnknown; }
};
} // namespace relocatable
{
public:
virtual ~DylibHandler() {}
- virtual File* findDylib(const char* installPath, const char* fromPath) = 0;
+ virtual File* findDylib(const char* installPath, const ld::dylib::File* fromDylib, bool speculative) = 0;
};
- File(const char* pth, time_t modTime, uint32_t ord)
- : ld::File(pth, modTime, ord), _dylibInstallPath(NULL),
+ File(const char* pth, time_t modTime, Ordinal ord)
+ : ld::File(pth, modTime, ord, Dylib), _dylibInstallPath(NULL), _frameworkName(NULL),
_dylibTimeStamp(0), _dylibCurrentVersion(0), _dylibCompatibilityVersion(0),
- _explicitlyLinked(false), _implicitlyLinked(false),
+ _explicitlyLinked(false), _implicitlyLinked(false), _speculativelyLoaded(false),
_lazyLoadedDylib(false), _forcedWeakLinked(false), _reExported(false),
_upward(false), _dead(false) { }
const char* installPath() const { return _dylibInstallPath; }
+ const char* frameworkName() const { return _frameworkName; }
uint32_t timestamp() const { return _dylibTimeStamp; }
uint32_t currentVersion() const { return _dylibCurrentVersion; }
uint32_t compatibilityVersion() const{ return _dylibCompatibilityVersion; }
bool explicitlyLinked() const { return _explicitlyLinked; }
void setImplicitlyLinked() { _implicitlyLinked = true; }
bool implicitlyLinked() const { return _implicitlyLinked; }
+ void setSpeculativelyLoaded() { _speculativelyLoaded = true; }
+ bool speculativelyLoaded() const { return _speculativelyLoaded; }
+
// attributes of how dylib will be used when linked
void setWillBeLazyLoadedDylb() { _lazyLoadedDylib = true; }
bool willBeLazyLoadedDylib() const { return _lazyLoadedDylib; }
virtual bool providedExportAtom() const = 0;
virtual const char* parentUmbrella() const = 0;
virtual const std::vector<const char*>* allowableClients() const = 0;
+ virtual const std::vector<const char*>& rpaths() const = 0;
virtual bool hasWeakExternals() const = 0;
virtual bool deadStrippable() const = 0;
virtual bool hasWeakDefinition(const char* name) const = 0;
virtual bool hasPublicInstallName() const = 0;
virtual bool allSymbolsAreWeakImported() const = 0;
- protected:
+ virtual bool installPathVersionSpecific() const { return false; }
+ virtual bool appExtensionSafe() const = 0;
+
+ public:
const char* _dylibInstallPath;
+ const char* _frameworkName;
uint32_t _dylibTimeStamp;
uint32_t _dylibCurrentVersion;
uint32_t _dylibCompatibilityVersion;
bool _explicitlyLinked;
bool _implicitlyLinked;
+ bool _speculativelyLoaded;
bool _lazyLoadedDylib;
bool _forcedWeakLinked;
bool _reExported;
class File : public ld::File
{
public:
- File(const char* pth, time_t modTime, uint32_t ord)
- : ld::File(pth, modTime, ord) { }
+ File(const char* pth, time_t modTime, Ordinal ord)
+ : ld::File(pth, modTime, ord, Archive) { }
virtual ~File() {}
virtual bool justInTimeDataOnlyforEachAtom(const char* name, AtomHandler&) const = 0;
};
{
public:
enum Type { typeUnclassified, typeCode, typePageZero, typeImportProxies, typeLinkEdit, typeMachHeader, typeStack,
- typeLiteral4, typeLiteral8, typeLiteral16, typeConstants, typeTempLTO,
+ typeLiteral4, typeLiteral8, typeLiteral16, typeConstants, typeTempLTO, typeTempAlias,
typeCString, typeNonStdCString, typeCStringPointer, typeUTF16Strings, typeCFString, typeObjC1Classes,
typeCFI, typeLSDA, typeDtraceDOF, typeUnwindInfo, typeObjCClassRefs, typeObjC2CategoryList,
typeZeroFill, typeTentativeDefs, typeLazyPointer, typeStub, typeNonLazyPointer, typeDyldInfo,
typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers,
typeStubClose, typeLazyPointerClose, typeAbsoluteSymbols,
typeTLVDefs, typeTLVZeroFill, typeTLVInitialValues, typeTLVInitializerPointers, typeTLVPointers,
- typeFirstSection, typeLastSection, typeDebug };
+ typeFirstSection, typeLastSection, typeDebug, typeSectCreate };
Section(const char* sgName, const char* sctName,
kindStoreARMLoad12,
kindStoreARMLow16, kindStoreARMHigh16,
kindStoreThumbLow16, kindStoreThumbHigh16,
- // PowerPC specific store kinds
- kindStorePPCBranch24, kindStorePPCBranch14,
- kindStorePPCPicLow14, kindStorePPCPicLow16, kindStorePPCPicHigh16AddLow,
- kindStorePPCAbsLow14, kindStorePPCAbsLow16, kindStorePPCAbsHigh16AddLow, kindStorePPCAbsHigh16,
+#if SUPPORT_ARCH_arm64
+ // ARM64 specific store kinds
+ kindStoreARM64Branch26,
+ kindStoreARM64Page21, kindStoreARM64PageOff12,
+ kindStoreARM64GOTLoadPage21, kindStoreARM64GOTLoadPageOff12,
+ kindStoreARM64GOTLeaPage21, kindStoreARM64GOTLeaPageOff12,
+ kindStoreARM64TLVPLoadPage21, kindStoreARM64TLVPLoadPageOff12,
+ kindStoreARM64TLVPLoadNowLeaPage21, kindStoreARM64TLVPLoadNowLeaPageOff12,
+ kindStoreARM64PointerToGOT, kindStoreARM64PCRelToGOT,
+#endif
// dtrace probes
kindDtraceExtra,
kindStoreX86DtraceCallSiteNop, kindStoreX86DtraceIsEnableSiteClear,
kindStoreARMDtraceCallSiteNop, kindStoreARMDtraceIsEnableSiteClear,
+ kindStoreARM64DtraceCallSiteNop, kindStoreARM64DtraceIsEnableSiteClear,
kindStoreThumbDtraceCallSiteNop, kindStoreThumbDtraceIsEnableSiteClear,
- kindStorePPCDtraceCallSiteNop, kindStorePPCDtraceIsEnableSiteClear,
// lazy binding
kindLazyTarget, kindSetLazyOffset,
+ // islands
+ kindIslandTarget,
+ // data-in-code markers
+ kindDataInCodeStartData, kindDataInCodeStartJT8, kindDataInCodeStartJT16,
+ kindDataInCodeStartJT32, kindDataInCodeStartJTA32, kindDataInCodeEnd,
+ // linker optimization hints
+ kindLinkerOptimizationHint,
// pointer store combinations
kindStoreTargetAddressLittleEndian32, // kindSetTargetAddress + kindStoreLittleEndian32
kindStoreTargetAddressLittleEndian64, // kindSetTargetAddress + kindStoreLittleEndian64
kindStoreTargetAddressARMBranch24, // kindSetTargetAddress + kindStoreARMBranch24
kindStoreTargetAddressThumbBranch22, // kindSetTargetAddress + kindStoreThumbBranch22
kindStoreTargetAddressARMLoad12, // kindSetTargetAddress + kindStoreARMLoad12
- // PowerPC value calculation and store combinations
- kindStoreTargetAddressPPCBranch24, // kindSetTargetAddress + kindStorePPCBranch24
+#if SUPPORT_ARCH_arm64
+ // ARM64 value calculation and store combinations
+ kindStoreTargetAddressARM64Branch26, // kindSetTargetAddress + kindStoreARM64Branch26
+ kindStoreTargetAddressARM64Page21, // kindSetTargetAddress + kindStoreARM64Page21
+ kindStoreTargetAddressARM64PageOff12, // kindSetTargetAddress + kindStoreARM64PageOff12
+ kindStoreTargetAddressARM64GOTLoadPage21, // kindSetTargetAddress + kindStoreARM64GOTLoadPage21
+ kindStoreTargetAddressARM64GOTLoadPageOff12,// kindSetTargetAddress + kindStoreARM64GOTLoadPageOff12
+ kindStoreTargetAddressARM64GOTLeaPage21, // kindSetTargetAddress + kindStoreARM64GOTLeaPage21
+ kindStoreTargetAddressARM64GOTLeaPageOff12, // kindSetTargetAddress + kindStoreARM64GOTLeaPageOff12
+ kindStoreTargetAddressARM64TLVPLoadPage21, // kindSetTargetAddress + kindStoreARM64TLVPLoadPage21
+ kindStoreTargetAddressARM64TLVPLoadPageOff12,// kindSetTargetAddress + kindStoreARM64TLVPLoadPageOff12
+ kindStoreTargetAddressARM64TLVPLoadNowLeaPage21, // kindSetTargetAddress + kindStoreARM64TLVPLoadNowLeaPage21
+ kindStoreTargetAddressARM64TLVPLoadNowLeaPageOff12, // kindSetTargetAddress + kindStoreARM64TLVPLoadNowLeaPageOff12
+#endif
};
union {
TargetBinding binding : 3;
bool contentAddendOnly : 1;
bool contentDetlaToAddendOnly : 1;
+ bool contentIgnoresAddend : 1;
typedef Fixup* iterator;
Fixup() :
offsetInAtom(0), kind(kindNone), clusterSize(k1of1), weakImport(false),
binding(bindingNone),
- contentAddendOnly(false), contentDetlaToAddendOnly(false) { u.target = NULL; }
+ contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false) { u.target = NULL; }
Fixup(Kind k, Atom* targetAtom) :
offsetInAtom(0), kind(k), clusterSize(k1of1), weakImport(false),
binding(Fixup::bindingDirectlyBound),
- contentAddendOnly(false), contentDetlaToAddendOnly(false)
+ contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
{ assert(targetAtom != NULL); u.target = targetAtom; }
Fixup(uint32_t off, Cluster c, Kind k) :
offsetInAtom(off), kind(k), clusterSize(c), weakImport(false),
binding(Fixup::bindingNone),
- contentAddendOnly(false), contentDetlaToAddendOnly(false)
+ contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
{ u.addend = 0; }
Fixup(uint32_t off, Cluster c, Kind k, bool weakIm, const char* name) :
offsetInAtom(off), kind(k), clusterSize(c), weakImport(weakIm),
binding(Fixup::bindingByNameUnbound),
- contentAddendOnly(false), contentDetlaToAddendOnly(false)
+ contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
{ assert(name != NULL); u.name = name; }
Fixup(uint32_t off, Cluster c, Kind k, TargetBinding b, const char* name) :
offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(b),
- contentAddendOnly(false), contentDetlaToAddendOnly(false)
+ contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
{ assert(name != NULL); u.name = name; }
Fixup(uint32_t off, Cluster c, Kind k, const Atom* targetAtom) :
offsetInAtom(off), kind(k), clusterSize(c), weakImport(false),
binding(Fixup::bindingDirectlyBound),
- contentAddendOnly(false), contentDetlaToAddendOnly(false)
+ contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
{ assert(targetAtom != NULL); u.target = targetAtom; }
Fixup(uint32_t off, Cluster c, Kind k, TargetBinding b, const Atom* targetAtom) :
offsetInAtom(off), kind(k), clusterSize(c), weakImport(false), binding(b),
- contentAddendOnly(false), contentDetlaToAddendOnly(false)
+ contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
{ assert(targetAtom != NULL); u.target = targetAtom; }
Fixup(uint32_t off, Cluster c, Kind k, uint64_t addend) :
offsetInAtom(off), kind(k), clusterSize(c), weakImport(false),
binding(Fixup::bindingNone),
- contentAddendOnly(false), contentDetlaToAddendOnly(false)
+ contentAddendOnly(false), contentDetlaToAddendOnly(false), contentIgnoresAddend(false)
{ u.addend = addend; }
+ Fixup(Kind k, uint32_t lohKind, uint32_t off1, uint32_t off2) :
+ offsetInAtom(off1), kind(k), clusterSize(k1of1),
+ weakImport(false), binding(Fixup::bindingNone), contentAddendOnly(false),
+ contentDetlaToAddendOnly(false), contentIgnoresAddend(false) {
+ assert(k == kindLinkerOptimizationHint);
+ LOH_arm64 extra;
+ extra.addend = 0;
+ extra.info.kind = lohKind;
+ extra.info.count = 1;
+ extra.info.delta1 = 0;
+ extra.info.delta2 = (off2 - off1) >> 2;
+ u.addend = extra.addend;
+ }
+
+
bool firstInCluster() const {
switch (clusterSize) {
case k1of1:
return false;
}
+ union LOH_arm64 {
+ uint64_t addend;
+ struct {
+ unsigned kind : 6,
+ count : 2, // 00 => 1 addr, 11 => 4 addrs
+ delta1 : 14, // 16-bit delta, low 2 bits assumed zero
+ delta2 : 14,
+ delta3 : 14,
+ delta4 : 14;
+ } info;
+ };
+
};
//
typeSectionEnd, typeBranchIsland, typeLazyPointer, typeStub, typeNonLazyPointer,
typeLazyDylibPointer, typeStubHelper, typeInitializerPointers, typeTerminatorPointers,
typeLTOtemporary, typeResolver,
- typeTLV, typeTLVZeroFill, typeTLVInitialValue, typeTLVInitializerPointers };
+ typeTLV, typeTLVZeroFill, typeTLVInitialValue, typeTLVInitializerPointers, typeTLVPointer };
enum SymbolTableInclusion { symbolTableNotIn, symbolTableNotInFinalLinkedImages, symbolTableIn,
symbolTableInAndNeverStrip, symbolTableInAsAbsolute,
_contentType(ct), _symbolTableInclusion(i),
_scope(s), _mode(modeSectionOffset),
_overridesADylibsWeakDef(false), _coalescedAway(false),
- _live(false), _machoSection(0), _weakImportState(weakImportUnset)
+ _live(false), _dontDeadStripIfRefLive(false),
+ _machoSection(0), _weakImportState(weakImportUnset)
{
#ifndef NDEBUG
switch ( _combine ) {
case combineByNameAndContent:
case combineByNameAndReferences:
- assert(_symbolTableInclusion == symbolTableNotIn);
+ assert(_symbolTableInclusion != symbolTableIn);
assert(_scope != scopeGlobal);
break;
case combineByName:
ContentType contentType() const { return _contentType; }
SymbolTableInclusion symbolTableInclusion() const{ return _symbolTableInclusion; }
bool dontDeadStrip() const { return _dontDeadStrip; }
+ bool dontDeadStripIfReferencesLive() const { return _dontDeadStripIfRefLive; }
bool isThumb() const { return _thumb; }
bool isAlias() const { return _alias; }
Alignment alignment() const { return Alignment(_alignmentPowerOf2, _alignmentModulus); }
void setCoalescedAway() { _coalescedAway = true; }
void setWeakImportState(bool w) { assert(_definition == definitionProxy); _weakImportState = ( w ? weakImportTrue : weakImportFalse); }
void setAutoHide() { _autoHide = true; }
+ void setDontDeadStripIfReferencesLive() { _dontDeadStripIfRefLive = true; }
void setLive() { _live = true; }
void setLive(bool value) { _live = value; }
void setMachoSection(unsigned x) { assert(x != 0); assert(x < 256); _machoSection = x; }
void setSectionStartAddress(uint64_t a) { assert(_mode == modeSectionOffset); _address += a; _mode = modeFinalAddress; }
uint64_t sectionOffset() const { assert(_mode == modeSectionOffset); return _address; }
uint64_t finalAddress() const { assert(_mode == modeFinalAddress); return _address; }
-
+#ifndef NDEBUG
+ bool finalAddressMode() const { return (_mode == modeFinalAddress); }
+#endif
virtual const File* file() const = 0;
- virtual bool translationUnitSource(const char** dir, const char** name) const = 0;
+ // Return the original file this atom belongs to, for instance for an LTO atom,
+ // file() would return the LTO MachO file instead of the original bitcode file.
+ virtual const ld::File* originalFile() const { return file(); }
+ virtual const char* translationUnitSource() const { return NULL; }
virtual const char* name() const = 0;
virtual uint64_t objectAddress() const = 0;
virtual uint64_t size() const = 0;
virtual bool canCoalesceWith(const Atom& rhs, const class IndirectBindingTable&) const { return false; }
virtual Fixup::iterator fixupsBegin() const { return NULL; }
virtual Fixup::iterator fixupsEnd() const { return NULL; }
+ bool hasFixupsOfKind(Fixup::Kind kind) const {
+ for (ld::Fixup::iterator fit = fixupsBegin(), end=fixupsEnd(); fit != end; ++fit) {
+ if ( fit->kind == kind ) return true;
+ }
+ return false;
+ }
+ virtual void setFile(const File* f) { }
+
virtual UnwindInfo::iterator beginUnwind() const { return NULL; }
virtual UnwindInfo::iterator endUnwind() const { return NULL; }
virtual LineInfo::iterator beginLineInfo() const { return NULL; }
virtual LineInfo::iterator endLineInfo() const { return NULL; }
-protected:
- enum AddressMode { modeSectionOffset, modeFinalAddress };
-
void setAttributesFromAtom(const Atom& a) {
_section = a._section;
_alignmentModulus = a._alignmentModulus;
_combine = a._combine;
_dontDeadStrip = a._dontDeadStrip;
_thumb = a._thumb;
- _alias = a._alias;
_autoHide = a._autoHide;
_contentType = a._contentType;
_symbolTableInclusion = a._symbolTableInclusion;
_weakImportState = a._weakImportState;
}
+protected:
+ enum AddressMode { modeSectionOffset, modeFinalAddress };
+
const Section * _section;
uint64_t _address;
uint16_t _alignmentModulus;
bool _overridesADylibsWeakDef : 1;
bool _coalescedAway : 1;
bool _live : 1;
+ bool _dontDeadStripIfRefLive : 1;
unsigned _machoSection : 8;
WeakImportState _weakImportState : 2;
};
};
+
+// utility classes for using std::unordered_map with c-strings
+struct CStringHash {
+ size_t operator()(const char* __s) const {
+ size_t __h = 0;
+ for ( ; *__s; ++__s)
+ __h = 5 * __h + *__s;
+ return __h;
+ };
+};
+struct CStringEquals
+{
+ bool operator()(const char* left, const char* right) const { return (strcmp(left, right) == 0); }
+};
+
+typedef std::unordered_set<const char*, ld::CStringHash, ld::CStringEquals> CStringSet;
+
+
class Internal
{
public:
bool hasExternalRelocs;
};
+ typedef std::map<const ld::Atom*, FinalSection*> AtomToSection;
+
+ virtual uint64_t assignFileOffsets() = 0;
+ virtual void setSectionSizesAndAlignments() = 0;
virtual ld::Internal::FinalSection* addAtom(const Atom&) = 0;
virtual ld::Internal::FinalSection* getFinalSection(const ld::Section& inputSection) = 0;
virtual ~Internal() {}
lazyBindingHelper(NULL), compressedFastBinderProxy(NULL),
objcObjectConstraint(ld::File::objcConstraintNone),
objcDylibConstraint(ld::File::objcConstraintNone),
- cpuSubType(0),
- allObjectFilesScatterable(true), hasObjcReplacementClasses(false),
- someObjectFileHasDwarf(false), usingHugeSections(false) { }
-
+ swiftVersion(0), cpuSubType(0), minOSVersion(0),
+ objectFileFoundWithNoVersion(false),
+ allObjectFilesScatterable(true),
+ someObjectFileHasDwarf(false), usingHugeSections(false),
+ hasThreadLocalVariableDefinitions(false),
+ hasWeakExternalSymbols(false),
+ someObjectHasOptimizationHints(false),
+ dropAllBitcode(false), embedMarkerOnly(false) { }
+
std::vector<FinalSection*> sections;
std::vector<ld::dylib::File*> dylibs;
+ std::vector<std::string> archivePaths;
std::vector<ld::relocatable::File::Stab> stabs;
+ AtomToSection atomToSection;
+ CStringSet unprocessedLinkerOptionLibraries;
+ CStringSet unprocessedLinkerOptionFrameworks;
+ CStringSet linkerOptionLibraries;
+ CStringSet linkerOptionFrameworks;
std::vector<const ld::Atom*> indirectBindingTable;
+ std::vector<const ld::relocatable::File*> filesWithBitcode;
+ std::vector<const ld::Atom*> deadAtoms;
+ std::unordered_set<const char*> allUndefProxies;
const ld::dylib::File* bundleLoader;
const Atom* entryPoint;
const Atom* classicBindingHelper;
const Atom* compressedFastBinderProxy;
ld::File::ObjcConstraint objcObjectConstraint;
ld::File::ObjcConstraint objcDylibConstraint;
+ uint8_t swiftVersion;
uint32_t cpuSubType;
+ uint32_t minOSVersion;
+ uint32_t derivedPlatformLoadCommand;
+ bool objectFileFoundWithNoVersion;
bool allObjectFilesScatterable;
- bool hasObjcReplacementClasses;
bool someObjectFileHasDwarf;
bool usingHugeSections;
+ bool hasThreadLocalVariableDefinitions;
+ bool hasWeakExternalSymbols;
+ bool someObjectHasOptimizationHints;
+ bool dropAllBitcode;
+ bool embedMarkerOnly;
+ std::vector<std::string> ltoBitcodePath;
};
-
-
-
-
-
} // namespace ld
#endif // __LD_HPP__