From 7716633bf762db3e57e51e325d045d4a3eebdb50 Mon Sep 17 00:00:00 2001 From: ptitSeb Date: Fri, 5 Mar 2021 10:16:02 +0100 Subject: Added printf wrapped function and some VA_ARG work --- src/include/myalign.h | 43 ++++ src/libtools/myalign.c | 427 +++++++++++++++++++++++++++++++ src/wrapped/generated/functions_list.txt | 1 + src/wrapped/generated/wrapper.c | 4 +- src/wrapped/generated/wrapper.h | 1 + src/wrapped/wrappedlibc.c | 26 +- src/wrapped/wrappedlibc_private.h | 2 +- 7 files changed, 484 insertions(+), 20 deletions(-) create mode 100755 src/include/myalign.h create mode 100755 src/libtools/myalign.c (limited to 'src') diff --git a/src/include/myalign.h b/src/include/myalign.h new file mode 100755 index 00000000..1d5a6b72 --- /dev/null +++ b/src/include/myalign.h @@ -0,0 +1,43 @@ +#include + +#ifdef __x86_64__ +// x86_64, 6 64bits general regs and 16 or 8? 128bits float regs +#define CREATE_SYSV_VALIST(A) \ + va_list sysv_varargs; \ + sysv_varargs->gp_offset=(6*8); \ + sysv_varargs->fp_offset=(6*8)+(16*16); \ + sysv_varargs->overflow_arg_area=A; +#elif defined(__aarch64__) +// aarch64: 8 64bits general regs and 8 128bits float regs +#define CREATE_SYSV_VALIST(A) \ + va_list sysv_varargs; \ + sysv_varargs->gp_offset=(8*8); \ + sysv_varargs->fp_offset=(8*8)+(8*16); \ + sysv_varargs->overflow_arg_area=A; +#elif defined(__powerpc64__) +// TODO, is this correct? +#define CREATE_SYSV_VALIST(A) \ + va_list sysv_varargs; \ + sysv_varargs->gpr=8; \ + sysv_varargs->fpr=8; \ + sysv_varargs->overflow_arg_area=A; +#else +#error Unknown architecture! +#endif + + +#define VARARGS sysv_varargs +#define PREPARE_VALIST CREATE_SYSV_VALIST(emu->scratch) +#define VARARGS_(A) sysv_varargs +#define PREPARE_VALIST_(A) CREATE_SYSV_VALIST(A) + +typedef struct x64emu_s x64emu_t; + +// 1st pos is of vaarg is 0, not 1! +void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos); +void myStackAlignGVariantNew(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos); +void myStackAlignW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos); + +// defined in wrapperlibc.c +int of_convert(int); // x86->arm +int of_unconvert(int); // arm->x86 diff --git a/src/libtools/myalign.c b/src/libtools/myalign.c new file mode 100755 index 00000000..c621fc64 --- /dev/null +++ b/src/libtools/myalign.c @@ -0,0 +1,427 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "x64emu.h" +#include "emu/x64emu_private.h" +#include "myalign.h" + +static int regs_abi[] = {_DI, _SI, _DX, _CX, _R8, _R9}; + +void myStackAlign(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos) +{ + + if(!fmt) + return; + // loop... + const char* p = fmt; + int state = 0; + #ifndef HAVE_LD80BITS + double d; + #endif + int x = 0; + while(*p) + { + switch(state) { + case 0: + switch(*p) { + case '%': state = 1; ++p; break; + default: + ++p; + } + break; + case 1: // normal + case 2: // l + case 3: // ll + case 4: // L + switch(*p) { + case '%': state = 0; ++p; break; //%% = back to 0 + case 'l': ++state; if (state>3) state=3; ++p; break; + case 'L': state = 4; ++p; break; + case 'a': + case 'A': + case 'e': + case 'E': + case 'g': + case 'G': + case 'F': + case 'f': state += 10; break; // float + case 'd': + case 'i': + case 'o': + case 'u': + case 'x': + case 'X': state += 20; break; // int + case 'h': ++p; break; // ignored... + case '\'': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + case '+': + case '-': ++p; break; // formating, ignored + case 'm': state = 0; ++p; break; // no argument + case 'n': + case 'p': + case 'S': + case 's': state = 30; break; // pointers + case '$': ++p; break; // should issue a warning, it's not handled... + case '*': *(mystack++) = *(st++); ++p; break; // fetch an int in the stack.... + case ' ': state=0; ++p; break; + default: + state=20; // other stuff, put an int... + } + break; + case 11: //double + case 12: //%lg, still double + case 13: //%llg, still double + if(xmm) { + *mystack = emu->xmm[x++].q[0]; + --xmm; + } else { + *mystack = *st; + st++; mystack++; + } + state = 0; + ++p; + break; + case 14: //%LG long double + #ifdef HAVE_LD80BITS + memcpy(mystack, st, 16); + st+=2; mystack+=2; + #else + // there is no long double on ARM, so tranform that in a regular double + LD2D((void*)st, &d); + *mystack = *(uint64_t*)&d; + st+=2; mystack+=1; + #endif + state = 0; + ++p; + break; + case 20: // fallback + case 21: + case 22: + case 23: // 64bits int + case 24: // normal int / pointer + case 30: + if(pos<6) + *mystack = emu->regs[regs_abi[pos++]].q[0]; + else { + *mystack = *st; + ++st; + } + ++mystack; + state = 0; + ++p; + break; + default: + // whattt? + state = 0; + } + } +} +#if 0 +void myStackAlignGVariantNew(const char* fmt, uint32_t* st, uint32_t* mystack) +{ + if (!fmt) + return; + + const char *p = fmt; + int state = 0; + int inblocks = 0; + int tmp; + + do { + switch(state) { + case 0: // Nothing + switch(*p) { + case 'b': // gboolean + case 'y': // guchar + case 'n': // gint16 + case 'q': // guint16 + case 'i': // gint32 + case 'u': // guint32 + case 'h': // gint32 + case 's': // const gchar* + case 'o': + case 'g': + case 'v': // GVariant* + case '*': // GVariant* of any type + case '?': // GVariant* of basic type + case 'r': // GVariant* of tuple type + *mystack = *st; + ++mystack; + ++st; + break; + case 'x': // gint64 + case 't': // guint64 + case 'd': // gdouble + if ((((uint32_t)mystack)&0x7)!=0) + ++mystack; + *(uint64_t*)mystack = *(uint64_t*)st; + st+=2; mystack+=2; + break; + case '{': + case '(': ++inblocks; break; + case '}': + case ')': --inblocks; break; + case 'a': state = 1; break; // GVariantBuilder* or GVariantIter** + case 'm': state = 2; break; // maybe types + case '@': state = 3; break; // GVariant* of type [type] + case '^': state = 4; break; // pointer value + case '&': break; // pointer: do nothing + } + break; + case 1: // Arrays + switch(*p) { + case '{': + case '(': ++tmp; break; + case '}': + case ')': --tmp; break; + } + if (*p == 'a') break; + if (tmp == 0) { + *mystack = *st; + ++mystack; + ++st; + state = 0; + } + break; + case 2: // Maybe-types + switch(*p) { + case 'b': // gboolean + case 'y': // guchar + case 'n': // gint16 + case 'q': // guint16 + case 'i': // gint32 + case 'u': // guint32 + case 'h': // gint32 + case 'x': // gint64 + case 't': // guint64 + case 'd': // gdouble + case '{': + case '}': + case '(': + case ')': + // Add a gboolean or gboolean*, no char increment + *mystack = *st; + ++mystack; + ++st; + --p; + state = 0; + break; + case 'a': // GVariantBuilder* or GVariantIter** + case 's': // const gchar* + case 'o': + case 'g': + case 'v': // GVariant* + case '@': // GVariant* of type [type] + case '*': // GVariant* of any type + case '?': // GVariant* of basic type + case 'r': // GVariant* of tuple type + case '&': // pointer + case '^': // pointer value + // Just maybe-NULL + --p; + state = 0; + break; + + default: // Default to add a gboolean & reinit state? + *mystack = *st; + ++mystack; + ++st; + --p; + state = 0; + } + break; + case 3: // GVariant* + switch(*p) { + case '{': + case '(': ++tmp; break; + case '}': + case ')': --tmp; break; + case 'a': // GVariantBuilder* or GVariantIter** + do { ++p; } while(*p == 'a'); // Use next character which is not an array (array definition) + switch(*p) { + case '{': + case '(': ++tmp; break; + case '}': + case ')': --tmp; break; + } + break; + } + if (tmp == 0) { + *mystack = *st; + ++mystack; + ++st; + state = 0; + } + break; + case 4: // ^ + if (*p == 'a') state = 5; + else if (*p == '&') state = 8; + else state = 0; //??? + break; + case 5: // ^a + if ((*p == 's') || (*p == 'o') || (*p == 'y')) { + *mystack = *st; + ++mystack; + ++st; + state = 0; + } else if (*p == '&') state = 6; + else if (*p == 'a') state = 7; + else state = 0; //??? + break; + case 6: // ^a& + if ((*p == 's') || (*p == 'o')) { + *mystack = *st; + ++mystack; + ++st; + state = 0; + } else if (*p == 'a') state = 7; + else state = 0; //??? + break; + case 7: // ^aa / ^a&a + if (*p == 'y') { + *mystack = *st; + ++mystack; + ++st; + state = 0; + } else state = 0; //??? + case 8: // ^& + if (*p == 'a') state = 9; + else state = 0; //??? + case 9: // ^&a + if (*p == 'y') { + *mystack = *st; + ++mystack; + ++st; + state = 0; + } else state = 0; //??? + } + ++p; + } while (*p && (inblocks || state)); +} + +void myStackAlignW(const char* fmt, uint32_t* st, uint32_t* mystack) +{ + // loop... + const wchar_t* p = (const wchar_t*)fmt; + int state = 0; + double d; + while(*p) + { + switch(state) { + case 0: + switch(*p) { + case '%': state = 1; ++p; break; + default: + ++p; + } + break; + case 1: // normal + case 2: // l + case 3: // ll + case 4: // L + switch(*p) { + case '%': state = 0; ++p; break; //%% = back to 0 + case 'l': ++state; if (state>3) state=3; ++p; break; + case 'L': state = 4; ++p; break; + case 'a': + case 'A': + case 'e': + case 'E': + case 'g': + case 'G': + case 'F': + case 'f': state += 10; break; // float + case 'd': + case 'i': + case 'o': + case 'u': + case 'x': + case 'X': state += 20; break; // int + case 'h': ++p; break; // ignored... + case '\'': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case '.': + case '+': + case '-': ++p; break; // formating, ignored + case 'm': state = 0; ++p; break; // no argument + case 'n': + case 'p': + case 'S': + case 's': state = 30; break; // pointers + case '$': ++p; break; // should issue a warning, it's not handled... + case '*': *(mystack++) = *(st++); ++p; break; //fetch an int in the stack + case ' ': state=0; ++p; break; + default: + state=20; // other stuff, put an int... + } + break; + case 11: //double + case 12: //%lg, still double + case 13: //%llg, still double + case 23: // 64bits int + if((((uint32_t)mystack)&0x7)!=0) + mystack++; + *(uint64_t*)mystack = *(uint64_t*)st; + st+=2; mystack+=2; + state = 0; + ++p; + break; + case 14: //%LG long double + #ifdef HAVE_LD80BITS + if((((uint32_t)mystack)&0x7)!=0) + mystack++; + memcpy(mystack, st, 10); + st+=3; mystack+=3; + #else + // there is no long double on ARM, so tranform that in a regular double + LD2D((void*)st, &d); + if((((uint32_t)mystack)&0x7)!=0) + mystack++; + *(uint64_t*)mystack = *(uint64_t*)&d; + st+=3; mystack+=2; + #endif + state = 0; + ++p; + break; + case 20: // fallback + case 21: + case 22: + case 24: // normal int / pointer + case 30: + *mystack = *st; + ++mystack; + ++st; + state = 0; + ++p; + break; + default: + // whattt? + state = 0; + } + } +} +#endif diff --git a/src/wrapped/generated/functions_list.txt b/src/wrapped/generated/functions_list.txt index c3c09f9b..7674cf90 100644 --- a/src/wrapped/generated/functions_list.txt +++ b/src/wrapped/generated/functions_list.txt @@ -14,6 +14,7 @@ #() pFEp #() vFEpu #() iFEpp +#() iFEpV #() iFpiu #() pFEpi #() pFEpp diff --git a/src/wrapped/generated/wrapper.c b/src/wrapped/generated/wrapper.c index 6eb1d761..f7aa3fea 100644 --- a/src/wrapped/generated/wrapper.c +++ b/src/wrapped/generated/wrapper.c @@ -85,6 +85,7 @@ typedef int32_t (*iFup_t)(uint32_t, void*); typedef void* (*pFEp_t)(x64emu_t*, void*); typedef void (*vFEpu_t)(x64emu_t*, void*, uint32_t); typedef int32_t (*iFEpp_t)(x64emu_t*, void*, void*); +typedef int32_t (*iFEpV_t)(x64emu_t*, void*, void*); typedef int32_t (*iFpiu_t)(void*, int32_t, uint32_t); typedef void* (*pFEpi_t)(x64emu_t*, void*, int32_t); typedef void* (*pFEpp_t)(x64emu_t*, void*, void*); @@ -114,6 +115,7 @@ void iFup(x64emu_t *emu, uintptr_t fcn) { iFup_t fn = (iFup_t)fcn; R_RAX=fn((uin void pFEp(x64emu_t *emu, uintptr_t fcn) { pFEp_t fn = (pFEp_t)fcn; R_RAX=(uintptr_t)fn(emu, (void*)R_RDI); } void vFEpu(x64emu_t *emu, uintptr_t fcn) { vFEpu_t fn = (vFEpu_t)fcn; fn(emu, (void*)R_RDI, (uint32_t)R_RSI); } void iFEpp(x64emu_t *emu, uintptr_t fcn) { iFEpp_t fn = (iFEpp_t)fcn; R_RAX=fn(emu, (void*)R_RDI, (void*)R_RSI); } +void iFEpV(x64emu_t *emu, uintptr_t fcn) { iFEpV_t fn = (iFEpV_t)fcn; R_RAX=fn(emu, (void*)R_RDI, (void*)(R_RSP + 16)); } void iFpiu(x64emu_t *emu, uintptr_t fcn) { iFpiu_t fn = (iFpiu_t)fcn; R_RAX=fn((void*)R_RDI, (int32_t)R_RSI, (uint32_t)R_RDX); } void pFEpi(x64emu_t *emu, uintptr_t fcn) { pFEpi_t fn = (pFEpi_t)fcn; R_RAX=(uintptr_t)fn(emu, (void*)R_RDI, (int32_t)R_RSI); } void pFEpp(x64emu_t *emu, uintptr_t fcn) { pFEpp_t fn = (pFEpp_t)fcn; R_RAX=(uintptr_t)fn(emu, (void*)R_RDI, (void*)R_RSI); } @@ -125,7 +127,7 @@ void iFuipp(x64emu_t *emu, uintptr_t fcn) { iFuipp_t fn = (iFuipp_t)fcn; R_RAX=f void pFEppi(x64emu_t *emu, uintptr_t fcn) { pFEppi_t fn = (pFEppi_t)fcn; R_RAX=(uintptr_t)fn(emu, (void*)R_RDI, (void*)R_RSI, (int32_t)R_RDX); } void pFEppp(x64emu_t *emu, uintptr_t fcn) { pFEppp_t fn = (pFEppp_t)fcn; R_RAX=(uintptr_t)fn(emu, (void*)R_RDI, (void*)R_RSI, (void*)R_RDX); } void iFipppi(x64emu_t *emu, uintptr_t fcn) { iFipppi_t fn = (iFipppi_t)fcn; R_RAX=fn((int32_t)R_RDI, (void*)R_RSI, (void*)R_RDX, (void*)R_RCX, (int32_t)R_R8); } -void iFEpippppp(x64emu_t *emu, uintptr_t fcn) { iFEpippppp_t fn = (iFEpippppp_t)fcn; R_RAX=fn(emu, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, *(void**)(R_RSP + 16), *(void**)(R_RSP + 24)); } +void iFEpippppp(x64emu_t *emu, uintptr_t fcn) { iFEpippppp_t fn = (iFEpippppp_t)fcn; R_RAX=fn(emu, (void*)R_RDI, (int32_t)R_RSI, (void*)R_RDX, (void*)R_RCX, (void*)R_R8, (void*)R_R9, *(void**)(R_RSP + 16)); } void iFEv(x64emu_t *emu, uintptr_t fcn) { iFE_t fn = (iFE_t)fcn; R_RAX=fn(emu); } void pFEv(x64emu_t *emu, uintptr_t fcn) { pFE_t fn = (pFE_t)fcn; R_RAX=(uintptr_t)fn(emu); } diff --git a/src/wrapped/generated/wrapper.h b/src/wrapped/generated/wrapper.h index ebcd25fa..ddc3d411 100644 --- a/src/wrapped/generated/wrapper.h +++ b/src/wrapped/generated/wrapper.h @@ -46,6 +46,7 @@ void iFup(x64emu_t *emu, uintptr_t fnc); void pFEp(x64emu_t *emu, uintptr_t fnc); void vFEpu(x64emu_t *emu, uintptr_t fnc); void iFEpp(x64emu_t *emu, uintptr_t fnc); +void iFEpV(x64emu_t *emu, uintptr_t fnc); void iFpiu(x64emu_t *emu, uintptr_t fnc); void pFEpi(x64emu_t *emu, uintptr_t fnc); void pFEpp(x64emu_t *emu, uintptr_t fnc); diff --git a/src/wrapped/wrappedlibc.c b/src/wrapped/wrappedlibc.c index 00b2f417..56b04f3b 100755 --- a/src/wrapped/wrappedlibc.c +++ b/src/wrapped/wrappedlibc.c @@ -42,12 +42,12 @@ #include "debug.h" #include "wrapper.h" #include "bridge.h" -//#include "callback.h" +#include "callback.h" #include "librarian.h" #include "librarian/library_private.h" #include "emu/x64emu_private.h" #include "box64context.h" -//#include "myalign.h" +#include "myalign.h" //#include "signals.h" #include "fileutils.h" #include "auxval.h" @@ -569,25 +569,15 @@ EXPORT void my___longjmp_chk(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/voi EXPORT int32_t my_setjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p); EXPORT int32_t my__setjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) __attribute__((alias("my_setjmp"))); EXPORT int32_t my___sigsetjmp(x64emu_t* emu, /*struct __jmp_buf_tag __env[1]*/void *p) __attribute__((alias("my_setjmp"))); +#endif -void myStackAlign(const char* fmt, uint32_t* st, uint32_t* mystack); // align st into mystack according to fmt (for v(f)printf(...)) -typedef int (*iFpp_t)(void*, void*); -typedef int (*iFppp_t)(void*, void*, void*); -typedef int (*iFpupp_t)(void*, uint32_t, void*, void*); -EXPORT int my_printf(x64emu_t *emu, void* fmt, void* b, va_list V) { - #ifndef NOALIGN - // need to align on arm - myStackAlign((const char*)fmt, b, emu->scratch); +EXPORT int my_printf(x64emu_t *emu, void* fmt, void* b) { + myStackAlign(emu, (const char*)fmt, b, emu->scratch, R_EAX, 1); PREPARE_VALIST; - void* f = vprintf; - return ((iFpp_t)f)(fmt, VARARGS); - #else - // other platform don't need that - return vprintf((const char*)fmt, V); - #endif + return vprintf((const char*)fmt, VARARGS); } -EXPORT int my___printf_chk(x64emu_t *emu, void* fmt, void* b, va_list V) __attribute__((alias("my_printf"))); - +EXPORT int my___printf_chk(x64emu_t *emu, void* fmt, void* b) __attribute__((alias("my_printf"))); +#if 0 EXPORT int my_vprintf(x64emu_t *emu, void* fmt, void* b, va_list V) { #ifndef NOALIGN // need to align on arm diff --git a/src/wrapped/wrappedlibc_private.h b/src/wrapped/wrappedlibc_private.h index dfce6d7d..20945388 100755 --- a/src/wrapped/wrappedlibc_private.h +++ b/src/wrapped/wrappedlibc_private.h @@ -1331,7 +1331,7 @@ GO(name_to_handle_at, iFipppi) //GO(preadv2, //GO(preadv64, //GO(preadv64v2, -//GO(printf, +GOM(printf, iFEpV) //GO(__printf_chk, //GO(__printf_fp, //GO(printf_size, -- cgit 1.4.1