Offset | Size | Description |
---|---|---|
0x0 | 0x80 | SHA-256 hash-table, verified by CRR |
0x80 | 0x04 | Magic "CRO0" |
0x84 | 0x04 | Name offset |
0x88 | 0x08 | Previous / Next loaded CRO pointer, set by RO during loading |
0x90 | 0x04 | File size |
0x94 | 0x18 | Unknown |
0xAC | 0x04 | "Segment offset", symbols are loaded relative to this. Probably filled by dynamic linker, set to 0xFFFFFFFF in file. |
0xB0 | 0x04 | Code offset |
0xB4 | 0x04 | Code size |
0xB8 | 0x04 | unk1 offset |
0xBC | 0x04 | unk1 size |
0xC0 | 0x04 | Module Name offset |
0xC4 | 0x04 | Module Name size |
0xC8 | 0x04 | Segment Table offset |
0xCC | 0x04 | Segment Table num (size = num*12) |
0xD0 | 0x04 | Export Table offset |
0xD4 | 0x04 | Export Table num (size = num * 8) |
0xD8 | 0x04 | unk3 offset |
0xDC | 0x04 | unk3 num |
0xE0 | 0x04 | Export Strings offset |
0xE4 | 0x04 | Export Strings size |
0xE8 | 0x04 | Export Tree offset (fast lookups based on strlen) |
0xEC | 0x04 | Export Tree num (size = num * 8) |
0xF0 | 0x04 | unk4 offset |
0xF4 | 0x04 | unk4 num |
0xF8 | 0x04 | Import Patches offset |
0xFC | 0x04 | Import Patches num (size = num * 12) |
0x100 | 0x04 | Import Table 1 offset |
0x104 | 0x04 | Import Table 1 num (size = num * 8) |
0x108 | 0x04 | Import Table 2 offset |
0x10C | 0x04 | Import Table 2 num (size = num * 8) |
0x110 | 0x04 | Import Table 3 offset |
0x114 | 0x04 | Import Table 3 num (size = num * 8) |
0x118 | 0x04 | Import Strings offset |
0x11C | 0x04 | Import Strings size |
0x120 | 0x04 | unk8 offset |
0x124 | 0x04 | unk8 num |
0x128 | 0x04 | Relocation Patches offset |
0x12C | 0x04 | Relocation Patches num (size = num * 12) |
0x130 | 0x04 | unk9 offset |
0x134 | 0x04 | unk9 num |
Segment offset (4 bytes)
Bits | Description |
---|---|
0-3 | Segment index for table |
4-31 | Offset into segment |
Segment Table entry (12 bytes)
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Segment offset |
0x4 | 0x4 | Segment size |
0x8 | 0x4 | Segment id (0, 1, 2..) |
Export Table entry (8 bytes)
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Name offset |
0x4 | 0x4 | "Segment offset" for export |
Import Table entry (8 bytes)
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | Name offset |
0x4 | 0x4 | Offset of the head of a linear list that contains the patches for this import |
Patch entry (12 bytes)
Offset | Size | Description |
---|---|---|
0x0 | 0x4 | "Segment offset" for output. |
0x4 | 0x1 | Patch type (0=nothing/ignore, 2=38=write u32 absolute (base+X), 3=write u32 relative (base+X-in_ptr), 10=THUMB branch, 28=ARM32 branch, 29=modify ARM32 branch offset, 42=write u32 relative (((signed int)base*2)/2+X-in_ptr), otherwise err) |
0x5 | 0x1 | Non-zero if last entry. |
0x6 | 0x1 | 1 is written to last entry if all symbols loaded successfully. |
0x7 | 0x1 | Unknown |
0x8 | 0x4 | X (00's in file, probably set by dynamic linker) |
ARM32 branch instruction is constructed as follows:
If X > 0x2000000 or X < 0xFE000000, then skip. If (X&1) == 1 then write "b +4" (nop). Else write as normal.
CRO with extension .cro is used for "DLLs". CRS with extension .crs can be used for storing "DLL" symbols as well. The end of the file is aligned to a 0x1000-byte boundary with 0xCC bytes. CRO0 files are usually stored under "romfs:/cro/".
The first hash-table entry hashes the 0x100-byte header following the hash-table. The following hash-table entries hash the sections specified in the header.
When the RO module loads the entire CRO into process memory(mapped in the 0x00100000-0x04000000 region), it modifies the mapped CRO data. The magic field is also changed to "FIXD".
Upon loading, the RO module will look for symbol "__aeabi_atexit" or "nnroAeabiAtexit_".
For dumping symbols and loading a CRO into IDA, see [1].