[lld] r190452 - Support darwin linker options:

Nick Kledzik kledzik at apple.com
Tue Sep 10 16:55:14 PDT 2013


Author: kledzik
Date: Tue Sep 10 18:55:14 2013
New Revision: 190452

URL: http://llvm.org/viewvc/llvm-project?rev=190452&view=rev
Log:
Support darwin linker options: 
-current_version, -compatibility_version, and -install_name.

Patch by Joe Ranieri


Modified:
    lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
    lld/trunk/lib/Driver/DarwinLdDriver.cpp
    lld/trunk/lib/Driver/DarwinLdOptions.td
    lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
    lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp

Modified: lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h?rev=190452&r1=190451&r2=190452&view=diff
==============================================================================
--- lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h (original)
+++ lld/trunk/include/lld/ReaderWriter/MachOLinkingContext.h Tue Sep 10 18:55:14 2013
@@ -72,6 +72,52 @@ public:
   void setDoNothing(bool value) { _doNothing = value; }
   bool doNothing() const { return _doNothing; }
 
+  /// \brief The dylib's binary compatibility version, in the raw uint32 format.
+  ///
+  /// When building a dynamic library, this is the compatibility version that
+  /// gets embedded into the result. Other Mach-O binaries that link against
+  /// this library will store the compatibility version in its load command. At
+  /// runtime, the loader will verify that the binary is compatible with the
+  /// installed dynamic library.
+  uint32_t compatibilityVersion() const { return _compatibilityVersion; }
+
+  /// \brief The dylib's current version, in the the raw uint32 format.
+  ///
+  /// When building a dynamic library, this is the current version that gets
+  /// embedded into the result. Other Mach-O binaries that link against
+  /// this library will store the compatibility version in its load command.
+  uint32_t currentVersion() const { return _currentVersion; }
+
+  /// \brief The dylib's install name.
+  ///
+  /// Binaries that link against the dylib will embed this path into the dylib
+  /// load command. When loading the binaries at runtime, this is the location
+  /// on disk that the loader will look for the dylib.
+  StringRef installName() const { return _installName; }
+
+  /// \brief Whether or not the dylib has side effects during initialization.
+  ///
+  /// Dylibs marked as being dead strippable provide the guarantee that loading
+  /// the dylib has no side effects, allowing the linker to strip out the dylib
+  /// when linking a binary that does not use any of its symbols.
+  bool deadStrippableDylib() const { return _deadStrippableDylib; }
+
+  /// \brief The path to the executable that will load the bundle at runtime.
+  ///
+  /// When building a Mach-O bundle, this executable will be examined if there
+  /// are undefined symbols after the main link phase. It is expected that this
+  /// binary will be loading the bundle at runtime and will provide the symbols
+  /// at that point.
+  StringRef bundleLoader() const { return _bundleLoader; }
+
+  void setCompatibilityVersion(uint32_t vers) { _compatibilityVersion = vers; }
+  void setCurrentVersion(uint32_t vers) { _currentVersion = vers; }
+  void setInstallName(StringRef name) { _installName = name; }
+  void setDeadStrippableDylib(bool deadStrippable) {
+    _deadStrippableDylib = deadStrippable;
+  }
+  void setBundleLoader(StringRef loader) { _bundleLoader = loader; }
+
   static Arch archFromCpuType(uint32_t cputype, uint32_t cpusubtype);
   static Arch archFromName(StringRef archName);
   static uint32_t cpuTypeFromArch(Arch arch);
@@ -91,6 +137,11 @@ private:
   OS _os;
   uint32_t _osMinVersion;
   uint64_t _pageZeroSize;
+  uint32_t _compatibilityVersion;
+  uint32_t _currentVersion;
+  StringRef _installName;
+  bool _deadStrippableDylib;
+  StringRef _bundleLoader;
   mutable std::unique_ptr<mach_o::KindHandler> _kindHandler;
   mutable std::unique_ptr<Reader> _machoReader;
   mutable std::unique_ptr<Writer> _writer;

Modified: lld/trunk/lib/Driver/DarwinLdDriver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdDriver.cpp?rev=190452&r1=190451&r2=190452&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdDriver.cpp (original)
+++ lld/trunk/lib/Driver/DarwinLdDriver.cpp Tue Sep 10 18:55:14 2013
@@ -154,6 +154,47 @@ bool DarwinLdDriver::parse(int argc, con
   if (parsedArgs->getLastArg(OPT_all_load))
     globalWholeArchive = true;
 
+  // Handle -install_name
+  if (llvm::opt::Arg *installName = parsedArgs->getLastArg(OPT_install_name))
+    ctx.setInstallName(installName->getValue());
+
+  // Handle -mark_dead_strippable_dylib
+  if (parsedArgs->getLastArg(OPT_mark_dead_strippable_dylib))
+    ctx.setDeadStrippableDylib(true);
+
+  // Handle -compatibility_version and -current_version
+  if (llvm::opt::Arg *vers =
+          parsedArgs->getLastArg(OPT_compatibility_version)) {
+    if (ctx.outputFileType() != mach_o::MH_DYLIB) {
+      diagnostics
+          << "error: -compatibility_version can only be used with -dylib\n";
+      return true;
+    }
+    uint32_t parsedVers;
+    if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) {
+      diagnostics << "error: -compatibility_version value is malformed\n";
+      return true;
+    }
+    ctx.setCompatibilityVersion(parsedVers);
+  }
+
+  if (llvm::opt::Arg *vers = parsedArgs->getLastArg(OPT_current_version)) {
+    if (ctx.outputFileType() != mach_o::MH_DYLIB) {
+      diagnostics << "-current_version can only be used with -dylib\n";
+      return true;
+    }
+    uint32_t parsedVers;
+    if (MachOLinkingContext::parsePackedVersion(vers->getValue(), parsedVers)) {
+      diagnostics << "error: -current_version value is malformed\n";
+      return true;
+    }
+    ctx.setCurrentVersion(parsedVers);
+  }
+
+  // Handle -bundle_loader
+  if (llvm::opt::Arg *loader = parsedArgs->getLastArg(OPT_bundle_loader))
+    ctx.setBundleLoader(loader->getValue());
+
   // Handle -arch xxx
   if (llvm::opt::Arg *archStr = parsedArgs->getLastArg(OPT_arch)) {
     ctx.setArch(MachOLinkingContext::archFromName(archStr->getValue()));

Modified: lld/trunk/lib/Driver/DarwinLdOptions.td
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/Driver/DarwinLdOptions.td?rev=190452&r1=190451&r2=190452&view=diff
==============================================================================
--- lld/trunk/lib/Driver/DarwinLdOptions.td (original)
+++ lld/trunk/lib/Driver/DarwinLdOptions.td Tue Sep 10 18:55:14 2013
@@ -37,6 +37,30 @@ def entry : Separate<["-"], "e">, HelpTe
 
 // dylib executable options
 def grp_dylib : OptionGroup<"opts">, HelpText<"DYLIB EXECUTABLE OPTIONS">;
+def install_name : Separate<["-"], "install_name">,
+    HelpText<"The dylib's install name">, Group<grp_dylib>;
+def mark_dead_strippable_dylib : Flag<["-"], "mark_dead_strippable_dylib">,
+    HelpText<"Marks the dylib as having no side effects during initialization">,
+    Group<grp_dylib>;
+def compatibility_version : Separate<["-"], "compatibility_version">,
+    HelpText<"The dylib's compatibility version">, Group<grp_dylib>;
+def current_version : Separate<["-"], "current_version">,
+    HelpText<"The dylib's current version">, Group<grp_dylib>;
+
+// dylib executable options - compatibility aliases
+def dylib_install_name : Separate<["-"], "dylib_install_name">,
+    Alias<install_name>;
+def dylib_compatibility_version :
+    Separate<["-"], "dylib_compatibility_version">,
+    Alias<compatibility_version>;
+def dylib_current_version : Separate<["-"], "dylib_current_version">,
+    Alias<current_version>;
+
+// bundle executable options
+def grp_bundle : OptionGroup<"opts">, HelpText<"BUNDLE EXECUTABLE OPTIONS">;
+def bundle_loader : Separate<["-"], "bundle_loader">,
+    HelpText<"The executable that will be loading this Mach-O bundle">,
+    Group<grp_bundle>;
 
 // library options
 def grp_libs : OptionGroup<"libs">, HelpText<"LIBRARY OPTIONS">;

Modified: lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp?rev=190452&r1=190451&r2=190452&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachOLinkingContext.cpp Tue Sep 10 18:55:14 2013
@@ -124,7 +124,8 @@ uint32_t MachOLinkingContext::cpuSubtype
 MachOLinkingContext::MachOLinkingContext()
     : _outputFileType(mach_o::MH_EXECUTE), _outputFileTypeStatic(false),
       _doNothing(false), _arch(arch_unknown), _os(OS::macOSX), _osMinVersion(0),
-      _pageZeroSize(0x1000), _kindHandler(nullptr) {}
+      _pageZeroSize(0x1000), _compatibilityVersion(0), _currentVersion(0),
+      _deadStrippableDylib(false), _kindHandler(nullptr) {}
 
 MachOLinkingContext::~MachOLinkingContext() {}
 
@@ -204,6 +205,29 @@ bool MachOLinkingContext::validateImpl(r
     }
   }
 
+  if (_currentVersion && _outputFileType != mach_o::MH_DYLIB) {
+    diagnostics << "error: -current_version can only be used with dylibs\n";
+    return true;
+  }
+
+  if (_compatibilityVersion && _outputFileType != mach_o::MH_DYLIB) {
+    diagnostics
+        << "error: -compatibility_version can only be used with dylibs\n";
+    return true;
+  }
+
+  if (_deadStrippableDylib && _outputFileType != mach_o::MH_DYLIB) {
+    diagnostics
+        << "error: -mark_dead_strippable_dylib can only be used with dylibs.\n";
+    return true;
+  }
+
+  if (!_bundleLoader.empty() && outputFileType() != mach_o::MH_BUNDLE) {
+    diagnostics
+        << "error: -bundle_loader can only be used with Mach-O bundles\n";
+    return true;
+  }
+
   return false;
 }
 

Modified: lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp?rev=190452&r1=190451&r2=190452&view=diff
==============================================================================
--- lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp (original)
+++ lld/trunk/unittests/DriverTests/DarwinLdDriverTest.cpp Tue Sep 10 18:55:14 2013
@@ -169,4 +169,56 @@ TEST_F(DarwinLdParserTest, iOS_Simulator
   EXPECT_TRUE(_context.minOS("", "6.0"));
 }
 
+TEST_F(DarwinLdParserTest, compatibilityVersion) {
+  EXPECT_FALSE(
+      parse("ld", "-dylib", "-compatibility_version", "1.2.3", "a.o", nullptr));
+  EXPECT_EQ(_context.compatibilityVersion(), 0x10203U);
+}
+
+TEST_F(DarwinLdParserTest, compatibilityVersionInvalidType) {
+  EXPECT_TRUE(parse("ld", "-bundle", "-compatibility_version", "1.2.3", "a.o",
+                    nullptr));
+}
+
+TEST_F(DarwinLdParserTest, compatibilityVersionInvalidValue) {
+  EXPECT_TRUE(parse("ld", "-bundle", "-compatibility_version", "1,2,3", "a.o",
+                    nullptr));
+}
+
+TEST_F(DarwinLdParserTest, currentVersion) {
+  EXPECT_FALSE(
+      parse("ld", "-dylib", "-current_version", "1.2.3", "a.o", nullptr));
+  EXPECT_EQ(_context.currentVersion(), 0x10203U);
+}
+
+TEST_F(DarwinLdParserTest, currentVersionInvalidType) {
+  EXPECT_TRUE(
+      parse("ld", "-bundle", "-current_version", "1.2.3", "a.o", nullptr));
+}
+
+TEST_F(DarwinLdParserTest, currentVersionInvalidValue) {
+  EXPECT_TRUE(
+      parse("ld", "-bundle", "-current_version", "1,2,3", "a.o", nullptr));
+}
+
+TEST_F(DarwinLdParserTest, bundleLoader) {
+  EXPECT_FALSE(
+      parse("ld", "-bundle", "-bundle_loader", "/bin/ls", "a.o", nullptr));
+  EXPECT_EQ(_context.bundleLoader(), "/bin/ls");
+}
+
+TEST_F(DarwinLdParserTest, bundleLoaderInvalidType) {
+  EXPECT_TRUE(parse("ld", "-bundle_loader", "/bin/ls", "a.o", nullptr));
+}
+
+TEST_F(DarwinLdParserTest, deadStrippableDylib) {
+  EXPECT_FALSE(
+      parse("ld", "-dylib", "-mark_dead_strippable_dylib", "a.o", nullptr));
+  EXPECT_EQ(true, _context.deadStrippableDylib());
+}
+
+TEST_F(DarwinLdParserTest, deadStrippableDylibInvalidType) {
+  EXPECT_TRUE(parse("ld", "-mark_dead_strippable_dylib", "a.o", nullptr));
+}
+
 }  // end anonymous namespace





More information about the llvm-commits mailing list