Julian Seward 6af183ac21 Changes to make function wrapping work better on ppc64-linux:
- when recording the non-redirected address in guest_NRADDR, also
  snapshot the current R2 value, as that will be needed to run the
  original safely

- As a consequence, the original-function information extracted by
  VALGRIND_GET_ORIG_FN is different on ppc64-linux (2 words) from
  all other platforms (1 word).  So change the type of it from
  void* to a new type OrigFn which can be defined differently for
  each platform.

- Change the CALL_FN_* macros for ppc64-linux to save/restore
  R2 values appropriately.

- ppc64-linux: detect overflow/underflow of the redirect stack
  and bring Valgrind to a halt if this happens

- Update VG_CLREQ_SZB for ppc32/64 (was out of date).





git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5569
2006-01-20 14:31:57 +00:00

156 lines
3.6 KiB
C

#include <stdlib.h>
#include <stdio.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 { \
UInt* vec = (_vec); \
/* x86 spills for v > 4, amd64 for v > 12. */ \
UInt i, sum = 0; \
UInt v1 = vec[1-1]; \
UInt v2 = vec[2-1]; \
UInt v3 = vec[3-1]; \
UInt v4 = vec[4-1]; \
UInt v5 = vec[5-1]; \
UInt v6 = vec[6-1]; \
UInt v7 = vec[7-1]; \
UInt v8 = vec[8-1]; \
UInt v9 = vec[9-1]; \
UInt v10 = vec[10-1]; \
UInt v11 = vec[11-1]; \
UInt v12 = vec[12-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); \
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); \
} \
_rlval = sum; \
} while (0)
/* --------------- 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;
OrigFn fn;
VALGRIND_GET_ORIG_FN(fn);
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);
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;
OrigFn fn;
VALGRIND_GET_ORIG_FN(fn);
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);
return r;
}
/* --------------- 2 --------------- */
UInt fn_2 ( UInt a1, UInt a2 )
{
UInt r;
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;
OrigFn fn;
VALGRIND_GET_ORIG_FN(fn);
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);
return r;
}
/* --------------- main --------------- */
int main ( void )
{
UInt w;
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);
return 0;
}