1 //===-- lib/MC/XCOFFObjectWriter.cpp - XCOFF file writer ------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
9 // This file implements XCOFF object file writer information.
11 //===----------------------------------------------------------------------===//
13 #include "llvm/BinaryFormat/XCOFF.h"
14 #include "llvm/MC/MCAsmBackend.h"
15 #include "llvm/MC/MCAsmLayout.h"
16 #include "llvm/MC/MCAssembler.h"
17 #include "llvm/MC/MCFixup.h"
18 #include "llvm/MC/MCFixupKindInfo.h"
19 #include "llvm/MC/MCObjectWriter.h"
20 #include "llvm/MC/MCSectionXCOFF.h"
21 #include "llvm/MC/MCSymbolXCOFF.h"
22 #include "llvm/MC/MCValue.h"
23 #include "llvm/MC/MCXCOFFObjectWriter.h"
24 #include "llvm/MC/StringTableBuilder.h"
25 #include "llvm/Support/Casting.h"
26 #include "llvm/Support/EndianStream.h"
27 #include "llvm/Support/ErrorHandling.h"
28 #include "llvm/Support/MathExtras.h"
35 // An XCOFF object file has a limited set of predefined sections. The most
36 // important ones for us (right now) are:
37 // .text --> contains program code and read-only data.
38 // .data --> contains initialized data, function descriptors, and the TOC.
39 // .bss --> contains uninitialized data.
40 // Each of these sections is composed of 'Control Sections'. A Control Section
41 // is more commonly referred to as a csect. A csect is an indivisible unit of
42 // code or data, and acts as a container for symbols. A csect is mapped
43 // into a section based on its storage-mapping class, with the exception of
44 // XMC_RW which gets mapped to either .data or .bss based on whether it's
45 // explicitly initialized or not.
47 // We don't represent the sections in the MC layer as there is nothing
48 // interesting about them at at that level: they carry information that is
49 // only relevant to the ObjectWriter, so we materialize them in this class.
52 constexpr unsigned DefaultSectionAlign
= 4;
53 constexpr int16_t MaxSectionIndex
= INT16_MAX
;
55 // Packs the csect's alignment and type into a byte.
56 uint8_t getEncodedType(const MCSectionXCOFF
*);
58 struct XCOFFRelocation
{
59 uint32_t SymbolTableIndex
;
60 uint32_t FixupOffsetInCsect
;
65 // Wrapper around an MCSymbolXCOFF.
67 const MCSymbolXCOFF
*const MCSym
;
68 uint32_t SymbolTableIndex
;
70 XCOFF::VisibilityType
getVisibilityType() const {
71 return MCSym
->getVisibilityType();
74 XCOFF::StorageClass
getStorageClass() const {
75 return MCSym
->getStorageClass();
77 StringRef
getSymbolTableName() const { return MCSym
->getSymbolTableName(); }
78 Symbol(const MCSymbolXCOFF
*MCSym
) : MCSym(MCSym
), SymbolTableIndex(-1) {}
81 // Wrapper for an MCSectionXCOFF.
82 // It can be a Csect or debug section or DWARF section and so on.
84 const MCSectionXCOFF
*const MCSec
;
85 uint32_t SymbolTableIndex
;
89 SmallVector
<Symbol
, 1> Syms
;
90 SmallVector
<XCOFFRelocation
, 1> Relocations
;
91 StringRef
getSymbolTableName() const { return MCSec
->getSymbolTableName(); }
92 XCOFF::VisibilityType
getVisibilityType() const {
93 return MCSec
->getVisibilityType();
95 XCOFFSection(const MCSectionXCOFF
*MCSec
)
96 : MCSec(MCSec
), SymbolTableIndex(-1), Address(-1), Size(0) {}
99 // Type to be used for a container representing a set of csects with
100 // (approximately) the same storage mapping class. For example all the csects
101 // with a storage mapping class of `xmc_pr` will get placed into the same
103 using CsectGroup
= std::deque
<XCOFFSection
>;
104 using CsectGroups
= std::deque
<CsectGroup
*>;
106 // The basic section entry defination. This Section represents a section entry
107 // in XCOFF section header table.
108 struct SectionEntry
{
109 char Name
[XCOFF::NameSize
];
110 // The physical/virtual address of the section. For an object file these
111 // values are equivalent, except for in the overflow section header, where
112 // the physical address specifies the number of relocation entries and the
113 // virtual address specifies the number of line number entries.
114 // TODO: Divide Address into PhysicalAddress and VirtualAddress when line
115 // number entries are supported.
118 uint64_t FileOffsetToData
;
119 uint64_t FileOffsetToRelocations
;
120 uint32_t RelocationCount
;
125 // XCOFF has special section numbers for symbols:
126 // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
127 // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
129 // 0 Specifies N_UNDEF, an undefined external symbol.
130 // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
131 // hasn't been initialized.
132 static constexpr int16_t UninitializedIndex
=
133 XCOFF::ReservedSectionNum::N_DEBUG
- 1;
135 SectionEntry(StringRef N
, int32_t Flags
)
136 : Name(), Address(0), Size(0), FileOffsetToData(0),
137 FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags
),
138 Index(UninitializedIndex
) {
139 assert(N
.size() <= XCOFF::NameSize
&& "section name too long");
140 memcpy(Name
, N
.data(), N
.size());
143 virtual void reset() {
146 FileOffsetToData
= 0;
147 FileOffsetToRelocations
= 0;
149 Index
= UninitializedIndex
;
152 virtual ~SectionEntry() = default;
155 // Represents the data related to a section excluding the csects that make up
156 // the raw data of the section. The csects are stored separately as not all
157 // sections contain csects, and some sections contain csects which are better
158 // stored separately, e.g. the .data section containing read-write, descriptor,
159 // TOCBase and TOC-entry csects.
160 struct CsectSectionEntry
: public SectionEntry
{
161 // Virtual sections do not need storage allocated in the object file.
162 const bool IsVirtual
;
164 // This is a section containing csect groups.
167 CsectSectionEntry(StringRef N
, XCOFF::SectionTypeFlags Flags
, bool IsVirtual
,
169 : SectionEntry(N
, Flags
), IsVirtual(IsVirtual
), Groups(Groups
) {
170 assert(N
.size() <= XCOFF::NameSize
&& "section name too long");
171 memcpy(Name
, N
.data(), N
.size());
174 void reset() override
{
175 SectionEntry::reset();
176 // Clear any csects we have stored.
177 for (auto *Group
: Groups
)
181 virtual ~CsectSectionEntry() = default;
184 struct DwarfSectionEntry
: public SectionEntry
{
185 // For DWARF section entry.
186 std::unique_ptr
<XCOFFSection
> DwarfSect
;
188 // For DWARF section, we must use real size in the section header. MemorySize
189 // is for the size the DWARF section occupies including paddings.
192 DwarfSectionEntry(StringRef N
, int32_t Flags
,
193 std::unique_ptr
<XCOFFSection
> Sect
)
194 : SectionEntry(N
, Flags
| XCOFF::STYP_DWARF
), DwarfSect(std::move(Sect
)),
196 assert(DwarfSect
->MCSec
->isDwarfSect() &&
197 "This should be a DWARF section!");
198 assert(N
.size() <= XCOFF::NameSize
&& "section name too long");
199 memcpy(Name
, N
.data(), N
.size());
202 DwarfSectionEntry(DwarfSectionEntry
&&s
) = default;
204 virtual ~DwarfSectionEntry() = default;
207 struct ExceptionTableEntry
{
208 const MCSymbol
*Trap
;
209 uint64_t TrapAddress
= ~0ul;
213 ExceptionTableEntry(const MCSymbol
*Trap
, unsigned Lang
, unsigned Reason
)
214 : Trap(Trap
), Lang(Lang
), Reason(Reason
) {}
217 struct ExceptionInfo
{
218 const MCSymbol
*FunctionSymbol
;
219 unsigned FunctionSize
;
220 std::vector
<ExceptionTableEntry
> Entries
;
223 struct ExceptionSectionEntry
: public SectionEntry
{
224 std::map
<const StringRef
, ExceptionInfo
> ExceptionTable
;
225 bool isDebugEnabled
= false;
227 ExceptionSectionEntry(StringRef N
, int32_t Flags
)
228 : SectionEntry(N
, Flags
| XCOFF::STYP_EXCEPT
) {
229 assert(N
.size() <= XCOFF::NameSize
&& "Section too long.");
230 memcpy(Name
, N
.data(), N
.size());
233 virtual ~ExceptionSectionEntry() = default;
236 class XCOFFObjectWriter
: public MCObjectWriter
{
238 uint32_t SymbolTableEntryCount
= 0;
239 uint64_t SymbolTableOffset
= 0;
240 uint16_t SectionCount
= 0;
241 uint32_t PaddingsBeforeDwarf
= 0;
242 std::vector
<std::pair
<std::string
, size_t>> FileNames
;
243 bool HasVisibility
= false;
245 support::endian::Writer W
;
246 std::unique_ptr
<MCXCOFFObjectTargetWriter
> TargetObjectWriter
;
247 StringTableBuilder Strings
;
249 const uint64_t MaxRawDataSize
=
250 TargetObjectWriter
->is64Bit() ? UINT64_MAX
: UINT32_MAX
;
252 // Maps the MCSection representation to its corresponding XCOFFSection
253 // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into
254 // from its containing MCSectionXCOFF.
255 DenseMap
<const MCSectionXCOFF
*, XCOFFSection
*> SectionMap
;
257 // Maps the MCSymbol representation to its corrresponding symbol table index.
258 // Needed for relocation.
259 DenseMap
<const MCSymbol
*, uint32_t> SymbolIndexMap
;
261 // CsectGroups. These store the csects which make up different parts of
262 // the sections. Should have one for each set of csects that get mapped into
263 // the same section and get handled in a 'similar' way.
264 CsectGroup UndefinedCsects
;
265 CsectGroup ProgramCodeCsects
;
266 CsectGroup ReadOnlyCsects
;
267 CsectGroup DataCsects
;
268 CsectGroup FuncDSCsects
;
269 CsectGroup TOCCsects
;
270 CsectGroup BSSCsects
;
271 CsectGroup TDataCsects
;
272 CsectGroup TBSSCsects
;
274 // The Predefined sections.
275 CsectSectionEntry Text
;
276 CsectSectionEntry Data
;
277 CsectSectionEntry BSS
;
278 CsectSectionEntry TData
;
279 CsectSectionEntry TBSS
;
281 // All the XCOFF sections, in the order they will appear in the section header
283 std::array
<CsectSectionEntry
*const, 5> Sections
{
284 {&Text
, &Data
, &BSS
, &TData
, &TBSS
}};
286 std::vector
<DwarfSectionEntry
> DwarfSections
;
287 std::vector
<SectionEntry
> OverflowSections
;
289 ExceptionSectionEntry ExceptionSection
;
291 CsectGroup
&getCsectGroup(const MCSectionXCOFF
*MCSec
);
293 void reset() override
;
295 void executePostLayoutBinding(MCAssembler
&, const MCAsmLayout
&) override
;
297 void recordRelocation(MCAssembler
&, const MCAsmLayout
&, const MCFragment
*,
298 const MCFixup
&, MCValue
, uint64_t &) override
;
300 uint64_t writeObject(MCAssembler
&, const MCAsmLayout
&) override
;
302 bool is64Bit() const { return TargetObjectWriter
->is64Bit(); }
303 bool nameShouldBeInStringTable(const StringRef
&);
304 void writeSymbolName(const StringRef
&);
306 void writeSymbolEntryForCsectMemberLabel(const Symbol
&SymbolRef
,
307 const XCOFFSection
&CSectionRef
,
308 int16_t SectionIndex
,
309 uint64_t SymbolOffset
);
310 void writeSymbolEntryForControlSection(const XCOFFSection
&CSectionRef
,
311 int16_t SectionIndex
,
312 XCOFF::StorageClass StorageClass
);
313 void writeSymbolEntryForDwarfSection(const XCOFFSection
&DwarfSectionRef
,
314 int16_t SectionIndex
);
315 void writeFileHeader();
316 void writeAuxFileHeader();
317 void writeSectionHeader(const SectionEntry
*Sec
);
318 void writeSectionHeaderTable();
319 void writeSections(const MCAssembler
&Asm
, const MCAsmLayout
&Layout
);
320 void writeSectionForControlSectionEntry(const MCAssembler
&Asm
,
321 const MCAsmLayout
&Layout
,
322 const CsectSectionEntry
&CsectEntry
,
323 uint64_t &CurrentAddressLocation
);
324 void writeSectionForDwarfSectionEntry(const MCAssembler
&Asm
,
325 const MCAsmLayout
&Layout
,
326 const DwarfSectionEntry
&DwarfEntry
,
327 uint64_t &CurrentAddressLocation
);
328 void writeSectionForExceptionSectionEntry(
329 const MCAssembler
&Asm
, const MCAsmLayout
&Layout
,
330 ExceptionSectionEntry
&ExceptionEntry
, uint64_t &CurrentAddressLocation
);
331 void writeSymbolTable(const MCAsmLayout
&Layout
);
332 void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion
,
333 uint64_t NumberOfRelocEnt
= 0);
334 void writeSymbolAuxCsectEntry(uint64_t SectionOrLength
,
335 uint8_t SymbolAlignmentAndType
,
336 uint8_t StorageMappingClass
);
337 void writeSymbolAuxFunctionEntry(uint32_t EntryOffset
, uint32_t FunctionSize
,
338 uint64_t LineNumberPointer
,
340 void writeSymbolAuxExceptionEntry(uint64_t EntryOffset
, uint32_t FunctionSize
,
342 void writeSymbolEntry(StringRef SymbolName
, uint64_t Value
,
343 int16_t SectionNumber
, uint16_t SymbolType
,
344 uint8_t StorageClass
, uint8_t NumberOfAuxEntries
= 1);
345 void writeRelocations();
346 void writeRelocation(XCOFFRelocation Reloc
, const XCOFFSection
&Section
);
348 // Called after all the csects and symbols have been processed by
349 // `executePostLayoutBinding`, this function handles building up the majority
350 // of the structures in the object file representation. Namely:
351 // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
353 // *) Assigns symbol table indices.
354 // *) Builds up the section header table by adding any non-empty sections to
356 void assignAddressesAndIndices(const MCAsmLayout
&);
357 // Called after relocations are recorded.
358 void finalizeSectionInfo();
359 void finalizeRelocationInfo(SectionEntry
*Sec
, uint64_t RelCount
);
360 void calcOffsetToRelocations(SectionEntry
*Sec
, uint64_t &RawPointer
);
362 void addExceptionEntry(const MCSymbol
*Symbol
, const MCSymbol
*Trap
,
363 unsigned LanguageCode
, unsigned ReasonCode
,
364 unsigned FunctionSize
, bool hasDebug
) override
;
365 bool hasExceptionSection() {
366 return !ExceptionSection
.ExceptionTable
.empty();
368 unsigned getExceptionSectionSize();
369 unsigned getExceptionOffset(const MCSymbol
*Symbol
);
371 size_t auxiliaryHeaderSize() const {
372 // 64-bit object files have no auxiliary header.
373 return HasVisibility
&& !is64Bit() ? XCOFF::AuxFileHeaderSizeShort
: 0;
377 XCOFFObjectWriter(std::unique_ptr
<MCXCOFFObjectTargetWriter
> MOTW
,
378 raw_pwrite_stream
&OS
);
380 void writeWord(uint64_t Word
) {
381 is64Bit() ? W
.write
<uint64_t>(Word
) : W
.write
<uint32_t>(Word
);
385 XCOFFObjectWriter::XCOFFObjectWriter(
386 std::unique_ptr
<MCXCOFFObjectTargetWriter
> MOTW
, raw_pwrite_stream
&OS
)
387 : W(OS
, support::big
), TargetObjectWriter(std::move(MOTW
)),
388 Strings(StringTableBuilder::XCOFF
),
389 Text(".text", XCOFF::STYP_TEXT
, /* IsVirtual */ false,
390 CsectGroups
{&ProgramCodeCsects
, &ReadOnlyCsects
}),
391 Data(".data", XCOFF::STYP_DATA
, /* IsVirtual */ false,
392 CsectGroups
{&DataCsects
, &FuncDSCsects
, &TOCCsects
}),
393 BSS(".bss", XCOFF::STYP_BSS
, /* IsVirtual */ true,
394 CsectGroups
{&BSSCsects
}),
395 TData(".tdata", XCOFF::STYP_TDATA
, /* IsVirtual */ false,
396 CsectGroups
{&TDataCsects
}),
397 TBSS(".tbss", XCOFF::STYP_TBSS
, /* IsVirtual */ true,
398 CsectGroups
{&TBSSCsects
}),
399 ExceptionSection(".except", XCOFF::STYP_EXCEPT
) {}
401 void XCOFFObjectWriter::reset() {
402 // Clear the mappings we created.
403 SymbolIndexMap
.clear();
406 UndefinedCsects
.clear();
407 // Reset any sections we have written to, and empty the section header table.
408 for (auto *Sec
: Sections
)
410 for (auto &DwarfSec
: DwarfSections
)
412 for (auto &OverflowSec
: OverflowSections
)
414 ExceptionSection
.reset();
416 // Reset states in XCOFFObjectWriter.
417 SymbolTableEntryCount
= 0;
418 SymbolTableOffset
= 0;
420 PaddingsBeforeDwarf
= 0;
423 MCObjectWriter::reset();
426 CsectGroup
&XCOFFObjectWriter::getCsectGroup(const MCSectionXCOFF
*MCSec
) {
427 switch (MCSec
->getMappingClass()) {
429 assert(XCOFF::XTY_SD
== MCSec
->getCSectType() &&
430 "Only an initialized csect can contain program code.");
431 return ProgramCodeCsects
;
433 assert(XCOFF::XTY_SD
== MCSec
->getCSectType() &&
434 "Only an initialized csect can contain read only data.");
435 return ReadOnlyCsects
;
437 if (XCOFF::XTY_CM
== MCSec
->getCSectType())
440 if (XCOFF::XTY_SD
== MCSec
->getCSectType())
443 report_fatal_error("Unhandled mapping of read-write csect to section.");
447 assert(XCOFF::XTY_CM
== MCSec
->getCSectType() &&
448 "Mapping invalid csect. CSECT with bss storage class must be "
452 assert(XCOFF::XTY_SD
== MCSec
->getCSectType() &&
453 "Mapping invalid csect. CSECT with tdata storage class must be "
454 "an initialized csect.");
457 assert(XCOFF::XTY_CM
== MCSec
->getCSectType() &&
458 "Mapping invalid csect. CSECT with tbss storage class must be "
459 "an uninitialized csect.");
462 assert(XCOFF::XTY_SD
== MCSec
->getCSectType() &&
463 "Only an initialized csect can contain TOC-base.");
464 assert(TOCCsects
.empty() &&
465 "We should have only one TOC-base, and it should be the first csect "
466 "in this CsectGroup.");
471 assert(XCOFF::XTY_SD
== MCSec
->getCSectType() &&
472 "Only an initialized csect can contain TC entry.");
473 assert(!TOCCsects
.empty() &&
474 "We should at least have a TOC-base in this CsectGroup.");
477 report_fatal_error("Unhandled mapping of csect to section.");
481 static MCSectionXCOFF
*getContainingCsect(const MCSymbolXCOFF
*XSym
) {
482 if (XSym
->isDefined())
483 return cast
<MCSectionXCOFF
>(XSym
->getFragment()->getParent());
484 return XSym
->getRepresentedCsect();
487 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler
&Asm
,
488 const MCAsmLayout
&Layout
) {
489 for (const auto &S
: Asm
) {
490 const auto *MCSec
= cast
<const MCSectionXCOFF
>(&S
);
491 assert(!SectionMap
.contains(MCSec
) && "Cannot add a section twice.");
493 // If the name does not fit in the storage provided in the symbol table
494 // entry, add it to the string table.
495 if (nameShouldBeInStringTable(MCSec
->getSymbolTableName()))
496 Strings
.add(MCSec
->getSymbolTableName());
497 if (MCSec
->isCsect()) {
498 // A new control section. Its CsectSectionEntry should already be staticly
499 // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of
500 // the CsectSectionEntry.
501 assert(XCOFF::XTY_ER
!= MCSec
->getCSectType() &&
502 "An undefined csect should not get registered.");
503 CsectGroup
&Group
= getCsectGroup(MCSec
);
504 Group
.emplace_back(MCSec
);
505 SectionMap
[MCSec
] = &Group
.back();
506 } else if (MCSec
->isDwarfSect()) {
507 // A new DwarfSectionEntry.
508 std::unique_ptr
<XCOFFSection
> DwarfSec
=
509 std::make_unique
<XCOFFSection
>(MCSec
);
510 SectionMap
[MCSec
] = DwarfSec
.get();
512 DwarfSectionEntry
SecEntry(MCSec
->getName(),
513 *MCSec
->getDwarfSubtypeFlags(),
514 std::move(DwarfSec
));
515 DwarfSections
.push_back(std::move(SecEntry
));
517 llvm_unreachable("unsupport section type!");
520 for (const MCSymbol
&S
: Asm
.symbols()) {
521 // Nothing to do for temporary symbols.
525 const MCSymbolXCOFF
*XSym
= cast
<MCSymbolXCOFF
>(&S
);
526 const MCSectionXCOFF
*ContainingCsect
= getContainingCsect(XSym
);
528 if (XSym
->getVisibilityType() != XCOFF::SYM_V_UNSPECIFIED
)
529 HasVisibility
= true;
531 if (ContainingCsect
->getCSectType() == XCOFF::XTY_ER
) {
532 // Handle undefined symbol.
533 UndefinedCsects
.emplace_back(ContainingCsect
);
534 SectionMap
[ContainingCsect
] = &UndefinedCsects
.back();
535 if (nameShouldBeInStringTable(ContainingCsect
->getSymbolTableName()))
536 Strings
.add(ContainingCsect
->getSymbolTableName());
540 // If the symbol is the csect itself, we don't need to put the symbol
541 // into csect's Syms.
542 if (XSym
== ContainingCsect
->getQualNameSymbol())
545 // Only put a label into the symbol table when it is an external label.
546 if (!XSym
->isExternal())
549 assert(SectionMap
.contains(ContainingCsect
) &&
550 "Expected containing csect to exist in map");
551 XCOFFSection
*Csect
= SectionMap
[ContainingCsect
];
552 // Lookup the containing csect and add the symbol to it.
553 assert(Csect
->MCSec
->isCsect() && "only csect is supported now!");
554 Csect
->Syms
.emplace_back(XSym
);
556 // If the name does not fit in the storage provided in the symbol table
557 // entry, add it to the string table.
558 if (nameShouldBeInStringTable(XSym
->getSymbolTableName()))
559 Strings
.add(XSym
->getSymbolTableName());
562 FileNames
= Asm
.getFileNames();
563 // Emit ".file" as the source file name when there is no file name.
564 if (FileNames
.empty())
565 FileNames
.emplace_back(".file", 0);
566 for (const std::pair
<std::string
, size_t> &F
: FileNames
) {
567 if (nameShouldBeInStringTable(F
.first
))
568 Strings
.add(F
.first
);
572 assignAddressesAndIndices(Layout
);
575 void XCOFFObjectWriter::recordRelocation(MCAssembler
&Asm
,
576 const MCAsmLayout
&Layout
,
577 const MCFragment
*Fragment
,
578 const MCFixup
&Fixup
, MCValue Target
,
579 uint64_t &FixedValue
) {
580 auto getIndex
= [this](const MCSymbol
*Sym
,
581 const MCSectionXCOFF
*ContainingCsect
) {
582 // If we could not find the symbol directly in SymbolIndexMap, this symbol
583 // could either be a temporary symbol or an undefined symbol. In this case,
584 // we would need to have the relocation reference its csect instead.
585 return SymbolIndexMap
.contains(Sym
)
586 ? SymbolIndexMap
[Sym
]
587 : SymbolIndexMap
[ContainingCsect
->getQualNameSymbol()];
590 auto getVirtualAddress
=
591 [this, &Layout
](const MCSymbol
*Sym
,
592 const MCSectionXCOFF
*ContainingSect
) -> uint64_t {
594 if (ContainingSect
->isDwarfSect())
595 return Layout
.getSymbolOffset(*Sym
);
598 if (!Sym
->isDefined())
599 return SectionMap
[ContainingSect
]->Address
;
602 assert(Sym
->isDefined() && "not a valid object that has address!");
603 return SectionMap
[ContainingSect
]->Address
+ Layout
.getSymbolOffset(*Sym
);
606 const MCSymbol
*const SymA
= &Target
.getSymA()->getSymbol();
608 MCAsmBackend
&Backend
= Asm
.getBackend();
609 bool IsPCRel
= Backend
.getFixupKindInfo(Fixup
.getKind()).Flags
&
610 MCFixupKindInfo::FKF_IsPCRel
;
614 std::tie(Type
, SignAndSize
) =
615 TargetObjectWriter
->getRelocTypeAndSignSize(Target
, Fixup
, IsPCRel
);
617 const MCSectionXCOFF
*SymASec
= getContainingCsect(cast
<MCSymbolXCOFF
>(SymA
));
618 assert(SectionMap
.contains(SymASec
) &&
619 "Expected containing csect to exist in map.");
621 const uint32_t Index
= getIndex(SymA
, SymASec
);
622 if (Type
== XCOFF::RelocationType::R_POS
||
623 Type
== XCOFF::RelocationType::R_TLS
)
624 // The FixedValue should be symbol's virtual address in this object file
625 // plus any constant value that we might get.
626 FixedValue
= getVirtualAddress(SymA
, SymASec
) + Target
.getConstant();
627 else if (Type
== XCOFF::RelocationType::R_TLSM
)
628 // The FixedValue should always be zero since the region handle is only
629 // known at load time.
631 else if (Type
== XCOFF::RelocationType::R_TOC
||
632 Type
== XCOFF::RelocationType::R_TOCL
) {
633 // For non toc-data external symbols, R_TOC type relocation will relocate to
634 // data symbols that have XCOFF::XTY_SD type csect. For toc-data external
635 // symbols, R_TOC type relocation will relocate to data symbols that have
636 // XCOFF_ER type csect. For XCOFF_ER kind symbols, there will be no TOC
637 // entry for them, so the FixedValue should always be 0.
638 if (SymASec
->getCSectType() == XCOFF::XTY_ER
) {
641 // The FixedValue should be the TOC entry offset from the TOC-base plus
642 // any constant offset value.
643 const int64_t TOCEntryOffset
= SectionMap
[SymASec
]->Address
-
644 TOCCsects
.front().Address
+
645 Target
.getConstant();
646 if (Type
== XCOFF::RelocationType::R_TOC
&& !isInt
<16>(TOCEntryOffset
))
647 report_fatal_error("TOCEntryOffset overflows in small code model mode");
649 FixedValue
= TOCEntryOffset
;
651 } else if (Type
== XCOFF::RelocationType::R_RBR
) {
652 MCSectionXCOFF
*ParentSec
= cast
<MCSectionXCOFF
>(Fragment
->getParent());
653 assert((SymASec
->getMappingClass() == XCOFF::XMC_PR
&&
654 ParentSec
->getMappingClass() == XCOFF::XMC_PR
) &&
655 "Only XMC_PR csect may have the R_RBR relocation.");
657 // The address of the branch instruction should be the sum of section
658 // address, fragment offset and Fixup offset.
659 uint64_t BRInstrAddress
= SectionMap
[ParentSec
]->Address
+
660 Layout
.getFragmentOffset(Fragment
) +
662 // The FixedValue should be the difference between SymA csect address and BR
663 // instr address plus any constant value.
665 SectionMap
[SymASec
]->Address
- BRInstrAddress
+ Target
.getConstant();
666 } else if (Type
== XCOFF::RelocationType::R_REF
)
667 // The FixedValue should always be 0 since it specifies a nonrelocating
671 assert((Fixup
.getOffset() <=
672 MaxRawDataSize
- Layout
.getFragmentOffset(Fragment
)) &&
673 "Fragment offset + fixup offset is overflowed.");
674 uint32_t FixupOffsetInCsect
=
675 Layout
.getFragmentOffset(Fragment
) + Fixup
.getOffset();
677 XCOFFRelocation Reloc
= {Index
, FixupOffsetInCsect
, SignAndSize
, Type
};
678 MCSectionXCOFF
*RelocationSec
= cast
<MCSectionXCOFF
>(Fragment
->getParent());
679 assert(SectionMap
.contains(RelocationSec
) &&
680 "Expected containing csect to exist in map.");
681 SectionMap
[RelocationSec
]->Relocations
.push_back(Reloc
);
683 if (!Target
.getSymB())
686 const MCSymbol
*const SymB
= &Target
.getSymB()->getSymbol();
688 report_fatal_error("relocation for opposite term is not yet supported");
690 const MCSectionXCOFF
*SymBSec
= getContainingCsect(cast
<MCSymbolXCOFF
>(SymB
));
691 assert(SectionMap
.contains(SymBSec
) &&
692 "Expected containing csect to exist in map.");
693 if (SymASec
== SymBSec
)
695 "relocation for paired relocatable term is not yet supported");
697 assert(Type
== XCOFF::RelocationType::R_POS
&&
698 "SymA must be R_POS here if it's not opposite term or paired "
699 "relocatable term.");
700 const uint32_t IndexB
= getIndex(SymB
, SymBSec
);
701 // SymB must be R_NEG here, given the general form of Target(MCValue) is
702 // "SymbolA - SymbolB + imm64".
703 const uint8_t TypeB
= XCOFF::RelocationType::R_NEG
;
704 XCOFFRelocation RelocB
= {IndexB
, FixupOffsetInCsect
, SignAndSize
, TypeB
};
705 SectionMap
[RelocationSec
]->Relocations
.push_back(RelocB
);
706 // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
707 // now we just need to fold "- SymbolB" here.
708 FixedValue
-= getVirtualAddress(SymB
, SymBSec
);
711 void XCOFFObjectWriter::writeSections(const MCAssembler
&Asm
,
712 const MCAsmLayout
&Layout
) {
713 uint64_t CurrentAddressLocation
= 0;
714 for (const auto *Section
: Sections
)
715 writeSectionForControlSectionEntry(Asm
, Layout
, *Section
,
716 CurrentAddressLocation
);
717 for (const auto &DwarfSection
: DwarfSections
)
718 writeSectionForDwarfSectionEntry(Asm
, Layout
, DwarfSection
,
719 CurrentAddressLocation
);
720 writeSectionForExceptionSectionEntry(Asm
, Layout
, ExceptionSection
,
721 CurrentAddressLocation
);
724 uint64_t XCOFFObjectWriter::writeObject(MCAssembler
&Asm
,
725 const MCAsmLayout
&Layout
) {
726 // We always emit a timestamp of 0 for reproducibility, so ensure incremental
727 // linking is not enabled, in case, like with Windows COFF, such a timestamp
728 // is incompatible with incremental linking of XCOFF.
729 if (Asm
.isIncrementalLinkerCompatible())
730 report_fatal_error("Incremental linking not supported for XCOFF.");
732 finalizeSectionInfo();
733 uint64_t StartOffset
= W
.OS
.tell();
736 writeAuxFileHeader();
737 writeSectionHeaderTable();
738 writeSections(Asm
, Layout
);
740 writeSymbolTable(Layout
);
741 // Write the string table.
744 return W
.OS
.tell() - StartOffset
;
747 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef
&SymbolName
) {
748 return SymbolName
.size() > XCOFF::NameSize
|| is64Bit();
751 void XCOFFObjectWriter::writeSymbolName(const StringRef
&SymbolName
) {
752 // Magic, Offset or SymbolName.
753 if (nameShouldBeInStringTable(SymbolName
)) {
755 W
.write
<uint32_t>(Strings
.getOffset(SymbolName
));
757 char Name
[XCOFF::NameSize
+ 1];
758 std::strncpy(Name
, SymbolName
.data(), XCOFF::NameSize
);
759 ArrayRef
<char> NameRef(Name
, XCOFF::NameSize
);
764 void XCOFFObjectWriter::writeSymbolEntry(StringRef SymbolName
, uint64_t Value
,
765 int16_t SectionNumber
,
767 uint8_t StorageClass
,
768 uint8_t NumberOfAuxEntries
) {
770 W
.write
<uint64_t>(Value
);
771 W
.write
<uint32_t>(Strings
.getOffset(SymbolName
));
773 writeSymbolName(SymbolName
);
774 W
.write
<uint32_t>(Value
);
776 W
.write
<int16_t>(SectionNumber
);
777 W
.write
<uint16_t>(SymbolType
);
778 W
.write
<uint8_t>(StorageClass
);
779 W
.write
<uint8_t>(NumberOfAuxEntries
);
782 void XCOFFObjectWriter::writeSymbolAuxCsectEntry(uint64_t SectionOrLength
,
783 uint8_t SymbolAlignmentAndType
,
784 uint8_t StorageMappingClass
) {
785 W
.write
<uint32_t>(is64Bit() ? Lo_32(SectionOrLength
) : SectionOrLength
);
786 W
.write
<uint32_t>(0); // ParameterHashIndex
787 W
.write
<uint16_t>(0); // TypeChkSectNum
788 W
.write
<uint8_t>(SymbolAlignmentAndType
);
789 W
.write
<uint8_t>(StorageMappingClass
);
791 W
.write
<uint32_t>(Hi_32(SectionOrLength
));
792 W
.OS
.write_zeros(1); // Reserved
793 W
.write
<uint8_t>(XCOFF::AUX_CSECT
);
795 W
.write
<uint32_t>(0); // StabInfoIndex
796 W
.write
<uint16_t>(0); // StabSectNum
800 void XCOFFObjectWriter::writeSymbolAuxDwarfEntry(
801 uint64_t LengthOfSectionPortion
, uint64_t NumberOfRelocEnt
) {
802 writeWord(LengthOfSectionPortion
);
804 W
.OS
.write_zeros(4); // Reserved
805 writeWord(NumberOfRelocEnt
);
807 W
.OS
.write_zeros(1); // Reserved
808 W
.write
<uint8_t>(XCOFF::AUX_SECT
);
810 W
.OS
.write_zeros(6); // Reserved
814 void XCOFFObjectWriter::writeSymbolEntryForCsectMemberLabel(
815 const Symbol
&SymbolRef
, const XCOFFSection
&CSectionRef
,
816 int16_t SectionIndex
, uint64_t SymbolOffset
) {
817 assert(SymbolOffset
<= MaxRawDataSize
- CSectionRef
.Address
&&
818 "Symbol address overflowed.");
820 auto Entry
= ExceptionSection
.ExceptionTable
.find(SymbolRef
.MCSym
->getName());
821 if (Entry
!= ExceptionSection
.ExceptionTable
.end()) {
822 writeSymbolEntry(SymbolRef
.getSymbolTableName(),
823 CSectionRef
.Address
+ SymbolOffset
, SectionIndex
,
824 // In the old version of the 32-bit XCOFF interpretation,
825 // symbols may require bit 10 (0x0020) to be set if the
826 // symbol is a function, otherwise the bit should be 0.
827 is64Bit() ? SymbolRef
.getVisibilityType()
828 : SymbolRef
.getVisibilityType() | 0x0020,
829 SymbolRef
.getStorageClass(),
830 (is64Bit() && ExceptionSection
.isDebugEnabled
) ? 3 : 2);
831 if (is64Bit() && ExceptionSection
.isDebugEnabled
) {
832 // On 64 bit with debugging enabled, we have a csect, exception, and
833 // function auxilliary entries, so we must increment symbol index by 4.
834 writeSymbolAuxExceptionEntry(
835 ExceptionSection
.FileOffsetToData
+
836 getExceptionOffset(Entry
->second
.FunctionSymbol
),
837 Entry
->second
.FunctionSize
,
838 SymbolIndexMap
[Entry
->second
.FunctionSymbol
] + 4);
840 // For exception section entries, csect and function auxilliary entries
841 // must exist. On 64-bit there is also an exception auxilliary entry.
842 writeSymbolAuxFunctionEntry(
843 ExceptionSection
.FileOffsetToData
+
844 getExceptionOffset(Entry
->second
.FunctionSymbol
),
845 Entry
->second
.FunctionSize
, 0,
846 (is64Bit() && ExceptionSection
.isDebugEnabled
)
847 ? SymbolIndexMap
[Entry
->second
.FunctionSymbol
] + 4
848 : SymbolIndexMap
[Entry
->second
.FunctionSymbol
] + 3);
850 writeSymbolEntry(SymbolRef
.getSymbolTableName(),
851 CSectionRef
.Address
+ SymbolOffset
, SectionIndex
,
852 SymbolRef
.getVisibilityType(),
853 SymbolRef
.getStorageClass());
855 writeSymbolAuxCsectEntry(CSectionRef
.SymbolTableIndex
, XCOFF::XTY_LD
,
856 CSectionRef
.MCSec
->getMappingClass());
859 void XCOFFObjectWriter::writeSymbolEntryForDwarfSection(
860 const XCOFFSection
&DwarfSectionRef
, int16_t SectionIndex
) {
861 assert(DwarfSectionRef
.MCSec
->isDwarfSect() && "Not a DWARF section!");
863 writeSymbolEntry(DwarfSectionRef
.getSymbolTableName(), /*Value=*/0,
864 SectionIndex
, /*SymbolType=*/0, XCOFF::C_DWARF
);
866 writeSymbolAuxDwarfEntry(DwarfSectionRef
.Size
);
869 void XCOFFObjectWriter::writeSymbolEntryForControlSection(
870 const XCOFFSection
&CSectionRef
, int16_t SectionIndex
,
871 XCOFF::StorageClass StorageClass
) {
872 writeSymbolEntry(CSectionRef
.getSymbolTableName(), CSectionRef
.Address
,
873 SectionIndex
, CSectionRef
.getVisibilityType(), StorageClass
);
875 writeSymbolAuxCsectEntry(CSectionRef
.Size
, getEncodedType(CSectionRef
.MCSec
),
876 CSectionRef
.MCSec
->getMappingClass());
879 void XCOFFObjectWriter::writeSymbolAuxFunctionEntry(uint32_t EntryOffset
,
880 uint32_t FunctionSize
,
881 uint64_t LineNumberPointer
,
884 writeWord(LineNumberPointer
);
886 W
.write
<uint32_t>(EntryOffset
);
887 W
.write
<uint32_t>(FunctionSize
);
889 writeWord(LineNumberPointer
);
890 W
.write
<uint32_t>(EndIndex
);
893 W
.write
<uint8_t>(XCOFF::AUX_FCN
);
899 void XCOFFObjectWriter::writeSymbolAuxExceptionEntry(uint64_t EntryOffset
,
900 uint32_t FunctionSize
,
902 assert(is64Bit() && "Exception auxilliary entries are 64-bit only.");
903 W
.write
<uint64_t>(EntryOffset
);
904 W
.write
<uint32_t>(FunctionSize
);
905 W
.write
<uint32_t>(EndIndex
);
906 W
.OS
.write_zeros(1); // Pad (unused)
907 W
.write
<uint8_t>(XCOFF::AUX_EXCEPT
);
910 void XCOFFObjectWriter::writeFileHeader() {
911 W
.write
<uint16_t>(is64Bit() ? XCOFF::XCOFF64
: XCOFF::XCOFF32
);
912 W
.write
<uint16_t>(SectionCount
);
913 W
.write
<int32_t>(0); // TimeStamp
914 writeWord(SymbolTableOffset
);
916 W
.write
<uint16_t>(auxiliaryHeaderSize());
917 W
.write
<uint16_t>(0); // Flags
918 W
.write
<int32_t>(SymbolTableEntryCount
);
920 W
.write
<int32_t>(SymbolTableEntryCount
);
921 W
.write
<uint16_t>(auxiliaryHeaderSize());
922 W
.write
<uint16_t>(0); // Flags
926 void XCOFFObjectWriter::writeAuxFileHeader() {
927 if (!auxiliaryHeaderSize())
929 W
.write
<uint16_t>(0); // Magic
931 XCOFF::NEW_XCOFF_INTERPRET
); // Version. The new interpretation of the
932 // n_type field in the symbol table entry is
934 W
.write
<uint32_t>(Sections
[0]->Size
); // TextSize
935 W
.write
<uint32_t>(Sections
[1]->Size
); // InitDataSize
936 W
.write
<uint32_t>(Sections
[2]->Size
); // BssDataSize
937 W
.write
<uint32_t>(0); // EntryPointAddr
938 W
.write
<uint32_t>(Sections
[0]->Address
); // TextStartAddr
939 W
.write
<uint32_t>(Sections
[1]->Address
); // DataStartAddr
942 void XCOFFObjectWriter::writeSectionHeader(const SectionEntry
*Sec
) {
943 bool IsDwarf
= (Sec
->Flags
& XCOFF::STYP_DWARF
) != 0;
944 bool IsOvrflo
= (Sec
->Flags
& XCOFF::STYP_OVRFLO
) != 0;
945 // Nothing to write for this Section.
946 if (Sec
->Index
== SectionEntry::UninitializedIndex
)
950 ArrayRef
<char> NameRef(Sec
->Name
, XCOFF::NameSize
);
953 // Write the Physical Address and Virtual Address.
954 // We use 0 for DWARF sections' Physical and Virtual Addresses.
955 writeWord(IsDwarf
? 0 : Sec
->Address
);
956 // Since line number is not supported, we set it to 0 for overflow sections.
957 writeWord((IsDwarf
|| IsOvrflo
) ? 0 : Sec
->Address
);
959 writeWord(Sec
->Size
);
960 writeWord(Sec
->FileOffsetToData
);
961 writeWord(Sec
->FileOffsetToRelocations
);
962 writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet.
965 W
.write
<uint32_t>(Sec
->RelocationCount
);
966 W
.write
<uint32_t>(0); // NumberOfLineNumbers. Not supported yet.
967 W
.write
<int32_t>(Sec
->Flags
);
970 // For the overflow section header, s_nreloc provides a reference to the
971 // primary section header and s_nlnno must have the same value.
972 // For common section headers, if either of s_nreloc or s_nlnno are set to
973 // 65535, the other one must also be set to 65535.
974 W
.write
<uint16_t>(Sec
->RelocationCount
);
975 W
.write
<uint16_t>((IsOvrflo
|| Sec
->RelocationCount
== XCOFF::RelocOverflow
)
976 ? Sec
->RelocationCount
977 : 0); // NumberOfLineNumbers. Not supported yet.
978 W
.write
<int32_t>(Sec
->Flags
);
982 void XCOFFObjectWriter::writeSectionHeaderTable() {
983 for (const auto *CsectSec
: Sections
)
984 writeSectionHeader(CsectSec
);
985 for (const auto &DwarfSec
: DwarfSections
)
986 writeSectionHeader(&DwarfSec
);
987 for (const auto &OverflowSec
: OverflowSections
)
988 writeSectionHeader(&OverflowSec
);
989 if (hasExceptionSection())
990 writeSectionHeader(&ExceptionSection
);
993 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc
,
994 const XCOFFSection
&Section
) {
995 if (Section
.MCSec
->isCsect())
996 writeWord(Section
.Address
+ Reloc
.FixupOffsetInCsect
);
998 // DWARF sections' address is set to 0.
999 assert(Section
.MCSec
->isDwarfSect() && "unsupport section type!");
1000 writeWord(Reloc
.FixupOffsetInCsect
);
1002 W
.write
<uint32_t>(Reloc
.SymbolTableIndex
);
1003 W
.write
<uint8_t>(Reloc
.SignAndSize
);
1004 W
.write
<uint8_t>(Reloc
.Type
);
1007 void XCOFFObjectWriter::writeRelocations() {
1008 for (const auto *Section
: Sections
) {
1009 if (Section
->Index
== SectionEntry::UninitializedIndex
)
1010 // Nothing to write for this Section.
1013 for (const auto *Group
: Section
->Groups
) {
1017 for (const auto &Csect
: *Group
) {
1018 for (const auto Reloc
: Csect
.Relocations
)
1019 writeRelocation(Reloc
, Csect
);
1024 for (const auto &DwarfSection
: DwarfSections
)
1025 for (const auto &Reloc
: DwarfSection
.DwarfSect
->Relocations
)
1026 writeRelocation(Reloc
, *DwarfSection
.DwarfSect
);
1029 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout
&Layout
) {
1030 // Write C_FILE symbols.
1031 // The n_name of a C_FILE symbol is the source file's name when no auxiliary
1032 // entries are present.
1033 for (const std::pair
<std::string
, size_t> &F
: FileNames
) {
1034 writeSymbolEntry(F
.first
, /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG
,
1035 /*SymbolType=*/0, XCOFF::C_FILE
,
1036 /*NumberOfAuxEntries=*/0);
1039 for (const auto &Csect
: UndefinedCsects
) {
1040 writeSymbolEntryForControlSection(Csect
, XCOFF::ReservedSectionNum::N_UNDEF
,
1041 Csect
.MCSec
->getStorageClass());
1044 for (const auto *Section
: Sections
) {
1045 if (Section
->Index
== SectionEntry::UninitializedIndex
)
1046 // Nothing to write for this Section.
1049 for (const auto *Group
: Section
->Groups
) {
1053 const int16_t SectionIndex
= Section
->Index
;
1054 for (const auto &Csect
: *Group
) {
1055 // Write out the control section first and then each symbol in it.
1056 writeSymbolEntryForControlSection(Csect
, SectionIndex
,
1057 Csect
.MCSec
->getStorageClass());
1059 for (const auto &Sym
: Csect
.Syms
)
1060 writeSymbolEntryForCsectMemberLabel(
1061 Sym
, Csect
, SectionIndex
, Layout
.getSymbolOffset(*(Sym
.MCSym
)));
1066 for (const auto &DwarfSection
: DwarfSections
)
1067 writeSymbolEntryForDwarfSection(*DwarfSection
.DwarfSect
,
1068 DwarfSection
.Index
);
1071 void XCOFFObjectWriter::finalizeRelocationInfo(SectionEntry
*Sec
,
1072 uint64_t RelCount
) {
1073 // Handles relocation field overflows in an XCOFF32 file. An XCOFF64 file
1074 // may not contain an overflow section header.
1075 if (!is64Bit() && (RelCount
>= static_cast<uint32_t>(XCOFF::RelocOverflow
))) {
1076 // Generate an overflow section header.
1077 SectionEntry
SecEntry(".ovrflo", XCOFF::STYP_OVRFLO
);
1079 // This field specifies the file section number of the section header that
1081 SecEntry
.RelocationCount
= Sec
->Index
;
1083 // This field specifies the number of relocation entries actually
1085 SecEntry
.Address
= RelCount
;
1086 SecEntry
.Index
= ++SectionCount
;
1087 OverflowSections
.push_back(std::move(SecEntry
));
1089 // The field in the primary section header is always 65535
1090 // (XCOFF::RelocOverflow).
1091 Sec
->RelocationCount
= XCOFF::RelocOverflow
;
1093 Sec
->RelocationCount
= RelCount
;
1097 void XCOFFObjectWriter::calcOffsetToRelocations(SectionEntry
*Sec
,
1098 uint64_t &RawPointer
) {
1099 if (!Sec
->RelocationCount
)
1102 Sec
->FileOffsetToRelocations
= RawPointer
;
1103 uint64_t RelocationSizeInSec
= 0;
1105 Sec
->RelocationCount
== static_cast<uint32_t>(XCOFF::RelocOverflow
)) {
1106 // Find its corresponding overflow section.
1107 for (auto &OverflowSec
: OverflowSections
) {
1108 if (OverflowSec
.RelocationCount
== static_cast<uint32_t>(Sec
->Index
)) {
1109 RelocationSizeInSec
=
1110 OverflowSec
.Address
* XCOFF::RelocationSerializationSize32
;
1112 // This field must have the same values as in the corresponding
1113 // primary section header.
1114 OverflowSec
.FileOffsetToRelocations
= Sec
->FileOffsetToRelocations
;
1117 assert(RelocationSizeInSec
&& "Overflow section header doesn't exist.");
1119 RelocationSizeInSec
= Sec
->RelocationCount
*
1120 (is64Bit() ? XCOFF::RelocationSerializationSize64
1121 : XCOFF::RelocationSerializationSize32
);
1124 RawPointer
+= RelocationSizeInSec
;
1125 if (RawPointer
> MaxRawDataSize
)
1126 report_fatal_error("Relocation data overflowed this object file.");
1129 void XCOFFObjectWriter::finalizeSectionInfo() {
1130 for (auto *Section
: Sections
) {
1131 if (Section
->Index
== SectionEntry::UninitializedIndex
)
1132 // Nothing to record for this Section.
1135 uint64_t RelCount
= 0;
1136 for (const auto *Group
: Section
->Groups
) {
1140 for (auto &Csect
: *Group
)
1141 RelCount
+= Csect
.Relocations
.size();
1143 finalizeRelocationInfo(Section
, RelCount
);
1146 for (auto &DwarfSection
: DwarfSections
)
1147 finalizeRelocationInfo(&DwarfSection
,
1148 DwarfSection
.DwarfSect
->Relocations
.size());
1150 // Calculate the RawPointer value for all headers.
1151 uint64_t RawPointer
=
1152 (is64Bit() ? (XCOFF::FileHeaderSize64
+
1153 SectionCount
* XCOFF::SectionHeaderSize64
)
1154 : (XCOFF::FileHeaderSize32
+
1155 SectionCount
* XCOFF::SectionHeaderSize32
)) +
1156 auxiliaryHeaderSize();
1158 // Calculate the file offset to the section data.
1159 for (auto *Sec
: Sections
) {
1160 if (Sec
->Index
== SectionEntry::UninitializedIndex
|| Sec
->IsVirtual
)
1163 Sec
->FileOffsetToData
= RawPointer
;
1164 RawPointer
+= Sec
->Size
;
1165 if (RawPointer
> MaxRawDataSize
)
1166 report_fatal_error("Section raw data overflowed this object file.");
1169 if (!DwarfSections
.empty()) {
1170 RawPointer
+= PaddingsBeforeDwarf
;
1171 for (auto &DwarfSection
: DwarfSections
) {
1172 DwarfSection
.FileOffsetToData
= RawPointer
;
1173 RawPointer
+= DwarfSection
.MemorySize
;
1174 if (RawPointer
> MaxRawDataSize
)
1175 report_fatal_error("Section raw data overflowed this object file.");
1179 if (hasExceptionSection()) {
1180 ExceptionSection
.FileOffsetToData
= RawPointer
;
1181 RawPointer
+= ExceptionSection
.Size
;
1183 assert(RawPointer
<= MaxRawDataSize
&&
1184 "Section raw data overflowed this object file.");
1187 for (auto *Sec
: Sections
) {
1188 if (Sec
->Index
!= SectionEntry::UninitializedIndex
)
1189 calcOffsetToRelocations(Sec
, RawPointer
);
1192 for (auto &DwarfSec
: DwarfSections
)
1193 calcOffsetToRelocations(&DwarfSec
, RawPointer
);
1195 // TODO Error check that the number of symbol table entries fits in 32-bits
1197 if (SymbolTableEntryCount
)
1198 SymbolTableOffset
= RawPointer
;
1201 void XCOFFObjectWriter::addExceptionEntry(
1202 const MCSymbol
*Symbol
, const MCSymbol
*Trap
, unsigned LanguageCode
,
1203 unsigned ReasonCode
, unsigned FunctionSize
, bool hasDebug
) {
1204 // If a module had debug info, debugging is enabled and XCOFF emits the
1205 // exception auxilliary entry.
1207 ExceptionSection
.isDebugEnabled
= true;
1208 auto Entry
= ExceptionSection
.ExceptionTable
.find(Symbol
->getName());
1209 if (Entry
!= ExceptionSection
.ExceptionTable
.end()) {
1210 Entry
->second
.Entries
.push_back(
1211 ExceptionTableEntry(Trap
, LanguageCode
, ReasonCode
));
1214 ExceptionInfo NewEntry
;
1215 NewEntry
.FunctionSymbol
= Symbol
;
1216 NewEntry
.FunctionSize
= FunctionSize
;
1217 NewEntry
.Entries
.push_back(
1218 ExceptionTableEntry(Trap
, LanguageCode
, ReasonCode
));
1219 ExceptionSection
.ExceptionTable
.insert(
1220 std::pair
<const StringRef
, ExceptionInfo
>(Symbol
->getName(), NewEntry
));
1223 unsigned XCOFFObjectWriter::getExceptionSectionSize() {
1224 unsigned EntryNum
= 0;
1226 for (auto it
= ExceptionSection
.ExceptionTable
.begin();
1227 it
!= ExceptionSection
.ExceptionTable
.end(); ++it
)
1228 // The size() gets +1 to account for the initial entry containing the
1229 // symbol table index.
1230 EntryNum
+= it
->second
.Entries
.size() + 1;
1232 return EntryNum
* (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
1233 : XCOFF::ExceptionSectionEntrySize32
);
1236 unsigned XCOFFObjectWriter::getExceptionOffset(const MCSymbol
*Symbol
) {
1237 unsigned EntryNum
= 0;
1238 for (auto it
= ExceptionSection
.ExceptionTable
.begin();
1239 it
!= ExceptionSection
.ExceptionTable
.end(); ++it
) {
1240 if (Symbol
== it
->second
.FunctionSymbol
)
1242 EntryNum
+= it
->second
.Entries
.size() + 1;
1244 return EntryNum
* (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
1245 : XCOFF::ExceptionSectionEntrySize32
);
1248 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout
&Layout
) {
1249 // The symbol table starts with all the C_FILE symbols.
1250 uint32_t SymbolTableIndex
= FileNames
.size();
1252 // Calculate indices for undefined symbols.
1253 for (auto &Csect
: UndefinedCsects
) {
1256 Csect
.SymbolTableIndex
= SymbolTableIndex
;
1257 SymbolIndexMap
[Csect
.MCSec
->getQualNameSymbol()] = Csect
.SymbolTableIndex
;
1258 // 1 main and 1 auxiliary symbol table entry for each contained symbol.
1259 SymbolTableIndex
+= 2;
1262 // The address corrresponds to the address of sections and symbols in the
1263 // object file. We place the shared address 0 immediately after the
1264 // section header table.
1265 uint64_t Address
= 0;
1266 // Section indices are 1-based in XCOFF.
1267 int32_t SectionIndex
= 1;
1268 bool HasTDataSection
= false;
1270 for (auto *Section
: Sections
) {
1271 const bool IsEmpty
=
1272 llvm::all_of(Section
->Groups
,
1273 [](const CsectGroup
*Group
) { return Group
->empty(); });
1277 if (SectionIndex
> MaxSectionIndex
)
1278 report_fatal_error("Section index overflow!");
1279 Section
->Index
= SectionIndex
++;
1282 bool SectionAddressSet
= false;
1283 // Reset the starting address to 0 for TData section.
1284 if (Section
->Flags
== XCOFF::STYP_TDATA
) {
1286 HasTDataSection
= true;
1288 // Reset the starting address to 0 for TBSS section if the object file does
1289 // not contain TData Section.
1290 if ((Section
->Flags
== XCOFF::STYP_TBSS
) && !HasTDataSection
)
1293 for (auto *Group
: Section
->Groups
) {
1297 for (auto &Csect
: *Group
) {
1298 const MCSectionXCOFF
*MCSec
= Csect
.MCSec
;
1299 Csect
.Address
= alignTo(Address
, MCSec
->getAlign());
1300 Csect
.Size
= Layout
.getSectionAddressSize(MCSec
);
1301 Address
= Csect
.Address
+ Csect
.Size
;
1302 Csect
.SymbolTableIndex
= SymbolTableIndex
;
1303 SymbolIndexMap
[MCSec
->getQualNameSymbol()] = Csect
.SymbolTableIndex
;
1304 // 1 main and 1 auxiliary symbol table entry for the csect.
1305 SymbolTableIndex
+= 2;
1307 for (auto &Sym
: Csect
.Syms
) {
1308 bool hasExceptEntry
= false;
1310 ExceptionSection
.ExceptionTable
.find(Sym
.MCSym
->getName());
1311 if (Entry
!= ExceptionSection
.ExceptionTable
.end()) {
1312 hasExceptEntry
= true;
1313 for (auto &TrapEntry
: Entry
->second
.Entries
) {
1314 TrapEntry
.TrapAddress
= Layout
.getSymbolOffset(*(Sym
.MCSym
)) +
1315 TrapEntry
.Trap
->getOffset();
1318 Sym
.SymbolTableIndex
= SymbolTableIndex
;
1319 SymbolIndexMap
[Sym
.MCSym
] = Sym
.SymbolTableIndex
;
1320 // 1 main and 1 auxiliary symbol table entry for each contained
1321 // symbol. For symbols with exception section entries, a function
1322 // auxilliary entry is needed, and on 64-bit XCOFF with debugging
1323 // enabled, an additional exception auxilliary entry is needed.
1324 SymbolTableIndex
+= 2;
1325 if (hasExceptionSection() && hasExceptEntry
) {
1326 if (is64Bit() && ExceptionSection
.isDebugEnabled
)
1327 SymbolTableIndex
+= 2;
1329 SymbolTableIndex
+= 1;
1334 if (!SectionAddressSet
) {
1335 Section
->Address
= Group
->front().Address
;
1336 SectionAddressSet
= true;
1340 // Make sure the address of the next section aligned to
1341 // DefaultSectionAlign.
1342 Address
= alignTo(Address
, DefaultSectionAlign
);
1343 Section
->Size
= Address
- Section
->Address
;
1346 // Start to generate DWARF sections. Sections other than DWARF section use
1347 // DefaultSectionAlign as the default alignment, while DWARF sections have
1348 // their own alignments. If these two alignments are not the same, we need
1349 // some paddings here and record the paddings bytes for FileOffsetToData
1351 if (!DwarfSections
.empty())
1352 PaddingsBeforeDwarf
=
1354 (*DwarfSections
.begin()).DwarfSect
->MCSec
->getAlign()) -
1357 DwarfSectionEntry
*LastDwarfSection
= nullptr;
1358 for (auto &DwarfSection
: DwarfSections
) {
1359 assert((SectionIndex
<= MaxSectionIndex
) && "Section index overflow!");
1361 XCOFFSection
&DwarfSect
= *DwarfSection
.DwarfSect
;
1362 const MCSectionXCOFF
*MCSec
= DwarfSect
.MCSec
;
1365 DwarfSection
.Index
= SectionIndex
++;
1369 DwarfSect
.SymbolTableIndex
= SymbolTableIndex
;
1370 SymbolIndexMap
[MCSec
->getQualNameSymbol()] = DwarfSect
.SymbolTableIndex
;
1371 // 1 main and 1 auxiliary symbol table entry for the csect.
1372 SymbolTableIndex
+= 2;
1374 // Section address. Make it align to section alignment.
1375 // We use address 0 for DWARF sections' Physical and Virtual Addresses.
1376 // This address is used to tell where is the section in the final object.
1377 // See writeSectionForDwarfSectionEntry().
1378 DwarfSection
.Address
= DwarfSect
.Address
=
1379 alignTo(Address
, MCSec
->getAlign());
1382 // For DWARF section, we must use the real size which may be not aligned.
1383 DwarfSection
.Size
= DwarfSect
.Size
= Layout
.getSectionAddressSize(MCSec
);
1385 Address
= DwarfSection
.Address
+ DwarfSection
.Size
;
1387 if (LastDwarfSection
)
1388 LastDwarfSection
->MemorySize
=
1389 DwarfSection
.Address
- LastDwarfSection
->Address
;
1390 LastDwarfSection
= &DwarfSection
;
1392 if (LastDwarfSection
) {
1393 // Make the final DWARF section address align to the default section
1394 // alignment for follow contents.
1395 Address
= alignTo(LastDwarfSection
->Address
+ LastDwarfSection
->Size
,
1396 DefaultSectionAlign
);
1397 LastDwarfSection
->MemorySize
= Address
- LastDwarfSection
->Address
;
1399 if (hasExceptionSection()) {
1400 ExceptionSection
.Index
= SectionIndex
++;
1402 ExceptionSection
.Address
= 0;
1403 ExceptionSection
.Size
= getExceptionSectionSize();
1404 Address
+= ExceptionSection
.Size
;
1405 Address
= alignTo(Address
, DefaultSectionAlign
);
1408 SymbolTableEntryCount
= SymbolTableIndex
;
1411 void XCOFFObjectWriter::writeSectionForControlSectionEntry(
1412 const MCAssembler
&Asm
, const MCAsmLayout
&Layout
,
1413 const CsectSectionEntry
&CsectEntry
, uint64_t &CurrentAddressLocation
) {
1414 // Nothing to write for this Section.
1415 if (CsectEntry
.Index
== SectionEntry::UninitializedIndex
)
1418 // There could be a gap (without corresponding zero padding) between
1420 // There could be a gap (without corresponding zero padding) between
1422 assert(((CurrentAddressLocation
<= CsectEntry
.Address
) ||
1423 (CsectEntry
.Flags
== XCOFF::STYP_TDATA
) ||
1424 (CsectEntry
.Flags
== XCOFF::STYP_TBSS
)) &&
1425 "CurrentAddressLocation should be less than or equal to section "
1426 "address if the section is not TData or TBSS.");
1428 CurrentAddressLocation
= CsectEntry
.Address
;
1430 // For virtual sections, nothing to write. But need to increase
1431 // CurrentAddressLocation for later sections like DWARF section has a correct
1432 // writing location.
1433 if (CsectEntry
.IsVirtual
) {
1434 CurrentAddressLocation
+= CsectEntry
.Size
;
1438 for (const auto &Group
: CsectEntry
.Groups
) {
1439 for (const auto &Csect
: *Group
) {
1440 if (uint32_t PaddingSize
= Csect
.Address
- CurrentAddressLocation
)
1441 W
.OS
.write_zeros(PaddingSize
);
1443 Asm
.writeSectionData(W
.OS
, Csect
.MCSec
, Layout
);
1444 CurrentAddressLocation
= Csect
.Address
+ Csect
.Size
;
1448 // The size of the tail padding in a section is the end virtual address of
1449 // the current section minus the the end virtual address of the last csect
1451 if (uint64_t PaddingSize
=
1452 CsectEntry
.Address
+ CsectEntry
.Size
- CurrentAddressLocation
) {
1453 W
.OS
.write_zeros(PaddingSize
);
1454 CurrentAddressLocation
+= PaddingSize
;
1458 void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
1459 const MCAssembler
&Asm
, const MCAsmLayout
&Layout
,
1460 const DwarfSectionEntry
&DwarfEntry
, uint64_t &CurrentAddressLocation
) {
1461 // There could be a gap (without corresponding zero padding) between
1462 // sections. For example DWARF section alignment is bigger than
1463 // DefaultSectionAlign.
1464 assert(CurrentAddressLocation
<= DwarfEntry
.Address
&&
1465 "CurrentAddressLocation should be less than or equal to section "
1468 if (uint64_t PaddingSize
= DwarfEntry
.Address
- CurrentAddressLocation
)
1469 W
.OS
.write_zeros(PaddingSize
);
1471 if (DwarfEntry
.Size
)
1472 Asm
.writeSectionData(W
.OS
, DwarfEntry
.DwarfSect
->MCSec
, Layout
);
1474 CurrentAddressLocation
= DwarfEntry
.Address
+ DwarfEntry
.Size
;
1476 // DWARF section size is not aligned to DefaultSectionAlign.
1477 // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign.
1478 uint32_t Mod
= CurrentAddressLocation
% DefaultSectionAlign
;
1479 uint32_t TailPaddingSize
= Mod
? DefaultSectionAlign
- Mod
: 0;
1480 if (TailPaddingSize
)
1481 W
.OS
.write_zeros(TailPaddingSize
);
1483 CurrentAddressLocation
+= TailPaddingSize
;
1486 void XCOFFObjectWriter::writeSectionForExceptionSectionEntry(
1487 const MCAssembler
&Asm
, const MCAsmLayout
&Layout
,
1488 ExceptionSectionEntry
&ExceptionEntry
, uint64_t &CurrentAddressLocation
) {
1489 for (auto it
= ExceptionEntry
.ExceptionTable
.begin();
1490 it
!= ExceptionEntry
.ExceptionTable
.end(); it
++) {
1491 // For every symbol that has exception entries, you must start the entries
1492 // with an initial symbol table index entry
1493 W
.write
<uint32_t>(SymbolIndexMap
[it
->second
.FunctionSymbol
]);
1495 // 4-byte padding on 64-bit.
1496 W
.OS
.write_zeros(4);
1498 W
.OS
.write_zeros(2);
1499 for (auto &TrapEntry
: it
->second
.Entries
) {
1500 writeWord(TrapEntry
.TrapAddress
);
1501 W
.write
<uint8_t>(TrapEntry
.Lang
);
1502 W
.write
<uint8_t>(TrapEntry
.Reason
);
1506 CurrentAddressLocation
+= getExceptionSectionSize();
1509 // Takes the log base 2 of the alignment and shifts the result into the 5 most
1510 // significant bits of a byte, then or's in the csect type into the least
1511 // significant 3 bits.
1512 uint8_t getEncodedType(const MCSectionXCOFF
*Sec
) {
1513 unsigned Log2Align
= Log2(Sec
->getAlign());
1514 // Result is a number in the range [0, 31] which fits in the 5 least
1515 // significant bits. Shift this value into the 5 most significant bits, and
1516 // bitwise-or in the csect type.
1517 uint8_t EncodedAlign
= Log2Align
<< 3;
1518 return EncodedAlign
| Sec
->getCSectType();
1521 } // end anonymous namespace
1523 std::unique_ptr
<MCObjectWriter
>
1524 llvm::createXCOFFObjectWriter(std::unique_ptr
<MCXCOFFObjectTargetWriter
> MOTW
,
1525 raw_pwrite_stream
&OS
) {
1526 return std::make_unique
<XCOFFObjectWriter
>(std::move(MOTW
), OS
);