First of all, the last time for the software breakpoint cc restore location, int 3 breakpoint, belongs to the Trap class exception, the place of recovery should be the next instruction of the exception instruction, but we receive the message when the Firstchance is the next, in the second time is exactly where the breakpoint occurred.
Recently read the next < software debugging > got an explanation
First, write a little program.
int _tmain (int argc,_tchar* argv[]) { int3; printf ("Hello INT 3"); return 0l }
When debugging, go to the Disassembly window and we see that the address where the exception occurred is 0X013813CE
In view Register window, find EIP as also 0x013813ce
The answer you get in software debugging is
Implementation of hardware breakpoints
· There are a total of 8 Drx debug registers, from DRx0 to DRx7. The characteristics of each register are as follows:
· DR0~DR3: Debug the address register, save the address to be monitored, such as setting a hardware breakpoint;
· DR4~DR5: reserved, not disclosed specific role;
· DR6: Debug Register Group status register;
· DR7: Debug Register Group Control register.
DR6 controls which registers are hit
DR7 controls which Drx sets the breakpoint, local or global, read/write breakpoint type, breakpoint length 1/2/4/8, information
typedefstruct_dbg_reg6{/*//Breakpoint hit flag bit, if a breakpoint at Dr0~3 is hit, the corresponding//b0~3 will be set to 1 before exception processing. */unsigned B0:1;//Dr0 Breakpoint Trigger positionUnsigned B1:1;//Dr1 Breakpoint Trigger positionUnsigned B2:1;//DR2 Breakpoint Trigger positionUnsigned B3:1;//DR3 Breakpoint Trigger position /*//Reserved Fields*/unsigned Reserve1:9; /*//Other status fields*/unsigned BD:1;//after the modulation register itself triggers a breakpoint, this bit is set to 1Unsigned BS:1;//a single-step exception is triggered and needs to be combined with the TF of the Register EFlagsUnsigned BT:1;//This bit is used in conjunction with the T flag of TSS for receiving CPU task switching exceptions /*//Reserved Fields*/unsigned Reserve2: -;} Dbg_reg6,*Pdbg_reg6;typedefstruct_dbg_reg7{/*//Local breakpoint (L0~3) and global Breakpoint (g0~3) Mark bit*/unsigned L0:1;//enable local breakpoints for Dr0 saved addressesUnsigned G0:1;//enable global breakpoints for Dr0 saved addressesUnsigned L1:1;//enable local breakpoints for DR1 saved addressesUnsigned G1:1;//enable global breakpoints for DR1 saved addressesUnsigned L2:1;//enable local breakpoints for DR2 saved addressesUnsigned G2:1;//enable global breakpoints for DR2 saved addressesUnsigned L3:1;//enable local breakpoints for DR3 saved addressesUnsigned G3:1;//enable global breakpoints for DR3 saved addresses /*//"deprecated" to reduce CPU frequency to facilitate accurate detection of breakpoint anomalies*/unsigned LE:1; Unsigned GE:1; /*//Reserved Fields*/unsigned Reserve1:3; /*//Protection debug register flag bit, if this bit is 1, then there is an instruction to modify the bar is the register will trigger an exception*/unsigned GD:1; /*//Reserved Fields*/unsigned Reserve2:2; /*//Save the breakpoint type (RW0~3) and the breakpoint length (len0~3) for the location pointed to by the DR0~DR3 address, as described below:*/unsigned RW0:2;//set the type of breakpoint Dr0 point to addressUnsigned LEN0:2;//set the length of the breakpoint Dr0 point to addressUnsigned RW1:2;//set the type of breakpoint Dr1 point to addressUnsigned LEN1:2;//set the length of the breakpoint Dr1 point to addressUnsigned RW2:2;//set the type of breakpoint Dr2 point to addressUnsigned LEN2:2;//set the length of the breakpoint Dr2 point to addressUnsigned RW3:2;//set the type of breakpoint Dr3 point to addressUnsigned LEN3:2;//set the length of the breakpoint Dr3 point to address}dbg_reg7,*pdbg_reg7;
Knowing the meaning of each bit of Dr7, we can set a hardware breakpoint.
The value of DR7 is first obtained by GetThreadContext, and the value of DR7 is set by SetThreadContext.
The code is as follows
HANDLE sethardwarebreakpoint (HANDLE hthread,hwbrk_type type,hwbrk_size SIZE,void*s) { if(M_vechard.size () >3) returnFALSE; Pointinfo bkpt; Bkpt.lppointaddr= (DWORD) s;//Record Breakpoint AddressBkpt.pttype = Dr_point;//Record Breakpoint Type intj =0; inty =0; CONTEXT CT= {0}; intIreg =0; J=suspendthread (G_hthread);//I've had a problem here .//This is always an invalid handle,y =GetLastError (); Ct. Contextflags= context_debug_registers|Context_full; if(! GetThreadContext (hthread,&CT)) {y=GetLastError (); MessageBox (null,l"Fail", L"1",1); } intFlagbit =0; BOOLDr0busy =false; BOOLDr1busy =false; BOOLDr2busy =false; BOOLDr3busy =false; if(Ct. DR7 &1)//0-bit 0 localDr0busy =true; if(Ct. DR7 &4)//2-bit 1 localDr1busy =true; if(Ct. DR7 & -)//4-bit 2 localDr2busy =true; if(Ct. DR7 & -)//6-bit 3 localDr3busy =true; if(!dr0busy) {bkpt. number=0; Ireg=0; Ct. Dr0= (dword_ptr) s;//AddressDr0busy =true; } Else if(!dr1busy) {bkpt. number=1; Ireg=1; Ct. DR1=(DWORD_PTR) s; Dr1busy=true; } Else if(!dr2busy) {bkpt. number=2; Ireg=2; Ct. DR2=(DWORD_PTR) s; Dr2busy=true; } Else if(!dr3busy) {bkpt. number=3; Ireg=3; Ct. DR3=(DWORD_PTR) s; Dr3busy=true; } Else { //h->succ = false;j =ResumeThread (hthread); Y=GetLastError (); return 0; } Ct. DR6=0; intSt =0; if(Type = =Hwbrk_type_code) St=0; if(Type = =hwbrk_type_readwrite) St=3; if(Type = =hwbrk_type_write) St=1; intLe =0; if(Size = =hwbrk_size_1) Le=0; if(Size = =hwbrk_size_2) Le=1; if(Size = =hwbrk_size_4) Le=3; if(Size = =hwbrk_size_8) Le=2; Setbits (Ct. DR7, -+ ireg*4,2, ST); Setbits (Ct. DR7, -+ ireg*4,2, le); Setbits (Ct. DR7, Ireg*2,1,1); Ct. Contextflags=context_debug_registers; if(! SetThreadContext (hthread,&CT)) {y=GetLastError (); MessageBox (null,l"Fail", L"1",1); } Ct. Contextflags=context_debug_registers; if(! GetThreadContext (hthread,&CT)) {y=GetLastError (); MessageBox (null,l"Fail", L"1",1); } J=ResumeThread (hthread); Y=GetLastError (); M_vechard.push_back (BKPT); return 0;}voidSetbits (dword_ptr& DW,intLowbit,intBitsintnewvalue) {Dword_ptr Mask= (1<< bits)-1; DW= (DW & ~ (Mask << lowbit)) | (NewValue <<lowbit);}
Before GetThreadContext must suspend the thread, SuspendThread, otherwise the context can be obtained when the thread stack is changing, then the structure is not accurate, But I always GetLastError back in the SuspendThread. 6, invalid handle, do not know why, debugging hardware breakpoints are broken down, do not debug directly run, it can not be broken down, feeling is suspendthread problem, record a bit, We'll fix it together next time.
Implementation of the Simple debugger (II.)