FPPS4/sys/kern/kern_mdbg.pas

406 lines
7.6 KiB
Plaintext

unit kern_mdbg;
{$mode ObjFPC}{$H+}
{$CALLING SysV_ABI_CDecl}
interface
function sys_mdbg_service(op:Integer;arg1,arg2:Pointer):Integer;
implementation
uses
sysutils,
errno,
systm,
kern_mtx,
kern_condvar,
kern_thr,
kern_proc,
subr_backtrace;
type
t_SetProcessProperty=packed record //0x48
f_0:QWORD;
f_1:QWORD;
f_2:QWORD;
f_3:QWORD;
f_4:QWORD;
name:array[0..31] of AnsiChar;
end;
t_coredump_ret=packed record //0x28
ret :Integer;
flags:Integer;
data :array[0..3] of QWORD;
end;
t_pevt_state=(pevt_none,pevt_inited,pevt_wait,pevt_finish);
p_mdbg_pevt=^t_mdbg_pevt;
t_mdbg_pevt=record
cv :t_cv;
mtx:mtx;
td_tid :Integer;
td_cancel :Integer;
td_ret :Integer;
td_flags :Integer;
td_state :t_pevt_state;
crash_state:Integer;
//
Sce:record
Flags :QWORD;
PSM_AppName :array[0..3] of QWORD;
PSM_SdbInfo :array[0..1] of QWORD;
PSM_LogArea :array[0..3] of QWORD;
Debug_UserObjArray:array[0..1] of QWORD;
Debug_Gnm :array[0..1] of QWORD;
end;
//
end;
var
g_mdbg_pevt:p_mdbg_pevt=nil;
function init_mdbg_pevt:p_mdbg_pevt;
var
props:p_mdbg_pevt;
begin
mtx_lock(p_proc.p_mtx);
props:=g_mdbg_pevt;
if (props<>nil) then
begin
mtx_unlock(p_proc.p_mtx);
Exit(props);
end;
props:=AllocMem(SizeOf(t_mdbg_pevt));
mtx_init(props^.mtx,'mdbg_pevt_MTX');
cv_init (@props^.cv,'mDBG Debug event');
props^.td_state:=pevt_inited;
g_mdbg_pevt:=props;
mtx_unlock(p_proc.p_mtx);
Writeln('init_mdbg_pevt');
Exit(props);
end;
function SetProcessProperty(arg1:Pointer):Integer;
var
data :t_SetProcessProperty;
props:p_mdbg_pevt;
begin
Result:=copyin(arg1,@data,SizeOf(t_SetProcessProperty));
if (Result<>0) then Exit;
props:=init_mdbg_pevt;
Result:=0;
mtx_lock(p_proc.p_mtx);
case String(data.name) of
'Sce.PSM:AppName': //1
begin
props^.Sce.Flags :=props^.Sce.Flags or $02;
props^.Sce.PSM_AppName[0]:=data.f_1;
props^.Sce.PSM_AppName[1]:=data.f_2;
props^.Sce.PSM_AppName[2]:=data.f_3;
props^.Sce.PSM_AppName[3]:=data.f_4;
end;
'Sce.PSM:SdbInfo': //2
begin
props^.Sce.Flags :=props^.Sce.Flags or $04;
props^.Sce.PSM_SdbInfo[0]:=data.f_1;
props^.Sce.PSM_SdbInfo[1]:=data.f_2;
end;
'Sce.PSM:LogArea': //3
begin
props^.Sce.Flags :=props^.Sce.Flags or $08;
props^.Sce.PSM_LogArea[0]:=data.f_1;
props^.Sce.PSM_LogArea[1]:=data.f_2;
props^.Sce.PSM_LogArea[2]:=data.f_3;
props^.Sce.PSM_LogArea[3]:=data.f_4;
end;
'Sce.Debug:UserObjArray': //4
begin
props^.Sce.Flags :=props^.Sce.Flags or $10;
props^.Sce.Debug_UserObjArray[0]:=data.f_1;
props^.Sce.Debug_UserObjArray[1]:=data.f_2;
end;
'Sce.Debug:Gnm': //5
begin
props^.Sce.Flags :=props^.Sce.Flags or $20;
props^.Sce.Debug_Gnm[0]:=data.f_1;
props^.Sce.Debug_Gnm[1]:=data.f_2;
end;
else
Result:=EINVAL;
end;
mtx_unlock(p_proc.p_mtx);
if (Result<>0) then Exit;
Writeln('SetProcessProperty("',data.name,'",0x',
HexStr(data.f_1,16),',0x',
HexStr(data.f_2,16),',0x',
HexStr(data.f_3,16),',0x',
HexStr(data.f_4,16),')');
end;
function sys_mdbg_service(op:Integer;arg1,arg2:Pointer):Integer;
var
props:p_mdbg_pevt;
ret,size:Integer;
coredump_ret:t_coredump_ret;
begin
Result:=0;
case op of
1: //SetProcessProperty
begin
Result:=SetProcessProperty(arg1);
end;
3: //sceKernelDebugRaiseException
begin
print_error_td('sceKernelDebugRaiseException:0x'+HexStr(DWORD(arg1),8));
Assert(False);
Result:=EINVAL;
end;
4: //sceKernelDebugRaiseExceptionOnReleaseMode
begin
Writeln('sceKernelDebugRaiseExceptionOnReleaseMode:0x',HexStr(DWORD(arg1),8));
print_backtrace_td(stderr);
Result:=0;
end;
8:
begin
//signal coredump thread start and wait
props:=init_mdbg_pevt;
//td->td_dbgflags = td->td_dbgflags | 0x100;
mtx_lock(props^.mtx);
props^.td_tid:=curkthread^.td_tid;
Result:=0;
if (props^.td_cancel=0) then
begin
props^.td_state:=pevt_wait;
cv_signal(@props^.cv);
ret:=_cv_wait_sig(@props^.cv,@props^.mtx);
Result:=0;
props^.td_state:=pevt_inited;
if (ret<>0) and (props^.td_cancel=0) then
begin
Result:=EINTR;
end;
end;
props^.td_cancel:=0;
if (props^.crash_state=0) then
begin
//
end else
begin
Result:=EINVAL;
end;
if (Result=0) then
begin
coredump_ret:=Default(t_coredump_ret);
coredump_ret.ret :=props^.td_ret;
coredump_ret.flags:=props^.td_flags;
mtx_unlock(props^.mtx);
size:=Integer(arg2);
if (size < 0) then
begin
Result:=EFAULT;
end else
begin
if (DWORD(size) < $28) then
begin
//
end else
begin
size:=$28;
end;
Result:=copyout(@coredump_ret,arg1,size);
if (Result=0) then
begin
Writeln('mDBG: Debughandler starting(',curkthread^.td_tid,':',curkthread^.td_name,')');
end;
end;
Exit;
end;
mtx_unlock(props^.mtx);
end;
9: //sceCoredumpUnregisterCoredumpHandler
begin
//cancel coredump thread and wait exit
mtx_lock(p_proc.p_mtx);
props:=g_mdbg_pevt;
if (props<>nil) then
begin
mtx_lock(props^.mtx);
props^.td_flags :=props^.td_flags or 1;
props^.td_ret :=Integer(arg1);
props^.td_cancel:=1;
if (props^.td_state=pevt_wait) then
begin
cv_signal(@props^.cv);
end;
mtx_unlock(props^.mtx);
mtx_unlock(p_proc.p_mtx);
//TODO: wait thread exit
Exit;
end else
begin
Result:=ESRCH;
end;
mtx_unlock(p_proc.p_mtx);
end;
10: //sceCoredumpAttach*
begin
//only in coredump thread
//(td->td_dbgflags | 0x100)=0 && not sceSblACMgrIsSystemUcred
Result:=EPERM;
end;
11:
begin
init_mdbg_pevt;
Result:=0;
end;
12:
begin
//wait coredump thread start
mtx_lock(p_proc.p_mtx);
props:=g_mdbg_pevt;
mtx_unlock(p_proc.p_mtx);
if (props=nil) then
begin
Exit(EINVAL);
end;
mtx_lock(props^.mtx);
if (props^.td_state=pevt_inited) then
begin
ret:=_cv_wait_sig(@props^.cv,@props^.mtx);
if (ret<>-1) then
begin
Result:=ret;
end else
begin
Result:=EINTR;
end;
end else
if (props^.td_state<>pevt_wait) then
begin
if (props^.td_state=pevt_finish) then
begin
Result:=ESRCH;
end else
begin
Result:=EAGAIN;
end;
end;
mtx_unlock(props^.mtx);
end;
13:
begin
//coredump thread reset
mtx_lock(p_proc.p_mtx);
//if (((td->td_dbgflags & 0x100) != 0) && (proc->debug_event == 0)) {
// td->td_dbgflags = td->td_dbgflags & (~0x100);
//}
props:=g_mdbg_pevt;
if (props<>nil) then
begin
mtx_lock(props^.mtx);
props^.td_flags:=props^.td_flags and (not 1);
if (arg1<>nil) then
begin
props^.td_state:=pevt_finish;
end;
mtx_unlock(props^.mtx);
end;
mtx_unlock(p_proc.p_mtx);
end;
20:
begin
//td->td_dbgflags = td->td_dbgflags | 0x800;
Result:=0;
end;
else
begin
print_error_td('sys_mdbg_service('+IntToStr(op)+')');
Assert(False);
Result:=EINVAL;
end;
end;
end;
end.