[llvm] [llvm-readobj][COFF] Dump hybrid object for ARM64X files. (PR #102245)
Jacek Caban via llvm-commits
llvm-commits at lists.llvm.org
Wed Aug 7 15:19:22 PDT 2024
https://github.com/cjacek updated https://github.com/llvm/llvm-project/pull/102245
>From 9d08c3bb8df7f74aa0bd8f1e0f74000c67c49dff Mon Sep 17 00:00:00 2001
From: Jacek Caban <jacek at codeweavers.com>
Date: Sat, 20 Jan 2024 01:07:17 +0100
Subject: [PATCH] [llvm-readobj][COFF] Dump hybrid object for ARM64X files.
---
llvm/include/llvm/Object/COFF.h | 1 +
llvm/lib/Object/COFFObjectFile.cpp | 48 ++++++
.../tools/llvm-readobj/COFF/arm64x-reloc.yaml | 144 ++++++++++++++++++
llvm/tools/llvm-readobj/ObjDumper.cpp | 6 +-
llvm/tools/llvm-readobj/llvm-readobj.cpp | 18 +++
5 files changed, 215 insertions(+), 2 deletions(-)
diff --git a/llvm/include/llvm/Object/COFF.h b/llvm/include/llvm/Object/COFF.h
index b084754c5f8fb..dc43c87c4125c 100644
--- a/llvm/include/llvm/Object/COFF.h
+++ b/llvm/include/llvm/Object/COFF.h
@@ -1085,6 +1085,7 @@ class COFFObjectFile : public ObjectFile {
Expected<SubtargetFeatures> getFeatures() const override {
return SubtargetFeatures();
}
+ std::unique_ptr<MemoryBuffer> getHybridObjectView() const;
import_directory_iterator import_directory_begin() const;
import_directory_iterator import_directory_end() const;
diff --git a/llvm/lib/Object/COFFObjectFile.cpp b/llvm/lib/Object/COFFObjectFile.cpp
index 34347e5681358..f8a177879b319 100644
--- a/llvm/lib/Object/COFFObjectFile.cpp
+++ b/llvm/lib/Object/COFFObjectFile.cpp
@@ -1489,6 +1489,54 @@ StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
.Default(Name);
}
+std::unique_ptr<MemoryBuffer> COFFObjectFile::getHybridObjectView() const {
+ if (getMachine() != COFF::IMAGE_FILE_MACHINE_ARM64X)
+ return nullptr;
+
+ std::unique_ptr<WritableMemoryBuffer> HybridView;
+
+ for (auto DynReloc : dynamic_relocs()) {
+ if (DynReloc.getType() != COFF::IMAGE_DYNAMIC_RELOCATION_ARM64X)
+ continue;
+
+ for (auto reloc : DynReloc.arm64x_relocs()) {
+ if (!HybridView) {
+ HybridView =
+ WritableMemoryBuffer::getNewUninitMemBuffer(Data.getBufferSize());
+ memcpy(HybridView->getBufferStart(), Data.getBufferStart(),
+ Data.getBufferSize());
+ }
+
+ uint32_t RVA = reloc.getRVA();
+ void *Ptr;
+ uintptr_t IntPtr;
+ if (RVA & ~0xfff) {
+ cantFail(getRvaPtr(RVA, IntPtr));
+ Ptr = HybridView->getBufferStart() + IntPtr -
+ reinterpret_cast<uintptr_t>(base());
+ } else {
+ // PE header relocation.
+ Ptr = HybridView->getBufferStart() + RVA;
+ }
+
+ switch (reloc.getType()) {
+ case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL:
+ memset(Ptr, 0, reloc.getSize());
+ break;
+ case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE: {
+ auto Value = static_cast<ulittle64_t>(reloc.getValue());
+ memcpy(Ptr, &Value, reloc.getSize());
+ break;
+ }
+ case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA:
+ *reinterpret_cast<ulittle32_t *>(Ptr) += reloc.getValue();
+ break;
+ }
+ }
+ }
+ return HybridView;
+}
+
bool ImportDirectoryEntryRef::
operator==(const ImportDirectoryEntryRef &Other) const {
return ImportTable == Other.ImportTable && Index == Other.Index;
diff --git a/llvm/test/tools/llvm-readobj/COFF/arm64x-reloc.yaml b/llvm/test/tools/llvm-readobj/COFF/arm64x-reloc.yaml
index df2d83db3a6a1..902a6b8b6eaa5 100644
--- a/llvm/test/tools/llvm-readobj/COFF/arm64x-reloc.yaml
+++ b/llvm/test/tools/llvm-readobj/COFF/arm64x-reloc.yaml
@@ -86,6 +86,32 @@
# CHECK-NEXT: ]
# CHECK-NEXT: ]
+# RUN: llvm-readobj --hex-dump=.test %t.dll | FileCheck --match-full-lines --strict-whitespace --check-prefix=HEX %s
+# HEX:Format: COFF-ARM64X
+# HEX-NEXT:Arch: aarch64
+# HEX-NEXT:AddressSize: 64bit
+# HEX-EMPTY:
+# HEX-NEXT:Hex dump of section '.test':
+# HEX-NEXT:0x180006000 11112222 33334444 55556666 77778888 ..""33DDUUffww..
+# HEX-NEXT:0x180006010 9999aaaa bbbbcccc ddddeeee ffff0000 ................
+# HEX-NEXT:0x180006020 00000000 00000000 00000000 00000000 ................
+# HEX-NEXT:0x180006030 00000000 00000000 00000000 00000000 ................
+# HEX-NEXT:0x180006040 10101010 20202020 30303030 40404040 .... 0000@@@@
+# HEX-NEXT:0x180006050 50505050 60606060 70707070 80808080 PPPP````pppp....
+# HEX-NEXT:HybridObject {
+# HEX-NEXT: Format: COFF-ARM64EC
+# HEX-NEXT: Arch: aarch64
+# HEX-NEXT: AddressSize: 64bit
+# HEX-EMPTY:
+# HEX-NEXT: Hex dump of section '.test':
+# HEX-NEXT: 0x180006000 00002222 00000000 55556666 77778888 ..""....UUffww..
+# HEX-NEXT: 0x180006010 00000000 00000000 ddddeeee ffff0000 ................
+# HEX-NEXT: 0x180006020 12340000 23456789 11223344 55667788 .4..#Eg.."3DUfw.
+# HEX-NEXT: 0x180006030 00000000 00000000 00000000 00000000 ................
+# HEX-NEXT: 0x180006040 941c1110 28392220 20303030 20404040 ....(9" 000 @@@
+# HEX-NEXT: 0x180006050 50505050 60606060 70707070 80808080 PPPP````pppp....
+# HEX-NEXT:}
+
--- !COFF
OptionalHeader:
@@ -203,6 +229,7 @@ symbols: []
# RUN: yaml2obj %s --docnum=2 -o %t2.dll
# RUN: llvm-readobj --coff-load-config %t2.dll | FileCheck --check-prefixes=CHECK,V2 %s
+# RUN: llvm-readobj --hex-dump=.test %t2.dll | FileCheck --match-full-lines --strict-whitespace --check-prefix=HEX %s
--- !COFF
OptionalHeader:
@@ -320,3 +347,120 @@ sections:
- Binary: 0000 # terminator
symbols: []
...
+
+# RUN: yaml2obj %s --docnum=3 -o %t3.dll
+# RUN: llvm-readobj --coff-exports %t3.dll | FileCheck --match-full-lines --strict-whitespace --check-prefix=EXP %s
+
+# EXP:Format: COFF-ARM64X
+# EXP-NEXT:Arch: aarch64
+# EXP-NEXT:AddressSize: 64bit
+# EXP-NEXT:Export {
+# EXP-NEXT: Ordinal: 1
+# EXP-NEXT: Name: test
+# EXP-NEXT: RVA: 0x2000
+# EXP-NEXT:}
+# EXP-NEXT:HybridObject {
+# EXP-NEXT: Format: COFF-ARM64EC
+# EXP-NEXT: Arch: aarch64
+# EXP-NEXT: AddressSize: 64bit
+# EXP-NEXT: Export {
+# EXP-NEXT: Ordinal: 1
+# EXP-NEXT: Name: test
+# EXP-NEXT: RVA: 0x2004
+# EXP-NEXT: }
+# EXP-NEXT:}
+
+--- !COFF
+OptionalHeader:
+ ImageBase: 0x180000000
+ SectionAlignment: 4096
+ FileAlignment: 512
+ DLLCharacteristics: [ ]
+ AddressOfEntryPoint: 0
+ ExportTable:
+ RelativeVirtualAddress: 0x1000
+ Size: 64
+ LoadConfigTable:
+ RelativeVirtualAddress: 0x3000
+ Size: 320
+header:
+ Machine: IMAGE_FILE_MACHINE_ARM64
+ 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: 64
+ StructuredData:
+ - UInt32: 0 # ExportFlags
+ - UInt32: 0 # TimeDateStamp
+ - UInt32: 0 # Version
+ - UInt32: 0x1028 # NameRVA
+ - UInt32: 1 # OrdinalBase
+ - UInt32: 1 # AddressTableEntries
+ - UInt32: 1 # NumberOfNamePointers
+ - UInt32: 0x1030 # ExportAddressTableRVA
+ - UInt32: 0x1034 # NamePointerRVA
+ - UInt32: 0x1038 # OrdinalTableRVA
+ - Binary: 7473742E646C6C00 # "tst.dll"
+ - UInt32: 0x2000 # export RVA
+ - UInt32: 0x103A # name RVA
+ - Binary: 0000 # ordinal
+ - Binary: 7465737400 # "test"
+ - Name: .data
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
+ VirtualAddress: 0x2000
+ VirtualSize: 80
+ StructuredData:
+ - UInt32: 1 # Version
+ - UInt32: 0 # CodeMap
+ - UInt32: 0 # CodeMapCount
+ - UInt32: 0 # CodeRangesToEntryPoints
+ - UInt32: 0 # RedirectionMetadata
+ - UInt32: 0
+ - UInt32: 0
+ - UInt32: 0
+ - UInt32: 0
+ - UInt32: 0
+ - UInt32: 0
+ - UInt32: 0
+ - UInt32: 0 # CodeRangesToEntryPointsCount
+ - UInt32: 0 # RedirectionMetadataCount
+ - UInt32: 0
+ - UInt32: 0
+ - UInt32: 0
+ - UInt32: 0
+ - UInt32: 0
+ - UInt32: 0
+ - Name: .cfg
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
+ VirtualAddress: 0x3000
+ VirtualSize: 328
+ StructuredData:
+ - LoadConfig:
+ CHPEMetadataPointer: 0x180002000
+ DynamicValueRelocTableOffset: 0
+ DynamicValueRelocTableSection: 4
+ - Name: .arm64x
+ Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_DISCARDABLE ]
+ VirtualAddress: 0x4000
+ VirtualSize: 56
+ StructuredData:
+ - UInt32: 2 # coff_dynamic_reloc_table.Version
+ - UInt32: 48 # coff_dynamic_reloc_table.Size
+ - UInt32: 24 # coff_dynamic_relocation64_v2.HeaderSize
+ - UInt32: 24 # coff_dynamic_relocation64_v2.FixupInfoSize
+ - UInt32: 6 # coff_dynamic_relocation64_v2.Symbol(low) = IMAGE_DYNAMIC_RELOCATION_ARM64X
+ - UInt32: 0 # coff_dynamic_relocation64_v2.Symbol(high)
+ - UInt32: 0 # coff_dynamic_relocation64_v2.SymbolGroup
+ - UInt32: 0 # coff_dynamic_relocation64_v2.Flags
+ - UInt32: 0 # coff_base_reloc_block_header[0].PageRVA
+ - UInt32: 12 # coff_base_reloc_block_header[0].BlockSize
+ - Binary: 8450 # VALUE offset 0x84 (PE header Machine), size 2
+ - Binary: 6486 # IMAGE_FILE_MACHINE_AMD64
+ - UInt32: 0x1000 # coff_base_reloc_block_header[1].PageRVA
+ - UInt32: 12 # coff_base_reloc_block_header[1].BlockSize
+ - Binary: 3020 # DELTA offset 0x30, mul 4
+ - Binary: 0100
+symbols: []
+...
diff --git a/llvm/tools/llvm-readobj/ObjDumper.cpp b/llvm/tools/llvm-readobj/ObjDumper.cpp
index 20e99d9d97f3a..d02d1e543d31d 100644
--- a/llvm/tools/llvm-readobj/ObjDumper.cpp
+++ b/llvm/tools/llvm-readobj/ObjDumper.cpp
@@ -91,8 +91,10 @@ void ObjDumper::printAsStringList(StringRef StringContent,
void ObjDumper::printFileSummary(StringRef FileStr, object::ObjectFile &Obj,
ArrayRef<std::string> InputFilenames,
const object::Archive *A) {
- W.getOStream() << "\n";
- W.printString("File", FileStr);
+ if (!FileStr.empty()) {
+ W.getOStream() << "\n";
+ W.printString("File", FileStr);
+ }
W.printString("Format", Obj.getFileFormatName());
W.printString("Arch", Triple::getArchTypeName(Obj.getArch()));
W.printString("AddressSize",
diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp
index 15d838617063b..3e76cda2dd433 100644
--- a/llvm/tools/llvm-readobj/llvm-readobj.cpp
+++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp
@@ -580,6 +580,22 @@ static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary,
}
}
+/// Dumps \a COFF file;
+static void dumpCOFFObject(COFFObjectFile *Obj, ScopedPrinter &Writer) {
+ dumpObject(*Obj, Writer);
+
+ // Dump a hybrid object when available.
+ std::unique_ptr<MemoryBuffer> HybridView = Obj->getHybridObjectView();
+ if (!HybridView)
+ return;
+ Expected<std::unique_ptr<COFFObjectFile>> HybridObjOrErr =
+ COFFObjectFile::create(*HybridView);
+ if (!HybridObjOrErr)
+ reportError(HybridObjOrErr.takeError(), Obj->getFileName().str());
+ DictScope D(Writer, "HybridObject");
+ dumpObject(**HybridObjOrErr, Writer);
+}
+
/// Dumps \a WinRes, Windows Resource (.res) file;
static void dumpWindowsResourceFile(WindowsResource *WinRes,
ScopedPrinter &Printer) {
@@ -617,6 +633,8 @@ static void dumpInput(StringRef File, ScopedPrinter &Writer) {
else if (MachOUniversalBinary *UBinary =
dyn_cast<MachOUniversalBinary>(Bin.get()))
dumpMachOUniversalBinary(UBinary, Writer);
+ else if (COFFObjectFile *Obj = dyn_cast<COFFObjectFile>(Bin.get()))
+ dumpCOFFObject(Obj, Writer);
else if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin.get()))
dumpObject(*Obj, Writer);
else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(Bin.get()))
More information about the llvm-commits
mailing list