Changes

2,755 bytes added ,  21:29, 25 September 2024
no edit summary
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
|
+
| TextMemoryOffset
 
|-
 
|-
 
| 0x18
 
| 0x18
| 4
+
| 0x4
| .text size
+
| TextSize
 
|-
 
|-
 
| 0x1C
 
| 0x1C
| 4
+
| 0x4
| 0x1000
+
| ModuleNameOffset (calculated by sizeof(header))
 
|-
 
|-
 
| 0x20
 
| 0x20
| 4
+
| 0x4
|  
+
| RoFileOffset
 
|-
 
|-
 
| 0x24
 
| 0x24
| 4
+
| 0x4
| .rodata offset
+
| RoMemoryOffset
 
|-
 
|-
 
| 0x28
 
| 0x28
| 4
+
| 0x4
| .rodata size
+
| RoSize
 
|-
 
|-
 
| 0x2C
 
| 0x2C
| 4
+
| 0x4
| 1
+
| ModuleNameSize
 
|-
 
|-
 
| 0x30
 
| 0x30
| 4
+
| 0x4
|  
+
| 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.