51constexpr unsigned DefaultSectionAlign = 4;
52constexpr int16_t MaxSectionIndex = INT16_MAX;
57struct XCOFFRelocation {
95 : MCSec(MCSec), SymbolTableIndex(-1),
Address(-1),
Size(0) {}
102using CsectGroup = std::deque<XCOFFSection>;
103using CsectGroups = std::deque<CsectGroup *>;
126 FileOffsetToData = RawPointer;
128 if (NewPointer > MaxRawDataSize)
140 static constexpr int16_t UninitializedIndex =
145 FileOffsetToRelocations(0), RelocationCount(0),
Flags(
Flags),
146 Index(UninitializedIndex) {
148 memcpy(Name,
N.data(),
N.size());
151 virtual void reset() {
154 FileOffsetToData = 0;
155 FileOffsetToRelocations = 0;
157 Index = UninitializedIndex;
170 const bool IsVirtual;
179 memcpy(
Name,
N.data(),
N.size());
182 void reset()
override {
183 SectionEntry::reset();
185 for (
auto *Group : Groups)
189 virtual ~CsectSectionEntry() =
default;
194 std::unique_ptr<XCOFFSection> DwarfSect;
205 const uint64_t RawPointer)
override {
206 FileOffsetToData = RawPointer;
207 uint64_t NewPointer = RawPointer + MemorySize;
208 assert(NewPointer <= MaxRawDataSize &&
209 "Section raw data overflowed this object file.");
214 std::unique_ptr<XCOFFSection> Sect)
217 assert(DwarfSect->MCSec->isDwarfSect() &&
218 "This should be a DWARF section!");
220 memcpy(
Name,
N.data(),
N.size());
223 DwarfSectionEntry(DwarfSectionEntry &&s) =
default;
225 virtual ~DwarfSectionEntry() =
default;
228struct ExceptionTableEntry {
234 ExceptionTableEntry(
const MCSymbol *Trap,
unsigned Lang,
unsigned Reason)
235 :
Trap(
Trap), Lang(Lang), Reason(Reason) {}
238struct ExceptionInfo {
240 unsigned FunctionSize;
241 std::vector<ExceptionTableEntry> Entries;
245 std::map<const StringRef, ExceptionInfo> ExceptionTable;
246 bool isDebugEnabled =
false;
248 ExceptionSectionEntry(
StringRef N, int32_t Flags)
251 memcpy(
Name,
N.data(),
N.size());
254 virtual ~ExceptionSectionEntry() =
default;
264 CInfoSymInfo(std::string Name, std::string
Metadata)
278 std::unique_ptr<CInfoSymInfo>
Entry;
281 virtual ~CInfoSymSectionEntry() =
default;
282 void addEntry(std::unique_ptr<CInfoSymInfo> NewEntry) {
283 Entry = std::move(NewEntry);
287 void reset()
override {
288 SectionEntry::reset();
299 bool HasVisibility =
false;
302 std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
306 TargetObjectWriter->is64Bit() ?
UINT64_MAX : UINT32_MAX;
320 CsectGroup UndefinedCsects;
321 CsectGroup ProgramCodeCsects;
322 CsectGroup ReadOnlyCsects;
323 CsectGroup DataCsects;
324 CsectGroup FuncDSCsects;
325 CsectGroup TOCCsects;
326 CsectGroup BSSCsects;
327 CsectGroup TDataCsects;
328 CsectGroup TBSSCsects;
331 CsectSectionEntry
Text;
332 CsectSectionEntry
Data;
333 CsectSectionEntry BSS;
334 CsectSectionEntry TData;
335 CsectSectionEntry TBSS;
339 std::array<CsectSectionEntry *const, 5> Sections{
340 {&
Text, &
Data, &BSS, &TData, &TBSS}};
342 std::vector<DwarfSectionEntry> DwarfSections;
343 std::vector<SectionEntry> OverflowSections;
345 ExceptionSectionEntry ExceptionSection;
346 CInfoSymSectionEntry CInfoSymSection;
350 void reset()
override;
359 bool is64Bit()
const {
return TargetObjectWriter->is64Bit(); }
360 bool nameShouldBeInStringTable(
const StringRef &);
362 bool auxFileSymNameShouldBeInStringTable(
const StringRef &);
363 void writeAuxFileSymName(
const StringRef &);
365 void writeSymbolEntryForCsectMemberLabel(
const Symbol &SymbolRef,
366 const XCOFFSection &CSectionRef,
367 int16_t SectionIndex,
369 void writeSymbolEntryForControlSection(
const XCOFFSection &CSectionRef,
370 int16_t SectionIndex,
372 void writeSymbolEntryForDwarfSection(
const XCOFFSection &DwarfSectionRef,
373 int16_t SectionIndex);
374 void writeFileHeader();
375 void writeAuxFileHeader();
377 void writeSectionHeaderTable();
379 void writeSectionForControlSectionEntry(
const MCAssembler &Asm,
380 const CsectSectionEntry &CsectEntry,
382 void writeSectionForDwarfSectionEntry(
const MCAssembler &Asm,
383 const DwarfSectionEntry &DwarfEntry,
386 writeSectionForExceptionSectionEntry(
const MCAssembler &Asm,
387 ExceptionSectionEntry &ExceptionEntry,
389 void writeSectionForCInfoSymSectionEntry(
const MCAssembler &Asm,
390 CInfoSymSectionEntry &CInfoSymEntry,
393 void writeSymbolAuxFileEntry(
StringRef &
Name, uint8_t ftype);
394 void writeSymbolAuxDwarfEntry(
uint64_t LengthOfSectionPortion,
396 void writeSymbolAuxCsectEntry(
uint64_t SectionOrLength,
397 uint8_t SymbolAlignmentAndType,
399 void writeSymbolAuxFunctionEntry(
uint32_t EntryOffset,
uint32_t FunctionSize,
402 void writeSymbolAuxExceptionEntry(
uint64_t EntryOffset,
uint32_t FunctionSize,
407 void writeRelocations();
408 void writeRelocation(XCOFFRelocation Reloc,
const XCOFFSection &Section);
420 void finalizeSectionInfo();
424 bool hasExceptionSection() {
425 return !ExceptionSection.ExceptionTable.empty();
427 unsigned getExceptionSectionSize();
428 unsigned getExceptionOffset(
const MCSymbol *Symbol);
430 size_t auxiliaryHeaderSize()
const {
436 XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
444 unsigned LanguageCode,
unsigned ReasonCode,
445 unsigned FunctionSize,
bool hasDebug);
449XCOFFObjectWriter::XCOFFObjectWriter(
454 CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
456 CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
458 CsectGroups{&BSSCsects}),
460 CsectGroups{&TDataCsects}),
462 CsectGroups{&TBSSCsects}),
464 CInfoSymSection(
".info", XCOFF::
STYP_INFO) {}
466void XCOFFObjectWriter::reset() {
468 SymbolIndexMap.
clear();
471 UndefinedCsects.clear();
473 for (
auto *Sec : Sections)
475 for (
auto &DwarfSec : DwarfSections)
477 for (
auto &OverflowSec : OverflowSections)
479 ExceptionSection.reset();
480 CInfoSymSection.reset();
483 SymbolTableEntryCount = 0;
484 SymbolTableOffset = 0;
486 PaddingsBeforeDwarf = 0;
492CsectGroup &XCOFFObjectWriter::getCsectGroup(
const MCSectionXCOFF *MCSec) {
496 "Only an initialized csect can contain program code.");
497 return ProgramCodeCsects;
500 "Only an initialized csect can contain read only data.");
501 return ReadOnlyCsects;
514 "Mapping invalid csect. CSECT with bss storage class must be "
519 "Mapping invalid csect. CSECT with tdata storage class must be "
520 "an initialized csect.");
524 "Mapping invalid csect. CSECT with tbss storage class must be "
525 "an uninitialized csect.");
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 "A TOC symbol must be an initialized csect.");
538 assert(!TOCCsects.empty() &&
539 "We should at least have a TOC-base in this CsectGroup.");
544 "Symbol type incompatible with toc-data.");
545 assert(!TOCCsects.empty() &&
546 "We should at least have a TOC-base in this CsectGroup.");
559void XCOFFObjectWriter::executePostLayoutBinding(
MCAssembler &Asm) {
560 for (
const auto &S : Asm) {
561 const auto *MCSec = cast<const MCSectionXCOFF>(&S);
562 assert(!SectionMap.
contains(MCSec) &&
"Cannot add a section twice.");
573 "An undefined csect should not get registered.");
574 CsectGroup &Group = getCsectGroup(MCSec);
575 Group.emplace_back(MCSec);
576 SectionMap[MCSec] = &Group.back();
579 std::unique_ptr<XCOFFSection> DwarfSec =
580 std::make_unique<XCOFFSection>(MCSec);
581 SectionMap[MCSec] = DwarfSec.get();
583 DwarfSectionEntry SecEntry(MCSec->
getName(),
585 std::move(DwarfSec));
586 DwarfSections.push_back(std::move(SecEntry));
603 HasVisibility =
true;
607 UndefinedCsects.emplace_back(ContainingCsect);
608 SectionMap[ContainingCsect] = &UndefinedCsects.back();
624 "Expected containing csect to exist in map");
625 XCOFFSection *Csect = SectionMap[ContainingCsect];
627 assert(Csect->MCSec->isCsect() &&
"only csect is supported now!");
628 Csect->Syms.emplace_back(XSym);
636 std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymSection.Entry;
637 if (CISI && nameShouldBeInStringTable(CISI->Name))
638 Strings.add(CISI->Name);
641 if (FileNames.empty())
642 FileNames.emplace_back(
".file", 0);
643 for (
const std::pair<std::string, size_t> &
F : FileNames) {
644 if (auxFileSymNameShouldBeInStringTable(
F.first))
645 Strings.add(
F.first);
650 if (nameShouldBeInStringTable(
".file"))
651 Strings.add(
".file");
653 if (auxFileSymNameShouldBeInStringTable(Vers))
657 assignAddressesAndIndices(Asm);
660void XCOFFObjectWriter::recordRelocation(
MCAssembler &Asm,
670 ? SymbolIndexMap[
Sym]
674 auto getVirtualAddress =
678 if (ContainingSect->isDwarfSect())
679 return Asm.getSymbolOffset(*
Sym);
682 if (!
Sym->isDefined())
683 return SectionMap[ContainingSect]->Address;
686 assert(
Sym->isDefined() &&
"not a valid object that has address!");
687 return SectionMap[ContainingSect]->Address +
Asm.getSymbolOffset(*
Sym);
698 std::tie(
Type, SignAndSize) =
699 TargetObjectWriter->getRelocTypeAndSignSize(
Target,
Fixup, IsPCRel);
701 const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
703 "Expected containing csect to exist in map.");
706 MaxRawDataSize -
Asm.getFragmentOffset(*Fragment)) &&
707 "Fragment offset + fixup offset is overflowed.");
709 Asm.getFragmentOffset(*Fragment) +
Fixup.getOffset();
712 if (
Type == XCOFF::RelocationType::R_POS ||
713 Type == XCOFF::RelocationType::R_TLS ||
714 Type == XCOFF::RelocationType::R_TLS_LE ||
715 Type == XCOFF::RelocationType::R_TLS_IE ||
716 Type == XCOFF::RelocationType::R_TLS_LD)
719 FixedValue = getVirtualAddress(SymA, SymASec) +
Target.getConstant();
720 else if (
Type == XCOFF::RelocationType::R_TLSM)
724 else if (
Type == XCOFF::RelocationType::R_TOC ||
725 Type == XCOFF::RelocationType::R_TOCL) {
736 int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
737 TOCCsects.front().Address +
Target.getConstant();
754 if (
Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset))
755 TOCEntryOffset = llvm::SignExtend64<16>(TOCEntryOffset);
757 FixedValue = TOCEntryOffset;
759 }
else if (
Type == XCOFF::RelocationType::R_RBR) {
763 "Only XMC_PR csect may have the R_RBR relocation.");
768 SectionMap[ParentSec]->Address + FixupOffsetInCsect;
771 FixedValue = getVirtualAddress(SymA, SymASec) - BRInstrAddress +
773 }
else if (
Type == XCOFF::RelocationType::R_REF) {
777 FixupOffsetInCsect = 0;
780 XCOFFRelocation Reloc = {
Index, FixupOffsetInCsect, SignAndSize,
Type};
783 "Expected containing csect to exist in map.");
784 SectionMap[RelocationSec]->Relocations.push_back(Reloc);
793 const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
795 "Expected containing csect to exist in map.");
796 if (SymASec == SymBSec)
798 "relocation for paired relocatable term is not yet supported");
800 assert(
Type == XCOFF::RelocationType::R_POS &&
801 "SymA must be R_POS here if it's not opposite term or paired "
802 "relocatable term.");
803 const uint32_t IndexB = getIndex(SymB, SymBSec);
806 const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
807 XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
808 SectionMap[RelocationSec]->Relocations.push_back(RelocB);
811 FixedValue -= getVirtualAddress(SymB, SymBSec);
814void XCOFFObjectWriter::writeSections(
const MCAssembler &Asm) {
815 uint64_t CurrentAddressLocation = 0;
816 for (
const auto *Section : Sections)
817 writeSectionForControlSectionEntry(Asm, *Section, CurrentAddressLocation);
818 for (
const auto &DwarfSection : DwarfSections)
819 writeSectionForDwarfSectionEntry(Asm, DwarfSection, CurrentAddressLocation);
820 writeSectionForExceptionSectionEntry(Asm, ExceptionSection,
821 CurrentAddressLocation);
822 writeSectionForCInfoSymSectionEntry(Asm, CInfoSymSection,
823 CurrentAddressLocation);
831 finalizeSectionInfo();
835 writeAuxFileHeader();
836 writeSectionHeaderTable();
843 return W.OS.tell() - StartOffset;
846bool XCOFFObjectWriter::nameShouldBeInStringTable(
const StringRef &SymbolName) {
850void XCOFFObjectWriter::writeSymbolName(
const StringRef &SymbolName) {
852 if (nameShouldBeInStringTable(SymbolName)) {
854 W.write<
uint32_t>(Strings.getOffset(SymbolName));
864 int16_t SectionNumber,
867 uint8_t NumberOfAuxEntries) {
870 W.write<
uint32_t>(Strings.getOffset(SymbolName));
872 writeSymbolName(SymbolName);
875 W.write<int16_t>(SectionNumber);
878 W.write<uint8_t>(NumberOfAuxEntries);
881void XCOFFObjectWriter::writeSymbolAuxCsectEntry(
uint64_t SectionOrLength,
882 uint8_t SymbolAlignmentAndType,
887 W.write<uint8_t>(SymbolAlignmentAndType);
899bool XCOFFObjectWriter::auxFileSymNameShouldBeInStringTable(
904void XCOFFObjectWriter::writeAuxFileSymName(
const StringRef &SymbolName) {
906 if (auxFileSymNameShouldBeInStringTable(SymbolName)) {
908 W.write<
uint32_t>(Strings.getOffset(SymbolName));
918void XCOFFObjectWriter::writeSymbolAuxFileEntry(
StringRef &
Name,
920 writeAuxFileSymName(
Name);
921 W.write<uint8_t>(ftype);
929void XCOFFObjectWriter::writeSymbolAuxDwarfEntry(
931 writeWord(LengthOfSectionPortion);
934 writeWord(NumberOfRelocEnt);
943void XCOFFObjectWriter::writeSymbolEntryForCsectMemberLabel(
944 const Symbol &SymbolRef,
const XCOFFSection &CSectionRef,
945 int16_t SectionIndex,
uint64_t SymbolOffset) {
946 assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address &&
947 "Symbol address overflowed.");
949 auto Entry = ExceptionSection.ExceptionTable.find(SymbolRef.MCSym->getName());
950 if (Entry != ExceptionSection.ExceptionTable.end()) {
951 writeSymbolEntry(SymbolRef.getSymbolTableName(),
952 CSectionRef.Address + SymbolOffset, SectionIndex,
956 is64Bit() ? SymbolRef.getVisibilityType()
957 : SymbolRef.getVisibilityType() | 0x0020,
958 SymbolRef.getStorageClass(),
959 (
is64Bit() && ExceptionSection.isDebugEnabled) ? 3 : 2);
960 if (
is64Bit() && ExceptionSection.isDebugEnabled) {
963 writeSymbolAuxExceptionEntry(
964 ExceptionSection.FileOffsetToData +
965 getExceptionOffset(
Entry->second.FunctionSymbol),
966 Entry->second.FunctionSize,
967 SymbolIndexMap[
Entry->second.FunctionSymbol] + 4);
971 writeSymbolAuxFunctionEntry(
972 ExceptionSection.FileOffsetToData +
973 getExceptionOffset(
Entry->second.FunctionSymbol),
974 Entry->second.FunctionSize, 0,
975 (
is64Bit() && ExceptionSection.isDebugEnabled)
976 ? SymbolIndexMap[
Entry->second.FunctionSymbol] + 4
977 : SymbolIndexMap[
Entry->second.FunctionSymbol] + 3);
979 writeSymbolEntry(SymbolRef.getSymbolTableName(),
980 CSectionRef.Address + SymbolOffset, SectionIndex,
981 SymbolRef.getVisibilityType(),
982 SymbolRef.getStorageClass());
984 writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex,
XCOFF::XTY_LD,
985 CSectionRef.MCSec->getMappingClass());
988void XCOFFObjectWriter::writeSymbolEntryForDwarfSection(
989 const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) {
990 assert(DwarfSectionRef.MCSec->isDwarfSect() &&
"Not a DWARF section!");
992 writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), 0,
995 writeSymbolAuxDwarfEntry(DwarfSectionRef.Size);
998void XCOFFObjectWriter::writeSymbolEntryForControlSection(
999 const XCOFFSection &CSectionRef, int16_t SectionIndex,
1001 writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address,
1002 SectionIndex, CSectionRef.getVisibilityType(),
StorageClass);
1004 writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec),
1005 CSectionRef.MCSec->getMappingClass());
1008void XCOFFObjectWriter::writeSymbolAuxFunctionEntry(
uint32_t EntryOffset,
1013 writeWord(LineNumberPointer);
1018 writeWord(LineNumberPointer);
1021 W.OS.write_zeros(1);
1024 W.OS.write_zeros(2);
1028void XCOFFObjectWriter::writeSymbolAuxExceptionEntry(
uint64_t EntryOffset,
1031 assert(
is64Bit() &&
"Exception auxilliary entries are 64-bit only.");
1035 W.OS.write_zeros(1);
1039void XCOFFObjectWriter::writeFileHeader() {
1042 W.write<int32_t>(0);
1043 writeWord(SymbolTableOffset);
1045 W.write<
uint16_t>(auxiliaryHeaderSize());
1047 W.write<int32_t>(SymbolTableEntryCount);
1049 W.write<int32_t>(SymbolTableEntryCount);
1050 W.write<
uint16_t>(auxiliaryHeaderSize());
1055void XCOFFObjectWriter::writeAuxFileHeader() {
1056 if (!auxiliaryHeaderSize())
1067 W.write<
uint32_t>(Sections[0]->Address);
1068 W.write<
uint32_t>(Sections[1]->Address);
1071void XCOFFObjectWriter::writeSectionHeader(
const SectionEntry *Sec) {
1075 if (Sec->Index == SectionEntry::UninitializedIndex)
1084 writeWord(IsDwarf ? 0 : Sec->Address);
1086 writeWord((IsDwarf || IsOvrflo) ? 0 : Sec->Address);
1088 writeWord(Sec->Size);
1089 writeWord(Sec->FileOffsetToData);
1090 writeWord(Sec->FileOffsetToRelocations);
1094 W.write<
uint32_t>(Sec->RelocationCount);
1096 W.write<int32_t>(Sec->Flags);
1097 W.OS.write_zeros(4);
1103 W.write<
uint16_t>(Sec->RelocationCount);
1105 ? Sec->RelocationCount
1107 W.write<int32_t>(Sec->Flags);
1111void XCOFFObjectWriter::writeSectionHeaderTable() {
1112 for (
const auto *CsectSec : Sections)
1113 writeSectionHeader(CsectSec);
1114 for (
const auto &DwarfSec : DwarfSections)
1115 writeSectionHeader(&DwarfSec);
1116 for (
const auto &OverflowSec : OverflowSections)
1117 writeSectionHeader(&OverflowSec);
1118 if (hasExceptionSection())
1119 writeSectionHeader(&ExceptionSection);
1120 if (CInfoSymSection.Entry)
1121 writeSectionHeader(&CInfoSymSection);
1124void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
1125 const XCOFFSection &Section) {
1127 writeWord(
Section.Address + Reloc.FixupOffsetInCsect);
1130 assert(
Section.MCSec->isDwarfSect() &&
"unsupport section type!");
1131 writeWord(Reloc.FixupOffsetInCsect);
1133 W.write<
uint32_t>(Reloc.SymbolTableIndex);
1134 W.write<uint8_t>(Reloc.SignAndSize);
1135 W.write<uint8_t>(Reloc.Type);
1138void XCOFFObjectWriter::writeRelocations() {
1139 for (
const auto *Section : Sections) {
1140 if (
Section->Index == SectionEntry::UninitializedIndex)
1144 for (
const auto *Group :
Section->Groups) {
1148 for (
const auto &Csect : *Group) {
1149 for (
const auto Reloc : Csect.Relocations)
1150 writeRelocation(Reloc, Csect);
1155 for (
const auto &DwarfSection : DwarfSections)
1156 for (
const auto &Reloc : DwarfSection.DwarfSect->Relocations)
1157 writeRelocation(Reloc, *DwarfSection.DwarfSect);
1160void XCOFFObjectWriter::writeSymbolTable(
MCAssembler &Asm) {
1164 for (
const std::pair<std::string, size_t> &
F : FileNames) {
1192 int NumberOfFileAuxEntries = 1;
1194 ++NumberOfFileAuxEntries;
1195 writeSymbolEntry(
".file", 0, XCOFF::ReservedSectionNum::N_DEBUG,
1197 NumberOfFileAuxEntries);
1203 if (CInfoSymSection.Entry)
1204 writeSymbolEntry(CInfoSymSection.Entry->Name, CInfoSymSection.Entry->Offset,
1205 CInfoSymSection.Index,
1209 for (
const auto &Csect : UndefinedCsects) {
1210 writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF,
1211 Csect.MCSec->getStorageClass());
1214 for (
const auto *Section : Sections) {
1215 if (
Section->Index == SectionEntry::UninitializedIndex)
1219 for (
const auto *Group :
Section->Groups) {
1223 const int16_t SectionIndex =
Section->Index;
1224 for (
const auto &Csect : *Group) {
1226 writeSymbolEntryForControlSection(Csect, SectionIndex,
1227 Csect.MCSec->getStorageClass());
1229 for (
const auto &
Sym : Csect.Syms)
1230 writeSymbolEntryForCsectMemberLabel(
1231 Sym, Csect, SectionIndex,
Asm.getSymbolOffset(*(
Sym.MCSym)));
1236 for (
const auto &DwarfSection : DwarfSections)
1237 writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect,
1238 DwarfSection.Index);
1241void XCOFFObjectWriter::finalizeRelocationInfo(
SectionEntry *Sec,
1251 SecEntry.RelocationCount = Sec->Index;
1255 SecEntry.Address = RelCount;
1256 SecEntry.Index = ++SectionCount;
1257 OverflowSections.push_back(std::move(SecEntry));
1263 Sec->RelocationCount = RelCount;
1267void XCOFFObjectWriter::calcOffsetToRelocations(
SectionEntry *Sec,
1269 if (!Sec->RelocationCount)
1272 Sec->FileOffsetToRelocations = RawPointer;
1277 for (
auto &OverflowSec : OverflowSections) {
1278 if (OverflowSec.RelocationCount ==
static_cast<uint32_t>(Sec->Index)) {
1279 RelocationSizeInSec =
1284 OverflowSec.FileOffsetToRelocations = Sec->FileOffsetToRelocations;
1287 assert(RelocationSizeInSec &&
"Overflow section header doesn't exist.");
1289 RelocationSizeInSec = Sec->RelocationCount *
1294 RawPointer += RelocationSizeInSec;
1295 if (RawPointer > MaxRawDataSize)
1299void XCOFFObjectWriter::finalizeSectionInfo() {
1300 for (
auto *Section : Sections) {
1301 if (
Section->Index == SectionEntry::UninitializedIndex)
1306 for (
const auto *Group :
Section->Groups) {
1310 for (
auto &Csect : *Group)
1311 RelCount += Csect.Relocations.size();
1313 finalizeRelocationInfo(Section, RelCount);
1316 for (
auto &DwarfSection : DwarfSections)
1317 finalizeRelocationInfo(&DwarfSection,
1318 DwarfSection.DwarfSect->Relocations.size());
1326 auxiliaryHeaderSize();
1329 for (
auto *Sec : Sections) {
1330 if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual)
1333 RawPointer = Sec->advanceFileOffset(MaxRawDataSize, RawPointer);
1336 if (!DwarfSections.empty()) {
1337 RawPointer += PaddingsBeforeDwarf;
1338 for (
auto &DwarfSection : DwarfSections) {
1339 RawPointer = DwarfSection.advanceFileOffset(MaxRawDataSize, RawPointer);
1343 if (hasExceptionSection())
1344 RawPointer = ExceptionSection.advanceFileOffset(MaxRawDataSize, RawPointer);
1346 if (CInfoSymSection.Entry)
1347 RawPointer = CInfoSymSection.advanceFileOffset(MaxRawDataSize, RawPointer);
1349 for (
auto *Sec : Sections) {
1350 if (Sec->Index != SectionEntry::UninitializedIndex)
1351 calcOffsetToRelocations(Sec, RawPointer);
1354 for (
auto &DwarfSec : DwarfSections)
1355 calcOffsetToRelocations(&DwarfSec, RawPointer);
1359 if (SymbolTableEntryCount)
1360 SymbolTableOffset = RawPointer;
1363void XCOFFObjectWriter::addExceptionEntry(
1365 unsigned ReasonCode,
unsigned FunctionSize,
bool hasDebug) {
1369 ExceptionSection.isDebugEnabled =
true;
1370 auto Entry = ExceptionSection.ExceptionTable.find(
Symbol->getName());
1371 if (Entry != ExceptionSection.ExceptionTable.end()) {
1372 Entry->second.Entries.push_back(
1373 ExceptionTableEntry(
Trap, LanguageCode, ReasonCode));
1376 ExceptionInfo NewEntry;
1377 NewEntry.FunctionSymbol =
Symbol;
1378 NewEntry.FunctionSize = FunctionSize;
1379 NewEntry.Entries.push_back(
1380 ExceptionTableEntry(
Trap, LanguageCode, ReasonCode));
1381 ExceptionSection.ExceptionTable.insert(
1382 std::pair<const StringRef, ExceptionInfo>(
Symbol->getName(), NewEntry));
1385unsigned XCOFFObjectWriter::getExceptionSectionSize() {
1386 unsigned EntryNum = 0;
1388 for (
const auto &
TableEntry : ExceptionSection.ExceptionTable)
1391 EntryNum +=
TableEntry.second.Entries.size() + 1;
1397unsigned XCOFFObjectWriter::getExceptionOffset(
const MCSymbol *Symbol) {
1398 unsigned EntryNum = 0;
1399 for (
const auto &
TableEntry : ExceptionSection.ExceptionTable) {
1400 if (Symbol ==
TableEntry.second.FunctionSymbol)
1402 EntryNum +=
TableEntry.second.Entries.size() + 1;
1409 assert(!CInfoSymSection.Entry &&
"Multiple entries are not supported");
1410 CInfoSymSection.addEntry(
1411 std::make_unique<CInfoSymInfo>(
Name.str(),
Metadata.str()));
1414void XCOFFObjectWriter::assignAddressesAndIndices(
MCAssembler &Asm) {
1418 (2 + (CompilerVersion.empty() ? 0 : 1)) * FileNames.size();
1420 if (CInfoSymSection.Entry)
1424 for (
auto &Csect : UndefinedCsects) {
1427 Csect.SymbolTableIndex = SymbolTableIndex;
1428 SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
1430 SymbolTableIndex += 2;
1438 int32_t SectionIndex = 1;
1439 bool HasTDataSection =
false;
1441 for (
auto *Section : Sections) {
1442 const bool IsEmpty =
1444 [](
const CsectGroup *Group) { return Group->empty(); });
1448 if (SectionIndex > MaxSectionIndex)
1450 Section->Index = SectionIndex++;
1453 bool SectionAddressSet =
false;
1457 HasTDataSection =
true;
1464 for (
auto *Group :
Section->Groups) {
1468 for (
auto &Csect : *Group) {
1471 Csect.Size =
Asm.getSectionAddressSize(*MCSec);
1472 Address = Csect.Address + Csect.Size;
1473 Csect.SymbolTableIndex = SymbolTableIndex;
1476 SymbolTableIndex += 2;
1478 for (
auto &
Sym : Csect.Syms) {
1479 bool hasExceptEntry =
false;
1481 ExceptionSection.ExceptionTable.find(
Sym.MCSym->getName());
1482 if (Entry != ExceptionSection.ExceptionTable.end()) {
1483 hasExceptEntry =
true;
1484 for (
auto &TrapEntry :
Entry->second.Entries) {
1485 TrapEntry.TrapAddress =
Asm.getSymbolOffset(*(
Sym.MCSym)) +
1486 TrapEntry.Trap->getOffset();
1489 Sym.SymbolTableIndex = SymbolTableIndex;
1490 SymbolIndexMap[
Sym.MCSym] =
Sym.SymbolTableIndex;
1495 SymbolTableIndex += 2;
1496 if (hasExceptionSection() && hasExceptEntry) {
1497 if (
is64Bit() && ExceptionSection.isDebugEnabled)
1498 SymbolTableIndex += 2;
1500 SymbolTableIndex += 1;
1505 if (!SectionAddressSet) {
1506 Section->Address = Group->front().Address;
1507 SectionAddressSet =
true;
1522 if (!DwarfSections.empty())
1523 PaddingsBeforeDwarf =
1525 (*DwarfSections.begin()).DwarfSect->MCSec->getAlign()) -
1528 DwarfSectionEntry *LastDwarfSection =
nullptr;
1529 for (
auto &DwarfSection : DwarfSections) {
1530 assert((SectionIndex <= MaxSectionIndex) &&
"Section index overflow!");
1532 XCOFFSection &DwarfSect = *DwarfSection.DwarfSect;
1536 DwarfSection.Index = SectionIndex++;
1540 DwarfSect.SymbolTableIndex = SymbolTableIndex;
1543 SymbolTableIndex += 2;
1549 DwarfSection.Address = DwarfSect.Address =
1554 DwarfSection.Size = DwarfSect.Size =
Asm.getSectionAddressSize(*MCSec);
1556 Address = DwarfSection.Address + DwarfSection.Size;
1558 if (LastDwarfSection)
1559 LastDwarfSection->MemorySize =
1560 DwarfSection.Address - LastDwarfSection->Address;
1561 LastDwarfSection = &DwarfSection;
1563 if (LastDwarfSection) {
1566 Address =
alignTo(LastDwarfSection->Address + LastDwarfSection->Size,
1567 DefaultSectionAlign);
1568 LastDwarfSection->MemorySize =
Address - LastDwarfSection->Address;
1570 if (hasExceptionSection()) {
1571 ExceptionSection.Index = SectionIndex++;
1573 ExceptionSection.Address = 0;
1574 ExceptionSection.Size = getExceptionSectionSize();
1575 Address += ExceptionSection.Size;
1579 if (CInfoSymSection.Entry) {
1580 CInfoSymSection.Index = SectionIndex++;
1582 CInfoSymSection.Address = 0;
1583 Address += CInfoSymSection.Size;
1587 SymbolTableEntryCount = SymbolTableIndex;
1590void XCOFFObjectWriter::writeSectionForControlSectionEntry(
1591 const MCAssembler &Asm,
const CsectSectionEntry &CsectEntry,
1592 uint64_t &CurrentAddressLocation) {
1594 if (CsectEntry.Index == SectionEntry::UninitializedIndex)
1601 assert(((CurrentAddressLocation <= CsectEntry.Address) ||
1604 "CurrentAddressLocation should be less than or equal to section "
1605 "address if the section is not TData or TBSS.");
1607 CurrentAddressLocation = CsectEntry.Address;
1612 if (CsectEntry.IsVirtual) {
1613 CurrentAddressLocation += CsectEntry.Size;
1617 for (
const auto &Group : CsectEntry.Groups) {
1618 for (
const auto &Csect : *Group) {
1619 if (
uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
1620 W.OS.write_zeros(PaddingSize);
1622 Asm.writeSectionData(
W.OS, Csect.MCSec);
1623 CurrentAddressLocation = Csect.Address + Csect.Size;
1631 CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) {
1632 W.OS.write_zeros(PaddingSize);
1633 CurrentAddressLocation += PaddingSize;
1637void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
1638 const MCAssembler &Asm,
const DwarfSectionEntry &DwarfEntry,
1639 uint64_t &CurrentAddressLocation) {
1643 assert(CurrentAddressLocation <= DwarfEntry.Address &&
1644 "CurrentAddressLocation should be less than or equal to section "
1647 if (
uint64_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation)
1648 W.OS.write_zeros(PaddingSize);
1650 if (DwarfEntry.Size)
1651 Asm.writeSectionData(
W.OS, DwarfEntry.DwarfSect->MCSec);
1653 CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size;
1657 uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign;
1659 if (TailPaddingSize)
1660 W.OS.write_zeros(TailPaddingSize);
1662 CurrentAddressLocation += TailPaddingSize;
1665void XCOFFObjectWriter::writeSectionForExceptionSectionEntry(
1666 const MCAssembler &Asm, ExceptionSectionEntry &ExceptionEntry,
1667 uint64_t &CurrentAddressLocation) {
1668 for (
const auto &
TableEntry : ExceptionEntry.ExceptionTable) {
1674 W.OS.write_zeros(4);
1676 W.OS.write_zeros(2);
1677 for (
auto &TrapEntry :
TableEntry.second.Entries) {
1678 writeWord(TrapEntry.TrapAddress);
1679 W.write<uint8_t>(TrapEntry.Lang);
1680 W.write<uint8_t>(TrapEntry.Reason);
1684 CurrentAddressLocation += getExceptionSectionSize();
1687void XCOFFObjectWriter::writeSectionForCInfoSymSectionEntry(
1688 const MCAssembler &Asm, CInfoSymSectionEntry &CInfoSymEntry,
1689 uint64_t &CurrentAddressLocation) {
1690 if (!CInfoSymSection.Entry)
1693 constexpr int WordSize =
sizeof(
uint32_t);
1694 std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymEntry.Entry;
1713 if (CISI->paddingSize()) {
1714 std::array<uint8_t, WordSize> LastWord = {0};
1719 CurrentAddressLocation += CISI->size();
1730 uint8_t EncodedAlign = Log2Align << 3;
1736std::unique_ptr<MCObjectWriter>
1739 return std::make_unique<XCOFFObjectWriter>(std::move(MOTW),
OS);
1746 unsigned ReasonCode,
unsigned FunctionSize,
1749 Symbol,
Trap, LanguageCode, ReasonCode, FunctionSize, hasDebug);
static void writeSymbolTable(raw_ostream &Out, object::Archive::Kind Kind, bool Deterministic, ArrayRef< MemberData > Members, StringRef StringTable, uint64_t MembersOffset, unsigned NumSyms, uint64_t PrevMemberOffset=0, uint64_t NextMemberOffset=0, bool Is64Bit=false)
PowerPC TLS Dynamic Call Fixup
if(auto Err=PB.parsePassPipeline(MPM, Passes)) return wrap(std MPM run * Mod
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static bool is64Bit(const char *name)
static const X86InstrFMA3Group Groups[]
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
bool contains(const_arg_type_t< KeyT > Val) const
Return true if the specified key is in the map, false otherwise.
Generic interface to target specific assembler backends.
virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
MCSection * getParent() const
Defines the object file and target independent interfaces used by the assembler backend to write nati...
virtual void executePostLayoutBinding(MCAssembler &Asm)
Perform any late binding of symbols (for example, to assign symbol indices for use when generating re...
virtual void reset()
lifetime management
virtual uint64_t writeObject(MCAssembler &Asm)=0
Write the object file and returns the number of bytes written.
virtual void recordRelocation(MCAssembler &Asm, const MCFragment *Fragment, const MCFixup &Fixup, MCValue Target, uint64_t &FixedValue)=0
Record a relocation entry.
StringRef getSymbolTableName() const
XCOFF::VisibilityType getVisibilityType() const
std::optional< XCOFF::DwarfSectionSubtypeFlags > getDwarfSubtypeFlags() const
XCOFF::StorageMappingClass getMappingClass() const
MCSymbolXCOFF * getQualNameSymbol() const
XCOFF::SymbolType getCSectType() const
StringRef getName() const
XCOFF::VisibilityType getVisibilityType() const
StringRef getSymbolTableName() const
XCOFF::StorageClass getStorageClass() const
MCSectionXCOFF * getRepresentedCsect() const
MCSymbol - Instances of this class represent a symbol name in the MC file, and MCSymbols are created ...
bool isDefined() const
isDefined - Check if this symbol is defined (i.e., it has an address).
MCFragment * getFragment(bool SetUsed=true) const
This represents an "assembler immediate".
SectionEntry - represents a section emitted into memory by the dynamic linker.
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
StringRef - Represent a constant reference to a string, i.e.
constexpr bool empty() const
empty - Check if the string is empty.
bool ends_with(StringRef Suffix) const
Check if this string ends with the given Suffix.
bool ends_with_insensitive(StringRef Suffix) const
Check if this string ends with the given Suffix, ignoring case.
Utility for building string tables with deduplicated suffixes.
Target - Wrapper for Target specific information.
The instances of the Type class are immutable: once they are created, they are never changed.
LLVM Value Representation.
An abstract base class for streams implementations that also support a pwrite operation.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
constexpr char SymbolName[]
Key for Kernel::Metadata::mSymbolName.
C::iterator addEntry(C &Container, StringRef InstallName)
constexpr size_t RelocationSerializationSize32
constexpr size_t ExceptionSectionEntrySize64
constexpr size_t RelocationSerializationSize64
constexpr size_t ExceptionSectionEntrySize32
constexpr size_t FileHeaderSize64
constexpr size_t SectionHeaderSize64
constexpr size_t AuxFileEntNameSize
@ AUX_SECT
Identifies a SECT auxiliary entry.
@ AUX_FILE
Identifies a file auxiliary entry.
@ AUX_EXCEPT
Identifies an exception auxiliary entry.
@ AUX_FCN
Identifies a function auxiliary entry.
@ AUX_CSECT
Identifies a csect auxiliary entry.
void addCInfoSymEntry(MCObjectWriter &Writer, StringRef Name, StringRef Metadata)
@ TB_Fortran
Fortran language.
@ TB_CPLUSPLUS
C++ language.
VisibilityType
Values for visibility as they would appear when encoded in the high 4 bits of the 16-bit unsigned n_t...
@ TCPU_PPC64
PowerPC common architecture 64-bit mode.
@ TCPU_COM
POWER and PowerPC architecture common.
constexpr size_t NameSize
constexpr uint16_t RelocOverflow
constexpr size_t AuxFileHeaderSizeShort
@ XFT_FN
Specifies the source-file name.
@ XFT_CV
Specifies the compiler version number.
constexpr size_t FileHeaderSize32
StorageMappingClass
Storage Mapping Class definitions.
@ XMC_TE
Symbol mapped at the end of TOC.
@ XMC_TC0
TOC Anchor for TOC Addressability.
@ XMC_DS
Descriptor csect.
@ XMC_TL
Initialized thread-local variable.
@ XMC_RO
Read Only Constant.
@ XMC_TD
Scalar data item in the TOC.
@ XMC_UL
Uninitialized thread-local variable.
@ XMC_BS
BSS class (uninitialized static internal)
@ XMC_TC
General TOC item.
constexpr size_t SectionHeaderSize32
constexpr size_t FileNamePadSize
@ XTY_CM
Common csect definition. For uninitialized storage.
@ XTY_SD
Csect definition for initialized storage.
@ XTY_LD
Label definition.
@ XTY_ER
External reference.
void addExceptionEntry(MCObjectWriter &Writer, const MCSymbol *Symbol, const MCSymbol *Trap, unsigned LanguageCode, unsigned ReasonCode, unsigned FunctionSize, bool hasDebug)
support::ulittle32_t Word
uint32_t read32be(const void *P)
This is an optimization pass for GlobalISel generic memory operations.
bool all_of(R &&range, UnaryPredicate P)
Provide wrappers to std::all_of which take ranges instead of having to pass begin/end explicitly.
auto size(R &&Range, std::enable_if_t< std::is_base_of< std::random_access_iterator_tag, typename std::iterator_traits< decltype(Range.begin())>::iterator_category >::value, void > *=nullptr)
Get the size of a range.
constexpr uint32_t Hi_32(uint64_t Value)
Return the high 32 bits of a 64 bit value.
void report_fatal_error(Error Err, bool gen_crash_diag=true)
Report a serious error, calling any installed error handler.
constexpr uint32_t Lo_32(uint64_t Value)
Return the low 32 bits of a 64 bit value.
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
OutputIt move(R &&Range, OutputIt Out)
Provide wrappers to std::move which take ranges instead of having to pass begin/end explicitly.
unsigned Log2(Align A)
Returns the log2 of the alignment.
std::unique_ptr< MCObjectWriter > createXCOFFObjectWriter(std::unique_ptr< MCXCOFFObjectTargetWriter > MOTW, raw_pwrite_stream &OS)
Implement std::hash so that hash_code can be used in STL containers.
@ FKF_IsPCRel
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...
unsigned Flags
Flags describing additional information on this fixup kind.
Adapter to write values to a stream in a particular byte order.