CRO0: Difference between revisions

Kynex7510 (talk | contribs)
mNo edit summary
Kynex7510 (talk | contribs)
Trie entries + unknown fields
Line 48: Line 48:
| 0x98
| 0x98
| 0x04
| 0x04
| Unknown
| 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 (4 bytes)|Segment offset]] that is always the same as export symbol "nnroControlObject_". 0xFFFFFFFF in CRS
| [[#Segment offset|Segment offset]] that is always the same as export symbol "nnroControlObject_". 0xFFFFFFFF in CRS
|-
|-
| 0xA4
| 0xA4
| 0x04
| 0x04
| [[#Segment offset (4 bytes)|Segment offset]] for "OnLoad" function, which will be called when the module is initialized. Set to 0xFFFFFFFF if not exists.
| [[#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 (4 bytes)|Segment offset]] for "OnExit" function, which will be called when the module is finalized. Set to 0xFFFFFFFF if not exists.
| [[#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 (4 bytes)|Segment offset]] for "OnUnresolved" function, which will be called when an unresolved function is called. Set to 0xFFFFFFFF if not exists.
| [[#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 Tree offset (fast lookups based on a trie-like structure)
| Export Trie offset
|-
|-
| 0xEC
| 0xEC
| 0x04
| 0x04
| Export Tree num (size = num * 8)
| Export Trie num (size = num * 8)
|-
|-
| 0xF0
| 0xF0
Line 144: Line 144:
| 0xF8
| 0xF8
| 0x04
| 0x04
| Import Patches offset
| Import Relocations offset
|-
|-
| 0xFC
| 0xFC
| 0x04
| 0x04
| Import Patches num (size = num * 12)
| Import Relocations num (size = num * 12)
|-
|-
| 0x100
| 0x100
Line 184: Line 184:
| 0x120
| 0x120
| 0x04
| 0x04
| unk8 offset
| [[#Fields 0x120, 0x130|Unknown Relocations]] base parameter offset
|-
|-
| 0x124
| 0x124
| 0x04
| 0x04
| unk8 num
| [[#Fields 0x120, 0x130|Unknown Relocations]] base parameter num (size = num * 8)
|-
|-
| 0x128
| 0x128
| 0x04
| 0x04
| Relocation Patches offset
| Internal Relocations offset
|-
|-
| 0x12C
| 0x12C
| 0x04
| 0x04
| Relocation Patches num (size = num * 12)
| Internal Relocations num (size = num * 12)
|-
|-
| 0x130
| 0x130
| 0x04
| 0x04
| unk9 offset
| [[#Fields 0x120, 0x130|Unknown Relocations]] offset
|-
|-
| 0x134
| 0x134
| 0x04
| 0x04
| unk9 num
| [[#Fields 0x120, 0x130|Unknown Relocations]] num (size = num * 12)
|}
|}


==Segment offset (4 bytes)==
== Segment offset ==


{| class="wikitable" border="1"
{| class="wikitable" border="1"
Line 220: Line 220:
|}
|}


==Segment Table entry (12 bytes)==
== Segment Table entry ==
{| class="wikitable" border="1"
{| class="wikitable" border="1"
!  Offset
!  Offset
Line 239: Line 239:
|}
|}


==Named Export Table entry (8 bytes)==
== Named Export Table entry ==
{| class="wikitable" border="1"
{| class="wikitable" border="1"
!  Offset
!  Offset
Line 254: Line 254:
|}
|}


==Indexed Export Table entry (4 bytes)==
== Indexed Export Table entry ==
{| class="wikitable" border="1"
{| class="wikitable" border="1"
!  Offset
!  Offset
Line 265: Line 265:
|}
|}


==Named Import Table entry (8 bytes)==
== 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 (8 bytes)==
== Indexed Import Table entry ==
{| class="wikitable" border="1"
{| class="wikitable" border="1"
!  Offset
!  Offset
Line 295: Line 326:
|}
|}


==Anonymous Import Table entry (8 bytes)==
== Anonymous Import Table entry ==
{| class="wikitable" border="1"
{| class="wikitable" border="1"
!  Offset
!  Offset
Line 310: Line 341:
|}
|}


==Import Module Table entry (20 bytes)==
== Import Module Table entry ==
{| class="wikitable" border="1"
{| class="wikitable" border="1"
!  Offset
!  Offset
Line 337: Line 368:
|}
|}


==Patch entry (12 bytes)==
== Relocation entry ==
{| class="wikitable" border="1"
{| class="wikitable" border="1"
!  Offset
!  Offset
Line 349: Line 380:
| 0x4
| 0x4
| 0x1
| 0x1
| Patch 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)
| 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 patches, non-zero if last entry; for relocation patches, this is the referred segment index
| For import relocations, non-zero if last entry; for internal relocations, this is the referred segment index
|-
|-
| 0x6
| 0x6
| 0x1
| 0x1
| For import patches, 1 is written to first entry if all symbols loaded successfully; unknown (padding?) for relocation patches
| 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 writePatch(u32* out, u32 patchType, u32 addend, u32 base, u32 inputPtr) {
  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 (patchType == R_ARM_NONE)
     if (relocType == R_ARM_NONE)
         return 0;
         return 0;
   
   
     if (patchType == R_ARM_ABS32 || patchType == R_ARM_TARGET1) {
     if (relocType == R_ARM_ABS32 || relocType == R_ARM_TARGET1) {
         *out = base + addend;
         *out = base + addend;
         return 0;
         return 0;
     }
     }
   
   
     if (patchType == R_ARM_REL32) {
     if (relocType == R_ARM_REL32) {
         *out = offset;
         *out = offset;
         return 0;
         return 0;
     }
     }
   
   
     if (patchType == R_ARM_THM_PC22) {
     if (relocType == R_ARM_THM_PC22) {
         // +-4MB.
         // +-4MB.
         if (branchOffset >= 0x400000 || branchOffset <= -0x400000)
         if (branchOffset >= 0x400000 || branchOffset <= -0x400000)
Line 404: Line 435:
     }
     }
   
   
     if (patchType == R_ARM_CALL) {
     if (relocType == R_ARM_CALL) {
         // +-32MB.
         // +-32MB.
         if (branchOffset >= 0x2000000 || branchOffset <= -0x2000000)
         if (branchOffset >= 0x2000000 || branchOffset <= -0x2000000)
Line 418: Line 449:
     }
     }
   
   
     if (patchType == R_ARM_JUMP24) {
     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 (patchType == R_ARM_PREL31) {
     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: