xref: /freebsd/contrib/llvm-project/llvm/lib/MC/XCOFFObjectWriter.cpp (revision 2c2ec6bbc9cc7762a250ffe903bda6c2e44d25ff)
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/MCAssembler.h"
16 #include "llvm/MC/MCFixup.h"
17 #include "llvm/MC/MCObjectWriter.h"
18 #include "llvm/MC/MCSectionXCOFF.h"
19 #include "llvm/MC/MCSymbolXCOFF.h"
20 #include "llvm/MC/MCValue.h"
21 #include "llvm/MC/MCXCOFFObjectWriter.h"
22 #include "llvm/MC/StringTableBuilder.h"
23 #include "llvm/Support/Casting.h"
24 #include "llvm/Support/EndianStream.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/MathExtras.h"
27 
28 #include <deque>
29 #include <map>
30 
31 using namespace llvm;
32 
33 // An XCOFF object file has a limited set of predefined sections. The most
34 // important ones for us (right now) are:
35 // .text --> contains program code and read-only data.
36 // .data --> contains initialized data, function descriptors, and the TOC.
37 // .bss  --> contains uninitialized data.
38 // Each of these sections is composed of 'Control Sections'. A Control Section
39 // is more commonly referred to as a csect. A csect is an indivisible unit of
40 // code or data, and acts as a container for symbols. A csect is mapped
41 // into a section based on its storage-mapping class, with the exception of
42 // XMC_RW which gets mapped to either .data or .bss based on whether it's
43 // explicitly initialized or not.
44 //
45 // We don't represent the sections in the MC layer as there is nothing
46 // interesting about them at at that level: they carry information that is
47 // only relevant to the ObjectWriter, so we materialize them in this class.
48 namespace {
49 
50 constexpr unsigned DefaultSectionAlign = 4;
51 constexpr int16_t MaxSectionIndex = INT16_MAX;
52 
53 // Packs the csect's alignment and type into a byte.
54 uint8_t getEncodedType(const MCSectionXCOFF *);
55 
56 struct XCOFFRelocation {
57   uint32_t SymbolTableIndex;
58   uint32_t FixupOffsetInCsect;
59   uint8_t SignAndSize;
60   uint8_t Type;
61 };
62 
63 // Wrapper around an MCSymbolXCOFF.
64 struct Symbol {
65   const MCSymbolXCOFF *const MCSym;
66   uint32_t SymbolTableIndex;
67 
68   XCOFF::VisibilityType getVisibilityType() const {
69     return MCSym->getVisibilityType();
70   }
71 
72   XCOFF::StorageClass getStorageClass() const {
73     return MCSym->getStorageClass();
74   }
75   StringRef getSymbolTableName() const { return MCSym->getSymbolTableName(); }
76   Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {}
77 };
78 
79 // Wrapper for an MCSectionXCOFF.
80 // It can be a Csect or debug section or DWARF section and so on.
81 struct XCOFFSection {
82   const MCSectionXCOFF *const MCSec;
83   uint32_t SymbolTableIndex;
84   uint64_t Address;
85   uint64_t Size;
86 
87   SmallVector<Symbol, 1> Syms;
88   SmallVector<XCOFFRelocation, 1> Relocations;
89   StringRef getSymbolTableName() const { return MCSec->getSymbolTableName(); }
90   XCOFF::VisibilityType getVisibilityType() const {
91     return MCSec->getVisibilityType();
92   }
93   XCOFFSection(const MCSectionXCOFF *MCSec)
94       : MCSec(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
95 };
96 
97 // Type to be used for a container representing a set of csects with
98 // (approximately) the same storage mapping class. For example all the csects
99 // with a storage mapping class of `xmc_pr` will get placed into the same
100 // container.
101 using CsectGroup = std::deque<XCOFFSection>;
102 using CsectGroups = std::deque<CsectGroup *>;
103 
104 // The basic section entry defination. This Section represents a section entry
105 // in XCOFF section header table.
106 struct SectionEntry {
107   char Name[XCOFF::NameSize];
108   // The physical/virtual address of the section. For an object file these
109   // values are equivalent, except for in the overflow section header, where
110   // the physical address specifies the number of relocation entries and the
111   // virtual address specifies the number of line number entries.
112   // TODO: Divide Address into PhysicalAddress and VirtualAddress when line
113   // number entries are supported.
114   uint64_t Address;
115   uint64_t Size;
116   uint64_t FileOffsetToData;
117   uint64_t FileOffsetToRelocations;
118   uint32_t RelocationCount;
119   int32_t Flags;
120 
121   int16_t Index;
122 
123   virtual uint64_t advanceFileOffset(const uint64_t MaxRawDataSize,
124                                      const uint64_t RawPointer) {
125     FileOffsetToData = RawPointer;
126     uint64_t NewPointer = RawPointer + Size;
127     if (NewPointer > MaxRawDataSize)
128       report_fatal_error("Section raw data overflowed this object file.");
129     return NewPointer;
130   }
131 
132   // XCOFF has special section numbers for symbols:
133   // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
134   // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
135   // relocatable.
136   //  0 Specifies N_UNDEF, an undefined external symbol.
137   // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
138   // hasn't been initialized.
139   static constexpr int16_t UninitializedIndex =
140       XCOFF::ReservedSectionNum::N_DEBUG - 1;
141 
142   SectionEntry(StringRef N, int32_t Flags)
143       : Name(), Address(0), Size(0), FileOffsetToData(0),
144         FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags),
145         Index(UninitializedIndex) {
146     assert(N.size() <= XCOFF::NameSize && "section name too long");
147     memcpy(Name, N.data(), N.size());
148   }
149 
150   virtual void reset() {
151     Address = 0;
152     Size = 0;
153     FileOffsetToData = 0;
154     FileOffsetToRelocations = 0;
155     RelocationCount = 0;
156     Index = UninitializedIndex;
157   }
158 
159   virtual ~SectionEntry() = default;
160 };
161 
162 // Represents the data related to a section excluding the csects that make up
163 // the raw data of the section. The csects are stored separately as not all
164 // sections contain csects, and some sections contain csects which are better
165 // stored separately, e.g. the .data section containing read-write, descriptor,
166 // TOCBase and TOC-entry csects.
167 struct CsectSectionEntry : public SectionEntry {
168   // Virtual sections do not need storage allocated in the object file.
169   const bool IsVirtual;
170 
171   // This is a section containing csect groups.
172   CsectGroups Groups;
173 
174   CsectSectionEntry(StringRef N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
175                     CsectGroups Groups)
176       : SectionEntry(N, Flags), IsVirtual(IsVirtual), Groups(Groups) {
177     assert(N.size() <= XCOFF::NameSize && "section name too long");
178     memcpy(Name, N.data(), N.size());
179   }
180 
181   void reset() override {
182     SectionEntry::reset();
183     // Clear any csects we have stored.
184     for (auto *Group : Groups)
185       Group->clear();
186   }
187 
188   virtual ~CsectSectionEntry() = default;
189 };
190 
191 struct DwarfSectionEntry : public SectionEntry {
192   // For DWARF section entry.
193   std::unique_ptr<XCOFFSection> DwarfSect;
194 
195   // For DWARF section, we must use real size in the section header. MemorySize
196   // is for the size the DWARF section occupies including paddings.
197   uint32_t MemorySize;
198 
199   // TODO: Remove this override. Loadable sections (e.g., .text, .data) may need
200   // to be aligned. Other sections generally don't need any alignment, but if
201   // they're aligned, the RawPointer should be adjusted before writing the
202   // section. Then a dwarf-specific function wouldn't be needed.
203   uint64_t advanceFileOffset(const uint64_t MaxRawDataSize,
204                              const uint64_t RawPointer) override {
205     FileOffsetToData = RawPointer;
206     uint64_t NewPointer = RawPointer + MemorySize;
207     assert(NewPointer <= MaxRawDataSize &&
208            "Section raw data overflowed this object file.");
209     return NewPointer;
210   }
211 
212   DwarfSectionEntry(StringRef N, int32_t Flags,
213                     std::unique_ptr<XCOFFSection> Sect)
214       : SectionEntry(N, Flags | XCOFF::STYP_DWARF), DwarfSect(std::move(Sect)),
215         MemorySize(0) {
216     assert(DwarfSect->MCSec->isDwarfSect() &&
217            "This should be a DWARF section!");
218     assert(N.size() <= XCOFF::NameSize && "section name too long");
219     memcpy(Name, N.data(), N.size());
220   }
221 
222   DwarfSectionEntry(DwarfSectionEntry &&s) = default;
223 
224   virtual ~DwarfSectionEntry() = default;
225 };
226 
227 struct ExceptionTableEntry {
228   const MCSymbol *Trap;
229   uint64_t TrapAddress = ~0ul;
230   unsigned Lang;
231   unsigned Reason;
232 
233   ExceptionTableEntry(const MCSymbol *Trap, unsigned Lang, unsigned Reason)
234       : Trap(Trap), Lang(Lang), Reason(Reason) {}
235 };
236 
237 struct ExceptionInfo {
238   const MCSymbol *FunctionSymbol;
239   unsigned FunctionSize;
240   std::vector<ExceptionTableEntry> Entries;
241 };
242 
243 struct ExceptionSectionEntry : public SectionEntry {
244   std::map<const StringRef, ExceptionInfo> ExceptionTable;
245   bool isDebugEnabled = false;
246 
247   ExceptionSectionEntry(StringRef N, int32_t Flags)
248       : SectionEntry(N, Flags | XCOFF::STYP_EXCEPT) {
249     assert(N.size() <= XCOFF::NameSize && "Section too long.");
250     memcpy(Name, N.data(), N.size());
251   }
252 
253   virtual ~ExceptionSectionEntry() = default;
254 };
255 
256 struct CInfoSymInfo {
257   // Name of the C_INFO symbol associated with the section
258   std::string Name;
259   std::string Metadata;
260   // Offset into the start of the metadata in the section
261   uint64_t Offset;
262 
263   CInfoSymInfo(std::string Name, std::string Metadata)
264       : Name(Name), Metadata(Metadata) {}
265   // Metadata needs to be padded out to an even word size.
266   uint32_t paddingSize() const {
267     return alignTo(Metadata.size(), sizeof(uint32_t)) - Metadata.size();
268   };
269 
270   // Total size of the entry, including the 4 byte length
271   uint32_t size() const {
272     return Metadata.size() + paddingSize() + sizeof(uint32_t);
273   };
274 };
275 
276 struct CInfoSymSectionEntry : public SectionEntry {
277   std::unique_ptr<CInfoSymInfo> Entry;
278 
279   CInfoSymSectionEntry(StringRef N, int32_t Flags) : SectionEntry(N, Flags) {}
280   virtual ~CInfoSymSectionEntry() = default;
281   void addEntry(std::unique_ptr<CInfoSymInfo> NewEntry) {
282     Entry = std::move(NewEntry);
283     Entry->Offset = sizeof(uint32_t);
284     Size += Entry->size();
285   }
286   void reset() override {
287     SectionEntry::reset();
288     Entry.reset();
289   }
290 };
291 
292 class XCOFFWriter final : public XCOFFObjectWriter {
293   uint32_t SymbolTableEntryCount = 0;
294   uint64_t SymbolTableOffset = 0;
295   uint16_t SectionCount = 0;
296   uint32_t PaddingsBeforeDwarf = 0;
297   bool HasVisibility = false;
298 
299   support::endian::Writer W;
300   std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
301   StringTableBuilder Strings;
302 
303   const uint64_t MaxRawDataSize =
304       TargetObjectWriter->is64Bit() ? UINT64_MAX : UINT32_MAX;
305 
306   // Maps the MCSection representation to its corresponding XCOFFSection
307   // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into
308   // from its containing MCSectionXCOFF.
309   DenseMap<const MCSectionXCOFF *, XCOFFSection *> SectionMap;
310 
311   // Maps the MCSymbol representation to its corrresponding symbol table index.
312   // Needed for relocation.
313   DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap;
314 
315   // CsectGroups. These store the csects which make up different parts of
316   // the sections. Should have one for each set of csects that get mapped into
317   // the same section and get handled in a 'similar' way.
318   CsectGroup UndefinedCsects;
319   CsectGroup ProgramCodeCsects;
320   CsectGroup ReadOnlyCsects;
321   CsectGroup DataCsects;
322   CsectGroup FuncDSCsects;
323   CsectGroup TOCCsects;
324   CsectGroup BSSCsects;
325   CsectGroup TDataCsects;
326   CsectGroup TBSSCsects;
327 
328   // The Predefined sections.
329   CsectSectionEntry Text;
330   CsectSectionEntry Data;
331   CsectSectionEntry BSS;
332   CsectSectionEntry TData;
333   CsectSectionEntry TBSS;
334 
335   // All the XCOFF sections, in the order they will appear in the section header
336   // table.
337   std::array<CsectSectionEntry *const, 5> Sections{
338       {&Text, &Data, &BSS, &TData, &TBSS}};
339 
340   std::vector<DwarfSectionEntry> DwarfSections;
341   std::vector<SectionEntry> OverflowSections;
342 
343   ExceptionSectionEntry ExceptionSection;
344   CInfoSymSectionEntry CInfoSymSection;
345 
346   CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
347 
348   void reset() override;
349 
350   void executePostLayoutBinding() override;
351 
352   void recordRelocation(const MCFragment &, const MCFixup &, MCValue,
353                         uint64_t &) override;
354 
355   uint64_t writeObject() override;
356 
357   bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
358   bool nameShouldBeInStringTable(const StringRef &);
359   void writeSymbolName(const StringRef &);
360   bool auxFileSymNameShouldBeInStringTable(const StringRef &);
361   void writeAuxFileSymName(const StringRef &);
362 
363   void writeSymbolEntryForCsectMemberLabel(const Symbol &SymbolRef,
364                                            const XCOFFSection &CSectionRef,
365                                            int16_t SectionIndex,
366                                            uint64_t SymbolOffset);
367   void writeSymbolEntryForControlSection(const XCOFFSection &CSectionRef,
368                                          int16_t SectionIndex,
369                                          XCOFF::StorageClass StorageClass);
370   void writeSymbolEntryForDwarfSection(const XCOFFSection &DwarfSectionRef,
371                                        int16_t SectionIndex);
372   void writeFileHeader();
373   void writeAuxFileHeader();
374   void writeSectionHeader(const SectionEntry *Sec);
375   void writeSectionHeaderTable();
376   void writeSections(const MCAssembler &Asm);
377   void writeSectionForControlSectionEntry(const MCAssembler &Asm,
378                                           const CsectSectionEntry &CsectEntry,
379                                           uint64_t &CurrentAddressLocation);
380   void writeSectionForDwarfSectionEntry(const MCAssembler &Asm,
381                                         const DwarfSectionEntry &DwarfEntry,
382                                         uint64_t &CurrentAddressLocation);
383   void
384   writeSectionForExceptionSectionEntry(const MCAssembler &Asm,
385                                        ExceptionSectionEntry &ExceptionEntry,
386                                        uint64_t &CurrentAddressLocation);
387   void writeSectionForCInfoSymSectionEntry(const MCAssembler &Asm,
388                                            CInfoSymSectionEntry &CInfoSymEntry,
389                                            uint64_t &CurrentAddressLocation);
390   void writeSymbolTable(MCAssembler &Asm);
391   void writeSymbolAuxFileEntry(StringRef &Name, uint8_t ftype);
392   void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion,
393                                 uint64_t NumberOfRelocEnt = 0);
394   void writeSymbolAuxCsectEntry(uint64_t SectionOrLength,
395                                 uint8_t SymbolAlignmentAndType,
396                                 uint8_t StorageMappingClass);
397   void writeSymbolAuxFunctionEntry(uint32_t EntryOffset, uint32_t FunctionSize,
398                                    uint64_t LineNumberPointer,
399                                    uint32_t EndIndex);
400   void writeSymbolAuxExceptionEntry(uint64_t EntryOffset, uint32_t FunctionSize,
401                                     uint32_t EndIndex);
402   void writeSymbolEntry(StringRef SymbolName, uint64_t Value,
403                         int16_t SectionNumber, uint16_t SymbolType,
404                         uint8_t StorageClass, uint8_t NumberOfAuxEntries = 1);
405   void writeRelocations();
406   void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section);
407 
408   // Called after all the csects and symbols have been processed by
409   // `executePostLayoutBinding`, this function handles building up the majority
410   // of the structures in the object file representation. Namely:
411   // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
412   //    sizes.
413   // *) Assigns symbol table indices.
414   // *) Builds up the section header table by adding any non-empty sections to
415   //    `Sections`.
416   void assignAddressesAndIndices(MCAssembler &Asm);
417   // Called after relocations are recorded.
418   void finalizeSectionInfo();
419   void finalizeRelocationInfo(SectionEntry *Sec, uint64_t RelCount);
420   void calcOffsetToRelocations(SectionEntry *Sec, uint64_t &RawPointer);
421 
422   bool hasExceptionSection() {
423     return !ExceptionSection.ExceptionTable.empty();
424   }
425   unsigned getExceptionSectionSize();
426   unsigned getExceptionOffset(const MCSymbol *Symbol);
427 
428   size_t auxiliaryHeaderSize() const {
429     // 64-bit object files have no auxiliary header.
430     return HasVisibility && !is64Bit() ? XCOFF::AuxFileHeaderSizeShort : 0;
431   }
432 
433 public:
434   XCOFFWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
435               raw_pwrite_stream &OS);
436 
437   void writeWord(uint64_t Word) {
438     is64Bit() ? W.write<uint64_t>(Word) : W.write<uint32_t>(Word);
439   }
440 
441   void addExceptionEntry(const MCSymbol *Symbol, const MCSymbol *Trap,
442                          unsigned LanguageCode, unsigned ReasonCode,
443                          unsigned FunctionSize, bool hasDebug) override;
444   void addCInfoSymEntry(StringRef Name, StringRef Metadata) override;
445 };
446 
447 XCOFFWriter::XCOFFWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
448                          raw_pwrite_stream &OS)
449     : W(OS, llvm::endianness::big), TargetObjectWriter(std::move(MOTW)),
450       Strings(StringTableBuilder::XCOFF),
451       Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
452            CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
453       Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false,
454            CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
455       BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
456           CsectGroups{&BSSCsects}),
457       TData(".tdata", XCOFF::STYP_TDATA, /* IsVirtual */ false,
458             CsectGroups{&TDataCsects}),
459       TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true,
460            CsectGroups{&TBSSCsects}),
461       ExceptionSection(".except", XCOFF::STYP_EXCEPT),
462       CInfoSymSection(".info", XCOFF::STYP_INFO) {}
463 
464 void XCOFFWriter::reset() {
465   // Clear the mappings we created.
466   SymbolIndexMap.clear();
467   SectionMap.clear();
468 
469   UndefinedCsects.clear();
470   // Reset any sections we have written to, and empty the section header table.
471   for (auto *Sec : Sections)
472     Sec->reset();
473   for (auto &DwarfSec : DwarfSections)
474     DwarfSec.reset();
475   for (auto &OverflowSec : OverflowSections)
476     OverflowSec.reset();
477   ExceptionSection.reset();
478   CInfoSymSection.reset();
479 
480   // Reset states in XCOFFWriter.
481   SymbolTableEntryCount = 0;
482   SymbolTableOffset = 0;
483   SectionCount = 0;
484   PaddingsBeforeDwarf = 0;
485   Strings.clear();
486 
487   MCObjectWriter::reset();
488 }
489 
490 CsectGroup &XCOFFWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
491   switch (MCSec->getMappingClass()) {
492   case XCOFF::XMC_PR:
493     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
494            "Only an initialized csect can contain program code.");
495     return ProgramCodeCsects;
496   case XCOFF::XMC_RO:
497     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
498            "Only an initialized csect can contain read only data.");
499     return ReadOnlyCsects;
500   case XCOFF::XMC_RW:
501     if (XCOFF::XTY_CM == MCSec->getCSectType())
502       return BSSCsects;
503 
504     if (XCOFF::XTY_SD == MCSec->getCSectType())
505       return DataCsects;
506 
507     report_fatal_error("Unhandled mapping of read-write csect to section.");
508   case XCOFF::XMC_DS:
509     return FuncDSCsects;
510   case XCOFF::XMC_BS:
511     assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
512            "Mapping invalid csect. CSECT with bss storage class must be "
513            "common type.");
514     return BSSCsects;
515   case XCOFF::XMC_TL:
516     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
517            "Mapping invalid csect. CSECT with tdata storage class must be "
518            "an initialized csect.");
519     return TDataCsects;
520   case XCOFF::XMC_UL:
521     assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
522            "Mapping invalid csect. CSECT with tbss storage class must be "
523            "an uninitialized csect.");
524     return TBSSCsects;
525   case XCOFF::XMC_TC0:
526     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
527            "Only an initialized csect can contain TOC-base.");
528     assert(TOCCsects.empty() &&
529            "We should have only one TOC-base, and it should be the first csect "
530            "in this CsectGroup.");
531     return TOCCsects;
532   case XCOFF::XMC_TC:
533   case XCOFF::XMC_TE:
534     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
535            "A TOC symbol must be an initialized csect.");
536     assert(!TOCCsects.empty() &&
537            "We should at least have a TOC-base in this CsectGroup.");
538     return TOCCsects;
539   case XCOFF::XMC_TD:
540     assert((XCOFF::XTY_SD == MCSec->getCSectType() ||
541             XCOFF::XTY_CM == MCSec->getCSectType()) &&
542            "Symbol type incompatible with toc-data.");
543     assert(!TOCCsects.empty() &&
544            "We should at least have a TOC-base in this CsectGroup.");
545     return TOCCsects;
546   default:
547     report_fatal_error("Unhandled mapping of csect to section.");
548   }
549 }
550 
551 static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) {
552   if (XSym->isDefined())
553     return cast<MCSectionXCOFF>(XSym->getFragment()->getParent());
554   return XSym->getRepresentedCsect();
555 }
556 
557 void XCOFFWriter::executePostLayoutBinding() {
558   for (const auto &S : *Asm) {
559     const auto *MCSec = cast<const MCSectionXCOFF>(&S);
560     assert(!SectionMap.contains(MCSec) && "Cannot add a section twice.");
561 
562     // If the name does not fit in the storage provided in the symbol table
563     // entry, add it to the string table.
564     if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
565       Strings.add(MCSec->getSymbolTableName());
566     if (MCSec->isCsect()) {
567       // A new control section. Its CsectSectionEntry should already be staticly
568       // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of
569       // the CsectSectionEntry.
570       assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
571              "An undefined csect should not get registered.");
572       CsectGroup &Group = getCsectGroup(MCSec);
573       Group.emplace_back(MCSec);
574       SectionMap[MCSec] = &Group.back();
575     } else if (MCSec->isDwarfSect()) {
576       // A new DwarfSectionEntry.
577       std::unique_ptr<XCOFFSection> DwarfSec =
578           std::make_unique<XCOFFSection>(MCSec);
579       SectionMap[MCSec] = DwarfSec.get();
580 
581       DwarfSectionEntry SecEntry(MCSec->getName(),
582                                  *MCSec->getDwarfSubtypeFlags(),
583                                  std::move(DwarfSec));
584       DwarfSections.push_back(std::move(SecEntry));
585     } else
586       llvm_unreachable("unsupport section type!");
587   }
588 
589   for (const MCSymbol &S : Asm->symbols()) {
590     // Nothing to do for temporary symbols.
591     if (S.isTemporary())
592       continue;
593 
594     const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
595     const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym);
596 
597     if (ContainingCsect->isDwarfSect())
598       continue;
599 
600     if (XSym->getVisibilityType() != XCOFF::SYM_V_UNSPECIFIED)
601       HasVisibility = true;
602 
603     if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
604       // Handle undefined symbol.
605       UndefinedCsects.emplace_back(ContainingCsect);
606       SectionMap[ContainingCsect] = &UndefinedCsects.back();
607       if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName()))
608         Strings.add(ContainingCsect->getSymbolTableName());
609       continue;
610     }
611 
612     // If the symbol is the csect itself, we don't need to put the symbol
613     // into csect's Syms.
614     if (XSym == ContainingCsect->getQualNameSymbol())
615       continue;
616 
617     // Only put a label into the symbol table when it is an external label.
618     if (!XSym->isExternal())
619       continue;
620 
621     assert(SectionMap.contains(ContainingCsect) &&
622            "Expected containing csect to exist in map");
623     XCOFFSection *Csect = SectionMap[ContainingCsect];
624     // Lookup the containing csect and add the symbol to it.
625     assert(Csect->MCSec->isCsect() && "only csect is supported now!");
626     Csect->Syms.emplace_back(XSym);
627 
628     // If the name does not fit in the storage provided in the symbol table
629     // entry, add it to the string table.
630     if (nameShouldBeInStringTable(XSym->getSymbolTableName()))
631       Strings.add(XSym->getSymbolTableName());
632   }
633 
634   std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymSection.Entry;
635   if (CISI && nameShouldBeInStringTable(CISI->Name))
636     Strings.add(CISI->Name);
637 
638   // Emit ".file" as the source file name when there is no file name.
639   if (FileNames.empty())
640     FileNames.emplace_back(".file", 0);
641   for (const std::pair<std::string, size_t> &F : FileNames) {
642     if (auxFileSymNameShouldBeInStringTable(F.first))
643       Strings.add(F.first);
644   }
645 
646   // Always add ".file" to the symbol table. The actual file name will be in
647   // the AUX_FILE auxiliary entry.
648   if (nameShouldBeInStringTable(".file"))
649     Strings.add(".file");
650   StringRef Vers = CompilerVersion;
651   if (auxFileSymNameShouldBeInStringTable(Vers))
652     Strings.add(Vers);
653 
654   Strings.finalize();
655   assignAddressesAndIndices(*Asm);
656 }
657 
658 void XCOFFWriter::recordRelocation(const MCFragment &F, const MCFixup &Fixup,
659                                    MCValue Target, uint64_t &FixedValue) {
660   auto getIndex = [this](const MCSymbol *Sym,
661                          const MCSectionXCOFF *ContainingCsect) {
662     // If we could not find the symbol directly in SymbolIndexMap, this symbol
663     // could either be a temporary symbol or an undefined symbol. In this case,
664     // we would need to have the relocation reference its csect instead.
665     auto It = SymbolIndexMap.find(Sym);
666     return It != SymbolIndexMap.end()
667                ? It->second
668                : SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
669   };
670 
671   auto getVirtualAddress =
672       [this](const MCSymbol *Sym,
673              const MCSectionXCOFF *ContainingSect) -> uint64_t {
674     // A DWARF section.
675     if (ContainingSect->isDwarfSect())
676       return Asm->getSymbolOffset(*Sym);
677 
678     // A csect.
679     if (!Sym->isDefined())
680       return SectionMap[ContainingSect]->Address;
681 
682     // A label.
683     assert(Sym->isDefined() && "not a valid object that has address!");
684     return SectionMap[ContainingSect]->Address + Asm->getSymbolOffset(*Sym);
685   };
686 
687   const MCSymbol *const SymA = Target.getAddSym();
688   uint8_t Type;
689   uint8_t SignAndSize;
690   std::tie(Type, SignAndSize) = TargetObjectWriter->getRelocTypeAndSignSize(
691       Target, Fixup, Fixup.isPCRel());
692 
693   const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
694   assert(SectionMap.contains(SymASec) &&
695          "Expected containing csect to exist in map.");
696 
697   assert((Fixup.getOffset() <= MaxRawDataSize - Asm->getFragmentOffset(F)) &&
698          "Fragment offset + fixup offset is overflowed.");
699   uint32_t FixupOffsetInCsect = Asm->getFragmentOffset(F) + Fixup.getOffset();
700 
701   const uint32_t Index = getIndex(SymA, SymASec);
702   if (Type == XCOFF::RelocationType::R_POS ||
703       Type == XCOFF::RelocationType::R_TLS ||
704       Type == XCOFF::RelocationType::R_TLS_LE ||
705       Type == XCOFF::RelocationType::R_TLS_IE ||
706       Type == XCOFF::RelocationType::R_TLS_LD)
707     // The FixedValue should be symbol's virtual address in this object file
708     // plus any constant value that we might get.
709     FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
710   else if (Type == XCOFF::RelocationType::R_TLSM)
711     // The FixedValue should always be zero since the region handle is only
712     // known at load time.
713     FixedValue = 0;
714   else if (Type == XCOFF::RelocationType::R_TOC ||
715            Type == XCOFF::RelocationType::R_TOCL) {
716     // For non toc-data external symbols, R_TOC type relocation will relocate to
717     // data symbols that have XCOFF::XTY_SD type csect. For toc-data external
718     // symbols, R_TOC type relocation will relocate to data symbols that have
719     // XCOFF_ER type csect. For XCOFF_ER kind symbols, there will be no TOC
720     // entry for them, so the FixedValue should always be 0.
721     if (SymASec->getCSectType() == XCOFF::XTY_ER) {
722       FixedValue = 0;
723     } else {
724       // The FixedValue should be the TOC entry offset from the TOC-base plus
725       // any constant offset value.
726       int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
727                                TOCCsects.front().Address + Target.getConstant();
728       // For small code model, if the TOCEntryOffset overflows the 16-bit value,
729       // we truncate it back down to 16 bits. The linker will be able to insert
730       // fix-up code when needed.
731       // For non toc-data symbols, we already did the truncation in
732       // PPCAsmPrinter.cpp through setting Target.getConstant() in the
733       // expression above by calling getTOCEntryLoadingExprForXCOFF for the
734       // various TOC PseudoOps.
735       // For toc-data symbols, we were not able to calculate the offset from
736       // the TOC in PPCAsmPrinter.cpp since the TOC has not been finalized at
737       // that point, so we are adjusting it here though
738       // llvm::SignExtend64<16>(TOCEntryOffset);
739       // TODO: Since the time that the handling for offsets over 16-bits was
740       // added in PPCAsmPrinter.cpp using getTOCEntryLoadingExprForXCOFF, the
741       // system assembler and linker have been updated to be able to handle the
742       // overflowing offsets, so we no longer need to keep
743       // getTOCEntryLoadingExprForXCOFF.
744       if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset))
745         TOCEntryOffset = llvm::SignExtend64<16>(TOCEntryOffset);
746 
747       FixedValue = TOCEntryOffset;
748     }
749   } else if (Type == XCOFF::RelocationType::R_RBR) {
750     MCSectionXCOFF *ParentSec = cast<MCSectionXCOFF>(F.getParent());
751     assert((SymASec->getMappingClass() == XCOFF::XMC_PR &&
752             ParentSec->getMappingClass() == XCOFF::XMC_PR) &&
753            "Only XMC_PR csect may have the R_RBR relocation.");
754 
755     // The address of the branch instruction should be the sum of section
756     // address, fragment offset and Fixup offset.
757     uint64_t BRInstrAddress =
758         SectionMap[ParentSec]->Address + FixupOffsetInCsect;
759     // The FixedValue should be the difference between symbol's virtual address
760     // and BR instr address plus any constant value.
761     FixedValue = getVirtualAddress(SymA, SymASec) - BRInstrAddress +
762                  Target.getConstant();
763   } else if (Type == XCOFF::RelocationType::R_REF) {
764     // The FixedValue and FixupOffsetInCsect should always be 0 since it
765     // specifies a nonrelocating reference.
766     FixedValue = 0;
767     FixupOffsetInCsect = 0;
768   }
769 
770   XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
771   MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(F.getParent());
772   assert(SectionMap.contains(RelocationSec) &&
773          "Expected containing csect to exist in map.");
774   SectionMap[RelocationSec]->Relocations.push_back(Reloc);
775 
776   const MCSymbol *const SymB = Target.getSubSym();
777   if (!SymB)
778     return;
779   if (SymA == SymB)
780     report_fatal_error("relocation for opposite term is not yet supported");
781 
782   const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
783   assert(SectionMap.contains(SymBSec) &&
784          "Expected containing csect to exist in map.");
785   if (SymASec == SymBSec)
786     report_fatal_error(
787         "relocation for paired relocatable term is not yet supported");
788 
789   assert(Type == XCOFF::RelocationType::R_POS &&
790          "SymA must be R_POS here if it's not opposite term or paired "
791          "relocatable term.");
792   const uint32_t IndexB = getIndex(SymB, SymBSec);
793   // SymB must be R_NEG here, given the general form of Target(MCValue) is
794   // "SymbolA - SymbolB + imm64".
795   const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
796   XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
797   SectionMap[RelocationSec]->Relocations.push_back(RelocB);
798   // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
799   // now we just need to fold "- SymbolB" here.
800   FixedValue -= getVirtualAddress(SymB, SymBSec);
801 }
802 
803 void XCOFFWriter::writeSections(const MCAssembler &Asm) {
804   uint64_t CurrentAddressLocation = 0;
805   for (const auto *Section : Sections)
806     writeSectionForControlSectionEntry(Asm, *Section, CurrentAddressLocation);
807   for (const auto &DwarfSection : DwarfSections)
808     writeSectionForDwarfSectionEntry(Asm, DwarfSection, CurrentAddressLocation);
809   writeSectionForExceptionSectionEntry(Asm, ExceptionSection,
810                                        CurrentAddressLocation);
811   writeSectionForCInfoSymSectionEntry(Asm, CInfoSymSection,
812                                       CurrentAddressLocation);
813 }
814 
815 uint64_t XCOFFWriter::writeObject() {
816   // We always emit a timestamp of 0 for reproducibility, so ensure incremental
817   // linking is not enabled, in case, like with Windows COFF, such a timestamp
818   // is incompatible with incremental linking of XCOFF.
819 
820   finalizeSectionInfo();
821   uint64_t StartOffset = W.OS.tell();
822 
823   writeFileHeader();
824   writeAuxFileHeader();
825   writeSectionHeaderTable();
826   writeSections(*Asm);
827   writeRelocations();
828   writeSymbolTable(*Asm);
829   // Write the string table.
830   Strings.write(W.OS);
831 
832   return W.OS.tell() - StartOffset;
833 }
834 
835 bool XCOFFWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
836   return SymbolName.size() > XCOFF::NameSize || is64Bit();
837 }
838 
839 void XCOFFWriter::writeSymbolName(const StringRef &SymbolName) {
840   // Magic, Offset or SymbolName.
841   if (nameShouldBeInStringTable(SymbolName)) {
842     W.write<int32_t>(0);
843     W.write<uint32_t>(Strings.getOffset(SymbolName));
844   } else {
845     char Name[XCOFF::NameSize + 1];
846     std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
847     ArrayRef<char> NameRef(Name, XCOFF::NameSize);
848     W.write(NameRef);
849   }
850 }
851 
852 void XCOFFWriter::writeSymbolEntry(StringRef SymbolName, uint64_t Value,
853                                    int16_t SectionNumber, uint16_t SymbolType,
854                                    uint8_t StorageClass,
855                                    uint8_t NumberOfAuxEntries) {
856   if (is64Bit()) {
857     W.write<uint64_t>(Value);
858     W.write<uint32_t>(Strings.getOffset(SymbolName));
859   } else {
860     writeSymbolName(SymbolName);
861     W.write<uint32_t>(Value);
862   }
863   W.write<int16_t>(SectionNumber);
864   W.write<uint16_t>(SymbolType);
865   W.write<uint8_t>(StorageClass);
866   W.write<uint8_t>(NumberOfAuxEntries);
867 }
868 
869 void XCOFFWriter::writeSymbolAuxCsectEntry(uint64_t SectionOrLength,
870                                            uint8_t SymbolAlignmentAndType,
871                                            uint8_t StorageMappingClass) {
872   W.write<uint32_t>(is64Bit() ? Lo_32(SectionOrLength) : SectionOrLength);
873   W.write<uint32_t>(0); // ParameterHashIndex
874   W.write<uint16_t>(0); // TypeChkSectNum
875   W.write<uint8_t>(SymbolAlignmentAndType);
876   W.write<uint8_t>(StorageMappingClass);
877   if (is64Bit()) {
878     W.write<uint32_t>(Hi_32(SectionOrLength));
879     W.OS.write_zeros(1); // Reserved
880     W.write<uint8_t>(XCOFF::AUX_CSECT);
881   } else {
882     W.write<uint32_t>(0); // StabInfoIndex
883     W.write<uint16_t>(0); // StabSectNum
884   }
885 }
886 
887 bool XCOFFWriter::auxFileSymNameShouldBeInStringTable(
888     const StringRef &SymbolName) {
889   return SymbolName.size() > XCOFF::AuxFileEntNameSize;
890 }
891 
892 void XCOFFWriter::writeAuxFileSymName(const StringRef &SymbolName) {
893   // Magic, Offset or SymbolName.
894   if (auxFileSymNameShouldBeInStringTable(SymbolName)) {
895     W.write<int32_t>(0);
896     W.write<uint32_t>(Strings.getOffset(SymbolName));
897     W.OS.write_zeros(XCOFF::FileNamePadSize);
898   } else {
899     char Name[XCOFF::AuxFileEntNameSize + 1];
900     std::strncpy(Name, SymbolName.data(), XCOFF::AuxFileEntNameSize);
901     ArrayRef<char> NameRef(Name, XCOFF::AuxFileEntNameSize);
902     W.write(NameRef);
903   }
904 }
905 
906 void XCOFFWriter::writeSymbolAuxFileEntry(StringRef &Name, uint8_t ftype) {
907   writeAuxFileSymName(Name);
908   W.write<uint8_t>(ftype);
909   W.OS.write_zeros(2);
910   if (is64Bit())
911     W.write<uint8_t>(XCOFF::AUX_FILE);
912   else
913     W.OS.write_zeros(1);
914 }
915 
916 void XCOFFWriter::writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion,
917                                            uint64_t NumberOfRelocEnt) {
918   writeWord(LengthOfSectionPortion);
919   if (!is64Bit())
920     W.OS.write_zeros(4); // Reserved
921   writeWord(NumberOfRelocEnt);
922   if (is64Bit()) {
923     W.OS.write_zeros(1); // Reserved
924     W.write<uint8_t>(XCOFF::AUX_SECT);
925   } else {
926     W.OS.write_zeros(6); // Reserved
927   }
928 }
929 
930 void XCOFFWriter::writeSymbolEntryForCsectMemberLabel(
931     const Symbol &SymbolRef, const XCOFFSection &CSectionRef,
932     int16_t SectionIndex, uint64_t SymbolOffset) {
933   assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address &&
934          "Symbol address overflowed.");
935 
936   auto Entry = ExceptionSection.ExceptionTable.find(SymbolRef.MCSym->getName());
937   if (Entry != ExceptionSection.ExceptionTable.end()) {
938     writeSymbolEntry(SymbolRef.getSymbolTableName(),
939                      CSectionRef.Address + SymbolOffset, SectionIndex,
940                      // In the old version of the 32-bit XCOFF interpretation,
941                      // symbols may require bit 10 (0x0020) to be set if the
942                      // symbol is a function, otherwise the bit should be 0.
943                      is64Bit() ? SymbolRef.getVisibilityType()
944                                : SymbolRef.getVisibilityType() | 0x0020,
945                      SymbolRef.getStorageClass(),
946                      (is64Bit() && ExceptionSection.isDebugEnabled) ? 3 : 2);
947     if (is64Bit() && ExceptionSection.isDebugEnabled) {
948       // On 64 bit with debugging enabled, we have a csect, exception, and
949       // function auxilliary entries, so we must increment symbol index by 4.
950       writeSymbolAuxExceptionEntry(
951           ExceptionSection.FileOffsetToData +
952               getExceptionOffset(Entry->second.FunctionSymbol),
953           Entry->second.FunctionSize,
954           SymbolIndexMap[Entry->second.FunctionSymbol] + 4);
955     }
956     // For exception section entries, csect and function auxilliary entries
957     // must exist. On 64-bit there is also an exception auxilliary entry.
958     writeSymbolAuxFunctionEntry(
959         ExceptionSection.FileOffsetToData +
960             getExceptionOffset(Entry->second.FunctionSymbol),
961         Entry->second.FunctionSize, 0,
962         (is64Bit() && ExceptionSection.isDebugEnabled)
963             ? SymbolIndexMap[Entry->second.FunctionSymbol] + 4
964             : SymbolIndexMap[Entry->second.FunctionSymbol] + 3);
965   } else {
966     writeSymbolEntry(SymbolRef.getSymbolTableName(),
967                      CSectionRef.Address + SymbolOffset, SectionIndex,
968                      SymbolRef.getVisibilityType(),
969                      SymbolRef.getStorageClass());
970   }
971   writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex, XCOFF::XTY_LD,
972                            CSectionRef.MCSec->getMappingClass());
973 }
974 
975 void XCOFFWriter::writeSymbolEntryForDwarfSection(
976     const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) {
977   assert(DwarfSectionRef.MCSec->isDwarfSect() && "Not a DWARF section!");
978 
979   writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), /*Value=*/0,
980                    SectionIndex, /*SymbolType=*/0, XCOFF::C_DWARF);
981 
982   writeSymbolAuxDwarfEntry(DwarfSectionRef.Size);
983 }
984 
985 void XCOFFWriter::writeSymbolEntryForControlSection(
986     const XCOFFSection &CSectionRef, int16_t SectionIndex,
987     XCOFF::StorageClass StorageClass) {
988   writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address,
989                    SectionIndex, CSectionRef.getVisibilityType(), StorageClass);
990 
991   writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec),
992                            CSectionRef.MCSec->getMappingClass());
993 }
994 
995 void XCOFFWriter::writeSymbolAuxFunctionEntry(uint32_t EntryOffset,
996                                               uint32_t FunctionSize,
997                                               uint64_t LineNumberPointer,
998                                               uint32_t EndIndex) {
999   if (is64Bit())
1000     writeWord(LineNumberPointer);
1001   else
1002     W.write<uint32_t>(EntryOffset);
1003   W.write<uint32_t>(FunctionSize);
1004   if (!is64Bit())
1005     writeWord(LineNumberPointer);
1006   W.write<uint32_t>(EndIndex);
1007   if (is64Bit()) {
1008     W.OS.write_zeros(1);
1009     W.write<uint8_t>(XCOFF::AUX_FCN);
1010   } else {
1011     W.OS.write_zeros(2);
1012   }
1013 }
1014 
1015 void XCOFFWriter::writeSymbolAuxExceptionEntry(uint64_t EntryOffset,
1016                                                uint32_t FunctionSize,
1017                                                uint32_t EndIndex) {
1018   assert(is64Bit() && "Exception auxilliary entries are 64-bit only.");
1019   W.write<uint64_t>(EntryOffset);
1020   W.write<uint32_t>(FunctionSize);
1021   W.write<uint32_t>(EndIndex);
1022   W.OS.write_zeros(1); // Pad (unused)
1023   W.write<uint8_t>(XCOFF::AUX_EXCEPT);
1024 }
1025 
1026 void XCOFFWriter::writeFileHeader() {
1027   W.write<uint16_t>(is64Bit() ? XCOFF::XCOFF64 : XCOFF::XCOFF32);
1028   W.write<uint16_t>(SectionCount);
1029   W.write<int32_t>(0); // TimeStamp
1030   writeWord(SymbolTableOffset);
1031   if (is64Bit()) {
1032     W.write<uint16_t>(auxiliaryHeaderSize());
1033     W.write<uint16_t>(0); // Flags
1034     W.write<int32_t>(SymbolTableEntryCount);
1035   } else {
1036     W.write<int32_t>(SymbolTableEntryCount);
1037     W.write<uint16_t>(auxiliaryHeaderSize());
1038     W.write<uint16_t>(0); // Flags
1039   }
1040 }
1041 
1042 void XCOFFWriter::writeAuxFileHeader() {
1043   if (!auxiliaryHeaderSize())
1044     return;
1045   W.write<uint16_t>(0); // Magic
1046   W.write<uint16_t>(
1047       XCOFF::NEW_XCOFF_INTERPRET); // Version. The new interpretation of the
1048                                    // n_type field in the symbol table entry is
1049                                    // used in XCOFF32.
1050   W.write<uint32_t>(Sections[0]->Size);    // TextSize
1051   W.write<uint32_t>(Sections[1]->Size);    // InitDataSize
1052   W.write<uint32_t>(Sections[2]->Size);    // BssDataSize
1053   W.write<uint32_t>(0);                    // EntryPointAddr
1054   W.write<uint32_t>(Sections[0]->Address); // TextStartAddr
1055   W.write<uint32_t>(Sections[1]->Address); // DataStartAddr
1056 }
1057 
1058 void XCOFFWriter::writeSectionHeader(const SectionEntry *Sec) {
1059   bool IsDwarf = (Sec->Flags & XCOFF::STYP_DWARF) != 0;
1060   bool IsOvrflo = (Sec->Flags & XCOFF::STYP_OVRFLO) != 0;
1061   // Nothing to write for this Section.
1062   if (Sec->Index == SectionEntry::UninitializedIndex)
1063     return;
1064 
1065   // Write Name.
1066   ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
1067   W.write(NameRef);
1068 
1069   // Write the Physical Address and Virtual Address.
1070   // We use 0 for DWARF sections' Physical and Virtual Addresses.
1071   writeWord(IsDwarf ? 0 : Sec->Address);
1072   // Since line number is not supported, we set it to 0 for overflow sections.
1073   writeWord((IsDwarf || IsOvrflo) ? 0 : Sec->Address);
1074 
1075   writeWord(Sec->Size);
1076   writeWord(Sec->FileOffsetToData);
1077   writeWord(Sec->FileOffsetToRelocations);
1078   writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet.
1079 
1080   if (is64Bit()) {
1081     W.write<uint32_t>(Sec->RelocationCount);
1082     W.write<uint32_t>(0); // NumberOfLineNumbers. Not supported yet.
1083     W.write<int32_t>(Sec->Flags);
1084     W.OS.write_zeros(4);
1085   } else {
1086     // For the overflow section header, s_nreloc provides a reference to the
1087     // primary section header and s_nlnno must have the same value.
1088     // For common section headers, if either of s_nreloc or s_nlnno are set to
1089     // 65535, the other one must also be set to 65535.
1090     W.write<uint16_t>(Sec->RelocationCount);
1091     W.write<uint16_t>((IsOvrflo || Sec->RelocationCount == XCOFF::RelocOverflow)
1092                           ? Sec->RelocationCount
1093                           : 0); // NumberOfLineNumbers. Not supported yet.
1094     W.write<int32_t>(Sec->Flags);
1095   }
1096 }
1097 
1098 void XCOFFWriter::writeSectionHeaderTable() {
1099   for (const auto *CsectSec : Sections)
1100     writeSectionHeader(CsectSec);
1101   for (const auto &DwarfSec : DwarfSections)
1102     writeSectionHeader(&DwarfSec);
1103   for (const auto &OverflowSec : OverflowSections)
1104     writeSectionHeader(&OverflowSec);
1105   if (hasExceptionSection())
1106     writeSectionHeader(&ExceptionSection);
1107   if (CInfoSymSection.Entry)
1108     writeSectionHeader(&CInfoSymSection);
1109 }
1110 
1111 void XCOFFWriter::writeRelocation(XCOFFRelocation Reloc,
1112                                   const XCOFFSection &Section) {
1113   if (Section.MCSec->isCsect())
1114     writeWord(Section.Address + Reloc.FixupOffsetInCsect);
1115   else {
1116     // DWARF sections' address is set to 0.
1117     assert(Section.MCSec->isDwarfSect() && "unsupport section type!");
1118     writeWord(Reloc.FixupOffsetInCsect);
1119   }
1120   W.write<uint32_t>(Reloc.SymbolTableIndex);
1121   W.write<uint8_t>(Reloc.SignAndSize);
1122   W.write<uint8_t>(Reloc.Type);
1123 }
1124 
1125 void XCOFFWriter::writeRelocations() {
1126   for (const auto *Section : Sections) {
1127     if (Section->Index == SectionEntry::UninitializedIndex)
1128       // Nothing to write for this Section.
1129       continue;
1130 
1131     for (const auto *Group : Section->Groups) {
1132       if (Group->empty())
1133         continue;
1134 
1135       for (const auto &Csect : *Group) {
1136         for (const auto Reloc : Csect.Relocations)
1137           writeRelocation(Reloc, Csect);
1138       }
1139     }
1140   }
1141 
1142   for (const auto &DwarfSection : DwarfSections)
1143     for (const auto &Reloc : DwarfSection.DwarfSect->Relocations)
1144       writeRelocation(Reloc, *DwarfSection.DwarfSect);
1145 }
1146 
1147 void XCOFFWriter::writeSymbolTable(MCAssembler &Asm) {
1148   // Write C_FILE symbols.
1149   StringRef Vers = CompilerVersion;
1150 
1151   for (const std::pair<std::string, size_t> &F : FileNames) {
1152     // The n_name of a C_FILE symbol is the source file's name when no auxiliary
1153     // entries are present.
1154     StringRef FileName = F.first;
1155 
1156     // For C_FILE symbols, the Source Language ID overlays the high-order byte
1157     // of the SymbolType field, and the CPU Version ID is defined as the
1158     // low-order byte.
1159     // AIX's system assembler determines the source language ID based on the
1160     // source file's name suffix, and the behavior here is consistent with it.
1161     uint8_t LangID;
1162     if (FileName.ends_with(".c"))
1163       LangID = XCOFF::TB_C;
1164     else if (FileName.ends_with_insensitive(".f") ||
1165              FileName.ends_with_insensitive(".f77") ||
1166              FileName.ends_with_insensitive(".f90") ||
1167              FileName.ends_with_insensitive(".f95") ||
1168              FileName.ends_with_insensitive(".f03") ||
1169              FileName.ends_with_insensitive(".f08"))
1170       LangID = XCOFF::TB_Fortran;
1171     else
1172       LangID = XCOFF::TB_CPLUSPLUS;
1173 
1174     uint8_t CpuID = XCOFF::getCpuID(getCPUType());
1175 
1176     int NumberOfFileAuxEntries = 1;
1177     if (!Vers.empty())
1178       ++NumberOfFileAuxEntries;
1179     writeSymbolEntry(".file", /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG,
1180                      /*SymbolType=*/(LangID << 8) | CpuID, XCOFF::C_FILE,
1181                      NumberOfFileAuxEntries);
1182     writeSymbolAuxFileEntry(FileName, XCOFF::XFT_FN);
1183     if (!Vers.empty())
1184       writeSymbolAuxFileEntry(Vers, XCOFF::XFT_CV);
1185   }
1186 
1187   if (CInfoSymSection.Entry)
1188     writeSymbolEntry(CInfoSymSection.Entry->Name, CInfoSymSection.Entry->Offset,
1189                      CInfoSymSection.Index,
1190                      /*SymbolType=*/0, XCOFF::C_INFO,
1191                      /*NumberOfAuxEntries=*/0);
1192 
1193   for (const auto &Csect : UndefinedCsects) {
1194     writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF,
1195                                       Csect.MCSec->getStorageClass());
1196   }
1197 
1198   for (const auto *Section : Sections) {
1199     if (Section->Index == SectionEntry::UninitializedIndex)
1200       // Nothing to write for this Section.
1201       continue;
1202 
1203     for (const auto *Group : Section->Groups) {
1204       if (Group->empty())
1205         continue;
1206 
1207       const int16_t SectionIndex = Section->Index;
1208       for (const auto &Csect : *Group) {
1209         // Write out the control section first and then each symbol in it.
1210         writeSymbolEntryForControlSection(Csect, SectionIndex,
1211                                           Csect.MCSec->getStorageClass());
1212 
1213         for (const auto &Sym : Csect.Syms)
1214           writeSymbolEntryForCsectMemberLabel(
1215               Sym, Csect, SectionIndex, Asm.getSymbolOffset(*(Sym.MCSym)));
1216       }
1217     }
1218   }
1219 
1220   for (const auto &DwarfSection : DwarfSections)
1221     writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect,
1222                                     DwarfSection.Index);
1223 }
1224 
1225 void XCOFFWriter::finalizeRelocationInfo(SectionEntry *Sec, uint64_t RelCount) {
1226   // Handles relocation field overflows in an XCOFF32 file. An XCOFF64 file
1227   // may not contain an overflow section header.
1228   if (!is64Bit() && (RelCount >= static_cast<uint32_t>(XCOFF::RelocOverflow))) {
1229     // Generate an overflow section header.
1230     SectionEntry SecEntry(".ovrflo", XCOFF::STYP_OVRFLO);
1231 
1232     // This field specifies the file section number of the section header that
1233     // overflowed.
1234     SecEntry.RelocationCount = Sec->Index;
1235 
1236     // This field specifies the number of relocation entries actually
1237     // required.
1238     SecEntry.Address = RelCount;
1239     SecEntry.Index = ++SectionCount;
1240     OverflowSections.push_back(std::move(SecEntry));
1241 
1242     // The field in the primary section header is always 65535
1243     // (XCOFF::RelocOverflow).
1244     Sec->RelocationCount = XCOFF::RelocOverflow;
1245   } else {
1246     Sec->RelocationCount = RelCount;
1247   }
1248 }
1249 
1250 void XCOFFWriter::calcOffsetToRelocations(SectionEntry *Sec,
1251                                           uint64_t &RawPointer) {
1252   if (!Sec->RelocationCount)
1253     return;
1254 
1255   Sec->FileOffsetToRelocations = RawPointer;
1256   uint64_t RelocationSizeInSec = 0;
1257   if (!is64Bit() &&
1258       Sec->RelocationCount == static_cast<uint32_t>(XCOFF::RelocOverflow)) {
1259     // Find its corresponding overflow section.
1260     for (auto &OverflowSec : OverflowSections) {
1261       if (OverflowSec.RelocationCount == static_cast<uint32_t>(Sec->Index)) {
1262         RelocationSizeInSec =
1263             OverflowSec.Address * XCOFF::RelocationSerializationSize32;
1264 
1265         // This field must have the same values as in the corresponding
1266         // primary section header.
1267         OverflowSec.FileOffsetToRelocations = Sec->FileOffsetToRelocations;
1268       }
1269     }
1270     assert(RelocationSizeInSec && "Overflow section header doesn't exist.");
1271   } else {
1272     RelocationSizeInSec = Sec->RelocationCount *
1273                           (is64Bit() ? XCOFF::RelocationSerializationSize64
1274                                      : XCOFF::RelocationSerializationSize32);
1275   }
1276 
1277   RawPointer += RelocationSizeInSec;
1278   if (RawPointer > MaxRawDataSize)
1279     report_fatal_error("Relocation data overflowed this object file.");
1280 }
1281 
1282 void XCOFFWriter::finalizeSectionInfo() {
1283   for (auto *Section : Sections) {
1284     if (Section->Index == SectionEntry::UninitializedIndex)
1285       // Nothing to record for this Section.
1286       continue;
1287 
1288     uint64_t RelCount = 0;
1289     for (const auto *Group : Section->Groups) {
1290       if (Group->empty())
1291         continue;
1292 
1293       for (auto &Csect : *Group)
1294         RelCount += Csect.Relocations.size();
1295     }
1296     finalizeRelocationInfo(Section, RelCount);
1297   }
1298 
1299   for (auto &DwarfSection : DwarfSections)
1300     finalizeRelocationInfo(&DwarfSection,
1301                            DwarfSection.DwarfSect->Relocations.size());
1302 
1303   // Calculate the RawPointer value for all headers.
1304   uint64_t RawPointer =
1305       (is64Bit() ? (XCOFF::FileHeaderSize64 +
1306                     SectionCount * XCOFF::SectionHeaderSize64)
1307                  : (XCOFF::FileHeaderSize32 +
1308                     SectionCount * XCOFF::SectionHeaderSize32)) +
1309       auxiliaryHeaderSize();
1310 
1311   // Calculate the file offset to the section data.
1312   for (auto *Sec : Sections) {
1313     if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual)
1314       continue;
1315 
1316     RawPointer = Sec->advanceFileOffset(MaxRawDataSize, RawPointer);
1317   }
1318 
1319   if (!DwarfSections.empty()) {
1320     RawPointer += PaddingsBeforeDwarf;
1321     for (auto &DwarfSection : DwarfSections) {
1322       RawPointer = DwarfSection.advanceFileOffset(MaxRawDataSize, RawPointer);
1323     }
1324   }
1325 
1326   if (hasExceptionSection())
1327     RawPointer = ExceptionSection.advanceFileOffset(MaxRawDataSize, RawPointer);
1328 
1329   if (CInfoSymSection.Entry)
1330     RawPointer = CInfoSymSection.advanceFileOffset(MaxRawDataSize, RawPointer);
1331 
1332   for (auto *Sec : Sections) {
1333     if (Sec->Index != SectionEntry::UninitializedIndex)
1334       calcOffsetToRelocations(Sec, RawPointer);
1335   }
1336 
1337   for (auto &DwarfSec : DwarfSections)
1338     calcOffsetToRelocations(&DwarfSec, RawPointer);
1339 
1340   // TODO Error check that the number of symbol table entries fits in 32-bits
1341   // signed ...
1342   if (SymbolTableEntryCount)
1343     SymbolTableOffset = RawPointer;
1344 }
1345 
1346 void XCOFFWriter::addExceptionEntry(const MCSymbol *Symbol,
1347                                     const MCSymbol *Trap, unsigned LanguageCode,
1348                                     unsigned ReasonCode, unsigned FunctionSize,
1349                                     bool hasDebug) {
1350   // If a module had debug info, debugging is enabled and XCOFF emits the
1351   // exception auxilliary entry.
1352   if (hasDebug)
1353     ExceptionSection.isDebugEnabled = true;
1354   auto Entry = ExceptionSection.ExceptionTable.find(Symbol->getName());
1355   if (Entry != ExceptionSection.ExceptionTable.end()) {
1356     Entry->second.Entries.push_back(
1357         ExceptionTableEntry(Trap, LanguageCode, ReasonCode));
1358     return;
1359   }
1360   ExceptionInfo NewEntry;
1361   NewEntry.FunctionSymbol = Symbol;
1362   NewEntry.FunctionSize = FunctionSize;
1363   NewEntry.Entries.push_back(
1364       ExceptionTableEntry(Trap, LanguageCode, ReasonCode));
1365   ExceptionSection.ExceptionTable.insert(
1366       std::pair<const StringRef, ExceptionInfo>(Symbol->getName(), NewEntry));
1367 }
1368 
1369 unsigned XCOFFWriter::getExceptionSectionSize() {
1370   unsigned EntryNum = 0;
1371 
1372   for (const auto &TableEntry : ExceptionSection.ExceptionTable)
1373     // The size() gets +1 to account for the initial entry containing the
1374     // symbol table index.
1375     EntryNum += TableEntry.second.Entries.size() + 1;
1376 
1377   return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
1378                                : XCOFF::ExceptionSectionEntrySize32);
1379 }
1380 
1381 unsigned XCOFFWriter::getExceptionOffset(const MCSymbol *Symbol) {
1382   unsigned EntryNum = 0;
1383   for (const auto &TableEntry : ExceptionSection.ExceptionTable) {
1384     if (Symbol == TableEntry.second.FunctionSymbol)
1385       break;
1386     EntryNum += TableEntry.second.Entries.size() + 1;
1387   }
1388   return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
1389                                : XCOFF::ExceptionSectionEntrySize32);
1390 }
1391 
1392 void XCOFFWriter::addCInfoSymEntry(StringRef Name, StringRef Metadata) {
1393   assert(!CInfoSymSection.Entry && "Multiple entries are not supported");
1394   CInfoSymSection.addEntry(
1395       std::make_unique<CInfoSymInfo>(Name.str(), Metadata.str()));
1396 }
1397 
1398 void XCOFFWriter::assignAddressesAndIndices(MCAssembler &Asm) {
1399   // The symbol table starts with all the C_FILE symbols. Each C_FILE symbol
1400   // requires 1 or 2 auxiliary entries.
1401   uint32_t SymbolTableIndex =
1402       (2 + (CompilerVersion.empty() ? 0 : 1)) * FileNames.size();
1403 
1404   if (CInfoSymSection.Entry)
1405     SymbolTableIndex++;
1406 
1407   // Calculate indices for undefined symbols.
1408   for (auto &Csect : UndefinedCsects) {
1409     Csect.Size = 0;
1410     Csect.Address = 0;
1411     Csect.SymbolTableIndex = SymbolTableIndex;
1412     SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
1413     // 1 main and 1 auxiliary symbol table entry for each contained symbol.
1414     SymbolTableIndex += 2;
1415   }
1416 
1417   // The address corrresponds to the address of sections and symbols in the
1418   // object file. We place the shared address 0 immediately after the
1419   // section header table.
1420   uint64_t Address = 0;
1421   // Section indices are 1-based in XCOFF.
1422   int32_t SectionIndex = 1;
1423   bool HasTDataSection = false;
1424 
1425   for (auto *Section : Sections) {
1426     const bool IsEmpty =
1427         llvm::all_of(Section->Groups,
1428                      [](const CsectGroup *Group) { return Group->empty(); });
1429     if (IsEmpty)
1430       continue;
1431 
1432     if (SectionIndex > MaxSectionIndex)
1433       report_fatal_error("Section index overflow!");
1434     Section->Index = SectionIndex++;
1435     SectionCount++;
1436 
1437     bool SectionAddressSet = false;
1438     // Reset the starting address to 0 for TData section.
1439     if (Section->Flags == XCOFF::STYP_TDATA) {
1440       Address = 0;
1441       HasTDataSection = true;
1442     }
1443     // Reset the starting address to 0 for TBSS section if the object file does
1444     // not contain TData Section.
1445     if ((Section->Flags == XCOFF::STYP_TBSS) && !HasTDataSection)
1446       Address = 0;
1447 
1448     for (auto *Group : Section->Groups) {
1449       if (Group->empty())
1450         continue;
1451 
1452       for (auto &Csect : *Group) {
1453         const MCSectionXCOFF *MCSec = Csect.MCSec;
1454         Csect.Address = alignTo(Address, MCSec->getAlign());
1455         Csect.Size = Asm.getSectionAddressSize(*MCSec);
1456         Address = Csect.Address + Csect.Size;
1457         Csect.SymbolTableIndex = SymbolTableIndex;
1458         SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
1459         // 1 main and 1 auxiliary symbol table entry for the csect.
1460         SymbolTableIndex += 2;
1461 
1462         for (auto &Sym : Csect.Syms) {
1463           bool hasExceptEntry = false;
1464           auto Entry =
1465               ExceptionSection.ExceptionTable.find(Sym.MCSym->getName());
1466           if (Entry != ExceptionSection.ExceptionTable.end()) {
1467             hasExceptEntry = true;
1468             for (auto &TrapEntry : Entry->second.Entries) {
1469               TrapEntry.TrapAddress = Asm.getSymbolOffset(*(Sym.MCSym)) +
1470                                       TrapEntry.Trap->getOffset();
1471             }
1472           }
1473           Sym.SymbolTableIndex = SymbolTableIndex;
1474           SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
1475           // 1 main and 1 auxiliary symbol table entry for each contained
1476           // symbol. For symbols with exception section entries, a function
1477           // auxilliary entry is needed, and on 64-bit XCOFF with debugging
1478           // enabled, an additional exception auxilliary entry is needed.
1479           SymbolTableIndex += 2;
1480           if (hasExceptionSection() && hasExceptEntry) {
1481             if (is64Bit() && ExceptionSection.isDebugEnabled)
1482               SymbolTableIndex += 2;
1483             else
1484               SymbolTableIndex += 1;
1485           }
1486         }
1487       }
1488 
1489       if (!SectionAddressSet) {
1490         Section->Address = Group->front().Address;
1491         SectionAddressSet = true;
1492       }
1493     }
1494 
1495     // Make sure the address of the next section aligned to
1496     // DefaultSectionAlign.
1497     Address = alignTo(Address, DefaultSectionAlign);
1498     Section->Size = Address - Section->Address;
1499   }
1500 
1501   // Start to generate DWARF sections. Sections other than DWARF section use
1502   // DefaultSectionAlign as the default alignment, while DWARF sections have
1503   // their own alignments. If these two alignments are not the same, we need
1504   // some paddings here and record the paddings bytes for FileOffsetToData
1505   // calculation.
1506   if (!DwarfSections.empty())
1507     PaddingsBeforeDwarf =
1508         alignTo(Address,
1509                 (*DwarfSections.begin()).DwarfSect->MCSec->getAlign()) -
1510         Address;
1511 
1512   DwarfSectionEntry *LastDwarfSection = nullptr;
1513   for (auto &DwarfSection : DwarfSections) {
1514     assert((SectionIndex <= MaxSectionIndex) && "Section index overflow!");
1515 
1516     XCOFFSection &DwarfSect = *DwarfSection.DwarfSect;
1517     const MCSectionXCOFF *MCSec = DwarfSect.MCSec;
1518 
1519     // Section index.
1520     DwarfSection.Index = SectionIndex++;
1521     SectionCount++;
1522 
1523     // Symbol index.
1524     DwarfSect.SymbolTableIndex = SymbolTableIndex;
1525     SymbolIndexMap[MCSec->getQualNameSymbol()] = DwarfSect.SymbolTableIndex;
1526     // 1 main and 1 auxiliary symbol table entry for the csect.
1527     SymbolTableIndex += 2;
1528 
1529     // Section address. Make it align to section alignment.
1530     // We use address 0 for DWARF sections' Physical and Virtual Addresses.
1531     // This address is used to tell where is the section in the final object.
1532     // See writeSectionForDwarfSectionEntry().
1533     DwarfSection.Address = DwarfSect.Address =
1534         alignTo(Address, MCSec->getAlign());
1535 
1536     // Section size.
1537     // For DWARF section, we must use the real size which may be not aligned.
1538     DwarfSection.Size = DwarfSect.Size = Asm.getSectionAddressSize(*MCSec);
1539 
1540     Address = DwarfSection.Address + DwarfSection.Size;
1541 
1542     if (LastDwarfSection)
1543       LastDwarfSection->MemorySize =
1544           DwarfSection.Address - LastDwarfSection->Address;
1545     LastDwarfSection = &DwarfSection;
1546   }
1547   if (LastDwarfSection) {
1548     // Make the final DWARF section address align to the default section
1549     // alignment for follow contents.
1550     Address = alignTo(LastDwarfSection->Address + LastDwarfSection->Size,
1551                       DefaultSectionAlign);
1552     LastDwarfSection->MemorySize = Address - LastDwarfSection->Address;
1553   }
1554   if (hasExceptionSection()) {
1555     ExceptionSection.Index = SectionIndex++;
1556     SectionCount++;
1557     ExceptionSection.Address = 0;
1558     ExceptionSection.Size = getExceptionSectionSize();
1559     Address += ExceptionSection.Size;
1560     Address = alignTo(Address, DefaultSectionAlign);
1561   }
1562 
1563   if (CInfoSymSection.Entry) {
1564     CInfoSymSection.Index = SectionIndex++;
1565     SectionCount++;
1566     CInfoSymSection.Address = 0;
1567     Address += CInfoSymSection.Size;
1568     Address = alignTo(Address, DefaultSectionAlign);
1569   }
1570 
1571   SymbolTableEntryCount = SymbolTableIndex;
1572 }
1573 
1574 void XCOFFWriter::writeSectionForControlSectionEntry(
1575     const MCAssembler &Asm, const CsectSectionEntry &CsectEntry,
1576     uint64_t &CurrentAddressLocation) {
1577   // Nothing to write for this Section.
1578   if (CsectEntry.Index == SectionEntry::UninitializedIndex)
1579     return;
1580 
1581   // There could be a gap (without corresponding zero padding) between
1582   // sections.
1583   // There could be a gap (without corresponding zero padding) between
1584   // sections.
1585   assert(((CurrentAddressLocation <= CsectEntry.Address) ||
1586           (CsectEntry.Flags == XCOFF::STYP_TDATA) ||
1587           (CsectEntry.Flags == XCOFF::STYP_TBSS)) &&
1588          "CurrentAddressLocation should be less than or equal to section "
1589          "address if the section is not TData or TBSS.");
1590 
1591   CurrentAddressLocation = CsectEntry.Address;
1592 
1593   // For virtual sections, nothing to write. But need to increase
1594   // CurrentAddressLocation for later sections like DWARF section has a correct
1595   // writing location.
1596   if (CsectEntry.IsVirtual) {
1597     CurrentAddressLocation += CsectEntry.Size;
1598     return;
1599   }
1600 
1601   for (const auto &Group : CsectEntry.Groups) {
1602     for (const auto &Csect : *Group) {
1603       if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
1604         W.OS.write_zeros(PaddingSize);
1605       if (Csect.Size)
1606         Asm.writeSectionData(W.OS, Csect.MCSec);
1607       CurrentAddressLocation = Csect.Address + Csect.Size;
1608     }
1609   }
1610 
1611   // The size of the tail padding in a section is the end virtual address of
1612   // the current section minus the end virtual address of the last csect
1613   // in that section.
1614   if (uint64_t PaddingSize =
1615           CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) {
1616     W.OS.write_zeros(PaddingSize);
1617     CurrentAddressLocation += PaddingSize;
1618   }
1619 }
1620 
1621 void XCOFFWriter::writeSectionForDwarfSectionEntry(
1622     const MCAssembler &Asm, const DwarfSectionEntry &DwarfEntry,
1623     uint64_t &CurrentAddressLocation) {
1624   // There could be a gap (without corresponding zero padding) between
1625   // sections. For example DWARF section alignment is bigger than
1626   // DefaultSectionAlign.
1627   assert(CurrentAddressLocation <= DwarfEntry.Address &&
1628          "CurrentAddressLocation should be less than or equal to section "
1629          "address.");
1630 
1631   if (uint64_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation)
1632     W.OS.write_zeros(PaddingSize);
1633 
1634   if (DwarfEntry.Size)
1635     Asm.writeSectionData(W.OS, DwarfEntry.DwarfSect->MCSec);
1636 
1637   CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size;
1638 
1639   // DWARF section size is not aligned to DefaultSectionAlign.
1640   // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign.
1641   uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign;
1642   uint32_t TailPaddingSize = Mod ? DefaultSectionAlign - Mod : 0;
1643   if (TailPaddingSize)
1644     W.OS.write_zeros(TailPaddingSize);
1645 
1646   CurrentAddressLocation += TailPaddingSize;
1647 }
1648 
1649 void XCOFFWriter::writeSectionForExceptionSectionEntry(
1650     const MCAssembler &Asm, ExceptionSectionEntry &ExceptionEntry,
1651     uint64_t &CurrentAddressLocation) {
1652   for (const auto &TableEntry : ExceptionEntry.ExceptionTable) {
1653     // For every symbol that has exception entries, you must start the entries
1654     // with an initial symbol table index entry
1655     W.write<uint32_t>(SymbolIndexMap[TableEntry.second.FunctionSymbol]);
1656     if (is64Bit()) {
1657       // 4-byte padding on 64-bit.
1658       W.OS.write_zeros(4);
1659     }
1660     W.OS.write_zeros(2);
1661     for (auto &TrapEntry : TableEntry.second.Entries) {
1662       writeWord(TrapEntry.TrapAddress);
1663       W.write<uint8_t>(TrapEntry.Lang);
1664       W.write<uint8_t>(TrapEntry.Reason);
1665     }
1666   }
1667 
1668   CurrentAddressLocation += getExceptionSectionSize();
1669 }
1670 
1671 void XCOFFWriter::writeSectionForCInfoSymSectionEntry(
1672     const MCAssembler &Asm, CInfoSymSectionEntry &CInfoSymEntry,
1673     uint64_t &CurrentAddressLocation) {
1674   if (!CInfoSymSection.Entry)
1675     return;
1676 
1677   constexpr int WordSize = sizeof(uint32_t);
1678   std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymEntry.Entry;
1679   const std::string &Metadata = CISI->Metadata;
1680 
1681   // Emit the 4-byte length of the metadata.
1682   W.write<uint32_t>(Metadata.size());
1683 
1684   if (Metadata.size() == 0)
1685     return;
1686 
1687   // Write out the payload one word at a time.
1688   size_t Index = 0;
1689   while (Index + WordSize <= Metadata.size()) {
1690     uint32_t NextWord =
1691         llvm::support::endian::read32be(Metadata.data() + Index);
1692     W.write<uint32_t>(NextWord);
1693     Index += WordSize;
1694   }
1695 
1696   // If there is padding, we have at least one byte of payload left to emit.
1697   if (CISI->paddingSize()) {
1698     std::array<uint8_t, WordSize> LastWord = {0};
1699     ::memcpy(LastWord.data(), Metadata.data() + Index, Metadata.size() - Index);
1700     W.write<uint32_t>(llvm::support::endian::read32be(LastWord.data()));
1701   }
1702 
1703   CurrentAddressLocation += CISI->size();
1704 }
1705 
1706 // Takes the log base 2 of the alignment and shifts the result into the 5 most
1707 // significant bits of a byte, then or's in the csect type into the least
1708 // significant 3 bits.
1709 uint8_t getEncodedType(const MCSectionXCOFF *Sec) {
1710   unsigned Log2Align = Log2(Sec->getAlign());
1711   // Result is a number in the range [0, 31] which fits in the 5 least
1712   // significant bits. Shift this value into the 5 most significant bits, and
1713   // bitwise-or in the csect type.
1714   uint8_t EncodedAlign = Log2Align << 3;
1715   return EncodedAlign | Sec->getCSectType();
1716 }
1717 
1718 } // end anonymous namespace
1719 
1720 std::unique_ptr<MCObjectWriter>
1721 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
1722                               raw_pwrite_stream &OS) {
1723   return std::make_unique<XCOFFWriter>(std::move(MOTW), OS);
1724 }
1725