• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            一直比較好奇,調(diào)試器是如何生成堆棧的調(diào)用過程的,比如如下代碼:
            int add(int a, int b)
            {
                return a + b;
            }

            int main()
            {
                int c = add(1, 2);
                system("pause");

                return 0;
            }

            調(diào)用Add時(shí)的堆棧截圖如下:


            調(diào)試器究竟是如何生成這個(gè)堆棧過程的呢?

            我最初的理解調(diào)試器是根據(jù)EBP來生成該堆棧的,原理如下:

            可以看到按照上面的原理, 每次EBP里存放的都是當(dāng)前函數(shù)的堆棧楨基址,所以我們只要一直遞推,就可以得到完整的Call Stack.

            但是我們很快會(huì)發(fā)現(xiàn), 并不是每個(gè)函數(shù)都是以
            push ebp   
            mov ebp, esp
            開頭的,我們可以寫一些裸(naked)函數(shù),
            比如int __declspec(naked) add(int x,int y) 來手動(dòng)控制函數(shù)頭,
            而且很多編譯器優(yōu)化過的函數(shù)代碼也是沒有該標(biāo)準(zhǔn)函數(shù)頭的。

            那么調(diào)試器在這種情況下又是如何生成完整的call stack的呢?

            和群里的朋友討論的結(jié)果是調(diào)試器很可能是在調(diào)用call指令時(shí)保存了調(diào)用現(xiàn)場(chǎng),
            這樣只要在調(diào)試器下運(yùn)行,它就一直可以知道正確而完整的call stack.

            這也解釋了為什么我們?cè)诜治鯟rash的Dump文件時(shí)很多時(shí)候得不到正確的堆棧過程?
            有可能是堆棧本身被我們的異常代碼破壞了;
            更有可能是因?yàn)槲覀兊拇a在直接運(yùn)行時(shí)沒有調(diào)試器的參與, 所以堆棧過程沒有被保存,所以windbg分析dump時(shí)只能根據(jù)堆棧里內(nèi)容自己分析和推理堆棧調(diào)用過程,所以很多時(shí)候得不到正確的堆棧過程。

            那么Windbg分析dump時(shí),會(huì)如何倒推堆棧過程呢?

            如果每個(gè)函數(shù)都是有標(biāo)準(zhǔn)的push ebp, 那么按照ebp遞推就可以了;
            否這就只能用其他方法分析,比如看看堆棧里某個(gè)地址是不是函數(shù)返回地址(該地址屬于某個(gè)模塊的代碼段),這樣就可以確定該地址是某個(gè)函數(shù)堆棧楨的起始地址。

            上面關(guān)于生成call stack的原理只是一些非專業(yè)人士的個(gè)人看法,如果有不正確的地方,歡迎指正。

            注: 和開發(fā)過調(diào)試器的朋友討論,上面 關(guān)于callstack產(chǎn)生原理的推論,實(shí)際上是不正確的, 調(diào)試器實(shí)際上是通過查詢PDB文件的方式獲取的callstack.
            posted on 2012-07-20 14:00 Richard Wei 閱讀(5362) 評(píng)論(3)  編輯 收藏 引用 所屬分類: 匯編

            FeedBack:
            # re: 堆棧楨的生成原理
            2012-07-20 15:31 | Richard Wei
            據(jù)寫過調(diào)試器的朋友指點(diǎn),調(diào)試器會(huì)盡量減少代碼運(yùn)行時(shí)的干預(yù),所以上面關(guān)于函數(shù)調(diào)用時(shí)調(diào)試器保存調(diào)用現(xiàn)場(chǎng)的猜測(cè),應(yīng)該是不正確的。
            調(diào)試器更多的可能是根據(jù)PDB文件信息來計(jì)算推理的,如果沒有PDB文件,它就只能猜測(cè),很多堆棧信息就會(huì)出錯(cuò)了。

            據(jù)說<<軟件調(diào)試>>里有相關(guān)介紹,回頭看下, 希望這篇博文不要誤導(dǎo)他人。  回復(fù)  更多評(píng)論
              
            # re: 堆棧楨的生成原理[未登錄]
            2012-07-20 21:19 | Korall
            “和群里的朋友討論的結(jié)果是調(diào)試器很可能是在調(diào)用call指令時(shí)保存了調(diào)用現(xiàn)場(chǎng),
            這樣只要在調(diào)試器下運(yùn)行,它就一直可以知道正確而完整的call stack.”

            猜測(cè)確實(shí)不太符合實(shí)際;我還沒有見過哪一款調(diào)試器是這樣實(shí)現(xiàn)的,虛擬機(jī)除外。
            就算是在調(diào)試器下運(yùn)行,不設(shè)置“堆棧幀”的函數(shù)調(diào)試器也是無法知道正確而完整的 call stack 的。  回復(fù)  更多評(píng)論
              
            # re: 堆棧楨的生成原理
            2012-07-21 00:14 | fzy
            call 會(huì)push下一條指令的地址到堆棧。
            可能是根據(jù)這個(gè)來進(jìn)行堆棧幀的檢測(cè)。
              回復(fù)  更多評(píng)論
              
            久久99精品国产麻豆不卡| 人妻无码αv中文字幕久久琪琪布| 无码伊人66久久大杳蕉网站谷歌| 7777精品伊人久久久大香线蕉| 亚洲愉拍99热成人精品热久久| 99久久婷婷国产综合亚洲| 久久综合久久综合久久| 亚洲欧洲精品成人久久曰影片| 久久久久久久亚洲Av无码| 99久久免费国产精品| AV无码久久久久不卡蜜桃| 99久久国产免费福利| 亚洲人成精品久久久久| 狠狠色丁香婷婷综合久久来来去| 久久精品国产99久久久古代| 好久久免费视频高清| 久久婷婷五月综合成人D啪| 18岁日韩内射颜射午夜久久成人 | 久久精品国产精品国产精品污| 久久亚洲国产精品五月天婷| 久久99精品久久久久子伦| 一97日本道伊人久久综合影院| 国产亚洲精品美女久久久| 亚洲人成无码久久电影网站| 国产精品久久久久久久午夜片| 久久综合狠狠综合久久| 久久久久久精品成人免费图片| 久久精品国产只有精品66| 国产美女久久久| 69久久夜色精品国产69| 久久久噜噜噜www成人网| 久久人人爽人人爽人人片AV东京热| 久久国产精品免费一区二区三区| 久久亚洲私人国产精品vA | 91久久婷婷国产综合精品青草| 色诱久久久久综合网ywww| 国产精品亚洲美女久久久| 久久免费小视频| 国内精品久久久久久久coent| 久久精品中文字幕久久| 国产三级久久久精品麻豆三级|