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 }