[lld/mac] Implement support for -mark_dead_strippable_dylib
lld doesn't read MH_DEAD_STRIPPABLE_DYLIB to strip dead dylibs yet,
but now it can produce dylibs with it set.
While here, also switch an existing test that looks only at the main Mach-O
header from --all-headers to --private-header.
Differential Revision: https://reviews.llvm.org/D98262
GitOrigin-RevId: 1aafaaca6717d2cf3084e4ba38bde63f619dca90
diff --git a/MachO/Config.h b/MachO/Config.h
index 810b719..6c85cd5 100644
--- a/MachO/Config.h
+++ b/MachO/Config.h
@@ -75,6 +75,7 @@
bool isPic = false;
bool headerPadMaxInstallNames = false;
bool ltoNewPassManager = LLVM_ENABLE_NEW_PASS_MANAGER;
+ bool markDeadStrippableDylib = false;
bool printEachFile = false;
bool printWhyLoad = false;
bool searchDylibsFirst = false;
diff --git a/MachO/Driver.cpp b/MachO/Driver.cpp
index b901080..b53ac2e 100644
--- a/MachO/Driver.cpp
+++ b/MachO/Driver.cpp
@@ -850,6 +850,13 @@
config->demangle = args.hasArg(OPT_demangle);
config->implicitDylibs = !args.hasArg(OPT_no_implicit_dylibs);
+ if (args.hasArg(OPT_mark_dead_strippable_dylib)) {
+ if (config->outputType != MH_DYLIB)
+ warn("-mark_dead_strippable_dylib: ignored, only has effect with -dylib");
+ else
+ config->markDeadStrippableDylib = true;
+ }
+
if (const Arg *arg = args.getLastArg(OPT_static, OPT_dynamic))
config->staticLink = (arg->getOption().getID() == OPT_static);
diff --git a/MachO/Options.td b/MachO/Options.td
index c83ed3e..74eaabc 100644
--- a/MachO/Options.td
+++ b/MachO/Options.td
@@ -335,8 +335,7 @@
Flags<[HelpHidden]>,
Group<grp_dylib>;
def mark_dead_strippable_dylib : Flag<["-"], "mark_dead_strippable_dylib">,
- HelpText<"Clients can discard this dylib if it is unreferenced">,
- Flags<[HelpHidden]>,
+ HelpText<"Mark output dylib as dead-strippable: When a client links against it but does not use any of its symbols, the dylib will not be added to the client's list of needed dylibs">,
Group<grp_dylib>;
def compatibility_version : Separate<["-"], "compatibility_version">,
MetaVarName<"<version>">,
diff --git a/MachO/SyntheticSections.cpp b/MachO/SyntheticSections.cpp
index 336eb12..423b645 100644
--- a/MachO/SyntheticSections.cpp
+++ b/MachO/SyntheticSections.cpp
@@ -86,6 +86,9 @@
if (config->outputType == MachO::MH_DYLIB && !config->hasReexports)
hdr->flags |= MachO::MH_NO_REEXPORTED_DYLIBS;
+ if (config->markDeadStrippableDylib)
+ hdr->flags |= MachO::MH_DEAD_STRIPPABLE_DYLIB;
+
if (config->outputType == MachO::MH_EXECUTE && config->isPic)
hdr->flags |= MachO::MH_PIE;
diff --git a/test/MachO/header.s b/test/MachO/header.s
index 4264893..17bcb0f 100644
--- a/test/MachO/header.s
+++ b/test/MachO/header.s
@@ -7,10 +7,10 @@
# RUN: %lld -arch x86_64 -dylib -o %t/x86-64-dylib %t/x86_64-test.o
# RUN: %lld -arch arm64 -dylib -o %t/arm64-dylib %t/arm64-test.o
-# RUN: llvm-objdump --macho --all-headers %t/x86-64-executable | FileCheck %s -DCAPS=LIB64
-# RUN: llvm-objdump --macho --all-headers %t/arm64-executable | FileCheck %s -DCAPS=0x00
-# RUN: llvm-objdump --macho --all-headers %t/x86-64-dylib | FileCheck %s -DCAPS=0x00
-# RUN: llvm-objdump --macho --all-headers %t/arm64-dylib | FileCheck %s -DCAPS=0x00
+# RUN: llvm-objdump --macho --private-header %t/x86-64-executable | FileCheck %s -DCAPS=LIB64
+# RUN: llvm-objdump --macho --private-header %t/arm64-executable | FileCheck %s -DCAPS=0x00
+# RUN: llvm-objdump --macho --private-header %t/x86-64-dylib | FileCheck %s -DCAPS=0x00
+# RUN: llvm-objdump --macho --private-header %t/arm64-dylib | FileCheck %s -DCAPS=0x00
# CHECK: magic cputype cpusubtype caps filetype {{.*}} flags
# CHECK-NEXT: MH_MAGIC_64 {{.*}} ALL [[CAPS]] {{.*}} NOUNDEFS {{.*}} TWOLEVEL
diff --git a/test/MachO/mark-dead-strippable-dylib.s b/test/MachO/mark-dead-strippable-dylib.s
new file mode 100644
index 0000000..ad2f709
--- /dev/null
+++ b/test/MachO/mark-dead-strippable-dylib.s
@@ -0,0 +1,27 @@
+# REQUIRES: x86
+
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-macos -o %t.o %s
+
+# RUN: %no_fatal_warnings_lld -o %t.exec %t.o -mark_dead_strippable_dylib 2>&1 \
+# RUN: | FileCheck --check-prefix=WARN %s
+# RUN: llvm-objdump --macho --private-header %t.exec \
+# RUN: | FileCheck --check-prefix=NO-DS %s
+
+# RUN: %no_fatal_warnings_lld -bundle -o %t.bundle %t.o \
+# RUN: -mark_dead_strippable_dylib 2>&1 \
+# RUN: | FileCheck --check-prefix=WARN %s
+# RUN: llvm-objdump --macho --private-header %t.bundle \
+# RUN: | FileCheck --check-prefix=NO-DS %s
+
+# RUN: %lld -dylib -o %t.dylib %t.o -mark_dead_strippable_dylib 2>&1
+# RUN: llvm-objdump --macho --private-header %t.dylib \
+# RUN: | FileCheck --check-prefix=DS %s
+
+# WARN: warning: -mark_dead_strippable_dylib: ignored, only has effect with -dylib
+
+# NO-DS-NOT: DEAD_STRIPPABLE_DYLIB
+# DS: DEAD_STRIPPABLE_DYLIB
+
+.globl _main
+_main:
+ ret