mirror of
https://github.com/switchbrew/libnx.git
synced 2025-06-21 12:32:40 +02:00
crt0: clean up/refactor; envSetup: properly detect NSO/NRO environment...
This commit is contained in:
parent
7c6d7849f5
commit
e655b48c41
@ -30,28 +30,21 @@ extern __attribute__((weak)) u32 __nx_applet_type;
|
||||
|
||||
void envSetup(void* ctx, Handle main_thread, LoaderReturnFn saved_lr)
|
||||
{
|
||||
// If we're running under NSO, we should just call svcExitProcess.
|
||||
// Otherwise we should return to loader via LR.
|
||||
if (saved_lr == NULL) {
|
||||
g_loaderRetAddr = (LoaderReturnFn) &svcExitProcess;
|
||||
}
|
||||
else {
|
||||
g_loaderRetAddr = saved_lr;
|
||||
}
|
||||
|
||||
// Detect NSO environment.
|
||||
if (main_thread != -1)
|
||||
// Detect and set up NSO environment.
|
||||
if (ctx == NULL)
|
||||
{
|
||||
g_mainThreadHandle = main_thread;
|
||||
// Under NSO, we use svcExitProcess as the return address and hint all syscalls as available.
|
||||
g_isNso = true;
|
||||
|
||||
// For NSO we assume kernelhax thus access to all syscalls.
|
||||
g_syscallHints[0] = g_syscallHints[1] = -1ull;
|
||||
|
||||
g_mainThreadHandle = main_thread;
|
||||
g_loaderRetAddr = (LoaderReturnFn) &svcExitProcess;
|
||||
g_syscallHints[0] = g_syscallHints[1] = UINT64_MAX;
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse NRO config entries.
|
||||
// Save the loader return address.
|
||||
g_loaderRetAddr = saved_lr;
|
||||
|
||||
// Parse homebrew ABI config entries.
|
||||
ConfigEntry* ent = ctx;
|
||||
|
||||
while (ent->Key != EntryType_EndOfList)
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "services/set.h"
|
||||
#include "runtime/devices/fs_dev.h"
|
||||
|
||||
void* __stack_top;
|
||||
void NORETURN __nx_exit(Result rc, LoaderReturnFn retaddr);
|
||||
|
||||
void virtmemSetup(void);
|
||||
|
@ -1,68 +1,66 @@
|
||||
.section ".crt0","ax"
|
||||
.section .crt0, "ax", %progbits
|
||||
.global _start
|
||||
.align 2
|
||||
|
||||
_start:
|
||||
b startup
|
||||
b 1f
|
||||
.word __nx_mod0 - _start
|
||||
.ascii "HOMEBREW"
|
||||
|
||||
.org _start+0x80
|
||||
startup:
|
||||
// save lr
|
||||
mov x7, x30
|
||||
.org _start+0x80; 1:
|
||||
// Arguments on NSO entry:
|
||||
// x0=zero | x1=main thread handle
|
||||
// Arguments on NRO entry (homebrew ABI):
|
||||
// x0=ptr to env context | x1=UINT64_MAX (-1 aka 0xFFFFFFFFFFFFFFFF)
|
||||
// Arguments on user-mode exception entry:
|
||||
// x0=excpt type (non-zero) | x1=ptr to excpt context
|
||||
|
||||
// get aslr base
|
||||
bl +4
|
||||
sub x6, x30, #0x88
|
||||
|
||||
// context ptr and main thread handle
|
||||
mov x5, x0
|
||||
mov x4, x1
|
||||
|
||||
// Handle the exception if needed.
|
||||
// if (ctx != NULL && main_thread != -1)__libnx_exception_entry(<inargs>);
|
||||
cmp x5, #0
|
||||
ccmn x4, #1, #4, ne // 4 = Z
|
||||
beq bssclr_start
|
||||
// Detect and handle user-mode exceptions first:
|
||||
// if (x0 != 0 && x1 != UINT64_MAX) __libnx_exception_entry(<inargs>);
|
||||
cmp x0, #0
|
||||
ccmn x1, #1, #4, ne // 4 = Z
|
||||
beq .Lcrt0_main_entry
|
||||
b __libnx_exception_entry
|
||||
|
||||
bssclr_start:
|
||||
mov x27, x7
|
||||
mov x25, x5
|
||||
mov x26, x4
|
||||
.Lcrt0_main_entry:
|
||||
// Get pointer to MOD0 struct (contains offsets to important places)
|
||||
adr x28, __nx_mod0
|
||||
|
||||
// clear .bss
|
||||
adrp x0, __bss_start__
|
||||
adrp x1, __bss_end__
|
||||
add x0, x0, #:lo12:__bss_start__
|
||||
add x1, x1, #:lo12:__bss_end__
|
||||
sub x1, x1, x0 // calculate size
|
||||
add x1, x1, #7 // round up to 8
|
||||
bic x1, x1, #7
|
||||
// Calculate BSS address/size
|
||||
ldp w8, w9, [x28, #8] // load BSS start/end offset from MOD0
|
||||
sub w9, w9, w8 // calculate BSS size
|
||||
add w9, w9, #7 // round up to 8
|
||||
bic w9, w9, #7 // ^
|
||||
add x8, x28, x8 // fixup the start pointer
|
||||
|
||||
bss_loop:
|
||||
str xzr, [x0], #8
|
||||
subs x1, x1, #8
|
||||
bne bss_loop
|
||||
// Clear the BSS in 8-byte units
|
||||
1: subs w9, w9, #8
|
||||
str xzr, [x8], #8
|
||||
bne 1b
|
||||
|
||||
// store stack pointer
|
||||
mov x1, sp
|
||||
adrp x0, __stack_top
|
||||
str x1, [x0, #:lo12:__stack_top]
|
||||
// Preserve registers across function calls
|
||||
mov x25, x0 // entrypoint argument 0
|
||||
mov x26, x1 // entrypoint argument 1
|
||||
mov x27, x30 // loader return address
|
||||
|
||||
// process .dynamic section
|
||||
mov x0, x6
|
||||
adrp x1, _DYNAMIC
|
||||
add x1, x1, #:lo12:_DYNAMIC
|
||||
// Save initial stack pointer
|
||||
mov x8, sp
|
||||
adrp x9, __stack_top
|
||||
str x8, [x9, #:lo12:__stack_top]
|
||||
|
||||
// Parse ELF .dynamic section (which applies relocations to our module)
|
||||
adr x0, _start // get aslr base
|
||||
ldr w1, [x28, #4] // pointer to .dynamic section
|
||||
add x1, x28, x1
|
||||
bl __nx_dynamic
|
||||
|
||||
// initialize system
|
||||
// Perform system initialization
|
||||
mov x0, x25
|
||||
mov x1, x26
|
||||
mov x2, x27
|
||||
bl __libnx_init
|
||||
|
||||
// call entrypoint
|
||||
// Jump to the main function
|
||||
adrp x0, __system_argc // argc
|
||||
ldr w0, [x0, #:lo12:__system_argc]
|
||||
adrp x1, __system_argv // argv
|
||||
@ -74,12 +72,12 @@ bss_loop:
|
||||
.global __nx_exit
|
||||
.type __nx_exit, %function
|
||||
__nx_exit:
|
||||
// restore stack pointer
|
||||
// Restore stack pointer
|
||||
adrp x8, __stack_top
|
||||
ldr x8, [x8, #:lo12:__stack_top]
|
||||
mov sp, x8
|
||||
|
||||
// jump back to loader
|
||||
// Jump back to loader
|
||||
br x1
|
||||
|
||||
.global __nx_mod0
|
||||
@ -96,3 +94,10 @@ __nx_mod0:
|
||||
.ascii "LNY0"
|
||||
.word __got_start__ - __nx_mod0
|
||||
.word __got_end__ - __nx_mod0
|
||||
|
||||
.section .bss.__stack_top, "aw", %nobits
|
||||
.global __stack_top
|
||||
.align 3
|
||||
|
||||
__stack_top:
|
||||
.space 8
|
||||
|
Loading…
Reference in New Issue
Block a user