Mercurial > projects > ddbg_continued
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); + } +}