CRO0: Difference between revisions
Link to the definition for segment offsets |
mNo edit summary |
||
(4 intermediate revisions by 2 users not shown) | |||
Line 10: | Line 10: | ||
For dumping symbols and loading a CRO into IDA, see [https://github.com/plutooo/ctr/] and [https://github.com/wwylele/IDA_plugin_CRO]. | For dumping symbols and loading a CRO into IDA, see [https://github.com/plutooo/ctr/] and [https://github.com/wwylele/IDA_plugin_CRO]. | ||
= Structure = | |||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
Line 54: | 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 (4 bytes)|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 (4 bytes)|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 (4 bytes)|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 (4 bytes)|Segment offset]] for "OnUnresolved" function, which will be called when an unresolved function is called. Set to 0xFFFFFFFF if not exists. | ||
|- | |- | ||
| 0xB0 | | 0xB0 | ||
Line 218: | Line 220: | ||
|} | |} | ||
Segment Table entry (12 bytes) | ==Segment Table entry (12 bytes)== | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
Line 237: | Line 239: | ||
|} | |} | ||
Named Export Table entry (8 bytes) | ==Named Export Table entry (8 bytes)== | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
Line 249: | Line 251: | ||
| 0x4 | | 0x4 | ||
| 0x4 | | 0x4 | ||
| [[Segment offset (4 bytes)|Segment offset]] for export | | [[#Segment offset (4 bytes)|Segment offset]] for export | ||
|} | |} | ||
Indexed Export Table entry (4 bytes) | ==Indexed Export Table entry (4 bytes)== | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
Line 260: | Line 262: | ||
| 0x0 | | 0x0 | ||
| 0x4 | | 0x4 | ||
| [[Segment offset (4 bytes)|Segment offset]] for export | | [[#Segment offset (4 bytes)|Segment offset]] for export | ||
|} | |} | ||
Named Import Table entry (8 bytes) | ==Named Import Table entry (8 bytes)== | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
Line 278: | Line 280: | ||
|} | |} | ||
Indexed Import Table entry (8 bytes) | ==Indexed Import Table entry (8 bytes)== | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
Line 293: | Line 295: | ||
|} | |} | ||
Anonymous Import Table entry (8 bytes) | ==Anonymous Import Table entry (8 bytes)== | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
Line 301: | Line 303: | ||
| 0x0 | | 0x0 | ||
| 0x4 | | 0x4 | ||
| [[Segment offset (4 bytes)|Segment offset]] of the export symbol | | [[#Segment offset (4 bytes)|Segment offset]] of the export symbol | ||
|- | |- | ||
| 0x4 | | 0x4 | ||
Line 308: | Line 310: | ||
|} | |} | ||
Import Module Table entry (20 bytes) | ==Import Module Table entry (20 bytes)== | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
Line 335: | Line 337: | ||
|} | |} | ||
Patch entry (12 bytes) | ==Patch entry (12 bytes)== | ||
{| class="wikitable" border="1" | {| class="wikitable" border="1" | ||
! Offset | ! Offset | ||
Line 343: | Line 345: | ||
| 0x0 | | 0x0 | ||
| 0x4 | | 0x4 | ||
| [[Segment offset (4 bytes)|Segment offset]] for output. | | [[#Segment offset (4 bytes)|Segment offset]] for output. | ||
|- | |- | ||
| 0x4 | | 0x4 | ||
| 0x1 | | 0x1 | ||
| Patch type (0= | | 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) | ||
|- | |- | ||
| 0x5 | | 0x5 | ||
Line 366: | Line 368: | ||
|} | |} | ||
Relocation code from RO: | |||
static Result writePatch(u32* out, u32 patchType, u32 addend, u32 base, u32 inputPtr) { | |||
const s32 branchOffset = inputPtr - base; | |||
u32 offset = base + addend - inputPtr; | |||
if (patchType == R_ARM_NONE) | |||
return 0; | |||
if (patchType == R_ARM_ABS32 || patchType == R_ARM_TARGET1) { | |||
*out = base + addend; | |||
return 0; | |||
} | |||
if (patchType == R_ARM_REL32) { | |||
*out = offset; | |||
return 0; | |||
} | |||
if (patchType == R_ARM_THM_PC22) { | |||
// +-4MB. | |||
if (branchOffset >= 0x400000 || branchOffset <= -0x400000) | |||
return 0xD9012C23; | |||
if (base & 1) { | |||
*out = (((offset >> 12) | 0xF000) << 16) | ((offset << 4) >> 5) | 0xF800; | |||
} else { | |||
if (offset & 2) | |||
offset += 2; | |||
*out = ((offset >> 12) | 0xF000) << 16 | ((offset << 4) >> 5) | 0xE800; | |||
} | |||
return 0; | |||
} | |||
if (patchType == R_ARM_CALL) { | |||
// +-32MB. | |||
if (branchOffset >= 0x2000000 || branchOffset <= -0x2000000) | |||
return 0xD9012C23; | |||
if (base & 1) { | |||
*out = ((offset << 23) & 0x1000000) | ((offset << 6) >> 8) | 0xFA000000; | |||
} else { | |||
*out = 0xEB000000 | ((offset << 6) >> 8); | |||
} | |||
return 0; | |||
} | |||
if (patchType == R_ARM_JUMP24) { | |||
// +-32MB. | |||
if (branchOffset >= 0x2000000 || branchOffset <= -0x2000000 || (base & 1)) | |||
return 0xD9012C23; | |||
*out = (*out & 0xFF000000) | ((offset << 6) >> 8); | |||
return 0; | |||
} | |||
if (patchType == R_ARM_PREL31) { | |||
*out = addend + ((base << 1) >> 1) - inputPtr; | |||
return 0; | |||
} | |||
return 0xD9012C22; | |||
} | |||
== nnroControlObject == | |||
---- | Signature: | ||
Result nnroControlObject(void* arg, u32 type); | |||
{| class="wikitable" border="1" | |||
! Type | |||
! Description | |||
|- | |||
| 0 | |||
| Write address of "nnroEitNode_" to memory pointed by arg (*(u32*)arg = &nnroEitNode_) | |||
|- | |||
| 1 | |||
| Set global in CRO to arg, where arg is the CRO end (g_CRO_end = (u32)arg) | |||
|- | |||
| 2 | |||
| Write CRO end to memory pointed by arg (*(u32*)arg = g_CRO_end) | |||
|- | |||
| 3 | |||
| Write begin, end of function list (C initializers?) to memory pointed by arg (*(u32*)arg = (u32)listBegin, ((u32*)arg)[1] = (u32)listEnd) | |||
|- | |||
| 4 | |||
| Write begin, end of function list (C++ initializers?) to memory pointed by arg (*(u32*)arg = (u32)listBegin, ((u32*)arg)[1] = (u32)listEnd) | |||
|} | |||
"EitNode" are nodes of a linked list containing informations about the main executable + loaded modules: | |||
{| class="wikitable" border="1" | |||
! Index Word | |||
! Type | |||
! Description | |||
|- | |||
| 0 | |||
| EitNode* | |||
| Pointer to the previous element of the list | |||
|- | |||
| 1 | |||
| EitNode* | |||
| Pointer to the next element of the list | |||
|- | |||
| 2 | |||
| u32 | |||
| Module code start, for the main executable this is .text base, for CROs this is the value at CRO+0xB0 | |||
|- | |||
| 3 | |||
| u32 | |||
| Module code end (start + size), for the main executable the size is the size of all mapped sections, for CROs it's the value at CRO+0xB4 | |||
|- | |||
| 4 | |||
| u32* | |||
| Unknown, seems to be an array of u32, probably holds debugging informations | |||
|- | |||
| 5 | |||
| u32* | |||
| This points at the end of the previous array | |||
|- | |||
| 6 | |||
| ElfNode* (?) | |||
| Unknown, this is only set for the main executable node, and it points to itself | |||
|} |