Home | History | Annotate | Download | only in tests
      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 
     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))
     44 int mul ( int x, int y ) { return x * y; }
     45 
     46 int fact1 ( int n )
     47 {
     48    addMoreLard();
     49    if (n == 0) return 1; else return mul(n, fact2(n-1));
     50 }
     51 int fact2 ( int n )
     52 {
     53    addMoreLard();
     54    if (n == 0) return 1; else return mul(n, fact1(n-1));
     55 }
     56 
     57 
     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 
     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 
     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 
    104 static void send ( char* s )
    105 {
    106   while (*s) {
    107     write(1, s, 1);
    108     s++;
    109   }
    110 }
    111 
    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 
    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