[PATCH] D121398: Return an error when dsymutil might produce an invalid mach-o file.
Greg Clayton via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Fri Mar 11 10:00:54 PST 2022
This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG0bc845fe24ce: Return an error when dsymutil might produce an invalid mach-o file. (authored by clayborg).
Changed prior to commit:
https://reviews.llvm.org/D121398?vs=414526&id=414687#toc
Repository:
rG LLVM Github Monorepo
CHANGES SINCE LAST ACTION
https://reviews.llvm.org/D121398/new/
https://reviews.llvm.org/D121398
Files:
llvm/tools/dsymutil/MachOUtils.cpp
llvm/tools/dsymutil/dsymutil.cpp
Index: llvm/tools/dsymutil/dsymutil.cpp
===================================================================
--- llvm/tools/dsymutil/dsymutil.cpp
+++ llvm/tools/dsymutil/dsymutil.cpp
@@ -730,24 +730,40 @@
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;
+ FileOffset += stat->getSize();
+ if (FileOffset > UINT32_MAX) {
+ WithColor::error() << "the univesral binary has a slice with an "
+ "offset exceeds 4GB and will produce an invalid Mach-O file.";
+ return EXIT_FAILURE;
+ }
+ }
if (!MachOUtils::generateUniversalBinary(TempFiles,
OutputLocationOrErr->DWARFFile,
Options.LinkOpts, SDKPath))
return EXIT_FAILURE;
}
-
- // The Mach-O object file format is limited to 4GB. Make sure that we print
- // an error when we emit an invalid Mach-O companion file. Leave the
- // invalid object file around on disk for inspection.
- ErrorOr<vfs::Status> stat =
- Options.LinkOpts.VFS->status(OutputLocationOrErr->DWARFFile);
- if (stat) {
- if (stat->getSize() > std::numeric_limits<uint32_t>::max()) {
- WithColor::error() << "the linked debug info exceeds the 4GB Mach-O "
- "object file format.";
- return EXIT_FAILURE;
- }
- }
}
return EXIT_SUCCESS;
Index: llvm/tools/dsymutil/MachOUtils.cpp
===================================================================
--- llvm/tools/dsymutil/MachOUtils.cpp
+++ llvm/tools/dsymutil/MachOUtils.cpp
@@ -304,7 +304,7 @@
}
// Write the __DWARF segment load command to the output file.
-static void createDwarfSegment(uint64_t VMAddr, uint64_t FileOffset,
+static bool createDwarfSegment(uint64_t VMAddr, uint64_t FileOffset,
uint64_t FileSize, unsigned NumSections,
MCAsmLayout &Layout, MachObjectWriter &Writer) {
Writer.writeSegmentLoadCommand("__DWARF", NumSections, VMAddr,
@@ -321,12 +321,16 @@
if (Align > 1) {
VMAddr = alignTo(VMAddr, Align);
FileOffset = alignTo(FileOffset, Align);
+ if (FileOffset > UINT32_MAX)
+ return error("section " + Sec->getName() + "'s file offset exceeds 4GB."
+ " Refusing to produce an invalid Mach-O file.");
}
Writer.writeSection(Layout, *Sec, VMAddr, FileOffset, 0, 0, 0);
FileOffset += Layout.getSectionAddressSize(Sec);
VMAddr += Layout.getSectionAddressSize(Sec);
}
+ return true;
}
static bool isExecutable(const object::MachOObjectFile &Obj) {
@@ -564,8 +568,9 @@
}
// Write the load command for the __DWARF segment.
- createDwarfSegment(DwarfVMAddr, DwarfSegmentStart, DwarfSegmentSize,
- NumDwarfSections, Layout, Writer);
+ if (!createDwarfSegment(DwarfVMAddr, DwarfSegmentStart, DwarfSegmentSize,
+ NumDwarfSections, Layout, Writer))
+ return false;
assert(OutFile.tell() == LoadCommandSize + HeaderSize);
OutFile.write_zeros(SymtabStart - (LoadCommandSize + HeaderSize));
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D121398.414687.patch
Type: text/x-patch
Size: 4470 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20220311/954b657d/attachment.bin>
More information about the llvm-commits
mailing list