1 //===-- lib/MC/XCOFFObjectWriter.cpp - XCOFF file writer ------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements XCOFF object file writer information.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/BinaryFormat/XCOFF.h"
14 #include "llvm/MC/MCAsmBackend.h"
15 #include "llvm/MC/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"
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.
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.
51 constexpr unsigned DefaultSectionAlign
= 4;
52 constexpr int16_t MaxSectionIndex
= INT16_MAX
;
54 // Packs the csect's alignment and type into a byte.
55 uint8_t getEncodedType(const MCSectionXCOFF
*);
57 struct XCOFFRelocation
{
58 uint32_t SymbolTableIndex
;
59 uint32_t FixupOffsetInCsect
;
64 // Wrapper around an MCSymbolXCOFF.
66 const MCSymbolXCOFF
*const MCSym
;
67 uint32_t SymbolTableIndex
;
69 XCOFF::VisibilityType
getVisibilityType() const {
70 return MCSym
->getVisibilityType();
73 XCOFF::StorageClass
getStorageClass() const {
74 return MCSym
->getStorageClass();
76 StringRef
getSymbolTableName() const { return MCSym
->getSymbolTableName(); }
77 Symbol(const MCSymbolXCOFF
*MCSym
) : MCSym(MCSym
), SymbolTableIndex(-1) {}
80 // Wrapper for an MCSectionXCOFF.
81 // It can be a Csect or debug section or DWARF section and so on.
83 const MCSectionXCOFF
*const MCSec
;
84 uint32_t SymbolTableIndex
;
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();
94 XCOFFSection(const MCSectionXCOFF
*MCSec
)
95 : MCSec(MCSec
), SymbolTableIndex(-1), Address(-1), Size(0) {}
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
102 using CsectGroup
= std::deque
<XCOFFSection
>;
103 using CsectGroups
= std::deque
<CsectGroup
*>;
105 // The basic section entry defination. This Section represents a section entry
106 // in XCOFF section header table.
107 struct 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.
117 uint64_t FileOffsetToData
;
118 uint64_t FileOffsetToRelocations
;
119 uint32_t RelocationCount
;
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("Section raw data overflowed this object file.");
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
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;
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(Name
, N
.data(), N
.size());
151 virtual void reset() {
154 FileOffsetToData
= 0;
155 FileOffsetToRelocations
= 0;
157 Index
= UninitializedIndex
;
160 virtual ~SectionEntry() = default;
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.
168 struct CsectSectionEntry
: public SectionEntry
{
169 // Virtual sections do not need storage allocated in the object file.
170 const bool IsVirtual
;
172 // This is a section containing csect groups.
175 CsectSectionEntry(StringRef N
, XCOFF::SectionTypeFlags Flags
, bool IsVirtual
,
177 : SectionEntry(N
, Flags
), IsVirtual(IsVirtual
), Groups(Groups
) {
178 assert(N
.size() <= XCOFF::NameSize
&& "section name too long");
179 memcpy(Name
, N
.data(), N
.size());
182 void reset() override
{
183 SectionEntry::reset();
184 // Clear any csects we have stored.
185 for (auto *Group
: Groups
)
189 virtual ~CsectSectionEntry() = default;
192 struct DwarfSectionEntry
: public SectionEntry
{
193 // For DWARF section entry.
194 std::unique_ptr
<XCOFFSection
> DwarfSect
;
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.
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.");
213 DwarfSectionEntry(StringRef N
, int32_t Flags
,
214 std::unique_ptr
<XCOFFSection
> Sect
)
215 : SectionEntry(N
, Flags
| XCOFF::STYP_DWARF
), DwarfSect(std::move(Sect
)),
217 assert(DwarfSect
->MCSec
->isDwarfSect() &&
218 "This should be a DWARF section!");
219 assert(N
.size() <= XCOFF::NameSize
&& "section name too long");
220 memcpy(Name
, N
.data(), N
.size());
223 DwarfSectionEntry(DwarfSectionEntry
&&s
) = default;
225 virtual ~DwarfSectionEntry() = default;
228 struct ExceptionTableEntry
{
229 const MCSymbol
*Trap
;
230 uint64_t TrapAddress
= ~0ul;
234 ExceptionTableEntry(const MCSymbol
*Trap
, unsigned Lang
, unsigned Reason
)
235 : Trap(Trap
), Lang(Lang
), Reason(Reason
) {}
238 struct ExceptionInfo
{
239 const MCSymbol
*FunctionSymbol
;
240 unsigned FunctionSize
;
241 std::vector
<ExceptionTableEntry
> Entries
;
244 struct ExceptionSectionEntry
: public SectionEntry
{
245 std::map
<const StringRef
, ExceptionInfo
> ExceptionTable
;
246 bool isDebugEnabled
= false;
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(Name
, N
.data(), N
.size());
254 virtual ~ExceptionSectionEntry() = default;
257 struct CInfoSymInfo
{
258 // Name of the C_INFO symbol associated with the section
260 std::string Metadata
;
261 // Offset into the start of the metadata in the section
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(Metadata
.size(), sizeof(uint32_t)) - Metadata
.size();
271 // Total size of the entry, including the 4 byte length
272 uint32_t size() const {
273 return Metadata
.size() + paddingSize() + sizeof(uint32_t);
277 struct CInfoSymSectionEntry
: public SectionEntry
{
278 std::unique_ptr
<CInfoSymInfo
> Entry
;
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();
287 void reset() override
{
288 SectionEntry::reset();
293 class 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;
300 support::endian::Writer W
;
301 std::unique_ptr
<MCXCOFFObjectTargetWriter
> TargetObjectWriter
;
302 StringTableBuilder Strings
;
304 const uint64_t MaxRawDataSize
=
305 TargetObjectWriter
->is64Bit() ? UINT64_MAX
: UINT32_MAX
;
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
;
312 // Maps the MCSymbol representation to its corrresponding symbol table index.
313 // Needed for relocation.
314 DenseMap
<const MCSymbol
*, uint32_t> SymbolIndexMap
;
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
;
329 // The Predefined sections.
330 CsectSectionEntry Text
;
331 CsectSectionEntry Data
;
332 CsectSectionEntry BSS
;
333 CsectSectionEntry TData
;
334 CsectSectionEntry TBSS
;
336 // All the XCOFF sections, in the order they will appear in the section header
338 std::array
<CsectSectionEntry
*const, 5> Sections
{
339 {&Text
, &Data
, &BSS
, &TData
, &TBSS
}};
341 std::vector
<DwarfSectionEntry
> DwarfSections
;
342 std::vector
<SectionEntry
> OverflowSections
;
344 ExceptionSectionEntry ExceptionSection
;
345 CInfoSymSectionEntry CInfoSymSection
;
347 CsectGroup
&getCsectGroup(const MCSectionXCOFF
*MCSec
);
349 void reset() override
;
351 void executePostLayoutBinding(MCAssembler
&) override
;
353 void recordRelocation(MCAssembler
&, const MCFragment
*, const MCFixup
&,
354 MCValue
, uint64_t &) override
;
356 uint64_t writeObject(MCAssembler
&) override
;
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
&);
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
);
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
,
401 void writeSymbolAuxExceptionEntry(uint64_t EntryOffset
, uint32_t FunctionSize
,
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
);
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
414 // *) Assigns symbol table indices.
415 // *) Builds up the section header table by adding any non-empty sections to
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
);
423 bool hasExceptionSection() {
424 return !ExceptionSection
.ExceptionTable
.empty();
426 unsigned getExceptionSectionSize();
427 unsigned getExceptionOffset(const MCSymbol
*Symbol
);
429 size_t auxiliaryHeaderSize() const {
430 // 64-bit object files have no auxiliary header.
431 return HasVisibility
&& !is64Bit() ? XCOFF::AuxFileHeaderSizeShort
: 0;
435 XCOFFWriter(std::unique_ptr
<MCXCOFFObjectTargetWriter
> MOTW
,
436 raw_pwrite_stream
&OS
);
438 void writeWord(uint64_t Word
) {
439 is64Bit() ? W
.write
<uint64_t>(Word
) : W
.write
<uint32_t>(Word
);
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
;
448 XCOFFWriter::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
) {}
465 void XCOFFWriter::reset() {
466 // Clear the mappings we created.
467 SymbolIndexMap
.clear();
470 UndefinedCsects
.clear();
471 // Reset any sections we have written to, and empty the section header table.
472 for (auto *Sec
: Sections
)
474 for (auto &DwarfSec
: DwarfSections
)
476 for (auto &OverflowSec
: OverflowSections
)
478 ExceptionSection
.reset();
479 CInfoSymSection
.reset();
481 // Reset states in XCOFFWriter.
482 SymbolTableEntryCount
= 0;
483 SymbolTableOffset
= 0;
485 PaddingsBeforeDwarf
= 0;
488 MCObjectWriter::reset();
491 CsectGroup
&XCOFFWriter::getCsectGroup(const MCSectionXCOFF
*MCSec
) {
492 switch (MCSec
->getMappingClass()) {
494 assert(XCOFF::XTY_SD
== MCSec
->getCSectType() &&
495 "Only an initialized csect can contain program code.");
496 return ProgramCodeCsects
;
498 assert(XCOFF::XTY_SD
== MCSec
->getCSectType() &&
499 "Only an initialized csect can contain read only data.");
500 return ReadOnlyCsects
;
502 if (XCOFF::XTY_CM
== MCSec
->getCSectType())
505 if (XCOFF::XTY_SD
== MCSec
->getCSectType())
508 report_fatal_error("Unhandled mapping of read-write csect to section.");
512 assert(XCOFF::XTY_CM
== MCSec
->getCSectType() &&
513 "Mapping invalid csect. CSECT with bss storage class must be "
517 assert(XCOFF::XTY_SD
== MCSec
->getCSectType() &&
518 "Mapping invalid csect. CSECT with tdata storage class must be "
519 "an initialized csect.");
522 assert(XCOFF::XTY_CM
== MCSec
->getCSectType() &&
523 "Mapping invalid csect. CSECT with tbss storage class must be "
524 "an uninitialized csect.");
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.");
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.");
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.");
548 report_fatal_error("Unhandled mapping of csect to section.");
552 static MCSectionXCOFF
*getContainingCsect(const MCSymbolXCOFF
*XSym
) {
553 if (XSym
->isDefined())
554 return cast
<MCSectionXCOFF
>(XSym
->getFragment()->getParent());
555 return XSym
->getRepresentedCsect();
558 void XCOFFWriter::executePostLayoutBinding(MCAssembler
&Asm
) {
559 for (const auto &S
: Asm
) {
560 const auto *MCSec
= cast
<const MCSectionXCOFF
>(&S
);
561 assert(!SectionMap
.contains(MCSec
) && "Cannot add a section twice.");
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(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(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
>(MCSec
);
580 SectionMap
[MCSec
] = DwarfSec
.get();
582 DwarfSectionEntry
SecEntry(MCSec
->getName(),
583 *MCSec
->getDwarfSubtypeFlags(),
584 std::move(DwarfSec
));
585 DwarfSections
.push_back(std::move(SecEntry
));
587 llvm_unreachable("unsupport section type!");
590 for (const MCSymbol
&S
: Asm
.symbols()) {
591 // Nothing to do for temporary symbols.
595 const MCSymbolXCOFF
*XSym
= cast
<MCSymbolXCOFF
>(&S
);
596 const MCSectionXCOFF
*ContainingCsect
= getContainingCsect(XSym
);
598 if (ContainingCsect
->isDwarfSect())
601 if (XSym
->getVisibilityType() != XCOFF::SYM_V_UNSPECIFIED
)
602 HasVisibility
= true;
604 if (ContainingCsect
->getCSectType() == XCOFF::XTY_ER
) {
605 // Handle undefined symbol.
606 UndefinedCsects
.emplace_back(ContainingCsect
);
607 SectionMap
[ContainingCsect
] = &UndefinedCsects
.back();
608 if (nameShouldBeInStringTable(ContainingCsect
->getSymbolTableName()))
609 Strings
.add(ContainingCsect
->getSymbolTableName());
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())
618 // Only put a label into the symbol table when it is an external label.
619 if (!XSym
->isExternal())
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(XSym
);
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(XSym
->getSymbolTableName());
635 std::unique_ptr
<CInfoSymInfo
> &CISI
= CInfoSymSection
.Entry
;
636 if (CISI
&& nameShouldBeInStringTable(CISI
->Name
))
637 Strings
.add(CISI
->Name
);
639 // Emit ".file" as the source file name when there is no file name.
640 if (FileNames
.empty())
641 FileNames
.emplace_back(".file", 0);
642 for (const std::pair
<std::string
, size_t> &F
: FileNames
) {
643 if (auxFileSymNameShouldBeInStringTable(F
.first
))
644 Strings
.add(F
.first
);
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(".file");
651 StringRef Vers
= CompilerVersion
;
652 if (auxFileSymNameShouldBeInStringTable(Vers
))
656 assignAddressesAndIndices(Asm
);
659 void XCOFFWriter::recordRelocation(MCAssembler
&Asm
, const MCFragment
*Fragment
,
660 const MCFixup
&Fixup
, MCValue Target
,
661 uint64_t &FixedValue
) {
662 auto getIndex
= [this](const MCSymbol
*Sym
,
663 const MCSectionXCOFF
*ContainingCsect
) {
664 // If we could not find the symbol directly in SymbolIndexMap, this symbol
665 // could either be a temporary symbol or an undefined symbol. In this case,
666 // we would need to have the relocation reference its csect instead.
667 auto It
= SymbolIndexMap
.find(Sym
);
668 return It
!= SymbolIndexMap
.end()
670 : SymbolIndexMap
[ContainingCsect
->getQualNameSymbol()];
673 auto getVirtualAddress
=
674 [this, &Asm
](const MCSymbol
*Sym
,
675 const MCSectionXCOFF
*ContainingSect
) -> uint64_t {
677 if (ContainingSect
->isDwarfSect())
678 return Asm
.getSymbolOffset(*Sym
);
681 if (!Sym
->isDefined())
682 return SectionMap
[ContainingSect
]->Address
;
685 assert(Sym
->isDefined() && "not a valid object that has address!");
686 return SectionMap
[ContainingSect
]->Address
+ Asm
.getSymbolOffset(*Sym
);
689 const MCSymbol
*const SymA
= &Target
.getSymA()->getSymbol();
691 MCAsmBackend
&Backend
= Asm
.getBackend();
692 bool IsPCRel
= Backend
.getFixupKindInfo(Fixup
.getKind()).Flags
&
693 MCFixupKindInfo::FKF_IsPCRel
;
697 std::tie(Type
, SignAndSize
) =
698 TargetObjectWriter
->getRelocTypeAndSignSize(Target
, Fixup
, IsPCRel
);
700 const MCSectionXCOFF
*SymASec
= getContainingCsect(cast
<MCSymbolXCOFF
>(SymA
));
701 assert(SectionMap
.contains(SymASec
) &&
702 "Expected containing csect to exist in map.");
704 assert((Fixup
.getOffset() <=
705 MaxRawDataSize
- Asm
.getFragmentOffset(*Fragment
)) &&
706 "Fragment offset + fixup offset is overflowed.");
707 uint32_t FixupOffsetInCsect
=
708 Asm
.getFragmentOffset(*Fragment
) + Fixup
.getOffset();
710 const uint32_t Index
= getIndex(SymA
, SymASec
);
711 if (Type
== XCOFF::RelocationType::R_POS
||
712 Type
== XCOFF::RelocationType::R_TLS
||
713 Type
== XCOFF::RelocationType::R_TLS_LE
||
714 Type
== XCOFF::RelocationType::R_TLS_IE
||
715 Type
== XCOFF::RelocationType::R_TLS_LD
)
716 // The FixedValue should be symbol's virtual address in this object file
717 // plus any constant value that we might get.
718 FixedValue
= getVirtualAddress(SymA
, SymASec
) + Target
.getConstant();
719 else if (Type
== XCOFF::RelocationType::R_TLSM
)
720 // The FixedValue should always be zero since the region handle is only
721 // known at load time.
723 else if (Type
== XCOFF::RelocationType::R_TOC
||
724 Type
== XCOFF::RelocationType::R_TOCL
) {
725 // For non toc-data external symbols, R_TOC type relocation will relocate to
726 // data symbols that have XCOFF::XTY_SD type csect. For toc-data external
727 // symbols, R_TOC type relocation will relocate to data symbols that have
728 // XCOFF_ER type csect. For XCOFF_ER kind symbols, there will be no TOC
729 // entry for them, so the FixedValue should always be 0.
730 if (SymASec
->getCSectType() == XCOFF::XTY_ER
) {
733 // The FixedValue should be the TOC entry offset from the TOC-base plus
734 // any constant offset value.
735 int64_t TOCEntryOffset
= SectionMap
[SymASec
]->Address
-
736 TOCCsects
.front().Address
+ Target
.getConstant();
737 // For small code model, if the TOCEntryOffset overflows the 16-bit value,
738 // we truncate it back down to 16 bits. The linker will be able to insert
739 // fix-up code when needed.
740 // For non toc-data symbols, we already did the truncation in
741 // PPCAsmPrinter.cpp through setting Target.getConstant() in the
742 // expression above by calling getTOCEntryLoadingExprForXCOFF for the
743 // various TOC PseudoOps.
744 // For toc-data symbols, we were not able to calculate the offset from
745 // the TOC in PPCAsmPrinter.cpp since the TOC has not been finalized at
746 // that point, so we are adjusting it here though
747 // llvm::SignExtend64<16>(TOCEntryOffset);
748 // TODO: Since the time that the handling for offsets over 16-bits was
749 // added in PPCAsmPrinter.cpp using getTOCEntryLoadingExprForXCOFF, the
750 // system assembler and linker have been updated to be able to handle the
751 // overflowing offsets, so we no longer need to keep
752 // getTOCEntryLoadingExprForXCOFF.
753 if (Type
== XCOFF::RelocationType::R_TOC
&& !isInt
<16>(TOCEntryOffset
))
754 TOCEntryOffset
= llvm::SignExtend64
<16>(TOCEntryOffset
);
756 FixedValue
= TOCEntryOffset
;
758 } else if (Type
== XCOFF::RelocationType::R_RBR
) {
759 MCSectionXCOFF
*ParentSec
= cast
<MCSectionXCOFF
>(Fragment
->getParent());
760 assert((SymASec
->getMappingClass() == XCOFF::XMC_PR
&&
761 ParentSec
->getMappingClass() == XCOFF::XMC_PR
) &&
762 "Only XMC_PR csect may have the R_RBR relocation.");
764 // The address of the branch instruction should be the sum of section
765 // address, fragment offset and Fixup offset.
766 uint64_t BRInstrAddress
=
767 SectionMap
[ParentSec
]->Address
+ FixupOffsetInCsect
;
768 // The FixedValue should be the difference between symbol's virtual address
769 // and BR instr address plus any constant value.
770 FixedValue
= getVirtualAddress(SymA
, SymASec
) - BRInstrAddress
+
771 Target
.getConstant();
772 } else if (Type
== XCOFF::RelocationType::R_REF
) {
773 // The FixedValue and FixupOffsetInCsect should always be 0 since it
774 // specifies a nonrelocating reference.
776 FixupOffsetInCsect
= 0;
779 XCOFFRelocation Reloc
= {Index
, FixupOffsetInCsect
, SignAndSize
, Type
};
780 MCSectionXCOFF
*RelocationSec
= cast
<MCSectionXCOFF
>(Fragment
->getParent());
781 assert(SectionMap
.contains(RelocationSec
) &&
782 "Expected containing csect to exist in map.");
783 SectionMap
[RelocationSec
]->Relocations
.push_back(Reloc
);
785 if (!Target
.getSymB())
788 const MCSymbol
*const SymB
= &Target
.getSymB()->getSymbol();
790 report_fatal_error("relocation for opposite term is not yet supported");
792 const MCSectionXCOFF
*SymBSec
= getContainingCsect(cast
<MCSymbolXCOFF
>(SymB
));
793 assert(SectionMap
.contains(SymBSec
) &&
794 "Expected containing csect to exist in map.");
795 if (SymASec
== SymBSec
)
797 "relocation for paired relocatable term is not yet supported");
799 assert(Type
== XCOFF::RelocationType::R_POS
&&
800 "SymA must be R_POS here if it's not opposite term or paired "
801 "relocatable term.");
802 const uint32_t IndexB
= getIndex(SymB
, SymBSec
);
803 // SymB must be R_NEG here, given the general form of Target(MCValue) is
804 // "SymbolA - SymbolB + imm64".
805 const uint8_t TypeB
= XCOFF::RelocationType::R_NEG
;
806 XCOFFRelocation RelocB
= {IndexB
, FixupOffsetInCsect
, SignAndSize
, TypeB
};
807 SectionMap
[RelocationSec
]->Relocations
.push_back(RelocB
);
808 // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
809 // now we just need to fold "- SymbolB" here.
810 FixedValue
-= getVirtualAddress(SymB
, SymBSec
);
813 void XCOFFWriter::writeSections(const MCAssembler
&Asm
) {
814 uint64_t CurrentAddressLocation
= 0;
815 for (const auto *Section
: Sections
)
816 writeSectionForControlSectionEntry(Asm
, *Section
, CurrentAddressLocation
);
817 for (const auto &DwarfSection
: DwarfSections
)
818 writeSectionForDwarfSectionEntry(Asm
, DwarfSection
, CurrentAddressLocation
);
819 writeSectionForExceptionSectionEntry(Asm
, ExceptionSection
,
820 CurrentAddressLocation
);
821 writeSectionForCInfoSymSectionEntry(Asm
, CInfoSymSection
,
822 CurrentAddressLocation
);
825 uint64_t XCOFFWriter::writeObject(MCAssembler
&Asm
) {
826 // We always emit a timestamp of 0 for reproducibility, so ensure incremental
827 // linking is not enabled, in case, like with Windows COFF, such a timestamp
828 // is incompatible with incremental linking of XCOFF.
830 finalizeSectionInfo();
831 uint64_t StartOffset
= W
.OS
.tell();
834 writeAuxFileHeader();
835 writeSectionHeaderTable();
838 writeSymbolTable(Asm
);
839 // Write the string table.
842 return W
.OS
.tell() - StartOffset
;
845 bool XCOFFWriter::nameShouldBeInStringTable(const StringRef
&SymbolName
) {
846 return SymbolName
.size() > XCOFF::NameSize
|| is64Bit();
849 void XCOFFWriter::writeSymbolName(const StringRef
&SymbolName
) {
850 // Magic, Offset or SymbolName.
851 if (nameShouldBeInStringTable(SymbolName
)) {
853 W
.write
<uint32_t>(Strings
.getOffset(SymbolName
));
855 char Name
[XCOFF::NameSize
+ 1];
856 std::strncpy(Name
, SymbolName
.data(), XCOFF::NameSize
);
857 ArrayRef
<char> NameRef(Name
, XCOFF::NameSize
);
862 void XCOFFWriter::writeSymbolEntry(StringRef SymbolName
, uint64_t Value
,
863 int16_t SectionNumber
, uint16_t SymbolType
,
864 uint8_t StorageClass
,
865 uint8_t NumberOfAuxEntries
) {
867 W
.write
<uint64_t>(Value
);
868 W
.write
<uint32_t>(Strings
.getOffset(SymbolName
));
870 writeSymbolName(SymbolName
);
871 W
.write
<uint32_t>(Value
);
873 W
.write
<int16_t>(SectionNumber
);
874 W
.write
<uint16_t>(SymbolType
);
875 W
.write
<uint8_t>(StorageClass
);
876 W
.write
<uint8_t>(NumberOfAuxEntries
);
879 void XCOFFWriter::writeSymbolAuxCsectEntry(uint64_t SectionOrLength
,
880 uint8_t SymbolAlignmentAndType
,
881 uint8_t StorageMappingClass
) {
882 W
.write
<uint32_t>(is64Bit() ? Lo_32(SectionOrLength
) : SectionOrLength
);
883 W
.write
<uint32_t>(0); // ParameterHashIndex
884 W
.write
<uint16_t>(0); // TypeChkSectNum
885 W
.write
<uint8_t>(SymbolAlignmentAndType
);
886 W
.write
<uint8_t>(StorageMappingClass
);
888 W
.write
<uint32_t>(Hi_32(SectionOrLength
));
889 W
.OS
.write_zeros(1); // Reserved
890 W
.write
<uint8_t>(XCOFF::AUX_CSECT
);
892 W
.write
<uint32_t>(0); // StabInfoIndex
893 W
.write
<uint16_t>(0); // StabSectNum
897 bool XCOFFWriter::auxFileSymNameShouldBeInStringTable(
898 const StringRef
&SymbolName
) {
899 return SymbolName
.size() > XCOFF::AuxFileEntNameSize
;
902 void XCOFFWriter::writeAuxFileSymName(const StringRef
&SymbolName
) {
903 // Magic, Offset or SymbolName.
904 if (auxFileSymNameShouldBeInStringTable(SymbolName
)) {
906 W
.write
<uint32_t>(Strings
.getOffset(SymbolName
));
907 W
.OS
.write_zeros(XCOFF::FileNamePadSize
);
909 char Name
[XCOFF::AuxFileEntNameSize
+ 1];
910 std::strncpy(Name
, SymbolName
.data(), XCOFF::AuxFileEntNameSize
);
911 ArrayRef
<char> NameRef(Name
, XCOFF::AuxFileEntNameSize
);
916 void XCOFFWriter::writeSymbolAuxFileEntry(StringRef
&Name
, uint8_t ftype
) {
917 writeAuxFileSymName(Name
);
918 W
.write
<uint8_t>(ftype
);
921 W
.write
<uint8_t>(XCOFF::AUX_FILE
);
926 void XCOFFWriter::writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion
,
927 uint64_t NumberOfRelocEnt
) {
928 writeWord(LengthOfSectionPortion
);
930 W
.OS
.write_zeros(4); // Reserved
931 writeWord(NumberOfRelocEnt
);
933 W
.OS
.write_zeros(1); // Reserved
934 W
.write
<uint8_t>(XCOFF::AUX_SECT
);
936 W
.OS
.write_zeros(6); // Reserved
940 void XCOFFWriter::writeSymbolEntryForCsectMemberLabel(
941 const Symbol
&SymbolRef
, const XCOFFSection
&CSectionRef
,
942 int16_t SectionIndex
, uint64_t SymbolOffset
) {
943 assert(SymbolOffset
<= MaxRawDataSize
- CSectionRef
.Address
&&
944 "Symbol address overflowed.");
946 auto Entry
= ExceptionSection
.ExceptionTable
.find(SymbolRef
.MCSym
->getName());
947 if (Entry
!= ExceptionSection
.ExceptionTable
.end()) {
948 writeSymbolEntry(SymbolRef
.getSymbolTableName(),
949 CSectionRef
.Address
+ SymbolOffset
, SectionIndex
,
950 // In the old version of the 32-bit XCOFF interpretation,
951 // symbols may require bit 10 (0x0020) to be set if the
952 // symbol is a function, otherwise the bit should be 0.
953 is64Bit() ? SymbolRef
.getVisibilityType()
954 : SymbolRef
.getVisibilityType() | 0x0020,
955 SymbolRef
.getStorageClass(),
956 (is64Bit() && ExceptionSection
.isDebugEnabled
) ? 3 : 2);
957 if (is64Bit() && ExceptionSection
.isDebugEnabled
) {
958 // On 64 bit with debugging enabled, we have a csect, exception, and
959 // function auxilliary entries, so we must increment symbol index by 4.
960 writeSymbolAuxExceptionEntry(
961 ExceptionSection
.FileOffsetToData
+
962 getExceptionOffset(Entry
->second
.FunctionSymbol
),
963 Entry
->second
.FunctionSize
,
964 SymbolIndexMap
[Entry
->second
.FunctionSymbol
] + 4);
966 // For exception section entries, csect and function auxilliary entries
967 // must exist. On 64-bit there is also an exception auxilliary entry.
968 writeSymbolAuxFunctionEntry(
969 ExceptionSection
.FileOffsetToData
+
970 getExceptionOffset(Entry
->second
.FunctionSymbol
),
971 Entry
->second
.FunctionSize
, 0,
972 (is64Bit() && ExceptionSection
.isDebugEnabled
)
973 ? SymbolIndexMap
[Entry
->second
.FunctionSymbol
] + 4
974 : SymbolIndexMap
[Entry
->second
.FunctionSymbol
] + 3);
976 writeSymbolEntry(SymbolRef
.getSymbolTableName(),
977 CSectionRef
.Address
+ SymbolOffset
, SectionIndex
,
978 SymbolRef
.getVisibilityType(),
979 SymbolRef
.getStorageClass());
981 writeSymbolAuxCsectEntry(CSectionRef
.SymbolTableIndex
, XCOFF::XTY_LD
,
982 CSectionRef
.MCSec
->getMappingClass());
985 void XCOFFWriter::writeSymbolEntryForDwarfSection(
986 const XCOFFSection
&DwarfSectionRef
, int16_t SectionIndex
) {
987 assert(DwarfSectionRef
.MCSec
->isDwarfSect() && "Not a DWARF section!");
989 writeSymbolEntry(DwarfSectionRef
.getSymbolTableName(), /*Value=*/0,
990 SectionIndex
, /*SymbolType=*/0, XCOFF::C_DWARF
);
992 writeSymbolAuxDwarfEntry(DwarfSectionRef
.Size
);
995 void XCOFFWriter::writeSymbolEntryForControlSection(
996 const XCOFFSection
&CSectionRef
, int16_t SectionIndex
,
997 XCOFF::StorageClass StorageClass
) {
998 writeSymbolEntry(CSectionRef
.getSymbolTableName(), CSectionRef
.Address
,
999 SectionIndex
, CSectionRef
.getVisibilityType(), StorageClass
);
1001 writeSymbolAuxCsectEntry(CSectionRef
.Size
, getEncodedType(CSectionRef
.MCSec
),
1002 CSectionRef
.MCSec
->getMappingClass());
1005 void XCOFFWriter::writeSymbolAuxFunctionEntry(uint32_t EntryOffset
,
1006 uint32_t FunctionSize
,
1007 uint64_t LineNumberPointer
,
1008 uint32_t EndIndex
) {
1010 writeWord(LineNumberPointer
);
1012 W
.write
<uint32_t>(EntryOffset
);
1013 W
.write
<uint32_t>(FunctionSize
);
1015 writeWord(LineNumberPointer
);
1016 W
.write
<uint32_t>(EndIndex
);
1018 W
.OS
.write_zeros(1);
1019 W
.write
<uint8_t>(XCOFF::AUX_FCN
);
1021 W
.OS
.write_zeros(2);
1025 void XCOFFWriter::writeSymbolAuxExceptionEntry(uint64_t EntryOffset
,
1026 uint32_t FunctionSize
,
1027 uint32_t EndIndex
) {
1028 assert(is64Bit() && "Exception auxilliary entries are 64-bit only.");
1029 W
.write
<uint64_t>(EntryOffset
);
1030 W
.write
<uint32_t>(FunctionSize
);
1031 W
.write
<uint32_t>(EndIndex
);
1032 W
.OS
.write_zeros(1); // Pad (unused)
1033 W
.write
<uint8_t>(XCOFF::AUX_EXCEPT
);
1036 void XCOFFWriter::writeFileHeader() {
1037 W
.write
<uint16_t>(is64Bit() ? XCOFF::XCOFF64
: XCOFF::XCOFF32
);
1038 W
.write
<uint16_t>(SectionCount
);
1039 W
.write
<int32_t>(0); // TimeStamp
1040 writeWord(SymbolTableOffset
);
1042 W
.write
<uint16_t>(auxiliaryHeaderSize());
1043 W
.write
<uint16_t>(0); // Flags
1044 W
.write
<int32_t>(SymbolTableEntryCount
);
1046 W
.write
<int32_t>(SymbolTableEntryCount
);
1047 W
.write
<uint16_t>(auxiliaryHeaderSize());
1048 W
.write
<uint16_t>(0); // Flags
1052 void XCOFFWriter::writeAuxFileHeader() {
1053 if (!auxiliaryHeaderSize())
1055 W
.write
<uint16_t>(0); // Magic
1057 XCOFF::NEW_XCOFF_INTERPRET
); // Version. The new interpretation of the
1058 // n_type field in the symbol table entry is
1060 W
.write
<uint32_t>(Sections
[0]->Size
); // TextSize
1061 W
.write
<uint32_t>(Sections
[1]->Size
); // InitDataSize
1062 W
.write
<uint32_t>(Sections
[2]->Size
); // BssDataSize
1063 W
.write
<uint32_t>(0); // EntryPointAddr
1064 W
.write
<uint32_t>(Sections
[0]->Address
); // TextStartAddr
1065 W
.write
<uint32_t>(Sections
[1]->Address
); // DataStartAddr
1068 void XCOFFWriter::writeSectionHeader(const SectionEntry
*Sec
) {
1069 bool IsDwarf
= (Sec
->Flags
& XCOFF::STYP_DWARF
) != 0;
1070 bool IsOvrflo
= (Sec
->Flags
& XCOFF::STYP_OVRFLO
) != 0;
1071 // Nothing to write for this Section.
1072 if (Sec
->Index
== SectionEntry::UninitializedIndex
)
1076 ArrayRef
<char> NameRef(Sec
->Name
, XCOFF::NameSize
);
1079 // Write the Physical Address and Virtual Address.
1080 // We use 0 for DWARF sections' Physical and Virtual Addresses.
1081 writeWord(IsDwarf
? 0 : Sec
->Address
);
1082 // Since line number is not supported, we set it to 0 for overflow sections.
1083 writeWord((IsDwarf
|| IsOvrflo
) ? 0 : Sec
->Address
);
1085 writeWord(Sec
->Size
);
1086 writeWord(Sec
->FileOffsetToData
);
1087 writeWord(Sec
->FileOffsetToRelocations
);
1088 writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet.
1091 W
.write
<uint32_t>(Sec
->RelocationCount
);
1092 W
.write
<uint32_t>(0); // NumberOfLineNumbers. Not supported yet.
1093 W
.write
<int32_t>(Sec
->Flags
);
1094 W
.OS
.write_zeros(4);
1096 // For the overflow section header, s_nreloc provides a reference to the
1097 // primary section header and s_nlnno must have the same value.
1098 // For common section headers, if either of s_nreloc or s_nlnno are set to
1099 // 65535, the other one must also be set to 65535.
1100 W
.write
<uint16_t>(Sec
->RelocationCount
);
1101 W
.write
<uint16_t>((IsOvrflo
|| Sec
->RelocationCount
== XCOFF::RelocOverflow
)
1102 ? Sec
->RelocationCount
1103 : 0); // NumberOfLineNumbers. Not supported yet.
1104 W
.write
<int32_t>(Sec
->Flags
);
1108 void XCOFFWriter::writeSectionHeaderTable() {
1109 for (const auto *CsectSec
: Sections
)
1110 writeSectionHeader(CsectSec
);
1111 for (const auto &DwarfSec
: DwarfSections
)
1112 writeSectionHeader(&DwarfSec
);
1113 for (const auto &OverflowSec
: OverflowSections
)
1114 writeSectionHeader(&OverflowSec
);
1115 if (hasExceptionSection())
1116 writeSectionHeader(&ExceptionSection
);
1117 if (CInfoSymSection
.Entry
)
1118 writeSectionHeader(&CInfoSymSection
);
1121 void XCOFFWriter::writeRelocation(XCOFFRelocation Reloc
,
1122 const XCOFFSection
&Section
) {
1123 if (Section
.MCSec
->isCsect())
1124 writeWord(Section
.Address
+ Reloc
.FixupOffsetInCsect
);
1126 // DWARF sections' address is set to 0.
1127 assert(Section
.MCSec
->isDwarfSect() && "unsupport section type!");
1128 writeWord(Reloc
.FixupOffsetInCsect
);
1130 W
.write
<uint32_t>(Reloc
.SymbolTableIndex
);
1131 W
.write
<uint8_t>(Reloc
.SignAndSize
);
1132 W
.write
<uint8_t>(Reloc
.Type
);
1135 void XCOFFWriter::writeRelocations() {
1136 for (const auto *Section
: Sections
) {
1137 if (Section
->Index
== SectionEntry::UninitializedIndex
)
1138 // Nothing to write for this Section.
1141 for (const auto *Group
: Section
->Groups
) {
1145 for (const auto &Csect
: *Group
) {
1146 for (const auto Reloc
: Csect
.Relocations
)
1147 writeRelocation(Reloc
, Csect
);
1152 for (const auto &DwarfSection
: DwarfSections
)
1153 for (const auto &Reloc
: DwarfSection
.DwarfSect
->Relocations
)
1154 writeRelocation(Reloc
, *DwarfSection
.DwarfSect
);
1157 void XCOFFWriter::writeSymbolTable(MCAssembler
&Asm
) {
1158 // Write C_FILE symbols.
1159 StringRef Vers
= CompilerVersion
;
1161 for (const std::pair
<std::string
, size_t> &F
: FileNames
) {
1162 // The n_name of a C_FILE symbol is the source file's name when no auxiliary
1163 // entries are present.
1164 StringRef FileName
= F
.first
;
1166 // For C_FILE symbols, the Source Language ID overlays the high-order byte
1167 // of the SymbolType field, and the CPU Version ID is defined as the
1169 // AIX's system assembler determines the source language ID based on the
1170 // source file's name suffix, and the behavior here is consistent with it.
1172 if (FileName
.ends_with(".c"))
1173 LangID
= XCOFF::TB_C
;
1174 else if (FileName
.ends_with_insensitive(".f") ||
1175 FileName
.ends_with_insensitive(".f77") ||
1176 FileName
.ends_with_insensitive(".f90") ||
1177 FileName
.ends_with_insensitive(".f95") ||
1178 FileName
.ends_with_insensitive(".f03") ||
1179 FileName
.ends_with_insensitive(".f08"))
1180 LangID
= XCOFF::TB_Fortran
;
1182 LangID
= XCOFF::TB_CPLUSPLUS
;
1185 CpuID
= XCOFF::TCPU_PPC64
;
1187 CpuID
= XCOFF::TCPU_COM
;
1189 int NumberOfFileAuxEntries
= 1;
1191 ++NumberOfFileAuxEntries
;
1192 writeSymbolEntry(".file", /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG
,
1193 /*SymbolType=*/(LangID
<< 8) | CpuID
, XCOFF::C_FILE
,
1194 NumberOfFileAuxEntries
);
1195 writeSymbolAuxFileEntry(FileName
, XCOFF::XFT_FN
);
1197 writeSymbolAuxFileEntry(Vers
, XCOFF::XFT_CV
);
1200 if (CInfoSymSection
.Entry
)
1201 writeSymbolEntry(CInfoSymSection
.Entry
->Name
, CInfoSymSection
.Entry
->Offset
,
1202 CInfoSymSection
.Index
,
1203 /*SymbolType=*/0, XCOFF::C_INFO
,
1204 /*NumberOfAuxEntries=*/0);
1206 for (const auto &Csect
: UndefinedCsects
) {
1207 writeSymbolEntryForControlSection(Csect
, XCOFF::ReservedSectionNum::N_UNDEF
,
1208 Csect
.MCSec
->getStorageClass());
1211 for (const auto *Section
: Sections
) {
1212 if (Section
->Index
== SectionEntry::UninitializedIndex
)
1213 // Nothing to write for this Section.
1216 for (const auto *Group
: Section
->Groups
) {
1220 const int16_t SectionIndex
= Section
->Index
;
1221 for (const auto &Csect
: *Group
) {
1222 // Write out the control section first and then each symbol in it.
1223 writeSymbolEntryForControlSection(Csect
, SectionIndex
,
1224 Csect
.MCSec
->getStorageClass());
1226 for (const auto &Sym
: Csect
.Syms
)
1227 writeSymbolEntryForCsectMemberLabel(
1228 Sym
, Csect
, SectionIndex
, Asm
.getSymbolOffset(*(Sym
.MCSym
)));
1233 for (const auto &DwarfSection
: DwarfSections
)
1234 writeSymbolEntryForDwarfSection(*DwarfSection
.DwarfSect
,
1235 DwarfSection
.Index
);
1238 void XCOFFWriter::finalizeRelocationInfo(SectionEntry
*Sec
, uint64_t RelCount
) {
1239 // Handles relocation field overflows in an XCOFF32 file. An XCOFF64 file
1240 // may not contain an overflow section header.
1241 if (!is64Bit() && (RelCount
>= static_cast<uint32_t>(XCOFF::RelocOverflow
))) {
1242 // Generate an overflow section header.
1243 SectionEntry
SecEntry(".ovrflo", XCOFF::STYP_OVRFLO
);
1245 // This field specifies the file section number of the section header that
1247 SecEntry
.RelocationCount
= Sec
->Index
;
1249 // This field specifies the number of relocation entries actually
1251 SecEntry
.Address
= RelCount
;
1252 SecEntry
.Index
= ++SectionCount
;
1253 OverflowSections
.push_back(std::move(SecEntry
));
1255 // The field in the primary section header is always 65535
1256 // (XCOFF::RelocOverflow).
1257 Sec
->RelocationCount
= XCOFF::RelocOverflow
;
1259 Sec
->RelocationCount
= RelCount
;
1263 void XCOFFWriter::calcOffsetToRelocations(SectionEntry
*Sec
,
1264 uint64_t &RawPointer
) {
1265 if (!Sec
->RelocationCount
)
1268 Sec
->FileOffsetToRelocations
= RawPointer
;
1269 uint64_t RelocationSizeInSec
= 0;
1271 Sec
->RelocationCount
== static_cast<uint32_t>(XCOFF::RelocOverflow
)) {
1272 // Find its corresponding overflow section.
1273 for (auto &OverflowSec
: OverflowSections
) {
1274 if (OverflowSec
.RelocationCount
== static_cast<uint32_t>(Sec
->Index
)) {
1275 RelocationSizeInSec
=
1276 OverflowSec
.Address
* XCOFF::RelocationSerializationSize32
;
1278 // This field must have the same values as in the corresponding
1279 // primary section header.
1280 OverflowSec
.FileOffsetToRelocations
= Sec
->FileOffsetToRelocations
;
1283 assert(RelocationSizeInSec
&& "Overflow section header doesn't exist.");
1285 RelocationSizeInSec
= Sec
->RelocationCount
*
1286 (is64Bit() ? XCOFF::RelocationSerializationSize64
1287 : XCOFF::RelocationSerializationSize32
);
1290 RawPointer
+= RelocationSizeInSec
;
1291 if (RawPointer
> MaxRawDataSize
)
1292 report_fatal_error("Relocation data overflowed this object file.");
1295 void XCOFFWriter::finalizeSectionInfo() {
1296 for (auto *Section
: Sections
) {
1297 if (Section
->Index
== SectionEntry::UninitializedIndex
)
1298 // Nothing to record for this Section.
1301 uint64_t RelCount
= 0;
1302 for (const auto *Group
: Section
->Groups
) {
1306 for (auto &Csect
: *Group
)
1307 RelCount
+= Csect
.Relocations
.size();
1309 finalizeRelocationInfo(Section
, RelCount
);
1312 for (auto &DwarfSection
: DwarfSections
)
1313 finalizeRelocationInfo(&DwarfSection
,
1314 DwarfSection
.DwarfSect
->Relocations
.size());
1316 // Calculate the RawPointer value for all headers.
1317 uint64_t RawPointer
=
1318 (is64Bit() ? (XCOFF::FileHeaderSize64
+
1319 SectionCount
* XCOFF::SectionHeaderSize64
)
1320 : (XCOFF::FileHeaderSize32
+
1321 SectionCount
* XCOFF::SectionHeaderSize32
)) +
1322 auxiliaryHeaderSize();
1324 // Calculate the file offset to the section data.
1325 for (auto *Sec
: Sections
) {
1326 if (Sec
->Index
== SectionEntry::UninitializedIndex
|| Sec
->IsVirtual
)
1329 RawPointer
= Sec
->advanceFileOffset(MaxRawDataSize
, RawPointer
);
1332 if (!DwarfSections
.empty()) {
1333 RawPointer
+= PaddingsBeforeDwarf
;
1334 for (auto &DwarfSection
: DwarfSections
) {
1335 RawPointer
= DwarfSection
.advanceFileOffset(MaxRawDataSize
, RawPointer
);
1339 if (hasExceptionSection())
1340 RawPointer
= ExceptionSection
.advanceFileOffset(MaxRawDataSize
, RawPointer
);
1342 if (CInfoSymSection
.Entry
)
1343 RawPointer
= CInfoSymSection
.advanceFileOffset(MaxRawDataSize
, RawPointer
);
1345 for (auto *Sec
: Sections
) {
1346 if (Sec
->Index
!= SectionEntry::UninitializedIndex
)
1347 calcOffsetToRelocations(Sec
, RawPointer
);
1350 for (auto &DwarfSec
: DwarfSections
)
1351 calcOffsetToRelocations(&DwarfSec
, RawPointer
);
1353 // TODO Error check that the number of symbol table entries fits in 32-bits
1355 if (SymbolTableEntryCount
)
1356 SymbolTableOffset
= RawPointer
;
1359 void XCOFFWriter::addExceptionEntry(const MCSymbol
*Symbol
,
1360 const MCSymbol
*Trap
, unsigned LanguageCode
,
1361 unsigned ReasonCode
, unsigned FunctionSize
,
1363 // If a module had debug info, debugging is enabled and XCOFF emits the
1364 // exception auxilliary entry.
1366 ExceptionSection
.isDebugEnabled
= true;
1367 auto Entry
= ExceptionSection
.ExceptionTable
.find(Symbol
->getName());
1368 if (Entry
!= ExceptionSection
.ExceptionTable
.end()) {
1369 Entry
->second
.Entries
.push_back(
1370 ExceptionTableEntry(Trap
, LanguageCode
, ReasonCode
));
1373 ExceptionInfo NewEntry
;
1374 NewEntry
.FunctionSymbol
= Symbol
;
1375 NewEntry
.FunctionSize
= FunctionSize
;
1376 NewEntry
.Entries
.push_back(
1377 ExceptionTableEntry(Trap
, LanguageCode
, ReasonCode
));
1378 ExceptionSection
.ExceptionTable
.insert(
1379 std::pair
<const StringRef
, ExceptionInfo
>(Symbol
->getName(), NewEntry
));
1382 unsigned XCOFFWriter::getExceptionSectionSize() {
1383 unsigned EntryNum
= 0;
1385 for (const auto &TableEntry
: ExceptionSection
.ExceptionTable
)
1386 // The size() gets +1 to account for the initial entry containing the
1387 // symbol table index.
1388 EntryNum
+= TableEntry
.second
.Entries
.size() + 1;
1390 return EntryNum
* (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
1391 : XCOFF::ExceptionSectionEntrySize32
);
1394 unsigned XCOFFWriter::getExceptionOffset(const MCSymbol
*Symbol
) {
1395 unsigned EntryNum
= 0;
1396 for (const auto &TableEntry
: ExceptionSection
.ExceptionTable
) {
1397 if (Symbol
== TableEntry
.second
.FunctionSymbol
)
1399 EntryNum
+= TableEntry
.second
.Entries
.size() + 1;
1401 return EntryNum
* (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
1402 : XCOFF::ExceptionSectionEntrySize32
);
1405 void XCOFFWriter::addCInfoSymEntry(StringRef Name
, StringRef Metadata
) {
1406 assert(!CInfoSymSection
.Entry
&& "Multiple entries are not supported");
1407 CInfoSymSection
.addEntry(
1408 std::make_unique
<CInfoSymInfo
>(Name
.str(), Metadata
.str()));
1411 void XCOFFWriter::assignAddressesAndIndices(MCAssembler
&Asm
) {
1412 // The symbol table starts with all the C_FILE symbols. Each C_FILE symbol
1413 // requires 1 or 2 auxiliary entries.
1414 uint32_t SymbolTableIndex
=
1415 (2 + (CompilerVersion
.empty() ? 0 : 1)) * FileNames
.size();
1417 if (CInfoSymSection
.Entry
)
1420 // Calculate indices for undefined symbols.
1421 for (auto &Csect
: UndefinedCsects
) {
1424 Csect
.SymbolTableIndex
= SymbolTableIndex
;
1425 SymbolIndexMap
[Csect
.MCSec
->getQualNameSymbol()] = Csect
.SymbolTableIndex
;
1426 // 1 main and 1 auxiliary symbol table entry for each contained symbol.
1427 SymbolTableIndex
+= 2;
1430 // The address corrresponds to the address of sections and symbols in the
1431 // object file. We place the shared address 0 immediately after the
1432 // section header table.
1433 uint64_t Address
= 0;
1434 // Section indices are 1-based in XCOFF.
1435 int32_t SectionIndex
= 1;
1436 bool HasTDataSection
= false;
1438 for (auto *Section
: Sections
) {
1439 const bool IsEmpty
=
1440 llvm::all_of(Section
->Groups
,
1441 [](const CsectGroup
*Group
) { return Group
->empty(); });
1445 if (SectionIndex
> MaxSectionIndex
)
1446 report_fatal_error("Section index overflow!");
1447 Section
->Index
= SectionIndex
++;
1450 bool SectionAddressSet
= false;
1451 // Reset the starting address to 0 for TData section.
1452 if (Section
->Flags
== XCOFF::STYP_TDATA
) {
1454 HasTDataSection
= true;
1456 // Reset the starting address to 0 for TBSS section if the object file does
1457 // not contain TData Section.
1458 if ((Section
->Flags
== XCOFF::STYP_TBSS
) && !HasTDataSection
)
1461 for (auto *Group
: Section
->Groups
) {
1465 for (auto &Csect
: *Group
) {
1466 const MCSectionXCOFF
*MCSec
= Csect
.MCSec
;
1467 Csect
.Address
= alignTo(Address
, MCSec
->getAlign());
1468 Csect
.Size
= Asm
.getSectionAddressSize(*MCSec
);
1469 Address
= Csect
.Address
+ Csect
.Size
;
1470 Csect
.SymbolTableIndex
= SymbolTableIndex
;
1471 SymbolIndexMap
[MCSec
->getQualNameSymbol()] = Csect
.SymbolTableIndex
;
1472 // 1 main and 1 auxiliary symbol table entry for the csect.
1473 SymbolTableIndex
+= 2;
1475 for (auto &Sym
: Csect
.Syms
) {
1476 bool hasExceptEntry
= false;
1478 ExceptionSection
.ExceptionTable
.find(Sym
.MCSym
->getName());
1479 if (Entry
!= ExceptionSection
.ExceptionTable
.end()) {
1480 hasExceptEntry
= true;
1481 for (auto &TrapEntry
: Entry
->second
.Entries
) {
1482 TrapEntry
.TrapAddress
= Asm
.getSymbolOffset(*(Sym
.MCSym
)) +
1483 TrapEntry
.Trap
->getOffset();
1486 Sym
.SymbolTableIndex
= SymbolTableIndex
;
1487 SymbolIndexMap
[Sym
.MCSym
] = Sym
.SymbolTableIndex
;
1488 // 1 main and 1 auxiliary symbol table entry for each contained
1489 // symbol. For symbols with exception section entries, a function
1490 // auxilliary entry is needed, and on 64-bit XCOFF with debugging
1491 // enabled, an additional exception auxilliary entry is needed.
1492 SymbolTableIndex
+= 2;
1493 if (hasExceptionSection() && hasExceptEntry
) {
1494 if (is64Bit() && ExceptionSection
.isDebugEnabled
)
1495 SymbolTableIndex
+= 2;
1497 SymbolTableIndex
+= 1;
1502 if (!SectionAddressSet
) {
1503 Section
->Address
= Group
->front().Address
;
1504 SectionAddressSet
= true;
1508 // Make sure the address of the next section aligned to
1509 // DefaultSectionAlign.
1510 Address
= alignTo(Address
, DefaultSectionAlign
);
1511 Section
->Size
= Address
- Section
->Address
;
1514 // Start to generate DWARF sections. Sections other than DWARF section use
1515 // DefaultSectionAlign as the default alignment, while DWARF sections have
1516 // their own alignments. If these two alignments are not the same, we need
1517 // some paddings here and record the paddings bytes for FileOffsetToData
1519 if (!DwarfSections
.empty())
1520 PaddingsBeforeDwarf
=
1522 (*DwarfSections
.begin()).DwarfSect
->MCSec
->getAlign()) -
1525 DwarfSectionEntry
*LastDwarfSection
= nullptr;
1526 for (auto &DwarfSection
: DwarfSections
) {
1527 assert((SectionIndex
<= MaxSectionIndex
) && "Section index overflow!");
1529 XCOFFSection
&DwarfSect
= *DwarfSection
.DwarfSect
;
1530 const MCSectionXCOFF
*MCSec
= DwarfSect
.MCSec
;
1533 DwarfSection
.Index
= SectionIndex
++;
1537 DwarfSect
.SymbolTableIndex
= SymbolTableIndex
;
1538 SymbolIndexMap
[MCSec
->getQualNameSymbol()] = DwarfSect
.SymbolTableIndex
;
1539 // 1 main and 1 auxiliary symbol table entry for the csect.
1540 SymbolTableIndex
+= 2;
1542 // Section address. Make it align to section alignment.
1543 // We use address 0 for DWARF sections' Physical and Virtual Addresses.
1544 // This address is used to tell where is the section in the final object.
1545 // See writeSectionForDwarfSectionEntry().
1546 DwarfSection
.Address
= DwarfSect
.Address
=
1547 alignTo(Address
, MCSec
->getAlign());
1550 // For DWARF section, we must use the real size which may be not aligned.
1551 DwarfSection
.Size
= DwarfSect
.Size
= Asm
.getSectionAddressSize(*MCSec
);
1553 Address
= DwarfSection
.Address
+ DwarfSection
.Size
;
1555 if (LastDwarfSection
)
1556 LastDwarfSection
->MemorySize
=
1557 DwarfSection
.Address
- LastDwarfSection
->Address
;
1558 LastDwarfSection
= &DwarfSection
;
1560 if (LastDwarfSection
) {
1561 // Make the final DWARF section address align to the default section
1562 // alignment for follow contents.
1563 Address
= alignTo(LastDwarfSection
->Address
+ LastDwarfSection
->Size
,
1564 DefaultSectionAlign
);
1565 LastDwarfSection
->MemorySize
= Address
- LastDwarfSection
->Address
;
1567 if (hasExceptionSection()) {
1568 ExceptionSection
.Index
= SectionIndex
++;
1570 ExceptionSection
.Address
= 0;
1571 ExceptionSection
.Size
= getExceptionSectionSize();
1572 Address
+= ExceptionSection
.Size
;
1573 Address
= alignTo(Address
, DefaultSectionAlign
);
1576 if (CInfoSymSection
.Entry
) {
1577 CInfoSymSection
.Index
= SectionIndex
++;
1579 CInfoSymSection
.Address
= 0;
1580 Address
+= CInfoSymSection
.Size
;
1581 Address
= alignTo(Address
, DefaultSectionAlign
);
1584 SymbolTableEntryCount
= SymbolTableIndex
;
1587 void XCOFFWriter::writeSectionForControlSectionEntry(
1588 const MCAssembler
&Asm
, const CsectSectionEntry
&CsectEntry
,
1589 uint64_t &CurrentAddressLocation
) {
1590 // Nothing to write for this Section.
1591 if (CsectEntry
.Index
== SectionEntry::UninitializedIndex
)
1594 // There could be a gap (without corresponding zero padding) between
1596 // There could be a gap (without corresponding zero padding) between
1598 assert(((CurrentAddressLocation
<= CsectEntry
.Address
) ||
1599 (CsectEntry
.Flags
== XCOFF::STYP_TDATA
) ||
1600 (CsectEntry
.Flags
== XCOFF::STYP_TBSS
)) &&
1601 "CurrentAddressLocation should be less than or equal to section "
1602 "address if the section is not TData or TBSS.");
1604 CurrentAddressLocation
= CsectEntry
.Address
;
1606 // For virtual sections, nothing to write. But need to increase
1607 // CurrentAddressLocation for later sections like DWARF section has a correct
1608 // writing location.
1609 if (CsectEntry
.IsVirtual
) {
1610 CurrentAddressLocation
+= CsectEntry
.Size
;
1614 for (const auto &Group
: CsectEntry
.Groups
) {
1615 for (const auto &Csect
: *Group
) {
1616 if (uint32_t PaddingSize
= Csect
.Address
- CurrentAddressLocation
)
1617 W
.OS
.write_zeros(PaddingSize
);
1619 Asm
.writeSectionData(W
.OS
, Csect
.MCSec
);
1620 CurrentAddressLocation
= Csect
.Address
+ Csect
.Size
;
1624 // The size of the tail padding in a section is the end virtual address of
1625 // the current section minus the end virtual address of the last csect
1627 if (uint64_t PaddingSize
=
1628 CsectEntry
.Address
+ CsectEntry
.Size
- CurrentAddressLocation
) {
1629 W
.OS
.write_zeros(PaddingSize
);
1630 CurrentAddressLocation
+= PaddingSize
;
1634 void XCOFFWriter::writeSectionForDwarfSectionEntry(
1635 const MCAssembler
&Asm
, const DwarfSectionEntry
&DwarfEntry
,
1636 uint64_t &CurrentAddressLocation
) {
1637 // There could be a gap (without corresponding zero padding) between
1638 // sections. For example DWARF section alignment is bigger than
1639 // DefaultSectionAlign.
1640 assert(CurrentAddressLocation
<= DwarfEntry
.Address
&&
1641 "CurrentAddressLocation should be less than or equal to section "
1644 if (uint64_t PaddingSize
= DwarfEntry
.Address
- CurrentAddressLocation
)
1645 W
.OS
.write_zeros(PaddingSize
);
1647 if (DwarfEntry
.Size
)
1648 Asm
.writeSectionData(W
.OS
, DwarfEntry
.DwarfSect
->MCSec
);
1650 CurrentAddressLocation
= DwarfEntry
.Address
+ DwarfEntry
.Size
;
1652 // DWARF section size is not aligned to DefaultSectionAlign.
1653 // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign.
1654 uint32_t Mod
= CurrentAddressLocation
% DefaultSectionAlign
;
1655 uint32_t TailPaddingSize
= Mod
? DefaultSectionAlign
- Mod
: 0;
1656 if (TailPaddingSize
)
1657 W
.OS
.write_zeros(TailPaddingSize
);
1659 CurrentAddressLocation
+= TailPaddingSize
;
1662 void XCOFFWriter::writeSectionForExceptionSectionEntry(
1663 const MCAssembler
&Asm
, ExceptionSectionEntry
&ExceptionEntry
,
1664 uint64_t &CurrentAddressLocation
) {
1665 for (const auto &TableEntry
: ExceptionEntry
.ExceptionTable
) {
1666 // For every symbol that has exception entries, you must start the entries
1667 // with an initial symbol table index entry
1668 W
.write
<uint32_t>(SymbolIndexMap
[TableEntry
.second
.FunctionSymbol
]);
1670 // 4-byte padding on 64-bit.
1671 W
.OS
.write_zeros(4);
1673 W
.OS
.write_zeros(2);
1674 for (auto &TrapEntry
: TableEntry
.second
.Entries
) {
1675 writeWord(TrapEntry
.TrapAddress
);
1676 W
.write
<uint8_t>(TrapEntry
.Lang
);
1677 W
.write
<uint8_t>(TrapEntry
.Reason
);
1681 CurrentAddressLocation
+= getExceptionSectionSize();
1684 void XCOFFWriter::writeSectionForCInfoSymSectionEntry(
1685 const MCAssembler
&Asm
, CInfoSymSectionEntry
&CInfoSymEntry
,
1686 uint64_t &CurrentAddressLocation
) {
1687 if (!CInfoSymSection
.Entry
)
1690 constexpr int WordSize
= sizeof(uint32_t);
1691 std::unique_ptr
<CInfoSymInfo
> &CISI
= CInfoSymEntry
.Entry
;
1692 const std::string
&Metadata
= CISI
->Metadata
;
1694 // Emit the 4-byte length of the metadata.
1695 W
.write
<uint32_t>(Metadata
.size());
1697 if (Metadata
.size() == 0)
1700 // Write out the payload one word at a time.
1702 while (Index
+ WordSize
<= Metadata
.size()) {
1704 llvm::support::endian::read32be(Metadata
.data() + Index
);
1705 W
.write
<uint32_t>(NextWord
);
1709 // If there is padding, we have at least one byte of payload left to emit.
1710 if (CISI
->paddingSize()) {
1711 std::array
<uint8_t, WordSize
> LastWord
= {0};
1712 ::memcpy(LastWord
.data(), Metadata
.data() + Index
, Metadata
.size() - Index
);
1713 W
.write
<uint32_t>(llvm::support::endian::read32be(LastWord
.data()));
1716 CurrentAddressLocation
+= CISI
->size();
1719 // Takes the log base 2 of the alignment and shifts the result into the 5 most
1720 // significant bits of a byte, then or's in the csect type into the least
1721 // significant 3 bits.
1722 uint8_t getEncodedType(const MCSectionXCOFF
*Sec
) {
1723 unsigned Log2Align
= Log2(Sec
->getAlign());
1724 // Result is a number in the range [0, 31] which fits in the 5 least
1725 // significant bits. Shift this value into the 5 most significant bits, and
1726 // bitwise-or in the csect type.
1727 uint8_t EncodedAlign
= Log2Align
<< 3;
1728 return EncodedAlign
| Sec
->getCSectType();
1731 } // end anonymous namespace
1733 std::unique_ptr
<MCObjectWriter
>
1734 llvm::createXCOFFObjectWriter(std::unique_ptr
<MCXCOFFObjectTargetWriter
> MOTW
,
1735 raw_pwrite_stream
&OS
) {
1736 return std::make_unique
<XCOFFWriter
>(std::move(MOTW
), OS
);