Skip to content

Commit

Permalink
[yaml2obj] Add support for structured COFF section data.
Browse files Browse the repository at this point in the history
Reviewed By: jhenderson
Differential Revision: https://reviews.llvm.org/D149439
  • Loading branch information
cjacek committed Jul 5, 2023
1 parent dd81c6b commit 2dad496
Show file tree
Hide file tree
Showing 8 changed files with 161 additions and 5 deletions.
5 changes: 5 additions & 0 deletions llvm/docs/yaml2obj.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
14 changes: 14 additions & 0 deletions llvm/include/llvm/ObjectYAML/COFFYAML.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,14 @@ struct Relocation {
std::optional<uint32_t> SymbolTableIndex;
};

struct SectionDataEntry {
std::optional<uint32_t> UInt32;
yaml::BinaryRef Binary;

size_t size() const;
void writeAsBinary(raw_ostream &OS) const;
};

struct Section {
COFF::section Header;
unsigned Alignment = 0;
Expand All @@ -74,6 +82,7 @@ struct Section {
std::vector<CodeViewYAML::LeafRecord> DebugT;
std::vector<CodeViewYAML::LeafRecord> DebugP;
std::optional<CodeViewYAML::DebugHSection> DebugH;
std::vector<SectionDataEntry> StructuredData;
std::vector<Relocation> Relocations;
StringRef Name;

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -241,6 +251,10 @@ struct MappingTraits<COFFYAML::Symbol> {
static void mapping(IO &IO, COFFYAML::Symbol &S);
};

template <> struct MappingTraits<COFFYAML::SectionDataEntry> {
static void mapping(IO &IO, COFFYAML::SectionDataEntry &Sec);
};

template <>
struct MappingTraits<COFFYAML::Section> {
static void mapping(IO &IO, COFFYAML::Section &Sec);
Expand Down
25 changes: 22 additions & 3 deletions llvm/lib/ObjectYAML/COFFEmitter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
Expand Down Expand Up @@ -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<uint32_t>(/*VirtualAddress=*/ S.Relocations.size() + 1)
<< binary_le<uint32_t>(/*SymbolTableIndex=*/ 0)
Expand Down Expand Up @@ -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 {

Expand Down
15 changes: 14 additions & 1 deletion llvm/lib/ObjectYAML/COFFYAML.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -547,6 +547,12 @@ void MappingTraits<COFF::AuxiliaryCLRToken>::mapping(
IO.mapRequired("SymbolTableIndex", ACT.SymbolTableIndex);
}

void MappingTraits<COFFYAML::SectionDataEntry>::mapping(
IO &IO, COFFYAML::SectionDataEntry &E) {
IO.mapOptional("UInt32", E.UInt32);
IO.mapOptional("Binary", E.Binary);
}

void MappingTraits<COFFYAML::Symbol>::mapping(IO &IO, COFFYAML::Symbol &S) {
MappingNormalization<NStorageClass, uint8_t> NS(IO, S.Header.StorageClass);

Expand Down Expand Up @@ -586,9 +592,16 @@ void MappingTraits<COFFYAML::Section>::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);

Expand Down
38 changes: 37 additions & 1 deletion llvm/test/tools/llvm-readobj/arm64ec-chpe.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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: []
...
22 changes: 22 additions & 0 deletions llvm/test/tools/yaml2obj/COFF/invalid-raw-data.yaml
Original file line number Diff line number Diff line change
@@ -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: []
...
22 changes: 22 additions & 0 deletions llvm/test/tools/yaml2obj/COFF/mixed-data.yaml
Original file line number Diff line number Diff line change
@@ -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: []
...
25 changes: 25 additions & 0 deletions llvm/test/tools/yaml2obj/COFF/structured-data.yaml
Original file line number Diff line number Diff line change
@@ -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: []
...

0 comments on commit 2dad496

Please sign in to comment.