[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