#include #include #include #include #include #include #include #include #include #include "x64emu.h" #include "emu/x64emu_private.h" #include "myalign32.h" #include "debug.h" #include "box32.h" void myStackAlign32(const char* fmt, uint32_t* st, uint64_t* mystack) { if(!fmt) return; // loop... const char* p = fmt; int state = 0; double d; long double ld; 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 'z': state = 2; ++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 'n': case 'o': state += 20; break; // int case 'x': case 'X': case 'u': state += 40; break; // uint 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 '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 case 43: // 64bits uint *(uint64_t*)mystack = *(uint64_t*)st; st+=2; mystack+=1; state = 0; ++p; break; case 22: // long int *(int64_t*)mystack = from_long(*(long_t*)st); st+=1; mystack+=1; state = 0; ++p; break; case 42: // long uint *(uint64_t*)mystack = from_ulong(*(ulong_t*)st); st+=1; mystack+=1; state = 0; ++p; break; case 14: //%LG long double #ifdef HAVE_LD80BITS memcpy(mystack, st, 10); st+=3; mystack+=2; #else LD2D((void*)st, &d); ld = d; if(((uintptr_t)mystack)&0xf) // align the long double mystack++; memcpy(mystack, &ld, 16); st+=3; mystack+=2; #endif state = 0; ++p; break; case 30: //pointer *(uintptr_t*)mystack = from_ptr(*st); st++; mystack+=1; state = 0; ++p; break; case 20: // fallback case 21: case 24: // normal int / pointer case 40: case 41: *mystack = *st; ++mystack; ++st; state = 0; ++p; break; default: // whattt? state = 0; } } } size_t myStackAlignScanf32(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem) { if(!fmt) return 0; // loop... const char* p = fmt; size_t conv = 0; int state = 0; int ign = 0; uint64_t* saved = mystack; 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 'n': 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 '[': state += 60; ++p; break; case 'm': state = 0; ++p; break; // no argument case 'p': state = 30; break; // pointers case 'S': case 's': state = 50; break; // string 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 42: // long uint case 45: case 30: // pointer if(!ign) { ++conv; saved[nb_elem-conv] = 0; *mystack = (uintptr_t)&saved[nb_elem-conv]; ++st; ++mystack; } state = 0; ++p; 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: case 50: if(!ign) { *mystack = *st; ++st; ++mystack; } state = 0; ++p; break; case 61: switch(*p) { case ']': state = 50; break; case '\\': ++p; if(*p) ++p; break; default: ++p; break; } 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; uint64_t* saved = mystack; 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 'n': 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 '[': state += 60; ++p; break; case 'm': state = 0; ++p; break; // no argument case 'p': state = 30; break; // pointers case 'S': case 's': state = 50; break; // strings 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 42: // long uint case 45: case 30: // pointer if(!ign) { ++conv; if((state==22) || (state==25)) { long_t* dst = from_ptrv(*st); *dst = saved[nb_elem-conv]; // not using to_long on purpose } else if(state==30) { ptr_t* dst = from_ptrv(*st); *dst = to_ptr(saved[nb_elem-conv]); } else { ulong_t* dst = from_ptrv(*st); *dst = saved[nb_elem-conv]; //not using to to_ulong on pupose } ++st; ++mystack; if(!--n) return; } state = 0; ++p; 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: case 50: if(!ign) { *mystack = *st; ++st; ++mystack; } state = 0; ++p; if(!--n) return; break; case 61: switch(*p) { case ']': state = 50; break; case '\\': ++p; if(*p) ++p; break; default: ++p; break; } break; default: // whaaaat? state = 0; } } } size_t myStackAlignScanfW32(const char* fmt, uint32_t* st, uint64_t* mystack, size_t nb_elem) { if(!fmt) return 0; // loop... const wchar_t* p = (const wchar_t*)fmt; int state = 0; size_t conv = 0; int ign = 0; uint64_t* saved = mystack; 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 'n': 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 'p': state = 30; break; // pointers case 'S': case 's': state = 50; break; // strings 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 42: // long uint case 45: case 30: // pointer if(!ign) { ++conv; saved[nb_elem-conv] = 0; *mystack = (uintptr_t)&saved[nb_elem-conv]; ++st; ++mystack; } state = 0; ++p; 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: case 50: 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; uint64_t* saved = mystack; 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 'n': 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 'p': state = 30; break; // pointers case 'S': case 's': state = 50; break; // string 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 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(saved[nb_elem-conv]); } else if(state==30) { ptr_t* dst = from_ptrv(*st); *dst = to_ptr(saved[nb_elem-conv]); } else { uint32_t* dst = from_ptrv(*st); *dst = to_ulong(saved[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: case 50: if(!ign) { *mystack = *st; ++st; ++mystack; } state = 0; ++p; if(!--n) return; break; default: // whaaaat? state = 0; } } } void myStackAlignGVariantNew32(const char* fmt, uint32_t* st, uint64_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 *(uint64_t*)mystack = *(uint64_t*)st; st+=2; mystack+=1; 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 myStackAlignW32(const char* fmt, uint32_t* st, uint64_t* mystack) { // loop... const wchar_t* p = (const wchar_t*)fmt; int state = 0; double d; long double ld; 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 'z': state = 2; ++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': state += 20; break; // int case 'x': case 'X': case 'u': state += 40; break; // uint 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 case 43: // 64bits uint *(uint64_t*)mystack = *(uint64_t*)st; st+=2; mystack+=1; state = 0; ++p; break; case 22: // long int *(int64_t*)mystack = from_long(*(long_t*)st); st+=1; mystack+=1; state = 0; ++p; break; case 42: // long uint *(uint64_t*)mystack = from_ulong(*(ulong_t*)st); st+=1; mystack+=1; state = 0; ++p; break; case 14: //%LG long double #ifdef HAVE_LD80BITS memcpy(mystack, st, 10); st+=3; mystack+=2; #else LD2D((void*)st, &d); if(((uintptr_t)mystack)&0xf) // align the long double mystack++; ld = d; memcpy(mystack, &ld, 16); st+=3; mystack+=2; #endif state = 0; ++p; break; case 30: //pointer *(uintptr_t*)mystack = from_ptr(*st); st++; mystack+=1; state = 0; ++p; break; case 20: // fallback case 21: case 24: // normal int / pointer case 40: case 41: *mystack = *st; ++mystack; ++st; state = 0; ++p; break; default: // whattt? state = 0; } } } #if 0 typedef struct __attribute__((packed, aligned(4))) { unsigned char *body_data; long body_storage; long body_fill; long body_returned; int *lacing_vals; int64_t *granule_vals; long lacing_storage; long lacing_fill; long lacing_packet; long lacing_returned; unsigned char header[282]; int header_fill __attribute__ ((aligned (4))); int e_o_s; int b_o_s; long serialno; long pageno; int64_t packetno; int64_t granulepos; } ogg_stream_state_x64; typedef struct __attribute__((packed, aligned(4))) vorbis_dsp_state_x64 { int analysisp; void *vi; //vorbis_info float **pcm; float **pcmret; int pcm_storage; int pcm_current; int pcm_returned; int preextrapolate; int eofflag; long lW; long W; long nW; long centerW; int64_t granulepos; int64_t sequence; int64_t glue_bits; int64_t time_bits; int64_t floor_bits; int64_t res_bits; void *backend_state; } vorbis_dsp_state_x64; typedef struct __attribute__((packed, aligned(4))) { long endbyte; int endbit; unsigned char *buffer; unsigned char *ptr; long storage; } oggpack_buffer_x64; typedef struct __attribute__((packed, aligned(4))) vorbis_block_x64 { float **pcm; oggpack_buffer_x64 opb; long lW; long W; long nW; int pcmend; int mode; int eofflag; int64_t granulepos; int64_t sequence; void *vd; void *localstore; long localtop; long localalloc; long totaluse; void *reap; long glue_bits; long time_bits; long floor_bits; long res_bits; void *internal; } vorbis_block_x64; typedef struct __attribute__((packed, aligned(4))) OggVorbis_x64 { void *datasource; /* Pointer to a FILE *, etc. */ int seekable; int64_t offset; int64_t end; ogg_sync_state oy; /* If the FILE handle isn't seekable (eg, a pipe), only the current stream appears */ int links; int64_t *offsets; int64_t *dataoffsets; long *serialnos; int64_t *pcmlengths; /* overloaded to maintain binary compatibility; x2 size, stores both beginning and end values */ void *vi; //vorbis_info void *vc; //vorbis_comment /* Decoding working state local storage */ int64_t pcm_offset; int ready_state; long current_serialno; int current_link; double bittrack; double samptrack; ogg_stream_state_x64 os; /* take physical pages, weld into a logical stream of packets */ vorbis_dsp_state_x64 vd; /* central working state for the packet->PCM decoder */ vorbis_block_x64 vb; /* local working space for packet->PCM decode */ ov_callbacks callbacks; } OggVorbis_x64; #define TRANSFERT \ GO(datasource) \ GO(seekable) \ GO(offset) \ GO(end) \ GOM(oy, sizeof(ogg_sync_state)) \ GO(links) \ GO(offsets) \ GO(dataoffsets) \ GO(serialnos) \ GO(pcmlengths) \ GO(vi) \ GO(vc) \ GO(pcm_offset) \ GO(ready_state) \ GO(current_serialno) \ GO(current_link) \ GOM(bittrack, 16) \ GO(os.body_data) \ GO(os.body_storage) \ GO(os.body_fill) \ GO(os.body_returned) \ GO(os.lacing_vals) \ GO(os.granule_vals) \ GO(os.lacing_storage) \ GO(os.lacing_fill) \ GO(os.lacing_packet) \ GO(os.lacing_returned) \ GOM(os.header, 282) \ GO(os.header_fill) \ GO(os.e_o_s) \ GO(os.b_o_s) \ GO(os.serialno) \ GO(os.pageno) \ GO(os.packetno) \ GO(os.granulepos) \ GO(vd.analysisp) \ GO(vd.vi) \ GO(vd.pcm) \ GO(vd.pcmret) \ GO(vd.pcm_storage) \ GO(vd.pcm_current) \ GO(vd.pcm_returned) \ GO(vd.preextrapolate) \ GO(vd.eofflag) \ GO(vd.lW) \ GO(vd.W) \ GO(vd.nW) \ GO(vd.centerW) \ GO(vd.granulepos) \ GO(vd.sequence) \ GO(vd.glue_bits) \ GO(vd.time_bits) \ GO(vd.floor_bits) \ GO(vd.res_bits) \ GO(vd.backend_state) \ GO(vb.pcm) \ GO(vb.opb.endbyte) \ GO(vb.opb.endbit) \ GO(vb.opb.buffer) \ GO(vb.opb.ptr) \ GO(vb.opb.storage) \ GO(vb.lW) \ GO(vb.W) \ GO(vb.nW) \ GO(vb.pcmend) \ GO(vb.mode) \ GO(vb.eofflag) \ GO(vb.granulepos) \ GO(vb.sequence) \ GO(vb.localstore) \ GO(vb.localtop) \ GO(vb.localalloc) \ GO(vb.totaluse) \ GO(vb.reap) \ GO(vb.glue_bits) \ GO(vb.time_bits) \ GO(vb.floor_bits) \ GO(vb.res_bits) \ GO(vb.internal) \ GOM(callbacks, sizeof(ov_callbacks)) void AlignOggVorbis(void* dest, void* source) { // Arm -> x64 OggVorbis_x64* src = (OggVorbis_x64*)source; OggVorbis* dst = (OggVorbis*)dest; #define GO(A) dst->A = src->A; #define GOM(A, S) memcpy(&dst->A, &src->A, S); TRANSFERT #undef GO #undef GOM dst->vb.vd = (src->vb.vd == &src->vd)?&dst->vd:(vorbis_dsp_state*)src->vb.vd; } void UnalignOggVorbis(void* dest, void* source) { // x64 -> Arm OggVorbis_x64* dst = (OggVorbis_x64*)dest; OggVorbis* src = (OggVorbis*)source; #define GO(A) dst->A = src->A; #define GOM(A, S) memcpy(&dst->A, &src->A, S); TRANSFERT #undef GO #undef GOM dst->vb.vd = (src->vb.vd == &src->vd)?&dst->vd:(vorbis_dsp_state_x64*)src->vb.vd; } #undef TRANSFERT #define TRANSFERT \ GO(analysisp) \ GO(vi) \ GO(pcm) \ GO(pcmret) \ GO(pcm_storage) \ GO(pcm_current) \ GO(pcm_returned) \ GO(preextrapolate) \ GO(eofflag) \ GO(lW) \ GO(W) \ GO(nW) \ GO(centerW) \ GO(granulepos) \ GO(sequence) \ GO(glue_bits) \ GO(time_bits) \ GO(floor_bits) \ GO(res_bits) \ GO(backend_state) void UnalignVorbisDspState(void* dest, void* source) { // Arm -> x64 #define GO(A) ((vorbis_dsp_state_x64*)dest)->A = ((vorbis_dsp_state*)source)->A; #define GOM(A, S) memcpy(&((vorbis_dsp_state_x64*)dest)->A, &((vorbis_dsp_state*)source)->A, S); TRANSFERT #undef GO #undef GOM } void AlignVorbisDspState(void* dest, void* source) { // x64 -> Arm #define GO(A) ((vorbis_dsp_state*)dest)->A = ((vorbis_dsp_state_x64*)source)->A; #define GOM(A, S) memcpy(&((vorbis_dsp_state*)dest)->A, &((vorbis_dsp_state_x64*)source)->A, S); TRANSFERT #undef GO #undef GOM } #undef TRANSFERT #define TRANSFERT \ GO(pcm) \ GO(opb.endbyte) \ GO(opb.endbit) \ GO(opb.buffer) \ GO(opb.ptr) \ GO(opb.storage) \ GO(lW) \ GO(W) \ GO(nW) \ GO(pcmend) \ GO(mode) \ GO(eofflag) \ GO(granulepos) \ GO(sequence) \ GO(vd) \ GO(localstore) \ GO(localtop) \ GO(localalloc) \ GO(totaluse) \ GO(reap) \ GO(glue_bits) \ GO(time_bits) \ GO(floor_bits) \ GO(res_bits) \ GO(internal) void UnalignVorbisBlock(void* dest, void* source) { // Arm -> x64 #define GO(A) ((vorbis_block_x64*)dest)->A = ((vorbis_block*)source)->A; #define GOM(A, S) memcpy(&((vorbis_block_x64*)dest)->A, &((vorbis_block*)source)->A, S); TRANSFERT #undef GO #undef GOM } void AlignVorbisBlock(void* dest, void* source) { // x64 -> Arm #define GO(A) ((vorbis_block*)dest)->A = ((vorbis_block_x64*)source)->A; #define GOM(A, S) memcpy(&((vorbis_block*)dest)->A, &((vorbis_block_x64*)source)->A, S); TRANSFERT #undef GO #undef GOM } #undef TRANSFERT #endif typedef union __attribute__((packed, aligned(4))) i386_epoll_data { ptr_t ptr; //void* int fd; uint32_t u32; uint64_t u64; } i386_epoll_data_t; struct __attribute__((packed, aligned(4))) i386_epoll_event { uint32_t events; i386_epoll_data_t data; }; // Arm -> i386 void UnalignEpollEvent32(void* dest, void* source, int nbr) { struct i386_epoll_event *i386_struct = (struct i386_epoll_event*)dest; struct epoll_event *arm_struct = (struct epoll_event*)source; while(nbr) { i386_struct->events = arm_struct->events; i386_struct->data.u64 = arm_struct->data.u64; ++i386_struct; ++arm_struct; --nbr; } } // i386 -> Arm void AlignEpollEvent32(void* dest, void* source, int nbr) { struct i386_epoll_event *i386_struct = (struct i386_epoll_event*)source; struct epoll_event *arm_struct = (struct epoll_event*)dest; while(nbr) { arm_struct->events = i386_struct->events; arm_struct->data.u64 = i386_struct->data.u64; ++i386_struct; ++arm_struct; --nbr; } } #if 0 typedef struct __attribute__((packed, aligned(4))) x64_SMPEG_Info_s { int has_audio; int has_video; int width; int height; int current_frame; double current_fps; char audio_string[80]; int audio_current_frame; uint32_t current_offset; uint32_t total_size; double current_time; double total_time; } x64_SMPEG_Info_t; #define TRANSFERT \ GO(has_audio) \ GO(has_video) \ GO(width) \ GO(height) \ GO(current_frame) \ GO(current_fps) \ GOM(audio_string, 80) \ GO(audio_current_frame) \ GO(current_offset) \ GO(total_size) \ GO(current_time) \ GO(total_time) // Arm -> x64 void UnalignSmpegInfo(void* dest, void* source) { #define GO(A) ((x64_SMPEG_Info_t*)dest)->A = ((my_SMPEG_Info_t*)source)->A; #define GOM(A, S) memcpy(&((x64_SMPEG_Info_t*)dest)->A, &((my_SMPEG_Info_t*)source)->A, S); TRANSFERT #undef GO #undef GOM } // x64 -> Arm void AlignSmpegInfo(void* dest, void* source) { #define GO(A) ((my_SMPEG_Info_t*)dest)->A = ((x64_SMPEG_Info_t*)source)->A; #define GOM(A, S) memcpy(&((my_SMPEG_Info_t*)dest)->A, &((x64_SMPEG_Info_t*)source)->A, S); TRANSFERT #undef GO #undef GOM } #undef TRANSFERT #define TRANSFERT \ GOV(fts_cycle) \ GOV(fts_parent) \ GOV(fts_link) \ GO(fts_number) \ GO(fts_pointer) \ GO(fts_accpath) \ GO(fts_path) \ GO(fts_errno) \ GO(fts_symfd) \ GO(fts_pathlen) \ GO(fts_namelen) \ GO(fts_ino) \ GO(fts_dev) \ GO(fts_nlink) \ GO(fts_level) \ GO(fts_info) \ GO(fts_flags) \ GO(fts_instr) \ GO(fts_statp) \ GOM(fts_name, sizeof(void*)) // Arm -> x64 void UnalignFTSENT(void* dest, void* source) { #define GO(A) ((x64_ftsent_t*)dest)->A = ((FTSENT*)source)->A; #define GOV(A) ((x64_ftsent_t*)dest)->A = (void*)((FTSENT*)source)->A; #define GOM(A, S) memcpy(&((x64_ftsent_t*)dest)->A, &((FTSENT*)source)->A, S); TRANSFERT #undef GO #undef GOV #undef GOM } // x64 -> Arm void AlignFTSENT(void* dest, void* source) { #define GO(A) ((FTSENT*)dest)->A = ((x64_ftsent_t*)source)->A; #define GOV(A) ((FTSENT*)dest)->A = (void*)((x64_ftsent_t*)source)->A; #define GOM(A, S) memcpy(&((FTSENT*)dest)->A, &((x64_ftsent_t*)source)->A, S); TRANSFERT #undef GO #undef GOV #undef GOM } #undef TRANSFERT void alignNGValue(my_GValue_t* v, void* value, int n) { while(n) { v->g_type = *(int*)value; memcpy(v->data, value+4, 2*sizeof(double)); ++v; value+=4+2*sizeof(double); --n; } } void unalignNGValue(void* value, my_GValue_t* v, int n) { while(n) { *(int*)value = v->g_type; memcpy(value+4, v->data, 2*sizeof(double)); ++v; value+=4+2*sizeof(double); --n; } } #endif // x86 -> Native void AlignIOV_32(void* dest, void* source) { struct iovec* d = dest; struct i386_iovec* s = source; d->iov_base = from_ptrv(s->iov_base); d->iov_len = s->iov_len; } // Native -> x86 void UnalignIOV_32(void* dest, void* source) { struct iovec* s = source; struct i386_iovec* d = dest; d->iov_base = to_ptrv(s->iov_base); d->iov_len = s->iov_len; } void* my32___cmsg_nxthdr(struct i386_msghdr* mhdr, struct i386_cmsghdr* cmsg); // x86 -> Native void AlignMsgHdr_32(void* dest, void* dest_iov, void* dest_cmsg, void* source, int convert_control) { struct iovec* iov = dest_iov; struct msghdr* d = dest; struct i386_msghdr* s = source; struct i386_iovec* s_iov = from_ptrv(s->msg_iov); d->msg_name = from_ptrv(s->msg_name); d->msg_namelen = s->msg_namelen; d->msg_iov = iov; // TODO: check if iovlen is too big for(int i=0; imsg_iovlen; ++i) { AlignIOV_32(d->msg_iov+i, s_iov+i); } d->msg_iovlen = s->msg_iovlen; d->msg_controllen = s->msg_controllen; if(convert_control) { if(s->msg_control) { d->msg_control = dest_cmsg; struct i386_cmsghdr* cmsg = (s->msg_controllen)?from_ptrv(s->msg_control):NULL; struct cmsghdr* dcmsg = dest_cmsg; while(cmsg) { dcmsg->cmsg_len = from_ulong(cmsg->cmsg_len); dcmsg->cmsg_level = cmsg->cmsg_level; dcmsg->cmsg_type = cmsg->cmsg_type; if(cmsg->cmsg_len) { dcmsg->cmsg_len += 4; memcpy(CMSG_DATA(dcmsg), cmsg+1, cmsg->cmsg_len-sizeof(struct i386_cmsghdr)); d->msg_controllen += 4; } struct cmsghdr* next = (struct cmsghdr*)(((uintptr_t)dcmsg) + ((dcmsg->cmsg_len+7)&~7)); cmsg = my32___cmsg_nxthdr(s, cmsg); uintptr_t next_diff = (uintptr_t)next-((uintptr_t)dcmsg+dcmsg->cmsg_len); if(cmsg) d->msg_controllen+=next_diff; dcmsg = next; } } else d->msg_control = NULL; } else { if(d->msg_controllen) d->msg_controllen+=4; d->msg_control = (s->msg_control)?dest_cmsg:NULL; if(d->msg_control) memset(d->msg_control, 0, d->msg_controllen); } d->msg_flags = s->msg_flags; } void UnalignMsgHdr_32(void* dest, void* source) { struct msghdr* s = source; struct i386_msghdr* d = dest; struct iovec* s_iov = s->msg_iov; struct i386_iovec* d_iov = from_ptrv(d->msg_iov); d->msg_name = to_ptrv(s->msg_name); d->msg_namelen = s->msg_namelen; // TODO: check if iovlen is too big for(int i=0; imsg_iovlen; ++i) { UnalignIOV_32(d_iov+i, s_iov+i); } d->msg_iovlen = s->msg_iovlen; d->msg_controllen = s->msg_controllen; if(s->msg_control) { struct i386_cmsghdr* dcmsg = from_ptrv(d->msg_control); struct cmsghdr* scmsg = (s->msg_controllen)?s->msg_control:NULL; while(scmsg) { dcmsg->cmsg_len = to_ulong(scmsg->cmsg_len); dcmsg->cmsg_level = scmsg->cmsg_level; dcmsg->cmsg_type = scmsg->cmsg_type; if(dcmsg->cmsg_len) { dcmsg->cmsg_len -= 4; memcpy(dcmsg+1, CMSG_DATA(scmsg), dcmsg->cmsg_len-sizeof(struct i386_cmsghdr)); d->msg_controllen -= 4; } dcmsg = (struct i386_cmsghdr*)(((uintptr_t)dcmsg) + ((dcmsg->cmsg_len+3)&~3)); scmsg = CMSG_NXTHDR(s, scmsg); } } else d->msg_control = 0; d->msg_flags = s->msg_flags; } #define TRANSFERT \ GO(l_type) \ GO(l_whence) \ GO(l_start) \ GO(l_len) \ GO(l_pid) // Arm -> x86 void UnalignFlock_32(void* dest, void* source) { #define GO(A) ((i386_flock_t*)dest)->A = ((my_flock64_t*)source)->A; TRANSFERT #undef GO } // x86 -> Arm void AlignFlock_32(void* dest, void* source) { #define GO(A) ((my_flock64_t*)dest)->A = ((i386_flock_t*)source)->A; TRANSFERT #undef GO } #undef TRANSFERT void convert_regext_to_32(void* d, void* s) { my_regex_32_t* dst = d; my_regex_t* src = s; dst->buffer = to_ptrv(src->buffer); dst->allocated = to_ulong(src->allocated); dst->used = to_ulong(src->used); dst->syntax = to_ulong(src->syntax); dst->fastmap = to_ptrv(src->fastmap); dst->translate = to_ptrv(src->translate); dst->re_nsub = to_ulong(src->re_nsub); dst->flags = src->flags; } void convert_regext_to_64(void* d, void* s) { my_regex_t* dst = d; my_regex_32_t* src = s; dst->buffer = from_ptrv(src->buffer); dst->allocated = from_ulong(src->allocated); dst->used = from_ulong(src->used); dst->syntax = from_ulong(src->syntax); dst->fastmap = from_ptrv(src->fastmap); dst->translate = from_ptrv(src->translate); dst->re_nsub = from_ulong(src->re_nsub); dst->flags = src->flags; } void* inplace_obstack_chunk_shrink(void* a) { if(a) { struct my_obstack_chunk_32_t* dst = a; struct _obstack_chunk* src = a; dst->limit = to_ptrv(src->limit); dst->prev = to_ptrv(src->prev); memcpy(dst->contents, src->contents, sizeof(dst->contents)); } return a; } void* inplace_obstack_chunk_enlarge(void* a) { if(a) { struct my_obstack_chunk_32_t* src = a; struct _obstack_chunk* dst = a; memcpy(dst->contents, src->contents, sizeof(dst->contents)); dst->prev = from_ptrv(src->prev); dst->limit = from_ptrv(src->limit); } return a; } void convert_obstack_to_32(void* d, void* s) { if(!d || !s) return; struct my_obstack_32_t* dst = d; struct obstack *src = s; // chunks struct _obstack_chunk* chunk = src->chunk; while(chunk) { struct _obstack_chunk* prev = chunk->prev; inplace_obstack_chunk_shrink(chunk); chunk = prev; } // struture dst->chunk_size = to_long(src->chunk_size); dst->chunk = to_ptrv(src->chunk); dst->object_base = to_ptrv(src->object_base); dst->next_free = to_ptrv(src->next_free); dst->chunk_limit = to_ptrv(src->chunk_limit); dst->temp.tempptr = to_ptrv(src->temp.tempptr); dst->chunkfun = to_ptrv(src->chunkfun); dst->freefun = to_ptrv(src->freefun); dst->extra_arg = to_ptrv(src->extra_arg); dst->use_extra_arg = src->use_extra_arg; dst->maybe_empty_object = src->maybe_empty_object; dst->alloc_failed = src->alloc_failed; } void convert_obstack_to_64(void* d, void* s) { if(!d || !s) return; struct my_obstack_32_t* src = s; struct obstack *dst = d; // struture dst->alloc_failed = src->alloc_failed; dst->maybe_empty_object = src->maybe_empty_object; dst->use_extra_arg = src->use_extra_arg; dst->extra_arg = from_ptrv(src->extra_arg); dst->freefun = from_ptrv(src->freefun); dst->chunkfun = from_ptrv(src->chunkfun); dst->temp.tempptr = from_ptrv(src->temp.tempptr); dst->chunk_limit = from_ptrv(src->chunk_limit); dst->next_free = from_ptrv(src->next_free); dst->object_base = from_ptrv(src->object_base); dst->chunk = from_ptrv(src->chunk); dst->chunk_size = from_long(src->chunk_size); // chunks struct _obstack_chunk* chunk = dst->chunk; while(chunk) { struct _obstack_chunk* prev = chunk->prev; inplace_obstack_chunk_enlarge(chunk); chunk = prev; } }