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