diff src/breakpoint.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
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/breakpoint.d	Tue Apr 05 20:44:01 2011 +0200
@@ -0,0 +1,199 @@
+/*  Ddbg - Win32 Debugger for the D programming language
+ *  Copyright (c) 2007 Jascha Wetzel
+ *  All rights reserved. See LICENSE.TXT for details.
+ */
+module breakpoint;
+
+import std.string;
+import std.c.string;
+
+import dbgthread;
+import codeview.codeview;
+import dbgprocess;
+import util;
+
+import win32.windef;
+
+enum StepMode {
+    e_in, e_over, e_out
+}
+
+/**************************************************************************************************
+    Represents a software breakpoint.
+**************************************************************************************************/
+class Breakpoint
+{
+    //---------------------------------------------------------------------------------------------
+    // constants
+    const ubyte BREAKPOINT_OPCODE = 0xccu;
+
+    //---------------------------------------------------------------------------------------------
+    // variables
+    byte            old_opcode;
+    bool            active,
+                    temporary,
+                    deactivate_d_exception_handler,
+                    propagate,				/// when hit on a jmp/call/ret instruction, shall be reactivated on it's destination
+                    hardware;
+    Breakpoint      foreach_end;
+    Location		location;
+    size_t          frame_ptr,
+                    threadId,
+                    old_dr_value;
+    ubyte           dr_index;
+
+    //---------------------------------------------------------------------------------------------
+    // properties
+    string file()				{ return location is null?null:location.file; }
+    uint line()					{ return location is null?0:location.line; }
+    uint address()				{ return location is null?0:location.address; }
+
+
+    //---------------------------------------------------------------------------------------------
+    // construction
+    this(Location loc, bool temp, uint _threadId, bool _hardware=false)
+    {
+        hardware = _hardware;
+        threadId = _threadId;
+        temporary = temp;
+        location = loc;
+    }
+
+
+    //---------------------------------------------------------------------------------------------
+    // methods
+
+    /**
+     *
+     */
+    string toString()
+    {
+        string tmp;
+        tmp.length = 100;
+        tmp.length = 0;
+        if ( location.path.length > 0 )
+            tmp ~= format("%s ", location.path);
+        if ( file.length > 0 )
+            tmp ~= format("%s:%d ", file, line);
+        if ( location.address > 0 )
+            tmp ~= format("0x%x ", location.address);
+        if ( hardware )
+            tmp ~= "hw ";
+        if ( threadId > 0 )
+            tmp ~= format("thread %s", threadId);
+        else
+            tmp ~= format("all threads");
+        return tmp;
+    }
+
+    /**********************************************************************************************
+        Restores the opcode that has been overwritten for the given breakpoint.
+        Returns success.
+    **********************************************************************************************/
+    bool deactivate(DbgProcess proc)
+    {
+        if ( !active )
+            return true;
+        if ( proc is null )
+            return false;
+
+        if ( hardware )
+        {
+            if ( threadId == 0 )
+            {
+                foreach ( thread; proc.threads.values )
+                    clearHWBP(thread, 0);
+            }
+            else
+                clearHWBP(proc.threads[threadId], 0);
+        }
+        else if( !proc.writeProcessMemory(location.address, &old_opcode, ubyte.sizeof))
+        {
+            DbgIO.println("restoreBreakpoint(): Failed to write original opcode at 0x%x", location.address);
+            return false;
+        }
+
+        active = false;
+        return true;
+    }
+
+    /**********************************************************************************************
+        Writes an int 3 opcode at the address of this breakpoint, saving the overwritten code.
+        Returns success.
+    **********************************************************************************************/
+    bool activate(DbgProcess proc)
+    {
+        if( active )
+            return true;
+        if( location.address == 0 || proc is null )
+            return false;
+
+        debug DbgIO.println("activating bp at 0x%x", location.address);
+
+        if ( hardware )
+        {
+            if ( threadId == 0 )
+            {
+                foreach ( thread; proc.threads.values )
+                    setHWBP(thread, location.address, 0);
+            }
+            else
+                setHWBP(proc.threads[threadId], location.address, 0);
+        }
+        else
+        {
+            uint	oldprot, oldprot2;
+            ubyte	ccByte = cast(ubyte)0xcc;
+
+            if( ubyte.sizeof > proc.readProcessMemory(location.address, &old_opcode, ubyte.sizeof) ) {
+                DbgIO.println( "readProcessMemory(): failed to read breakpoint opcode at 0x%08x", location.address );
+                return false;
+            }
+
+            ubyte opcode = BREAKPOINT_OPCODE;
+            if( ubyte.sizeof > proc.writeProcessMemory(location.address, &opcode, ubyte.sizeof) ) {
+                DbgIO.println("writeProcessMemory(): Failed to write breakpoint at 0x%08x", location.address );
+                return false;
+            }
+        }
+
+        active = true;
+        return true;
+    }
+
+    /**********************************************************************************************
+
+    **********************************************************************************************/
+    void setHWBP(DbgThread thread, size_t address, ubyte index)
+    {
+        assert(index < 4);
+
+        CONTEXT ctx;
+        thread.getContext(ctx, CONTEXT_DEBUG_REGISTERS);
+        DbgIO.println("Dr0 = %x\nDr1 = %x\nDr2 = %x\nDr3 = %x\nDr7 = %x\n", ctx.Dr0, ctx.Dr1, ctx.Dr2, ctx.Dr3, ctx.Dr7);
+
+        old_dr_value = *(&ctx.Dr0 + index);
+        *(&ctx.Dr0 + index) = address+thread.getDsBase;
+        dr_index = index;
+
+        ctx.Dr7 |= 1<<10 | (1 << index) | (15 << (16+index*4));
+        DbgIO.println("Dr0 = %x\nDr1 = %x\nDr2 = %x\nDr3 = %x\nDr7 = %x\n", ctx.Dr0, ctx.Dr1, ctx.Dr2, ctx.Dr3, ctx.Dr7);
+        thread.setContext(ctx);
+    }
+
+    /**********************************************************************************************
+
+    **********************************************************************************************/
+    void clearHWBP(DbgThread thread, ubyte index)
+    {
+        assert(index < 4);
+
+        CONTEXT ctx;
+        thread.getContext(ctx, CONTEXT_DEBUG_REGISTERS);
+        DbgIO.println("Dr0 = %x\nDr1 = %x\nDr2 = %x\nDr3 = %x\nDr7 = %x\n", ctx.Dr0, ctx.Dr1, ctx.Dr2, ctx.Dr3, ctx.Dr7);
+
+        ctx.Dr7 &= ~((1 << index) | (15 << (16+index*4)));
+        DbgIO.println("Dr0 = %x\nDr1 = %x\nDr2 = %x\nDr3 = %x\nDr7 = %x\n", ctx.Dr0, ctx.Dr1, ctx.Dr2, ctx.Dr3, ctx.Dr7);
+        thread.setContext(ctx);
+    }
+}