五月天青色头像情侣网名,国产亚洲av片在线观看18女人,黑人巨茎大战俄罗斯美女,扒下她的小内裤打屁股

歡迎光臨散文網(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)遵守國家法律
镇坪县| 福泉市| 凤台县| 来安县| 抚顺县| 龙陵县| 泊头市| 沂南县| 旬邑县| 铜鼓县| 凤凰县| 北碚区| 聂拉木县| 枞阳县| 嘉禾县| 普陀区| 永城市| 老河口市| 隆安县| 大埔县| 文水县| 东光县| 富顺县| 双桥区| 望城县| 永城市| 乌什县| 台江县| 湖南省| 怀仁县| 沙雅县| 湖州市| 霍州市| 塔城市| 确山县| 溧水县| 大厂| 沾化县| 原平市| 阜康市| 鲁山县|