Looking at the output of objdump -d ELFfile
, I could not distinguish between direct and indirect Jumps/calls. Any suggestions?
objdump displays information about one or more object files. The options control what particular information to display. This information is mostly useful to programmers who are working on the compilation tools, as opposed to programmers who just want their program to compile and work.
Similarly, you can use the -D command-line option to make objdump display assembler contents of all sections, and -S option to make sure the tool intermixes source code with disassembly.
Indirect calls and jumps have a *
after the instruction and before the location like in callq *%r13
and jmpq *0x204d8a(%rip)
.
I'll show two real examples from my x86-64 Linux machine:
The qsort() implementation in GLIBC actually calls different sort algorithms depending on input size. One such implementation is msort_with_tmp() in /lib64/libc.so.6:
0000003cbde37d70 <msort_with_tmp.part.0>:
<...>
3cbde37dd6: 4c 8b 68 10 mov 0x10(%rax),%r13
<...>
3cbde37e2f: 41 ff d5 callq *%r13
The code snippet above moves the address of the comparison function into R13 and eventually does an indirect call.
For a dynamically linked executable calling strcmp(), I'll use /bin/true as an example. All calls to strcmp() in the main executable gets translated into a call to the PLT stub, strcmp@plt:
$ gdb /bin/true
(gdb) disassemble 'strcmp@plt'
0x401350 <+0>: ff 25 8a 4d 20 00 jmpq *0x204d8a(%rip) # 0x6060e0 <[email protected]>
0x401356 <+6>: 68 19 00 00 00 pushq $0x19
0x40135b <+11>: e9 50 fe ff ff jmpq 0x4011b0
In the first instruction, 0x204d8a(%rip) uses RIP relative addressing to locate [email protected].
If we try to inspect what value [email protected] holds at runtime:
(gdb) break *0x401350
(gdb) run --XXX
Breakpoint 1, 0x0000000000401350 in strcmp@plt ()
(gdb) p/a '[email protected]'
$1 = 0x3cbdf2fbe0 <__strcmp_sse42>
(gdb) break *0x3cbdf2fbe0
Breakpoint 2 at 0x3cbdf2fbe0: file ../sysdeps/x86_64/multiarch/strcmp-sse42.S, line 128.
(gdb) continue
Continuing.
Breakpoint 2, __strcmp_sse42 ()
at ../sysdeps/x86_64/multiarch/strcmp-sse42.S:128
128 mov %esi, %ecx
We see that [email protected] points to __strcmp_sse42() in /usr/lib64/libc.so.6.
Thus the first indirect jump we met, jmpq *0x204d8a(%rip) in strcmp@plt, ends up jumping to __strcmp_sse42(). This is the STT_GNU_IFUNC mechanism in action. It uses the dynamic linker to find the most suitable strcmp() variant at runtime based on CPU capabilities.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With