diff --git a/sys/elf64.pas b/sys/elf64.pas index 69c753e3..f9c0a67a 100644 --- a/sys/elf64.pas +++ b/sys/elf64.pas @@ -397,6 +397,8 @@ const SELF_PT_SECURE_MODULE=$E; SELF_PT_SECURE_KERNEL=$F; + SELF_CONTROL_BLOCK_TYPE_NPDRM = $3; + type p_self_segment=^t_self_segment; t_self_segment=packed record @@ -412,10 +414,17 @@ type Program_Type :QWORD; Program_Version:QWORD; System_Version :QWORD; - //Content_ID :array[0..31] of Byte; //Optional Digest_SHA_256 :array[0..31] of Byte; end; + p_self_npdrm_control_block=^t_self_npdrm_control_block; + t_self_npdrm_control_block=packed record + pType :Word; + Unknown :array[0..13] of byte; + ContentID:array[0..18] of byte; + RandomPad:array[0..12] of byte; + end; + p_eh_frame_hdr=^eh_frame_hdr; eh_frame_hdr=packed record version :Byte; diff --git a/sys/jit/kern_jit.pas b/sys/jit/kern_jit.pas index fb3e1d84..7693f98f 100644 --- a/sys/jit/kern_jit.pas +++ b/sys/jit/kern_jit.pas @@ -1020,6 +1020,9 @@ begin vm_map_unlock(@g_vmspace.vm_map); end; +var + _print_stat:Integer=0; + procedure pick_locked(var ctx:t_jit_context2); const SCODES:array[TSimdOpcode] of Byte=(0,0,1,3,2); @@ -1060,7 +1063,10 @@ begin Writeln(' ctx.text___end:0x',HexStr(ctx.text___end,16)); Writeln(' ctx.map____end:0x',HexStr(ctx.map____end,16)); - print_test_jit_cbs(False,True); + if System.InterlockedExchange(_print_stat,1)=0 then + begin + print_test_jit_cbs(False,True); + end; links:=Default(t_jit_context2.t_forward_links); addr:=nil; @@ -1091,7 +1097,7 @@ begin goto _invalid; end; - if ((pmap_get_raw(QWORD(ptr)) and PAGE_PROT_EXECUTE)=0) then + if ((pmap_get_prot(QWORD(ptr)) and PAGE_PROT_EXECUTE)=0) then begin writeln('not excec:0x',HexStr(ptr)); goto _invalid; diff --git a/sys/jit/kern_jit_asm.pas b/sys/jit/kern_jit_asm.pas index f7fd620b..12138ae2 100644 --- a/sys/jit/kern_jit_asm.pas +++ b/sys/jit/kern_jit_asm.pas @@ -163,7 +163,7 @@ asm add PAGE_MAP(%rip),%r14 mov (%r14),%r14d //filter (r14) - and PAGE_OFS_MASK,%r14 + test %r14,%r14 jz _sigsegv //combine (r14|rax) shl PAGE_SHIFT,%r14 @@ -228,9 +228,6 @@ asm mov (%rax,%rsi),%esi //restore mov - kthread.td_frame.tf_r13 + kthread.td_frame.tf_rax(%r13) ,%rax - //filter (rdi,rsi) - and PAGE_OFS_MASK,%rdi - and PAGE_OFS_MASK,%rsi // inc %rdi cmp %rdi,%rsi diff --git a/sys/jit/kern_jit_ctx.pas b/sys/jit/kern_jit_ctx.pas index 050e295a..eb7416e6 100644 --- a/sys/jit/kern_jit_ctx.pas +++ b/sys/jit/kern_jit_ctx.pas @@ -845,13 +845,13 @@ begin //jmp [addr] if ctx.is_map_addr(ofs) then - if ((pmap_get_raw(QWORD(ofs)) and PAGE_PROT_READ)<>0) then + if ((pmap_get_prot(QWORD(ofs)) and PAGE_PROT_READ)<>0) then begin ofs:=PInt64(ofs)^; if ctx.is_text_addr(ofs) then if (ctx.max=0) or (ofs<=ctx.max) then - if ((pmap_get_raw(QWORD(ofs)) and PAGE_PROT_EXECUTE)<>0) then + if ((pmap_get_prot(QWORD(ofs)) and PAGE_PROT_EXECUTE)<>0) then begin ctx.add_forward_point(fpCall,Pointer(ofs)); end; @@ -865,7 +865,7 @@ begin if ctx.is_text_addr(ofs) then begin if (ofs<=ctx.max) then - if ((pmap_get_raw(QWORD(ofs)) and PAGE_PROT_EXECUTE)<>0) then + if ((pmap_get_prot(QWORD(ofs)) and PAGE_PROT_EXECUTE)<>0) then begin ctx.add_forward_point(fpData,Pointer(ofs)); end; diff --git a/sys/jit/kern_jit_dynamic.pas b/sys/jit/kern_jit_dynamic.pas index 850eb03b..ef870ea2 100644 --- a/sys/jit/kern_jit_dynamic.pas +++ b/sys/jit/kern_jit_dynamic.pas @@ -156,7 +156,7 @@ begin begin Result:=addr; - if ((pmap_get_raw(QWORD(addr)) and PAGE_PROT_EXECUTE)=0) then + if ((pmap_get_prot(QWORD(addr)) and PAGE_PROT_EXECUTE)=0) then begin Break; end; @@ -174,7 +174,7 @@ begin begin Result:=addr; - if ((pmap_get_raw(QWORD(addr)) and PAGE_PROT_EXECUTE)=0) then + if ((pmap_get_prot(QWORD(addr)) and PAGE_PROT_EXECUTE)=0) then begin Break; end; @@ -397,7 +397,7 @@ begin _start: - if ((pmap_get_raw(QWORD(addr)) and PAGE_PROT_EXECUTE)=0) then + if ((pmap_get_prot(QWORD(addr)) and PAGE_PROT_EXECUTE)=0) then begin writeln('not excec:0x',HexStr(addr)); Assert(False,'TODO'); diff --git a/sys/kern/systm.pas b/sys/kern/systm.pas index a0ff91bf..86187ee7 100644 --- a/sys/kern/systm.pas +++ b/sys/kern/systm.pas @@ -75,7 +75,7 @@ begin guest:=is_guest_addr(QWORD(udaddr)); if guest then begin - if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_READ)=0) then + if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_READ)=0) then begin Result:=EFAULT; goto _exit; @@ -97,7 +97,7 @@ begin if guest then begin - if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_READ)<>0) then + if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_READ)<>0) then begin goto _next; end else @@ -152,7 +152,7 @@ begin guest:=is_guest_addr(QWORD(udaddr)); if guest then begin - if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_READ)=0) then + if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_READ)=0) then begin Result:=EFAULT; goto _exit; @@ -177,7 +177,7 @@ begin begin if guest then begin - if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_READ)<>0) then + if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_READ)<>0) then begin Result:=0; end else @@ -227,7 +227,7 @@ begin guest:=is_guest_addr(QWORD(udaddr)); if guest then begin - if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_READ)=0) then + if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_READ)=0) then begin Result:=EFAULT; goto _exit; @@ -249,7 +249,7 @@ begin if guest then begin - if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_READ)<>0) then + if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_READ)<>0) then begin goto _next; end else @@ -321,7 +321,7 @@ begin guest:=is_guest_addr(QWORD(udaddr)); if guest then begin - if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_WRITE)=0) then + if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_WRITE)=0) then begin Result:=EFAULT; goto _exit; @@ -343,7 +343,7 @@ begin if guest then begin - if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_WRITE)<>0) then + if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_WRITE)<>0) then begin goto _next; end else @@ -398,7 +398,7 @@ begin guest:=is_guest_addr(QWORD(udaddr)); if guest then begin - if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_WRITE)=0) then + if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_WRITE)=0) then begin Result:=EFAULT; goto _exit; @@ -423,7 +423,7 @@ begin begin if guest then begin - if ((pmap_get_raw(QWORD(udaddr)) and PAGE_PROT_WRITE)<>0) then + if ((pmap_get_prot(QWORD(udaddr)) and PAGE_PROT_WRITE)<>0) then begin Result:=0; end else @@ -514,7 +514,7 @@ begin _fault: if guest then begin - if ((pmap_get_raw(QWORD(@base)) and PAGE_PROT_RW)=PAGE_PROT_RW) then + if ((pmap_get_prot(QWORD(@base)) and PAGE_PROT_RW)=PAGE_PROT_RW) then begin goto _begin; end else @@ -571,7 +571,7 @@ begin _fault: if guest then begin - if ((pmap_get_raw(QWORD(@base)) and PAGE_PROT_RW)=PAGE_PROT_RW) then + if ((pmap_get_prot(QWORD(@base)) and PAGE_PROT_RW)=PAGE_PROT_RW) then begin goto _begin; end else diff --git a/sys/md/vm_pmap.pas b/sys/md/vm_pmap.pas index 0d2c2cec..ba360c25 100644 --- a/sys/md/vm_pmap.pas +++ b/sys/md/vm_pmap.pas @@ -16,26 +16,22 @@ const PAGE_MAP_COUNT =(QWORD(VM_MAXUSER_ADDRESS) shr PAGE_SHIFT); PAGE_MAP_MASK =PAGE_MAP_COUNT-1; - PAGE_PROT_EXECUTE=DWORD($80000000); - PAGE_PROT_WRITE =DWORD($40000000); - PAGE_PROT_READ =DWORD($20000000); + PAGE_PROT_EXECUTE=VM_PROT_EXECUTE; + PAGE_PROT_WRITE =VM_PROT_WRITE; + PAGE_PROT_READ =VM_PROT_READ; PAGE_PROT_RW =PAGE_PROT_READ or PAGE_PROT_WRITE; - PAGE_PROT_SHIFT =29; - - PAGE_OFS_MASK =(1 shl PAGE_PROT_SHIFT)-1; //Possible addressing in 8TB - //PAGE_BUSY_FLAG =DWORD($10000000); //PAGE_PATCH_FLAG =DWORD($08000000); var - PAGE_MAP:PDWORD=nil; + PAGE_MAP :PDWORD=nil; + PAGE_PROT :PBYTE =nil; -procedure pmap_mark (start,__end,__off:vm_offset_t;flags:DWORD); +procedure pmap_mark (start,__end,__off:vm_offset_t;prots:Byte); procedure pmap_unmark (start,__end:vm_offset_t); -procedure pmap_mark_flags(start,__end:vm_offset_t;flags:DWORD); -function pmap_get_raw (addr:vm_offset_t):DWORD; +function pmap_get_prot (addr:vm_offset_t):Byte; function pmap_get_page (addr:vm_offset_t):DWORD; function pmap_test_cross(addr:vm_offset_t;h:Integer):Boolean; @@ -114,6 +110,7 @@ procedure pmap_pinit(pmap:p_pmap); var base:Pointer; size:QWORD; + prot:QWORD; i,r:Integer; begin @@ -139,6 +136,9 @@ begin PAGE_MAP:=nil; size:=PAGE_MAP_COUNT*SizeOf(DWORD); + prot:=size; + size:=size+PAGE_MAP_COUNT; + r:=md_mmap(PAGE_MAP,size,MD_PROT_RW); if (r<>0) then @@ -147,6 +147,8 @@ begin Assert(false,'pmap_init'); end; + PAGE_PROT:=Pointer(PAGE_MAP)+prot; + //Mapping to internal memory, isolate TODO if Length(exclude_mem)<>0 then begin @@ -202,14 +204,15 @@ begin Result:=QWORD(x) shr PAGE_SHIFT; end; -procedure pmap_mark(start,__end,__off:vm_offset_t;flags:DWORD); +procedure pmap_mark(start,__end,__off:vm_offset_t;prots:Byte); begin start:=OFF_TO_IDX(start); __end:=OFF_TO_IDX(__end); __off:=OFF_TO_IDX(__off); while (start<__end) do begin - PAGE_MAP[start and PAGE_MAP_MASK]:=(__off and PAGE_OFS_MASK) or flags; + PAGE_MAP [start and PAGE_MAP_MASK]:=__off; + PAGE_PROT[start and PAGE_MAP_MASK]:=prots; Inc(__off); Inc(start); end; @@ -222,32 +225,18 @@ begin __end:=OFF_TO_IDX(__end); while (start<__end) do begin - PAGE_MAP[start and PAGE_MAP_MASK]:=0; + PAGE_MAP [start and PAGE_MAP_MASK]:=0; + PAGE_PROT[start and PAGE_MAP_MASK]:=0; Inc(start); end; WriteBarrier; end; -procedure pmap_mark_flags(start,__end:vm_offset_t;flags:DWORD); -var - i:vm_offset_t; -begin - start:=OFF_TO_IDX(start); - __end:=OFF_TO_IDX(__end); - while (start<__end) do - begin - i:=start and PAGE_MAP_MASK; - PAGE_MAP[i]:=PAGE_MAP[i] or flags; - Inc(start); - end; - WriteBarrier; -end; - -function pmap_get_raw(addr:vm_offset_t):DWORD; +function pmap_get_prot(addr:vm_offset_t):Byte; begin addr:=OFF_TO_IDX(addr); addr:=addr and PAGE_MAP_MASK; - Result:=PAGE_MAP[addr]; + Result:=PAGE_PROT[addr]; end; function pmap_get_page(addr:vm_offset_t):DWORD; @@ -255,7 +244,6 @@ begin addr:=OFF_TO_IDX(addr); addr:=addr and PAGE_MAP_MASK; Result:=PAGE_MAP[addr]; - Result:=Result and PAGE_OFS_MASK; end; function pmap_test_cross(addr:vm_offset_t;h:Integer):Boolean; @@ -269,8 +257,6 @@ begin Result:=False; end else begin - page1:=PAGE_MAP[page1] and PAGE_OFS_MASK; - page2:=PAGE_MAP[page2] and PAGE_OFS_MASK; Result:=(page1<>page2); end; end; @@ -297,7 +283,7 @@ asm mov PAGE_MAP(%rip),%rax mov (%rax,%rdi,4),%edi //filter (rdi) - and PAGE_OFS_MASK,%rdi + test %rdi,%rdi jz _exit //combine (rdi|rsi) shl PAGE_SHIFT,%rdi @@ -367,7 +353,7 @@ begin Assert(false,'pmap_enter_object'); end; - pmap_mark(start,__end,QWORD(base),(prot and VM_RWX) shl PAGE_PROT_SHIFT); + pmap_mark(start,__end,QWORD(base),(prot and VM_RWX)); end; procedure pmap_move(pmap :pmap_t; @@ -414,7 +400,7 @@ begin end; end; - pmap_mark(start,start+size,ofs_new,(new_prot and VM_RWX) shl PAGE_PROT_SHIFT); + pmap_mark(start,start+size,ofs_new,(new_prot and VM_RWX)); //free old r:=md_remove(Pointer(ofs_old),size); @@ -483,7 +469,7 @@ begin Assert(false,'pmap_protect'); end; - pmap_mark(start,__end,QWORD(base_new),(new_prot and VM_RWX) shl PAGE_PROT_SHIFT); + pmap_mark(start,__end,QWORD(base_new),(new_prot and VM_RWX)); end; procedure pmap_madv_free(pmap :pmap_t; diff --git a/tools/oelf2fself/DCPsha256.pas b/tools/oelf2fself/DCPsha256.pas new file mode 100644 index 00000000..0bbb79c6 --- /dev/null +++ b/tools/oelf2fself/DCPsha256.pas @@ -0,0 +1,250 @@ +{******************************************************************************} +{* DCPcrypt v2.0 written by David Barton (crypto@cityinthesky.co.uk) **********} +{******************************************************************************} +{* A binary compatible implementation of SHA256 *******************************} +{******************************************************************************} +{* Copyright (c) 1999-2002 David Barton *} +{* Permission is hereby granted, free of charge, to any person obtaining a *} +{* copy of this software and associated documentation files (the "Software"), *} +{* to deal in the Software without restriction, including without limitation *} +{* the rights to use, copy, modify, merge, publish, distribute, sublicense, *} +{* and/or sell copies of the Software, and to permit persons to whom the *} +{* Software is furnished to do so, subject to the following conditions: *} +{* *} +{* The above copyright notice and this permission notice shall be included in *} +{* all copies or substantial portions of the Software. *} +{* *} +{* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *} +{* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, *} +{* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL *} +{* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER *} +{* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *} +{* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER *} +{* DEALINGS IN THE SOFTWARE. *} +{******************************************************************************} +unit DCPsha256; + +interface +uses + Classes, Sysutils; + +type + TDCP_sha256=object + protected + fInitialized:Boolean; + LenHi, LenLo: longword; + Index: DWord; + CurrentHash: array[0..7] of DWord; + HashBuffer: array[0..63] of byte; + procedure Compress; + public + class function GetAlgorithm: string; + class function GetHashSize: integer; + procedure Init; + procedure Final(var Digest); + procedure Burn; + procedure Update(const Buffer; Size: longword); + end; + +{******************************************************************************} +{******************************************************************************} +implementation +{$R-}{$Q-} + +function SwapDWord(a: dword): dword; +begin + Result:= ((a and $FF) shl 24) or ((a and $FF00) shl 8) or ((a and $FF0000) shr 8) or ((a and $FF000000) shr 24); +end; + +procedure TDCP_sha256.Compress; +var + a, b, c, d, e, f, g, h, t1, t2: DWord; + W: array[0..63] of DWord; + i: longword; +begin + Index:= 0; + FillChar(W, SizeOf(W), 0); + a:= CurrentHash[0]; b:= CurrentHash[1]; c:= CurrentHash[2]; d:= CurrentHash[3]; + e:= CurrentHash[4]; f:= CurrentHash[5]; g:= CurrentHash[6]; h:= CurrentHash[7]; + Move(HashBuffer,W,Sizeof(HashBuffer)); + for i:= 0 to 15 do + W[i]:= SwapDWord(W[i]); + for i:= 16 to 63 do + W[i]:= (((W[i-2] shr 17) or (W[i-2] shl 15)) xor ((W[i-2] shr 19) or (W[i-2] shl 13)) xor + (W[i-2] shr 10)) + W[i-7] + (((W[i-15] shr 7) or (W[i-15] shl 25)) xor + ((W[i-15] shr 18) or (W[i-15] shl 14)) xor (W[i-15] shr 3)) + W[i-16]; +{ +Non-optimised version + for i:= 0 to 63 do + begin + t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + + ((e and f) xor (not e and g)) + K[i] + W[i]; + t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + + ((a and b) xor (a and c) xor (b and c)); + h:= g; g:= f; f:= e; e:= d + t1; d:= c; c:= b; b:= a; a:= t1 + t2; + end; +} + + t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $428a2f98 + W[0]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1; + t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $71374491 + W[1]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1; + t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $b5c0fbcf + W[2]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1; + t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $e9b5dba5 + W[3]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1; + t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $3956c25b + W[4]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1; + t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $59f111f1 + W[5]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1; + t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $923f82a4 + W[6]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1; + t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $ab1c5ed5 + W[7]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1; + t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $d807aa98 + W[8]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1; + t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $12835b01 + W[9]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1; + t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $243185be + W[10]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1; + t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $550c7dc3 + W[11]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1; + t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $72be5d74 + W[12]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1; + t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $80deb1fe + W[13]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1; + t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $9bdc06a7 + W[14]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1; + t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $c19bf174 + W[15]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1; + t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $e49b69c1 + W[16]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1; + t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $efbe4786 + W[17]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1; + t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $0fc19dc6 + W[18]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1; + t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $240ca1cc + W[19]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1; + t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $2de92c6f + W[20]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1; + t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $4a7484aa + W[21]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1; + t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $5cb0a9dc + W[22]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1; + t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $76f988da + W[23]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1; + t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $983e5152 + W[24]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1; + t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $a831c66d + W[25]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1; + t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $b00327c8 + W[26]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1; + t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $bf597fc7 + W[27]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1; + t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $c6e00bf3 + W[28]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1; + t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $d5a79147 + W[29]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1; + t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $06ca6351 + W[30]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1; + t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $14292967 + W[31]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1; + t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $27b70a85 + W[32]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1; + t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $2e1b2138 + W[33]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1; + t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $4d2c6dfc + W[34]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1; + t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $53380d13 + W[35]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1; + t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $650a7354 + W[36]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1; + t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $766a0abb + W[37]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1; + t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $81c2c92e + W[38]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1; + t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $92722c85 + W[39]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1; + t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $a2bfe8a1 + W[40]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1; + t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $a81a664b + W[41]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1; + t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $c24b8b70 + W[42]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1; + t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $c76c51a3 + W[43]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1; + t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $d192e819 + W[44]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1; + t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $d6990624 + W[45]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1; + t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $f40e3585 + W[46]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1; + t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $106aa070 + W[47]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1; + t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $19a4c116 + W[48]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1; + t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $1e376c08 + W[49]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1; + t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $2748774c + W[50]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1; + t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $34b0bcb5 + W[51]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1; + t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $391c0cb3 + W[52]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1; + t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $4ed8aa4a + W[53]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1; + t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $5b9cca4f + W[54]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1; + t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $682e6ff3 + W[55]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1; + t1:= h + (((e shr 6) or (e shl 26)) xor ((e shr 11) or (e shl 21)) xor ((e shr 25) or (e shl 7))) + ((e and f) xor (not e and g)) + $748f82ee + W[56]; t2:= (((a shr 2) or (a shl 30)) xor ((a shr 13) or (a shl 19)) xor ((a shr 22) xor (a shl 10))) + ((a and b) xor (a and c) xor (b and c)); h:= t1 + t2; d:= d + t1; + t1:= g + (((d shr 6) or (d shl 26)) xor ((d shr 11) or (d shl 21)) xor ((d shr 25) or (d shl 7))) + ((d and e) xor (not d and f)) + $78a5636f + W[57]; t2:= (((h shr 2) or (h shl 30)) xor ((h shr 13) or (h shl 19)) xor ((h shr 22) xor (h shl 10))) + ((h and a) xor (h and b) xor (a and b)); g:= t1 + t2; c:= c + t1; + t1:= f + (((c shr 6) or (c shl 26)) xor ((c shr 11) or (c shl 21)) xor ((c shr 25) or (c shl 7))) + ((c and d) xor (not c and e)) + $84c87814 + W[58]; t2:= (((g shr 2) or (g shl 30)) xor ((g shr 13) or (g shl 19)) xor ((g shr 22) xor (g shl 10))) + ((g and h) xor (g and a) xor (h and a)); f:= t1 + t2; b:= b + t1; + t1:= e + (((b shr 6) or (b shl 26)) xor ((b shr 11) or (b shl 21)) xor ((b shr 25) or (b shl 7))) + ((b and c) xor (not b and d)) + $8cc70208 + W[59]; t2:= (((f shr 2) or (f shl 30)) xor ((f shr 13) or (f shl 19)) xor ((f shr 22) xor (f shl 10))) + ((f and g) xor (f and h) xor (g and h)); e:= t1 + t2; a:= a + t1; + t1:= d + (((a shr 6) or (a shl 26)) xor ((a shr 11) or (a shl 21)) xor ((a shr 25) or (a shl 7))) + ((a and b) xor (not a and c)) + $90befffa + W[60]; t2:= (((e shr 2) or (e shl 30)) xor ((e shr 13) or (e shl 19)) xor ((e shr 22) xor (e shl 10))) + ((e and f) xor (e and g) xor (f and g)); d:= t1 + t2; h:= h + t1; + t1:= c + (((h shr 6) or (h shl 26)) xor ((h shr 11) or (h shl 21)) xor ((h shr 25) or (h shl 7))) + ((h and a) xor (not h and b)) + $a4506ceb + W[61]; t2:= (((d shr 2) or (d shl 30)) xor ((d shr 13) or (d shl 19)) xor ((d shr 22) xor (d shl 10))) + ((d and e) xor (d and f) xor (e and f)); c:= t1 + t2; g:= g + t1; + t1:= b + (((g shr 6) or (g shl 26)) xor ((g shr 11) or (g shl 21)) xor ((g shr 25) or (g shl 7))) + ((g and h) xor (not g and a)) + $bef9a3f7 + W[62]; t2:= (((c shr 2) or (c shl 30)) xor ((c shr 13) or (c shl 19)) xor ((c shr 22) xor (c shl 10))) + ((c and d) xor (c and e) xor (d and e)); b:= t1 + t2; f:= f + t1; + t1:= a + (((f shr 6) or (f shl 26)) xor ((f shr 11) or (f shl 21)) xor ((f shr 25) or (f shl 7))) + ((f and g) xor (not f and h)) + $c67178f2 + W[63]; t2:= (((b shr 2) or (b shl 30)) xor ((b shr 13) or (b shl 19)) xor ((b shr 22) xor (b shl 10))) + ((b and c) xor (b and d) xor (c and d)); a:= t1 + t2; e:= e + t1; + + CurrentHash[0]:= CurrentHash[0] + a; + CurrentHash[1]:= CurrentHash[1] + b; + CurrentHash[2]:= CurrentHash[2] + c; + CurrentHash[3]:= CurrentHash[3] + d; + CurrentHash[4]:= CurrentHash[4] + e; + CurrentHash[5]:= CurrentHash[5] + f; + CurrentHash[6]:= CurrentHash[6] + g; + CurrentHash[7]:= CurrentHash[7] + h; + FillChar(W,Sizeof(W),0); + FillChar(HashBuffer,Sizeof(HashBuffer),0); +end; + +class function TDCP_sha256.GetAlgorithm: string; +begin + Result:= 'SHA256'; +end; + +class function TDCP_sha256.GetHashSize: integer; +begin + Result:= 256; +end; + +procedure TDCP_sha256.Init; +begin + Burn; + CurrentHash[0]:= $6a09e667; + CurrentHash[1]:= $bb67ae85; + CurrentHash[2]:= $3c6ef372; + CurrentHash[3]:= $a54ff53a; + CurrentHash[4]:= $510e527f; + CurrentHash[5]:= $9b05688c; + CurrentHash[6]:= $1f83d9ab; + CurrentHash[7]:= $5be0cd19; + fInitialized:= true; +end; + +procedure TDCP_sha256.Burn; +begin + LenHi:= 0; LenLo:= 0; + Index:= 0; + FillChar(HashBuffer,Sizeof(HashBuffer),0); + FillChar(CurrentHash,Sizeof(CurrentHash),0); + fInitialized:= false; +end; + +procedure TDCP_sha256.Update(const Buffer; Size: longword); +var + PBuf: ^byte; +begin + if not fInitialized then Exit; + + Inc(LenHi,Size shr 29); + Inc(LenLo,Size*8); + if LenLo< (Size*8) then + Inc(LenHi); + + PBuf:= @Buffer; + while Size> 0 do + begin + if (Sizeof(HashBuffer)-Index)<= DWord(Size) then + begin + Move(PBuf^,HashBuffer[Index],Sizeof(HashBuffer)-Index); + Dec(Size,Sizeof(HashBuffer)-Index); + Inc(PBuf,Sizeof(HashBuffer)-Index); + Compress; + end + else + begin + Move(PBuf^,HashBuffer[Index],Size); + Inc(Index,Size); + Size:= 0; + end; + end; +end; + +procedure TDCP_sha256.Final(var Digest); +begin + if not fInitialized then Exit; + + HashBuffer[Index]:= $80; + if Index>= 56 then + Compress; + PDWord(@HashBuffer[56])^:= SwapDWord(LenHi); + PDWord(@HashBuffer[60])^:= SwapDWord(LenLo); + Compress; + CurrentHash[0]:= SwapDWord(CurrentHash[0]); + CurrentHash[1]:= SwapDWord(CurrentHash[1]); + CurrentHash[2]:= SwapDWord(CurrentHash[2]); + CurrentHash[3]:= SwapDWord(CurrentHash[3]); + CurrentHash[4]:= SwapDWord(CurrentHash[4]); + CurrentHash[5]:= SwapDWord(CurrentHash[5]); + CurrentHash[6]:= SwapDWord(CurrentHash[6]); + CurrentHash[7]:= SwapDWord(CurrentHash[7]); + Move(CurrentHash,Digest,Sizeof(CurrentHash)); + Burn; +end; + +end. diff --git a/tools/oelf2fself/oelf2fself.lpi b/tools/oelf2fself/oelf2fself.lpi new file mode 100644 index 00000000..33be5e49 --- /dev/null +++ b/tools/oelf2fself/oelf2fself.lpi @@ -0,0 +1,72 @@ + + + + + + + + + + + + + + <UseAppBundle Value="False"/> + <ResourceType Value="res"/> + </General> + <BuildModes> + <Item Name="Default" Default="True"/> + </BuildModes> + <PublishOptions> + <Version Value="2"/> + <UseFileFilters Value="True"/> + </PublishOptions> + <RunParams> + <FormatVersion Value="2"/> + </RunParams> + <Units> + <Unit> + <Filename Value="oelf2fself.lpr"/> + <IsPartOfProject Value="True"/> + </Unit> + <Unit> + <Filename Value="..\..\sys\elf64.pas"/> + <IsPartOfProject Value="True"/> + </Unit> + <Unit> + <Filename Value="DCPsha256.pas"/> + <IsPartOfProject Value="True"/> + </Unit> + </Units> + </ProjectOptions> + <CompilerOptions> + <Version Value="11"/> + <PathDelim Value="\"/> + <Target> + <Filename Value="oelf2fself"/> + </Target> + <SearchPaths> + <IncludeFiles Value="$(ProjOutDir)"/> + <OtherUnitFiles Value="..\.."/> + <UnitOutputDirectory Value="lib\$(TargetCPU)-$(TargetOS)"/> + </SearchPaths> + <Linking> + <Debugging> + <DebugInfoType Value="dsDwarf3"/> + </Debugging> + </Linking> + </CompilerOptions> + <Debugging> + <Exceptions> + <Item> + <Name Value="EAbort"/> + </Item> + <Item> + <Name Value="ECodetoolError"/> + </Item> + <Item> + <Name Value="EFOpenError"/> + </Item> + </Exceptions> + </Debugging> +</CONFIG> diff --git a/tools/oelf2fself/oelf2fself.lpr b/tools/oelf2fself/oelf2fself.lpr new file mode 100644 index 00000000..22641476 --- /dev/null +++ b/tools/oelf2fself/oelf2fself.lpr @@ -0,0 +1,1166 @@ +program oelf2fself; + +uses + sysutils, + DCPsha256, + elf64 in '..\..\sys\elf64.pas', + ps4libdoc; + +const + PAGE_SHIFT=14; + PAGE_SIZE =1 shl PAGE_SHIFT; //16384 + PAGE_MASK =PAGE_SIZE-1; + + BLOCK_SIZE=$4000; + + SELF_MODE_SPECIFICUSER = $1; + SELF_DATA_LSB = $1; + + SELF_HEADER_SIZE =$20; + SELF_ENTRY_SIZE =$50; + SELF_ELF_HEADER_SIZE =$40; + SELF_ELF_PROGHEADER_SIZE =$38; + SELF_EXTENDED_HEADER_SIZE =$40; + SELF_META_FOOTER_SIZE =$50; + SELF_NPDRM_BLOCK_SIZE =$30; + SELF_META_BLOCK_SIZE =$50; + SELF_META_DATA_BLOCK_SIZE =$20; + SELF_SIGNATURE_SIZE =$100; + +type + Tsha256Digest=array[0..31] of Byte; + + Tsignature=array[0..SELF_SIGNATURE_SIZE-1] of Byte; + + AByte=array of byte; + + SelfEntryInfo=record + data:AByte; + info:t_self_segment; + end; + + a_self_segment=array of SelfEntryInfo; + + p_image_params=^t_image_params; + t_image_params=packed record + image_self :p_self_header; + image_header:p_elf64_hdr; + entry_addr :Pointer; + elf_size :Integer; + + dyn_vaddr:p_elf64_dyn; + + tls_size :QWORD; + tls_align :QWORD; + tls_init_size:QWORD; + tls_init_addr:Pointer; + + eh_frame_hdr_addr:Pointer; + eh_frame_hdr_size:QWORD; + + proc_param_addr:pSceProcParam; + proc_param_size:QWORD; + + module_param_addr:psceModuleParam; + module_param_size:QWORD; + + dyn_id :Integer; + sce_dynlib_data_id:Integer; + sce_comment_id :Integer; + dyn_exist :Integer; + + dyn_offset :QWORD; + dyn_filesz :QWORD; + + sce_dynlib_data_addr:QWORD; + sce_dynlib_data_size:QWORD; + + sce_comment_offset :QWORD; + sce_comment_filesz :QWORD; + + min_addr:QWORD; + max_addr:QWORD; + + _selfEntries:a_self_segment; + + outputFself:THandle; + end; + +function maxInt64(a,b:Int64):Int64; inline; +begin + if (a>b) then Result:=a else Result:=b; +end; + +function minInt64(a,b:Int64):Int64; inline; +begin + if (a<b) then Result:=a else Result:=b; +end; + +function get_elf_phdr(elf_hdr:p_elf64_hdr):p_elf64_phdr; +begin + if (elf_hdr=nil) then Exit(nil); + if (elf_hdr^.e_phoff=0) then + begin + Result:=Pointer(elf_hdr+1); + end else + begin + Result:=Pointer(elf_hdr)+elf_hdr^.e_phoff; + end; +end; + +function get_elf_phdr_offset(elf_hdr:p_elf64_hdr):Int64; +begin + if (elf_hdr=nil) then Exit(0); + if (elf_hdr^.e_phoff=0) then + begin + Result:=SizeOf(elf64_hdr); + end else + begin + Result:=elf_hdr^.e_phoff; + end; +end; + +procedure fixup_offset_size(var offset,size:Int64;max:Int64); +var + s,e:Int64; +begin + s:=offset; + e:=s+size; + + s:=MinInt64(s,max); + e:=MinInt64(e,max); + + offset:=s; + size :=(e-s); +end; + +procedure free_imgp(imgp:p_image_params); +begin + if (imgp=nil) then Exit; + SetLength(imgp^._selfEntries,0); + FreeMem(imgp^.image_header); + imgp^:=Default(t_image_params); +end; + +function load_oelf(Const name:RawByteString;imgp:p_image_params):Integer; +Var + F:THandle; + obj_size:Int64; + n:Int64; + Magic:DWORD; + elf_hdr:p_elf64_hdr; +begin + Result:=0; + + if (name='') or (imgp=nil) then Exit(-1); + + F:=FileOpen(name,fmOpenRead); + if (F=feInvalidHandle) then Exit(-2); + + n:=FileRead(F,Magic,SizeOf(DWORD)); + if (n<>SizeOf(DWORD)) then + begin + FileClose(F); + Exit(-3); + end; + + obj_size:=FileSeek(F,0,fsFromEnd); + + if (obj_size<=0) then + begin + FileClose(F); + Exit(-4); + end; + + case Magic of + ELFMAG: //elf64 + begin + elf_hdr:=AllocMem(obj_size); + + FileSeek(F,0,fsFromBeginning); + n:=FileRead(F,elf_hdr^,obj_size); + FileClose(F); + + if (n<>obj_size) then + begin + FreeMem(elf_hdr); + elf_hdr:=nil; + Exit(-5); + end; + + imgp^.image_header:=elf_hdr; + imgp^.image_self :=nil; + imgp^.elf_size :=obj_size; + end; + else + begin + Exit(-5); + end; + end; + +end; + +function scan_phdr(imgp:p_image_params;phdr:p_elf64_phdr;count:Integer):Integer; +var + i:Integer; + text_id :Integer; + data_id :Integer; + sce_relro_id:Integer; + vaddr:QWORD; + memsz:QWORD; +begin + if (imgp=nil) then Exit(-1); + if (phdr=nil) then Exit(-1); + if (count=0) then Exit(-1); + + imgp^.min_addr:=High(Int64); + imgp^.max_addr:=0; + + text_id :=-1; + data_id :=-1; + sce_relro_id:=-1; + imgp^.dyn_id:=-1; + + if (count<>0) then + For i:=0 to count-1 do + begin + + case phdr[i].p_type of + PT_LOAD, + PT_SCE_RELRO: + begin + vaddr:=phdr[i].p_vaddr; + + if ((phdr[i].p_align and PAGE_MASK)<>0) or + ((vaddr and PAGE_MASK)<>0) or + ((phdr[i].p_offset and PAGE_MASK)<>0) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' is not page aligned'); + Exit(-2); + end; + + memsz:=phdr[i].p_memsz; + + if (memsz<=phdr[i].p_filesz) and (phdr[i].p_filesz<>memsz) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz'); + Exit(-2); + end; + + if (memsz > $7fffffff) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz'); + Exit(-2); + end; + + if ((phdr[i].p_offset shr $20)<>0) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_offset'); + Exit(-2); + end; + + imgp^.min_addr:=MinInt64(imgp^.min_addr,vaddr); + + vaddr:=(vaddr+memsz+$3fff) and QWORD($ffffffffffffc000); + + imgp^.max_addr:=MaxInt64(imgp^.max_addr,vaddr); + + if (phdr[i].p_type=PT_SCE_RELRO) then + begin + sce_relro_id:=i; + end else + if ((phdr[i].p_flags and PF_X)=0) then + begin + if (data_id=-1) then data_id:=i; + end else + begin + text_id:=i; + end; + end; + + PT_DYNAMIC: + begin + imgp^.dyn_exist :=1; + imgp^.dyn_id :=i; + imgp^.dyn_vaddr :=Pointer(phdr[i].p_vaddr); + imgp^.dyn_offset:=phdr[i].p_offset; + imgp^.dyn_filesz:=phdr[i].p_filesz; + + memsz:=phdr[i].p_memsz; + + if (memsz<=phdr[i].p_filesz) and (phdr[i].p_filesz<>memsz) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz'); + Exit(-2); + end; + + if (memsz > $7fffffff) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz'); + Exit(-2); + end; + + if ((phdr[i].p_offset shr $20)<>0) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_offset'); + Exit(-2); + end; + end; + + PT_TLS: + begin + imgp^.tls_size :=phdr[i].p_memsz; + imgp^.tls_align :=phdr[i].p_align; + imgp^.tls_init_size:=phdr[i].p_filesz; + imgp^.tls_init_addr:=Pointer(phdr[i].p_vaddr); + + memsz:=phdr[i].p_memsz; + + if (memsz<=phdr[i].p_filesz) and (phdr[i].p_filesz<>memsz) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz'); + Exit(-2); + end; + + if (memsz > $7fffffff) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz'); + Exit(-2); + end; + + if ((phdr[i].p_offset shr $20)<>0) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_offset'); + Exit(-2); + end; + + if (phdr[i].p_align > 32) then + begin + Writeln(StdErr,'scan_phdr:',' alignment of segment #',i,' it must be less than 32.'); + Exit(-2); + end; + end; + + PT_SCE_DYNLIBDATA: + begin + imgp^.sce_dynlib_data_id :=i; + imgp^.sce_dynlib_data_addr:=phdr[i].p_offset; + imgp^.sce_dynlib_data_size:=phdr[i].p_filesz; + + if (phdr[i].p_memsz<>0) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz'); + Exit(-2); + end; + + if (phdr[i].p_filesz > $7fffffff) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_filesz'); + Exit(-2); + end; + + if ((phdr[i].p_offset shr $20)<>0) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_offset'); + Exit(-2); + end; + end; + + PT_SCE_PROCPARAM: + begin + imgp^.proc_param_addr:=Pointer(phdr[i].p_vaddr); + imgp^.proc_param_size:=phdr[i].p_filesz; + end; + + PT_SCE_MODULE_PARAM: + begin + imgp^.module_param_addr:=Pointer(phdr[i].p_vaddr); + imgp^.module_param_size:=phdr[i].p_filesz; + end; + + PT_GNU_EH_FRAME: + begin + imgp^.eh_frame_hdr_addr:=Pointer(phdr[i].p_vaddr); + imgp^.eh_frame_hdr_size:=phdr[i].p_memsz; + + memsz:=phdr[i].p_memsz; + + if (memsz<=phdr[i].p_filesz) and (phdr[i].p_filesz<>memsz) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz'); + Exit(-2); + end; + + if (memsz > $7fffffff) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz'); + Exit(-2); + end; + + if ((phdr[i].p_offset shr $20)<>0) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_offset'); + Exit(-2); + end; + end; + + PT_SCE_COMMENT: + begin + imgp^.sce_comment_id :=i; + imgp^.sce_comment_offset:=phdr[i].p_offset; + imgp^.sce_comment_filesz:=phdr[i].p_filesz; + + if (phdr[i].p_memsz<>0) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_memsz'); + Exit(-2); + end; + + if (phdr[i].p_filesz > $7fffffff) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_filesz'); + Exit(-2); + end; + + if ((phdr[i].p_offset shr $20)<>0) then + begin + Writeln(StdErr,'scan_phdr:',' segment #',i,' wrong p_offset'); + Exit(-2); + end; + end; + + end; + + end; + + if (imgp^.min_addr=High(Int64)) then + begin + Exit(-2); + end; + + if (imgp^.max_addr=0) then + begin + Exit(-2); + end; + + if (imgp^.dyn_exist<>0) then + begin + if (imgp^.sce_dynlib_data_size=0) then + begin + Writeln(StdErr,'scan_phdr:',' sce_dynlib_data_size is zero'); + Exit(-2); + end; + + if (imgp^.dyn_filesz=0) then + begin + Writeln(StdErr,'scan_phdr:',' dyn_filesz is zero'); + Exit(-2); + end; + end; + + if (sce_relro_id<>-1) then + begin + vaddr:=phdr[sce_relro_id].p_vaddr; + + if (vaddr=0) then + begin + Exit(-2); + end; + + memsz:=phdr[sce_relro_id].p_memsz; + + if (memsz=0) then + begin + Exit(-2); + end; + + if (((phdr[text_id].p_vaddr+phdr[text_id].p_memsz+$1fffff) and QWORD($ffffffffffe00000))<>vaddr) and + (((phdr[text_id].p_vaddr+phdr[text_id].p_memsz+$003fff) and QWORD($ffffffffffffc000))<>vaddr) then + begin + Exit(-2); + end; + + if (((vaddr+memsz+$1fffff) and QWORD($ffffffffffe00000))<>phdr[data_id].p_vaddr) and + (((vaddr+memsz+$003fff) and QWORD($ffffffffffffc000))<>phdr[data_id].p_vaddr) then + begin + Exit(-2); + end; + end; + + Result:=0; +end; + +function exec_oelf_imgact(imgp:p_image_params):Integer; +var + hdr :p_elf64_hdr; + phdr:p_elf64_phdr; +begin + Result:=0; + + if (imgp=nil) then Exit(-1); + + hdr:=imgp^.image_header; + + hdr^.e_shoff :=0; + hdr^.e_shentsize:=0; + hdr^.e_shnum :=0; + hdr^.e_shstrndx :=0; + + if (hdr=nil) then Exit(-1); + + Case hdr^.e_type of + ET_SCE_EXEC , + ET_SCE_REPLAY_EXEC, + ET_SCE_DYNEXEC : + else + begin + Writeln(StdErr,'exec_oelf_imgact:',' unspported e_type:0x',HexStr(hdr^.e_type,4)); + Exit(-2); + end; + end; + + if (hdr^.e_machine<>EM_X86_64) then + begin + Writeln(StdErr,'exec_oelf_imgact:',' unspported e_machine:',hdr^.e_machine); + Exit(-2); + end; + + phdr:=get_elf_phdr(hdr); + + Result:=scan_phdr(imgp,phdr,hdr^.e_phnum); + if (Result<>0) then + begin + Writeln(StdErr,'exec_oelf_imgact:','found illegal segment header'); + Exit; + end; + + if (imgp^.dyn_exist=0) and (hdr^.e_type=ET_SCE_DYNEXEC) then + begin + Writeln(StdErr,'exec_oelf_imgact:','illegal ELF file image'); + Exit(-2); + end; + +end; + +procedure sha256(P:Pointer;S:longword;F:PByte); +Var + D:TDCP_sha256; +begin + D.Init; + D.Update(P^,S); + D.Final(F^); +end; + +function setProperty(prop,bit,mask,val:QWORD):QWORD; inline; +begin + Result:=prop or ((val and mask) shl bit); +end; + +procedure append(var A:a_self_segment;S:SelfEntryInfo); +var + i:Integer; +begin + i:=Length(A); + SetLength(A,i+1); + A[i]:=S; +end; + +function ilog2(i:QWORD):QWORD; inline; +begin + Result:=BsfQWORD(i or 1); +end; + +function make(size:sizeint):AByte; inline; +begin + Result:=nil; + SetLength(Result,size); +end; + +function createSelfEntries(imgp:p_image_params; + prog:p_elf64_phdr; + prog_size:Integer):Integer; +var + i,entryIndex:Integer; + metaEntryProperties:QWORD; + dataEntryProperties:QWORD; + seg:SelfEntryInfo; +begin + entryIndex:=0; + + for i:=0 to prog_size-1 do + begin + + if (prog^.p_type <> PT_LOAD) and + (prog^.p_type <> PT_SCE_RELRO) and + (prog^.p_type <> PT_SCE_DYNLIBDATA) then + begin + Inc(prog); + continue; + end; + + metaEntryProperties:=0; + + metaEntryProperties:=metaEntryProperties or SELF_PROPS_SIGNED; + metaEntryProperties:=metaEntryProperties or SELF_PROPS_HAS_DIGESTS; + metaEntryProperties:=setProperty(metaEntryProperties, SELF_PROPS_SEGMENT_INDEX_OFFSET, SELF_PROPS_SEGMENT_INDEX_MASK, entryIndex+1); + + seg:=Default(SelfEntryInfo); + seg.info.flags:=metaEntryProperties; + + append(imgp^._selfEntries,seg); + + dataEntryProperties:=0; + + dataEntryProperties:=dataEntryProperties or SELF_PROPS_SIGNED; + dataEntryProperties:=dataEntryProperties or SELF_PROPS_BLOCKED; + dataEntryProperties:=setProperty(dataEntryProperties, SELF_PROPS_BLOCK_SIZE_OFFSET , SELF_PROPS_BLOCK_SIZE_MASK , ilog2(BLOCK_SIZE)-12); + dataEntryProperties:=setProperty(dataEntryProperties, SELF_PROPS_SEGMENT_INDEX_OFFSET, SELF_PROPS_SEGMENT_INDEX_MASK, i); + + seg:=Default(SelfEntryInfo); + seg.info.flags:=dataEntryProperties; + + append(imgp^._selfEntries,seg); + + entryIndex += 2; + Inc(prog); + end; + + Result:=length(imgp^._selfEntries) * SELF_META_DATA_BLOCK_SIZE; +end; + +function writeNullPadding(imgp:p_image_params; + size,_align:Integer):Integer; +var + buf:Pointer; + w:sizeint; +begin + size:=(-size) and (_align-1); + if (size=0) then Exit(0); + + buf:=AllocMem(size); + + w:=FileWrite(imgp^.outputFself,buf^,size); + if (w<>size) then + begin + Writeln(StdErr,'writeNullBytes:',' FileWrite:',w); + end; + + FreeMem(buf); + Result:=size; +end; + +function writeSelfHeader(imgp:p_image_params; + version:byte; + mode:byte; + endian:byte; + attr:byte; + headerSize:word; + fileSize:QWORD; + flags:word):Integer; +var + selfHeader:t_self_header; + w:sizeint; +begin + selfHeader.Magic :=SELF_MAGIC; + selfHeader.Version :=version; + selfHeader.Mode :=mode; + selfHeader.Endian :=endian; + selfHeader.Attr :=attr; + selfHeader.Content_Type:=1; + selfHeader.Program_Type:=1; + selfHeader.Padding :=0; + selfHeader.Header_Size :=headerSize; + selfHeader.Meta_size :=(length(imgp^._selfEntries) * SELF_ENTRY_SIZE) + SELF_META_FOOTER_SIZE + SELF_SIGNATURE_SIZE; + selfHeader.File_size :=fileSize; + selfHeader.Num_Segments:=length(imgp^._selfEntries); + selfHeader.Flags :=flags; + selfHeader.reserved :=0; + + w:=FileWrite(imgp^.outputFself,selfHeader,SizeOf(selfHeader)); + if (w<>SizeOf(selfHeader)) then + begin + Writeln(StdErr,'writeSelfHeader:',' FileWrite:',w); + end; + + Result:=SizeOf(selfHeader); +end; + +function writeSelfEntries(imgp:p_image_params):Integer; +var + i:Integer; + w:sizeint; +begin + Result:=0; + + for i:=0 to high(imgp^._selfEntries) do + begin + + w:=FileWrite(imgp^.outputFself,imgp^._selfEntries[i].info,SizeOf(t_self_segment)); + if (w<>SizeOf(t_self_segment)) then + begin + Writeln(StdErr,'writeSelfEntries:',' FileWrite:',w); + end; + + Result:=Result+SizeOf(t_self_segment); + end; + +end; + +function writeELFHeaders(imgp:p_image_params):Integer; +var + hdr:elf64_hdr; + prog:p_elf64_phdr; + prog_size:Integer; + w,s:sizeint; +begin + Result:=0; + + prog:=get_elf_phdr(imgp^.image_header); + prog_size:=imgp^.image_header^.e_phnum; + + hdr:=Default(elf64_hdr); + hdr:=imgp^.image_header^; + + w:=FileWrite(imgp^.outputFself,hdr,SizeOf(elf64_hdr)); + if (w<>SizeOf(elf64_hdr)) then + begin + Writeln(StdErr,'writeELFHeaders:',' FileWrite:',w); + end; + + Result:=SizeOf(elf64_hdr); + + s:=Sizeof(elf64_phdr)*prog_size; + + w:=FileWrite(imgp^.outputFself,prog^,s); + if (w<>s) then + begin + Writeln(StdErr,'writeELFHeaders:',' FileWrite:',w); + end; + + Result:=Result+s; +end; + +function writeExtendedInfo(imgp:p_image_params; + pType:RawByteString; + paid:uint64; + appVersion:uint64; + fwVersion:uint64; + var digest:Tsha256Digest):Integer; +var + extendedHeader:t_self_authinfo; + programType:Integer; + w:Integer; +begin + programType := SELF_PT_FAKE; + + case lowercase(Trim(pType)) of + 'npdrm_exec' :programType:=SELF_PT_NPDRM_EXEC; + 'npdrm_dynlib' :programType:=SELF_PT_NPDRM_DYNLIB; + 'system_exec' :programType:=SELF_PT_SYSTEM_EXEC; + 'system_dynlib':programType:=SELF_PT_SYSTEM_DYNLIB; + 'host_kernel' :programType:=SELF_PT_HOST_KERNEL; + 'secure_module':programType:=SELF_PT_SECURE_MODULE; + 'secure_kernel':programType:=SELF_PT_SECURE_KERNEL; + else; + end; + + extendedHeader.AuthorityID :=paid; + extendedHeader.Program_Type :=programType; + extendedHeader.Program_Version:=appVersion; + extendedHeader.System_Version :=fwVersion; + extendedHeader.Digest_SHA_256 :=digest; + + w:=FileWrite(imgp^.outputFself,extendedHeader,sizeof(t_self_authinfo)); + if (w<>sizeof(t_self_authinfo)) then + begin + Writeln(StdErr,'writeExtendedInfo:',' FileWrite:',w); + end; + + Result:=sizeof(t_self_authinfo); +end; + +function writeNpdrmControlBlock(imgp:p_image_params):Integer; +var + controlBlock:t_self_npdrm_control_block; + w:Integer; +begin + controlBlock:=Default(t_self_npdrm_control_block); + controlBlock.pType:=SELF_CONTROL_BLOCK_TYPE_NPDRM; + + w:=FileWrite(imgp^.outputFself,controlBlock,sizeof(t_self_npdrm_control_block)); + if (w<>sizeof(t_self_npdrm_control_block)) then + begin + Writeln(StdErr,'writeNpdrmControlBlock:',' FileWrite:',w); + end; + + Result:=sizeof(t_self_npdrm_control_block); +end; + +function writeMetaBlocks(imgp:p_image_params):Integer; +var + buf:Pointer; + w,size:sizeint; +begin + size:=SELF_META_BLOCK_SIZE*length(imgp^._selfEntries); + buf:=AllocMem(size); + + w:=FileWrite(imgp^.outputFself,buf^,size); + if (w<>size) then + begin + Writeln(StdErr,'writeMetaBlocks:',' FileWrite:',w); + end; + + FreeMem(buf); + Result:=size; +end; + +function writeMetaFooter(imgp:p_image_params;val:DWORD):Integer; +var + buf:Pointer; + w,size:sizeint; +begin + size:=SELF_META_FOOTER_SIZE; + buf:=AllocMem(size); + + PDWORD(buf+$30)^:=val; + + w:=FileWrite(imgp^.outputFself,buf^,size); + if (w<>size) then + begin + Writeln(StdErr,'writeMetaFooter:',' FileWrite:',w); + end; + + FreeMem(buf); + Result:=size; +end; + +function writeSignature(imgp:p_image_params;var signature:Tsignature):Integer; +var + w:sizeint; +begin + + w:=FileWrite(imgp^.outputFself,signature,sizeof(Tsignature)); + if (w<>sizeof(Tsignature)) then + begin + Writeln(StdErr,'writeSignature:',' FileWrite:',w); + end; + + Result:=sizeof(Tsignature); +end; + +function writeSegments(imgp:p_image_params):Integer; +var + i:Integer; + w,s:sizeint; +begin + Result:=0; + + for i:=0 to high(imgp^._selfEntries) do + begin + + //Writeln(imgp^._selfEntries[i].info.offset,':',Length(imgp^._selfEntries[i].data)); + + s:=imgp^._selfEntries[i].info.offset; + w:=FileSeek(imgp^.outputFself,s,fsFromBeginning); + if (w<>s) then + begin + Writeln(StdErr,'writeSegments:',' FileSeek:',w); + end; + + s:=Length(imgp^._selfEntries[i].data); + + w:=FileWrite(imgp^.outputFself,imgp^._selfEntries[i].data[0],s); + if (w<>s) then + begin + Writeln(StdErr,'writeSegments:',' FileWrite:',w); + end; + + Result:=Result+s; + end; + +end; + +function CreateFSELF(imgp:p_image_params; + outputPath:RawByteString; + paid:int64; + pType:RawByteString; + appVersion:int64; + fwVersion:int64; + authInfo:RawByteString):Integer; + +var + sha256Digest:Tsha256Digest; + signature:Tsignature; + headerSize:QWORD; + offset:QWORD; + fileSize:QWORD; + finalFileSize:QWORD; + prog:p_elf64_phdr; + prog_size:Integer; + i,entryIndex:Integer; + numBlocks:Integer; + signedBlockCount:Integer; + flags:Integer; + metaData:AByte; + segmentData:AByte; + base:Pointer; +begin + + imgp^.outputFself:=FileCreate(outputPath); + + if (imgp^.outputFself=THandle(-1)) then + begin + Writeln(StdErr,'CreateFSELF:',' FileCreate error'); + Exit; + end; + + sha256Digest:=Default(Tsha256Digest); + sha256(imgp^.image_header,imgp^.elf_size,@sha256Digest); + + signature:=Default(Tsignature); + + { + if authInfo != "" { + signature = createSignature(authInfo, paid) + } + } + + prog:=get_elf_phdr(imgp^.image_header); + prog_size:=imgp^.image_header^.e_phnum; + + headerSize := SELF_HEADER_SIZE; + headerSize += createSelfEntries(imgp,prog,prog_size); + headerSize += SELF_ELF_HEADER_SIZE; + headerSize += prog_size * SELF_ELF_PROGHEADER_SIZE; + + headerSize := Align(headerSize, $10); + + headerSize += SELF_EXTENDED_HEADER_SIZE; + headerSize += SELF_NPDRM_BLOCK_SIZE; + + entryIndex := 0; + offset := headerSize + (length(imgp^._selfEntries)*SELF_ENTRY_SIZE)+SELF_META_FOOTER_SIZE+SELF_SIGNATURE_SIZE; + + for i:=0 to prog_size-1 do + begin + + if (prog^.p_type <> PT_LOAD) and + (prog^.p_type <> PT_SCE_RELRO) and + (prog^.p_type <> PT_SCE_DYNLIBDATA) then + begin + Inc(prog); + continue; + end; + + numBlocks := align(prog^.p_filesz, BLOCK_SIZE) div BLOCK_SIZE; + + metaData:=make(SELF_META_DATA_BLOCK_SIZE*numBlocks); + + imgp^._selfEntries[entryIndex].Data := metaData; + imgp^._selfEntries[entryIndex].info.offset := offset; + imgp^._selfEntries[entryIndex].info.filesz := length(metaData); + imgp^._selfEntries[entryIndex].info.memsz := length(metaData); + + offset += imgp^._selfEntries[entryIndex].info.filesz; + offset := align(offset, $10); + + segmentData := make(prog^.p_filesz); + + base:=Pointer(imgp^.image_header)+prog^.p_offset; + Move(base^,segmentData[0],length(segmentData)); + + imgp^._selfEntries[entryIndex+1].Data := segmentData; + imgp^._selfEntries[entryIndex+1].info.offset := offset; + imgp^._selfEntries[entryIndex+1].info.filesz := prog^.p_filesz; + imgp^._selfEntries[entryIndex+1].info.memsz := prog^.p_filesz; + + offset += imgp^._selfEntries[entryIndex+1].info.filesz; + offset := align(offset, $10); + + entryIndex += 2; + Inc(prog); + end; + + fileSize := offset; + + signedBlockCount := $2; + flags := $2 or ((signedBlockCount and $7) shl 4); + + finalFileSize := 0; + + finalFileSize += writeSelfHeader(imgp, + 0, + SELF_MODE_SPECIFICUSER, + SELF_DATA_LSB, + $12, + headerSize, + fileSize, + flags + ); + + finalFileSize += writeNullPadding(imgp, finalFileSize, $10); + finalFileSize += writeSelfEntries(imgp); + finalFileSize += writeELFHeaders(imgp); + finalFileSize += writeNullPadding(imgp, finalFileSize, $10); + finalFileSize += writeExtendedInfo(imgp, pType, paid, appVersion, fwVersion, sha256Digest); + finalFileSize += writeNpdrmControlBlock(imgp); + finalFileSize += writeMetaBlocks(imgp); + finalFileSize += writeMetaFooter(imgp, $10000); + finalFileSize += writeSignature(imgp, signature); + finalFileSize += writeSegments(imgp); + + FileClose(imgp^.outputFself); + + Result:=0; +end; + +function get_sdk_version_str(version:QWORD):RawByteString; +begin + Result:=HexStr((version shr 24),2)+'.'+HexStr(((version shr 12) and $fff),3)+'.'+HexStr((version and $fff),3); +end; + +function HexToDword(S:RawByteString;_def:DWORD):DWORD; +begin + Result:=_def; + + if (copy(S,1,2)='0x') then + begin + Delete(S,1,2); + S:='$'+S; + end; + + TryStrToUInt(S,Result); +end; + +function HexToQword(S:RawByteString;_def:QWORD):QWORD; +begin + Result:=_def; + + if (copy(S,1,2)='0x') then + begin + Delete(S,1,2); + S:='$'+S; + end; + + TryStrToUInt64(S,Result); +end; + +var + InputFileName :RawByteString=''; //input Orbis OELF filepath + OutputFileName:RawByteString=''; //output Orbis FSELF filepath + sdkver :DWORD =$1000051; //SDK version integer + ptype :RawByteString=''; //program type + authInfo :RawByteString=''; //authentication info + paid :QWORD =$3800000000000011; //program authentication ID + appVer :QWORD =0; //application version + fwVer :QWORD =0; //firmware version + +procedure parse_param; +var + i:Integer; + S:RawByteString; + n:Integer; +begin + n:=-1; + For i:=1 to ParamCount do + begin + S:=Trim(ParamStr(i)); + + case LowerCase(S) of + '-i':n:=0; + '-o':n:=1; + '-sdkver':n:=2; + '-ptype':n:=3; + '-authinfo':n:=4; + '-paid':n:=5; + '-appver':n:=6; + '-fwver':n:=7; + else + if (n<>-1) then + begin + Case n of + 0:InputFileName :=S; + 1:OutputFileName:=S; + 2:sdkver :=HexToDword(S,sdkver); + 3:ptype :=LowerCase(S); + 4:authInfo :=S; + 5:paid :=HexToQword(S,paid); + 6:appVer :=HexToQword(S,appVer); + 7:fwVer :=HexToQword(S,fwVer); + end; + n:=-1; + end else + begin + InputFileName:=S; + end; + end; + + end; +end; + +var + r:Integer; + img:t_image_params; + +begin + parse_param; + + if (ParamCount<=1) or (InputFileName='') then + begin + + Writeln('Usage: oelf2fself <option(s)>'); + Writeln(' Convert Orbis ELF file to Fake SELF file'); + Writeln(' Options are:'); + Writeln(' -i input Orbis OELF filepath'); + Writeln(' -o output Orbis FSELF filepath'); + Writeln(' -sdkver SDK version integer'); + Writeln(' -ptype program type'); + Writeln(' -authinfo authentication info'); + Writeln(' -paid program authentication ID'); + Writeln(' -appver application version'); + Writeln(' -fwver firmware version'); + + Exit; + end; + + if (OutputFileName='') then + begin + OutputFileName:=ChangeFileExt(InputFileName,'.bin'); + end; + + img:=Default(t_image_params); + r:=load_oelf(InputFileName,@img); + + if (r<>0) then + begin + Writeln('Error(',r,') load file:',InputFileName); + end else + begin + r:=exec_oelf_imgact(@img); + + if (r<>0) then + begin + Writeln('Error(',r,') parse file:',InputFileName); + end else + begin + + CreateFSELF(@img, + OutputFileName, + paid, + ptype, + appVer, + fwVer, + authInfo); + + end; + + + + + end; + + free_imgp(@img); + + readln; +end. + diff --git a/tools/readself/elf64.pas b/tools/readself/elf64.pas deleted file mode 100644 index 69c753e3..00000000 --- a/tools/readself/elf64.pas +++ /dev/null @@ -1,730 +0,0 @@ -unit elf64; - -{$mode objfpc}{$H+} - -interface - -uses ctypes; - -{ - /--------------------------------------\--\ - |SELF Header Structure(t_self_header) | | - +--------------------------------------+--|-\ - |SELF Segment Structure(t_self_segment)| | | <- t_self_header.Num_Segments * SizeOf(t_self_segment) - +--------------------------------------+--|-/ - |ELF Segment Structure(elf64_hdr) | | - +--------------------------------------+--|-\ - |ELF Program header(elf64_phdr) | | | <- elf64_hdr.e_phnum * SizeOf(elf64_phdr) - +--------------------------------------+--|-/ - |Align(addr,16) | | - +--------------------------------------+ | - |SELF authinfo(t_self_authinfo) | | <- t_self_header.Header_Size - +--------------------------------------+ | - |Content_ID/Digest_SHA_256 | | - +--------------------------------------+-/--\ - |Metadata/Segment Certification | | <- t_self_header.Meta_size - +--------------------------------------+----/ - |ELF segments data | - \--------------------------------------/ -} - -Const - ET_NONE =0; - ET_REL =1; - ET_EXEC =2; - ET_DYN =3; - ET_CORE =4; - ET_SCE_EXEC =$FE00; - ET_SCE_REPLAY_EXEC=$FE01; - ET_SCE_RELEXEC =$FE04; - ET_SCE_STUBLIB =$FE0C; - ET_SCE_DYNEXEC =$FE10; - ET_SCE_DYNAMIC =$FE18; - - EI_MAG0 = 0; // e_ident[] indexes - EI_MAG1 = 1; - EI_MAG2 = 2; - EI_MAG3 = 3; - EI_CLASS = 4; - EI_DATA = 5; - EI_VERSION = 6; - EI_OSABI = 7; - EI_ABIVERSION = 8; - - EI_NIDENT=16; - - ELFMAG =$464C457F; - SELFMAG=4; - - EM_NONE =0; - EM_X86_64 =62; // AMD x86-64 - - PT_NULL = 0; - PT_LOAD = 1; - PT_DYNAMIC = 2; - PT_INTERP = 3; - PT_NOTE = 4; - PT_SHLIB = 5; - PT_PHDR = 6; - PT_TLS = 7; // Thread local storage segment - PT_SCE_RELA = $60000000; - PT_SCE_DYNLIBDATA = $61000000; - PT_SCE_PROCPARAM = $61000001; - PT_SCE_MODULE_PARAM = $61000002; - PT_SCE_RELRO = $61000010; - PT_GNU_EH_FRAME = $6474e550; - PT_GNU_STACK = $6474E551; - PT_SCE_COMMENT = $6FFFFF00; - PT_SCE_VERSION = $6FFFFF01; - PT_SCE_SEGSYM = $700000A8; - - // This is the info that is needed to parse the dynamic section of the file - DT_NULL = 0; - DT_NEEDED = 1; - DT_PLTRELSZ = 2; - DT_PLTGOT = 3; - DT_HASH = 4; - DT_STRTAB = 5; - DT_SYMTAB = 6; - DT_RELA = 7; - DT_RELASZ = 8; - DT_RELAENT = 9; - DT_STRSZ =10; - DT_SYMENT =11; - DT_INIT =12; - DT_FINI =13; - DT_SONAME =14; - DT_RPATH =15; - DT_SYMBOLIC =16; - DT_REL =17; - DT_RELSZ =18; - DT_RELENT =19; - DT_PLTREL =20; - DT_DEBUG =21; - DT_TEXTREL =22; - DT_JMPREL =23; - DT_BIND_NOW =24; - DT_INIT_ARRAY =25; - DT_FINI_ARRAY =26; - DT_INIT_ARRAYSZ =27; - DT_FINI_ARRAYSZ =28; - DT_RUNPATH =29; - DT_FLAGS =30; - DT_ENCODING =31; - DT_PREINIT_ARRAY =32; - DT_PREINIT_ARRAYSZ =33; - DT_SCE_IDTABENTSZ =$61000005; - DT_SCE_FINGERPRINT =$61000007; - DT_SCE_ORIGINAL_FILENAME =$61000009; - DT_SCE_MODULE_INFO =$6100000D; - DT_SCE_NEEDED_MODULE =$6100000F; - DT_SCE_MODULE_ATTR =$61000011; - DT_SCE_EXPORT_LIB =$61000013; - DT_SCE_IMPORT_LIB =$61000015; - DT_SCE_EXPORT_LIB_ATTR =$61000017; - DT_SCE_IMPORT_LIB_ATTR =$61000019; - DT_SCE_STUB_MODULE_NAME =$6100001D; - DT_SCE_STUB_MODULE_VERSION =$6100001F; - DT_SCE_STUB_LIBRARY_NAME =$61000021; - DT_SCE_STUB_LIBRARY_VERSION =$61000023; - DT_SCE_HASH =$61000025; - DT_SCE_PLTGOT =$61000027; - DT_SCE_JMPREL =$61000029; - DT_SCE_PLTREL =$6100002B; - DT_SCE_PLTRELSZ =$6100002D; - DT_SCE_RELA =$6100002F; - DT_SCE_RELASZ =$61000031; - DT_SCE_RELAENT =$61000033; - DT_SCE_STRTAB =$61000035; - DT_SCE_STRSZ =$61000037; - DT_SCE_SYMTAB =$61000039; - DT_SCE_SYMENT =$6100003B; - DT_SCE_HASHSZ =$6100003D; - DT_SCE_SYMTABSZ =$6100003F; - DT_SCE_HIOS =$6FFFF000; - DT_GNU_HASH =$6ffffef5; - DT_VERSYM =$6ffffff0; - DT_RELACOUNT =$6ffffff9; - DT_RELCOUNT =$6ffffffa; - DT_FLAGS_1 =$6ffffffb; - DT_VERDEF =$6ffffffc; - DT_VERDEFNUM =$6ffffffd; - - DF_ORIGIN =$01; - DF_SYMBOLIC =$02; - DF_TEXTREL =$04; - DF_BIND_NOW =$08; - DF_STATIC_TLS=$10; - - DF_1_BIND_NOW=$01; - DF_1_NODELETE=$08; - DF_1_LOADFLTR=$10; - DF_1_NOOPEN =$40; - - SHT_SYMTAB=2; - SHT_STRTAB=3; - - // Relocation types for AMD x86-64 architecture - R_X86_64_NONE = 0; // No reloc - R_X86_64_64 = 1; // Direct 64 bit - R_X86_64_PC32 = 2; // PC relative 32 bit signed - R_X86_64_GOT32 = 3; // 32 bit GOT entry - R_X86_64_PLT32 = 4; // 32 bit PLT address - R_X86_64_COPY = 5; // Copy symbol at runtime - R_X86_64_GLOB_DAT = 6; // Create GOT entry - R_X86_64_JUMP_SLOT = 7; // Create PLT entry - R_X86_64_RELATIVE = 8; // Adjust by program base - R_X86_64_GOTPCREL = 9; // 32 bit signed pc relative offset to GOT - R_X86_64_32 =10; // Direct 32 bit zero extended - R_X86_64_32S =11; // Direct 32 bit sign extended - R_X86_64_16 =12; // Direct 16 bit zero extended - R_X86_64_PC16 =13; // 16 bit sign extended pc relative - R_X86_64_8 =14; // Direct 8 bit sign extended - R_X86_64_PC8 =15; // 8 bit sign extended pc relative - R_X86_64_DTPMOD64 =16; // ID of module containing symbol - R_X86_64_DTPOFF64 =17; // Offset in module's TLS block - R_X86_64_TPOFF64 =18; // Offset in initial TLS block - R_X86_64_TLSGD =19; // 32 bit signed PC relative offset to two GOT entries for GD symbol - R_X86_64_TLSLD =20; // 32 bit signed PC relative offset to two GOT entries for LD symbol - R_X86_64_DTPOFF32 =21; // Offset in TLS block - R_X86_64_GOTTPOFF =22; // 32 bit signed PC relative offset to GOT entry for IE symbol - R_X86_64_TPOFF32 =23; // Offset in initial TLS block - R_X86_64_PC64 =24; // PC relative 64 bit - R_X86_64_GOTOFF64 =25; // 64 bit offset to GOT - R_X86_64_GOTPC32 =26; // 32 bit signed pc relative offset to GOT - R_X86_64_GOT64 =27; // 64-bit GOT entry offset - R_X86_64_GOTPCREL64 =28; // 64-bit PC relative offset to GOT entry - R_X86_64_GOTPC64 =29; // 64-bit PC relative offset to GOT - R_X86_64_GOTPLT64 =30; // like GOT64, says PLT entry needed - R_X86_64_PLTOFF64 =31; // 64-bit GOT relative offset to PLT entry - R_X86_64_SIZE32 =32; // Size of symbol plus 32-bit addend - R_X86_64_SIZE64 =33; // Size of symbol plus 64-bit addend - R_X86_64_GOTPC32_TLSDESC =34; // GOT offset for TLS descriptor - R_X86_64_TLSDESC_CALL =35; // Marker for call through TLS descriptor - R_X86_64_TLSDESC =36; // TLS descriptor - R_X86_64_IRELATIVE =37; // Adjust indirectly by program base - R_X86_64_RELATIVE64 =38; // 64bit adjust by program base - R_X86_64_ORBIS_GOTPCREL_LOAD =40; - - STB_LOCAL =0; - STB_GLOBAL=1; - STB_WEAK =2; - - STT_NOTYPE = 0; //module_start/module_stop - STT_OBJECT = 1; - STT_FUN = 2; - STT_SECTION = 3; - STT_FILE = 4; - STT_COMMON = 5; - STT_TLS = 6; - STT_LOOS =10; - STT_SCE =11; //module_start/module_stop - - //ST_LOCAL_NONE = 0x00 - //ST_LOCAL_OBJECT = 0x01 - //ST_LOCAL_FUNCTION = 0x02 - //ST_LOCAL_SECTION = 0x03 - //ST_LOCAL_FILE = 0x04 - //ST_LOCAL_COMMON = 0x05 - //ST_LOCAL_TLS = 0x06 - //ST_LOCAL_SCE = 0x0B - //ST_GLOBAL_NONE = 0x10 - //ST_GLOBAL_OBJECT = 0x11 - //ST_GLOBAL_FUNCTION = 0x12 - //ST_GLOBAL_SECTION = 0x13 - //ST_GLOBAL_FILE = 0x14 - //ST_GLOBAL_COMMON = 0x15 - //ST_GLOBAL_TLS = 0x16 - //ST_GLOBAL_SCE = 0x1B - //ST_WEAK_NONE = 0x20 - //ST_WEAK_OBJECT = 0x21 - //ST_WEAK_FUNCTION = 0x22 - //ST_WEAK_SECTION = 0x23 - //ST_WEAK_FILE = 0x24 - //ST_WEAK_COMMON = 0x25 - //ST_WEAK_TLS = 0x26 - //ST_WEAK_SCE = 0x2B - - STV_DEFAULT =0; - STV_INTERNAL =1; - STV_HIDDEN =2; - STV_PROTECTED =3; - - SHN_UNDEF=0; - - PF_X=$1; - PF_W=$2; - PF_R=$4; - -type - Elf64_Addr =cuint64; - Elf64_Half =cuint16; - Elf64_SHalf =cint64 ; - Elf64_Off =cuint64; - Elf64_Sword =cint32 ; - Elf64_Word =cuint32; - Elf64_Xword =cuint64; - Elf64_Sxword=cint64 ; - - p_elf64_hdr=^elf64_hdr; - elf64_hdr=packed record - e_ident:Array[0..EI_NIDENT-1] of Byte; // ELF "magic number" - e_type :Elf64_Half; - e_machine :Elf64_Half; - e_version :Elf64_Word; - e_entry :Elf64_Addr; // Entry point virtual address from where the process starts executing. - e_phoff :Elf64_Off ; // Program header table file offset - e_shoff :Elf64_Off ; // Section header table file offset - e_flags :Elf64_Word; - e_ehsize :Elf64_Half; - e_phentsize:Elf64_Half; - e_phnum :Elf64_Half; - e_shentsize:Elf64_Half; - e_shnum :Elf64_Half; - e_shstrndx :Elf64_Half; - end; - - p_elf64_phdr=^elf64_phdr; - elf64_phdr=packed record - p_type :Elf64_Word ; - p_flags :Elf64_Word ; - p_offset:Elf64_Off ; // Segment file offset - p_vaddr :Elf64_Addr ; // Segment virtual address - p_paddr :Elf64_Addr ; // Segment physical address - p_filesz:Elf64_Xword; // Segment size in file - p_memsz :Elf64_Xword; // Segment size in memory - p_align :Elf64_Xword; // Segment alignment, file & memory - end; - - p_elf64_shdr=^elf64_shdr; - elf64_shdr=packed record - sh_name :Elf64_Word ; // Section name, index in string tbl - sh_type :Elf64_Word ; // Type of section - sh_flags :Elf64_Xword; // Miscellaneous section attributes - sh_addr :Elf64_Addr ; // Section virtual addr at execution - sh_offset :Elf64_Off ; // Section file offset - sh_size :Elf64_Xword; // Size of section in bytes - sh_link :Elf64_Word ; // Index of another section - sh_info :Elf64_Word ; // Additional section information - sh_addralign:Elf64_Xword; // Section alignment - sh_entsize :Elf64_Xword; // Entry size if section holds table - end; - - p_elf64_dyn=^elf64_dyn; - elf64_dyn=packed record - d_tag:Elf64_Sxword; // entry tag value - d_un :packed record - Case Byte of - 0:(d_val:Elf64_Xword); - 1:(d_ptr:Elf64_Addr); - end; - end; - - p_elf64_rela=^elf64_rela; - elf64_rela=packed record - r_offset:Elf64_Addr; // Location at which to apply the action - r_info :Elf64_Xword; // index and type of relocation - r_addend:Elf64_Sxword; // Constant addend used to compute value - end; - - p_elf64_sym=^elf64_sym; - elf64_sym=packed record - st_name :Elf64_Word; // Symbol name, index in string tbl - st_info :Byte; // Type and binding attributes - st_other:Byte; // No defined meaning, 0 - st_shndx:Elf64_Half; // Associated section index - st_value:Elf64_Addr; // Value of the symbol - st_size :Elf64_Xword; // Associated symbol size - end; - -const - SELF_MAGIC =$1D3D154F; - SELF_VERSION =$0; - SELF_MODE =$1; - SELF_ENDIANNESS=$1; - - SELF_AUTH_INFO_SIZE =$88; - SELF_KEY_SIZE =$10; - SELF_DIGEST_SIZE =$20; - SELF_SEGMENT_BLOCK_ALIGNMENT=$10; - -type - p_self_header=^t_self_header; - t_self_header=packed record - Magic :DWORD; //Magic 4F 15 3D 1D - Version :Byte; //0 - Mode :Byte; //1 - Endian :Byte; //1 - Attr :Byte; // - Content_Type:Byte; //Content Type 1 on Self, 4 on PUP Entry - Program_Type:Byte; //Program Type - Padding :Word; //Padding - Header_Size :Word; //Header Size - Meta_size :Word; //Signature Size Metadata Size? - File_size :QWORD; //Size of SELF - Num_Segments:Word; //Number of Segments - Flags :Word; // - reserved :DWORD; // - end; - -const - SELF_PROPS_ORDERED = $00000001; - SELF_PROPS_ENCRYPTED = $00000002; - SELF_PROPS_SIGNED = $00000004; - SELF_PROPS_COMPRESSED = $00000008; - SELF_PROPS_WINDOW = $00000700; - SELF_PROPS_BLOCKED = $00000800; - SELF_PROPS_BLOCK_SIZE = $0000F000; - SELF_PROPS_HAS_DIGESTS = $00010000; - SELF_PROPS_HAS_EXTENTS = $00020000; - SELF_PROPS_SEGMENT_INDEX = $7FF00000; - - SELF_PROPS_WINDOW_OFFSET=8; - SELF_PROPS_WINDOW_MASK =7; - - SELF_PROPS_BLOCK_SIZE_OFFSET=12; - SELF_PROPS_BLOCK_SIZE_MASK =$F; - - SELF_PROPS_SEGMENT_INDEX_OFFSET=20; - SELF_PROPS_SEGMENT_INDEX_MASK =$7FF; - - SELF_PT_FAKE =$1; - SELF_PT_NPDRM_EXEC =$4; - SELF_PT_NPDRM_DYNLIB =$5; - SELF_PT_SYSTEM_EXEC =$8; - SELF_PT_SYSTEM_DYNLIB=$9; - SELF_PT_HOST_KERNEL =$C; - SELF_PT_SECURE_MODULE=$E; - SELF_PT_SECURE_KERNEL=$F; - -type - p_self_segment=^t_self_segment; - t_self_segment=packed record - flags :QWORD; - offset:QWORD; - filesz:QWORD; - memsz :QWORD; - end; - - p_self_authinfo=^t_self_authinfo; - t_self_authinfo=packed record - AuthorityID :QWORD; - Program_Type :QWORD; - Program_Version:QWORD; - System_Version :QWORD; - //Content_ID :array[0..31] of Byte; //Optional - Digest_SHA_256 :array[0..31] of Byte; - end; - - 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); - 1:(name_offset:DWORD; - version :Word; - id :Word); - end; - - TLibraryValue=packed record - case Byte of - 0:(value :Int64); - 1:(name_offset:DWORD; - version :Word; - id :Word); - end; - - TLibraryAttr=packed record - case Byte of - 0:(value:Int64); - 1:(attr :WORD; - align:DWORD; - id :Word); - end; - - PTLS_index=^TLS_index; - TLS_index=packed record - ti_moduleid :QWORD; - ti_tlsoffset:QWORD; - end; - - PPS4StartupParams=^TPS4StartupParams; - TPS4StartupParams=packed record - argc:Integer; - align:Integer; - argv:array[0..2] of Pointer; - //envrion = argv + argc + 1 - end; - -type - t_user_malloc_init =function():Integer; SysV_ABI_CDecl; - t_user_malloc_finalize =function():Integer; SysV_ABI_CDecl; - t_user_malloc =function(size:qword):Pointer; SysV_ABI_CDecl; - t_user_free =procedure(ptr:Pointer); SysV_ABI_CDecl; - t_user_calloc =function(nelem,count:qword):Pointer; SysV_ABI_CDecl; - t_user_realloc =function(ptr:Pointer;size:qword):Pointer; SysV_ABI_CDecl; - t_user_memalign =function(align,size:qword):Pointer; SysV_ABI_CDecl; - t_user_reallocalign =function(ptr:Pointer;size,align:qword):Pointer; SysV_ABI_CDecl; - t_user_posix_memalign =function(ptr:PPointer;align,size:qword):Integer; SysV_ABI_CDecl; - t_user_malloc_stats =function(mmsize:Pointer):Integer; SysV_ABI_CDecl; - t_user_malloc_stats_fast =function(mmsize:Pointer):Integer; SysV_ABI_CDecl; - t_user_malloc_usable_size=function(ptr:Pointer):qword; SysV_ABI_CDecl; - - PsceLibcMallocReplace=^TsceLibcMallocReplace; - TsceLibcMallocReplace=packed record - Size:QWORD; - Unknown1:QWORD; //00000001 - user_malloc_init :t_user_malloc_init; - user_malloc_finalize :t_user_malloc_finalize; - user_malloc :t_user_malloc; - user_free :t_user_free; - user_calloc :t_user_calloc; - user_realloc :t_user_realloc; - user_memalign :t_user_memalign; - user_reallocalign :t_user_reallocalign; - user_posix_memalign :t_user_posix_memalign; - user_malloc_stats :t_user_malloc_stats; - user_malloc_stats_fast :t_user_malloc_stats_fast; - user_malloc_usable_size:t_user_malloc_usable_size; - end; - - t_user_new_1 =function(size:qword):Pointer; SysV_ABI_CDecl; - t_user_new_2 =function(size:qword;throw:Pointer):Pointer; SysV_ABI_CDecl; - t_user_new_array_1 =function(size:qword):Pointer; SysV_ABI_CDecl; - t_user_new_array_2 =function(size:qword;throw:Pointer):Pointer; SysV_ABI_CDecl; - t_user_delete_1 =procedure(ptr:Pointer); SysV_ABI_CDecl; - t_user_delete_2 =procedure(ptr:Pointer;throw:Pointer); SysV_ABI_CDecl; - t_user_delete_array_1=procedure(ptr:Pointer); SysV_ABI_CDecl; - t_user_delete_array_2=procedure(ptr:Pointer;throw:Pointer); SysV_ABI_CDecl; - t_user_delete_3 =procedure(ptr:Pointer;size:qword); SysV_ABI_CDecl; - t_user_delete_4 =procedure(ptr:Pointer;size:qword;throw:Pointer); SysV_ABI_CDecl; - t_user_delete_array_3=procedure(ptr:Pointer;size:qword); SysV_ABI_CDecl; - t_user_delete_array_4=procedure(ptr:Pointer;size:qword;throw:Pointer); SysV_ABI_CDecl; - - PsceLibcNewReplace=^TsceLibcNewReplace; - TsceLibcNewReplace=packed record - Size:QWORD; - Unknown1:QWORD; //00000002 - user_new_1 :t_user_new_1; - user_new_2 :t_user_new_2; - user_new_array_1 :t_user_new_array_1; - user_new_array_2 :t_user_new_array_2; - user_delete_1 :t_user_delete_1; - user_delete_2 :t_user_delete_2; - user_delete_array_1:t_user_delete_array_1; - user_delete_array_2:t_user_delete_array_2; - user_delete_3 :t_user_delete_3; - user_delete_4 :t_user_delete_4; - user_delete_array_3:t_user_delete_array_3; - user_delete_array_4:t_user_delete_array_4; - end; - - t_user_malloc_init_for_tls =function():Integer; SysV_ABI_CDecl; - t_user_malloc_fini_for_tls =function():Integer; SysV_ABI_CDecl; - t_user_malloc_for_tls =function(size:qword):Pointer; SysV_ABI_CDecl; - t_user_posix_memalign_for_tls=function(ptr:PPointer;align,size:qword):Integer; SysV_ABI_CDecl; - t_user_free_for_tls =procedure(ptr:Pointer); SysV_ABI_CDecl; - - PsceLibcMallocReplaceForTls=^TsceLibcMallocReplaceForTls; - TsceLibcMallocReplaceForTls=packed record - Size:QWORD; - Unknown1:QWORD; //00000001 - user_malloc_init_for_tls :t_user_malloc_init_for_tls; - user_malloc_fini_for_tls :t_user_malloc_fini_for_tls; - user_malloc_for_tls :t_user_malloc_for_tls; - user_posix_memalign_for_tls:t_user_posix_memalign_for_tls; - user_free_for_tls :t_user_free_for_tls; - end; - - PSceLibcParam=^TSceLibcParam; - TSceLibcParam=packed record - Size:QWORD; - entry_count:DWORD; - SceLibcInternalHeap :DWORD; //1 //(entry_count > 1) - sceLibcHeapSize :PDWORD; - sceLibcHeapDelayedAlloc :PDWORD; - sceLibcHeapExtendedAlloc :PDWORD; - sceLibcHeapInitialSize :PDWORD; - _sceLibcMallocReplace :PsceLibcMallocReplace; - _sceLibcNewReplace :PsceLibcNewReplace; - sceLibcHeapHighAddressAlloc :PQWORD; //(entry_count > 2) - Need_sceLibc :PDWORD; - sceLibcHeapMemoryLock :PQWORD; //(entry_count > 4) - sceKernelInternalMemorySize :PQWORD; - _sceLibcMallocReplaceForTls :PsceLibcMallocReplaceForTls; - //The maximum amount of the memory areas for the mspace. min:0x1000000 - sceLibcMaxSystemSize :PQWORD; //(entry_count > 7) - sceLibcHeapDebugFlags :PQWORD; //(entry_count > 8) - sceLibcStdThreadStackSize :PDWORD; - Unknown3:QWORD; - sceKernelInternalMemoryDebugFlags:PDWORD; - sceLibcWorkerThreadNum :PDWORD; - sceLibcWorkerThreadPriority :PDWORD; - sceLibcThreadUnnamedObjects :PDWORD; - end; - - PSceKernelMemParam=^TSceKernelMemParam; - TSceKernelMemParam=packed record - Size:QWORD; - sceKernelExtendedPageTable :PQWORD; - sceKernelFlexibleMemorySize :PQWORD; - sceKernelExtendedMemory1 :PByte; - sceKernelExtendedGpuPageTable:PQWORD; - sceKernelExtendedMemory2 :PByte; - sceKernelExtendedCpuPageTable:PQWORD; - end; - - PSceKernelFsParam=^TSceKernelFsParam; - TSceKernelFsParam=packed record - Size:QWORD; - sceKernelFsDupDent :PDWORD; - sceWorkspaceUpdateMode:Pointer; - sceTraceAprNameMode :Pointer; - end; - - PSceProcParam=^TSceProcParam; - TSceProcParam=packed record - Size :QWORD; //0x50 - Magic :DWORD; //"ORBI" //0x4942524F - Entry_count :DWORD; //>=1 - SDK_version :QWORD; //0x4508101 - sceProcessName :PChar; - sceUserMainThreadName :PChar; - sceUserMainThreadPriority :PDWORD; - sceUserMainThreadStackSize:PDWORD; - _sceLibcParam :PSceLibcParam; - _sceKernelMemParam :PSceKernelMemParam; - _sceKernelFsParam :PSceKernelFsParam; - sceProcessPreloadEnabled :PDWORD; - Unknown1 :QWORD; - end; - - PsceModuleParam=^TsceModuleParam; - TsceModuleParam=packed record - Size :QWORD; - Magic :QWORD; - SDK_version:QWORD; - end; - -function SELF_WINDOW(i:Int64):Integer; inline; -function SELF_BLOCK_SIZE(i:Int64):Int64; inline; -function SELF_SEGMENT_INDEX(i:Int64):Integer; inline; - -function ELF64_R_SYM (i:QWORD):DWORD; inline; -function ELF64_R_TYPE(i:QWORD):DWORD; inline; -function ELF64_ST_BIND(i:Byte):Byte; inline; -function ELF64_ST_TYPE(i:Byte):Byte; inline; -function ELF64_ST_VISIBILITY(i:Byte):Byte; inline; - -function AlignUp(addr:PtrUInt;alignment:PtrUInt):PtrUInt; inline; -function AlignUp(addr:Pointer;alignment:PtrUInt):Pointer; inline; -function AlignDw(addr:PtrUInt;alignment:PtrUInt):PtrUInt; inline; -function AlignDw(addr:Pointer;alignment:PtrUInt):Pointer; inline; -function IsAlign(Addr:Pointer;Alignment:PtrUInt):Boolean; inline; -function IsAlign(Addr:PtrUInt;Alignment:PtrUInt):Boolean; inline; - -implementation - -function SELF_WINDOW(i:Int64):Integer; inline; -begin - Result:=(i shr SELF_PROPS_WINDOW_OFFSET) and SELF_PROPS_WINDOW_MASK; -end; - -function SELF_BLOCK_SIZE(i:Int64):Int64; inline; -begin - Result:=(i shr SELF_PROPS_BLOCK_SIZE_OFFSET) and SELF_PROPS_BLOCK_SIZE_MASK; - Result:=1 shl (Result+12) -end; - -function SELF_SEGMENT_INDEX(i:Int64):Integer; inline; -begin - Result:=(i shr SELF_PROPS_SEGMENT_INDEX_OFFSET) and SELF_PROPS_SEGMENT_INDEX_MASK; -end; - -function ELF64_R_SYM(i:QWORD):DWORD; inline; -begin - Result:=i shr 32; -end; - -function ELF64_R_TYPE(i:QWORD):DWORD; inline; -begin - Result:=i and $ffffffff; -end; - -function ELF64_ST_BIND(i:Byte):Byte; inline; -begin - Result:=i shr 4; -end; - -function ELF64_ST_TYPE(i:Byte):Byte; inline; -begin - Result:=i and $f; -end; - -function ELF64_ST_VISIBILITY(i:Byte):Byte; inline; -begin - Result:=i and 3; -end; - -function AlignUp(addr:PtrUInt;alignment:PtrUInt):PtrUInt; inline; -var - tmp:PtrUInt; -begin - if (alignment=0) then Exit(addr); - tmp:=addr+PtrUInt(alignment-1); - Result:=tmp-(tmp mod alignment) -end; - -function AlignUp(addr:Pointer;alignment:PtrUInt):Pointer; inline; -begin - Result:=Pointer(Align(PtrUInt(addr),alignment)); -end; - -function AlignDw(addr:PtrUInt;alignment:PtrUInt):PtrUInt; inline; -begin - Result:=addr-(addr mod alignment); -end; - -function AlignDw(addr:Pointer;alignment:PtrUInt):Pointer; inline; -begin - Result:=Pointer(AlignDw(PtrUInt(addr),alignment)); -end; - -function IsAlign(Addr:Pointer;Alignment:PtrUInt):Boolean; inline; -begin - Result:=(PtrUInt(addr) mod alignment)=0; -end; - -function IsAlign(Addr:PtrUInt;Alignment:PtrUInt):Boolean; inline; -begin - Result:=(addr mod alignment)=0; -end; - -end. - diff --git a/tools/readself/readself.lpi b/tools/readself/readself.lpi index bd0760ad..12c828e4 100644 --- a/tools/readself/readself.lpi +++ b/tools/readself/readself.lpi @@ -33,6 +33,10 @@ <Filename Value="elf_nid_utils.pas"/> <IsPartOfProject Value="True"/> </Unit> + <Unit> + <Filename Value="..\..\sys\elf64.pas"/> + <IsPartOfProject Value="True"/> + </Unit> </Units> </ProjectOptions> <CompilerOptions> diff --git a/tools/readself/readself.lpr b/tools/readself/readself.lpr index 107fee78..acc6e06c 100644 --- a/tools/readself/readself.lpr +++ b/tools/readself/readself.lpr @@ -2,7 +2,7 @@ program readself; uses sysutils, - elf64, + elf64 in '..\..\sys\elf64.pas', elf_nid_utils, ps4libdoc;