virtual void setUUID(const uint8_t digest[16]) = 0;
virtual void recopyUUIDCommand() = 0;
+ virtual const uint8_t* getUUID() const = 0;
+ virtual bool bitcodeBundleCommand(uint64_t& cmdOffset, uint64_t& cmdEnd,
+ uint64_t& sectOffset, uint64_t& sectEnd) const = 0;
+ virtual void linkeditCmdInfo(uint64_t& offset, uint64_t& size) const = 0;
+ virtual void symbolTableCmdInfo(uint64_t& offset, uint64_t& size) const = 0;
+
};
template <typename A>
// overrides of HeaderAndLoadCommandsAbtract
virtual void setUUID(const uint8_t digest[16]) { memcpy(_uuid, digest, 16); }
virtual void recopyUUIDCommand();
-
+ virtual const uint8_t* getUUID() const { return &_uuid[0]; }
+ virtual bool bitcodeBundleCommand(uint64_t& cmdOffset, uint64_t& cmdEnd,
+ uint64_t& sectOffset, uint64_t& sectEnd) const;
+ virtual void linkeditCmdInfo(uint64_t& offset, uint64_t& size) const;
+ virtual void symbolTableCmdInfo(uint64_t& offset, uint64_t& size) const;
+
+
private:
typedef typename A::P P;
typedef typename A::P::E E;
uint32_t commandsCount() const;
uint32_t threadLoadCommandSize() const;
uint8_t* copySingleSegmentLoadCommand(uint8_t* p) const;
- uint8_t* copySegmentLoadCommands(uint8_t* p) const;
+ uint8_t* copySegmentLoadCommands(uint8_t* p, uint8_t* base) const;
uint8_t* copyDyldInfoLoadCommand(uint8_t* p) const;
- uint8_t* copySymbolTableLoadCommand(uint8_t* p) const;
+ uint8_t* copySymbolTableLoadCommand(uint8_t* p, uint8_t* base) const;
uint8_t* copyDynamicSymbolTableLoadCommand(uint8_t* p) const;
uint8_t* copyDyldLoadCommand(uint8_t* p) const;
uint8_t* copyDylibIDLoadCommand(uint8_t* p) const;
uint8_t* copyRoutinesLoadCommand(uint8_t* p) const;
uint8_t* copyUUIDLoadCommand(uint8_t* p) const;
uint8_t* copyVersionLoadCommand(uint8_t* p) const;
+ uint8_t* copyBuildVersionLoadCommand(uint8_t* p) const;
uint8_t* copySourceVersionLoadCommand(uint8_t* p) const;
uint8_t* copyThreadsLoadCommand(uint8_t* p) const;
uint8_t* copyEntryPointLoadCommand(uint8_t* p) const;
uint8_t* copySubUmbrellaLoadCommand(uint8_t* p, const char* name) const;
uint8_t* copyFunctionStartsLoadCommand(uint8_t* p) const;
uint8_t* copyDataInCodeLoadCommand(uint8_t* p) const;
- uint8_t* copyDependentDRLoadCommand(uint8_t* p) const;
uint8_t* copyDyldEnvLoadCommand(uint8_t* p, const char* env) const;
uint8_t* copyLinkerOptionsLoadCommand(uint8_t* p, const std::vector<const char*>&) const;
uint8_t* copyOptimizationHintsLoadCommand(uint8_t* p) const;
bool _hasRPathLoadCommands;
bool _hasSubFrameworkLoadCommand;
bool _hasVersionLoadCommand;
+ bool _hasBuildVersionLoadCommand;
bool _hasFunctionStartsLoadCommand;
bool _hasDataInCodeLoadCommand;
bool _hasSourceVersionLoadCommand;
- bool _hasDependentDRInfo;
bool _hasOptimizationHints;
+ Options::Platform _platform;
uint32_t _dylibLoadCommmandsCount;
uint32_t _allowableClientLoadCommmandsCount;
uint32_t _dyldEnvironExrasCount;
std::vector<const char*> _subUmbrellaNames;
uint8_t _uuid[16];
mutable macho_uuid_command<P>* _uuidCmdInOutputBuffer;
+ mutable uint32_t _linkeditCmdOffset;
+ mutable uint32_t _symboltableCmdOffset;
std::vector< std::vector<const char*> > _linkerOptions;
+ std::unordered_set<uint64_t>& _toolsVersions;
static ld::Section _s_section;
static ld::Section _s_preload_section;
ld::Atom::definitionRegular, ld::Atom::combineNever,
ld::Atom::scopeTranslationUnit, ld::Atom::typeUnclassified,
ld::Atom::symbolTableNotIn, false, false, false,
- (opts.outputKind() == Options::kPreload) ? ld::Atom::Alignment(0) : ld::Atom::Alignment(12) ),
- _options(opts), _state(state), _writer(writer), _address(0), _uuidCmdInOutputBuffer(NULL)
+ (opts.outputKind() == Options::kPreload) ? ld::Atom::Alignment(0) : ld::Atom::Alignment(log2(opts.segmentAlignment())) ),
+ _options(opts), _state(state), _writer(writer), _address(0), _uuidCmdInOutputBuffer(NULL), _linkeditCmdOffset(0), _symboltableCmdOffset(0),
+ _toolsVersions(state.toolsVersions)
{
bzero(_uuid, 16);
_hasDyldInfoLoadCommand = opts.makeCompressedDyldInfo();
break;
}
}
- for (CStringSet::const_iterator it = _state.linkerOptionFrameworks.begin(); it != _state.linkerOptionFrameworks.end(); ++it) {
- const char* frameWorkName = *it;
+ for (const char* frameworkName : _state.unprocessedLinkerOptionFrameworks) {
std::vector<const char*>* lo = new std::vector<const char*>();
lo->push_back("-framework");
- lo->push_back(frameWorkName);
+ lo->push_back(frameworkName);
_linkerOptions.push_back(*lo);
};
- for (CStringSet::const_iterator it = _state.linkerOptionLibraries.begin(); it != _state.linkerOptionLibraries.end(); ++it) {
- const char* libName = *it;
+ for (const char* libName : _state.unprocessedLinkerOptionLibraries) {
std::vector<const char*>* lo = new std::vector<const char*>();
char * s = new char[strlen(libName)+3];
strcpy(s, "-l");
}
_hasRPathLoadCommands = (_options.rpaths().size() != 0);
_hasSubFrameworkLoadCommand = (_options.umbrellaName() != NULL);
- _hasVersionLoadCommand = _options.addVersionLoadCommand();
+ _platform = _options.platform();
+ if ( (_platform == Options::kPlatformUnknown) && (_state.derivedPlatform != 0) )
+ _platform = (Options::Platform)_state.derivedPlatform;
+ if ( _options.addVersionLoadCommand() ) {
+ _hasBuildVersionLoadCommand = _options.addBuildVersionLoadCommand();
+ _hasVersionLoadCommand = !_hasBuildVersionLoadCommand;
+ }
+ else if (((_options.outputKind() == Options::kObjectFile) && (_platform != Options::kPlatformUnknown) && !state.objectFileFoundWithNoVersion) ) {
+ _hasBuildVersionLoadCommand = (_platform == Options::kPlatform_bridgeOS);
+ _hasVersionLoadCommand = !_hasBuildVersionLoadCommand;
+ }
+ else {
+ _hasVersionLoadCommand = false;
+ _hasBuildVersionLoadCommand = false;
+ }
_hasFunctionStartsLoadCommand = _options.addFunctionStarts();
_hasDataInCodeLoadCommand = _options.addDataInCodeInfo();
_hasSourceVersionLoadCommand = _options.needsSourceVersionLoadCommand();
- _hasDependentDRInfo = _options.needsDependentDRInfo();
_dylibLoadCommmandsCount = _writer.dylibCount();
_allowableClientLoadCommmandsCount = _options.allowableClients().size();
_dyldEnvironExrasCount = _options.dyldEnvironExtras().size();
return count;
}
+template <typename A>
+bool HeaderAndLoadCommandsAtom<A>::bitcodeBundleCommand(uint64_t &cmdOffset, uint64_t &cmdEnd,
+ uint64_t §Offset, uint64_t §End) const
+{
+ if ( _options.outputKind() == Options::kObjectFile ) {
+ return false;
+ }
+ cmdOffset = sizeof(macho_header<P>);
+ const char* lastSegName = "";
+ for (std::vector<ld::Internal::FinalSection*>::iterator it = _state.sections.begin(); it != _state.sections.end(); ++it) {
+ if ( strcmp(lastSegName, (*it)->segmentName()) != 0 ) {
+ lastSegName = (*it)->segmentName();
+ cmdOffset += sizeof(macho_segment_command<P>);
+ }
+ if ( strcmp((*it)->segmentName(), "__LLVM") == 0 && strcmp((*it)->sectionName(), "__bundle") == 0 ) {
+ sectOffset = (*it)->fileOffset;
+ sectEnd = (*(it + 1))->fileOffset;
+ cmdEnd = cmdOffset + sizeof(macho_section<P>);
+ return true;
+ }
+ if ( ! (*it)->isSectionHidden() )
+ cmdOffset += sizeof(macho_section<P>);
+ }
+ return false;
+}
+
+template <typename A>
+void HeaderAndLoadCommandsAtom<A>::linkeditCmdInfo(uint64_t &offset, uint64_t &size) const
+{
+ offset = _linkeditCmdOffset;
+ size = sizeof(macho_segment_command<P>);
+}
+
+template <typename A>
+void HeaderAndLoadCommandsAtom<A>::symbolTableCmdInfo(uint64_t &offset, uint64_t &size) const
+{
+ offset = _symboltableCmdOffset;
+ size = sizeof(macho_symtab_command<P>);
+}
+
template <typename A>
uint64_t HeaderAndLoadCommandsAtom<A>::size() const
if ( _hasVersionLoadCommand )
sz += sizeof(macho_version_min_command<P>);
+ if ( _hasBuildVersionLoadCommand )
+ sz += alignedSize(sizeof(macho_build_version_command<P>) + sizeof(macho_build_tool_version<P>)*_toolsVersions.size());
+
if ( _hasSourceVersionLoadCommand )
sz += sizeof(macho_source_version_command<P>);
}
}
- if ( _hasDependentDRInfo )
- sz += sizeof(macho_linkedit_data_command<P>);
-
if ( _hasOptimizationHints )
sz += sizeof(macho_linkedit_data_command<P>);
if ( _hasVersionLoadCommand )
++count;
+ if ( _hasBuildVersionLoadCommand )
+ ++count;
+
if ( _hasSourceVersionLoadCommand )
++count;
}
}
- if ( _hasDependentDRInfo )
- ++count;
-
if ( _hasOptimizationHints )
++count;
bits |= MH_HAS_TLV_DESCRIPTORS;
if ( _options.hasNonExecutableHeap() )
bits |= MH_NO_HEAP_EXECUTION;
+ if ( _options.markAppExtensionSafe() && (_options.outputKind() == Options::kDynamicLibrary) )
+ bits |= MH_APP_EXTENSION_SAFE;
}
if ( _options.hasExecutableStack() )
bits |= MH_ALLOW_STACK_EXECUTION;
template <> uint32_t HeaderAndLoadCommandsAtom<arm64>::cpuType() const { return CPU_TYPE_ARM64; }
-
template <>
uint32_t HeaderAndLoadCommandsAtom<x86>::cpuSubType() const
{
template <>
uint32_t HeaderAndLoadCommandsAtom<arm64>::cpuSubType() const
{
- return CPU_SUBTYPE_ARM64_ALL;
+ return _state.cpuSubType;
}
if ( cmd->fileoff() == 0 )
cmd->set_fileoff(fsect->fileOffset);
cmd->set_vmsize(fsect->address + fsect->size - cmd->vmaddr());
- if ( (fsect->type() != ld::Section::typeZeroFill) && (fsect->type() != ld::Section::typeTentativeDefs) )
+ if ( !sectionTakesNoDiskSpace(fsect) )
cmd->set_filesize(fsect->fileOffset + fsect->size - cmd->fileoff());
++msect;
}
SegInfo(const char* n, const Options&);
const char* segName;
uint32_t nonHiddenSectionCount;
+ uint32_t nonSectCreateSections;
uint32_t maxProt;
uint32_t initProt;
std::vector<ld::Internal::FinalSection*> sections;
SegInfo::SegInfo(const char* n, const Options& opts)
- : segName(n), nonHiddenSectionCount(0), maxProt(opts.maxSegProtection(n)), initProt(opts.initialSegProtection(n))
+ : segName(n), nonHiddenSectionCount(0), nonSectCreateSections(0), maxProt(opts.maxSegProtection(n)), initProt(opts.initialSegProtection(n))
{
}
return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
else if ( (strncmp(sect->sectionName(), "__objc_nlcatlist", 16) == 0) && (strcmp(sect->segmentName(), "__DATA") == 0) )
return S_REGULAR | S_ATTR_NO_DEAD_STRIP;
+ else if ( (_options.outputKind() == Options::kObjectFile) && !sect->atoms.empty() && sect->atoms.front()->dontDeadStripIfReferencesLive() )
+ return S_REGULAR | S_ATTR_LIVE_SUPPORT;
else
return S_REGULAR;
case ld::Section::typeCode:
case ld::Section::typeTempLTO:
assert(0 && "typeTempLTO should not make it to final linked image");
return S_REGULAR;
+ case ld::Section::typeTempAlias:
+ assert(0 && "typeAlias should not make it to final linked image");
+ return S_REGULAR;
case ld::Section::typeAbsoluteSymbols:
assert(0 && "typeAbsoluteSymbols should not make it to final linked image");
return S_REGULAR;
return S_REGULAR;
case ld::Section::typeDebug:
return S_REGULAR | S_ATTR_DEBUG;
+ case ld::Section::typeSectCreate:
+ return S_REGULAR;
}
return S_REGULAR;
}
template <typename A>
-uint8_t* HeaderAndLoadCommandsAtom<A>::copySegmentLoadCommands(uint8_t* p) const
+uint8_t* HeaderAndLoadCommandsAtom<A>::copySegmentLoadCommands(uint8_t* p, uint8_t* base) const
{
// group sections into segments
std::vector<SegInfo> segs;
}
if ( ! sect->isSectionHidden() )
segs.back().nonHiddenSectionCount++;
+ if ( sect->type() != ld::Section::typeSectCreate )
+ segs.back().nonSectCreateSections++;
+
segs.back().sections.push_back(sect);
}
// write out segment load commands for each section with trailing sections
segCmd->set_maxprot(si.maxProt);
segCmd->set_initprot(si.initProt);
segCmd->set_nsects(si.nonHiddenSectionCount);
- segCmd->set_flags(0);
+ segCmd->set_flags(si.nonSectCreateSections ? 0 : SG_NORELOC); // FIXME, really should check all References
+ if ( strcmp(segCmd->segname(), "__LINKEDIT") == 0 )
+ _linkeditCmdOffset = p - base;
p += sizeof(macho_segment_command<P>);
macho_section<P>* msect = (macho_section<P>*)p;
for (std::vector<ld::Internal::FinalSection*>::iterator sit = si.sections.begin(); sit != si.sections.end(); ++sit) {
template <typename A>
-uint8_t* HeaderAndLoadCommandsAtom<A>::copySymbolTableLoadCommand(uint8_t* p) const
+uint8_t* HeaderAndLoadCommandsAtom<A>::copySymbolTableLoadCommand(uint8_t* p, uint8_t* base) const
{
+ _symboltableCmdOffset = p - base;
// build LC_SYMTAB command
macho_symtab_command<P>* symbolTableCmd = (macho_symtab_command<P>*)p;
symbolTableCmd->set_cmd(LC_SYMTAB);
uint8_t* HeaderAndLoadCommandsAtom<A>::copyVersionLoadCommand(uint8_t* p) const
{
macho_version_min_command<P>* cmd = (macho_version_min_command<P>*)p;
- ld::MacVersionMin macVersion = _options.macosxVersionMin();
- ld::IOSVersionMin iOSVersion = _options.iOSVersionMin();
- assert( (macVersion != ld::macVersionUnset) || (iOSVersion != ld::iOSVersionUnset) );
- if ( macVersion != ld::macVersionUnset ) {
- cmd->set_cmd(LC_VERSION_MIN_MACOSX);
- cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
- cmd->set_version((uint32_t)macVersion);
- cmd->set_sdk(_options.sdkVersion());
- }
- else {
- cmd->set_cmd(LC_VERSION_MIN_IPHONEOS);
- cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
- cmd->set_version((uint32_t)iOSVersion);
- cmd->set_sdk(_options.sdkVersion());
+ switch (_platform) {
+ case Options::kPlatformOSX:
+ cmd->set_cmd(LC_VERSION_MIN_MACOSX);
+ cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
+ cmd->set_version(_state.minOSVersion);
+ cmd->set_sdk(_options.sdkVersion());
+ break;
+ case Options::kPlatformiOS:
+ cmd->set_cmd(LC_VERSION_MIN_IPHONEOS);
+ cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
+ cmd->set_version(_state.minOSVersion);
+ cmd->set_sdk(_options.sdkVersion());
+ break;
+ case Options::kPlatformWatchOS:
+ cmd->set_cmd(LC_VERSION_MIN_WATCHOS);
+ cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
+ cmd->set_version(_state.minOSVersion);
+ cmd->set_sdk(_options.sdkVersion());
+ break;
+#if SUPPORT_APPLE_TV
+ case Options::kPlatform_tvOS:
+ cmd->set_cmd(LC_VERSION_MIN_TVOS);
+ cmd->set_cmdsize(sizeof(macho_version_min_command<P>));
+ cmd->set_version(_state.minOSVersion);
+ cmd->set_sdk(_options.sdkVersion());
+ break;
+#endif
+ case Options::kPlatformUnknown:
+ assert(0 && "unknown platform");
+ break;
+ case Options::kPlatform_bridgeOS:
+ assert(0 && "bridgeOS uses LC_BUILD_VERSION");
+ break;
}
return p + sizeof(macho_version_min_command<P>);
}
+
+
+template <typename A>
+uint8_t* HeaderAndLoadCommandsAtom<A>::copyBuildVersionLoadCommand(uint8_t* p) const
+{
+ macho_build_version_command<P>* cmd = (macho_build_version_command<P>*)p;
+
+ cmd->set_cmd(LC_BUILD_VERSION);
+ cmd->set_cmdsize(alignedSize(sizeof(macho_build_version_command<P>) + sizeof(macho_build_tool_version<P>)*_toolsVersions.size()));
+ cmd->set_platform(_options.platform());
+ cmd->set_minos(_state.minOSVersion);
+ cmd->set_sdk(_options.sdkVersion());
+ cmd->set_ntools(_toolsVersions.size());
+ macho_build_tool_version<P>* tools = (macho_build_tool_version<P>*)(p + sizeof(macho_build_version_command<P>));
+ for (uint64_t tool : _toolsVersions) {
+ tools->set_tool((uint64_t)tool >> 32);
+ tools->set_version(tool & 0xFFFFFFFF);
+ ++tools;
+ }
+
+ return p + cmd->cmdsize();
+}
+
+
template <typename A>
uint8_t* HeaderAndLoadCommandsAtom<A>::copySourceVersionLoadCommand(uint8_t* p) const
{
template <>
uint32_t HeaderAndLoadCommandsAtom<x86_64>::threadLoadCommandSize() const
{
- return this->alignedSize(16 + x86_THREAD_STATE64_COUNT * 4);
+ return this->alignedSize(16 + 42*4); // base size + x86_THREAD_STATE64_COUNT * 4
}
template <>
macho_thread_command<P>* cmd = (macho_thread_command<P>*)p;
cmd->set_cmd(LC_UNIXTHREAD);
cmd->set_cmdsize(threadLoadCommandSize());
- cmd->set_flavor(x86_THREAD_STATE64);
- cmd->set_count(x86_THREAD_STATE64_COUNT);
+ cmd->set_flavor(4); // x86_THREAD_STATE64
+ cmd->set_count(42); // x86_THREAD_STATE64_COUNT
cmd->set_thread_register(16, start); // rip
if ( _options.hasCustomStack() )
cmd->set_thread_register(7, _options.customStackAddr()); // r1
{
uint32_t sz = alignedSize(sizeof(macho_dylib_command<P>) + strlen(dylib->installPath()) + 1);
macho_dylib_command<P>* cmd = (macho_dylib_command<P>*)p;
+ bool weakLink = dylib->forcedWeakLinked() || dylib->allSymbolsAreWeakImported();
+ bool upward = dylib->willBeUpwardDylib() && _options.useUpwardDylibs();
+ bool reExport = dylib->willBeReExported() && _options.useSimplifiedDylibReExports();
+ if ( weakLink && upward )
+ warning("cannot weak upward link. Dropping weak for %s", dylib->installPath());
+ if ( weakLink && reExport )
+ warning("cannot weak re-export a dylib. Dropping weak for %s", dylib->installPath());
if ( dylib->willBeLazyLoadedDylib() )
cmd->set_cmd(LC_LAZY_LOAD_DYLIB);
- else if ( dylib->forcedWeakLinked() || dylib->allSymbolsAreWeakImported() )
- cmd->set_cmd(LC_LOAD_WEAK_DYLIB);
- else if ( dylib->willBeReExported() && _options.useSimplifiedDylibReExports() )
+ else if ( reExport )
cmd->set_cmd(LC_REEXPORT_DYLIB);
- else if ( dylib->willBeUpwardDylib() && _options.useUpwardDylibs() )
+ else if ( upward )
cmd->set_cmd(LC_LOAD_UPWARD_DYLIB);
+ else if ( weakLink )
+ cmd->set_cmd(LC_LOAD_WEAK_DYLIB);
else
cmd->set_cmd(LC_LOAD_DYLIB);
cmd->set_cmdsize(sz);
}
-template <typename A>
-uint8_t* HeaderAndLoadCommandsAtom<A>::copyDependentDRLoadCommand(uint8_t* p) const
-{
- macho_linkedit_data_command<P>* cmd = (macho_linkedit_data_command<P>*)p;
- cmd->set_cmd(LC_DYLIB_CODE_SIGN_DRS);
- cmd->set_cmdsize(sizeof(macho_linkedit_data_command<P>));
- cmd->set_dataoff(_writer.dependentDRsSection->fileOffset);
- cmd->set_datasize(_writer.dependentDRsSection->size);
- return p + sizeof(macho_linkedit_data_command<P>);
-}
-
-
template <typename A>
uint8_t* HeaderAndLoadCommandsAtom<A>::copyOptimizationHintsLoadCommand(uint8_t* p) const
if ( _options.outputKind() == Options::kObjectFile )
p = this->copySingleSegmentLoadCommand(p);
else
- p = this->copySegmentLoadCommands(p);
+ p = this->copySegmentLoadCommands(p, buffer);
if ( _hasDylibIDLoadCommand )
p = this->copyDylibIDLoadCommand(p);
p = this->copyDyldInfoLoadCommand(p);
if ( _hasSymbolTableLoadCommand )
- p = this->copySymbolTableLoadCommand(p);
+ p = this->copySymbolTableLoadCommand(p, buffer);
if ( _hasDynamicSymbolTableLoadCommand )
p = this->copyDynamicSymbolTableLoadCommand(p);
if ( _hasVersionLoadCommand )
p = this->copyVersionLoadCommand(p);
+ if ( _hasBuildVersionLoadCommand )
+ p = this->copyBuildVersionLoadCommand(p);
+
if ( _hasSourceVersionLoadCommand )
p = this->copySourceVersionLoadCommand(p);
}
}
- if ( _hasDependentDRInfo )
- p = this->copyDependentDRLoadCommand(p);
-
if ( _hasOptimizationHints )
p = this->copyOptimizationHintsLoadCommand(p);