Line 1: |
Line 1: |
| NSO is the main executable format. | | NSO is the main executable format. |
| | | |
− | It starts with a header: | + | It starts with the "NSO" header and mainly describes .text, .rodata, and .data segments (like a short-form of ELF program headers). If the segments are compressed, they are compressed using LZ4. |
| + | |
| + | = NsoHeader = |
| {| class="wikitable" border="1" | | {| class="wikitable" border="1" |
| |- | | |- |
Line 10: |
Line 12: |
| | 0x0 | | | 0x0 |
| | 4 | | | 4 |
− | | Magic "NSO0" | + | | Signature ("NSO0") |
| |- | | |- |
| | 0x4 | | | 0x4 |
| | 4 | | | 4 |
− | | | + | | Version |
| |- | | |- |
| | 0x8 | | | 0x8 |
| | 4 | | | 4 |
− | | | + | | Reserved |
| |- | | |- |
| | 0xC | | | 0xC |
| | 4 | | | 4 |
− | | | + | | [[#Flags|Flags]] |
| |- | | |- |
| | 0x10 | | | 0x10 |
− | | 4 | + | | 0x4 |
− | | | + | | TextFileOffset |
| |- | | |- |
| | 0x14 | | | 0x14 |
− | | 4 | + | | 0x4 |
− | | .text offset? (0) | + | | TextMemoryOffset |
| |- | | |- |
| | 0x18 | | | 0x18 |
− | | 4 | + | | 0x4 |
− | | .text size | + | | TextSize |
| |- | | |- |
| | 0x1C | | | 0x1C |
− | | 4 | + | | 0x4 |
− | | .text required align? (0x1000) | + | | ModuleNameOffset (calculated by sizeof(header)) |
| |- | | |- |
| | 0x20 | | | 0x20 |
− | | 4 | + | | 0x4 |
− | | .text compressed size? | + | | RoFileOffset |
| |- | | |- |
| | 0x24 | | | 0x24 |
− | | 4 | + | | 0x4 |
− | | .rodata offset | + | | RoMemoryOffset |
| |- | | |- |
| | 0x28 | | | 0x28 |
− | | 4 | + | | 0x4 |
− | | .rodata size | + | | RoSize |
| |- | | |- |
| | 0x2C | | | 0x2C |
− | | 4 | + | | 0x4 |
− | | .rodata required align? (1) | + | | ModuleNameSize |
| |- | | |- |
| | 0x30 | | | 0x30 |
− | | 4 | + | | 0x4 |
− | | .rodata compressed size? | + | | DataFileOffset |
| |- | | |- |
| | 0x34 | | | 0x34 |
− | | 4 | + | | 0x4 |
− | | .data offset | + | | DataMemoryOffset |
| |- | | |- |
| | 0x38 | | | 0x38 |
− | | 4 | + | | 0x4 |
− | | | + | | DataSize |
| + | |- |
| + | | 0x3C |
| + | | 0x4 |
| + | | BssSize |
| + | |- |
| + | | 0x40 |
| + | | 0x20 |
| + | | [[#ModuleId|ModuleId]] |
| + | |- |
| + | | 0x60 |
| + | | 0x4 |
| + | | TextFileSize (.text compressed size) |
| + | |- |
| + | | 0x64 |
| + | | 0x4 |
| + | | RoFileSize (.rodata compressed size) |
| + | |- |
| + | | 0x68 |
| + | | 0x4 |
| + | | DataFileSize (.data compressed size) |
| + | |- |
| + | | 0x6C |
| + | | 0x1C |
| + | | Reserved |
| + | |- |
| + | | 0x88 |
| + | | 0x4 |
| + | | EmbeddedOffset (relative to the .rodata section) |
| + | |- |
| + | | 0x8C |
| + | | 0x4 |
| + | | EmbeddedSize |
| + | |- |
| + | | 0x90 |
| + | | 0x4 |
| + | | DynStrOffset (relative to the .rodata section) |
| + | |- |
| + | | 0x94 |
| + | | 0x4 |
| + | | DynStrSize |
| + | |- |
| + | | 0x98 |
| + | | 0x4 |
| + | | DynSymOffset (relative to the .rodata section) |
| + | |- |
| + | | 0x9C |
| + | | 0x4 |
| + | | DynSymSize |
| |- | | |- |
| | 0xA0 | | | 0xA0 |
− | | 0x60 | + | | 0x20 |
− | | 3 Hashes over the decompressed sections using the above byte-sizes: .text, .rodata, and .data. | + | | TextHash (SHA-256 hash over the decompressed .text section using the above size) |
| + | |- |
| + | | 0xC0 |
| + | | 0x20 |
| + | | RoHash (SHA-256 hash over the decompressed .rodata section using the above size) |
| + | |- |
| + | | 0xE0 |
| + | | 0x20 |
| + | | DataHash (SHA-256 hash over the decompressed .data section using the above size) |
| |- | | |- |
| | 0x100 | | | 0x100 |
− | | | + | | Variable |
| | Compressed sections | | | Compressed sections |
| |} | | |} |
| + | |
| + | == Flags == |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Bits |
| + | ! Description |
| + | |- |
| + | | 0 |
| + | | TextCompress (.text section is compressed) |
| + | |- |
| + | | 1 |
| + | | RoCompress (.rodata section is compressed) |
| + | |- |
| + | | 2 |
| + | | DataCompress (.data section is compressed) |
| + | |- |
| + | | 3 |
| + | | TextHash (.text hash must be checked when loading) |
| + | |- |
| + | | 4 |
| + | | RoHash (.rodata hash must be checked when loading) |
| + | |- |
| + | | 5 |
| + | | DataHash (.data hash must be checked when loading) |
| + | |} |
| + | |
| + | == ModuleId == |
| + | This is "nn::ro::detail::ModuleId". |
| + | |
| + | Value of "build id" from ELF's GNU .note section. Contains variable sized digest, up to 32bytes. |
| + | |
| + | = Arguments = |
| + | [[Loader_services|Loader]] maps memory and writes the [[Loader_services#SetProgramArgument|arguments]] to {end of rwdata section}. Official processes use argdata_addr = {page-aligned _end}. svcQueryMemory is used by official sw to verify that argdata_addr is mapped RW, since this memory is only mapped when arguments are specified via that command. Afterwards, official sw aligns the argdata_addr to 4-bytes. |
| + | |
| + | The structure located at argdata_addr is as follows: |
| + | {| class="wikitable" border="1" |
| + | |- |
| + | ! Offset |
| + | ! Size |
| + | ! Description |
| + | |- |
| + | | 0x0 || 0x4 || This is the total allocated space relative to argdata_addr, used for calculating the max size of the argv ptr array. Normally 0x9000? |
| + | |- |
| + | | 0x4 || 0x4 || This is the total_bytesize of the actual argdata string. |
| + | |- |
| + | | 0x8 || 0x18 || Unused by official sw. |
| + | |- |
| + | | 0x20 || See above || Actual argdata string. |
| + | |} |
| + | |
| + | * The copy of the args used with the argv array is written by official processes to actual_argdata_string+actual_argdata_size. |
| + | * argv_ptrarray written by official processes is at (args_copy+actual_argdata_size) + 0x9 & ~0x7. |