... matching the other 157 .c files in the tree
Unified · Split
| @@ -1,41 +1,41 @@ | ||
| 1 | −#include <stdio.h> | |
| 2 | −#include <stdlib.h> | |
| 3 | −asm ( | |
| 4 | − ".text;" | |
| 5 | − ".globl _us;.globl _ss;.globl _uc;.globl _sc;" | |
| 6 | − "_us:;_ss:;_uc:;_sc:;" | |
| 7 | − "movl $0x1234ABCD, %eax;" | |
| 8 | − "ret;" | |
| 9 | −); | |
| 10 | − | |
| 11 | −#if 1 | |
| 12 | −#define us _us | |
| 13 | −#define ss _ss | |
| 14 | −#define uc _uc | |
| 15 | −#define sc _sc | |
| 16 | −#endif | |
| 17 | − | |
| 18 | −int main() | |
| 19 | −{ | |
| 20 | − unsigned short us(void); | |
| 21 | − short ss(void); | |
| 22 | − unsigned char uc(void); | |
| 23 | − signed char sc(void); | |
| 24 | − | |
| 25 | − unsigned short (*fpus)(void) = us; | |
| 26 | − short (*fpss)(void) = ss; | |
| 27 | − unsigned char (*fpuc)(void) = uc; | |
| 28 | − signed char (*fpsc)(void) = sc; | |
| 29 | − | |
| 30 | − printf("%08X %08X\n", us() + 1, fpus() + 1); | |
| 31 | − printf("%08X %08X\n", ss() + 1, fpss() + 1); | |
| 32 | − printf("%08X %08X\n", uc() + 1, fpuc() + 1); | |
| 33 | − printf("%08X %08X\n", sc() + 1, fpsc() + 1); | |
| 34 | − printf("\n"); | |
| 35 | − printf("%08X %08X\n", fpus() + 1, us() + 1); | |
| 36 | − printf("%08X %08X\n", fpss() + 1, ss() + 1); | |
| 37 | − printf("%08X %08X\n", fpuc() + 1, uc() + 1); | |
| 38 | − printf("%08X %08X\n", fpsc() + 1, sc() + 1); | |
| 39 | − | |
| 40 | − return 0; | |
| 41 | −} | |
| 1 | +#include <stdio.h> | |
| 2 | +#include <stdlib.h> | |
| 3 | +asm ( | |
| 4 | + ".text;" | |
| 5 | + ".globl _us;.globl _ss;.globl _uc;.globl _sc;" | |
| 6 | + "_us:;_ss:;_uc:;_sc:;" | |
| 7 | + "movl $0x1234ABCD, %eax;" | |
| 8 | + "ret;" | |
| 9 | +); | |
| 10 | + | |
| 11 | +#if 1 | |
| 12 | +#define us _us | |
| 13 | +#define ss _ss | |
| 14 | +#define uc _uc | |
| 15 | +#define sc _sc | |
| 16 | +#endif | |
| 17 | + | |
| 18 | +int main() | |
| 19 | +{ | |
| 20 | + unsigned short us(void); | |
| 21 | + short ss(void); | |
| 22 | + unsigned char uc(void); | |
| 23 | + signed char sc(void); | |
| 24 | + | |
| 25 | + unsigned short (*fpus)(void) = us; | |
| 26 | + short (*fpss)(void) = ss; | |
| 27 | + unsigned char (*fpuc)(void) = uc; | |
| 28 | + signed char (*fpsc)(void) = sc; | |
| 29 | + | |
| 30 | + printf("%08X %08X\n", us() + 1, fpus() + 1); | |
| 31 | + printf("%08X %08X\n", ss() + 1, fpss() + 1); | |
| 32 | + printf("%08X %08X\n", uc() + 1, fpuc() + 1); | |
| 33 | + printf("%08X %08X\n", sc() + 1, fpsc() + 1); | |
| 34 | + printf("\n"); | |
| 35 | + printf("%08X %08X\n", fpus() + 1, us() + 1); | |
| 36 | + printf("%08X %08X\n", fpss() + 1, ss() + 1); | |
| 37 | + printf("%08X %08X\n", fpuc() + 1, uc() + 1); | |
| 38 | + printf("%08X %08X\n", fpsc() + 1, sc() + 1); | |
| 39 | + | |
| 40 | + return 0; | |
| 41 | +} | |
| @@ -1,276 +1,276 @@ | ||
| 1 | −#include <stdio.h> | |
| 2 | −#include <assert.h> | |
| 3 | − | |
| 4 | −#ifndef _WIN32 | |
| 5 | −#define __fastcall __attribute((fastcall)) | |
| 6 | −#endif | |
| 7 | − | |
| 8 | −#if 1 | |
| 9 | −#define SYMBOL(x) _##x | |
| 10 | −#else | |
| 11 | −#define SYMBOL(x) x | |
| 12 | −#endif | |
| 13 | − | |
| 14 | −///////////////////////////////////////////////////////////////////////// | |
| 15 | −////////// TRAP FRAMEWORK | |
| 16 | −///////////////////////////////////////////////////////////////////////// | |
| 17 | −// if you cast 'TRAP' to a function pointer and call it, | |
| 18 | −// it will save all 8 registers, | |
| 19 | −// and jump into C-code (previously set using 'SET_TRAP_HANDLER(x)'), | |
| 20 | −// in C-code you can pop DWORDs from stack and modify registers | |
| 21 | −// | |
| 22 | − | |
| 23 | −void *SYMBOL(trap_handler); | |
| 24 | − | |
| 25 | −extern unsigned char SYMBOL(trap)[]; | |
| 26 | −asm ( | |
| 27 | − ".text;" | |
| 28 | − "_trap:;" | |
| 29 | − "pushl %esp;" | |
| 30 | − "pusha;" | |
| 31 | − "addl $0x4, 0xc(%esp);" | |
| 32 | − "pushl %esp;" | |
| 33 | − "call *_trap_handler;" | |
| 34 | − "addl $0x4, %esp;" | |
| 35 | − "movl 0xc(%esp), %eax;" | |
| 36 | − "movl %eax, 0x20(%esp);" | |
| 37 | − "popa;" | |
| 38 | − "popl %esp;" | |
| 39 | − "ret;" | |
| 40 | −); | |
| 41 | − | |
| 42 | −struct trapframe { | |
| 43 | − unsigned edi, esi, ebp, esp, ebx, edx, ecx, eax; | |
| 44 | −}; | |
| 45 | − | |
| 46 | − | |
| 47 | −#define M_FLOAT(addr) (*(float *)(addr)) | |
| 48 | −#define M_DWORD(addr) (*(unsigned *)(addr)) | |
| 49 | −#define M_WORD(addr) (*(unsigned short *)(addr)) | |
| 50 | −#define M_BYTE(addr) (*(unsigned char *)(addr)) | |
| 51 | −#define R_EAX ((tf)->eax) | |
| 52 | −#define R_ECX ((tf)->ecx) | |
| 53 | −#define R_EDX ((tf)->edx) | |
| 54 | −#define R_EBX ((tf)->ebx) | |
| 55 | −#define R_ESP ((tf)->esp) | |
| 56 | −#define R_EBP ((tf)->ebp) | |
| 57 | −#define R_ESI ((tf)->esi) | |
| 58 | −#define R_EDI ((tf)->edi) | |
| 59 | − | |
| 60 | −#define ARG(x) (M_DWORD(R_ESP + (x) * 4)) | |
| 61 | − | |
| 62 | −#define RETN(x) do { \ | |
| 63 | − M_DWORD(R_ESP + (x)) = M_DWORD(R_ESP); \ | |
| 64 | − R_ESP += (x); \ | |
| 65 | −} while (0) | |
| 66 | − | |
| 67 | −#define DUMP() do { \ | |
| 68 | − unsigned i; \ | |
| 69 | − printf("EAX: %08X\n", R_EAX); \ | |
| 70 | − printf("ECX: %08X\n", R_ECX); \ | |
| 71 | − printf("EDX: %08X\n", R_EDX); \ | |
| 72 | − printf("EBX: %08X\n", R_EBX); \ | |
| 73 | − printf("ESP: %08X\n", R_ESP); \ | |
| 74 | − printf("EBP: %08X\n", R_EBP); \ | |
| 75 | − printf("ESI: %08X\n", R_ESI); \ | |
| 76 | − printf("EDI: %08X\n", R_EDI); \ | |
| 77 | − printf("\n"); \ | |
| 78 | − printf("[RETADDR]: %08X\n", M_DWORD(R_ESP)); \ | |
| 79 | − for (i = 1; i <= 8; i++) { \ | |
| 80 | − printf("[ARG%4d]: %08X\n", i, ARG(i)); \ | |
| 81 | − } \ | |
| 82 | −} while (0) | |
| 83 | − | |
| 84 | −#define SET_TRAP_HANDLER(x) ((SYMBOL(trap_handler)) = (x)) | |
| 85 | −#define TRAP ((void *) &SYMBOL(trap)) | |
| 86 | − | |
| 87 | − | |
| 88 | − | |
| 89 | −///////////////////////////////////////////////////////////////////////// | |
| 90 | −////////// SAFECALL FRAMEWORK | |
| 91 | −///////////////////////////////////////////////////////////////////////// | |
| 92 | −// this framwork will convert any calling convention to cdecl | |
| 93 | −// usage: first set call target with 'SET_SAFECALL_TARGET(x)' | |
| 94 | −// then cast 'SAFECALL' to target funtion pointer type and invoke it | |
| 95 | −// after calling, 'ESPDIFF' is the differance of old and new esp | |
| 96 | − | |
| 97 | −void *SYMBOL(sc_call_target); | |
| 98 | −unsigned SYMBOL(sc_retn_addr); | |
| 99 | −unsigned SYMBOL(sc_old_esp); | |
| 100 | −unsigned SYMBOL(sc_new_esp); | |
| 101 | − | |
| 102 | −extern unsigned char SYMBOL(safecall)[]; | |
| 103 | −asm ( | |
| 104 | − ".text;" | |
| 105 | − "_safecall:;" | |
| 106 | − "popl _sc_retn_addr;" | |
| 107 | − "movl %esp, _sc_old_esp;" | |
| 108 | − "call *_sc_call_target;" | |
| 109 | − "movl %esp, _sc_new_esp;" | |
| 110 | − "movl _sc_old_esp, %esp;" | |
| 111 | − "jmp *_sc_retn_addr;" | |
| 112 | −); | |
| 113 | − | |
| 114 | −#define SET_SAFECALL_TARGET(x) ((SYMBOL(sc_call_target)) = (x)) | |
| 115 | −#define SAFECALL ((void *) &SYMBOL(safecall)) | |
| 116 | −#define ESPDIFF (SYMBOL(sc_new_esp) - SYMBOL(sc_old_esp)) | |
| 117 | − | |
| 118 | − | |
| 119 | −///////////////////////////////////////////////////////////////////////// | |
| 120 | −////////// TEST FASTCALL INVOKE | |
| 121 | −///////////////////////////////////////////////////////////////////////// | |
| 122 | − | |
| 123 | −void check_fastcall_invoke_0(struct trapframe *tf) | |
| 124 | −{ | |
| 125 | − //DUMP(); | |
| 126 | − RETN(0); | |
| 127 | −} | |
| 128 | − | |
| 129 | −void check_fastcall_invoke_1(struct trapframe *tf) | |
| 130 | −{ | |
| 131 | − //DUMP(); | |
| 132 | − assert(R_ECX == 0x11111111); | |
| 133 | − RETN(0); | |
| 134 | −} | |
| 135 | −void check_fastcall_invoke_2(struct trapframe *tf) | |
| 136 | −{ | |
| 137 | − //DUMP(); | |
| 138 | − assert(R_ECX == 0x11111111); | |
| 139 | − assert(R_EDX == 0x22222222); | |
| 140 | − RETN(0); | |
| 141 | −} | |
| 142 | −void check_fastcall_invoke_3(struct trapframe *tf) | |
| 143 | −{ | |
| 144 | − //DUMP(); | |
| 145 | − assert(R_ECX == 0x11111111); | |
| 146 | − assert(R_EDX == 0x22222222); | |
| 147 | − assert(ARG(1) == 0x33333333); | |
| 148 | − RETN(1*4); | |
| 149 | −} | |
| 150 | −void check_fastcall_invoke_4(struct trapframe *tf) | |
| 151 | −{ | |
| 152 | − //DUMP(); | |
| 153 | − assert(R_ECX == 0x11111111); | |
| 154 | − assert(R_EDX == 0x22222222); | |
| 155 | − assert(ARG(1) == 0x33333333); | |
| 156 | − assert(ARG(2) == 0x44444444); | |
| 157 | − RETN(2*4); | |
| 158 | −} | |
| 159 | − | |
| 160 | −void check_fastcall_invoke_5(struct trapframe *tf) | |
| 161 | −{ | |
| 162 | − //DUMP(); | |
| 163 | − assert(R_ECX == 0x11111111); | |
| 164 | − assert(R_EDX == 0x22222222); | |
| 165 | − assert(ARG(1) == 0x33333333); | |
| 166 | − assert(ARG(2) == 0x44444444); | |
| 167 | − assert(ARG(3) == 0x55555555); | |
| 168 | − RETN(3*4); | |
| 169 | −} | |
| 170 | − | |
| 171 | −void test_fastcall_invoke() | |
| 172 | −{ | |
| 173 | − SET_TRAP_HANDLER(check_fastcall_invoke_0); | |
| 174 | − ((void __fastcall (*)(void)) TRAP)(); | |
| 175 | − | |
| 176 | − SET_TRAP_HANDLER(check_fastcall_invoke_1); | |
| 177 | − ((void __fastcall (*)(unsigned)) TRAP)(0x11111111); | |
| 178 | − | |
| 179 | − SET_TRAP_HANDLER(check_fastcall_invoke_2); | |
| 180 | − ((void __fastcall (*)(unsigned, unsigned)) TRAP)(0x11111111, 0x22222222); | |
| 181 | − | |
| 182 | − SET_TRAP_HANDLER(check_fastcall_invoke_3); | |
| 183 | − ((void __fastcall (*)(unsigned, unsigned, unsigned)) TRAP)(0x11111111, 0x22222222, 0x33333333); | |
| 184 | − | |
| 185 | − SET_TRAP_HANDLER(check_fastcall_invoke_4); | |
| 186 | − ((void __fastcall (*)(unsigned, unsigned, unsigned, unsigned)) TRAP)(0x11111111, 0x22222222, 0x33333333, 0x44444444); | |
| 187 | − | |
| 188 | − SET_TRAP_HANDLER(check_fastcall_invoke_5); | |
| 189 | − ((void __fastcall (*)(unsigned, unsigned, unsigned, unsigned, unsigned)) TRAP)(0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555); | |
| 190 | −} | |
| 191 | − | |
| 192 | − | |
| 193 | −///////////////////////////////////////////////////////////////////////// | |
| 194 | −////////// TEST FUNCTION CODE GENERATION | |
| 195 | −///////////////////////////////////////////////////////////////////////// | |
| 196 | − | |
| 197 | −int __fastcall check_fastcall_espdiff_0(void) | |
| 198 | −{ | |
| 199 | − return 0; | |
| 200 | −} | |
| 201 | − | |
| 202 | −int __fastcall check_fastcall_espdiff_1(int a) | |
| 203 | −{ | |
| 204 | − return a; | |
| 205 | −} | |
| 206 | − | |
| 207 | −int __fastcall check_fastcall_espdiff_2(int a, int b) | |
| 208 | −{ | |
| 209 | − return a + b; | |
| 210 | −} | |
| 211 | − | |
| 212 | −int __fastcall check_fastcall_espdiff_3(int a, int b, int c) | |
| 213 | −{ | |
| 214 | − return a + b + c; | |
| 215 | −} | |
| 216 | − | |
| 217 | −int __fastcall check_fastcall_espdiff_4(int a, int b, int c, int d) | |
| 218 | −{ | |
| 219 | − return a + b + c + d; | |
| 220 | −} | |
| 221 | − | |
| 222 | −int __fastcall check_fastcall_espdiff_5(int a, int b, int c, int d, int e) | |
| 223 | −{ | |
| 224 | − return a + b + c + d + e; | |
| 225 | −} | |
| 226 | − | |
| 227 | −void test_fastcall_espdiff() | |
| 228 | −{ | |
| 229 | − int x; | |
| 230 | − SET_SAFECALL_TARGET(check_fastcall_espdiff_0); | |
| 231 | − x = ((typeof(&check_fastcall_espdiff_0))SAFECALL)(); | |
| 232 | − assert(x == 0); | |
| 233 | − assert(ESPDIFF == 0); | |
| 234 | − | |
| 235 | − SET_SAFECALL_TARGET(check_fastcall_espdiff_1); | |
| 236 | − x = ((typeof(&check_fastcall_espdiff_1))SAFECALL)(1); | |
| 237 | − assert(x == 1); | |
| 238 | − assert(ESPDIFF == 0); | |
| 239 | − | |
| 240 | − SET_SAFECALL_TARGET(check_fastcall_espdiff_2); | |
| 241 | − x = ((typeof(&check_fastcall_espdiff_2))SAFECALL)(1, 2); | |
| 242 | − assert(x == 1 + 2); | |
| 243 | − assert(ESPDIFF == 0); | |
| 244 | − | |
| 245 | − SET_SAFECALL_TARGET(check_fastcall_espdiff_3); | |
| 246 | − x = ((typeof(&check_fastcall_espdiff_3))SAFECALL)(1, 2, 3); | |
| 247 | − assert(x == 1 + 2 + 3); | |
| 248 | − assert(ESPDIFF == 1*4); | |
| 249 | − | |
| 250 | − SET_SAFECALL_TARGET(check_fastcall_espdiff_4); | |
| 251 | − x = ((typeof(&check_fastcall_espdiff_4))SAFECALL)(1, 2, 3, 4); | |
| 252 | − assert(x == 1 + 2 + 3 + 4); | |
| 253 | − assert(ESPDIFF == 2*4); | |
| 254 | − | |
| 255 | − SET_SAFECALL_TARGET(check_fastcall_espdiff_5); | |
| 256 | − x = ((typeof(&check_fastcall_espdiff_5))SAFECALL)(1, 2, 3, 4, 5); | |
| 257 | − assert(x == 1 + 2 + 3 + 4 + 5); | |
| 258 | − assert(ESPDIFF == 3*4); | |
| 259 | −} | |
| 260 | − | |
| 261 | −int main() | |
| 262 | −{ | |
| 263 | −#define N 10000 | |
| 264 | − int i; | |
| 265 | − | |
| 266 | − for (i = 1; i <= N; i++) { | |
| 267 | − test_fastcall_espdiff(); | |
| 268 | − } | |
| 269 | − | |
| 270 | − for (i = 1; i <= N; i++) { | |
| 271 | − test_fastcall_invoke(); | |
| 272 | − } | |
| 273 | − | |
| 274 | − puts("TEST OK"); | |
| 275 | − return 0; | |
| 276 | −} | |
| 1 | +#include <stdio.h> | |
| 2 | +#include <assert.h> | |
| 3 | + | |
| 4 | +#ifndef _WIN32 | |
| 5 | +#define __fastcall __attribute((fastcall)) | |
| 6 | +#endif | |
| 7 | + | |
| 8 | +#if 1 | |
| 9 | +#define SYMBOL(x) _##x | |
| 10 | +#else | |
| 11 | +#define SYMBOL(x) x | |
| 12 | +#endif | |
| 13 | + | |
| 14 | +///////////////////////////////////////////////////////////////////////// | |
| 15 | +////////// TRAP FRAMEWORK | |
| 16 | +///////////////////////////////////////////////////////////////////////// | |
| 17 | +// if you cast 'TRAP' to a function pointer and call it, | |
| 18 | +// it will save all 8 registers, | |
| 19 | +// and jump into C-code (previously set using 'SET_TRAP_HANDLER(x)'), | |
| 20 | +// in C-code you can pop DWORDs from stack and modify registers | |
| 21 | +// | |
| 22 | + | |
| 23 | +void *SYMBOL(trap_handler); | |
| 24 | + | |
| 25 | +extern unsigned char SYMBOL(trap)[]; | |
| 26 | +asm ( | |
| 27 | + ".text;" | |
| 28 | + "_trap:;" | |
| 29 | + "pushl %esp;" | |
| 30 | + "pusha;" | |
| 31 | + "addl $0x4, 0xc(%esp);" | |
| 32 | + "pushl %esp;" | |
| 33 | + "call *_trap_handler;" | |
| 34 | + "addl $0x4, %esp;" | |
| 35 | + "movl 0xc(%esp), %eax;" | |
| 36 | + "movl %eax, 0x20(%esp);" | |
| 37 | + "popa;" | |
| 38 | + "popl %esp;" | |
| 39 | + "ret;" | |
| 40 | +); | |
| 41 | + | |
| 42 | +struct trapframe { | |
| 43 | + unsigned edi, esi, ebp, esp, ebx, edx, ecx, eax; | |
| 44 | +}; | |
| 45 | + | |
| 46 | + | |
| 47 | +#define M_FLOAT(addr) (*(float *)(addr)) | |
| 48 | +#define M_DWORD(addr) (*(unsigned *)(addr)) | |
| 49 | +#define M_WORD(addr) (*(unsigned short *)(addr)) | |
| 50 | +#define M_BYTE(addr) (*(unsigned char *)(addr)) | |
| 51 | +#define R_EAX ((tf)->eax) | |
| 52 | +#define R_ECX ((tf)->ecx) | |
| 53 | +#define R_EDX ((tf)->edx) | |
| 54 | +#define R_EBX ((tf)->ebx) | |
| 55 | +#define R_ESP ((tf)->esp) | |
| 56 | +#define R_EBP ((tf)->ebp) | |
| 57 | +#define R_ESI ((tf)->esi) | |
| 58 | +#define R_EDI ((tf)->edi) | |
| 59 | + | |
| 60 | +#define ARG(x) (M_DWORD(R_ESP + (x) * 4)) | |
| 61 | + | |
| 62 | +#define RETN(x) do { \ | |
| 63 | + M_DWORD(R_ESP + (x)) = M_DWORD(R_ESP); \ | |
| 64 | + R_ESP += (x); \ | |
| 65 | +} while (0) | |
| 66 | + | |
| 67 | +#define DUMP() do { \ | |
| 68 | + unsigned i; \ | |
| 69 | + printf("EAX: %08X\n", R_EAX); \ | |
| 70 | + printf("ECX: %08X\n", R_ECX); \ | |
| 71 | + printf("EDX: %08X\n", R_EDX); \ | |
| 72 | + printf("EBX: %08X\n", R_EBX); \ | |
| 73 | + printf("ESP: %08X\n", R_ESP); \ | |
| 74 | + printf("EBP: %08X\n", R_EBP); \ | |
| 75 | + printf("ESI: %08X\n", R_ESI); \ | |
| 76 | + printf("EDI: %08X\n", R_EDI); \ | |
| 77 | + printf("\n"); \ | |
| 78 | + printf("[RETADDR]: %08X\n", M_DWORD(R_ESP)); \ | |
| 79 | + for (i = 1; i <= 8; i++) { \ | |
| 80 | + printf("[ARG%4d]: %08X\n", i, ARG(i)); \ | |
| 81 | + } \ | |
| 82 | +} while (0) | |
| 83 | + | |
| 84 | +#define SET_TRAP_HANDLER(x) ((SYMBOL(trap_handler)) = (x)) | |
| 85 | +#define TRAP ((void *) &SYMBOL(trap)) | |
| 86 | + | |
| 87 | + | |
| 88 | + | |
| 89 | +///////////////////////////////////////////////////////////////////////// | |
| 90 | +////////// SAFECALL FRAMEWORK | |
| 91 | +///////////////////////////////////////////////////////////////////////// | |
| 92 | +// this framwork will convert any calling convention to cdecl | |
| 93 | +// usage: first set call target with 'SET_SAFECALL_TARGET(x)' | |
| 94 | +// then cast 'SAFECALL' to target funtion pointer type and invoke it | |
| 95 | +// after calling, 'ESPDIFF' is the differance of old and new esp | |
| 96 | + | |
| 97 | +void *SYMBOL(sc_call_target); | |
| 98 | +unsigned SYMBOL(sc_retn_addr); | |
| 99 | +unsigned SYMBOL(sc_old_esp); | |
| 100 | +unsigned SYMBOL(sc_new_esp); | |
| 101 | + | |
| 102 | +extern unsigned char SYMBOL(safecall)[]; | |
| 103 | +asm ( | |
| 104 | + ".text;" | |
| 105 | + "_safecall:;" | |
| 106 | + "popl _sc_retn_addr;" | |
| 107 | + "movl %esp, _sc_old_esp;" | |
| 108 | + "call *_sc_call_target;" | |
| 109 | + "movl %esp, _sc_new_esp;" | |
| 110 | + "movl _sc_old_esp, %esp;" | |
| 111 | + "jmp *_sc_retn_addr;" | |
| 112 | +); | |
| 113 | + | |
| 114 | +#define SET_SAFECALL_TARGET(x) ((SYMBOL(sc_call_target)) = (x)) | |
| 115 | +#define SAFECALL ((void *) &SYMBOL(safecall)) | |
| 116 | +#define ESPDIFF (SYMBOL(sc_new_esp) - SYMBOL(sc_old_esp)) | |
| 117 | + | |
| 118 | + | |
| 119 | +///////////////////////////////////////////////////////////////////////// | |
| 120 | +////////// TEST FASTCALL INVOKE | |
| 121 | +///////////////////////////////////////////////////////////////////////// | |
| 122 | + | |
| 123 | +void check_fastcall_invoke_0(struct trapframe *tf) | |
| 124 | +{ | |
| 125 | + //DUMP(); | |
| 126 | + RETN(0); | |
| 127 | +} | |
| 128 | + | |
| 129 | +void check_fastcall_invoke_1(struct trapframe *tf) | |
| 130 | +{ | |
| 131 | + //DUMP(); | |
| 132 | + assert(R_ECX == 0x11111111); | |
| 133 | + RETN(0); | |
| 134 | +} | |
| 135 | +void check_fastcall_invoke_2(struct trapframe *tf) | |
| 136 | +{ | |
| 137 | + //DUMP(); | |
| 138 | + assert(R_ECX == 0x11111111); | |
| 139 | + assert(R_EDX == 0x22222222); | |
| 140 | + RETN(0); | |
| 141 | +} | |
| 142 | +void check_fastcall_invoke_3(struct trapframe *tf) | |
| 143 | +{ | |
| 144 | + //DUMP(); | |
| 145 | + assert(R_ECX == 0x11111111); | |
| 146 | + assert(R_EDX == 0x22222222); | |
| 147 | + assert(ARG(1) == 0x33333333); | |
| 148 | + RETN(1*4); | |
| 149 | +} | |
| 150 | +void check_fastcall_invoke_4(struct trapframe *tf) | |
| 151 | +{ | |
| 152 | + //DUMP(); | |
| 153 | + assert(R_ECX == 0x11111111); | |
| 154 | + assert(R_EDX == 0x22222222); | |
| 155 | + assert(ARG(1) == 0x33333333); | |
| 156 | + assert(ARG(2) == 0x44444444); | |
| 157 | + RETN(2*4); | |
| 158 | +} | |
| 159 | + | |
| 160 | +void check_fastcall_invoke_5(struct trapframe *tf) | |
| 161 | +{ | |
| 162 | + //DUMP(); | |
| 163 | + assert(R_ECX == 0x11111111); | |
| 164 | + assert(R_EDX == 0x22222222); | |
| 165 | + assert(ARG(1) == 0x33333333); | |
| 166 | + assert(ARG(2) == 0x44444444); | |
| 167 | + assert(ARG(3) == 0x55555555); | |
| 168 | + RETN(3*4); | |
| 169 | +} | |
| 170 | + | |
| 171 | +void test_fastcall_invoke() | |
| 172 | +{ | |
| 173 | + SET_TRAP_HANDLER(check_fastcall_invoke_0); | |
| 174 | + ((void __fastcall (*)(void)) TRAP)(); | |
| 175 | + | |
| 176 | + SET_TRAP_HANDLER(check_fastcall_invoke_1); | |
| 177 | + ((void __fastcall (*)(unsigned)) TRAP)(0x11111111); | |
| 178 | + | |
| 179 | + SET_TRAP_HANDLER(check_fastcall_invoke_2); | |
| 180 | + ((void __fastcall (*)(unsigned, unsigned)) TRAP)(0x11111111, 0x22222222); | |
| 181 | + | |
| 182 | + SET_TRAP_HANDLER(check_fastcall_invoke_3); | |
| 183 | + ((void __fastcall (*)(unsigned, unsigned, unsigned)) TRAP)(0x11111111, 0x22222222, 0x33333333); | |
| 184 | + | |
| 185 | + SET_TRAP_HANDLER(check_fastcall_invoke_4); | |
| 186 | + ((void __fastcall (*)(unsigned, unsigned, unsigned, unsigned)) TRAP)(0x11111111, 0x22222222, 0x33333333, 0x44444444); | |
| 187 | + | |
| 188 | + SET_TRAP_HANDLER(check_fastcall_invoke_5); | |
| 189 | + ((void __fastcall (*)(unsigned, unsigned, unsigned, unsigned, unsigned)) TRAP)(0x11111111, 0x22222222, 0x33333333, 0x44444444, 0x55555555); | |
| 190 | +} | |
| 191 | + | |
| 192 | + | |
| 193 | +///////////////////////////////////////////////////////////////////////// | |
| 194 | +////////// TEST FUNCTION CODE GENERATION | |
| 195 | +///////////////////////////////////////////////////////////////////////// | |
| 196 | + | |
| 197 | +int __fastcall check_fastcall_espdiff_0(void) | |
| 198 | +{ | |
| 199 | + return 0; | |
| 200 | +} | |
| 201 | + | |
| 202 | +int __fastcall check_fastcall_espdiff_1(int a) | |
| 203 | +{ | |
| 204 | + return a; | |
| 205 | +} | |
| 206 | + | |
| 207 | +int __fastcall check_fastcall_espdiff_2(int a, int b) | |
| 208 | +{ | |
| 209 | + return a + b; | |
| 210 | +} | |
| 211 | + | |
| 212 | +int __fastcall check_fastcall_espdiff_3(int a, int b, int c) | |
| 213 | +{ | |
| 214 | + return a + b + c; | |
| 215 | +} | |
| 216 | + | |
| 217 | +int __fastcall check_fastcall_espdiff_4(int a, int b, int c, int d) | |
| 218 | +{ | |
| 219 | + return a + b + c + d; | |
| 220 | +} | |
| 221 | + | |
| 222 | +int __fastcall check_fastcall_espdiff_5(int a, int b, int c, int d, int e) | |
| 223 | +{ | |
| 224 | + return a + b + c + d + e; | |
| 225 | +} | |
| 226 | + | |
| 227 | +void test_fastcall_espdiff() | |
| 228 | +{ | |
| 229 | + int x; | |
| 230 | + SET_SAFECALL_TARGET(check_fastcall_espdiff_0); | |
| 231 | + x = ((typeof(&check_fastcall_espdiff_0))SAFECALL)(); | |
| 232 | + assert(x == 0); | |
| 233 | + assert(ESPDIFF == 0); | |
| 234 | + | |
| 235 | + SET_SAFECALL_TARGET(check_fastcall_espdiff_1); | |
| 236 | + x = ((typeof(&check_fastcall_espdiff_1))SAFECALL)(1); | |
| 237 | + assert(x == 1); | |
| 238 | + assert(ESPDIFF == 0); | |
| 239 | + | |
| 240 | + SET_SAFECALL_TARGET(check_fastcall_espdiff_2); | |
| 241 | + x = ((typeof(&check_fastcall_espdiff_2))SAFECALL)(1, 2); | |
| 242 | + assert(x == 1 + 2); | |
| 243 | + assert(ESPDIFF == 0); | |
| 244 | + | |
| 245 | + SET_SAFECALL_TARGET(check_fastcall_espdiff_3); | |
| 246 | + x = ((typeof(&check_fastcall_espdiff_3))SAFECALL)(1, 2, 3); | |
| 247 | + assert(x == 1 + 2 + 3); | |
| 248 | + assert(ESPDIFF == 1*4); | |
| 249 | + | |
| 250 | + SET_SAFECALL_TARGET(check_fastcall_espdiff_4); | |
| 251 | + x = ((typeof(&check_fastcall_espdiff_4))SAFECALL)(1, 2, 3, 4); | |
| 252 | + assert(x == 1 + 2 + 3 + 4); | |
| 253 | + assert(ESPDIFF == 2*4); | |
| 254 | + | |
| 255 | + SET_SAFECALL_TARGET(check_fastcall_espdiff_5); | |
| 256 | + x = ((typeof(&check_fastcall_espdiff_5))SAFECALL)(1, 2, 3, 4, 5); | |
| 257 | + assert(x == 1 + 2 + 3 + 4 + 5); | |
| 258 | + assert(ESPDIFF == 3*4); | |
| 259 | +} | |
| 260 | + | |
| 261 | +int main() | |
| 262 | +{ | |
| 263 | +#define N 10000 | |
| 264 | + int i; | |
| 265 | + | |
| 266 | + for (i = 1; i <= N; i++) { | |
| 267 | + test_fastcall_espdiff(); | |
| 268 | + } | |
| 269 | + | |
| 270 | + for (i = 1; i <= N; i++) { | |
| 271 | + test_fastcall_invoke(); | |
| 272 | + } | |
| 273 | + | |
| 274 | + puts("TEST OK"); | |
| 275 | + return 0; | |
| 276 | +} | |