1//===- MCMachOStreamer.cpp - MachO Streamer -------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/ADT/DenseMap.h"
10#include "llvm/ADT/SmallString.h"
11#include "llvm/ADT/SmallVector.h"
12#include "llvm/ADT/StringRef.h"
13#include "llvm/BinaryFormat/MachO.h"
14#include "llvm/MC/MCAsmBackend.h"
15#include "llvm/MC/MCAssembler.h"
16#include "llvm/MC/MCCodeEmitter.h"
17#include "llvm/MC/MCContext.h"
18#include "llvm/MC/MCDirectives.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCFixup.h"
21#include "llvm/MC/MCFragment.h"
22#include "llvm/MC/MCLinkerOptimizationHint.h"
23#include "llvm/MC/MCMachObjectWriter.h"
24#include "llvm/MC/MCObjectFileInfo.h"
25#include "llvm/MC/MCObjectStreamer.h"
26#include "llvm/MC/MCObjectWriter.h"
27#include "llvm/MC/MCSection.h"
28#include "llvm/MC/MCSectionMachO.h"
29#include "llvm/MC/MCSymbol.h"
30#include "llvm/MC/MCSymbolMachO.h"
31#include "llvm/MC/MCValue.h"
32#include "llvm/MC/SectionKind.h"
33#include "llvm/MC/TargetRegistry.h"
34#include "llvm/Support/Casting.h"
35#include "llvm/Support/ErrorHandling.h"
36#include <cassert>
37#include <vector>
38
39namespace llvm {
40class MCInst;
41class MCStreamer;
42class MCSubtargetInfo;
43class Triple;
44} // namespace llvm
45
46using namespace llvm;
47
48namespace {
49
50class MCMachOStreamer : public MCObjectStreamer {
51private:
52 /// LabelSections - true if each section change should emit a linker local
53 /// label for use in relocations for assembler local references. Obviates the
54 /// need for local relocations. False by default.
55 bool LabelSections;
56
57 /// HasSectionLabel - map of which sections have already had a non-local
58 /// label emitted to them. Used so we don't emit extraneous linker local
59 /// labels in the middle of the section.
60 DenseMap<const MCSection*, bool> HasSectionLabel;
61
62 void emitInstToData(const MCInst &Inst, const MCSubtargetInfo &STI) override;
63
64 void emitDataRegion(MachO::DataRegionType Kind);
65 void emitDataRegionEnd();
66
67public:
68 MCMachOStreamer(MCContext &Context, std::unique_ptr<MCAsmBackend> MAB,
69 std::unique_ptr<MCObjectWriter> OW,
70 std::unique_ptr<MCCodeEmitter> Emitter, bool label)
71 : MCObjectStreamer(Context, std::move(MAB), std::move(OW),
72 std::move(Emitter)),
73 LabelSections(label) {}
74
75 /// state management
76 void reset() override {
77 HasSectionLabel.clear();
78 MCObjectStreamer::reset();
79 }
80
81 MachObjectWriter &getWriter() {
82 return static_cast<MachObjectWriter &>(getAssembler().getWriter());
83 }
84
85 /// @name MCStreamer Interface
86 /// @{
87
88 void changeSection(MCSection *Sect, uint32_t Subsection = 0) override;
89 void emitLabel(MCSymbol *Symbol, SMLoc Loc = SMLoc()) override;
90 void emitAssignment(MCSymbol *Symbol, const MCExpr *Value) override;
91 void emitEHSymAttributes(const MCSymbol *Symbol, MCSymbol *EHSymbol) override;
92 void emitAssemblerFlag(MCAssemblerFlag Flag) override;
93 void emitLinkerOptions(ArrayRef<std::string> Options) override;
94 void emitDataRegion(MCDataRegionType Kind) override;
95 void emitVersionMin(MCVersionMinType Kind, unsigned Major, unsigned Minor,
96 unsigned Update, VersionTuple SDKVersion) override;
97 void emitBuildVersion(unsigned Platform, unsigned Major, unsigned Minor,
98 unsigned Update, VersionTuple SDKVersion) override;
99 void emitDarwinTargetVariantBuildVersion(unsigned Platform, unsigned Major,
100 unsigned Minor, unsigned Update,
101 VersionTuple SDKVersion) override;
102 void emitThumbFunc(MCSymbol *Func) override;
103 bool emitSymbolAttribute(MCSymbol *Symbol, MCSymbolAttr Attribute) override;
104 void emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) override;
105 void emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
106 Align ByteAlignment) override;
107
108 void emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
109 Align ByteAlignment) override;
110 void emitZerofill(MCSection *Section, MCSymbol *Symbol = nullptr,
111 uint64_t Size = 0, Align ByteAlignment = Align(1),
112 SMLoc Loc = SMLoc()) override;
113 void emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol, uint64_t Size,
114 Align ByteAlignment = Align(1)) override;
115
116 void emitIdent(StringRef IdentString) override {
117 llvm_unreachable("macho doesn't support this directive");
118 }
119
120 void emitLOHDirective(MCLOHType Kind, const MCLOHArgs &Args) override {
121 getWriter().getLOHContainer().addDirective(Kind, Args);
122 }
123 void emitCGProfileEntry(const MCSymbolRefExpr *From,
124 const MCSymbolRefExpr *To, uint64_t Count) override {
125 if (!From->getSymbol().isTemporary() && !To->getSymbol().isTemporary())
126 getWriter().getCGProfile().push_back(Elt: {.From: From, .To: To, .Count: Count});
127 }
128
129 void finishImpl() override;
130
131 void finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE);
132 void finalizeCGProfile();
133 void createAddrSigSection();
134};
135
136} // end anonymous namespace.
137
138void MCMachOStreamer::changeSection(MCSection *Section, uint32_t Subsection) {
139 // Change the section normally.
140 changeSectionImpl(Section, Subsection);
141
142 // Output a linker-local symbol so we don't need section-relative local
143 // relocations. The linker hates us when we do that.
144 if (LabelSections && !HasSectionLabel[Section] &&
145 !Section->getBeginSymbol()) {
146 MCSymbol *Label = getContext().createLinkerPrivateTempSymbol();
147 Section->setBeginSymbol(Label);
148 HasSectionLabel[Section] = true;
149 }
150}
151
152void MCMachOStreamer::emitEHSymAttributes(const MCSymbol *Symbol,
153 MCSymbol *EHSymbol) {
154 auto *Sym = cast<MCSymbolMachO>(Val: Symbol);
155 getAssembler().registerSymbol(Symbol: *Symbol);
156 if (Symbol->isExternal())
157 emitSymbolAttribute(Symbol: EHSymbol, Attribute: MCSA_Global);
158 if (Sym->isWeakDefinition())
159 emitSymbolAttribute(Symbol: EHSymbol, Attribute: MCSA_WeakDefinition);
160 if (Sym->isPrivateExtern())
161 emitSymbolAttribute(Symbol: EHSymbol, Attribute: MCSA_PrivateExtern);
162}
163
164void MCMachOStreamer::emitLabel(MCSymbol *Symbol, SMLoc Loc) {
165 // We have to create a new fragment if this is an atom defining symbol,
166 // fragments cannot span atoms.
167 if (cast<MCSymbolMachO>(Val: Symbol)->isSymbolLinkerVisible())
168 insert(F: getContext().allocFragment<MCDataFragment>());
169
170 MCObjectStreamer::emitLabel(Symbol, Loc);
171
172 // This causes the reference type flag to be cleared. Darwin 'as' was "trying"
173 // to clear the weak reference and weak definition bits too, but the
174 // implementation was buggy. For now we just try to match 'as', for
175 // diffability.
176 //
177 // FIXME: Cleanup this code, these bits should be emitted based on semantic
178 // properties, not on the order of definition, etc.
179 cast<MCSymbolMachO>(Val: Symbol)->clearReferenceType();
180}
181
182void MCMachOStreamer::emitAssignment(MCSymbol *Symbol, const MCExpr *Value) {
183 MCValue Res;
184
185 if (Value->evaluateAsRelocatable(Res, Asm: nullptr, Fixup: nullptr)) {
186 if (const MCSymbolRefExpr *SymAExpr = Res.getSymA()) {
187 const MCSymbol &SymA = SymAExpr->getSymbol();
188 if (!Res.getSymB() && (SymA.getName() == "" || Res.getConstant() != 0))
189 cast<MCSymbolMachO>(Val: Symbol)->setAltEntry();
190 }
191 }
192 MCObjectStreamer::emitAssignment(Symbol, Value);
193}
194
195void MCMachOStreamer::emitDataRegion(MachO::DataRegionType Kind) {
196 // Create a temporary label to mark the start of the data region.
197 MCSymbol *Start = getContext().createTempSymbol();
198 emitLabel(Symbol: Start);
199 // Record the region for the object writer to use.
200 getWriter().getDataRegions().push_back(x: {.Kind: Kind, .Start: Start, .End: nullptr});
201}
202
203void MCMachOStreamer::emitDataRegionEnd() {
204 auto &Regions = getWriter().getDataRegions();
205 assert(!Regions.empty() && "Mismatched .end_data_region!");
206 auto &Data = Regions.back();
207 assert(!Data.End && "Mismatched .end_data_region!");
208 // Create a temporary label to mark the end of the data region.
209 Data.End = getContext().createTempSymbol();
210 emitLabel(Symbol: Data.End);
211}
212
213void MCMachOStreamer::emitAssemblerFlag(MCAssemblerFlag Flag) {
214 // Let the target do whatever target specific stuff it needs to do.
215 getAssembler().getBackend().handleAssemblerFlag(Flag);
216 // Do any generic stuff we need to do.
217 switch (Flag) {
218 case MCAF_SyntaxUnified: return; // no-op here.
219 case MCAF_Code16: return; // Change parsing mode; no-op here.
220 case MCAF_Code32: return; // Change parsing mode; no-op here.
221 case MCAF_Code64: return; // Change parsing mode; no-op here.
222 case MCAF_SubsectionsViaSymbols:
223 getWriter().setSubsectionsViaSymbols(true);
224 return;
225 }
226}
227
228void MCMachOStreamer::emitLinkerOptions(ArrayRef<std::string> Options) {
229 getWriter().getLinkerOptions().push_back(x: Options);
230}
231
232void MCMachOStreamer::emitDataRegion(MCDataRegionType Kind) {
233 switch (Kind) {
234 case MCDR_DataRegion:
235 emitDataRegion(Kind: MachO::DataRegionType::DICE_KIND_DATA);
236 return;
237 case MCDR_DataRegionJT8:
238 emitDataRegion(Kind: MachO::DataRegionType::DICE_KIND_JUMP_TABLE8);
239 return;
240 case MCDR_DataRegionJT16:
241 emitDataRegion(Kind: MachO::DataRegionType::DICE_KIND_JUMP_TABLE16);
242 return;
243 case MCDR_DataRegionJT32:
244 emitDataRegion(Kind: MachO::DataRegionType::DICE_KIND_JUMP_TABLE32);
245 return;
246 case MCDR_DataRegionEnd:
247 emitDataRegionEnd();
248 return;
249 }
250}
251
252void MCMachOStreamer::emitVersionMin(MCVersionMinType Kind, unsigned Major,
253 unsigned Minor, unsigned Update,
254 VersionTuple SDKVersion) {
255 getWriter().setVersionMin(Type: Kind, Major, Minor, Update, SDKVersion);
256}
257
258void MCMachOStreamer::emitBuildVersion(unsigned Platform, unsigned Major,
259 unsigned Minor, unsigned Update,
260 VersionTuple SDKVersion) {
261 getWriter().setBuildVersion(Platform: (MachO::PlatformType)Platform, Major, Minor,
262 Update, SDKVersion);
263}
264
265void MCMachOStreamer::emitDarwinTargetVariantBuildVersion(
266 unsigned Platform, unsigned Major, unsigned Minor, unsigned Update,
267 VersionTuple SDKVersion) {
268 getWriter().setTargetVariantBuildVersion(Platform: (MachO::PlatformType)Platform, Major,
269 Minor, Update, SDKVersion);
270}
271
272void MCMachOStreamer::emitThumbFunc(MCSymbol *Symbol) {
273 // Remember that the function is a thumb function. Fixup and relocation
274 // values will need adjusted.
275 getAssembler().setIsThumbFunc(Symbol);
276 cast<MCSymbolMachO>(Val: Symbol)->setThumbFunc();
277}
278
279bool MCMachOStreamer::emitSymbolAttribute(MCSymbol *Sym,
280 MCSymbolAttr Attribute) {
281 MCSymbolMachO *Symbol = cast<MCSymbolMachO>(Val: Sym);
282
283 // Indirect symbols are handled differently, to match how 'as' handles
284 // them. This makes writing matching .o files easier.
285 if (Attribute == MCSA_IndirectSymbol) {
286 // Note that we intentionally cannot use the symbol data here; this is
287 // important for matching the string table that 'as' generates.
288 getWriter().getIndirectSymbols().push_back(
289 x: {.Symbol: Symbol, .Section: getCurrentSectionOnly()});
290 return true;
291 }
292
293 // Adding a symbol attribute always introduces the symbol, note that an
294 // important side effect of calling registerSymbol here is to register
295 // the symbol with the assembler.
296 getAssembler().registerSymbol(Symbol: *Symbol);
297
298 // The implementation of symbol attributes is designed to match 'as', but it
299 // leaves much to desired. It doesn't really make sense to arbitrarily add and
300 // remove flags, but 'as' allows this (in particular, see .desc).
301 //
302 // In the future it might be worth trying to make these operations more well
303 // defined.
304 switch (Attribute) {
305 case MCSA_Invalid:
306 case MCSA_ELF_TypeFunction:
307 case MCSA_ELF_TypeIndFunction:
308 case MCSA_ELF_TypeObject:
309 case MCSA_ELF_TypeTLS:
310 case MCSA_ELF_TypeCommon:
311 case MCSA_ELF_TypeNoType:
312 case MCSA_ELF_TypeGnuUniqueObject:
313 case MCSA_Extern:
314 case MCSA_Hidden:
315 case MCSA_IndirectSymbol:
316 case MCSA_Internal:
317 case MCSA_Protected:
318 case MCSA_Weak:
319 case MCSA_Local:
320 case MCSA_LGlobal:
321 case MCSA_Exported:
322 case MCSA_Memtag:
323 case MCSA_WeakAntiDep:
324 return false;
325
326 case MCSA_Global:
327 Symbol->setExternal(true);
328 // This effectively clears the undefined lazy bit, in Darwin 'as', although
329 // it isn't very consistent because it implements this as part of symbol
330 // lookup.
331 //
332 // FIXME: Cleanup this code, these bits should be emitted based on semantic
333 // properties, not on the order of definition, etc.
334 Symbol->setReferenceTypeUndefinedLazy(false);
335 break;
336
337 case MCSA_LazyReference:
338 // FIXME: This requires -dynamic.
339 Symbol->setNoDeadStrip();
340 if (Symbol->isUndefined())
341 Symbol->setReferenceTypeUndefinedLazy(true);
342 break;
343
344 // Since .reference sets the no dead strip bit, it is equivalent to
345 // .no_dead_strip in practice.
346 case MCSA_Reference:
347 case MCSA_NoDeadStrip:
348 Symbol->setNoDeadStrip();
349 break;
350
351 case MCSA_SymbolResolver:
352 Symbol->setSymbolResolver();
353 break;
354
355 case MCSA_AltEntry:
356 Symbol->setAltEntry();
357 break;
358
359 case MCSA_PrivateExtern:
360 Symbol->setExternal(true);
361 Symbol->setPrivateExtern(true);
362 break;
363
364 case MCSA_WeakReference:
365 // FIXME: This requires -dynamic.
366 if (Symbol->isUndefined())
367 Symbol->setWeakReference();
368 break;
369
370 case MCSA_WeakDefinition:
371 // FIXME: 'as' enforces that this is defined and global. The manual claims
372 // it has to be in a coalesced section, but this isn't enforced.
373 Symbol->setWeakDefinition();
374 break;
375
376 case MCSA_WeakDefAutoPrivate:
377 Symbol->setWeakDefinition();
378 Symbol->setWeakReference();
379 break;
380
381 case MCSA_Cold:
382 Symbol->setCold();
383 break;
384 }
385
386 return true;
387}
388
389void MCMachOStreamer::emitSymbolDesc(MCSymbol *Symbol, unsigned DescValue) {
390 // Encode the 'desc' value into the lowest implementation defined bits.
391 getAssembler().registerSymbol(Symbol: *Symbol);
392 cast<MCSymbolMachO>(Val: Symbol)->setDesc(DescValue);
393}
394
395void MCMachOStreamer::emitCommonSymbol(MCSymbol *Symbol, uint64_t Size,
396 Align ByteAlignment) {
397 // FIXME: Darwin 'as' does appear to allow redef of a .comm by itself.
398 assert(Symbol->isUndefined() && "Cannot define a symbol twice!");
399
400 getAssembler().registerSymbol(Symbol: *Symbol);
401 Symbol->setExternal(true);
402 Symbol->setCommon(Size, Alignment: ByteAlignment);
403}
404
405void MCMachOStreamer::emitLocalCommonSymbol(MCSymbol *Symbol, uint64_t Size,
406 Align ByteAlignment) {
407 // '.lcomm' is equivalent to '.zerofill'.
408 return emitZerofill(Section: getContext().getObjectFileInfo()->getDataBSSSection(),
409 Symbol, Size, ByteAlignment);
410}
411
412void MCMachOStreamer::emitZerofill(MCSection *Section, MCSymbol *Symbol,
413 uint64_t Size, Align ByteAlignment,
414 SMLoc Loc) {
415 // On darwin all virtual sections have zerofill type. Disallow the usage of
416 // .zerofill in non-virtual functions. If something similar is needed, use
417 // .space or .zero.
418 if (!Section->isVirtualSection()) {
419 getContext().reportError(
420 L: Loc, Msg: "The usage of .zerofill is restricted to sections of "
421 "ZEROFILL type. Use .zero or .space instead.");
422 return; // Early returning here shouldn't harm. EmitZeros should work on any
423 // section.
424 }
425
426 pushSection();
427 switchSection(Section);
428
429 // The symbol may not be present, which only creates the section.
430 if (Symbol) {
431 emitValueToAlignment(Alignment: ByteAlignment, Value: 0, ValueSize: 1, MaxBytesToEmit: 0);
432 emitLabel(Symbol);
433 emitZeros(NumBytes: Size);
434 }
435 popSection();
436}
437
438// This should always be called with the thread local bss section. Like the
439// .zerofill directive this doesn't actually switch sections on us.
440void MCMachOStreamer::emitTBSSSymbol(MCSection *Section, MCSymbol *Symbol,
441 uint64_t Size, Align ByteAlignment) {
442 emitZerofill(Section, Symbol, Size, ByteAlignment);
443}
444
445void MCMachOStreamer::emitInstToData(const MCInst &Inst,
446 const MCSubtargetInfo &STI) {
447 MCDataFragment *DF = getOrCreateDataFragment();
448
449 SmallVector<MCFixup, 4> Fixups;
450 SmallString<256> Code;
451 getAssembler().getEmitter().encodeInstruction(Inst, CB&: Code, Fixups, STI);
452
453 // Add the fixups and data.
454 for (MCFixup &Fixup : Fixups) {
455 Fixup.setOffset(Fixup.getOffset() + DF->getContents().size());
456 DF->getFixups().push_back(Elt: Fixup);
457 }
458 DF->setHasInstructions(STI);
459 DF->getContents().append(in_start: Code.begin(), in_end: Code.end());
460}
461
462void MCMachOStreamer::finishImpl() {
463 emitFrames(MAB: &getAssembler().getBackend());
464
465 // We have to set the fragment atom associations so we can relax properly for
466 // Mach-O.
467
468 // First, scan the symbol table to build a lookup table from fragments to
469 // defining symbols.
470 DenseMap<const MCFragment *, const MCSymbol *> DefiningSymbolMap;
471 for (const MCSymbol &Symbol : getAssembler().symbols()) {
472 auto &Sym = cast<MCSymbolMachO>(Val: Symbol);
473 if (Sym.isSymbolLinkerVisible() && Sym.isInSection() && !Sym.isVariable() &&
474 !Sym.isAltEntry()) {
475 // An atom defining symbol should never be internal to a fragment.
476 assert(Symbol.getOffset() == 0 &&
477 "Invalid offset in atom defining symbol!");
478 DefiningSymbolMap[Symbol.getFragment()] = &Symbol;
479 }
480 }
481
482 // Set the fragment atom associations by tracking the last seen atom defining
483 // symbol.
484 for (MCSection &Sec : getAssembler()) {
485 cast<MCSectionMachO>(Val&: Sec).allocAtoms();
486 const MCSymbol *CurrentAtom = nullptr;
487 size_t I = 0;
488 for (MCFragment &Frag : Sec) {
489 if (const MCSymbol *Symbol = DefiningSymbolMap.lookup(Val: &Frag))
490 CurrentAtom = Symbol;
491 cast<MCSectionMachO>(Val&: Sec).setAtom(I: I++, Sym: CurrentAtom);
492 }
493 }
494
495 finalizeCGProfile();
496
497 createAddrSigSection();
498 this->MCObjectStreamer::finishImpl();
499}
500
501void MCMachOStreamer::finalizeCGProfileEntry(const MCSymbolRefExpr *&SRE) {
502 const MCSymbol *S = &SRE->getSymbol();
503 if (getAssembler().registerSymbol(Symbol: *S))
504 S->setExternal(true);
505}
506
507void MCMachOStreamer::finalizeCGProfile() {
508 MCAssembler &Asm = getAssembler();
509 MCObjectWriter &W = getWriter();
510 if (W.getCGProfile().empty())
511 return;
512 for (auto &E : W.getCGProfile()) {
513 finalizeCGProfileEntry(SRE&: E.From);
514 finalizeCGProfileEntry(SRE&: E.To);
515 }
516 // We can't write the section out until symbol indices are finalized which
517 // doesn't happen until after section layout. We need to create the section
518 // and set its size now so that it's accounted for in layout.
519 MCSection *CGProfileSection = Asm.getContext().getMachOSection(
520 Segment: "__LLVM", Section: "__cg_profile", TypeAndAttributes: 0, K: SectionKind::getMetadata());
521 changeSection(Section: CGProfileSection);
522 // For each entry, reserve space for 2 32-bit indices and a 64-bit count.
523 size_t SectionBytes =
524 W.getCGProfile().size() * (2 * sizeof(uint32_t) + sizeof(uint64_t));
525 cast<MCDataFragment>(Val&: *CGProfileSection->begin())
526 .getContents()
527 .resize(N: SectionBytes);
528}
529
530MCStreamer *llvm::createMachOStreamer(MCContext &Context,
531 std::unique_ptr<MCAsmBackend> &&MAB,
532 std::unique_ptr<MCObjectWriter> &&OW,
533 std::unique_ptr<MCCodeEmitter> &&CE,
534 bool DWARFMustBeAtTheEnd,
535 bool LabelSections) {
536 MCMachOStreamer *S = new MCMachOStreamer(
537 Context, std::move(MAB), std::move(OW), std::move(CE), LabelSections);
538 const Triple &Target = Context.getTargetTriple();
539 S->emitVersionForTarget(
540 Target, SDKVersion: Context.getObjectFileInfo()->getSDKVersion(),
541 DarwinTargetVariantTriple: Context.getObjectFileInfo()->getDarwinTargetVariantTriple(),
542 DarwinTargetVariantSDKVersion: Context.getObjectFileInfo()->getDarwinTargetVariantSDKVersion());
543 return S;
544}
545
546// The AddrSig section uses a series of relocations to refer to the symbols that
547// should be considered address-significant. The only interesting content of
548// these relocations is their symbol; the type, length etc will be ignored by
549// the linker. The reason we are not referring to the symbol indices directly is
550// that those indices will be invalidated by tools that update the symbol table.
551// Symbol relocations OTOH will have their indices updated by e.g. llvm-strip.
552void MCMachOStreamer::createAddrSigSection() {
553 MCAssembler &Asm = getAssembler();
554 MCObjectWriter &writer = Asm.getWriter();
555 if (!writer.getEmitAddrsigSection())
556 return;
557 // Create the AddrSig section and first data fragment here as its layout needs
558 // to be computed immediately after in order for it to be exported correctly.
559 MCSection *AddrSigSection =
560 Asm.getContext().getObjectFileInfo()->getAddrSigSection();
561 changeSection(Section: AddrSigSection);
562 auto *Frag = cast<MCDataFragment>(Val: AddrSigSection->curFragList()->Head);
563 // We will generate a series of pointer-sized symbol relocations at offset
564 // 0x0. Set the section size to be large enough to contain a single pointer
565 // (instead of emitting a zero-sized section) so these relocations are
566 // technically valid, even though we don't expect these relocations to
567 // actually be applied by the linker.
568 Frag->getContents().resize(N: 8);
569}
570