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 
getStorageClass__anond1f806720111::Symbol68   XCOFF::StorageClass getStorageClass() const {
69     return MCSym->getStorageClass();
70   }
getSymbolTableName__anond1f806720111::Symbol71   StringRef getSymbolTableName() const { return MCSym->getSymbolTableName(); }
Symbol__anond1f806720111::Symbol72   Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {}
73 };
74 
75 // Wrapper for an MCSectionXCOFF.
76 // It can be a Csect or debug section or DWARF section and so on.
77 struct XCOFFSection {
78   const MCSectionXCOFF *const MCSec;
79   uint32_t SymbolTableIndex;
80   uint32_t Address;
81   uint32_t Size;
82 
83   SmallVector<Symbol, 1> Syms;
84   SmallVector<XCOFFRelocation, 1> Relocations;
getSymbolTableName__anond1f806720111::XCOFFSection85   StringRef getSymbolTableName() const { return MCSec->getSymbolTableName(); }
XCOFFSection__anond1f806720111::XCOFFSection86   XCOFFSection(const MCSectionXCOFF *MCSec)
87       : MCSec(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
88 };
89 
90 // Type to be used for a container representing a set of csects with
91 // (approximately) the same storage mapping class. For example all the csects
92 // with a storage mapping class of `xmc_pr` will get placed into the same
93 // container.
94 using CsectGroup = std::deque<XCOFFSection>;
95 using CsectGroups = std::deque<CsectGroup *>;
96 
97 // The basic section entry defination. This Section represents a section entry
98 // in XCOFF section header table.
99 struct SectionEntry {
100   char Name[XCOFF::NameSize];
101   // The physical/virtual address of the section. For an object file
102   // these values are equivalent.
103   uint32_t Address;
104   uint32_t Size;
105   uint32_t FileOffsetToData;
106   uint32_t FileOffsetToRelocations;
107   uint32_t RelocationCount;
108   int32_t Flags;
109 
110   int16_t Index;
111 
112   // XCOFF has special section numbers for symbols:
113   // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
114   // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
115   // relocatable.
116   //  0 Specifies N_UNDEF, an undefined external symbol.
117   // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
118   // hasn't been initialized.
119   static constexpr int16_t UninitializedIndex =
120       XCOFF::ReservedSectionNum::N_DEBUG - 1;
121 
SectionEntry__anond1f806720111::SectionEntry122   SectionEntry(StringRef N, int32_t Flags)
123       : Name(), Address(0), Size(0), FileOffsetToData(0),
124         FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags),
125         Index(UninitializedIndex) {
126     assert(N.size() <= XCOFF::NameSize && "section name too long");
127     memcpy(Name, N.data(), N.size());
128   }
129 
reset__anond1f806720111::SectionEntry130   virtual void reset() {
131     Address = 0;
132     Size = 0;
133     FileOffsetToData = 0;
134     FileOffsetToRelocations = 0;
135     RelocationCount = 0;
136     Index = UninitializedIndex;
137   }
138 
~SectionEntry__anond1f806720111::SectionEntry139   virtual ~SectionEntry() {}
140 };
141 
142 // Represents the data related to a section excluding the csects that make up
143 // the raw data of the section. The csects are stored separately as not all
144 // sections contain csects, and some sections contain csects which are better
145 // stored separately, e.g. the .data section containing read-write, descriptor,
146 // TOCBase and TOC-entry csects.
147 struct CsectSectionEntry : public SectionEntry {
148   // Virtual sections do not need storage allocated in the object file.
149   const bool IsVirtual;
150 
151   // This is a section containing csect groups.
152   CsectGroups Groups;
153 
CsectSectionEntry__anond1f806720111::CsectSectionEntry154   CsectSectionEntry(StringRef N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
155                     CsectGroups Groups)
156       : SectionEntry(N, Flags), IsVirtual(IsVirtual), Groups(Groups) {
157     assert(N.size() <= XCOFF::NameSize && "section name too long");
158     memcpy(Name, N.data(), N.size());
159   }
160 
reset__anond1f806720111::CsectSectionEntry161   void reset() override {
162     SectionEntry::reset();
163     // Clear any csects we have stored.
164     for (auto *Group : Groups)
165       Group->clear();
166   }
167 
~CsectSectionEntry__anond1f806720111::CsectSectionEntry168   virtual ~CsectSectionEntry() {}
169 };
170 
171 struct DwarfSectionEntry : public SectionEntry {
172   // For DWARF section entry.
173   std::unique_ptr<XCOFFSection> DwarfSect;
174 
DwarfSectionEntry__anond1f806720111::DwarfSectionEntry175   DwarfSectionEntry(StringRef N, int32_t Flags,
176                     std::unique_ptr<XCOFFSection> Sect)
177       : SectionEntry(N, Flags | XCOFF::STYP_DWARF), DwarfSect(std::move(Sect)) {
178     assert(DwarfSect->MCSec->isDwarfSect() &&
179            "This should be a DWARF section!");
180     assert(N.size() <= XCOFF::NameSize && "section name too long");
181     memcpy(Name, N.data(), N.size());
182   }
183 
184   DwarfSectionEntry(DwarfSectionEntry &&s) = default;
185 
~DwarfSectionEntry__anond1f806720111::DwarfSectionEntry186   virtual ~DwarfSectionEntry() {}
187 };
188 
189 class XCOFFObjectWriter : public MCObjectWriter {
190 
191   uint32_t SymbolTableEntryCount = 0;
192   uint32_t SymbolTableOffset = 0;
193   uint16_t SectionCount = 0;
194   uint32_t RelocationEntryOffset = 0;
195 
196   support::endian::Writer W;
197   std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
198   StringTableBuilder Strings;
199 
200   // Maps the MCSection representation to its corresponding XCOFFSection
201   // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into
202   // from its containing MCSectionXCOFF.
203   DenseMap<const MCSectionXCOFF *, XCOFFSection *> SectionMap;
204 
205   // Maps the MCSymbol representation to its corrresponding symbol table index.
206   // Needed for relocation.
207   DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap;
208 
209   // CsectGroups. These store the csects which make up different parts of
210   // the sections. Should have one for each set of csects that get mapped into
211   // the same section and get handled in a 'similar' way.
212   CsectGroup UndefinedCsects;
213   CsectGroup ProgramCodeCsects;
214   CsectGroup ReadOnlyCsects;
215   CsectGroup DataCsects;
216   CsectGroup FuncDSCsects;
217   CsectGroup TOCCsects;
218   CsectGroup BSSCsects;
219   CsectGroup TDataCsects;
220   CsectGroup TBSSCsects;
221 
222   // The Predefined sections.
223   CsectSectionEntry Text;
224   CsectSectionEntry Data;
225   CsectSectionEntry BSS;
226   CsectSectionEntry TData;
227   CsectSectionEntry TBSS;
228 
229   // All the XCOFF sections, in the order they will appear in the section header
230   // table.
231   std::array<CsectSectionEntry *const, 5> Sections{
232       {&Text, &Data, &BSS, &TData, &TBSS}};
233 
234   std::vector<DwarfSectionEntry> DwarfSections;
235 
236   CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
237 
238   virtual void reset() override;
239 
240   void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override;
241 
242   void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *,
243                         const MCFixup &, MCValue, uint64_t &) override;
244 
245   uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override;
246 
247   static bool nameShouldBeInStringTable(const StringRef &);
248   void writeSymbolName(const StringRef &);
249   void writeSymbolTableEntryForCsectMemberLabel(const Symbol &,
250                                                 const XCOFFSection &, int16_t,
251                                                 uint64_t);
252   void writeSymbolTableEntryForControlSection(const XCOFFSection &, int16_t,
253                                               XCOFF::StorageClass);
254   void writeSymbolTableEntryForDwarfSection(const XCOFFSection &, int16_t);
255   void writeFileHeader();
256   void writeSectionHeaderTable();
257   void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
258   void writeSectionForControlSectionEntry(const MCAssembler &Asm,
259                                           const MCAsmLayout &Layout,
260                                           const CsectSectionEntry &CsectEntry,
261                                           uint32_t &CurrentAddressLocation);
262   void writeSectionForDwarfSectionEntry(const MCAssembler &Asm,
263                                         const MCAsmLayout &Layout,
264                                         const DwarfSectionEntry &DwarfEntry,
265                                         uint32_t &CurrentAddressLocation);
266   void writeSymbolTable(const MCAsmLayout &Layout);
267   void writeRelocations();
268   void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &Section);
269 
270   // Called after all the csects and symbols have been processed by
271   // `executePostLayoutBinding`, this function handles building up the majority
272   // of the structures in the object file representation. Namely:
273   // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
274   //    sizes.
275   // *) Assigns symbol table indices.
276   // *) Builds up the section header table by adding any non-empty sections to
277   //    `Sections`.
278   void assignAddressesAndIndices(const MCAsmLayout &);
279   void finalizeSectionInfo();
280 
281   bool
needsAuxiliaryHeader() const282   needsAuxiliaryHeader() const { /* TODO aux header support not implemented. */
283     return false;
284   }
285 
286   // Returns the size of the auxiliary header to be written to the object file.
auxiliaryHeaderSize() const287   size_t auxiliaryHeaderSize() const {
288     assert(!needsAuxiliaryHeader() &&
289            "Auxiliary header support not implemented.");
290     return 0;
291   }
292 
293 public:
294   XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
295                     raw_pwrite_stream &OS);
296 };
297 
XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,raw_pwrite_stream & OS)298 XCOFFObjectWriter::XCOFFObjectWriter(
299     std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
300     : W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
301       Strings(StringTableBuilder::XCOFF),
302       Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
303            CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
304       Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false,
305            CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
306       BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
307           CsectGroups{&BSSCsects}),
308       TData(".tdata", XCOFF::STYP_TDATA, /* IsVirtual */ false,
309             CsectGroups{&TDataCsects}),
310       TBSS(".tbss", XCOFF::STYP_TBSS, /* IsVirtual */ true,
311            CsectGroups{&TBSSCsects}) {}
312 
reset()313 void XCOFFObjectWriter::reset() {
314   // Clear the mappings we created.
315   SymbolIndexMap.clear();
316   SectionMap.clear();
317 
318   UndefinedCsects.clear();
319   // Reset any sections we have written to, and empty the section header table.
320   for (auto *Sec : Sections)
321     Sec->reset();
322   for (auto &DwarfSec : DwarfSections)
323     DwarfSec.reset();
324 
325   // Reset states in XCOFFObjectWriter.
326   SymbolTableEntryCount = 0;
327   SymbolTableOffset = 0;
328   SectionCount = 0;
329   RelocationEntryOffset = 0;
330   Strings.clear();
331 
332   MCObjectWriter::reset();
333 }
334 
getCsectGroup(const MCSectionXCOFF * MCSec)335 CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
336   switch (MCSec->getMappingClass()) {
337   case XCOFF::XMC_PR:
338     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
339            "Only an initialized csect can contain program code.");
340     return ProgramCodeCsects;
341   case XCOFF::XMC_RO:
342     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
343            "Only an initialized csect can contain read only data.");
344     return ReadOnlyCsects;
345   case XCOFF::XMC_RW:
346     if (XCOFF::XTY_CM == MCSec->getCSectType())
347       return BSSCsects;
348 
349     if (XCOFF::XTY_SD == MCSec->getCSectType())
350       return DataCsects;
351 
352     report_fatal_error("Unhandled mapping of read-write csect to section.");
353   case XCOFF::XMC_DS:
354     return FuncDSCsects;
355   case XCOFF::XMC_BS:
356     assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
357            "Mapping invalid csect. CSECT with bss storage class must be "
358            "common type.");
359     return BSSCsects;
360   case XCOFF::XMC_TL:
361     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
362            "Mapping invalid csect. CSECT with tdata storage class must be "
363            "an initialized csect.");
364     return TDataCsects;
365   case XCOFF::XMC_UL:
366     assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
367            "Mapping invalid csect. CSECT with tbss storage class must be "
368            "an uninitialized csect.");
369     return TBSSCsects;
370   case XCOFF::XMC_TC0:
371     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
372            "Only an initialized csect can contain TOC-base.");
373     assert(TOCCsects.empty() &&
374            "We should have only one TOC-base, and it should be the first csect "
375            "in this CsectGroup.");
376     return TOCCsects;
377   case XCOFF::XMC_TC:
378   case XCOFF::XMC_TE:
379     assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
380            "Only an initialized csect can contain TC entry.");
381     assert(!TOCCsects.empty() &&
382            "We should at least have a TOC-base in this CsectGroup.");
383     return TOCCsects;
384   case XCOFF::XMC_TD:
385     report_fatal_error("toc-data not yet supported when writing object files.");
386   default:
387     report_fatal_error("Unhandled mapping of csect to section.");
388   }
389 }
390 
getContainingCsect(const MCSymbolXCOFF * XSym)391 static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) {
392   if (XSym->isDefined())
393     return cast<MCSectionXCOFF>(XSym->getFragment()->getParent());
394   return XSym->getRepresentedCsect();
395 }
396 
executePostLayoutBinding(MCAssembler & Asm,const MCAsmLayout & Layout)397 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
398                                                  const MCAsmLayout &Layout) {
399   if (TargetObjectWriter->is64Bit())
400     report_fatal_error("64-bit XCOFF object files are not supported yet.");
401 
402   for (const auto &S : Asm) {
403     const auto *MCSec = cast<const MCSectionXCOFF>(&S);
404     assert(SectionMap.find(MCSec) == SectionMap.end() &&
405            "Cannot add a section twice.");
406 
407     // If the name does not fit in the storage provided in the symbol table
408     // entry, add it to the string table.
409     if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
410       Strings.add(MCSec->getSymbolTableName());
411     if (MCSec->isCsect()) {
412       // A new control section. Its CsectSectionEntry should already be staticly
413       // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of
414       // the CsectSectionEntry.
415       assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
416              "An undefined csect should not get registered.");
417       CsectGroup &Group = getCsectGroup(MCSec);
418       Group.emplace_back(MCSec);
419       SectionMap[MCSec] = &Group.back();
420     } else if (MCSec->isDwarfSect()) {
421       // A new DwarfSectionEntry.
422       std::unique_ptr<XCOFFSection> DwarfSec =
423           std::make_unique<XCOFFSection>(MCSec);
424       SectionMap[MCSec] = DwarfSec.get();
425 
426       DwarfSectionEntry SecEntry(MCSec->getName(),
427                                  MCSec->getDwarfSubtypeFlags().getValue(),
428                                  std::move(DwarfSec));
429       DwarfSections.push_back(std::move(SecEntry));
430     } else
431       llvm_unreachable("unsupport section type!");
432   }
433 
434   for (const MCSymbol &S : Asm.symbols()) {
435     // Nothing to do for temporary symbols.
436     if (S.isTemporary())
437       continue;
438 
439     const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
440     const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym);
441 
442     if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
443       // Handle undefined symbol.
444       UndefinedCsects.emplace_back(ContainingCsect);
445       SectionMap[ContainingCsect] = &UndefinedCsects.back();
446       if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName()))
447         Strings.add(ContainingCsect->getSymbolTableName());
448       continue;
449     }
450 
451     // If the symbol is the csect itself, we don't need to put the symbol
452     // into csect's Syms.
453     if (XSym == ContainingCsect->getQualNameSymbol())
454       continue;
455 
456     // Only put a label into the symbol table when it is an external label.
457     if (!XSym->isExternal())
458       continue;
459 
460     assert(SectionMap.find(ContainingCsect) != SectionMap.end() &&
461            "Expected containing csect to exist in map");
462     XCOFFSection *Csect = SectionMap[ContainingCsect];
463     // Lookup the containing csect and add the symbol to it.
464     assert(Csect->MCSec->isCsect() && "only csect is supported now!");
465     Csect->Syms.emplace_back(XSym);
466 
467     // If the name does not fit in the storage provided in the symbol table
468     // entry, add it to the string table.
469     if (nameShouldBeInStringTable(XSym->getSymbolTableName()))
470       Strings.add(XSym->getSymbolTableName());
471   }
472 
473   Strings.finalize();
474   assignAddressesAndIndices(Layout);
475 }
476 
recordRelocation(MCAssembler & Asm,const MCAsmLayout & Layout,const MCFragment * Fragment,const MCFixup & Fixup,MCValue Target,uint64_t & FixedValue)477 void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
478                                          const MCAsmLayout &Layout,
479                                          const MCFragment *Fragment,
480                                          const MCFixup &Fixup, MCValue Target,
481                                          uint64_t &FixedValue) {
482   auto getIndex = [this](const MCSymbol *Sym,
483                          const MCSectionXCOFF *ContainingCsect) {
484     // If we could not find the symbol directly in SymbolIndexMap, this symbol
485     // could either be a temporary symbol or an undefined symbol. In this case,
486     // we would need to have the relocation reference its csect instead.
487     return SymbolIndexMap.find(Sym) != SymbolIndexMap.end()
488                ? SymbolIndexMap[Sym]
489                : SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
490   };
491 
492   auto getVirtualAddress =
493       [this, &Layout](const MCSymbol *Sym,
494                       const MCSectionXCOFF *ContainingSect) -> uint64_t {
495     // A DWARF section.
496     if (ContainingSect->isDwarfSect())
497       return Layout.getSymbolOffset(*Sym);
498 
499     // A csect.
500     if (!Sym->isDefined())
501       return SectionMap[ContainingSect]->Address;
502 
503     // A label.
504     assert(Sym->isDefined() && "not a valid object that has address!");
505     return SectionMap[ContainingSect]->Address + Layout.getSymbolOffset(*Sym);
506   };
507 
508   const MCSymbol *const SymA = &Target.getSymA()->getSymbol();
509 
510   MCAsmBackend &Backend = Asm.getBackend();
511   bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
512                  MCFixupKindInfo::FKF_IsPCRel;
513 
514   uint8_t Type;
515   uint8_t SignAndSize;
516   std::tie(Type, SignAndSize) =
517       TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel);
518 
519   const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
520 
521   if (SymASec->isCsect() && SymASec->getMappingClass() == XCOFF::XMC_TD)
522     report_fatal_error("toc-data not yet supported when writing object files.");
523 
524   assert(SectionMap.find(SymASec) != SectionMap.end() &&
525          "Expected containing csect to exist in map.");
526 
527   const uint32_t Index = getIndex(SymA, SymASec);
528   if (Type == XCOFF::RelocationType::R_POS ||
529       Type == XCOFF::RelocationType::R_TLS)
530     // The FixedValue should be symbol's virtual address in this object file
531     // plus any constant value that we might get.
532     FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
533   else if (Type == XCOFF::RelocationType::R_TLSM)
534     // The FixedValue should always be zero since the region handle is only
535     // known at load time.
536     FixedValue = 0;
537   else if (Type == XCOFF::RelocationType::R_TOC ||
538            Type == XCOFF::RelocationType::R_TOCL) {
539     // The FixedValue should be the TOC entry offset from the TOC-base plus any
540     // constant offset value.
541     const int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
542                                    TOCCsects.front().Address +
543                                    Target.getConstant();
544     if (Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset))
545       report_fatal_error("TOCEntryOffset overflows in small code model mode");
546 
547     FixedValue = TOCEntryOffset;
548   }
549 
550   assert(
551       (TargetObjectWriter->is64Bit() ||
552        Fixup.getOffset() <= UINT32_MAX - Layout.getFragmentOffset(Fragment)) &&
553       "Fragment offset + fixup offset is overflowed in 32-bit mode.");
554   uint32_t FixupOffsetInCsect =
555       Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
556 
557   XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
558   MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent());
559   assert(SectionMap.find(RelocationSec) != SectionMap.end() &&
560          "Expected containing csect to exist in map.");
561   SectionMap[RelocationSec]->Relocations.push_back(Reloc);
562 
563   if (!Target.getSymB())
564     return;
565 
566   const MCSymbol *const SymB = &Target.getSymB()->getSymbol();
567   if (SymA == SymB)
568     report_fatal_error("relocation for opposite term is not yet supported");
569 
570   const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
571   assert(SectionMap.find(SymBSec) != SectionMap.end() &&
572          "Expected containing csect to exist in map.");
573   if (SymASec == SymBSec)
574     report_fatal_error(
575         "relocation for paired relocatable term is not yet supported");
576 
577   assert(Type == XCOFF::RelocationType::R_POS &&
578          "SymA must be R_POS here if it's not opposite term or paired "
579          "relocatable term.");
580   const uint32_t IndexB = getIndex(SymB, SymBSec);
581   // SymB must be R_NEG here, given the general form of Target(MCValue) is
582   // "SymbolA - SymbolB + imm64".
583   const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
584   XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
585   SectionMap[RelocationSec]->Relocations.push_back(RelocB);
586   // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
587   // now we just need to fold "- SymbolB" here.
588   FixedValue -= getVirtualAddress(SymB, SymBSec);
589 }
590 
writeSections(const MCAssembler & Asm,const MCAsmLayout & Layout)591 void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
592                                       const MCAsmLayout &Layout) {
593   uint32_t CurrentAddressLocation = 0;
594   for (const auto *Section : Sections)
595     writeSectionForControlSectionEntry(Asm, Layout, *Section,
596                                        CurrentAddressLocation);
597   for (const auto &DwarfSection : DwarfSections)
598     writeSectionForDwarfSectionEntry(Asm, Layout, DwarfSection,
599                                      CurrentAddressLocation);
600 }
601 
writeObject(MCAssembler & Asm,const MCAsmLayout & Layout)602 uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
603                                         const MCAsmLayout &Layout) {
604   // We always emit a timestamp of 0 for reproducibility, so ensure incremental
605   // linking is not enabled, in case, like with Windows COFF, such a timestamp
606   // is incompatible with incremental linking of XCOFF.
607   if (Asm.isIncrementalLinkerCompatible())
608     report_fatal_error("Incremental linking not supported for XCOFF.");
609 
610   if (TargetObjectWriter->is64Bit())
611     report_fatal_error("64-bit XCOFF object files are not supported yet.");
612 
613   finalizeSectionInfo();
614   uint64_t StartOffset = W.OS.tell();
615 
616   writeFileHeader();
617   writeSectionHeaderTable();
618   writeSections(Asm, Layout);
619   writeRelocations();
620 
621   writeSymbolTable(Layout);
622   // Write the string table.
623   Strings.write(W.OS);
624 
625   return W.OS.tell() - StartOffset;
626 }
627 
nameShouldBeInStringTable(const StringRef & SymbolName)628 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
629   return SymbolName.size() > XCOFF::NameSize;
630 }
631 
writeSymbolName(const StringRef & SymbolName)632 void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) {
633   if (nameShouldBeInStringTable(SymbolName)) {
634     W.write<int32_t>(0);
635     W.write<uint32_t>(Strings.getOffset(SymbolName));
636   } else {
637     char Name[XCOFF::NameSize+1];
638     std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
639     ArrayRef<char> NameRef(Name, XCOFF::NameSize);
640     W.write(NameRef);
641   }
642 }
643 
writeSymbolTableEntryForCsectMemberLabel(const Symbol & SymbolRef,const XCOFFSection & CSectionRef,int16_t SectionIndex,uint64_t SymbolOffset)644 void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel(
645     const Symbol &SymbolRef, const XCOFFSection &CSectionRef,
646     int16_t SectionIndex, uint64_t SymbolOffset) {
647   // Name or Zeros and string table offset
648   writeSymbolName(SymbolRef.getSymbolTableName());
649   assert(SymbolOffset <= UINT32_MAX - CSectionRef.Address &&
650          "Symbol address overflows.");
651   W.write<uint32_t>(CSectionRef.Address + SymbolOffset);
652   W.write<int16_t>(SectionIndex);
653   // Basic/Derived type. See the description of the n_type field for symbol
654   // table entries for a detailed description. Since we don't yet support
655   // visibility, and all other bits are either optionally set or reserved, this
656   // is always zero.
657   // TODO FIXME How to assert a symbol's visibilty is default?
658   // TODO Set the function indicator (bit 10, 0x0020) for functions
659   // when debugging is enabled.
660   W.write<uint16_t>(0);
661   W.write<uint8_t>(SymbolRef.getStorageClass());
662   // Always 1 aux entry for now.
663   W.write<uint8_t>(1);
664 
665   // Now output the auxiliary entry.
666   W.write<uint32_t>(CSectionRef.SymbolTableIndex);
667   // Parameter typecheck hash. Not supported.
668   W.write<uint32_t>(0);
669   // Typecheck section number. Not supported.
670   W.write<uint16_t>(0);
671   // Symbol type: Label
672   W.write<uint8_t>(XCOFF::XTY_LD);
673   // Storage mapping class.
674   W.write<uint8_t>(CSectionRef.MCSec->getMappingClass());
675   // Reserved (x_stab).
676   W.write<uint32_t>(0);
677   // Reserved (x_snstab).
678   W.write<uint16_t>(0);
679 }
680 
writeSymbolTableEntryForDwarfSection(const XCOFFSection & DwarfSectionRef,int16_t SectionIndex)681 void XCOFFObjectWriter::writeSymbolTableEntryForDwarfSection(
682     const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) {
683   assert(DwarfSectionRef.MCSec->isDwarfSect() && "Not a DWARF section!");
684 
685   // n_name, n_zeros, n_offset
686   writeSymbolName(DwarfSectionRef.getSymbolTableName());
687   // n_value
688   W.write<uint32_t>(0);
689   // n_scnum
690   W.write<int16_t>(SectionIndex);
691   // n_type
692   W.write<uint16_t>(0);
693   // n_sclass
694   W.write<uint8_t>(XCOFF::C_DWARF);
695   // Always 1 aux entry for now.
696   W.write<uint8_t>(1);
697 
698   // Now output the auxiliary entry.
699   // x_scnlen
700   W.write<uint32_t>(DwarfSectionRef.Size);
701   // Reserved
702   W.write<uint32_t>(0);
703   // x_nreloc. Set to 0 for now.
704   W.write<uint32_t>(0);
705   // Reserved
706   W.write<uint32_t>(0);
707   // Reserved
708   W.write<uint16_t>(0);
709 }
710 
writeSymbolTableEntryForControlSection(const XCOFFSection & CSectionRef,int16_t SectionIndex,XCOFF::StorageClass StorageClass)711 void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
712     const XCOFFSection &CSectionRef, int16_t SectionIndex,
713     XCOFF::StorageClass StorageClass) {
714   // n_name, n_zeros, n_offset
715   writeSymbolName(CSectionRef.getSymbolTableName());
716   // n_value
717   W.write<uint32_t>(CSectionRef.Address);
718   // n_scnum
719   W.write<int16_t>(SectionIndex);
720   // Basic/Derived type. See the description of the n_type field for symbol
721   // table entries for a detailed description. Since we don't yet support
722   // visibility, and all other bits are either optionally set or reserved, this
723   // is always zero.
724   // TODO FIXME How to assert a symbol's visibilty is default?
725   // TODO Set the function indicator (bit 10, 0x0020) for functions
726   // when debugging is enabled.
727   W.write<uint16_t>(0);
728   // n_sclass
729   W.write<uint8_t>(StorageClass);
730   // Always 1 aux entry for now.
731   W.write<uint8_t>(1);
732 
733   // Now output the auxiliary entry.
734   W.write<uint32_t>(CSectionRef.Size);
735   // Parameter typecheck hash. Not supported.
736   W.write<uint32_t>(0);
737   // Typecheck section number. Not supported.
738   W.write<uint16_t>(0);
739   // Symbol type.
740   W.write<uint8_t>(getEncodedType(CSectionRef.MCSec));
741   // Storage mapping class.
742   W.write<uint8_t>(CSectionRef.MCSec->getMappingClass());
743   // Reserved (x_stab).
744   W.write<uint32_t>(0);
745   // Reserved (x_snstab).
746   W.write<uint16_t>(0);
747 }
748 
writeFileHeader()749 void XCOFFObjectWriter::writeFileHeader() {
750   // Magic.
751   W.write<uint16_t>(0x01df);
752   // Number of sections.
753   W.write<uint16_t>(SectionCount);
754   // Timestamp field. For reproducible output we write a 0, which represents no
755   // timestamp.
756   W.write<int32_t>(0);
757   // Byte Offset to the start of the symbol table.
758   W.write<uint32_t>(SymbolTableOffset);
759   // Number of entries in the symbol table.
760   W.write<int32_t>(SymbolTableEntryCount);
761   // Size of the optional header.
762   W.write<uint16_t>(0);
763   // Flags.
764   W.write<uint16_t>(0);
765 }
766 
writeSectionHeaderTable()767 void XCOFFObjectWriter::writeSectionHeaderTable() {
768   auto writeSectionHeader = [&](const SectionEntry *Sec, bool IsDwarf) {
769     // Nothing to write for this Section.
770     if (Sec->Index == SectionEntry::UninitializedIndex)
771       return false;
772 
773     // Write Name.
774     ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
775     W.write(NameRef);
776 
777     // Write the Physical Address and Virtual Address. In an object file these
778     // are the same.
779     // We use 0 for DWARF sections' Physical and Virtual Addresses.
780     if (!IsDwarf) {
781       W.write<uint32_t>(Sec->Address);
782       W.write<uint32_t>(Sec->Address);
783     } else {
784       W.write<uint32_t>(0);
785       W.write<uint32_t>(0);
786     }
787 
788     W.write<uint32_t>(Sec->Size);
789     W.write<uint32_t>(Sec->FileOffsetToData);
790     W.write<uint32_t>(Sec->FileOffsetToRelocations);
791 
792     // Line number pointer. Not supported yet.
793     W.write<uint32_t>(0);
794 
795     W.write<uint16_t>(Sec->RelocationCount);
796 
797     // Line number counts. Not supported yet.
798     W.write<uint16_t>(0);
799 
800     W.write<int32_t>(Sec->Flags);
801 
802     return true;
803   };
804 
805   for (const auto *CsectSec : Sections)
806     writeSectionHeader(CsectSec, /* IsDwarf */ false);
807   for (const auto &DwarfSec : DwarfSections)
808     writeSectionHeader(&DwarfSec, /* IsDwarf */ true);
809 }
810 
writeRelocation(XCOFFRelocation Reloc,const XCOFFSection & Section)811 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
812                                         const XCOFFSection &Section) {
813   if (Section.MCSec->isCsect())
814     W.write<uint32_t>(Section.Address + Reloc.FixupOffsetInCsect);
815   else {
816     // DWARF sections' address is set to 0.
817     assert(Section.MCSec->isDwarfSect() && "unsupport section type!");
818     W.write<uint32_t>(Reloc.FixupOffsetInCsect);
819   }
820   W.write<uint32_t>(Reloc.SymbolTableIndex);
821   W.write<uint8_t>(Reloc.SignAndSize);
822   W.write<uint8_t>(Reloc.Type);
823 }
824 
writeRelocations()825 void XCOFFObjectWriter::writeRelocations() {
826   for (const auto *Section : Sections) {
827     if (Section->Index == SectionEntry::UninitializedIndex)
828       // Nothing to write for this Section.
829       continue;
830 
831     for (const auto *Group : Section->Groups) {
832       if (Group->empty())
833         continue;
834 
835       for (const auto &Csect : *Group) {
836         for (const auto Reloc : Csect.Relocations)
837           writeRelocation(Reloc, Csect);
838       }
839     }
840   }
841 
842   for (const auto &DwarfSection : DwarfSections)
843     for (const auto &Reloc : DwarfSection.DwarfSect->Relocations)
844       writeRelocation(Reloc, *DwarfSection.DwarfSect);
845 }
846 
writeSymbolTable(const MCAsmLayout & Layout)847 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
848   // Write symbol 0 as C_FILE.
849   // FIXME: support 64-bit C_FILE symbol.
850   //
851   // n_name. The n_name of a C_FILE symbol is the source filename when no
852   // auxiliary entries are present. The source filename is alternatively
853   // provided by an auxiliary entry, in which case the n_name of the C_FILE
854   // symbol is `.file`.
855   // FIXME: add the real source filename.
856   writeSymbolName(".file");
857   // n_value. The n_value of a C_FILE symbol is its symbol table index.
858   W.write<uint32_t>(0);
859   // n_scnum. N_DEBUG is a reserved section number for indicating a special
860   // symbolic debugging symbol.
861   W.write<int16_t>(XCOFF::ReservedSectionNum::N_DEBUG);
862   // n_type. The n_type field of a C_FILE symbol encodes the source language and
863   // CPU version info; zero indicates no info.
864   W.write<uint16_t>(0);
865   // n_sclass. The C_FILE symbol provides source file-name information,
866   // source-language ID and CPU-version ID information and some other optional
867   // infos.
868   W.write<uint8_t>(XCOFF::C_FILE);
869   // n_numaux. No aux entry for now.
870   W.write<uint8_t>(0);
871 
872   for (const auto &Csect : UndefinedCsects) {
873     writeSymbolTableEntryForControlSection(Csect,
874                                            XCOFF::ReservedSectionNum::N_UNDEF,
875                                            Csect.MCSec->getStorageClass());
876   }
877 
878   for (const auto *Section : Sections) {
879     if (Section->Index == SectionEntry::UninitializedIndex)
880       // Nothing to write for this Section.
881       continue;
882 
883     for (const auto *Group : Section->Groups) {
884       if (Group->empty())
885         continue;
886 
887       const int16_t SectionIndex = Section->Index;
888       for (const auto &Csect : *Group) {
889         // Write out the control section first and then each symbol in it.
890         writeSymbolTableEntryForControlSection(Csect, SectionIndex,
891                                                Csect.MCSec->getStorageClass());
892 
893         for (const auto &Sym : Csect.Syms)
894           writeSymbolTableEntryForCsectMemberLabel(
895               Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
896       }
897     }
898   }
899 
900   for (const auto &DwarfSection : DwarfSections)
901     writeSymbolTableEntryForDwarfSection(*DwarfSection.DwarfSect,
902                                          DwarfSection.Index);
903 }
904 
finalizeSectionInfo()905 void XCOFFObjectWriter::finalizeSectionInfo() {
906   for (auto *Section : Sections) {
907     if (Section->Index == SectionEntry::UninitializedIndex)
908       // Nothing to record for this Section.
909       continue;
910 
911     for (const auto *Group : Section->Groups) {
912       if (Group->empty())
913         continue;
914 
915       for (auto &Csect : *Group) {
916         const size_t CsectRelocCount = Csect.Relocations.size();
917         if (CsectRelocCount >= XCOFF::RelocOverflow ||
918             Section->RelocationCount >= XCOFF::RelocOverflow - CsectRelocCount)
919           report_fatal_error(
920               "relocation entries overflowed; overflow section is "
921               "not implemented yet");
922 
923         Section->RelocationCount += CsectRelocCount;
924       }
925     }
926   }
927 
928   for (auto &DwarfSection : DwarfSections)
929     DwarfSection.RelocationCount = DwarfSection.DwarfSect->Relocations.size();
930 
931   // Calculate the file offset to the relocation entries.
932   uint64_t RawPointer = RelocationEntryOffset;
933   auto calcOffsetToRelocations = [&](SectionEntry *Sec, bool IsDwarf) {
934     if (!IsDwarf && Sec->Index == SectionEntry::UninitializedIndex)
935       return false;
936 
937     if (!Sec->RelocationCount)
938       return false;
939 
940     Sec->FileOffsetToRelocations = RawPointer;
941     const uint32_t RelocationSizeInSec =
942         Sec->RelocationCount * XCOFF::RelocationSerializationSize32;
943     RawPointer += RelocationSizeInSec;
944     if (RawPointer > UINT32_MAX)
945       report_fatal_error("Relocation data overflowed this object file.");
946 
947     return true;
948   };
949 
950   for (auto *Sec : Sections)
951     calcOffsetToRelocations(Sec, /* IsDwarf */ false);
952 
953   for (auto &DwarfSec : DwarfSections)
954     calcOffsetToRelocations(&DwarfSec, /* IsDwarf */ true);
955 
956   // TODO Error check that the number of symbol table entries fits in 32-bits
957   // signed ...
958   if (SymbolTableEntryCount)
959     SymbolTableOffset = RawPointer;
960 }
961 
assignAddressesAndIndices(const MCAsmLayout & Layout)962 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
963   // The first symbol table entry (at index 0) is for the file name.
964   uint32_t SymbolTableIndex = 1;
965 
966   // Calculate indices for undefined symbols.
967   for (auto &Csect : UndefinedCsects) {
968     Csect.Size = 0;
969     Csect.Address = 0;
970     Csect.SymbolTableIndex = SymbolTableIndex;
971     SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
972     // 1 main and 1 auxiliary symbol table entry for each contained symbol.
973     SymbolTableIndex += 2;
974   }
975 
976   // The address corrresponds to the address of sections and symbols in the
977   // object file. We place the shared address 0 immediately after the
978   // section header table.
979   uint32_t Address = 0;
980   // Section indices are 1-based in XCOFF.
981   int32_t SectionIndex = 1;
982   bool HasTDataSection = false;
983 
984   for (auto *Section : Sections) {
985     const bool IsEmpty =
986         llvm::all_of(Section->Groups,
987                      [](const CsectGroup *Group) { return Group->empty(); });
988     if (IsEmpty)
989       continue;
990 
991     if (SectionIndex > MaxSectionIndex)
992       report_fatal_error("Section index overflow!");
993     Section->Index = SectionIndex++;
994     SectionCount++;
995 
996     bool SectionAddressSet = false;
997     // Reset the starting address to 0 for TData section.
998     if (Section->Flags == XCOFF::STYP_TDATA) {
999       Address = 0;
1000       HasTDataSection = true;
1001     }
1002     // Reset the starting address to 0 for TBSS section if the object file does
1003     // not contain TData Section.
1004     if ((Section->Flags == XCOFF::STYP_TBSS) && !HasTDataSection)
1005       Address = 0;
1006 
1007     for (auto *Group : Section->Groups) {
1008       if (Group->empty())
1009         continue;
1010 
1011       for (auto &Csect : *Group) {
1012         const MCSectionXCOFF *MCSec = Csect.MCSec;
1013         Csect.Address = alignTo(Address, MCSec->getAlignment());
1014         Csect.Size = Layout.getSectionAddressSize(MCSec);
1015         Address = Csect.Address + Csect.Size;
1016         Csect.SymbolTableIndex = SymbolTableIndex;
1017         SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
1018         // 1 main and 1 auxiliary symbol table entry for the csect.
1019         SymbolTableIndex += 2;
1020 
1021         for (auto &Sym : Csect.Syms) {
1022           Sym.SymbolTableIndex = SymbolTableIndex;
1023           SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
1024           // 1 main and 1 auxiliary symbol table entry for each contained
1025           // symbol.
1026           SymbolTableIndex += 2;
1027         }
1028       }
1029 
1030       if (!SectionAddressSet) {
1031         Section->Address = Group->front().Address;
1032         SectionAddressSet = true;
1033       }
1034     }
1035 
1036     // Make sure the address of the next section aligned to
1037     // DefaultSectionAlign.
1038     Address = alignTo(Address, DefaultSectionAlign);
1039     Section->Size = Address - Section->Address;
1040   }
1041 
1042   for (auto &DwarfSection : DwarfSections) {
1043     assert((SectionIndex <= MaxSectionIndex) && "Section index overflow!");
1044 
1045     XCOFFSection &DwarfSect = *DwarfSection.DwarfSect;
1046     const MCSectionXCOFF *MCSec = DwarfSect.MCSec;
1047 
1048     // Section index.
1049     DwarfSection.Index = SectionIndex++;
1050     SectionCount++;
1051 
1052     // Symbol index.
1053     DwarfSect.SymbolTableIndex = SymbolTableIndex;
1054     SymbolIndexMap[MCSec->getQualNameSymbol()] = DwarfSect.SymbolTableIndex;
1055     // 1 main and 1 auxiliary symbol table entry for the csect.
1056     SymbolTableIndex += 2;
1057 
1058     // Section address. Make it align to section alignment.
1059     // We use address 0 for DWARF sections' Physical and Virtual Addresses.
1060     // This address is used to tell where is the section in the final object.
1061     // See writeSectionForDwarfSectionEntry().
1062     DwarfSection.Address = DwarfSect.Address =
1063         alignTo(Address, MCSec->getAlignment());
1064 
1065     // Section size.
1066     // For DWARF section, we must use the real size which may be not aligned.
1067     DwarfSection.Size = DwarfSect.Size = Layout.getSectionAddressSize(MCSec);
1068 
1069     // Make the Address align to default alignment for follow section.
1070     Address = alignTo(DwarfSect.Address + DwarfSect.Size, DefaultSectionAlign);
1071   }
1072 
1073   SymbolTableEntryCount = SymbolTableIndex;
1074 
1075   // Calculate the RawPointer value for each section.
1076   uint64_t RawPointer = XCOFF::FileHeaderSize32 + auxiliaryHeaderSize() +
1077                         SectionCount * XCOFF::SectionHeaderSize32;
1078   for (auto *Sec : Sections) {
1079     if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual)
1080       continue;
1081 
1082     Sec->FileOffsetToData = RawPointer;
1083     RawPointer += Sec->Size;
1084     if (RawPointer > UINT32_MAX)
1085       report_fatal_error("Section raw data overflowed this object file.");
1086   }
1087 
1088   for (auto &DwarfSection : DwarfSections) {
1089     // Address of csect sections are always aligned to DefaultSectionAlign, but
1090     // address of DWARF section are aligned to Section alignment which may be
1091     // bigger than DefaultSectionAlign, need to execlude the padding bits.
1092     RawPointer =
1093           alignTo(RawPointer, DwarfSection.DwarfSect->MCSec->getAlignment());
1094 
1095     DwarfSection.FileOffsetToData = RawPointer;
1096     // Some section entries, like DWARF section size is not aligned, so
1097     // RawPointer may be not aligned.
1098     RawPointer += DwarfSection.Size;
1099     // Make sure RawPointer is aligned.
1100     RawPointer = alignTo(RawPointer, DefaultSectionAlign);
1101 
1102     assert(RawPointer <= UINT32_MAX &&
1103            "Section raw data overflowed this object file.");
1104   }
1105 
1106   RelocationEntryOffset = RawPointer;
1107 }
1108 
writeSectionForControlSectionEntry(const MCAssembler & Asm,const MCAsmLayout & Layout,const CsectSectionEntry & CsectEntry,uint32_t & CurrentAddressLocation)1109 void XCOFFObjectWriter::writeSectionForControlSectionEntry(
1110     const MCAssembler &Asm, const MCAsmLayout &Layout,
1111     const CsectSectionEntry &CsectEntry, uint32_t &CurrentAddressLocation) {
1112   // Nothing to write for this Section.
1113   if (CsectEntry.Index == SectionEntry::UninitializedIndex)
1114     return;
1115 
1116   // There could be a gap (without corresponding zero padding) between
1117   // sections.
1118   // There could be a gap (without corresponding zero padding) between
1119   // sections.
1120   assert(((CurrentAddressLocation <= CsectEntry.Address) ||
1121           (CsectEntry.Flags == XCOFF::STYP_TDATA) ||
1122           (CsectEntry.Flags == XCOFF::STYP_TBSS)) &&
1123          "CurrentAddressLocation should be less than or equal to section "
1124          "address if the section is not TData or TBSS.");
1125 
1126   CurrentAddressLocation = CsectEntry.Address;
1127 
1128   // For virtual sections, nothing to write. But need to increase
1129   // CurrentAddressLocation for later sections like DWARF section has a correct
1130   // writing location.
1131   if (CsectEntry.IsVirtual) {
1132     CurrentAddressLocation += CsectEntry.Size;
1133     return;
1134   }
1135 
1136   for (const auto &Group : CsectEntry.Groups) {
1137     for (const auto &Csect : *Group) {
1138       if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
1139         W.OS.write_zeros(PaddingSize);
1140       if (Csect.Size)
1141         Asm.writeSectionData(W.OS, Csect.MCSec, Layout);
1142       CurrentAddressLocation = Csect.Address + Csect.Size;
1143     }
1144   }
1145 
1146   // The size of the tail padding in a section is the end virtual address of
1147   // the current section minus the the end virtual address of the last csect
1148   // in that section.
1149   if (uint32_t PaddingSize =
1150           CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) {
1151     W.OS.write_zeros(PaddingSize);
1152     CurrentAddressLocation += PaddingSize;
1153   }
1154 }
1155 
writeSectionForDwarfSectionEntry(const MCAssembler & Asm,const MCAsmLayout & Layout,const DwarfSectionEntry & DwarfEntry,uint32_t & CurrentAddressLocation)1156 void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
1157     const MCAssembler &Asm, const MCAsmLayout &Layout,
1158     const DwarfSectionEntry &DwarfEntry, uint32_t &CurrentAddressLocation) {
1159   // There could be a gap (without corresponding zero padding) between
1160   // sections. For example DWARF section alignment is bigger than
1161   // DefaultSectionAlign.
1162   assert(CurrentAddressLocation <= DwarfEntry.Address &&
1163          "CurrentAddressLocation should be less than or equal to section "
1164          "address.");
1165 
1166   if (uint32_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation)
1167     W.OS.write_zeros(PaddingSize);
1168 
1169   if (DwarfEntry.Size)
1170     Asm.writeSectionData(W.OS, DwarfEntry.DwarfSect->MCSec, Layout);
1171 
1172   CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size;
1173 
1174   // DWARF section size is not aligned to DefaultSectionAlign.
1175   // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign.
1176   uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign;
1177   uint32_t TailPaddingSize = Mod ? DefaultSectionAlign - Mod : 0;
1178   if (TailPaddingSize)
1179     W.OS.write_zeros(TailPaddingSize);
1180 
1181   CurrentAddressLocation += TailPaddingSize;
1182 }
1183 
1184 // Takes the log base 2 of the alignment and shifts the result into the 5 most
1185 // significant bits of a byte, then or's in the csect type into the least
1186 // significant 3 bits.
getEncodedType(const MCSectionXCOFF * Sec)1187 uint8_t getEncodedType(const MCSectionXCOFF *Sec) {
1188   unsigned Align = Sec->getAlignment();
1189   assert(isPowerOf2_32(Align) && "Alignment must be a power of 2.");
1190   unsigned Log2Align = Log2_32(Align);
1191   // Result is a number in the range [0, 31] which fits in the 5 least
1192   // significant bits. Shift this value into the 5 most significant bits, and
1193   // bitwise-or in the csect type.
1194   uint8_t EncodedAlign = Log2Align << 3;
1195   return EncodedAlign | Sec->getCSectType();
1196 }
1197 
1198 } // end anonymous namespace
1199 
1200 std::unique_ptr<MCObjectWriter>
createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,raw_pwrite_stream & OS)1201 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
1202                               raw_pwrite_stream &OS) {
1203   return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);
1204 }
1205