Index: llvm/test/tools/llvm-readobj/xcoff-overflow-section.test =================================================================== --- /dev/null +++ llvm/test/tools/llvm-readobj/xcoff-overflow-section.test @@ -0,0 +1,47 @@ +# RUN: llvm-readobj --sections %p/Inputs/xcoff-reloc-overflow.o | \ +# RUN: FileCheck --check-prefix=SECOVERFLOW %s +# SECOVERFLOW: File: {{.*}}xcoff-reloc-overflow.o +# SECOVERFLOW-NEXT: Format: aixcoff-rs6000 +# SECOVERFLOW-NEXT: Arch: powerpc +# SECOVERFLOW-NEXT: AddressSize: 32bit +# SECOVERFLOW-NEXT: Sections [ +# SECOVERFLOW-NEXT: Section { +# SECOVERFLOW-NEXT: Index: 1 +# SECOVERFLOW-NEXT: Name: .text +# SECOVERFLOW-NEXT: PhysicalAddress: 0x0 +# SECOVERFLOW-NEXT: VirtualAddress: 0x0 +# SECOVERFLOW-NEXT: Size: 0x38 +# SECOVERFLOW-NEXT: RawDataOffset: 0x8C +# SECOVERFLOW-NEXT: RelocationPointer: 0x0 +# SECOVERFLOW-NEXT: LineNumberPointer: 0x0 +# SECOVERFLOW-NEXT: NumberOfRelocations: 0 +# SECOVERFLOW-NEXT: NumberOfLineNumbers: 0 +# SECOVERFLOW-NEXT: Type: STYP_TEXT (0x20) +# SECOVERFLOW-NEXT: } +# SECOVERFLOW-NEXT: Section { +# SECOVERFLOW-NEXT: Index: 2 +# SECOVERFLOW-NEXT: Name: .data +# SECOVERFLOW-NEXT: PhysicalAddress: 0x38 +# SECOVERFLOW-NEXT: VirtualAddress: 0x38 +# SECOVERFLOW-NEXT: Size: 0x1C +# SECOVERFLOW-NEXT: RawDataOffset: 0xC4 +# SECOVERFLOW-NEXT: RelocationPointer: 0xE0 +# SECOVERFLOW-NEXT: LineNumberPointer: 0x0 +# SECOVERFLOW-NEXT: NumberOfRelocations: 65535 +# SECOVERFLOW-NEXT: NumberOfLineNumbers: 65535 +# SECOVERFLOW-NEXT: Type: STYP_DATA (0x40) +# SECOVERFLOW-NEXT: } +# SECOVERFLOW-NEXT: Section { +# SECOVERFLOW-NEXT: Index: 3 +# SECOVERFLOW-NEXT: Name: .ovrflo +# SECOVERFLOW-NEXT: NumberOfRelocations: 3 +# SECOVERFLOW-NEXT: NumberOfLineNumbers: 3 +# SECOVERFLOW-NEXT: Size: 0x0 +# SECOVERFLOW-NEXT: RawDataOffset: 0x0 +# SECOVERFLOW-NEXT: RelocationPointer: 0xE0 +# SECOVERFLOW-NEXT: LineNumberPointer: 0x0 +# SECOVERFLOW-NEXT: IndexOfSectionOverflowed: 2 +# SECOVERFLOW-NEXT: IndexOfSectionOverflowed: 2 +# SECOVERFLOW-NEXT: Type: STYP_OVRFLO (0x8000) +# SECOVERFLOW-NEXT: } +# SECOVERFLOW-NEXT: ] Index: llvm/tools/llvm-readobj/XCOFFDumper.cpp =================================================================== --- llvm/tools/llvm-readobj/XCOFFDumper.cpp +++ llvm/tools/llvm-readobj/XCOFFDumper.cpp @@ -43,6 +43,8 @@ private: template void printSectionHeaders(ArrayRef Sections); + template void printGenericSectionHeader(T &Sec) const; + template void printOverflowSectionHeader(T &Sec) const; void printFileAuxEnt(const XCOFFFileAuxEnt *AuxEntPtr); void printCsectAuxEnt32(const XCOFFCsectAuxEnt32 *AuxEntPtr); void printSectAuxEntForStat(const XCOFFSectAuxEntForStat *AuxEntPtr); @@ -50,6 +52,10 @@ // Least significant 3 bits are reserved. static constexpr unsigned SectionFlagsReservedMask = 0x7; + + // The low order 16 bits of section flags denotes the section type. + static constexpr unsigned SectionFlagsTypeMask = 0xffffu; + const XCOFFObjectFile &Obj; }; } // anonymous namespace @@ -397,6 +403,39 @@ }; template +void XCOFFDumper::printOverflowSectionHeader(T &Sec) const { + if (Obj.is64Bit()) { + reportWarning(make_error("An 64-bit XCOFF object file may not " + "contain an overflow section header.", + object_error::parse_failed), + Obj.getFileName()); + } + + W.printString("Name", Sec.getName()); + W.printNumber("NumberOfRelocations", Sec.PhysicalAddress); + W.printNumber("NumberOfLineNumbers", Sec.VirtualAddress); + W.printHex("Size", Sec.SectionSize); + W.printHex("RawDataOffset", Sec.FileOffsetToRawData); + W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo); + W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo); + W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfRelocations); + W.printNumber("IndexOfSectionOverflowed", Sec.NumberOfLineNumbers); +} + +template +void XCOFFDumper::printGenericSectionHeader(T &Sec) const { + W.printString("Name", Sec.getName()); + W.printHex("PhysicalAddress", Sec.PhysicalAddress); + W.printHex("VirtualAddress", Sec.VirtualAddress); + W.printHex("Size", Sec.SectionSize); + W.printHex("RawDataOffset", Sec.FileOffsetToRawData); + W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo); + W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo); + W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations); + W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers); +} + +template void XCOFFDumper::printSectionHeaders(ArrayRef Sections) { ListScope Group(W, "Sections"); @@ -405,27 +444,28 @@ DictScope SecDS(W, "Section"); W.printNumber("Index", Index++); - W.printString("Name", Sec.getName()); - - W.printHex("PhysicalAddress", Sec.PhysicalAddress); - W.printHex("VirtualAddress", Sec.VirtualAddress); - W.printHex("Size", Sec.SectionSize); - W.printHex("RawDataOffset", Sec.FileOffsetToRawData); - W.printHex("RelocationPointer", Sec.FileOffsetToRelocationInfo); - W.printHex("LineNumberPointer", Sec.FileOffsetToLineNumberInfo); - - // TODO Need to add overflow handling when NumberOfX == _OVERFLOW_MARKER - // in 32-bit object files. - W.printNumber("NumberOfRelocations", Sec.NumberOfRelocations); - W.printNumber("NumberOfLineNumbers", Sec.NumberOfLineNumbers); - - // The most significant 16-bits represent the DWARF section subtype. For - // now we just dump the section type flags. - uint16_t Flags = Sec.Flags & 0xffffu; - if (Flags & SectionFlagsReservedMask) - W.printHex("Flags", "Reserved", Flags); + + uint16_t SectionType = Sec.Flags & SectionFlagsTypeMask; + switch (SectionType) { + case XCOFF::STYP_OVRFLO: + printOverflowSectionHeader(Sec); + break; + case XCOFF::STYP_LOADER: + case XCOFF::STYP_EXCEPT: + case XCOFF::STYP_TYPCHK: + // TODO: The interpretation of loader, exception and type check section + // headers are different from that of generic section headers. We will + // implement them later. We interpret them as generic section headers for + // now. + default: + printGenericSectionHeader(Sec); + break; + } + // For now we just dump the section type portion of the flags. + if (SectionType & SectionFlagsReservedMask) + W.printHex("Flags", "Reserved", SectionType); else - W.printEnum("Type", Flags, makeArrayRef(SectionTypeFlagsNames)); + W.printEnum("Type", SectionType, makeArrayRef(SectionTypeFlagsNames)); } if (opts::SectionRelocations)