diff --git a/rtl/x86_index_instr.pas b/rtl/x86_index_instr.pas new file mode 100644 index 00000000..3bb3d598 --- /dev/null +++ b/rtl/x86_index_instr.pas @@ -0,0 +1,260 @@ +unit x86_index_instr; + +{$mode ObjFPC}{$H+} +{$CALLING SysV_ABI_CDecl} + +interface + +const + //instruction reg + RAX= 0; + RCX= 1; + RDX= 2; + RBX= 3; + RSP= 4; + RBP= 5; + RSI= 6; + RDI= 7; + R8 = 8; + R9 = 9; + R10=10; + R11=11; + R12=12; + R13=13; + R14=14; + R15=15; + + //instruction segment base + FSBASE=16; + GSBASE=17; + + //instruction id + I_MOV_BASE32=0; + I_MOV_BASE64=1; + I_SYSCALL =2; + +type + p_instr_index_info=^t_instr_index_info; + t_instr_index_info=record + inlen:Byte; //instruction len + instr:Byte; //instruction id + inreg:Byte; //instruction reg + sbase:Byte; //instruction segment base + osize:Byte; //instruction data offset size + offst:Int64; //instruction data offset + end; + +function IndexInstr(var pbuf:Pointer;pend:Pointer;var info:t_instr_index_info):Boolean; + +implementation + +function IndexInstr(var pbuf:Pointer;pend:Pointer;var info:t_instr_index_info):Boolean; +var + psrc:Pointer; + W:DWORD; + i:Integer; + offset:Int64; +begin + Result:=False; + + i:=-1; + + psrc:=pbuf; + while (psrc$25) then + begin + Inc(psrc,4); + Continue; + end; + + offset:=PInteger(@PBYTE(psrc)[5])^; + + if (offset>+65536) or + (offset<-65536) then + begin + Inc(psrc,4); + Continue; + end; + + info.inlen:=9; + info.instr:=I_MOV_BASE32; + + case i of + 0..15:info.inreg:=i; + 17..32:info.inreg:=i-17; + else; + end; + + case i of + 0..15:info.sbase:=FSBASE; + 17..32:info.sbase:=GSBASE; + else; + end; + + info.osize:=4; + info.offst:=offset; + end; + 16, + 33: + begin + offset:=PInt64(@PBYTE(psrc)[3])^; + + if (offset>+65536) or + (offset<-65536) then + begin + Inc(psrc,4); + Continue; + end; + + info.inlen:=12; + info.instr:=I_MOV_BASE64; + info.inreg:=RAX; + + case i of + 16:info.sbase:=FSBASE; + 33:info.sbase:=GSBASE; + else; + end; + + info.osize:=8; + info.offst:=offset; + end; + 34: + begin + if (PDWORD(@PBYTE(psrc)[4])^<>$050FCA89) then + begin + Inc(psrc,4); + Continue; + end; + + Case PBYTE(psrc)[8] of + $41, + $48, + $5f, + $72, + $c3:; + else + begin + Inc(psrc,4); + Continue; + end; + end; + + Inc(psrc,3); + + info.inlen:=5; + info.instr:=I_SYSCALL; + info.sbase:=0; + info.osize:=0; + info.offst:=0; + end; + else; + end; + + if (i<>-1) then + begin + pbuf:=psrc; + Exit(True); + end; + + Inc(psrc); + end; //while +end; + +end. + diff --git a/sys/kern/kern_dlsym.pas b/sys/kern/kern_dlsym.pas index 3b1ed14d..3a369202 100644 --- a/sys/kern/kern_dlsym.pas +++ b/sys/kern/kern_dlsym.pas @@ -371,10 +371,11 @@ type t_jmpq64_trampoline=packed record lea:array[0..6] of Byte; // - inst :Word; //FF 25 - offset:DWORD; //00 - addr :QWORD; - str :PChar; + inst :Word; //FF 25 + offset :DWORD; //00 + addr :QWORD; + str :PChar; + libname:PChar; end; const @@ -382,11 +383,11 @@ const procedure _unresolve_symbol(data:p_jmpq64_trampoline); begin - Writeln('_unresolve_symbol:',data^.str); + Writeln('_unresolve_symbol:',data^.str,':',data^.libname); readln; end; -function get_unresolve_ptr(str:PChar):Pointer; +function get_unresolve_ptr(str,libname:PChar):Pointer; var stub:p_stub_chunk; begin @@ -395,6 +396,7 @@ begin p_jmpq64_trampoline(@stub^.body)^:=c_jmpq64_trampoline; p_jmpq64_trampoline(@stub^.body)^.addr:=QWORD(@_unresolve_symbol); p_jmpq64_trampoline(@stub^.body)^.str:=str; + p_jmpq64_trampoline(@stub^.body)^.libname:=libname; Result:=@stub^.body; end; @@ -493,7 +495,7 @@ begin begin dynlibs_info.sym_nops.st_info :=(STB_GLOBAL shl 4) or STT_NOTYPE; dynlibs_info.sym_nops.st_shndx:=SHN_UNDEF; - dynlibs_info.sym_nops.st_value:=-Int64(dynlibs_info.libprogram^.relocbase)+Int64(get_unresolve_ptr(str)); + dynlibs_info.sym_nops.st_value:=-Int64(dynlibs_info.libprogram^.relocbase)+Int64(get_unresolve_ptr(str,req.libname)); def :=@dynlibs_info.sym_nops; defobj:=dynlibs_info.libprogram; diff --git a/sys/kern/kern_exec.pas b/sys/kern/kern_exec.pas index 87c643e9..8f1f5de6 100644 --- a/sys/kern/kern_exec.pas +++ b/sys/kern/kern_exec.pas @@ -844,6 +844,11 @@ begin end; end; +procedure null_init; assembler; nostackframe; +asm + // +end; + function dynlib_proc_initialize_step2(imgp:p_image_params):Integer; var obj,tail:p_lib_info; @@ -895,8 +900,8 @@ begin tail, dynlibs_info.init_proc_list); - obj^.init_proc_addr:=init_proc_addr; - obj^.fini_proc_addr:=fini_proc_addr; + obj^.init_proc_addr:=@null_init;//init_proc_addr; + obj^.fini_proc_addr:=@null_init;//fini_proc_addr; /// end; diff --git a/sys/kern/kern_patcher.pas b/sys/kern/kern_patcher.pas index 791b8da2..768722ff 100644 --- a/sys/kern/kern_patcher.pas +++ b/sys/kern/kern_patcher.pas @@ -17,7 +17,8 @@ uses kern_thr, vm_pmap, vm_patch_link, - trap; + trap, + x86_index_instr; { 64 48 A1 [0000000000000000] mov rax,fs:[$0000000000000000] -> 65 48 A1 [0807000000000000] mov rax,gs:[$0000000000000708] @@ -39,6 +40,25 @@ uses 64 4C 8B 3C 25 [00000000] mov r15,fs:[$00000000] -> 65 4C 8B 3C 25 [08070000] mov r15,gs:[$00000708] } +{ +90488B80 [11111111] mov rax,[rax+$11111111] +90488B89 [11111111] mov rcx,[rcx+$11111111] +90488B92 [11111111] mov rdx,[rdx+$11111111] +90488B9B [11111111] mov rbx,[rbx+$11111111] +488BA424 [11111111] mov rsp,[rsp+$11111111] +90488BAD [11111111] mov rbp,[rbp+$11111111] +90488BB6 [11111111] mov rsi,[rsi+$11111111] +90488BBF [11111111] mov rdi,[rdi+$11111111] +904D8B80 [11111111] mov r8 ,[r8 +$11111111] +904D8B89 [11111111] mov r9 ,[r9 +$11111111] +904D8B92 [11111111] mov r10,[r10+$11111111] +904D8B9B [11111111] mov r11,[r11+$11111111] +4D8BA424 [11111111] mov r12,[r12+$11111111] +904D8BAD [11111111] mov r13,[r13+$11111111] +904D8BB6 [11111111] mov r14,[r14+$11111111] +904D8BBF [11111111] mov r15,[r15+$11111111] +} + { [48 b8 | 10 01 00 00 00 00 00 00]:MOV RAX,0x110 @@ -201,6 +221,7 @@ c3 RET } type + { p_patch_base_long=^t_patch_base_long; t_patch_base_long=packed record len :Byte ; //12 @@ -221,6 +242,7 @@ type 1:(B:t_patch_base_short); 2:(C:array[0..11] of Byte); end; + } p_jmpq64_trampoline=^t_jmpq64_trampoline; t_jmpq64_trampoline=packed record @@ -235,8 +257,28 @@ type addr:Integer; end; + p_mov_rel_base32=^t_mov_rel_base32; + t_mov_rel_base32=packed record + inst:array[0..4] of Byte; + addr:Integer; //teb_tcb/teb_gsbase + end; + + p_mov_rel32=^t_mov_rel32; + t_mov_rel32=packed record + inst:array[0..3] of Byte; + addr:Integer; //offset + end; + + p_base_data_trampoline=^t_base_data_trampoline; + t_base_data_trampoline=packed record + bseg:t_mov_rel_base32; + data:t_mov_rel32; + bjmp:t_jmpq64_trampoline; + end; + const - patch_table:array[0..33] of t_patch_inst=( + { + patch_table:array[0..33] of t_patch_inst=( (B:(len: 9;inst:($65,$48,$8B,$04,$25);addr:teb_tcb )), (B:(len: 9;inst:($65,$48,$8B,$0C,$25);addr:teb_tcb )), (B:(len: 9;inst:($65,$48,$8B,$14,$25);addr:teb_tcb )), @@ -273,196 +315,131 @@ const (B:(len: 9;inst:($65,$4C,$8B,$3C,$25);addr:teb_gsbase)), (A:(len:12;inst:($65,$48,$A1 );addr:teb_gsbase)) ); + } + + patch_fs_table:array[0..15] of t_mov_rel_base32=( + (inst:($65,$48,$8B,$04,$25);addr:teb_tcb), + (inst:($65,$48,$8B,$0C,$25);addr:teb_tcb), + (inst:($65,$48,$8B,$14,$25);addr:teb_tcb), + (inst:($65,$48,$8B,$1C,$25);addr:teb_tcb), + (inst:($65,$48,$8B,$24,$25);addr:teb_tcb), + (inst:($65,$48,$8B,$2C,$25);addr:teb_tcb), + (inst:($65,$48,$8B,$34,$25);addr:teb_tcb), + (inst:($65,$48,$8B,$3C,$25);addr:teb_tcb), + (inst:($65,$4C,$8B,$04,$25);addr:teb_tcb), + (inst:($65,$4C,$8B,$0C,$25);addr:teb_tcb), + (inst:($65,$4C,$8B,$14,$25);addr:teb_tcb), + (inst:($65,$4C,$8B,$1C,$25);addr:teb_tcb), + (inst:($65,$4C,$8B,$24,$25);addr:teb_tcb), + (inst:($65,$4C,$8B,$2C,$25);addr:teb_tcb), + (inst:($65,$4C,$8B,$34,$25);addr:teb_tcb), + (inst:($65,$4C,$8B,$3C,$25);addr:teb_tcb) + ); + + patch_gs_table:array[0..15] of t_mov_rel_base32=( + (inst:($65,$48,$8B,$04,$25);addr:teb_gsbase), + (inst:($65,$48,$8B,$0C,$25);addr:teb_gsbase), + (inst:($65,$48,$8B,$14,$25);addr:teb_gsbase), + (inst:($65,$48,$8B,$1C,$25);addr:teb_gsbase), + (inst:($65,$48,$8B,$24,$25);addr:teb_gsbase), + (inst:($65,$48,$8B,$2C,$25);addr:teb_gsbase), + (inst:($65,$48,$8B,$34,$25);addr:teb_gsbase), + (inst:($65,$48,$8B,$3C,$25);addr:teb_gsbase), + (inst:($65,$4C,$8B,$04,$25);addr:teb_gsbase), + (inst:($65,$4C,$8B,$0C,$25);addr:teb_gsbase), + (inst:($65,$4C,$8B,$14,$25);addr:teb_gsbase), + (inst:($65,$4C,$8B,$1C,$25);addr:teb_gsbase), + (inst:($65,$4C,$8B,$24,$25);addr:teb_gsbase), + (inst:($65,$4C,$8B,$2C,$25);addr:teb_gsbase), + (inst:($65,$4C,$8B,$34,$25);addr:teb_gsbase), + (inst:($65,$4C,$8B,$3C,$25);addr:teb_gsbase) + ); + + patch_mov_rel_table:array[0..15] of t_mov_rel32=( + (inst:($90,$48,$8B,$80);addr:0), + (inst:($90,$48,$8B,$89);addr:0), + (inst:($90,$48,$8B,$92);addr:0), + (inst:($90,$48,$8B,$9B);addr:0), + (inst:($48,$8B,$A4,$24);addr:0), + (inst:($90,$48,$8B,$AD);addr:0), + (inst:($90,$48,$8B,$B6);addr:0), + (inst:($90,$48,$8B,$BF);addr:0), + (inst:($90,$4D,$8B,$80);addr:0), + (inst:($90,$4D,$8B,$89);addr:0), + (inst:($90,$4D,$8B,$92);addr:0), + (inst:($90,$4D,$8B,$9B);addr:0), + (inst:($4D,$8B,$A4,$24);addr:0), + (inst:($90,$4D,$8B,$AD);addr:0), + (inst:($90,$4D,$8B,$B6);addr:0), + (inst:($90,$4D,$8B,$BF);addr:0) + ); c_jmpq64_trampoline:t_jmpq64_trampoline=(inst:$25FF;offset:0;addr:0); c_call32_trampoline:t_call32_trampoline=(inst:$E8;addr:0); + c_jmpl32_trampoline:t_call32_trampoline=(inst:$E9;addr:0); -function IndexInstr(var pbuf:Pointer;pend:Pointer;var offset:Int64):Integer; +procedure patch_original(const info:t_instr_index_info;delta:Integer;addr_out:Pointer); var - psrc:Pointer; - W:DWORD; + trampoline:t_call32_trampoline; begin - Result:=-1; - psrc:=pbuf; - while (psrc$25) then - begin - Inc(psrc,4); - Continue; - end; - - offset:=PInteger(@PBYTE(psrc)[5])^; - - if (offset>+65536) or - (offset<-65536) then - begin - Inc(psrc,4); - Continue; - end; - end; - 16, - 33: - begin - offset:=PInt64(@PBYTE(psrc)[3])^; - - if (offset>+65536) or - (offset<-65536) then - begin - Inc(psrc,4); - Continue; - end; - end; - 34: - begin - offset:=0; - - if (PDWORD(@PBYTE(psrc)[4])^<>$050FCA89) then - begin - Inc(psrc,4); - Continue; - end; - - //Write(HexStr(PBYTE(psrc)[0],2),' '); - //Write(HexStr(PBYTE(psrc)[1],2),' '); - //Write(HexStr(PBYTE(psrc)[2],2),' '); - //Write(HexStr(PBYTE(psrc)[3],2),' '); - //Write(HexStr(PBYTE(psrc)[4],2),' '); - //Write(HexStr(PBYTE(psrc)[5],2),' '); - //Write(HexStr(PBYTE(psrc)[6],2),' '); - //Write(HexStr(PBYTE(psrc)[7],2),' '); - //Write(HexStr(PBYTE(psrc)[8],2),' '); - //Write(HexStr(PBYTE(psrc)[9],2),' '); - - Case PBYTE(psrc)[8] of - $41, - $48, - $5f, - $72, - $c3:{Writeln('True')}; - else - begin - //Writeln('False'); - Inc(psrc,4); - Continue; - end; - end; - end; - else; - end; - - if (Result<>-1) then - begin - pbuf:=psrc; - exit; - end; - - Inc(psrc); + case info.instr of + I_MOV_BASE32:trampoline:=c_jmpl32_trampoline; + I_MOV_BASE64:trampoline:=c_jmpl32_trampoline; + I_SYSCALL :trampoline:=c_call32_trampoline; + else; end; - Result:=-1; + + trampoline.addr:=delta; + p_call32_trampoline(addr_out)^:=trampoline; end; -procedure vm_add_syscall_patch(_obj,vaddr,addr_out:Pointer); +procedure vm_add_mov_base_patch(const info:t_instr_index_info;_obj,vaddr,addr_out:Pointer); var stub:p_stub_chunk; - jmpq64_trampoline:t_jmpq64_trampoline; - call32_trampoline:t_call32_trampoline; + trampoline:t_base_data_trampoline; + delta:Int64; +begin + stub:=p_alloc(vaddr,SizeOf(t_base_data_trampoline)); + + delta:=Int64(@stub^.body)-(Int64(vaddr)+SizeOf(t_call32_trampoline)); + Assert(deltanil,'patcher_process_section'); @@ -526,49 +522,22 @@ begin addr:=data; pend:=addr+filesz; repeat - offset:=0; - i:=IndexInstr(addr,pend,offset); + info:=Default(t_instr_index_info); - if (i=-1) then Break; + b:=IndexInstr(addr,pend,info); - Case i of - 0..33: - begin - len:=patch_table[i].C[0]; - // + if (not b) then Break; - if (offset=0) then - begin - Case i of - 0..16: - begin - Inc(fs_count); - do_patch_base_zero(addr,i,pt_fsbase); - end; - 17..33: - begin - Inc(gs_count); - do_patch_base_zero(addr,i,pt_gsbase); - end - else; - end; - end else - begin - //Writeln('patch with offset:',offset); - end; - end; - 34: - begin - Inc(sv_count); - // - do_patch_syscall(addr+3); - len:=9; - end - else - Assert(False); + do_patch_syscall(addr); + + case info.instr of + I_MOV_BASE32:Inc(fs_count); + I_MOV_BASE64:Inc(gs_count); + I_SYSCALL :Inc(sv_count); + else; end; - Inc(addr,len); + Inc(addr,info.inlen); until false; diff --git a/sys/kern/kern_sysctl.pas b/sys/kern/kern_sysctl.pas index 91762b00..41ec839c 100644 --- a/sys/kern/kern_sysctl.pas +++ b/sys/kern/kern_sysctl.pas @@ -69,6 +69,7 @@ const KERN_PROC_IDTABLE =37; //ID table information KERN_PROC_SANITIZER =41; //kern_sanitizer (Sanitizing mode) + KERN_PROC_PTC =43; //Process time counter (value at program start) KERN_PROC_TEXT_SEGMENT=44; //kern_dynlib_get_libkernel_text_segment @@ -416,6 +417,11 @@ begin Result:=SYSCTL_OUT(req,@g_vmspace.sv_usrstack,SizeOf(Pointer)); end; +function sysctl_kern_proc_ptc(oidp:p_sysctl_oid;arg1:Pointer;arg2:ptrint;req:p_sysctl_req):Integer; +begin + Result:=SYSCTL_OUT(req,@p_proc.p_ptc,SizeOf(Int64)); +end; + function sysctl_handle_int(oidp:p_sysctl_oid;arg1:Pointer;arg2:ptrint;req:p_sysctl_req):Integer; var tmpout:Integer; @@ -449,6 +455,13 @@ begin oid[2]:=KERN_CPUS; len^ :=3; end; + 'kern.proc.ptc': + begin + oid[0]:=CTL_KERN; + oid[1]:=KERN_PROC; + oid[2]:=KERN_PROC_PTC; + len^ :=3; + end; else Writeln(StdErr,'Unhandled name2oid:',name); @@ -485,7 +498,7 @@ begin case name[0] of KERN_PROC_APPINFO:Result:=SYSCTL_HANDLE(noid,name,$C0040001,@sysctl_kern_proc_appinfo); - + KERN_PROC_PTC :Result:=SYSCTL_HANDLE(noid,name,$90040009,@sysctl_kern_proc_ptc); else begin Writeln(StdErr,'Unhandled sysctl_kern_proc:',name[0]); diff --git a/sys/kern/kern_thr.pas b/sys/kern/kern_thr.pas index ae0bdbcc..a062fdae 100644 --- a/sys/kern/kern_thr.pas +++ b/sys/kern/kern_thr.pas @@ -315,6 +315,8 @@ var p_sdk_version:Integer; p_sce_replay_exec:Integer; + p_ptc:Int64; + p_nsignals:Int64; p_nvcsw :Int64; p_nivcsw :Int64; @@ -331,7 +333,8 @@ var implementation uses - kern_event; + kern_event, + md_time; function curkthread:p_kthread; assembler; nostackframe; asm @@ -539,6 +542,7 @@ begin mtx_unlock(p_proc.p_mtx); end; + procedure PROC_INIT; begin FillChar(p_proc,SizeOf(p_proc),0); @@ -547,6 +551,8 @@ begin knlist_init_mtx(@p_proc.p_klist,@p_proc.p_mtx); p_proc.p_randomized_path:='system'; + + p_proc.p_ptc:=rdtsc; end; // diff --git a/sys/md/md_time.pas b/sys/md/md_time.pas index 6fcb1052..6d13a447 100644 --- a/sys/md/md_time.pas +++ b/sys/md/md_time.pas @@ -11,6 +11,12 @@ uses Procedure md_timeinit; +function rdtsc:Int64; assembler; +function tsc_calibrate:Int64; + +function get_proc_time:Int64; +function get_proc_time_freq:Int64; + function get_unit_uptime:Int64; procedure unittime(time:PInt64); procedure calcru_proc(user,syst:PInt64); @@ -37,6 +43,72 @@ begin NtSetTimerResolution(max,True,@cur); end; +function rdtsc:Int64; assembler; nostackframe; +asm + rdtsc + shl $0x20,%rdx + or %rdx,%rax +end; + + +function tsc_calibrate:Int64; +const + samples=20; +var + i:Integer; + + tsc_freq :Int64; + qpc_begin:Int64; + tsc_begin:Int64; + qpc_end :Int64; + tsc_end :Int64; + qpc_freq :Int64; +begin + tsc_freq:=0; + qpc_freq:=get_proc_time_freq; + + For i:=0 to samples-1 do + begin + qpc_begin:=get_proc_time; + tsc_begin:=rdtsc; + + Sleep(2); + + qpc_end:=get_proc_time; + tsc_end:=rdtsc; + + tsc_freq:=tsc_freq + (tsc_end - tsc_begin) * qpc_freq div (qpc_end - qpc_begin); + end; + + tsc_freq:=tsc_freq div samples; + + Result:=tsc_freq; +end; + +function get_proc_time:Int64; +var + pc:QWORD; + pf:QWORD; +begin + pc:=0; + pf:=1; + NtQueryPerformanceCounter(@pc,@pf); + + Result:=pc; +end; + +function get_proc_time_freq:Int64; +var + pc:QWORD; + pf:QWORD; +begin + pc:=0; + pf:=1; + NtQueryPerformanceCounter(@pc,@pf); + + Result:=pf; +end; + function mul_div_u64(m,d,v:QWORD):QWORD; sysv_abi_default; assembler; nostackframe; asm movq v,%rax diff --git a/sys/test/project1.lpi b/sys/test/project1.lpi index 5a948983..e5db6426 100644 --- a/sys/test/project1.lpi +++ b/sys/test/project1.lpi @@ -621,6 +621,10 @@ + + + +