假设在运行时,我想找出函数“printf”的定义位置。我该怎么做? 我的第一次尝试是打印出“printf”的地址,并将其与进程的虚拟地址映射进行比较:
我的程序:
#include <stdio.h>
#include <unistd.h>
void main()
{
printf("address of printf is 0x%X\n", printf);
printf("pid is %d\n", getpid());
while (1);
}
输出:
-bash-4.1$ ./a &
[1] 28837
-bash-4.1$ address of printf is 0x4003F8
pid is 28837
但是,这表示该函数是在我自己的程序中定义的!
-bash-4.1$ head /proc/28837/maps
00400000-00401000 r-xp 00000000 08:06 6946857 /data2/temp/del/a <<<<<<< Address 0x4003F8 is in my own program?
00600000-00601000 rw-p 00000000 08:06 6946857 /data2/temp/del/a
397ec00000-397ec20000 r-xp 00000000 08:11 55837039 /lib64/ld-2.12.so
397ee1f000-397ee20000 r--p 0001f000 08:11 55837039 /lib64/ld-2.12.so
397ee20000-397ee21000 rw-p 00020000 08:11 55837039 /lib64/ld-2.12.so
397ee21000-397ee22000 rw-p 00000000 00:00 0
397f000000-397f18a000 r-xp 00000000 08:11 55837204 /lib64/libc-2.12.so
397f18a000-397f38a000 ---p 0018a000 08:11 55837204 /lib64/libc-2.12.so
397f38a000-397f38e000 r--p 0018a000 08:11 55837204 /lib64/libc-2.12.so
397f38e000-397f38f000 rw-p 0018e000 08:11 55837204 /lib64/libc-2.12.so
不应该是对 libc 的调用吗?如何找出这个“printf”或任何其他函数的来源?
最佳答案
您观察到的地址位于过程链接表 (PLT) 中。在编译和链接二进制文件时,当外部(动态链接)符号的位置未知时,使用此机制。
目的是,外部链接只发生在一个地方,PLT,而不是在整个代码中调用符号的所有地方。所以,如果调用printf()
,方式是:
main -> printf@PLT -> printf@libc
在运行时,你无法轻易找出你调用的函数位于哪个外部库中;您必须在目的地(PLT)解析操作码,它通常从 .dynamic 部分获取地址并跳转到那里,然后查看符号的实际位置,最后解析/proc/pid/maps 以获取外部库。
关于c - Linux C 程序 : How to find the library to which a function belongs,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52599211/