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