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();
298 bool HasVisibility =
false;
301 std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
305 TargetObjectWriter->is64Bit() ?
UINT64_MAX : UINT32_MAX;
319 CsectGroup UndefinedCsects;
320 CsectGroup ProgramCodeCsects;
321 CsectGroup ReadOnlyCsects;
322 CsectGroup DataCsects;
323 CsectGroup FuncDSCsects;
324 CsectGroup TOCCsects;
325 CsectGroup BSSCsects;
326 CsectGroup TDataCsects;
327 CsectGroup TBSSCsects;
330 CsectSectionEntry
Text;
331 CsectSectionEntry
Data;
332 CsectSectionEntry BSS;
333 CsectSectionEntry TData;
334 CsectSectionEntry TBSS;
338 std::array<CsectSectionEntry *const, 5> Sections{
339 {&
Text, &
Data, &BSS, &TData, &TBSS}};
341 std::vector<DwarfSectionEntry> DwarfSections;
342 std::vector<SectionEntry> OverflowSections;
344 ExceptionSectionEntry ExceptionSection;
345 CInfoSymSectionEntry CInfoSymSection;
349 void reset()
override;
358 bool is64Bit()
const {
return TargetObjectWriter->is64Bit(); }
359 bool nameShouldBeInStringTable(
const StringRef &);
361 bool auxFileSymNameShouldBeInStringTable(
const StringRef &);
362 void writeAuxFileSymName(
const StringRef &);
364 void writeSymbolEntryForCsectMemberLabel(
const Symbol &SymbolRef,
365 const XCOFFSection &CSectionRef,
366 int16_t SectionIndex,
368 void writeSymbolEntryForControlSection(
const XCOFFSection &CSectionRef,
369 int16_t SectionIndex,
371 void writeSymbolEntryForDwarfSection(
const XCOFFSection &DwarfSectionRef,
372 int16_t SectionIndex);
373 void writeFileHeader();
374 void writeAuxFileHeader();
376 void writeSectionHeaderTable();
378 void writeSectionForControlSectionEntry(
const MCAssembler &Asm,
379 const CsectSectionEntry &CsectEntry,
381 void writeSectionForDwarfSectionEntry(
const MCAssembler &Asm,
382 const DwarfSectionEntry &DwarfEntry,
385 writeSectionForExceptionSectionEntry(
const MCAssembler &Asm,
386 ExceptionSectionEntry &ExceptionEntry,
388 void writeSectionForCInfoSymSectionEntry(
const MCAssembler &Asm,
389 CInfoSymSectionEntry &CInfoSymEntry,
393 void writeSymbolAuxDwarfEntry(
uint64_t LengthOfSectionPortion,
395 void writeSymbolAuxCsectEntry(
uint64_t SectionOrLength,
396 uint8_t SymbolAlignmentAndType,
398 void writeSymbolAuxFunctionEntry(
uint32_t EntryOffset,
uint32_t FunctionSize,
401 void writeSymbolAuxExceptionEntry(
uint64_t EntryOffset,
uint32_t FunctionSize,
406 void writeRelocations();
407 void writeRelocation(XCOFFRelocation Reloc,
const XCOFFSection &Section);
419 void finalizeSectionInfo();
423 bool hasExceptionSection() {
424 return !ExceptionSection.ExceptionTable.empty();
426 unsigned getExceptionSectionSize();
427 unsigned getExceptionOffset(
const MCSymbol *Symbol);
429 size_t auxiliaryHeaderSize()
const {
435 XCOFFWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
443 unsigned LanguageCode,
unsigned ReasonCode,
444 unsigned FunctionSize,
bool hasDebug)
override;
448XCOFFWriter::XCOFFWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
453 CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
455 CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
457 CsectGroups{&BSSCsects}),
459 CsectGroups{&TDataCsects}),
461 CsectGroups{&TBSSCsects}),
463 CInfoSymSection(
".info", XCOFF::
STYP_INFO) {}
465void XCOFFWriter::reset() {
467 SymbolIndexMap.
clear();
470 UndefinedCsects.clear();
472 for (
auto *Sec : Sections)
474 for (
auto &DwarfSec : DwarfSections)
476 for (
auto &OverflowSec : OverflowSections)
478 ExceptionSection.reset();
479 CInfoSymSection.reset();
482 SymbolTableEntryCount = 0;
483 SymbolTableOffset = 0;
485 PaddingsBeforeDwarf = 0;
491CsectGroup &XCOFFWriter::getCsectGroup(
const MCSectionXCOFF *MCSec) {
495 "Only an initialized csect can contain program code.");
496 return ProgramCodeCsects;
499 "Only an initialized csect can contain read only data.");
500 return ReadOnlyCsects;
513 "Mapping invalid csect. CSECT with bss storage class must be "
518 "Mapping invalid csect. CSECT with tdata storage class must be "
519 "an initialized csect.");
523 "Mapping invalid csect. CSECT with tbss storage class must be "
524 "an uninitialized csect.");
528 "Only an initialized csect can contain TOC-base.");
529 assert(TOCCsects.empty() &&
530 "We should have only one TOC-base, and it should be the first csect "
531 "in this CsectGroup.");
536 "A TOC symbol must be an initialized csect.");
537 assert(!TOCCsects.empty() &&
538 "We should at least have a TOC-base in this CsectGroup.");
543 "Symbol type incompatible with toc-data.");
544 assert(!TOCCsects.empty() &&
545 "We should at least have a TOC-base in this CsectGroup.");
558void XCOFFWriter::executePostLayoutBinding(
MCAssembler &Asm) {
559 for (
const auto &S : Asm) {
560 const auto *MCSec = cast<const MCSectionXCOFF>(&S);
561 assert(!SectionMap.
contains(MCSec) &&
"Cannot add a section twice.");
572 "An undefined csect should not get registered.");
573 CsectGroup &Group = getCsectGroup(MCSec);
574 Group.emplace_back(MCSec);
575 SectionMap[MCSec] = &Group.back();
578 std::unique_ptr<XCOFFSection> DwarfSec =
579 std::make_unique<XCOFFSection>(MCSec);
580 SectionMap[MCSec] = DwarfSec.get();
582 DwarfSectionEntry SecEntry(MCSec->
getName(),
584 std::move(DwarfSec));
585 DwarfSections.push_back(std::move(SecEntry));
602 HasVisibility =
true;
606 UndefinedCsects.emplace_back(ContainingCsect);
607 SectionMap[ContainingCsect] = &UndefinedCsects.back();
623 "Expected containing csect to exist in map");
624 XCOFFSection *Csect = SectionMap[ContainingCsect];
626 assert(Csect->MCSec->isCsect() &&
"only csect is supported now!");
627 Csect->Syms.emplace_back(XSym);
635 std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymSection.Entry;
636 if (CISI && nameShouldBeInStringTable(CISI->Name))
637 Strings.add(CISI->Name);
640 if (FileNames.empty())
641 FileNames.emplace_back(
".file", 0);
642 for (
const std::pair<std::string, size_t> &
F : FileNames) {
643 if (auxFileSymNameShouldBeInStringTable(
F.first))
644 Strings.add(
F.first);
649 if (nameShouldBeInStringTable(
".file"))
650 Strings.add(
".file");
652 if (auxFileSymNameShouldBeInStringTable(Vers))
656 assignAddressesAndIndices(Asm);
667 auto It = SymbolIndexMap.
find(
Sym);
668 return It != SymbolIndexMap.
end()
673 auto getVirtualAddress =
677 if (ContainingSect->isDwarfSect())
678 return Asm.getSymbolOffset(*
Sym);
681 if (!
Sym->isDefined())
682 return SectionMap[ContainingSect]->Address;
685 assert(
Sym->isDefined() &&
"not a valid object that has address!");
686 return SectionMap[ContainingSect]->Address +
Asm.getSymbolOffset(*
Sym);
697 std::tie(
Type, SignAndSize) =
698 TargetObjectWriter->getRelocTypeAndSignSize(
Target,
Fixup, IsPCRel);
700 const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
702 "Expected containing csect to exist in map.");
705 MaxRawDataSize -
Asm.getFragmentOffset(*Fragment)) &&
706 "Fragment offset + fixup offset is overflowed.");
708 Asm.getFragmentOffset(*Fragment) +
Fixup.getOffset();
711 if (
Type == XCOFF::RelocationType::R_POS ||
712 Type == XCOFF::RelocationType::R_TLS ||
713 Type == XCOFF::RelocationType::R_TLS_LE ||
714 Type == XCOFF::RelocationType::R_TLS_IE ||
715 Type == XCOFF::RelocationType::R_TLS_LD)
718 FixedValue = getVirtualAddress(SymA, SymASec) +
Target.getConstant();
719 else if (
Type == XCOFF::RelocationType::R_TLSM)
723 else if (
Type == XCOFF::RelocationType::R_TOC ||
724 Type == XCOFF::RelocationType::R_TOCL) {
735 int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
736 TOCCsects.front().Address +
Target.getConstant();
753 if (
Type == XCOFF::RelocationType::R_TOC && !isInt<16>(TOCEntryOffset))
754 TOCEntryOffset = llvm::SignExtend64<16>(TOCEntryOffset);
756 FixedValue = TOCEntryOffset;
758 }
else if (
Type == XCOFF::RelocationType::R_RBR) {
762 "Only XMC_PR csect may have the R_RBR relocation.");
767 SectionMap[ParentSec]->Address + FixupOffsetInCsect;
770 FixedValue = getVirtualAddress(SymA, SymASec) - BRInstrAddress +
772 }
else if (
Type == XCOFF::RelocationType::R_REF) {
776 FixupOffsetInCsect = 0;
779 XCOFFRelocation Reloc = {
Index, FixupOffsetInCsect, SignAndSize,
Type};
782 "Expected containing csect to exist in map.");
783 SectionMap[RelocationSec]->Relocations.push_back(Reloc);
792 const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
794 "Expected containing csect to exist in map.");
795 if (SymASec == SymBSec)
797 "relocation for paired relocatable term is not yet supported");
799 assert(
Type == XCOFF::RelocationType::R_POS &&
800 "SymA must be R_POS here if it's not opposite term or paired "
801 "relocatable term.");
802 const uint32_t IndexB = getIndex(SymB, SymBSec);
805 const uint8_t TypeB = XCOFF::RelocationType::R_NEG;
806 XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
807 SectionMap[RelocationSec]->Relocations.push_back(RelocB);
810 FixedValue -= getVirtualAddress(SymB, SymBSec);
813void XCOFFWriter::writeSections(
const MCAssembler &Asm) {
814 uint64_t CurrentAddressLocation = 0;
815 for (
const auto *Section : Sections)
816 writeSectionForControlSectionEntry(Asm, *Section, CurrentAddressLocation);
817 for (
const auto &DwarfSection : DwarfSections)
818 writeSectionForDwarfSectionEntry(Asm, DwarfSection, CurrentAddressLocation);
819 writeSectionForExceptionSectionEntry(Asm, ExceptionSection,
820 CurrentAddressLocation);
821 writeSectionForCInfoSymSectionEntry(Asm, CInfoSymSection,
822 CurrentAddressLocation);
830 finalizeSectionInfo();
834 writeAuxFileHeader();
835 writeSectionHeaderTable();
842 return W.OS.tell() - StartOffset;
845bool XCOFFWriter::nameShouldBeInStringTable(
const StringRef &SymbolName) {
849void XCOFFWriter::writeSymbolName(
const StringRef &SymbolName) {
851 if (nameShouldBeInStringTable(SymbolName)) {
853 W.write<
uint32_t>(Strings.getOffset(SymbolName));
868 W.write<
uint32_t>(Strings.getOffset(SymbolName));
870 writeSymbolName(SymbolName);
873 W.write<int16_t>(SectionNumber);
876 W.write<
uint8_t>(NumberOfAuxEntries);
879void XCOFFWriter::writeSymbolAuxCsectEntry(
uint64_t SectionOrLength,
880 uint8_t SymbolAlignmentAndType,
885 W.write<
uint8_t>(SymbolAlignmentAndType);
897bool XCOFFWriter::auxFileSymNameShouldBeInStringTable(
902void XCOFFWriter::writeAuxFileSymName(
const StringRef &SymbolName) {
904 if (auxFileSymNameShouldBeInStringTable(SymbolName)) {
906 W.write<
uint32_t>(Strings.getOffset(SymbolName));
917 writeAuxFileSymName(
Name);
926void XCOFFWriter::writeSymbolAuxDwarfEntry(
uint64_t LengthOfSectionPortion,
928 writeWord(LengthOfSectionPortion);
931 writeWord(NumberOfRelocEnt);
940void XCOFFWriter::writeSymbolEntryForCsectMemberLabel(
941 const Symbol &SymbolRef,
const XCOFFSection &CSectionRef,
942 int16_t SectionIndex,
uint64_t SymbolOffset) {
943 assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address &&
944 "Symbol address overflowed.");
946 auto Entry = ExceptionSection.ExceptionTable.find(SymbolRef.MCSym->getName());
947 if (Entry != ExceptionSection.ExceptionTable.end()) {
948 writeSymbolEntry(SymbolRef.getSymbolTableName(),
949 CSectionRef.Address + SymbolOffset, SectionIndex,
953 is64Bit() ? SymbolRef.getVisibilityType()
954 : SymbolRef.getVisibilityType() | 0x0020,
955 SymbolRef.getStorageClass(),
956 (
is64Bit() && ExceptionSection.isDebugEnabled) ? 3 : 2);
957 if (
is64Bit() && ExceptionSection.isDebugEnabled) {
960 writeSymbolAuxExceptionEntry(
961 ExceptionSection.FileOffsetToData +
962 getExceptionOffset(
Entry->second.FunctionSymbol),
963 Entry->second.FunctionSize,
964 SymbolIndexMap[
Entry->second.FunctionSymbol] + 4);
968 writeSymbolAuxFunctionEntry(
969 ExceptionSection.FileOffsetToData +
970 getExceptionOffset(
Entry->second.FunctionSymbol),
971 Entry->second.FunctionSize, 0,
972 (
is64Bit() && ExceptionSection.isDebugEnabled)
973 ? SymbolIndexMap[
Entry->second.FunctionSymbol] + 4
974 : SymbolIndexMap[
Entry->second.FunctionSymbol] + 3);
976 writeSymbolEntry(SymbolRef.getSymbolTableName(),
977 CSectionRef.Address + SymbolOffset, SectionIndex,
978 SymbolRef.getVisibilityType(),
979 SymbolRef.getStorageClass());
981 writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex,
XCOFF::XTY_LD,
982 CSectionRef.MCSec->getMappingClass());
985void XCOFFWriter::writeSymbolEntryForDwarfSection(
986 const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) {
987 assert(DwarfSectionRef.MCSec->isDwarfSect() &&
"Not a DWARF section!");
989 writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), 0,
992 writeSymbolAuxDwarfEntry(DwarfSectionRef.Size);
995void XCOFFWriter::writeSymbolEntryForControlSection(
996 const XCOFFSection &CSectionRef, int16_t SectionIndex,
998 writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address,
999 SectionIndex, CSectionRef.getVisibilityType(),
StorageClass);
1001 writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec),
1002 CSectionRef.MCSec->getMappingClass());
1005void XCOFFWriter::writeSymbolAuxFunctionEntry(
uint32_t EntryOffset,
1010 writeWord(LineNumberPointer);
1015 writeWord(LineNumberPointer);
1018 W.OS.write_zeros(1);
1021 W.OS.write_zeros(2);
1025void XCOFFWriter::writeSymbolAuxExceptionEntry(
uint64_t EntryOffset,
1028 assert(
is64Bit() &&
"Exception auxilliary entries are 64-bit only.");
1032 W.OS.write_zeros(1);
1036void XCOFFWriter::writeFileHeader() {
1039 W.write<int32_t>(0);
1040 writeWord(SymbolTableOffset);
1042 W.write<
uint16_t>(auxiliaryHeaderSize());
1044 W.write<int32_t>(SymbolTableEntryCount);
1046 W.write<int32_t>(SymbolTableEntryCount);
1047 W.write<
uint16_t>(auxiliaryHeaderSize());
1052void XCOFFWriter::writeAuxFileHeader() {
1053 if (!auxiliaryHeaderSize())
1064 W.write<
uint32_t>(Sections[0]->Address);
1065 W.write<
uint32_t>(Sections[1]->Address);
1068void XCOFFWriter::writeSectionHeader(
const SectionEntry *Sec) {
1072 if (Sec->Index == SectionEntry::UninitializedIndex)
1081 writeWord(IsDwarf ? 0 : Sec->Address);
1083 writeWord((IsDwarf || IsOvrflo) ? 0 : Sec->Address);
1085 writeWord(Sec->Size);
1086 writeWord(Sec->FileOffsetToData);
1087 writeWord(Sec->FileOffsetToRelocations);
1091 W.write<
uint32_t>(Sec->RelocationCount);
1093 W.write<int32_t>(Sec->Flags);
1094 W.OS.write_zeros(4);
1100 W.write<
uint16_t>(Sec->RelocationCount);
1102 ? Sec->RelocationCount
1104 W.write<int32_t>(Sec->Flags);
1108void XCOFFWriter::writeSectionHeaderTable() {
1109 for (
const auto *CsectSec : Sections)
1110 writeSectionHeader(CsectSec);
1111 for (
const auto &DwarfSec : DwarfSections)
1112 writeSectionHeader(&DwarfSec);
1113 for (
const auto &OverflowSec : OverflowSections)
1114 writeSectionHeader(&OverflowSec);
1115 if (hasExceptionSection())
1116 writeSectionHeader(&ExceptionSection);
1117 if (CInfoSymSection.Entry)
1118 writeSectionHeader(&CInfoSymSection);
1121void XCOFFWriter::writeRelocation(XCOFFRelocation Reloc,
1122 const XCOFFSection &Section) {
1124 writeWord(
Section.Address + Reloc.FixupOffsetInCsect);
1127 assert(
Section.MCSec->isDwarfSect() &&
"unsupport section type!");
1128 writeWord(Reloc.FixupOffsetInCsect);
1130 W.write<
uint32_t>(Reloc.SymbolTableIndex);
1131 W.write<
uint8_t>(Reloc.SignAndSize);
1135void XCOFFWriter::writeRelocations() {
1136 for (
const auto *Section : Sections) {
1137 if (
Section->Index == SectionEntry::UninitializedIndex)
1141 for (
const auto *Group :
Section->Groups) {
1145 for (
const auto &Csect : *Group) {
1146 for (
const auto Reloc : Csect.Relocations)
1147 writeRelocation(Reloc, Csect);
1152 for (
const auto &DwarfSection : DwarfSections)
1153 for (
const auto &Reloc : DwarfSection.DwarfSect->Relocations)
1154 writeRelocation(Reloc, *DwarfSection.DwarfSect);
1157void XCOFFWriter::writeSymbolTable(
MCAssembler &Asm) {
1161 for (
const std::pair<std::string, size_t> &
F : FileNames) {
1186 int NumberOfFileAuxEntries = 1;
1188 ++NumberOfFileAuxEntries;
1189 writeSymbolEntry(
".file", 0, XCOFF::ReservedSectionNum::N_DEBUG,
1191 NumberOfFileAuxEntries);
1197 if (CInfoSymSection.Entry)
1198 writeSymbolEntry(CInfoSymSection.Entry->Name, CInfoSymSection.Entry->Offset,
1199 CInfoSymSection.Index,
1203 for (
const auto &Csect : UndefinedCsects) {
1204 writeSymbolEntryForControlSection(Csect, XCOFF::ReservedSectionNum::N_UNDEF,
1205 Csect.MCSec->getStorageClass());
1208 for (
const auto *Section : Sections) {
1209 if (
Section->Index == SectionEntry::UninitializedIndex)
1213 for (
const auto *Group :
Section->Groups) {
1217 const int16_t SectionIndex =
Section->Index;
1218 for (
const auto &Csect : *Group) {
1220 writeSymbolEntryForControlSection(Csect, SectionIndex,
1221 Csect.MCSec->getStorageClass());
1223 for (
const auto &
Sym : Csect.Syms)
1224 writeSymbolEntryForCsectMemberLabel(
1225 Sym, Csect, SectionIndex,
Asm.getSymbolOffset(*(
Sym.MCSym)));
1230 for (
const auto &DwarfSection : DwarfSections)
1231 writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect,
1232 DwarfSection.Index);
1244 SecEntry.RelocationCount = Sec->Index;
1248 SecEntry.Address = RelCount;
1249 SecEntry.Index = ++SectionCount;
1250 OverflowSections.push_back(std::move(SecEntry));
1256 Sec->RelocationCount = RelCount;
1260void XCOFFWriter::calcOffsetToRelocations(
SectionEntry *Sec,
1262 if (!Sec->RelocationCount)
1265 Sec->FileOffsetToRelocations = RawPointer;
1270 for (
auto &OverflowSec : OverflowSections) {
1271 if (OverflowSec.RelocationCount ==
static_cast<uint32_t>(Sec->Index)) {
1272 RelocationSizeInSec =
1277 OverflowSec.FileOffsetToRelocations = Sec->FileOffsetToRelocations;
1280 assert(RelocationSizeInSec &&
"Overflow section header doesn't exist.");
1282 RelocationSizeInSec = Sec->RelocationCount *
1287 RawPointer += RelocationSizeInSec;
1288 if (RawPointer > MaxRawDataSize)
1292void XCOFFWriter::finalizeSectionInfo() {
1293 for (
auto *Section : Sections) {
1294 if (
Section->Index == SectionEntry::UninitializedIndex)
1299 for (
const auto *Group :
Section->Groups) {
1303 for (
auto &Csect : *Group)
1304 RelCount += Csect.Relocations.size();
1306 finalizeRelocationInfo(Section, RelCount);
1309 for (
auto &DwarfSection : DwarfSections)
1310 finalizeRelocationInfo(&DwarfSection,
1311 DwarfSection.DwarfSect->Relocations.size());
1319 auxiliaryHeaderSize();
1322 for (
auto *Sec : Sections) {
1323 if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual)
1326 RawPointer = Sec->advanceFileOffset(MaxRawDataSize, RawPointer);
1329 if (!DwarfSections.empty()) {
1330 RawPointer += PaddingsBeforeDwarf;
1331 for (
auto &DwarfSection : DwarfSections) {
1332 RawPointer = DwarfSection.advanceFileOffset(MaxRawDataSize, RawPointer);
1336 if (hasExceptionSection())
1337 RawPointer = ExceptionSection.advanceFileOffset(MaxRawDataSize, RawPointer);
1339 if (CInfoSymSection.Entry)
1340 RawPointer = CInfoSymSection.advanceFileOffset(MaxRawDataSize, RawPointer);
1342 for (
auto *Sec : Sections) {
1343 if (Sec->Index != SectionEntry::UninitializedIndex)
1344 calcOffsetToRelocations(Sec, RawPointer);
1347 for (
auto &DwarfSec : DwarfSections)
1348 calcOffsetToRelocations(&DwarfSec, RawPointer);
1352 if (SymbolTableEntryCount)
1353 SymbolTableOffset = RawPointer;
1356void XCOFFWriter::addExceptionEntry(
const MCSymbol *Symbol,
1358 unsigned ReasonCode,
unsigned FunctionSize,
1363 ExceptionSection.isDebugEnabled =
true;
1364 auto Entry = ExceptionSection.ExceptionTable.find(
Symbol->getName());
1365 if (Entry != ExceptionSection.ExceptionTable.end()) {
1366 Entry->second.Entries.push_back(
1367 ExceptionTableEntry(
Trap, LanguageCode, ReasonCode));
1370 ExceptionInfo NewEntry;
1371 NewEntry.FunctionSymbol =
Symbol;
1372 NewEntry.FunctionSize = FunctionSize;
1373 NewEntry.Entries.push_back(
1374 ExceptionTableEntry(
Trap, LanguageCode, ReasonCode));
1375 ExceptionSection.ExceptionTable.insert(
1376 std::pair<const StringRef, ExceptionInfo>(
Symbol->getName(), NewEntry));
1379unsigned XCOFFWriter::getExceptionSectionSize() {
1380 unsigned EntryNum = 0;
1382 for (
const auto &
TableEntry : ExceptionSection.ExceptionTable)
1385 EntryNum +=
TableEntry.second.Entries.size() + 1;
1391unsigned XCOFFWriter::getExceptionOffset(
const MCSymbol *Symbol) {
1392 unsigned EntryNum = 0;
1393 for (
const auto &
TableEntry : ExceptionSection.ExceptionTable) {
1394 if (Symbol ==
TableEntry.second.FunctionSymbol)
1396 EntryNum +=
TableEntry.second.Entries.size() + 1;
1403 assert(!CInfoSymSection.Entry &&
"Multiple entries are not supported");
1404 CInfoSymSection.addEntry(
1405 std::make_unique<CInfoSymInfo>(
Name.str(),
Metadata.str()));
1408void XCOFFWriter::assignAddressesAndIndices(
MCAssembler &Asm) {
1412 (2 + (CompilerVersion.empty() ? 0 : 1)) * FileNames.size();
1414 if (CInfoSymSection.Entry)
1418 for (
auto &Csect : UndefinedCsects) {
1421 Csect.SymbolTableIndex = SymbolTableIndex;
1422 SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
1424 SymbolTableIndex += 2;
1432 int32_t SectionIndex = 1;
1433 bool HasTDataSection =
false;
1435 for (
auto *Section : Sections) {
1436 const bool IsEmpty =
1438 [](
const CsectGroup *Group) { return Group->empty(); });
1442 if (SectionIndex > MaxSectionIndex)
1444 Section->Index = SectionIndex++;
1447 bool SectionAddressSet =
false;
1451 HasTDataSection =
true;
1458 for (
auto *Group :
Section->Groups) {
1462 for (
auto &Csect : *Group) {
1465 Csect.Size =
Asm.getSectionAddressSize(*MCSec);
1466 Address = Csect.Address + Csect.Size;
1467 Csect.SymbolTableIndex = SymbolTableIndex;
1470 SymbolTableIndex += 2;
1472 for (
auto &
Sym : Csect.Syms) {
1473 bool hasExceptEntry =
false;
1475 ExceptionSection.ExceptionTable.find(
Sym.MCSym->getName());
1476 if (Entry != ExceptionSection.ExceptionTable.end()) {
1477 hasExceptEntry =
true;
1478 for (
auto &TrapEntry :
Entry->second.Entries) {
1479 TrapEntry.TrapAddress =
Asm.getSymbolOffset(*(
Sym.MCSym)) +
1480 TrapEntry.Trap->getOffset();
1483 Sym.SymbolTableIndex = SymbolTableIndex;
1484 SymbolIndexMap[
Sym.MCSym] =
Sym.SymbolTableIndex;
1489 SymbolTableIndex += 2;
1490 if (hasExceptionSection() && hasExceptEntry) {
1491 if (
is64Bit() && ExceptionSection.isDebugEnabled)
1492 SymbolTableIndex += 2;
1494 SymbolTableIndex += 1;
1499 if (!SectionAddressSet) {
1500 Section->Address = Group->front().Address;
1501 SectionAddressSet =
true;
1516 if (!DwarfSections.empty())
1517 PaddingsBeforeDwarf =
1519 (*DwarfSections.begin()).DwarfSect->MCSec->getAlign()) -
1522 DwarfSectionEntry *LastDwarfSection =
nullptr;
1523 for (
auto &DwarfSection : DwarfSections) {
1524 assert((SectionIndex <= MaxSectionIndex) &&
"Section index overflow!");
1526 XCOFFSection &DwarfSect = *DwarfSection.DwarfSect;
1530 DwarfSection.Index = SectionIndex++;
1534 DwarfSect.SymbolTableIndex = SymbolTableIndex;
1537 SymbolTableIndex += 2;
1543 DwarfSection.Address = DwarfSect.Address =
1548 DwarfSection.Size = DwarfSect.Size =
Asm.getSectionAddressSize(*MCSec);
1550 Address = DwarfSection.Address + DwarfSection.Size;
1552 if (LastDwarfSection)
1553 LastDwarfSection->MemorySize =
1554 DwarfSection.Address - LastDwarfSection->Address;
1555 LastDwarfSection = &DwarfSection;
1557 if (LastDwarfSection) {
1560 Address =
alignTo(LastDwarfSection->Address + LastDwarfSection->Size,
1561 DefaultSectionAlign);
1562 LastDwarfSection->MemorySize =
Address - LastDwarfSection->Address;
1564 if (hasExceptionSection()) {
1565 ExceptionSection.Index = SectionIndex++;
1567 ExceptionSection.Address = 0;
1568 ExceptionSection.Size = getExceptionSectionSize();
1569 Address += ExceptionSection.Size;
1573 if (CInfoSymSection.Entry) {
1574 CInfoSymSection.Index = SectionIndex++;
1576 CInfoSymSection.Address = 0;
1577 Address += CInfoSymSection.Size;
1581 SymbolTableEntryCount = SymbolTableIndex;
1584void XCOFFWriter::writeSectionForControlSectionEntry(
1585 const MCAssembler &Asm,
const CsectSectionEntry &CsectEntry,
1586 uint64_t &CurrentAddressLocation) {
1588 if (CsectEntry.Index == SectionEntry::UninitializedIndex)
1595 assert(((CurrentAddressLocation <= CsectEntry.Address) ||
1598 "CurrentAddressLocation should be less than or equal to section "
1599 "address if the section is not TData or TBSS.");
1601 CurrentAddressLocation = CsectEntry.Address;
1606 if (CsectEntry.IsVirtual) {
1607 CurrentAddressLocation += CsectEntry.Size;
1611 for (
const auto &Group : CsectEntry.Groups) {
1612 for (
const auto &Csect : *Group) {
1613 if (
uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
1614 W.OS.write_zeros(PaddingSize);
1616 Asm.writeSectionData(
W.OS, Csect.MCSec);
1617 CurrentAddressLocation = Csect.Address + Csect.Size;
1625 CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) {
1626 W.OS.write_zeros(PaddingSize);
1627 CurrentAddressLocation += PaddingSize;
1631void XCOFFWriter::writeSectionForDwarfSectionEntry(
1632 const MCAssembler &Asm,
const DwarfSectionEntry &DwarfEntry,
1633 uint64_t &CurrentAddressLocation) {
1637 assert(CurrentAddressLocation <= DwarfEntry.Address &&
1638 "CurrentAddressLocation should be less than or equal to section "
1641 if (
uint64_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation)
1642 W.OS.write_zeros(PaddingSize);
1644 if (DwarfEntry.Size)
1645 Asm.writeSectionData(
W.OS, DwarfEntry.DwarfSect->MCSec);
1647 CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size;
1651 uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign;
1653 if (TailPaddingSize)
1654 W.OS.write_zeros(TailPaddingSize);
1656 CurrentAddressLocation += TailPaddingSize;
1659void XCOFFWriter::writeSectionForExceptionSectionEntry(
1660 const MCAssembler &Asm, ExceptionSectionEntry &ExceptionEntry,
1661 uint64_t &CurrentAddressLocation) {
1662 for (
const auto &
TableEntry : ExceptionEntry.ExceptionTable) {
1668 W.OS.write_zeros(4);
1670 W.OS.write_zeros(2);
1671 for (
auto &TrapEntry :
TableEntry.second.Entries) {
1672 writeWord(TrapEntry.TrapAddress);
1674 W.write<
uint8_t>(TrapEntry.Reason);
1678 CurrentAddressLocation += getExceptionSectionSize();
1681void XCOFFWriter::writeSectionForCInfoSymSectionEntry(
1682 const MCAssembler &Asm, CInfoSymSectionEntry &CInfoSymEntry,
1683 uint64_t &CurrentAddressLocation) {
1684 if (!CInfoSymSection.Entry)
1687 constexpr int WordSize =
sizeof(
uint32_t);
1688 std::unique_ptr<CInfoSymInfo> &CISI = CInfoSymEntry.Entry;
1699 while (Index + WordSize <=
Metadata.size()) {
1707 if (CISI->paddingSize()) {
1708 std::array<uint8_t, WordSize> LastWord = {0};
1709 ::memcpy(LastWord.data(),
Metadata.data() + Index,
Metadata.size() - Index);
1713 CurrentAddressLocation += CISI->size();
1724 uint8_t EncodedAlign = Log2Align << 3;
1730std::unique_ptr<MCObjectWriter>
1733 return std::make_unique<XCOFFWriter>(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)
static unsigned getCPUType(const MachOObjectFile &O)
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),...
iterator find(const_arg_type_t< KeyT > Val)
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
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.
virtual void addExceptionEntry(const MCSymbol *Symbol, const MCSymbol *Trap, unsigned LanguageCode, unsigned ReasonCode, unsigned FunctionSize, bool hasDebug)=0
virtual void addCInfoSymEntry(StringRef Name, StringRef Metadata)=0
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
XCOFF::CFileCpuId getCpuID(StringRef CPU)
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...
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.