【转】gdb调试动态链接库

来源:互联网 发布:阿里云服务器好用吗 编辑:程序博客网 时间:2024/05/29 11:49

【转】gdb调试动态链接库

【原文地址】http://www.microsuncn.com/index.php?title=%E7%94%A8gdb%E8%B0%83%E8%AF%95%E5%8A%A8%E6%80%81%E9%93%BE%E6%8E%A5%E5%BA%93

在 Linux 可以用 gdb 来调试应用程序,当然前提是用 gcc 编译程序时要加上 -g 参数。我这篇文章里将讨论一下用 gdb 来调试动态链接库的问题。首先,假设我们准备这样的一个动态链接库:引用:库名称是: ggg 动态链接库文件名是: libggg.so 头文件是: get.h 提供这样两个函数调用接口:

   int get ();   int set (int a);

要生成这样一个动态链接库,我们首先编写这样一个头文件:

/************关于本文档*********************************************filename: get.h*********************************************************************/int get ();int set (int a);

然后准备这样一个生成动态链接库的源文件:

/************关于本文档*********************************************filename:  get.cpp*********************************************************************/#include <stdio.h>#include "get.h"static int x=0;int get (){        printf ("get x=%d\n", x);        return x;}int set (int a){        printf ("set a=%d\n", a);        x = a;        return x;}

然后我们用 GNU 的 C/C++ 编译器来生成动态链接库,编译命令如下:

g++ get.cpp -shared -g -DDEBUG -o libggg.sog++ get.cpp -shared -g -fPIC -DDEBUG -o libggg.so (64位机器)

这样我们就准备好了动态链接库了,下面我们编写一个应用程序来调用此动态链接库,源代码如下:

/************关于本文档*********************************************filename: pk.cpp*********************************************************************/#include <stdio.h>#include "get.h"int main (int argc, char** argv){        int a = 100;        int b = get ();        int c = set (a);        int d = get ();        printf ("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);        return 0;}

编译此程序用下列命令,如果已经把上面生成的 libggg.so 放到了库文件搜索路径指定的文件目录,比如 /lib 或 /usr/lib 之类的,就用下面这条命令:

g++ pk.cpp -o app -Wall -g -lggg

否则就用下面这条命令:

g++ pk.cpp -o app -Wall -g -lggg -L`pwd`

下面我们就开始调试上面命令生成的 app 程序吧。如果已经把上面生成的 libggg.so 放到了库文件搜索路径指定的文件目录,比如 /lib 或 /usr/lib 之类的,调试就顺利完成,如下:

#gdb ./appGNU gdb 6.4-debianCopyright 2005 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB.  Type "show warranty" for details.This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".(gdb) b main    /* 这是在程序的 main 处设置断点 */Breakpoint 1 at 0x804853c: file pk.cpp, line 7.(gdb) b set      /* 这是在程序的 set 处设置断点 */Function "set" not defined.Make breakpoint pending on future shared library load? (y or [n]) y /* 这里必须选择 y 调试程序才会跟踪到动态链接库内部去 */Breakpoint 2 (set) pending.(gdb) run /* 开始运行我们的程序,直到遇见断点时暂停 */Starting program: /data/example/c/appBreakpoint 3 at 0xb7f665f8: file get.cpp, line 11.Pending breakpoint "set" resolvedBreakpoint 1, main (argc=1, argv=0xbf990504) at pk.cpp:77               int a = 100;(gdb) n     /* 继续执行程序的下一行代码 */8               int b = get ();(gdb) n      /* 程序执行到了我们断点所在的动态链接库了 */get x=09               int c = set (a);(gdb) nBreakpoint 3, set (a=100) at get.cpp:1111              printf ("set a=%d\n", a);(gdb) list   /* 查看当前代码行周围的代码,证明我们已经跟踪到动态链接库的源代码里面了 */6               printf ("get x=%d\n", x);7               return x;8       }9       int set (int a)10      {11              printf ("set a=%d\n", a);12              x = a;13              return x;14      }(gdb) nset a=10012              x = a;(gdb) n13              return x;(gdb) n14      }(gdb) nmain (argc=1, argv=0xbf990504) at pk.cpp:1010              int d = get ();(gdb) nget x=10011              printf ("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d);(gdb) na=100,b=0,c=100,d=10012              return 0;(gdb) cContinuing.Program exited normally.(gdb) quit  /* 程序顺利执行结束 */如果我们没有把动态链接库放到指定目录,比如/lib里面,调试就会失败,过程如下:# gdb ./appGNU gdb 6.4-debianCopyright 2005 Free Software Foundation, Inc.GDB is free software, covered by the GNU General Public License, and you arewelcome to change it and/or distribute copies of it under certain conditions.Type "show copying" to see the conditions.There is absolutely no warranty for GDB.  Type "show warranty" for details.This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/tls/i686/cmov/libthread_db.so.1".(gdb) b mainBreakpoint 1 at 0x804853c: file pk.cpp, line 7.(gdb) b setFunction "set" not defined.Make breakpoint pending on future shared library load? (y or [n]) yBreakpoint 2 (set) pending.(gdb) run  /* 虽然调试操作都一样,但程序执行失败 */Starting program: /data/example/c/app/data/example/c/app: error while loading shared libraries: libggg.so: cannot open shared object file: No such file or directoryProgram exited with code 0177.(gdb) quit 

调试失败的原因是因为gdb不能找到libggg.so,可以通过下面的方法解决:

1) 将库路径加到LD_LIBRARY_PATH里2) 执行:ldconfig YOUR_LIB_PATH3) 在/etc/ld.so.conf里加入库所在路径。然后执行:ldconfig上面3个方法任意一个都可以,然后再去用gdb调试就没有问题了。

另:

1、假设我的可执行程序是ServerName,共享库为worker.so2、我用gdb调试ServerName,想在B的某个源文件(比如worker.cpp,worker.cpp与ServerName不在同一个目录下)中设置断点,使用下面的命令行break worker.cpp:123若找不到源文件可使用如下命令设定源文件目录:设定gdb环境变量 LD_PRELOAD,在执行程序前先把共享库代码load进来指定你的链接库的位置,可以通过设定环境变量LD_LIBRARY_PATH来实现拷贝到标准的lib搜寻目录下,例如/usr/lib等b main, r,然后再设置断点就可以了,共享库只有当程序运行才开始加载的 
0 0
原创粉丝点击