about summary refs log tree commit diff stats
diff options
context:
space:
mode:
authorptitSeb <sebastien.chev@gmail.com>2021-03-05 10:16:02 +0100
committerptitSeb <sebastien.chev@gmail.com>2021-03-05 10:16:02 +0100
commit7716633bf762db3e57e51e325d045d4a3eebdb50 (patch)
tree9a2bf4df911a4ed1c4acc2cfe8fb5f9faceb3342
parent2e3c25f8e17fd73edd59d3e818e48e56f373c058 (diff)
downloadbox64-7716633bf762db3e57e51e325d045d4a3eebdb50.tar.gz
box64-7716633bf762db3e57e51e325d045d4a3eebdb50.zip
Added printf wrapped function and some VA_ARG work
-rwxr-xr-xCMakeLists.txt1
-rwxr-xr-xrebuild_wrappers.py30
-rwxr-xr-xsrc/include/myalign.h43
-rwxr-xr-xsrc/libtools/myalign.c427
-rw-r--r--src/wrapped/generated/functions_list.txt1
-rw-r--r--src/wrapped/generated/wrapper.c4
-rw-r--r--src/wrapped/generated/wrapper.h1
-rwxr-xr-xsrc/wrapped/wrappedlibc.c26
-rwxr-xr-xsrc/wrapped/wrappedlibc_private.h2
9 files changed, 502 insertions, 33 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 63f14706..cfc55967 100755
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -117,6 +117,7 @@ set(ELFLOADER_SRC
     "${BOX64_ROOT}/src/librarian/librarian.c"
     "${BOX64_ROOT}/src/librarian/library.c"
     "${BOX64_ROOT}/src/libtools/auxval.c"
+    "${BOX64_ROOT}/src/libtools/myalign.c"
     "${BOX64_ROOT}/src/libtools/threads.c"
     "${BOX64_ROOT}/src/tools/box64stack.c"
     "${BOX64_ROOT}/src/tools/bridge.c"
diff --git a/rebuild_wrappers.py b/rebuild_wrappers.py
index fcab11dc..77528635 100755
--- a/rebuild_wrappers.py
+++ b/rebuild_wrappers.py
@@ -376,16 +376,16 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
 		reg_arg = ["R_RDI", "R_RSI", "R_RDX", "R_RCX", "R_R8", "R_R9"]
 		# vreg: value is in a general register
 		#         E  e  v  c  w  i  I  C  W  u  U  f  d  D  K  l  L  p  V  O  S  2  P  G  N, M
-		vreg   = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0]
+		vreg   = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 2]
 		# vxmm: value is in a XMM register
 		#         E  e  v  c  w  i  I  C  W  u  U  f  d  D  K  l  L  p  V  O  S  2  P  G  N, M
 		vxmm   = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]
 		# vother: value is elsewere
 		#         E  e  v  c  w  i  I  C  W  u  U  f  d  D  K  l  L  p  V  O  S  2  P  G  N, M
-		vother = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1]
+		vother = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0]
 		# vstack: value is on the stack (or out of register)
 		#         E  e  v  c  w  i  I  C  W  u  U  f  d  D  K  l  L  p  V  O  S  2  P  G  N, M
-		vstack = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 0]
+		vstack = [0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 2]
 		arg_s = [
 			"",											# E
 			"",											# e
@@ -405,14 +405,14 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
 			"*(intptr_t*)(R_RSP + {p}), ",				# l
 			"*(uintptr_t*)(R_RSP + {p}), ",				# L
 			"*(void**)(R_RSP + {p}), ",					# p
-			"(void*)(R_RSP + {p}), ",					# V
+			"",					# V
 			"of_convert(*(int32_t*)(R_RSP + {p})), ",	# O
 			"io_convert(*(void**)(R_RSP + {p})), ",		# S
 			"(_2uint_struct_t){{*(uintptr_t*)(R_RSP + {p}),*(uintptr_t*)(R_RSP + {p} + 4)}}, ",	# 2
 			"",									# P
 			"",								# G
 			"*(void**)(R_RSP + {p}), ",					# N
-			"*(void**)(R_RSP + {p}),*(void**)(R_RSP + {p} + 4), ",	# M
+			"*(void**)(R_RSP + {p}),*(void**)(R_RSP + {p} + 8), ",	# M
 		]
 		arg_r = [
 			"",                                  		# E
@@ -439,8 +439,8 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
 			"",	# 2
 			"",                               # P
 			"",                              # G
-			"",				  # N
-			"",	# M
+			"(void*){p}, ",				  # N
+			"(void*){p}, ",	# M
 		]
 		arg_x = [
 			"",                                  # E
@@ -489,14 +489,14 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
 			"",            # l
 			"",           # L
 			"",               # p
-			"",                 # V
+			"(void*)(R_RSP + {p}), ",                 # V
 			"", # O
 			"",   # S
 			"",	# 2
 			"arg{p}, ",                               # P
 			"&arg{p}, ",                              # G
-			"*(void**)(R_RSP + {p}), ",					# N
-			"*(void**)(R_RSP + {p}),*(void**)(R_RSP + {p} + 4), ",	# M
+			"",					# N
+			"",	# M
 		]
 
 		vals = [
@@ -546,9 +546,13 @@ typedef void (*wrapper_t)(x64emu_t* emu, uintptr_t fnc);
 				return "1, " + function_args(args[1:], d, r, x)
 			
 			idx = values.index(args[0])
-			if r<5 and vreg[idx]>0:
-    				return arg_r[idx].format(p=reg_arg[r]) + function_args(args[1:], d, r+1, x)
-			if x<7 and vxmm[idx]>0:
+			if r<6 and vreg[idx]>0:
+					if vreg[idx]==2 and r==6:
+						return arg_r[idx-1].format(p=reg_arg[r]) + arg_s[idx-1].format(p=d) + function_args(args[1:], d + vother[idx-1]*8, r+1, x)
+					if vreg[idx]==2 and r<6:
+						return arg_r[idx].format(p=reg_arg[r]) + arg_r[idx].format(p=reg_arg[r+1]) + function_args(args[1:], d, r+2, x)
+					return arg_r[idx].format(p=reg_arg[r]) + function_args(args[1:], d, r+1, x)
+			if x<8 and vxmm[idx]>0:
 					return arg_x[idx].format(p=x) + function_args(args[1:], d, r, x+1)
 			if vstack[idx]>0:
     				return arg_s[idx].format(p=d) + function_args(args[1:], d+8*vstack[idx], r, x)
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 <stdint.h>
+
+#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 <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdint.h>
+#include <wchar.h>
+#include <sys/epoll.h>
+#include <fts.h>
+
+#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,