[lld] 437e6bd - [lld-macho] Implement -force_load

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Wed Aug 12 19:51:10 PDT 2020


Author: Jez Ng
Date: 2020-08-12T19:50:27-07:00
New Revision: 437e6bd286acc2515b0b4eb622c2a2e9539e1ab6

URL: https://github.com/llvm/llvm-project/commit/437e6bd286acc2515b0b4eb622c2a2e9539e1ab6
DIFF: https://github.com/llvm/llvm-project/commit/437e6bd286acc2515b0b4eb622c2a2e9539e1ab6.diff

LOG: [lld-macho] Implement -force_load

It's similar to lld-ELF's `-whole-archive`, but applied to individual
archives instead of to a series of them.

Reviewed By: #lld-macho, smeenai

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

Added: 
    lld/test/MachO/force-load.s

Modified: 
    lld/MachO/Driver.cpp
    lld/test/MachO/invalid/bad-archive.s

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index b0ce2f52d8e9..55ec2d226f08 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -40,8 +40,9 @@
 
 using namespace llvm;
 using namespace llvm::MachO;
-using namespace llvm::sys;
+using namespace llvm::object;
 using namespace llvm::opt;
+using namespace llvm::sys;
 using namespace lld;
 using namespace lld::macho;
 
@@ -253,6 +254,35 @@ static void addFileList(StringRef path) {
     addFile(path);
 }
 
+// Returns slices of MB by parsing MB as an archive file.
+// Each slice consists of a member file in the archive.
+static std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef mb) {
+  std::unique_ptr<Archive> file =
+      CHECK(Archive::create(mb),
+            mb.getBufferIdentifier() + ": failed to parse archive");
+
+  std::vector<MemoryBufferRef> v;
+  Error err = Error::success();
+  for (const Archive::Child &c : file->children(err)) {
+    MemoryBufferRef mbref =
+        CHECK(c.getMemoryBufferRef(),
+              mb.getBufferIdentifier() +
+                  ": could not get the buffer for a child of the archive");
+    v.push_back(mbref);
+  }
+  if (err)
+    fatal(mb.getBufferIdentifier() +
+          ": Archive::children failed: " + toString(std::move(err)));
+
+  return v;
+}
+
+static void forceLoadArchive(StringRef path) {
+  if (Optional<MemoryBufferRef> buffer = readFile(path))
+    for (MemoryBufferRef member : getArchiveMembers(*buffer))
+      inputFiles.push_back(make<ObjFile>(member));
+}
+
 static std::array<StringRef, 6> archNames{"arm",    "arm64", "i386",
                                           "x86_64", "ppc",   "ppc64"};
 static bool isArchString(StringRef s) {
@@ -508,6 +538,9 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
     case OPT_filelist:
       addFileList(arg->getValue());
       break;
+    case OPT_force_load:
+      forceLoadArchive(arg->getValue());
+      break;
     case OPT_l: {
       StringRef name = arg->getValue();
       if (Optional<std::string> path = findLibrary(name)) {

diff  --git a/lld/test/MachO/force-load.s b/lld/test/MachO/force-load.s
new file mode 100644
index 000000000000..0c0909431918
--- /dev/null
+++ b/lld/test/MachO/force-load.s
@@ -0,0 +1,19 @@
+# REQUIRES: x86
+# RUN: mkdir -p %t
+# RUN: echo ".section __TEXT,archive; .globl _foo; .weak_definition _foo; _foo:" | llvm-mc -filetype=obj -triple=x86_64-apple-darwin -o %t/archive-foo.o
+# RUN: rm -f %t/foo.a
+# RUN: llvm-ar rcs %t/foo.a %t/archive-foo.o
+# RUN: echo ".section __TEXT,obj; .globl _foo; .weak_definition _foo; _foo:" | llvm-mc -filetype=obj -triple=x86_64-apple-darwin -o %t/foo.o
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t/test.o
+
+# RUN: lld -flavor darwinnew -force_load %t/foo.a %t/foo.o %t/test.o -o %t/test-force-load-first
+# FORCE-LOAD-FIRST:  __TEXT,archive _foo
+# RUN: llvm-objdump --syms %t/test-force-load-first | FileCheck %s --check-prefix=FORCE-LOAD-FIRST
+
+# RUN: lld -flavor darwinnew %t/foo.o -force_load %t/foo.a %t/test.o -o %t/test-force-load-second
+# RUN: llvm-objdump --syms %t/test-force-load-second | FileCheck %s --check-prefix=FORCE-LOAD-SECOND
+# FORCE-LOAD-SECOND: __TEXT,obj _foo
+
+.globl _main
+_main:
+  ret

diff  --git a/lld/test/MachO/invalid/bad-archive.s b/lld/test/MachO/invalid/bad-archive.s
index 9429dc3ec311..b341fb43ab9b 100644
--- a/lld/test/MachO/invalid/bad-archive.s
+++ b/lld/test/MachO/invalid/bad-archive.s
@@ -4,6 +4,7 @@
 # RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
 
 # RUN: not lld -flavor darwinnew %t.o %t.a -o /dev/null 2>&1 | FileCheck -DFILE=%t.a %s
+# RUN: not lld -flavor darwinnew %t.o -force_load %t.a -o /dev/null 2>&1 | FileCheck -DFILE=%t.a %s
 # CHECK: error: [[FILE]]: failed to parse archive: truncated or malformed archive (remaining size of archive too small for next archive member header at offset 8)
 
 .global _main


        


More information about the llvm-commits mailing list