[llvm-readobj] Add -elf-section-groups option

Adds a way to inspect SHT_GROUP sections in ELF objects.
Displays signature, member sections of these sections.

Differential revision: http://reviews.llvm.org/D16555

llvm-svn: 258845
diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp
index f6ec977..fac6bf4 100644
--- a/llvm/tools/llvm-readobj/ELFDumper.cpp
+++ b/llvm/tools/llvm-readobj/ELFDumper.cpp
@@ -59,6 +59,7 @@
   void printGnuHashTable() override;
   void printLoadName() override;
   void printVersionInfo() override;
+  void printGroupSections() override;
 
   void printAttributes() override;
   void printMipsPLTGOT() override;
@@ -792,6 +793,13 @@
   }
 }
 
+static const char *getGroupType(uint32_t Flag) {
+  if (Flag & ELF::GRP_COMDAT)
+    return "COMDAT";
+  else
+    return "(unknown)";
+}
+
 static const EnumEntry<unsigned> ElfSectionFlags[] = {
   LLVM_READOBJ_ENUM_ENT(ELF, SHF_WRITE           ),
   LLVM_READOBJ_ENUM_ENT(ELF, SHF_ALLOC           ),
@@ -2250,3 +2258,41 @@
               llvm::outs(),
               StackMapV1Parser<ELFT::TargetEndianness>(*StackMapContentsArray));
 }
+template <class ELFT> void ELFDumper<ELFT>::printGroupSections() {
+  DictScope Lists(W, "Groups");
+  uint32_t SectionIndex = 0;
+  bool HasGroups = false;
+  for (const Elf_Shdr &Sec : Obj->sections()) {
+    if (Sec.sh_type == ELF::SHT_GROUP) {
+      HasGroups = true;
+      ErrorOr<const Elf_Shdr *> Symtab =
+          errorOrDefault(Obj->getSection(Sec.sh_link));
+      ErrorOr<StringRef> StrTableOrErr = Obj->getStringTableForSymtab(**Symtab);
+      error(StrTableOrErr.getError());
+      StringRef StrTable = *StrTableOrErr;
+      const Elf_Sym *Sym =
+          Obj->template getEntry<Elf_Sym>(*Symtab, Sec.sh_info);
+      auto Data = errorOrDefault(
+          Obj->template getSectionContentsAsArray<Elf32_Word>(&Sec));
+      DictScope D(W, "Group");
+      StringRef Name = errorOrDefault(Obj->getSectionName(&Sec));
+      W.printNumber("Name", Name, Sec.sh_name);
+      W.printNumber("Index", SectionIndex);
+      W.printHex("Type", getGroupType(Data[0]), Data[0]);
+      W.startLine() << "Signature: " << StrTable.data() + Sym->st_name << "\n";
+      {
+        ListScope L(W, "Section(s) in group");
+        int Member = 1;
+        while (Member < Data.size()) {
+          auto Sec = errorOrDefault(Obj->getSection(Data[Member]));
+          const StringRef Name = errorOrDefault(Obj->getSectionName(Sec));
+          W.startLine() << Name << " (" << std::to_string(Data[Member++])
+                        << ")\n";
+        }
+      }
+    }
+    ++SectionIndex;
+  }
+  if (!HasGroups)
+    W.startLine() << "There are no group sections in the file.\n";
+}