[lld] 9b29dae - [lld-macho] Allow exporting weak_def_can_be_hidden(AKA "autohide") symbols
Vy Nguyen via llvm-commits
llvm-commits at lists.llvm.org
Fri Nov 12 18:57:42 PST 2021
Author: Vy Nguyen
Date: 2021-11-12T21:57:30-05:00
New Revision: 9b29dae3cae1860f663698fcb709a19cf0c398be
URL: https://github.com/llvm/llvm-project/commit/9b29dae3cae1860f663698fcb709a19cf0c398be
DIFF: https://github.com/llvm/llvm-project/commit/9b29dae3cae1860f663698fcb709a19cf0c398be.diff
LOG: [lld-macho] Allow exporting weak_def_can_be_hidden(AKA "autohide") symbols
autohide symbols behaves similarly to private_extern symbols.
However, LD64 allows exporting autohide symbols. LLD currently does not.
This patch allows LLD to export them.
Differential Revision: https://reviews.llvm.org/D113167
Added:
Modified:
lld/MachO/ConcatOutputSection.cpp
lld/MachO/Driver.cpp
lld/MachO/InputFiles.cpp
lld/MachO/SymbolTable.cpp
lld/MachO/SymbolTable.h
lld/MachO/Symbols.cpp
lld/MachO/Symbols.h
lld/test/MachO/export-options.s
Removed:
################################################################################
diff --git a/lld/MachO/ConcatOutputSection.cpp b/lld/MachO/ConcatOutputSection.cpp
index 17da4d045585d..46cd15a40025d 100644
--- a/lld/MachO/ConcatOutputSection.cpp
+++ b/lld/MachO/ConcatOutputSection.cpp
@@ -329,7 +329,7 @@ void ConcatOutputSection::finalize() {
thunkName, /*file=*/nullptr, thunkInfo.isec, /*value=*/0,
/*size=*/thunkSize, /*isWeakDef=*/false, /*isPrivateExtern=*/true,
/*isThumb=*/false, /*isReferencedDynamically=*/false,
- /*noDeadStrip=*/false);
+ /*noDeadStrip=*/false, /*isWeakDefCanBeHidden=*/false);
thunkInfo.sym->used = true;
target->populateThunk(thunkInfo.isec, funcSym);
finalizeOne(thunkInfo.isec);
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index ceaefeda839d2..ddd84bce35c6c 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -1467,8 +1467,16 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
StringRef symbolName = defined->getName();
if (config->exportedSymbols.match(symbolName)) {
if (defined->privateExtern) {
- warn("cannot export hidden symbol " + symbolName +
- "\n>>> defined in " + toString(defined->getFile()));
+ if (defined->weakDefCanBeHidden) {
+ // weak_def_can_be_hidden symbols behave similarly to
+ // private_extern symbols in most cases, except for when
+ // it is explicitly exported.
+ // The former can be exported but the latter cannot.
+ defined->privateExtern = false;
+ } else {
+ warn("cannot export hidden symbol " + symbolName +
+ "\n>>> defined in " + toString(defined->getFile()));
+ }
}
} else {
defined->privateExtern = true;
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index 1b233920ffb27..769fdddf67f72 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -567,16 +567,22 @@ static macho::Symbol *createDefined(const NList &sym, StringRef name,
// with ld64's semantics, because it means the non-private-extern
// definition will continue to take priority if more private extern
// definitions are encountered. With lld's semantics there's no observable
- //
diff erence between a symbol that's isWeakDefCanBeHidden or one that's
- // privateExtern -- neither makes it into the dynamic symbol table. So just
- // promote isWeakDefCanBeHidden to isPrivateExtern here.
- if (isWeakDefCanBeHidden)
+ //
diff erence between a symbol that's isWeakDefCanBeHidden(autohide) or one
+ // that's privateExtern -- neither makes it into the dynamic symbol table,
+ // unless the autohide symbol is explicitly exported.
+ // But if a symbol is both privateExtern and autohide then it can't
+ // be exported.
+ // So we nullify the autohide flag when privateExtern is present
+ // and promote the symbol to privateExtern when it is not already.
+ if (isWeakDefCanBeHidden && isPrivateExtern)
+ isWeakDefCanBeHidden = false;
+ else if (isWeakDefCanBeHidden)
isPrivateExtern = true;
-
return symtab->addDefined(
name, isec->getFile(), isec, value, size, sym.n_desc & N_WEAK_DEF,
isPrivateExtern, sym.n_desc & N_ARM_THUMB_DEF,
- sym.n_desc & REFERENCED_DYNAMICALLY, sym.n_desc & N_NO_DEAD_STRIP);
+ sym.n_desc & REFERENCED_DYNAMICALLY, sym.n_desc & N_NO_DEAD_STRIP,
+ isWeakDefCanBeHidden);
}
assert(!isWeakDefCanBeHidden &&
"weak_def_can_be_hidden on already-hidden symbol?");
@@ -596,7 +602,8 @@ static macho::Symbol *createAbsolute(const NList &sym, InputFile *file,
return symtab->addDefined(
name, file, nullptr, sym.n_value, /*size=*/0,
/*isWeakDef=*/false, sym.n_type & N_PEXT, sym.n_desc & N_ARM_THUMB_DEF,
- /*isReferencedDynamically=*/false, sym.n_desc & N_NO_DEAD_STRIP);
+ /*isReferencedDynamically=*/false, sym.n_desc & N_NO_DEAD_STRIP,
+ /*isWeakDefCanBeHidden=*/false);
}
return make<Defined>(name, file, nullptr, sym.n_value, /*size=*/0,
/*isWeakDef=*/false,
@@ -1448,7 +1455,8 @@ static macho::Symbol *createBitcodeSymbol(const lto::InputFile::Symbol &objSym,
/*size=*/0, objSym.isWeak(), isPrivateExtern,
/*isThumb=*/false,
/*isReferencedDynamically=*/false,
- /*noDeadStrip=*/false);
+ /*noDeadStrip=*/false,
+ /*isWeakDefCanBeHidden=*/false);
}
BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
diff --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp
index df7237468ae3d..c212516a47804 100644
--- a/lld/MachO/SymbolTable.cpp
+++ b/lld/MachO/SymbolTable.cpp
@@ -49,8 +49,8 @@ Defined *SymbolTable::addDefined(StringRef name, InputFile *file,
InputSection *isec, uint64_t value,
uint64_t size, bool isWeakDef,
bool isPrivateExtern, bool isThumb,
- bool isReferencedDynamically,
- bool noDeadStrip) {
+ bool isReferencedDynamically, bool noDeadStrip,
+ bool isWeakDefCanBeHidden) {
Symbol *s;
bool wasInserted;
bool overridesWeakDef = false;
@@ -62,10 +62,10 @@ Defined *SymbolTable::addDefined(StringRef name, InputFile *file,
if (!wasInserted) {
if (auto *defined = dyn_cast<Defined>(s)) {
if (isWeakDef) {
-
// See further comment in createDefined() in InputFiles.cpp
if (defined->isWeakDef()) {
defined->privateExtern &= isPrivateExtern;
+ defined->weakDefCanBeHidden &= isWeakDefCanBeHidden;
defined->referencedDynamically |= isReferencedDynamically;
defined->noDeadStrip |= noDeadStrip;
}
@@ -98,8 +98,8 @@ Defined *SymbolTable::addDefined(StringRef name, InputFile *file,
Defined *defined = replaceSymbol<Defined>(
s, name, file, isec, value, size, isWeakDef, /*isExternal=*/true,
- isPrivateExtern, isThumb, isReferencedDynamically, noDeadStrip);
- defined->overridesWeakDef = overridesWeakDef;
+ isPrivateExtern, isThumb, isReferencedDynamically, noDeadStrip,
+ overridesWeakDef, isWeakDefCanBeHidden);
return defined;
}
@@ -195,10 +195,11 @@ Defined *SymbolTable::addSynthetic(StringRef name, InputSection *isec,
uint64_t value, bool isPrivateExtern,
bool includeInSymtab,
bool referencedDynamically) {
- Defined *s = addDefined(name, nullptr, isec, value, /*size=*/0,
- /*isWeakDef=*/false, isPrivateExtern,
- /*isThumb=*/false, referencedDynamically,
- /*noDeadStrip=*/false);
+ Defined *s =
+ addDefined(name, nullptr, isec, value, /*size=*/0,
+ /*isWeakDef=*/false, isPrivateExtern,
+ /*isThumb=*/false, referencedDynamically,
+ /*noDeadStrip=*/false, /*isWeakDefCanBeHidden=*/false);
s->includeInSymtab = includeInSymtab;
return s;
}
diff --git a/lld/MachO/SymbolTable.h b/lld/MachO/SymbolTable.h
index 17f1ecbd346bd..625f78aa61411 100644
--- a/lld/MachO/SymbolTable.h
+++ b/lld/MachO/SymbolTable.h
@@ -40,7 +40,8 @@ class SymbolTable {
Defined *addDefined(StringRef name, InputFile *, InputSection *,
uint64_t value, uint64_t size, bool isWeakDef,
bool isPrivateExtern, bool isThumb,
- bool isReferencedDynamically, bool noDeadStrip);
+ bool isReferencedDynamically, bool noDeadStrip,
+ bool isWeakDefCanBeHidden);
Symbol *addUndefined(StringRef name, InputFile *, bool isWeakRef);
diff --git a/lld/MachO/Symbols.cpp b/lld/MachO/Symbols.cpp
index c663b21dd7d9c..7b04d2512f677 100644
--- a/lld/MachO/Symbols.cpp
+++ b/lld/MachO/Symbols.cpp
@@ -34,12 +34,14 @@ uint64_t Symbol::getTlvVA() const { return in.tlvPointers->getVA(gotIndex); }
Defined::Defined(StringRefZ name, InputFile *file, InputSection *isec,
uint64_t value, uint64_t size, bool isWeakDef, bool isExternal,
bool isPrivateExtern, bool isThumb,
- bool isReferencedDynamically, bool noDeadStrip)
+ bool isReferencedDynamically, bool noDeadStrip,
+ bool canOverrideWeakDef, bool isWeakDefCanBeHidden)
: Symbol(DefinedKind, name, file), isec(isec), value(value), size(size),
- overridesWeakDef(false), privateExtern(isPrivateExtern),
+ overridesWeakDef(canOverrideWeakDef), privateExtern(isPrivateExtern),
includeInSymtab(true), thumb(isThumb),
referencedDynamically(isReferencedDynamically), noDeadStrip(noDeadStrip),
- weakDef(isWeakDef), external(isExternal) {
+ weakDef(isWeakDef), external(isExternal),
+ weakDefCanBeHidden(isWeakDefCanBeHidden) {
if (isec) {
isec->symbols.push_back(this);
// Maintain sorted order.
diff --git a/lld/MachO/Symbols.h b/lld/MachO/Symbols.h
index 54f1a35127282..2d38eea88be08 100644
--- a/lld/MachO/Symbols.h
+++ b/lld/MachO/Symbols.h
@@ -113,7 +113,8 @@ class Defined : public Symbol {
public:
Defined(StringRefZ name, InputFile *file, InputSection *isec, uint64_t value,
uint64_t size, bool isWeakDef, bool isExternal, bool isPrivateExtern,
- bool isThumb, bool isReferencedDynamically, bool noDeadStrip);
+ bool isThumb, bool isReferencedDynamically, bool noDeadStrip,
+ bool canOverrideWeakDef = false, bool isWeakDefCanBeHidden = false);
bool isWeakDef() const override { return weakDef; }
bool isExternalWeakDef() const {
@@ -160,6 +161,8 @@ class Defined : public Symbol {
// to the output.
bool noDeadStrip : 1;
+ bool weakDefCanBeHidden : 1;
+
private:
const bool weakDef : 1;
const bool external : 1;
diff --git a/lld/test/MachO/export-options.s b/lld/test/MachO/export-options.s
index 30f05effad1b8..5678a48719a65 100644
--- a/lld/test/MachO/export-options.s
+++ b/lld/test/MachO/export-options.s
@@ -119,6 +119,33 @@
# GLOBBY-DAG: globby_also
# GLOBBY-NOT: literal_only
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos \
+# RUN: %t/autohide.s -o %t/autohide.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos \
+# RUN: %t/autohide-private-extern.s -o %t/autohide-private-extern.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos \
+# RUN: %t/glob-private-extern.s -o %t/glob-private-extern.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos \
+# RUN: %t/weak-private-extern.s -o %t/weak-private-extern.o
+## Test that we can export the autohide symbol but not when it's also
+## private-extern
+# RUN: %lld -dylib -exported_symbol "_foo" %t/autohide.o -o %t/exp-autohide.dylib
+# RUN: llvm-nm -g %t/exp-autohide.dylib | FileCheck %s --check-prefix=EXP-AUTOHIDE
+
+# RUN: not %lld -dylib -exported_symbol "_foo" %t/autohide-private-extern.o \
+# RUN: -o /dev/null 2>&1 | FileCheck %s --check-prefix=AUTOHIDE-PRIVATE
+
+# RUN: not %lld -dylib -exported_symbol "_foo" %t/autohide.o \
+# RUN: %t/glob-private-extern.o -o /dev/null 2>&1 | \
+# RUN: FileCheck %s --check-prefix=AUTOHIDE-PRIVATE
+
+# RUN: not %lld -dylib -exported_symbol "_foo" %t/autohide.o \
+# RUN: %t/weak-private-extern.o -o /dev/null 2>&1 | \
+# RUN: FileCheck %s --check-prefix=AUTOHIDE-PRIVATE
+
+# EXP-AUTOHIDE: T _foo
+# AUTOHIDE-PRIVATE: error: cannot export hidden symbol _foo
+
#--- default.s
.globl _keep_globl, _hide_globl
@@ -164,3 +191,29 @@ globby_also:
l?ter[aeiou]l_*[^y] # comment
*gl?bby_*
+
+#--- autohide.s
+.globl _foo
+.weak_def_can_be_hidden _foo
+_foo:
+ retq
+
+#--- autohide-private-extern.s
+.globl _foo
+.weak_def_can_be_hidden _foo
+.private_extern _foo
+_foo:
+ retq
+
+#--- glob-private-extern.s
+.global _foo
+.private_extern _foo
+_foo:
+ retq
+
+#--- weak-private-extern.s
+.global _foo
+.weak_definition _foo
+.private_extern _foo
+_foo:
+ retq
More information about the llvm-commits
mailing list