I use ltrace and objdump to analyse the simple code below. But I find there is a difference on instruction address shown between ltrace and objdump.
#include <iostream>
int main() {
std::cout << "Hello";
return 0;
}
As the following info, you can see that the address of [call std::basic_ostream] is [0x400789] in ltrace. (0x400789 is the address of the instruction "call", not std::basic_ostream)
binary@binary-VirtualBox:~/code/chapter5/test$ ltrace -i -C ./a.out
[0x4006a9] __libc_start_main(0x400776, 1, 0x7fff06c6ad28, 0x4007f0 <unfinished ...>
[0x4007b7] std::ios_base::Init::Init()(0x601171, 0xffff, 0x7fff06c6ad38, 160) = 0
[0x4007cb] __cxa_atexit(0x400650, 0x601171, 0x601048, 0x7fff06c6ab00) = 0
[0x400789] std::basic_ostream<char, std::char_traits<char> >& std::operator<< <std::char_traits<char> >(std::basic_ostream<char, std::char_traits<char> >&, char const*)(0x601060, 0x400874, 0x7fff06c6ad38, 192) = 0x601060
[0x7f220180aff8] std::ios_base::Init::~Init()(0x601171, 0, 0x400650, 0x7f2201b96d10Hello) = 0x7f2201f19880
[0xffffffffffffffff] +++ exited (status 0) +++
However, the address of [call std::basic_ostream] shown in objdump is [0x400784] and another instruction [mov eax,0x0] is on [0x400789]. The same is true for other "call" instructions.
0000000000400776 <main>:
400776: 55 push rbp
400777: 48 89 e5 mov rbp,rsp
40077a: be 74 08 40 00 mov esi,0x400874
40077f: bf 60 10 60 00 mov edi,0x601060
400784: e8 d7 fe ff ff call 400660 <_ZStlsISt11char_traitsIcEERSt13basic_ostreamIcT_ES5_PKc@plt>
400789: b8 00 00 00 00 mov eax,0x0
40078e: 5d pop rbp
40078f: c3 ret
I really want to know what causes the gap. Thank you a lot.
Those are return addresses (instruction after the call
in the parent, the address which call
pushes on the stack).
ltrace
can't know how long the instruction was that called a function, e.g. call reg
with a function pointer is only 2 bytes vs. 5 for call rel32
vs. 6 for call [RIP + rel32]
(memory-indirect call which GCC will use if you compile with -fno-plt
.)
Or if it was tail-called, execution would have reached it from a jmp
or something, so even on an ISA with fixed-length instructions like MIPS or AArch64, ltrace
still couldn't reliably print where it was called from. Best to not try to make too much stuff up and keep it simple, printing the address it can actually see on the callstack.