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

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

深入浅出根据函数调用过程谈栈回溯原理

發(fā)布時(shí)間:2023/12/18 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 深入浅出根据函数调用过程谈栈回溯原理 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

?

???????????

? ? ? ? 通過(guò)分析函數(shù)調(diào)用過(guò)程的堆棧變化,可以看出在被調(diào)函數(shù)的EBP寄存器地址存放的是調(diào)用函數(shù)的EBP寄存器地址,EBP地址+4存放的是函數(shù)調(diào)用完成后的下一條指令存放地址,該指令的前一條指令則是調(diào)用函數(shù)的指令。說(shuō)起來(lái)有點(diǎn)拗口,接下來(lái)代碼分析一下:

? ? ? ? 分析使用的源碼如下:

[cpp] view plaincopyprint?
  • int?_cdecl?FunA(int?a,?int?b)??
  • {??
  • ????int?d;??
  • ????d?=?a?+?b;??
  • ????return?d;??
  • }??
  • ??
  • int?_cdecl?FunB(int?a,?int?b)??
  • {??
  • ????return?FunA(a,?b);??
  • }??
  • ??
  • int?_cdecl?FunC(int?a,?int?b)??
  • {??
  • ????return?FunB(a,?b);??
  • }??
  • ??
  • int?_cdecl?main(int?argc,?char*?argv[])??
  • {??
  • ????int?r;??
  • ????r?=?FunC(2,?3);??
  • ????return?0;??
  • }??
  • int _cdecl FunA(int a, int b) {int d;d = a + b;return d; }int _cdecl FunB(int a, int b) {return FunA(a, b); }int _cdecl FunC(int a, int b) {return FunB(a, b); }int _cdecl main(int argc, char* argv[]) {int r;r = FunC(2, 3);return 0; }

    在函數(shù)FunA內(nèi)的任意位置添加斷點(diǎn),然后執(zhí)行代碼,則會(huì)在該處停住,通過(guò)VS的cmd窗口分析步驟如下:

    1、? 查看寄存器值,得出EBP=0x002FF734

    2、? 根據(jù)該EBP,找到FuncA返回后的指令執(zhí)行地址0x0005142B

    3、? 因?yàn)镃ALL函數(shù)執(zhí)行的機(jī)器碼=call機(jī)器碼(1個(gè)字節(jié))+函數(shù)地址(4個(gè)字節(jié)),得出call funcA這條指令的執(zhí)行地址為0x00051426(0x0005142B-5)

    4、? 得出指令機(jī)器碼為e8 6b fc ff ff

    5、? 機(jī)器碼算出調(diào)用指令地址 0Xfffffc6B+5(五個(gè)字節(jié))+0x00051426(call指令地址)=0x00051096

    6、? 查看0x00051096地址得出機(jī)器碼 e9 25 0300 00,該機(jī)器碼顯示為jmp指令

    7、 ?再通過(guò)計(jì)算0x000325+5+0x0005196=0x000513c0最終得出調(diào)用函數(shù)的地址。

    在VS2008窗口中分析命令如下:


    通過(guò)實(shí)際查看FunA的函數(shù)入口位置如下所示:


    ? ? ? ? 通過(guò)以上分析可以得出FunA函數(shù)的調(diào)用地址,但是整個(gè)過(guò)程是沒(méi)辦法知道函數(shù)的名稱的,知道函數(shù)名稱需要使用.pdb(symbol文件:在編譯過(guò)程中生成的符號(hào)文件)。這邊就不分析了。

    ? ? ? ? 所以通過(guò)EBP加函數(shù)返回的指令地址可以一步一步的回溯整個(gè)過(guò)程的函數(shù)調(diào)用關(guān)系,也就是所謂的?;厮菰砹?。

    ? ? ? ? 好吧,原理歸原理,我們還是乖乖的命令窗口敲下>kb命令看看整個(gè)的函數(shù)調(diào)用過(guò)程吧。


    ? ? ? ? ?可以看出到后面VS也沒(méi)法知道整個(gè)系統(tǒng)的符號(hào)文件,只能給出一個(gè)地址。

    ? ? ? ? ?至此?;厮菰矸治鼋Y(jié)束,若有問(wèn)題,請(qǐng)幫忙指出,不勝感激。  創(chuàng)作挑戰(zhàn)賽新人創(chuàng)作獎(jiǎng)勵(lì)來(lái)咯,堅(jiān)持創(chuàng)作打卡瓜分現(xiàn)金大獎(jiǎng)

    總結(jié)

    以上是生活随笔為你收集整理的深入浅出根据函数调用过程谈栈回溯原理的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。