使用GDB調試Linux應用程序

2023-06-27 16:08:23 來源:嵌入式Linux充電站


(資料圖片)

本篇講解使用GDB調試Linux應用程序,以下以 hellowld.c為例介紹 GDB 的調試入門:

編寫代碼

#include < stdio.h >int main(int argc, char **argv){    int i;    int result = 0;    if(1 >= argc)    {        printf("Helloworld.\\n");    }    printf("Hello World %s!\\n",argv[1]);    for(i = 1; i <= 100; i++)  {        result += i;    }    printf("result = %d\\n", result );    return 0;}

編譯時加上 -g參數:

gcc helloworld.c -o hellowrld -g

啟動調試

$ gdb helloWorldGNU gdb (GDB) Red Hat Enterprise Linux 8.2-12.el8Copyright (C) 2018 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".Type "show configuration" for configuration details.For bug reporting instructions, please see:< http://www.gnu.org/software/gdb/bugs/ >.Find the GDB manual and other documentation resources online at:    < http://www.gnu.org/software/gdb/documentation/ >.For help, type "help".Type "apropos word" to search for commands related to "word"...Reading symbols from helloworld...done.(gdb) run                  < ----------------------------- 不帶參數運行Starting program: /home/zhuzhg/helloworldMissing separate debuginfos, use: yum debuginfo-install glibc-2.28-101.el8.x86_64helloworld.result = 5050[Inferior 1 (process 1069013) exited normally](gdb) run China            < ----------------------------- 帶參數運行Starting program: /home/zhuzhg/helloworld ChinaHello World China!result = 5050[Inferior 1 (process 1071086) exited normally](gdb)

斷點

設置斷點

文件行號斷點:break hellowrld.c:9函數斷點:break main條件斷點:break helloworld.c:17 if c == 10臨時斷點, 假設某處的斷點只想生效一次,那么可以設置臨時斷點,這樣斷點后面就不復存在了:tbreak helleworld.c:9禁用或啟動斷點:
disable                 # 禁用所有斷點  disable bnum            # 禁用標號為bnum的斷點  enable                  # 啟用所有斷點  enable bnum             # 啟用標號為bnum的斷點  enable delete bnum      # 啟動標號為bnum的斷點,并且在此之后刪除該斷點
斷點清除:
clear                   # 刪除當前行所有breakpoints  clear function          # 刪除函數名為function處的斷點  clear filename:function # 刪除文件filename中函數function處的斷點  clear lineNum           # 刪除行號為lineNum處的斷點  clear f:lename:lineNum  # 刪除文件filename中行號為lineNum處的斷點  delete                  # 刪除所有breakpoints,watchpoints和catchpoints  delete bnum             # 刪除斷點號為bnum的斷點

變量查看

變量查看:最常見的使用便是使用print(可簡寫為p)打印變量內容。以上述程序為例:

gdb helloworldbreak helloworld.c:17 if i == 0(gdb) runStarting program: /home/book/helloworldhelloworld.Breakpoint 2, main (argc=1, argv=0x7fffffffdca8) at helloworld.c:1717            result += i;(gdb) print i                < ------------------ 查看變量 i 當前的值$1 = 10(gdb) print result           < ------------------ 查看變量 result 當前的值$2 = 45(gdb) print argc             < ------------------ 查看變量 argc 當前的值$3 = 1(gdb) print str$4 = 0x4006c8 "Hello World" < ------------------ 查看變量 str 當前的值

查看內存:examine(簡寫為x)可以用來查看內存地址中的值。語法如下:

x/[n][f][u] addr

其中:

單元類型常見有如下:

示例:

(gdb) x/4b str0x4006c8:    01001000    01100101    01101100    01101100

可以看到,變量 str 的四個字節都以二進制的方式打印出來了。

b 字節h 半字,即雙字節w 字,即四字節g 八字節n 表示要顯示的內存單元數,默認值為1f 表示要打印的格式,前面已經提到了格式控制字符u 要打印的單元長度addr 內存地址

查看寄存器內容:info registers

ra             0x3ff7ef2282     0x3ff7ef2282 < __libc_start_main+160 >sp             0x3ffffffaa0     0x3ffffffaa0gp             0x2aaaaac800     0x2aaaaac800tp             0x3ff7fdd250     0x3ff7fdd250t0             0x3ff7ed60b0     274742468784t1             0x3ff7ef21e2     274742583778t2             0x2aaaaac4f0     183251944688fp             0x3ffffffab0     0x3ffffffab0s1             0x0      0a0             0x1      1a1             0x3ffffffc28     274877905960a2             0x3ffffffc38     274877905976a3             0x0      0a4             0x3ffffffad8     274877905624a5             0x0      0a6             0x3ff7fd88a8     274743527592(內容過多未顯示完全)

單步調試

單步執行-next:next命令(可簡寫為n)用于在程序斷住后,繼續執行下一條語句,假設已經啟動調試,并在第12行停住,如果要繼續執行,則使用n執行下一條語句,如果后面跟上數字num,則表示執行該命令num次,就達到繼續執行n行的效果了:
gdb helloworld                     < ------------------------------- 加載程序   (gdb) break helloworld.c:18        < ------------------------------- 設置斷點   (gdb) run                          < ------------------------------- 啟動調試   The program being debugged has been started already.   Start it from the beginning? (y or n) y   Starting program: /home/book/helloworld   Helleo World.      Breakpoint 2, main (argc=1, argv=0x7fffffffdca8) at helloworld.c:18         < -------- 程序在 18 行暫停   18            result += i;   Breakpoint 2, main (argc=1, argv=0x7fffffffdca8) at helloworld.c:18   18            result += i;   (gdb) next                                    < --------  單步執行      17        for(i = 1; i <= 100; i++)  {      Breakpoint 2, main (argc=1, argv=0x7fffffffdca8) at helloworld.c:18   18            result += i;   (gdb) next 2                                  < --------  執行兩次      Breakpoint 2, main (argc=1, argv=0x7fffffffdca8) at helloworld.c:18   18            result += i;
單步進入-step:如果我們想跟蹤函數內部的情況,可以使用step命令(可簡寫為s),它可以單步跟蹤到函數內部,但前提是該函數有調試信息并且有源碼信息。斷點繼續-continue:continue命令(可簡寫為c),它會繼續執行程序,直到再次遇到斷點處。

標簽:

上一篇:FOC控制算法的Simulink模型-每日時訊
下一篇:最后一頁