Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

direct and indirect calls/jumps in output of objdump

Looking at the output of objdump -d ELFfile, I could not distinguish between direct and indirect Jumps/calls. Any suggestions?

like image 200
ehsan moghadam Avatar asked May 07 '13 16:05

ehsan moghadam


People also ask

What is objdump output?

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.

Which parameter of objdump is used to show all disassembled output of an executable?

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.


1 Answers

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:

  1. qsort() in the C standard library calling the user-supplied comparison function
  2. A dynamically linked executable calling strcmp()

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.

like image 86
scottt Avatar answered Oct 08 '22 20:10

scottt