[lld] 98f0390 - [lld-macho] Support -weak_lx, -weak_library, -weak_framework

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Wed Sep 23 19:26:59 PDT 2020


Author: Jez Ng
Date: 2020-09-23T19:26:41-07:00
New Revision: 98f03908d07d06c74be5547cc0436bd89186cae2

URL: https://github.com/llvm/llvm-project/commit/98f03908d07d06c74be5547cc0436bd89186cae2
DIFF: https://github.com/llvm/llvm-project/commit/98f03908d07d06c74be5547cc0436bd89186cae2.diff

LOG: [lld-macho] Support -weak_lx, -weak_library, -weak_framework

They cause their corresponding libraries / frameworks to be loaded via
`LC_LOAD_WEAK_DYLIB` instead of `LC_LOAD_DYLIB`.

Reviewed By: #lld-macho, gkm

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

Added: 
    lld/test/MachO/weak-import.s

Modified: 
    lld/MachO/Driver.cpp
    lld/MachO/InputFiles.h
    lld/MachO/Options.td
    lld/MachO/Writer.cpp

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index cc0211a967fa6..0f1551a18a622 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -237,11 +237,12 @@ static std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef mb) {
   return v;
 }
 
-static void addFile(StringRef path) {
+static InputFile *addFile(StringRef path) {
   Optional<MemoryBufferRef> buffer = readFile(path);
   if (!buffer)
-    return;
+    return nullptr;
   MemoryBufferRef mbref = *buffer;
+  InputFile *newFile = nullptr;
 
   switch (identify_magic(mbref.getBuffer())) {
   case file_magic::archive: {
@@ -270,25 +271,27 @@ static void addFile(StringRef path) {
             inputFiles.push_back(make<ObjFile>(member));
     }
 
-    inputFiles.push_back(make<ArchiveFile>(std::move(file)));
+    newFile = make<ArchiveFile>(std::move(file));
     break;
   }
   case file_magic::macho_object:
-    inputFiles.push_back(make<ObjFile>(mbref));
+    newFile = make<ObjFile>(mbref);
     break;
   case file_magic::macho_dynamically_linked_shared_lib:
-    inputFiles.push_back(make<DylibFile>(mbref));
+    newFile = make<DylibFile>(mbref);
     break;
   case file_magic::tapi_file: {
     Optional<DylibFile *> dylibFile = makeDylibFromTAPI(mbref);
     if (!dylibFile)
-      return;
-    inputFiles.push_back(*dylibFile);
+      return nullptr;
+    newFile = *dylibFile;
     break;
   }
   default:
     error(path + ": unhandled file type");
   }
+  inputFiles.push_back(newFile);
+  return newFile;
 }
 
 static void addFileList(StringRef path) {
@@ -596,29 +599,41 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
     warnIfDeprecatedOption(opt);
     warnIfUnimplementedOption(opt);
     // TODO: are any of these better handled via filtered() or getLastArg()?
-    switch (arg->getOption().getID()) {
+    switch (opt.getID()) {
     case OPT_INPUT:
       addFile(arg->getValue());
       break;
+    case OPT_weak_library: {
+      auto *dylibFile = dyn_cast_or_null<DylibFile>(addFile(arg->getValue()));
+      if (dylibFile != nullptr)
+        dylibFile->forceWeakImport = true;
+      break;
+    }
     case OPT_filelist:
       addFileList(arg->getValue());
       break;
     case OPT_force_load:
       forceLoadArchive(arg->getValue());
       break;
-    case OPT_l: {
+    case OPT_l:
+    case OPT_weak_l: {
       StringRef name = arg->getValue();
       if (Optional<std::string> path = findLibrary(name)) {
-        addFile(*path);
+        auto *dylibFile = dyn_cast_or_null<DylibFile>(addFile(*path));
+        if (opt.getID() == OPT_weak_l && dylibFile != nullptr)
+          dylibFile->forceWeakImport = true;
         break;
       }
       error("library not found for -l" + name);
       break;
     }
-    case OPT_framework: {
+    case OPT_framework:
+    case OPT_weak_framework: {
       StringRef name = arg->getValue();
       if (Optional<std::string> path = findFramework(name)) {
-        addFile(*path);
+        auto *dylibFile = dyn_cast_or_null<DylibFile>(addFile(*path));
+        if (opt.getID() == OPT_weak_framework && dylibFile != nullptr)
+          dylibFile->forceWeakImport = true;
         break;
       }
       error("framework not found for -framework " + name);

diff  --git a/lld/MachO/InputFiles.h b/lld/MachO/InputFiles.h
index 194de0e1a4e9b..bb83c2091178d 100644
--- a/lld/MachO/InputFiles.h
+++ b/lld/MachO/InputFiles.h
@@ -107,6 +107,7 @@ class DylibFile : public InputFile {
   StringRef dylibName;
   uint64_t ordinal = 0; // Ordinal numbering starts from 1, so 0 is a sentinel
   bool reexport = false;
+  bool forceWeakImport = false;
   std::vector<DylibFile *> reexported;
 };
 

diff  --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index 2a05ddf5714d7..ddcf8aa338644 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -64,12 +64,10 @@ def l : Joined<["-"], "l">,
 def weak_l : Joined<["-"], "weak-l">,
      MetaVarName<"<name>">,
      HelpText<"Like -l<name>, but mark library and its references as weak imports">,
-     Flags<[HelpHidden]>,
      Group<grp_libs>;
 def weak_library : Separate<["-"], "weak_library">,
      MetaVarName<"<path>">,
      HelpText<"Like bare <path>, but mark library and its references as weak imports">,
-     Flags<[HelpHidden]>,
      Group<grp_libs>;
 def reexport_l : Joined<["-"], "reexport-l">,
      MetaVarName<"<name>">,
@@ -115,7 +113,6 @@ def framework : Separate<["-"], "framework">,
 def weak_framework : Separate<["-"], "weak_framework">,
      MetaVarName<"<name>">,
      HelpText<"Like -framework <name>, but mark framework and its references as weak imports">,
-     Flags<[HelpHidden]>,
      Group<grp_libs>;
 def reexport_framework : Separate<["-"], "reexport_framework">,
      MetaVarName<"<name>">,

diff  --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 1f1c34ca0bed5..aabe6a98a155f 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -376,8 +376,11 @@ void Writer::createLoadCommands() {
   uint64_t dylibOrdinal = 1;
   for (InputFile *file : inputFiles) {
     if (auto *dylibFile = dyn_cast<DylibFile>(file)) {
-      in.header->addLoadCommand(
-          make<LCDylib>(LC_LOAD_DYLIB, dylibFile->dylibName));
+      // TODO: dylibs that are only referenced by weak refs should also be
+      // loaded via LC_LOAD_WEAK_DYLIB.
+      LoadCommandType lcType =
+          dylibFile->forceWeakImport ? LC_LOAD_WEAK_DYLIB : LC_LOAD_DYLIB;
+      in.header->addLoadCommand(make<LCDylib>(lcType, dylibFile->dylibName));
       dylibFile->ordinal = dylibOrdinal++;
 
       if (dylibFile->reexport)

diff  --git a/lld/test/MachO/weak-import.s b/lld/test/MachO/weak-import.s
new file mode 100644
index 0000000000000..a20337536aa22
--- /dev/null
+++ b/lld/test/MachO/weak-import.s
@@ -0,0 +1,31 @@
+# REQUIRES: x86
+# RUN: split-file %s %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/test.s -o %t/test.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %t/foo.s -o %t/foo.o
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -lSystem -dylib %t/foo.o -o %t/libfoo.dylib
+
+# RUN: lld -flavor darwinnew -syslibroot %S/Inputs/MacOSX.sdk -weak-lSystem %t/test.o -weak_framework CoreFoundation -weak_library %t/libfoo.dylib -o %t/test
+# RUN: llvm-objdump --macho --all-headers %t/test | FileCheck %s -DDIR=%t
+
+# CHECK:          cmd LC_LOAD_WEAK_DYLIB
+# CHECK-NEXT: cmdsize
+# CHECK-NEXT:    name /usr/lib/libSystem.B.dylib
+
+# CHECK:          cmd LC_LOAD_WEAK_DYLIB
+# CHECK-NEXT: cmdsize
+# CHECK-NEXT:    name /System/Library/Frameworks/CoreFoundation.framework/CoreFoundation
+
+# CHECK:          cmd LC_LOAD_WEAK_DYLIB
+# CHECK-NEXT: cmdsize
+# CHECK-NEXT:    name [[DIR]]/libfoo.dylib
+
+#--- foo.s
+.globl _foo
+_foo:
+  ret
+
+#--- test.s
+.globl _main
+.text
+_main:
+  ret


        


More information about the llvm-commits mailing list