diff --git a/llvm/include/llvm/BinaryFormat/XCOFF.h b/llvm/include/llvm/BinaryFormat/XCOFF.h --- a/llvm/include/llvm/BinaryFormat/XCOFF.h +++ b/llvm/include/llvm/BinaryFormat/XCOFF.h @@ -26,8 +26,13 @@ constexpr size_t FileNamePadSize = 6; constexpr size_t NameSize = 8; +constexpr size_t FileHeaderSize32 = 20; +constexpr size_t FileHeaderSize64 = 24; +constexpr size_t SectionHeaderSize32 = 40; +constexpr size_t SectionHeaderSize64 = 72; constexpr size_t SymbolTableEntrySize = 18; constexpr size_t RelocationSerializationSize32 = 10; +constexpr size_t RelocationSerializationSize64 = 14; constexpr uint16_t RelocOverflow = 65535; constexpr uint8_t AllocRegNo = 31; @@ -255,29 +260,6 @@ ///< large code model TOC-relative relocation. }; -struct FileHeader32 { - uint16_t Magic; - uint16_t NumberOfSections; - int32_t TimeStamp; - uint32_t SymbolTableFileOffset; - int32_t NumberOfSymbolTableEntries; - uint16_t AuxiliaryHeaderSize; - uint16_t Flags; -}; - -struct SectionHeader32 { - char Name[XCOFF::NameSize]; - uint32_t PhysicalAddress; - uint32_t VirtualAddress; - uint32_t Size; - uint32_t FileOffsetToData; - uint32_t FileOffsetToRelocations; - uint32_t FileOffsetToLineNumbers; - uint16_t NumberOfRelocations; - uint16_t NumberOfLineNumbers; - int32_t Flags; -}; - enum CFileStringType : uint8_t { XFT_FN = 0, ///< Specifies the source-file name. XFT_CT = 1, ///< Specifies the compiler time stamp. 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 @@ -911,8 +911,8 @@ SymbolTableEntryCount = SymbolTableIndex; // Calculate the RawPointer value for each section. - uint64_t RawPointer = sizeof(XCOFF::FileHeader32) + auxiliaryHeaderSize() + - SectionCount * sizeof(XCOFF::SectionHeader32); + uint64_t RawPointer = XCOFF::FileHeaderSize32 + auxiliaryHeaderSize() + + SectionCount * XCOFF::SectionHeaderSize32; for (auto *Sec : Sections) { if (Sec->Index == Section::UninitializedIndex || Sec->IsVirtual) continue; diff --git a/llvm/lib/ObjectYAML/XCOFFEmitter.cpp b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp --- a/llvm/lib/ObjectYAML/XCOFFEmitter.cpp +++ b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp @@ -65,7 +65,8 @@ }; bool XCOFFWriter::nameShouldBeInStringTable(StringRef SymbolName) { - return SymbolName.size() > XCOFF::NameSize; + // For XCOFF64: The symbol name is always in string table or .debug section. + return (SymbolName.size() > XCOFF::NameSize) || Is64Bit; } bool XCOFFWriter::initRelocations(uint64_t &CurrentOffset) { @@ -73,8 +74,9 @@ if (!InitSections[I].Relocations.empty()) { InitSections[I].NumberOfRelocations = InitSections[I].Relocations.size(); InitSections[I].FileOffsetToRelocations = CurrentOffset; - CurrentOffset += InitSections[I].NumberOfRelocations * - XCOFF::RelocationSerializationSize32; + uint64_t RelSize = Is64Bit ? XCOFF::RelocationSerializationSize64 + : XCOFF::RelocationSerializationSize32; + CurrentOffset += InitSections[I].NumberOfRelocations * RelSize; if (CurrentOffset > MaxRawDataSize) { ErrHandler("maximum object size of" + Twine(MaxRawDataSize) + "exceeded when writing relocation data"); @@ -132,7 +134,7 @@ InitFileHdr.Magic = XCOFF::XCOFF32; InitFileHdr.NumberOfSections = Obj.Sections.size(); InitFileHdr.NumberOfSymTableEntries = Obj.Symbols.size(); - + for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) { // Add the number of auxiliary symbols to the total number. InitFileHdr.NumberOfSymTableEntries += YamlSym.NumberOfAuxEntries; @@ -158,9 +160,13 @@ } bool XCOFFWriter::assignAddressesAndIndices() { - uint64_t CurrentOffset = - sizeof(XCOFF::FileHeader32) /* TODO: + auxiliaryHeaderSize() */ + - InitSections.size() * sizeof(XCOFF::SectionHeader32); + Strings.clear(); + uint64_t FileHdrSize = + Is64Bit ? XCOFF::FileHeaderSize64 : XCOFF::FileHeaderSize32; + uint64_t SecHdrSize = + Is64Bit ? XCOFF::SectionHeaderSize64 : XCOFF::SectionHeaderSize32; + uint64_t CurrentOffset = FileHdrSize /* TODO: + auxiliaryHeaderSize() */ + + InitSections.size() * SecHdrSize; // Calculate section header info. if (!initSectionHeader(CurrentOffset)) @@ -174,14 +180,25 @@ W.write(Obj.Header.NumberOfSections ? Obj.Header.NumberOfSections : InitFileHdr.NumberOfSections); W.write(Obj.Header.TimeStamp); - W.write(Obj.Header.SymbolTableOffset - ? Obj.Header.SymbolTableOffset - : InitFileHdr.SymbolTableOffset); - W.write(Obj.Header.NumberOfSymTableEntries - ? Obj.Header.NumberOfSymTableEntries - : InitFileHdr.NumberOfSymTableEntries); - W.write(Obj.Header.AuxHeaderSize); - W.write(Obj.Header.Flags); + if (Is64Bit) { + W.write(Obj.Header.SymbolTableOffset + ? Obj.Header.SymbolTableOffset + : InitFileHdr.SymbolTableOffset); + W.write(Obj.Header.AuxHeaderSize); + W.write(Obj.Header.Flags); + W.write(Obj.Header.NumberOfSymTableEntries + ? Obj.Header.NumberOfSymTableEntries + : InitFileHdr.NumberOfSymTableEntries); + } else { + W.write(Obj.Header.SymbolTableOffset + ? Obj.Header.SymbolTableOffset + : InitFileHdr.SymbolTableOffset); + W.write(Obj.Header.NumberOfSymTableEntries + ? Obj.Header.NumberOfSymTableEntries + : InitFileHdr.NumberOfSymTableEntries); + W.write(Obj.Header.AuxHeaderSize); + W.write(Obj.Header.Flags); + } } void XCOFFWriter::writeSectionHeader() { @@ -192,22 +209,40 @@ : "N_NULL", sizeof(XCOFF::NameSize)); // Virtual address is the same as physical address. - uint32_t SectionAddress = + uint64_t SectionAddress = YamlSec.Address ? YamlSec.Address : DerivedSec.Address; - W.write(SectionAddress); // Physical address - W.write(SectionAddress); // Virtual address - W.write(YamlSec.Size ? YamlSec.Size : DerivedSec.Size); - W.write(YamlSec.FileOffsetToData ? YamlSec.FileOffsetToData - : DerivedSec.FileOffsetToData); - W.write(YamlSec.FileOffsetToRelocations - ? YamlSec.FileOffsetToRelocations - : DerivedSec.FileOffsetToRelocations); - W.write(YamlSec.FileOffsetToLineNumbers); - W.write(YamlSec.NumberOfRelocations - ? YamlSec.NumberOfRelocations - : DerivedSec.NumberOfRelocations); - W.write(YamlSec.NumberOfLineNumbers); - W.write(YamlSec.Flags); + if (Is64Bit) { + W.write(SectionAddress); // Physical address + W.write(SectionAddress); // Virtual address + W.write(YamlSec.Size ? YamlSec.Size : DerivedSec.Size); + W.write(YamlSec.FileOffsetToData ? YamlSec.FileOffsetToData + : DerivedSec.FileOffsetToData); + W.write(YamlSec.FileOffsetToRelocations + ? YamlSec.FileOffsetToRelocations + : DerivedSec.FileOffsetToRelocations); + W.write(YamlSec.FileOffsetToLineNumbers); + W.write(YamlSec.NumberOfRelocations + ? YamlSec.NumberOfRelocations + : DerivedSec.NumberOfRelocations); + W.write(YamlSec.NumberOfLineNumbers); + W.write(YamlSec.Flags); + W.OS.write_zeros(4); + } else { + W.write(SectionAddress); // Physical address + W.write(SectionAddress); // Virtual address + W.write(YamlSec.Size ? YamlSec.Size : DerivedSec.Size); + W.write(YamlSec.FileOffsetToData ? YamlSec.FileOffsetToData + : DerivedSec.FileOffsetToData); + W.write(YamlSec.FileOffsetToRelocations + ? YamlSec.FileOffsetToRelocations + : DerivedSec.FileOffsetToRelocations); + W.write(YamlSec.FileOffsetToLineNumbers); + W.write(YamlSec.NumberOfRelocations + ? YamlSec.NumberOfRelocations + : DerivedSec.NumberOfRelocations); + W.write(YamlSec.NumberOfLineNumbers); + W.write(YamlSec.Flags); + } } } @@ -241,7 +276,10 @@ } W.OS.write_zeros(PaddingSize); for (const XCOFFYAML::Relocation &YamlRel : YamlSec.Relocations) { - W.write(YamlRel.VirtualAddress); + if (Is64Bit) + W.write(YamlRel.VirtualAddress); + else + W.write(YamlRel.VirtualAddress); W.write(YamlRel.SymbolIndex); W.write(YamlRel.Info); W.write(YamlRel.Type); @@ -263,12 +301,16 @@ if (nameShouldBeInStringTable(YamlSym.SymbolName)) { // For XCOFF32: A value of 0 indicates that the symbol name is in the // string table or .debug section. - W.write(0); + if (!Is64Bit) + W.write(0); W.write(Strings.getOffset(YamlSym.SymbolName)); } else { W.OS.write(YamlSym.SymbolName.data(), sizeof(XCOFF::NameSize)); } - W.write(YamlSym.Value); + if (Is64Bit) + W.write(YamlSym.Value); + else + W.write(YamlSym.Value); W.write(SectionIndexMap[YamlSym.SectionName]); W.write(YamlSym.Type); W.write(YamlSym.StorageClass); @@ -288,10 +330,6 @@ } bool XCOFFWriter::writeXCOFF() { - if (Is64Bit) { - ErrHandler("only XCOFF32 is currently supported"); - return false; - } if (!assignAddressesAndIndices()) return false; StartOffset = W.OS.tell(); diff --git a/llvm/test/tools/yaml2obj/XCOFF/basic-doc64.yaml b/llvm/test/tools/yaml2obj/XCOFF/basic-doc64.yaml --- a/llvm/test/tools/yaml2obj/XCOFF/basic-doc64.yaml +++ b/llvm/test/tools/yaml2obj/XCOFF/basic-doc64.yaml @@ -0,0 +1,117 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-readobj --headers %t | FileCheck %s --check-prefix=HEADERS64 +# RUN: llvm-readobj --symbols %t | FileCheck %s --check-prefix=SYMBOLS64 + +--- !XCOFF +FileHeader: + MagicNumber: 0x01F7 +Sections: + - Name: .text + Flags: 0x20 + SectionData: "9061FFF8808200008064000038630001906400008061FFF8386300019061FFF88061FFF88082000480840000888400007C6322149061FFF88061FFF84E8000200000000000092040800001010000000000000040000466756E310000600000007C0802A693E1FFFC900100089421FFB07C3F0B7838600000907F004880620008907F0044808300003884000190830000806300004BFFFF6D60000000807F0044806300004BFFFF5D60000000382100508001000883E1FFFC7C0803A64E8000200000000000092261800100010000006000046D61696E1F006162636400000000" + - Name: .data + Flags: 0x40 + SectionData: "00000000000000FC0000000000000060000000FC00000000000000D800000108000000F800000000" + Relocations: + - Address: 0x3A + Type: 0x02 + - Flags: 0x80 +Symbols: + - Name: .file + Section: N_DEBUG + - Name: .text + Value: 0x0 + Section: .text + Type: 0x0 + StorageClass: C_HIDEXT + - Name: i + Value: 0x0 + Section: .data + Type: 0x0 + StorageClass: C_EXT + + +# HEADERS64: Format: aix5coff64-rs6000 +# HEADERS64-NEXT: Arch: powerpc64 +# HEADERS64-NEXT: AddressSize: 64bit +# HEADERS64-NEXT: FileHeader { +# HEADERS64-NEXT: Magic: 0x1F7 +# HEADERS64-NEXT: NumberOfSections: 3 +# HEADERS64-NEXT: TimeStamp: None (0x0) +# HEADERS64-NEXT: SymbolTableOffset: 0x206 +# HEADERS64-NEXT: SymbolTableEntries: 3 +# HEADERS64-NEXT: OptionalHeaderSize: 0x0 +# HEADERS64-NEXT: Flags: 0x0 +# HEADERS64-NEXT: } + +# HEADERS64: Sections [ +# HEADERS64-NEXT: Section { +# HEADERS64-NEXT: Index: 1 +# HEADERS64-NEXT: Name: .text +# HEADERS64: PhysicalAddress: 0x0 +# HEADERS64-NEXT: VirtualAddress: 0x0 +# HEADERS64-NEXT: Size: 0xE0 +# HEADERS64-NEXT: RawDataOffset: 0xF0 +# HEADERS64-NEXT: RelocationPointer: 0x0 +# HEADERS64-NEXT: LineNumberPointer: 0x0 +# HEADERS64-NEXT: NumberOfRelocations: 0 +# HEADERS64-NEXT: NumberOfLineNumbers: 0 +# HEADERS64-NEXT: Type: STYP_TEXT (0x20) +# HEADERS64-NEXT: } +# HEADERS64-NEXT: Section { +# HEADERS64-NEXT: Index: 2 +# HEADERS64-NEXT: Name: .data +# HEADERS64: PhysicalAddress: 0xE0 +# HEADERS64-NEXT: VirtualAddress: 0xE0 +# HEADERS64-NEXT: Size: 0x28 +# HEADERS64-NEXT: RawDataOffset: 0x1D0 +# HEADERS64-NEXT: RelocationPointer: 0x1F8 +# HEADERS64-NEXT: LineNumberPointer: 0x0 +# HEADERS64-NEXT: NumberOfRelocations: 1 +# HEADERS64-NEXT: NumberOfLineNumbers: 0 +# HEADERS64-NEXT: Type: STYP_DATA (0x40) +# HEADERS64-NEXT: } +# HEADERS64-NEXT: Section { +# HEADERS64-NEXT: Index: 3 +# HEADERS64-NEXT: Name: N_NULL +# HEADERS64-NEXT: PhysicalAddress: 0x108 +# HEADERS64-NEXT: VirtualAddress: 0x108 +# HEADERS64-NEXT: Size: 0x0 +# HEADERS64-NEXT: RawDataOffset: 0x0 +# HEADERS64-NEXT: RelocationPointer: 0x0 +# HEADERS64-NEXT: LineNumberPointer: 0x0 +# HEADERS64-NEXT: NumberOfRelocations: 0 +# HEADERS64-NEXT: NumberOfLineNumbers: 0 +# HEADERS64-NEXT: Type: STYP_BSS (0x80) +# HEADERS64-NEXT: } +# HEADERS64-NEXT: ] + +# SYMBOLS64: Symbols [ +# SYMBOLS64-NEXT: Symbol { +# SYMBOLS64-NEXT: Index: 0 +# SYMBOLS64-NEXT: Name: +# SYMBOLS64-NEXT: Value: 0xC00000000 +# SYMBOLS64-NEXT: Section: N_DEBUG +# SYMBOLS64-NEXT: Type: 0x0 +# SYMBOLS64-NEXT: StorageClass: C_NULL (0x0) +# SYMBOLS64-NEXT: NumberOfAuxEntries: 0 +# SYMBOLS64-NEXT: } +# SYMBOLS64-NEXT: Symbol { +# SYMBOLS64-NEXT: Index: 1 +# SYMBOLS64-NEXT: Name: +# SYMBOLS64-NEXT: Value (RelocatableAddress): 0x400000000 +# SYMBOLS64-NEXT: Section: .text +# SYMBOLS64: Type: 0x0 +# SYMBOLS64-NEXT: StorageClass: C_HIDEXT (0x6B) +# SYMBOLS64-NEXT: NumberOfAuxEntries: 0 +# SYMBOLS64-NEXT: } +# SYMBOLS64-NEXT: Symbol { +# SYMBOLS64-NEXT: Index: 2 +# SYMBOLS64-NEXT: Name: +# SYMBOLS64-NEXT: Value (RelocatableAddress): 0xA00000000 +# SYMBOLS64-NEXT: Section: .data +# SYMBOLS64: Type: 0x0 +# SYMBOLS64-NEXT: StorageClass: C_EXT (0x2) +# SYMBOLS64-NEXT: NumberOfAuxEntries: 0 +# SYMBOLS64-NEXT: } +# SYMBOLS64-NEXT: ]