我正在使用wireshark-2.6.10
跟踪Pin
。在初始化过程中的几点,我可以看到一些调用,例如:
00000000004e9400 <__libc_csu_init@@Base>:
...
4e9449: 41 ff 14 dc callq *(%r12,%rbx,8)
...
此呼叫的目标是0x197db0
,如下所示:
0000000000197cb0 <_start@@Base>:
...
197db0: 55 push %rbp
197db1: 48 89 e5 mov %rsp,%rbp
197db4: 5d pop %rbp
197db5: e9 66 ff ff ff jmpq 197d20 <_start@@Base+0x70>
197dba: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1)
...
Pin
表示这是在包含例程(即_start@@Base
)的中间。但是,当我使用gdb
达到此目标时,会看到以下输出:
>│0x5555556ebdb0 <frame_dummy> push %rbp
│0x5555556ebdb1 <frame_dummy+1> mov %rsp,%rbp
│0x5555556ebdb4 <frame_dummy+4> pop %rbp
│0x5555556ebdb5 <frame_dummy+5> jmpq 0x5555556ebd20 <register_tm_clones>
│0x5555556ebdba <frame_dummy+10> nopw 0x0(%rax,%rax,1)
│0x5555556ebdc0 <main_window_update()> xor %edi,%edi
[请注意,如果我减去偏差值,则运行时目标地址将与编译时间值(即0x5555556ebdb0 - 0x555555554000 = 0x197db0
)一致。似乎在pseudo-routine
中存在一个称为frame_dummy
的_start@@Base
。那怎么可能?如何提前(即在执行之前)提取这些pseudo-routines
的地址?
UPDATE:
GIMP
和Anjuta
中几乎没有这些类型的函数中间调用(它们几乎完全写在C
中,并且是从源代码构建的)。但是存在于Inkscape
和Wireshark
中(用C++
编写,尽管我不认为这是语言的原因。这两个是从软件包中安装的。)
起初,似乎这种情况仅在初始化期间和调用main()
函数之前发生。但是,至少在wireshark-2.6.10
中,此现象至少在main()
开始后的一个地方发生。在这里,我们有wireshark-qt.cpp: Lines 522-524
(它是main()
的一部分)。
/* Get the compile-time version information string */ comp_info_str = get_compiled_version_info(get_wireshark_qt_compiled_info, get_gui_compiled_info);
这是对
get_compiled_version_info()
的呼叫。在汇编中,该函数在地址0x5555556e74c2 (0x1934c2 without bias)
处调用,如下所示:
>│0x5555556e74c2 <main(int, char**)+178> callq 0x5555556f5870 <get_compiled_version_info> │0x5555556e74c7 <main(int, char**)+183> lea 0x4972(%rip),%rdi # 0x5555556ebe40 <get_wireshark_runtime_info(_GString*)> │0x5555556e74ce <main(int, char**)+190> mov %rax,%r13
同样,目标位于另一个函数的中间,
_ZN7QStringD1Ev@@Base
:
00000000001980f0 <_ZN7QStringD1Ev@@Base>: ... 1a1870: 41 54 push %r12 ...
这是
gdb
(0x5555556f5870 - 0x555555554000 = 0x1a1870
)的输出:
>│0x5555556f5870 <get_compiled_version_info> push %r12 │0x5555556f5872 <get_compiled_version_info+2> mov %rdi,%r12 │0x5555556f5875 <get_compiled_version_info+5> push %rbp │0x5555556f5876 <get_compiled_version_info+6> lea 0x349445(%rip),%rdi # 0x555555a3ecc2
可以看出,调试器识别出该地址是
get_compiled_version_info()
的起始地址。这是因为它可以访问debug_info
。在我发现的所有情况下,这些pseudo-routines
的符号都从原始二进制文件中删除了(因为从二进制文件中删除了.symtab
)。但是奇怪的是它位于_ZN7QStringD1Ev@@Base
内部。因此,Pin
认为get_compiled_version_info()
在_ZN7QStringD1Ev@@Base
内部。
我正在使用Pin跟踪wirehark-2.6.10。在初始化期间的几个时间点,我可以看到一些调用,例如:00000000004e9400 <__libc_csu_init>:... 4e9449:41 ff ...
怎么可能?