[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