blob: 93a3dcf8d91991de7415c5320cfec96210759b4d [file] [log] [blame]
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001//===- lib/MC/MachObjectWriter.cpp - Mach-O File Writer -------------------===//
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 Dunbarae5abd52010-12-16 16:09:19 +000010#include "llvm/MC/MCMachObjectWriter.h"
11#include "llvm/ADT/OwningPtr.h"
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000012#include "llvm/ADT/StringMap.h"
13#include "llvm/ADT/Twine.h"
14#include "llvm/MC/MCAssembler.h"
Daniel Dunbar207e06e2010-03-24 03:43:40 +000015#include "llvm/MC/MCAsmLayout.h"
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000016#include "llvm/MC/MCExpr.h"
17#include "llvm/MC/MCObjectWriter.h"
18#include "llvm/MC/MCSectionMachO.h"
19#include "llvm/MC/MCSymbol.h"
Kevin Enderbya6eeb6e2010-05-07 21:44:23 +000020#include "llvm/MC/MCMachOSymbolFlags.h"
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000021#include "llvm/MC/MCValue.h"
Daniel Dunbar821ecd72010-11-27 04:19:38 +000022#include "llvm/Object/MachOFormat.h"
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000023#include "llvm/Support/ErrorHandling.h"
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000024#include "llvm/Target/TargetAsmBackend.h"
25
26// FIXME: Gross.
Daniel Dunbar294e6782010-12-22 16:19:24 +000027#include "../Target/ARM/ARMFixupKinds.h"
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000028#include "../Target/X86/X86FixupKinds.h"
29
30#include <vector>
31using namespace llvm;
Daniel Dunbar821ecd72010-11-27 04:19:38 +000032using namespace llvm::object;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000033
Rafael Espindolaa8c02c32010-09-30 03:11:42 +000034// FIXME: this has been copied from (or to) X86AsmBackend.cpp
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000035static unsigned getFixupKindLog2Size(unsigned Kind) {
36 switch (Kind) {
Jim Grosbachdff84b02010-12-02 00:28:45 +000037 // FIXME: Until ARM has it's own relocation stuff spun off, it comes
38 // through here and we don't want it to puke all over. Any reasonable
39 // values will only come when ARM relocation support gets added, at which
40 // point this will be X86 only again and the llvm_unreachable can be
41 // re-enabled.
42 default: return 0;// llvm_unreachable("invalid fixup kind!");
Rafael Espindolae04ed7e2010-11-28 14:17:56 +000043 case FK_PCRel_1:
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000044 case FK_Data_1: return 0;
Rafael Espindolae04ed7e2010-11-28 14:17:56 +000045 case FK_PCRel_2:
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000046 case FK_Data_2: return 1;
Rafael Espindolae04ed7e2010-11-28 14:17:56 +000047 case FK_PCRel_4:
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000048 case X86::reloc_riprel_4byte:
Daniel Dunbar602b40f2010-03-19 18:07:55 +000049 case X86::reloc_riprel_4byte_movq_load:
Rafael Espindolaa8c02c32010-09-30 03:11:42 +000050 case X86::reloc_signed_4byte:
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000051 case FK_Data_4: return 2;
52 case FK_Data_8: return 3;
53 }
54}
55
Daniel Dunbare9460ec2010-05-10 23:15:13 +000056static bool doesSymbolRequireExternRelocation(MCSymbolData *SD) {
57 // Undefined symbols are always extern.
58 if (SD->Symbol->isUndefined())
59 return true;
60
61 // References to weak definitions require external relocation entries; the
62 // definition may not always be the one in the same object file.
63 if (SD->getFlags() & SF_WeakDefinition)
64 return true;
65
66 // Otherwise, we can use an internal relocation.
67 return false;
68}
69
Rafael Espindola70703872010-09-30 02:22:20 +000070static bool isScatteredFixupFullyResolved(const MCAssembler &Asm,
71 const MCValue Target,
72 const MCSymbolData *BaseSymbol) {
73 // The effective fixup address is
74 // addr(atom(A)) + offset(A)
75 // - addr(atom(B)) - offset(B)
76 // - addr(BaseSymbol) + <fixup offset from base symbol>
77 // and the offsets are not relocatable, so the fixup is fully resolved when
78 // addr(atom(A)) - addr(atom(B)) - addr(BaseSymbol) == 0.
79 //
80 // Note that "false" is almost always conservatively correct (it means we emit
81 // a relocation which is unnecessary), except when it would force us to emit a
82 // relocation which the target cannot encode.
83
84 const MCSymbolData *A_Base = 0, *B_Base = 0;
85 if (const MCSymbolRefExpr *A = Target.getSymA()) {
86 // Modified symbol references cannot be resolved.
87 if (A->getKind() != MCSymbolRefExpr::VK_None)
88 return false;
89
90 A_Base = Asm.getAtom(&Asm.getSymbolData(A->getSymbol()));
91 if (!A_Base)
92 return false;
93 }
94
95 if (const MCSymbolRefExpr *B = Target.getSymB()) {
96 // Modified symbol references cannot be resolved.
97 if (B->getKind() != MCSymbolRefExpr::VK_None)
98 return false;
99
100 B_Base = Asm.getAtom(&Asm.getSymbolData(B->getSymbol()));
101 if (!B_Base)
102 return false;
103 }
104
105 // If there is no base, A and B have to be the same atom for this fixup to be
106 // fully resolved.
107 if (!BaseSymbol)
108 return A_Base == B_Base;
109
110 // Otherwise, B must be missing and A must be the base.
111 return !B_Base && BaseSymbol == A_Base;
112}
113
114static bool isScatteredFixupFullyResolvedSimple(const MCAssembler &Asm,
115 const MCValue Target,
116 const MCSection *BaseSection) {
117 // The effective fixup address is
118 // addr(atom(A)) + offset(A)
119 // - addr(atom(B)) - offset(B)
120 // - addr(<base symbol>) + <fixup offset from base symbol>
121 // and the offsets are not relocatable, so the fixup is fully resolved when
122 // addr(atom(A)) - addr(atom(B)) - addr(<base symbol>)) == 0.
123 //
124 // The simple (Darwin, except on x86_64) way of dealing with this was to
125 // assume that any reference to a temporary symbol *must* be a temporary
126 // symbol in the same atom, unless the sections differ. Therefore, any PCrel
127 // relocation to a temporary symbol (in the same section) is fully
128 // resolved. This also works in conjunction with absolutized .set, which
129 // requires the compiler to use .set to absolutize the differences between
130 // symbols which the compiler knows to be assembly time constants, so we don't
131 // need to worry about considering symbol differences fully resolved.
132
133 // Non-relative fixups are only resolved if constant.
134 if (!BaseSection)
135 return Target.isAbsolute();
136
137 // Otherwise, relative fixups are only resolved if not a difference and the
138 // target is a temporary in the same section.
139 if (Target.isAbsolute() || Target.getSymB())
140 return false;
141
142 const MCSymbol *A = &Target.getSymA()->getSymbol();
143 if (!A->isTemporary() || !A->isInSection() ||
144 &A->getSection() != BaseSection)
145 return false;
146
147 return true;
148}
149
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000150namespace {
151
Daniel Dunbar115a3dd2010-11-13 07:33:40 +0000152class MachObjectWriter : public MCObjectWriter {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000153 /// MachSymbolData - Helper struct for containing some precomputed information
154 /// on symbols.
155 struct MachSymbolData {
156 MCSymbolData *SymbolData;
157 uint64_t StringIndex;
158 uint8_t SectionIndex;
159
160 // Support lexicographic sorting.
161 bool operator<(const MachSymbolData &RHS) const {
Benjamin Kramerc37791e2010-05-20 14:14:22 +0000162 return SymbolData->getSymbol().getName() <
163 RHS.SymbolData->getSymbol().getName();
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000164 }
165 };
166
Daniel Dunbarae5abd52010-12-16 16:09:19 +0000167 /// The target specific Mach-O writer instance.
168 llvm::OwningPtr<MCMachObjectTargetWriter> TargetObjectWriter;
Daniel Dunbar7e06af82010-12-16 15:42:31 +0000169
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000170 /// @name Relocation Data
171 /// @{
172
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000173 llvm::DenseMap<const MCSectionData*,
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +0000174 std::vector<macho::RelocationEntry> > Relocations;
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +0000175 llvm::DenseMap<const MCSectionData*, unsigned> IndirectSymBase;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000176
177 /// @}
178 /// @name Symbol Table Data
179 /// @{
180
181 SmallString<256> StringTable;
182 std::vector<MachSymbolData> LocalSymbolData;
183 std::vector<MachSymbolData> ExternalSymbolData;
184 std::vector<MachSymbolData> UndefinedSymbolData;
185
186 /// @}
187
Daniel Dunbarae5abd52010-12-16 16:09:19 +0000188private:
189 /// @name Utility Methods
190 /// @{
191
192 bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) {
193 const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo(
194 (MCFixupKind) Kind);
195
196 return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel;
197 }
198
199 /// @}
200
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000201 SectionAddrMap SectionAddress;
202 uint64_t getSectionAddress(const MCSectionData* SD) const {
203 return SectionAddress.lookup(SD);
204 }
205 uint64_t getSymbolAddress(const MCSymbolData* SD,
206 const MCAsmLayout &Layout) const {
207 return getSectionAddress(SD->getFragment()->getParent()) +
208 Layout.getSymbolOffset(SD);
209 }
210 uint64_t getFragmentAddress(const MCFragment *Fragment,
211 const MCAsmLayout &Layout) const {
212 return getSectionAddress(Fragment->getParent()) +
213 Layout.getFragmentOffset(Fragment);
214 }
215
216 uint64_t getPaddingSize(const MCSectionData *SD,
217 const MCAsmLayout &Layout) const {
218 uint64_t EndAddr = getSectionAddress(SD) + Layout.getSectionAddressSize(SD);
219 unsigned Next = SD->getLayoutOrder() + 1;
220 if (Next >= Layout.getSectionOrder().size())
221 return 0;
222
223 const MCSectionData &NextSD = *Layout.getSectionOrder()[Next];
224 if (NextSD.getSection().isVirtualSection())
225 return 0;
226 return OffsetToAlignment(EndAddr, NextSD.getAlignment());
227 }
228
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000229public:
Daniel Dunbarae5abd52010-12-16 16:09:19 +0000230 MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS,
Daniel Dunbar115a3dd2010-11-13 07:33:40 +0000231 bool _IsLittleEndian)
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000232 : MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000233 }
234
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000235 /// @name Target Writer Proxy Accessors
236 /// @{
237
238 bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
Daniel Dunbar532c4562010-12-22 13:49:43 +0000239 bool isARM() const {
Daniel Dunbarfdfbc6a2010-12-22 16:19:20 +0000240 uint32_t CPUType = TargetObjectWriter->getCPUType() & ~mach::CTFM_ArchMask;
Daniel Dunbar532c4562010-12-22 13:49:43 +0000241 return CPUType == mach::CTM_ARM;
242 }
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000243
244 /// @}
245
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000246 void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
247 bool SubsectionsViaSymbols) {
248 uint32_t Flags = 0;
249
250 if (SubsectionsViaSymbols)
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000251 Flags |= macho::HF_SubsectionsViaSymbols;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000252
253 // struct mach_header (28 bytes) or
254 // struct mach_header_64 (32 bytes)
255
256 uint64_t Start = OS.tell();
257 (void) Start;
258
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000259 Write32(is64Bit() ? macho::HM_Object64 : macho::HM_Object32);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000260
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000261 Write32(TargetObjectWriter->getCPUType());
262 Write32(TargetObjectWriter->getCPUSubtype());
Jim Grosbachc9d14392010-11-05 18:48:58 +0000263
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000264 Write32(macho::HFT_Object);
Daniel Dunbar590956f2010-11-27 07:39:37 +0000265 Write32(NumLoadCommands);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000266 Write32(LoadCommandsSize);
267 Write32(Flags);
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000268 if (is64Bit())
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000269 Write32(0); // reserved
270
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000271 assert(OS.tell() - Start == is64Bit() ?
Daniel Dunbar821ecd72010-11-27 04:19:38 +0000272 macho::Header64Size : macho::Header32Size);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000273 }
274
275 /// WriteSegmentLoadCommand - Write a segment load command.
276 ///
277 /// \arg NumSections - The number of sections in this segment.
278 /// \arg SectionDataSize - The total size of the sections.
279 void WriteSegmentLoadCommand(unsigned NumSections,
280 uint64_t VMSize,
281 uint64_t SectionDataStartOffset,
282 uint64_t SectionDataSize) {
283 // struct segment_command (56 bytes) or
284 // struct segment_command_64 (72 bytes)
285
286 uint64_t Start = OS.tell();
287 (void) Start;
288
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000289 unsigned SegmentLoadCommandSize =
290 is64Bit() ? macho::SegmentLoadCommand64Size:
Daniel Dunbar821ecd72010-11-27 04:19:38 +0000291 macho::SegmentLoadCommand32Size;
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000292 Write32(is64Bit() ? macho::LCT_Segment64 : macho::LCT_Segment);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000293 Write32(SegmentLoadCommandSize +
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000294 NumSections * (is64Bit() ? macho::Section64Size :
Daniel Dunbar821ecd72010-11-27 04:19:38 +0000295 macho::Section32Size));
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000296
297 WriteBytes("", 16);
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000298 if (is64Bit()) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000299 Write64(0); // vmaddr
300 Write64(VMSize); // vmsize
301 Write64(SectionDataStartOffset); // file offset
302 Write64(SectionDataSize); // file size
303 } else {
304 Write32(0); // vmaddr
305 Write32(VMSize); // vmsize
306 Write32(SectionDataStartOffset); // file offset
307 Write32(SectionDataSize); // file size
308 }
309 Write32(0x7); // maxprot
310 Write32(0x7); // initprot
311 Write32(NumSections);
312 Write32(0); // flags
313
314 assert(OS.tell() - Start == SegmentLoadCommandSize);
315 }
316
Daniel Dunbar207e06e2010-03-24 03:43:40 +0000317 void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
318 const MCSectionData &SD, uint64_t FileOffset,
319 uint64_t RelocationsStart, unsigned NumRelocations) {
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000320 uint64_t SectionSize = Layout.getSectionAddressSize(&SD);
Daniel Dunbar5d428512010-03-25 02:00:07 +0000321
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000322 // The offset is unused for virtual sections.
Rafael Espindolaf2dc4aa2010-11-17 20:03:54 +0000323 if (SD.getSection().isVirtualSection()) {
Daniel Dunbarb026d642010-03-25 07:10:05 +0000324 assert(Layout.getSectionFileSize(&SD) == 0 && "Invalid file size!");
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000325 FileOffset = 0;
326 }
327
328 // struct section (68 bytes) or
329 // struct section_64 (80 bytes)
330
331 uint64_t Start = OS.tell();
332 (void) Start;
333
Daniel Dunbar56279f42010-05-18 17:28:20 +0000334 const MCSectionMachO &Section = cast<MCSectionMachO>(SD.getSection());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000335 WriteBytes(Section.getSectionName(), 16);
336 WriteBytes(Section.getSegmentName(), 16);
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000337 if (is64Bit()) {
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000338 Write64(getSectionAddress(&SD)); // address
Daniel Dunbar5d428512010-03-25 02:00:07 +0000339 Write64(SectionSize); // size
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000340 } else {
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000341 Write32(getSectionAddress(&SD)); // address
Daniel Dunbar5d428512010-03-25 02:00:07 +0000342 Write32(SectionSize); // size
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000343 }
344 Write32(FileOffset);
345
346 unsigned Flags = Section.getTypeAndAttributes();
347 if (SD.hasInstructions())
348 Flags |= MCSectionMachO::S_ATTR_SOME_INSTRUCTIONS;
349
350 assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!");
351 Write32(Log2_32(SD.getAlignment()));
352 Write32(NumRelocations ? RelocationsStart : 0);
353 Write32(NumRelocations);
354 Write32(Flags);
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +0000355 Write32(IndirectSymBase.lookup(&SD)); // reserved1
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000356 Write32(Section.getStubSize()); // reserved2
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000357 if (is64Bit())
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000358 Write32(0); // reserved3
359
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000360 assert(OS.tell() - Start == is64Bit() ? macho::Section64Size :
Daniel Dunbar821ecd72010-11-27 04:19:38 +0000361 macho::Section32Size);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000362 }
363
364 void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
365 uint32_t StringTableOffset,
366 uint32_t StringTableSize) {
367 // struct symtab_command (24 bytes)
368
369 uint64_t Start = OS.tell();
370 (void) Start;
371
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000372 Write32(macho::LCT_Symtab);
Daniel Dunbar821ecd72010-11-27 04:19:38 +0000373 Write32(macho::SymtabLoadCommandSize);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000374 Write32(SymbolOffset);
375 Write32(NumSymbols);
376 Write32(StringTableOffset);
377 Write32(StringTableSize);
378
Daniel Dunbar821ecd72010-11-27 04:19:38 +0000379 assert(OS.tell() - Start == macho::SymtabLoadCommandSize);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000380 }
381
382 void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
383 uint32_t NumLocalSymbols,
384 uint32_t FirstExternalSymbol,
385 uint32_t NumExternalSymbols,
386 uint32_t FirstUndefinedSymbol,
387 uint32_t NumUndefinedSymbols,
388 uint32_t IndirectSymbolOffset,
389 uint32_t NumIndirectSymbols) {
390 // struct dysymtab_command (80 bytes)
391
392 uint64_t Start = OS.tell();
393 (void) Start;
394
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000395 Write32(macho::LCT_Dysymtab);
Daniel Dunbar821ecd72010-11-27 04:19:38 +0000396 Write32(macho::DysymtabLoadCommandSize);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000397 Write32(FirstLocalSymbol);
398 Write32(NumLocalSymbols);
399 Write32(FirstExternalSymbol);
400 Write32(NumExternalSymbols);
401 Write32(FirstUndefinedSymbol);
402 Write32(NumUndefinedSymbols);
403 Write32(0); // tocoff
404 Write32(0); // ntoc
405 Write32(0); // modtaboff
406 Write32(0); // nmodtab
407 Write32(0); // extrefsymoff
408 Write32(0); // nextrefsyms
409 Write32(IndirectSymbolOffset);
410 Write32(NumIndirectSymbols);
411 Write32(0); // extreloff
412 Write32(0); // nextrel
413 Write32(0); // locreloff
414 Write32(0); // nlocrel
415
Daniel Dunbar821ecd72010-11-27 04:19:38 +0000416 assert(OS.tell() - Start == macho::DysymtabLoadCommandSize);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000417 }
418
Daniel Dunbar207e06e2010-03-24 03:43:40 +0000419 void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000420 MCSymbolData &Data = *MSD.SymbolData;
421 const MCSymbol &Symbol = Data.getSymbol();
422 uint8_t Type = 0;
423 uint16_t Flags = Data.getFlags();
424 uint32_t Address = 0;
425
426 // Set the N_TYPE bits. See <mach-o/nlist.h>.
427 //
428 // FIXME: Are the prebound or indirect fields possible here?
429 if (Symbol.isUndefined())
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000430 Type = macho::STT_Undefined;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000431 else if (Symbol.isAbsolute())
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000432 Type = macho::STT_Absolute;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000433 else
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000434 Type = macho::STT_Section;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000435
436 // FIXME: Set STAB bits.
437
438 if (Data.isPrivateExtern())
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000439 Type |= macho::STF_PrivateExtern;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000440
441 // Set external bit.
442 if (Data.isExternal() || Symbol.isUndefined())
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000443 Type |= macho::STF_External;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000444
445 // Compute the symbol address.
446 if (Symbol.isDefined()) {
447 if (Symbol.isAbsolute()) {
Daniel Dunbar2d7fd612010-05-05 19:01:05 +0000448 Address = cast<MCConstantExpr>(Symbol.getVariableValue())->getValue();
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000449 } else {
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000450 Address = getSymbolAddress(&Data, Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000451 }
452 } else if (Data.isCommon()) {
453 // Common symbols are encoded with the size in the address
454 // field, and their alignment in the flags.
455 Address = Data.getCommonSize();
456
457 // Common alignment is packed into the 'desc' bits.
458 if (unsigned Align = Data.getCommonAlignment()) {
459 unsigned Log2Size = Log2_32(Align);
460 assert((1U << Log2Size) == Align && "Invalid 'common' alignment!");
461 if (Log2Size > 15)
Chris Lattner75361b62010-04-07 22:58:41 +0000462 report_fatal_error("invalid 'common' alignment '" +
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000463 Twine(Align) + "'");
464 // FIXME: Keep this mask with the SymbolFlags enumeration.
465 Flags = (Flags & 0xF0FF) | (Log2Size << 8);
466 }
467 }
468
469 // struct nlist (12 bytes)
470
471 Write32(MSD.StringIndex);
472 Write8(Type);
473 Write8(MSD.SectionIndex);
474
475 // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
476 // value.
477 Write16(Flags);
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000478 if (is64Bit())
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000479 Write64(Address);
480 else
481 Write32(Address);
482 }
483
Daniel Dunbar35b06572010-03-22 23:16:43 +0000484 // FIXME: We really need to improve the relocation validation. Basically, we
485 // want to implement a separate computation which evaluates the relocation
486 // entry as the linker would, and verifies that the resultant fixup value is
487 // exactly what the encoder wanted. This will catch several classes of
488 // problems:
489 //
490 // - Relocation entry bugs, the two algorithms are unlikely to have the same
491 // exact bug.
492 //
493 // - Relaxation issues, where we forget to relax something.
494 //
495 // - Input errors, where something cannot be correctly encoded. 'as' allows
496 // these through in many cases.
497
Daniel Dunbar7e06af82010-12-16 15:42:31 +0000498 static bool isFixupKindRIPRel(unsigned Kind) {
499 return Kind == X86::reloc_riprel_4byte ||
500 Kind == X86::reloc_riprel_4byte_movq_load;
501 }
Daniel Dunbar207e06e2010-03-24 03:43:40 +0000502 void RecordX86_64Relocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
Daniel Dunbarb7514182010-03-22 20:35:50 +0000503 const MCFragment *Fragment,
Daniel Dunbarc90e30a2010-05-26 15:18:56 +0000504 const MCFixup &Fixup, MCValue Target,
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000505 uint64_t &FixedValue) {
Daniel Dunbar7e06af82010-12-16 15:42:31 +0000506 unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
Daniel Dunbar482ad802010-05-26 15:18:31 +0000507 unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind());
508 unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000509
510 // See <reloc.h>.
Daniel Dunbar482ad802010-05-26 15:18:31 +0000511 uint32_t FixupOffset =
512 Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
513 uint32_t FixupAddress =
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000514 getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000515 int64_t Value = 0;
516 unsigned Index = 0;
517 unsigned IsExtern = 0;
518 unsigned Type = 0;
519
520 Value = Target.getConstant();
521
522 if (IsPCRel) {
523 // Compensate for the relocation offset, Darwin x86_64 relocations only
524 // have the addend and appear to have attempted to define it to be the
525 // actual expression addend without the PCrel bias. However, instructions
526 // with data following the relocation are not accomodated for (see comment
527 // below regarding SIGNED{1,2,4}), so it isn't exactly that either.
Benjamin Kramer454c4ce2010-04-08 15:25:57 +0000528 Value += 1LL << Log2Size;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000529 }
530
531 if (Target.isAbsolute()) { // constant
532 // SymbolNum of 0 indicates the absolute section.
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000533 Type = macho::RIT_X86_64_Unsigned;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000534 Index = 0;
535
536 // FIXME: I believe this is broken, I don't think the linker can
537 // understand it. I think it would require a local relocation, but I'm not
538 // sure if that would work either. The official way to get an absolute
539 // PCrel relocation is to use an absolute symbol (which we don't support
540 // yet).
541 if (IsPCRel) {
542 IsExtern = 1;
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000543 Type = macho::RIT_X86_64_Branch;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000544 }
545 } else if (Target.getSymB()) { // A - B + constant
546 const MCSymbol *A = &Target.getSymA()->getSymbol();
547 MCSymbolData &A_SD = Asm.getSymbolData(*A);
Rafael Espindolab8141102010-09-27 18:13:03 +0000548 const MCSymbolData *A_Base = Asm.getAtom(&A_SD);
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000549
550 const MCSymbol *B = &Target.getSymB()->getSymbol();
551 MCSymbolData &B_SD = Asm.getSymbolData(*B);
Rafael Espindolab8141102010-09-27 18:13:03 +0000552 const MCSymbolData *B_Base = Asm.getAtom(&B_SD);
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000553
554 // Neither symbol can be modified.
555 if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
556 Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None)
Chris Lattner75361b62010-04-07 22:58:41 +0000557 report_fatal_error("unsupported relocation of modified symbol");
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000558
559 // We don't support PCrel relocations of differences. Darwin 'as' doesn't
560 // implement most of these correctly.
561 if (IsPCRel)
Chris Lattner75361b62010-04-07 22:58:41 +0000562 report_fatal_error("unsupported pc-relative relocation of difference");
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000563
Kevin Enderby8c9aa922010-10-02 00:13:41 +0000564 // The support for the situation where one or both of the symbols would
565 // require a local relocation is handled just like if the symbols were
566 // external. This is certainly used in the case of debug sections where
567 // the section has only temporary symbols and thus the symbols don't have
568 // base symbols. This is encoded using the section ordinal and
569 // non-extern relocation entries.
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000570
571 // Darwin 'as' doesn't emit correct relocations for this (it ends up with
Kevin Enderby8c9aa922010-10-02 00:13:41 +0000572 // a single SIGNED relocation); reject it for now. Except the case where
573 // both symbols don't have a base, equal but both NULL.
574 if (A_Base == B_Base && A_Base)
Chris Lattner75361b62010-04-07 22:58:41 +0000575 report_fatal_error("unsupported relocation with identical base");
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000576
Rafael Espindolaf10d2be2010-12-07 01:09:54 +0000577 Value += getSymbolAddress(&A_SD, Layout) -
578 (A_Base == NULL ? 0 : getSymbolAddress(A_Base, Layout));
579 Value -= getSymbolAddress(&B_SD, Layout) -
580 (B_Base == NULL ? 0 : getSymbolAddress(B_Base, Layout));
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000581
Kevin Enderby8c9aa922010-10-02 00:13:41 +0000582 if (A_Base) {
583 Index = A_Base->getIndex();
584 IsExtern = 1;
585 }
586 else {
587 Index = A_SD.getFragment()->getParent()->getOrdinal() + 1;
588 IsExtern = 0;
589 }
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000590 Type = macho::RIT_X86_64_Unsigned;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000591
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +0000592 macho::RelocationEntry MRE;
Daniel Dunbar640e9482010-05-11 23:53:07 +0000593 MRE.Word0 = FixupOffset;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000594 MRE.Word1 = ((Index << 0) |
595 (IsPCRel << 24) |
596 (Log2Size << 25) |
597 (IsExtern << 27) |
598 (Type << 28));
Daniel Dunbarb7514182010-03-22 20:35:50 +0000599 Relocations[Fragment->getParent()].push_back(MRE);
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000600
Kevin Enderby8c9aa922010-10-02 00:13:41 +0000601 if (B_Base) {
602 Index = B_Base->getIndex();
603 IsExtern = 1;
604 }
605 else {
606 Index = B_SD.getFragment()->getParent()->getOrdinal() + 1;
607 IsExtern = 0;
608 }
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000609 Type = macho::RIT_X86_64_Subtractor;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000610 } else {
611 const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
612 MCSymbolData &SD = Asm.getSymbolData(*Symbol);
Rafael Espindolab8141102010-09-27 18:13:03 +0000613 const MCSymbolData *Base = Asm.getAtom(&SD);
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000614
Daniel Dunbarae7fb0b2010-05-05 17:22:39 +0000615 // Relocations inside debug sections always use local relocations when
616 // possible. This seems to be done because the debugger doesn't fully
617 // understand x86_64 relocation entries, and expects to find values that
618 // have already been fixed up.
Daniel Dunbar2d7fd612010-05-05 19:01:05 +0000619 if (Symbol->isInSection()) {
Daniel Dunbarae7fb0b2010-05-05 17:22:39 +0000620 const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(
621 Fragment->getParent()->getSection());
622 if (Section.hasAttribute(MCSectionMachO::S_ATTR_DEBUG))
623 Base = 0;
624 }
625
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000626 // x86_64 almost always uses external relocations, except when there is no
627 // symbol to use as a base address (a local symbol with no preceeding
628 // non-local symbol).
629 if (Base) {
630 Index = Base->getIndex();
631 IsExtern = 1;
632
633 // Add the local offset, if needed.
634 if (Base != &SD)
Rafael Espindola1dda29b2010-12-06 21:51:55 +0000635 Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base);
Daniel Dunbaref4591e2010-05-11 23:53:05 +0000636 } else if (Symbol->isInSection()) {
Daniel Dunbar8fb04032010-03-25 08:08:54 +0000637 // The index is the section ordinal (1-based).
638 Index = SD.getFragment()->getParent()->getOrdinal() + 1;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000639 IsExtern = 0;
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000640 Value += getSymbolAddress(&SD, Layout);
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000641
642 if (IsPCRel)
Daniel Dunbardb4c7e62010-05-11 23:53:11 +0000643 Value -= FixupAddress + (1 << Log2Size);
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000644 } else if (Symbol->isVariable()) {
645 const MCExpr *Value = Symbol->getVariableValue();
646 int64_t Res;
647 bool isAbs = Value->EvaluateAsAbsolute(Res, Layout, SectionAddress);
648 if (isAbs) {
649 FixedValue = Res;
650 return;
651 } else {
652 report_fatal_error("unsupported relocation of variable '" +
653 Symbol->getName() + "'");
654 }
Daniel Dunbaref4591e2010-05-11 23:53:05 +0000655 } else {
656 report_fatal_error("unsupported relocation of undefined symbol '" +
657 Symbol->getName() + "'");
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000658 }
659
660 MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind();
661 if (IsPCRel) {
662 if (IsRIPRel) {
663 if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
664 // x86_64 distinguishes movq foo@GOTPCREL so that the linker can
665 // rewrite the movq to an leaq at link time if the symbol ends up in
666 // the same linkage unit.
Daniel Dunbar482ad802010-05-26 15:18:31 +0000667 if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load)
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000668 Type = macho::RIT_X86_64_GOTLoad;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000669 else
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000670 Type = macho::RIT_X86_64_GOT;
Eric Christopheraeed4d82010-05-27 00:52:31 +0000671 } else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000672 Type = macho::RIT_X86_64_TLV;
Eric Christopheraeed4d82010-05-27 00:52:31 +0000673 } else if (Modifier != MCSymbolRefExpr::VK_None) {
674 report_fatal_error("unsupported symbol modifier in relocation");
Daniel Dunbarf0f6cdb2010-05-14 18:53:40 +0000675 } else {
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000676 Type = macho::RIT_X86_64_Signed;
Daniel Dunbarf0f6cdb2010-05-14 18:53:40 +0000677
678 // The Darwin x86_64 relocation format has a problem where it cannot
679 // encode an address (L<foo> + <constant>) which is outside the atom
680 // containing L<foo>. Generally, this shouldn't occur but it does
681 // happen when we have a RIPrel instruction with data following the
682 // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel
683 // adjustment Darwin x86_64 uses, the offset is still negative and
684 // the linker has no way to recognize this.
685 //
686 // To work around this, Darwin uses several special relocation types
687 // to indicate the offsets. However, the specification or
688 // implementation of these seems to also be incomplete; they should
689 // adjust the addend as well based on the actual encoded instruction
690 // (the additional bias), but instead appear to just look at the
691 // final offset.
692 switch (-(Target.getConstant() + (1LL << Log2Size))) {
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000693 case 1: Type = macho::RIT_X86_64_Signed1; break;
694 case 2: Type = macho::RIT_X86_64_Signed2; break;
695 case 4: Type = macho::RIT_X86_64_Signed4; break;
Daniel Dunbarf0f6cdb2010-05-14 18:53:40 +0000696 }
697 }
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000698 } else {
699 if (Modifier != MCSymbolRefExpr::VK_None)
Chris Lattner75361b62010-04-07 22:58:41 +0000700 report_fatal_error("unsupported symbol modifier in branch "
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000701 "relocation");
702
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000703 Type = macho::RIT_X86_64_Branch;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000704 }
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000705 } else {
Daniel Dunbar1de558b2010-03-29 23:56:40 +0000706 if (Modifier == MCSymbolRefExpr::VK_GOT) {
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000707 Type = macho::RIT_X86_64_GOT;
Daniel Dunbar1de558b2010-03-29 23:56:40 +0000708 } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
709 // GOTPCREL is allowed as a modifier on non-PCrel instructions, in
710 // which case all we do is set the PCrel bit in the relocation entry;
711 // this is used with exception handling, for example. The source is
712 // required to include any necessary offset directly.
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000713 Type = macho::RIT_X86_64_GOT;
Daniel Dunbar1de558b2010-03-29 23:56:40 +0000714 IsPCRel = 1;
Eric Christopher96ac5152010-05-26 00:02:12 +0000715 } else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
716 report_fatal_error("TLVP symbol modifier should have been rip-rel");
Daniel Dunbar1de558b2010-03-29 23:56:40 +0000717 } else if (Modifier != MCSymbolRefExpr::VK_None)
Chris Lattner75361b62010-04-07 22:58:41 +0000718 report_fatal_error("unsupported symbol modifier in relocation");
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000719 else
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000720 Type = macho::RIT_X86_64_Unsigned;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000721 }
722 }
723
724 // x86_64 always writes custom values into the fixups.
725 FixedValue = Value;
726
727 // struct relocation_info (8 bytes)
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +0000728 macho::RelocationEntry MRE;
Daniel Dunbar640e9482010-05-11 23:53:07 +0000729 MRE.Word0 = FixupOffset;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000730 MRE.Word1 = ((Index << 0) |
731 (IsPCRel << 24) |
732 (Log2Size << 25) |
733 (IsExtern << 27) |
734 (Type << 28));
Daniel Dunbarb7514182010-03-22 20:35:50 +0000735 Relocations[Fragment->getParent()].push_back(MRE);
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000736 }
737
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000738 void RecordScatteredRelocation(const MCAssembler &Asm,
Daniel Dunbar207e06e2010-03-24 03:43:40 +0000739 const MCAsmLayout &Layout,
Daniel Dunbarb7514182010-03-22 20:35:50 +0000740 const MCFragment *Fragment,
Daniel Dunbarc90e30a2010-05-26 15:18:56 +0000741 const MCFixup &Fixup, MCValue Target,
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000742 uint64_t &FixedValue) {
Daniel Dunbar482ad802010-05-26 15:18:31 +0000743 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
Daniel Dunbar7e06af82010-12-16 15:42:31 +0000744 unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
Daniel Dunbar482ad802010-05-26 15:18:31 +0000745 unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000746 unsigned Type = macho::RIT_Vanilla;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000747
748 // See <reloc.h>.
749 const MCSymbol *A = &Target.getSymA()->getSymbol();
750 MCSymbolData *A_SD = &Asm.getSymbolData(*A);
751
752 if (!A_SD->getFragment())
Chris Lattner75361b62010-04-07 22:58:41 +0000753 report_fatal_error("symbol '" + A->getName() +
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000754 "' can not be undefined in a subtraction expression");
755
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000756 uint32_t Value = getSymbolAddress(A_SD, Layout);
757 uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent());
758 FixedValue += SecAddr;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000759 uint32_t Value2 = 0;
760
761 if (const MCSymbolRefExpr *B = Target.getSymB()) {
762 MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
763
764 if (!B_SD->getFragment())
Chris Lattner75361b62010-04-07 22:58:41 +0000765 report_fatal_error("symbol '" + B->getSymbol().getName() +
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000766 "' can not be undefined in a subtraction expression");
767
768 // Select the appropriate difference relocation type.
769 //
770 // Note that there is no longer any semantic difference between these two
771 // relocation types from the linkers point of view, this is done solely
772 // for pedantic compatibility with 'as'.
Matt Beaumont-Gaye733cf82010-12-21 23:43:23 +0000773 Type = A_SD->isExternal() ? (unsigned)macho::RIT_Difference :
774 (unsigned)macho::RIT_Generic_LocalDifference;
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000775 Value2 = getSymbolAddress(B_SD, Layout);
776 FixedValue -= getSectionAddress(B_SD->getFragment()->getParent());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000777 }
778
779 // Relocations are written out in reverse order, so the PAIR comes first.
Daniel Dunbare1feeb92010-12-21 15:26:45 +0000780 if (Type == macho::RIT_Difference ||
781 Type == macho::RIT_Generic_LocalDifference) {
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +0000782 macho::RelocationEntry MRE;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000783 MRE.Word0 = ((0 << 0) |
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000784 (macho::RIT_Pair << 24) |
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000785 (Log2Size << 28) |
786 (IsPCRel << 30) |
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000787 macho::RF_Scattered);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000788 MRE.Word1 = Value2;
Daniel Dunbarb7514182010-03-22 20:35:50 +0000789 Relocations[Fragment->getParent()].push_back(MRE);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000790 }
791
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +0000792 macho::RelocationEntry MRE;
Daniel Dunbar640e9482010-05-11 23:53:07 +0000793 MRE.Word0 = ((FixupOffset << 0) |
794 (Type << 24) |
795 (Log2Size << 28) |
796 (IsPCRel << 30) |
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000797 macho::RF_Scattered);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000798 MRE.Word1 = Value;
Daniel Dunbarb7514182010-03-22 20:35:50 +0000799 Relocations[Fragment->getParent()].push_back(MRE);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000800 }
801
Eric Christopherc9ada472010-06-15 22:59:05 +0000802 void RecordTLVPRelocation(const MCAssembler &Asm,
Eric Christophere48dbf82010-06-16 00:26:36 +0000803 const MCAsmLayout &Layout,
804 const MCFragment *Fragment,
805 const MCFixup &Fixup, MCValue Target,
806 uint64_t &FixedValue) {
Eric Christopherc9ada472010-06-15 22:59:05 +0000807 assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP &&
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000808 !is64Bit() &&
Eric Christopherc9ada472010-06-15 22:59:05 +0000809 "Should only be called with a 32-bit TLVP relocation!");
810
Eric Christopherc9ada472010-06-15 22:59:05 +0000811 unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
812 uint32_t Value = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
813 unsigned IsPCRel = 0;
814
815 // Get the symbol data.
816 MCSymbolData *SD_A = &Asm.getSymbolData(Target.getSymA()->getSymbol());
817 unsigned Index = SD_A->getIndex();
818
Eric Christopherbc067372010-06-16 21:32:38 +0000819 // We're only going to have a second symbol in pic mode and it'll be a
820 // subtraction from the picbase. For 32-bit pic the addend is the difference
Eric Christopher04b8d3c2010-06-17 00:49:46 +0000821 // between the picbase and the next address. For 32-bit static the addend
822 // is zero.
Eric Christopherbc067372010-06-16 21:32:38 +0000823 if (Target.getSymB()) {
Eric Christopher1008d352010-06-22 23:51:47 +0000824 // If this is a subtraction then we're pcrel.
825 uint32_t FixupAddress =
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000826 getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
Eric Christopher1008d352010-06-22 23:51:47 +0000827 MCSymbolData *SD_B = &Asm.getSymbolData(Target.getSymB()->getSymbol());
Eric Christopherc9ada472010-06-15 22:59:05 +0000828 IsPCRel = 1;
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000829 FixedValue = (FixupAddress - getSymbolAddress(SD_B, Layout) +
Eric Christopher1008d352010-06-22 23:51:47 +0000830 Target.getConstant());
Chris Lattnerabf8f9c2010-08-16 16:35:20 +0000831 FixedValue += 1ULL << Log2Size;
Eric Christopherbc067372010-06-16 21:32:38 +0000832 } else {
833 FixedValue = 0;
834 }
Jim Grosbach3c384922010-11-11 20:16:23 +0000835
Eric Christopherc9ada472010-06-15 22:59:05 +0000836 // struct relocation_info (8 bytes)
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +0000837 macho::RelocationEntry MRE;
Eric Christopherc9ada472010-06-15 22:59:05 +0000838 MRE.Word0 = Value;
Daniel Dunbare1feeb92010-12-21 15:26:45 +0000839 MRE.Word1 = ((Index << 0) |
840 (IsPCRel << 24) |
841 (Log2Size << 25) |
842 (1 << 27) | // Extern
843 (macho::RIT_Generic_TLV << 28)); // Type
Eric Christopherc9ada472010-06-15 22:59:05 +0000844 Relocations[Fragment->getParent()].push_back(MRE);
845 }
Jim Grosbach3c384922010-11-11 20:16:23 +0000846
Daniel Dunbar294e6782010-12-22 16:19:24 +0000847 static bool getARMFixupKindMachOInfo(unsigned Kind, bool &Is24BitBranch,
848 unsigned &Log2Size) {
849 switch (Kind) {
850 default:
851 return false;
852
853 // Handle 24-bit branch kinds.
854 case ARM::fixup_arm_ldst_pcrel_12:
855 case ARM::fixup_arm_pcrel_10:
856 case ARM::fixup_arm_adr_pcrel_12:
857 case ARM::fixup_arm_branch:
858 Is24BitBranch = true;
859 // Report as 'long', even though that is not quite accurate.
860 Log2Size = llvm::Log2_32(4);
861 return true;
862 }
863 }
Daniel Dunbar532c4562010-12-22 13:49:43 +0000864 void RecordARMRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
865 const MCFragment *Fragment, const MCFixup &Fixup,
866 MCValue Target, uint64_t &FixedValue) {
Daniel Dunbar4d743052010-12-22 13:50:05 +0000867 unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
Daniel Dunbar294e6782010-12-22 16:19:24 +0000868 unsigned Log2Size;
869 bool Is24BitBranch;
870 if (!getARMFixupKindMachOInfo(Fixup.getKind(), Is24BitBranch, Log2Size)) {
871 report_fatal_error("unknown ARM fixup kind!");
872 return;
873 }
Daniel Dunbar4d743052010-12-22 13:50:05 +0000874
875 // If this is a difference or a defined symbol plus an offset, then we need
876 // a scattered relocation entry. Differences always require scattered
877 // relocations.
878 if (Target.getSymB())
879 return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
880 Target, FixedValue);
881
882 // Get the symbol data, if any.
883 MCSymbolData *SD = 0;
884 if (Target.getSymA())
885 SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
886
887 // FIXME: For other platforms, we need to use scattered relocations for
888 // internal relocations with offsets. If this is an internal relocation
889 // with an offset, it also needs a scattered relocation entry.
890 //
891 // Is this right for ARM?
892 uint32_t Offset = Target.getConstant();
893 if (IsPCRel)
894 Offset += 1 << Log2Size;
895 if (Offset && SD && !doesSymbolRequireExternRelocation(SD))
896 return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
897 Target, FixedValue);
898
899 // See <reloc.h>.
900 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
901 unsigned Index = 0;
902 unsigned IsExtern = 0;
903 unsigned Type = 0;
904
905 if (Target.isAbsolute()) { // constant
906 // FIXME!
907 report_fatal_error("FIXME: relocations to absolute targets "
908 "not yet implemented");
909 } else if (SD->getSymbol().isVariable()) {
910 int64_t Res;
911 if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
912 Res, Layout, SectionAddress)) {
913 FixedValue = Res;
914 return;
915 }
916
917 report_fatal_error("unsupported relocation of variable '" +
918 SD->getSymbol().getName() + "'");
919 } else {
920 // Check whether we need an external or internal relocation.
921 if (doesSymbolRequireExternRelocation(SD)) {
922 IsExtern = 1;
923 Index = SD->getIndex();
924 // For external relocations, make sure to offset the fixup value to
925 // compensate for the addend of the symbol address, if it was
926 // undefined. This occurs with weak definitions, for example.
927 if (!SD->Symbol->isUndefined())
928 FixedValue -= Layout.getSymbolOffset(SD);
929 } else {
930 // The index is the section ordinal (1-based).
931 Index = SD->getFragment()->getParent()->getOrdinal() + 1;
932 FixedValue += getSectionAddress(SD->getFragment()->getParent());
933 }
934 if (IsPCRel)
935 FixedValue -= getSectionAddress(Fragment->getParent());
936
Daniel Dunbar294e6782010-12-22 16:19:24 +0000937 // Determine the appropriate type based on the fixup kind.
938 Type = Is24BitBranch ? macho::RIT_ARM_Branch24Bit : macho::RIT_Vanilla;
Daniel Dunbar4d743052010-12-22 13:50:05 +0000939 }
940
941 // struct relocation_info (8 bytes)
942 macho::RelocationEntry MRE;
943 MRE.Word0 = FixupOffset;
944 MRE.Word1 = ((Index << 0) |
945 (IsPCRel << 24) |
946 (Log2Size << 25) |
947 (IsExtern << 27) |
948 (Type << 28));
949 Relocations[Fragment->getParent()].push_back(MRE);
Daniel Dunbar532c4562010-12-22 13:49:43 +0000950 }
951
Daniel Dunbar207e06e2010-03-24 03:43:40 +0000952 void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
Daniel Dunbarc90e30a2010-05-26 15:18:56 +0000953 const MCFragment *Fragment, const MCFixup &Fixup,
Daniel Dunbar207e06e2010-03-24 03:43:40 +0000954 MCValue Target, uint64_t &FixedValue) {
Daniel Dunbar532c4562010-12-22 13:49:43 +0000955 // FIXME: These needs to be factored into the target Mach-O writer.
956 if (isARM()) {
957 RecordARMRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue);
958 return;
959 }
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000960 if (is64Bit()) {
Daniel Dunbar207e06e2010-03-24 03:43:40 +0000961 RecordX86_64Relocation(Asm, Layout, Fragment, Fixup, Target, FixedValue);
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000962 return;
963 }
964
Daniel Dunbar7e06af82010-12-16 15:42:31 +0000965 unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
Daniel Dunbar482ad802010-05-26 15:18:31 +0000966 unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000967
Eric Christopherc9ada472010-06-15 22:59:05 +0000968 // If this is a 32-bit TLVP reloc it's handled a bit differently.
Daniel Dunbar23bea412010-09-17 15:21:50 +0000969 if (Target.getSymA() &&
970 Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) {
Eric Christopherc9ada472010-06-15 22:59:05 +0000971 RecordTLVPRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue);
972 return;
973 }
Jim Grosbach3c384922010-11-11 20:16:23 +0000974
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000975 // If this is a difference or a defined symbol plus an offset, then we need
976 // a scattered relocation entry.
Daniel Dunbara8251fa2010-05-10 23:15:20 +0000977 // Differences always require scattered relocations.
978 if (Target.getSymB())
979 return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
980 Target, FixedValue);
981
982 // Get the symbol data, if any.
983 MCSymbolData *SD = 0;
984 if (Target.getSymA())
985 SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
986
987 // If this is an internal relocation with an offset, it also needs a
988 // scattered relocation entry.
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000989 uint32_t Offset = Target.getConstant();
990 if (IsPCRel)
991 Offset += 1 << Log2Size;
Daniel Dunbara8251fa2010-05-10 23:15:20 +0000992 if (Offset && SD && !doesSymbolRequireExternRelocation(SD))
993 return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
994 Target, FixedValue);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000995
996 // See <reloc.h>.
Daniel Dunbar482ad802010-05-26 15:18:31 +0000997 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000998 unsigned Index = 0;
999 unsigned IsExtern = 0;
1000 unsigned Type = 0;
1001
1002 if (Target.isAbsolute()) { // constant
1003 // SymbolNum of 0 indicates the absolute section.
1004 //
1005 // FIXME: Currently, these are never generated (see code below). I cannot
1006 // find a case where they are actually emitted.
Daniel Dunbarf52788f2010-11-27 04:59:14 +00001007 Type = macho::RIT_Vanilla;
Rafael Espindola545b77e2010-12-07 17:12:32 +00001008 } else if (SD->getSymbol().isVariable()) {
Rafael Espindola545b77e2010-12-07 17:12:32 +00001009 int64_t Res;
Daniel Dunbar42b52862010-12-22 13:49:56 +00001010 if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
1011 Res, Layout, SectionAddress)) {
Rafael Espindola545b77e2010-12-07 17:12:32 +00001012 FixedValue = Res;
1013 return;
Rafael Espindola545b77e2010-12-07 17:12:32 +00001014 }
Daniel Dunbar42b52862010-12-22 13:49:56 +00001015
1016 report_fatal_error("unsupported relocation of variable '" +
1017 SD->getSymbol().getName() + "'");
Michael J. Spencerb0f3b3e2010-08-10 16:00:49 +00001018 } else {
Daniel Dunbare9460ec2010-05-10 23:15:13 +00001019 // Check whether we need an external or internal relocation.
1020 if (doesSymbolRequireExternRelocation(SD)) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001021 IsExtern = 1;
1022 Index = SD->getIndex();
Daniel Dunbare9460ec2010-05-10 23:15:13 +00001023 // For external relocations, make sure to offset the fixup value to
1024 // compensate for the addend of the symbol address, if it was
1025 // undefined. This occurs with weak definitions, for example.
1026 if (!SD->Symbol->isUndefined())
Rafael Espindola3b3148f2010-12-07 05:57:28 +00001027 FixedValue -= Layout.getSymbolOffset(SD);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001028 } else {
Daniel Dunbar8fb04032010-03-25 08:08:54 +00001029 // The index is the section ordinal (1-based).
1030 Index = SD->getFragment()->getParent()->getOrdinal() + 1;
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001031 FixedValue += getSectionAddress(SD->getFragment()->getParent());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001032 }
Rafael Espindolabf60dad2010-12-07 03:50:14 +00001033 if (IsPCRel)
1034 FixedValue -= getSectionAddress(Fragment->getParent());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001035
Daniel Dunbarf52788f2010-11-27 04:59:14 +00001036 Type = macho::RIT_Vanilla;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001037 }
1038
1039 // struct relocation_info (8 bytes)
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +00001040 macho::RelocationEntry MRE;
Daniel Dunbar640e9482010-05-11 23:53:07 +00001041 MRE.Word0 = FixupOffset;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001042 MRE.Word1 = ((Index << 0) |
1043 (IsPCRel << 24) |
1044 (Log2Size << 25) |
1045 (IsExtern << 27) |
1046 (Type << 28));
Daniel Dunbarb7514182010-03-22 20:35:50 +00001047 Relocations[Fragment->getParent()].push_back(MRE);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001048 }
1049
1050 void BindIndirectSymbols(MCAssembler &Asm) {
1051 // This is the point where 'as' creates actual symbols for indirect symbols
1052 // (in the following two passes). It would be easier for us to do this
1053 // sooner when we see the attribute, but that makes getting the order in the
1054 // symbol table much more complicated than it is worth.
1055 //
1056 // FIXME: Revisit this when the dust settles.
1057
1058 // Bind non lazy symbol pointers first.
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001059 unsigned IndirectIndex = 0;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001060 for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001061 ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001062 const MCSectionMachO &Section =
Daniel Dunbar56279f42010-05-18 17:28:20 +00001063 cast<MCSectionMachO>(it->SectionData->getSection());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001064
1065 if (Section.getType() != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS)
1066 continue;
1067
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001068 // Initialize the section indirect symbol base, if necessary.
1069 if (!IndirectSymBase.count(it->SectionData))
1070 IndirectSymBase[it->SectionData] = IndirectIndex;
Jim Grosbach3c384922010-11-11 20:16:23 +00001071
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001072 Asm.getOrCreateSymbolData(*it->Symbol);
1073 }
1074
1075 // Then lazy symbol pointers and symbol stubs.
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001076 IndirectIndex = 0;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001077 for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001078 ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001079 const MCSectionMachO &Section =
Daniel Dunbar56279f42010-05-18 17:28:20 +00001080 cast<MCSectionMachO>(it->SectionData->getSection());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001081
1082 if (Section.getType() != MCSectionMachO::S_LAZY_SYMBOL_POINTERS &&
1083 Section.getType() != MCSectionMachO::S_SYMBOL_STUBS)
1084 continue;
1085
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001086 // Initialize the section indirect symbol base, if necessary.
1087 if (!IndirectSymBase.count(it->SectionData))
1088 IndirectSymBase[it->SectionData] = IndirectIndex;
1089
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001090 // Set the symbol type to undefined lazy, but only on construction.
1091 //
1092 // FIXME: Do not hardcode.
1093 bool Created;
1094 MCSymbolData &Entry = Asm.getOrCreateSymbolData(*it->Symbol, &Created);
1095 if (Created)
1096 Entry.setFlags(Entry.getFlags() | 0x0001);
1097 }
1098 }
1099
1100 /// ComputeSymbolTable - Compute the symbol table data
1101 ///
1102 /// \param StringTable [out] - The string table data.
1103 /// \param StringIndexMap [out] - Map from symbol names to offsets in the
1104 /// string table.
1105 void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
1106 std::vector<MachSymbolData> &LocalSymbolData,
1107 std::vector<MachSymbolData> &ExternalSymbolData,
1108 std::vector<MachSymbolData> &UndefinedSymbolData) {
1109 // Build section lookup table.
1110 DenseMap<const MCSection*, uint8_t> SectionIndexMap;
1111 unsigned Index = 1;
1112 for (MCAssembler::iterator it = Asm.begin(),
1113 ie = Asm.end(); it != ie; ++it, ++Index)
1114 SectionIndexMap[&it->getSection()] = Index;
1115 assert(Index <= 256 && "Too many sections!");
1116
1117 // Index 0 is always the empty string.
1118 StringMap<uint64_t> StringIndexMap;
1119 StringTable += '\x00';
1120
1121 // Build the symbol arrays and the string table, but only for non-local
1122 // symbols.
1123 //
1124 // The particular order that we collect the symbols and create the string
1125 // table, then sort the symbols is chosen to match 'as'. Even though it
1126 // doesn't matter for correctness, this is important for letting us diff .o
1127 // files.
1128 for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
1129 ie = Asm.symbol_end(); it != ie; ++it) {
1130 const MCSymbol &Symbol = it->getSymbol();
1131
1132 // Ignore non-linker visible symbols.
Daniel Dunbar843aa1f2010-06-16 20:04:29 +00001133 if (!Asm.isSymbolLinkerVisible(it->getSymbol()))
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001134 continue;
1135
1136 if (!it->isExternal() && !Symbol.isUndefined())
1137 continue;
1138
1139 uint64_t &Entry = StringIndexMap[Symbol.getName()];
1140 if (!Entry) {
1141 Entry = StringTable.size();
1142 StringTable += Symbol.getName();
1143 StringTable += '\x00';
1144 }
1145
1146 MachSymbolData MSD;
1147 MSD.SymbolData = it;
1148 MSD.StringIndex = Entry;
1149
1150 if (Symbol.isUndefined()) {
1151 MSD.SectionIndex = 0;
1152 UndefinedSymbolData.push_back(MSD);
1153 } else if (Symbol.isAbsolute()) {
1154 MSD.SectionIndex = 0;
1155 ExternalSymbolData.push_back(MSD);
1156 } else {
1157 MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
1158 assert(MSD.SectionIndex && "Invalid section index!");
1159 ExternalSymbolData.push_back(MSD);
1160 }
1161 }
1162
1163 // Now add the data for local symbols.
1164 for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
1165 ie = Asm.symbol_end(); it != ie; ++it) {
1166 const MCSymbol &Symbol = it->getSymbol();
1167
1168 // Ignore non-linker visible symbols.
Daniel Dunbar843aa1f2010-06-16 20:04:29 +00001169 if (!Asm.isSymbolLinkerVisible(it->getSymbol()))
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001170 continue;
1171
1172 if (it->isExternal() || Symbol.isUndefined())
1173 continue;
1174
1175 uint64_t &Entry = StringIndexMap[Symbol.getName()];
1176 if (!Entry) {
1177 Entry = StringTable.size();
1178 StringTable += Symbol.getName();
1179 StringTable += '\x00';
1180 }
1181
1182 MachSymbolData MSD;
1183 MSD.SymbolData = it;
1184 MSD.StringIndex = Entry;
1185
1186 if (Symbol.isAbsolute()) {
1187 MSD.SectionIndex = 0;
1188 LocalSymbolData.push_back(MSD);
1189 } else {
1190 MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
1191 assert(MSD.SectionIndex && "Invalid section index!");
1192 LocalSymbolData.push_back(MSD);
1193 }
1194 }
1195
1196 // External and undefined symbols are required to be in lexicographic order.
1197 std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
1198 std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());
1199
1200 // Set the symbol indices.
1201 Index = 0;
1202 for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
1203 LocalSymbolData[i].SymbolData->setIndex(Index++);
1204 for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
1205 ExternalSymbolData[i].SymbolData->setIndex(Index++);
1206 for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
1207 UndefinedSymbolData[i].SymbolData->setIndex(Index++);
1208
1209 // The string table is padded to a multiple of 4.
1210 while (StringTable.size() % 4)
1211 StringTable += '\x00';
1212 }
1213
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001214 void computeSectionAddresses(const MCAssembler &Asm,
1215 const MCAsmLayout &Layout) {
1216 uint64_t StartAddress = 0;
1217 const SmallVectorImpl<MCSectionData*> &Order = Layout.getSectionOrder();
1218 for (int i = 0, n = Order.size(); i != n ; ++i) {
1219 const MCSectionData *SD = Order[i];
1220 StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment());
1221 SectionAddress[SD] = StartAddress;
1222 StartAddress += Layout.getSectionAddressSize(SD);
1223 // Explicitly pad the section to match the alignment requirements of the
1224 // following one. This is for 'gas' compatibility, it shouldn't
1225 /// strictly be necessary.
1226 StartAddress += getPaddingSize(SD, Layout);
1227 }
1228 }
1229
1230 void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) {
1231 computeSectionAddresses(Asm, Layout);
1232
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001233 // Create symbol data for any indirect symbols.
1234 BindIndirectSymbols(Asm);
1235
1236 // Compute symbol table information and bind symbol indices.
1237 ComputeSymbolTable(Asm, StringTable, LocalSymbolData, ExternalSymbolData,
1238 UndefinedSymbolData);
1239 }
1240
Daniel Dunbar1f3662a2010-12-17 04:54:54 +00001241 bool IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
1242 const MCSymbolRefExpr *A,
Rafael Espindola31327802010-12-18 06:27:54 +00001243 const MCSymbolRefExpr *B,
1244 bool InSet) const {
1245 if (InSet)
1246 return true;
1247
Daniel Dunbarb8742272010-12-17 05:50:29 +00001248 if (!TargetObjectWriter->useAggressiveSymbolFolding())
1249 return false;
1250
Daniel Dunbar32c1c5a2010-12-17 04:54:58 +00001251 // The effective address is
1252 // addr(atom(A)) + offset(A)
1253 // - addr(atom(B)) - offset(B)
1254 // and the offsets are not relocatable, so the fixup is fully resolved when
1255 // addr(atom(A)) - addr(atom(B)) == 0.
1256 const MCSymbolData *A_Base = 0, *B_Base = 0;
1257
1258 // Modified symbol references cannot be resolved.
1259 if (A->getKind() != MCSymbolRefExpr::VK_None ||
1260 B->getKind() != MCSymbolRefExpr::VK_None)
1261 return false;
1262
1263 A_Base = Asm.getAtom(&Asm.getSymbolData(A->getSymbol()));
1264 if (!A_Base)
1265 return false;
1266
1267 B_Base = Asm.getAtom(&Asm.getSymbolData(B->getSymbol()));
1268 if (!B_Base)
1269 return false;
1270
1271 // If the atoms are the same, they are guaranteed to have the same address.
1272 if (A_Base == B_Base)
1273 return true;
1274
1275 // Otherwise, we can't prove this is fully resolved.
Daniel Dunbar1f3662a2010-12-17 04:54:54 +00001276 return false;
1277 }
1278
Rafael Espindola70703872010-09-30 02:22:20 +00001279 bool IsFixupFullyResolved(const MCAssembler &Asm,
1280 const MCValue Target,
1281 bool IsPCRel,
1282 const MCFragment *DF) const {
Daniel Dunbar7976b882010-11-27 05:18:48 +00001283 // Otherwise, determine whether this value is actually resolved; scattering
1284 // may cause atoms to move.
Rafael Espindola70703872010-09-30 02:22:20 +00001285
Daniel Dunbar7976b882010-11-27 05:18:48 +00001286 // Check if we are using the "simple" resolution algorithm (e.g.,
1287 // i386).
1288 if (!Asm.getBackend().hasReliableSymbolDifference()) {
1289 const MCSection *BaseSection = 0;
1290 if (IsPCRel)
1291 BaseSection = &DF->getParent()->getSection();
1292
1293 return isScatteredFixupFullyResolvedSimple(Asm, Target, BaseSection);
Rafael Espindola70703872010-09-30 02:22:20 +00001294 }
Daniel Dunbar7976b882010-11-27 05:18:48 +00001295
1296 // Otherwise, compute the proper answer as reliably as possible.
1297
1298 // If this is a PCrel relocation, find the base atom (identified by its
1299 // symbol) that the fixup value is relative to.
1300 const MCSymbolData *BaseSymbol = 0;
1301 if (IsPCRel) {
1302 BaseSymbol = DF->getAtom();
1303 if (!BaseSymbol)
1304 return false;
1305 }
1306
1307 return isScatteredFixupFullyResolved(Asm, Target, BaseSymbol);
Rafael Espindola70703872010-09-30 02:22:20 +00001308 }
1309
Daniel Dunbar115a3dd2010-11-13 07:33:40 +00001310 void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001311 unsigned NumSections = Asm.size();
1312
1313 // The section data starts after the header, the segment load command (and
1314 // section headers) and the symbol table.
1315 unsigned NumLoadCommands = 1;
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001316 uint64_t LoadCommandsSize = is64Bit() ?
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001317 macho::SegmentLoadCommand64Size + NumSections * macho::Section64Size :
1318 macho::SegmentLoadCommand32Size + NumSections * macho::Section32Size;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001319
1320 // Add the symbol table load command sizes, if used.
1321 unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() +
1322 UndefinedSymbolData.size();
1323 if (NumSymbols) {
1324 NumLoadCommands += 2;
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001325 LoadCommandsSize += (macho::SymtabLoadCommandSize +
1326 macho::DysymtabLoadCommandSize);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001327 }
1328
1329 // Compute the total size of the section data, as well as its file size and
1330 // vm size.
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001331 uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size :
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001332 macho::Header32Size) + LoadCommandsSize;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001333 uint64_t SectionDataSize = 0;
1334 uint64_t SectionDataFileSize = 0;
1335 uint64_t VMSize = 0;
1336 for (MCAssembler::const_iterator it = Asm.begin(),
1337 ie = Asm.end(); it != ie; ++it) {
1338 const MCSectionData &SD = *it;
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001339 uint64_t Address = getSectionAddress(&SD);
1340 uint64_t Size = Layout.getSectionAddressSize(&SD);
Daniel Dunbar5d428512010-03-25 02:00:07 +00001341 uint64_t FileSize = Layout.getSectionFileSize(&SD);
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001342 FileSize += getPaddingSize(&SD, Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001343
Daniel Dunbar5d428512010-03-25 02:00:07 +00001344 VMSize = std::max(VMSize, Address + Size);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001345
Rafael Espindolaf2dc4aa2010-11-17 20:03:54 +00001346 if (SD.getSection().isVirtualSection())
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001347 continue;
1348
Daniel Dunbar5d428512010-03-25 02:00:07 +00001349 SectionDataSize = std::max(SectionDataSize, Address + Size);
1350 SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001351 }
1352
1353 // The section data is padded to 4 bytes.
1354 //
1355 // FIXME: Is this machine dependent?
1356 unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4);
1357 SectionDataFileSize += SectionDataPadding;
1358
1359 // Write the prolog, starting with the header and load command...
1360 WriteHeader(NumLoadCommands, LoadCommandsSize,
1361 Asm.getSubsectionsViaSymbols());
1362 WriteSegmentLoadCommand(NumSections, VMSize,
1363 SectionDataStart, SectionDataSize);
1364
1365 // ... and then the section headers.
1366 uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
1367 for (MCAssembler::const_iterator it = Asm.begin(),
1368 ie = Asm.end(); it != ie; ++it) {
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +00001369 std::vector<macho::RelocationEntry> &Relocs = Relocations[it];
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001370 unsigned NumRelocs = Relocs.size();
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001371 uint64_t SectionStart = SectionDataStart + getSectionAddress(it);
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001372 WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs);
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001373 RelocTableEnd += NumRelocs * macho::RelocationInfoSize;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001374 }
1375
1376 // Write the symbol table load command, if used.
1377 if (NumSymbols) {
1378 unsigned FirstLocalSymbol = 0;
1379 unsigned NumLocalSymbols = LocalSymbolData.size();
1380 unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;
1381 unsigned NumExternalSymbols = ExternalSymbolData.size();
1382 unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;
1383 unsigned NumUndefinedSymbols = UndefinedSymbolData.size();
1384 unsigned NumIndirectSymbols = Asm.indirect_symbol_size();
1385 unsigned NumSymTabSymbols =
1386 NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols;
1387 uint64_t IndirectSymbolSize = NumIndirectSymbols * 4;
1388 uint64_t IndirectSymbolOffset = 0;
1389
1390 // If used, the indirect symbols are written after the section data.
1391 if (NumIndirectSymbols)
1392 IndirectSymbolOffset = RelocTableEnd;
1393
1394 // The symbol table is written after the indirect symbol data.
1395 uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize;
1396
1397 // The string table is written after symbol table.
1398 uint64_t StringTableOffset =
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001399 SymbolTableOffset + NumSymTabSymbols * (is64Bit() ? macho::Nlist64Size :
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001400 macho::Nlist32Size);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001401 WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
1402 StringTableOffset, StringTable.size());
1403
1404 WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
1405 FirstExternalSymbol, NumExternalSymbols,
1406 FirstUndefinedSymbol, NumUndefinedSymbols,
1407 IndirectSymbolOffset, NumIndirectSymbols);
1408 }
1409
1410 // Write the actual section data.
1411 for (MCAssembler::const_iterator it = Asm.begin(),
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001412 ie = Asm.end(); it != ie; ++it) {
Daniel Dunbar5d2477c2010-12-17 02:45:59 +00001413 Asm.WriteSectionData(it, Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001414
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001415 uint64_t Pad = getPaddingSize(it, Layout);
1416 for (unsigned int i = 0; i < Pad; ++i)
1417 Write8(0);
1418 }
1419
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001420 // Write the extra padding.
1421 WriteZeros(SectionDataPadding);
1422
1423 // Write the relocation entries.
1424 for (MCAssembler::const_iterator it = Asm.begin(),
1425 ie = Asm.end(); it != ie; ++it) {
1426 // Write the section relocation entries, in reverse order to match 'as'
1427 // (approximately, the exact algorithm is more complicated than this).
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +00001428 std::vector<macho::RelocationEntry> &Relocs = Relocations[it];
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001429 for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
1430 Write32(Relocs[e - i - 1].Word0);
1431 Write32(Relocs[e - i - 1].Word1);
1432 }
1433 }
1434
1435 // Write the symbol table data, if used.
1436 if (NumSymbols) {
1437 // Write the indirect symbol entries.
1438 for (MCAssembler::const_indirect_symbol_iterator
1439 it = Asm.indirect_symbol_begin(),
1440 ie = Asm.indirect_symbol_end(); it != ie; ++it) {
1441 // Indirect symbols in the non lazy symbol pointer section have some
1442 // special handling.
1443 const MCSectionMachO &Section =
1444 static_cast<const MCSectionMachO&>(it->SectionData->getSection());
1445 if (Section.getType() == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) {
1446 // If this symbol is defined and internal, mark it as such.
1447 if (it->Symbol->isDefined() &&
1448 !Asm.getSymbolData(*it->Symbol).isExternal()) {
Daniel Dunbarf52788f2010-11-27 04:59:14 +00001449 uint32_t Flags = macho::ISF_Local;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001450 if (it->Symbol->isAbsolute())
Daniel Dunbarf52788f2010-11-27 04:59:14 +00001451 Flags |= macho::ISF_Absolute;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001452 Write32(Flags);
1453 continue;
1454 }
1455 }
1456
1457 Write32(Asm.getSymbolData(*it->Symbol).getIndex());
1458 }
1459
1460 // FIXME: Check that offsets match computed ones.
1461
1462 // Write the symbol table entries.
1463 for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001464 WriteNlist(LocalSymbolData[i], Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001465 for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001466 WriteNlist(ExternalSymbolData[i], Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001467 for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001468 WriteNlist(UndefinedSymbolData[i], Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001469
1470 // Write the string table.
1471 OS << StringTable.str();
1472 }
1473 }
1474};
1475
1476}
1477
Daniel Dunbarae5abd52010-12-16 16:09:19 +00001478MCObjectWriter *llvm::createMachObjectWriter(MCMachObjectTargetWriter *MOTW,
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001479 raw_ostream &OS,
Daniel Dunbar115a3dd2010-11-13 07:33:40 +00001480 bool IsLittleEndian) {
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001481 return new MachObjectWriter(MOTW, OS, IsLittleEndian);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001482}