[lld] d058b69 - [lld/mac] implement -compatibility_version, -current_version

Nico Weber via llvm-commits llvm-commits at lists.llvm.org
Mon Dec 14 15:41:48 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-commits mailing list