GDB調試命令小結

1.啓動調試mysql

前置條件:編譯生成執行碼時帶上 -g,若是使用Makefile,經過給CFLAGS指定-g選項,不然調試時沒有符號信息。
gdb program //最經常使用的用gdb啓動程序,開始調試的方式
gdb program core //用gdb查看core dump文件,跟蹤程序core的緣由
gdb program pid //用gdb調試已經開始運行的程序,指定pid便可
gdb attach pid //用gdb調試已經開始運行的程序,指定pid便可linux

2.調試命令
(1)執行命令模式
-batch選項。
好比:打印$pid進程全部線程的堆棧並退出。
gdb -ex "set pagination 0" -ex "thread apply all bt" -batch -p $pidsql

(2).交互模式
run         //運行程序
continue  //中斷後繼續運行到下一個斷點
step        //單步執行,進入函數
next       //單步執行
return    //函數未執行完,忽略未執行的語句,返回。
finish     //函數執行完畢返回。
call        //調用某一個函數 fun("1234")
(backtrace)bt //顯示棧楨
bt N              //顯示開頭N個棧楨
bt -N            //顯示最後N個棧楨
(frame)f N     //顯示第N層棧楨
list //顯示源碼
set directory  //設置gdb的工做目錄
pwd              //當前的工做目錄多線程

(3)反覆執行
continue N    //連續執行cointiue N次,通常用於避免頻繁斷點
step N
next Napp

3.斷點
break 函數名        //設置斷在某個函數
break 文件名:行號 //設置斷在某一行
info break            //查看設置的斷點信息
break if condition //條件斷點
break 函數名 thread 線程號 //設置斷點只斷某個線程,經過info threads 查看線程號
delete 斷點號 斷點號... //刪除一個或多個斷點
diable 斷點號 斷點號... //禁止一個或多個斷點
enable 斷點號 斷點號... //打開一個或多個斷點
command 斷點號 //斷點觸發時,執行命令,通常用於打印變量
(gdb) command 1
Type commands for breakpoint(s) 1, one per line.
End with a line saying just "end".
>print x
>end
(gdb) async

4.檢測點
watch //爲表達式(變量)expr設置一個觀察點。一量表達式值有變化時,立刻停住程序。
rwatch //當表達式(變量)expr被讀時,停住程序。
awatch //當表達式(變量)的值被讀或被寫時,停住程序。
info watchpoints //列出當前所設置了的全部觀察點。函數

經驗:觀察某個變量是否變化,被讀或者被寫,因爲變量只在某一個做用域,能夠獲取變量的地址,而後觀察。
好比:觀察examined_rows變量神馬時候被修改
(1).p &examined_rows,獲得地址
(2).watch *(ha_rows *) 0x7ffec8005e28,則能夠觀察這個變量的變化狀況。測試

5.查看變量
(1)設置
set print elements N //指定打印的長度,對長字符串特別有用。
set print element 0 //輸出完整的字符串
set print pretty //設置GDB打印結構的時候,每行一個成員,而且有相應的縮進,缺省是關閉的
print {type} variable
好比:
(gdb) p {ABC} 0x7fffffffe710
$2 = {val = 1.5, val2 = 10}ui

print xxx //打印變量
p /x xxx //16進制顯示
p str@str_len //打印字符串spa

info locals //打印出當前函數中全部局部變量及其值。
info args //打印出當前函數的參數名及其值。
display 變量 //自動打印變量
undisplay //取消自動打印
注意:默認編譯的時候,調試過程是看不見宏的值的,編譯時候須要給選項。-g3

6.內存查看
格式: x /nfu <addr> x 是 examine 的縮寫
a.n表示要顯示的內存單元的個數
b.f表示顯示方式, 可取以下值
(1).x 按十六進制格式顯示變量。
(2).d 按十進制格式顯示變量。
(3).u 按十進制格式顯示無符號整型。
(4).o 按八進制格式顯示變量。
(5).t 按二進制格式顯示變量。
(6).a 按十六進制格式顯示變量。
(7).i 指令地址格式
(8).c 按字符格式顯示變量。
(9).f 按浮點數格式顯示變量。
c.u表示一個地址單元的長度
(1).b表示單字節,
(2).h表示雙字節,
(3).w表示四字節,
(4).g表示八字節

好比:x/3xh buf
表示從內存地址buf讀取內容,3表示三個單位,x表示按十六進制顯示,h表示以雙字節爲一個單位。

7.多線程調試
info threads //查看線程
thread thread_no //切換到線程號
thread apply all command //全部線程都執行命令打印棧楨
好比:thread apply all bt //全部線程都打印棧楨

(1)線程鎖
show scheduler-locking
set scheduler-locking on
set scheduler-locking off
默認是off,當程序繼續運行的時候若是有斷點,那麼就把全部的線程都停下來,直到你指定某個線程繼續執行(thread thread_no apply continue).
可是若是直接在當前線程執行continue的話,默認是會啓動全部線程。這種模式有一種反作用,若是多個線程都斷在同一個函數,這時候調試會出問題。
這個時候須要打開線程鎖,但打開線程鎖,意味着其它線程不能運行了。

(2)non-stop模式(7.0之後的版本支持)
set target-async 1
set pagination off
set non-stop on
gdb啓動了不停模式,除了斷點有關的線程會被停下來,其餘線程會執行。

8.信號量
(1).singal 發送信號
假定你的程序已將一個專用的 SIGINT(鍵盤輸入,或CTRL-C;信號2)信號處理程序設置成採起某個清理動做,
要想測試該信號處理程序,你能夠設置一個斷點並使用以下命令:
(gdb) signal 2
(2).handle 攔截信號
Handle命令可控制信號的處理,他有兩個參數,一個是信號名,另外一個是接受到信號時該做什麼。幾種可能的參數是:
* nostop 接收到信號時,不要將它發送給程序,也不要中止程序。
* stop 接受到信號時中止程序的執行,從而容許程序調試;顯示一條表示已接受到信號的消息(禁止使用消息除外)
* print 接受到信號時顯示一條消息
* noprint 接受到信號時不要顯示消息(並且隱含着不中止程序運行)
* pass 將信號發送給程序,從而容許你的程序去處理它、中止運行或採起別的動做。
* nopass 中止程序運行,但不要將信號發送給程序。
好比:
handle SIGPIPE stop print //截獲SIGPIPE信號,程序中止並打印信息
handle SIGUSR1 nostop noprint //忽略SIGUSR1信號

9.生產環境使用GDB場景
內核轉儲(coredump)
(1).配置產生core文件
前置條件:確保系統配置的core file size足夠,通常設置成unlimited
ulimit -c unlimited

配置corefile的參數:
echo 2 > /proc/sys/fs/suid_dumpable [程序中切換用戶,也要產生corefile]
mkdir /tmp/corefiles
chmod 777 /tmp/corefiles
echo "/tmp/corefiles/core">/proc/sys/kernel/core_pattern //配置core文件產生的目錄爲/tmp/corefiles
echo "1" > /proc/sys/kernel/core_uses_pid

kill -sigsegv pid  //模擬異常內存訪問信號

注意:
a.確保配置的目錄有足夠的磁盤空間,不然產生core文件可能不完整。
b.對於mysqld而言,要保證正確產生core-file,須要加上--core-file,默認這個參數是不打開的。
c.kill -9 pid 是不能產生core文件的,由於SIGKILL信號不能被捕獲。

(2).使用core文件
gdb /usr/mysql/bin/mysqld core.24556

(3).dump已經運行進程的狀態信息
gdb attach pid
(gdb) generate-core-file
調試完畢後,經過detach命令退出。
另外,經過gcore pid 命令也能夠dump core文件,生成在當前目錄下。

(4).打印線程信息
pstack pid
pt-pmp -p pid
pstack和pt-pmp均可以打印線程的信息,可是pt-pmp會對同類堆棧的線程作聚合彙總,相對於pstack功能更強大,顯示也更友好。

(5).altert日誌
這裏主要針對mysqld問題排查,mysqld異常crash後,有時候在alter日誌中能夠看到最後crash線程的堆棧,可是通常只有函數名或一串二進制地址,沒法定位到具體是crash到哪一行,經過addr2line能夠解這個問題。
好比:alter日誌中記錄crash時的地址是0x64bd60,經過以下命令,能夠定位到具體是哪一行
addr2line -e /usr/mysql/bin/mysqld 0x64bd60
/home/admin/131_20160715135613566_11155487_code/rpm_workspace/sql/sql_parse.cc:3067

參考文檔
https://www.percona.com/blog/2011/08/26/getting-mysql-core-file-on-linux/

相關文章
相關標籤/搜索