1 //===-- lib/MC/XCOFFObjectWriter.cpp - XCOFF file writer ------------------===//
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 // This file implements XCOFF object file writer information.
10 //
11 //===----------------------------------------------------------------------===//
12 
13 #include "llvm/BinaryFormat/XCOFF.h"
14 #include "llvm/MC/MCAsmBackend.h"
15 #include "llvm/MC/MCAsmLayout.h"
16 #include "llvm/MC/MCAssembler.h"
17 #include "llvm/MC/MCFixup.h"
18 #include "llvm/MC/MCFixupKindInfo.h"
19 #include "llvm/MC/MCObjectWriter.h"
20 #include "llvm/MC/MCSectionXCOFF.h"
21 #include "llvm/MC/MCSymbolXCOFF.h"
22 #include "llvm/MC/MCValue.h"
23 #include "llvm/MC/MCXCOFFObjectWriter.h"
24 #include "llvm/MC/StringTableBuilder.h"
25 #include "llvm/Support/Casting.h"
26 #include "llvm/Support/EndianStream.h"
27 #include "llvm/Support/ErrorHandling.h"
28 #include "llvm/Support/MathExtras.h"
29 
30 #include <deque>
31 
32 using namespace llvm;
33 
34 // An XCOFF object file has a limited set of predefined sections. The most
35 // important ones for us (right now) are:
36 // .text --> contains program code and read-only data.
37 // .data --> contains initialized data, function descriptors, and the TOC.
38 // .bss  --> contains uninitialized data.
39 // Each of these sections is composed of 'Control Sections'. A Control Section
40 // is more commonly referred to as a csect. A csect is an indivisible unit of
41 // code or data, and acts as a container for symbols. A csect is mapped
42 // into a section based on its storage-mapping class, with the exception of
43 // XMC_RW which gets mapped to either .data or .bss based on whether it's
44 // explicitly initialized or not.
45 //
46 // We don't represent the sections in the MC layer as there is nothing
47 // interesting about them at at that level: they carry information that is
48 // only relevant to the ObjectWriter, so we materialize them in this class.
49 namespace {
50 
51 constexpr unsigned DefaultSectionAlign = 4;
52 constexpr int16_t MaxSectionIndex = INT16_MAX;
53 
54 // Packs the csect's alignment and type into a byte.
55 uint8_t getEncodedType(const MCSectionXCOFF *);
56 
57 struct XCOFFRelocation {
58   uint32_t SymbolTableIndex;
59   uint32_t FixupOffsetInCsect;
60   uint8_t SignAndSize;
61   uint8_t Type;
62 };
63 
64 // Wrapper around an MCSymbolXCOFF.
65 struct Symbol {
66   const MCSymbolXCOFF *const MCSym;
67   uint32_t SymbolTableIndex;
68 
69   XCOFF::StorageClass getStorageClass() const {
70     return MCSym->getStorageClass();
71   }
72   StringRef getSymbolTableName() const { return MCSym->getSymbolTableName(); }
73   Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {}
74 };
75 
76 // Wrapper for an MCSectionXCOFF.
77 // It can be a Csect or debug section or DWARF section and so on.
78 struct XCOFFSection {
79   const MCSectionXCOFF *const MCSec;
80   uint32_t SymbolTableIndex;
81   uint64_t Address;
82   uint64_t Size;
83 
84   SmallVector<Symbol, 1> Syms;
85   SmallVector<XCOFFRelocation, 1> Relocations;
86   StringRef getSymbolTableName() const { return MCSec->getSymbolTableName(); }
87   XCOFFSection(const MCSectionXCOFF *MCSec)
88       : MCSec(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
89 };
90 
91 // Type to be used for a container representing a set of csects with
92 // (approximately) the same storage mapping class. For example all the csects
93 // with a storage mapping class of `xmc_pr` will get placed into the same
94 // container.
95 using CsectGroup = std::deque<XCOFFSection>;
96 using CsectGroups = std::deque<CsectGroup *>;
97 
98 // The basic section entry defination. This Section represents a section entry
99 // in XCOFF section header table.
100 struct SectionEntry {
101   char Name[XCOFF::NameSize];
102   // The physical/virtual address of the section. For an object file
103   // these values are equivalent.
104   uint64_t Address;
105   uint64_t Size;
106   uint64_t FileOffsetToData;
107   uint64_t FileOffsetToRelocations;
108   uint32_t RelocationCount;
109   int32_t Flags;
110 
111   int16_t Index;
112 
113   // XCOFF has special section numbers for symbols:
114   // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
115   // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
116   // relocatable.
117   //  0 Specifies N_UNDEF, an undefined external symbol.
118   // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
119   // hasn't been initialized.
120   static constexpr int16_t UninitializedIndex =
121       XCOFF::ReservedSectionNum::N_DEBUG - 1;
122 
123   SectionEntry(StringRef N, int32_t Flags)
124       : Name(), Address(0), Size(0), FileOffsetToData(0),
125         FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags),
126         Index(UninitializedIndex) {
127     assert(N.size() <= XCOFF::NameSize && "section name too long");
128     memcpy(Name, N.data(), N.size());
129   }
130 
131   virtual void reset() {
132     Address = 0;
133     Size = 0;
134     FileOffsetToData = 0;
135     FileOffsetToRelocations = 0;
136     RelocationCount = 0;
137     Index = UninitializedIndex;
138   }
139 
140   virtual ~SectionEntry() = default;
141 };
142 
143 // Represents the data related to a section excluding the csects that make up
144 // the raw data of the section. The csects are stored separately as not all
145 // sections contain csects, and some sections contain csects which are better
146 // stored separately, e.g. the .data section containing read-write, descriptor,
147 // TOCBase and TOC-entry csects.
148 struct CsectSectionEntry : public SectionEntry {
149   // Virtual sections do not need storage allocated in the object file.
150   const bool IsVirtual;
151 
152   // This is a section containing csect groups.
153   CsectGroups Groups;
154 
155   CsectSectionEntry(StringRef N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
156                     CsectGroups Groups)
157       : SectionEntry(N, Flags), IsVirtual(IsVirtual), Groups(Groups) {
158     assert(N.size() <= XCOFF::NameSize && "section name too long");
159     memcpy(Name, N.data(), N.size());
160   }
161 
162   void reset() override {
163     SectionEntry::reset();
164     // Clear any csects we have stored.
165     for (auto *Group : Groups)
166       Group->clear();
167   }
168 
169   virtual ~CsectSectionEntry() = default;
170 };
171 
172 struct DwarfSectionEntry : public SectionEntry {
173   // For DWARF section entry.
174   std::unique_ptr<XCOFFSection> DwarfSect;
175 
176   DwarfSectionEntry(StringRef N, int32_t Flags,
177                     std::unique_ptr<XCOFFSection> Sect)
178       : SectionEntry(N, Flags | XCOFF::STYP_DWARF), DwarfSect(std::move(Sect)) {
179     assert(DwarfSect->MCSec->isDwarfSect() &&
180            "This should be a DWARF section!");
181     assert(N.size() <= XCOFF::NameSize && "section name too long");
182     memcpy(Name, N.data(), N.size());
183   }
184 
185   DwarfSectionEntry(DwarfSectionEntry &&s) = default;
186 
187   virtual ~DwarfSectionEntry() = default;
188 };
189 
190 class XCOFFObjectWriter : public MCObjectWriter {
191 
192   uint32_t SymbolTableEntryCount = 0;
193   uint64_t SymbolTableOffset = 0;
194   uint16_t SectionCount = 0;
195   uint64_t RelocationEntryOffset = 0;
196 
197   support::endian::Writer W;
198   std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
199   StringTableBuilder Strings;
200 
201   const uint64_t MaxRawDataSize =
202       TargetObjectWriter->is64Bit() ? UINT64_MAX : UINT32_MAX;
203 
204   // Maps the MCSection representation to its corresponding XCOFFSection
205   // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into
206   // from its containing MCSectionXCOFF.
207   DenseMap<const MCSectionXCOFF *, XCOFFSection *> SectionMap;
208 
209   // Maps the MCSymbol representation to its corrresponding symbol table index.
210   // Needed for relocation.
211   DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap;
212 
213   // CsectGroups. These store the csects which make up different parts of
214   // the sections. Should have one for each set of csects that get mapped into
215   // the same section and get handled in a 'similar' way.
216   CsectGroup UndefinedCsects;
217   CsectGroup ProgramCodeCsects;
218   CsectGroup ReadOnlyCsects;
219   CsectGroup DataCsects;
220   CsectGroup FuncDSCsects;
221   CsectGroup TOCCsects;
222   CsectGroup BSSCsects;
223   CsectGroup TDataCsects;
224   CsectGroup TBSSCsects;
225 
226   // The Predefined sections.
227   CsectSectionEntry Text;
228   CsectSectionEntry Data;
229   CsectSectionEntry BSS;
230   CsectSectionEntry TData;
231   CsectSectionEntry TBSS;
232 
233   // All the XCOFF sections, in the order they will appear in the section header
234   // table.
235   std::array<CsectSectionEntry *const, 5> Sections{
236       {&Text, &Data, &BSS, &TData, &TBSS}};
237 
238   std::vector<DwarfSectionEntry> DwarfSections;
239 
240   CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
241 
242   virtual void reset() override;
243 
244   void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override;
245 
246   void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *,
247                         const MCFixup &, MCValue, uint64_t &) override;
248 
249   uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override;
250 
251   bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
252   static bool nameShouldBeInStringTable(const StringRef &);
253   void writeSymbolName(const StringRef &);
254 
255   void writeSymbolEntryForCsectMemberLabel(const Symbol &SymbolRef,
256                                            const XCOFFSection &CSectionRef,
257                                            int16_t SectionIndex,
258                                            uint64_t SymbolOffset);
259   void writeSymbolEntryForControlSection(const XCOFFSection &CSectionRef,
260                                          int16_t SectionIndex,
261                                          XCOFF::StorageClass StorageClass);
262   void writeSymbolEntryForDwarfSection(const XCOFFSection &DwarfSectionRef,
263                                        int16_t SectionIndex);
264   void writeFileHeader();
265   void writeSectionHeaderTable();
266   void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
267   void writeSectionForControlSectionEntry(const MCAssembler &Asm,
268                                           const MCAsmLayout &Layout,
269                                           const CsectSectionEntry &CsectEntry,
270                                           uint32_t &CurrentAddressLocation);
271   void writeSectionForDwarfSectionEntry(const MCAssembler &Asm,
272                                         const MCAsmLayout &Layout,
273                                         const DwarfSectionEntry &DwarfEntry,
274                                         uint32_t &CurrentAddressLocation);
275   void writeSymbolTable(const MCAsmLayout &Layout);
276   void writeSymbolAuxDwarfEntry(uint32_t LengthOfSectionPortion,
277                                 uint32_t NumberOfRelocEnt = 0);
278   void writeSymbolAuxCsectEntry(uint32_t SectionOrLength,
279                                 uint8_t SymbolAlignmentAndType,
280                                 uint8_t StorageMappingClass);
281   void writeSymbolEntry(StringRef SymbolName, uint32_t Value,
282                         int16_t SectionNumber, uint16_t SymbolType,
283                         uint8_t StorageClass, uint8_t NumberOfAuxEntries = 1);
284   void writeRelocations();
285   void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section);
286 
287   // Called after all the csects and symbols have been processed by
288   // `executePostLayoutBinding`, this function handles building up the majority
289   // of the structures in the object file representation. Namely:
290   // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
291   //    sizes.
292   // *) Assigns symbol table indices.
293   // *) Builds up the section header table by adding any non-empty sections to
294   //    `Sections`.
295   void assignAddressesAndIndices(const MCAsmLayout &);
296   void finalizeSectionInfo();
297 
298   // TODO aux header support not implemented.
299   bool needsAuxiliaryHeader() const { return false; }
300 
301   // Returns the size of the auxiliary header to be written to the object file.
302   size_t auxiliaryHeaderSize() const {
303     assert(!needsAuxiliaryHeader() &&
304            "Auxiliary header support not implemented.");
305     return 0;
306   }
307 
308 public:
309   XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
310                     raw_pwrite_stream &OS);
311 
312   void writeWord(uint64_t Word) {
313     is64Bit() ? W.write<uint64_t>(Word) : W.write<uint32_t>(Word);
314   }
315 };
316 
317 XCOFFObjectWriter::XCOFFObjectWriter(
318     std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
319     : W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
320       Strings(StringTableBuilder::XCOFF),
321       Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
322            CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
323       Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false,
324            CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
325       BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
326           CsectGroups{&BSSCsects}),
327       TData(".tdata", XCOFF::STYP_TDATA, /* IsVirtual */ false,
328             CsectGroups{&TDataCsects}),
329       TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true,
330            CsectGroups{&TBSSCsects}) {}
331 
332 void XCOFFObjectWriter::reset() {
333   // Clear the mappings we created.
334   SymbolIndexMap.clear();
335   SectionMap.clear();
336 
337   UndefinedCsects.clear();
338   // Reset any sections we have written to, and empty the section header table.
339   for (auto *Sec : Sections)
340     Sec->reset();
341   for (auto &DwarfSec : DwarfSections)
342     DwarfSec.reset();
343 
344   // Reset states in XCOFFObjectWriter.
345   SymbolTableEntryCount = 0;
346   SymbolTableOffset = 0;
347   SectionCount = 0;
348   RelocationEntryOffset = 0;
349   Strings.clear();
350 
351   MCObjectWriter::reset();
352 }
353 
354 CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
355   switch (MCSec->getMappingClass()) {
356   case XCOFF::XMC_PR:
357     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
358            "Only an initialized csect can contain program code.");
359     return ProgramCodeCsects;
360   case XCOFF::XMC_RO:
361     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
362            "Only an initialized csect can contain read only data.");
363     return ReadOnlyCsects;
364   case XCOFF::XMC_RW:
365     if (XCOFF::XTY_CM == MCSec->getCSectType())
366       return BSSCsects;
367 
368     if (XCOFF::XTY_SD == MCSec->getCSectType())
369       return DataCsects;
370 
371     report_fatal_error("Unhandled mapping of read-write csect to section.");
372   case XCOFF::XMC_DS:
373     return FuncDSCsects;
374   case XCOFF::XMC_BS:
375     assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
376            "Mapping invalid csect. CSECT with bss storage class must be "
377            "common type.");
378     return BSSCsects;
379   case XCOFF::XMC_TL:
380     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
381            "Mapping invalid csect. CSECT with tdata storage class must be "
382            "an initialized csect.");
383     return TDataCsects;
384   case XCOFF::XMC_UL:
385     assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
386            "Mapping invalid csect. CSECT with tbss storage class must be "
387            "an uninitialized csect.");
388     return TBSSCsects;
389   case XCOFF::XMC_TC0:
390     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
391            "Only an initialized csect can contain TOC-base.");
392     assert(TOCCsects.empty() &&
393            "We should have only one TOC-base, and it should be the first csect "
394            "in this CsectGroup.");
395     return TOCCsects;
396   case XCOFF::XMC_TC:
397   case XCOFF::XMC_TE:
398     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
399            "Only an initialized csect can contain TC entry.");
400     assert(!TOCCsects.empty() &&
401            "We should at least have a TOC-base in this CsectGroup.");
402     return TOCCsects;
403   case XCOFF::XMC_TD:
404     report_fatal_error("toc-data not yet supported when writing object files.");
405   default:
406     report_fatal_error("Unhandled mapping of csect to section.");
407   }
408 }
409 
410 static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) {
411   if (XSym->isDefined())
412     return cast<MCSectionXCOFF>(XSym->getFragment()->getParent());
413   return XSym->getRepresentedCsect();
414 }
415 
416 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
417                                                  const MCAsmLayout &Layout) {
418   for (const auto &S : Asm) {
419     const auto *MCSec = cast<const MCSectionXCOFF>(&S);
420     assert(SectionMap.find(MCSec) == SectionMap.end() &&
421            "Cannot add a section twice.");
422 
423     // If the name does not fit in the storage provided in the symbol table
424     // entry, add it to the string table.
425     if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
426       Strings.add(MCSec->getSymbolTableName());
427     if (MCSec->isCsect()) {
428       // A new control section. Its CsectSectionEntry should already be staticly
429       // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of
430       // the CsectSectionEntry.
431       assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
432              "An undefined csect should not get registered.");
433       CsectGroup &Group = getCsectGroup(MCSec);
434       Group.emplace_back(MCSec);
435       SectionMap[MCSec] = &Group.back();
436     } else if (MCSec->isDwarfSect()) {
437       // A new DwarfSectionEntry.
438       std::unique_ptr<XCOFFSection> DwarfSec =
439           std::make_unique<XCOFFSection>(MCSec);
440       SectionMap[MCSec] = DwarfSec.get();
441 
442       DwarfSectionEntry SecEntry(MCSec->getName(),
443                                  MCSec->getDwarfSubtypeFlags().getValue(),
444                                  std::move(DwarfSec));
445       DwarfSections.push_back(std::move(SecEntry));
446     } else
447       llvm_unreachable("unsupport section type!");
448   }
449 
450   for (const MCSymbol &S : Asm.symbols()) {
451     // Nothing to do for temporary symbols.
452     if (S.isTemporary())
453       continue;
454 
455     const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
456     const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym);
457 
458     if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
459       // Handle undefined symbol.
460       UndefinedCsects.emplace_back(ContainingCsect);
461       SectionMap[ContainingCsect] = &UndefinedCsects.back();
462       if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName()))
463         Strings.add(ContainingCsect->getSymbolTableName());
464       continue;
465     }
466 
467     // If the symbol is the csect itself, we don't need to put the symbol
468     // into csect's Syms.
469     if (XSym == ContainingCsect->getQualNameSymbol())
470       continue;
471 
472     // Only put a label into the symbol table when it is an external label.
473     if (!XSym->isExternal())
474       continue;
475 
476     assert(SectionMap.find(ContainingCsect) != SectionMap.end() &&
477            "Expected containing csect to exist in map");
478     XCOFFSection *Csect = SectionMap[ContainingCsect];
479     // Lookup the containing csect and add the symbol to it.
480     assert(Csect->MCSec->isCsect() && "only csect is supported now!");
481     Csect->Syms.emplace_back(XSym);
482 
483     // If the name does not fit in the storage provided in the symbol table
484     // entry, add it to the string table.
485     if (nameShouldBeInStringTable(XSym->getSymbolTableName()))
486       Strings.add(XSym->getSymbolTableName());
487   }
488 
489   Strings.finalize();
490   assignAddressesAndIndices(Layout);
491 }
492 
493 void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
494                                          const MCAsmLayout &Layout,
495                                          const MCFragment *Fragment,
496                                          const MCFixup &Fixup, MCValue Target,
497                                          uint64_t &FixedValue) {
498   auto getIndex = [this](const MCSymbol *Sym,
499                          const MCSectionXCOFF *ContainingCsect) {
500     // If we could not find the symbol directly in SymbolIndexMap, this symbol
501     // could either be a temporary symbol or an undefined symbol. In this case,
502     // we would need to have the relocation reference its csect instead.
503     return SymbolIndexMap.find(Sym) != SymbolIndexMap.end()
504                ? SymbolIndexMap[Sym]
505                : SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
506   };
507 
508   auto getVirtualAddress =
509       [this, &Layout](const MCSymbol *Sym,
510                       const MCSectionXCOFF *ContainingSect) -> uint64_t {
511     // A DWARF section.
512     if (ContainingSect->isDwarfSect())
513       return Layout.getSymbolOffset(*Sym);
514 
515     // A csect.
516     if (!Sym->isDefined())
517       return SectionMap[ContainingSect]->Address;
518 
519     // A label.
520     assert(Sym->isDefined() && "not a valid object that has address!");
521     return SectionMap[ContainingSect]->Address + Layout.getSymbolOffset(*Sym);
522   };
523 
524   const MCSymbol *const SymA = &Target.getSymA()->getSymbol();
525 
526   MCAsmBackend &Backend = Asm.getBackend();
527   bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
528                  MCFixupKindInfo::FKF_IsPCRel;
529 
530   uint8_t Type;
531   uint8_t SignAndSize;
532   std::tie(Type, SignAndSize) =
533       TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel);
534 
535   const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
536 
537   if (SymASec->isCsect() && SymASec->getMappingClass() == XCOFF::XMC_TD)
538     report_fatal_error("toc-data not yet supported when writing object files.");
539 
540   assert(SectionMap.find(SymASec) != SectionMap.end() &&
541          "Expected containing csect to exist in map.");
542 
543   const uint32_t Index = getIndex(SymA, SymASec);
544   if (Type == XCOFF::RelocationType::R_POS ||
545       Type == XCOFF::RelocationType::R_TLS)
546     // The FixedValue should be symbol's virtual address in this object file
547     // plus any constant value that we might get.
548     FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
549   else if (Type == XCOFF::RelocationType::R_TLSM)
550     // The FixedValue should always be zero since the region handle is only
551     // known at load time.
552     FixedValue = 0;
553   else if (Type == XCOFF::RelocationType::R_TOC ||
554            Type == XCOFF::RelocationType::R_TOCL) {
555     // The FixedValue should be the TOC entry offset from the TOC-base plus any
556     // constant offset value.
557     const int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
558                                    TOCCsects.front().Address +
559                                    Target.getConstant();
560     if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset))
561       report_fatal_error("TOCEntryOffset overflows in small code model mode");
562 
563     FixedValue = TOCEntryOffset;
564   }
565 
566   assert((Fixup.getOffset() <=
567           MaxRawDataSize - Layout.getFragmentOffset(Fragment)) &&
568          "Fragment offset + fixup offset is overflowed.");
569   uint32_t FixupOffsetInCsect =
570       Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
571 
572   XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
573   MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent());
574   assert(SectionMap.find(RelocationSec) != SectionMap.end() &&
575          "Expected containing csect to exist in map.");
576   SectionMap[RelocationSec]->Relocations.push_back(Reloc);
577 
578   if (!Target.getSymB())
579     return;
580 
581   const MCSymbol *const SymB = &Target.getSymB()->getSymbol();
582   if (SymA == SymB)
583     report_fatal_error("relocation for opposite term is not yet supported");
584 
585   const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
586   assert(SectionMap.find(SymBSec) != SectionMap.end() &&
587          "Expected containing csect to exist in map.");
588   if (SymASec == SymBSec)
589     report_fatal_error(
590         "relocation for paired relocatable term is not yet supported");
591 
592   assert(Type == XCOFF::RelocationType::R_POS &&
593          "SymA must be R_POS here if it's not opposite term or paired "
594          "relocatable term.");
595   const uint32_t IndexB = getIndex(SymB, SymBSec);
596   // SymB must be R_NEG here, given the general form of Target(MCValue) is
597   // "SymbolA - SymbolB + imm64".
598   const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
599   XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
600   SectionMap[RelocationSec]->Relocations.push_back(RelocB);
601   // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
602   // now we just need to fold "- SymbolB" here.
603   FixedValue -= getVirtualAddress(SymB, SymBSec);
604 }
605 
606 void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
607                                       const MCAsmLayout &Layout) {
608   assert(!is64Bit() && "Writing 64-bit sections is not yet supported.");
609   uint32_t CurrentAddressLocation = 0;
610   for (const auto *Section : Sections)
611     writeSectionForControlSectionEntry(Asm, Layout, *Section,
612                                        CurrentAddressLocation);
613   for (const auto &DwarfSection : DwarfSections)
614     writeSectionForDwarfSectionEntry(Asm, Layout, DwarfSection,
615                                      CurrentAddressLocation);
616 }
617 
618 uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
619                                         const MCAsmLayout &Layout) {
620   // We always emit a timestamp of 0 for reproducibility, so ensure incremental
621   // linking is not enabled, in case, like with Windows COFF, such a timestamp
622   // is incompatible with incremental linking of XCOFF.
623   if (Asm.isIncrementalLinkerCompatible())
624     report_fatal_error("Incremental linking not supported for XCOFF.");
625 
626   finalizeSectionInfo();
627   uint64_t StartOffset = W.OS.tell();
628 
629   writeFileHeader();
630   writeSectionHeaderTable();
631 
632   if (!is64Bit()) {
633     writeSections(Asm, Layout);
634     writeRelocations();
635 
636     writeSymbolTable(Layout);
637     // Write the string table.
638     Strings.write(W.OS);
639   }
640 
641   return W.OS.tell() - StartOffset;
642 }
643 
644 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
645   return SymbolName.size() > XCOFF::NameSize;
646 }
647 
648 void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) {
649   // Magic, Offset or SymbolName.
650   if (nameShouldBeInStringTable(SymbolName)) {
651     W.write<int32_t>(0);
652     W.write<uint32_t>(Strings.getOffset(SymbolName));
653   } else {
654     char Name[XCOFF::NameSize + 1];
655     std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
656     ArrayRef<char> NameRef(Name, XCOFF::NameSize);
657     W.write(NameRef);
658   }
659 }
660 
661 void XCOFFObjectWriter::writeSymbolEntry(StringRef SymbolName, uint32_t Value,
662                                          int16_t SectionNumber,
663                                          uint16_t SymbolType,
664                                          uint8_t StorageClass,
665                                          uint8_t NumberOfAuxEntries) {
666   writeSymbolName(SymbolName);
667   W.write<uint32_t>(Value);
668   W.write<int16_t>(SectionNumber);
669   // Basic/Derived type. See the description of the n_type field for symbol
670   // table entries for a detailed description. Since we don't yet support
671   // visibility, and all other bits are either optionally set or reserved, this
672   // is always zero.
673   // TODO FIXME How to assert a symbol's visibilty is default?
674   // TODO Set the function indicator (bit 10, 0x0020) for functions
675   // when debugging is enabled.
676   W.write<uint16_t>(SymbolType);
677   W.write<uint8_t>(StorageClass);
678   W.write<uint8_t>(NumberOfAuxEntries);
679 }
680 
681 void XCOFFObjectWriter::writeSymbolAuxCsectEntry(uint32_t SectionOrLength,
682                                                  uint8_t SymbolAlignmentAndType,
683                                                  uint8_t StorageMappingClass) {
684   W.write<uint32_t>(SectionOrLength);
685   W.write<uint32_t>(0); // ParameterHashIndex
686   W.write<uint16_t>(0); // TypeChkSectNum
687   W.write<uint8_t>(SymbolAlignmentAndType);
688   W.write<uint8_t>(StorageMappingClass);
689   W.write<uint32_t>(0); // StabInfoIndex
690   W.write<uint16_t>(0); // StabSectNum
691 }
692 
693 void XCOFFObjectWriter::writeSymbolAuxDwarfEntry(
694     uint32_t LengthOfSectionPortion, uint32_t NumberOfRelocEnt) {
695   W.write<uint32_t>(LengthOfSectionPortion);
696   W.OS.write_zeros(4); // Reserved
697   W.write<uint32_t>(NumberOfRelocEnt);
698   W.OS.write_zeros(6); // Reserved
699 }
700 
701 void XCOFFObjectWriter::writeSymbolEntryForCsectMemberLabel(
702     const Symbol &SymbolRef, const XCOFFSection &CSectionRef,
703     int16_t SectionIndex, uint64_t SymbolOffset) {
704   assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address &&
705          "Symbol address overflowed.");
706 
707   writeSymbolEntry(SymbolRef.getSymbolTableName(),
708                    CSectionRef.Address + SymbolOffset, SectionIndex,
709                    /*SymbolType=*/0, SymbolRef.getStorageClass());
710 
711   writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex, XCOFF::XTY_LD,
712                            CSectionRef.MCSec->getMappingClass());
713 }
714 
715 void XCOFFObjectWriter::writeSymbolEntryForDwarfSection(
716     const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) {
717   assert(DwarfSectionRef.MCSec->isDwarfSect() && "Not a DWARF section!");
718 
719   writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), /*Value=*/0,
720                    SectionIndex, /*SymbolType=*/0, XCOFF::C_DWARF);
721 
722   writeSymbolAuxDwarfEntry(DwarfSectionRef.Size);
723 }
724 
725 void XCOFFObjectWriter::writeSymbolEntryForControlSection(
726     const XCOFFSection &CSectionRef, int16_t SectionIndex,
727     XCOFF::StorageClass StorageClass) {
728   writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address,
729                    SectionIndex, /*SymbolType=*/0, StorageClass);
730 
731   writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec),
732                            CSectionRef.MCSec->getMappingClass());
733 }
734 
735 void XCOFFObjectWriter::writeFileHeader() {
736   W.write<uint16_t>(is64Bit() ? XCOFF::XCOFF64 : XCOFF::XCOFF32);
737   W.write<uint16_t>(SectionCount);
738   W.write<int32_t>(0); // TimeStamp
739   writeWord(SymbolTableOffset);
740   if (is64Bit()) {
741     W.write<uint16_t>(0); // AuxHeaderSize. No optional header for an object
742                           // file that is not to be loaded.
743     W.write<uint16_t>(0); // Flags
744     W.write<int32_t>(0);  // SymbolTableEntryCount. Not supported yet.
745   } else {
746     W.write<int32_t>(SymbolTableEntryCount);
747     W.write<uint16_t>(0); // AuxHeaderSize. No optional header for an object
748                           // file that is not to be loaded.
749     W.write<uint16_t>(0); // Flags
750   }
751 }
752 
753 void XCOFFObjectWriter::writeSectionHeaderTable() {
754   auto writeSectionHeader = [&](const SectionEntry *Sec, bool IsDwarf) {
755     // Nothing to write for this Section.
756     if (Sec->Index == SectionEntry::UninitializedIndex)
757       return false;
758 
759     // Write Name.
760     ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
761     W.write(NameRef);
762 
763     // Write the Physical Address and Virtual Address. In an object file these
764     // are the same.
765     // We use 0 for DWARF sections' Physical and Virtual Addresses.
766     writeWord(IsDwarf ? 0 : Sec->Address);
767     writeWord(IsDwarf ? 0 : Sec->Address);
768 
769     writeWord(Sec->Size);
770     writeWord(Sec->FileOffsetToData);
771     writeWord(Sec->FileOffsetToRelocations);
772     writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet.
773 
774     if (is64Bit()) {
775       W.write<uint32_t>(0); // NumberOfRelocations. Not yet supported in 64-bit.
776       W.write<uint32_t>(0); // NumberOfLineNumbers. Not supported yet.
777       W.write<int32_t>(Sec->Flags);
778       W.OS.write_zeros(4);
779     } else {
780       W.write<uint16_t>(Sec->RelocationCount);
781       W.write<uint16_t>(0); // NumberOfLineNumbers. Not supported yet.
782       W.write<int32_t>(Sec->Flags);
783     }
784 
785     return true;
786   };
787 
788   for (const auto *CsectSec : Sections)
789     writeSectionHeader(CsectSec, /* IsDwarf */ false);
790   for (const auto &DwarfSec : DwarfSections)
791     writeSectionHeader(&DwarfSec, /* IsDwarf */ true);
792 }
793 
794 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
795                                         const XCOFFSection &Section) {
796   assert(!is64Bit() && "Writing 64-bit relocation is not yet supported.");
797   if (Section.MCSec->isCsect())
798     W.write<uint32_t>(Section.Address + Reloc.FixupOffsetInCsect);
799   else {
800     // DWARF sections' address is set to 0.
801     assert(Section.MCSec->isDwarfSect() && "unsupport section type!");
802     W.write<uint32_t>(Reloc.FixupOffsetInCsect);
803   }
804   W.write<uint32_t>(Reloc.SymbolTableIndex);
805   W.write<uint8_t>(Reloc.SignAndSize);
806   W.write<uint8_t>(Reloc.Type);
807 }
808 
809 void XCOFFObjectWriter::writeRelocations() {
810   for (const auto *Section : Sections) {
811     if (Section->Index == SectionEntry::UninitializedIndex)
812       // Nothing to write for this Section.
813       continue;
814 
815     for (const auto *Group : Section->Groups) {
816       if (Group->empty())
817         continue;
818 
819       for (const auto &Csect : *Group) {
820         for (const auto Reloc : Csect.Relocations)
821           writeRelocation(Reloc, Csect);
822       }
823     }
824   }
825 
826   for (const auto &DwarfSection : DwarfSections)
827     for (const auto &Reloc : DwarfSection.DwarfSect->Relocations)
828       writeRelocation(Reloc, *DwarfSection.DwarfSect);
829 }
830 
831 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
832   assert(!is64Bit() && "Writing 64-bit symbol table is not yet supported.");
833   // Write symbol 0 as C_FILE.
834   // FIXME: support 64-bit C_FILE symbol.
835   // The n_name of a C_FILE symbol is the source file's name when no auxiliary
836   // entries are present. The source file's name is alternatively provided by an
837   // auxiliary entry, in which case the n_name of the C_FILE symbol is `.file`.
838   // FIXME: add the real source file's name.
839   writeSymbolEntry(".file", /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG,
840                    /*SymbolType=*/0, XCOFF::C_FILE,
841                    /*NumberOfAuxEntries=*/0);
842 
843   for (const auto &Csect : UndefinedCsects) {
844     writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF,
845                                       Csect.MCSec->getStorageClass());
846   }
847 
848   for (const auto *Section : Sections) {
849     if (Section->Index == SectionEntry::UninitializedIndex)
850       // Nothing to write for this Section.
851       continue;
852 
853     for (const auto *Group : Section->Groups) {
854       if (Group->empty())
855         continue;
856 
857       const int16_t SectionIndex = Section->Index;
858       for (const auto &Csect : *Group) {
859         // Write out the control section first and then each symbol in it.
860         writeSymbolEntryForControlSection(Csect, SectionIndex,
861                                           Csect.MCSec->getStorageClass());
862 
863         for (const auto &Sym : Csect.Syms)
864           writeSymbolEntryForCsectMemberLabel(
865               Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
866       }
867     }
868   }
869 
870   for (const auto &DwarfSection : DwarfSections)
871     writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect,
872                                     DwarfSection.Index);
873 }
874 
875 void XCOFFObjectWriter::finalizeSectionInfo() {
876   for (auto *Section : Sections) {
877     if (Section->Index == SectionEntry::UninitializedIndex)
878       // Nothing to record for this Section.
879       continue;
880 
881     for (const auto *Group : Section->Groups) {
882       if (Group->empty())
883         continue;
884 
885       for (auto &Csect : *Group) {
886         const size_t CsectRelocCount = Csect.Relocations.size();
887         if (CsectRelocCount >= XCOFF::RelocOverflow ||
888             Section->RelocationCount >= XCOFF::RelocOverflow - CsectRelocCount)
889           report_fatal_error(
890               "relocation entries overflowed; overflow section is "
891               "not implemented yet");
892 
893         Section->RelocationCount += CsectRelocCount;
894       }
895     }
896   }
897 
898   for (auto &DwarfSection : DwarfSections)
899     DwarfSection.RelocationCount = DwarfSection.DwarfSect->Relocations.size();
900 
901   // Calculate the file offset to the relocation entries.
902   uint64_t RawPointer = RelocationEntryOffset;
903   auto calcOffsetToRelocations = [&](SectionEntry *Sec, bool IsDwarf) {
904     if (!IsDwarf && Sec->Index == SectionEntry::UninitializedIndex)
905       return false;
906 
907     if (!Sec->RelocationCount)
908       return false;
909 
910     Sec->FileOffsetToRelocations = RawPointer;
911     const uint32_t RelocationSizeInSec =
912         Sec->RelocationCount * XCOFF::RelocationSerializationSize32;
913     RawPointer += RelocationSizeInSec;
914     if (RawPointer > MaxRawDataSize)
915       report_fatal_error("Relocation data overflowed this object file.");
916 
917     return true;
918   };
919 
920   for (auto *Sec : Sections)
921     calcOffsetToRelocations(Sec, /* IsDwarf */ false);
922 
923   for (auto &DwarfSec : DwarfSections)
924     calcOffsetToRelocations(&DwarfSec, /* IsDwarf */ true);
925 
926   // TODO Error check that the number of symbol table entries fits in 32-bits
927   // signed ...
928   if (SymbolTableEntryCount)
929     SymbolTableOffset = RawPointer;
930 }
931 
932 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
933   // The first symbol table entry (at index 0) is for the file name.
934   uint32_t SymbolTableIndex = 1;
935 
936   // Calculate indices for undefined symbols.
937   for (auto &Csect : UndefinedCsects) {
938     Csect.Size = 0;
939     Csect.Address = 0;
940     Csect.SymbolTableIndex = SymbolTableIndex;
941     SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
942     // 1 main and 1 auxiliary symbol table entry for each contained symbol.
943     SymbolTableIndex += 2;
944   }
945 
946   // The address corrresponds to the address of sections and symbols in the
947   // object file. We place the shared address 0 immediately after the
948   // section header table.
949   uint32_t Address = 0;
950   // Section indices are 1-based in XCOFF.
951   int32_t SectionIndex = 1;
952   bool HasTDataSection = false;
953 
954   for (auto *Section : Sections) {
955     const bool IsEmpty =
956         llvm::all_of(Section->Groups,
957                      [](const CsectGroup *Group) { return Group->empty(); });
958     if (IsEmpty)
959       continue;
960 
961     if (SectionIndex > MaxSectionIndex)
962       report_fatal_error("Section index overflow!");
963     Section->Index = SectionIndex++;
964     SectionCount++;
965 
966     bool SectionAddressSet = false;
967     // Reset the starting address to 0 for TData section.
968     if (Section->Flags == XCOFF::STYP_TDATA) {
969       Address = 0;
970       HasTDataSection = true;
971     }
972     // Reset the starting address to 0 for TBSS section if the object file does
973     // not contain TData Section.
974     if ((Section->Flags == XCOFF::STYP_TBSS) && !HasTDataSection)
975       Address = 0;
976 
977     for (auto *Group : Section->Groups) {
978       if (Group->empty())
979         continue;
980 
981       for (auto &Csect : *Group) {
982         const MCSectionXCOFF *MCSec = Csect.MCSec;
983         Csect.Address = alignTo(Address, MCSec->getAlignment());
984         Csect.Size = Layout.getSectionAddressSize(MCSec);
985         Address = Csect.Address + Csect.Size;
986         Csect.SymbolTableIndex = SymbolTableIndex;
987         SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
988         // 1 main and 1 auxiliary symbol table entry for the csect.
989         SymbolTableIndex += 2;
990 
991         for (auto &Sym : Csect.Syms) {
992           Sym.SymbolTableIndex = SymbolTableIndex;
993           SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
994           // 1 main and 1 auxiliary symbol table entry for each contained
995           // symbol.
996           SymbolTableIndex += 2;
997         }
998       }
999 
1000       if (!SectionAddressSet) {
1001         Section->Address = Group->front().Address;
1002         SectionAddressSet = true;
1003       }
1004     }
1005 
1006     // Make sure the address of the next section aligned to
1007     // DefaultSectionAlign.
1008     Address = alignTo(Address, DefaultSectionAlign);
1009     Section->Size = Address - Section->Address;
1010   }
1011 
1012   for (auto &DwarfSection : DwarfSections) {
1013     assert((SectionIndex <= MaxSectionIndex) && "Section index overflow!");
1014 
1015     XCOFFSection &DwarfSect = *DwarfSection.DwarfSect;
1016     const MCSectionXCOFF *MCSec = DwarfSect.MCSec;
1017 
1018     // Section index.
1019     DwarfSection.Index = SectionIndex++;
1020     SectionCount++;
1021 
1022     // Symbol index.
1023     DwarfSect.SymbolTableIndex = SymbolTableIndex;
1024     SymbolIndexMap[MCSec->getQualNameSymbol()] = DwarfSect.SymbolTableIndex;
1025     // 1 main and 1 auxiliary symbol table entry for the csect.
1026     SymbolTableIndex += 2;
1027 
1028     // Section address. Make it align to section alignment.
1029     // We use address 0 for DWARF sections' Physical and Virtual Addresses.
1030     // This address is used to tell where is the section in the final object.
1031     // See writeSectionForDwarfSectionEntry().
1032     DwarfSection.Address = DwarfSect.Address =
1033         alignTo(Address, MCSec->getAlignment());
1034 
1035     // Section size.
1036     // For DWARF section, we must use the real size which may be not aligned.
1037     DwarfSection.Size = DwarfSect.Size = Layout.getSectionAddressSize(MCSec);
1038 
1039     // Make the Address align to default alignment for follow section.
1040     Address = alignTo(DwarfSect.Address + DwarfSect.Size, DefaultSectionAlign);
1041   }
1042 
1043   SymbolTableEntryCount = SymbolTableIndex;
1044 
1045   // Calculate the RawPointer value for each section.
1046   uint64_t RawPointer =
1047       (is64Bit() ? (XCOFF::FileHeaderSize64 +
1048                     SectionCount * XCOFF::SectionHeaderSize64)
1049                  : (XCOFF::FileHeaderSize32 +
1050                     SectionCount * XCOFF::SectionHeaderSize32)) +
1051       auxiliaryHeaderSize();
1052 
1053   for (auto *Sec : Sections) {
1054     if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual)
1055       continue;
1056 
1057     Sec->FileOffsetToData = RawPointer;
1058     RawPointer += Sec->Size;
1059     if (RawPointer > MaxRawDataSize)
1060       report_fatal_error("Section raw data overflowed this object file.");
1061   }
1062 
1063   for (auto &DwarfSection : DwarfSections) {
1064     // Address of csect sections are always aligned to DefaultSectionAlign, but
1065     // address of DWARF section are aligned to Section alignment which may be
1066     // bigger than DefaultSectionAlign, need to execlude the padding bits.
1067     RawPointer =
1068         alignTo(RawPointer, DwarfSection.DwarfSect->MCSec->getAlignment());
1069 
1070     DwarfSection.FileOffsetToData = RawPointer;
1071     // Some section entries, like DWARF section size is not aligned, so
1072     // RawPointer may be not aligned.
1073     RawPointer += DwarfSection.Size;
1074     // Make sure RawPointer is aligned.
1075     RawPointer = alignTo(RawPointer, DefaultSectionAlign);
1076 
1077     assert(RawPointer <= MaxRawDataSize &&
1078            "Section raw data overflowed this object file.");
1079   }
1080 
1081   RelocationEntryOffset = RawPointer;
1082 }
1083 
1084 void XCOFFObjectWriter::writeSectionForControlSectionEntry(
1085     const MCAssembler &Asm, const MCAsmLayout &Layout,
1086     const CsectSectionEntry &CsectEntry, uint32_t &CurrentAddressLocation) {
1087   // Nothing to write for this Section.
1088   if (CsectEntry.Index == SectionEntry::UninitializedIndex)
1089     return;
1090 
1091   // There could be a gap (without corresponding zero padding) between
1092   // sections.
1093   // There could be a gap (without corresponding zero padding) between
1094   // sections.
1095   assert(((CurrentAddressLocation <= CsectEntry.Address) ||
1096           (CsectEntry.Flags == XCOFF::STYP_TDATA) ||
1097           (CsectEntry.Flags == XCOFF::STYP_TBSS)) &&
1098          "CurrentAddressLocation should be less than or equal to section "
1099          "address if the section is not TData or TBSS.");
1100 
1101   CurrentAddressLocation = CsectEntry.Address;
1102 
1103   // For virtual sections, nothing to write. But need to increase
1104   // CurrentAddressLocation for later sections like DWARF section has a correct
1105   // writing location.
1106   if (CsectEntry.IsVirtual) {
1107     CurrentAddressLocation += CsectEntry.Size;
1108     return;
1109   }
1110 
1111   for (const auto &Group : CsectEntry.Groups) {
1112     for (const auto &Csect : *Group) {
1113       if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
1114         W.OS.write_zeros(PaddingSize);
1115       if (Csect.Size)
1116         Asm.writeSectionData(W.OS, Csect.MCSec, Layout);
1117       CurrentAddressLocation = Csect.Address + Csect.Size;
1118     }
1119   }
1120 
1121   // The size of the tail padding in a section is the end virtual address of
1122   // the current section minus the the end virtual address of the last csect
1123   // in that section.
1124   if (uint32_t PaddingSize =
1125           CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) {
1126     W.OS.write_zeros(PaddingSize);
1127     CurrentAddressLocation += PaddingSize;
1128   }
1129 }
1130 
1131 void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
1132     const MCAssembler &Asm, const MCAsmLayout &Layout,
1133     const DwarfSectionEntry &DwarfEntry, uint32_t &CurrentAddressLocation) {
1134   // There could be a gap (without corresponding zero padding) between
1135   // sections. For example DWARF section alignment is bigger than
1136   // DefaultSectionAlign.
1137   assert(CurrentAddressLocation <= DwarfEntry.Address &&
1138          "CurrentAddressLocation should be less than or equal to section "
1139          "address.");
1140 
1141   if (uint32_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation)
1142     W.OS.write_zeros(PaddingSize);
1143 
1144   if (DwarfEntry.Size)
1145     Asm.writeSectionData(W.OS, DwarfEntry.DwarfSect->MCSec, Layout);
1146 
1147   CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size;
1148 
1149   // DWARF section size is not aligned to DefaultSectionAlign.
1150   // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign.
1151   uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign;
1152   uint32_t TailPaddingSize = Mod ? DefaultSectionAlign - Mod : 0;
1153   if (TailPaddingSize)
1154     W.OS.write_zeros(TailPaddingSize);
1155 
1156   CurrentAddressLocation += TailPaddingSize;
1157 }
1158 
1159 // Takes the log base 2 of the alignment and shifts the result into the 5 most
1160 // significant bits of a byte, then or's in the csect type into the least
1161 // significant 3 bits.
1162 uint8_t getEncodedType(const MCSectionXCOFF *Sec) {
1163   unsigned Align = Sec->getAlignment();
1164   assert(isPowerOf2_32(Align) && "Alignment must be a power of 2.");
1165   unsigned Log2Align = Log2_32(Align);
1166   // Result is a number in the range [0, 31] which fits in the 5 least
1167   // significant bits. Shift this value into the 5 most significant bits, and
1168   // bitwise-or in the csect type.
1169   uint8_t EncodedAlign = Log2Align << 3;
1170   return EncodedAlign | Sec->getCSectType();
1171 }
1172 
1173 } // end anonymous namespace
1174 
1175 std::unique_ptr<MCObjectWriter>
1176 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
1177                               raw_pwrite_stream &OS) {
1178   return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);
1179 }
1180