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