#include <stdlib.h> #include <stdio.h> #include <assert.h> #include "valgrind.h" /* Program that checks all numbers of args (0 through 12) work for wrapping. Also calls originals which trash all the iregs in an attempt to shake out any problems caused by insufficient saving of caller-save registers around the hidden call instruction. */ typedef unsigned int UInt; #define ROL(_x,n) (((_x) << n) | ((UInt)(_x)) >> ((8*sizeof(UInt)-n))) #define TRASH_IREGS(_rlval, _vec) \ do { \ register UInt* vec = (_vec); \ /* x86 spills for v > 4, amd64 for v > 12. Getting ppc */ \ /* to spill is quite difficult, requiring v > 28 or so. */ \ register UInt i, sum = 0; \ register UInt v1 = vec[1-1]; \ register UInt v2 = vec[2-1]; \ register UInt v3 = vec[3-1]; \ register UInt v4 = vec[4-1]; \ register UInt v5 = vec[5-1]; \ register UInt v6 = vec[6-1]; \ register UInt v7 = vec[7-1]; \ register UInt v8 = vec[8-1]; \ register UInt v9 = vec[9-1]; \ register UInt v10 = vec[10-1]; \ register UInt v11 = vec[11-1]; \ register UInt v12 = vec[12-1]; \ register UInt v13 = vec[13-1]; \ register UInt v14 = vec[14-1]; \ register UInt v15 = vec[15-1]; \ register UInt v16 = vec[16-1]; \ register UInt v17 = vec[17-1]; \ register UInt v18 = vec[18-1]; \ register UInt v19 = vec[19-1]; \ register UInt v20 = vec[20-1]; \ register UInt v21 = vec[21-1]; \ register UInt v22 = vec[22-1]; \ register UInt v23 = vec[23-1]; \ register UInt v24 = vec[24-1]; \ register UInt v25 = vec[25-1]; \ register UInt v26 = vec[26-1]; \ register UInt v27 = vec[27-1]; \ register UInt v28 = vec[28-1]; \ register UInt v29 = vec[29-1]; \ for (i = 0; i < 50; i++) { \ v1 = ROL(v1,1); \ v2 = ROL(v2,2); \ v3 = ROL(v3,3); \ v4 = ROL(v4,4); \ v5 = ROL(v5,5); \ v6 = ROL(v6,6); \ v7 = ROL(v7,7); \ v8 = ROL(v8,8); \ v9 = ROL(v9,9); \ v10 = ROL(v10,10); \ v11 = ROL(v11,11); \ v12 = ROL(v12,12); \ v13 = ROL(v13,13); \ v14 = ROL(v14,14); \ v15 = ROL(v15,15); \ v16 = ROL(v16,16); \ v17 = ROL(v17,17); \ v18 = ROL(v18,18); \ v19 = ROL(v19,19); \ v20 = ROL(v20,20); \ v21 = ROL(v21,21); \ v22 = ROL(v22,22); \ v23 = ROL(v23,23); \ v24 = ROL(v24,24); \ v25 = ROL(v25,25); \ v26 = ROL(v26,26); \ v27 = ROL(v27,27); \ v28 = ROL(v28,28); \ v29 = ROL(v29,29); \ sum ^= ((0xFFF & v1) * i); \ sum ^= (v1-v2); \ sum ^= (v1-v3); \ sum ^= (v1-v4); \ sum ^= (v1-v5); \ sum ^= (v1-v6); \ sum ^= (v1-v7); \ sum ^= (v1-v8); \ sum ^= (v1-v9); \ sum ^= (v1-v10); \ sum ^= (v1-v11); \ sum ^= (v1-v12); \ sum ^= (v1-v13); \ sum ^= (v1-v14); \ sum ^= (v1-v15); \ sum ^= (v1-v16); \ sum ^= (v1-v17); \ sum ^= (v1-v18); \ sum ^= (v1-v19); \ sum ^= (v1-v20); \ sum ^= (v1-v21); \ sum ^= (v1-v22); \ sum ^= (v1-v23); \ sum ^= (v1-v24); \ sum ^= (v1-v25); \ sum ^= (v1-v26); \ sum ^= (v1-v27); \ sum ^= (v1-v28); \ sum ^= (v1-v29); \ } \ _rlval = sum; \ } while (0) /* Returns one, in a way that gcc probably can't constant fold out */ volatile int one_actual_return_value = 0; /* the value one() returns */ __attribute__((noinline)) int one ( void ) { int i, sum, a[7]; for (i = 0; i < 7; i++) a[i] = i; a[3] = 3+one_actual_return_value; sum = 0; for (i = 7-1; i >= 0; i--) sum += a[i] - i; return sum; } #define LOOPS_START \ { register int len = one(); \ register int x0; for (x0 = 0x1000; x0 < 0x1000+len; x0++) { \ register int x1; for (x1 = 0x1100; x1 < 0x1100+len; x1++) { \ register int x2; for (x2 = 0x1200; x2 < 0x1200+len; x2++) { \ register int x3; for (x3 = 0x1300; x3 < 0x1300+len; x3++) { \ register int x4; for (x4 = 0x1400; x4 < 0x1400+len; x4++) { \ register int x5; for (x5 = 0x1500; x5 < 0x1500+len; x5++) { \ register int x6; for (x6 = 0x1600; x6 < 0x1600+len; x6++) { \ register int x7; for (x7 = 0x1700; x7 < 0x1700+len; x7++) { \ register int x8; for (x8 = 0x1800; x8 < 0x1800+len; x8++) { \ register int x9; for (x9 = 0x1900; x9 < 0x1900+len; x9++) { \ register int xA; for (xA = 0x1A00; xA < 0x1A00+len; xA++) { \ register int xB; for (xB = 0x1B00; xB < 0x1B00+len; xB++) { \ register int xC; for (xC = 0x1C00; xC < 0x1C00+len; xC++) { \ register int xD; for (xD = 0x1D00; xD < 0x1D00+len; xD++) { \ register int xE; for (xE = 0x1E00; xE < 0x1E00+len; xE++) { \ register int xF; for (xF = 0x1F00; xF < 0x1F00+len; xF++) { \ /* */ #define LOOPS_END \ assert(xF >= 0x1F00 && xF <= 0x1F00+len); } \ assert(xE >= 0x1E00 && xE <= 0x1E00+len); } \ assert(xD >= 0x1D00 && xD <= 0x1D00+len); } \ assert(xC >= 0x1C00 && xC <= 0x1C00+len); } \ assert(xB >= 0x1B00 && xB <= 0x1B00+len); } \ assert(xA >= 0x1A00 && xA <= 0x1A00+len); } \ assert(x9 >= 0x1900 && x9 <= 0x1900+len); } \ assert(x8 >= 0x1800 && x8 <= 0x1800+len); } \ assert(x7 >= 0x1700 && x7 <= 0x1700+len); } \ assert(x6 >= 0x1600 && x6 <= 0x1600+len); } \ assert(x5 >= 0x1500 && x5 <= 0x1500+len); } \ assert(x4 >= 0x1400 && x4 <= 0x1400+len); } \ assert(x3 >= 0x1300 && x3 <= 0x1300+len); } \ assert(x2 >= 0x1200 && x2 <= 0x1200+len); } \ assert(x1 >= 0x1100 && x1 <= 0x1100+len); } \ assert(x0 >= 0x1000 && x0 <= 0x1000+len); } \ } /* General idea is for the wrappers to use LOOPS_START / LOOPS_END to soak up lots of int registers. And the orig fn uses TRASH_IREGS to do the same. If there is insufficient saving of caller-saves regs by the CALL_FN_* macros, then hopefully the assertions in LOOPS_END will fail. */ /* --------------- 0 --------------- */ UInt fn_0 ( void ) { UInt r; UInt* words = calloc(200, sizeof(UInt)); TRASH_IREGS(r, words); free(words); return r; } UInt I_WRAP_SONAME_FNNAME_ZU(NONE,fn_0) ( UInt a1 ) { UInt r = 0; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); LOOPS_START printf("fn_0 wrapper pre ()\n"); CALL_FN_W_v(r, fn); printf("fn_0 wrapper post1 = %d\n", (int)r); CALL_FN_v_v(fn); printf("fn_0 wrapper post2 = %d\n", (int)r); LOOPS_END return r; } /* --------------- 1 --------------- */ UInt fn_1 ( UInt a1 ) { UInt r; UInt* words = calloc(200, sizeof(UInt)); words[1-1] = a1; TRASH_IREGS(r, words); free(words); return r; } UInt I_WRAP_SONAME_FNNAME_ZU(NONE,fn_1) ( UInt a1 ) { UInt r = 0; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); LOOPS_START printf("fn_1 wrapper pre ( %d )\n", (int)a1); CALL_FN_W_W(r, fn, a1); printf("fn_1 wrapper post1 = %d\n", (int)r); CALL_FN_v_W(fn, a1); printf("fn_1 wrapper post2 = %d\n", (int)r); LOOPS_END return r; } /* --------------- 2 --------------- */ UInt fn_2 ( UInt a1, UInt a2 ) { UInt r = 0; UInt* words = calloc(200, sizeof(UInt)); words[1-1] = a1; words[2-1] = a2; TRASH_IREGS(r, words); free(words); return r; } UInt I_WRAP_SONAME_FNNAME_ZU(NONE,fn_2) ( UInt a1, UInt a2 ) { UInt r = 0; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); LOOPS_START printf("fn_2 wrapper pre ( %d, %d )\n", (int)a1, (int)a2); CALL_FN_W_WW(r, fn, a1, a2); printf("fn_2 wrapper post1 = %d\n", (int)r); CALL_FN_v_WW(fn, a1, a2); printf("fn_2 wrapper post2 = %d\n", (int)r); LOOPS_END return r; } /* --------------- 3 --------------- */ UInt fn_3 ( UInt a1, UInt a2, UInt a3 ) { UInt r; UInt* words = calloc(200, sizeof(UInt)); words[1-1] = a1; words[2-1] = a2; words[3-1] = a3; TRASH_IREGS(r, words); free(words); return r; } UInt I_WRAP_SONAME_FNNAME_ZU(NONE,fn_3) ( UInt a1, UInt a2, UInt a3 ) { UInt r = 0; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); LOOPS_START printf("fn_3 wrapper pre ( %d, %d, %d )\n", (int)a1, (int)a2, (int)a3); CALL_FN_W_WWW(r, fn, a1, a2, a3); printf("fn_3 wrapper post1 = %d\n", (int)r); CALL_FN_v_WWW(fn, a1, a2, a3); printf("fn_3 wrapper post2 = %d\n", (int)r); LOOPS_END return r; } /* --------------- 4 --------------- */ UInt fn_4 ( UInt a1, UInt a2, UInt a3, UInt a4 ) { UInt r; UInt* words = calloc(200, sizeof(UInt)); words[1-1] = a1; words[2-1] = a2; words[3-1] = a3; words[4-1] = a4; TRASH_IREGS(r, words); free(words); return r; } UInt I_WRAP_SONAME_FNNAME_ZU(NONE,fn_4) ( UInt a1, UInt a2, UInt a3, UInt a4 ) { UInt r = 0; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); LOOPS_START printf("fn_4 wrapper pre ( %d, %d, %d, %d )\n", (int)a1, (int)a2, (int)a3, (int)a4); CALL_FN_W_WWWW(r, fn, a1, a2, a3, a4); printf("fn_4 wrapper post1 = %d\n", (int)r); LOOPS_END return r; } /* --------------- 5 --------------- */ UInt fn_5 ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5 ) { UInt r; UInt* words = calloc(200, sizeof(UInt)); words[1-1] = a1; words[2-1] = a2; words[3-1] = a3; words[4-1] = a4; words[5-1] = a5; TRASH_IREGS(r, words); free(words); return r; } UInt I_WRAP_SONAME_FNNAME_ZU(NONE,fn_5) ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5 ) { UInt r = 0; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); LOOPS_START printf("fn_5 wrapper pre ( %d, %d, %d, %d, %d )\n", (int)a1, (int)a2, (int)a3, (int)a4, (int)a5); CALL_FN_W_5W(r, fn, a1, a2, a3, a4, a5); printf("fn_5 wrapper post1 = %d\n", (int)r); LOOPS_END return r; } /* --------------- 6 --------------- */ UInt fn_6 ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5, UInt a6 ) { UInt r; UInt* words = calloc(200, sizeof(UInt)); words[1-1] = a1; words[2-1] = a2; words[3-1] = a3; words[4-1] = a4; words[5-1] = a5; words[6-1] = a6; TRASH_IREGS(r, words); free(words); return r; } UInt I_WRAP_SONAME_FNNAME_ZU(NONE,fn_6) ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5, UInt a6 ) { UInt r = 0; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); LOOPS_START printf("fn_6 wrapper pre ( %d, %d, %d, %d, %d, %d )\n", (int)a1, (int)a2, (int)a3, (int)a4, (int)a5, (int)a6); CALL_FN_W_6W(r, fn, a1, a2, a3, a4, a5, a6); printf("fn_6 wrapper post1 = %d\n", (int)r); LOOPS_END return r; } /* --------------- 7 --------------- */ UInt fn_7 ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5, UInt a6, UInt a7 ) { UInt r; UInt* words = calloc(200, sizeof(UInt)); words[1-1] = a1; words[2-1] = a2; words[3-1] = a3; words[4-1] = a4; words[5-1] = a5; words[6-1] = a6; words[7-1] = a7; TRASH_IREGS(r, words); free(words); return r; } UInt I_WRAP_SONAME_FNNAME_ZU(NONE,fn_7) ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5, UInt a6, UInt a7 ) { UInt r = 0; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); LOOPS_START printf("fn_7 wrapper pre ( %d, %d, %d, %d, %d, %d, %d )\n", (int)a1, (int)a2, (int)a3, (int)a4, (int)a5, (int)a6, (int)a7); CALL_FN_W_7W(r, fn, a1, a2, a3, a4, a5, a6, a7); printf("fn_7 wrapper post1 = %d\n", (int)r); LOOPS_END return r; } /* --------------- 8 --------------- */ UInt fn_8 ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5, UInt a6, UInt a7, UInt a8 ) { UInt r; UInt* words = calloc(200, sizeof(UInt)); words[1-1] = a1; words[2-1] = a2; words[3-1] = a3; words[4-1] = a4; words[5-1] = a5; words[6-1] = a6; words[7-1] = a7; words[8-1] = a8; TRASH_IREGS(r, words); free(words); return r; } UInt I_WRAP_SONAME_FNNAME_ZU(NONE,fn_8) ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5, UInt a6, UInt a7, UInt a8 ) { UInt r = 0; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); LOOPS_START printf("fn_8 wrapper pre ( %d, %d, %d, %d, %d, %d, %d, %d )\n", (int)a1, (int)a2, (int)a3, (int)a4, (int)a5, (int)a6, (int)a7, (int)a8); CALL_FN_W_8W(r, fn, a1, a2, a3, a4, a5, a6, a7, a8); printf("fn_8 wrapper post1 = %d\n", (int)r); LOOPS_END return r; } /* --------------- 9 --------------- */ UInt fn_9 ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5, UInt a6, UInt a7, UInt a8, UInt a9 ) { UInt r; UInt* words = calloc(200, sizeof(UInt)); words[1-1] = a1; words[2-1] = a2; words[3-1] = a3; words[4-1] = a4; words[5-1] = a5; words[6-1] = a6; words[7-1] = a7; words[8-1] = a8; words[9-1] = a9; TRASH_IREGS(r, words); free(words); return r; } UInt I_WRAP_SONAME_FNNAME_ZU(NONE,fn_9) ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5, UInt a6, UInt a7, UInt a8, UInt a9 ) { UInt r = 0; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); LOOPS_START printf("fn_9 wrapper pre ( %d, %d, %d, %d, %d, %d, %d, %d, %d )\n", (int)a1, (int)a2, (int)a3, (int)a4, (int)a5, (int)a6, (int)a7, (int)a8, (int)a9); CALL_FN_W_9W(r, fn, a1, a2, a3, a4, a5, a6, a7, a8, a9); printf("fn_9 wrapper post1 = %d\n", (int)r); LOOPS_END return r; } /* --------------- 10 --------------- */ UInt fn_10 ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5, UInt a6, UInt a7, UInt a8, UInt a9, UInt a10 ) { UInt r; UInt* words = calloc(200, sizeof(UInt)); words[1-1] = a1; words[2-1] = a2; words[3-1] = a3; words[4-1] = a4; words[5-1] = a5; words[6-1] = a6; words[7-1] = a7; words[8-1] = a8; words[9-1] = a9; words[10-1] = a10; TRASH_IREGS(r, words); free(words); return r; } UInt I_WRAP_SONAME_FNNAME_ZU(NONE,fn_10) ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5, UInt a6, UInt a7, UInt a8, UInt a9, UInt a10 ) { UInt r = 0; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); LOOPS_START printf("fn_10 wrapper pre ( %d, %d, %d, %d, %d, %d, %d, %d, %d, %d )\n", (int)a1, (int)a2, (int)a3, (int)a4, (int)a5, (int)a6, (int)a7, (int)a8, (int)a9, (int)a10); CALL_FN_W_10W(r, fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10); printf("fn_10 wrapper post1 = %d\n", (int)r); LOOPS_END return r; } /* --------------- 11 --------------- */ UInt fn_11 ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5, UInt a6, UInt a7, UInt a8, UInt a9, UInt a10, UInt a11 ) { UInt r; UInt* words = calloc(200, sizeof(UInt)); words[1-1] = a1; words[2-1] = a2; words[3-1] = a3; words[4-1] = a4; words[5-1] = a5; words[6-1] = a6; words[7-1] = a7; words[8-1] = a8; words[9-1] = a9; words[10-1] = a10; words[11-1] = a11; TRASH_IREGS(r, words); free(words); return r; } UInt I_WRAP_SONAME_FNNAME_ZU(NONE,fn_11) ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5, UInt a6, UInt a7, UInt a8, UInt a9, UInt a10, UInt a11 ) { UInt r = 0; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); LOOPS_START printf("fn_11 wrapper pre ( %d, %d, %d, %d, %d, %d, %d, %d, %d, %d, %d )\n", (int)a1, (int)a2, (int)a3, (int)a4, (int)a5, (int)a6, (int)a7, (int)a8, (int)a9, (int)a10, (int)a11); CALL_FN_W_11W(r, fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11); printf("fn_11 wrapper post1 = %d\n", (int)r); LOOPS_END return r; } /* --------------- 12 --------------- */ UInt fn_12 ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5, UInt a6, UInt a7, UInt a8, UInt a9, UInt a10, UInt a11, UInt a12 ) { UInt r; UInt* words = calloc(200, sizeof(UInt)); words[1-1] = a1; words[2-1] = a2; words[3-1] = a3; words[4-1] = a4; words[5-1] = a5; words[6-1] = a6; words[7-1] = a7; words[8-1] = a8; words[9-1] = a9; words[10-1] = a10; words[11-1] = a11; words[12-1] = a12; TRASH_IREGS(r, words); free(words); return r; } UInt I_WRAP_SONAME_FNNAME_ZU(NONE,fn_12) ( UInt a1, UInt a2, UInt a3, UInt a4, UInt a5, UInt a6, UInt a7, UInt a8, UInt a9, UInt a10, UInt a11, UInt a12 ) { UInt r = 0; OrigFn fn; VALGRIND_GET_ORIG_FN(fn); LOOPS_START printf("fn_12 wrapper pre ( %d, %d, %d, %d, %d, %d, " "%d, %d, %d, %d, %d, %d )\n", (int)a1, (int)a2, (int)a3, (int)a4, (int)a5, (int)a6, (int)a7, (int)a8, (int)a9, (int)a10, (int)a11, (int)a12); CALL_FN_W_12W(r, fn, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12); printf("fn_12 wrapper post1 = %d\n", (int)r); LOOPS_END return r; } /* --------------- main --------------- */ int main ( void ) { UInt w; one_actual_return_value = 1; printf("fn_0 ...\n"); w = fn_0(); printf(" ... %d\n\n", (int)w); printf("fn_1 ...\n"); w = fn_1(42); printf(" ... %d\n\n", (int)w); printf("fn_2 ...\n"); w = fn_2(42,43); printf(" ... %d\n\n", (int)w); printf("fn_3 ...\n"); w = fn_3(42,43,44); printf(" ... %d\n\n", (int)w); printf("fn_4 ...\n"); w = fn_4(42,43,44,45); printf(" ... %d\n\n", (int)w); printf("fn_5 ...\n"); w = fn_5(42,43,44,45,46); printf(" ... %d\n\n", (int)w); printf("fn_6 ...\n"); w = fn_6(42,43,44,45,46,47); printf(" ... %d\n\n", (int)w); printf("fn_7 ...\n"); w = fn_7(42,43,44,45,46,47,48); printf(" ... %d\n\n", (int)w); printf("fn_8 ...\n"); w = fn_8(42,43,44,45,46,47,48,49); printf(" ... %d\n\n", (int)w); printf("fn_9 ...\n"); w = fn_9(42,43,44,45,46,47,48,49,50); printf(" ... %d\n\n", (int)w); printf("fn_10 ...\n"); w = fn_10(42,43,44,45,46,47,48,49,50,51); printf(" ... %d\n\n", (int)w); printf("fn_11 ...\n"); w = fn_11(42,43,44,45,46,47,48,49,50,51,52); printf(" ... %d\n\n", (int)w); printf("fn_12 ...\n"); w = fn_12(42,43,44,45,46,47,48,49,50,51,52,53); printf(" ... %d\n\n", (int)w); return 0; }