mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-25 20:23:11 +01:00
[llvm-readobj] Add -hex-dump (-x) option
Differential Revision: https://reviews.llvm.org/D48281 llvm-svn: 336782
This commit is contained in:
parent
d9b763cee8
commit
18368fef36
@ -965,6 +965,8 @@ public:
|
||||
std::error_code getDataDirectory(uint32_t index,
|
||||
const data_directory *&Res) const;
|
||||
std::error_code getSection(int32_t index, const coff_section *&Res) const;
|
||||
std::error_code getSection(StringRef SectionName,
|
||||
const coff_section *&Res) const;
|
||||
|
||||
template <typename coff_symbol_type>
|
||||
std::error_code getSymbol(uint32_t Index,
|
||||
|
@ -304,6 +304,8 @@ public:
|
||||
std::error_code getSectionContents(DataRefImpl Sec,
|
||||
StringRef &Res) const override;
|
||||
uint64_t getSectionAlignment(DataRefImpl Sec) const override;
|
||||
Expected<SectionRef> getSection(unsigned SectionIndex) const;
|
||||
Expected<SectionRef> getSection(StringRef SectionName) const;
|
||||
bool isSectionCompressed(DataRefImpl Sec) const override;
|
||||
bool isSectionText(DataRefImpl Sec) const override;
|
||||
bool isSectionData(DataRefImpl Sec) const override;
|
||||
|
@ -979,6 +979,21 @@ std::error_code COFFObjectFile::getSection(int32_t Index,
|
||||
return object_error::parse_failed;
|
||||
}
|
||||
|
||||
std::error_code COFFObjectFile::getSection(StringRef SectionName,
|
||||
const coff_section *&Result) const {
|
||||
Result = nullptr;
|
||||
StringRef SecName;
|
||||
for (const SectionRef &Section : sections()) {
|
||||
if (std::error_code E = Section.getName(SecName))
|
||||
return E;
|
||||
if (SecName == SectionName) {
|
||||
Result = getCOFFSection(Section);
|
||||
return std::error_code();
|
||||
}
|
||||
}
|
||||
return object_error::parse_failed;
|
||||
}
|
||||
|
||||
std::error_code COFFObjectFile::getString(uint32_t Offset,
|
||||
StringRef &Result) const {
|
||||
if (StringTableSize <= 4)
|
||||
|
@ -1939,6 +1939,27 @@ uint64_t MachOObjectFile::getSectionAlignment(DataRefImpl Sec) const {
|
||||
return uint64_t(1) << Align;
|
||||
}
|
||||
|
||||
Expected<SectionRef> MachOObjectFile::getSection(unsigned SectionIndex) const {
|
||||
if (SectionIndex < 1 || SectionIndex > Sections.size())
|
||||
return malformedError("bad section index: " + Twine((int)SectionIndex));
|
||||
|
||||
DataRefImpl DRI;
|
||||
DRI.d.a = SectionIndex - 1;
|
||||
return SectionRef(DRI, this);
|
||||
}
|
||||
|
||||
Expected<SectionRef> MachOObjectFile::getSection(StringRef SectionName) const {
|
||||
StringRef SecName;
|
||||
for (const SectionRef &Section : sections()) {
|
||||
if (std::error_code E = Section.getName(SecName))
|
||||
return errorCodeToError(E);
|
||||
if (SecName == SectionName) {
|
||||
return Section;
|
||||
}
|
||||
}
|
||||
return errorCodeToError(object_error::parse_failed);
|
||||
}
|
||||
|
||||
bool MachOObjectFile::isSectionCompressed(DataRefImpl Sec) const {
|
||||
return false;
|
||||
}
|
||||
|
20
test/tools/llvm-readobj/print-hex.test
Normal file
20
test/tools/llvm-readobj/print-hex.test
Normal file
@ -0,0 +1,20 @@
|
||||
RUN: llvm-readobj -x .strtab %p/Inputs/trivial.obj.elf-x86-64 \
|
||||
RUN: | FileCheck %s --check-prefix ELF
|
||||
|
||||
ELF: 0x00000000 00747269 7669616c 2e6c6c00 6d61696e .trivial.ll.main
|
||||
ELF: 0x00000010 002e4c2e 73747200 70757473 00536f6d ..L.str.puts.Som
|
||||
ELF: 0x00000020 654f7468 65724675 6e637469 6f6e005f eOtherFunction._
|
||||
ELF: 0x00000030 474c4f42 414c5f4f 46465345 545f5441 GLOBAL_OFFSET_TA
|
||||
ELF: 0x00000040 424c455f 00 BLE_.
|
||||
|
||||
RUN: llvm-readobj -x 1 %p/Inputs/trivial.obj.coff-x86-64 \
|
||||
RUN: | FileCheck %s --check-prefix COFF
|
||||
|
||||
COFF: 0x00000000 4883ec28 488d0d00 000000e8 00000000 H..(H...........
|
||||
COFF: 0x00000010 e8000000 0031c048 83c428c3 .....1.H..(.
|
||||
|
||||
RUN: llvm-readobj -x 1 %p/Inputs/trivial.obj.macho-x86-64 \
|
||||
RUN: | FileCheck %s --check-prefix MACHO
|
||||
|
||||
MACHO: 0x00000000 50488d3d 00000000 e8000000 00e80000 PH.=............
|
||||
MACHO: 0x00000010 000031c0 5ac3 ..1.Z.
|
@ -83,6 +83,7 @@ public:
|
||||
void printSymbols() override;
|
||||
void printDynamicSymbols() override;
|
||||
void printUnwindInfo() override;
|
||||
void printSectionAsHex(StringRef StringName) override;
|
||||
|
||||
void printNeededLibraries() override;
|
||||
|
||||
@ -654,6 +655,28 @@ void COFFDumper::printFileHeaders() {
|
||||
printDOSHeader(DH);
|
||||
}
|
||||
|
||||
void COFFDumper::printSectionAsHex(StringRef SectionName) {
|
||||
char *StrPtr;
|
||||
long SectionIndex = strtol(SectionName.data(), &StrPtr, 10);
|
||||
const coff_section *Sec;
|
||||
if (*StrPtr)
|
||||
error(Obj->getSection(SectionName, Sec));
|
||||
else {
|
||||
error(Obj->getSection((int)SectionIndex, Sec));
|
||||
if (!Sec)
|
||||
return error(object_error::parse_failed);
|
||||
}
|
||||
|
||||
StringRef SecName;
|
||||
error(Obj->getSectionName(Sec, SecName));
|
||||
|
||||
ArrayRef<uint8_t> Content;
|
||||
error(Obj->getSectionContents(Sec, Content));
|
||||
const uint8_t *SecContent = Content.data();
|
||||
|
||||
SectionHexDump(SecName, SecContent, Content.size());
|
||||
}
|
||||
|
||||
void COFFDumper::printDOSHeader(const dos_header *DH) {
|
||||
DictScope D(W, "DOSHeader");
|
||||
W.printString("Magic", StringRef(DH->Magic, sizeof(DH->Magic)));
|
||||
|
@ -152,6 +152,7 @@ public:
|
||||
void printNeededLibraries() override;
|
||||
void printProgramHeaders() override;
|
||||
void printSectionAsString(StringRef StringName) override;
|
||||
void printSectionAsHex(StringRef StringName) override;
|
||||
void printHashTable() override;
|
||||
void printGnuHashTable() override;
|
||||
void printLoadName() override;
|
||||
@ -281,6 +282,23 @@ public:
|
||||
const Elf_GnuHash *getGnuHashTable() const { return GnuHashTable; }
|
||||
};
|
||||
|
||||
template <class ELFT>
|
||||
void ELFDumper<ELFT>::printSectionAsHex(StringRef SectionName) {
|
||||
char *StrPtr;
|
||||
long SectionIndex = strtol(SectionName.data(), &StrPtr, 10);
|
||||
const Elf_Shdr *Sec;
|
||||
if (*StrPtr)
|
||||
Sec = unwrapOrError(Obj->getSection(SectionName));
|
||||
else
|
||||
Sec = unwrapOrError(Obj->getSection((unsigned int)SectionIndex));
|
||||
|
||||
StringRef SecName = unwrapOrError(Obj->getSectionName(Sec));
|
||||
const uint8_t *SecContent =
|
||||
reinterpret_cast<const uint8_t *>(Obj->base() + Sec->sh_offset);
|
||||
|
||||
SectionHexDump(SecName, SecContent, Sec->sh_size);
|
||||
}
|
||||
|
||||
template <class ELFT>
|
||||
void ELFDumper<ELFT>::printSymbolsHelper(bool IsDynamic) const {
|
||||
StringRef StrTable, SymtabName;
|
||||
|
@ -38,6 +38,7 @@ public:
|
||||
void printDynamicSymbols() override;
|
||||
void printUnwindInfo() override;
|
||||
void printStackMap() const override;
|
||||
void printSectionAsHex(StringRef SectionName) override;
|
||||
|
||||
void printNeededLibraries() override;
|
||||
|
||||
@ -676,6 +677,26 @@ void MachODumper::printStackMap() const {
|
||||
StackMapV2Parser<support::big>(StackMapContentsArray));
|
||||
}
|
||||
|
||||
void MachODumper::printSectionAsHex(StringRef SectionName) {
|
||||
char *StrPtr;
|
||||
long SectionIndex = strtol(SectionName.data(), &StrPtr, 10);
|
||||
SectionRef SecTmp;
|
||||
const SectionRef *Sec = &SecTmp;
|
||||
if (*StrPtr)
|
||||
SecTmp = unwrapOrError(Obj->getSection(SectionName));
|
||||
else
|
||||
SecTmp = unwrapOrError(Obj->getSection((unsigned int)SectionIndex));
|
||||
|
||||
StringRef SecName;
|
||||
error(Sec->getName(SecName));
|
||||
|
||||
StringRef Data;
|
||||
error(Sec->getContents(Data));
|
||||
const uint8_t *SecContent = reinterpret_cast<const uint8_t *>(Data.data());
|
||||
|
||||
SectionHexDump(SecName, SecContent, Data.size());
|
||||
}
|
||||
|
||||
void MachODumper::printNeededLibraries() {
|
||||
ListScope D(W, "NeededLibraries");
|
||||
|
||||
|
@ -25,4 +25,46 @@ ObjDumper::ObjDumper(ScopedPrinter &Writer) : W(Writer) {}
|
||||
ObjDumper::~ObjDumper() {
|
||||
}
|
||||
|
||||
void ObjDumper::SectionHexDump(StringRef SecName, const uint8_t *Section,
|
||||
size_t Size) {
|
||||
const uint8_t *SecContent = Section;
|
||||
const uint8_t *SecEnd = Section + Size;
|
||||
W.startLine() << "Hex dump of section '" << SecName << "':\n";
|
||||
|
||||
for (const uint8_t *SecPtr = SecContent; SecPtr < SecEnd; SecPtr += 16) {
|
||||
const uint8_t *TmpSecPtr = SecPtr;
|
||||
uint8_t i;
|
||||
uint8_t k;
|
||||
|
||||
W.startLine() << format_hex(SecPtr - SecContent, 10);
|
||||
W.startLine() << ' ';
|
||||
for (i = 0; TmpSecPtr < SecEnd && i < 4; ++i) {
|
||||
for (k = 0; TmpSecPtr < SecEnd && k < 4; k++, TmpSecPtr++) {
|
||||
uint8_t Val = *(reinterpret_cast<const uint8_t *>(TmpSecPtr));
|
||||
W.startLine() << format_hex_no_prefix(Val, 2);
|
||||
}
|
||||
W.startLine() << ' ';
|
||||
}
|
||||
|
||||
// We need to print the correct amount of spaces to match the format.
|
||||
// We are adding the (4 - i) last rows that are 8 characters each.
|
||||
// Then, the (4 - i) spaces that are in between the rows.
|
||||
// Least, if we cut in a middle of a row, we add the remaining characters,
|
||||
// which is (8 - (k * 2))
|
||||
if (i < 4)
|
||||
W.startLine() << format("%*c", (4 - i) * 8 + (4 - i) + (8 - (k * 2)),
|
||||
' ');
|
||||
|
||||
TmpSecPtr = SecPtr;
|
||||
for (i = 0; TmpSecPtr + i < SecEnd && i < 16; ++i) {
|
||||
if (isprint(TmpSecPtr[i]))
|
||||
W.startLine() << TmpSecPtr[i];
|
||||
else
|
||||
W.startLine() << '.';
|
||||
}
|
||||
|
||||
W.startLine() << '\n';
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace llvm
|
||||
|
@ -44,6 +44,7 @@ public:
|
||||
virtual void printNeededLibraries() { }
|
||||
virtual void printProgramHeaders() { }
|
||||
virtual void printSectionAsString(StringRef SectionName) {}
|
||||
virtual void printSectionAsHex(StringRef SectionName) {}
|
||||
virtual void printHashTable() { }
|
||||
virtual void printGnuHashTable() { }
|
||||
virtual void printLoadName() {}
|
||||
@ -88,6 +89,7 @@ public:
|
||||
|
||||
protected:
|
||||
ScopedPrinter &W;
|
||||
void SectionHexDump(StringRef SecName, const uint8_t *Section, size_t Size);
|
||||
};
|
||||
|
||||
std::error_code createCOFFDumper(const object::ObjectFile *Obj,
|
||||
|
@ -152,6 +152,12 @@ namespace opts {
|
||||
cl::alias StringDumpShort("p", cl::desc("Alias for --string-dump"),
|
||||
cl::aliasopt(StringDump));
|
||||
|
||||
// -hex-dump
|
||||
cl::list<std::string> HexDump("hex-dump", cl::desc("<number|name>"),
|
||||
cl::ZeroOrMore);
|
||||
cl::alias HexDumpShort("x", cl::desc("Alias for --hex-dump"),
|
||||
cl::aliasopt(HexDump));
|
||||
|
||||
// -hash-table
|
||||
cl::opt<bool> HashTable("hash-table",
|
||||
cl::desc("Display ELF hash table"));
|
||||
@ -431,6 +437,10 @@ static void dumpObject(const ObjectFile *Obj, ScopedPrinter &Writer) {
|
||||
llvm::for_each(opts::StringDump, [&Dumper](StringRef SectionName) {
|
||||
Dumper->printSectionAsString(SectionName);
|
||||
});
|
||||
if (!opts::HexDump.empty())
|
||||
llvm::for_each(opts::HexDump, [&Dumper](StringRef SectionName) {
|
||||
Dumper->printSectionAsHex(SectionName);
|
||||
});
|
||||
if (opts::HashTable)
|
||||
Dumper->printHashTable();
|
||||
if (opts::GnuHashTable)
|
||||
|
Loading…
Reference in New Issue
Block a user