1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 10:42:39 +01:00

[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
This commit is contained in:
Hemant Kulkarni 2016-01-26 19:46:39 +00:00
parent 218caa8595
commit e89fec8eee
6 changed files with 110 additions and 10 deletions

View File

@ -80,6 +80,10 @@ input. Otherwise, it will read from the specified ``filenames``.
Display the ELF program headers (only for ELF object files).
.. option:: -elf-section-groups, -g
Display section groups (only for ELF object files).
EXIT STATUS
-----------

Binary file not shown.

View File

@ -0,0 +1,39 @@
# Source file compiled:
##include <iostream>
# #include <typeinfo>
#template <class A>
#void foo(A variable) {
# std::cout << "foo is " << typeid(A).name() << "\n";
#}
#int main () {
# char x = 'x';
# int y = 1;
# foo(x);
# foo(y);
# return 0;
#}
RUN: llvm-readobj -g %p/Inputs/elf-groups.x86_64 \
RUN: | FileCheck %s
CHECK: Groups {
CHECK-NEXT: Group {
CHECK-NEXT: Name: .group (92)
CHECK-NEXT: Index: 1
CHECK-NEXT: Type: COMDAT (0x1)
CHECK-NEXT: Signature: _Z3fooIcEvT_
CHECK-NEXT: Section(s) in group [
CHECK-NEXT: .text._Z3fooIcEvT_ (10)
CHECK-NEXT: .rela.text._Z3fooIcEvT_ (11)
CHECK-NEXT: ]
CHECK-NEXT: }
CHECK-NEXT: Group {
CHECK-NEXT: Name: .group (92)
CHECK-NEXT: Index: 2
CHECK-NEXT: Type: COMDAT (0x1)
CHECK-NEXT: Signature: _Z3fooIiEvT_
CHECK-NEXT: Section(s) in group [
CHECK-NEXT: .text._Z3fooIiEvT_ (12)
CHECK-NEXT: .rela.text._Z3fooIiEvT_ (13)
CHECK-NEXT: ]
CHECK-NEXT: }

View File

@ -59,6 +59,7 @@ public:
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 *getElfSectionType(unsigned Arch, unsigned Type) {
}
}
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 @@ template <class ELFT> void ELFDumper<ELFT>::printStackMap() const {
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";
}

View File

@ -42,6 +42,7 @@ public:
virtual void printGnuHashTable() { }
virtual void printLoadName() {}
virtual void printVersionInfo() {}
virtual void printGroupSections() {}
// Only implemented for ARM ELF at this time.
virtual void printAttributes() { }

View File

@ -227,6 +227,12 @@ namespace opts {
cl::desc("Display ELF version sections (if present)"));
cl::alias VersionInfoShort("V", cl::desc("Alias for -version-info"),
cl::aliasopt(VersionInfo));
cl::opt<bool> SectionGroups("elf-section-groups",
cl::desc("Display ELF section group contents"));
cl::alias SectionGroupsShort("g", cl::desc("Alias for -elf-sections-groups"),
cl::aliasopt(SectionGroups));
} // namespace opts
namespace llvm {
@ -334,16 +340,20 @@ static void dumpObject(const ObjectFile *Obj) {
Dumper->printGnuHashTable();
if (opts::VersionInfo)
Dumper->printVersionInfo();
if (Obj->getArch() == llvm::Triple::arm && Obj->isELF())
if (opts::ARMAttributes)
Dumper->printAttributes();
if (isMipsArch(Obj->getArch()) && Obj->isELF()) {
if (opts::MipsPLTGOT)
Dumper->printMipsPLTGOT();
if (opts::MipsABIFlags)
Dumper->printMipsABIFlags();
if (opts::MipsReginfo)
Dumper->printMipsReginfo();
if (Obj->isELF()) {
if (Obj->getArch() == llvm::Triple::arm)
if (opts::ARMAttributes)
Dumper->printAttributes();
if (isMipsArch(Obj->getArch())) {
if (opts::MipsPLTGOT)
Dumper->printMipsPLTGOT();
if (opts::MipsABIFlags)
Dumper->printMipsABIFlags();
if (opts::MipsReginfo)
Dumper->printMipsReginfo();
}
if (opts::SectionGroups)
Dumper->printGroupSections();
}
if (Obj->isCOFF()) {
if (opts::COFFImports)