forked from OSchip/llvm-project
llvm-mc/Mach-O: Add section padding where needed (to align the next section).
Also, simplify some of Mach-O writer code which can now use section addresses. llvm-svn: 80067
This commit is contained in:
parent
458055a890
commit
066d0f93bf
|
@ -82,7 +82,7 @@ public:
|
|||
|
||||
uint64_t getAddress() const;
|
||||
|
||||
unsigned getFileSize() const {
|
||||
uint64_t getFileSize() const {
|
||||
assert(FileSize != ~UINT64_C(0) && "File size not set!");
|
||||
return FileSize;
|
||||
}
|
||||
|
@ -267,6 +267,9 @@ private:
|
|||
/// initialized.
|
||||
uint64_t Address;
|
||||
|
||||
/// Size - The content size of this section. This is ~0 until initialized.
|
||||
uint64_t Size;
|
||||
|
||||
/// FileSize - The size of this section in the object file. This is ~0 until
|
||||
/// initialized.
|
||||
uint64_t FileSize;
|
||||
|
@ -305,13 +308,19 @@ public:
|
|||
//
|
||||
// FIXME: This could all be kept private to the assembler implementation.
|
||||
|
||||
unsigned getAddress() const {
|
||||
uint64_t getAddress() const {
|
||||
assert(Address != ~UINT64_C(0) && "Address not set!");
|
||||
return Address;
|
||||
}
|
||||
void setAddress(uint64_t Value) { Address = Value; }
|
||||
|
||||
unsigned getFileSize() const {
|
||||
uint64_t getSize() const {
|
||||
assert(Size != ~UINT64_C(0) && "File size not set!");
|
||||
return Size;
|
||||
}
|
||||
void setSize(uint64_t Value) { Size = Value; }
|
||||
|
||||
uint64_t getFileSize() const {
|
||||
assert(FileSize != ~UINT64_C(0) && "File size not set!");
|
||||
return FileSize;
|
||||
}
|
||||
|
@ -414,7 +423,11 @@ private:
|
|||
/// LayoutSection - Assign offsets and sizes to the fragments in the section
|
||||
/// \arg SD, and update the section size. The section file offset should
|
||||
/// already have been computed.
|
||||
void LayoutSection(MCSectionData &SD);
|
||||
///
|
||||
/// \param NextAlign - The alignment for the section end address, which may
|
||||
/// add padding bytes to the section (these are included in the section "file"
|
||||
/// size, but not its regular size).
|
||||
void LayoutSection(MCSectionData &SD, unsigned NextAlign);
|
||||
|
||||
public:
|
||||
/// Construct a new assembler instance.
|
||||
|
|
|
@ -217,7 +217,7 @@ public:
|
|||
WriteString(Section.getSectionName(), 16);
|
||||
WriteString(Section.getSegmentName(), 16);
|
||||
Write32(SD.getAddress()); // address
|
||||
Write32(SD.getFileSize()); // size
|
||||
Write32(SD.getSize()); // size
|
||||
Write32(FileOffset);
|
||||
|
||||
assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!");
|
||||
|
@ -507,11 +507,6 @@ public:
|
|||
if (NumSymbols)
|
||||
ComputeSymbolTable(Asm, StringTable, LocalSymbolData, ExternalSymbolData,
|
||||
UndefinedSymbolData);
|
||||
|
||||
// Compute the file offsets for all the sections in advance, so that we can
|
||||
// write things out in order.
|
||||
SmallVector<uint64_t, 16> SectionFileOffsets;
|
||||
SectionFileOffsets.resize(NumSections);
|
||||
|
||||
// The section data starts after the header, the segment load command (and
|
||||
// section headers) and the symbol table.
|
||||
|
@ -525,27 +520,22 @@ public:
|
|||
LoadCommandsSize += SymtabLoadCommandSize + DysymtabLoadCommandSize;
|
||||
}
|
||||
|
||||
uint64_t FileOffset = Header32Size + LoadCommandsSize;
|
||||
uint64_t SectionDataStartOffset = FileOffset;
|
||||
uint64_t SectionDataStart = Header32Size + LoadCommandsSize;
|
||||
uint64_t SectionDataEnd = SectionDataStart;
|
||||
uint64_t SectionDataSize = 0;
|
||||
unsigned Index = 0;
|
||||
for (MCAssembler::iterator it = Asm.begin(),
|
||||
ie = Asm.end(); it != ie; ++it, ++Index) {
|
||||
SectionFileOffsets[Index] = FileOffset;
|
||||
FileOffset += it->getFileSize();
|
||||
SectionDataSize += it->getFileSize();
|
||||
if (!Asm.getSectionList().empty()) {
|
||||
MCSectionData &SD = Asm.getSectionList().back();
|
||||
SectionDataSize = SD.getAddress() + SD.getSize();
|
||||
SectionDataEnd = SectionDataStart + SD.getAddress() + SD.getFileSize();
|
||||
}
|
||||
|
||||
// Write the prolog, starting with the header and load command...
|
||||
WriteHeader32(NumLoadCommands, LoadCommandsSize);
|
||||
WriteSegmentLoadCommand32(NumSections, SectionDataStartOffset,
|
||||
SectionDataSize);
|
||||
WriteSegmentLoadCommand32(NumSections, SectionDataStart, SectionDataSize);
|
||||
|
||||
// ... and then the section headers.
|
||||
Index = 0;
|
||||
for (MCAssembler::iterator it = Asm.begin(),
|
||||
ie = Asm.end(); it != ie; ++it, ++Index)
|
||||
WriteSection32(*it, SectionFileOffsets[Index]);
|
||||
for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
|
||||
WriteSection32(*it, SectionDataStart + it->getAddress());
|
||||
|
||||
// Write the symbol table load command, if used.
|
||||
if (NumSymbols) {
|
||||
|
@ -563,11 +553,10 @@ public:
|
|||
|
||||
// If used, the indirect symbols are written after the section data.
|
||||
if (NumIndirectSymbols)
|
||||
IndirectSymbolOffset = SectionDataStartOffset + SectionDataSize;
|
||||
IndirectSymbolOffset = SectionDataEnd;
|
||||
|
||||
// The symbol table is written after the indirect symbol data.
|
||||
uint64_t SymbolTableOffset =
|
||||
SectionDataStartOffset + SectionDataSize + IndirectSymbolSize;
|
||||
uint64_t SymbolTableOffset = SectionDataEnd + IndirectSymbolSize;
|
||||
|
||||
// The string table is written after symbol table.
|
||||
uint64_t StringTableOffset =
|
||||
|
@ -675,6 +664,7 @@ MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
|
|||
: Section(_Section),
|
||||
Alignment(1),
|
||||
Address(~UINT64_C(0)),
|
||||
Size(~UINT64_C(0)),
|
||||
FileSize(~UINT64_C(0))
|
||||
{
|
||||
if (A)
|
||||
|
@ -701,26 +691,24 @@ MCAssembler::MCAssembler(raw_ostream &_OS) : OS(_OS) {}
|
|||
MCAssembler::~MCAssembler() {
|
||||
}
|
||||
|
||||
void MCAssembler::LayoutSection(MCSectionData &SD) {
|
||||
uint64_t Offset = 0;
|
||||
void MCAssembler::LayoutSection(MCSectionData &SD, unsigned NextAlign) {
|
||||
uint64_t Address = SD.getAddress();
|
||||
|
||||
for (MCSectionData::iterator it = SD.begin(), ie = SD.end(); it != ie; ++it) {
|
||||
MCFragment &F = *it;
|
||||
|
||||
F.setOffset(Offset);
|
||||
F.setOffset(Address - SD.getAddress());
|
||||
|
||||
// Evaluate fragment size.
|
||||
switch (F.getKind()) {
|
||||
case MCFragment::FT_Align: {
|
||||
MCAlignFragment &AF = cast<MCAlignFragment>(F);
|
||||
|
||||
uint64_t AlignedOffset = RoundUpToAlignment(Offset, AF.getAlignment());
|
||||
uint64_t PaddingBytes = AlignedOffset - Offset;
|
||||
|
||||
if (PaddingBytes > AF.getMaxBytesToEmit())
|
||||
uint64_t Size = RoundUpToAlignment(Address, AF.getAlignment()) - Address;
|
||||
if (Size > AF.getMaxBytesToEmit())
|
||||
AF.setFileSize(0);
|
||||
else
|
||||
AF.setFileSize(PaddingBytes);
|
||||
AF.setFileSize(Size);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -735,22 +723,24 @@ void MCAssembler::LayoutSection(MCSectionData &SD) {
|
|||
if (!OF.getOffset().isAbsolute())
|
||||
llvm_unreachable("FIXME: Not yet implemented!");
|
||||
uint64_t OrgOffset = OF.getOffset().getConstant();
|
||||
uint64_t Offset = Address - SD.getAddress();
|
||||
|
||||
// FIXME: We need a way to communicate this error.
|
||||
if (OrgOffset < Offset)
|
||||
llvm_report_error("invalid .org offset '" + Twine(OrgOffset) +
|
||||
"' (section offset '" + Twine(Offset) + "'");
|
||||
"' (at offset '" + Twine(Offset) + "'");
|
||||
|
||||
F.setFileSize(OrgOffset - Offset);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
Offset += F.getFileSize();
|
||||
Address += F.getFileSize();
|
||||
}
|
||||
|
||||
// FIXME: Pad section?
|
||||
SD.setFileSize(Offset);
|
||||
// Set the section sizes.
|
||||
SD.setSize(Address - SD.getAddress());
|
||||
SD.setFileSize(RoundUpToAlignment(Address, NextAlign) - SD.getAddress());
|
||||
}
|
||||
|
||||
/// WriteFileData - Write the \arg F data to the output file.
|
||||
|
@ -836,16 +826,32 @@ static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
|
|||
ie = SD.end(); it != ie; ++it)
|
||||
WriteFileData(OS, *it, MOW);
|
||||
|
||||
// Add section padding.
|
||||
assert(SD.getFileSize() >= SD.getSize() && "Invalid section sizes!");
|
||||
MOW.WriteZeros(SD.getFileSize() - SD.getSize());
|
||||
|
||||
assert(OS.tell() - Start == SD.getFileSize());
|
||||
}
|
||||
|
||||
void MCAssembler::Finish() {
|
||||
// Layout the sections and fragments.
|
||||
uint64_t Address = 0;
|
||||
for (iterator it = begin(), ie = end(); it != ie; ++it) {
|
||||
it->setAddress(Address);
|
||||
LayoutSection(*it);
|
||||
Address += it->getFileSize();
|
||||
for (iterator it = begin(), ie = end(); it != ie;) {
|
||||
MCSectionData &SD = *it;
|
||||
|
||||
// Select the amount of padding alignment we need, based on either the next
|
||||
// sections alignment or the default alignment.
|
||||
//
|
||||
// FIXME: This should probably match the native word size.
|
||||
unsigned NextAlign = 4;
|
||||
++it;
|
||||
if (it != ie)
|
||||
NextAlign = it->getAlignment();
|
||||
|
||||
// Layout the section fragments and its size.
|
||||
SD.setAddress(Address);
|
||||
LayoutSection(SD, NextAlign);
|
||||
Address += SD.getFileSize();
|
||||
}
|
||||
|
||||
// Write the object file.
|
||||
|
|
|
@ -0,0 +1,87 @@
|
|||
// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump | FileCheck %s
|
||||
|
||||
name:
|
||||
.byte 0
|
||||
|
||||
// Check that symbol table is aligned to 4 bytes.
|
||||
|
||||
|
||||
// CHECK: ('cputype', 7)
|
||||
// CHECK: ('cpusubtype', 3)
|
||||
// CHECK: ('filetype', 1)
|
||||
// CHECK: ('num_load_commands', 1)
|
||||
// CHECK: ('load_commands_size', 228)
|
||||
// CHECK: ('flag', 0)
|
||||
// CHECK: ('load_commands', [
|
||||
// CHECK: # Load Command 0
|
||||
// CHECK: (('command', 1)
|
||||
// CHECK: ('size', 124)
|
||||
// CHECK: ('segment_name', '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('vm_addr', 0)
|
||||
// CHECK: ('vm_size', 1)
|
||||
// CHECK: ('file_offset', 256)
|
||||
// CHECK: ('file_size', 1)
|
||||
// CHECK: ('maxprot', 7)
|
||||
// CHECK: ('initprot', 7)
|
||||
// CHECK: ('num_sections', 1)
|
||||
// CHECK: ('flags', 0)
|
||||
// CHECK: ('sections', [
|
||||
// CHECK: # Section 0
|
||||
// CHECK: (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('address', 0)
|
||||
// CHECK: ('size', 1)
|
||||
// CHECK: ('offset', 256)
|
||||
// CHECK: ('alignment', 0)
|
||||
// CHECK: ('reloc_offset', 0)
|
||||
// CHECK: ('num_reloc', 0)
|
||||
// CHECK: ('flags', 0x80000000)
|
||||
// CHECK: ('reserved1', 0)
|
||||
// CHECK: ('reserved2', 0)
|
||||
// CHECK: ),
|
||||
// CHECK: ])
|
||||
// CHECK: ),
|
||||
// CHECK: # Load Command 1
|
||||
// CHECK: (('command', 2)
|
||||
// CHECK: ('size', 24)
|
||||
// CHECK: ('symoff', 260)
|
||||
// CHECK: ('nsyms', 1)
|
||||
// CHECK: ('stroff', 272)
|
||||
// CHECK: ('strsize', 8)
|
||||
// CHECK: ('_string_data', '\x00name\x00\x00\x00')
|
||||
// CHECK: ('_symbols', [
|
||||
// CHECK: # Symbol 0
|
||||
// CHECK: (('n_strx', 1)
|
||||
// CHECK: ('n_type', 0xe)
|
||||
// CHECK: ('n_sect', 1)
|
||||
// CHECK: ('n_desc', 0)
|
||||
// CHECK: ('n_value', 0)
|
||||
// CHECK: ('_string', 'name')
|
||||
// CHECK: ),
|
||||
// CHECK: ])
|
||||
// CHECK: ),
|
||||
// CHECK: # Load Command 2
|
||||
// CHECK: (('command', 11)
|
||||
// CHECK: ('size', 80)
|
||||
// CHECK: ('ilocalsym', 0)
|
||||
// CHECK: ('nlocalsym', 1)
|
||||
// CHECK: ('iextdefsym', 1)
|
||||
// CHECK: ('nextdefsym', 0)
|
||||
// CHECK: ('iundefsym', 1)
|
||||
// CHECK: ('nundefsym', 0)
|
||||
// CHECK: ('tocoff', 0)
|
||||
// CHECK: ('ntoc', 0)
|
||||
// CHECK: ('modtaboff', 0)
|
||||
// CHECK: ('nmodtab', 0)
|
||||
// CHECK: ('extrefsymoff', 0)
|
||||
// CHECK: ('nextrefsyms', 0)
|
||||
// CHECK: ('indirectsymoff', 0)
|
||||
// CHECK: ('nindirectsyms', 0)
|
||||
// CHECK: ('extreloff', 0)
|
||||
// CHECK: ('nextrel', 0)
|
||||
// CHECK: ('locreloff', 0)
|
||||
// CHECK: ('nlocrel', 0)
|
||||
// CHECK: ('_indirect_symbols', [
|
||||
// CHECK: ])
|
||||
// CHECK: ),
|
||||
// CHECK: ])
|
|
@ -0,0 +1,137 @@
|
|||
// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump | FileCheck %s
|
||||
|
||||
.byte 0
|
||||
|
||||
// There should be 3 padding bytes here.
|
||||
|
||||
.data
|
||||
.align 2
|
||||
foo:
|
||||
.org 8
|
||||
bar:
|
||||
.byte 0
|
||||
|
||||
.const
|
||||
baz:
|
||||
|
||||
// CHECK: ('cputype', 7)
|
||||
// CHECK: ('cpusubtype', 3)
|
||||
// CHECK: ('filetype', 1)
|
||||
// CHECK: ('num_load_commands', 1)
|
||||
// CHECK: ('load_commands_size', 364)
|
||||
// CHECK: ('flag', 0)
|
||||
// CHECK: ('load_commands', [
|
||||
// CHECK: # Load Command 0
|
||||
// CHECK: (('command', 1)
|
||||
// CHECK: ('size', 260)
|
||||
// CHECK: ('segment_name', '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('vm_addr', 0)
|
||||
// CHECK: ('vm_size', 13)
|
||||
// CHECK: ('file_offset', 392)
|
||||
// CHECK: ('file_size', 13)
|
||||
// CHECK: ('maxprot', 7)
|
||||
// CHECK: ('initprot', 7)
|
||||
// CHECK: ('num_sections', 3)
|
||||
// CHECK: ('flags', 0)
|
||||
// CHECK: ('sections', [
|
||||
// CHECK: # Section 0
|
||||
// CHECK: (('section_name', '__text\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('address', 0)
|
||||
// CHECK: ('size', 1)
|
||||
// CHECK: ('offset', 392)
|
||||
// CHECK: ('alignment', 0)
|
||||
// CHECK: ('reloc_offset', 0)
|
||||
// CHECK: ('num_reloc', 0)
|
||||
// CHECK: ('flags', 0x80000000)
|
||||
// CHECK: ('reserved1', 0)
|
||||
// CHECK: ('reserved2', 0)
|
||||
// CHECK: ),
|
||||
// CHECK: # Section 1
|
||||
// CHECK: (('section_name', '__data\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('address', 4)
|
||||
// CHECK: ('size', 9)
|
||||
// CHECK: ('offset', 396)
|
||||
// CHECK: ('alignment', 2)
|
||||
// CHECK: ('reloc_offset', 0)
|
||||
// CHECK: ('num_reloc', 0)
|
||||
// CHECK: ('flags', 0x0)
|
||||
// CHECK: ('reserved1', 0)
|
||||
// CHECK: ('reserved2', 0)
|
||||
// CHECK: ),
|
||||
// CHECK: # Section 2
|
||||
// CHECK: (('section_name', '__const\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
|
||||
// CHECK: ('address', 13)
|
||||
// CHECK: ('size', 0)
|
||||
// CHECK: ('offset', 405)
|
||||
// CHECK: ('alignment', 0)
|
||||
// CHECK: ('reloc_offset', 0)
|
||||
// CHECK: ('num_reloc', 0)
|
||||
// CHECK: ('flags', 0x0)
|
||||
// CHECK: ('reserved1', 0)
|
||||
// CHECK: ('reserved2', 0)
|
||||
// CHECK: ),
|
||||
// CHECK: ])
|
||||
// CHECK: ),
|
||||
// CHECK: # Load Command 1
|
||||
// CHECK: (('command', 2)
|
||||
// CHECK: ('size', 24)
|
||||
// CHECK: ('symoff', 408)
|
||||
// CHECK: ('nsyms', 3)
|
||||
// CHECK: ('stroff', 444)
|
||||
// CHECK: ('strsize', 16)
|
||||
// CHECK: ('_string_data', '\x00foo\x00bar\x00baz\x00\x00\x00\x00')
|
||||
// CHECK: ('_symbols', [
|
||||
// CHECK: # Symbol 0
|
||||
// CHECK: (('n_strx', 1)
|
||||
// CHECK: ('n_type', 0xe)
|
||||
// CHECK: ('n_sect', 2)
|
||||
// CHECK: ('n_desc', 0)
|
||||
// CHECK: ('n_value', 4)
|
||||
// CHECK: ('_string', 'foo')
|
||||
// CHECK: ),
|
||||
// CHECK: # Symbol 1
|
||||
// CHECK: (('n_strx', 5)
|
||||
// CHECK: ('n_type', 0xe)
|
||||
// CHECK: ('n_sect', 2)
|
||||
// CHECK: ('n_desc', 0)
|
||||
// CHECK: ('n_value', 12)
|
||||
// CHECK: ('_string', 'bar')
|
||||
// CHECK: ),
|
||||
// CHECK: # Symbol 2
|
||||
// CHECK: (('n_strx', 9)
|
||||
// CHECK: ('n_type', 0xe)
|
||||
// CHECK: ('n_sect', 3)
|
||||
// CHECK: ('n_desc', 0)
|
||||
// CHECK: ('n_value', 13)
|
||||
// CHECK: ('_string', 'baz')
|
||||
// CHECK: ),
|
||||
// CHECK: ])
|
||||
// CHECK: ),
|
||||
// CHECK: # Load Command 2
|
||||
// CHECK: (('command', 11)
|
||||
// CHECK: ('size', 80)
|
||||
// CHECK: ('ilocalsym', 0)
|
||||
// CHECK: ('nlocalsym', 3)
|
||||
// CHECK: ('iextdefsym', 3)
|
||||
// CHECK: ('nextdefsym', 0)
|
||||
// CHECK: ('iundefsym', 3)
|
||||
// CHECK: ('nundefsym', 0)
|
||||
// CHECK: ('tocoff', 0)
|
||||
// CHECK: ('ntoc', 0)
|
||||
// CHECK: ('modtaboff', 0)
|
||||
// CHECK: ('nmodtab', 0)
|
||||
// CHECK: ('extrefsymoff', 0)
|
||||
// CHECK: ('nextrefsyms', 0)
|
||||
// CHECK: ('indirectsymoff', 0)
|
||||
// CHECK: ('nindirectsyms', 0)
|
||||
// CHECK: ('extreloff', 0)
|
||||
// CHECK: ('nextrel', 0)
|
||||
// CHECK: ('locreloff', 0)
|
||||
// CHECK: ('nlocrel', 0)
|
||||
// CHECK: ('_indirect_symbols', [
|
||||
// CHECK: ])
|
||||
// CHECK: ),
|
||||
// CHECK: ])
|
Loading…
Reference in New Issue