欢迎来到天天文库
浏览记录
ID:16452187
大小:833.81 KB
页数:127页
时间:2018-08-09
《一个调试器的实现》由会员上传分享,免费在线阅读,更多相关内容在教育资源-天天文库。
1、一个调试器的实现(一)调试事件与调试循环前言程序员离不开调试器,它可以动态显示程序的执行过程,对于解决程序问题有极大的帮助。如果你和我一样对调试器的工作原理很感兴趣,那么这一系列文章很适合你,这些文章记录了我开发一个调试器雏形的过程,希望对你有帮助。或许我写的代码很拙劣,还请大家多多见谅! 这个调试器使用VisualStudio2010作为开发工具,是一个控制台程序。为了简化,一切输入输出都使用C++标准库的相关类,而且省略了很多错误检查和处理的过程。 启动被调试程序要想对一个程序进行调试,首先要做的当然是启动这个程序,这
2、要使用CreateProcess这个WindowsAPI来完成。例如,下面的代码以记事本作为被调试程序: 1 #include 2 #include 3 4 int wmain(int argc, wchar_t** argv) { 5 6 STARTUPINFO si = { 0 }; 7 si.cb = sizeof(si); 8 9 PROCESS_INFORMATION pi = { 0 };10 11 if (CreateProc
3、ess(12 TEXT("C:\windowsotepad.exe"),13 NULL,14 NULL,15 NULL,16 FALSE,17 DEBUG_ONLY_THIS_PROCESS
4、 CREATE_NEW_CONSOLE,18 NULL,19 NULL,20 &si,21 &pi) == FALSE) {22 23 std::wc
5、out << TEXT("CreateProcess failed:") << GetLastError() << std::endl;24 return -1;25 }26 27 CloseHandle(pi.hThread);28 CloseHandle(pi.hProcess);29 30 return 0;31 } CreateProcess的第六个参数使用了DEBUG_ONLY_THIS_PROCESS,这意味着调用CreateProcess的进程成为了调试器,而它
6、启动的子进程成了被调试的进程。除了DEBUG_ONLY_THIS_PROCESS之外,还可以使用DEBUG_PROCESS,两者的不同在于:DEBUG_PROCESS会调试被调试进程以及它的所有子进程,而DEBUG_ONLY_THIS_PROCESS只调试被调试进程,不调试它的子进程。一般情况下我们只想调试一个进程,所以应使用后者。 我建议在第六个参数中加上CREATE_NEW_CONSOLE标记。因为如果被调试程序是一个控制台程序的话,调试器和被调试程序的输出都在同一个控制台窗口内,显得很混乱,加上这个标记之后,被调试程
7、序就会在一个新的控制台窗口中输出信息。如果被调试程序是一个窗口程序,这个标记没有影响。 上面的代码仅仅是启动了被调试进程,然后就立即退出了。要注意的是,如果调试器进程结束了,那么被它调试的所有子进程都会随着结束。这就是为什么虽然CreateProcess调用成功了,却看不到记事本窗口。 调试循环调试器如何知道被调试进程内部发生了什么呢?是这样的,当一个进程成为被调试进程之后,在完成了某些操作或者发生异常时,它会发送通知给调试器,然后将自身挂起,直到调试器命令它继续执行。这有点像Windows窗口的消息机制。 被调试进程发送
8、的通知称为调试事件,DEBUG_EVENT结构体描述了调试事件的内容: 1 typedef struct _DEBUG_EVENT { 2 DWORD dwDebugEventCode; 3 DWORD dwProcessId; 4 DWORD dwThreadId; 5 union { 6 EXCEPTION_DEBUG_INFO Exception; 7 CREATE_THREAD_DEBUG_INFO CreateThread; 8 CREATE_PROCESS_DEBUG_I
9、NFO CreateProcessInfo; 9 EXIT_THREAD_DEBUG_INFO ExitThread;10 EXIT_PROCESS_DEBUG_INFO ExitProcess;11 LOAD_DLL_DEBUG_INFO LoadDll;12 UNLO
此文档下载收益归作者所有