[llvm-branch-commits] [lld] d058b69 - [lld/mac] implement -compatibility_version, -current_version
Nico Weber via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Mon Dec 14 15:45:54 PST 2020
Author: Nico Weber
Date: 2020-12-14T18:41:36-05:00
New Revision: d058b69b1cd3d71b9bcb45011f5f3ef3a576a5e2
URL: https://github.com/llvm/llvm-project/commit/d058b69b1cd3d71b9bcb45011f5f3ef3a576a5e2
DIFF: https://github.com/llvm/llvm-project/commit/d058b69b1cd3d71b9bcb45011f5f3ef3a576a5e2.diff
LOG: [lld/mac] implement -compatibility_version, -current_version
Differential Revision: https://reviews.llvm.org/D93237
Added:
lld/test/MachO/dylib-version.s
Modified:
lld/MachO/Config.h
lld/MachO/Driver.cpp
lld/MachO/Options.td
lld/MachO/Writer.cpp
Removed:
################################################################################
diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index 2835b5c1546e..029b9ab2296c 100644
--- a/lld/MachO/Config.h
+++ b/lld/MachO/Config.h
@@ -44,6 +44,8 @@ struct Configuration {
bool searchDylibsFirst = false;
bool saveTemps = false;
uint32_t headerPad;
+ uint32_t dylibCompatibilityVersion = 0;
+ uint32_t dylibCurrentVersion = 0;
llvm::StringRef installName;
llvm::StringRef outputFile;
llvm::StringRef ltoObjPath;
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 73846d420096..c456d2fb1fd5 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -663,6 +663,46 @@ static void parseClangOption(StringRef opt, const Twine &msg) {
error(msg + ": " + StringRef(err).trim());
}
+static uint32_t parseDylibVersion(const opt::ArgList& args, unsigned id) {
+ const opt::Arg *arg = args.getLastArg(id);
+ if (!arg)
+ return 0;
+
+ if (config->outputType != MH_DYLIB) {
+ error(arg->getAsString(args) + ": only valid with -dylib");
+ return 0;
+ }
+
+ llvm::VersionTuple version;
+ if (version.tryParse(arg->getValue()) || version.getBuild().hasValue()) {
+ error(arg->getAsString(args) + ": malformed version");
+ return 0;
+ }
+
+ unsigned major = version.getMajor();
+ if (major > UINT16_MAX) {
+ error(arg->getAsString(args) + ": component " + Twine(major) +
+ " out of range");
+ return 0;
+ }
+
+ unsigned minor = version.getMinor().getValueOr(0);
+ if (minor > UINT8_MAX) {
+ error(arg->getAsString(args) + ": component " + Twine(minor) +
+ " out of range");
+ return 0;
+ }
+
+ unsigned subminor = version.getSubminor().getValueOr(0);
+ if (subminor > UINT8_MAX) {
+ error(arg->getAsString(args) + ": component " + Twine(subminor) +
+ " out of range");
+ return 0;
+ }
+
+ return (major << 16) | (minor << 8) | subminor;
+}
+
bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
raw_ostream &stdoutOS, raw_ostream &stderrOS) {
lld::stdoutOS = &stdoutOS;
@@ -732,6 +772,10 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
config->searchDylibsFirst =
(arg && arg->getOption().getID() == OPT_search_dylibs_first);
+ config->dylibCompatibilityVersion =
+ parseDylibVersion(args, OPT_compatibility_version);
+ config->dylibCurrentVersion = parseDylibVersion(args, OPT_current_version);
+
config->saveTemps = args.hasArg(OPT_save_temps);
if (args.hasArg(OPT_v)) {
diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index d1d06879cafa..ca666613e3b9 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -290,7 +290,6 @@ def mark_dead_strippable_dylib : Flag<["-"], "mark_dead_strippable_dylib">,
def compatibility_version : Separate<["-"], "compatibility_version">,
MetaVarName<"<version>">,
HelpText<"Compatibility <version> of this library">,
- Flags<[HelpHidden]>,
Group<grp_dylib>;
def dylib_compatibility_version : Separate<["-"], "dylib_compatibility_version">,
MetaVarName<"<version>">,
@@ -301,7 +300,6 @@ def dylib_compatibility_version : Separate<["-"], "dylib_compatibility_version">
def current_version : Separate<["-"], "current_version">,
MetaVarName<"<version>">,
HelpText<"Current <version> of this library">,
- Flags<[HelpHidden]>,
Group<grp_dylib>;
def dylib_current_version : Separate<["-"], "dylib_current_version">,
MetaVarName<"<version>">,
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 2d033febb79b..9f6aa0b49692 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -242,7 +242,10 @@ class LCSymtab : public LoadCommand {
// * LC_REEXPORT_DYLIB
class LCDylib : public LoadCommand {
public:
- LCDylib(LoadCommandType type, StringRef path) : type(type), path(path) {
+ LCDylib(LoadCommandType type, StringRef path,
+ uint32_t compatibilityVersion = 0, uint32_t currentVersion = 0)
+ : type(type), path(path), compatibilityVersion(compatibilityVersion),
+ currentVersion(currentVersion) {
instanceCount++;
}
@@ -257,6 +260,9 @@ class LCDylib : public LoadCommand {
c->cmd = type;
c->cmdsize = getSize();
c->dylib.name = sizeof(dylib_command);
+ c->dylib.timestamp = 0;
+ c->dylib.compatibility_version = compatibilityVersion;
+ c->dylib.current_version = currentVersion;
memcpy(buf, path.data(), path.size());
buf[path.size()] = '\0';
@@ -267,6 +273,8 @@ class LCDylib : public LoadCommand {
private:
LoadCommandType type;
StringRef path;
+ uint32_t compatibilityVersion;
+ uint32_t currentVersion;
static uint32_t instanceCount;
};
@@ -431,7 +439,9 @@ void Writer::createLoadCommands() {
in.header->addLoadCommand(make<LCLoadDylinker>());
break;
case MH_DYLIB:
- in.header->addLoadCommand(make<LCDylib>(LC_ID_DYLIB, config->installName));
+ in.header->addLoadCommand(make<LCDylib>(LC_ID_DYLIB, config->installName,
+ config->dylibCompatibilityVersion,
+ config->dylibCurrentVersion));
break;
case MH_BUNDLE:
break;
diff --git a/lld/test/MachO/dylib-version.s b/lld/test/MachO/dylib-version.s
new file mode 100644
index 000000000000..41c3c6135d1d
--- /dev/null
+++ b/lld/test/MachO/dylib-version.s
@@ -0,0 +1,57 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
+
+# RUN: not %lld -o %t/executable %t.o -o /dev/null \
+# RUN: -compatibility_version 10 -current_version 11 2>&1 | \
+# RUN: FileCheck --check-prefix=NEEDDYLIB %s
+# RUN: not %lld -execute -o %t/executable %t.o -o /dev/null \
+# RUN: -compatibility_version 10 -current_version 11 2>&1 | \
+# RUN: FileCheck --check-prefix=NEEDDYLIB %s
+# RUN: not %lld -bundle -o %t/executable %t.o -o /dev/null \
+# RUN: -compatibility_version 10 -current_version 11 2>&1 | \
+# RUN: FileCheck --check-prefix=NEEDDYLIB %s
+
+# NEEDDYLIB: error: -compatibility_version 10: only valid with -dylib
+# NEEDDYLIB: error: -current_version 11: only valid with -dylib
+
+# RUN: not %lld -dylib -o %t/executable %t.o -o /dev/null \
+# RUN: -compatibility_version 1.2.3.4 -current_version 1.2.3.4.5 2>&1 | \
+# RUN: FileCheck --check-prefix=MALFORMED %s
+
+# MALFORMED: error: -compatibility_version 1.2.3.4: malformed version
+# MALFORMED: error: -current_version 1.2.3.4.5: malformed version
+
+# RUN: not %lld -dylib -o %t/executable %t.o -o /dev/null \
+# RUN: -compatibility_version 80000.1 -current_version 1.2.3 2>&1 | \
+# RUN: FileCheck --check-prefix=BADMAJOR %s
+
+# BADMAJOR: error: -compatibility_version 80000.1: component 80000 out of range
+
+# RUN: not %lld -dylib -o %t/executable %t.o -o /dev/null \
+# RUN: -compatibility_version 8.300 -current_version 1.2.3 2>&1 | \
+# RUN: FileCheck --check-prefix=BADMINOR %s
+
+# BADMINOR: error: -compatibility_version 8.300: component 300 out of range
+
+# RUN: not %lld -dylib -o %t/executable %t.o -o /dev/null \
+# RUN: -compatibility_version 8.8.300 -current_version 1.2.3 2>&1 | \
+# RUN: FileCheck --check-prefix=BADSUBMINOR %s
+
+# BADSUBMINOR: error: -compatibility_version 8.8.300: component 300 out of range
+
+# RUN: %lld -dylib -o %t/executable %t.o -o %t.dylib \
+# RUN: -compatibility_version 1.2.3 -current_version 2.5.6
+# RUN: llvm-objdump --macho --all-headers %t.dylib | FileCheck %s
+
+# CHECK: cmd LC_ID_DYLIB
+# CHECK-NEXT: cmdsize
+# CHECK-NEXT: name
+# CHECK-NEXT: time stamp
+# CHECK-NEXT: current version 2.5.6
+# CHECK-NEXT: compatibility version 1.2.3
+
+.text
+.global _foo
+_foo:
+ mov $0, %rax
+ ret
More information about the llvm-branch-commits
mailing list