[llvm] 8011fc1 - [yaml2obj] Enable support for parsing 64-bit XCOFF.
via llvm-commits
llvm-commits at lists.llvm.org
Thu Jul 29 19:06:42 PDT 2021
Author: Esme-Yi
Date: 2021-07-30T02:06:04Z
New Revision: 8011fc1953831ff289da7e8854f684f5c8e6205c
URL: https://github.com/llvm/llvm-project/commit/8011fc1953831ff289da7e8854f684f5c8e6205c
DIFF: https://github.com/llvm/llvm-project/commit/8011fc1953831ff289da7e8854f684f5c8e6205c.diff
LOG: [yaml2obj] Enable support for parsing 64-bit XCOFF.
Summary: Add support for yaml2obj to parse 64-bit XCOFF.
Reviewed By: shchenz
Differential Revision: https://reviews.llvm.org/D100375
Added:
llvm/test/tools/yaml2obj/XCOFF/basic-doc64.yaml
Modified:
llvm/include/llvm/BinaryFormat/XCOFF.h
llvm/lib/ObjectYAML/XCOFFEmitter.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/BinaryFormat/XCOFF.h b/llvm/include/llvm/BinaryFormat/XCOFF.h
index 8a42d26f3f4a..6705cdd324fb 100644
--- a/llvm/include/llvm/BinaryFormat/XCOFF.h
+++ b/llvm/include/llvm/BinaryFormat/XCOFF.h
@@ -28,9 +28,12 @@ namespace XCOFF {
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
index 14fea5437a32..8b132ebf5e5d 100644
--- a/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
+++ b/llvm/lib/ObjectYAML/XCOFFEmitter.cpp
@@ -75,7 +75,8 @@ static void writeName(StringRef StrName, support::endian::Writer W) {
}
bool XCOFFWriter::nameShouldBeInStringTable(StringRef SymbolName) {
- return SymbolName.size() > XCOFF::NameSize;
+ // For XCOFF64: The symbol name is always in the string table.
+ return (SymbolName.size() > XCOFF::NameSize) || Is64Bit;
}
bool XCOFFWriter::initRelocations(uint64_t &CurrentOffset) {
@@ -83,8 +84,9 @@ bool XCOFFWriter::initRelocations(uint64_t &CurrentOffset) {
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::initFileHeader(uint64_t CurrentOffset) {
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 @@ void XCOFFWriter::writeFileHeader() {
W.write<uint16_t>(Obj.Header.NumberOfSections ? Obj.Header.NumberOfSections
: InitFileHdr.NumberOfSections);
W.write<int32_t>(Obj.Header.TimeStamp);
- W.write<uint32_t>(Obj.Header.SymbolTableOffset
- ? Obj.Header.SymbolTableOffset
- : InitFileHdr.SymbolTableOffset);
- W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
- ? Obj.Header.NumberOfSymTableEntries
- : InitFileHdr.NumberOfSymTableEntries);
- W.write<uint16_t>(Obj.Header.AuxHeaderSize);
- W.write<uint16_t>(Obj.Header.Flags);
+ if (Is64Bit) {
+ W.write<uint64_t>(Obj.Header.SymbolTableOffset
+ ? Obj.Header.SymbolTableOffset
+ : InitFileHdr.SymbolTableOffset);
+ W.write<uint16_t>(Obj.Header.AuxHeaderSize);
+ W.write<uint16_t>(Obj.Header.Flags);
+ W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
+ ? Obj.Header.NumberOfSymTableEntries
+ : InitFileHdr.NumberOfSymTableEntries);
+ } else {
+ W.write<uint32_t>(Obj.Header.SymbolTableOffset
+ ? Obj.Header.SymbolTableOffset
+ : InitFileHdr.SymbolTableOffset);
+ W.write<int32_t>(Obj.Header.NumberOfSymTableEntries
+ ? Obj.Header.NumberOfSymTableEntries
+ : InitFileHdr.NumberOfSymTableEntries);
+ W.write<uint16_t>(Obj.Header.AuxHeaderSize);
+ W.write<uint16_t>(Obj.Header.Flags);
+ }
}
void XCOFFWriter::writeSectionHeader() {
@@ -202,22 +218,40 @@ void XCOFFWriter::writeSectionHeader() {
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<uint32_t>(SectionAddress); // Physical address
- W.write<uint32_t>(SectionAddress); // Virtual address
- W.write<uint32_t>(YamlSec.Size ? YamlSec.Size : DerivedSec.Size);
- W.write<uint32_t>(YamlSec.FileOffsetToData ? YamlSec.FileOffsetToData
- : DerivedSec.FileOffsetToData);
- W.write<uint32_t>(YamlSec.FileOffsetToRelocations
- ? YamlSec.FileOffsetToRelocations
- : DerivedSec.FileOffsetToRelocations);
- W.write<uint32_t>(YamlSec.FileOffsetToLineNumbers);
- W.write<uint16_t>(YamlSec.NumberOfRelocations
- ? YamlSec.NumberOfRelocations
- : DerivedSec.NumberOfRelocations);
- W.write<uint16_t>(YamlSec.NumberOfLineNumbers);
- W.write<int32_t>(YamlSec.Flags);
+ if (Is64Bit) {
+ W.write<uint64_t>(SectionAddress); // Physical address
+ W.write<uint64_t>(SectionAddress); // Virtual address
+ W.write<uint64_t>(YamlSec.Size ? YamlSec.Size : DerivedSec.Size);
+ W.write<uint64_t>(YamlSec.FileOffsetToData ? YamlSec.FileOffsetToData
+ : DerivedSec.FileOffsetToData);
+ W.write<uint64_t>(YamlSec.FileOffsetToRelocations
+ ? YamlSec.FileOffsetToRelocations
+ : DerivedSec.FileOffsetToRelocations);
+ W.write<uint64_t>(YamlSec.FileOffsetToLineNumbers);
+ W.write<uint32_t>(YamlSec.NumberOfRelocations
+ ? YamlSec.NumberOfRelocations
+ : DerivedSec.NumberOfRelocations);
+ W.write<uint32_t>(YamlSec.NumberOfLineNumbers);
+ W.write<int32_t>(YamlSec.Flags);
+ W.OS.write_zeros(4);
+ } else {
+ W.write<uint32_t>(SectionAddress); // Physical address
+ W.write<uint32_t>(SectionAddress); // Virtual address
+ W.write<uint32_t>(YamlSec.Size ? YamlSec.Size : DerivedSec.Size);
+ W.write<uint32_t>(YamlSec.FileOffsetToData ? YamlSec.FileOffsetToData
+ : DerivedSec.FileOffsetToData);
+ W.write<uint32_t>(YamlSec.FileOffsetToRelocations
+ ? YamlSec.FileOffsetToRelocations
+ : DerivedSec.FileOffsetToRelocations);
+ W.write<uint32_t>(YamlSec.FileOffsetToLineNumbers);
+ W.write<uint16_t>(YamlSec.NumberOfRelocations
+ ? YamlSec.NumberOfRelocations
+ : DerivedSec.NumberOfRelocations);
+ W.write<uint16_t>(YamlSec.NumberOfLineNumbers);
+ W.write<int32_t>(YamlSec.Flags);
+ }
}
}
@@ -232,8 +266,7 @@ bool XCOFFWriter::writeSectionData() {
ErrHandler("redundant data was written before section data");
return false;
}
- if (PaddingSize > 0)
- W.OS.write_zeros(PaddingSize);
+ W.OS.write_zeros(PaddingSize);
YamlSec.SectionData.writeAsBinary(W.OS);
}
}
@@ -250,10 +283,12 @@ bool XCOFFWriter::writeRelocations() {
ErrHandler("redundant data was written before relocations");
return false;
}
- if (PaddingSize > 0)
- W.OS.write_zeros(PaddingSize);
+ W.OS.write_zeros(PaddingSize);
for (const XCOFFYAML::Relocation &YamlRel : YamlSec.Relocations) {
- W.write<uint32_t>(YamlRel.VirtualAddress);
+ if (Is64Bit)
+ W.write<uint64_t>(YamlRel.VirtualAddress);
+ else
+ W.write<uint32_t>(YamlRel.VirtualAddress);
W.write<uint32_t>(YamlRel.SymbolIndex);
W.write<uint8_t>(YamlRel.Info);
W.write<uint8_t>(YamlRel.Type);
@@ -270,18 +305,22 @@ bool XCOFFWriter::writeSymbols() {
ErrHandler("redundant data was written before symbols");
return false;
}
- if (PaddingSize > 0)
- W.OS.write_zeros(PaddingSize);
+ 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<int32_t>(0);
+ if (Is64Bit) {
+ W.write<uint64_t>(YamlSym.Value);
W.write<uint32_t>(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<int32_t>(0);
+ W.write<uint32_t>(Strings.getOffset(YamlSym.SymbolName));
+ } else {
+ writeName(YamlSym.SymbolName, W);
+ }
+ W.write<uint32_t>(YamlSym.Value);
}
- W.write<uint32_t>(YamlSym.Value);
W.write<int16_t>(
YamlSym.SectionName.size() ? SectionIndexMap[YamlSym.SectionName] : 0);
W.write<uint16_t>(YamlSym.Type);
@@ -295,17 +334,13 @@ bool XCOFFWriter::writeSymbols() {
// length of each auxiliary entry is the same as a symbol table entry (18
// bytes). The format and quantity of auxiliary entries depend on the
// storage class (n_sclass) and type (n_type) of the symbol table entry.
- W.OS.write_zeros(18);
+ W.OS.write_zeros(XCOFF::SymbolTableEntrySize);
}
}
return true;
}
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
new file mode 100644
index 000000000000..49334680ea0d
--- /dev/null
+++ b/llvm/test/tools/yaml2obj/XCOFF/basic-doc64.yaml
@@ -0,0 +1,136 @@
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-readobj --headers --symbols %t | \
+# RUN: FileCheck %s --check-prefix=CHECK64
+
+--- !XCOFF
+FileHeader:
+ MagicNumber: 0x01F7
+Sections:
+ - Name: .text
+ Flags: [ STYP_TEXT ]
+ - Name: .data
+ Flags: [ STYP_DATA ]
+ SectionData: "0000000000000FC0"
+ - Name: .bss
+ Flags: [ STYP_BSS ]
+ 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: .bss
+# CHECK64-NEXT: PhysicalAddress: 0x8
+# CHECK64-NEXT: VirtualAddress: 0x8
+# 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: STYP_BSS (0x80)
+# 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: ]
More information about the llvm-commits
mailing list