Add newlib syscalls.

This commit is contained in:
James Benton 2018-05-25 11:31:38 +01:00
parent 11adfb8f07
commit 5b8b60b390
7 changed files with 303 additions and 30 deletions

View File

@ -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

View File

@ -4,3 +4,4 @@ project(libraries C)
add_subdirectory(libdefaultheap)
add_subdirectory(libgfd)
add_subdirectory(libwhb)
add_subdirectory(wutnewlib)

View File

@ -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")

View File

@ -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

View File

@ -0,0 +1,181 @@
#include <wut.h>
#include <coreinit/atomic.h>
#include <coreinit/baseheap.h>
#include <coreinit/exit.h>
#include <coreinit/expandedheap.h>
#include <coreinit/mutex.h>
#include <coreinit/time.h>
#include <malloc.h>
#include <sys/errno.h>
#include <sys/iosupport.h>
#include <sys/reent.h>
#include <sys/time.h>
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();
}

View File

@ -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)

View File

@ -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)
}
}