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     // Handle undefined symbol.
347     if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
348       UndefinedCsects.emplace_back(ContainingCsect);
349       SectionMap[ContainingCsect] = &UndefinedCsects.back();
350       continue;
351     }
352 
353     // If the symbol is the csect itself, we don't need to put the symbol
354     // into csect's Syms.
355     if (XSym == ContainingCsect->getQualNameSymbol())
356       continue;
357 
358     assert(SectionMap.find(ContainingCsect) != SectionMap.end() &&
359            "Expected containing csect to exist in map");
360 
361     // Lookup the containing csect and add the symbol to it.
362     SectionMap[ContainingCsect]->Syms.emplace_back(XSym);
363 
364     // If the name does not fit in the storage provided in the symbol table
365     // entry, add it to the string table.
366     if (nameShouldBeInStringTable(XSym->getName()))
367       Strings.add(XSym->getName());
368     }
369 
370   Strings.finalize();
371   assignAddressesAndIndices(Layout);
372 }
373 
374 void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
375                                          const MCAsmLayout &Layout,
376                                          const MCFragment *Fragment,
377                                          const MCFixup &Fixup, MCValue Target,
378                                          uint64_t &FixedValue) {
379 
380   if (Target.getSymB())
381     report_fatal_error("Handling Target.SymB for relocation is unimplemented.");
382 
383   const MCSymbol &SymA = Target.getSymA()->getSymbol();
384 
385   MCAsmBackend &Backend = Asm.getBackend();
386   bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
387                  MCFixupKindInfo::FKF_IsPCRel;
388 
389   uint8_t Type;
390   uint8_t SignAndSize;
391   std::tie(Type, SignAndSize) =
392       TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel);
393 
394   const MCSectionXCOFF *SymASec =
395       cast<MCSymbolXCOFF>(SymA).getContainingCsect();
396   assert(SectionMap.find(SymASec) != SectionMap.end() &&
397          "Expected containing csect to exist in map.");
398 
399   // If we could not find SymA directly in SymbolIndexMap, this symbol could
400   // either be a temporary symbol or an undefined symbol. In this case, we
401   // would need to have the relocation reference its csect instead.
402   uint32_t Index = SymbolIndexMap.find(&SymA) != SymbolIndexMap.end()
403                        ? SymbolIndexMap[&SymA]
404                        : SymbolIndexMap[SymASec->getQualNameSymbol()];
405 
406   if (Type == XCOFF::RelocationType::R_POS)
407     // The FixedValue should be symbol's virtual address in this object file
408     // plus any constant value that we might get.
409     // Notice that SymA.isDefined() could return false, but SymASec could still
410     // be a defined csect. One of the example is the TOC-base symbol.
411     FixedValue = SectionMap[SymASec]->Address +
412                  (SymA.isDefined() ? Layout.getSymbolOffset(SymA) : 0) +
413                  Target.getConstant();
414   else if (Type == XCOFF::RelocationType::R_TOC)
415     // The FixedValue should be the TC entry offset from TOC-base.
416     FixedValue = SectionMap[SymASec]->Address - TOCCsects.front().Address;
417 
418   assert(
419       (TargetObjectWriter->is64Bit() ||
420        Fixup.getOffset() <= UINT32_MAX - Layout.getFragmentOffset(Fragment)) &&
421       "Fragment offset + fixup offset is overflowed in 32-bit mode.");
422   uint32_t FixupOffsetInCsect =
423       Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
424 
425   XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
426   MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent());
427   assert(SectionMap.find(RelocationSec) != SectionMap.end() &&
428          "Expected containing csect to exist in map.");
429   SectionMap[RelocationSec]->Relocations.push_back(Reloc);
430 }
431 
432 void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
433                                       const MCAsmLayout &Layout) {
434   uint32_t CurrentAddressLocation = 0;
435   for (const auto *Section : Sections) {
436     // Nothing to write for this Section.
437     if (Section->Index == Section::UninitializedIndex || Section->IsVirtual)
438       continue;
439 
440     assert(CurrentAddressLocation == Section->Address &&
441            "Sections should be written consecutively.");
442     for (const auto *Group : Section->Groups) {
443       for (const auto &Csect : *Group) {
444         if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
445           W.OS.write_zeros(PaddingSize);
446         if (Csect.Size)
447           Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
448         CurrentAddressLocation = Csect.Address + Csect.Size;
449       }
450     }
451 
452     // The size of the tail padding in a section is the end virtual address of
453     // the current section minus the the end virtual address of the last csect
454     // in that section.
455     if (uint32_t PaddingSize =
456             Section->Address + Section->Size - CurrentAddressLocation) {
457       W.OS.write_zeros(PaddingSize);
458       CurrentAddressLocation += PaddingSize;
459     }
460   }
461 }
462 
463 uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
464                                         const MCAsmLayout &Layout) {
465   // We always emit a timestamp of 0 for reproducibility, so ensure incremental
466   // linking is not enabled, in case, like with Windows COFF, such a timestamp
467   // is incompatible with incremental linking of XCOFF.
468   if (Asm.isIncrementalLinkerCompatible())
469     report_fatal_error("Incremental linking not supported for XCOFF.");
470 
471   if (TargetObjectWriter->is64Bit())
472     report_fatal_error("64-bit XCOFF object files are not supported yet.");
473 
474   finalizeSectionInfo();
475   uint64_t StartOffset = W.OS.tell();
476 
477   writeFileHeader();
478   writeSectionHeaderTable();
479   writeSections(Asm, Layout);
480   writeRelocations();
481 
482   writeSymbolTable(Layout);
483   // Write the string table.
484   Strings.write(W.OS);
485 
486   return W.OS.tell() - StartOffset;
487 }
488 
489 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
490   return SymbolName.size() > XCOFF::NameSize;
491 }
492 
493 void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) {
494   if (nameShouldBeInStringTable(SymbolName)) {
495     W.write<int32_t>(0);
496     W.write<uint32_t>(Strings.getOffset(SymbolName));
497   } else {
498     char Name[XCOFF::NameSize+1];
499     std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
500     ArrayRef<char> NameRef(Name, XCOFF::NameSize);
501     W.write(NameRef);
502   }
503 }
504 
505 void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel(
506     const Symbol &SymbolRef, const ControlSection &CSectionRef,
507     int16_t SectionIndex, uint64_t SymbolOffset) {
508   // Name or Zeros and string table offset
509   writeSymbolName(SymbolRef.getName());
510   assert(SymbolOffset <= UINT32_MAX - CSectionRef.Address &&
511          "Symbol address overflows.");
512   W.write<uint32_t>(CSectionRef.Address + SymbolOffset);
513   W.write<int16_t>(SectionIndex);
514   // Basic/Derived type. See the description of the n_type field for symbol
515   // table entries for a detailed description. Since we don't yet support
516   // visibility, and all other bits are either optionally set or reserved, this
517   // is always zero.
518   // TODO FIXME How to assert a symbol's visibilty is default?
519   // TODO Set the function indicator (bit 10, 0x0020) for functions
520   // when debugging is enabled.
521   W.write<uint16_t>(0);
522   W.write<uint8_t>(SymbolRef.getStorageClass());
523   // Always 1 aux entry for now.
524   W.write<uint8_t>(1);
525 
526   // Now output the auxiliary entry.
527   W.write<uint32_t>(CSectionRef.SymbolTableIndex);
528   // Parameter typecheck hash. Not supported.
529   W.write<uint32_t>(0);
530   // Typecheck section number. Not supported.
531   W.write<uint16_t>(0);
532   // Symbol type: Label
533   W.write<uint8_t>(XCOFF::XTY_LD);
534   // Storage mapping class.
535   W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass());
536   // Reserved (x_stab).
537   W.write<uint32_t>(0);
538   // Reserved (x_snstab).
539   W.write<uint16_t>(0);
540 }
541 
542 void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
543     const ControlSection &CSectionRef, int16_t SectionIndex,
544     XCOFF::StorageClass StorageClass) {
545   // n_name, n_zeros, n_offset
546   writeSymbolName(CSectionRef.getName());
547   // n_value
548   W.write<uint32_t>(CSectionRef.Address);
549   // n_scnum
550   W.write<int16_t>(SectionIndex);
551   // Basic/Derived type. See the description of the n_type field for symbol
552   // table entries for a detailed description. Since we don't yet support
553   // visibility, and all other bits are either optionally set or reserved, this
554   // is always zero.
555   // TODO FIXME How to assert a symbol's visibilty is default?
556   // TODO Set the function indicator (bit 10, 0x0020) for functions
557   // when debugging is enabled.
558   W.write<uint16_t>(0);
559   // n_sclass
560   W.write<uint8_t>(StorageClass);
561   // Always 1 aux entry for now.
562   W.write<uint8_t>(1);
563 
564   // Now output the auxiliary entry.
565   W.write<uint32_t>(CSectionRef.Size);
566   // Parameter typecheck hash. Not supported.
567   W.write<uint32_t>(0);
568   // Typecheck section number. Not supported.
569   W.write<uint16_t>(0);
570   // Symbol type.
571   W.write<uint8_t>(getEncodedType(CSectionRef.MCCsect));
572   // Storage mapping class.
573   W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass());
574   // Reserved (x_stab).
575   W.write<uint32_t>(0);
576   // Reserved (x_snstab).
577   W.write<uint16_t>(0);
578 }
579 
580 void XCOFFObjectWriter::writeFileHeader() {
581   // Magic.
582   W.write<uint16_t>(0x01df);
583   // Number of sections.
584   W.write<uint16_t>(SectionCount);
585   // Timestamp field. For reproducible output we write a 0, which represents no
586   // timestamp.
587   W.write<int32_t>(0);
588   // Byte Offset to the start of the symbol table.
589   W.write<uint32_t>(SymbolTableOffset);
590   // Number of entries in the symbol table.
591   W.write<int32_t>(SymbolTableEntryCount);
592   // Size of the optional header.
593   W.write<uint16_t>(0);
594   // Flags.
595   W.write<uint16_t>(0);
596 }
597 
598 void XCOFFObjectWriter::writeSectionHeaderTable() {
599   for (const auto *Sec : Sections) {
600     // Nothing to write for this Section.
601     if (Sec->Index == Section::UninitializedIndex)
602       continue;
603 
604     // Write Name.
605     ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
606     W.write(NameRef);
607 
608     // Write the Physical Address and Virtual Address. In an object file these
609     // are the same.
610     W.write<uint32_t>(Sec->Address);
611     W.write<uint32_t>(Sec->Address);
612 
613     W.write<uint32_t>(Sec->Size);
614     W.write<uint32_t>(Sec->FileOffsetToData);
615     W.write<uint32_t>(Sec->FileOffsetToRelocations);
616 
617     // Line number pointer. Not supported yet.
618     W.write<uint32_t>(0);
619 
620     W.write<uint16_t>(Sec->RelocationCount);
621 
622     // Line number counts. Not supported yet.
623     W.write<uint16_t>(0);
624 
625     W.write<int32_t>(Sec->Flags);
626   }
627 }
628 
629 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
630                                         const ControlSection &CSection) {
631   W.write<uint32_t>(CSection.Address + Reloc.FixupOffsetInCsect);
632   W.write<uint32_t>(Reloc.SymbolTableIndex);
633   W.write<uint8_t>(Reloc.SignAndSize);
634   W.write<uint8_t>(Reloc.Type);
635 }
636 
637 void XCOFFObjectWriter::writeRelocations() {
638   for (const auto *Section : Sections) {
639     if (Section->Index == Section::UninitializedIndex)
640       // Nothing to write for this Section.
641       continue;
642 
643     for (const auto *Group : Section->Groups) {
644       if (Group->empty())
645         continue;
646 
647       for (const auto &Csect : *Group) {
648         for (const auto Reloc : Csect.Relocations)
649           writeRelocation(Reloc, Csect);
650       }
651     }
652   }
653 }
654 
655 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
656   for (const auto &Csect : UndefinedCsects) {
657     writeSymbolTableEntryForControlSection(
658         Csect, XCOFF::ReservedSectionNum::N_UNDEF, Csect.MCCsect->getStorageClass());
659   }
660 
661   for (const auto *Section : Sections) {
662     if (Section->Index == Section::UninitializedIndex)
663       // Nothing to write for this Section.
664       continue;
665 
666     for (const auto *Group : Section->Groups) {
667       if (Group->empty())
668         continue;
669 
670       const int16_t SectionIndex = Section->Index;
671       for (const auto &Csect : *Group) {
672         // Write out the control section first and then each symbol in it.
673         writeSymbolTableEntryForControlSection(
674             Csect, SectionIndex, Csect.MCCsect->getStorageClass());
675 
676         for (const auto &Sym : Csect.Syms)
677           writeSymbolTableEntryForCsectMemberLabel(
678               Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
679       }
680     }
681   }
682 }
683 
684 void XCOFFObjectWriter::finalizeSectionInfo() {
685   for (auto *Section : Sections) {
686     if (Section->Index == Section::UninitializedIndex)
687       // Nothing to record for this Section.
688       continue;
689 
690     for (const auto *Group : Section->Groups) {
691       if (Group->empty())
692         continue;
693 
694       for (auto &Csect : *Group)
695         Section->RelocationCount += Csect.Relocations.size();
696     }
697   }
698 
699   // Calculate the file offset to the relocation entries.
700   uint64_t RawPointer = RelocationEntryOffset;
701   for (auto Sec : Sections) {
702     if (Sec->Index == Section::UninitializedIndex || !Sec->RelocationCount)
703       continue;
704 
705     Sec->FileOffsetToRelocations = RawPointer;
706     const uint32_t RelocationSizeInSec =
707         Sec->RelocationCount * XCOFF::RelocationSerializationSize32;
708     RawPointer += RelocationSizeInSec;
709     if (RawPointer > UINT32_MAX)
710       report_fatal_error("Relocation data overflowed this object file.");
711   }
712 
713   // TODO Error check that the number of symbol table entries fits in 32-bits
714   // signed ...
715   if (SymbolTableEntryCount)
716     SymbolTableOffset = RawPointer;
717 }
718 
719 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
720   // The first symbol table entry is for the file name. We are not emitting it
721   // yet, so start at index 0.
722   uint32_t SymbolTableIndex = 0;
723 
724   // Calculate indices for undefined symbols.
725   for (auto &Csect : UndefinedCsects) {
726     Csect.Size = 0;
727     Csect.Address = 0;
728     Csect.SymbolTableIndex = SymbolTableIndex;
729     SymbolIndexMap[Csect.MCCsect->getQualNameSymbol()] = Csect.SymbolTableIndex;
730     // 1 main and 1 auxiliary symbol table entry for each contained symbol.
731     SymbolTableIndex += 2;
732   }
733 
734   // The address corrresponds to the address of sections and symbols in the
735   // object file. We place the shared address 0 immediately after the
736   // section header table.
737   uint32_t Address = 0;
738   // Section indices are 1-based in XCOFF.
739   int32_t SectionIndex = 1;
740 
741   for (auto *Section : Sections) {
742     const bool IsEmpty =
743         llvm::all_of(Section->Groups,
744                      [](const CsectGroup *Group) { return Group->empty(); });
745     if (IsEmpty)
746       continue;
747 
748     if (SectionIndex > MaxSectionIndex)
749       report_fatal_error("Section index overflow!");
750     Section->Index = SectionIndex++;
751     SectionCount++;
752 
753     bool SectionAddressSet = false;
754     for (auto *Group : Section->Groups) {
755       if (Group->empty())
756         continue;
757 
758       for (auto &Csect : *Group) {
759         const MCSectionXCOFF *MCSec = Csect.MCCsect;
760         Csect.Address = alignTo(Address, MCSec->getAlignment());
761         Csect.Size = Layout.getSectionAddressSize(MCSec);
762         Address = Csect.Address + Csect.Size;
763         Csect.SymbolTableIndex = SymbolTableIndex;
764         SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
765         // 1 main and 1 auxiliary symbol table entry for the csect.
766         SymbolTableIndex += 2;
767 
768         for (auto &Sym : Csect.Syms) {
769           Sym.SymbolTableIndex = SymbolTableIndex;
770           SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
771           // 1 main and 1 auxiliary symbol table entry for each contained
772           // symbol.
773           SymbolTableIndex += 2;
774         }
775       }
776 
777       if (!SectionAddressSet) {
778         Section->Address = Group->front().Address;
779         SectionAddressSet = true;
780       }
781     }
782 
783     // Make sure the address of the next section aligned to
784     // DefaultSectionAlign.
785     Address = alignTo(Address, DefaultSectionAlign);
786     Section->Size = Address - Section->Address;
787   }
788 
789   SymbolTableEntryCount = SymbolTableIndex;
790 
791   // Calculate the RawPointer value for each section.
792   uint64_t RawPointer = sizeof(XCOFF::FileHeader32) + auxiliaryHeaderSize() +
793                         SectionCount * sizeof(XCOFF::SectionHeader32);
794   for (auto *Sec : Sections) {
795     if (Sec->Index == Section::UninitializedIndex || Sec->IsVirtual)
796       continue;
797 
798     Sec->FileOffsetToData = RawPointer;
799     RawPointer += Sec->Size;
800     if (RawPointer > UINT32_MAX)
801       report_fatal_error("Section raw data overflowed this object file.");
802   }
803 
804   RelocationEntryOffset = RawPointer;
805 }
806 
807 // Takes the log base 2 of the alignment and shifts the result into the 5 most
808 // significant bits of a byte, then or's in the csect type into the least
809 // significant 3 bits.
810 uint8_t getEncodedType(const MCSectionXCOFF *Sec) {
811   unsigned Align = Sec->getAlignment();
812   assert(isPowerOf2_32(Align) && "Alignment must be a power of 2.");
813   unsigned Log2Align = Log2_32(Align);
814   // Result is a number in the range [0, 31] which fits in the 5 least
815   // significant bits. Shift this value into the 5 most significant bits, and
816   // bitwise-or in the csect type.
817   uint8_t EncodedAlign = Log2Align << 3;
818   return EncodedAlign | Sec->getCSectType();
819 }
820 
821 } // end anonymous namespace
822 
823 std::unique_ptr<MCObjectWriter>
824 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
825                               raw_pwrite_stream &OS) {
826   return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);
827 }
828