Add support for dumping section headers to llvm-objdump. This uses the same
authorNick Lewycky <nicholas@mxc.ca>
Mon, 10 Oct 2011 21:21:34 +0000 (21:21 +0000)
committerNick Lewycky <nicholas@mxc.ca>
Mon, 10 Oct 2011 21:21:34 +0000 (21:21 +0000)
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
test/Object/objdump-sectionheaders.test [new file with mode: 0644]
tools/llvm-objdump/llvm-objdump.cpp

index f64e3db7d6506acb6e7443d5a7a80e2df1c06713..59812d98f5898569ff08884744339ca36d2fd6b8 100644 (file)
@@ -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 <typename T1, typename T2, typename T3, typename T4>
+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 <typename T1, typename T2, typename T3, typename T4, typename T5>
+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 <typename T>
@@ -149,6 +193,24 @@ template <typename T1, typename T2, typename T3>
   return format_object3<T1, T2, T3>(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 <typename T1, typename T2, typename T3, typename T4>
+inline format_object4<T1, T2, T3, T4> format(const char *Fmt, const T1 &Val1,
+                                             const T2 &Val2, const T3 &Val3,
+                                             const T4 &Val4) {
+  return format_object4<T1, T2, T3, T4>(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 <typename T1, typename T2, typename T3, typename T4, typename T5>
+inline format_object5<T1, T2, T3, T4, T5> format(const char *Fmt,const T1 &Val1,
+                                             const T2 &Val2, const T3 &Val3,
+                                             const T4 &Val4, const T5 &Val5) {
+  return format_object5<T1, T2, T3, T4, T5>(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 (file)
index 0000000..4515d00
--- /dev/null
@@ -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 
index a8df3e57f98214434e4abe3078bbaf9db9566ad0..3acf808437581d96c2d35825590af38b97295358 100644 (file)
@@ -73,6 +73,16 @@ cl::opt<std::string>
 llvm::ArchName("arch", cl::desc("Target arch to disassemble for, "
                                 "see -version for available targets"));
 
+static cl::opt<bool>
+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;
   }