blob: 2cfd10b4d5ecd7fa1a1d9d0b8d279cf786acb16c [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) {
Daniel Dunbar36645642010-12-22 16:32:37 +0000849 Is24BitBranch = false;
850 Log2Size = ~0U;
851
Daniel Dunbar294e6782010-12-22 16:19:24 +0000852 switch (Kind) {
853 default:
854 return false;
855
Daniel Dunbar36645642010-12-22 16:32:37 +0000856 case FK_Data_1:
857 Log2Size = llvm::Log2_32(1);
858 return true;
859 case FK_Data_2:
860 Log2Size = llvm::Log2_32(2);
861 return true;
862 case FK_Data_4:
863 Log2Size = llvm::Log2_32(4);
864 return true;
865 case FK_Data_8:
866 Log2Size = llvm::Log2_32(8);
867 return true;
868
Daniel Dunbar294e6782010-12-22 16:19:24 +0000869 // Handle 24-bit branch kinds.
870 case ARM::fixup_arm_ldst_pcrel_12:
871 case ARM::fixup_arm_pcrel_10:
872 case ARM::fixup_arm_adr_pcrel_12:
873 case ARM::fixup_arm_branch:
874 Is24BitBranch = true;
875 // Report as 'long', even though that is not quite accurate.
876 Log2Size = llvm::Log2_32(4);
877 return true;
878 }
879 }
Daniel Dunbar532c4562010-12-22 13:49:43 +0000880 void RecordARMRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
881 const MCFragment *Fragment, const MCFixup &Fixup,
882 MCValue Target, uint64_t &FixedValue) {
Daniel Dunbar4d743052010-12-22 13:50:05 +0000883 unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
Daniel Dunbar294e6782010-12-22 16:19:24 +0000884 unsigned Log2Size;
885 bool Is24BitBranch;
886 if (!getARMFixupKindMachOInfo(Fixup.getKind(), Is24BitBranch, Log2Size)) {
887 report_fatal_error("unknown ARM fixup kind!");
888 return;
889 }
Daniel Dunbar4d743052010-12-22 13:50:05 +0000890
891 // If this is a difference or a defined symbol plus an offset, then we need
892 // a scattered relocation entry. Differences always require scattered
893 // relocations.
894 if (Target.getSymB())
895 return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
896 Target, FixedValue);
897
898 // Get the symbol data, if any.
899 MCSymbolData *SD = 0;
900 if (Target.getSymA())
901 SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
902
903 // FIXME: For other platforms, we need to use scattered relocations for
904 // internal relocations with offsets. If this is an internal relocation
905 // with an offset, it also needs a scattered relocation entry.
906 //
907 // Is this right for ARM?
908 uint32_t Offset = Target.getConstant();
909 if (IsPCRel)
910 Offset += 1 << Log2Size;
911 if (Offset && SD && !doesSymbolRequireExternRelocation(SD))
912 return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
913 Target, FixedValue);
914
915 // See <reloc.h>.
916 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
917 unsigned Index = 0;
918 unsigned IsExtern = 0;
919 unsigned Type = 0;
920
921 if (Target.isAbsolute()) { // constant
922 // FIXME!
923 report_fatal_error("FIXME: relocations to absolute targets "
924 "not yet implemented");
925 } else if (SD->getSymbol().isVariable()) {
926 int64_t Res;
927 if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
928 Res, Layout, SectionAddress)) {
929 FixedValue = Res;
930 return;
931 }
932
933 report_fatal_error("unsupported relocation of variable '" +
934 SD->getSymbol().getName() + "'");
935 } else {
936 // Check whether we need an external or internal relocation.
937 if (doesSymbolRequireExternRelocation(SD)) {
938 IsExtern = 1;
939 Index = SD->getIndex();
940 // For external relocations, make sure to offset the fixup value to
941 // compensate for the addend of the symbol address, if it was
942 // undefined. This occurs with weak definitions, for example.
943 if (!SD->Symbol->isUndefined())
944 FixedValue -= Layout.getSymbolOffset(SD);
945 } else {
946 // The index is the section ordinal (1-based).
947 Index = SD->getFragment()->getParent()->getOrdinal() + 1;
948 FixedValue += getSectionAddress(SD->getFragment()->getParent());
949 }
950 if (IsPCRel)
951 FixedValue -= getSectionAddress(Fragment->getParent());
952
Daniel Dunbar294e6782010-12-22 16:19:24 +0000953 // Determine the appropriate type based on the fixup kind.
954 Type = Is24BitBranch ? macho::RIT_ARM_Branch24Bit : macho::RIT_Vanilla;
Daniel Dunbar4d743052010-12-22 13:50:05 +0000955 }
956
957 // struct relocation_info (8 bytes)
958 macho::RelocationEntry MRE;
959 MRE.Word0 = FixupOffset;
960 MRE.Word1 = ((Index << 0) |
961 (IsPCRel << 24) |
962 (Log2Size << 25) |
963 (IsExtern << 27) |
964 (Type << 28));
965 Relocations[Fragment->getParent()].push_back(MRE);
Daniel Dunbar532c4562010-12-22 13:49:43 +0000966 }
967
Daniel Dunbar207e06e2010-03-24 03:43:40 +0000968 void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
Daniel Dunbarc90e30a2010-05-26 15:18:56 +0000969 const MCFragment *Fragment, const MCFixup &Fixup,
Daniel Dunbar207e06e2010-03-24 03:43:40 +0000970 MCValue Target, uint64_t &FixedValue) {
Daniel Dunbar532c4562010-12-22 13:49:43 +0000971 // FIXME: These needs to be factored into the target Mach-O writer.
972 if (isARM()) {
973 RecordARMRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue);
974 return;
975 }
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000976 if (is64Bit()) {
Daniel Dunbar207e06e2010-03-24 03:43:40 +0000977 RecordX86_64Relocation(Asm, Layout, Fragment, Fixup, Target, FixedValue);
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000978 return;
979 }
980
Daniel Dunbar7e06af82010-12-16 15:42:31 +0000981 unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
Daniel Dunbar482ad802010-05-26 15:18:31 +0000982 unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000983
Eric Christopherc9ada472010-06-15 22:59:05 +0000984 // If this is a 32-bit TLVP reloc it's handled a bit differently.
Daniel Dunbar23bea412010-09-17 15:21:50 +0000985 if (Target.getSymA() &&
986 Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) {
Eric Christopherc9ada472010-06-15 22:59:05 +0000987 RecordTLVPRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue);
988 return;
989 }
Jim Grosbach3c384922010-11-11 20:16:23 +0000990
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000991 // If this is a difference or a defined symbol plus an offset, then we need
992 // a scattered relocation entry.
Daniel Dunbara8251fa2010-05-10 23:15:20 +0000993 // Differences always require scattered relocations.
994 if (Target.getSymB())
995 return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
996 Target, FixedValue);
997
998 // Get the symbol data, if any.
999 MCSymbolData *SD = 0;
1000 if (Target.getSymA())
1001 SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
1002
1003 // If this is an internal relocation with an offset, it also needs a
1004 // scattered relocation entry.
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001005 uint32_t Offset = Target.getConstant();
1006 if (IsPCRel)
1007 Offset += 1 << Log2Size;
Daniel Dunbara8251fa2010-05-10 23:15:20 +00001008 if (Offset && SD && !doesSymbolRequireExternRelocation(SD))
1009 return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
1010 Target, FixedValue);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001011
1012 // See <reloc.h>.
Daniel Dunbar482ad802010-05-26 15:18:31 +00001013 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001014 unsigned Index = 0;
1015 unsigned IsExtern = 0;
1016 unsigned Type = 0;
1017
1018 if (Target.isAbsolute()) { // constant
1019 // SymbolNum of 0 indicates the absolute section.
1020 //
1021 // FIXME: Currently, these are never generated (see code below). I cannot
1022 // find a case where they are actually emitted.
Daniel Dunbarf52788f2010-11-27 04:59:14 +00001023 Type = macho::RIT_Vanilla;
Rafael Espindola545b77e2010-12-07 17:12:32 +00001024 } else if (SD->getSymbol().isVariable()) {
Rafael Espindola545b77e2010-12-07 17:12:32 +00001025 int64_t Res;
Daniel Dunbar42b52862010-12-22 13:49:56 +00001026 if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
1027 Res, Layout, SectionAddress)) {
Rafael Espindola545b77e2010-12-07 17:12:32 +00001028 FixedValue = Res;
1029 return;
Rafael Espindola545b77e2010-12-07 17:12:32 +00001030 }
Daniel Dunbar42b52862010-12-22 13:49:56 +00001031
1032 report_fatal_error("unsupported relocation of variable '" +
1033 SD->getSymbol().getName() + "'");
Michael J. Spencerb0f3b3e2010-08-10 16:00:49 +00001034 } else {
Daniel Dunbare9460ec2010-05-10 23:15:13 +00001035 // Check whether we need an external or internal relocation.
1036 if (doesSymbolRequireExternRelocation(SD)) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001037 IsExtern = 1;
1038 Index = SD->getIndex();
Daniel Dunbare9460ec2010-05-10 23:15:13 +00001039 // For external relocations, make sure to offset the fixup value to
1040 // compensate for the addend of the symbol address, if it was
1041 // undefined. This occurs with weak definitions, for example.
1042 if (!SD->Symbol->isUndefined())
Rafael Espindola3b3148f2010-12-07 05:57:28 +00001043 FixedValue -= Layout.getSymbolOffset(SD);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001044 } else {
Daniel Dunbar8fb04032010-03-25 08:08:54 +00001045 // The index is the section ordinal (1-based).
1046 Index = SD->getFragment()->getParent()->getOrdinal() + 1;
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001047 FixedValue += getSectionAddress(SD->getFragment()->getParent());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001048 }
Rafael Espindolabf60dad2010-12-07 03:50:14 +00001049 if (IsPCRel)
1050 FixedValue -= getSectionAddress(Fragment->getParent());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001051
Daniel Dunbarf52788f2010-11-27 04:59:14 +00001052 Type = macho::RIT_Vanilla;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001053 }
1054
1055 // struct relocation_info (8 bytes)
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +00001056 macho::RelocationEntry MRE;
Daniel Dunbar640e9482010-05-11 23:53:07 +00001057 MRE.Word0 = FixupOffset;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001058 MRE.Word1 = ((Index << 0) |
1059 (IsPCRel << 24) |
1060 (Log2Size << 25) |
1061 (IsExtern << 27) |
1062 (Type << 28));
Daniel Dunbarb7514182010-03-22 20:35:50 +00001063 Relocations[Fragment->getParent()].push_back(MRE);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001064 }
1065
1066 void BindIndirectSymbols(MCAssembler &Asm) {
1067 // This is the point where 'as' creates actual symbols for indirect symbols
1068 // (in the following two passes). It would be easier for us to do this
1069 // sooner when we see the attribute, but that makes getting the order in the
1070 // symbol table much more complicated than it is worth.
1071 //
1072 // FIXME: Revisit this when the dust settles.
1073
1074 // Bind non lazy symbol pointers first.
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001075 unsigned IndirectIndex = 0;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001076 for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001077 ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001078 const MCSectionMachO &Section =
Daniel Dunbar56279f42010-05-18 17:28:20 +00001079 cast<MCSectionMachO>(it->SectionData->getSection());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001080
1081 if (Section.getType() != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS)
1082 continue;
1083
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001084 // Initialize the section indirect symbol base, if necessary.
1085 if (!IndirectSymBase.count(it->SectionData))
1086 IndirectSymBase[it->SectionData] = IndirectIndex;
Jim Grosbach3c384922010-11-11 20:16:23 +00001087
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001088 Asm.getOrCreateSymbolData(*it->Symbol);
1089 }
1090
1091 // Then lazy symbol pointers and symbol stubs.
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001092 IndirectIndex = 0;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001093 for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001094 ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001095 const MCSectionMachO &Section =
Daniel Dunbar56279f42010-05-18 17:28:20 +00001096 cast<MCSectionMachO>(it->SectionData->getSection());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001097
1098 if (Section.getType() != MCSectionMachO::S_LAZY_SYMBOL_POINTERS &&
1099 Section.getType() != MCSectionMachO::S_SYMBOL_STUBS)
1100 continue;
1101
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001102 // Initialize the section indirect symbol base, if necessary.
1103 if (!IndirectSymBase.count(it->SectionData))
1104 IndirectSymBase[it->SectionData] = IndirectIndex;
1105
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001106 // Set the symbol type to undefined lazy, but only on construction.
1107 //
1108 // FIXME: Do not hardcode.
1109 bool Created;
1110 MCSymbolData &Entry = Asm.getOrCreateSymbolData(*it->Symbol, &Created);
1111 if (Created)
1112 Entry.setFlags(Entry.getFlags() | 0x0001);
1113 }
1114 }
1115
1116 /// ComputeSymbolTable - Compute the symbol table data
1117 ///
1118 /// \param StringTable [out] - The string table data.
1119 /// \param StringIndexMap [out] - Map from symbol names to offsets in the
1120 /// string table.
1121 void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
1122 std::vector<MachSymbolData> &LocalSymbolData,
1123 std::vector<MachSymbolData> &ExternalSymbolData,
1124 std::vector<MachSymbolData> &UndefinedSymbolData) {
1125 // Build section lookup table.
1126 DenseMap<const MCSection*, uint8_t> SectionIndexMap;
1127 unsigned Index = 1;
1128 for (MCAssembler::iterator it = Asm.begin(),
1129 ie = Asm.end(); it != ie; ++it, ++Index)
1130 SectionIndexMap[&it->getSection()] = Index;
1131 assert(Index <= 256 && "Too many sections!");
1132
1133 // Index 0 is always the empty string.
1134 StringMap<uint64_t> StringIndexMap;
1135 StringTable += '\x00';
1136
1137 // Build the symbol arrays and the string table, but only for non-local
1138 // symbols.
1139 //
1140 // The particular order that we collect the symbols and create the string
1141 // table, then sort the symbols is chosen to match 'as'. Even though it
1142 // doesn't matter for correctness, this is important for letting us diff .o
1143 // files.
1144 for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
1145 ie = Asm.symbol_end(); it != ie; ++it) {
1146 const MCSymbol &Symbol = it->getSymbol();
1147
1148 // Ignore non-linker visible symbols.
Daniel Dunbar843aa1f2010-06-16 20:04:29 +00001149 if (!Asm.isSymbolLinkerVisible(it->getSymbol()))
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001150 continue;
1151
1152 if (!it->isExternal() && !Symbol.isUndefined())
1153 continue;
1154
1155 uint64_t &Entry = StringIndexMap[Symbol.getName()];
1156 if (!Entry) {
1157 Entry = StringTable.size();
1158 StringTable += Symbol.getName();
1159 StringTable += '\x00';
1160 }
1161
1162 MachSymbolData MSD;
1163 MSD.SymbolData = it;
1164 MSD.StringIndex = Entry;
1165
1166 if (Symbol.isUndefined()) {
1167 MSD.SectionIndex = 0;
1168 UndefinedSymbolData.push_back(MSD);
1169 } else if (Symbol.isAbsolute()) {
1170 MSD.SectionIndex = 0;
1171 ExternalSymbolData.push_back(MSD);
1172 } else {
1173 MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
1174 assert(MSD.SectionIndex && "Invalid section index!");
1175 ExternalSymbolData.push_back(MSD);
1176 }
1177 }
1178
1179 // Now add the data for local symbols.
1180 for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
1181 ie = Asm.symbol_end(); it != ie; ++it) {
1182 const MCSymbol &Symbol = it->getSymbol();
1183
1184 // Ignore non-linker visible symbols.
Daniel Dunbar843aa1f2010-06-16 20:04:29 +00001185 if (!Asm.isSymbolLinkerVisible(it->getSymbol()))
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001186 continue;
1187
1188 if (it->isExternal() || Symbol.isUndefined())
1189 continue;
1190
1191 uint64_t &Entry = StringIndexMap[Symbol.getName()];
1192 if (!Entry) {
1193 Entry = StringTable.size();
1194 StringTable += Symbol.getName();
1195 StringTable += '\x00';
1196 }
1197
1198 MachSymbolData MSD;
1199 MSD.SymbolData = it;
1200 MSD.StringIndex = Entry;
1201
1202 if (Symbol.isAbsolute()) {
1203 MSD.SectionIndex = 0;
1204 LocalSymbolData.push_back(MSD);
1205 } else {
1206 MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
1207 assert(MSD.SectionIndex && "Invalid section index!");
1208 LocalSymbolData.push_back(MSD);
1209 }
1210 }
1211
1212 // External and undefined symbols are required to be in lexicographic order.
1213 std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
1214 std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());
1215
1216 // Set the symbol indices.
1217 Index = 0;
1218 for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
1219 LocalSymbolData[i].SymbolData->setIndex(Index++);
1220 for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
1221 ExternalSymbolData[i].SymbolData->setIndex(Index++);
1222 for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
1223 UndefinedSymbolData[i].SymbolData->setIndex(Index++);
1224
1225 // The string table is padded to a multiple of 4.
1226 while (StringTable.size() % 4)
1227 StringTable += '\x00';
1228 }
1229
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001230 void computeSectionAddresses(const MCAssembler &Asm,
1231 const MCAsmLayout &Layout) {
1232 uint64_t StartAddress = 0;
1233 const SmallVectorImpl<MCSectionData*> &Order = Layout.getSectionOrder();
1234 for (int i = 0, n = Order.size(); i != n ; ++i) {
1235 const MCSectionData *SD = Order[i];
1236 StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment());
1237 SectionAddress[SD] = StartAddress;
1238 StartAddress += Layout.getSectionAddressSize(SD);
1239 // Explicitly pad the section to match the alignment requirements of the
1240 // following one. This is for 'gas' compatibility, it shouldn't
1241 /// strictly be necessary.
1242 StartAddress += getPaddingSize(SD, Layout);
1243 }
1244 }
1245
1246 void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) {
1247 computeSectionAddresses(Asm, Layout);
1248
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001249 // Create symbol data for any indirect symbols.
1250 BindIndirectSymbols(Asm);
1251
1252 // Compute symbol table information and bind symbol indices.
1253 ComputeSymbolTable(Asm, StringTable, LocalSymbolData, ExternalSymbolData,
1254 UndefinedSymbolData);
1255 }
1256
Daniel Dunbar1f3662a2010-12-17 04:54:54 +00001257 bool IsSymbolRefDifferenceFullyResolved(const MCAssembler &Asm,
1258 const MCSymbolRefExpr *A,
Rafael Espindola31327802010-12-18 06:27:54 +00001259 const MCSymbolRefExpr *B,
1260 bool InSet) const {
1261 if (InSet)
1262 return true;
1263
Daniel Dunbarb8742272010-12-17 05:50:29 +00001264 if (!TargetObjectWriter->useAggressiveSymbolFolding())
1265 return false;
1266
Daniel Dunbar32c1c5a2010-12-17 04:54:58 +00001267 // The effective address is
1268 // addr(atom(A)) + offset(A)
1269 // - addr(atom(B)) - offset(B)
1270 // and the offsets are not relocatable, so the fixup is fully resolved when
1271 // addr(atom(A)) - addr(atom(B)) == 0.
1272 const MCSymbolData *A_Base = 0, *B_Base = 0;
1273
1274 // Modified symbol references cannot be resolved.
1275 if (A->getKind() != MCSymbolRefExpr::VK_None ||
1276 B->getKind() != MCSymbolRefExpr::VK_None)
1277 return false;
1278
1279 A_Base = Asm.getAtom(&Asm.getSymbolData(A->getSymbol()));
1280 if (!A_Base)
1281 return false;
1282
1283 B_Base = Asm.getAtom(&Asm.getSymbolData(B->getSymbol()));
1284 if (!B_Base)
1285 return false;
1286
1287 // If the atoms are the same, they are guaranteed to have the same address.
1288 if (A_Base == B_Base)
1289 return true;
1290
1291 // Otherwise, we can't prove this is fully resolved.
Daniel Dunbar1f3662a2010-12-17 04:54:54 +00001292 return false;
1293 }
1294
Rafael Espindola70703872010-09-30 02:22:20 +00001295 bool IsFixupFullyResolved(const MCAssembler &Asm,
1296 const MCValue Target,
1297 bool IsPCRel,
1298 const MCFragment *DF) const {
Daniel Dunbar7976b882010-11-27 05:18:48 +00001299 // Otherwise, determine whether this value is actually resolved; scattering
1300 // may cause atoms to move.
Rafael Espindola70703872010-09-30 02:22:20 +00001301
Daniel Dunbar7976b882010-11-27 05:18:48 +00001302 // Check if we are using the "simple" resolution algorithm (e.g.,
1303 // i386).
1304 if (!Asm.getBackend().hasReliableSymbolDifference()) {
1305 const MCSection *BaseSection = 0;
1306 if (IsPCRel)
1307 BaseSection = &DF->getParent()->getSection();
1308
1309 return isScatteredFixupFullyResolvedSimple(Asm, Target, BaseSection);
Rafael Espindola70703872010-09-30 02:22:20 +00001310 }
Daniel Dunbar7976b882010-11-27 05:18:48 +00001311
1312 // Otherwise, compute the proper answer as reliably as possible.
1313
1314 // If this is a PCrel relocation, find the base atom (identified by its
1315 // symbol) that the fixup value is relative to.
1316 const MCSymbolData *BaseSymbol = 0;
1317 if (IsPCRel) {
1318 BaseSymbol = DF->getAtom();
1319 if (!BaseSymbol)
1320 return false;
1321 }
1322
1323 return isScatteredFixupFullyResolved(Asm, Target, BaseSymbol);
Rafael Espindola70703872010-09-30 02:22:20 +00001324 }
1325
Daniel Dunbar115a3dd2010-11-13 07:33:40 +00001326 void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001327 unsigned NumSections = Asm.size();
1328
1329 // The section data starts after the header, the segment load command (and
1330 // section headers) and the symbol table.
1331 unsigned NumLoadCommands = 1;
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001332 uint64_t LoadCommandsSize = is64Bit() ?
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001333 macho::SegmentLoadCommand64Size + NumSections * macho::Section64Size :
1334 macho::SegmentLoadCommand32Size + NumSections * macho::Section32Size;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001335
1336 // Add the symbol table load command sizes, if used.
1337 unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() +
1338 UndefinedSymbolData.size();
1339 if (NumSymbols) {
1340 NumLoadCommands += 2;
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001341 LoadCommandsSize += (macho::SymtabLoadCommandSize +
1342 macho::DysymtabLoadCommandSize);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001343 }
1344
1345 // Compute the total size of the section data, as well as its file size and
1346 // vm size.
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001347 uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size :
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001348 macho::Header32Size) + LoadCommandsSize;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001349 uint64_t SectionDataSize = 0;
1350 uint64_t SectionDataFileSize = 0;
1351 uint64_t VMSize = 0;
1352 for (MCAssembler::const_iterator it = Asm.begin(),
1353 ie = Asm.end(); it != ie; ++it) {
1354 const MCSectionData &SD = *it;
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001355 uint64_t Address = getSectionAddress(&SD);
1356 uint64_t Size = Layout.getSectionAddressSize(&SD);
Daniel Dunbar5d428512010-03-25 02:00:07 +00001357 uint64_t FileSize = Layout.getSectionFileSize(&SD);
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001358 FileSize += getPaddingSize(&SD, Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001359
Daniel Dunbar5d428512010-03-25 02:00:07 +00001360 VMSize = std::max(VMSize, Address + Size);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001361
Rafael Espindolaf2dc4aa2010-11-17 20:03:54 +00001362 if (SD.getSection().isVirtualSection())
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001363 continue;
1364
Daniel Dunbar5d428512010-03-25 02:00:07 +00001365 SectionDataSize = std::max(SectionDataSize, Address + Size);
1366 SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001367 }
1368
1369 // The section data is padded to 4 bytes.
1370 //
1371 // FIXME: Is this machine dependent?
1372 unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4);
1373 SectionDataFileSize += SectionDataPadding;
1374
1375 // Write the prolog, starting with the header and load command...
1376 WriteHeader(NumLoadCommands, LoadCommandsSize,
1377 Asm.getSubsectionsViaSymbols());
1378 WriteSegmentLoadCommand(NumSections, VMSize,
1379 SectionDataStart, SectionDataSize);
1380
1381 // ... and then the section headers.
1382 uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
1383 for (MCAssembler::const_iterator it = Asm.begin(),
1384 ie = Asm.end(); it != ie; ++it) {
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +00001385 std::vector<macho::RelocationEntry> &Relocs = Relocations[it];
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001386 unsigned NumRelocs = Relocs.size();
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001387 uint64_t SectionStart = SectionDataStart + getSectionAddress(it);
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001388 WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs);
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001389 RelocTableEnd += NumRelocs * macho::RelocationInfoSize;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001390 }
1391
1392 // Write the symbol table load command, if used.
1393 if (NumSymbols) {
1394 unsigned FirstLocalSymbol = 0;
1395 unsigned NumLocalSymbols = LocalSymbolData.size();
1396 unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;
1397 unsigned NumExternalSymbols = ExternalSymbolData.size();
1398 unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;
1399 unsigned NumUndefinedSymbols = UndefinedSymbolData.size();
1400 unsigned NumIndirectSymbols = Asm.indirect_symbol_size();
1401 unsigned NumSymTabSymbols =
1402 NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols;
1403 uint64_t IndirectSymbolSize = NumIndirectSymbols * 4;
1404 uint64_t IndirectSymbolOffset = 0;
1405
1406 // If used, the indirect symbols are written after the section data.
1407 if (NumIndirectSymbols)
1408 IndirectSymbolOffset = RelocTableEnd;
1409
1410 // The symbol table is written after the indirect symbol data.
1411 uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize;
1412
1413 // The string table is written after symbol table.
1414 uint64_t StringTableOffset =
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001415 SymbolTableOffset + NumSymTabSymbols * (is64Bit() ? macho::Nlist64Size :
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001416 macho::Nlist32Size);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001417 WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
1418 StringTableOffset, StringTable.size());
1419
1420 WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
1421 FirstExternalSymbol, NumExternalSymbols,
1422 FirstUndefinedSymbol, NumUndefinedSymbols,
1423 IndirectSymbolOffset, NumIndirectSymbols);
1424 }
1425
1426 // Write the actual section data.
1427 for (MCAssembler::const_iterator it = Asm.begin(),
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001428 ie = Asm.end(); it != ie; ++it) {
Daniel Dunbar5d2477c2010-12-17 02:45:59 +00001429 Asm.WriteSectionData(it, Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001430
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001431 uint64_t Pad = getPaddingSize(it, Layout);
1432 for (unsigned int i = 0; i < Pad; ++i)
1433 Write8(0);
1434 }
1435
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001436 // Write the extra padding.
1437 WriteZeros(SectionDataPadding);
1438
1439 // Write the relocation entries.
1440 for (MCAssembler::const_iterator it = Asm.begin(),
1441 ie = Asm.end(); it != ie; ++it) {
1442 // Write the section relocation entries, in reverse order to match 'as'
1443 // (approximately, the exact algorithm is more complicated than this).
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +00001444 std::vector<macho::RelocationEntry> &Relocs = Relocations[it];
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001445 for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
1446 Write32(Relocs[e - i - 1].Word0);
1447 Write32(Relocs[e - i - 1].Word1);
1448 }
1449 }
1450
1451 // Write the symbol table data, if used.
1452 if (NumSymbols) {
1453 // Write the indirect symbol entries.
1454 for (MCAssembler::const_indirect_symbol_iterator
1455 it = Asm.indirect_symbol_begin(),
1456 ie = Asm.indirect_symbol_end(); it != ie; ++it) {
1457 // Indirect symbols in the non lazy symbol pointer section have some
1458 // special handling.
1459 const MCSectionMachO &Section =
1460 static_cast<const MCSectionMachO&>(it->SectionData->getSection());
1461 if (Section.getType() == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) {
1462 // If this symbol is defined and internal, mark it as such.
1463 if (it->Symbol->isDefined() &&
1464 !Asm.getSymbolData(*it->Symbol).isExternal()) {
Daniel Dunbarf52788f2010-11-27 04:59:14 +00001465 uint32_t Flags = macho::ISF_Local;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001466 if (it->Symbol->isAbsolute())
Daniel Dunbarf52788f2010-11-27 04:59:14 +00001467 Flags |= macho::ISF_Absolute;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001468 Write32(Flags);
1469 continue;
1470 }
1471 }
1472
1473 Write32(Asm.getSymbolData(*it->Symbol).getIndex());
1474 }
1475
1476 // FIXME: Check that offsets match computed ones.
1477
1478 // Write the symbol table entries.
1479 for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001480 WriteNlist(LocalSymbolData[i], Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001481 for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001482 WriteNlist(ExternalSymbolData[i], Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001483 for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001484 WriteNlist(UndefinedSymbolData[i], Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001485
1486 // Write the string table.
1487 OS << StringTable.str();
1488 }
1489 }
1490};
1491
1492}
1493
Daniel Dunbarae5abd52010-12-16 16:09:19 +00001494MCObjectWriter *llvm::createMachObjectWriter(MCMachObjectTargetWriter *MOTW,
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001495 raw_ostream &OS,
Daniel Dunbar115a3dd2010-11-13 07:33:40 +00001496 bool IsLittleEndian) {
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001497 return new MachObjectWriter(MOTW, OS, IsLittleEndian);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001498}