[llvm-readobj] Switch command line parsing from llvm::cl to OptTable

Users should generally observe no difference as long as they don't use
unintended option forms. Behavior changes:

* `-t=d` is removed. Use `-t d` instead.
* `--demangle=false` and `--demangle=0` cannot be used. Omit the option or use `--no-demangle`. Other flag-style options don't have `--no-` forms.
* `--help-list` is removed. This is a `cl::` specific option.
* llvm-readobj now supports grouped short options as well.
* `--color` is removed. This is generally not useful (only apply to errors/warnings) but was inherited from Support.

Some adjustment to the canonical forms
(usually from GNU readelf; currently llvm-readobj has too many redundant aliases):

* --dyn-syms is canonical. --dyn-symbols is a hidden alias
* --file-header is canonical. --file-headers is a hidden alias
* --histogram is canonical. --elf-hash-histogram is a hidden alias
* --relocs is canonical. --relocations is a hidden alias
* --section-groups is canonical. --elf-section-groups is a hidden alias

OptTable avoids global option collision if we decide to support multiplexing for binary utilities.

* Most one-dash long options are still supported. `-dt, -sd, -st, -sr` are dropped due to their conflict with grouped short options.
* `--section-mapping=false` (D57365) is strange but is kept for now.
* Many `cl::opt` variables were unnecessarily external. I added `static` whenever appropriate.

Reviewed By: jhenderson

Differential Revision: https://reviews.llvm.org/D105532
This commit is contained in:
Fangrui Song 2021-07-12 10:14:42 -07:00
parent fe892114e3
commit 46580d43fc
17 changed files with 422 additions and 481 deletions

View File

@ -37,10 +37,6 @@ OPTIONS
Display the contents of the basic block address map section(s), which contain the 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. 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 .. option:: --demangle, -C
Display demangled symbol names in the output. Display demangled symbol names in the output.
@ -84,7 +80,7 @@ OPTIONS
When used with :option:`--relocations`, display each relocation in an expanded When used with :option:`--relocations`, display each relocation in an expanded
multi-line format. multi-line format.
.. option:: --file-headers, -h .. option:: --file-header, -h
Display file headers. Display file headers.
@ -109,10 +105,6 @@ OPTIONS
Display a summary of command line options. Display a summary of command line options.
.. option:: --help-list
Display an uncategorized summary of command line options.
.. option:: --hex-dump=<section[,section,...]>, -x .. option:: --hex-dump=<section[,section,...]>, -x
Display the specified section(s) as hexadecimal bytes. ``section`` may be a Display the specified section(s) as hexadecimal bytes. ``section`` may be a

View File

@ -56,32 +56,24 @@ file formats.
Display the address-significance table. Display the address-significance table.
.. option:: --color
Use colors in the output for warnings and errors.
.. option:: --expand-relocs .. 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. multi-line format.
.. option:: --file-headers, -h .. option:: --file-header, -h
Display file headers. Display file headers.
.. option:: --headers, -e .. option:: --headers, -e
Equivalent to setting: :option:`--file-headers`, :option:`--program-headers`, Equivalent to setting: :option:`--file-header`, :option:`--program-headers`,
and :option:`--sections`. and :option:`--sections`.
.. option:: --help .. option:: --help
Display a summary of command line options. Display a summary of command line options.
.. option:: --help-list
Display an uncategorized summary of command line options.
.. option:: --hex-dump=<section[,section,...]>, -x .. option:: --hex-dump=<section[,section,...]>, -x
Display the specified section(s) as hexadecimal bytes. ``section`` may be a Display the specified section(s) as hexadecimal bytes. ``section`` may be a
@ -181,7 +173,7 @@ The following options are implemented only for the ELF file format.
Display the callgraph profile section. Display the callgraph profile section.
.. option:: --elf-hash-histogram, --histogram, -I .. option:: --histogram, -I
Display a bucket list histogram for dynamic symbol hash tables. Display a bucket list histogram for dynamic symbol hash tables.
@ -195,7 +187,7 @@ The following options are implemented only for the ELF file format.
``GNU``. ``LLVM`` output (the default) is an expanded and structured format, ``GNU``. ``LLVM`` output (the default) is an expanded and structured format,
whilst ``GNU`` output mimics the equivalent GNU :program:`readelf` output. whilst ``GNU`` output mimics the equivalent GNU :program:`readelf` output.
.. option:: --elf-section-groups, --section-groups, -g .. option:: --section-groups, -g
Display section groups. Display section groups.

View File

@ -406,7 +406,7 @@ Symbols:
## Check llvm-readobj reports it. ## Check llvm-readobj reports it.
# RUN: yaml2obj %s --docnum=19 -o %t19 # 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 # INVALID-VERSION: warning: '[[FILE]]': SHT_GNU_versym section refers to a version index 255 which is missing

View File

@ -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-tblgen --help-hidden %t | FileCheck --check-prefix=CHECK-TBLGEN %s
# RUN: llvm-opt-report --help-hidden %t | FileCheck --check-prefix=CHECK-OPT-RPT %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-TBLGEN: -h - Alias for --help
# CHECK-OPT-RPT: -h - Alias for --help # CHECK-OPT-RPT: -h - Alias for --help

View File

@ -19,7 +19,7 @@
# RUN: %t.so > %t.llvm.default # RUN: %t.so > %t.llvm.default
# RUN: llvm-readobj --symbols --relocations --dyn-symbols --dyn-relocations \ # RUN: llvm-readobj --symbols --relocations --dyn-symbols --dyn-relocations \
# RUN: --elf-section-groups --cg-profile --addrsig \ # 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: FileCheck %s --input-file %t.llvm.default --check-prefixes=LLVM-COMMON,LLVM-MANGLED
# RUN: diff %t.llvm.default %t.llvm.nodemangle # RUN: diff %t.llvm.default %t.llvm.nodemangle
@ -78,7 +78,7 @@
# RUN: llvm-readelf --symbols --relocations --dyn-symbols --dyn-relocations \ # RUN: llvm-readelf --symbols --relocations --dyn-symbols --dyn-relocations \
# RUN: --elf-section-groups --addrsig %t.so > %t.gnu.default # RUN: --elf-section-groups --addrsig %t.so > %t.gnu.default
# RUN: llvm-readelf --symbols --relocations --dyn-symbols --dyn-relocations \ # 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: FileCheck %s --input-file %t.gnu.default --check-prefixes=GNU-COMMON,GNU-MANGLED
# RUN: diff %t.gnu.default %t.gnu.nodemangle # RUN: diff %t.gnu.default %t.gnu.nodemangle

View File

@ -49,9 +49,7 @@ DynamicSymbols:
- Name: foo - Name: foo
Binding: STB_GLOBAL Binding: STB_GLOBAL
## llvm-readobj does not support grouped options, because it also supports some old ## Check llvm-readobj supports grouped short options as well.
## flags (-st, -sd, etc.), and it would be confusing if only some grouped options # RUN: llvm-readobj -aeWhSsrnudlVgIS %t.o > %t.grouped
## were supported. # RUN: llvm-readobj -a -e -W -h -S -r -n -u -d -l -V -g -I -s %t.o > %t.not-grouped
# RUN: not llvm-readobj -aeWhSsrnudlVgIS %t.o 2>&1 | FileCheck %s --check-prefix=UNKNOWN # RUN: cmp %t.grouped %t.not-grouped
# UNKNOWN: for the --section-headers option: may only occur zero or one times!

View File

@ -2,21 +2,11 @@
## all other combinations are identical. ## all other combinations are identical.
# RUN: yaml2obj --docnum=1 %s -o %t # RUN: yaml2obj --docnum=1 %s -o %t
# RUN: llvm-readelf --file-header --hex-dump=.shstrtab %t > %t.hexdump.out # 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 --hex-dump .shstrtab %t | cmp %t.hexdump.out -
# RUN: llvm-readelf -h -x .shstrtab %t > %t.hexdump.2 # RUN: llvm-readelf -h -x .shstrtab %t | cmp %t.hexdump.out -
# RUN: llvm-readelf -h -x=.shstrtab %t > %t.hexdump.3 # RUN: llvm-readelf -h -x.shstrtab %t | cmp %t.hexdump.out -
# RUN: llvm-readelf -h -x.shstrtab %t > %t.hexdump.4 # RUN: llvm-readelf -hx .shstrtab %t | cmp %t.hexdump.out -
# RUN: llvm-readelf -hx .shstrtab %t > %t.hexdump.5 # RUN: llvm-readelf -hx.shstrtab %t | cmp %t.hexdump.out -
# 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
## A sanity check to verify that the .shstrtab section has index 2. ## A sanity check to verify that the .shstrtab section has index 2.
# RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=ELF-SEC # RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=ELF-SEC

View File

@ -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'

View File

@ -8,17 +8,9 @@
# Also test the different ways --string-dump can be specified, i.e. as a short # 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 # 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. # 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 | cmp %t.readobj.out -
# 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 | cmp %t.readobj.out -
# RUN: llvm-readobj --string-dump=1 --string-dump=2 %t > %t.readobj.3 # RUN: llvm-readobj -p1 -p1 -p2 %t | cmp %t.readobj.out -
# 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 readelf flag tests with an additional flag, --file-header, so we can test # Run readelf flag tests with an additional flag, --file-header, so we can test
# -p grouped with something. # -p grouped with something.
@ -26,19 +18,10 @@
# RUN: --string-dump=.not_null_terminated %t > %t.readelf.out # RUN: --string-dump=.not_null_terminated %t > %t.readelf.out
# RUN: FileCheck %s --input-file=%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 -h -p .strings -p .not_null_terminated %t | cmp %t.readelf.out -
# RUN: llvm-readelf -p.strings -hp.not_null_terminated %t > %t.readelf.2 # RUN: llvm-readelf -p.strings -hp.not_null_terminated %t | cmp %t.readelf.out -
# RUN: llvm-readelf -h --string-dump=1 --string-dump=2 %t > %t.readelf.3 # RUN: llvm-readelf -hp1 -p2 %t | cmp %t.readelf.out -
# RUN: llvm-readelf -hp1 -p2 %t > %t.readelf.4 # RUN: llvm-readelf -hp 1 -p.not_null_terminated %t | cmp %t.readelf.out -
# 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
# CHECK: String dump of section '.strings': # CHECK: String dump of section '.strings':
# CHECK-NEXT: [ 0] here # CHECK-NEXT: [ 0] here

View File

@ -38,7 +38,7 @@ RUN: FileCheck --check-prefix=BITCODE -DFILE1=%t.bc.1 -DFILE2=%t.bc.2 %s
# Test case where switch it not recognised. # Test case where switch it not recognised.
RUN: not llvm-readobj --unknown-switch 2>&1 | FileCheck --check-prefix=UNKNOWN %s 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. # Test version switch.
RUN: llvm-readobj --version | FileCheck %s --check-prefix=VERSION RUN: llvm-readobj --version | FileCheck %s --check-prefix=VERSION
@ -54,6 +54,12 @@ HELP: OVERVIEW: LLVM Object Reader
OBJ: llvm-readobj{{.*}} [options] <input object files> OBJ: llvm-readobj{{.*}} [options] <input object files>
ELF: llvm-readelf{{.*}} [options] <input object files> ELF: llvm-readelf{{.*}} [options] <input object files>
HELP: OPTIONS: HELP: OPTIONS:
HELP -s - Alias for --symbols HELP: -s Alias for --symbols
HELP -t - Alias for --section-details 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 HELP: @FILE

View File

@ -4,7 +4,7 @@
## Case 1: custom name specified for string table. ## Case 1: custom name specified for string table.
# RUN: yaml2obj --docnum=1 %s -o %t1 -DSHSTRTAB=.strings # 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: There are 5 section headers
# CASE1-EMPTY: # CASE1-EMPTY:
@ -37,7 +37,7 @@ Sections:
## Case 2: reuse symbol string table. ## Case 2: reuse symbol string table.
# RUN: yaml2obj --docnum=2 %s -o %t2 -DSHSTRTAB=.strtab # 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: There are 5 section headers
# CASE2-EMPTY: # CASE2-EMPTY:
@ -81,7 +81,7 @@ Symbols:
## Case 3: reuse dynamic string table. ## Case 3: reuse dynamic string table.
# RUN: yaml2obj --docnum=3 %s -o %t3 -DSHSTRTAB=.dynstr # 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 --- !ELF
FileHeader: FileHeader:
@ -128,7 +128,7 @@ DynamicSymbols:
## Case 4: shstrtab specified to be otherwise ungenerated non-strtab implicit ## Case 4: shstrtab specified to be otherwise ungenerated non-strtab implicit
## section. ## section.
# RUN: yaml2obj --docnum=1 %s -o %t4 -DSHSTRTAB=.symtab # 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: There are 5 section headers
# CASE4-EMPTY: # CASE4-EMPTY:
@ -149,7 +149,7 @@ DynamicSymbols:
## Case 5: shstrtab specified to be otherwise ungenerated .dynstr section. In ## Case 5: shstrtab specified to be otherwise ungenerated .dynstr section. In
## this case, the SHF_ALLOC flag will be set. ## this case, the SHF_ALLOC flag will be set.
# RUN: yaml2obj --docnum=1 %s -o %t5 -DSHSTRTAB=.dynstr # 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: There are 5 section headers
# CASE5-EMPTY: # CASE5-EMPTY:
@ -170,7 +170,7 @@ DynamicSymbols:
## Case 6: shstrtab specified to be otherwise ungenerated .debug_str section. In ## Case 6: shstrtab specified to be otherwise ungenerated .debug_str section. In
## this case, the sh_entsize will be set to 1. ## this case, the sh_entsize will be set to 1.
# RUN: yaml2obj --docnum=1 %s -o %t6 -DSHSTRTAB=.debug_str # 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: There are 5 section headers
# CASE6-EMPTY: # CASE6-EMPTY:
@ -221,7 +221,7 @@ DWARF:
## Case 10: can explicitly specifiy ".shstrtab" as shstrtab. Output will be the ## Case 10: can explicitly specifiy ".shstrtab" as shstrtab. Output will be the
## same as if it wasn't sepcified at all. ## same as if it wasn't sepcified at all.
# RUN: yaml2obj --docnum=1 %s -o %t10 -DSHSTRTAB=.shstrtab # 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: yaml2obj --docnum=1 %s -o %t10.default
# RUN: cmp %t10 %t10.default # RUN: cmp %t10 %t10.default
@ -247,7 +247,7 @@ DWARF:
## not overwritten, which is inconsistent with when the section is not ## not overwritten, which is inconsistent with when the section is not
## specified at all. ## specified at all.
# RUN: yaml2obj --docnum=5 %s -o %t11 -DENTSIZE=2 # 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: There are 5 section headers
# CASE11-EMPTY: # CASE11-EMPTY:
@ -316,7 +316,7 @@ Sections:
## Case 14: shstrtab has specified Size. The section will be filled with zeros ## Case 14: shstrtab has specified Size. The section will be filled with zeros
## to the requested size. ## to the requested size.
# RUN: yaml2obj --docnum=5 %s -o %t14 -DSIZE=32 # 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: There are 5 section headers
# CASE14-EMPTY: # CASE14-EMPTY:
@ -420,7 +420,7 @@ Sections:
## Case 18: section name for excluded section does not appear in custom ## Case 18: section name for excluded section does not appear in custom
## shstrtab. ## shstrtab.
# RUN: yaml2obj --docnum=9 %s -o %t18 # 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: There are 4 section headers
# CASE18-EMPTY: # CASE18-EMPTY:
@ -458,7 +458,7 @@ Sections:
## Case 19: custom shstrtab can have a uniqued name. ## Case 19: custom shstrtab can have a uniqued name.
# RUN: yaml2obj --docnum=1 %s -o %t19 '-DSHSTRTAB=.strings (1)' '-DOTHER=.strings (0)' # 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: There are 5 section headers
# CASE19-EMPTY: # CASE19-EMPTY:
@ -478,7 +478,7 @@ Sections:
## Case 20: custom shstrtab named ".strtab" with uniquifying ID. ## Case 20: custom shstrtab named ".strtab" with uniquifying ID.
# RUN: yaml2obj --docnum=2 %s -o %t20 '-DSHSTRTAB=.strtab (1)' # 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: There are 6 section headers
# CASE20-EMPTY: # CASE20-EMPTY:
@ -511,7 +511,7 @@ Sections:
## Case 21: custom shstrtab named ".dynstr" with uniquifying ID. ## Case 21: custom shstrtab named ".dynstr" with uniquifying ID.
# RUN: yaml2obj --docnum=3 %s -o %t21 '-DSHSTRTAB=.dynstr (1)' # 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: There are 7 section headers
# CASE21-EMPTY: # CASE21-EMPTY:

View File

@ -4,12 +4,17 @@ set(LLVM_LINK_COMPONENTS
Demangle Demangle
Object Object
BinaryFormat BinaryFormat
Option
Support Support
DebugInfoCodeView DebugInfoCodeView
DebugInfoMSF DebugInfoMSF
DebugInfoPDB 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 add_llvm_tool(llvm-readobj
ARMWinEHPrinter.cpp ARMWinEHPrinter.cpp
COFFDumper.cpp COFFDumper.cpp

View File

@ -0,0 +1,129 @@
include "llvm/Option/OptParser.td"
class F<string letter, string help> : Flag<["-"], letter>, HelpText<help>;
class FF<string name, string help> : Flag<["--", "-"], name>, HelpText<help>;
multiclass BB<string name, string help1, string help2> {
def NAME: Flag<["--", "-"], name>, HelpText<help1>;
def no_ # NAME: Flag<["--", "-"], "no-" # name>, HelpText<help2>;
}
multiclass Eq<string name, string help> {
def NAME #_EQ : Joined<["--", "-"], name #"=">,
HelpText<help>;
def : Separate<["--", "-"], name>, Alias<!cast<Joined>(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<"<name or index>">;
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<"<name or index>">;
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<grp_elf>;
def elf_linker_options : FF<"elf-linker-options", "Display the .linker-options section">, Group<grp_elf>;
defm elf_output_style : Eq<"elf-output-style", "Specify ELF dump style">, Group<grp_elf>;
def histogram : FF<"histogram", "Display bucket list histogram for hash sections">, Group<grp_elf>;
def section_groups : FF<"section-groups", "Display section groups">, Group<grp_elf>;
def gnu_hash_table : FF<"gnu-hash-table", "Display .gnu.hash section">, Group<grp_elf>;
def hash_symbols : FF<"hash-symbols", "Display the dynamic symbols derived from the hash section">, Group<grp_elf>;
def hash_table : FF<"hash-table", "Display .hash section">, Group<grp_elf>;
def needed_libs : FF<"needed-libs", "Display the needed libraries">, Group<grp_elf>;
def notes : FF<"notes", "Display notes">, Group<grp_elf>;
def program_headers : FF<"program-headers", "Display program headers">, Group<grp_elf>;
def raw_relr : FF<"raw-relr", "Do not decode relocations in SHT_RELR section, display raw contents">, Group<grp_elf>;
def version_info : FF<"version-info", "Display version sections">, Group<grp_elf>;
// 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<grp_mach_o>;
def macho_dysymtab : FF<"macho-dysymtab", "Display Dysymtab command">, Group<grp_mach_o>;
def macho_indirect_symbols : FF<"macho-indirect-symbols", "Display indirect symbols">, Group<grp_mach_o>;
def macho_linker_options : FF<"macho-linker-options", "Display linker options">, Group<grp_mach_o>;
def macho_segment : FF<"macho-segment", "Display Segment command">, Group<grp_mach_o>;
def macho_version_min : FF<"macho-version-min", "Display version min command">, Group<grp_mach_o>;
// PE/COFF specific options.
def grp_coff : OptionGroup<"kind">, HelpText<"OPTIONS (PE/COFF specific)">;
def codeview : FF<"codeview", "Display CodeView debug information">, Group<grp_coff>;
def codeview_ghash : FF<"codeview-ghash", "Enable global hashing for CodeView type stream de-duplication">, Group<grp_coff>;
def codeview_merged_types : FF<"codeview-merged-types", "Display the merged CodeView type stream">, Group<grp_coff>;
def codeview_subsection_bytes : FF<"codeview-subsection-bytes", "Dump raw contents of codeview debug sections and records">, Group<grp_coff>;
def coff_basereloc : FF<"coff-basereloc", "Display .reloc section">, Group<grp_coff>;
def coff_debug_directory : FF<"coff-debug-directory", "Display debug directory">, Group<grp_coff>;
def coff_directives : FF<"coff-directives", "Display .drectve section">, Group<grp_coff>;
def coff_exports : FF<"coff-exports", "Display export table">, Group<grp_coff>;
def coff_imports : FF<"coff-imports", "Display import table">, Group<grp_coff>;
def coff_load_config : FF<"coff-load-config", "Display load config">, Group<grp_coff>;
def coff_resources : FF<"coff-resources", "Display .rsrc section">, Group<grp_coff>;
def coff_tls_directory : FF<"coff-tls-directory", "Display TLS directory">, Group<grp_coff>;
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<dyn_syms>, HelpText<"Alias for --dyn-syms">;
def : Flag<["--"], "sd">, Alias<section_data>, HelpText<"Alias for --section-data">;
def : Flag<["--"], "st">, Alias<section_symbols>, HelpText<"Alias for --section-symbols">;
def : Flag<["--"], "sr">, Alias<section_relocations>, HelpText<"Alias for --section-relocations">;
// Aliases.
def : FF<"dyn-symbols", "Alias for --dyn-syms">, Alias<dyn_syms>;
def : FF<"dynamic", "Alias for --dynamic-table">, Alias<dynamic_table>;
def : FF<"elf-cg-profile", "Alias for --cg-profile">, Alias<cg_profile>, Flags<[HelpHidden]>;
def : FF<"elf-hash-histogram", "Alias for --histogram">, Alias<histogram>, Flags<[HelpHidden]>;
def : FF<"elf-section-groups", "Alias for --section-groups">, Alias<section_groups>, Flags<[HelpHidden]>;
def : FF<"file-headers", "Alias for --file-header">, Alias<file_header>, Flags<[HelpHidden]>;
def : FF<"relocations", "Alias for --relocs">, Alias<relocs>;
def : FF<"sections", "Alias for --section-headers">, Alias<section_headers>;
def : FF<"segments", "Alias for --program-headers">, Alias<program_headers>, Group<grp_elf>;
def : FF<"syms", "Alias for --symbols">, Alias<symbols>;
def : F<"A", "Alias for --arch-specific">, Alias<arch_specific>;
def : F<"a", "Alias for --all">, Alias<all>;
def : F<"C", "Alias for --demangle">, Alias<demangle>;
def : F<"d", "Alias for --dynamic-table">, Alias<dynamic_table>, Group<grp_elf>;
def : F<"e", "Alias for --headers">, Alias<headers>;
def : F<"g", "Alias for --section-groups">, Alias<section_groups>, Group<grp_elf>;
def : F<"h", "Alias for --file-header">, Alias<file_header>;
def : F<"I", "Alias for --histogram">, Alias<histogram>, Group<grp_elf>;
def : F<"l", "Alias for --program-headers">, Alias<program_headers>;
def : F<"n", "Alias for --notes">, Alias<notes>;
def : JoinedOrSeparate<["-"], "p">, Alias<string_dump_EQ>, HelpText<"Alias for --string-dump">, MetaVarName<"<name or index>">;
def : F<"r", "Alias for --relocs">, Alias<relocs>;
def : F<"S", "Alias for --section-headers">, Alias<section_headers>;
def : F<"s", "Alias for --symbols">, Alias<symbols>;
def : F<"t", "Alias for --section-details">, Alias<section_details>;
def : F<"u", "Alias for --unwind">, Alias<unwind>;
def : F<"V", "Alias for --version-info">, Alias<version_info>, Group<grp_elf>;
def : JoinedOrSeparate<["-"], "x">, Alias<hex_dump_EQ>, HelpText<"Alias for --hex-dump">, MetaVarName<"<name or index>">;

View File

@ -31,6 +31,9 @@
#include "llvm/Object/Wasm.h" #include "llvm/Object/Wasm.h"
#include "llvm/Object/WindowsResource.h" #include "llvm/Object/WindowsResource.h"
#include "llvm/Object/XCOFFObjectFile.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/Casting.h"
#include "llvm/Support/CommandLine.h" #include "llvm/Support/CommandLine.h"
#include "llvm/Support/DataTypes.h" #include "llvm/Support/DataTypes.h"
@ -47,356 +50,107 @@
using namespace llvm; using namespace llvm;
using namespace llvm::object; 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 { namespace opts {
cl::list<std::string> InputFilenames(cl::Positional, static bool Addrsig;
cl::desc("<input object files>"), static bool All;
cl::ZeroOrMore); 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<std::string> 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<std::string> StringDump;
static bool StringTable;
static bool Symbols;
static bool UnwindInfo;
static cl::boolOrDefault SectionMapping;
// --all, -a // ELF specific options.
cl::opt<bool> static bool DynamicTable;
All("all", static bool ELFLinkerOptions;
cl::desc("Equivalent to setting: --file-headers, --program-headers, " static bool GnuHashTable;
"--section-headers, --symbols, --relocations, " static bool HashSymbols;
"--dynamic-table, --notes, --version-info, --unwind, " static bool HashTable;
"--section-groups and --elf-hash-histogram.")); static bool HashHistogram;
cl::alias AllShort("a", cl::desc("Alias for --all"), cl::aliasopt(All)); static bool NeededLibraries;
static bool Notes;
static bool ProgramHeaders;
bool RawRelr;
static bool SectionGroups;
static bool VersionInfo;
// --dependent-libraries // Mach-O specific options.
cl::opt<bool> static bool MachODataInCode;
DependentLibraries("dependent-libraries", static bool MachODysymtab;
cl::desc("Display the dependent libraries section")); static bool MachOIndirectSymbols;
static bool MachOLinkerOptions;
static bool MachOSegment;
static bool MachOVersionMin;
// --headers, -e // PE/COFF specific options.
cl::opt<bool> static bool CodeView;
Headers("headers", static bool CodeViewEnableGHash;
cl::desc("Equivalent to setting: --file-headers, --program-headers, " static bool CodeViewMergedTypes;
"--section-headers")); bool CodeViewSubsectionBytes;
cl::alias HeadersShort("e", cl::desc("Alias for --headers"), static bool COFFBaseRelocs;
cl::aliasopt(Headers), cl::NotHidden); static bool COFFDebugDirectory;
static bool COFFDirectives;
static bool COFFExports;
static bool COFFImports;
static bool COFFLoadConfig;
static bool COFFResources;
static bool COFFTLSDirectory;
// --wide, -W OutputStyleTy Output = OutputStyleTy::LLVM;
cl::opt<bool> static std::vector<std::string> InputFilenames;
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<bool> 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<bool> 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<bool> SectionRelocations("section-relocations",
cl::desc("Display relocations for each section shown."));
// --section-symbols
// Also --st in llvm-readobj mode.
cl::opt<bool> SectionSymbols("section-symbols",
cl::desc("Display symbols for each section shown."));
// --section-data
// Also --sd in llvm-readobj mode.
cl::opt<bool> SectionData("section-data",
cl::desc("Display section data for each section shown."));
// --section-mapping
cl::opt<cl::boolOrDefault>
SectionMapping("section-mapping",
cl::desc("Display the section to segment mapping."));
// --relocations, --relocs, -r
cl::opt<bool> 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<bool> 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<bool> DynRelocs("dyn-relocations",
cl::desc("Display the dynamic relocation entries in the file"));
// --section-details
// Also -t in llvm-readelf mode.
cl::opt<bool> 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<bool>
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<bool> 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<bool> HashSymbols(
"hash-symbols",
cl::desc("Display the dynamic symbols derived from the hash section"));
// --unwind, -u
cl::opt<bool> 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<bool> 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<bool> NeededLibraries("needed-libs",
cl::desc("Display the needed libraries"));
// --program-headers, --segments, -l
cl::opt<bool> 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<std::string> 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<bool>
StringTable("string-table",
cl::desc("Display the string table (only for XCOFF now)"));
// --hex-dump, -x
cl::list<std::string>
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<bool> 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<bool> HashTable("hash-table",
cl::desc("Display ELF hash table"));
// --gnu-hash-table
cl::opt<bool> GnuHashTable("gnu-hash-table",
cl::desc("Display ELF .gnu.hash section"));
// --expand-relocs
cl::opt<bool> ExpandRelocs("expand-relocs",
cl::desc("Expand each shown relocation to multiple lines"));
// --raw-relr
cl::opt<bool> RawRelr("raw-relr",
cl::desc("Do not decode relocations in SHT_RELR section, display raw contents"));
// --codeview
cl::opt<bool> CodeView("codeview",
cl::desc("Display CodeView debug information"));
// --codeview-merged-types
cl::opt<bool>
CodeViewMergedTypes("codeview-merged-types",
cl::desc("Display the merged CodeView type stream"));
// --codeview-ghash
cl::opt<bool> CodeViewEnableGHash(
"codeview-ghash",
cl::desc(
"Enable global hashing for CodeView type stream de-duplication"));
// --codeview-subsection-bytes
cl::opt<bool> CodeViewSubsectionBytes(
"codeview-subsection-bytes",
cl::desc("Dump raw contents of codeview debug sections and records"));
// --arch-specific
cl::opt<bool> 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<bool>
COFFImports("coff-imports", cl::desc("Display the PE/COFF import table"));
// --coff-exports
cl::opt<bool>
COFFExports("coff-exports", cl::desc("Display the PE/COFF export table"));
// --coff-directives
cl::opt<bool>
COFFDirectives("coff-directives",
cl::desc("Display the PE/COFF .drectve section"));
// --coff-basereloc
cl::opt<bool>
COFFBaseRelocs("coff-basereloc",
cl::desc("Display the PE/COFF .reloc section"));
// --coff-debug-directory
cl::opt<bool>
COFFDebugDirectory("coff-debug-directory",
cl::desc("Display the PE/COFF debug directory"));
// --coff-tls-directory
cl::opt<bool> COFFTLSDirectory("coff-tls-directory",
cl::desc("Display the PE/COFF TLS directory"));
// --coff-resources
cl::opt<bool> COFFResources("coff-resources",
cl::desc("Display the PE/COFF .rsrc section"));
// --coff-load-config
cl::opt<bool>
COFFLoadConfig("coff-load-config",
cl::desc("Display the PE/COFF load config"));
// --elf-linker-options
cl::opt<bool>
ELFLinkerOptions("elf-linker-options",
cl::desc("Display the ELF .linker-options section"));
// --macho-data-in-code
cl::opt<bool>
MachODataInCode("macho-data-in-code",
cl::desc("Display MachO Data in Code command"));
// --macho-indirect-symbols
cl::opt<bool>
MachOIndirectSymbols("macho-indirect-symbols",
cl::desc("Display MachO indirect symbols"));
// --macho-linker-options
cl::opt<bool>
MachOLinkerOptions("macho-linker-options",
cl::desc("Display MachO linker options"));
// --macho-segment
cl::opt<bool>
MachOSegment("macho-segment",
cl::desc("Display MachO Segment command"));
// --macho-version-min
cl::opt<bool>
MachOVersionMin("macho-version-min",
cl::desc("Display MachO version min command"));
// --macho-dysymtab
cl::opt<bool>
MachODysymtab("macho-dysymtab",
cl::desc("Display MachO Dysymtab command"));
// --stackmap
cl::opt<bool>
PrintStackMap("stackmap",
cl::desc("Display contents of stackmap section"));
// --stack-sizes
cl::opt<bool>
PrintStackSizes("stack-sizes",
cl::desc("Display contents of all stack sizes sections"));
// --version-info, -V
cl::opt<bool>
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<bool> 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<bool> 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<bool> 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<bool> BBAddrMap("bb-addr-map",
cl::desc("Display the BB address map section"));
// -addrsig
cl::opt<bool> Addrsig("addrsig",
cl::desc("Display address-significance table"));
// -elf-output-style
cl::opt<OutputStyleTy>
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");
} // namespace opts } // namespace opts
static StringRef ToolName; static StringRef ToolName;
@ -436,6 +190,87 @@ void reportWarning(Error Err, StringRef Input) {
} // namespace llvm } // 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 { namespace {
struct ReadObjTypeTableBuilder { struct ReadObjTypeTableBuilder {
ReadObjTypeTableBuilder() ReadObjTypeTableBuilder()
@ -706,49 +541,34 @@ static void dumpInput(StringRef File, ScopedPrinter &Writer) {
OwningBinary<Binary>(std::move(Bin), std::move(Buffer))); OwningBinary<Binary>(std::move(Bin), std::move(Buffer)));
} }
/// Registers aliases that should only be allowed by readobj. int main(int argc, char *argv[]) {
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[]) {
InitLLVM X(argc, argv); InitLLVM X(argc, argv);
BumpPtrAllocator A;
StringSaver Saver(A);
ReadobjOptTable Tbl;
ToolName = argv[0]; ToolName = argv[0];
opt::InputArgList Args =
// Register the target printer for --version. Tbl.parseArgs(argc, argv, OPT_UNKNOWN, Saver, [&](StringRef Msg) {
cl::AddExtraVersionPrinter(TargetRegistry::printRegisteredTargetsForVersion); error(Msg);
exit(1);
if (sys::path::stem(argv[0]).contains("readelf")) { });
opts::Output = opts::GNU; if (Args.hasArg(OPT_help)) {
registerReadelfAliases(); Tbl.printHelp(
} else { outs(),
registerReadobjAliases(); (Twine(ToolName) + " [options] <input object files>").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. // Default to print error if no filename is specified.
if (opts::InputFilenames.empty()) { if (opts::InputFilenames.empty()) {

View File

@ -32,15 +32,15 @@ namespace llvm {
} // namespace llvm } // namespace llvm
namespace opts { namespace opts {
extern llvm::cl::opt<bool> SectionRelocations; extern bool SectionRelocations;
extern llvm::cl::opt<bool> SectionSymbols; extern bool SectionSymbols;
extern llvm::cl::opt<bool> SectionData; extern bool SectionData;
extern llvm::cl::opt<bool> ExpandRelocs; extern bool ExpandRelocs;
extern llvm::cl::opt<bool> RawRelr; extern bool RawRelr;
extern llvm::cl::opt<bool> CodeViewSubsectionBytes; extern bool CodeViewSubsectionBytes;
extern llvm::cl::opt<bool> Demangle; extern bool Demangle;
enum OutputStyleTy { LLVM, GNU }; enum OutputStyleTy { LLVM, GNU };
extern llvm::cl::opt<OutputStyleTy> Output; extern OutputStyleTy Output;
} // namespace opts } // namespace opts
#define LLVM_READOBJ_ENUM_ENT(ns, enum) \ #define LLVM_READOBJ_ENUM_ENT(ns, enum) \

View File

@ -1,6 +1,12 @@
import("//llvm/tools/binutils_symlinks.gni") import("//llvm/tools/binutils_symlinks.gni")
import("//llvm/utils/TableGen/tablegen.gni")
import("//llvm/utils/gn/build/symlink_or_copy.gni") import("//llvm/utils/gn/build/symlink_or_copy.gni")
tablegen("Opts") {
visibility = [ ":llvm-readobj" ]
args = [ "-gen-opt-parser-defs" ]
}
symlinks = [ "llvm-readelf" ] symlinks = [ "llvm-readelf" ]
if (llvm_install_binutils_symlinks) { if (llvm_install_binutils_symlinks) {
symlinks += [ "readelf" ] symlinks += [ "readelf" ]
@ -23,12 +29,14 @@ group("symlinks") {
executable("llvm-readobj") { executable("llvm-readobj") {
deps = [ deps = [
":Opts",
"//llvm/lib/BinaryFormat", "//llvm/lib/BinaryFormat",
"//llvm/lib/DebugInfo/CodeView", "//llvm/lib/DebugInfo/CodeView",
"//llvm/lib/DebugInfo/DWARF", "//llvm/lib/DebugInfo/DWARF",
"//llvm/lib/DebugInfo/MSF", "//llvm/lib/DebugInfo/MSF",
"//llvm/lib/DebugInfo/PDB", "//llvm/lib/DebugInfo/PDB",
"//llvm/lib/Object", "//llvm/lib/Object",
"//llvm/lib/Option",
"//llvm/lib/Support", "//llvm/lib/Support",
] ]
sources = [ sources = [

View File

@ -3385,6 +3385,18 @@ binary_alias(
binary = ":llvm-rc", 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( cc_binary(
name = "llvm-readobj", name = "llvm-readobj",
srcs = glob([ srcs = glob([
@ -3401,6 +3413,8 @@ cc_binary(
":DebugInfoDWARF", ":DebugInfoDWARF",
":Demangle", ":Demangle",
":Object", ":Object",
":Option",
":ReadobjOptsTableGen",
":Support", ":Support",
], ],
) )