1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140
|
#include <unistd.h>
#include <stdio.h>
#include <malloc.h>
#include <stdlib.h>
#include "valgrind.h"
/* This is the same as wrap5.c, except that the recursion depth is 16.
This is intended to check that on ppc64-linux, which uses a
16-entry per-thread stack, the resulting stack overflow is caught.
(Undetected overflows in redirection stacks are very bad news; they
cause guest code to fail in all sorts of strange ways.)
Hence this test has two expected outcomes:
- on ppc64-linux, a stack overflow is caught, and V aborts.
- on everything else, it runs successfully to completion.
Note, pre() and post() used so as to avoid printf, which messes
up the call stacks on ppc64-linux due to intercept of mempcpy.
*/
typedef
struct _Lard {
struct _Lard* next;
char stuff[999];
}
Lard;
Lard* lard = NULL;
static int ctr = 0;
void addMoreLard ( void )
{
Lard* p;
ctr++;
if ((ctr % 3) == 1) {
p = malloc(sizeof(Lard));
p->next = lard;
lard = p;
}
}
static void post ( char* s, int n, int r );
static void pre ( char* s, int n );
static int fact1 ( int n );
static int fact2 ( int n );
/* This is needed to stop gcc4 turning 'fact' into a loop */
__attribute__((noinline))
int mul ( int x, int y ) { return x * y; }
int fact1 ( int n )
{
addMoreLard();
if (n == 0) return 1; else return mul(n, fact2(n-1));
}
int fact2 ( int n )
{
addMoreLard();
if (n == 0) return 1; else return mul(n, fact1(n-1));
}
int I_WRAP_SONAME_FNNAME_ZU(NONE,fact1) ( int n )
{
int r;
OrigFn fn;
VALGRIND_GET_ORIG_FN(fn);
pre("wrapper1", n);
addMoreLard();
CALL_FN_W_W(r, fn, n);
addMoreLard();
post("wrapper1", n, r);
if (n >= 3) r += fact2(2);
return r;
}
int I_WRAP_SONAME_FNNAME_ZU(NONE,fact2) ( int n )
{
int r;
OrigFn fn;
VALGRIND_GET_ORIG_FN(fn);
pre("wrapper2", n);
addMoreLard();
CALL_FN_W_W(r, fn, n);
addMoreLard();
post("wrapper2", n, r);
return r;
}
/* --------------- */
int main ( void )
{
int r, n = 15; /* 14 succeeds on ppc64-linux, >= 15 fails */
Lard *p, *p_next;
printf("computing fact1(%d)\n", n); fflush(stdout);
r = fact1(n);
printf("fact1(%d) = %d\n", n, r); fflush(stdout);
printf("allocated %d Lards\n", ctr); fflush(stdout);
for (p = lard; p; p = p_next) {
p_next = p->next;
free(p);
}
return 0;
}
static void send ( char* s )
{
while (*s) {
write(1, s, 1);
s++;
}
}
static void pre ( char* s, int n )
{
char buf[50];
fflush(stdout);
sprintf(buf,"%d", n);
send("in ");
send(s);
send("-pre: fact(");
send(buf);
send(")\n");
fflush(stdout);
}
static void post ( char* s, int n, int r )
{
char buf[50];
fflush(stdout);
sprintf(buf,"%d", n);
send("in ");
send(s);
send("-post: fact(");
send(buf);
send(") = ");
sprintf(buf,"%d", r);
send(buf);
send("\n");
fflush(stdout);
}
|