diff --git a/src/emu/x64emu_private.h b/src/emu/x64emu_private.h index 6b6c75e7f..0c02f5edf 100644 --- a/src/emu/x64emu_private.h +++ b/src/emu/x64emu_private.h @@ -58,6 +58,8 @@ typedef struct emu_flags_s { #define JUMPBUFF struct __jmp_buf_tag #endif +#define N_SCRATCH 200 + typedef struct x64emu_s { // cpu reg64_t regs[16]; @@ -119,7 +121,7 @@ typedef struct x64emu_s { #endif // scratch stack, used for alignment of double and 64bits ints on arm. 200 elements should be enough __int128_t dummy_align; // here to have scratch 128bits aligned - uint64_t scratch[200]; + uint64_t scratch[N_SCRATCH]; // local stack, do be deleted when emu is freed void* stack2free; // this is the stack to free (can be NULL) void* init_stack; // initial stack (owned or not) diff --git a/src/include/myalign32.h b/src/include/myalign32.h index bf382c659..57ae0194e 100755 --- a/src/include/myalign32.h +++ b/src/include/myalign32.h @@ -77,9 +77,11 @@ typedef struct va_list { #define PREPARE_VALIST_32_(A) CREATE_SYSV_VALIST_32(A) void myStackAlign32(const char* fmt, uint32_t* st, uint64_t* mystack); -void myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack); +size_t myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem); // return the number of long/ptr_t conversion pending +void myStackAlignScanf32_final(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem, int n); // convert the long/ptr_t scanf results void myStackAlignGVariantNew32(const char* fmt, uint32_t* st, uint64_t* mystack); -void myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack); +size_t myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem); +void myStackAlignScanfW32_final(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem, int n); void myStackAlignW32(const char* fmt, uint32_t* st, uint64_t* mystack); void UnalignStat64_32(const void* source, void* dest); diff --git a/src/libtools/myalign32.c b/src/libtools/myalign32.c index 47aa3ff3e..83a4fbddd 100755 --- a/src/libtools/myalign32.c +++ b/src/libtools/myalign32.c @@ -139,13 +139,14 @@ void myStackAlign32(const char* fmt, uint32_t* st, uint64_t* mystack) } } -void myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack) +size_t myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem) { if(!fmt) - return; + return 0; // loop... const char* p = fmt; + size_t conv = 0; int state = 0; int ign = 0; while(*p) @@ -179,10 +180,10 @@ void myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack) case 'f': state += 10; break; // float case 'd': case 'i': - case 'o': + case 'o': state += 20; break; // int case 'u': case 'x': - case 'X': state += 20; break; // int + case 'X': state += 40; break; // usigned int case 'h': ++p; break; // ignored... case '\'': case '0': @@ -211,6 +212,22 @@ void myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack) state=20; // other stuff, put an int... } break; + case 22: // long uint + case 25: // size_t int + case 42: // long uint + case 45: + case 30: // pointer + if(!ign) { + ++conv; + mystack[nb_elem-conv] = 0; + *mystack = (uintptr_t)&mystack[nb_elem-conv]; + ++st; + ++mystack; + } + state = 0; + ++p; + break; + case 11: //double case 12: //%lg, still double case 13: //%llg, still double @@ -218,11 +235,139 @@ void myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack) case 15: //%zg case 20: // fallback case 21: - case 22: case 23: // 64bits int case 24: // normal int / pointer + case 40: + case 41: + case 43: + case 44: + if(!ign) { + *mystack = *st; + ++st; + ++mystack; + } + state = 0; + ++p; + break; + default: + // whaaaat? + state = 0; + } + } + return conv; +} + +void myStackAlignScanf32_final(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem, int n) +{ + + if(!fmt || n<=0) + return; + // loop... + const char* p = fmt; + size_t conv = 0; + int state = 0; + int ign = 0; + while(*p) + { + switch(state) { + case 0: + ign = 0; + switch(*p) { + case '%': state = 1; ++p; break; + default: + ++p; + } + break; + case 1: // normal + case 2: // l + case 3: // ll + case 4: // L + case 5: // z + 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 'z': state = 5; ++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': state += 20; break; // int + case 'u': + case 'x': + case 'X': state += 40; break; // usigned 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 '+': + 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 '*': ign=1; ++p; break; // ignore arg + case ' ': state=0; ++p; break; + default: + state=20; // other stuff, put an int... + } + break; + case 22: // long int case 25: // size_t int - case 30: + case 42: // long uint + case 45: + case 30: // pointer + if(!ign) { + ++conv; + if(state==22 || state==0x25) { + int32_t* dst = from_ptrv(*st); + *dst = to_long(mystack[nb_elem-conv]); + } else if(state==30) { + ptr_t* dst = from_ptrv(*st); + *dst = to_ptr(mystack[nb_elem-conv]); + } else { + uint32_t* dst = from_ptrv(*st); + *dst = to_ulong(mystack[nb_elem-conv]); + } + ++st; + ++mystack; + } + state = 0; + ++p; + if(!--n) return; + break; + + case 11: //double + case 12: //%lg, still double + case 13: //%llg, still double + case 14: //%Lg long double + case 15: //%zg + case 20: // fallback + case 21: + case 23: // 64bits int + case 24: // normal int / pointer + case 40: + case 41: + case 43: + case 44: if(!ign) { *mystack = *st; ++st; @@ -230,6 +375,7 @@ void myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack) } state = 0; ++p; + if(!--n) return; break; default: // whaaaat? @@ -238,14 +384,15 @@ void myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack) } } -void myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack) +size_t myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem) { if(!fmt) - return; + return 0; // loop... const wchar_t* p = (const wchar_t*)fmt; int state = 0; + size_t conv = 0; int ign = 0; while(*p) { @@ -278,10 +425,10 @@ void myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack) case 'f': state += 10; break; // float case 'd': case 'i': - case 'o': + case 'o': state += 20; break; // int case 'u': case 'x': - case 'X': state += 20; break; // int + case 'X': state += 40; break; // usigned int case 'h': ++p; break; // ignored... case '\'': case '0': @@ -310,6 +457,22 @@ void myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack) state=20; // other stuff, put an int... } break; + case 22: // long uint + case 25: // size_t int + case 42: // long uint + case 45: + case 30: // pointer + if(!ign) { + ++conv; + mystack[nb_elem-conv] = 0; + *mystack = (uintptr_t)&mystack[nb_elem-conv]; + ++st; + ++mystack; + } + state = 0; + ++p; + break; + case 11: //double case 12: //%lg, still double case 13: //%llg, still double @@ -317,11 +480,139 @@ void myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack) case 15: //%zg case 20: // fallback case 21: - case 22: case 23: // 64bits int case 24: // normal int / pointer + case 40: + case 41: + case 43: + case 44: + if(!ign) { + *mystack = *st; + ++st; + ++mystack; + } + state = 0; + ++p; + break; + default: + // whaaaat? + state = 0; + } + } + return conv; +} + +void myStackAlignScanfW32_final(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem, int n) +{ + + if(!fmt || n<=0) + return; + // loop... + const wchar_t* p = (const wchar_t*)fmt; + int state = 0; + size_t conv = 0; + int ign = 0; + while(*p) + { + switch(state) { + case 0: + ign = 0; + switch(*p) { + case '%': state = 1; ++p; break; + default: + ++p; + } + break; + case 1: // normal + case 2: // l + case 3: // ll + case 4: // L + case 5: // z + 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 'z': state = 5; ++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': state += 20; break; // int + case 'u': + case 'x': + case 'X': state += 40; break; // usigned 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 '+': + 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 '*': ign=1; ++p; break; // ignore arg + case ' ': state=0; ++p; break; + default: + state=20; // other stuff, put an int... + } + break; + case 22: // long uint case 25: // size_t int - case 30: + case 42: // long uint + case 45: + case 30: // pointer + if(!ign) { + ++conv; + if(state==22 || state==0x25) { + int32_t* dst = from_ptrv(*st); + *dst = to_long(mystack[nb_elem-conv]); + } else if(state==30) { + ptr_t* dst = from_ptrv(*st); + *dst = to_ptr(mystack[nb_elem-conv]); + } else { + uint32_t* dst = from_ptrv(*st); + *dst = to_ulong(mystack[nb_elem-conv]); + } + ++st; + ++mystack; + } + state = 0; + ++p; + if(!--n) return; + break; + + case 11: //double + case 12: //%lg, still double + case 13: //%llg, still double + case 14: //%Lg long double + case 15: //%zg + case 20: // fallback + case 21: + case 23: // 64bits int + case 24: // normal int / pointer + case 40: + case 41: + case 43: + case 44: if(!ign) { *mystack = *st; ++st; @@ -329,6 +620,7 @@ void myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack) } state = 0; ++p; + if(!--n) return; break; default: // whaaaat? diff --git a/src/wrapped32/wrappedlibc.c b/src/wrapped32/wrappedlibc.c index 7552d31ce..9d7c31c08 100755 --- a/src/wrapped32/wrappedlibc.c +++ b/src/wrapped32/wrappedlibc.c @@ -856,9 +856,11 @@ EXPORT int my32___vsprintf_chk(x64emu_t* emu, void* buff, int flags, size_t len, EXPORT int my32_vfscanf(x64emu_t* emu, void* stream, void* fmt, void* b) // probably uneeded to do a GOM, a simple wrap should enough { - myStackAlignScanf32((const char*)fmt, (uint32_t*)b, emu->scratch); + int n = myStackAlignScanf32((const char*)fmt, (uint32_t*)b, emu->scratch, N_SCRATCH); PREPARE_VALIST_32; - return vfscanf(stream, fmt, VARARGS_32); + int ret = vfscanf(stream, fmt, VARARGS_32); + if(n) myStackAlignScanf32_final((const char*)fmt, (uint32_t*)b, emu->scratch, N_SCRATCH, ret); + return ret; } EXPORT int my32__IO_vfscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my32_vfscanf"))); EXPORT int my32___isoc99_vfscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my32_vfscanf"))); @@ -867,9 +869,11 @@ EXPORT int my32_fscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attrib EXPORT int my32_vsscanf(x64emu_t* emu, void* buff, void* fmt, void* b) { - myStackAlignScanf32((const char*)fmt, (uint32_t*)b, emu->scratch); + int n = myStackAlignScanf32((const char*)fmt, (uint32_t*)b, emu->scratch, N_SCRATCH); PREPARE_VALIST_32; - return vsscanf(buff, fmt, VARARGS_32); + int ret = vsscanf(buff, fmt, VARARGS_32); + if(ret>0) myStackAlignScanf32_final((const char*)fmt, (uint32_t*)b, emu->scratch, N_SCRATCH, ret); + return ret; } EXPORT int my32___isoc99_vsscanf(x64emu_t* emu, void* stream, void* fmt, void* b) __attribute__((alias("my32_vsscanf"))); EXPORT int my32__vsscanf(x64emu_t* emu, void* buff, void* fmt, void* b) __attribute__((alias("my32_vsscanf"))); @@ -933,9 +937,11 @@ EXPORT int my32___vswprintf_chk(x64emu_t* emu, void* buff, size_t s, int flags, EXPORT int my32_vswscanf(x64emu_t* emu, void* buff, void* fmt, void* b) { - myStackAlignScanfW32((const char*)fmt, (uint32_t*)b, emu->scratch); + int n = myStackAlignScanfW32((const char*)fmt, (uint32_t*)b, emu->scratch, N_SCRATCH); PREPARE_VALIST_32; - vswscanf(buff, fmt, VARARGS_32); + int ret = vswscanf(buff, fmt, VARARGS_32); + if(n) myStackAlignScanfW32_final((const char*)fmt, (uint32_t*)b, emu->scratch, N_SCRATCH, ret); + return ret; } EXPORT int my32__vswscanf(x64emu_t* emu, void* buff, void* fmt, void* b) __attribute__((alias("my32_vswscanf")));