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