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 &);
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,
381 const CsectSectionEntry &CsectEntry,
383 void writeSectionForDwarfSectionEntry(
const MCAssembler &Asm,
385 const DwarfSectionEntry &DwarfEntry,
387 void writeSectionForExceptionSectionEntry(
389 ExceptionSectionEntry &ExceptionEntry,
uint64_t &CurrentAddressLocation);
390 void writeSectionForCInfoSymSectionEntry(
const MCAssembler &Asm,
392 CInfoSymSectionEntry &CInfoSymEntry,
395 void writeSymbolAuxDwarfEntry(
uint64_t LengthOfSectionPortion,
397 void writeSymbolAuxCsectEntry(
uint64_t SectionOrLength,
398 uint8_t SymbolAlignmentAndType,
400 void writeSymbolAuxFunctionEntry(
uint32_t EntryOffset,
uint32_t FunctionSize,
403 void writeSymbolAuxExceptionEntry(
uint64_t EntryOffset,
uint32_t FunctionSize,
408 void writeRelocations();
409 void writeRelocation(XCOFFRelocation Reloc,
const XCOFFSection &Section);
419 void assignAddressesAndIndices(
const MCAsmLayout &);
421 void finalizeSectionInfo();
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);
435 size_t auxiliaryHeaderSize()
const {
441 XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
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.");
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.");
553void XCOFFObjectWriter::executePostLayoutBinding(
MCAssembler &Asm,
555 for (
const auto &S : Asm) {
556 const auto *MCSec = cast<const MCSectionXCOFF>(&S);
557 assert(!SectionMap.
contains(MCSec) &&
"Cannot add a section twice.");
568 "An undefined csect should not get registered.");
569 CsectGroup &Group = getCsectGroup(MCSec);
570 Group.emplace_back(MCSec);
571 SectionMap[MCSec] = &Group.back();
574 std::unique_ptr<XCOFFSection> DwarfSec =
575 std::make_unique<XCOFFSection>(MCSec);
576 SectionMap[MCSec] = DwarfSec.get();
578 DwarfSectionEntry SecEntry(MCSec->
getName(),
580 std::move(DwarfSec));
581 DwarfSections.push_back(std::move(SecEntry));
595 HasVisibility =
true;
599 UndefinedCsects.emplace_back(ContainingCsect);
600 SectionMap[ContainingCsect] = &UndefinedCsects.back();
616 "Expected containing csect to exist in map");
617 XCOFFSection *Csect = SectionMap[ContainingCsect];
619 assert(Csect->MCSec->isCsect() &&
"only csect is supported now!");
620 Csect->Syms.emplace_back(XSym);
628 std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymSection.Entry;
629 if (CISI && nameShouldBeInStringTable(CISI->Name))
630 Strings.add(CISI->Name);
632 FileNames =
Asm.getFileNames();
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);
645void XCOFFObjectWriter::recordRelocation(
MCAssembler &Asm,
656 ? SymbolIndexMap[
Sym]
660 auto getVirtualAddress =
664 if (ContainingSect->isDwarfSect())
668 if (!
Sym->isDefined())
669 return SectionMap[ContainingSect]->Address;
672 assert(
Sym->isDefined() &&
"not a valid object that has address!");
684 std::tie(
Type, SignAndSize) =
685 TargetObjectWriter->getRelocTypeAndSignSize(
Target,
Fixup, IsPCRel);
687 const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
689 "Expected containing csect to exist in map.");
693 "Fragment offset + fixup offset is overflowed.");
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)
704 FixedValue = getVirtualAddress(SymA, SymASec) +
Target.getConstant();
705 else if (
Type == XCOFF::RelocationType::R_TLSM)
709 else if (
Type == XCOFF::RelocationType::R_TOC ||
710 Type == XCOFF::RelocationType::R_TOCL) {
721 const int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
722 TOCCsects.front().Address +
724 if (
Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset))
727 FixedValue = TOCEntryOffset;
729 }
else if (
Type == XCOFF::RelocationType::R_RBR) {
733 "Only XMC_PR csect may have the R_RBR relocation.");
738 SectionMap[ParentSec]->Address + FixupOffsetInCsect;
741 FixedValue = getVirtualAddress(SymA, SymASec) - BRInstrAddress +
743 }
else if (
Type == XCOFF::RelocationType::R_REF) {
747 FixupOffsetInCsect = 0;
750 XCOFFRelocation Reloc = {
Index, FixupOffsetInCsect, SignAndSize,
Type};
753 "Expected containing csect to exist in map.");
754 SectionMap[RelocationSec]->Relocations.push_back(Reloc);
763 const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
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);
776 const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
777 XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
778 SectionMap[RelocationSec]->Relocations.push_back(RelocB);
781 FixedValue -= getVirtualAddress(SymB, SymBSec);
784void XCOFFObjectWriter::writeSections(
const MCAssembler &Asm,
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);
804 if (
Asm.isIncrementalLinkerCompatible())
807 finalizeSectionInfo();
811 writeAuxFileHeader();
812 writeSectionHeaderTable();
813 writeSections(Asm, Layout);
819 return W.OS.tell() - StartOffset;
822bool XCOFFObjectWriter::nameShouldBeInStringTable(
const StringRef &SymbolName) {
826void XCOFFObjectWriter::writeSymbolName(
const StringRef &SymbolName) {
828 if (nameShouldBeInStringTable(SymbolName)) {
830 W.write<
uint32_t>(Strings.getOffset(SymbolName));
840 int16_t SectionNumber,
843 uint8_t NumberOfAuxEntries) {
846 W.write<
uint32_t>(Strings.getOffset(SymbolName));
848 writeSymbolName(SymbolName);
851 W.write<int16_t>(SectionNumber);
854 W.write<uint8_t>(NumberOfAuxEntries);
857void XCOFFObjectWriter::writeSymbolAuxCsectEntry(
uint64_t SectionOrLength,
858 uint8_t SymbolAlignmentAndType,
863 W.write<uint8_t>(SymbolAlignmentAndType);
875void XCOFFObjectWriter::writeSymbolAuxDwarfEntry(
877 writeWord(LengthOfSectionPortion);
880 writeWord(NumberOfRelocEnt);
889void 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,
902 is64Bit() ? SymbolRef.getVisibilityType()
903 : SymbolRef.getVisibilityType() | 0x0020,
904 SymbolRef.getStorageClass(),
905 (
is64Bit() && ExceptionSection.isDebugEnabled) ? 3 : 2);
906 if (
is64Bit() && ExceptionSection.isDebugEnabled) {
909 writeSymbolAuxExceptionEntry(
910 ExceptionSection.FileOffsetToData +
911 getExceptionOffset(Entry->second.FunctionSymbol),
912 Entry->second.FunctionSize,
913 SymbolIndexMap[Entry->second.FunctionSymbol] + 4);
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());
934void XCOFFObjectWriter::writeSymbolEntryForDwarfSection(
935 const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) {
936 assert(DwarfSectionRef.MCSec->isDwarfSect() &&
"Not a DWARF section!");
938 writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), 0,
941 writeSymbolAuxDwarfEntry(DwarfSectionRef.Size);
944void XCOFFObjectWriter::writeSymbolEntryForControlSection(
945 const XCOFFSection &CSectionRef, int16_t SectionIndex,
947 writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address,
948 SectionIndex, CSectionRef.getVisibilityType(),
StorageClass);
950 writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec),
951 CSectionRef.MCSec->getMappingClass());
954void XCOFFObjectWriter::writeSymbolAuxFunctionEntry(
uint32_t EntryOffset,
959 writeWord(LineNumberPointer);
964 writeWord(LineNumberPointer);
974void XCOFFObjectWriter::writeSymbolAuxExceptionEntry(
uint64_t EntryOffset,
977 assert(
is64Bit() &&
"Exception auxilliary entries are 64-bit only.");
985void XCOFFObjectWriter::writeFileHeader() {
989 writeWord(SymbolTableOffset);
991 W.write<
uint16_t>(auxiliaryHeaderSize());
993 W.write<int32_t>(SymbolTableEntryCount);
995 W.write<int32_t>(SymbolTableEntryCount);
996 W.write<
uint16_t>(auxiliaryHeaderSize());
1001void XCOFFObjectWriter::writeAuxFileHeader() {
1002 if (!auxiliaryHeaderSize())
1013 W.write<
uint32_t>(Sections[0]->Address);
1014 W.write<
uint32_t>(Sections[1]->Address);
1017void XCOFFObjectWriter::writeSectionHeader(
const SectionEntry *Sec) {
1021 if (Sec->Index == SectionEntry::UninitializedIndex)
1030 writeWord(IsDwarf ? 0 : Sec->Address);
1032 writeWord((IsDwarf || IsOvrflo) ? 0 : Sec->Address);
1034 writeWord(Sec->Size);
1035 writeWord(Sec->FileOffsetToData);
1036 writeWord(Sec->FileOffsetToRelocations);
1040 W.write<
uint32_t>(Sec->RelocationCount);
1042 W.write<int32_t>(Sec->Flags);
1043 W.OS.write_zeros(4);
1049 W.write<
uint16_t>(Sec->RelocationCount);
1051 ? Sec->RelocationCount
1053 W.write<int32_t>(Sec->Flags);
1057void 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);
1070void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
1071 const XCOFFSection &Section) {
1073 writeWord(
Section.Address + Reloc.FixupOffsetInCsect);
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);
1084void XCOFFObjectWriter::writeRelocations() {
1085 for (
const auto *Section : Sections) {
1086 if (
Section->Index == SectionEntry::UninitializedIndex)
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);
1106void XCOFFObjectWriter::writeSymbolTable(
const MCAsmLayout &Layout) {
1108 for (
const std::pair<std::string, size_t> &
F : FileNames) {
1136 writeSymbolEntry(FileName, 0, XCOFF::ReservedSectionNum::N_DEBUG,
1141 if (CInfoSymSection.Entry)
1142 writeSymbolEntry(CInfoSymSection.Entry->Name, CInfoSymSection.Entry->Offset,
1143 CInfoSymSection.Index,
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)
1157 for (
const auto *Group :
Section->Groups) {
1161 const int16_t SectionIndex =
Section->Index;
1162 for (
const auto &Csect : *Group) {
1164 writeSymbolEntryForControlSection(Csect, SectionIndex,
1165 Csect.MCSec->getStorageClass());
1167 for (
const auto &
Sym : Csect.Syms)
1168 writeSymbolEntryForCsectMemberLabel(
1174 for (
const auto &DwarfSection : DwarfSections)
1175 writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect,
1176 DwarfSection.Index);
1179void XCOFFObjectWriter::finalizeRelocationInfo(
SectionEntry *Sec,
1189 SecEntry.RelocationCount = Sec->Index;
1193 SecEntry.Address = RelCount;
1194 SecEntry.Index = ++SectionCount;
1195 OverflowSections.push_back(std::move(SecEntry));
1201 Sec->RelocationCount = RelCount;
1205void XCOFFObjectWriter::calcOffsetToRelocations(
SectionEntry *Sec,
1207 if (!Sec->RelocationCount)
1210 Sec->FileOffsetToRelocations = RawPointer;
1215 for (
auto &OverflowSec : OverflowSections) {
1216 if (OverflowSec.RelocationCount ==
static_cast<uint32_t>(Sec->Index)) {
1217 RelocationSizeInSec =
1222 OverflowSec.FileOffsetToRelocations = Sec->FileOffsetToRelocations;
1225 assert(RelocationSizeInSec &&
"Overflow section header doesn't exist.");
1227 RelocationSizeInSec = Sec->RelocationCount *
1232 RawPointer += RelocationSizeInSec;
1233 if (RawPointer > MaxRawDataSize)
1237void XCOFFObjectWriter::finalizeSectionInfo() {
1238 for (
auto *Section : Sections) {
1239 if (
Section->Index == SectionEntry::UninitializedIndex)
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());
1264 auxiliaryHeaderSize();
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);
1297 if (SymbolTableEntryCount)
1298 SymbolTableOffset = RawPointer;
1301void XCOFFObjectWriter::addExceptionEntry(
1303 unsigned ReasonCode,
unsigned FunctionSize,
bool hasDebug) {
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));
1323unsigned XCOFFObjectWriter::getExceptionSectionSize() {
1324 unsigned EntryNum = 0;
1326 for (
auto it = ExceptionSection.ExceptionTable.begin();
1327 it != ExceptionSection.ExceptionTable.end(); ++it)
1330 EntryNum += it->second.Entries.size() + 1;
1336unsigned 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;
1349 assert(!CInfoSymSection.Entry &&
"Multiple entries are not supported");
1350 CInfoSymSection.addEntry(
1351 std::make_unique<CInfoSymInfo>(
Name.str(),
Metadata.str()));
1354void XCOFFObjectWriter::assignAddressesAndIndices(
const MCAsmLayout &Layout) {
1356 uint32_t SymbolTableIndex = FileNames.size();
1358 if (CInfoSymSection.Entry)
1362 for (
auto &Csect : UndefinedCsects) {
1365 Csect.SymbolTableIndex = SymbolTableIndex;
1366 SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
1368 SymbolTableIndex += 2;
1376 int32_t SectionIndex = 1;
1377 bool HasTDataSection =
false;
1379 for (
auto *Section : Sections) {
1380 const bool IsEmpty =
1382 [](
const CsectGroup *Group) { return Group->empty(); });
1386 if (SectionIndex > MaxSectionIndex)
1388 Section->Index = SectionIndex++;
1391 bool SectionAddressSet =
false;
1395 HasTDataSection =
true;
1402 for (
auto *Group :
Section->Groups) {
1406 for (
auto &Csect : *Group) {
1410 Address = Csect.Address + Csect.Size;
1411 Csect.SymbolTableIndex = SymbolTableIndex;
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) {
1424 TrapEntry.Trap->getOffset();
1427 Sym.SymbolTableIndex = SymbolTableIndex;
1428 SymbolIndexMap[
Sym.MCSym] =
Sym.SymbolTableIndex;
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;
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;
1474 DwarfSection.Index = SectionIndex++;
1478 DwarfSect.SymbolTableIndex = SymbolTableIndex;
1481 SymbolTableIndex += 2;
1487 DwarfSection.Address = DwarfSect.Address =
1494 Address = DwarfSection.Address + DwarfSection.Size;
1496 if (LastDwarfSection)
1497 LastDwarfSection->MemorySize =
1498 DwarfSection.Address - LastDwarfSection->Address;
1499 LastDwarfSection = &DwarfSection;
1501 if (LastDwarfSection) {
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;
1517 if (CInfoSymSection.Entry) {
1518 CInfoSymSection.Index = SectionIndex++;
1520 CInfoSymSection.Address = 0;
1521 Address += CInfoSymSection.Size;
1525 SymbolTableEntryCount = SymbolTableIndex;
1528void XCOFFObjectWriter::writeSectionForControlSectionEntry(
1530 const CsectSectionEntry &CsectEntry,
uint64_t &CurrentAddressLocation) {
1532 if (CsectEntry.Index == SectionEntry::UninitializedIndex)
1539 assert(((CurrentAddressLocation <= CsectEntry.Address) ||
1542 "CurrentAddressLocation should be less than or equal to section "
1543 "address if the section is not TData or TBSS.");
1545 CurrentAddressLocation = CsectEntry.Address;
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;
1569 CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) {
1570 W.OS.write_zeros(PaddingSize);
1571 CurrentAddressLocation += PaddingSize;
1575void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
1577 const DwarfSectionEntry &DwarfEntry,
uint64_t &CurrentAddressLocation) {
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;
1595 uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign;
1597 if (TailPaddingSize)
1598 W.OS.write_zeros(TailPaddingSize);
1600 CurrentAddressLocation += TailPaddingSize;
1603void XCOFFObjectWriter::writeSectionForExceptionSectionEntry(
1605 ExceptionSectionEntry &ExceptionEntry,
uint64_t &CurrentAddressLocation) {
1606 for (
auto it = ExceptionEntry.ExceptionTable.begin();
1607 it != ExceptionEntry.ExceptionTable.end(); it++) {
1610 W.write<
uint32_t>(SymbolIndexMap[it->second.FunctionSymbol]);
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();
1626void XCOFFObjectWriter::writeSectionForCInfoSymSectionEntry(
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;
1652 if (CISI->paddingSize()) {
1653 std::array<uint8_t, WordSize> LastWord = {0};
1658 CurrentAddressLocation += CISI->size();
1669 uint8_t EncodedAlign = Log2Align << 3;
1675std::unique_ptr<MCObjectWriter>
1678 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.
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
@ AUX_SECT
Identifies a SECT 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
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
@ 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.