日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[Win32]一个调试器的实现(六)显示源代码

發布時間:2025/7/14 编程问答 26 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [Win32]一个调试器的实现(六)显示源代码 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

上一篇文章介紹了調試符號以及DbgHelp的加載和清理,這回我們使用它來實現一個顯示源代碼的功能。該功能的實際使用效果如下圖所示:

該功能不僅僅是顯示源代碼,還要顯示每一行代碼對應的地址。實現該功能大概需要進行以下的步驟:

①獲取下一條要執行的指令的地址。

②通過調試符號獲取該地址對應哪個源文件的哪一行。

③對于其它的行,通過調試符號獲取它對應的地址。

?

第一步可以通過獲取EIP寄存器的值來完成,相關的內容已經在第四篇文章中進行了講解,這里不再重復。下面講一下如何實現第二個和第三個步驟。

?

獲取源文件以及行號

在調試符號中,記錄了每一行源代碼對應的地址。通過DbgHelpSymGetLineFromAddr64函數可以由地址獲取源文件路徑以及行號。該函數的聲明如下:

1?BOOL?WINAPI?SymGetLineFromAddr64(
2?????HANDLE?hProcess,
3?????DWORD64?dwAddr,
4?????PDWORD?pdwDisplacement,
5?????PIMAGEHLP_LINE64?Line
6?);

hProcess參數是符號處理器的標識符,dwAddr是指令的地址。pdwDisplacement是一個輸出參數,用于獲取dwAddr相對于它所在行的起始地址的偏移量,以字節為單位。之所以需要這么一個參數,是因為一行代碼可能對應多條匯編指令,有了它就可以知道下一條要執行的指令位于這一行代碼的哪個位置。例如,int b = 3 * a + a;這行代碼對應以下的匯編指令:

1?8B?45?F8????mov????eax,dword?ptr?[a]?
2?6B?C0?03????imul???eax,eax,3?
3?03?45?F8????add????eax,dword?ptr?[a]?
4?89?45?EC????mov????dword?ptr?[b],eax?

如果分別以這四條指令的地址調用SymGetLineFromAddr64函數,那么通過pdwDisplacement返回的值分別是0369

?

第四個參數是指向IMAGEHLP_LINE64結構體的指針,該結構體用來保存有關于行的信息,其聲明如下:

1?typedef?struct?_IMAGEHLP_LINE64?{
2?????DWORD?SizeOfStruct;
3?????PVOID?Key;
4?????DWORD?LineNumber;
5?????PTSTR?FileName;
6?????DWORD64?Address;
7?}?IMAGEHLP_LINE64,?*PIMAGEHLP_LINE64;

SizeOfStruct字段保存結構體的大小,在調用SymGetLineFromAddr64之前需要初始化這個字段,否則函數調用會失敗。Key字段是由操作系統保留的,我們不需要使用它。FileNameLineNumber字段分別是源文件的絕對路徑以及行號。Address是該行的起始地址。

?

要注意,FileName字段是一個指向字符串的指針,而這個字符串的存儲空間并不需要我們自己分配,我們也不需要釋放這個指針指向的內存。實際上這個指針指向了調試符號內的某個地方,我們可以讀取這些數據,但是不能修改其中的數據,一旦這些數據被修改,其它的DbgHelp函數可能會出現奇怪的問題。如果一定要修改這個字符串,要先將它復制到另一個地方再進行操作。我很奇怪為什么這個字段不是PCTSTR類型的,這樣的話就不必擔心這個字符串被修改了。

?

調用SymGetLineFromAddr64成功的條件有兩個:一是dwAddr的值所在的模塊已經通過SymLoadModule64函數加載到符號處理器中;二是該模塊含有SymGetLineFromAddr64所需的調試符號信息。如果第一個條件沒有滿足,GetLastError返回126;如果第二個條件沒有滿足,GetLastError返回487

?

下面是調用SymGetLineFromAddr64的一個例子:

?1?//獲取EIP
?2?CONTEXT?context;
?3?GetDebuggeeContext(&context);
?4?
?5?//獲取源文件以及行信息
?6?IMAGEHLP_LINE64?lineInfo?=?{?0?};
?7?lineInfo.SizeOfStruct?=?sizeof(lineInfo);
?8?DWORD?displacement?=?0;
?9?
10?if?(SymGetLineFromAddr64(
11?????GetDebuggeeHandle(),
12?????context.Eip,
13?????&displacement,
14?????&lineInfo)?==?FALSE)?{
15?
16?????DWORD?errorCode?=?GetLastError();
17?????????
18?????switch?(errorCode)?{
19?
20?????????//?126?表示還沒有通過SymLoadModule64加載模塊信息
21?????????case?126:
22?????????????std::wcout?<<?TEXT("Debug?info?in?current?module?has?not?loaded.")?<<?std::endl;
23?????????????return;
24?
25?????????//?487?表示模塊沒有調試符號
26?????????case?487:
27?????????????std::wcout?<<?TEXT("No?debug?info?in?current?module.")?<<?std::endl;
28?????????????return;
29?
30?????????default:
31?????????????std::wcout?<<?TEXT("SymGetLineFromAddr64?failed:?")?<<?errorCode?<<?std::endl;
32?????????????return;
33?????}
34?}

?

獲取行的地址

通過SymGetLineFromAddr64可以獲取指令對應的源文件以及行號,那么能不能根據源文件路徑以及行號獲取行的地址呢?當然可以,SymGetLineFromName64函數就是用作此目的的。該函數的聲明如下:

1?BOOL?WINAPI?SymGetLineFromName64(
2?????HANDLE?hProcess,
3?????PCTSTR?ModuleName,
4?????PCTSTR?FileName,
5?????DWORD?dwLineNumber,
6?????PLONG?lpDisplacement,
7?????PIMAGEHLP_LINE64?Line
8?);

該函數與SymGetLineFromAddr64很相似,都是通過IMAGEHLP_LINE64結構體來返回行的信息,并且都有一個displacement輸出參數,不過這個參數在兩個函數中的意義大不相同,下面將會詳述。首先來看一下其它參數的含義。

?

ModuleName用于指定模塊的名稱,上一篇文章講解SymLoadModule64函數時提到的ModuleName參數就可以用在這個地方(奇怪的是SymLoadModule64ModuleName參數是PCSTR類型,而SymGetLineFromName64ModuleName參數卻是PCTSTR類型)。當FileName參數只指定了文件名,而多個模塊中含有同名的源文件時,SymGetLineFromName64就使用這個參數確定使用哪個模塊的源文件。如果各個模塊都沒有同名的源文件,或者FileName指定的是絕對路徑時,這個參數就沒有必要了,指定為NULL即可。

?

FileNamedwLineNumber 參數分別指定源文件和行號。FileName可以是文件名,也可以是絕對路徑,正如上面的描述那樣。dwLineNumber是任意非零值,即使行號在源文件中不存在,甚至是負數,SymGetLineFromName64也會返回TRUE!那么我們如何知道指定的行號是否有效呢?只要檢查displacement的值即可。大多數情況下,displacement表示指定行與最接近該行的有效行的行號之差,而且有效行的行號要小于等于指定行的行號。可以用下面的式子表示(式中的變量均使用函數參數的名字):

*lpDisplacement?=?dwLine?-?Line->LineNumber??(dwLine?>=?Line->LineNumber)

所謂有效行即能夠產生匯編指令的行(能產生匯編指令才會有對應的地址),例如int a = 1 + 1;是有效行,而int a;和空白行則不屬于有效行。用以下的代碼為例進行說明:

?1?int?wmain(int?argc,?wchar_t**?argv)?{
?2?
?3?????int?a?=?1?+?1;
?4?
?5?
?6?
?7?????int?b?=?2?+?2;
?8?
?9?????return?0;
10?}

dwLine = 2時,Line->LineNumber = 1*lpDisplacement = 1

dwLine = 4, 5, 6時,Line->LineNumber = 3*lpDisplacement = 1, 2 , 3

dwLine = 7時,Line->LineNumber = 7*lpDisplacement = 0

dwLine = 12時,Line->LineNumber = 10*lpDisplacement = 2

?

由第四個例子可以看出,如果指定的行號大于源文件的行數,則函數返回最后一行有效行的信息,displacement為指定行號與該有效行行號的差,同樣符合上面的式子。

?

如果dwLine0,那么SymGetLineFromName64返回FALSEGetLastError返回1168。奇怪的是,dwLine為負數竟然也可以調用成功,此時函數返回最后一行有效行的信息,displacementINT_MAX + dwLine

?

綜上所述,要判斷指定的行是否為有效行,只要檢查displacement是否為0即可。

?

示例代碼

好了,知道了如何獲取行號以及行的地址之后就可以實現顯示源代碼的功能了,詳細的方法請參考示例代碼。使用這個功能時要注意源文件必須與被調試程序和調試符號同步,如果修改了源代碼而沒有重新編譯鏈接的話,顯示的代碼肯定是錯誤的。

?

現在MiniDebugger中增加了一個命令:

?

l [after] [before]

顯示當前正在執行的那一行以及附近的代碼。after指定顯示當前那一行代碼的后面多少行,before指定顯示當前那一行代碼的前面多少行。如果省略的話,默認取值為10

?

如果在執行s命令啟動了被調試進程之后立即執行l命令,會得到“SymGetLineFromAddr64 failed: 6”的錯誤信息,這是因為此時還沒有創建符號處理器。要至少執行一次g命令之后才可以使用l命令。

?

http://files.cnblogs.com/zplutor/MiniDebugger6.rar

轉載于:https://www.cnblogs.com/zplutor/archive/2011/03/27/1997198.html

總結

以上是生活随笔為你收集整理的[Win32]一个调试器的实现(六)显示源代码的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

主站蜘蛛池模板: 在线视频综合网 | 九月婷婷| 狗爬女子的视频 | 一本久道久久综合无码中文 | 亚洲狠狠爱 | 专干老肥女人88av | 激情丁香六月 | 亚洲一区影视 | 欧洲女性下面有没有毛发 | 中文字幕校园春色 | 69性视频 | 国产又粗又猛又黄又爽无遮挡 | 成人久久18免费网站图片 | 污污的网站在线观看 | 国产福利在线视频 | 国产suv精品一区二区 | 嫩草视频入口 | 九月婷婷色 | 丁香婷婷久久久综合精品国产 | 永久免费未网 | 日本精品免费一区二区三区 | 色婷婷一区二区三区四区 | 久久精品人人 | 日韩新片王网 | 一级黄色免费观看 | 午夜家庭影院 | 91插插影库 | 久久人人爽人人爽人人片av免费 | 美国黄色片网站 | 综合网激情 | 国产成人自拍偷拍 | 永久免费汤不热视频 | 中文字幕一区二区三区乱码 | 亚洲免费毛片 | 超碰p | 四虎永久在线观看 | 黑人一区| 四川丰满妇女毛片四川话 | 毛片在线免费播放 | 国产99久久久久 | 亚洲欧美精品一区二区三区 | 午夜av网 | 免费视频91 | 国产在线不卡 | 亚洲最新偷拍 | 欧美精品啪啪 | 中文字幕av影视 | 欧美三p | 无码人妻久久一区二区三区 | www.youjizz.com国产| 日本女人一区二区三区 | 午夜激情网站 | 碰碰色| 色资源网站 | 欧美男人亚洲天堂 | 99爱爱视频 | 国产一区二区三区视频免费观看 | 欧美国产综合视频 | 肥臀熟女一区二区三区 | 青青av在线 | 国产日韩精品suv | 日韩免费在线看 | 亚洲成a人在线观看 | 亚洲欧美日韩图片 | 放几个免费的毛片出来看 | 天堂网久久 | av一区二区不卡 | 伊人成人动漫 | 久啪视频| 亚洲女同二女同志 | 九九天堂 | 网站国产| 国产一区日韩精品 | 日本黄色生活片 | 国产91在线 | 亚洲 | 久久亚洲精品视频 | 性色生活片 | 亚洲国产精品毛片av不卡在线 | 粉嫩av一区二区三区四区五区 | 一区二区精彩视频 | 午夜激情男女 | 成人传媒| 国产免费黄色网址 | 欧美成人精品在线 | 日操夜操天天操 | 最近2019中文字幕大全第二页 | 99ri在线 | 国产拍拍拍拍拍拍拍拍拍拍拍拍拍 | 小珊的性放荡羞辱日记 | 一道本在线播放 | 欧美国产三级 | 偷偷操不一样的99 | 亚洲自拍激情 | 午夜视频在线观看国产 | 久久影院午夜 | 操你妹影院 | 欧美日韩一区二区在线观看视频 | 日韩欧美一区二区视频 | 香蕉网站在线 |