blob: f049b1c6e2a422651e3a8e97a0fd3cc536f24c49 [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) {
Daniel Dunbar5cc63902010-12-22 16:32:41 +000037 default:
38 llvm_unreachable("invalid fixup kind!");
Rafael Espindolae04ed7e2010-11-28 14:17:56 +000039 case FK_PCRel_1:
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000040 case FK_Data_1: return 0;
Rafael Espindolae04ed7e2010-11-28 14:17:56 +000041 case FK_PCRel_2:
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000042 case FK_Data_2: return 1;
Rafael Espindolae04ed7e2010-11-28 14:17:56 +000043 case FK_PCRel_4:
Daniel Dunbar5cc63902010-12-22 16:32:41 +000044 // FIXME: Remove these!!!
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000045 case X86::reloc_riprel_4byte:
Daniel Dunbar602b40f2010-03-19 18:07:55 +000046 case X86::reloc_riprel_4byte_movq_load:
Rafael Espindolaa8c02c32010-09-30 03:11:42 +000047 case X86::reloc_signed_4byte:
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000048 case FK_Data_4: return 2;
49 case FK_Data_8: return 3;
50 }
51}
52
Daniel Dunbare9460ec2010-05-10 23:15:13 +000053static bool doesSymbolRequireExternRelocation(MCSymbolData *SD) {
54 // Undefined symbols are always extern.
55 if (SD->Symbol->isUndefined())
56 return true;
57
58 // References to weak definitions require external relocation entries; the
59 // definition may not always be the one in the same object file.
60 if (SD->getFlags() & SF_WeakDefinition)
61 return true;
62
63 // Otherwise, we can use an internal relocation.
64 return false;
65}
66
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000067namespace {
68
Daniel Dunbar115a3dd2010-11-13 07:33:40 +000069class MachObjectWriter : public MCObjectWriter {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000070 /// MachSymbolData - Helper struct for containing some precomputed information
71 /// on symbols.
72 struct MachSymbolData {
73 MCSymbolData *SymbolData;
74 uint64_t StringIndex;
75 uint8_t SectionIndex;
76
77 // Support lexicographic sorting.
78 bool operator<(const MachSymbolData &RHS) const {
Benjamin Kramerc37791e2010-05-20 14:14:22 +000079 return SymbolData->getSymbol().getName() <
80 RHS.SymbolData->getSymbol().getName();
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000081 }
82 };
83
Daniel Dunbarae5abd52010-12-16 16:09:19 +000084 /// The target specific Mach-O writer instance.
85 llvm::OwningPtr<MCMachObjectTargetWriter> TargetObjectWriter;
Daniel Dunbar7e06af82010-12-16 15:42:31 +000086
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000087 /// @name Relocation Data
88 /// @{
89
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000090 llvm::DenseMap<const MCSectionData*,
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +000091 std::vector<macho::RelocationEntry> > Relocations;
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +000092 llvm::DenseMap<const MCSectionData*, unsigned> IndirectSymBase;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +000093
94 /// @}
95 /// @name Symbol Table Data
96 /// @{
97
98 SmallString<256> StringTable;
99 std::vector<MachSymbolData> LocalSymbolData;
100 std::vector<MachSymbolData> ExternalSymbolData;
101 std::vector<MachSymbolData> UndefinedSymbolData;
102
103 /// @}
104
Daniel Dunbarae5abd52010-12-16 16:09:19 +0000105private:
106 /// @name Utility Methods
107 /// @{
108
109 bool isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) {
110 const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo(
111 (MCFixupKind) Kind);
112
113 return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel;
114 }
115
116 /// @}
117
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000118 SectionAddrMap SectionAddress;
119 uint64_t getSectionAddress(const MCSectionData* SD) const {
120 return SectionAddress.lookup(SD);
121 }
122 uint64_t getSymbolAddress(const MCSymbolData* SD,
123 const MCAsmLayout &Layout) const {
Daniel Dunbar173aa9c2011-04-29 18:13:42 +0000124 const MCSymbol &S = SD->getSymbol();
125
126 // If this is a variable, then recursively evaluate now.
127 if (S.isVariable()) {
128 MCValue Target;
129 if (!S.getVariableValue()->EvaluateAsRelocatable(Target, Layout))
130 report_fatal_error("unable to evaluate offset for variable '" +
131 S.getName() + "'");
132
133 // Verify that any used symbols are defined.
134 if (Target.getSymA() && Target.getSymA()->getSymbol().isUndefined())
135 report_fatal_error("unable to evaluate offset to undefined symbol '" +
136 Target.getSymA()->getSymbol().getName() + "'");
137 if (Target.getSymB() && Target.getSymB()->getSymbol().isUndefined())
138 report_fatal_error("unable to evaluate offset to undefined symbol '" +
139 Target.getSymB()->getSymbol().getName() + "'");
140
141 uint64_t Address = Target.getConstant();
142 if (Target.getSymA())
143 Address += getSymbolAddress(&Layout.getAssembler().getSymbolData(
144 Target.getSymA()->getSymbol()), Layout);
145 if (Target.getSymB())
146 Address += getSymbolAddress(&Layout.getAssembler().getSymbolData(
147 Target.getSymB()->getSymbol()), Layout);
148 return Address;
149 }
150
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000151 return getSectionAddress(SD->getFragment()->getParent()) +
152 Layout.getSymbolOffset(SD);
153 }
154 uint64_t getFragmentAddress(const MCFragment *Fragment,
155 const MCAsmLayout &Layout) const {
156 return getSectionAddress(Fragment->getParent()) +
157 Layout.getFragmentOffset(Fragment);
158 }
159
160 uint64_t getPaddingSize(const MCSectionData *SD,
161 const MCAsmLayout &Layout) const {
162 uint64_t EndAddr = getSectionAddress(SD) + Layout.getSectionAddressSize(SD);
163 unsigned Next = SD->getLayoutOrder() + 1;
164 if (Next >= Layout.getSectionOrder().size())
165 return 0;
166
167 const MCSectionData &NextSD = *Layout.getSectionOrder()[Next];
168 if (NextSD.getSection().isVirtualSection())
169 return 0;
170 return OffsetToAlignment(EndAddr, NextSD.getAlignment());
171 }
172
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000173public:
Daniel Dunbarae5abd52010-12-16 16:09:19 +0000174 MachObjectWriter(MCMachObjectTargetWriter *MOTW, raw_ostream &_OS,
Daniel Dunbar115a3dd2010-11-13 07:33:40 +0000175 bool _IsLittleEndian)
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000176 : MCObjectWriter(_OS, _IsLittleEndian), TargetObjectWriter(MOTW) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000177 }
178
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000179 /// @name Target Writer Proxy Accessors
180 /// @{
181
182 bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
Daniel Dunbar532c4562010-12-22 13:49:43 +0000183 bool isARM() const {
Daniel Dunbarfdfbc6a2010-12-22 16:19:20 +0000184 uint32_t CPUType = TargetObjectWriter->getCPUType() & ~mach::CTFM_ArchMask;
Daniel Dunbar532c4562010-12-22 13:49:43 +0000185 return CPUType == mach::CTM_ARM;
186 }
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000187
188 /// @}
189
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000190 void WriteHeader(unsigned NumLoadCommands, unsigned LoadCommandsSize,
191 bool SubsectionsViaSymbols) {
192 uint32_t Flags = 0;
193
194 if (SubsectionsViaSymbols)
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000195 Flags |= macho::HF_SubsectionsViaSymbols;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000196
197 // struct mach_header (28 bytes) or
198 // struct mach_header_64 (32 bytes)
199
200 uint64_t Start = OS.tell();
201 (void) Start;
202
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000203 Write32(is64Bit() ? macho::HM_Object64 : macho::HM_Object32);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000204
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000205 Write32(TargetObjectWriter->getCPUType());
206 Write32(TargetObjectWriter->getCPUSubtype());
Jim Grosbachc9d14392010-11-05 18:48:58 +0000207
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000208 Write32(macho::HFT_Object);
Daniel Dunbar590956f2010-11-27 07:39:37 +0000209 Write32(NumLoadCommands);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000210 Write32(LoadCommandsSize);
211 Write32(Flags);
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000212 if (is64Bit())
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000213 Write32(0); // reserved
214
Evan Chenge087afa2011-02-01 01:50:49 +0000215 assert(OS.tell() - Start ==
216 (is64Bit() ? macho::Header64Size : macho::Header32Size));
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000217 }
218
219 /// WriteSegmentLoadCommand - Write a segment load command.
220 ///
221 /// \arg NumSections - The number of sections in this segment.
222 /// \arg SectionDataSize - The total size of the sections.
223 void WriteSegmentLoadCommand(unsigned NumSections,
224 uint64_t VMSize,
225 uint64_t SectionDataStartOffset,
226 uint64_t SectionDataSize) {
227 // struct segment_command (56 bytes) or
228 // struct segment_command_64 (72 bytes)
229
230 uint64_t Start = OS.tell();
231 (void) Start;
232
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000233 unsigned SegmentLoadCommandSize =
234 is64Bit() ? macho::SegmentLoadCommand64Size:
Daniel Dunbar821ecd72010-11-27 04:19:38 +0000235 macho::SegmentLoadCommand32Size;
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000236 Write32(is64Bit() ? macho::LCT_Segment64 : macho::LCT_Segment);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000237 Write32(SegmentLoadCommandSize +
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000238 NumSections * (is64Bit() ? macho::Section64Size :
Daniel Dunbar821ecd72010-11-27 04:19:38 +0000239 macho::Section32Size));
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000240
241 WriteBytes("", 16);
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000242 if (is64Bit()) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000243 Write64(0); // vmaddr
244 Write64(VMSize); // vmsize
245 Write64(SectionDataStartOffset); // file offset
246 Write64(SectionDataSize); // file size
247 } else {
248 Write32(0); // vmaddr
249 Write32(VMSize); // vmsize
250 Write32(SectionDataStartOffset); // file offset
251 Write32(SectionDataSize); // file size
252 }
253 Write32(0x7); // maxprot
254 Write32(0x7); // initprot
255 Write32(NumSections);
256 Write32(0); // flags
257
258 assert(OS.tell() - Start == SegmentLoadCommandSize);
259 }
260
Daniel Dunbar207e06e2010-03-24 03:43:40 +0000261 void WriteSection(const MCAssembler &Asm, const MCAsmLayout &Layout,
262 const MCSectionData &SD, uint64_t FileOffset,
263 uint64_t RelocationsStart, unsigned NumRelocations) {
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000264 uint64_t SectionSize = Layout.getSectionAddressSize(&SD);
Daniel Dunbar5d428512010-03-25 02:00:07 +0000265
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000266 // The offset is unused for virtual sections.
Rafael Espindolaf2dc4aa2010-11-17 20:03:54 +0000267 if (SD.getSection().isVirtualSection()) {
Daniel Dunbarb026d642010-03-25 07:10:05 +0000268 assert(Layout.getSectionFileSize(&SD) == 0 && "Invalid file size!");
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000269 FileOffset = 0;
270 }
271
272 // struct section (68 bytes) or
273 // struct section_64 (80 bytes)
274
275 uint64_t Start = OS.tell();
276 (void) Start;
277
Daniel Dunbar56279f42010-05-18 17:28:20 +0000278 const MCSectionMachO &Section = cast<MCSectionMachO>(SD.getSection());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000279 WriteBytes(Section.getSectionName(), 16);
280 WriteBytes(Section.getSegmentName(), 16);
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000281 if (is64Bit()) {
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000282 Write64(getSectionAddress(&SD)); // address
Daniel Dunbar5d428512010-03-25 02:00:07 +0000283 Write64(SectionSize); // size
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000284 } else {
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000285 Write32(getSectionAddress(&SD)); // address
Daniel Dunbar5d428512010-03-25 02:00:07 +0000286 Write32(SectionSize); // size
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000287 }
288 Write32(FileOffset);
289
290 unsigned Flags = Section.getTypeAndAttributes();
291 if (SD.hasInstructions())
292 Flags |= MCSectionMachO::S_ATTR_SOME_INSTRUCTIONS;
293
294 assert(isPowerOf2_32(SD.getAlignment()) && "Invalid alignment!");
295 Write32(Log2_32(SD.getAlignment()));
296 Write32(NumRelocations ? RelocationsStart : 0);
297 Write32(NumRelocations);
298 Write32(Flags);
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +0000299 Write32(IndirectSymBase.lookup(&SD)); // reserved1
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000300 Write32(Section.getStubSize()); // reserved2
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000301 if (is64Bit())
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000302 Write32(0); // reserved3
303
Oscar Fuentes9bf9aa52011-03-01 23:11:57 +0000304 assert(OS.tell() - Start == (is64Bit() ? macho::Section64Size :
305 macho::Section32Size));
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000306 }
307
308 void WriteSymtabLoadCommand(uint32_t SymbolOffset, uint32_t NumSymbols,
309 uint32_t StringTableOffset,
310 uint32_t StringTableSize) {
311 // struct symtab_command (24 bytes)
312
313 uint64_t Start = OS.tell();
314 (void) Start;
315
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000316 Write32(macho::LCT_Symtab);
Daniel Dunbar821ecd72010-11-27 04:19:38 +0000317 Write32(macho::SymtabLoadCommandSize);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000318 Write32(SymbolOffset);
319 Write32(NumSymbols);
320 Write32(StringTableOffset);
321 Write32(StringTableSize);
322
Daniel Dunbar821ecd72010-11-27 04:19:38 +0000323 assert(OS.tell() - Start == macho::SymtabLoadCommandSize);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000324 }
325
326 void WriteDysymtabLoadCommand(uint32_t FirstLocalSymbol,
327 uint32_t NumLocalSymbols,
328 uint32_t FirstExternalSymbol,
329 uint32_t NumExternalSymbols,
330 uint32_t FirstUndefinedSymbol,
331 uint32_t NumUndefinedSymbols,
332 uint32_t IndirectSymbolOffset,
333 uint32_t NumIndirectSymbols) {
334 // struct dysymtab_command (80 bytes)
335
336 uint64_t Start = OS.tell();
337 (void) Start;
338
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000339 Write32(macho::LCT_Dysymtab);
Daniel Dunbar821ecd72010-11-27 04:19:38 +0000340 Write32(macho::DysymtabLoadCommandSize);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000341 Write32(FirstLocalSymbol);
342 Write32(NumLocalSymbols);
343 Write32(FirstExternalSymbol);
344 Write32(NumExternalSymbols);
345 Write32(FirstUndefinedSymbol);
346 Write32(NumUndefinedSymbols);
347 Write32(0); // tocoff
348 Write32(0); // ntoc
349 Write32(0); // modtaboff
350 Write32(0); // nmodtab
351 Write32(0); // extrefsymoff
352 Write32(0); // nextrefsyms
353 Write32(IndirectSymbolOffset);
354 Write32(NumIndirectSymbols);
355 Write32(0); // extreloff
356 Write32(0); // nextrel
357 Write32(0); // locreloff
358 Write32(0); // nlocrel
359
Daniel Dunbar821ecd72010-11-27 04:19:38 +0000360 assert(OS.tell() - Start == macho::DysymtabLoadCommandSize);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000361 }
362
Daniel Dunbar207e06e2010-03-24 03:43:40 +0000363 void WriteNlist(MachSymbolData &MSD, const MCAsmLayout &Layout) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000364 MCSymbolData &Data = *MSD.SymbolData;
365 const MCSymbol &Symbol = Data.getSymbol();
366 uint8_t Type = 0;
367 uint16_t Flags = Data.getFlags();
368 uint32_t Address = 0;
369
370 // Set the N_TYPE bits. See <mach-o/nlist.h>.
371 //
372 // FIXME: Are the prebound or indirect fields possible here?
373 if (Symbol.isUndefined())
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000374 Type = macho::STT_Undefined;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000375 else if (Symbol.isAbsolute())
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000376 Type = macho::STT_Absolute;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000377 else
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000378 Type = macho::STT_Section;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000379
380 // FIXME: Set STAB bits.
381
382 if (Data.isPrivateExtern())
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000383 Type |= macho::STF_PrivateExtern;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000384
385 // Set external bit.
386 if (Data.isExternal() || Symbol.isUndefined())
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000387 Type |= macho::STF_External;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000388
389 // Compute the symbol address.
390 if (Symbol.isDefined()) {
391 if (Symbol.isAbsolute()) {
Daniel Dunbar2d7fd612010-05-05 19:01:05 +0000392 Address = cast<MCConstantExpr>(Symbol.getVariableValue())->getValue();
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000393 } else {
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000394 Address = getSymbolAddress(&Data, Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000395 }
396 } else if (Data.isCommon()) {
397 // Common symbols are encoded with the size in the address
398 // field, and their alignment in the flags.
399 Address = Data.getCommonSize();
400
401 // Common alignment is packed into the 'desc' bits.
402 if (unsigned Align = Data.getCommonAlignment()) {
403 unsigned Log2Size = Log2_32(Align);
404 assert((1U << Log2Size) == Align && "Invalid 'common' alignment!");
405 if (Log2Size > 15)
Chris Lattner75361b62010-04-07 22:58:41 +0000406 report_fatal_error("invalid 'common' alignment '" +
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000407 Twine(Align) + "'");
408 // FIXME: Keep this mask with the SymbolFlags enumeration.
409 Flags = (Flags & 0xF0FF) | (Log2Size << 8);
410 }
411 }
412
413 // struct nlist (12 bytes)
414
415 Write32(MSD.StringIndex);
416 Write8(Type);
417 Write8(MSD.SectionIndex);
418
419 // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
420 // value.
421 Write16(Flags);
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000422 if (is64Bit())
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000423 Write64(Address);
424 else
425 Write32(Address);
426 }
427
Daniel Dunbar35b06572010-03-22 23:16:43 +0000428 // FIXME: We really need to improve the relocation validation. Basically, we
429 // want to implement a separate computation which evaluates the relocation
430 // entry as the linker would, and verifies that the resultant fixup value is
431 // exactly what the encoder wanted. This will catch several classes of
432 // problems:
433 //
434 // - Relocation entry bugs, the two algorithms are unlikely to have the same
435 // exact bug.
436 //
437 // - Relaxation issues, where we forget to relax something.
438 //
439 // - Input errors, where something cannot be correctly encoded. 'as' allows
440 // these through in many cases.
441
Daniel Dunbar7e06af82010-12-16 15:42:31 +0000442 static bool isFixupKindRIPRel(unsigned Kind) {
443 return Kind == X86::reloc_riprel_4byte ||
444 Kind == X86::reloc_riprel_4byte_movq_load;
445 }
Daniel Dunbar207e06e2010-03-24 03:43:40 +0000446 void RecordX86_64Relocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
Daniel Dunbarb7514182010-03-22 20:35:50 +0000447 const MCFragment *Fragment,
Daniel Dunbarc90e30a2010-05-26 15:18:56 +0000448 const MCFixup &Fixup, MCValue Target,
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000449 uint64_t &FixedValue) {
Daniel Dunbar7e06af82010-12-16 15:42:31 +0000450 unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
Daniel Dunbar482ad802010-05-26 15:18:31 +0000451 unsigned IsRIPRel = isFixupKindRIPRel(Fixup.getKind());
452 unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000453
454 // See <reloc.h>.
Daniel Dunbar482ad802010-05-26 15:18:31 +0000455 uint32_t FixupOffset =
456 Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
457 uint32_t FixupAddress =
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000458 getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000459 int64_t Value = 0;
460 unsigned Index = 0;
461 unsigned IsExtern = 0;
462 unsigned Type = 0;
463
464 Value = Target.getConstant();
465
466 if (IsPCRel) {
467 // Compensate for the relocation offset, Darwin x86_64 relocations only
468 // have the addend and appear to have attempted to define it to be the
469 // actual expression addend without the PCrel bias. However, instructions
Chris Lattner7a2bdde2011-04-15 05:18:47 +0000470 // with data following the relocation are not accommodated for (see comment
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000471 // below regarding SIGNED{1,2,4}), so it isn't exactly that either.
Benjamin Kramer454c4ce2010-04-08 15:25:57 +0000472 Value += 1LL << Log2Size;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000473 }
474
475 if (Target.isAbsolute()) { // constant
476 // SymbolNum of 0 indicates the absolute section.
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000477 Type = macho::RIT_X86_64_Unsigned;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000478 Index = 0;
479
480 // FIXME: I believe this is broken, I don't think the linker can
481 // understand it. I think it would require a local relocation, but I'm not
482 // sure if that would work either. The official way to get an absolute
483 // PCrel relocation is to use an absolute symbol (which we don't support
484 // yet).
485 if (IsPCRel) {
486 IsExtern = 1;
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000487 Type = macho::RIT_X86_64_Branch;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000488 }
489 } else if (Target.getSymB()) { // A - B + constant
490 const MCSymbol *A = &Target.getSymA()->getSymbol();
491 MCSymbolData &A_SD = Asm.getSymbolData(*A);
Rafael Espindolab8141102010-09-27 18:13:03 +0000492 const MCSymbolData *A_Base = Asm.getAtom(&A_SD);
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000493
494 const MCSymbol *B = &Target.getSymB()->getSymbol();
495 MCSymbolData &B_SD = Asm.getSymbolData(*B);
Rafael Espindolab8141102010-09-27 18:13:03 +0000496 const MCSymbolData *B_Base = Asm.getAtom(&B_SD);
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000497
498 // Neither symbol can be modified.
499 if (Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None ||
500 Target.getSymB()->getKind() != MCSymbolRefExpr::VK_None)
Chris Lattner75361b62010-04-07 22:58:41 +0000501 report_fatal_error("unsupported relocation of modified symbol");
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000502
503 // We don't support PCrel relocations of differences. Darwin 'as' doesn't
504 // implement most of these correctly.
505 if (IsPCRel)
Chris Lattner75361b62010-04-07 22:58:41 +0000506 report_fatal_error("unsupported pc-relative relocation of difference");
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000507
Kevin Enderby8c9aa922010-10-02 00:13:41 +0000508 // The support for the situation where one or both of the symbols would
509 // require a local relocation is handled just like if the symbols were
510 // external. This is certainly used in the case of debug sections where
511 // the section has only temporary symbols and thus the symbols don't have
512 // base symbols. This is encoded using the section ordinal and
513 // non-extern relocation entries.
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000514
515 // Darwin 'as' doesn't emit correct relocations for this (it ends up with
Kevin Enderby8c9aa922010-10-02 00:13:41 +0000516 // a single SIGNED relocation); reject it for now. Except the case where
517 // both symbols don't have a base, equal but both NULL.
518 if (A_Base == B_Base && A_Base)
Chris Lattner75361b62010-04-07 22:58:41 +0000519 report_fatal_error("unsupported relocation with identical base");
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000520
Rafael Espindolaf10d2be2010-12-07 01:09:54 +0000521 Value += getSymbolAddress(&A_SD, Layout) -
522 (A_Base == NULL ? 0 : getSymbolAddress(A_Base, Layout));
523 Value -= getSymbolAddress(&B_SD, Layout) -
524 (B_Base == NULL ? 0 : getSymbolAddress(B_Base, Layout));
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000525
Kevin Enderby8c9aa922010-10-02 00:13:41 +0000526 if (A_Base) {
527 Index = A_Base->getIndex();
528 IsExtern = 1;
529 }
530 else {
531 Index = A_SD.getFragment()->getParent()->getOrdinal() + 1;
532 IsExtern = 0;
533 }
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000534 Type = macho::RIT_X86_64_Unsigned;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000535
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +0000536 macho::RelocationEntry MRE;
Daniel Dunbar640e9482010-05-11 23:53:07 +0000537 MRE.Word0 = FixupOffset;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000538 MRE.Word1 = ((Index << 0) |
539 (IsPCRel << 24) |
540 (Log2Size << 25) |
541 (IsExtern << 27) |
542 (Type << 28));
Daniel Dunbarb7514182010-03-22 20:35:50 +0000543 Relocations[Fragment->getParent()].push_back(MRE);
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000544
Kevin Enderby8c9aa922010-10-02 00:13:41 +0000545 if (B_Base) {
546 Index = B_Base->getIndex();
547 IsExtern = 1;
548 }
549 else {
550 Index = B_SD.getFragment()->getParent()->getOrdinal() + 1;
551 IsExtern = 0;
552 }
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000553 Type = macho::RIT_X86_64_Subtractor;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000554 } else {
555 const MCSymbol *Symbol = &Target.getSymA()->getSymbol();
556 MCSymbolData &SD = Asm.getSymbolData(*Symbol);
Rafael Espindolab8141102010-09-27 18:13:03 +0000557 const MCSymbolData *Base = Asm.getAtom(&SD);
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000558
Daniel Dunbarae7fb0b2010-05-05 17:22:39 +0000559 // Relocations inside debug sections always use local relocations when
560 // possible. This seems to be done because the debugger doesn't fully
561 // understand x86_64 relocation entries, and expects to find values that
562 // have already been fixed up.
Daniel Dunbar2d7fd612010-05-05 19:01:05 +0000563 if (Symbol->isInSection()) {
Daniel Dunbarae7fb0b2010-05-05 17:22:39 +0000564 const MCSectionMachO &Section = static_cast<const MCSectionMachO&>(
565 Fragment->getParent()->getSection());
566 if (Section.hasAttribute(MCSectionMachO::S_ATTR_DEBUG))
567 Base = 0;
568 }
569
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000570 // x86_64 almost always uses external relocations, except when there is no
Chris Lattner7a2bdde2011-04-15 05:18:47 +0000571 // symbol to use as a base address (a local symbol with no preceding
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000572 // non-local symbol).
573 if (Base) {
574 Index = Base->getIndex();
575 IsExtern = 1;
576
577 // Add the local offset, if needed.
578 if (Base != &SD)
Rafael Espindola1dda29b2010-12-06 21:51:55 +0000579 Value += Layout.getSymbolOffset(&SD) - Layout.getSymbolOffset(Base);
Daniel Dunbar5ff919b2011-04-29 18:10:47 +0000580 } else if (Symbol->isInSection() && !Symbol->isVariable()) {
Daniel Dunbar8fb04032010-03-25 08:08:54 +0000581 // The index is the section ordinal (1-based).
582 Index = SD.getFragment()->getParent()->getOrdinal() + 1;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000583 IsExtern = 0;
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000584 Value += getSymbolAddress(&SD, Layout);
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000585
586 if (IsPCRel)
Daniel Dunbardb4c7e62010-05-11 23:53:11 +0000587 Value -= FixupAddress + (1 << Log2Size);
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000588 } else if (Symbol->isVariable()) {
589 const MCExpr *Value = Symbol->getVariableValue();
590 int64_t Res;
591 bool isAbs = Value->EvaluateAsAbsolute(Res, Layout, SectionAddress);
592 if (isAbs) {
593 FixedValue = Res;
594 return;
595 } else {
596 report_fatal_error("unsupported relocation of variable '" +
597 Symbol->getName() + "'");
598 }
Daniel Dunbaref4591e2010-05-11 23:53:05 +0000599 } else {
600 report_fatal_error("unsupported relocation of undefined symbol '" +
601 Symbol->getName() + "'");
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000602 }
603
604 MCSymbolRefExpr::VariantKind Modifier = Target.getSymA()->getKind();
605 if (IsPCRel) {
606 if (IsRIPRel) {
607 if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
608 // x86_64 distinguishes movq foo@GOTPCREL so that the linker can
609 // rewrite the movq to an leaq at link time if the symbol ends up in
610 // the same linkage unit.
Daniel Dunbar482ad802010-05-26 15:18:31 +0000611 if (unsigned(Fixup.getKind()) == X86::reloc_riprel_4byte_movq_load)
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000612 Type = macho::RIT_X86_64_GOTLoad;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000613 else
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000614 Type = macho::RIT_X86_64_GOT;
Eric Christopheraeed4d82010-05-27 00:52:31 +0000615 } else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000616 Type = macho::RIT_X86_64_TLV;
Eric Christopheraeed4d82010-05-27 00:52:31 +0000617 } else if (Modifier != MCSymbolRefExpr::VK_None) {
618 report_fatal_error("unsupported symbol modifier in relocation");
Daniel Dunbarf0f6cdb2010-05-14 18:53:40 +0000619 } else {
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000620 Type = macho::RIT_X86_64_Signed;
Daniel Dunbarf0f6cdb2010-05-14 18:53:40 +0000621
622 // The Darwin x86_64 relocation format has a problem where it cannot
623 // encode an address (L<foo> + <constant>) which is outside the atom
624 // containing L<foo>. Generally, this shouldn't occur but it does
625 // happen when we have a RIPrel instruction with data following the
626 // relocation entry (e.g., movb $012, L0(%rip)). Even with the PCrel
627 // adjustment Darwin x86_64 uses, the offset is still negative and
628 // the linker has no way to recognize this.
629 //
630 // To work around this, Darwin uses several special relocation types
631 // to indicate the offsets. However, the specification or
632 // implementation of these seems to also be incomplete; they should
633 // adjust the addend as well based on the actual encoded instruction
634 // (the additional bias), but instead appear to just look at the
635 // final offset.
636 switch (-(Target.getConstant() + (1LL << Log2Size))) {
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000637 case 1: Type = macho::RIT_X86_64_Signed1; break;
638 case 2: Type = macho::RIT_X86_64_Signed2; break;
639 case 4: Type = macho::RIT_X86_64_Signed4; break;
Daniel Dunbarf0f6cdb2010-05-14 18:53:40 +0000640 }
641 }
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000642 } else {
643 if (Modifier != MCSymbolRefExpr::VK_None)
Chris Lattner75361b62010-04-07 22:58:41 +0000644 report_fatal_error("unsupported symbol modifier in branch "
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000645 "relocation");
646
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000647 Type = macho::RIT_X86_64_Branch;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000648 }
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000649 } else {
Daniel Dunbar1de558b2010-03-29 23:56:40 +0000650 if (Modifier == MCSymbolRefExpr::VK_GOT) {
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000651 Type = macho::RIT_X86_64_GOT;
Daniel Dunbar1de558b2010-03-29 23:56:40 +0000652 } else if (Modifier == MCSymbolRefExpr::VK_GOTPCREL) {
653 // GOTPCREL is allowed as a modifier on non-PCrel instructions, in
654 // which case all we do is set the PCrel bit in the relocation entry;
655 // this is used with exception handling, for example. The source is
656 // required to include any necessary offset directly.
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000657 Type = macho::RIT_X86_64_GOT;
Daniel Dunbar1de558b2010-03-29 23:56:40 +0000658 IsPCRel = 1;
Eric Christopher96ac5152010-05-26 00:02:12 +0000659 } else if (Modifier == MCSymbolRefExpr::VK_TLVP) {
660 report_fatal_error("TLVP symbol modifier should have been rip-rel");
Daniel Dunbar1de558b2010-03-29 23:56:40 +0000661 } else if (Modifier != MCSymbolRefExpr::VK_None)
Chris Lattner75361b62010-04-07 22:58:41 +0000662 report_fatal_error("unsupported symbol modifier in relocation");
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000663 else
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000664 Type = macho::RIT_X86_64_Unsigned;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000665 }
666 }
667
668 // x86_64 always writes custom values into the fixups.
669 FixedValue = Value;
670
671 // struct relocation_info (8 bytes)
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +0000672 macho::RelocationEntry MRE;
Daniel Dunbar640e9482010-05-11 23:53:07 +0000673 MRE.Word0 = FixupOffset;
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000674 MRE.Word1 = ((Index << 0) |
675 (IsPCRel << 24) |
676 (Log2Size << 25) |
677 (IsExtern << 27) |
678 (Type << 28));
Daniel Dunbarb7514182010-03-22 20:35:50 +0000679 Relocations[Fragment->getParent()].push_back(MRE);
Daniel Dunbar602b40f2010-03-19 18:07:55 +0000680 }
681
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000682 void RecordScatteredRelocation(const MCAssembler &Asm,
Daniel Dunbar207e06e2010-03-24 03:43:40 +0000683 const MCAsmLayout &Layout,
Daniel Dunbarb7514182010-03-22 20:35:50 +0000684 const MCFragment *Fragment,
Daniel Dunbarc90e30a2010-05-26 15:18:56 +0000685 const MCFixup &Fixup, MCValue Target,
Evan Chengf3eb3bb2011-01-14 02:38:49 +0000686 unsigned Log2Size,
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000687 uint64_t &FixedValue) {
Daniel Dunbar482ad802010-05-26 15:18:31 +0000688 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
Daniel Dunbar7e06af82010-12-16 15:42:31 +0000689 unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000690 unsigned Type = macho::RIT_Vanilla;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000691
692 // See <reloc.h>.
693 const MCSymbol *A = &Target.getSymA()->getSymbol();
694 MCSymbolData *A_SD = &Asm.getSymbolData(*A);
695
696 if (!A_SD->getFragment())
Chris Lattner75361b62010-04-07 22:58:41 +0000697 report_fatal_error("symbol '" + A->getName() +
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000698 "' can not be undefined in a subtraction expression");
699
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000700 uint32_t Value = getSymbolAddress(A_SD, Layout);
701 uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent());
702 FixedValue += SecAddr;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000703 uint32_t Value2 = 0;
704
705 if (const MCSymbolRefExpr *B = Target.getSymB()) {
706 MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
707
708 if (!B_SD->getFragment())
Chris Lattner75361b62010-04-07 22:58:41 +0000709 report_fatal_error("symbol '" + B->getSymbol().getName() +
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000710 "' can not be undefined in a subtraction expression");
711
712 // Select the appropriate difference relocation type.
713 //
714 // Note that there is no longer any semantic difference between these two
715 // relocation types from the linkers point of view, this is done solely
716 // for pedantic compatibility with 'as'.
Matt Beaumont-Gaye733cf82010-12-21 23:43:23 +0000717 Type = A_SD->isExternal() ? (unsigned)macho::RIT_Difference :
718 (unsigned)macho::RIT_Generic_LocalDifference;
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000719 Value2 = getSymbolAddress(B_SD, Layout);
720 FixedValue -= getSectionAddress(B_SD->getFragment()->getParent());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000721 }
722
723 // Relocations are written out in reverse order, so the PAIR comes first.
Daniel Dunbare1feeb92010-12-21 15:26:45 +0000724 if (Type == macho::RIT_Difference ||
725 Type == macho::RIT_Generic_LocalDifference) {
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +0000726 macho::RelocationEntry MRE;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000727 MRE.Word0 = ((0 << 0) |
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000728 (macho::RIT_Pair << 24) |
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000729 (Log2Size << 28) |
730 (IsPCRel << 30) |
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000731 macho::RF_Scattered);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000732 MRE.Word1 = Value2;
Daniel Dunbarb7514182010-03-22 20:35:50 +0000733 Relocations[Fragment->getParent()].push_back(MRE);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000734 }
735
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +0000736 macho::RelocationEntry MRE;
Daniel Dunbar640e9482010-05-11 23:53:07 +0000737 MRE.Word0 = ((FixupOffset << 0) |
738 (Type << 24) |
739 (Log2Size << 28) |
740 (IsPCRel << 30) |
Daniel Dunbarf52788f2010-11-27 04:59:14 +0000741 macho::RF_Scattered);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000742 MRE.Word1 = Value;
Daniel Dunbarb7514182010-03-22 20:35:50 +0000743 Relocations[Fragment->getParent()].push_back(MRE);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +0000744 }
745
Daniel Dunbar25bcc9c2010-12-22 16:45:29 +0000746 void RecordARMScatteredRelocation(const MCAssembler &Asm,
747 const MCAsmLayout &Layout,
748 const MCFragment *Fragment,
749 const MCFixup &Fixup, MCValue Target,
Evan Chengf3eb3bb2011-01-14 02:38:49 +0000750 unsigned Log2Size,
Daniel Dunbar25bcc9c2010-12-22 16:45:29 +0000751 uint64_t &FixedValue) {
752 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
753 unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
Daniel Dunbar25bcc9c2010-12-22 16:45:29 +0000754 unsigned Type = macho::RIT_Vanilla;
755
756 // See <reloc.h>.
757 const MCSymbol *A = &Target.getSymA()->getSymbol();
758 MCSymbolData *A_SD = &Asm.getSymbolData(*A);
759
760 if (!A_SD->getFragment())
761 report_fatal_error("symbol '" + A->getName() +
762 "' can not be undefined in a subtraction expression");
763
764 uint32_t Value = getSymbolAddress(A_SD, Layout);
765 uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent());
766 FixedValue += SecAddr;
767 uint32_t Value2 = 0;
768
769 if (const MCSymbolRefExpr *B = Target.getSymB()) {
770 MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
771
772 if (!B_SD->getFragment())
773 report_fatal_error("symbol '" + B->getSymbol().getName() +
774 "' can not be undefined in a subtraction expression");
775
776 // Select the appropriate difference relocation type.
Daniel Dunbardf561e02010-12-22 16:52:19 +0000777 Type = macho::RIT_Difference;
Daniel Dunbar25bcc9c2010-12-22 16:45:29 +0000778 Value2 = getSymbolAddress(B_SD, Layout);
779 FixedValue -= getSectionAddress(B_SD->getFragment()->getParent());
780 }
781
782 // Relocations are written out in reverse order, so the PAIR comes first.
783 if (Type == macho::RIT_Difference ||
784 Type == macho::RIT_Generic_LocalDifference) {
785 macho::RelocationEntry MRE;
786 MRE.Word0 = ((0 << 0) |
787 (macho::RIT_Pair << 24) |
788 (Log2Size << 28) |
789 (IsPCRel << 30) |
790 macho::RF_Scattered);
791 MRE.Word1 = Value2;
792 Relocations[Fragment->getParent()].push_back(MRE);
793 }
794
795 macho::RelocationEntry MRE;
796 MRE.Word0 = ((FixupOffset << 0) |
797 (Type << 24) |
798 (Log2Size << 28) |
799 (IsPCRel << 30) |
800 macho::RF_Scattered);
801 MRE.Word1 = Value;
802 Relocations[Fragment->getParent()].push_back(MRE);
803 }
804
Evan Chengf3eb3bb2011-01-14 02:38:49 +0000805 void RecordARMMovwMovtRelocation(const MCAssembler &Asm,
806 const MCAsmLayout &Layout,
807 const MCFragment *Fragment,
808 const MCFixup &Fixup, MCValue Target,
809 uint64_t &FixedValue) {
810 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
811 unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
812 unsigned Type = macho::RIT_ARM_Half;
813
814 // See <reloc.h>.
815 const MCSymbol *A = &Target.getSymA()->getSymbol();
816 MCSymbolData *A_SD = &Asm.getSymbolData(*A);
817
818 if (!A_SD->getFragment())
819 report_fatal_error("symbol '" + A->getName() +
820 "' can not be undefined in a subtraction expression");
821
822 uint32_t Value = getSymbolAddress(A_SD, Layout);
823 uint32_t Value2 = 0;
824 uint64_t SecAddr = getSectionAddress(A_SD->getFragment()->getParent());
825 FixedValue += SecAddr;
826
827 if (const MCSymbolRefExpr *B = Target.getSymB()) {
828 MCSymbolData *B_SD = &Asm.getSymbolData(B->getSymbol());
829
830 if (!B_SD->getFragment())
831 report_fatal_error("symbol '" + B->getSymbol().getName() +
832 "' can not be undefined in a subtraction expression");
833
834 // Select the appropriate difference relocation type.
835 Type = macho::RIT_ARM_HalfDifference;
836 Value2 = getSymbolAddress(B_SD, Layout);
837 FixedValue -= getSectionAddress(B_SD->getFragment()->getParent());
838 }
839
840 // Relocations are written out in reverse order, so the PAIR comes first.
841 // ARM_RELOC_HALF and ARM_RELOC_HALF_SECTDIFF abuse the r_length field:
842 //
843 // For these two r_type relocations they always have a pair following them
844 // and the r_length bits are used differently. The encoding of the
845 // r_length is as follows:
846 // low bit of r_length:
847 // 0 - :lower16: for movw instructions
848 // 1 - :upper16: for movt instructions
849 // high bit of r_length:
850 // 0 - arm instructions
Owen Andersonf862b352011-03-22 22:52:54 +0000851 // 1 - thumb instructions
Evan Chengf3eb3bb2011-01-14 02:38:49 +0000852 // the other half of the relocated expression is in the following pair
853 // relocation entry in the the low 16 bits of r_address field.
854 unsigned ThumbBit = 0;
855 unsigned MovtBit = 0;
Duncan Sands36b8e432011-03-15 08:54:51 +0000856 switch ((unsigned)Fixup.getKind()) {
Evan Chengf3eb3bb2011-01-14 02:38:49 +0000857 default: break;
858 case ARM::fixup_arm_movt_hi16:
859 case ARM::fixup_arm_movt_hi16_pcrel:
860 MovtBit = 1;
861 break;
862 case ARM::fixup_t2_movt_hi16:
863 case ARM::fixup_t2_movt_hi16_pcrel:
864 MovtBit = 1;
865 // Fallthrough
866 case ARM::fixup_t2_movw_lo16:
867 case ARM::fixup_t2_movw_lo16_pcrel:
868 ThumbBit = 1;
869 break;
870 }
871
872
873 if (Type == macho::RIT_ARM_HalfDifference) {
874 uint32_t OtherHalf = MovtBit
875 ? (FixedValue & 0xffff) : ((FixedValue & 0xffff0000) >> 16);
876
877 macho::RelocationEntry MRE;
878 MRE.Word0 = ((OtherHalf << 0) |
879 (macho::RIT_Pair << 24) |
880 (MovtBit << 28) |
881 (ThumbBit << 29) |
882 (IsPCRel << 30) |
883 macho::RF_Scattered);
884 MRE.Word1 = Value2;
885 Relocations[Fragment->getParent()].push_back(MRE);
886 }
887
888 macho::RelocationEntry MRE;
889 MRE.Word0 = ((FixupOffset << 0) |
890 (Type << 24) |
891 (MovtBit << 28) |
892 (ThumbBit << 29) |
893 (IsPCRel << 30) |
894 macho::RF_Scattered);
895 MRE.Word1 = Value;
896 Relocations[Fragment->getParent()].push_back(MRE);
897 }
898
Eric Christopherc9ada472010-06-15 22:59:05 +0000899 void RecordTLVPRelocation(const MCAssembler &Asm,
Eric Christophere48dbf82010-06-16 00:26:36 +0000900 const MCAsmLayout &Layout,
901 const MCFragment *Fragment,
902 const MCFixup &Fixup, MCValue Target,
903 uint64_t &FixedValue) {
Eric Christopherc9ada472010-06-15 22:59:05 +0000904 assert(Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP &&
Daniel Dunbar5d05d972010-12-16 17:21:02 +0000905 !is64Bit() &&
Eric Christopherc9ada472010-06-15 22:59:05 +0000906 "Should only be called with a 32-bit TLVP relocation!");
907
Eric Christopherc9ada472010-06-15 22:59:05 +0000908 unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
909 uint32_t Value = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
910 unsigned IsPCRel = 0;
911
912 // Get the symbol data.
913 MCSymbolData *SD_A = &Asm.getSymbolData(Target.getSymA()->getSymbol());
914 unsigned Index = SD_A->getIndex();
915
Eric Christopherbc067372010-06-16 21:32:38 +0000916 // We're only going to have a second symbol in pic mode and it'll be a
917 // subtraction from the picbase. For 32-bit pic the addend is the difference
Eric Christopher04b8d3c2010-06-17 00:49:46 +0000918 // between the picbase and the next address. For 32-bit static the addend
919 // is zero.
Eric Christopherbc067372010-06-16 21:32:38 +0000920 if (Target.getSymB()) {
Eric Christopher1008d352010-06-22 23:51:47 +0000921 // If this is a subtraction then we're pcrel.
922 uint32_t FixupAddress =
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000923 getFragmentAddress(Fragment, Layout) + Fixup.getOffset();
Eric Christopher1008d352010-06-22 23:51:47 +0000924 MCSymbolData *SD_B = &Asm.getSymbolData(Target.getSymB()->getSymbol());
Eric Christopherc9ada472010-06-15 22:59:05 +0000925 IsPCRel = 1;
Rafael Espindola85f2ecc2010-12-07 00:27:36 +0000926 FixedValue = (FixupAddress - getSymbolAddress(SD_B, Layout) +
Eric Christopher1008d352010-06-22 23:51:47 +0000927 Target.getConstant());
Chris Lattnerabf8f9c2010-08-16 16:35:20 +0000928 FixedValue += 1ULL << Log2Size;
Eric Christopherbc067372010-06-16 21:32:38 +0000929 } else {
930 FixedValue = 0;
931 }
Jim Grosbach3c384922010-11-11 20:16:23 +0000932
Eric Christopherc9ada472010-06-15 22:59:05 +0000933 // struct relocation_info (8 bytes)
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +0000934 macho::RelocationEntry MRE;
Eric Christopherc9ada472010-06-15 22:59:05 +0000935 MRE.Word0 = Value;
Daniel Dunbare1feeb92010-12-21 15:26:45 +0000936 MRE.Word1 = ((Index << 0) |
937 (IsPCRel << 24) |
938 (Log2Size << 25) |
939 (1 << 27) | // Extern
940 (macho::RIT_Generic_TLV << 28)); // Type
Eric Christopherc9ada472010-06-15 22:59:05 +0000941 Relocations[Fragment->getParent()].push_back(MRE);
942 }
Jim Grosbach3c384922010-11-11 20:16:23 +0000943
Daniel Dunbare8624532010-12-27 14:49:49 +0000944 static bool getARMFixupKindMachOInfo(unsigned Kind, unsigned &RelocType,
Daniel Dunbar294e6782010-12-22 16:19:24 +0000945 unsigned &Log2Size) {
Daniel Dunbare8624532010-12-27 14:49:49 +0000946 RelocType = unsigned(macho::RIT_Vanilla);
Daniel Dunbar36645642010-12-22 16:32:37 +0000947 Log2Size = ~0U;
948
Daniel Dunbar294e6782010-12-22 16:19:24 +0000949 switch (Kind) {
950 default:
951 return false;
952
Daniel Dunbar36645642010-12-22 16:32:37 +0000953 case FK_Data_1:
954 Log2Size = llvm::Log2_32(1);
955 return true;
956 case FK_Data_2:
957 Log2Size = llvm::Log2_32(2);
958 return true;
959 case FK_Data_4:
960 Log2Size = llvm::Log2_32(4);
961 return true;
962 case FK_Data_8:
963 Log2Size = llvm::Log2_32(8);
964 return true;
965
Daniel Dunbar294e6782010-12-22 16:19:24 +0000966 // Handle 24-bit branch kinds.
967 case ARM::fixup_arm_ldst_pcrel_12:
968 case ARM::fixup_arm_pcrel_10:
969 case ARM::fixup_arm_adr_pcrel_12:
Jason W Kim685c3502011-02-04 19:47:15 +0000970 case ARM::fixup_arm_condbranch:
971 case ARM::fixup_arm_uncondbranch:
Daniel Dunbare8624532010-12-27 14:49:49 +0000972 RelocType = unsigned(macho::RIT_ARM_Branch24Bit);
Daniel Dunbar294e6782010-12-22 16:19:24 +0000973 // Report as 'long', even though that is not quite accurate.
974 Log2Size = llvm::Log2_32(4);
975 return true;
Daniel Dunbar4010dd72010-12-24 16:41:46 +0000976
977 // Handle Thumb branches.
978 case ARM::fixup_arm_thumb_br:
Daniel Dunbare8624532010-12-27 14:49:49 +0000979 RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit);
Daniel Dunbar4010dd72010-12-24 16:41:46 +0000980 Log2Size = llvm::Log2_32(2);
981 return true;
Owen Anderson76147832011-03-23 21:19:56 +0000982
983 case ARM::fixup_arm_thumb_bl:
Daniel Dunbar4010dd72010-12-24 16:41:46 +0000984 case ARM::fixup_arm_thumb_blx:
Daniel Dunbare8624532010-12-27 14:49:49 +0000985 RelocType = unsigned(macho::RIT_ARM_ThumbBranch22Bit);
Daniel Dunbar4010dd72010-12-24 16:41:46 +0000986 Log2Size = llvm::Log2_32(4);
987 return true;
Evan Chengf3eb3bb2011-01-14 02:38:49 +0000988
989 case ARM::fixup_arm_movt_hi16:
990 case ARM::fixup_arm_movt_hi16_pcrel:
991 case ARM::fixup_t2_movt_hi16:
992 case ARM::fixup_t2_movt_hi16_pcrel:
993 RelocType = unsigned(macho::RIT_ARM_HalfDifference);
994 // Report as 'long', even though that is not quite accurate.
995 Log2Size = llvm::Log2_32(4);
996 return true;
997
998 case ARM::fixup_arm_movw_lo16:
999 case ARM::fixup_arm_movw_lo16_pcrel:
1000 case ARM::fixup_t2_movw_lo16:
1001 case ARM::fixup_t2_movw_lo16_pcrel:
1002 RelocType = unsigned(macho::RIT_ARM_Half);
1003 // Report as 'long', even though that is not quite accurate.
1004 Log2Size = llvm::Log2_32(4);
1005 return true;
Daniel Dunbar294e6782010-12-22 16:19:24 +00001006 }
1007 }
Daniel Dunbar532c4562010-12-22 13:49:43 +00001008 void RecordARMRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
1009 const MCFragment *Fragment, const MCFixup &Fixup,
1010 MCValue Target, uint64_t &FixedValue) {
Daniel Dunbar4d743052010-12-22 13:50:05 +00001011 unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
Daniel Dunbar294e6782010-12-22 16:19:24 +00001012 unsigned Log2Size;
Daniel Dunbare8624532010-12-27 14:49:49 +00001013 unsigned RelocType = macho::RIT_Vanilla;
1014 if (!getARMFixupKindMachOInfo(Fixup.getKind(), RelocType, Log2Size)) {
Daniel Dunbar294e6782010-12-22 16:19:24 +00001015 report_fatal_error("unknown ARM fixup kind!");
1016 return;
1017 }
Daniel Dunbar4d743052010-12-22 13:50:05 +00001018
1019 // If this is a difference or a defined symbol plus an offset, then we need
1020 // a scattered relocation entry. Differences always require scattered
1021 // relocations.
Evan Chengf3eb3bb2011-01-14 02:38:49 +00001022 if (Target.getSymB()) {
1023 if (RelocType == macho::RIT_ARM_Half ||
1024 RelocType == macho::RIT_ARM_HalfDifference)
1025 return RecordARMMovwMovtRelocation(Asm, Layout, Fragment, Fixup,
1026 Target, FixedValue);
1027 return RecordARMScatteredRelocation(Asm, Layout, Fragment, Fixup,
1028 Target, Log2Size, FixedValue);
1029 }
Daniel Dunbar4d743052010-12-22 13:50:05 +00001030
1031 // Get the symbol data, if any.
1032 MCSymbolData *SD = 0;
1033 if (Target.getSymA())
1034 SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
1035
1036 // FIXME: For other platforms, we need to use scattered relocations for
1037 // internal relocations with offsets. If this is an internal relocation
1038 // with an offset, it also needs a scattered relocation entry.
1039 //
1040 // Is this right for ARM?
1041 uint32_t Offset = Target.getConstant();
Daniel Dunbare8624532010-12-27 14:49:49 +00001042 if (IsPCRel && RelocType == macho::RIT_Vanilla)
Daniel Dunbar4d743052010-12-22 13:50:05 +00001043 Offset += 1 << Log2Size;
1044 if (Offset && SD && !doesSymbolRequireExternRelocation(SD))
Evan Chengf3eb3bb2011-01-14 02:38:49 +00001045 return RecordARMScatteredRelocation(Asm, Layout, Fragment, Fixup, Target,
1046 Log2Size, FixedValue);
Daniel Dunbar4d743052010-12-22 13:50:05 +00001047
1048 // See <reloc.h>.
1049 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
1050 unsigned Index = 0;
1051 unsigned IsExtern = 0;
1052 unsigned Type = 0;
1053
1054 if (Target.isAbsolute()) { // constant
1055 // FIXME!
1056 report_fatal_error("FIXME: relocations to absolute targets "
1057 "not yet implemented");
Daniel Dunbar5ff919b2011-04-29 18:10:47 +00001058 } else {
1059 // Resolve constant variables.
1060 if (SD->getSymbol().isVariable()) {
1061 int64_t Res;
1062 if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
1063 Res, Layout, SectionAddress)) {
1064 FixedValue = Res;
1065 return;
1066 }
Daniel Dunbar4d743052010-12-22 13:50:05 +00001067 }
1068
Daniel Dunbar4d743052010-12-22 13:50:05 +00001069 // Check whether we need an external or internal relocation.
1070 if (doesSymbolRequireExternRelocation(SD)) {
1071 IsExtern = 1;
1072 Index = SD->getIndex();
1073 // For external relocations, make sure to offset the fixup value to
1074 // compensate for the addend of the symbol address, if it was
1075 // undefined. This occurs with weak definitions, for example.
1076 if (!SD->Symbol->isUndefined())
1077 FixedValue -= Layout.getSymbolOffset(SD);
1078 } else {
1079 // The index is the section ordinal (1-based).
Daniel Dunbar08b99352011-04-29 18:07:43 +00001080 const MCSectionData &SymSD = Asm.getSectionData(
1081 SD->getSymbol().getSection());
1082 Index = SymSD.getOrdinal() + 1;
1083 FixedValue += getSectionAddress(&SymSD);
Daniel Dunbar4d743052010-12-22 13:50:05 +00001084 }
1085 if (IsPCRel)
1086 FixedValue -= getSectionAddress(Fragment->getParent());
1087
Daniel Dunbare8624532010-12-27 14:49:49 +00001088 // The type is determined by the fixup kind.
1089 Type = RelocType;
Daniel Dunbar4d743052010-12-22 13:50:05 +00001090 }
1091
1092 // struct relocation_info (8 bytes)
1093 macho::RelocationEntry MRE;
1094 MRE.Word0 = FixupOffset;
1095 MRE.Word1 = ((Index << 0) |
1096 (IsPCRel << 24) |
1097 (Log2Size << 25) |
1098 (IsExtern << 27) |
1099 (Type << 28));
1100 Relocations[Fragment->getParent()].push_back(MRE);
Daniel Dunbar532c4562010-12-22 13:49:43 +00001101 }
1102
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001103 void RecordRelocation(const MCAssembler &Asm, const MCAsmLayout &Layout,
Daniel Dunbarc90e30a2010-05-26 15:18:56 +00001104 const MCFragment *Fragment, const MCFixup &Fixup,
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001105 MCValue Target, uint64_t &FixedValue) {
Daniel Dunbar532c4562010-12-22 13:49:43 +00001106 // FIXME: These needs to be factored into the target Mach-O writer.
1107 if (isARM()) {
1108 RecordARMRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue);
1109 return;
1110 }
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001111 if (is64Bit()) {
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001112 RecordX86_64Relocation(Asm, Layout, Fragment, Fixup, Target, FixedValue);
Daniel Dunbar602b40f2010-03-19 18:07:55 +00001113 return;
1114 }
1115
Daniel Dunbar7e06af82010-12-16 15:42:31 +00001116 unsigned IsPCRel = isFixupKindPCRel(Asm, Fixup.getKind());
Daniel Dunbar482ad802010-05-26 15:18:31 +00001117 unsigned Log2Size = getFixupKindLog2Size(Fixup.getKind());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001118
Eric Christopherc9ada472010-06-15 22:59:05 +00001119 // If this is a 32-bit TLVP reloc it's handled a bit differently.
Daniel Dunbar23bea412010-09-17 15:21:50 +00001120 if (Target.getSymA() &&
1121 Target.getSymA()->getKind() == MCSymbolRefExpr::VK_TLVP) {
Eric Christopherc9ada472010-06-15 22:59:05 +00001122 RecordTLVPRelocation(Asm, Layout, Fragment, Fixup, Target, FixedValue);
1123 return;
1124 }
Jim Grosbach3c384922010-11-11 20:16:23 +00001125
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001126 // If this is a difference or a defined symbol plus an offset, then we need
1127 // a scattered relocation entry.
Daniel Dunbara8251fa2010-05-10 23:15:20 +00001128 // Differences always require scattered relocations.
1129 if (Target.getSymB())
1130 return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
Evan Chengf3eb3bb2011-01-14 02:38:49 +00001131 Target, Log2Size, FixedValue);
Daniel Dunbara8251fa2010-05-10 23:15:20 +00001132
1133 // Get the symbol data, if any.
1134 MCSymbolData *SD = 0;
1135 if (Target.getSymA())
1136 SD = &Asm.getSymbolData(Target.getSymA()->getSymbol());
1137
1138 // If this is an internal relocation with an offset, it also needs a
1139 // scattered relocation entry.
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001140 uint32_t Offset = Target.getConstant();
1141 if (IsPCRel)
1142 Offset += 1 << Log2Size;
Daniel Dunbara8251fa2010-05-10 23:15:20 +00001143 if (Offset && SD && !doesSymbolRequireExternRelocation(SD))
1144 return RecordScatteredRelocation(Asm, Layout, Fragment, Fixup,
Evan Chengf3eb3bb2011-01-14 02:38:49 +00001145 Target, Log2Size, FixedValue);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001146
1147 // See <reloc.h>.
Daniel Dunbar482ad802010-05-26 15:18:31 +00001148 uint32_t FixupOffset = Layout.getFragmentOffset(Fragment)+Fixup.getOffset();
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001149 unsigned Index = 0;
1150 unsigned IsExtern = 0;
1151 unsigned Type = 0;
1152
1153 if (Target.isAbsolute()) { // constant
1154 // SymbolNum of 0 indicates the absolute section.
1155 //
1156 // FIXME: Currently, these are never generated (see code below). I cannot
1157 // find a case where they are actually emitted.
Daniel Dunbarf52788f2010-11-27 04:59:14 +00001158 Type = macho::RIT_Vanilla;
Daniel Dunbar5ff919b2011-04-29 18:10:47 +00001159 } else {
1160 // Resolve constant variables.
1161 if (SD->getSymbol().isVariable()) {
1162 int64_t Res;
1163 if (SD->getSymbol().getVariableValue()->EvaluateAsAbsolute(
1164 Res, Layout, SectionAddress)) {
1165 FixedValue = Res;
1166 return;
1167 }
Rafael Espindola545b77e2010-12-07 17:12:32 +00001168 }
Daniel Dunbar42b52862010-12-22 13:49:56 +00001169
Daniel Dunbare9460ec2010-05-10 23:15:13 +00001170 // Check whether we need an external or internal relocation.
1171 if (doesSymbolRequireExternRelocation(SD)) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001172 IsExtern = 1;
1173 Index = SD->getIndex();
Daniel Dunbare9460ec2010-05-10 23:15:13 +00001174 // For external relocations, make sure to offset the fixup value to
1175 // compensate for the addend of the symbol address, if it was
1176 // undefined. This occurs with weak definitions, for example.
1177 if (!SD->Symbol->isUndefined())
Rafael Espindola3b3148f2010-12-07 05:57:28 +00001178 FixedValue -= Layout.getSymbolOffset(SD);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001179 } else {
Daniel Dunbar8fb04032010-03-25 08:08:54 +00001180 // The index is the section ordinal (1-based).
Daniel Dunbar08b99352011-04-29 18:07:43 +00001181 const MCSectionData &SymSD = Asm.getSectionData(
1182 SD->getSymbol().getSection());
1183 Index = SymSD.getOrdinal() + 1;
1184 FixedValue += getSectionAddress(&SymSD);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001185 }
Rafael Espindolabf60dad2010-12-07 03:50:14 +00001186 if (IsPCRel)
1187 FixedValue -= getSectionAddress(Fragment->getParent());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001188
Daniel Dunbarf52788f2010-11-27 04:59:14 +00001189 Type = macho::RIT_Vanilla;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001190 }
1191
1192 // struct relocation_info (8 bytes)
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +00001193 macho::RelocationEntry MRE;
Daniel Dunbar640e9482010-05-11 23:53:07 +00001194 MRE.Word0 = FixupOffset;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001195 MRE.Word1 = ((Index << 0) |
1196 (IsPCRel << 24) |
1197 (Log2Size << 25) |
1198 (IsExtern << 27) |
1199 (Type << 28));
Daniel Dunbarb7514182010-03-22 20:35:50 +00001200 Relocations[Fragment->getParent()].push_back(MRE);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001201 }
1202
1203 void BindIndirectSymbols(MCAssembler &Asm) {
1204 // This is the point where 'as' creates actual symbols for indirect symbols
1205 // (in the following two passes). It would be easier for us to do this
1206 // sooner when we see the attribute, but that makes getting the order in the
1207 // symbol table much more complicated than it is worth.
1208 //
1209 // FIXME: Revisit this when the dust settles.
1210
1211 // Bind non lazy symbol pointers first.
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001212 unsigned IndirectIndex = 0;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001213 for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001214 ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001215 const MCSectionMachO &Section =
Daniel Dunbar56279f42010-05-18 17:28:20 +00001216 cast<MCSectionMachO>(it->SectionData->getSection());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001217
1218 if (Section.getType() != MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS)
1219 continue;
1220
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001221 // Initialize the section indirect symbol base, if necessary.
1222 if (!IndirectSymBase.count(it->SectionData))
1223 IndirectSymBase[it->SectionData] = IndirectIndex;
Jim Grosbach3c384922010-11-11 20:16:23 +00001224
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001225 Asm.getOrCreateSymbolData(*it->Symbol);
1226 }
1227
1228 // Then lazy symbol pointers and symbol stubs.
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001229 IndirectIndex = 0;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001230 for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001231 ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001232 const MCSectionMachO &Section =
Daniel Dunbar56279f42010-05-18 17:28:20 +00001233 cast<MCSectionMachO>(it->SectionData->getSection());
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001234
1235 if (Section.getType() != MCSectionMachO::S_LAZY_SYMBOL_POINTERS &&
1236 Section.getType() != MCSectionMachO::S_SYMBOL_STUBS)
1237 continue;
1238
Daniel Dunbar2ae4bfd2010-05-18 17:28:24 +00001239 // Initialize the section indirect symbol base, if necessary.
1240 if (!IndirectSymBase.count(it->SectionData))
1241 IndirectSymBase[it->SectionData] = IndirectIndex;
1242
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001243 // Set the symbol type to undefined lazy, but only on construction.
1244 //
1245 // FIXME: Do not hardcode.
1246 bool Created;
1247 MCSymbolData &Entry = Asm.getOrCreateSymbolData(*it->Symbol, &Created);
1248 if (Created)
1249 Entry.setFlags(Entry.getFlags() | 0x0001);
1250 }
1251 }
1252
1253 /// ComputeSymbolTable - Compute the symbol table data
1254 ///
1255 /// \param StringTable [out] - The string table data.
1256 /// \param StringIndexMap [out] - Map from symbol names to offsets in the
1257 /// string table.
1258 void ComputeSymbolTable(MCAssembler &Asm, SmallString<256> &StringTable,
1259 std::vector<MachSymbolData> &LocalSymbolData,
1260 std::vector<MachSymbolData> &ExternalSymbolData,
1261 std::vector<MachSymbolData> &UndefinedSymbolData) {
1262 // Build section lookup table.
1263 DenseMap<const MCSection*, uint8_t> SectionIndexMap;
1264 unsigned Index = 1;
1265 for (MCAssembler::iterator it = Asm.begin(),
1266 ie = Asm.end(); it != ie; ++it, ++Index)
1267 SectionIndexMap[&it->getSection()] = Index;
1268 assert(Index <= 256 && "Too many sections!");
1269
1270 // Index 0 is always the empty string.
1271 StringMap<uint64_t> StringIndexMap;
1272 StringTable += '\x00';
1273
1274 // Build the symbol arrays and the string table, but only for non-local
1275 // symbols.
1276 //
1277 // The particular order that we collect the symbols and create the string
1278 // table, then sort the symbols is chosen to match 'as'. Even though it
1279 // doesn't matter for correctness, this is important for letting us diff .o
1280 // files.
1281 for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
1282 ie = Asm.symbol_end(); it != ie; ++it) {
1283 const MCSymbol &Symbol = it->getSymbol();
1284
1285 // Ignore non-linker visible symbols.
Daniel Dunbar843aa1f2010-06-16 20:04:29 +00001286 if (!Asm.isSymbolLinkerVisible(it->getSymbol()))
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001287 continue;
1288
1289 if (!it->isExternal() && !Symbol.isUndefined())
1290 continue;
1291
1292 uint64_t &Entry = StringIndexMap[Symbol.getName()];
1293 if (!Entry) {
1294 Entry = StringTable.size();
1295 StringTable += Symbol.getName();
1296 StringTable += '\x00';
1297 }
1298
1299 MachSymbolData MSD;
1300 MSD.SymbolData = it;
1301 MSD.StringIndex = Entry;
1302
1303 if (Symbol.isUndefined()) {
1304 MSD.SectionIndex = 0;
1305 UndefinedSymbolData.push_back(MSD);
1306 } else if (Symbol.isAbsolute()) {
1307 MSD.SectionIndex = 0;
1308 ExternalSymbolData.push_back(MSD);
1309 } else {
1310 MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
1311 assert(MSD.SectionIndex && "Invalid section index!");
1312 ExternalSymbolData.push_back(MSD);
1313 }
1314 }
1315
1316 // Now add the data for local symbols.
1317 for (MCAssembler::symbol_iterator it = Asm.symbol_begin(),
1318 ie = Asm.symbol_end(); it != ie; ++it) {
1319 const MCSymbol &Symbol = it->getSymbol();
1320
1321 // Ignore non-linker visible symbols.
Daniel Dunbar843aa1f2010-06-16 20:04:29 +00001322 if (!Asm.isSymbolLinkerVisible(it->getSymbol()))
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001323 continue;
1324
1325 if (it->isExternal() || Symbol.isUndefined())
1326 continue;
1327
1328 uint64_t &Entry = StringIndexMap[Symbol.getName()];
1329 if (!Entry) {
1330 Entry = StringTable.size();
1331 StringTable += Symbol.getName();
1332 StringTable += '\x00';
1333 }
1334
1335 MachSymbolData MSD;
1336 MSD.SymbolData = it;
1337 MSD.StringIndex = Entry;
1338
1339 if (Symbol.isAbsolute()) {
1340 MSD.SectionIndex = 0;
1341 LocalSymbolData.push_back(MSD);
1342 } else {
1343 MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
1344 assert(MSD.SectionIndex && "Invalid section index!");
1345 LocalSymbolData.push_back(MSD);
1346 }
1347 }
1348
1349 // External and undefined symbols are required to be in lexicographic order.
1350 std::sort(ExternalSymbolData.begin(), ExternalSymbolData.end());
1351 std::sort(UndefinedSymbolData.begin(), UndefinedSymbolData.end());
1352
1353 // Set the symbol indices.
1354 Index = 0;
1355 for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
1356 LocalSymbolData[i].SymbolData->setIndex(Index++);
1357 for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
1358 ExternalSymbolData[i].SymbolData->setIndex(Index++);
1359 for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
1360 UndefinedSymbolData[i].SymbolData->setIndex(Index++);
1361
1362 // The string table is padded to a multiple of 4.
1363 while (StringTable.size() % 4)
1364 StringTable += '\x00';
1365 }
1366
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001367 void computeSectionAddresses(const MCAssembler &Asm,
1368 const MCAsmLayout &Layout) {
1369 uint64_t StartAddress = 0;
1370 const SmallVectorImpl<MCSectionData*> &Order = Layout.getSectionOrder();
1371 for (int i = 0, n = Order.size(); i != n ; ++i) {
1372 const MCSectionData *SD = Order[i];
1373 StartAddress = RoundUpToAlignment(StartAddress, SD->getAlignment());
1374 SectionAddress[SD] = StartAddress;
1375 StartAddress += Layout.getSectionAddressSize(SD);
1376 // Explicitly pad the section to match the alignment requirements of the
1377 // following one. This is for 'gas' compatibility, it shouldn't
1378 /// strictly be necessary.
1379 StartAddress += getPaddingSize(SD, Layout);
1380 }
1381 }
1382
1383 void ExecutePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout) {
1384 computeSectionAddresses(Asm, Layout);
1385
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001386 // Create symbol data for any indirect symbols.
1387 BindIndirectSymbols(Asm);
1388
1389 // Compute symbol table information and bind symbol indices.
1390 ComputeSymbolTable(Asm, StringTable, LocalSymbolData, ExternalSymbolData,
1391 UndefinedSymbolData);
1392 }
1393
Rafael Espindolafea753b2010-12-24 21:22:02 +00001394 virtual bool IsSymbolRefDifferenceFullyResolvedImpl(const MCAssembler &Asm,
1395 const MCSymbolData &DataA,
1396 const MCFragment &FB,
1397 bool InSet,
1398 bool IsPCRel) const {
Rafael Espindola31327802010-12-18 06:27:54 +00001399 if (InSet)
1400 return true;
1401
Daniel Dunbar32c1c5a2010-12-17 04:54:58 +00001402 // The effective address is
1403 // addr(atom(A)) + offset(A)
1404 // - addr(atom(B)) - offset(B)
1405 // and the offsets are not relocatable, so the fixup is fully resolved when
1406 // addr(atom(A)) - addr(atom(B)) == 0.
1407 const MCSymbolData *A_Base = 0, *B_Base = 0;
1408
Rafael Espindolafea753b2010-12-24 21:22:02 +00001409 const MCSymbol &SA = DataA.getSymbol().AliasedSymbol();
1410 const MCSection &SecA = SA.getSection();
1411 const MCSection &SecB = FB.getParent()->getSection();
Daniel Dunbar32c1c5a2010-12-17 04:54:58 +00001412
Rafael Espindolafea753b2010-12-24 21:22:02 +00001413 if (IsPCRel) {
1414 // The simple (Darwin, except on x86_64) way of dealing with this was to
1415 // assume that any reference to a temporary symbol *must* be a temporary
1416 // symbol in the same atom, unless the sections differ. Therefore, any
1417 // PCrel relocation to a temporary symbol (in the same section) is fully
1418 // resolved. This also works in conjunction with absolutized .set, which
1419 // requires the compiler to use .set to absolutize the differences between
1420 // symbols which the compiler knows to be assembly time constants, so we
1421 // don't need to worry about considering symbol differences fully
1422 // resolved.
1423
1424 if (!Asm.getBackend().hasReliableSymbolDifference()) {
1425 if (!SA.isTemporary() || !SA.isInSection() || &SecA != &SecB)
1426 return false;
1427 return true;
1428 }
1429 } else {
1430 if (!TargetObjectWriter->useAggressiveSymbolFolding())
1431 return false;
1432 }
1433
1434 const MCFragment &FA = *Asm.getSymbolData(SA).getFragment();
1435
1436 A_Base = FA.getAtom();
Daniel Dunbar32c1c5a2010-12-17 04:54:58 +00001437 if (!A_Base)
1438 return false;
1439
Rafael Espindolafea753b2010-12-24 21:22:02 +00001440 B_Base = FB.getAtom();
Daniel Dunbar32c1c5a2010-12-17 04:54:58 +00001441 if (!B_Base)
1442 return false;
1443
1444 // If the atoms are the same, they are guaranteed to have the same address.
1445 if (A_Base == B_Base)
1446 return true;
1447
1448 // Otherwise, we can't prove this is fully resolved.
Daniel Dunbar1f3662a2010-12-17 04:54:54 +00001449 return false;
1450 }
1451
Daniel Dunbar115a3dd2010-11-13 07:33:40 +00001452 void WriteObject(MCAssembler &Asm, const MCAsmLayout &Layout) {
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001453 unsigned NumSections = Asm.size();
1454
1455 // The section data starts after the header, the segment load command (and
1456 // section headers) and the symbol table.
1457 unsigned NumLoadCommands = 1;
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001458 uint64_t LoadCommandsSize = is64Bit() ?
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001459 macho::SegmentLoadCommand64Size + NumSections * macho::Section64Size :
1460 macho::SegmentLoadCommand32Size + NumSections * macho::Section32Size;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001461
1462 // Add the symbol table load command sizes, if used.
1463 unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() +
1464 UndefinedSymbolData.size();
1465 if (NumSymbols) {
1466 NumLoadCommands += 2;
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001467 LoadCommandsSize += (macho::SymtabLoadCommandSize +
1468 macho::DysymtabLoadCommandSize);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001469 }
1470
1471 // Compute the total size of the section data, as well as its file size and
1472 // vm size.
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001473 uint64_t SectionDataStart = (is64Bit() ? macho::Header64Size :
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001474 macho::Header32Size) + LoadCommandsSize;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001475 uint64_t SectionDataSize = 0;
1476 uint64_t SectionDataFileSize = 0;
1477 uint64_t VMSize = 0;
1478 for (MCAssembler::const_iterator it = Asm.begin(),
1479 ie = Asm.end(); it != ie; ++it) {
1480 const MCSectionData &SD = *it;
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001481 uint64_t Address = getSectionAddress(&SD);
1482 uint64_t Size = Layout.getSectionAddressSize(&SD);
Daniel Dunbar5d428512010-03-25 02:00:07 +00001483 uint64_t FileSize = Layout.getSectionFileSize(&SD);
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001484 FileSize += getPaddingSize(&SD, Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001485
Daniel Dunbar5d428512010-03-25 02:00:07 +00001486 VMSize = std::max(VMSize, Address + Size);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001487
Rafael Espindolaf2dc4aa2010-11-17 20:03:54 +00001488 if (SD.getSection().isVirtualSection())
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001489 continue;
1490
Daniel Dunbar5d428512010-03-25 02:00:07 +00001491 SectionDataSize = std::max(SectionDataSize, Address + Size);
1492 SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001493 }
1494
1495 // The section data is padded to 4 bytes.
1496 //
1497 // FIXME: Is this machine dependent?
1498 unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4);
1499 SectionDataFileSize += SectionDataPadding;
1500
1501 // Write the prolog, starting with the header and load command...
1502 WriteHeader(NumLoadCommands, LoadCommandsSize,
1503 Asm.getSubsectionsViaSymbols());
1504 WriteSegmentLoadCommand(NumSections, VMSize,
1505 SectionDataStart, SectionDataSize);
1506
1507 // ... and then the section headers.
1508 uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
1509 for (MCAssembler::const_iterator it = Asm.begin(),
1510 ie = Asm.end(); it != ie; ++it) {
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +00001511 std::vector<macho::RelocationEntry> &Relocs = Relocations[it];
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001512 unsigned NumRelocs = Relocs.size();
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001513 uint64_t SectionStart = SectionDataStart + getSectionAddress(it);
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001514 WriteSection(Asm, Layout, *it, SectionStart, RelocTableEnd, NumRelocs);
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001515 RelocTableEnd += NumRelocs * macho::RelocationInfoSize;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001516 }
1517
1518 // Write the symbol table load command, if used.
1519 if (NumSymbols) {
1520 unsigned FirstLocalSymbol = 0;
1521 unsigned NumLocalSymbols = LocalSymbolData.size();
1522 unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;
1523 unsigned NumExternalSymbols = ExternalSymbolData.size();
1524 unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;
1525 unsigned NumUndefinedSymbols = UndefinedSymbolData.size();
1526 unsigned NumIndirectSymbols = Asm.indirect_symbol_size();
1527 unsigned NumSymTabSymbols =
1528 NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols;
1529 uint64_t IndirectSymbolSize = NumIndirectSymbols * 4;
1530 uint64_t IndirectSymbolOffset = 0;
1531
1532 // If used, the indirect symbols are written after the section data.
1533 if (NumIndirectSymbols)
1534 IndirectSymbolOffset = RelocTableEnd;
1535
1536 // The symbol table is written after the indirect symbol data.
1537 uint64_t SymbolTableOffset = RelocTableEnd + IndirectSymbolSize;
1538
1539 // The string table is written after symbol table.
1540 uint64_t StringTableOffset =
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001541 SymbolTableOffset + NumSymTabSymbols * (is64Bit() ? macho::Nlist64Size :
Daniel Dunbar821ecd72010-11-27 04:19:38 +00001542 macho::Nlist32Size);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001543 WriteSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
1544 StringTableOffset, StringTable.size());
1545
1546 WriteDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
1547 FirstExternalSymbol, NumExternalSymbols,
1548 FirstUndefinedSymbol, NumUndefinedSymbols,
1549 IndirectSymbolOffset, NumIndirectSymbols);
1550 }
1551
1552 // Write the actual section data.
1553 for (MCAssembler::const_iterator it = Asm.begin(),
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001554 ie = Asm.end(); it != ie; ++it) {
Daniel Dunbar5d2477c2010-12-17 02:45:59 +00001555 Asm.WriteSectionData(it, Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001556
Rafael Espindola85f2ecc2010-12-07 00:27:36 +00001557 uint64_t Pad = getPaddingSize(it, Layout);
1558 for (unsigned int i = 0; i < Pad; ++i)
1559 Write8(0);
1560 }
1561
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001562 // Write the extra padding.
1563 WriteZeros(SectionDataPadding);
1564
1565 // Write the relocation entries.
1566 for (MCAssembler::const_iterator it = Asm.begin(),
1567 ie = Asm.end(); it != ie; ++it) {
1568 // Write the section relocation entries, in reverse order to match 'as'
1569 // (approximately, the exact algorithm is more complicated than this).
Daniel Dunbar90e3e3a2010-11-27 13:39:48 +00001570 std::vector<macho::RelocationEntry> &Relocs = Relocations[it];
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001571 for (unsigned i = 0, e = Relocs.size(); i != e; ++i) {
1572 Write32(Relocs[e - i - 1].Word0);
1573 Write32(Relocs[e - i - 1].Word1);
1574 }
1575 }
1576
1577 // Write the symbol table data, if used.
1578 if (NumSymbols) {
1579 // Write the indirect symbol entries.
1580 for (MCAssembler::const_indirect_symbol_iterator
1581 it = Asm.indirect_symbol_begin(),
1582 ie = Asm.indirect_symbol_end(); it != ie; ++it) {
1583 // Indirect symbols in the non lazy symbol pointer section have some
1584 // special handling.
1585 const MCSectionMachO &Section =
1586 static_cast<const MCSectionMachO&>(it->SectionData->getSection());
1587 if (Section.getType() == MCSectionMachO::S_NON_LAZY_SYMBOL_POINTERS) {
1588 // If this symbol is defined and internal, mark it as such.
1589 if (it->Symbol->isDefined() &&
1590 !Asm.getSymbolData(*it->Symbol).isExternal()) {
Daniel Dunbarf52788f2010-11-27 04:59:14 +00001591 uint32_t Flags = macho::ISF_Local;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001592 if (it->Symbol->isAbsolute())
Daniel Dunbarf52788f2010-11-27 04:59:14 +00001593 Flags |= macho::ISF_Absolute;
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001594 Write32(Flags);
1595 continue;
1596 }
1597 }
1598
1599 Write32(Asm.getSymbolData(*it->Symbol).getIndex());
1600 }
1601
1602 // FIXME: Check that offsets match computed ones.
1603
1604 // Write the symbol table entries.
1605 for (unsigned i = 0, e = LocalSymbolData.size(); i != e; ++i)
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001606 WriteNlist(LocalSymbolData[i], Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001607 for (unsigned i = 0, e = ExternalSymbolData.size(); i != e; ++i)
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001608 WriteNlist(ExternalSymbolData[i], Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001609 for (unsigned i = 0, e = UndefinedSymbolData.size(); i != e; ++i)
Daniel Dunbar207e06e2010-03-24 03:43:40 +00001610 WriteNlist(UndefinedSymbolData[i], Layout);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001611
1612 // Write the string table.
1613 OS << StringTable.str();
1614 }
1615 }
1616};
1617
1618}
1619
Daniel Dunbarae5abd52010-12-16 16:09:19 +00001620MCObjectWriter *llvm::createMachObjectWriter(MCMachObjectTargetWriter *MOTW,
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001621 raw_ostream &OS,
Daniel Dunbar115a3dd2010-11-13 07:33:40 +00001622 bool IsLittleEndian) {
Daniel Dunbar5d05d972010-12-16 17:21:02 +00001623 return new MachObjectWriter(MOTW, OS, IsLittleEndian);
Daniel Dunbar2df4ceb2010-03-19 10:43:15 +00001624}