From 2dad496be35332f2c076a06b13d2dab3a37026cf Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Fri, 28 Apr 2023 14:28:00 +0200 Subject: [PATCH] [yaml2obj] Add support for structured COFF section data. Reviewed By: jhenderson Differential Revision: https://reviews.llvm.org/D149439 --- llvm/docs/yaml2obj.rst | 5 +++ llvm/include/llvm/ObjectYAML/COFFYAML.h | 14 ++++++++ llvm/lib/ObjectYAML/COFFEmitter.cpp | 25 ++++++++++++-- llvm/lib/ObjectYAML/COFFYAML.cpp | 15 ++++++++- llvm/test/tools/llvm-readobj/arm64ec-chpe.yaml | 38 +++++++++++++++++++++- .../test/tools/yaml2obj/COFF/invalid-raw-data.yaml | 22 +++++++++++++ llvm/test/tools/yaml2obj/COFF/mixed-data.yaml | 22 +++++++++++++ llvm/test/tools/yaml2obj/COFF/structured-data.yaml | 25 ++++++++++++++ 8 files changed, 161 insertions(+), 5 deletions(-) create mode 100644 llvm/test/tools/yaml2obj/COFF/invalid-raw-data.yaml create mode 100644 llvm/test/tools/yaml2obj/COFF/mixed-data.yaml create mode 100644 llvm/test/tools/yaml2obj/COFF/structured-data.yaml diff --git a/llvm/docs/yaml2obj.rst b/llvm/docs/yaml2obj.rst index d18ce02..a0bca06 100644 --- a/llvm/docs/yaml2obj.rst +++ b/llvm/docs/yaml2obj.rst @@ -29,6 +29,11 @@ Here's a sample COFF file. ] # 0x60500020 SectionData: "\x83\xEC\x0C\xC7\x44\x24\x08\x00\x00\x00\x00\xC7\x04\x24\x00\x00\x00\x00\xE8\x00\x00\x00\x00\xE8\x00\x00\x00\x00\x8B\x44\x24\x08\x83\xC4\x0C\xC3" # |....D$.......$...............D$.....| + - Name: .rdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + StructuredData: + - Binary: {type: str} + - UInt32: {type: int} symbols: - Name: .text diff --git a/llvm/include/llvm/ObjectYAML/COFFYAML.h b/llvm/include/llvm/ObjectYAML/COFFYAML.h index fbd8298..1d941ae 100644 --- a/llvm/include/llvm/ObjectYAML/COFFYAML.h +++ b/llvm/include/llvm/ObjectYAML/COFFYAML.h @@ -66,6 +66,14 @@ struct Relocation { std::optional SymbolTableIndex; }; +struct SectionDataEntry { + std::optional UInt32; + yaml::BinaryRef Binary; + + size_t size() const; + void writeAsBinary(raw_ostream &OS) const; +}; + struct Section { COFF::section Header; unsigned Alignment = 0; @@ -74,6 +82,7 @@ struct Section { std::vector DebugT; std::vector DebugP; std::optional DebugH; + std::vector StructuredData; std::vector Relocations; StringRef Name; @@ -117,6 +126,7 @@ struct Object { LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Section) LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Symbol) LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::Relocation) +LLVM_YAML_IS_SEQUENCE_VECTOR(COFFYAML::SectionDataEntry) namespace llvm { namespace yaml { @@ -241,6 +251,10 @@ struct MappingTraits { static void mapping(IO &IO, COFFYAML::Symbol &S); }; +template <> struct MappingTraits { + static void mapping(IO &IO, COFFYAML::SectionDataEntry &Sec); +}; + template <> struct MappingTraits { static void mapping(IO &IO, COFFYAML::Section &Sec); diff --git a/llvm/lib/ObjectYAML/COFFEmitter.cpp b/llvm/lib/ObjectYAML/COFFEmitter.cpp index f8a285d..b4ce90d 100644 --- a/llvm/lib/ObjectYAML/COFFEmitter.cpp +++ b/llvm/lib/ObjectYAML/COFFEmitter.cpp @@ -242,10 +242,13 @@ static bool layoutCOFF(COFFParser &CP) { S.SectionData = CodeViewYAML::toDebugH(*S.DebugH, CP.Allocator); } - if (S.SectionData.binary_size() > 0) { + size_t DataSize = S.SectionData.binary_size(); + for (auto E : S.StructuredData) + DataSize += E.size(); + if (DataSize > 0) { CurrentSectionDataOffset = alignTo(CurrentSectionDataOffset, CP.isPE() ? CP.getFileAlignment() : 4); - S.Header.SizeOfRawData = S.SectionData.binary_size(); + S.Header.SizeOfRawData = DataSize; if (CP.isPE()) S.Header.SizeOfRawData = alignTo(S.Header.SizeOfRawData, CP.getFileAlignment()); @@ -496,9 +499,12 @@ static bool writeCOFF(COFFParser &CP, raw_ostream &OS) { continue; assert(S.Header.PointerToRawData >= OS.tell()); OS.write_zeros(S.Header.PointerToRawData - OS.tell()); + for (auto E : S.StructuredData) + E.writeAsBinary(OS); S.SectionData.writeAsBinary(OS); assert(S.Header.SizeOfRawData >= S.SectionData.binary_size()); - OS.write_zeros(S.Header.SizeOfRawData - S.SectionData.binary_size()); + OS.write_zeros(S.Header.PointerToRawData + S.Header.SizeOfRawData - + OS.tell()); if (S.Header.Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) OS << binary_le(/*VirtualAddress=*/ S.Relocations.size() + 1) << binary_le(/*SymbolTableIndex=*/ 0) @@ -588,6 +594,19 @@ static bool writeCOFF(COFFParser &CP, raw_ostream &OS) { return true; } +size_t COFFYAML::SectionDataEntry::size() const { + size_t Size = Binary.binary_size(); + if (UInt32) + Size += sizeof(*UInt32); + return Size; +} + +void COFFYAML::SectionDataEntry::writeAsBinary(raw_ostream &OS) const { + if (UInt32) + OS << binary_le(*UInt32); + Binary.writeAsBinary(OS); +} + namespace llvm { namespace yaml { diff --git a/llvm/lib/ObjectYAML/COFFYAML.cpp b/llvm/lib/ObjectYAML/COFFYAML.cpp index fe9a9f8..5ef634c 100644 --- a/llvm/lib/ObjectYAML/COFFYAML.cpp +++ b/llvm/lib/ObjectYAML/COFFYAML.cpp @@ -547,6 +547,12 @@ void MappingTraits::mapping( IO.mapRequired("SymbolTableIndex", ACT.SymbolTableIndex); } +void MappingTraits::mapping( + IO &IO, COFFYAML::SectionDataEntry &E) { + IO.mapOptional("UInt32", E.UInt32); + IO.mapOptional("Binary", E.Binary); +} + void MappingTraits::mapping(IO &IO, COFFYAML::Symbol &S) { MappingNormalization NS(IO, S.Header.StorageClass); @@ -586,9 +592,16 @@ void MappingTraits::mapping(IO &IO, COFFYAML::Section &Sec) { else if (Sec.Name == ".debug$H") IO.mapOptional("GlobalHashes", Sec.DebugH); + IO.mapOptional("StructuredData", Sec.StructuredData); + + if (!Sec.StructuredData.empty() && Sec.SectionData.binary_size()) { + IO.setError("StructuredData and SectionData can't be used together"); + return; + } + // Uninitialized sections, such as .bss, typically have no data, but the size // is carried in SizeOfRawData, even though PointerToRawData is zero. - if (Sec.SectionData.binary_size() == 0 && + if (Sec.SectionData.binary_size() == 0 && Sec.StructuredData.empty() && NC->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA) IO.mapOptional("SizeOfRawData", Sec.Header.SizeOfRawData); diff --git a/llvm/test/tools/llvm-readobj/arm64ec-chpe.yaml b/llvm/test/tools/llvm-readobj/arm64ec-chpe.yaml index 629fe02..e3758da 100644 --- a/llvm/test/tools/llvm-readobj/arm64ec-chpe.yaml +++ b/llvm/test/tools/llvm-readobj/arm64ec-chpe.yaml @@ -44,6 +44,42 @@ sections: Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] VirtualAddress: 0x5000 VirtualSize: 144 - SectionData: '010000005050000003000000685000008050000000000000000000000000000000000000000000000000000000000000020000000200000000000000000000000000000000000000000000000000000001100000300000000020000040000000023000005000000000100000201000000010000020100000401000000020000000100000002000002010000030200000' + StructuredData: + - UInt32: 1 # Version + - UInt32: 0x5050 # CodeMap + - UInt32: 3 # CodeMapCount + - UInt32: 0x5068 # CodeRangesToEntryPoints + - UInt32: 0x5080 # RedirectionMetadata + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 2 # CodeRangesToEntryPointsCount + - UInt32: 2 # RedirectionMetadataCount + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0 + - UInt32: 0x1001 # CodeMap[0] + - UInt32: 0x30 + - UInt32: 0x2000 # CodeMap[1] + - UInt32: 0x40 + - UInt32: 0x3002 # CodeMap[2] + - UInt32: 0x50 + - UInt32: 0x1000 # CodeRangesToEntryPoints[0] + - UInt32: 0x1020 + - UInt32: 0x1000 + - UInt32: 0x1020 # CodeRangesToEntryPoints[1] + - UInt32: 0x1040 + - UInt32: 0x2000 + - UInt32: 0x1000 # RedirectionMetadata[0] + - UInt32: 0x2000 + - UInt32: 0x1020 # RedirectionMetadata[1] + - UInt32: 0x2030 symbols: [] ... diff --git a/llvm/test/tools/yaml2obj/COFF/invalid-raw-data.yaml b/llvm/test/tools/yaml2obj/COFF/invalid-raw-data.yaml new file mode 100644 index 0000000..62445fa --- /dev/null +++ b/llvm/test/tools/yaml2obj/COFF/invalid-raw-data.yaml @@ -0,0 +1,22 @@ +# RUN: not yaml2obj %s -o %t 2>&1 | FileCheck %s +# CHECK: YAML:18:5: error: unknown key 'SizeOfRawData' + +--- !COFF +OptionalHeader: + ImageBase: 0x180000000 + SectionAlignment: 4096 + FileAlignment: 512 + DLLCharacteristics: [ ] +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE, IMAGE_FILE_DLL ] +sections: + - Name: .rdata + Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + VirtualAddress: 0x1000 + VirtualSize: 20 + SizeOfRawData: 4 + StructuredData: + - UInt32: 1 +symbols: [] +... diff --git a/llvm/test/tools/yaml2obj/COFF/mixed-data.yaml b/llvm/test/tools/yaml2obj/COFF/mixed-data.yaml new file mode 100644 index 0000000..7f23f4d --- /dev/null +++ b/llvm/test/tools/yaml2obj/COFF/mixed-data.yaml @@ -0,0 +1,22 @@ +# RUN: not yaml2obj %s -o %t 2>&1 | FileCheck %s +# CHECK: error: StructuredData and SectionData can't be used together + +--- !COFF +OptionalHeader: + ImageBase: 0x180000000 + SectionAlignment: 4096 + FileAlignment: 512 + DLLCharacteristics: [ ] +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE, IMAGE_FILE_DLL ] +sections: + - Name: .rdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + VirtualAddress: 0x1000 + VirtualSize: 20 + SectionData: 55 + StructuredData: + - UInt32: 1 +symbols: [] +... diff --git a/llvm/test/tools/yaml2obj/COFF/structured-data.yaml b/llvm/test/tools/yaml2obj/COFF/structured-data.yaml new file mode 100644 index 0000000..687c43d --- /dev/null +++ b/llvm/test/tools/yaml2obj/COFF/structured-data.yaml @@ -0,0 +1,25 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-readobj --hex-dump=.rdata %t | FileCheck %s +# CHECK: 0x180001000 01000000 02000000 11223344 ffffffff + +--- !COFF +OptionalHeader: + ImageBase: 0x180000000 + SectionAlignment: 4096 + FileAlignment: 512 + DLLCharacteristics: [ ] +header: + Machine: IMAGE_FILE_MACHINE_AMD64 + Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE, IMAGE_FILE_DLL ] +sections: + - Name: .rdata + Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] + VirtualAddress: 0x1000 + VirtualSize: 20 + StructuredData: + - UInt32: 1 + - UInt32: 2 + - Binary: 11223344 + - UInt32: 0xffffffff +symbols: [] +... -- 2.7.4