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