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