Mercurial > projects > ddbg_continued
comparison src/cli/userinterface.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 | 496dfd8f7342 |
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 cli.userinterface; | |
6 | |
7 import breakpoint; | |
8 import dbgprocess; | |
9 import dbgthread; | |
10 import debugger; | |
11 import expression.datahandler; | |
12 import codeview.codeview; | |
13 import util; | |
14 import disasm; | |
15 import codeview.coff; | |
16 | |
17 import win32.winnt; | |
18 | |
19 import std.string; | |
20 import std.c.string; | |
21 import std.utf; | |
22 | |
23 interface UserInterface | |
24 { | |
25 void init(string[] args); | |
26 int start(); | |
27 | |
28 bool readCommand(); | |
29 bool parseCommand(string cmd); | |
30 void runCommands(string cmdstr); | |
31 | |
32 void debugString(string str); | |
33 bool breakpoint(int index, Breakpoint bp, DbgThread thread); | |
34 void userInterrupt(); | |
35 void exception(uint threadId, string class_name, string msg, size_t obj_ptr); | |
36 void win32exception(uint threadId, EXCEPTION_RECORD* exrec); | |
37 void loadedDLL(DLL dll); | |
38 void exitProcess(); | |
39 void singleStep(); | |
40 } | |
41 | |
42 struct StackTraceEntry | |
43 { | |
44 uint index; | |
45 Location loc; | |
46 uint frame_level; | |
47 CodeBlock last_known_cb; | |
48 | |
49 void describe(UserInterfaceBase ui) | |
50 { | |
51 DbgIO.print("#%d ", index); | |
52 if ( loc is null ) { | |
53 DbgIO.println("<no debug symbols available>"); | |
54 return; | |
55 } | |
56 if ( index > 0 ) | |
57 DbgIO.print("0x%08x in ", loc.address); | |
58 if ( loc.scope_sym !is null ) | |
59 { | |
60 ProcedureSymbol psym = cast(ProcedureSymbol)loc.scope_sym; | |
61 | |
62 string argstr; | |
63 bool first = true; | |
64 foreach_reverse ( argsym; psym.arguments.stack_symbols ) | |
65 { | |
66 string name = argsym.name_notype; | |
67 if ( !first ) | |
68 argstr ~= ", "; | |
69 else | |
70 first = false; | |
71 argstr ~= argsym.name_notype; | |
72 try { | |
73 SymbolValue symval = ui.dbg.handleData(ui.dbg.evaluateExpression(name, frame_level), false); | |
74 argstr ~= " = "~ui.symbolValueToString(symval); | |
75 } | |
76 catch ( Exception e ) { | |
77 } | |
78 } | |
79 int end = find(psym.name_type, '('), | |
80 start = find(psym.name_type, ' '); | |
81 if ( end < 0 ) | |
82 end = psym.name_type.length; | |
83 if ( start < 0 ) | |
84 start = 0; | |
85 if ( end-start < 2 ) | |
86 start = 0; | |
87 DbgIO.print("%s (", psym.name_type[start..end]); | |
88 DbgIO.write(argstr~") "); | |
89 } | |
90 else if ( loc.data_sym !is null ) | |
91 DbgIO.print(loc.data_sym.name_type, " () "); | |
92 else | |
93 DbgIO.print("?? () "); | |
94 if ( loc.codeblock !is null ) | |
95 DbgIO.print("at %s:%d", loc.file, loc.line); | |
96 else | |
97 { | |
98 if ( last_known_cb !is null && last_known_cb.segment !is null ) | |
99 DbgIO.print("at %s:%d ", last_known_cb.segment.file.name, last_known_cb.line); | |
100 if ( loc.mod !is null ) | |
101 DbgIO.print("from %s", loc.mod.name); | |
102 else if ( ui.dbg.process !is null ) | |
103 { | |
104 DLL dll = ui.dbg.process.findDLL(loc.address); | |
105 if ( dll !is null ) | |
106 DbgIO.print("from %s", dll.image.name); | |
107 } | |
108 } | |
109 DbgIO.println(""); | |
110 } | |
111 } | |
112 | |
113 abstract class UserInterfaceBase : UserInterface | |
114 { | |
115 CodeBlock last_codeblock; | |
116 Module last_module; | |
117 DLL last_dll; | |
118 | |
119 Debugger dbg; | |
120 | |
121 string[] cmdQueue; | |
122 | |
123 void printAsmLine(uint address, string bytes, string asmsource, string symbol, string location, string source); | |
124 string symbolValueToString(SymbolValue val); | |
125 | |
126 /********************************************************************************************** | |
127 | |
128 **********************************************************************************************/ | |
129 void unwindStack() | |
130 { | |
131 StackTraceEntry[] entries; | |
132 | |
133 uint index, | |
134 counter, | |
135 frame_level; | |
136 debug DbgIO.println("Stack: base 0x%x top 0x%x frame 0x%x", dbg.stack.base_ptr, dbg.stack.top_ptr, dbg.stack.frame_ptr); | |
137 Location loc = dbg.images.findLocation(dbg.current_address); | |
138 if ( loc is null ) | |
139 loc = new Location(dbg.current_address, null); | |
140 entries ~= StackTraceEntry(counter++, loc, frame_level); | |
141 | |
142 dbg.stack.firstFrame(index); | |
143 ubyte[] frame = dbg.stack.prevFrame(index, index); | |
144 size_t next_frame=1; | |
145 while ( frame !is null ) | |
146 { | |
147 uint ret_adr = (cast(uint[])frame)[1]; | |
148 loc = dbg.images.findLocation(ret_adr); | |
149 if ( loc is null ) | |
150 loc = new Location(ret_adr, null); | |
151 frame = dbg.stack.prevFrame(index, index); | |
152 ++frame_level; | |
153 if ( next_frame >= entries.length ) | |
154 entries.length = entries.length*2+1; | |
155 entries[next_frame++] = StackTraceEntry(counter++, loc, frame_level); | |
156 } | |
157 entries.length = next_frame; | |
158 | |
159 CodeBlock last_known_cb; | |
160 foreach_reverse ( ref ste; entries ) | |
161 { | |
162 if ( ste.loc !is null && ste.loc.codeblock !is null ) | |
163 last_known_cb = ste.loc.codeblock; | |
164 else | |
165 ste.last_known_cb = last_known_cb; | |
166 } | |
167 | |
168 foreach ( ste; entries ) | |
169 ste.describe(this); | |
170 } | |
171 | |
172 /********************************************************************************************** | |
173 Prints an instruction with looked up symbols if existant. | |
174 **********************************************************************************************/ | |
175 bool printDisassembly(ud_t* ud_obj) | |
176 { | |
177 // first call | |
178 if ( ud_obj is null ) { | |
179 last_codeblock = null; | |
180 return true; | |
181 } | |
182 | |
183 uint address = cast(uint)ud_insn_off(ud_obj); | |
184 string source, location; | |
185 | |
186 // check whether we have symbols here | |
187 Location loc = dbg.images.findLocation(address); | |
188 if ( loc.codeblock !is null ) | |
189 { | |
190 if ( last_codeblock !is loc.codeblock ) | |
191 { | |
192 last_codeblock = loc.codeblock; | |
193 string[] source_file = dbg.getSourceFile(loc.file); | |
194 location = format("%s:%d", loc.file, loc.line); | |
195 if ( source_file !is null && loc.line <= source_file.length ) | |
196 source = source_file[loc.line-1]; | |
197 } | |
198 } | |
199 else | |
200 { | |
201 CodeView cv; | |
202 CodeBlock cb = dbg.images.findCodeBlockRel(address, cv); | |
203 if ( cb !is null ) | |
204 { | |
205 if ( last_codeblock !is cb ) | |
206 last_codeblock = cb; | |
207 } | |
208 else | |
209 { | |
210 uint seg; | |
211 Module mod = dbg.images.findModule(address, seg); | |
212 if ( mod !is null && last_module !is mod ) { | |
213 last_module = mod; | |
214 location = mod.name; | |
215 } | |
216 else | |
217 { | |
218 DLL dll = dbg.process.findDLL(address); | |
219 if ( dll !is null && last_dll !is dll ) { | |
220 last_dll = dll; | |
221 location = dll.image.name; | |
222 } | |
223 } | |
224 } | |
225 } | |
226 | |
227 string symbol; | |
228 bool is_imm=true; | |
229 uint jmp_dest = DisAsm.calcJumpDestination(dbg.process, dbg.process.threads[dbg.thread_id], ud_obj, is_imm); | |
230 if ( is_imm && jmp_dest>0 ) | |
231 symbol = "\t"~describeLocation(jmp_dest, false); | |
232 | |
233 char* hex = ud_insn_hex(ud_obj); | |
234 uint hexlen = strlen(hex); | |
235 char* ins = ud_insn_asm(ud_obj); | |
236 | |
237 printAsmLine(address, hex[0..hexlen], ins[0..strlen(ins)], symbol, location, source); | |
238 return true; | |
239 } | |
240 | |
241 /********************************************************************************************** | |
242 | |
243 **********************************************************************************************/ | |
244 void printSymbols(CodeView cv, NamedSymbol[] syms, string substring=null, uint indent=0) | |
245 { | |
246 foreach ( ns; syms ) | |
247 { | |
248 if ( substring.length > 0 && find(ns.name_notype, substring)<0 ) | |
249 continue; | |
250 | |
251 char[] indent_str; | |
252 indent_str.length = indent*2; | |
253 indent_str[0..indent*2] = ' '; | |
254 ClassInfo cs = ns.classinfo; | |
255 if ( cs == ProcedureSymbol.classinfo ) | |
256 { | |
257 ProcedureSymbol ps = cast(ProcedureSymbol)ns; | |
258 size_t start = ps.cvdata.offset+cv.getCodeBase; | |
259 DbgIO.println("%s%s %d arguments, entry 0x%x, debug start 0x%x, debug end 0x%x", | |
260 indent_str, ps.name_type, ps.arguments.symbols.length, start, | |
261 start+ps.cvdata.debug_start, start+ps.cvdata.debug_end | |
262 ); | |
263 } | |
264 else if ( cs == StackSymbol.classinfo ) { | |
265 StackSymbol ss = cast(StackSymbol)ns; | |
266 DbgIO.println("%s%s stack (%s) %x ebp%s%d", indent_str, ns.name_type, ns.mangled_name, ss.cvtype, ss.offset>=0?"+":"", ss.offset); | |
267 } | |
268 else if ( cs == DataSymbol.classinfo ) | |
269 { | |
270 DataSymbol ds = cast(DataSymbol)ns; | |
271 DbgIO.println("%s%s (%s) data offset: 0x%x size: 0x%x segment: 0x%x type: 0x%x (%s)", indent_str, ds.name_type, ds.name_notype, | |
272 ds.offset, ds.size, ds.cvdata.segment, ds.cvdata.type, dbg.images.mangleCVtype(ds.cvdata.type) | |
273 ); | |
274 } | |
275 else | |
276 DbgIO.println("%s%s %s", indent_str, ns.name_type, cs.name); | |
277 ScopeSymbol scs = cast(ScopeSymbol)ns; | |
278 if ( scs !is null ) | |
279 printSymbols(cv, scs.symbols.named_symbols, substring, indent+1); | |
280 } | |
281 } | |
282 | |
283 /********************************************************************************************** | |
284 | |
285 **********************************************************************************************/ | |
286 string describeLocation(uint vaddress, bool with_address=true) | |
287 { | |
288 Location loc = dbg.images.findLocation(vaddress); | |
289 return describeLocation(loc, with_address); | |
290 } | |
291 | |
292 /********************************************************************************************** | |
293 | |
294 **********************************************************************************************/ | |
295 string describeLocation(Location loc, bool with_address=true) | |
296 { | |
297 string desc; | |
298 | |
299 if ( loc is null ) | |
300 return "unknown"; | |
301 | |
302 if ( loc.codeblock !is null ) | |
303 desc = format("%s:%d", loc.file, loc.line); | |
304 if ( with_address ) | |
305 desc ~= (desc.length>0?" ":"")~format("(0x%08x)", loc.address); | |
306 | |
307 if ( loc.scope_sym !is null ) | |
308 return loc.scope_sym.name_notype~" "~desc; | |
309 if ( loc.data_sym !is null ) | |
310 return loc.data_sym.name_notype~" "~desc; | |
311 if ( loc.mod !is null ) | |
312 return loc.mod.name~" "~desc; | |
313 if ( dbg.process !is null ) | |
314 { | |
315 DLL dll = dbg.process.findDLL(loc.address); | |
316 if ( dll !is null ) | |
317 return dll.image.name~" "~desc; | |
318 } | |
319 | |
320 return desc; | |
321 } | |
322 | |
323 /********************************************************************************************** | |
324 | |
325 **********************************************************************************************/ | |
326 void runCommands(string cmd_string) | |
327 { | |
328 cmd_string = replace(cmd_string, "\\\"", "\""); | |
329 auto r = std.regexp.RegExp("(([^;\" \\t]+)|(\"[^\"]+\"))+|;"); | |
330 string cmd; | |
331 string[] cmds; | |
332 foreach ( m; r.search(cmd_string) ) | |
333 { | |
334 if ( m.match(0) == ";" ) { | |
335 cmdQueue ~= cmd~";"; | |
336 cmd = null; | |
337 } | |
338 else | |
339 cmd ~= " "~m.match(0); | |
340 } | |
341 if ( cmd !is null ) | |
342 cmdQueue ~= cmd~";"; | |
343 } | |
344 } |