fpPS4/sys/sys_context.pas
2022-05-31 10:20:10 +03:00

207 lines
4.5 KiB
ObjectPascal

unit sys_context;
{$mode objfpc}{$H+}
interface
uses
Windows;
const
XSTATE_LEGACY_FLOATING_POINT=0;
XSTATE_LEGACY_SSE =1;
XSTATE_GSSE =2;
XSTATE_AVX =XSTATE_GSSE;
XSTATE_MPX_BNDREGS =3;
XSTATE_MPX_BNDCSR =4;
XSTATE_AVX512_KMASK =5;
XSTATE_AVX512_ZMM_H =6;
XSTATE_AVX512_ZMM =7;
XSTATE_IPT =8;
XSTATE_CET_U =11;
XSTATE_LWP =62;
MAXIMUM_XSTATE_FEATURES =64;
XSTATE_MASK_LEGACY_FLOATING_POINT=(1 shl XSTATE_LEGACY_FLOATING_POINT);
XSTATE_MASK_LEGACY_SSE =(1 shl XSTATE_LEGACY_SSE);
XSTATE_MASK_LEGACY =(XSTATE_MASK_LEGACY_FLOATING_POINT or XSTATE_MASK_LEGACY_SSE);
XSTATE_MASK_GSSE =(1 shl XSTATE_GSSE);
XSTATE_MASK_AVX =(XSTATE_MASK_GSSE);
const
CONTEXT_XSTATE =(CONTEXT_AMD64 or $0040);
CONTEXT_ALLX =(CONTEXT_ALL or CONTEXT_XSTATE);
type
PYMMCONTEXT=^TYMMCONTEXT;
TYMMCONTEXT=packed record
Ymm0 :M128A;
Ymm1 :M128A;
Ymm2 :M128A;
Ymm3 :M128A;
Ymm4 :M128A;
Ymm5 :M128A;
Ymm6 :M128A;
Ymm7 :M128A;
Ymm8 :M128A;
Ymm9 :M128A;
Ymm10:M128A;
Ymm11:M128A;
Ymm12:M128A;
Ymm13:M128A;
Ymm14:M128A;
Ymm15:M128A;
end;
PXSTATE=^TXSTATE;
TXSTATE=packed record
Mask:QWORD;
CompactionMask:QWORD;
Reserved:array[0..5] of QWORD;
YmmContext:TYMMCONTEXT;
end;
PCONTEXT_CHUNK=^TCONTEXT_CHUNK;
TCONTEXT_CHUNK=packed record
Offset:LONG;
Length:ULONG;
end;
PCONTEXT_EX=^TCONTEXT_EX;
TCONTEXT_EX=packed record
All :TCONTEXT_CHUNK;
Legacy:TCONTEXT_CHUNK;
XState:TCONTEXT_CHUNK;
_align:QWORD;
end;
PPCONTEXT=^PCONTEXT;
const
CONTEXT_STUB_SIZE=SizeOf(TCONTEXT)+SizeOf(TCONTEXT_EX)+SizeOf(TXSTATE)+64;
type
TCONTEXT_STUB=array[0..CONTEXT_STUB_SIZE-1] of Byte;
PCONTEXT_EXTENDED=^TCONTEXT_EXTENDED;
TCONTEXT_EXTENDED=packed record
CONTEXT:PCONTEXT;
STUB:TCONTEXT_STUB;
end;
function GetEnabledXStateFeatures:QWORD; stdcall external 'kernel32';
function InitializeContext(
Buffer:Pointer;
ContextFlags:DWORD;
Context:PPCONTEXT;
ContextLength:PDWORD
):BOOL; stdcall external 'kernel32';
function GetXStateFeaturesMask(
Context:PCONTEXT;
FeatureMask:PQWORD
):BOOL; stdcall external 'kernel32';
function LocateXStateFeature(
Context:PCONTEXT;
FeatureId:DWORD;
Length:PDWORD
):Pointer; stdcall external 'kernel32';
function SetXStateFeaturesMask(
Context:PCONTEXT;
FeatureMask:QWORD
):BOOL; stdcall external 'kernel32';
function CopyContext(
Destination:PCONTEXT;
ContextFlags:DWORD;
Source:PCONTEXT
):BOOL; stdcall external 'kernel32';
Function GetContextXSize:DWORD;
function InitializeContextExtended(lpContext:PCONTEXT_EXTENDED):Boolean;
function CopyContextExtended(src,dst:PCONTEXT_EXTENDED):Boolean;
function IS_SYSCALL(rip:qword):Boolean;
implementation
Function GetContextXSize:DWORD;
begin
Result:=0;
InitializeContext(nil,
CONTEXT_ALLX,
nil,
@Result);
end;
function InitializeContextExtended(lpContext:PCONTEXT_EXTENDED):Boolean;
var
ContextSize:DWORD;
FeatureMask:QWORD;
begin
Result:=False;
if (lpContext=nil) then
begin
SetLastError(ERROR_INVALID_PARAMETER);
Exit(False);
end;
ContextSize:=GetContextXSize;
if (ContextSize=0) then Exit(False);
if (ContextSize>SizeOf(TCONTEXT_EXTENDED)) then
begin
Assert(false);
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
Exit(False);
end;
lpContext^:=Default(TCONTEXT_EXTENDED);
if not InitializeContext(@lpContext^.STUB,
CONTEXT_ALLX,
@lpContext^.CONTEXT,
@ContextSize) then
begin
Exit(False);
end;
FeatureMask:=GetEnabledXStateFeatures;
if ((FeatureMask and XSTATE_MASK_AVX)<>0) then
if not SetXStateFeaturesMask(lpContext^.CONTEXT,XSTATE_MASK_AVX) then
begin
Exit(False);
end;
Result:=True;
end;
function CopyContextExtended(src,dst:PCONTEXT_EXTENDED):Boolean;
begin
if (src=nil) or (dst=nil) then Exit(False);
if (src^.CONTEXT=nil) then Exit(False);
if not InitializeContextExtended(dst) then Exit(False);
Result:=CopyContext(dst^.CONTEXT,src^.CONTEXT^.ContextFlags,src^.CONTEXT);
end;
function IS_SYSCALL(rip:qword):Boolean;
var
w:Word;
n:ptruint;
begin
Result:=False;
if (rip<>0) then
begin
w:=0;
ReadProcessMemory(GetCurrentProcess,@PWord(Rip)[-1],@w,SizeOf(Word),@n);
Result:=(w=$050F);
end;
end;
end.