diff --git a/llvm/include/llvm/BinaryFormat/COFF.h b/llvm/include/llvm/BinaryFormat/COFF.h --- a/llvm/include/llvm/BinaryFormat/COFF.h +++ b/llvm/include/llvm/BinaryFormat/COFF.h @@ -130,6 +130,10 @@ return Machine == IMAGE_FILE_MACHINE_ARM64 || isArm64EC(Machine); } +template bool is64Bit(T Machine) { + return Machine == IMAGE_FILE_MACHINE_AMD64 || isAnyArm64(Machine); +} + enum Characteristics : unsigned { C_Invalid = 0, diff --git a/llvm/include/llvm/ObjectYAML/COFFYAML.h b/llvm/include/llvm/ObjectYAML/COFFYAML.h --- a/llvm/include/llvm/ObjectYAML/COFFYAML.h +++ b/llvm/include/llvm/ObjectYAML/COFFYAML.h @@ -15,6 +15,7 @@ #include "llvm/ADT/StringRef.h" #include "llvm/BinaryFormat/COFF.h" +#include "llvm/Object/COFF.h" #include "llvm/ObjectYAML/CodeViewYAMLDebugSections.h" #include "llvm/ObjectYAML/CodeViewYAMLTypeHashing.h" #include "llvm/ObjectYAML/CodeViewYAMLTypes.h" @@ -69,6 +70,8 @@ struct SectionDataEntry { std::optional Int32; yaml::BinaryRef Binary; + std::optional LoadConfig32; + std::optional LoadConfig64; size_t size() const; void writeAsBinary(raw_ostream &OS) const; @@ -246,6 +249,18 @@ static void mapping(IO &IO, COFF::AuxiliaryCLRToken &ACT); }; +template <> struct MappingTraits { + static void mapping(IO &IO, object::coff_load_configuration32 &ACT); +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, object::coff_load_configuration64 &ACT); +}; + +template <> struct MappingTraits { + static void mapping(IO &IO, object::coff_load_config_code_integrity &ACT); +}; + template <> struct MappingTraits { static void mapping(IO &IO, COFFYAML::Symbol &S); diff --git a/llvm/lib/ObjectYAML/COFFEmitter.cpp b/llvm/lib/ObjectYAML/COFFEmitter.cpp --- a/llvm/lib/ObjectYAML/COFFEmitter.cpp +++ b/llvm/lib/ObjectYAML/COFFEmitter.cpp @@ -16,7 +16,6 @@ #include "llvm/ADT/StringMap.h" #include "llvm/DebugInfo/CodeView/DebugStringTableSubsection.h" #include "llvm/DebugInfo/CodeView/StringsAndChecksums.h" -#include "llvm/Object/COFF.h" #include "llvm/ObjectYAML/ObjectYAML.h" #include "llvm/ObjectYAML/yaml2obj.h" #include "llvm/Support/BinaryStreamWriter.h" @@ -48,10 +47,7 @@ } bool isPE() const { return Obj.OptionalHeader.has_value(); } - bool is64Bit() const { - return Obj.Header.Machine == COFF::IMAGE_FILE_MACHINE_AMD64 || - COFF::isAnyArm64(Obj.Header.Machine); - } + bool is64Bit() const { return COFF::is64Bit(Obj.Header.Machine); } uint32_t getFileAlignment() const { return Obj.OptionalHeader->Header.FileAlignment; @@ -598,13 +594,28 @@ size_t Size = Binary.binary_size(); if (Int32) Size += sizeof(int32_t); + if (LoadConfig32) + Size += LoadConfig32->Size; + if (LoadConfig64) + Size += LoadConfig64->Size; return Size; } +template static void writeLoadConfig(T &S, raw_ostream &OS) { + OS.write(reinterpret_cast(&S), + std::min(sizeof(S), size_t(S.Size))); + if (sizeof(S) < S.Size) + OS.write_zeros(S.Size - sizeof(S)); +} + void COFFYAML::SectionDataEntry::writeAsBinary(raw_ostream &OS) const { if (Int32) OS << binary_le(*Int32); Binary.writeAsBinary(OS); + if (LoadConfig32) + writeLoadConfig(*LoadConfig32, OS); + if (LoadConfig64) + writeLoadConfig(*LoadConfig64, OS); } namespace llvm { diff --git a/llvm/lib/ObjectYAML/COFFYAML.cpp b/llvm/lib/ObjectYAML/COFFYAML.cpp --- a/llvm/lib/ObjectYAML/COFFYAML.cpp +++ b/llvm/lib/ObjectYAML/COFFYAML.cpp @@ -547,10 +547,93 @@ IO.mapRequired("SymbolTableIndex", ACT.SymbolTableIndex); } +void MappingTraits::mapping( + IO &IO, object::coff_load_config_code_integrity &S) { + IO.mapOptional("Flags", S.Flags); + IO.mapOptional("Catalog", S.Catalog); + IO.mapOptional("CatalogOffset", S.CatalogOffset); +} + +template void mapLoadConfig(IO &IO, T &S) { + IO.mapOptional("Size", S.Size, support::ulittle32_t(sizeof(S))); + IO.mapOptional("TimeDateStamp", S.TimeDateStamp); + IO.mapOptional("MajorVersion", S.MajorVersion); + IO.mapOptional("MinorVersion", S.MinorVersion); + IO.mapOptional("GlobalFlagsClear", S.GlobalFlagsClear); + IO.mapOptional("GlobalFlagsSet", S.GlobalFlagsSet); + IO.mapOptional("CriticalSectionDefaultTimeout", + S.CriticalSectionDefaultTimeout); + IO.mapOptional("DeCommitFreeBlockThreshold", S.DeCommitFreeBlockThreshold); + IO.mapOptional("DeCommitTotalFreeThreshold", S.DeCommitTotalFreeThreshold); + IO.mapOptional("LockPrefixTable", S.LockPrefixTable); + IO.mapOptional("MaximumAllocationSize", S.MaximumAllocationSize); + IO.mapOptional("VirtualMemoryThreshold", S.VirtualMemoryThreshold); + IO.mapOptional("ProcessAffinityMask", S.ProcessAffinityMask); + IO.mapOptional("ProcessHeapFlags", S.ProcessHeapFlags); + IO.mapOptional("CSDVersion", S.CSDVersion); + IO.mapOptional("DependentLoadFlags", S.DependentLoadFlags); + IO.mapOptional("EditList", S.EditList); + IO.mapOptional("SecurityCookie", S.SecurityCookie); + IO.mapOptional("SEHandlerTable", S.SEHandlerTable); + IO.mapOptional("SEHandlerCount", S.SEHandlerCount); + IO.mapOptional("GuardCFCheckFunction", S.GuardCFCheckFunction); + IO.mapOptional("GuardCFCheckDispatch", S.GuardCFCheckDispatch); + IO.mapOptional("GuardCFFunctionTable", S.GuardCFFunctionTable); + IO.mapOptional("GuardCFFunctionCount", S.GuardCFFunctionCount); + IO.mapOptional("GuardFlags", S.GuardFlags); + IO.mapOptional("CodeIntegrity", S.CodeIntegrity); + IO.mapOptional("GuardAddressTakenIatEntryTable", + S.GuardAddressTakenIatEntryTable); + IO.mapOptional("GuardAddressTakenIatEntryCount", + S.GuardAddressTakenIatEntryCount); + IO.mapOptional("GuardLongJumpTargetTable", S.GuardLongJumpTargetTable); + IO.mapOptional("GuardLongJumpTargetCount", S.GuardLongJumpTargetCount); + IO.mapOptional("DynamicValueRelocTable", S.DynamicValueRelocTable); + IO.mapOptional("CHPEMetadataPointer", S.CHPEMetadataPointer); + IO.mapOptional("GuardRFFailureRoutine", S.GuardRFFailureRoutine); + IO.mapOptional("GuardRFFailureRoutineFunctionPointer", + S.GuardRFFailureRoutineFunctionPointer); + IO.mapOptional("DynamicValueRelocTableOffset", + S.DynamicValueRelocTableOffset); + IO.mapOptional("DynamicValueRelocTableSection", + S.DynamicValueRelocTableSection); + IO.mapOptional("GuardRFVerifyStackPointerFunctionPointer", + S.GuardRFVerifyStackPointerFunctionPointer); + IO.mapOptional("HotPatchTableOffset", S.HotPatchTableOffset); + IO.mapOptional("EnclaveConfigurationPointer", S.EnclaveConfigurationPointer); + IO.mapOptional("VolatileMetadataPointer", S.VolatileMetadataPointer); + IO.mapOptional("GuardEHContinuationTable", S.GuardEHContinuationTable); + IO.mapOptional("GuardEHContinuationCount", S.GuardEHContinuationCount); + IO.mapOptional("GuardXFGCheckFunctionPointer", + S.GuardXFGCheckFunctionPointer); + IO.mapOptional("GuardXFGDispatchFunctionPointer", + S.GuardXFGDispatchFunctionPointer); + IO.mapOptional("GuardXFGTableDispatchFunctionPointer", + S.GuardXFGTableDispatchFunctionPointer); + IO.mapOptional("CastGuardOsDeterminedFailureMode", + S.CastGuardOsDeterminedFailureMode); +} + +void MappingTraits::mapping( + IO &IO, object::coff_load_configuration32 &S) { + mapLoadConfig(IO, S); +} + +void MappingTraits::mapping( + IO &IO, object::coff_load_configuration64 &S) { + mapLoadConfig(IO, S); +} + void MappingTraits::mapping( IO &IO, COFFYAML::SectionDataEntry &E) { IO.mapOptional("Int32", E.Int32); IO.mapOptional("Binary", E.Binary); + + COFF::header &H = *static_cast(IO.getContext()); + if (COFF::is64Bit(H.Machine)) + IO.mapOptional("LoadConfig", E.LoadConfig64); + else + IO.mapOptional("LoadConfig", E.LoadConfig32); } void MappingTraits::mapping(IO &IO, COFFYAML::Symbol &S) { diff --git a/llvm/test/tools/yaml2obj/COFF/load-config32.yaml b/llvm/test/tools/yaml2obj/COFF/load-config32.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/yaml2obj/COFF/load-config32.yaml @@ -0,0 +1,31 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-readobj --coff-load-config %t | FileCheck %s + +# CHECK: LoadConfig [ +# CHECK: MaximumAllocationSize: 0x100000 +# CHECK: VirtualMemoryThreshold: 0x2000000 +# CHECK: CHPEMetadataPointer: 0 + +--- !COFF +OptionalHeader: + ImageBase: 0x180000000 + SectionAlignment: 4096 + FileAlignment: 512 + DLLCharacteristics: [ ] + LoadConfigTable: + RelativeVirtualAddress: 0x1000 + Size: 320 +header: + Machine: IMAGE_FILE_MACHINE_I386 + 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: 320 + Data: + - LoadConfig: + MaximumAllocationSize: 0x100000 + VirtualMemoryThreshold: 0x2000000 +symbols: [] +... diff --git a/llvm/test/tools/yaml2obj/COFF/load-config64.yaml b/llvm/test/tools/yaml2obj/COFF/load-config64.yaml new file mode 100644 --- /dev/null +++ b/llvm/test/tools/yaml2obj/COFF/load-config64.yaml @@ -0,0 +1,33 @@ +# RUN: yaml2obj %s -o %t +# RUN: llvm-readobj --coff-load-config %t | FileCheck %s + +# CHECK: LoadConfig [ +# CHECK: MaximumAllocationSize: 0x100000 +# CHECK: VirtualMemoryThreshold: 0x2000000 +# CHECK: CHPEMetadataPointer: 0 + +--- !COFF +OptionalHeader: + ImageBase: 0x180000000 + SectionAlignment: 4096 + FileAlignment: 512 + DLLCharacteristics: [ ] + LoadConfigTable: + RelativeVirtualAddress: 0x1000 + Size: 320 +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: 320 + Data: + - LoadConfig: + MaximumAllocationSize: 0x100000 + VirtualMemoryThreshold: 0x2000000 + CodeIntegrity: + Flags: 0x100 +symbols: [] +...