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
This commit is contained in:
Tim Northover 2014-06-30 09:49:30 +00:00
parent 7650a9b871
commit 08d6a7bfef
2 changed files with 60 additions and 6 deletions

View File

@ -142,6 +142,7 @@ private:
struct SegExtraInfo {
uint32_t fileOffset;
uint32_t fileSize;
std::vector<const Section*> sections;
};
typedef std::map<const Segment*, SegExtraInfo> SegMap;
@ -423,23 +424,32 @@ void MachOFileLayout::buildFileOffsets() {
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 @@ std::error_code MachOFileLayout::writeSegmentLoadCommands(uint8_t *&lc) {
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();

View File

@ -0,0 +1,44 @@
# RUN: lld -flavor darwin -arch x86_64 %s -o %t -e start
# RUN: llvm-readobj -sections %t | FileCheck %s
# Make sure data gets put at offset
--- !native
defined-atoms:
- name: start
scope: global
content: [ 90 ]
- name: _s1
type: data
content: [ 31, 32, 33, 34 ]
- name: _s2
type: zero-fill
size: 8192
- name: _s3
type: zero-fill
size: 100
- name: _s4
type: data
content: [ 01 ]
# CHECK-LABEL: Section {
# CHECK: Name: __text
# CHECK: Segment: __TEXT
# CHECK: Size: 0x1
# CHECK: Offset: 0
# CHECK-LABEL: Section {
# CHECK: Name: __data
# CHECK: Segment: __DATA
# CHECK: Size: 0x5
# CHECK: Offset: 4096
# CHECK-LABEL: Section {
# CHECK: Name: ___bss
# CHECK: Segment: __DATA
# CHECK: Size: 0x0
# CHECK: Offset: 4101