大家都知道在 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
#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.so
这样我们就准备好了动态链接库了,下面我们编写一个应用程序来调用此动态链接库,源代码如下:
/************关于本文档********************************************
*filename: pk.cpp
*********************************************************************/
#include
#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 ./app
GNU gdb 6.4-debian
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome 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/app
Breakpoint 3 at 0xb7f665f8: file get.cpp, line 11.
Pending breakpoint "set" resolved
Breakpoint 1, main (argc=1, argv=0xbfArrayArray0504) at pk.cpp:7
7 int a = 100
(gdb) n /* 继续执行程序的下一行代码 */
8 int b = get ()
(gdb) n /* 程序执行到了我们断点所在的动态链接库了 */
get x=0
Array int c = set (a)
(gdb) n
Breakpoint 3, set (a=100) at get.cpp:11
11 printf ("set a=%d\n", a)
(gdb) list /* 查看当前代码行周围的代码,证明我们已经跟踪到动态链接库的源代码里面了 */
6 printf ("get x=%d\n", x)
7 return x
8 }
Array int set (int a)
10 {
11 printf ("set a=%d\n", a)
12 x = a
13 return x
14 }
(gdb) n
set a=100
12 x = a
(gdb) n
13 return x
(gdb) n
14 }
(gdb) n
main (argc=1, argv=0xbfArrayArray0504) at pk.cpp:10
10 int d = get ()
(gdb) n
get x=100
11 printf ("a=%d,b=%d,c=%d,d=%d\n",a,b,c,d)
(gdb) n
a=100,b=0,c=100,d=100
12 return 0
(gdb) c
Continuing.
Program exited normally.
(gdb) quit /* 程序顺利执行结束 */
如果我们没有把动态链接库放到指定目录,比如/lib里面,调试就会失败,过程如下:
引用:
# gdb ./app
GNU gdb 6.4-debian
Copyright 2005 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome 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
Breakpoint 1 at 0x804853c: file pk.cpp, line 7.
(gdb) b set
Function "set" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 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 directory
Program exited with code 0177.
(gdb) quit
创建 assembler工程
然后编译生成test可执行文件
如果是进程已经存在,再去 attach则
可以看到进程test启动了,pid位19879
-找到需要打断点的地方
先找到目标进程test(23946)的段基址
段基址缺册闭为0xaaaaa000,还要找到关心地址偏移,可以用ida反编译打开看
最后断点的地址 = 段基址 + 偏移 = 0xaaaaa000 + 0x0000065C
然后就可以看到断点断在了0xaaaaa65c,继续n,下一步调试
可伏裂以通过 layout reg打姿行开寄存器窗口
2009年12月29日,程序调试工具 GDB 7.0.1 发布,新版本修正了7.0版本的一些严重的堆栈溢出bug,这些bug可能导致 GDB 调试进程中断,修正了在 FreeBSD 和 IRⅨ 系统下无法编译的问题,增加了对 Thumb2调试的支持,还有其他一些小bug的修复。2010年03月19日,GDB 7.1 发布,
详细改进内容:多程序调试的支持;
位置独立的可执行文件(派)调试的支持;
新的目标(包括一个模拟器):Xilinx MicroBlaze和瑞萨RX
Python支持增强;
c++支持扩展;
新tracepoint功能;
过程记录的改进
远程协议扩展。
2010年09月06日 ,GDB 7.2 发布,
该版本改进记录:
⒈ 支持D语言
⒉ C++ 改进,支持参数依赖查找ADL,静态常量类成员和改进了用户自腔培定义 *** 作符的支持
⒊ Python 调试的改进,包括断点、符号、符号表、程序空间、线程等可通过命令行进行 *** 作
⒋ Furthermore,enhancements were made for tracepoints and for GDBserver.在跟踪点和GDB程序上有了改善。
⒌ 支持 ARM Symbian 平台
⒍ 其他方面伍贺唯拍迅的改进和bug修复。
2011年08月26日,GDB 7.3a 发布,
变化:
1。GDB可以理解线程的名字。
2。这个命令”线程名称”(指定一个名称)和“线程找到[REGEXP]”(匹配名称、目标ID,或者额外的信息)被添加。
3。Python脚本支持是大大增强。
4。在c++的支持,异常处理是提高,模板参数放在范围在一个实例化时调试。
5。线程调试的核心转储在GNU / Linux成为可能。
6。最初支持C语言版本的OpenCL。
7。许多其他改进。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)