#ifndef __MY_ALIGN__H_ #define __MY_ALIGN__H_ #include typedef struct x64_va_list_s { unsigned int gp_offset; unsigned int fp_offset; void *overflow_arg_area; void *reg_save_area; } x64_va_list_t[1]; #define X64_VA_MAX_REG (6*8) #define X64_VA_MAX_XMM ((6*8)+(8*16)) #ifdef __x86_64__ // x86_64, 6 64bits general regs and 16 or 8? 128bits float regs /* For reference, here is the x86_64 va_list structure typedef struct { unsigned int gp_offset; unsigned int fp_offset; void *overflow_arg_area; void *reg_save_area; } va_list[1]; */ #define CREATE_SYSV_VALIST(A) \ va_list sysv_varargs; \ sysv_varargs->gp_offset=X64_VA_MAX_REG; \ sysv_varargs->fp_offset=X64_VA_MAX_XMM; \ sysv_varargs->reg_save_area=(A); \ sysv_varargs->overflow_arg_area=A #define CONVERT_VALIST(A) \ va_list sysv_varargs; \ sysv_varargs->gp_offset=(A)->gp_offset; \ sysv_varargs->fp_offset=(A)->fp_offset; \ sysv_varargs->reg_save_area=(A)->reg_save_area; \ sysv_varargs->overflow_arg_area=(A)->overflow_arg_area; #define CREATE_VALIST_FROM_VAARG(STACK, SCRATCH, N) \ va_list sysv_varargs; \ sysv_varargs->gp_offset=(6-(((N)<6)?(N):6))*8; \ sysv_varargs->fp_offset=(6*8); \ sysv_varargs->reg_save_area=(SCRATCH); \ sysv_varargs->overflow_arg_area=(STACK); \ { \ uint64_t *p = (uint64_t*)(SCRATCH); \ p[0]=R_RDI; p[1]=R_RSI; p[2]=R_RDX; \ p[3]=R_RCX; p[4]=R_R8; p[5]=R_R9; \ memcpy(&p[6], emu->xmm, 8*16); \ } #define PREFER_CONVERT_VAARG #elif defined(__aarch64__) // aarch64: 8 64bits general regs and 8 128bits float regs /* va_list declared as typedef struct va_list { void * stack; // next stack param void * gr_top; // end of GP arg reg save area void * vr_top; // end of FP/SIMD arg reg save area int gr_offs; // offset from gr_top to next GP register arg int vr_offs; // offset from vr_top to next FP/SIMD register arg } va_list; */ #define CREATE_SYSV_VALIST(A) \ va_list sysv_varargs; \ sysv_varargs.__gr_offs=(8*8); \ sysv_varargs.__vr_offs=(8*16); \ sysv_varargs.__stack=(A) #define CONVERT_VALIST(A) \ va_list sysv_varargs; \ sysv_varargs.__gr_offs=-(6*8)+(A)->gp_offset; \ sysv_varargs.__vr_offs=-(8*16)+((A)->fp_offset-X64_VA_MAX_REG); \ sysv_varargs.__stack=(A)->overflow_arg_area; \ sysv_varargs.__gr_top=(A)->reg_save_area + X64_VA_MAX_REG; \ sysv_varargs.__vr_top=(A)->reg_save_area + X64_VA_MAX_XMM; #define CREATE_VALIST_FROM_VAARG(STACK, SCRATCH, N) \ va_list sysv_varargs; \ sysv_varargs.__gr_offs=-(6*8)+(8*(((N)<6)?(N):6)); \ sysv_varargs.__vr_offs=-(8*16); \ sysv_varargs.__stack=(STACK); \ sysv_varargs.__gr_top=(void*)((uintptr_t)(SCRATCH) + X64_VA_MAX_REG); \ sysv_varargs.__vr_top=(void*)((uintptr_t)(SCRATCH) + X64_VA_MAX_XMM); \ { \ uintptr_t *p = (uintptr_t*)(SCRATCH); \ p[0]=R_RDI; p[1]=R_RSI; p[2]=R_RDX; \ p[3]=R_RCX; p[4]=R_R8; p[5]=R_R9; \ memcpy(&p[6], emu->xmm, 8*16); \ } #define PREFER_CONVERT_VAARG #elif defined(__sw_64__) /* or Alpha */ /* typdef struct { char* __base; int __offset; }va_list; */ // the follow three macro is not fully compatiable with SW64/Alpha // so don't expect va function works well. #define CREATE_SYSV_VALIST(A) \ va_list sysv_varargs; \ sysv_varargs.__offset=0; \ sysv_varargs.__base=(A) #define CREATE_VALIST_FROM_VALIST(VA, SCRATCH) \ va_list sysv_varargs; \ { \ uintptr_t *p = (uintptr_t*)(SCRATCH); \ int n = (X64_VA_MAX_REG - (VA)->gp_offset)/8; \ if(n) memcpy(&p[0], (VA)->reg_save_area+X64_VA_MAX_REG-n*8, n*8); \ memcpy(&p[n], (VA)->overflow_arg_area, 20*8); \ sysv_varargs.__offset = (VA)->gp_offset; \ sysv_varargs.__base = (char*)p; \ } #define CREATE_VALIST_FROM_VAARG(STACK, SCRATCH, N) \ va_list sysv_varargs; \ { \ uintptr_t *p = (uintptr_t*)(SCRATCH); \ p[0]=R_RDI; p[1]=R_RSI; p[2]=R_RDX; \ p[3]=R_RCX; p[4]=R_R8; p[5]=R_R9; \ memcpy(&p[8+N], STACK, 20*8); \ sysv_varargs.__offset = N*8; \ sysv_varargs.__base = (char*)p; \ } #elif defined(__loongarch64) || defined(__powerpc64__) || defined(__riscv) #define CREATE_SYSV_VALIST(A) \ va_list sysv_varargs = (va_list)A // not creating CONVERT_VALIST(A) on purpose // this one will create a VA_LIST from x64_va_list using only GPRS and 100 stack element #define CREATE_VALIST_FROM_VALIST(VA, SCRATCH) \ va_list sysv_varargs; \ { \ if((VA)->fp_offset!=X64_VA_MAX_XMM) printf_log(LOG_DEBUG, "Warning: %s: CREATE_VALIST_FROM_VALIST with %d XMM register!\n", __FUNCTION__, (X64_VA_MAX_XMM - (VA)->fp_offset)/16);\ uintptr_t *p = (uintptr_t*)(SCRATCH); \ int n = (X64_VA_MAX_REG - (VA)->gp_offset)/8; \ if(n) memcpy(&p[0], (VA)->reg_save_area+X64_VA_MAX_REG-n*8, n*8); \ memcpy(&p[n], (VA)->overflow_arg_area, 20*8); \ sysv_varargs = (va_list)p; \ } // this is an approximation, and if the va_list have some float/double, it will fail! // if the funciton needs more than 100 args, it will also fail #define CREATE_VALIST_FROM_VAARG(STACK, SCRATCH, N) \ va_list sysv_varargs; \ { \ uintptr_t *p = (uintptr_t*)(SCRATCH); \ p[0]=R_RDI; p[1]=R_RSI; p[2]=R_RDX; \ p[3]=R_RCX; p[4]=R_R8; p[5]=R_R9; \ memcpy(&p[6], STACK, 20*8); \ sysv_varargs = (va_list)&p[N]; \ } #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 myStackAlignScanf(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int pos); void myStackAlignW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int xmm, int pos); void myStackAlignScanfW(x64emu_t* emu, const char* fmt, uint64_t* st, uint64_t* mystack, int pos); #ifndef CONVERT_VALIST void myStackAlignValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va); void myStackAlignWValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va); void myStackAlignScanfValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va); void myStackAlignScanfWValist(x64emu_t* emu, const char* fmt, uint64_t* mystack, x64_va_list_t va); #endif struct x64_stat64 { /* x86_64 arm64 */ uint64_t st_dev; /* 0 */ /* 0 */ uint64_t st_ino; /* 8 */ /* 8 */ uint64_t st_nlink; /* 16 */ /* 20 */ uint32_t st_mode; /* 24 */ /* 16 */ uint32_t st_uid; /* 28 */ /* 24 */ uint32_t st_gid; /* 32 */ /* 28 */ int __pad0; /* 36 */ /* --- */ uint64_t st_rdev; /* 40 */ /* 32 */ int64_t st_size; /* 48 */ /* 48 */ int64_t st_blksize; /* 56 */ /* 56 */ uint64_t st_blocks; /* 64 */ /* 64 */ struct timespec st_atim; /* 72 */ /* 72 */ struct timespec st_mtim; /* 88 */ /* 88 */ struct timespec st_ctim; /* 104 */ /* 104 */ uint64_t __glibc_reserved[3]; /* 120 */ /* 120 */ } __attribute__((packed)); /* 144 */ /* 128 */ void AlignStat64(const void* source, void* dest); void UnalignStat64(const void* source, void* dest); // defined in wrapperlibc.c int of_convert(int); // x86->arm int of_unconvert(int); // arm->x86 void UnalignEpollEvent(void* dest, void* source, int nbr); // Arm -> x86 void AlignEpollEvent(void* dest, void* source, int nbr); // x86 -> Arm void UnalignSemidDs(void *dest, const void* source); void AlignSemidDs(void *dest, const void* source); void* align_xcb_connection(void* src); void unalign_xcb_connection(void* src, void* dst); void* add_xcb_connection(void* src); void del_xcb_connection(void* src); uintptr_t getVArgs(x64emu_t* emu, int pos, uintptr_t* b, int N); // longjmp / setjmp typedef struct jump_buff_x64_s { uint64_t save_rbx; uint64_t save_rbp; uint64_t save_r12; uint64_t save_r13; uint64_t save_r14; uint64_t save_r15; uint64_t save_rsp; uint64_t save_rip; } jump_buff_x64_t; typedef struct __jmp_buf_tag_s { jump_buff_x64_t __jmpbuf; int __mask_was_saved; #ifdef ANDROID sigset_t __saved_mask; #else __sigset_t __saved_mask; #endif } __jmp_buf_tag_t; #endif //__MY_ALIGN__H_