mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-11-23 22:00:10 +00:00
[lld][MachO] Add support for $ld$install_name symbols
This diff adds support for $ld$install_name symbols. Test plan: make check-lld-macho Differential revision: https://reviews.llvm.org/D103746
This commit is contained in:
parent
7b839b3542
commit
5e49ee8794
@ -849,7 +849,7 @@ DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella,
|
||||
parseTrie(buf + c->export_off, c->export_size,
|
||||
[&](const Twine &name, uint64_t flags) {
|
||||
StringRef savedName = saver.save(name);
|
||||
if (handleLdSymbol(savedName))
|
||||
if (handleLDSymbol(savedName))
|
||||
return;
|
||||
bool isWeakDef = flags & EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
|
||||
bool isTlv = flags & EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL;
|
||||
@ -937,7 +937,7 @@ DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella,
|
||||
if (!symbol->getArchitectures().has(config->arch()))
|
||||
continue;
|
||||
|
||||
if (handleLdSymbol(symbol->getName()))
|
||||
if (handleLDSymbol(symbol->getName()))
|
||||
continue;
|
||||
|
||||
switch (symbol->getKind()) {
|
||||
@ -974,18 +974,23 @@ void DylibFile::parseReexports(const InterfaceFile &interface) {
|
||||
// $ld$ symbols modify the properties/behavior of the library (e.g. its install
|
||||
// name, compatibility version or hide/add symbols) for specific target
|
||||
// versions.
|
||||
bool DylibFile::handleLdSymbol(StringRef originalName) {
|
||||
// $ld$ previous $ <installname> $ <compatversion> $ <platformstr> $
|
||||
// <startversion> $ <endversion> $ <symbol-name> $
|
||||
bool DylibFile::handleLDSymbol(StringRef originalName) {
|
||||
if (!originalName.startswith("$ld$"))
|
||||
return false;
|
||||
|
||||
StringRef action;
|
||||
StringRef name;
|
||||
std::tie(action, name) = originalName.drop_front(4 /* $ld$ */).split('$');
|
||||
if (action.empty() || action != "previous")
|
||||
if (action == "previous")
|
||||
handleLDPreviousSymbol(name, originalName);
|
||||
else if (action == "install_name")
|
||||
handleLDInstallNameSymbol(name, originalName);
|
||||
return true;
|
||||
}
|
||||
|
||||
void DylibFile::handleLDPreviousSymbol(StringRef name, StringRef originalName) {
|
||||
// originalName: $ld$ previous $ <installname> $ <compatversion> $
|
||||
// <platformstr> $ <startversion> $ <endversion> $ <symbol-name> $
|
||||
StringRef installName;
|
||||
StringRef compatVersion;
|
||||
StringRef platformStr;
|
||||
@ -1002,26 +1007,26 @@ bool DylibFile::handleLdSymbol(StringRef originalName) {
|
||||
std::tie(symbolName, rest) = symbolName.split('$');
|
||||
// TODO: ld64 contains some logic for non-empty symbolName as well.
|
||||
if (!symbolName.empty())
|
||||
return true;
|
||||
return;
|
||||
unsigned platform;
|
||||
if (platformStr.getAsInteger(10, platform) ||
|
||||
platform != static_cast<unsigned>(config->platform()))
|
||||
return true;
|
||||
return;
|
||||
|
||||
VersionTuple start;
|
||||
if (start.tryParse(startVersion)) {
|
||||
warn("failed to parse start version, symbol '" + originalName +
|
||||
"' ignored");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
VersionTuple end;
|
||||
if (end.tryParse(endVersion)) {
|
||||
warn("failed to parse end version, symbol '" + originalName + "' ignored");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
if (config->platformInfo.minimum < start ||
|
||||
config->platformInfo.minimum >= end)
|
||||
return true;
|
||||
return;
|
||||
|
||||
dylibName = saver.save(installName);
|
||||
|
||||
@ -1030,12 +1035,26 @@ bool DylibFile::handleLdSymbol(StringRef originalName) {
|
||||
if (cVersion.tryParse(compatVersion)) {
|
||||
warn("failed to parse compatibility version, symbol '" + originalName +
|
||||
"' ignored");
|
||||
return true;
|
||||
return;
|
||||
}
|
||||
compatibilityVersion = encodeVersion(cVersion);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
void DylibFile::handleLDInstallNameSymbol(StringRef name,
|
||||
StringRef originalName) {
|
||||
// originalName: $ld$ install_name $ os<version> $ install_name
|
||||
StringRef condition, installName;
|
||||
std::tie(condition, installName) = name.split('$');
|
||||
VersionTuple version;
|
||||
if (!condition.startswith("os") ||
|
||||
version.tryParse(condition.drop_front(2 /* os */))) {
|
||||
warn("failed to parse os version, symbol '" + originalName + "' ignored");
|
||||
return;
|
||||
}
|
||||
if (version != config->platformInfo.minimum)
|
||||
return;
|
||||
dylibName = saver.save(installName);
|
||||
}
|
||||
|
||||
ArchiveFile::ArchiveFile(std::unique_ptr<object::Archive> &&f)
|
||||
|
@ -175,7 +175,9 @@ public:
|
||||
bool isBundleLoader;
|
||||
|
||||
private:
|
||||
bool handleLdSymbol(StringRef name);
|
||||
bool handleLDSymbol(StringRef originalName);
|
||||
void handleLDPreviousSymbol(StringRef name, StringRef originalName);
|
||||
void handleLDInstallNameSymbol(StringRef name, StringRef originalName);
|
||||
};
|
||||
|
||||
// .a file
|
||||
|
55
lld/test/MachO/special-symbol-ld-install-name.s
Normal file
55
lld/test/MachO/special-symbol-ld-install-name.s
Normal file
@ -0,0 +1,55 @@
|
||||
# REQUIRES: x86
|
||||
|
||||
# RUN: rm -rf %t; split-file --no-leading-lines %s %t
|
||||
|
||||
# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo.s -o %t/foo.o
|
||||
|
||||
## Case 1: special symbol $ld$install_name affects the install name
|
||||
## since the specified version 11.0.0 matches the target version 11.0.0
|
||||
|
||||
# RUN: %lld -o %t/libfoo1.dylib %t/libLDInstallName.tbd %t/foo.o -dylib -platform_version macos 11.0.0 11.0.0
|
||||
# RUN: llvm-objdump --macho --dylibs-used %t/libfoo1.dylib | FileCheck --check-prefix=CASE1 %s
|
||||
# CASE1: /New (compatibility version 1.1.1, current version 5.0.0)
|
||||
|
||||
## Case 2: special symbol $ld$install_name does not affect the install name
|
||||
## since the specified version 11.0.0 does not match the target version 12.0.0
|
||||
|
||||
# RUN: %lld -o %t/libfoo2.dylib %t/libLDInstallName.tbd %t/foo.o -dylib -platform_version macos 12.0.0 12.0.0
|
||||
# RUN: llvm-objdump --macho --dylibs-used %t/libfoo2.dylib | FileCheck --check-prefix=CASE2 %s
|
||||
# CASE2: /Old (compatibility version 1.1.1, current version 5.0.0)
|
||||
|
||||
## Check that we emit a warning for an invalid os version.
|
||||
|
||||
# RUN: %no_fatal_warnings_lld -o %t/libfoo3.dylib %t/libLDInstallNameInvalid.tbd %t/foo.o -dylib \
|
||||
# RUN: -platform_version macos 11.0.0 11.0.0 2>&1 | FileCheck --check-prefix=INVALID-VERSION %s
|
||||
|
||||
# INVALID-VERSION: failed to parse os version, symbol '$ld$install_name$os11.a$/New' ignored
|
||||
|
||||
#--- foo.s
|
||||
.long _xxx@GOTPCREL
|
||||
|
||||
#--- libLDInstallName.tbd
|
||||
--- !tapi-tbd-v3
|
||||
archs: [ x86_64 ]
|
||||
uuids: [ 'x86_64: 19311012-01AB-342E-812B-73A74271A715' ]
|
||||
platform: macosx
|
||||
install-name: '/Old'
|
||||
current-version: 5
|
||||
compatibility-version: 1.1.1
|
||||
exports:
|
||||
- archs: [ x86_64 ]
|
||||
symbols: [ '$ld$install_name$os11.0$/New', _xxx ]
|
||||
...
|
||||
|
||||
#--- libLDInstallNameInvalid.tbd
|
||||
--- !tapi-tbd-v3
|
||||
archs: [ x86_64 ]
|
||||
uuids: [ 'x86_64: 19311011-01AB-342E-112B-73A74271A715' ]
|
||||
platform: macosx
|
||||
install-name: '/Old'
|
||||
current-version: 5
|
||||
compatibility-version: 1.1.1
|
||||
exports:
|
||||
- archs: [ x86_64 ]
|
||||
symbols: [ '$ld$install_name$os11.a$/New', _xxx ]
|
||||
...
|
Loading…
Reference in New Issue
Block a user