blob: 1f62b060528fb92c3feb648b9e5db902f9c86448 [file] [log] [blame]
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +00001//===- lib/MC/MCAssembler.cpp - Assembler Backend Implementation ----------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Daniel Dunbar0adcd352009-08-25 21:10:45 +000010#define DEBUG_TYPE "assembler"
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +000011#include "llvm/MC/MCAssembler.h"
Chris Lattnerbea2c952009-08-22 19:19:12 +000012#include "llvm/MC/MCSectionMachO.h"
13#include "llvm/Target/TargetMachOWriterInfo.h"
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +000014#include "llvm/ADT/DenseMap.h"
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +000015#include "llvm/ADT/SmallString.h"
Daniel Dunbar0adcd352009-08-25 21:10:45 +000016#include "llvm/ADT/Statistic.h"
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +000017#include "llvm/ADT/StringMap.h"
Daniel Dunbard6f761e2009-08-21 23:07:38 +000018#include "llvm/ADT/Twine.h"
Daniel Dunbar0705fbf2009-08-21 18:29:01 +000019#include "llvm/Support/ErrorHandling.h"
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +000020#include "llvm/Support/raw_ostream.h"
Chris Lattner23132b12009-08-24 03:52:50 +000021#include <vector>
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +000022using namespace llvm;
23
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +000024class MachObjectWriter;
25
Daniel Dunbar0adcd352009-08-25 21:10:45 +000026STATISTIC(EmittedFragments, "Number of emitted assembler fragments");
27
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +000028static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
29 MachObjectWriter &MOW);
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +000030
31class MachObjectWriter {
32 // See <mach-o/loader.h>.
33 enum {
34 Header_Magic32 = 0xFEEDFACE,
35 Header_Magic64 = 0xFEEDFACF
36 };
37
38 static const unsigned Header32Size = 28;
39 static const unsigned Header64Size = 32;
40 static const unsigned SegmentLoadCommand32Size = 56;
41 static const unsigned Section32Size = 68;
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +000042 static const unsigned SymtabLoadCommandSize = 24;
43 static const unsigned DysymtabLoadCommandSize = 80;
44 static const unsigned Nlist32Size = 12;
Daniel Dunbar3f6a9602009-08-26 13:58:10 +000045 static const unsigned RelocationInfoSize = 8;
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +000046
47 enum HeaderFileType {
48 HFT_Object = 0x1
49 };
50
51 enum LoadCommandType {
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +000052 LCT_Segment = 0x1,
53 LCT_Symtab = 0x2,
54 LCT_Dysymtab = 0xb
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +000055 };
56
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +000057 // See <mach-o/nlist.h>.
58 enum SymbolTypeType {
59 STT_Undefined = 0x00,
60 STT_Absolute = 0x02,
61 STT_Section = 0x0e
62 };
63
64 enum SymbolTypeFlags {
65 // If any of these bits are set, then the entry is a stab entry number (see
66 // <mach-o/stab.h>. Otherwise the other masks apply.
67 STF_StabsEntryMask = 0xe0,
68
69 STF_TypeMask = 0x0e,
70 STF_External = 0x01,
71 STF_PrivateExtern = 0x10
72 };
73
Daniel Dunbarad7c3d52009-08-26 00:18:21 +000074 /// IndirectSymbolFlags - Flags for encoding special values in the indirect
75 /// symbol entry.
76 enum IndirectSymbolFlags {
77 ISF_Local = 0x80000000,
78 ISF_Absolute = 0x40000000
79 };
80
Daniel Dunbar3f6a9602009-08-26 13:58:10 +000081 /// RelocationFlags - Special flags for addresses.
82 enum RelocationFlags {
83 RF_Scattered = 0x80000000
84 };
85
86 enum RelocationInfoType {
87 RIT_Vanilla = 0,
88 RIT_Pair = 1,
89 RIT_Difference = 2,
90 RIT_PreboundLazyPointer = 3,
91 RIT_LocalDifference = 4
92 };
93
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +000094 /// MachSymbolData - Helper struct for containing some precomputed information
95 /// on symbols.
96 struct MachSymbolData {
97 MCSymbolData *SymbolData;
98 uint64_t StringIndex;
99 uint8_t SectionIndex;
100
101 // Support lexicographic sorting.
102 bool operator<(const MachSymbolData &RHS) const {
103 const std::string &Name = SymbolData->getSymbol().getName();
104 return Name < RHS.SymbolData->getSymbol().getName();
105 }
106 };
107
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000108 raw_ostream &OS;
109 bool IsLSB;
110
111public:
112 MachObjectWriter(raw_ostream &_OS, bool _IsLSB = true)
113 : OS(_OS), IsLSB(_IsLSB) {
114 }
115
116 /// @name Helper Methods
117 /// @{
118
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000119 void Write8(uint8_t Value) {
120 OS << char(Value);
121 }
122
123 void Write16(uint16_t Value) {
124 if (IsLSB) {
125 Write8(uint8_t(Value >> 0));
126 Write8(uint8_t(Value >> 8));
127 } else {
128 Write8(uint8_t(Value >> 8));
129 Write8(uint8_t(Value >> 0));
130 }
131 }
132
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000133 void Write32(uint32_t Value) {
134 if (IsLSB) {
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000135 Write16(uint16_t(Value >> 0));
136 Write16(uint16_t(Value >> 16));
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000137 } else {
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000138 Write16(uint16_t(Value >> 16));
139 Write16(uint16_t(Value >> 0));
140 }
141 }
142
143 void Write64(uint64_t Value) {
144 if (IsLSB) {
145 Write32(uint32_t(Value >> 0));
146 Write32(uint32_t(Value >> 32));
147 } else {
148 Write32(uint32_t(Value >> 32));
149 Write32(uint32_t(Value >> 0));
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000150 }
151 }
152
153 void WriteZeros(unsigned N) {
154 const char Zeros[16] = { 0 };
155
156 for (unsigned i = 0, e = N / 16; i != e; ++i)
157 OS << StringRef(Zeros, 16);
158
159 OS << StringRef(Zeros, N % 16);
160 }
161
162 void WriteString(const StringRef &Str, unsigned ZeroFillSize = 0) {
163 OS << Str;
164 if (ZeroFillSize)
165 WriteZeros(ZeroFillSize - Str.size());
166 }
167
168 /// @}
169
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000170 void WriteHeader32(unsigned NumLoadCommands, unsigned LoadCommandsSize) {
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000171 // struct mach_header (28 bytes)
172
173 uint64_t Start = OS.tell();
174 (void) Start;
175
176 Write32(Header_Magic32);
177
178 // FIXME: Support cputype.
179 Write32(TargetMachOWriterInfo::HDR_CPU_TYPE_I386);
180
181 // FIXME: Support cpusubtype.
182 Write32(TargetMachOWriterInfo::HDR_CPU_SUBTYPE_I386_ALL);
183
184 Write32(HFT_Object);
185
186 // Object files have a single load command, the segment.
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000187 Write32(NumLoadCommands);
188 Write32(LoadCommandsSize);
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000189 Write32(0); // Flags
190
191 assert(OS.tell() - Start == Header32Size);
192 }
193
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000194 /// WriteSegmentLoadCommand32 - Write a 32-bit segment load command.
195 ///
196 /// \arg NumSections - The number of sections in this segment.
197 /// \arg SectionDataSize - The total size of the sections.
198 void WriteSegmentLoadCommand32(unsigned NumSections,
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000199 uint64_t SectionDataStartOffset,
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000200 uint64_t SectionDataSize) {
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000201 // struct segment_command (56 bytes)
202
203 uint64_t Start = OS.tell();
204 (void) Start;
205
206 Write32(LCT_Segment);
207 Write32(SegmentLoadCommand32Size + NumSections * Section32Size);
208
209 WriteString("", 16);
210 Write32(0); // vmaddr
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000211 Write32(SectionDataSize); // vmsize
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000212 Write32(SectionDataStartOffset); // file offset
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000213 Write32(SectionDataSize); // file size
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000214 Write32(0x7); // maxprot
215 Write32(0x7); // initprot
216 Write32(NumSections);
217 Write32(0); // flags
218
219 assert(OS.tell() - Start == SegmentLoadCommand32Size);
220 }
221
Daniel Dunbar3f6a9602009-08-26 13:58:10 +0000222 void WriteSection32(const MCSectionData &SD, uint64_t FileOffset,
223 uint64_t RelocationsStart, unsigned NumRelocations) {
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000224 // struct section (68 bytes)
225
226 uint64_t Start = OS.tell();
227 (void) Start;
228
229 // FIXME: cast<> support!
230 const MCSectionMachO &Section =
231 static_cast<const MCSectionMachO&>(SD.getSection());
232 WriteString(Section.getSectionName(), 16);
233 WriteString(Section.getSegmentName(), 16);
Daniel Dunbar5e835962009-08-26 02:48:04 +0000234 Write32(SD.getAddress()); // address
Daniel Dunbar6742e342009-08-26 04:13:32 +0000235 Write32(SD.getSize()); // size
Daniel Dunbar2ae58f22009-08-22 08:28:27 +0000236 Write32(FileOffset);
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000237
238 assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!");
239 Write32(Log2_32(SD.getAlignment()));
Daniel Dunbar3f6a9602009-08-26 13:58:10 +0000240 Write32(NumRelocations ? RelocationsStart : 0);
241 Write32(NumRelocations);
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000242 Write32(Section.getTypeAndAttributes());
243 Write32(0); // reserved1
244 Write32(Section.getStubSize()); // reserved2
245
246 assert(OS.tell() - Start == Section32Size);
247 }
Daniel Dunbar2ae58f22009-08-22 08:28:27 +0000248
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000249 void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
250 uint32_t StringTableOffset,
251 uint32_t StringTableSize) {
252 // struct symtab_command (24 bytes)
253
254 uint64_t Start = OS.tell();
255 (void) Start;
256
257 Write32(LCT_Symtab);
258 Write32(SymtabLoadCommandSize);
259 Write32(SymbolOffset);
260 Write32(NumSymbols);
261 Write32(StringTableOffset);
262 Write32(StringTableSize);
263
264 assert(OS.tell() - Start == SymtabLoadCommandSize);
265 }
266
267 void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
268 uint32_t NumLocalSymbols,
269 uint32_t FirstExternalSymbol,
270 uint32_t NumExternalSymbols,
271 uint32_t FirstUndefinedSymbol,
272 uint32_t NumUndefinedSymbols,
273 uint32_t IndirectSymbolOffset,
274 uint32_t NumIndirectSymbols) {
275 // struct dysymtab_command (80 bytes)
276
277 uint64_t Start = OS.tell();
278 (void) Start;
279
280 Write32(LCT_Dysymtab);
281 Write32(DysymtabLoadCommandSize);
282 Write32(FirstLocalSymbol);
283 Write32(NumLocalSymbols);
284 Write32(FirstExternalSymbol);
285 Write32(NumExternalSymbols);
286 Write32(FirstUndefinedSymbol);
287 Write32(NumUndefinedSymbols);
288 Write32(0); // tocoff
289 Write32(0); // ntoc
290 Write32(0); // modtaboff
291 Write32(0); // nmodtab
292 Write32(0); // extrefsymoff
293 Write32(0); // nextrefsyms
294 Write32(IndirectSymbolOffset);
295 Write32(NumIndirectSymbols);
296 Write32(0); // extreloff
297 Write32(0); // nextrel
298 Write32(0); // locreloff
299 Write32(0); // nlocrel
300
301 assert(OS.tell() - Start == DysymtabLoadCommandSize);
302 }
303
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000304 void WriteNlist32(MachSymbolData &MSD) {
Daniel Dunbar5e835962009-08-26 02:48:04 +0000305 MCSymbolData &Data = *MSD.SymbolData;
306 MCSymbol &Symbol = Data.getSymbol();
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000307 uint8_t Type = 0;
308
309 // Set the N_TYPE bits. See <mach-o/nlist.h>.
310 //
311 // FIXME: Are the prebound or indirect fields possible here?
312 if (Symbol.isUndefined())
313 Type = STT_Undefined;
314 else if (Symbol.isAbsolute())
315 Type = STT_Absolute;
316 else
317 Type = STT_Section;
318
319 // FIXME: Set STAB bits.
320
Daniel Dunbar5e835962009-08-26 02:48:04 +0000321 if (Data.isPrivateExtern())
Daniel Dunbar6aff2fb2009-08-24 08:40:12 +0000322 Type |= STF_PrivateExtern;
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000323
324 // Set external bit.
Daniel Dunbar5e835962009-08-26 02:48:04 +0000325 if (Data.isExternal() || Symbol.isUndefined())
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000326 Type |= STF_External;
327
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000328 // struct nlist (12 bytes)
329
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000330 Write32(MSD.StringIndex);
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000331 Write8(Type);
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000332 Write8(MSD.SectionIndex);
Daniel Dunbar6aff2fb2009-08-24 08:40:12 +0000333
334 // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
335 // value.
Daniel Dunbar5e835962009-08-26 02:48:04 +0000336 Write16(Data.getFlags() & 0xFFFF);
Daniel Dunbar6aff2fb2009-08-24 08:40:12 +0000337
Daniel Dunbar5e835962009-08-26 02:48:04 +0000338 // Write the symbol address.
339 uint32_t Address = 0;
340 if (Symbol.isDefined()) {
341 if (Symbol.isAbsolute()) {
342 llvm_unreachable("FIXME: Not yet implemented!");
343 } else {
344 Address = Data.getFragment()->getAddress() + Data.getOffset();
345 }
346 }
347 Write32(Address);
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000348 }
349
Daniel Dunbar3f6a9602009-08-26 13:58:10 +0000350 struct MachRelocationEntry {
351 uint32_t Word0;
352 uint32_t Word1;
353 };
354 void ComputeScatteredRelocationInfo(MCAssembler &Asm,
355 MCSectionData::Fixup &Fixup,
356 DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
357 std::vector<MachRelocationEntry> &Relocs) {
358 uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset;
359 unsigned IsPCRel = 0;
360 unsigned Type = RIT_Vanilla;
361
362 // See <reloc.h>.
363
364 const MCSymbol *A = Fixup.Value.getSymA();
365 MCSymbolData *SD = SymbolMap.lookup(A);
366 uint32_t Value = SD->getFragment()->getAddress() + SD->getOffset();
367 uint32_t Value2 = 0;
368
369 if (const MCSymbol *B = Fixup.Value.getSymB()) {
370 Type = RIT_LocalDifference;
371
372 MCSymbolData *SD = SymbolMap.lookup(B);
373 Value2 = SD->getFragment()->getAddress() + SD->getOffset();
374 }
375
376 unsigned Log2Size = Log2_32(Fixup.Size);
377 assert((1U << Log2Size) == Fixup.Size && "Invalid fixup size!");
378
379 // The value which goes in the fixup is current value of the expression.
380 Fixup.FixedValue = Value - Value2 + Fixup.Value.getConstant();
381
382 MachRelocationEntry MRE;
383 MRE.Word0 = ((Address << 0) |
384 (Type << 24) |
385 (Log2Size << 28) |
386 (IsPCRel << 30) |
387 RF_Scattered);
388 MRE.Word1 = Value;
389 Relocs.push_back(MRE);
390
391 if (Type == RIT_LocalDifference) {
392 Type = RIT_Pair;
393
394 MachRelocationEntry MRE;
395 MRE.Word0 = ((0 << 0) |
396 (Type << 24) |
397 (Log2Size << 28) |
398 (0 << 30) |
399 RF_Scattered);
400 MRE.Word1 = Value2;
401 Relocs.push_back(MRE);
402 }
403 }
404
405 void ComputeRelocationInfo(MCAssembler &Asm,
406 MCSectionData::Fixup &Fixup,
407 DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap,
408 std::vector<MachRelocationEntry> &Relocs) {
409 // If this is a local symbol plus an offset or a difference, then we need a
410 // scattered relocation entry.
411 if (Fixup.Value.getSymB()) // a - b
412 return ComputeScatteredRelocationInfo(Asm, Fixup, SymbolMap, Relocs);
413 if (Fixup.Value.getSymA() && Fixup.Value.getConstant())
414 if (!Fixup.Value.getSymA()->isUndefined())
415 return ComputeScatteredRelocationInfo(Asm, Fixup, SymbolMap, Relocs);
416
417 // See <reloc.h>.
418 uint32_t Address = Fixup.Fragment->getOffset() + Fixup.Offset;
419 uint32_t Value = 0;
420 unsigned Index = 0;
421 unsigned IsPCRel = 0;
422 unsigned IsExtern = 0;
423 unsigned Type = 0;
424
425 if (Fixup.Value.isAbsolute()) { // constant
426 // SymbolNum of 0 indicates the absolute section.
427 Type = RIT_Vanilla;
428 Value = 0;
429 llvm_unreachable("FIXME: Not yet implemented!");
430 } else {
431 const MCSymbol *Symbol = Fixup.Value.getSymA();
432 MCSymbolData *SD = SymbolMap.lookup(Symbol);
433
434 if (Symbol->isUndefined()) {
435 IsExtern = 1;
436 Index = SD->getIndex();
437 Value = 0;
438 } else {
439 // The index is the section ordinal.
440 //
441 // FIXME: O(N)
442 Index = 1;
443 for (MCAssembler::iterator it = Asm.begin(),
444 ie = Asm.end(); it != ie; ++it, ++Index)
445 if (&*it == SD->getFragment()->getParent())
446 break;
447 Value = SD->getFragment()->getAddress() + SD->getOffset();
448 }
449
450 Type = RIT_Vanilla;
451 }
452
453 // The value which goes in the fixup is current value of the expression.
454 Fixup.FixedValue = Value + Fixup.Value.getConstant();
455
456 unsigned Log2Size = Log2_32(Fixup.Size);
457 assert((1U << Log2Size) == Fixup.Size && "Invalid fixup size!");
458
459 // struct relocation_info (8 bytes)
460 MachRelocationEntry MRE;
461 MRE.Word0 = Address;
462 MRE.Word1 = ((Index << 0) |
463 (IsPCRel << 24) |
464 (Log2Size << 25) |
465 (IsExtern << 27) |
466 (Type << 28));
467 Relocs.push_back(MRE);
468 }
469
Daniel Dunbarad7c3d52009-08-26 00:18:21 +0000470 void BindIndirectSymbols(MCAssembler &Asm,
Daniel Dunbarbe963552009-08-26 13:57:54 +0000471 DenseMap<const MCSymbol*,MCSymbolData*> &SymbolMap) {
Daniel Dunbar0c7761b2009-08-24 11:56:58 +0000472 // This is the point where 'as' creates actual symbols for indirect symbols
473 // (in the following two passes). It would be easier for us to do this
474 // sooner when we see the attribute, but that makes getting the order in the
475 // symbol table much more complicated than it is worth.
476 //
477 // FIXME: Revisit this when the dust settles.
478
Daniel Dunbar0c7761b2009-08-24 11:56:58 +0000479 // Bind non lazy symbol pointers first.
480 for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
481 ie = Asm.indirect_symbol_end(); it != ie; ++it) {
482 // FIXME: cast<> support!
483 const MCSectionMachO &Section =
484 static_cast<const MCSectionMachO&>(it->SectionData->getSection());
485
486 unsigned Type =
487 Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE;
488 if (Type != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS)
489 continue;
490
491 MCSymbolData *&Entry = SymbolMap[it->Symbol];
492 if (!Entry)
493 Entry = new MCSymbolData(*it->Symbol, 0, 0, &Asm);
494 }
495
496 // Then lazy symbol pointers and symbol stubs.
497 for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
498 ie = Asm.indirect_symbol_end(); it != ie; ++it) {
499 // FIXME: cast<> support!
500 const MCSectionMachO &Section =
501 static_cast<const MCSectionMachO&>(it->SectionData->getSection());
502
503 unsigned Type =
504 Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE;
505 if (Type != MCSectionMachO::S_LAZY_SYMBOL_POINTERS &&
506 Type != MCSectionMachO::S_SYMBOL_STUBS)
507 continue;
508
509 MCSymbolData *&Entry = SymbolMap[it->Symbol];
510 if (!Entry) {
511 Entry = new MCSymbolData(*it->Symbol, 0, 0, &Asm);
512
513 // Set the symbol type to undefined lazy, but only on construction.
514 //
515 // FIXME: Do not hardcode.
516 Entry->setFlags(Entry->getFlags() | 0x0001);
517 }
518 }
519 }
520
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000521 /// ComputeSymbolTable - Compute the symbol table data
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000522 ///
523 /// \param StringTable [out] - The string table data.
524 /// \param StringIndexMap [out] - Map from symbol names to offsets in the
525 /// string table.
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000526 void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
527 std::vector<MachSymbolData> &LocalSymbolData,
528 std::vector<MachSymbolData> &ExternalSymbolData,
529 std::vector<MachSymbolData> &UndefinedSymbolData) {
530 // Build section lookup table.
531 DenseMap<const MCSection*, uint8_t> SectionIndexMap;
532 unsigned Index = 1;
533 for (MCAssembler::iterator it = Asm.begin(),
534 ie = Asm.end(); it != ie; ++it, ++Index)
535 SectionIndexMap[&it->getSection()] = Index;
536 assert(Index <= 256 && "Too many sections!");
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000537
538 // Index 0 is always the empty string.
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000539 StringMap<uint64_t> StringIndexMap;
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000540 StringTable += '\x00';
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000541
542 // Build the symbol arrays and the string table, but only for non-local
543 // symbols.
544 //
545 // The particular order that we collect the symbols and create the string
546 // table, then sort the symbols is chosen to match 'as'. Even though it
547 // doesn't matter for correctness, this is important for letting us diff .o
548 // files.
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000549 for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
550 ie = Asm.symbol_end(); it != ie; ++it) {
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000551 MCSymbol &Symbol = it->getSymbol();
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000552
Daniel Dunbar50e48b32009-08-24 08:39:57 +0000553 if (!it->isExternal() && !Symbol.isUndefined())
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000554 continue;
555
556 uint64_t &Entry = StringIndexMap[Symbol.getName()];
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000557 if (!Entry) {
558 Entry = StringTable.size();
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000559 StringTable += Symbol.getName();
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000560 StringTable += '\x00';
561 }
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000562
563 MachSymbolData MSD;
564 MSD.SymbolData = it;
565 MSD.StringIndex = Entry;
566
567 if (Symbol.isUndefined()) {
568 MSD.SectionIndex = 0;
569 UndefinedSymbolData.push_back(MSD);
570 } else if (Symbol.isAbsolute()) {
571 MSD.SectionIndex = 0;
572 ExternalSymbolData.push_back(MSD);
573 } else {
574 MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
575 assert(MSD.SectionIndex && "Invalid section index!");
576 ExternalSymbolData.push_back(MSD);
577 }
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000578 }
579
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000580 // Now add the data for local symbols.
581 for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
582 ie = Asm.symbol_end(); it != ie; ++it) {
583 MCSymbol &Symbol = it->getSymbol();
584
Daniel Dunbar50e48b32009-08-24 08:39:57 +0000585 if (it->isExternal() || Symbol.isUndefined())
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000586 continue;
587
588 uint64_t &Entry = StringIndexMap[Symbol.getName()];
589 if (!Entry) {
590 Entry = StringTable.size();
591 StringTable += Symbol.getName();
592 StringTable += '\x00';
593 }
594
595 MachSymbolData MSD;
596 MSD.SymbolData = it;
597 MSD.StringIndex = Entry;
598
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000599 if (Symbol.isAbsolute()) {
600 MSD.SectionIndex = 0;
601 LocalSymbolData.push_back(MSD);
602 } else {
603 MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
604 assert(MSD.SectionIndex && "Invalid section index!");
605 LocalSymbolData.push_back(MSD);
606 }
607 }
608
609 // External and undefined symbols are required to be in lexicographic order.
610 std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
611 std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());
612
Daniel Dunbarbe963552009-08-26 13:57:54 +0000613 // Set the symbol indices.
614 Index = 0;
615 for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
616 LocalSymbolData[i].SymbolData->setIndex(Index++);
617 for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
618 ExternalSymbolData[i].SymbolData->setIndex(Index++);
619 for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
620 UndefinedSymbolData[i].SymbolData->setIndex(Index++);
621
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000622 // The string table is padded to a multiple of 4.
623 //
624 // FIXME: Check to see if this varies per arch.
625 while (StringTable.size() % 4)
626 StringTable += '\x00';
627 }
628
629 void WriteObject(MCAssembler &Asm) {
Daniel Dunbar2ae58f22009-08-22 08:28:27 +0000630 unsigned NumSections = Asm.size();
631
Daniel Dunbarad7c3d52009-08-26 00:18:21 +0000632 // Compute the symbol -> symbol data map.
633 //
634 // FIXME: This should not be here.
Daniel Dunbarbe963552009-08-26 13:57:54 +0000635 DenseMap<const MCSymbol*, MCSymbolData *> SymbolMap;
Daniel Dunbarad7c3d52009-08-26 00:18:21 +0000636 for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
637 ie = Asm.symbol_end(); it != ie; ++it)
638 SymbolMap[&it->getSymbol()] = it;
639
640 // Create symbol data for any indirect symbols.
641 BindIndirectSymbols(Asm, SymbolMap);
Daniel Dunbar0c7761b2009-08-24 11:56:58 +0000642
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000643 // Compute symbol table information.
644 SmallString<256> StringTable;
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000645 std::vector<MachSymbolData> LocalSymbolData;
646 std::vector<MachSymbolData> ExternalSymbolData;
647 std::vector<MachSymbolData> UndefinedSymbolData;
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000648 unsigned NumSymbols = Asm.symbol_size();
649
650 // No symbol table command is written if there are no symbols.
651 if (NumSymbols)
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000652 ComputeSymbolTable(Asm, StringTable, LocalSymbolData, ExternalSymbolData,
653 UndefinedSymbolData);
Daniel Dunbar2ae58f22009-08-22 08:28:27 +0000654
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000655 // The section data starts after the header, the segment load command (and
656 // section headers) and the symbol table.
657 unsigned NumLoadCommands = 1;
658 uint64_t LoadCommandsSize =
659 SegmentLoadCommand32Size + NumSections * Section32Size;
660
661 // Add the symbol table load command sizes, if used.
662 if (NumSymbols) {
663 NumLoadCommands += 2;
664 LoadCommandsSize += SymtabLoadCommandSize + DysymtabLoadCommandSize;
665 }
666
Daniel Dunbar6742e342009-08-26 04:13:32 +0000667 uint64_t SectionDataStart = Header32Size + LoadCommandsSize;
668 uint64_t SectionDataEnd = SectionDataStart;
Daniel Dunbar2ae58f22009-08-22 08:28:27 +0000669 uint64_t SectionDataSize = 0;
Daniel Dunbar6742e342009-08-26 04:13:32 +0000670 if (!Asm.getSectionList().empty()) {
671 MCSectionData &SD = Asm.getSectionList().back();
672 SectionDataSize = SD.getAddress() + SD.getSize();
673 SectionDataEnd = SectionDataStart + SD.getAddress() + SD.getFileSize();
Daniel Dunbar2ae58f22009-08-22 08:28:27 +0000674 }
675
676 // Write the prolog, starting with the header and load command...
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000677 WriteHeader32(NumLoadCommands, LoadCommandsSize);
Daniel Dunbar6742e342009-08-26 04:13:32 +0000678 WriteSegmentLoadCommand32(NumSections, SectionDataStart, SectionDataSize);
Daniel Dunbar2ae58f22009-08-22 08:28:27 +0000679
680 // ... and then the section headers.
Daniel Dunbar3f6a9602009-08-26 13:58:10 +0000681 //
682 // We also compute the section relocations while we do this. Note that
683 // compute relocation info will also update the fixup to have the correct
684 // value; this will be overwrite the appropriate data in the fragment when
685 // it is written.
686 std::vector<MachRelocationEntry> RelocInfos;
687 uint64_t RelocTableEnd = SectionDataEnd;
688 for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie;
689 ++it) {
690 MCSectionData &SD = *it;
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000691
Daniel Dunbar3f6a9602009-08-26 13:58:10 +0000692 // The assembler writes relocations in the reverse order they were seen.
693 //
694 // FIXME: It is probably more complicated than this.
695 unsigned NumRelocsStart = RelocInfos.size();
696 for (unsigned i = 0, e = SD.fixup_size(); i != e; ++i)
697 ComputeRelocationInfo(Asm, SD.getFixups()[e - i - 1], SymbolMap,
698 RelocInfos);
699
700 unsigned NumRelocs = RelocInfos.size() - NumRelocsStart;
701 uint64_t SectionStart = SectionDataStart + SD.getAddress();
702 WriteSection32(SD, SectionStart, RelocTableEnd, NumRelocs);
703 RelocTableEnd += NumRelocs * RelocationInfoSize;
704 }
705
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000706 // Write the symbol table load command, if used.
707 if (NumSymbols) {
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000708 unsigned FirstLocalSymbol = 0;
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000709 unsigned NumLocalSymbols = LocalSymbolData.size();
710 unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;
711 unsigned NumExternalSymbols = ExternalSymbolData.size();
712 unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;
713 unsigned NumUndefinedSymbols = UndefinedSymbolData.size();
Daniel Dunbar0c7761b2009-08-24 11:56:58 +0000714 unsigned NumIndirectSymbols = Asm.indirect_symbol_size();
715 unsigned NumSymTabSymbols =
716 NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols;
717 uint64_t IndirectSymbolSize = NumIndirectSymbols * 4;
718 uint64_t IndirectSymbolOffset = 0;
719
720 // If used, the indirect symbols are written after the section data.
721 if (NumIndirectSymbols)
Daniel Dunbar3f6a9602009-08-26 13:58:10 +0000722 IndirectSymbolOffset = RelocTableEnd;
Daniel Dunbar0c7761b2009-08-24 11:56:58 +0000723
724 // The symbol table is written after the indirect symbol data.
Daniel Dunbar3f6a9602009-08-26 13:58:10 +0000725 uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize;
Daniel Dunbar0c7761b2009-08-24 11:56:58 +0000726
727 // The string table is written after symbol table.
728 uint64_t StringTableOffset =
729 SymbolTableOffset + NumSymTabSymbols * Nlist32Size;
730 WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
731 StringTableOffset, StringTable.size());
732
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000733 WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
734 FirstExternalSymbol, NumExternalSymbols,
735 FirstUndefinedSymbol, NumUndefinedSymbols,
736 IndirectSymbolOffset, NumIndirectSymbols);
737 }
738
739 // Write the actual section data.
740 for (MCAssembler::iterator it = Asm.begin(), ie = Asm.end(); it != ie; ++it)
741 WriteFileData(OS, *it, *this);
742
Daniel Dunbar3f6a9602009-08-26 13:58:10 +0000743 // Write the relocation entries.
744 for (unsigned i = 0, e = RelocInfos.size(); i != e; ++i) {
745 Write32(RelocInfos[i].Word0);
746 Write32(RelocInfos[i].Word1);
747 }
748
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000749 // Write the symbol table data, if used.
750 if (NumSymbols) {
Daniel Dunbar0c7761b2009-08-24 11:56:58 +0000751 // Write the indirect symbol entries.
Daniel Dunbarad7c3d52009-08-26 00:18:21 +0000752 for (MCAssembler::indirect_symbol_iterator
753 it = Asm.indirect_symbol_begin(),
754 ie = Asm.indirect_symbol_end(); it != ie; ++it) {
755 // Indirect symbols in the non lazy symbol pointer section have some
756 // special handling.
757 const MCSectionMachO &Section =
758 static_cast<const MCSectionMachO&>(it->SectionData->getSection());
759 unsigned Type =
760 Section.getTypeAndAttributes() & MCSectionMachO::SECTION_TYPE;
761 if (Type == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) {
762 // If this symbol is defined and internal, mark it as such.
763 if (it->Symbol->isDefined() &&
764 !SymbolMap.lookup(it->Symbol)->isExternal()) {
765 uint32_t Flags = ISF_Local;
766 if (it->Symbol->isAbsolute())
767 Flags |= ISF_Absolute;
768 Write32(Flags);
769 continue;
770 }
771 }
772
Daniel Dunbarbe963552009-08-26 13:57:54 +0000773 Write32(SymbolMap[it->Symbol]->getIndex());
Daniel Dunbarad7c3d52009-08-26 00:18:21 +0000774 }
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000775
Daniel Dunbar0c7761b2009-08-24 11:56:58 +0000776 // FIXME: Check that offsets match computed ones.
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000777
778 // Write the symbol table entries.
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000779 for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
780 WriteNlist32(LocalSymbolData[i]);
781 for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
782 WriteNlist32(ExternalSymbolData[i]);
783 for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
784 WriteNlist32(UndefinedSymbolData[i]);
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000785
786 // Write the string table.
787 OS << StringTable.str();
788 }
Daniel Dunbar2ae58f22009-08-22 08:28:27 +0000789 }
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000790};
791
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000792/* *** */
793
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000794MCFragment::MCFragment() : Kind(FragmentType(~0)) {
795}
796
Daniel Dunbar5e835962009-08-26 02:48:04 +0000797MCFragment::MCFragment(FragmentType _Kind, MCSectionData *_Parent)
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000798 : Kind(_Kind),
Daniel Dunbar5e835962009-08-26 02:48:04 +0000799 Parent(_Parent),
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000800 FileSize(~UINT64_C(0))
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000801{
Daniel Dunbar5e835962009-08-26 02:48:04 +0000802 if (Parent)
803 Parent->getFragmentList().push_back(this);
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000804}
805
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000806MCFragment::~MCFragment() {
807}
808
Daniel Dunbar5e835962009-08-26 02:48:04 +0000809uint64_t MCFragment::getAddress() const {
810 assert(getParent() && "Missing Section!");
811 return getParent()->getAddress() + Offset;
812}
813
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000814/* *** */
815
816MCSectionData::MCSectionData() : Section(*(MCSection*)0) {}
817
818MCSectionData::MCSectionData(const MCSection &_Section, MCAssembler *A)
819 : Section(_Section),
820 Alignment(1),
Daniel Dunbar5e835962009-08-26 02:48:04 +0000821 Address(~UINT64_C(0)),
Daniel Dunbar6742e342009-08-26 04:13:32 +0000822 Size(~UINT64_C(0)),
Daniel Dunbar3f6a9602009-08-26 13:58:10 +0000823 FileSize(~UINT64_C(0)),
824 LastFixupLookup(~0)
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000825{
826 if (A)
827 A->getSectionList().push_back(this);
828}
829
Daniel Dunbar3f6a9602009-08-26 13:58:10 +0000830const MCSectionData::Fixup *
831MCSectionData::LookupFixup(const MCFragment *Fragment, uint64_t Offset) const {
832 // Use a one level cache to turn the common case of accessing the fixups in
833 // order into O(1) instead of O(N).
834 unsigned i = LastFixupLookup, Count = Fixups.size(), End = Fixups.size();
835 if (i >= End)
836 i = 0;
837 while (Count--) {
838 const Fixup &F = Fixups[i];
839 if (F.Fragment == Fragment && F.Offset == Offset) {
840 LastFixupLookup = i;
841 return &F;
842 }
843
844 ++i;
845 if (i == End)
846 i = 0;
847 }
848
849 return 0;
850}
851
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000852/* *** */
853
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000854MCSymbolData::MCSymbolData() : Symbol(*(MCSymbol*)0) {}
855
856MCSymbolData::MCSymbolData(MCSymbol &_Symbol, MCFragment *_Fragment,
857 uint64_t _Offset, MCAssembler *A)
Daniel Dunbar3edd9bb2009-08-22 11:41:10 +0000858 : Symbol(_Symbol), Fragment(_Fragment), Offset(_Offset),
Daniel Dunbarbe963552009-08-26 13:57:54 +0000859 IsExternal(false), IsPrivateExtern(false), Flags(0), Index(0)
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +0000860{
861 if (A)
862 A->getSymbolList().push_back(this);
863}
864
865/* *** */
866
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +0000867MCAssembler::MCAssembler(raw_ostream &_OS) : OS(_OS) {}
868
869MCAssembler::~MCAssembler() {
870}
871
Daniel Dunbar6742e342009-08-26 04:13:32 +0000872void MCAssembler::LayoutSection(MCSectionData &SD, unsigned NextAlign) {
873 uint64_t Address = SD.getAddress();
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000874
875 for (MCSectionData::iterator it = SD.begin(), ie = SD.end(); it != ie; ++it) {
876 MCFragment &F = *it;
Daniel Dunbard6f761e2009-08-21 23:07:38 +0000877
Daniel Dunbar6742e342009-08-26 04:13:32 +0000878 F.setOffset(Address - SD.getAddress());
Daniel Dunbard6f761e2009-08-21 23:07:38 +0000879
880 // Evaluate fragment size.
881 switch (F.getKind()) {
882 case MCFragment::FT_Align: {
883 MCAlignFragment &AF = cast<MCAlignFragment>(F);
884
Daniel Dunbar6742e342009-08-26 04:13:32 +0000885 uint64_t Size = RoundUpToAlignment(Address, AF.getAlignment()) - Address;
886 if (Size > AF.getMaxBytesToEmit())
Daniel Dunbard6f761e2009-08-21 23:07:38 +0000887 AF.setFileSize(0);
888 else
Daniel Dunbar6742e342009-08-26 04:13:32 +0000889 AF.setFileSize(Size);
Daniel Dunbard6f761e2009-08-21 23:07:38 +0000890 break;
891 }
892
893 case MCFragment::FT_Data:
Daniel Dunbard6f761e2009-08-21 23:07:38 +0000894 F.setFileSize(F.getMaxFileSize());
895 break;
896
Daniel Dunbar3f6a9602009-08-26 13:58:10 +0000897 case MCFragment::FT_Fill: {
898 MCFillFragment &FF = cast<MCFillFragment>(F);
899
900 F.setFileSize(F.getMaxFileSize());
901
902 // If the fill value is constant, thats it.
903 if (FF.getValue().isAbsolute())
904 break;
905
906 // Otherwise, add fixups for the values.
907 for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) {
908 MCSectionData::Fixup Fix(F, i * FF.getValueSize(),
909 FF.getValue(),FF.getValueSize());
910 SD.getFixups().push_back(Fix);
911 }
912 break;
913 }
914
Daniel Dunbard6f761e2009-08-21 23:07:38 +0000915 case MCFragment::FT_Org: {
916 MCOrgFragment &OF = cast<MCOrgFragment>(F);
917
918 if (!OF.getOffset().isAbsolute())
919 llvm_unreachable("FIXME: Not yet implemented!");
920 uint64_t OrgOffset = OF.getOffset().getConstant();
Daniel Dunbar6742e342009-08-26 04:13:32 +0000921 uint64_t Offset = Address - SD.getAddress();
Daniel Dunbard6f761e2009-08-21 23:07:38 +0000922
923 // FIXME: We need a way to communicate this error.
Daniel Dunbara5441fe2009-08-22 08:27:54 +0000924 if (OrgOffset < Offset)
Daniel Dunbard6f761e2009-08-21 23:07:38 +0000925 llvm_report_error("invalid .org offset '" + Twine(OrgOffset) +
Daniel Dunbar6742e342009-08-26 04:13:32 +0000926 "' (at offset '" + Twine(Offset) + "'");
Daniel Dunbard6f761e2009-08-21 23:07:38 +0000927
Daniel Dunbara5441fe2009-08-22 08:27:54 +0000928 F.setFileSize(OrgOffset - Offset);
Daniel Dunbard6f761e2009-08-21 23:07:38 +0000929 break;
930 }
931 }
932
Daniel Dunbar6742e342009-08-26 04:13:32 +0000933 Address += F.getFileSize();
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000934 }
935
Daniel Dunbar6742e342009-08-26 04:13:32 +0000936 // Set the section sizes.
937 SD.setSize(Address - SD.getAddress());
938 SD.setFileSize(RoundUpToAlignment(Address, NextAlign) - SD.getAddress());
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000939}
940
941/// WriteFileData - Write the \arg F data to the output file.
942static void WriteFileData(raw_ostream &OS, const MCFragment &F,
943 MachObjectWriter &MOW) {
944 uint64_t Start = OS.tell();
945 (void) Start;
946
Daniel Dunbar0adcd352009-08-25 21:10:45 +0000947 ++EmittedFragments;
948
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000949 // FIXME: Embed in fragments instead?
950 switch (F.getKind()) {
Daniel Dunbard6f761e2009-08-21 23:07:38 +0000951 case MCFragment::FT_Align: {
952 MCAlignFragment &AF = cast<MCAlignFragment>(F);
953 uint64_t Count = AF.getFileSize() / AF.getValueSize();
954
955 // FIXME: This error shouldn't actually occur (the front end should emit
956 // multiple .align directives to enforce the semantics it wants), but is
957 // severe enough that we want to report it. How to handle this?
958 if (Count * AF.getValueSize() != AF.getFileSize())
959 llvm_report_error("undefined .align directive, value size '" +
960 Twine(AF.getValueSize()) +
961 "' is not a divisor of padding size '" +
962 Twine(AF.getFileSize()) + "'");
963
964 for (uint64_t i = 0; i != Count; ++i) {
965 switch (AF.getValueSize()) {
966 default:
967 assert(0 && "Invalid size!");
968 case 1: MOW.Write8 (uint8_t (AF.getValue())); break;
969 case 2: MOW.Write16(uint16_t(AF.getValue())); break;
970 case 4: MOW.Write32(uint32_t(AF.getValue())); break;
971 case 8: MOW.Write64(uint64_t(AF.getValue())); break;
972 }
973 }
974 break;
975 }
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000976
977 case MCFragment::FT_Data:
978 OS << cast<MCDataFragment>(F).getContents().str();
979 break;
980
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000981 case MCFragment::FT_Fill: {
982 MCFillFragment &FF = cast<MCFillFragment>(F);
983
Daniel Dunbar3f6a9602009-08-26 13:58:10 +0000984 int64_t Value = 0;
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000985 if (!FF.getValue().isAbsolute())
Daniel Dunbar3f6a9602009-08-26 13:58:10 +0000986 Value = FF.getValue().getConstant();
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000987 for (uint64_t i = 0, e = FF.getCount(); i != e; ++i) {
Daniel Dunbar3f6a9602009-08-26 13:58:10 +0000988 if (!FF.getValue().isAbsolute()) {
989 // Find the fixup.
990 //
991 // FIXME: Find a better way to write in the fixes.
992 const MCSectionData::Fixup *Fixup =
993 F.getParent()->LookupFixup(&F, i * FF.getValueSize());
994 assert(Fixup && "Missing fixup for fill value!");
995 Value = Fixup->FixedValue;
996 }
997
Daniel Dunbar0705fbf2009-08-21 18:29:01 +0000998 switch (FF.getValueSize()) {
999 default:
1000 assert(0 && "Invalid size!");
Daniel Dunbard6f761e2009-08-21 23:07:38 +00001001 case 1: MOW.Write8 (uint8_t (Value)); break;
1002 case 2: MOW.Write16(uint16_t(Value)); break;
1003 case 4: MOW.Write32(uint32_t(Value)); break;
1004 case 8: MOW.Write64(uint64_t(Value)); break;
Daniel Dunbar0705fbf2009-08-21 18:29:01 +00001005 }
1006 }
1007 break;
1008 }
1009
Daniel Dunbard6f761e2009-08-21 23:07:38 +00001010 case MCFragment::FT_Org: {
1011 MCOrgFragment &OF = cast<MCOrgFragment>(F);
1012
1013 for (uint64_t i = 0, e = OF.getFileSize(); i != e; ++i)
1014 MOW.Write8(uint8_t(OF.getValue()));
1015
1016 break;
1017 }
Daniel Dunbar0705fbf2009-08-21 18:29:01 +00001018 }
1019
1020 assert(OS.tell() - Start == F.getFileSize());
1021}
1022
1023/// WriteFileData - Write the \arg SD data to the output file.
1024static void WriteFileData(raw_ostream &OS, const MCSectionData &SD,
1025 MachObjectWriter &MOW) {
1026 uint64_t Start = OS.tell();
1027 (void) Start;
1028
1029 for (MCSectionData::const_iterator it = SD.begin(),
1030 ie = SD.end(); it != ie; ++it)
1031 WriteFileData(OS, *it, MOW);
1032
Daniel Dunbar6742e342009-08-26 04:13:32 +00001033 // Add section padding.
1034 assert(SD.getFileSize() >= SD.getSize() && "Invalid section sizes!");
1035 MOW.WriteZeros(SD.getFileSize() - SD.getSize());
1036
Daniel Dunbar0705fbf2009-08-21 18:29:01 +00001037 assert(OS.tell() - Start == SD.getFileSize());
1038}
1039
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +00001040void MCAssembler::Finish() {
Daniel Dunbar0705fbf2009-08-21 18:29:01 +00001041 // Layout the sections and fragments.
Daniel Dunbar5e835962009-08-26 02:48:04 +00001042 uint64_t Address = 0;
Daniel Dunbar6742e342009-08-26 04:13:32 +00001043 for (iterator it = begin(), ie = end(); it != ie;) {
1044 MCSectionData &SD = *it;
1045
1046 // Select the amount of padding alignment we need, based on either the next
1047 // sections alignment or the default alignment.
1048 //
1049 // FIXME: This should probably match the native word size.
1050 unsigned NextAlign = 4;
1051 ++it;
1052 if (it != ie)
1053 NextAlign = it->getAlignment();
1054
1055 // Layout the section fragments and its size.
1056 SD.setAddress(Address);
1057 LayoutSection(SD, NextAlign);
1058 Address += SD.getFileSize();
Daniel Dunbar5e835962009-08-26 02:48:04 +00001059 }
Daniel Dunbar0705fbf2009-08-21 18:29:01 +00001060
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +00001061 // Write the object file.
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +00001062 MachObjectWriter MOW(OS);
Daniel Dunbarf3d2ef02009-08-22 10:13:24 +00001063 MOW.WriteObject(*this);
Daniel Dunbar0705fbf2009-08-21 18:29:01 +00001064
Daniel Dunbarfb4a6b32009-08-21 09:11:24 +00001065 OS.flush();
1066}