[lld] 4a12248 - [lld/mac] Honor REFERENCED_DYAMICALLY, set it on __mh_execute_header
Nico Weber via llvm-commits
llvm-commits at lists.llvm.org
Mon May 17 11:22:24 PDT 2021
Author: Nico Weber
Date: 2021-05-17T14:22:12-04:00
New Revision: 4a12248ee27631c86c2c29d203b22599339ced92
URL: https://github.com/llvm/llvm-project/commit/4a12248ee27631c86c2c29d203b22599339ced92
DIFF: https://github.com/llvm/llvm-project/commit/4a12248ee27631c86c2c29d203b22599339ced92.diff
LOG: [lld/mac] Honor REFERENCED_DYAMICALLY, set it on __mh_execute_header
Has the effect that `__mh_execute_header` stays in the symbol table of
outputs even after running `strip` on the output. I don't know if that's
important for anything -- my motivation for the patch is just is to make
the output more similar to ld64.
(Corresponds to symbolTableInAndNeverStrip in ld64.)
Differential Revision: https://reviews.llvm.org/D102619
Added:
lld/test/MachO/referenced-dynamically.s
Modified:
lld/MachO/Driver.cpp
lld/MachO/InputFiles.cpp
lld/MachO/MergedOutputSection.cpp
lld/MachO/SymbolTable.cpp
lld/MachO/SymbolTable.h
lld/MachO/Symbols.h
lld/MachO/SyntheticSections.cpp
lld/MachO/UnwindInfoSection.cpp
lld/test/MachO/stabs.s
lld/test/MachO/symtab.s
Removed:
################################################################################
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index c561d7cf0980e..135ca2d14524d 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -521,7 +521,8 @@ static void replaceCommonSymbols() {
/*size=*/0,
/*isWeakDef=*/false,
/*isExternal=*/true, common->privateExtern,
- /*isThumb=*/false);
+ /*isThumb=*/false,
+ /*isReferencedDynamically=*/false);
}
}
diff --git a/lld/MachO/InputFiles.cpp b/lld/MachO/InputFiles.cpp
index 26230a0d7a037..a6d63e24f03d5 100644
--- a/lld/MachO/InputFiles.cpp
+++ b/lld/MachO/InputFiles.cpp
@@ -492,7 +492,8 @@ static macho::Symbol *createDefined(const NList &sym, StringRef name,
return symtab->addDefined(name, isec->file, isec, value, size,
sym.n_desc & N_WEAK_DEF, isPrivateExtern,
- sym.n_desc & N_ARM_THUMB_DEF);
+ sym.n_desc & N_ARM_THUMB_DEF,
+ sym.n_desc & REFERENCED_DYNAMICALLY);
}
assert(!isWeakDefCanBeHidden &&
@@ -500,7 +501,8 @@ static macho::Symbol *createDefined(const NList &sym, StringRef name,
return make<Defined>(name, isec->file, isec, value, size,
sym.n_desc & N_WEAK_DEF,
/*isExternal=*/false, /*isPrivateExtern=*/false,
- sym.n_desc & N_ARM_THUMB_DEF);
+ sym.n_desc & N_ARM_THUMB_DEF,
+ sym.n_desc & REFERENCED_DYNAMICALLY);
}
// Absolute symbols are defined symbols that do not have an associated
@@ -512,12 +514,14 @@ static macho::Symbol *createAbsolute(const NList &sym, InputFile *file,
assert((sym.n_type & N_EXT) && "invalid input");
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);
+ sym.n_desc & N_ARM_THUMB_DEF,
+ /*isReferencedDynamically=*/false);
}
return make<Defined>(name, file, nullptr, sym.n_value, /*size=*/0,
/*isWeakDef=*/false,
/*isExternal=*/false, /*isPrivateExtern=*/false,
- sym.n_desc & N_ARM_THUMB_DEF);
+ sym.n_desc & N_ARM_THUMB_DEF,
+ /*isReferencedDynamically=*/false);
}
template <class NList>
@@ -1015,7 +1019,8 @@ static macho::Symbol *createBitcodeSymbol(const lto::InputFile::Symbol &objSym,
return symtab->addDefined(name, &file, /*isec=*/nullptr, /*value=*/0,
/*size=*/0, objSym.isWeak(), isPrivateExtern,
- /*isThumb=*/false);
+ /*isThumb=*/false,
+ /*isReferencedDynamically=*/false);
}
BitcodeFile::BitcodeFile(MemoryBufferRef mbref)
diff --git a/lld/MachO/MergedOutputSection.cpp b/lld/MachO/MergedOutputSection.cpp
index de84cdee3cb6b..867f76e326f2f 100644
--- a/lld/MachO/MergedOutputSection.cpp
+++ b/lld/MachO/MergedOutputSection.cpp
@@ -299,7 +299,7 @@ void MergedOutputSection::finalize() {
r.referent = thunkInfo.sym = symtab->addDefined(
thunkName, /*file=*/nullptr, thunkInfo.isec, /*value=*/0,
/*size=*/thunkSize, /*isWeakDef=*/false, /*isPrivateExtern=*/true,
- /*isThumb=*/false);
+ /*isThumb=*/false, /*isReferencedDynamically=*/false);
target->populateThunk(thunkInfo.isec, funcSym);
finalizeOne(thunkInfo.isec);
thunks.push_back(thunkInfo.isec);
diff --git a/lld/MachO/SymbolTable.cpp b/lld/MachO/SymbolTable.cpp
index ad163d314c7be..565137e570bd6 100644
--- a/lld/MachO/SymbolTable.cpp
+++ b/lld/MachO/SymbolTable.cpp
@@ -45,7 +45,8 @@ std::pair<Symbol *, bool> SymbolTable::insert(StringRef name,
Defined *SymbolTable::addDefined(StringRef name, InputFile *file,
InputSection *isec, uint64_t value,
uint64_t size, bool isWeakDef,
- bool isPrivateExtern, bool isThumb) {
+ bool isPrivateExtern, bool isThumb,
+ bool isReferencedDynamically) {
Symbol *s;
bool wasInserted;
bool overridesWeakDef = false;
@@ -57,10 +58,11 @@ Defined *SymbolTable::addDefined(StringRef name, InputFile *file,
if (!wasInserted) {
if (auto *defined = dyn_cast<Defined>(s)) {
if (isWeakDef) {
- // Both old and new symbol weak (e.g. inline function in two TUs):
- // If one of them isn't private extern, the merged symbol isn't.
if (defined->isWeakDef()) {
+ // Both old and new symbol weak (e.g. inline function in two TUs):
+ // If one of them isn't private extern, the merged symbol isn't.
defined->privateExtern &= isPrivateExtern;
+ defined->referencedDynamically |= isReferencedDynamically;
// FIXME: Handle this for bitcode files.
// FIXME: We currently only do this if both symbols are weak.
@@ -84,9 +86,9 @@ Defined *SymbolTable::addDefined(StringRef name, InputFile *file,
// of a name conflict, we fall through to the replaceSymbol() call below.
}
- Defined *defined =
- replaceSymbol<Defined>(s, name, file, isec, value, size, isWeakDef,
- /*isExternal=*/true, isPrivateExtern, isThumb);
+ Defined *defined = replaceSymbol<Defined>(
+ s, name, file, isec, value, size, isWeakDef, /*isExternal=*/true,
+ isPrivateExtern, isThumb, isReferencedDynamically);
defined->overridesWeakDef = overridesWeakDef;
return defined;
}
@@ -178,10 +180,11 @@ Symbol *SymbolTable::addLazy(StringRef name, ArchiveFile *file,
Defined *SymbolTable::addSynthetic(StringRef name, InputSection *isec,
uint64_t value, bool isPrivateExtern,
- bool includeInSymtab) {
+ bool includeInSymtab,
+ bool referencedDynamically) {
Defined *s = addDefined(name, nullptr, isec, value, /*size=*/0,
/*isWeakDef=*/false, isPrivateExtern,
- /*isThumb=*/false);
+ /*isThumb=*/false, referencedDynamically);
s->includeInSymtab = includeInSymtab;
return s;
}
diff --git a/lld/MachO/SymbolTable.h b/lld/MachO/SymbolTable.h
index 1239cd9a9cb3a..462c84b7aeea1 100644
--- a/lld/MachO/SymbolTable.h
+++ b/lld/MachO/SymbolTable.h
@@ -39,7 +39,8 @@ class SymbolTable {
public:
Defined *addDefined(StringRef name, InputFile *, InputSection *,
uint64_t value, uint64_t size, bool isWeakDef,
- bool isPrivateExtern, bool isThumb);
+ bool isPrivateExtern, bool isThumb,
+ bool isReferencedDynamically);
Symbol *addUndefined(StringRef name, InputFile *, bool isWeakRef);
@@ -53,7 +54,8 @@ class SymbolTable {
const llvm::object::Archive::Symbol &sym);
Defined *addSynthetic(StringRef name, InputSection *, uint64_t value,
- bool isPrivateExtern, bool includeInSymtab);
+ bool isPrivateExtern, bool includeInSymtab,
+ bool referencedDynamically);
ArrayRef<Symbol *> getSymbols() const { return symVector; }
Symbol *find(llvm::CachedHashStringRef name);
diff --git a/lld/MachO/Symbols.h b/lld/MachO/Symbols.h
index 9428e74147b4c..82637ee15b5fa 100644
--- a/lld/MachO/Symbols.h
+++ b/lld/MachO/Symbols.h
@@ -112,10 +112,11 @@ 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 isThumb, bool isReferencedDynamically)
: Symbol(DefinedKind, name, file), isec(isec), value(value), size(size),
overridesWeakDef(false), privateExtern(isPrivateExtern),
- includeInSymtab(true), thumb(isThumb), weakDef(isWeakDef),
+ includeInSymtab(true), thumb(isThumb),
+ referencedDynamically(isReferencedDynamically), weakDef(isWeakDef),
external(isExternal) {
if (isec)
isec->numRefs++;
@@ -151,6 +152,11 @@ class Defined : public Symbol {
bool includeInSymtab : 1;
// Only relevant when compiling for Thumb-supporting arm32 archs.
bool thumb : 1;
+ // Symbols marked referencedDynamically won't be removed from the output's
+ // symbol table by tools like strip. In theory, this could be set on arbitrary
+ // symbols in input object files. In practice, it's used solely for the
+ // synthetic __mh_execute_header symbol.
+ bool referencedDynamically : 1;
private:
const bool weakDef : 1;
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
index 7727ad121b60a..730145230cb09 100644
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -472,7 +472,7 @@ void StubHelperSection::setup() {
make<Defined>("__dyld_private", nullptr, in.imageLoaderCache, 0, 0,
/*isWeakDef=*/false,
/*isExternal=*/false, /*isPrivateExtern=*/false,
- /*isThumb=*/false);
+ /*isThumb=*/false, /*isReferencedDynamically=*/false);
}
ImageLoaderCacheSection::ImageLoaderCacheSection() {
@@ -856,6 +856,8 @@ template <class LP> void SymtabSectionImpl<LP>::writeTo(uint8_t *buf) const {
}
nList->n_desc |= defined->thumb ? N_ARM_THUMB_DEF : 0;
nList->n_desc |= defined->isExternalWeakDef() ? N_WEAK_DEF : 0;
+ nList->n_desc |=
+ defined->referencedDynamically ? REFERENCED_DYNAMICALLY : 0;
} else if (auto *dysym = dyn_cast<DylibSymbol>(entry.sym)) {
uint16_t n_desc = nList->n_desc;
int16_t ordinal = ordinalForDylibSymbol(*dysym);
@@ -1091,9 +1093,9 @@ void BitcodeBundleSection::writeTo(uint8_t *buf) const {
void macho::createSyntheticSymbols() {
auto addHeaderSymbol = [](const char *name) {
- symtab->addSynthetic(name, in.header->isec, 0,
- /*privateExtern=*/true,
- /*includeInSymtab=*/false);
+ symtab->addSynthetic(name, in.header->isec, /*value=*/0,
+ /*privateExtern=*/true, /*includeInSymtab=*/false,
+ /*referencedDynamically=*/false);
};
switch (config->outputType) {
@@ -1105,16 +1107,15 @@ void macho::createSyntheticSymbols() {
// Otherwise, it's an absolute symbol.
if (config->isPic)
symtab->addSynthetic("__mh_execute_header", in.header->isec, /*value=*/0,
- /*privateExtern=*/false,
- /*includeInSymtab=*/true);
+ /*privateExtern=*/false, /*includeInSymtab=*/true,
+ /*referencedDynamically=*/true);
else
- symtab->addSynthetic("__mh_execute_header",
- /*isec*/ nullptr, /*value=*/0,
- /*privateExtern=*/false,
- /*includeInSymtab=*/true);
+ symtab->addSynthetic("__mh_execute_header", /*isec=*/nullptr, /*value=*/0,
+ /*privateExtern=*/false, /*includeInSymtab=*/true,
+ /*referencedDynamically=*/true);
break;
- // The following symbols are N_SECT symbols, even though the header is not
+ // The following symbols are N_SECT symbols, even though the header is not
// part of any section and that they are private to the bundle/dylib/object
// they are part of.
case MH_BUNDLE:
diff --git a/lld/MachO/UnwindInfoSection.cpp b/lld/MachO/UnwindInfoSection.cpp
index a9f0bbd555014..93a2e8037ee8b 100644
--- a/lld/MachO/UnwindInfoSection.cpp
+++ b/lld/MachO/UnwindInfoSection.cpp
@@ -187,7 +187,7 @@ void UnwindInfoSectionImpl<Ptr>::prepareRelocations(InputSection *isec) {
s = make<Defined>("<internal>", /*file=*/nullptr, referentIsec,
r.addend, /*size=*/0, /*isWeakDef=*/false,
/*isExternal=*/false, /*isPrivateExtern=*/false,
- /*isThumb=*/false);
+ /*isThumb=*/false, /*isReferencedDynamically=*/false);
in.got->addEntry(s);
}
r.referent = s;
diff --git a/lld/test/MachO/referenced-dynamically.s b/lld/test/MachO/referenced-dynamically.s
new file mode 100644
index 0000000000000..d75e99b07b389
--- /dev/null
+++ b/lld/test/MachO/referenced-dynamically.s
@@ -0,0 +1,35 @@
+# REQUIRES: x86
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
+
+# RUN: %lld %t.o -lSystem -o %t.out
+# RUN: llvm-readobj --syms %t.out | FileCheck %s
+
+## ld64 has a "TEMP work around until <rdar://problem/7702923> goes in"
+## that promotes PrivateExtern ReferencedDynamically symbols in dylibs to
+## normal Externs. lld does not do this.
+# RUN: %lld -dylib %t.o -o %t.dylib
+# RUN: llvm-readobj --syms %t.dylib | FileCheck %s
+
+# CHECK: Name: ___crashreporter_info__
+# CHECK-NEXT: PrivateExtern
+# CHECK-NEXT: Type: Section (0xE)
+# CHECK-NEXT: Section: __common
+# CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
+# CHECK-NEXT: Flags [ (0x10)
+# CHECK-NEXT: ReferencedDynamically (0x10)
+# CHECK-NEXT: ]
+
+## Reduced from lib/Support/PrettyStackTrace.cpp
+.section __TEXT,__text,regular,pure_instructions
+
+.globl _main
+_main:
+ ret
+
+## .private_extern maches what PrettyStackTrace.cpp does, but it makes
+## the ReferencedDynamically pointless: https://reviews.llvm.org/D27683#2763729
+.private_extern ___crashreporter_info__
+.globl ___crashreporter_info__
+.desc ___crashreporter_info__,16
+.zerofill __DATA,__common,___crashreporter_info__,8,3
+.subsections_via_symbols
diff --git a/lld/test/MachO/stabs.s b/lld/test/MachO/stabs.s
index 65d447bf7e4e0..c9213289fa5da 100644
--- a/lld/test/MachO/stabs.s
+++ b/lld/test/MachO/stabs.s
@@ -78,7 +78,7 @@
# CHECK-DAG: ( SECT EXT) [[#%.2d,COMM_ID + 1]] 0000 [[#ZERO]] '_zero'
# CHECK-DAG: ( SECT EXT) [[#%.2d,MORE_TEXT_ID + 1]] 0000 [[#FUN]] '_fun'
# CHECK-DAG: ( SECT EXT) [[#%.2d,TEXT_ID + 1]] 0000 {{[0-9a-f]+}} '_no_debug'
-# CHECK-DAG: ( {{.*}}) {{[0-9]+}} 0000 {{[0-9a-f]+}} '__mh_execute_header'
+# CHECK-DAG: ( {{.*}}) {{[0-9]+}} 0010 {{[0-9a-f]+}} '__mh_execute_header'
# CHECK-EMPTY:
## Check that we don't attempt to emit rebase opcodes for the debug sections
diff --git a/lld/test/MachO/symtab.s b/lld/test/MachO/symtab.s
index 5a26bfd550590..2a23b3fb77f28 100644
--- a/lld/test/MachO/symtab.s
+++ b/lld/test/MachO/symtab.s
@@ -62,7 +62,8 @@
# CHECK-NEXT: Type: Section (0xE)
# CHECK-NEXT: Section: __text (0x1)
# CHECK-NEXT: RefType: UndefinedNonLazy (0x0)
-# CHECK-NEXT: Flags [ (0x0)
+# CHECK-NEXT: Flags [ (0x10)
+# CHECK-NEXT: ReferencedDynamically (0x10)
# CHECK-NEXT: ]
# CHECK-NEXT: Value: 0x100000000
# CHECK-NEXT: }
More information about the llvm-commits
mailing list