diff --git a/kernel/ps4_libkernel.pas b/kernel/ps4_libkernel.pas index 8b6d594d..509c1654 100644 --- a/kernel/ps4_libkernel.pas +++ b/kernel/ps4_libkernel.pas @@ -80,10 +80,10 @@ end; // eStopNotificationReason procedure ps4_sceKernelDebugRaiseException(dwStopReason,dwStopId:DWORD); SysV_ABI_CDecl; -var - t:pthread; +//var +// t:pthread; begin - t:=_get_curthread; + //t:=_get_curthread; //if (t<>nil) then // Writeln('RaiseThread=',t^.name); Writeln(StdErr,'RaiseException:',HexStr(dwStopReason,8),':',HexStr(dwStopId,8),':',GetStopReasonInfo(dwStopReason)); @@ -91,10 +91,10 @@ begin end; procedure ps4_sceKernelDebugRaiseExceptionOnReleaseMode(dwStopReason,dwStopId:DWORD); SysV_ABI_CDecl; -var - t:pthread; +//var +// t:pthread; begin - t:=_get_curthread; + //t:=_get_curthread; //if (t<>nil) then // Writeln('RaiseThread=',t^.name); Writeln(StdErr,'RaiseException:',HexStr(dwStopReason,8),':',HexStr(dwStopId,8),':',GetStopReasonInfo(dwStopReason)); @@ -123,31 +123,6 @@ end; // void *memblock //); -type - pSceKernelModuleInfoEx=^SceKernelModuleInfoEx; - SceKernelModuleInfoEx=packed record - st_size:QWORD; - name:array[0..255] of AnsiChar; - id :Integer; - tls_index :DWORD; - tls_init_addr :QWORD; - tls_init_size :DWORD; - tls_size :DWORD; - tls_offset :DWORD; - tls_align :DWORD; - init_proc_addr :QWORD; - fini_proc_addr :QWORD; - reserved1 :QWORD; - reserved2 :QWORD; - eh_frame_hdr_addr:QWORD; - eh_frame_addr :QWORD; - eh_frame_hdr_size:DWORD; - eh_frame_size :DWORD; - segments:array[0..3] of TKernelModuleSegmentInfo; - segment_count:DWORD; - ref_count :DWORD; - end; - function ps4_sceKernelGetModuleInfoFromAddr(Addr:Pointer;flags:DWORD;info:pSceKernelModuleInfoEx):Integer; SysV_ABI_CDecl; var node:TElf_node; @@ -175,14 +150,13 @@ begin Exit(-$7ffdfffd); end; - info^.st_size:=424; - - //info^:=node.GetModuleInfo; + info^:=node.GetModuleInfoEx; node.Release; _sig_unlock; Result:=0; + end; end else begin @@ -191,7 +165,7 @@ begin end; end; -function ps4_sceKernelGetModuleInfo(handle:Integer;info:PKernelModuleInfo):Integer; SysV_ABI_CDecl; +function ps4_sceKernelGetModuleInfo(handle:Integer;info:pSceKernelModuleInfo):Integer; SysV_ABI_CDecl; var node:TElf_node; begin @@ -210,20 +184,10 @@ begin Result:=0; end; -type - PSceModuleInfoForUnwind=^SceModuleInfoForUnwind; - SceModuleInfoForUnwind=packed record - st_size:qword; //304 - name:array[0..255] of AnsiChar; - eh_frame_hdr_addr:qword; - eh_frame_addr:qword; - eh_frame_size:qword; - seg0_addr:qword; - seg0_size:qword; - end; - -//nop nid:libkernel:4694092552938853:sceKernelGetModuleInfoForUnwind -function ps4_sceKernelGetModuleInfoForUnwind(addr:Pointer;flags:DWORD;info:PSceModuleInfoForUnwind):Integer; SysV_ABI_CDecl; +function ps4_sceKernelGetModuleInfoForUnwind(addr:Pointer;flags:DWORD;info:pSceModuleInfoForUnwind):Integer; SysV_ABI_CDecl; +var + node:TElf_node; + info_ex:SceKernelModuleInfoEx; begin if (info=nil) then Exit(SCE_KERNEL_ERROR_EFAULT); if (flags - 1 < 2) then @@ -237,7 +201,33 @@ begin if (info^.st_size > 303) then begin - //Result:=-$7ffdfffd; //not found + _sig_lock; + + Writeln('sceKernelGetModuleInfoForUnwind:',HexStr(Addr),':',flags,':',HexStr(info)); + node:=ps4_app.AcqureFileByCodeAdr(Addr); + + if (node=nil) then + begin + _sig_unlock; + + info^:=Default(SceModuleInfoForUnwind); + Exit(-$7ffdfffd); + end; + + info_ex:=node.GetModuleInfoEx; + + node.Release; + + _sig_unlock; + + info^.name :=info_ex.name; + info^.eh_frame_hdr_addr:=info_ex.eh_frame_hdr_addr; + info^.eh_frame_addr :=info_ex.eh_frame_addr; + info^.eh_frame_size :=info_ex.eh_frame_size; + info^.seg0_addr :=info_ex.segments[0].address; + info^.seg0_size :=info_ex.segments[0].size; + + Result:=0; end; end; end else @@ -874,6 +864,7 @@ begin lib^.set_proc($FD84D6FAA5DCDC24,@ps4_sceKernelInternalMemoryGetModuleSegmentInfo); lib^.set_proc($7FB28139A7F2B17A,@ps4_sceKernelGetModuleInfoFromAddr); lib^.set_proc($914A60AD722BCFB4,@ps4_sceKernelGetModuleInfo); + lib^.set_proc($4694092552938853,@ps4_sceKernelGetModuleInfoForUnwind); lib^.set_proc($F79F6AADACCF22B8,@ps4_sceKernelGetProcParam); lib^.set_proc($A7911C41E11E2401,@ps4_sceKernelRtldSetApplicationHeapAPI); lib^.set_proc($ACD856CFE96F38C5,@ps4_sceKernelSetThreadDtors); diff --git a/kernel/ps4_rwlock.pas b/kernel/ps4_rwlock.pas index ced28cab..bb20a0c3 100644 --- a/kernel/ps4_rwlock.pas +++ b/kernel/ps4_rwlock.pas @@ -183,11 +183,12 @@ function pthread_rwlock_init(m:p_pthread_rwlock;a:p_pthread_rwlockattr;str:PChar var mi:pthread_rwlock; begin + Result:=0; + mi:=m^; mi:=rwlock_impl_init(m,mi); if (mi=nil) then Exit(ENOMEM); - if (Result<>0) then Exit; if (str<>nil) then MoveChar0(str^,mi^.name,32); end; diff --git a/ps4_elf.pas b/ps4_elf.pas index 56ac38ab..fe5739d4 100644 --- a/ps4_elf.pas +++ b/ps4_elf.pas @@ -158,7 +158,7 @@ type mElf:TMemChunk; mMap:TMemChunk; - ModuleInfo:TKernelModuleInfo; + ModuleInfo:SceKernelModuleInfo; ro_segments:array[0..3] of TMemChunk; @@ -181,6 +181,7 @@ type end; dtInit:QWORD; + dtFini:QWORD; pInit:packed record dt_preinit_array, @@ -189,7 +190,15 @@ type dt_init_array_count:QWORD; end; - dtFini:QWORD; + eh_frame_hdr:packed record + addr:QWORD; + size:QWORD; + end; + + eh_frame:packed record + addr:QWORD; + size:QWORD; + end; pSceDynLib:TMemChunk; //mElf @@ -250,7 +259,8 @@ type function module_start(argc:size_t;argp,param:PPointer):Integer; override; function GetCodeFrame:TMemChunk; override; function GetEntryPoint:Pointer; override; - Function GetModuleInfo:TKernelModuleInfo; override; + Function GetModuleInfo:SceKernelModuleInfo; override; + Function GetModuleInfoEx:SceKernelModuleInfoEx; override; procedure mapCodeEntry; end; @@ -585,6 +595,94 @@ begin if (p_flags and PF_R)<>0 then Result:=Result+' PF_R'; end; +function read_encoded_value(hdr:p_eh_frame_hdr;hdr_size,hdr_vaddr:Int64;enc:Byte;var P:Pointer;var res:Int64):Boolean; +var + value:Int64; + endp:Pointer; +begin + Result:=False; + + res:=0; + + Case (enc and $70) of + DW_EH_PE_absptr:; + DW_EH_PE_pcrel: + begin + res:=(hdr_vaddr + (P - hdr)); + end; + DW_EH_PE_datarel: + begin + res:=hdr_vaddr; + end; + else + Exit(True); + end; + + value:=0; + endp:=Pointer(hdr) + hdr_size; + + Case (enc and $0f) of + DW_EH_PE_udata2: + begin + if (p + 2 > endp) then Exit(True); + value:=PWORD(p)^; + p:=p + 2; + end; + DW_EH_PE_sdata2: + begin + if (p + 2 > endp) then Exit(True); + value:=PSmallint(p)^; + p:=p + 2; + end; + DW_EH_PE_udata4: + begin + if (p + 4 > endp) then Exit(True); + value:=PDWORD(p)^; + p:=p + 4; + end; + DW_EH_PE_sdata4: + begin + if (p + 4 > endp) then Exit(True); + value:=PInteger(p)^; + p:=p + 4; + end; + DW_EH_PE_udata8, + DW_EH_PE_sdata8: + begin + if (p + 8 > endp) then Exit(True); + value:=PInteger(p)^; + p:=p + 8; + end; + DW_EH_PE_absptr: + begin + value:=0; + end; + else + Exit(True); + end; + + res:=res+value; + + Result:=False; +end; + +function parse_eh_frame_hdr(hdr:p_eh_frame_hdr;hdr_size,hdr_vaddr:Int64;var eh_frame_ptr:Int64):Boolean; +var + p:Pointer; +begin + if (hdr^.eh_frame_ptr_enc=DW_EH_PE_omit) then Exit(False); + + p:=@hdr^.encoded; + + if read_encoded_value(hdr,hdr_size, + hdr_vaddr, + hdr^.eh_frame_ptr_enc, + p, + eh_frame_ptr) then Exit(False); + + Result:=True; +end; + function Telf_file.PreparePhdr:Boolean; Var i:SizeInt; @@ -594,8 +692,8 @@ Var begin Result:=False; - ModuleInfo:=Default(TKernelModuleInfo); - ModuleInfo.size:=SizeOf(TKernelModuleInfo); + ModuleInfo:=Default(SceKernelModuleInfo); + ModuleInfo.size:=SizeOf(SceKernelModuleInfo); elf_hdr:=mElf.pAddr; if (elf_hdr=nil) then Exit; @@ -698,7 +796,8 @@ begin end; PT_GNU_EH_FRAME: begin - + eh_frame_hdr.addr:=elf_phdr[i].p_vaddr; + eh_frame_hdr.size:=elf_phdr[i].p_filesz; end; else @@ -1026,7 +1125,7 @@ begin end; end; -procedure _add_seg(MI:PKernelModuleInfo;adr:Pointer;size:DWORD;prot:Integer); inline; +procedure _add_seg(MI:pSceKernelModuleInfo;adr:Pointer;size:DWORD;prot:Integer); inline; var i:DWORD; begin @@ -1240,6 +1339,9 @@ var i:SizeInt; elf_hdr:Pelf64_hdr; elf_phdr:Pelf64_phdr; + + hdr:p_eh_frame_hdr; + eh_frame_ptr:Int64; begin Result:=False; if (Self=nil) then Exit; @@ -1293,18 +1395,55 @@ begin begin _addSegment(@elf_phdr[i],'.DYNM'); end; + PT_SCE_PROCPARAM, - PT_TLS, - PT_GNU_EH_FRAME: - if (elf_phdr[i].p_flags=PF_R) then + PT_TLS: begin - _add_ro_seg(@elf_phdr[i]); + if (elf_phdr[i].p_flags=PF_R) then + begin + _add_ro_seg(@elf_phdr[i]); + end; end; + + PT_GNU_EH_FRAME: + begin + if (elf_phdr[i].p_flags=PF_R) then + begin + _add_ro_seg(@elf_phdr[i]); + end; + + eh_frame_hdr.addr:=elf_phdr[i].p_vaddr; + eh_frame_hdr.size:=elf_phdr[i].p_filesz; + + hdr:=mMap.pAddr+eh_frame_hdr.addr; + + eh_frame_ptr:=0; + if parse_eh_frame_hdr(hdr, + eh_frame_hdr.size, + Int64(hdr), + eh_frame_ptr) then + begin + eh_frame.addr:=eh_frame_ptr-QWORD(mMap.pAddr); + + if (eh_frame_hdr.addr>eh_frame.addr) then + begin + eh_frame.size:=(eh_frame_hdr.addr-eh_frame.addr); + end else + begin + eh_frame.size:=(mMap.nSize-eh_frame_hdr.addr) + end; + + end; + + end; + end; end; _print_rdol; + + pEntryPoint:=Pelf64_hdr(mElf.pAddr)^.e_entry; Result:=True; @@ -2681,7 +2820,7 @@ begin end; end; -Function Telf_file.GetModuleInfo:TKernelModuleInfo; +Function Telf_file.GetModuleInfo:SceKernelModuleInfo; begin if (ModuleInfo.name[0]=#0) then begin @@ -2690,6 +2829,36 @@ begin Result:=ModuleInfo; end; +Function Telf_file.GetModuleInfoEx:SceKernelModuleInfoEx; +begin + Result:=inherited; + + if (ModuleInfo.name[0]=#0) then + begin + MoveChar0(PChar(pFileName)^,ModuleInfo.name,SCE_DBG_MAX_NAME_LENGTH); + end; + + Result.name:=ModuleInfo.name; + + Result.tls_index :=pTls.index; + Result.tls_init_addr :=mMap.pAddr+pTls.tmpl_start; + Result.tls_init_size :=pTls.tmpl_size; + Result.tls_size :=pTls.full_size; + Result.tls_offset :=pTls.offset; + Result.tls_align :=pTls.align; + + Result.init_proc_addr :=mMap.pAddr+dtInit; + Result.fini_proc_addr :=mMap.pAddr+dtFini; + + Result.eh_frame_hdr_addr:=mMap.pAddr+eh_frame_hdr.addr; + Result.eh_frame_addr :=mMap.pAddr+eh_frame.addr; + Result.eh_frame_hdr_size:=eh_frame_hdr.size; + Result.eh_frame_size :=eh_frame.size; + + Result.segments :=ModuleInfo.segmentInfo; + Result.segment_count:=ModuleInfo.segmentCount; +end; + procedure Telf_file.mapCodeEntry; var P:TEntryPoint; diff --git a/ps4_program.pas b/ps4_program.pas index 4e218324..0c7e8666 100644 --- a/ps4_program.pas +++ b/ps4_program.pas @@ -89,7 +89,8 @@ type function module_start(argc:size_t;argp,param:PPointer):Integer; virtual; function GetCodeFrame:TMemChunk; virtual; function GetEntryPoint:Pointer; virtual; - Function GetModuleInfo:TKernelModuleInfo; virtual; + Function GetModuleInfo:SceKernelModuleInfo; virtual; + Function GetModuleInfoEx:SceKernelModuleInfoEx; virtual; Function get_proc(nid:QWORD):Pointer; Function get_proc_by_name(const name:RawByteString):Pointer; end; @@ -948,16 +949,23 @@ begin Result:=nil; end; -Function TElf_node.GetModuleInfo:TKernelModuleInfo; +Function TElf_node.GetModuleInfo:SceKernelModuleInfo; begin - Result:=Default(TKernelModuleInfo); - Result.size:=SizeOf(TKernelModuleInfo); + Result:=Default(SceKernelModuleInfo); + Result.size:=SizeOf(SceKernelModuleInfo); + + MoveChar0(PChar(pFileName)^,Result.name,SCE_DBG_MAX_NAME_LENGTH); +end; + +Function TElf_node.GetModuleInfoEx:SceKernelModuleInfoEx; +begin + Result:=Default(SceKernelModuleInfoEx); + Result.st_size:=SizeOf(SceKernelModuleInfoEx); MoveChar0(PChar(pFileName)^,Result.name,SCE_DBG_MAX_NAME_LENGTH); -//segmentInfo:array[0..SCE_DBG_MAX_SEGMENTS-1] of TKernelModuleSegmentInfo; -//segmentCount:DWORD; -//fingerprint:array[0..SCE_DBG_NUM_FINGERPRINT-1] of Byte; + Result.id:=FHandle; + Result.ref_count:=1; end; Function TElf_node.get_proc(nid:QWORD):Pointer; diff --git a/sys/sys_types.pas b/sys/sys_types.pas index e5e08449..a91b9a07 100644 --- a/sys/sys_types.pas +++ b/sys/sys_types.pas @@ -316,21 +316,85 @@ const SCE_DBG_NUM_FINGERPRINT = 20; type - TKernelModuleSegmentInfo=packed record + SceKernelModuleSegmentInfo=packed record address:Pointer; size:DWORD; prot:Integer; //PF_ end; - PKernelModuleInfo=^TKernelModuleInfo; - TKernelModuleInfo=packed record + pSceKernelModuleInfo=^SceKernelModuleInfo; + SceKernelModuleInfo=packed record size:QWORD; //Size of this structure name:array[0..SCE_DBG_MAX_NAME_LENGTH-1] of AnsiChar; //module name - segmentInfo:array[0..SCE_DBG_MAX_SEGMENTS-1] of TKernelModuleSegmentInfo; + segmentInfo:array[0..SCE_DBG_MAX_SEGMENTS-1] of SceKernelModuleSegmentInfo; segmentCount:DWORD; fingerprint:array[0..SCE_DBG_NUM_FINGERPRINT-1] of Byte; end; + pSceKernelModuleInfoEx=^SceKernelModuleInfoEx; + SceKernelModuleInfoEx=packed record + st_size:QWORD; //424 + name:array[0..SCE_DBG_MAX_NAME_LENGTH-1] of AnsiChar; + id :Integer; + tls_index :DWORD; + tls_init_addr :Pointer; + tls_init_size :DWORD; + tls_size :DWORD; + tls_offset :DWORD; + tls_align :DWORD; + init_proc_addr :Pointer; + fini_proc_addr :Pointer; + reserved1 :QWORD; + reserved2 :QWORD; + eh_frame_hdr_addr:Pointer; + eh_frame_addr :Pointer; + eh_frame_hdr_size:QWORD; + eh_frame_size :DWORD; + segments:array[0..SCE_DBG_MAX_SEGMENTS-1] of SceKernelModuleSegmentInfo; + segment_count:DWORD; + ref_count :DWORD; + end; + + pSceModuleInfoForUnwind=^SceModuleInfoForUnwind; + SceModuleInfoForUnwind=packed record + st_size:qword; //304 + name:array[0..SCE_DBG_MAX_NAME_LENGTH-1] of AnsiChar; + eh_frame_hdr_addr:Pointer; + eh_frame_addr:Pointer; + eh_frame_size:qword; + seg0_addr:Pointer; + seg0_size:qword; + end; + +type + p_eh_frame_hdr=^eh_frame_hdr; + eh_frame_hdr=packed record + version:Byte; + eh_frame_ptr_enc:Byte; + fde_count_enc:Byte; + table_enc:Byte; + encoded:record end; + //encoded eh_frame_ptr + //encoded fde_count + end; + +const + DW_EH_PE_omit =$ff; // no data follows + + DW_EH_PE_absptr =$00; + DW_EH_PE_pcrel =$10; + DW_EH_PE_datarel=$30; + + DW_EH_PE_uleb128=$01; + DW_EH_PE_udata2 =$02; + DW_EH_PE_udata4 =$03; + DW_EH_PE_udata8 =$04; + DW_EH_PE_sleb128=$09; + DW_EH_PE_sdata2 =$0A; + DW_EH_PE_sdata4 =$0B; + DW_EH_PE_sdata8 =$0C; + +type TModuleValue=packed record case Byte of 0:(value:Int64);