PRX: Difference between revisions
(The headers are not ignored, the addresses are just relative) |
Aerosoul94 (talk | contribs) (more info, second load segment is nothing special (maps to .data, .opd, .toc, etc). nothing new.) |
||
Line 3: | Line 3: | ||
=Structure= | =Structure= | ||
First LOAD segment p_paddr points to module info. | |||
==Module Info== | |||
{| class="wikitable" | {| class="wikitable" | ||
! Offset | ! Offset | ||
Line 124: | Line 118: | ||
| +4 | | +4 | ||
| short | | short | ||
| Attributes. | | 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 | | +6 | ||
| short | | short | ||
| | | Number of functions | ||
|- | |- | ||
| +8 | | +8 | ||
Line 148: | Line 142: | ||
| +20 | | +20 | ||
| long | | long | ||
| Pointer to | | Pointer to the list of NID's for the exported functions. | ||
|- | |- | ||
| +24 | | +24 | ||
| long | | long | ||
| Pointer to the | | Pointer to the list of exported functions. | ||
|- | |- | ||
| +28 | | +28 | ||
| long | | long | ||
| | | var_nid_table | ||
|- | |- | ||
| +32 | | +32 | ||
| long | | long | ||
| | | var_entry_table | ||
|- | |- | ||
| +36 | | +36 | ||
Line 171: | Line 165: | ||
|} | |} | ||
== | == 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 = | = FNID generation = | ||
Line 215: | Line 189: | ||
_Mbstatet>, std::_Iosb<int>::_Openmode)')) = FNID('_ZNSt13basic_filebufIwSt11char_traitsIwEE7seekposESt4fposISt9_MbstatetENSt5_IosbIiE9_OpenmodeE') = '''0xB6A4D760''' | _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> |
Revision as of 14:09, 23 February 2017
Overview
Signed PPU Relocatable Executable (SPRX)
Structure
First LOAD segment p_paddr points to module info.
Module Info
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
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
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') = FEEAF9A123D7D1A7619B40CD52500F9735A852A4 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') = 1630f4d70bf3df419db9d481983411fd3130482a = 0xD7F43016
|