nintendoswitch: support outputting .nro files directly
By modifying the linker script a bit and adding the NRO0 header directly in the assembly, it's possible to craft an ELF file that can be converted straight to a binary (using objcopy or similar) that is a NRO file. This avoids custom code for NRO files or an extra build step. With another change, .nro files are recognized by TinyGo so that this will create a ready-to-run NRO file: tinygo build -o test.nro -target=nintendoswitch examples/serial
Этот коммит содержится в:
родитель
81e325205f
коммит
9e599bac49
4 изменённых файлов: 64 добавлений и 30 удалений
4
Makefile
4
Makefile
|
@ -373,8 +373,8 @@ endif
|
|||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -size short -o test.hex -target=pca10040 -opt=1 examples/blinky1
|
||||
@$(MD5SUM) test.hex
|
||||
$(TINYGO) build -o test.elf -target=nintendoswitch examples/serial
|
||||
@$(MD5SUM) test.elf
|
||||
$(TINYGO) build -o test.nro -target=nintendoswitch examples/serial
|
||||
@$(MD5SUM) test.nro
|
||||
|
||||
wasmtest:
|
||||
$(GO) test ./tests/wasm
|
||||
|
|
|
@ -243,7 +243,7 @@ func (c *Config) Debug() bool {
|
|||
// extension and the configured binary format in the target JSON file.
|
||||
func (c *Config) BinaryFormat(ext string) string {
|
||||
switch ext {
|
||||
case ".bin", ".gba":
|
||||
case ".bin", ".gba", ".nro":
|
||||
// The simplest format possible: dump everything in a raw binary file.
|
||||
if c.Target.BinaryFormat != "" {
|
||||
return c.Target.BinaryFormat
|
||||
|
|
|
@ -1,61 +1,69 @@
|
|||
OUTPUT_FORMAT(elf64-littleaarch64)
|
||||
OUTPUT_ARCH(aarch64)
|
||||
ENTRY(_start)
|
||||
|
||||
PHDRS
|
||||
{
|
||||
text PT_LOAD FLAGS(5);
|
||||
rodata PT_LOAD FLAGS(4);
|
||||
data PT_LOAD FLAGS(6);
|
||||
bss PT_LOAD FLAGS(6);
|
||||
dynamic PT_DYNAMIC;
|
||||
}
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
. = 0;
|
||||
|
||||
.text : ALIGN(0x1000) {
|
||||
/* Code and file header */
|
||||
|
||||
.text : {
|
||||
HIDDEN(__text_start = .);
|
||||
KEEP(*(.text.jmp))
|
||||
|
||||
. = 0x80;
|
||||
|
||||
*(.text .text.*)
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
HIDDEN(__text_end = .);
|
||||
HIDDEN(__text_size = . - __text_start);
|
||||
}
|
||||
|
||||
/* Read-only sections */
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
.rodata : {
|
||||
HIDDEN(__rodata_start = .);
|
||||
|
||||
*(.rodata .rodata.*)
|
||||
|
||||
*(.got)
|
||||
|
||||
.rodata : { *(.rodata .rodata.*) } :rodata
|
||||
.mod0 : {
|
||||
KEEP(crt0.nso.o(.data.mod0))
|
||||
KEEP(crt0.nro.o(.data.mod0))
|
||||
KEEP(crt0.lib.nro.o(.data.mod0))
|
||||
KEEP(*(.data.mod0))
|
||||
|
||||
HIDDEN(__dynamic_start = .);
|
||||
*(.dynamic)
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
HIDDEN(__rodata_end = .);
|
||||
HIDDEN(__rodata_size = . - __rodata_start);
|
||||
}
|
||||
|
||||
/* Read-write sections */
|
||||
. = ALIGN(0x1000);
|
||||
|
||||
.data : {
|
||||
*(.data .data.*)
|
||||
} :data
|
||||
HIDDEN(__data_start = .);
|
||||
|
||||
.dynamic : {
|
||||
HIDDEN(__dynamic_start = .);
|
||||
*(.dynamic)
|
||||
*(.data .data.*)
|
||||
|
||||
HIDDEN(__data_end = .);
|
||||
HIDDEN(__data_size = . - __data_start);
|
||||
}
|
||||
|
||||
/* BSS section */
|
||||
|
||||
. = ALIGN(0x1000);
|
||||
|
||||
.bss : {
|
||||
HIDDEN(__bss_start = .);
|
||||
|
||||
*(.bss .bss.*)
|
||||
*(COMMON)
|
||||
. = ALIGN(8);
|
||||
|
||||
HIDDEN(__bss_end = .);
|
||||
} :bss
|
||||
HIDDEN(__bss_size = . - __bss_start);
|
||||
}
|
||||
|
||||
/DISCARD/ :
|
||||
{
|
||||
*(.eh_frame) /* This is probably unnecessary and bloats the binary. */
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,8 +1,34 @@
|
|||
// For more information on the .nro file format, see:
|
||||
// https://switchbrew.org/wiki/NRO
|
||||
|
||||
.section .text.jmp, "x"
|
||||
.global _start
|
||||
_start:
|
||||
b start
|
||||
.word _mod_header - _start
|
||||
.word 0
|
||||
.word 0
|
||||
|
||||
.ascii "NRO0" // magic
|
||||
.word 0 // version (always 0)
|
||||
.word __bss_start - _start // total NRO file size
|
||||
.word 0 // flags (unused)
|
||||
|
||||
// segment headers
|
||||
.word __text_start
|
||||
.word __text_size
|
||||
.word __rodata_start
|
||||
.word __rodata_size
|
||||
.word __data_start
|
||||
.word __data_size
|
||||
.word __bss_size
|
||||
.word 0
|
||||
|
||||
// ModuleId (not supported)
|
||||
. = 0x50; // skip 32 bytes
|
||||
|
||||
.word 0 // DSO Module Offset (unused)
|
||||
.word 0 // reserved (unused)
|
||||
|
||||
.section .data.mod0
|
||||
.word 0, 8
|
||||
|
|
Загрузка…
Создание таблицы
Сослаться в новой задаче