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