diff --git a/sys/kern/kern_dlsym.pas b/sys/kern/kern_dlsym.pas index 0f04c067..3b1ed14d 100644 --- a/sys/kern/kern_dlsym.pas +++ b/sys/kern/kern_dlsym.pas @@ -39,7 +39,8 @@ implementation uses errno, - elf_nid_utils; + elf_nid_utils, + kern_stub; function convert_raw_symbol_str_to_base64(symbol:pchar):RawByteString; var @@ -363,6 +364,45 @@ begin end; end; +//48 8D 3D 00 00 00 00 lea rdi,[rip+$00000000] lea (%rip),%rdi + +type + p_jmpq64_trampoline=^t_jmpq64_trampoline; + t_jmpq64_trampoline=packed record + lea:array[0..6] of Byte; + // + inst :Word; //FF 25 + offset:DWORD; //00 + addr :QWORD; + str :PChar; + end; + +const + c_jmpq64_trampoline:t_jmpq64_trampoline=(lea:($48,$8D,$3D,$F9,$FF,$FF,$FF);inst:$25FF;offset:0;addr:0); + +procedure _unresolve_symbol(data:p_jmpq64_trampoline); +begin + Writeln('_unresolve_symbol:',data^.str); + readln; +end; + +function get_unresolve_ptr(str:PChar):Pointer; +var + stub:p_stub_chunk; +begin + stub:=p_alloc(nil,SizeOf(t_jmpq64_trampoline)); + + p_jmpq64_trampoline(@stub^.body)^:=c_jmpq64_trampoline; + p_jmpq64_trampoline(@stub^.body)^.addr:=QWORD(@_unresolve_symbol); + p_jmpq64_trampoline(@stub^.body)^.str:=str; + + Result:=@stub^.body; +end; + + + +//kern_stub + function find_symdef(symnum:QWORD;refobj:p_lib_info;var defobj_out:p_lib_info;flags:DWORD;cache:p_SymCache):p_elf64_sym; var req:t_SymLook; @@ -370,8 +410,14 @@ var ref:p_elf64_sym; defobj:p_lib_info; str:pchar; + count:Integer; err:Integer; ST_BIND:Integer; + + nModuleId,nLibraryId:WORD; + nNid:QWORD; + + fname:RawByteString; begin Result:=nil; @@ -389,8 +435,8 @@ begin def:=nil; defobj_out:=nil; - err:=refobj^.rel_data^.symtab_size div SizeOf(elf64_sym); - if (symnum<=err) then Exit(nil); + count:=refobj^.rel_data^.symtab_size div SizeOf(elf64_sym); + if (symnum>=count) then Exit(nil); ref:=refobj^.rel_data^.symtab_addr + symnum; @@ -411,9 +457,20 @@ begin req:=Default(t_SymLook); req.symbol:=str; - req.flags :=(flags or SYMLOOK_MANGLED); + req.flags :=(flags{ or SYMLOOK_MANGLED}); req.obj :=refobj; + if DecodeEncName(str,nModuleId,nLibraryId,nNid) then + begin + req.modname:=get_mod_name(refobj,nModuleId); + req.libname:=get_lib_name(refobj,nLibraryId); + + fname:=BaseEncName(str); + + req.name:=pchar(fname); + end; + + //convert_mangled_name_to_long //req.libname //req.name @@ -432,6 +489,15 @@ begin begin def :=@dynlibs_info.sym_zero; defobj:=dynlibs_info.libprogram; + end else + 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)); + + def :=@dynlibs_info.sym_nops; + defobj:=dynlibs_info.libprogram; + end; end; diff --git a/sys/kern/kern_patcher.pas b/sys/kern/kern_patcher.pas index f38a8917..791b8da2 100644 --- a/sys/kern/kern_patcher.pas +++ b/sys/kern/kern_patcher.pas @@ -9,93 +9,16 @@ uses mqueue, kern_stub; -type - t_patch_type=(pt_fsbase,pt_gsbase,pt_syscall); - - p_patch_node=^t_patch_node; - t_patch_node=record - link :TAILQ_ENTRY; - vaddr:Pointer; - ptype:t_patch_type; - stub :p_stub_chunk; - end; - -procedure add_patch_link (_obj,vaddr:Pointer;ptype:t_patch_type;stub:p_stub_chunk); -procedure free_patch_link(_obj:Pointer;node:p_patch_node); -procedure vm_object_patch_remove(_obj:Pointer;start,__end:DWORD); - procedure patcher_process_section(_obj,data,vaddr:Pointer;filesz:QWORD); implementation uses - hamt, - kern_rwlock, kern_thr, - vm, - vmparam, - vm_map, - vm_mmap, - vm_object, vm_pmap, + vm_patch_link, trap; -procedure add_patch_link(_obj,vaddr:Pointer;ptype:t_patch_type;stub:p_stub_chunk); -var - obj:vm_object_t; - node:p_patch_node; -begin - Writeln('patch:vaddr=0x',HexStr(vaddr),' type:',ptype); - - obj:=_obj; - node:=AllocMem(SizeOf(t_patch_node)); - node^.vaddr:=vaddr; - node^.ptype:=ptype; - node^.stub :=stub; - - p_inc_ref(stub); - - TAILQ_INSERT_TAIL(@obj^.patchq,node,@node^.link); -end; - -procedure free_patch_link(_obj:Pointer;node:p_patch_node); -var - obj:vm_object_t; -begin - obj:=_obj; - TAILQ_REMOVE(@obj^.patchq,node,@node^.link); - - p_dec_ref(node^.stub); - FreeMem(node); -end; - -function OFF_TO_IDX(x:Pointer):DWORD; inline; -begin - Result:=QWORD(x) shr PAGE_SHIFT; -end; - -procedure vm_object_patch_remove(_obj:Pointer;start,__end:DWORD); -var - obj:vm_object_t; - entry,next:p_patch_node; -begin - obj:=_obj; - - entry:=TAILQ_FIRST(@obj^.patchq); - while (entry<>nil) do - begin - next:=TAILQ_NEXT(entry,@entry^.link); - // - if ((start=0) or (OFF_TO_IDX(entry^.vaddr)>=start)) and - ((__end=0) or (OFF_TO_IDX(entry^.vaddr)<=__end)) then - begin - free_patch_link(_obj,entry); - end; - // - entry:=next; - end; -end; - { 64 48 A1 [0000000000000000] mov rax,fs:[$0000000000000000] -> 65 48 A1 [0807000000000000] mov rax,gs:[$0000000000000708] 64 48 8B 04 25 [00000000] mov rax,fs:[$00000000] -> 65 48 8B 04 25 [08070000] mov rax,gs:[$00000708] @@ -533,10 +456,32 @@ begin Result:=-1; end; -procedure _fast_syscall; assembler; nostackframe; -asm - mov %rax,%rax - jmp fast_syscall +procedure vm_add_syscall_patch(_obj,vaddr,addr_out:Pointer); +var + stub:p_stub_chunk; + + jmpq64_trampoline:t_jmpq64_trampoline; + call32_trampoline:t_call32_trampoline; + + delta:Int64; +begin + stub:=p_alloc(vaddr,SizeOf(t_jmpq64_trampoline)); + + delta:=Int64(@stub^.body)-(Int64(vaddr)+SizeOf(t_call32_trampoline)); + Assert(delta=(size+SizeOf(stub_chunk))) then begin delta:=abs(Int64(vaddr)-Int64(@entry^.body)); - if (delta is_big_app + //bit 2 -> first find addr is (1 shl 33) -> + // _sceKernelMapFlexibleMemory + // _sceKernelMapDirectMemory + // sceKernelMapDirectMemory2 + + //excp_flags + //bit 1 -> use in [libkernel_exception] -> + // -> sceKernelInstallExceptionHandler + // -> sceKernelRemoveExceptionHandler + // -> sceKernelAddGpuExceptionEvent + // -> sceKernelDeleteGpuExceptionEvent + // -> sceKernelBacktraceSelf + //bit 2 -> sys_mdbg_service + +type + TCUSANAME=array[0..9] of AnsiChar; + + PSCE_APP_ENV=^TSCE_APP_ENV; + TSCE_APP_ENV=packed record + AppId :Integer; //4 + mmap_flags :Integer; //4 + excp_flags :Integer; //4 + AppType :Integer; //4 5? + CUSANAME :TCUSANAME; //10 + debug_level:Byte; //1 + slv_flags :Byte; //1 eLoadOptions + f_1c :Byte; + f_1d :Byte; + f_1e :Byte; + f_1f :Byte; + f_20 :QWORD; + f_28 :Integer; + f_2c :Integer; + f_30 :Integer; + f_34 :Integer; + f_38 :QWORD; + f_40 :QWORD; + end; + {$IF sizeof(TSCE_APP_ENV)<>72}{$STOP sizeof(TSCE_APP_ENV)<>72}{$ENDIF} + +var + G_APPINFO:TSCE_APP_ENV; + +function sysctl_kern_proc_appinfo(oidp:p_sysctl_oid;arg1:Pointer;arg2:ptrint;req:p_sysctl_req):Integer; +var + pid:Integer; + + APPINFO:TSCE_APP_ENV; +begin + if (req^.oldlen > 72) then Exit(EINVAL); + + pid:=PInteger(arg1)^; + + if (pid<>g_pid) then Exit(EINVAL); + + //sceSblACMgrIsSystemUcred()!=0 -> any proc + //sceSblACMgrIsSystemUcred()==0 -> cur proc + + Result:=SYSCTL_OUT(req,@G_APPINFO,SizeOf(TSCE_APP_ENV)); + + if (Result=0) and (req^.newlen=SizeOf(TSCE_APP_ENV)) then + begin + Result:=SYSCTL_IN(req,@APPINFO,SizeOf(TSCE_APP_ENV)); + if (Result=0) then + begin + G_APPINFO:=APPINFO; + end; + end; + +end; + function sysctl_kern_proc(name:PInteger;namelen:DWORD;noid:p_sysctl_oid;req:p_sysctl_req):Integer; begin if (namelen=0) then Exit(ENOTDIR); Result:=ENOENT; - Writeln(StdErr,'sysctl_kern_proc:',name[0]); + case name[0] of + KERN_PROC_APPINFO:Result:=SYSCTL_HANDLE(noid,name,@sysctl_kern_proc_appinfo); + + else + begin + Writeln(StdErr,'Unhandled sysctl_kern_proc:',name[0]); + Assert(False); + end; + end; end; function sysctl_kern(name:PInteger;namelen:DWORD;noid:p_sysctl_oid;req:p_sysctl_req):Integer; @@ -233,10 +325,11 @@ begin case name[0] of KERN_PROC:Result:=sysctl_kern_proc(name+1,namelen-1,noid,req); - KERN_ARND:Result:=SYSCTL_HANDLE(noid,@sysctl_kern_arandom); + KERN_ARND:Result:=SYSCTL_HANDLE(noid,name,@sysctl_kern_arandom); else begin Writeln(StdErr,'Unhandled sysctl_kern:',name[0]); + Assert(False); end; end; end; @@ -253,7 +346,8 @@ begin CTL_KERN:Result:=sysctl_kern(name+1,namelen-1,noid,req); else begin - Writeln(StdErr,'Unhandled sysctl_find_oid:',name[0]); + Writeln(StdErr,'Unhandled sysctl_root:',name[0]); + Assert(False); end; end; end; @@ -264,6 +358,7 @@ function sysctl_root(oidp:p_sysctl_oid; req :p_sysctl_req):Integer; var oid:t_sysctl_oid; + indx:Integer; begin oid:=Default(t_sysctl_oid); @@ -271,6 +366,12 @@ begin if (Result<>0) then Exit; if (oid.oid_handler=nil) then Exit(EINVAL); + if (oid.oid_name =nil) then Exit(EINVAL); + + indx:=oid.oid_name-arg1; + + arg1:=arg1 + indx; + arg2:=arg2 - indx; //if ((oid.oid_kind and CTLTYPE)=CTLTYPE_NODE) then //begin diff --git a/sys/kern/subr_dynlib.pas b/sys/kern/subr_dynlib.pas index ebdd4d0e..1c50d78d 100644 --- a/sys/kern/subr_dynlib.pas +++ b/sys/kern/subr_dynlib.pas @@ -209,6 +209,7 @@ type sysc_e00:Pointer; sym_zero:elf64_sym; + sym_nops:elf64_sym; dyn_non_exist:Integer; end; @@ -2200,7 +2201,7 @@ begin Result:=nil; err:=0; - fname:=ExtractFileName(path); + fname:=dynlib_basename(path); obj:=TAILQ_FIRST(@dynlibs_info.obj_list); while (obj<>nil) do @@ -2239,6 +2240,8 @@ begin fname:=ChangeFileExt(fname,'.prx'); if rtld_file_exists(pchar(fname)) then goto _do_load; + Writeln(StdErr,' prx module not found:',path); + err:=ENOENT; Exit(nil); diff --git a/sys/test/project1.lpi b/sys/test/project1.lpi index 5928abb9..3dfd0a32 100644 --- a/sys/test/project1.lpi +++ b/sys/test/project1.lpi @@ -605,6 +605,10 @@ + + + + diff --git a/sys/vm/vm_object.pas b/sys/vm/vm_object.pas index dd96b3f6..e11ca088 100644 --- a/sys/vm/vm_object.pas +++ b/sys/vm/vm_object.pas @@ -108,7 +108,7 @@ uses vmparam, vnode, vfs_subr, - kern_patcher; + vm_patch_link; function IDX_TO_OFF(x:DWORD):QWORD; inline; begin diff --git a/sys/vm/vm_patch_link.pas b/sys/vm/vm_patch_link.pas new file mode 100644 index 00000000..7f7e0466 --- /dev/null +++ b/sys/vm/vm_patch_link.pas @@ -0,0 +1,95 @@ +unit vm_patch_link; + +{$mode ObjFPC}{$H+} +{$CALLING SysV_ABI_CDecl} + +interface + +uses + mqueue, + kern_stub; + +type + t_patch_type=(pt_fsbase,pt_gsbase,pt_syscall); + + p_patch_node=^t_patch_node; + t_patch_node=record + link :TAILQ_ENTRY; + vaddr:Pointer; + ptype:t_patch_type; + stub :p_stub_chunk; + end; + +procedure vm_add_patch_link(_obj,vaddr:Pointer;ptype:t_patch_type;stub:p_stub_chunk); +procedure vm_object_patch_remove(_obj:Pointer;start,__end:DWORD); + +implementation + +uses + vmparam, + vm_object; + +procedure vm_add_patch_link(_obj,vaddr:Pointer;ptype:t_patch_type;stub:p_stub_chunk); +var + obj:vm_object_t; + node:p_patch_node; +begin + //Writeln('patch:vaddr=0x',HexStr(vaddr),' type:',ptype); + + obj:=_obj; + node:=AllocMem(SizeOf(t_patch_node)); + node^.vaddr:=vaddr; + node^.ptype:=ptype; + node^.stub :=stub; + + p_inc_ref(stub); + + VM_OBJECT_LOCK(obj); + TAILQ_INSERT_TAIL(@obj^.patchq,node,@node^.link); + VM_OBJECT_UNLOCK(obj); +end; + +procedure vm_free_patch_link(_obj:Pointer;node:p_patch_node); +var + obj:vm_object_t; +begin + obj:=_obj; + TAILQ_REMOVE(@obj^.patchq,node,@node^.link); + + p_dec_ref(node^.stub); + FreeMem(node); +end; + +function OFF_TO_IDX(x:Pointer):DWORD; inline; +begin + Result:=QWORD(x) shr PAGE_SHIFT; +end; + +procedure vm_object_patch_remove(_obj:Pointer;start,__end:DWORD); +var + obj:vm_object_t; + entry,next:p_patch_node; +begin + obj:=_obj; + + VM_OBJECT_LOCK(obj); + + entry:=TAILQ_FIRST(@obj^.patchq); + while (entry<>nil) do + begin + next:=TAILQ_NEXT(entry,@entry^.link); + // + if ((start=0) or (OFF_TO_IDX(entry^.vaddr)>=start)) and + ((__end=0) or (OFF_TO_IDX(entry^.vaddr)<=__end)) then + begin + vm_free_patch_link(_obj,entry); + end; + // + entry:=next; + end; + + VM_OBJECT_UNLOCK(obj); +end; + +end. +