diff --git a/rtl/x86_jit.pas b/rtl/x86_jit.pas index a51aa724..aa69fdfc 100644 --- a/rtl/x86_jit.pas +++ b/rtl/x86_jit.pas @@ -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; diff --git a/sys/jit/kern_jit.pas b/sys/jit/kern_jit.pas index 2b6be9f0..0c451aeb 100644 --- a/sys/jit/kern_jit.pas +++ b/sys/jit/kern_jit.pas @@ -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; diff --git a/sys/jit/kern_jit_ctx.pas b/sys/jit/kern_jit_ctx.pas index e0c9e34b..2ceb332c 100644 --- a/sys/jit/kern_jit_ctx.pas +++ b/sys/jit/kern_jit_ctx.pas @@ -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. diff --git a/sys/jit/kern_jit_dynamic.pas b/sys/jit/kern_jit_dynamic.pas index 3c917e29..761bbf29 100644 --- a/sys/jit/kern_jit_dynamic.pas +++ b/sys/jit/kern_jit_dynamic.pas @@ -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. diff --git a/sys/kern/kern_dmem.pas b/sys/kern/kern_dmem.pas index f756ee15..ad6262e0 100644 --- a/sys/kern/kern_dmem.pas +++ b/sys/kern/kern_dmem.pas @@ -149,6 +149,8 @@ begin dmem.vmap:=vmap; dmem.rmap:=@rmap; + + rmap.tmap:=@vmap^.pmap^.tr_map; end; const diff --git a/sys/md/vm_pmap.pas b/sys/md/vm_pmap.pas index a3959719..3cb73bc6 100644 --- a/sys/md/vm_pmap.pas +++ b/sys/md/vm_pmap.pas @@ -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? diff --git a/sys/md/vm_pmap_prot.pas b/sys/md/vm_pmap_prot.pas index aebcd04b..9c20dad5 100644 --- a/sys/md/vm_pmap_prot.pas +++ b/sys/md/vm_pmap_prot.pas @@ -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; diff --git a/sys/vm/rmem_map.pas b/sys/vm/rmem_map.pas index db446839..d7e56aa6 100644 --- a/sys/vm/rmem_map.pas +++ b/sys/vm/rmem_map.pas @@ -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 (__ende_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. diff --git a/sys/vm/vm_map.pas b/sys/vm/vm_map.pas index f389df87..d51a1725 100644 --- a/sys/vm/vm_map.pas +++ b/sys/vm/vm_map.pas @@ -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 (__ende_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. + + diff --git a/sys/vm/vm_nt_map.pas b/sys/vm/vm_nt_map.pas index 72840694..ba0c7a4f 100644 --- a/sys/vm/vm_nt_map.pas +++ b/sys/vm/vm_nt_map.pas @@ -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__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; diff --git a/sys/vm/vm_tracking_map.pas b/sys/vm/vm_tracking_map.pas index befb9f48..7b236635 100644 --- a/sys/vm/vm_tracking_map.pas +++ b/sys/vm/vm_tracking_map.pas @@ -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__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;