Debugger Engine Overview

一、调试会话与执行模型

调试引擎可以调试多个目标。一个调试会话开始于引擎接受一个目标,一直到所有目标丢弃结束。一个调试会话在目标运行期间不可访问,在当前目标挂起后可访问。在会话可访问期间引擎只能被用于测试和操作目标。
一个调试器的主循环通常由设置运行状态,调用WaitForEvent方法和处理产生的事件组成。当WaitForEvent被调用,会话变成不可访问。
当目标中产生一个事件,引擎挂起所有目标,会话变成可访问。引擎通知事件的回调函数并遵循事件过滤器规则。事件回调函数和事件过滤器决定目标的执行应该怎样继续。如果他们决定引擎应该中断调试器,那么WaitForEvent方法便返回,会话保持可访问;否则,引擎将继续目标的执行过程按照被事件回调函数和事件过滤器规定的方式,同时会话又变得不可访问。
在WaitForEvent调用——特别是当通知事件回调函数,处理过滤规则期间,引擎处于一种号称为“在等待中“的状态。当处于此状态中时WaitForEvent不能被调用。
在一个目标中启动执行流程分两步:设置执行状态,然后调用WaitForEvent。执行状态可以被 SetExecutionStatus方法设定或者通过运行一条调试器命令来设置运行状态比如说,g(Go)和p(Step)。
二、客户端对象(可理解为面向对象的对象,一个客户端对象是调试器会话的一个实例)
几乎所有与调试器引擎的交互都是通过客户端对象,常简称为客户。每个客户提供某个顶层引擎接口的实现。每个接口提供不同系列的方法,他们可以被用于与引擎互动。一个引擎实例可以有很多客户,每个有它们自己的状态。(类和对象的概念,接口便是类,客户便是该类的一个对象)
1、主要客户
主要客户就是那些已经参与当前调试会话的客户。最初,当一个新客户对象被创建,它不是一个主要客户。一个客户当被用于接受一个目标(举例来说通过调用CreateProcess2)或通过调用ConnectSession被连接到一个调试会话时会变成主要对象。调试器命令.clients只列出主要客户机。
2、回调对象
回调对象可被与每一个客户注册。有三种回调对象类型:
(1)输入回调对象:引擎调用输入回调来请求输入。举例,带控制台的调试器可注册一个输入回调来给引擎提供来自用户的输入,或者调试器可以注册一个输入回调给引擎提供来自一个文件的输入。
(2)输出回调对象:
引擎调用输出回调来显示输出。举例来说,带控制台窗口的调试器可以注册一个输出回调来呈现调试器的输出给用户,或者调试器也可以注册一个输出回调将输出发送一个日志文件。
(3)事件回调对象:
每当目标中一个事件产生(或引擎的状态发生改变)引擎便调用事件回调。举例来说,调试器扩展库可以注册一个事件回调来监控某事件或当一特殊事件发生时执行自动操作。
3、远程调试
4、额外信息
有关创建和使用客户端对象,请参阅使用回调对象。有关注册回调对象的详细信息,请参阅使用回调对象。
三、输入和输出
调试器引擎保持一个输入流和输出流。输入可以被从输入流中申请,输出可发送给输出流。
当Input方法被调用要求从引擎的输入流输入时,引擎会调用所有已注册的输入回调来通知这里正等待输入。然后它通过调用ReturnInput方法等待输入回调来提供输入。
当输出发送到引擎的输出流,引擎会调用已注册的输出回调给它们传送输出。当正传送输出给输出流时,可以被客户对象过滤;在这种情况下,只有被注册给特殊客户机对象的输出回调才能接收到输出。
四、远程调试

五、目标
调试器可调试不同类型的目标,用户模式和内核模式目标,活跃目标和崩溃转储文件,还有本地和远程目标。对于这些不同类型的目标有不同连接到引擎的方法。
1、崩溃转储文件
不管是用户模式还是内核模式的崩溃转储文件都用OpenDumpFile打开。引擎也可以用WriteDumpFile2从一个目标中创建转储文件。
2、活跃,用户模式目标
调试器可以打开和附加到用户模式进程。
创建进程通过提供一个命令行,新进程的可选初始目录和环境来完成。引擎可以连接到新进程或让新进程暂停,而它连接到其他进程。举例来说,当调试一个由客户端和服务端构成的程序,引擎可以在一个挂起的状态创建一个客户端并附加到一个已在运行的服务端,在客户端运行并引发服务端操作前给服务端设置断点。
3、活跃,内核模式目标
AttackKernel方法让调试器引擎连接到系统内核。
4、远程目标
当用调试器引擎来远程调试时,由两个额外的步骤:
连接主机引擎。如果主机引擎不是本地引擎,用DebugConnect来创建一个客户端对象来连接到主机引擎。
把主机引擎连接到进程服务器或者内核连接服务器。如果主机引擎不直接连接目标,那他必须连接到一个进程服务器或内核连接服务器。
现在客户端对象可以告诉主机引擎通过进程服务器或内核连接服务器获得一个目标。
5、获取目标
当获取一个目标时,目标的获取直到那个目标产生一个事件前是不完整的。通常,这意味着首先调用方法让调试器附加到目标,然后调用WaitForEvent让目标产生一个事件。当目标是一个转储文件时这仍然适用,因为他们总是存储一个事件——通常要创建导致转储文件的事件。
六、事件
调试器提供设施来监控并向目标相应事件。当一个事件发生,引擎挂起目标(往往只是简单的),它会提示所有事件的客户,那些反过来会指导引擎目标中的执行流程应该怎样继续。
为了通知一个事件的客户端,引擎要调用被与客户端注册的事件回调对象。引擎给每个事件回调提供事件的详情,事件回调指导引擎接下来执行应该怎样在目标中继续运行。当不同的事件回调提供相矛盾的指导时,引擎按照高优先权的来相应(参考DEBUG_STATUS_XXX),通常意味着选择了涉及至少执行所述目标的指令。
注意当事件回调在处理事件时,目标被暂停,调试会话不可访问。
1、事件过滤器
调试引擎同样提供事件过滤器(这是基本事件监控一个简单替代)。事件过滤器提供一些简单的规则,指定是否一个事件应该被打印到调试器的输出流或中断下来。当一个事件发生时他们也可以被用来执行调试器命令。
五、断点
调试器可以创建并监控目标中的断点。
有两种类型的断点引擎可以插入到一个目标中:软件断点和硬件断点。
1、软件断点通过修改断点处的处理器指令来被插入到目标代码中。调试器引擎一直跟踪这样的断点;对于对象在那个位置读和写来说他们都是无形的。当目标执行到代码修改处软件断点才被触发。
2、硬件断点通过在指定位置执行一段代码,读或写内存才会被触发。
断点的地址可以通过一个明确的地址来指定,由计算结果为一个地址,或者可能要评估一个地址在将来某个时间表达式的表达式。在后一种情况下,一个模块加载或卸载目标中的每个时间,发动机将尝试重新评估表达和插入断点,如果它能够确定的地址;这使得被载入模块可以设置断点。
许多参数可以被与断点关联来控制它的行为:
一个断点可以被与目标中一个特殊的线程相关联,然后它只会被那个线程所触发。
一个断点可以与调试器命令相关联;这些命令在断点触发时被自动执行。
一个断点可以被标记为待用,直到目标通过它一系列指定的次数。
一个断点可以在第一次触发后被自动移除

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值