diff options
11 files changed, 125 insertions, 29 deletions
diff --git a/lld/include/lld/ReaderWriter/MachOLinkingContext.h b/lld/include/lld/ReaderWriter/MachOLinkingContext.h index ef4de3b47c8..e1822a028a4 100644 --- a/lld/include/lld/ReaderWriter/MachOLinkingContext.h +++ b/lld/include/lld/ReaderWriter/MachOLinkingContext.h @@ -254,6 +254,10 @@ public: /// search paths to allow indirect dylibs to be overridden. mach_o::MachODylibFile* findIndirectDylib(StringRef path); + uint32_t dylibCurrentVersion(StringRef installName) const; + + uint32_t dylibCompatVersion(StringRef installName) const; + /// Creates a copy (owned by this MachOLinkingContext) of a string. StringRef copy(StringRef str) { return str.copy(_allocator); } diff --git a/lld/lib/ReaderWriter/MachO/File.h b/lld/lib/ReaderWriter/MachO/File.h index cc98cd51f57..7d0292d0e93 100644 --- a/lld/lib/ReaderWriter/MachO/File.h +++ b/lld/lib/ReaderWriter/MachO/File.h @@ -198,8 +198,10 @@ private: class MachODylibFile : public SharedLibraryFile { public: - MachODylibFile(StringRef path, StringRef installName) - : SharedLibraryFile(path), _installName(installName) { + MachODylibFile(StringRef path, StringRef installName, uint32_t compatVersion, + uint32_t currentVersion) + : SharedLibraryFile(path), _installName(installName), + _currentVersion(currentVersion), _compatVersion(compatVersion) { } const SharedLibraryAtom *exports(StringRef name, @@ -243,6 +245,10 @@ public: StringRef installName() { return _installName; } + uint32_t currentVersion() { return _currentVersion; } + + uint32_t compatVersion() { return _compatVersion; } + typedef std::function<MachODylibFile *(StringRef)> FindDylib; void loadReExportedDylibs(FindDylib find) { @@ -292,7 +298,9 @@ private: bool weakDef; }; - StringRef _installName; + StringRef _installName; + uint32_t _currentVersion; + uint32_t _compatVersion; atom_collection_vector<DefinedAtom> _definedAtoms; atom_collection_vector<UndefinedAtom> _undefinedAtoms; atom_collection_vector<SharedLibraryAtom> _sharedLibraryAtoms; diff --git a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp index 8bdee4e446a..3e91e4a56b3 100644 --- a/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp +++ b/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp @@ -652,6 +652,22 @@ MachODylibFile* MachOLinkingContext::findIndirectDylib(StringRef path) { return nullptr; } +uint32_t MachOLinkingContext::dylibCurrentVersion(StringRef installName) const { + auto pos = _pathToDylibMap.find(installName); + if (pos != _pathToDylibMap.end()) + return pos->second->currentVersion(); + else + return 0x1000; // 1.0 +} + +uint32_t MachOLinkingContext::dylibCompatVersion(StringRef installName) const { + auto pos = _pathToDylibMap.find(installName); + if (pos != _pathToDylibMap.end()) + return pos->second->compatVersion(); + else + return 0x1000; // 1.0 +} + bool MachOLinkingContext::createImplicitFiles( std::vector<std::unique_ptr<File> > &result) { // Add indirect dylibs by asking each linked dylib to add its indirects. diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h b/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h index 29d2fc8ea01..64b8231eb2b 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h @@ -1,4 +1,4 @@ -//===- lib/ReaderWriter/MachO/NormalizedFile.h ----------------------===// +//===- lib/ReaderWriter/MachO/MachONormalizedFile.h -----------------------===// // // The LLVM Linker // @@ -145,6 +145,9 @@ struct Symbol { /// A typedef so that YAML I/O can (de/en)code the protection bits of a segment. LLVM_YAML_STRONG_TYPEDEF(uint32_t, VMProtect) +/// A typedef to hold verions X.Y.X packed into 32-bit xxxx.yy.zz +LLVM_YAML_STRONG_TYPEDEF(uint32_t, PackedVersion) + /// Segments are only used in normalized final linked images (not in relocatable /// object files). They specify how a range of the file is loaded. struct Segment { @@ -159,6 +162,8 @@ struct Segment { struct DependentDylib { StringRef path; LoadCommandType kind; + PackedVersion compatVersion; + PackedVersion currentVersion; }; /// A normalized rebasing entry. Only used in normalized final linked images. @@ -203,7 +208,6 @@ struct DataInCode { /// A typedef so that YAML I/O can encode/decode mach_header.flags. LLVM_YAML_STRONG_TYPEDEF(uint32_t, FileFlags) - /// struct NormalizedFile { NormalizedFile() : arch(MachOLinkingContext::arch_unknown), @@ -225,14 +229,16 @@ struct NormalizedFile { // Maps to load commands with no LINKEDIT content (final linked images only). std::vector<DependentDylib> dependentDylibs; - StringRef installName; + StringRef installName; // dylibs only + PackedVersion compatVersion; // dylibs only + PackedVersion currentVersion; // dylibs only bool hasUUID; std::vector<StringRef> rpaths; Hex64 entryAddress; MachOLinkingContext::OS os; Hex64 sourceVersion; - Hex32 minOSverson; - Hex32 sdkVersion; + PackedVersion minOSverson; + PackedVersion sdkVersion; // Maps to load commands with LINKEDIT content (final linked images only). Hex32 pageSize; diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp index 042cca7125d..a05fa750326 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp @@ -455,8 +455,10 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb, DependentDylib entry; entry.path = lc + read32(&dl->dylib.name, isBig); entry.kind = LoadCommandType(cmd); + entry.compatVersion = read32(&dl->dylib.compatibility_version, isBig); + entry.currentVersion = read32(&dl->dylib.current_version, isBig); f->dependentDylibs.push_back(entry); - } + } break; case LC_DYLD_INFO: case LC_DYLD_INFO_ONLY: diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp index 3bc341ffa3a..71643bda02c 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp @@ -734,9 +734,9 @@ std::error_code MachOFileLayout::writeLoadCommands() { dc->cmd = LC_ID_DYLIB; dc->cmdsize = size; dc->dylib.name = sizeof(dylib_command); // offset - dc->dylib.timestamp = 0; // FIXME - dc->dylib.current_version = 0; // FIXME - dc->dylib.compatibility_version = 0; // FIXME + dc->dylib.timestamp = 2; + dc->dylib.current_version = _file.currentVersion; + dc->dylib.compatibility_version = _file.compatVersion; if (_swap) swapStruct(*dc); memcpy(lc + sizeof(dylib_command), path.begin(), path.size()); @@ -834,9 +834,9 @@ std::error_code MachOFileLayout::writeLoadCommands() { dc->cmd = dep.kind; dc->cmdsize = size; dc->dylib.name = sizeof(dylib_command); // offset - dc->dylib.timestamp = 0; // FIXME - dc->dylib.current_version = 0; // FIXME - dc->dylib.compatibility_version = 0; // FIXME + dc->dylib.timestamp = 2; + dc->dylib.current_version = dep.currentVersion; + dc->dylib.compatibility_version = dep.compatVersion; if (_swap) swapStruct(*dc); memcpy(lc+sizeof(dylib_command), dep.path.begin(), dep.path.size()); diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp index a668dadb129..19a7e45b4df 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp @@ -941,6 +941,8 @@ void Util::addDependentDylibs(const lld::File &atomFile,NormalizedFile &nFile) { DependentDylib depInfo; depInfo.path = loadPath; depInfo.kind = llvm::MachO::LC_LOAD_DYLIB; + depInfo.currentVersion = _context.dylibCurrentVersion(loadPath); + depInfo.compatVersion = _context.dylibCompatVersion(loadPath); nFile.dependentDylibs.push_back(depInfo); } else { if ( slAtom->canBeNullAtRuntime() ) @@ -1188,6 +1190,8 @@ normalizedFromAtoms(const lld::File &atomFile, normFile.fileType = context.outputMachOType(); normFile.flags = util.fileFlags(); normFile.installName = context.installName(); + normFile.currentVersion = context.currentVersion(); + normFile.compatVersion = context.compatibilityVersion(); normFile.pageSize = context.pageSize(); util.addDependentDylibs(atomFile, normFile); util.copySegmentInfo(normFile); diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp index a94329e50f9..7465fb2e613 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp @@ -820,7 +820,9 @@ normalizedDylibToAtoms(const NormalizedFile &normalizedFile, StringRef path, bool copyRefs) { // Instantiate SharedLibraryFile object. std::unique_ptr<MachODylibFile> file( - new MachODylibFile(path, normalizedFile.installName)); + new MachODylibFile(path, normalizedFile.installName, + normalizedFile.compatVersion, + normalizedFile.currentVersion)); // Tell MachODylibFile object about all symbols it exports. if (!normalizedFile.exportInfo.empty()) { // If exports trie exists, use it instead of traditional symbol table. diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp index af4fc587484..ae14d755e2b 100644 --- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp +++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp @@ -25,6 +25,7 @@ #include "llvm/ADT/Twine.h" #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" +#include "llvm/Support/Format.h" #include "llvm/Support/MachO.h" #include "llvm/Support/MemoryBuffer.h" #include "llvm/Support/SourceMgr.h" @@ -529,8 +530,13 @@ struct ScalarEnumerationTraits<LoadCommandType> { template <> struct MappingTraits<DependentDylib> { static void mapping(IO &io, DependentDylib& dylib) { - io.mapRequired("path", dylib.path); - io.mapOptional("kind", dylib.kind, llvm::MachO::LC_LOAD_DYLIB); + io.mapRequired("path", dylib.path); + io.mapOptional("kind", dylib.kind, + llvm::MachO::LC_LOAD_DYLIB); + io.mapOptional("compat-version", dylib.compatVersion, + PackedVersion(0x10000)); + io.mapOptional("current-version", dylib.currentVersion, + PackedVersion(0x10000)); } }; @@ -650,6 +656,24 @@ struct MappingTraits<DataInCode> { } }; +template <> +struct ScalarTraits<PackedVersion> { + static void output(const PackedVersion &value, void*, raw_ostream &out) { + out << llvm::format("%d.%d", (value >> 16), (value >> 8) & 0xFF); + if (value & 0xFF) { + out << llvm::format(".%d", (value & 0xFF)); + } + } + static StringRef input(StringRef scalar, void*, PackedVersion &result) { + uint32_t value; + if (lld::MachOLinkingContext::parsePackedVersion(scalar, value)) + return "malformed version number"; + result = value; + // Return the empty string on success, + return StringRef(); + } + static bool mustQuote(StringRef) { return false; } +}; template <> struct MappingTraits<NormalizedFile> { @@ -659,13 +683,15 @@ struct MappingTraits<NormalizedFile> { io.mapOptional("flags", file.flags); io.mapOptional("dependents", file.dependentDylibs); io.mapOptional("install-name", file.installName, StringRef()); + io.mapOptional("compat-version", file.compatVersion, PackedVersion(0x10000)); + io.mapOptional("current-version", file.currentVersion, PackedVersion(0x10000)); io.mapOptional("has-UUID", file.hasUUID, true); io.mapOptional("rpaths", file.rpaths); io.mapOptional("entry-point", file.entryAddress, Hex64(0)); io.mapOptional("source-version", file.sourceVersion, Hex64(0)); io.mapOptional("OS", file.os); - io.mapOptional("min-os-version", file.minOSverson, Hex32(0)); - io.mapOptional("sdk-version", file.sdkVersion, Hex32(0)); + io.mapOptional("min-os-version", file.minOSverson, PackedVersion(0)); + io.mapOptional("sdk-version", file.sdkVersion, PackedVersion(0)); io.mapOptional("segments", file.segments); io.mapOptional("sections", file.sections); io.mapOptional("local-symbols", file.localSymbols); diff --git a/lld/test/mach-o/dylib-install-names.yaml b/lld/test/mach-o/dylib-install-names.yaml index 5f4fde8deee..a79581c0e26 100644 --- a/lld/test/mach-o/dylib-install-names.yaml +++ b/lld/test/mach-o/dylib-install-names.yaml @@ -1,5 +1,6 @@ # Check we accept -install_name correctly: # RUN: lld -flavor darwin -arch x86_64 -install_name libwibble.dylib -dylib \ +# RUN: -compatibility_version 2.0 -current_version 5.3 \ # RUN: %p/Inputs/libSystem.yaml %s -o %t.dylib # RUN: macho-dump %t.dylib | FileCheck %s --check-prefix=CHECK-BINARY-WRITE @@ -9,12 +10,14 @@ # Check we default the install-name to the output file: # RUN: lld -flavor darwin -arch x86_64 -dylib %s -o libwibble.dylib \ +# RUN: -compatibility_version 2.0 -current_version 5.3 \ # RUN: %p/Inputs/libSystem.yaml # RUN: macho-dump libwibble.dylib | FileCheck %s --check-prefix=CHECK-BINARY-WRITE # RUN: rm -f libwibble.dylib # Check -single_module does nothing # RUN: lld -flavor darwin -arch x86_64 -dylib %s -install_name libwibble.dylib \ +# RUN: -compatibility_version 2.0 -current_version 5.3 \ # RUN: -single_module -o %t2.dylib %p/Inputs/libSystem.yaml # RUN: macho-dump %t2.dylib | FileCheck %s --check-prefix=CHECK-BINARY-WRITE @@ -51,6 +54,9 @@ global-symbols: # CHECK-BINARY-WRITE: (('command', 13) # CHECK-BINARY-WRITE-NEXT: ('size', 40) # CHECK-BINARY-WRITE-NEXT: ('install_name', 'libwibble.dylib') +# CHECK-BINARY-WRITE-NEXT: ('timestamp, +# CHECK-BINARY-WRITE-NEXT: ('cur_version, 328448) +# CHECK-BINARY-WRITE-NEXT: ('compat_version, 131072) # CHECK-BINARY-READ: shared-library-atoms: # CHECK-BINARY-READ: - name: _myGlobal diff --git a/lld/test/mach-o/lazy-bind-x86_64.yaml b/lld/test/mach-o/lazy-bind-x86_64.yaml index 0a474ffe5f8..a6800098823 100644 --- a/lld/test/mach-o/lazy-bind-x86_64.yaml +++ b/lld/test/mach-o/lazy-bind-x86_64.yaml @@ -3,6 +3,7 @@ # RUN: llvm-objdump -lazy-bind %t | FileCheck %s # RUN: llvm-nm -m %t | FileCheck --check-prefix=CHECK-NM %s # RUN: llvm-objdump -disassemble %t | FileCheck --check-prefix=CHECK-HELPERS %s +# RUN: llvm-objdump -private-headers %t | FileCheck --check-prefix=CHECK-DYLIBS %s # # Test that correct two-level namespace ordinals are used for lazy bindings. # @@ -61,23 +62,29 @@ undefined-symbols: value: 0x0000000000000000 --- !mach-o -arch: x86_64 -file-type: MH_DYLIB -install-name: /usr/lib/libbar.dylib +arch: x86_64 +file-type: MH_DYLIB +install-name: /usr/lib/libbar.dylib +compat-version: 1.0 +current-version: 2.3 exports: - name: _bar --- !mach-o -arch: x86_64 -file-type: MH_DYLIB -install-name: /usr/lib/libfoo.dylib +arch: x86_64 +file-type: MH_DYLIB +install-name: /usr/lib/libfoo.dylib +compat-version: 2.0 +current-version: 3.4 exports: - name: _foo --- !mach-o -arch: x86_64 -file-type: MH_DYLIB -install-name: /usr/lib/libbaz.dylib +arch: x86_64 +file-type: MH_DYLIB +install-name: /usr/lib/libbaz.dylib +compat-version: 3.0 +current-version: 4.5 exports: - name: _baz @@ -99,3 +106,18 @@ exports: # CHECK-HELPERS: 68 10 00 00 00 pushq $16 # CHECK-HELPERS: 68 20 00 00 00 pushq $32 + +# CHECK-DYLIBS: cmd LC_LOAD_DYLIB +# CHECK-DYLIBS: name /usr/lib/libbar.dylib (offset 24) +# CHECK-DYLIBS: current version 2.3.0 +# CHECK-DYLIBS: compatibility version 1.0.0 +# CHECK-DYLIBS: cmd LC_LOAD_DYLIB +# CHECK-DYLIBS: name /usr/lib/libfoo.dylib (offset 24) +# CHECK-DYLIBS: current version 3.4.0 +# CHECK-DYLIBS: compatibility version 2.0.0 +# CHECK-DYLIBS: cmd LC_LOAD_DYLIB +# CHECK-DYLIBS: name /usr/lib/libbaz.dylib (offset 24) +# CHECK-DYLIBS: current version 4.5.0 +# CHECK-DYLIBS: compatibility version 3.0.0 + + |

