標籤:cc++基礎二十六 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 _cplusplusextern "C" {#endifvoid 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步驟如下(請注意觀察紅色的備註陳述式):
[[email protected] 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"45int main(int argc,char **argv)6{78void *soHandle;9int (*fun)();10char *errorMsg;1112soHandle=dlopen("first.so",RTLD_LAZY);(gdb) l13errorMsg=dlerror();141516printf("A1---------loadSo is %s \n",soHandle ? "success" : "failed");17if(errorMsg)18{19printf("A2--------loadSo error , Msg is: %s \n",errorMsg);20return -1;21}22(gdb) l23fun=dlsym(soHandle,"fun1");24errorMsg=dlerror();25printf("B1---------fun1 , fun1 is %s \n",fun ? "success" : "Null");26if(fun)27{28fun();29}30if(errorMsg)31{32printf("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:2828fun();(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:44printf("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>2void fun1()3{4printf("i am from filea fun1 \n");5printf("i am from filea fun11 \n");6printf("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 5printf("i am from filea fun11 \n");(gdb) ni am from filea fun11 6printf("i am from filea fun12 \n");(gdb) ni am from filea fun12 7}(gdb) nmain (argc=1, argv=0x7fffffffe638) at CLoadSo.c:3030if(errorMsg)(gdb) n35fun=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 教程