mirror of https://github.com/red-prig/fpPS4.git
245 lines
4.6 KiB
Plaintext
245 lines
4.6 KiB
Plaintext
unit vm_pmap_prot;
|
|
|
|
{$mode ObjFPC}{$H+}
|
|
{$CALLING SysV_ABI_CDecl}
|
|
|
|
interface
|
|
|
|
uses
|
|
atomic,
|
|
vm,
|
|
vmparam,
|
|
md_map;
|
|
|
|
const
|
|
PMAPP_SHIFT=MD_PAGE_SHIFT; //12;
|
|
PMAPP_SIZE =MD_PAGE_SIZE; //1 shl PMAPP_SHIFT; //4*1024
|
|
PMAPP_MASK =MD_PAGE_MASK; //PMAPP_SIZE-1;
|
|
|
|
PAGE_MAP_COUNT =(QWORD(VM_MAXUSER_ADDRESS) shr PMAPP_SHIFT);
|
|
PAGE_MAP_MASK =PAGE_MAP_COUNT-1;
|
|
|
|
PAGE_PROT_READ =VM_PROT_READ;
|
|
PAGE_PROT_WRITE =VM_PROT_WRITE;
|
|
PAGE_PROT_EXECUTE=VM_PROT_EXECUTE;
|
|
|
|
PAGE_PROT_RW =PAGE_PROT_READ or PAGE_PROT_WRITE;
|
|
PAGE_PROT_RWX =PAGE_PROT_READ or PAGE_PROT_WRITE or PAGE_PROT_EXECUTE;
|
|
|
|
PAGE_TRACK_R =$08;
|
|
PAGE_TRACK_W =$10;
|
|
PAGE_TRACK_X =$20;
|
|
PAGE_TRACK_RWX =PAGE_TRACK_R or PAGE_TRACK_W or PAGE_TRACK_X;
|
|
PAGE_TRACK_SHIFT =3;
|
|
|
|
TRACK_PROT=1; //Take tracking bits into account
|
|
REMAP_PROT=2; //Ignore protect bit checking
|
|
|
|
var
|
|
PAGE_PROT:PBYTE=nil;
|
|
|
|
procedure ppmap_mark_rwx (start,__end:vm_offset_t;prots:Byte);
|
|
procedure ppmap_unmark (start,__end:vm_offset_t);
|
|
procedure ppmap_unmark_rwx(start,__end:vm_offset_t);
|
|
procedure ppmap_track (start,__end:vm_offset_t;prots:Byte);
|
|
//procedure ppmap_untrack (start,__end:vm_offset_t;prots:Byte);
|
|
function ppmap_scan (start,__end:vm_offset_t):vm_offset_t;
|
|
function ppmap_scan_rwx (start,__end:vm_offset_t):vm_offset_t;
|
|
function ppmap_get_prot (addr:vm_offset_t):Byte;
|
|
function ppmap_get_prot (addr,size:vm_offset_t):Byte;
|
|
|
|
implementation
|
|
|
|
//PAGE_MAP
|
|
|
|
function IDX_TO_OFF(x:DWORD):QWORD; inline;
|
|
begin
|
|
Result:=QWORD(x) shl PMAPP_SHIFT;
|
|
end;
|
|
|
|
function OFF_TO_IDX(x:QWORD):DWORD; inline;
|
|
begin
|
|
Result:=QWORD(x) shr PMAPP_SHIFT;
|
|
end;
|
|
|
|
function MAX_IDX(x:DWORD):DWORD; inline;
|
|
begin
|
|
if (x>PAGE_MAP_MASK) then
|
|
Result:=PAGE_MAP_MASK
|
|
else
|
|
Result:=x;
|
|
end;
|
|
|
|
procedure ppmap_mark_rwx(start,__end:vm_offset_t;prots:Byte);
|
|
var
|
|
clear:Byte;
|
|
begin
|
|
prots:=prots and PAGE_PROT_RWX;
|
|
clear:=(not prots) and PAGE_PROT_RWX;
|
|
start:=OFF_TO_IDX(start);
|
|
__end:=OFF_TO_IDX(__end);
|
|
start:=MAX_IDX(start);
|
|
__end:=MAX_IDX(__end);
|
|
while (start<__end) do
|
|
begin
|
|
atomic_clear_byte(@PAGE_PROT[start],clear);
|
|
atomic_set_byte (@PAGE_PROT[start],prots);
|
|
//PAGE_PROT[start]:=prots;
|
|
Inc(start);
|
|
end;
|
|
WriteBarrier;
|
|
end;
|
|
|
|
procedure ppmap_unmark(start,__end:vm_offset_t);
|
|
begin
|
|
start:=OFF_TO_IDX(start);
|
|
__end:=OFF_TO_IDX(__end);
|
|
start:=MAX_IDX(start);
|
|
__end:=MAX_IDX(__end);
|
|
while (start<__end) do
|
|
begin
|
|
//PAGE_PROT[start]:=0;
|
|
Inc(start);
|
|
end;
|
|
WriteBarrier;
|
|
end;
|
|
|
|
procedure ppmap_unmark_rwx(start,__end:vm_offset_t);
|
|
begin
|
|
start:=OFF_TO_IDX(start);
|
|
__end:=OFF_TO_IDX(__end);
|
|
start:=MAX_IDX(start);
|
|
__end:=MAX_IDX(__end);
|
|
while (start<__end) do
|
|
begin
|
|
atomic_clear_byte(@PAGE_PROT[start],PAGE_PROT_RWX);
|
|
Inc(start);
|
|
end;
|
|
WriteBarrier;
|
|
end;
|
|
|
|
procedure ppmap_track(start,__end:vm_offset_t;prots:Byte);
|
|
var
|
|
s_prots:Byte;
|
|
c_prots:Byte;
|
|
begin
|
|
s_prots:=prots and PAGE_TRACK_RWX;
|
|
c_prots:=(not prots) and PAGE_TRACK_RWX;
|
|
|
|
start:=OFF_TO_IDX(start);
|
|
__end:=OFF_TO_IDX(__end);
|
|
start:=MAX_IDX(start);
|
|
__end:=MAX_IDX(__end);
|
|
while (start<__end) do
|
|
begin
|
|
atomic_set_byte (@PAGE_PROT[start],s_prots);
|
|
atomic_clear_byte(@PAGE_PROT[start],c_prots);
|
|
Inc(start);
|
|
end;
|
|
WriteBarrier;
|
|
end;
|
|
|
|
{
|
|
procedure ppmap_untrack(start,__end:vm_offset_t;prots:Byte);
|
|
begin
|
|
prots:=prots and PAGE_TRACK_RWX;
|
|
start:=OFF_TO_IDX(start);
|
|
__end:=OFF_TO_IDX(__end);
|
|
start:=MAX_IDX(start);
|
|
__end:=MAX_IDX(__end);
|
|
while (start<__end) do
|
|
begin
|
|
atomic_clear_byte(@PAGE_PROT[start],prots);
|
|
Inc(start);
|
|
end;
|
|
WriteBarrier;
|
|
end;
|
|
}
|
|
|
|
function ppmap_scan(start,__end:vm_offset_t):vm_offset_t;
|
|
var
|
|
b,v:Byte;
|
|
begin
|
|
start:=OFF_TO_IDX(start);
|
|
__end:=OFF_TO_IDX(__end);
|
|
start:=MAX_IDX(start);
|
|
__end:=MAX_IDX(__end);
|
|
|
|
ReadBarrier;
|
|
|
|
b:=PAGE_PROT[start];
|
|
Inc(start);
|
|
|
|
while (start<__end) do
|
|
begin
|
|
v:=PAGE_PROT[start];
|
|
|
|
if (b<>v) then
|
|
begin
|
|
start:=IDX_TO_OFF(start);
|
|
Exit(start);
|
|
end;
|
|
|
|
Inc(start);
|
|
end;
|
|
|
|
__end:=IDX_TO_OFF(__end);
|
|
|
|
Result:=__end;
|
|
end;
|
|
|
|
function ppmap_scan_rwx(start,__end:vm_offset_t):vm_offset_t;
|
|
var
|
|
b,v:Byte;
|
|
begin
|
|
start:=OFF_TO_IDX(start);
|
|
__end:=OFF_TO_IDX(__end);
|
|
start:=MAX_IDX(start);
|
|
__end:=MAX_IDX(__end);
|
|
|
|
ReadBarrier;
|
|
|
|
b:=(PAGE_PROT[start] and PAGE_PROT_RWX);
|
|
Inc(start);
|
|
|
|
while (start<__end) do
|
|
begin
|
|
v:=(PAGE_PROT[start] and PAGE_PROT_RWX);
|
|
|
|
if (b<>v) then
|
|
begin
|
|
start:=IDX_TO_OFF(start);
|
|
Exit(start);
|
|
end;
|
|
|
|
Inc(start);
|
|
end;
|
|
|
|
__end:=IDX_TO_OFF(__end);
|
|
|
|
Result:=__end;
|
|
end;
|
|
|
|
function ppmap_get_prot(addr:vm_offset_t):Byte;
|
|
begin
|
|
addr:=OFF_TO_IDX(addr);
|
|
if (addr>PAGE_MAP_MASK) then
|
|
begin
|
|
Result:=0
|
|
end else
|
|
begin
|
|
Result:=PAGE_PROT[addr];
|
|
end;
|
|
end;
|
|
|
|
function ppmap_get_prot(addr,size:vm_offset_t):Byte;
|
|
begin
|
|
Result:=ppmap_get_prot(addr) or ppmap_get_prot(addr+size);
|
|
end;
|
|
|
|
|
|
end.
|
|
|
|
|
|
|