From 064db4306cf1173d4ac980e16321ed1eede5d2c3 Mon Sep 17 00:00:00 2001 From: Paul Semel Date: Fri, 15 Jun 2018 14:15:02 +0000 Subject: [PATCH] [llvm-readobj] Add -string-dump (-p) option This option prints the section content as a string. Differential Revision: https://reviews.llvm.org/D47989 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@334834 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Object/ELF.h | 17 +++++++++ tools/llvm-readobj/ELFDumper.cpp | 72 +++++++++++++++++++++++++++++++++++++ tools/llvm-readobj/ObjDumper.h | 3 ++ tools/llvm-readobj/llvm-readobj.cpp | 10 ++++++ 4 files changed, 102 insertions(+) diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h index 06f49c4ac73..c0fcda3b475 100644 --- a/include/llvm/Object/ELF.h +++ b/include/llvm/Object/ELF.h @@ -235,6 +235,7 @@ public: Elf_Sym_Range Symtab, ArrayRef ShndxTable) const; Expected getSection(uint32_t Index) const; + Expected getSection(const StringRef SectionName) const; Expected getSymbol(const Elf_Shdr *Sec, uint32_t Index) const; @@ -499,6 +500,22 @@ ELFFile::getSection(uint32_t Index) const { } template +Expected +ELFFile::getSection(const StringRef SectionName) const { + auto TableOrErr = sections(); + if (!TableOrErr) + return TableOrErr.takeError(); + for (auto &Sec : *TableOrErr) { + auto SecNameOrErr = getSectionName(&Sec); + if (!SecNameOrErr) + return SecNameOrErr.takeError(); + if (*SecNameOrErr == SectionName) + return &Sec; + } + return createError("invalid section name"); +} + +template Expected ELFFile::getStringTable(const Elf_Shdr *Section) const { if (Section->sh_type != ELF::SHT_STRTAB) diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index 2492fa2acc2..05bcd1a4b56 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -149,6 +149,7 @@ public: void printDynamicTable() override; void printNeededLibraries() override; void printProgramHeaders() override; + void printSectionAsString(StringRef StringName) override; void printHashTable() override; void printGnuHashTable() override; void printLoadName() override; @@ -324,6 +325,8 @@ public: const Elf_Sym *FirstSym, StringRef StrTable, bool IsDynamic) = 0; virtual void printProgramHeaders(const ELFFile *Obj) = 0; + virtual void printSectionAsString(const ELFFile *Obj, + StringRef SectionName) = 0; virtual void printHashHistogram(const ELFFile *Obj) = 0; virtual void printCGProfile(const ELFFile *Obj) = 0; virtual void printNotes(const ELFFile *Obj) = 0; @@ -355,6 +358,7 @@ public: void printSymtabMessage(const ELFO *Obj, StringRef Name, size_t Offset) override; void printProgramHeaders(const ELFO *Obj) override; + void printSectionAsString(const ELFO *Obj, StringRef SectionName) override; void printHashHistogram(const ELFFile *Obj) override; void printCGProfile(const ELFFile *Obj) override; void printNotes(const ELFFile *Obj) override; @@ -417,6 +421,7 @@ public: void printDynamicSymbols(const ELFO *Obj) override; void printDynamicRelocations(const ELFO *Obj) override; void printProgramHeaders(const ELFO *Obj) override; + void printSectionAsString(const ELFO *Obj, StringRef SectionName) override; void printHashHistogram(const ELFFile *Obj) override; void printCGProfile(const ELFFile *Obj) override; void printNotes(const ELFFile *Obj) override; @@ -1539,6 +1544,11 @@ template void ELFDumper::printProgramHeaders() { ELFDumperStyle->printProgramHeaders(Obj); } +template +void ELFDumper::printSectionAsString(StringRef SectionName) { + ELFDumperStyle->printSectionAsString(Obj, SectionName); +} + template void ELFDumper::printDynamicRelocations() { ELFDumperStyle->printDynamicRelocations(Obj); } @@ -3211,6 +3221,36 @@ void GNUStyle::printProgramHeaders(const ELFO *Obj) { } template +void GNUStyle::printSectionAsString(const ELFO *Obj, + 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)); + OS << "String dump of section '" << SecName << "':\n"; + const char *SecContent = + reinterpret_cast(Obj->base() + Sec->sh_offset); + const char *CurrentWord = SecContent; + const char *SecEnd = SecContent + Sec->sh_size; + while (CurrentWord <= SecEnd) { + size_t WordSize = strnlen(CurrentWord, SecEnd - CurrentWord); + if (!WordSize) { + CurrentWord++; + continue; + } + OS << format("[%6tx]", CurrentWord - SecContent); + OS << format(" %.*s\n", WordSize, CurrentWord); + CurrentWord += WordSize + 1; + } + OS.flush(); +} + +template void GNUStyle::printDynamicRelocation(const ELFO *Obj, Elf_Rela R, bool IsRela) { SmallString<32> RelocName; @@ -4205,6 +4245,38 @@ void LLVMStyle::printProgramHeaders(const ELFO *Obj) { } template +void LLVMStyle::printSectionAsString(const ELFO *Obj, + 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)); + W.startLine() << "String dump of section '" << SecName << "':\n"; + const char *SecContent = + reinterpret_cast(Obj->base() + Sec->sh_offset); + const char *CurrentWord = SecContent; + const char *SecEnd = SecContent + Sec->sh_size; + while (CurrentWord <= SecEnd) { + size_t WordSize = strnlen(CurrentWord, SecEnd - CurrentWord); + if (!WordSize) { + CurrentWord++; + continue; + } + W.startLine() << "[" + << to_string( + format_hex_no_prefix((CurrentWord - SecContent), 6)) + << "]"; + W.startLine() << format(" %.*s\n", WordSize, CurrentWord); + CurrentWord += WordSize + 1; + } +} + +template void LLVMStyle::printHashHistogram(const ELFFile *Obj) { W.startLine() << "Hash Histogram not implemented!\n"; } diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h index e13646588e7..57e59372ee5 100644 --- a/tools/llvm-readobj/ObjDumper.h +++ b/tools/llvm-readobj/ObjDumper.h @@ -13,6 +13,8 @@ #include #include +#include "llvm/ADT/StringRef.h" + namespace llvm { namespace object { class COFFImportFile; @@ -41,6 +43,7 @@ public: virtual void printDynamicTable() { } virtual void printNeededLibraries() { } virtual void printProgramHeaders() { } + virtual void printSectionAsString(StringRef SectionName) {} virtual void printHashTable() { } virtual void printGnuHashTable() { } virtual void printLoadName() {} diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index f871dc90950..22a8fcde391 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -146,6 +146,12 @@ namespace opts { cl::alias ProgramHeadersShort("l", cl::desc("Alias for --program-headers"), cl::aliasopt(ProgramHeaders)); + // -string-dump + cl::list StringDump("string-dump", cl::desc(""), + cl::ZeroOrMore); + cl::alias StringDumpShort("p", cl::desc("Alias for --string-dump"), + cl::aliasopt(StringDump)); + // -hash-table cl::opt HashTable("hash-table", cl::desc("Display ELF hash table")); @@ -417,6 +423,10 @@ static void dumpObject(const ObjectFile *Obj, ScopedPrinter &Writer) { Dumper->printNeededLibraries(); if (opts::ProgramHeaders) Dumper->printProgramHeaders(); + if (!opts::StringDump.empty()) + llvm::for_each(opts::StringDump, [&Dumper](StringRef SectionName) { + Dumper->printSectionAsString(SectionName); + }); if (opts::HashTable) Dumper->printHashTable(); if (opts::GnuHashTable) -- 2.11.0