diff --git a/llvm/include/llvm/MC/MCSectionXCOFF.h b/llvm/include/llvm/MC/MCSectionXCOFF.h --- a/llvm/include/llvm/MC/MCSectionXCOFF.h +++ b/llvm/include/llvm/MC/MCSectionXCOFF.h @@ -104,6 +104,9 @@ bool isVirtualSection() const override; StringRef getSymbolTableName() const { return SymbolTableName; } bool isMultiSymbolsAllowed() const { return MultiSymbolsAllowed; } + bool isDWARFSection() const { + return getSecFlags() & (unsigned)XCOFF::STYP_DWARF; + } bool isCsect() const { return CsectProp.hasValue(); } unsigned getSecFlags() const { return SecFlags; } }; 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,17 +73,44 @@ }; // 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; + XCOFFSection(const MCSectionXCOFF *MCSec) + : MCSec(MCSec), SymbolTableIndex(-1), Address(-1), Size(0) {} + 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(); } + // The kind of the XCOFF Section. + // FIXME: add more section types, like debug, comment and so on. + enum SectionKind { SectionUnknown, SectionDWARF, SectionCsect }; + virtual uint32_t getSectionKind() const { return SectionUnknown; }; +}; + +struct ControlSection : public XCOFFSection { + // Symbols defined in this Csect + SmallVector Syms; + ControlSection(const MCSectionXCOFF *MCSec) : XCOFFSection(MCSec) { + assert(MCSec->isCsect() && "Not a Csect!"); + } + uint32_t getSectionKind() const override { return SectionCsect; }; + static bool classof(const XCOFFSection *Sec) { + return Sec->getSectionKind() == SectionCsect; + } +}; + +struct DWARFSection : public XCOFFSection { + DWARFSection(const MCSectionXCOFF *MCSec) : XCOFFSection(MCSec) { + assert(MCSec->isDWARFSection() && "Not a DWARF section!"); + } + uint32_t getSectionKind() const override { return SectionDWARF; }; + static bool classof(const XCOFFSection *Sec) { + return Sec->getSectionKind() == SectionDWARF; + } }; // Type to be used for a container representing a set of csects with @@ -93,12 +120,9 @@ 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. @@ -107,13 +131,10 @@ uint32_t FileOffsetToData; uint32_t FileOffsetToRelocations; uint32_t RelocationCount; - int32_t Flags; + uint32_t Flags; 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 +145,85 @@ static constexpr int16_t UninitializedIndex = XCOFF::ReservedSectionNum::N_DEBUG - 1; - CsectGroups Groups; + SectionEntry(StringRef N, uint32_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; + } + + // 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) { + 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, uint32_t Flags, DWARFSection *DWARFSect) + : SectionEntry(N, Flags), DWARFSect(std::move(DWARFSect)) { assert(N.size() <= XCOFF::NameSize && "section name too long"); memcpy(Name, N.data(), N.size()); } + + void reset() override { + SectionEntry::reset(); + // Destory DWARFSection we own. + DWARFSect.reset(); + } + + uint32_t getSectionEntryKind() const override { return SectionEntryDWARF; }; + static bool classof(const SectionEntry *Sec) { + return Sec->getSectionEntryKind() == SectionEntryDWARF; + } }; class XCOFFObjectWriter : public MCObjectWriter { @@ -162,7 +240,7 @@ // Maps the MCSection representation to its corresponding ControlSection // wrapper. Needed for finding the ControlSection 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 +258,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); @@ -330,7 +408,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."); @@ -373,7 +451,11 @@ assert(SectionMap.find(ContainingCsect) != SectionMap.end() && "Expected containing csect to exist in map"); // Lookup the containing csect and add the symbol to it. - SectionMap[ContainingCsect]->Syms.emplace_back(XSym); + assert(isa(SectionMap[ContainingCsect]) && + "only csect is supported now!"); + ControlSection *Csect = + dyn_cast(SectionMap[ContainingCsect]); + 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 +569,27 @@ const MCAsmLayout &Layout) { uint32_t CurrentAddressLocation = 0; for (const auto *Section : Sections) { + assert(isa(Section) && "Only csect entry is supported!"); + 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 +598,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; } @@ -592,7 +677,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). @@ -628,9 +713,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 +743,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. @@ -696,11 +781,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!"); + auto CsectEntry = dyn_cast(Section); + + for (const auto *Group : CsectEntry->Groups) { if (Group->empty()) continue; @@ -714,24 +802,28 @@ void XCOFFObjectWriter::writeSymbolTable(const MCAsmLayout &Layout) { 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!"); + 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()); + Csect, SectionIndex, Csect.MCSec->getStorageClass()); for (const auto &Sym : Csect.Syms) writeSymbolTableEntryForCsectMemberLabel( @@ -743,11 +835,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; @@ -759,7 +854,7 @@ "relocation entries overflowed; overflow section is " "not implemented yet"); - Section->RelocationCount += CsectRelocCount; + CsectEntry->RelocationCount += CsectRelocCount; } } } @@ -767,12 +862,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."); @@ -794,7 +893,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; } @@ -807,24 +906,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; @@ -843,7 +944,7 @@ } if (!SectionAddressSet) { - Section->Address = Group->front().Address; + CsectEntry->Address = Group->front().Address; SectionAddressSet = true; } } @@ -851,7 +952,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; @@ -860,11 +961,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."); }