llvm-mc: Support .zerofill emission.

- I'm still trying to figure out the cleanest way to implement this and match the assembler, currently there are some substantial differences.

llvm-svn: 80347
This commit is contained in:
Daniel Dunbar 2009-08-28 05:49:21 +00:00
parent 1935aed414
commit 5749caa698
7 changed files with 623 additions and 5 deletions

View File

@ -33,7 +33,8 @@ public:
FT_Data,
FT_Align,
FT_Fill,
FT_Org
FT_Org,
FT_ZeroFill
};
private:
@ -218,6 +219,7 @@ public:
MCOrgFragment(MCValue _Offset, int8_t _Value, MCSectionData *SD = 0)
: MCFragment(FT_Org, SD),
Offset(_Offset), Value(_Value) {}
/// @name Accessors
/// @{
@ -238,6 +240,40 @@ public:
static bool classof(const MCOrgFragment *) { return true; }
};
/// MCZeroFillFragment - Represent data which has a fixed size and alignment,
/// but requires no physical space in the object file.
class MCZeroFillFragment : public MCFragment {
/// Size - The size of this fragment.
uint64_t Size;
/// Alignment - The alignment for this fragment.
unsigned Alignment;
public:
MCZeroFillFragment(uint64_t _Size, unsigned _Alignment, MCSectionData *SD = 0)
: MCFragment(FT_ZeroFill, SD),
Size(_Size), Alignment(_Alignment) {}
/// @name Accessors
/// @{
uint64_t getMaxFileSize() const {
// FIXME: This also doesn't make much sense, this method is misnamed.
return ~UINT64_C(0);
}
uint64_t getSize() const { return Size; }
unsigned getAlignment() const { return Alignment; }
/// @}
static bool classof(const MCFragment *F) {
return F->getKind() == MCFragment::FT_ZeroFill;
}
static bool classof(const MCZeroFillFragment *) { return true; }
};
// FIXME: Should this be a separate class, or just merged into MCSection? Since
// we anticipate the fast path being through an MCAssembler, the only reason to
// keep it out is for API abstraction.

View File

@ -28,6 +28,15 @@ STATISTIC(EmittedFragments, "Number of emitted assembler fragments");
static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
MachObjectWriter &MOW);
/// isVirtualSection - Check if this is a section which does not actually exist
/// in the object file.
static bool isVirtualSection(const MCSection &Section) {
// FIXME: Lame.
const MCSectionMachO &SMO = static_cast<const MCSectionMachO&>(Section);
unsigned Type = SMO.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE;
return (Type == MCSectionMachO::S_ZEROFILL);
}
class MachObjectWriter {
// See <mach-o/loader.h>.
enum {
@ -229,6 +238,12 @@ public:
void WriteSection32(const MCSectionData &SD, uint64_t FileOffset,
uint64_t RelocationsStart, unsigned NumRelocations) {
// The offset is unused for virtual sections.
if (isVirtualSection(SD.getSection())) {
assert(SD.getFileSize() == 0 && "Invalid file size!");
FileOffset = 0;
}
// struct section (68 bytes)
uint64_t Start = OS.tell();
@ -692,6 +707,9 @@ public:
VMSize = std::max(VMSize, SD.getAddress() + SD.getSize());
if (isVirtualSection(SD.getSection()))
continue;
SectionDataSize = std::max(SectionDataSize,
SD.getAddress() + SD.getSize());
SectionDataFileSize = std::max(SectionDataFileSize,
@ -922,7 +940,7 @@ void MCAssembler::LayoutSection(MCSectionData &SD) {
case MCFragment::FT_Align: {
MCAlignFragment &AF = cast<MCAlignFragment>(F);
uint64_t Size = RoundUpToAlignment(Address, AF.getAlignment()) - Address;
uint64_t Size = OffsetToAlignment(Address, AF.getAlignment());
if (Size > AF.getMaxBytesToEmit())
AF.setFileSize(0);
else
@ -968,6 +986,19 @@ void MCAssembler::LayoutSection(MCSectionData &SD) {
F.setFileSize(OrgOffset - Offset);
break;
}
case MCFragment::FT_ZeroFill: {
MCZeroFillFragment &ZFF = cast<MCZeroFillFragment>(F);
// Align the fragment offset; it is safe to adjust the offset freely since
// this is only in virtual sections.
uint64_t Aligned = RoundUpToAlignment(Address, ZFF.getAlignment());
F.setOffset(Aligned - SD.getAddress());
// FIXME: This is misnamed.
F.setFileSize(ZFF.getSize());
break;
}
}
Address += F.getFileSize();
@ -975,7 +1006,10 @@ void MCAssembler::LayoutSection(MCSectionData &SD) {
// Set the section sizes.
SD.setSize(Address - SD.getAddress());
SD.setFileSize(Address - SD.getAddress());
if (isVirtualSection(SD.getSection()))
SD.setFileSize(0);
else
SD.setFileSize(Address - SD.getAddress());
}
/// WriteFileData - Write the \arg F data to the output file.
@ -1055,6 +1089,11 @@ static void WriteFileData(raw_ostream &OS, const MCFragment &F,
break;
}
case MCFragment::FT_ZeroFill: {
assert(0 && "Invalid zero fill fragment in concrete section!");
break;
}
}
assert(OS.tell() - Start == F.getFileSize());
@ -1063,6 +1102,12 @@ static void WriteFileData(raw_ostream &OS, const MCFragment &F,
/// WriteFileData - Write the \arg SD data to the output file.
static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
MachObjectWriter &MOW) {
// Ignore virtual sections.
if (isVirtualSection(SD.getSection())) {
assert(SD.getFileSize() == 0);
return;
}
uint64_t Start = OS.tell();
(void) Start;
@ -1078,12 +1123,16 @@ static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
}
void MCAssembler::Finish() {
// Layout the sections and fragments.
// Layout the concrete sections and fragments.
uint64_t Address = 0;
MCSectionData *Prev = 0;
for (iterator it = begin(), ie = end(); it != ie; ++it) {
MCSectionData &SD = *it;
// Skip virtual sections.
if (isVirtualSection(SD.getSection()))
continue;
// Align this section if necessary by adding padding bytes to the previous
// section.
if (uint64_t Pad = OffsetToAlignment(Address, it->getAlignment())) {
@ -1100,6 +1149,18 @@ void MCAssembler::Finish() {
Prev = &SD;
}
// Layout the virtual sections.
for (iterator it = begin(), ie = end(); it != ie; ++it) {
MCSectionData &SD = *it;
if (!isVirtualSection(SD.getSection()))
continue;
SD.setAddress(Address);
LayoutSection(SD);
Address += SD.getSize();
}
// Write the object file.
MachObjectWriter MOW(OS);
MOW.WriteObject(*this);

View File

@ -278,7 +278,27 @@ void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
void MCMachOStreamer::EmitZerofill(const MCSection *Section, MCSymbol *Symbol,
unsigned Size, unsigned Pow2Alignment) {
llvm_unreachable("FIXME: Not yet implemented!");
unsigned ByteAlignment = 1 << Pow2Alignment;
MCSectionData &SectData = getSectionData(*Section);
// The symbol may not be present, which only creates the section.
if (!Symbol)
return;
// FIXME: Assert that this section has the zerofill type.
assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
MCSymbolData &SD = getSymbolData(*Symbol);
MCFragment *F = new MCZeroFillFragment(Size, 1 << Pow2Alignment, &SectData);
SD.setFragment(F);
Symbol->setSection(*Section);
// Update the maximum alignment on the zero fill section if necessary.
if (ByteAlignment > SectData.getAlignment())
SectData.setAlignment(ByteAlignment);
}
void MCMachOStreamer::EmitBytes(const StringRef &Data) {

View File

@ -0,0 +1,136 @@
// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump | FileCheck %s
// Note, this test intentionally mismatches Darwin 'as', which loses the
// following global marker.
//
// FIXME: We should probably warn about our interpretation of this.
.globl sym_lcomm_ext_A
.lcomm sym_lcomm_ext_A, 4
.lcomm sym_lcomm_ext_B, 4
.globl sym_lcomm_ext_B
.globl sym_zfill_ext_A
.zerofill __DATA, __bss, sym_zfill_ext_A, 4
.zerofill __DATA, __bss, sym_zfill_ext_B, 4
.globl sym_zfill_ext_B
// CHECK: ('cputype', 7)
// CHECK: ('cpusubtype', 3)
// CHECK: ('filetype', 1)
// CHECK: ('num_load_commands', 1)
// CHECK: ('load_commands_size', 296)
// CHECK: ('flag', 0)
// CHECK: ('load_commands', [
// CHECK: # Load Command 0
// CHECK: (('command', 1)
// CHECK: ('size', 192)
// 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', 16)
// CHECK: ('file_offset', 324)
// CHECK: ('file_size', 0)
// CHECK: ('maxprot', 7)
// CHECK: ('initprot', 7)
// CHECK: ('num_sections', 2)
// 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', 0)
// CHECK: ('offset', 324)
// CHECK: ('alignment', 0)
// CHECK: ('reloc_offset', 0)
// CHECK: ('num_reloc', 0)
// CHECK: ('flags', 0x80000000)
// CHECK: ('reserved1', 0)
// CHECK: ('reserved2', 0)
// CHECK: ),
// CHECK: ('_relocations', [
// CHECK: ])
// CHECK: # Section 1
// CHECK: (('section_name', '__bss\x00\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', 0)
// CHECK: ('size', 16)
// CHECK: ('offset', 0)
// CHECK: ('alignment', 0)
// CHECK: ('reloc_offset', 0)
// CHECK: ('num_reloc', 0)
// CHECK: ('flags', 0x1)
// CHECK: ('reserved1', 0)
// CHECK: ('reserved2', 0)
// CHECK: ),
// CHECK: ('_relocations', [
// CHECK: ])
// CHECK: ])
// CHECK: ),
// CHECK: # Load Command 1
// CHECK: (('command', 2)
// CHECK: ('size', 24)
// CHECK: ('symoff', 324)
// CHECK: ('nsyms', 4)
// CHECK: ('stroff', 372)
// CHECK: ('strsize', 68)
// CHECK: ('_string_data', '\x00sym_lcomm_ext_A\x00sym_lcomm_ext_B\x00sym_zfill_ext_A\x00sym_zfill_ext_B\x00\x00\x00\x00')
// CHECK: ('_symbols', [
// CHECK: # Symbol 0
// CHECK: (('n_strx', 1)
// CHECK: ('n_type', 0xf)
// CHECK: ('n_sect', 2)
// CHECK: ('n_desc', 0)
// CHECK: ('n_value', 0)
// CHECK: ('_string', 'sym_lcomm_ext_A')
// CHECK: ),
// CHECK: # Symbol 1
// CHECK: (('n_strx', 17)
// CHECK: ('n_type', 0xf)
// CHECK: ('n_sect', 2)
// CHECK: ('n_desc', 0)
// CHECK: ('n_value', 4)
// CHECK: ('_string', 'sym_lcomm_ext_B')
// CHECK: ),
// CHECK: # Symbol 2
// CHECK: (('n_strx', 33)
// CHECK: ('n_type', 0xf)
// CHECK: ('n_sect', 2)
// CHECK: ('n_desc', 0)
// CHECK: ('n_value', 8)
// CHECK: ('_string', 'sym_zfill_ext_A')
// CHECK: ),
// CHECK: # Symbol 3
// CHECK: (('n_strx', 49)
// CHECK: ('n_type', 0xf)
// CHECK: ('n_sect', 2)
// CHECK: ('n_desc', 0)
// CHECK: ('n_value', 12)
// CHECK: ('_string', 'sym_zfill_ext_B')
// CHECK: ),
// CHECK: ])
// CHECK: ),
// CHECK: # Load Command 2
// CHECK: (('command', 11)
// CHECK: ('size', 80)
// CHECK: ('ilocalsym', 0)
// CHECK: ('nlocalsym', 0)
// CHECK: ('iextdefsym', 0)
// CHECK: ('nextdefsym', 4)
// CHECK: ('iundefsym', 4)
// 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: ])

121
test/MC/MachO/zerofill-1.s Normal file
View File

@ -0,0 +1,121 @@
// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump --dump-section-data | FileCheck %s
.text
.byte 0 // Align to 2**3 bytes, not 2**1
.zerofill __DATA, __common, zfill, 2, 1
.data
.align 3
// 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', 10)
// CHECK: ('file_offset', 392)
// CHECK: ('file_size', 8)
// 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: ('_relocations', [
// CHECK: ])
// CHECK: # Section 1
// CHECK: (('section_name', '__common\x00\x00\x00\x00\x00\x00\x00\x00')
// CHECK: ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
// CHECK: ('address', 8)
// CHECK: ('size', 2)
// CHECK: ('offset', 0)
// CHECK: ('alignment', 1)
// CHECK: ('reloc_offset', 0)
// CHECK: ('num_reloc', 0)
// CHECK: ('flags', 0x1)
// CHECK: ('reserved1', 0)
// CHECK: ('reserved2', 0)
// CHECK: ),
// CHECK: ('_relocations', [
// CHECK: ])
// CHECK: # Section 2
// 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', 8)
// CHECK: ('size', 0)
// CHECK: ('offset', 400)
// CHECK: ('alignment', 3)
// CHECK: ('reloc_offset', 0)
// CHECK: ('num_reloc', 0)
// CHECK: ('flags', 0x0)
// CHECK: ('reserved1', 0)
// CHECK: ('reserved2', 0)
// CHECK: ),
// CHECK: ('_relocations', [
// CHECK: ])
// CHECK: ])
// CHECK: ),
// CHECK: # Load Command 1
// CHECK: (('command', 2)
// CHECK: ('size', 24)
// CHECK: ('symoff', 400)
// CHECK: ('nsyms', 1)
// CHECK: ('stroff', 412)
// CHECK: ('strsize', 8)
// CHECK: ('_string_data', '\x00zfill\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', 8)
// CHECK: ('_string', 'zfill')
// 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: ])

103
test/MC/MachO/zerofill-2.s Normal file
View File

@ -0,0 +1,103 @@
// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump --dump-section-data | FileCheck %s
.byte 0
// This file has size 2, the tail padding doesn't count.
.zerofill __DATA, __bss, sym_a, 1
// CHECK: ('cputype', 7)
// CHECK: ('cpusubtype', 3)
// CHECK: ('filetype', 1)
// CHECK: ('num_load_commands', 1)
// CHECK: ('load_commands_size', 296)
// CHECK: ('flag', 0)
// CHECK: ('load_commands', [
// CHECK: # Load Command 0
// CHECK: (('command', 1)
// CHECK: ('size', 192)
// 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', 2)
// CHECK: ('file_offset', 324)
// CHECK: ('file_size', 1)
// CHECK: ('maxprot', 7)
// CHECK: ('initprot', 7)
// CHECK: ('num_sections', 2)
// 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', 324)
// CHECK: ('alignment', 0)
// CHECK: ('reloc_offset', 0)
// CHECK: ('num_reloc', 0)
// CHECK: ('flags', 0x80000000)
// CHECK: ('reserved1', 0)
// CHECK: ('reserved2', 0)
// CHECK: ),
// CHECK: ('_relocations', [
// CHECK: ])
// CHECK: # Section 1
// CHECK: (('section_name', '__bss\x00\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', 1)
// CHECK: ('size', 1)
// CHECK: ('offset', 0)
// CHECK: ('alignment', 0)
// CHECK: ('reloc_offset', 0)
// CHECK: ('num_reloc', 0)
// CHECK: ('flags', 0x1)
// CHECK: ('reserved1', 0)
// CHECK: ('reserved2', 0)
// CHECK: ),
// CHECK: ('_relocations', [
// CHECK: ])
// CHECK: ])
// CHECK: ),
// CHECK: # Load Command 1
// CHECK: (('command', 2)
// CHECK: ('size', 24)
// CHECK: ('symoff', 328)
// CHECK: ('nsyms', 1)
// CHECK: ('stroff', 340)
// CHECK: ('strsize', 8)
// CHECK: ('_string_data', '\x00sym_a\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', 1)
// CHECK: ('_string', 'sym_a')
// 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: ])

141
test/MC/MachO/zerofill-3.s Normal file
View File

@ -0,0 +1,141 @@
// RUN: llvm-mc -triple i386-apple-darwin9 %s -filetype=obj -o - | macho-dump --dump-section-data | FileCheck %s
// FIXME: We don't get the order right currently, the assembler first
// orders the symbols, then assigns addresses. :(
.if 0
.lcomm sym_lcomm_B, 4
.lcomm sym_lcomm_C, 4, 4
.lcomm sym_lcomm_A, 4, 3
.lcomm sym_lcomm_D, 4
.globl sym_lcomm_D
.globl sym_lcomm_C
.else
.lcomm sym_lcomm_C, 4, 4
.lcomm sym_lcomm_D, 4
.globl sym_lcomm_D
.globl sym_lcomm_C
.lcomm sym_lcomm_A, 4, 3
.lcomm sym_lcomm_B, 4
.endif
// CHECK: ('cputype', 7)
// CHECK: ('cpusubtype', 3)
// CHECK: ('filetype', 1)
// CHECK: ('num_load_commands', 1)
// CHECK: ('load_commands_size', 296)
// CHECK: ('flag', 0)
// CHECK: ('load_commands', [
// CHECK: # Load Command 0
// CHECK: (('command', 1)
// CHECK: ('size', 192)
// 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', 16)
// CHECK: ('file_offset', 324)
// CHECK: ('file_size', 0)
// CHECK: ('maxprot', 7)
// CHECK: ('initprot', 7)
// CHECK: ('num_sections', 2)
// 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', 0)
// CHECK: ('offset', 324)
// CHECK: ('alignment', 0)
// CHECK: ('reloc_offset', 0)
// CHECK: ('num_reloc', 0)
// CHECK: ('flags', 0x80000000)
// CHECK: ('reserved1', 0)
// CHECK: ('reserved2', 0)
// CHECK: ),
// CHECK: ('_relocations', [
// CHECK: ])
// CHECK: # Section 1
// CHECK: (('section_name', '__bss\x00\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', 0)
// CHECK: ('size', 16)
// CHECK: ('offset', 0)
// CHECK: ('alignment', 4)
// CHECK: ('reloc_offset', 0)
// CHECK: ('num_reloc', 0)
// CHECK: ('flags', 0x1)
// CHECK: ('reserved1', 0)
// CHECK: ('reserved2', 0)
// CHECK: ),
// CHECK: ('_relocations', [
// CHECK: ])
// CHECK: ])
// CHECK: ),
// CHECK: # Load Command 1
// CHECK: (('command', 2)
// CHECK: ('size', 24)
// CHECK: ('symoff', 324)
// CHECK: ('nsyms', 4)
// CHECK: ('stroff', 372)
// CHECK: ('strsize', 52)
// CHECK: ('_string_data', '\x00sym_lcomm_C\x00sym_lcomm_D\x00sym_lcomm_A\x00sym_lcomm_B\x00\x00\x00\x00')
// CHECK: ('_symbols', [
// CHECK: # Symbol 0
// CHECK: (('n_strx', 25)
// CHECK: ('n_type', 0xe)
// CHECK: ('n_sect', 2)
// CHECK: ('n_desc', 0)
// CHECK: ('n_value', 8)
// CHECK: ('_string', 'sym_lcomm_A')
// CHECK: ),
// CHECK: # Symbol 1
// CHECK: (('n_strx', 37)
// CHECK: ('n_type', 0xe)
// CHECK: ('n_sect', 2)
// CHECK: ('n_desc', 0)
// CHECK: ('n_value', 12)
// CHECK: ('_string', 'sym_lcomm_B')
// CHECK: ),
// CHECK: # Symbol 2
// CHECK: (('n_strx', 1)
// CHECK: ('n_type', 0xf)
// CHECK: ('n_sect', 2)
// CHECK: ('n_desc', 0)
// CHECK: ('n_value', 0)
// CHECK: ('_string', 'sym_lcomm_C')
// CHECK: ),
// CHECK: # Symbol 3
// CHECK: (('n_strx', 13)
// CHECK: ('n_type', 0xf)
// CHECK: ('n_sect', 2)
// CHECK: ('n_desc', 0)
// CHECK: ('n_value', 4)
// CHECK: ('_string', 'sym_lcomm_D')
// CHECK: ),
// CHECK: ])
// CHECK: ),
// CHECK: # Load Command 2
// CHECK: (('command', 11)
// CHECK: ('size', 80)
// CHECK: ('ilocalsym', 0)
// CHECK: ('nlocalsym', 2)
// CHECK: ('iextdefsym', 2)
// CHECK: ('nextdefsym', 2)
// CHECK: ('iundefsym', 4)
// 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: ])