1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-22 02:33:06 +01:00

[llvm-objdump] Add an llvm-otool tool

This implements an LLVM tool that's flag- and output-compatible
with macOS's `otool` -- except for bugs, but from testing with both
`otool` and `xcrun otool-classic`, llvm-otool matches vanilla
otool's behavior very well already. It's not 100% perfect, but
it's a very solid start.

This uses the same approach as llvm-objcopy: llvm-objdump uses
a different OptTable when it's invoked as llvm-otool. This
is possible thanks to D100433.

Differential Revision: https://reviews.llvm.org/D100583
This commit is contained in:
Nico Weber 2021-04-15 10:55:22 -04:00
parent 2e96104338
commit 74a701ab05
29 changed files with 509 additions and 68 deletions

View File

@ -29,6 +29,7 @@ Basic Commands
llvm-link
llvm-lipo
llvm-mca
llvm-otool
llvm-profdata
llvm-readobj
llvm-stress

View File

@ -390,4 +390,5 @@ To report bugs, please visit <https://bugs.llvm.org/>.
SEE ALSO
--------
:manpage:`llvm-nm(1)`, :manpage:`llvm-readelf(1)`, :manpage:`llvm-readobj(1)`
:manpage:`llvm-nm(1)`, :manpage:`llvm-otool(1)`, :manpage:`llvm-readelf(1)`,
:manpage:`llvm-readobj(1)`

View File

@ -0,0 +1,140 @@
llvm-otool - Mach-O dumping tool
================================
.. program:: llvm-otool
SYNOPSIS
--------
:program:`llvm-otool` [*option...*] *[file...]*
DESCRIPTION
-----------
:program:`llvm-otool` is a tool for dumping Mach-O files.
It attempts to be command-line-compatible and output-compatible with macOS's
:program:`otool`.
OPTIONS
-------
.. option:: -arch <value>
Select slice of universal Mach-O file.
.. option:: -C
Print linker optimization hints.
.. option:: -D
Print shared library id.
.. option:: -d
Print data section.
.. option:: -f
Print universal headers.
.. option:: -G
Print data-in-code table.
.. option:: --help-hidden
Print help for hidden flags.
.. option:: --help
Print help.
.. option:: -h
Print mach header.
.. option:: -I
Print indirect symbol table.
.. option:: -j
Print opcode bytes.
.. option:: -L
Print used shared libraries.
.. option:: -l
Print load commnads.
.. option:: -mcpu=<value>
Select cpu for disassembly.
.. option:: -o
Print Objective-C segment.
.. option:: -P
Print __TEXT,__info_plist section as strings.
.. option:: -p <function name>
Start disassembly at <function name>.
.. option:: -r
Print relocation entries.
.. option:: -s <segname> <sectname>
Print contents of section.
.. option:: -t
Print text section.
.. option:: --version
Print version.
.. option:: -V
Symbolize disassembled operands (implies :option:`-v`).
.. option:: -v
Verbose output / disassemble when printing text sections.
.. option:: -X
Omit leading addresses or headers.
.. option:: -x
Print all text sections.
.. option:: @<FILE>
Read command-line options and commands from response file `<FILE>`.
EXIT STATUS
-----------
:program:`llvm-otool` exits with a non-zero exit code if there is an error.
Otherwise, it exits with code 0.
BUGS
----
To report bugs, please visit <https://bugs.llvm.org/>.
SEE ALSO
--------
:manpage:`llvm-nm(1)`, :manpage:`llvm-objdump(1)`

View File

@ -100,6 +100,7 @@ set(LLVM_TEST_DEPENDS
llvm-objdump
llvm-opt-fuzzer
llvm-opt-report
llvm-otool
llvm-pdbutil
llvm-profdata
llvm-profgen

View File

@ -160,7 +160,7 @@ tools.extend([
'llvm-isel-fuzzer', 'llvm-ifs',
'llvm-install-name-tool', 'llvm-jitlink', 'llvm-opt-fuzzer', 'llvm-lib',
'llvm-link', 'llvm-lto', 'llvm-lto2', 'llvm-mc', 'llvm-mca',
'llvm-modextract', 'llvm-nm', 'llvm-objcopy', 'llvm-objdump',
'llvm-modextract', 'llvm-nm', 'llvm-objcopy', 'llvm-objdump', 'llvm-otool',
'llvm-pdbutil', 'llvm-profdata', 'llvm-ranlib', 'llvm-rc', 'llvm-readelf',
'llvm-readobj', 'llvm-rtdyld', 'llvm-size', 'llvm-split', 'llvm-strings',
'llvm-strip', 'llvm-tblgen', 'llvm-undname', 'llvm-c-test', 'llvm-cxxfilt',

View File

@ -1,4 +1,5 @@
RUN: llvm-objdump -m --link-opt-hints %p/Inputs/link-opt-hints.macho-aarch64 | FileCheck %s
RUN: llvm-otool -C %p/Inputs/link-opt-hints.macho-aarch64 | FileCheck %s
CHECK: Linker optimiztion hints (8 total bytes)
CHECK: identifier 8 AdrpLdrGot

View File

@ -1,5 +1,7 @@
RUN: llvm-objdump -m --data-in-code %p/Inputs/data-in-code.macho-arm | FileCheck %s
RUN: llvm-otool -Gv %p/Inputs/data-in-code.macho-arm | FileCheck %s
RUN: llvm-objdump -m --data-in-code --non-verbose %p/Inputs/data-in-code.macho-arm | FileCheck %s --check-prefix=NON_VERBOSE
RUN: llvm-otool -G %p/Inputs/data-in-code.macho-arm | FileCheck %s --check-prefix=NON_VERBOSE
CHECK: Data in code table (4 entries)
CHECK: offset length kind

View File

@ -1,4 +1,6 @@
@ RUN: llvm-mc < %s -triple thumbv7-apple-darwin -mcpu=cortex-a7 -filetype=obj | llvm-objdump --triple thumbv7-apple-darwin10 -m -d --mcpu=cortex-a7 - | FileCheck %s
@ RUN: llvm-mc %s -triple thumbv7-apple-darwin -mcpu=cortex-a7 -filetype=obj -o %t.o
@ RUN: llvm-objdump --triple thumbv7-apple-darwin10 -m -d --mcpu=cortex-a7 %t.o | FileCheck %s
@ RUN: llvm-otool -tv -mcpu=cortex-a7 %t.o | FileCheck %s
.thumb
.thumb_func _t

View File

@ -1,5 +1,6 @@
; RUN: llc --mtriple x86_64-apple-darwin -filetype=obj -O0 %s -o %t.o
; RUN: llvm-objdump --macho -d --no-show-raw-insn %t.o | FileCheck %s
; RUN: llvm-otool -tv %t.o | FileCheck %s
; CHECK: .long {{[0-9]+}} @ KIND_JUMP_TABLE32
; CHECK: .long {{[0-9]+}} @ KIND_JUMP_TABLE32

View File

@ -1,6 +1,7 @@
# RUN: llvm-objdump --macho -d %p/Inputs/hello.obj.macho-x86_64 --no-show-raw-insn --print-imm-hex --no-leading-addr | FileCheck %s
# RUN: llvm-objdump --macho -d %p/Inputs/hello.obj.macho-x86_64 --no-show-raw-insn --print-imm-hex --no-leading-addr | FileCheck --check-prefixes=CHECK,HEAD %s
# RUN: llvm-otool -tVX %p/Inputs/hello.obj.macho-x86_64 | FileCheck --implicit-check-not=section %s
# CHECK: (__TEXT,__text) section
# HEAD: (__TEXT,__text) section
# CHECK: _main:
# CHECK: pushq %rbp
# CHECK: movq %rsp, %rbp

View File

@ -1,4 +1,5 @@
# RUN: llvm-objdump --macho -d %p/Inputs/exeThread.macho-x86_64 --dis-symname start --no-show-raw-insn --full-leading-addr --print-imm-hex | FileCheck %s
# RUN: llvm-otool -tV %p/Inputs/exeThread.macho-x86_64 -p start | FileCheck %s
# CHECK: (__TEXT,__text) section
# CHECK: start:
@ -18,8 +19,8 @@
# CHECK-NOT: 0000000100000d22
# CHECK-NOT: _main:
# not RUN: llvm-objdump --macho -d %p/Inputs/exeThread.macho-x86_64 --dis-symname _environ 2>&1 | FileCheck --check-prefix BAD-SYMAME-1 %s
# RUN: llvm-objdump --macho -d %p/Inputs/exeThread.macho-x86_64 --dis-symname _environ 2>&1 | FileCheck --check-prefix BAD-SYMAME-1 %s
BAD-SYMAME-1: -dis-symname: _environ not in the section
# not RUN: llvm-objdump --macho -d %p/Inputs/exeThread.macho-x86_64 --dis-symname __mh_execute_header 2>&1 | FileCheck --check-prefix BAD-SYMAME-2 %s
# RUN: llvm-objdump --macho -d %p/Inputs/exeThread.macho-x86_64 --dis-symname __mh_execute_header 2>&1 | FileCheck --check-prefix BAD-SYMAME-2 %s
BAD-SYMAME-2: -dis-symname: __mh_execute_header not in any section

View File

@ -1,4 +1,5 @@
RUN: llvm-objdump --macho --dylibs-used %p/Inputs/dylibLoadKinds.macho-x86_64 | FileCheck %s --check-prefix=USED
RUN: llvm-otool -L %p/Inputs/dylibLoadKinds.macho-x86_64 | FileCheck %s --check-prefix=USED
USED: /usr/lib/foo1.dylib (compatibility version 0.0.0, current version 0.0.0)
USED: /usr/lib/foo2.dylib (compatibility version 0.0.0, current version 0.0.0, weak)
USED: /usr/lib/foo3.dylib (compatibility version 0.0.0, current version 0.0.0, reexport)
@ -6,8 +7,10 @@ USED: /usr/lib/foo4.dylib (compatibility version 0.0.0, current version 0.0.0, l
USED: /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)
RUN: llvm-objdump --macho --dylib-id %p/Inputs/dylibLoadKinds.macho-x86_64 | FileCheck %s --check-prefix=ID
RUN: llvm-otool -D %p/Inputs/dylibLoadKinds.macho-x86_64 | FileCheck %s --check-prefix=ID
ID: /usr/lib/foo.dylib
RUN: llvm-objdump --macho --dylib-id --no-leading-headers %p/Inputs/dylibLoadKinds.macho-x86_64 | FileCheck %s --check-prefix=IDNOHEADERS
RUN: llvm-otool -DX %p/Inputs/dylibLoadKinds.macho-x86_64 | FileCheck %s --check-prefix=IDNOHEADERS
IDNOHEADERS-NOT: dylibLoadKinds.macho-x86_64:
IDNOHEADERS: /usr/lib/foo.dylib

View File

@ -1,5 +1,7 @@
RUN: llvm-objdump --macho --indirect-symbols %p/Inputs/hello.exe.macho-x86_64 | FileCheck %s
RUN: llvm-otool -Iv %p/Inputs/hello.exe.macho-x86_64 | FileCheck %s
RUN: llvm-objdump --macho --indirect-symbols --non-verbose %p/Inputs/hello.exe.macho-x86_64 | FileCheck %s --check-prefix=NON_VERBOSE
RUN: llvm-otool -I %p/Inputs/hello.exe.macho-x86_64 | FileCheck %s --check-prefix=NON_VERBOSE
CHECK: Indirect symbols for (__TEXT,__stubs) 1 entries
CHECK: address index name

View File

@ -1,5 +1,8 @@
# RUN: llvm-mc < %s --triple x86_64-apple-darwin -filetype=obj | llvm-objdump --macho --info-plist - | FileCheck %s
# RUN: llvm-mc < %s --triple x86_64-apple-darwin -filetype=obj | llvm-objdump --macho --info-plist --no-leading-headers - | FileCheck --check-prefix=NOHEADER %s
# RUN: llvm-mc %s --triple x86_64-apple-darwin -filetype=obj -o %t.o
# RUN: llvm-objdump --macho --info-plist %t.o | FileCheck %s
# RUN: llvm-otool -P %t.o | FileCheck %s
# RUN: llvm-objdump --macho --info-plist --no-leading-headers %t.o | FileCheck --check-prefix=NOHEADER %s
# RUN: llvm-otool -PX %t.o | FileCheck --check-prefix=NOHEADER %s
.section __TEXT, __info_plist
.asciz "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"

View File

@ -1,4 +1,5 @@
# RUN: llvm-objdump --macho --objc-meta-data %p/Inputs/Objc2.64bit.exe.macho-x86_64 | FileCheck %s --check-prefix=OBJC2_64BIT_EXE
# RUN: llvm-otool -o %p/Inputs/Objc2.64bit.exe.macho-x86_64 | FileCheck %s --check-prefix=OBJC2_64BIT_EXE
# RUN: llvm-objdump --macho --objc-meta-data %p/Inputs/Objc2.64bit.obj.macho-x86_64 | FileCheck %s --check-prefix=OBJC2_64BIT_OBJ
# RUN: llvm-objdump --macho --objc-meta-data %p/Inputs/Objc2.32bit.exe.macho-i386 | FileCheck %s --check-prefix=OBJC2_32BIT_EXE
# RUN: llvm-objdump --macho --objc-meta-data %p/Inputs/Objc2.32bit.obj.macho-i386 | FileCheck %s --check-prefix=OBJC2_32BIT_OBJ

View File

@ -1,4 +1,5 @@
// RUN: llvm-objdump -p %p/Inputs/hello.obj.macho-x86_64 | FileCheck %s
// RUN: llvm-otool -lv %p/Inputs/hello.obj.macho-x86_64 | FileCheck %s
// RUN: llvm-objdump -p %p/Inputs/hello.exe.macho-x86_64 \
// RUN: | FileCheck %s -check-prefix=EXE
// RUN: llvm-objdump -p %p/Inputs/dylibLoadKinds.macho-x86_64 \

View File

@ -1,9 +1,24 @@
RUN: llvm-objdump --macho -r %p/Inputs/hello.obj.macho-x86_64 | FileCheck %s
RUN: llvm-objdump --macho -r %p/Inputs/hello.obj.macho-x86_64 | \
RUN: FileCheck --check-prefix=VERBOSE %s
RUN: llvm-otool -rv %p/Inputs/hello.obj.macho-x86_64 | \
RUN: FileCheck --check-prefix=VERBOSE %s
RUN: llvm-objdump --macho -r --non-verbose %p/Inputs/hello.obj.macho-x86_64 | \
RUN: FileCheck --check-prefix=NONVERBOSE %s
RUN: llvm-otool -r %p/Inputs/hello.obj.macho-x86_64 | \
RUN: FileCheck --check-prefix=NONVERBOSE %s
CHECK: Relocation information (__TEXT,__text) 2 entries
CHECK: address pcrel length extern type scattered symbolnum/value
CHECK: 00000027 True long True BRANCH False _printf
CHECK: 0000000b True long True SIGNED False L_.str
CHECK: Relocation information (__LD,__compact_unwind) 1 entries
CHECK: address pcrel length extern type scattered symbolnum/value
CHECK: 00000000 False quad False UNSIGND False 1 (__TEXT,__text)
VERBOSE: Relocation information (__TEXT,__text) 2 entries
VERBOSE-NEXT: address pcrel length extern type scattered symbolnum/value
VERBOSE-NEXT: 00000027 True long True BRANCH False _printf
VERBOSE-NEXT: 0000000b True long True SIGNED False L_.str
VERBOSE-NEXT: Relocation information (__LD,__compact_unwind) 1 entries
VERBOSE-NEXT: address pcrel length extern type scattered symbolnum/value
VERBOSE-NEXT: 00000000 False quad False UNSIGND False 1 (__TEXT,__text)
NONVERBOSE: Relocation information (__TEXT,__text) 2 entries
NONVERBOSE-NEXT: address pcrel length extern type scattered symbolnum/value
NONVERBOSE-NEXT: 00000027 1 2 1 2 0 4
NONVERBOSE-NEXT: 0000000b 1 2 1 1 0 0
NONVERBOSE-NEXT: Relocation information (__LD,__compact_unwind) 1 entries
NONVERBOSE-NEXT: address pcrel length extern type scattered symbolnum/value
NONVERBOSE-NEXT: 00000000 0 3 0 0 0 1

View File

@ -1,4 +1,5 @@
# RUN: llvm-objdump --macho --section=__data %p/Inputs/bind2.macho-x86_64 | FileCheck %s
# RUN: llvm-otool -d %p/Inputs/bind2.macho-x86_64 | FileCheck %s
# CHECK: bind2.macho-x86_64:

View File

@ -1,5 +1,7 @@
// RUN: llvm-objdump -d --macho --no-show-raw-insn --full-leading-addr --print-imm-hex %p/Inputs/hello.obj.macho-x86_64 | FileCheck %s --check-prefix=OBJ
// RUN: llvm-otool -tV %p/Inputs/hello.obj.macho-x86_64 | FileCheck %s --check-prefix=OBJ
// RUN: llvm-objdump -d --macho --no-show-raw-insn --full-leading-addr --print-imm-hex %p/Inputs/hello.exe.macho-x86_64 | FileCheck %s --check-prefix=EXE
// RUN: llvm-otool -tV %p/Inputs/hello.exe.macho-x86_64 | FileCheck %s --check-prefix=EXE
// RUN: llvm-objdump -d --macho --no-show-raw-insn --full-leading-addr --print-imm-hex %p/Inputs/ObjC.obj.macho-x86_64 | FileCheck %s --check-prefix=ObjC-OBJ
// RUN: llvm-objdump -d --macho --no-show-raw-insn --full-leading-addr --print-imm-hex %p/Inputs/ObjC.exe.macho-x86_64 | FileCheck %s --check-prefix=ObjC-EXE
// RUN: llvm-objdump -d --macho --no-show-raw-insn --full-leading-addr --print-imm-hex %p/Inputs/hello_cpp.exe.macho-x86_64 | FileCheck %s --check-prefix=CXX-EXE
@ -8,7 +10,9 @@
// RUN: llvm-objdump -d --macho --no-show-raw-insn --full-leading-addr --print-imm-hex %p/Inputs/hello.exe.macho-i386 | FileCheck %s --check-prefix=i386-EXE
// RUN: llvm-objdump -d --macho --no-show-raw-insn --full-leading-addr --print-imm-hex --no-symbolic-operands %p/Inputs/hello.obj.macho-x86_64 | FileCheck %s --check-prefix=NO-SYM-OPS-OBJ
// RUN: llvm-otool -tv %p/Inputs/hello.obj.macho-x86_64 | FileCheck %s --check-prefix=NO-SYM-OPS-OBJ
// RUN: llvm-objdump -d --macho --no-show-raw-insn --full-leading-addr --print-imm-hex --no-symbolic-operands %p/Inputs/hello.exe.macho-x86_64 | FileCheck %s --check-prefix=NO-SYM-OPS-EXE
// RUN: llvm-otool -tv %p/Inputs/hello.exe.macho-x86_64 | FileCheck %s --check-prefix=NO-SYM-OPS-EXE
OBJ: 0000000000000008 leaq L_.str(%rip), %rax ## literal pool for: "Hello world\n"
OBJ: 0000000000000026 callq _printf

View File

@ -4,6 +4,10 @@
# RUN: yaml2obj %s -o %tarm.o
# RUN: llvm-objdump %tarm.o --universal-headers --macho | \
# RUN: FileCheck %s --match-full-lines
# RUN: llvm-otool -fv %tarm.o | FileCheck %s --match-full-lines
# RUN: llvm-objdump %tarm.o --universal-headers --macho --non-verbose | \
# RUN: FileCheck %s --match-full-lines --check-prefix=NONVERBOSE
# RUN: llvm-otool -f %tarm.o | FileCheck %s --match-full-lines --check-prefix=NONVERBOSE
# CHECK: Fat headers
# CHECK-NEXT: fat_magic FAT_MAGIC
@ -31,6 +35,33 @@
# CHECK-NEXT: align 2^12 (4096)
# CHECK-NOT:{{.}}
# NONVERBOSE: Fat headers
# NONVERBOSE-NEXT: fat_magic 0xcafebabe
# NONVERBOSE-NEXT: nfat_arch 3
# NONVERBOSE-NEXT: architecture 0
# NONVERBOSE-NEXT: cputype 16777228
# NONVERBOSE-NEXT: cpusubtype 0
# NONVERBOSE-NEXT: capabilities 0x0
# NONVERBOSE-NEXT: offset 4096
# NONVERBOSE-NEXT: size 352
# NONVERBOSE-NEXT: align 2^12 (4096)
# NONVERBOSE-NEXT: architecture 1
# NONVERBOSE-NEXT: cputype 16777228
# NONVERBOSE-NEXT: cpusubtype 1
# NONVERBOSE-NEXT: capabilities 0x0
# NONVERBOSE-NEXT: offset 16384
# NONVERBOSE-NEXT: size 384
# NONVERBOSE-NEXT: align 2^14 (16384)
# NONVERBOSE-NEXT: architecture 2
# NONVERBOSE-NEXT: cputype 16777228
# NONVERBOSE-NEXT: cpusubtype 2
# NONVERBOSE-NEXT: capabilities 0x0
# NONVERBOSE-NEXT: offset 28672
# NONVERBOSE-NEXT: size 384
# NONVERBOSE-NEXT: align 2^12 (4096)
# NONVERBOSE-NOT:{{.}}
--- !fat-mach-o
FatHeader:
magic: 0xCAFEBABE

View File

@ -0,0 +1,15 @@
## Don't make symlinks on Windows.
# UNSUPPORTED: system-windows
# RUN: rm -rf %t
# RUN: mkdir %t
# RUN: ln -s llvm-objdump %t/llvm-otool-11.exe
# RUN: ln -s llvm-objdump %t/powerpc64-unknown-freebsd13-objdump
# RUN: %t/llvm-otool-11.exe --help | FileCheck --check-prefix=OTOOL %s
# RUN: %t/powerpc64-unknown-freebsd13-objdump --help | \
# RUN: FileCheck --check-prefix=OBJDUMP %s
# OBJDUMP: OVERVIEW: llvm object file dumper
# OTOOL: OVERVIEW: Mach-O object file displaying tool

View File

@ -18,6 +18,10 @@ set(LLVM_TARGET_DEFINITIONS ObjdumpOpts.td)
tablegen(LLVM ObjdumpOpts.inc -gen-opt-parser-defs)
add_public_tablegen_target(ObjdumpOptsTableGen)
set(LLVM_TARGET_DEFINITIONS OtoolOpts.td)
tablegen(LLVM OtoolOpts.inc -gen-opt-parser-defs)
add_public_tablegen_target(OtoolOptsTableGen)
add_llvm_tool(llvm-objdump
llvm-objdump.cpp
COFFDump.cpp
@ -27,12 +31,15 @@ add_llvm_tool(llvm-objdump
XCOFFDump.cpp
DEPENDS
ObjdumpOptsTableGen
OtoolOptsTableGen
)
if(HAVE_LIBXAR)
target_link_libraries(llvm-objdump PRIVATE ${XAR_LIB})
endif()
add_llvm_tool_symlink(llvm-otool llvm-objdump)
if(LLVM_INSTALL_BINUTILS_SYMLINKS)
add_llvm_tool_symlink(objdump llvm-objdump)
endif()

View File

@ -71,8 +71,8 @@ bool objdump::LazyBind;
bool objdump::WeakBind;
static bool UseDbg;
static std::string DSYMFile;
static bool FullLeadingAddr;
static bool NoLeadingHeaders;
bool objdump::FullLeadingAddr;
bool objdump::NoLeadingHeaders;
bool objdump::UniversalHeaders;
static bool ArchiveMemberOffsets;
bool objdump::IndirectSymbols;
@ -82,10 +82,10 @@ bool objdump::LinkOptHints;
bool objdump::InfoPlist;
bool objdump::DylibsUsed;
bool objdump::DylibId;
static bool NonVerbose;
bool objdump::NonVerbose;
bool objdump::ObjcMetaData;
static std::string DisSymName;
static bool NoSymbolicOperands;
std::string objdump::DisSymName;
bool objdump::NoSymbolicOperands;
static std::vector<std::string> ArchFlags;
static bool ArchAll = false;

View File

@ -40,12 +40,17 @@ extern bool DylibsUsed;
extern bool DylibId;
extern bool ExportsTrie;
extern bool FirstPrivateHeader;
extern bool FullLeadingAddr;
extern bool FunctionStarts;
extern bool IndirectSymbols;
extern bool InfoPlist;
extern bool LazyBind;
extern bool LinkOptHints;
extern bool NoLeadingHeaders;
extern bool NoSymbolicOperands;
extern bool NonVerbose;
extern bool ObjcMetaData;
extern std::string DisSymName;
extern bool Rebase;
extern bool UniversalHeaders;
extern bool WeakBind;

View File

@ -1,7 +1,7 @@
#ifndef LLVM_TOOLS_LLVM_OBJDUMP_OBJDUMP_OPT_ID_H
#define LLVM_TOOLS_LLVM_OBJDUMP_OBJDUMP_OPT_ID_H
enum ID {
enum ObjdumpOptID {
OBJDUMP_INVALID = 0, // This is not an option ID.
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR, VALUES) \

View File

@ -0,0 +1,68 @@
include "llvm/Option/OptParser.td"
def help : Flag<["--"], "help">, HelpText<"print help">;
def help_hidden : Flag<["--"], "help-hidden">,
HelpText<"print help for hidden flags">;
def arch : Separate<["-"], "arch">,
HelpText<"select slice of universal Mach-O file">;
def C : Flag<["-"], "C">, HelpText<"print linker optimization hints">;
def d : Flag<["-"], "d">, HelpText<"print data section">;
def D : Flag<["-"], "D">, HelpText<"print shared library id">;
def f : Flag<["-"], "f">, HelpText<"print universal headers">;
def G : Flag<["-"], "G">, HelpText<"print data-in-code table">;
def h : Flag<["-"], "h">, HelpText<"print mach header">;
def I : Flag<["-"], "I">, HelpText<"print indirect symbol table">;
def j : Flag<["-"], "j">, HelpText<"print opcode bytes">;
def l : Flag<["-"], "l">, HelpText<"print load commnads">;
def L : Flag<["-"], "L">, HelpText<"print used shared libraries">;
def mcpu_EQ : Joined<["-"], "mcpu=">, HelpText<"select cpu for disassembly">;
def o : Flag<["-"], "o">, HelpText<"print Objective-C segment">;
def p : Separate<["-"], "p">,
MetaVarName<"<function name>">,
HelpText<"start disassembly at <function name>">;
def P : Flag<["-"], "P">, HelpText<"print __TEXT,__info_plist section as strings">;
def : Flag<["-"], "q">, Flags<[HelpHidden]>,
HelpText<"use LLVM's disassembler (default)">;
def r : Flag<["-"], "r">, HelpText<"print relocation entries">;
def s : MultiArg<["-"], "s", 2>,
MetaVarName<"<segname> <sectname>">,
HelpText<"print contents of section">;
def t : Flag<["-"], "t">, HelpText<"print text section">;
def version : Flag<["--"], "version">, HelpText<"print version">;
def v : Flag<["-"], "v">,
HelpText<"verbose output / disassemble when printing text sections">;
def V : Flag<["-"], "V">,
HelpText<"symbolize disassembled operands (implies -v)">;
def x : Flag<["-"], "x">, HelpText<"print all text sections">;
def X : Flag<["-"], "X">, HelpText<"omit leading addresses or headers">;
// Not (yet?) implemented:
// def a : Flag<["-"], "a">, HelpText<"print archive header">;
// -c print argument strings of a core file
// -m don't use archive(member) syntax
// -dyld_info
// -dyld_opcodes
// -chained_fixups
// -addr_slide=arg
// -function_offsets
// Obsolete and unsupported:
def grp_obsolete : OptionGroup<"kind">,
HelpText<"Obsolete and unsupported flags">;
def : Flag<["-"], "B">, Flags<[HelpHidden]>, Group<grp_obsolete>,
HelpText<"force Thum disassembly (ARM 32-bit objects only)">;
def : Flag<["-"], "H">, Flags<[HelpHidden]>, Group<grp_obsolete>,
HelpText<"print two-level hints table">;
def : Flag<["-"], "M">, Flags<[HelpHidden]>, Group<grp_obsolete>,
HelpText<"print module table of shared library">;
def : Flag<["-"], "R">, Flags<[HelpHidden]>, Group<grp_obsolete>,
HelpText<"print reference table of shared library">;
def : Flag<["-"], "S">, Flags<[HelpHidden]>, Group<grp_obsolete>,
HelpText<"print table of contents of library">;
def : Flag<["-"], "T">, Flags<[HelpHidden]>, Group<grp_obsolete>,
HelpText<"print table of contents of shared library">;
def : Flag<["-"], "Q">, Flags<[HelpHidden]>, Group<grp_obsolete>,
HelpText<"llvm-otool cannot use otool-classic's disassembler">;

View File

@ -88,32 +88,84 @@ using namespace llvm::opt;
namespace {
#define PREFIX(NAME, VALUE) const char *const NAME[] = VALUE;
class CommonOptTable : public opt::OptTable {
public:
CommonOptTable(ArrayRef<Info> OptionInfos, const char *Usage,
const char *Description)
: OptTable(OptionInfos), Usage(Usage), Description(Description) {
setGroupedShortOptions(true);
}
void printHelp(StringRef Argv0, bool ShowHidden = false) const {
Argv0 = sys::path::filename(Argv0);
PrintHelp(outs(), (Argv0 + Usage).str().c_str(), Description, ShowHidden,
ShowHidden);
// TODO Replace this with OptTable API once it adds extrahelp support.
outs() << "\nPass @FILE as argument to read options from FILE.\n";
}
private:
const char *Usage;
const char *Description;
};
// ObjdumpOptID is in ObjdumpOptID.h
#define PREFIX(NAME, VALUE) const char *const OBJDUMP_##NAME[] = VALUE;
#include "ObjdumpOpts.inc"
#undef PREFIX
static constexpr opt::OptTable::Info ObjdumpInfoTable[] = {
#define OBJDUMP_nullptr nullptr
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR, VALUES) \
{PREFIX, NAME, HELPTEXT, \
METAVAR, OBJDUMP_##ID, opt::Option::KIND##Class, \
PARAM, FLAGS, OBJDUMP_##GROUP, \
OBJDUMP_##ALIAS, ALIASARGS, VALUES},
{OBJDUMP_##PREFIX, NAME, HELPTEXT, \
METAVAR, OBJDUMP_##ID, opt::Option::KIND##Class, \
PARAM, FLAGS, OBJDUMP_##GROUP, \
OBJDUMP_##ALIAS, ALIASARGS, VALUES},
#include "ObjdumpOpts.inc"
#undef OPTION
#undef OBJDUMP_nullptr
};
class ObjdumpOptTable : public CommonOptTable {
public:
ObjdumpOptTable()
: CommonOptTable(ObjdumpInfoTable, " [options] <input object files>",
"llvm object file dumper") {}
};
enum OtoolOptID {
OTOOL_INVALID = 0, // This is not an option ID.
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR, VALUES) \
OTOOL_##ID,
#include "OtoolOpts.inc"
#undef OPTION
};
class ObjdumpOptTable : public opt::OptTable {
public:
ObjdumpOptTable() : OptTable(ObjdumpInfoTable) {}
#define PREFIX(NAME, VALUE) const char *const OTOOL_##NAME[] = VALUE;
#include "OtoolOpts.inc"
#undef PREFIX
void PrintObjdumpHelp(StringRef Argv0, bool ShowHidden = false) const {
Argv0 = sys::path::filename(Argv0);
PrintHelp(outs(), (Argv0 + " [options] <input object files>").str().c_str(),
"llvm object file dumper", ShowHidden, ShowHidden);
// TODO Replace this with OptTable API once it adds extrahelp support.
outs() << "\nPass @FILE as argument to read options from FILE.\n";
}
static constexpr opt::OptTable::Info OtoolInfoTable[] = {
#define OTOOL_nullptr nullptr
#define OPTION(PREFIX, NAME, ID, KIND, GROUP, ALIAS, ALIASARGS, FLAGS, PARAM, \
HELPTEXT, METAVAR, VALUES) \
{OTOOL_##PREFIX, NAME, HELPTEXT, \
METAVAR, OTOOL_##ID, opt::Option::KIND##Class, \
PARAM, FLAGS, OTOOL_##GROUP, \
OTOOL_##ALIAS, ALIASARGS, VALUES},
#include "OtoolOpts.inc"
#undef OPTION
#undef OTOOL_nullptr
};
class OtoolOptTable : public CommonOptTable {
public:
OtoolOptTable()
: CommonOptTable(OtoolInfoTable, " [option...] [file...]",
"Mach-O object file displaying tool") {}
};
} // namespace
@ -2787,7 +2839,55 @@ commaSeparatedValues(const llvm::opt::InputArgList &InputArgs, int ID) {
return Values;
}
static void parseOptions(const llvm::opt::InputArgList &InputArgs) {
static void parseOtoolOptions(const llvm::opt::InputArgList &InputArgs) {
MachOOpt = true;
FullLeadingAddr = true;
PrintImmHex = true;
ArchName = InputArgs.getLastArgValue(OTOOL_arch).str();
LinkOptHints = InputArgs.hasArg(OTOOL_C);
if (InputArgs.hasArg(OTOOL_d))
FilterSections.push_back("__DATA,__data");
DylibId = InputArgs.hasArg(OTOOL_D);
UniversalHeaders = InputArgs.hasArg(OTOOL_f);
DataInCode = InputArgs.hasArg(OTOOL_G);
FirstPrivateHeader = InputArgs.hasArg(OTOOL_h);
IndirectSymbols = InputArgs.hasArg(OTOOL_I);
NoShowRawInsn = !InputArgs.hasArg(OTOOL_j);
PrivateHeaders = InputArgs.hasArg(OTOOL_l);
DylibsUsed = InputArgs.hasArg(OTOOL_L);
MCPU = InputArgs.getLastArgValue(OTOOL_mcpu_EQ).str();
ObjcMetaData = InputArgs.hasArg(OTOOL_o);
DisSymName = InputArgs.getLastArgValue(OTOOL_p).str();
InfoPlist = InputArgs.hasArg(OTOOL_P);
Relocations = InputArgs.hasArg(OTOOL_r);
if (const Arg *A = InputArgs.getLastArg(OTOOL_s)) {
auto Filter = (A->getValue(0) + StringRef(",") + A->getValue(1)).str();
FilterSections.push_back(Filter);
}
if (InputArgs.hasArg(OTOOL_t))
FilterSections.push_back("__TEXT,__text");
NonVerbose = !(InputArgs.hasArg(OTOOL_v) || InputArgs.hasArg(OTOOL_V) ||
InputArgs.hasArg(OTOOL_o));
NoSymbolicOperands = !InputArgs.hasArg(OTOOL_V);
if (InputArgs.hasArg(OTOOL_x))
FilterSections.push_back(",__text");
NoLeadingAddr = NoLeadingHeaders = InputArgs.hasArg(OTOOL_X);
InputFilenames = InputArgs.getAllArgValues(OTOOL_INPUT);
if (InputFilenames.empty())
reportCmdLineError("no input file");
for (const Arg *A : InputArgs) {
const Option &O = A->getOption();
if (O.getGroup().isValid() && O.getGroup().getID() == OTOOL_grp_obsolete) {
reportCmdLineWarning(O.getPrefixedName() +
" is obsolete and not implemented");
}
}
}
static void parseObjdumpOptions(const llvm::opt::InputArgList &InputArgs) {
parseIntArg(InputArgs, OBJDUMP_adjust_vma_EQ, AdjustVMA);
AllHeaders = InputArgs.hasArg(OBJDUMP_all_headers);
ArchName = InputArgs.getLastArgValue(OBJDUMP_arch_name_EQ).str();
@ -2880,6 +2980,10 @@ static void parseOptions(const llvm::opt::InputArgList &InputArgs) {
LLVMArgs.push_back("--riscv-no-aliases");
LLVMArgs.push_back(nullptr);
llvm::cl::ParseCommandLineOptions(LLVMArgs.size() - 1, LLVMArgs.data());
// objdump defaults to a.out if no filenames specified.
if (InputFilenames.empty())
InputFilenames.push_back("a.out");
}
int main(int argc, char **argv) {
@ -2887,27 +2991,46 @@ int main(int argc, char **argv) {
InitLLVM X(argc, argv);
ToolName = argv[0];
std::unique_ptr<CommonOptTable> T;
OptSpecifier Unknown, HelpFlag, HelpHiddenFlag, VersionFlag;
ObjdumpOptTable T;
T.setGroupedShortOptions(true);
StringRef Stem = sys::path::stem(ToolName);
auto Is = [=](StringRef Tool) {
// We need to recognize the following filenames:
//
// llvm-objdump -> objdump
// llvm-otool-10.exe -> otool
// powerpc64-unknown-freebsd13-objdump -> objdump
auto I = Stem.rfind_lower(Tool);
return I != StringRef::npos &&
(I + Tool.size() == Stem.size() || !isAlnum(Stem[I + Tool.size()]));
};
if (Is("otool")) {
T = std::make_unique<OtoolOptTable>();
Unknown = OTOOL_UNKNOWN;
HelpFlag = OTOOL_help;
HelpHiddenFlag = OTOOL_help_hidden;
VersionFlag = OTOOL_version;
} else {
T = std::make_unique<ObjdumpOptTable>();
Unknown = OBJDUMP_UNKNOWN;
HelpFlag = OBJDUMP_help;
HelpHiddenFlag = OBJDUMP_help_hidden;
VersionFlag = OBJDUMP_version;
}
bool HasError = false;
BumpPtrAllocator A;
StringSaver Saver(A);
opt::InputArgList InputArgs =
T.parseArgs(argc, argv, OBJDUMP_UNKNOWN, Saver, [&](StringRef Msg) {
errs() << "error: " << Msg << '\n';
HasError = true;
});
if (HasError)
exit(1);
T->parseArgs(argc, argv, Unknown, Saver,
[&](StringRef Msg) { reportCmdLineError(Msg); });
if (InputArgs.size() == 0 || InputArgs.hasArg(OBJDUMP_help)) {
T.PrintObjdumpHelp(ToolName);
if (InputArgs.size() == 0 || InputArgs.hasArg(HelpFlag)) {
T->printHelp(ToolName);
return 0;
}
if (InputArgs.hasArg(OBJDUMP_help_hidden)) {
T.PrintObjdumpHelp(ToolName, /*show_hidden=*/true);
if (InputArgs.hasArg(HelpHiddenFlag)) {
T->printHelp(ToolName, /*show_hidden=*/true);
return 0;
}
@ -2916,23 +3039,23 @@ int main(int argc, char **argv) {
InitializeAllTargetMCs();
InitializeAllDisassemblers();
if (InputArgs.hasArg(OBJDUMP_version)) {
if (InputArgs.hasArg(VersionFlag)) {
cl::PrintVersionMessage();
outs() << '\n';
TargetRegistry::printRegisteredTargetsForVersion(outs());
exit(0);
if (!Is("otool")) {
outs() << '\n';
TargetRegistry::printRegisteredTargetsForVersion(outs());
}
return 0;
}
parseOptions(InputArgs);
if (Is("otool"))
parseOtoolOptions(InputArgs);
else
parseObjdumpOptions(InputArgs);
if (StartAddress >= StopAddress)
reportCmdLineError("start address should be less than stop address");
// Defaults to a.out if no filenames specified.
if (InputFilenames.empty())
InputFilenames.push_back("a.out");
// Removes trailing separators from prefix.
while (!Prefix.empty() && sys::path::is_separator(Prefix.back()))
Prefix.pop_back();
@ -2954,7 +3077,7 @@ int main(int argc, char **argv) {
FirstPrivateHeader || FunctionStarts || IndirectSymbols || InfoPlist ||
LazyBind || LinkOptHints || ObjcMetaData || Rebase ||
UniversalHeaders || WeakBind || !FilterSections.empty()))) {
T.PrintObjdumpHelp(ToolName);
T->printHelp(ToolName);
return 2;
}

View File

@ -250,7 +250,7 @@ group("test") {
"//llvm/tools/llvm-mt",
"//llvm/tools/llvm-nm",
"//llvm/tools/llvm-objcopy:symlinks",
"//llvm/tools/llvm-objdump",
"//llvm/tools/llvm-objdump:symlinks",
"//llvm/tools/llvm-opt-fuzzer",
"//llvm/tools/llvm-opt-report",
"//llvm/tools/llvm-pdbutil",

View File

@ -7,25 +7,36 @@ tablegen("ObjdumpOpts") {
args = [ "-gen-opt-parser-defs" ]
}
tablegen("OtoolOpts") {
visibility = [ ":llvm-objdump" ]
args = [ "-gen-opt-parser-defs" ]
}
symlinks = [ "llvm-otool" ]
if (llvm_install_binutils_symlinks) {
symlink_or_copy("objdump") {
symlinks += [ "objdump" ]
}
foreach(target, symlinks) {
symlink_or_copy(target) {
deps = [ ":llvm-objdump" ]
source = "llvm-objdump"
output = "$root_out_dir/bin/objdump"
output = "$root_out_dir/bin/$target"
}
}
# //:llvm-objdump depends on this symlink target, see comment in //BUILD.gn.
group("symlinks") {
deps = [ ":llvm-objdump" ]
if (llvm_install_binutils_symlinks) {
deps += [ ":objdump" ]
foreach(target, symlinks) {
deps += [ ":$target" ]
}
}
executable("llvm-objdump") {
deps = [
":ObjdumpOpts",
":OtoolOpts",
"//llvm/include/llvm/Config:config",
"//llvm/lib/CodeGen",
"//llvm/lib/DebugInfo/DWARF",