原贴地址:http://hi.baidu.com/colin719/blog/item/bd48351fff396ac8a786699e.html
相信有不少的同志调试过包含共享库代码的程序,这个时候最为头疼的就是不能进行单步跟踪(当然是在你不知道如何解决的情况下^_^),本文根据一个实例来讲述如何来解决这个问题。首先来看我们的程序,包含两个文件:dyn.c, main.c,其中dyn.c被编译成一个共享库libdyn.so,在链接的时候要用到它。有一点必须声明,就是你的共享库代码必须是带有调试信息的(比如使用 -g选项)。
$cat dyn.c
dyn ()
{ puts ("Hello."); } $cat main.c
main ()
{ puts ("before"); dyn (); puts ("after"); } $cat Makefile
main:
gcc -g -save-temps -c main.c -o main.o gcc -g -save-temps -c -fpic -ffunction-sections dyn.c gcc -g -save-temps -shared dyn.o -o libdyn.so gcc -g -save-temps main.o libdyn.so -o main clean: rm -rf *.o *.so main 下面我们就来编译和调试程序: $make main 这之后就会在当前目录下生成我们所要的libdyn.so 和 main程序 如果我们向往常一样直接输入 $./main 来执行程序,这是不行的,它会给我们这样的错误提示: before ./main: relocation error: ./main: undefined symbol: dyn 为什么?原来是我们使用了共享库libdyn.so却没有告诉动态链接程序到哪里去找他!好,这回我们告诉它: $LD_LIBRARY_PATH=`pwd` ./main before Hello. after 怎么样,出现我们想要的结果了吧。 以上这些是一些小儿科啦,牛人们不要笑话啊,下面才是这次要讲的。通常情况下我们使用gdb进行调试的时候: $ gdb -q main
(gdb) b main
按照我们的本意,我们是想跟踪到dyn()函数内部去看一些咚咚的,可是它却找不到对应的符号信息,怎么办?
Breakpoint 1 at 0x8048478: file main.c, line 3. (gdb) r Starting program: /home/lirui/Test/main Breakpoint 1, main () at main.c:3 3 puts ("before"); (gdb) next before 4 dyn (); (gdb) /home/lirui/Test/main: relocation error: /home/lirui/Test/main: undefined symbol: dyn Program exited with code 0177. (gdb) 方法一: 设定gdb环境变量 LD_PRELOAD,在执行程序前先把共享库代码load进来不就能找到了吗 $gdb -q main
(gdb) set environment LD_PRELOAD ./libdyn.so
这下不就找到dyn()函数了吗,这样你就可以很舒心的调试喽!
(gdb) break dyn Breakpoint 1 at 0x80483a8 (gdb) run Starting program: /home/lirui/Test/main Breakpoint 1 at 0x400176ff: file dyn.c, line 3. before Breakpoint 1, dyn () at dyn.c:3 3 puts ("Hello."); (gdb) list 1 dyn () 2 { 3 puts ("Hello."); 4 } (gdb) 方法二:如果你使用的gdb版本中对” pending breakpoint"提供支持(V6.3当中就有支持),那么恭喜你,你可以先设定一个pending breakpoint,然后有gdb来决定到什么时候这个断点起作用。这里面有一点必须注意,你必须指定你的链接库的位置,可以通过设定环境变量LD_LIBRARY_PATH来实现。在执行gdb之前,我们可以这样做: $ export LD_LIBARY_PATH=`pwd`,告诉gdb在当前目录下查找共享库文件,然后向往常一样调试程序就可以了: $ export LD_LIBRARY_PATH=`pwd` $ gdb -q main
Using host libthread_db library "/lib/libthread_db.so.1".
(gdb) b dyn Function "dyn" not defined. Make breakpoint pending on future shared library load? (y or [n]) y Breakpoint 1 (dyn) pending. (gdb) r Starting program: /home/lirui/Test/tmp/main Reading symbols from shared object read from target memory...done. Loaded system supplied DSO at 0xffffe000 Breakpoint 2 at 0xb7f4853a: file dyn.c, line 3. Pending breakpoint "dyn" resolved before Breakpoint 2, dyn () at dyn.c:3 3 puts ("Hello."); (gdb) l 1 dyn () 2 { 3 puts ("Hello."); 4 } (gdb) 这样是不是也可以啊,^_^ 另外一种Makefile的写法是: .PHONY:all clean all:main |