I'm using otool
on macOS to disassemble some simple C programs I built in order to gain a better understanding of assembly language. I disassembled three programs, all of which consist of a single printf
statement. One prints the string "Hello, World!\n"
, one prints a single integer formatted as a decimal, and the other prints two integers formatted as decimals.
My question regards the instruction call _printf
. The disassembly doesn't show _printf
; it shows the address of the _printf
symbol. I get a different address each time. At first I thought this was because gcc
converts any printf
that doesn't use additional parameters to puts
, but when I disassembled the third program I got still another address for printf. The code looks like this:
First program:
0000000100000f76 callq 0x100000f82
Second program:
0000000100000f7e callq 0x100000f8a
Third program:
0000000100000f7a callq 0x100000f86
I would like to gain a better understanding of how the glibc symbols are laid out in the executable. I am of course using the Mach-O format, but I have a feeling this variation in addresses is more universal. Also, given that the address is more or less random, how can one tell from the disassembly what function is being called?