调用例程中的地址

问题描述 投票:1回答:1

我正在使用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:

GIMPAnjuta中几乎没有这些类型的函数中间调用(它们几乎完全写在C中,并且是从源代码构建的)。但是存在于InkscapeWireshark中(用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
...

这是gdb0x5555556f5870 - 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 ...

debugging gdb function-call backtrace intel-pin
1个回答
1
投票

怎么可能?

© www.soinside.com 2019 - 2024. All rights reserved.