我正在使用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,1)
│0x5555556ebdc0 <main_window_update()> xor %edi,%edi
请注意,如果我减去偏差值,则运行时目标地址将与编译时间值(即0x5555556ebdb0 - 0x555555554000 = 0x197db0
)一致。似乎在pseudo-routine
内部存在一个名为frame_dummy
的{{1}}。那怎么可能?如何预先(即在执行之前)提取这些_start@@Base
的地址?
更新:
pseudo-routines
和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()
内部。