From 5b8b60b39014f1b9f4ecb1d60e519411f6ee1d06 Mon Sep 17 00:00:00 2001 From: James Benton Date: Fri, 25 May 2018 11:31:38 +0100 Subject: [PATCH] Add newlib syscalls. --- README.md | 3 +- libraries/CMakeLists.txt | 1 + libraries/wutnewlib/CMakeLists.txt | 12 ++ libraries/wutnewlib/crt0.s | 15 +++ libraries/wutnewlib/syscalls.c | 181 +++++++++++++++++++++++++++++ share/wut.cmake | 14 ++- share/wut.ld | 107 +++++++++++++---- 7 files changed, 303 insertions(+), 30 deletions(-) create mode 100644 libraries/wutnewlib/CMakeLists.txt create mode 100644 libraries/wutnewlib/crt0.s create mode 100644 libraries/wutnewlib/syscalls.c diff --git a/README.md b/README.md index fdfb859..0017339 100644 --- a/README.md +++ b/README.md @@ -9,8 +9,7 @@ Licensed under the terms of the GNU General Public License, version 2 or later ( This branch is an WIP experimental rewrite to simplify how elf2rpl works and hopefully make it more correct for more advanced C++ programs. ## TODO: -- Bring back the old tools (readrpl etc) -- newlib / devoptab +- Maybe add fopen for sdcard ? ## Linux Requires CMake + Make + [devkitPPC](https://devkitpro.org/wiki/Getting_Started/devkitPPC) + libzdev diff --git a/libraries/CMakeLists.txt b/libraries/CMakeLists.txt index 18ef69b..3144b92 100644 --- a/libraries/CMakeLists.txt +++ b/libraries/CMakeLists.txt @@ -4,3 +4,4 @@ project(libraries C) add_subdirectory(libdefaultheap) add_subdirectory(libgfd) add_subdirectory(libwhb) +add_subdirectory(wutnewlib) diff --git a/libraries/wutnewlib/CMakeLists.txt b/libraries/wutnewlib/CMakeLists.txt new file mode 100644 index 0000000..6ae8885 --- /dev/null +++ b/libraries/wutnewlib/CMakeLists.txt @@ -0,0 +1,12 @@ +cmake_minimum_required(VERSION 3.2) +project(wutnewlib C) + +set_property(SOURCE crt0.s PROPERTY LANGUAGE C) + +add_library(wutnewlib + crt0.s + syscalls.c) +target_include_directories(wutnewlib PRIVATE "${WUT_ROOT}/include") + +install(TARGETS wutnewlib + ARCHIVE DESTINATION "${CMAKE_INSTALL_PREFIX}/lib") diff --git a/libraries/wutnewlib/crt0.s b/libraries/wutnewlib/crt0.s new file mode 100644 index 0000000..cb78f14 --- /dev/null +++ b/libraries/wutnewlib/crt0.s @@ -0,0 +1,15 @@ +.extern main +.extern exit +.extern __init_wut_newlibc + +.global _start +_start: + stwu 1, -0x8(1) + stw 3, 0(1) + stw 4, 4(1) + bl __init_wut_newlibc + lwz 3, 0(1) + lwz 4, 4(1) + bl main + addi 1, 1, 0x8 + b exit diff --git a/libraries/wutnewlib/syscalls.c b/libraries/wutnewlib/syscalls.c new file mode 100644 index 0000000..3acf34c --- /dev/null +++ b/libraries/wutnewlib/syscalls.c @@ -0,0 +1,181 @@ +#include + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +static OSMutex sMallocMutex; +static uint8_t *sHeapBase = NULL; +static uint32_t sHeapMaxSize = 0; +static volatile uint32_t sHeapSize = 0; + +void +__init_wut_newlibc(); + +static void * +__libwut_sbrk_r(struct _reent *r, + ptrdiff_t incr) +{ + uint32_t oldSize, newSize; + + do { + oldSize = sHeapSize; + newSize = oldSize + incr; + + if (newSize > sHeapMaxSize) { + r->_errno = ENOMEM; + return (void *)-1; + } + } while (!OSCompareAndSwapAtomic(&sHeapSize, oldSize, newSize)); + + return sHeapBase + oldSize; +} + +static int +__libwut_lock_init(int *lock, + int recursive) +{ + OSMutex *mutex = NULL; + if (!lock) { + return -1; + } + + mutex = (OSMutex *)malloc(sizeof(OSMutex)); + if (!mutex) { + return -1; + } + + OSInitMutex(mutex); + *lock = (int)mutex; + return 0; +} + +static int +__libwut_lock_close(int *lock) +{ + if (!lock || *lock == 0) { + return -1; + } + + free((void *)*lock); + *lock = 0; + return 0; +} + +static int +__libwut_lock_acquire(int *lock) +{ + OSMutex *mutex = (OSMutex *)*lock; + if (!lock || *lock == 0) { + return -1; + } + + OSLockMutex(mutex); + return 0; +} + +static int +__libwut_lock_release(int *lock) +{ + OSMutex *mutex = (OSMutex *)*lock; + if (!lock || *lock == 0) { + return -1; + } + + OSUnlockMutex(mutex); + return 0; +} + +static void +__libwut_malloc_lock(struct _reent *r) +{ + OSLockMutex(&sMallocMutex); +} + +static void +__libwut_malloc_unlock(struct _reent *r) +{ + OSUnlockMutex(&sMallocMutex); +} + +static void +__libwut_exit(int code) +{ + exit(code); +} + +static int +__libwut_gettod_r(struct _reent *ptr, + struct timeval *tp, + struct timezone *tz) +{ + OSCalendarTime tm; + OSTicksToCalendarTime(OSGetTime(), &tm); + + if (tp != NULL) { + tp->tv_sec = tm.tm_sec; + tp->tv_usec = tm.tm_usec + tm.tm_msec * 1000; + } + + if (tz != NULL) { + tz->tz_minuteswest = 0; + tz->tz_dsttime = 0; + } + + return 0; +} + +static void +__init_malloc_lock() +{ + OSInitMutex(&sMallocMutex); +} + +static void +__init_libc_heap() +{ + MEMExpandedHeap *heap = (MEMExpandedHeap *)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2); + uint32_t freeSize = MEMGetAllocatableSizeForExpHeapEx(heap, 0x1000); + + sHeapMaxSize = (uint32_t)(0.9f * (float)freeSize) & ~0xFFF; + sHeapBase = (uint8_t *)MEMAllocFromExpHeapEx(heap, sHeapMaxSize, 0x1000); + sHeapSize = 0; +} + +static void +__free_libc_heap() +{ + MEMExpandedHeap *heap = (MEMExpandedHeap *)MEMGetBaseHeapHandle(MEM_BASE_HEAP_MEM2); + MEMFreeToExpHeap(heap, sHeapBase); +} + +static void +__init_syscall_array() +{ + __syscalls.sbrk_r = __libwut_sbrk_r; + __syscalls.lock_init = __libwut_lock_init; + __syscalls.lock_close = __libwut_lock_close; + __syscalls.lock_acquire = __libwut_lock_acquire; + __syscalls.lock_release = __libwut_lock_release; + __syscalls.malloc_lock = __libwut_malloc_lock; + __syscalls.malloc_unlock = __libwut_malloc_unlock; + __syscalls.exit = __libwut_exit; + __syscalls.gettod_r = __libwut_gettod_r; +} + +void +__init_wut_newlibc() +{ + __init_libc_heap(); + __init_malloc_lock(); + __init_syscall_array(); +} diff --git a/share/wut.cmake b/share/wut.cmake index 27bdb61..7f306f4 100644 --- a/share/wut.cmake +++ b/share/wut.cmake @@ -1,10 +1,14 @@ cmake_minimum_required(VERSION 3.2) macro(wut_create_rpx target source) - add_custom_target(${target} ALL - COMMAND ${WUT_ELF2RPL} ${source} ${target} - DEPENDS ${source} - COMMENT "Converting to RPX ${target}" - ) + target_link_libraries(${source} + wutnewlib + coreinit) + + add_custom_target(${target} ALL + COMMAND ${WUT_ELF2RPL} ${source} ${target} + DEPENDS ${source} + COMMENT "Converting to RPX ${target}") + add_dependencies(${target} ${source}) endmacro(wut_create_rpx) diff --git a/share/wut.ld b/share/wut.ld index 8fd94f5..3929375 100644 --- a/share/wut.ld +++ b/share/wut.ld @@ -8,8 +8,8 @@ MEMORY { loadmem (rwx) : ORIGIN = 0xC0000000, LENGTH = 128M } -EXTERN(main) -ENTRY(main) +EXTERN(_start) +ENTRY(_start) SECTIONS { @@ -19,76 +19,135 @@ SECTIONS } > codemem .text ALIGN(32) : { - *(.text .text.*) - *(.init) - *(.fini) + KEEP (*crt0.o(*.init)) + KEEP (*(.init)) + + *(.text) + *(.text.*) + *(.gnu.warning) + *(.gnu.linkonce.t.*) + + KEEP (*(.fini)) } > codemem . = ORIGIN(datamem); .rodata ALIGN(32) : { - *(.rodata .rodata.*) - *(.ctors) - *(.dtors) + *(.rodata) + *(.rodata.*) + *(.gnu.linkonce.r.*) + + *(.preinit_array) *(.init_array) *(.fini_array) + + KEEP (*crtbegin.o(.ctors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .ctors)) + KEEP (*(SORT(.ctors.*))) + KEEP (*(.ctors)) + + KEEP (*crtbegin.o(.dtors)) + KEEP (*(EXCLUDE_FILE (*crtend.o ) .dtors)) + KEEP (*(SORT(.dtors.*))) + KEEP (*(.dtors)) + *(.jcr) - *(.gcc_except_table .gcc_except_table.*) + *(.dynamic) *(.eh_frame_hdr) - *(.eh_frame) + KEEP (*(.eh_frame)) + *(.fixup) + *(.gcc_except_table) + *(.gcc_except_table.*) *(.got) *(.got1) *(.got2) + *(.got.plt) + *(.plt) *(.tm_clone_table) } > datamem .data ALIGN(32) : { - *(.data .data.*) + *(.data) + *(.data.*) + *(.gnu.linkonce.d.*) + SORT(CONSTRUCTORS) . = ALIGN(32); __sdata_start = .; - *(.sdata .sdata.*) + *(.sdata) + *(.sdata.*) + *(.gnu.linkonce.s.*) + . = ALIGN(32); __sdata_end = .; - . = ALIGN(32); __sdata2_start = .; - *(.sdata2 .sdata2.*) + *(.sdata2) + *(.sdata2.*) + *(.gnu.linkonce.s2.*) + . = ALIGN(32); __sdata2_end = .; } > datamem __bss_start = .; .bss ALIGN(64) : { - *(.bss .bss.*) + *(.dynbss) + *(.bss) + *(.bss.*) + *(.gnu.linkonce.b.*) + *(COMMON) . = ALIGN(64); __sbss_start = .; - *(.sbss .sbss.*) + *(.dynsbss) + *(.sbss) + *(.sbss.*) + *(.gnu.linkonce.sb.*) + *(.scommon) __sbss_end = .; . = ALIGN(64); __sbss2_start = .; - *(.sbss2 .sbss2.*) + *(.sbss2) + *(.sbss2.*) + *(.gnu.linkonce.sb2.*) __sbss2_end = .; + + + . = ALIGN(32); } __bss_end = .; . = ORIGIN(relmem); .rela.text ALIGN(4) : { - *(.rela.text .rela.text.*) + *(.rela.text) + *(.rela.text.*) + *(.rela.gnu.linkonce.t.*) *(.rela.init) *(.rela.fini) } > relmem .rela.data ALIGN(4) : { - *(.rela.data .rela.data.*) + *(.rela.data) + *(.rela.data.*) + *(.rela.gnu.linkonce.d.*) *(.rela.sdata) + *(.rela.gnu.linkonce.s.*) *(.rela.sdata2) + *(.rela.gnu.linkonce.s2.*) *(.rela.init_array) *(.rela.fini_array) *(.rela.gcc_except_table .rela.gcc_except_table.*) *(.rela.eh_frame) + *(.rela.got) + *(.rela.got1) *(.rela.got2) + *(.rela.got.plt) + *(.rela.plt) } > relmem .rela.rodata ALIGN(4) : { - *(.rela.rodata .rela.rodata.*) + *(.rela.rodata) + *(.rela.rodata.*) + *(.rel.gnu.linkonce.r.*) + *(.rela.ctors) + *(.rela.dtors) } > relmem . = ORIGIN(loadmem); @@ -137,9 +196,11 @@ SECTIONS _SDA2_BASE_ = __sdata2_start + ((__sbss2_end - __sdata2_start) / 2); /DISCARD/ : { - *(.comment) - *(.fixup) - *(.gnu.attributes) *(.abs) + *(.comment) + *(.gnu.attributes) + *(.gnu.version) + *(.gnu.version_d) + *(.gnu.version_r) } }