Index: test/tools/llvm-readobj/dyn-symbols.test =================================================================== --- /dev/null +++ test/tools/llvm-readobj/dyn-symbols.test @@ -0,0 +1,163 @@ +RUN: llvm-readobj --dyn-symbols %p/Inputs/dynamic-table-so.x86 | FileCheck %s + +# Check the two-letter aliases -dt is equivalent to --dyn-symbols +# full flag names. +RUN: llvm-readobj -dt %p/Inputs/dynamic-table-so.x86 > %t.readobj-dt-alias +RUN: llvm-readobj --dyn-symbols %p/Inputs/dynamic-table-so.x86 > %t.readobj-dt-no-alias +RUN: cmp %t.readobj-dt-alias %t.readobj-dt-no-alias + +# CHECK: DynamicSymbols [ +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: +# CHECK-NEXT: Value: 0x618 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local +# CHECK-NEXT: Type: Section +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .init +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: +# CHECK-NEXT: Value: 0x200DC0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Local +# CHECK-NEXT: Type: Section +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .tbss +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: _ITM_deregisterTMCloneTable +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Weak +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: puts@GLIBC_2.2.5 +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: __tls_get_addr@GLIBC_2.3 +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: __gmon_start__ +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Weak +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: _Jv_RegisterClasses +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Weak +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: _ITM_registerTMCloneTable +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Weak +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: __cxa_finalize@GLIBC_2.2.5 +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Weak +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: Undefined +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: _edata +# CHECK-NEXT: Value: 0x201030 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .data +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: foo +# CHECK-NEXT: Value: 0x0 +# CHECK-NEXT: Size: 4 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: TLS +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .tbss +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: _end +# CHECK-NEXT: Value: 0x201038 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .bss +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: __bss_start +# CHECK-NEXT: Value: 0x201030 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: None +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .bss +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: main +# CHECK-NEXT: Value: 0x780 +# CHECK-NEXT: Size: 59 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .text +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: _init +# CHECK-NEXT: Value: 0x618 +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .init +# CHECK-NEXT: } +# CHECK-NEXT: Symbol { +# CHECK-NEXT: Name: _fini +# CHECK-NEXT: Value: 0x7BC +# CHECK-NEXT: Size: 0 +# CHECK-NEXT: Binding: Global +# CHECK-NEXT: Type: Function +# CHECK-NEXT: Other: 0 +# CHECK-NEXT: Section: .fini +# CHECK-NEXT: } +# CHECK-NEXT: ] Index: test/tools/llvm-readobj/merged.test =================================================================== --- /dev/null +++ test/tools/llvm-readobj/merged.test @@ -0,0 +1,13 @@ +# Check merged args produce identical output to when not merged. +RUN: llvm-readelf -aeWhSrnudlVgIs %p/Inputs/trivial.obj.elf-i386 > %t.merged +RUN: llvm-readelf -a -e -W -h -S -r -n -u -d -l -V -g -I -s %p/Inputs/trivial.obj.elf-i386 > %t.not-merged +RUN: cmp %t.merged %t.not-merged +RUN: FileCheck %s --input-file %t.merged + +# llvm-readobj does not support merged args, because it also supports some old +# flags (-st, -sd, etc.), and it would be confusing if only some merged args +# were supported. +RUN: not llvm-readobj -aeWhSrnudlVgIs %p/Inputs/trivial.obj.elf-i386 2>&1 | FileCheck %s --check-prefix=UNKNOWN + +CHECK-NOT: Unknown command line argument +UNKNOWN: Unknown command line argument Index: test/tools/llvm-readobj/sections-ext.test =================================================================== --- test/tools/llvm-readobj/sections-ext.test +++ test/tools/llvm-readobj/sections-ext.test @@ -13,6 +13,20 @@ RUN: llvm-readobj -expand-relocs -s -st -sr -sd %p/Inputs/trivial.obj.macho-arm \ RUN: | FileCheck %s -check-prefix MACHO-ARM +# Check the two-letter aliases above (-st, -sr, -sd) are equivalent to their +# full flag names. +RUN: llvm-readobj -s -st %p/Inputs/trivial.obj.elf-i386 > %t.readobj-st-alias +RUN: llvm-readobj -s --section-symbols %p/Inputs/trivial.obj.elf-i386 > %t.readobj-st-no-alias +RUN: cmp %t.readobj-st-alias %t.readobj-st-no-alias + +RUN: llvm-readobj -s -sr %p/Inputs/trivial.obj.elf-i386 > %t.readobj-sr-alias +RUN: llvm-readobj -s --section-relocations %p/Inputs/trivial.obj.elf-i386 > %t.readobj-sr-no-alias +RUN: cmp %t.readobj-sr-alias %t.readobj-sr-no-alias + +RUN: llvm-readobj -s -sd %p/Inputs/trivial.obj.elf-i386 > %t.readobj-sd-alias +RUN: llvm-readobj -s --section-data %p/Inputs/trivial.obj.elf-i386 > %t.readobj-sd-no-alias +RUN: cmp %t.readobj-sd-alias %t.readobj-sd-no-alias + COFF: Sections [ COFF-NEXT: Section { COFF-NEXT: Number: 1 Index: tools/llvm-readobj/llvm-readobj.cpp =================================================================== --- tools/llvm-readobj/llvm-readobj.cpp +++ tools/llvm-readobj/llvm-readobj.cpp @@ -92,26 +92,20 @@ cl::desc("Alias for --section-headers"), cl::aliasopt(SectionHeaders), cl::NotHidden); - // -section-relocations, -sr + // -section-relocations + // Also -sr in llvm-readobj mode. cl::opt SectionRelocations("section-relocations", cl::desc("Display relocations for each section shown.")); - cl::alias SectionRelocationsShort("sr", - cl::desc("Alias for --section-relocations"), - cl::aliasopt(SectionRelocations)); - // -section-symbols, -st + // -section-symbols + // Also -st in llvm-readobj mode. cl::opt SectionSymbols("section-symbols", cl::desc("Display symbols for each section shown.")); - cl::alias SectionSymbolsShort("st", - cl::desc("Alias for --section-symbols"), - cl::aliasopt(SectionSymbols)); - // -section-data, -sd + // -section-data + // Also -sd in llvm-readobj mode. cl::opt SectionData("section-data", cl::desc("Display section data for each section shown.")); - cl::alias SectionDataShort("sd", - cl::desc("Alias for --section-data"), - cl::aliasopt(SectionData)); // -relocations, -relocs, -r cl::opt Relocations("relocations", @@ -136,12 +130,10 @@ cl::alias SymbolsGNU("syms", cl::desc("Alias for --symbols"), cl::aliasopt(Symbols)); - // -dyn-symbols, -dyn-syms, -dt + // -dyn-symbols, -dyn-syms + // Also -dt in llvm-readobj mode. cl::opt DynamicSymbols("dyn-symbols", cl::desc("Display the dynamic symbol table")); - cl::alias DynamicSymbolsShort("dt", - cl::desc("Alias for --dyn-symbols"), - cl::aliasopt(DynamicSymbols)); cl::alias DynSymsGNU("dyn-syms", cl::desc("Alias for --dyn-symbols"), cl::aliasopt(DynamicSymbols)); @@ -636,13 +628,36 @@ // --section-details (not implemented yet). static cl::alias SymbolsShort("t", cl::desc("Alias for --symbols"), cl::aliasopt(opts::Symbols), cl::NotHidden); + + // The following two-letter aliases are only provided for readobj, as readelf + // allows single-letter to be grouped together. + static cl::alias SectionRelocationsShort( + "sr", cl::desc("Alias for --section-relocations"), + cl::aliasopt(opts::SectionRelocations)); + static cl::alias SectionDataShort("sd", cl::desc("Alias for --section-data"), + cl::aliasopt(opts::SectionData)); + static cl::alias SectionSymbolsShort("st", + cl::desc("Alias for --section-symbols"), + cl::aliasopt(opts::SectionSymbols)); + static cl::alias DynamicSymbolsShort("dt", + cl::desc("Alias for --dyn-symbols"), + cl::aliasopt(opts::DynamicSymbols)); } /// Registers aliases that should only be allowed by readelf. static void registerReadelfAliases() { // -s is here because for readobj it means --sections. static cl::alias SymbolsShort("s", cl::desc("Alias for --symbols"), - cl::aliasopt(opts::Symbols), cl::NotHidden); + cl::aliasopt(opts::Symbols), cl::NotHidden, + cl::Grouping); + + // Allow all single letter flags to be grouped together. + for (auto &OptEntry : cl::getRegisteredOptions()) { + StringRef ArgName = OptEntry.getKey(); + cl::Option *Option = OptEntry.getValue(); + if (ArgName.size() == 1) + Option->setFormattingFlag(cl::Grouping); + } } int main(int argc, const char *argv[]) {