Mercurial > projects > ddbg_continued
comparison src/breakpoint.d @ 1:4a9dcbd9e54f
-files of 0.13 beta
-fixes so that it now compiles with the current dmd version
author | marton@basel.hu |
---|---|
date | Tue, 05 Apr 2011 20:44:01 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:586e4a649642 | 1:4a9dcbd9e54f |
---|---|
1 /* Ddbg - Win32 Debugger for the D programming language | |
2 * Copyright (c) 2007 Jascha Wetzel | |
3 * All rights reserved. See LICENSE.TXT for details. | |
4 */ | |
5 module breakpoint; | |
6 | |
7 import std.string; | |
8 import std.c.string; | |
9 | |
10 import dbgthread; | |
11 import codeview.codeview; | |
12 import dbgprocess; | |
13 import util; | |
14 | |
15 import win32.windef; | |
16 | |
17 enum StepMode { | |
18 e_in, e_over, e_out | |
19 } | |
20 | |
21 /************************************************************************************************** | |
22 Represents a software breakpoint. | |
23 **************************************************************************************************/ | |
24 class Breakpoint | |
25 { | |
26 //--------------------------------------------------------------------------------------------- | |
27 // constants | |
28 const ubyte BREAKPOINT_OPCODE = 0xccu; | |
29 | |
30 //--------------------------------------------------------------------------------------------- | |
31 // variables | |
32 byte old_opcode; | |
33 bool active, | |
34 temporary, | |
35 deactivate_d_exception_handler, | |
36 propagate, /// when hit on a jmp/call/ret instruction, shall be reactivated on it's destination | |
37 hardware; | |
38 Breakpoint foreach_end; | |
39 Location location; | |
40 size_t frame_ptr, | |
41 threadId, | |
42 old_dr_value; | |
43 ubyte dr_index; | |
44 | |
45 //--------------------------------------------------------------------------------------------- | |
46 // properties | |
47 string file() { return location is null?null:location.file; } | |
48 uint line() { return location is null?0:location.line; } | |
49 uint address() { return location is null?0:location.address; } | |
50 | |
51 | |
52 //--------------------------------------------------------------------------------------------- | |
53 // construction | |
54 this(Location loc, bool temp, uint _threadId, bool _hardware=false) | |
55 { | |
56 hardware = _hardware; | |
57 threadId = _threadId; | |
58 temporary = temp; | |
59 location = loc; | |
60 } | |
61 | |
62 | |
63 //--------------------------------------------------------------------------------------------- | |
64 // methods | |
65 | |
66 /** | |
67 * | |
68 */ | |
69 string toString() | |
70 { | |
71 string tmp; | |
72 tmp.length = 100; | |
73 tmp.length = 0; | |
74 if ( location.path.length > 0 ) | |
75 tmp ~= format("%s ", location.path); | |
76 if ( file.length > 0 ) | |
77 tmp ~= format("%s:%d ", file, line); | |
78 if ( location.address > 0 ) | |
79 tmp ~= format("0x%x ", location.address); | |
80 if ( hardware ) | |
81 tmp ~= "hw "; | |
82 if ( threadId > 0 ) | |
83 tmp ~= format("thread %s", threadId); | |
84 else | |
85 tmp ~= format("all threads"); | |
86 return tmp; | |
87 } | |
88 | |
89 /********************************************************************************************** | |
90 Restores the opcode that has been overwritten for the given breakpoint. | |
91 Returns success. | |
92 **********************************************************************************************/ | |
93 bool deactivate(DbgProcess proc) | |
94 { | |
95 if ( !active ) | |
96 return true; | |
97 if ( proc is null ) | |
98 return false; | |
99 | |
100 if ( hardware ) | |
101 { | |
102 if ( threadId == 0 ) | |
103 { | |
104 foreach ( thread; proc.threads.values ) | |
105 clearHWBP(thread, 0); | |
106 } | |
107 else | |
108 clearHWBP(proc.threads[threadId], 0); | |
109 } | |
110 else if( !proc.writeProcessMemory(location.address, &old_opcode, ubyte.sizeof)) | |
111 { | |
112 DbgIO.println("restoreBreakpoint(): Failed to write original opcode at 0x%x", location.address); | |
113 return false; | |
114 } | |
115 | |
116 active = false; | |
117 return true; | |
118 } | |
119 | |
120 /********************************************************************************************** | |
121 Writes an int 3 opcode at the address of this breakpoint, saving the overwritten code. | |
122 Returns success. | |
123 **********************************************************************************************/ | |
124 bool activate(DbgProcess proc) | |
125 { | |
126 if( active ) | |
127 return true; | |
128 if( location.address == 0 || proc is null ) | |
129 return false; | |
130 | |
131 debug DbgIO.println("activating bp at 0x%x", location.address); | |
132 | |
133 if ( hardware ) | |
134 { | |
135 if ( threadId == 0 ) | |
136 { | |
137 foreach ( thread; proc.threads.values ) | |
138 setHWBP(thread, location.address, 0); | |
139 } | |
140 else | |
141 setHWBP(proc.threads[threadId], location.address, 0); | |
142 } | |
143 else | |
144 { | |
145 uint oldprot, oldprot2; | |
146 ubyte ccByte = cast(ubyte)0xcc; | |
147 | |
148 if( ubyte.sizeof > proc.readProcessMemory(location.address, &old_opcode, ubyte.sizeof) ) { | |
149 DbgIO.println( "readProcessMemory(): failed to read breakpoint opcode at 0x%08x", location.address ); | |
150 return false; | |
151 } | |
152 | |
153 ubyte opcode = BREAKPOINT_OPCODE; | |
154 if( ubyte.sizeof > proc.writeProcessMemory(location.address, &opcode, ubyte.sizeof) ) { | |
155 DbgIO.println("writeProcessMemory(): Failed to write breakpoint at 0x%08x", location.address ); | |
156 return false; | |
157 } | |
158 } | |
159 | |
160 active = true; | |
161 return true; | |
162 } | |
163 | |
164 /********************************************************************************************** | |
165 | |
166 **********************************************************************************************/ | |
167 void setHWBP(DbgThread thread, size_t address, ubyte index) | |
168 { | |
169 assert(index < 4); | |
170 | |
171 CONTEXT ctx; | |
172 thread.getContext(ctx, CONTEXT_DEBUG_REGISTERS); | |
173 DbgIO.println("Dr0 = %x\nDr1 = %x\nDr2 = %x\nDr3 = %x\nDr7 = %x\n", ctx.Dr0, ctx.Dr1, ctx.Dr2, ctx.Dr3, ctx.Dr7); | |
174 | |
175 old_dr_value = *(&ctx.Dr0 + index); | |
176 *(&ctx.Dr0 + index) = address+thread.getDsBase; | |
177 dr_index = index; | |
178 | |
179 ctx.Dr7 |= 1<<10 | (1 << index) | (15 << (16+index*4)); | |
180 DbgIO.println("Dr0 = %x\nDr1 = %x\nDr2 = %x\nDr3 = %x\nDr7 = %x\n", ctx.Dr0, ctx.Dr1, ctx.Dr2, ctx.Dr3, ctx.Dr7); | |
181 thread.setContext(ctx); | |
182 } | |
183 | |
184 /********************************************************************************************** | |
185 | |
186 **********************************************************************************************/ | |
187 void clearHWBP(DbgThread thread, ubyte index) | |
188 { | |
189 assert(index < 4); | |
190 | |
191 CONTEXT ctx; | |
192 thread.getContext(ctx, CONTEXT_DEBUG_REGISTERS); | |
193 DbgIO.println("Dr0 = %x\nDr1 = %x\nDr2 = %x\nDr3 = %x\nDr7 = %x\n", ctx.Dr0, ctx.Dr1, ctx.Dr2, ctx.Dr3, ctx.Dr7); | |
194 | |
195 ctx.Dr7 &= ~((1 << index) | (15 << (16+index*4))); | |
196 DbgIO.println("Dr0 = %x\nDr1 = %x\nDr2 = %x\nDr3 = %x\nDr7 = %x\n", ctx.Dr0, ctx.Dr1, ctx.Dr2, ctx.Dr3, ctx.Dr7); | |
197 thread.setContext(ctx); | |
198 } | |
199 } |