diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp index c561d7cf0980e7..135ca2d14524d9 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 26230a0d7a037f..a6d63e24f03d5f 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(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(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 @@ -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 de84cdee3cb6b8..867f76e326f2fd 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 ad163d314c7bec..565137e570bd68 100644 --- a/lld/MachO/SymbolTable.cpp +++ b/lld/MachO/SymbolTable.cpp @@ -45,7 +45,8 @@ std::pair 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(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(s, name, file, isec, value, size, isWeakDef, - /*isExternal=*/true, isPrivateExtern, isThumb); + Defined *defined = replaceSymbol( + 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 1239cd9a9cb3ac..462c84b7aeea10 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 getSymbols() const { return symVector; } Symbol *find(llvm::CachedHashStringRef name); diff --git a/lld/MachO/Symbols.h b/lld/MachO/Symbols.h index 9428e74147b4c3..82637ee15b5fab 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 7727ad121b60ae..730145230cb094 100644 --- a/lld/MachO/SyntheticSections.cpp +++ b/lld/MachO/SyntheticSections.cpp @@ -472,7 +472,7 @@ void StubHelperSection::setup() { make("__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 void SymtabSectionImpl::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(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 a9f0bbd5550149..93a2e8037ee8ba 100644 --- a/lld/MachO/UnwindInfoSection.cpp +++ b/lld/MachO/UnwindInfoSection.cpp @@ -187,7 +187,7 @@ void UnwindInfoSectionImpl::prepareRelocations(InputSection *isec) { s = make("", /*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 00000000000000..d75e99b07b3898 --- /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 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 65d447bf7e4e0c..c9213289fa5dab 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 5a26bfd550590d..2a23b3fb77f28c 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: }