Editing PRX
Jump to navigation
Jump to search
The edit can be undone. Please check the comparison below to verify that this is what you want to do, and then publish the changes below to finish undoing the edit.
Latest revision | Your text | ||
Line 1: | Line 1: | ||
= Overview = | =Overview= | ||
'''S'''igned '''P'''PU '''R'''elocatable E'''x'''ecutable (SPRX) | |||
=Structure= | |||
First LOAD segment p_paddr points to module info. | |||
==Module Info== | |||
{| class="wikitable" | |||
! Offset | |||
! Type | |||
! Description | |||
|- | |||
| +0 | |||
| short | |||
| Module attributes | |||
|- | |||
| +2 | |||
| char[2] | |||
| Module version | |||
|- | |||
| +4 | |||
| char[28] | |||
| Module name | |||
|- | |||
| +32 | |||
| long | |||
| TOC address | |||
|- | |||
| +36 | |||
| long | |||
| Pointer to the start of exports section | |||
|- | |||
| +40 | |||
| long | |||
| Pointer to end of exports section | |||
|- | |||
| +44 | |||
| long | |||
| Points to the start of imports section | |||
|- | |||
| +48 | |||
| long | |||
| Points to the end of imports section | |||
|} | |||
= | ===Exports=== | ||
{| class="wikitable" | |||
! Offset | |||
! Type | |||
! Description | |||
|- | |||
| +0 | |||
| char[2] | |||
| Structure size (0x1C 32-bit or 0x28 64-bit), padding | |||
|- | |||
| +2 | |||
| short | |||
| Version | |||
|- | |||
| +4 | |||
| short | |||
| Attributes | |||
|- | |||
| +6 | |||
| short | |||
| Number of functions | |||
|- | |||
| +8 | |||
| short | |||
| Number of variables | |||
|- | |||
| +10 | |||
| short | |||
| Number of thread local storage variables | |||
|- | |||
| +12 | |||
| char | |||
| Hash info | |||
|- | |||
| +13 | |||
| char | |||
| Thread local storage hash info | |||
|- | |||
| +14 | |||
| char[2] | |||
| Reserved | |||
|- | |||
| +16 | |||
| long | |||
| Pointer to exported library name | |||
|- | |||
| +20 | |||
| long | |||
| Pointer to function NID table | |||
|- | |||
| +24 | |||
| long | |||
| Pointer to function stub table | |||
|} | |||
===Imports=== | |||
{| class="wikitable" | |||
! Offset | |||
! Type | |||
! Description | |||
|- | |||
| +0 | |||
| char | |||
| Structure size (0x2C) | |||
|- | |||
| +1 | |||
| char | |||
| Unused | |||
|- | |||
| +2 | |||
| short | |||
| Version | |||
|- | |||
| +4 | |||
| short | |||
| Attributes. AUTO_EXPORT=0x0001, WEAK_EXPORT=0x0002, NOLINK_EXPORT=0x0004, WEAK_IMPORT=0x0008, 0x2000 seems to indicate a non-PRX library (like "stdc" or "allocator") that comes from somewhere else (LV2?) | |||
|- | |||
| +6 | |||
| short | |||
| Number of functions | |||
|- | |||
| +8 | |||
| short | |||
| Number of variables | |||
|- | |||
| +10 | |||
| short | |||
| Number of thread local storage variables | |||
|- | |||
| +12 | |||
| byte[4] | |||
| reserved | |||
|- | |||
| +16 | |||
| long | |||
| Pointer to imported library name. | |||
|- | |||
| +20 | |||
| long | |||
| Pointer to the list of NID's for the exported functions. | |||
|- | |||
| +24 | |||
| long | |||
| Pointer to the list of exported functions. | |||
|- | |||
| +28 | |||
| long | |||
| var_nid_table | |||
|- | |||
| +32 | |||
| long | |||
| var_entry_table | |||
|- | |||
| +36 | |||
| long | |||
| tls_nid_table | |||
|- | |||
| +40 | |||
| long | |||
| tls_entry_table | |||
|} | |||
== | == Relocations == | ||
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 PRX's but it is currently unknown what it is used for. | |||
= | = FNID generation = | ||
== symbol name suffix == | |||
symbol_name_suffix: 6759659904250490566427499489741A | |||
To calculate FNID value of exported/imported symbol from .PRX you need to take SHA-1 hash over concatenation of symbol's name and symbol_name_suffix and then grab first 4 bytes from it and reverse these bytes (because of little-endian). | |||
Let's take, for example, ''_sys_sprintf'': | |||
''SHA1''('_sys_sprintf' + '\x67\x59\x65\x99\x04\x25\x04\x90\x56\x64\x27\x49\x94\x89\x74\x1A') = '''FEEAF9A1'''23D7D1A7619B40CD52500F9735A852A4 | |||
''FNID''('_sys_sprintf') = ''swap_uint32''('''0xFEEAF9A1''') = '''0xA1F9EAFE'''. | |||
= | |||
For C++ functions you should use mangled representation of symbol's name. | |||
For example, mangled name of ''std::runtime_error::what() const'' is ''_ZNKSt13runtime_error4whatEv'' and FNID('_ZNKSt13runtime_error4whatEv') = '''0x5333BDC9'''. | |||
More complex example: | |||
FNID(mangle('std::basic_filebuf<wchar_t, std::char_traits<wchar_t> >::seekpos(std::fpos<std:: | |||
_Mbstatet>, std::_Iosb<int>::_Openmode)')) = FNID('_ZNSt13basic_filebufIwSt11char_traitsIwEE7seekposESt4fposISt9_MbstatetENSt5_IosbIiE9_OpenmodeE') = '''0xB6A4D760''' | |||
noname_nid_suffix: 0xbc5eba9e042504905b64274994d9c41f | |||
For import stub's with no names, you must use SHA1 over concatenation of symbol's name and noname_nid_suffix as an ascii string. Some examples of noname imports are module_start, module_info, and module_stop. | |||
''SHA1''('module_info' + '0xbc5eba9e042504905b64274994d9c41f') = '''1630f4d7'''0bf3df419db9d481983411fd3130482a = '''0xD7F43016''' | |||
{{File Formats}} | {{File Formats}} | ||
<noinclude>[[Category:Main]]</noinclude> | <noinclude>[[Category:Main]]</noinclude> |