From 40576fa0e924f8f6e56cf09ac19e76379720b6c7 Mon Sep 17 00:00:00 2001 From: Pete Cooper Date: Thu, 4 Feb 2016 02:45:23 +0000 Subject: [PATCH] Add support for the source_version cmdline option. This is of the form A.B.C.D.E and to match ld64's behaviour, is always output to files, even when the version is 0. rdar://problem/24472630 llvm-svn: 259746 --- lld/include/lld/ReaderWriter/MachOLinkingContext.h | 8 ++++++ lld/lib/Driver/DarwinLdDriver.cpp | 11 ++++++++ lld/lib/Driver/DarwinLdOptions.td | 3 +++ lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp | 29 ++++++++++++++++++++++ .../MachO/MachONormalizedFileBinaryWriter.cpp | 15 +++++++++++ .../MachO/MachONormalizedFileFromAtoms.cpp | 1 + 6 files changed, 67 insertions(+) diff --git a/lld/include/lld/ReaderWriter/MachOLinkingContext.h b/lld/include/lld/ReaderWriter/MachOLinkingContext.h index f317072..fec165d 100644 --- a/lld/include/lld/ReaderWriter/MachOLinkingContext.h +++ b/lld/include/lld/ReaderWriter/MachOLinkingContext.h @@ -169,6 +169,9 @@ public: uint32_t sdkVersion() const { return _sdkVersion; } void setSdkVersion(uint64_t v) { _sdkVersion = v; } + uint64_t sourceVersion() const { return _sourceVersion; } + void setSourceVersion(uint64_t v) { _sourceVersion = v; } + uint32_t swiftVersion() const { return _swiftVersion; } /// \brief Checks whether a given path on the filesystem exists. @@ -371,6 +374,10 @@ public: /// bits are xxxx.yy.zz. Largest number is 65535.255.255 static bool parsePackedVersion(StringRef str, uint32_t &result); + /// Construct 64-bit value from string "A.B.C.D.E" where + /// bits are aaaa.bb.cc.dd.ee. Largest number is 16777215.1023.1023.1023.1023 + static bool parsePackedVersion(StringRef str, uint64_t &result); + void finalizeInputFiles() override; std::error_code handleLoadedFile(File &file) override; @@ -424,6 +431,7 @@ private: OS _os; uint32_t _osMinVersion; uint32_t _sdkVersion = 0; + uint64_t _sourceVersion = 0; uint64_t _pageZeroSize; uint64_t _pageSize; uint64_t _baseAddress; diff --git a/lld/lib/Driver/DarwinLdDriver.cpp b/lld/lib/Driver/DarwinLdDriver.cpp index 7b82dbe..494da5b 100644 --- a/lld/lib/Driver/DarwinLdDriver.cpp +++ b/lld/lib/Driver/DarwinLdDriver.cpp @@ -812,6 +812,17 @@ bool DarwinLdDriver::parse(llvm::ArrayRef args, ctx.setSdkVersion(ctx.osMinVersion()); } + // Handle source_version + if (llvm::opt::Arg *arg = parsedArgs.getLastArg(OPT_source_version)) { + uint64_t version = 0; + if (MachOLinkingContext::parsePackedVersion(arg->getValue(), + version)) { + diagnostics << "error: malformed source_version value\n"; + return false; + } + ctx.setSourceVersion(version); + } + // Handle stack_size if (llvm::opt::Arg *stackSize = parsedArgs.getLastArg(OPT_stack_size)) { uint64_t stackSizeVal; diff --git a/lld/lib/Driver/DarwinLdOptions.td b/lld/lib/Driver/DarwinLdOptions.td index 74ccc83..576cf3f 100644 --- a/lld/lib/Driver/DarwinLdOptions.td +++ b/lld/lib/Driver/DarwinLdOptions.td @@ -36,6 +36,9 @@ def ios_simulator_version_min : Separate<["-"], "ios_simulator_version_min">, def sdk_version : Separate<["-"], "sdk_version">, MetaVarName<"">, HelpText<"SDK version">, Group; +def source_version : Separate<["-"], "source_version">, + MetaVarName<"">, + HelpText<"Source version">, Group; def version_load_command : Flag<["-"], "version_load_command">, HelpText<"Force generation of a version load command">, Group; def no_version_load_command : Flag<["-"], "no_version_load_command">, diff --git a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp index c758612..5e7db8f 100644 --- a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp +++ b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp @@ -76,6 +76,35 @@ bool MachOLinkingContext::parsePackedVersion(StringRef str, uint32_t &result) { return false; } +bool MachOLinkingContext::parsePackedVersion(StringRef str, uint64_t &result) { + result = 0; + + if (str.empty()) + return false; + + SmallVector parts; + llvm::SplitString(str, parts, "."); + + uint64_t num; + if (llvm::getAsUnsignedInteger(parts[0], 10, num)) + return true; + if (num > 0xFFFFFF) + return true; + result = num << 40; + + unsigned Shift = 30; + for (StringRef str : llvm::makeArrayRef(parts).slice(1)) { + if (llvm::getAsUnsignedInteger(str, 10, num)) + return true; + if (num > 0x3FF) + return true; + result |= (num << Shift); + Shift -= 10; + } + + return false; +} + MachOLinkingContext::ArchInfo MachOLinkingContext::_s_archInfos[] = { { "x86_64", arch_x86_64, true, CPU_TYPE_X86_64, CPU_SUBTYPE_X86_64_ALL }, { "i386", arch_x86, true, CPU_TYPE_I386, CPU_SUBTYPE_X86_ALL }, diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp index 0eb2b11..4e303dd 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp @@ -467,6 +467,10 @@ uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) { ++count; } + // Add LC_SOURCE_VERSION + size += sizeof(source_version_command); + ++count; + // If main executable add LC_MAIN if (_file.fileType == llvm::MachO::MH_EXECUTE) { size += sizeof(entry_point_command); @@ -915,6 +919,17 @@ std::error_code MachOFileLayout::writeLoadCommands() { // LC_VERSION_MIN_TVOS writeVersionMinLoadCommand(_file, _swap, lc); + // Add LC_SOURCE_VERSION + { + source_version_command* sv = reinterpret_cast(lc); + sv->cmd = LC_SOURCE_VERSION; + sv->cmdsize = sizeof(source_version_command); + sv->version = _file.sourceVersion; + if (_swap) + swapStruct(*sv); + lc += sizeof(source_version_command); + } + // If main executable, add LC_MAIN. if (_file.fileType == llvm::MachO::MH_EXECUTE) { // Build LC_MAIN load command. diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp index c7fd2ca..6ac567b 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp @@ -1285,6 +1285,7 @@ normalizedFromAtoms(const lld::File &atomFile, normFile.minOSVersionKind = util.minVersionCommandType(); normFile.sdkVersion = context.sdkVersion(); + normFile.sourceVersion = context.sourceVersion(); if (context.generateVersionLoadCommand() && context.os() != MachOLinkingContext::OS::unknown) -- 2.7.4