aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/MC/MCAssembler.h137
-rw-r--r--lib/MC/MCAssembler.cpp228
-rw-r--r--lib/MC/MCMachOStreamer.cpp170
-rw-r--r--test/MC/MachO/dg.exp3
-rw-r--r--test/MC/MachO/sections.s532
-rwxr-xr-xtest/Scripts/macho-dump159
-rw-r--r--tools/llvm-mc/llvm-mc.cpp30
7 files changed, 1255 insertions, 4 deletions
diff --git a/include/llvm/MC/MCAssembler.h b/include/llvm/MC/MCAssembler.h
new file mode 100644
index 0000000000..a714e4503d
--- /dev/null
+++ b/include/llvm/MC/MCAssembler.h
@@ -0,0 +1,137 @@
+//===- MCAssembler.h - Object File Generation -------------------*- C++ -*-===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_MC_MCASSEMBLER_H
+#define LLVM_MC_MCASSEMBLER_H
+
+#include "llvm/ADT/ilist.h"
+#include "llvm/ADT/ilist_node.h"
+
+namespace llvm {
+class raw_ostream;
+class MCAssembler;
+class MCSection;
+class MCSectionData;
+
+class MCFragment : public ilist_node<MCFragment> {
+ MCFragment(const MCFragment&); // DO NOT IMPLEMENT
+ void operator=(const MCFragment&); // DO NOT IMPLEMENT
+
+public:
+ MCFragment(MCSectionData *SD = 0);
+};
+
+// 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.
+class MCSectionData : public ilist_node<MCSectionData> {
+ MCSectionData(const MCSectionData&); // DO NOT IMPLEMENT
+ void operator=(const MCSectionData&); // DO NOT IMPLEMENT
+
+public:
+ typedef iplist<MCFragment> FragmentListType;
+
+private:
+ iplist<MCFragment> Fragments;
+ const MCSection &Section;
+
+ /// Alignment - The maximum alignment seen in this section.
+ unsigned Alignment;
+
+ /// @name Assembler Backend Data
+ /// @{
+ //
+ // FIXME: This could all be kept private to the assembler implementation.
+
+ /// FileOffset - The offset of this section in the object file.
+ uint64_t FileOffset;
+
+ /// FileSize - The size of this section in the object file.
+ uint64_t FileSize;
+
+ /// @}
+
+public:
+ // Only for use as sentinel.
+ MCSectionData();
+ MCSectionData(const MCSection &Section, MCAssembler *A = 0);
+
+ const FragmentListType &getFragmentList() const { return Fragments; }
+ FragmentListType &getFragmentList() { return Fragments; }
+
+ const MCSection &getSection() const { return Section; }
+
+ unsigned getAlignment() const { return Alignment; }
+ void setAlignment(unsigned Value) { Alignment = Value; }
+
+ /// @name Assembler Backend Support
+ /// @{
+ //
+ // FIXME: This could all be kept private to the assembler implementation.
+
+ unsigned getFileSize() const { return FileSize; }
+
+ uint64_t getFileOffset() const { return FileOffset; }
+ void setFileOffset(uint64_t Value) { FileOffset = Value; }
+
+ void WriteFileData(raw_ostream &OS) const;
+
+ /// @}
+};
+
+class MCAssembler {
+public:
+ typedef iplist<MCSectionData> SectionDataListType;
+
+ typedef SectionDataListType::const_iterator const_iterator;
+ typedef SectionDataListType::iterator iterator;
+
+private:
+ MCAssembler(const MCAssembler&); // DO NOT IMPLEMENT
+ void operator=(const MCAssembler&); // DO NOT IMPLEMENT
+
+ raw_ostream &OS;
+
+ iplist<MCSectionData> Sections;
+
+public:
+ /// Construct a new assembler instance.
+ ///
+ /// \arg OS - The stream to output to.
+ //
+ // FIXME: How are we going to parameterize this? Two obvious options are stay
+ // concrete and require clients to pass in a target like object. The other
+ // option is to make this abstract, and have targets provide concrete
+ // implementations as we do with AsmParser.
+ MCAssembler(raw_ostream &OS);
+ ~MCAssembler();
+
+ /// Finish - Do final processing and write the object to the output stream.
+ void Finish();
+
+ /// @name Section List Access
+ /// @{
+
+ const SectionDataListType &getSectionList() const { return Sections; }
+ SectionDataListType &getSectionList() { return Sections; }
+
+ iterator begin() { return Sections.begin(); }
+ const_iterator begin() const { return Sections.begin(); }
+
+ iterator end() { return Sections.end(); }
+ const_iterator end() const { return Sections.end(); }
+
+ size_t size() const { return Sections.size(); }
+
+ /// @}
+};
+
+} // end namespace llvm
+
+#endif
diff --git a/lib/MC/MCAssembler.cpp b/lib/MC/MCAssembler.cpp
new file mode 100644
index 0000000000..7a1e935af4
--- /dev/null
+++ b/lib/MC/MCAssembler.cpp
@@ -0,0 +1,228 @@
+//===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCSectionMachO.h"
+#include "llvm/Support/DataTypes.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/Target/TargetMachOWriterInfo.h"
+
+using namespace llvm;
+
+namespace {
+
+class MachObjectWriter {
+ // See <mach-o/loader.h>.
+ enum {
+ Header_Magic32 = 0xFEEDFACE,
+ Header_Magic64 = 0xFEEDFACF
+ };
+
+ static const unsigned Header32Size = 28;
+ static const unsigned Header64Size = 32;
+ static const unsigned SegmentLoadCommand32Size = 56;
+ static const unsigned Section32Size = 68;
+
+ enum HeaderFileType {
+ HFT_Object = 0x1
+ };
+
+ enum LoadCommandType {
+ LCT_Segment = 0x1
+ };
+
+ raw_ostream &OS;
+ bool IsLSB;
+
+public:
+ MachObjectWriter(raw_ostream &_OS, bool _IsLSB = true)
+ : OS(_OS), IsLSB(_IsLSB) {
+ }
+
+ /// @name Helper Methods
+ /// @{
+
+ void Write32(uint32_t Value) {
+ if (IsLSB) {
+ OS << char(Value >> 0);
+ OS << char(Value >> 8);
+ OS << char(Value >> 16);
+ OS << char(Value >> 24);
+ } else {
+ OS << char(Value >> 24);
+ OS << char(Value >> 16);
+ OS << char(Value >> 8);
+ OS << char(Value >> 0);
+ }
+ }
+
+ void WriteZeros(unsigned N) {
+ const char Zeros[16] = { 0 };
+
+ for (unsigned i = 0, e = N / 16; i != e; ++i)
+ OS << StringRef(Zeros, 16);
+
+ OS << StringRef(Zeros, N % 16);
+ }
+
+ void WriteString(const StringRef &Str, unsigned ZeroFillSize = 0) {
+ OS << Str;
+ if (ZeroFillSize)
+ WriteZeros(ZeroFillSize - Str.size());
+ }
+
+ /// @}
+
+ static unsigned getPrologSize32(unsigned NumSections) {
+ return Header32Size + SegmentLoadCommand32Size +
+ NumSections * Section32Size;
+ }
+
+ void WriteHeader32(unsigned NumSections) {
+ // struct mach_header (28 bytes)
+
+ uint64_t Start = OS.tell();
+ (void) Start;
+
+ Write32(Header_Magic32);
+
+ // FIXME: Support cputype.
+ Write32(TargetMachOWriterInfo::HDR_CPU_TYPE_I386);
+
+ // FIXME: Support cpusubtype.
+ Write32(TargetMachOWriterInfo::HDR_CPU_SUBTYPE_I386_ALL);
+
+ Write32(HFT_Object);
+
+ // Object files have a single load command, the segment.
+ Write32(1);
+ Write32(SegmentLoadCommand32Size + NumSections * Section32Size);
+ Write32(0); // Flags
+
+ assert(OS.tell() - Start == Header32Size);
+ }
+
+ void WriteLoadCommandHeader(uint32_t Cmd, uint32_t CmdSize) {
+ assert((CmdSize & 0x3) == 0 && "Invalid size!");
+
+ Write32(Cmd);
+ Write32(CmdSize);
+ }
+
+ void WriteSegmentLoadCommand32(unsigned NumSections) {
+ // struct segment_command (56 bytes)
+
+ uint64_t Start = OS.tell();
+ (void) Start;
+
+ Write32(LCT_Segment);
+ Write32(SegmentLoadCommand32Size + NumSections * Section32Size);
+
+ WriteString("", 16);
+ Write32(0); // vmaddr
+ Write32(0); // vmsize
+ Write32(Header32Size + SegmentLoadCommand32Size +
+ NumSections * Section32Size); // file offset
+ Write32(0); // file size
+ Write32(0x7); // maxprot
+ Write32(0x7); // initprot
+ Write32(NumSections);
+ Write32(0); // flags
+
+ assert(OS.tell() - Start == SegmentLoadCommand32Size);
+ }
+
+ void WriteSection32(const MCSectionData &SD) {
+ // struct section (68 bytes)
+
+ uint64_t Start = OS.tell();
+ (void) Start;
+
+ // FIXME: cast<> support!
+ const MCSectionMachO &Section =
+ static_cast<const MCSectionMachO&>(SD.getSection());
+ WriteString(Section.getSectionName(), 16);
+ WriteString(Section.getSegmentName(), 16);
+ Write32(0); // address
+ Write32(SD.getFileSize()); // size
+ Write32(SD.getFileOffset());
+
+ assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!");
+ Write32(Log2_32(SD.getAlignment()));
+ Write32(0); // file offset of relocation entries
+ Write32(0); // number of relocation entrions
+ Write32(Section.getTypeAndAttributes());
+ Write32(0); // reserved1
+ Write32(Section.getStubSize()); // reserved2
+
+ assert(OS.tell() - Start == Section32Size);
+ }
+};
+
+}
+
+/* *** */
+
+MCFragment::MCFragment(MCSectionData *SD)
+{
+ if (SD)
+ SD->getFragmentList().push_back(this);
+}
+
+/* *** */
+
+MCSectionData::MCSectionData() : Section(*(MCSection*)0) {}
+
+MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
+ : Section(_Section),
+ Alignment(1),
+ FileOffset(0),
+ FileSize(0)
+{
+ if (A)
+ A->getSectionList().push_back(this);
+}
+
+void MCSectionData::WriteFileData(raw_ostream &OS) const {
+
+}
+
+/* *** */
+
+MCAssembler::MCAssembler(raw_ostream &_OS) : OS(_OS) {}
+
+MCAssembler::~MCAssembler() {
+}
+
+void MCAssembler::Finish() {
+ unsigned NumSections = Sections.size();
+
+ // Compute the file offsets so we can write in a single pass.
+ uint64_t Offset = MachObjectWriter::getPrologSize32(NumSections);
+ for (iterator it = begin(), ie = end(); it != ie; ++it) {
+ it->setFileOffset(Offset);
+ Offset += it->getFileSize();
+ }
+
+ MachObjectWriter MOW(OS);
+
+ // Write the prolog, starting with the header and load command...
+ MOW.WriteHeader32(NumSections);
+ MOW.WriteSegmentLoadCommand32(NumSections);
+
+ // ... and then the section headers.
+ for (iterator it = begin(), ie = end(); it != ie; ++it)
+ MOW.WriteSection32(*it);
+
+ // Finally, write the section data.
+ for (iterator it = begin(), ie = end(); it != ie; ++it)
+ it->WriteFileData(OS);
+
+ OS.flush();
+}
diff --git a/lib/MC/MCMachOStreamer.cpp b/lib/MC/MCMachOStreamer.cpp
new file mode 100644
index 0000000000..f34fcd9a61
--- /dev/null
+++ b/lib/MC/MCMachOStreamer.cpp
@@ -0,0 +1,170 @@
+//===- lib/MC/MCMachOStreamer.cpp - Mach-O Object Output ------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/MC/MCStreamer.h"
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/MC/MCAssembler.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCSection.h"
+#include "llvm/MC/MCSymbol.h"
+#include "llvm/MC/MCValue.h"
+#include "llvm/Support/ErrorHandling.h"
+using namespace llvm;
+
+namespace {
+
+class MCMachOStreamer : public MCStreamer {
+ MCAssembler Assembler;
+
+ MCSectionData *CurSectionData;
+
+ DenseMap<const MCSection*, MCSectionData*> SectionMap;
+
+public:
+ MCMachOStreamer(MCContext &Context, raw_ostream &_OS)
+ : MCStreamer(Context), Assembler(_OS), CurSectionData(0) {}
+ ~MCMachOStreamer() {}
+
+ /// @name MCStreamer Interface
+ /// @{
+
+ virtual void SwitchSection(const MCSection *Section);
+
+ virtual void EmitLabel(MCSymbol *Symbol);
+
+ virtual void EmitAssemblerFlag(AssemblerFlag Flag);
+
+ virtual void EmitAssignment(MCSymbol *Symbol, const MCValue &Value,
+ bool MakeAbsolute = false);
+
+ virtual void EmitSymbolAttribute(MCSymbol *Symbol, SymbolAttr Attribute);
+
+ virtual void EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue);
+
+ virtual void EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value);
+
+ virtual void EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
+ unsigned Pow2Alignment, bool IsLocal);
+
+ virtual void EmitZerofill(MCSection *Section, MCSymbol *Symbol = NULL,
+ unsigned Size = 0, unsigned Pow2Alignment = 0);
+
+ virtual void EmitBytes(const StringRef &Data);
+
+ virtual void EmitValue(const MCValue &Value, unsigned Size);
+
+ virtual void EmitValueToAlignment(unsigned ByteAlignment, int64_t Value = 0,
+ unsigned ValueSize = 1,
+ unsigned MaxBytesToEmit = 0);
+
+ virtual void EmitValueToOffset(const MCValue &Offset,
+ unsigned char Value = 0);
+
+ virtual void EmitInstruction(const MCInst &Inst);
+
+ virtual void Finish();
+
+ /// @}
+};
+
+} // end anonymous namespace.
+
+void MCMachOStreamer::SwitchSection(const MCSection *Section) {
+ assert(Section && "Cannot switch to a null section!");
+
+ if (Section != CurSection) {
+ CurSection = Section;
+ MCSectionData *&Entry = SectionMap[Section];
+
+ if (!Entry)
+ Entry = new MCSectionData(*Section, &Assembler);
+
+ CurSectionData = Entry;
+ }
+}
+
+void MCMachOStreamer::EmitLabel(MCSymbol *Symbol) {
+ assert(Symbol->getSection() == 0 && "Cannot emit a symbol twice!");
+ assert(CurSection && "Cannot emit before setting section!");
+ assert(!getContext().GetSymbolValue(Symbol) &&
+ "Cannot emit symbol which was directly assigned to!");
+
+ llvm_unreachable("FIXME: Not yet implemented!");
+
+ Symbol->setSection(CurSection);
+ Symbol->setExternal(false);
+}
+
+void MCMachOStreamer::EmitAssemblerFlag(AssemblerFlag Flag) {
+ llvm_unreachable("FIXME: Not yet implemented!");
+}
+
+void MCMachOStreamer::EmitAssignment(MCSymbol *Symbol,
+ const MCValue &Value,
+ bool MakeAbsolute) {
+ assert(!Symbol->getSection() && "Cannot assign to a label!");
+
+ llvm_unreachable("FIXME: Not yet implemented!");
+}
+
+void MCMachOStreamer::EmitSymbolAttribute(MCSymbol *Symbol,
+ SymbolAttr Attribute) {
+ llvm_unreachable("FIXME: Not yet implemented!");
+}
+
+void MCMachOStreamer::EmitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
+ llvm_unreachable("FIXME: Not yet implemented!");
+}
+
+void MCMachOStreamer::EmitLocalSymbol(MCSymbol *Symbol, const MCValue &Value) {
+ llvm_unreachable("FIXME: Not yet implemented!");
+}
+
+void MCMachOStreamer::EmitCommonSymbol(MCSymbol *Symbol, unsigned Size,
+ unsigned Pow2Alignment,
+ bool IsLocal) {
+ llvm_unreachable("FIXME: Not yet implemented!");
+}
+
+void MCMachOStreamer::EmitZerofill(MCSection *Section, MCSymbol *Symbol,
+ unsigned Size, unsigned Pow2Alignment) {
+ llvm_unreachable("FIXME: Not yet implemented!");
+}
+
+void MCMachOStreamer::EmitBytes(const StringRef &Data) {
+ llvm_unreachable("FIXME: Not yet implemented!");
+}
+
+void MCMachOStreamer::EmitValue(const MCValue &Value, unsigned Size) {
+ llvm_unreachable("FIXME: Not yet implemented!");
+}
+
+void MCMachOStreamer::EmitValueToAlignment(unsigned ByteAlignment,
+ int64_t Value, unsigned ValueSize,
+ unsigned MaxBytesToEmit) {
+ llvm_unreachable("FIXME: Not yet implemented!");
+}
+
+void MCMachOStreamer::EmitValueToOffset(const MCValue &Offset,
+ unsigned char Value) {
+ llvm_unreachable("FIXME: Not yet implemented!");
+}
+
+void MCMachOStreamer::EmitInstruction(const MCInst &Inst) {
+ llvm_unreachable("FIXME: Not yet implemented!");
+}
+
+void MCMachOStreamer::Finish() {
+ Assembler.Finish();
+}
+
+MCStreamer *llvm::createMachOStreamer(MCContext &Context, raw_ostream &OS) {
+ return new MCMachOStreamer(Context, OS);
+}
diff --git a/test/MC/MachO/dg.exp b/test/MC/MachO/dg.exp
new file mode 100644
index 0000000000..ebd84187f5
--- /dev/null
+++ b/test/MC/MachO/dg.exp
@@ -0,0 +1,3 @@
+load_lib llvm.exp
+
+RunLLVMTests [lsort [glob -nocomplain $srcdir/$subdir/*.{s}]]
diff --git a/test/MC/MachO/sections.s b/test/MC/MachO/sections.s
new file mode 100644
index 0000000000..7b7f9a1e43
--- /dev/null
+++ b/test/MC/MachO/sections.s
@@ -0,0 +1,532 @@
+// RUN: llvm-mc %s -filetype=obj -o - | macho-dump | FileCheck %s
+
+ .const
+ .static_const
+ .cstring
+ .literal4
+ .literal8
+ .literal16
+ .constructor
+ .destructor
+ .symbol_stub
+ .picsymbol_stub
+ .data
+ .static_data
+ .non_lazy_symbol_pointer
+ .lazy_symbol_pointer
+ .dyld
+ .mod_init_func
+ .mod_term_func
+ .const_data
+ .objc_class
+ .objc_meta_class
+ .objc_cat_cls_meth
+ .objc_cat_inst_meth
+ .objc_protocol
+ .objc_string_object
+ .objc_cls_meth
+ .objc_inst_meth
+ .objc_cls_refs
+ .objc_message_refs
+ .objc_symbols
+ .objc_category
+ .objc_class_vars
+ .objc_instance_vars
+ .objc_module_info
+
+// FIXME: These are aliases for __TEXT, __cstring which we don't properly unique
+// yet.
+// .objc_class_names
+// .objc_meth_var_types
+// .objc_meth_var_names
+
+ .objc_selector_strs
+
+
+// CHECK: ('cputype', 7)
+// CHECK: ('cpusubtype', 3)
+// CHECK: ('filetype', 1)
+// CHECK: ('num_load_commands', 1)
+// CHECK: ('load_commands_size', 2436)
+// CHECK: ('flag', 0)
+// CHECK: ('load_commands', [
+// CHECK: # Load Command 0
+// CHECK: (('command', 1)
+// CHECK: ('size', 2436)
+// 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', 0)
+// CHECK: ('file_offset', 2464)
+// CHECK: ('file_size', 0)
+// CHECK: ('maxprot', 7)
+// CHECK: ('initprot', 7)
+// CHECK: ('num_sections', 35)
+// 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', 2464)
+// 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', '__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', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x0)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 2
+// CHECK: (('section_name', '__static_const\x00\x00')
+// CHECK: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x0)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 3
+// CHECK: (('section_name', '__cstring\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', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x2)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 4
+// CHECK: (('section_name', '__literal4\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', 2464)
+ // FIXME: We aren't setting alignment correctly yet.
+// CHECX: ('alignment', 2)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x3)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 5
+// CHECK: (('section_name', '__literal8\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', 2464)
+ // FIXME: We aren't setting alignment correctly yet.
+// CHECX: ('alignment', 3)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x4)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 6
+// CHECK: (('section_name', '__literal16\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', 2464)
+ // FIXME: We aren't setting alignment correctly yet.
+// CHECX: ('alignment', 4)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0xe)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 7
+// CHECK: (('section_name', '__constructor\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', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x0)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 8
+// CHECK: (('section_name', '__destructor\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', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x0)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 9
+// CHECK: (('section_name', '__symbol_stub\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', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x80000008)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 16)
+// CHECK: ),
+// CHECK: # Section 10
+// CHECK: (('section_name', '__picsymbol_stub')
+// CHECK: ('segment_name', '__TEXT\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x80000008)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 26)
+// CHECK: ),
+// CHECK: # Section 11
+// 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', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x0)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 12
+// CHECK: (('section_name', '__static_data\x00\x00\x00')
+// CHECK: ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x0)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 13
+// CHECK: (('section_name', '__nl_symbol_ptr\x00')
+// CHECK: ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+ // FIXME: We aren't setting alignment correctly yet.
+// CHECX: ('alignment', 2)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x6)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 14
+// CHECK: (('section_name', '__la_symbol_ptr\x00')
+// CHECK: ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+ // FIXME: We aren't setting alignment correctly yet.
+// CHECX: ('alignment', 2)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x7)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 15
+// CHECK: (('section_name', '__dyld\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', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x0)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 16
+// CHECK: (('section_name', '__mod_init_func\x00')
+// CHECK: ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+ // FIXME: We aren't setting alignment correctly yet.
+// CHECX: ('alignment', 2)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x9)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 17
+// CHECK: (('section_name', '__mod_term_func\x00')
+// CHECK: ('segment_name', '__DATA\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+ // FIXME: We aren't setting alignment correctly yet.
+// CHECX: ('alignment', 2)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0xa)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 18
+// CHECK: (('section_name', '__const\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', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x0)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 19
+// CHECK: (('section_name', '__class\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('segment_name', '__OBJC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x10000000)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 20
+// CHECK: (('section_name', '__meta_class\x00\x00\x00\x00')
+// CHECK: ('segment_name', '__OBJC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x10000000)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 21
+// CHECK: (('section_name', '__cat_cls_meth\x00\x00')
+// CHECK: ('segment_name', '__OBJC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x10000000)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 22
+// CHECK: (('section_name', '__cat_inst_meth\x00')
+// CHECK: ('segment_name', '__OBJC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x10000000)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 23
+// CHECK: (('section_name', '__protocol\x00\x00\x00\x00\x00\x00')
+// CHECK: ('segment_name', '__OBJC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x10000000)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 24
+// CHECK: (('section_name', '__string_object\x00')
+// CHECK: ('segment_name', '__OBJC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x10000000)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 25
+// CHECK: (('section_name', '__cls_meth\x00\x00\x00\x00\x00\x00')
+// CHECK: ('segment_name', '__OBJC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x10000000)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 26
+// CHECK: (('section_name', '__inst_meth\x00\x00\x00\x00\x00')
+// CHECK: ('segment_name', '__OBJC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x10000000)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 27
+// CHECK: (('section_name', '__cls_refs\x00\x00\x00\x00\x00\x00')
+// CHECK: ('segment_name', '__OBJC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+ // FIXME: We aren't setting alignment correctly yet.
+// CHECX: ('alignment', 2)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x10000005)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 28
+// CHECK: (('section_name', '__message_refs\x00\x00')
+// CHECK: ('segment_name', '__OBJC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+ // FIXME: We aren't setting alignment correctly yet.
+// CHECX: ('alignment', 2)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x10000005)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 29
+// CHECK: (('section_name', '__symbols\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('segment_name', '__OBJC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)
+// CHECK: ('num_reloc', 0)
+// CHECK: ('flags', 0x10000000)
+// CHECK: ('reserved1', 0)
+// CHECK: ('reserved2', 0)
+// CHECK: ),
+// CHECK: # Section 30
+// CHECK: (('section_name', '__category\x00\x00\x00\x00\x00\x00')
+// CHECK: ('segment_name', '__OBJC\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00')
+// CHECK: ('address', 0)
+// CHECK: ('size', 0)
+// CHECK: ('offset', 2464)
+// CHECK: ('alignment', 0)
+// CHECK: ('reloc_offset', 0)