-
Notifications
You must be signed in to change notification settings - Fork 15.2k
[llvm-objdump] Add the --visualize-jumps option #74858
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
8e9c663
ed7d814
4dd15ee
aa38a0a
2cb0e8d
7472b54
a8fd5df
13771da
cb709ed
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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. | ||
|
|
||
| If ``modes`` is omitted, the default is ``unicode,auto`` | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Unlike |
||
|
|
||
| .. option:: off | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 Oh, hang on, looking downwards, I see the |
||
|
|
||
| Disable control-flow graph | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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. | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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; | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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; | ||
| } | ||
|
|
||
| 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 | \ | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Omit
|
||
| // 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 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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: [0m 94000000 bl 0x0 <test_func> | ||
| 4: [0m 14000000 b 0x4 <test_func+0x4> | ||
| 8: [0;31m ╭[0;31m──[0m 14000001 b 0xc <test_func+0xc> | ||
| c: [0;31m ├[0;31m─>[0m d503201f nop | ||
| 10: [0;31m ╰[0;31m──[0m 17ffffff b 0xc <test_func+0xc> | ||
| 14: [0m 14000000 b 0x14 <test_func+0x14> | ||
| 18: [0;32m ╭[0;32m──[0m 54000040 b.eq 0x20 <test_func+0x20> | ||
| 1c: [0;32m ├[0;32m──[0m b4000020 cbz x0, 0x20 <test_func+0x20> | ||
| 20: [0;32m ╰[0;32m─>[0m d503201f nop | ||
| 24: [0;33m ╭[0;33m──[0;33m──[0;33m──[0m 14000005 b 0x38 <test_func+0x38> | ||
| 28: [0;33m │[0;34m ╭[0;34m──[0;34m──[0m 14000003 b 0x34 <test_func+0x34> | ||
| 2c: [0;33m │[0;34m │[0;35m ╭[0;35m──[0m 14000001 b 0x30 <test_func+0x30> | ||
| 30: [0;33m │[0;34m │[0;35m ╰[0;35m─>[0m d503201f nop | ||
| 34: [0;33m │[0;34m ╰[0;34m──[0;34m─>[0m d503201f nop | ||
| 38: [0;33m ╰[0;33m──[0;33m──[0;33m─>[0m d503201f nop | ||
| 3c: [0;36m ╭[0;36m──[0m 14000002 b 0x44 <test_func+0x44> | ||
| 40: [0;31m ╭[0;31m─[0;36m│[0;31m──[0m 14000002 b 0x48 <test_func+0x48> | ||
| 44: [0;31m │[0;36m ╰[0;36m─>[0m d503201f nop | ||
| 48: [0;31m ╰[0;31m──[0;31m─>[0m d503201f nop | ||
| 4c: [0;32m ╭[0;32m──[0m 14000001 b 0x50 <test_func+0x50> | ||
| 50: [0;33m ╭[0;33m─[0;32m│[0;33m──[0m 14000001 b 0x54 <test_func+0x54> | ||
| 54: [0;33m ╰[0;33m──[0;33m─>[0m d503201f nop | ||
| 58: [0;34m ╭[0;34m──[0m 14000002 b 0x60 <test_func+0x60> | ||
| 5c: [0;34m │ [0m 94000000 bl 0x5c <test_func+0x5c> | ||
| 60: [0;34m ╰[0;34m─>[0m 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 | ||
| 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 |
There was a problem hiding this comment.
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.