Line data Source code
1 : //===- 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 :
10 : #include "llvm/ADT/DenseMap.h"
11 : #include "llvm/ADT/Twine.h"
12 : #include "llvm/ADT/iterator_range.h"
13 : #include "llvm/BinaryFormat/MachO.h"
14 : #include "llvm/MC/MCAsmBackend.h"
15 : #include "llvm/MC/MCAsmLayout.h"
16 : #include "llvm/MC/MCAssembler.h"
17 : #include "llvm/MC/MCDirectives.h"
18 : #include "llvm/MC/MCExpr.h"
19 : #include "llvm/MC/MCFixupKindInfo.h"
20 : #include "llvm/MC/MCFragment.h"
21 : #include "llvm/MC/MCMachObjectWriter.h"
22 : #include "llvm/MC/MCObjectWriter.h"
23 : #include "llvm/MC/MCSection.h"
24 : #include "llvm/MC/MCSectionMachO.h"
25 : #include "llvm/MC/MCSymbol.h"
26 : #include "llvm/MC/MCSymbolMachO.h"
27 : #include "llvm/MC/MCValue.h"
28 : #include "llvm/Support/Casting.h"
29 : #include "llvm/Support/Debug.h"
30 : #include "llvm/Support/ErrorHandling.h"
31 : #include "llvm/Support/MathExtras.h"
32 : #include "llvm/Support/raw_ostream.h"
33 : #include <algorithm>
34 : #include <cassert>
35 : #include <cstdint>
36 : #include <string>
37 : #include <utility>
38 : #include <vector>
39 :
40 : using namespace llvm;
41 :
42 : #define DEBUG_TYPE "mc"
43 :
44 295 : void MachObjectWriter::reset() {
45 295 : Relocations.clear();
46 295 : IndirectSymBase.clear();
47 295 : StringTable.clear();
48 : LocalSymbolData.clear();
49 : ExternalSymbolData.clear();
50 : UndefinedSymbolData.clear();
51 : MCObjectWriter::reset();
52 295 : }
53 :
54 1498 : bool MachObjectWriter::doesSymbolRequireExternRelocation(const MCSymbol &S) {
55 : // Undefined symbols are always extern.
56 1498 : if (S.isUndefined())
57 : return true;
58 :
59 : // References to weak definitions require external relocation entries; the
60 : // definition may not always be the one in the same object file.
61 283 : if (cast<MCSymbolMachO>(S).isWeakDefinition())
62 5 : return true;
63 :
64 : // Otherwise, we can use an internal relocation.
65 : return false;
66 : }
67 :
68 1722 : bool MachObjectWriter::
69 : MachSymbolData::operator<(const MachSymbolData &RHS) const {
70 5166 : return Symbol->getName() < RHS.Symbol->getName();
71 : }
72 :
73 3583 : bool MachObjectWriter::isFixupKindPCRel(const MCAssembler &Asm, unsigned Kind) {
74 : const MCFixupKindInfo &FKI = Asm.getBackend().getFixupKindInfo(
75 3583 : (MCFixupKind) Kind);
76 :
77 3583 : return FKI.Flags & MCFixupKindInfo::FKF_IsPCRel;
78 : }
79 :
80 1583 : uint64_t MachObjectWriter::getFragmentAddress(const MCFragment *Fragment,
81 : const MCAsmLayout &Layout) const {
82 1583 : return getSectionAddress(Fragment->getParent()) +
83 1583 : Layout.getFragmentOffset(Fragment);
84 : }
85 :
86 2546 : uint64_t MachObjectWriter::getSymbolAddress(const MCSymbol &S,
87 : const MCAsmLayout &Layout) const {
88 : // If this is a variable, then recursively evaluate now.
89 2546 : if (S.isVariable()) {
90 : if (const MCConstantExpr *C =
91 : dyn_cast<const MCConstantExpr>(S.getVariableValue()))
92 4 : return C->getValue();
93 :
94 36 : MCValue Target;
95 36 : if (!S.getVariableValue()->evaluateAsRelocatable(Target, &Layout, nullptr))
96 0 : report_fatal_error("unable to evaluate offset for variable '" +
97 0 : S.getName() + "'");
98 :
99 : // Verify that any used symbols are defined.
100 36 : if (Target.getSymA() && Target.getSymA()->getSymbol().isUndefined())
101 0 : report_fatal_error("unable to evaluate offset to undefined symbol '" +
102 0 : Target.getSymA()->getSymbol().getName() + "'");
103 36 : if (Target.getSymB() && Target.getSymB()->getSymbol().isUndefined())
104 0 : report_fatal_error("unable to evaluate offset to undefined symbol '" +
105 0 : Target.getSymB()->getSymbol().getName() + "'");
106 :
107 36 : uint64_t Address = Target.getConstant();
108 36 : if (Target.getSymA())
109 36 : Address += getSymbolAddress(Target.getSymA()->getSymbol(), Layout);
110 36 : if (Target.getSymB())
111 3 : Address += getSymbolAddress(Target.getSymB()->getSymbol(), Layout);
112 36 : return Address;
113 : }
114 :
115 2506 : return getSectionAddress(S.getFragment()->getParent()) +
116 2506 : Layout.getSymbolOffset(S);
117 : }
118 :
119 11005 : uint64_t MachObjectWriter::getPaddingSize(const MCSection *Sec,
120 : const MCAsmLayout &Layout) const {
121 11005 : uint64_t EndAddr = getSectionAddress(Sec) + Layout.getSectionAddressSize(Sec);
122 11005 : unsigned Next = Sec->getLayoutOrder() + 1;
123 11005 : if (Next >= Layout.getSectionOrder().size())
124 : return 0;
125 :
126 9117 : const MCSection &NextSec = *Layout.getSectionOrder()[Next];
127 9117 : if (NextSec.isVirtualSection())
128 : return 0;
129 17976 : return OffsetToAlignment(EndAddr, NextSec.getAlignment());
130 : }
131 :
132 666 : void MachObjectWriter::writeHeader(MachO::HeaderFileType Type,
133 : unsigned NumLoadCommands,
134 : unsigned LoadCommandsSize,
135 : bool SubsectionsViaSymbols) {
136 : uint32_t Flags = 0;
137 :
138 666 : if (SubsectionsViaSymbols)
139 : Flags |= MachO::MH_SUBSECTIONS_VIA_SYMBOLS;
140 :
141 : // struct mach_header (28 bytes) or
142 : // struct mach_header_64 (32 bytes)
143 :
144 666 : uint64_t Start = W.OS.tell();
145 : (void) Start;
146 :
147 859 : W.write<uint32_t>(is64Bit() ? MachO::MH_MAGIC_64 : MachO::MH_MAGIC);
148 :
149 666 : W.write<uint32_t>(TargetObjectWriter->getCPUType());
150 : W.write<uint32_t>(TargetObjectWriter->getCPUSubtype());
151 :
152 666 : W.write<uint32_t>(Type);
153 666 : W.write<uint32_t>(NumLoadCommands);
154 666 : W.write<uint32_t>(LoadCommandsSize);
155 666 : W.write<uint32_t>(Flags);
156 666 : if (is64Bit())
157 473 : W.write<uint32_t>(0); // reserved
158 :
159 : assert(W.OS.tell() - Start == (is64Bit() ? sizeof(MachO::mach_header_64)
160 : : sizeof(MachO::mach_header)));
161 666 : }
162 :
163 8764 : void MachObjectWriter::writeWithPadding(StringRef Str, uint64_t Size) {
164 : assert(Size >= Str.size());
165 8764 : W.OS << Str;
166 17528 : W.OS.write_zeros(Size - Str.size());
167 8764 : }
168 :
169 : /// writeSegmentLoadCommand - Write a segment load command.
170 : ///
171 : /// \param NumSections The number of sections in this segment.
172 : /// \param SectionDataSize The total size of the sections.
173 666 : void MachObjectWriter::writeSegmentLoadCommand(
174 : StringRef Name, unsigned NumSections, uint64_t VMAddr, uint64_t VMSize,
175 : uint64_t SectionDataStartOffset, uint64_t SectionDataSize, uint32_t MaxProt,
176 : uint32_t InitProt) {
177 : // struct segment_command (56 bytes) or
178 : // struct segment_command_64 (72 bytes)
179 :
180 666 : uint64_t Start = W.OS.tell();
181 : (void) Start;
182 :
183 : unsigned SegmentLoadCommandSize =
184 : is64Bit() ? sizeof(MachO::segment_command_64):
185 666 : sizeof(MachO::segment_command);
186 859 : W.write<uint32_t>(is64Bit() ? MachO::LC_SEGMENT_64 : MachO::LC_SEGMENT);
187 859 : W.write<uint32_t>(SegmentLoadCommandSize +
188 : NumSections * (is64Bit() ? sizeof(MachO::section_64) :
189 : sizeof(MachO::section)));
190 :
191 666 : writeWithPadding(Name, 16);
192 666 : if (is64Bit()) {
193 473 : W.write<uint64_t>(VMAddr); // vmaddr
194 473 : W.write<uint64_t>(VMSize); // vmsize
195 473 : W.write<uint64_t>(SectionDataStartOffset); // file offset
196 473 : W.write<uint64_t>(SectionDataSize); // file size
197 : } else {
198 193 : W.write<uint32_t>(VMAddr); // vmaddr
199 193 : W.write<uint32_t>(VMSize); // vmsize
200 193 : W.write<uint32_t>(SectionDataStartOffset); // file offset
201 193 : W.write<uint32_t>(SectionDataSize); // file size
202 : }
203 : // maxprot
204 666 : W.write<uint32_t>(MaxProt);
205 : // initprot
206 666 : W.write<uint32_t>(InitProt);
207 666 : W.write<uint32_t>(NumSections);
208 666 : W.write<uint32_t>(0); // flags
209 :
210 : assert(W.OS.tell() - Start == SegmentLoadCommandSize);
211 666 : }
212 :
213 4049 : void MachObjectWriter::writeSection(const MCAsmLayout &Layout,
214 : const MCSection &Sec, uint64_t VMAddr,
215 : uint64_t FileOffset, unsigned Flags,
216 : uint64_t RelocationsStart,
217 : unsigned NumRelocations) {
218 4049 : uint64_t SectionSize = Layout.getSectionAddressSize(&Sec);
219 : const MCSectionMachO &Section = cast<MCSectionMachO>(Sec);
220 :
221 : // The offset is unused for virtual sections.
222 4049 : if (Section.isVirtualSection()) {
223 : assert(Layout.getSectionFileSize(&Sec) == 0 && "Invalid file size!");
224 : FileOffset = 0;
225 : }
226 :
227 : // struct section (68 bytes) or
228 : // struct section_64 (80 bytes)
229 :
230 4049 : uint64_t Start = W.OS.tell();
231 : (void) Start;
232 :
233 4049 : writeWithPadding(Section.getSectionName(), 16);
234 4049 : writeWithPadding(Section.getSegmentName(), 16);
235 4049 : if (is64Bit()) {
236 3372 : W.write<uint64_t>(VMAddr); // address
237 3372 : W.write<uint64_t>(SectionSize); // size
238 : } else {
239 677 : W.write<uint32_t>(VMAddr); // address
240 677 : W.write<uint32_t>(SectionSize); // size
241 : }
242 4049 : W.write<uint32_t>(FileOffset);
243 :
244 : assert(isPowerOf2_32(Section.getAlignment()) && "Invalid alignment!");
245 8098 : W.write<uint32_t>(Log2_32(Section.getAlignment()));
246 4049 : W.write<uint32_t>(NumRelocations ? RelocationsStart : 0);
247 4049 : W.write<uint32_t>(NumRelocations);
248 4049 : W.write<uint32_t>(Flags);
249 8098 : W.write<uint32_t>(IndirectSymBase.lookup(&Sec)); // reserved1
250 4049 : W.write<uint32_t>(Section.getStubSize()); // reserved2
251 4049 : if (is64Bit())
252 3372 : W.write<uint32_t>(0); // reserved3
253 :
254 : assert(W.OS.tell() - Start ==
255 : (is64Bit() ? sizeof(MachO::section_64) : sizeof(MachO::section)));
256 4049 : }
257 :
258 545 : void MachObjectWriter::writeSymtabLoadCommand(uint32_t SymbolOffset,
259 : uint32_t NumSymbols,
260 : uint32_t StringTableOffset,
261 : uint32_t StringTableSize) {
262 : // struct symtab_command (24 bytes)
263 :
264 545 : uint64_t Start = W.OS.tell();
265 : (void) Start;
266 :
267 545 : W.write<uint32_t>(MachO::LC_SYMTAB);
268 545 : W.write<uint32_t>(sizeof(MachO::symtab_command));
269 545 : W.write<uint32_t>(SymbolOffset);
270 545 : W.write<uint32_t>(NumSymbols);
271 545 : W.write<uint32_t>(StringTableOffset);
272 545 : W.write<uint32_t>(StringTableSize);
273 :
274 : assert(W.OS.tell() - Start == sizeof(MachO::symtab_command));
275 545 : }
276 :
277 492 : void MachObjectWriter::writeDysymtabLoadCommand(uint32_t FirstLocalSymbol,
278 : uint32_t NumLocalSymbols,
279 : uint32_t FirstExternalSymbol,
280 : uint32_t NumExternalSymbols,
281 : uint32_t FirstUndefinedSymbol,
282 : uint32_t NumUndefinedSymbols,
283 : uint32_t IndirectSymbolOffset,
284 : uint32_t NumIndirectSymbols) {
285 : // struct dysymtab_command (80 bytes)
286 :
287 492 : uint64_t Start = W.OS.tell();
288 : (void) Start;
289 :
290 492 : W.write<uint32_t>(MachO::LC_DYSYMTAB);
291 492 : W.write<uint32_t>(sizeof(MachO::dysymtab_command));
292 492 : W.write<uint32_t>(FirstLocalSymbol);
293 492 : W.write<uint32_t>(NumLocalSymbols);
294 492 : W.write<uint32_t>(FirstExternalSymbol);
295 492 : W.write<uint32_t>(NumExternalSymbols);
296 492 : W.write<uint32_t>(FirstUndefinedSymbol);
297 492 : W.write<uint32_t>(NumUndefinedSymbols);
298 492 : W.write<uint32_t>(0); // tocoff
299 492 : W.write<uint32_t>(0); // ntoc
300 492 : W.write<uint32_t>(0); // modtaboff
301 492 : W.write<uint32_t>(0); // nmodtab
302 492 : W.write<uint32_t>(0); // extrefsymoff
303 492 : W.write<uint32_t>(0); // nextrefsyms
304 492 : W.write<uint32_t>(IndirectSymbolOffset);
305 492 : W.write<uint32_t>(NumIndirectSymbols);
306 492 : W.write<uint32_t>(0); // extreloff
307 492 : W.write<uint32_t>(0); // nextrel
308 492 : W.write<uint32_t>(0); // locreloff
309 492 : W.write<uint32_t>(0); // nlocrel
310 :
311 : assert(W.OS.tell() - Start == sizeof(MachO::dysymtab_command));
312 492 : }
313 :
314 : MachObjectWriter::MachSymbolData *
315 24 : MachObjectWriter::findSymbolData(const MCSymbol &Sym) {
316 69 : for (auto *SymbolData :
317 48 : {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
318 151 : for (MachSymbolData &Entry : *SymbolData)
319 127 : if (Entry.Symbol == &Sym)
320 : return &Entry;
321 :
322 : return nullptr;
323 : }
324 :
325 3697 : const MCSymbol &MachObjectWriter::findAliasedSymbol(const MCSymbol &Sym) const {
326 : const MCSymbol *S = &Sym;
327 3726 : while (S->isVariable()) {
328 : const MCExpr *Value = S->getVariableValue();
329 : const auto *Ref = dyn_cast<MCSymbolRefExpr>(Value);
330 : if (!Ref)
331 22 : return *S;
332 29 : S = &Ref->getSymbol();
333 : }
334 : return *S;
335 : }
336 :
337 1676 : void MachObjectWriter::writeNlist(MachSymbolData &MSD,
338 : const MCAsmLayout &Layout) {
339 1676 : const MCSymbol *Symbol = MSD.Symbol;
340 : const MCSymbol &Data = *Symbol;
341 1676 : const MCSymbol *AliasedSymbol = &findAliasedSymbol(*Symbol);
342 1676 : uint8_t SectionIndex = MSD.SectionIndex;
343 : uint8_t Type = 0;
344 : uint64_t Address = 0;
345 : bool IsAlias = Symbol != AliasedSymbol;
346 :
347 : const MCSymbol &OrigSymbol = *Symbol;
348 : MachSymbolData *AliaseeInfo;
349 1676 : if (IsAlias) {
350 24 : AliaseeInfo = findSymbolData(*AliasedSymbol);
351 24 : if (AliaseeInfo)
352 21 : SectionIndex = AliaseeInfo->SectionIndex;
353 : Symbol = AliasedSymbol;
354 : // FIXME: Should this update Data as well?
355 : }
356 :
357 : // Set the N_TYPE bits. See <mach-o/nlist.h>.
358 : //
359 : // FIXME: Are the prebound or indirect fields possible here?
360 1700 : if (IsAlias && Symbol->isUndefined())
361 : Type = MachO::N_INDR;
362 1671 : else if (Symbol->isUndefined())
363 : Type = MachO::N_UNDF;
364 1207 : else if (Symbol->isAbsolute())
365 : Type = MachO::N_ABS;
366 : else
367 : Type = MachO::N_SECT;
368 :
369 : // FIXME: Set STAB bits.
370 :
371 1676 : if (Data.isPrivateExtern())
372 22 : Type |= MachO::N_PEXT;
373 :
374 : // Set external bit.
375 2612 : if (Data.isExternal() || (!IsAlias && Symbol->isUndefined()))
376 1108 : Type |= MachO::N_EXT;
377 :
378 : // Compute the symbol address.
379 1700 : if (IsAlias && Symbol->isUndefined())
380 5 : Address = AliaseeInfo->StringIndex;
381 1671 : else if (Symbol->isDefined())
382 1207 : Address = getSymbolAddress(OrigSymbol, Layout);
383 464 : else if (Symbol->isCommon()) {
384 : // Common symbols are encoded with the size in the address
385 : // field, and their alignment in the flags.
386 53 : Address = Symbol->getCommonSize();
387 : }
388 :
389 : // struct nlist (12 bytes)
390 :
391 1676 : W.write<uint32_t>(MSD.StringIndex);
392 1676 : W.OS << char(Type);
393 1676 : W.OS << char(SectionIndex);
394 :
395 : // The Mach-O streamer uses the lowest 16-bits of the flags for the 'desc'
396 : // value.
397 : bool EncodeAsAltEntry =
398 1676 : IsAlias && cast<MCSymbolMachO>(OrigSymbol).isAltEntry();
399 1676 : W.write<uint16_t>(cast<MCSymbolMachO>(Symbol)->getEncodedFlags(EncodeAsAltEntry));
400 1676 : if (is64Bit())
401 1023 : W.write<uint64_t>(Address);
402 : else
403 653 : W.write<uint32_t>(Address);
404 1676 : }
405 :
406 18 : void MachObjectWriter::writeLinkeditLoadCommand(uint32_t Type,
407 : uint32_t DataOffset,
408 : uint32_t DataSize) {
409 18 : uint64_t Start = W.OS.tell();
410 : (void) Start;
411 :
412 18 : W.write<uint32_t>(Type);
413 18 : W.write<uint32_t>(sizeof(MachO::linkedit_data_command));
414 18 : W.write<uint32_t>(DataOffset);
415 18 : W.write<uint32_t>(DataSize);
416 :
417 : assert(W.OS.tell() - Start == sizeof(MachO::linkedit_data_command));
418 18 : }
419 :
420 : static unsigned ComputeLinkerOptionsLoadCommandSize(
421 : const std::vector<std::string> &Options, bool is64Bit)
422 : {
423 : unsigned Size = sizeof(MachO::linker_option_command);
424 24 : for (const std::string &Option : Options)
425 14 : Size += Option.size() + 1;
426 10 : return alignTo(Size, is64Bit ? 8 : 4);
427 : }
428 :
429 5 : void MachObjectWriter::writeLinkerOptionsLoadCommand(
430 : const std::vector<std::string> &Options)
431 : {
432 : unsigned Size = ComputeLinkerOptionsLoadCommandSize(Options, is64Bit());
433 5 : uint64_t Start = W.OS.tell();
434 : (void) Start;
435 :
436 5 : W.write<uint32_t>(MachO::LC_LINKER_OPTION);
437 5 : W.write<uint32_t>(Size);
438 10 : W.write<uint32_t>(Options.size());
439 : uint64_t BytesWritten = sizeof(MachO::linker_option_command);
440 12 : for (const std::string &Option : Options) {
441 : // Write each string, including the null byte.
442 7 : W.OS << Option << '\0';
443 7 : BytesWritten += Option.size() + 1;
444 : }
445 :
446 : // Pad to a multiple of the pointer size.
447 10 : W.OS.write_zeros(OffsetToAlignment(BytesWritten, is64Bit() ? 8 : 4));
448 :
449 : assert(W.OS.tell() - Start == Size);
450 5 : }
451 :
452 3455 : void MachObjectWriter::recordRelocation(MCAssembler &Asm,
453 : const MCAsmLayout &Layout,
454 : const MCFragment *Fragment,
455 : const MCFixup &Fixup, MCValue Target,
456 : uint64_t &FixedValue) {
457 3455 : TargetObjectWriter->recordRelocation(this, Asm, Layout, Fragment, Fixup,
458 3455 : Target, FixedValue);
459 3455 : }
460 :
461 667 : void MachObjectWriter::bindIndirectSymbols(MCAssembler &Asm) {
462 : // This is the point where 'as' creates actual symbols for indirect symbols
463 : // (in the following two passes). It would be easier for us to do this sooner
464 : // when we see the attribute, but that makes getting the order in the symbol
465 : // table much more complicated than it is worth.
466 : //
467 : // FIXME: Revisit this when the dust settles.
468 :
469 : // Report errors for use of .indirect_symbol not in a symbol pointer section
470 : // or stub section.
471 : for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
472 708 : ie = Asm.indirect_symbol_end(); it != ie; ++it) {
473 41 : const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section);
474 :
475 41 : if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS &&
476 7 : Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS &&
477 46 : Section.getType() != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS &&
478 : Section.getType() != MachO::S_SYMBOL_STUBS) {
479 0 : MCSymbol &Symbol = *it->Symbol;
480 0 : report_fatal_error("indirect symbol '" + Symbol.getName() +
481 : "' not in a symbol pointer or stub section");
482 : }
483 : }
484 :
485 : // Bind non-lazy symbol pointers first.
486 : unsigned IndirectIndex = 0;
487 41 : for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
488 708 : ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) {
489 41 : const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section);
490 :
491 82 : if (Section.getType() != MachO::S_NON_LAZY_SYMBOL_POINTERS &&
492 : Section.getType() != MachO::S_THREAD_LOCAL_VARIABLE_POINTERS)
493 : continue;
494 :
495 : // Initialize the section indirect symbol base, if necessary.
496 30 : IndirectSymBase.insert(std::make_pair(it->Section, IndirectIndex));
497 :
498 30 : Asm.registerSymbol(*it->Symbol);
499 : }
500 :
501 : // Then lazy symbol pointers and symbol stubs.
502 : IndirectIndex = 0;
503 41 : for (MCAssembler::indirect_symbol_iterator it = Asm.indirect_symbol_begin(),
504 708 : ie = Asm.indirect_symbol_end(); it != ie; ++it, ++IndirectIndex) {
505 41 : const MCSectionMachO &Section = cast<MCSectionMachO>(*it->Section);
506 :
507 82 : if (Section.getType() != MachO::S_LAZY_SYMBOL_POINTERS &&
508 : Section.getType() != MachO::S_SYMBOL_STUBS)
509 30 : continue;
510 :
511 : // Initialize the section indirect symbol base, if necessary.
512 11 : IndirectSymBase.insert(std::make_pair(it->Section, IndirectIndex));
513 :
514 : // Set the symbol type to undefined lazy, but only on construction.
515 : //
516 : // FIXME: Do not hardcode.
517 : bool Created;
518 11 : Asm.registerSymbol(*it->Symbol, &Created);
519 11 : if (Created)
520 4 : cast<MCSymbolMachO>(it->Symbol)->setReferenceTypeUndefinedLazy(true);
521 : }
522 667 : }
523 :
524 : /// computeSymbolTable - Compute the symbol table data
525 612 : void MachObjectWriter::computeSymbolTable(
526 : MCAssembler &Asm, std::vector<MachSymbolData> &LocalSymbolData,
527 : std::vector<MachSymbolData> &ExternalSymbolData,
528 : std::vector<MachSymbolData> &UndefinedSymbolData) {
529 : // Build section lookup table.
530 : DenseMap<const MCSection*, uint8_t> SectionIndexMap;
531 : unsigned Index = 1;
532 3464 : for (MCAssembler::iterator it = Asm.begin(),
533 4076 : ie = Asm.end(); it != ie; ++it, ++Index)
534 3464 : SectionIndexMap[&*it] = Index;
535 : assert(Index <= 256 && "Too many sections!");
536 :
537 : // Build the string table.
538 17678 : for (const MCSymbol &Symbol : Asm.symbols()) {
539 17066 : if (!Asm.isSymbolLinkerVisible(Symbol))
540 : continue;
541 :
542 3354 : StringTable.add(Symbol.getName());
543 : }
544 612 : StringTable.finalize();
545 :
546 : // Build the symbol arrays but only for non-local symbols.
547 : //
548 : // The particular order that we collect and then sort the symbols is chosen to
549 : // match 'as'. Even though it doesn't matter for correctness, this is
550 : // important for letting us diff .o files.
551 17678 : for (const MCSymbol &Symbol : Asm.symbols()) {
552 : // Ignore non-linker visible symbols.
553 17066 : if (!Asm.isSymbolLinkerVisible(Symbol))
554 15957 : continue;
555 :
556 2629 : if (!Symbol.isExternal() && !Symbol.isUndefined())
557 : continue;
558 :
559 : MachSymbolData MSD;
560 1109 : MSD.Symbol = &Symbol;
561 1109 : MSD.StringIndex = StringTable.getOffset(Symbol.getName());
562 :
563 1109 : if (Symbol.isUndefined()) {
564 469 : MSD.SectionIndex = 0;
565 469 : UndefinedSymbolData.push_back(MSD);
566 640 : } else if (Symbol.isAbsolute()) {
567 3 : MSD.SectionIndex = 0;
568 3 : ExternalSymbolData.push_back(MSD);
569 : } else {
570 637 : MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
571 : assert(MSD.SectionIndex && "Invalid section index!");
572 637 : ExternalSymbolData.push_back(MSD);
573 : }
574 : }
575 :
576 : // Now add the data for local symbols.
577 17678 : for (const MCSymbol &Symbol : Asm.symbols()) {
578 : // Ignore non-linker visible symbols.
579 17066 : if (!Asm.isSymbolLinkerVisible(Symbol))
580 16498 : continue;
581 :
582 2629 : if (Symbol.isExternal() || Symbol.isUndefined())
583 1109 : continue;
584 :
585 : MachSymbolData MSD;
586 568 : MSD.Symbol = &Symbol;
587 568 : MSD.StringIndex = StringTable.getOffset(Symbol.getName());
588 :
589 568 : if (Symbol.isAbsolute()) {
590 4 : MSD.SectionIndex = 0;
591 4 : LocalSymbolData.push_back(MSD);
592 : } else {
593 564 : MSD.SectionIndex = SectionIndexMap.lookup(&Symbol.getSection());
594 : assert(MSD.SectionIndex && "Invalid section index!");
595 564 : LocalSymbolData.push_back(MSD);
596 : }
597 : }
598 :
599 : // External and undefined symbols are required to be in lexicographic order.
600 : llvm::sort(ExternalSymbolData);
601 : llvm::sort(UndefinedSymbolData);
602 :
603 : // Set the symbol indices.
604 : Index = 0;
605 3672 : for (auto *SymbolData :
606 2448 : {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
607 3513 : for (MachSymbolData &Entry : *SymbolData)
608 1677 : Entry.Symbol->setIndex(Index++);
609 :
610 4076 : for (const MCSection &Section : Asm) {
611 6731 : for (RelAndSymbol &Rel : Relocations[&Section]) {
612 3267 : if (!Rel.Sym)
613 : continue;
614 :
615 : // Set the Index and the IsExtern bit.
616 1899 : unsigned Index = Rel.Sym->getIndex();
617 : assert(isInt<24>(Index));
618 1899 : if (W.Endian == support::little)
619 1898 : Rel.MRE.r_word1 = (Rel.MRE.r_word1 & (~0U << 24)) | Index | (1 << 27);
620 : else
621 1 : Rel.MRE.r_word1 = (Rel.MRE.r_word1 & 0xff) | Index << 8 | (1 << 4);
622 : }
623 : }
624 612 : }
625 :
626 667 : void MachObjectWriter::computeSectionAddresses(const MCAssembler &Asm,
627 : const MCAsmLayout &Layout) {
628 : uint64_t StartAddress = 0;
629 4744 : for (const MCSection *Sec : Layout.getSectionOrder()) {
630 4077 : StartAddress = alignTo(StartAddress, Sec->getAlignment());
631 4077 : SectionAddress[Sec] = StartAddress;
632 4077 : StartAddress += Layout.getSectionAddressSize(Sec);
633 :
634 : // Explicitly pad the section to match the alignment requirements of the
635 : // following one. This is for 'gas' compatibility, it shouldn't
636 : /// strictly be necessary.
637 4077 : StartAddress += getPaddingSize(Sec, Layout);
638 : }
639 667 : }
640 :
641 667 : void MachObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
642 : const MCAsmLayout &Layout) {
643 667 : computeSectionAddresses(Asm, Layout);
644 :
645 : // Create symbol data for any indirect symbols.
646 667 : bindIndirectSymbols(Asm);
647 667 : }
648 :
649 9737 : bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
650 : const MCAssembler &Asm, const MCSymbol &A, const MCSymbol &B,
651 : bool InSet) const {
652 : // FIXME: We don't handle things like
653 : // foo = .
654 : // creating atoms.
655 9737 : if (A.isVariable() || B.isVariable())
656 : return false;
657 9734 : return MCObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(Asm, A, B,
658 9734 : InSet);
659 : }
660 :
661 10896 : bool MachObjectWriter::isSymbolRefDifferenceFullyResolvedImpl(
662 : const MCAssembler &Asm, const MCSymbol &SymA, const MCFragment &FB,
663 : bool InSet, bool IsPCRel) const {
664 10896 : if (InSet)
665 : return true;
666 :
667 : // The effective address is
668 : // addr(atom(A)) + offset(A)
669 : // - addr(atom(B)) - offset(B)
670 : // and the offsets are not relocatable, so the fixup is fully resolved when
671 : // addr(atom(A)) - addr(atom(B)) == 0.
672 2009 : const MCSymbol &SA = findAliasedSymbol(SymA);
673 : const MCSection &SecA = SA.getSection();
674 2009 : const MCSection &SecB = *FB.getParent();
675 :
676 2009 : if (IsPCRel) {
677 : // The simple (Darwin, except on x86_64) way of dealing with this was to
678 : // assume that any reference to a temporary symbol *must* be a temporary
679 : // symbol in the same atom, unless the sections differ. Therefore, any PCrel
680 : // relocation to a temporary symbol (in the same section) is fully
681 : // resolved. This also works in conjunction with absolutized .set, which
682 : // requires the compiler to use .set to absolutize the differences between
683 : // symbols which the compiler knows to be assembly time constants, so we
684 : // don't need to worry about considering symbol differences fully resolved.
685 : //
686 : // If the file isn't using sub-sections-via-symbols, we can make the
687 : // same assumptions about any symbol that we normally make about
688 : // assembler locals.
689 :
690 : bool hasReliableSymbolDifference = isX86_64();
691 1162 : if (!hasReliableSymbolDifference) {
692 714 : if (!SA.isInSection() || &SecA != &SecB ||
693 60 : (!SA.isTemporary() && FB.getAtom() != SA.getFragment()->getAtom() &&
694 : Asm.getSubsectionsViaSymbols()))
695 53 : return false;
696 661 : return true;
697 : }
698 : // For Darwin x86_64, there is one special case when the reference IsPCRel.
699 : // If the fragment with the reference does not have a base symbol but meets
700 : // the simple way of dealing with this, in that it is a temporary symbol in
701 : // the same atom then it is assumed to be fully resolved. This is needed so
702 : // a relocation entry is not created and so the static linker does not
703 : // mess up the reference later.
704 44 : else if(!FB.getAtom() &&
705 478 : SA.isTemporary() && SA.isInSection() && &SecA == &SecB){
706 : return true;
707 : }
708 : }
709 :
710 : // If they are not in the same section, we can't compute the diff.
711 1293 : if (&SecA != &SecB)
712 : return false;
713 :
714 1078 : const MCFragment *FA = SA.getFragment();
715 :
716 : // Bail if the symbol has no fragment.
717 1078 : if (!FA)
718 : return false;
719 :
720 : // If the atoms are the same, they are guaranteed to have the same address.
721 1078 : if (FA->getAtom() == FB.getAtom())
722 957 : return true;
723 :
724 : // Otherwise, we can't prove this is fully resolved.
725 : return false;
726 : }
727 :
728 : static MachO::LoadCommandType getLCFromMCVM(MCVersionMinType Type) {
729 : switch (Type) {
730 : case MCVM_OSXVersionMin: return MachO::LC_VERSION_MIN_MACOSX;
731 : case MCVM_IOSVersionMin: return MachO::LC_VERSION_MIN_IPHONEOS;
732 : case MCVM_TvOSVersionMin: return MachO::LC_VERSION_MIN_TVOS;
733 : case MCVM_WatchOSVersionMin: return MachO::LC_VERSION_MIN_WATCHOS;
734 : }
735 0 : llvm_unreachable("Invalid mc version min type");
736 : }
737 :
738 612 : uint64_t MachObjectWriter::writeObject(MCAssembler &Asm,
739 : const MCAsmLayout &Layout) {
740 612 : uint64_t StartOffset = W.OS.tell();
741 :
742 : // Compute symbol table information and bind symbol indices.
743 612 : computeSymbolTable(Asm, LocalSymbolData, ExternalSymbolData,
744 612 : UndefinedSymbolData);
745 :
746 612 : unsigned NumSections = Asm.size();
747 : const MCAssembler::VersionInfoType &VersionInfo =
748 612 : Layout.getAssembler().getVersionInfo();
749 :
750 : // The section data starts after the header, the segment load command (and
751 : // section headers) and the symbol table.
752 : unsigned NumLoadCommands = 1;
753 612 : uint64_t LoadCommandsSize = is64Bit() ?
754 422 : sizeof(MachO::segment_command_64) + NumSections * sizeof(MachO::section_64):
755 190 : sizeof(MachO::segment_command) + NumSections * sizeof(MachO::section);
756 :
757 : // Add the deployment target version info load command size, if used.
758 612 : if (VersionInfo.Major != 0) {
759 : ++NumLoadCommands;
760 343 : if (VersionInfo.EmitBuildVersion)
761 1 : LoadCommandsSize += sizeof(MachO::build_version_command);
762 : else
763 342 : LoadCommandsSize += sizeof(MachO::version_min_command);
764 : }
765 :
766 : // Add the data-in-code load command size, if used.
767 612 : unsigned NumDataRegions = Asm.getDataRegions().size();
768 612 : if (NumDataRegions) {
769 17 : ++NumLoadCommands;
770 17 : LoadCommandsSize += sizeof(MachO::linkedit_data_command);
771 : }
772 :
773 : // Add the loh load command size, if used.
774 612 : uint64_t LOHRawSize = Asm.getLOHContainer().getEmitSize(*this, Layout);
775 612 : uint64_t LOHSize = alignTo(LOHRawSize, is64Bit() ? 8 : 4);
776 612 : if (LOHSize) {
777 1 : ++NumLoadCommands;
778 1 : LoadCommandsSize += sizeof(MachO::linkedit_data_command);
779 : }
780 :
781 : // Add the symbol table load command sizes, if used.
782 1224 : unsigned NumSymbols = LocalSymbolData.size() + ExternalSymbolData.size() +
783 612 : UndefinedSymbolData.size();
784 612 : if (NumSymbols) {
785 492 : NumLoadCommands += 2;
786 492 : LoadCommandsSize += (sizeof(MachO::symtab_command) +
787 : sizeof(MachO::dysymtab_command));
788 : }
789 :
790 : // Add the linker option load commands sizes.
791 617 : for (const auto &Option : Asm.getLinkerOptions()) {
792 5 : ++NumLoadCommands;
793 5 : LoadCommandsSize += ComputeLinkerOptionsLoadCommandSize(Option, is64Bit());
794 : }
795 :
796 : // Compute the total size of the section data, as well as its file size and vm
797 : // size.
798 612 : uint64_t SectionDataStart = (is64Bit() ? sizeof(MachO::mach_header_64) :
799 612 : sizeof(MachO::mach_header)) + LoadCommandsSize;
800 612 : uint64_t SectionDataSize = 0;
801 612 : uint64_t SectionDataFileSize = 0;
802 612 : uint64_t VMSize = 0;
803 4076 : for (const MCSection &Sec : Asm) {
804 : uint64_t Address = getSectionAddress(&Sec);
805 3464 : uint64_t Size = Layout.getSectionAddressSize(&Sec);
806 3464 : uint64_t FileSize = Layout.getSectionFileSize(&Sec);
807 3464 : FileSize += getPaddingSize(&Sec, Layout);
808 :
809 3464 : VMSize = std::max(VMSize, Address + Size);
810 :
811 3464 : if (Sec.isVirtualSection())
812 : continue;
813 :
814 3421 : SectionDataSize = std::max(SectionDataSize, Address + Size);
815 6504 : SectionDataFileSize = std::max(SectionDataFileSize, Address + FileSize);
816 : }
817 :
818 : // The section data is padded to 4 bytes.
819 : //
820 : // FIXME: Is this machine dependent?
821 612 : unsigned SectionDataPadding = OffsetToAlignment(SectionDataFileSize, 4);
822 612 : SectionDataFileSize += SectionDataPadding;
823 :
824 : // Write the prolog, starting with the header and load command...
825 612 : writeHeader(MachO::MH_OBJECT, NumLoadCommands, LoadCommandsSize,
826 : Asm.getSubsectionsViaSymbols());
827 : uint32_t Prot =
828 : MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE;
829 1224 : writeSegmentLoadCommand("", NumSections, 0, VMSize, SectionDataStart,
830 : SectionDataSize, Prot, Prot);
831 :
832 : // ... and then the section headers.
833 612 : uint64_t RelocTableEnd = SectionDataStart + SectionDataFileSize;
834 4076 : for (const MCSection &Section : Asm) {
835 : const auto &Sec = cast<MCSectionMachO>(Section);
836 3464 : std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];
837 6928 : unsigned NumRelocs = Relocs.size();
838 3464 : uint64_t SectionStart = SectionDataStart + getSectionAddress(&Sec);
839 3464 : unsigned Flags = Sec.getTypeAndAttributes();
840 3464 : if (Sec.hasInstructions())
841 410 : Flags |= MachO::S_ATTR_SOME_INSTRUCTIONS;
842 3464 : writeSection(Layout, Sec, getSectionAddress(&Sec), SectionStart, Flags,
843 : RelocTableEnd, NumRelocs);
844 3464 : RelocTableEnd += NumRelocs * sizeof(MachO::any_relocation_info);
845 : }
846 :
847 : // Write out the deployment target information, if it's available.
848 612 : if (VersionInfo.Major != 0) {
849 : assert(VersionInfo.Update < 256 && "unencodable update target version");
850 : assert(VersionInfo.Minor < 256 && "unencodable minor target version");
851 : assert(VersionInfo.Major < 65536 && "unencodable major target version");
852 686 : uint32_t EncodedVersion = VersionInfo.Update | (VersionInfo.Minor << 8) |
853 343 : (VersionInfo.Major << 16);
854 343 : if (VersionInfo.EmitBuildVersion) {
855 : // FIXME: Currently empty tools. Add clang version in the future.
856 1 : W.write<uint32_t>(MachO::LC_BUILD_VERSION);
857 1 : W.write<uint32_t>(sizeof(MachO::build_version_command));
858 1 : W.write<uint32_t>(VersionInfo.TypeOrPlatform.Platform);
859 1 : W.write<uint32_t>(EncodedVersion);
860 1 : W.write<uint32_t>(0); // SDK version.
861 1 : W.write<uint32_t>(0); // Empty tools list.
862 : } else {
863 : MachO::LoadCommandType LCType
864 342 : = getLCFromMCVM(VersionInfo.TypeOrPlatform.Type);
865 342 : W.write<uint32_t>(LCType);
866 342 : W.write<uint32_t>(sizeof(MachO::version_min_command));
867 342 : W.write<uint32_t>(EncodedVersion);
868 342 : W.write<uint32_t>(0); // reserved.
869 : }
870 : }
871 :
872 : // Write the data-in-code load command, if used.
873 612 : uint64_t DataInCodeTableEnd = RelocTableEnd + NumDataRegions * 8;
874 612 : if (NumDataRegions) {
875 : uint64_t DataRegionsOffset = RelocTableEnd;
876 : uint64_t DataRegionsSize = NumDataRegions * 8;
877 17 : writeLinkeditLoadCommand(MachO::LC_DATA_IN_CODE, DataRegionsOffset,
878 : DataRegionsSize);
879 : }
880 :
881 : // Write the loh load command, if used.
882 612 : uint64_t LOHTableEnd = DataInCodeTableEnd + LOHSize;
883 612 : if (LOHSize)
884 1 : writeLinkeditLoadCommand(MachO::LC_LINKER_OPTIMIZATION_HINT,
885 : DataInCodeTableEnd, LOHSize);
886 :
887 : // Write the symbol table load command, if used.
888 612 : if (NumSymbols) {
889 : unsigned FirstLocalSymbol = 0;
890 492 : unsigned NumLocalSymbols = LocalSymbolData.size();
891 : unsigned FirstExternalSymbol = FirstLocalSymbol + NumLocalSymbols;
892 492 : unsigned NumExternalSymbols = ExternalSymbolData.size();
893 492 : unsigned FirstUndefinedSymbol = FirstExternalSymbol + NumExternalSymbols;
894 984 : unsigned NumUndefinedSymbols = UndefinedSymbolData.size();
895 492 : unsigned NumIndirectSymbols = Asm.indirect_symbol_size();
896 492 : unsigned NumSymTabSymbols =
897 : NumLocalSymbols + NumExternalSymbols + NumUndefinedSymbols;
898 492 : uint64_t IndirectSymbolSize = NumIndirectSymbols * 4;
899 : uint64_t IndirectSymbolOffset = 0;
900 :
901 : // If used, the indirect symbols are written after the section data.
902 492 : if (NumIndirectSymbols)
903 : IndirectSymbolOffset = LOHTableEnd;
904 :
905 : // The symbol table is written after the indirect symbol data.
906 492 : uint64_t SymbolTableOffset = LOHTableEnd + IndirectSymbolSize;
907 :
908 : // The string table is written after symbol table.
909 : uint64_t StringTableOffset =
910 984 : SymbolTableOffset + NumSymTabSymbols * (is64Bit() ?
911 : sizeof(MachO::nlist_64) :
912 492 : sizeof(MachO::nlist));
913 492 : writeSymtabLoadCommand(SymbolTableOffset, NumSymTabSymbols,
914 492 : StringTableOffset, StringTable.getSize());
915 :
916 492 : writeDysymtabLoadCommand(FirstLocalSymbol, NumLocalSymbols,
917 : FirstExternalSymbol, NumExternalSymbols,
918 : FirstUndefinedSymbol, NumUndefinedSymbols,
919 : IndirectSymbolOffset, NumIndirectSymbols);
920 : }
921 :
922 : // Write the linker options load commands.
923 617 : for (const auto &Option : Asm.getLinkerOptions())
924 5 : writeLinkerOptionsLoadCommand(Option);
925 :
926 : // Write the actual section data.
927 4076 : for (const MCSection &Sec : Asm) {
928 3464 : Asm.writeSectionData(W.OS, &Sec, Layout);
929 :
930 3464 : uint64_t Pad = getPaddingSize(&Sec, Layout);
931 3464 : W.OS.write_zeros(Pad);
932 : }
933 :
934 : // Write the extra padding.
935 612 : W.OS.write_zeros(SectionDataPadding);
936 :
937 : // Write the relocation entries.
938 4076 : for (const MCSection &Sec : Asm) {
939 : // Write the section relocation entries, in reverse order to match 'as'
940 : // (approximately, the exact algorithm is more complicated than this).
941 3464 : std::vector<RelAndSymbol> &Relocs = Relocations[&Sec];
942 6731 : for (const RelAndSymbol &Rel : make_range(Relocs.rbegin(), Relocs.rend())) {
943 3267 : W.write<uint32_t>(Rel.MRE.r_word0);
944 3267 : W.write<uint32_t>(Rel.MRE.r_word1);
945 : }
946 : }
947 :
948 : // Write out the data-in-code region payload, if there is one.
949 : for (MCAssembler::const_data_region_iterator
950 : it = Asm.data_region_begin(), ie = Asm.data_region_end();
951 659 : it != ie; ++it) {
952 : const DataRegionData *Data = &(*it);
953 48 : uint64_t Start = getSymbolAddress(*Data->Start, Layout);
954 : uint64_t End;
955 48 : if (Data->End)
956 47 : End = getSymbolAddress(*Data->End, Layout);
957 : else
958 1 : report_fatal_error("Data region not terminated");
959 :
960 : LLVM_DEBUG(dbgs() << "data in code region-- kind: " << Data->Kind
961 : << " start: " << Start << "(" << Data->Start->getName()
962 : << ")"
963 : << " end: " << End << "(" << Data->End->getName() << ")"
964 : << " size: " << End - Start << "\n");
965 47 : W.write<uint32_t>(Start);
966 47 : W.write<uint16_t>(End - Start);
967 47 : W.write<uint16_t>(Data->Kind);
968 : }
969 :
970 : // Write out the loh commands, if there is one.
971 611 : if (LOHSize) {
972 : #ifndef NDEBUG
973 : unsigned Start = W.OS.tell();
974 : #endif
975 : Asm.getLOHContainer().emit(*this, Layout);
976 : // Pad to a multiple of the pointer size.
977 2 : W.OS.write_zeros(OffsetToAlignment(LOHRawSize, is64Bit() ? 8 : 4));
978 : assert(W.OS.tell() - Start == LOHSize);
979 : }
980 :
981 : // Write the symbol table data, if used.
982 611 : if (NumSymbols) {
983 : // Write the indirect symbol entries.
984 : for (MCAssembler::const_indirect_symbol_iterator
985 : it = Asm.indirect_symbol_begin(),
986 532 : ie = Asm.indirect_symbol_end(); it != ie; ++it) {
987 : // Indirect symbols in the non-lazy symbol pointer section have some
988 : // special handling.
989 : const MCSectionMachO &Section =
990 41 : static_cast<const MCSectionMachO &>(*it->Section);
991 82 : if (Section.getType() == MachO::S_NON_LAZY_SYMBOL_POINTERS) {
992 : // If this symbol is defined and internal, mark it as such.
993 28 : if (it->Symbol->isDefined() && !it->Symbol->isExternal()) {
994 : uint32_t Flags = MachO::INDIRECT_SYMBOL_LOCAL;
995 3 : if (it->Symbol->isAbsolute())
996 : Flags |= MachO::INDIRECT_SYMBOL_ABS;
997 3 : W.write<uint32_t>(Flags);
998 3 : continue;
999 : }
1000 : }
1001 :
1002 38 : W.write<uint32_t>(it->Symbol->getIndex());
1003 : }
1004 :
1005 : // FIXME: Check that offsets match computed ones.
1006 :
1007 : // Write the symbol table entries.
1008 2946 : for (auto *SymbolData :
1009 1964 : {&LocalSymbolData, &ExternalSymbolData, &UndefinedSymbolData})
1010 3149 : for (MachSymbolData &Entry : *SymbolData)
1011 1676 : writeNlist(Entry, Layout);
1012 :
1013 : // Write the string table.
1014 491 : StringTable.write(W.OS);
1015 : }
1016 :
1017 611 : return W.OS.tell() - StartOffset;
1018 : }
1019 :
1020 : std::unique_ptr<MCObjectWriter>
1021 3050 : llvm::createMachObjectWriter(std::unique_ptr<MCMachObjectTargetWriter> MOTW,
1022 : raw_pwrite_stream &OS, bool IsLittleEndian) {
1023 3050 : return llvm::make_unique<MachObjectWriter>(std::move(MOTW), OS,
1024 3050 : IsLittleEndian);
1025 : }
|