From 2ae326d6a487bdf0eac8359ec8b1d12cb35a1bde Mon Sep 17 00:00:00 2001 From: aliaspider Date: Fri, 6 Nov 2015 12:21:37 +0100 Subject: [PATCH 1/3] expand the original stack to __stacksize__ instead of moving sp to a different buffer. --- libctru/source/system/allocateHeaps.c | 24 ++++++++++- libctru/source/system/ctru_exit.c | 19 ++++++++- libctru/source/system/initSystem.c | 10 +++++ libctru/source/system/stack_adjust.s | 57 --------------------------- 4 files changed, 50 insertions(+), 60 deletions(-) delete mode 100644 libctru/source/system/stack_adjust.s diff --git a/libctru/source/system/allocateHeaps.c b/libctru/source/system/allocateHeaps.c index 44bbe63..f09b285 100644 --- a/libctru/source/system/allocateHeaps.c +++ b/libctru/source/system/allocateHeaps.c @@ -7,18 +7,38 @@ u32 __linear_heap; u32 __heapBase; extern u32 __heap_size, __linear_heap_size; +u32 __attribute__((weak)) __stacksize__ = 0x8000; +u32 __stack_bottom; +u32 __allocated_stack_size; + +void __system_allocateStack() { + u32 tmp=0; + MemInfo memInfo; + PageInfo pageInfo; + + register u32 sp_val __asm__("sp"); + svcQueryMemory(&memInfo, &pageInfo, sp_val); + + __stacksize__ += 0xFFF; + __stacksize__ &= ~0xFFF; + __allocated_stack_size = __stacksize__ > memInfo.size ? __stacksize__ - memInfo.size: 0; + __stack_bottom = memInfo.base_addr - __allocated_stack_size; + + if (__allocated_stack_size) + svcControlMemory(&tmp, __stack_bottom, 0x0, __allocated_stack_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); +} void __attribute__((weak)) __system_allocateHeaps() { u32 tmp=0; // Allocate the application heap __heapBase = 0x08000000; - svcControlMemory(&tmp, __heapBase, 0x0, __heap_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); + svcControlMemory(&tmp, __heapBase, 0x0, __heap_size - __allocated_stack_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); // Allocate the linear heap svcControlMemory(&__linear_heap, 0x0, 0x0, __linear_heap_size, MEMOP_ALLOC_LINEAR, MEMPERM_READ | MEMPERM_WRITE); // Set up newlib heap fake_heap_start = (char*)__heapBase; - fake_heap_end = fake_heap_start + __heap_size; + fake_heap_end = fake_heap_start + __heap_size - __allocated_stack_size; } \ No newline at end of file diff --git a/libctru/source/system/ctru_exit.c b/libctru/source/system/ctru_exit.c index 41c5acd..f50139b 100644 --- a/libctru/source/system/ctru_exit.c +++ b/libctru/source/system/ctru_exit.c @@ -4,6 +4,8 @@ extern u32 __linear_heap; extern u32 __heapBase; extern u32 __heap_size, __linear_heap_size; +extern u32 __stack_bottom; +extern u32 __allocated_stack_size; extern void (*__system_retAddr)(void); void __destroy_handle_list(void); @@ -21,7 +23,7 @@ void __attribute__((weak)) __attribute__((noreturn)) __libctru_exit(int rc) svcControlMemory(&tmp, __linear_heap, 0x0, __linear_heap_size, MEMOP_FREE, 0x0); // Unmap the application heap - svcControlMemory(&tmp, __heapBase, 0x0, __heap_size, MEMOP_FREE, 0x0); + svcControlMemory(&tmp, __heapBase, 0x0, __heap_size - __allocated_stack_size, MEMOP_FREE, 0x0); // Close some handles __destroy_handle_list(); @@ -36,3 +38,18 @@ void __attribute__((weak)) __attribute__((noreturn)) __libctru_exit(int rc) // Since above did not jump, end this process svcExitProcess(); } + +void __system_deallocateStack() { + u32 tmp=0; + + if (__allocated_stack_size) + svcControlMemory(&tmp, __stack_bottom, 0x0, __allocated_stack_size, MEMOP_FREE, 0x0); +} + +void __attribute__((noreturn)) __ctru_exit(int rc) +{ + __libc_fini_array(); + __appExit(); + __system_deallocateStack(); + __libctru_exit(rc); +} diff --git a/libctru/source/system/initSystem.c b/libctru/source/system/initSystem.c index 98c5837..9991c86 100644 --- a/libctru/source/system/initSystem.c +++ b/libctru/source/system/initSystem.c @@ -10,9 +10,11 @@ void (*__system_retAddr)(void); // Data from _prm structure extern void* __service_ptr; // used to detect if we're run from a homebrew launcher +void __system_allocateStack(); void __system_allocateHeaps(); void __system_initArgv(); void __appInit(); +void __libc_init_array(); void __ctru_exit(int rc); @@ -32,9 +34,17 @@ void __attribute__((weak)) __libctru_init(void (*retAddr)(void)) if (__sync_init) __sync_init(); + __system_allocateStack(); __system_allocateHeaps(); // Build argc/argv if present __system_initArgv(); } + +void initSystem(void (*retAddr)(void)) +{ + __libctru_init(retAddr); + __appInit(); + __libc_init_array(); +} diff --git a/libctru/source/system/stack_adjust.s b/libctru/source/system/stack_adjust.s deleted file mode 100644 index 2d15767..0000000 --- a/libctru/source/system/stack_adjust.s +++ /dev/null @@ -1,57 +0,0 @@ - - .arm - .align 2 - - .global initSystem - .type initSystem, %function - -initSystem: - ldr r2, =saved_stack - str sp, [r2] - str lr, [r2,#4] - - bl __libctru_init - - ldr r2, =fake_heap_start - ldr sp, [r2] - - ldr r3, =__stacksize__ - ldr r3, [r3] - add sp, sp, r3 - add sp, sp, #7 - bics sp, sp, #7 - str sp, [r2] - - - bl __appInit - bl __libc_init_array - - ldr r2, =saved_stack - ldr lr, [r2,#4] - bx lr - - - .global __ctru_exit - .type __ctru_exit, %function - -__ctru_exit: - bl __libc_fini_array - bl __appExit - - ldr r2, =saved_stack - ldr sp, [r2] - b __libctru_exit - - .data - .align 2 -__stacksize__: - .word 32 * 1024 - .weak __stacksize__ - - - .bss - .align 2 -saved_stack: - .space 8 - - From 9e264473e9e1a463c154956ab8adee32b8c9f935 Mon Sep 17 00:00:00 2001 From: aliaspider Date: Fri, 6 Nov 2015 18:31:59 +0100 Subject: [PATCH 2/3] add some safety checks when extending the stack. --- libctru/source/system/allocateHeaps.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/libctru/source/system/allocateHeaps.c b/libctru/source/system/allocateHeaps.c index f09b285..83505ac 100644 --- a/libctru/source/system/allocateHeaps.c +++ b/libctru/source/system/allocateHeaps.c @@ -13,16 +13,37 @@ u32 __allocated_stack_size; void __system_allocateStack() { u32 tmp=0; + u32 original_stack_bottom; + u32 original_stack_size; MemInfo memInfo; PageInfo pageInfo; register u32 sp_val __asm__("sp"); svcQueryMemory(&memInfo, &pageInfo, sp_val); + original_stack_bottom = memInfo.base_addr; + original_stack_size = memInfo.size; + + svcQueryMemory(&memInfo, &pageInfo, original_stack_bottom - 0x1000); + + if (memInfo.state != MEMSTATE_FREE) + { + original_stack_bottom = memInfo.base_addr; + original_stack_size += memInfo.size; + svcQueryMemory(&memInfo, &pageInfo, original_stack_bottom - 0x1000); + } + + if (memInfo.state != MEMSTATE_FREE) + { + __allocated_stack_size = 0; + return; + } __stacksize__ += 0xFFF; __stacksize__ &= ~0xFFF; - __allocated_stack_size = __stacksize__ > memInfo.size ? __stacksize__ - memInfo.size: 0; - __stack_bottom = memInfo.base_addr - __allocated_stack_size; + __allocated_stack_size = __stacksize__ > original_stack_size ? __stacksize__ - original_stack_size: 0; + __allocated_stack_size = __allocated_stack_size > memInfo.size ? memInfo.size : __allocated_stack_size; + __stacksize__ = original_stack_size + __allocated_stack_size; + __stack_bottom = original_stack_bottom - __allocated_stack_size; if (__allocated_stack_size) svcControlMemory(&tmp, __stack_bottom, 0x0, __allocated_stack_size, MEMOP_ALLOC, MEMPERM_READ | MEMPERM_WRITE); From 156a82b8a391e22454591e77de5521169d319bf4 Mon Sep 17 00:00:00 2001 From: aliaspider Date: Fri, 6 Nov 2015 19:39:24 +0100 Subject: [PATCH 3/3] only the check for the segment's size under the original stack is actually needed. --- libctru/source/system/allocateHeaps.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/libctru/source/system/allocateHeaps.c b/libctru/source/system/allocateHeaps.c index 83505ac..e00bf8b 100644 --- a/libctru/source/system/allocateHeaps.c +++ b/libctru/source/system/allocateHeaps.c @@ -25,19 +25,6 @@ void __system_allocateStack() { svcQueryMemory(&memInfo, &pageInfo, original_stack_bottom - 0x1000); - if (memInfo.state != MEMSTATE_FREE) - { - original_stack_bottom = memInfo.base_addr; - original_stack_size += memInfo.size; - svcQueryMemory(&memInfo, &pageInfo, original_stack_bottom - 0x1000); - } - - if (memInfo.state != MEMSTATE_FREE) - { - __allocated_stack_size = 0; - return; - } - __stacksize__ += 0xFFF; __stacksize__ &= ~0xFFF; __allocated_stack_size = __stacksize__ > original_stack_size ? __stacksize__ - original_stack_size: 0;