自己動手開發調試器 01

背景:
??? 在做XXX編譯器檢證時經常需要區分是代碼端錯誤,還是編譯器端錯誤,因此對代碼進行調試是必不可少的。但是狗日的甲方并沒有提供對應的調試器XXXDB,而用GDB調試XXX生成的可執行程序很不穩定,經常出現異常,干脆自己動手,寫mini調試器,順便學習一下開發一個調試器到底需要哪些知識。

目標:
??? GDB一共有十幾萬行代碼,95%的功能都用不上。三個最基本的功能:“單步”、“斷點”、“查看變量”即可滿足日常工作中的大部分需求。并且基于學習、分享的初衷,我盡量把代碼控制在千行左右,足夠簡單,足夠傻瓜,最關鍵的是,老夫沒那么時間啊。

預備知識:
??? 先簡單解釋下調試器的基本原理。
??? 假設調試器進程為A,被調試程序的進程為B. 如果要實現“單步”、“斷點” 和“查看變量”三種基本功能,那也就意味著A進程必須要擁有三種操控B進程的能力:
??? 1?? A可以暫停B進程的執行
??? 2?? A可以恢復B進程的執行
??? 3?? A可以在任意時刻查看B進程的內存及寄存器
??? 顯然,所謂“斷點”就是在某個特定“時刻”暫停B進程的執行;所謂“單步”就是先恢復B進程的執行“一小會兒”,然后立刻暫停;所謂watch變量,就是查看特定內存或者某個寄存器,不管啥變量都只能存在這倆地方。

??? 問題是,如果你是進程B,你不會覺得很不踏實么,居然有人可以這么樣將你玩弄在鼓掌之中,你在他面前根本就是完全透明,毫無秘密,任人蹂躪。很顯然,不應該有這么苦逼的事情發生。或者說,一個普通的用戶進程不可能僅通過什么絢爛的編程技巧來做到這一點,再或者說,這必須是操作系統提供的“能力”。

??? 認識到這一點很重要,也就是說如果是linux,那就應該是某些神奇的系統調用,如果是windows,那就應該是某些擁有又臭又長參數的API,如果你的操作系統沒提供這樣的接口,那你就不要想了(僅限于二進制代碼,基于虛擬機的,解釋器的不算)。 windows下的不知道也暫時不關心,linux下的就是“ptrace”,32位/64位都是它。 因為第一篇文章嘛,只是簡單解釋下,而且后面要說的還有很多,所以我就不詳細介紹了,關于ptrace的資料你可以參考

原版:

??? http://www.linuxjournal.com/article/6100
??? http://www.linuxjournal.com/node/6210/print
中文版:

  http://www.kgdb.info/gdb/playing_with_ptrace_part_i/

  http://www.kgdb.info/gdb/playing_with_ptrace_part_ii/


??? 但是有一個關鍵點需要仔細說明一下,進程A怎么通過ptrace讓進程B暫停? 這么說吧,首先進程A通過ptrace可以改寫B進程空間的任意地址的內容,當然也就能改寫B進程的機器指令,比如下面的超白癡C代碼

1 //test.c
2 int main()
3 {
4 return 0;
5 }


先編譯 gcc test.c -o test,然后用objdump -d test 反匯編下

1  0000000000400474 <main>:
2 400474: 55 push %rbp
3 400475: 48 89 e5 mov %rsp,%rbp
4 400478: b8 00 00 00 00 mov $0x0,%eax
5 40047d: c9 leaveq
6 40047e: c3 retq
7 40047f: 90 nop



main函數一共6條指令,
第一條在 0x400474處,1個字節,內容是"0x55", 意思是? push?? %rbp
第二條在 0x400475處,3個字節,內容是"0x48 0x89 0xe5", 意思是?? mov %rsp,%rbp
...省略...


如果我想B進程在第3行暫停,或者說在第3行設置一個斷點,那么在進程B運行到第3行之前,進程A通過ptrace修改進程B內存空間0x400478處, 將第一個字節(0xb8)修改成(0xcc),那么進程B運行到第三行自動就暫停了。為啥?因為0xcc就是INT 3 指令,先show一些官方文檔吧:

==============================================
Opcode Instruction Description
CC??? ? INT3?????????? Interrupt 3—trap to debugger
CD ib? INT imm8??? Interrupt vector numbered by immediate byte
CE??? ? INTO?????? ??? Interrupt 4—if overflow flag is 1

Intel? Itanium? Architecture Software Developer’s Manual
Volume 2: System Architecture
==============================================

==============================================
The INT 3 instruction generates a special one byte opcode (CC) that is
intended for calling the
debug exception handler. (This one byte form is valuable because it can
be used to replace the
first byte of any instruction with a breakpoint, including other one
byte instructions, without
over-writing other code).

Intel Architecture Software Developer’s Manual
Volume 2:Instruction Set Reference
================================================

看不懂沒關系,原理很簡單,0xcc就是“暫停”(Trap)指令,并且它只有一個字節。64位下的機器指令的長度不等,比如上面的6條指令就有1,3,5幾種,但是最小必須是1,也就是說INT 3是最短的一條指令,那它就能覆蓋到任意一條指令的最開始部分,比如,把它覆蓋到0x400478處,

第4行 400478:       b8 00 00 00 00          mov    $0x0,%eax

就變成了

第4行  400478:       cc 00 00 00 00          mov    $0x0,%eax 

?

除了第一個“操作符”變了,其他的“操作數”都沒變 ,當B進程執行到0x400478處時,它就會暫停,然后將控制權交給父進程,也就是A,然后A干完它想干的事情,比如查查寄存器,看看內存啥的,再把B的0x400478處改回來,于是又變成了

第4行  400478:       b8 00 00 00 00          mov    $0x0,%eax 

進程內存一點兒沒變,但是這時候指令寄存器(SP? IP? 反正好幾種叫法)已經指向下一條指令了,也就是b8后面的00,為啥?因為b8以前cc,單字節指令,執行過了,ip往前挪了一個字節,于是指向00了,所以A進程通過ptrace把指令寄存器-1,于是又指向了b8,一切如常,繼續執行。

ok,總結一下。
假設你想設置幾個斷點,那么首先確定好位置,比如0x400474, 0x400478,0x40047e,然后流程如下:
================================================
a 保存位置的第一個字節,然后修改位置的第一個字節為0xcc(INT 3)
b 繼續B進程
c B進程遇到斷點暫停,將控制權交還A進程
d A進程將斷點位置的第一個字節改回來,將指令寄存器-1,繼續B進程,轉入步驟b.
================================================


假設你想單步執行,在能設置斷點基礎上,流程如下:
================================================
a 將斷點設在下一條指令處,繼續B進程
b B進程遇到斷點暫停,轉入a步驟
================================================
瞧瞧,原來單步執行就是不停的在下一條指令前設斷點啊...


后記:
??? 在上面的內容中,我屏蔽了很多細節,比如:

?? 1 “下一條指令”,假設你在0x400475處

第3行  400475:       48 89 e5                mov    %rsp,%rbp
第4行 400478: b8 00 00 00 00 mov $0x0,%ea

?
顯然,下一條指令在0x400478處,也就是3個字節之后,問題是你怎么知道要去跳
過“3”個字節,為啥不是2個,不是1個?很顯然因為0x400475指令的內容“48
89 e5”告訴你這條指令有3個字節長。它怎么告訴你的?“48 89 e5”這6個字母
里面一個“3”都沒有。

? 2? “B進程將控制權交還給A”,B怎么就還給A了?B與A到底通過什么樣的方式
來交互?進程間交還還是線程間交互?

? 3?? 到目前為止,操作的都是機器碼,我能停在0x400475處有什么用?我需要的
是能停在 "int i = 0;"處。換句話說,如何建立機器碼與源代碼之間的關系。

實現:
??? 在參考文獻的鏈接中,提供了關于ptrace的C代碼示例。不過這種有歷史的東西,肯定有一大堆封裝好的庫。這里我用的python的封裝,python-ptrace。

??? python-ptrace本身提供了一個gdb.py,800行左右代碼。基本上局部了簡單的單線程匯編代碼調試能力。不過,我的目標是提供源代碼級的調試功能,而且還要限制在千行左右,gdb就有點大了,自己簡單寫搭了個框架,200行,先實現了匯編碼的單步執行,慢慢擴展。


當前要執行的匯編代碼,效果如下:
================================================
In [6]: run fdb.py ../test/test
fdb: step
fdb: command:step params:[]
fdb: a_step
Assembly:? 0x000000360ae00af0: MOV RDI, RSP
fdb: step
fdb: command:step params:[]
fdb: a_step
Assembly:? 0x000000360ae00af3: CALL 0x360ae01120
fdb: step
fdb: command:step params:[]
fdb: a_step
Assembly:? 0x000000360ae00af8: MOV R12, RAX
================================================

??? 具體源碼在附件,但是首先,它依賴一些第三方庫,其次它只支持64 位,linux,再次,它是python實現的,再次,我剛開了個頭。

cd /usr/tmp/luqi/python-ptrace-0.6.3
fdb.py ../test/test
fdb: step


??? 后面我會繼續解釋上面的一些細節,進一步補充理論,也會深入到具體代碼實現,作為一個開頭,這次的內容已經很多,歡迎有這方面經驗的兄弟一起交流,因為,其實我也有很多不明白的地方想要找高人請教。

參考文獻:
??? 互聯網上關于調試器的內容并不多,先貢獻一個精品
??? http://eli.thegreenplace.net/2011/01/23/how-debuggers-work-part-1/

??? http://eli.thegreenplace.net/2011/01/27/how-debuggers-work-part-2-breakpoints/

??? http://eli.thegreenplace.net/2011/02/07/how-debuggers-work-part-3-debugging-information/

?

附件地址:

http://files.cnblogs.com/quixotic/fdb.rar

轉載于:https://www.cnblogs.com/quixotic/archive/2012/01/16/2323541.html

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/275057.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/275057.shtml
英文地址,請注明出處:http://en.pswp.cn/news/275057.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

02如何抓住重點,系統高效地學習數據結構與算法?

以下內容總結自極客時間王爭大佬的《數據結構與算法之美》課程&#xff0c;本文章僅供個人學習總結。 什么是數據結構?什么是算法? 從廣義上講&#xff0c;數據結構就是指一組數據的存儲結構。算法就是操作數據的一組方法。 類比圖書館的書籍&#xff0c;我們如果想找一本書可…

第2年,倒數第3天,1.5萬票,感動!

1源碼共讀大家好&#xff0c;我是若川。眾所周知。從8月份開始&#xff0c;我組織了源碼共讀活動&#xff0c;至今已經有5個月了&#xff0c;每周一期&#xff0c;進行到了第18期。每周堅持寫源碼解讀文章&#xff0c;每天堅持答疑解惑&#xff0c;幫助了很多人學會看源碼&…

啟發式搜索給神經網絡_神經科學如何支持UX啟發式

啟發式搜索給神經網絡重點 (Top highlight)Interaction and UX designers have long known and used heuristics to guide the creation of a user-friendly interface. We know empirically that these principles work, and they make “common sense”. These heuristics th…

Django實戰(1):需求分析和設計

Depot是《Agile Web Development with Rails》中的一個購物車應用。 該書中用多次迭代的方法&#xff0c;逐步實現購物車應用&#xff0c;使很多人走上了rails開發的道路。 遺憾的是Django世界中好像沒有類似的指引&#xff0c;也許是因為pythoner 不需要具體的例子。 但是如果…

使用 apiDoc 為你的Node.js API 生成文檔

翻譯&#xff1a; 瘋狂的技術宅 原文&#xff1a;jonathas.com/documenting… 未經許可&#xff0c;禁止轉載&#xff01; 當你為其他開發人員&#xff08;前端&#xff0c;桌面&#xff0c;移動等&#xff09;開發 API 時&#xff0c;需要生成一份風格良好的文檔&#xff0c;以…

海浪 shader_海浪下的發現

海浪 shaderI’ve been playing Subnautica for over 25 hours now, and likely have at least that many more to go. The game puts you in the shoes of a crew member on the Aurora, a spaceship that suffers a catastrophic incident and plummets to the largely ocean…

最后一天,特邀小姐姐配音拉票,今日可投28票

1源碼共讀大家好&#xff0c;我是若川。最后一天&#xff0c;特邀小姐姐配音拉票&#xff0c;超級好聽。眾所周知。從8月份開始&#xff0c;我組織了源碼共讀活動&#xff0c;至今已經有5個月了&#xff0c;每周一期&#xff0c;進行到了第18期。每周堅持寫源碼解讀文章&#x…

NET中使用Memcached的相關資源整理

本文轉自&#xff1a;http://www.cnblogs.com/dudu/archive/2009/07/19/1526407.html Memcached官方站點&#xff1a;http://www.danga.com/memcached / Memcached Win32 1.2.6下載&#xff1a;http://code.jellycan.com/memcached/ 安裝幫助&#xff1a;Windows下的.NET Memca…

FFMPEG 視頻圖像解封裝解碼

FFMPEG4.0 音頻解碼解封裝FFMPEG 音頻封裝編碼 下面的函數方法基于最新的FFMPEG 4.0&#xff08;4.X&#xff09;&#xff1a;本文講是如何從一個視頻文件中提取出其中的圖像數據&#xff0c;并將圖像數據保存到文件中。 解碼解封裝的過程與音頻差不多&#xff0c;具體如下&…

對數據可視化的理解_使數據可視化更容易理解

對數據可視化的理解Data is weaving its way into almost all aspects of our lives since the past decade. Our ability to store more information in smaller and smaller spaces has encouraged us to make sure we leave no information out. The ease of collecting inf…

面試官:項目中常用的 .env 文件原理是什么?如何實現?

1. 前言大家好&#xff0c;我是若川。持續組織了5個月源碼共讀活動&#xff0c;感興趣的可以點此加我微信 ruochuan12 參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。本文倉庫 h…

語言分類,我接觸和我想學習的

本文信息和數據出自hyperpolyglot&#xff0c;將當前主流編程語言分為11個大類&#xff0c;分別為&#xff1a;解釋型(PHP,Perl,Python,Ruby,Tcl,Lua,JavaScript,Io)、操作系統自動化型(POSIX Shell,AppleScript,PowerShell)、C風格(C,Objective C,Java,C#)、Pascal風格(Pascal…

梯度下降法和隨機梯度下降法

1. 梯度 在微積分里面&#xff0c;對多元函數的參數求?偏導數&#xff0c;把求得的各個參數的偏導數以向量的形式寫出來&#xff0c;就是梯度。比如函數f(x,y), 分別對x,y求偏導數&#xff0c;求得的梯度向量就是(?f/?x, ?f/?y)T,簡稱grad f(x,y)或者▽f(x,y)。對于在點(x…

一張圖看程序媛阿源的2021個人年度流水賬

大家好&#xff0c;我是若川。持續組織了5個月源碼共讀活動&#xff0c;感興趣的可以點此加我微信 ruochuan12 參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。本文來自讀者阿源小…

案例研究:設計與方法_如何進行1小時的重新設計(案例研究)

案例研究:設計與方法速度設計簡介 (Intro to Speed Designing) I’ve been an advocate of speed redesigning technique for a while. The idea is simple — decrease the hand-eye lag and make super quick decisions, seemingly without thinking. The logic behind it is…

圖文并茂重新認識下遞歸

大家好&#xff0c;我是若川。持續組織了5個月源碼共讀活動&#xff0c;感興趣的可以點此加我微信 ruochuan12 參與&#xff0c;每周大家一起學習200行左右的源碼&#xff0c;共同進步。同時極力推薦訂閱我寫的《學習源碼整體架構系列》 包含20余篇源碼文章。對于大部分前端(包…

《C和指針》讀書筆記

看過了經典的K&R C&#xff0c;又看了這本Pointers on C&#xff0c;溫習了C語言的基本語法。 在重溫過程中&#xff0c;感覺需要重點把握的知識是指針、結構和動態內存分配。 這對今后的算法和操作系統方面的研究學習很有幫助。 3.2.3 聲明指針int* b, c, d;本以為這條語句…

FPGA設計者的5項基本功

記得《佟林傳》里&#xff0c;佟林練的基本功是“繞大樹、解皮繩”&#xff0c;然后才練成了什么“鬼影隨行、柳葉綿絲掌”。 在我看來&#xff0c;成為一名說得過去的FPGA設計者&#xff0c;需要練好5項基本功&#xff1a;仿真、綜合、時序分析、調試、驗證。 需要強調的一點是…

unity 全息交互ui_UI向3D投影全息界面的連續發展

unity 全息交互uiThe user interface has been natural in its evolution and strategically heading towards the 3D-projection holographic interface (3D-PHI) era.用戶界面在其發展過程中一直很自然&#xff0c;并且在戰略上正朝著3D投影全息界面( 3D-PHI )時代邁進。 Si…

開發工具 快捷鍵整理

快捷鍵大全 JAVA 開發工具 MyEclipse -------------------------------------MyEclipse 快捷鍵1(CTRL)-------------------------------------Ctrl1 快速修復CtrlD: 刪除當前行 CtrlQ 定位到最后編輯的地方 CtrlL 定位在某行 CtrlO 快速顯示 OutLine CtrlT 快速顯示當前類…