diff --git a/llvm/docs/CommandGuide/llvm-readelf.rst b/llvm/docs/CommandGuide/llvm-readelf.rst --- a/llvm/docs/CommandGuide/llvm-readelf.rst +++ b/llvm/docs/CommandGuide/llvm-readelf.rst @@ -142,6 +142,10 @@ When used with :option:`--sections`, display section data for each section shown. This option has no effect for GNU style output. +.. option:: --section-details, -t + + Display all section details. Used as an alternative to :option:`--sections`. + .. option:: --section-mapping Display the section to segment mapping. diff --git a/llvm/test/tools/llvm-readobj/ELF/section-details.test b/llvm/test/tools/llvm-readobj/ELF/section-details.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/section-details.test @@ -0,0 +1,256 @@ +## Check how llvm-readelf prints section details with --section-details. + +## Check the output for the 64-bit case. +# RUN: yaml2obj %s -DBITS=64 -o %t64.o +# RUN: llvm-readelf %t64.o --section-details | \ +# RUN: FileCheck %s --strict-whitespace --match-full-lines --check-prefix=GNU64 + +# GNU64:There are 19 section headers, starting at offset 0xf8: +# GNU64-EMPTY: +# GNU64-NEXT:Section Headers: +# GNU64-NEXT: [Nr] Name +# GNU64-NEXT: Type Address Off Size ES Lk Inf Al +# GNU64-NEXT: Flags +# GNU64-NEXT: [ 0] {{$}} +# GNU64-NEXT: NULL 0000000000000000 000000 000000 00 0 0 0 +# GNU64-NEXT: [0000000000000000]: {{$}} +# GNU64-NEXT: [ 1] allflags_and_long_fields +# GNU64-NEXT: PROGBITS 1111111111111111 2222222222222222 4444444444444444 5555555555555555 858993459 1717986918 8608480567731124087 +# GNU64-NEXT: [ffffffffffffffff]: WRITE, ALLOC, EXEC, MERGE, STRINGS, INFO LINK, LINK ORDER, OS NONCONF, GROUP, TLS, COMPRESSED, EXCLUDE, OS (000000000ff00000), PROC (0000000070000000), UNKNOWN (ffffffff000ff008) +# GNU64-NEXT: [ 2] noflags +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [0000000000000000]: {{$}} +# GNU64-NEXT: [ 3] write +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [0000000000000001]: WRITE +# GNU64-NEXT: [ 4] alloc +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [0000000000000002]: ALLOC +# GNU64-NEXT: [ 5] exec +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [0000000000000004]: EXEC +# GNU64-NEXT: [ 6] merge +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [0000000000000010]: MERGE +# GNU64-NEXT: [ 7] strings +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [0000000000000020]: STRINGS +# GNU64-NEXT: [ 8] infolink +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [0000000000000040]: INFO LINK +# GNU64-NEXT: [ 9] linkorder +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [0000000000000080]: LINK ORDER +# GNU64-NEXT: [10] nonconforming +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [0000000000000100]: OS NONCONF +# GNU64-NEXT: [11] group +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [0000000000000200]: GROUP +# GNU64-NEXT: [12] tls +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [0000000000000400]: TLS +# GNU64-NEXT: [13] compressed +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [0000000000000800]: COMPRESSED +# GNU64-NEXT: [14] exclude +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [0000000080000000]: EXCLUDE +# GNU64-NEXT: [15] known_and_unknown +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [00000000000f0003]: WRITE, ALLOC, UNKNOWN (00000000000f0000) +# GNU64-NEXT: [16] only_unknown +# GNU64-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# GNU64-NEXT: [00000000000f0000]: UNKNOWN (00000000000f0000) +# GNU64-NEXT: [17] .strtab +# GNU64-NEXT: STRTAB 0000000000000000 000040 000001 00 0 0 1 +# GNU64-NEXT: [0000000000000000]: {{$}} +# GNU64-NEXT: [18] .shstrtab +# GNU64-NEXT: STRTAB 0000000000000000 000041 0000b0 00 0 0 1 +# GNU64-NEXT: [0000000000000000]: {{$}} +# GNU64-NOT:{{.}} + +--- !ELF +FileHeader: + Class: ELFCLASS[[BITS]] + Data: ELFDATA2LSB + Type: ET_REL + Flags: [] +Sections: + - Name: allflags_and_long_fields + Type: SHT_PROGBITS + ShFlags: 0xffffffffffffffff + Address: 0x1111111111111111 + ShOffset: 0x2222222222222222 + Link: 0x33333333 + ShSize: 0x4444444444444444 + EntSize: 0x5555555555555555 + Info: 0x66666666 + ShAddrAlign: 0x7777777777777777 + - Name: noflags + Type: SHT_PROGBITS + Flags: [ ] + - Name: write + Type: SHT_PROGBITS + Flags: [ SHF_WRITE ] + - Name: alloc + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC ] + - Name: exec + Type: SHT_PROGBITS + Flags: [ SHF_EXECINSTR ] + - Name: merge + Type: SHT_PROGBITS + Flags: [ SHF_MERGE ] + - Name: strings + Type: SHT_PROGBITS + Flags: [ SHF_STRINGS ] + - Name: infolink + Type: SHT_PROGBITS + Flags: [ SHF_INFO_LINK ] + - Name: linkorder + Type: SHT_PROGBITS + Flags: [ SHF_LINK_ORDER ] + - Name: nonconforming + Type: SHT_PROGBITS + Flags: [ SHF_OS_NONCONFORMING ] + - Name: group + Type: SHT_PROGBITS + Flags: [ SHF_GROUP ] + - Name: tls + Type: SHT_PROGBITS + Flags: [ SHF_TLS ] + - Name: compressed + Type: SHT_PROGBITS + Flags: [ SHF_COMPRESSED ] + - Name: exclude + Type: SHT_PROGBITS + Flags: [ SHF_EXCLUDE ] + - Name: known_and_unknown + Type: SHT_PROGBITS + ShFlags: 0x000f0003 + - Name: only_unknown + Type: SHT_PROGBITS + ShFlags: 0x000f0000 + +## Check the output for the 32-bit case. +# RUN: yaml2obj %s -DBITS=32 -o %t32.o +# RUN: llvm-readelf %t32.o --section-details | \ +# RUN: FileCheck %s --strict-whitespace --match-full-lines --check-prefix=GNU32 + +# GNU32:There are 19 section headers, starting at offset 0xe8: +# GNU32-EMPTY: +# GNU32-NEXT:Section Headers: +# GNU32-NEXT: [Nr] Name +# GNU32-NEXT: Type Addr Off Size ES Lk Inf Al +# GNU32-NEXT: Flags +# GNU32-NEXT: [ 0] {{$}} +# GNU32-NEXT: NULL 00000000 000000 000000 00 0 0 0 +# GNU32-NEXT: [00000000]: {{$}} +# GNU32-NEXT: [ 1] allflags_and_long_fields +# GNU32-NEXT: PROGBITS 11111111 22222222 44444444 55555555 858993459 1717986918 2004318071 +# GNU32-NEXT: [ffffffff]: WRITE, ALLOC, EXEC, MERGE, STRINGS, INFO LINK, LINK ORDER, OS NONCONF, GROUP, TLS, COMPRESSED, EXCLUDE, OS (0ff00000), PROC (70000000), UNKNOWN (000ff008) +# GNU32-NEXT: [ 2] noflags +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [00000000]: {{$}} +# GNU32-NEXT: [ 3] write +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [00000001]: WRITE +# GNU32-NEXT: [ 4] alloc +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [00000002]: ALLOC +# GNU32-NEXT: [ 5] exec +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [00000004]: EXEC +# GNU32-NEXT: [ 6] merge +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [00000010]: MERGE +# GNU32-NEXT: [ 7] strings +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [00000020]: STRINGS +# GNU32-NEXT: [ 8] infolink +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [00000040]: INFO LINK +# GNU32-NEXT: [ 9] linkorder +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [00000080]: LINK ORDER +# GNU32-NEXT: [10] nonconforming +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [00000100]: OS NONCONF +# GNU32-NEXT: [11] group +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [00000200]: GROUP +# GNU32-NEXT: [12] tls +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [00000400]: TLS +# GNU32-NEXT: [13] compressed +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [00000800]: COMPRESSED +# GNU32-NEXT: [14] exclude +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [80000000]: EXCLUDE +# GNU32-NEXT: [15] known_and_unknown +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [000f0003]: WRITE, ALLOC, UNKNOWN (000f0000) +# GNU32-NEXT: [16] only_unknown +# GNU32-NEXT: PROGBITS 00000000 000034 000000 00 0 0 0 +# GNU32-NEXT: [000f0000]: UNKNOWN (000f0000) +# GNU32-NEXT: [17] .strtab +# GNU32-NEXT: STRTAB 00000000 000034 000001 00 0 0 1 +# GNU32-NEXT: [00000000]: {{$}} +# GNU32-NEXT: [18] .shstrtab +# GNU32-NEXT: STRTAB 00000000 000035 0000b0 00 0 0 1 +# GNU32-NEXT: [00000000]: {{$}} +# GNU32-NOT:{{.}} + +## When --section-details and --sections are both specified, --sections is ignored. +# RUN: llvm-readelf %t64.o --section-details --sections | FileCheck %s --check-prefix=GNU64 +# RUN: llvm-readelf %t64.o --sections --section-details | FileCheck %s --check-prefix=GNU64 + +## Check that we produce the same output with -t (alias). +# RUN: llvm-readelf --section-details %t64.o > %t.readelf.full +# RUN: llvm-readelf -t %t64.o > %t.readelf.alias +# RUN: cmp %t.readelf.full %t.readelf.alias + +## Check how we dump sections when the section header string table can't be read. + +# RUN: yaml2obj --docnum=2 %s -o %tshstrndx.o +# RUN: llvm-readelf %tshstrndx.o --section-details 2>&1 | \ +# RUN: FileCheck %s -DFILE=%tshstrndx.o --check-prefix=SHSTRNDX + +# SHSTRNDX: Section Headers: +# SHSTRNDX-NEXT: [Nr] Name +# SHSTRNDX-NEXT: Type Address Off Size ES Lk Inf Al +# SHSTRNDX-NEXT: Flags +# SHSTRNDX-NEXT: warning: '[[FILE]]': section header string table index 65279 does not exist +# SHSTRNDX-NEXT: [ 0] +# SHSTRNDX-NEXT: NULL 0000000000000000 000000 000000 00 0 0 0 +# SHSTRNDX-NEXT: [0000000000000000]: +# SHSTRNDX-NEXT: warning: '[[FILE]]': a section [index 1] has an invalid sh_name (0x5) offset which goes past the end of the section name string table +# SHSTRNDX-NEXT: [ 1] +# SHSTRNDX-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# SHSTRNDX-NEXT: [0000000000000000]: +# SHSTRNDX-NEXT: warning: '[[FILE]]': a section [index 2] has an invalid sh_name (0x1) offset which goes past the end of the section name string table +# SHSTRNDX-NEXT: [ 2] +# SHSTRNDX-NEXT: PROGBITS 0000000000000000 000040 000000 00 0 0 0 +# SHSTRNDX-NEXT: [0000000000000000]: +# SHSTRNDX-NEXT: warning: '[[FILE]]': a section [index 3] has an invalid sh_name (0x13) offset which goes past the end of the section name string table +# SHSTRNDX-NEXT: [ 3] +# SHSTRNDX-NEXT: STRTAB 0000000000000000 000040 000001 00 0 0 1 +# SHSTRNDX-NEXT: [0000000000000000]: +# SHSTRNDX-NEXT: warning: '[[FILE]]': a section [index 4] has an invalid sh_name (0x9) offset which goes past the end of the section name string table +# SHSTRNDX-NEXT: [ 4] +# SHSTRNDX-NEXT: STRTAB 0000000000000000 000041 00001b 00 0 0 1 +# SHSTRNDX-NEXT: [0000000000000000]: + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + EShStrNdx: 0xfeff +Sections: + - Name: foo + Type: SHT_PROGBITS + - Name: bar + Type: SHT_PROGBITS diff --git a/llvm/test/tools/llvm-readobj/ELF/symbols.test b/llvm/test/tools/llvm-readobj/ELF/symbols.test --- a/llvm/test/tools/llvm-readobj/ELF/symbols.test +++ b/llvm/test/tools/llvm-readobj/ELF/symbols.test @@ -78,9 +78,7 @@ # RUN: llvm-readelf --symbols %t64 > %t.symbols.gnu # RUN: llvm-readelf --syms %t64 > %t.syms.gnu # RUN: cmp %t.symbols.gnu %t.syms.gnu -## There is no -t option in llvm-readelf. -# RUN: not llvm-readelf -t %t64 2>&1 | FileCheck %s --check-prefix=NO-T-ERR -# NO-T-ERR: Unknown command line argument '-t' + ## -s is an llvm-readobj option to dump sections. # RUN: llvm-readobj -s --elf-output-style=GNU %t64 | FileCheck %s --implicit-check-not="Symbol table" diff --git a/llvm/test/tools/llvm-readobj/basic.test b/llvm/test/tools/llvm-readobj/basic.test --- a/llvm/test/tools/llvm-readobj/basic.test +++ b/llvm/test/tools/llvm-readobj/basic.test @@ -41,5 +41,5 @@ OBJ: -s - Alias for --section-headers OBJ: -t - Alias for --symbols ELF: -s - Alias for --symbols -ELF-NOT: {{ }}-t{{ }} +ELF: -t - Alias for --section-details HELP: @FILE diff --git a/llvm/tools/llvm-readobj/ELFDumper.cpp b/llvm/tools/llvm-readobj/ELFDumper.cpp --- a/llvm/tools/llvm-readobj/ELFDumper.cpp +++ b/llvm/tools/llvm-readobj/ELFDumper.cpp @@ -239,6 +239,7 @@ void printDynamicRelocations() override; void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) override; void printHashSymbols() override; + void printSectionDetails() override; void printUnwindInfo() override; void printDynamicTable() override; @@ -736,6 +737,7 @@ virtual void printSectionHeaders() = 0; virtual void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) = 0; virtual void printHashSymbols() {} + virtual void printSectionDetails() {} virtual void printDependentLibs() = 0; virtual void printDynamic() {} virtual void printDynamicRelocations() = 0; @@ -814,6 +816,7 @@ void printSectionHeaders() override; void printSymbols(bool PrintSymbols, bool PrintDynamicSymbols) override; void printHashSymbols() override; + void printSectionDetails() override; void printDependentLibs() override; void printDynamic() override; void printDynamicRelocations() override; @@ -2305,6 +2308,10 @@ ELFDumperStyle->printHashSymbols(); } +template void ELFDumper::printSectionDetails() { + ELFDumperStyle->printSectionDetails(); +} + template void ELFDumper::printHashHistograms() { ELFDumperStyle->printHashHistograms(); } @@ -4159,6 +4166,115 @@ } } +template void GNUStyle::printSectionDetails() { + ArrayRef Sections = cantFail(this->Obj.sections()); + OS << "There are " << to_string(Sections.size()) + << " section headers, starting at offset " + << "0x" << to_hexString(this->Obj.getHeader().e_shoff, false) << ":\n\n"; + + OS << "Section Headers:\n"; + + auto PrintFields = [&](ArrayRef V) { + for (const Field &F : V) + printField(F); + OS << "\n"; + }; + + PrintFields({{"[Nr]", 2}, {"Name", 7}}); + + constexpr bool Is64 = ELFT::Is64Bits; + PrintFields({{"Type", 7}, + {Is64 ? "Address" : "Addr", 23}, + {"Off", Is64 ? 40 : 32}, + {"Size", Is64 ? 47 : 39}, + {"ES", Is64 ? 54 : 46}, + {"Lk", Is64 ? 59 : 51}, + {"Inf", Is64 ? 62 : 54}, + {"Al", Is64 ? 66 : 57}}); + PrintFields({{"Flags", 7}}); + + StringRef SecStrTable; + if (Expected SecStrTableOrErr = this->Obj.getSectionStringTable( + Sections, this->dumper().WarningHandler)) + SecStrTable = *SecStrTableOrErr; + else + this->reportUniqueWarning(SecStrTableOrErr.takeError()); + + size_t SectionIndex = 0; + const unsigned AddrSize = Is64 ? 16 : 8; + for (const Elf_Shdr &S : Sections) { + StringRef Name = ""; + if (Expected NameOrErr = + this->Obj.getSectionName(S, SecStrTable)) + Name = *NameOrErr; + else + this->reportUniqueWarning(NameOrErr.takeError()); + + OS.PadToColumn(2); + OS << "[" << right_justify(to_string(SectionIndex), 2) << "]"; + PrintFields({{Name, 7}}); + PrintFields( + {{getSectionTypeString(this->Obj.getHeader().e_machine, S.sh_type), 7}, + {to_string(format_hex_no_prefix(S.sh_addr, AddrSize)), 23}, + {to_string(format_hex_no_prefix(S.sh_offset, 6)), Is64 ? 39 : 32}, + {to_string(format_hex_no_prefix(S.sh_size, 6)), Is64 ? 47 : 39}, + {to_string(format_hex_no_prefix(S.sh_entsize, 2)), Is64 ? 54 : 46}, + {to_string(S.sh_link), Is64 ? 59 : 51}, + {to_string(S.sh_info), Is64 ? 63 : 55}, + {to_string(S.sh_addralign), Is64 ? 66 : 58}}); + + OS.PadToColumn(7); + OS << "[" << to_string(format_hex_no_prefix(S.sh_flags, AddrSize)) << "]: "; + + DenseMap FlagToName = { + {SHF_WRITE, "WRITE"}, {SHF_ALLOC, "ALLOC"}, + {SHF_EXECINSTR, "EXEC"}, {SHF_MERGE, "MERGE"}, + {SHF_STRINGS, "STRINGS"}, {SHF_INFO_LINK, "INFO LINK"}, + {SHF_LINK_ORDER, "LINK ORDER"}, {SHF_OS_NONCONFORMING, "OS NONCONF"}, + {SHF_GROUP, "GROUP"}, {SHF_TLS, "TLS"}, + {SHF_COMPRESSED, "COMPRESSED"}, {SHF_EXCLUDE, "EXCLUDE"}}; + + uint64_t Flags = S.sh_flags; + uint64_t UnknownFlags = 0; + bool NeedsComma = false; + while (Flags) { + // Take the least significant bit as a flag. + uint64_t Flag = Flags & -Flags; + Flags -= Flag; + + auto It = FlagToName.find(Flag); + if (It != FlagToName.end()) { + if (NeedsComma) + OS << ", "; + NeedsComma = true; + OS << It->second; + } else { + UnknownFlags |= Flag; + } + } + + auto PrintUnknownFlags = [&](uint64_t Mask, StringRef Name) { + uint64_t FlagsToPrint = UnknownFlags & Mask; + if (!FlagsToPrint) + return; + + if (NeedsComma) + OS << ", "; + OS << Name << " (" + << to_string(format_hex_no_prefix(FlagsToPrint, AddrSize)) << ")"; + UnknownFlags &= ~Mask; + NeedsComma = true; + }; + + PrintUnknownFlags(SHF_MASKOS, "OS"); + PrintUnknownFlags(SHF_MASKPROC, "PROC"); + PrintUnknownFlags(uint64_t(-1), "UNKNOWN"); + + OS << "\n"; + ++SectionIndex; + } +} + static inline std::string printPhdrFlags(unsigned Flag) { std::string Str; Str = (Flag & PF_R) ? "R" : " "; diff --git a/llvm/tools/llvm-readobj/ObjDumper.h b/llvm/tools/llvm-readobj/ObjDumper.h --- a/llvm/tools/llvm-readobj/ObjDumper.h +++ b/llvm/tools/llvm-readobj/ObjDumper.h @@ -72,7 +72,8 @@ virtual void printNotes() {} virtual void printELFLinkerOptions() {} virtual void printStackSizes() {} - virtual void printArchSpecificInfo() { } + virtual void printSectionDetails() {} + virtual void printArchSpecificInfo() {} // Only implemented for PE/COFF. virtual void printCOFFImports() { } diff --git a/llvm/tools/llvm-readobj/llvm-readobj.cpp b/llvm/tools/llvm-readobj/llvm-readobj.cpp --- a/llvm/tools/llvm-readobj/llvm-readobj.cpp +++ b/llvm/tools/llvm-readobj/llvm-readobj.cpp @@ -137,6 +137,11 @@ cl::opt DynRelocs("dyn-relocations", cl::desc("Display the dynamic relocation entries in the file")); + // --section-details + // Also -t in llvm-readelf mode. + cl::opt SectionDetails("section-details", + cl::desc("Display the section details")); + // --symbols // Also -s in llvm-readelf mode, or -t in llvm-readobj mode. cl::opt @@ -480,8 +485,14 @@ if (opts::FileHeaders) Dumper->printFileHeaders(); - if (opts::SectionHeaders) - Dumper->printSectionHeaders(); + + if (opts::SectionDetails || opts::SectionHeaders) { + if (opts::Output == opts::GNU && opts::SectionDetails) + Dumper->printSectionDetails(); + else + Dumper->printSectionHeaders(); + } + if (opts::HashSymbols) Dumper->printHashSymbols(); if (opts::ProgramHeaders || opts::SectionMapping == cl::BOU_TRUE) @@ -656,8 +667,7 @@ cl::aliasopt(opts::SectionHeaders), cl::NotHidden); - // Only register -t in llvm-readobj, as readelf reserves it for - // --section-details (not implemented yet). + // llvm-readelf reserves it for --section-details. static cl::alias SymbolsShort("t", cl::desc("Alias for --symbols"), cl::aliasopt(opts::Symbols), cl::NotHidden); @@ -683,6 +693,11 @@ cl::aliasopt(opts::Symbols), cl::NotHidden, cl::Grouping); + // -t is here because for readobj it is an alias for --symbols. + static cl::alias SectionDetailsShort( + "t", cl::desc("Alias for --section-details"), + cl::aliasopt(opts::SectionDetails), cl::NotHidden); + // Allow all single letter flags to be grouped together. for (auto &OptEntry : cl::getRegisteredOptions()) { StringRef ArgName = OptEntry.getKey();