mirror of
https://github.com/cheat-engine/cheat-engine
synced 2026-08-15 02:26:08 -04:00
347 lines
8.6 KiB
ObjectPascal
Executable file
347 lines
8.6 KiB
ObjectPascal
Executable file
unit debuggertypedefinitions;
|
|
|
|
{$mode delphi}
|
|
|
|
interface
|
|
|
|
uses
|
|
{$ifdef darwin}
|
|
macport,
|
|
{$endif}
|
|
{$ifdef windows}
|
|
Windows,
|
|
{$endif}
|
|
Classes, SysUtils,
|
|
cefuncproc, NewKernelHandler, 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, bpmDBVM=3, bpmDBVMNative=4, bpmGDB=5);
|
|
|
|
type
|
|
TBreakOption = (bo_Break = 0, bo_ChangeRegister = 1, bo_FindCode = 2, bo_FindWhatCodeAccesses = 3, bo_BreakAndTrace=4, bo_OnBreakpoint=5, bo_ChangeRegisterEx = 6);
|
|
TBreakPointAction = TBreakOption;
|
|
|
|
type
|
|
TBreakpointTrigger = (bptExecute=0, bptAccess=1, bptWrite=2);
|
|
|
|
{$ifdef cpu32}
|
|
M128A= record
|
|
low,high: qword;
|
|
end;
|
|
{$endif}
|
|
|
|
TXMMFIELDS=array [0..3] of DWORD;
|
|
PXMMFIELDS=^TXMMFIELDS;
|
|
|
|
TRegisterModificationFloatList=bitpacked record
|
|
change_fp0: 0..1;
|
|
change_fp1: 0..1;
|
|
change_fp2: 0..1;
|
|
change_fp3: 0..1;
|
|
change_fp4: 0..1;
|
|
change_fp5: 0..1;
|
|
change_fp6: 0..1;
|
|
change_fp7: 0..1;
|
|
end;
|
|
PRegisterModificationFloatList=^TRegisterModificationFloatList;
|
|
|
|
TRegisterModificationXMMListSingleEntry=bitpacked record
|
|
change_part1: 0..1;
|
|
change_part2: 0..1;
|
|
change_part3: 0..1;
|
|
change_part4: 0..1;
|
|
end;
|
|
PRegisterModificationXMMListSingleEntry=^TRegisterModificationXMMListSingleEntry;
|
|
|
|
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;
|
|
|
|
change_FP: BYTE; //binary, each bit is a new FP
|
|
new_FP0: double;
|
|
new_FP1: double;
|
|
new_FP2: double;
|
|
new_FP3: double;
|
|
new_FP4: double;
|
|
new_FP5: double;
|
|
new_FP6: double;
|
|
new_FP7: double;
|
|
|
|
change_XMM: DWORD; //binary, each nibble is an XMM register, and each bit of the nibble is a dword part of the xmm reg
|
|
new_XMM0: TXMMFIELDS;
|
|
new_XMM1: TXMMFIELDS;
|
|
new_XMM2: TXMMFIELDS;
|
|
new_XMM3: TXMMFIELDS;
|
|
new_XMM4: TXMMFIELDS;
|
|
new_XMM5: TXMMFIELDS;
|
|
new_XMM6: TXMMFIELDS;
|
|
new_XMM7: TXMMFIELDS;
|
|
|
|
usesDouble: BYTE; //each bit specifies an xmm field what weas edited using a double specifier
|
|
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;
|
|
|
|
change_FP: BYTE; //binary, each bit is a new FP
|
|
new_FP0: M128A; //only need the 10 bytes
|
|
new_FP1: M128A;
|
|
new_FP2: M128A;
|
|
new_FP3: M128A;
|
|
new_FP4: M128A;
|
|
new_FP5: M128A;
|
|
new_FP6: M128A;
|
|
new_FP7: M128A;
|
|
|
|
change_XMM: QWORD; //binary, each nibble is an XMM register, and each bit of the nibble is a dword part of the xmm reg
|
|
new_XMM0: TXMMFIELDS;
|
|
new_XMM1: TXMMFIELDS;
|
|
new_XMM2: TXMMFIELDS;
|
|
new_XMM3: TXMMFIELDS;
|
|
new_XMM4: TXMMFIELDS;
|
|
new_XMM5: TXMMFIELDS;
|
|
new_XMM6: TXMMFIELDS;
|
|
new_XMM7: TXMMFIELDS;
|
|
new_XMM8: TXMMFIELDS;
|
|
new_XMM9: TXMMFIELDS;
|
|
new_XMM10: TXMMFIELDS;
|
|
new_XMM11: TXMMFIELDS;
|
|
new_XMM12: TXMMFIELDS;
|
|
new_XMM13: TXMMFIELDS;
|
|
new_XMM14: TXMMFIELDS;
|
|
new_XMM15: TXMMFIELDS;
|
|
|
|
//for gui purposes only:
|
|
usesDouble: WORD; //each bit specifies an xmm field what was edited using a double specifier
|
|
|
|
end;
|
|
|
|
type
|
|
PRegisterModificationBP64 = ^TRegisterModificationBP64;
|
|
|
|
{$ifdef CPU64}
|
|
type
|
|
TRegisterModificationBP = TRegisterModificationBP64;
|
|
|
|
type
|
|
PRegisterModificationBP = PRegisterModificationBP64;
|
|
{$else}
|
|
type
|
|
TRegisterModificationBP = TRegisterModificationBP32;
|
|
|
|
type
|
|
PRegisterModificationBP = PRegisterModificationBP32;
|
|
{$endif}
|
|
|
|
|
|
TRegisterModificationBPEx=record
|
|
address: ptruint;
|
|
mask: pointer; //same size as the context. Bit 1 means it gets changed, else unchanged
|
|
context: Pointer; //full context to set. Bits get set according to the bits in the contextmask (currentcontext.field=(currentcontext.field and (not mask.field)) or context.field
|
|
end;
|
|
|
|
PRegisterModificationBPEx = ^TRegisterModificationBPEx;
|
|
|
|
|
|
|
|
// 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';
|
|
rsDBVMBreakpoint = 'DBVM Breakpoint';
|
|
rsDBVMNativeBreakpoint = 'DBVM-Level 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;
|
|
else
|
|
result:='Error';
|
|
end;
|
|
end;
|
|
|
|
function BreakpointMethodToString(bpm: TBreakpointMethod): string;
|
|
begin
|
|
case bpm of
|
|
bpmInt3: result:=rsSoftwareBreakpoint;
|
|
bpmDebugRegister: result:=rsHardwareBreakpoint;
|
|
bpmException: result:=rsExceptionBreakpoint;
|
|
bpmDBVM: result:=rsDBVMBreakpoint;
|
|
bpmDBVMNative: result:=rsDBVMNativeBreakpoint;
|
|
else
|
|
result:='Error';
|
|
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;
|
|
else
|
|
result:='Error';
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|