This commit is contained in:
Pavel 2024-06-18 17:47:33 +03:00
parent eb614ec4fb
commit cf6f0435e4
11 changed files with 606 additions and 134 deletions

View File

@ -329,10 +329,12 @@ type
function leap(reg:TRegValue):t_jit_i_link;
//
Procedure jmp(reg:TRegValue);
Procedure jmp(mem:t_jit_leas);
Procedure call(reg:TRegValue);
Procedure call(mem:t_jit_leas);
Procedure reta;
Procedure ud2;
Procedure nop(length:DWORD);
//
Function GetInstructionsSize:Integer;
Function GetDataSize:Integer;
@ -1530,6 +1532,13 @@ begin
_R(desc,reg);
end;
Procedure t_jit_builder.jmp(mem:t_jit_leas);
const
desc:t_op_type=(op:$FF;index:4);
begin
_M(desc,mem);
end;
Procedure t_jit_builder.call(reg:TRegValue);
const
desc:t_op_type=(op:$FF;index:2);
@ -1556,6 +1565,43 @@ begin
_O($0F0B);
end;
Procedure t_jit_builder.nop(length:DWORD);
var
i:DWORD;
ji:t_jit_instruction;
begin
if (length=0) then Exit;
ji:=default_jit_instruction;
i:=length div 9;
while (i<>0) do
begin
ji.EmitInt64($00000000841F0F66);
ji.EmitByte ($00);
Dec(i);
end;
i:=length mod 9;
case i of
1: ji.EmitByte($90);
2: ji.EmitWord($9066);
3: begin ji.EmitWord($1F0F); ji.EmitByte($00); end;
4: ji.EmitInt32($00401F0F);
5: begin ji.EmitInt32($00441F0F); ji.EmitByte($00); end;
6: begin ji.EmitInt32($441F0F66); ji.EmitWord($00); end;
7: begin ji.EmitInt32($00801F0F); ji.EmitWord($00); ji.EmitByte($00); end;
8: ji.EmitInt64($0000000000841F0F);
else;
end;
_add(ji);
end;
Function t_jit_builder.GetInstructionsSize:Integer;
begin
Result:=AInstructionSize;

View File

@ -1374,11 +1374,17 @@ var
map:vm_map_t;
lock:Pointer;
node:p_jit_entry_point;
lock_start:QWORD;
lock___end:QWORD;
begin
map:=p_proc.p_vmspace;
lock_start:=ctx.text_start;
lock___end:=ctx.text___end;
//vm_map_lock(map);
lock:=pmap_wlock(map^.pmap,ctx.text_start,ctx.text___end);
lock:=pmap_wlock(map^.pmap,lock_start,lock___end);
if (preload<>nil) then
begin
@ -1391,10 +1397,10 @@ begin
end;
end;
//lock pageflt read-only
//vm_map_lock(map);
// _pmap_prot_int(map^.pmap,ctx.text_start,ctx.text___end,PAGE_PROT_READ);
//vm_map_unlock(map);
//lock pageflt read-only (mirrors?)
vm_map_lock(map);
_pmap_prot_int(map^.pmap,lock_start,lock___end,PAGE_PROT_READ);
vm_map_unlock(map);
if (cmInternal in ctx.modes) then
begin
@ -1404,38 +1410,16 @@ begin
pick_locked(ctx);
end;
//restore non tracked
//vm_map_lock(map);
// _pmap_prot_fix(map^.pmap,ctx.text_start,ctx.text___end,TRACK_PROT or REMAP_PROT);
//vm_map_unlock(map);
//restore non tracked (mirrors?)
vm_map_lock(map);
_pmap_prot_fix(map^.pmap,lock_start,lock___end,TRACK_PROT or REMAP_PROT);
vm_map_unlock(map);
_exit:
pmap_unlock(map^.pmap,lock);
//vm_map_unlock(map);
end;
procedure pick_track(var ctx:t_jit_context2);
var
chunk:p_jit_code_chunk;
begin
chunk:=TAILQ_FIRST(@ctx.builder.ACodeChunkList);
while (chunk<>nil) do
begin
if (chunk^.start<>chunk^.__end) then
begin
pmap_track(chunk^.start,
chunk^.__end+PAGE_MASK,
PAGE_TRACK_W or PAGE_TRACK_X);
end;
//
chunk:=TAILQ_NEXT(chunk,@chunk^.entry);
end;
end;
procedure pick_locked_internal(var ctx:t_jit_context2);
var
node:t_jit_context2.p_export_point;
@ -1493,9 +1477,8 @@ begin
ctx.end_chunk(ctx.ptr_next);
pick_track(ctx);
build(ctx);
ctx.Free;
end;
@ -1909,9 +1892,8 @@ begin
ctx.builder.int3;
ctx.builder.ud2;
pick_track(ctx);
build(ctx);
ctx.Free;
end;

View File

@ -265,9 +265,17 @@ procedure op_emit_bmi_rrm(var ctx:t_jit_context2;const desc:t_op_type);
procedure print_disassemble(addr:Pointer;vsize:Integer);
type
t_instruction_info=record
code_size:Byte;
mema_size:Byte;
end;
function get_instruction_info(addr:Pointer):t_instruction_info;
var
jit_relative_analize:Boolean=True;
jit_memory_guard:Boolean=False;
jit_memory_guard :Boolean=False;
implementation
@ -3907,6 +3915,40 @@ begin
end;
end;
//
function get_instruction_info(addr:Pointer):t_instruction_info;
var
ptr:Pointer;
dis:TX86Disassembler;
din:TInstruction;
i:Byte;
begin
dis:=Default(TX86Disassembler);
din:=Default(TInstruction);
ptr:=addr;
dis.Disassemble(dm64,ptr,din);
Result.code_size:=(ptr-addr);
Result.mema_size:=0;
if (din.OperCnt<>0) then
For i:=1 to din.OperCnt do
if is_memory(din.Operand[i]) then
begin
Result.mema_size:=OPERAND_BYTES[din.Operand[i].Size];
Exit;
end;
Assert(false,'get_instruction_info');
end;
//
end.

View File

@ -54,11 +54,12 @@ type
pLeft :p_jcode_chunk;
pRight:p_jcode_chunk;
blob :p_jit_dynamic_blob;
start :QWORD; //<-guest
__end :QWORD; //<-guest
dest :QWORD; //<-host
d_end :QWORD; //<-host
hash :QWORD; //MurmurHash64A(Pointer(start),__end-start,$010CA1C0DE);
tobj :Pointer; //p_vm_track_object
start :QWORD; //<-guest
__end :QWORD; //<-guest
dest :QWORD; //<-host
d_end :QWORD; //<-host
hash :QWORD; //MurmurHash64A(Pointer(start),__end-start,$010CA1C0DE);
count :QWORD;
table :record end; //p_jinstr_len[]
function c(n1,n2:p_jcode_chunk):Integer; static;
@ -162,9 +163,13 @@ uses
sysutils,
vmparam,
sys_bootparam,
kern_proc,
vm,
vm_map,
vm_pmap_prot,
vm_pmap,
md_map,
vm_tracking_map,
kern_dlsym;
//
@ -1349,6 +1354,51 @@ begin
dec_ref
end;
function on_destroy(handle:Pointer):Integer;
begin
p_jcode_chunk(handle)^.tobj:=nil;
Result:=DO_DELETE;
end;
function on_trigger(handle:Pointer;start,__end:vm_offset_t):Integer;
begin
Result:=DO_INCREMENT;
end;
procedure blob_track(blob:p_jit_dynamic_blob);
var
node:p_jcode_chunk;
tobj:p_vm_track_object;
begin
node:=blob^.chunk_list;
while (node<>nil) do
begin
if (node^.start<>node^.__end) then
begin
tobj:=vm_track_object_allocate(node,node^.start,node^.__end);
tobj^.on_destroy:=@on_destroy;
tobj^.on_trigger:=@on_trigger;
node^.tobj:=tobj;
vm_map_track(p_proc.p_vmspace,node^.start,node^.__end,tobj);
vm_track_object_deallocate(tobj);
//pmap_track(node^.start,
// node^.__end+PAGE_MASK,
// PAGE_TRACK_W or PAGE_TRACK_X);
//
end;
//
node:=node^.next;
end;
end;
end.

View File

@ -149,6 +149,8 @@ begin
dmem.vmap:=vmap;
dmem.rmap:=@rmap;
rmap.tmap:=@vmap^.pmap^.tr_map;
end;
const

View File

@ -16,6 +16,7 @@ uses
kern_rangelock,
md_map,
vm_pmap_prot,
vm_tracking_map,
vm_nt_map;
const
@ -41,11 +42,12 @@ function uplift(addr:Pointer):Pointer;
procedure iov_uplift(iov:p_iovec);
type
p_pmap=^_pmap;
_pmap=packed object
p_pmap=^t_pmap;
t_pmap=packed object
rmlock:rangelock;
rm_mtx:mtx;
nt_map:_vm_nt_map;
nt_map:t_vm_nt_map;
tr_map:t_vm_track_map;
end;
pmap_t=p_pmap;
@ -306,6 +308,8 @@ begin
end;
end;
vm_track_map_init(@pmap^.tr_map,VM_MINUSER_ADDRESS,VM_MAXUSER_ADDRESS);
end;
type
@ -626,12 +630,12 @@ end;
* is mapped; only those for which a resident page exists with the
* corresponding offset from m_start are mapped.
}
procedure pmap_enter_object(pmap :pmap_t;
obj :vm_object_t;
offset :vm_ooffset_t;
start :vm_offset_t;
__end :vm_offset_t;
prot :vm_prot_t);
procedure pmap_enter_object(pmap :pmap_t;
obj :vm_object_t;
offset:vm_ooffset_t;
start :vm_offset_t;
__end :vm_offset_t;
prot :vm_prot_t);
label
_default;
var
@ -968,7 +972,7 @@ begin
vm_nt_map_prot_fix(@pmap^.nt_map,
start,
__end,
TRACK_PROT);
TRACK_PROT or REMAP_PROT);
//vm_nt_map_protect(@pmap^.nt_map,
// start,
@ -1124,6 +1128,8 @@ begin
pmap_untrack (start,__end,PAGE_TRACK_RWX);
//untrack?
vm_track_map_remove_memory(@pmap^.tr_map,start,__end);
r:=0;
case vm_object_type(obj) of
OBJT_SELF , // same?

View File

@ -31,8 +31,8 @@ const
PAGE_TRACK_RWX =PAGE_TRACK_R or PAGE_TRACK_W or PAGE_TRACK_X;
PAGE_TRACK_SHIFT =3;
TRACK_PROT=1;
REMAP_PROT=2;
TRACK_PROT=1; //Take tracking bits into account
REMAP_PROT=2; //Ignore protect bit checking
var
PAGE_PROT:PBYTE=nil;

View File

@ -36,6 +36,7 @@ type
lock :mtx; // Lock for map data
root :p_rmem_map_entry; // Root of a binary search tree
nentries:DWORD; // Number of entries
tmap :Pointer; // p_vm_track_map
property min_offset:DWORD read header.start write header.start;
property max_offset:DWORD read header.__end write header.__end;
end;
@ -59,11 +60,16 @@ function rmem_map_delete(map:p_rmem_map;
vaddr:QWORD;
start,__end:DWORD):Integer;
procedure rmem_map_track(map:p_rmem_map;
start,__end:DWORD;
tobj:Pointer);
implementation
uses
errno,
kern_thr;
kern_thr,
vm_tracking_map;
function IDX_TO_OFF(x:DWORD):QWORD; inline;
begin
@ -102,7 +108,7 @@ begin
TAILQ_INSERT_TAIL(@entry^.vlist,node,@node^.entry);
end;
procedure rmem_entry_add_vaddr(entry:p_rmem_map_entry;vaddr:QWORD);
function rmem_entry_add_vaddr(entry:p_rmem_map_entry;vaddr:QWORD):Boolean;
var
node:p_rmem_vaddr_instance;
begin
@ -113,15 +119,45 @@ begin
if (node^.vaddr=vaddr) then
begin
Exit;
Exit(False);
end;
node:=TAILQ_NEXT(node,@node^.entry);
end;
//if not one vaddr
Result:=(TAILQ_FIRST(@entry^.vlist)<>nil);
_rmem_entry_add_vaddr(entry,vaddr);
end;
procedure rmem_entry_add_track(tmap:Pointer;entry:p_rmem_map_entry;vaddr:QWORD);
var
node:p_rmem_vaddr_instance;
size:vm_offset_t;
begin
//try add mirror track
size:=IDX_TO_OFF(entry^.__end-entry^.start);
vm_track_map_lock(tmap);
node:=TAILQ_FIRST(@entry^.vlist);
while (node<>nil) do
begin
if (node^.vaddr<>vaddr) then
begin
_vm_track_map_insert_mirror(tmap,node^.vaddr,vaddr,size);
end;
node:=TAILQ_NEXT(node,@node^.entry);
end;
vm_track_map_unlock(tmap);
end;
function _rmem_entry_del_node(entry:p_rmem_map_entry;node:p_rmem_vaddr_instance):Boolean;
begin
TAILQ_REMOVE(@entry^.vlist,node,@node^.entry);
@ -211,18 +247,18 @@ begin
Result:=True;
end;
procedure copy_vaddr_list(const src:TAILQ_HEAD;entry:p_rmem_map_entry);
procedure copy_vaddr_list(src,dst:p_rmem_map_entry);
var
node:p_rmem_vaddr_instance;
begin
TAILQ_INIT(@entry^.vlist);
TAILQ_INIT(@dst^.vlist);
node:=TAILQ_FIRST(@src);
node:=TAILQ_FIRST(@src^.vlist);
while (node<>nil) do
begin
_rmem_entry_add_vaddr(entry,node^.vaddr);
_rmem_entry_add_vaddr(dst,node^.vaddr);
node:=TAILQ_NEXT(node,@node^.entry);
end;
@ -625,7 +661,7 @@ begin
new_entry^.__end:=start;
copy_vaddr_list(entry^.vlist,new_entry);
copy_vaddr_list(entry,new_entry);
entry^.start:=start;
@ -653,7 +689,7 @@ begin
entry^.__end:=__end;
copy_vaddr_list(entry^.vlist,new_entry);
copy_vaddr_list(entry,new_entry);
rmem_entry_link(map, entry, new_entry);
end;
@ -701,7 +737,10 @@ begin
current:=rmem_map_insert_internal(map,current,current^.__end,__end);
rmem_entry_add_vaddr(current,vaddr);
if rmem_entry_add_vaddr(current,vaddr) then
begin
rmem_entry_add_track(map^.tmap,entry,vaddr);
end;
current:=current^.next;
end;
@ -772,9 +811,9 @@ begin
until false;
end;
function rmem_map_delete(map:p_rmem_map;
vaddr:QWORD;
start,__end:DWORD):Integer;
function rmem_map_delete(map:p_rmem_map;
vaddr:QWORD;
start,__end:DWORD):Integer;
var
entry :p_rmem_map_entry;
first_entry:p_rmem_map_entry;
@ -840,6 +879,84 @@ begin
Result:=(KERN_SUCCESS);
end;
procedure rmem_entry_track(tmap:Pointer;entry:p_rmem_map_entry;diff,size:QWORD;tobj:Pointer);
var
node:p_rmem_vaddr_instance;
start:vm_offset_t;
__end:vm_offset_t;
begin
node:=TAILQ_FIRST(@entry^.vlist);
while (node<>nil) do
begin
start:=node^.vaddr+diff;
__end:=start+size;
_vm_track_map_insert(tmap,start,__end,tobj);
node:=TAILQ_NEXT(node,@node^.entry);
end;
end;
procedure rmem_map_track(map:p_rmem_map;
start,__end:DWORD;
tobj:Pointer);
var
entry:p_rmem_map_entry;
e_start:DWORD;
e___end:DWORD;
diff:QWORD;
size:QWORD;
begin
rmem_map_lock(map);
vm_track_map_lock(map^.tmap);
if (rmem_map_lookup_entry(map, start, @entry)) then
begin
//
end else
begin
entry:=entry^.next;
end;
while (entry<>@map^.header) and (entry^.start<__end) do
begin
e_start:=entry^.start;
e___end:=entry^.__end;
if (start>e_start) then
begin
e_start:=start;
end;
if (__end<e___end) then
begin
e___end:=__end;
end;
if (e___end>e_start) then
begin
diff:=IDX_TO_OFF(e_start-entry^.start);
size:=IDX_TO_OFF(e___end-e_start);
rmem_entry_track(map^.tmap,entry,diff,size,tobj);
end;
entry:=entry^.next;
end;
vm_track_map_unlock(map^.tmap);
rmem_map_unlock(map);
end;
end.

View File

@ -59,7 +59,7 @@ type
busy :Integer;
root :vm_map_entry_t; // Root of a binary search tree
pmap :pmap_t; // (c) Physical map
rmap :Pointer;
rmap :Pointer; // p_rmem_map
entry_id :QWORD;
property min_offset:vm_offset_t read header.start write header.start;
property max_offset:vm_offset_t read header.__end write header.__end;
@ -81,7 +81,7 @@ type
vm_daddr :caddr_t; // (c) user virtual address of data
vm_maxsaddr :caddr_t; // user VA at max stack growth
//
vm_pmap :_pmap; // private physical map
vm_pmap :t_pmap; // private physical map
end;
const
@ -276,6 +276,8 @@ procedure vm_map_set_name(map:vm_map_t;start,__end:vm_offset_t;name:PChar);
procedure vm_map_set_name_locked(map:vm_map_t;start,__end:vm_offset_t;name:PChar);
procedure vm_map_set_name_locked(map:vm_map_t;start,__end:vm_offset_t;name:PChar;i:vm_inherit_t);
procedure vm_map_track(map:vm_map_t;start,__end:vm_offset_t;tobj:Pointer);
function vmspace_pmap(vm:p_vmspace):pmap_t; inline;
procedure vm_map_entry_deallocate(entry:vm_map_entry_t);
@ -288,6 +290,7 @@ uses
md_map,
kern_proc,
rmem_map,
vm_tracking_map,
kern_budget;
var
@ -3292,10 +3295,94 @@ begin
vm_map_unlock(map);
end;
procedure vm_map_track(map:vm_map_t;start,__end:vm_offset_t;tobj:Pointer);
var
entry:vm_map_entry_t;
obj:vm_object_t;
e_start:vm_offset_t;
e___end:vm_offset_t;
diff:DWORD;
size:DWORD;
offset:DWORD;
begin
vm_map_lock(map);
VM_MAP_RANGE_CHECK(map, start, __end);
if (vm_map_lookup_entry(map, start, @entry)) then
begin
//
end else
begin
entry:=entry^.next;
end;
while (entry<>@map^.header) and (entry^.start<__end) do
begin
e_start:=entry^.start;
e___end:=entry^.__end;
if (start>e_start) then
begin
e_start:=start;
end;
if (__end<e___end) then
begin
e___end:=__end;
end;
if (e___end>e_start) then
begin
obj:=entry^.vm_obj;
if (obj<>nil) then
begin
if ((obj^.flags and OBJ_DMEM_EXT)<>0) then
begin
//ext rmap track
diff:=OFF_TO_IDX(e_start-entry^.start);
size:=OFF_TO_IDX(e___end-e_start);
offset:=OFF_TO_IDX(entry^.offset);
offset:=offset+diff;
rmem_map_track(map^.rmap,
offset,
offset + size,
tobj);
//next
entry:=entry^.next;
Continue;
end;
//file mirrors TODO
end;
//one map track
vm_track_map_lock(@map^.pmap^.tr_map);
_vm_track_map_insert(@map^.pmap^.tr_map,e_start,e___end,tobj);
vm_track_map_unlock(@map^.pmap^.tr_map)
end; //
entry:=entry^.next;
end;
vm_map_unlock(map);
end;
procedure vminit;
begin
p_proc.p_vmspace:=vmspace_alloc();
end;
end.

View File

@ -58,8 +58,8 @@ type
offset :vm_ooffset_t; // offset into object
end;
p_vm_nt_map=^_vm_nt_map;
_vm_nt_map=object
p_vm_nt_map=^t_vm_nt_map;
t_vm_nt_map=object
header :vm_nt_entry; // List of entries
size :vm_size_t; // virtual size
nentries :Integer; // Number of entries
@ -206,6 +206,7 @@ var
next:vm_offset_t;
base,size:vm_size_t;
prot:Integer;
mask:Integer;
r:Integer;
begin
if (PAGE_PROT=nil) then Exit;
@ -218,19 +219,23 @@ begin
next:=pmap_scan_rwx(start,__end);
prot:=pmap_get_prot(start);
prot:=(prot and VM_RW);
end else
begin
next:=pmap_scan(start,__end);
prot:=pmap_get_prot(start);
prot:=(prot and VM_RW) and (not (prot shr PAGE_TRACK_SHIFT));
mask:=not (prot shr PAGE_TRACK_SHIFT);
prot:=(prot and VM_RW) and mask;
end;
base:=start;
size:=next-start;
if ((mode and REMAP_PROT)=0) or (prot<>(max and VM_RW)) then
if ((mode and REMAP_PROT)<>0) or (prot<>(max and VM_RW)) then
begin
r:=md_protect(Pointer(base),size,prot);
if (r<>0) then
@ -1152,7 +1157,8 @@ procedure vm_nt_map_protect(map:p_vm_nt_map;
prot :Integer);
var
entry:p_vm_nt_entry;
base,size:vm_size_t;
e_start:vm_offset_t;
e___end:vm_offset_t;
max:Integer;
r:Integer;
begin
@ -1168,34 +1174,37 @@ begin
while (entry<>@map^.header) and (entry^.start<__end) do
begin
base:=entry^.start;
size:=entry^.__end;
e_start:=entry^.start;
e___end:=entry^.__end;
if (base<start) then
if (e_start<start) then
begin
base:=start;
e_start:=start;
end;
if (size>__end) then
if (e___end>__end) then
begin
size:=__end;
e___end:=__end;
end;
size:=size-base;
if (e___end>e_start) then
begin
if (entry^.obj<>nil) then
begin
max:=entry^.obj^.maxp;
end else
begin
max:=0;
end;
if (entry^.obj<>nil) then
begin
max:=entry^.obj^.maxp;
end else
begin
max:=0;
end;
r:=md_protect(Pointer(e_start),e___end-e_start,(prot and max and VM_RW));
if (r<>0) then
begin
Writeln('failed md_protect(',HexStr(e_start,11),',',HexStr(e___end,11),'):0x',HexStr(r,8));
Assert(false,'vm_nt_map_protect');
end;
r:=md_protect(Pointer(base),size,(prot and max and VM_RW));
if (r<>0) then
begin
Writeln('failed md_protect(',HexStr(base,11),',',HexStr(base+size,11),'):0x',HexStr(r,8));
Assert(false,'vm_nt_map_protect');
end;
entry:=entry^.next;
@ -1208,7 +1217,8 @@ procedure vm_nt_map_prot_fix(map:p_vm_nt_map;
mode :Integer);
var
entry:p_vm_nt_entry;
e_start,e___end:vm_size_t;
e_start:vm_offset_t;
e___end:vm_offset_t;
begin
if (start=__end) then Exit;
@ -1238,7 +1248,10 @@ begin
e___end:=__end;
end;
vm_prot_fixup(map,e_start,e___end,entry^.obj^.maxp,mode);
if (e___end>e_start) then
begin
vm_prot_fixup(map,e_start,e___end,entry^.obj^.maxp,mode);
end;
end;
entry:=entry^.next;

View File

@ -17,8 +17,14 @@ type
__end:vm_offset_t;
end;
t_on_destroy=function (handle:Pointer):Boolean;
t_on_trigger=procedure(handle:Pointer;start,__end:vm_offset_t);
const
DO_NOTHING =0;
DO_DELETE =1;
DO_INCREMENT=2;
type
t_on_destroy=function(handle:Pointer):Integer;
t_on_trigger=function(handle:Pointer;start,__end:vm_offset_t):Integer;
p_vm_track_object=^t_vm_track_object;
t_vm_track_object=record
@ -63,15 +69,25 @@ type
property max_offset:vm_offset_t read header.__end write header.__end;
end;
procedure vm_track_map_init(map:p_vm_track_map;min,max:vm_offset_t);
//
function vm_track_object_allocate (handle:TObject;start,__end:vm_offset_t):p_vm_track_object;
function vm_track_object_allocate (handle:Pointer;start,__end:vm_offset_t):p_vm_track_object;
procedure vm_track_object_deallocate(obj:p_vm_track_object);
procedure vm_track_object_reference (obj:p_vm_track_object);
//
procedure vm_track_map_lock (map:p_vm_track_map);
procedure vm_track_map_unlock(map:p_vm_track_map);
function _vm_track_map_insert(map:p_vm_track_map;start,__end:vm_offset_t;obj:p_vm_track_object):Integer;
function _vm_track_map_insert_mirror(map:p_vm_track_map;src,dst,size:vm_offset_t):Integer;
//
function vm_track_map_insert_object(map:p_vm_track_map;obj:p_vm_track_object):Integer;
function vm_track_map_remove_object(map:p_vm_track_map;obj:p_vm_track_object):Integer;
function vm_track_map_remove_memory(map:p_vm_track_map;start,__end:vm_offset_t):Integer;
@ -79,7 +95,7 @@ function vm_track_map_trigger (map:p_vm_track_map;start,__end:vm_offset_t)
implementation
function vm_track_object_allocate(handle:TObject;start,__end:vm_offset_t):p_vm_track_object;
function vm_track_object_allocate(handle:Pointer;start,__end:vm_offset_t):p_vm_track_object;
begin
Result:=AllocMem(SizeOf(t_vm_track_object));
@ -106,7 +122,7 @@ begin
if (obj^.on_destroy<>nil) then
begin
if not obj^.on_destroy(obj^.handle) then
if ((obj^.on_destroy(obj^.handle) and DO_DELETE)=0) then
begin
Exit;
end;
@ -123,8 +139,9 @@ begin
System.InterlockedIncrement(obj^.ref_count);
end;
procedure vm_track_object_trigger(map:p_vm_track_map;obj:p_vm_track_object;start,__end:vm_offset_t);
function vm_track_object_trigger(map:p_vm_track_map;obj:p_vm_track_object;start,__end:vm_offset_t):Integer;
begin
Result:=DO_NOTHING;
if (obj=nil) then Exit;
if (obj^.timestamp<>map^.timestamp) then
@ -133,7 +150,10 @@ begin
if (obj^.on_trigger<>nil) then
begin
obj^.on_trigger(obj^.handle,start,__end);
Result:=obj^.on_trigger(obj^.handle,start,__end);
end else
begin
Result:=DO_INCREMENT;
end;
end;
@ -230,21 +250,6 @@ begin
end;
end;
procedure vm_track_entry_trigger(map:p_vm_track_map;entry:p_vm_track_map_entry;start,__end:vm_offset_t);
var
node:p_vm_track_object_instance;
begin
node:=TAILQ_FIRST(@entry^.instances);
while (node<>nil) do
begin
vm_track_object_trigger(map,node^.obj,start,__end);
node:=TAILQ_NEXT(node,@node^.entry_link);
end;
end;
//
function in_obj_list(const b:TAILQ_HEAD;obj:p_vm_track_object):Boolean;
@ -287,19 +292,19 @@ begin
Result:=True;
end;
procedure copy_obj_list(const src:TAILQ_HEAD;entry:p_vm_track_map_entry);
procedure copy_obj_list(src,dst:p_vm_track_map_entry);
var
node:p_vm_track_object_instance;
begin
TAILQ_INIT(@entry^.instances);
TAILQ_INIT(@dst^.instances);
node:=TAILQ_FIRST(@src);
node:=TAILQ_FIRST(@src^.instances);
while (node<>nil) do
begin
_vm_track_entry_add_obj(entry,node^.obj);
_vm_track_entry_add_obj(dst,node^.obj);
node:=TAILQ_NEXT(node,@node^.entry_link);
end;
@ -650,7 +655,7 @@ begin
new_entry^.__end:=start;
copy_obj_list(entry^.instances,new_entry);
copy_obj_list(entry,new_entry);
entry^.start:=start;
@ -678,7 +683,7 @@ begin
entry^.__end:=__end;
copy_obj_list(entry^.instances,new_entry);
copy_obj_list(entry,new_entry);
vm_track_map_entry_link(map, entry, new_entry);
end;
@ -691,11 +696,11 @@ begin
end;
end;
function vm_track_map_insert(map:p_vm_track_map;start,__end:vm_offset_t;obj:p_vm_track_object):Integer;
function _vm_track_map_insert(map:p_vm_track_map;start,__end:vm_offset_t;obj:p_vm_track_object):Integer;
var
current,entry:p_vm_track_map_entry;
begin
if (start=__end) then
if (start>=__end) then
begin
Exit(KERN_SUCCESS);
end;
@ -736,7 +741,7 @@ begin
vm_track_map_lock(map);
Result:=vm_track_map_insert(map,obj^.main.start,obj^.main.__end,obj);
Result:=_vm_track_map_insert(map,obj^.main.start,obj^.main.__end,obj);
vm_track_map_unlock(map);
end;
@ -889,24 +894,37 @@ begin
end;
function vm_track_map_trigger(map:p_vm_track_map;start,__end:vm_offset_t):Integer;
label
_repeat;
var
last:vm_offset_t;
current,entry:p_vm_track_map_entry;
node,next:p_vm_track_object_instance;
ret:Integer;
change:Boolean;
begin
if (start=__end) then
Result:=0; //count
if (start>=__end) or (map=nil) then
begin
Exit(KERN_SUCCESS);
Exit;
end;
if (map=nil) then
begin
Exit(KERN_INVALID_ARGUMENT);
end;
last:=start;
vm_track_map_lock(map);
vm_track_map_RANGE_CHECK(map, start, __end);
vm_track_map_RANGE_CHECK(map, last, __end);
if (vm_track_map_lookup_entry(map, start, @entry)) then
_repeat:
if (last>=__end) then
begin
vm_track_map_unlock(map);
Exit;
end;
if (vm_track_map_lookup_entry(map, last, @entry)) then
begin
//
end else
@ -918,12 +936,121 @@ begin
while (current<>@map^.header) and (current^.start<__end) do
begin
vm_track_entry_trigger(map,current,start,__end);
last:=current^.__end;
change:=False;
node:=TAILQ_FIRST(@entry^.instances);
while (node<>nil) do
begin
next:=TAILQ_NEXT(node,@node^.entry_link);
ret:=vm_track_object_trigger(map,node^.obj,start,__end);
if ((ret and DO_DELETE)<>0) then
begin
//delete full object
vm_track_map_delete_object(map, node^.obj);
change:=True;
end;
if ((ret and DO_INCREMENT)<>0) then
begin
Inc(Result);
end;
node:=next;
end;
if change then
begin
goto _repeat;
end;
current:=current^.next;
end;
vm_track_map_unlock(map);
end;
function _vm_track_map_insert_mirror(map:p_vm_track_map;src,dst,size:vm_offset_t):Integer;
label
_repeat;
var
last :vm_offset_t;
start:vm_offset_t;
__end:vm_offset_t;
e_start:vm_offset_t;
e___end:vm_offset_t;
d_start:vm_offset_t;
d___end:vm_offset_t;
entry:p_vm_track_map_entry;
node,next:p_vm_track_object_instance;
begin
start:=src;
__end:=src+size;
VM_MAP_ASSERT_LOCKED(map);
vm_track_map_RANGE_CHECK(map, start, __end);
last:=start;
_repeat:
if (last>=__end) then
begin
Exit;
end;
if (vm_track_map_lookup_entry(map, start, @entry)) then
begin
//
end else
begin
entry:=entry^.next;
end;
while (entry<>@map^.header) and (entry^.start<__end) do
begin
e_start:=entry^.start;
e___end:=entry^.__end;
last:=e___end;
if (e_start<start) then
begin
e_start:=start;
end;
if (e___end>__end) then
begin
e___end:=__end;
end;
if (e___end>e_start) then
begin
d_start:=dst+(e_start-src);
d___end:=d_start+(e___end-e_start);
node:=TAILQ_FIRST(@entry^.instances);
while (node<>nil) do
begin
next:=TAILQ_NEXT(node,@node^.entry_link);
_vm_track_map_insert(map,d_start,d___end,node^.obj);
node:=next;
end;
goto _repeat;
end;
entry:=entry^.next;
end;
Result:=(KERN_SUCCESS);
end;