gpt4 book ai didi

C函数剖析(地址好像有偏移)

转载 作者:太空狗 更新时间:2023-10-29 17:09:58 25 4
gpt4 key购买 nike

我正在尝试使用 -finstrument-functions 选项分析函数调用。基本上,我所做的是将以下内容写入任何已编译的源代码:

static int __stepper=0;
void __cyg_profile_func_enter(void *this_fn, void *call_site)
__attribute__((no_instrument_function));
void __cyg_profile_func_enter(void *this_fn, void *call_site) {
int i=0;
for( ; i<__stepper; i++ ) printf(" ");
printf("E: %p %p\n", this_fn, call_site);
__stepper ++;
} /* __cyg_profile_func_enter */

void __cyg_profile_func_exit(void *this_fn, void *call_site)
__attribute__((no_instrument_function));
void __cyg_profile_func_exit(void *this_fn, void *call_site) {
int i=0;
__stepper --;
for( ; i<__stepper; i++ ) printf(" ");
printf("L: %p %p\n", this_fn, call_site);
} /* __cyg_profile_func_enter */

得到如下结果:

 E: 0xb7597ea0 0xb75987a8
E: 0xb7597de0 0xb7597ef5
L: 0xb7597de0 0xb7597ef5
L: 0xb7597ea0 0xb75987a8

所有的函数调用地址都在那个区域附近(0xb7......)但是,如果我尝试使用“readelf -s”读取函数的符号,它会给出以下内容:

2157: 00101150   361 FUNC    LOCAL  DEFAULT   13 usb_audio_initfn
2158: 00100940 234 FUNC LOCAL DEFAULT 13 usb_audio_handle_reset
2159: 00100de0 867 FUNC LOCAL DEFAULT 13 usb_audio_handle_control

所有二进制函数的地址区都在0x00左右……所以,我无法从函数指针中获取函数名。看起来像是函数指针如何获得偏移量之类的。

有人知道吗?

最佳答案

从问题来看,您似乎是在分析一个库函数。

要知道测量的功能是什么,您有两个选择:

1 运行使用gdb 下的库的程序并在main 处停止。此时,获取程序PID=...pid 并执行`cat/proc/$PID/maps'。在那里你应该看到这样的东西:

➜  ~  ps
PID TTY TIME CMD
18533 pts/4 00:00:00 zsh
18664 pts/4 00:00:00 ps
➜ ~ PID=18533
➜ ~ cat /proc/$PID/maps
00400000-004a2000 r-xp 00000000 08:01 3670052 /bin/zsh5
006a1000-006a2000 r--p 000a1000 08:01 3670052 /bin/zsh5
006a2000-006a8000 rw-p 000a2000 08:01 3670052 /bin/zsh5
006a8000-006bc000 rw-p 00000000 00:00 0
...
7fa174cc9000-7fa174ccd000 r-xp 00000000 08:01 528003 /lib/x86_64-linux-gnu/libcap.so.2.22
7fa174ccd000-7fa174ecc000 ---p 00004000 08:01 528003 /lib/x86_64-linux-gnu/libcap.so.2.22
7fa174ecc000-7fa174ecd000 r--p 00003000 08:01 528003 /lib/x86_64-linux-gnu/libcap.so.2.22
7fa174ecd000-7fa174ece000 rw-p 00004000 08:01 528003 /lib/x86_64-linux-gnu/libcap.so.2.22
...

这里的7fa174cc9000/lib/x86_64-linux-gnu/libcap.so.2.22库的基地址。因此,您通过 readelf -s 获得的所有地址都将被该值偏移。知道基地址后,您可以计算出文件中的原始偏移量。

即如果您得到值 7fa174206370 并且库的基地址为 7fa1741cf000,则偏移量为 7fa174206370 - 7fa1741cf000 = 37370。在我的示例中,它是来自 GLIBC 的 sigsuspend:

94: 0000000000037370   132 FUNC    WEAK   DEFAULT   12 sigsuspend@@GLIBC_2.2.5

2 在使用这些库的程序上运行gdb。它会立即在内存中找到加载的库,或者需要指向库的 .text 部分。

> gdb
(gdb) attach YOUR_PID
(a lot of output about symbols)
(gdb) x/i 0x00007fa174206386
=> 0x7fa174206386 <sigsuspend+22>: cmp $0xfffffffffffff000,%rax

这样你就知道 0x7fa174206386sigsuspend 中。

如果 gdb 本身不加载任何符号(在附加后没有像 Reading symbols from ... Loading symbols for ... 这样的输出),您可以在选项1中查找库的基地址,然后向其添加.text部分

的偏移量
➜  ~  readelf -S /lib/x86_64-linux-gnu/libcap.so.2.22 | grep '.text.'
[11] .text PROGBITS 0000000000001620 00001620

7fa174cc9000 + 0000000000001620 十六进制给出 7FA174CCA620,然后你按上面的 gdb 附加并执行

(gdb) add-symbol-file /lib/x86_64-linux-gnu/libcap.so.2.22 7FA174CCA620

然后你应该能够找到符号(通过 x/i ADDRESS 作为选项 1)即使 gdb 没有加载它们本身。

有什么不明白的请追问,我会尽量解释

澄清为什么会这样:

观察到的行为是由于库被编译为 Position-Independent Code .它使我们能够轻松支持动态库。 PIC 本质上意味着库的 ELF 有 .plt.got 部分,可以在任何基地址加载。 PLT是procedure linkage table,它包含调用位于其他模块的函数的陷阱,它首先进入程序解释器,让它重新定位被调用的函数,然后跳转到第一次调用后的函数。它之所以起作用,是因为程序解释器更新了 GOT(全局偏移表),其中包含要调用的函数的地址。最初 GOT 被初始化,以便在第一次函数调用时执行跳转到程序解释器的函数,该函数执行当前调用函数的解析。

在 x86-64 上,PLT 条目通常如下所示:

0000000000001430 <free@plt>:
1430: ff 25 e2 2b 20 00 jmpq *0x202be2(%rip) # 204018 <_fini+0x201264>
1436: 68 00 00 00 00 pushq $0x0
143b: e9 e0 ff ff ff jmpq 1420 <_init+0x28>

第一个 jmpq 是跳转到地址,存储在 GOT 中的位置 %rip + 0x202be2:

  [20] .got              PROGBITS         0000000000203fd0  00003fd0
0000000000000030 0000000000000008 WA 0 0 8

%rip + 0x202be2 将是 0x204012,它被添加到库的基址以生成与库实际加载位置相关的绝对地址。 IE。如果它在 0x7f66dfc03000 处加载,则相应 GOT 条目的结果地址将为 0x7F66DFE07012。存储在该位置的地址是(在此示例中)free 函数的地址。它由程序解释器维护,指向 libc 中的实际 free

有关这方面的更多信息,请参见 here .

关于C函数剖析(地址好像有偏移),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19655451/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com