[lld] 6c2f26a - [lld-macho] -all_load and -ObjC should not affect LC_LINKER_OPTION flags

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Fri Oct 29 08:00:57 PDT 2021


Author: Jez Ng
Date: 2021-10-29T11:00:28-04:00
New Revision: 6c2f26a159ec0a68d16424cc8aadd8801c7ef31d

URL: https://github.com/llvm/llvm-project/commit/6c2f26a159ec0a68d16424cc8aadd8801c7ef31d
DIFF: https://github.com/llvm/llvm-project/commit/6c2f26a159ec0a68d16424cc8aadd8801c7ef31d.diff

LOG: [lld-macho] -all_load and -ObjC should not affect LC_LINKER_OPTION flags

In particular, they should not cause archives to be eagerly loaded. This
matches ld64's behavior.

Fixes PR52246.

Reviewed By: #lld-macho, thakis

Differential Revision: https://reviews.llvm.org/D112756

Added: 
    

Modified: 
    lld/MachO/Config.h
    lld/MachO/Driver.cpp
    lld/test/MachO/lc-linker-option.ll

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index 765524b137796..698839895ba61 100644
--- a/lld/MachO/Config.h
+++ b/lld/MachO/Config.h
@@ -198,6 +198,13 @@ struct SymbolPriorityEntry {
   llvm::DenseMap<llvm::StringRef, size_t> objectFiles;
 };
 
+// Whether to force-load an archive.
+enum class ForceLoad {
+  Default, // Apply -all_load or -ObjC behaviors if those flags are enabled
+  Yes,     // Always load the archive, regardless of other flags
+  No,      // Never load the archive, regardless of other flags
+};
+
 extern Configuration *config;
 
 } // namespace macho

diff  --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index bd39024e3fcf4..c5dccb307db7a 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -226,7 +226,7 @@ static llvm::CachePruningPolicy getLTOCachePolicy(InputArgList &args) {
 
 static DenseMap<StringRef, ArchiveFile *> loadedArchives;
 
-static InputFile *addFile(StringRef path, bool forceLoadArchive,
+static InputFile *addFile(StringRef path, ForceLoad forceLoadArchive,
                           bool isExplicit = true, bool isBundleLoader = false) {
   Optional<MemoryBufferRef> buffer = readFile(path);
   if (!buffer)
@@ -253,11 +253,13 @@ static InputFile *addFile(StringRef path, bool forceLoadArchive,
       error(path + ": archive has no index; run ranlib to add one");
 
     auto *file = make<ArchiveFile>(std::move(archive));
-    if (config->allLoad || forceLoadArchive) {
+    if ((forceLoadArchive == ForceLoad::Default && config->allLoad) ||
+        forceLoadArchive == ForceLoad::Yes) {
       if (Optional<MemoryBufferRef> buffer = readFile(path)) {
         Error e = Error::success();
         for (const object::Archive::Child &c : file->getArchive().children(e)) {
-          StringRef reason = forceLoadArchive ? "-force_load" : "-all_load";
+          StringRef reason =
+              forceLoadArchive == ForceLoad::Yes ? "-force_load" : "-all_load";
           if (Error e = file->fetch(c, reason))
             error(toString(file) + ": " + reason +
                   " failed to load archive member: " + toString(std::move(e)));
@@ -266,7 +268,8 @@ static InputFile *addFile(StringRef path, bool forceLoadArchive,
           error(toString(file) +
                 ": Archive::children failed: " + toString(std::move(e)));
       }
-    } else if (config->forceLoadObjC) {
+    } else if (forceLoadArchive == ForceLoad::Default &&
+               config->forceLoadObjC) {
       for (const object::Archive::Symbol &sym : file->getArchive().symbols())
         if (sym.getName().startswith(objc::klass))
           file->fetch(sym);
@@ -331,10 +334,11 @@ static InputFile *addFile(StringRef path, bool forceLoadArchive,
 }
 
 static void addLibrary(StringRef name, bool isNeeded, bool isWeak,
-                       bool isReexport, bool isExplicit, bool forceLoad) {
+                       bool isReexport, bool isExplicit,
+                       ForceLoad forceLoadArchive) {
   if (Optional<StringRef> path = findLibrary(name)) {
     if (auto *dylibFile = dyn_cast_or_null<DylibFile>(
-            addFile(*path, forceLoad, isExplicit))) {
+            addFile(*path, forceLoadArchive, isExplicit))) {
       if (isNeeded)
         dylibFile->forceNeeded = true;
       if (isWeak)
@@ -350,10 +354,11 @@ static void addLibrary(StringRef name, bool isNeeded, bool isWeak,
 }
 
 static void addFramework(StringRef name, bool isNeeded, bool isWeak,
-                         bool isReexport, bool isExplicit) {
+                         bool isReexport, bool isExplicit,
+                         ForceLoad forceLoadArchive) {
   if (Optional<StringRef> path = findFramework(name)) {
     if (auto *dylibFile = dyn_cast_or_null<DylibFile>(
-            addFile(*path, /*forceLoadArchive=*/false, isExplicit))) {
+            addFile(*path, forceLoadArchive, isExplicit))) {
       if (isNeeded)
         dylibFile->forceNeeded = true;
       if (isWeak)
@@ -392,15 +397,16 @@ void macho::parseLCLinkerOption(InputFile *f, unsigned argc, StringRef data) {
     switch (arg->getOption().getID()) {
     case OPT_l: {
       StringRef name = arg->getValue();
-      bool forceLoad =
-          config->forceLoadSwift ? name.startswith("swift") : false;
+      ForceLoad forceLoadArchive =
+          config->forceLoadSwift && name.startswith("swift") ? ForceLoad::Yes
+                                                             : ForceLoad::No;
       addLibrary(name, /*isNeeded=*/false, /*isWeak=*/false,
-                 /*isReexport=*/false, /*isExplicit=*/false, forceLoad);
+                 /*isReexport=*/false, /*isExplicit=*/false, forceLoadArchive);
       break;
     }
     case OPT_framework:
       addFramework(arg->getValue(), /*isNeeded=*/false, /*isWeak=*/false,
-                   /*isReexport=*/false, /*isExplicit=*/false);
+                   /*isReexport=*/false, /*isExplicit=*/false, ForceLoad::No);
       break;
     default:
       error(arg->getSpelling() + " is not allowed in LC_LINKER_OPTION");
@@ -414,7 +420,7 @@ static void addFileList(StringRef path) {
     return;
   MemoryBufferRef mbref = *buffer;
   for (StringRef path : args::getLines(mbref))
-    addFile(rerootPath(path), /*forceLoadArchive=*/false);
+    addFile(rerootPath(path), ForceLoad::Default);
 }
 
 // An order file has one entry per line, in the following format:
@@ -947,30 +953,30 @@ static void createFiles(const InputArgList &args) {
 
     switch (opt.getID()) {
     case OPT_INPUT:
-      addFile(rerootPath(arg->getValue()), /*forceLoadArchive=*/false);
+      addFile(rerootPath(arg->getValue()), ForceLoad::Default);
       break;
     case OPT_needed_library:
       if (auto *dylibFile = dyn_cast_or_null<DylibFile>(
-              addFile(rerootPath(arg->getValue()), false)))
+              addFile(rerootPath(arg->getValue()), ForceLoad::Default)))
         dylibFile->forceNeeded = true;
       break;
     case OPT_reexport_library:
-      if (auto *dylibFile = dyn_cast_or_null<DylibFile>(addFile(
-              rerootPath(arg->getValue()), /*forceLoadArchive=*/false))) {
+      if (auto *dylibFile = dyn_cast_or_null<DylibFile>(
+              addFile(rerootPath(arg->getValue()), ForceLoad::Default))) {
         config->hasReexports = true;
         dylibFile->reexport = true;
       }
       break;
     case OPT_weak_library:
       if (auto *dylibFile = dyn_cast_or_null<DylibFile>(
-              addFile(rerootPath(arg->getValue()), /*forceLoadArchive=*/false)))
+              addFile(rerootPath(arg->getValue()), ForceLoad::Default)))
         dylibFile->forceWeakImport = true;
       break;
     case OPT_filelist:
       addFileList(arg->getValue());
       break;
     case OPT_force_load:
-      addFile(rerootPath(arg->getValue()), /*forceLoadArchive=*/true);
+      addFile(rerootPath(arg->getValue()), ForceLoad::Yes);
       break;
     case OPT_l:
     case OPT_needed_l:
@@ -978,7 +984,7 @@ static void createFiles(const InputArgList &args) {
     case OPT_weak_l:
       addLibrary(arg->getValue(), opt.getID() == OPT_needed_l,
                  opt.getID() == OPT_weak_l, opt.getID() == OPT_reexport_l,
-                 /*isExplicit=*/true, /*forceLoad=*/false);
+                 /*isExplicit=*/true, ForceLoad::Default);
       break;
     case OPT_framework:
     case OPT_needed_framework:
@@ -986,7 +992,8 @@ static void createFiles(const InputArgList &args) {
     case OPT_weak_framework:
       addFramework(arg->getValue(), opt.getID() == OPT_needed_framework,
                    opt.getID() == OPT_weak_framework,
-                   opt.getID() == OPT_reexport_framework, /*isExplicit=*/true);
+                   opt.getID() == OPT_reexport_framework, /*isExplicit=*/true,
+                   ForceLoad::Default);
       break;
     default:
       break;
@@ -1175,7 +1182,7 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
   if (const Arg *arg = args.getLastArg(OPT_bundle_loader)) {
     if (config->outputType != MH_BUNDLE)
       error("-bundle_loader can only be used with MachO bundle output");
-    addFile(arg->getValue(), /*forceLoadArchive=*/false, /*isExplicit=*/false,
+    addFile(arg->getValue(), ForceLoad::Default, /*isExplicit=*/false,
             /*isBundleLoader=*/true);
   }
   if (const Arg *arg = args.getLastArg(OPT_umbrella)) {

diff  --git a/lld/test/MachO/lc-linker-option.ll b/lld/test/MachO/lc-linker-option.ll
index 96d399375dc5f..ea56226fb6be4 100644
--- a/lld/test/MachO/lc-linker-option.ll
+++ b/lld/test/MachO/lc-linker-option.ll
@@ -58,9 +58,24 @@
 ;; actual archive at Foo.framework/Versions/Current, but we skip that here so
 ;; that this test can run on Windows.
 ; RUN: llvm-ar rcs %t/Foo.framework/Foo %t/foo.o
-; RUN: llc %t/objfile1.ll -o %t/objfile1.o -filetype=obj
+; RUN: llc %t/load-framework-foo.ll -o %t/load-framework-foo.o -filetype=obj
 ; RUN: llc %t/main.ll -o %t/main.o -filetype=obj
-; RUN: %lld %t/objfile1.o %t/main.o -o /dev/null -F%t
+; RUN: %lld %t/load-framework-foo.o %t/main.o -o %t/main -F%t
+; RUN: llvm-objdump --macho --syms %t/main | FileCheck %s --check-prefix=SYMS
+
+;; Make sure -all_load and -ObjC have no effect on libraries loaded via
+;; LC_LINKER_OPTION flags.
+; RUN: llc %t/load-library-foo.ll -o %t/load-library-foo.o -filetype=obj
+; RUN: llvm-ar rcs %t/libfoo.a %t/foo.o
+; RUN: %lld -all_load -ObjC %t/load-framework-foo.o %t/load-library-foo.o \
+; RUN:   %t/main.o -o %t/main -F%t -L%t
+; RUN: llvm-objdump --macho --syms %t/main | FileCheck %s --check-prefix=SYMS
+
+;; Note that _OBJC_CLASS_$_TestClass is *not* included here.
+; SYMS:       SYMBOL TABLE:
+; SYMS-NEXT:  g     F __TEXT,__text _main
+; SYMS-NEXT:  g     F __TEXT,__text __mh_execute_header
+; SYMS-EMPTY:
 
 ;--- framework.ll
 target triple = "x86_64-apple-macosx10.15.0"
@@ -105,13 +120,20 @@ define void @main() {
   ret void
 }
 
-;--- objfile1.ll
+;--- load-framework-foo.ll
 target triple = "x86_64-apple-macosx10.15.0"
 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 
 !0 = !{!"-framework", !"Foo"}
 !llvm.linker.options = !{!0}
 
+;--- load-library-foo.ll
+target triple = "x86_64-apple-macosx10.15.0"
+target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
+
+!0 = !{!"-lfoo"}
+!llvm.linker.options = !{!0}
+
 ;--- main.ll
 target triple = "x86_64-apple-macosx10.15.0"
 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
@@ -127,6 +149,5 @@ define void @main() {
 target triple = "x86_64-apple-macosx10.15.0"
 target datalayout = "e-m:o-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
 
-define void @foo() {
-  ret void
-}
+%struct._class_t = type {}
+@"OBJC_CLASS_$_TestClass" = global %struct._class_t {}, section "__DATA, __objc_data", align 8


        


More information about the llvm-commits mailing list