forked from OSchip/llvm-project
[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
This commit is contained in:
parent
4d8fff477e
commit
9b29dae3ca
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
// difference 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)
|
||||
// difference 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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -40,7 +40,8 @@ public:
|
|||
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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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 @@ public:
|
|||
// to the output.
|
||||
bool noDeadStrip : 1;
|
||||
|
||||
bool weakDefCanBeHidden : 1;
|
||||
|
||||
private:
|
||||
const bool weakDef : 1;
|
||||
const bool external : 1;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue