3 Copyright (c) 1998-2001 Klaus P. Gerlicher
11 setting, listing and removing breakpoints
25 15-Nov-2000: general cleanup of source files
29 This file may be distributed under the terms of the GNU Public License.
33 ////////////////////////////////////////////////////
39 ////////////////////////////////////////////////////
44 ULONG OldInt3Handler
=0;
46 SW_BP aSwBreakpoints
[64]={{0,0,0,0},};
48 //*************************************************************************
51 //*************************************************************************
52 PSW_BP
FindSwBp(ULONG ulAddress
)
56 for(i
=0;i
<DIM(aSwBreakpoints
);i
++)
58 if(aSwBreakpoints
[i
].ulAddress
== ulAddress
&& aSwBreakpoints
[i
].bUsed
==TRUE
&& aSwBreakpoints
[i
].bVirtual
==FALSE
)
59 return &aSwBreakpoints
[i
];
65 //*************************************************************************
66 // FindEmptySwBpSlot()
68 //*************************************************************************
69 PSW_BP
FindEmptySwBpSlot(void)
73 for(i
=0;i
<(sizeof(aSwBreakpoints
)/sizeof(SW_BP
));i
++)
75 if(aSwBreakpoints
[i
].bUsed
== FALSE
)
77 return &aSwBreakpoints
[i
];
84 //*************************************************************************
87 //*************************************************************************
88 PSW_BP
FindVirtualSwBp(LPSTR ModName
,LPSTR szFunctionName
)
93 for(i
=0;i
<(sizeof(aSwBreakpoints
)/sizeof(SW_BP
));i
++)
95 p
= &aSwBreakpoints
[i
];
97 if(p
->bUsed
== TRUE
&&
98 p
->bVirtual
== TRUE
&&
99 PICE_strcmpi(p
->szModName
,ModName
)==0 &&
100 PICE_strcmpi(p
->szFunctionName
,szFunctionName
)==0)
109 //*************************************************************************
110 // IsSwBpAtAddressInstalled()
112 //*************************************************************************
113 BOOLEAN
IsSwBpAtAddressInstalled(ULONG ulAddress
)
117 for(i
=0;i
<DIM(aSwBreakpoints
);i
++)
119 if(aSwBreakpoints
[i
].ulAddress
== ulAddress
&&
120 aSwBreakpoints
[i
].bUsed
== TRUE
&&
121 aSwBreakpoints
[i
].bInstalled
&&
122 aSwBreakpoints
[i
].bVirtual
== FALSE
)
129 //*************************************************************************
132 //*************************************************************************
133 BOOLEAN
IsSwBpAtAddress(ULONG ulAddress
)
137 for(i
=0;i
<DIM(aSwBreakpoints
);i
++)
139 if(aSwBreakpoints
[i
].ulAddress
== ulAddress
&& aSwBreakpoints
[i
].bUsed
==TRUE
&& aSwBreakpoints
[i
].bVirtual
==FALSE
)
146 //*************************************************************************
147 // NeedToReInstallSWBreakpoints()
149 //*************************************************************************
150 BOOLEAN
NeedToReInstallSWBreakpoints(ULONG ulAddress
,BOOLEAN bUseAddress
)
153 BOOLEAN bResult
= FALSE
;
157 DPRINT((0,"NeedToReInstallSWBreakpoint() for %x (bUseAddress = %s)\n",ulAddress
,bUseAddress
?"TRUE":"FALSE"));
159 for(i
=0;i
<(sizeof(aSwBreakpoints
)/sizeof(SW_BP
));i
++)
161 p
= &aSwBreakpoints
[i
];
164 if(p
->bUsed
== TRUE
&& p
->bInstalled
== FALSE
&& p
->ulAddress
==ulAddress
&& p
->bVirtual
==FALSE
)
166 if(IsAddressValid(p
->ulAddress
))
168 DPRINT((0,"NeedToReInstallSWBreakpoint(): [1] found BP\n"));
176 if(p
->bUsed
== TRUE
&& p
->bInstalled
== FALSE
&& p
->bVirtual
== FALSE
)
178 if(IsAddressValid(p
->ulAddress
))
180 DPRINT((0,"NeedToReInstallSWBreakpoint(): [2] found BP\n"));
193 //*************************************************************************
194 // ReInstallSWBreakpoint()
196 //*************************************************************************
197 BOOLEAN
ReInstallSWBreakpoint(ULONG ulAddress
)
200 BOOLEAN bResult
= FALSE
;
204 DPRINT((0,"ReInstallSWBreakpoint()\n"));
206 for(i
=0;i
<(sizeof(aSwBreakpoints
)/sizeof(SW_BP
));i
++)
208 p
= &aSwBreakpoints
[i
];
209 if(p
->bUsed
== TRUE
&& p
->bInstalled
== FALSE
&& p
->ulAddress
== ulAddress
&& p
->bVirtual
== FALSE
)
211 if(IsAddressValid(p
->ulAddress
))
215 if( !( isWriteable
= IsAddressWriteable(p
->ulAddress
) ) )
216 SetAddressWriteable(p
->ulAddress
,TRUE
);
217 *(PUCHAR
)(p
->ulAddress
) = 0xCC;
219 SetAddressWriteable(p
->ulAddress
,FALSE
);
220 p
->bInstalled
= TRUE
;
232 //*************************************************************************
233 // InstallSWBreakpoint()
235 //*************************************************************************
236 BOOLEAN
InstallSWBreakpoint(ULONG ulAddress
,BOOLEAN bPermanent
,void (*SWBreakpointCallback
)(void))
239 BOOLEAN bResult
= FALSE
;
242 DPRINT((0,"InstallSWBreakpoint()\n"));
244 // check if page is present
245 // TODO: must also check if it's a writable page
246 if(IsAddressValid(ulAddress
) )
248 DPRINT((0,"InstallSWBreakpoint(): %.8X is valid, writable? %d\n",ulAddress
,IsAddressWriteable(ulAddress
)));
249 DPRINT((0,"pde: %x, pte: %x\n", *(ADDR_TO_PDE(ulAddress
)), *(ADDR_TO_PTE(ulAddress
))));
250 if((p
= FindSwBp(ulAddress
))==NULL
)
252 DPRINT((0,"InstallSWBreakpoint(): %.8X is free\n",ulAddress
));
253 if( (p
=FindEmptySwBpSlot()) )
256 DPRINT((0,"InstallSWBreakpoint(): found empty slot\n"));
257 DPRINT((0,"InstallSWBreakpoint(): %x value: %x", ulAddress
, *(PUCHAR
)ulAddress
));
258 p
->ucOriginalOpcode
= *(PUCHAR
)ulAddress
;
259 //allow writing to page
260 if( !( isWriteable
= IsAddressWriteable(ulAddress
) ) )
261 SetAddressWriteable(ulAddress
,TRUE
);
262 DPRINT((0,"writing breakpoint\n"));
263 *(PUCHAR
)ulAddress
= 0xCC;
264 DPRINT((0,"restoring page access\n"));
266 SetAddressWriteable(ulAddress
,FALSE
);
268 p
->bInstalled
= TRUE
;
270 p
->ulAddress
= ulAddress
;
271 Disasm(&ulAddress
,(PUCHAR
)&tempBp
);
272 p
->ulNextInstr
= ulAddress
;
273 p
->bPermanent
= bPermanent
;
275 p
->Callback
= SWBreakpointCallback
;
283 DPRINT((0,"InstallSWBreakpoint(): %.8X is already used\n",ulAddress
));
286 DPRINT((0,"InstallSWBreakpoint(): %.8X is a permanent breakpoint\n",ulAddress
));
296 //*************************************************************************
297 // InstallVirtualSWBreakpoint()
299 //*************************************************************************
300 BOOLEAN
InstallVirtualSWBreakpoint(LPSTR ModName
,LPSTR FunctionName
)
303 BOOLEAN bResult
= FALSE
;
306 DPRINT((0,"InstallVirtualSWBreakpoint(%s!%s)\n",ModName
,FunctionName
));
308 if( (p
=FindEmptySwBpSlot()) )
310 DPRINT((0,"InstallVirtualSWBreakpoint(): found empty slot\n"));
313 p
->bInstalled
= TRUE
;
316 PICE_strcpy(p
->szModName
,ModName
);
317 PICE_strcpy(p
->szFunctionName
,FunctionName
);
327 //*************************************************************************
328 // TryToInstallVirtualSWBreakpoints()
330 //*************************************************************************
331 void TryToInstallVirtualSWBreakpoints(void)
337 DPRINT((0,"TryToInstallVirtualSWBreakpoints()\n"));
339 for(i
=0;i
<(sizeof(aSwBreakpoints
)/sizeof(SW_BP
));i
++)
341 p
= &aSwBreakpoints
[i
];
342 if(p
->bUsed
== TRUE
&& p
->bVirtual
)
344 if((pMod
= IsModuleLoaded(p
->szModName
)))
346 if((ulAddress
= FindFunctionInModuleByName(p
->szFunctionName
,pMod
)))
348 if((p
= FindVirtualSwBp(p
->szModName
,p
->szFunctionName
)))
350 ULONG ulAddressWithOffset
= ulAddress
+p
->ulAddress
;
351 DPRINT((0,"TryToInstallVirtualSWBreakpoints(): ulAddressWithOffset = %x (offset = %x)\n",ulAddressWithOffset
,p
->ulAddress
));
353 if(IsAddressValid(ulAddressWithOffset
))
356 DPRINT((0,"TryToInstallVirtualSWBreakpoints(): installing...\n"));
357 p
->ucOriginalOpcode
= *(PUCHAR
)ulAddressWithOffset
;
358 //allow writing to page
359 if( !( isWriteable
= IsAddressWriteable(ulAddressWithOffset
) ) )
360 SetAddressWriteable(ulAddressWithOffset
,TRUE
);
361 *(PUCHAR
)ulAddressWithOffset
= 0xCC;
363 SetAddressWriteable(ulAddressWithOffset
,FALSE
);
365 p
->bInstalled
= TRUE
;
368 p
->ulAddress
= ulAddressWithOffset
;
369 Disasm(&ulAddressWithOffset
,(PUCHAR
)&tempBp
);
370 p
->ulNextInstr
= ulAddressWithOffset
;
371 p
->bPermanent
= FALSE
;
376 DPRINT((0,"TryToInstallVirtualSWBreakpoints(): not valid address\n"));
377 PICE_memset(p
,0,sizeof(*p
));
387 //*************************************************************************
388 // RemoveSWBreakpoint()
390 // removes breakpoint from breakpoint list
391 //*************************************************************************
392 BOOLEAN
RemoveSWBreakpoint(ULONG ulAddress
)
395 BOOLEAN bResult
= FALSE
;
398 DPRINT((0,"RemoveSWBreakpoint()\n"));
400 if( (p
= FindSwBp(ulAddress
)) )
402 if(IsAddressValid(ulAddress
) && p
->bInstalled
== TRUE
&& p
->bVirtual
==FALSE
)
405 if( !( isWriteable
= IsAddressWriteable(ulAddress
) ) )
406 SetAddressWriteable(ulAddress
,TRUE
);
407 // restore original opcode
408 *(PUCHAR
)(p
->ulAddress
) = p
->ucOriginalOpcode
;
410 SetAddressWriteable(ulAddress
,FALSE
);
413 PICE_memset(p
,0,sizeof(*p
));
424 //*************************************************************************
425 // DeInstallSWBreakpoint()
427 //*************************************************************************
428 BOOLEAN
DeInstallSWBreakpoint(ULONG ulAddress
)
431 BOOLEAN bResult
= FALSE
;
434 DPRINT((0,"DeInstallSWBreakpoint()\n"));
436 if( (p
= FindSwBp(ulAddress
)) )
438 if(IsAddressValid(ulAddress
) && p
->bInstalled
== TRUE
&& p
->bVirtual
==FALSE
)
441 if( !( isWriteable
= IsAddressWriteable(ulAddress
) ) )
442 SetAddressWriteable(ulAddress
,TRUE
);
443 // restore original opcode
444 *(PUCHAR
)(p
->ulAddress
) = p
->ucOriginalOpcode
;
446 SetAddressWriteable(ulAddress
,FALSE
);
449 p
->bInstalled
= FALSE
;
459 //*************************************************************************
460 // RemoveAllSWBreakpoints()
462 //*************************************************************************
463 BOOLEAN
RemoveAllSWBreakpoints(BOOLEAN bEvenPermanents
)
466 BOOLEAN bResult
= FALSE
;
470 DPRINT((0,"RemoveAllSWBreakpoint()\n"));
472 for(i
=0;i
<(sizeof(aSwBreakpoints
)/sizeof(SW_BP
));i
++)
474 p
= &aSwBreakpoints
[i
];
479 if(IsAddressValid(p
->ulAddress
) && p
->bVirtual
==FALSE
)
482 if( !( isWriteable
= IsAddressWriteable(p
->ulAddress
) ) )
483 SetAddressWriteable(p
->ulAddress
,TRUE
);
484 *(PUCHAR
)(p
->ulAddress
) = p
->ucOriginalOpcode
;
486 SetAddressWriteable(p
->ulAddress
,FALSE
);
489 PICE_memset(p
,0,sizeof(*p
));
495 if(IsAddressValid(p
->ulAddress
) && p
->bVirtual
==FALSE
)
498 if( !( isWriteable
= IsAddressWriteable(p
->ulAddress
) ) )
499 SetAddressWriteable(p
->ulAddress
,TRUE
);
500 *(PUCHAR
)(p
->ulAddress
) = p
->ucOriginalOpcode
;
502 SetAddressWriteable(p
->ulAddress
,FALSE
);
505 PICE_memset(p
,0,sizeof(*p
));
516 //*************************************************************************
517 // IsPermanentSWBreakpoint()
519 //*************************************************************************
520 PSW_BP
IsPermanentSWBreakpoint(ULONG ulAddress
)
526 DPRINT((0,"IsPermanentSWBreakpoint(%.8X)\n",ulAddress
));
528 for(i
=0;i
<(sizeof(aSwBreakpoints
)/sizeof(aSwBreakpoints
[0]));i
++)
530 p
= &aSwBreakpoints
[i
];
531 if(p
->ulAddress
== ulAddress
&&
533 p
->bPermanent
== TRUE
)
545 //*************************************************************************
546 // ListSWBreakpoints()
548 //*************************************************************************
549 void ListSWBreakpoints(void)
557 DPRINT((0,"ListSWBreakpoints()\n"));
559 for(i
=0;i
<(sizeof(aSwBreakpoints
)/sizeof(SW_BP
));i
++)
561 p
= &aSwBreakpoints
[i
];
562 if(p
->bUsed
== TRUE
&& p
->bVirtual
== FALSE
)
564 if((pSymbolName
= FindFunctionByAddress(p
->ulAddress
,NULL
,NULL
)) )
566 pMod
= FindModuleFromAddress(p
->ulAddress
);
567 PICE_sprintf(tempBp
,"[%u] %.8X (%S!%s) %s\n",i
,p
->ulAddress
,pMod
->name
,pSymbolName
,p
->bPermanent
?"PERMANENT":"");
571 if(ScanExportsByAddress(&pSymbolName
,p
->ulAddress
))
572 PICE_sprintf(tempBp
,"[%u] %.8X (%s) %s\n",i
,p
->ulAddress
,pSymbolName
,p
->bPermanent
?"PERMANENT":"");
574 PICE_sprintf(tempBp
,"[%u] %.8X (no symbol) %s\n",i
,p
->ulAddress
,p
->bPermanent
?"PERMANENT":"");
576 Print(OUTPUT_WINDOW
,tempBp
);
578 else if(p
->bUsed
== TRUE
)
580 PICE_sprintf(tempBp
,"[%u] xxxxxxxx (%s!%s) VIRTUAL\n",i
,p
->szModName
,p
->szFunctionName
);
581 Print(OUTPUT_WINDOW
,tempBp
);
588 //*************************************************************************
589 // RevirtualizeBreakpointsForModule()
591 //*************************************************************************
592 void RevirtualizeBreakpointsForModule(PDEBUG_MODULE pMod
)
596 char temp
[DEBUG_MODULE_NAME_LEN
];
598 DPRINT((0,"RevirtualizeBreakpointsForModule(%x)\n",(ULONG
)pMod
));
600 if(IsRangeValid((ULONG
)pMod
,sizeof(DEBUG_MODULE
)) )
602 start
= (ULONG
)pMod
->BaseAddress
;
603 end
= (ULONG
)pMod
->BaseAddress
+pMod
->size
;
605 DPRINT((0,"RevirtualizeBreakpointsForModule(): module %x (%x-%x)\n",(ULONG
)pMod
,start
,end
));
606 // go through all breakpoints
607 for(i
=0;i
<(sizeof(aSwBreakpoints
)/sizeof(SW_BP
));i
++)
609 p
= &aSwBreakpoints
[i
];
610 // if it's used and installed and not virtual
611 if(p
->bUsed
&& p
->bInstalled
&& p
->bVirtual
== FALSE
)
613 // make sure we're in module's bound
614 if(p
->ulAddress
>=start
&& p
->ulAddress
<end
)
617 ULONG ulFunctionAddress
;
619 DPRINT((0,"RevirtualizeBreakpointsForModule(): module breakpoint %u\n",i
));
620 // find the function in which this breakpoint resides
621 if(ScanExportsByAddress(&pFind
,p
->ulAddress
))
623 // from now on it's virtual again
625 if(IsAddressValid(p
->ulAddress
) )
628 if( !( isWriteable
= IsAddressWriteable(p
->ulAddress
) ) )
629 SetAddressWriteable(p
->ulAddress
,TRUE
);
630 DPRINT((0,"RevirtualizeBreakpointsForModule(): restoring original opcode @ %x\n",p
->ulAddress
));
631 *(PUCHAR
)(p
->ulAddress
) = p
->ucOriginalOpcode
;
633 SetAddressWriteable(p
->ulAddress
,FALSE
);
637 DPRINT((0,"RevirtualizeBreakpointsForModule(): could not restore original opcode @ %x\n",p
->ulAddress
));
639 // skip past the module separator
640 while(*pFind
!='!')pFind
++;
642 // remember the function and the module for reinstallation
643 CopyWideToAnsi(temp
,pMod
->name
);
644 PICE_strcpy(p
->szModName
,temp
);
645 PICE_strcpy(p
->szFunctionName
,pFind
);
646 DPRINT((0,"RevirtualizeBreakpointsForModule(): %s!%s\n",p
->szModName
,p
->szFunctionName
));
647 // if function name contains a '+' it's an offset
648 pFind
= p
->szFunctionName
;
651 DPRINT((0,"RevirtualizeBreakpointsForModule(): [1] %s\n",pFind
));
652 // found any offset to function
661 DPRINT((0,"RevirtualizeBreakpointsForModule(): [2] %s\n",p
->szFunctionName
));
662 if(ScanExports(p
->szFunctionName
,&ulFunctionAddress
))
664 p
->ulAddress
-= ulFunctionAddress
;
665 DPRINT((0,"RevirtualizeBreakpointsForModule(): [1] function @ %x offset = %x\n",ulFunctionAddress
,p
->ulAddress
));
669 if((ulFunctionAddress
= FindFunctionInModuleByName(p
->szFunctionName
,pMod
)) )
671 p
->ulAddress
-= ulFunctionAddress
;
672 DPRINT((0,"RevirtualizeBreakpointsForModule(): [2] function @ %x offset = %x\n",ulFunctionAddress
,p
->ulAddress
));
676 DPRINT((0,"RevirtualizeBreakpointsForModule(): Breakpoint %u could not be virtualized properly!\n",i
));
677 PICE_sprintf(tempBp
,"Breakpoint %u could not be virtualized properly!\n",i
);
678 Print(OUTPUT_WINDOW
,tempBp
);
684 DPRINT((0,"RevirtualizeBreakpointsForModule(): function for %x not found!\n",p
->ulAddress
));
685 PICE_memset(p
,0,sizeof(*p
));
693 //*************************************************************************
696 //*************************************************************************
698 NewInt3Handler:\n\t \
699 pushl $" STR(REASON_INT3
) "\n\t \
700 // call debugger loop\n\t \
701 jmp NewInt31Handler\n\t \
705 //*************************************************************************
708 //*************************************************************************
709 void InstallInt3Hook(void)
711 ULONG LocalInt3Handler
;
714 DPRINT((0,"enter InstallInt3Hook()...\n"));
719 PICE_memset(aSwBreakpoints
,0,sizeof(aSwBreakpoints
));
720 __asm__("mov $NewInt3Handler,%0"
721 :"=r" (LocalInt3Handler
)
724 OldInt3Handler
=SetGlobalInt(0x03,(ULONG
)LocalInt3Handler
);
728 DPRINT((0,"leave InstallInt3Hook()...\n"));
732 //*************************************************************************
733 // DeInstallInt3Hook()
735 //*************************************************************************
736 void DeInstallInt3Hook(void)
739 DPRINT((0,"enter DeInstallInt3Hook()...\n"));
744 RemoveAllSWBreakpoints(TRUE
);
745 SetGlobalInt(0x03,(ULONG
)OldInt3Handler
);
750 DPRINT((0,"leave DeInstallInt3Hook()...\n"));