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 @@ -27,9 +27,12 @@ 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; 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 @@ -75,7 +75,8 @@ } bool XCOFFWriter::nameShouldBeInStringTable(StringRef SymbolName) { - return SymbolName.size() > XCOFF::NameSize; + // For XCOFF64: The symbol name is always in string table. + return (SymbolName.size() > XCOFF::NameSize) || Is64Bit; } bool XCOFFWriter::initRelocations(uint64_t &CurrentOffset) { @@ -83,8 +84,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"); @@ -170,9 +172,12 @@ bool XCOFFWriter::assignAddressesAndIndices() { Strings.clear(); - uint64_t CurrentOffset = - XCOFF::FileHeaderSize32 /* TODO: + auxiliaryHeaderSize() */ + - InitSections.size() * XCOFF::SectionHeaderSize32; + 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)) @@ -186,14 +191,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() { @@ -202,22 +218,40 @@ XCOFFYAML::Section DerivedSec = InitSections[I]; writeName(YamlSec.SectionName, W); // 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); + } } } @@ -253,7 +287,10 @@ if (PaddingSize > 0) 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); @@ -273,15 +310,20 @@ if (PaddingSize > 0) W.OS.write_zeros(PaddingSize); for (const XCOFFYAML::Symbol &YamlSym : Obj.Symbols) { - if (nameShouldBeInStringTable(YamlSym.SymbolName)) { - // For XCOFF32: A value of 0 indicates that the symbol name is in the - // string table. - W.write(0); + if (Is64Bit) { + W.write(YamlSym.Value); W.write(Strings.getOffset(YamlSym.SymbolName)); } else { - writeName(YamlSym.SymbolName, W); + if (nameShouldBeInStringTable(YamlSym.SymbolName)) { + // For XCOFF32: A value of 0 indicates that the symbol name is in the + // string table. + W.write(0); + W.write(Strings.getOffset(YamlSym.SymbolName)); + } else { + writeName(YamlSym.SymbolName, W); + } + W.write(YamlSym.Value); } - W.write(YamlSym.Value); W.write( YamlSym.SectionName.size() ? SectionIndexMap[YamlSym.SectionName] : 0); W.write(YamlSym.Type); @@ -302,10 +344,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,134 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-readobj --headers --symbols %t | FileCheck %s --check-prefix=CHECK64 + +--- !XCOFF +FileHeader: + MagicNumber: 0x01F7 +Sections: + - Name: .text + Flags: [ STYP_TEXT ] + - Name: .data + Flags: [ STYP_DATA ] + SectionData: "0000000000000FC0" + - Name: .data + Relocations: + - Type: 0x02 + - Name: .debug + Address: 0x0 + Size: 0x60 + Flags: [ STYP_DEBUG, STYP_DATA ] + SectionData: 01110103 +Symbols: + - Name: .file + Section: N_DEBUG + - Name: .undef + - Name: .abs + Section: N_ABS + - Name: .text + Value: 0x0 + Section: .text + Type: 0x0 + StorageClass: C_HIDEXT + +# CHECK64: AddressSize: 64bit +# CHECK64-NEXT: FileHeader { +# CHECK64-NEXT: Magic: 0x1F7 +# CHECK64-NEXT: NumberOfSections: 4 +# CHECK64-NEXT: TimeStamp: None (0x0) +# CHECK64-NEXT: SymbolTableOffset: 0x152 +# CHECK64-NEXT: SymbolTableEntries: 4 +# CHECK64-NEXT: OptionalHeaderSize: 0x0 +# CHECK64-NEXT: Flags: 0x0 +# CHECK64-NEXT: } +# CHECK64-NEXT: Sections [ +# CHECK64-NEXT: Section { +# CHECK64-NEXT: Index: 1 +# CHECK64-NEXT: Name: .text +# CHECK64-NEXT: PhysicalAddress: 0x0 +# CHECK64-NEXT: VirtualAddress: 0x0 +# CHECK64-NEXT: Size: 0x0 +# CHECK64-NEXT: RawDataOffset: 0x0 +# CHECK64-NEXT: RelocationPointer: 0x0 +# CHECK64-NEXT: LineNumberPointer: 0x0 +# CHECK64-NEXT: NumberOfRelocations: 0 +# CHECK64-NEXT: NumberOfLineNumbers: 0 +# CHECK64-NEXT: Type: STYP_TEXT (0x20) +# CHECK64-NEXT: } +# CHECK64-NEXT: Section { +# CHECK64-NEXT: Index: 2 +# CHECK64-NEXT: Name: .data +# CHECK64-NEXT: PhysicalAddress: 0x0 +# CHECK64-NEXT: VirtualAddress: 0x0 +# CHECK64-NEXT: Size: 0x8 +# CHECK64-NEXT: RawDataOffset: 0x138 +# CHECK64-NEXT: RelocationPointer: 0x0 +# CHECK64-NEXT: LineNumberPointer: 0x0 +# CHECK64-NEXT: NumberOfRelocations: 0 +# CHECK64-NEXT: NumberOfLineNumbers: 0 +# CHECK64-NEXT: Type: STYP_DATA (0x40) +# CHECK64-NEXT: } +# CHECK64-NEXT: Section { +# CHECK64-NEXT: Index: 3 +# CHECK64-NEXT: Name: .data +# CHECK64-NEXT: PhysicalAddress: 0x0 +# CHECK64-NEXT: VirtualAddress: 0x0 +# CHECK64-NEXT: Size: 0x0 +# CHECK64-NEXT: RawDataOffset: 0x0 +# CHECK64-NEXT: RelocationPointer: 0x144 +# CHECK64-NEXT: LineNumberPointer: 0x0 +# CHECK64-NEXT: NumberOfRelocations: 1 +# CHECK64-NEXT: NumberOfLineNumbers: 0 +# CHECK64-NEXT: Type: 0x0 +# CHECK64-NEXT: } +# CHECK64-NEXT: Section { +# CHECK64-NEXT: Index: 4 +# CHECK64-NEXT: Name: .debug +# CHECK64-NEXT: PhysicalAddress: 0x0 +# CHECK64-NEXT: VirtualAddress: 0x0 +# CHECK64-NEXT: Size: 0x60 +# CHECK64-NEXT: RawDataOffset: 0x140 +# CHECK64-NEXT: RelocationPointer: 0x0 +# CHECK64-NEXT: LineNumberPointer: 0x0 +# CHECK64-NEXT: NumberOfRelocations: 0 +# CHECK64-NEXT: NumberOfLineNumbers: 0 +# CHECK64-NEXT: Type: 0x2040 +# CHECK64-NEXT: } +# CHECK64-NEXT: ] +# CHECK64-NEXT: Symbols [ +# CHECK64-NEXT: Symbol { +# CHECK64-NEXT: Index: 0 +# CHECK64-NEXT: Name: .file +# CHECK64-NEXT: Value: 0x0 +# CHECK64-NEXT: Section: N_DEBUG +# CHECK64-NEXT: Type: 0x0 +# CHECK64-NEXT: StorageClass: C_NULL (0x0) +# CHECK64-NEXT: NumberOfAuxEntries: 0 +# CHECK64-NEXT: } +# CHECK64-NEXT: Symbol { +# CHECK64-NEXT: Index: 1 +# CHECK64-NEXT: Name: .undef +# CHECK64-NEXT: Value: 0x0 +# CHECK64-NEXT: Section: N_UNDEF +# CHECK64-NEXT: Type: 0x0 +# CHECK64-NEXT: StorageClass: C_NULL (0x0) +# CHECK64-NEXT: NumberOfAuxEntries: 0 +# CHECK64-NEXT: } +# CHECK64-NEXT: Symbol { +# CHECK64-NEXT: Index: 2 +# CHECK64-NEXT: Name: .abs +# CHECK64-NEXT: Value: 0x0 +# CHECK64-NEXT: Section: N_ABS +# CHECK64-NEXT: Type: 0x0 +# CHECK64-NEXT: StorageClass: C_NULL (0x0) +# CHECK64-NEXT: NumberOfAuxEntries: 0 +# CHECK64-NEXT: } +# CHECK64-NEXT: Symbol { +# CHECK64-NEXT: Index: 3 +# CHECK64-NEXT: Name: .text +# CHECK64-NEXT: Value (RelocatableAddress): 0x0 +# CHECK64-NEXT: Section: .text +# CHECK64-NEXT: Type: 0x0 +# CHECK64-NEXT: StorageClass: C_HIDEXT (0x6B) +# CHECK64-NEXT: NumberOfAuxEntries: 0 +# CHECK64-NEXT: } +# CHECK64-NEXT: ]