首页 > 代码库 > c/c++基础(二十六) gdb调试so 教程

c/c++基础(二十六) gdb调试so 教程

当自己开发了一个so文件,如何调试呢?

对与如何编写一个so,请参考文章:http://blog.csdn.net/zz7zz7zz/article/details/41448987

对于如何进行gdb调试,请参考文章:http://blog.csdn.net/zz7zz7zz/article/details/41654457


假设我们的源文件分别是:

filea.c

#include <stdio.h>
void fun1()
{
	printf("i am from filea fun1 \n");
	printf("i am from filea fun11 \n");
	printf("i am from filea fun12 \n");
}

fileb.c

#include <stdio.h>
void fun2()
{
	printf("i am from fileb fun2 \n");
	printf("i am from fileb fun21 \n");
	printf("i am from fileb fun22 \n");
}

CLoadSo.h

#ifndef _CLOADSO_H
#define _CLOADSO_H

#ifdef _cplusplus
	extern "C" {
#endif

	void fun1();
	void fun2();

#ifdef _cplusplus
	}
#endif


#endif

CLoadSo.c

#include <stdio.h>
#include <dlfcn.h>
#include "CLoadSo.h"

int main(int argc,char **argv)
{

	void *soHandle;
	int (*fun)();
	char *errorMsg;

	soHandle=dlopen("first.so",RTLD_LAZY);
	errorMsg=dlerror();


	printf("A1---------loadSo  is %s \n",soHandle ? "success" : "failed");
	if(errorMsg)
	{
		printf("A2--------loadSo error , Msg is: %s \n",errorMsg);
		return -1;
	}

	fun=dlsym(soHandle,"fun1");
	errorMsg=dlerror();
	printf("B1---------fun1 , fun1 is %s \n",fun ? "success" : "Null");
	if(fun)
	{
		fun();
	}
	if(errorMsg)
	{
		printf("B2---------fun1 error , Msg is: %s \n",errorMsg);
	}

	fun=dlsym(soHandle,"fun2");
	errorMsg=dlerror();
	printf("B3---------fun2 , fun2 is %s \n",fun ? "success" : "Null");
	if(fun)
	{
		fun();
	}
	if(errorMsg)
	{
		printf("B4---------fun2 error , Msg is: %s \n",errorMsg);
	}

	fun=dlsym(soHandle,"fun3");
	errorMsg=dlerror();
	printf("B5---------fun3 , fun3 is %s \n",fun ? "success": "Null");
	if(fun)
	{
		fun();
	}
	if(!errorMsg)
	{
		printf("B6---------fun3 error , Msg is: %s \n",errorMsg);
	}
	

	dlclose(soHandle);
	printf("C---------close LoadSo \n");

	return 0;
}

用命令 gcc -Wall -fpic -g -shared filea.c fileb.c -o first.so 生成first.so文件

用命令 gcc -g -Wall CLoadSo.c -o CLoadSo -ldl生成可执行文件CLoadSo


gdb步骤如下(请注意观察红色的注释语句):


[DexYang@local103-22 GdbSo]$ gdb CLoadSo----------(1).启动gdb调试

GNU gdb (GDB) CentOS (7.0.1-45.el5.centos)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /disk1/DexYang/Test/GdbSo/CLoadSo...done.
(gdb) l<span style="color: rgb(204, 0, 0); font-family: Arial, Helvetica, sans-serif;"><strong>----------(2).列出加载so的main函数源码</strong></span>
3	#include "CLoadSoFun.h"
4	
5	int main(int argc,char **argv)
6	{
7	
8		void *soHandle;
9		int (*fun)();
10		char *errorMsg;
11	
12		soHandle=dlopen("first.so",RTLD_LAZY);
(gdb) l
13		errorMsg=dlerror();
14	
15	
16		printf("A1---------loadSo  is %s \n",soHandle ? "success" : "failed");
17		if(errorMsg)
18		{
19			printf("A2--------loadSo error , Msg is: %s \n",errorMsg);
20			return -1;
21		}
22	
(gdb) l
23		fun=dlsym(soHandle,"fun1");
24		errorMsg=dlerror();
25		printf("B1---------fun1 , fun1 is %s \n",fun ? "success" : "Null");
26		if(fun)
27		{
28			fun();
29		}
30		if(errorMsg)
31		{
32			printf("B2---------fun1 error , Msg is: %s \n",errorMsg);
(gdb) b 28 <span style="color: rgb(204, 0, 0); font-family: Arial, Helvetica, sans-serif;"><strong>----------(3).在28行处加入断点,也即在fun1函数调用处加入断点</strong></span>
Breakpoint 1 at 0x400723: file CLoadSo.c, line 28.
(gdb) r<strong> <span style="color: rgb(204, 0, 0); font-family: Arial, Helvetica, sans-serif;">----------(4).开始运行程序</span></strong>
Starting program: /disk1/DexYang/Test/GdbSo/CLoadSo 
A1---------loadSo  is success 
B1---------fun1 , fun1 is success 

Breakpoint 1, main (argc=1, argv=0x7fffffffe638) at CLoadSo.c:28
28			fun();
(gdb) sharedlibrary first.so  <span style="color: rgb(204, 0, 0); font-family: Arial, Helvetica, sans-serif; font-weight: bold;">----------(</span><span style="font-family: Arial, Helvetica, sans-serif; font-weight: bold;"><span style="color:#990000;">5).<span style="font-family: 宋体, Arial; font-size: 14px; line-height: 26px;">sharedlibrary是将动态库的符号读入gdb,为了你能找到变量和函数名。</span></span></span>
Symbols already loaded for first.so
(gdb) s  <span style="color: rgb(204, 0, 0); font-family: Arial, Helvetica, sans-serif; font-weight: bold;">----------(6).进入函数</span>
fun1 () at filea.c:4
4		printf("i am from filea fun1 \n");
(gdb) l <span style="color: rgb(204, 0, 0); font-family: Arial, Helvetica, sans-serif; font-weight: bold;">---------(7).列出函数源代码</span>
1	#include <stdio.h>
2	void fun1()
3	{
4		printf("i am from filea fun1 \n");
5		printf("i am from filea fun11 \n");
6		printf("i am from filea fun12 \n");
7	}
(gdb) n <span style="color: rgb(204, 0, 0); font-family: Arial, Helvetica, sans-serif; font-weight: bold;">---------(8).在函数内单步执行</span>
i am from filea fun1 
5		printf("i am from filea fun11 \n");
(gdb) n
i am from filea fun11 
6		printf("i am from filea fun12 \n");
(gdb) n
i am from filea fun12 
7	}
(gdb) n
main (argc=1, argv=0x7fffffffe638) at CLoadSo.c:30
30		if(errorMsg)
(gdb) n
35		fun=dlsym(soHandle,"fun2");
(gdb) c  <span style="color: rgb(204, 0, 0); font-family: Arial, Helvetica, sans-serif; font-weight: bold;">---------(9).继续直到程序执行完</span>
Continuing.
B3---------fun2 , fun2 is success 
i am from fileb fun2 
i am from fileb fun21 
i am from fileb fun22 
B5---------fun3 , fun3 is Null 
C---------close LoadSo 

Program exited normally.
(gdb) 

结果:成功进入到了so的fun1中

大概步骤:

1.启动gdb调试:gdb CLoadSo

2.打断点 gdb) : break 28

3.执行 gdb) : run

4.将动态库的符号读入gdb,为了你能找到变量和函数名 gdb)sharedlibrary first.so

5.s进入函数,l列出源代码,n单步执行,直到结束.









c/c++基础(二十六) gdb调试so 教程