MachO: calculate segment offsets in final MachO files properly.
Because of how we were calculating fileOffset and fileSize for segments, most
ended up at a single offset in a finalised MachO file. This meant the data
often didn't even get written in the final object, let alone where it would be
useful.
llvm-svn: 212030
diff --git a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
index a593f07..2f61607 100644
--- a/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
+++ b/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
@@ -142,6 +142,7 @@
struct SegExtraInfo {
uint32_t fileOffset;
+ uint32_t fileSize;
std::vector<const Section*> sections;
};
typedef std::map<const Segment*, SegExtraInfo> SegMap;
@@ -423,23 +424,32 @@
DEBUG_WITH_TYPE("MachOFileLayout",
llvm::dbgs() << "buildFileOffsets()\n");
for (const Segment &sg : _file.segments) {
- // FIXME: 4096 should be inferred from segments in normalized file.
- _segInfo[&sg].fileOffset = llvm::RoundUpToAlignment(fileOffset, 4096);
+ _segInfo[&sg].fileOffset = fileOffset;
if ((_seg1addr == INT64_MAX) && sg.access)
_seg1addr = sg.address;
DEBUG_WITH_TYPE("MachOFileLayout",
llvm::dbgs() << " segment=" << sg.name
<< ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
+
+ uint32_t segFileSize = 0;
for (const Section *s : _segInfo[&sg].sections) {
- fileOffset = s->address - sg.address + _segInfo[&sg].fileOffset;
- _sectInfo[s].fileOffset = fileOffset;
+ uint32_t sectOffset = s->address - sg.address;
+ uint32_t sectFileSize =
+ s->type == llvm::MachO::S_ZEROFILL ? 0 : s->content.size();
+ segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
+
+ _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
DEBUG_WITH_TYPE("MachOFileLayout",
llvm::dbgs() << " section=" << s->sectionName
<< ", fileOffset=" << fileOffset << "\n");
}
+
+ // FIXME: 4096 should be inferred from segments in normalized file.
+ _segInfo[&sg].fileSize = llvm::RoundUpToAlignment(segFileSize, 4096);
+ fileOffset = llvm::RoundUpToAlignment(fileOffset + segFileSize, 4096);
_addressOfLinkEdit = sg.address + sg.size;
}
- _startOfLinkEdit = llvm::RoundUpToAlignment(fileOffset, 4096);
+ _startOfLinkEdit = fileOffset;
}
@@ -537,7 +547,7 @@
cmd->vmaddr = seg.address;
cmd->vmsize = seg.size;
cmd->fileoff = segInfo.fileOffset;
- cmd->filesize = seg.access ? seg.size : Hex64(0);
+ cmd->filesize = segInfo.fileSize;
cmd->maxprot = seg.access;
cmd->initprot = seg.access;
cmd->nsects = segInfo.sections.size();