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