[llvm] [dsymutil] Add new argument allow_invalid_macho (PR #173503)

via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 24 10:15:39 PST 2025


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-debuginfo

Author: Ch1p (Ch111p)

<details>
<summary>Changes</summary>

Similar to the issue discussed in [#<!-- -->165940](https://github.com/llvm/llvm-project/pull/165940) and in some apps I’ve seen at work, we’ve observed dSYM files being generated where a section’s offset exceeds 4GB.

This seems to happen because many DWARF sections produced for DWARF4 end up with an alignment of 0. Before [PR #<!-- -->168925](https://github.com/llvm/llvm-project/pull/168925) (which added validation for sections with a zero alignment attribute), this could go unnoticed and result in an invalid MachO.

However, such a dSYM is effectively an invalid Mach-O file today. Unless/until Mach-O explicitly defines standards like:
["32-bit section offsets can exceed 4G but must be ordered for 64-bit offset reconstruction"](https://github.com/llvm/llvm-project/pull/165940#issuecomment-3483238444), I think the proper approach is to add a new argument to support this.

---
Full diff: https://github.com/llvm/llvm-project/pull/173503.diff


6 Files Affected:

- (modified) llvm/tools/dsymutil/DwarfLinkerForBinary.cpp (+1-1) 
- (modified) llvm/tools/dsymutil/LinkUtils.h (+4) 
- (modified) llvm/tools/dsymutil/MachOUtils.cpp (+4-4) 
- (modified) llvm/tools/dsymutil/MachOUtils.h (+1-1) 
- (modified) llvm/tools/dsymutil/Options.td (+6) 
- (modified) llvm/tools/dsymutil/dsymutil.cpp (+2) 


``````````diff
diff --git a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
index 1fc5bba602d8b..68756a891d90d 100644
--- a/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
+++ b/llvm/tools/dsymutil/DwarfLinkerForBinary.cpp
@@ -883,7 +883,7 @@ bool DwarfLinkerForBinary::linkImpl(
       ObjectType == Linker::OutputFileType::Object)
     return MachOUtils::generateDsymCompanion(
         Options.VFS, Map, *Streamer->getAsmPrinter().OutStreamer, OutFile,
-        RelocationsToApply);
+        RelocationsToApply, Options.AllowInvalidMachO);
 
   Streamer->finish();
   return true;
diff --git a/llvm/tools/dsymutil/LinkUtils.h b/llvm/tools/dsymutil/LinkUtils.h
index c333a3d4afee0..d950f5f19474c 100644
--- a/llvm/tools/dsymutil/LinkUtils.h
+++ b/llvm/tools/dsymutil/LinkUtils.h
@@ -123,6 +123,10 @@ struct LinkOptions {
   bool IncludeSwiftModulesFromInterface = false;
   /// @}
 
+  /// Whether to allow generating Mach-O files that exceed certain format
+  /// limitations, such as sections with file offsets greater than 4GB.
+  bool AllowInvalidMachO = false;
+
   LinkOptions() = default;
 };
 
diff --git a/llvm/tools/dsymutil/MachOUtils.cpp b/llvm/tools/dsymutil/MachOUtils.cpp
index fba698896618b..deb2225dc22c6 100644
--- a/llvm/tools/dsymutil/MachOUtils.cpp
+++ b/llvm/tools/dsymutil/MachOUtils.cpp
@@ -324,7 +324,7 @@ static void transferSegmentAndSections(
 // Write the __DWARF segment load command to the output file.
 static bool createDwarfSegment(const MCAssembler& Asm,uint64_t VMAddr, uint64_t FileOffset,
                                uint64_t FileSize, unsigned NumSections,
-                                MachObjectWriter &Writer) {
+                                MachObjectWriter &Writer, bool AllowInvalidMachO) {
   Writer.writeSegmentLoadCommand("__DWARF", NumSections, VMAddr,
                                  alignTo(FileSize, 0x1000), FileOffset,
                                  FileSize, /* MaxProt */ 7,
@@ -340,7 +340,7 @@ static bool createDwarfSegment(const MCAssembler& Asm,uint64_t VMAddr, uint64_t
       VMAddr = alignTo(VMAddr, Alignment);
       FileOffset = alignTo(FileOffset, Alignment);
     }
-    if (FileOffset > UINT32_MAX)
+    if (FileOffset > UINT32_MAX && !AllowInvalidMachO)
       return error("section " + Sec->getName() +
                    "'s file offset exceeds 4GB."
                    " Refusing to produce an invalid Mach-O file.");
@@ -374,7 +374,7 @@ bool generateDsymCompanion(
     llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, const DebugMap &DM,
     MCStreamer &MS, raw_fd_ostream &OutFile,
     const std::vector<MachOUtils::DwarfRelocationApplicationInfo>
-        &RelocationsToApply) {
+        &RelocationsToApply, bool AllowInvalidMachO) {
   auto &ObjectStreamer = static_cast<MCObjectStreamer &>(MS);
   MCAssembler &MCAsm = ObjectStreamer.getAssembler();
   auto &Writer = static_cast<MachObjectWriter &>(MCAsm.getWriter());
@@ -586,7 +586,7 @@ bool generateDsymCompanion(
 
   // Write the load command for the __DWARF segment.
   if (!createDwarfSegment(MCAsm, DwarfVMAddr, DwarfSegmentStart, DwarfSegmentSize,
-                          NumDwarfSections, Writer))
+                          NumDwarfSections, Writer, AllowInvalidMachO))
     return false;
 
   assert(OutFile.tell() == LoadCommandSize + HeaderSize);
diff --git a/llvm/tools/dsymutil/MachOUtils.h b/llvm/tools/dsymutil/MachOUtils.h
index 0229647b00f85..d276a21b6de72 100644
--- a/llvm/tools/dsymutil/MachOUtils.h
+++ b/llvm/tools/dsymutil/MachOUtils.h
@@ -59,7 +59,7 @@ bool generateDsymCompanion(
     llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> VFS, const DebugMap &DM,
     MCStreamer &MS, raw_fd_ostream &OutFile,
     const std::vector<MachOUtils::DwarfRelocationApplicationInfo>
-        &RelocationsToApply);
+        &RelocationsToApply, bool AllowInvalidMachO);
 
 std::string getArchName(StringRef Arch);
 } // namespace MachOUtils
diff --git a/llvm/tools/dsymutil/Options.td b/llvm/tools/dsymutil/Options.td
index 571f90c1e46f5..036094f5eeca5 100644
--- a/llvm/tools/dsymutil/Options.td
+++ b/llvm/tools/dsymutil/Options.td
@@ -108,6 +108,12 @@ def fat64: F<"fat64">,
 def update: F<"update">,
   HelpText<"Updates existing dSYM files to contain the latest accelerator tables and other DWARF optimizations.">,
   Group<grp_general>;
+
+def allow_invalid_macho: F<"allow-invalid-macho">,
+  HelpText<"Allow generating Mach-O files that exceed certain format limitations, such as sections with file offsets greater than 4GB."
+           "Use with caution, as such files may not be compatible with all tools.">,
+  Group<grp_general>;
+
 def: Flag<["-"], "u">,
   Alias<update>,
   HelpText<"Alias for --update">,
diff --git a/llvm/tools/dsymutil/dsymutil.cpp b/llvm/tools/dsymutil/dsymutil.cpp
index a71c57c60593c..0a3af1bdb0cec 100644
--- a/llvm/tools/dsymutil/dsymutil.cpp
+++ b/llvm/tools/dsymutil/dsymutil.cpp
@@ -315,6 +315,8 @@ static Expected<DsymutilOptions> getOptions(opt::InputArgList &Args) {
   Options.LinkOpts.Fat64 = Args.hasArg(OPT_fat64);
   Options.LinkOpts.KeepFunctionForStatic =
       Args.hasArg(OPT_keep_func_for_static);
+  Options.LinkOpts.AllowInvalidMachO =
+      Args.hasArg(OPT_allow_invalid_macho);
 
   if (opt::Arg *ReproducerPath = Args.getLastArg(OPT_use_reproducer)) {
     Options.ReproMode = ReproducerMode::Use;

``````````

</details>


https://github.com/llvm/llvm-project/pull/173503


More information about the llvm-commits mailing list