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/EndianStream.h"
26 #include "llvm/Support/Error.h"
27 #include "llvm/Support/MathExtras.h"
28 
29 #include <deque>
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::StorageClass getStorageClass() const {
69     return MCSym->getStorageClass();
70   }
71 
72   XCOFF::VisibilityType getVisibilityType() const {
73     return MCSym->getVisibilityType();
74   }
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 struct ControlSection {
82   const MCSectionXCOFF *const MCCsect;
83   uint32_t SymbolTableIndex;
84   uint32_t Address;
85   uint32_t Size;
86 
87   SmallVector<Symbol, 1> Syms;
88   SmallVector<XCOFFRelocation, 1> Relocations;
89   StringRef getSymbolTableName() const { return MCCsect->getSymbolTableName(); }
90   ControlSection(const MCSectionXCOFF *MCSec)
91       : MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
92 };
93 
94 // Type to be used for a container representing a set of csects with
95 // (approximately) the same storage mapping class. For example all the csects
96 // with a storage mapping class of `xmc_pr` will get placed into the same
97 // container.
98 using CsectGroup = std::deque<ControlSection>;
99 using CsectGroups = std::deque<CsectGroup *>;
100 
101 // Represents the data related to a section excluding the csects that make up
102 // the raw data of the section. The csects are stored separately as not all
103 // sections contain csects, and some sections contain csects which are better
104 // stored separately, e.g. the .data section containing read-write, descriptor,
105 // TOCBase and TOC-entry csects.
106 struct Section {
107   char Name[XCOFF::NameSize];
108   // The physical/virtual address of the section. For an object file
109   // these values are equivalent.
110   uint32_t Address;
111   uint32_t Size;
112   uint32_t FileOffsetToData;
113   uint32_t FileOffsetToRelocations;
114   uint32_t RelocationCount;
115   int32_t Flags;
116 
117   int16_t Index;
118 
119   // Virtual sections do not need storage allocated in the object file.
120   const bool IsVirtual;
121 
122   // XCOFF has special section numbers for symbols:
123   // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
124   // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
125   // relocatable.
126   //  0 Specifies N_UNDEF, an undefined external symbol.
127   // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
128   // hasn't been initialized.
129   static constexpr int16_t UninitializedIndex =
130       XCOFF::ReservedSectionNum::N_DEBUG - 1;
131 
132   CsectGroups Groups;
133 
134   void reset() {
135     Address = 0;
136     Size = 0;
137     FileOffsetToData = 0;
138     FileOffsetToRelocations = 0;
139     RelocationCount = 0;
140     Index = UninitializedIndex;
141     // Clear any csects we have stored.
142     for (auto *Group : Groups)
143       Group->clear();
144   }
145 
146   Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
147           CsectGroups Groups)
148       : Address(0), Size(0), FileOffsetToData(0), FileOffsetToRelocations(0),
149         RelocationCount(0), Flags(Flags), Index(UninitializedIndex),
150         IsVirtual(IsVirtual), Groups(Groups) {
151     strncpy(Name, N, XCOFF::NameSize);
152   }
153 };
154 
155 class XCOFFObjectWriter : public MCObjectWriter {
156 
157   uint32_t SymbolTableEntryCount = 0;
158   uint32_t SymbolTableOffset = 0;
159   uint16_t SectionCount = 0;
160   uint32_t RelocationEntryOffset = 0;
161 
162   support::endian::Writer W;
163   std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
164   StringTableBuilder Strings;
165 
166   // Maps the MCSection representation to its corresponding ControlSection
167   // wrapper. Needed for finding the ControlSection to insert an MCSymbol into
168   // from its containing MCSectionXCOFF.
169   DenseMap<const MCSectionXCOFF *, ControlSection *> SectionMap;
170 
171   // Maps the MCSymbol representation to its corrresponding symbol table index.
172   // Needed for relocation.
173   DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap;
174 
175   // CsectGroups. These store the csects which make up different parts of
176   // the sections. Should have one for each set of csects that get mapped into
177   // the same section and get handled in a 'similar' way.
178   CsectGroup UndefinedCsects;
179   CsectGroup ProgramCodeCsects;
180   CsectGroup ReadOnlyCsects;
181   CsectGroup DataCsects;
182   CsectGroup FuncDSCsects;
183   CsectGroup TOCCsects;
184   CsectGroup BSSCsects;
185 
186   // The Predefined sections.
187   Section Text;
188   Section Data;
189   Section BSS;
190 
191   // All the XCOFF sections, in the order they will appear in the section header
192   // table.
193   std::array<Section *const, 3> Sections{{&Text, &Data, &BSS}};
194 
195   CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
196 
197   virtual void reset() override;
198 
199   void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override;
200 
201   void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *,
202                         const MCFixup &, MCValue, uint64_t &) override;
203 
204   uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override;
205 
206   static bool nameShouldBeInStringTable(const StringRef &);
207   void writeSymbolName(const StringRef &);
208   void writeSymbolTableEntryForCsectMemberLabel(const Symbol &,
209                                                 const ControlSection &, int16_t,
210                                                 uint64_t);
211   void writeSymbolTableEntryForControlSection(const ControlSection &, int16_t,
212                                               XCOFF::StorageClass);
213   void writeFileHeader();
214   void writeSectionHeaderTable();
215   void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
216   void writeSymbolTable(const MCAsmLayout &Layout);
217   void writeRelocations();
218   void writeRelocation(XCOFFRelocation Reloc, const ControlSection &CSection);
219 
220   // Called after all the csects and symbols have been processed by
221   // `executePostLayoutBinding`, this function handles building up the majority
222   // of the structures in the object file representation. Namely:
223   // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
224   //    sizes.
225   // *) Assigns symbol table indices.
226   // *) Builds up the section header table by adding any non-empty sections to
227   //    `Sections`.
228   void assignAddressesAndIndices(const MCAsmLayout &);
229   void finalizeSectionInfo();
230 
231   bool
232   needsAuxiliaryHeader() const { /* TODO aux header support not implemented. */
233     return false;
234   }
235 
236   // Returns the size of the auxiliary header to be written to the object file.
237   size_t auxiliaryHeaderSize() const {
238     assert(!needsAuxiliaryHeader() &&
239            "Auxiliary header support not implemented.");
240     return 0;
241   }
242 
243 public:
244   XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
245                     raw_pwrite_stream &OS);
246 };
247 
248 XCOFFObjectWriter::XCOFFObjectWriter(
249     std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
250     : W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
251       Strings(StringTableBuilder::XCOFF),
252       Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
253            CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
254       Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false,
255            CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
256       BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
257           CsectGroups{&BSSCsects}) {}
258 
259 void XCOFFObjectWriter::reset() {
260   // Clear the mappings we created.
261   SymbolIndexMap.clear();
262   SectionMap.clear();
263 
264   UndefinedCsects.clear();
265   // Reset any sections we have written to, and empty the section header table.
266   for (auto *Sec : Sections)
267     Sec->reset();
268 
269   // Reset states in XCOFFObjectWriter.
270   SymbolTableEntryCount = 0;
271   SymbolTableOffset = 0;
272   SectionCount = 0;
273   RelocationEntryOffset = 0;
274   Strings.clear();
275 
276   MCObjectWriter::reset();
277 }
278 
279 CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
280   switch (MCSec->getMappingClass()) {
281   case XCOFF::XMC_PR:
282     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
283            "Only an initialized csect can contain program code.");
284     return ProgramCodeCsects;
285   case XCOFF::XMC_RO:
286     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
287            "Only an initialized csect can contain read only data.");
288     return ReadOnlyCsects;
289   case XCOFF::XMC_RW:
290     if (XCOFF::XTY_CM == MCSec->getCSectType())
291       return BSSCsects;
292 
293     if (XCOFF::XTY_SD == MCSec->getCSectType())
294       return DataCsects;
295 
296     report_fatal_error("Unhandled mapping of read-write csect to section.");
297   case XCOFF::XMC_DS:
298     return FuncDSCsects;
299   case XCOFF::XMC_BS:
300     assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
301            "Mapping invalid csect. CSECT with bss storage class must be "
302            "common type.");
303     return BSSCsects;
304   case XCOFF::XMC_TC0:
305     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
306            "Only an initialized csect can contain TOC-base.");
307     assert(TOCCsects.empty() &&
308            "We should have only one TOC-base, and it should be the first csect "
309            "in this CsectGroup.");
310     return TOCCsects;
311   case XCOFF::XMC_TC:
312     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
313            "Only an initialized csect can contain TC entry.");
314     assert(!TOCCsects.empty() &&
315            "We should at least have a TOC-base in this CsectGroup.");
316     return TOCCsects;
317   default:
318     report_fatal_error("Unhandled mapping of csect to section.");
319   }
320 }
321 
322 static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) {
323   if (XSym->isDefined())
324     return cast<MCSectionXCOFF>(XSym->getFragment()->getParent());
325   return XSym->getRepresentedCsect();
326 }
327 
328 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
329                                                  const MCAsmLayout &Layout) {
330   if (TargetObjectWriter->is64Bit())
331     report_fatal_error("64-bit XCOFF object files are not supported yet.");
332 
333   for (const auto &S : Asm) {
334     const auto *MCSec = cast<const MCSectionXCOFF>(&S);
335     assert(SectionMap.find(MCSec) == SectionMap.end() &&
336            "Cannot add a csect twice.");
337     assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
338            "An undefined csect should not get registered.");
339 
340     // If the name does not fit in the storage provided in the symbol table
341     // entry, add it to the string table.
342     if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
343       Strings.add(MCSec->getSymbolTableName());
344 
345     CsectGroup &Group = getCsectGroup(MCSec);
346     Group.emplace_back(MCSec);
347     SectionMap[MCSec] = &Group.back();
348   }
349 
350   for (const MCSymbol &S : Asm.symbols()) {
351     // Nothing to do for temporary symbols.
352     if (S.isTemporary())
353       continue;
354 
355     const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
356     const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym);
357 
358     if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
359       // Handle undefined symbol.
360       UndefinedCsects.emplace_back(ContainingCsect);
361       SectionMap[ContainingCsect] = &UndefinedCsects.back();
362       if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName()))
363         Strings.add(ContainingCsect->getSymbolTableName());
364       continue;
365     }
366 
367     // If the symbol is the csect itself, we don't need to put the symbol
368     // into csect's Syms.
369     if (XSym == ContainingCsect->getQualNameSymbol())
370       continue;
371 
372     // Only put a label into the symbol table when it is an external label.
373     if (!XSym->isExternal())
374       continue;
375 
376     assert(SectionMap.find(ContainingCsect) != SectionMap.end() &&
377            "Expected containing csect to exist in map");
378     // Lookup the containing csect and add the symbol to it.
379     SectionMap[ContainingCsect]->Syms.emplace_back(XSym);
380 
381     // If the name does not fit in the storage provided in the symbol table
382     // entry, add it to the string table.
383     if (nameShouldBeInStringTable(XSym->getSymbolTableName()))
384       Strings.add(XSym->getSymbolTableName());
385   }
386 
387   Strings.finalize();
388   assignAddressesAndIndices(Layout);
389 }
390 
391 void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
392                                          const MCAsmLayout &Layout,
393                                          const MCFragment *Fragment,
394                                          const MCFixup &Fixup, MCValue Target,
395                                          uint64_t &FixedValue) {
396   auto getIndex = [this](const MCSymbol *Sym,
397                          const MCSectionXCOFF *ContainingCsect) {
398     // If we could not find the symbol directly in SymbolIndexMap, this symbol
399     // could either be a temporary symbol or an undefined symbol. In this case,
400     // we would need to have the relocation reference its csect instead.
401     return SymbolIndexMap.find(Sym) != SymbolIndexMap.end()
402                ? SymbolIndexMap[Sym]
403                : SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
404   };
405 
406   auto getVirtualAddress = [this,
407                             &Layout](const MCSymbol *Sym,
408                                      const MCSectionXCOFF *ContainingCsect) {
409     // If Sym is a csect, return csect's address.
410     // If Sym is a label, return csect's address + label's offset from the csect.
411     return SectionMap[ContainingCsect]->Address +
412            (Sym->isDefined() ? Layout.getSymbolOffset(*Sym) : 0);
413   };
414 
415   const MCSymbol *const SymA = &Target.getSymA()->getSymbol();
416 
417   MCAsmBackend &Backend = Asm.getBackend();
418   bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
419                  MCFixupKindInfo::FKF_IsPCRel;
420 
421   uint8_t Type;
422   uint8_t SignAndSize;
423   std::tie(Type, SignAndSize) =
424       TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel);
425 
426   const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
427   assert(SectionMap.find(SymASec) != SectionMap.end() &&
428          "Expected containing csect to exist in map.");
429 
430   const uint32_t Index = getIndex(SymA, SymASec);
431   if (Type == XCOFF::RelocationType::R_POS)
432     // The FixedValue should be symbol's virtual address in this object file
433     // plus any constant value that we might get.
434     FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
435   else if (Type == XCOFF::RelocationType::R_TOC)
436     // The FixedValue should be the TC entry offset from TOC-base.
437     FixedValue = SectionMap[SymASec]->Address - TOCCsects.front().Address;
438 
439   assert(
440       (TargetObjectWriter->is64Bit() ||
441        Fixup.getOffset() <= UINT32_MAX - Layout.getFragmentOffset(Fragment)) &&
442       "Fragment offset + fixup offset is overflowed in 32-bit mode.");
443   uint32_t FixupOffsetInCsect =
444       Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
445 
446   XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
447   MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent());
448   assert(SectionMap.find(RelocationSec) != SectionMap.end() &&
449          "Expected containing csect to exist in map.");
450   SectionMap[RelocationSec]->Relocations.push_back(Reloc);
451 
452   if (!Target.getSymB())
453     return;
454 
455   const MCSymbol *const SymB = &Target.getSymB()->getSymbol();
456   if (SymA == SymB)
457     report_fatal_error("relocation for opposite term is not yet supported");
458 
459   const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
460   assert(SectionMap.find(SymBSec) != SectionMap.end() &&
461          "Expected containing csect to exist in map.");
462   if (SymASec == SymBSec)
463     report_fatal_error(
464         "relocation for paired relocatable term is not yet supported");
465 
466   assert(Type == XCOFF::RelocationType::R_POS &&
467          "SymA must be R_POS here if it's not opposite term or paired "
468          "relocatable term.");
469   const uint32_t IndexB = getIndex(SymB, SymBSec);
470   // SymB must be R_NEG here, given the general form of Target(MCValue) is
471   // "SymbolA - SymbolB + imm64".
472   const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
473   XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
474   SectionMap[RelocationSec]->Relocations.push_back(RelocB);
475   // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
476   // now we just need to fold "- SymbolB" here.
477   FixedValue -= getVirtualAddress(SymB, SymBSec);
478 }
479 
480 void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
481                                       const MCAsmLayout &Layout) {
482   uint32_t CurrentAddressLocation = 0;
483   for (const auto *Section : Sections) {
484     // Nothing to write for this Section.
485     if (Section->Index == Section::UninitializedIndex || Section->IsVirtual)
486       continue;
487 
488     // There could be a gap (without corresponding zero padding) between
489     // sections.
490     assert(CurrentAddressLocation <= Section->Address &&
491            "CurrentAddressLocation should be less than or equal to section "
492            "address.");
493 
494     CurrentAddressLocation = Section->Address;
495 
496     for (const auto *Group : Section->Groups) {
497       for (const auto &Csect : *Group) {
498         if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
499           W.OS.write_zeros(PaddingSize);
500         if (Csect.Size)
501           Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
502         CurrentAddressLocation = Csect.Address + Csect.Size;
503       }
504     }
505 
506     // The size of the tail padding in a section is the end virtual address of
507     // the current section minus the the end virtual address of the last csect
508     // in that section.
509     if (uint32_t PaddingSize =
510             Section->Address + Section->Size - CurrentAddressLocation) {
511       W.OS.write_zeros(PaddingSize);
512       CurrentAddressLocation += PaddingSize;
513     }
514   }
515 }
516 
517 uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
518                                         const MCAsmLayout &Layout) {
519   // We always emit a timestamp of 0 for reproducibility, so ensure incremental
520   // linking is not enabled, in case, like with Windows COFF, such a timestamp
521   // is incompatible with incremental linking of XCOFF.
522   if (Asm.isIncrementalLinkerCompatible())
523     report_fatal_error("Incremental linking not supported for XCOFF.");
524 
525   if (TargetObjectWriter->is64Bit())
526     report_fatal_error("64-bit XCOFF object files are not supported yet.");
527 
528   finalizeSectionInfo();
529   uint64_t StartOffset = W.OS.tell();
530 
531   writeFileHeader();
532   writeSectionHeaderTable();
533   writeSections(Asm, Layout);
534   writeRelocations();
535 
536   writeSymbolTable(Layout);
537   // Write the string table.
538   Strings.write(W.OS);
539 
540   return W.OS.tell() - StartOffset;
541 }
542 
543 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
544   return SymbolName.size() > XCOFF::NameSize;
545 }
546 
547 void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) {
548   if (nameShouldBeInStringTable(SymbolName)) {
549     W.write<int32_t>(0);
550     W.write<uint32_t>(Strings.getOffset(SymbolName));
551   } else {
552     char Name[XCOFF::NameSize+1];
553     std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
554     ArrayRef<char> NameRef(Name, XCOFF::NameSize);
555     W.write(NameRef);
556   }
557 }
558 
559 void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel(
560     const Symbol &SymbolRef, const ControlSection &CSectionRef,
561     int16_t SectionIndex, uint64_t SymbolOffset) {
562   // Name or Zeros and string table offset
563   writeSymbolName(SymbolRef.getSymbolTableName());
564   assert(SymbolOffset <= UINT32_MAX - CSectionRef.Address &&
565          "Symbol address overflows.");
566   W.write<uint32_t>(CSectionRef.Address + SymbolOffset);
567   W.write<int16_t>(SectionIndex);
568   // Basic/Derived type. See the description of the n_type field for symbol
569   // table entries for a detailed description. Since we support visibility, and
570   // all other bits are either optionally set or reserved, we only set bits 0-3
571   // for symbol's visibility and leave other bits to zero.
572   // TODO Set the function indicator (bit 10, 0x0020) for functions
573   // when debugging is enabled.
574   W.write<uint16_t>(SymbolRef.getVisibilityType());
575   W.write<uint8_t>(SymbolRef.getStorageClass());
576   // Always 1 aux entry for now.
577   W.write<uint8_t>(1);
578 
579   // Now output the auxiliary entry.
580   W.write<uint32_t>(CSectionRef.SymbolTableIndex);
581   // Parameter typecheck hash. Not supported.
582   W.write<uint32_t>(0);
583   // Typecheck section number. Not supported.
584   W.write<uint16_t>(0);
585   // Symbol type: Label
586   W.write<uint8_t>(XCOFF::XTY_LD);
587   // Storage mapping class.
588   W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass());
589   // Reserved (x_stab).
590   W.write<uint32_t>(0);
591   // Reserved (x_snstab).
592   W.write<uint16_t>(0);
593 }
594 
595 void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
596     const ControlSection &CSectionRef, int16_t SectionIndex,
597     XCOFF::StorageClass StorageClass) {
598   // n_name, n_zeros, n_offset
599   writeSymbolName(CSectionRef.getSymbolTableName());
600   // n_value
601   W.write<uint32_t>(CSectionRef.Address);
602   // n_scnum
603   W.write<int16_t>(SectionIndex);
604   // Basic/Derived type. See the description of the n_type field for symbol
605   // table entries for a detailed description. Since we support visibility, and
606   // all other bits are either optionally set or reserved, we only set bits 0-3
607   // for symbol's visibility and leave other bits to zero.
608   // TODO Set the function indicator (bit 10, 0x0020) for functions
609   // when debugging is enabled.
610   W.write<uint16_t>(CSectionRef.MCCsect->getVisibilityType());
611   // n_sclass
612   W.write<uint8_t>(StorageClass);
613   // Always 1 aux entry for now.
614   W.write<uint8_t>(1);
615 
616   // Now output the auxiliary entry.
617   W.write<uint32_t>(CSectionRef.Size);
618   // Parameter typecheck hash. Not supported.
619   W.write<uint32_t>(0);
620   // Typecheck section number. Not supported.
621   W.write<uint16_t>(0);
622   // Symbol type.
623   W.write<uint8_t>(getEncodedType(CSectionRef.MCCsect));
624   // Storage mapping class.
625   W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass());
626   // Reserved (x_stab).
627   W.write<uint32_t>(0);
628   // Reserved (x_snstab).
629   W.write<uint16_t>(0);
630 }
631 
632 void XCOFFObjectWriter::writeFileHeader() {
633   // Magic.
634   W.write<uint16_t>(0x01df);
635   // Number of sections.
636   W.write<uint16_t>(SectionCount);
637   // Timestamp field. For reproducible output we write a 0, which represents no
638   // timestamp.
639   W.write<int32_t>(0);
640   // Byte Offset to the start of the symbol table.
641   W.write<uint32_t>(SymbolTableOffset);
642   // Number of entries in the symbol table.
643   W.write<int32_t>(SymbolTableEntryCount);
644   // Size of the optional header.
645   W.write<uint16_t>(0);
646   // Flags.
647   W.write<uint16_t>(0);
648 }
649 
650 void XCOFFObjectWriter::writeSectionHeaderTable() {
651   for (const auto *Sec : Sections) {
652     // Nothing to write for this Section.
653     if (Sec->Index == Section::UninitializedIndex)
654       continue;
655 
656     // Write Name.
657     ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
658     W.write(NameRef);
659 
660     // Write the Physical Address and Virtual Address. In an object file these
661     // are the same.
662     W.write<uint32_t>(Sec->Address);
663     W.write<uint32_t>(Sec->Address);
664 
665     W.write<uint32_t>(Sec->Size);
666     W.write<uint32_t>(Sec->FileOffsetToData);
667     W.write<uint32_t>(Sec->FileOffsetToRelocations);
668 
669     // Line number pointer. Not supported yet.
670     W.write<uint32_t>(0);
671 
672     W.write<uint16_t>(Sec->RelocationCount);
673 
674     // Line number counts. Not supported yet.
675     W.write<uint16_t>(0);
676 
677     W.write<int32_t>(Sec->Flags);
678   }
679 }
680 
681 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
682                                         const ControlSection &CSection) {
683   W.write<uint32_t>(CSection.Address + Reloc.FixupOffsetInCsect);
684   W.write<uint32_t>(Reloc.SymbolTableIndex);
685   W.write<uint8_t>(Reloc.SignAndSize);
686   W.write<uint8_t>(Reloc.Type);
687 }
688 
689 void XCOFFObjectWriter::writeRelocations() {
690   for (const auto *Section : Sections) {
691     if (Section->Index == Section::UninitializedIndex)
692       // Nothing to write for this Section.
693       continue;
694 
695     for (const auto *Group : Section->Groups) {
696       if (Group->empty())
697         continue;
698 
699       for (const auto &Csect : *Group) {
700         for (const auto Reloc : Csect.Relocations)
701           writeRelocation(Reloc, Csect);
702       }
703     }
704   }
705 }
706 
707 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
708   for (const auto &Csect : UndefinedCsects) {
709     writeSymbolTableEntryForControlSection(
710         Csect, XCOFF::ReservedSectionNum::N_UNDEF, Csect.MCCsect->getStorageClass());
711   }
712 
713   for (const auto *Section : Sections) {
714     if (Section->Index == Section::UninitializedIndex)
715       // Nothing to write for this Section.
716       continue;
717 
718     for (const auto *Group : Section->Groups) {
719       if (Group->empty())
720         continue;
721 
722       const int16_t SectionIndex = Section->Index;
723       for (const auto &Csect : *Group) {
724         // Write out the control section first and then each symbol in it.
725         writeSymbolTableEntryForControlSection(
726             Csect, SectionIndex, Csect.MCCsect->getStorageClass());
727 
728         for (const auto &Sym : Csect.Syms)
729           writeSymbolTableEntryForCsectMemberLabel(
730               Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
731       }
732     }
733   }
734 }
735 
736 void XCOFFObjectWriter::finalizeSectionInfo() {
737   for (auto *Section : Sections) {
738     if (Section->Index == Section::UninitializedIndex)
739       // Nothing to record for this Section.
740       continue;
741 
742     for (const auto *Group : Section->Groups) {
743       if (Group->empty())
744         continue;
745 
746       for (auto &Csect : *Group) {
747         const size_t CsectRelocCount = Csect.Relocations.size();
748         if (CsectRelocCount >= XCOFF::RelocOverflow ||
749             Section->RelocationCount >= XCOFF::RelocOverflow - CsectRelocCount)
750           report_fatal_error(
751               "relocation entries overflowed; overflow section is "
752               "not implemented yet");
753 
754         Section->RelocationCount += CsectRelocCount;
755       }
756     }
757   }
758 
759   // Calculate the file offset to the relocation entries.
760   uint64_t RawPointer = RelocationEntryOffset;
761   for (auto Sec : Sections) {
762     if (Sec->Index == Section::UninitializedIndex || !Sec->RelocationCount)
763       continue;
764 
765     Sec->FileOffsetToRelocations = RawPointer;
766     const uint32_t RelocationSizeInSec =
767         Sec->RelocationCount * XCOFF::RelocationSerializationSize32;
768     RawPointer += RelocationSizeInSec;
769     if (RawPointer > UINT32_MAX)
770       report_fatal_error("Relocation data overflowed this object file.");
771   }
772 
773   // TODO Error check that the number of symbol table entries fits in 32-bits
774   // signed ...
775   if (SymbolTableEntryCount)
776     SymbolTableOffset = RawPointer;
777 }
778 
779 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
780   // The first symbol table entry is for the file name. We are not emitting it
781   // yet, so start at index 0.
782   uint32_t SymbolTableIndex = 0;
783 
784   // Calculate indices for undefined symbols.
785   for (auto &Csect : UndefinedCsects) {
786     Csect.Size = 0;
787     Csect.Address = 0;
788     Csect.SymbolTableIndex = SymbolTableIndex;
789     SymbolIndexMap[Csect.MCCsect->getQualNameSymbol()] = Csect.SymbolTableIndex;
790     // 1 main and 1 auxiliary symbol table entry for each contained symbol.
791     SymbolTableIndex += 2;
792   }
793 
794   // The address corrresponds to the address of sections and symbols in the
795   // object file. We place the shared address 0 immediately after the
796   // section header table.
797   uint32_t Address = 0;
798   // Section indices are 1-based in XCOFF.
799   int32_t SectionIndex = 1;
800 
801   for (auto *Section : Sections) {
802     const bool IsEmpty =
803         llvm::all_of(Section->Groups,
804                      [](const CsectGroup *Group) { return Group->empty(); });
805     if (IsEmpty)
806       continue;
807 
808     if (SectionIndex > MaxSectionIndex)
809       report_fatal_error("Section index overflow!");
810     Section->Index = SectionIndex++;
811     SectionCount++;
812 
813     bool SectionAddressSet = false;
814     for (auto *Group : Section->Groups) {
815       if (Group->empty())
816         continue;
817 
818       for (auto &Csect : *Group) {
819         const MCSectionXCOFF *MCSec = Csect.MCCsect;
820         Csect.Address = alignTo(Address, MCSec->getAlignment());
821         Csect.Size = Layout.getSectionAddressSize(MCSec);
822         Address = Csect.Address + Csect.Size;
823         Csect.SymbolTableIndex = SymbolTableIndex;
824         SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
825         // 1 main and 1 auxiliary symbol table entry for the csect.
826         SymbolTableIndex += 2;
827 
828         for (auto &Sym : Csect.Syms) {
829           Sym.SymbolTableIndex = SymbolTableIndex;
830           SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
831           // 1 main and 1 auxiliary symbol table entry for each contained
832           // symbol.
833           SymbolTableIndex += 2;
834         }
835       }
836 
837       if (!SectionAddressSet) {
838         Section->Address = Group->front().Address;
839         SectionAddressSet = true;
840       }
841     }
842 
843     // Make sure the address of the next section aligned to
844     // DefaultSectionAlign.
845     Address = alignTo(Address, DefaultSectionAlign);
846     Section->Size = Address - Section->Address;
847   }
848 
849   SymbolTableEntryCount = SymbolTableIndex;
850 
851   // Calculate the RawPointer value for each section.
852   uint64_t RawPointer = sizeof(XCOFF::FileHeader32) + auxiliaryHeaderSize() +
853                         SectionCount * sizeof(XCOFF::SectionHeader32);
854   for (auto *Sec : Sections) {
855     if (Sec->Index == Section::UninitializedIndex || Sec->IsVirtual)
856       continue;
857 
858     Sec->FileOffsetToData = RawPointer;
859     RawPointer += Sec->Size;
860     if (RawPointer > UINT32_MAX)
861       report_fatal_error("Section raw data overflowed this object file.");
862   }
863 
864   RelocationEntryOffset = RawPointer;
865 }
866 
867 // Takes the log base 2 of the alignment and shifts the result into the 5 most
868 // significant bits of a byte, then or's in the csect type into the least
869 // significant 3 bits.
870 uint8_t getEncodedType(const MCSectionXCOFF *Sec) {
871   unsigned Align = Sec->getAlignment();
872   assert(isPowerOf2_32(Align) && "Alignment must be a power of 2.");
873   unsigned Log2Align = Log2_32(Align);
874   // Result is a number in the range [0, 31] which fits in the 5 least
875   // significant bits. Shift this value into the 5 most significant bits, and
876   // bitwise-or in the csect type.
877   uint8_t EncodedAlign = Log2Align << 3;
878   return EncodedAlign | Sec->getCSectType();
879 }
880 
881 } // end anonymous namespace
882 
883 std::unique_ptr<MCObjectWriter>
884 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
885                               raw_pwrite_stream &OS) {
886   return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);
887 }
888