comparison src/cli/gdbcli.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 cli.gdbcli;
6
7 import std.string;
8 static import std.regexp;
9 import std.c.stdio : sscanf;
10 import std.c.string;
11 import std.demangle;
12
13 import util;
14 import codeview.codeview;
15 import breakpoint;
16 import debugger;
17 import disasm;
18 import callstack;
19 import dbgprocess;
20 import dbgthread;
21 import expression.expression_apd;
22 import expression.datahandler : SymbolValue;
23 import expression.evaluationcontext;
24 import cli.userinterface;
25
26 import win32.winbase;
27 import win32.winuser;
28 import win32.winnt;
29
30 /**************************************************************************************************
31
32 **************************************************************************************************/
33 class GDBCLI : UserInterfaceBase
34 {
35 string[] lastcmd;
36
37 uint current_frame_level;
38
39 string prompt,
40 command_line,
41 debuggee;
42 bool fullname = false,
43 quit;
44
45 /**********************************************************************************************
46
47 **********************************************************************************************/
48 this()
49 {
50 prompt = "(gdb) ";
51 }
52
53 /**********************************************************************************************
54
55 **********************************************************************************************/
56 void init(string[] args)
57 {
58 DbgIO.println(WELCOME_STRING);
59 if ( args.length < 2 )
60 throw new DebuggerException("Usage: ddbg -cli=gdb [-cmd=<commands>] [-fullname] -args <exe file> [arguments]");
61
62 bool read_args = false;
63 Lfe: foreach ( int i, a; args )
64 {
65 switch ( a )
66 {
67 case "-fullname":
68 case "--fullname":
69 fullname = true;
70 break;
71 case "-args":
72 case "--args":
73 read_args=true;
74 break;
75 default:
76 debuggee = a;
77 if ( read_args )
78 {
79 if ( find(a, ' ') >= 0 )
80 command_line = "\""~a~"\"";
81 else
82 command_line = a;
83 if ( args.length > i+1 )
84 command_line ~= " "~join(args[i+1..$], " ");
85 break Lfe;
86 }
87 }
88 }
89
90 dbg = new Debugger(debuggee, this);
91 dbg.create_new_console = true;
92 }
93
94 int start()
95 {
96 while ( !quit )
97 {
98 try readCommand();
99 catch ( Exception e )
100 DbgIO.println(e.msg);
101 }
102 return 0;
103 }
104
105 /**********************************************************************************************
106
107 **********************************************************************************************/
108 void singleStep()
109 {
110 DbgIO.println(describeLocation(dbg.current_address));
111 }
112
113 /**********************************************************************************************
114
115 **********************************************************************************************/
116 void exitProcess()
117 {
118 DbgIO.println("Program exited");
119 }
120
121 /**********************************************************************************************
122
123 **********************************************************************************************/
124 void loadedDLL(DLL dll)
125 {
126 if( dll !is null && dll.image.name.length )
127 DbgIO.writeln(dll.image.name~" loaded");
128 else
129 DbgIO.writeln("unknown DLL loaded");
130 }
131
132 /**********************************************************************************************
133
134 **********************************************************************************************/
135 void win32exception(uint threadId, EXCEPTION_RECORD* exrec)
136 {
137 DbgIO.println(
138 "Program received signal SIG Unhandled Exception: %s(0x%x) at 0x%x",
139 getExceptionName(exrec.ExceptionCode), exrec.ExceptionCode, exrec.ExceptionAddress //describeLocation(dbg.current_address)
140 );
141 }
142
143 /**********************************************************************************************
144
145 **********************************************************************************************/
146 void exception(uint threadId, string class_name, string msg, size_t obj_ptr)
147 {
148 DbgIO.println(
149 "Program received signal SIG Unhandled D Exception (%s%s) at %s",
150 class_name, msg.length>0?" \""~msg~"\"":"", describeLocation(dbg.current_address)
151 );
152 }
153
154 /**********************************************************************************************
155
156 **********************************************************************************************/
157 void userInterrupt()
158 {
159 DbgIO.println("User interrupt at %s", describeLocation(dbg.current_address));
160 }
161
162 /**********************************************************************************************
163
164 **********************************************************************************************/
165 bool breakpoint(int index, Breakpoint bp, DbgThread thread)
166 {
167 if ( bp.file is null || bp.line == 0 )
168 DbgIO.println("Unknown breakpoint hit at %s", describeLocation(bp.address));
169 else
170 DbgIO.println("\032\032%s:%d:0:begmidl:0x%08x", fullname?dbg.getFullSourcePath(bp.file):bp.file, bp.line, bp.address);
171 return true;
172 }
173
174 /**********************************************************************************************
175
176 **********************************************************************************************/
177 void debugString(string str)
178 {
179 printf("Error OUTPUT DEBUG STRING:\n%s\n", toStringz(str));
180 }
181
182 /**********************************************************************************************
183 Command line parser. Gets called when debuggee is suspended.
184 **********************************************************************************************/
185 bool parseCommand(string input)
186 {
187 if ( strip(input).length > 0 )
188 {
189 auto r = std.regexp.RegExp("(([^\" \\t]+)|(\"[^\"]+\"))+");
190 lastcmd.length = 0;
191 foreach ( m; r.search(strip(input)) )
192 lastcmd ~= r.match(0);
193 }
194 if ( lastcmd.length <= 0 )
195 return false;
196
197 int slash_pos = find(lastcmd[0], '/');
198 if ( slash_pos >= 0 ) {
199 lastcmd ~= lastcmd[0];
200 lastcmd[0] = lastcmd[0][0..slash_pos];
201 }
202
203 switch ( lastcmd[0] )
204 {
205 case "help":
206 DbgIO.println("GDB emulation mode - no help available, yet");
207 break;
208 case "delete":
209 if ( lastcmd.length < 2 )
210 DbgIO.println("Warning: too few arguments for set");
211 else switch ( lastcmd[1] )
212 {
213 case "breakpoints":
214 if ( lastcmd.length < 3 )
215 {
216 foreach ( uint i; dbg.breakpoints.keys )
217 dbg.removeBreakpoint(i);
218 }
219 else if ( !isNumeric(lastcmd[2]) )
220 DbgIO.println("Warning: invalid breakpoint index '%s'", lastcmd[2]);
221 else
222 dbg.removeBreakpoint(cast(uint)atoi(lastcmd[2]));
223 break;
224 default:
225 DbgIO.println("Warning: unknown argument %s", lastcmd[1]);
226 }
227 break;
228 case "set":
229 if ( lastcmd.length < 2 )
230 DbgIO.println("Warning: too few arguments for set");
231 else switch ( lastcmd[1] )
232 {
233 case "prompt":
234 if ( lastcmd.length < 3 )
235 DbgIO.println("Warning: too few arguments for set prompt");
236 else
237 prompt = lastcmd[2];
238 break;
239 case "args":
240 if ( dbg.process_loaded )
241 DbgIO.println("Warning: process already started");
242 command_line = debuggee~" "~join(lastcmd[2..$], " ");
243 break;
244 default:
245 DbgIO.println("Warning: unknown variable %s", lastcmd[1]);
246 }
247 break;
248 case "info":
249 if ( lastcmd.length < 2 )
250 DbgIO.println("Warning: too few arguments for info");
251 else
252 {
253 switch ( lastcmd[1] )
254 {
255 case "locals":
256 if ( dbg.process_loaded )
257 {
258 uint scope_address = dbg.getScopeAddress(current_frame_level);
259 ScopeSymbol scope_sym = dbg.images.findProcedureSymbol(scope_address);
260 for ( ; scope_sym !is null; scope_sym = scope_sym.parent_scope )
261 {
262 if ( scope_sym is null )
263 DbgIO.println("No valid scope active");
264 else
265 evalStackSymbols(scope_sym.symbols.stack_symbols);
266 }
267 }
268 break;
269 case "args":
270 if ( dbg.process_loaded )
271 {
272 uint scope_address = dbg.getScopeAddress(current_frame_level);
273 ScopeSymbol scope_sym = dbg.images.findProcedureSymbol(scope_address);
274 for ( ; scope_sym !is null; scope_sym = scope_sym.parent_scope )
275 {
276 if ( scope_sym is null )
277 DbgIO.println("No valid scope active");
278 else
279 {
280 auto psym = cast(ProcedureSymbol)scope_sym;
281 if ( psym !is null )
282 evalStackSymbols(psym.arguments.stack_symbols);
283 }
284 }
285 }
286 break;
287 case "registers":
288 printRegisterDump(dbg.process.threads[dbg.thread_id]);
289 break;
290 case "frame":
291 uint scope_address = dbg.getScopeAddress(current_frame_level);
292 ubyte[] frame = dbg.stack.getFrame(current_frame_level);
293 Location loc = dbg.images.findLocation(scope_address);
294 DbgIO.print("Stack level %d, frame at ", current_frame_level);
295 if ( loc.scope_sym !is null ) {
296 ProcedureSymbol psym = cast(ProcedureSymbol)loc.scope_sym;
297 DbgIO.println("0x%x:", loc.getCodeBase + psym.cvdata.offset + psym.cvdata.debug_start);
298 }
299 else
300 DbgIO.println("0x%x:", dbg.current_address);
301
302 DbgIO.print(" eip = 0x%x in %s (",
303 loc.address, loc.scope_sym is null?"??":loc.scope_sym.name_notype
304 );
305
306 if ( loc.codeblock !is null )
307 DbgIO.print("%s:%d", loc.file, loc.line);
308 else if ( loc.mod !is null )
309 DbgIO.write(loc.mod.name);
310 else
311 {
312 DLL dll = dbg.process.findDLL(loc.address);
313 if ( dll !is null )
314 DbgIO.write(dll.image.name);
315 }
316
317 DbgIO.println("); saved eip 0x%x", (cast(uint[])frame)[1]);
318 break;
319 default:
320 DbgIO.println("Warning: unknown argument %s", lastcmd[1]);
321 }
322 }
323 break;
324 // select frame
325 case "select-frame":
326 if ( lastcmd.length > 1 )
327 current_frame_level = cast(uint)atoi(lastcmd[1]);
328 DbgIO.println("Current frame level is %d", current_frame_level);
329 break;
330 // add breakpoint
331 case "tbreak":
332 case "clear":
333 case "break":
334 int index;
335 if ( lastcmd.length < 2 ) {
336 DbgIO.println("invalid syntax - see help for details");
337 break;
338 }
339 Location loc = new Location(lastcmd[1]);
340 loc.bind(dbg.images, dbg.source_search_paths);
341 if ( loc is null )
342 break;
343 if ( lastcmd.length > 2 )
344 index = cast(int)atoi(lastcmd[2]);
345
346 if ( lastcmd[0] == "clear" )
347 {
348 Breakpoint bp = dbg.getBreakpoint(loc, index);
349 dbg.removeBreakpoint(index);
350 }
351 else
352 {
353 Breakpoint bp;
354 if ( lastcmd[0] == "tbreak" )
355 index = -1;
356 else if ( index <= 0 && dbg.breakpoints.length > 0 )
357 index = dbg.breakpoints.keys.dup.sort[$-1]+1;
358 bp = dbg.setBreakpoint(loc, index, 0);
359 DbgIO.println("Breakpoint %d at 0x%08x", index, bp.address);
360 }
361 break;
362 // add source search path
363 case "directory":
364 if ( lastcmd.length > 1 )
365 {
366 string sp = lastcmd[1].dup;
367 if ( find(sp, '/') >= 0 )
368 sp = replace(sp, "/", "\\");
369 if ( sp[$-1] != '\\' )
370 sp ~= '\\';
371 dbg.source_search_paths ~= sp;
372 }
373 else
374 DbgIO.println("usage: ssp <search_path>");
375 break;
376 // quit
377 case "quit":
378 case "q":
379 dbg.abort = true;
380 quit = true;
381 return true;
382 // run/continue
383 case "cont":
384 case "run":
385 case "start":
386 if ( dbg.process_loaded ) {
387 dbg.single_step = false;
388 dbg.paused = false;
389 return true;
390 }
391 else {
392 dbg.start(command_line);
393 return true;
394 }
395 // single-step
396 case "nexti":
397 dbg.single_step = true;
398 dbg.activateSingleStep(true);
399 return true;
400 // step over
401 case "next":
402 if ( dbg.step(StepMode.e_over) )
403 return true;
404 break;
405 // step into
406 case "step":
407 if ( dbg.step(StepMode.e_in) )
408 return true;
409 break;
410 // step out
411 case "finish":
412 if ( dbg.step(StepMode.e_out) )
413 return true;
414 break;
415 // unwind stack
416 case "bt":
417 unwindStack();
418 break;
419 case "print":
420 case "output":
421 if ( dbg.process_loaded && lastcmd.length > 1 )
422 {
423 string expr;
424 if ( lastcmd[1][0] == '/' )
425 expr = lastcmd[2];
426 else
427 expr = lastcmd[1];
428 try DbgIO.println(symbolValueToString(dbg.handleData(dbg.evaluateExpression(expr), false)));
429 catch ( EvaluationException e ) {
430 DbgIO.writeln(e.toString);
431 }
432 }
433 break;
434 case "disassemble":
435 if ( !dbg.process_loaded )
436 break;
437
438 uint start_address = dbg.current_address;
439 if ( lastcmd.length > 1 )
440 sscanf(toStringz(lastcmd[1]), "%x", &start_address);
441 else
442 {
443 Location loc = dbg.images.findLocation(dbg.current_address);
444 if ( loc.scope_sym !is null ) {
445 ProcedureSymbol psym = cast(ProcedureSymbol)loc.scope_sym;
446 start_address = loc.getCodeBase + psym.cvdata.offset;
447 DisAsm.disasm(dbg.process, start_address, start_address+psym.cvdata.proc_length, &printDisassembly);
448 break;
449 }
450 }
451 DisAsm.disasm(dbg.process, start_address, 0, &printDisassembly);
452 break;
453 case "x":
454 uint start_address;
455 if ( lastcmd.length > 2 )
456 {
457 if ( lastcmd[1].length > 2 && lastcmd[1][0..2] == "0x" )
458 lastcmd[1] = lastcmd[1][2..$];
459 sscanf(toStringz(lastcmd[1]), "%x", &start_address);
460 string count_str = lastcmd[$-1][2..$-2];
461 uint count = cast(uint)atoi(count_str);
462
463 dumpMemory(start_address, count);
464 }
465 else
466 DbgIO.println("Warning: too few arguments for x");
467 break;
468 case "whatis":
469 if ( dbg.process_loaded && lastcmd.length > 1 )
470 {
471 SymbolData sd = dbg.evaluateExpression(lastcmd[1], current_frame_level);
472 string type = demangle("_D0"~sd.type);
473 try DbgIO.println("type = %s", type);
474 catch ( EvaluationException e ) {
475 DbgIO.writeln(e.toString);
476 }
477 }
478 break;
479
480
481 // list source search paths
482 case "lsp":
483 foreach ( s; dbg.source_search_paths )
484 DbgIO.writeln(s);
485 break;
486 // list breakpoints
487 case "lbp":
488 if ( dbg.breakpoints.length <= 0 )
489 DbgIO.println("no breakpoints set");
490 foreach ( uint i, bp; dbg.breakpoints )
491 DbgIO.println("%d %s", i, bp.toString);
492 break;
493 // list temporary breakpoints
494 case "ltbp":
495 if ( dbg.temp_breakpoints.empty )
496 DbgIO.println("no temporary breakpoints set");
497 foreach ( bp; dbg.temp_breakpoints )
498 DbgIO.writeln(bp.value.toString);
499 break;
500 // list debug modules
501 case "lm":
502 string[] modules_noinfo;
503 foreach ( img; dbg.images.images )
504 {
505 if ( img.codeView is null )
506 continue;
507 foreach ( m; img.codeView.modulesByIndex )
508 {
509 string name = m.name;
510
511 if ( m.header.iLib > 0 )
512 name ~= " from "~img.codeView.libraries[m.header.iLib];
513
514 if ( lastcmd.length > 1 && find(name, lastcmd[1]) < 0 )
515 continue;
516
517 bool has_info = false;
518 with ( m.symbols ) if ( proc_symbols.length+stack_symbols.length+data_symbols.length > 0 )
519 {
520 DbgIO.println(
521 "%s\n\tSymbols: %d proc %d stack %d data",
522 name, proc_symbols.length, stack_symbols.length, data_symbols.length
523 );
524 has_info = true;
525 }
526 if ( m.source_module !is null )
527 {
528 DbgIO.println("\tSource files:");
529 has_info = true;
530 foreach ( sf; m.source_module.files )
531 DbgIO.println("\t\t%s", sf.name);
532 }
533 if ( !has_info )
534 modules_noinfo ~= name;
535 }
536 }
537 if ( modules_noinfo.length > 0 )
538 {
539 DbgIO.println("Modules without debug information:");
540 foreach ( m; modules_noinfo )
541 DbgIO.println("%s ", m);
542 }
543 break;
544 // list source modules
545 case "lsm":
546 foreach ( img; dbg.images.images )
547 {
548 if ( img.codeView is null )
549 continue;
550 foreach ( m; img.codeView.modulesByIndex )
551 {
552 if ( m.source_module !is null )
553 {
554 foreach ( sf; m.source_module.files )
555 {
556 if ( lastcmd.length > 1 && find(sf.name, lastcmd[1]) < 0 )
557 continue;
558 DbgIO.writeln(sf.name);
559 }
560 }
561 }
562 }
563 break;
564 // list all symbols
565 case "ls":
566 foreach ( img; dbg.images.images )
567 {
568 if ( img.codeView is null )
569 continue;
570 printSymbols(img.codeView, img.codeView.global_pub.named_symbols, lastcmd.length>1?lastcmd[1]:null);
571 printSymbols(img.codeView, img.codeView.global_sym.named_symbols, lastcmd.length>1?lastcmd[1]:null);
572 printSymbols(img.codeView, img.codeView.static_sym.named_symbols, lastcmd.length>1?lastcmd[1]:null);
573 foreach ( m; img.codeView.modulesByIndex )
574 printSymbols(img.codeView, m.symbols.named_symbols, lastcmd.length>1?lastcmd[1]:null);
575 }
576 break;
577 // list function symbols
578 case "lf":
579 foreach ( img; dbg.images.images )
580 {
581 if ( img.codeView is null )
582 continue;
583 printSymbols(img.codeView, img.codeView.global_pub.proc_symbols, lastcmd.length>1?lastcmd[1]:null);
584 printSymbols(img.codeView, img.codeView.global_sym.proc_symbols, lastcmd.length>1?lastcmd[1]:null);
585 printSymbols(img.codeView, img.codeView.static_sym.proc_symbols, lastcmd.length>1?lastcmd[1]:null);
586 foreach ( m; img.codeView.modulesByIndex )
587 printSymbols(img.codeView, m.symbols.proc_symbols, lastcmd.length>1?lastcmd[1]:null);
588 }
589 break;
590 // list data symbols
591 case "ld":
592 foreach ( img; dbg.images.images )
593 {
594 if ( img.codeView is null )
595 continue;
596 printSymbols(img.codeView, img.codeView.global_pub.data_symbols, lastcmd.length>1?lastcmd[1]:null);
597 printSymbols(img.codeView, img.codeView.global_sym.data_symbols, lastcmd.length>1?lastcmd[1]:null);
598 printSymbols(img.codeView, img.codeView.static_sym.data_symbols, lastcmd.length>1?lastcmd[1]:null);
599 foreach ( m; img.codeView.modulesByIndex )
600 printSymbols(img.codeView, m.symbols.data_symbols, lastcmd.length>1?lastcmd[1]:null);
601 }
602 break;
603 // list global symbols
604 case "lg":
605 foreach ( img; dbg.images.images )
606 {
607 if ( img.codeView is null )
608 continue;
609 printSymbols(img.codeView, img.codeView.global_pub.named_symbols, lastcmd.length>1?lastcmd[1]:null);
610 printSymbols(img.codeView, img.codeView.global_sym.named_symbols, lastcmd.length>1?lastcmd[1]:null);
611 }
612 break;
613 // list global publics
614 case "lp":
615 foreach ( img; dbg.images.images )
616 {
617 if ( img.codeView is null )
618 continue;
619 printSymbols(img.codeView, img.codeView.global_pub.named_symbols, lastcmd.length>1?lastcmd[1]:null);
620 }
621 break;
622 // delete breakpoint
623 case "dbp":
624 if ( lastcmd.length > 1 )
625 {
626 if ( lastcmd[1] == "*" )
627 {
628 foreach ( uint i, bp; dbg.breakpoints )
629 {
630 bp.deactivate(dbg.process);
631 dbg.breakpoints.remove(i);
632 }
633 }
634 else if ( isNumeric(lastcmd[1]) )
635 {
636 if ( !dbg.removeBreakpoint(cast(uint)atoi(lastcmd[1])) )
637 DbgIO.println("invalid breakpoint index: %s",lastcmd[1]);
638 }
639 else
640 {
641 Location loc = new Location(lastcmd[1]);
642 loc.bind(dbg.images, dbg.source_search_paths);
643 if ( loc !is null )
644 {
645 int bp_index;
646 dbg.getBreakpoint(loc, bp_index);
647 if ( bp_index >= 0 && !dbg.removeBreakpoint(bp_index) )
648 DbgIO.println("No breakpoint set at "~lastcmd[1]);
649 }
650 else
651 DbgIO.println("Usage: dbp [<bp index>|<file:line>]");
652 }
653 }
654 else
655 DbgIO.println("Usage: bp <sourc file>:<line>");
656 break;
657 // dump stack
658 case "ds":
659 int dump_length;
660 if ( lastcmd.length > 1 )
661 dump_length = cast(int)atoi(lastcmd[1])*4;
662 else
663 {
664 CONTEXT ctx;
665 if ( dbg.process.threads[dbg.thread_id].getContext(ctx, CONTEXT_CONTROL) )
666 dump_length = ctx.Ebp-ctx.Esp+8;
667 if ( dump_length <= 0 )
668 dump_length = 16*4;
669 }
670 int top = dbg.stack.data.length>dump_length?dump_length:dbg.stack.data.length;
671 dumpMemory(dbg.stack.top_ptr, top, dbg.stack.data);
672 break;
673 case "dm":
674 if ( lastcmd.length < 3 ) {
675 DbgIO.println("usage: dm <start> <length>");
676 break;
677 }
678 uint start;
679 sscanf(toStringz(lastcmd[1]), "%x", &start);
680 dumpMemory(start, cast(uint)atoi(lastcmd[2]));
681 break;
682
683 // unknown command
684 default:
685 DbgIO.println("Warning: Unknown command '%s' ignored!", lastcmd[0]);
686 break;
687 }
688
689 return false;
690 }
691
692 /**********************************************************************************************
693
694 **********************************************************************************************/
695 void dumpMemory(uint start, uint length, ubyte[] _data=null)
696 {
697 ubyte[] data;
698 if ( _data is null )
699 {
700 data.length = length;
701 if ( !dbg.process.readProcessMemory(start, data.ptr, data.length) )
702 return;
703 }
704 else
705 data = _data;
706 for ( uint i = 0; i < length; ++i )
707 {
708 if ( i % (8*4) == 0 )
709 {
710 if ( i > 0 )
711 DbgIO.println("");
712 DbgIO.print("0x%08x:", start+i);
713 }
714 DbgIO.print(" 0x%02x", data[i]);
715 }
716 DbgIO.println("");
717 }
718
719 /**********************************************************************************************
720
721 **********************************************************************************************/
722 void evalStackSymbols(StackSymbol[] symbols)
723 {
724 foreach ( sym; symbols )
725 {
726 string name = sym.mangled_name;
727 DbgIO.print("%s = ", name);
728 try DbgIO.writeln(symbolValueToString(dbg.handleData(dbg.evaluateExpression(name, current_frame_level, sym), true)));
729 catch ( EvaluationException e ) {
730 DbgIO.println(e.msg);
731 }
732 }
733 }
734
735 /**********************************************************************************************
736
737 **********************************************************************************************/
738 void printAsmLine(uint address, string bytes, string asmsource, string symbol, string location, string source)
739 {
740 bool nl = false;
741 if ( location !is null ) {
742 DbgIO.print("0x%08x <??>: // ", address);
743 DbgIO.write(location);
744 nl = true;
745 }
746 if ( source !is null )
747 {
748 if ( !nl )
749 DbgIO.print("0x%08x <??>: // ", address);
750 DbgIO.write(source);
751 nl = true;
752 }
753 if ( nl )
754 DbgIO.println;
755
756 assert(asmsource !is null);
757 DbgIO.print("0x%08x <??>: ", address, asmsource);
758
759 if ( symbol !is null )
760 DbgIO.write(symbol);
761 DbgIO.println;
762 }
763
764 /**********************************************************************************************
765 Prints the register contents of the given thread's context.
766 **********************************************************************************************/
767 void printRegisterDump(DbgThread thread)
768 {
769 CONTEXT ctx;
770 if ( thread.getContext(ctx) )
771 {
772 DbgIO.println("eax\t0x%x -\nebx\t0x%x -\necx\t0x%x -\nedx\t0x%x -", ctx.Eax, ctx.Ebx, ctx.Ecx, ctx.Edx);
773 DbgIO.println("cs\t0x%x -\nds\t0x%x -\nes\t0x%x -\nfs\t0x%x -", ctx.SegCs, ctx.SegDs, ctx.SegEs, ctx.SegFs);
774 DbgIO.println("gs\t0x%x -\nss\t0x%x -\nedi\t0x%x -\nesi\t0x%x -", ctx.SegGs, ctx.SegSs, ctx.Edi, ctx.Esi);
775 DbgIO.println("ebp\t0x%x -\nesp\t0x%x -\neip\t0x%x -\neflags\t0x%x -", ctx.Ebp, ctx.Esp, ctx.Eip, ctx.EFlags);
776 }
777 else
778 DbgIO.println("Warning: Couldn't get main thread's context");
779 }
780
781 /**********************************************************************************************
782
783 **********************************************************************************************/
784 string symbolValueToString(SymbolValue val)
785 {
786 string str;
787 if ( val.name !is null )
788 str = val.name~" = ";
789 if ( val.value !is null )
790 str ~= val.value;
791 else
792 {
793 if ( val.children.length > 0 )
794 {
795 str ~= "{";
796 bool first = true;
797 foreach ( c; val.children )
798 {
799 if ( first )
800 first = false;
801 else
802 str ~= ",";
803 str ~= symbolValueToString(c);
804 }
805 str ~= "}";
806 }
807 else
808 str ~= "{}";
809 }
810 return str;
811 }
812
813 /**********************************************************************************************
814 Read command and call CLI supplied parser function.
815 Gets called when debuggee is suspended.
816 **********************************************************************************************/
817 bool readCommand()
818 {
819 if ( cmdQueue.length > 0 )
820 {
821 string cmd = strip(cmdQueue[0]);
822 cmdQueue = cmdQueue[1..$];
823 DbgIO.writeln(prompt~cmd);
824 return parseCommand(cmd);
825 }
826 else {
827 DbgIO.write(prompt);
828 string input = DbgIO.readln();
829 return parseCommand(input);
830 }
831 }
832 }