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