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