From 6bcc9a26c1305cc38ad504a655d14e7922293261 Mon Sep 17 00:00:00 2001 From: Pavel <68122101+red-prig@users.noreply.github.com> Date: Thu, 23 Jan 2025 17:56:51 +0300 Subject: [PATCH] + --- src/np/ps4_libscenpcommon.pas | 108 +++++++++++- sys/jit/kern_jit.pas | 25 ++- sys/jit/kern_jit_dynamic.pas | 9 + sys/kern/kern_dlsym.pas | 1 + sys/kern/subr_dynlib.pas | 308 +++++++++++++++++++++++++--------- 5 files changed, 364 insertions(+), 87 deletions(-) diff --git a/src/np/ps4_libscenpcommon.pas b/src/np/ps4_libscenpcommon.pas index 18ff1830..38b29e70 100644 --- a/src/np/ps4_libscenpcommon.pas +++ b/src/np/ps4_libscenpcommon.pas @@ -595,17 +595,27 @@ begin end; end; -{ +type + pSceKernelEventFlag=PPointer; + pSceKernelEventFlagOptParam=Pointer; + +var + ps4_sceKernelCreateEventFlag:function(ef:pSceKernelEventFlag; + pName:PChar; + attr:DWORD; + initPattern:QWORD; + pOptParam:pSceKernelEventFlagOptParam + ):Integer; + function ps4_sceNpCreateEventFlag(ef:pSceKernelEventFlag; pName:PChar; attr:DWORD; initPattern:QWORD - ):Integer; + ):Integer; begin Result:=ps4_sceKernelCreateEventFlag(ef,pName,attr,initPattern,nil); Result:=(Result shr $1F) and Result; // Looks like bool, but True when Result<0 end; -} function ExecuteGuest_mallocFunc(addr:Pointer;size:size_t;userdata:Pointer):Pointer; external name 'ExecuteGuest'; @@ -615,12 +625,88 @@ var npObj:PSceNpObject; begin npObj:=ExecuteGuest_mallocFunc(mem^.mallocFunc,size+$10,mem^.userdata); - if npObj<>nil then + if (npObj<>nil) then begin npObj^.mem:=mem; Result:=@npObj^.entry; end else + begin Result:=nil; + end; +end; + +// + +type + p_obj_cbs=^t_obj_cbs; + t_obj_cbs=packed record + clear:Pointer; + free :Pointer; + end; + + p_EventFlag=^t_EventFlag; + t_EventFlag=packed record + cbs :p_obj_cbs; + evf :Pointer; + evtype:Integer; + end; + + p_Mutex=^t_Mutex; + t_Mutex=packed record + cbs :p_obj_cbs; + mutex :Pointer; + init :Byte; + end; + +var + global_evf_cbs :p_obj_cbs; + global_mutex_cbs:p_obj_cbs; + +//sce::np::EventFlag::EventFlag(EventFlag *this) +procedure ps4__ZN3sce2np9EventFlagC1Ev(this:p_EventFlag); +begin + this^.cbs :=global_evf_cbs; + this^.evf :=nil; + this^.evtype:=0; +end; + +//sce::np::EventFlag::Create(EventFlag *this,char *name,uint attr) +function ps4__ZN3sce2np9EventFlag6CreateEPKcj(this:p_EventFlag;name:PChar;attr:DWORD):Integer; +begin + Result:=Integer($80559e03); + if (this^.evtype=0) then + begin + Result:=ps4_sceNpCreateEventFlag(@this^.evf,name,attr,0); + if (Result > -1) then + begin + this^.evtype:=1; + end; + end; +end; + +// + +//sce::np::Mutex::Mutex(Mutex *this) +procedure ps4__ZN3sce2np5MutexC1Ev(this:p_Mutex); +begin + this^.cbs :=global_mutex_cbs; + this^.mutex:=nil; + this^.init :=0; +end; + +//sce::np::Mutex::Init(Mutex *this,char *name,uint flags) +function ps4__ZN3sce2np5Mutex4InitEPKcj(this:p_Mutex;name:PChar;flags:DWORD):Integer; +begin + Result:=Integer($80559e03); + if (this^.init=0) then + begin + Result:=ps4_sceNpMutexInit(@this^.mutex,name,(flags and 1)<>0); + if (Result > -1) then + begin + Result:=0; + this^.init:=1; + end; + end; end; function Load_libSceNpCommon(name:pchar):p_lib_info; @@ -652,15 +738,27 @@ begin lib.set_proc($DA3747A0FA52F96D,@ps4_sceNpHeapGetStat); lib.set_proc($C15767EFC1CA737D,@ps4_sceNpHeapDestroy); // - //lib.set_proc($EA3156A407EA01C7,@ps4_sceNpCreateEventFlag); + lib.set_proc($EA3156A407EA01C7,@ps4_sceNpCreateEventFlag); // lib.set_proc($D2CC8D921240355C,@ps4__ZN3sce2np6ObjectnwEmR14SceNpAllocator); + // + lib.set_proc($70C3A0904D8CD9EF,@ps4__ZN3sce2np9EventFlagC1Ev); + lib.set_proc($6A6162FC0BF5F615,@ps4__ZN3sce2np9EventFlag6CreateEPKcj); + // + lib.set_proc($3B502F950537DE92,@ps4__ZN3sce2np5MutexC1Ev); + lib.set_proc($69334E97D101E15E,@ps4__ZN3sce2np5Mutex4InitEPKcj); + // + lib.add_data(@global_evf_cbs ,SizeOf(t_obj_cbs)); + lib.add_data(@global_mutex_cbs,SizeOf(t_obj_cbs)); + // //import module:=Result^.add_mod('libkernel',1); lib:=module.add_lib('libkernel'); + lib.set_proc($0691686E8509A195,@ps4_sceKernelCreateEventFlag); + lib.set_proc($98BF0D0C7F3A8902,@ps4_sceKernelMapNamedFlexibleMemory); lib.set_proc($17C6D41F0006DBCE,@ps4_scePthreadMutexattrInit); diff --git a/sys/jit/kern_jit.pas b/sys/jit/kern_jit.pas index 1ce2d0a5..f72107d6 100644 --- a/sys/jit/kern_jit.pas +++ b/sys/jit/kern_jit.pas @@ -1283,6 +1283,16 @@ begin end; end; +procedure ExecuteStop; SysV_ABI_CDecl; assembler; nostackframe; public; +asm + //restore rbp,rsp + + //load r14,r15,r13 + movq jit_frame.tf_r14(%r13),%r14 + movq jit_frame.tf_r15(%r13),%r15 + movq jit_frame.tf_r13(%r13),%r13 +end; + //rdi -> addr //rsi -> rdi //rdx -> rsi @@ -1290,6 +1300,9 @@ end; //r8 -> rcx //r9 -> r8 +// EXECUTE_MAGIC_ADDR $FFFFFFFFFCAFEDAD +// $0xFCAFEDAD = -55579219 + procedure ExecuteGuest; SysV_ABI_CDecl; assembler; nostackframe; public; asm //save r13 @@ -1323,14 +1336,14 @@ asm xorq %r15,%r15 call jit_jmp_dispatch //in:r14(addr) r15(plt) out:r14(addr) - call %r14 + movq jit_frame.tf_rsp(%r13), %r15 //mov r15,rsp + leaq -8(%r15), %r15 //lea r15,[r15-8] - //restore rbp,rsp + movq $-55579219,(%r15) //mov [r15],magic (sign extend) - //load r14,r15,r13 - movq jit_frame.tf_r14(%r13),%r14 - movq jit_frame.tf_r15(%r13),%r15 - movq jit_frame.tf_r13(%r13),%r13 + movq %r15, jit_frame.tf_rsp(%r13) //mov rsp,r15 + + jmp %r14 end; function is_push_op(Opcode:TOpcode):Boolean; inline; diff --git a/sys/jit/kern_jit_dynamic.pas b/sys/jit/kern_jit_dynamic.pas index 68d90276..cf52f819 100644 --- a/sys/jit/kern_jit_dynamic.pas +++ b/sys/jit/kern_jit_dynamic.pas @@ -655,6 +655,11 @@ begin Result:=Byte(QWORD(addr) shr 4) xor Byte(QWORD(addr) shr 12); end; +procedure ExecuteStop; external; + +const + EXECUTE_MAGIC_ADDR:QWORD=QWORD($FFFFFFFFFCAFEDAD); + function jmp_dispatcher(addr:Pointer;plt:p_jit_plt;from:Pointer):Pointer; public; label _start; @@ -674,6 +679,10 @@ begin begin //switch to internal + if (QWORD(addr)=EXECUTE_MAGIC_ADDR) then + begin + Exit(@ExecuteStop); + end else if ((QWORD(addr) and UNRESOLVE_MAGIC_MASK)=UNRESOLVE_MAGIC_ADDR) then begin if exist_jit_host(from,@td^.td_frame.tf_rip) then diff --git a/sys/kern/kern_dlsym.pas b/sys/kern/kern_dlsym.pas index 7a71bb7b..bd468246 100644 --- a/sys/kern/kern_dlsym.pas +++ b/sys/kern/kern_dlsym.pas @@ -659,6 +659,7 @@ begin str:=obj_get_str(refobj,ref^.st_name); ST_BIND:=ELF64_ST_BIND(ref^.st_info); + if (ST_BIND=STB_LOCAL) then begin def :=ref; diff --git a/sys/kern/subr_dynlib.pas b/sys/kern/subr_dynlib.pas index 0acf943d..f16f22fb 100644 --- a/sys/kern/subr_dynlib.pas +++ b/sys/kern/subr_dynlib.pas @@ -19,10 +19,12 @@ type TLIBRARY=packed object libptr:Pointer; //p_Lib_Entry mod_id:Word; - function set_symb (nid:QWORD;info:Byte;value:Pointer):Boolean; - function set_proc (nid:QWORD;value:Pointer):Boolean; - function set_data (nid:QWORD;value:Pointer):Boolean; + function set_symb (nid:QWORD;info:Byte;value:Pointer;size:QWORD):Boolean; + function set_proc (nid:QWORD;value:Pointer):Boolean; //publish procedure export:[JIT->HLE] or import:[JIT->value^] + function set_data (nid:QWORD;value:Pointer;size:QWORD):Boolean; //publish data export:[JIT->HLE] function set_weak (nid:QWORD;value:Pointer):Boolean; + function add_data (value:PPointer;size:QWORD):Boolean; //alloc local data [guest->value^] + function add_func (value:PPointer;code:Pointer):Boolean; //alloc JIT addr [guest->value^] function get_value(nid:QWORD):Pointer; end; @@ -554,7 +556,7 @@ begin Result.mod_id:=mod_id; end; -function TLIBRARY.set_symb(nid:QWORD;info:Byte;value:Pointer):Boolean; +function TLIBRARY.set_symb(nid:QWORD;info:Byte;value:Pointer;size:QWORD):Boolean; var lib_entry:p_Lib_Entry; h_entry:p_sym_hash_entry; @@ -570,6 +572,7 @@ begin // h_entry^.sym.st_info :=info; h_entry^.sym.st_value:=0; //jit build + h_entry^.sym.st_size :=size; // h_entry^.native:=value; @@ -599,17 +602,67 @@ end; function TLIBRARY.set_proc(nid:QWORD;value:Pointer):Boolean; begin - Result:=set_symb(nid,(STB_GLOBAL shl 4) or STT_FUN,value); + Result:=set_symb(nid,(STB_GLOBAL shl 4) or STT_FUN,value,0); end; -function TLIBRARY.set_data(nid:QWORD;value:Pointer):Boolean; +function TLIBRARY.set_data(nid:QWORD;value:Pointer;size:QWORD):Boolean; begin - Result:=set_symb(nid,(STB_GLOBAL shl 4) or STT_OBJECT,value); + Result:=set_symb(nid,(STB_GLOBAL shl 4) or STT_OBJECT,value,size); end; function TLIBRARY.set_weak(nid:QWORD;value:Pointer):Boolean; begin - Result:=set_symb(nid,(STB_WEAK shl 4) or STT_FUN,value); + Result:=set_symb(nid,(STB_WEAK shl 4) or STT_FUN,value,0); +end; + +function TLIBRARY.add_data(value:PPointer;size:QWORD):Boolean; +var + lib_entry:p_Lib_Entry; + h_entry:p_sym_hash_entry; + data:PPointer; +begin + lib_entry:=libptr; + // + h_entry:=AllocMem(SizeOf(t_sym_hash_entry)); + // + h_entry^.nid :=0; + h_entry^.mod_id:=mod_id; //export -> mod_id=0 + h_entry^.lib_id:=lib_entry^.dval.id; + // + h_entry^.sym.st_info :=(STB_LOCAL shl 4) or STT_OBJECT; + h_entry^.sym.st_value:=0; //preload build + h_entry^.sym.st_size :=size; + // + h_entry^.native:=value; + + TAILQ_INSERT_TAIL(@Lib_Entry^.syms,h_entry,@h_entry^.link); + Inc(Lib_Entry^.count); + Result:=True; +end; + +function TLIBRARY.add_func(value:PPointer;code:Pointer):Boolean; +var + lib_entry:p_Lib_Entry; + h_entry:p_sym_hash_entry; + data:PPointer; +begin + lib_entry:=libptr; + // + h_entry:=AllocMem(SizeOf(t_sym_hash_entry)); + // + h_entry^.nid :=0; + h_entry^.mod_id:=mod_id; //export -> mod_id=0 + h_entry^.lib_id:=lib_entry^.dval.id; + // + h_entry^.sym.st_info :=(STB_LOCAL shl 4) or STT_FUN; + h_entry^.sym.st_value:=PtrUint(code); + h_entry^.sym.st_size :=0; + // + h_entry^.native:=value; + + TAILQ_INSERT_TAIL(@Lib_Entry^.syms,h_entry,@h_entry^.link); + Inc(Lib_Entry^.count); + Result:=True; end; function TLIBRARY.get_value(nid:QWORD):Pointer; @@ -2890,40 +2943,84 @@ end; function map_prx_internal(name:pchar;obj:p_lib_info):Integer; var Lib_Entry:p_Lib_Entry; - h_entry:p_sym_hash_entry; + h_entry :p_sym_hash_entry; hle_import_table:p_hle_import_entry; hle_import_base :PPointer; + hle_local_data :Pointer; map:vm_map_t; - vaddr_lo:QWORD; - vaddr_hi:QWORD; - data :Pointer; + vaddr_lo :QWORD; + vaddr_hi :QWORD; + data :Pointer; export_count:Integer; import_count:Integer; + local_size :QWORD; + s :QWORD; i,error:Integer; begin Result:=0; export_count:=0; import_count:=0; + local_size :=0; //get sym count Lib_Entry:=TAILQ_FIRST(@obj^.lib_table); while (Lib_Entry<>nil) do begin - if (Lib_Entry^.import=0) then //export + // + h_entry:=TAILQ_FIRST(@Lib_Entry^.syms); + while (h_entry<>nil) do begin - export_count:=export_count+Lib_Entry^.count; - end else - begin - import_count:=import_count+Lib_Entry^.count; + // + if (ELF64_ST_BIND(h_entry^.sym.st_info)=STB_LOCAL) then + begin + //local + Case ELF64_ST_TYPE(h_entry^.sym.st_info) of + STT_NOTYPE, + STT_FUN, + STT_SCE: + begin + export_count:=export_count+1; + end; + STT_OBJECT: + begin + local_size:=local_size+h_entry^.sym.st_size; + end; + else; + end; //case + //local + end else + if (ELF64_ST_BIND(h_entry^.sym.st_info)=STB_GLOBAL) then + begin + //global + Case ELF64_ST_TYPE(h_entry^.sym.st_info) of + STT_NOTYPE, + STT_FUN, + STT_SCE: + begin + if (Lib_Entry^.import=0) then //export + begin + export_count:=export_count+1; + end else + begin + import_count:=import_count+1; + end; + end; + else; + end; //case + //global + end; + // + h_entry:=TAILQ_NEXT(h_entry,@h_entry^.link) end; + // Lib_Entry:=TAILQ_NEXT(Lib_Entry,@Lib_Entry^.link) end; //jit export space = (export_count*8) + (import_count*2*8) obj^.text_size:=AlignUp((export_count*8) + (import_count*2*8),PAGE_SIZE); - //jit import space = sceModuleParam + import_count*8 - obj^.data_size:=AlignUp(Sizeof(TsceModuleParam)+import_count*8,PAGE_SIZE); + //jit import space = sceModuleParam + local_size + import_count*8 + obj^.data_size:=AlignUp(Sizeof(TsceModuleParam)+local_size+import_count*8,PAGE_SIZE); //sum obj^.map_size :=obj^.text_size+obj^.data_size; @@ -2966,37 +3063,80 @@ begin pSceModuleParam(data)^:=obj^.module_param^; obj^.module_param:=data; - hle_import_base:=data+sizeOf(TsceModuleParam); //HLE + //per lib global data + hle_local_data :=data+sizeOf(TsceModuleParam); //HLE + + //per lib import table + hle_import_base:=hle_local_data+local_size; //HLE obj^.hle_import_count:=import_count; - //alloc hle import table - if (import_count<>0) then + //alloc hle import table / per lib global data + if (import_count<>0) or (local_size<>0) then begin - hle_import_table:=AllocMem(import_count*SizeOf(t_hle_import_entry)); - obj^.hle_import_table:=hle_import_table; + + if (import_count<>0) then + begin + hle_import_table:=AllocMem(import_count*SizeOf(t_hle_import_entry)); + obj^.hle_import_table:=hle_import_table; + end; i:=0; + s:=0; Lib_Entry:=TAILQ_FIRST(@obj^.lib_table); while (Lib_Entry<>nil) do begin - if (Lib_Entry^.import<>0) then //import + // + h_entry:=TAILQ_FIRST(@Lib_Entry^.syms); + while (h_entry<>nil) do begin - h_entry:=TAILQ_FIRST(@Lib_Entry^.syms); - while (h_entry<>nil) do + // + if (ELF64_ST_BIND(h_entry^.sym.st_info)=STB_LOCAL) then begin - hle_import_table[i].h_entry :=h_entry; - hle_import_table[i].jit_guest_addr :=nil; //jit build - hle_import_table[i].jit_host_addr :=nil; //jit dynamic cache - hle_import_table[i].import_place_addr:=@hle_import_base[i]; - Inc(i); - // - h_entry:=TAILQ_NEXT(h_entry,@h_entry^.link) + //local + Case ELF64_ST_TYPE(h_entry^.sym.st_info) of + STT_OBJECT: + begin + PPointer(h_entry^.native)^:=(hle_local_data+s); + s:=s+h_entry^.sym.st_size; + end; + else; + end; //case + //local + end else + if (ELF64_ST_BIND(h_entry^.sym.st_info)=STB_GLOBAL) then + begin + //global + Case ELF64_ST_TYPE(h_entry^.sym.st_info) of + STT_NOTYPE, + STT_FUN, + STT_SCE: + begin + if (Lib_Entry^.import=0) then //export + begin + // + end else + begin + // + hle_import_table[i].h_entry :=h_entry; + hle_import_table[i].jit_guest_addr :=nil; //jit build + hle_import_table[i].jit_host_addr :=nil; //jit dynamic cache + hle_import_table[i].import_place_addr:=@hle_import_base[i]; + Inc(i); + // + end; + end; + else; + end; //case + //global end; + // + h_entry:=TAILQ_NEXT(h_entry,@h_entry^.link) end; + // Lib_Entry:=TAILQ_NEXT(Lib_Entry,@Lib_Entry^.link) end; - end; + end; //(import_count<>0) //protect text,data vm_map_lock(map); @@ -3118,7 +3258,7 @@ var Lib_Entry:p_Lib_Entry; h_entry:p_sym_hash_entry; - i,hle_count,ST_TYPE:Integer; + i,hle_count:Integer; hle_import_table:p_hle_import_entry; @@ -3142,17 +3282,35 @@ begin h_entry:=TAILQ_FIRST(@Lib_Entry^.syms); while (h_entry<>nil) do begin - ST_TYPE:=ELF64_ST_TYPE(h_entry^.sym.st_info); - Case ST_TYPE of - STT_NOTYPE, - STT_FUN, - STT_SCE: - begin - ctx.add_export_point(h_entry^.native,@h_entry^.sym.st_value); - end; - else; - end; //case + if (ELF64_ST_BIND(h_entry^.sym.st_info)=STB_LOCAL) then + begin + //local + Case ELF64_ST_TYPE(h_entry^.sym.st_info) of + STT_NOTYPE, + STT_FUN, + STT_SCE: + begin + ctx.add_export_point(Pointer(h_entry^.sym.st_value),h_entry^.native); + end; + else; + end; //case + //local + end else + if (ELF64_ST_BIND(h_entry^.sym.st_info)=STB_GLOBAL) then + begin + //global + Case ELF64_ST_TYPE(h_entry^.sym.st_info) of + STT_NOTYPE, + STT_FUN, + STT_SCE: + begin + ctx.add_export_point(h_entry^.native,@h_entry^.sym.st_value); + end; + else; + end; //case + //global + end; h_entry:=TAILQ_NEXT(h_entry,@h_entry^.link) end; @@ -3171,17 +3329,16 @@ begin begin h_entry:=hle_import_table[i].h_entry; - ST_TYPE:=ELF64_ST_TYPE(h_entry^.sym.st_info); - - Case ST_TYPE of - STT_NOTYPE, - STT_FUN, - STT_SCE: - begin - ctx.add_import_point(hle_import_table[i].import_place_addr,@hle_import_table[i].jit_guest_addr); - end; - else; - end; //case + if (ELF64_ST_BIND(h_entry^.sym.st_info)=STB_GLOBAL) then + Case ELF64_ST_TYPE(h_entry^.sym.st_info) of + STT_NOTYPE, + STT_FUN, + STT_SCE: + begin + ctx.add_import_point(hle_import_table[i].import_place_addr,@hle_import_table[i].jit_guest_addr); + end; + else; + end; //case end; end; @@ -3196,26 +3353,25 @@ begin begin h_entry:=hle_import_table[i].h_entry; - ST_TYPE:=ELF64_ST_TYPE(h_entry^.sym.st_info); + if (ELF64_ST_BIND(h_entry^.sym.st_info)=STB_GLOBAL) then + Case ELF64_ST_TYPE(h_entry^.sym.st_info) of + STT_NOTYPE, + STT_FUN, + STT_SCE: + begin + // + Assert(hle_import_table[i].jit_guest_addr<>nil,'jit_guest_addr'); - Case ST_TYPE of - STT_NOTYPE, - STT_FUN, - STT_SCE: - begin - // - Assert(hle_import_table[i].jit_guest_addr<>nil,'jit_guest_addr'); - - node:=fetch_entry(hle_import_table[i].jit_guest_addr); - Assert(node<>nil,'fetch_entry'); - // - hle_import_table[i].jit_host_addr:=node^.dst; - // - node^.dec_ref('fetch_entry'); - // - end; - else; - end; //case + node:=fetch_entry(hle_import_table[i].jit_guest_addr); + Assert(node<>nil,'fetch_entry'); + // + hle_import_table[i].jit_host_addr:=node^.dst; + // + node^.dec_ref('fetch_entry'); + // + end; + else; + end; //case end; end;