最美情侣中文字幕电影,在线麻豆精品传媒,在线网站高清黄,久久黄色视频

歡迎光臨散文網(wǎng) 會(huì)員登陸 & 注冊(cè)

手把手教你寫一個(gè)GDB(基本功能~)

2022-06-23 14:15 作者:補(bǔ)給站Linux內(nèi)核  | 我要投稿

什么是 GDB

  • GDB 全稱 the GNU Project debugger,主要用來調(diào)試用戶態(tài)應(yīng)用程序。

  • 根據(jù)官方文檔介紹,GDB 支持調(diào)試以下語言編寫的應(yīng)用程序:

  1. Ada

  2. Assembly

  3. C

  4. C++

  5. D

  6. Fortran

  7. Go

  8. Objective-C

  9. OpenCL

  10. Modula-2

  11. Pascal

  12. Rust

  • 當(dāng)然,最常用的還是用于調(diào)試 C/C++ 編寫的應(yīng)用程序。

  • 本文并不是 GDB 的使用教程,所以不會(huì)對(duì) GDB 的使用進(jìn)行詳細(xì)的介紹。本文的目的是,教會(huì)大家自己動(dòng)手?jǐn)]一個(gè)簡(jiǎn)易的 GDB。所以閱讀本文前,最好先了解下 GDB 的使用。

  • 在編程圈中流傳一句話:不要重復(fù)造輪子。但是本人覺得,重復(fù)造輪子才能真正理解輪子的實(shí)現(xiàn)原理。

ptrace 系統(tǒng)調(diào)用

  • GDB 實(shí)現(xiàn)的核心技術(shù)是 ptrace() 系統(tǒng)調(diào)用。

如果你對(duì) ptrace 的實(shí)現(xiàn)原理有興趣,可以閱讀這篇文章進(jìn)行了解:《ptrace實(shí)現(xiàn)原理》

  • ptrace() 是一個(gè)復(fù)雜的系統(tǒng)調(diào)用,主要用于編寫調(diào)試程序。你可以通過以下命令來查看 ptrace() 的介紹:

  • ptrace() 系統(tǒng)調(diào)用的功能很強(qiáng)大,但我們并不會(huì)用到所有的功能。所以,本文的約定是:在編寫程序的過程中,使用到的功能才會(huì)進(jìn)行詳細(xì)介紹。

  • 可見,運(yùn)行 ls 這個(gè)命令需要執(zhí)行 40 多萬條指令。


【文章福利】小編推薦自己的Linux內(nèi)核技術(shù)交流群:【891587639】整理了一些個(gè)人覺得比較好的學(xué)習(xí)書籍、視頻資料共享在群文件里面,有需要的可以自行添加哦?。。。ê曨l教程、電子書、實(shí)戰(zhàn)項(xiàng)目及代碼)? ??


簡(jiǎn)易的 GDB

  • 我們要實(shí)現(xiàn)一個(gè)有如下功能的 GDB:

  1. 可以對(duì)一個(gè)可執(zhí)行程序進(jìn)行調(diào)試。

  2. 可以在調(diào)試程序時(shí),設(shè)置斷點(diǎn)。

  3. 可以在調(diào)試程序時(shí),打印程序的信息。

  • 下面主要圍繞這三個(gè)功能進(jìn)行闡述。

1. 調(diào)試可執(zhí)行文件

  • 我們使用 GDB 調(diào)試程序時(shí),一般使用 GDB 直接加載程序的可執(zhí)行文件,如下命令:

  • 上面命令的執(zhí)行過程如下:

  1. 首先,GDB 調(diào)用 fork() 系統(tǒng)調(diào)用創(chuàng)建一個(gè)新的子進(jìn)程。

  2. 然后,子進(jìn)程會(huì)調(diào)用 exec() 系統(tǒng)調(diào)用加載程序的可執(zhí)行文件到內(nèi)存。

  3. 接著,子進(jìn)程便進(jìn)入停止?fàn)顟B(tài)(停止運(yùn)行),并且等待 GDB 主進(jìn)程發(fā)送調(diào)試命令。

  • 流程如下圖所示:



  • 我們可以按照上面的流程來編寫代碼:

第一步:創(chuàng)建被調(diào)試子進(jìn)程

  • 調(diào)試程序一般分為 被調(diào)試進(jìn)程 與 調(diào)試進(jìn)程。

  1. 被調(diào)試進(jìn)程:就是需要被調(diào)試的進(jìn)程。

  2. 調(diào)試進(jìn)程:主要用于向 被調(diào)試進(jìn)程 發(fā)送調(diào)試命令。

  • 實(shí)現(xiàn)代碼如下:

  • 上面的代碼執(zhí)行流程如下:

  1. 主進(jìn)程首先調(diào)用 fork() 系統(tǒng)調(diào)用創(chuàng)建一個(gè)子進(jìn)程。

  2. 然后子進(jìn)程會(huì)調(diào)用 load_executable_file() 函數(shù)加載要進(jìn)行調(diào)試的程序,并且等待主進(jìn)程發(fā)送調(diào)試命令。

  3. 最后主進(jìn)程會(huì)調(diào)用 send_debug_command() 向被調(diào)試進(jìn)程(子進(jìn)程)發(fā)送調(diào)試命令。

  • 所以,接下來我們主要介紹 load_executable_file() 和 send_debug_command() 這兩個(gè)函數(shù)的實(shí)現(xiàn)過程。

第二步:加載被調(diào)試程序

  • 前面我們說過,子進(jìn)程主要用于加載被調(diào)試的程序,并且等待調(diào)試進(jìn)程(主進(jìn)程)發(fā)送調(diào)試命令,現(xiàn)在我們來分析下 load_executable_file() 函數(shù)的實(shí)現(xiàn):

  • load_executable_file() 函數(shù)的實(shí)現(xiàn)很簡(jiǎn)單,主要執(zhí)行流程如下:

  1. 調(diào)用 ptrace(PTRACE_TRACEME...) 系統(tǒng)調(diào)用告知內(nèi)核,當(dāng)前進(jìn)程可以被進(jìn)行跟蹤,也就是可以被調(diào)試。

  2. 調(diào)用 execl() 系統(tǒng)調(diào)用加載并且執(zhí)行被調(diào)試的程序可執(zhí)行文件。

  • 首先,我們來看看 ptrace() 系統(tǒng)調(diào)用的原型定義:

  • 下面我們對(duì)其各個(gè)參數(shù)進(jìn)行說明:

  1. request:向進(jìn)程發(fā)送的調(diào)試命令,可以發(fā)送的命令很多。比如上面代碼的 PTRACE_TRACEME 命令定義為 0,表示能夠?qū)M(jìn)程進(jìn)行調(diào)試。

  2. pid:指定要對(duì)哪個(gè)進(jìn)程發(fā)送調(diào)試命令的進(jìn)程ID。

  3. addr:如果要讀取或者修改進(jìn)程某個(gè)內(nèi)存地址的內(nèi)容,就可以通過這個(gè)參數(shù)指定。

  4. data:如果要修改進(jìn)程某個(gè)地址的內(nèi)容,要修改的值可以通過這個(gè)參數(shù)指定,配合 addr 參數(shù)使用。

  • 所以,代碼:

  • 的作用就是告知內(nèi)核,當(dāng)前進(jìn)程能夠被跟蹤(調(diào)試)。

  • 接著,當(dāng)調(diào)用 execl() 系統(tǒng)調(diào)用加載并且執(zhí)行被調(diào)試的程序時(shí),內(nèi)核會(huì)把當(dāng)前被調(diào)試的進(jìn)程掛起(把運(yùn)行狀態(tài)設(shè)置為停止?fàn)顟B(tài)),等待主進(jìn)程發(fā)送調(diào)試命令。

當(dāng)進(jìn)程的運(yùn)行狀態(tài)被設(shè)置為停止?fàn)顟B(tài)時(shí),內(nèi)核會(huì)停止對(duì)此進(jìn)程進(jìn)行調(diào)度,除非有其他進(jìn)程把此進(jìn)程的運(yùn)行狀態(tài)改為可運(yùn)行狀態(tài)。

第三步:向被調(diào)試進(jìn)程發(fā)送調(diào)試命令

  • 我們來到最重要的一步了,就是要向被調(diào)試的進(jìn)程發(fā)送調(diào)試命令。

  • 用過 GDB 調(diào)試程序的同學(xué)都非常熟悉,我們可以向被調(diào)試的進(jìn)程發(fā)送 單步調(diào)試、打印當(dāng)前堆棧信息、查看某個(gè)變量的值 和 設(shè)置斷點(diǎn) 等操作。

  • 這些命令都可以通過 ptrace() 系統(tǒng)調(diào)用發(fā)送,下面我們介紹一下怎么使用 ptrace() 系統(tǒng)調(diào)用來對(duì)被調(diào)試進(jìn)程進(jìn)行調(diào)試操作。

  • send_debug_command() 函數(shù)的實(shí)現(xiàn)有點(diǎn)小復(fù)雜,我們來分析下這個(gè)函數(shù)的主要執(zhí)行流程吧。

  1. 當(dāng)被調(diào)試進(jìn)程被內(nèi)核掛起時(shí),內(nèi)核會(huì)向其父進(jìn)程發(fā)送一個(gè) SIGCHLD 信號(hào),父進(jìn)程可以通過調(diào)用 wait() 系統(tǒng)調(diào)用來捕獲這個(gè)信息。

  2. 然后我們?cè)谝粋€(gè)循環(huán)內(nèi),跟蹤進(jìn)程執(zhí)行指令的過程。

  3. 通過調(diào)用 ptrace(PTRACE_GETREGS...) 來獲取當(dāng)前進(jìn)程所有寄存器的值。

  4. 通過調(diào)用 ptrace(PTRACE_PEEKTEXT...) 來獲取某個(gè)內(nèi)存地址的值。

  5. 通過調(diào)用 ptrace(PTRACE_SINGLESTEP...) 將被調(diào)試進(jìn)程設(shè)置為單步調(diào)試模式,這樣當(dāng)被調(diào)試進(jìn)程每執(zhí)行一條指令,都會(huì)進(jìn)入停止?fàn)顟B(tài)。

  • 整個(gè)調(diào)試流程可以歸納為以下的圖片:



測(cè)試程序

  • 最后,我們來測(cè)試一下這個(gè)簡(jiǎn)單的調(diào)試工具的效果。我們使用以下命令編譯程序:

編譯之后,我們會(huì)獲得一個(gè)名為 tdb 的可執(zhí)行文件。然后,我們可以使用以下命令來調(diào)試程序:

例如我們要調(diào)試 ls 命令這個(gè)程序,可以輸入以下命令:

  • 可見,運(yùn)行 ls 這個(gè)命令需要執(zhí)行 40 多萬條指令。




手把手教你寫一個(gè)GDB(基本功能~)的評(píng)論 (共 條)

分享到微博請(qǐng)遵守國家法律
富顺县| 彩票| 永定县| 广宗县| 罗田县| 华蓥市| 闻喜县| 新河县| 淮安市| 木里| 柳林县| 封丘县| 长顺县| 南投县| 石狮市| 额济纳旗| 平南县| 全南县| 凤翔县| 工布江达县| 民乐县| 昌吉市| 东莞市| 湖南省| 兴宁市| 犍为县| 丰镇市| 岳阳市| 清流县| 龙陵县| 长丰县| 文登市| 曲周县| 都匀市| 林口县| 虎林市| 蚌埠市| 云和县| 临西县| 九江县| 阿尔山市|