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