nintendoswitch: Add dynamic loader for runtime loading PIE sections

This commit is contained in:
Lucas Teske
2020-09-13 21:10:27 -03:00
committed by Ron Evans
parent 490e377bba
commit fb1fc267ab
6 changed files with 148 additions and 35 deletions
+4
View File
@@ -20,6 +20,10 @@
"-fno-exceptions", "-fno-unwind-tables",
"-ffunction-sections", "-fdata-sections"
],
"ldflags": [
"-pie",
"-z", "notext"
],
"linkerscript": "targets/nintendoswitch.ld",
"extra-files": [
"targets/nintendoswitch.s",
+35 -20
View File
@@ -1,69 +1,84 @@
PHDRS
{
text PT_LOAD FLAGS(5) /* Read | Execute */;
rodata PT_LOAD FLAGS(4) /* Read */;
data PT_LOAD FLAGS(6) /* Read | Write */;
bss PT_LOAD FLAGS(6) /* Read | Write */;
dynamic PT_DYNAMIC;
}
SECTIONS
{
/* Code and file header */
. = 0;
/* Code and file header */
.text : {
.text : ALIGN(0x1000) {
HIDDEN(__text_start = .);
KEEP(*(.text.jmp))
. = 0x80;
*(.text .text.*)
*(.plt .plt.*)
. = ALIGN(0x1000);
HIDDEN(__text_end = .);
HIDDEN(__text_size = . - __text_start);
}
/* Read-only sections */
. = ALIGN(0x1000);
.rodata : {
HIDDEN(__rodata_start = .);
*(.rodata .rodata.*)
*(.got)
HIDDEN(__rodata_start = .);
.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);
}
.dynsym : { *(.dynsym) } :rodata
.dynstr : { *(.dynstr) } :rodata
.rela.dyn : { *(.rela.*) } :rodata
HIDDEN(__rodata_end = .);
HIDDEN(__rodata_size = . - __rodata_start);
/* Read-write sections */
. = ALIGN(0x1000);
.data : {
HIDDEN(__data_start = .);
*(.data .data.*)
*(.got .got.*)
*(.got.plt .got.plt.*)
HIDDEN(__data_end = .);
HIDDEN(__data_size = . - __data_start);
} :data
.dynamic : {
HIDDEN(__dynamic_start = .);
*(.dynamic)
}
/* BSS section */
. = ALIGN(0x1000);
.bss : {
HIDDEN(__bss_start = .);
*(.bss .bss.*)
*(COMMON)
. = ALIGN(8);
HIDDEN(__bss_end = .);
HIDDEN(__bss_size = . - __bss_start);
}
} : bss
/DISCARD/ :
{
*(.eh_frame) /* This is probably unnecessary and bloats the binary. */
*(.eh_frame_hdr)
}
}
+32 -14
View File
@@ -6,8 +6,7 @@
_start:
b start
.word _mod_header - _start
.word 0
.word 0
.ascii "HOMEBREW"
.ascii "NRO0" // magic
.word 0 // version (always 0)
@@ -15,11 +14,11 @@ _start:
.word 0 // flags (unused)
// segment headers
.word __text_start
.word 0 // __text_start
.word __text_size
.word __rodata_start
.word 0 //__rodata_start
.word __rodata_size
.word __data_start
.word 0 //__data_start
.word __data_size
.word __bss_size
.word 0
@@ -45,18 +44,17 @@ _mod_header:
.section .text, "x"
.global start
start:
// save lr
mov x7, x30
// get aslr base
bl +4
sub x6, x30, #0x88
// Get ASLR Base
adrp x6, _start
// context ptr and main thread handle
mov x5, x0
mov x4, x1
// Save lr, context pointer, main thread handler
adrp x0, _aslr_base
str x6, [x0, #:lo12:_aslr_base]
// clear .bss
adrp x5, __bss_start
add x5, x5, #:lo12:__bss_start
@@ -71,7 +69,27 @@ bssloop:
b bssloop
run:
// process .dynamic section
adrp x0, _aslr_base
ldr x0, [x0, #:lo12:_aslr_base]
adrp x1, _DYNAMIC
add x1, x1, #:lo12:_DYNAMIC
bl __dynamic_loader
// set LR to svcExitProcess if it's null
adrp x3, exit
add x3, x3, #:lo12:exit
cmp x30, xzr
csel x30, x3, x30, eq
// call entrypoint
adrp x30, exit
add x30, x30, #:lo12:exit
mov x3, sp
sub sp, sp, 0x10
stp x29, x30, [sp]
b main
.section .data.horizon
.align 8
.global _aslr_base // Placeholder for ASLR Base Address
_aslr_base:
.dword 0