溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Linux系統(tǒng)中GDB是什么

發(fā)布時間:2022-01-30 11:00:04 來源:億速云 閱讀:411 作者:小新 欄目:開發(fā)技術

小編給大家分享一下Linux系統(tǒng)中GDB是什么,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!

GDB是 Linux 平臺下最常用的一款程序調試器。Linux GDB調試是C/C++程序員必須掌握的技能。

Linux系統(tǒng)中GDB是什么

1、GDB簡介:

GDB(GNU symbolic debugger)是 GNU Project 調試器,它使你可以查看另一個程序在“執(zhí)行”期間正在執(zhí)行的操作–或該程序崩潰時正在執(zhí)行的操作。

GDB 可以做四種主要的事情(以及支持這些事情的其他事情)來幫助你捕獲行為中的錯誤:

  • 啟動你的程序,并指定可能影響其行為的所有內容。

  • 使程序在指定條件下停止。

  • 檢查程序停止時發(fā)生的情況。

  • 更改程序中的內容,以便你可以嘗試糾正一個錯誤的影響,然后繼續(xù)學習另一個錯誤。

這些程序可能與GDB(本機)在同一臺計算機上執(zhí)行,在另一臺計算機(遠程)上或在模擬器上執(zhí)行。GDB可以在大多數(shù)流行的UNIX和Microsoft Windows變體以及Mac OS X上運行。

2、GDB基本調試命令

2.1 準備

  通過 gcc 的 -g 選項,將調試信息加到可執(zhí)行文件中。

 $ gcc -g hello.c -o hello1

  如果使用 Makefile 構建,一般要在 CFLAGS 中指定 -g 選項。

 CFLAGS := -Wall -O2 -g1

  注意,給 GCC 編譯器加上優(yōu)化選項后,實際的執(zhí)行順序可能由于優(yōu)化而與源代碼順序不同,因此利用調試器跟蹤運行時,有時會執(zhí)行到莫名奇妙的地方,從而造成混亂。

2.2 啟動

  使用命令 gdb 程序名啟動。

2.3 設置斷點

  可以在函數(shù)名和行號等上設置斷點。程序到達斷點就會自動暫停運行。此時可以查看該時刻的變量值,顯示棧幀、重新設置斷點或重新運行等。斷點命令 break 可以簡寫為 b,命令為 break 。      斷點可以通過函數(shù)名、當前文件內的行號來設置,也可以先指定文件名再指定行號,還可以指定與暫停位置的偏移量,或者用地址來設置。格式:

格式說明
break對當前正在執(zhí)行的文件中的指定函數(shù)設置斷點
break對當前正在執(zhí)行的文件中的特定行設置斷點
break 文件名:行號對指定文件的指定行設置斷點,最常用的設置斷點方式
break 文件名:函數(shù)名對指定文件的指定函數(shù)設置斷點
break當前指令行+/-偏移量出設置斷點
break指定地址處設置斷點

     設置好的斷點可以通過 info break 確認。

2.4 運行

  使用 run 參數(shù) 命令開始運行,其中參數(shù)為可執(zhí)行程序的參數(shù)。如果設置了斷點,會執(zhí)行到設置了斷點的位置后暫停運行。可以簡寫為 r。

2.5 顯示棧幀

  backtrace 命令可以在遇到斷點或異常而暫停執(zhí)行時顯示棧幀,該命令簡寫為 bt。此外,backtrace 的別名還有 where 和 info stack。

格式說明
bt顯示所有棧幀
bt 只顯示開頭 N 個棧幀
bt只顯示最后 N 個棧幀
bt full不僅顯示 backtrace,還要顯示局部變量
bt full 

     顯示棧幀之后,就可以看出程序在何處停止,以及程序的調用路徑。

2.6 顯示變量

  print 命令可以顯示變量,可以簡寫為 p。      格式:print 變量。

2.7 顯示寄存器

  info registers 可以顯示寄存器,簡寫為 info reg。      在寄存器名之前添加 $,顯示寄存器的內容,例如 p $eax。   p/格式 $寄存器 可以指定寄存器的顯示格式,例如 p/c $eax??墒褂玫母袷饺缦拢?/p>

格式說明
x顯示為十六進制數(shù)
d顯示為十進制數(shù)
u顯示為無符號十進制數(shù)
o顯示為八進制數(shù)
t顯示為二進制數(shù)
a地址
c顯示為字符(ASCII)
f浮點小數(shù)
s顯示為字符串
i顯示為機器語言,僅在顯示內存的 x 命令中可用

顯示詳細信息

     程序指針可以寫為 ,也可以寫為eip,使用 p $pc 顯示程序指針內容。程序指針指向當前程序的運行點的地址。      x 命令可以顯示內存的內容,格式:x/ 。例如 x/i $ps,顯示匯編指令。      一般使用 x 命令時,格式為 x/ 。此處 ADDR 為希望顯示的地址,N 為重復次數(shù),F(xiàn) 為前面的顯示格式,U 代表的單位如下:

單位說明
b字節(jié)
h半字(2 字節(jié))
w字(4 字節(jié))(默認值)
g雙字(8 字節(jié))

  例如命令 x\10i $pc 顯示從 pc 所指地址開始的 10 條指令。      反匯編命令 disassemble,簡寫為 disas。格式:

  • disassemble。反匯編當前整個函數(shù)。

  • disassemble 程序計數(shù)器。反匯編程序計數(shù)器所在函數(shù)的整個函數(shù)。

  • disassemble 開始地址 結束地址。反匯編從開始地址到結束地址之間的部分。

2.8 單步執(zhí)行

  單步執(zhí)行的意思時根據(jù)源代碼一行一行地執(zhí)行。執(zhí)行源代碼中一行的命令為 next ,簡寫為 n。執(zhí)行時如果遇到函數(shù)調用,想執(zhí)行到函數(shù)內部,使用 step 命令,簡寫為 p。   如果要逐條執(zhí)行匯編指令,可以分別使用 nexti 和 stepi 命令。

2.9 繼續(xù)運行

  使用 continue 命令繼續(xù)運行程序,簡寫為 c。程序會在遇到斷點后再次暫停運行。使用 continue  命令指定忽略斷點的次數(shù)。

2.10 監(jiān)視點

  大型軟件或大量使用指針的程序中,很難弄清變量在什么地方被改變,要想找到變量在何處被改變,可以使用 watch 命令(監(jiān)視點,watchpoint)。格式如下:

  • watch 。表達式發(fā)生變化時暫停運行。

  • awatch 。表達式被訪問、改變時暫停運行。

  • rwatch 。表達式被訪問時暫停運行。

  需要注意,設置監(jiān)視點可能會降低運行速度。

2.11 刪除斷點和監(jiān)視點

  delete 命令刪除斷點和監(jiān)視點,簡寫為 d。格式為 delete ,表示刪除編號指示的斷點或監(jiān)視點,編號可以用命令 info b 查看。   clear 命令刪除已定義的斷點??捎妹畎ǎ?    clear      clear      clear 文件名:行號     clear 文件名:函數(shù)名      disable 命令禁用斷點。命令格式如下:     disable:禁用所有斷點。     disable :禁用指定斷點。     disable display :禁用 display 命令定義的自動顯示。     disable mem :禁用 mem 命令定義的內存區(qū)域。      enable 命令用于啟用斷點。命令格式如下:     enable     enable      enable once :使指定的斷點只啟用一次。     enable delete      enable display      enable mem

2.12 其他斷點

  硬件斷點(hbreak),適用于 ROM 空間等無法修改的內存區(qū)域中的程序,在有些架構中無法使用。      臨時斷點(tbreak)和臨時硬件斷點(thbreak),在運行到該處時暫停,此時斷點會被刪除,在只需要停止一次時用起來方便。

2.13 改變變量的值

  格式:set variable 。例如命令 set variable options = 0,將變量 options 的值改成了 0。

2.14 生成內核轉儲文件

  使用 generate-core-file 可將調試中的進程生成內核轉儲文件。通過內核轉儲文件和調試對象,查看生成轉儲文件時的運行歷史。      gcore 命令可以從命令行直接生成內核轉儲文件。在命令行使用 gcore pid,其中 pid 為進程號。該命令無須停止正在運行的程序以獲得內核轉儲文件,當需要在其他機器上單獨分析問題原因,或是分析客戶現(xiàn)場發(fā)生的問題時十分有用。


3、內核轉儲

  內核轉儲(core dump)的最大好處是,它能保存問題發(fā)生時的狀態(tài)。只要有問題發(fā)生時程序的可執(zhí)行文件和內核轉儲,就可以知道進程當前的狀態(tài)。

3.1 啟用內核轉儲

  大多數(shù) Linux 發(fā)行版默認關閉了內核轉儲功能,使用 ulimit 命令可以查看當前的內核轉儲功能是否有效。

 $ ulimit -c
 012

  -c 選項表示內核轉儲文件的大小限制,0 表示內核轉儲無效。開啟內核轉儲執(zhí)行命令:

 $ ulimit -c unlimited
 or
 $ ulimit -c 上限123

  unlimited 意思是不限制內核轉儲文件的大小,發(fā)生問題時進程的內存就可以全部轉儲到內核轉儲文件中?;蛘咴O置內核轉儲文件的上限,在參數(shù)中指定上限大小,單位為 Kb。      程序發(fā)生異常時會在當前目錄下生成內核轉儲文件。例如程序 a.out 生成轉儲文件 core,使用以下方式啟動 GDB:

 $ gdb -c core ./a.out1

     使用 GDB 的 list 命令可以查看附近的源代碼。命令使用方法

格式說明
list 顯示程序第 linenum 行周圍的源代碼
list 顯示函數(shù)名為 function 的函數(shù)的源代碼
list顯示當前行后面的源代碼
list –顯示當前行前面的源代碼
set listsize 設置一次顯示源代碼的行數(shù)
show listsize查看當前 listsize 的設置
list ,顯示從 first 行到 last 行之間的源代碼
list ,顯示從當前行到 last 行之間的源代碼
list +往后顯示源代碼
3.2 在專用目錄中生成內核轉儲

  轉儲保存位置的完整路徑可以通過 sysctl 變量 kernel.core_pattern 設置。在文件 /etc/sysctl.conf 中設置如下:

 $ cat /etc/sysctl.conf
 kernel.core_pattern = /var/core/%t-%e-%p-%c.core
 kernel.core_uses_pid = 0
 $ sysctl -p1234

     此外,還可以在 /proc/sys/kernel 下修改設置。   /proc/sys/kernel/core_uses_pid 可以控制產(chǎn)生的 core 文件的文件名中是否添加 pid 作為擴展 ,如果添加則文件內容為 1 ,否則為 0。   proc/sys/kernel/core_pattern 可以設置格式化的 core 文件保存位置或文件名 ,可以這樣修改 :

 $ echo "/corefile/core-%e-%p-%t" > core_pattern1

     kernel.core_pattern 中可以設置的格式符如下:

格式符說明
%%% 字符本身
%p被轉儲進程的進程 ID(PID)
%u被轉儲進程的真實用戶 ID(real UID)
%g被轉儲進程的真實組 ID(real GID)
%s引發(fā)轉儲的信號編號
%t轉儲時刻(從 1970/1/1 0:00 開始的秒數(shù))
%h主機名(同 uname(2) 返回的 nodename)
%e可執(zhí)行文件名
%c轉儲文件的大小上限(內核版本 2.6.24 后可用)
3.3 使用用戶模式輔助程序自動壓縮內核轉儲文件

  修改 /etc/sysctl.conf中 的 kernel.core_pattern 變量來設置。

  $ cat /etc/sysctl.conf
 kernel.core_pattern= | usr/local/sbin/core_helper %t %e %p %c
 kernel.core_uses_pid= 0
  $ sysctl -p1234

  core_helper 的內容:

 $cat usr/local/sbin/core_helper
 #!/bin/sh
 
 execgzip ->/var/core/$1-$2-$3-$4.core.gz1234

  這樣,發(fā)生內核轉儲時就會在 /var/core 下生成壓縮的內核轉儲文件。

3.4 啟用整個系統(tǒng)的內核轉儲功能

  /etc/profile 文件中可以設置開啟所有用戶的內核轉儲功能,默認情況下禁止內核轉儲:

 ulimit -S -c 0 > /dev/null 2>&11

  將其修改為

 ulimit -S -c unlimited > /dev/null 2>&11

     接下來要讓通過 init 腳本啟動的守護進程的內核轉儲功能有效。在 /etc/sysconfig/init 文件中添加一行命令。

 DAEMON_COREFILE_LIMIT='unlimited'1

     最后在 /etc/sysctl.conf 中加入以下設置。

 fs.suid_dumpable=11

  這個設置使得被 SUID 的程序也能內核轉儲。重新啟動啟動,就可以啟用整個系統(tǒng)的內核轉儲。      在我使用的Ubuntu、Debian和移植的嵌入式Linux系統(tǒng)中,沒有找到 /etc/sysconfig 文件夾。修改了文件 /etc/security/limits.conf,按照文件的內容提示修改,使 unlimited 永久生效。

3.4 利用內核轉儲掩碼排除共享內存

  多進程程序如果使用龐大的共享內存,內核轉儲時所有進程的共享內存全部轉儲,會對磁盤造成巨大的壓力,轉儲過程也會加重系統(tǒng)的負載。由于共享內存的內容是相同的,只需要在某個進程中轉儲共享內存。      通過 /proc//coredump_filter 進行設置。coredump_filter 使用比特掩碼表示內存類型。如下所示:

比特掩碼內存類型
比特 0匿名專用內存
比特 1匿名共享內存
比特 2file-backed 專用內從
比特 3file-backed 共享內存
比特 4ELF 文件映射(內核版本 2.6.24 后可用)

  要跳過所有的共享內存區(qū)段,應將值改位 1。


4、GDB調試技巧

4.1 attach 到進程

  要調試已經(jīng)啟動的進程,或是調試陷入死循環(huán)而無法返回控制臺的進程時,可以使用 attach 命令。格式:attach,執(zhí)行這一命令可以 attach 到進程 ID 為 pid 的進程上。   attach 之后就能使用普通的 gdb 命令。      gdb 和進程分離時使用 detach 命令,調試的進程就從 gdb 的控制下釋放出來。進程被 detach 后繼續(xù)運行。      進程信息可以用 info proc 命令顯示。   守護者進程在啟動好子進程后,會自動關閉主進程,如果沒有設定監(jiān)控模式的話,gdb 會提示斷開與進程的鏈接。所以必須設定監(jiān)控對象,設置命令為 set follow-fork-mode child/parent。

4.2 條件斷點

  break  if ,這條命令將測試給定的條件,如果為幀則暫停運行。      如果斷點已經(jīng)存在,condition   命令給斷點添加觸發(fā)條件,condition  命令刪除指定編號斷點的觸發(fā)條件。

4.3 反復執(zhí)行

  ignore  :在編號指定的斷點、監(jiān)視點或捕獲點忽略指定的次數(shù)。   continue : 達到指定次數(shù)前,執(zhí)行到斷電時不暫停。   s/stepi/n/nexti :執(zhí)行指定次數(shù)的相應命令。   finish:執(zhí)行完當前函數(shù)后暫停。   until:執(zhí)行完當前函數(shù)等代碼塊后暫停,如果是循環(huán),則在執(zhí)行完循環(huán)后暫停,常用于跳出循環(huán)。   until :執(zhí)行到指定地址停止。

4.4 斷點命令

  commands 命令可以定義在斷點終端后自動執(zhí)行的命令。格式如下:

 (gdb) commands 
 
 ...
 end1234
4.5 值的歷史

  通過 print 命令顯示過的值會記錄在內部的值歷史中。這些值通過 $ 進行引用,使用 show value 命令可以顯示歷史中的最后 10 個值。

變量說明
$值歷史的最后一個值
$n值歷史的第 n 個值
$$值歷史的倒數(shù)第 2 個值
$$n值歷史的倒數(shù)第 n 個值
$_x 命令顯示過的最后的地址
$__x 命令顯示過的最后的地址的值
$_eexitcode調試過程中的程序的返回代碼
$bpnum最后設置的斷點編號

     還可以隨意定義變量,變量以 $ 開頭,由英文字母和數(shù)字組成。例如:

 (gdb) set $i=0
 (gdb) p $i
 $i = 0123
4.6 命令歷史

  show history 將命令歷史保存到文件中,默認命令歷史文件位于 ./.gdb_history。

  set history expansion   show history expansion

  可以使用 csh 風格的 ! 字符。

  set history filename    show history filename

  將命令歷史保存到文件中。可以通過環(huán)境變量 GDBHISTFILE 改變默認文件名。

  set history save   show history save

  啟用命令歷史保存到文件和恢復的功能。

  set history size    show history size

  可設置保存到命令歷史中的命令數(shù)量。默認值為 256。

4.7 初始化文件(.gdbinit)

  Linux 環(huán)境下的初始化文件為 .gdbinit。如果存在 .gdbinit 文件,GDB 會在啟動之前將其作為命令文件運行。初始化文件和命令文件的運行順序如下。

  • 1、$HOME/.gdbinit。

  • 2、運行命令行選項。

  • 3、./.gdbinit。

  • 4、通過 -x 選項給出的命令文件。

  初始化文件和命令文件的語法相同。利用 define 命令可以自定義命令,document 命令給自定義命令添加說明,GDB 運行時使用 help  可以查看定義的命令。示例如下:

 define li
    x/10i $pc
 end
 document li
    list machine instruction
 end123456

     除了初始化文件,還可以把設置寫在文件中,在運行 GDB 時讀取這些文件。命令為 source ,例如:

 (gdb) source gdbcalc
 (gdb) p $log10(10000.0)
 $1 = 4123

  其中 gdbcalc 文件內容如下:

 #!/usr/bin/gdb -x
 file /usr/bin/gdb
 start
 set $e = 2.7182818284590452354
 set $pi = 3.14159265358979323846
 set $fabs = (double (*)(double)) fabs
 set $sqrt = (double (*)(double)) sqrt
 set $cbrt = (double (*)(double)) cbrt
 set $exp = (double (*)(double)) exp
 set $exp2 = (double (*)(double)) exp2
 set $exp10 = (double (*)(double)) exp10
 set $log = (double (*)(double)) log
 set $log2 = (double (*)(double)) log2
 set $log10 = (double (*)(double)) log10
 set $pow = (double (*)(double, double)) pow
 set $sin = (double (*)(double)) sin
 set $cos = (double (*)(double)) cos
 set $tan = (double (*)(double)) tan
 set $asin = (double (*)(double)) asin
 set $acos = (double (*)(double)) acos
 set $atan = (double (*)(double)) atan
 set $atan2 = (double (*)(double, double)) atan
 set $sinh = (double (*)(double)) sinh
 set $cosh = (double (*)(double)) cosh
 set $tanh = (double (*)(double)) tanh
 set $asinh = (double (*)(double)) asinh
 set $acosh = (double (*)(double)) acosh
 set $atanh = (double (*)(double)) atanh22345678910111213141516171819202122232425262728

5、總結

  GDB 常用命令及縮略形式如下表:

命令簡寫形式說明
backtracebt、where顯示 backtrace
break設置斷點
continuec、cont繼續(xù)運行
deleted刪除斷點
finish運行到函數(shù)結束
info breakpoints顯示斷點信息
nextn執(zhí)行下一行
printp顯示表達式
runr運行程序
steps一次執(zhí)行一行,包括函數(shù)內部
x顯示內存內容
untilu執(zhí)行到指定行
directorydir插入目錄
disabledis禁用斷點
downdo在當前調用的棧幀中選擇要顯示的棧幀
edite編輯文件或函數(shù)
framef選擇要顯示的棧幀
forward-searchfo向前搜索
generate-core-filegcore生成內核轉儲
helph顯示幫助一覽
infoi顯示信息
listl顯示函數(shù)或行
nextini執(zhí)行下一行(以匯編代碼為單位)
print-objectpo顯示目標信息
sharedlibraryshare加載共享庫的符號
setpisi執(zhí)行下一行

顯示詳細信息

以上是“Linux系統(tǒng)中GDB是什么”這篇文章的所有內容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內容對大家有所幫助,如果還想學習更多知識,歡迎關注億速云行業(yè)資訊頻道!

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權內容。

AI