diff --git a/docs/CommandGuide/index.rst b/docs/CommandGuide/index.rst
index 19ec9cf700c..4f5c912bb41 100644
--- a/docs/CommandGuide/index.rst
+++ b/docs/CommandGuide/index.rst
@@ -29,6 +29,7 @@ Basic Commands
llvm-link
llvm-lipo
llvm-mca
+ llvm-otool
llvm-profdata
llvm-readobj
llvm-stress
diff --git a/docs/CommandGuide/llvm-objdump.rst b/docs/CommandGuide/llvm-objdump.rst
index 49edbcd91b0..acfe8076366 100644
--- a/docs/CommandGuide/llvm-objdump.rst
+++ b/docs/CommandGuide/llvm-objdump.rst
@@ -390,4 +390,5 @@ To report bugs, please visit .
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)`
diff --git a/docs/CommandGuide/llvm-otool.rst b/docs/CommandGuide/llvm-otool.rst
new file mode 100644
index 00000000000..9284bd946bb
--- /dev/null
+++ b/docs/CommandGuide/llvm-otool.rst
@@ -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
+
+ 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=
+
+ Select cpu for disassembly.
+
+.. option:: -o
+
+ Print Objective-C segment.
+
+.. option:: -P
+
+ Print __TEXT,__info_plist section as strings.
+
+.. option:: -p
+
+ Start disassembly at .
+
+.. option:: -r
+
+ Print relocation entries.
+
+.. option:: -s
+
+ 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:: @
+
+ Read command-line options and commands from response 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 .
+
+SEE ALSO
+--------
+
+:manpage:`llvm-nm(1)`, :manpage:`llvm-objdump(1)`
diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt
index 81107be862d..bd02027c060 100644
--- a/test/CMakeLists.txt
+++ b/test/CMakeLists.txt
@@ -100,6 +100,7 @@ set(LLVM_TEST_DEPENDS
llvm-objdump
llvm-opt-fuzzer
llvm-opt-report
+ llvm-otool
llvm-pdbutil
llvm-profdata
llvm-profgen
diff --git a/test/lit.cfg.py b/test/lit.cfg.py
index db94537bb46..89c7497d0cd 100644
--- a/test/lit.cfg.py
+++ b/test/lit.cfg.py
@@ -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',
diff --git a/test/tools/llvm-objdump/MachO/AArch64/macho-link-opt-hints.test b/test/tools/llvm-objdump/MachO/AArch64/macho-link-opt-hints.test
index 2f39aba92af..2cd044a3be3 100644
--- a/test/tools/llvm-objdump/MachO/AArch64/macho-link-opt-hints.test
+++ b/test/tools/llvm-objdump/MachO/AArch64/macho-link-opt-hints.test
@@ -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
diff --git a/test/tools/llvm-objdump/MachO/ARM/data-in-code.test b/test/tools/llvm-objdump/MachO/ARM/data-in-code.test
index b2f2b3e09a2..f0d8f43a4b7 100644
--- a/test/tools/llvm-objdump/MachO/ARM/data-in-code.test
+++ b/test/tools/llvm-objdump/MachO/ARM/data-in-code.test
@@ -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
diff --git a/test/tools/llvm-objdump/MachO/ARM/mcpu-arm.test b/test/tools/llvm-objdump/MachO/ARM/mcpu-arm.test
index fed00c5fdb9..6d2577c00c9 100644
--- a/test/tools/llvm-objdump/MachO/ARM/mcpu-arm.test
+++ b/test/tools/llvm-objdump/MachO/ARM/mcpu-arm.test
@@ -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
diff --git a/test/tools/llvm-objdump/MachO/data-in-code.ll b/test/tools/llvm-objdump/MachO/data-in-code.ll
index de78203c98c..d214bf65322 100644
--- a/test/tools/llvm-objdump/MachO/data-in-code.ll
+++ b/test/tools/llvm-objdump/MachO/data-in-code.ll
@@ -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
diff --git a/test/tools/llvm-objdump/MachO/dis-no-leading-addr.test b/test/tools/llvm-objdump/MachO/dis-no-leading-addr.test
index 57d328ea3a2..28319920d01 100644
--- a/test/tools/llvm-objdump/MachO/dis-no-leading-addr.test
+++ b/test/tools/llvm-objdump/MachO/dis-no-leading-addr.test
@@ -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
diff --git a/test/tools/llvm-objdump/MachO/dis-symname.test b/test/tools/llvm-objdump/MachO/dis-symname.test
index 9c7a341e33b..5990095725d 100644
--- a/test/tools/llvm-objdump/MachO/dis-symname.test
+++ b/test/tools/llvm-objdump/MachO/dis-symname.test
@@ -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
diff --git a/test/tools/llvm-objdump/MachO/dylib.test b/test/tools/llvm-objdump/MachO/dylib.test
index 32c64f019c4..01fb4c6334a 100644
--- a/test/tools/llvm-objdump/MachO/dylib.test
+++ b/test/tools/llvm-objdump/MachO/dylib.test
@@ -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
diff --git a/test/tools/llvm-objdump/MachO/indirect-symbols.test b/test/tools/llvm-objdump/MachO/indirect-symbols.test
index dcdb068e711..1615109b78e 100644
--- a/test/tools/llvm-objdump/MachO/indirect-symbols.test
+++ b/test/tools/llvm-objdump/MachO/indirect-symbols.test
@@ -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
diff --git a/test/tools/llvm-objdump/MachO/info-plist.test b/test/tools/llvm-objdump/MachO/info-plist.test
index 8370b6b3e39..a3390568a51 100644
--- a/test/tools/llvm-objdump/MachO/info-plist.test
+++ b/test/tools/llvm-objdump/MachO/info-plist.test
@@ -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 "\n"
diff --git a/test/tools/llvm-objdump/MachO/macho-objc-meta-data.test b/test/tools/llvm-objdump/MachO/macho-objc-meta-data.test
index 566bde6f458..7f0c7a4654d 100644
--- a/test/tools/llvm-objdump/MachO/macho-objc-meta-data.test
+++ b/test/tools/llvm-objdump/MachO/macho-objc-meta-data.test
@@ -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
diff --git a/test/tools/llvm-objdump/MachO/private-headers.test b/test/tools/llvm-objdump/MachO/private-headers.test
index 8ca13a383c7..c3a48820243 100644
--- a/test/tools/llvm-objdump/MachO/private-headers.test
+++ b/test/tools/llvm-objdump/MachO/private-headers.test
@@ -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 \
diff --git a/test/tools/llvm-objdump/MachO/relocations.test b/test/tools/llvm-objdump/MachO/relocations.test
index 95db5ec1ab2..bc6aba0aae9 100644
--- a/test/tools/llvm-objdump/MachO/relocations.test
+++ b/test/tools/llvm-objdump/MachO/relocations.test
@@ -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
diff --git a/test/tools/llvm-objdump/MachO/sections.test b/test/tools/llvm-objdump/MachO/sections.test
index 2bed7871b49..b39e1b5040f 100644
--- a/test/tools/llvm-objdump/MachO/sections.test
+++ b/test/tools/llvm-objdump/MachO/sections.test
@@ -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:
diff --git a/test/tools/llvm-objdump/MachO/symbolized-disassembly.test b/test/tools/llvm-objdump/MachO/symbolized-disassembly.test
index 31016a2c107..c01fb168fb1 100644
--- a/test/tools/llvm-objdump/MachO/symbolized-disassembly.test
+++ b/test/tools/llvm-objdump/MachO/symbolized-disassembly.test
@@ -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
diff --git a/test/tools/llvm-objdump/MachO/universal-arm64.test b/test/tools/llvm-objdump/MachO/universal-arm64.test
index e15b31159d2..4f39ee9a112 100644
--- a/test/tools/llvm-objdump/MachO/universal-arm64.test
+++ b/test/tools/llvm-objdump/MachO/universal-arm64.test
@@ -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
diff --git a/test/tools/llvm-objdump/tool-name.test b/test/tools/llvm-objdump/tool-name.test
new file mode 100644
index 00000000000..8aefce82c83
--- /dev/null
+++ b/test/tools/llvm-objdump/tool-name.test
@@ -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
diff --git a/tools/llvm-objdump/CMakeLists.txt b/tools/llvm-objdump/CMakeLists.txt
index 5a0c855b37c..89dea90d600 100644
--- a/tools/llvm-objdump/CMakeLists.txt
+++ b/tools/llvm-objdump/CMakeLists.txt
@@ -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()
diff --git a/tools/llvm-objdump/MachODump.cpp b/tools/llvm-objdump/MachODump.cpp
index fadb2999d20..170dcae90ae 100644
--- a/tools/llvm-objdump/MachODump.cpp
+++ b/tools/llvm-objdump/MachODump.cpp
@@ -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 ArchFlags;
static bool ArchAll = false;
diff --git a/tools/llvm-objdump/MachODump.h b/tools/llvm-objdump/MachODump.h
index 447749a23e5..70d8b80b361 100644
--- a/tools/llvm-objdump/MachODump.h
+++ b/tools/llvm-objdump/MachODump.h
@@ -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;
diff --git a/tools/llvm-objdump/ObjdumpOptID.h b/tools/llvm-objdump/ObjdumpOptID.h
index 2c17f441a03..65f6c60ad88 100644
--- a/tools/llvm-objdump/ObjdumpOptID.h
+++ b/tools/llvm-objdump/ObjdumpOptID.h
@@ -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) \
diff --git a/tools/llvm-objdump/OtoolOpts.td b/tools/llvm-objdump/OtoolOpts.td
new file mode 100644
index 00000000000..61ea701ed75
--- /dev/null
+++ b/tools/llvm-objdump/OtoolOpts.td
@@ -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<"">,
+ HelpText<"start disassembly at ">;
+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<" ">,
+ 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,
+ HelpText<"force Thum disassembly (ARM 32-bit objects only)">;
+def : Flag<["-"], "H">, Flags<[HelpHidden]>, Group,
+ HelpText<"print two-level hints table">;
+def : Flag<["-"], "M">, Flags<[HelpHidden]>, Group,
+ HelpText<"print module table of shared library">;
+def : Flag<["-"], "R">, Flags<[HelpHidden]>, Group,
+ HelpText<"print reference table of shared library">;
+def : Flag<["-"], "S">, Flags<[HelpHidden]>, Group,
+ HelpText<"print table of contents of library">;
+def : Flag<["-"], "T">, Flags<[HelpHidden]>, Group,
+ HelpText<"print table of contents of shared library">;
+def : Flag<["-"], "Q">, Flags<[HelpHidden]>, Group,
+ HelpText<"llvm-otool cannot use otool-classic's disassembler">;
diff --git a/tools/llvm-objdump/llvm-objdump.cpp b/tools/llvm-objdump/llvm-objdump.cpp
index 8490a9156d1..e0944683602 100644
--- a/tools/llvm-objdump/llvm-objdump.cpp
+++ b/tools/llvm-objdump/llvm-objdump.cpp
@@ -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 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] ",
+ "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] ").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 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();
+ Unknown = OTOOL_UNKNOWN;
+ HelpFlag = OTOOL_help;
+ HelpHiddenFlag = OTOOL_help_hidden;
+ VersionFlag = OTOOL_version;
+ } else {
+ T = std::make_unique();
+ 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;
}
diff --git a/utils/gn/secondary/llvm/test/BUILD.gn b/utils/gn/secondary/llvm/test/BUILD.gn
index 3ec55ddd2db..c381df75be0 100644
--- a/utils/gn/secondary/llvm/test/BUILD.gn
+++ b/utils/gn/secondary/llvm/test/BUILD.gn
@@ -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",
diff --git a/utils/gn/secondary/llvm/tools/llvm-objdump/BUILD.gn b/utils/gn/secondary/llvm/tools/llvm-objdump/BUILD.gn
index bdf650b3a50..33dfbc24efd 100644
--- a/utils/gn/secondary/llvm/tools/llvm-objdump/BUILD.gn
+++ b/utils/gn/secondary/llvm/tools/llvm-objdump/BUILD.gn
@@ -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",