mirror of
https://github.com/decompals/wibo.git
synced 2025-12-11 22:43:58 +00:00
- Removes blockUpper2GB hack; we now start early in the process and reserve all (available) space in the lower 2GB address space, leaving the upper 2GB untouched for host code - All virtual memory operations flow through wibo::heap for bookkeeping - All guest code uses a guest mimalloc area + thread-local heaps reserved in the guest address space
370 lines
9.0 KiB
C++
370 lines
9.0 KiB
C++
#include "crt.h"
|
|
|
|
#include "common.h"
|
|
#include "context.h"
|
|
#include "crt_trampolines.h"
|
|
#include "heap.h"
|
|
#include "kernel32/internal.h"
|
|
#include "modules.h"
|
|
|
|
#include <csignal>
|
|
#include <cstdarg>
|
|
#include <cstdio>
|
|
#include <cstdlib>
|
|
#include <cstring>
|
|
#include <unistd.h>
|
|
#include <vector>
|
|
|
|
namespace crt {
|
|
|
|
int _commode = 0;
|
|
int _fmode = 0;
|
|
|
|
std::vector<_PVFV> atexitFuncs;
|
|
_invalid_parameter_handler invalidParameterHandler = nullptr;
|
|
|
|
void CDECL _initterm(const _PVFV *ppfn, const _PVFV *end) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("_initterm(%p, %p)\n", ppfn, end);
|
|
do {
|
|
if (_PVFV pfn = *++ppfn) {
|
|
DEBUG_LOG("-> calling %p\n", pfn);
|
|
call__PVFV(pfn);
|
|
}
|
|
} while (ppfn < end);
|
|
}
|
|
|
|
int CDECL _initterm_e(const _PIFV *ppfn, const _PIFV *end) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("_initterm_e(%p, %p)\n", ppfn, end);
|
|
do {
|
|
if (_PIFV pfn = *++ppfn) {
|
|
DEBUG_LOG("-> calling %p\n", pfn);
|
|
int err = call__PIFV(pfn);
|
|
if (err)
|
|
return err;
|
|
}
|
|
} while (ppfn < end);
|
|
|
|
return 0;
|
|
}
|
|
|
|
void CDECL _set_app_type(_crt_app_type type) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("STUB: _set_app_type(%i)\n", type);
|
|
}
|
|
|
|
int CDECL _set_fmode(int mode) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("_set_fmode(%i)\n", mode);
|
|
_fmode = mode;
|
|
return 0;
|
|
}
|
|
|
|
int *CDECL __p__commode() {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("__p__commode()\n");
|
|
return &_commode;
|
|
}
|
|
|
|
int *CDECL __p__fmode() {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("__p__fmode()\n");
|
|
return &_fmode;
|
|
}
|
|
|
|
int CDECL _crt_atexit(void (*func)()) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("_crt_atexit(%p)\n", func);
|
|
atexitFuncs.push_back(func);
|
|
return 0;
|
|
}
|
|
|
|
int CDECL _configure_narrow_argv(_crt_argv_mode mode) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("STUB: _configure_narrow_argv(%i)\n", mode);
|
|
return 0;
|
|
}
|
|
|
|
_invalid_parameter_handler CDECL _set_invalid_parameter_handler(_invalid_parameter_handler newHandler) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("STUB: _set_invalid_parameter_handler(%p)\n", newHandler);
|
|
_invalid_parameter_handler oldHandler = invalidParameterHandler;
|
|
invalidParameterHandler = newHandler;
|
|
return oldHandler;
|
|
}
|
|
|
|
int CDECL _controlfp_s(unsigned int *currentControl, unsigned int newControl, unsigned int mask) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("STUB: _controlfp_s(%p, %u, %u)\n", currentControl, newControl, mask);
|
|
return 0;
|
|
}
|
|
|
|
int CDECL _configthreadlocale(int per_thread_locale_type) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("STUB: _configthreadlocale(%i)\n", per_thread_locale_type);
|
|
return 0;
|
|
}
|
|
|
|
int CDECL _initialize_narrow_environment() {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("STUB: _initialize_narrow_environment()\n");
|
|
return 0;
|
|
}
|
|
|
|
int CDECL _set_new_mode(int newhandlermode) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("STUB: _set_new_mode(%i)\n", newhandlermode);
|
|
return 0;
|
|
}
|
|
|
|
char **CDECL _get_initial_narrow_environment() {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("_get_initial_narrow_environment()\n");
|
|
return environ;
|
|
}
|
|
|
|
char ***CDECL __p__environ() {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("__p__environ()\n");
|
|
return &environ;
|
|
}
|
|
|
|
char ***CDECL __p___argv() {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("__p___argv()\n");
|
|
return &wibo::argv;
|
|
}
|
|
|
|
int *CDECL __p___argc() {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("__p___argc()\n");
|
|
return &wibo::argc;
|
|
}
|
|
|
|
SIZE_T CDECL strlen(const char *str) {
|
|
HOST_CONTEXT_GUARD();
|
|
VERBOSE_LOG("strlen(%p)\n", str);
|
|
return ::strlen(str);
|
|
}
|
|
|
|
int CDECL strcmp(const char *lhs, const char *rhs) {
|
|
HOST_CONTEXT_GUARD();
|
|
VERBOSE_LOG("strcmp(%p, %p)\n", lhs, rhs);
|
|
return ::strcmp(lhs, rhs);
|
|
}
|
|
|
|
int CDECL strncmp(const char *lhs, const char *rhs, SIZE_T count) {
|
|
HOST_CONTEXT_GUARD();
|
|
VERBOSE_LOG("strncmp(%p, %p, %zu)\n", lhs, rhs, count);
|
|
return ::strncmp(lhs, rhs, count);
|
|
}
|
|
|
|
char *CDECL strcpy(char *dest, const char *src) {
|
|
HOST_CONTEXT_GUARD();
|
|
VERBOSE_LOG("strcpy(%p, %p)\n", dest, src);
|
|
return ::strcpy(dest, src);
|
|
}
|
|
|
|
char *CDECL strncpy(char *dest, const char *src, SIZE_T count) {
|
|
HOST_CONTEXT_GUARD();
|
|
VERBOSE_LOG("strncpy(%p, %p, %zu)\n", dest, src, count);
|
|
return ::strncpy(dest, src, count);
|
|
}
|
|
|
|
const char *CDECL strrchr(const char *str, int ch) {
|
|
HOST_CONTEXT_GUARD();
|
|
VERBOSE_LOG("strrchr(%p, %i)\n", str, ch);
|
|
return ::strrchr(str, ch);
|
|
}
|
|
|
|
void *CDECL malloc(SIZE_T size) {
|
|
HOST_CONTEXT_GUARD();
|
|
VERBOSE_LOG("malloc(%zu)\n", size);
|
|
return wibo::heap::guestMalloc(size);
|
|
}
|
|
|
|
void *CDECL calloc(SIZE_T count, SIZE_T size) {
|
|
HOST_CONTEXT_GUARD();
|
|
VERBOSE_LOG("calloc(%zu, %zu)\n", count, size);
|
|
return wibo::heap::guestCalloc(count, size);
|
|
}
|
|
|
|
void *CDECL realloc(void *ptr, SIZE_T newSize) {
|
|
HOST_CONTEXT_GUARD();
|
|
VERBOSE_LOG("realloc(%p, %zu)\n", ptr, newSize);
|
|
return wibo::heap::guestRealloc(ptr, newSize);
|
|
}
|
|
|
|
void CDECL free(void *ptr) {
|
|
HOST_CONTEXT_GUARD();
|
|
VERBOSE_LOG("free(%p)\n", ptr);
|
|
wibo::heap::guestFree(ptr);
|
|
}
|
|
|
|
void *CDECL memcpy(void *dest, const void *src, SIZE_T count) {
|
|
HOST_CONTEXT_GUARD();
|
|
VERBOSE_LOG("memcpy(%p, %p, %zu)\n", dest, src, count);
|
|
return std::memcpy(dest, src, count);
|
|
}
|
|
|
|
void *CDECL memmove(void *dest, const void *src, SIZE_T count) {
|
|
HOST_CONTEXT_GUARD();
|
|
VERBOSE_LOG("memmove(%p, %p, %zu)\n", dest, src, count);
|
|
return std::memmove(dest, src, count);
|
|
}
|
|
|
|
void *CDECL memset(void *dest, int ch, SIZE_T count) {
|
|
HOST_CONTEXT_GUARD();
|
|
VERBOSE_LOG("memset(%p, %i, %zu)\n", dest, ch, count);
|
|
return std::memset(dest, ch, count);
|
|
}
|
|
|
|
int CDECL memcmp(const void *lhs, const void *rhs, SIZE_T count) {
|
|
HOST_CONTEXT_GUARD();
|
|
VERBOSE_LOG("memcmp(%p, %p, %zu)\n", lhs, rhs, count);
|
|
return std::memcmp(lhs, rhs, count);
|
|
}
|
|
|
|
int CDECL __setusermatherr(void *handler) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("STUB: __setusermatherr(%p)\n", handler);
|
|
return 0;
|
|
}
|
|
|
|
int CDECL _initialize_onexit_table(void *table) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("STUB: _initialize_onexit_table(%p)\n", table);
|
|
wibo::registerOnExitTable(table);
|
|
return 0;
|
|
}
|
|
|
|
int CDECL _register_onexit_function(void *table, void (*func)()) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("STUB: _register_onexit_function(%p, %p)\n", table, func);
|
|
wibo::addOnExitFunction(table, func);
|
|
return 0;
|
|
}
|
|
|
|
int CDECL _execute_onexit_table(void *table) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("STUB: _execute_onexit_table(%p)\n", table);
|
|
wibo::executeOnExitTable(table);
|
|
return 0;
|
|
}
|
|
|
|
void CDECL exit(int status) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("exit(%i)\n", status);
|
|
for (auto it = atexitFuncs.rbegin(); it != atexitFuncs.rend(); ++it) {
|
|
DEBUG_LOG("Calling atexit function %p\n", *it);
|
|
call__PVFV(*it);
|
|
}
|
|
kernel32::exitInternal(status);
|
|
}
|
|
|
|
void CDECL _cexit() {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("_cexit()\n");
|
|
for (auto it = atexitFuncs.rbegin(); it != atexitFuncs.rend(); ++it) {
|
|
DEBUG_LOG("Calling atexit function %p\n", *it);
|
|
call__PVFV(*it);
|
|
}
|
|
}
|
|
|
|
void CDECL _exit(int status) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("_exit(%i)\n", status);
|
|
kernel32::exitInternal(status);
|
|
}
|
|
|
|
void CDECL abort() {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("abort()\n");
|
|
std::abort();
|
|
}
|
|
|
|
signal_handler CDECL signal(int signum, signal_handler handler) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("signal(%i, %p)\n", signum, handler);
|
|
return std::signal(signum, handler);
|
|
}
|
|
|
|
void *CDECL __acrt_iob_func(unsigned int index) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("__acrt_iob_func(%u)\n", index);
|
|
if (index == 0)
|
|
return stdin;
|
|
if (index == 1)
|
|
return stdout;
|
|
if (index == 2)
|
|
return stderr;
|
|
return nullptr;
|
|
}
|
|
|
|
int CDECL __stdio_common_vfprintf(unsigned long long options, FILE *stream, const char *format, void *locale,
|
|
va_list args) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("__stdio_common_vfprintf(%llu, %p, %s, %p, %p)\n", options, stream, format, locale, args);
|
|
return vfprintf(stream, format, args);
|
|
}
|
|
|
|
int CDECL __stdio_common_vsprintf(unsigned long long options, char *buffer, SIZE_T len, const char *format,
|
|
void *locale, va_list args) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("__stdio_common_vsprintf(%llu, %p, %zu, %s, %p, ...)\n", options, buffer, len, format, locale);
|
|
if (!buffer || !format)
|
|
return -1;
|
|
int result = vsnprintf(buffer, len, format, args);
|
|
if (result < 0)
|
|
return -1;
|
|
if (len > 0 && static_cast<SIZE_T>(result) >= len)
|
|
return -1;
|
|
return result;
|
|
}
|
|
|
|
static thread_local sort_compare currentCompare = nullptr;
|
|
|
|
static int doCompare(const void *a, const void *b) { return call_sort_compare(currentCompare, a, b); }
|
|
|
|
void CDECL qsort(void *base, SIZE_T num, SIZE_T size, sort_compare compare) {
|
|
HOST_CONTEXT_GUARD();
|
|
DEBUG_LOG("qsort(%p, %zu, %zu, %p)\n", base, num, size, compare);
|
|
currentCompare = compare;
|
|
::qsort(base, num, size, doCompare);
|
|
}
|
|
|
|
int CDECL puts(const char *str) {
|
|
HOST_CONTEXT_GUARD();
|
|
if (!str) {
|
|
str = "(null)";
|
|
}
|
|
DEBUG_LOG("puts(%s)\n", str);
|
|
if (std::fputs(str, stdout) < 0)
|
|
return EOF;
|
|
if (std::fputc('\n', stdout) == EOF)
|
|
return EOF;
|
|
return 0;
|
|
}
|
|
|
|
} // namespace crt
|
|
|
|
#include "crt_trampolines.h"
|
|
|
|
extern const wibo::ModuleStub lib_crt = {
|
|
(const char *[]){
|
|
"api-ms-win-crt-heap-l1-1-0",
|
|
"api-ms-win-crt-locale-l1-1-0",
|
|
"api-ms-win-crt-runtime-l1-1-0",
|
|
"api-ms-win-crt-stdio-l1-1-0",
|
|
"api-ms-win-crt-string-l1-1-0",
|
|
"api-ms-win-crt-environment-l1-1-0",
|
|
"api-ms-win-crt-math-l1-1-0",
|
|
"api-ms-win-crt-private-l1-1-0",
|
|
"api-ms-win-crt-utility-l1-1-0",
|
|
nullptr,
|
|
},
|
|
crtThunkByName,
|
|
nullptr,
|
|
};
|