From 023bb15beaac3744ce3a5d1f750d6e32829c7130 Mon Sep 17 00:00:00 2001 From: Nick Lewycky Date: Mon, 10 Oct 2011 21:21:34 +0000 Subject: [PATCH] Add support for dumping section headers to llvm-objdump. This uses the same flags as binutils objdump but the output is different, not just in format but also showing different sections. Compare its results against readelf, not objdump. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@141579 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Support/Format.h | 62 +++++++++++++++++++++++++ test/Object/objdump-sectionheaders.test | 16 +++++++ tools/llvm-objdump/llvm-objdump.cpp | 40 +++++++++++++++- 3 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 test/Object/objdump-sectionheaders.test diff --git a/include/llvm/Support/Format.h b/include/llvm/Support/Format.h index f64e3db7d65..59812d98f58 100644 --- a/include/llvm/Support/Format.h +++ b/include/llvm/Support/Format.h @@ -126,6 +126,50 @@ public: } }; +/// format_object4 - This is a templated helper class used by the format +/// function that captures the object to be formated and the format string. When +/// actually printed, this synthesizes the string into a temporary buffer +/// provided and returns whether or not it is big enough. +template +class format_object4 : public format_object_base { + T1 Val1; + T2 Val2; + T3 Val3; + T4 Val4; +public: + format_object4(const char *fmt, const T1 &val1, const T2 &val2, + const T3 &val3, const T4 &val4) + : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4) { + } + + virtual int snprint(char *Buffer, unsigned BufferSize) const { + return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4); + } +}; + +/// format_object5 - This is a templated helper class used by the format +/// function that captures the object to be formated and the format string. When +/// actually printed, this synthesizes the string into a temporary buffer +/// provided and returns whether or not it is big enough. +template +class format_object5 : public format_object_base { + T1 Val1; + T2 Val2; + T3 Val3; + T4 Val4; + T5 Val5; +public: + format_object5(const char *fmt, const T1 &val1, const T2 &val2, + const T3 &val3, const T4 &val4, const T5 &val5) + : format_object_base(fmt), Val1(val1), Val2(val2), Val3(val3), Val4(val4), + Val5(val5) { + } + + virtual int snprint(char *Buffer, unsigned BufferSize) const { + return snprintf(Buffer, BufferSize, Fmt, Val1, Val2, Val3, Val4, Val5); + } +}; + /// format - This is a helper function that is used to produce formatted output. /// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; template @@ -149,6 +193,24 @@ template return format_object3(Fmt, Val1, Val2, Val3); } +/// format - This is a helper function that is used to produce formatted output. +/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +template +inline format_object4 format(const char *Fmt, const T1 &Val1, + const T2 &Val2, const T3 &Val3, + const T4 &Val4) { + return format_object4(Fmt, Val1, Val2, Val3, Val4); +} + +/// format - This is a helper function that is used to produce formatted output. +/// This is typically used like: OS << format("%0.4f", myfloat) << '\n'; +template +inline format_object5 format(const char *Fmt,const T1 &Val1, + const T2 &Val2, const T3 &Val3, + const T4 &Val4, const T5 &Val5) { + return format_object5(Fmt, Val1, Val2, Val3, Val4, Val5); +} + } // end namespace llvm #endif diff --git a/test/Object/objdump-sectionheaders.test b/test/Object/objdump-sectionheaders.test new file mode 100644 index 00000000000..4515d00e618 --- /dev/null +++ b/test/Object/objdump-sectionheaders.test @@ -0,0 +1,16 @@ +; RUN: llvm-objdump -h %p/TestObjectFiles/trivial-object-test.elf-x86-64 \ +; RUN: | FileCheck %s + +; To verify this, use readelf -S, not objdump -h. Binutils objdump filters the +; results in a way that we don't emulate. + +; CHECK: Sections: +; CHECK: Idx Name Size Address Type +; CHECK: 0 000000000 00000000000000000 +; CHECK: 1 .text 000000026 00000000000000000 TEXT DATA +; CHECK: 2 .rodata.str1.1 00000000d 00000000000000026 DATA +; CHECK: 3 .note.GNU-stack 000000000 00000000000000033 +; CHECK: 4 .rela.text 000000048 00000000000000038 +; CHECK: 5 .symtab 0000000c0 00000000000000080 +; CHECK: 6 .strtab 000000033 00000000000000140 +; CHECK: 7 .shstrtab 00000004b 00000000000000173 diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp index a8df3e57f98..3acf8084375 100644 --- a/tools/llvm-objdump/llvm-objdump.cpp +++ b/tools/llvm-objdump/llvm-objdump.cpp @@ -73,6 +73,16 @@ cl::opt llvm::ArchName("arch", cl::desc("Target arch to disassemble for, " "see -version for available targets")); +static cl::opt +SectionHeaders("section-headers", cl::desc("Display summaries of the headers " + "for each section.")); +static cl::alias +SectionHeadersShort("headers", cl::desc("Alias for --section-headers"), + cl::aliasopt(SectionHeaders)); +static cl::alias +SectionHeadersShorter("h", cl::desc("Alias for --section-headers"), + cl::aliasopt(SectionHeaders)); + static StringRef ToolName; static bool error(error_code ec) { @@ -281,11 +291,39 @@ static void PrintRelocations(const ObjectFile *o) { } } +static void PrintSectionHeaders(const ObjectFile *o) { + outs() << "Sections:\n" + "Idx Name Size Address Type\n"; + error_code ec; + unsigned i = 0; + for (section_iterator si = o->begin_sections(), se = o->end_sections(); + si != se; si.increment(ec)) { + if (error(ec)) return; + StringRef Name; + if (error(si->getName(Name))) return; + uint64_t Address; + if (error(si->getAddress(Address))) return; + uint64_t Size; + if (error(si->getSize(Size))) return; + bool Text, Data, BSS; + if (error(si->isText(Text))) return; + if (error(si->isData(Data))) return; + if (error(si->isBSS(BSS))) return; + std::string Type = (std::string(Text ? "TEXT " : "") + + (Data ? "DATA " : "") + (BSS ? "BSS" : "")); + outs() << format("%3d %-13s %09x %017x %s\n", i, Name.str().c_str(), Size, + Address, Type.c_str()); + ++i; + } +} + static void DumpObject(const ObjectFile *o) { if (Disassemble) DisassembleObject(o); if (Relocations) PrintRelocations(o); + if (SectionHeaders) + PrintSectionHeaders(o); } /// @brief Dump each object file in \a a; @@ -356,7 +394,7 @@ int main(int argc, char **argv) { if (InputFilenames.size() == 0) InputFilenames.push_back("a.out"); - if (!Disassemble && !Relocations) { + if (!Disassemble && !Relocations && !SectionHeaders) { cl::PrintHelpMessage(); return 2; } -- 2.34.1