Skip to content

Commit f70491b

Browse files
committed
[llvm-readobj][COFF] Dump hybrid object as well for ARM64X files.
1 parent ba8c61e commit f70491b

File tree

7 files changed

+120
-20
lines changed

7 files changed

+120
-20
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: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1489,6 +1489,53 @@ 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+
uint64_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+
Ptr = HybridView->getBufferStart() + rva;
1519+
}
1520+
1521+
switch (reloc.getType()) {
1522+
case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_ZEROFILL:
1523+
memset(Ptr, 0, reloc.getSize());
1524+
break;
1525+
case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_VALUE: {
1526+
auto Value = static_cast<ulittle64_t>(reloc.getValue());
1527+
memcpy(Ptr, &Value, reloc.getSize());
1528+
break;
1529+
}
1530+
case COFF::IMAGE_DVRT_ARM64X_FIXUP_TYPE_DELTA:
1531+
*reinterpret_cast<ulittle32_t *>(Ptr) += reloc.getValue();
1532+
break;
1533+
}
1534+
}
1535+
}
1536+
return HybridView;
1537+
}
1538+
14921539
bool ImportDirectoryEntryRef::
14931540
operator==(const ImportDirectoryEntryRef &Other) const {
14941541
return ImportTable == Other.ImportTable && Index == Other.Index;

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

Lines changed: 27 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 --check-prefix=TEST %s
90+
# TEST: Format: COFF-ARM64X
91+
# TEST-NEXT: Arch: aarch64
92+
# TEST-NEXT: AddressSize: 64bit
93+
# TEST-EMPTY:
94+
# TEST-NEXT: Hex dump of section '.test':
95+
# TEST-NEXT: 0x180006000 11112222 33334444 55556666 77778888 ..""33DDUUffww..
96+
# TEST-NEXT: 0x180006010 9999aaaa bbbbcccc ddddeeee ffff0000 ................
97+
# TEST-NEXT: 0x180006020 00000000 00000000 00000000 00000000 ................
98+
# TEST-NEXT: 0x180006030 00000000 00000000 00000000 00000000 ................
99+
# TEST-NEXT: 0x180006040 10101010 20202020 30303030 40404040 .... 0000@@@@
100+
# TEST-NEXT: 0x180006050 50505050 60606060 70707070 80808080 PPPP````pppp....
101+
# TEST-NEXT: HybridObject {
102+
# TEST-NEXT: Format: COFF-ARM64EC
103+
# TEST-NEXT: Arch: aarch64
104+
# TEST-NEXT: AddressSize: 64bit
105+
# TEST-EMPTY:
106+
# TEST-NEXT: Hex dump of section '.test':
107+
# TEST-NEXT: 0x180006000 00002222 00000000 55556666 77778888 ..""....UUffww..
108+
# TEST-NEXT: 0x180006010 00000000 00000000 ddddeeee ffff0000 ................
109+
# TEST-NEXT: 0x180006020 12340000 23456789 11223344 55667788 .4..#Eg.."3DUfw.
110+
# TEST-NEXT: 0x180006030 00000000 00000000 00000000 00000000 ................
111+
# TEST-NEXT: 0x180006040 941c1110 28392220 20303030 20404040 ....(9" 000 @@@
112+
# TEST-NEXT: 0x180006050 50505050 60606060 70707070 80808080 PPPP````pppp....
113+
# TEST-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 --check-prefix=TEST %s
206233

207234
--- !COFF
208235
OptionalHeader:

llvm/tools/llvm-readobj/COFFDumper.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ class COFFDumper : public ObjDumper {
9999
void printCOFFTLSDirectory() override;
100100
void printCOFFResources() override;
101101
void printCOFFLoadConfig() override;
102+
void printCOFFHybridObject() override;
102103
void printCodeViewDebugInfo() override;
103104
void mergeCodeViewTypes(llvm::codeview::MergingTypeTableBuilder &CVIDs,
104105
llvm::codeview::MergingTypeTableBuilder &CVTypes,
@@ -2271,3 +2272,15 @@ void COFFDumper::printCOFFTLSDirectory(
22712272
ArrayRef(ImageSectionCharacteristics),
22722273
COFF::SectionCharacteristics(COFF::IMAGE_SCN_ALIGN_MASK));
22732274
}
2275+
2276+
void COFFDumper::printCOFFHybridObject() {
2277+
std::unique_ptr<MemoryBuffer> HybridView = Obj->getHybridObjectView();
2278+
if (!HybridView)
2279+
return;
2280+
Expected<std::unique_ptr<COFFObjectFile>> HybridObjOrErr =
2281+
COFFObjectFile::create(*HybridView);
2282+
if (!HybridObjOrErr)
2283+
reportError(HybridObjOrErr.takeError(), Obj->getFileName().str());
2284+
DictScope D(Writer, "HybridObject");
2285+
ObjDumper::dumpObject(**HybridObjOrErr, Writer, nullptr, true);
2286+
}

llvm/tools/llvm-readobj/ObjDumper.cpp

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -82,17 +82,19 @@ void ObjDumper::printAsStringList(StringRef StringContent,
8282
continue;
8383
}
8484
W.startLine() << format("[%6tx] ", CurrentWord - StrContent);
85-
printAsPrintable(W.startLine(), CurrentWord, WordSize);
86-
W.startLine() << '\n';
85+
printAsPrintable(W.getOStream(), CurrentWord, WordSize);
86+
W.getOStream() << '\n';
8787
CurrentWord += WordSize + 1;
8888
}
8989
}
9090

9191
void ObjDumper::printFileSummary(StringRef FileStr, object::ObjectFile &Obj,
9292
ArrayRef<std::string> InputFilenames,
9393
const object::Archive *A) {
94-
W.startLine() << "\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",
@@ -163,7 +165,8 @@ void ObjDumper::printSectionsAsString(const object::ObjectFile &Obj,
163165
for (object::SectionRef Section :
164166
getSectionRefsByNameOrIndex(Obj, Sections)) {
165167
StringRef SectionName = unwrapOrError(Obj.getFileName(), Section.getName());
166-
W.startLine() << "\nString dump of section '" << SectionName << "':\n";
168+
W.getOStream() << '\n';
169+
W.startLine() << "String dump of section '" << SectionName << "':\n";
167170

168171
StringRef SectionContent =
169172
unwrapOrError(Obj.getFileName(), Section.getContents());
@@ -180,7 +183,8 @@ void ObjDumper::printSectionsAsHex(const object::ObjectFile &Obj,
180183
for (object::SectionRef Section :
181184
getSectionRefsByNameOrIndex(Obj, Sections)) {
182185
StringRef SectionName = unwrapOrError(Obj.getFileName(), Section.getName());
183-
W.startLine() << "\nHex dump of section '" << SectionName << "':\n";
186+
W.getOStream() << '\n';
187+
W.startLine() << "Hex dump of section '" << SectionName << "':\n";
184188

185189
StringRef SectionContent =
186190
unwrapOrError(Obj.getFileName(), Section.getContents());
@@ -196,13 +200,13 @@ void ObjDumper::printSectionsAsHex(const object::ObjectFile &Obj,
196200

197201
W.startLine() << format_hex(Section.getAddress() + (SecPtr - SecContent),
198202
10);
199-
W.startLine() << ' ';
203+
W.getOStream() << ' ';
200204
for (i = 0; TmpSecPtr < SecEnd && i < 4; ++i) {
201205
for (k = 0; TmpSecPtr < SecEnd && k < 4; k++, TmpSecPtr++) {
202206
uint8_t Val = *(reinterpret_cast<const uint8_t *>(TmpSecPtr));
203-
W.startLine() << format_hex_no_prefix(Val, 2);
207+
W.getOStream() << format_hex_no_prefix(Val, 2);
204208
}
205-
W.startLine() << ' ';
209+
W.getOStream() << ' ';
206210
}
207211

208212
// We need to print the correct amount of spaces to match the format.
@@ -211,17 +215,17 @@ void ObjDumper::printSectionsAsHex(const object::ObjectFile &Obj,
211215
// Least, if we cut in a middle of a row, we add the remaining characters,
212216
// which is (8 - (k * 2)).
213217
if (i < 4)
214-
W.startLine() << format("%*c", (4 - i) * 8 + (4 - i), ' ');
218+
W.getOStream() << format("%*c", (4 - i) * 8 + (4 - i), ' ');
215219
if (k < 4)
216-
W.startLine() << format("%*c", 8 - k * 2, ' ');
220+
W.getOStream() << format("%*c", 8 - k * 2, ' ');
217221

218222
TmpSecPtr = SecPtr;
219223
for (i = 0; TmpSecPtr + i < SecEnd && i < 16; ++i)
220-
W.startLine() << (isPrint(TmpSecPtr[i])
221-
? static_cast<char>(TmpSecPtr[i])
222-
: '.');
224+
W.getOStream() << (isPrint(TmpSecPtr[i])
225+
? static_cast<char>(TmpSecPtr[i])
226+
: '.');
223227

224-
W.startLine() << '\n';
228+
W.getOStream() << '\n';
225229
}
226230
}
227231
}

llvm/tools/llvm-readobj/ObjDumper.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ class ObjDumper {
149149
virtual void printCOFFTLSDirectory() {}
150150
virtual void printCOFFResources() {}
151151
virtual void printCOFFLoadConfig() { }
152+
virtual void printCOFFHybridObject() {}
152153
virtual void printCodeViewDebugInfo() { }
153154
virtual void
154155
mergeCodeViewTypes(llvm::codeview::MergingTypeTableBuilder &CVIDs,
@@ -185,6 +186,10 @@ class ObjDumper {
185186
void reportUniqueWarning(Error Err) const;
186187
void reportUniqueWarning(const Twine &Msg) const;
187188

189+
static void dumpObject(object::ObjectFile &Obj, ScopedPrinter &Writer,
190+
const object::Archive *A = nullptr,
191+
bool IsHybrid = false);
192+
188193
protected:
189194
ScopedPrinter &W;
190195

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

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,8 @@ createDumper(const ObjectFile &Obj, ScopedPrinter &Writer) {
360360
}
361361

362362
/// Dumps the specified object file.
363-
static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
364-
const Archive *A = nullptr) {
363+
void ObjDumper::dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
364+
const Archive *A, bool IsHybrid) {
365365
std::string FileStr =
366366
A ? Twine(A->getFileName() + "(" + Obj.getFileName() + ")").str()
367367
: Obj.getFileName().str();
@@ -538,6 +538,9 @@ static void dumpObject(ObjectFile &Obj, ScopedPrinter &Writer,
538538
Dumper->printStackMap();
539539
if (opts::PrintStackSizes)
540540
Dumper->printStackSizes();
541+
542+
if (!IsHybrid && Obj.isCOFF())
543+
Dumper->printCOFFHybridObject();
541544
}
542545

543546
/// Dumps each object file in \a Arc;
@@ -553,7 +556,7 @@ static void dumpArchive(const Archive *Arc, ScopedPrinter &Writer) {
553556

554557
Binary *Bin = ChildOrErr->get();
555558
if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin))
556-
dumpObject(*Obj, Writer, Arc);
559+
ObjDumper::dumpObject(*Obj, Writer, Arc);
557560
else if (COFFImportFile *Imp = dyn_cast<COFFImportFile>(Bin))
558561
dumpCOFFImportFile(Imp, Writer);
559562
else
@@ -572,7 +575,7 @@ static void dumpMachOUniversalBinary(const MachOUniversalBinary *UBinary,
572575
for (const MachOUniversalBinary::ObjectForArch &Obj : UBinary->objects()) {
573576
Expected<std::unique_ptr<MachOObjectFile>> ObjOrErr = Obj.getAsObjectFile();
574577
if (ObjOrErr)
575-
dumpObject(*ObjOrErr.get(), Writer);
578+
ObjDumper::dumpObject(*ObjOrErr.get(), Writer);
576579
else if (auto E = isNotObjectErrorInvalidFileType(ObjOrErr.takeError()))
577580
reportError(ObjOrErr.takeError(), UBinary->getFileName());
578581
else if (Expected<std::unique_ptr<Archive>> AOrErr = Obj.getAsArchive())
@@ -618,7 +621,7 @@ static void dumpInput(StringRef File, ScopedPrinter &Writer) {
618621
dyn_cast<MachOUniversalBinary>(Bin.get()))
619622
dumpMachOUniversalBinary(UBinary, Writer);
620623
else if (ObjectFile *Obj = dyn_cast<ObjectFile>(Bin.get()))
621-
dumpObject(*Obj, Writer);
624+
ObjDumper::dumpObject(*Obj, Writer);
622625
else if (COFFImportFile *Import = dyn_cast<COFFImportFile>(Bin.get()))
623626
dumpCOFFImportFile(Import, Writer);
624627
else if (WindowsResource *WinRes = dyn_cast<WindowsResource>(Bin.get()))

0 commit comments

Comments
 (0)