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 virtual uint64_t advanceFileOffset(const uint64_t MaxRawDataSize
,
126 const uint64_t RawPointer
) {
127 FileOffsetToData
= RawPointer
;
128 uint64_t NewPointer
= RawPointer
+ Size
;
129 if (NewPointer
> MaxRawDataSize
)
130 report_fatal_error("Section raw data overflowed this object file.");
134 // XCOFF has special section numbers for symbols:
135 // -2 Specifies N_DEBUG, a special symbolic debugging symbol.
136 // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not
138 // 0 Specifies N_UNDEF, an undefined external symbol.
139 // Therefore, we choose -3 (N_DEBUG - 1) to represent a section index that
140 // hasn't been initialized.
141 static constexpr int16_t UninitializedIndex
=
142 XCOFF::ReservedSectionNum::N_DEBUG
- 1;
144 SectionEntry(StringRef N
, int32_t Flags
)
145 : Name(), Address(0), Size(0), FileOffsetToData(0),
146 FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags
),
147 Index(UninitializedIndex
) {
148 assert(N
.size() <= XCOFF::NameSize
&& "section name too long");
149 memcpy(Name
, N
.data(), N
.size());
152 virtual void reset() {
155 FileOffsetToData
= 0;
156 FileOffsetToRelocations
= 0;
158 Index
= UninitializedIndex
;
161 virtual ~SectionEntry() = default;
164 // Represents the data related to a section excluding the csects that make up
165 // the raw data of the section. The csects are stored separately as not all
166 // sections contain csects, and some sections contain csects which are better
167 // stored separately, e.g. the .data section containing read-write, descriptor,
168 // TOCBase and TOC-entry csects.
169 struct CsectSectionEntry
: public SectionEntry
{
170 // Virtual sections do not need storage allocated in the object file.
171 const bool IsVirtual
;
173 // This is a section containing csect groups.
176 CsectSectionEntry(StringRef N
, XCOFF::SectionTypeFlags Flags
, bool IsVirtual
,
178 : SectionEntry(N
, Flags
), IsVirtual(IsVirtual
), Groups(Groups
) {
179 assert(N
.size() <= XCOFF::NameSize
&& "section name too long");
180 memcpy(Name
, N
.data(), N
.size());
183 void reset() override
{
184 SectionEntry::reset();
185 // Clear any csects we have stored.
186 for (auto *Group
: Groups
)
190 virtual ~CsectSectionEntry() = default;
193 struct DwarfSectionEntry
: public SectionEntry
{
194 // For DWARF section entry.
195 std::unique_ptr
<XCOFFSection
> DwarfSect
;
197 // For DWARF section, we must use real size in the section header. MemorySize
198 // is for the size the DWARF section occupies including paddings.
201 // TODO: Remove this override. Loadable sections (e.g., .text, .data) may need
202 // to be aligned. Other sections generally don't need any alignment, but if
203 // they're aligned, the RawPointer should be adjusted before writing the
204 // section. Then a dwarf-specific function wouldn't be needed.
205 uint64_t advanceFileOffset(const uint64_t MaxRawDataSize
,
206 const uint64_t RawPointer
) override
{
207 FileOffsetToData
= RawPointer
;
208 uint64_t NewPointer
= RawPointer
+ MemorySize
;
209 assert(NewPointer
<= MaxRawDataSize
&&
210 "Section raw data overflowed this object file.");
214 DwarfSectionEntry(StringRef N
, int32_t Flags
,
215 std::unique_ptr
<XCOFFSection
> Sect
)
216 : SectionEntry(N
, Flags
| XCOFF::STYP_DWARF
), DwarfSect(std::move(Sect
)),
218 assert(DwarfSect
->MCSec
->isDwarfSect() &&
219 "This should be a DWARF section!");
220 assert(N
.size() <= XCOFF::NameSize
&& "section name too long");
221 memcpy(Name
, N
.data(), N
.size());
224 DwarfSectionEntry(DwarfSectionEntry
&&s
) = default;
226 virtual ~DwarfSectionEntry() = default;
229 struct ExceptionTableEntry
{
230 const MCSymbol
*Trap
;
231 uint64_t TrapAddress
= ~0ul;
235 ExceptionTableEntry(const MCSymbol
*Trap
, unsigned Lang
, unsigned Reason
)
236 : Trap(Trap
), Lang(Lang
), Reason(Reason
) {}
239 struct ExceptionInfo
{
240 const MCSymbol
*FunctionSymbol
;
241 unsigned FunctionSize
;
242 std::vector
<ExceptionTableEntry
> Entries
;
245 struct ExceptionSectionEntry
: public SectionEntry
{
246 std::map
<const StringRef
, ExceptionInfo
> ExceptionTable
;
247 bool isDebugEnabled
= false;
249 ExceptionSectionEntry(StringRef N
, int32_t Flags
)
250 : SectionEntry(N
, Flags
| XCOFF::STYP_EXCEPT
) {
251 assert(N
.size() <= XCOFF::NameSize
&& "Section too long.");
252 memcpy(Name
, N
.data(), N
.size());
255 virtual ~ExceptionSectionEntry() = default;
258 struct CInfoSymInfo
{
259 // Name of the C_INFO symbol associated with the section
261 std::string Metadata
;
262 // Offset into the start of the metadata in the section
265 CInfoSymInfo(std::string Name
, std::string Metadata
)
266 : Name(Name
), Metadata(Metadata
) {}
267 // Metadata needs to be padded out to an even word size.
268 uint32_t paddingSize() const {
269 return alignTo(Metadata
.size(), sizeof(uint32_t)) - Metadata
.size();
272 // Total size of the entry, including the 4 byte length
273 uint32_t size() const {
274 return Metadata
.size() + paddingSize() + sizeof(uint32_t);
278 struct CInfoSymSectionEntry
: public SectionEntry
{
279 std::unique_ptr
<CInfoSymInfo
> Entry
;
281 CInfoSymSectionEntry(StringRef N
, int32_t Flags
) : SectionEntry(N
, Flags
) {}
282 virtual ~CInfoSymSectionEntry() = default;
283 void addEntry(std::unique_ptr
<CInfoSymInfo
> NewEntry
) {
284 Entry
= std::move(NewEntry
);
285 Entry
->Offset
= sizeof(uint32_t);
286 Size
+= Entry
->size();
288 void reset() override
{
289 SectionEntry::reset();
294 class XCOFFObjectWriter
: public MCObjectWriter
{
296 uint32_t SymbolTableEntryCount
= 0;
297 uint64_t SymbolTableOffset
= 0;
298 uint16_t SectionCount
= 0;
299 uint32_t PaddingsBeforeDwarf
= 0;
300 std::vector
<std::pair
<std::string
, size_t>> FileNames
;
301 bool HasVisibility
= false;
303 support::endian::Writer W
;
304 std::unique_ptr
<MCXCOFFObjectTargetWriter
> TargetObjectWriter
;
305 StringTableBuilder Strings
;
307 const uint64_t MaxRawDataSize
=
308 TargetObjectWriter
->is64Bit() ? UINT64_MAX
: UINT32_MAX
;
310 // Maps the MCSection representation to its corresponding XCOFFSection
311 // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into
312 // from its containing MCSectionXCOFF.
313 DenseMap
<const MCSectionXCOFF
*, XCOFFSection
*> SectionMap
;
315 // Maps the MCSymbol representation to its corrresponding symbol table index.
316 // Needed for relocation.
317 DenseMap
<const MCSymbol
*, uint32_t> SymbolIndexMap
;
319 // CsectGroups. These store the csects which make up different parts of
320 // the sections. Should have one for each set of csects that get mapped into
321 // the same section and get handled in a 'similar' way.
322 CsectGroup UndefinedCsects
;
323 CsectGroup ProgramCodeCsects
;
324 CsectGroup ReadOnlyCsects
;
325 CsectGroup DataCsects
;
326 CsectGroup FuncDSCsects
;
327 CsectGroup TOCCsects
;
328 CsectGroup BSSCsects
;
329 CsectGroup TDataCsects
;
330 CsectGroup TBSSCsects
;
332 // The Predefined sections.
333 CsectSectionEntry Text
;
334 CsectSectionEntry Data
;
335 CsectSectionEntry BSS
;
336 CsectSectionEntry TData
;
337 CsectSectionEntry TBSS
;
339 // All the XCOFF sections, in the order they will appear in the section header
341 std::array
<CsectSectionEntry
*const, 5> Sections
{
342 {&Text
, &Data
, &BSS
, &TData
, &TBSS
}};
344 std::vector
<DwarfSectionEntry
> DwarfSections
;
345 std::vector
<SectionEntry
> OverflowSections
;
347 ExceptionSectionEntry ExceptionSection
;
348 CInfoSymSectionEntry CInfoSymSection
;
350 CsectGroup
&getCsectGroup(const MCSectionXCOFF
*MCSec
);
352 void reset() override
;
354 void executePostLayoutBinding(MCAssembler
&, const MCAsmLayout
&) override
;
356 void recordRelocation(MCAssembler
&, const MCAsmLayout
&, const MCFragment
*,
357 const MCFixup
&, MCValue
, uint64_t &) override
;
359 uint64_t writeObject(MCAssembler
&, const MCAsmLayout
&) override
;
361 bool is64Bit() const { return TargetObjectWriter
->is64Bit(); }
362 bool nameShouldBeInStringTable(const StringRef
&);
363 void writeSymbolName(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
, const MCAsmLayout
&Layout
);
379 void writeSectionForControlSectionEntry(const MCAssembler
&Asm
,
380 const MCAsmLayout
&Layout
,
381 const CsectSectionEntry
&CsectEntry
,
382 uint64_t &CurrentAddressLocation
);
383 void writeSectionForDwarfSectionEntry(const MCAssembler
&Asm
,
384 const MCAsmLayout
&Layout
,
385 const DwarfSectionEntry
&DwarfEntry
,
386 uint64_t &CurrentAddressLocation
);
387 void writeSectionForExceptionSectionEntry(
388 const MCAssembler
&Asm
, const MCAsmLayout
&Layout
,
389 ExceptionSectionEntry
&ExceptionEntry
, uint64_t &CurrentAddressLocation
);
390 void writeSectionForCInfoSymSectionEntry(const MCAssembler
&Asm
,
391 const MCAsmLayout
&Layout
,
392 CInfoSymSectionEntry
&CInfoSymEntry
,
393 uint64_t &CurrentAddressLocation
);
394 void writeSymbolTable(const MCAsmLayout
&Layout
);
395 void writeSymbolAuxDwarfEntry(uint64_t LengthOfSectionPortion
,
396 uint64_t NumberOfRelocEnt
= 0);
397 void writeSymbolAuxCsectEntry(uint64_t SectionOrLength
,
398 uint8_t SymbolAlignmentAndType
,
399 uint8_t StorageMappingClass
);
400 void writeSymbolAuxFunctionEntry(uint32_t EntryOffset
, uint32_t FunctionSize
,
401 uint64_t LineNumberPointer
,
403 void writeSymbolAuxExceptionEntry(uint64_t EntryOffset
, uint32_t FunctionSize
,
405 void writeSymbolEntry(StringRef SymbolName
, uint64_t Value
,
406 int16_t SectionNumber
, uint16_t SymbolType
,
407 uint8_t StorageClass
, uint8_t NumberOfAuxEntries
= 1);
408 void writeRelocations();
409 void writeRelocation(XCOFFRelocation Reloc
, const XCOFFSection
&Section
);
411 // Called after all the csects and symbols have been processed by
412 // `executePostLayoutBinding`, this function handles building up the majority
413 // of the structures in the object file representation. Namely:
414 // *) Calculates physical/virtual addresses, raw-pointer offsets, and section
416 // *) Assigns symbol table indices.
417 // *) Builds up the section header table by adding any non-empty sections to
419 void assignAddressesAndIndices(const MCAsmLayout
&);
420 // Called after relocations are recorded.
421 void finalizeSectionInfo();
422 void finalizeRelocationInfo(SectionEntry
*Sec
, uint64_t RelCount
);
423 void calcOffsetToRelocations(SectionEntry
*Sec
, uint64_t &RawPointer
);
425 void addExceptionEntry(const MCSymbol
*Symbol
, const MCSymbol
*Trap
,
426 unsigned LanguageCode
, unsigned ReasonCode
,
427 unsigned FunctionSize
, bool hasDebug
) override
;
428 bool hasExceptionSection() {
429 return !ExceptionSection
.ExceptionTable
.empty();
431 unsigned getExceptionSectionSize();
432 unsigned getExceptionOffset(const MCSymbol
*Symbol
);
434 void addCInfoSymEntry(StringRef Name
, StringRef Metadata
) override
;
435 size_t auxiliaryHeaderSize() const {
436 // 64-bit object files have no auxiliary header.
437 return HasVisibility
&& !is64Bit() ? XCOFF::AuxFileHeaderSizeShort
: 0;
441 XCOFFObjectWriter(std::unique_ptr
<MCXCOFFObjectTargetWriter
> MOTW
,
442 raw_pwrite_stream
&OS
);
444 void writeWord(uint64_t Word
) {
445 is64Bit() ? W
.write
<uint64_t>(Word
) : W
.write
<uint32_t>(Word
);
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.");
537 assert(XCOFF::XTY_SD
== MCSec
->getCSectType() &&
538 "Only an initialized csect can contain TC entry.");
539 assert(!TOCCsects
.empty() &&
540 "We should at least have a TOC-base in this CsectGroup.");
543 report_fatal_error("Unhandled mapping of csect to section.");
547 static MCSectionXCOFF
*getContainingCsect(const MCSymbolXCOFF
*XSym
) {
548 if (XSym
->isDefined())
549 return cast
<MCSectionXCOFF
>(XSym
->getFragment()->getParent());
550 return XSym
->getRepresentedCsect();
553 void XCOFFObjectWriter::executePostLayoutBinding(MCAssembler
&Asm
,
554 const MCAsmLayout
&Layout
) {
555 for (const auto &S
: Asm
) {
556 const auto *MCSec
= cast
<const MCSectionXCOFF
>(&S
);
557 assert(!SectionMap
.contains(MCSec
) && "Cannot add a section twice.");
559 // If the name does not fit in the storage provided in the symbol table
560 // entry, add it to the string table.
561 if (nameShouldBeInStringTable(MCSec
->getSymbolTableName()))
562 Strings
.add(MCSec
->getSymbolTableName());
563 if (MCSec
->isCsect()) {
564 // A new control section. Its CsectSectionEntry should already be staticly
565 // generated as Text/Data/BSS/TDATA/TBSS. Add this section to the group of
566 // the CsectSectionEntry.
567 assert(XCOFF::XTY_ER
!= MCSec
->getCSectType() &&
568 "An undefined csect should not get registered.");
569 CsectGroup
&Group
= getCsectGroup(MCSec
);
570 Group
.emplace_back(MCSec
);
571 SectionMap
[MCSec
] = &Group
.back();
572 } else if (MCSec
->isDwarfSect()) {
573 // A new DwarfSectionEntry.
574 std::unique_ptr
<XCOFFSection
> DwarfSec
=
575 std::make_unique
<XCOFFSection
>(MCSec
);
576 SectionMap
[MCSec
] = DwarfSec
.get();
578 DwarfSectionEntry
SecEntry(MCSec
->getName(),
579 *MCSec
->getDwarfSubtypeFlags(),
580 std::move(DwarfSec
));
581 DwarfSections
.push_back(std::move(SecEntry
));
583 llvm_unreachable("unsupport section type!");
586 for (const MCSymbol
&S
: Asm
.symbols()) {
587 // Nothing to do for temporary symbols.
591 const MCSymbolXCOFF
*XSym
= cast
<MCSymbolXCOFF
>(&S
);
592 const MCSectionXCOFF
*ContainingCsect
= getContainingCsect(XSym
);
594 if (XSym
->getVisibilityType() != XCOFF::SYM_V_UNSPECIFIED
)
595 HasVisibility
= true;
597 if (ContainingCsect
->getCSectType() == XCOFF::XTY_ER
) {
598 // Handle undefined symbol.
599 UndefinedCsects
.emplace_back(ContainingCsect
);
600 SectionMap
[ContainingCsect
] = &UndefinedCsects
.back();
601 if (nameShouldBeInStringTable(ContainingCsect
->getSymbolTableName()))
602 Strings
.add(ContainingCsect
->getSymbolTableName());
606 // If the symbol is the csect itself, we don't need to put the symbol
607 // into csect's Syms.
608 if (XSym
== ContainingCsect
->getQualNameSymbol())
611 // Only put a label into the symbol table when it is an external label.
612 if (!XSym
->isExternal())
615 assert(SectionMap
.contains(ContainingCsect
) &&
616 "Expected containing csect to exist in map");
617 XCOFFSection
*Csect
= SectionMap
[ContainingCsect
];
618 // Lookup the containing csect and add the symbol to it.
619 assert(Csect
->MCSec
->isCsect() && "only csect is supported now!");
620 Csect
->Syms
.emplace_back(XSym
);
622 // If the name does not fit in the storage provided in the symbol table
623 // entry, add it to the string table.
624 if (nameShouldBeInStringTable(XSym
->getSymbolTableName()))
625 Strings
.add(XSym
->getSymbolTableName());
628 std::unique_ptr
<CInfoSymInfo
> &CISI
= CInfoSymSection
.Entry
;
629 if (CISI
&& nameShouldBeInStringTable(CISI
->Name
))
630 Strings
.add(CISI
->Name
);
632 FileNames
= Asm
.getFileNames();
633 // Emit ".file" as the source file name when there is no file name.
634 if (FileNames
.empty())
635 FileNames
.emplace_back(".file", 0);
636 for (const std::pair
<std::string
, size_t> &F
: FileNames
) {
637 if (nameShouldBeInStringTable(F
.first
))
638 Strings
.add(F
.first
);
642 assignAddressesAndIndices(Layout
);
645 void XCOFFObjectWriter::recordRelocation(MCAssembler
&Asm
,
646 const MCAsmLayout
&Layout
,
647 const MCFragment
*Fragment
,
648 const MCFixup
&Fixup
, MCValue Target
,
649 uint64_t &FixedValue
) {
650 auto getIndex
= [this](const MCSymbol
*Sym
,
651 const MCSectionXCOFF
*ContainingCsect
) {
652 // If we could not find the symbol directly in SymbolIndexMap, this symbol
653 // could either be a temporary symbol or an undefined symbol. In this case,
654 // we would need to have the relocation reference its csect instead.
655 return SymbolIndexMap
.contains(Sym
)
656 ? SymbolIndexMap
[Sym
]
657 : SymbolIndexMap
[ContainingCsect
->getQualNameSymbol()];
660 auto getVirtualAddress
=
661 [this, &Layout
](const MCSymbol
*Sym
,
662 const MCSectionXCOFF
*ContainingSect
) -> uint64_t {
664 if (ContainingSect
->isDwarfSect())
665 return Layout
.getSymbolOffset(*Sym
);
668 if (!Sym
->isDefined())
669 return SectionMap
[ContainingSect
]->Address
;
672 assert(Sym
->isDefined() && "not a valid object that has address!");
673 return SectionMap
[ContainingSect
]->Address
+ Layout
.getSymbolOffset(*Sym
);
676 const MCSymbol
*const SymA
= &Target
.getSymA()->getSymbol();
678 MCAsmBackend
&Backend
= Asm
.getBackend();
679 bool IsPCRel
= Backend
.getFixupKindInfo(Fixup
.getKind()).Flags
&
680 MCFixupKindInfo::FKF_IsPCRel
;
684 std::tie(Type
, SignAndSize
) =
685 TargetObjectWriter
->getRelocTypeAndSignSize(Target
, Fixup
, IsPCRel
);
687 const MCSectionXCOFF
*SymASec
= getContainingCsect(cast
<MCSymbolXCOFF
>(SymA
));
688 assert(SectionMap
.contains(SymASec
) &&
689 "Expected containing csect to exist in map.");
691 assert((Fixup
.getOffset() <=
692 MaxRawDataSize
- Layout
.getFragmentOffset(Fragment
)) &&
693 "Fragment offset + fixup offset is overflowed.");
694 uint32_t FixupOffsetInCsect
=
695 Layout
.getFragmentOffset(Fragment
) + Fixup
.getOffset();
697 const uint32_t Index
= getIndex(SymA
, SymASec
);
698 if (Type
== XCOFF::RelocationType::R_POS
||
699 Type
== XCOFF::RelocationType::R_TLS
||
700 Type
== XCOFF::RelocationType::R_TLS_LE
||
701 Type
== XCOFF::RelocationType::R_TLS_IE
)
702 // The FixedValue should be symbol's virtual address in this object file
703 // plus any constant value that we might get.
704 FixedValue
= getVirtualAddress(SymA
, SymASec
) + Target
.getConstant();
705 else if (Type
== XCOFF::RelocationType::R_TLSM
)
706 // The FixedValue should always be zero since the region handle is only
707 // known at load time.
709 else if (Type
== XCOFF::RelocationType::R_TOC
||
710 Type
== XCOFF::RelocationType::R_TOCL
) {
711 // For non toc-data external symbols, R_TOC type relocation will relocate to
712 // data symbols that have XCOFF::XTY_SD type csect. For toc-data external
713 // symbols, R_TOC type relocation will relocate to data symbols that have
714 // XCOFF_ER type csect. For XCOFF_ER kind symbols, there will be no TOC
715 // entry for them, so the FixedValue should always be 0.
716 if (SymASec
->getCSectType() == XCOFF::XTY_ER
) {
719 // The FixedValue should be the TOC entry offset from the TOC-base plus
720 // any constant offset value.
721 const int64_t TOCEntryOffset
= SectionMap
[SymASec
]->Address
-
722 TOCCsects
.front().Address
+
723 Target
.getConstant();
724 if (Type
== XCOFF::RelocationType::R_TOC
&& !isInt
<16>(TOCEntryOffset
))
725 report_fatal_error("TOCEntryOffset overflows in small code model mode");
727 FixedValue
= TOCEntryOffset
;
729 } else if (Type
== XCOFF::RelocationType::R_RBR
) {
730 MCSectionXCOFF
*ParentSec
= cast
<MCSectionXCOFF
>(Fragment
->getParent());
731 assert((SymASec
->getMappingClass() == XCOFF::XMC_PR
&&
732 ParentSec
->getMappingClass() == XCOFF::XMC_PR
) &&
733 "Only XMC_PR csect may have the R_RBR relocation.");
735 // The address of the branch instruction should be the sum of section
736 // address, fragment offset and Fixup offset.
737 uint64_t BRInstrAddress
=
738 SectionMap
[ParentSec
]->Address
+ FixupOffsetInCsect
;
739 // The FixedValue should be the difference between symbol's virtual address
740 // and BR instr address plus any constant value.
741 FixedValue
= getVirtualAddress(SymA
, SymASec
) - BRInstrAddress
+
742 Target
.getConstant();
743 } else if (Type
== XCOFF::RelocationType::R_REF
) {
744 // The FixedValue and FixupOffsetInCsect should always be 0 since it
745 // specifies a nonrelocating reference.
747 FixupOffsetInCsect
= 0;
750 XCOFFRelocation Reloc
= {Index
, FixupOffsetInCsect
, SignAndSize
, Type
};
751 MCSectionXCOFF
*RelocationSec
= cast
<MCSectionXCOFF
>(Fragment
->getParent());
752 assert(SectionMap
.contains(RelocationSec
) &&
753 "Expected containing csect to exist in map.");
754 SectionMap
[RelocationSec
]->Relocations
.push_back(Reloc
);
756 if (!Target
.getSymB())
759 const MCSymbol
*const SymB
= &Target
.getSymB()->getSymbol();
761 report_fatal_error("relocation for opposite term is not yet supported");
763 const MCSectionXCOFF
*SymBSec
= getContainingCsect(cast
<MCSymbolXCOFF
>(SymB
));
764 assert(SectionMap
.contains(SymBSec
) &&
765 "Expected containing csect to exist in map.");
766 if (SymASec
== SymBSec
)
768 "relocation for paired relocatable term is not yet supported");
770 assert(Type
== XCOFF::RelocationType::R_POS
&&
771 "SymA must be R_POS here if it's not opposite term or paired "
772 "relocatable term.");
773 const uint32_t IndexB
= getIndex(SymB
, SymBSec
);
774 // SymB must be R_NEG here, given the general form of Target(MCValue) is
775 // "SymbolA - SymbolB + imm64".
776 const uint8_t TypeB
= XCOFF::RelocationType::R_NEG
;
777 XCOFFRelocation RelocB
= {IndexB
, FixupOffsetInCsect
, SignAndSize
, TypeB
};
778 SectionMap
[RelocationSec
]->Relocations
.push_back(RelocB
);
779 // We already folded "SymbolA + imm64" above when Type is R_POS for SymbolA,
780 // now we just need to fold "- SymbolB" here.
781 FixedValue
-= getVirtualAddress(SymB
, SymBSec
);
784 void XCOFFObjectWriter::writeSections(const MCAssembler
&Asm
,
785 const MCAsmLayout
&Layout
) {
786 uint64_t CurrentAddressLocation
= 0;
787 for (const auto *Section
: Sections
)
788 writeSectionForControlSectionEntry(Asm
, Layout
, *Section
,
789 CurrentAddressLocation
);
790 for (const auto &DwarfSection
: DwarfSections
)
791 writeSectionForDwarfSectionEntry(Asm
, Layout
, DwarfSection
,
792 CurrentAddressLocation
);
793 writeSectionForExceptionSectionEntry(Asm
, Layout
, ExceptionSection
,
794 CurrentAddressLocation
);
795 writeSectionForCInfoSymSectionEntry(Asm
, Layout
, CInfoSymSection
,
796 CurrentAddressLocation
);
799 uint64_t XCOFFObjectWriter::writeObject(MCAssembler
&Asm
,
800 const MCAsmLayout
&Layout
) {
801 // We always emit a timestamp of 0 for reproducibility, so ensure incremental
802 // linking is not enabled, in case, like with Windows COFF, such a timestamp
803 // is incompatible with incremental linking of XCOFF.
804 if (Asm
.isIncrementalLinkerCompatible())
805 report_fatal_error("Incremental linking not supported for XCOFF.");
807 finalizeSectionInfo();
808 uint64_t StartOffset
= W
.OS
.tell();
811 writeAuxFileHeader();
812 writeSectionHeaderTable();
813 writeSections(Asm
, Layout
);
815 writeSymbolTable(Layout
);
816 // Write the string table.
819 return W
.OS
.tell() - StartOffset
;
822 bool XCOFFObjectWriter::nameShouldBeInStringTable(const StringRef
&SymbolName
) {
823 return SymbolName
.size() > XCOFF::NameSize
|| is64Bit();
826 void XCOFFObjectWriter::writeSymbolName(const StringRef
&SymbolName
) {
827 // Magic, Offset or SymbolName.
828 if (nameShouldBeInStringTable(SymbolName
)) {
830 W
.write
<uint32_t>(Strings
.getOffset(SymbolName
));
832 char Name
[XCOFF::NameSize
+ 1];
833 std::strncpy(Name
, SymbolName
.data(), XCOFF::NameSize
);
834 ArrayRef
<char> NameRef(Name
, XCOFF::NameSize
);
839 void XCOFFObjectWriter::writeSymbolEntry(StringRef SymbolName
, uint64_t Value
,
840 int16_t SectionNumber
,
842 uint8_t StorageClass
,
843 uint8_t NumberOfAuxEntries
) {
845 W
.write
<uint64_t>(Value
);
846 W
.write
<uint32_t>(Strings
.getOffset(SymbolName
));
848 writeSymbolName(SymbolName
);
849 W
.write
<uint32_t>(Value
);
851 W
.write
<int16_t>(SectionNumber
);
852 W
.write
<uint16_t>(SymbolType
);
853 W
.write
<uint8_t>(StorageClass
);
854 W
.write
<uint8_t>(NumberOfAuxEntries
);
857 void XCOFFObjectWriter::writeSymbolAuxCsectEntry(uint64_t SectionOrLength
,
858 uint8_t SymbolAlignmentAndType
,
859 uint8_t StorageMappingClass
) {
860 W
.write
<uint32_t>(is64Bit() ? Lo_32(SectionOrLength
) : SectionOrLength
);
861 W
.write
<uint32_t>(0); // ParameterHashIndex
862 W
.write
<uint16_t>(0); // TypeChkSectNum
863 W
.write
<uint8_t>(SymbolAlignmentAndType
);
864 W
.write
<uint8_t>(StorageMappingClass
);
866 W
.write
<uint32_t>(Hi_32(SectionOrLength
));
867 W
.OS
.write_zeros(1); // Reserved
868 W
.write
<uint8_t>(XCOFF::AUX_CSECT
);
870 W
.write
<uint32_t>(0); // StabInfoIndex
871 W
.write
<uint16_t>(0); // StabSectNum
875 void XCOFFObjectWriter::writeSymbolAuxDwarfEntry(
876 uint64_t LengthOfSectionPortion
, uint64_t NumberOfRelocEnt
) {
877 writeWord(LengthOfSectionPortion
);
879 W
.OS
.write_zeros(4); // Reserved
880 writeWord(NumberOfRelocEnt
);
882 W
.OS
.write_zeros(1); // Reserved
883 W
.write
<uint8_t>(XCOFF::AUX_SECT
);
885 W
.OS
.write_zeros(6); // Reserved
889 void XCOFFObjectWriter::writeSymbolEntryForCsectMemberLabel(
890 const Symbol
&SymbolRef
, const XCOFFSection
&CSectionRef
,
891 int16_t SectionIndex
, uint64_t SymbolOffset
) {
892 assert(SymbolOffset
<= MaxRawDataSize
- CSectionRef
.Address
&&
893 "Symbol address overflowed.");
895 auto Entry
= ExceptionSection
.ExceptionTable
.find(SymbolRef
.MCSym
->getName());
896 if (Entry
!= ExceptionSection
.ExceptionTable
.end()) {
897 writeSymbolEntry(SymbolRef
.getSymbolTableName(),
898 CSectionRef
.Address
+ SymbolOffset
, SectionIndex
,
899 // In the old version of the 32-bit XCOFF interpretation,
900 // symbols may require bit 10 (0x0020) to be set if the
901 // symbol is a function, otherwise the bit should be 0.
902 is64Bit() ? SymbolRef
.getVisibilityType()
903 : SymbolRef
.getVisibilityType() | 0x0020,
904 SymbolRef
.getStorageClass(),
905 (is64Bit() && ExceptionSection
.isDebugEnabled
) ? 3 : 2);
906 if (is64Bit() && ExceptionSection
.isDebugEnabled
) {
907 // On 64 bit with debugging enabled, we have a csect, exception, and
908 // function auxilliary entries, so we must increment symbol index by 4.
909 writeSymbolAuxExceptionEntry(
910 ExceptionSection
.FileOffsetToData
+
911 getExceptionOffset(Entry
->second
.FunctionSymbol
),
912 Entry
->second
.FunctionSize
,
913 SymbolIndexMap
[Entry
->second
.FunctionSymbol
] + 4);
915 // For exception section entries, csect and function auxilliary entries
916 // must exist. On 64-bit there is also an exception auxilliary entry.
917 writeSymbolAuxFunctionEntry(
918 ExceptionSection
.FileOffsetToData
+
919 getExceptionOffset(Entry
->second
.FunctionSymbol
),
920 Entry
->second
.FunctionSize
, 0,
921 (is64Bit() && ExceptionSection
.isDebugEnabled
)
922 ? SymbolIndexMap
[Entry
->second
.FunctionSymbol
] + 4
923 : SymbolIndexMap
[Entry
->second
.FunctionSymbol
] + 3);
925 writeSymbolEntry(SymbolRef
.getSymbolTableName(),
926 CSectionRef
.Address
+ SymbolOffset
, SectionIndex
,
927 SymbolRef
.getVisibilityType(),
928 SymbolRef
.getStorageClass());
930 writeSymbolAuxCsectEntry(CSectionRef
.SymbolTableIndex
, XCOFF::XTY_LD
,
931 CSectionRef
.MCSec
->getMappingClass());
934 void XCOFFObjectWriter::writeSymbolEntryForDwarfSection(
935 const XCOFFSection
&DwarfSectionRef
, int16_t SectionIndex
) {
936 assert(DwarfSectionRef
.MCSec
->isDwarfSect() && "Not a DWARF section!");
938 writeSymbolEntry(DwarfSectionRef
.getSymbolTableName(), /*Value=*/0,
939 SectionIndex
, /*SymbolType=*/0, XCOFF::C_DWARF
);
941 writeSymbolAuxDwarfEntry(DwarfSectionRef
.Size
);
944 void XCOFFObjectWriter::writeSymbolEntryForControlSection(
945 const XCOFFSection
&CSectionRef
, int16_t SectionIndex
,
946 XCOFF::StorageClass StorageClass
) {
947 writeSymbolEntry(CSectionRef
.getSymbolTableName(), CSectionRef
.Address
,
948 SectionIndex
, CSectionRef
.getVisibilityType(), StorageClass
);
950 writeSymbolAuxCsectEntry(CSectionRef
.Size
, getEncodedType(CSectionRef
.MCSec
),
951 CSectionRef
.MCSec
->getMappingClass());
954 void XCOFFObjectWriter::writeSymbolAuxFunctionEntry(uint32_t EntryOffset
,
955 uint32_t FunctionSize
,
956 uint64_t LineNumberPointer
,
959 writeWord(LineNumberPointer
);
961 W
.write
<uint32_t>(EntryOffset
);
962 W
.write
<uint32_t>(FunctionSize
);
964 writeWord(LineNumberPointer
);
965 W
.write
<uint32_t>(EndIndex
);
968 W
.write
<uint8_t>(XCOFF::AUX_FCN
);
974 void XCOFFObjectWriter::writeSymbolAuxExceptionEntry(uint64_t EntryOffset
,
975 uint32_t FunctionSize
,
977 assert(is64Bit() && "Exception auxilliary entries are 64-bit only.");
978 W
.write
<uint64_t>(EntryOffset
);
979 W
.write
<uint32_t>(FunctionSize
);
980 W
.write
<uint32_t>(EndIndex
);
981 W
.OS
.write_zeros(1); // Pad (unused)
982 W
.write
<uint8_t>(XCOFF::AUX_EXCEPT
);
985 void XCOFFObjectWriter::writeFileHeader() {
986 W
.write
<uint16_t>(is64Bit() ? XCOFF::XCOFF64
: XCOFF::XCOFF32
);
987 W
.write
<uint16_t>(SectionCount
);
988 W
.write
<int32_t>(0); // TimeStamp
989 writeWord(SymbolTableOffset
);
991 W
.write
<uint16_t>(auxiliaryHeaderSize());
992 W
.write
<uint16_t>(0); // Flags
993 W
.write
<int32_t>(SymbolTableEntryCount
);
995 W
.write
<int32_t>(SymbolTableEntryCount
);
996 W
.write
<uint16_t>(auxiliaryHeaderSize());
997 W
.write
<uint16_t>(0); // Flags
1001 void XCOFFObjectWriter::writeAuxFileHeader() {
1002 if (!auxiliaryHeaderSize())
1004 W
.write
<uint16_t>(0); // Magic
1006 XCOFF::NEW_XCOFF_INTERPRET
); // Version. The new interpretation of the
1007 // n_type field in the symbol table entry is
1009 W
.write
<uint32_t>(Sections
[0]->Size
); // TextSize
1010 W
.write
<uint32_t>(Sections
[1]->Size
); // InitDataSize
1011 W
.write
<uint32_t>(Sections
[2]->Size
); // BssDataSize
1012 W
.write
<uint32_t>(0); // EntryPointAddr
1013 W
.write
<uint32_t>(Sections
[0]->Address
); // TextStartAddr
1014 W
.write
<uint32_t>(Sections
[1]->Address
); // DataStartAddr
1017 void XCOFFObjectWriter::writeSectionHeader(const SectionEntry
*Sec
) {
1018 bool IsDwarf
= (Sec
->Flags
& XCOFF::STYP_DWARF
) != 0;
1019 bool IsOvrflo
= (Sec
->Flags
& XCOFF::STYP_OVRFLO
) != 0;
1020 // Nothing to write for this Section.
1021 if (Sec
->Index
== SectionEntry::UninitializedIndex
)
1025 ArrayRef
<char> NameRef(Sec
->Name
, XCOFF::NameSize
);
1028 // Write the Physical Address and Virtual Address.
1029 // We use 0 for DWARF sections' Physical and Virtual Addresses.
1030 writeWord(IsDwarf
? 0 : Sec
->Address
);
1031 // Since line number is not supported, we set it to 0 for overflow sections.
1032 writeWord((IsDwarf
|| IsOvrflo
) ? 0 : Sec
->Address
);
1034 writeWord(Sec
->Size
);
1035 writeWord(Sec
->FileOffsetToData
);
1036 writeWord(Sec
->FileOffsetToRelocations
);
1037 writeWord(0); // FileOffsetToLineNumberInfo. Not supported yet.
1040 W
.write
<uint32_t>(Sec
->RelocationCount
);
1041 W
.write
<uint32_t>(0); // NumberOfLineNumbers. Not supported yet.
1042 W
.write
<int32_t>(Sec
->Flags
);
1043 W
.OS
.write_zeros(4);
1045 // For the overflow section header, s_nreloc provides a reference to the
1046 // primary section header and s_nlnno must have the same value.
1047 // For common section headers, if either of s_nreloc or s_nlnno are set to
1048 // 65535, the other one must also be set to 65535.
1049 W
.write
<uint16_t>(Sec
->RelocationCount
);
1050 W
.write
<uint16_t>((IsOvrflo
|| Sec
->RelocationCount
== XCOFF::RelocOverflow
)
1051 ? Sec
->RelocationCount
1052 : 0); // NumberOfLineNumbers. Not supported yet.
1053 W
.write
<int32_t>(Sec
->Flags
);
1057 void XCOFFObjectWriter::writeSectionHeaderTable() {
1058 for (const auto *CsectSec
: Sections
)
1059 writeSectionHeader(CsectSec
);
1060 for (const auto &DwarfSec
: DwarfSections
)
1061 writeSectionHeader(&DwarfSec
);
1062 for (const auto &OverflowSec
: OverflowSections
)
1063 writeSectionHeader(&OverflowSec
);
1064 if (hasExceptionSection())
1065 writeSectionHeader(&ExceptionSection
);
1066 if (CInfoSymSection
.Entry
)
1067 writeSectionHeader(&CInfoSymSection
);
1070 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc
,
1071 const XCOFFSection
&Section
) {
1072 if (Section
.MCSec
->isCsect())
1073 writeWord(Section
.Address
+ Reloc
.FixupOffsetInCsect
);
1075 // DWARF sections' address is set to 0.
1076 assert(Section
.MCSec
->isDwarfSect() && "unsupport section type!");
1077 writeWord(Reloc
.FixupOffsetInCsect
);
1079 W
.write
<uint32_t>(Reloc
.SymbolTableIndex
);
1080 W
.write
<uint8_t>(Reloc
.SignAndSize
);
1081 W
.write
<uint8_t>(Reloc
.Type
);
1084 void XCOFFObjectWriter::writeRelocations() {
1085 for (const auto *Section
: Sections
) {
1086 if (Section
->Index
== SectionEntry::UninitializedIndex
)
1087 // Nothing to write for this Section.
1090 for (const auto *Group
: Section
->Groups
) {
1094 for (const auto &Csect
: *Group
) {
1095 for (const auto Reloc
: Csect
.Relocations
)
1096 writeRelocation(Reloc
, Csect
);
1101 for (const auto &DwarfSection
: DwarfSections
)
1102 for (const auto &Reloc
: DwarfSection
.DwarfSect
->Relocations
)
1103 writeRelocation(Reloc
, *DwarfSection
.DwarfSect
);
1106 void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout
&Layout
) {
1107 // Write C_FILE symbols.
1108 for (const std::pair
<std::string
, size_t> &F
: FileNames
) {
1109 // The n_name of a C_FILE symbol is the source file's name when no auxiliary
1110 // entries are present.
1111 StringRef FileName
= F
.first
;
1113 // For C_FILE symbols, the Source Language ID overlays the high-order byte
1114 // of the SymbolType field, and the CPU Version ID is defined as the
1116 // AIX's system assembler determines the source language ID based on the
1117 // source file's name suffix, and the behavior here is consistent with it.
1119 if (FileName
.ends_with(".c"))
1120 LangID
= XCOFF::TB_C
;
1121 else if (FileName
.ends_with_insensitive(".f") ||
1122 FileName
.ends_with_insensitive(".f77") ||
1123 FileName
.ends_with_insensitive(".f90") ||
1124 FileName
.ends_with_insensitive(".f95") ||
1125 FileName
.ends_with_insensitive(".f03") ||
1126 FileName
.ends_with_insensitive(".f08"))
1127 LangID
= XCOFF::TB_Fortran
;
1129 LangID
= XCOFF::TB_CPLUSPLUS
;
1132 CpuID
= XCOFF::TCPU_PPC64
;
1134 CpuID
= XCOFF::TCPU_COM
;
1136 writeSymbolEntry(FileName
, /*Value=*/0, XCOFF::ReservedSectionNum::N_DEBUG
,
1137 /*SymbolType=*/(LangID
<< 8) | CpuID
, XCOFF::C_FILE
,
1138 /*NumberOfAuxEntries=*/0);
1141 if (CInfoSymSection
.Entry
)
1142 writeSymbolEntry(CInfoSymSection
.Entry
->Name
, CInfoSymSection
.Entry
->Offset
,
1143 CInfoSymSection
.Index
,
1144 /*SymbolType=*/0, XCOFF::C_INFO
,
1145 /*NumberOfAuxEntries=*/0);
1147 for (const auto &Csect
: UndefinedCsects
) {
1148 writeSymbolEntryForControlSection(Csect
, XCOFF::ReservedSectionNum::N_UNDEF
,
1149 Csect
.MCSec
->getStorageClass());
1152 for (const auto *Section
: Sections
) {
1153 if (Section
->Index
== SectionEntry::UninitializedIndex
)
1154 // Nothing to write for this Section.
1157 for (const auto *Group
: Section
->Groups
) {
1161 const int16_t SectionIndex
= Section
->Index
;
1162 for (const auto &Csect
: *Group
) {
1163 // Write out the control section first and then each symbol in it.
1164 writeSymbolEntryForControlSection(Csect
, SectionIndex
,
1165 Csect
.MCSec
->getStorageClass());
1167 for (const auto &Sym
: Csect
.Syms
)
1168 writeSymbolEntryForCsectMemberLabel(
1169 Sym
, Csect
, SectionIndex
, Layout
.getSymbolOffset(*(Sym
.MCSym
)));
1174 for (const auto &DwarfSection
: DwarfSections
)
1175 writeSymbolEntryForDwarfSection(*DwarfSection
.DwarfSect
,
1176 DwarfSection
.Index
);
1179 void XCOFFObjectWriter::finalizeRelocationInfo(SectionEntry
*Sec
,
1180 uint64_t RelCount
) {
1181 // Handles relocation field overflows in an XCOFF32 file. An XCOFF64 file
1182 // may not contain an overflow section header.
1183 if (!is64Bit() && (RelCount
>= static_cast<uint32_t>(XCOFF::RelocOverflow
))) {
1184 // Generate an overflow section header.
1185 SectionEntry
SecEntry(".ovrflo", XCOFF::STYP_OVRFLO
);
1187 // This field specifies the file section number of the section header that
1189 SecEntry
.RelocationCount
= Sec
->Index
;
1191 // This field specifies the number of relocation entries actually
1193 SecEntry
.Address
= RelCount
;
1194 SecEntry
.Index
= ++SectionCount
;
1195 OverflowSections
.push_back(std::move(SecEntry
));
1197 // The field in the primary section header is always 65535
1198 // (XCOFF::RelocOverflow).
1199 Sec
->RelocationCount
= XCOFF::RelocOverflow
;
1201 Sec
->RelocationCount
= RelCount
;
1205 void XCOFFObjectWriter::calcOffsetToRelocations(SectionEntry
*Sec
,
1206 uint64_t &RawPointer
) {
1207 if (!Sec
->RelocationCount
)
1210 Sec
->FileOffsetToRelocations
= RawPointer
;
1211 uint64_t RelocationSizeInSec
= 0;
1213 Sec
->RelocationCount
== static_cast<uint32_t>(XCOFF::RelocOverflow
)) {
1214 // Find its corresponding overflow section.
1215 for (auto &OverflowSec
: OverflowSections
) {
1216 if (OverflowSec
.RelocationCount
== static_cast<uint32_t>(Sec
->Index
)) {
1217 RelocationSizeInSec
=
1218 OverflowSec
.Address
* XCOFF::RelocationSerializationSize32
;
1220 // This field must have the same values as in the corresponding
1221 // primary section header.
1222 OverflowSec
.FileOffsetToRelocations
= Sec
->FileOffsetToRelocations
;
1225 assert(RelocationSizeInSec
&& "Overflow section header doesn't exist.");
1227 RelocationSizeInSec
= Sec
->RelocationCount
*
1228 (is64Bit() ? XCOFF::RelocationSerializationSize64
1229 : XCOFF::RelocationSerializationSize32
);
1232 RawPointer
+= RelocationSizeInSec
;
1233 if (RawPointer
> MaxRawDataSize
)
1234 report_fatal_error("Relocation data overflowed this object file.");
1237 void XCOFFObjectWriter::finalizeSectionInfo() {
1238 for (auto *Section
: Sections
) {
1239 if (Section
->Index
== SectionEntry::UninitializedIndex
)
1240 // Nothing to record for this Section.
1243 uint64_t RelCount
= 0;
1244 for (const auto *Group
: Section
->Groups
) {
1248 for (auto &Csect
: *Group
)
1249 RelCount
+= Csect
.Relocations
.size();
1251 finalizeRelocationInfo(Section
, RelCount
);
1254 for (auto &DwarfSection
: DwarfSections
)
1255 finalizeRelocationInfo(&DwarfSection
,
1256 DwarfSection
.DwarfSect
->Relocations
.size());
1258 // Calculate the RawPointer value for all headers.
1259 uint64_t RawPointer
=
1260 (is64Bit() ? (XCOFF::FileHeaderSize64
+
1261 SectionCount
* XCOFF::SectionHeaderSize64
)
1262 : (XCOFF::FileHeaderSize32
+
1263 SectionCount
* XCOFF::SectionHeaderSize32
)) +
1264 auxiliaryHeaderSize();
1266 // Calculate the file offset to the section data.
1267 for (auto *Sec
: Sections
) {
1268 if (Sec
->Index
== SectionEntry::UninitializedIndex
|| Sec
->IsVirtual
)
1271 RawPointer
= Sec
->advanceFileOffset(MaxRawDataSize
, RawPointer
);
1274 if (!DwarfSections
.empty()) {
1275 RawPointer
+= PaddingsBeforeDwarf
;
1276 for (auto &DwarfSection
: DwarfSections
) {
1277 RawPointer
= DwarfSection
.advanceFileOffset(MaxRawDataSize
, RawPointer
);
1281 if (hasExceptionSection())
1282 RawPointer
= ExceptionSection
.advanceFileOffset(MaxRawDataSize
, RawPointer
);
1284 if (CInfoSymSection
.Entry
)
1285 RawPointer
= CInfoSymSection
.advanceFileOffset(MaxRawDataSize
, RawPointer
);
1287 for (auto *Sec
: Sections
) {
1288 if (Sec
->Index
!= SectionEntry::UninitializedIndex
)
1289 calcOffsetToRelocations(Sec
, RawPointer
);
1292 for (auto &DwarfSec
: DwarfSections
)
1293 calcOffsetToRelocations(&DwarfSec
, RawPointer
);
1295 // TODO Error check that the number of symbol table entries fits in 32-bits
1297 if (SymbolTableEntryCount
)
1298 SymbolTableOffset
= RawPointer
;
1301 void XCOFFObjectWriter::addExceptionEntry(
1302 const MCSymbol
*Symbol
, const MCSymbol
*Trap
, unsigned LanguageCode
,
1303 unsigned ReasonCode
, unsigned FunctionSize
, bool hasDebug
) {
1304 // If a module had debug info, debugging is enabled and XCOFF emits the
1305 // exception auxilliary entry.
1307 ExceptionSection
.isDebugEnabled
= true;
1308 auto Entry
= ExceptionSection
.ExceptionTable
.find(Symbol
->getName());
1309 if (Entry
!= ExceptionSection
.ExceptionTable
.end()) {
1310 Entry
->second
.Entries
.push_back(
1311 ExceptionTableEntry(Trap
, LanguageCode
, ReasonCode
));
1314 ExceptionInfo NewEntry
;
1315 NewEntry
.FunctionSymbol
= Symbol
;
1316 NewEntry
.FunctionSize
= FunctionSize
;
1317 NewEntry
.Entries
.push_back(
1318 ExceptionTableEntry(Trap
, LanguageCode
, ReasonCode
));
1319 ExceptionSection
.ExceptionTable
.insert(
1320 std::pair
<const StringRef
, ExceptionInfo
>(Symbol
->getName(), NewEntry
));
1323 unsigned XCOFFObjectWriter::getExceptionSectionSize() {
1324 unsigned EntryNum
= 0;
1326 for (auto it
= ExceptionSection
.ExceptionTable
.begin();
1327 it
!= ExceptionSection
.ExceptionTable
.end(); ++it
)
1328 // The size() gets +1 to account for the initial entry containing the
1329 // symbol table index.
1330 EntryNum
+= it
->second
.Entries
.size() + 1;
1332 return EntryNum
* (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
1333 : XCOFF::ExceptionSectionEntrySize32
);
1336 unsigned XCOFFObjectWriter::getExceptionOffset(const MCSymbol
*Symbol
) {
1337 unsigned EntryNum
= 0;
1338 for (auto it
= ExceptionSection
.ExceptionTable
.begin();
1339 it
!= ExceptionSection
.ExceptionTable
.end(); ++it
) {
1340 if (Symbol
== it
->second
.FunctionSymbol
)
1342 EntryNum
+= it
->second
.Entries
.size() + 1;
1344 return EntryNum
* (is64Bit() ? XCOFF::ExceptionSectionEntrySize64
1345 : XCOFF::ExceptionSectionEntrySize32
);
1348 void XCOFFObjectWriter::addCInfoSymEntry(StringRef Name
, StringRef Metadata
) {
1349 assert(!CInfoSymSection
.Entry
&& "Multiple entries are not supported");
1350 CInfoSymSection
.addEntry(
1351 std::make_unique
<CInfoSymInfo
>(Name
.str(), Metadata
.str()));
1354 void XCOFFObjectWriter::assignAddressesAndIndices(const MCAsmLayout
&Layout
) {
1355 // The symbol table starts with all the C_FILE symbols.
1356 uint32_t SymbolTableIndex
= FileNames
.size();
1358 if (CInfoSymSection
.Entry
)
1361 // Calculate indices for undefined symbols.
1362 for (auto &Csect
: UndefinedCsects
) {
1365 Csect
.SymbolTableIndex
= SymbolTableIndex
;
1366 SymbolIndexMap
[Csect
.MCSec
->getQualNameSymbol()] = Csect
.SymbolTableIndex
;
1367 // 1 main and 1 auxiliary symbol table entry for each contained symbol.
1368 SymbolTableIndex
+= 2;
1371 // The address corrresponds to the address of sections and symbols in the
1372 // object file. We place the shared address 0 immediately after the
1373 // section header table.
1374 uint64_t Address
= 0;
1375 // Section indices are 1-based in XCOFF.
1376 int32_t SectionIndex
= 1;
1377 bool HasTDataSection
= false;
1379 for (auto *Section
: Sections
) {
1380 const bool IsEmpty
=
1381 llvm::all_of(Section
->Groups
,
1382 [](const CsectGroup
*Group
) { return Group
->empty(); });
1386 if (SectionIndex
> MaxSectionIndex
)
1387 report_fatal_error("Section index overflow!");
1388 Section
->Index
= SectionIndex
++;
1391 bool SectionAddressSet
= false;
1392 // Reset the starting address to 0 for TData section.
1393 if (Section
->Flags
== XCOFF::STYP_TDATA
) {
1395 HasTDataSection
= true;
1397 // Reset the starting address to 0 for TBSS section if the object file does
1398 // not contain TData Section.
1399 if ((Section
->Flags
== XCOFF::STYP_TBSS
) && !HasTDataSection
)
1402 for (auto *Group
: Section
->Groups
) {
1406 for (auto &Csect
: *Group
) {
1407 const MCSectionXCOFF
*MCSec
= Csect
.MCSec
;
1408 Csect
.Address
= alignTo(Address
, MCSec
->getAlign());
1409 Csect
.Size
= Layout
.getSectionAddressSize(MCSec
);
1410 Address
= Csect
.Address
+ Csect
.Size
;
1411 Csect
.SymbolTableIndex
= SymbolTableIndex
;
1412 SymbolIndexMap
[MCSec
->getQualNameSymbol()] = Csect
.SymbolTableIndex
;
1413 // 1 main and 1 auxiliary symbol table entry for the csect.
1414 SymbolTableIndex
+= 2;
1416 for (auto &Sym
: Csect
.Syms
) {
1417 bool hasExceptEntry
= false;
1419 ExceptionSection
.ExceptionTable
.find(Sym
.MCSym
->getName());
1420 if (Entry
!= ExceptionSection
.ExceptionTable
.end()) {
1421 hasExceptEntry
= true;
1422 for (auto &TrapEntry
: Entry
->second
.Entries
) {
1423 TrapEntry
.TrapAddress
= Layout
.getSymbolOffset(*(Sym
.MCSym
)) +
1424 TrapEntry
.Trap
->getOffset();
1427 Sym
.SymbolTableIndex
= SymbolTableIndex
;
1428 SymbolIndexMap
[Sym
.MCSym
] = Sym
.SymbolTableIndex
;
1429 // 1 main and 1 auxiliary symbol table entry for each contained
1430 // symbol. For symbols with exception section entries, a function
1431 // auxilliary entry is needed, and on 64-bit XCOFF with debugging
1432 // enabled, an additional exception auxilliary entry is needed.
1433 SymbolTableIndex
+= 2;
1434 if (hasExceptionSection() && hasExceptEntry
) {
1435 if (is64Bit() && ExceptionSection
.isDebugEnabled
)
1436 SymbolTableIndex
+= 2;
1438 SymbolTableIndex
+= 1;
1443 if (!SectionAddressSet
) {
1444 Section
->Address
= Group
->front().Address
;
1445 SectionAddressSet
= true;
1449 // Make sure the address of the next section aligned to
1450 // DefaultSectionAlign.
1451 Address
= alignTo(Address
, DefaultSectionAlign
);
1452 Section
->Size
= Address
- Section
->Address
;
1455 // Start to generate DWARF sections. Sections other than DWARF section use
1456 // DefaultSectionAlign as the default alignment, while DWARF sections have
1457 // their own alignments. If these two alignments are not the same, we need
1458 // some paddings here and record the paddings bytes for FileOffsetToData
1460 if (!DwarfSections
.empty())
1461 PaddingsBeforeDwarf
=
1463 (*DwarfSections
.begin()).DwarfSect
->MCSec
->getAlign()) -
1466 DwarfSectionEntry
*LastDwarfSection
= nullptr;
1467 for (auto &DwarfSection
: DwarfSections
) {
1468 assert((SectionIndex
<= MaxSectionIndex
) && "Section index overflow!");
1470 XCOFFSection
&DwarfSect
= *DwarfSection
.DwarfSect
;
1471 const MCSectionXCOFF
*MCSec
= DwarfSect
.MCSec
;
1474 DwarfSection
.Index
= SectionIndex
++;
1478 DwarfSect
.SymbolTableIndex
= SymbolTableIndex
;
1479 SymbolIndexMap
[MCSec
->getQualNameSymbol()] = DwarfSect
.SymbolTableIndex
;
1480 // 1 main and 1 auxiliary symbol table entry for the csect.
1481 SymbolTableIndex
+= 2;
1483 // Section address. Make it align to section alignment.
1484 // We use address 0 for DWARF sections' Physical and Virtual Addresses.
1485 // This address is used to tell where is the section in the final object.
1486 // See writeSectionForDwarfSectionEntry().
1487 DwarfSection
.Address
= DwarfSect
.Address
=
1488 alignTo(Address
, MCSec
->getAlign());
1491 // For DWARF section, we must use the real size which may be not aligned.
1492 DwarfSection
.Size
= DwarfSect
.Size
= Layout
.getSectionAddressSize(MCSec
);
1494 Address
= DwarfSection
.Address
+ DwarfSection
.Size
;
1496 if (LastDwarfSection
)
1497 LastDwarfSection
->MemorySize
=
1498 DwarfSection
.Address
- LastDwarfSection
->Address
;
1499 LastDwarfSection
= &DwarfSection
;
1501 if (LastDwarfSection
) {
1502 // Make the final DWARF section address align to the default section
1503 // alignment for follow contents.
1504 Address
= alignTo(LastDwarfSection
->Address
+ LastDwarfSection
->Size
,
1505 DefaultSectionAlign
);
1506 LastDwarfSection
->MemorySize
= Address
- LastDwarfSection
->Address
;
1508 if (hasExceptionSection()) {
1509 ExceptionSection
.Index
= SectionIndex
++;
1511 ExceptionSection
.Address
= 0;
1512 ExceptionSection
.Size
= getExceptionSectionSize();
1513 Address
+= ExceptionSection
.Size
;
1514 Address
= alignTo(Address
, DefaultSectionAlign
);
1517 if (CInfoSymSection
.Entry
) {
1518 CInfoSymSection
.Index
= SectionIndex
++;
1520 CInfoSymSection
.Address
= 0;
1521 Address
+= CInfoSymSection
.Size
;
1522 Address
= alignTo(Address
, DefaultSectionAlign
);
1525 SymbolTableEntryCount
= SymbolTableIndex
;
1528 void XCOFFObjectWriter::writeSectionForControlSectionEntry(
1529 const MCAssembler
&Asm
, const MCAsmLayout
&Layout
,
1530 const CsectSectionEntry
&CsectEntry
, uint64_t &CurrentAddressLocation
) {
1531 // Nothing to write for this Section.
1532 if (CsectEntry
.Index
== SectionEntry::UninitializedIndex
)
1535 // There could be a gap (without corresponding zero padding) between
1537 // There could be a gap (without corresponding zero padding) between
1539 assert(((CurrentAddressLocation
<= CsectEntry
.Address
) ||
1540 (CsectEntry
.Flags
== XCOFF::STYP_TDATA
) ||
1541 (CsectEntry
.Flags
== XCOFF::STYP_TBSS
)) &&
1542 "CurrentAddressLocation should be less than or equal to section "
1543 "address if the section is not TData or TBSS.");
1545 CurrentAddressLocation
= CsectEntry
.Address
;
1547 // For virtual sections, nothing to write. But need to increase
1548 // CurrentAddressLocation for later sections like DWARF section has a correct
1549 // writing location.
1550 if (CsectEntry
.IsVirtual
) {
1551 CurrentAddressLocation
+= CsectEntry
.Size
;
1555 for (const auto &Group
: CsectEntry
.Groups
) {
1556 for (const auto &Csect
: *Group
) {
1557 if (uint32_t PaddingSize
= Csect
.Address
- CurrentAddressLocation
)
1558 W
.OS
.write_zeros(PaddingSize
);
1560 Asm
.writeSectionData(W
.OS
, Csect
.MCSec
, Layout
);
1561 CurrentAddressLocation
= Csect
.Address
+ Csect
.Size
;
1565 // The size of the tail padding in a section is the end virtual address of
1566 // the current section minus the end virtual address of the last csect
1568 if (uint64_t PaddingSize
=
1569 CsectEntry
.Address
+ CsectEntry
.Size
- CurrentAddressLocation
) {
1570 W
.OS
.write_zeros(PaddingSize
);
1571 CurrentAddressLocation
+= PaddingSize
;
1575 void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
1576 const MCAssembler
&Asm
, const MCAsmLayout
&Layout
,
1577 const DwarfSectionEntry
&DwarfEntry
, uint64_t &CurrentAddressLocation
) {
1578 // There could be a gap (without corresponding zero padding) between
1579 // sections. For example DWARF section alignment is bigger than
1580 // DefaultSectionAlign.
1581 assert(CurrentAddressLocation
<= DwarfEntry
.Address
&&
1582 "CurrentAddressLocation should be less than or equal to section "
1585 if (uint64_t PaddingSize
= DwarfEntry
.Address
- CurrentAddressLocation
)
1586 W
.OS
.write_zeros(PaddingSize
);
1588 if (DwarfEntry
.Size
)
1589 Asm
.writeSectionData(W
.OS
, DwarfEntry
.DwarfSect
->MCSec
, Layout
);
1591 CurrentAddressLocation
= DwarfEntry
.Address
+ DwarfEntry
.Size
;
1593 // DWARF section size is not aligned to DefaultSectionAlign.
1594 // Make sure CurrentAddressLocation is aligned to DefaultSectionAlign.
1595 uint32_t Mod
= CurrentAddressLocation
% DefaultSectionAlign
;
1596 uint32_t TailPaddingSize
= Mod
? DefaultSectionAlign
- Mod
: 0;
1597 if (TailPaddingSize
)
1598 W
.OS
.write_zeros(TailPaddingSize
);
1600 CurrentAddressLocation
+= TailPaddingSize
;
1603 void XCOFFObjectWriter::writeSectionForExceptionSectionEntry(
1604 const MCAssembler
&Asm
, const MCAsmLayout
&Layout
,
1605 ExceptionSectionEntry
&ExceptionEntry
, uint64_t &CurrentAddressLocation
) {
1606 for (auto it
= ExceptionEntry
.ExceptionTable
.begin();
1607 it
!= ExceptionEntry
.ExceptionTable
.end(); it
++) {
1608 // For every symbol that has exception entries, you must start the entries
1609 // with an initial symbol table index entry
1610 W
.write
<uint32_t>(SymbolIndexMap
[it
->second
.FunctionSymbol
]);
1612 // 4-byte padding on 64-bit.
1613 W
.OS
.write_zeros(4);
1615 W
.OS
.write_zeros(2);
1616 for (auto &TrapEntry
: it
->second
.Entries
) {
1617 writeWord(TrapEntry
.TrapAddress
);
1618 W
.write
<uint8_t>(TrapEntry
.Lang
);
1619 W
.write
<uint8_t>(TrapEntry
.Reason
);
1623 CurrentAddressLocation
+= getExceptionSectionSize();
1626 void XCOFFObjectWriter::writeSectionForCInfoSymSectionEntry(
1627 const MCAssembler
&Asm
, const MCAsmLayout
&Layout
,
1628 CInfoSymSectionEntry
&CInfoSymEntry
, uint64_t &CurrentAddressLocation
) {
1629 if (!CInfoSymSection
.Entry
)
1632 constexpr int WordSize
= sizeof(uint32_t);
1633 std::unique_ptr
<CInfoSymInfo
> &CISI
= CInfoSymEntry
.Entry
;
1634 const std::string
&Metadata
= CISI
->Metadata
;
1636 // Emit the 4-byte length of the metadata.
1637 W
.write
<uint32_t>(Metadata
.size());
1639 if (Metadata
.size() == 0)
1642 // Write out the payload one word at a time.
1644 while (Index
+ WordSize
<= Metadata
.size()) {
1646 llvm::support::endian::read32be(Metadata
.data() + Index
);
1647 W
.write
<uint32_t>(NextWord
);
1651 // If there is padding, we have at least one byte of payload left to emit.
1652 if (CISI
->paddingSize()) {
1653 std::array
<uint8_t, WordSize
> LastWord
= {0};
1654 ::memcpy(LastWord
.data(), Metadata
.data() + Index
, Metadata
.size() - Index
);
1655 W
.write
<uint32_t>(llvm::support::endian::read32be(LastWord
.data()));
1658 CurrentAddressLocation
+= CISI
->size();
1661 // Takes the log base 2 of the alignment and shifts the result into the 5 most
1662 // significant bits of a byte, then or's in the csect type into the least
1663 // significant 3 bits.
1664 uint8_t getEncodedType(const MCSectionXCOFF
*Sec
) {
1665 unsigned Log2Align
= Log2(Sec
->getAlign());
1666 // Result is a number in the range [0, 31] which fits in the 5 least
1667 // significant bits. Shift this value into the 5 most significant bits, and
1668 // bitwise-or in the csect type.
1669 uint8_t EncodedAlign
= Log2Align
<< 3;
1670 return EncodedAlign
| Sec
->getCSectType();
1673 } // end anonymous namespace
1675 std::unique_ptr
<MCObjectWriter
>
1676 llvm::createXCOFFObjectWriter(std::unique_ptr
<MCXCOFFObjectTargetWriter
> MOTW
,
1677 raw_pwrite_stream
&OS
) {
1678 return std::make_unique
<XCOFFObjectWriter
>(std::move(MOTW
), OS
);