diff --git a/.gitignore b/.gitignore
index 296797ca..a08ef334 100644
--- a/.gitignore
+++ b/.gitignore
@@ -11,6 +11,9 @@
*.bat
*.prx
*.sprx
+*.bin
+*.elf
+*.self
*.dump
*.h
link.res
diff --git a/tools/readself/elf64.pas b/tools/readself/elf64.pas
new file mode 100644
index 00000000..e113b49b
--- /dev/null
+++ b/tools/readself/elf64.pas
@@ -0,0 +1,718 @@
+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;
+
+ // Dynamic Section Types
+ 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 =$1;
+ DF_SYMBOLIC =$2;
+ DF_TEXTREL =$4;
+ DF_BIND_NOW =$8;
+ DF_STATIC_TLS=$10;
+
+ 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_minor:Byte;
+ version_major:Byte;
+ id:Word);
+ end;
+
+ TLibraryValue=packed record
+ case Byte of
+ 0:(value:Int64);
+ 1:(name_offset:DWORD;
+ version_minor:Byte;
+ version_major:Byte;
+ 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 :PQWORD;
+ sceKernelExtendedGpuPageTable:PQWORD;
+ sceKernelExtendedMemory2 :PQWORD;
+ sceKernelExtendedCpuPageTable:PQWORD;
+ end;
+
+ PSceKernelFsParam=^TSceKernelFsParam;
+ TSceKernelFsParam=packed record
+ Size:QWORD;
+ sceKernelFsDupDent:PQWORD;
+ 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;
+ 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
new file mode 100644
index 00000000..799f3465
--- /dev/null
+++ b/tools/readself/readself.lpi
@@ -0,0 +1,63 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ -
+
+
+ -
+
+
+ -
+
+
+
+
+
diff --git a/tools/readself/readself.lpr b/tools/readself/readself.lpr
new file mode 100644
index 00000000..ca47573d
--- /dev/null
+++ b/tools/readself/readself.lpr
@@ -0,0 +1,746 @@
+program readself;
+
+uses
+ sysutils,
+ elf64;
+
+type
+ p_elf_obj=^elf_obj;
+ elf_obj=packed record
+ is_encrypted:Integer;
+ self:record
+ hdr :p_self_header;
+ segs :p_self_segment;
+ elf_hdr :p_elf64_hdr;
+ MinSeg :Int64;
+ MaxSeg :Int64;
+ end;
+ elf:record
+ hdr :p_elf64_hdr;
+ size:Int64;
+ end;
+ size:Int64;
+ 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 (aSizeOf(DWORD)) then
+ begin
+ FileClose(F);
+ Exit(-3);
+ end;
+
+ case Magic of
+ ELFMAG: //elf64
+ begin
+ obj^.size:=FileSeek(F,0,fsFromEnd);
+
+ if (obj^.size<=0) then
+ begin
+ FileClose(F);
+ Exit(-4);
+ end;
+
+ obj^.elf.hdr :=GetMem(obj^.size);
+ obj^.elf.size:=obj^.size;
+
+ FileSeek(F,0,fsFromBeginning);
+ n:=FileRead(F,obj^.elf.hdr^,obj^.size);
+ FileClose(F);
+
+ if (n<>obj^.size) then
+ begin
+ FreeMem(obj^.elf.hdr);
+ obj^.elf.hdr:=nil;
+ Exit(-5);
+ end;
+ end;
+ SELF_MAGIC:
+ begin
+ obj^.size:=FileSeek(F,0,fsFromEnd);
+
+ if (obj^.size<=0) then
+ begin
+ FileClose(F);
+ Exit(-4);
+ end;
+
+ self_hdr:=GetMem(obj^.size);
+ obj^.self.hdr:=self_hdr;
+
+ FileSeek(F,0,fsFromBeginning);
+ n:=FileRead(F,self_hdr^,obj^.size);
+ FileClose(F);
+
+ if (n<>obj^.size) then
+ begin
+ FreeMem(obj^.self.hdr);
+ obj^.self.hdr:=nil;
+ Exit(-5);
+ end;
+
+ count:=self_hdr^.Num_Segments;
+
+ self_segs:=Pointer(self_hdr+1);
+ obj^.self.segs:=self_segs;
+
+ is_encrypted:=0;
+ if (count<>0) then
+ For i:=0 to count-1 do
+ if ((self_segs[i].flags and (SELF_PROPS_ENCRYPTED or SELF_PROPS_COMPRESSED))<>0) then
+ begin
+ is_encrypted:=1;
+ Break;
+ end;
+
+ obj^.is_encrypted:=is_encrypted;
+
+ elf_hdr:=Pointer(self_segs)+(count*SizeOf(t_self_segment));
+ obj^.self.elf_hdr:=elf_hdr;
+
+ elf_phdr:=get_elf_phdr(elf_hdr);
+
+ MinSeg:=High(Int64);
+ MaxSeg:=0;
+
+ count:=elf_hdr^.e_phnum;
+
+ if (count<>0) then
+ For i:=0 to count-1 do
+ begin
+ s:=elf_phdr[i].p_offset;
+ if (s<>0) then
+ begin
+ MinSeg:=MinInt64(s,MinSeg);
+ end;
+ s:=s+elf_phdr[i].p_filesz;
+ MaxSeg:=MaxInt64(s,MaxSeg);
+ end;
+
+ n:=ptruint(elf_hdr)-ptruint(self_hdr); //offset to hdr
+ s:=MaxInt64(obj^.size,n)-n; //get size
+
+ MinSeg:=MinInt64(MinSeg,s);
+ MaxSeg:=MinInt64(MaxSeg,s);
+
+ obj^.self.MinSeg:=MinSeg;
+ obj^.self.MaxSeg:=MaxSeg;
+
+ if (is_encrypted=0) then //load elf
+ begin
+ obj^.elf.hdr :=AllocMem(MaxSeg);
+ obj^.elf.size:=MaxSeg;
+
+ //elf_hdr part
+ n:=ptruint(elf_hdr)-ptruint(self_hdr); //offset to hdr
+ s:=self_hdr^.Header_Size+self_hdr^.Meta_size; //offset to end
+ s:=MinInt64(obj^.size,s); //min size
+ s:=MaxInt64(s,n)-n; //get size
+
+ //first page
+ Move(elf_hdr^,obj^.elf.hdr^,s);
+
+ count:=self_hdr^.Num_Segments;
+
+ if (count<>0) then
+ For i:=0 to count-1 do
+ if ((self_segs[i].flags and SELF_PROPS_BLOCKED)<>0) then
+ begin
+ s:=SELF_SEGMENT_INDEX(self_segs[i].flags);
+
+ mem_size:=minInt64(self_segs[i].filesz,self_segs[i].memsz);
+
+ src_ofs_s:=self_segs[i].offset; //start offset
+ dst_ofs_s:=elf_phdr[s].p_offset; //start offset
+
+ src_ofs_e:=src_ofs_s+mem_size; //end offset
+ dst_ofs_e:=dst_ofs_s+mem_size; //end offset
+
+ src_ofs_s:=MinInt64(src_ofs_s,obj^.size); //bound self
+ src_ofs_e:=MinInt64(src_ofs_s,obj^.size); //bound self
+
+ dst_ofs_s:=MinInt64(dst_ofs_s,obj^.elf.size); //bound elf
+ dst_ofs_e:=MinInt64(dst_ofs_s,obj^.elf.size); //bound elf
+
+ mem_size:=minInt64(src_ofs_e-src_ofs_s,dst_ofs_e-dst_ofs_s); //min of two size
+
+ Move( (Pointer(self_hdr) +src_ofs_s)^, //src
+ (Pointer(obj^.elf.hdr)+dst_ofs_s)^, //dst
+ mem_size); //size
+ end;
+ end;
+
+ end;
+ else
+ begin
+ FileClose(F);
+ Exit(-1);
+ end;
+ end;
+
+end;
+
+procedure print_file_size(obj:p_elf_obj);
+begin
+ Writeln('FILE Size:',obj^.size);
+ Writeln();
+end;
+
+procedure print_self_header(obj:p_elf_obj);
+var
+ s,e:ptruint;
+begin
+ if (obj^.self.hdr<>nil) then
+ begin
+ s:=0;
+ e:=obj^.self.hdr^.Header_Size+obj^.self.hdr^.Meta_size;
+
+ Writeln('SELF Header:0x',HexStr(s,8),'..0x',HexStr(e,8),':',e);
+
+ Writeln(' Magic :0x',HexStr(obj^.self.hdr^.Magic,8));
+ Writeln(' Version :',obj^.self.hdr^.Version );
+ Writeln(' Mode :',obj^.self.hdr^.Mode );
+ Writeln(' Endian :',obj^.self.hdr^.Endian );
+ Writeln(' Attr :',obj^.self.hdr^.Attr );
+ Writeln(' Content_Type:',obj^.self.hdr^.Content_Type);
+ Writeln(' Program_Type:0x',HexStr(obj^.self.hdr^.Program_Type,2));
+ Writeln(' Header_Size :',obj^.self.hdr^.Header_Size );
+ Writeln(' Meta_size :',obj^.self.hdr^.Meta_size );
+ Writeln(' File_size :',obj^.self.hdr^.File_size );
+ Writeln(' Num_Segments:',obj^.self.hdr^.Num_Segments);
+ Writeln(' Flags :0x',HexStr(obj^.self.hdr^.Flags,4));
+ Writeln(' MinSeg :0x',HexStr(obj^.self.MinSeg,8));
+ Writeln(' MaxSeg :0x',HexStr(obj^.self.MaxSeg,8));
+ end else
+ begin
+ Writeln('SELF Header:','not exist');
+ end;
+ Writeln();
+end;
+
+procedure print_bytes(p:PByte;size:Integer);
+begin
+ while (size<>0) do
+ begin
+ Write(HexStr(P^,2));
+ Inc(P);
+ Dec(size);
+ end;
+end;
+
+function get_program_type_str(pt:Byte):RawByteString;
+begin
+ Result:='';
+ Case pt of
+ SELF_PT_FAKE :Result:='(FAKE)';
+ SELF_PT_NPDRM_EXEC :Result:='(NPDRM_EXEC)';
+ SELF_PT_NPDRM_DYNLIB :Result:='(NPDRM_DYNLIB)';
+ SELF_PT_SYSTEM_EXEC :Result:='(SYSTEM_EXEC)';
+ SELF_PT_SYSTEM_DYNLIB:Result:='(SYSTEM_DYNLIB)';
+ SELF_PT_HOST_KERNEL :Result:='(HOST_KERNEL)';
+ SELF_PT_SECURE_MODULE:Result:='(SECURE_MODULE)';
+ SELF_PT_SECURE_KERNEL:Result:='(SECURE_KERNEL)';
+ else;
+ end;
+end;
+
+procedure print_self_authinfo(obj:p_elf_obj);
+label
+ _not_exist;
+var
+ s,e,len:ptruint;
+ elf_hdr:p_elf64_hdr;
+ authinfo:p_self_authinfo;
+begin
+ if (obj^.self.hdr<>nil) then
+ begin
+ elf_hdr:=obj^.self.elf_hdr;
+ s:=SizeOf(t_self_header);
+ s:=s+(obj^.self.hdr^.Num_Segments*SizeOf(t_self_segment));
+ s:=s+get_elf_phdr_offset(elf_hdr);
+ s:=s+(elf_hdr^.e_phnum*SizeOf(elf64_phdr));
+ s:=AlignUp(s,SELF_SEGMENT_BLOCK_ALIGNMENT);
+
+ e:=obj^.self.hdr^.Header_Size;
+
+ if (s>=e) then goto _not_exist;
+
+ len:=(e-s);
+
+ if (lennil) then
+ begin
+ s:=obj^.self.hdr^.Header_Size;
+ e:=s+obj^.self.hdr^.Meta_size;
+
+ if (s>=e) then goto _not_exist;
+
+ Writeln('SELF Metadata:0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
+
+ m:=Pointer(Pointer(obj^.self.hdr)+s);
+
+ Writeln(' Offset(h)|00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F');
+ Write (' ---------+-----------------------------------------------');
+
+ for s:=s to e-1 do
+ begin
+ if ((s mod 16)=0) then
+ begin
+ Writeln();
+ Write(' 0x',HexStr(s-(s mod 16),7),'|');
+ end;
+ Write(HexStr(m^,2),' ');
+ Inc(m);
+ end;
+
+ Writeln;
+ end else
+ begin
+ _not_exist:
+ Writeln('SELF Metadata:','not exist');
+ end;
+ Writeln;
+end;
+
+function get_seg_flags_str(flags:QWORD):RawByteString;
+begin
+ Result:='_______';
+
+ if ((flags and SELF_PROPS_ORDERED )<>0) then Result[1]:='O';
+ if ((flags and SELF_PROPS_ENCRYPTED )<>0) then Result[2]:='E';
+ if ((flags and SELF_PROPS_SIGNED )<>0) then Result[3]:='S';
+ if ((flags and SELF_PROPS_COMPRESSED )<>0) then Result[4]:='C';
+ if ((flags and SELF_PROPS_BLOCKED )<>0) then Result[5]:='B';
+ if ((flags and SELF_PROPS_HAS_DIGESTS)<>0) then Result[6]:='D';
+ if ((flags and SELF_PROPS_HAS_EXTENTS)<>0) then Result[7]:='E';
+end;
+
+procedure print_self_segs(obj:p_elf_obj);
+label
+ _not_exist;
+var
+ i,count:Integer;
+ seg:p_self_segment;
+ s,e:ptruint;
+begin
+ if (obj^.self.segs<>nil) then
+ begin
+ count:=obj^.self.hdr^.Num_Segments;
+
+ if (count=0) then goto _not_exist;
+
+ s:=ptruint(obj^.self.segs)-ptruint(obj^.self.hdr);
+ e:=s+(count*SizeOf(t_self_segment));
+
+ Writeln('SELF Segments Headers:0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
+
+ seg:=obj^.self.segs;
+
+ Writeln(' Num Flags W BlockSize SEGID Offset Filesz Memsz');
+
+ For i:=0 to count-1 do
+ begin
+ Write(' ',i:3,' ');
+ Write(get_seg_flags_str(seg^.flags) ,' ');
+ Write(SELF_WINDOW(seg^.flags) ,' ');
+ Write('0x',HexStr(SELF_BLOCK_SIZE(seg^.flags),8),' ');
+ Write(SELF_SEGMENT_INDEX(seg^.flags):5,' ');
+
+ Write('0x',HexStr(seg^.offset,8),' ');
+ Write('0x',HexStr(seg^.filesz,8),' ');
+ Write('0x',HexStr(seg^.memsz ,8),' ');
+
+ Writeln();
+ Inc(seg);
+ end;
+ end else
+ begin
+ _not_exist:
+ Writeln('SELF Segments Headers:','not exist');
+ end;
+ Writeln();
+end;
+
+function get_elf_hdr_offset(obj:p_elf_obj):Int64;
+begin
+ if (obj^.self.hdr<>nil) then
+ begin
+ Result:=obj^.self.hdr^.Num_Segments*SizeOf(t_self_segment);
+ end else
+ begin
+ Result:=0;
+ end;
+end;
+
+function get_e_class_str(e_class:Byte):RawByteString;
+begin
+ Result:='';
+ Case e_class of
+ 0:Result:='(SNONE)';
+ 1:Result:='(S32)';
+ 2:Result:='(S64)';
+ else;
+ end;
+end;
+
+function get_e_data_str(e_data:Byte):RawByteString;
+begin
+ Result:='';
+ Case e_data of
+ 0:Result:='(NONE)';
+ 1:Result:='(2LSB)';
+ 2:Result:='(2MSB)';
+ else;
+ end;
+end;
+
+function get_e_type_str(e_type:Word):RawByteString;
+begin
+ Result:='';
+ Case e_type of
+ ET_NONE :Result:='(NONE)';
+ ET_REL :Result:='(REL)';
+ ET_EXEC :Result:='(EXEC)';
+ ET_DYN :Result:='(DYN)';
+ ET_CORE :Result:='(CORE)';
+ ET_SCE_EXEC :Result:='(SCE_EXEC)';
+ ET_SCE_REPLAY_EXEC:Result:='(SCE_REPLAY_EXEC)';
+ ET_SCE_RELEXEC :Result:='(SCE_RELEXEC)';
+ ET_SCE_STUBLIB :Result:='(SCE_STUBLIB)';
+ ET_SCE_DYNEXEC :Result:='(SCE_DYNEXEC)';
+ ET_SCE_DYNAMIC :Result:='(SCE_DYNAMIC)';
+ else;
+ end;
+end;
+
+function get_e_machine_str(e_machine:Word):RawByteString;
+begin
+ Result:='';
+ Case e_machine of
+ EM_NONE :Result:='(NONE)';
+ EM_X86_64:Result:='(X86_64)';
+ else;
+ end;
+end;
+
+function get_osabi_name(e_machine:Word):RawByteString;
+begin
+ Result:='';
+ Case e_machine of
+ 0:Result:='(NONE)';
+ 3:Result:='(LINUX)';
+ 9:Result:='(FREEBSD)';
+ else;
+ end;
+end;
+
+procedure print_elf_header(obj:p_elf_obj);
+var
+ s,e:ptruint;
+ elf_hdr:p_elf64_hdr;
+begin
+ if (obj^.is_encrypted<>0) then
+ begin
+ Writeln('ELF Header:','is_encrypted');
+ Exit;
+ end;
+
+ if (obj^.elf.hdr<>nil) then
+ begin
+ elf_hdr:=obj^.elf.hdr;
+ s:=get_elf_hdr_offset(obj);
+ e:=s+SizeOf(elf64_hdr);
+
+ Writeln('ELF Header:0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
+
+ Writeln(' Magic :0x',HexStr(PDWORD(@elf_hdr^.e_ident)^,8));
+ Writeln(' Class: :',elf_hdr^.e_ident[EI_CLASS],' ',get_e_class_str(elf_hdr^.e_ident[EI_CLASS]));
+ Writeln(' Data: :',elf_hdr^.e_ident[EI_DATA],' ',get_e_data_str(elf_hdr^.e_ident[EI_DATA]));
+ Writeln(' Version: :',elf_hdr^.e_ident[EI_VERSION]);
+ Writeln(' OS/ABI: :',elf_hdr^.e_ident[EI_OSABI],' ',get_osabi_name(elf_hdr^.e_ident[EI_OSABI]));
+ Writeln(' ABI Version:',elf_hdr^.e_ident[EI_ABIVERSION]);
+
+ Writeln(' e_type :0x',HexStr(elf_hdr^.e_type,4),' ',get_e_type_str(elf_hdr^.e_type));
+ Writeln(' e_machine :',elf_hdr^.e_machine,' ',get_e_machine_str(elf_hdr^.e_machine));
+ Writeln(' e_version :',elf_hdr^.e_version );
+ Writeln(' e_entry :0x',HexStr(elf_hdr^.e_entry,8));
+ Writeln(' e_phoff :0x',HexStr(elf_hdr^.e_phoff,8));
+ Writeln(' e_shoff :0x',HexStr(elf_hdr^.e_shoff,8));
+ Writeln(' e_flags :0x',HexStr(elf_hdr^.e_flags,8));
+ Writeln(' e_ehsize :',elf_hdr^.e_ehsize );
+ Writeln(' e_phentsize:',elf_hdr^.e_phentsize);
+ Writeln(' e_phnum :',elf_hdr^.e_phnum );
+ Writeln(' e_shentsize:',elf_hdr^.e_shentsize);
+ Writeln(' e_shnum :',elf_hdr^.e_shnum );
+ Writeln(' e_shstrndx :',elf_hdr^.e_shstrndx );
+
+ end else
+ begin
+ Writeln('ELF Header:','not exist');
+ end;
+ Writeln();
+end;
+
+function get_pt_name(p_type:DWORD):RawByteString;
+begin
+ Result:='';
+ Case p_type of
+ PT_NULL :Result:='NULL';
+ PT_LOAD :Result:='LOAD';
+ PT_DYNAMIC :Result:='DYNAMIC';
+ PT_INTERP :Result:='INTERP';
+ PT_NOTE :Result:='NOTE';
+ PT_SHLIB :Result:='SHLIB';
+ PT_PHDR :Result:='PHDR';
+ PT_TLS :Result:='TLS';
+ PT_SCE_RELA :Result:='SCE_RELA';
+ PT_SCE_DYNLIBDATA :Result:='SCE_DYNLIBDATA';
+ PT_SCE_PROCPARAM :Result:='SCE_PROCPARAM';
+ PT_SCE_MODULE_PARAM:Result:='SCE_MODULE_PARAM';
+ PT_SCE_RELRO :Result:='SCE_RELRO';
+ PT_GNU_EH_FRAME :Result:='GNU_EH_FRAME';
+ PT_GNU_STACK :Result:='GNU_STACK';
+ PT_SCE_COMMENT :Result:='SCE_COMMENT';
+ PT_SCE_VERSION :Result:='SCE_VERSION';
+ PT_SCE_SEGSYM :Result:='SCE_SEGSYM';
+ else Result:='0x'+HexStr(p_type,8);
+ end;
+end;
+
+function get_p_flags_str(flags:DWORD):RawByteString;
+begin
+ Result:='___';
+
+ if ((flags and PF_X)<>0) then Result[1]:='X';
+ if ((flags and PF_W)<>0) then Result[2]:='W';
+ if ((flags and PF_R)<>0) then Result[3]:='R';
+end;
+
+procedure print_elf_phdr(obj:p_elf_obj);
+var
+ s,e:ptruint;
+ elf_hdr :p_elf64_hdr;
+ elf_phdr:p_elf64_phdr;
+ i,count:Integer;
+ str:RawByteString;
+begin
+ if (obj^.is_encrypted<>0) then
+ begin
+ Writeln('ELF Header:','is_encrypted');
+ Exit;
+ end;
+
+ if (obj^.elf.hdr<>nil) then
+ begin
+ elf_hdr :=obj^.elf.hdr;
+ elf_phdr:=get_elf_phdr(elf_hdr);
+ count:=elf_hdr^.e_phnum;
+
+ s:=get_elf_hdr_offset(obj);
+ s:=s+get_elf_phdr_offset(elf_hdr);
+ e:=s+count*SizeOf(elf64_phdr);
+
+ Writeln('Program Headers:0x',HexStr(s,8),'..0x',HexStr(e,8),':',(e-s));
+
+ Writeln(' Type Flags Offset VirtAddr PhysAddr FileSize MemSize Align');
+ if (count<>0) then
+ For i:=0 to count-1 do
+ begin
+
+ str:=get_pt_name(elf_phdr^.p_type);
+ str:=str+space(16-Length(str));
+
+ Write(' ',str,' ');
+
+ Write(get_p_flags_str(elf_phdr^.p_flags),' ');
+
+ Write('0x'+HexStr(elf_phdr^.p_offset,8),' ');
+ Write('0x'+HexStr(elf_phdr^.p_vaddr ,8),' ');
+ Write('0x'+HexStr(elf_phdr^.p_paddr ,8),' ');
+ Write('0x'+HexStr(elf_phdr^.p_filesz,8),' ');
+ Write('0x'+HexStr(elf_phdr^.p_memsz ,8),' ');
+ Write('0x'+HexStr(elf_phdr^.p_align ,8),' ');
+
+ Writeln;
+
+ Inc(elf_phdr);
+ end;
+
+ end else
+ begin
+ Writeln('Program Headers:','not exist');
+ end;
+ Writeln();
+end;
+
+type
+ t_print_param=(
+ pp_file_size,
+ pp_self_header,
+ pp_self_segs,
+ pp_self_authinfo,
+ pp_self_metadata,
+ pp_file_header,
+ pp_program_headers
+ );
+ t_print_param_set=Set of t_print_param;
+
+var
+ print_param:t_print_param_set=[];
+ FileName:RawByteString;
+
+procedure parse_param;
+var
+ i:Integer;
+ S:RawByteString;
+begin
+ print_param:=[];
+ For i:=1 to ParamCount do
+ begin
+ S:=Trim(ParamStr(i));
+ case S of
+ '-a','-all' :print_param:=[pp_file_size,
+ pp_self_header,
+ pp_self_segs,
+ pp_self_authinfo,
+ pp_self_metadata,
+ pp_file_header,
+ pp_program_headers];
+
+ '-F','--file_size' :print_param:=print_param+[pp_file_size ];
+ '-H','--self_header' :print_param:=print_param+[pp_self_header ];
+ '-S','--self_segs' :print_param:=print_param+[pp_self_segs ];
+ '-A','--self_authinfo' :print_param:=print_param+[pp_self_authinfo ];
+ '-M','--self_metadata' :print_param:=print_param+[pp_self_metadata ];
+ '-h','--file-header' :print_param:=print_param+[pp_file_header ];
+ '-l','--program-headers':print_param:=print_param+[pp_program_headers];
+ else
+ FileName:=S;
+ end;
+ end;
+end;
+
+var
+ r:Integer;
+ obj:elf_obj;
+
+begin
+ parse_param;
+
+ r:=load_self(FileName,@obj);
+
+ if (r=0) then
+ begin
+ if (pp_file_size in print_param) then print_file_size (@obj);
+ if (pp_self_header in print_param) then print_self_header (@obj);
+ if (pp_self_segs in print_param) then print_self_segs (@obj);
+ if (pp_self_authinfo in print_param) then print_self_authinfo(@obj);
+ if (pp_self_metadata in print_param) then print_self_metadata(@obj);
+ if (pp_file_header in print_param) then print_elf_header (@obj);
+ if (pp_program_headers in print_param) then print_elf_phdr (@obj);
+ end else
+ begin
+ Writeln('Error(',r,') load file:',FileName);
+ end;
+
+ free_elf_obj(@obj);
+
+ readln;
+end.
+