diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -88,6 +88,24 @@ 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 findAlongPathsWithExtensions(StringRef name, ArrayRef extensions) { llvm::SmallString<261> base; @@ -575,7 +593,7 @@ 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 @@ } 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 --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -377,6 +377,8 @@ case MH_DYLIB: in.header->addLoadCommand(make(LC_ID_DYLIB, config->installName)); break; + case MH_BUNDLE: + break; default: llvm_unreachable("unhandled output file type"); } @@ -532,6 +534,7 @@ make(); 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 --- 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