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