[Win32]一个调试器的实现(六)显示源代码
摘要:上一篇文章介绍了调试符号以及DbgHelp的加载和清理,这回我们使用它来实现一个显示源代码的功能。该功能的实际使用效果如下图所示:该功能不仅仅是显示源代码,还要显示每一行代码对应的地址。实现该功能大概需要进行以下的步骤:①获取下一条要执行的指令的地址。②通过调试符号获取该地址对应哪个源文件的哪一行。③对于其它的行,通过调试符号获取它对应的地址。第一步可以通过获取EIP寄存器的值来完成,相关的内容已经在第四篇文章中进行了讲解,这里不再重复。下面讲一下如何实现第二个和第三个步骤。获取源文件以及行号在调试符号中,记录了每一行源代码对应的地址。通过DbgHelp的SymGetLineFromAddr6
阅读全文
posted @
2011-03-27 21:32
Zplutor
阅读(9139)
推荐(2) 编辑
[Win32]一个调试器的实现(五)调试符号
摘要:一个调试器应该可以跟踪被调试程序执行到了什么地方,显示下一条将要执行的语句,显示各个变量的值,设置断点,进行单步执行等等,这些功能都需要一个基础设施的支持,那就是调试符号。什么是调试符号我们知道,在exe、dll等可执行文件中保存的数据大部分都是二进制指令,CPU直接读取这些指令并执行。那么调试器是如何知道每条指令对应哪个源文件的哪一行代码呢?它又是如何知道每个变量和函数的名称,并显示变量的值呢?很显然,可执行文件的二进制数据中不可能包含这么多信息,这一切都是由调试符号来支持的。所谓符号,简单来说就是源代码中每个对象的名称。例如变量、函数、类型等,它们都有一个名称,以及其它的相关信息:变量有类
阅读全文
posted @
2011-03-20 22:51
Zplutor
阅读(12780)
推荐(4) 编辑
[Win32]一个调试器的实现(四)读取寄存器和内存
摘要:在前几篇文章中,我实现的那个调试器只能被动接收调试事件并输出这些事件的信息。现在,我要将它修改成可以接收命令,并根据命令对被调试进程进行各种操作。首先从最基本的操作开始。获取寄存器的值每个线程都有一个上下文环境,它包含了有关线程的大部分信息,例如线程栈的地址,线程当前正在执行的指令地址等。上下文环境保存在寄存器中,系统进行线程调度的时候会发生上下文切换,实际上就是将一个线程的上下文环境保存到内存中,然后将另一个线程的上下文环境装入寄存器。获取某个线程的上下文环境需要使用GetThreadContext函数,该函数声明如下:1BOOLWINAPIGetThreadContext(2HANDLEh
阅读全文
posted @
2011-03-13 21:57
Zplutor
阅读(11498)
推荐(4) 编辑
[Win32]一个调试器的实现(三)异常
摘要:这回接着处理上一篇文章留下的问题:如何处理EXCEPTION_DEBUG_EVENT这类调试事件。这类调试事件是调试器与被调试进程进行交互的最主要手段,在后面的文章中你会看到调试器如何使用它完成断点、单步执行等操作。所以,关于这类调试事件的处理很自由,调试器的作者可以根据需要进行不同的处理。但是,在对其进行处理之前必须要了解一些关于异常的知识,这也是本文的重点。(本文的内容参考了《软件调试》一书)异常的分类根据异常发生时是否可以恢复执行,可以将异常分为三种类型,分别是错误异常,陷阱异常以及中止异常。错误异常和陷阱异常一般都可以修复,并且在修复后程序可以恢复执行。两者的不同之处在于,错误异常恢复
阅读全文
posted @
2011-03-08 22:39
Zplutor
阅读(18461)
推荐(3) 编辑
[Win32]一个调试器的实现(二)调试事件的处理
摘要:上一篇文章说到了调试循环的写法,这回讲一下调试器应该如何处理各种调试事件。RIP_EVENT关于这种调试事件的文档资料非常少,即使提到也只是用“系统错误”或者“内部错误”一笔带过。既然如此,我们也不需要对其进行什么处理,只要输出一条信息或者干脆忽略它即可。OUTPUT_DEBUG_STRING_EVENT当被调试进程调用OutputDebugString时就会引发该类调试事件,OUTPUT_DEBUG_STRING_INFO结构体描述了关于该事件的详细信息。在MSDN中,对该结构体各字段的解释是:lpDebugStringData字段是字符串在被调试进程的进程空间内的地址;nDebugStri
阅读全文
posted @
2011-03-06 21:47
Zplutor
阅读(9925)
推荐(2) 编辑
[Win32]一个调试器的实现(一)调试事件与调试循环
摘要:前言程序员离不开调试器,它可以动态显示程序的执行过程,对于解决程序问题有极大的帮助。如果你和我一样对调试器的工作原理很感兴趣,那么这一系列文章很适合你,这些文章记录了我开发一个调试器雏形的过程,希望对你有帮助。或许我写的代码很拙劣,还请大家多多见谅!这个调试器使用Visual Studio 2010作为开发工具,是一个控制台程序。为了简化,一切输入输出都使用C++标准库的相关类,而且省略了很多错误检查和处理的过程。启动被调试程序要想对一个程序进行调试,首先要做的当然是启动这个程序,这要使用CreateProcess这个Windows API来完成。例如,下面的代码以记事本作为被调试程序:1#i
阅读全文
posted @
2011-03-04 22:26
Zplutor
阅读(19238)
推荐(7) 编辑