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~";";
+	}
+}