51 constexpr
unsigned DefaultSectionAlign = 4;
52 constexpr int16_t MaxSectionIndex = INT16_MAX;
57 struct XCOFFRelocation {
95 : MCSec(MCSec), SymbolTableIndex(-1),
Address(-1),
Size(0) {}
102 using CsectGroup = std::deque<XCOFFSection>;
103 using CsectGroups = std::deque<CsectGroup *>;
127 static constexpr int16_t UninitializedIndex =
132 FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags),
133 Index(UninitializedIndex) {
138 virtual void reset() {
141 FileOffsetToData = 0;
142 FileOffsetToRelocations = 0;
144 Index = UninitializedIndex;
157 const bool IsVirtual;
169 void reset()
override {
170 SectionEntry::reset();
172 for (
auto *Group : Groups)
176 virtual ~CsectSectionEntry() =
default;
181 std::unique_ptr<XCOFFSection> DwarfSect;
184 std::unique_ptr<XCOFFSection> Sect)
186 assert(DwarfSect->MCSec->isDwarfSect() &&
187 "This should be a DWARF section!");
192 DwarfSectionEntry(DwarfSectionEntry &&
s) =
default;
194 virtual ~DwarfSectionEntry() =
default;
206 std::unique_ptr<MCXCOFFObjectTargetWriter> TargetObjectWriter;
210 TargetObjectWriter->is64Bit() ?
UINT64_MAX : UINT32_MAX;
224 CsectGroup UndefinedCsects;
225 CsectGroup ProgramCodeCsects;
226 CsectGroup ReadOnlyCsects;
227 CsectGroup DataCsects;
228 CsectGroup FuncDSCsects;
229 CsectGroup TOCCsects;
230 CsectGroup BSSCsects;
231 CsectGroup TDataCsects;
232 CsectGroup TBSSCsects;
235 CsectSectionEntry Text;
236 CsectSectionEntry
Data;
237 CsectSectionEntry BSS;
238 CsectSectionEntry TData;
239 CsectSectionEntry TBSS;
243 std::array<CsectSectionEntry *const, 5> Sections{
244 {&Text, &
Data, &BSS, &TData, &TBSS}};
246 std::vector<DwarfSectionEntry> DwarfSections;
250 virtual void reset()
override;
259 bool is64Bit()
const {
return TargetObjectWriter->is64Bit(); }
260 bool nameShouldBeInStringTable(
const StringRef &);
263 void writeSymbolEntryForCsectMemberLabel(
const Symbol &SymbolRef,
264 const XCOFFSection &CSectionRef,
265 int16_t SectionIndex,
267 void writeSymbolEntryForControlSection(
const XCOFFSection &CSectionRef,
268 int16_t SectionIndex,
270 void writeSymbolEntryForDwarfSection(
const XCOFFSection &DwarfSectionRef,
271 int16_t SectionIndex);
272 void writeFileHeader();
273 void writeSectionHeaderTable();
277 const CsectSectionEntry &CsectEntry,
281 const DwarfSectionEntry &DwarfEntry,
284 void writeSymbolAuxDwarfEntry(
uint64_t LengthOfSectionPortion,
286 void writeSymbolAuxCsectEntry(
uint64_t SectionOrLength,
287 uint8_t SymbolAlignmentAndType,
292 void writeRelocations();
293 void writeRelocation(XCOFFRelocation Reloc,
const XCOFFSection &Section);
303 void assignAddressesAndIndices(
const MCAsmLayout &);
304 void finalizeSectionInfo();
307 bool needsAuxiliaryHeader()
const {
return false; }
310 size_t auxiliaryHeaderSize()
const {
311 assert(!needsAuxiliaryHeader() &&
312 "Auxiliary header support not implemented.");
317 XCOFFObjectWriter(std::unique_ptr<MCXCOFFObjectTargetWriter> MOTW,
325 XCOFFObjectWriter::XCOFFObjectWriter(
330 CsectGroups{&ProgramCodeCsects, &ReadOnlyCsects}),
332 CsectGroups{&DataCsects, &FuncDSCsects, &TOCCsects}),
334 CsectGroups{&BSSCsects}),
336 CsectGroups{&TDataCsects}),
338 CsectGroups{&TBSSCsects}) {}
340 void XCOFFObjectWriter::reset() {
342 SymbolIndexMap.
clear();
345 UndefinedCsects.clear();
347 for (
auto *Sec : Sections)
349 for (
auto &DwarfSec : DwarfSections)
353 SymbolTableEntryCount = 0;
354 SymbolTableOffset = 0;
356 RelocationEntryOffset = 0;
359 MCObjectWriter::reset();
362 CsectGroup &XCOFFObjectWriter::getCsectGroup(
const MCSectionXCOFF *MCSec) {
366 "Only an initialized csect can contain program code.");
367 return ProgramCodeCsects;
370 "Only an initialized csect can contain read only data.");
371 return ReadOnlyCsects;
384 "Mapping invalid csect. CSECT with bss storage class must be "
389 "Mapping invalid csect. CSECT with tdata storage class must be "
390 "an initialized csect.");
394 "Mapping invalid csect. CSECT with tbss storage class must be "
395 "an uninitialized csect.");
399 "Only an initialized csect can contain TOC-base.");
400 assert(TOCCsects.empty() &&
401 "We should have only one TOC-base, and it should be the first csect "
402 "in this CsectGroup.");
407 "Only an initialized csect can contain TC entry.");
408 assert(!TOCCsects.empty() &&
409 "We should at least have a TOC-base in this CsectGroup.");
424 void XCOFFObjectWriter::executePostLayoutBinding(
MCAssembler &
Asm,
426 for (
const auto &
S :
Asm) {
427 const auto *MCSec = cast<const MCSectionXCOFF>(&
S);
429 "Cannot add a section twice.");
440 "An undefined csect should not get registered.");
441 CsectGroup &Group = getCsectGroup(MCSec);
442 Group.emplace_back(MCSec);
443 SectionMap[MCSec] = &Group.back();
446 std::unique_ptr<XCOFFSection> DwarfSec =
447 std::make_unique<XCOFFSection>(MCSec);
448 SectionMap[MCSec] = DwarfSec.get();
450 DwarfSectionEntry SecEntry(MCSec->
getName(),
453 DwarfSections.push_back(
std::move(SecEntry));
468 UndefinedCsects.emplace_back(ContainingCsect);
469 SectionMap[ContainingCsect] = &UndefinedCsects.back();
484 assert(SectionMap.
find(ContainingCsect) != SectionMap.
end() &&
485 "Expected containing csect to exist in map");
486 XCOFFSection *Csect = SectionMap[ContainingCsect];
488 assert(Csect->MCSec->isCsect() &&
"only csect is supported now!");
489 Csect->Syms.emplace_back(XSym);
498 if (nameShouldBeInStringTable(SourceFileName))
499 Strings.add(SourceFileName);
502 assignAddressesAndIndices(Layout);
510 auto getIndex = [
this](
const MCSymbol *Sym,
515 return SymbolIndexMap.
find(Sym) != SymbolIndexMap.
end()
516 ? SymbolIndexMap[Sym]
520 auto getVirtualAddress =
521 [
this, &Layout](
const MCSymbol *Sym,
524 if (ContainingSect->isDwarfSect())
529 return SectionMap[ContainingSect]->Address;
533 return SectionMap[ContainingSect]->Address + Layout.
getSymbolOffset(*Sym);
540 MCFixupKindInfo::FKF_IsPCRel;
544 std::tie(
Type, SignAndSize) =
545 TargetObjectWriter->getRelocTypeAndSignSize(
Target,
Fixup, IsPCRel);
547 const MCSectionXCOFF *SymASec = getContainingCsect(cast<MCSymbolXCOFF>(SymA));
553 "Expected containing csect to exist in map.");
560 FixedValue = getVirtualAddress(SymA, SymASec) +
Target.getConstant();
569 const int64_t TOCEntryOffset = SectionMap[SymASec]->Address -
570 TOCCsects.front().Address +
575 FixedValue = TOCEntryOffset;
580 "Fragment offset + fixup offset is overflowed.");
584 XCOFFRelocation Reloc = {
Index, FixupOffsetInCsect, SignAndSize,
Type};
587 "Expected containing csect to exist in map.");
588 SectionMap[RelocationSec]->Relocations.push_back(Reloc);
597 const MCSectionXCOFF *SymBSec = getContainingCsect(cast<MCSymbolXCOFF>(SymB));
599 "Expected containing csect to exist in map.");
600 if (SymASec == SymBSec)
602 "relocation for paired relocatable term is not yet supported");
605 "SymA must be R_POS here if it's not opposite term or paired "
606 "relocatable term.");
607 const uint32_t IndexB = getIndex(SymB, SymBSec);
611 XCOFFRelocation RelocB = {IndexB, FixupOffsetInCsect, SignAndSize, TypeB};
612 SectionMap[RelocationSec]->Relocations.push_back(RelocB);
615 FixedValue -= getVirtualAddress(SymB, SymBSec);
620 uint64_t CurrentAddressLocation = 0;
621 for (
const auto *
Section : Sections)
622 writeSectionForControlSectionEntry(
Asm, Layout, *
Section,
623 CurrentAddressLocation);
624 for (
const auto &DwarfSection : DwarfSections)
625 writeSectionForDwarfSectionEntry(
Asm, Layout, DwarfSection,
626 CurrentAddressLocation);
634 if (
Asm.isIncrementalLinkerCompatible())
637 finalizeSectionInfo();
641 writeSectionHeaderTable();
642 writeSections(
Asm, Layout);
648 return W.OS.tell() - StartOffset;
669 int16_t SectionNumber,
672 uint8_t NumberOfAuxEntries) {
680 W.write<int16_t>(SectionNumber);
691 W.write<uint8_t>(NumberOfAuxEntries);
694 void XCOFFObjectWriter::writeSymbolAuxCsectEntry(
uint64_t SectionOrLength,
695 uint8_t SymbolAlignmentAndType,
700 W.write<uint8_t>(SymbolAlignmentAndType);
712 void XCOFFObjectWriter::writeSymbolAuxDwarfEntry(
714 writeWord(LengthOfSectionPortion);
717 writeWord(NumberOfRelocEnt);
726 void XCOFFObjectWriter::writeSymbolEntryForCsectMemberLabel(
727 const Symbol &SymbolRef,
const XCOFFSection &CSectionRef,
728 int16_t SectionIndex,
uint64_t SymbolOffset) {
729 assert(SymbolOffset <= MaxRawDataSize - CSectionRef.Address &&
730 "Symbol address overflowed.");
732 writeSymbolEntry(SymbolRef.getSymbolTableName(),
733 CSectionRef.Address + SymbolOffset, SectionIndex,
734 SymbolRef.getVisibilityType(), SymbolRef.getStorageClass());
736 writeSymbolAuxCsectEntry(CSectionRef.SymbolTableIndex,
XCOFF::XTY_LD,
737 CSectionRef.MCSec->getMappingClass());
740 void XCOFFObjectWriter::writeSymbolEntryForDwarfSection(
741 const XCOFFSection &DwarfSectionRef, int16_t SectionIndex) {
742 assert(DwarfSectionRef.MCSec->isDwarfSect() &&
"Not a DWARF section!");
744 writeSymbolEntry(DwarfSectionRef.getSymbolTableName(), 0,
747 writeSymbolAuxDwarfEntry(DwarfSectionRef.Size);
750 void XCOFFObjectWriter::writeSymbolEntryForControlSection(
751 const XCOFFSection &CSectionRef, int16_t SectionIndex,
753 writeSymbolEntry(CSectionRef.getSymbolTableName(), CSectionRef.Address,
754 SectionIndex, CSectionRef.getVisibilityType(),
StorageClass);
756 writeSymbolAuxCsectEntry(CSectionRef.Size, getEncodedType(CSectionRef.MCSec),
757 CSectionRef.MCSec->getMappingClass());
760 void XCOFFObjectWriter::writeFileHeader() {
764 writeWord(SymbolTableOffset);
769 W.write<int32_t>(SymbolTableEntryCount);
771 W.write<int32_t>(SymbolTableEntryCount);
778 void XCOFFObjectWriter::writeSectionHeaderTable() {
779 auto writeSectionHeader = [&](
const SectionEntry *Sec,
bool IsDwarf) {
781 if (Sec->Index == SectionEntry::UninitializedIndex)
791 writeWord(IsDwarf ? 0 : Sec->Address);
792 writeWord(IsDwarf ? 0 : Sec->Address);
794 writeWord(Sec->Size);
795 writeWord(Sec->FileOffsetToData);
796 writeWord(Sec->FileOffsetToRelocations);
802 W.write<int32_t>(Sec->Flags);
807 W.write<int32_t>(Sec->Flags);
813 for (
const auto *CsectSec : Sections)
814 writeSectionHeader(CsectSec,
false);
815 for (
const auto &DwarfSec : DwarfSections)
816 writeSectionHeader(&DwarfSec,
true);
819 void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc,
822 writeWord(
Section.Address + Reloc.FixupOffsetInCsect);
825 assert(
Section.MCSec->isDwarfSect() &&
"unsupport section type!");
826 writeWord(Reloc.FixupOffsetInCsect);
828 W.write<
uint32_t>(Reloc.SymbolTableIndex);
829 W.write<uint8_t>(Reloc.SignAndSize);
830 W.write<uint8_t>(Reloc.Type);
833 void XCOFFObjectWriter::writeRelocations() {
834 for (
const auto *
Section : Sections) {
835 if (
Section->Index == SectionEntry::UninitializedIndex)
839 for (
const auto *Group :
Section->Groups) {
843 for (
const auto &Csect : *Group) {
844 for (
const auto Reloc : Csect.Relocations)
845 writeRelocation(Reloc, Csect);
850 for (
const auto &DwarfSection : DwarfSections)
851 for (
const auto &Reloc : DwarfSection.DwarfSect->Relocations)
852 writeRelocation(Reloc, *DwarfSection.DwarfSect);
861 writeSymbolEntry(SourceFileName, 0,
866 for (
const auto &Csect : UndefinedCsects) {
868 Csect.MCSec->getStorageClass());
871 for (
const auto *
Section : Sections) {
872 if (
Section->Index == SectionEntry::UninitializedIndex)
876 for (
const auto *Group :
Section->Groups) {
880 const int16_t SectionIndex =
Section->Index;
881 for (
const auto &Csect : *Group) {
883 writeSymbolEntryForControlSection(Csect, SectionIndex,
884 Csect.MCSec->getStorageClass());
886 for (
const auto &Sym : Csect.Syms)
887 writeSymbolEntryForCsectMemberLabel(
893 for (
const auto &DwarfSection : DwarfSections)
894 writeSymbolEntryForDwarfSection(*DwarfSection.DwarfSect,
898 void XCOFFObjectWriter::finalizeSectionInfo() {
899 for (
auto *
Section : Sections) {
900 if (
Section->Index == SectionEntry::UninitializedIndex)
904 for (
const auto *Group :
Section->Groups) {
908 for (
auto &Csect : *Group) {
909 const size_t CsectRelocCount = Csect.Relocations.size();
915 "relocation entries overflowed; overflow section is "
916 "not implemented yet");
918 Section->RelocationCount += CsectRelocCount;
923 for (
auto &DwarfSection : DwarfSections)
924 DwarfSection.RelocationCount = DwarfSection.DwarfSect->Relocations.size();
927 uint64_t RawPointer = RelocationEntryOffset;
928 auto calcOffsetToRelocations = [&](
SectionEntry *Sec,
bool IsDwarf) {
929 if (!IsDwarf && Sec->Index == SectionEntry::UninitializedIndex)
932 if (!Sec->RelocationCount)
935 Sec->FileOffsetToRelocations = RawPointer;
936 const uint64_t RelocationSizeInSec =
937 Sec->RelocationCount * (
is64Bit()
940 RawPointer += RelocationSizeInSec;
941 if (RawPointer > MaxRawDataSize)
947 for (
auto *Sec : Sections)
948 calcOffsetToRelocations(Sec,
false);
950 for (
auto &DwarfSec : DwarfSections)
951 calcOffsetToRelocations(&DwarfSec,
true);
955 if (SymbolTableEntryCount)
956 SymbolTableOffset = RawPointer;
959 void XCOFFObjectWriter::assignAddressesAndIndices(
const MCAsmLayout &Layout) {
964 for (
auto &Csect : UndefinedCsects) {
967 Csect.SymbolTableIndex = SymbolTableIndex;
968 SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex;
970 SymbolTableIndex += 2;
978 int32_t SectionIndex = 1;
979 bool HasTDataSection =
false;
981 for (
auto *
Section : Sections) {
984 [](
const CsectGroup *Group) { return Group->empty(); });
988 if (SectionIndex > MaxSectionIndex)
990 Section->Index = SectionIndex++;
993 bool SectionAddressSet =
false;
997 HasTDataSection =
true;
1004 for (
auto *Group :
Section->Groups) {
1008 for (
auto &Csect : *Group) {
1012 Address = Csect.Address + Csect.Size;
1013 Csect.SymbolTableIndex = SymbolTableIndex;
1016 SymbolTableIndex += 2;
1018 for (
auto &Sym : Csect.Syms) {
1019 Sym.SymbolTableIndex = SymbolTableIndex;
1020 SymbolIndexMap[Sym.MCSym] = Sym.SymbolTableIndex;
1023 SymbolTableIndex += 2;
1027 if (!SectionAddressSet) {
1028 Section->Address = Group->front().Address;
1029 SectionAddressSet =
true;
1039 for (
auto &DwarfSection : DwarfSections) {
1040 assert((SectionIndex <= MaxSectionIndex) &&
"Section index overflow!");
1042 XCOFFSection &DwarfSect = *DwarfSection.DwarfSect;
1046 DwarfSection.Index = SectionIndex++;
1050 DwarfSect.SymbolTableIndex = SymbolTableIndex;
1053 SymbolTableIndex += 2;
1059 DwarfSection.Address = DwarfSect.Address =
1067 Address =
alignTo(DwarfSect.Address + DwarfSect.Size, DefaultSectionAlign);
1070 SymbolTableEntryCount = SymbolTableIndex;
1078 auxiliaryHeaderSize();
1080 for (
auto *Sec : Sections) {
1081 if (Sec->Index == SectionEntry::UninitializedIndex || Sec->IsVirtual)
1084 Sec->FileOffsetToData = RawPointer;
1085 RawPointer += Sec->Size;
1086 if (RawPointer > MaxRawDataSize)
1090 for (
auto &DwarfSection : DwarfSections) {
1095 alignTo(RawPointer, DwarfSection.DwarfSect->MCSec->getAlignment());
1097 DwarfSection.FileOffsetToData = RawPointer;
1100 RawPointer += DwarfSection.Size;
1102 RawPointer =
alignTo(RawPointer, DefaultSectionAlign);
1104 assert(RawPointer <= MaxRawDataSize &&
1105 "Section raw data overflowed this object file.");
1108 RelocationEntryOffset = RawPointer;
1111 void XCOFFObjectWriter::writeSectionForControlSectionEntry(
1113 const CsectSectionEntry &CsectEntry,
uint64_t &CurrentAddressLocation) {
1115 if (CsectEntry.Index == SectionEntry::UninitializedIndex)
1122 assert(((CurrentAddressLocation <= CsectEntry.Address) ||
1125 "CurrentAddressLocation should be less than or equal to section "
1126 "address if the section is not TData or TBSS.");
1128 CurrentAddressLocation = CsectEntry.Address;
1133 if (CsectEntry.IsVirtual) {
1134 CurrentAddressLocation += CsectEntry.Size;
1138 for (
const auto &Group : CsectEntry.Groups) {
1139 for (
const auto &Csect : *Group) {
1140 if (
uint32_t PaddingSize = Csect.Address - CurrentAddressLocation)
1141 W.OS.write_zeros(PaddingSize);
1143 Asm.writeSectionData(
W.OS, Csect.MCSec, Layout);
1144 CurrentAddressLocation = Csect.Address + Csect.Size;
1152 CsectEntry.Address + CsectEntry.Size - CurrentAddressLocation) {
1153 W.OS.write_zeros(PaddingSize);
1154 CurrentAddressLocation += PaddingSize;
1158 void XCOFFObjectWriter::writeSectionForDwarfSectionEntry(
1160 const DwarfSectionEntry &DwarfEntry,
uint64_t &CurrentAddressLocation) {
1164 assert(CurrentAddressLocation <= DwarfEntry.Address &&
1165 "CurrentAddressLocation should be less than or equal to section "
1168 if (
uint64_t PaddingSize = DwarfEntry.Address - CurrentAddressLocation)
1169 W.OS.write_zeros(PaddingSize);
1171 if (DwarfEntry.Size)
1172 Asm.writeSectionData(
W.OS, DwarfEntry.DwarfSect->MCSec, Layout);
1174 CurrentAddressLocation = DwarfEntry.Address + DwarfEntry.Size;
1178 uint32_t Mod = CurrentAddressLocation % DefaultSectionAlign;
1180 if (TailPaddingSize)
1181 W.OS.write_zeros(TailPaddingSize);
1183 CurrentAddressLocation += TailPaddingSize;
1196 uint8_t EncodedAlign = Log2Align << 3;
1202 std::unique_ptr<MCObjectWriter>
1205 return std::make_unique<XCOFFObjectWriter>(
std::move(MOTW), OS);