mirror of
https://github.com/cheat-engine/cheat-engine
synced 2026-08-15 02:26:08 -04:00
241 lines
8.1 KiB
ObjectPascal
Executable file
241 lines
8.1 KiB
ObjectPascal
Executable file
unit DebuggerInterface;
|
|
{
|
|
This unit contains the base class description for the debugger interface.
|
|
The other debugger interfaces are inherited from this
|
|
}
|
|
|
|
{$mode delphi}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils{$ifdef windows},windows{$endif}{$ifndef STANDALONEDEBUG},NewKernelHandler, debuggertypedefinitions{$endif}{$ifdef darwin}, macport, macportdefines{$endif};
|
|
|
|
type
|
|
TDebuggerCapabilities=(dbcHardwareBreakpoint, dbcSoftwareBreakpoint, dbcExceptionBreakpoint, dbcDBVMBreakpoint, dbcBreakOnEntry, dbcCanUseInt1BasedBreakpoints, dbcDealsWithBreakpointsInternally);
|
|
TDebuggerCapabilitiesSet=set of TDebuggerCapabilities;
|
|
TDebuggerInterface=class
|
|
private
|
|
status: string;
|
|
statusmrew: TMultiReadExclusiveWriteSynchronizer;
|
|
function getCurrentDebugggerAttachStatus: string;
|
|
procedure setCurrentDebuggerAttachStatus(newstatus: string);
|
|
protected
|
|
fwatchpointsTriggerAfterExecution: boolean;
|
|
fmaxInstructionBreakpointCount: integer;
|
|
fmaxWatchpointBreakpointCount: integer;
|
|
fmaxSharedBreakpointCount: integer;
|
|
|
|
fDebuggerCapabilities: TDebuggerCapabilitiesSet;
|
|
fErrorString: string;
|
|
noBreakList: array of thandle;
|
|
public
|
|
name: string;
|
|
|
|
constructor create;
|
|
destructor destroy; override;
|
|
|
|
function WaitForDebugEvent(var lpDebugEvent: TDebugEvent; dwMilliseconds: DWORD): BOOL; virtual; abstract;
|
|
function ContinueDebugEvent(dwProcessId: DWORD; dwThreadId: DWORD; dwContinueStatus: DWORD): BOOL; virtual; abstract;
|
|
function SetThreadContext(hThread: THandle; const lpContext: TContext; isFrozenThread: Boolean=false): BOOL; overload; virtual;
|
|
function SetThreadContext(hThread: THandle; lpContext: pointer; isFrozenThread: Boolean=false): BOOL; overload; virtual;
|
|
{$ifndef STANDALONEDEBUG}
|
|
function SetThreadContextArm(hThread: THandle; const lpContext: TARMCONTEXT; isFrozenThread: Boolean=false): BOOL; virtual;
|
|
function SetThreadContextArm64(hThread: THandle; const lpContext: TARM64CONTEXT; isFrozenThread: Boolean=false): BOOL; virtual;
|
|
{$endif}
|
|
function GetThreadContext(hThread: THandle; var lpContext: TContext; isFrozenThread: Boolean=false): BOOL; overload; virtual;
|
|
function GetThreadContext(hThread: THandle; lpContext: pointer; isFrozenThread: Boolean=false): BOOL; overload; virtual;
|
|
{$ifndef STANDALONEDEBUG}
|
|
function GetThreadContextArm(hThread: THandle; var lpContext: TARMCONTEXT; isFrozenThread: Boolean=false): BOOL; virtual;
|
|
function GetThreadContextArm64(hThread: THandle; var lpContext: TARM64CONTEXT; isFrozenThread: Boolean=false): BOOL; virtual;
|
|
{$endif}
|
|
function DebugActiveProcess(dwProcessId: DWORD): BOOL; virtual; abstract;
|
|
function DebugActiveProcessStop(dwProcessID: DWORD): BOOL; virtual;
|
|
function GetLastBranchRecords(lbr: pointer): integer; virtual;
|
|
function isInjectedEvent: boolean; virtual;
|
|
function usesDebugRegisters: boolean; virtual;
|
|
|
|
function inNoBreakList(threadid: integer): boolean; virtual;
|
|
procedure AddToNoBreakList(threadid: integer); virtual;
|
|
procedure RemoveFromNoBreakList(threadid: integer); virtual;
|
|
|
|
function canUseIPT: boolean; virtual;
|
|
function canReportExactDebugRegisterTrigger: boolean; virtual;
|
|
function needsToAttach: boolean; virtual;
|
|
function controlsTheThreadList: boolean; virtual;
|
|
|
|
property DebuggerCapabilities: TDebuggerCapabilitiesSet read fDebuggerCapabilities;
|
|
property errorstring: string read ferrorstring;
|
|
|
|
property maxInstructionBreakpointCount: integer read fmaxInstructionBreakpointCount;
|
|
property maxWatchpointBreakpointCount: integer read fmaxWatchpointBreakpointCount;
|
|
property maxSharedBreakpointCount: integer read fmaxSharedBreakpointCount;
|
|
property watchpointsTriggerAfterExecution: boolean read fwatchpointsTriggerAfterExecution;
|
|
|
|
property debuggerAttachStatus: string read getCurrentDebugggerAttachStatus write setCurrentDebuggerAttachStatus; //threadsafe getter/setter for a string
|
|
end;
|
|
|
|
const
|
|
DBG_CONTINUE_SINGLESTEP = $00010003; //continueDebugEvent continuestatus only for DBVM BP's (and gdbserver protocol)
|
|
DBG_CONTINUE_SINGLESTEP_UNHANDLED = $00010004;
|
|
|
|
|
|
implementation
|
|
|
|
function TDebuggerInterface.getCurrentDebugggerAttachStatus: string;
|
|
begin
|
|
if statusmrew<>nil then
|
|
begin
|
|
statusmrew.Beginread;
|
|
result:=status;
|
|
statusmrew.Endread;
|
|
end;
|
|
end;
|
|
|
|
procedure TDebuggerInterface.setCurrentDebuggerAttachStatus(newstatus: string);
|
|
begin
|
|
if statusmrew<>nil then
|
|
begin
|
|
statusmrew.Beginwrite;
|
|
status:=newstatus;
|
|
statusmrew.Endwrite;
|
|
end;
|
|
end;
|
|
|
|
function TDebuggerInterface.SetThreadContext(hThread: THandle; const lpContext: TContext; isFrozenThread: Boolean=false): BOOL;
|
|
begin
|
|
result:=false;
|
|
end;
|
|
|
|
function TDebuggerInterface.SetThreadContext(hThread: THandle; lpContext: pointer; isFrozenThread: Boolean=false): BOOL;
|
|
begin
|
|
result:=SetThreadContext(hThread, PContext(lpContext)^, isFrozenThread);
|
|
end;
|
|
|
|
{$ifndef STANDALONEDEBUG}
|
|
function TDebuggerInterface.SetThreadContextArm(hThread: THandle; const lpContext: TARMCONTEXT; isFrozenThread: Boolean=false): BOOL;
|
|
begin
|
|
result:=false;
|
|
end;
|
|
|
|
function TDebuggerInterface.SetThreadContextArm64(hThread: THandle; const lpContext: TARM64CONTEXT; isFrozenThread: Boolean=false): BOOL;
|
|
begin
|
|
result:=false;
|
|
end;
|
|
|
|
function TDebuggerInterface.GetThreadContextArm(hThread: THandle; var lpContext: TARMCONTEXT; isFrozenThread: Boolean=false): BOOL;
|
|
begin
|
|
result:=false;
|
|
end;
|
|
|
|
function TDebuggerInterface.GetThreadContextArm64(hThread: THandle; var lpContext: TARM64CONTEXT; isFrozenThread: Boolean=false): BOOL;
|
|
begin
|
|
result:=false;
|
|
end;
|
|
{$endif}
|
|
|
|
function TDebuggerInterface.GetThreadContext(hThread: THandle; var lpContext: TContext; isFrozenThread: Boolean=false): BOOL;
|
|
begin
|
|
result:=false;
|
|
end;
|
|
|
|
function TDebuggerInterface.GetThreadContext(hThread: THandle; lpContext: pointer; isFrozenThread: Boolean=false): BOOL;
|
|
begin
|
|
result:=GetThreadContext(hthread, PContext(lpContext)^,isFrozenThread);
|
|
end;
|
|
|
|
|
|
function TDebuggerInterface.DebugActiveProcessStop(dwProcessID: DWORD): BOOL;
|
|
begin
|
|
//don't complain if not implemented
|
|
result:=true;
|
|
end;
|
|
|
|
function TDebuggerInterface.GetLastBranchRecords(lbr: pointer): integer;
|
|
begin
|
|
//if implemented fill in the lbr pointer with the lbr records (array of qwords) and return the count (max 16)
|
|
result:=-1;
|
|
end;
|
|
|
|
function TDebuggerInterface.isInjectedEvent: boolean;
|
|
begin
|
|
result:=false;
|
|
end;
|
|
|
|
function TDebuggerInterface.inNoBreakList(threadid: integer): boolean;
|
|
var i: integer;
|
|
begin
|
|
result:=false;
|
|
for i:=0 to length(nobreaklist)-1 do
|
|
if nobreaklist[i]=threadid then
|
|
begin
|
|
result:=true;
|
|
exit;
|
|
end;
|
|
end;
|
|
|
|
procedure TDebuggerInterface.AddToNoBreakList(threadid: integer);
|
|
begin
|
|
if inNoBreaklist(threadid) then exit;
|
|
|
|
setlength(nobreaklist, length(nobreaklist)+1);
|
|
nobreaklist[length(nobreaklist)-1]:=threadid;
|
|
end;
|
|
|
|
procedure TDebuggerInterface.RemoveFromNoBreakList(threadid: integer);
|
|
var i,j: integer;
|
|
begin
|
|
for i:=0 to length(noBreakList)-1 do
|
|
begin
|
|
if nobreaklist[i]=threadid then
|
|
begin
|
|
for j:=i to length(nobreaklist)-2 do
|
|
nobreaklist[j]:=nobreaklist[j+1];
|
|
|
|
setlength(nobreaklist, length(nobreaklist)-1);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TDebuggerInterface.canUseIPT: boolean;
|
|
begin
|
|
result:=false;
|
|
end;
|
|
|
|
function TDebuggerInterface.canReportExactDebugRegisterTrigger: boolean;
|
|
begin
|
|
result:=true;
|
|
end;
|
|
|
|
function TDebuggerInterface.needsToAttach: boolean;
|
|
begin
|
|
result:=true;
|
|
end;
|
|
|
|
function TDebuggerInterface.controlsTheThreadList: boolean;
|
|
begin
|
|
result:=true;
|
|
end;
|
|
|
|
function TDebuggerInterface.usesDebugRegisters: boolean;
|
|
begin
|
|
result:=true;
|
|
end;
|
|
|
|
constructor TDebuggerInterface.create;
|
|
begin
|
|
fwatchpointsTriggerAfterExecution:=true;
|
|
fDebuggerCapabilities:=[dbcCanUseInt1BasedBreakpoints]; //all except DBVM (which will remove this flags)
|
|
|
|
status:='Before attach';
|
|
|
|
statusmrew:=TMultiReadExclusiveWriteSynchronizer.Create;
|
|
end;
|
|
|
|
destructor TDebuggerInterface.destroy;
|
|
begin
|
|
freeandnil(statusmrew);
|
|
end;
|
|
|
|
end.
|
|
|