[llvm] 05d8d64 - [llvm-readobj] Add support for dumping CHPE metadata.
Jacek Caban via llvm-commits
llvm-commits at lists.llvm.org
Fri Jun 30 05:58:36 PDT 2023
Author: Jacek Caban
Date: 2023-06-30T14:57:10+02:00
New Revision: 05d8d6405ef10a81c3d2bc9da53665221a8a9f1b
URL: https://github.com/llvm/llvm-project/commit/05d8d6405ef10a81c3d2bc9da53665221a8a9f1b
DIFF: https://github.com/llvm/llvm-project/commit/05d8d6405ef10a81c3d2bc9da53665221a8a9f1b.diff
LOG: [llvm-readobj] Add support for dumping CHPE metadata.
CHPE metadata is used by ARM64EC/ARM64X PE files to provide metadata for
emulator/loader. Most of this metadata will need to be generated by LLD.
Differential Revision: https://reviews.llvm.org/D149089
Added:
llvm/test/tools/llvm-readobj/arm64ec-chpe.yaml
Modified:
llvm/include/llvm/Object/COFF.h
llvm/lib/Object/COFFObjectFile.cpp
llvm/tools/llvm-readobj/COFFDumper.cpp
Removed:
################################################################################
diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h
index fa90c58f1836ab..e6a607921da0ef 100644
--- a/llvm/include/llvm/Object/COFF.h
+++ b/llvm/include/llvm/Object/COFF.h
@@ -722,6 +722,47 @@ struct coff_load_configuration64 {
support::ulittle64_t CastGuardOsDeterminedFailureMode;
};
+struct chpe_metadata {
+ support::ulittle32_t Version;
+ support::ulittle32_t CodeMap;
+ support::ulittle32_t CodeMapCount;
+ support::ulittle32_t CodeRangesToEntryPoints;
+ support::ulittle32_t RedirectionMetadata;
+ support::ulittle32_t __os_arm64x_dispatch_call_no_redirect;
+ support::ulittle32_t __os_arm64x_dispatch_ret;
+ support::ulittle32_t __os_arm64x_dispatch_call;
+ support::ulittle32_t __os_arm64x_dispatch_icall;
+ support::ulittle32_t __os_arm64x_dispatch_icall_cfg;
+ support::ulittle32_t AlternateEntryPoint;
+ support::ulittle32_t AuxiliaryIAT;
+ support::ulittle32_t CodeRangesToEntryPointsCount;
+ support::ulittle32_t RedirectionMetadataCount;
+ support::ulittle32_t GetX64InformationFunctionPointer;
+ support::ulittle32_t SetX64InformationFunctionPointer;
+ support::ulittle32_t ExtraRFETable;
+ support::ulittle32_t ExtraRFETableSize;
+ support::ulittle32_t __os_arm64x_dispatch_fptr;
+ support::ulittle32_t AuxiliaryIATCopy;
+};
+
+struct chpe_range_entry {
+ support::ulittle32_t StartOffset;
+ support::ulittle32_t Length;
+};
+
+enum chpe_range_type { CHPE_RANGE_ARM64, CHPE_RANGE_ARM64EC, CHPE_RANGE_AMD64 };
+
+struct chpe_code_range_entry {
+ support::ulittle32_t StartRva;
+ support::ulittle32_t EndRva;
+ support::ulittle32_t EntryPoint;
+};
+
+struct chpe_redirection_entry {
+ support::ulittle32_t Source;
+ support::ulittle32_t Destination;
+};
+
struct coff_runtime_function_x64 {
support::ulittle32_t BeginAddress;
support::ulittle32_t EndAddress;
@@ -813,6 +854,7 @@ class COFFObjectFile : public ObjectFile {
const coff_tls_directory64 *TLSDirectory64;
// Either coff_load_configuration32 or coff_load_configuration64.
const void *LoadConfig = nullptr;
+ const chpe_metadata *CHPEMetadata = nullptr;
Expected<StringRef> getString(uint32_t offset) const;
@@ -927,6 +969,9 @@ class COFFObjectFile : public ObjectFile {
assert(is64());
return reinterpret_cast<const coff_load_configuration64 *>(LoadConfig);
}
+
+ const chpe_metadata *getCHPEMetadata() const { return CHPEMetadata; }
+
StringRef getRelocationTypeName(uint16_t Type) const;
protected:
diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp
index 1b7ab45ea8aacc..08eb0d034c53a3 100644
--- a/llvm/lib/Object/COFFObjectFile.cpp
+++ b/llvm/lib/Object/COFFObjectFile.cpp
@@ -753,6 +753,54 @@ Error COFFObjectFile::initLoadConfigPtr() {
return E;
LoadConfig = (const void *)IntPtr;
+
+ if (is64()) {
+ auto Config = getLoadConfig64();
+ if (Config->Size >=
+ offsetof(coff_load_configuration64, CHPEMetadataPointer) +
+ sizeof(Config->CHPEMetadataPointer) &&
+ Config->CHPEMetadataPointer) {
+ uint64_t ChpeOff = Config->CHPEMetadataPointer;
+ if (Error E =
+ getRvaPtr(ChpeOff - getImageBase(), IntPtr, "CHPE metadata"))
+ return E;
+ if (Error E = checkOffset(Data, IntPtr, sizeof(CHPEMetadata)))
+ return E;
+
+ CHPEMetadata = reinterpret_cast<const chpe_metadata *>(IntPtr);
+
+ // Validate CHPE metadata
+ if (CHPEMetadata->CodeMapCount) {
+ if (Error E = getRvaPtr(CHPEMetadata->CodeMap, IntPtr, "CHPE code map"))
+ return E;
+ if (Error E = checkOffset(Data, IntPtr,
+ CHPEMetadata->CodeMapCount *
+ sizeof(chpe_range_entry)))
+ return E;
+ }
+
+ if (CHPEMetadata->CodeRangesToEntryPointsCount) {
+ if (Error E = getRvaPtr(CHPEMetadata->CodeRangesToEntryPoints, IntPtr,
+ "CHPE entry point ranges"))
+ return E;
+ if (Error E = checkOffset(Data, IntPtr,
+ CHPEMetadata->CodeRangesToEntryPointsCount *
+ sizeof(chpe_code_range_entry)))
+ return E;
+ }
+
+ if (CHPEMetadata->RedirectionMetadataCount) {
+ if (Error E = getRvaPtr(CHPEMetadata->RedirectionMetadata, IntPtr,
+ "CHPE redirection metadata"))
+ return E;
+ if (Error E = checkOffset(Data, IntPtr,
+ CHPEMetadata->RedirectionMetadataCount *
+ sizeof(chpe_redirection_entry)))
+ return E;
+ }
+ }
+ }
+
return Error::success();
}
diff --git a/llvm/test/tools/llvm-readobj/arm64ec-chpe.yaml b/llvm/test/tools/llvm-readobj/arm64ec-chpe.yaml
new file mode 100644
index 00000000000000..629fe027b64e33
--- /dev/null
+++ b/llvm/test/tools/llvm-readobj/arm64ec-chpe.yaml
@@ -0,0 +1,49 @@
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-readobj --coff-load-config %t | FileCheck %s
+
+# CHECK: CHPEMetadataPointer: 0x180005000
+# CHECK: CHPEMetadata [
+# CHECK-NEXT: Version: 0x1
+# CHECK-NEXT: CodeMap [
+# CHECK-NEXT: 0x1000 - 0x1030 ARM64EC
+# CHECK-NEXT: 0x2000 - 0x2040 ARM64
+# CHECK-NEXT: 0x3000 - 0x3050 X64
+# CHECK-NEXT: ]
+# CHECK-NEXT: CodeRangesToEntryPoints [
+# CHECK-NEXT: 0x1000 - 0x1020 -> 0x1000
+# CHECK-NEXT: 0x1020 - 0x1040 -> 0x2000
+# CHECK-NEXT: ]
+# CHECK-NEXT: RedirectionMetadata [
+# CHECK-NEXT: 0x1000 -> 0x2000
+# CHECK-NEXT: 0x1020 -> 0x2030
+# CHECK-NEXT: ]
+
+--- !COFF
+OptionalHeader:
+ ImageBase: 0x180000000
+ SectionAlignment: 4096
+ FileAlignment: 512
+ DLLCharacteristics: [ ]
+ LoadConfigTable:
+ RelativeVirtualAddress: 0x4000
+ Size: 320
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE, IMAGE_FILE_DLL ]
+sections:
+ - Name: .text
+ Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 0x1000
+ VirtualSize: 0x2050
+ - Name: .rdata
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 0x4000
+ VirtualSize: 328
+ SectionData: '40010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000050008001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000'
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ VirtualAddress: 0x5000
+ VirtualSize: 144
+ SectionData: '010000005050000003000000685000008050000000000000000000000000000000000000000000000000000000000000020000000200000000000000000000000000000000000000000000000000000001100000300000000020000040000000023000005000000000100000201000000010000020100000401000000020000000100000002000002010000030200000'
+symbols: []
+...
diff --git a/llvm/tools/llvm-readobj/COFFDumper.cpp b/llvm/tools/llvm-readobj/COFFDumper.cpp
index c6d1f2cf9c63d0..0a5073d2d23fa0 100644
--- a/llvm/tools/llvm-readobj/COFFDumper.cpp
+++ b/llvm/tools/llvm-readobj/COFFDumper.cpp
@@ -842,6 +842,93 @@ void COFFDumper::printCOFFLoadConfig() {
else
printCOFFLoadConfig(Obj->getLoadConfig32(), Tables);
+ if (auto CHPE = Obj->getCHPEMetadata()) {
+ ListScope LS(W, "CHPEMetadata");
+ W.printHex("Version", CHPE->Version);
+
+ if (CHPE->CodeMapCount) {
+ ListScope CMLS(W, "CodeMap");
+
+ uintptr_t CodeMapInt;
+ if (Error E = Obj->getRvaPtr(CHPE->CodeMap, CodeMapInt))
+ reportError(std::move(E), Obj->getFileName());
+ auto CodeMap = reinterpret_cast<const chpe_range_entry *>(CodeMapInt);
+ for (uint32_t i = 0; i < CHPE->CodeMapCount; i++) {
+ uint32_t Start = CodeMap[i].StartOffset & ~3;
+ W.startLine() << W.hex(Start) << " - "
+ << W.hex(Start + CodeMap[i].Length) << " ";
+ switch (CodeMap[i].StartOffset & 3) {
+ case CHPE_RANGE_ARM64:
+ W.getOStream() << "ARM64\n";
+ break;
+ case CHPE_RANGE_ARM64EC:
+ W.getOStream() << "ARM64EC\n";
+ break;
+ case CHPE_RANGE_AMD64:
+ W.getOStream() << "X64\n";
+ break;
+ default:
+ W.getOStream() << W.hex(CodeMap[i].StartOffset & 3) << "\n";
+ break;
+ }
+ }
+ } else {
+ W.printNumber("CodeMap", CHPE->CodeMap);
+ }
+
+ if (CHPE->CodeRangesToEntryPointsCount) {
+ ListScope CRLS(W, "CodeRangesToEntryPoints");
+
+ uintptr_t CodeRangesInt;
+ if (Error E =
+ Obj->getRvaPtr(CHPE->CodeRangesToEntryPoints, CodeRangesInt))
+ reportError(std::move(E), Obj->getFileName());
+ auto CodeRanges =
+ reinterpret_cast<const chpe_code_range_entry *>(CodeRangesInt);
+ for (uint32_t i = 0; i < CHPE->CodeRangesToEntryPointsCount; i++) {
+ W.startLine() << W.hex(CodeRanges[i].StartRva) << " - "
+ << W.hex(CodeRanges[i].EndRva) << " -> "
+ << W.hex(CodeRanges[i].EntryPoint) << "\n";
+ }
+ } else {
+ W.printNumber("CodeRangesToEntryPoints", CHPE->CodeRangesToEntryPoints);
+ }
+
+ if (CHPE->RedirectionMetadataCount) {
+ ListScope RMLS(W, "RedirectionMetadata");
+
+ uintptr_t RedirMetadataInt;
+ if (Error E = Obj->getRvaPtr(CHPE->RedirectionMetadata, RedirMetadataInt))
+ reportError(std::move(E), Obj->getFileName());
+ auto RedirMetadata =
+ reinterpret_cast<const chpe_redirection_entry *>(RedirMetadataInt);
+ for (uint32_t i = 0; i < CHPE->RedirectionMetadataCount; i++) {
+ W.startLine() << W.hex(RedirMetadata[i].Source) << " -> "
+ << W.hex(RedirMetadata[i].Destination) << "\n";
+ }
+ } else {
+ W.printNumber("RedirectionMetadata", CHPE->RedirectionMetadata);
+ }
+
+ W.printHex("__os_arm64x_dispatch_call_no_redirect",
+ CHPE->__os_arm64x_dispatch_call_no_redirect);
+ W.printHex("__os_arm64x_dispatch_ret", CHPE->__os_arm64x_dispatch_ret);
+ W.printHex("__os_arm64x_dispatch_call", CHPE->__os_arm64x_dispatch_call);
+ W.printHex("__os_arm64x_dispatch_icall", CHPE->__os_arm64x_dispatch_icall);
+ W.printHex("__os_arm64x_dispatch_icall_cfg",
+ CHPE->__os_arm64x_dispatch_icall_cfg);
+ W.printHex("AlternateEntryPoint", CHPE->AlternateEntryPoint);
+ W.printHex("AuxiliaryIAT", CHPE->AuxiliaryIAT);
+ W.printHex("GetX64InformationFunctionPointer",
+ CHPE->GetX64InformationFunctionPointer);
+ W.printHex("SetX64InformationFunctionPointer",
+ CHPE->SetX64InformationFunctionPointer);
+ W.printHex("ExtraRFETable", CHPE->ExtraRFETable);
+ W.printHex("ExtraRFETableSize", CHPE->ExtraRFETableSize);
+ W.printHex("__os_arm64x_dispatch_fptr", CHPE->__os_arm64x_dispatch_fptr);
+ W.printHex("AuxiliaryIATCopy", CHPE->AuxiliaryIATCopy);
+ }
+
if (Tables.SEHTableVA) {
ListScope LS(W, "SEHTable");
printRVATable(Tables.SEHTableVA, Tables.SEHTableCount, 4);
@@ -921,7 +1008,7 @@ void COFFDumper::printCOFFLoadConfig(const T *Conf, LoadConfigTables &Tables) {
W.printHex("SecurityCookie", Conf->SecurityCookie);
// Print the safe SEH table if present.
- if (Conf->Size < offsetof(coff_load_configuration32, GuardCFCheckFunction))
+ if (Conf->Size < offsetof(T, GuardCFCheckFunction))
return;
W.printHex("SEHandlerTable", Conf->SEHandlerTable);
W.printNumber("SEHandlerCount", Conf->SEHandlerCount);
More information about the llvm-commits
mailing list