From e89fec8eee4f94f8ccce9db85eb1a6ee2324ae67 Mon Sep 17 00:00:00 2001 From: Hemant Kulkarni Date: Tue, 26 Jan 2016 19:46:39 +0000 Subject: [PATCH] [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 --- docs/CommandGuide/llvm-readobj.rst | 4 ++ .../llvm-readobj/Inputs/elf-groups.x86_64 | Bin 0 -> 4384 bytes test/tools/llvm-readobj/elf-groups.test | 39 +++++++++++++++ tools/llvm-readobj/ELFDumper.cpp | 46 ++++++++++++++++++ tools/llvm-readobj/ObjDumper.h | 1 + tools/llvm-readobj/llvm-readobj.cpp | 30 ++++++++---- 6 files changed, 110 insertions(+), 10 deletions(-) create mode 100644 test/tools/llvm-readobj/Inputs/elf-groups.x86_64 create mode 100644 test/tools/llvm-readobj/elf-groups.test diff --git a/docs/CommandGuide/llvm-readobj.rst b/docs/CommandGuide/llvm-readobj.rst index b1918b548f8..417fcd05c8a 100644 --- a/docs/CommandGuide/llvm-readobj.rst +++ b/docs/CommandGuide/llvm-readobj.rst @@ -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 ----------- diff --git a/test/tools/llvm-readobj/Inputs/elf-groups.x86_64 b/test/tools/llvm-readobj/Inputs/elf-groups.x86_64 new file mode 100644 index 0000000000000000000000000000000000000000..29628ca09b023655dbacef36796901f61602fd4c GIT binary patch literal 4384 zcmcIn-ES0C6rXKTssgPb2tvXJAN)u@6I{h+uPa1_;Hdu=iJ}< zym#)Nx%-|o@_I+1&}lIhtXHjqOfvkw=6&CNbgynn&H_I=NVyTH~+{M~N_QnszBdq))R z*CHvCrn8d8n;^2g_kWDlFz*@#kLmEoLzC7?E9bQYtAmaa~LPOy6<#d{qsf2?KWqZy07ns zH0Lb2b8eS=^*g*5w|Q#uSG>kGoB)y+FWjAo<6@K)Exd4{pyF32i!)(8iQ;N;z&>L4 z6`xQ2$>iV}XT&*HcD#WjeFrC^s$Y45e4b*z&UepPg+@|@<9__1w0 zA9f6HeUwD#27wU`;9=;-fDwgw7`hrTqCDNrOl6${H~c!w#*c>L79mLbqVU>jOB+(RhlKS=Za?P?Q z>oHh0PDA^|=-FOU1n;nAIOR>$DW+v7Q%PD+{c)0nUzt|(OMdF>fxYts^vX(+Gc)Gp z-~riTPTGs`cK#!9BGUc0(_H+7xAQ-zye+GX zIr8tw@jpx$ehoN(I$h+6I)|E~N0TA;(U4kn)gYQ85%eJBhn>`evkv;02J){pW`IN= zWo*OK%ypbB5VM^>V(Vo3kCHNP{hzSYTe>sJ=K4#7nK9uq#p|EPgb3?Lo#y({?p6K{ z5_ICi)$duu&HVTlsQiZiGUs1lU*tzSGxOgfEH8iUZ|47${PXhP?j{A%f_i4_$5}S> z<4ot}|B3Ufp2ac1%=Q1s{x4}Z5PNw)^cD`B!>)0hdu)|?eg@fJ>V+@JoFiV|`)_ce za?Y{;fW%+$mkC3RJ{md=aei9|NjB>bG)y4&an<)OW{`Uzp_Z}{N4E~IXMrQr!6K3r&KgTcrHY<@2{nyNYld!z}J-FNv z9WW9a)66L6`59rGtlw8n)pY_osEX69P~TmWFVZMjn;C7rrKdx#4}UiEw0;P_7D+5gZ6@1TP6?7wPbUv7hc z(+0QNUE~Nar-Ml?MGD# zJ64J)+NC7+ru^!qN~khbl2SSC?+>OZa$5JJG${p+bB3@1T16CiG2Qw?f4UTmc~1GT zclu81#=7`b!0RPQ!6p1(#n8&Qt5xoZY?Pf_Ai%hS=l0 zfMCB%N!jCBmd!Z58op1nKf*HN@1-H}xs9p#=)poFBYx}GU|EtEanLg*4*t`CU@tXe zeiRQP*zcer_6|TIGtS8jR&kJ5I?tPooA&yCO3g5pU;IC*{~68&_J7wesZb}@dYXYE mbF5eP0MIKM{s_xp=QR8=4No;(_6pFvhRZhw&=(r6*Yg*1ZS1N5 literal 0 HcmV?d00001 diff --git a/test/tools/llvm-readobj/elf-groups.test b/test/tools/llvm-readobj/elf-groups.test new file mode 100644 index 00000000000..e41b9dd977d --- /dev/null +++ b/test/tools/llvm-readobj/elf-groups.test @@ -0,0 +1,39 @@ +# Source file compiled: +##include +# #include +#template +#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: } + diff --git a/tools/llvm-readobj/ELFDumper.cpp b/tools/llvm-readobj/ELFDumper.cpp index f6ec9770d80..fac6bf4296e 100644 --- a/tools/llvm-readobj/ELFDumper.cpp +++ b/tools/llvm-readobj/ELFDumper.cpp @@ -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 ElfSectionFlags[] = { LLVM_READOBJ_ENUM_ENT(ELF, SHF_WRITE ), LLVM_READOBJ_ENUM_ENT(ELF, SHF_ALLOC ), @@ -2250,3 +2258,41 @@ template void ELFDumper::printStackMap() const { llvm::outs(), StackMapV1Parser(*StackMapContentsArray)); } +template void ELFDumper::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 Symtab = + errorOrDefault(Obj->getSection(Sec.sh_link)); + ErrorOr StrTableOrErr = Obj->getStringTableForSymtab(**Symtab); + error(StrTableOrErr.getError()); + StringRef StrTable = *StrTableOrErr; + const Elf_Sym *Sym = + Obj->template getEntry(*Symtab, Sec.sh_info); + auto Data = errorOrDefault( + Obj->template getSectionContentsAsArray(&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"; +} diff --git a/tools/llvm-readobj/ObjDumper.h b/tools/llvm-readobj/ObjDumper.h index db26d698355..b83b8d49f22 100644 --- a/tools/llvm-readobj/ObjDumper.h +++ b/tools/llvm-readobj/ObjDumper.h @@ -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() { } diff --git a/tools/llvm-readobj/llvm-readobj.cpp b/tools/llvm-readobj/llvm-readobj.cpp index fa8fee2b03a..790b1d59550 100644 --- a/tools/llvm-readobj/llvm-readobj.cpp +++ b/tools/llvm-readobj/llvm-readobj.cpp @@ -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 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)