Skip to content

Commit 9d08c3b

Browse files
committed
[llvm-readobj][COFF] Dump hybrid object for ARM64X files.
1 parent 278c0ad commit 9d08c3b

File tree

5 files changed

+215
-2
lines changed

5 files changed

+215
-2
lines changed

llvm/include/llvm/Object/COFF.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1085,6 +1085,7 @@ class COFFObjectFile : public ObjectFile {
10851085
Expected<SubtargetFeatures> getFeatures() const override {
10861086
return SubtargetFeatures();
10871087
}
1088+
std::unique_ptr<MemoryBuffer> getHybridObjectView() const;
10881089

10891090
import_directory_iterator import_directory_begin() const;
10901091
import_directory_iterator import_directory_end() const;

llvm/lib/Object/COFFObjectFile.cpp

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,54 @@ StringRef COFFObjectFile::mapDebugSectionName(StringRef Name) const {
14891489
.Default(Name);
14901490
}
14911491

1492+
std::unique_ptr<MemoryBuffer> COFFObjectFile::getHybridObjectView() const {
1493+
if (getMachine() != COFF::IMAGE_FILE_MACHINE_ARM64X)
1494+
return nullptr;
1495+
1496+
std::unique_ptr<WritableMemoryBuffer> HybridView;
1497+
1498+
for (auto DynReloc : dynamic_relocs()) {
1499+
if (DynReloc.getType() != COFF::IMAGE_DYNAMIC_RELOCATION_ARM64X)
1500+
continue;
1501+
1502+
for (auto reloc : DynReloc.arm64x_relocs()) {
1503+
if (!HybridView) {
1504+
HybridView =
1505+
WritableMemoryBuffer::getNewUninitMemBuffer(Data.getBufferSize());
1506+
memcpy(HybridView->getBufferStart(), Data.getBufferStart(),
1507+
Data.getBufferSize());
1508+
}
1509+
1510+
uint32_t RVA = reloc.getRVA();
1511+
void *Ptr;
1512+
uintptr_t IntPtr;
1513+
if (RVA & ~0xfff) {
1514+
cantFail(getRvaPtr(RVA, IntPtr));
1515+
Ptr = HybridView->getBufferStart() + IntPtr -
1516+
reinterpret_cast<uintptr_t>(base());
1517+
} else {
1518+
// PE header relocation.
1519+
Ptr = HybridView->getBufferStart() + RVA;
1520+
}
1521+
1522+
switch (reloc.getType()) {
1523+
case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL:
1524+
memset(Ptr, 0, reloc.getSize());
1525+
break;
1526+
case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE: {
1527+
auto Value = static_cast<ulittle64_t>(reloc.getValue());
1528+
memcpy(Ptr, &Value, reloc.getSize());
1529+
break;
1530+
}
1531+
case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA:
1532+
*reinterpret_cast<ulittle32_t *>(Ptr) += reloc.getValue();
1533+
break;
1534+
}
1535+
}
1536+
}
1537+
return HybridView;
1538+
}
1539+
14921540
bool ImportDirectoryEntryRef::
14931541
operator==(const ImportDirectoryEntryRef &Other) const {
14941542
return ImportTable == Other.ImportTable && Index == Other.Index;

llvm/test/tools/llvm-readobj/COFF/arm64x-reloc.yaml

Lines changed: 144 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,32 @@
8686
# CHECK-NEXT: ]
8787
# CHECK-NEXT: ]
8888

89+
# RUN: llvm-readobj --hex-dump=.test %t.dll | FileCheck --match-full-lines --strict-whitespace --check-prefix=HEX %s
90+
# HEX:Format: COFF-ARM64X
91+
# HEX-NEXT:Arch: aarch64
92+
# HEX-NEXT:AddressSize: 64bit
93+
# HEX-EMPTY:
94+
# HEX-NEXT:Hex dump of section '.test':
95+
# HEX-NEXT:0x180006000 11112222 33334444 55556666 77778888 ..""33DDUUffww..
96+
# HEX-NEXT:0x180006010 9999aaaa bbbbcccc ddddeeee ffff0000 ................
97+
# HEX-NEXT:0x180006020 00000000 00000000 00000000 00000000 ................
98+
# HEX-NEXT:0x180006030 00000000 00000000 00000000 00000000 ................
99+
# HEX-NEXT:0x180006040 10101010 20202020 30303030 40404040 .... 0000@@@@
100+
# HEX-NEXT:0x180006050 50505050 60606060 70707070 80808080 PPPP````pppp....
101+
# HEX-NEXT:HybridObject {
102+
# HEX-NEXT: Format: COFF-ARM64EC
103+
# HEX-NEXT: Arch: aarch64
104+
# HEX-NEXT: AddressSize: 64bit
105+
# HEX-EMPTY:
106+
# HEX-NEXT: Hex dump of section '.test':
107+
# HEX-NEXT: 0x180006000 00002222 00000000 55556666 77778888 ..""....UUffww..
108+
# HEX-NEXT: 0x180006010 00000000 00000000 ddddeeee ffff0000 ................
109+
# HEX-NEXT: 0x180006020 12340000 23456789 11223344 55667788 .4..#Eg.."3DUfw.
110+
# HEX-NEXT: 0x180006030 00000000 00000000 00000000 00000000 ................
111+
# HEX-NEXT: 0x180006040 941c1110 28392220 20303030 20404040 ....(9" 000 @@@
112+
# HEX-NEXT: 0x180006050 50505050 60606060 70707070 80808080 PPPP````pppp....
113+
# HEX-NEXT:}
114+
89115

90116
--- !COFF
91117
OptionalHeader:
@@ -203,6 +229,7 @@ symbols: []
203229

204230
# RUN: yaml2obj %s --docnum=2 -o %t2.dll
205231
# RUN: llvm-readobj --coff-load-config %t2.dll | FileCheck --check-prefixes=CHECK,V2 %s
232+
# RUN: llvm-readobj --hex-dump=.test %t2.dll | FileCheck --match-full-lines --strict-whitespace --check-prefix=HEX %s
206233

207234
--- !COFF
208235
OptionalHeader:
@@ -320,3 +347,120 @@ sections:
320347
- Binary: 0000 # terminator
321348
symbols: []
322349
...
350+
351+
# RUN: yaml2obj %s --docnum=3 -o %t3.dll
352+
# RUN: llvm-readobj --coff-exports %t3.dll | FileCheck --match-full-lines --strict-whitespace --check-prefix=EXP %s
353+
354+
# EXP:Format: COFF-ARM64X
355+
# EXP-NEXT:Arch: aarch64
356+
# EXP-NEXT:AddressSize: 64bit
357+
# EXP-NEXT:Export {
358+
# EXP-NEXT: Ordinal: 1
359+
# EXP-NEXT: Name: test
360+
# EXP-NEXT: RVA: 0x2000
361+
# EXP-NEXT:}
362+
# EXP-NEXT:HybridObject {
363+
# EXP-NEXT: Format: COFF-ARM64EC
364+
# EXP-NEXT: Arch: aarch64
365+
# EXP-NEXT: AddressSize: 64bit
366+
# EXP-NEXT: Export {
367+
# EXP-NEXT: Ordinal: 1
368+
# EXP-NEXT: Name: test
369+
# EXP-NEXT: RVA: 0x2004
370+
# EXP-NEXT: }
371+
# EXP-NEXT:}
372+
373+
--- !COFF
374+
OptionalHeader:
375+
ImageBase: 0x180000000
376+
SectionAlignment: 4096
377+
FileAlignment: 512
378+
DLLCharacteristics: [ ]
379+
AddressOfEntryPoint: 0
380+
ExportTable:
381+
RelativeVirtualAddress: 0x1000
382+
Size: 64
383+
LoadConfigTable:
384+
RelativeVirtualAddress: 0x3000
385+
Size: 320
386+
header:
387+
Machine: IMAGE_FILE_MACHINE_ARM64
388+
Characteristics: [ IMAGE_FILE_EXECUTABLE_IMAGE, IMAGE_FILE_LARGE_ADDRESS_AWARE, IMAGE_FILE_DLL ]
389+
sections:
390+
- Name: .rdata
391+
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
392+
VirtualAddress: 0x1000
393+
VirtualSize: 64
394+
StructuredData:
395+
- UInt32: 0 # ExportFlags
396+
- UInt32: 0 # TimeDateStamp
397+
- UInt32: 0 # Version
398+
- UInt32: 0x1028 # NameRVA
399+
- UInt32: 1 # OrdinalBase
400+
- UInt32: 1 # AddressTableEntries
401+
- UInt32: 1 # NumberOfNamePointers
402+
- UInt32: 0x1030 # ExportAddressTableRVA
403+
- UInt32: 0x1034 # NamePointerRVA
404+
- UInt32: 0x1038 # OrdinalTableRVA
405+
- Binary: 7473742E646C6C00 # "tst.dll"
406+
- UInt32: 0x2000 # export RVA
407+
- UInt32: 0x103A # name RVA
408+
- Binary: 0000 # ordinal
409+
- Binary: 7465737400 # "test"
410+
- Name: .data
411+
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
412+
VirtualAddress: 0x2000
413+
VirtualSize: 80
414+
StructuredData:
415+
- UInt32: 1 # Version
416+
- UInt32: 0 # CodeMap
417+
- UInt32: 0 # CodeMapCount
418+
- UInt32: 0 # CodeRangesToEntryPoints
419+
- UInt32: 0 # RedirectionMetadata
420+
- UInt32: 0
421+
- UInt32: 0
422+
- UInt32: 0
423+
- UInt32: 0
424+
- UInt32: 0
425+
- UInt32: 0
426+
- UInt32: 0
427+
- UInt32: 0 # CodeRangesToEntryPointsCount
428+
- UInt32: 0 # RedirectionMetadataCount
429+
- UInt32: 0
430+
- UInt32: 0
431+
- UInt32: 0
432+
- UInt32: 0
433+
- UInt32: 0
434+
- UInt32: 0
435+
- Name: .cfg
436+
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
437+
VirtualAddress: 0x3000
438+
VirtualSize: 328
439+
StructuredData:
440+
- LoadConfig:
441+
CHPEMetadataPointer: 0x180002000
442+
DynamicValueRelocTableOffset: 0
443+
DynamicValueRelocTableSection: 4
444+
- Name: .arm64x
445+
Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_DISCARDABLE ]
446+
VirtualAddress: 0x4000
447+
VirtualSize: 56
448+
StructuredData:
449+
- UInt32: 2 # coff_dynamic_reloc_table.Version
450+
- UInt32: 48 # coff_dynamic_reloc_table.Size
451+
- UInt32: 24 # coff_dynamic_relocation64_v2.HeaderSize
452+
- UInt32: 24 # coff_dynamic_relocation64_v2.FixupInfoSize
453+
- UInt32: 6 # coff_dynamic_relocation64_v2.Symbol(low) = IMAGE_DYNAMIC_RELOCATION_ARM64X
454+
- UInt32: 0 # coff_dynamic_relocation64_v2.Symbol(high)
455+
- UInt32: 0 # coff_dynamic_relocation64_v2.SymbolGroup
456+
- UInt32: 0 # coff_dynamic_relocation64_v2.Flags
457+
- UInt32: 0 # coff_base_reloc_block_header[0].PageRVA
458+
- UInt32: 12 # coff_base_reloc_block_header[0].BlockSize
459+
- Binary: 8450 # VALUE offset 0x84 (PE header Machine), size 2
460+
- Binary: 6486 # IMAGE_FILE_MACHINE_AMD64
461+
- UInt32: 0x1000 # coff_base_reloc_block_header[1].PageRVA
462+
- UInt32: 12 # coff_base_reloc_block_header[1].BlockSize
463+
- Binary: 3020 # DELTA offset 0x30, mul 4
464+
- Binary: 0100
465+
symbols: []
466+
...

llvm/tools/llvm-readobj/ObjDumper.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,10 @@ void ObjDumper::printAsStringList(StringRef StringContent,
9191
void ObjDumper::printFileSummary(StringRef FileStr, object::ObjectFile &Obj,
9292
ArrayRef<std::string> InputFilenames,
9393
const object::Archive *A) {
94-
W.getOStream() << "\n";
95-
W.printString("File", FileStr);
94+
if (!FileStr.empty()) {
95+
W.getOStream() << "\n";
96+
W.printString("File", FileStr);
97+
}
9698
W.printString("Format", Obj.getFileFormatName());
9799
W.printString("Arch", Triple::getArchTypeName(Obj.getArch()));
98100
W.printString("AddressSize",

llvm/tools/llvm-readobj/llvm-readobj.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -580,6 +580,22 @@ static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary,
580580
}
581581
}
582582

583+
/// Dumps \a COFF file;
584+
static void dumpCOFFObject(COFFObjectFile *Obj, ScopedPrinter &Writer) {
585+
dumpObject(*Obj, Writer);
586+
587+
// Dump a hybrid object when available.
588+
std::unique_ptr<MemoryBuffer> HybridView = Obj->getHybridObjectView();
589+
if (!HybridView)
590+
return;
591+
Expected<std::unique_ptr<COFFObjectFile>> HybridObjOrErr =
592+
COFFObjectFile::create(*HybridView);
593+
if (!HybridObjOrErr)
594+
reportError(HybridObjOrErr.takeError(), Obj->getFileName().str());
595+
DictScope D(Writer, "HybridObject");
596+
dumpObject(**HybridObjOrErr, Writer);
597+
}
598+
583599
/// Dumps \a WinRes, Windows Resource (.res) file;
584600
static void dumpWindowsResourceFile(WindowsResource *WinRes,
585601
ScopedPrinter &Printer) {
@@ -617,6 +633,8 @@ static void dumpInput(StringRef File, ScopedPrinter &Writer) {
617633
else if (MachOUniversalBinary *UBinary =
618634
dyn_cast<MachOUniversalBinary>(Bin.get()))
619635
dumpMachOUniversalBinary(UBinary, Writer);
636+
else if (COFFObjectFile *Obj = dyn_cast<COFFObjectFile>(Bin.get()))
637+
dumpCOFFObject(Obj, Writer);
620638
else if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin.get()))
621639
dumpObject(*Obj, Writer);
622640
else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(Bin.get()))

0 commit comments

Comments
 (0)