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