diff --git a/llvm/lib/MC/XCOFFObjectWriter.cpp b/llvm/lib/MC/XCOFFObjectWriter.cpp --- a/llvm/lib/MC/XCOFFObjectWriter.cpp +++ b/llvm/lib/MC/XCOFFObjectWriter.cpp @@ -73,32 +73,30 @@ }; // Wrapper for an MCSectionXCOFF. -struct ControlSection { - const MCSectionXCOFF *const MCCsect; +// It can be a Csect or debug section or DWARF section and so on. +struct XCOFFSection { + const MCSectionXCOFF *const MCSec; uint32_t SymbolTableIndex; uint32_t Address; uint32_t Size; SmallVector Syms; SmallVector Relocations; - StringRef getSymbolTableName() const { return MCCsect->getSymbolTableName(); } - ControlSection(const MCSectionXCOFF *MCSec) - : MCCsect(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {} + StringRef getSymbolTableName() const { return MCSec->getSymbolTableName(); } + XCOFFSection(const MCSectionXCOFF *MCSec) + : MCSec(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {} }; // Type to be used for a container representing a set of csects with // (approximately) the same storage mapping class. For example all the csects // with a storage mapping class of `xmc_pr` will get placed into the same // container. -using CsectGroup = std::deque; +using CsectGroup = std::deque; using CsectGroups = std::deque; -// Represents the data related to a section excluding the csects that make up -// the raw data of the section. The csects are stored separately as not all -// sections contain csects, and some sections contain csects which are better -// stored separately, e.g. the .data section containing read-write, descriptor, -// TOCBase and TOC-entry csects. -struct Section { +// The basic section entry defination. This Section represents a section entry +// in XCOFF section header table. +struct SectionEntry { char Name[XCOFF::NameSize]; // The physical/virtual address of the section. For an object file // these values are equivalent. @@ -111,9 +109,6 @@ int16_t Index; - // Virtual sections do not need storage allocated in the object file. - const bool IsVirtual; - // XCOFF has special section numbers for symbols: // -2 Specifies N_DEBUG, a special symbolic debugging symbol. // -1 Specifies N_ABS, an absolute symbol. The symbol has a value but is not @@ -124,28 +119,95 @@ static constexpr int16_t UninitializedIndex = XCOFF::ReservedSectionNum::N_DEBUG - 1; - CsectGroups Groups; + SectionEntry(StringRef N, int32_t Flags) + : Name(), Address(0), Size(0), FileOffsetToData(0), + FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags), + Index(UninitializedIndex) { + assert(N.size() <= XCOFF::NameSize && "section name too long"); + memcpy(Name, N.data(), N.size()); + } - void reset() { + virtual void reset() { Address = 0; Size = 0; FileOffsetToData = 0; FileOffsetToRelocations = 0; RelocationCount = 0; Index = UninitializedIndex; + } + + virtual ~SectionEntry() {} + + // The kind of the XCOFF Section entry. + // FIXME: add more section entry types, like debug, comment and so on. + enum SectionEntryKind { + SectionEntryUnknown, + SectionEntryDwarf, + SectionEntryCsect + }; + virtual uint32_t getSectionEntryKind() const { return SectionEntryUnknown; }; +}; + +// Represents the data related to a section excluding the csects that make up +// the raw data of the section. The csects are stored separately as not all +// sections contain csects, and some sections contain csects which are better +// stored separately, e.g. the .data section containing read-write, descriptor, +// TOCBase and TOC-entry csects. +struct CsectSectionEntry : public SectionEntry { + // Virtual sections do not need storage allocated in the object file. + const bool IsVirtual; + + // This is a section containing csect groups. + CsectGroups Groups; + + CsectSectionEntry(StringRef N, XCOFF::SectionTypeFlags Flags, bool IsVirtual, + CsectGroups Groups) + : SectionEntry(N, Flags), IsVirtual(IsVirtual), Groups(Groups) { + assert(N.size() <= XCOFF::NameSize && "section name too long"); + memcpy(Name, N.data(), N.size()); + } + + void reset() override { + SectionEntry::reset(); // Clear any csects we have stored. for (auto *Group : Groups) Group->clear(); } - Section(StringRef N, XCOFF::SectionTypeFlags Flags, bool IsVirtual, - CsectGroups Groups) - : Name(), Address(0), Size(0), FileOffsetToData(0), - FileOffsetToRelocations(0), RelocationCount(0), Flags(Flags), - Index(UninitializedIndex), IsVirtual(IsVirtual), Groups(Groups) { + virtual ~CsectSectionEntry() {} + + uint32_t getSectionEntryKind() const override { return SectionEntryCsect; }; + static bool classof(const SectionEntry *Sec) { + return Sec->getSectionEntryKind() == SectionEntryCsect; + } +}; + +struct DwarfSectionEntry : public SectionEntry { + // For DWARF section entry. + std::unique_ptr DwarfSect; + + DwarfSectionEntry(StringRef N, int32_t Flags, + std::unique_ptr DwarfSect) + : SectionEntry(N, Flags | XCOFF::STYP_DWARF), + DwarfSect(std::move(DwarfSect)) { + assert(this->DwarfSect->MCSec->isDwarfSect() && + "This should be a DWARF section!"); assert(N.size() <= XCOFF::NameSize && "section name too long"); memcpy(Name, N.data(), N.size()); } + + void reset() override { + SectionEntry::reset(); + // Destory XCOFFSection we own. + DwarfSect.reset(); + } + + virtual ~DwarfSectionEntry() {} + + uint32_t getSectionEntryKind() const override { return SectionEntryDwarf; }; + static bool classof(const SectionEntry *Sec) { + return Sec->getSectionEntryKind() == SectionEntryDwarf; + } }; class XCOFFObjectWriter : public MCObjectWriter { @@ -159,10 +221,10 @@ std::unique_ptr TargetObjectWriter; StringTableBuilder Strings; - // Maps the MCSection representation to its corresponding ControlSection - // wrapper. Needed for finding the ControlSection to insert an MCSymbol into + // Maps the MCSection representation to its corresponding XCOFFSection + // wrapper. Needed for finding the XCOFFSection to insert an MCSymbol into // from its containing MCSectionXCOFF. - DenseMap SectionMap; + DenseMap SectionMap; // Maps the MCSymbol representation to its corrresponding symbol table index. // Needed for relocation. @@ -180,13 +242,13 @@ CsectGroup BSSCsects; // The Predefined sections. - Section Text; - Section Data; - Section BSS; + CsectSectionEntry Text; + CsectSectionEntry Data; + CsectSectionEntry BSS; // All the XCOFF sections, in the order they will appear in the section header // table. - std::array
Sections{{&Text, &Data, &BSS}}; + std::array Sections{{&Text, &Data, &BSS}}; CsectGroup &getCsectGroup(const MCSectionXCOFF *MCSec); @@ -202,16 +264,16 @@ static bool nameShouldBeInStringTable(const StringRef &); void writeSymbolName(const StringRef &); void writeSymbolTableEntryForCsectMemberLabel(const Symbol &, - const ControlSection &, int16_t, + const XCOFFSection &, int16_t, uint64_t); - void writeSymbolTableEntryForControlSection(const ControlSection &, int16_t, + void writeSymbolTableEntryForControlSection(const XCOFFSection &, int16_t, XCOFF::StorageClass); void writeFileHeader(); void writeSectionHeaderTable(); void writeSections(const MCAssembler &Asm, const MCAsmLayout &Layout); void writeSymbolTable(const MCAsmLayout &Layout); void writeRelocations(); - void writeRelocation(XCOFFRelocation Reloc, const ControlSection &CSection); + void writeRelocation(XCOFFRelocation Reloc, const XCOFFSection &CSection); // Called after all the csects and symbols have been processed by // `executePostLayoutBinding`, this function handles building up the majority @@ -330,7 +392,7 @@ for (const auto &S : Asm) { const auto *MCSec = cast(&S); assert(SectionMap.find(MCSec) == SectionMap.end() && - "Cannot add a csect twice."); + "Cannot add a section twice."); assert(XCOFF::XTY_ER != MCSec->getCSectType() && "An undefined csect should not get registered."); @@ -372,8 +434,10 @@ assert(SectionMap.find(ContainingCsect) != SectionMap.end() && "Expected containing csect to exist in map"); + XCOFFSection *Csect = SectionMap[ContainingCsect]; // Lookup the containing csect and add the symbol to it. - SectionMap[ContainingCsect]->Syms.emplace_back(XSym); + assert(Csect->MCSec->isCsect() && "only csect is supported now!"); + Csect->Syms.emplace_back(XSym); // If the name does not fit in the storage provided in the symbol table // entry, add it to the string table. @@ -487,24 +551,27 @@ const MCAsmLayout &Layout) { uint32_t CurrentAddressLocation = 0; for (const auto *Section : Sections) { + assert(isa(Section) && "Only csect entry is supported!"); + const auto *CsectEntry = dyn_cast(Section); // Nothing to write for this Section. - if (Section->Index == Section::UninitializedIndex || Section->IsVirtual) + if (CsectEntry->Index == SectionEntry::UninitializedIndex || + CsectEntry->IsVirtual) continue; // There could be a gap (without corresponding zero padding) between // sections. - assert(CurrentAddressLocation <= Section->Address && + assert(CurrentAddressLocation <= CsectEntry->Address && "CurrentAddressLocation should be less than or equal to section " "address."); - CurrentAddressLocation = Section->Address; + CurrentAddressLocation = CsectEntry->Address; - for (const auto *Group : Section->Groups) { + for (const auto *Group : CsectEntry->Groups) { for (const auto &Csect : *Group) { if (uint32_t PaddingSize = Csect.Address - CurrentAddressLocation) W.OS.write_zeros(PaddingSize); if (Csect.Size) - Asm.writeSectionData(W.OS, Csect.MCCsect, Layout); + Asm.writeSectionData(W.OS, Csect.MCSec, Layout); CurrentAddressLocation = Csect.Address + Csect.Size; } } @@ -513,7 +580,7 @@ // the current section minus the the end virtual address of the last csect // in that section. if (uint32_t PaddingSize = - Section->Address + Section->Size - CurrentAddressLocation) { + CsectEntry->Address + CsectEntry->Size - CurrentAddressLocation) { W.OS.write_zeros(PaddingSize); CurrentAddressLocation += PaddingSize; } @@ -563,7 +630,7 @@ } void XCOFFObjectWriter::writeSymbolTableEntryForCsectMemberLabel( - const Symbol &SymbolRef, const ControlSection &CSectionRef, + const Symbol &SymbolRef, const XCOFFSection &CSectionRef, int16_t SectionIndex, uint64_t SymbolOffset) { // Name or Zeros and string table offset writeSymbolName(SymbolRef.getSymbolTableName()); @@ -592,7 +659,7 @@ // Symbol type: Label W.write(XCOFF::XTY_LD); // Storage mapping class. - W.write(CSectionRef.MCCsect->getMappingClass()); + W.write(CSectionRef.MCSec->getMappingClass()); // Reserved (x_stab). W.write(0); // Reserved (x_snstab). @@ -600,7 +667,7 @@ } void XCOFFObjectWriter::writeSymbolTableEntryForControlSection( - const ControlSection &CSectionRef, int16_t SectionIndex, + const XCOFFSection &CSectionRef, int16_t SectionIndex, XCOFF::StorageClass StorageClass) { // n_name, n_zeros, n_offset writeSymbolName(CSectionRef.getSymbolTableName()); @@ -628,9 +695,9 @@ // Typecheck section number. Not supported. W.write(0); // Symbol type. - W.write(getEncodedType(CSectionRef.MCCsect)); + W.write(getEncodedType(CSectionRef.MCSec)); // Storage mapping class. - W.write(CSectionRef.MCCsect->getMappingClass()); + W.write(CSectionRef.MCSec->getMappingClass()); // Reserved (x_stab). W.write(0); // Reserved (x_snstab). @@ -658,7 +725,7 @@ void XCOFFObjectWriter::writeSectionHeaderTable() { for (const auto *Sec : Sections) { // Nothing to write for this Section. - if (Sec->Index == Section::UninitializedIndex) + if (Sec->Index == SectionEntry::UninitializedIndex) continue; // Write Name. @@ -687,7 +754,7 @@ } void XCOFFObjectWriter::writeRelocation(XCOFFRelocation Reloc, - const ControlSection &CSection) { + const XCOFFSection &CSection) { W.write(CSection.Address + Reloc.FixupOffsetInCsect); W.write(Reloc.SymbolTableIndex); W.write(Reloc.SignAndSize); @@ -696,11 +763,14 @@ void XCOFFObjectWriter::writeRelocations() { for (const auto *Section : Sections) { - if (Section->Index == Section::UninitializedIndex) + if (Section->Index == SectionEntry::UninitializedIndex) // Nothing to write for this Section. continue; - for (const auto *Group : Section->Groups) { + assert(isa(Section) && "Only csect entry is supported!"); + const auto *CsectEntry = dyn_cast(Section); + + for (const auto *Group : CsectEntry->Groups) { if (Group->empty()) continue; @@ -738,24 +808,28 @@ W.write(0); for (const auto &Csect : UndefinedCsects) { - writeSymbolTableEntryForControlSection( - Csect, XCOFF::ReservedSectionNum::N_UNDEF, Csect.MCCsect->getStorageClass()); + writeSymbolTableEntryForControlSection(Csect, + XCOFF::ReservedSectionNum::N_UNDEF, + Csect.MCSec->getStorageClass()); } for (const auto *Section : Sections) { - if (Section->Index == Section::UninitializedIndex) + if (Section->Index == SectionEntry::UninitializedIndex) // Nothing to write for this Section. continue; - for (const auto *Group : Section->Groups) { + assert(isa(Section) && "Only csect entry is supported!"); + const auto *CsectEntry = dyn_cast(Section); + + for (const auto *Group : CsectEntry->Groups) { if (Group->empty()) continue; - const int16_t SectionIndex = Section->Index; + const int16_t SectionIndex = CsectEntry->Index; for (const auto &Csect : *Group) { // Write out the control section first and then each symbol in it. - writeSymbolTableEntryForControlSection( - Csect, SectionIndex, Csect.MCCsect->getStorageClass()); + writeSymbolTableEntryForControlSection(Csect, SectionIndex, + Csect.MCSec->getStorageClass()); for (const auto &Sym : Csect.Syms) writeSymbolTableEntryForCsectMemberLabel( @@ -767,11 +841,14 @@ void XCOFFObjectWriter::finalizeSectionInfo() { for (auto *Section : Sections) { - if (Section->Index == Section::UninitializedIndex) + if (Section->Index == SectionEntry::UninitializedIndex) // Nothing to record for this Section. continue; - for (const auto *Group : Section->Groups) { + assert(isa(Section) && "Only csect entry is supported!"); + auto *CsectEntry = dyn_cast(Section); + + for (const auto *Group : CsectEntry->Groups) { if (Group->empty()) continue; @@ -783,7 +860,7 @@ "relocation entries overflowed; overflow section is " "not implemented yet"); - Section->RelocationCount += CsectRelocCount; + CsectEntry->RelocationCount += CsectRelocCount; } } } @@ -791,12 +868,16 @@ // Calculate the file offset to the relocation entries. uint64_t RawPointer = RelocationEntryOffset; for (auto Sec : Sections) { - if (Sec->Index == Section::UninitializedIndex || !Sec->RelocationCount) + assert(isa(Sec) && "Only csect entry is supported!"); + auto *CsectEntry = dyn_cast(Sec); + + if (CsectEntry->Index == SectionEntry::UninitializedIndex || + !CsectEntry->RelocationCount) continue; - Sec->FileOffsetToRelocations = RawPointer; + CsectEntry->FileOffsetToRelocations = RawPointer; const uint32_t RelocationSizeInSec = - Sec->RelocationCount * XCOFF::RelocationSerializationSize32; + CsectEntry->RelocationCount * XCOFF::RelocationSerializationSize32; RawPointer += RelocationSizeInSec; if (RawPointer > UINT32_MAX) report_fatal_error("Relocation data overflowed this object file."); @@ -817,7 +898,7 @@ Csect.Size = 0; Csect.Address = 0; Csect.SymbolTableIndex = SymbolTableIndex; - SymbolIndexMap[Csect.MCCsect->getQualNameSymbol()] = Csect.SymbolTableIndex; + SymbolIndexMap[Csect.MCSec->getQualNameSymbol()] = Csect.SymbolTableIndex; // 1 main and 1 auxiliary symbol table entry for each contained symbol. SymbolTableIndex += 2; } @@ -830,24 +911,26 @@ int32_t SectionIndex = 1; for (auto *Section : Sections) { + assert(isa(Section) && "Only csect entry is supported!"); + auto *CsectEntry = dyn_cast(Section); const bool IsEmpty = - llvm::all_of(Section->Groups, + llvm::all_of(CsectEntry->Groups, [](const CsectGroup *Group) { return Group->empty(); }); if (IsEmpty) continue; if (SectionIndex > MaxSectionIndex) report_fatal_error("Section index overflow!"); - Section->Index = SectionIndex++; + CsectEntry->Index = SectionIndex++; SectionCount++; bool SectionAddressSet = false; - for (auto *Group : Section->Groups) { + for (auto *Group : CsectEntry->Groups) { if (Group->empty()) continue; for (auto &Csect : *Group) { - const MCSectionXCOFF *MCSec = Csect.MCCsect; + const MCSectionXCOFF *MCSec = Csect.MCSec; Csect.Address = alignTo(Address, MCSec->getAlignment()); Csect.Size = Layout.getSectionAddressSize(MCSec); Address = Csect.Address + Csect.Size; @@ -866,7 +949,7 @@ } if (!SectionAddressSet) { - Section->Address = Group->front().Address; + CsectEntry->Address = Group->front().Address; SectionAddressSet = true; } } @@ -874,7 +957,7 @@ // Make sure the address of the next section aligned to // DefaultSectionAlign. Address = alignTo(Address, DefaultSectionAlign); - Section->Size = Address - Section->Address; + CsectEntry->Size = Address - CsectEntry->Address; } SymbolTableEntryCount = SymbolTableIndex; @@ -883,11 +966,14 @@ uint64_t RawPointer = sizeof(XCOFF::FileHeader32) + auxiliaryHeaderSize() + SectionCount * sizeof(XCOFF::SectionHeader32); for (auto *Sec : Sections) { - if (Sec->Index == Section::UninitializedIndex || Sec->IsVirtual) + assert(isa(Sec) && "Only csect entry is supported!"); + auto *CsectEntry = dyn_cast(Sec); + if (CsectEntry->Index == SectionEntry::UninitializedIndex || + CsectEntry->IsVirtual) continue; - Sec->FileOffsetToData = RawPointer; - RawPointer += Sec->Size; + CsectEntry->FileOffsetToData = RawPointer; + RawPointer += CsectEntry->Size; if (RawPointer > UINT32_MAX) report_fatal_error("Section raw data overflowed this object file."); }