forked from OSchip/llvm-project
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:
parent
7650a9b871
commit
08d6a7bfef
|
@ -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();
|
||||
|
|
|
@ -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
|
Loading…
Reference in New Issue