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