1 //===-- lib/MC/XCOFFObjectWriter.cpp - XCOFF file writer ------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements XCOFF object file writer information.
11 //===----------------------------------------------------------------------===//
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"
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.
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.
50 constexpr unsigned DefaultSectionAlign = 4;
51 constexpr int16_t MaxSectionIndex = INT16_MAX;
53 // Packs the csect's alignment and type into a byte.
54 uint8_t getEncodedType(const MCSectionXCOFF *);
56 struct XCOFFRelocation {
57 uint32_t SymbolTableIndex;
58 uint32_t FixupOffsetInCsect;
63 // Wrapper around an MCSymbolXCOFF.
65 const MCSymbolXCOFF *const MCSym;
66 uint32_t SymbolTableIndex;
68 XCOFF::StorageClass getStorageClass() const {
69 return MCSym->getStorageClass();
71 StringRef getSymbolTableName() const { return MCSym->getSymbolTableName(); }
72 Symbol(const MCSymbolXCOFF *MCSym) : MCSym(MCSym), SymbolTableIndex(-1) {}
75 // Wrapper for an MCSectionXCOFF.
76 struct ControlSection {
77 const MCSectionXCOFF *const MCCsect;
78 uint32_t SymbolTableIndex;
82 SmallVector<Symbol, 1> Syms;
83 SmallVector<XCOFFRelocation, 1> Relocations;
84 StringRef getSymbolTableName() const { return MCCsect->getSymbolTableName(); }
85 ControlSection(const MCSectionXCOFF *MCSec)
86 : MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {}
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
93 using CsectGroup = std::deque<ControlSection>;
94 using CsectGroups = std::deque<CsectGroup *>;
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.
102 char Name[XCOFF::NameSize];
103 // The physical/virtual address of the section. For an object file
104 // these values are equivalent.
107 uint32_t FileOffsetToData;
108 uint32_t FileOffsetToRelocations;
109 uint32_t RelocationCount;
114 // Virtual sections do not need storage allocated in the object file.
115 const bool IsVirtual;
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
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;
132 FileOffsetToData = 0;
133 FileOffsetToRelocations = 0;
135 Index = UninitializedIndex;
136 // Clear any csects we have stored.
137 for (auto *Group : Groups)
141 Section(const char *N, XCOFF::SectionTypeFlags Flags, bool IsVirtual,
143 : Address(0), Size(0), FileOffsetToData(0), FileOffsetToRelocations(0),
144 RelocationCount(0), Flags(Flags), Index(UninitializedIndex),
145 IsVirtual(IsVirtual), Groups(Groups) {
146 strncpy(Name, N, XCOFF::NameSize);
150 class XCOFFObjectWriter : public MCObjectWriter {
152 uint32_t SymbolTableEntryCount = 0;
153 uint32_t SymbolTableOffset = 0;
154 uint16_t SectionCount = 0;
155 uint32_t RelocationEntryOffset = 0;
157 support::endian::Writer W;
158 std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
159 StringTableBuilder Strings;
161 // Maps the MCSection representation to its corresponding ControlSection
162 // wrapper. Needed for finding the ControlSection to insert an MCSymbol into
163 // from its containing MCSectionXCOFF.
164 DenseMap<const MCSectionXCOFF *, ControlSection *> SectionMap;
166 // Maps the MCSymbol representation to its corrresponding symbol table index.
167 // Needed for relocation.
168 DenseMap<const MCSymbol *, uint32_t> SymbolIndexMap;
170 // CsectGroups. These store the csects which make up different parts of
171 // the sections. Should have one for each set of csects that get mapped into
172 // the same section and get handled in a 'similar' way.
173 CsectGroup UndefinedCsects;
174 CsectGroup ProgramCodeCsects;
175 CsectGroup ReadOnlyCsects;
176 CsectGroup DataCsects;
177 CsectGroup FuncDSCsects;
178 CsectGroup TOCCsects;
179 CsectGroup BSSCsects;
181 // The Predefined sections.
186 // All the XCOFF sections, in the order they will appear in the section header
188 std::array<Section *const, 3> Sections{{&Text, &Data, &BSS}};
190 CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec);
192 virtual void reset() override;
194 void executePostLayoutBinding(MCAssembler &, const MCAsmLayout &) override;
196 void recordRelocation(MCAssembler &, const MCAsmLayout &, const MCFragment *,
197 const MCFixup &, MCValue, uint64_t &) override;
199 uint64_t writeObject(MCAssembler &, const MCAsmLayout &) override;
201 static bool nameShouldBeInStringTable(const StringRef &);
202 void writeSymbolName(const StringRef &);
203 void writeSymbolTableEntryForCsectMemberLabel(const Symbol &,
204 const ControlSection &, int16_t,
206 void writeSymbolTableEntryForControlSection(const ControlSection &, int16_t,
207 XCOFF::StorageClass);
208 void writeFileHeader();
209 void writeSectionHeaderTable();
210 void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout);
211 void writeSymbolTable(const MCAsmLayout &Layout);
212 void writeRelocations();
213 void writeRelocation(XCOFFRelocation Reloc, const ControlSection &CSection);
215 // Called after all the csects and symbols have been processed by
216 // `executePostLayoutBinding`, this function handles building up the majority
217 // of the structures in the object file representation. Namely:
218 // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
220 // *) Assigns symbol table indices.
221 // *) Builds up the section header table by adding any non-empty sections to
223 void assignAddressesAndIndices(const MCAsmLayout &);
224 void finalizeSectionInfo();
227 needsAuxiliaryHeader() const { /* TODO aux header support not implemented. */
231 // Returns the size of the auxiliary header to be written to the object file.
232 size_t auxiliaryHeaderSize() const {
233 assert(!needsAuxiliaryHeader() &&
234 "Auxiliary header support not implemented.");
239 XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
240 raw_pwrite_stream &OS);
243 XCOFFObjectWriter::XCOFFObjectWriter(
244 std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW, raw_pwrite_stream &OS)
245 : W(OS, support::big), TargetObjectWriter(std::move(MOTW)),
246 Strings(StringTableBuilder::XCOFF),
247 Text(".text", XCOFF::STYP_TEXT, /* IsVirtual */ false,
248 CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
249 Data(".data", XCOFF::STYP_DATA, /* IsVirtual */ false,
250 CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
251 BSS(".bss", XCOFF::STYP_BSS, /* IsVirtual */ true,
252 CsectGroups{&BSSCsects}) {}
254 void XCOFFObjectWriter::reset() {
255 // Clear the mappings we created.
256 SymbolIndexMap.clear();
259 UndefinedCsects.clear();
260 // Reset any sections we have written to, and empty the section header table.
261 for (auto *Sec : Sections)
264 // Reset states in XCOFFObjectWriter.
265 SymbolTableEntryCount = 0;
266 SymbolTableOffset = 0;
268 RelocationEntryOffset = 0;
271 MCObjectWriter::reset();
274 CsectGroup &XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF *MCSec) {
275 switch (MCSec->getMappingClass()) {
277 assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
278 "Only an initialized csect can contain program code.");
279 return ProgramCodeCsects;
281 assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
282 "Only an initialized csect can contain read only data.");
283 return ReadOnlyCsects;
285 if (XCOFF::XTY_CM == MCSec->getCSectType())
288 if (XCOFF::XTY_SD == MCSec->getCSectType())
291 report_fatal_error("Unhandled mapping of read-write csect to section.");
295 assert(XCOFF::XTY_CM == MCSec->getCSectType() &&
296 "Mapping invalid csect. CSECT with bss storage class must be "
300 assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
301 "Only an initialized csect can contain TOC-base.");
302 assert(TOCCsects.empty() &&
303 "We should have only one TOC-base, and it should be the first csect "
304 "in this CsectGroup.");
307 assert(XCOFF::XTY_SD == MCSec->getCSectType() &&
308 "Only an initialized csect can contain TC entry.");
309 assert(!TOCCsects.empty() &&
310 "We should at least have a TOC-base in this CsectGroup.");
313 report_fatal_error("Unhandled mapping of csect to section.");
317 static MCSectionXCOFF *getContainingCsect(const MCSymbolXCOFF *XSym) {
318 if (XSym->isDefined())
319 return cast<MCSectionXCOFF>(XSym->getFragment()->getParent());
320 return XSym->getRepresentedCsect();
323 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler &Asm,
324 const MCAsmLayout &Layout) {
325 if (TargetObjectWriter->is64Bit())
326 report_fatal_error("64-bit XCOFF object files are not supported yet.");
328 for (const auto &S : Asm) {
329 const auto *MCSec = cast<const MCSectionXCOFF>(&S);
330 assert(SectionMap.find(MCSec) == SectionMap.end() &&
331 "Cannot add a csect twice.");
332 assert(XCOFF::XTY_ER != MCSec->getCSectType() &&
333 "An undefined csect should not get registered.");
335 // If the name does not fit in the storage provided in the symbol table
336 // entry, add it to the string table.
337 if (nameShouldBeInStringTable(MCSec->getSymbolTableName()))
338 Strings.add(MCSec->getSymbolTableName());
340 CsectGroup &Group = getCsectGroup(MCSec);
341 Group.emplace_back(MCSec);
342 SectionMap[MCSec] = &Group.back();
345 for (const MCSymbol &S : Asm.symbols()) {
346 // Nothing to do for temporary symbols.
350 const MCSymbolXCOFF *XSym = cast<MCSymbolXCOFF>(&S);
351 const MCSectionXCOFF *ContainingCsect = getContainingCsect(XSym);
353 if (ContainingCsect->getCSectType() == XCOFF::XTY_ER) {
354 // Handle undefined symbol.
355 UndefinedCsects.emplace_back(ContainingCsect);
356 SectionMap[ContainingCsect] = &UndefinedCsects.back();
357 if (nameShouldBeInStringTable(ContainingCsect->getSymbolTableName()))
358 Strings.add(ContainingCsect->getSymbolTableName());
362 // If the symbol is the csect itself, we don't need to put the symbol
363 // into csect's Syms.
364 if (XSym == ContainingCsect->getQualNameSymbol())
367 // Only put a label into the symbol table when it is an external label.
368 if (!XSym->isExternal())
371 assert(SectionMap.find(ContainingCsect) != SectionMap.end() &&
372 "Expected containing csect to exist in map");
373 // Lookup the containing csect and add the symbol to it.
374 SectionMap[ContainingCsect]->Syms.emplace_back(XSym);
376 // If the name does not fit in the storage provided in the symbol table
377 // entry, add it to the string table.
378 if (nameShouldBeInStringTable(XSym->getSymbolTableName()))
379 Strings.add(XSym->getSymbolTableName());
383 assignAddressesAndIndices(Layout);
386 void XCOFFObjectWriter::recordRelocation(MCAssembler &Asm,
387 const MCAsmLayout &Layout,
388 const MCFragment *Fragment,
389 const MCFixup &Fixup, MCValue Target,
390 uint64_t &FixedValue) {
391 auto getIndex = [this](const MCSymbol *Sym,
392 const MCSectionXCOFF *ContainingCsect) {
393 // If we could not find the symbol directly in SymbolIndexMap, this symbol
394 // could either be a temporary symbol or an undefined symbol. In this case,
395 // we would need to have the relocation reference its csect instead.
396 return SymbolIndexMap.find(Sym) != SymbolIndexMap.end()
397 ? SymbolIndexMap[Sym]
398 : SymbolIndexMap[ContainingCsect->getQualNameSymbol()];
401 auto getVirtualAddress = [this,
402 &Layout](const MCSymbol *Sym,
403 const MCSectionXCOFF *ContainingCsect) {
404 // If Sym is a csect, return csect's address.
405 // If Sym is a label, return csect's address + label's offset from the csect.
406 return SectionMap[ContainingCsect]->Address +
407 (Sym->isDefined() ? Layout.getSymbolOffset(*Sym) : 0);
410 const MCSymbol *const SymA = &Target.getSymA()->getSymbol();
412 MCAsmBackend &Backend = Asm.getBackend();
413 bool IsPCRel = Backend.getFixupKindInfo(Fixup.getKind()).Flags &
414 MCFixupKindInfo::FKF_IsPCRel;
418 std::tie(Type, SignAndSize) =
419 TargetObjectWriter->getRelocTypeAndSignSize(Target, Fixup, IsPCRel);
421 const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
422 assert(SectionMap.find(SymASec) != SectionMap.end() &&
423 "Expected containing csect to exist in map.");
425 const uint32_t Index = getIndex(SymA, SymASec);
426 if (Type == XCOFF::RelocationType::R_POS)
427 // The FixedValue should be symbol's virtual address in this object file
428 // plus any constant value that we might get.
429 FixedValue = getVirtualAddress(SymA, SymASec) + Target.getConstant();
430 else if (Type == XCOFF::RelocationType::R_TOC)
431 // The FixedValue should be the TC entry offset from TOC-base.
432 FixedValue = SectionMap[SymASec]->Address - TOCCsects.front().Address;
435 (TargetObjectWriter->is64Bit() ||
436 Fixup.getOffset() <= UINT32_MAX - Layout.getFragmentOffset(Fragment)) &&
437 "Fragment offset + fixup offset is overflowed in 32-bit mode.");
438 uint32_t FixupOffsetInCsect =
439 Layout.getFragmentOffset(Fragment) + Fixup.getOffset();
441 XCOFFRelocation Reloc = {Index, FixupOffsetInCsect, SignAndSize, Type};
442 MCSectionXCOFF *RelocationSec = cast<MCSectionXCOFF>(Fragment->getParent());
443 assert(SectionMap.find(RelocationSec) != SectionMap.end() &&
444 "Expected containing csect to exist in map.");
445 SectionMap[RelocationSec]->Relocations.push_back(Reloc);
447 if (!Target.getSymB())
450 const MCSymbol *const SymB = &Target.getSymB()->getSymbol();
452 report_fatal_error("relocation for opposite term is not yet supported");
454 const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
455 assert(SectionMap.find(SymBSec) != SectionMap.end() &&
456 "Expected containing csect to exist in map.");
457 if (SymASec == SymBSec)
459 "relocation for paired relocatable term is not yet supported");
461 assert(Type == XCOFF::RelocationType::R_POS &&
462 "SymA must be R_POS here if it's not opposite term or paired "
463 "relocatable term.");
464 const uint32_t IndexB = getIndex(SymB, SymBSec);
465 // SymB must be R_NEG here, given the general form of Target(MCValue) is
466 // "SymbolA - SymbolB + imm64".
467 const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
468 XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
469 SectionMap[RelocationSec]->Relocations.push_back(RelocB);
470 // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
471 // now we just need to fold "- SymbolB" here.
472 FixedValue -= getVirtualAddress(SymB, SymBSec);
475 void XCOFFObjectWriter::writeSections(const MCAssembler &Asm,
476 const MCAsmLayout &Layout) {
477 uint32_t CurrentAddressLocation = 0;
478 for (const auto *Section : Sections) {
479 // Nothing to write for this Section.
480 if (Section->Index == Section::UninitializedIndex || Section->IsVirtual)
483 // There could be a gap (without corresponding zero padding) between
485 assert(CurrentAddressLocation <= Section->Address &&
486 "CurrentAddressLocation should be less than or equal to section "
489 CurrentAddressLocation = Section->Address;
491 for (const auto *Group : Section->Groups) {
492 for (const auto &Csect : *Group) {
493 if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
494 W.OS.write_zeros(PaddingSize);
496 Asm.writeSectionData(W.OS, Csect.MCCsect, Layout);
497 CurrentAddressLocation = Csect.Address + Csect.Size;
501 // The size of the tail padding in a section is the end virtual address of
502 // the current section minus the the end virtual address of the last csect
504 if (uint32_t PaddingSize =
505 Section->Address + Section->Size - CurrentAddressLocation) {
506 W.OS.write_zeros(PaddingSize);
507 CurrentAddressLocation += PaddingSize;
512 uint64_t XCOFFObjectWriter::writeObject(MCAssembler &Asm,
513 const MCAsmLayout &Layout) {
514 // We always emit a timestamp of 0 for reproducibility, so ensure incremental
515 // linking is not enabled, in case, like with Windows COFF, such a timestamp
516 // is incompatible with incremental linking of XCOFF.
517 if (Asm.isIncrementalLinkerCompatible())
518 report_fatal_error("Incremental linking not supported for XCOFF.");
520 if (TargetObjectWriter->is64Bit())
521 report_fatal_error("64-bit XCOFF object files are not supported yet.");
523 finalizeSectionInfo();
524 uint64_t StartOffset = W.OS.tell();
527 writeSectionHeaderTable();
528 writeSections(Asm, Layout);
531 writeSymbolTable(Layout);
532 // Write the string table.
535 return W.OS.tell() - StartOffset;
538 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef &SymbolName) {
539 return SymbolName.size() > XCOFF::NameSize;
542 void XCOFFObjectWriter::writeSymbolName(const StringRef &SymbolName) {
543 if (nameShouldBeInStringTable(SymbolName)) {
545 W.write<uint32_t>(Strings.getOffset(SymbolName));
547 char Name[XCOFF::NameSize+1];
548 std::strncpy(Name, SymbolName.data(), XCOFF::NameSize);
549 ArrayRef<char> NameRef(Name, XCOFF::NameSize);
554 void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel(
555 const Symbol &SymbolRef, const ControlSection &CSectionRef,
556 int16_t SectionIndex, uint64_t SymbolOffset) {
557 // Name or Zeros and string table offset
558 writeSymbolName(SymbolRef.getSymbolTableName());
559 assert(SymbolOffset <= UINT32_MAX - CSectionRef.Address &&
560 "Symbol address overflows.");
561 W.write<uint32_t>(CSectionRef.Address + SymbolOffset);
562 W.write<int16_t>(SectionIndex);
563 // Basic/Derived type. See the description of the n_type field for symbol
564 // table entries for a detailed description. Since we don't yet support
565 // visibility, and all other bits are either optionally set or reserved, this
567 // TODO FIXME How to assert a symbol's visibilty is default?
568 // TODO Set the function indicator (bit 10, 0x0020) for functions
569 // when debugging is enabled.
570 W.write<uint16_t>(0);
571 W.write<uint8_t>(SymbolRef.getStorageClass());
572 // Always 1 aux entry for now.
575 // Now output the auxiliary entry.
576 W.write<uint32_t>(CSectionRef.SymbolTableIndex);
577 // Parameter typecheck hash. Not supported.
578 W.write<uint32_t>(0);
579 // Typecheck section number. Not supported.
580 W.write<uint16_t>(0);
581 // Symbol type: Label
582 W.write<uint8_t>(XCOFF::XTY_LD);
583 // Storage mapping class.
584 W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass());
585 // Reserved (x_stab).
586 W.write<uint32_t>(0);
587 // Reserved (x_snstab).
588 W.write<uint16_t>(0);
591 void XCOFFObjectWriter::writeSymbolTableEntryForControlSection(
592 const ControlSection &CSectionRef, int16_t SectionIndex,
593 XCOFF::StorageClass StorageClass) {
594 // n_name, n_zeros, n_offset
595 writeSymbolName(CSectionRef.getSymbolTableName());
597 W.write<uint32_t>(CSectionRef.Address);
599 W.write<int16_t>(SectionIndex);
600 // Basic/Derived type. See the description of the n_type field for symbol
601 // table entries for a detailed description. Since we don't yet support
602 // visibility, and all other bits are either optionally set or reserved, this
604 // TODO FIXME How to assert a symbol's visibilty is default?
605 // TODO Set the function indicator (bit 10, 0x0020) for functions
606 // when debugging is enabled.
607 W.write<uint16_t>(0);
609 W.write<uint8_t>(StorageClass);
610 // Always 1 aux entry for now.
613 // Now output the auxiliary entry.
614 W.write<uint32_t>(CSectionRef.Size);
615 // Parameter typecheck hash. Not supported.
616 W.write<uint32_t>(0);
617 // Typecheck section number. Not supported.
618 W.write<uint16_t>(0);
620 W.write<uint8_t>(getEncodedType(CSectionRef.MCCsect));
621 // Storage mapping class.
622 W.write<uint8_t>(CSectionRef.MCCsect->getMappingClass());
623 // Reserved (x_stab).
624 W.write<uint32_t>(0);
625 // Reserved (x_snstab).
626 W.write<uint16_t>(0);
629 void XCOFFObjectWriter::writeFileHeader() {
631 W.write<uint16_t>(0x01df);
632 // Number of sections.
633 W.write<uint16_t>(SectionCount);
634 // Timestamp field. For reproducible output we write a 0, which represents no
637 // Byte Offset to the start of the symbol table.
638 W.write<uint32_t>(SymbolTableOffset);
639 // Number of entries in the symbol table.
640 W.write<int32_t>(SymbolTableEntryCount);
641 // Size of the optional header.
642 W.write<uint16_t>(0);
644 W.write<uint16_t>(0);
647 void XCOFFObjectWriter::writeSectionHeaderTable() {
648 for (const auto *Sec : Sections) {
649 // Nothing to write for this Section.
650 if (Sec->Index == Section::UninitializedIndex)
654 ArrayRef<char> NameRef(Sec->Name, XCOFF::NameSize);
657 // Write the Physical Address and Virtual Address. In an object file these
659 W.write<uint32_t>(Sec->Address);
660 W.write<uint32_t>(Sec->Address);
662 W.write<uint32_t>(Sec->Size);
663 W.write<uint32_t>(Sec->FileOffsetToData);
664 W.write<uint32_t>(Sec->FileOffsetToRelocations);
666 // Line number pointer. Not supported yet.
667 W.write<uint32_t>(0);
669 W.write<uint16_t>(Sec->RelocationCount);
671 // Line number counts. Not supported yet.
672 W.write<uint16_t>(0);
674 W.write<int32_t>(Sec->Flags);
678 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
679 const ControlSection &CSection) {
680 W.write<uint32_t>(CSection.Address + Reloc.FixupOffsetInCsect);
681 W.write<uint32_t>(Reloc.SymbolTableIndex);
682 W.write<uint8_t>(Reloc.SignAndSize);
683 W.write<uint8_t>(Reloc.Type);
686 void XCOFFObjectWriter::writeRelocations() {
687 for (const auto *Section : Sections) {
688 if (Section->Index == Section::UninitializedIndex)
689 // Nothing to write for this Section.
692 for (const auto *Group : Section->Groups) {
696 for (const auto &Csect : *Group) {
697 for (const auto Reloc : Csect.Relocations)
698 writeRelocation(Reloc, Csect);
704 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) {
705 for (const auto &Csect : UndefinedCsects) {
706 writeSymbolTableEntryForControlSection(
707 Csect, XCOFF::ReservedSectionNum::N_UNDEF, Csect.MCCsect->getStorageClass());
710 for (const auto *Section : Sections) {
711 if (Section->Index == Section::UninitializedIndex)
712 // Nothing to write for this Section.
715 for (const auto *Group : Section->Groups) {
719 const int16_t SectionIndex = Section->Index;
720 for (const auto &Csect : *Group) {
721 // Write out the control section first and then each symbol in it.
722 writeSymbolTableEntryForControlSection(
723 Csect, SectionIndex, Csect.MCCsect->getStorageClass());
725 for (const auto &Sym : Csect.Syms)
726 writeSymbolTableEntryForCsectMemberLabel(
727 Sym, Csect, SectionIndex, Layout.getSymbolOffset(*(Sym.MCSym)));
733 void XCOFFObjectWriter::finalizeSectionInfo() {
734 for (auto *Section : Sections) {
735 if (Section->Index == Section::UninitializedIndex)
736 // Nothing to record for this Section.
739 for (const auto *Group : Section->Groups) {
743 for (auto &Csect : *Group) {
744 const size_t CsectRelocCount = Csect.Relocations.size();
745 if (CsectRelocCount >= XCOFF::RelocOverflow ||
746 Section->RelocationCount >= XCOFF::RelocOverflow - CsectRelocCount)
748 "relocation entries overflowed; overflow section is "
749 "not implemented yet");
751 Section->RelocationCount += CsectRelocCount;
756 // Calculate the file offset to the relocation entries.
757 uint64_t RawPointer = RelocationEntryOffset;
758 for (auto Sec : Sections) {
759 if (Sec->Index == Section::UninitializedIndex || !Sec->RelocationCount)
762 Sec->FileOffsetToRelocations = RawPointer;
763 const uint32_t RelocationSizeInSec =
764 Sec->RelocationCount * XCOFF::RelocationSerializationSize32;
765 RawPointer += RelocationSizeInSec;
766 if (RawPointer > UINT32_MAX)
767 report_fatal_error("Relocation data overflowed this object file.");
770 // TODO Error check that the number of symbol table entries fits in 32-bits
772 if (SymbolTableEntryCount)
773 SymbolTableOffset = RawPointer;
776 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout &Layout) {
777 // The first symbol table entry is for the file name. We are not emitting it
778 // yet, so start at index 0.
779 uint32_t SymbolTableIndex = 0;
781 // Calculate indices for undefined symbols.
782 for (auto &Csect : UndefinedCsects) {
785 Csect.SymbolTableIndex = SymbolTableIndex;
786 SymbolIndexMap[Csect.MCCsect->getQualNameSymbol()] = Csect.SymbolTableIndex;
787 // 1 main and 1 auxiliary symbol table entry for each contained symbol.
788 SymbolTableIndex += 2;
791 // The address corrresponds to the address of sections and symbols in the
792 // object file. We place the shared address 0 immediately after the
793 // section header table.
794 uint32_t Address = 0;
795 // Section indices are 1-based in XCOFF.
796 int32_t SectionIndex = 1;
798 for (auto *Section : Sections) {
800 llvm::all_of(Section->Groups,
801 [](const CsectGroup *Group) { return Group->empty(); });
805 if (SectionIndex > MaxSectionIndex)
806 report_fatal_error("Section index overflow!");
807 Section->Index = SectionIndex++;
810 bool SectionAddressSet = false;
811 for (auto *Group : Section->Groups) {
815 for (auto &Csect : *Group) {
816 const MCSectionXCOFF *MCSec = Csect.MCCsect;
817 Csect.Address = alignTo(Address, MCSec->getAlignment());
818 Csect.Size = Layout.getSectionAddressSize(MCSec);
819 Address = Csect.Address + Csect.Size;
820 Csect.SymbolTableIndex = SymbolTableIndex;
821 SymbolIndexMap[MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
822 // 1 main and 1 auxiliary symbol table entry for the csect.
823 SymbolTableIndex += 2;
825 for (auto &Sym : Csect.Syms) {
826 Sym.SymbolTableIndex = SymbolTableIndex;
827 SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
828 // 1 main and 1 auxiliary symbol table entry for each contained
830 SymbolTableIndex += 2;
834 if (!SectionAddressSet) {
835 Section->Address = Group->front().Address;
836 SectionAddressSet = true;
840 // Make sure the address of the next section aligned to
841 // DefaultSectionAlign.
842 Address = alignTo(Address, DefaultSectionAlign);
843 Section->Size = Address - Section->Address;
846 SymbolTableEntryCount = SymbolTableIndex;
848 // Calculate the RawPointer value for each section.
849 uint64_t RawPointer = sizeof(XCOFF::FileHeader32) + auxiliaryHeaderSize() +
850 SectionCount * sizeof(XCOFF::SectionHeader32);
851 for (auto *Sec : Sections) {
852 if (Sec->Index == Section::UninitializedIndex || Sec->IsVirtual)
855 Sec->FileOffsetToData = RawPointer;
856 RawPointer += Sec->Size;
857 if (RawPointer > UINT32_MAX)
858 report_fatal_error("Section raw data overflowed this object file.");
861 RelocationEntryOffset = RawPointer;
864 // Takes the log base 2 of the alignment and shifts the result into the 5 most
865 // significant bits of a byte, then or's in the csect type into the least
866 // significant 3 bits.
867 uint8_t getEncodedType(const MCSectionXCOFF *Sec) {
868 unsigned Align = Sec->getAlignment();
869 assert(isPowerOf2_32(Align) && "Alignment must be a power of 2.");
870 unsigned Log2Align = Log2_32(Align);
871 // Result is a number in the range [0, 31] which fits in the 5 least
872 // significant bits. Shift this value into the 5 most significant bits, and
873 // bitwise-or in the csect type.
874 uint8_t EncodedAlign = Log2Align << 3;
875 return EncodedAlign | Sec->getCSectType();
878 } // end anonymous namespace
880 std::unique_ptr<MCObjectWriter>
881 llvm::createXCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
882 raw_pwrite_stream &OS) {
883 return std::make_unique<XCOFFObjectWriter>(std::move(MOTW), OS);