ltrace 和 objdump 中显示的不同指令地址
Different instruction address shown in ltrace and objdump
我使用ltrace和objdump来分析下面的简单代码。但是我发现 ltrace 和 objdump 显示的指令地址不同。
#include <iostream>
int main() {
std::cout << "Hello";
return 0;
}
如下信息,在ltrace中可以看到[call std::basic_ostream]的地址是[0x400789]。 (0x400789是call指令的地址,不是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) +++
然而,objdump中显示的[call std::basic_ostream]的地址是[0x400784]并且
另一条指令 [mov eax,0x0] 在 [0x400789] 上。其他“调用”指令也是如此。
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
我真的很想知道造成差距的原因。
非常感谢。
那些是return地址(在父call
之后的指令,call
压入堆栈的地址)。
ltrace
无法知道调用函数的指令有多长,例如带有函数指针的 call reg
只有 2 个字节,call rel32
为 5 个字节,call [RIP + rel32]
为 6 个字节(如果使用 [=16= 编译,GCC 将使用 memory-indirect 调用].)
或者如果它是 tail-called,执行将从 jmp
或其他东西到达它,所以即使在具有 fixed-length 指令的 ISA 上,如 MIPS 或 AArch64,ltrace
仍然无法可靠地打印调用它的位置。最好不要试图编造太多东西并保持简单,打印它在调用堆栈上实际看到的地址。
我使用ltrace和objdump来分析下面的简单代码。但是我发现 ltrace 和 objdump 显示的指令地址不同。
#include <iostream>
int main() {
std::cout << "Hello";
return 0;
}
如下信息,在ltrace中可以看到[call std::basic_ostream]的地址是[0x400789]。 (0x400789是call指令的地址,不是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) +++
然而,objdump中显示的[call std::basic_ostream]的地址是[0x400784]并且 另一条指令 [mov eax,0x0] 在 [0x400789] 上。其他“调用”指令也是如此。
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
我真的很想知道造成差距的原因。 非常感谢。
那些是return地址(在父call
之后的指令,call
压入堆栈的地址)。
ltrace
无法知道调用函数的指令有多长,例如带有函数指针的 call reg
只有 2 个字节,call rel32
为 5 个字节,call [RIP + rel32]
为 6 个字节(如果使用 [=16= 编译,GCC 将使用 memory-indirect 调用].)
或者如果它是 tail-called,执行将从 jmp
或其他东西到达它,所以即使在具有 fixed-length 指令的 ISA 上,如 MIPS 或 AArch64,ltrace
仍然无法可靠地打印调用它的位置。最好不要试图编造太多东西并保持简单,打印它在调用堆栈上实际看到的地址。