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