Mercurial > projects > ddbg_continued
view 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 source
/* 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); } }