summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Kledzik <kledzik@apple.com>2014-11-19 02:21:53 +0000
committerNick Kledzik <kledzik@apple.com>2014-11-19 02:21:53 +0000
commit5b9e48b4cec3834303db0f80e6ee197b1dc5e2a4 (patch)
tree52511b3371adf95d089fcd0d5cd23c7cbd8657d8
parent970dda295e708a54df1c9516c365a915ba68e96c (diff)
downloadbcm5719-llvm-5b9e48b4cec3834303db0f80e6ee197b1dc5e2a4.tar.gz
bcm5719-llvm-5b9e48b4cec3834303db0f80e6ee197b1dc5e2a4.zip
[mach-o] propagate dylib version numbers
Mach-o does not use a simple SO_NEEDED to track dependent dylibs. Instead, the linker copies four things from each dylib to each client: the runtime path (aka "install name"), the build time, current version (dylib build number), and compatibility version The build time is no longer used (it cause every rebuild of a dylib to be different). The compatibility version is usually just 1.0 and never changes, or the dylib becomes incompatible. This patch copies that information into the NormalizedMachO format and propagates it to clients. llvm-svn: 222300
-rw-r--r--lld/include/lld/ReaderWriter/MachOLinkingContext.h4
-rw-r--r--lld/lib/ReaderWriter/MachO/File.h14
-rw-r--r--lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp16
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFile.h16
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp12
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp4
-rw-r--r--lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp34
-rw-r--r--lld/test/mach-o/dylib-install-names.yaml6
-rw-r--r--lld/test/mach-o/lazy-bind-x86_64.yaml40
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
+
+
OpenPOWER on IntegriCloud