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 XCOFFObjectWriter
: public MCObjectWriter
{
295 uint32_t SymbolTableEntryCount
= 0;
296 uint64_t SymbolTableOffset
= 0;
297 uint16_t SectionCount
= 0;
298 uint32_t PaddingsBeforeDwarf
= 0;
299 bool HasVisibility
= false;
301 support::endian::Writer W
;
302 std::unique_ptr
<MCXCOFFObjectTargetWriter
> TargetObjectWriter
;
303 StringTableBuilder Strings
;
305 const uint64_t MaxRawDataSize
=
306 TargetObjectWriter
->is64Bit() ? UINT64_MAX
: UINT32_MAX
;
308 // Maps the MCSection representation to its corresponding XCOFFSection
309 // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into
310 // from its containing MCSectionXCOFF.
311 DenseMap
<const MCSectionXCOFF
*, XCOFFSection
*> SectionMap
;
313 // Maps the MCSymbol representation to its corrresponding symbol table index.
314 // Needed for relocation.
315 DenseMap
<const MCSymbol
*, uint32_t> SymbolIndexMap
;
317 // CsectGroups. These store the csects which make up different parts of
318 // the sections. Should have one for each set of csects that get mapped into
319 // the same section and get handled in a 'similar' way.
320 CsectGroup UndefinedCsects
;
321 CsectGroup ProgramCodeCsects
;
322 CsectGroup ReadOnlyCsects
;
323 CsectGroup DataCsects
;
324 CsectGroup FuncDSCsects
;
325 CsectGroup TOCCsects
;
326 CsectGroup BSSCsects
;
327 CsectGroup TDataCsects
;
328 CsectGroup TBSSCsects
;
330 // The Predefined sections.
331 CsectSectionEntry Text
;
332 CsectSectionEntry Data
;
333 CsectSectionEntry BSS
;
334 CsectSectionEntry TData
;
335 CsectSectionEntry TBSS
;
337 // All the XCOFF sections, in the order they will appear in the section header
339 std::array
<CsectSectionEntry
*const, 5> Sections
{
340 {&Text
, &Data
, &BSS
, &TData
, &TBSS
}};
342 std::vector
<DwarfSectionEntry
> DwarfSections
;
343 std::vector
<SectionEntry
> OverflowSections
;
345 ExceptionSectionEntry ExceptionSection
;
346 CInfoSymSectionEntry CInfoSymSection
;
348 CsectGroup
&getCsectGroup(const MCSectionXCOFF
*MCSec
);
350 void reset() override
;
352 void executePostLayoutBinding(MCAssembler
&) override
;
354 void recordRelocation(MCAssembler
&, const MCFragment
*, const MCFixup
&,
355 MCValue
, uint64_t &) override
;
357 uint64_t writeObject(MCAssembler
&) override
;
359 bool is64Bit() const { return TargetObjectWriter
->is64Bit(); }
360 bool nameShouldBeInStringTable(const StringRef
&);
361 void writeSymbolName(const StringRef
&);
362 bool auxFileSymNameShouldBeInStringTable(const StringRef
&);
363 void writeAuxFileSymName(const StringRef
&);
365 void writeSymbolEntryForCsectMemberLabel(const Symbol
&SymbolRef
,
366 const XCOFFSection
&CSectionRef
,
367 int16_t SectionIndex
,
368 uint64_t SymbolOffset
);
369 void writeSymbolEntryForControlSection(const XCOFFSection
&CSectionRef
,
370 int16_t SectionIndex
,
371 XCOFF::StorageClass StorageClass
);
372 void writeSymbolEntryForDwarfSection(const XCOFFSection
&DwarfSectionRef
,
373 int16_t SectionIndex
);
374 void writeFileHeader();
375 void writeAuxFileHeader();
376 void writeSectionHeader(const SectionEntry
*Sec
);
377 void writeSectionHeaderTable();
378 void writeSections(const MCAssembler
&Asm
);
379 void writeSectionForControlSectionEntry(const MCAssembler
&Asm
,
380 const CsectSectionEntry
&CsectEntry
,
381 uint64_t &CurrentAddressLocation
);
382 void writeSectionForDwarfSectionEntry(const MCAssembler
&Asm
,
383 const DwarfSectionEntry
&DwarfEntry
,
384 uint64_t &CurrentAddressLocation
);
386 writeSectionForExceptionSectionEntry(const MCAssembler
&Asm
,
387 ExceptionSectionEntry
&ExceptionEntry
,
388 uint64_t &CurrentAddressLocation
);
389 void writeSectionForCInfoSymSectionEntry(const MCAssembler
&Asm
,
390 CInfoSymSectionEntry
&CInfoSymEntry
,
391 uint64_t &CurrentAddressLocation
);
392 void writeSymbolTable(MCAssembler
&Asm
);
393 void writeSymbolAuxFileEntry(StringRef
&Name
, uint8_t ftype
);
394 void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion
,
395 uint64_t NumberOfRelocEnt
= 0);
396 void writeSymbolAuxCsectEntry(uint64_t SectionOrLength
,
397 uint8_t SymbolAlignmentAndType
,
398 uint8_t StorageMappingClass
);
399 void writeSymbolAuxFunctionEntry(uint32_t EntryOffset
, uint32_t FunctionSize
,
400 uint64_t LineNumberPointer
,
402 void writeSymbolAuxExceptionEntry(uint64_t EntryOffset
, uint32_t FunctionSize
,
404 void writeSymbolEntry(StringRef SymbolName
, uint64_t Value
,
405 int16_t SectionNumber
, uint16_t SymbolType
,
406 uint8_t StorageClass
, uint8_t NumberOfAuxEntries
= 1);
407 void writeRelocations();
408 void writeRelocation(XCOFFRelocation Reloc
, const XCOFFSection
&Section
);
410 // Called after all the csects and symbols have been processed by
411 // `executePostLayoutBinding`, this function handles building up the majority
412 // of the structures in the object file representation. Namely:
413 // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
415 // *) Assigns symbol table indices.
416 // *) Builds up the section header table by adding any non-empty sections to
418 void assignAddressesAndIndices(MCAssembler
&Asm
);
419 // Called after relocations are recorded.
420 void finalizeSectionInfo();
421 void finalizeRelocationInfo(SectionEntry
*Sec
, uint64_t RelCount
);
422 void calcOffsetToRelocations(SectionEntry
*Sec
, uint64_t &RawPointer
);
424 bool hasExceptionSection() {
425 return !ExceptionSection
.ExceptionTable
.empty();
427 unsigned getExceptionSectionSize();
428 unsigned getExceptionOffset(const MCSymbol
*Symbol
);
430 size_t auxiliaryHeaderSize() const {
431 // 64-bit object files have no auxiliary header.
432 return HasVisibility
&& !is64Bit() ? XCOFF::AuxFileHeaderSizeShort
: 0;
436 XCOFFObjectWriter(std::unique_ptr
<MCXCOFFObjectTargetWriter
> MOTW
,
437 raw_pwrite_stream
&OS
);
439 void writeWord(uint64_t Word
) {
440 is64Bit() ? W
.write
<uint64_t>(Word
) : W
.write
<uint32_t>(Word
);
443 void addExceptionEntry(const MCSymbol
*Symbol
, const MCSymbol
*Trap
,
444 unsigned LanguageCode
, unsigned ReasonCode
,
445 unsigned FunctionSize
, bool hasDebug
);
446 void addCInfoSymEntry(StringRef Name
, StringRef Metadata
);
449 XCOFFObjectWriter::XCOFFObjectWriter(
450 std::unique_ptr
<MCXCOFFObjectTargetWriter
> MOTW
, raw_pwrite_stream
&OS
)
451 : W(OS
, llvm::endianness::big
), TargetObjectWriter(std::move(MOTW
)),
452 Strings(StringTableBuilder::XCOFF
),
453 Text(".text", XCOFF::STYP_TEXT
, /* IsVirtual */ false,
454 CsectGroups
{&ProgramCodeCsects
, &ReadOnlyCsects
}),
455 Data(".data", XCOFF::STYP_DATA
, /* IsVirtual */ false,
456 CsectGroups
{&DataCsects
, &FuncDSCsects
, &TOCCsects
}),
457 BSS(".bss", XCOFF::STYP_BSS
, /* IsVirtual */ true,
458 CsectGroups
{&BSSCsects
}),
459 TData(".tdata", XCOFF::STYP_TDATA
, /* IsVirtual */ false,
460 CsectGroups
{&TDataCsects
}),
461 TBSS(".tbss", XCOFF::STYP_TBSS
, /* IsVirtual */ true,
462 CsectGroups
{&TBSSCsects
}),
463 ExceptionSection(".except", XCOFF::STYP_EXCEPT
),
464 CInfoSymSection(".info", XCOFF::STYP_INFO
) {}
466 void XCOFFObjectWriter::reset() {
467 // Clear the mappings we created.
468 SymbolIndexMap
.clear();
471 UndefinedCsects
.clear();
472 // Reset any sections we have written to, and empty the section header table.
473 for (auto *Sec
: Sections
)
475 for (auto &DwarfSec
: DwarfSections
)
477 for (auto &OverflowSec
: OverflowSections
)
479 ExceptionSection
.reset();
480 CInfoSymSection
.reset();
482 // Reset states in XCOFFObjectWriter.
483 SymbolTableEntryCount
= 0;
484 SymbolTableOffset
= 0;
486 PaddingsBeforeDwarf
= 0;
489 MCObjectWriter::reset();
492 CsectGroup
&XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF
*MCSec
) {
493 switch (MCSec
->getMappingClass()) {
495 assert(XCOFF::XTY_SD
== MCSec
->getCSectType() &&
496 "Only an initialized csect can contain program code.");
497 return ProgramCodeCsects
;
499 assert(XCOFF::XTY_SD
== MCSec
->getCSectType() &&
500 "Only an initialized csect can contain read only data.");
501 return ReadOnlyCsects
;
503 if (XCOFF::XTY_CM
== MCSec
->getCSectType())
506 if (XCOFF::XTY_SD
== MCSec
->getCSectType())
509 report_fatal_error("Unhandled mapping of read-write csect to section.");
513 assert(XCOFF::XTY_CM
== MCSec
->getCSectType() &&
514 "Mapping invalid csect. CSECT with bss storage class must be "
518 assert(XCOFF::XTY_SD
== MCSec
->getCSectType() &&
519 "Mapping invalid csect. CSECT with tdata storage class must be "
520 "an initialized csect.");
523 assert(XCOFF::XTY_CM
== MCSec
->getCSectType() &&
524 "Mapping invalid csect. CSECT with tbss storage class must be "
525 "an uninitialized csect.");
528 assert(XCOFF::XTY_SD
== MCSec
->getCSectType() &&
529 "Only an initialized csect can contain TOC-base.");
530 assert(TOCCsects
.empty() &&
531 "We should have only one TOC-base, and it should be the first csect "
532 "in this CsectGroup.");
536 assert(XCOFF::XTY_SD
== MCSec
->getCSectType() &&
537 "A TOC symbol must be an initialized csect.");
538 assert(!TOCCsects
.empty() &&
539 "We should at least have a TOC-base in this CsectGroup.");
542 assert((XCOFF::XTY_SD
== MCSec
->getCSectType() ||
543 XCOFF::XTY_CM
== MCSec
->getCSectType()) &&
544 "Symbol type incompatible with toc-data.");
545 assert(!TOCCsects
.empty() &&
546 "We should at least have a TOC-base in this CsectGroup.");
549 report_fatal_error("Unhandled mapping of csect to section.");
553 static MCSectionXCOFF
*getContainingCsect(const MCSymbolXCOFF
*XSym
) {
554 if (XSym
->isDefined())
555 return cast
<MCSectionXCOFF
>(XSym
->getFragment()->getParent());
556 return XSym
->getRepresentedCsect();
559 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler
&Asm
) {
560 for (const auto &S
: Asm
) {
561 const auto *MCSec
= cast
<const MCSectionXCOFF
>(&S
);
562 assert(!SectionMap
.contains(MCSec
) && "Cannot add a section twice.");
564 // If the name does not fit in the storage provided in the symbol table
565 // entry, add it to the string table.
566 if (nameShouldBeInStringTable(MCSec
->getSymbolTableName()))
567 Strings
.add(MCSec
->getSymbolTableName());
568 if (MCSec
->isCsect()) {
569 // A new control section. Its CsectSectionEntry should already be staticly
570 // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of
571 // the CsectSectionEntry.
572 assert(XCOFF::XTY_ER
!= MCSec
->getCSectType() &&
573 "An undefined csect should not get registered.");
574 CsectGroup
&Group
= getCsectGroup(MCSec
);
575 Group
.emplace_back(MCSec
);
576 SectionMap
[MCSec
] = &Group
.back();
577 } else if (MCSec
->isDwarfSect()) {
578 // A new DwarfSectionEntry.
579 std::unique_ptr
<XCOFFSection
> DwarfSec
=
580 std::make_unique
<XCOFFSection
>(MCSec
);
581 SectionMap
[MCSec
] = DwarfSec
.get();
583 DwarfSectionEntry
SecEntry(MCSec
->getName(),
584 *MCSec
->getDwarfSubtypeFlags(),
585 std::move(DwarfSec
));
586 DwarfSections
.push_back(std::move(SecEntry
));
588 llvm_unreachable("unsupport section type!");
591 for (const MCSymbol
&S
: Asm
.symbols()) {
592 // Nothing to do for temporary symbols.
596 const MCSymbolXCOFF
*XSym
= cast
<MCSymbolXCOFF
>(&S
);
597 const MCSectionXCOFF
*ContainingCsect
= getContainingCsect(XSym
);
599 if (ContainingCsect
->isDwarfSect())
602 if (XSym
->getVisibilityType() != XCOFF::SYM_V_UNSPECIFIED
)
603 HasVisibility
= true;
605 if (ContainingCsect
->getCSectType() == XCOFF::XTY_ER
) {
606 // Handle undefined symbol.
607 UndefinedCsects
.emplace_back(ContainingCsect
);
608 SectionMap
[ContainingCsect
] = &UndefinedCsects
.back();
609 if (nameShouldBeInStringTable(ContainingCsect
->getSymbolTableName()))
610 Strings
.add(ContainingCsect
->getSymbolTableName());
614 // If the symbol is the csect itself, we don't need to put the symbol
615 // into csect's Syms.
616 if (XSym
== ContainingCsect
->getQualNameSymbol())
619 // Only put a label into the symbol table when it is an external label.
620 if (!XSym
->isExternal())
623 assert(SectionMap
.contains(ContainingCsect
) &&
624 "Expected containing csect to exist in map");
625 XCOFFSection
*Csect
= SectionMap
[ContainingCsect
];
626 // Lookup the containing csect and add the symbol to it.
627 assert(Csect
->MCSec
->isCsect() && "only csect is supported now!");
628 Csect
->Syms
.emplace_back(XSym
);
630 // If the name does not fit in the storage provided in the symbol table
631 // entry, add it to the string table.
632 if (nameShouldBeInStringTable(XSym
->getSymbolTableName()))
633 Strings
.add(XSym
->getSymbolTableName());
636 std::unique_ptr
<CInfoSymInfo
> &CISI
= CInfoSymSection
.Entry
;
637 if (CISI
&& nameShouldBeInStringTable(CISI
->Name
))
638 Strings
.add(CISI
->Name
);
640 // Emit ".file" as the source file name when there is no file name.
641 if (FileNames
.empty())
642 FileNames
.emplace_back(".file", 0);
643 for (const std::pair
<std::string
, size_t> &F
: FileNames
) {
644 if (auxFileSymNameShouldBeInStringTable(F
.first
))
645 Strings
.add(F
.first
);
648 // Always add ".file" to the symbol table. The actual file name will be in
649 // the AUX_FILE auxiliary entry.
650 if (nameShouldBeInStringTable(".file"))
651 Strings
.add(".file");
652 StringRef Vers
= CompilerVersion
;
653 if (auxFileSymNameShouldBeInStringTable(Vers
))
657 assignAddressesAndIndices(Asm
);
660 void XCOFFObjectWriter::recordRelocation(MCAssembler
&Asm
,
661 const MCFragment
*Fragment
,
662 const MCFixup
&Fixup
, MCValue Target
,
663 uint64_t &FixedValue
) {
664 auto getIndex
= [this](const MCSymbol
*Sym
,
665 const MCSectionXCOFF
*ContainingCsect
) {
666 // If we could not find the symbol directly in SymbolIndexMap, this symbol
667 // could either be a temporary symbol or an undefined symbol. In this case,
668 // we would need to have the relocation reference its csect instead.
669 return SymbolIndexMap
.contains(Sym
)
670 ? SymbolIndexMap
[Sym
]
671 : SymbolIndexMap
[ContainingCsect
->getQualNameSymbol()];
674 auto getVirtualAddress
=
675 [this, &Asm
](const MCSymbol
*Sym
,
676 const MCSectionXCOFF
*ContainingSect
) -> uint64_t {
678 if (ContainingSect
->isDwarfSect())
679 return Asm
.getSymbolOffset(*Sym
);
682 if (!Sym
->isDefined())
683 return SectionMap
[ContainingSect
]->Address
;
686 assert(Sym
->isDefined() && "not a valid object that has address!");
687 return SectionMap
[ContainingSect
]->Address
+ Asm
.getSymbolOffset(*Sym
);
690 const MCSymbol
*const SymA
= &Target
.getSymA()->getSymbol();
692 MCAsmBackend
&Backend
= Asm
.getBackend();
693 bool IsPCRel
= Backend
.getFixupKindInfo(Fixup
.getKind()).Flags
&
694 MCFixupKindInfo::FKF_IsPCRel
;
698 std::tie(Type
, SignAndSize
) =
699 TargetObjectWriter
->getRelocTypeAndSignSize(Target
, Fixup
, IsPCRel
);
701 const MCSectionXCOFF
*SymASec
= getContainingCsect(cast
<MCSymbolXCOFF
>(SymA
));
702 assert(SectionMap
.contains(SymASec
) &&
703 "Expected containing csect to exist in map.");
705 assert((Fixup
.getOffset() <=
706 MaxRawDataSize
- Asm
.getFragmentOffset(*Fragment
)) &&
707 "Fragment offset + fixup offset is overflowed.");
708 uint32_t FixupOffsetInCsect
=
709 Asm
.getFragmentOffset(*Fragment
) + Fixup
.getOffset();
711 const uint32_t Index
= getIndex(SymA
, SymASec
);
712 if (Type
== XCOFF::RelocationType::R_POS
||
713 Type
== XCOFF::RelocationType::R_TLS
||
714 Type
== XCOFF::RelocationType::R_TLS_LE
||
715 Type
== XCOFF::RelocationType::R_TLS_IE
||
716 Type
== XCOFF::RelocationType::R_TLS_LD
)
717 // The FixedValue should be symbol's virtual address in this object file
718 // plus any constant value that we might get.
719 FixedValue
= getVirtualAddress(SymA
, SymASec
) + Target
.getConstant();
720 else if (Type
== XCOFF::RelocationType::R_TLSM
)
721 // The FixedValue should always be zero since the region handle is only
722 // known at load time.
724 else if (Type
== XCOFF::RelocationType::R_TOC
||
725 Type
== XCOFF::RelocationType::R_TOCL
) {
726 // For non toc-data external symbols, R_TOC type relocation will relocate to
727 // data symbols that have XCOFF::XTY_SD type csect. For toc-data external
728 // symbols, R_TOC type relocation will relocate to data symbols that have
729 // XCOFF_ER type csect. For XCOFF_ER kind symbols, there will be no TOC
730 // entry for them, so the FixedValue should always be 0.
731 if (SymASec
->getCSectType() == XCOFF::XTY_ER
) {
734 // The FixedValue should be the TOC entry offset from the TOC-base plus
735 // any constant offset value.
736 int64_t TOCEntryOffset
= SectionMap
[SymASec
]->Address
-
737 TOCCsects
.front().Address
+ Target
.getConstant();
738 // For small code model, if the TOCEntryOffset overflows the 16-bit value,
739 // we truncate it back down to 16 bits. The linker will be able to insert
740 // fix-up code when needed.
741 // For non toc-data symbols, we already did the truncation in
742 // PPCAsmPrinter.cpp through setting Target.getConstant() in the
743 // expression above by calling getTOCEntryLoadingExprForXCOFF for the
744 // various TOC PseudoOps.
745 // For toc-data symbols, we were not able to calculate the offset from
746 // the TOC in PPCAsmPrinter.cpp since the TOC has not been finalized at
747 // that point, so we are adjusting it here though
748 // llvm::SignExtend64<16>(TOCEntryOffset);
749 // TODO: Since the time that the handling for offsets over 16-bits was
750 // added in PPCAsmPrinter.cpp using getTOCEntryLoadingExprForXCOFF, the
751 // system assembler and linker have been updated to be able to handle the
752 // overflowing offsets, so we no longer need to keep
753 // getTOCEntryLoadingExprForXCOFF.
754 if (Type
== XCOFF::RelocationType::R_TOC
&& !isInt
<16>(TOCEntryOffset
))
755 TOCEntryOffset
= llvm::SignExtend64
<16>(TOCEntryOffset
);
757 FixedValue
= TOCEntryOffset
;
759 } else if (Type
== XCOFF::RelocationType::R_RBR
) {
760 MCSectionXCOFF
*ParentSec
= cast
<MCSectionXCOFF
>(Fragment
->getParent());
761 assert((SymASec
->getMappingClass() == XCOFF::XMC_PR
&&
762 ParentSec
->getMappingClass() == XCOFF::XMC_PR
) &&
763 "Only XMC_PR csect may have the R_RBR relocation.");
765 // The address of the branch instruction should be the sum of section
766 // address, fragment offset and Fixup offset.
767 uint64_t BRInstrAddress
=
768 SectionMap
[ParentSec
]->Address
+ FixupOffsetInCsect
;
769 // The FixedValue should be the difference between symbol's virtual address
770 // and BR instr address plus any constant value.
771 FixedValue
= getVirtualAddress(SymA
, SymASec
) - BRInstrAddress
+
772 Target
.getConstant();
773 } else if (Type
== XCOFF::RelocationType::R_REF
) {
774 // The FixedValue and FixupOffsetInCsect should always be 0 since it
775 // specifies a nonrelocating reference.
777 FixupOffsetInCsect
= 0;
780 XCOFFRelocation Reloc
= {Index
, FixupOffsetInCsect
, SignAndSize
, Type
};
781 MCSectionXCOFF
*RelocationSec
= cast
<MCSectionXCOFF
>(Fragment
->getParent());
782 assert(SectionMap
.contains(RelocationSec
) &&
783 "Expected containing csect to exist in map.");
784 SectionMap
[RelocationSec
]->Relocations
.push_back(Reloc
);
786 if (!Target
.getSymB())
789 const MCSymbol
*const SymB
= &Target
.getSymB()->getSymbol();
791 report_fatal_error("relocation for opposite term is not yet supported");
793 const MCSectionXCOFF
*SymBSec
= getContainingCsect(cast
<MCSymbolXCOFF
>(SymB
));
794 assert(SectionMap
.contains(SymBSec
) &&
795 "Expected containing csect to exist in map.");
796 if (SymASec
== SymBSec
)
798 "relocation for paired relocatable term is not yet supported");
800 assert(Type
== XCOFF::RelocationType::R_POS
&&
801 "SymA must be R_POS here if it's not opposite term or paired "
802 "relocatable term.");
803 const uint32_t IndexB
= getIndex(SymB
, SymBSec
);
804 // SymB must be R_NEG here, given the general form of Target(MCValue) is
805 // "SymbolA - SymbolB + imm64".
806 const uint8_t TypeB
= XCOFF::RelocationType::R_NEG
;
807 XCOFFRelocation RelocB
= {IndexB
, FixupOffsetInCsect
, SignAndSize
, TypeB
};
808 SectionMap
[RelocationSec
]->Relocations
.push_back(RelocB
);
809 // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
810 // now we just need to fold "- SymbolB" here.
811 FixedValue
-= getVirtualAddress(SymB
, SymBSec
);
814 void XCOFFObjectWriter::writeSections(const MCAssembler
&Asm
) {
815 uint64_t CurrentAddressLocation
= 0;
816 for (const auto *Section
: Sections
)
817 writeSectionForControlSectionEntry(Asm
, *Section
, CurrentAddressLocation
);
818 for (const auto &DwarfSection
: DwarfSections
)
819 writeSectionForDwarfSectionEntry(Asm
, DwarfSection
, CurrentAddressLocation
);
820 writeSectionForExceptionSectionEntry(Asm
, ExceptionSection
,
821 CurrentAddressLocation
);
822 writeSectionForCInfoSymSectionEntry(Asm
, CInfoSymSection
,
823 CurrentAddressLocation
);
826 uint64_t XCOFFObjectWriter::writeObject(MCAssembler
&Asm
) {
827 // We always emit a timestamp of 0 for reproducibility, so ensure incremental
828 // linking is not enabled, in case, like with Windows COFF, such a timestamp
829 // is incompatible with incremental linking of XCOFF.
831 finalizeSectionInfo();
832 uint64_t StartOffset
= W
.OS
.tell();
835 writeAuxFileHeader();
836 writeSectionHeaderTable();
839 writeSymbolTable(Asm
);
840 // Write the string table.
843 return W
.OS
.tell() - StartOffset
;
846 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef
&SymbolName
) {
847 return SymbolName
.size() > XCOFF::NameSize
|| is64Bit();
850 void XCOFFObjectWriter::writeSymbolName(const StringRef
&SymbolName
) {
851 // Magic, Offset or SymbolName.
852 if (nameShouldBeInStringTable(SymbolName
)) {
854 W
.write
<uint32_t>(Strings
.getOffset(SymbolName
));
856 char Name
[XCOFF::NameSize
+ 1];
857 std::strncpy(Name
, SymbolName
.data(), XCOFF::NameSize
);
858 ArrayRef
<char> NameRef(Name
, XCOFF::NameSize
);
863 void XCOFFObjectWriter::writeSymbolEntry(StringRef SymbolName
, uint64_t Value
,
864 int16_t SectionNumber
,
866 uint8_t StorageClass
,
867 uint8_t NumberOfAuxEntries
) {
869 W
.write
<uint64_t>(Value
);
870 W
.write
<uint32_t>(Strings
.getOffset(SymbolName
));
872 writeSymbolName(SymbolName
);
873 W
.write
<uint32_t>(Value
);
875 W
.write
<int16_t>(SectionNumber
);
876 W
.write
<uint16_t>(SymbolType
);
877 W
.write
<uint8_t>(StorageClass
);
878 W
.write
<uint8_t>(NumberOfAuxEntries
);
881 void XCOFFObjectWriter::writeSymbolAuxCsectEntry(uint64_t SectionOrLength
,
882 uint8_t SymbolAlignmentAndType
,
883 uint8_t StorageMappingClass
) {
884 W
.write
<uint32_t>(is64Bit() ? Lo_32(SectionOrLength
) : SectionOrLength
);
885 W
.write
<uint32_t>(0); // ParameterHashIndex
886 W
.write
<uint16_t>(0); // TypeChkSectNum
887 W
.write
<uint8_t>(SymbolAlignmentAndType
);
888 W
.write
<uint8_t>(StorageMappingClass
);
890 W
.write
<uint32_t>(Hi_32(SectionOrLength
));
891 W
.OS
.write_zeros(1); // Reserved
892 W
.write
<uint8_t>(XCOFF::AUX_CSECT
);
894 W
.write
<uint32_t>(0); // StabInfoIndex
895 W
.write
<uint16_t>(0); // StabSectNum
899 bool XCOFFObjectWriter::auxFileSymNameShouldBeInStringTable(
900 const StringRef
&SymbolName
) {
901 return SymbolName
.size() > XCOFF::AuxFileEntNameSize
;
904 void XCOFFObjectWriter::writeAuxFileSymName(const StringRef
&SymbolName
) {
905 // Magic, Offset or SymbolName.
906 if (auxFileSymNameShouldBeInStringTable(SymbolName
)) {
908 W
.write
<uint32_t>(Strings
.getOffset(SymbolName
));
909 W
.OS
.write_zeros(XCOFF::FileNamePadSize
);
911 char Name
[XCOFF::AuxFileEntNameSize
+ 1];
912 std::strncpy(Name
, SymbolName
.data(), XCOFF::AuxFileEntNameSize
);
913 ArrayRef
<char> NameRef(Name
, XCOFF::AuxFileEntNameSize
);
918 void XCOFFObjectWriter::writeSymbolAuxFileEntry(StringRef
&Name
,
920 writeAuxFileSymName(Name
);
921 W
.write
<uint8_t>(ftype
);
924 W
.write
<uint8_t>(XCOFF::AUX_FILE
);
929 void XCOFFObjectWriter::writeSymbolAuxDwarfEntry(
930 uint64_t LengthOfSectionPortion
, uint64_t NumberOfRelocEnt
) {
931 writeWord(LengthOfSectionPortion
);
933 W
.OS
.write_zeros(4); // Reserved
934 writeWord(NumberOfRelocEnt
);
936 W
.OS
.write_zeros(1); // Reserved
937 W
.write
<uint8_t>(XCOFF::AUX_SECT
);
939 W
.OS
.write_zeros(6); // Reserved
943 void XCOFFObjectWriter::writeSymbolEntryForCsectMemberLabel(
944 const Symbol
&SymbolRef
, const XCOFFSection
&CSectionRef
,
945 int16_t SectionIndex
, uint64_t SymbolOffset
) {
946 assert(SymbolOffset
<= MaxRawDataSize
- CSectionRef
.Address
&&
947 "Symbol address overflowed.");
949 auto Entry
= ExceptionSection
.ExceptionTable
.find(SymbolRef
.MCSym
->getName());
950 if (Entry
!= ExceptionSection
.ExceptionTable
.end()) {
951 writeSymbolEntry(SymbolRef
.getSymbolTableName(),
952 CSectionRef
.Address
+ SymbolOffset
, SectionIndex
,
953 // In the old version of the 32-bit XCOFF interpretation,
954 // symbols may require bit 10 (0x0020) to be set if the
955 // symbol is a function, otherwise the bit should be 0.
956 is64Bit() ? SymbolRef
.getVisibilityType()
957 : SymbolRef
.getVisibilityType() | 0x0020,
958 SymbolRef
.getStorageClass(),
959 (is64Bit() && ExceptionSection
.isDebugEnabled
) ? 3 : 2);
960 if (is64Bit() && ExceptionSection
.isDebugEnabled
) {
961 // On 64 bit with debugging enabled, we have a csect, exception, and
962 // function auxilliary entries, so we must increment symbol index by 4.
963 writeSymbolAuxExceptionEntry(
964 ExceptionSection
.FileOffsetToData
+
965 getExceptionOffset(Entry
->second
.FunctionSymbol
),
966 Entry
->second
.FunctionSize
,
967 SymbolIndexMap
[Entry
->second
.FunctionSymbol
] + 4);
969 // For exception section entries, csect and function auxilliary entries
970 // must exist. On 64-bit there is also an exception auxilliary entry.
971 writeSymbolAuxFunctionEntry(
972 ExceptionSection
.FileOffsetToData
+
973 getExceptionOffset(Entry
->second
.FunctionSymbol
),
974 Entry
->second
.FunctionSize
, 0,
975 (is64Bit() && ExceptionSection
.isDebugEnabled
)
976 ? SymbolIndexMap
[Entry
->second
.FunctionSymbol
] + 4
977 : SymbolIndexMap
[Entry
->second
.FunctionSymbol
] + 3);
979 writeSymbolEntry(SymbolRef
.getSymbolTableName(),
980 CSectionRef
.Address
+ SymbolOffset
, SectionIndex
,
981 SymbolRef
.getVisibilityType(),
982 SymbolRef
.getStorageClass());
984 writeSymbolAuxCsectEntry(CSectionRef
.SymbolTableIndex
, XCOFF::XTY_LD
,
985 CSectionRef
.MCSec
->getMappingClass());
988 void XCOFFObjectWriter::writeSymbolEntryForDwarfSection(
989 const XCOFFSection
&DwarfSectionRef
, int16_t SectionIndex
) {
990 assert(DwarfSectionRef
.MCSec
->isDwarfSect() && "Not a DWARF section!");
992 writeSymbolEntry(DwarfSectionRef
.getSymbolTableName(), /*Value=*/0,
993 SectionIndex
, /*SymbolType=*/0, XCOFF::C_DWARF
);
995 writeSymbolAuxDwarfEntry(DwarfSectionRef
.Size
);
998 void XCOFFObjectWriter::writeSymbolEntryForControlSection(
999 const XCOFFSection
&CSectionRef
, int16_t SectionIndex
,
1000 XCOFF::StorageClass StorageClass
) {
1001 writeSymbolEntry(CSectionRef
.getSymbolTableName(), CSectionRef
.Address
,
1002 SectionIndex
, CSectionRef
.getVisibilityType(), StorageClass
);
1004 writeSymbolAuxCsectEntry(CSectionRef
.Size
, getEncodedType(CSectionRef
.MCSec
),
1005 CSectionRef
.MCSec
->getMappingClass());
1008 void XCOFFObjectWriter::writeSymbolAuxFunctionEntry(uint32_t EntryOffset
,
1009 uint32_t FunctionSize
,
1010 uint64_t LineNumberPointer
,
1011 uint32_t EndIndex
) {
1013 writeWord(LineNumberPointer
);
1015 W
.write
<uint32_t>(EntryOffset
);
1016 W
.write
<uint32_t>(FunctionSize
);
1018 writeWord(LineNumberPointer
);
1019 W
.write
<uint32_t>(EndIndex
);
1021 W
.OS
.write_zeros(1);
1022 W
.write
<uint8_t>(XCOFF::AUX_FCN
);
1024 W
.OS
.write_zeros(2);
1028 void XCOFFObjectWriter::writeSymbolAuxExceptionEntry(uint64_t EntryOffset
,
1029 uint32_t FunctionSize
,
1030 uint32_t EndIndex
) {
1031 assert(is64Bit() && "Exception auxilliary entries are 64-bit only.");
1032 W
.write
<uint64_t>(EntryOffset
);
1033 W
.write
<uint32_t>(FunctionSize
);
1034 W
.write
<uint32_t>(EndIndex
);
1035 W
.OS
.write_zeros(1); // Pad (unused)
1036 W
.write
<uint8_t>(XCOFF::AUX_EXCEPT
);
1039 void XCOFFObjectWriter::writeFileHeader() {
1040 W
.write
<uint16_t>(is64Bit() ? XCOFF::XCOFF64
: XCOFF::XCOFF32
);
1041 W
.write
<uint16_t>(SectionCount
);
1042 W
.write
<int32_t>(0); // TimeStamp
1043 writeWord(SymbolTableOffset
);
1045 W
.write
<uint16_t>(auxiliaryHeaderSize());
1046 W
.write
<uint16_t>(0); // Flags
1047 W
.write
<int32_t>(SymbolTableEntryCount
);
1049 W
.write
<int32_t>(SymbolTableEntryCount
);
1050 W
.write
<uint16_t>(auxiliaryHeaderSize());
1051 W
.write
<uint16_t>(0); // Flags
1055 void XCOFFObjectWriter::writeAuxFileHeader() {
1056 if (!auxiliaryHeaderSize())
1058 W
.write
<uint16_t>(0); // Magic
1060 XCOFF::NEW_XCOFF_INTERPRET
); // Version. The new interpretation of the
1061 // n_type field in the symbol table entry is
1063 W
.write
<uint32_t>(Sections
[0]->Size
); // TextSize
1064 W
.write
<uint32_t>(Sections
[1]->Size
); // InitDataSize
1065 W
.write
<uint32_t>(Sections
[2]->Size
); // BssDataSize
1066 W
.write
<uint32_t>(0); // EntryPointAddr
1067 W
.write
<uint32_t>(Sections
[0]->Address
); // TextStartAddr
1068 W
.write
<uint32_t>(Sections
[1]->Address
); // DataStartAddr
1071 void XCOFFObjectWriter::writeSectionHeader(const SectionEntry
*Sec
) {
1072 bool IsDwarf
= (Sec
->Flags
& XCOFF::STYP_DWARF
) != 0;
1073 bool IsOvrflo
= (Sec
->Flags
& XCOFF::STYP_OVRFLO
) != 0;
1074 // Nothing to write for this Section.
1075 if (Sec
->Index
== SectionEntry::UninitializedIndex
)
1079 ArrayRef
<char> NameRef(Sec
->Name
, XCOFF::NameSize
);
1082 // Write the Physical Address and Virtual Address.
1083 // We use 0 for DWARF sections' Physical and Virtual Addresses.
1084 writeWord(IsDwarf
? 0 : Sec
->Address
);
1085 // Since line number is not supported, we set it to 0 for overflow sections.
1086 writeWord((IsDwarf
|| IsOvrflo
) ? 0 : Sec
->Address
);
1088 writeWord(Sec
->Size
);
1089 writeWord(Sec
->FileOffsetToData
);
1090 writeWord(Sec
->FileOffsetToRelocations
);
1091 writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet.
1094 W
.write
<uint32_t>(Sec
->RelocationCount
);
1095 W
.write
<uint32_t>(0); // NumberOfLineNumbers. Not supported yet.
1096 W
.write
<int32_t>(Sec
->Flags
);
1097 W
.OS
.write_zeros(4);
1099 // For the overflow section header, s_nreloc provides a reference to the
1100 // primary section header and s_nlnno must have the same value.
1101 // For common section headers, if either of s_nreloc or s_nlnno are set to
1102 // 65535, the other one must also be set to 65535.
1103 W
.write
<uint16_t>(Sec
->RelocationCount
);
1104 W
.write
<uint16_t>((IsOvrflo
|| Sec
->RelocationCount
== XCOFF::RelocOverflow
)
1105 ? Sec
->RelocationCount
1106 : 0); // NumberOfLineNumbers. Not supported yet.
1107 W
.write
<int32_t>(Sec
->Flags
);
1111 void XCOFFObjectWriter::writeSectionHeaderTable() {
1112 for (const auto *CsectSec
: Sections
)
1113 writeSectionHeader(CsectSec
);
1114 for (const auto &DwarfSec
: DwarfSections
)
1115 writeSectionHeader(&DwarfSec
);
1116 for (const auto &OverflowSec
: OverflowSections
)
1117 writeSectionHeader(&OverflowSec
);
1118 if (hasExceptionSection())
1119 writeSectionHeader(&ExceptionSection
);
1120 if (CInfoSymSection
.Entry
)
1121 writeSectionHeader(&CInfoSymSection
);
1124 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc
,
1125 const XCOFFSection
&Section
) {
1126 if (Section
.MCSec
->isCsect())
1127 writeWord(Section
.Address
+ Reloc
.FixupOffsetInCsect
);
1129 // DWARF sections' address is set to 0.
1130 assert(Section
.MCSec
->isDwarfSect() && "unsupport section type!");
1131 writeWord(Reloc
.FixupOffsetInCsect
);
1133 W
.write
<uint32_t>(Reloc
.SymbolTableIndex
);
1134 W
.write
<uint8_t>(Reloc
.SignAndSize
);
1135 W
.write
<uint8_t>(Reloc
.Type
);
1138 void XCOFFObjectWriter::writeRelocations() {
1139 for (const auto *Section
: Sections
) {
1140 if (Section
->Index
== SectionEntry::UninitializedIndex
)
1141 // Nothing to write for this Section.
1144 for (const auto *Group
: Section
->Groups
) {
1148 for (const auto &Csect
: *Group
) {
1149 for (const auto Reloc
: Csect
.Relocations
)
1150 writeRelocation(Reloc
, Csect
);
1155 for (const auto &DwarfSection
: DwarfSections
)
1156 for (const auto &Reloc
: DwarfSection
.DwarfSect
->Relocations
)
1157 writeRelocation(Reloc
, *DwarfSection
.DwarfSect
);
1160 void XCOFFObjectWriter::writeSymbolTable(MCAssembler
&Asm
) {
1161 // Write C_FILE symbols.
1162 StringRef Vers
= CompilerVersion
;
1164 for (const std::pair
<std::string
, size_t> &F
: FileNames
) {
1165 // The n_name of a C_FILE symbol is the source file's name when no auxiliary
1166 // entries are present.
1167 StringRef FileName
= F
.first
;
1169 // For C_FILE symbols, the Source Language ID overlays the high-order byte
1170 // of the SymbolType field, and the CPU Version ID is defined as the
1172 // AIX's system assembler determines the source language ID based on the
1173 // source file's name suffix, and the behavior here is consistent with it.
1175 if (FileName
.ends_with(".c"))
1176 LangID
= XCOFF::TB_C
;
1177 else if (FileName
.ends_with_insensitive(".f") ||
1178 FileName
.ends_with_insensitive(".f77") ||
1179 FileName
.ends_with_insensitive(".f90") ||
1180 FileName
.ends_with_insensitive(".f95") ||
1181 FileName
.ends_with_insensitive(".f03") ||
1182 FileName
.ends_with_insensitive(".f08"))
1183 LangID
= XCOFF::TB_Fortran
;
1185 LangID
= XCOFF::TB_CPLUSPLUS
;
1188 CpuID
= XCOFF::TCPU_PPC64
;
1190 CpuID
= XCOFF::TCPU_COM
;
1192 int NumberOfFileAuxEntries
= 1;
1194 ++NumberOfFileAuxEntries
;
1195 writeSymbolEntry(".file", /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG
,
1196 /*SymbolType=*/(LangID
<< 8) | CpuID
, XCOFF::C_FILE
,
1197 NumberOfFileAuxEntries
);
1198 writeSymbolAuxFileEntry(FileName
, XCOFF::XFT_FN
);
1200 writeSymbolAuxFileEntry(Vers
, XCOFF::XFT_CV
);
1203 if (CInfoSymSection
.Entry
)
1204 writeSymbolEntry(CInfoSymSection
.Entry
->Name
, CInfoSymSection
.Entry
->Offset
,
1205 CInfoSymSection
.Index
,
1206 /*SymbolType=*/0, XCOFF::C_INFO
,
1207 /*NumberOfAuxEntries=*/0);
1209 for (const auto &Csect
: UndefinedCsects
) {
1210 writeSymbolEntryForControlSection(Csect
, XCOFF::ReservedSectionNum::N_UNDEF
,
1211 Csect
.MCSec
->getStorageClass());
1214 for (const auto *Section
: Sections
) {
1215 if (Section
->Index
== SectionEntry::UninitializedIndex
)
1216 // Nothing to write for this Section.
1219 for (const auto *Group
: Section
->Groups
) {
1223 const int16_t SectionIndex
= Section
->Index
;
1224 for (const auto &Csect
: *Group
) {
1225 // Write out the control section first and then each symbol in it.
1226 writeSymbolEntryForControlSection(Csect
, SectionIndex
,
1227 Csect
.MCSec
->getStorageClass());
1229 for (const auto &Sym
: Csect
.Syms
)
1230 writeSymbolEntryForCsectMemberLabel(
1231 Sym
, Csect
, SectionIndex
, Asm
.getSymbolOffset(*(Sym
.MCSym
)));
1236 for (const auto &DwarfSection
: DwarfSections
)
1237 writeSymbolEntryForDwarfSection(*DwarfSection
.DwarfSect
,
1238 DwarfSection
.Index
);
1241 void XCOFFObjectWriter::finalizeRelocationInfo(SectionEntry
*Sec
,
1242 uint64_t RelCount
) {
1243 // Handles relocation field overflows in an XCOFF32 file. An XCOFF64 file
1244 // may not contain an overflow section header.
1245 if (!is64Bit() && (RelCount
>= static_cast<uint32_t>(XCOFF::RelocOverflow
))) {
1246 // Generate an overflow section header.
1247 SectionEntry
SecEntry(".ovrflo", XCOFF::STYP_OVRFLO
);
1249 // This field specifies the file section number of the section header that
1251 SecEntry
.RelocationCount
= Sec
->Index
;
1253 // This field specifies the number of relocation entries actually
1255 SecEntry
.Address
= RelCount
;
1256 SecEntry
.Index
= ++SectionCount
;
1257 OverflowSections
.push_back(std::move(SecEntry
));
1259 // The field in the primary section header is always 65535
1260 // (XCOFF::RelocOverflow).
1261 Sec
->RelocationCount
= XCOFF::RelocOverflow
;
1263 Sec
->RelocationCount
= RelCount
;
1267 void XCOFFObjectWriter::calcOffsetToRelocations(SectionEntry
*Sec
,
1268 uint64_t &RawPointer
) {
1269 if (!Sec
->RelocationCount
)
1272 Sec
->FileOffsetToRelocations
= RawPointer
;
1273 uint64_t RelocationSizeInSec
= 0;
1275 Sec
->RelocationCount
== static_cast<uint32_t>(XCOFF::RelocOverflow
)) {
1276 // Find its corresponding overflow section.
1277 for (auto &OverflowSec
: OverflowSections
) {
1278 if (OverflowSec
.RelocationCount
== static_cast<uint32_t>(Sec
->Index
)) {
1279 RelocationSizeInSec
=
1280 OverflowSec
.Address
* XCOFF::RelocationSerializationSize32
;
1282 // This field must have the same values as in the corresponding
1283 // primary section header.
1284 OverflowSec
.FileOffsetToRelocations
= Sec
->FileOffsetToRelocations
;
1287 assert(RelocationSizeInSec
&& "Overflow section header doesn't exist.");
1289 RelocationSizeInSec
= Sec
->RelocationCount
*
1290 (is64Bit() ? XCOFF::RelocationSerializationSize64
1291 : XCOFF::RelocationSerializationSize32
);
1294 RawPointer
+= RelocationSizeInSec
;
1295 if (RawPointer
> MaxRawDataSize
)
1296 report_fatal_error("Relocation data overflowed this object file.");
1299 void XCOFFObjectWriter::finalizeSectionInfo() {
1300 for (auto *Section
: Sections
) {
1301 if (Section
->Index
== SectionEntry::UninitializedIndex
)
1302 // Nothing to record for this Section.
1305 uint64_t RelCount
= 0;
1306 for (const auto *Group
: Section
->Groups
) {
1310 for (auto &Csect
: *Group
)
1311 RelCount
+= Csect
.Relocations
.size();
1313 finalizeRelocationInfo(Section
, RelCount
);
1316 for (auto &DwarfSection
: DwarfSections
)
1317 finalizeRelocationInfo(&DwarfSection
,
1318 DwarfSection
.DwarfSect
->Relocations
.size());
1320 // Calculate the RawPointer value for all headers.
1321 uint64_t RawPointer
=
1322 (is64Bit() ? (XCOFF::FileHeaderSize64
+
1323 SectionCount
* XCOFF::SectionHeaderSize64
)
1324 : (XCOFF::FileHeaderSize32
+
1325 SectionCount
* XCOFF::SectionHeaderSize32
)) +
1326 auxiliaryHeaderSize();
1328 // Calculate the file offset to the section data.
1329 for (auto *Sec
: Sections
) {
1330 if (Sec
->Index
== SectionEntry::UninitializedIndex
|| Sec
->IsVirtual
)
1333 RawPointer
= Sec
->advanceFileOffset(MaxRawDataSize
, RawPointer
);
1336 if (!DwarfSections
.empty()) {
1337 RawPointer
+= PaddingsBeforeDwarf
;
1338 for (auto &DwarfSection
: DwarfSections
) {
1339 RawPointer
= DwarfSection
.advanceFileOffset(MaxRawDataSize
, RawPointer
);
1343 if (hasExceptionSection())
1344 RawPointer
= ExceptionSection
.advanceFileOffset(MaxRawDataSize
, RawPointer
);
1346 if (CInfoSymSection
.Entry
)
1347 RawPointer
= CInfoSymSection
.advanceFileOffset(MaxRawDataSize
, RawPointer
);
1349 for (auto *Sec
: Sections
) {
1350 if (Sec
->Index
!= SectionEntry::UninitializedIndex
)
1351 calcOffsetToRelocations(Sec
, RawPointer
);
1354 for (auto &DwarfSec
: DwarfSections
)
1355 calcOffsetToRelocations(&DwarfSec
, RawPointer
);
1357 // TODO Error check that the number of symbol table entries fits in 32-bits
1359 if (SymbolTableEntryCount
)
1360 SymbolTableOffset
= RawPointer
;
1363 void XCOFFObjectWriter::addExceptionEntry(
1364 const MCSymbol
*Symbol
, const MCSymbol
*Trap
, unsigned LanguageCode
,
1365 unsigned ReasonCode
, unsigned FunctionSize
, bool hasDebug
) {
1366 // If a module had debug info, debugging is enabled and XCOFF emits the
1367 // exception auxilliary entry.
1369 ExceptionSection
.isDebugEnabled
= true;
1370 auto Entry
= ExceptionSection
.ExceptionTable
.find(Symbol
->getName());
1371 if (Entry
!= ExceptionSection
.ExceptionTable
.end()) {
1372 Entry
->second
.Entries
.push_back(
1373 ExceptionTableEntry(Trap
, LanguageCode
, ReasonCode
));
1376 ExceptionInfo NewEntry
;
1377 NewEntry
.FunctionSymbol
= Symbol
;
1378 NewEntry
.FunctionSize
= FunctionSize
;
1379 NewEntry
.Entries
.push_back(
1380 ExceptionTableEntry(Trap
, LanguageCode
, ReasonCode
));
1381 ExceptionSection
.ExceptionTable
.insert(
1382 std::pair
<const StringRef
, ExceptionInfo
>(Symbol
->getName(), NewEntry
));
1385 unsigned XCOFFObjectWriter::getExceptionSectionSize() {
1386 unsigned EntryNum
= 0;
1388 for (const auto &TableEntry
: ExceptionSection
.ExceptionTable
)
1389 // The size() gets +1 to account for the initial entry containing the
1390 // symbol table index.
1391 EntryNum
+= TableEntry
.second
.Entries
.size() + 1;
1393 return EntryNum
* (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
1394 : XCOFF::ExceptionSectionEntrySize32
);
1397 unsigned XCOFFObjectWriter::getExceptionOffset(const MCSymbol
*Symbol
) {
1398 unsigned EntryNum
= 0;
1399 for (const auto &TableEntry
: ExceptionSection
.ExceptionTable
) {
1400 if (Symbol
== TableEntry
.second
.FunctionSymbol
)
1402 EntryNum
+= TableEntry
.second
.Entries
.size() + 1;
1404 return EntryNum
* (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
1405 : XCOFF::ExceptionSectionEntrySize32
);
1408 void XCOFFObjectWriter::addCInfoSymEntry(StringRef Name
, StringRef Metadata
) {
1409 assert(!CInfoSymSection
.Entry
&& "Multiple entries are not supported");
1410 CInfoSymSection
.addEntry(
1411 std::make_unique
<CInfoSymInfo
>(Name
.str(), Metadata
.str()));
1414 void XCOFFObjectWriter::assignAddressesAndIndices(MCAssembler
&Asm
) {
1415 // The symbol table starts with all the C_FILE symbols. Each C_FILE symbol
1416 // requires 1 or 2 auxiliary entries.
1417 uint32_t SymbolTableIndex
=
1418 (2 + (CompilerVersion
.empty() ? 0 : 1)) * FileNames
.size();
1420 if (CInfoSymSection
.Entry
)
1423 // Calculate indices for undefined symbols.
1424 for (auto &Csect
: UndefinedCsects
) {
1427 Csect
.SymbolTableIndex
= SymbolTableIndex
;
1428 SymbolIndexMap
[Csect
.MCSec
->getQualNameSymbol()] = Csect
.SymbolTableIndex
;
1429 // 1 main and 1 auxiliary symbol table entry for each contained symbol.
1430 SymbolTableIndex
+= 2;
1433 // The address corrresponds to the address of sections and symbols in the
1434 // object file. We place the shared address 0 immediately after the
1435 // section header table.
1436 uint64_t Address
= 0;
1437 // Section indices are 1-based in XCOFF.
1438 int32_t SectionIndex
= 1;
1439 bool HasTDataSection
= false;
1441 for (auto *Section
: Sections
) {
1442 const bool IsEmpty
=
1443 llvm::all_of(Section
->Groups
,
1444 [](const CsectGroup
*Group
) { return Group
->empty(); });
1448 if (SectionIndex
> MaxSectionIndex
)
1449 report_fatal_error("Section index overflow!");
1450 Section
->Index
= SectionIndex
++;
1453 bool SectionAddressSet
= false;
1454 // Reset the starting address to 0 for TData section.
1455 if (Section
->Flags
== XCOFF::STYP_TDATA
) {
1457 HasTDataSection
= true;
1459 // Reset the starting address to 0 for TBSS section if the object file does
1460 // not contain TData Section.
1461 if ((Section
->Flags
== XCOFF::STYP_TBSS
) && !HasTDataSection
)
1464 for (auto *Group
: Section
->Groups
) {
1468 for (auto &Csect
: *Group
) {
1469 const MCSectionXCOFF
*MCSec
= Csect
.MCSec
;
1470 Csect
.Address
= alignTo(Address
, MCSec
->getAlign());
1471 Csect
.Size
= Asm
.getSectionAddressSize(*MCSec
);
1472 Address
= Csect
.Address
+ Csect
.Size
;
1473 Csect
.SymbolTableIndex
= SymbolTableIndex
;
1474 SymbolIndexMap
[MCSec
->getQualNameSymbol()] = Csect
.SymbolTableIndex
;
1475 // 1 main and 1 auxiliary symbol table entry for the csect.
1476 SymbolTableIndex
+= 2;
1478 for (auto &Sym
: Csect
.Syms
) {
1479 bool hasExceptEntry
= false;
1481 ExceptionSection
.ExceptionTable
.find(Sym
.MCSym
->getName());
1482 if (Entry
!= ExceptionSection
.ExceptionTable
.end()) {
1483 hasExceptEntry
= true;
1484 for (auto &TrapEntry
: Entry
->second
.Entries
) {
1485 TrapEntry
.TrapAddress
= Asm
.getSymbolOffset(*(Sym
.MCSym
)) +
1486 TrapEntry
.Trap
->getOffset();
1489 Sym
.SymbolTableIndex
= SymbolTableIndex
;
1490 SymbolIndexMap
[Sym
.MCSym
] = Sym
.SymbolTableIndex
;
1491 // 1 main and 1 auxiliary symbol table entry for each contained
1492 // symbol. For symbols with exception section entries, a function
1493 // auxilliary entry is needed, and on 64-bit XCOFF with debugging
1494 // enabled, an additional exception auxilliary entry is needed.
1495 SymbolTableIndex
+= 2;
1496 if (hasExceptionSection() && hasExceptEntry
) {
1497 if (is64Bit() && ExceptionSection
.isDebugEnabled
)
1498 SymbolTableIndex
+= 2;
1500 SymbolTableIndex
+= 1;
1505 if (!SectionAddressSet
) {
1506 Section
->Address
= Group
->front().Address
;
1507 SectionAddressSet
= true;
1511 // Make sure the address of the next section aligned to
1512 // DefaultSectionAlign.
1513 Address
= alignTo(Address
, DefaultSectionAlign
);
1514 Section
->Size
= Address
- Section
->Address
;
1517 // Start to generate DWARF sections. Sections other than DWARF section use
1518 // DefaultSectionAlign as the default alignment, while DWARF sections have
1519 // their own alignments. If these two alignments are not the same, we need
1520 // some paddings here and record the paddings bytes for FileOffsetToData
1522 if (!DwarfSections
.empty())
1523 PaddingsBeforeDwarf
=
1525 (*DwarfSections
.begin()).DwarfSect
->MCSec
->getAlign()) -
1528 DwarfSectionEntry
*LastDwarfSection
= nullptr;
1529 for (auto &DwarfSection
: DwarfSections
) {
1530 assert((SectionIndex
<= MaxSectionIndex
) && "Section index overflow!");
1532 XCOFFSection
&DwarfSect
= *DwarfSection
.DwarfSect
;
1533 const MCSectionXCOFF
*MCSec
= DwarfSect
.MCSec
;
1536 DwarfSection
.Index
= SectionIndex
++;
1540 DwarfSect
.SymbolTableIndex
= SymbolTableIndex
;
1541 SymbolIndexMap
[MCSec
->getQualNameSymbol()] = DwarfSect
.SymbolTableIndex
;
1542 // 1 main and 1 auxiliary symbol table entry for the csect.
1543 SymbolTableIndex
+= 2;
1545 // Section address. Make it align to section alignment.
1546 // We use address 0 for DWARF sections' Physical and Virtual Addresses.
1547 // This address is used to tell where is the section in the final object.
1548 // See writeSectionForDwarfSectionEntry().
1549 DwarfSection
.Address
= DwarfSect
.Address
=
1550 alignTo(Address
, MCSec
->getAlign());
1553 // For DWARF section, we must use the real size which may be not aligned.
1554 DwarfSection
.Size
= DwarfSect
.Size
= Asm
.getSectionAddressSize(*MCSec
);
1556 Address
= DwarfSection
.Address
+ DwarfSection
.Size
;
1558 if (LastDwarfSection
)
1559 LastDwarfSection
->MemorySize
=
1560 DwarfSection
.Address
- LastDwarfSection
->Address
;
1561 LastDwarfSection
= &DwarfSection
;
1563 if (LastDwarfSection
) {
1564 // Make the final DWARF section address align to the default section
1565 // alignment for follow contents.
1566 Address
= alignTo(LastDwarfSection
->Address
+ LastDwarfSection
->Size
,
1567 DefaultSectionAlign
);
1568 LastDwarfSection
->MemorySize
= Address
- LastDwarfSection
->Address
;
1570 if (hasExceptionSection()) {
1571 ExceptionSection
.Index
= SectionIndex
++;
1573 ExceptionSection
.Address
= 0;
1574 ExceptionSection
.Size
= getExceptionSectionSize();
1575 Address
+= ExceptionSection
.Size
;
1576 Address
= alignTo(Address
, DefaultSectionAlign
);
1579 if (CInfoSymSection
.Entry
) {
1580 CInfoSymSection
.Index
= SectionIndex
++;
1582 CInfoSymSection
.Address
= 0;
1583 Address
+= CInfoSymSection
.Size
;
1584 Address
= alignTo(Address
, DefaultSectionAlign
);
1587 SymbolTableEntryCount
= SymbolTableIndex
;
1590 void XCOFFObjectWriter::writeSectionForControlSectionEntry(
1591 const MCAssembler
&Asm
, const CsectSectionEntry
&CsectEntry
,
1592 uint64_t &CurrentAddressLocation
) {
1593 // Nothing to write for this Section.
1594 if (CsectEntry
.Index
== SectionEntry::UninitializedIndex
)
1597 // There could be a gap (without corresponding zero padding) between
1599 // There could be a gap (without corresponding zero padding) between
1601 assert(((CurrentAddressLocation
<= CsectEntry
.Address
) ||
1602 (CsectEntry
.Flags
== XCOFF::STYP_TDATA
) ||
1603 (CsectEntry
.Flags
== XCOFF::STYP_TBSS
)) &&
1604 "CurrentAddressLocation should be less than or equal to section "
1605 "address if the section is not TData or TBSS.");
1607 CurrentAddressLocation
= CsectEntry
.Address
;
1609 // For virtual sections, nothing to write. But need to increase
1610 // CurrentAddressLocation for later sections like DWARF section has a correct
1611 // writing location.
1612 if (CsectEntry
.IsVirtual
) {
1613 CurrentAddressLocation
+= CsectEntry
.Size
;
1617 for (const auto &Group
: CsectEntry
.Groups
) {
1618 for (const auto &Csect
: *Group
) {
1619 if (uint32_t PaddingSize
= Csect
.Address
- CurrentAddressLocation
)
1620 W
.OS
.write_zeros(PaddingSize
);
1622 Asm
.writeSectionData(W
.OS
, Csect
.MCSec
);
1623 CurrentAddressLocation
= Csect
.Address
+ Csect
.Size
;
1627 // The size of the tail padding in a section is the end virtual address of
1628 // the current section minus the end virtual address of the last csect
1630 if (uint64_t PaddingSize
=
1631 CsectEntry
.Address
+ CsectEntry
.Size
- CurrentAddressLocation
) {
1632 W
.OS
.write_zeros(PaddingSize
);
1633 CurrentAddressLocation
+= PaddingSize
;
1637 void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
1638 const MCAssembler
&Asm
, const DwarfSectionEntry
&DwarfEntry
,
1639 uint64_t &CurrentAddressLocation
) {
1640 // There could be a gap (without corresponding zero padding) between
1641 // sections. For example DWARF section alignment is bigger than
1642 // DefaultSectionAlign.
1643 assert(CurrentAddressLocation
<= DwarfEntry
.Address
&&
1644 "CurrentAddressLocation should be less than or equal to section "
1647 if (uint64_t PaddingSize
= DwarfEntry
.Address
- CurrentAddressLocation
)
1648 W
.OS
.write_zeros(PaddingSize
);
1650 if (DwarfEntry
.Size
)
1651 Asm
.writeSectionData(W
.OS
, DwarfEntry
.DwarfSect
->MCSec
);
1653 CurrentAddressLocation
= DwarfEntry
.Address
+ DwarfEntry
.Size
;
1655 // DWARF section size is not aligned to DefaultSectionAlign.
1656 // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign.
1657 uint32_t Mod
= CurrentAddressLocation
% DefaultSectionAlign
;
1658 uint32_t TailPaddingSize
= Mod
? DefaultSectionAlign
- Mod
: 0;
1659 if (TailPaddingSize
)
1660 W
.OS
.write_zeros(TailPaddingSize
);
1662 CurrentAddressLocation
+= TailPaddingSize
;
1665 void XCOFFObjectWriter::writeSectionForExceptionSectionEntry(
1666 const MCAssembler
&Asm
, ExceptionSectionEntry
&ExceptionEntry
,
1667 uint64_t &CurrentAddressLocation
) {
1668 for (const auto &TableEntry
: ExceptionEntry
.ExceptionTable
) {
1669 // For every symbol that has exception entries, you must start the entries
1670 // with an initial symbol table index entry
1671 W
.write
<uint32_t>(SymbolIndexMap
[TableEntry
.second
.FunctionSymbol
]);
1673 // 4-byte padding on 64-bit.
1674 W
.OS
.write_zeros(4);
1676 W
.OS
.write_zeros(2);
1677 for (auto &TrapEntry
: TableEntry
.second
.Entries
) {
1678 writeWord(TrapEntry
.TrapAddress
);
1679 W
.write
<uint8_t>(TrapEntry
.Lang
);
1680 W
.write
<uint8_t>(TrapEntry
.Reason
);
1684 CurrentAddressLocation
+= getExceptionSectionSize();
1687 void XCOFFObjectWriter::writeSectionForCInfoSymSectionEntry(
1688 const MCAssembler
&Asm
, CInfoSymSectionEntry
&CInfoSymEntry
,
1689 uint64_t &CurrentAddressLocation
) {
1690 if (!CInfoSymSection
.Entry
)
1693 constexpr int WordSize
= sizeof(uint32_t);
1694 std::unique_ptr
<CInfoSymInfo
> &CISI
= CInfoSymEntry
.Entry
;
1695 const std::string
&Metadata
= CISI
->Metadata
;
1697 // Emit the 4-byte length of the metadata.
1698 W
.write
<uint32_t>(Metadata
.size());
1700 if (Metadata
.size() == 0)
1703 // Write out the payload one word at a time.
1705 while (Index
+ WordSize
<= Metadata
.size()) {
1707 llvm::support::endian::read32be(Metadata
.data() + Index
);
1708 W
.write
<uint32_t>(NextWord
);
1712 // If there is padding, we have at least one byte of payload left to emit.
1713 if (CISI
->paddingSize()) {
1714 std::array
<uint8_t, WordSize
> LastWord
= {0};
1715 ::memcpy(LastWord
.data(), Metadata
.data() + Index
, Metadata
.size() - Index
);
1716 W
.write
<uint32_t>(llvm::support::endian::read32be(LastWord
.data()));
1719 CurrentAddressLocation
+= CISI
->size();
1722 // Takes the log base 2 of the alignment and shifts the result into the 5 most
1723 // significant bits of a byte, then or's in the csect type into the least
1724 // significant 3 bits.
1725 uint8_t getEncodedType(const MCSectionXCOFF
*Sec
) {
1726 unsigned Log2Align
= Log2(Sec
->getAlign());
1727 // Result is a number in the range [0, 31] which fits in the 5 least
1728 // significant bits. Shift this value into the 5 most significant bits, and
1729 // bitwise-or in the csect type.
1730 uint8_t EncodedAlign
= Log2Align
<< 3;
1731 return EncodedAlign
| Sec
->getCSectType();
1734 } // end anonymous namespace
1736 std::unique_ptr
<MCObjectWriter
>
1737 llvm::createXCOFFObjectWriter(std::unique_ptr
<MCXCOFFObjectTargetWriter
> MOTW
,
1738 raw_pwrite_stream
&OS
) {
1739 return std::make_unique
<XCOFFObjectWriter
>(std::move(MOTW
), OS
);
1742 // TODO: Export XCOFFObjectWriter to llvm/MC/MCXCOFFObjectWriter.h and remove
1744 void XCOFF::addExceptionEntry(MCObjectWriter
&Writer
, const MCSymbol
*Symbol
,
1745 const MCSymbol
*Trap
, unsigned LanguageCode
,
1746 unsigned ReasonCode
, unsigned FunctionSize
,
1748 static_cast<XCOFFObjectWriter
&>(Writer
).addExceptionEntry(
1749 Symbol
, Trap
, LanguageCode
, ReasonCode
, FunctionSize
, hasDebug
);
1752 void XCOFF::addCInfoSymEntry(MCObjectWriter
&Writer
, StringRef Name
,
1753 StringRef Metadata
) {
1754 static_cast<XCOFFObjectWriter
&>(Writer
).addCInfoSymEntry(Name
, Metadata
);