Better way than a terminal+objdump to read assembly?
Asked Answered
B

1

5

For example if I'm in perf report I can press enter to follow a branch. If a bin was using -g some source shows up too.

I don't really need the source but it'd be very convenient if I could follow the jumps. What can I do to make reading assembly easier? Since I'm on linux I ended up running perf and using report to read this

Bipetalous answered 14/12, 2022 at 4:30 Comment(4)
objdump -d --visualize-jumps=color is interesting, although unusable on a large binary as it has so many columns of lines. Agner Fog's objconv disassembler will create branch targets, making it easier to find the tops of loops, example in How to disassemble a binary executable in Linux to get the assembly code? . Other answers show examples of objdump -d -S to mix source and asm.Epicurean
@PeterCordes thats pretty good. If this is an answer I'd accept itBipetalous
IDA, Binary Ninja, Radare2, Hopper (for macOS), Ghidra. All are far better alternatives than objdump for reading a disassembly. You can double-click on a jump to reach its target and all show the graph of basic blocks.Walley
Which is your favorite? Which works on linux? I do have a mac (ARM) so I can try hopperBipetalous
E
4

objdump -d --visualize-jumps=color is interesting, although unusable on a large binary as it has so many columns of lines. In a random smaller binary I had lying around (from testing alignment of 64-bit _Atomic vars in 32-bit mode, in case anyone's curious; this binary was from clang):

objdump -drwC -Mintel --visualize-jumps=color

...
 726:                e8 a5 fd ff ff             call   4d0 <pthread_create@plt>
 72b:                83 c4 10                   add    esp,0x10
 72e:                85 c0                      test   eax,eax
 730:      /-------- 75 62                      jne    794 <main+0xb4>
 732:   /--|-------> c5 f8 57 c0                vxorps xmm0,xmm0,xmm0
 736:   |  |         c5 fb 10 8e 48 e8 ff ff    vmovsd xmm1,QWORD PTR [esi-0x17b8]
 73e:   |  |         66 90                      xchg   ax,ax
 740:   |  |  /----> 31 c0                      xor    eax,eax
 742:   |  |  |      31 d2                      xor    edx,edx
 744:   |  |  |      31 c9                      xor    ecx,ecx
 746:   |  |  |      31 db                      xor    ebx,ebx
 748:   |  |  |      f0 0f c7 8e c0 00 00 00    lock cmpxchg8b QWORD PTR [esi+0xc0]
 750:   |  |  |      c5 f9 6e d0                vmovd  xmm2,eax
 754:   |  |  |      c4 e3 69 22 d2 01          vpinsrd xmm2,xmm2,edx,0x1
 75a:   |  |  |      c5 f9 2e d0                vucomisd xmm2,xmm0
 75e:   |  |  |  /-- 75 02                      jne    762 <main+0x82>
 760:   |  |  +--|-- 7b de                      jnp    740 <main+0x60>
 762:   |  |  |  \-> c5 f9 2e d1                vucomisd xmm2,xmm1
 766:   |  |  |  /-- 75 02                      jne    76a <main+0x8a>
 768:   |  |  \--|-- 7b d6                      jnp    740 <main+0x60>
 76a:   |  |     \-> 83 ec 04                   sub    esp,0x4

...

Agner Fog's objconv disassembler makes output that's ready to assemble, including labels on branch targets, making it easier to find the tops of loops. Example output in How to disassemble a binary executable in Linux to get the assembly code? Other answers show examples of objdump -d -S to mix source and asm.


Also related: How to remove "noise" from GCC/clang assembly output? I usually look at gcc -O3 ... -S output instead of assembling into a binary. Unless I already have a specific binary. The Godbolt compiler explorer has good tools for finding asm associated with a source line, like a loop body, which works most of the time depending on the debug info generated by compilers.

Epicurean answered 14/12, 2022 at 6:8 Comment(6)
Great idea with -S. I used that before but I don't think I ever used it with the intention of reading the assembly (without modifying it). I tried objconv and will try the rest of your suggestionsBipetalous
And BTW, --visualize-jumps=color actually is colorized on a terminal to help you track which line is which, but SO code blocks don't support that even if I did copy/paste the ANSI escape sequences.Epicurean
Is this functionality available for arm binaries as well? I've tried this flag with aarch64-linux-gnu-objdump, but it doesn't seem to output any arrows.Seeley
@NikosMavrogeorgis: Apparently not for AArch64. It did work for me with arm-none-eabi-objdump from GNU Binutils 2.40, but not the same version of aarch64-linux-gnu-objdump. (On a compiler-generated .o with a function that had b and b.hi instructions.)Epicurean
Thank you for checking. I would expect that it's straightforward to replicate the functionality for AArch64 as well, but perhaps nobody took up the task yet.Seeley
@NikosMavrogeorgis: Yes, exactly what I was thinking. objdump does already need to know which instructions are branches so it can print the absolute target address like b.hi 24 <fib+0x24>, but probably the visualization was a recent addition and needs separate per-target code for some reason, which nobody's written yet.Epicurean

© 2022 - 2024 — McMap. All rights reserved.