diff --git a/llvm/include/llvm/Object/XCOFFObjectFile.h b/llvm/include/llvm/Object/XCOFFObjectFile.h index 47926ab3ae401..fa23aa9c5d3f4 100644 --- a/llvm/include/llvm/Object/XCOFFObjectFile.h +++ b/llvm/include/llvm/Object/XCOFFObjectFile.h @@ -153,15 +153,19 @@ struct XCOFFAuxiliaryHeader64 : XCOFFAuxiliaryHeader { }; template struct XCOFFSectionHeader { - // Least significant 3 bits are reserved. + // The section flags definitions are the same in both 32- and 64-bit objects. + // Least significant 3 bits are reserved. static constexpr unsigned SectionFlagsReservedMask = 0x7; // The low order 16 bits of section flags denotes the section type. + // The high order 16 bits of section flags denotes the section subtype. + // For now, this is only used for DWARF sections. static constexpr unsigned SectionFlagsTypeMask = 0xffffu; public: StringRef getName() const; uint16_t getSectionType() const; + uint32_t getSectionSubtype() const; bool isReservedSectionType() const; }; diff --git a/llvm/include/llvm/ObjectYAML/XCOFFYAML.h b/llvm/include/llvm/ObjectYAML/XCOFFYAML.h index dd359ac8e53dd..2874c998d6903 100644 --- a/llvm/include/llvm/ObjectYAML/XCOFFYAML.h +++ b/llvm/include/llvm/ObjectYAML/XCOFFYAML.h @@ -79,6 +79,7 @@ struct Section { llvm::yaml::Hex16 NumberOfRelocations; llvm::yaml::Hex16 NumberOfLineNumbers; // Line number counts. Not supported yet. uint32_t Flags; + std::optional SectionSubtype; yaml::BinaryRef SectionData; std::vector Relocations; }; @@ -232,6 +233,10 @@ template <> struct ScalarBitSetTraits { static void bitset(IO &IO, XCOFF::SectionTypeFlags &Value); }; +template <> struct ScalarEnumerationTraits { + static void enumeration(IO &IO, XCOFF::DwarfSectionSubtypeFlags &Value); +}; + template <> struct ScalarEnumerationTraits { static void enumeration(IO &IO, XCOFF::StorageClass &Value); }; diff --git a/llvm/lib/Object/XCOFFObjectFile.cpp b/llvm/lib/Object/XCOFFObjectFile.cpp index 3fbd51887831e..d09e7b0698ca0 100644 --- a/llvm/lib/Object/XCOFFObjectFile.cpp +++ b/llvm/lib/Object/XCOFFObjectFile.cpp @@ -64,6 +64,12 @@ template uint16_t XCOFFSectionHeader::getSectionType() const { return DerivedXCOFFSectionHeader.Flags & SectionFlagsTypeMask; } +template +uint32_t XCOFFSectionHeader::getSectionSubtype() const { + const T &DerivedXCOFFSectionHeader = static_cast(*this); + return DerivedXCOFFSectionHeader.Flags & ~SectionFlagsTypeMask; +} + template bool XCOFFSectionHeader::isReservedSectionType() const { return getSectionType() & SectionFlagsReservedMask; diff --git a/llvm/lib/ObjectYAML/XCOFFEmitter.cpp b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp index f68c571da9fa0..0f03d3c48a317 100644 --- a/llvm/lib/ObjectYAML/XCOFFEmitter.cpp +++ b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp @@ -210,6 +210,21 @@ bool XCOFFWriter::initSectionHeaders(uint64_t &CurrentOffset) { return false; } } + if (InitSections[I].SectionSubtype) { + uint32_t DWARFSubtype = + static_cast(*InitSections[I].SectionSubtype); + if (InitSections[I].Flags != XCOFF::STYP_DWARF) { + ErrHandler("a DWARFSectionSubtype is only allowed for a DWARF section"); + return false; + } + unsigned Mask = Is64Bit ? XCOFFSectionHeader64::SectionFlagsTypeMask + : XCOFFSectionHeader32::SectionFlagsTypeMask; + if (DWARFSubtype & Mask) { + ErrHandler("the low-order bits of DWARFSectionSubtype must be 0"); + return false; + } + InitSections[I].Flags |= DWARFSubtype; + } } return initRelocations(CurrentOffset); } diff --git a/llvm/lib/ObjectYAML/XCOFFYAML.cpp b/llvm/lib/ObjectYAML/XCOFFYAML.cpp index 83bf61301387f..575334ee980e8 100644 --- a/llvm/lib/ObjectYAML/XCOFFYAML.cpp +++ b/llvm/lib/ObjectYAML/XCOFFYAML.cpp @@ -44,6 +44,24 @@ void ScalarBitSetTraits::bitset( #undef ECase } +void ScalarEnumerationTraits::enumeration( + IO &IO, XCOFF::DwarfSectionSubtypeFlags &Value) { +#define ECase(X) IO.enumCase(Value, #X, XCOFF::X) + ECase(SSUBTYP_DWINFO); + ECase(SSUBTYP_DWLINE); + ECase(SSUBTYP_DWPBNMS); + ECase(SSUBTYP_DWPBTYP); + ECase(SSUBTYP_DWARNGE); + ECase(SSUBTYP_DWABREV); + ECase(SSUBTYP_DWSTR); + ECase(SSUBTYP_DWRNGES); + ECase(SSUBTYP_DWLOC); + ECase(SSUBTYP_DWFRAME); + ECase(SSUBTYP_DWMAC); +#undef ECase + IO.enumFallback(Value); +} + void ScalarEnumerationTraits::enumeration( IO &IO, XCOFF::StorageClass &Value) { #define ECase(X) IO.enumCase(Value, #X, XCOFF::X) @@ -232,6 +250,7 @@ void MappingTraits::mapping(IO &IO, IO.mapOptional("NumberOfRelocations", Sec.NumberOfRelocations); IO.mapOptional("NumberOfLineNumbers", Sec.NumberOfLineNumbers); IO.mapOptional("Flags", NC->Flags); + IO.mapOptional("DWARFSectionSubtype", Sec.SectionSubtype); IO.mapOptional("SectionData", Sec.SectionData); IO.mapOptional("Relocations", Sec.Relocations); } diff --git a/llvm/test/CodeGen/PowerPC/aix-dwarf.ll b/llvm/test/CodeGen/PowerPC/aix-dwarf.ll index eaa7c493ee6ae..33e61a8cab376 100644 --- a/llvm/test/CodeGen/PowerPC/aix-dwarf.ll +++ b/llvm/test/CodeGen/PowerPC/aix-dwarf.ll @@ -84,6 +84,7 @@ entry: ; SEC-NEXT: NumberOfRelocations: 0 ; SEC-NEXT: NumberOfLineNumbers: 0 ; SEC-NEXT: Type: STYP_DWARF (0x10) +; SEC-NEXT: DWARFSubType: SSUBTYP_DWABREV (0x60000) ; SEC-NEXT: } ; SEC-NEXT: Section { ; SEC-NEXT: Index: 4 @@ -100,6 +101,7 @@ entry: ; SEC-NEXT: NumberOfRelocations: 4 ; SEC-NEXT: NumberOfLineNumbers: 0 ; SEC-NEXT: Type: STYP_DWARF (0x10) +; SEC-NEXT: DWARFSubType: SSUBTYP_DWINFO (0x10000) ; SEC-NEXT: } ; SEC-NEXT: Section { ; SEC-NEXT: Index: 5 @@ -116,6 +118,7 @@ entry: ; SEC-NEXT: NumberOfRelocations: 1 ; SEC-NEXT: NumberOfLineNumbers: 0 ; SEC-NEXT: Type: STYP_DWARF (0x10) +; SEC-NEXT: DWARFSubType: SSUBTYP_DWLINE (0x20000) ; SEC-NEXT: } ; SEC-NEXT: ] diff --git a/llvm/test/tools/llvm-readobj/XCOFF/sections.test b/llvm/test/tools/llvm-readobj/XCOFF/sections.test index 36e85d6033652..6640d5bb655f5 100644 --- a/llvm/test/tools/llvm-readobj/XCOFF/sections.test +++ b/llvm/test/tools/llvm-readobj/XCOFF/sections.test @@ -2,39 +2,61 @@ # RUN: yaml2obj %s -o %t1 # RUN: llvm-readobj --section-headers %t1 | \ -# RUN: FileCheck --strict-whitespace --match-full-lines --check-prefix=SEC32 %s +# RUN: FileCheck --strict-whitespace --match-full-lines --check-prefixes=SEC,SEC32 %s + +# RUN: yaml2obj -DMAGIC=0x01F7 %s -o %t2 +# RUN: llvm-readobj --section-headers %t2 | \ +# RUN: FileCheck --strict-whitespace --match-full-lines --check-prefixes=SEC,SEC64 %s # SEC32:Format: aixcoff-rs6000 +# SEC64:Format: aix5coff64-rs6000 # SEC32-NEXT:Arch: powerpc +# SEC64-NEXT:Arch: powerpc64 # SEC32-NEXT:AddressSize: 32bit -# SEC32-NEXT:Sections [ -# SEC32-NEXT: Section { -# SEC32-NEXT: Index: 1 -# SEC32-NEXT: Name: .text -# SEC32-NEXT: PhysicalAddress: 0x0 -# SEC32-NEXT: VirtualAddress: 0x0 -# SEC32-NEXT: Size: 0x2 -# SEC32-NEXT: RawDataOffset: 0x64 -# SEC32-NEXT: RelocationPointer: 0x0 -# SEC32-NEXT: LineNumberPointer: 0x0 -# SEC32-NEXT: NumberOfRelocations: 0 -# SEC32-NEXT: NumberOfLineNumbers: 0 -# SEC32-NEXT: Type: STYP_TEXT (0x20) -# SEC32-NEXT: } -# SEC32-NEXT: Section { -# SEC32-NEXT: Index: 2 -# SEC32-NEXT: Name: .data -# SEC32-NEXT: PhysicalAddress: 0x0 -# SEC32-NEXT: VirtualAddress: 0x0 -# SEC32-NEXT: Size: 0x2 -# SEC32-NEXT: RawDataOffset: 0x68 -# SEC32-NEXT: RelocationPointer: 0x6A -# SEC32-NEXT: LineNumberPointer: 0x0 -# SEC32-NEXT: NumberOfRelocations: 1 -# SEC32-NEXT: NumberOfLineNumbers: 0 -# SEC32-NEXT: Type: STYP_DATA (0x40) -# SEC32-NEXT: } -# SEC32-NEXT:] +# SEC64-NEXT:AddressSize: 64bit +# SEC-NEXT:Sections [ +# SEC-NEXT: Section { +# SEC-NEXT: Index: 1 +# SEC-NEXT: Name: .text +# SEC-NEXT: PhysicalAddress: 0x0 +# SEC-NEXT: VirtualAddress: 0x0 +# SEC-NEXT: Size: 0x2 +# SEC32-NEXT: RawDataOffset: 0xB4 +# SEC64-NEXT: RawDataOffset: 0x138 +# SEC-NEXT: RelocationPointer: 0x0 +# SEC-NEXT: LineNumberPointer: 0x0 +# SEC-NEXT: NumberOfRelocations: 0 +# SEC-NEXT: NumberOfLineNumbers: 0 +# SEC-NEXT: Type: STYP_TEXT (0x20) +# SEC-NEXT: } +# SEC-NEXT: Section { +# SEC-NEXT: Index: 2 +# SEC-NEXT: Name: .data +# SEC-NEXT: PhysicalAddress: 0x0 +# SEC-NEXT: VirtualAddress: 0x0 +# SEC-NEXT: Size: 0x2 +# SEC32-NEXT: RawDataOffset: 0xB8 +# SEC64-NEXT: RawDataOffset: 0x13C +# SEC32-NEXT: RelocationPointer: 0xC4 +# SEC64-NEXT: RelocationPointer: 0x148 +# SEC-NEXT: LineNumberPointer: 0x0 +# SEC-NEXT: NumberOfRelocations: 1 +# SEC-NEXT: NumberOfLineNumbers: 0 +# SEC-NEXT: Type: STYP_DATA (0x40) +# SEC-NEXT: } +# SEC-NEXT: Section { +# SEC-NEXT: Index: 3 +# SEC-NEXT: Name: .dwabrev +# SEC: Type: STYP_DWARF (0x10) +# SEC-NEXT: DWARFSubType: SSUBTYP_DWABREV (0x60000) +# SEC-NEXT: } +# SEC-NEXT: Section { +# SEC-NEXT: Index: 4 +# SEC-NEXT: Name: .dwinfo +# SEC: Type: STYP_DWARF (0x10) +# SEC-NEXT: DWARFSubType: SSUBTYP_DWINFO (0x10000) +# SEC-NEXT: } +# SEC-NEXT:] --- !XCOFF FileHeader: @@ -51,39 +73,15 @@ Sections: Symbol: 0x21 Info: 0x1F Type: 0x0 - -# RUN: yaml2obj -DMAGIC=0x01F7 %s -o %t2 -# RUN: llvm-readobj --section-headers %t2 | \ -# RUN: FileCheck --strict-whitespace --match-full-lines --check-prefix=SEC64 %s - -# SEC64:Format: aix5coff64-rs6000 -# SEC64-NEXT:Arch: powerpc64 -# SEC64-NEXT:AddressSize: 64bit -# SEC64-NEXT:Sections [ -# SEC64-NEXT: Section { -# SEC64-NEXT: Index: 1 -# SEC64-NEXT: Name: .text -# SEC64-NEXT: PhysicalAddress: 0x0 -# SEC64-NEXT: VirtualAddress: 0x0 -# SEC64-NEXT: Size: 0x2 -# SEC64-NEXT: RawDataOffset: 0xA8 -# SEC64-NEXT: RelocationPointer: 0x0 -# SEC64-NEXT: LineNumberPointer: 0x0 -# SEC64-NEXT: NumberOfRelocations: 0 -# SEC64-NEXT: NumberOfLineNumbers: 0 -# SEC64-NEXT: Type: STYP_TEXT (0x20) -# SEC64-NEXT: } -# SEC64-NEXT: Section { -# SEC64-NEXT: Index: 2 -# SEC64-NEXT: Name: .data -# SEC64-NEXT: PhysicalAddress: 0x0 -# SEC64-NEXT: VirtualAddress: 0x0 -# SEC64-NEXT: Size: 0x2 -# SEC64-NEXT: RawDataOffset: 0xAC -# SEC64-NEXT: RelocationPointer: 0xAE -# SEC64-NEXT: LineNumberPointer: 0x0 -# SEC64-NEXT: NumberOfRelocations: 1 -# SEC64-NEXT: NumberOfLineNumbers: 0 -# SEC64-NEXT: Type: STYP_DATA (0x40) -# SEC64-NEXT: } -# SEC64-NEXT:] + - Name: .dwabrev + Address: 0x0 + Size: 0x4 + Flags: [ STYP_DWARF ] + DWARFSectionSubtype: SSUBTYP_DWABREV + SectionData: 01110125 + - Name: .dwinfo + Address: 0x0 + Size: 0x4 + Flags: [ STYP_DWARF ] + DWARFSectionSubtype: SSUBTYP_DWINFO + SectionData: 00000080 diff --git a/llvm/test/tools/yaml2obj/XCOFF/dwarf-subsection-types.yaml b/llvm/test/tools/yaml2obj/XCOFF/dwarf-subsection-types.yaml new file mode 100644 index 0000000000000..a24557a247d14 --- /dev/null +++ b/llvm/test/tools/yaml2obj/XCOFF/dwarf-subsection-types.yaml @@ -0,0 +1,105 @@ +## Test that we can generate and read DWARF section headers. + +# RUN: yaml2obj --docnum=1 %s -o %t32 +# RUN: obj2yaml %t32 | FileCheck --check-prefix=YAML %s + +# RUN: yaml2obj --docnum=1 -DMAGIC=0x01F7 %s -o %t64 +# RUN: obj2yaml %t64 | FileCheck --check-prefix=YAML %s + +# YAML: - Name: .dwabrev +# YAML: Flags: [ STYP_DWARF ] +# YAML-NEXT: DWARFSectionSubtype: SSUBTYP_DWABREV +# YAML: - Name: .dwinfo +# YAML: Flags: [ STYP_DWARF ] +# YAML-NEXT: DWARFSectionSubtype: SSUBTYP_DWINFO +# YAML: - Name: .dwline +# YAML: Flags: [ STYP_DWARF ] +# YAML-NEXT: DWARFSectionSubtype: SSUBTYP_DWLINE + +--- !XCOFF +FileHeader: + MagicNumber: [[MAGIC=0x01DF]] + NumberOfSections: 4 + CreationTime: 0 + AuxiliaryHeaderSize: 0 + Flags: 0x0 +Sections: + - Name: .data + Address: 0x0 + Size: 0x4 + Flags: [ STYP_DATA ] + SectionData: '00000001' + - Name: .dwabrev + Address: 0x0 + Size: 0x4 + Flags: [ STYP_DWARF ] + DWARFSectionSubtype: SSUBTYP_DWABREV + SectionData: 01110125 + - Name: .dwinfo + Address: 0x0 + Size: 0x4 + Flags: [ STYP_DWARF ] + DWARFSectionSubtype: SSUBTYP_DWINFO + SectionData: 00000080 + - Name: .dwline + Address: 0x0 + Size: 0x4 + Flags: [ STYP_DWARF ] + DWARFSectionSubtype: SSUBTYP_DWLINE + SectionData: 00000021 +StringTable: {} +... + +## Test that an invalid DWARF section subtype is diagnosed. +# RUN: not yaml2obj --docnum=2 %s -o %t 2>&1 | FileCheck --check-prefix=ERR1 %s + +# ERR1: the low-order bits of DWARFSectionSubtype must be 0 + +--- !XCOFF +FileHeader: + MagicNumber: 0x01DF + NumberOfSections: 2 + CreationTime: 0 + AuxiliaryHeaderSize: 0 + Flags: 0x0 +Sections: + - Name: .data + Address: 0x0 + Size: 0x4 + Flags: [ STYP_DATA ] + SectionData: '00000001' + - Name: .dwabrev + Address: 0x0 + Size: 0x4 + Flags: [ STYP_DWARF ] + DWARFSectionSubtype: 0x12345 + SectionData: 01110125 +StringTable: {} +... + +## Test that a DWARF section subtype on a non-DWARF section is diagnosed. +# RUN: not yaml2obj --docnum=3 %s -o %t 2>&1 | FileCheck --check-prefix=ERR2 %s + +# ERR2: a DWARFSectionSubtype is only allowed for a DWARF section + +--- !XCOFF +FileHeader: + MagicNumber: 0x01DF + NumberOfSections: 2 + CreationTime: 0 + AuxiliaryHeaderSize: 0 + Flags: 0x0 +Sections: + - Name: .data + Address: 0x0 + Size: 0x4 + Flags: [ STYP_DATA ] + DWARFSectionSubtype: SSUBTYP_DWABREV + SectionData: '00000001' + - Name: .dwabrev + Address: 0x0 + Size: 0x4 + Flags: [ STYP_DWARF ] + SectionData: 01110125 +StringTable: {} +... diff --git a/llvm/tools/llvm-readobj/XCOFFDumper.cpp b/llvm/tools/llvm-readobj/XCOFFDumper.cpp index 8ebd670d5d56a..e7f50e8a18841 100644 --- a/llvm/tools/llvm-readobj/XCOFFDumper.cpp +++ b/llvm/tools/llvm-readobj/XCOFFDumper.cpp @@ -983,6 +983,17 @@ const EnumEntry SectionTypeFlagsNames[] = { #undef ECase }; +const EnumEntry + DWARFSectionSubtypeFlagsNames[] = { +#define ECase(X) \ + { #X, XCOFF::X } + ECase(SSUBTYP_DWINFO), ECase(SSUBTYP_DWLINE), ECase(SSUBTYP_DWPBNMS), + ECase(SSUBTYP_DWPBTYP), ECase(SSUBTYP_DWARNGE), ECase(SSUBTYP_DWABREV), + ECase(SSUBTYP_DWSTR), ECase(SSUBTYP_DWRNGES), ECase(SSUBTYP_DWLOC), + ECase(SSUBTYP_DWFRAME), ECase(SSUBTYP_DWMAC) +#undef ECase +}; + template void XCOFFDumper::printOverflowSectionHeader(T &Sec) const { if (Obj.is64Bit()) { @@ -1180,6 +1191,7 @@ void XCOFFDumper::printSectionHeaders(ArrayRef Sections) { W.printNumber("Index", Index++); uint16_t SectionType = Sec.getSectionType(); + int32_t SectionSubtype = Sec.getSectionSubtype(); switch (SectionType) { case XCOFF::STYP_OVRFLO: printOverflowSectionHeader(Sec); @@ -1197,8 +1209,13 @@ void XCOFFDumper::printSectionHeaders(ArrayRef Sections) { } if (Sec.isReservedSectionType()) W.printHex("Flags", "Reserved", SectionType); - else + else { W.printEnum("Type", SectionType, ArrayRef(SectionTypeFlagsNames)); + if (SectionType == XCOFF::STYP_DWARF) { + W.printEnum("DWARFSubType", SectionSubtype, + ArrayRef(DWARFSectionSubtypeFlagsNames)); + } + } } if (opts::SectionRelocations) diff --git a/llvm/tools/obj2yaml/xcoff2yaml.cpp b/llvm/tools/obj2yaml/xcoff2yaml.cpp index e426b645cbeff..4b9ebb85b62e3 100644 --- a/llvm/tools/obj2yaml/xcoff2yaml.cpp +++ b/llvm/tools/obj2yaml/xcoff2yaml.cpp @@ -95,6 +95,13 @@ Error XCOFFDumper::dumpSections(ArrayRef Sections) { YamlSec.FileOffsetToRelocations = S.FileOffsetToRelocationInfo; YamlSec.FileOffsetToLineNumbers = S.FileOffsetToLineNumberInfo; YamlSec.Flags = S.Flags; + if (YamlSec.Flags & XCOFF::STYP_DWARF) { + unsigned Mask = Obj.is64Bit() + ? XCOFFSectionHeader64::SectionFlagsTypeMask + : XCOFFSectionHeader32::SectionFlagsTypeMask; + YamlSec.SectionSubtype = + static_cast(S.Flags & ~Mask); + } // Dump section data. if (S.FileOffsetToRawData) {