RSO (File Format)
RSO format is the file format used for shared objects in some Wii games. Unlike DOL which is not relocatable and statically linked, RSO files are relocatable and are loaded and linked dynamically. It is similar usage to REL, with the difference that REL files uses pre-calculated offsets for linking to the DOL while RSO uses symbol name lookup for linking.
In games using RSO files, there is usually a .sel file stored. This is a RSO file containing no code or data and only contains symbols exported from the DOL file.
File Format
Header
The file starts with the following header:
| Offset | Type | Description |
|---|---|---|
| 0x00 | UInt32 | Next module link. Pointer to the next loaded RSO module. Always 0, filled in at runtime. |
| 0x04 | UInt32 | Previous module link. Pointer to the previous RSO module. Always 0, filled in at runtime. |
| 0x08 | UInt32 | Section count. Number of sections contained in the file. |
| 0x0C | UInt32 | Section info offset. |
| 0x10 | UInt32 | Module name offset. May be 0, meaning no module name. |
| 0x14 | UInt32 | Module name size. |
| 0x18 | UInt32 | Module version. Always 1. |
| 0x1C | UInt32 | BSS size in bytes. |
| 0x20 | Byte | Prolog section index. Section index of the prolog function, which is called when the module is linked. May be 0 if this module doesn't contain a prolog function. |
| 0x21 | Byte | Epilog section index. Section index of the epilog function, which is called when the module is unlinked. May be 0 if this module doesn't contain an epilog function. |
| 0x22 | Byte | Unresolved section index. Section index of the unresolved function, which is called if the module attempts to call an unlinked function. May be 0 if this module doesn't contain an unresolved function. |
| 0x23 | Byte | BSS section index Section index of the BSS section. Always 0, filled in at runtime. |
| 0x24 | UInt32 | Prolog function offset. Section-relative offset of the prolog function. May be 0 if this module doesn't contain a prolog function. |
| 0x28 | UInt32 | Epilog function offset. Section-relative offset of the epilog function. May be 0 if this module doesn't contain an epilog function. |
| 0x2C | UInt32 | Unresolved function offset. Section-relative offset of the unresolved function. May be 0 if this module doesn't contain an unresolved function. |
| 0x30 | UInt32 | Internal relocation table offset. Offset to the relocation table used for relocations within this module. |
| 0x34 | UInt32 | Internal relocation table size in bytes. |
| 0x30 | UInt32 | External relocation table offset. Offset to the relocation table used for relocations outside this module. |
| 0x34 | UInt32 | External relocation table size in bytes. |
| 0x40 | UInt32 | Export symbol table offset. Offset to the symbol table which stores symbols exported from this module. |
| 0x44 | UInt32 | Export symbol table size in bytes. |
| 0x48 | UInt32 | Export symbol name table offset. |
| 0x4C | UInt32 | Import symbol table offset. Offset to the symbol table which stores symbols imported to this module from other modules. |
| 0x50 | UInt32 | Import symbol table size in bytes. |
| 0x54 | UInt32 | Import symbol name table offset. |
Section Info Table
The header specifies the number of sections stored in the file. Each section has the following structure:
| Offset | Type | Description |
|---|---|---|
| 0x00 | UInt32 | Section data offset, relative to the start of the file. |
| 0x04 | UInt32 | Section data size in bytes. |
Relocation Table
Each RSO stores two relocation tables, one for internal relocation and one for external relocation. The relocation table allows code to the loaded into any virtual memory address. Each entry in the relocation table has the following structure:
| Offset | Type | Description |
|---|---|---|
| 0x00 | UInt32 | Relocation offset. Offset of this relocation, relative to the start of the file. |
| 0x04 | UInt24 | Internal relocation: Section index of the symbol. External relocation: Imported symbol index. |
| 0x07 | Byte | Relocation type. Specifies how the data located at the offset specified should be transformed. |
| 0x08 | UInt32 | Internal relocation: Section-relative offset of the symbol being patched to. External relocation: Unused, always 0. |
Symbol Table
The header specifies the offset and size of the symbol table, as well as an offset to the symbol name table, which contains null-terminated strings. To calculate the number of entries, divide the symbol table size by 0x10 and 0x0C for the exported and imported symbol table respectively.
In order to resolve symbols at runtime two symbol tables are stored. This is a big difference compared to REL, which does not relocate by symbols. The export table is used for specifying symbols in the current RSO module. The import symbol table is used for symbols outside this module which are referenced in the current RSO module. The symbol names in the import table is used to find the actual symbol from the export symbol table of another RSO module.
The structure is slightly different between export and import symbols, since import symbols do not store an ELF hash. However, everything else is the same. Each symbol has the following structure:
| Offset | Type | Description |
|---|---|---|
| 0x00 | UInt32 | Symbol name offset, relative to the symbol name table specified in the header. |
| 0x04 | UInt32 | Symbol offset. Section-relative offset to the symbol. Always 0 for import symbols. |
| 0x08 | UInt32 | Export: Section index which contains this symbol. Import: Unknown, seems to be an offset. |
| 0x0C | UInt32 | ELF hash. Only stored for export symbols. |
Tools
The following tools can handle RSO files:
- (none)