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