#define _LARGEFILE_SOURCE 1
#define _FILE_OFFSET_BITS 64
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdio.h>
#include <stddef.h>
#include <string.h>
#include <wchar.h>
#include <dlfcn.h>
#include <signal.h>
#include <errno.h>
#include <err.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/select.h>
#include <unistd.h>
#include <fcntl.h>
#include <glob.h>
#include <ctype.h>
#include <dirent.h>
#include <search.h>
#include <sys/types.h>
#include <poll.h>
#include <sys/epoll.h>
#include <ftw.h>
#include <sys/syscall.h>
#include <sys/socket.h>
#include <sys/utsname.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <setjmp.h>
#include <sys/vfs.h>
#include <spawn.h>
#include <fts.h>
#include <syslog.h>
#include <malloc.h>
#include <getopt.h>
#include <sys/resource.h>
#include <sys/prctl.h>
#include <sys/ptrace.h>
#undef LOG_INFO
#undef LOG_DEBUG
#include "wrappedlibs.h"
#include "box64stack.h"
#include "x64emu.h"
#include "debug.h"
#include "wrapper.h"
#include "bridge.h"
#include "callback.h"
#include "librarian.h"
#include "librarian/library_private.h"
#include "emu/x64emu_private.h"
#include "box64context.h"
#include "myalign.h"
#include "signals.h"
#include "fileutils.h"
#include "auxval.h"
#include "elfloader.h"
#include "bridge.h"
#include "globalsymbols.h"
#include "rcfile.h"
#ifndef LOG_INFO
#define LOG_INFO 1
#endif
#ifndef LOG_DEBUG
#define LOG_DEBUG 2
#endif
#define LIBNAME libc
const char* libcName =
#ifdef ANDROID
"libc.so"
#else
"libc.so.6"
#endif
;
typedef int (*iFi_t)(int);
typedef int (*iFp_t)(void*);
typedef int (*iFL_t)(unsigned long);
typedef void (*vFpp_t)(void*, void*);
typedef void (*vFipp_t)(int32_t, void*, void*);
typedef int32_t (*iFpi_t)(void*, int32_t);
typedef int32_t (*iFpp_t)(void*, void*);
typedef int32_t (*iFpL_t)(void*, size_t);
typedef int32_t (*iFiip_t)(int32_t, int32_t, void*);
typedef int32_t (*iFipp_t)(int32_t, void*, void*);
typedef int32_t (*iFppi_t)(void*, void*, int32_t);
typedef int32_t (*iFpup_t)(void*, uint32_t, void*);
typedef int32_t (*iFpuu_t)(void*, uint32_t, uint32_t);
typedef int32_t (*iFiiII_t)(int, int, int64_t, int64_t);
typedef int32_t (*iFiiiV_t)(int, int, int, ...);
typedef int32_t (*iFippi_t)(int32_t, void*, void*, int32_t);
typedef int32_t (*iFpppp_t)(void*, void*, void*, void*);
typedef int32_t (*iFpipp_t)(void*, int32_t, void*, void*);
typedef int32_t (*iFppii_t)(void*, void*, int32_t, int32_t);
typedef int32_t (*iFipuu_t)(int32_t, void*, uint32_t, uint32_t);
typedef int32_t (*iFipiI_t)(int32_t, void*, int32_t, int64_t);
typedef int32_t (*iFipuup_t)(int32_t, void*, uint32_t, uint32_t, void*);
typedef int32_t (*iFiiV_t)(int32_t, int32_t, ...);
typedef void* (*pFp_t)(void*);
typedef void* (*pFpip_t)(void*, int, void*);
#define SUPER() \
GO(_ITM_addUserCommitAction, iFpup_t) \
GO(_IO_file_stat, iFpp_t) \
GO(fts64_open, pFpip_t) \
GO(register_printf_specifier, iFipp_t) \
GO(register_printf_type, iFp_t)
#include "wrappercallback.h"
static int regs_abi[] = {_DI, _SI, _DX, _CX, _R8, _R9};
void* getVargN(x64emu_t *emu, int n)
{
if(n<6)
return (void*)emu->regs[regs_abi[n]].q[0];
return ((void**)R_RSP)[1+n-6];
}
#define SUPER() \
GO(0) \
GO(1) \
GO(2) \
GO(3) \
GO(4) \
GO(5) \
GO(6) \
GO(7) \
GO(8) \
GO(9) \
GO(10) \
GO(11) \
GO(12) \
GO(13) \
GO(14) \
GO(15)
#define GO(A) \
static uintptr_t my_compare_fct_##A = 0; \
static int my_compare_##A(void* a, void* b) \
{ \
return (int)RunFunctionFmt(my_compare_fct_##A, "pp", a, b); \
}
SUPER()
#undef GO
static void* findcompareFct(void* fct)
{
if(!fct) return NULL;
void* p;
if((p = GetNativeFnc((uintptr_t)fct))) return p;
#define GO(A) if(my_compare_fct_##A == (uintptr_t)fct) return my_compare_##A;
SUPER()
#undef GO
#define GO(A) if(my_compare_fct_##A == 0) {my_compare_fct_##A = (uintptr_t)fct; return my_compare_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for libc compare callback\n");
return NULL;
}
#define GO(A) \
static uintptr_t my_action_fct_##A = 0; \
static void my_action_##A(void* a, uint32_t b, int c) \
{ \
RunFunctionFmt(my_action_fct_##A, "pui", a, b, c); \
}
SUPER()
#undef GO
static void* findactionFct(void* fct)
{
if(!fct) return NULL;
void* p;
if((p = GetNativeFnc((uintptr_t)fct))) return p;
#define GO(A) if(my_action_fct_##A == (uintptr_t)fct) return my_action_##A;
SUPER()
#undef GO
#define GO(A) if(my_action_fct_##A == 0) {my_action_fct_##A = (uintptr_t)fct; return my_action_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for libc action callback\n");
return NULL;
}
#define GO(A) \
static uintptr_t my_ftw64_fct_##A = 0; \
static int my_ftw64_##A(void* fpath, void* sb, int flag) \
{ \
struct x64_stat64 x64st; \
UnalignStat64(sb, &x64st); \
return (int)RunFunctionFmt(my_ftw64_fct_##A, "ppi", fpath, &x64st, flag); \
}
SUPER()
#undef GO
static void* findftw64Fct(void* fct)
{
if(!fct) return NULL;
#define GO(A) if(my_ftw64_fct_##A == (uintptr_t)fct) return my_ftw64_##A;
SUPER()
#undef GO
#define GO(A) if(my_ftw64_fct_##A == 0) {my_ftw64_fct_##A = (uintptr_t)fct; return my_ftw64_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for libc ftw64 callback\n");
return NULL;
}
#define GO(A) \
static uintptr_t my_nftw64_fct_##A = 0; \
static int my_nftw64_##A(void* fpath, void* sb, int flag, void* ftwbuff) \
{ \
struct x64_stat64 x64st; \
UnalignStat64(sb, &x64st); \
return (int)RunFunctionFmt(my_nftw64_fct_##A, "ppip", fpath, &x64st, flag, ftwbuff); \
}
SUPER()
#undef GO
static void* findnftw64Fct(void* fct)
{
if(!fct) return NULL;
#define GO(A) if(my_nftw64_fct_##A == (uintptr_t)fct) return my_nftw64_##A;
SUPER()
#undef GO
#define GO(A) if(my_nftw64_fct_##A == 0) {my_nftw64_fct_##A = (uintptr_t)fct; return my_nftw64_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for libc nftw64 callback\n");
return NULL;
}
#define GO(A) \
static uintptr_t my_globerr_fct_##A = 0; \
static int my_globerr_##A(void* epath, int eerrno) \
{ \
return (int)RunFunctionFmt(my_globerr_fct_##A, "pi", epath, eerrno); \
}
SUPER()
#undef GO
static void* findgloberrFct(void* fct)
{
if(!fct) return NULL;
void* p;
if((p = GetNativeFnc((uintptr_t)fct))) return p;
#define GO(A) if(my_globerr_fct_##A == (uintptr_t)fct) return my_globerr_##A;
SUPER()
#undef GO
#define GO(A) if(my_globerr_fct_##A == 0) {my_globerr_fct_##A = (uintptr_t)fct; return my_globerr_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for libc globerr callback\n");
return NULL;
}
#define GO(A) \
static uintptr_t my_free_fct_##A = 0; \
static void my_free_##A(void* p) \
{ \
RunFunctionFmt(my_free_fct_##A, "p", p); \
}
SUPER()
#undef GO
static void* findfreeFct(void* fct)
{
if(!fct) return NULL;
void* p;
if((p = GetNativeFnc((uintptr_t)fct))) return p;
#define GO(A) if(my_free_fct_##A == (uintptr_t)fct) return my_free_##A;
SUPER()
#undef GO
#define GO(A) if(my_free_fct_##A == 0) {my_free_fct_##A = (uintptr_t)fct; return my_free_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for libc free callback\n");
return NULL;
}
#if 0
#undef dirent
#define GO(A) \
static uintptr_t my_filter_dir_fct_##A = 0; \
static int my_filter_dir_##A(const struct dirent* a) \
{ \
return (int)RunFunctionFmt(my_filter_dir_fct_##A, "p", a); \
}
SUPER()
#undef GO
static void* findfilter_dirFct(void* fct)
{
if(!fct) return NULL;
void* p;
if((p = GetNativeFnc((uintptr_t)fct))) return p;
#define GO(A) if(my_filter_dir_fct_##A == (uintptr_t)fct) return my_filter_dir_##A;
SUPER()
#undef GO
#define GO(A) if(my_filter_dir_fct_##A == 0) {my_filter_dir_fct_##A = (uintptr_t)fct; return my_filter_dir_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for libc filter_dir callback\n");
return NULL;
}
#define GO(A) \
static uintptr_t my_compare_dir_fct_##A = 0; \
static int my_compare_dir_##A(const struct dirent* a, const struct dirent* b) \
{ \
return (int)RunFunctionFmt(my_compare_dir_fct_##A, "pp", a, b); \
}
SUPER()
#undef GO
static void* findcompare_dirFct(void* fct)
{
if(!fct) return NULL;
void* p;
if((p = GetNativeFnc((uintptr_t)fct))) return p;
#define GO(A) if(my_compare_dir_fct_##A == (uintptr_t)fct) return my_compare_dir_##A;
SUPER()
#undef GO
#define GO(A) if(my_compare_dir_fct_##A == 0) {my_compare_dir_fct_##A = (uintptr_t)fct; return my_compare_dir_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for libc compare_dir callback\n");
return NULL;
}
#endif
#define GO(A) \
static uintptr_t my_filter64_fct_##A = 0; \
static int my_filter64_##A(const struct dirent64* a) \
{ \
return (int)RunFunctionFmt(my_filter64_fct_##A, "p", a); \
}
SUPER()
#undef GO
static void* findfilter64Fct(void* fct)
{
if(!fct) return NULL;
void* p;
if((p = GetNativeFnc((uintptr_t)fct))) return p;
#define GO(A) if(my_filter64_fct_##A == (uintptr_t)fct) return my_filter64_##A;
SUPER()
#undef GO
#define GO(A) if(my_filter64_fct_##A == 0) {my_filter64_fct_##A = (uintptr_t)fct; return my_filter64_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for libc filter64 callback\n");
return NULL;
}
#define GO(A) \
static uintptr_t my_compare64_fct_##A = 0; \
static int my_compare64_##A(const struct dirent64* a, const struct dirent64* b) \
{ \
return (int)RunFunctionFmt(my_compare64_fct_##A, "pp", a, b); \
}
SUPER()
#undef GO
static void* findcompare64Fct(void* fct)
{
if(!fct) return NULL;
void* p;
if((p = GetNativeFnc((uintptr_t)fct))) return p;
#define GO(A) if(my_compare64_fct_##A == (uintptr_t)fct) return my_compare64_##A;
SUPER()
#undef GO
#define GO(A) if(my_compare64_fct_##A == 0) {my_compare64_fct_##A = (uintptr_t)fct; return my_compare64_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for libc compare64 callback\n");
return NULL;
}
#define GO(A) \
static uintptr_t my_printf_output_fct_##A = 0; \
static int my_printf_output_##A(void* a, void* b, void* c) \
{ \
return (int)RunFunctionFmt(my_printf_output_fct_##A, "ppp", a, b, c); \
}
SUPER()
#undef GO
static void* findprintf_outputFct(void* fct)
{
if(!fct) return NULL;
void* p;
if((p = GetNativeFnc((uintptr_t)fct))) return p;
#define GO(A) if(my_printf_output_fct_##A == (uintptr_t)fct) return my_printf_output_##A;
SUPER()
#undef GO
#define GO(A) if(my_printf_output_fct_##A == 0) {my_printf_output_fct_##A = (uintptr_t)fct; return my_printf_output_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for libc printf_output callback\n");
return NULL;
}
#define GO(A) \
static uintptr_t my_printf_arginfo_fct_##A = 0; \
static int my_printf_arginfo_##A(void* a, size_t b, void* c, void* d) \
{ \
return (int)RunFunctionFmt(my_printf_arginfo_fct_##A, "pLpp", a, b, c, d); \
}
SUPER()
#undef GO
static void* findprintf_arginfoFct(void* fct)
{
if(!fct) return NULL;
void* p;
if((p = GetNativeFnc((uintptr_t)fct))) return p;
#define GO(A) if(my_printf_arginfo_fct_##A == (uintptr_t)fct) return my_printf_arginfo_##A;
SUPER()
#undef GO
#define GO(A) if(my_printf_arginfo_fct_##A == 0) {my_printf_arginfo_fct_##A = (uintptr_t)fct; return my_printf_arginfo_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for libc printf_arginfo callback\n");
return NULL;
}
#define GO(A) \
static uintptr_t my_printf_type_fct_##A = 0; \
static void my_printf_type_##A(void* a, va_list* b) \
{ \
RunFunctionFmt(my_printf_type_fct_##A, "pp", a, b); \
}
SUPER()
#undef GO
static void* findprintf_typeFct(void* fct)
{
if(!fct) return NULL;
void* p;
if((p = GetNativeFnc((uintptr_t)fct))) return p;
#define GO(A) if(my_printf_type_fct_##A == (uintptr_t)fct) return my_printf_type_##A;
SUPER()
#undef GO
#define GO(A) if(my_printf_type_fct_##A == 0) {my_printf_type_fct_##A = (uintptr_t)fct; return my_printf_type_##A; }
SUPER()
#undef GO
printf_log(LOG_NONE, "Warning, no more slot for libc printf_type callback\n");
return NULL;
}
#undef SUPER
int32_t my___libc_start_main(x64emu_t* emu, int (*main) (int, char * *, char * *),
int argc, char * * ubp_av, void (*init) (void), void (*fini) (void),
void (*rtld_fini) (void), void (* stack_end));
EXPORT void my___libc_init_first(x64emu_t* emu, int argc, char* arg0, char** b)
{
(void)emu; (void)argc; (void)arg0; (void)b;
return;
}
uintptr_t my_syscall(x64emu_t *emu);
void EXPORT my___stack_chk_fail(x64emu_t* emu)
{
char buff[200];
#ifdef HAVE_TRACE
sprintf(buff, "%p: Stack is corrupted, aborting (prev IP=%p)\n", (void*)emu->old_ip, (void*)emu->prev2_ip);
#else
sprintf(buff, "%p: Stack is corrupted, aborting\n", (void*)emu->old_ip);
#endif
if(cycle_log) {
print_cycle_log(LOG_INFO);
}
StopEmu(emu, buff, emu->segs[_CS]==0x23);
}
void EXPORT my___gmon_start__(x64emu_t *emu)
{
(void)emu;
printf_log(LOG_DEBUG, "__gmon_start__ called (dummy call)\n");
}
int EXPORT my___cxa_atexit(x64emu_t* emu, void* p, void* a, void* dso_handle)
{
AddCleanup1Arg(emu, p, a, FindElfAddress(my_context, (uintptr_t)dso_handle));
return 0;
}
void EXPORT my___cxa_finalize(x64emu_t* emu, void* p)
{
if(!p) {
CallAllCleanup(emu);
return;
}
CallCleanup(emu, FindElfAddress(my_context, (uintptr_t)p));
}
int EXPORT my_atexit(x64emu_t* emu, void *p)
{
AddCleanup(emu, p);
return 0;
}
int my_getcontext(x64emu_t* emu, void* ucp);
int my_setcontext(x64emu_t* emu, void* ucp);
int my_makecontext(x64emu_t* emu, void* ucp, void* fnc, int32_t argc, void* argv);
int my_swapcontext(x64emu_t* emu, void* ucp1, void* ucp2);
int my_dl_iterate_phdr(x64emu_t *emu, void* F, void *data);
pid_t EXPORT my_fork(x64emu_t* emu)
{
#if 1
emu->quit = 1;
emu->fork = 1;
return 0;
#else
for (int i=my_context->atfork_sz-1; i>=0; --i)
if(my_context->atforks[i].prepare)
RunFunctionWithEmu(emu, 0, my_context->atforks[i].prepare, 0);
int type = emu->type;
pid_t v;
v = fork();
if(type == EMUTYPE_MAIN)
thread_set_emu(emu);
if(v<0) {
printf_log(LOG_NONE, "BOX64: Warning, fork errored... (%d)\n", v);
} else if(v>0) {
for (int i=0; i<my_context->atfork_sz; --i)
if(my_context->atforks[i].parent)
RunFunctionWithEmu(emu, 0, my_context->atforks[i].parent, 0);
} else {
for (int i=0; i<my_context->atfork_sz; --i)
if(my_context->atforks[i].child)
RunFunctionWithEmu(emu, 0, my_context->atforks[i].child, 0);
}
return v;
#endif
}
pid_t EXPORT my___fork(x64emu_t* emu) __attribute__((alias("my_fork")));
pid_t EXPORT my_vfork(x64emu_t* emu)
{
#if 1
emu->quit = 1;
emu->fork = 3;
return 0;
#else
return 0;
#endif
}
int EXPORT my_uname(struct utsname *buf)
{
int ret = uname(buf);
strcpy(buf->machine, "x86_64");
return ret;
}
#define X86_O_WRONLY 0x01
#define X86_O_RDWR 0x02
#define X86_FMODE_EXEC 0x20
#define X86_O_CREAT 0x40
#define X86_O_EXCL 0x80
#define X86_O_NOCTTY 0x100
#define X86_O_TRUNC 0x200
#define X86_O_APPEND 0x400
#define X86_O_NONBLOCK 0x800
#define X86_O_SYNC 0x101000
#define X86_O_DSYNC 0x1000
#define X86_O_RSYNC O_SYNC
#define X86_FASYNC 020000
#define X86_O_DIRECT 040000
#define X86_O_LARGEFILE 0100000
#define X86_O_DIRECTORY 0200000
#define X86_O_NOFOLLOW 0400000
#define X86_O_NOATIME 01000000
#define X86_O_CLOEXEC 02000000
#define X86_O_PATH 010000000
#define X86_O_TMPFILE 020200000
#define X86_FMODE_NONOTIFY 0x4000000
#ifndef O_TMPFILE
#define O_TMPFILE (020000000 | O_DIRECTORY)
#endif
#ifndef FMODE_EXEC
#define FMODE_EXEC 0x20
#endif
#ifndef FMODE_NONOTIFY
#define FMODE_NONOTIFY 0x4000000
#endif
#define SUPER() \
GO(O_WRONLY) \
GO(O_RDWR) \
GO(FMODE_EXEC) \
GO(O_CREAT) \
GO(O_EXCL) \
GO(O_NOCTTY) \
GO(O_TRUNC) \
GO(O_APPEND) \
GO(O_NONBLOCK) \
GO(O_SYNC) \
GO(O_DSYNC) \
GO(O_RSYNC) \
GO(FASYNC) \
GO(O_DIRECT) \
GO(O_LARGEFILE) \
GO(O_TMPFILE) \
GO(O_DIRECTORY) \
GO(O_NOFOLLOW) \
GO(O_NOATIME) \
GO(O_CLOEXEC) \
GO(O_PATH) \
GO(FMODE_NONOTIFY)
int of_convert(int a)
{
if(!a || a==-1) return a;
int b=0;
#define GO(A) if((a&(X86_##A))==(X86_##A)) {a&=~(X86_##A); b|=(A);}
SUPER();
#undef GO
if(a) {
printf_log(LOG_NONE, "Warning, of_convert(...) left over 0x%x, converted 0x%x\n", a, b);
}
return a|b;
}
int of_unconvert(int a)
{
if(!a || a==-1) return a;
int b=0;
#define GO(A) if((a&(A))==(A)) {a&=~(A); b|=(X86_##A);}
SUPER();
#undef GO
if(a && (a&~0x20000)) {
printf_log(LOG_NONE, "Warning, of_unconvert(...) left over 0x%x, converted 0x%x\n", a, b);
}
return a|b;
}
#undef SUPER
EXPORT void* my__ZGTtnaX (size_t a) { (void)a; printf("warning _ZGTtnaX called\n"); return NULL; }
EXPORT void my__ZGTtdlPv (void* a) { (void)a; printf("warning _ZGTtdlPv called\n"); }
EXPORT uint8_t my__ITM_RU1(const uint8_t * a) { (void)a; printf("warning _ITM_RU1 called\n"); return 0; }
EXPORT uint32_t my__ITM_RU4(const uint32_t * a) { (void)a; printf("warning _ITM_RU4 called\n"); return 0; }
EXPORT uint64_t my__ITM_RU8(const uint64_t * a) { (void)a; printf("warning _ITM_RU8 called\n"); return 0; }
EXPORT void my__ITM_memcpyRtWn(void * a, const void * b, size_t c) { (void)a; (void)b; (void)c; printf("warning _ITM_memcpyRtWn called\n"); }
EXPORT void my__ITM_memcpyRnWt(void * a, const void * b, size_t c) { (void)a; (void)b; (void)c; printf("warning _ITM_memcpyRnWt called\n"); }
EXPORT void my_longjmp(x64emu_t* emu, void *p, int32_t __val);
EXPORT void my__longjmp(x64emu_t* emu, void *p, int32_t __val) __attribute__((alias("my_longjmp")));
EXPORT void my_siglongjmp(x64emu_t* emu, void *p, int32_t __val) __attribute__((alias("my_longjmp")));
EXPORT void my___longjmp_chk(x64emu_t* emu, void *p, int32_t __val) __attribute__((alias("my_longjmp")));
EXPORT int my_printf(x64emu_t *emu, void* fmt, void* b) {
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 1);
PREPARE_VALIST;
return vprintf((const char*)fmt, VARARGS);
}
EXPORT int my___printf_chk(x64emu_t *emu, int chk, void* fmt, void* b)
{
(void)chk;
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 2);
PREPARE_VALIST;
return vprintf((const char*)fmt, VARARGS);
}
EXPORT int my_wprintf(x64emu_t *emu, void* fmt, void* b) {
myStackAlignW(emu, (const char*)fmt, b, emu->scratch, R_EAX, 1);
PREPARE_VALIST;
return vwprintf((const wchar_t*)fmt, VARARGS);
}
EXPORT int my___wprintf_chk(x64emu_t *emu, int chk, void* fmt, void* b)
{
(void)chk;
myStackAlignW(emu, (const char*)fmt, b, emu->scratch, R_EAX, 2);
PREPARE_VALIST;
return vwprintf((const wchar_t*)fmt, VARARGS);
}
EXPORT int my_vprintf(x64emu_t *emu, void* fmt, x64_va_list_t b) {
(void)emu;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
return vprintf(fmt, VARARGS);
}
EXPORT int my___vprintf_chk(x64emu_t *emu, void* fmt, x64_va_list_t b) __attribute__((alias("my_vprintf")));
EXPORT int my_vfprintf(x64emu_t *emu, void* F, void* fmt, x64_va_list_t b) {
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
return vfprintf(F, fmt, VARARGS);
}
EXPORT int my___vfprintf_chk(x64emu_t *emu, void* F, void* fmt, x64_va_list_t b) __attribute__((alias("my_vfprintf")));
EXPORT int my__IO_vfprintf(x64emu_t *emu, void* F, void* fmt, x64_va_list_t b) __attribute__((alias("my_vfprintf")));
EXPORT int my_fprintf(x64emu_t *emu, void* F, void* fmt, void* b) {
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 2);
PREPARE_VALIST;
return vfprintf(F, fmt, VARARGS);
}
EXPORT int my___fprintf_chk(x64emu_t *emu, void* F, int flag, void* fmt, void* b) {
(void)flag;
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 3);
PREPARE_VALIST;
return vfprintf(F, fmt, VARARGS);
}
EXPORT int my_vwprintf(x64emu_t *emu, void* fmt, x64_va_list_t b) {
(void)emu;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignWValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
int r = vwprintf(fmt, VARARGS);
return r;
}
EXPORT int my_fwprintf(x64emu_t *emu, void* F, void* fmt, void* b) {
myStackAlignW(emu, (const char*)fmt, b, emu->scratch, R_EAX, 2);
PREPARE_VALIST;
return vfwprintf(F, fmt, VARARGS);
}
EXPORT int my___fwprintf_chk(x64emu_t *emu, void* F, int flag, void* fmt, void* b) {
myStackAlignW(emu, (const char*)fmt, b, emu->scratch, R_EAX, 3);
PREPARE_VALIST;
return vfwprintf(F, fmt, VARARGS);
}
EXPORT int my_vfwprintf(x64emu_t *emu, void* F, void* fmt, x64_va_list_t b) {
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignWValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
return vfwprintf(F, fmt, VARARGS);
}
EXPORT int my___vfwprintf_chk(x64emu_t *emu, void* F, int flag, void* fmt, x64_va_list_t b) {
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignWValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
return vfwprintf(F, fmt, VARARGS);
}
EXPORT int my_dprintf(x64emu_t *emu, int d, void* fmt, void* b) {
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 2);
PREPARE_VALIST;
return vdprintf(d, fmt, VARARGS);
}
EXPORT int my___dprintf_chk(x64emu_t *emu, int d, int flag, void* fmt, void* b) {
(void)flag;
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 3);
PREPARE_VALIST;
return vdprintf(d, fmt, VARARGS);
}
EXPORT int my_vdprintf(x64emu_t *emu, int d, void* fmt, x64_va_list_t b) {
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
return vdprintf(d, fmt, VARARGS);
}
EXPORT int my___vdprintf_chk(x64emu_t *emu, int d, int flag, void* fmt, x64_va_list_t b) {
(void)flag;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
return vdprintf(d, fmt, VARARGS);
}
#if 0
EXPORT void *my_div(void *result, int numerator, int denominator) {
*(div_t *)result = div(numerator, denominator);
return result;
}
#endif
EXPORT int my_snprintf(x64emu_t* emu, void* buff, size_t s, void * fmt, uint64_t * b) {
#ifdef PREFER_CONVERT_VAARG
CREATE_VALIST_FROM_VAARG(b, emu->scratch, 3);
#else
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 3);
PREPARE_VALIST;
#endif
int r = vsnprintf(buff, s, fmt, VARARGS);
return r;
}
EXPORT int my___snprintf(x64emu_t* emu, void* buff, size_t s, void * fmt, uint64_t * b) __attribute__((alias("my_snprintf")));
EXPORT int my___snprintf_chk(x64emu_t* emu, void* buff, size_t s, int flags, size_t maxlen, void * fmt, uint64_t * b)
{
(void)flags; (void)maxlen;
#ifdef PREFER_CONVERT_VAARG
CREATE_VALIST_FROM_VAARG(b, emu->scratch, 5);
#else
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 5);
PREPARE_VALIST;
#endif
int r = vsnprintf(buff, s, fmt, VARARGS);
return r;
}
EXPORT int my_sprintf(x64emu_t* emu, void* buff, void * fmt, void * b) {
#ifdef PREFER_CONVERT_VAARG
CREATE_VALIST_FROM_VAARG(b, emu->scratch, 2);
#else
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 2);
PREPARE_VALIST;
#endif
return vsprintf(buff, (const char*)fmt, VARARGS);
}
EXPORT int my___sprintf_chk(x64emu_t* emu, void* buff, int flag, size_t l, void * fmt, void * b) {
(void)flag; (void)l;
#ifdef PREFER_CONVERT_VAARG
CREATE_VALIST_FROM_VAARG(b, emu->scratch, 4);
#else
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 4);
PREPARE_VALIST;
#endif
return vsprintf(buff, (const char*)fmt, VARARGS);
}
EXPORT int my_asprintf(x64emu_t* emu, void** buff, void * fmt, uint64_t * b) {
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 2);
PREPARE_VALIST;
return vasprintf((char**)buff, (char*)fmt, VARARGS);
}
EXPORT int my___asprintf(x64emu_t* emu, void** buff, void * fmt, uint64_t * b) __attribute__((alias("my_asprintf")));
EXPORT int my_vasprintf(x64emu_t* emu, char** buff, void* fmt, x64_va_list_t b) {
(void)emu;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
return vasprintf(buff, fmt, VARARGS);
}
EXPORT int my_vsprintf(x64emu_t* emu, void* buff, void * fmt, x64_va_list_t b) {
(void)emu;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
return vsprintf(buff, fmt, VARARGS);
}
EXPORT int my___vsprintf_chk(x64emu_t* emu, void* buff, void * fmt, x64_va_list_t b) __attribute__((alias("my_vsprintf")));
EXPORT int my_vfscanf(x64emu_t* emu, void* stream, void* fmt, x64_va_list_t b)
{
(void)emu;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignScanfValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
return vfscanf(stream, fmt, VARARGS);
}
EXPORT int my_vsscanf(x64emu_t* emu, void* stream, void* fmt, x64_va_list_t b)
{
(void)emu;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignScanfValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
return vsscanf(stream, fmt, VARARGS);
}
EXPORT int my___vsscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my_vsscanf")));
EXPORT int my_vswscanf(x64emu_t* emu, void* stream, void* fmt, x64_va_list_t b)
{
(void)emu;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignScanfWValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
return vswscanf(stream, fmt, VARARGS);
}
EXPORT int my_sscanf(x64emu_t* emu, void* stream, void* fmt, uint64_t* b)
{
myStackAlignScanf(emu, (const char*)fmt, b, emu->scratch, 2);
PREPARE_VALIST;
return vsscanf(stream, fmt, VARARGS);
}
EXPORT int my_vscanf(x64emu_t* emu, void* fmt, x64_va_list_t b)
{
(void)emu;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignScanfValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
return vscanf(fmt, VARARGS);
}
EXPORT int my__IO_vfscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my_vfscanf")));
EXPORT int my___isoc99_vsscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my_vsscanf")));
EXPORT int my___isoc99_vscanf(x64emu_t* emu, void* fmt, void* b) __attribute__((alias("my_vscanf")));
EXPORT int my___isoc99_vswscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my_vswscanf")));
EXPORT int my___isoc99_vfscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my_vfscanf")));
EXPORT int my___isoc99_fscanf(x64emu_t* emu, void* stream, void* fmt, uint64_t* b)
{
myStackAlignScanf(emu, (const char*)fmt, b, emu->scratch, 2);
PREPARE_VALIST;
return vfscanf(stream, fmt, VARARGS);
}
EXPORT int my_fscanf(x64emu_t* emu, void* stream, void* fmt, uint64_t* b) __attribute__((alias("my___isoc99_fscanf")));
EXPORT int my___isoc99_scanf(x64emu_t* emu, void* fmt, uint64_t* b)
{
myStackAlignScanf(emu, (const char*)fmt, b, emu->scratch, 1);
PREPARE_VALIST;
return vscanf(fmt, VARARGS);
}
EXPORT int my___isoc99_sscanf(x64emu_t* emu, void* stream, void* fmt, uint64_t* b)
{
myStackAlignScanf(emu, (const char*)fmt, b, emu->scratch, 2);
PREPARE_VALIST;
return vsscanf(stream, fmt, VARARGS);
}
EXPORT int my___isoc99_swscanf(x64emu_t* emu, void* stream, void* fmt, uint64_t* b)
{
myStackAlignScanf(emu, (const char*)fmt, b, emu->scratch, 2);
PREPARE_VALIST;
return vswscanf(stream, fmt, VARARGS);
}
EXPORT int my_vsnprintf(x64emu_t* emu, void* buff, size_t s, void * fmt, x64_va_list_t b) {
(void)emu;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
int r = vsnprintf(buff, s, fmt, VARARGS);
return r;
}
EXPORT int my___vsnprintf(x64emu_t* emu, void* buff, size_t s, void * fmt, x64_va_list_t b) __attribute__((alias("my_vsnprintf")));
EXPORT int my___vsnprintf_chk(x64emu_t* emu, void* buff, size_t s, int flags, size_t slen, void * fmt, x64_va_list_t b) {
(void)emu;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
int r = vsnprintf(buff, s, fmt, VARARGS);
return r;
}
#if 0
EXPORT int my_vasprintf(x64emu_t* emu, void* strp, void* fmt, void* b, va_list V)
{
#ifndef NOALIGN
myStackAlign((const char*)fmt, (uint32_t*)b, emu->scratch);
PREPARE_VALIST;
void* f = vasprintf;
int r = ((iFppp_t)f)(strp, fmt, VARARGS);
return r;
#else
void* f = vasprintf;
int r = ((iFppp_t)f)(strp, fmt, (uint32_t*)b);
return r;
#endif
}
#endif
EXPORT int my___vasprintf_chk(x64emu_t* emu, void* buff, int flags, void* fmt, x64_va_list_t b)
{
(void)emu; (void)flags;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
int r = vasprintf(buff, fmt, VARARGS);
return r;
}
EXPORT int my___asprintf_chk(x64emu_t* emu, void* result_ptr, int flags, void* fmt, void* b)
{
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 3);
PREPARE_VALIST;
return vasprintf((char**)result_ptr, (char*)fmt, VARARGS);
}
EXPORT int my_vswprintf(x64emu_t* emu, void* buff, size_t s, void * fmt, x64_va_list_t b) {
(void)emu;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignWValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
int r = vswprintf(buff, s, fmt, VARARGS);
return r;
}
EXPORT int my___vswprintf(x64emu_t* emu, void* buff, size_t s, void * fmt, x64_va_list_t b) __attribute__((alias("my_vswprintf")));
EXPORT int my___vswprintf_chk(x64emu_t* emu, void* buff, size_t s, void * fmt, x64_va_list_t b) __attribute__((alias("my_vswprintf")));
EXPORT int my_swscanf(x64emu_t* emu, void* stream, void* fmt, uint64_t* b)
{
myStackAlignScanfW(emu, (const char*)fmt, b, emu->scratch, 2);
PREPARE_VALIST;
return vswscanf(stream, fmt, VARARGS);
}
#if 0
EXPORT void my_verr(x64emu_t* emu, int eval, void* fmt, void* b) {
#ifndef NOALIGN
myStackAlignW((const char*)fmt, (uint32_t*)b, emu->scratch);
PREPARE_VALIST;
void* f = verr;
((vFipp_t)f)(eval, fmt, VARARGS);
#else
void* f = verr;
((vFipp_t)f)(eval, fmt, (uint32_t*)b);
#endif
}
EXPORT void my_vwarn(x64emu_t* emu, void* fmt, void* b) {
#ifndef NOALIGN
myStackAlignW((const char*)fmt, (uint32_t*)b, emu->scratch);
PREPARE_VALIST;
void* f = vwarn;
((vFpp_t)f)(fmt, VARARGS);
#else
void* f = vwarn;
((vFpp_t)f)(fmt, (uint32_t*)b);
#endif
}
#endif
EXPORT void my_err(x64emu_t *emu, int eval, void* fmt, void* b) {
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 2);
PREPARE_VALIST;
verr(eval, (const char*)fmt, VARARGS);
}
EXPORT void my_errx(x64emu_t *emu, int eval, void* fmt, void* b) {
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 2);
PREPARE_VALIST;
verrx(eval, (const char*)fmt, VARARGS);
}
EXPORT void my_warn(x64emu_t *emu, void* fmt, void* b) {
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 1);
PREPARE_VALIST;
vwarn((const char*)fmt, VARARGS);
}
EXPORT void my_warnx(x64emu_t *emu, void* fmt, void* b) {
myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 1);
PREPARE_VALIST;
vwarnx((const char*)fmt, VARARGS);
}
EXPORT void my_syslog(x64emu_t* emu, int priority, const char* fmt, uint64_t* b)
{
myStackAlign(emu, fmt, b, emu->scratch, R_EAX, 2);
PREPARE_VALIST;
return vsyslog(priority, fmt, VARARGS);
}
EXPORT void my___syslog_chk(x64emu_t* emu, int priority, int flags, const char* fmt, uint64_t* b)
{
(void)flags;
myStackAlign(emu, fmt, b, emu->scratch, R_EAX, 3);
PREPARE_VALIST;
return vsyslog(priority, fmt, VARARGS);
}
EXPORT void my_vsyslog(x64emu_t* emu, int priority, const char* fmt, x64_va_list_t b)
{
(void)emu;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
return vsyslog(priority, fmt, VARARGS);
}
EXPORT void my___vsyslog_chk(x64emu_t* emu, int priority, int flag, const char* fmt, x64_va_list_t b)
{
(void)emu;
#ifdef CONVERT_VALIST
CONVERT_VALIST(b);
#else
myStackAlignValist(emu, (const char*)fmt, emu->scratch, b);
PREPARE_VALIST;
#endif
return vsyslog(priority, fmt, VARARGS);
}
EXPORT int my___swprintf_chk(x64emu_t* emu, void* s, size_t n, int32_t flag, size_t slen, void* fmt, uint64_t* b)
{
(void)flag;
(void)slen;
myStackAlignW(emu, (const char*)fmt, b, emu->scratch, R_EAX, 5);
PREPARE_VALIST;
return vswprintf(s, n, (const wchar_t*)fmt, VARARGS);
}
EXPORT int my_swprintf(x64emu_t* emu, void* s, size_t n, void* fmt, uint64_t* b)
{
myStackAlignW(emu, (const char*)fmt, b, emu->scratch, R_EAX, 3);
PREPARE_VALIST;
return vswprintf(s, n, (const wchar_t*)fmt, VARARGS);
}
EXPORT void my__ITM_addUserCommitAction(x64emu_t* emu, void* cb, uint32_t b, void* c)
{
#if 0
libc_my_t *my = (libc_my_t *)emu->context->libclib->w.p2;
x64emu_t *cbemu = AddCallback(emu, (uintptr_t)cb, 1, c, NULL, NULL, NULL);
my->_ITM_addUserCommitAction(libc1ArgCallback, b, cbemu);
#else
(void)emu; (void)cb; (void)b; (void)c;
printf("warning _ITM_addUserCommitAction called\n");
#endif
}
EXPORT void my__ITM_registerTMCloneTable(x64emu_t* emu, void* p, uint32_t s) { (void)emu; (void)p; (void)s; }
EXPORT void my__ITM_deregisterTMCloneTable(x64emu_t* emu, void* p) { (void)emu; (void)p; }
EXPORT int my___fxstat(x64emu_t *emu, int vers, int fd, void* buf)
{
(void)emu; (void)vers;
struct stat64 st;
int r = fstat64(fd, buf?&st:buf);
if(buf && !r)
UnalignStat64(&st, buf);
return r;
}
EXPORT int my___fxstat64(x64emu_t *emu, int vers, int fd, void* buf)
{
(void)emu; (void)vers;
struct stat64 st;
int r = fstat64(fd, buf?&st:buf);
if(buf && !r)
UnalignStat64(&st, buf);
return r;
}
EXPORT int my___xmknod(x64emu_t* emu, int v, char* path, uint32_t mode, dev_t* dev)
{
(void)emu;
(void)v;
return mknod((const char*)path, mode, *dev);
}
EXPORT int my___xmknodat(x64emu_t* emu, int v, int dirfd, char* path, uint32_t mode, dev_t* dev)
{
(void)emu;
(void)v;
return mknodat(dirfd, (const char*)path, mode, *dev);
}
EXPORT int my___xstat(x64emu_t* emu, int v, void* path, void* buf)
{
(void)emu; (void)v;
struct stat64 st;
int r = stat64((const char*)path, buf?&st:buf);
if(buf && !r)
UnalignStat64(&st, buf);
return r;
}
EXPORT int my___xstat64(x64emu_t* emu, int v, void* path, void* buf)
{
(void)emu; (void)v;
struct stat64 st;
int r = stat64((const char*)path, buf?&st:buf);
if(buf && !r)
UnalignStat64(&st, buf);
return r;
}
EXPORT int my___lxstat(x64emu_t* emu, int v, void* name, void* buf)
{
(void)emu; (void)v;
struct stat64 st;
int r = lstat64((const char*)name, buf?&st:buf);
if(buf && !r)
UnalignStat64(&st, buf);
return r;
}
EXPORT int my___lxstat64(x64emu_t* emu, int v, void* name, void* buf)
{
(void)emu; (void)v;
struct stat64 st;
int r = lstat64((const char*)name, buf?&st:buf);
if(buf && !r)
UnalignStat64(&st, buf);
return r;
}
EXPORT int my___fxstatat(x64emu_t* emu, int v, int d, void* path, void* buf, int flags)
{
(void)emu; (void)v;
struct stat64 st;
int r = fstatat64(d, path, &st, flags);
if(!r)
UnalignStat64(&st, buf);
return r;
}
EXPORT int my___fxstatat64(x64emu_t* emu, int v, int d, void* path, void* buf, int flags)
{
(void)emu; (void)v;
struct stat64 st;
int r = fstatat64(d, path, &st, flags);
if(!r)
UnalignStat64(&st, buf);
return r;
}
EXPORT int my_stat(x64emu_t *emu, void* filename, void* buf)
{
(void)emu;
struct stat st;
int r = stat(filename, &st);
if(!r)
UnalignStat64(&st, buf);
return r;
}
EXPORT int my_stat64(x64emu_t *emu, void* filename, void* buf) __attribute__((alias("my_stat")));
EXPORT int my_lstat(x64emu_t *emu, void* filename, void* buf)
{
(void)emu;
struct stat st;
int r = lstat(filename, &st);
if(!r)
UnalignStat64(&st, buf);
return r;
}
EXPORT int my_lstat64(x64emu_t *emu, void* filename, void* buf) __attribute__((alias("my_lstat")));
EXPORT int my_fstat(x64emu_t *emu, int fd, void* buf)
{
(void)emu;
struct stat st;
int r = fstat(fd, &st);
if(!r)
UnalignStat64(&st, buf);
return r;
}
EXPORT int my_fstat64(x64emu_t* emu, int fd, void* buf) __attribute__((alias("my_fstat")));
EXPORT int my_fstatat(x64emu_t *emu, int fd, const char* path, void* buf, int flags)
{
(void)emu;
struct stat st;
int r = fstatat(fd, path, &st, flags);
if(!r)
UnalignStat64(&st, buf);
return r;
}
EXPORT int my_fstatat64(x64emu_t *emu, int fd, const char* path, void* buf, int flags) __attribute__((alias("my_fstatat")));
EXPORT int my__IO_file_stat(x64emu_t* emu, void* f, void* buf)
{
struct stat64 st;
int r = my->_IO_file_stat(f, &st);
UnalignStat64(&st, buf);
return r;
}
#if 0
EXPORT int my_fstatfs64(int fd, void* buf)
{
struct statfs64 st;
int r = fstatfs64(fd, &st);
UnalignStatFS64(&st, buf);
return r;
}
EXPORT int my_statfs64(const char* path, void* buf)
{
struct statfs64 st;
int r = statfs64(path, &st);
UnalignStatFS64(&st, buf);
return r;
}
#endif
#ifdef ANDROID
typedef int (*__compar_d_fn_t)(const void*, const void*, void*);
static size_t qsort_r_partition(void* base, size_t size, __compar_d_fn_t compar, void* arg, size_t lo, size_t hi)
{
void* tmp = alloca(size);
void* pivot = ((char*)base) + lo * size;
size_t i = lo;
for (size_t j = lo; j <= hi; j++)
{
void* base_i = ((char*)base) + i * size;
void* base_j = ((char*)base) + j * size;
if (compar(base_j, pivot, arg) < 0)
{
memcpy(tmp, base_i, size);
memcpy(base_i, base_j, size);
memcpy(base_j, tmp, size);
i++;
}
}
void* base_i = ((char *)base) + i * size;
void* base_hi = ((char *)base) + hi * size;
memcpy(tmp, base_i, size);
memcpy(base_i, base_hi, size);
memcpy(base_hi, tmp, size);
return i;
}
static void qsort_r_helper(void* base, size_t size, __compar_d_fn_t compar, void* arg, ssize_t lo, ssize_t hi)
{
if (lo < hi)
{
size_t p = qsort_r_partition(base, size, compar, arg, lo, hi);
qsort_r_helper(base, size, compar, arg, lo, p - 1);
qsort_r_helper(base, size, compar, arg, p + 1, hi);
}
}
static void qsort_r(void* base, size_t nmemb, size_t size, __compar_d_fn_t compar, void* arg)
{
return qsort_r_helper(base, size, compar, arg, 0, nmemb - 1);
}
#endif
typedef struct compare_r_s {
x64emu_t* emu;
uintptr_t f;
void* data;
int r;
} compare_r_t;
static int my_compare_r_cb(void* a, void* b, compare_r_t* arg)
{
return (int)RunFunctionWithEmu(arg->emu, 0, arg->f, 2+arg->r, a, b, arg->data);
}
EXPORT void my_qsort(x64emu_t* emu, void* base, size_t nmemb, size_t size, void* fnc)
{
compare_r_t args;
args.emu = emu; args.f = (uintptr_t)fnc; args.r = 0; args.data = NULL;
qsort_r(base, nmemb, size, (__compar_d_fn_t)my_compare_r_cb, &args);
}
EXPORT void my_qsort_r(x64emu_t* emu, void* base, size_t nmemb, size_t size, void* fnc, void* data)
{
compare_r_t args;
args.emu = emu; args.f = (uintptr_t)fnc; args.r = 1; args.data = data;
qsort_r(base, nmemb, size, (__compar_d_fn_t)my_compare_r_cb, &args);
}
EXPORT void* my_bsearch(x64emu_t* emu, void* key, void* base, size_t nmemb, size_t size, void* fnc)
{
(void)emu;
return bsearch(key, base, nmemb, size, findcompareFct(fnc));
}
EXPORT void* my_lsearch(x64emu_t* emu, void* key, void* base, size_t* nmemb, size_t size, void* fnc)
{
(void)emu;
return lsearch(key, base, nmemb, size, findcompareFct(fnc));
}
EXPORT void* my_tsearch(x64emu_t* emu, void* key, void* root, void* fnc)
{
(void)emu;
return tsearch(key, root, findcompareFct(fnc));
}
EXPORT void my_tdestroy(x64emu_t* emu, void* root, void* fnc)
{
(void)emu;
tdestroy(root, findfreeFct(fnc));
}
EXPORT void* my_tdelete(x64emu_t* emu, void* key, void** root, void* fnc)
{
(void)emu;
return tdelete(key, root, findcompareFct(fnc));
}
EXPORT void* my_tfind(x64emu_t* emu, void* key, void** root, void* fnc)
{
(void)emu;
return tfind(key, root, findcompareFct(fnc));
}
EXPORT void my_twalk(x64emu_t* emu, void* root, void* fnc)
{
(void)emu;
twalk(root, findactionFct(fnc));
}
EXPORT void* my_lfind(x64emu_t* emu, void* key, void* base, size_t* nmemb, size_t size, void* fnc)
{
(void)emu;
return lfind(key, base, nmemb, size, findcompareFct(fnc));
}
EXPORT void* my_fts_open(x64emu_t* emu, void* path, int options, void* c)
{
(void)emu;
return fts_open(path, options, findcompareFct(c));
}
EXPORT void* my_fts64_open(x64emu_t* emu, void* path, int options, void* c)
{
(void)emu;
return my->fts64_open(path, options, findcompareFct(c));
}
#if 0
struct i386_dirent {
uint32_t d_ino;
int32_t d_off;
uint16_t d_reclen;
uint8_t d_type;
char d_name[256];
};
EXPORT void* my_readdir(x64emu_t* emu, void* dirp)
{
if (fix_64bit_inodes)
{
struct dirent64 *dp64 = readdir64((DIR *)dirp);
if (!dp64) return NULL;
uint32_t ino32 = dp64->d_ino ^ (dp64->d_ino >> 32);
int32_t off32 = dp64->d_off;
struct i386_dirent *dp32 = (struct i386_dirent *)&(dp64->d_off);
dp32->d_ino = ino32;
dp32->d_off = off32;
dp32->d_reclen -= 8;
return dp32;
}
else
{
static pFp_t f = NULL;
if(!f) {
library_t* lib = my_lib;
if(!lib) return NULL;
f = (pFp_t)dlsym(lib->w.lib, "readdir");
}
return f(dirp);
}
}
EXPORT int32_t my_readdir_r(x64emu_t* emu, void* dirp, void* entry, void** result)
{
struct dirent64 d64, *dp64;
if (fix_64bit_inodes && (sizeof(d64.d_name) > 1))
{
static iFppp_t f = NULL;
if(!f) {
library_t* lib = my_lib;
if(!lib)
{
*result = NULL;
return 0;
}
f = (iFppp_t)dlsym(lib->w.lib, "readdir64_r");
}
int r = f(dirp, &d64, &dp64);
if (r || !dp64 || !entry)
{
*result = NULL;
return r;
}
struct i386_dirent *dp32 = (struct i386_dirent *)entry;
int namelen = dp64->d_reclen - offsetof(struct dirent64, d_name);
if (namelen > sizeof(dp32->d_name))
{
*result = NULL;
return ENAMETOOLONG;
}
dp32->d_ino = dp64->d_ino ^ (dp64->d_ino >> 32);
dp32->d_off = dp64->d_off;
dp32->d_reclen = namelen + offsetof(struct i386_dirent, d_name);
dp32->d_type = dp64->d_type;
memcpy(dp32->d_name, dp64->d_name, namelen);
*result = dp32;
return 0;
}
else
{
static iFppp_t f = NULL;
if(!f) {
library_t* lib = my_lib;
if(!lib)
{
*result = NULL;
return 0;
}
f = (iFppp_t)dlsym(lib->w.lib, "readdir_r");
}
return f(dirp, entry, result);
}
}
#endif
static int isProcSelf(const char *path, const char* w)
{
if(strncmp(path, "/proc/", 6)==0) {
char tmp[64];
sprintf(tmp, "/proc/self/%s", w);
if(strcmp((const char*)path, tmp)==0)
return 1;
pid_t pid = getpid();
sprintf(tmp, "/proc/%d/%s", pid, w);
if(strcmp((const char*)path, tmp)==0)
return 1;
}
return 0;
}
static int isSysCpuCache(const char *path, const char* w, int* _cpu, int* _index)
{
char tmp[128];
int cpu, index;
if(sscanf(path, "/sys/devices/system/cpu/cpu%d/cache/index%d/%s", &cpu, &index, tmp)!=3)
return 0;
if(strcmp(tmp, w))
return 0;
if(_cpu) * _cpu = cpu;
if(_index) *_index = index;
return 1;
}
EXPORT ssize_t my_readlink(x64emu_t* emu, void* path, void* buf, size_t sz)
{
if(isProcSelf((const char*)path, "exe")) {
return strlen(strncpy((char*)buf, emu->context->fullpath, sz));
}
return readlink((const char*)path, (char*)buf, sz);
}
int getNCpu();
const char* getBoxCpuName();
const char* getCpuName();
double getBogoMips();
#ifndef NOALIGN
void CreateCPUInfoFile(int fd)
{
size_t dummy;
char buff[600];
double freq = 600.0;
FILE *f = fopen("/sys/devices/system/cpu/cpu0/cpufreq/cpuinfo_max_freq", "r");
if(f) {
int r;
if(1==fscanf(f, "%d", &r))
freq = r/1000.;
fclose(f);
}
int n = getNCpu();
#define P \
dummy = write(fd, buff, strlen(buff))
for (int i=0; i<n; ++i) {
sprintf(buff, "processor\t: %d\n", i);
P;
sprintf(buff, "vendor_id\t: GenuineIntel\n");
P;
sprintf(buff, "cpu family\t: 6\n");
P;
sprintf(buff, "model\t\t: 1\n");
P;
sprintf(buff, "model name\t: %s\n", getBoxCpuName());
P;
sprintf(buff, "stepping\t: 1\nmicrocode\t: 0x10\n");
P;
sprintf(buff, "cpu MHz\t\t: %g\n", freq);
P;
sprintf(buff, "cache size\t: %d\n", 4096);
P;
sprintf(buff, "physical id\t: %d\nsiblings\t: %d\n", 0, n);
P;
sprintf(buff, "core id\t\t: %d\ncpu cores\t: %d\n", i, n);
P;
sprintf(buff, "bogomips\t: %g\n", getBogoMips());
P;
sprintf(buff, "flags\t\t: fpu cx8 sep ht cmov clflush mmx sse sse2 syscall tsc lahf_lm ssse3 ht tm lm fxsr cpuid pclmulqdq cx16 aes movbe pni sse4_1%s%s lzcnt popcnt%s%s%s%s%s\n", box64_sse42?" sse4_2":"", box64_avx?" avx":"", box64_avx?" bmi1":"", box64_avx2?" avx2":"", box64_avx?" bmi2":"", box64_avx2?" vaes":"", box64_avx2?" fma":"");
P;
sprintf(buff, "address sizes\t: 48 bits physical, 48 bits virtual\n");
P;
sprintf(buff, "\n");
P;
}
(void)dummy;
#undef P
}
void CreateCPUPresentFile(int fd)
{
size_t dummy;
char buff[600];
int n = getNCpu();
sprintf(buff, "0-%d\n", n-1);
dummy = write(fd, buff, strlen(buff));
(void)dummy;
}
void CreateClocksourceFile(int fd)
{
size_t dummy;
dummy = write(fd, "tsc\n", strlen("tsc\n"));
(void)dummy;
}
void CreateCpuCacheAssoc(int fd, int cpu, int index)
{
size_t dummy;
char tmp[64];
sprintf(tmp, "%d\n", (index>=3)?16:8);
dummy = write(fd, tmp, strlen(tmp));
(void)dummy;
}
void CreateCpuCacheCoher(int fd, int cpu, int index)
{
size_t dummy;
char tmp[64];
sprintf(tmp, "%d\n", 64);
dummy = write(fd, tmp, strlen(tmp));
(void)dummy;
}
void CreateCpuCacheSize(int fd, int cpu, int index)
{
size_t dummy;
char tmp[64];
int cachesize = 12288;
switch(index) {
case 0: cachesize = 32; break;
case 1: cachesize = 32; break;
case 2: cachesize = 256; break;
}
sprintf(tmp, "%dK\n", cachesize);
dummy = write(fd, tmp, strlen(tmp));
(void)dummy;
}
#ifdef ANDROID
static int shm_open(const char *name, int oflag, mode_t mode) {
return -1;
}
static int shm_unlink(const char *name) {
return -1;
}
#endif
#define TMP_CPUINFO "box64_tmpcpuinfo"
#define TMP_CPUTOPO "box64_tmpcputopo%d"
#define TMP_CLOCKSOURCE "box64_tmpclocksource"
#endif
#define TMP_MEMMAP "box64_tmpmemmap"
#define TMP_CMDLINE "box64_tmpcmdline"
#define TMP_CPUPRESENT "box64_cpupresent"
#define TMP_CPUCACHE_ASSOC "box64_cpucacheassoc"
#define TMP_CPUCACHE_COHER "box64_cpucachecoher"
#define TMP_CPUCACHE_SIZE "box64_cpucachesize"
EXPORT int32_t my_open(x64emu_t* emu, void* pathname, int32_t flags, uint32_t mode)
{
if(isProcSelf((const char*) pathname, "cmdline")) {
#if 0
char tmpcmdline[200] = {0};
char tmpbuff[100] = {0};
sprintf(tmpbuff, "%s/cmdlineXXXXXX", getenv("TMP")?getenv("TMP"):".");
int tmp = mkstemp(tmpbuff);
int dummy;
if(tmp<0) return open(pathname, flags, mode);
dummy = write(tmp, emu->context->fullpath, strlen(emu->context->fullpath)+1);
for (int i=1; i<emu->context->argc; ++i)
dummy = write(tmp, emu->context->argv[i], strlen(emu->context->argv[i])+1);
lseek(tmp, 0, SEEK_SET);
#else
int tmp = shm_open(TMP_CMDLINE, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return open(pathname, flags, mode);
shm_unlink(TMP_CMDLINE);
int dummy = write(tmp, emu->context->fullpath, strlen(emu->context->fullpath)+1);
(void)dummy;
for (int i=1; i<emu->context->argc; ++i)
if(emu->context->argv[i])
dummy = write(tmp, emu->context->argv[i], strlen(emu->context->argv[i])+1);
lseek(tmp, 0, SEEK_SET);
#endif
return tmp;
}
if(isProcSelf((const char*)pathname, "exe")) {
return open(emu->context->fullpath, flags, mode);
}
#ifndef NOALIGN
if(strcmp((const char*)pathname, "/proc/cpuinfo")==0) {
int tmp = shm_open(TMP_CPUINFO, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return open(pathname, flags, mode);
shm_unlink(TMP_CPUINFO);
CreateCPUInfoFile(tmp);
lseek(tmp, 0, SEEK_SET);
return tmp;
}
if(!strcmp((const char*)pathname, "/sys/bus/clocksource/devices/clocksource0/current_clocksource")) {
int tmp = shm_open(TMP_CLOCKSOURCE, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return open(pathname, flags, mode);
shm_unlink(TMP_CLOCKSOURCE);
CreateClocksourceFile(tmp);
lseek(tmp, 0, SEEK_SET);
return tmp;
}
int cpu, index;
if(isSysCpuCache(pathname, "ways_of_associativity", &cpu, &index) && !FileExist(pathname, IS_FILE)) {
int tmp = shm_open(TMP_CPUCACHE_ASSOC, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return open(pathname, flags, mode);
shm_unlink(TMP_CPUCACHE_ASSOC);
CreateCpuCacheAssoc(tmp, cpu, index);
lseek(tmp, 0, SEEK_SET);
return tmp;
}
if(isSysCpuCache(pathname, "coherency_line_size", &cpu, &index) && !FileExist(pathname, IS_FILE)) {
int tmp = shm_open(TMP_CPUCACHE_COHER, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return open(pathname, flags, mode);
shm_unlink(TMP_CPUCACHE_COHER);
CreateCpuCacheCoher(tmp, cpu, index);
lseek(tmp, 0, SEEK_SET);
return tmp;
}
if(isSysCpuCache(pathname, "size", &cpu, &index) && !FileExist(pathname, IS_FILE)) {
int tmp = shm_open(TMP_CPUCACHE_SIZE, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return open(pathname, flags, mode);
shm_unlink(TMP_CPUCACHE_SIZE);
CreateCpuCacheAssoc(tmp, cpu, index);
lseek(tmp, 0, SEEK_SET);
return tmp;
}
#endif
int ret = open(pathname, flags, mode);
return ret;
}
EXPORT int32_t my___open(x64emu_t* emu, void* pathname, int32_t flags, uint32_t mode) __attribute__((alias("my_open")));
EXPORT int32_t my_open64(x64emu_t* emu, void* pathname, int32_t flags, uint32_t mode)
{
if(isProcSelf((const char*)pathname, "cmdline")) {
#if 0
char tmpcmdline[200] = {0};
char tmpbuff[100] = {0};
sprintf(tmpbuff, "%s/cmdlineXXXXXX", getenv("TMP")?getenv("TMP"):".");
int tmp = mkstemp64(tmpbuff);
int dummy;
if(tmp<0) return open64(pathname, flags, mode);
dummy = write(tmp, emu->context->fullpath, strlen(emu->context->fullpath)+1);
for (int i=1; i<emu->context->argc; ++i)
dummy = write(tmp, emu->context->argv[i], strlen(emu->context->argv[i])+1);
lseek64(tmp, 0, SEEK_SET);
#else
int tmp = shm_open(TMP_CMDLINE, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return open64(pathname, flags, mode);
shm_unlink(TMP_CMDLINE);
int dummy = write(tmp, emu->context->fullpath, strlen(emu->context->fullpath)+1);
(void)dummy;
for (int i=1; i<emu->context->argc; ++i)
if(emu->context->argv[i])
dummy = write(tmp, emu->context->argv[i], strlen(emu->context->argv[i])+1);
lseek(tmp, 0, SEEK_SET);
#endif
return tmp;
}
if(isProcSelf((const char*)pathname, "exe")) {
return open64(emu->context->fullpath, flags, mode);
}
#ifndef NOALIGN
if(strcmp((const char*)pathname, "/proc/cpuinfo")==0) {
int tmp = shm_open(TMP_CPUINFO, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return open64(pathname, flags, mode);
shm_unlink(TMP_CPUINFO);
CreateCPUInfoFile(tmp);
lseek(tmp, 0, SEEK_SET);
return tmp;
}
if(box64_maxcpu && (!strcmp(pathname, "/sys/devices/system/cpu/present") || !strcmp(pathname, "/sys/devices/system/cpu/online")) && (getNCpu()>=box64_maxcpu)) {
int tmp = shm_open(TMP_CPUPRESENT, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return open64(pathname, mode);
shm_unlink(TMP_CPUPRESENT);
CreateCPUPresentFile(tmp);
lseek(tmp, 0, SEEK_SET);
return tmp;
}
if(!strcmp((const char*)pathname, "/sys/bus/clocksource/devices/clocksource0/current_clocksource")) {
int tmp = shm_open(TMP_CLOCKSOURCE, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return open64(pathname, flags, mode);
shm_unlink(TMP_CLOCKSOURCE);
CreateClocksourceFile(tmp);
lseek(tmp, 0, SEEK_SET);
return tmp;
}
int cpu, index;
if(isSysCpuCache(pathname, "ways_of_associativity", &cpu, &index) && !FileExist(pathname, IS_FILE)) {
int tmp = shm_open(TMP_CPUCACHE_ASSOC, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return open(pathname, flags, mode);
shm_unlink(TMP_CPUCACHE_ASSOC);
CreateCpuCacheAssoc(tmp, cpu, index);
lseek(tmp, 0, SEEK_SET);
return tmp;
}
if(isSysCpuCache(pathname, "coherency_line_size", &cpu, &index) && !FileExist(pathname, IS_FILE)) {
int tmp = shm_open(TMP_CPUCACHE_COHER, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return open(pathname, flags, mode);
shm_unlink(TMP_CPUCACHE_COHER);
CreateCpuCacheCoher(tmp, cpu, index);
lseek(tmp, 0, SEEK_SET);
return tmp;
}
if(isSysCpuCache(pathname, "size", &cpu, &index) && !FileExist(pathname, IS_FILE)) {
int tmp = shm_open(TMP_CPUCACHE_SIZE, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return open(pathname, flags, mode);
shm_unlink(TMP_CPUCACHE_SIZE);
CreateCpuCacheAssoc(tmp, cpu, index);
lseek(tmp, 0, SEEK_SET);
return tmp;
}
#endif
return open64(pathname, flags, mode);
}
EXPORT FILE* my_fopen64(x64emu_t* emu, const char* path, const char* mode)
{
if(isProcSelf(path, "maps")) {
int tmp = shm_open(TMP_MEMMAP, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return fopen64(path, mode);
shm_unlink(TMP_MEMMAP);
CreateMemorymapFile(emu->context, tmp);
lseek(tmp, 0, SEEK_SET);
return fdopen(tmp, mode);
}
#ifndef NOALIGN
if(strcmp(path, "/proc/cpuinfo")==0) {
int tmp = shm_open(TMP_CPUINFO, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return fopen64(path, mode);
shm_unlink(TMP_CPUINFO);
CreateCPUInfoFile(tmp);
lseek(tmp, 0, SEEK_SET);
return fdopen(tmp, mode);
}
if(box64_maxcpu && (!strcmp(path, "/sys/devices/system/cpu/present") || !strcmp(path, "/sys/devices/system/cpu/online")) && (getNCpu()>=box64_maxcpu)) {
int tmp = shm_open(TMP_CPUPRESENT, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return fopen64(path, mode);
shm_unlink(TMP_CPUPRESENT);
CreateCPUPresentFile(tmp);
lseek(tmp, 0, SEEK_SET);
return fdopen(tmp, mode);
}
if(strcmp(path, "/sys/bus/clocksource/devices/clocksource0/current_clocksource")==0) {
int tmp = shm_open(TMP_CLOCKSOURCE, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return fopen64(path, mode);
shm_unlink(TMP_CLOCKSOURCE);
CreateClocksourceFile(tmp);
lseek(tmp, 0, SEEK_SET);
return fdopen(tmp, mode);
}
int cpu, index;
if(isSysCpuCache(path, "ways_of_associativity", &cpu, &index) && !FileExist(path, IS_FILE)) {
int tmp = shm_open(TMP_CPUCACHE_ASSOC, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return fopen64(path, mode);
shm_unlink(TMP_CPUCACHE_ASSOC);
CreateCpuCacheAssoc(tmp, cpu, index);
lseek(tmp, 0, SEEK_SET);
return fdopen(tmp, mode);
}
if(isSysCpuCache(path, "coherency_line_size", &cpu, &index) && !FileExist(path, IS_FILE)) {
int tmp = shm_open(TMP_CPUCACHE_COHER, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return fopen64(path, mode);
shm_unlink(TMP_CPUCACHE_COHER);
CreateCpuCacheCoher(tmp, cpu, index);
lseek(tmp, 0, SEEK_SET);
return fdopen(tmp, mode);
}
if(isSysCpuCache(path, "size", &cpu, &index) && !FileExist(path, IS_FILE)) {
int tmp = shm_open(TMP_CPUCACHE_SIZE, O_RDWR | O_CREAT, S_IRWXU);
if(tmp<0) return fopen64(path, mode);
shm_unlink(TMP_CPUCACHE_SIZE);
CreateCpuCacheAssoc(tmp, cpu, index);
lseek(tmp, 0, SEEK_SET);
return fdopen(tmp, mode);
}
#endif
if(isProcSelf(path, "exe")) {
return fopen64(emu->context->fullpath, mode);
}
return fopen64(path, mode);
}
EXPORT FILE* my_fopen(x64emu_t* emu, const char* path, const char* mode) __attribute__((alias("my_fopen64")));
#if 0
EXPORT int32_t my_ftw(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd)
{
static iFppi_t f = NULL;
if(!f) {
library_t* lib = my_lib;
if(!lib) return 0;
f = (iFppi_t)dlsym(lib->w.lib, "ftw");
}
return f(pathname, findftwFct(B), nopenfd);
}
EXPORT int32_t my_nftw(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd, int32_t flags)
{
static iFppii_t f = NULL;
if(!f) {
library_t* lib = my_lib;
if(!lib) return 0;
f = (iFppii_t)dlsym(lib->w.lib, "nftw");
}
return f(pathname, findnftwFct(B), nopenfd, flags);
}
EXPORT void* my_ldiv(x64emu_t* emu, void* p, int32_t num, int32_t den)
{
*((ldiv_t*)p) = ldiv(num, den);
return p;
}
#endif
#ifndef NOALIGN
EXPORT int32_t my_epoll_ctl(x64emu_t* emu, int32_t epfd, int32_t op, int32_t fd, void* event)
{
struct epoll_event _event[1] = {0};
if(event && (op!=EPOLL_CTL_DEL))
AlignEpollEvent(_event, event, 1);
return epoll_ctl(epfd, op, fd, event?_event:NULL);
}
EXPORT int32_t my_epoll_wait(x64emu_t* emu, int32_t epfd, void* events, int32_t maxevents, int32_t timeout)
{
struct epoll_event _events[maxevents];
int32_t ret = epoll_wait(epfd, events?_events:NULL, maxevents, timeout);
if(ret>0)
UnalignEpollEvent(events, _events, ret);
return ret;
}
EXPORT int32_t my_epoll_pwait(x64emu_t* emu, int32_t epfd, void* events, int32_t maxevents, int32_t timeout, const sigset_t *sigmask)
{
struct epoll_event _events[maxevents];
int32_t ret = epoll_pwait(epfd, events?_events:NULL, maxevents, timeout, sigmask);
if(ret>0)
UnalignEpollEvent(events, _events, ret);
return ret;
}
#endif
#ifndef ANDROID
EXPORT int32_t my_glob64(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, void* pglob)
{
(void)emu;
return glob64(pat, flags, findgloberrFct(errfnc), pglob);
}
EXPORT int32_t my_glob(x64emu_t *emu, void* pat, int32_t flags, void* errfnc, void* pglob) __attribute__((alias("my_glob64")));
#endif
EXPORT int my_scandir64(x64emu_t *emu, void* dir, void* namelist, void* sel, void* comp)
{
(void)emu;
return scandir64(dir, namelist, findfilter64Fct(sel), findcompare64Fct(comp));
}
EXPORT int my_scandir(x64emu_t *emu, void* dir, void* namelist, void* sel, void* comp) __attribute__((alias("my_scandir64")));
EXPORT int my_scandirat(x64emu_t *emu, int dirfd, void* dirp, void* namelist, void* sel, void* comp)
{
(void)emu;
return scandirat(dirfd, dirp, namelist, findfilter64Fct(sel), findcompare64Fct(comp));
}
EXPORT int my_ftw64(x64emu_t* emu, void* filename, void* func, int descriptors)
{
(void)emu;
return ftw64(filename, findftw64Fct(func), descriptors);
}
EXPORT int my_ftw(x64emu_t* emu, void* filename, void* func, int descriptors) __attribute__((alias("my_ftw64")));
EXPORT int32_t my_nftw64(x64emu_t* emu, void* pathname, void* B, int32_t nopenfd, int32_t flags)
{
(void)emu;
return nftw64(pathname, findnftw64Fct(B), nopenfd, flags);
}
EXPORT char** my_environ = NULL;
EXPORT char** my__environ = NULL;
EXPORT char** my___environ = NULL;
EXPORT int32_t my_execv(x64emu_t* emu, const char* path, char* const argv[])
{
int self = isProcSelf(path, "exe");
int x64 = FileIsX64ELF(path);
int x86 = my_context->box86path?FileIsX86ELF(path):0;
int script = (my_context->bashpath && FileIsShell(path))?1:0;
printf_log(LOG_DEBUG, "execv(\"%s\", %p) is x64=%d x86=%d script=%d self=%d\n", path, argv, x64, x86, script, self);
#if 1
if (x64 || x86 || script || self) {
int skip_first = 0;
if(strlen(path)>=strlen("wine64-preloader") && strcmp(path+strlen(path)-strlen("wine64-preloader"), "wine64-preloader")==0)
skip_first++;
int n=skip_first;
while(argv[n]) ++n;
int toadd = script?2:1;
const char** newargv = (const char**)box_calloc(n+toadd+2, sizeof(char*));
newargv[0] = x86?emu->context->box86path:emu->context->box64path;
if(script) newargv[1] = emu->context->bashpath;
memcpy(newargv+toadd, argv+skip_first, sizeof(char*)*(n+toadd));
if(self)
newargv[1] = emu->context->fullpath;
else {
if(strcmp(newargv[toadd], skip_first?argv[skip_first]:path))
setenv(x86?"BOX86_ARG0":"BOX64_ARG0", newargv[toadd], 1);
newargv[toadd] = skip_first?argv[skip_first]:path;
}
printf_log(LOG_DEBUG, " => execv(\"%s\", %p [\"%s\", \"%s\", \"%s\"...:%d])\n", newargv[0], newargv, newargv[0], n?newargv[1]:"", (n>1)?newargv[2]:"",n);
char** envv = NULL;
if(my_environ!=my_context->envv) envv = my_environ;
if(my__environ!=my_context->envv) envv = my__environ;
if(my___environ!=my_context->envv) envv = my___environ;
setenv("BOX64_LOG", "2", 1);
setenv("BOX64_TRACE_FILE", "/home/seb/trace-%pid.txt", 1);
setenv("BOX64_TRACE","server_init_process_done", 1);
setenv("BOX64_DYNAREC", "0", 1);
setenv("WINEDEBUG", "+server", 1);
//setenv("BOX64_DYNAREC", "0", 1);
}*/
int ret;
if(envv)
ret = execve(newargv[0], (char* const*)newargv, envv);
else
ret = execv(newargv[0], (char* const*)newargv);
box_free(newargv);
return ret;
}
#endif
return execv(path, argv);
}
EXPORT int32_t my_execve(x64emu_t* emu, const char* path, char* const argv[], char* const envp[])
{
int self = isProcSelf(path, "exe");
int x64 = FileIsX64ELF(path);
int x86 = my_context->box86path?FileIsX86ELF(path):0;
int script = (my_context->bashpath && FileIsShell(path))?1:0;
printf_log(LOG_DEBUG, "execve(\"%s\", %p[\"%s\", \"%s\", \"%s\"...], %p) is x64=%d x86=%d script=%d (my_context->envv=%p, environ=%p\n", path, argv, argv[0], argv[1]?argv[1]:"(nil)", argv[2]?argv[2]:"(nil)", envp, x64, x86, script, my_context->envv, environ);
if(envp == my_context->envv && environ) {
envp = environ;
}
#if 1
if (x64 || x86 || self || script) {
int skip_first = 0;
if(strlen(path)>=strlen("wine64-preloader") && strcmp(path+strlen(path)-strlen("wine64-preloader"), "wine64-preloader")==0)
skip_first++;
int n=skip_first;
while(argv[n]) ++n;
int toadd = script?2:1;
const char** newargv = (const char**)alloca((n+1+toadd-skip_first)*sizeof(char*));
memset(newargv, 0, (n+1+toadd)*sizeof(char*));
newargv[0] = x86?emu->context->box86path:emu->context->box64path;
if(script) newargv[1] = emu->context->bashpath;
memcpy(newargv+toadd, argv+skip_first, sizeof(char*)*(n+1-skip_first));
if(self) newargv[toadd] = emu->context->fullpath;
else {
if(strcmp(newargv[toadd], path))
setenv(x86?"BOX86_ARG0":"BOX64_ARG0", newargv[toadd], 1);
newargv[toadd] = path;
}
printf_log(LOG_DEBUG, " => execve(\"%s\", %p [\"%s\", \"%s\", \"%s\"...:%d], %p)\n", newargv[0], newargv, newargv[0], (n+toadd-skip_first)?newargv[1]:"", ((n+toadd-skip_first)>1)?newargv[2]:"",n, envp);
int ret = execve(newargv[0], (char* const*)newargv, envp);
return ret;
}
#endif
if(!strcmp(path + strlen(path) - strlen("/uname"), "/uname")
&& argv[1] && (!strcmp(argv[1], "-m") || !strcmp(argv[1], "-p") || !strcmp(argv[1], "-i"))
&& !argv[2]) {
path = my_context->box64path;
char *argv2[3] = { my_context->box64path, argv[1], NULL };
return execve(path, argv2, envp);
}
#ifndef NOALIGN
if(!strcmp(path + strlen(path) - strlen("/grep"), "/grep")
&& argv[1] && argv[2] && (!strcmp(argv[2], "/proc/cpuinfo") || (argv[1][1]=='-' && argv[3] && !strcmp(argv[3], "/proc/cpuinfo")))) {
int cpuinfo = strcmp(argv[2], "/proc/cpuinfo")?3:2;
int n=0;
while(argv[n]) ++n;
const char** newargv = (const char**)alloca((n+1)*sizeof(char*));
memcpy(newargv, argv, sizeof(char*)*(n+1));
const char* tmpdir = GetTmpDir();
char template[100] = {0};
sprintf(template, "%s/box64cpuinfoXXXXXX", tmpdir);
int fd = mkstemp(template);
CreateCPUInfoFile(fd);
char cpuinfo_file[100] = {0};
sprintf(template, "/proc/self/fd/%d", fd);
int rl = readlink(template, cpuinfo_file, sizeof(cpuinfo_file));
close(fd);
chmod(cpuinfo_file, 0666);
newargv[cpuinfo] = cpuinfo_file;
printf_log(LOG_DEBUG, " => execve(\"%s\", %p [\"%s\", \"%s\", \"%s\"...:%d], %p)\n", path, newargv, newargv[0], newargv[1], newargv[2],n, envp);
int ret = execve(path, (char* const*)newargv, envp);
return ret;
}
if(!strcmp(path + strlen(path) - strlen("/cat"), "/cat")
&& argv[1] && !strcmp(argv[1], "/proc/cpuinfo")) {
int cpuinfo = 1;
int n=0;
while(argv[n]) ++n;
const char** newargv = (const char**)alloca((n+1)*sizeof(char*));
memcpy(newargv, argv, sizeof(char*)*(n+1));
const char* tmpdir = GetTmpDir();
char template[100] = {0};
sprintf(template, "%s/box64cpuinfoXXXXXX", tmpdir);
int fd = mkstemp(template);
CreateCPUInfoFile(fd);
char cpuinfo_file[100] = {0};
sprintf(template, "/proc/self/fd/%d", fd);
int rl = readlink(template, cpuinfo_file, sizeof(cpuinfo_file));
close(fd);
chmod(cpuinfo_file, 0666);
newargv[cpuinfo] = cpuinfo_file;
printf_log(LOG_DEBUG, " => execve(\"%s\", %p [\"%s\", \"%s\", \"%s\"...:%d], %p)\n", path, newargv, newargv[0], newargv[1], newargv[2],n, envp);
int ret = execve(path, (char* const*)newargv, envp);
return ret;
}
printf_log(LOG_NONE, "\n\n*********\n\nCalling bwrap!\n\n**********\n\n");
}*/
#endif
return execve(path, argv, envp);
}
EXPORT int32_t my_execvp(x64emu_t* emu, const char* path, char* const argv[])
{
char* fullpath = ResolveFileSoft(path, &my_context->box64_path);
int self = isProcSelf(fullpath, "exe");
int x64 = FileIsX64ELF(fullpath);
int x86 = my_context->box86path?FileIsX86ELF(fullpath):0;
int script = (my_context->bashpath && FileIsShell(fullpath))?1:0;
printf_log(LOG_DEBUG, "execvp(\"%s\", %p), IsX86=%d / fullpath=\"%s\"\n", path, argv, x64, fullpath);
if (x64 || x86 || script || self) {
int i=0;
while(argv[i]) ++i;
int toadd = script?2:1;
char** newargv = (char**)alloca((i+toadd+1)*sizeof(char*));
memset(newargv, 0, (i+toadd+1)*sizeof(char*));
newargv[0] = x86?emu->context->box86path:emu->context->box64path;
if(script) newargv[1] = emu->context->bashpath;
for (int j=0; j<i; ++j)
newargv[j+toadd] = argv[j];
if(self) newargv[1] = emu->context->fullpath;
else {
if(strcmp(newargv[toadd], path))
setenv(x86?"BOX86_ARG0":"BOX64_ARG0", newargv[toadd], 1);
newargv[toadd] = fullpath;
}
printf_log(LOG_DEBUG, " => execvp(\"%s\", %p [\"%s\", \"%s\"...:%d])\n", newargv[0], newargv, newargv[1], i?newargv[2]:"", i);
char** envv = NULL;
if(my_environ!=my_context->envv) envv = my_environ;
if(my__environ!=my_context->envv) envv = my__environ;
if(my___environ!=my_context->envv) envv = my___environ;
int ret;
if(envv)
ret = execvpe(newargv[0], newargv, envv);
else
ret = execvp(newargv[0], newargv);
box_free(fullpath);
return ret;
}
if((!strcmp(path + strlen(path) - strlen("/uname"), "/uname") || !strcmp(path, "uname"))
&& argv[1] && (!strcmp(argv[1], "-m") || !strcmp(argv[1], "-p") || !strcmp(argv[1], "-i"))
&& !argv[2]) {
path = my_context->box64path;
char *argv2[3] = { my_context->box64path, argv[1], NULL };
return execvp(path, argv2);
}
return execvp(path, argv);
}
EXPORT int32_t my_execl(x64emu_t* emu, const char* path)
{
int self = isProcSelf(path, "exe");
int x64 = FileIsX64ELF(path);
int x86 = my_context->box86path?FileIsX86ELF(path):0;
int script = (my_context->bashpath && FileIsShell(path))?1:0;
printf_log(LOG_DEBUG, "execle(\"%s\", ...), IsX86=%d, self=%d\n", path, x64, self);
int i=0;
while(getVargN(emu, i+1)) ++i;
int toadd = script?2:((x64||self)?1:0);
char** newargv = (char**)box_calloc(i+toadd+1, sizeof(char*));
int j=0;
if ((x64 || x86 || script || self))
newargv[j++] = x86?emu->context->box86path:emu->context->box64path;
if(script) newargv[j++] = emu->context->bashpath;
for (int k=0; k<i; ++k)
newargv[j++] = getVargN(emu, k+1);
if(self) newargv[1] = emu->context->fullpath;
printf_log(LOG_DEBUG, " => execle(\"%s\", %p [\"%s\", \"%s\"...:%d])\n", newargv[0], newargv, newargv[1], i?newargv[2]:"", i);
int ret = 0;
if (!(x64 || x86 || script || self)) {
ret = execv(path, newargv);
} else {
ret = execv(newargv[0], newargv);
}
box_free(newargv);
return ret;
}
EXPORT int32_t my_execle(x64emu_t* emu, const char* path)
{
int self = isProcSelf(path, "exe");
int x64 = FileIsX64ELF(path);
int x86 = my_context->box86path?FileIsX86ELF(path):0;
int script = (my_context->bashpath && FileIsShell(path))?1:0;
printf_log(LOG_DEBUG, "execl(\"%s\", ...), IsX86=%d, self=%d\n", path, x64, self);
int i=0;
while(getVargN(emu, i+1)) ++i;
int toadd = script?2:((x64||self)?1:0);
char** newargv = (char**)box_calloc(i+toadd+1, sizeof(char*));
char** envp = (char**)getVargN(emu, i+2);
if(envp == my_context->envv && environ) {
envp = environ;
}
int j=0;
if ((x64 || x86 || script || self))
newargv[j++] = x86?emu->context->box86path:emu->context->box64path;
if(script) newargv[j++] = emu->context->bashpath;
for (int k=0; k<i; ++k)
newargv[j++] = getVargN(emu, k+1);
if(self) newargv[1] = emu->context->fullpath;
printf_log(LOG_DEBUG, " => execle(\"%s\", %p [\"%s\", \"%s\"...:%d], %p)\n", newargv[0], newargv, newargv[1], i?newargv[2]:"", i, envp);
int ret = execve(newargv[0], newargv, envp);
box_free(newargv);
return ret;
}
EXPORT int32_t my_execlp(x64emu_t* emu, const char* path)
{
char* fullpath = ResolveFileSoft(path, &my_context->box64_path);
int self = isProcSelf(fullpath, "exe");
int x64 = FileIsX64ELF(fullpath);
int x86 = my_context->box86path?FileIsX86ELF(fullpath):0;
int script = (my_context->bashpath && FileIsShell(fullpath))?1:0;
printf_log(LOG_DEBUG, "execlp(\"%s\", ...), IsX86=%d / fullpath=\"%s\"\n", path, x64, fullpath);
int i=0;
while(getVargN(emu, i+1)) ++i;
int toadd = script?2:((x64||self)?1:0);
char** newargv = (char**)box_calloc(i+toadd+1, sizeof(char*));
int j=0;
if ((x64 || x86 || script || self))
newargv[j++] = x86?emu->context->box86path:emu->context->box64path;
if(script) newargv[j++] = emu->context->bashpath;
for (int k=0; k<i; ++k)
newargv[j++] = getVargN(emu, k+1);
if(self) newargv[1] = emu->context->fullpath;
if(script) newargv[2] = fullpath;
printf_log(LOG_DEBUG, " => execlp(\"%s\", %p [\"%s\", \"%s\"...:%d])\n", newargv[0], newargv, newargv[1], i?newargv[2]:"", i);
char** envv = NULL;
if(my_environ!=my_context->envv) envv = my_environ;
if(my__environ!=my_context->envv) envv = my__environ;
if(my___environ!=my_context->envv) envv = my___environ;
int ret;
if(envv)
ret = execvpe(newargv[0], newargv, envv);
else
ret = execvp(newargv[0], newargv);
box_free(newargv);
box_free(fullpath);
return ret;
}
EXPORT int32_t my_posix_spawn(x64emu_t* emu, pid_t* pid, const char* fullpath,
const posix_spawn_file_actions_t *actions, const posix_spawnattr_t* attrp, char* const argv[], char* const envp[])
{
int self = isProcSelf(fullpath, "exe");
int x64 = FileIsX64ELF(fullpath);
int x86 = my_context->box86path?FileIsX86ELF(fullpath):0;
int script = (my_context->bashpath && FileIsShell(fullpath))?1:0;
int ret;
printf_log(LOG_INFO, "posix_spawn(%p, \"%s\", %p, %p, %p[\"%s\", \"%s\", ...], %p), IsX64=%d, IsX86=%d IsScript=%d %s\n", pid, fullpath, actions, attrp, argv, argv[0], argv[1]?argv[1]:"", envp, x64, x86, script, (envp==my_context->envv)?"envp is context->envv":"");
if(envp == my_context->envv && environ) {
envp = environ;
}
if (x64 || x86 || script || self) {
int n=1;
while(argv[n]) ++n;
int toadd = script?2:1;
const char** newargv = (const char**)alloca((n+1+toadd)*sizeof(char*));
memset(newargv, 0, (n+1+toadd)*sizeof(char*));
newargv[0] = x86?emu->context->box86path:emu->context->box64path;
if(script) newargv[1] = emu->context->bashpath;
memcpy(newargv+toadd, argv, (n+1)*sizeof(char*));
if(self) newargv[toadd] = emu->context->fullpath;
else {
if(strcmp(newargv[toadd], fullpath))
setenv(x86?"BOX86_ARG0":"BOX64_ARG0", newargv[toadd], 1);
newargv[toadd] = fullpath;
}
printf_log(LOG_INFO, " => posix_spawn(%p, \"%s\", %p, %p, %p [\"%s\", \"%s\", \"%s\"...:%d], %p)\n", pid, newargv[0], actions, attrp, newargv, newargv[0], newargv[1], newargv[2]?newargv[2]:"", n, envp);
ret = posix_spawn(pid, newargv[0], actions, attrp, (char* const*)newargv, envp);
printf_log(LOG_INFO, "posix_spawn returned %d\n", ret);
} else
ret = posix_spawn(pid, fullpath, actions, attrp, argv, envp);
return ret;
}
EXPORT int32_t my_posix_spawnp(x64emu_t* emu, pid_t* pid, const char* path,
const posix_spawn_file_actions_t *actions, const posix_spawnattr_t* attrp, char* const argv[], char* const envp[])
{
char* fullpath = ResolveFileSoft(path, &my_context->box64_path);
int self = isProcSelf(fullpath, "exe");
int x64 = FileIsX64ELF(fullpath);
int x86 = my_context->box86path?FileIsX86ELF(path):0;
int script = (my_context->bashpath && FileIsShell(fullpath))?1:0;
int ret;
printf_log(LOG_INFO, "posix_spawnp(%p, \"%s\", %p, %p, %p, %p), IsX86=%d / fullpath=\"%s\"\n", pid, path, actions, attrp, argv, envp, x64, fullpath);
if(envp == my_context->envv && environ) {
envp = environ;
}
if (x64 || x86 || script || self) {
int n=1;
while(argv[n]) ++n;
int toadd = script?2:1;
const char** newargv = (const char**)alloca((n+1+toadd)*sizeof(char*));
memset(newargv, 0, (n+1+toadd)*sizeof(char*));
newargv[0] = x86?emu->context->box86path:emu->context->box64path;
if(script) newargv[1] = emu->context->bashpath;
memcpy(newargv+toadd, argv, (n+1)*sizeof(char*));
if(self) newargv[toadd] = emu->context->fullpath;
else {
if(strcmp(newargv[toadd], fullpath))
setenv(x86?"BOX86_ARG0":"BOX64_ARG0", newargv[toadd], 1);
newargv[toadd] = fullpath;
}
printf_log(LOG_INFO, " => posix_spawn(%p, \"%s\", %p, %p, %p [\"%s\", \"%s\", \"%s\"...:%d], %p)\n", pid, newargv[0], actions, attrp, newargv, newargv[0], newargv[1], newargv[2]?newargv[2]:"", n, envp);
ret = posix_spawn(pid, newargv[0], actions, attrp, (char* const*)newargv, envp);
printf_log(LOG_INFO, "posix_spawn returned %d\n", ret);
} else
ret = posix_spawnp(pid, path, actions, attrp, argv, envp);
box_free(fullpath);
return ret;
}
EXPORT void my__Jv_RegisterClasses() {}
EXPORT int32_t my___cxa_thread_atexit_impl(x64emu_t* emu, void* dtor, void* obj, void* dso)
{
(void)emu;
AddCleanup1Arg(emu, dtor, obj, FindElfAddress(my_context, (uintptr_t)dso));
return 0;
}
EXPORT int32_t my___register_atfork(x64emu_t *emu, void* prepare, void* parent, void* child, void* handle)
{
(void)emu;
if(my_context->atfork_sz==my_context->atfork_cap) {
my_context->atfork_cap += 4;
my_context->atforks = (atfork_fnc_t*)box_realloc(my_context->atforks, my_context->atfork_cap*sizeof(atfork_fnc_t));
}
my_context->atforks[my_context->atfork_sz].prepare = (uintptr_t)prepare;
my_context->atforks[my_context->atfork_sz].parent = (uintptr_t)parent;
my_context->atforks[my_context->atfork_sz].child = (uintptr_t)child;
my_context->atforks[my_context->atfork_sz].handle = handle;
return 0;
}
#if 0
EXPORT uint64_t my___umoddi3(uint64_t a, uint64_t b)
{
return a%b;
}
EXPORT uint64_t my___udivdi3(uint64_t a, uint64_t b)
{
return a/b;
}
EXPORT int64_t my___divdi3(int64_t a, int64_t b)
{
return a/b;
}
EXPORT int32_t my___poll_chk(void* a, uint32_t b, int c, int l)
{
return poll(a, b, c);
}
#endif
EXPORT int32_t my_fcntl64(x64emu_t* emu, int32_t a, int32_t b, void* c)
{
(void)emu;
if(b==F_SETFL)
c = (void*)(uintptr_t)of_convert((intptr_t)c);
#if 0
if(b==F_GETLK64 || b==F_SETLK64 || b==F_SETLKW64)
{
my_flock64_t fl;
AlignFlock64(&fl, c);
int ret = fcntl(a, b, &fl);
UnalignFlock64(c, &fl);
return ret;
}
#endif
int ret = fcntl(a, b, c);
if(b==F_GETFL && ret!=-1)
ret = of_unconvert(ret);
return ret;
}
EXPORT int32_t my_fcntl(x64emu_t* emu, int32_t a, int32_t b, void* c)
{
(void)emu;
if(b==F_SETFL && (intptr_t)c==0xFFFFF7FF) {
int flags = fcntl(a, F_GETFL);
if(flags&O_NONBLOCK) {
flags &= ~O_NONBLOCK;
return fcntl(a, b, flags);
}
return 0;
}
if(b==F_SETFL)
c = (void*)(uintptr_t)of_convert((intptr_t)c);
#if 0
if(b==F_GETLK64 || b==F_SETLK64 || b==F_SETLKW64)
{
my_flock64_t fl;
AlignFlock64(&fl, c);
int ret = fcntl(a, b, &fl);
UnalignFlock64(c, &fl);
return ret;
}
#endif
int ret = fcntl(a, b, c);
if(b==F_GETFL && ret!=-1)
ret = of_unconvert(ret);
return ret;
}
EXPORT int32_t my___fcntl(x64emu_t* emu, int32_t a, int32_t b, void* c) __attribute__((alias("my_fcntl")));
#if 0
EXPORT int32_t my_preadv64(x64emu_t* emu, int32_t fd, void* v, int32_t c, int64_t o)
{
library_t* lib = my_lib;
if(!lib) return 0;
void* f = dlsym(lib->w.lib, "preadv64");
if(f)
return ((iFipiI_t)f)(fd, v, c, o);
return syscall(__NR_preadv, fd, v, c,(uint32_t)(o&0xffffffff), (uint32_t)((o>>32)&0xffffffff));
}
EXPORT int32_t my_pwritev64(x64emu_t* emu, int32_t fd, void* v, int32_t c, int64_t o)
{
library_t* lib = my_lib;
if(!lib) return 0;
void* f = dlsym(lib->w.lib, "pwritev64");
if(f)
return ((iFipiI_t)f)(fd, v, c, o);
#ifdef __arm__
return syscall(__NR_pwritev, fd, v, c, 0, (uint32_t)(o&0xffffffff), (uint32_t)((o>>32)&0xffffffff));
#else
return syscall(__NR_pwritev, fd, v, c,(uint32_t)(o&0xffffffff), (uint32_t)((o>>32)&0xffffffff));
#endif
}
EXPORT int32_t my_accept4(x64emu_t* emu, int32_t fd, void* a, void* l, int32_t flags)
{
library_t* lib = my_lib;
if(!lib) return 0;
void* f = dlsym(lib->w.lib, "accept4");
if(f)
return ((iFippi_t)f)(fd, a, l, flags);
if(!flags)
return accept(fd, a, l);
return syscall(__NR_accept4, fd, a, l, flags);
}
EXPORT int32_t my_fallocate64(int fd, int mode, int64_t offs, int64_t len)
{
iFiiII_t f = NULL;
static int done = 0;
if(!done) {
library_t* lib = my_lib;
f = (iFiiII_t)dlsym(lib->w.lib, "fallocate64");
done = 1;
}
if(f)
return f(fd, mode, offs, len);
else
return syscall(__NR_fallocate, fd, mode, (uint32_t)(offs&0xffffffff), (uint32_t)((offs>>32)&0xffffffff), (uint32_t)(len&0xffffffff), (uint32_t)((len>>32)&0xffffffff));
}
EXPORT struct __processor_model
{
unsigned int __cpu_vendor;
unsigned int __cpu_type;
unsigned int __cpu_subtype;
unsigned int __cpu_features[1];
} my___cpu_model;
#include "cpu_info.h"
void InitCpuModel()
{
my___cpu_model.__cpu_vendor = VENDOR_INTEL;
my___cpu_model.__cpu_type = INTEL_PENTIUM_M;
my___cpu_model.__cpu_subtype = 0;
my___cpu_model.__cpu_features[0] = (1<<FEATURE_CMOV)
| (1<<FEATURE_MMX)
| (1<<FEATURE_SSE)
| (1<<FEATURE_SSE2)
| (1<<FEATURE_SSE3)
| (1<<FEATURE_SSSE3)
| (1<<FEATURE_MOVBE)
| (1<<FEATURE_ADX);
}
#endif
#ifdef ANDROID
void ctSetup()
{
}
#else
EXPORT const unsigned short int *my___ctype_b;
EXPORT const int32_t *my___ctype_tolower;
EXPORT const int32_t *my___ctype_toupper;
void ctSetup()
{
my___ctype_b = *(__ctype_b_loc());
my___ctype_toupper = *(__ctype_toupper_loc());
my___ctype_tolower = *(__ctype_tolower_loc());
}
#endif
EXPORT void my___register_frame_info(void* a, void* b)
{
(void)a; (void)b;
}
EXPORT void* my___deregister_frame_info(void* a)
{
(void)a;
return NULL;
}
EXPORT void* my____brk_addr = NULL;
void EXPORT my_longjmp(x64emu_t* emu, void *p, int32_t __val)
{
jump_buff_x64_t *jpbuff = &((__jmp_buf_tag_t*)p)->__jmpbuf;
R_RBX = jpbuff->save_rbx;
R_RBP = jpbuff->save_rbp;
R_R12 = jpbuff->save_r12;
R_R13 = jpbuff->save_r13;
R_R14 = jpbuff->save_r14;
R_R15 = jpbuff->save_r15;
R_RSP = jpbuff->save_rsp;
R_RAX = __val;
R_RIP = jpbuff->save_rip;
if(((__jmp_buf_tag_t*)p)->__mask_was_saved) {
sigprocmask(SIG_SETMASK, &((__jmp_buf_tag_t*)p)->__saved_mask, NULL);
}
if(emu->flags.quitonlongjmp) {
emu->flags.longjmp = 1;
emu->quit = 1;
}
}
EXPORT int32_t my___sigsetjmp(x64emu_t* emu, void *p, int savesigs)
{
jump_buff_x64_t *jpbuff = &((__jmp_buf_tag_t*)p)->__jmpbuf;
jpbuff->save_rbx = R_RBX;
jpbuff->save_rbp = R_RBP;
jpbuff->save_r12 = R_R12;
jpbuff->save_r13 = R_R13;
jpbuff->save_r14 = R_R14;
jpbuff->save_r15 = R_R15;
jpbuff->save_rsp = R_RSP+sizeof(uintptr_t);
jpbuff->save_rip = *(uintptr_t*)(R_RSP);
if(savesigs) {
if(sigprocmask(SIG_SETMASK, NULL, &((__jmp_buf_tag_t*)p)->__saved_mask))
((__jmp_buf_tag_t*)p)->__mask_was_saved = 0;
else
((__jmp_buf_tag_t*)p)->__mask_was_saved = 1;
} else
((__jmp_buf_tag_t*)p)->__mask_was_saved = 0;
if(!emu->flags.jmpbuf_ready) {
emu->flags.need_jmpbuf = 1;
emu->quit = 1;
}
return 0;
}
EXPORT int32_t my_sigsetjmp(x64emu_t* emu, void *p, int savesigs)
{
return my___sigsetjmp(emu, p, savesigs);
}
EXPORT int32_t my__setjmp(x64emu_t* emu, void *p)
{
return my___sigsetjmp(emu, p, 0);
}
EXPORT int32_t my_setjmp(x64emu_t* emu, void *p)
{
return my___sigsetjmp(emu, p, 1);
}
EXPORT void my___explicit_bzero_chk(x64emu_t* emu, void* dst, uint32_t len, uint32_t dstlen)
{
(void)emu; (void)dstlen;
memset(dst, 0, len);
}
EXPORT void* my_realpath(x64emu_t* emu, void* path, void* resolved_path)
{
if(isProcSelf(path, "exe")) {
return realpath(emu->context->fullpath, resolved_path);
}
return realpath(path, resolved_path);
}
EXPORT int my_readlinkat(x64emu_t* emu, int fd, void* path, void* buf, size_t bufsize)
{
if(isProcSelf(path, "exe")) {
strncpy(buf, emu->context->fullpath, bufsize);
size_t l = strlen(emu->context->fullpath);
return (l>bufsize)?bufsize:(l+1);
}
return readlinkat(fd, path, buf, bufsize);
}
#ifndef MAP_FIXED_NOREPLACE
#define MAP_FIXED_NOREPLACE 0x200000
#endif
#ifndef MAP_32BIT
#define MAP_32BIT 0x40
#endif
extern int have48bits;
EXPORT void* my_mmap64(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset)
{
(void)emu;
if(prot&PROT_WRITE)
prot|=PROT_READ;
if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "mmap64(%p, 0x%lx, 0x%x, 0x%x, %d, %ld) => ", addr, length, prot, flags, fd, offset);}
int new_flags = flags;
#ifndef NOALIGN
void* old_addr = addr;
new_flags&=~MAP_32BIT;
if(flags&MAP_32BIT) {
addr = find31bitBlockNearHint(addr, length, 0);
} else if (box64_wine || 1) {
if(!addr)
addr = find47bitBlock(length);
}
#endif
void* ret = internal_mmap(addr, length, prot, new_flags, fd, offset);
#ifndef NOALIGN
if((ret!=MAP_FAILED) && (flags&MAP_32BIT) &&
(((uintptr_t)ret>0xffffffffLL) || ((box64_wine) && ((uintptr_t)ret&0xffff) && (ret!=addr)))) {
int olderr = errno;
if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) printf_log(LOG_NONE, "Warning, mmap on 32bits didn't worked, ask %p, got %p ", addr, ret);
munmap(ret, length);
loadProtectionFromMap();
addr = find31bitBlockNearHint(old_addr, length, 0);
new_flags = (addr && isBlockFree(addr, length) )? (new_flags|MAP_FIXED) : new_flags;
if((new_flags&(MAP_FIXED|MAP_FIXED_NOREPLACE))==(MAP_FIXED|MAP_FIXED_NOREPLACE)) new_flags&=~MAP_FIXED_NOREPLACE;
ret = internal_mmap(addr, length, prot, new_flags, fd, offset);
if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) printf_log(LOG_NONE, " tried again with %p, got %p\n", addr, ret);
if(old_addr && ret!=old_addr && ret!=MAP_FAILED)
errno = olderr;
} else if((ret!=MAP_FAILED) && !(flags&MAP_FIXED) && ((box64_wine)) && (addr && (addr!=ret)) &&
(((uintptr_t)ret>0x7fffffffffffLL) || ((uintptr_t)ret&~0xffff))) {
int olderr = errno;
if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) printf_log(LOG_NONE, "Warning, mmap on 47bits didn't worked, ask %p, got %p ", addr, ret);
munmap(ret, length);
loadProtectionFromMap();
addr = find47bitBlockNearHint(old_addr, length, 0);
new_flags = (addr && isBlockFree(addr, length)) ? (new_flags|MAP_FIXED) : new_flags;
if((new_flags&(MAP_FIXED|MAP_FIXED_NOREPLACE))==(MAP_FIXED|MAP_FIXED_NOREPLACE)) new_flags&=~MAP_FIXED_NOREPLACE;
ret = internal_mmap(addr, length, prot, new_flags, fd, offset);
if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) printf_log(LOG_NONE, " tried again with %p, got %p\n", addr, ret);
if(old_addr && ret!=old_addr && ret!=MAP_FAILED) {
errno = olderr;
if(old_addr>(void*)0x7fffffffff && !have48bits)
errno = EEXIST;
}
}
#endif
if((ret!=MAP_FAILED) && (flags&MAP_FIXED_NOREPLACE) && (ret!=addr)) {
internal_munmap(ret, length);
errno = EEXIST;
return MAP_FAILED;
}
if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "%p\n", ret);}
#ifdef DYNAREC
if(box64_dynarec && ret!=MAP_FAILED) {
{
// program used MAP_FIXED_NOREPLACE but the host linux didn't support it
// and responded with a different address, so ignore it
} else*/ {
if(prot& PROT_EXEC)
addDBFromAddressRange((uintptr_t)ret, length);
else
cleanDBFromAddressRange((uintptr_t)ret, length, prot?0:1);
}
}
#endif
if(ret!=MAP_FAILED) {
if((flags&MAP_SHARED) && (fd>0)) {
uint32_t flags = fcntl(fd, F_GETFL);
if((flags&O_ACCMODE)==O_RDWR) {
if((box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "Note: Marking the region (%p-%p prot=%x) as NEVERCLEAN because fd have O_RDWR attribute\n", ret, ret+length, prot);}
prot |= PROT_NEVERCLEAN;
}
}
static int unityplayer_detected = 0;
if(fd>0 && box64_unityplayer && !unityplayer_detected) {
char filename[4096];
char buf[128];
sprintf(buf, "/proc/self/fd/%d", fd);
ssize_t r = readlink(buf, filename, sizeof(filename)-1);
if(r!=1) filename[r]=0;
if(r>0 && strlen(filename)>strlen("UnityPlayer.dll") && !strcasecmp(filename+strlen(filename)-strlen("UnityPlayer.dll"), "UnityPlayer.dll")) {
printf_log(LOG_INFO, "BOX64: Detected UnityPlayer.dll\n");
#ifdef DYNAREC
if(!box64_dynarec_strongmem)
box64_dynarec_strongmem = 1;
#endif
unityplayer_detected = 1;
}
}
if(emu)
setProtection_mmap((uintptr_t)ret, length, prot);
else
setProtection((uintptr_t)ret, length, prot);
}
return ret;
}
EXPORT void* my_mmap(x64emu_t* emu, void *addr, unsigned long length, int prot, int flags, int fd, ssize_t offset) __attribute__((alias("my_mmap64")));
EXPORT void* my_mremap(x64emu_t* emu, void* old_addr, size_t old_size, size_t new_size, int flags, void* new_addr)
{
(void)emu;
if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "mremap(%p, %lu, %lu, %d, %p)=>", old_addr, old_size, new_size, flags, new_addr);}
void* ret = mremap(old_addr, old_size, new_size, flags, new_addr);
if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "%p\n", ret);}
if(ret!=(void*)-1) {
uint32_t prot = getProtection((uintptr_t)old_addr)&~PROT_CUSTOM;
if(ret==old_addr) {
if(old_size && old_size<new_size) {
setProtection_mmap((uintptr_t)ret+old_size, new_size-old_size, prot);
#ifdef DYNAREC
if(box64_dynarec)
addDBFromAddressRange((uintptr_t)ret+old_size, new_size-old_size);
#endif
} else if(old_size && new_size<old_size) {
freeProtection((uintptr_t)ret+new_size, old_size-new_size);
#ifdef DYNAREC
if(box64_dynarec)
cleanDBFromAddressRange((uintptr_t)ret+new_size, old_size-new_size, 1);
#endif
} else if(!old_size) {
setProtection_mmap((uintptr_t)ret, new_size, prot);
#ifdef DYNAREC
if(box64_dynarec)
addDBFromAddressRange((uintptr_t)ret, new_size);
#endif
}
} else {
if(old_size
#ifdef MREMAP_DONTUNMAP
&& ((flags&MREMAP_DONTUNMAP)==0)
#endif
) {
freeProtection((uintptr_t)old_addr, old_size);
#ifdef DYNAREC
if(box64_dynarec)
cleanDBFromAddressRange((uintptr_t)old_addr, old_size, 1);
#endif
}
setProtection_mmap((uintptr_t)ret, new_size, prot);
#ifdef DYNAREC
if(box64_dynarec)
addDBFromAddressRange((uintptr_t)ret, new_size);
#endif
}
}
return ret;
}
EXPORT int my_munmap(x64emu_t* emu, void* addr, unsigned long length)
{
(void)emu;
if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "munmap(%p, %lu)\n", addr, length);}
int ret = internal_munmap(addr, length);
#ifdef DYNAREC
if(!ret && box64_dynarec && length) {
cleanDBFromAddressRange((uintptr_t)addr, length, 1);
}
#endif
if(!ret) {
freeProtection((uintptr_t)addr, length);
}
return ret;
}
EXPORT int my_mprotect(x64emu_t* emu, void *addr, unsigned long len, int prot)
{
(void)emu;
if(emu && (box64_log>=LOG_DEBUG || box64_dynarec_log>=LOG_DEBUG)) {printf_log(LOG_NONE, "mprotect(%p, %lu, 0x%x)\n", addr, len, prot);}
if(prot&PROT_WRITE)
prot|=PROT_READ;
int ret = mprotect(addr, len, prot);
#ifdef DYNAREC
if(box64_dynarec && !ret && len) {
if(prot& PROT_EXEC)
addDBFromAddressRange((uintptr_t)addr, len);
else
cleanDBFromAddressRange((uintptr_t)addr, len, 1);
}
#endif
if(!ret && len) {
updateProtection((uintptr_t)addr, len, prot);
}
return ret;
}
typedef struct mallinfo (*mallinfo_fnc)(void);
EXPORT void* my_mallinfo(x64emu_t* emu, void* p)
{
static mallinfo_fnc f = NULL;
static int inited = 0;
if(!inited) {
inited = 1;
f = (mallinfo_fnc)dlsym(my_lib->w.lib, "mallinfo");
}
if(f)
*(struct mallinfo*)p=f();
else
memset(p, 0, sizeof(struct mallinfo));
return p;
}
#ifdef STATICBUILD
void my_updateGlobalOpt() {}
void my_checkGlobalOpt() {}
#endif
EXPORT int my_getopt(int argc, char* const argv[], const char *optstring)
{
my_updateGlobalOpt();
int ret = getopt(argc, argv, optstring);
my_checkGlobalOpt();
return ret;
}
EXPORT int my_getopt_long(int argc, char* const argv[], const char* optstring, const struct option *longopts, int *longindex)
{
my_updateGlobalOpt();
int ret = getopt_long(argc, argv, optstring, longopts, longindex);
my_checkGlobalOpt();
return ret;
}
EXPORT int my_getopt_long_only(int argc, char* const argv[], const char* optstring, const struct option *longopts, int *longindex)
{
my_updateGlobalOpt();
int ret = getopt_long_only(argc, argv, optstring, longopts, longindex);
my_checkGlobalOpt();
return ret;
}
#ifndef ANDROID
typedef struct {
void *read;
void *write;
void *seek;
void *close;
} my_cookie_io_functions_t;
typedef struct my_cookie_s {
uintptr_t r, w, s, c;
void* cookie;
} my_cookie_t;
static ssize_t my_cookie_read(void *p, char *buf, size_t size)
{
my_cookie_t* cookie = (my_cookie_t*)p;
return (ssize_t)RunFunctionFmt(cookie->r, "ppL", cookie->cookie, buf, size) ;
}
static ssize_t my_cookie_write(void *p, const char *buf, size_t size)
{
my_cookie_t* cookie = (my_cookie_t*)p;
return (ssize_t)RunFunctionFmt(cookie->w, "ppL", cookie->cookie, buf, size) ;
}
static int my_cookie_seek(void *p, off64_t *offset, int whence)
{
my_cookie_t* cookie = (my_cookie_t*)p;
return RunFunctionFmt(cookie->s, "ppi", cookie->cookie, offset, whence) ;
}
static int my_cookie_close(void *p)
{
my_cookie_t* cookie = (my_cookie_t*)p;
int ret = 0;
if(cookie->c)
ret = RunFunctionFmt(cookie->c, "p", cookie->cookie) ;
box_free(cookie);
return ret;
}
EXPORT void* my_fopencookie(x64emu_t* emu, void* cookie, void* mode, my_cookie_io_functions_t *s)
{
cookie_io_functions_t io_funcs = {s->read?my_cookie_read:NULL, s->write?my_cookie_write:NULL, s->seek?my_cookie_seek:NULL, my_cookie_close};
my_cookie_t *cb = (my_cookie_t*)box_calloc(1, sizeof(my_cookie_t));
cb->r = (uintptr_t)s->read;
cb->w = (uintptr_t)s->write;
cb->s = (uintptr_t)s->seek;
cb->c = (uintptr_t)s->close;
cb->cookie = cookie;
return fopencookie(cb, mode, io_funcs);
}
#endif
#if 0
EXPORT long my_prlimit64(void* pid, uint32_t res, void* new_rlim, void* old_rlim)
{
return syscall(__NR_prlimit64, pid, res, new_rlim, old_rlim);
}
EXPORT void* my_reallocarray(void* ptr, size_t nmemb, size_t size)
{
return realloc(ptr, nmemb*size);
}
#ifndef __OPEN_NEEDS_MODE
# define __OPEN_NEEDS_MODE(oflag) \
(((oflag) & O_CREAT) != 0)
#endif
EXPORT int my___open_nocancel(x64emu_t* emu, void* file, int oflag, int* b)
{
int mode = 0;
if (__OPEN_NEEDS_MODE (oflag))
mode = b[0];
return openat(AT_FDCWD, file, oflag, mode);
}
EXPORT int my___libc_alloca_cutoff(x64emu_t* emu, size_t size)
{
library_t* lib = my_lib;
if(!lib) return 0;
void* f = dlsym(lib->w.lib, "__libc_alloca_cutoff");
if(f)
return ((iFL_t)f)(size);
return (size<=(65536*4));
}
void* my_dlopen(x64emu_t* emu, void *filename, int flag);
int my_dlclose(x64emu_t* emu, void *handle);
void* my_dlsym(x64emu_t* emu, void *handle, void *symbol);
EXPORT int my___libc_dlclose(x64emu_t* emu, void* handle)
{
return my_dlclose(emu, handle);
}
EXPORT void* my___libc_dlopen_mode(x64emu_t* emu, void* name, int mode)
{
return my_dlopen(emu, name, mode);
}
EXPORT void* my___libc_dlsym(x64emu_t* emu, void* handle, void* name)
{
return my_dlsym(emu, handle, name);
}
EXPORT int my_nanosleep(const struct timespec *req, struct timespec *rem)
{
if(!req)
return 0;
return nanosleep(req, rem);
}
#endif
#ifdef ANDROID
void obstackSetup() {
}
#else
void obstackSetup();
#endif
EXPORT void* my_malloc(unsigned long size)
{
return calloc(1, size);
}
EXPORT int my_setrlimit(x64emu_t* emu, int ressource, const struct rlimit *rlim)
{
int ret = (ressource==RLIMIT_AS)?0:setrlimit(ressource, rlim);
if(ressource==RLIMIT_AS) printf_log(LOG_DEBUG, " (ignored) RLIMIT_AS, cur=0x%lx, max=0x%lx ", rlim->rlim_cur, rlim->rlim_max);
return ret;
}
#if 0
#ifdef PANDORA
#define RENAME_NOREPLACE (1 << 0)
#define RENAME_EXCHANGE (1 << 1)
#define RENAME_WHITEOUT (1 << 2)
EXPORT int my_renameat2(int olddirfd, void* oldpath, int newdirfd, void* newpath, uint32_t flags)
{
if(flags&RENAME_NOREPLACE) {
if(FileExist(newpath, -1)) {
errno = EEXIST;
return -1;
}
flags &= ~RENAME_NOREPLACE;
}
if(!flags) return renameat(olddirfd, oldpath, newdirfd, newpath);
if(flags&RENAME_WHITEOUT) {
errno = EINVAL;
return -1;
}
if((flags&RENAME_EXCHANGE) && (olddirfd==-1) && (newdirfd==-1)) {
char* tmp = (char*)box_malloc(strlen(oldpath)+10);
tmp = strcat(oldpath, ".tmp");
int ret = renameat(-1, oldpath, -1, tmp);
if(ret==-1) return -1;
ret = renameat(-1, newpath, -1, oldpath);
if(ret==-1) return -1;
ret = renameat(-1, tmp, -1, newpath);
box_free(tmp);
return ret;
}
return -1;
}
#endif
#ifndef __NR_memfd_create
#define MFD_CLOEXEC 0x0001U
#define MFD_ALLOW_SEALING 0x0002U
EXPORT int my_memfd_create(x64emu_t* emu, void* name, uint32_t flags)
{
uint32_t fl = O_RDWR | O_CREAT;
if(flags&MFD_CLOEXEC)
fl |= O_CLOEXEC;
int tmp = shm_open(name, fl, S_IRWXU);
if(tmp<0) return -1;
shm_unlink(name);
return tmp;
}
#endif
#ifndef GRND_RANDOM
#define GRND_RANDOM 0x0002
#endif
EXPORT int my_getentropy(x64emu_t* emu, void* buffer, size_t length)
{
library_t* lib = my_lib;
if(!lib) return 0;
void* f = dlsym(lib->w.lib, "getentropy");
if(f)
return ((iFpL_t)f)(buffer, length);
if(length>256) {
errno = EIO;
return -1;
}
int ret = my_getrandom(emu, buffer, length, GRND_RANDOM);
if(ret!=length) {
errno = EIO;
return -1;
}
return 0;
}
EXPORT void my_mcount(void* frompc, void* selfpc)
{
return;
}
#endif
#ifndef ANDROID
union semun {
int val;
struct semid_ds *buf;
unsigned short *array;
struct seminfo *__buf;
(Linux-specific) */
};
#endif
#ifndef SEM_STAT_ANY
#define SEM_STAT_ANY 20
#endif
EXPORT int my_semctl(int semid, int semnum, int cmd, union semun b)
{
struct semid_ds semidds;
void *backup = NULL;
if ((cmd == IPC_STAT) || (cmd == IPC_SET) || (cmd == SEM_STAT) || (cmd == SEM_STAT_ANY)) {
backup = b.buf;
b.buf = &semidds;
if (cmd == IPC_SET) {
AlignSemidDs(&semidds, backup);
}
}
int ret = semctl(semid, semnum, cmd, b);
if ((cmd == IPC_STAT) || (cmd == IPC_SET) || (cmd == SEM_STAT) || (cmd == SEM_STAT_ANY)) {
b.buf = backup;
if (cmd == IPC_STAT) {
UnalignSemidDs(backup, &semidds);
}
}
return ret;
}
EXPORT int64_t userdata_sign = 0x1234598765ABCEF0;
EXPORT uint32_t userdata[1024];
EXPORT long my_ptrace(x64emu_t* emu, int request, pid_t pid, void* addr, uint32_t* data)
{
if(request == PTRACE_POKEUSER) {
if(ptrace(PTRACE_PEEKDATA, pid, &userdata_sign, NULL)==userdata_sign && (uintptr_t)addr < sizeof(userdata)) {
ptrace(PTRACE_POKEDATA, pid, addr+(uintptr_t)userdata, data);
return 0;
}
if((uintptr_t)addr < sizeof(userdata))
*(uintptr_t*)(addr+(uintptr_t)userdata) = (uintptr_t)data;
return 0;
}
if(request == PTRACE_PEEKUSER) {
if(ptrace(PTRACE_PEEKDATA, pid, &userdata_sign, NULL)==userdata_sign && (uintptr_t)addr < sizeof(userdata)) {
return ptrace(PTRACE_PEEKDATA, pid, addr+(uintptr_t)userdata, data);
}
if((uintptr_t)addr < sizeof(userdata))
return *(uintptr_t*)(addr+(uintptr_t)userdata);
}
return ptrace(request, pid, addr, data);
}
#include "elfs/elfdwarf_private.h"
EXPORT int my_backtrace(x64emu_t* emu, void** buffer, int size)
{
if (!size) return 0;
dwarf_unwind_t *unwind = init_dwarf_unwind_registers(emu);
int idx = 0;
char success = 0;
uintptr_t addr = *(uintptr_t*)R_RSP;
buffer[0] = (void*)addr;
while (++idx < size) {
uintptr_t ret_addr = get_parent_registers(unwind, FindElfAddress(my_context, addr), addr, &success);
if (ret_addr == my_context->exit_bridge) {
buffer[idx] = (void*)ret_addr;
success = 2;
unwind->regs[7] = unwind->regs[6];
unwind->regs[6] = *(uint64_t*)unwind->regs[7];
unwind->regs[7] += 8;
ret_addr = *(uint64_t*)unwind->regs[7];
unwind->regs[7] += 8;
if (++idx < size) buffer[idx] = (void*)ret_addr;
} else if (!success) break;
else buffer[idx] = (void*)ret_addr;
addr = ret_addr;
}
free_dwarf_unwind_registers(&unwind);
return idx;
}
EXPORT int my_backtrace_ip(x64emu_t* emu, void** buffer, int size)
{
if (!size) return 0;
dwarf_unwind_t *unwind = init_dwarf_unwind_registers(emu);
int idx = 0;
char success = 1;
uintptr_t addr = R_RIP;
buffer[0] = (void*)addr;
while ((++idx < size) && success) {
uintptr_t ret_addr = get_parent_registers(unwind, FindElfAddress(my_context, addr), addr, &success);
if (ret_addr == my_context->exit_bridge) {
buffer[idx] = (void*)ret_addr;
success = 2;
unwind->regs[7] = unwind->regs[6];
unwind->regs[6] = *(uint64_t*)unwind->regs[7];
unwind->regs[7] += 8;
ret_addr = *(uint64_t*)unwind->regs[7];
unwind->regs[7] += 8;
if (++idx < size) buffer[idx] = (void*)ret_addr;
} else if (!success) {
if(getProtection((uintptr_t)addr)&(PROT_READ)) {
if(getProtection((uintptr_t)addr-19) && *(uint8_t*)(addr-19)==0xCC && *(uint8_t*)(addr-19+1)=='S' && *(uint8_t*)(addr-19+2)=='C') {
buffer[idx-1] = (void*)(addr-19);
success = 2;
if(idx==1)
unwind->regs[7] -= 8;
ret_addr = *(uint64_t*)unwind->regs[7];
unwind->regs[7] += 8;
buffer[idx] = (void*)ret_addr;
} else {
unwind->regs[7] = unwind->regs[6];
if(getProtection(unwind->regs[7])&(PROT_READ)) {
unwind->regs[6] = *(uint64_t*)unwind->regs[7];
unwind->regs[7] += 8;
ret_addr = *(uint64_t*)unwind->regs[7];
unwind->regs[7] += 8;
buffer[idx] = (void*)ret_addr;
success = 2;
} else
break;
}
} else
break;
} else buffer[idx] = (void*)ret_addr;
addr = ret_addr;
}
free_dwarf_unwind_registers(&unwind);
return idx;
}
EXPORT char** my_backtrace_symbols(x64emu_t* emu, uintptr_t* buffer, int size)
{
(void)emu;
char** ret = (char**)calloc(1, size*sizeof(char*) + size*200);
char* s = (char*)(ret+size);
for (int i=0; i<size; ++i) {
uintptr_t start = 0;
uint64_t sz = 0;
elfheader_t *hdr = FindElfAddress(my_context, buffer[i]);
const char* symbname = FindNearestSymbolName(hdr, (void*)buffer[i], &start, &sz);
if(!sz) sz=0x100;
if (symbname && buffer[i]>=start && (buffer[i]<(start+sz) || !sz)) {
snprintf(s, 200, "%s(%s+%lx) [%p]", ElfName(hdr), symbname, buffer[i] - start, (void*)buffer[i]);
} else if (hdr) {
snprintf(s, 200, "%s+%lx [%p]", ElfName(hdr), buffer[i] - (uintptr_t)GetBaseAddress(hdr), (void*)buffer[i]);
} else {
snprintf(s, 200, "??? [%p]", (void*)buffer[i]);
}
ret[i] = s;
s += 200;
}
return ret;
}
EXPORT void my_backtrace_symbols_fd(x64emu_t* emu, uintptr_t* buffer, int size, int fd)
{
(void)emu;
char s[200];
for (int i=0; i<size; ++i) {
uintptr_t start = 0;
uint64_t sz = 0;
const char* symbname = FindNearestSymbolName(FindElfAddress(my_context, buffer[i]), (void*)buffer[i], &start, &sz);
if(!sz) sz=0x100;
if(symbname && buffer[i]>=start && (buffer[i]<(start+sz) || !sz))
snprintf(s, 200, "%s+%ld [%p]\n", symbname, buffer[i] - start, (void*)buffer[i]);
else
snprintf(s, 200, "??? [%p]\n", (void*)buffer[i]);
int dummy = write(fd, s, strlen(s));
(void)dummy;
}
}
EXPORT int my_iopl(x64emu_t* emu, int level)
{
static int searched = 0;
if(!searched) {
searched = 1;
real_iopl = (iFi_t)dlsym(my_lib, "iopl");
}
if(real_iopl)
return real_iopl(level);*/
errno = ENOSYS;
return -1;
}
EXPORT int my_stime(x64emu_t* emu, const time_t *t)
{
errno = EPERM;
return -1;
}
int GetTID();
#ifdef ANDROID
void updateGlibcTidCache() {}
#else
struct glibc_pthread {
#if defined(NO_ALIGN)
char header[704];
#else
void* header[24];
#endif
void* list[2];
pid_t tid;
};
pid_t getGlibcCachedTid() {
pthread_mutex_t lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
pthread_mutex_lock(&lock);
pid_t tid = lock.__data.__owner;
pthread_mutex_unlock(&lock);
pthread_mutex_destroy(&lock);
return tid;
}
void updateGlibcTidCache() {
pid_t real_tid = GetTID();
pid_t cached_tid = getGlibcCachedTid();
if (cached_tid != real_tid) {
pid_t* cached_tid_location =
&((struct glibc_pthread*)(pthread_self()))->tid;
*cached_tid_location = real_tid;
}
}
#endif
typedef struct clone_arg_s {
uintptr_t stack;
x64emu_t *emu;
uintptr_t fnc;
void* args;
int stack_clone_used;
void* tls;
} clone_arg_t;
static int clone_fn(void* p)
{
clone_arg_t* arg = (clone_arg_t*)p;
updateGlibcTidCache();
x64emu_t *emu = arg->emu;
R_RSP = arg->stack;
emu->flags.quitonexit = 1;
thread_set_emu(emu);
int ret = RunFunctionWithEmu(emu, 0, arg->fnc, 1, arg->args);
int exited = (emu->flags.quitonexit==2);
thread_set_emu(NULL);
FreeX64Emu(&emu);
if(arg->stack_clone_used)
my_context->stack_clone_used = 0;
box_free(arg);
exit(ret);*/
return ret;
}
EXPORT int my_clone(x64emu_t* emu, void* fn, void* stack, int flags, void* args, void* parent, void* tls, void* child)
{
printf_log(LOG_DEBUG, "my_clone(fn:%p(%s), stack:%p, 0x%x, args:%p, %p, %p, %p)", fn, getAddrFunctionName((uintptr_t)fn), stack, flags, args, parent, tls, child);
void* mystack = NULL;
clone_arg_t* arg = (clone_arg_t*)box_calloc(1, sizeof(clone_arg_t));
x64emu_t * newemu = NewX64Emu(emu->context, R_RIP, (uintptr_t)stack, 0, 0);
SetupX64Emu(newemu, emu);
if(my_context->stack_clone_used) {
printf_log(LOG_DEBUG, " no free stack_clone ");
mystack = box_malloc(1024*1024);
} else {
if(!my_context->stack_clone)
my_context->stack_clone = box_malloc(1024*1024);
mystack = my_context->stack_clone;
printf_log(LOG_DEBUG, " using stack_clone ");
my_context->stack_clone_used = 1;
arg->stack_clone_used = 1;
}
arg->stack = (uintptr_t)stack &~7LL;
arg->args = args;
arg->fnc = (uintptr_t)fn;
arg->tls = tls;
arg->emu = newemu;
if((flags|(CLONE_VM|CLONE_VFORK|CLONE_SETTLS))==flags)
flags&=~(CLONE_VM|CLONE_VFORK|CLONE_SETTLS);
int64_t ret = clone(clone_fn, (void*)((uintptr_t)mystack+1024*1024), flags, arg, parent, NULL, child);
return (uintptr_t)ret;
}
EXPORT void my___cxa_pure_virtual(x64emu_t* emu)
{
printf_log(LOG_NONE, "Pure virtual function called\n");
emu->quit = 1;
abort();
}
EXPORT size_t my_strlcpy(x64emu_t* emu, void* dst, void* src, size_t l)
{
strncpy(dst, src, l-1);
((char*)dst)[l-1] = '\0';
return strlen(src);
}
EXPORT size_t my_strlcat(x64emu_t* emu, void* dst, void* src, size_t l)
{
size_t s = strlen(dst);
if(s>=l)
return l;
strncat(dst, src, l-1);
((char*)dst)[l-1] = '\0';
return s+strlen(src);
}
EXPORT int my_register_printf_specifier(x64emu_t* emu, int c, void* f1, void* f2)
{
return my->register_printf_specifier(c, findprintf_outputFct(f1), findprintf_arginfoFct(f2));
}
EXPORT int my_register_printf_type(x64emu_t* emu, void* f)
{
return my->register_printf_type(findprintf_typeFct(f));
}
extern int box64_quit;
extern int box64_exit_code;
void endBox64();
static void* timed_exit_thread(void* a)
{
usleep(5000000);
printf_log(LOG_DEBUG, "Too late, forced exit...\n");
_exit(box64_exit_code);
}
void startTimedExit()
{
static int started = 0;
if(started)
return;
started = 1;
pthread_t exit_thread;
pthread_create(&exit_thread, NULL, timed_exit_thread, NULL);
}
EXPORT void my_exit(x64emu_t* emu, int code)
{
if(emu->flags.quitonexit) {
emu->quit = 1;
R_EAX = code;
emu->flags.quitonexit = 2;
return;
}
emu->quit = 1;
box64_exit_code = code;
endBox64();
startTimedExit();
exit(code);
}
EXPORT void my__exit(x64emu_t* emu, int code) __attribute__((alias("my_exit")));
EXPORT int my_prctl(x64emu_t* emu, int option, unsigned long arg2, unsigned long arg3, unsigned long arg4, unsigned long arg5)
{
if(option==PR_SET_NAME) {
printf_log(LOG_DEBUG, "BOX64: set process name to \"%s\"\n", (char*)arg2);
ApplyParams((char*)arg2);
size_t l = strlen((char*)arg2);
if(l>4 && !strcasecmp((char*)arg2+l-4, ".exe")) {
printf_log(LOG_DEBUG, "BOX64: hacking orig command line to \"%s\"\n", (char*)arg2);
strcpy(my_context->orig_argv[0], (char*)arg2);
}
}
if(option==PR_SET_SECCOMP) {
printf_log(LOG_INFO, "BOX64: ignoring prctl(PR_SET_SECCOMP, ...)\n");
return 0;
}
return prctl(option, arg2, arg3, arg4, arg5);
}
#ifndef _SC_NPROCESSORS_ONLN
#define _SC_NPROCESSORS_ONLN 84
#endif
#ifndef _SC_NPROCESSORS_CONF
#define _SC_NPROCESSORS_CONF 83
#endif
EXPORT long my_sysconf(x64emu_t* emu, int what) {
if(what==_SC_NPROCESSORS_ONLN) {
return getNCpu();
}
if(what==_SC_NPROCESSORS_CONF) {
return getNCpu();
}
return sysconf(what);
}
EXPORT long my___sysconf(x64emu_t* emu, int what) __attribute__((alias("my_sysconf")));
EXPORT char* my___progname = NULL;
EXPORT char* my___progname_full = NULL;
EXPORT char* my_program_invocation_name = NULL;
EXPORT char* my_program_invocation_short_name = NULL;
EXPORT char my___libc_single_threaded = 0;
#ifdef STATICBUILD
#include "libtools/static_libc.h"
#endif
#ifndef STATICBUILD
#define PRE_INIT\
if(1) \
lib->w.lib = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL); \
else
#endif
#ifdef ANDROID
#define NEEDED_LIBS_DEF 4,\
"libpthread.so", \
"libdl.so" , \
"libm.so", \
"libbsd.so"
#define NEEDED_LIBS_234 4, \
"libpthread.so", \
"libdl.so" , \
"libm.so", \
"libbsd.so"
#else
#define NEEDED_LIBS_DEF 6,\
"ld-linux-x86-64.so.2", \
"libpthread.so.0", \
"libdl.so.2", \
"libutil.so.1", \
"librt.so.1", \
"libbsd.so.0"
#define NEEDED_LIBS_234 7, \
"ld-linux-x86-64.so.2", \
"libpthread.so.0", \
"libdl.so.2", \
"libutil.so.1", \
"libresolv.so.2", \
"librt.so.1", \
"libbsd.so.0"
#endif
#undef HAS_MY
#define CUSTOM_INIT \
box64->libclib = lib; \
\
ctSetup(); \
obstackSetup(); \
my_environ = my__environ = my___environ = box64->envv; \
my___progname_full = my_program_invocation_name = box64->argv[0]; \
my___progname = my_program_invocation_short_name = \
strrchr(box64->argv[0], '/') + 1; \
getMy(lib); \
if(box64_isglibc234) \
setNeededLibs(lib, NEEDED_LIBS_234); \
else \
setNeededLibs(lib, NEEDED_LIBS_DEF);
#define CUSTOM_FINI \
freeMy(); \
return;
#include "wrappedlib_init.h"