Index: lld/MachO/InputFiles.cpp =================================================================== --- lld/MachO/InputFiles.cpp +++ lld/MachO/InputFiles.cpp @@ -439,6 +439,12 @@ static macho::Symbol *createDefined(const NList &sym, StringRef name, InputSection *isec, uint64_t value, uint64_t size) { + // LLVM's assembler isn't able to produce .o files with this set. + // If a tool ever appears that produces input files with this set, + // we'll have to add an `isReferencedDynamically` arg to Defined's + // constructor and pass this in. + assert(!(sym.n_desc & REFERENCED_DYNAMICALLY)); + // Symbol scope is determined by sym.n_type & (N_EXT | N_PEXT): // N_EXT: Global symbols. These go in the symbol table during the link, // and also in the export table of the output so that the dynamic Index: lld/MachO/Symbols.h =================================================================== --- lld/MachO/Symbols.h +++ lld/MachO/Symbols.h @@ -115,8 +115,8 @@ bool isThumb) : Symbol(DefinedKind, name, file), isec(isec), value(value), size(size), overridesWeakDef(false), privateExtern(isPrivateExtern), - includeInSymtab(true), thumb(isThumb), weakDef(isWeakDef), - external(isExternal) { + includeInSymtab(true), thumb(isThumb), referencedDynamically(false), + weakDef(isWeakDef), external(isExternal) { if (isec) isec->numRefs++; } @@ -151,6 +151,11 @@ 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; Index: lld/MachO/SyntheticSections.cpp =================================================================== --- lld/MachO/SyntheticSections.cpp +++ lld/MachO/SyntheticSections.cpp @@ -856,6 +856,8 @@ } nList->n_desc |= defined->thumb ? N_ARM_THUMB_DEF : 0; nList->n_desc |= defined->isExternalWeakDef() ? N_WEAK_DEF : 0; + if (defined->referencedDynamically) + nList->n_desc |= REFERENCED_DYNAMICALLY; } else if (auto *dysym = dyn_cast(entry.sym)) { uint16_t n_desc = nList->n_desc; int16_t ordinal = ordinalForDylibSymbol(*dysym); @@ -1099,22 +1101,26 @@ switch (config->outputType) { // FIXME: Assign the right address value for these symbols // (rather than 0). But we need to do that after assignAddresses(). - case MH_EXECUTE: + case MH_EXECUTE: { // If linking PIE, __mh_execute_header is a defined symbol in // __TEXT, __text) // Otherwise, it's an absolute symbol. + Defined *execHeader; if (config->isPic) - symtab->addSynthetic("__mh_execute_header", in.header->isec, /*value=*/0, - /*privateExtern=*/false, - /*includeInSymtab=*/true); + execHeader = symtab->addSynthetic("__mh_execute_header", in.header->isec, + /*value=*/0, + /*privateExtern=*/false, + /*includeInSymtab=*/true); else - symtab->addSynthetic("__mh_execute_header", - /*isec*/ nullptr, /*value=*/0, - /*privateExtern=*/false, - /*includeInSymtab=*/true); + execHeader = symtab->addSynthetic("__mh_execute_header", + /*isec=*/nullptr, /*value=*/0, + /*privateExtern=*/false, + /*includeInSymtab=*/true); + execHeader->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: Index: lld/test/MachO/stabs.s =================================================================== --- lld/test/MachO/stabs.s +++ 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 Index: lld/test/MachO/symtab.s =================================================================== --- lld/test/MachO/symtab.s +++ 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: }