[lld] f23f512 - [lld-macho] Support -bundle

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Fri Sep 25 11:28:50 PDT 2020


Author: Jez Ng
Date: 2020-09-25T11:28:32-07:00
New Revision: f23f5126912b7da3f2a118a7cb1bcf6be3d8c1bc

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

LOG: [lld-macho] Support -bundle

Not 100% sure but it appears that bundles are almost identical to
dylibs, aside from the fact that they do not contain `LC_ID_DYLIB`. ld64's code
seems to treat bundles and dylibs identically in most places.

Supporting bundles allows us to run e.g. XCTests, as all test suites are
compiled into bundles which get dynamically loaded by the `xctest` test runner.

Reviewed By: #lld-macho, smeenai

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

Added: 
    

Modified: 
    lld/MachO/Driver.cpp
    lld/MachO/Writer.cpp
    lld/test/MachO/load-commands.s

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 38dc561ca675..49919662fe4c 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -88,6 +88,24 @@ void MachOOptTable::printHelp(const char *argv0, bool showHidden) const {
   lld::outs() << "\n";
 }
 
+HeaderFileType getOutputType(const opt::InputArgList &args) {
+  // TODO: -r, -dylinker, -preload...
+  opt::Arg *outputArg = args.getLastArg(OPT_bundle, OPT_dylib, OPT_execute);
+  if (outputArg == nullptr)
+    return MH_EXECUTE;
+
+  switch (outputArg->getOption().getID()) {
+  case OPT_bundle:
+    return MH_BUNDLE;
+  case OPT_dylib:
+    return MH_DYLIB;
+  case OPT_execute:
+    return MH_EXECUTE;
+  default:
+    llvm_unreachable("internal error");
+  }
+}
+
 static Optional<std::string>
 findAlongPathsWithExtensions(StringRef name, ArrayRef<StringRef> extensions) {
   llvm::SmallString<261> base;
@@ -575,7 +593,7 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
   config->headerPad = args::getHex(args, OPT_headerpad, /*Default=*/32);
   config->headerPadMaxInstallNames =
       args.hasArg(OPT_headerpad_max_install_names);
-  config->outputType = args.hasArg(OPT_dylib) ? MH_DYLIB : MH_EXECUTE;
+  config->outputType = getOutputType(args);
   config->runtimePaths = args::getStrings(args, OPT_rpath);
   config->allLoad = args.hasArg(OPT_all_load);
   config->forceLoadObjC = args.hasArg(OPT_ObjC);
@@ -661,6 +679,7 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
   }
 
   config->isPic = config->outputType == MH_DYLIB ||
+                  config->outputType == MH_BUNDLE ||
                   (config->outputType == MH_EXECUTE && args.hasArg(OPT_pie));
 
   // Now that all dylibs have been loaded, search for those that should be

diff  --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 055e2f2e9138..4572c521ab29 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -377,6 +377,8 @@ void Writer::createLoadCommands() {
   case MH_DYLIB:
     in.header->addLoadCommand(make<LCDylib>(LC_ID_DYLIB, config->installName));
     break;
+  case MH_BUNDLE:
+    break;
   default:
     llvm_unreachable("unhandled output file type");
   }
@@ -532,6 +534,7 @@ void Writer::createOutputSections() {
     make<PageZeroSection>();
     break;
   case MH_DYLIB:
+  case MH_BUNDLE:
     break;
   default:
     llvm_unreachable("unhandled output file type");

diff  --git a/lld/test/MachO/load-commands.s b/lld/test/MachO/load-commands.s
index c9f5d9b5c218..3e9c07c97fe0 100644
--- a/lld/test/MachO/load-commands.s
+++ b/lld/test/MachO/load-commands.s
@@ -1,19 +1,48 @@
 # REQUIRES: x86
-# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o
-# RUN: lld -flavor darwinnew -o %t %t.o
+# RUN: rm -rf %t && mkdir -p %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t/test.o
+# RUN: lld -flavor darwinnew -o %t/executable %t/test.o
+# RUN: lld -flavor darwinnew -bundle -o %t/bundle %t/test.o
+# RUN: lld -flavor darwinnew -dylib -o %t/dylib %t/test.o
+
+## These load commands should be in every final output binary.
+# COMMON-DAG: cmd LC_DYLD_INFO_ONLY
+# COMMON-DAG: cmd LC_SYMTAB
+# COMMON-DAG: cmd LC_DYSYMTAB
 
 ## Check for the presence of load commands that are essential for a working
-## executable.
-# RUN: llvm-objdump --macho --all-headers %t | FileCheck %s
-# CHECK-DAG: cmd LC_DYLD_INFO_ONLY
-# CHECK-DAG: cmd LC_SYMTAB
-# CHECK-DAG: cmd LC_DYSYMTAB
-# CHECK-DAG: cmd LC_MAIN
-# CHECK-DAG: cmd LC_LOAD_DYLINKER
+## executable. Also check that it has the right filetype.
+# RUN: llvm-objdump --macho --all-headers %t/executable | FileCheck %s --check-prefix=COMMON
+# RUN: llvm-objdump --macho --all-headers %t/executable | FileCheck %s --check-prefix=EXEC
+# EXEC:      magic        cputype cpusubtype  caps    filetype
+# EXEC-NEXT: MH_MAGIC_64  X86_64         ALL  {{.*}}  EXECUTE
+# EXEC-DAG:  cmd LC_MAIN
+# EXEC-DAG:  cmd LC_LOAD_DYLINKER
 
 ## Check for the absence of load commands that should not be in an executable.
-# RUN: llvm-objdump --macho --all-headers %t | FileCheck %s --check-prefix=NCHECK
-# NCHECK-NOT: cmd: LC_ID_DYLIB
+# RUN: llvm-objdump --macho --all-headers %t/executable | FileCheck %s --check-prefix=NEXEC
+# NEXEC-NOT: cmd: LC_ID_DYLIB
+
+## Check for the presence / absence of load commands for the dylib.
+# RUN: llvm-objdump --macho --all-headers %t/dylib | FileCheck %s --check-prefix=COMMON
+# RUN: llvm-objdump --macho --all-headers %t/dylib | FileCheck %s --check-prefix=DYLIB
+# DYLIB:      magic        cputype cpusubtype  caps    filetype
+# DYLIB-NEXT: MH_MAGIC_64  X86_64         ALL  {{.*}}  DYLIB
+# DYLIB:      cmd LC_ID_DYLIB
+
+# RUN: llvm-objdump --macho --all-headers %t/bundle | FileCheck %s --check-prefix=NDYLIB
+# NDYLIB-NOT: cmd: LC_MAIN
+# NDYLIB-NOT: cmd: LC_LOAD_DYLINKER
+
+## Check for the presence / absence of load commands for the bundle.
+# RUN: llvm-objdump --macho --all-headers %t/bundle | FileCheck %s --check-prefix=COMMON
+# RUN: llvm-objdump --macho --all-headers %t/bundle | FileCheck %s --check-prefix=BUNDLE
+# BUNDLE:      magic        cputype cpusubtype  caps    filetype
+# BUNDLE-NEXT: MH_MAGIC_64  X86_64         ALL  {{.*}}  BUNDLE
+
+# RUN: llvm-objdump --macho --all-headers %t/bundle | FileCheck %s --check-prefix=NBUNDLE
+# NBUNDLE-NOT: cmd: LC_MAIN
+# NBUNDLE-NOT: cmd: LC_LOAD_DYLINKER
 
 .text
 .global _main


        


More information about the llvm-commits mailing list