GDB調試指南-啟動調試


前言

GDB(GNU Debugger)是UNIX及UNIX-like下的強大調試工具,可以調試ada, c, c++, asm, minimal, d, fortran, objective-c, go, java,pascal等語言。本文以C程序為例,介紹GDB啟動調試的多種方式。

哪類程序可被調試

對於C程序來說,需要在編譯時加上-g參數,保留調試信息,否則不能使用GDB進行調試。
但如果不是自己編譯的程序,並不知道是否帶有-g參數,如何判斷一個文件是否帶有調試信息呢?

gdb 文件

例如:

$ gdb helloworld
Reading symbols from helloWorld...(no debugging symbols found)...done.

如果沒有調試信息,會提示no debugging symbols found。
如果是下面的提示:

Reading symbols from helloWorld...done.

則可以進行調試。

readelf查看段信息

例如:

$ readelf -S helloWorld|grep debug
  [28] .debug_aranges    PROGBITS         0000000000000000  0000106d
  [29] .debug_info       PROGBITS         0000000000000000  0000109d
  [30] .debug_abbrev     PROGBITS         0000000000000000  0000115b
  [31] .debug_line       PROGBITS         0000000000000000  000011b9
  [32] .debug_str        PROGBITS         0000000000000000  000011fc

helloWorld為文件名,如果沒有任何debug信息,則不能被調試。

file查看strip狀況

下面的情況也是不可調試的:

file helloWorld
helloWorld: (省略前面內容) stripped

如果最后是stripped,則說明該文件的符號表信息和調試信息已被去除,不能使用gdb調試。但是not stripped的情況並不能說明能夠被調試。

調試方式運行程序

程序還未啟動時,可有多種方式啟動調試。

調試啟動無參程序

例如:

$ gdb helloWorld
(gdb)

輸入run命令,即可運行程序

調試啟動帶參程序

假設有以下程序,啟動時需要帶參數:

#include<stdio.h>
int main(int argc,char *argv[])
{
    if(1 >= argc)
    {
        printf("usage:hello name\n");
        return 0;
    }
    printf("Hello World %s!\n",argv[1]);
    return 0 ;
}

編譯:

gcc -g -o hello hello.c

這種情況如何啟動調試呢?需要設置參數:

$ gdb hello
(gdb)run 編程珠璣
Starting program: /home/shouwang/workspaces/c/hello 編程珠璣
Hello World 編程珠璣!
[Inferior 1 (process 20084) exited normally]
(gdb)

只需要run的時候帶上參數即可。
或者使用set args,然后在用run啟動:

gdb hello
(gdb) set args 編程珠璣
(gdb) run
Starting program: /home/hyb/workspaces/c/hello 編程珠璣
Hello World 編程珠璣!
[Inferior 1 (process 20201) exited normally]
(gdb) 

調試core文件

當程序core dump時,可能會產生core文件,它能夠很大程序幫助我們定位問題。但前提是系統沒有限制core文件的產生。可以使用命令limit -c查看:

$ ulimit -c
0

如果結果是0,那么恭喜你,即便程序core dump了也不會有core文件留下。我們需要讓core文件能夠產生:

ulimit -c unlimied  #表示不限制core文件大小
ulimit -c 10        #設置最大大小,單位為塊,一塊默認為512字節

上面兩種方式可選其一。第一種無限制,第二種指定最大產生的大小。
調試core文件也很簡單:

gdb 程序文件名 core文件名

具體可參看《linux常用命令-開發調試篇》gdb部分。

調試已運行程序

如果程序已經運行了怎么辦呢?
首先使用ps命令找到進程id:

ps -ef|grep 進程名

attach方式

假設獲取到進程id為20829,則可用下面的方式調試進程:

$ gdb
(gdb) attach 20829

接下來就可以繼續你的調試啦。

可能會有下面的錯誤提示:

Could not attach to process.  If your uid matches the uid of the target
process, check the setting of /proc/sys/kernel/yama/ptrace_scope, or try
again as the root user.  For more details, see /etc/sysctl.d/10-ptrace.conf
ptrace: Operation not permitted.

解決方法,切換到root用戶:
將/etc/sysctl.d/10-ptrace.conf中的

kernel.yama.ptrace_scope = 1

修改為

kernel.yama.ptrace_scope = 0

直接調試相關id進程

還可以是用這樣的方式gdb program pid,例如:

gdb hello 20829  

或者:

gdb hello --pid 20829

已運行程序沒有調試信息

為了節省磁盤空間,已經運行的程序通常沒有調試信息。但如果又不能停止當前程序重新啟動調試,那怎么辦呢?還有辦法,那就是同樣的代碼,再編譯出一個帶調試信息的版本。然后使用和前面提到的方式操作。對於attach方式,在attach之前,使用file命令即可:

$ gdb
(gdb) file hello
Reading symbols from hello...done.
(gdb)attach 20829

總結

本文主要介紹了兩種類型的GDB啟動調試方式,分別是調試未運行的程序和已經運行的程序。對於什么樣的程序能夠進行調試也進行了簡單說明。

歡迎留言補充。

微信公眾號【編程珠璣】:專注但不限於分享計算機編程基礎,Linux,C語言,C++,算法,數據庫等編程相關[原創]技術文章,號內包含大量經典電子書和視頻學習資源。歡迎一起交流學習,一起修煉計算機“內功”,知其然,更知其所以然。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM