Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[llvm-readobj][COFF] Dump hybrid object for ARM64X files. #102245

Merged
merged 1 commit into from
Aug 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions llvm/include/llvm/Object/COFF.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
48 changes: 48 additions & 0 deletions llvm/lib/Object/COFFObjectFile.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
144 changes: 144 additions & 0 deletions llvm/test/tools/llvm-readobj/COFF/arm64x-reloc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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:
Expand Down Expand Up @@ -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: []
...
6 changes: 4 additions & 2 deletions llvm/tools/llvm-readobj/ObjDumper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
18 changes: 18 additions & 0 deletions llvm/tools/llvm-readobj/llvm-readobj.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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()))
Expand Down
Loading