PRX: Difference between revisions

From PS3 Developer wiki
Jump to navigation Jump to search
mNo edit summary
 
(39 intermediate revisions by 11 users not shown)
Line 1: Line 1:
scetool can decrypt SPRX's, producing an ELF... or is it? Not really. It has an ELF header but...
= Overview =


First LOAD section, paddr points to what I'll call the module descriptor.
'''P'''laystation '''R'''elocatable E'''x'''ecutable (PRX)


Second LOAD section starts off with a list of the entry points for all the exposed functions and then some (more on that later). The remainder is garbage/padding.
= PRX2 =


NOTE: All addresses inside the file assume the ELF header isn't there (basically add 0xE0 to all addresses.)
PRX2 is only present on PSVita. PSP and PS3 use PRX version 1.
{| class="wikitable"
! Offset
! Type
! Description
|-
| +0
| long
| flags? Always 0x101
|-
| +4
| char[always 16?]
| Name of the module as a null-terminated string.
|-
| +20
| long
| ????? Perhaps a unique module ID?
|-
| +24
| long
| Points to start of symbol table header
|-
| +28
| long
| Points to end of symbol table header
|-
| +32
| long
| Points to start of first symbol defn
|-
| +36
| long
| points to end of last symbol defn
|}


Symbol table header:
== Recognition ==
{| class="wikitable"
! Offset
! Type
! Description
|-
| +0
| long[4]
| ?????
|-
| +16
| quad or maybe a long preceded by zeroes?
| Appears to point to a table of something crypto-looking... clearly in four-byte segments. The whole library gets six, and then each function gets ????? it varies. This pointer points to the first three.
|-
| +24
| long
| ...and this points to the second three.
|}


Symbol defn:
A PRX module is PRX2 format only if ehdr.e_type is ET_SCE_EXEC or ET_SCE_RELEXEC.
{| class="wikitable"
! Offset
! Type
! Description
|-
| +0
| quad
| Always zeroes
|-
| +8
| long
| Always(?) 0x2C000001
|-
| +12
| long
| ????? Probably flags...
|-
| +16
| long
| ????? Usually 0, but "paf" gets 0x60000 instead.
|-
| +20
| (quad or maybe a long preceded by zeroes?)
| Pointer to the name of the function! As a null/terminated ASCII string.
|-
| +28
| long
| Pointer to this function's section of the Big Mystery Table. The values are always big and always in ascending order... very odd.
|-
| +32
| long
| Pointer to the (long) pointer (in the second LOAD section) to the entry point of this function!
|-
| +36
| long[2]
| Appears to be for overflow for the Big Mystery Table. Zeroes if not needed.
|}


A Program Segment is PRX2 format only if p_type is PT_SCE_RELA or PT_SCE_COMMENT.


Two functions are ALWAYS present: "paf" and "SysPrxForUser". What do they do? Not sure. They are real functions with legitimate entry points, so they can't be some kind of metadata. Hm.
= Module Info =
 
PS3 and PSP PRX embed Module Info version 0.
 
== Location ==
 
For PS3 (?and PSP?), it is located in text segment (first LOAD segment) at offset Elf32_Phdrs[text_seg_id].p_paddr - Elf32_Phdrs[text_seg_id].p_offset. Or more simply: at offset Elf32_Phdrs[text_seg_id].p_paddr in the ELF file.
 
== Structure ==
 
<source lang="C">
#define MODULE_NAME_MAX_LEN 27
 
typedef struct sceModuleInfo_common { // size is 0x20
  unsigned short modattr;
  unsigned char modver[2];
  char modname[MODULE_NAME_MAX_LEN];
  unsigned char infover;
} sceModuleInfo_common;
 
typedef struct sceModuleInfo_v0 { // size is 0x34
  sceModuleInfo_common c;
  Elf32_Addr gp_value;
  Elf32_Addr libent_top;
  Elf32_Addr libent_btm;
  Elf32_Addr libstub_top;
  Elf32_Addr libstub_btm;
} sceModuleInfo_v0;
</source>
 
= Exports =
 
PS3 uses exports structure of size 0x1C ?or 0x28 in 64bits?.
 
<source lang="C">
typedef struct _scelibent_common { // size is 0x10
unsigned char size;
unsigned char auxattribute;
unsigned short version;
unsigned short attribute;
unsigned short nfunc;
unsigned short nvar;
unsigned short ntls;
unsigned char hashinfo;
unsigned char hashinfotls;
unsigned char reserved;
unsigned char nidaltsets;
} sceKernelLibraryEntryTable_common;
 
typedef struct _scelibent_1C { // size is 0x1C
sceKernelLibraryEntryTable_common c;
Elf32_Addr libname;
Elf32_Addr nid_table;
Elf32_Addr entry_table;
} sceKernelLibraryEntryTable_1C;
</source>
 
= Imports =
 
PS3 use imports structures of size 0x2C.
 
<source lang="C">
typedef struct _scelibstub_common { // size is 0xC
unsigned short size;
unsigned short version;
unsigned short attribute;
unsigned short nfunc;
unsigned short nvar;
unsigned short ntls;
} sceKernelLibraryStubTable_common;
 
typedef struct _scelibstub_2C { // size is 0x2C
sceKernelLibraryStubTable_common c;
unsigned char reserved[4];
Elf32_Addr libname;
Elf32_Addr func_nid_table;
Elf32_Addr func_entry_table;
Elf32_Addr var_nid_table;
Elf32_Addr var_entry_table;
Elf32_Addr tls_nid_table;
Elf32_Addr tls_entry_table;
} sceKernelLibraryStubTable_2C;
</source>
 
= Relocations =
 
== PS3 ==
 
Relocations can be found in either PT_SCE_PPURELA segments or SHT_SCE_PPURELA / SHT_RELA sections. RELA relocations are standard relocations while PPURELA relocations have 2 segment (program header) indexes stored in r_sym of r_info.
*The first index can be extracted with 0x7FFFFF00 as a mask and is used as a base address for r_addend. This sum will be the value applied to the patch.
*The second index can be extracted with 0x000000FF as a mask and is used as a base address for the target segment to patch and is added to r_offset.
*The first bit (0x80000000) is also set on earlier PRXs but it is currently unknown what it is used for.
 
 
 
{{File Formats}}
<noinclude>[[Category:Main]]</noinclude>

Latest revision as of 23:05, 19 January 2020

Overview[edit | edit source]

Playstation Relocatable Executable (PRX)

PRX2[edit | edit source]

PRX2 is only present on PSVita. PSP and PS3 use PRX version 1.

Recognition[edit | edit source]

A PRX module is PRX2 format only if ehdr.e_type is ET_SCE_EXEC or ET_SCE_RELEXEC.

A Program Segment is PRX2 format only if p_type is PT_SCE_RELA or PT_SCE_COMMENT.

Module Info[edit | edit source]

PS3 and PSP PRX embed Module Info version 0.

Location[edit | edit source]

For PS3 (?and PSP?), it is located in text segment (first LOAD segment) at offset Elf32_Phdrs[text_seg_id].p_paddr - Elf32_Phdrs[text_seg_id].p_offset. Or more simply: at offset Elf32_Phdrs[text_seg_id].p_paddr in the ELF file.

Structure[edit | edit source]

#define MODULE_NAME_MAX_LEN 27

typedef struct sceModuleInfo_common { // size is 0x20
  unsigned short modattr;
  unsigned char modver[2];
  char modname[MODULE_NAME_MAX_LEN];
  unsigned char infover;
} sceModuleInfo_common;

typedef struct sceModuleInfo_v0 { // size is 0x34
  sceModuleInfo_common c;
  Elf32_Addr gp_value;
  Elf32_Addr libent_top;
  Elf32_Addr libent_btm;
  Elf32_Addr libstub_top;
  Elf32_Addr libstub_btm;
} sceModuleInfo_v0;

Exports[edit | edit source]

PS3 uses exports structure of size 0x1C ?or 0x28 in 64bits?.

typedef struct _scelibent_common { // size is 0x10
	unsigned char size;
	unsigned char auxattribute;
	unsigned short version;
	unsigned short attribute;
	unsigned short nfunc;
	unsigned short nvar;
	unsigned short ntls;
	unsigned char hashinfo;
	unsigned char hashinfotls;
	unsigned char reserved;
	unsigned char nidaltsets;
} sceKernelLibraryEntryTable_common;

typedef struct _scelibent_1C { // size is 0x1C
	sceKernelLibraryEntryTable_common c;
	Elf32_Addr libname;
	Elf32_Addr nid_table;
	Elf32_Addr entry_table;
} sceKernelLibraryEntryTable_1C;

Imports[edit | edit source]

PS3 use imports structures of size 0x2C.

typedef struct _scelibstub_common { // size is 0xC
	unsigned short size;
	unsigned short version;
	unsigned short attribute;
	unsigned short nfunc;
	unsigned short nvar;
	unsigned short ntls;
} sceKernelLibraryStubTable_common;

typedef struct _scelibstub_2C { // size is 0x2C
	sceKernelLibraryStubTable_common c;
	unsigned char reserved[4];
	Elf32_Addr libname;
	Elf32_Addr func_nid_table;
	Elf32_Addr func_entry_table;
	Elf32_Addr var_nid_table;
	Elf32_Addr var_entry_table;
	Elf32_Addr tls_nid_table;
	Elf32_Addr tls_entry_table;
} sceKernelLibraryStubTable_2C;

Relocations[edit | edit source]

PS3[edit | edit source]

Relocations can be found in either PT_SCE_PPURELA segments or SHT_SCE_PPURELA / SHT_RELA sections. RELA relocations are standard relocations while PPURELA relocations have 2 segment (program header) indexes stored in r_sym of r_info.

  • The first index can be extracted with 0x7FFFFF00 as a mask and is used as a base address for r_addend. This sum will be the value applied to the patch.
  • The second index can be extracted with 0x000000FF as a mask and is used as a base address for the target segment to patch and is added to r_offset.
  • The first bit (0x80000000) is also set on earlier PRXs but it is currently unknown what it is used for.