zoukankan      html  css  js  c++  java
  • 在编写简单调试器时遇到的一些问题的总结

    前言

    为了熟悉调试子系统与调试器之间的联系,以及了解调试器各种断点的原理以及win32调试API的使用自己尝试写了一个简单的调试器。中间遇到了很多问题,总结一下希望能帮助到遇见类似问题的人。

    问题一

    CreateDialogParam()创建非模态对话框的时候,虽然其消息循环在外部,但并不是调用完就立刻返回到消息循环。其需要根据对话框资源在内部在默认窗口类“#32720”基础上调用CreateWindowEx创建窗口,发送消息WM_CREATE,WM_INITDIALOG消息到对话框管理器中,然后消息在传到消息回调函数中,当对话框回调函数(或对话框管理器)处理完这些消息后CreateWindowEx才会返回。

    DialogParam()创建模态对话框的时候,因为其是内建消息循环,当调用完DialogParam后如果内部消息循环不退出,则DialogParam不返回。这也是模态对话框没关闭时不能点击其他窗口的原因。

    问题二

    附件进程的时候如果DebugActiveProcess()和调试事件循环不在一个线程中就会调试循环就会接收不到调试事件。调用GetLastError()显示是:句柄无效,这是因为线程在创建调试会话时会创建一个调试内核对象,并把这个调试内核对象放在当前线程信息块TEB的DbgSsReserved[1]中,这个也是此调试线程区别于其他普通线程的标志。因为在WaitForDebugEvent()在等待调试事件时候实际是在等待调试内核对象的EventsPresent。所以如果等待调试事件循环与创建调试会话不在一个线程将无法获得调试内核对象的句柄。

    问题三

    VirtualProtectEx()改变指定内存属性时,最后一个参数用来接收内存原属性其必须指定,不能传NULL。(如果传NULL会返回指针无效)

    问题四

    调试线程在接收到进程退出事件时EXIT_PROCESS_DEBUG_EVENT,需要在自己处理完相应操作后在交给ContinueDebugEvent处理。如果没让ContinueDebugEvent处理,进程就无法真正退出调试并结束进程。原因是因为当被调试进程退出时,向调试子系统发送调试事件(EXIT_PROCESS_DEBUG_EVENT),此时被调试进程会被挂起等待调试子系统处理完调试事件消息后返回,而调试子系统通过事件对象与调试进程通信并将调试消息事件发送给调试器进程通过调用KeWaitForSingalEvent来等待此同步事件,调试器进程调用WaitForDebugEvent来同步事件同步对象,只有当调试器进程调用了ContinueDebugEvent后才会设置同步事件对象,这时调试子系统的KeWaitSingalEvent才能返回,进而被调试进程才能被激活进而正常退出。

    问题五

    在利用调试寄存器实现硬件执行断点时,因为硬件执行断点产生的异常属于错误类异常,所以如果在调试器中捕捉异常后如果不处理,当程序返回后eip依然指向引发异常的指令。继续运行又会重新引发异常,所以需要在调试器中捕捉异常后设置DR7调试控制寄存器令断点冻结并设置单步标志(为了恢复冻结的断点)。

    然后我在看张银奎老师的《软件调试》时发现可以通过设置EFlags标志寄存器的RF位为一,让其在返回后不响应第一条指令产生的异常。

    关于RF位

    重启动标志RF(Restart Flag)
    重启动标志RF用来控制是否接受调试故障。规定:RF=0时,表示“接受”调试故障,否则拒绝之。

  • 相关阅读:
    Quick Find
    并查集
    树形问题和更多树
    二叉搜索树的局限性
    Oracle Auto Increment Column
    测试机器性能
    EXP/IMP version
    python getaddrinfo 函数
    open cursor too much error
    要看的一些链接
  • 原文地址:https://www.cnblogs.com/revercc/p/13287071.html
Copyright © 2011-2022 走看看