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