CRO0: Difference between revisions
mNo edit summary |
Trie entries + unknown fields |
||
| Line 48: | Line 48: | ||
| 0x98 | | 0x98 | ||
| 0x04 | | 0x04 | ||
| | | Fixed size, set by RO after fixing, used to keep track of the new size | ||
|- | |- | ||
| 0x9C | | 0x9C | ||
| Line 56: | Line 56: | ||
| 0xA0 | | 0xA0 | ||
| 0x04 | | 0x04 | ||
| [[#Segment offset | | [[#Segment offset|Segment offset]] that is always the same as export symbol "nnroControlObject_". 0xFFFFFFFF in CRS | ||
|- | |- | ||
| 0xA4 | | 0xA4 | ||
| 0x04 | | 0x04 | ||
| [[#Segment offset | | [[#Segment offset|Segment offset]] for "OnLoad" function, which will be called when the module is initialized. Set to 0xFFFFFFFF if not exists. | ||
|- | |- | ||
| 0xA8 | | 0xA8 | ||
| 0x04 | | 0x04 | ||
| [[#Segment offset | | [[#Segment offset|Segment offset]] for "OnExit" function, which will be called when the module is finalized. Set to 0xFFFFFFFF if not exists. | ||
|- | |- | ||
| 0xAC | | 0xAC | ||
| 0x04 | | 0x04 | ||
| [[#Segment offset | | [[#Segment offset|Segment offset]] for "OnUnresolved" function, which will be called when an unresolved function is called. Set to 0xFFFFFFFF if not exists. | ||
|- | |- | ||
| 0xB0 | | 0xB0 | ||
| Line 100: | Line 100: | ||
| 0xCC | | 0xCC | ||
| 0x04 | | 0x04 | ||
| Segment Table num (size = num*12) | | Segment Table num (size = num * 12) | ||
|- | |- | ||
| 0xD0 | | 0xD0 | ||
| Line 128: | Line 128: | ||
| 0xE8 | | 0xE8 | ||
| 0x04 | | 0x04 | ||
| Export | | Export Trie offset | ||
|- | |- | ||
| 0xEC | | 0xEC | ||
| 0x04 | | 0x04 | ||
| Export | | Export Trie num (size = num * 8) | ||
|- | |- | ||
| 0xF0 | | 0xF0 | ||
| Line 144: | Line 144: | ||
| 0xF8 | | 0xF8 | ||
| 0x04 | | 0x04 | ||
| Import | | Import Relocations offset | ||
|- | |- | ||
| 0xFC | | 0xFC | ||
| 0x04 | | 0x04 | ||
| Import | | Import Relocations num (size = num * 12) | ||
|- | |- | ||
| 0x100 | | 0x100 | ||
| Line 184: | Line 184: | ||
| 0x120 | | 0x120 | ||
| 0x04 | | 0x04 | ||
| | | [[#Fields 0x120, 0x130|Unknown Relocations]] base parameter offset | ||
|- | |- | ||
| 0x124 | | 0x124 | ||
| 0x04 | | 0x04 | ||
| | | [[#Fields 0x120, 0x130|Unknown Relocations]] base parameter num (size = num * 8) | ||
|- | |- | ||
| 0x128 | | 0x128 | ||
| 0x04 | | 0x04 | ||
| | | Internal Relocations offset | ||
|- | |- | ||
| 0x12C | | 0x12C | ||
| 0x04 | | 0x04 | ||
| | | Internal Relocations num (size = num * 12) | ||
|- | |- | ||
| 0x130 | | 0x130 | ||
| 0x04 | | 0x04 | ||
| | | [[#Fields 0x120, 0x130|Unknown Relocations]] offset | ||
|- | |- | ||
| 0x134 | | 0x134 | ||
| 0x04 | | 0x04 | ||
| | | [[#Fields 0x120, 0x130|Unknown Relocations]] num (size = num * 12) | ||
|} | |} | ||
==Segment offset | == Segment offset == | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
| Line 220: | Line 220: | ||
|} | |} | ||
==Segment Table entry | == Segment Table entry == | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
| Line 239: | Line 239: | ||
|} | |} | ||
==Named Export Table entry | == Named Export Table entry == | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
| Line 254: | Line 254: | ||
|} | |} | ||
==Indexed Export Table entry | == Indexed Export Table entry == | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
| Line 265: | Line 265: | ||
|} | |} | ||
==Named Import Table entry | == Export Trie entry == | ||
Each entry represents a node in the trie: | |||
{| class="wikitable" border="1" | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x2 | |||
| Flags (bits 0-2: bit index, bits 3-15: char index) | |||
|- | |||
| 0x2 | |||
| 0x2 | |||
| Left node info (bit 0-14: node index, bit 15: is leaf) | |||
|- | |||
| 0x4 | |||
| 0x2 | |||
| Right node info (same as left node) | |||
|- | |||
| 0x6 | |||
| 0x2 | |||
| Index for the named exports table | |||
|} | |||
The root node is a dummy node, with the right child being a leaf and pointing to the empty string. Hence the search must be performed starting from the left child. | |||
Search is performed by extracting the bit of the input using informations encoded in the flags. If the bit is 0 or the offsets are out of bounds the search continues on the left, else on the right. | |||
The search always yields a result, which may not match the input string, so a final strcmp call is required. | |||
== Named Import Table entry == | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
| Line 280: | Line 311: | ||
|} | |} | ||
==Indexed Import Table entry | == Indexed Import Table entry == | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
| Line 295: | Line 326: | ||
|} | |} | ||
==Anonymous Import Table entry | == Anonymous Import Table entry == | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
| Line 310: | Line 341: | ||
|} | |} | ||
==Import Module Table entry | == Import Module Table entry == | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
| Line 337: | Line 368: | ||
|} | |} | ||
== | == Relocation entry == | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
| Line 349: | Line 380: | ||
| 0x4 | | 0x4 | ||
| 0x1 | | 0x1 | ||
| | | Relocation type (R_ARM_NONE = 0, R_ARM_ABS32 = 2, R_ARM_REL32 = 3, R_ARM_THM_PC22 = 10, R_ARM_CALL = 28, R_ARM_JUMP24 = 29, R_ARM_TARGET1 = 38, R_ARM_PREL31 = 42) | ||
|- | |- | ||
| 0x5 | | 0x5 | ||
| 0x1 | | 0x1 | ||
| For import | | For import relocations, non-zero if last entry; for internal relocations, this is the referred segment index | ||
|- | |- | ||
| 0x6 | | 0x6 | ||
| 0x1 | | 0x1 | ||
| For import | | For import relocations, 1 is written to first entry if all symbols loaded successfully; unknown (padding?) for internal relocations | ||
|- | |- | ||
| 0x7 | | 0x7 | ||
| Line 370: | Line 401: | ||
Relocation code from RO: | Relocation code from RO: | ||
static Result | static Result writeRelocation(u32* out, u32 relocType, u32 addend, u32 base, u32 inputPtr) { | ||
const s32 branchOffset = inputPtr - base; | const s32 branchOffset = inputPtr - base; | ||
u32 offset = base + addend - inputPtr; | u32 offset = base + addend - inputPtr; | ||
if ( | if (relocType == R_ARM_NONE) | ||
return 0; | return 0; | ||
if ( | if (relocType == R_ARM_ABS32 || relocType == R_ARM_TARGET1) { | ||
*out = base + addend; | *out = base + addend; | ||
return 0; | return 0; | ||
} | } | ||
if ( | if (relocType == R_ARM_REL32) { | ||
*out = offset; | *out = offset; | ||
return 0; | return 0; | ||
} | } | ||
if ( | if (relocType == R_ARM_THM_PC22) { | ||
// +-4MB. | // +-4MB. | ||
if (branchOffset >= 0x400000 || branchOffset <= -0x400000) | if (branchOffset >= 0x400000 || branchOffset <= -0x400000) | ||
| Line 404: | Line 435: | ||
} | } | ||
if ( | if (relocType == R_ARM_CALL) { | ||
// +-32MB. | // +-32MB. | ||
if (branchOffset >= 0x2000000 || branchOffset <= -0x2000000) | if (branchOffset >= 0x2000000 || branchOffset <= -0x2000000) | ||
| Line 418: | Line 449: | ||
} | } | ||
if ( | if (relocType == R_ARM_JUMP24) { | ||
// +-32MB. | // +-32MB. | ||
if (branchOffset >= 0x2000000 || branchOffset <= -0x2000000 || (base & 1)) | if (branchOffset >= 0x2000000 || branchOffset <= -0x2000000 || (base & 1)) | ||
| Line 427: | Line 458: | ||
} | } | ||
if ( | if (relocType == R_ARM_PREL31) { | ||
*out = addend + ((base << 1) >> 1) - inputPtr; | *out = addend + ((base << 1) >> 1) - inputPtr; | ||
return 0; | return 0; | ||
| Line 435: | Line 466: | ||
} | } | ||
== nnroControlObject | == Fields 0x120, 0x130 == | ||
Field 0x130 is a list of relocations which serve an unknown purpose. Field 0x120 is a list of entries related to the previous list: | |||
{| class="wikitable" border="1" | |||
! Offset | |||
! Size | |||
! Description | |||
|- | |||
| 0x0 | |||
| 0x4 | |||
| Offset to a relocation entry in field 0x130 | |||
|- | |||
| 0x4 | |||
| 0x4 | |||
| Segment offset used for calculating the "base" parameter | |||
|} | |||
= nnroControlObject = | |||
Signature: | Signature: | ||