308 lines
8.3 KiB
ObjectPascal
308 lines
8.3 KiB
ObjectPascal
unit debuggertypedefinitions;
|
|
|
|
{$mode delphi}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, Windows, FoundCodeUnit, formchangedaddresses, frmTracerUnit,
|
|
cefuncproc, NewKernelHandler, fgl, commonTypeDefs;
|
|
|
|
type
|
|
TNewProcedureData = record
|
|
processid: dword;
|
|
processhandle: dword;
|
|
filehandle: dword;
|
|
EntryPoint: dword;
|
|
OriginalEntryByte: byte;
|
|
DotNet: boolean;
|
|
FirstBreak: boolean;
|
|
end;
|
|
|
|
|
|
|
|
type
|
|
TDebugRegisterType = (drtAny, drtExecute, drtWatch);
|
|
|
|
type
|
|
TContinueOption = (co_run=0, co_stepinto=1, co_stepover=2, co_runtill=3);
|
|
|
|
type
|
|
TBreakpointMethod = (bpmInt3=0, bpmDebugRegister=1, bpmException=2);
|
|
|
|
type
|
|
TBreakOption = (bo_Break = 0, bo_ChangeRegister = 1, bo_FindCode = 2, bo_FindWhatCodeAccesses = 3, bo_BreakAndTrace=4, bo_OnBreakpoint=5);
|
|
TBreakPointAction = TBreakOption;
|
|
|
|
type
|
|
TBreakpointTrigger = (bptExecute=0, bptAccess=1, bptWrite=2);
|
|
|
|
type
|
|
tregistermodificationBP32 = record
|
|
address: uint_ptr; //addres to break on
|
|
change_eax: BOOL;
|
|
change_ebx: BOOL;
|
|
change_ecx: BOOL;
|
|
change_edx: BOOL;
|
|
change_esi: BOOL;
|
|
change_edi: BOOL;
|
|
change_ebp: BOOL;
|
|
change_esp: BOOL;
|
|
change_eip: BOOL;
|
|
change_cf: BOOL;
|
|
change_pf: BOOL;
|
|
change_af: BOOL;
|
|
change_zf: BOOL;
|
|
change_sf: BOOL;
|
|
change_of: BOOL;
|
|
new_eax: dword;
|
|
new_ebx: dword;
|
|
new_ecx: dword;
|
|
new_edx: dword;
|
|
new_esi: dword;
|
|
new_edi: dword;
|
|
new_ebp: dword;
|
|
new_esp: dword;
|
|
new_eip: dword;
|
|
new_cf: BOOL;
|
|
new_pf: BOOL;
|
|
new_af: BOOL;
|
|
new_zf: BOOL;
|
|
new_sf: BOOL;
|
|
new_of: BOOL;
|
|
end;
|
|
|
|
type
|
|
PRegisterModificationBP32 = ^TRegisterModificationBP32;
|
|
|
|
type
|
|
tregistermodificationBP64 = record
|
|
address: uint_ptr; //addres to break on
|
|
change_eax: BOOL;
|
|
change_ebx: BOOL;
|
|
change_ecx: BOOL;
|
|
change_edx: BOOL;
|
|
change_esi: BOOL;
|
|
change_edi: BOOL;
|
|
change_ebp: BOOL;
|
|
change_esp: BOOL;
|
|
change_eip: BOOL;
|
|
change_r8: BOOL;
|
|
change_r9: BOOL;
|
|
change_r10: BOOL;
|
|
change_r11: BOOL;
|
|
change_r12: BOOL;
|
|
change_r13: BOOL;
|
|
change_r14: BOOL;
|
|
change_r15: BOOL;
|
|
change_cf: BOOL;
|
|
change_pf: BOOL;
|
|
change_af: BOOL;
|
|
change_zf: BOOL;
|
|
change_sf: BOOL;
|
|
change_of: BOOL;
|
|
new_eax: ptrUint;
|
|
new_ebx: ptrUint;
|
|
new_ecx: ptrUint;
|
|
new_edx: ptrUint;
|
|
new_esi: ptrUint;
|
|
new_edi: ptrUint;
|
|
new_ebp: ptrUint;
|
|
new_esp: ptrUint;
|
|
new_eip: ptrUint;
|
|
new_r8: ptrUint;
|
|
new_r9: ptrUint;
|
|
new_r10: ptrUint;
|
|
new_r11: ptrUint;
|
|
new_r12: ptrUint;
|
|
new_r13: ptrUint;
|
|
new_r14: ptrUint;
|
|
new_r15: ptrUint;
|
|
new_cf: BOOL;
|
|
new_pf: BOOL;
|
|
new_af: BOOL;
|
|
new_zf: BOOL;
|
|
new_sf: BOOL;
|
|
new_of: BOOL;
|
|
end;
|
|
|
|
type
|
|
PRegisterModificationBP64 = ^TRegisterModificationBP64;
|
|
|
|
{$ifdef CPU64}
|
|
type
|
|
TRegisterModificationBP = TRegisterModificationBP64;
|
|
|
|
type
|
|
PRegisterModificationBP = PRegisterModificationBP64;
|
|
{$else}
|
|
type
|
|
TRegisterModificationBP = TRegisterModificationBP32;
|
|
|
|
type
|
|
PRegisterModificationBP = PRegisterModificationBP32;
|
|
{$endif}
|
|
|
|
|
|
type
|
|
|
|
PBreakpoint = ^TBreakPoint;
|
|
|
|
TOnBreakpointEvent=function(bp: PBreakpoint; OnBreakpointContext: pointer):boolean of object;
|
|
|
|
TBreakpoint = record
|
|
{
|
|
the following 2 items: active and markedfordeletion handle the case when a
|
|
breakpoint has been removed right at the same moment it has fired and the user
|
|
thread managed to get to the critical section first
|
|
}
|
|
active: boolean; //todo: Perhaps a per/threadid activate field
|
|
//set if the debugger should handle it fully, or just skip it (but no dbg_nothandled)
|
|
markedfordeletion: boolean;
|
|
deletetickcount: dword;
|
|
deletecountdown: integer; //when markedfordeletion is set and deletecountdown hits 0, it'll get deleted
|
|
referencecount: integer; //the number of windows this bp is currently being edited in (mainly used in 'set/change condition')
|
|
|
|
//If set the next time no events take place this breakpoint will be removed
|
|
|
|
// condition: TCondition;
|
|
|
|
owner: PBreakpoint;
|
|
//in case of a multi DR/address breakpoint, removing one of these or the owner, affects the others
|
|
address: uint_ptr;
|
|
size: integer; //size of this breakpoint (can be any size in case of exception bp)
|
|
originalbyte: byte;
|
|
|
|
originalaccessrights: TAccessRights;
|
|
|
|
breakpointMethod: TBreakpointMethod;
|
|
breakpointAction: TBreakOption;
|
|
breakpointTrigger: TBreakpointTrigger;
|
|
debugRegister: integer;
|
|
//if debugRegister bp this will hold which debug register is used for it
|
|
|
|
FoundcodeDialog: TFoundcodedialog;
|
|
frmchangedaddresses: Tfrmchangedaddresses;
|
|
frmTracer: TfrmTracer;
|
|
tracecount: integer;
|
|
traceendcondition: pchar;
|
|
tracestepOver: boolean; //when set the tracer will step over instead of single step
|
|
|
|
//set if it's a bpaFetchRegistersandcontinue set on memory access
|
|
//ChangedAddresses: TfrmChangedAddresses; //set if it's a bpaFetchRegistersandcontinue set on execute
|
|
ThreadID: DWORD;
|
|
//set if the breakpoint is for one specific thread, ignore breaks if it happens on other threads
|
|
|
|
OneTimeOnly: boolean; //true if the breakpoint should be removed after the first time it is hit
|
|
StepOverBp: boolean;
|
|
|
|
changereg: tregistermodificationBP;
|
|
|
|
conditonalbreakpoint: record
|
|
script: pchar;
|
|
easymode: boolean;
|
|
end;
|
|
|
|
OnBreakpoint: TOnBreakpointEvent; //method to be called by the debuggerthread when this breakpoint triggers
|
|
OnBreakpointContext: pointer;
|
|
end;
|
|
|
|
|
|
TBreakpointSplit = record //the breakpointsplit type is used by GetBreakpointList
|
|
address: uint_ptr; //address alligned on size
|
|
size: integer; //1, 2 or 4
|
|
end;
|
|
TBreakpointSplitArray = array of TBreakpointSplit;
|
|
TBreakpointList=TFPGList<PBreakpoint>;
|
|
|
|
function BreakPointTriggerIsWatchpoint(bpt: TBreakpointTrigger): boolean; inline;
|
|
|
|
function breakpointTriggerToString(bpt: TBreakpointTrigger): string;
|
|
function breakpointMethodToString(bpm: TBreakpointMethod): string;
|
|
function breakpointActionToString(bpa: TBreakpointAction): string;
|
|
|
|
//kernel debug
|
|
function SizeToBreakLength(size: integer): TBreakLength;
|
|
function BreakPointTriggerToBreakType(bpt: TBreakpointTrigger): TBreakType;
|
|
|
|
|
|
|
|
var int3byte: byte = $cc;
|
|
|
|
implementation
|
|
|
|
//this is a new one... (rebuild as usual)
|
|
resourcestring
|
|
rsOnExecute = 'On Execute';
|
|
rsOnWrite = 'On Write';
|
|
rsOnReadWrite = 'On Read/Write';
|
|
rsSoftwareBreakpoint = 'Software Breakpoint';
|
|
rsHardwareBreakpoint = 'Hardware Breakpoint';
|
|
rsExceptionBreakpoint = 'Exception Breakpoint';
|
|
rsBreak = 'Break';
|
|
rsChangeReg = 'Change reg';
|
|
rsFindCode = 'Find code';
|
|
rsFindCodeAccess = 'Find code access';
|
|
rsBreakAndTrace = 'Break and trace';
|
|
|
|
function SizeToBreakLength(size: integer): TBreakLength;
|
|
begin
|
|
case size of
|
|
1: result:=bl_1byte;
|
|
2: result:=bl_2byte;
|
|
4: result:=bl_4byte;
|
|
8: result:=bl_8byte;
|
|
else
|
|
result:=bl_1byte;
|
|
end;
|
|
end;
|
|
|
|
function BreakPointTriggerIsWatchpoint(bpt: TBreakpointTrigger): boolean; inline;
|
|
begin
|
|
result:=bpt in [bptAccess, bptWrite];
|
|
end;
|
|
|
|
function BreakPointTriggerToBreakType(bpt: TBreakpointTrigger): TBreakType;
|
|
begin
|
|
case bpt of
|
|
bptExecute: result:=bt_OnInstruction;
|
|
bptAccess: result:=bt_OnReadsAndWrites;
|
|
bptWrite: result:=bt_OnWrites;
|
|
else
|
|
result:=bt_OnInstruction;
|
|
end;
|
|
end;
|
|
|
|
|
|
function breakpointTriggerToString(bpt: TBreakpointTrigger): string;
|
|
begin
|
|
case bpt of
|
|
bptExecute: result:=rsOnExecute;
|
|
bptWrite: result:=rsOnWrite;
|
|
bptAccess: result:=rsOnReadWrite;
|
|
end;
|
|
end;
|
|
|
|
function BreakpointMethodToString(bpm: TBreakpointMethod): string;
|
|
begin
|
|
case bpm of
|
|
bpmInt3: result:=rsSoftwareBreakpoint;
|
|
bpmDebugRegister: result:=rsHardwareBreakpoint;
|
|
bpmException: result:=rsExceptionBreakpoint;
|
|
end;
|
|
end;
|
|
|
|
function breakpointActionToString(bpa: TBreakpointAction): string;
|
|
begin
|
|
case bpa of
|
|
bo_Break: result:=rsBreak;
|
|
bo_ChangeRegister: result:=rsChangeReg;
|
|
bo_FindCode: result:=rsFindCode;
|
|
bo_FindWhatCodeAccesses: result:=rsFindCodeAccess;
|
|
bo_BreakAndTrace: result:=rsBreakAndTrace;
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|