1 //===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #include "llvm/MC/MCAssembler.h"
11 #include "llvm/MC/MCSectionMachO.h"
12 #include "llvm/Support/DataTypes.h"
13 #include "llvm/Support/raw_ostream.h"
14 #include "llvm/Target/TargetMachOWriterInfo.h"
20 class MachObjectWriter {
21 // See <mach-o/loader.h>.
23 Header_Magic32 = 0xFEEDFACE,
24 Header_Magic64 = 0xFEEDFACF
27 static const unsigned Header32Size = 28;
28 static const unsigned Header64Size = 32;
29 static const unsigned SegmentLoadCommand32Size = 56;
30 static const unsigned Section32Size = 68;
36 enum LoadCommandType {
44 MachObjectWriter(raw_ostream &_OS, bool _IsLSB = true)
45 : OS(_OS), IsLSB(_IsLSB) {
48 /// @name Helper Methods
51 void Write32(uint32_t Value) {
53 OS << char(Value >> 0);
54 OS << char(Value >> 8);
55 OS << char(Value >> 16);
56 OS << char(Value >> 24);
58 OS << char(Value >> 24);
59 OS << char(Value >> 16);
60 OS << char(Value >> 8);
61 OS << char(Value >> 0);
65 void WriteZeros(unsigned N) {
66 const char Zeros[16] = { 0 };
68 for (unsigned i = 0, e = N / 16; i != e; ++i)
69 OS << StringRef(Zeros, 16);
71 OS << StringRef(Zeros, N % 16);
74 void WriteString(const StringRef &Str, unsigned ZeroFillSize = 0) {
77 WriteZeros(ZeroFillSize - Str.size());
82 static unsigned getPrologSize32(unsigned NumSections) {
83 return Header32Size + SegmentLoadCommand32Size +
84 NumSections * Section32Size;
87 void WriteHeader32(unsigned NumSections) {
88 // struct mach_header (28 bytes)
90 uint64_t Start = OS.tell();
93 Write32(Header_Magic32);
95 // FIXME: Support cputype.
96 Write32(TargetMachOWriterInfo::HDR_CPU_TYPE_I386);
98 // FIXME: Support cpusubtype.
99 Write32(TargetMachOWriterInfo::HDR_CPU_SUBTYPE_I386_ALL);
103 // Object files have a single load command, the segment.
105 Write32(SegmentLoadCommand32Size + NumSections * Section32Size);
108 assert(OS.tell() - Start == Header32Size);
111 void WriteLoadCommandHeader(uint32_t Cmd, uint32_t CmdSize) {
112 assert((CmdSize & 0x3) == 0 && "Invalid size!");
118 void WriteSegmentLoadCommand32(unsigned NumSections) {
119 // struct segment_command (56 bytes)
121 uint64_t Start = OS.tell();
124 Write32(LCT_Segment);
125 Write32(SegmentLoadCommand32Size + NumSections * Section32Size);
128 Write32(0); // vmaddr
129 Write32(0); // vmsize
130 Write32(Header32Size + SegmentLoadCommand32Size +
131 NumSections * Section32Size); // file offset
132 Write32(0); // file size
133 Write32(0x7); // maxprot
134 Write32(0x7); // initprot
135 Write32(NumSections);
138 assert(OS.tell() - Start == SegmentLoadCommand32Size);
141 void WriteSection32(const MCSectionData &SD) {
142 // struct section (68 bytes)
144 uint64_t Start = OS.tell();
147 // FIXME: cast<> support!
148 const MCSectionMachO &Section =
149 static_cast<const MCSectionMachO&>(SD.getSection());
150 WriteString(Section.getSectionName(), 16);
151 WriteString(Section.getSegmentName(), 16);
152 Write32(0); // address
153 Write32(SD.getFileSize()); // size
154 Write32(SD.getFileOffset());
156 assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!");
157 Write32(Log2_32(SD.getAlignment()));
158 Write32(0); // file offset of relocation entries
159 Write32(0); // number of relocation entrions
160 Write32(Section.getTypeAndAttributes());
161 Write32(0); // reserved1
162 Write32(Section.getStubSize()); // reserved2
164 assert(OS.tell() - Start == Section32Size);
172 MCFragment::MCFragment(MCSectionData *SD)
175 SD->getFragmentList().push_back(this);
180 MCSectionData::MCSectionData() : Section(*(MCSection*)0) {}
182 MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
189 A->getSectionList().push_back(this);
192 void MCSectionData::WriteFileData(raw_ostream &OS) const {
198 MCAssembler::MCAssembler(raw_ostream &_OS) : OS(_OS) {}
200 MCAssembler::~MCAssembler() {
203 void MCAssembler::Finish() {
204 unsigned NumSections = Sections.size();
206 // Compute the file offsets so we can write in a single pass.
207 uint64_t Offset = MachObjectWriter::getPrologSize32(NumSections);
208 for (iterator it = begin(), ie = end(); it != ie; ++it) {
209 it->setFileOffset(Offset);
210 Offset += it->getFileSize();
213 MachObjectWriter MOW(OS);
215 // Write the prolog, starting with the header and load command...
216 MOW.WriteHeader32(NumSections);
217 MOW.WriteSegmentLoadCommand32(NumSections);
219 // ... and then the section headers.
220 for (iterator it = begin(), ie = end(); it != ie; ++it)
221 MOW.WriteSection32(*it);
223 // Finally, write the section data.
224 for (iterator it = begin(), ie = end(); it != ie; ++it)
225 it->WriteFileData(OS);