RSO (File Format)
The RSO format is the file format for shared objects for Wii games. This is essentially the Wii's equivalent of a DLL file, allowing for code modules to be dynamically linked at runtime and unlinked when not in use to save memory. It's very similar to the GameCube's REL format, with the main difference being that the RSO format resolves symbol references via runtime symbol lookups rather than having pre-calculated offsets into the game's module files.
RSO files are usually accompanied by a SEL file, which is an RSO file that contains no code or data sections, and instead just has an export table for the DOL file. This is used to resolve module references to symbols in the main executable.
Format
Header
Offset | Type | Count | Name | Notes |
---|---|---|---|---|
0x0 | u32 | 1 | Next Module Link | Pointer to the next module, forming a linked list. Always 0, filled in at runtime. |
0x4 | u32 | 1 | Previous Module Link | Pointer to the previous module, forming a linked list. Always 0, filled in at runtime. |
0x8 | u32 | 1 | Section Count | Number of sections contained in the file. |
0xC | u32 | 1 | Section Info Offset | Offset to the section info table. Always 0x58. |
0x10 | u32 | 1 | Module Name Offset | Offset to the module name. Can be 0, in which case this module doesn't contain a name string. |
0x14 | u32 | 1 | Module Name Size | Size of the module name string. |
0x18 | u32 | 1 | Module Version | Module version number. Always 1. |
0x1C | u32 | 1 | BSS Size | Size of the BSS section, which is allocated at runtime (not included in the file). |
0x20 | u8 | 1 | Prolog Section | Section index of the prolog function, which is called when the module is linked. 0 if this module doesn't contain a prolog function. |
0x21 | u8 | 1 | Epilog Section | Section index of the epilog function, which is called when the module is unlinked. 0 if this module doesn't contain an epilog function. |
0x22 | u8 | 1 | Unresolved Section | Section index of the unresolved function, which is called if the module attempts to call an unlinked function. 0 if this module doesn't contain an unresolved function. |
0x23 | u8 | 1 | BSS Section | Section index of the BSS section. Always 0, filled in at runtime. |
0x24 | u32 | 1 | Prolog Function Offset | Section-relative offset of the prolog function. 0 if this module doesn't contain a prolog function. |
0x28 | u32 | 1 | Epilog Function Offset | Section-relative offset of the epilog function. 0 if this module doesn't contain an epilog function. |
0x2C | u32 | 1 | Unresolved Function Offset | Section-relative offset of the unresolved function. 0 if this module doesn't contain an unresolved function. |
0x30 | u32 | 1 | Internal Relocation Table Offset | Absolute offset of the relocation table for internal relocations (relocations for symbols within this module). |
0x34 | u32 | 1 | Internal Relocation Table Size | Size of the relocation table for internal relocations. |
0x38 | u32 | 1 | External Relocation Table Offset | Absolute offset of the relocation table for external relocations (relocations for symbols within other modules). |
0x3C | u32 | 1 | External Relocation Table Size | Size of the relocation table for external relocations. |
0x40 | u32 | 1 | Export Symbol Table Offset | Absolute offset of the symbol table for exports (symbols within this module). |
0x44 | u32 | 1 | Export Symbol Table Size | Size of the symbol table for exports. |
0x48 | u32 | 1 | Export Symbol Names Offset | Absolute offset of the string table containing export symbol names. |
0x4C | u32 | 1 | Import Symbol Table Offset | Absolute offset of the symbol table for imports (symbols within other modules, referenced by this one). |
0x50 | u32 | 1 | Import Symbol Table Size | Size of the symbol table for imports. |
0x54 | u32 | 1 | Import Symbol Names Offset | Absolute offset of the string table containing import symbol names. |
0x58 | End of RSO header |
Section Info Table
This data is pointed to by the Section Info Offset value in the header. It specifies the layout of the file. The structure loops once for each section in the file, as specified by the Section Count in the header. Any compiler-generated sections that are unused (such as the symbol table or the section name table) are nulled out and listed with a size/offset of 0. The first section is always null. The BSS section is listed with a valid size but an offset of 0 (as the BSS section is not included in the file, but instead has space allocated at runtime).
Offset | Type | Count | Name | Notes |
---|---|---|---|---|
0x0 | u32 | 1 | Offset | Absolute offset of the section. |
0x4 | u32 | 1 | Size | Size of the section. |
0x8 | End of section info |
Relocation Table
Since modules have space allocated at runtime and therefore do not have a fixed memory address, the relocations table is needed to ensure all data and function addresses in the RSO are correct; this includes both symbols within the RSO itself, which don't have a fixed address until the RSO is linked in, and symbols within the DOL, which need corrections due to the usage of relative offsets in branch instructions. The relocation table describes the location of every instruction that needs to be patched, and how to patch it.
There are two relocation tables in the file; one for internal relocations (relocations for addresses pointing to symbols within this RSO), and one for external relocations (relocations for addresses pointing to symbols within the main DOL executable). These tables are pointed to by the Internal Relocation Table Offset and External Relocation Table Offset values in the header. You can calculate the number of relocation entries by dividing the size of the table by 0xC (the size of one relocation entry).
Offset | Type | Count | Name | Notes |
---|---|---|---|---|
0x0 | u32 | 1 | Offset | Absolute offset of this relocation (relative to the start of the RSO file). |
0x4 | u24 | 1 | Symbol ID | For internal relocations, this is the section index of the symbol being patched to. For external relocations, this is the index of the symbol within the import symbol table. |
0x7 | u8 | 1 | Relocation Type | Type of the relocation. See the below table for a list of possible types. |
0x8 | u32 | 1 | Symbol Offset | For internal relocations, this is the section-relative offset of the symbol being patched to. For external relocations, this is unused and always 0 (the offset is calculated using the import symbol table). |
0xC | End of relocation |
These are the possible relocation types. The "used" column indicates whether this relocation type is used by any of the modules in any of Retro's games.
Value | Name | Description | Used? |
---|---|---|---|
0 | R_PPC_NONE | Do nothing. | ✖ |
1 | R_PPC_ADDR32 | Write the full, 32-bit address of the symbol. | ✔ |
2 | R_PPC_ADDR24 | Write the 24-bit address of the symbol. Leave the existing value of the bottom two bits intact. | ✖ |
3 | R_PPC_ADDR16 | Write the 16-bit address of the symbol. | ✖ |
4 | R_PPC_ADDR16_LO | Write the low 16 bits of the symbol address. | ✔ |
5 | R_PPC_ADDR16_HI | Write the high 16 bits of the symbol address. | ✔ |
6 | R_PPC_ADDR16_HA | Write the high 16 bits of the symbol address, plus 0x10000. This is used for cases where the bottom half is >= 0x8000, in which case a subtract operation is used to load the lower half of the address. | ✔ |
7 | R_PPC_ADDR14 | Write the 14-bit address of the symbol. Leave the existing value of the bottom two bits intact. This is used for conditional branch instructions. | ✖ |
8 | R_PPC_ADDR14_BRTAKEN | Write the 14-bit address of the symbol. Leave the existing value of the bottom two bits intact. Note: Needs a proper check on differences between this and ADDR14 | ✖ |
9 | R_PPC_ADDR14_BRNTAKEN | Write the 14-bit address of the symbol. Leave the existing value of the bottom two bits intact. Note: Needs a proper check on differences between this and ADDR14 | ✖ |
10 | R_PPC_REL24 | Write a 24-bit offset from the address of this instruction to the address of the symbol. This is used for branch instructions. | ✔ |
11 | R_PPC_REL14 | Write a 14-bit offset from the address of this instruction to the address of the symbol. | ✖ |
Symbol Table
RSO modules resolve references to symbols at runtime, rather than using precalculated offsets into the module files like REL does. To accomplish this, there's two symbol tables in the file; one for exports (symbols that are included in this RSO), and imports (symbols that are included in other modules but are referenced from this module). The name of the symbol in the import table is used to locate the same symbol in another module's export table, from which the address of the symbol can be calculated. Note that although the main DOL file doesn't contain an export table, there is a DOL export table in the SEL file, which can usually be found alongside the RSOs.
Offset | Type | Count | Name | Notes |
---|---|---|---|---|
0x0 | u32 | 1 | Symbol Name Offset | Relative offset into the name table pointed to in the header, which points to the name of this symbol. |
0x4 | u32 | 1 | Symbol Offset | The section-relative offset to the symbol. This is always 0 for imports. |
0x8 | u32 | 1 | Symbol Section Index | For exports, index of the section that contains this symbol. For imports, appears to be an offset? |
0xC | u32 | 1 | ELF Hash | A hash. Exact details unknown, but isn't required to link to the symbol. This field is omitted for imports. |
0x10 | End of symbol |