52constexpr unsigned DefaultSectionAlign = 4;
53constexpr int16_t MaxSectionIndex = INT16_MAX;
58struct XCOFFRelocation {
96 : MCSec(MCSec), SymbolTableIndex(-1),
Address(-1),
Size(0) {}
103using CsectGroup = std::deque<XCOFFSection>;
104using CsectGroups = std::deque<CsectGroup *>;
127 FileOffsetToData = RawPointer;
129 if (NewPointer > MaxRawDataSize)
141 static constexpr int16_t UninitializedIndex =
146 FileOffsetToRelocations(0), RelocationCount(0),
Flags(
Flags),
147 Index(UninitializedIndex) {
149 memcpy(Name,
N.data(),
N.size());
152 virtual void reset() {
155 FileOffsetToData = 0;
156 FileOffsetToRelocations = 0;
158 Index = UninitializedIndex;
171 const bool IsVirtual;
180 memcpy(
Name,
N.data(),
N.size());
183 void reset()
override {
184 SectionEntry::reset();
186 for (
auto *Group : Groups)
190 virtual ~CsectSectionEntry() =
default;
195 std::unique_ptr<XCOFFSection> DwarfSect;
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.");
215 std::unique_ptr<XCOFFSection> Sect)
218 assert(DwarfSect->MCSec->isDwarfSect() &&
219 "This should be a DWARF section!");
221 memcpy(
Name,
N.data(),
N.size());
224 DwarfSectionEntry(DwarfSectionEntry &&s) =
default;
226 virtual ~DwarfSectionEntry() =
default;
229struct ExceptionTableEntry {
235 ExceptionTableEntry(
const MCSymbol *Trap,
unsigned Lang,
unsigned Reason)
236 :
Trap(
Trap), Lang(Lang), Reason(Reason) {}
239struct ExceptionInfo {
241 unsigned FunctionSize;
242 std::vector<ExceptionTableEntry> Entries;
246 std::map<const StringRef, ExceptionInfo> ExceptionTable;
247 bool isDebugEnabled =
false;
249 ExceptionSectionEntry(
StringRef N, int32_t Flags)
252 memcpy(
Name,
N.data(),
N.size());
255 virtual ~ExceptionSectionEntry() =
default;
265 CInfoSymInfo(std::string Name, std::string
Metadata)
279 std::unique_ptr<CInfoSymInfo> Entry;
282 virtual ~CInfoSymSectionEntry() =
default;
283 void addEntry(std::unique_ptr<CInfoSymInfo> NewEntry) {
284 Entry = std::move(NewEntry);
286 Size += Entry->size();
288 void reset()
override {
289 SectionEntry::reset();
300 std::vector<std::pair<std::string, size_t>> FileNames;
301 bool HasVisibility =
false;
304 std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
308 TargetObjectWriter->is64Bit() ?
UINT64_MAX : UINT32_MAX;
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;
333 CsectSectionEntry
Text;
334 CsectSectionEntry
Data;
335 CsectSectionEntry BSS;
336 CsectSectionEntry TData;
337 CsectSectionEntry TBSS;
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;
352 void reset()
override;
361 bool is64Bit()
const {
return TargetObjectWriter->is64Bit(); }
362 bool nameShouldBeInStringTable(
const StringRef &);
364 bool auxFileSymNameShouldBeInStringTable(
const StringRef &);
365 void writeAuxFileSymName(
const StringRef &);
367 void writeSymbolEntryForCsectMemberLabel(
const Symbol &SymbolRef,
368 const XCOFFSection &CSectionRef,
369 int16_t SectionIndex,
371 void writeSymbolEntryForControlSection(
const XCOFFSection &CSectionRef,
372 int16_t SectionIndex,
374 void writeSymbolEntryForDwarfSection(
const XCOFFSection &DwarfSectionRef,
375 int16_t SectionIndex);
376 void writeFileHeader();
377 void writeAuxFileHeader();
379 void writeSectionHeaderTable();
381 void writeSectionForControlSectionEntry(
const MCAssembler &Asm,
383 const CsectSectionEntry &CsectEntry,
385 void writeSectionForDwarfSectionEntry(
const MCAssembler &Asm,
387 const DwarfSectionEntry &DwarfEntry,
389 void writeSectionForExceptionSectionEntry(
391 ExceptionSectionEntry &ExceptionEntry,
uint64_t &CurrentAddressLocation);
392 void writeSectionForCInfoSymSectionEntry(
const MCAssembler &Asm,
394 CInfoSymSectionEntry &CInfoSymEntry,
397 void writeSymbolAuxFileEntry(
StringRef &
Name, uint8_t ftype);
398 void writeSymbolAuxDwarfEntry(
uint64_t LengthOfSectionPortion,
400 void writeSymbolAuxCsectEntry(
uint64_t SectionOrLength,
401 uint8_t SymbolAlignmentAndType,
403 void writeSymbolAuxFunctionEntry(
uint32_t EntryOffset,
uint32_t FunctionSize,
406 void writeSymbolAuxExceptionEntry(
uint64_t EntryOffset,
uint32_t FunctionSize,
411 void writeRelocations();
412 void writeRelocation(XCOFFRelocation Reloc,
const XCOFFSection &Section);
424 void finalizeSectionInfo();
429 unsigned LanguageCode,
unsigned ReasonCode,
430 unsigned FunctionSize,
bool hasDebug)
override;
431 bool hasExceptionSection() {
432 return !ExceptionSection.ExceptionTable.empty();
434 unsigned getExceptionSectionSize();
435 unsigned getExceptionOffset(
const MCSymbol *Symbol);
438 size_t auxiliaryHeaderSize()
const {
444 XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
452XCOFFObjectWriter::XCOFFObjectWriter(
457 CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
459 CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
461 CsectGroups{&BSSCsects}),
463 CsectGroups{&TDataCsects}),
465 CsectGroups{&TBSSCsects}),
467 CInfoSymSection(
".info", XCOFF::
STYP_INFO) {}
469void XCOFFObjectWriter::reset() {
471 SymbolIndexMap.
clear();
474 UndefinedCsects.clear();
476 for (
auto *Sec : Sections)
478 for (
auto &DwarfSec : DwarfSections)
480 for (
auto &OverflowSec : OverflowSections)
482 ExceptionSection.reset();
483 CInfoSymSection.reset();
486 SymbolTableEntryCount = 0;
487 SymbolTableOffset = 0;
489 PaddingsBeforeDwarf = 0;
495CsectGroup &XCOFFObjectWriter::getCsectGroup(
const MCSectionXCOFF *MCSec) {
499 "Only an initialized csect can contain program code.");
500 return ProgramCodeCsects;
503 "Only an initialized csect can contain read only data.");
504 return ReadOnlyCsects;
517 "Mapping invalid csect. CSECT with bss storage class must be "
522 "Mapping invalid csect. CSECT with tdata storage class must be "
523 "an initialized csect.");
527 "Mapping invalid csect. CSECT with tbss storage class must be "
528 "an uninitialized csect.");
532 "Only an initialized csect can contain TOC-base.");
533 assert(TOCCsects.empty() &&
534 "We should have only one TOC-base, and it should be the first csect "
535 "in this CsectGroup.");
540 "A TOC symbol must be an initialized csect.");
541 assert(!TOCCsects.empty() &&
542 "We should at least have a TOC-base in this CsectGroup.");
547 "Symbol type incompatible with toc-data.");
548 assert(!TOCCsects.empty() &&
549 "We should at least have a TOC-base in this CsectGroup.");
562void XCOFFObjectWriter::executePostLayoutBinding(
MCAssembler &Asm,
564 for (
const auto &S : Asm) {
565 const auto *MCSec = cast<const MCSectionXCOFF>(&S);
566 assert(!SectionMap.
contains(MCSec) &&
"Cannot add a section twice.");
577 "An undefined csect should not get registered.");
578 CsectGroup &Group = getCsectGroup(MCSec);
579 Group.emplace_back(MCSec);
580 SectionMap[MCSec] = &Group.back();
583 std::unique_ptr<XCOFFSection> DwarfSec =
584 std::make_unique<XCOFFSection>(MCSec);
585 SectionMap[MCSec] = DwarfSec.get();
587 DwarfSectionEntry SecEntry(MCSec->
getName(),
589 std::move(DwarfSec));
590 DwarfSections.push_back(std::move(SecEntry));
604 HasVisibility =
true;
608 UndefinedCsects.emplace_back(ContainingCsect);
609 SectionMap[ContainingCsect] = &UndefinedCsects.back();
625 "Expected containing csect to exist in map");
626 XCOFFSection *Csect = SectionMap[ContainingCsect];
628 assert(Csect->MCSec->isCsect() &&
"only csect is supported now!");
629 Csect->Syms.emplace_back(XSym);
637 std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymSection.Entry;
638 if (CISI && nameShouldBeInStringTable(CISI->Name))
639 Strings.add(CISI->Name);
641 FileNames =
Asm.getFileNames();
643 if (FileNames.empty())
644 FileNames.emplace_back(
".file", 0);
645 for (
const std::pair<std::string, size_t> &
F : FileNames) {
646 if (auxFileSymNameShouldBeInStringTable(
F.first))
647 Strings.add(
F.first);
652 if (nameShouldBeInStringTable(
".file"))
653 Strings.add(
".file");
655 if (auxFileSymNameShouldBeInStringTable(Vers))
659 assignAddressesAndIndices(Asm, Layout);
662void XCOFFObjectWriter::recordRelocation(
MCAssembler &Asm,
673 ? SymbolIndexMap[
Sym]
677 auto getVirtualAddress =
681 if (ContainingSect->isDwarfSect())
685 if (!
Sym->isDefined())
686 return SectionMap[ContainingSect]->Address;
689 assert(
Sym->isDefined() &&
"not a valid object that has address!");
701 std::tie(
Type, SignAndSize) =
702 TargetObjectWriter->getRelocTypeAndSignSize(
Target,
Fixup, IsPCRel);
704 const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
706 "Expected containing csect to exist in map.");
710 "Fragment offset + fixup offset is overflowed.");
715 if (
Type == XCOFF::RelocationType::R_POS ||
716 Type == XCOFF::RelocationType::R_TLS ||
717 Type == XCOFF::RelocationType::R_TLS_LE ||
718 Type == XCOFF::RelocationType::R_TLS_IE ||
719 Type == XCOFF::RelocationType::R_TLS_LD)
722 FixedValue = getVirtualAddress(SymA, SymASec) +
Target.getConstant();
723 else if (
Type == XCOFF::RelocationType::R_TLSM)
727 else if (
Type == XCOFF::RelocationType::R_TOC ||
728 Type == XCOFF::RelocationType::R_TOCL) {
739 const int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
740 TOCCsects.front().Address +
742 if (
Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset))
745 FixedValue = TOCEntryOffset;
747 }
else if (
Type == XCOFF::RelocationType::R_RBR) {
751 "Only XMC_PR csect may have the R_RBR relocation.");
756 SectionMap[ParentSec]->Address + FixupOffsetInCsect;
759 FixedValue = getVirtualAddress(SymA, SymASec) - BRInstrAddress +
761 }
else if (
Type == XCOFF::RelocationType::R_REF) {
765 FixupOffsetInCsect = 0;
768 XCOFFRelocation Reloc = {
Index, FixupOffsetInCsect, SignAndSize,
Type};
771 "Expected containing csect to exist in map.");
772 SectionMap[RelocationSec]->Relocations.push_back(Reloc);
781 const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
783 "Expected containing csect to exist in map.");
784 if (SymASec == SymBSec)
786 "relocation for paired relocatable term is not yet supported");
788 assert(
Type == XCOFF::RelocationType::R_POS &&
789 "SymA must be R_POS here if it's not opposite term or paired "
790 "relocatable term.");
791 const uint32_t IndexB = getIndex(SymB, SymBSec);
794 const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
795 XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
796 SectionMap[RelocationSec]->Relocations.push_back(RelocB);
799 FixedValue -= getVirtualAddress(SymB, SymBSec);
802void XCOFFObjectWriter::writeSections(
const MCAssembler &Asm,
804 uint64_t CurrentAddressLocation = 0;
805 for (
const auto *Section : Sections)
806 writeSectionForControlSectionEntry(Asm, Layout, *Section,
807 CurrentAddressLocation);
808 for (
const auto &DwarfSection : DwarfSections)
809 writeSectionForDwarfSectionEntry(Asm, Layout, DwarfSection,
810 CurrentAddressLocation);
811 writeSectionForExceptionSectionEntry(Asm, Layout, ExceptionSection,
812 CurrentAddressLocation);
813 writeSectionForCInfoSymSectionEntry(Asm, Layout, CInfoSymSection,
814 CurrentAddressLocation);
822 if (
Asm.isIncrementalLinkerCompatible())
825 finalizeSectionInfo();
829 writeAuxFileHeader();
830 writeSectionHeaderTable();
831 writeSections(Asm, Layout);
837 return W.OS.tell() - StartOffset;
840bool XCOFFObjectWriter::nameShouldBeInStringTable(
const StringRef &SymbolName) {
844void XCOFFObjectWriter::writeSymbolName(
const StringRef &SymbolName) {
846 if (nameShouldBeInStringTable(SymbolName)) {
848 W.write<
uint32_t>(Strings.getOffset(SymbolName));
858 int16_t SectionNumber,
861 uint8_t NumberOfAuxEntries) {
864 W.write<
uint32_t>(Strings.getOffset(SymbolName));
866 writeSymbolName(SymbolName);
869 W.write<int16_t>(SectionNumber);
872 W.write<uint8_t>(NumberOfAuxEntries);
875void XCOFFObjectWriter::writeSymbolAuxCsectEntry(
uint64_t SectionOrLength,
876 uint8_t SymbolAlignmentAndType,
881 W.write<uint8_t>(SymbolAlignmentAndType);
893bool XCOFFObjectWriter::auxFileSymNameShouldBeInStringTable(
898void XCOFFObjectWriter::writeAuxFileSymName(
const StringRef &SymbolName) {
900 if (auxFileSymNameShouldBeInStringTable(SymbolName)) {
902 W.write<
uint32_t>(Strings.getOffset(SymbolName));
912void XCOFFObjectWriter::writeSymbolAuxFileEntry(
StringRef &
Name,
914 writeAuxFileSymName(
Name);
915 W.write<uint8_t>(ftype);
923void XCOFFObjectWriter::writeSymbolAuxDwarfEntry(
925 writeWord(LengthOfSectionPortion);
928 writeWord(NumberOfRelocEnt);
937void XCOFFObjectWriter::writeSymbolEntryForCsectMemberLabel(
938 const Symbol &SymbolRef,
const XCOFFSection &CSectionRef,
939 int16_t SectionIndex,
uint64_t SymbolOffset) {
940 assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address &&
941 "Symbol address overflowed.");
943 auto Entry = ExceptionSection.ExceptionTable.find(SymbolRef.MCSym->getName());
944 if (Entry != ExceptionSection.ExceptionTable.end()) {
945 writeSymbolEntry(SymbolRef.getSymbolTableName(),
946 CSectionRef.Address + SymbolOffset, SectionIndex,
950 is64Bit() ? SymbolRef.getVisibilityType()
951 : SymbolRef.getVisibilityType() | 0x0020,
952 SymbolRef.getStorageClass(),
953 (
is64Bit() && ExceptionSection.isDebugEnabled) ? 3 : 2);
954 if (
is64Bit() && ExceptionSection.isDebugEnabled) {
957 writeSymbolAuxExceptionEntry(
958 ExceptionSection.FileOffsetToData +
959 getExceptionOffset(Entry->second.FunctionSymbol),
960 Entry->second.FunctionSize,
961 SymbolIndexMap[Entry->second.FunctionSymbol] + 4);
965 writeSymbolAuxFunctionEntry(
966 ExceptionSection.FileOffsetToData +
967 getExceptionOffset(Entry->second.FunctionSymbol),
968 Entry->second.FunctionSize, 0,
969 (
is64Bit() && ExceptionSection.isDebugEnabled)
970 ? SymbolIndexMap[Entry->second.FunctionSymbol] + 4
971 : SymbolIndexMap[Entry->second.FunctionSymbol] + 3);
973 writeSymbolEntry(SymbolRef.getSymbolTableName(),
974 CSectionRef.Address + SymbolOffset, SectionIndex,
975 SymbolRef.getVisibilityType(),
976 SymbolRef.getStorageClass());
978 writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex,
XCOFF::XTY_LD,
979 CSectionRef.MCSec->getMappingClass());
982void XCOFFObjectWriter::writeSymbolEntryForDwarfSection(
983 const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) {
984 assert(DwarfSectionRef.MCSec->isDwarfSect() &&
"Not a DWARF section!");
986 writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), 0,
989 writeSymbolAuxDwarfEntry(DwarfSectionRef.Size);
992void XCOFFObjectWriter::writeSymbolEntryForControlSection(
993 const XCOFFSection &CSectionRef, int16_t SectionIndex,
995 writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address,
996 SectionIndex, CSectionRef.getVisibilityType(),
StorageClass);
998 writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec),
999 CSectionRef.MCSec->getMappingClass());
1002void XCOFFObjectWriter::writeSymbolAuxFunctionEntry(
uint32_t EntryOffset,
1007 writeWord(LineNumberPointer);
1012 writeWord(LineNumberPointer);
1015 W.OS.write_zeros(1);
1018 W.OS.write_zeros(2);
1022void XCOFFObjectWriter::writeSymbolAuxExceptionEntry(
uint64_t EntryOffset,
1025 assert(
is64Bit() &&
"Exception auxilliary entries are 64-bit only.");
1029 W.OS.write_zeros(1);
1033void XCOFFObjectWriter::writeFileHeader() {
1036 W.write<int32_t>(0);
1037 writeWord(SymbolTableOffset);
1039 W.write<
uint16_t>(auxiliaryHeaderSize());
1041 W.write<int32_t>(SymbolTableEntryCount);
1043 W.write<int32_t>(SymbolTableEntryCount);
1044 W.write<
uint16_t>(auxiliaryHeaderSize());
1049void XCOFFObjectWriter::writeAuxFileHeader() {
1050 if (!auxiliaryHeaderSize())
1061 W.write<
uint32_t>(Sections[0]->Address);
1062 W.write<
uint32_t>(Sections[1]->Address);
1065void XCOFFObjectWriter::writeSectionHeader(
const SectionEntry *Sec) {
1069 if (Sec->Index == SectionEntry::UninitializedIndex)
1078 writeWord(IsDwarf ? 0 : Sec->Address);
1080 writeWord((IsDwarf || IsOvrflo) ? 0 : Sec->Address);
1082 writeWord(Sec->Size);
1083 writeWord(Sec->FileOffsetToData);
1084 writeWord(Sec->FileOffsetToRelocations);
1088 W.write<
uint32_t>(Sec->RelocationCount);
1090 W.write<int32_t>(Sec->Flags);
1091 W.OS.write_zeros(4);
1097 W.write<
uint16_t>(Sec->RelocationCount);
1099 ? Sec->RelocationCount
1101 W.write<int32_t>(Sec->Flags);
1105void XCOFFObjectWriter::writeSectionHeaderTable() {
1106 for (
const auto *CsectSec : Sections)
1107 writeSectionHeader(CsectSec);
1108 for (
const auto &DwarfSec : DwarfSections)
1109 writeSectionHeader(&DwarfSec);
1110 for (
const auto &OverflowSec : OverflowSections)
1111 writeSectionHeader(&OverflowSec);
1112 if (hasExceptionSection())
1113 writeSectionHeader(&ExceptionSection);
1114 if (CInfoSymSection.Entry)
1115 writeSectionHeader(&CInfoSymSection);
1118void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
1119 const XCOFFSection &Section) {
1121 writeWord(
Section.Address + Reloc.FixupOffsetInCsect);
1124 assert(
Section.MCSec->isDwarfSect() &&
"unsupport section type!");
1125 writeWord(Reloc.FixupOffsetInCsect);
1127 W.write<
uint32_t>(Reloc.SymbolTableIndex);
1128 W.write<uint8_t>(Reloc.SignAndSize);
1129 W.write<uint8_t>(Reloc.Type);
1132void XCOFFObjectWriter::writeRelocations() {
1133 for (
const auto *Section : Sections) {
1134 if (
Section->Index == SectionEntry::UninitializedIndex)
1138 for (
const auto *Group :
Section->Groups) {
1142 for (
const auto &Csect : *Group) {
1143 for (
const auto Reloc : Csect.Relocations)
1144 writeRelocation(Reloc, Csect);
1149 for (
const auto &DwarfSection : DwarfSections)
1150 for (
const auto &Reloc : DwarfSection.DwarfSect->Relocations)
1151 writeRelocation(Reloc, *DwarfSection.DwarfSect);
1154void XCOFFObjectWriter::writeSymbolTable(
MCAssembler &Asm,
1159 for (
const std::pair<std::string, size_t> &
F : FileNames) {
1187 int NumberOfFileAuxEntries = 1;
1189 ++NumberOfFileAuxEntries;
1190 writeSymbolEntry(
".file", 0, XCOFF::ReservedSectionNum::N_DEBUG,
1192 NumberOfFileAuxEntries);
1198 if (CInfoSymSection.Entry)
1199 writeSymbolEntry(CInfoSymSection.Entry->Name, CInfoSymSection.Entry->Offset,
1200 CInfoSymSection.Index,
1204 for (
const auto &Csect : UndefinedCsects) {
1205 writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF,
1206 Csect.MCSec->getStorageClass());
1209 for (
const auto *Section : Sections) {
1210 if (
Section->Index == SectionEntry::UninitializedIndex)
1214 for (
const auto *Group :
Section->Groups) {
1218 const int16_t SectionIndex =
Section->Index;
1219 for (
const auto &Csect : *Group) {
1221 writeSymbolEntryForControlSection(Csect, SectionIndex,
1222 Csect.MCSec->getStorageClass());
1224 for (
const auto &
Sym : Csect.Syms)
1225 writeSymbolEntryForCsectMemberLabel(
1231 for (
const auto &DwarfSection : DwarfSections)
1232 writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect,
1233 DwarfSection.Index);
1236void XCOFFObjectWriter::finalizeRelocationInfo(
SectionEntry *Sec,
1246 SecEntry.RelocationCount = Sec->Index;
1250 SecEntry.Address = RelCount;
1251 SecEntry.Index = ++SectionCount;
1252 OverflowSections.push_back(std::move(SecEntry));
1258 Sec->RelocationCount = RelCount;
1262void XCOFFObjectWriter::calcOffsetToRelocations(
SectionEntry *Sec,
1264 if (!Sec->RelocationCount)
1267 Sec->FileOffsetToRelocations = RawPointer;
1272 for (
auto &OverflowSec : OverflowSections) {
1273 if (OverflowSec.RelocationCount ==
static_cast<uint32_t>(Sec->Index)) {
1274 RelocationSizeInSec =
1279 OverflowSec.FileOffsetToRelocations = Sec->FileOffsetToRelocations;
1282 assert(RelocationSizeInSec &&
"Overflow section header doesn't exist.");
1284 RelocationSizeInSec = Sec->RelocationCount *
1289 RawPointer += RelocationSizeInSec;
1290 if (RawPointer > MaxRawDataSize)
1294void XCOFFObjectWriter::finalizeSectionInfo() {
1295 for (
auto *Section : Sections) {
1296 if (
Section->Index == SectionEntry::UninitializedIndex)
1301 for (
const auto *Group :
Section->Groups) {
1305 for (
auto &Csect : *Group)
1306 RelCount += Csect.Relocations.size();
1308 finalizeRelocationInfo(Section, RelCount);
1311 for (
auto &DwarfSection : DwarfSections)
1312 finalizeRelocationInfo(&DwarfSection,
1313 DwarfSection.DwarfSect->Relocations.size());
1321 auxiliaryHeaderSize();
1324 for (
auto *Sec : Sections) {
1325 if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual)
1328 RawPointer = Sec->advanceFileOffset(MaxRawDataSize, RawPointer);
1331 if (!DwarfSections.empty()) {
1332 RawPointer += PaddingsBeforeDwarf;
1333 for (
auto &DwarfSection : DwarfSections) {
1334 RawPointer = DwarfSection.advanceFileOffset(MaxRawDataSize, RawPointer);
1338 if (hasExceptionSection())
1339 RawPointer = ExceptionSection.advanceFileOffset(MaxRawDataSize, RawPointer);
1341 if (CInfoSymSection.Entry)
1342 RawPointer = CInfoSymSection.advanceFileOffset(MaxRawDataSize, RawPointer);
1344 for (
auto *Sec : Sections) {
1345 if (Sec->Index != SectionEntry::UninitializedIndex)
1346 calcOffsetToRelocations(Sec, RawPointer);
1349 for (
auto &DwarfSec : DwarfSections)
1350 calcOffsetToRelocations(&DwarfSec, RawPointer);
1354 if (SymbolTableEntryCount)
1355 SymbolTableOffset = RawPointer;
1358void XCOFFObjectWriter::addExceptionEntry(
1360 unsigned ReasonCode,
unsigned FunctionSize,
bool hasDebug) {
1364 ExceptionSection.isDebugEnabled =
true;
1365 auto Entry = ExceptionSection.ExceptionTable.find(
Symbol->getName());
1366 if (Entry != ExceptionSection.ExceptionTable.end()) {
1367 Entry->second.Entries.push_back(
1368 ExceptionTableEntry(
Trap, LanguageCode, ReasonCode));
1371 ExceptionInfo NewEntry;
1372 NewEntry.FunctionSymbol =
Symbol;
1373 NewEntry.FunctionSize = FunctionSize;
1374 NewEntry.Entries.push_back(
1375 ExceptionTableEntry(
Trap, LanguageCode, ReasonCode));
1376 ExceptionSection.ExceptionTable.insert(
1377 std::pair<const StringRef, ExceptionInfo>(
Symbol->getName(), NewEntry));
1380unsigned XCOFFObjectWriter::getExceptionSectionSize() {
1381 unsigned EntryNum = 0;
1383 for (
auto it = ExceptionSection.ExceptionTable.begin();
1384 it != ExceptionSection.ExceptionTable.end(); ++it)
1387 EntryNum += it->second.Entries.size() + 1;
1393unsigned XCOFFObjectWriter::getExceptionOffset(
const MCSymbol *Symbol) {
1394 unsigned EntryNum = 0;
1395 for (
auto it = ExceptionSection.ExceptionTable.begin();
1396 it != ExceptionSection.ExceptionTable.end(); ++it) {
1397 if (Symbol == it->second.FunctionSymbol)
1399 EntryNum += it->second.Entries.size() + 1;
1406 assert(!CInfoSymSection.Entry &&
"Multiple entries are not supported");
1407 CInfoSymSection.addEntry(
1408 std::make_unique<CInfoSymInfo>(
Name.str(),
Metadata.str()));
1411void XCOFFObjectWriter::assignAddressesAndIndices(
MCAssembler &Asm,
1416 (2 + (
Asm.getCompilerVersion().empty() ? 0 : 1)) * FileNames.size();
1418 if (CInfoSymSection.Entry)
1422 for (
auto &Csect : UndefinedCsects) {
1425 Csect.SymbolTableIndex = SymbolTableIndex;
1426 SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
1428 SymbolTableIndex += 2;
1436 int32_t SectionIndex = 1;
1437 bool HasTDataSection =
false;
1439 for (
auto *Section : Sections) {
1440 const bool IsEmpty =
1442 [](
const CsectGroup *Group) { return Group->empty(); });
1446 if (SectionIndex > MaxSectionIndex)
1448 Section->Index = SectionIndex++;
1451 bool SectionAddressSet =
false;
1455 HasTDataSection =
true;
1462 for (
auto *Group :
Section->Groups) {
1466 for (
auto &Csect : *Group) {
1470 Address = Csect.Address + Csect.Size;
1471 Csect.SymbolTableIndex = SymbolTableIndex;
1474 SymbolTableIndex += 2;
1476 for (
auto &
Sym : Csect.Syms) {
1477 bool hasExceptEntry =
false;
1479 ExceptionSection.ExceptionTable.find(
Sym.MCSym->getName());
1480 if (Entry != ExceptionSection.ExceptionTable.end()) {
1481 hasExceptEntry =
true;
1482 for (
auto &TrapEntry : Entry->second.Entries) {
1484 TrapEntry.Trap->getOffset();
1487 Sym.SymbolTableIndex = SymbolTableIndex;
1488 SymbolIndexMap[
Sym.MCSym] =
Sym.SymbolTableIndex;
1493 SymbolTableIndex += 2;
1494 if (hasExceptionSection() && hasExceptEntry) {
1495 if (
is64Bit() && ExceptionSection.isDebugEnabled)
1496 SymbolTableIndex += 2;
1498 SymbolTableIndex += 1;
1503 if (!SectionAddressSet) {
1504 Section->Address = Group->front().Address;
1505 SectionAddressSet =
true;
1520 if (!DwarfSections.empty())
1521 PaddingsBeforeDwarf =
1523 (*DwarfSections.begin()).DwarfSect->MCSec->getAlign()) -
1526 DwarfSectionEntry *LastDwarfSection =
nullptr;
1527 for (
auto &DwarfSection : DwarfSections) {
1528 assert((SectionIndex <= MaxSectionIndex) &&
"Section index overflow!");
1530 XCOFFSection &DwarfSect = *DwarfSection.DwarfSect;
1534 DwarfSection.Index = SectionIndex++;
1538 DwarfSect.SymbolTableIndex = SymbolTableIndex;
1541 SymbolTableIndex += 2;
1547 DwarfSection.Address = DwarfSect.Address =
1554 Address = DwarfSection.Address + DwarfSection.Size;
1556 if (LastDwarfSection)
1557 LastDwarfSection->MemorySize =
1558 DwarfSection.Address - LastDwarfSection->Address;
1559 LastDwarfSection = &DwarfSection;
1561 if (LastDwarfSection) {
1564 Address =
alignTo(LastDwarfSection->Address + LastDwarfSection->Size,
1565 DefaultSectionAlign);
1566 LastDwarfSection->MemorySize =
Address - LastDwarfSection->Address;
1568 if (hasExceptionSection()) {
1569 ExceptionSection.Index = SectionIndex++;
1571 ExceptionSection.Address = 0;
1572 ExceptionSection.Size = getExceptionSectionSize();
1573 Address += ExceptionSection.Size;
1577 if (CInfoSymSection.Entry) {
1578 CInfoSymSection.Index = SectionIndex++;
1580 CInfoSymSection.Address = 0;
1581 Address += CInfoSymSection.Size;
1585 SymbolTableEntryCount = SymbolTableIndex;
1588void XCOFFObjectWriter::writeSectionForControlSectionEntry(
1590 const CsectSectionEntry &CsectEntry,
uint64_t &CurrentAddressLocation) {
1592 if (CsectEntry.Index == SectionEntry::UninitializedIndex)
1599 assert(((CurrentAddressLocation <= CsectEntry.Address) ||
1602 "CurrentAddressLocation should be less than or equal to section "
1603 "address if the section is not TData or TBSS.");
1605 CurrentAddressLocation = CsectEntry.Address;
1610 if (CsectEntry.IsVirtual) {
1611 CurrentAddressLocation += CsectEntry.Size;
1615 for (
const auto &Group : CsectEntry.Groups) {
1616 for (
const auto &Csect : *Group) {
1617 if (
uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
1618 W.OS.write_zeros(PaddingSize);
1620 Asm.writeSectionData(
W.OS, Csect.MCSec, Layout);
1621 CurrentAddressLocation = Csect.Address + Csect.Size;
1629 CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) {
1630 W.OS.write_zeros(PaddingSize);
1631 CurrentAddressLocation += PaddingSize;
1635void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
1637 const DwarfSectionEntry &DwarfEntry,
uint64_t &CurrentAddressLocation) {
1641 assert(CurrentAddressLocation <= DwarfEntry.Address &&
1642 "CurrentAddressLocation should be less than or equal to section "
1645 if (
uint64_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation)
1646 W.OS.write_zeros(PaddingSize);
1648 if (DwarfEntry.Size)
1649 Asm.writeSectionData(
W.OS, DwarfEntry.DwarfSect->MCSec, Layout);
1651 CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size;
1655 uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign;
1657 if (TailPaddingSize)
1658 W.OS.write_zeros(TailPaddingSize);
1660 CurrentAddressLocation += TailPaddingSize;
1663void XCOFFObjectWriter::writeSectionForExceptionSectionEntry(
1665 ExceptionSectionEntry &ExceptionEntry,
uint64_t &CurrentAddressLocation) {
1666 for (
auto it = ExceptionEntry.ExceptionTable.begin();
1667 it != ExceptionEntry.ExceptionTable.end(); it++) {
1670 W.write<
uint32_t>(SymbolIndexMap[it->second.FunctionSymbol]);
1673 W.OS.write_zeros(4);
1675 W.OS.write_zeros(2);
1676 for (
auto &TrapEntry : it->second.Entries) {
1677 writeWord(TrapEntry.TrapAddress);
1678 W.write<uint8_t>(TrapEntry.Lang);
1679 W.write<uint8_t>(TrapEntry.Reason);
1683 CurrentAddressLocation += getExceptionSectionSize();
1686void XCOFFObjectWriter::writeSectionForCInfoSymSectionEntry(
1688 CInfoSymSectionEntry &CInfoSymEntry,
uint64_t &CurrentAddressLocation) {
1689 if (!CInfoSymSection.Entry)
1692 constexpr int WordSize =
sizeof(
uint32_t);
1693 std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymEntry.Entry;
1712 if (CISI->paddingSize()) {
1713 std::array<uint8_t, WordSize> LastWord = {0};
1718 CurrentAddressLocation += CISI->size();
1729 uint8_t EncodedAlign = Log2Align << 3;
1735std::unique_ptr<MCObjectWriter>
1738 return std::make_unique<XCOFFObjectWriter>(std::move(MOTW),
OS);
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
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.
Encapsulates the layout of an assembly file at a particular point in time.
uint64_t getSectionAddressSize(const MCSection *Sec) const
Get the address space size of the given section, as it effects layout.
bool getSymbolOffset(const MCSymbol &S, uint64_t &Val) const
Get the offset of the given symbol, as computed in the current layout.
uint64_t getFragmentOffset(const MCFragment *F) const
Get the offset of the given fragment inside its containing section.
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 uint64_t writeObject(MCAssembler &Asm, const MCAsmLayout &Layout)=0
Write the object file and returns the number of bytes written.
virtual void addExceptionEntry(const MCSymbol *Symbol, const MCSymbol *Trap, unsigned LanguageCode, unsigned ReasonCode, unsigned FunctionSize, bool hasDebug)
virtual void addCInfoSymEntry(StringRef Name, StringRef Metadata)
virtual void executePostLayoutBinding(MCAssembler &Asm, const MCAsmLayout &Layout)=0
Perform any late binding of symbols (for example, to assign symbol indices for use when generating re...
virtual void reset()
lifetime management
virtual void recordRelocation(MCAssembler &Asm, const MCAsmLayout &Layout, 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.
@ 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.
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.