_dwarfTranslationUnitPath(NULL),
_dwarfDebugInfoSect(NULL), _dwarfDebugAbbrevSect(NULL),
_dwarfDebugLineSect(NULL), _dwarfDebugStringSect(NULL),
- _objConstraint(ld::File::objcConstraintNone),
+ _hasObjC(false),
_swiftVersion(0),
_cpuSubType(0),
_minOSVersion(0),
- _platform(Options::kPlatformUnknown),
_canScatterAtoms(false),
_hasllvmProfiling(false),
_objcHasCategoryClassPropertiesField(false),
virtual bool forEachAtom(ld::File::AtomHandler&) const;
virtual bool justInTimeforEachAtom(const char* name, ld::File::AtomHandler&) const
{ return false; }
- virtual uint32_t minOSVersion() const { return _minOSVersion; }
- virtual uint32_t platform() const { return _platform; }
+ virtual const ld::VersionSet& platforms() const { return _platforms; }
// overrides of ld::relocatable::File
- virtual ObjcConstraint objCConstraint() const { return _objConstraint; }
+ virtual bool hasObjC() const { return _hasObjC; }
virtual bool objcHasCategoryClassPropertiesField() const
{ return _objcHasCategoryClassPropertiesField; }
virtual uint32_t cpuSubType() const { return _cpuSubType; }
const macho_section<P>* _dwarfDebugAbbrevSect;
const macho_section<P>* _dwarfDebugLineSect;
const macho_section<P>* _dwarfDebugStringSect;
- ld::File::ObjcConstraint _objConstraint;
+ bool _hasObjC;
uint8_t _swiftVersion;
uint32_t _cpuSubType;
uint32_t _minOSVersion;
- Options::Platform _platform;
+ ld::VersionSet _platforms;
bool _canScatterAtoms;
bool _hasllvmProfiling;
bool _objcHasCategoryClassPropertiesField;
static bool validFile(const uint8_t* fileContent, bool subtypeMustMatch=false,
cpu_subtype_t subtype=0);
static const char* fileKind(const uint8_t* fileContent);
- static Options::Platform findPlatform(const macho_header<typename A::P>* header);
+ static ld::Platform findPlatform(const macho_header<typename A::P>* header, uint32_t* minOsVers);
static bool hasObjC2Categories(const uint8_t* fileContent);
static bool hasObjC1Categories(const uint8_t* fileContent);
static bool getNonLocalSymbols(const uint8_t* fileContnet, std::vector<const char*> &syms);
const char* name; // only used if targetAtom is NULL
int64_t addend;
bool weakImport; // only used if targetAtom is NULL
+#if SUPPORT_ARCH_arm64e
+ ld::Fixup::AuthData authData; // only used for authenticated pointers
+#endif
};
struct FixupInAtom {
FixupInAtom(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, uint64_t addend) :
fixup(src.offsetInAtom, c, k, addend), atom(src.atom) { src.atom->incrementFixupCount(); }
+#if SUPPORT_ARCH_arm64e
+ FixupInAtom(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, ld::Fixup::AuthData authData) :
+ fixup(src.offsetInAtom, c, k, authData), atom(src.atom) { src.atom->incrementFixupCount(); }
+#endif
+
FixupInAtom(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k) :
fixup(src.offsetInAtom, c, k, (uint64_t)0), atom(src.atom) { src.atom->incrementFixupCount(); }
_allFixups.push_back(FixupInAtom(src, c, k, addend));
}
+#if SUPPORT_ARCH_arm64e
+ void addFixup(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k, ld::Fixup::AuthData authData) {
+ _allFixups.push_back(FixupInAtom(src, c, k, authData));
+ }
+#endif
+
void addFixup(const SourceLocation& src, ld::Fixup::Cluster c, ld::Fixup::Kind k) {
_allFixups.push_back(FixupInAtom(src, c, k));
}
bool verboseOptimizationHints, bool ignoreMismatchPlatform);
ld::relocatable::File* parse(const ParserOptions& opts);
static uint8_t loadCommandSizeMask();
- bool parseLoadCommands(Options::Platform platform, uint32_t minOSVersion, bool simulator, bool ignoreMismatchPlatform);
+ static bool useSimulatorVariant();
+ bool parseLoadCommands(ld::VersionSet platforms, bool simulator, bool ignoreMismatchPlatform);
void makeSections();
void prescanSymbolTable();
void makeSortedSymbolsArray(uint32_t symArray[], const uint32_t sectionArray[]);
const macho_section<P>* _stubsMachOSection;
std::vector<const char*> _dtraceProviderInfo;
std::vector<FixupInAtom> _allFixups;
+#if SUPPORT_ARCH_arm64e
+ bool _supportsAuthenticatedPointers;
+#endif
};
return false;
if ( header->filetype() != MH_OBJECT )
return false;
+ if ( subtypeMustMatch && (header->cpusubtype() != (uint32_t)subtype) )
+ return false;
return true;
}
bool Parser<A>::LabelAndCFIBreakIterator::next(Parser<A>& parser, const Section<A>& sect, uint32_t sectNum, pint_t startAddr, pint_t endAddr,
pint_t* addr, pint_t* size, const macho_nlist<P>** symbol)
{
+ bool cfiApplicable = (sect.machoSection()->flags() & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SOME_INSTRUCTIONS));
// may not be a label on start of section, but need atom demarcation there
if ( newSection ) {
newSection = false;
// advance symIndex until we get to the first label at or past the start of this section
while ( symIndex < sortedSymbolCount ) {
- const macho_nlist<P>& sym = parser.symbolFromIndex(sortedSymbolIndexes[symIndex]);
- if ( ! sect.ignoreLabel(parser.nameFromSymbol(sym)) ) {
- pint_t nextSymbolAddr = sym.n_value();
+ const macho_nlist<P>* sym = &parser.symbolFromIndex(sortedSymbolIndexes[symIndex]);
+ // if compile threw in "ltmp*" symbol at start of section and there is another real label at same location, ignore ltmp one
+ if ( symIndex+1 < sortedSymbolCount ) {
+ const macho_nlist<P>* sym2 = &parser.symbolFromIndex(sortedSymbolIndexes[symIndex+1]);
+ if ( (sym->n_sect() == sym2->n_sect()) && (sym->n_value() == sym2->n_value()) ) {
+ if ( strncmp(parser.nameFromSymbol(*sym), "ltmp", 4) == 0 ) {
+ ++symIndex;
+ sym = sym2;
+ }
+ }
+ }
+ if ( ! sect.ignoreLabel(parser.nameFromSymbol(*sym)) ) {
+ pint_t nextSymbolAddr = sym->n_value();
//fprintf(stderr, "sectNum=%d, nextSymbolAddr=0x%08llX, name=%s\n", sectNum, (uint64_t)nextSymbolAddr, parser.nameFromSymbol(sym));
- if ( (nextSymbolAddr > startAddr) || ((nextSymbolAddr == startAddr) && (sym.n_sect() == sectNum)) )
+ if ( (nextSymbolAddr > startAddr) || ((nextSymbolAddr == startAddr) && (sym->n_sect() == sectNum)) )
break;
}
++symIndex;
return true;
}
// no symbols in section, check CFI
- if ( cfiIndex < cfiStartsCount ) {
+ if ( cfiApplicable && (cfiIndex < cfiStartsCount) ) {
pint_t nextCfiAddr = cfiStartsArray[cfiIndex];
if ( nextCfiAddr < endAddr ) {
// use cfi
_treateBitcodeAsData = opts.treateBitcodeAsData;
_usingBitcode = opts.usingBitcode;
+#if SUPPORT_ARCH_arm64e
+ _supportsAuthenticatedPointers = opts.supportsAuthenticatedPointers;
+#endif
+
// respond to -t option
if ( opts.logAllFiles )
printf("%s\n", _path);
_maxDefaultCommonAlignment = opts.maxDefaultCommonAlignment;
// parse start of mach-o file
- if ( ! parseLoadCommands(opts.platform, opts.minOSVersion, opts.simulator, opts.ignoreMismatchPlatform) )
+ if ( ! parseLoadCommands(opts.platforms, opts.simulator, opts.ignoreMismatchPlatform) )
return _file;
// make array of
template <> uint8_t Parser<x86_64>::loadCommandSizeMask() { return 0x07; }
template <> uint8_t Parser<arm>::loadCommandSizeMask() { return 0x03; }
template <> uint8_t Parser<arm64>::loadCommandSizeMask() { return 0x07; }
+template <> bool Parser<x86>::useSimulatorVariant() { return true; }
+template <> bool Parser<x86_64>::useSimulatorVariant() { return true; }
+template <typename A> bool Parser<A>::useSimulatorVariant() { return false; }
+
template <typename A>
-bool Parser<A>::parseLoadCommands(Options::Platform platform, uint32_t linkMinOSVersion, bool simulator, bool ignoreMismatchPlatform)
+bool Parser<A>::parseLoadCommands(ld::VersionSet platforms, bool simulator, bool ignoreMismatchPlatform)
{
const macho_header<P>* header = (const macho_header<P>*)_fileContent;
// <rdar://problem/5394172> an empty .o file with zero load commands will crash linker
if ( cmd_count == 0 )
return false;
- Options::Platform lcPlatform = Options::kPlatformUnknown;
+ ld::VersionSet lcPlatforms;
const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
const macho_load_command<P>* const cmdsEnd = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>) + header->sizeofcmds());
const macho_load_command<P>* cmd = cmds;
case LC_VERSION_MIN_MACOSX:
case LC_VERSION_MIN_IPHONEOS:
case LC_VERSION_MIN_WATCHOS:
- #if SUPPORT_APPLE_TV
case LC_VERSION_MIN_TVOS:
- #endif
if ( ignoreMismatchPlatform )
break;
- lcPlatform = Options::platformForLoadCommand(cmd->cmd());
- _file->_platform = lcPlatform;
- _file->_minOSVersion = ((macho_version_min_command<P>*)cmd)->version();
+ lcPlatforms.add({Options::platformForLoadCommand(cmd->cmd(), useSimulatorVariant()), ((macho_version_min_command<P>*)cmd)->version()});
+ _file->_platforms.add({Options::platformForLoadCommand(cmd->cmd(), useSimulatorVariant()), ((macho_version_min_command<P>*)cmd)->version()});
break;
case LC_BUILD_VERSION:
{
const macho_build_version_command<P>* buildVersCmd = (macho_build_version_command<P>*)cmd;
if ( ignoreMismatchPlatform )
break;
- lcPlatform = (Options::Platform)buildVersCmd->platform();
- _file->_platform = lcPlatform;
- _file->_minOSVersion = buildVersCmd->minos();
+ lcPlatforms.add({(ld::Platform)buildVersCmd->platform(), buildVersCmd->minos()});
+ _file->_platforms.add({(ld::Platform)buildVersCmd->platform(), buildVersCmd->minos()});
const macho_build_tool_version<P>* entry = (macho_build_tool_version<P>*)((uint8_t*)cmd + sizeof(macho_build_version_command<P>));
for (uint32_t t=0; t < buildVersCmd->ntools(); ++t) {
_file->_toolVersions.push_back(std::make_pair(entry->tool(), entry->version()));
if ( cmd > cmdsEnd )
throwf("malformed mach-o file, load command #%d is outside size of load commands", i);
}
+
// arm/arm64 objects are default to ios platform if not set.
// rdar://problem/21746314
- if (lcPlatform == Options::kPlatformUnknown &&
+ if (lcPlatforms.empty() &&
(std::is_same<A, arm>::value || std::is_same<A, arm64>::value))
- lcPlatform = Options::kPlatformiOS;
+ lcPlatforms.add({ld::kPlatform_iOS,0});
// Check platform cross-linking.
if ( !ignoreMismatchPlatform ) {
- if ( lcPlatform != platform ) {
- switch (platform) {
- case Options::kPlatformOSX:
- case Options::kPlatformiOS:
- if ( lcPlatform == Options::kPlatformUnknown )
- break;
- // fall through if the Platform is not Unknown
- case Options::kPlatform_bridgeOS:
- case Options::kPlatformWatchOS:
- // Error when using bitcocde, warning otherwise.
- if (_usingBitcode)
- throwf("building for %s%s, but linking in object file built for %s,",
- Options::platformName(platform), (simulator ? " simulator" : ""),
- Options::platformName(lcPlatform));
- else
- warning("URGENT: building for %s%s, but linking in object file (%s) built for %s. "
- "Note: This will be an error in the future.",
- Options::platformName(platform), (simulator ? " simulator" : ""), path(),
- Options::platformName(lcPlatform));
- break;
- #if SUPPORT_APPLE_TV
- case Options::kPlatform_tvOS:
- // Error when using bitcocde, warning otherwise.
- if (_usingBitcode)
- throwf("building for %s%s, but linking in object file built for %s,",
- Options::platformName(platform), (simulator ? " simulator" : ""),
- Options::platformName(lcPlatform));
- else
- warning("URGENT: building for %s%s, but linking in object file (%s) built for %s. "
- "Note: This will be an error in the future.",
- Options::platformName(platform), (simulator ? " simulator" : ""), path(),
- Options::platformName(lcPlatform));
- break;
- #endif
- case Options::kPlatformUnknown:
- // skip if the target platform is unknown
- break;
+ __block bool warned = false;
+ platforms.forEach(^(ld::Platform platform, uint32_t version, bool &stop) {
+ if ( !warned && !lcPlatforms.contains(platform) ) {
+ if (_usingBitcode)
+ throwf("building for %s, but linking in object file built for %s,",
+ platforms.to_str().c_str(), lcPlatforms.to_str().c_str());
+#if 0
+// FIXME: Re-enable once clang supports zippering
+// <rdar://problem/36749415> Turn off "urgent:" linker warning about iOSMac / macOS mismatch
+ else
+ warning("URGENT: building for %s, but linking in object file (%s) built for %s. "
+ "Note: This will be an error in the future.",
+ platforms.to_str().c_str(), path(), lcPlatforms.to_str().c_str());
+#endif
+ warned = true;
}
- }
- if ( linkMinOSVersion && (_file->_minOSVersion > linkMinOSVersion) ) {
- char t1[32];
- char t2[32];
- versionToString(_file->_minOSVersion, t1);
- versionToString(linkMinOSVersion, t2);
- warning("object file (%s) was built for newer %s version (%s) than being linked (%s)",
- _path, Options::platformName(lcPlatform), t1, t2);
- }
+ if ( version && (lcPlatforms.minOS(platform) > version) ) {
+ char t1[32];
+ char t2[32];
+ versionToString(lcPlatforms.minOS(platform), t1);
+ versionToString(version, t2);
+ warning("object file (%s) was built for newer %s version (%s) than being linked (%s)",
+ _path, Options::platformName(platform), t1, t2);
+ }
+ });
}
-
- // record range of sections
+ // validate just one segment
if ( segment == NULL )
throw "missing LC_SEGMENT";
+ if ( segment->filesize() > _fileLength )
+ throw "LC_SEGMENT filesize too large";
+
+ // record and validate sections
_sectionsStart = (macho_section<P>*)((char*)segment + sizeof(macho_segment_command<P>));
_machOSectionsCount = segment->nsects();
if ( (sizeof(macho_segment_command<P>) + _machOSectionsCount * sizeof(macho_section<P>)) > segment->cmdsize() )
throw "too many sections for size of LC_SEGMENT command";
+
return true;
}
template <typename A>
-Options::Platform Parser<A>::findPlatform(const macho_header<P>* header)
+ld::Platform Parser<A>::findPlatform(const macho_header<P>* header, uint32_t* minOsVers)
{
const uint32_t cmd_count = header->ncmds();
if ( cmd_count == 0 )
- return Options::kPlatformUnknown;
+ return ld::kPlatform_unknown;
const macho_load_command<P>* const cmds = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>));
const macho_load_command<P>* const cmdsEnd = (macho_load_command<P>*)((char*)header + sizeof(macho_header<P>) + header->sizeofcmds());
const macho_load_command<P>* cmd = cmds;
const uint8_t* endOfCmd = ((uint8_t*)cmd)+cmd->cmdsize();
if ( endOfCmd > (uint8_t*)cmdsEnd )
throwf("load command #%d extends beyond the end of the load commands", i);
+ const macho_version_min_command<P>* versCmd = (macho_version_min_command<P>*)cmd;
+ const macho_build_version_command<P>* buildVersCmd = (macho_build_version_command<P>*)cmd;
+ *minOsVers = versCmd->version();
switch (cmd->cmd()) {
case LC_VERSION_MIN_MACOSX:
- return Options::kPlatformOSX;
+ return ld::kPlatform_macOS;
case LC_VERSION_MIN_IPHONEOS:
- return Options::kPlatformiOS;
+ if (useSimulatorVariant())
+ return ld::kPlatform_iOSSimulator;
+ else
+ return ld::kPlatform_iOS;
case LC_VERSION_MIN_WATCHOS:
- return Options::kPlatformWatchOS;
- #if SUPPORT_APPLE_TV
+ if (useSimulatorVariant())
+ return ld::kPlatform_watchOSSimulator;
+ else
+ return ld::kPlatform_watchOS;
case LC_VERSION_MIN_TVOS:
- return Options::kPlatform_tvOS;
- #endif
+ if (useSimulatorVariant())
+ return ld::kPlatform_tvOSSimulator;
+ else
+ return ld::kPlatform_tvOS;
case LC_BUILD_VERSION:
- return (Options::Platform)((macho_build_version_command<P>*)cmd)->platform();
+ *minOsVers = buildVersCmd->minos();
+ return (ld::Platform)buildVersCmd->platform();
}
cmd = (const macho_load_command<P>*)(((char*)cmd)+cmd->cmdsize());
if ( cmd > cmdsEnd )
throwf("malformed mach-o file, load command #%d is outside size of load commands", i);
}
- return Options::kPlatformUnknown;
+ *minOsVers = 0;
+ return ld::kPlatform_unknown;
}
const uint32_t* contents = (uint32_t*)(_file->fileContent()+sect->offset());
if ( (sect->size() >= 8) && (contents[0] == 0) ) {
uint32_t flags = E::get32(contents[1]);
- if ( (flags & 4) == 4 )
- _file->_objConstraint = ld::File::objcConstraintGC;
- else if ( (flags & 2) == 2 )
- _file->_objConstraint = ld::File::objcConstraintRetainReleaseOrGC;
- else if ( (flags & 32) == 32 )
- _file->_objConstraint = ld::File::objcConstraintRetainReleaseForSimulator;
- else
- _file->_objConstraint = ld::File::objcConstraintRetainRelease;
+ _file->_hasObjC = true;
_file->_swiftVersion = ((flags >> 8) & 0xFF);
_file->_objcHasCategoryClassPropertiesField = (flags & 64);
if ( sect->size() > 8 ) {
ld::Fixup::Cluster cl = ld::Fixup::k1of3;
ld::Fixup::Kind firstKind = ld::Fixup::kindSetTargetAddress;
bool combined = false;
+
+#if SUPPORT_ARCH_arm64e
+ bool isAuthenticated = setKind == ld::Fixup::kindStoreLittleEndianAuth64;
+ // Authenticated pointers need an extra fixup for the auth data.
+ if (isAuthenticated)
+ cl = ld::Fixup::k2of4;
+#endif
if ( target.addend == 0 ) {
cl = ld::Fixup::k1of1;
combined = true;
case ld::Fixup::kindStoreARM64TLVPLoadPageOff12:
firstKind = ld::Fixup::kindStoreTargetAddressARM64TLVPLoadPageOff12;
break;
+#endif
+#if SUPPORT_ARCH_arm64e
+ case ld::Fixup::kindStoreLittleEndianAuth64:
+ firstKind = ld::Fixup::kindStoreTargetAddressLittleEndianAuth64;
+ cl = ld::Fixup::k2of2;
+ break;
#endif
default:
combined = false;
}
}
+#if SUPPORT_ARCH_arm64e
+ // As the auth data is independent of the addend and target, we can just always
+ // put it first.
+ if (isAuthenticated) {
+ if (cl == ld::Fixup::k2of2) {
+ addFixup(src, ld::Fixup::k1of2, ld::Fixup::kindSetAuthData, target.authData);
+ } else {
+ assert(cl == ld::Fixup::k2of4);
+ addFixup(src, ld::Fixup::k1of4, ld::Fixup::kindSetAuthData, target.authData);
+ }
+ }
+#endif
+
if ( target.atom != NULL ) {
if ( target.atom->scope() == ld::Atom::scopeTranslationUnit ) {
addFixup(src, cl, firstKind, target.atom);
addFixup(src, cl, firstKind, target.weakImport, target.name);
}
if ( target.addend == 0 ) {
+#if SUPPORT_ARCH_arm64e
+ if (isAuthenticated)
+ assert(combined);
+#endif
if ( ! combined )
addFixup(src, ld::Fixup::k2of2, setKind);
}
else {
- addFixup(src, ld::Fixup::k2of3, ld::Fixup::kindAddAddend, target.addend);
- addFixup(src, ld::Fixup::k3of3, setKind);
+#if SUPPORT_ARCH_arm64e
+ if (isAuthenticated) {
+ addFixup(src, ld::Fixup::k3of4, ld::Fixup::kindAddAddend, target.addend);
+ addFixup(src, ld::Fixup::k4of4, setKind);
+ } else
+#endif
+ {
+ addFixup(src, ld::Fixup::k2of3, ld::Fixup::kindAddAddend, target.addend);
+ addFixup(src, ld::Fixup::k3of3, setKind);
+ }
}
}
}
else {
// make named atom for label
- //fprintf(stderr, " 0x%08llX make labeled\n", (uint64_t)foundAddr);
+ //fprintf(stderr, " 0x%08llX make labeled: %s\n", (uint64_t)foundAddr, parser.nameFromSymbol(*foundLabel));
new (allocatedSpace) Atom<A>(*this, parser, *foundLabel, labeledAtomSize);
}
if ( !skip ) {
Parser<x86_64>::TargetDesc target;
Parser<x86_64>::TargetDesc toTarget;
src.atom = this->findAtomByAddress(srcAddr);
+ if ( src.atom == NULL )
+ throwf("malformed mach-o, reloc addr 0x%llX not in any atom", srcAddr);
src.offsetInAtom = srcAddr - src.atom->_objAddress;
const uint8_t* fixUpPtr = file().fileContent() + sect->offset() + reloc->r_address();
uint64_t contentValue = 0;
parser.addFixups(src, ld::Fixup::kindStoreARM64PointerToGOT, target);
}
break;
+#if SUPPORT_ARCH_arm64e
+ case ARM64_RELOC_AUTHENTICATED_POINTER: {
+ if ( reloc->r_pcrel() )
+ throw "pcrel and ARM64_RELOC_AUTHENTICATED_POINTER not supported";
+ if ( ! reloc->r_extern() )
+ throw "r_extern == 0 and ARM64_RELOC_AUTHENTICATED_POINTER not supported";
+ // An authenticated pointer is:
+ // {
+ // int32_t addend;
+ // uint16_t diversityData;
+ // uint16_t hasAddressDiversity : 1;
+ // uint16_t key : 2;
+ // uint16_t zeroes : 11;
+ // uint16_t zero : 1;
+ // uint16_t authenticated : 1;
+ // }
+ target.addend = (int32_t)(contentValue & 0xFFFFFFFF);
+ if (parser._supportsAuthenticatedPointers) {
+ target.authData.discriminator = (uint16_t)(contentValue >> 32);
+ target.authData.hasAddressDiversity = (contentValue & (1ULL << 48)) != 0;
+ target.authData.key = (ld::Fixup::AuthData::ptrauth_key)((contentValue >> 49) & 0x3);
+ } else {
+ static bool emittedWarning = false;
+ if (!emittedWarning) {
+ emittedWarning = true;
+ warning("stripping authenticated relocation as image uses -preload or -static");
+ }
+ }
+ bool isAuthenticated = (contentValue & (1ULL << 63)) != 0;
+ if (!isAuthenticated)
+ throw "ARM64_RELOC_AUTHENTICATED_POINTER value must have authenticated bit set";
+ switch ( reloc->r_length() ) {
+ case 0:
+ case 1:
+ case 2:
+ throw "length < 3 and ARM64_RELOC_AUTHENTICATED_POINTER not supported";
+ case 3:
+ if (parser._supportsAuthenticatedPointers)
+ parser.addFixups(src, ld::Fixup::kindStoreLittleEndianAuth64, target);
+ else
+ parser.addFixups(src, ld::Fixup::kindStoreLittleEndian64, target);
+ break;
+ }
+ break;
+ }
+#endif
default:
throwf("unknown relocation type %d", reloc->r_type());
}
//
// used by linker to infer architecture when no -arch is on command line
//
-bool isObjectFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* subResult, Options::Platform* platform)
+bool isObjectFile(const uint8_t* fileContent, cpu_type_t* result, cpu_subtype_t* subResult, ld::Platform* platform, uint32_t* minOsVers)
{
if ( mach_o::relocatable::Parser<x86_64>::validFile(fileContent) ) {
*result = CPU_TYPE_X86_64;
const macho_header<Pointer64<LittleEndian> >* header = (const macho_header<Pointer64<LittleEndian> >*)fileContent;
*subResult = header->cpusubtype();
- *platform = Parser<x86_64>::findPlatform(header);
+ *platform = Parser<x86_64>::findPlatform(header, minOsVers);
return true;
}
if ( mach_o::relocatable::Parser<x86>::validFile(fileContent) ) {
const macho_header<Pointer32<LittleEndian> >* header = (const macho_header<Pointer32<LittleEndian> >*)fileContent;
*result = CPU_TYPE_I386;
*subResult = CPU_SUBTYPE_X86_ALL;
- *platform = Parser<x86>::findPlatform(header);
+ *platform = Parser<x86>::findPlatform(header, minOsVers);
return true;
}
if ( mach_o::relocatable::Parser<arm>::validFile(fileContent, false, 0) ) {
const macho_header<Pointer32<LittleEndian> >* header = (const macho_header<Pointer32<LittleEndian> >*)fileContent;
*result = CPU_TYPE_ARM;
*subResult = header->cpusubtype();
- *platform = Parser<arm>::findPlatform(header);
+ *platform = Parser<arm>::findPlatform(header, minOsVers);
return true;
}
if ( mach_o::relocatable::Parser<arm64>::validFile(fileContent, false, 0) ) {
const macho_header<Pointer64<LittleEndian> >* header = (const macho_header<Pointer64<LittleEndian> >*)fileContent;
*result = CPU_TYPE_ARM64;
*subResult = header->cpusubtype();
- *platform = Parser<arm64>::findPlatform(header);
+ *platform = Parser<arm64>::findPlatform(header, minOsVers);
return true;
}
return false;
else if ( mach_o::relocatable::Parser<x86>::validFile(fileContent, false, 0) ) {
return mach_o::relocatable::Parser<x86>::getNonLocalSymbols(fileContent, syms);
}
+#if SUPPORT_ARCH_arm64
else if ( mach_o::relocatable::Parser<arm64>::validFile(fileContent, false, 0) ) {
return mach_o::relocatable::Parser<arm64>::getNonLocalSymbols(fileContent, syms);
}
+#endif
return false;
}