xref: /freebsd/contrib/llvm-project/llvm/lib/MC/XCOFFObjectWriter.cpp (revision 7ef62cebc2f965b0f640263e179276928885e33d)
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/Casting.h"
26 #include "llvm/Support/EndianStream.h"
27 #include "llvm/Support/ErrorHandling.h"
28 #include "llvm/Support/MathExtras.h"
29 
30 #include <deque>
31 #include <map>
32 
33 using namespace llvm;
34 
35 // An XCOFF object file has a limited set of predefined sections. The most
36 // important ones for us (right now) are:
37 // .text --> contains program code and read-only data.
38 // .data --> contains initialized data, function descriptors, and the TOC.
39 // .bss  --> contains uninitialized data.
40 // Each of these sections is composed of 'Control Sections'. A Control Section
41 // is more commonly referred to as a csect. A csect is an indivisible unit of
42 // code or data, and acts as a container for symbols. A csect is mapped
43 // into a section based on its storage-mapping class, with the exception of
44 // XMC_RW which gets mapped to either .data or .bss based on whether it's
45 // explicitly initialized or not.
46 //
47 // We don't represent the sections in the MC layer as there is nothing
48 // interesting about them at at that level: they carry information that is
49 // only relevant to the ObjectWriter, so we materialize them in this class.
50 namespace {
51 
52 constexpr unsigned DefaultSectionAlign = 4;
53 constexpr int16_t MaxSectionIndex = INT16_MAX;
54 
55 // Packs the csect's alignment and type into a byte.
56 uint8_t getEncodedType(const MCSectionXCOFF *);
57 
58 struct XCOFFRelocation {
59   uint32_t SymbolTableIndex;
60   uint32_t FixupOffsetInCsect;
61   uint8_t SignAndSize;
62   uint8_t Type;
63 };
64 
65 // Wrapper around an MCSymbolXCOFF.
66 struct Symbol {
67   const MCSymbolXCOFF *const MCSym;
68   uint32_t SymbolTableIndex;
69 
70   XCOFF::VisibilityType getVisibilityType() const {
71     return MCSym->getVisibilityType();
72   }
73 
74   XCOFF::StorageClass getStorageClass() const {
75     return MCSym->getStorageClass();
76   }
77   StringRef getSymbolTableName() const { return MCSym->getSymbolTableName(); }
78   Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {}
79 };
80 
81 // Wrapper for an MCSectionXCOFF.
82 // It can be a Csect or debug section or DWARF section and so on.
83 struct XCOFFSection {
84   const MCSectionXCOFF *const MCSec;
85   uint32_t SymbolTableIndex;
86   uint64_t Address;
87   uint64_t Size;
88 
89   SmallVector<Symbol, 1> Syms;
90   SmallVector<XCOFFRelocation, 1> Relocations;
91   StringRef getSymbolTableName() const { return MCSec->getSymbolTableName(); }
92   XCOFF::VisibilityType getVisibilityType() const {
93     return MCSec->getVisibilityType();
94   }
95   XCOFFSection(const MCSectionXCOFF *MCSec)
96       : MCSec(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
97 };
98 
99 // Type to be used for a container representing a set of csects with
100 // (approximately) the same storage mapping class. For example all the csects
101 // with a storage mapping class of `xmc_pr` will get placed into the same
102 // container.
103 using CsectGroup = std::deque<XCOFFSection>;
104 using CsectGroups = std::deque<CsectGroup *>;
105 
106 // The basic section entry defination. This Section represents a section entry
107 // in XCOFF section header table.
108 struct SectionEntry {
109   char Name[XCOFF::NameSize];
110   // The physical/virtual address of the section. For an object file these
111   // values are equivalent, except for in the overflow section header, where
112   // the physical address specifies the number of relocation entries and the
113   // virtual address specifies the number of line number entries.
114   // TODO: Divide Address into PhysicalAddress and VirtualAddress when line
115   // number entries are supported.
116   uint64_t Address;
117   uint64_t Size;
118   uint64_t FileOffsetToData;
119   uint64_t FileOffsetToRelocations;
120   uint32_t RelocationCount;
121   int32_t Flags;
122 
123   int16_t Index;
124 
125   // XCOFF has special section numbers for symbols:
126   // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
127   // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
128   // relocatable.
129   //  0 Specifies N_UNDEF, an undefined external symbol.
130   // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
131   // hasn't been initialized.
132   static constexpr int16_t UninitializedIndex =
133       XCOFF::ReservedSectionNum::N_DEBUG - 1;
134 
135   SectionEntry(StringRef N, int32_t Flags)
136       : Name(), Address(0), Size(0), FileOffsetToData(0),
137         FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags),
138         Index(UninitializedIndex) {
139     assert(N.size() <= XCOFF::NameSize && "section name too long");
140     memcpy(Name, N.data(), N.size());
141   }
142 
143   virtual void reset() {
144     Address = 0;
145     Size = 0;
146     FileOffsetToData = 0;
147     FileOffsetToRelocations = 0;
148     RelocationCount = 0;
149     Index = UninitializedIndex;
150   }
151 
152   virtual ~SectionEntry() = default;
153 };
154 
155 // Represents the data related to a section excluding the csects that make up
156 // the raw data of the section. The csects are stored separately as not all
157 // sections contain csects, and some sections contain csects which are better
158 // stored separately, e.g. the .data section containing read-write, descriptor,
159 // TOCBase and TOC-entry csects.
160 struct CsectSectionEntry : public SectionEntry {
161   // Virtual sections do not need storage allocated in the object file.
162   const bool IsVirtual;
163 
164   // This is a section containing csect groups.
165   CsectGroups Groups;
166 
167   CsectSectionEntry(StringRef N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
168                     CsectGroups Groups)
169       : SectionEntry(N, Flags), IsVirtual(IsVirtual), Groups(Groups) {
170     assert(N.size() <= XCOFF::NameSize && "section name too long");
171     memcpy(Name, N.data(), N.size());
172   }
173 
174   void reset() override {
175     SectionEntry::reset();
176     // Clear any csects we have stored.
177     for (auto *Group : Groups)
178       Group->clear();
179   }
180 
181   virtual ~CsectSectionEntry() = default;
182 };
183 
184 struct DwarfSectionEntry : public SectionEntry {
185   // For DWARF section entry.
186   std::unique_ptr<XCOFFSection> DwarfSect;
187 
188   // For DWARF section, we must use real size in the section header. MemorySize
189   // is for the size the DWARF section occupies including paddings.
190   uint32_t MemorySize;
191 
192   DwarfSectionEntry(StringRef N, int32_t Flags,
193                     std::unique_ptr<XCOFFSection> Sect)
194       : SectionEntry(N, Flags | XCOFF::STYP_DWARF), DwarfSect(std::move(Sect)),
195         MemorySize(0) {
196     assert(DwarfSect->MCSec->isDwarfSect() &&
197            "This should be a DWARF section!");
198     assert(N.size() <= XCOFF::NameSize && "section name too long");
199     memcpy(Name, N.data(), N.size());
200   }
201 
202   DwarfSectionEntry(DwarfSectionEntry &&s) = default;
203 
204   virtual ~DwarfSectionEntry() = default;
205 };
206 
207 struct ExceptionTableEntry {
208   const MCSymbol *Trap;
209   uint64_t TrapAddress;
210   unsigned Lang;
211   unsigned Reason;
212 
213   ExceptionTableEntry(const MCSymbol *Trap, unsigned Lang, unsigned Reason)
214       : Trap(Trap), Lang(Lang), Reason(Reason) {}
215 };
216 
217 struct ExceptionInfo {
218   const MCSymbol *FunctionSymbol;
219   unsigned FunctionSize;
220   std::vector<ExceptionTableEntry> Entries;
221 };
222 
223 struct ExceptionSectionEntry : public SectionEntry {
224   std::map<const StringRef, ExceptionInfo> ExceptionTable;
225   bool isDebugEnabled = false;
226 
227   ExceptionSectionEntry(StringRef N, int32_t Flags)
228       : SectionEntry(N, Flags | XCOFF::STYP_EXCEPT) {
229     assert(N.size() <= XCOFF::NameSize && "Section too long.");
230     memcpy(Name, N.data(), N.size());
231   }
232 
233   virtual ~ExceptionSectionEntry() = default;
234 };
235 
236 class XCOFFObjectWriter : public MCObjectWriter {
237 
238   uint32_t SymbolTableEntryCount = 0;
239   uint64_t SymbolTableOffset = 0;
240   uint16_t SectionCount = 0;
241   uint32_t PaddingsBeforeDwarf = 0;
242   std::vector<std::pair<std::string, size_t>> FileNames;
243   bool HasVisibility = false;
244 
245   support::endian::Writer W;
246   std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
247   StringTableBuilder Strings;
248 
249   const uint64_t MaxRawDataSize =
250       TargetObjectWriter->is64Bit() ? UINT64_MAX : UINT32_MAX;
251 
252   // Maps the MCSection representation to its corresponding XCOFFSection
253   // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into
254   // from its containing MCSectionXCOFF.
255   DenseMap<const MCSectionXCOFF *, XCOFFSection *> SectionMap;
256 
257   // Maps the MCSymbol representation to its corrresponding symbol table index.
258   // Needed for relocation.
259   DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap;
260 
261   // CsectGroups. These store the csects which make up different parts of
262   // the sections. Should have one for each set of csects that get mapped into
263   // the same section and get handled in a 'similar' way.
264   CsectGroup UndefinedCsects;
265   CsectGroup ProgramCodeCsects;
266   CsectGroup ReadOnlyCsects;
267   CsectGroup DataCsects;
268   CsectGroup FuncDSCsects;
269   CsectGroup TOCCsects;
270   CsectGroup BSSCsects;
271   CsectGroup TDataCsects;
272   CsectGroup TBSSCsects;
273 
274   // The Predefined sections.
275   CsectSectionEntry Text;
276   CsectSectionEntry Data;
277   CsectSectionEntry BSS;
278   CsectSectionEntry TData;
279   CsectSectionEntry TBSS;
280 
281   // All the XCOFF sections, in the order they will appear in the section header
282   // table.
283   std::array<CsectSectionEntry *const, 5> Sections{
284       {&Text, &Data, &BSS, &TData, &TBSS}};
285 
286   std::vector<DwarfSectionEntry> DwarfSections;
287   std::vector<SectionEntry> OverflowSections;
288 
289   ExceptionSectionEntry ExceptionSection;
290 
291   CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
292 
293   void reset() override;
294 
295   void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override;
296 
297   void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *,
298                         const MCFixup &, MCValue, uint64_t &) override;
299 
300   uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override;
301 
302   bool is64Bit() const { return TargetObjectWriter->is64Bit(); }
303   bool nameShouldBeInStringTable(const StringRef &);
304   void writeSymbolName(const StringRef &);
305 
306   void writeSymbolEntryForCsectMemberLabel(const Symbol &SymbolRef,
307                                            const XCOFFSection &CSectionRef,
308                                            int16_t SectionIndex,
309                                            uint64_t SymbolOffset);
310   void writeSymbolEntryForControlSection(const XCOFFSection &CSectionRef,
311                                          int16_t SectionIndex,
312                                          XCOFF::StorageClass StorageClass);
313   void writeSymbolEntryForDwarfSection(const XCOFFSection &DwarfSectionRef,
314                                        int16_t SectionIndex);
315   void writeFileHeader();
316   void writeAuxFileHeader();
317   void writeSectionHeader(const SectionEntry *Sec);
318   void writeSectionHeaderTable();
319   void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
320   void writeSectionForControlSectionEntry(const MCAssembler &Asm,
321                                           const MCAsmLayout &Layout,
322                                           const CsectSectionEntry &CsectEntry,
323                                           uint64_t &CurrentAddressLocation);
324   void writeSectionForDwarfSectionEntry(const MCAssembler &Asm,
325                                         const MCAsmLayout &Layout,
326                                         const DwarfSectionEntry &DwarfEntry,
327                                         uint64_t &CurrentAddressLocation);
328   void writeSectionForExceptionSectionEntry(
329       const MCAssembler &Asm, const MCAsmLayout &Layout,
330       ExceptionSectionEntry &ExceptionEntry, uint64_t &CurrentAddressLocation);
331   void writeSymbolTable(const MCAsmLayout &Layout);
332   void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion,
333                                 uint64_t NumberOfRelocEnt = 0);
334   void writeSymbolAuxCsectEntry(uint64_t SectionOrLength,
335                                 uint8_t SymbolAlignmentAndType,
336                                 uint8_t StorageMappingClass);
337   void writeSymbolAuxFunctionEntry(uint32_t EntryOffset, uint32_t FunctionSize,
338                                    uint64_t LineNumberPointer,
339                                    uint32_t EndIndex);
340   void writeSymbolAuxExceptionEntry(uint64_t EntryOffset, uint32_t FunctionSize,
341                                     uint32_t EndIndex);
342   void writeSymbolEntry(StringRef SymbolName, uint64_t Value,
343                         int16_t SectionNumber, uint16_t SymbolType,
344                         uint8_t StorageClass, uint8_t NumberOfAuxEntries = 1);
345   void writeRelocations();
346   void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section);
347 
348   // Called after all the csects and symbols have been processed by
349   // `executePostLayoutBinding`, this function handles building up the majority
350   // of the structures in the object file representation. Namely:
351   // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
352   //    sizes.
353   // *) Assigns symbol table indices.
354   // *) Builds up the section header table by adding any non-empty sections to
355   //    `Sections`.
356   void assignAddressesAndIndices(const MCAsmLayout &);
357   // Called after relocations are recorded.
358   void finalizeSectionInfo();
359   void finalizeRelocationInfo(SectionEntry *Sec, uint64_t RelCount);
360   void calcOffsetToRelocations(SectionEntry *Sec, uint64_t &RawPointer);
361 
362   void addExceptionEntry(const MCSymbol *Symbol, const MCSymbol *Trap,
363                          unsigned LanguageCode, unsigned ReasonCode,
364                          unsigned FunctionSize, bool hasDebug) override;
365   bool hasExceptionSection() {
366     return !ExceptionSection.ExceptionTable.empty();
367   }
368   unsigned getExceptionSectionSize();
369   unsigned getExceptionOffset(const MCSymbol *Symbol);
370 
371   size_t auxiliaryHeaderSize() const {
372     // 64-bit object files have no auxiliary header.
373     return HasVisibility && !is64Bit() ? XCOFF::AuxFileHeaderSizeShort : 0;
374   }
375 
376 public:
377   XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
378                     raw_pwrite_stream &OS);
379 
380   void writeWord(uint64_t Word) {
381     is64Bit() ? W.write<uint64_t>(Word) : W.write<uint32_t>(Word);
382   }
383 };
384 
385 XCOFFObjectWriter::XCOFFObjectWriter(
386     std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
387     : W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
388       Strings(StringTableBuilder::XCOFF),
389       Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
390            CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
391       Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false,
392            CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
393       BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
394           CsectGroups{&BSSCsects}),
395       TData(".tdata", XCOFF::STYP_TDATA, /* IsVirtual */ false,
396             CsectGroups{&TDataCsects}),
397       TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true,
398            CsectGroups{&TBSSCsects}),
399       ExceptionSection(".except", XCOFF::STYP_EXCEPT) {}
400 
401 void XCOFFObjectWriter::reset() {
402   // Clear the mappings we created.
403   SymbolIndexMap.clear();
404   SectionMap.clear();
405 
406   UndefinedCsects.clear();
407   // Reset any sections we have written to, and empty the section header table.
408   for (auto *Sec : Sections)
409     Sec->reset();
410   for (auto &DwarfSec : DwarfSections)
411     DwarfSec.reset();
412   for (auto &OverflowSec : OverflowSections)
413     OverflowSec.reset();
414   ExceptionSection.reset();
415 
416   // Reset states in XCOFFObjectWriter.
417   SymbolTableEntryCount = 0;
418   SymbolTableOffset = 0;
419   SectionCount = 0;
420   PaddingsBeforeDwarf = 0;
421   Strings.clear();
422 
423   MCObjectWriter::reset();
424 }
425 
426 CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
427   switch (MCSec->getMappingClass()) {
428   case XCOFF::XMC_PR:
429     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
430            "Only an initialized csect can contain program code.");
431     return ProgramCodeCsects;
432   case XCOFF::XMC_RO:
433     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
434            "Only an initialized csect can contain read only data.");
435     return ReadOnlyCsects;
436   case XCOFF::XMC_RW:
437     if (XCOFF::XTY_CM == MCSec->getCSectType())
438       return BSSCsects;
439 
440     if (XCOFF::XTY_SD == MCSec->getCSectType())
441       return DataCsects;
442 
443     report_fatal_error("Unhandled mapping of read-write csect to section.");
444   case XCOFF::XMC_DS:
445     return FuncDSCsects;
446   case XCOFF::XMC_BS:
447     assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
448            "Mapping invalid csect. CSECT with bss storage class must be "
449            "common type.");
450     return BSSCsects;
451   case XCOFF::XMC_TL:
452     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
453            "Mapping invalid csect. CSECT with tdata storage class must be "
454            "an initialized csect.");
455     return TDataCsects;
456   case XCOFF::XMC_UL:
457     assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
458            "Mapping invalid csect. CSECT with tbss storage class must be "
459            "an uninitialized csect.");
460     return TBSSCsects;
461   case XCOFF::XMC_TC0:
462     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
463            "Only an initialized csect can contain TOC-base.");
464     assert(TOCCsects.empty() &&
465            "We should have only one TOC-base, and it should be the first csect "
466            "in this CsectGroup.");
467     return TOCCsects;
468   case XCOFF::XMC_TC:
469   case XCOFF::XMC_TE:
470   case XCOFF::XMC_TD:
471     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
472            "Only an initialized csect can contain TC entry.");
473     assert(!TOCCsects.empty() &&
474            "We should at least have a TOC-base in this CsectGroup.");
475     return TOCCsects;
476   default:
477     report_fatal_error("Unhandled mapping of csect to section.");
478   }
479 }
480 
481 static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) {
482   if (XSym->isDefined())
483     return cast<MCSectionXCOFF>(XSym->getFragment()->getParent());
484   return XSym->getRepresentedCsect();
485 }
486 
487 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
488                                                  const MCAsmLayout &Layout) {
489   for (const auto &S : Asm) {
490     const auto *MCSec = cast<const MCSectionXCOFF>(&S);
491     assert(SectionMap.find(MCSec) == SectionMap.end() &&
492            "Cannot add a section twice.");
493 
494     // If the name does not fit in the storage provided in the symbol table
495     // entry, add it to the string table.
496     if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
497       Strings.add(MCSec->getSymbolTableName());
498     if (MCSec->isCsect()) {
499       // A new control section. Its CsectSectionEntry should already be staticly
500       // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of
501       // the CsectSectionEntry.
502       assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
503              "An undefined csect should not get registered.");
504       CsectGroup &Group = getCsectGroup(MCSec);
505       Group.emplace_back(MCSec);
506       SectionMap[MCSec] = &Group.back();
507     } else if (MCSec->isDwarfSect()) {
508       // A new DwarfSectionEntry.
509       std::unique_ptr<XCOFFSection> DwarfSec =
510           std::make_unique<XCOFFSection>(MCSec);
511       SectionMap[MCSec] = DwarfSec.get();
512 
513       DwarfSectionEntry SecEntry(MCSec->getName(),
514                                  *MCSec->getDwarfSubtypeFlags(),
515                                  std::move(DwarfSec));
516       DwarfSections.push_back(std::move(SecEntry));
517     } else
518       llvm_unreachable("unsupport section type!");
519   }
520 
521   for (const MCSymbol &S : Asm.symbols()) {
522     // Nothing to do for temporary symbols.
523     if (S.isTemporary())
524       continue;
525 
526     const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
527     const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym);
528 
529     if (XSym->getVisibilityType() != XCOFF::SYM_V_UNSPECIFIED)
530       HasVisibility = true;
531 
532     if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
533       // Handle undefined symbol.
534       UndefinedCsects.emplace_back(ContainingCsect);
535       SectionMap[ContainingCsect] = &UndefinedCsects.back();
536       if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName()))
537         Strings.add(ContainingCsect->getSymbolTableName());
538       continue;
539     }
540 
541     // If the symbol is the csect itself, we don't need to put the symbol
542     // into csect's Syms.
543     if (XSym == ContainingCsect->getQualNameSymbol())
544       continue;
545 
546     // Only put a label into the symbol table when it is an external label.
547     if (!XSym->isExternal())
548       continue;
549 
550     assert(SectionMap.find(ContainingCsect) != SectionMap.end() &&
551            "Expected containing csect to exist in map");
552     XCOFFSection *Csect = SectionMap[ContainingCsect];
553     // Lookup the containing csect and add the symbol to it.
554     assert(Csect->MCSec->isCsect() && "only csect is supported now!");
555     Csect->Syms.emplace_back(XSym);
556 
557     // If the name does not fit in the storage provided in the symbol table
558     // entry, add it to the string table.
559     if (nameShouldBeInStringTable(XSym->getSymbolTableName()))
560       Strings.add(XSym->getSymbolTableName());
561   }
562 
563   FileNames = Asm.getFileNames();
564   // Emit ".file" as the source file name when there is no file name.
565   if (FileNames.empty())
566     FileNames.emplace_back(".file", 0);
567   for (const std::pair<std::string, size_t> &F : FileNames) {
568     if (nameShouldBeInStringTable(F.first))
569       Strings.add(F.first);
570   }
571 
572   Strings.finalize();
573   assignAddressesAndIndices(Layout);
574 }
575 
576 void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
577                                          const MCAsmLayout &Layout,
578                                          const MCFragment *Fragment,
579                                          const MCFixup &Fixup, MCValue Target,
580                                          uint64_t &FixedValue) {
581   auto getIndex = [this](const MCSymbol *Sym,
582                          const MCSectionXCOFF *ContainingCsect) {
583     // If we could not find the symbol directly in SymbolIndexMap, this symbol
584     // could either be a temporary symbol or an undefined symbol. In this case,
585     // we would need to have the relocation reference its csect instead.
586     return SymbolIndexMap.find(Sym) != SymbolIndexMap.end()
587                ? SymbolIndexMap[Sym]
588                : SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
589   };
590 
591   auto getVirtualAddress =
592       [this, &Layout](const MCSymbol *Sym,
593                       const MCSectionXCOFF *ContainingSect) -> uint64_t {
594     // A DWARF section.
595     if (ContainingSect->isDwarfSect())
596       return Layout.getSymbolOffset(*Sym);
597 
598     // A csect.
599     if (!Sym->isDefined())
600       return SectionMap[ContainingSect]->Address;
601 
602     // A label.
603     assert(Sym->isDefined() && "not a valid object that has address!");
604     return SectionMap[ContainingSect]->Address + Layout.getSymbolOffset(*Sym);
605   };
606 
607   const MCSymbol *const SymA = &Target.getSymA()->getSymbol();
608 
609   MCAsmBackend &Backend = Asm.getBackend();
610   bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
611                  MCFixupKindInfo::FKF_IsPCRel;
612 
613   uint8_t Type;
614   uint8_t SignAndSize;
615   std::tie(Type, SignAndSize) =
616       TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel);
617 
618   const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
619   assert(SectionMap.find(SymASec) != SectionMap.end() &&
620          "Expected containing csect to exist in map.");
621 
622   const uint32_t Index = getIndex(SymA, SymASec);
623   if (Type == XCOFF::RelocationType::R_POS ||
624       Type == XCOFF::RelocationType::R_TLS)
625     // The FixedValue should be symbol's virtual address in this object file
626     // plus any constant value that we might get.
627     FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
628   else if (Type == XCOFF::RelocationType::R_TLSM)
629     // The FixedValue should always be zero since the region handle is only
630     // known at load time.
631     FixedValue = 0;
632   else if (Type == XCOFF::RelocationType::R_TOC ||
633            Type == XCOFF::RelocationType::R_TOCL) {
634     // For non toc-data external symbols, R_TOC type relocation will relocate to
635     // data symbols that have XCOFF::XTY_SD type csect. For toc-data external
636     // symbols, R_TOC type relocation will relocate to data symbols that have
637     // XCOFF_ER type csect. For XCOFF_ER kind symbols, there will be no TOC
638     // entry for them, so the FixedValue should always be 0.
639     if (SymASec->getCSectType() == XCOFF::XTY_ER) {
640       FixedValue = 0;
641     } else {
642       // The FixedValue should be the TOC entry offset from the TOC-base plus
643       // any constant offset value.
644       const int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
645                                      TOCCsects.front().Address +
646                                      Target.getConstant();
647       if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset))
648         report_fatal_error("TOCEntryOffset overflows in small code model mode");
649 
650       FixedValue = TOCEntryOffset;
651     }
652   } else if (Type == XCOFF::RelocationType::R_RBR) {
653     MCSectionXCOFF *ParentSec = cast<MCSectionXCOFF>(Fragment->getParent());
654     assert((SymASec->getMappingClass() == XCOFF::XMC_PR &&
655             ParentSec->getMappingClass() == XCOFF::XMC_PR) &&
656            "Only XMC_PR csect may have the R_RBR relocation.");
657 
658     // The address of the branch instruction should be the sum of section
659     // address, fragment offset and Fixup offset.
660     uint64_t BRInstrAddress = SectionMap[ParentSec]->Address +
661                               Layout.getFragmentOffset(Fragment) +
662                               Fixup.getOffset();
663     // The FixedValue should be the difference between SymA csect address and BR
664     // instr address plus any constant value.
665     FixedValue =
666         SectionMap[SymASec]->Address - BRInstrAddress + Target.getConstant();
667   }
668 
669   assert((Fixup.getOffset() <=
670           MaxRawDataSize - Layout.getFragmentOffset(Fragment)) &&
671          "Fragment offset + fixup offset is overflowed.");
672   uint32_t FixupOffsetInCsect =
673       Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
674 
675   XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
676   MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent());
677   assert(SectionMap.find(RelocationSec) != SectionMap.end() &&
678          "Expected containing csect to exist in map.");
679   SectionMap[RelocationSec]->Relocations.push_back(Reloc);
680 
681   if (!Target.getSymB())
682     return;
683 
684   const MCSymbol *const SymB = &Target.getSymB()->getSymbol();
685   if (SymA == SymB)
686     report_fatal_error("relocation for opposite term is not yet supported");
687 
688   const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
689   assert(SectionMap.find(SymBSec) != SectionMap.end() &&
690          "Expected containing csect to exist in map.");
691   if (SymASec == SymBSec)
692     report_fatal_error(
693         "relocation for paired relocatable term is not yet supported");
694 
695   assert(Type == XCOFF::RelocationType::R_POS &&
696          "SymA must be R_POS here if it's not opposite term or paired "
697          "relocatable term.");
698   const uint32_t IndexB = getIndex(SymB, SymBSec);
699   // SymB must be R_NEG here, given the general form of Target(MCValue) is
700   // "SymbolA - SymbolB + imm64".
701   const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
702   XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
703   SectionMap[RelocationSec]->Relocations.push_back(RelocB);
704   // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
705   // now we just need to fold "- SymbolB" here.
706   FixedValue -= getVirtualAddress(SymB, SymBSec);
707 }
708 
709 void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
710                                       const MCAsmLayout &Layout) {
711   uint64_t CurrentAddressLocation = 0;
712   for (const auto *Section : Sections)
713     writeSectionForControlSectionEntry(Asm, Layout, *Section,
714                                        CurrentAddressLocation);
715   for (const auto &DwarfSection : DwarfSections)
716     writeSectionForDwarfSectionEntry(Asm, Layout, DwarfSection,
717                                      CurrentAddressLocation);
718   writeSectionForExceptionSectionEntry(Asm, Layout, ExceptionSection,
719                                        CurrentAddressLocation);
720 }
721 
722 uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
723                                         const MCAsmLayout &Layout) {
724   // We always emit a timestamp of 0 for reproducibility, so ensure incremental
725   // linking is not enabled, in case, like with Windows COFF, such a timestamp
726   // is incompatible with incremental linking of XCOFF.
727   if (Asm.isIncrementalLinkerCompatible())
728     report_fatal_error("Incremental linking not supported for XCOFF.");
729 
730   finalizeSectionInfo();
731   uint64_t StartOffset = W.OS.tell();
732 
733   writeFileHeader();
734   writeAuxFileHeader();
735   writeSectionHeaderTable();
736   writeSections(Asm, Layout);
737   writeRelocations();
738   writeSymbolTable(Layout);
739   // Write the string table.
740   Strings.write(W.OS);
741 
742   return W.OS.tell() - StartOffset;
743 }
744 
745 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
746   return SymbolName.size() > XCOFF::NameSize || is64Bit();
747 }
748 
749 void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) {
750   // Magic, Offset or SymbolName.
751   if (nameShouldBeInStringTable(SymbolName)) {
752     W.write<int32_t>(0);
753     W.write<uint32_t>(Strings.getOffset(SymbolName));
754   } else {
755     char Name[XCOFF::NameSize + 1];
756     std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
757     ArrayRef<char> NameRef(Name, XCOFF::NameSize);
758     W.write(NameRef);
759   }
760 }
761 
762 void XCOFFObjectWriter::writeSymbolEntry(StringRef SymbolName, uint64_t Value,
763                                          int16_t SectionNumber,
764                                          uint16_t SymbolType,
765                                          uint8_t StorageClass,
766                                          uint8_t NumberOfAuxEntries) {
767   if (is64Bit()) {
768     W.write<uint64_t>(Value);
769     W.write<uint32_t>(Strings.getOffset(SymbolName));
770   } else {
771     writeSymbolName(SymbolName);
772     W.write<uint32_t>(Value);
773   }
774   W.write<int16_t>(SectionNumber);
775   W.write<uint16_t>(SymbolType);
776   W.write<uint8_t>(StorageClass);
777   W.write<uint8_t>(NumberOfAuxEntries);
778 }
779 
780 void XCOFFObjectWriter::writeSymbolAuxCsectEntry(uint64_t SectionOrLength,
781                                                  uint8_t SymbolAlignmentAndType,
782                                                  uint8_t StorageMappingClass) {
783   W.write<uint32_t>(is64Bit() ? Lo_32(SectionOrLength) : SectionOrLength);
784   W.write<uint32_t>(0); // ParameterHashIndex
785   W.write<uint16_t>(0); // TypeChkSectNum
786   W.write<uint8_t>(SymbolAlignmentAndType);
787   W.write<uint8_t>(StorageMappingClass);
788   if (is64Bit()) {
789     W.write<uint32_t>(Hi_32(SectionOrLength));
790     W.OS.write_zeros(1); // Reserved
791     W.write<uint8_t>(XCOFF::AUX_CSECT);
792   } else {
793     W.write<uint32_t>(0); // StabInfoIndex
794     W.write<uint16_t>(0); // StabSectNum
795   }
796 }
797 
798 void XCOFFObjectWriter::writeSymbolAuxDwarfEntry(
799     uint64_t LengthOfSectionPortion, uint64_t NumberOfRelocEnt) {
800   writeWord(LengthOfSectionPortion);
801   if (!is64Bit())
802     W.OS.write_zeros(4); // Reserved
803   writeWord(NumberOfRelocEnt);
804   if (is64Bit()) {
805     W.OS.write_zeros(1); // Reserved
806     W.write<uint8_t>(XCOFF::AUX_SECT);
807   } else {
808     W.OS.write_zeros(6); // Reserved
809   }
810 }
811 
812 void XCOFFObjectWriter::writeSymbolEntryForCsectMemberLabel(
813     const Symbol &SymbolRef, const XCOFFSection &CSectionRef,
814     int16_t SectionIndex, uint64_t SymbolOffset) {
815   assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address &&
816          "Symbol address overflowed.");
817 
818   auto Entry = ExceptionSection.ExceptionTable.find(SymbolRef.MCSym->getName());
819   if (Entry != ExceptionSection.ExceptionTable.end()) {
820     writeSymbolEntry(SymbolRef.getSymbolTableName(),
821                      CSectionRef.Address + SymbolOffset, SectionIndex,
822                      // In the old version of the 32-bit XCOFF interpretation,
823                      // symbols may require bit 10 (0x0020) to be set if the
824                      // symbol is a function, otherwise the bit should be 0.
825                      is64Bit() ? SymbolRef.getVisibilityType()
826                                : SymbolRef.getVisibilityType() | 0x0020,
827                      SymbolRef.getStorageClass(),
828                      (is64Bit() && ExceptionSection.isDebugEnabled) ? 3 : 2);
829     if (is64Bit() && ExceptionSection.isDebugEnabled) {
830       // On 64 bit with debugging enabled, we have a csect, exception, and
831       // function auxilliary entries, so we must increment symbol index by 4.
832       writeSymbolAuxExceptionEntry(
833           ExceptionSection.FileOffsetToData +
834               getExceptionOffset(Entry->second.FunctionSymbol),
835           Entry->second.FunctionSize,
836           SymbolIndexMap[Entry->second.FunctionSymbol] + 4);
837     }
838     // For exception section entries, csect and function auxilliary entries
839     // must exist. On 64-bit there is also an exception auxilliary entry.
840     writeSymbolAuxFunctionEntry(
841         ExceptionSection.FileOffsetToData +
842             getExceptionOffset(Entry->second.FunctionSymbol),
843         Entry->second.FunctionSize, 0,
844         (is64Bit() && ExceptionSection.isDebugEnabled)
845             ? SymbolIndexMap[Entry->second.FunctionSymbol] + 4
846             : SymbolIndexMap[Entry->second.FunctionSymbol] + 3);
847   } else {
848     writeSymbolEntry(SymbolRef.getSymbolTableName(),
849                      CSectionRef.Address + SymbolOffset, SectionIndex,
850                      SymbolRef.getVisibilityType(),
851                      SymbolRef.getStorageClass());
852   }
853   writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex, XCOFF::XTY_LD,
854                            CSectionRef.MCSec->getMappingClass());
855 }
856 
857 void XCOFFObjectWriter::writeSymbolEntryForDwarfSection(
858     const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) {
859   assert(DwarfSectionRef.MCSec->isDwarfSect() && "Not a DWARF section!");
860 
861   writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), /*Value=*/0,
862                    SectionIndex, /*SymbolType=*/0, XCOFF::C_DWARF);
863 
864   writeSymbolAuxDwarfEntry(DwarfSectionRef.Size);
865 }
866 
867 void XCOFFObjectWriter::writeSymbolEntryForControlSection(
868     const XCOFFSection &CSectionRef, int16_t SectionIndex,
869     XCOFF::StorageClass StorageClass) {
870   writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address,
871                    SectionIndex, CSectionRef.getVisibilityType(), StorageClass);
872 
873   writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec),
874                            CSectionRef.MCSec->getMappingClass());
875 }
876 
877 void XCOFFObjectWriter::writeSymbolAuxFunctionEntry(uint32_t EntryOffset,
878                                                     uint32_t FunctionSize,
879                                                     uint64_t LineNumberPointer,
880                                                     uint32_t EndIndex) {
881   if (is64Bit())
882     writeWord(LineNumberPointer);
883   else
884     W.write<uint32_t>(EntryOffset);
885   W.write<uint32_t>(FunctionSize);
886   if (!is64Bit())
887     writeWord(LineNumberPointer);
888   W.write<uint32_t>(EndIndex);
889   if (is64Bit()) {
890     W.OS.write_zeros(1);
891     W.write<uint8_t>(XCOFF::AUX_FCN);
892   } else {
893     W.OS.write_zeros(2);
894   }
895 }
896 
897 void XCOFFObjectWriter::writeSymbolAuxExceptionEntry(uint64_t EntryOffset,
898                                                      uint32_t FunctionSize,
899                                                      uint32_t EndIndex) {
900   assert(is64Bit() && "Exception auxilliary entries are 64-bit only.");
901   W.write<uint64_t>(EntryOffset);
902   W.write<uint32_t>(FunctionSize);
903   W.write<uint32_t>(EndIndex);
904   W.OS.write_zeros(1); // Pad (unused)
905   W.write<uint8_t>(XCOFF::AUX_EXCEPT);
906 }
907 
908 void XCOFFObjectWriter::writeFileHeader() {
909   W.write<uint16_t>(is64Bit() ? XCOFF::XCOFF64 : XCOFF::XCOFF32);
910   W.write<uint16_t>(SectionCount);
911   W.write<int32_t>(0); // TimeStamp
912   writeWord(SymbolTableOffset);
913   if (is64Bit()) {
914     W.write<uint16_t>(auxiliaryHeaderSize());
915     W.write<uint16_t>(0); // Flags
916     W.write<int32_t>(SymbolTableEntryCount);
917   } else {
918     W.write<int32_t>(SymbolTableEntryCount);
919     W.write<uint16_t>(auxiliaryHeaderSize());
920     W.write<uint16_t>(0); // Flags
921   }
922 }
923 
924 void XCOFFObjectWriter::writeAuxFileHeader() {
925   if (!auxiliaryHeaderSize())
926     return;
927   W.write<uint16_t>(0); // Magic
928   W.write<uint16_t>(
929       XCOFF::NEW_XCOFF_INTERPRET); // Version. The new interpretation of the
930                                    // n_type field in the symbol table entry is
931                                    // used in XCOFF32.
932   W.write<uint32_t>(Sections[0]->Size);    // TextSize
933   W.write<uint32_t>(Sections[1]->Size);    // InitDataSize
934   W.write<uint32_t>(Sections[2]->Size);    // BssDataSize
935   W.write<uint32_t>(0);                    // EntryPointAddr
936   W.write<uint32_t>(Sections[0]->Address); // TextStartAddr
937   W.write<uint32_t>(Sections[1]->Address); // DataStartAddr
938 }
939 
940 void XCOFFObjectWriter::writeSectionHeader(const SectionEntry *Sec) {
941   bool IsDwarf = (Sec->Flags & XCOFF::STYP_DWARF) != 0;
942   bool IsOvrflo = (Sec->Flags & XCOFF::STYP_OVRFLO) != 0;
943   // Nothing to write for this Section.
944   if (Sec->Index == SectionEntry::UninitializedIndex)
945     return;
946 
947   // Write Name.
948   ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
949   W.write(NameRef);
950 
951   // Write the Physical Address and Virtual Address.
952   // We use 0 for DWARF sections' Physical and Virtual Addresses.
953   writeWord(IsDwarf ? 0 : Sec->Address);
954   // Since line number is not supported, we set it to 0 for overflow sections.
955   writeWord((IsDwarf || IsOvrflo) ? 0 : Sec->Address);
956 
957   writeWord(Sec->Size);
958   writeWord(Sec->FileOffsetToData);
959   writeWord(Sec->FileOffsetToRelocations);
960   writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet.
961 
962   if (is64Bit()) {
963     W.write<uint32_t>(Sec->RelocationCount);
964     W.write<uint32_t>(0); // NumberOfLineNumbers. Not supported yet.
965     W.write<int32_t>(Sec->Flags);
966     W.OS.write_zeros(4);
967   } else {
968     // For the overflow section header, s_nreloc provides a reference to the
969     // primary section header and s_nlnno must have the same value.
970     // For common section headers, if either of s_nreloc or s_nlnno are set to
971     // 65535, the other one must also be set to 65535.
972     W.write<uint16_t>(Sec->RelocationCount);
973     W.write<uint16_t>((IsOvrflo || Sec->RelocationCount == XCOFF::RelocOverflow)
974                           ? Sec->RelocationCount
975                           : 0); // NumberOfLineNumbers. Not supported yet.
976     W.write<int32_t>(Sec->Flags);
977   }
978 }
979 
980 void XCOFFObjectWriter::writeSectionHeaderTable() {
981   for (const auto *CsectSec : Sections)
982     writeSectionHeader(CsectSec);
983   for (const auto &DwarfSec : DwarfSections)
984     writeSectionHeader(&DwarfSec);
985   for (const auto &OverflowSec : OverflowSections)
986     writeSectionHeader(&OverflowSec);
987   if (hasExceptionSection())
988     writeSectionHeader(&ExceptionSection);
989 }
990 
991 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
992                                         const XCOFFSection &Section) {
993   if (Section.MCSec->isCsect())
994     writeWord(Section.Address + Reloc.FixupOffsetInCsect);
995   else {
996     // DWARF sections' address is set to 0.
997     assert(Section.MCSec->isDwarfSect() && "unsupport section type!");
998     writeWord(Reloc.FixupOffsetInCsect);
999   }
1000   W.write<uint32_t>(Reloc.SymbolTableIndex);
1001   W.write<uint8_t>(Reloc.SignAndSize);
1002   W.write<uint8_t>(Reloc.Type);
1003 }
1004 
1005 void XCOFFObjectWriter::writeRelocations() {
1006   for (const auto *Section : Sections) {
1007     if (Section->Index == SectionEntry::UninitializedIndex)
1008       // Nothing to write for this Section.
1009       continue;
1010 
1011     for (const auto *Group : Section->Groups) {
1012       if (Group->empty())
1013         continue;
1014 
1015       for (const auto &Csect : *Group) {
1016         for (const auto Reloc : Csect.Relocations)
1017           writeRelocation(Reloc, Csect);
1018       }
1019     }
1020   }
1021 
1022   for (const auto &DwarfSection : DwarfSections)
1023     for (const auto &Reloc : DwarfSection.DwarfSect->Relocations)
1024       writeRelocation(Reloc, *DwarfSection.DwarfSect);
1025 }
1026 
1027 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
1028   // Write C_FILE symbols.
1029   // The n_name of a C_FILE symbol is the source file's name when no auxiliary
1030   // entries are present.
1031   for (const std::pair<std::string, size_t> &F : FileNames) {
1032     writeSymbolEntry(F.first, /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG,
1033                      /*SymbolType=*/0, XCOFF::C_FILE,
1034                      /*NumberOfAuxEntries=*/0);
1035   }
1036 
1037   for (const auto &Csect : UndefinedCsects) {
1038     writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF,
1039                                       Csect.MCSec->getStorageClass());
1040   }
1041 
1042   for (const auto *Section : Sections) {
1043     if (Section->Index == SectionEntry::UninitializedIndex)
1044       // Nothing to write for this Section.
1045       continue;
1046 
1047     for (const auto *Group : Section->Groups) {
1048       if (Group->empty())
1049         continue;
1050 
1051       const int16_t SectionIndex = Section->Index;
1052       for (const auto &Csect : *Group) {
1053         // Write out the control section first and then each symbol in it.
1054         writeSymbolEntryForControlSection(Csect, SectionIndex,
1055                                           Csect.MCSec->getStorageClass());
1056 
1057         for (const auto &Sym : Csect.Syms)
1058           writeSymbolEntryForCsectMemberLabel(
1059               Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
1060       }
1061     }
1062   }
1063 
1064   for (const auto &DwarfSection : DwarfSections)
1065     writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect,
1066                                     DwarfSection.Index);
1067 }
1068 
1069 void XCOFFObjectWriter::finalizeRelocationInfo(SectionEntry *Sec,
1070                                                uint64_t RelCount) {
1071   // Handles relocation field overflows in an XCOFF32 file. An XCOFF64 file
1072   // may not contain an overflow section header.
1073   if (!is64Bit() && (RelCount >= static_cast<uint32_t>(XCOFF::RelocOverflow))) {
1074     // Generate an overflow section header.
1075     SectionEntry SecEntry(".ovrflo", XCOFF::STYP_OVRFLO);
1076 
1077     // This field specifies the file section number of the section header that
1078     // overflowed.
1079     SecEntry.RelocationCount = Sec->Index;
1080 
1081     // This field specifies the number of relocation entries actually
1082     // required.
1083     SecEntry.Address = RelCount;
1084     SecEntry.Index = ++SectionCount;
1085     OverflowSections.push_back(std::move(SecEntry));
1086 
1087     // The field in the primary section header is always 65535
1088     // (XCOFF::RelocOverflow).
1089     Sec->RelocationCount = XCOFF::RelocOverflow;
1090   } else {
1091     Sec->RelocationCount = RelCount;
1092   }
1093 }
1094 
1095 void XCOFFObjectWriter::calcOffsetToRelocations(SectionEntry *Sec,
1096                                                 uint64_t &RawPointer) {
1097   if (!Sec->RelocationCount)
1098     return;
1099 
1100   Sec->FileOffsetToRelocations = RawPointer;
1101   uint64_t RelocationSizeInSec = 0;
1102   if (!is64Bit() &&
1103       Sec->RelocationCount == static_cast<uint32_t>(XCOFF::RelocOverflow)) {
1104     // Find its corresponding overflow section.
1105     for (auto &OverflowSec : OverflowSections) {
1106       if (OverflowSec.RelocationCount == static_cast<uint32_t>(Sec->Index)) {
1107         RelocationSizeInSec =
1108             OverflowSec.Address * XCOFF::RelocationSerializationSize32;
1109 
1110         // This field must have the same values as in the corresponding
1111         // primary section header.
1112         OverflowSec.FileOffsetToRelocations = Sec->FileOffsetToRelocations;
1113       }
1114     }
1115     assert(RelocationSizeInSec && "Overflow section header doesn't exist.");
1116   } else {
1117     RelocationSizeInSec = Sec->RelocationCount *
1118                           (is64Bit() ? XCOFF::RelocationSerializationSize64
1119                                      : XCOFF::RelocationSerializationSize32);
1120   }
1121 
1122   RawPointer += RelocationSizeInSec;
1123   if (RawPointer > MaxRawDataSize)
1124     report_fatal_error("Relocation data overflowed this object file.");
1125 }
1126 
1127 void XCOFFObjectWriter::finalizeSectionInfo() {
1128   for (auto *Section : Sections) {
1129     if (Section->Index == SectionEntry::UninitializedIndex)
1130       // Nothing to record for this Section.
1131       continue;
1132 
1133     uint64_t RelCount = 0;
1134     for (const auto *Group : Section->Groups) {
1135       if (Group->empty())
1136         continue;
1137 
1138       for (auto &Csect : *Group)
1139         RelCount += Csect.Relocations.size();
1140     }
1141     finalizeRelocationInfo(Section, RelCount);
1142   }
1143 
1144   for (auto &DwarfSection : DwarfSections)
1145     finalizeRelocationInfo(&DwarfSection,
1146                            DwarfSection.DwarfSect->Relocations.size());
1147 
1148   // Calculate the RawPointer value for all headers.
1149   uint64_t RawPointer =
1150       (is64Bit() ? (XCOFF::FileHeaderSize64 +
1151                     SectionCount * XCOFF::SectionHeaderSize64)
1152                  : (XCOFF::FileHeaderSize32 +
1153                     SectionCount * XCOFF::SectionHeaderSize32)) +
1154       auxiliaryHeaderSize();
1155 
1156   // Calculate the file offset to the section data.
1157   for (auto *Sec : Sections) {
1158     if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual)
1159       continue;
1160 
1161     Sec->FileOffsetToData = RawPointer;
1162     RawPointer += Sec->Size;
1163     if (RawPointer > MaxRawDataSize)
1164       report_fatal_error("Section raw data overflowed this object file.");
1165   }
1166 
1167   if (!DwarfSections.empty()) {
1168     RawPointer += PaddingsBeforeDwarf;
1169     for (auto &DwarfSection : DwarfSections) {
1170       DwarfSection.FileOffsetToData = RawPointer;
1171       RawPointer += DwarfSection.MemorySize;
1172       if (RawPointer > MaxRawDataSize)
1173         report_fatal_error("Section raw data overflowed this object file.");
1174     }
1175   }
1176 
1177   if (hasExceptionSection()) {
1178     ExceptionSection.FileOffsetToData = RawPointer;
1179     RawPointer += ExceptionSection.Size;
1180 
1181     assert(RawPointer <= MaxRawDataSize &&
1182            "Section raw data overflowed this object file.");
1183   }
1184 
1185   for (auto *Sec : Sections) {
1186     if (Sec->Index != SectionEntry::UninitializedIndex)
1187       calcOffsetToRelocations(Sec, RawPointer);
1188   }
1189 
1190   for (auto &DwarfSec : DwarfSections)
1191     calcOffsetToRelocations(&DwarfSec, RawPointer);
1192 
1193   // TODO Error check that the number of symbol table entries fits in 32-bits
1194   // signed ...
1195   if (SymbolTableEntryCount)
1196     SymbolTableOffset = RawPointer;
1197 }
1198 
1199 void XCOFFObjectWriter::addExceptionEntry(
1200     const MCSymbol *Symbol, const MCSymbol *Trap, unsigned LanguageCode,
1201     unsigned ReasonCode, unsigned FunctionSize, bool hasDebug) {
1202   // If a module had debug info, debugging is enabled and XCOFF emits the
1203   // exception auxilliary entry.
1204   if (hasDebug)
1205     ExceptionSection.isDebugEnabled = true;
1206   auto Entry = ExceptionSection.ExceptionTable.find(Symbol->getName());
1207   if (Entry != ExceptionSection.ExceptionTable.end()) {
1208     Entry->second.Entries.push_back(
1209         ExceptionTableEntry(Trap, LanguageCode, ReasonCode));
1210     return;
1211   }
1212   ExceptionInfo NewEntry;
1213   NewEntry.FunctionSymbol = Symbol;
1214   NewEntry.FunctionSize = FunctionSize;
1215   NewEntry.Entries.push_back(
1216       ExceptionTableEntry(Trap, LanguageCode, ReasonCode));
1217   ExceptionSection.ExceptionTable.insert(
1218       std::pair<const StringRef, ExceptionInfo>(Symbol->getName(), NewEntry));
1219 }
1220 
1221 unsigned XCOFFObjectWriter::getExceptionSectionSize() {
1222   unsigned EntryNum = 0;
1223 
1224   for (auto it = ExceptionSection.ExceptionTable.begin();
1225        it != ExceptionSection.ExceptionTable.end(); ++it)
1226     // The size() gets +1 to account for the initial entry containing the
1227     // symbol table index.
1228     EntryNum += it->second.Entries.size() + 1;
1229 
1230   return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
1231                                : XCOFF::ExceptionSectionEntrySize32);
1232 }
1233 
1234 unsigned XCOFFObjectWriter::getExceptionOffset(const MCSymbol *Symbol) {
1235   unsigned EntryNum = 0;
1236   for (auto it = ExceptionSection.ExceptionTable.begin();
1237        it != ExceptionSection.ExceptionTable.end(); ++it) {
1238     if (Symbol == it->second.FunctionSymbol)
1239       break;
1240     EntryNum += it->second.Entries.size() + 1;
1241   }
1242   return EntryNum * (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
1243                                : XCOFF::ExceptionSectionEntrySize32);
1244 }
1245 
1246 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
1247   // The symbol table starts with all the C_FILE symbols.
1248   uint32_t SymbolTableIndex = FileNames.size();
1249 
1250   // Calculate indices for undefined symbols.
1251   for (auto &Csect : UndefinedCsects) {
1252     Csect.Size = 0;
1253     Csect.Address = 0;
1254     Csect.SymbolTableIndex = SymbolTableIndex;
1255     SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
1256     // 1 main and 1 auxiliary symbol table entry for each contained symbol.
1257     SymbolTableIndex += 2;
1258   }
1259 
1260   // The address corrresponds to the address of sections and symbols in the
1261   // object file. We place the shared address 0 immediately after the
1262   // section header table.
1263   uint64_t Address = 0;
1264   // Section indices are 1-based in XCOFF.
1265   int32_t SectionIndex = 1;
1266   bool HasTDataSection = false;
1267 
1268   for (auto *Section : Sections) {
1269     const bool IsEmpty =
1270         llvm::all_of(Section->Groups,
1271                      [](const CsectGroup *Group) { return Group->empty(); });
1272     if (IsEmpty)
1273       continue;
1274 
1275     if (SectionIndex > MaxSectionIndex)
1276       report_fatal_error("Section index overflow!");
1277     Section->Index = SectionIndex++;
1278     SectionCount++;
1279 
1280     bool SectionAddressSet = false;
1281     // Reset the starting address to 0 for TData section.
1282     if (Section->Flags == XCOFF::STYP_TDATA) {
1283       Address = 0;
1284       HasTDataSection = true;
1285     }
1286     // Reset the starting address to 0 for TBSS section if the object file does
1287     // not contain TData Section.
1288     if ((Section->Flags == XCOFF::STYP_TBSS) && !HasTDataSection)
1289       Address = 0;
1290 
1291     for (auto *Group : Section->Groups) {
1292       if (Group->empty())
1293         continue;
1294 
1295       for (auto &Csect : *Group) {
1296         const MCSectionXCOFF *MCSec = Csect.MCSec;
1297         Csect.Address = alignTo(Address, MCSec->getAlign());
1298         Csect.Size = Layout.getSectionAddressSize(MCSec);
1299         Address = Csect.Address + Csect.Size;
1300         Csect.SymbolTableIndex = SymbolTableIndex;
1301         SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
1302         // 1 main and 1 auxiliary symbol table entry for the csect.
1303         SymbolTableIndex += 2;
1304 
1305         for (auto &Sym : Csect.Syms) {
1306           bool hasExceptEntry = false;
1307           auto Entry =
1308               ExceptionSection.ExceptionTable.find(Sym.MCSym->getName());
1309           if (Entry != ExceptionSection.ExceptionTable.end()) {
1310             hasExceptEntry = true;
1311             for (auto &TrapEntry : Entry->second.Entries) {
1312               TrapEntry.TrapAddress = Layout.getSymbolOffset(*(Sym.MCSym)) +
1313                                       TrapEntry.Trap->getOffset();
1314             }
1315           }
1316           Sym.SymbolTableIndex = SymbolTableIndex;
1317           SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
1318           // 1 main and 1 auxiliary symbol table entry for each contained
1319           // symbol. For symbols with exception section entries, a function
1320           // auxilliary entry is needed, and on 64-bit XCOFF with debugging
1321           // enabled, an additional exception auxilliary entry is needed.
1322           SymbolTableIndex += 2;
1323           if (hasExceptionSection() && hasExceptEntry) {
1324             if (is64Bit() && ExceptionSection.isDebugEnabled)
1325               SymbolTableIndex += 2;
1326             else
1327               SymbolTableIndex += 1;
1328           }
1329         }
1330       }
1331 
1332       if (!SectionAddressSet) {
1333         Section->Address = Group->front().Address;
1334         SectionAddressSet = true;
1335       }
1336     }
1337 
1338     // Make sure the address of the next section aligned to
1339     // DefaultSectionAlign.
1340     Address = alignTo(Address, DefaultSectionAlign);
1341     Section->Size = Address - Section->Address;
1342   }
1343 
1344   // Start to generate DWARF sections. Sections other than DWARF section use
1345   // DefaultSectionAlign as the default alignment, while DWARF sections have
1346   // their own alignments. If these two alignments are not the same, we need
1347   // some paddings here and record the paddings bytes for FileOffsetToData
1348   // calculation.
1349   if (!DwarfSections.empty())
1350     PaddingsBeforeDwarf =
1351         alignTo(Address,
1352                 (*DwarfSections.begin()).DwarfSect->MCSec->getAlign()) -
1353         Address;
1354 
1355   DwarfSectionEntry *LastDwarfSection = nullptr;
1356   for (auto &DwarfSection : DwarfSections) {
1357     assert((SectionIndex <= MaxSectionIndex) && "Section index overflow!");
1358 
1359     XCOFFSection &DwarfSect = *DwarfSection.DwarfSect;
1360     const MCSectionXCOFF *MCSec = DwarfSect.MCSec;
1361 
1362     // Section index.
1363     DwarfSection.Index = SectionIndex++;
1364     SectionCount++;
1365 
1366     // Symbol index.
1367     DwarfSect.SymbolTableIndex = SymbolTableIndex;
1368     SymbolIndexMap[MCSec->getQualNameSymbol()] = DwarfSect.SymbolTableIndex;
1369     // 1 main and 1 auxiliary symbol table entry for the csect.
1370     SymbolTableIndex += 2;
1371 
1372     // Section address. Make it align to section alignment.
1373     // We use address 0 for DWARF sections' Physical and Virtual Addresses.
1374     // This address is used to tell where is the section in the final object.
1375     // See writeSectionForDwarfSectionEntry().
1376     DwarfSection.Address = DwarfSect.Address =
1377         alignTo(Address, MCSec->getAlign());
1378 
1379     // Section size.
1380     // For DWARF section, we must use the real size which may be not aligned.
1381     DwarfSection.Size = DwarfSect.Size = Layout.getSectionAddressSize(MCSec);
1382 
1383     Address = DwarfSection.Address + DwarfSection.Size;
1384 
1385     if (LastDwarfSection)
1386       LastDwarfSection->MemorySize =
1387           DwarfSection.Address - LastDwarfSection->Address;
1388     LastDwarfSection = &DwarfSection;
1389   }
1390   if (LastDwarfSection) {
1391     // Make the final DWARF section address align to the default section
1392     // alignment for follow contents.
1393     Address = alignTo(LastDwarfSection->Address + LastDwarfSection->Size,
1394                       DefaultSectionAlign);
1395     LastDwarfSection->MemorySize = Address - LastDwarfSection->Address;
1396   }
1397   if (hasExceptionSection()) {
1398     ExceptionSection.Index = SectionIndex++;
1399     SectionCount++;
1400     ExceptionSection.Address = 0;
1401     ExceptionSection.Size = getExceptionSectionSize();
1402     Address += ExceptionSection.Size;
1403     Address = alignTo(Address, DefaultSectionAlign);
1404   }
1405 
1406   SymbolTableEntryCount = SymbolTableIndex;
1407 }
1408 
1409 void XCOFFObjectWriter::writeSectionForControlSectionEntry(
1410     const MCAssembler &Asm, const MCAsmLayout &Layout,
1411     const CsectSectionEntry &CsectEntry, uint64_t &CurrentAddressLocation) {
1412   // Nothing to write for this Section.
1413   if (CsectEntry.Index == SectionEntry::UninitializedIndex)
1414     return;
1415 
1416   // There could be a gap (without corresponding zero padding) between
1417   // sections.
1418   // There could be a gap (without corresponding zero padding) between
1419   // sections.
1420   assert(((CurrentAddressLocation <= CsectEntry.Address) ||
1421           (CsectEntry.Flags == XCOFF::STYP_TDATA) ||
1422           (CsectEntry.Flags == XCOFF::STYP_TBSS)) &&
1423          "CurrentAddressLocation should be less than or equal to section "
1424          "address if the section is not TData or TBSS.");
1425 
1426   CurrentAddressLocation = CsectEntry.Address;
1427 
1428   // For virtual sections, nothing to write. But need to increase
1429   // CurrentAddressLocation for later sections like DWARF section has a correct
1430   // writing location.
1431   if (CsectEntry.IsVirtual) {
1432     CurrentAddressLocation += CsectEntry.Size;
1433     return;
1434   }
1435 
1436   for (const auto &Group : CsectEntry.Groups) {
1437     for (const auto &Csect : *Group) {
1438       if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
1439         W.OS.write_zeros(PaddingSize);
1440       if (Csect.Size)
1441         Asm.writeSectionData(W.OS, Csect.MCSec, Layout);
1442       CurrentAddressLocation = Csect.Address + Csect.Size;
1443     }
1444   }
1445 
1446   // The size of the tail padding in a section is the end virtual address of
1447   // the current section minus the the end virtual address of the last csect
1448   // in that section.
1449   if (uint64_t PaddingSize =
1450           CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) {
1451     W.OS.write_zeros(PaddingSize);
1452     CurrentAddressLocation += PaddingSize;
1453   }
1454 }
1455 
1456 void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
1457     const MCAssembler &Asm, const MCAsmLayout &Layout,
1458     const DwarfSectionEntry &DwarfEntry, uint64_t &CurrentAddressLocation) {
1459   // There could be a gap (without corresponding zero padding) between
1460   // sections. For example DWARF section alignment is bigger than
1461   // DefaultSectionAlign.
1462   assert(CurrentAddressLocation <= DwarfEntry.Address &&
1463          "CurrentAddressLocation should be less than or equal to section "
1464          "address.");
1465 
1466   if (uint64_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation)
1467     W.OS.write_zeros(PaddingSize);
1468 
1469   if (DwarfEntry.Size)
1470     Asm.writeSectionData(W.OS, DwarfEntry.DwarfSect->MCSec, Layout);
1471 
1472   CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size;
1473 
1474   // DWARF section size is not aligned to DefaultSectionAlign.
1475   // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign.
1476   uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign;
1477   uint32_t TailPaddingSize = Mod ? DefaultSectionAlign - Mod : 0;
1478   if (TailPaddingSize)
1479     W.OS.write_zeros(TailPaddingSize);
1480 
1481   CurrentAddressLocation += TailPaddingSize;
1482 }
1483 
1484 void XCOFFObjectWriter::writeSectionForExceptionSectionEntry(
1485     const MCAssembler &Asm, const MCAsmLayout &Layout,
1486     ExceptionSectionEntry &ExceptionEntry, uint64_t &CurrentAddressLocation) {
1487   for (auto it = ExceptionEntry.ExceptionTable.begin();
1488        it != ExceptionEntry.ExceptionTable.end(); it++) {
1489     // For every symbol that has exception entries, you must start the entries
1490     // with an initial symbol table index entry
1491     W.write<uint32_t>(SymbolIndexMap[it->second.FunctionSymbol]);
1492     if (is64Bit()) {
1493       // 4-byte padding on 64-bit.
1494       W.OS.write_zeros(4);
1495     }
1496     W.OS.write_zeros(2);
1497     for (auto &TrapEntry : it->second.Entries) {
1498       writeWord(TrapEntry.TrapAddress);
1499       W.write<uint8_t>(TrapEntry.Lang);
1500       W.write<uint8_t>(TrapEntry.Reason);
1501     }
1502   }
1503 
1504   CurrentAddressLocation += getExceptionSectionSize();
1505 }
1506 
1507 // Takes the log base 2 of the alignment and shifts the result into the 5 most
1508 // significant bits of a byte, then or's in the csect type into the least
1509 // significant 3 bits.
1510 uint8_t getEncodedType(const MCSectionXCOFF *Sec) {
1511   unsigned Log2Align = Log2(Sec->getAlign());
1512   // Result is a number in the range [0, 31] which fits in the 5 least
1513   // significant bits. Shift this value into the 5 most significant bits, and
1514   // bitwise-or in the csect type.
1515   uint8_t EncodedAlign = Log2Align << 3;
1516   return EncodedAlign | Sec->getCSectType();
1517 }
1518 
1519 } // end anonymous namespace
1520 
1521 std::unique_ptr<MCObjectWriter>
1522 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
1523                               raw_pwrite_stream &OS) {
1524   return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);
1525 }
1526