forked from OSchip/llvm-project
Support darwin linker options:
-current_version, -compatibility_version, and -install_name. Patch by Joe Ranieri llvm-svn: 190452
This commit is contained in:
parent
e850d9dedd
commit
e773e327d3
|
@ -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;
|
||||
|
|
|
@ -154,6 +154,47 @@ bool DarwinLdDriver::parse(int argc, const char *argv[],
|
|||
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()));
|
||||
|
|
|
@ -37,6 +37,30 @@ def entry : Separate<["-"], "e">, HelpText<"entry symbol name">,Group<grp_main>;
|
|||
|
||||
// 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">;
|
||||
|
|
|
@ -124,7 +124,8 @@ uint32_t MachOLinkingContext::cpuSubtypeFromArch(Arch arch) {
|
|||
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(raw_ostream &diagnostics) {
|
|||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -169,4 +169,56 @@ TEST_F(DarwinLdParserTest, iOS_Simulator6) {
|
|||
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
|
||||
|
|
Loading…
Reference in New Issue