目前,大部分可执行程序为了节省内存空间等目的,都是动态链接的, 动态链接的程序在每次运行时,所依赖的动态库的地址总是变化的,那么库中的函数地址也跟着变化。如何在程序(动态链接的)运行期间,查看某个库函数的虚拟地址?
方法很简单,首先确定,你需要查看的函数,在哪个动态库中,并且确定该函数相对于该动态库的相对地址。其次,在程序运行期间,查看程序的映射表,找到动态库的加载地址。最后将这两个地址相加,就是你要的库函数在运行时的虚拟地址。
我的系统是64位Ubuntu 12.04.1 LTS。
举例如下:
1、编写测试程序hello.c:
#include
int main()
{
printf("Hello world\n");
sleep(-1);
return 0;
}
加sleep的原因是,我们需要看到该程序运行时的状态,执行完了就看不到其链接状态了。printf就是动态库libc-2.15.so中的一个函数(在你的系统上也有可能是其他库的名字比如libc-2.13.so)。
2、编译运行
# gcc hello.c (不加-static,默认就是动态链接)
# ./a.out & (后台运行,并且打印出程序pid)
[3] 1049
3、打印进程映射信息,得到进程运行时的动态库基地址:
root@Heron:/home# cat /proc/1049/maps
00400000-00401000 r-xp 00000000 08:01 2364347 /home/zhangqianlong/Lib_test/a.out
00600000-00601000 r--p 00000000 08:01 2364347 /home/zhangqianlong/Lib_test/a.out
00601000-00602000 rw-p 00001000 08:01 2364347 /home/zhangqianlong/Lib_test/a.out
7fa5b9f44000-7fa5ba0f9000 r-xp 00000000 08:01 5243800 /lib/x86_64-linux-gnu/libc-2.15.so
7fa5ba0f9000-7fa5ba2f8000 ---p 001b5000 08:01 5243800 /lib/x86_64-linux-gnu/libc-2.15.so
7fa5ba2f8000-7fa5ba2fc000 r--p 001b4000 08:01 5243800 /lib/x86_64-linux-gnu/libc-2.15.so
7fa5ba2fc000-7fa5ba2fe000 rw-p 001b8000 08:01 5243800 /lib/x86_64-linux-gnu/libc-2.15.so
7fa5ba2fe000-7fa5ba303000 rw-p 00000000 00:00 0
7fa5ba303000-7fa5ba325000 r-xp 00000000 08:01 5243815 /lib/x86_64-linux-gnu/ld-2.15.so
7fa5ba508000-7fa5ba50b000 rw-p 00000000 00:00 0
7fa5ba522000-7fa5ba525000 rw-p 00000000 00:00 0
7fa5ba525000-7fa5ba526000 r--p 00022000 08:01 5243815 /lib/x86_64-linux-gnu/ld-2.15.so
7fa5ba526000-7fa5ba528000 rw-p 00023000 08:01 5243815 /lib/x86_64-linux-gnu/ld-2.15.so
7ffff2260000-7ffff2281000 rw-p 00000000 00:00 0 [stack]
7ffff2383000-7ffff2384000 r-xp 00000000 00:00 0 [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]
以上内容,红色部分就是动态库libc-2.15.so的运行时基地址
对于maps文件的解析:
一共有6列 第一列代表内存段的虚拟地址 第二列代表执行权限,r,w,x不必说,p=私有 s=共享 不用说,heap和stack段不应该有x,否则就容易被xx,不过这个跟具体的版本有关 第三列代表在进程地址里的偏移量 第四列映射文件的主设备号和次设备号 通过 cat /proc/devices 得知fd是253 device-mapper 第五列映像文件的节点号,即inode 第六列是映像文件的路径
4、查看动态库中,printf函数的相对地址:
# nm -D libc-2.15.so |grep -w printf
0000000000053840T printf
nm意思不懂得自己去man以下,-w是抓取一个字,以上红色部分就是printf函数对于动态库libc-2.15.so的相对地址
5、计算函数printf在动态运行时的虚拟地址:
0000000000053840 +7fa5b9f44000=7FA5B9F97840
不同的系统,得出的结果有可能是不一样的,同一个系统,测试两次结果肯定是不一样的,因为动态链接的库,每次的加载地址都不一样。