Difference between revisions of "NSO"

From Nintendo Switch Brew
Jump to navigation Jump to search
(Undo revision 1894 by Aerosoul (talk) Removed info which appears to be directly from SDK.)
Line 3: Line 3:
 
It starts with the "NSO" header and mainly describes .text, .rodata, and .data segments (like a short-form of ELF program headers):
 
It starts with the "NSO" header and mainly describes .text, .rodata, and .data segments (like a short-form of ELF program headers):
  
=== SegmentHeader ===
+
= NSO Header =
{| class="wikitable" border="1"
 
|-
 
! Offset
 
! Size
 
! Description
 
|-
 
| 0x0
 
| 4
 
| file offset of data
 
|-
 
| 0x4
 
| 4
 
| memory offset loaded to
 
|-
 
| 0x8
 
| 4
 
| size of data copied to memory offset (i.e. size after decompression)
 
|-
 
| 0xC
 
| 4
 
| alignment used on memory size / size of .bss in the case of .data segment
 
|}
 
 
 
=== .rodata-relative extent ===
 
{| class="wikitable" border="1"
 
|-
 
! Offset
 
! Size
 
! Description
 
|-
 
| 0x0
 
| 4
 
| offset (relative to .rodata)
 
|-
 
| 0x4
 
| 4
 
| size of region
 
|}
 
 
 
=== NSO Header ===
 
 
{| class="wikitable" border="1"
 
{| class="wikitable" border="1"
 
|-
 
|-
Line 68: Line 28:
 
| 0x10
 
| 0x10
 
| 0x10 * 3
 
| 0x10 * 3
| SegmentHeader for each segment
+
| SegmentHeader[3]
 
|-
 
|-
 
| 0x40
 
| 0x40
Line 76: Line 36:
 
| 0x60
 
| 0x60
 
| 0x4 * 3
 
| 0x4 * 3
| file size of each segment (i.e. LZ4-compressed size)
+
| CompressedSize[3]
 
|-
 
|-
 
| 0x6c
 
| 0x6c
Line 102: Line 62:
 
For example, the MOD header is essentially a replacement for a PT_DYNAMIC program header.
 
For example, the MOD header is essentially a replacement for a PT_DYNAMIC program header.
  
=== MOD ===
+
== SegmentHeader ==
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 4
 +
| FileOffset
 +
|-
 +
| 0x4
 +
| 4
 +
| MemoryOffset
 +
|-
 +
| 0x8
 +
| 4
 +
| DecompressedSize
 +
|-
 +
| 0xC
 +
| 4
 +
| UnkOffset/UnkSize/BssSize
 +
|}
 +
 
 +
== .rodata-relative extent ==
 +
{| class="wikitable" border="1"
 +
|-
 +
! Offset
 +
! Size
 +
! Description
 +
|-
 +
| 0x0
 +
| 4
 +
| RegionRoDataOffset
 +
|-
 +
| 0x4
 +
| 4
 +
| RegionSize
 +
|}
 +
 
 +
== MOD ==
 
All offsets are signed 32bit values relative to the magic field.
 
All offsets are signed 32bit values relative to the magic field.
 
The 32bits at image base + 4 must point to the magic field.
 
The 32bits at image base + 4 must point to the magic field.
Line 115: Line 115:
 
| 0x00
 
| 0x00
 
| 4
 
| 4
| zero padding
+
| ZeroPadding
 
|-
 
|-
 
| 0x04
 
| 0x04
 
| 4
 
| 4
| offset to magic. Always 8 (so it works when MOD is at image_base + 0).
+
| MagicOffset. Always 8 (so it works when MOD is at image_base + 0).
 
|-
 
|-
 
| 0x08
 
| 0x08
 
| 4
 
| 4
| magic "MOD0"
+
| Magic "MOD0"
 
|-
 
|-
 
| 0x0C
 
| 0x0C

Revision as of 19:52, 2 October 2017

NSO is the main executable format.

It starts with the "NSO" header and mainly describes .text, .rodata, and .data segments (like a short-form of ELF program headers):

NSO Header

Offset Size Description
0x0 4 Magic "NSO0"
0x4 4
0x8 4
0xC 4 Always 0x3f?
0x10 0x10 * 3 SegmentHeader[3]
0x40 0x20 Value of "build id" from ELF's GNU .note section. Contains variable sized digest, up to 32bytes.
0x60 0x4 * 3 CompressedSize[3]
0x6c 0x24 Padding
0x90 8 .rodata-relative extents of .dynstr
0x98 8 .rodata-relative extents of .dynsym
0xA0 0x20 * 3 SHA256 hashes over the decompressed sections using the above byte-sizes: .text, .rodata, and .data.
0x100 Compressed sections

Most data in Switch binaries are standard ELF structures, however some are custom. For example, the MOD header is essentially a replacement for a PT_DYNAMIC program header.

SegmentHeader

Offset Size Description
0x0 4 FileOffset
0x4 4 MemoryOffset
0x8 4 DecompressedSize
0xC 4 UnkOffset/UnkSize/BssSize

.rodata-relative extent

Offset Size Description
0x0 4 RegionRoDataOffset
0x4 4 RegionSize

MOD

All offsets are signed 32bit values relative to the magic field. The 32bits at image base + 4 must point to the magic field. The MOD structure is designed such that it can be placed at image base and point to itself. The 2 fields preceding the magic field get copied around with the structure, even if it is relocated to somewhere besides the image base. If MOD is not located at image base, the value at offset 4 must still point to the MOD magic. In the case of .text being at image base, this implies that the first instruction can only be an unconditional branch over the offset literal.

Offset Size Description
0x00 4 ZeroPadding
0x04 4 MagicOffset. Always 8 (so it works when MOD is at image_base + 0).
0x08 4 Magic "MOD0"
0x0C 4 .dynamic offset
0x10 4 .bss start offset
0x14 4 .bss end offset
0x18 4 .eh_frame_hdr start offset
0x1C 4 .eh_frame_hdr end offset
0x20 4 offset to runtime-generated module object. typically equal to .bss base.