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 @@ -37,10 +37,6 @@ Display the contents of the basic block address map section(s), which contain the address of each function, along with the relative offset of each basic block. -.. option:: --color - - Use colors in the output for warnings and errors. - .. option:: --demangle, -C Display demangled symbol names in the output. @@ -84,7 +80,7 @@ When used with :option:`--relocations`, display each relocation in an expanded multi-line format. -.. option:: --file-headers, -h +.. option:: --file-header, -h Display file headers. @@ -109,10 +105,6 @@ Display a summary of command line options. -.. option:: --help-list - - Display an uncategorized summary of command line options. - .. option:: --hex-dump=, -x Display the specified section(s) as hexadecimal bytes. ``section`` may be a diff --git a/llvm/docs/CommandGuide/llvm-readobj.rst b/llvm/docs/CommandGuide/llvm-readobj.rst --- a/llvm/docs/CommandGuide/llvm-readobj.rst +++ b/llvm/docs/CommandGuide/llvm-readobj.rst @@ -56,32 +56,24 @@ Display the address-significance table. -.. option:: --color - - Use colors in the output for warnings and errors. - .. option:: --expand-relocs - When used with :option:`--relocations`, display each relocation in an expanded + When used with :option:`--relocs`, display each relocation in an expanded multi-line format. -.. option:: --file-headers, -h +.. option:: --file-header, -h Display file headers. .. option:: --headers, -e - Equivalent to setting: :option:`--file-headers`, :option:`--program-headers`, + Equivalent to setting: :option:`--file-header`, :option:`--program-headers`, and :option:`--sections`. .. option:: --help Display a summary of command line options. -.. option:: --help-list - - Display an uncategorized summary of command line options. - .. option:: --hex-dump=, -x Display the specified section(s) as hexadecimal bytes. ``section`` may be a @@ -181,7 +173,7 @@ Display the callgraph profile section. -.. option:: --elf-hash-histogram, --histogram, -I +.. option:: --histogram, -I Display a bucket list histogram for dynamic symbol hash tables. @@ -195,7 +187,7 @@ ``GNU``. ``LLVM`` output (the default) is an expanded and structured format, whilst ``GNU`` output mimics the equivalent GNU :program:`readelf` output. -.. option:: --elf-section-groups, --section-groups, -g +.. option:: --section-groups, -g Display section groups. diff --git a/llvm/test/Object/invalid.test b/llvm/test/Object/invalid.test --- a/llvm/test/Object/invalid.test +++ b/llvm/test/Object/invalid.test @@ -406,7 +406,7 @@ ## Check llvm-readobj reports it. # RUN: yaml2obj %s --docnum=19 -o %t19 -# RUN: llvm-readobj -dt %t19 2>&1 | FileCheck -DFILE=%t19 --check-prefix=INVALID-VERSION %s +# RUN: llvm-readobj --dyn-symbols %t19 2>&1 | FileCheck -DFILE=%t19 --check-prefix=INVALID-VERSION %s # INVALID-VERSION: warning: '[[FILE]]': SHT_GNU_versym section refers to a version index 255 which is missing diff --git a/llvm/test/Support/check-default-options.txt b/llvm/test/Support/check-default-options.txt --- a/llvm/test/Support/check-default-options.txt +++ b/llvm/test/Support/check-default-options.txt @@ -1,7 +1,7 @@ -# RUN: llvm-readobj --help-hidden %t | FileCheck --check-prefix=CHECK-READOBJ %s +# RUN: llvm-readobj --help | FileCheck --check-prefix=CHECK-READOBJ %s # RUN: llvm-tblgen --help-hidden %t | FileCheck --check-prefix=CHECK-TBLGEN %s # RUN: llvm-opt-report --help-hidden %t | FileCheck --check-prefix=CHECK-OPT-RPT %s -# CHECK-READOBJ: -h - Alias for --file-headers +# CHECK-READOBJ: -h Alias for --file-header # CHECK-TBLGEN: -h - Alias for --help # CHECK-OPT-RPT: -h - Alias for --help diff --git a/llvm/test/tools/llvm-readobj/ELF/demangle.test b/llvm/test/tools/llvm-readobj/ELF/demangle.test --- a/llvm/test/tools/llvm-readobj/ELF/demangle.test +++ b/llvm/test/tools/llvm-readobj/ELF/demangle.test @@ -19,7 +19,7 @@ # RUN: %t.so > %t.llvm.default # RUN: llvm-readobj --symbols --relocations --dyn-symbols --dyn-relocations \ # RUN: --elf-section-groups --cg-profile --addrsig \ -# RUN: --demangle=false %t.so > %t.llvm.nodemangle +# RUN: --no-demangle %t.so > %t.llvm.nodemangle # RUN: FileCheck %s --input-file %t.llvm.default --check-prefixes=LLVM-COMMON,LLVM-MANGLED # RUN: diff %t.llvm.default %t.llvm.nodemangle @@ -78,7 +78,7 @@ # RUN: llvm-readelf --symbols --relocations --dyn-symbols --dyn-relocations \ # RUN: --elf-section-groups --addrsig %t.so > %t.gnu.default # RUN: llvm-readelf --symbols --relocations --dyn-symbols --dyn-relocations \ -# RUN: --elf-section-groups --addrsig --demangle=false %t.so > %t.gnu.nodemangle +# RUN: --elf-section-groups --addrsig --no-demangle %t.so > %t.gnu.nodemangle # RUN: FileCheck %s --input-file %t.gnu.default --check-prefixes=GNU-COMMON,GNU-MANGLED # RUN: diff %t.gnu.default %t.gnu.nodemangle diff --git a/llvm/test/tools/llvm-readobj/ELF/grouped.test b/llvm/test/tools/llvm-readobj/ELF/grouped.test --- a/llvm/test/tools/llvm-readobj/ELF/grouped.test +++ b/llvm/test/tools/llvm-readobj/ELF/grouped.test @@ -49,9 +49,7 @@ - Name: foo Binding: STB_GLOBAL -## llvm-readobj does not support grouped options, because it also supports some old -## flags (-st, -sd, etc.), and it would be confusing if only some grouped options -## were supported. -# RUN: not llvm-readobj -aeWhSsrnudlVgIS %t.o 2>&1 | FileCheck %s --check-prefix=UNKNOWN - -# UNKNOWN: for the --section-headers option: may only occur zero or one times! +## Check llvm-readobj supports grouped short options as well. +# RUN: llvm-readobj -aeWhSsrnudlVgIS %t.o > %t.grouped +# RUN: llvm-readobj -a -e -W -h -S -r -n -u -d -l -V -g -I -s %t.o > %t.not-grouped +# RUN: cmp %t.grouped %t.not-grouped diff --git a/llvm/test/tools/llvm-readobj/ELF/hex-dump.test b/llvm/test/tools/llvm-readobj/ELF/hex-dump.test --- a/llvm/test/tools/llvm-readobj/ELF/hex-dump.test +++ b/llvm/test/tools/llvm-readobj/ELF/hex-dump.test @@ -2,21 +2,11 @@ ## all other combinations are identical. # RUN: yaml2obj --docnum=1 %s -o %t # RUN: llvm-readelf --file-header --hex-dump=.shstrtab %t > %t.hexdump.out -# RUN: llvm-readelf -h --hex-dump .shstrtab %t > %t.hexdump.1 -# RUN: llvm-readelf -h -x .shstrtab %t > %t.hexdump.2 -# RUN: llvm-readelf -h -x=.shstrtab %t > %t.hexdump.3 -# RUN: llvm-readelf -h -x.shstrtab %t > %t.hexdump.4 -# RUN: llvm-readelf -hx .shstrtab %t > %t.hexdump.5 -# RUN: llvm-readelf -hx=.shstrtab %t > %t.hexdump.6 -# RUN: llvm-readelf -hx.shstrtab %t > %t.hexdump.7 - -# RUN: cmp %t.hexdump.out %t.hexdump.1 -# RUN: cmp %t.hexdump.out %t.hexdump.2 -# RUN: cmp %t.hexdump.out %t.hexdump.3 -# RUN: cmp %t.hexdump.out %t.hexdump.4 -# RUN: cmp %t.hexdump.out %t.hexdump.5 -# RUN: cmp %t.hexdump.out %t.hexdump.6 -# RUN: cmp %t.hexdump.out %t.hexdump.7 +# RUN: llvm-readelf -h --hex-dump .shstrtab %t | cmp %t.hexdump.out - +# RUN: llvm-readelf -h -x .shstrtab %t | cmp %t.hexdump.out - +# RUN: llvm-readelf -h -x.shstrtab %t | cmp %t.hexdump.out - +# RUN: llvm-readelf -hx .shstrtab %t | cmp %t.hexdump.out - +# RUN: llvm-readelf -hx.shstrtab %t | cmp %t.hexdump.out - ## A sanity check to verify that the .shstrtab section has index 2. # RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=ELF-SEC diff --git a/llvm/test/tools/llvm-readobj/ELF/output-style.test b/llvm/test/tools/llvm-readobj/ELF/output-style.test new file mode 100644 --- /dev/null +++ b/llvm/test/tools/llvm-readobj/ELF/output-style.test @@ -0,0 +1,4 @@ +## Error for an unknown output style. +RUN: not llvm-readobj --elf-output-style=unknown 2>&1 | FileCheck %s + +CHECK: error: --elf-output-style value should be either 'LLVM' or 'GNU' diff --git a/llvm/test/tools/llvm-readobj/ELF/string-dump.test b/llvm/test/tools/llvm-readobj/ELF/string-dump.test --- a/llvm/test/tools/llvm-readobj/ELF/string-dump.test +++ b/llvm/test/tools/llvm-readobj/ELF/string-dump.test @@ -8,17 +8,9 @@ # Also test the different ways --string-dump can be specified, i.e. as a short # flag (-p), with different prefix modes (-p .foo, -p=.foo, -p.foo), and with # the value being a index section number instead of a section name. -# RUN: llvm-readobj -p=.strings -p=.not_null_terminated %t > %t.readobj.1 -# RUN: llvm-readobj -p.strings -p.strings -p.not_null_terminated %t > %t.readobj.2 -# RUN: llvm-readobj --string-dump=1 --string-dump=2 %t > %t.readobj.3 -# RUN: llvm-readobj -p1 -p1 -p2 %t > %t.readobj.4 -# RUN: llvm-readobj -p=1 -p=2 %t > %t.readobj.5 - -# RUN: cmp %t.readobj.out %t.readobj.1 -# RUN: cmp %t.readobj.out %t.readobj.2 -# RUN: cmp %t.readobj.out %t.readobj.3 -# RUN: cmp %t.readobj.out %t.readobj.4 -# RUN: cmp %t.readobj.out %t.readobj.5 +# RUN: llvm-readobj -p.strings -p.strings -p.not_null_terminated %t | cmp %t.readobj.out - +# RUN: llvm-readobj --string-dump=1 --string-dump=2 %t | cmp %t.readobj.out - +# RUN: llvm-readobj -p1 -p1 -p2 %t | cmp %t.readobj.out - # Run readelf flag tests with an additional flag, --file-header, so we can test # -p grouped with something. @@ -26,19 +18,10 @@ # RUN: --string-dump=.not_null_terminated %t > %t.readelf.out # RUN: FileCheck %s --input-file=%t.readelf.out -# RUN: llvm-readelf -h -p=.strings -p=.not_null_terminated %t > %t.readelf.1 -# RUN: llvm-readelf -p.strings -hp.not_null_terminated %t > %t.readelf.2 -# RUN: llvm-readelf -h --string-dump=1 --string-dump=2 %t > %t.readelf.3 -# RUN: llvm-readelf -hp1 -p2 %t > %t.readelf.4 -# RUN: llvm-readelf -hp 1 -p.not_null_terminated %t > %t.readelf.5 -# RUN: llvm-readelf -p=1 -hp=2 %t > %t.readelf.6 - -# RUN: cmp %t.readelf.out %t.readelf.1 -# RUN: cmp %t.readelf.out %t.readelf.2 -# RUN: cmp %t.readelf.out %t.readelf.3 -# RUN: cmp %t.readelf.out %t.readelf.4 -# RUN: cmp %t.readelf.out %t.readelf.5 -# RUN: cmp %t.readelf.out %t.readelf.6 +# RUN: llvm-readelf -h -p .strings -p .not_null_terminated %t | cmp %t.readelf.out - +# RUN: llvm-readelf -p.strings -hp.not_null_terminated %t | cmp %t.readelf.out - +# RUN: llvm-readelf -hp1 -p2 %t | cmp %t.readelf.out - +# RUN: llvm-readelf -hp 1 -p.not_null_terminated %t | cmp %t.readelf.out - # CHECK: String dump of section '.strings': # CHECK-NEXT: [ 0] here 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 @@ -38,7 +38,7 @@ # Test case where switch it not recognised. RUN: not llvm-readobj --unknown-switch 2>&1 | FileCheck --check-prefix=UNKNOWN %s -UNKNOWN: Unknown command line argument '--unknown-switch' +UNKNOWN: error: unknown argument '--unknown-switch' # Test version switch. RUN: llvm-readobj --version | FileCheck %s --check-prefix=VERSION @@ -54,6 +54,12 @@ OBJ: llvm-readobj{{.*}} [options] ELF: llvm-readelf{{.*}} [options] HELP: OPTIONS: -HELP -s - Alias for --symbols -HELP -t - Alias for --section-details +HELP: -s Alias for --symbols +HELP: -t Alias for --section-details +HELP: OPTIONS (ELF specific): +HELP: --dynamic-table +HELP: OPTIONS (Mach-O specific): +HELP: --macho-data-in-code +HELP: OPTIONS (PE/COFF specific): +HELP: --codeview-ghash HELP: @FILE diff --git a/llvm/test/tools/yaml2obj/ELF/shstrtab.yaml b/llvm/test/tools/yaml2obj/ELF/shstrtab.yaml --- a/llvm/test/tools/yaml2obj/ELF/shstrtab.yaml +++ b/llvm/test/tools/yaml2obj/ELF/shstrtab.yaml @@ -4,7 +4,7 @@ ## Case 1: custom name specified for string table. # RUN: yaml2obj --docnum=1 %s -o %t1 -DSHSTRTAB=.strings -# RUN: llvm-readelf -S -p=.strings %t1 | FileCheck %s --check-prefix=CASE1 +# RUN: llvm-readelf -S -p .strings %t1 | FileCheck %s --check-prefix=CASE1 # CASE1: There are 5 section headers # CASE1-EMPTY: @@ -37,7 +37,7 @@ ## Case 2: reuse symbol string table. # RUN: yaml2obj --docnum=2 %s -o %t2 -DSHSTRTAB=.strtab -# RUN: llvm-readelf -S -s -p=.strtab %t2 | FileCheck %s --check-prefix=CASE2 +# RUN: llvm-readelf -S -s -p .strtab %t2 | FileCheck %s --check-prefix=CASE2 # CASE2: There are 5 section headers # CASE2-EMPTY: @@ -81,7 +81,7 @@ ## Case 3: reuse dynamic string table. # RUN: yaml2obj --docnum=3 %s -o %t3 -DSHSTRTAB=.dynstr -# RUN: llvm-readelf -S --dyn-syms -p=.dynstr %t3 | FileCheck %s --check-prefix=CASE3 +# RUN: llvm-readelf -S --dyn-syms -p .dynstr %t3 | FileCheck %s --check-prefix=CASE3 --- !ELF FileHeader: @@ -128,7 +128,7 @@ ## Case 4: shstrtab specified to be otherwise ungenerated non-strtab implicit ## section. # RUN: yaml2obj --docnum=1 %s -o %t4 -DSHSTRTAB=.symtab -# RUN: llvm-readelf -S -p=.symtab %t4 | FileCheck %s --check-prefix=CASE4 +# RUN: llvm-readelf -S -p .symtab %t4 | FileCheck %s --check-prefix=CASE4 # CASE4: There are 5 section headers # CASE4-EMPTY: @@ -149,7 +149,7 @@ ## Case 5: shstrtab specified to be otherwise ungenerated .dynstr section. In ## this case, the SHF_ALLOC flag will be set. # RUN: yaml2obj --docnum=1 %s -o %t5 -DSHSTRTAB=.dynstr -# RUN: llvm-readelf -S -p=.dynstr %t5 | FileCheck %s --check-prefix=CASE5 +# RUN: llvm-readelf -S -p .dynstr %t5 | FileCheck %s --check-prefix=CASE5 # CASE5: There are 5 section headers # CASE5-EMPTY: @@ -170,7 +170,7 @@ ## Case 6: shstrtab specified to be otherwise ungenerated .debug_str section. In ## this case, the sh_entsize will be set to 1. # RUN: yaml2obj --docnum=1 %s -o %t6 -DSHSTRTAB=.debug_str -# RUN: llvm-readelf -S -p=.debug_str %t6 | FileCheck %s --check-prefix=CASE6 +# RUN: llvm-readelf -S -p .debug_str %t6 | FileCheck %s --check-prefix=CASE6 # CASE6: There are 5 section headers # CASE6-EMPTY: @@ -221,7 +221,7 @@ ## Case 10: can explicitly specifiy ".shstrtab" as shstrtab. Output will be the ## same as if it wasn't sepcified at all. # RUN: yaml2obj --docnum=1 %s -o %t10 -DSHSTRTAB=.shstrtab -# RUN: llvm-readelf -S -p=.shstrtab %t10 | FileCheck %s --check-prefix=CASE10 +# RUN: llvm-readelf -S -p .shstrtab %t10 | FileCheck %s --check-prefix=CASE10 # RUN: yaml2obj --docnum=1 %s -o %t10.default # RUN: cmp %t10 %t10.default @@ -247,7 +247,7 @@ ## not overwritten, which is inconsistent with when the section is not ## specified at all. # RUN: yaml2obj --docnum=5 %s -o %t11 -DENTSIZE=2 -# RUN: llvm-readelf -S -p=.strings %t11 | FileCheck %s --check-prefix=CASE11 +# RUN: llvm-readelf -S -p .strings %t11 | FileCheck %s --check-prefix=CASE11 # CASE11: There are 5 section headers # CASE11-EMPTY: @@ -316,7 +316,7 @@ ## Case 14: shstrtab has specified Size. The section will be filled with zeros ## to the requested size. # RUN: yaml2obj --docnum=5 %s -o %t14 -DSIZE=32 -# RUN: llvm-readelf -S -p=2 %t14 | FileCheck %s --check-prefix=CASE14 +# RUN: llvm-readelf -S -p 2 %t14 | FileCheck %s --check-prefix=CASE14 # CASE14: There are 5 section headers # CASE14-EMPTY: @@ -420,7 +420,7 @@ ## Case 18: section name for excluded section does not appear in custom ## shstrtab. # RUN: yaml2obj --docnum=9 %s -o %t18 -# RUN: llvm-readelf -S -p=.strings %t18 | FileCheck %s --check-prefix=CASE18 +# RUN: llvm-readelf -S -p .strings %t18 | FileCheck %s --check-prefix=CASE18 # CASE18: There are 4 section headers # CASE18-EMPTY: @@ -458,7 +458,7 @@ ## Case 19: custom shstrtab can have a uniqued name. # RUN: yaml2obj --docnum=1 %s -o %t19 '-DSHSTRTAB=.strings (1)' '-DOTHER=.strings (0)' -# RUN: llvm-readelf -S -p=4 %t19 | FileCheck %s --check-prefix=CASE19 +# RUN: llvm-readelf -S -p 4 %t19 | FileCheck %s --check-prefix=CASE19 # CASE19: There are 5 section headers # CASE19-EMPTY: @@ -478,7 +478,7 @@ ## Case 20: custom shstrtab named ".strtab" with uniquifying ID. # RUN: yaml2obj --docnum=2 %s -o %t20 '-DSHSTRTAB=.strtab (1)' -# RUN: llvm-readelf -S -s -p=4 -p=5 %t20 | FileCheck %s --check-prefix=CASE20 +# RUN: llvm-readelf -S -s -p 4 -p 5 %t20 | FileCheck %s --check-prefix=CASE20 # CASE20: There are 6 section headers # CASE20-EMPTY: @@ -511,7 +511,7 @@ ## Case 21: custom shstrtab named ".dynstr" with uniquifying ID. # RUN: yaml2obj --docnum=3 %s -o %t21 '-DSHSTRTAB=.dynstr (1)' -# RUN: llvm-readelf -S --dyn-syms -p=4 -p=6 %t21 | FileCheck %s --check-prefix=CASE21 +# RUN: llvm-readelf -S --dyn-syms -p 4 -p 6 %t21 | FileCheck %s --check-prefix=CASE21 # CASE21: There are 7 section headers # CASE21-EMPTY: diff --git a/llvm/tools/llvm-readobj/CMakeLists.txt b/llvm/tools/llvm-readobj/CMakeLists.txt --- a/llvm/tools/llvm-readobj/CMakeLists.txt +++ b/llvm/tools/llvm-readobj/CMakeLists.txt @@ -4,12 +4,17 @@ Demangle Object BinaryFormat + Option Support DebugInfoCodeView DebugInfoMSF DebugInfoPDB ) +set(LLVM_TARGET_DEFINITIONS Opts.td) +tablegen(LLVM Opts.inc -gen-opt-parser-defs) +add_public_tablegen_target(ReadobjOptsTableGen) + add_llvm_tool(llvm-readobj ARMWinEHPrinter.cpp COFFDumper.cpp diff --git a/llvm/tools/llvm-readobj/Opts.td b/llvm/tools/llvm-readobj/Opts.td new file mode 100644 --- /dev/null +++ b/llvm/tools/llvm-readobj/Opts.td @@ -0,0 +1,129 @@ +include "llvm/Option/OptParser.td" + +class F : Flag<["-"], letter>, HelpText; +class FF : Flag<["--", "-"], name>, HelpText; + +multiclass BB { + def NAME: Flag<["--", "-"], name>, HelpText; + def no_ # NAME: Flag<["--", "-"], "no-" # name>, HelpText; +} + +multiclass Eq { + def NAME #_EQ : Joined<["--", "-"], name #"=">, + HelpText; + def : Separate<["--", "-"], name>, Alias(NAME #_EQ)>; +} + +def addrsig : FF<"addrsig", "Display address-significance table">; +def all : FF<"all", "Equivalent to setting: --file-header, --program-headers, --section-headers, " + "--symbols, --relocations, --dynamic-table, --notes, --version-info, --unwind, " + "--section-groups and --histogram">; +def arch_specific : FF<"arch-specific", "Display architecture-specific information">; +def bb_addr_map : FF<"bb-addr-map", "Display the BB address map section">; +def cg_profile : FF<"cg-profile", "Display call graph profile section">; +defm demangle : BB<"demangle", "Demangle symbol names", "Do not demangle symbol names (default)">; +def dependent_libraries : FF<"dependent-libraries", "Display the dependent libraries section">; +def dyn_relocations : FF<"dyn-relocations", "Display the dynamic relocation entries in the file">; +def dyn_syms : FF<"dyn-syms", "Display the dynamic symbol table">; +def expand_relocs : FF<"expand-relocs", "Expand each shown relocation to multiple lines">; +def file_header : FF<"file-header", "Display file header">; +def headers : FF<"headers", "Equivalent to setting: --file-header, --program-headers, --section-headers">; +defm hex_dump : Eq<"hex-dump", "Display the specified section(s) as hexadecimal bytes">, MetaVarName<"">; +def relocs : FF<"relocs", "Display the relocation entries in the file">; +def section_data : FF<"section-data", "Display section data for each section shown">; +def section_details : FF<"section-details", "Display the section details">; +def section_headers : FF<"section-headers", "Display section headers">; +def section_mapping : FF<"section-mapping", "Display the section to segment mapping">; +def section_mapping_EQ_false : FF<"section-mapping=false", "Don't display the section to segment mapping">, Flags<[HelpHidden]>; +def section_relocations : FF<"section-relocations", "Display relocations for each section shown">; +def section_symbols : FF<"section-symbols", "Display symbols for each section shown">; +def stack_sizes : FF<"stack-sizes", "Display contents of all stack sizes sections">; +def stackmap : FF<"stackmap", "Display contents of stackmap section">; +defm string_dump : Eq<"string-dump", "Display the specified section(s) as a list of strings">, MetaVarName<"">; +def string_table : FF<"string-table", "Display the string table (only for XCOFF now)">; +def symbols : FF<"symbols", "Display the symbol table. Also display the dynamic symbol table when using GNU output style for ELF">; +def unwind : FF<"unwind", "Display unwind information">; + +// ELF specific options. +def grp_elf : OptionGroup<"kind">, HelpText<"OPTIONS (ELF specific)">; +def dynamic_table : FF<"dynamic-table", "Display the dynamic section table">, Group; +def elf_linker_options : FF<"elf-linker-options", "Display the .linker-options section">, Group; +defm elf_output_style : Eq<"elf-output-style", "Specify ELF dump style">, Group; +def histogram : FF<"histogram", "Display bucket list histogram for hash sections">, Group; +def section_groups : FF<"section-groups", "Display section groups">, Group; +def gnu_hash_table : FF<"gnu-hash-table", "Display .gnu.hash section">, Group; +def hash_symbols : FF<"hash-symbols", "Display the dynamic symbols derived from the hash section">, Group; +def hash_table : FF<"hash-table", "Display .hash section">, Group; +def needed_libs : FF<"needed-libs", "Display the needed libraries">, Group; +def notes : FF<"notes", "Display notes">, Group; +def program_headers : FF<"program-headers", "Display program headers">, Group; +def raw_relr : FF<"raw-relr", "Do not decode relocations in SHT_RELR section, display raw contents">, Group; +def version_info : FF<"version-info", "Display version sections">, Group; + +// Mach-O specific options. +def grp_mach_o : OptionGroup<"kind">, HelpText<"OPTIONS (Mach-O specific)">; +def macho_data_in_code : FF<"macho-data-in-code", "Display Data in Code command">, Group; +def macho_dysymtab : FF<"macho-dysymtab", "Display Dysymtab command">, Group; +def macho_indirect_symbols : FF<"macho-indirect-symbols", "Display indirect symbols">, Group; +def macho_linker_options : FF<"macho-linker-options", "Display linker options">, Group; +def macho_segment : FF<"macho-segment", "Display Segment command">, Group; +def macho_version_min : FF<"macho-version-min", "Display version min command">, Group; + +// PE/COFF specific options. +def grp_coff : OptionGroup<"kind">, HelpText<"OPTIONS (PE/COFF specific)">; +def codeview : FF<"codeview", "Display CodeView debug information">, Group; +def codeview_ghash : FF<"codeview-ghash", "Enable global hashing for CodeView type stream de-duplication">, Group; +def codeview_merged_types : FF<"codeview-merged-types", "Display the merged CodeView type stream">, Group; +def codeview_subsection_bytes : FF<"codeview-subsection-bytes", "Dump raw contents of codeview debug sections and records">, Group; +def coff_basereloc : FF<"coff-basereloc", "Display .reloc section">, Group; +def coff_debug_directory : FF<"coff-debug-directory", "Display debug directory">, Group; +def coff_directives : FF<"coff-directives", "Display .drectve section">, Group; +def coff_exports : FF<"coff-exports", "Display export table">, Group; +def coff_imports : FF<"coff-imports", "Display import table">, Group; +def coff_load_config : FF<"coff-load-config", "Display load config">, Group; +def coff_resources : FF<"coff-resources", "Display .rsrc section">, Group; +def coff_tls_directory : FF<"coff-tls-directory", "Display TLS directory">, Group; + +def help : FF<"help", "Display this help">; +def version : FF<"version", "Display the version">; + +// Ignored for GNU readelf compatibility. +def : F<"W", "Ignored for GNU readelf compatibility">; +def : FF<"wide", "Ignored for GNU readelf compatibility">; + +// Traditional llvm-readobj Aliases. +def : Flag<["--"], "dt">, Alias, HelpText<"Alias for --dyn-syms">; +def : Flag<["--"], "sd">, Alias, HelpText<"Alias for --section-data">; +def : Flag<["--"], "st">, Alias, HelpText<"Alias for --section-symbols">; +def : Flag<["--"], "sr">, Alias, HelpText<"Alias for --section-relocations">; + +// Aliases. +def : FF<"dyn-symbols", "Alias for --dyn-syms">, Alias; +def : FF<"dynamic", "Alias for --dynamic-table">, Alias; +def : FF<"elf-cg-profile", "Alias for --cg-profile">, Alias, Flags<[HelpHidden]>; +def : FF<"elf-hash-histogram", "Alias for --histogram">, Alias, Flags<[HelpHidden]>; +def : FF<"elf-section-groups", "Alias for --section-groups">, Alias, Flags<[HelpHidden]>; +def : FF<"file-headers", "Alias for --file-header">, Alias, Flags<[HelpHidden]>; +def : FF<"relocations", "Alias for --relocs">, Alias; +def : FF<"sections", "Alias for --section-headers">, Alias; +def : FF<"segments", "Alias for --program-headers">, Alias, Group; +def : FF<"syms", "Alias for --symbols">, Alias; + +def : F<"A", "Alias for --arch-specific">, Alias; +def : F<"a", "Alias for --all">, Alias; +def : F<"C", "Alias for --demangle">, Alias; +def : F<"d", "Alias for --dynamic-table">, Alias, Group; +def : F<"e", "Alias for --headers">, Alias; +def : F<"g", "Alias for --section-groups">, Alias, Group; +def : F<"h", "Alias for --file-header">, Alias; +def : F<"I", "Alias for --histogram">, Alias, Group; +def : F<"l", "Alias for --program-headers">, Alias; +def : F<"n", "Alias for --notes">, Alias; +def : JoinedOrSeparate<["-"], "p">, Alias, HelpText<"Alias for --string-dump">, MetaVarName<"">; +def : F<"r", "Alias for --relocs">, Alias; +def : F<"S", "Alias for --section-headers">, Alias; +def : F<"s", "Alias for --symbols">, Alias; +def : F<"t", "Alias for --section-details">, Alias; +def : F<"u", "Alias for --unwind">, Alias; +def : F<"V", "Alias for --version-info">, Alias, Group; +def : JoinedOrSeparate<["-"], "x">, Alias, HelpText<"Alias for --hex-dump">, MetaVarName<"">; diff --git a/llvm/tools/llvm-readobj/llvm-readobj.h b/llvm/tools/llvm-readobj/llvm-readobj.h --- a/llvm/tools/llvm-readobj/llvm-readobj.h +++ b/llvm/tools/llvm-readobj/llvm-readobj.h @@ -32,15 +32,15 @@ } // namespace llvm namespace opts { - extern llvm::cl::opt SectionRelocations; - extern llvm::cl::opt SectionSymbols; - extern llvm::cl::opt SectionData; - extern llvm::cl::opt ExpandRelocs; - extern llvm::cl::opt RawRelr; - extern llvm::cl::opt CodeViewSubsectionBytes; - extern llvm::cl::opt Demangle; - enum OutputStyleTy { LLVM, GNU }; - extern llvm::cl::opt Output; +extern bool SectionRelocations; +extern bool SectionSymbols; +extern bool SectionData; +extern bool ExpandRelocs; +extern bool RawRelr; +extern bool CodeViewSubsectionBytes; +extern bool Demangle; +enum OutputStyleTy { LLVM, GNU }; +extern OutputStyleTy Output; } // namespace opts #define LLVM_READOBJ_ENUM_ENT(ns, enum) \ 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 @@ -31,6 +31,9 @@ #include "llvm/Object/Wasm.h" #include "llvm/Object/WindowsResource.h" #include "llvm/Object/XCOFFObjectFile.h" +#include "llvm/Option/Arg.h" +#include "llvm/Option/ArgList.h" +#include "llvm/Option/Option.h" #include "llvm/Support/Casting.h" #include "llvm/Support/CommandLine.h" #include "llvm/Support/DataTypes.h" @@ -47,356 +50,107 @@ using namespace llvm; using namespace llvm::object; +namespace { +using namespace llvm::opt; // for HelpHidden in Opts.inc +enum ID { + OPT_INVALID = 0, // This is not an option ID. +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + OPT_##ID, +#include "Opts.inc" +#undef OPTION +}; + +#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE; +#include "Opts.inc" +#undef PREFIX + +static const opt::OptTable::Info InfoTable[] = { +#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \ + HELPTEXT, METAVAR, VALUES) \ + { \ + PREFIX, NAME, HELPTEXT, \ + METAVAR, OPT_##ID, opt::Option::KIND##Class, \ + PARAM, FLAGS, OPT_##GROUP, \ + OPT_##ALIAS, ALIASARGS, VALUES}, +#include "Opts.inc" +#undef OPTION +}; + +class ReadobjOptTable : public opt::OptTable { +public: + ReadobjOptTable() : OptTable(InfoTable) { setGroupedShortOptions(true); } +}; + +enum OutputFormatTy { bsd, sysv, posix, darwin, just_symbols }; +} // namespace + namespace opts { - cl::list InputFilenames(cl::Positional, - cl::desc(""), - cl::ZeroOrMore); - - // --all, -a - cl::opt - All("all", - cl::desc("Equivalent to setting: --file-headers, --program-headers, " - "--section-headers, --symbols, --relocations, " - "--dynamic-table, --notes, --version-info, --unwind, " - "--section-groups and --elf-hash-histogram.")); - cl::alias AllShort("a", cl::desc("Alias for --all"), cl::aliasopt(All)); - - // --dependent-libraries - cl::opt - DependentLibraries("dependent-libraries", - cl::desc("Display the dependent libraries section")); - - // --headers, -e - cl::opt - Headers("headers", - cl::desc("Equivalent to setting: --file-headers, --program-headers, " - "--section-headers")); - cl::alias HeadersShort("e", cl::desc("Alias for --headers"), - cl::aliasopt(Headers), cl::NotHidden); - - // --wide, -W - cl::opt - WideOutput("wide", cl::desc("Ignored for compatibility with GNU readelf"), - cl::Hidden); - cl::alias WideOutputShort("W", - cl::desc("Alias for --wide"), - cl::aliasopt(WideOutput)); - - // --file-headers, --file-header, -h - cl::opt FileHeaders("file-headers", - cl::desc("Display file headers ")); - cl::alias FileHeadersShort("h", cl::desc("Alias for --file-headers"), - cl::aliasopt(FileHeaders), cl::NotHidden); - cl::alias FileHeadersSingular("file-header", - cl::desc("Alias for --file-headers"), - cl::aliasopt(FileHeaders)); - - // --section-headers, --sections, -S - // Also -s in llvm-readobj mode. - cl::opt SectionHeaders("section-headers", - cl::desc("Display all section headers.")); - cl::alias SectionsShortUpper("S", cl::desc("Alias for --section-headers"), - cl::aliasopt(SectionHeaders), cl::NotHidden); - cl::alias SectionHeadersAlias("sections", - cl::desc("Alias for --section-headers"), - cl::aliasopt(SectionHeaders), cl::NotHidden); - - // --section-relocations - // Also --sr in llvm-readobj mode. - cl::opt SectionRelocations("section-relocations", - cl::desc("Display relocations for each section shown.")); - - // --section-symbols - // Also --st in llvm-readobj mode. - cl::opt SectionSymbols("section-symbols", - cl::desc("Display symbols for each section shown.")); - - // --section-data - // Also --sd in llvm-readobj mode. - cl::opt SectionData("section-data", - cl::desc("Display section data for each section shown.")); - - // --section-mapping - cl::opt - SectionMapping("section-mapping", - cl::desc("Display the section to segment mapping.")); - - // --relocations, --relocs, -r - cl::opt Relocations("relocations", - cl::desc("Display the relocation entries in the file")); - cl::alias RelocationsShort("r", cl::desc("Alias for --relocations"), - cl::aliasopt(Relocations), cl::NotHidden); - cl::alias RelocationsGNU("relocs", cl::desc("Alias for --relocations"), - cl::aliasopt(Relocations)); - - // --notes, -n - cl::opt Notes("notes", cl::desc("Display the ELF notes in the file")); - cl::alias NotesShort("n", cl::desc("Alias for --notes"), cl::aliasopt(Notes), - cl::NotHidden); - - // --dyn-relocations - 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")); - static cl::alias SectionDetailsShort("t", - cl::desc("Alias for --section-details"), - cl::aliasopt(SectionDetails), - cl::NotHidden); - - // --symbols - // Also -s in llvm-readelf mode, or -t in llvm-readobj mode. - cl::opt - Symbols("symbols", - cl::desc("Display the symbol table. Also display the dynamic " - "symbol table when using GNU output style for ELF")); - cl::alias SymbolsGNU("syms", cl::desc("Alias for --symbols"), - cl::aliasopt(Symbols)); - static cl::alias SymbolsShort("s", cl::desc("Alias for --symbols"), - cl::aliasopt(Symbols), cl::NotHidden, - cl::Grouping); - - // --dyn-symbols, --dyn-syms - // Also --dt in llvm-readobj mode. - cl::opt DynamicSymbols("dyn-symbols", - cl::desc("Display the dynamic symbol table")); - cl::alias DynSymsGNU("dyn-syms", cl::desc("Alias for --dyn-symbols"), - cl::aliasopt(DynamicSymbols)); - - // --hash-symbols - cl::opt HashSymbols( - "hash-symbols", - cl::desc("Display the dynamic symbols derived from the hash section")); - - // --unwind, -u - cl::opt UnwindInfo("unwind", - cl::desc("Display unwind information")); - cl::alias UnwindInfoShort("u", cl::desc("Alias for --unwind"), - cl::aliasopt(UnwindInfo), cl::NotHidden); - - // --dynamic-table, --dynamic, -d - cl::opt DynamicTable("dynamic-table", - cl::desc("Display the ELF .dynamic section table")); - cl::alias DynamicTableShort("d", cl::desc("Alias for --dynamic-table"), - cl::aliasopt(DynamicTable), cl::NotHidden); - cl::alias DynamicTableAlias("dynamic", cl::desc("Alias for --dynamic-table"), - cl::aliasopt(DynamicTable)); - - // --needed-libs - cl::opt NeededLibraries("needed-libs", - cl::desc("Display the needed libraries")); - - // --program-headers, --segments, -l - cl::opt ProgramHeaders("program-headers", - cl::desc("Display ELF program headers")); - cl::alias ProgramHeadersShort("l", cl::desc("Alias for --program-headers"), - cl::aliasopt(ProgramHeaders), cl::NotHidden); - cl::alias SegmentsAlias("segments", cl::desc("Alias for --program-headers"), - cl::aliasopt(ProgramHeaders)); - - // --string-dump, -p - cl::list StringDump( - "string-dump", cl::value_desc("number|name"), - cl::desc("Display the specified section(s) as a list of strings"), - cl::ZeroOrMore); - cl::alias StringDumpShort("p", cl::desc("Alias for --string-dump"), - cl::aliasopt(StringDump), cl::Prefix, - cl::NotHidden); - - // --string-table - cl::opt - StringTable("string-table", - cl::desc("Display the string table (only for XCOFF now)")); - - // --hex-dump, -x - cl::list - HexDump("hex-dump", cl::value_desc("number|name"), - cl::desc("Display the specified section(s) as hexadecimal bytes"), - cl::ZeroOrMore); - cl::alias HexDumpShort("x", cl::desc("Alias for --hex-dump"), - cl::aliasopt(HexDump), cl::Prefix, cl::NotHidden); - - // --demangle, -C - cl::opt Demangle("demangle", - cl::desc("Demangle symbol names in output")); - cl::alias DemangleShort("C", cl::desc("Alias for --demangle"), - cl::aliasopt(Demangle), cl::NotHidden); - - // --hash-table - cl::opt HashTable("hash-table", - cl::desc("Display ELF hash table")); - - // --gnu-hash-table - cl::opt GnuHashTable("gnu-hash-table", - cl::desc("Display ELF .gnu.hash section")); - - // --expand-relocs - cl::opt ExpandRelocs("expand-relocs", - cl::desc("Expand each shown relocation to multiple lines")); - - // --raw-relr - cl::opt RawRelr("raw-relr", - cl::desc("Do not decode relocations in SHT_RELR section, display raw contents")); - - // --codeview - cl::opt CodeView("codeview", - cl::desc("Display CodeView debug information")); - - // --codeview-merged-types - cl::opt - CodeViewMergedTypes("codeview-merged-types", - cl::desc("Display the merged CodeView type stream")); - - // --codeview-ghash - cl::opt CodeViewEnableGHash( - "codeview-ghash", - cl::desc( - "Enable global hashing for CodeView type stream de-duplication")); - - // --codeview-subsection-bytes - cl::opt CodeViewSubsectionBytes( - "codeview-subsection-bytes", - cl::desc("Dump raw contents of codeview debug sections and records")); - - // --arch-specific - cl::opt ArchSpecificInfo("arch-specific", - cl::desc("Displays architecture-specific information, if there is any.")); - cl::alias ArchSpecifcInfoShort("A", cl::desc("Alias for --arch-specific"), - cl::aliasopt(ArchSpecificInfo), cl::NotHidden); - - // --coff-imports - cl::opt - COFFImports("coff-imports", cl::desc("Display the PE/COFF import table")); - - // --coff-exports - cl::opt - COFFExports("coff-exports", cl::desc("Display the PE/COFF export table")); - - // --coff-directives - cl::opt - COFFDirectives("coff-directives", - cl::desc("Display the PE/COFF .drectve section")); - - // --coff-basereloc - cl::opt - COFFBaseRelocs("coff-basereloc", - cl::desc("Display the PE/COFF .reloc section")); - - // --coff-debug-directory - cl::opt - COFFDebugDirectory("coff-debug-directory", - cl::desc("Display the PE/COFF debug directory")); - - // --coff-tls-directory - cl::opt COFFTLSDirectory("coff-tls-directory", - cl::desc("Display the PE/COFF TLS directory")); - - // --coff-resources - cl::opt COFFResources("coff-resources", - cl::desc("Display the PE/COFF .rsrc section")); - - // --coff-load-config - cl::opt - COFFLoadConfig("coff-load-config", - cl::desc("Display the PE/COFF load config")); - - // --elf-linker-options - cl::opt - ELFLinkerOptions("elf-linker-options", - cl::desc("Display the ELF .linker-options section")); - - // --macho-data-in-code - cl::opt - MachODataInCode("macho-data-in-code", - cl::desc("Display MachO Data in Code command")); - - // --macho-indirect-symbols - cl::opt - MachOIndirectSymbols("macho-indirect-symbols", - cl::desc("Display MachO indirect symbols")); - - // --macho-linker-options - cl::opt - MachOLinkerOptions("macho-linker-options", - cl::desc("Display MachO linker options")); - - // --macho-segment - cl::opt - MachOSegment("macho-segment", - cl::desc("Display MachO Segment command")); - - // --macho-version-min - cl::opt - MachOVersionMin("macho-version-min", - cl::desc("Display MachO version min command")); - - // --macho-dysymtab - cl::opt - MachODysymtab("macho-dysymtab", - cl::desc("Display MachO Dysymtab command")); - - // --stackmap - cl::opt - PrintStackMap("stackmap", - cl::desc("Display contents of stackmap section")); - - // --stack-sizes - cl::opt - PrintStackSizes("stack-sizes", - cl::desc("Display contents of all stack sizes sections")); - - // --version-info, -V - cl::opt - VersionInfo("version-info", - cl::desc("Display ELF version sections (if present)")); - cl::alias VersionInfoShort("V", cl::desc("Alias for -version-info"), - cl::aliasopt(VersionInfo), cl::NotHidden); - - // --elf-section-groups, --section-groups, -g - cl::opt SectionGroups("elf-section-groups", - cl::desc("Display ELF section group contents")); - cl::alias SectionGroupsAlias("section-groups", - cl::desc("Alias for -elf-sections-groups"), - cl::aliasopt(SectionGroups)); - cl::alias SectionGroupsShort("g", cl::desc("Alias for -elf-sections-groups"), - cl::aliasopt(SectionGroups), cl::NotHidden); - - // --elf-hash-histogram, --histogram, -I - cl::opt HashHistogram( - "elf-hash-histogram", - cl::desc("Display bucket list histogram for hash sections")); - cl::alias HashHistogramShort("I", cl::desc("Alias for -elf-hash-histogram"), - cl::aliasopt(HashHistogram), cl::NotHidden); - cl::alias HistogramAlias("histogram", - cl::desc("Alias for --elf-hash-histogram"), - cl::aliasopt(HashHistogram)); - - // --cg-profile - cl::opt CGProfile("cg-profile", - cl::desc("Display callgraph profile section")); - cl::alias ELFCGProfile("elf-cg-profile", cl::desc("Alias for --cg-profile"), - cl::aliasopt(CGProfile)); - - // --bb-addr-map - cl::opt BBAddrMap("bb-addr-map", - cl::desc("Display the BB address map section")); - - // -addrsig - cl::opt Addrsig("addrsig", - cl::desc("Display address-significance table")); - - // -elf-output-style - cl::opt - Output("elf-output-style", cl::desc("Specify ELF dump style"), - cl::values(clEnumVal(LLVM, "LLVM default style"), - clEnumVal(GNU, "GNU readelf style")), - cl::init(LLVM)); - - cl::extrahelp - HelpResponse("\nPass @FILE as argument to read options from FILE.\n"); +static bool Addrsig; +static bool All; +static bool ArchSpecificInfo; +static bool BBAddrMap; +bool ExpandRelocs; +static bool CGProfile; +bool Demangle; +static bool DependentLibraries; +static bool DynRelocs; +static bool DynamicSymbols; +static bool FileHeaders; +static bool Headers; +static std::vector HexDump; +static bool PrintStackMap; +static bool PrintStackSizes; +static bool Relocations; +bool SectionData; +static bool SectionDetails; +static bool SectionHeaders; +bool SectionRelocations; +bool SectionSymbols; +static std::vector StringDump; +static bool StringTable; +static bool Symbols; +static bool UnwindInfo; +static cl::boolOrDefault SectionMapping; + +// ELF specific options. +static bool DynamicTable; +static bool ELFLinkerOptions; +static bool GnuHashTable; +static bool HashSymbols; +static bool HashTable; +static bool HashHistogram; +static bool NeededLibraries; +static bool Notes; +static bool ProgramHeaders; +bool RawRelr; +static bool SectionGroups; +static bool VersionInfo; + +// Mach-O specific options. +static bool MachODataInCode; +static bool MachODysymtab; +static bool MachOIndirectSymbols; +static bool MachOLinkerOptions; +static bool MachOSegment; +static bool MachOVersionMin; + +// PE/COFF specific options. +static bool CodeView; +static bool CodeViewEnableGHash; +static bool CodeViewMergedTypes; +bool CodeViewSubsectionBytes; +static bool COFFBaseRelocs; +static bool COFFDebugDirectory; +static bool COFFDirectives; +static bool COFFExports; +static bool COFFImports; +static bool COFFLoadConfig; +static bool COFFResources; +static bool COFFTLSDirectory; + +OutputStyleTy Output = OutputStyleTy::LLVM; +static std::vector InputFilenames; } // namespace opts static StringRef ToolName; @@ -436,6 +190,87 @@ } // namespace llvm +static void parseOptions(const opt::InputArgList &Args) { + opts::Addrsig = Args.hasArg(OPT_addrsig); + opts::All = Args.hasArg(OPT_all); + opts::ArchSpecificInfo = Args.hasArg(OPT_arch_specific); + opts::BBAddrMap = Args.hasArg(OPT_bb_addr_map); + opts::CGProfile = Args.hasArg(OPT_cg_profile); + opts::Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, false); + opts::DependentLibraries = Args.hasArg(OPT_dependent_libraries); + opts::DynRelocs = Args.hasArg(OPT_dyn_relocations); + opts::DynamicSymbols = Args.hasArg(OPT_dyn_syms); + opts::ExpandRelocs = Args.hasArg(OPT_expand_relocs); + opts::FileHeaders = Args.hasArg(OPT_file_header); + opts::Headers = Args.hasArg(OPT_headers); + opts::HexDump = Args.getAllArgValues(OPT_hex_dump_EQ); + opts::Relocations = Args.hasArg(OPT_relocs); + opts::SectionData = Args.hasArg(OPT_section_data); + opts::SectionDetails = Args.hasArg(OPT_section_details); + opts::SectionHeaders = Args.hasArg(OPT_section_headers); + opts::SectionRelocations = Args.hasArg(OPT_section_relocations); + opts::SectionSymbols = Args.hasArg(OPT_section_symbols); + if (Args.hasArg(OPT_section_mapping)) + opts::SectionMapping = cl::BOU_TRUE; + else if (Args.hasArg(OPT_section_mapping_EQ_false)) + opts::SectionMapping = cl::BOU_FALSE; + else + opts::SectionMapping = cl::BOU_UNSET; + opts::PrintStackSizes = Args.hasArg(OPT_stack_sizes); + opts::PrintStackMap = Args.hasArg(OPT_stackmap); + opts::StringDump = Args.getAllArgValues(OPT_string_dump_EQ); + opts::StringTable = Args.hasArg(OPT_string_table); + opts::Symbols = Args.hasArg(OPT_symbols); + opts::UnwindInfo = Args.hasArg(OPT_unwind); + + // ELF specific options. + opts::DynamicTable = Args.hasArg(OPT_dynamic_table); + opts::ELFLinkerOptions = Args.hasArg(OPT_elf_linker_options); + if (Arg *A = Args.getLastArg(OPT_elf_output_style_EQ)) { + StringRef V(A->getValue()); + if (V == "LLVM") + opts::Output = opts::OutputStyleTy::LLVM; + else if (V == "GNU") + opts::Output = opts::OutputStyleTy::GNU; + else + error("--elf-output-style value should be either 'LLVM' or 'GNU'"); + } + opts::GnuHashTable = Args.hasArg(OPT_gnu_hash_table); + opts::HashSymbols = Args.hasArg(OPT_hash_symbols); + opts::HashTable = Args.hasArg(OPT_hash_table); + opts::HashHistogram = Args.hasArg(OPT_histogram); + opts::NeededLibraries = Args.hasArg(OPT_needed_libs); + opts::Notes = Args.hasArg(OPT_notes); + opts::ProgramHeaders = Args.hasArg(OPT_program_headers); + opts::RawRelr = Args.hasArg(OPT_raw_relr); + opts::SectionGroups = Args.hasArg(OPT_section_groups); + opts::VersionInfo = Args.hasArg(OPT_version_info); + + // Mach-O specific options. + opts::MachODataInCode = Args.hasArg(OPT_macho_data_in_code); + opts::MachODysymtab = Args.hasArg(OPT_macho_dysymtab); + opts::MachOIndirectSymbols = Args.hasArg(OPT_macho_indirect_symbols); + opts::MachOLinkerOptions = Args.hasArg(OPT_macho_linker_options); + opts::MachOSegment = Args.hasArg(OPT_macho_segment); + opts::MachOVersionMin = Args.hasArg(OPT_macho_version_min); + + // PE/COFF specific options. + opts::CodeView = Args.hasArg(OPT_codeview); + opts::CodeViewEnableGHash = Args.hasArg(OPT_codeview_ghash); + opts::CodeViewMergedTypes = Args.hasArg(OPT_codeview_merged_types); + opts::CodeViewSubsectionBytes = Args.hasArg(OPT_codeview_subsection_bytes); + opts::COFFBaseRelocs = Args.hasArg(OPT_coff_basereloc); + opts::COFFDebugDirectory = Args.hasArg(OPT_coff_debug_directory); + opts::COFFDirectives = Args.hasArg(OPT_coff_directives); + opts::COFFExports = Args.hasArg(OPT_coff_exports); + opts::COFFImports = Args.hasArg(OPT_coff_imports); + opts::COFFLoadConfig = Args.hasArg(OPT_coff_load_config); + opts::COFFResources = Args.hasArg(OPT_coff_resources); + opts::COFFTLSDirectory = Args.hasArg(OPT_coff_tls_directory); + + opts::InputFilenames = Args.getAllArgValues(OPT_INPUT); +} + namespace { struct ReadObjTypeTableBuilder { ReadObjTypeTableBuilder() @@ -706,49 +541,34 @@ OwningBinary(std::move(Bin), std::move(Buffer))); } -/// Registers aliases that should only be allowed by readobj. -static void registerReadobjAliases() { - // The following two-letter aliases are only provided for readobj, as readelf - // allows single-letter args 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() { - // 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) - apply(Option, cl::Grouping); - } -} - -int main(int argc, const char *argv[]) { +int main(int argc, char *argv[]) { InitLLVM X(argc, argv); + BumpPtrAllocator A; + StringSaver Saver(A); + ReadobjOptTable Tbl; ToolName = argv[0]; - - // Register the target printer for --version. - cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); - - if (sys::path::stem(argv[0]).contains("readelf")) { - opts::Output = opts::GNU; - registerReadelfAliases(); - } else { - registerReadobjAliases(); + opt::InputArgList Args = + Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) { + error(Msg); + exit(1); + }); + if (Args.hasArg(OPT_help)) { + Tbl.printHelp( + outs(), + (Twine(ToolName) + " [options] ").str().c_str(), + "LLVM Object Reader"); + // TODO Replace this with OptTable API once it adds extrahelp support. + outs() << "\nPass @FILE as argument to read options from FILE.\n"; + return 0; + } + if (Args.hasArg(OPT_version)) { + cl::PrintVersionMessage(); + return 0; } - cl::ParseCommandLineOptions(argc, argv, "LLVM Object Reader\n"); + if (sys::path::stem(argv[0]).contains("readelf")) + opts::Output = opts::GNU; + parseOptions(Args); // Default to print error if no filename is specified. if (opts::InputFilenames.empty()) { diff --git a/llvm/utils/gn/secondary/llvm/tools/llvm-readobj/BUILD.gn b/llvm/utils/gn/secondary/llvm/tools/llvm-readobj/BUILD.gn --- a/llvm/utils/gn/secondary/llvm/tools/llvm-readobj/BUILD.gn +++ b/llvm/utils/gn/secondary/llvm/tools/llvm-readobj/BUILD.gn @@ -1,6 +1,12 @@ import("//llvm/tools/binutils_symlinks.gni") +import("//llvm/utils/TableGen/tablegen.gni") import("//llvm/utils/gn/build/symlink_or_copy.gni") +tablegen("Opts") { + visibility = [ ":llvm-readobj" ] + args = [ "-gen-opt-parser-defs" ] +} + symlinks = [ "llvm-readelf" ] if (llvm_install_binutils_symlinks) { symlinks += [ "readelf" ] @@ -23,12 +29,14 @@ executable("llvm-readobj") { deps = [ + ":Opts", "//llvm/lib/BinaryFormat", "//llvm/lib/DebugInfo/CodeView", "//llvm/lib/DebugInfo/DWARF", "//llvm/lib/DebugInfo/MSF", "//llvm/lib/DebugInfo/PDB", "//llvm/lib/Object", + "//llvm/lib/Option", "//llvm/lib/Support", ] sources = [ diff --git a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel --- a/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel +++ b/utils/bazel/llvm-project-overlay/llvm/BUILD.bazel @@ -3385,6 +3385,18 @@ binary = ":llvm-rc", ) +gentbl( + name = "ReadobjOptsTableGen", + strip_include_prefix = "tools/llvm-readobj", + tbl_outs = [( + "-gen-opt-parser-defs", + "tools/llvm-readobj/Opts.inc", + )], + tblgen = ":llvm-tblgen", + td_file = "tools/llvm-readobj/Opts.td", + td_srcs = ["include/llvm/Option/OptParser.td"], +) + cc_binary( name = "llvm-readobj", srcs = glob([ @@ -3401,6 +3413,8 @@ ":DebugInfoDWARF", ":Demangle", ":Object", + ":Option", + ":ReadobjOptsTableGen", ":Support", ], )