[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