Added printf wrapped function and some VA_ARG work

This commit is contained in:
ptitSeb 2021-03-05 10:16:02 +01:00
parent 2e3c25f8e1
commit 7716633bf7
9 changed files with 502 additions and 33 deletions

View File

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

View File

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

43
src/include/myalign.h Executable file
View File

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

427
src/libtools/myalign.c Executable file
View File

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

View File

@ -14,6 +14,7 @@
#() pFEp
#() vFEpu
#() iFEpp
#() iFEpV
#() iFpiu
#() pFEpi
#() pFEpp

View File

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

View File

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

View File

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

View File

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