665 lines
21 KiB
ObjectPascal
Executable File
665 lines
21 KiB
ObjectPascal
Executable File
unit NetworkDebuggerInterface;
|
|
|
|
{$mode delphi}
|
|
|
|
interface
|
|
|
|
uses
|
|
|
|
{$ifdef windows}
|
|
jwawindows, windows,
|
|
{$endif}
|
|
Classes, SysUtils,cefuncproc, newkernelhandler,
|
|
DebuggerInterface, networkInterface, networkInterfaceApi, contnrs{$ifdef darwin},macport, macportdefines{$endif};
|
|
|
|
type
|
|
TNetworkDebuggerInterface=class(TDebuggerInterface)
|
|
private
|
|
handle: THandle;
|
|
lastevent: TNetworkDebugEvent;
|
|
fsinglestepNextContinue: boolean;
|
|
|
|
public
|
|
function WaitForDebugEvent(var lpDebugEvent: TDebugEvent; dwMilliseconds: DWORD): BOOL; override;
|
|
function ContinueDebugEvent(dwProcessId: DWORD; dwThreadId: DWORD; dwContinueStatus: DWORD): BOOL; override;
|
|
function SetThreadContext(hThread: THandle; const lpContext: TContext; isFrozenThread: Boolean=false): BOOL; override;
|
|
function GetThreadContext(hThread: THandle; var lpContext: TContext; isFrozenThread: Boolean=false): BOOL; override;
|
|
|
|
function SetThreadContextArm(hThread: THandle; const lpContext: TArmContext; isFrozenThread: Boolean=false): BOOL; override;
|
|
function GetThreadContextArm(hThread: THandle; var lpContext: TArmContext; isFrozenThread: Boolean=false): BOOL; override;
|
|
function GetThreadContextArm64(hThread: THandle; var lpContext: TArm64Context; isFrozenThread: Boolean=false): BOOL; override;
|
|
function SetThreadContextArm64(hThread: THandle; const lpContext: TArm64Context; isFrozenThread: Boolean=false): BOOL; override;
|
|
|
|
|
|
function GetLastBranchRecords(lbr: pointer): integer; override;
|
|
function canReportExactDebugRegisterTrigger: boolean; override;
|
|
|
|
function DebugActiveProcess(dwProcessId: DWORD): WINBOOL; override;
|
|
property SingleStepNextContinue: boolean read fSingleStepNextContinue write fSingleStepNextContinue;
|
|
|
|
destructor destroy; override;
|
|
constructor create;
|
|
end;
|
|
|
|
|
|
function SetThreadContext(hThread: THandle; const lpContext: TContext): BOOL;
|
|
function GetThreadContext(hThread: THandle; var lpContext: TContext): BOOL;
|
|
function SetThreadContextArm(hThread: THandle; const lpContext: TArmContext): BOOL;
|
|
function GetThreadContextArm(hThread: THandle; var lpContext: TArmContext): BOOL;
|
|
function GetThreadContextArm64(hThread: THandle; var lpContext: TArm64Context): BOOL;
|
|
function SetThreadContextArm64(hThread: THandle; const lpContext: TArm64Context): BOOL;
|
|
|
|
|
|
|
|
|
|
implementation
|
|
|
|
uses debuggertypedefinitions, ProcessHandlerUnit;
|
|
|
|
const
|
|
networkContextType_X86=0;
|
|
networkContextType_X86_64=1;
|
|
networkContextType_Arm=2;
|
|
networkContextType_Arm64=3;
|
|
|
|
type
|
|
TNetworkX86_32Context=packed record
|
|
ebx: dword;
|
|
ecx: dword;
|
|
edx: dword;
|
|
esi: dword;
|
|
edi: dword;
|
|
ebp: dword;
|
|
eax: dword;
|
|
ds: integer;
|
|
es: integer;
|
|
fs: integer;
|
|
gs: integer;
|
|
orig_eax: dword;
|
|
eip: dword;
|
|
cs: integer;
|
|
eflags: dword;
|
|
esp: dword;
|
|
ss: integer;
|
|
|
|
fp: TXmmSaveArea;
|
|
end;
|
|
|
|
PNetworkX86_32Context=^TNetworkX86_32Context;
|
|
|
|
TNetworkX86_64Context=packed record
|
|
r15: qword;
|
|
r14: qword;
|
|
r13: qword;
|
|
r12: qword;
|
|
rbp: qword;
|
|
rbx: qword;
|
|
r11: qword;
|
|
r10: qword;
|
|
r9: qword;
|
|
r8: qword;
|
|
rax: qword;
|
|
rcx: qword;
|
|
rdx: qword;
|
|
rsi: qword;
|
|
rdi: qword;
|
|
orig_rax: qword;
|
|
rip: qword;
|
|
cs: qword;
|
|
eflags: qword;
|
|
rsp: qword;
|
|
ss: qword;
|
|
fs_base: qword;
|
|
gs_base: qword;
|
|
ds: qword;
|
|
es: qword;
|
|
fs: qword;
|
|
gs: qword;
|
|
fp: TXmmSaveArea;
|
|
end;
|
|
PNetworkX86_64Context=^TNetworkX86_64Context;
|
|
|
|
|
|
TNetworkARM_32Context=packed record
|
|
R0: DWORD;
|
|
R1: DWORD;
|
|
R2: DWORD;
|
|
R3: DWORD;
|
|
R4: DWORD;
|
|
R5: DWORD;
|
|
R6: DWORD;
|
|
R7: DWORD;
|
|
R8: DWORD;
|
|
R9: DWORD;
|
|
R10: DWORD;
|
|
FP: DWORD;
|
|
IP: DWORD;
|
|
SP: DWORD;
|
|
LR: DWORD;
|
|
PC: DWORD;
|
|
CPSR: DWORD;
|
|
ORIG_R0: DWORD;
|
|
|
|
fpu: record
|
|
regs: array [0..31] of QWORD;
|
|
control: DWORD;
|
|
end;
|
|
end;
|
|
|
|
TNetworkARM_64Context=TARM64CONTEXT;
|
|
|
|
TNetworkContext=packed record
|
|
contextsize: uint32;
|
|
contexttype: uint32; //0=x86, 1=x86_64, 2=arm, 3=arm64
|
|
case integer of //contexttype
|
|
0: (contextx86: TNetworkX86_32Context);
|
|
1: (contextx86_64: TNetworkX86_64Context);
|
|
2: (contextarm32: TNetworkARM_32Context);
|
|
3: (contextarm64: TNetworkARM_64Context);
|
|
end;
|
|
PNetworkContext=^TNetworkContext;
|
|
|
|
|
|
function SetThreadContext(hThread: THandle; const lpContext: TContext): bool;
|
|
var
|
|
context: TNetworkContext;
|
|
c: TCEConnection=nil;
|
|
begin
|
|
c:=getConnection;
|
|
if c<>nil then
|
|
begin
|
|
{$ifdef cpu64}
|
|
if processhandler.is64Bit then
|
|
begin
|
|
context.contextsize:=sizeof(TNetworkX86_64Context)+8;
|
|
context.contexttype:=1; //x86_64
|
|
|
|
context.contextx86_64.r15:=lpcontext.r15;
|
|
context.contextx86_64.r14:=lpcontext.r14;
|
|
context.contextx86_64.r13:=lpcontext.r13;
|
|
context.contextx86_64.r12:=lpcontext.r12;
|
|
context.contextx86_64.rbp:=lpcontext.rbp;
|
|
context.contextx86_64.rbx:=lpcontext.Rbx;
|
|
context.contextx86_64.r11:=lpcontext.R11;
|
|
context.contextx86_64.r10:=lpcontext.R10;
|
|
context.contextx86_64.r9:= lpcontext.R9;
|
|
context.contextx86_64.r8:= lpcontext.R8;
|
|
context.contextx86_64.rax:=lpcontext.Rax;
|
|
context.contextx86_64.rcx:=lpcontext.Rcx;
|
|
context.contextx86_64.rdx:=lpcontext.Rdx;
|
|
context.contextx86_64.rsi:=lpcontext.Rsi;
|
|
context.contextx86_64.rdi:=lpcontext.Rdi;
|
|
|
|
context.contextx86_64.orig_rax:=lpcontext.P1Home;
|
|
context.contextx86_64.rip:=lpcontext.rip;
|
|
context.contextx86_64.cs:=lpcontext.SegCs;
|
|
context.contextx86_64.eflags:=lpcontext.EFlags;
|
|
context.contextx86_64.rsp:=lpcontext.rsp;
|
|
context.contextx86_64.ss:=lpcontext.Segss;
|
|
context.contextx86_64.fs_base:=lpcontext.P2Home;
|
|
context.contextx86_64.gs_base:=lpcontext.P3Home;
|
|
context.contextx86_64.ds:=lpcontext.Segds;
|
|
context.contextx86_64.es:=lpcontext.Seges;
|
|
context.contextx86_64.fs:=lpcontext.Segfs;
|
|
context.contextx86_64.gs:=lpcontext.Seggs;
|
|
context.contextx86_64.fp:=lpcontext.FltSave;
|
|
end
|
|
else
|
|
{$endif}
|
|
begin
|
|
context.contextsize:=sizeof(TNetworkX86_64Context)+8;
|
|
context.contexttype:=0; // x86
|
|
|
|
context.contextx86.ebx:=lpcontext.{$ifdef cpu64}rbx{$else}ebx{$endif};
|
|
context.contextx86.ecx:=lpcontext.{$ifdef cpu64}rcx{$else}ecx{$endif};
|
|
context.contextx86.edx:=lpcontext.{$ifdef cpu64}rdx{$else}edx{$endif};
|
|
context.contextx86.esi:=lpcontext.{$ifdef cpu64}rsi{$else}esi{$endif};
|
|
context.contextx86.edi:=lpcontext.{$ifdef cpu64}rdi{$else}edi{$endif};
|
|
context.contextx86.ebp:=lpcontext.{$ifdef cpu64}rbp{$else}ebp{$endif};
|
|
context.contextx86.eax:=lpcontext.{$ifdef cpu64}rax{$else}eax{$endif};
|
|
context.contextx86.ds:=lpcontext.segds;
|
|
context.contextx86.es:=lpcontext.seges;
|
|
context.contextx86.fs:=lpcontext.segfs;
|
|
context.contextx86.gs:=lpcontext.seggs;
|
|
context.contextx86.eip:=lpcontext.{$ifdef cpu64}rip{$else}eip{$endif};
|
|
context.contextx86.cs:=lpcontext.segcs;
|
|
context.contextx86.eflags:=lpcontext.EFlags;
|
|
context.contextx86.esp:=lpcontext.{$ifdef cpu64}rsp{$else}esp{$endif};
|
|
context.contextx86.ss:=lpcontext.segss;
|
|
context.contextx86.fp:=lpcontext.{$ifdef cpu64}FltSave{$else}ext{$endif};
|
|
end;
|
|
|
|
|
|
result:=c.setContext(processhandle, hThread, @context, context.contextsize);
|
|
end;
|
|
end;
|
|
|
|
|
|
function GetThreadContext(hThread: THandle; var lpContext: TContext): BOOL;
|
|
var
|
|
context: PNetworkContext=nil;
|
|
c: TCEConnection=nil;
|
|
begin
|
|
result:=false;
|
|
|
|
zeromemory(@lpContext, sizeof(TContext));
|
|
|
|
c:=getConnection;
|
|
if c<>nil then
|
|
begin
|
|
context:=c.AllocateAndGetContext(processhandle, hThread);
|
|
try
|
|
if (context<>nil) and (processhandler.SystemArchitecture=archX86) then
|
|
begin
|
|
{$ifdef cpu64}
|
|
if processhandler.is64Bit then
|
|
begin
|
|
if context^.contexttype<>networkContextType_X86_64 then
|
|
begin
|
|
OutputDebugString('Expected X86_64 context, received type '+context^.contexttype.ToString);
|
|
exit(false);
|
|
end;
|
|
lpcontext.r15:=context^.contextx86_64.r15;
|
|
lpcontext.r14:=context^.contextx86_64.r14;
|
|
lpcontext.r13:=context^.contextx86_64.r13;
|
|
lpcontext.r12:=context^.contextx86_64.r12;
|
|
lpcontext.rbp:=context^.contextx86_64.rbp;
|
|
lpcontext.Rbx:=context^.contextx86_64.rbx;
|
|
lpcontext.R11:=context^.contextx86_64.r11;
|
|
lpcontext.R10:=context^.contextx86_64.r10;
|
|
lpcontext.R9:=context^.contextx86_64.r9;
|
|
lpcontext.R8:=context^.contextx86_64.r8;
|
|
lpcontext.Rax:=context^.contextx86_64.rax;
|
|
lpcontext.Rcx:=context^.contextx86_64.rcx;
|
|
lpcontext.Rdx:=context^.contextx86_64.rdx;
|
|
lpcontext.Rsi:=context^.contextx86_64.rsi;
|
|
lpcontext.Rdi:=context^.contextx86_64.rdi;
|
|
|
|
lpcontext.P1Home:=context^.contextx86_64.orig_rax;
|
|
lpcontext.rip:=context^.contextx86_64.rip;
|
|
lpcontext.SegCs:=context^.contextx86_64.cs;
|
|
lpcontext.EFlags:=context^.contextx86_64.eflags;
|
|
lpcontext.rsp:=context^.contextx86_64.rsp;
|
|
lpcontext.Segss:=context^.contextx86_64.ss;
|
|
lpcontext.P2Home:=context^.contextx86_64.fs_base;
|
|
lpcontext.P3Home:=context^.contextx86_64.gs_base;
|
|
lpcontext.Segds:=context^.contextx86_64.ds;
|
|
lpcontext.Seges:=context^.contextx86_64.es;
|
|
lpcontext.Segfs:=context^.contextx86_64.fs;
|
|
lpcontext.Seggs:=context^.contextx86_64.gs;
|
|
lpcontext.FltSave:=context^.contextx86_64.fp;
|
|
end
|
|
else
|
|
{$endif}
|
|
begin
|
|
if context^.contexttype<>networkContextType_X86 then
|
|
begin
|
|
OutputDebugString('Expected X86_32 context, received type '+context^.contexttype.ToString);
|
|
exit(false);
|
|
end;
|
|
|
|
lpcontext.{$ifdef cpu64}rbx{$else}ebx{$endif}:=context^.contextx86.ebx;
|
|
lpcontext.{$ifdef cpu64}rcx{$else}ecx{$endif}:=context^.contextx86.ecx;
|
|
lpcontext.{$ifdef cpu64}rdx{$else}edx{$endif}:=context^.contextx86.edx;
|
|
lpcontext.{$ifdef cpu64}rsi{$else}esi{$endif}:=context^.contextx86.esi;
|
|
lpcontext.{$ifdef cpu64}rdi{$else}edi{$endif}:=context^.contextx86.edi;
|
|
lpcontext.{$ifdef cpu64}rbp{$else}ebp{$endif}:=context^.contextx86.ebp;
|
|
lpcontext.{$ifdef cpu64}rax{$else}eax{$endif}:=context^.contextx86.eax;
|
|
lpcontext.segds:=context^.contextx86.ds;
|
|
lpcontext.seges:=context^.contextx86.es;
|
|
lpcontext.segfs:=context^.contextx86.fs;
|
|
lpcontext.seggs:=context^.contextx86.gs;
|
|
|
|
lpcontext.{$ifdef cpu64}rip{$else}eip{$endif}:=context^.contextx86.eip;
|
|
lpcontext.segcs:=context^.contextx86.cs;
|
|
lpcontext.EFlags:=context^.contextx86.eflags;
|
|
lpcontext.{$ifdef cpu64}rsp{$else}esp{$endif}:=context^.contextx86.esp;
|
|
lpcontext.segss:=context^.contextx86.ss;
|
|
lpcontext.{$ifdef cpu64}FltSave{$else}ext{$endif}:=context^.contextx86.fp;
|
|
end;
|
|
end; //you should use GetThreadContextArm
|
|
finally
|
|
if context<>nil then
|
|
FreeMemAndNil(context);
|
|
end;
|
|
end;
|
|
|
|
result:=lpContext.{$ifdef cpu64}rip{$else}eip{$endif}<>0;
|
|
end;
|
|
|
|
function SetThreadContextArm(hThread: THandle; const lpContext: TArmContext): BOOL;
|
|
var
|
|
carm: TNetworkContext;
|
|
c: TCEConnection=nil;
|
|
begin
|
|
c:=getConnection;
|
|
if c<>nil then
|
|
begin
|
|
carm.contextsize:=sizeof(TNetworkARM_32Context)+8;
|
|
carm.contexttype:=2; //arm 32
|
|
|
|
|
|
|
|
carm.contextarm32.R0:=lpContext.R0;
|
|
carm.contextarm32.R1:=lpContext.R1;
|
|
carm.contextarm32.R2:=lpContext.R2;
|
|
carm.contextarm32.R3:=lpContext.R3;
|
|
carm.contextarm32.R4:=lpContext.R4;
|
|
carm.contextarm32.R5:=lpContext.R5;
|
|
carm.contextarm32.R6:=lpContext.R6;
|
|
carm.contextarm32.R7:=lpContext.R7;
|
|
carm.contextarm32.R8:=lpContext.R8;
|
|
carm.contextarm32.R9:=lpContext.R9;
|
|
carm.contextarm32.R10:=lpContext.R10;
|
|
carm.contextarm32.FP:=lpContext.FP;
|
|
carm.contextarm32.IP:=lpContext.IP;
|
|
carm.contextarm32.SP:=lpContext.SP;
|
|
carm.contextarm32.LR:=lpContext.LR;
|
|
carm.contextarm32.PC:=lpContext.PC and $fffffffe;
|
|
carm.contextarm32.CPSR:=lpContext.CPSR;
|
|
carm.contextarm32.ORIG_R0:=lpContext.ORIG_R0;
|
|
|
|
CopyMemory(@carm.contextarm32.fpu.regs[0], @lpContext.fpu[0], 32*sizeof(qword));
|
|
carm.contextarm32.fpu.control:=lpContext.fpureg;
|
|
|
|
result:=c.setContext(processhandle, hThread, @carm, carm.contextsize);
|
|
end;
|
|
end;
|
|
|
|
function GetThreadContextArm(hThread: THandle; var lpContext: TArmContext): BOOL;
|
|
var
|
|
carm: PNetworkContext=nil;
|
|
c: TCEConnection=nil;
|
|
begin
|
|
result:=false;
|
|
|
|
c:=getConnection;
|
|
if c<>nil then
|
|
begin
|
|
carm:=c.AllocateAndGetContext(processhandle, hThread);
|
|
try
|
|
if (carm<>nil) and (processhandler.SystemArchitecture=archARM) then
|
|
begin
|
|
if processhandler.is64Bit then
|
|
begin
|
|
lpContext.PC:=$64646464; //holder for 64 bit for now
|
|
end
|
|
else
|
|
begin
|
|
if carm^.contexttype<>networkContextType_Arm then
|
|
begin
|
|
OutputDebugString('Expected ARM context, received type '+carm^.contexttype.ToString);
|
|
exit(false);
|
|
end;
|
|
|
|
lpContext.R0:=carm^.contextarm32.R0;
|
|
lpContext.R1:=carm^.contextarm32.R1;
|
|
lpContext.R2:=carm^.contextarm32.R2;
|
|
lpContext.R3:=carm^.contextarm32.R3;
|
|
lpContext.R4:=carm^.contextarm32.R4;
|
|
lpContext.R5:=carm^.contextarm32.R5;
|
|
lpContext.R6:=carm^.contextarm32.R6;
|
|
lpContext.R7:=carm^.contextarm32.R7;
|
|
lpContext.R8:=carm^.contextarm32.R8;
|
|
lpContext.R9:=carm^.contextarm32.R9;
|
|
lpContext.R10:=carm^.contextarm32.R10;
|
|
lpContext.FP:=carm^.contextarm32.FP;
|
|
lpContext.IP:=carm^.contextarm32.IP;
|
|
lpContext.SP:=carm^.contextarm32.SP;
|
|
lpContext.LR:=carm^.contextarm32.LR;
|
|
lpContext.PC:=carm^.contextarm32.PC;
|
|
lpContext.CPSR:=carm^.contextarm32.CPSR;
|
|
lpContext.ORIG_R0:=carm^.contextarm32.ORIG_R0;
|
|
|
|
if (lpContext.CPSR and (1 shl 5))<>0 then //Thumb bit
|
|
lpContext.PC:=lpContext.PC or 1; //quick hack to identify that thumb is used
|
|
|
|
|
|
CopyMemory(@lpContext.fpu[0], @carm^.contextarm32.fpu.regs[0], 32*sizeof(qword) );
|
|
lpcontext.fpureg:=carm^.contextarm32.fpu.control;
|
|
|
|
|
|
result:=true;
|
|
end;
|
|
end; //else use GetThreadContext
|
|
finally
|
|
if (carm<>nil) then
|
|
FreeMemAndNil(carm);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
|
|
function GetThreadContextArm64(hThread: THandle; var lpContext: TArm64Context): BOOL;
|
|
var
|
|
carm64: PNetworkContext=nil;
|
|
c: TCEConnection=nil;
|
|
begin
|
|
result:=false;
|
|
|
|
c:=getConnection;
|
|
if c<>nil then
|
|
begin
|
|
carm64:=c.AllocateAndGetContext(processhandle, hThread);
|
|
try
|
|
|
|
if (carm64<>nil) and (processhandler.SystemArchitecture=archArm) then
|
|
begin
|
|
if processhandler.is64Bit then
|
|
begin
|
|
if carm64^.contexttype<>networkContextType_Arm64 then
|
|
begin
|
|
OutputDebugString('Expected ARM64 context, received type '+carm64^.contexttype.ToString);
|
|
exit(false);
|
|
end;
|
|
|
|
lpContext:=carm64^.contextarm64;
|
|
result:=true;
|
|
end; //else use GetThreadContextArm()
|
|
end; //else use GetThreadContext
|
|
finally
|
|
if (carm64<>nil) then
|
|
FreeMemAndNil(carm64);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function SetThreadContextArm64(hThread: THandle; const lpContext: TArm64Context): BOOL;
|
|
var
|
|
carm64: TNetworkContext;
|
|
c: TCEConnection=nil;
|
|
begin
|
|
c:=getConnection;
|
|
if c<>nil then
|
|
begin
|
|
carm64.contextsize:=sizeof(TNetworkARM_64Context)+8;
|
|
carm64.contexttype:=3; //arm64
|
|
carm64.contextarm64:=lpContext;
|
|
|
|
result:=c.setContext(processhandle, hThread, @carm64, carm64.contextsize);
|
|
end;
|
|
end;
|
|
|
|
|
|
|
|
|
|
function TNetworkDebuggerInterface.WaitForDebugEvent(var lpDebugEvent: TDebugEvent; dwMilliseconds: DWORD): BOOL;
|
|
var
|
|
c: TCEConnection;
|
|
begin
|
|
|
|
result:=false;
|
|
c:=getConnection;
|
|
if c<>nil then
|
|
begin
|
|
lastevent.signal:=5;
|
|
|
|
result:=c.WaitForDebugEvent(handle, dwMilliseconds*5, lastevent);
|
|
|
|
if result then
|
|
begin
|
|
//convert it to 'something' useful
|
|
lpDebugEvent.dwThreadId:=lastevent.threadid;
|
|
lpDebugEvent.dwProcessId:=processid;
|
|
|
|
case lastevent.signal of
|
|
-1 : //create thread
|
|
begin
|
|
lpDebugEvent.dwDebugEventCode:=CREATE_THREAD_DEBUG_EVENT;
|
|
lpDebugEvent.CreateThread.hThread:=lastevent.threadid;
|
|
end;
|
|
|
|
-2 : //create process
|
|
begin
|
|
lpDebugEvent.dwDebugEventCode:=CREATE_PROCESS_DEBUG_EVENT;
|
|
lpDebugEvent.CreateProcessInfo.hProcess:=handle;
|
|
lpDebugEvent.CreateProcessInfo.hThread:=lastevent.threadid;
|
|
|
|
//set the breakpoint capability
|
|
fmaxInstructionBreakpointCount:=lastevent.createProcess.maxBreakpointCount;
|
|
fmaxWatchpointBreakpointCount:=lastevent.createProcess.maxWatchpointCount;
|
|
fmaxSharedBreakpointCount:=lastevent.createProcess.maxSharedBreakpoints;
|
|
end;
|
|
|
|
5: //SIGTRAP
|
|
begin
|
|
lpDebugEvent.dwDebugEventCode:=EXCEPTION_DEBUG_EVENT;
|
|
lpDebugEvent.Exception.dwFirstChance:=1;
|
|
lpDebugEvent.Exception.ExceptionRecord.NumberParameters:=0;
|
|
|
|
lpDebugEvent.Exception.ExceptionRecord.ExceptionCode:=EXCEPTION_SINGLE_STEP;
|
|
lpDebugEvent.Exception.ExceptionRecord.ExceptionAddress:=pointer(lastevent.address);
|
|
|
|
end;
|
|
|
|
19: //sigstop
|
|
begin
|
|
//just ignore. continue and return that no stop happened (timeout)
|
|
ContinueDebugEvent(handle, lastevent.threadid, DBG_CONTINUE);
|
|
result:=false;
|
|
end;
|
|
|
|
|
|
|
|
else
|
|
begin
|
|
//no idea
|
|
|
|
ContinueDebugEvent(handle, lastevent.threadid, DBG_EXCEPTION_NOT_HANDLED);
|
|
result:=false;
|
|
end;
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
end;
|
|
|
|
function TNetworkDebuggerInterface.ContinueDebugEvent(dwProcessId: DWORD; dwThreadId: DWORD; dwContinueStatus: DWORD): BOOL;
|
|
var
|
|
c: TCEConnection;
|
|
begin
|
|
|
|
result:=false;
|
|
c:=getConnection;
|
|
if c<>nil then
|
|
begin
|
|
if dwContinueStatus=DBG_CONTINUE then
|
|
begin
|
|
if fSingleStepNextContinue then
|
|
result:=c.ContinueDebugEvent(handle, dwThreadID, 2) //ignore this signal and enter a single step mode
|
|
else
|
|
result:=c.ContinueDebugEvent(handle, dwThreadID, 1); //ignore this signal
|
|
|
|
fSingleStepNextContinue:=false;
|
|
end
|
|
else
|
|
result:=c.ContinueDebugEvent(handle, dwThreadID, 0);
|
|
end;
|
|
|
|
end;
|
|
|
|
function TNetworkDebuggerInterface.SetThreadContextArm(hThread: THandle; const lpContext: TArmContext; isFrozenThread: Boolean=false): BOOL;
|
|
begin
|
|
exit(NetworkDebuggerInterface.SetThreadContextArm(hThread, lpContext));
|
|
end;
|
|
|
|
function TNetworkDebuggerInterface.SetThreadContextArm64(hThread: THandle; const lpContext: TArm64Context; isFrozenThread: Boolean=false): BOOL;
|
|
begin
|
|
exit(NetworkDebuggerInterface.SetThreadContextArm64(hThread, lpContext));
|
|
end;
|
|
|
|
function TNetworkDebuggerInterface.GetThreadContextArm64(hThread: THandle; var lpContext: TArm64Context; isFrozenThread: Boolean=false): BOOL;
|
|
begin
|
|
exit(NetworkDebuggerInterface.GetThreadContextArm64(hThread, lpContext));
|
|
end;
|
|
|
|
function TNetworkDebuggerInterface.GetThreadContextArm(hThread: THandle; var lpContext: TArmContext; isFrozenThread: Boolean=false): BOOL;
|
|
begin
|
|
exit(NetworkDebuggerInterface.GetThreadContextArm(hthread, lpcontext));
|
|
end;
|
|
|
|
|
|
|
|
function TNetworkDebuggerInterface.SetThreadContext(hThread: THandle; const lpContext: TContext; isFrozenThread: Boolean=false): BOOL;
|
|
begin
|
|
exit(NetworkDebuggerInterface.SetThreadContext(hthread, lpcontext));
|
|
end;
|
|
|
|
function TNetworkDebuggerInterface.GetThreadContext(hThread: THandle; var lpContext: TContext; isFrozenThread: Boolean=false): BOOL;
|
|
begin
|
|
exit(NetworkDebuggerInterface.GetThreadContext(hthread, lpcontext));
|
|
end;
|
|
|
|
function TNetworkDebuggerInterface.GetLastBranchRecords(lbr: pointer): integer;
|
|
begin
|
|
result:=0;
|
|
end;
|
|
|
|
function TNetworkDebuggerInterface.DebugActiveProcess(dwProcessId: DWORD): WINBOOL;
|
|
var c: TCEConnection;
|
|
begin
|
|
result:=false;
|
|
processhandler.processid:=dwProcessID;
|
|
Open_Process;
|
|
|
|
handle:=ProcessHandle;
|
|
|
|
if (handle<>0) then
|
|
begin
|
|
c:=getConnection;
|
|
if c<>nil then
|
|
result:=c.StartDebug(handle);
|
|
|
|
end;
|
|
|
|
end;
|
|
|
|
function TNetworkDebuggerInterface.canReportExactDebugRegisterTrigger: boolean;
|
|
begin
|
|
result:=false;
|
|
end;
|
|
|
|
|
|
destructor TNetworkDebuggerInterface.destroy;
|
|
begin
|
|
|
|
{
|
|
if (handle)
|
|
networkStopDebug();
|
|
}
|
|
inherited destroy;
|
|
end;
|
|
|
|
constructor TNetworkDebuggerInterface.create;
|
|
begin
|
|
inherited create;
|
|
|
|
//no software breakpoint for now
|
|
fDebuggerCapabilities:=[dbcHardwareBreakpoint];
|
|
|
|
end;
|
|
|
|
|
|
end.
|
|
|