[llvm] 4d683f7 - [dsymutil] Add the ability to generate universal binaries with a fat64 header
Jonas Devlieghere via llvm-commits
llvm-commits at lists.llvm.org
Mon Mar 27 16:22:41 PDT 2023
Author: Jonas Devlieghere
Date: 2023-03-27T16:22:16-07:00
New Revision: 4d683f7fa7d49fa5837cea7a55902dd565d32838
URL: https://github.com/llvm/llvm-project/commit/4d683f7fa7d49fa5837cea7a55902dd565d32838
DIFF: https://github.com/llvm/llvm-project/commit/4d683f7fa7d49fa5837cea7a55902dd565d32838.diff
LOG: [dsymutil] Add the ability to generate universal binaries with a fat64 header
Add the ability to generate universal binaries with a fat64 header.
rdar://107223939
Differential revision: https://reviews.llvm.org/D146879
Added:
llvm/test/tools/dsymutil/fat-header.test
Modified:
llvm/docs/CommandGuide/dsymutil.rst
llvm/test/tools/dsymutil/cmdline.test
llvm/tools/dsymutil/LinkUtils.h
llvm/tools/dsymutil/MachOUtils.cpp
llvm/tools/dsymutil/MachOUtils.h
llvm/tools/dsymutil/Options.td
llvm/tools/dsymutil/dsymutil.cpp
Removed:
################################################################################
diff --git a/llvm/docs/CommandGuide/dsymutil.rst b/llvm/docs/CommandGuide/dsymutil.rst
index 7ee6566cad421..d3ae16d03679e 100644
--- a/llvm/docs/CommandGuide/dsymutil.rst
+++ b/llvm/docs/CommandGuide/dsymutil.rst
@@ -37,6 +37,10 @@ OPTIONS
Dump the *executable*'s debug-map (the list of the object files containing the
debug information) in YAML format and exit. No DWARF link will take place.
+.. option:: --fat64
+
+ Use a 64-bit header when emitting universal binaries.
+
.. option:: --flat, -f
Produce a flat dSYM file. A ``.dwarf`` extension will be appended to the
diff --git a/llvm/test/tools/dsymutil/cmdline.test b/llvm/test/tools/dsymutil/cmdline.test
index 03a57f62eedbc..bf256bd4a9b70 100644
--- a/llvm/test/tools/dsymutil/cmdline.test
+++ b/llvm/test/tools/dsymutil/cmdline.test
@@ -8,6 +8,7 @@ HELP: Dsymutil Options:
CHECK: -accelerator
CHECK: -arch <arch>
CHECK: -dump-debug-map
+CHECK: -fat64
CHECK: -flat
CHECK: -gen-reproducer
CHECK: -help
diff --git a/llvm/test/tools/dsymutil/fat-header.test b/llvm/test/tools/dsymutil/fat-header.test
new file mode 100644
index 0000000000000..91192b2a412f7
--- /dev/null
+++ b/llvm/test/tools/dsymutil/fat-header.test
@@ -0,0 +1,10 @@
+REQUIRES: system-darwin
+
+RUN: dsymutil -oso-prepend-path %p %p/Inputs/fat-test.arm.dylib -o %t.fat32.dSYM
+RUN: llvm-objdump -m --universal-headers %t.fat32.dSYM/Contents/Resources/DWARF/fat-test.arm.dylib | FileCheck %s -check-prefixes=FAT32
+
+RUN: dsymutil -oso-prepend-path %p %p/Inputs/fat-test.arm.dylib -o %t.fat64.dSYM -fat64
+RUN: llvm-objdump -m --universal-headers %t.fat64.dSYM/Contents/Resources/DWARF/fat-test.arm.dylib | FileCheck %s -check-prefixes=FAT64
+
+FAT32: fat_magic FAT_MAGIC
+FAT64: fat_magic FAT_MAGIC_64
diff --git a/llvm/tools/dsymutil/LinkUtils.h b/llvm/tools/dsymutil/LinkUtils.h
index f08d92300e3a5..77f3608881416 100644
--- a/llvm/tools/dsymutil/LinkUtils.h
+++ b/llvm/tools/dsymutil/LinkUtils.h
@@ -57,6 +57,9 @@ struct LinkOptions {
/// function.
bool KeepFunctionForStatic = false;
+ /// Use a 64-bit header when emitting universal binaries.
+ bool Fat64 = false;
+
/// Number of threads.
unsigned Threads = 1;
diff --git a/llvm/tools/dsymutil/MachOUtils.cpp b/llvm/tools/dsymutil/MachOUtils.cpp
index 2d3437e1a8c97..9d440e8fb4484 100644
--- a/llvm/tools/dsymutil/MachOUtils.cpp
+++ b/llvm/tools/dsymutil/MachOUtils.cpp
@@ -78,7 +78,8 @@ static bool runLipo(StringRef SDKPath, SmallVectorImpl<StringRef> &Args) {
bool generateUniversalBinary(SmallVectorImpl<ArchAndFile> &ArchFiles,
StringRef OutputFileName,
- const LinkOptions &Options, StringRef SDKPath) {
+ const LinkOptions &Options, StringRef SDKPath,
+ bool Fat64) {
// No need to merge one file into a universal fat binary.
if (ArchFiles.size() == 1) {
if (auto E = ArchFiles.front().File->keep(OutputFileName)) {
@@ -97,7 +98,7 @@ bool generateUniversalBinary(SmallVectorImpl<ArchAndFile> &ArchFiles,
for (auto &Thin : ArchFiles)
Args.push_back(Thin.path());
- // Align segments to match dsymutil-classic alignment
+ // Align segments to match dsymutil-classic alignment.
for (auto &Thin : ArchFiles) {
Thin.Arch = getArchName(Thin.Arch);
Args.push_back("-segalign");
@@ -105,6 +106,10 @@ bool generateUniversalBinary(SmallVectorImpl<ArchAndFile> &ArchFiles,
Args.push_back("20");
}
+ // Use a 64-bit fat header if requested.
+ if (Fat64)
+ Args.push_back("-fat64");
+
Args.push_back("-output");
Args.push_back(OutputFileName.data());
diff --git a/llvm/tools/dsymutil/MachOUtils.h b/llvm/tools/dsymutil/MachOUtils.h
index 8cc4e73e59f14..9d3581348853a 100644
--- a/llvm/tools/dsymutil/MachOUtils.h
+++ b/llvm/tools/dsymutil/MachOUtils.h
@@ -54,7 +54,7 @@ struct DwarfRelocationApplicationInfo {
bool generateUniversalBinary(SmallVectorImpl<ArchAndFile> &ArchFiles,
StringRef OutputFileName, const LinkOptions &,
- StringRef SDKPath);
+ StringRef SDKPath, bool Fat64 = false);
bool generateDsymCompanion(
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, const DebugMap &DM,
SymbolMapTranslator &Translator, MCStreamer &MS, raw_fd_ostream &OutFile,
diff --git a/llvm/tools/dsymutil/Options.td b/llvm/tools/dsymutil/Options.td
index d500762fc830b..8af6dbef0c3d5 100644
--- a/llvm/tools/dsymutil/Options.td
+++ b/llvm/tools/dsymutil/Options.td
@@ -91,6 +91,10 @@ def: Flag<["-"], "f">,
HelpText<"Alias for --flat">,
Group<grp_general>;
+def fat64: F<"fat64">,
+ HelpText<"Use a 64-bit header when emitting universal binaries.">,
+ Group<grp_general>;
+
def update: F<"update">,
HelpText<"Updates existing dSYM files to contain the latest accelerator tables and other DWARF optimizations.">,
Group<grp_general>;
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index 1da434c0227e5..d868459f4327c 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -301,6 +301,7 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
Options.LinkOpts.Update = Args.hasArg(OPT_update);
Options.LinkOpts.Verbose = Args.hasArg(OPT_verbose);
Options.LinkOpts.Statistics = Args.hasArg(OPT_statistics);
+ Options.LinkOpts.Fat64 = Args.hasArg(OPT_fat64);
Options.LinkOpts.KeepFunctionForStatic =
Args.hasArg(OPT_keep_func_for_static);
@@ -780,40 +781,47 @@ int main(int argc, char **argv) {
return EXIT_FAILURE;
if (NeedsTempFiles) {
- // Universal Mach-O files can't have an archicture slice that starts
- // beyond the 4GB boundary. "lipo" can creeate a 64 bit universal header,
- // but not all tools can parse these files so we want to return an error
- // if the file can't be encoded as a file with a 32 bit universal header.
- // To detect this, we check the size of each architecture's skinny Mach-O
- // file and add up the offsets. If they exceed 4GB, then we return an
- // error.
-
- // First we compute the right offset where the first architecture will fit
- // followin the 32 bit universal header. The 32 bit universal header
- // starts with a uint32_t magic and a uint32_t number of architecture
- // infos. Then it is followed by 5 uint32_t values for each architecture.
- // So we set the start offset to the right value so we can calculate the
- // exact offset that the first architecture slice can start at.
- constexpr uint64_t MagicAndCountSize = 2 * 4;
- constexpr uint64_t UniversalArchInfoSize = 5 * 4;
- uint64_t FileOffset = MagicAndCountSize +
- UniversalArchInfoSize * TempFiles.size();
- for (const auto &File: TempFiles) {
- ErrorOr<vfs::Status> stat = Options.LinkOpts.VFS->status(File.path());
- if (!stat)
- break;
- if (FileOffset > UINT32_MAX) {
- WithColor::error() << formatv(
- "the universal binary has a slice with a starting offset ({0:x}) "
- "that exceeds 4GB and will produce an invalid Mach-O file.",
- FileOffset);
- return EXIT_FAILURE;
+ const bool Fat64 = Options.LinkOpts.Fat64;
+ if (!Fat64) {
+ // Universal Mach-O files can't have an archicture slice that starts
+ // beyond the 4GB boundary. "lipo" can create a 64 bit universal
+ // header, but not all tools can parse these files so we want to return
+ // an error if the file can't be encoded as a file with a 32 bit
+ // universal header. To detect this, we check the size of each
+ // architecture's skinny Mach-O file and add up the offsets. If they
+ // exceed 4GB, then we return an error.
+
+ // First we compute the right offset where the first architecture will
+ // fit followin the 32 bit universal header. The 32 bit universal header
+ // starts with a uint32_t magic and a uint32_t number of architecture
+ // infos. Then it is followed by 5 uint32_t values for each
+ // architecture. So we set the start offset to the right value so we can
+ // calculate the exact offset that the first architecture slice can
+ // start at.
+ constexpr uint64_t MagicAndCountSize = 2 * 4;
+ constexpr uint64_t UniversalArchInfoSize = 5 * 4;
+ uint64_t FileOffset =
+ MagicAndCountSize + UniversalArchInfoSize * TempFiles.size();
+ for (const auto &File : TempFiles) {
+ ErrorOr<vfs::Status> stat = Options.LinkOpts.VFS->status(File.path());
+ if (!stat)
+ break;
+ if (FileOffset > UINT32_MAX) {
+ WithColor::error()
+ << formatv("the universal binary has a slice with a starting "
+ "offset ({0:x}) that exceeds 4GB and will produce "
+ "an invalid Mach-O file. Use the -fat64 flag to "
+ "generate a universal binary with a 64-bit header "
+ "but note that not all tools support this format.",
+ FileOffset);
+ return EXIT_FAILURE;
+ }
+ FileOffset += stat->getSize();
}
- FileOffset += stat->getSize();
}
- if (!MachOUtils::generateUniversalBinary(TempFiles,
- OutputLocationOrErr->DWARFFile,
- Options.LinkOpts, SDKPath))
+ if (!MachOUtils::generateUniversalBinary(
+ TempFiles, OutputLocationOrErr->DWARFFile, Options.LinkOpts,
+ SDKPath, Fat64))
return EXIT_FAILURE;
}
}
More information about the llvm-commits
mailing list