[llvm] 4f90e67 - [lld-macho] Handle $ld$hide[$os] symbols.
Vy Nguyen via llvm-commits
llvm-commits at lists.llvm.org
Fri Dec 17 13:40:17 PST 2021
Author: Vy Nguyen
Date: 2021-12-17T16:40:07-05:00
New Revision: 4f90e67e2f0f3718b4195813caf5e00677c4813d
URL: https://github.com/llvm/llvm-project/commit/4f90e67e2f0f3718b4195813caf5e00677c4813d
DIFF: https://github.com/llvm/llvm-project/commit/4f90e67e2f0f3718b4195813caf5e00677c4813d.diff
LOG: [lld-macho] Handle $ld$hide[$os] symbols.
PR/52708
Differential Revision: https://reviews.llvm.org/D115775
Added:
lld/test/MachO/special-symbol-ld-hidden.s
Modified:
lld/MachO/InputFiles.cpp
lld/MachO/InputFiles.h
llvm/include/llvm/TextAPI/InterfaceFile.h
Removed:
################################################################################
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index 51c7327652487..c596b8c1ff329 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -1147,16 +1147,34 @@ DylibFile::DylibFile(MemoryBufferRef mb, DylibFile *umbrella,
exportingFile = isImplicitlyLinked(installName) ? this : this->umbrella;
if (const load_command *cmd = findCommand(hdr, LC_DYLD_INFO_ONLY)) {
auto *c = reinterpret_cast<const dyld_info_command *>(cmd);
+ struct TrieEntry {
+ StringRef name;
+ uint64_t flags;
+ };
+
+ std::vector<TrieEntry> entries;
+ // Find all the $ld$* symbols to process first.
parseTrie(buf + c->export_off, c->export_size,
[&](const Twine &name, uint64_t flags) {
StringRef savedName = saver.save(name);
if (handleLDSymbol(savedName))
return;
- bool isWeakDef = flags & EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
- bool isTlv = flags & EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL;
- symbols.push_back(symtab->addDylib(savedName, exportingFile,
- isWeakDef, isTlv));
+ entries.push_back({savedName, flags});
});
+
+ // Process the "normal" symbols.
+ for (TrieEntry &entry : entries) {
+ if (exportingFile->hiddenSymbols.contains(
+ CachedHashStringRef(entry.name)))
+ continue;
+
+ bool isWeakDef = entry.flags & EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION;
+ bool isTlv = entry.flags & EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL;
+
+ symbols.push_back(
+ symtab->addDylib(entry.name, exportingFile, isWeakDef, isTlv));
+ }
+
} else {
error("LC_DYLD_INFO_ONLY not found in " + toString(this));
return;
@@ -1231,19 +1249,35 @@ DylibFile::DylibFile(const InterfaceFile &interface, DylibFile *umbrella,
exportingFile = isImplicitlyLinked(installName) ? this : umbrella;
auto addSymbol = [&](const Twine &name) -> void {
- symbols.push_back(symtab->addDylib(saver.save(name), exportingFile,
+ StringRef savedName = saver.save(name);
+ if (exportingFile->hiddenSymbols.contains(CachedHashStringRef(savedName)))
+ return;
+
+ symbols.push_back(symtab->addDylib(savedName, exportingFile,
/*isWeakDef=*/false,
/*isTlv=*/false));
};
- // TODO(compnerd) filter out symbols based on the target platform
- // TODO: handle weak defs, thread locals
+
+ std::vector<const llvm::MachO::Symbol *> normalSymbols;
+ normalSymbols.reserve(interface.symbolsCount());
for (const auto *symbol : interface.symbols()) {
if (!symbol->getArchitectures().has(config->arch()))
continue;
-
if (handleLDSymbol(symbol->getName()))
continue;
+ switch (symbol->getKind()) {
+ case SymbolKind::GlobalSymbol: // Fallthrough
+ case SymbolKind::ObjectiveCClass: // Fallthrough
+ case SymbolKind::ObjectiveCClassEHType: // Fallthrough
+ case SymbolKind::ObjectiveCInstanceVariable: // Fallthrough
+ normalSymbols.push_back(symbol);
+ }
+ }
+
+ // TODO(compnerd) filter out symbols based on the target platform
+ // TODO: handle weak defs, thread locals
+ for (const auto *symbol : normalSymbols) {
switch (symbol->getKind()) {
case SymbolKind::GlobalSymbol:
addSymbol(symbol->getName());
@@ -1289,6 +1323,8 @@ bool DylibFile::handleLDSymbol(StringRef originalName) {
handleLDPreviousSymbol(name, originalName);
else if (action == "install_name")
handleLDInstallNameSymbol(name, originalName);
+ else if (action == "hide")
+ handleLDHideSymbol(name, originalName);
return true;
}
@@ -1357,6 +1393,29 @@ void DylibFile::handleLDInstallNameSymbol(StringRef name,
this->installName = saver.save(installName);
}
+void DylibFile::handleLDHideSymbol(StringRef name, StringRef originalName) {
+ StringRef symbolName;
+ bool shouldHide = true;
+ if (name.startswith("os")) {
+ // If it's hidden based on versions.
+ name = name.drop_front(2);
+ StringRef minVersion;
+ std::tie(minVersion, symbolName) = name.split('$');
+ VersionTuple versionTup;
+ if (versionTup.tryParse(minVersion)) {
+ warn("Failed to parse hidden version, symbol `" + originalName +
+ "` ignored.");
+ return;
+ }
+ shouldHide = versionTup == config->platformInfo.minimum;
+ } else {
+ symbolName = name;
+ }
+
+ if (shouldHide)
+ exportingFile->hiddenSymbols.insert(CachedHashStringRef(symbolName));
+}
+
void DylibFile::checkAppExtensionSafety(bool dylibIsAppExtensionSafe) const {
if (config->applicationExtension && !dylibIsAppExtensionSafe)
warn("using '-application_extension' with unsafe dylib: " + toString(this));
diff --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h
index 47e77cc2c796b..36da70011170c 100644
--- a/lld/MachO/InputFiles.h
+++ b/lld/MachO/InputFiles.h
@@ -190,7 +190,10 @@ class DylibFile final : public InputFile {
bool handleLDSymbol(StringRef originalName);
void handleLDPreviousSymbol(StringRef name, StringRef originalName);
void handleLDInstallNameSymbol(StringRef name, StringRef originalName);
+ void handleLDHideSymbol(StringRef name, StringRef originalName);
void checkAppExtensionSafety(bool dylibIsAppExtensionSafe) const;
+
+ llvm::DenseSet<llvm::CachedHashStringRef> hiddenSymbols;
};
// .a file
diff --git a/lld/test/MachO/special-symbol-ld-hidden.s b/lld/test/MachO/special-symbol-ld-hidden.s
new file mode 100644
index 0000000000000..d2649cd95ed11
--- /dev/null
+++ b/lld/test/MachO/special-symbol-ld-hidden.s
@@ -0,0 +1,93 @@
+# REQUIRES: x86
+
+# RUN: rm -rf %t; split-file --no-leading-lines %s %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/ref-all.s -o %t/ref-all.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/ref-reexported.s -o %t/ref-reexported.o
+
+## Check that the hidden symbols(foo11) can't be referenced from HideFoo.tbd when current version is 11.
+# RUN: not %lld -o /dev/null %t/libHideFoo.tbd %t/ref-all.o -dylib -platform_version macos 11.0.0 11.0.0 2>&1 | FileCheck %s --check-prefix=ERROR
+
+## Check that the hidden symbol(foo11) can be referenced when the current version is NOT 11.
+# RUN: %lld -o %t/ref-foo-12.dylib %t/libHideFoo.tbd %t/ref-all.o -dylib -platform_version macos 12.0.0 12.0.0
+# RUN: llvm-objdump --macho --bind %t/ref-foo-12.dylib | FileCheck %s --check-prefix=HAS-FOO
+
+## Check that when we link multiple tbd files, foo11 comes from the tbd where it is visible.
+# RUN: %lld -o %t/ref-all.dylib %t/libHideFoo.tbd %t/libHasFoo.tbd %t/ref-all.o -dylib -platform_version macos 11.0.0 11.0.0
+# RUN: llvm-objdump --macho --bind %t/ref-all.dylib | FileCheck %s --check-prefix=FOO
+
+## Check that '$hide$' has no effect on reexported symbols.
+# RUN: %lld -o %t/reexport.dylib %t/libReexportSystem2.tbd %t/ref-reexported.o -dylib -platform_version macos 11.0.0 11.0.0
+# RUN: llvm-objdump --macho --bind %t/reexport.dylib | FileCheck %s --check-prefix=REEXP
+
+# ERROR: error: undefined symbol: _OBJC_CLASS_$_foo11
+
+# HAS-FOO: __DATA __data {{.*}} pointer 0 /HideFoo _OBJC_CLASS_$_foo11
+
+# FOO: segment section address type addend dylib symbol
+# FOO-DAG: __DATA __data {{.*}} pointer 0 /HideFoo _OBJC_CLASS_$_bar
+# FOO-DAG: __DATA __data {{.*}} pointer 0 /HideFoo _OBJC_CLASS_$_foo10
+# FOO-DAG: __DATA __data {{.*}} pointer 0 /HasFoo _OBJC_CLASS_$_foo11
+# FOO-DAG: __DATA __data {{.*}} pointer 0 /HideFoo _xxx
+
+# REEXP: __DATA __data {{.*}} pointer 0 libSystem ___nan
+
+#--- ref-all.s
+.data
+.quad _xxx
+.quad _OBJC_CLASS_$_foo11
+.quad _OBJC_CLASS_$_foo10
+.quad _OBJC_CLASS_$_bar
+
+#--- ref-reexported.s
+.data
+.quad ___nan
+
+#--- libHideFoo.tbd
+--- !tapi-tbd
+tbd-version: 4
+targets: [ x86_64-macos ]
+uuids:
+ - target: x86_64-macos
+ value: 2E994C7F-3F03-3A07-879C-55690D22BEDA
+install-name: '/HideFoo'
+current-version: 9
+compatibility-version: 4.5.6
+exports:
+ - targets: [ x86_64-macos ]
+ symbols: [ '$ld$hide$os11.0$_OBJC_CLASS_$_foo11', '$ld$hide$os10.0$_OBJC_CLASS_$_foo10', _xxx ]
+ objc-classes: [foo10, foo11, bar]
+...
+
+#--- libHasFoo.tbd
+--- !tapi-tbd
+tbd-version: 4
+targets: [ x86_64-macos ]
+uuids:
+ - target: x86_64-macos
+ value: 2E994C7F-3F03-3A07-879C-55690D22BEDB
+install-name: '/HasFoo'
+current-version: 9
+compatibility-version: 4.5.6
+exports:
+ - targets: [ x86_64-macos ]
+ symbols: [ _xxx ]
+ objc-classes: [foo10, foo11, bar]
+...
+
+#--- libReexportSystem2.tbd
+--- !tapi-tbd
+tbd-version: 4
+targets: [ x86_64-macos ]
+uuids:
+ - target: x86_64-macos
+ value: 00000000-0000-0000-0000-000000000002
+install-name: '/libReexportSystem2'
+current-version: 9
+exports:
+ - targets: [ x86_64-macos ]
+ symbols: [ '$ld$hide$___nan' ]
+reexported-libraries:
+ - targets: [ x86_64-macos ]
+ libraries: [ '/usr/lib/libSystem.dylib' ]
+...
+
diff --git a/llvm/include/llvm/TextAPI/InterfaceFile.h b/llvm/include/llvm/TextAPI/InterfaceFile.h
index 03a541454e1a6..6ef4db2ae158e 100644
--- a/llvm/include/llvm/TextAPI/InterfaceFile.h
+++ b/llvm/include/llvm/TextAPI/InterfaceFile.h
@@ -381,6 +381,8 @@ class InterfaceFile {
return {Symbols.begin(), Symbols.end()};
}
+ size_t symbolsCount() const { return Symbols.size(); }
+
const_filtered_symbol_range exports() const {
std::function<bool(const Symbol *)> fn = [](const Symbol *Symbol) {
return !Symbol->isUndefined();
More information about the llvm-commits
mailing list