Mercurial > projects > ddbg_continued
diff 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 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/cli/userinterface.d Tue Apr 05 20:44:01 2011 +0200 @@ -0,0 +1,344 @@ +/* Ddbg - Win32 Debugger for the D programming language + * Copyright (c) 2007 Jascha Wetzel + * All rights reserved. See LICENSE.TXT for details. + */ +module cli.userinterface; + +import breakpoint; +import dbgprocess; +import dbgthread; +import debugger; +import expression.datahandler; +import codeview.codeview; +import util; +import disasm; +import codeview.coff; + +import win32.winnt; + +import std.string; +import std.c.string; +import std.utf; + +interface UserInterface +{ + void init(string[] args); + int start(); + + bool readCommand(); + bool parseCommand(string cmd); + void runCommands(string cmdstr); + + void debugString(string str); + bool breakpoint(int index, Breakpoint bp, DbgThread thread); + void userInterrupt(); + void exception(uint threadId, string class_name, string msg, size_t obj_ptr); + void win32exception(uint threadId, EXCEPTION_RECORD* exrec); + void loadedDLL(DLL dll); + void exitProcess(); + void singleStep(); +} + +struct StackTraceEntry +{ + uint index; + Location loc; + uint frame_level; + CodeBlock last_known_cb; + + void describe(UserInterfaceBase ui) + { + DbgIO.print("#%d ", index); + if ( loc is null ) { + DbgIO.println("<no debug symbols available>"); + return; + } + if ( index > 0 ) + DbgIO.print("0x%08x in ", loc.address); + if ( loc.scope_sym !is null ) + { + ProcedureSymbol psym = cast(ProcedureSymbol)loc.scope_sym; + + string argstr; + bool first = true; + foreach_reverse ( argsym; psym.arguments.stack_symbols ) + { + string name = argsym.name_notype; + if ( !first ) + argstr ~= ", "; + else + first = false; + argstr ~= argsym.name_notype; + try { + SymbolValue symval = ui.dbg.handleData(ui.dbg.evaluateExpression(name, frame_level), false); + argstr ~= " = "~ui.symbolValueToString(symval); + } + catch ( Exception e ) { + } + } + int end = find(psym.name_type, '('), + start = find(psym.name_type, ' '); + if ( end < 0 ) + end = psym.name_type.length; + if ( start < 0 ) + start = 0; + if ( end-start < 2 ) + start = 0; + DbgIO.print("%s (", psym.name_type[start..end]); + DbgIO.write(argstr~") "); + } + else if ( loc.data_sym !is null ) + DbgIO.print(loc.data_sym.name_type, " () "); + else + DbgIO.print("?? () "); + if ( loc.codeblock !is null ) + DbgIO.print("at %s:%d", loc.file, loc.line); + else + { + if ( last_known_cb !is null && last_known_cb.segment !is null ) + DbgIO.print("at %s:%d ", last_known_cb.segment.file.name, last_known_cb.line); + if ( loc.mod !is null ) + DbgIO.print("from %s", loc.mod.name); + else if ( ui.dbg.process !is null ) + { + DLL dll = ui.dbg.process.findDLL(loc.address); + if ( dll !is null ) + DbgIO.print("from %s", dll.image.name); + } + } + DbgIO.println(""); + } +} + +abstract class UserInterfaceBase : UserInterface +{ + CodeBlock last_codeblock; + Module last_module; + DLL last_dll; + + Debugger dbg; + + string[] cmdQueue; + + void printAsmLine(uint address, string bytes, string asmsource, string symbol, string location, string source); + string symbolValueToString(SymbolValue val); + + /********************************************************************************************** + + **********************************************************************************************/ + void unwindStack() + { + StackTraceEntry[] entries; + + uint index, + counter, + frame_level; + 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); + Location loc = dbg.images.findLocation(dbg.current_address); + if ( loc is null ) + loc = new Location(dbg.current_address, null); + entries ~= StackTraceEntry(counter++, loc, frame_level); + + dbg.stack.firstFrame(index); + ubyte[] frame = dbg.stack.prevFrame(index, index); + size_t next_frame=1; + while ( frame !is null ) + { + uint ret_adr = (cast(uint[])frame)[1]; + loc = dbg.images.findLocation(ret_adr); + if ( loc is null ) + loc = new Location(ret_adr, null); + frame = dbg.stack.prevFrame(index, index); + ++frame_level; + if ( next_frame >= entries.length ) + entries.length = entries.length*2+1; + entries[next_frame++] = StackTraceEntry(counter++, loc, frame_level); + } + entries.length = next_frame; + + CodeBlock last_known_cb; + foreach_reverse ( ref ste; entries ) + { + if ( ste.loc !is null && ste.loc.codeblock !is null ) + last_known_cb = ste.loc.codeblock; + else + ste.last_known_cb = last_known_cb; + } + + foreach ( ste; entries ) + ste.describe(this); + } + + /********************************************************************************************** + Prints an instruction with looked up symbols if existant. + **********************************************************************************************/ + bool printDisassembly(ud_t* ud_obj) + { + // first call + if ( ud_obj is null ) { + last_codeblock = null; + return true; + } + + uint address = cast(uint)ud_insn_off(ud_obj); + string source, location; + + // check whether we have symbols here + Location loc = dbg.images.findLocation(address); + if ( loc.codeblock !is null ) + { + if ( last_codeblock !is loc.codeblock ) + { + last_codeblock = loc.codeblock; + string[] source_file = dbg.getSourceFile(loc.file); + location = format("%s:%d", loc.file, loc.line); + if ( source_file !is null && loc.line <= source_file.length ) + source = source_file[loc.line-1]; + } + } + else + { + CodeView cv; + CodeBlock cb = dbg.images.findCodeBlockRel(address, cv); + if ( cb !is null ) + { + if ( last_codeblock !is cb ) + last_codeblock = cb; + } + else + { + uint seg; + Module mod = dbg.images.findModule(address, seg); + if ( mod !is null && last_module !is mod ) { + last_module = mod; + location = mod.name; + } + else + { + DLL dll = dbg.process.findDLL(address); + if ( dll !is null && last_dll !is dll ) { + last_dll = dll; + location = dll.image.name; + } + } + } + } + + string symbol; + bool is_imm=true; + uint jmp_dest = DisAsm.calcJumpDestination(dbg.process, dbg.process.threads[dbg.thread_id], ud_obj, is_imm); + if ( is_imm && jmp_dest>0 ) + symbol = "\t"~describeLocation(jmp_dest, false); + + char* hex = ud_insn_hex(ud_obj); + uint hexlen = strlen(hex); + char* ins = ud_insn_asm(ud_obj); + + printAsmLine(address, hex[0..hexlen], ins[0..strlen(ins)], symbol, location, source); + return true; + } + + /********************************************************************************************** + + **********************************************************************************************/ + void printSymbols(CodeView cv, NamedSymbol[] syms, string substring=null, uint indent=0) + { + foreach ( ns; syms ) + { + if ( substring.length > 0 && find(ns.name_notype, substring)<0 ) + continue; + + char[] indent_str; + indent_str.length = indent*2; + indent_str[0..indent*2] = ' '; + ClassInfo cs = ns.classinfo; + if ( cs == ProcedureSymbol.classinfo ) + { + ProcedureSymbol ps = cast(ProcedureSymbol)ns; + size_t start = ps.cvdata.offset+cv.getCodeBase; + DbgIO.println("%s%s %d arguments, entry 0x%x, debug start 0x%x, debug end 0x%x", + indent_str, ps.name_type, ps.arguments.symbols.length, start, + start+ps.cvdata.debug_start, start+ps.cvdata.debug_end + ); + } + else if ( cs == StackSymbol.classinfo ) { + StackSymbol ss = cast(StackSymbol)ns; + 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); + } + else if ( cs == DataSymbol.classinfo ) + { + DataSymbol ds = cast(DataSymbol)ns; + 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, + ds.offset, ds.size, ds.cvdata.segment, ds.cvdata.type, dbg.images.mangleCVtype(ds.cvdata.type) + ); + } + else + DbgIO.println("%s%s %s", indent_str, ns.name_type, cs.name); + ScopeSymbol scs = cast(ScopeSymbol)ns; + if ( scs !is null ) + printSymbols(cv, scs.symbols.named_symbols, substring, indent+1); + } + } + + /********************************************************************************************** + + **********************************************************************************************/ + string describeLocation(uint vaddress, bool with_address=true) + { + Location loc = dbg.images.findLocation(vaddress); + return describeLocation(loc, with_address); + } + + /********************************************************************************************** + + **********************************************************************************************/ + string describeLocation(Location loc, bool with_address=true) + { + string desc; + + if ( loc is null ) + return "unknown"; + + if ( loc.codeblock !is null ) + desc = format("%s:%d", loc.file, loc.line); + if ( with_address ) + desc ~= (desc.length>0?" ":"")~format("(0x%08x)", loc.address); + + if ( loc.scope_sym !is null ) + return loc.scope_sym.name_notype~" "~desc; + if ( loc.data_sym !is null ) + return loc.data_sym.name_notype~" "~desc; + if ( loc.mod !is null ) + return loc.mod.name~" "~desc; + if ( dbg.process !is null ) + { + DLL dll = dbg.process.findDLL(loc.address); + if ( dll !is null ) + return dll.image.name~" "~desc; + } + + return desc; + } + + /********************************************************************************************** + + **********************************************************************************************/ + void runCommands(string cmd_string) + { + cmd_string = replace(cmd_string, "\\\"", "\""); + auto r = std.regexp.RegExp("(([^;\" \\t]+)|(\"[^\"]+\"))+|;"); + string cmd; + string[] cmds; + foreach ( m; r.search(cmd_string) ) + { + if ( m.match(0) == ";" ) { + cmdQueue ~= cmd~";"; + cmd = null; + } + else + cmd ~= " "~m.match(0); + } + if ( cmd !is null ) + cmdQueue ~= cmd~";"; + } +}