- 作者:zhaozj
- 发表时间:2020-12-23 11:00
- 来源:未知
用汇编语句定位程序异常 (作者:彭春华,胡松 2000年08月01日 17:14) 概述 本文提出一种用汇编语言快速定位导致程序异常终了的代码,以加快异常系Bug的调查修改速度的方法。 前言 在程序的调试过程中,经常遇到程序的异常终了。在程序运行一些操作后,Windows弹出一个异常终了的信息框之后就关闭了该程序。 图1-1 遇到这种问题是每个程序员的不幸,因为这种异常终了的Bug再现性差,操作步骤不明。谁也说不清什么样的操作,什么样的环境下可以重现这个错误。编程调试人员不得不一次又一次地运行程序,希望能找到产生该错误的步骤和发生该错误的代码。另外,如果只有Release版才发生,Debug版不发生时,就更加麻烦了。程序员只能不停的在程序中加入log纪录,希望能发现错误的程序代码。 如果有方法能知道错误代码的位置,也就是说,知道源代码的哪一行导致该异常信息框弹出时,这个问题就解决了一半了。 那么,根据该信息框,如何定位该指令在EXE/DLL文件中的位置呢?知道了位置又如何得到产生该指令的源代码呢? 本文就如何加快定位异常代码的位置,提出用汇编语言快速定位的一种方法。 原理 一. Windows文件的结构 在了解该方法之前,首先了解一下Windows文件的基本知识。 对于Windows 32位的EXE和DLL而言(PE文件),在文件的头部,维护着执行文件的一些信息(节Section)。对于一个可执行的代码而言,.text节是不可少的。通过quickview就可以看到,在Image Optional Header中的Image Base和Section Table的.text节中的Virtual Address,Point to Raw Data 。对于EXE而言一般是Image Base = 0x00400000,Virtual Address= 0x00001000。对于DLL而言为Image Base = 0x10000000,Virtual Address= 0x00001000。其中Point to Raw Data则因DLL的不同而不同。实际值也可以通过quickview得到。 这几个参数的意义是: Image Base:程序运行时基址。EXE一般为0X00400000,DLL为0x10000000。该值为程序运行时载入内存时的优先地址。EXE值一般不变,DLL则有可能载入地址和基址不一致。这是因为有多个DLL时,在0x10000000上只能有一个DLL,其他的DLL则被载入别的地址。 Virtual Address:程序载入内存时.text节的相对地址。 Point to Raw Data:文件中.text节的地址 这3个参数的关系为: 内存中的位置 - EXE/DLL的载入地址 - Virtual Address+ Point to Raw Data = 该指令在EXE/DLL文件中的位置。 如 图1-1中的0x00401010处的指令出现异常,该指令在文件中的位置为: 通过Proc List.exe工具,可以看到该EXE载入内存时 载入地址= 0x00400000 通过quickview可以看到,该EXE的其他参数为: Virtual Address = 0x00001000 Point to Raw Data = 0x00001000 那么可以计算出该代码在文件中的位置为: 0x00401010 - 0x00400000 - 0x00001000 + 0x00001000 = 0x00001010 对dll而言,处理方法基本相同。 注:上述计算工作在ProcList.exe中已经实现。运用时只需输入异常终了的地址,即可得出异常代码在文件中的地址。