[Win32] Implementation of a debugger (a) debug events and Debug loops

Source: Internet
Author: User
Tags visual studio 2010

[Win32] Implementation of a debugger (a) debug events and Debug loops

Zplutor
Source: http://www.cnblogs.com/zplutor/
This article copyright belongs to the author and the blog Garden altogether, welcome reprint. However, without the author's consent, this statement must be retained, and in the article page obvious location to the original link, otherwise reserves the right to pursue legal responsibility.

Objective

Programmers are inseparable from the debugger, which can dynamically display the program's execution process, for solving program problems have great help. If you and I are interested in how the debugger works, then this series of articles is good for you, and these articles document the process of developing a debugger prototype that I hope will help you. Perhaps I write the code is very poor, but also ask you many forgive me!

This debugger uses visual Studio 2010 as a development tool and is a console program. To simplify, all input and output uses the relevant classes of the C + + standard library, and many error checking and processing procedures are omitted.

Start the Debugged program

To debug a program, the first thing to do is to start the program, which is done using CreateProcess, the Windows API. For example, the following code takes Notepad as the program being debugged:

1 #include <Windows.h>
2 #include <iostream>
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
if (CreateProcess (
TEXT ("C:\\windows\\notepad.exe"),
NULL,
NULL,
NULL,
FALSE,
debug_only_this_process | Create_new_console,
NULL,
NULL,
&si,
&AMP;PI) = = FALSE) {
22
Std::wcout << TEXT ("CreateProcess failed:") << GetLastError () << Std::endl;
return-1;
25}
26
CloseHandle (Pi.hthread);
CloseHandle (pi.hprocess);
29
return 0;
31}

The sixth parameter of CreateProcess uses debug_only_this_process, which means that the process that invokes CreateProcess becomes the debugger, and the child process it initiates becomes the process being debugged. In addition to Debug_only_this_process, you can also use debug_process, the difference is that debug_process will debug the debugged process and all its child processes, and Debug_only_this_ Process only debugs the processes that are being debugged, and does not debug its child processes. In general we only want to debug a process, so we should use the latter.

I recommend adding a create_new_console tag to the sixth parameter. Because if the debugger is a console program, the debugger and the output of the debugger are in the same console window, it is confusing, and after this tag, the debugger will output the information in a new console window. If the debugger is a window program, this tag has no effect.

The code above simply initiates the process of being debugged and then exits immediately. Note that if the debugger process is finished, all child processes that are debugged by it will end with it. This is why, although the CreateProcess call succeeds, it does not see the Notepad window.

Debug loops

How does the debugger know what is going on inside the debugged process? So, when a process becomes a debugged process, when something is done or an exception occurs, it sends a notification to the debugger and then suspends itself until the debugger commands it to continue execution. This is a bit like the Windows window's message mechanism.

Notifications sent by the debug process are called Debug events, and the Debug_event struct describes the contents of the 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_info Createprocessinfo;
9 Exit_thread_debug_info ExitThread;
Ten Exit_process_debug_info exitprocess;
One by one load_dll_debug_info Loaddll;
Unload_dll_debug_info Unloaddll;
Output_debug_string_info debugstring;
Rip_info Ripinfo;
-} u;
+} debug_event,
*lpdebug_event;

Dwdebugeventcode describes the type of debug event, with a total of 9 types of debug events:

Create_process_debug_event

This type of debug event is sent after the process is created, which is the first debug event that the debugger receives.

Create_thread_debug_event

This type of debug event is sent after a thread is created.

Exception_debug_event

This type of debug event is sent when an exception occurs.

Exit_process_debug_event

This type of debug event is sent after the process finishes.

Exit_thread_debug_event

This type of debug event is sent when a thread ends.

Load_dll_debug_event

This type of debug event is sent after a DLL module is loaded.

Output_debug_string_event

This type of debug event is sent when a function such as OutputDebugString is called by the debugging process.

Rip_event

This type of debug event is sent when a system debug error occurs.

Unload_dll_debug_event

This type of debug event is sent after uninstalling a DLL module.

The details of each debug event are recorded by the Union U, which quickly determines which field is associated with which event by the name of the field you are using. For example, Create_process_debug_event debug event details are logged by the Createprocessinfo field.

Dwprocessid and dwThreadID are process IDs and thread IDs that trigger debug events, respectively. A debugger may debug multiple processes at the same time, and there may be multiple threads in each process, and through these two fields you know which thread of the process the debug event was fired from. This series of articles only considers single-process single-threaded cases, so these two fields will not be used because these two values have been obtained when CreateProcess is called.

The debugger obtains debug events through the Waitfordebugevent function and continues the execution of the debug process through Continuedebugevent. Continuedebugevent has three parameters, the first and second parameters are the process ID and the thread ID, which means that the specified thread in the specified process continues execution. Typically this is done in a loop, as shown in the following code:

1 void onprocesscreated (const create_process_debug_info*);
2 void onthreadcreated (const create_thread_debug_info*);
3 void Onexception (const exception_debug_info*);
4 void onprocessexited (const exit_process_debug_info*);
5 void onthreadexited (const exit_thread_debug_info*);
6 void onoutputdebugstring (const output_debug_string_info*);
7 void Onripevent (const rip_info*);
8 void ondllloaded (const load_dll_debug_info*);
9 void ondllunloaded (const unload_dll_debug_info*);
10
One BOOL waitevent = TRUE;
Debug_event debugEvent;
while (waitevent = = TRUE && waitfordebugevent (&debugevent, INFINITE)) {
14
Switch (debugevent.dwdebugeventcode) {
16
Case Create_process_debug_event:
Onprocesscreated (&debugevent.u.createprocessinfo);
break;
20
Case Create_thread_debug_event:
Onthreadcreated (&debugevent.u.createthread);
At a break;
24
Case Exception_debug_event:
Onexception (&debugevent.u.exception);
break;
28
Case Exit_process_debug_event:
Onprocessexited (&debugevent.u.exitprocess);
Waitevent = FALSE;
break;
33
Case Exit_thread_debug_event:
Onthreadexited (&debugevent.u.exitthread);
break;
37
Load_dll_debug_event Case:
Ondllloaded (&debugevent.u.loaddll);
a break;
41
Unload_dll_debug_event Case:
Ondllunloaded (&debugevent.u.unloaddll);
a break;
45
Case Output_debug_string_event:
Onoutputdebugstring (&debugevent.u.debugstring);
a break;
49
Case Rip_event:
Wuyi onripevent (&debugevent.u.ripinfo);
a break;
53
Default:
Std::wcout << TEXT ("Unknown debug event.") << Std::endl;
a break;
57}
58
if (waitevent = = TRUE) {
Continuedebugevent (Debugevent.dwprocessid, Debugevent.dwthreadid, dbg_continue);
61}
+ Else {
a break;
64}
65}

Such a loop is called a debug loop. Notice how this exits the loop: introduce a waitevent variable of type bool and change its value to false after processing exit_process_debug_event. This is done because you can still call the Waitfordebugevent function to wait for the debug event after the end of the debugging process, so that you are stuck in an infinite wait, causing the debugger process to end.

Sample code

The example code combines the above two pieces of code, and implements the debug event handler functions such as onprocesscreated, which is only the output hint information. Of course, the handling of debug events is much more than simple, although you can choose to ignore certain debug events, but some debug events must be handled, and this part will be explained in the next article.

Http://files.cnblogs.com/zplutor/MiniDebugger1.rar

[Win32] Implementation of a debugger (a) debug events and Debug loops

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.