Mercurial > projects > ddbg_continued
view src/cli/userinterface.d @ 5:496dfd8f7342 default tip
added:
-repeat option for "in", "ov"
-run until a line option
-run until a function option
-break on a function start
-n is an alias for ov
author | marton@basel.hu |
---|---|
date | Sun, 17 Apr 2011 11:05:31 +0200 |
parents | 4a9dcbd9e54f |
children |
line wrap: on
line source
/* 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; } /********************************************************************************************** prints information about symbol (not recursive) **********************************************************************************************/ void printSymbol( NamedSymbol ns, uint indent=0) { { 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; DbgIO.println("%s%s %d arguments", indent_str, ps.name_type, ps.arguments.symbols.length ); } 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, indent+1); } } /********************************************************************************************** prints symbols that contain substring with indentation indent **********************************************************************************************/ 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~";"; } }