Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions llvm/docs/CommandGuide/llvm-objdump.rst
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,36 @@ OPTIONS

Target triple to disassemble for, see ``--version`` for available targets.

.. option:: --visualize-jumps=<modes>

Display a control-flow graph which shows the targets of branch instructions to the left of disasembly. ``modes`` is a comma-separated list of options, which configure the character set and used to print the graph.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably should be wrapped at a sensible width.


If ``modes`` is omitted, the default is ``unicode,auto``
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unlike .td help messages, the documentation descriptions should have a trailing period.


.. option:: off
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you built and inspected the documentation? I don't have a currently working doc build, so I can't myself, but I'd be slightly concerned that this would look like a general command, rather than an argument of the --visualize-jumps option. --disassembler-color uses a different format. Perhaps that should be what you follow for consistency?

Oh, hang on, looking downwards, I see the --x86-asm-syntax=<style> is formatted this way. I personally prefer the bullet points of --disassembler-color (plus it's used in another place too), so I still think you should change.


Disable control-flow graph
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: all of these should end with "."


.. option:: ascii

Render control-flow graph using ASCII characters

.. option:: unicode

Render control-flow graph using unicode box-drawing characters

.. option:: nocolor

Render control-flow graph without using colors

.. option:: auto

Render control-flow graph using colors if supported by the terminal

.. option:: color

Render control-flow graph using colors

.. option:: -w, --wide

Ignored for compatibility with GNU objdump.
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Support/FormattedStream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ void formatted_raw_ostream::UpdatePosition(const char *Ptr, size_t Size) {
break;
case '\t':
// Assumes tab stop = 8 characters.
Column += 1;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm concerned this will have a wider impact on tools than just llvm-objdump. What's it actually doing?

Column += (8 - (Column & 0x7)) & 0x7;
break;
}
Expand Down
204 changes: 204 additions & 0 deletions llvm/test/tools/llvm-objdump/visualize-jumps-aarch64.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,204 @@
# RUN: rm -rf %t && split-file %s %t && cd %t

// RUN: llvm-mc < input.s -triple aarch64 -filetype=obj | \
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Omit < for llvm-mc

REQUIRES: aarch64-registered-target is needed unless you place it in ELF/AArch64

// RUN: llvm-objdump --triple aarch64 -d --visualize-jumps=unicode - | \
// RUN: diff - expected-unicode.txt

// RUN: llvm-mc < input.s -triple aarch64 -filetype=obj | \
// RUN: llvm-objdump --triple aarch64 -d --visualize-jumps=ascii - | \
// RUN: diff - expected-ascii.txt

// RUN: llvm-mc < input.s -triple aarch64 -filetype=obj | \
// RUN: llvm-objdump --triple aarch64 -d --visualize-jumps=unicode,color - | \
// RUN: diff - expected-unicode-color.txt

// RUN: llvm-mc < input.s -triple aarch64 -filetype=obj | \
// RUN: llvm-objdump --triple aarch64 -d --visualize-jumps=unicode --reloc - | \
// RUN: diff - expected-unicode-relocs.txt

//--- input.s
test_func:
// Relocated instructions don't get control-flow edges.
bl extern_func
b extern_func

// Two branches to the same label, one forward and one backward.
b .Llabel1
.Llabel1:
nop
b .Llabel1

// Branch to self, no CFG edge shown
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: missing full stop, here and in other comments.

b .

// Conditional branches
b.eq .Llabel2
cbz x0, .Llabel2
.Llabel2:
nop

// Branches are sorted with shorter ones to the right, to reduce number of
// crossings, and keep the lines for short branches short themselves.
b .Llabel5
b .Llabel4
b .Llabel3
.Llabel3:
nop
.Llabel4:
nop
.Llabel5:
nop

// Sometimes crossings can't be avoided.
b .Llabel6
b .Llabel7
.Llabel6:
nop
.Llabel7:
nop

// TODO If a branch goes to another branch instruction, we don't have a way
// to represent that. Can we improve on this?
b .Llabel8
.Llabel8:
b .Llabel9
.Llabel9:
nop

// Graph lines need to be drawn on the same output line as relocations.
b .Llabel10
bl extern_func
.Llabel10:
nop

//--- expected-unicode.txt

<stdin>: file format elf64-littleaarch64

Disassembly of section .text:

0000000000000000 <test_func>:
0: 94000000 bl 0x0 <test_func>
4: 14000000 b 0x4 <test_func+0x4>
8: ╭── 14000001 b 0xc <test_func+0xc>
c: ├─> d503201f nop
10: ╰── 17ffffff b 0xc <test_func+0xc>
14: 14000000 b 0x14 <test_func+0x14>
18: ╭── 54000040 b.eq 0x20 <test_func+0x20>
1c: ├── b4000020 cbz x0, 0x20 <test_func+0x20>
20: ╰─> d503201f nop
24: ╭────── 14000005 b 0x38 <test_func+0x38>
28: │ ╭──── 14000003 b 0x34 <test_func+0x34>
2c: │ │ ╭── 14000001 b 0x30 <test_func+0x30>
30: │ │ ╰─> d503201f nop
34: │ ╰───> d503201f nop
38: ╰─────> d503201f nop
3c: ╭── 14000002 b 0x44 <test_func+0x44>
40: ╭─│── 14000002 b 0x48 <test_func+0x48>
44: │ ╰─> d503201f nop
48: ╰───> d503201f nop
4c: ╭── 14000001 b 0x50 <test_func+0x50>
50: ╭─│── 14000001 b 0x54 <test_func+0x54>
54: ╰───> d503201f nop
58: ╭── 14000002 b 0x60 <test_func+0x60>
5c:94000000 bl 0x5c <test_func+0x5c>
60: ╰─> d503201f nop
//--- expected-ascii.txt

<stdin>: file format elf64-littleaarch64

Disassembly of section .text:

0000000000000000 <test_func>:
0: 94000000 bl 0x0 <test_func>
4: 14000000 b 0x4 <test_func+0x4>
8: /-- 14000001 b 0xc <test_func+0xc>
c: +-> d503201f nop
10: \-- 17ffffff b 0xc <test_func+0xc>
14: 14000000 b 0x14 <test_func+0x14>
18: /-- 54000040 b.eq 0x20 <test_func+0x20>
1c: +-- b4000020 cbz x0, 0x20 <test_func+0x20>
20: \-> d503201f nop
24: /------ 14000005 b 0x38 <test_func+0x38>
28: | /---- 14000003 b 0x34 <test_func+0x34>
2c: | | /-- 14000001 b 0x30 <test_func+0x30>
30: | | \-> d503201f nop
34: | \---> d503201f nop
38: \-----> d503201f nop
3c: /-- 14000002 b 0x44 <test_func+0x44>
40: /-|-- 14000002 b 0x48 <test_func+0x48>
44: | \-> d503201f nop
48: \---> d503201f nop
4c: /-- 14000001 b 0x50 <test_func+0x50>
50: /-|-- 14000001 b 0x54 <test_func+0x54>
54: \---> d503201f nop
58: /-- 14000002 b 0x60 <test_func+0x60>
5c: | 94000000 bl 0x5c <test_func+0x5c>
60: \-> d503201f nop
//--- expected-unicode-color.txt

<stdin>: file format elf64-littleaarch64

Disassembly of section .text:

0000000000000000 <test_func>:
0:  94000000 bl 0x0 <test_func>
4:  14000000 b 0x4 <test_func+0x4>
8:  ╭── 14000001 b 0xc <test_func+0xc>
c:  ├─> d503201f nop
10:  ╰── 17ffffff b 0xc <test_func+0xc>
14:  14000000 b 0x14 <test_func+0x14>
18:  ╭── 54000040 b.eq 0x20 <test_func+0x20>
1c:  ├── b4000020 cbz x0, 0x20 <test_func+0x20>
20:  ╰─> d503201f nop
24:  ╭────── 14000005 b 0x38 <test_func+0x38>
28:  │ ╭──── 14000003 b 0x34 <test_func+0x34>
2c:  │ │ ╭── 14000001 b 0x30 <test_func+0x30>
30:  │ │ ╰─> d503201f nop
34:  │ ╰───> d503201f nop
38:  ╰─────> d503201f nop
3c:  ╭── 14000002 b 0x44 <test_func+0x44>
40:  ╭─│── 14000002 b 0x48 <test_func+0x48>
44:  │ ╰─> d503201f nop
48:  ╰───> d503201f nop
4c:  ╭── 14000001 b 0x50 <test_func+0x50>
50:  ╭─│── 14000001 b 0x54 <test_func+0x54>
54:  ╰───> d503201f nop
58:  ╭── 14000002 b 0x60 <test_func+0x60>
5c:  │  94000000 bl 0x5c <test_func+0x5c>
60:  ╰─> d503201f nop
//--- expected-unicode-relocs.txt

<stdin>: file format elf64-littleaarch64

Disassembly of section .text:

0000000000000000 <test_func>:
0: 94000000 bl 0x0 <test_func>
0000000000000000: R_AARCH64_CALL26 extern_func
4: 14000000 b 0x4 <test_func+0x4>
0000000000000004: R_AARCH64_JUMP26 extern_func
8: ╭── 14000001 b 0xc <test_func+0xc>
c: ├─> d503201f nop
10: ╰── 17ffffff b 0xc <test_func+0xc>
14: 14000000 b 0x14 <test_func+0x14>
18: ╭── 54000040 b.eq 0x20 <test_func+0x20>
1c: ├── b4000020 cbz x0, 0x20 <test_func+0x20>
20: ╰─> d503201f nop
24: ╭────── 14000005 b 0x38 <test_func+0x38>
28: │ ╭──── 14000003 b 0x34 <test_func+0x34>
2c: │ │ ╭── 14000001 b 0x30 <test_func+0x30>
30: │ │ ╰─> d503201f nop
34: │ ╰───> d503201f nop
38: ╰─────> d503201f nop
3c: ╭── 14000002 b 0x44 <test_func+0x44>
40: ╭─│── 14000002 b 0x48 <test_func+0x48>
44: │ ╰─> d503201f nop
48: ╰───> d503201f nop
4c: ╭── 14000001 b 0x50 <test_func+0x50>
50: ╭─│── 14000001 b 0x54 <test_func+0x54>
54: ╰───> d503201f nop
58: ╭── 14000002 b 0x60 <test_func+0x60>
5c:94000000 bl 0x5c <test_func+0x5c>
000000000000005c: R_AARCH64_CALL26 extern_func
60: ╰─> d503201f nop
114 changes: 114 additions & 0 deletions llvm/test/tools/llvm-objdump/visualize-jumps-arm.s
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
// RUN: rm -rf %t && split-file %s %t && cd %t

// RUN: llvm-mc < input.s -triple armv8a -filetype=obj | \
// RUN: llvm-objdump --triple armv8a -d --visualize-jumps=unicode - | \
// RUN: diff - expected-unicode.txt

// RUN: llvm-mc < input.s -triple armv8a -filetype=obj | \
// RUN: llvm-objdump --triple armv8a -d --visualize-jumps=ascii - | \
// RUN: diff - expected-ascii.txt

//--- input.s
test_func:
// Relocated instructions don't get control-flow edges.
bl extern_func
b extern_func

// Two branches to the same label, one forward and one backward.
b .Llabel1
.Llabel1:
nop
b .Llabel1

// Branch to self, no CFG edge shown
b .

// Conditional branches
beq .Llabel2
.Llabel2:
nop

// Branches are sorted with shorter ones to the right, to reduce number of
// crossings, and keep the lines for short branches short themselves.
b .Llabel5
b .Llabel4
b .Llabel3
.Llabel3:
nop
.Llabel4:
nop
.Llabel5:
nop

// Sometimes crossings can't be avoided.
b .Llabel6
b .Llabel7
.Llabel6:
nop
.Llabel7:
nop

// TODO If a branch goes to another branch instruction, we don't have a way
// to represent that. Can we improve on this?
b .Llabel8
.Llabel8:
b .Llabel9
.Llabel9:
nop

//--- expected-unicode.txt

<stdin>: file format elf32-littlearm

Disassembly of section .text:

00000000 <test_func>:
0: ebfffffe bl 0x0 <test_func> @ imm = #-0x8
4: eafffffe b 0x4 <test_func+0x4> @ imm = #-0x8
8: ╭── eaffffff b 0xc <test_func+0xc> @ imm = #-0x4
c: ├─> e320f000 nop
10: ╰── eafffffd b 0xc <test_func+0xc> @ imm = #-0xc
14: eafffffe b 0x14 <test_func+0x14> @ imm = #-0x8
18: ╭── 0affffff beq 0x1c <test_func+0x1c> @ imm = #-0x4
1c: ╰─> e320f000 nop
20: ╭────── ea000003 b 0x34 <test_func+0x34> @ imm = #0xc
24: │ ╭──── ea000001 b 0x30 <test_func+0x30> @ imm = #0x4
28: │ │ ╭── eaffffff b 0x2c <test_func+0x2c> @ imm = #-0x4
2c: │ │ ╰─> e320f000 nop
30: │ ╰───> e320f000 nop
34: ╰─────> e320f000 nop
38: ╭── ea000000 b 0x40 <test_func+0x40> @ imm = #0x0
3c: ╭─│── ea000000 b 0x44 <test_func+0x44> @ imm = #0x0
40: │ ╰─> e320f000 nop
44: ╰───> e320f000 nop
48: ╭──── eaffffff b 0x4c <test_func+0x4c> @ imm = #-0x4
4c: ╰─│─> eaffffff b 0x50 <test_func+0x50> @ imm = #-0x4
50: ╰─> e320f000 nop
//--- expected-ascii.txt

<stdin>: file format elf32-littlearm

Disassembly of section .text:

00000000 <test_func>:
0: ebfffffe bl 0x0 <test_func> @ imm = #-0x8
4: eafffffe b 0x4 <test_func+0x4> @ imm = #-0x8
8: /-- eaffffff b 0xc <test_func+0xc> @ imm = #-0x4
c: +-> e320f000 nop
10: \-- eafffffd b 0xc <test_func+0xc> @ imm = #-0xc
14: eafffffe b 0x14 <test_func+0x14> @ imm = #-0x8
18: /-- 0affffff beq 0x1c <test_func+0x1c> @ imm = #-0x4
1c: \-> e320f000 nop
20: /------ ea000003 b 0x34 <test_func+0x34> @ imm = #0xc
24: | /---- ea000001 b 0x30 <test_func+0x30> @ imm = #0x4
28: | | /-- eaffffff b 0x2c <test_func+0x2c> @ imm = #-0x4
2c: | | \-> e320f000 nop
30: | \---> e320f000 nop
34: \-----> e320f000 nop
38: /-- ea000000 b 0x40 <test_func+0x40> @ imm = #0x0
3c: /-|-- ea000000 b 0x44 <test_func+0x44> @ imm = #0x0
40: | \-> e320f000 nop
44: \---> e320f000 nop
48: /---- eaffffff b 0x4c <test_func+0x4c> @ imm = #-0x4
4c: \-|-> eaffffff b 0x50 <test_func+0x50> @ imm = #-0x4
50: \-> e320f000 nop
Loading