This commit allows us to force the relocation of functions being
[dyninst.git] / dyninstAPI / tests / src / test5.C
1 // $Id: test1.C,v 1.52 2000/03/22 19:08:48 tikir Exp 
2 //
3 // libdyninst validation suite test #1
4 //    Author: Jeff Hollingsworth (1/7/97)
5 //        derived from a previous test by Bryan Buck
6 //
7
8 //  This program tests the basic features of the dyninst API.  
9 //      The mutatee that goes with this file is test5.mutatee.C
10 //      
11 //  Naming conventions:
12 //      All functions, variables, etc are name funcXX_YY, exprXX_YY, etc.
13 //          XX is the test number
14 //          YY is the instance withing the test
15 //          func1_2 is the second function used in test case #1.
16 //
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <assert.h>
21 #ifdef i386_unknown_nt4_0
22 #include <windows.h>
23 #include <winbase.h>
24 #else
25 #include <unistd.h>
26 #endif
27
28 #include "BPatch.h"
29 #include "BPatch_Vector.h"
30 #include "BPatch_thread.h"
31 #include "BPatch_snippet.h"
32 #include "BPatch_flowGraph.h"
33 #include "test_util.h"
34
35 // #include <vector.h>
36
37
38 int debugPrint = 0; // internal "mutator" tracing
39 int errorPrint = 0; // external "dyninst" tracing (via errorFunc)
40
41 bool forceRelocation = false;  // Force relocation upon instrumentation
42
43 bool runAllTests = true;
44 const unsigned int MAX_TEST = 12;
45 bool runTest[MAX_TEST+1];
46 bool passedTest[MAX_TEST+1];
47
48 BPatch *bpatch;
49
50 static char *mutateeNameRoot = "test5.mutatee";
51
52 // control debug printf statements
53 #define dprintf if (debugPrint) printf
54
55 /**************************************************************************
56  * Error callback
57  **************************************************************************/
58
59 void errorFunc(BPatchErrorLevel level, int num, const char **params)
60 {
61     if (num == 0) {
62         // conditional reporting of warnings and informational messages
63         if (errorPrint) {
64             if (level == BPatchInfo)
65               { if (errorPrint > 1) printf("%s\n", params[0]); }
66             else
67                 printf("%s", params[0]);
68         }
69     } else {
70         // reporting of actual errors
71         char line[256];
72         const char *msg = bpatch->getEnglishErrorString(num);
73         bpatch->formatErrorString(line, sizeof(line), msg, params);
74         
75         printf("Error #%d (level %d): %s\n", num, level, line);
76     
77         // We consider some errors fatal.
78         if (num == 101) {
79            exit(-1);
80         }
81     }
82 }
83
84 /**************************************************************************
85  * Utility functions
86  **************************************************************************/
87
88 // check that the cost of a snippet is sane.  Due to differences between
89 //   platforms, it is impossible to check this exactly in a machine independent
90 //   manner.
91 void checkCost(BPatch_snippet snippet)
92 {
93     float cost;
94     BPatch_snippet copy;
95
96     // test copy constructor too.
97     copy = snippet;
98
99     cost = snippet.getCost();
100     dprintf("Snippet cost=%g\n", cost);
101     if (cost < 0.0) {
102         printf("*Error*: negative snippet cost\n");
103     } else if (cost == 0.0) {
104         printf("*Warning*: zero snippet cost\n");
105     } else if (cost > 0.01) {
106         printf("*Error*: snippet cost of %f, exceeds max expected of 0.1",
107             cost);
108     }
109 }
110
111
112 /**************************************************************************
113  * Tests
114  **************************************************************************/
115
116 //  
117 // Start Test Case #1 - (C++ argument pass)
118 //       
119 void mutatorTest1(BPatch_thread *appThread, BPatch_image *appImage)
120 {
121 #if defined(sparc_sun_solaris2_4)
122    BPatch_Vector<BPatch_point *> *point1_1 =
123       appImage->findProcedurePoint("arg_test::call_cpp", BPatch_subroutine);
124
125    assert(point1_1);
126
127    // check the paramter passing modes
128    BPatch_variableExpr *arg0 = appImage->findVariable(*(*point1_1)[0],
129        "reference");
130    BPatch_variableExpr *arg1 = appImage->findVariable(*(*point1_1)[0],
131        "arg1");
132    BPatch_variableExpr *arg2 = appImage->findVariable(*(*point1_1)[0],
133        "arg2");
134    BPatch_variableExpr *arg3 = appImage->findVariable(*(*point1_1)[0],
135        "arg3");
136    BPatch_variableExpr *arg4 = appImage->findVariable(*(*point1_1)[0],
137        "m");
138
139    if (!arg0 || !arg1 || !arg2 || !arg3 || !arg4) {
140       fprintf(stderr, "**Failed** test #1 (argument passing)\n");
141       if ( !arg0 )
142          fprintf(stderr, "  can't find local variable arg0\n");
143       if ( !arg1 )
144          fprintf(stderr, "  can't find local variable arg1\n");
145       if ( !arg2 )
146          fprintf(stderr, "  can't find local variable arg2\n");
147       if ( !arg3 )
148          fprintf(stderr, "  can't find local variable arg3\n");
149       if ( !arg4 )
150          fprintf(stderr, "  can't find local variable arg4\n");
151       return;
152    }
153
154    BPatch_type *type1_0 = const_cast<BPatch_type *> (arg0->getType());
155    BPatch_type *type1_1 = const_cast<BPatch_type *> (arg1->getType());
156    BPatch_type *type1_2 = const_cast<BPatch_type *> (arg2->getType());
157    BPatch_type *type1_3 = const_cast<BPatch_type *> (arg4->getType());
158    assert(type1_0 && type1_1 && type1_2 && type1_3);
159
160    if (!type1_1->isCompatible(type1_3)) {
161        fprintf(stderr, "**Failed** test #1 (C++ argument pass)\n");
162        fprintf(stderr,"    type1_1 reported as incompatibile with type1_3\n");
163        return;
164    }
165
166    if (!type1_2->isCompatible(type1_0)) {
167         fprintf(stderr, "**Failed** test #1 (C++ argument pass)\n");
168         fprintf(stderr,"    type1_2 reported as incompatibile with type1_0\n")
169 ;
170         return;
171    }
172
173    BPatch_arithExpr expr1_1(BPatch_assign, *arg3, BPatch_constExpr(1));
174    checkCost(expr1_1);
175    appThread->insertSnippet(expr1_1, *point1_1);
176
177    // pass a paramter to a class member function
178    BPatch_Vector<BPatch_point *> *point1_2 =
179      appImage->findProcedurePoint("arg_test::func_cpp", BPatch_exit);
180    if (!point1_2 || (point1_2->size() < 1)) {
181       fprintf(stderr, "Unable to find point arg_test::func_cpp - exit.\n");
182       exit(-1);
183    }
184
185    BPatch_function *call1_func = appImage->findFunction("arg_test::arg_pass");
186    if (call1_func == NULL) {
187        fprintf(stderr, "Unable to find function \"cpp_test_util::call_cpp.\"\n");
188        exit(1);
189    }
190
191    BPatch_variableExpr *this1 = appImage->findVariable("test1");
192    if (this1 == NULL) {
193       fprintf(stderr, "**Failed** test #1 (C++ argument pass)\n");
194       fprintf(stderr, "Unable to find variable \"test1\"\n");
195       exit(1);
196    }
197
198    BPatch_Vector<BPatch_snippet *> call1_args;
199    BPatch_constExpr expr1_2((unsigned long)this1->getBaseAddr());
200    call1_args.push_back(&expr1_2);
201    BPatch_constExpr expr1_3(1);
202    call1_args.push_back(&expr1_3);
203    BPatch_funcCallExpr call1Expr(*call1_func, call1_args);
204
205    checkCost(call1Expr);
206    appThread->insertSnippet(call1Expr, *point1_2);
207 #endif
208 }
209
210 //
211 // Start Test Case #2 - (overload function)
212 // 
213 void mutatorTest2(BPatch_thread *appThread, BPatch_image *appImage)
214 {
215
216 #if defined(sparc_sun_solaris2_4)
217     BPatch_Vector<BPatch_point *> *point2_1 =
218        appImage->findProcedurePoint("overload_func_test::func_cpp", BPatch_subroutine);
219     if (!point2_1 || (point2_1->size() < 2)) {
220          fprintf(stderr, "Unable to find point overload_func_test::func_cpp - calls. \n");
221          exit(-1);
222     }
223
224     for (int n=0; n<point2_1->size(); n++) {
225        BPatch_function *func;
226
227        if ((func = (*point2_1)[n]->getCalledFunction()) == NULL) continue;
228
229        char fn[256];
230        if (func->getName(fn, 256) == NULL) {
231             fprintf(stderr, "**Failed** test #2 (overloaded functions)\n");
232             fprintf(stderr, "    Can't get name of called function in overload_func_test::func_cpp\n");
233             return;
234        }
235        if (strcmp(fn, "overload_func_test::call_cpp")) {
236            fprintf(stderr, "**Failed** test #2 (overloaded functions)\n");
237            fprintf(stderr, "    The called function was named \"%s\""
238                            " not \"overload_func_test::call_cpp\"\n", fn);
239            return;
240        }
241        BPatch_Vector<BPatch_point *> *point2_2 = func->findPoint(BPatch_entry);
242        BPatch_Vector<BPatch_localVar *> *param = func->getParams();
243        assert(point2_2 && param);
244
245        switch (n) {
246           case 0 : {
247
248               if ( (param->size() == 1) ||
249                    ((param->size() == 2) && (!strcmp((*param)[0]->getName(), "this"))) ) 
250                  //First param might be "this"!
251                  break;
252               else {
253                  fprintf(stderr, "**Failed** test #2 (overloaded functions)\n");
254                  fprintf(stderr, "    The overloaded function has wrong number of parameters\n");
255                  return;
256               }
257           }
258           case 1 : {
259               if ( (param->size() == 1) ||
260                    ((param->size() == 2) && (!strcmp((*param)[0]->getName(), "this"))) )
261                  //First param might be "this"!
262                  break;
263               else {
264                  fprintf(stderr, "**Failed** test #2 (overloaded functions)\n"); 
265                  fprintf(stderr, "    The overloaded function has wrong number of parameters\n");
266                  return;
267               }
268           }
269           case 2 : {
270               if ( (param->size() == 2) ||
271                    ((param->size() == 3) && (!strcmp((*param)[0]->getName(), "this"))) )
272                  //First param might be "this"!
273                  break;
274               else {
275                  fprintf(stderr, "**Failed** test #2 (overloaded functions)\n"); 
276                  fprintf(stderr, "    The overloaded function has wrong number of parameters\n");
277                  return;
278               }
279           }
280           default : {
281               fprintf(stderr, "**Failed** test #2 (overloaded functions)\n");
282               fprintf(stderr, "    Incorrect number of subroutine calls from overload_func_test::func_cpp\n");
283               return;
284           }
285        };
286     }
287
288     BPatch_Vector<BPatch_point *> *point2_3 =
289     appImage->findProcedurePoint("overload_func_test::func_cpp", BPatch_exit);
290     if (!point2_3 || point2_3->size() <1) {
291          fprintf(stderr, "Unable to find point overload_func_test::func_cpp - exit.\n");
292          exit(-1);
293     }
294
295     BPatch_function *call2_func = appImage->findFunction("cpp_test_util::call_cpp");
296     if (call2_func == NULL) {
297         fprintf(stderr, "Unable to find function \"cpp_test_util::call_cpp.\"\n");
298         exit(1);
299     }
300
301     BPatch_variableExpr *this2 = appImage->findVariable("test2");
302     if (this2 == NULL) {
303        fprintf(stderr, "**Failed** test #2 (overloaded functions)\n");
304        fprintf(stderr, "Unable to find variable \"test2\"\n");
305        exit(1);
306     }
307
308     BPatch_Vector<BPatch_snippet *> call2_args;
309     BPatch_constExpr expr2_0((unsigned long)this2->getBaseAddr());
310     call2_args.push_back(&expr2_0);
311     BPatch_constExpr expr2_1(2);
312     call2_args.push_back(&expr2_1);
313     BPatch_funcCallExpr call2Expr(*call2_func, call2_args);
314
315     checkCost(call2Expr);
316     appThread->insertSnippet(call2Expr, *point2_3);
317 #endif
318 }
319
320 //
321 // Start Test Case #3 - (overload operator)
322 //      
323 void mutatorTest3(BPatch_thread *appThread, BPatch_image *appImage)
324 {
325    BPatch_Vector<BPatch_point *> *point3_1 =
326      appImage->findProcedurePoint("overload_op_test::func_cpp", BPatch_subroutine);
327    assert(point3_1);
328
329   int index = 0;
330   BPatch_function *func;
331   while (index < point3_1->size()) {
332      if ((func = (*point3_1)[index]->getCalledFunction()) == NULL) {
333         fprintf(stderr, "**Failed** test #3 (overload operation)\n");
334         fprintf(stderr, "    Can't find the overload operator\n");
335         exit(1);
336      }
337      char fn[256];
338      if (!strcmp("overload_op_test::operator++", func->getName(fn, 256)))
339         break;
340      index ++;
341   }
342
343    BPatch_Vector<BPatch_point *> *point3_2 = func->findPoint(BPatch_exit);
344    assert(point3_2);
345
346    BPatch_function *call3_1 = appImage->findFunction("overload_op_test_call_cpp");
347    if (call3_1 == NULL) {
348        fprintf(stderr, "Unable to find function \"overload_op_test_call_cpp\"\n");
349        exit(1);
350    }
351
352    BPatch_Vector<BPatch_snippet *> opArgs;
353    opArgs.push_back(new BPatch_retExpr());
354    BPatch_funcCallExpr call3_1Expr(*call3_1, opArgs);
355
356    checkCost(call3_1Expr);
357    appThread->insertSnippet(call3_1Expr, *point3_2);
358    //  int tag = 1;
359    //  while (tag != 0) {}
360 }
361
362 //  
363 // Start Test Case #4 - (static member)
364 // 
365 void mutatorTest4(BPatch_thread *appThread, BPatch_image *appImage)
366 {
367 #if defined(sparc_sun_solaris2_4)
368
369    BPatch_Vector<BPatch_point *> *point4_1 =
370      appImage->findProcedurePoint("static_test::func_cpp", BPatch_subroutine);
371    assert(point4_1);
372
373    int index = 0;
374    BPatch_function *func;
375    int bound = point4_1->size();
376    BPatch_Vector<BPatch_variableExpr *> vect4_1;
377   
378    while ((index < bound) && (vect4_1.size() < 2)) {
379      if ((func = (*point4_1)[index]->getCalledFunction()) == NULL) {
380         fprintf(stderr, "**Failed** test #4 (static member)\n");
381         fprintf(stderr, "    Can't find the invoked function\n");
382         exit(1);
383      }
384
385      char fn[256];
386      if (!strcmp("static_test::call_cpp", func->getName(fn, 256))) {
387         BPatch_Vector<BPatch_point *> *point4_2 = func->findPoint(BPatch_exit);
388         assert(point4_2);
389
390         // use getComponent to access this "count". However, getComponent is
391         // causing core dump at this point
392         BPatch_variableExpr *var4_1 = appImage->findVariable(*(*point4_2)[0],
393              "count");
394         if (!var4_1) {
395            fprintf(stderr, "**Failed** test #4 (static member)\n");
396            fprintf(stderr, "  Can't find static variable count\n");
397            return;
398         }
399         vect4_1.push_back(var4_1);
400      }
401      index ++;
402    }
403
404    if (2 != vect4_1.size()) {
405        fprintf(stderr, "**Failed** test #4 (static member)\n");
406        fprintf(stderr, "  Incorrect size of an vector\n");
407        exit(1);
408    }
409    if (vect4_1[0]->getBaseAddr() != vect4_1[1]->getBaseAddr()) {
410        fprintf(stderr, "**Failed** test #4 (static member)\n");
411        fprintf(stderr, "  Static member does not have a same address\n");
412        exit(1);
413    };
414
415    BPatch_Vector<BPatch_point *> *point4_3 =
416    appImage->findProcedurePoint("static_test::func_cpp", BPatch_exit);
417    assert(point4_3);
418
419    BPatch_function *call4_func = appImage->findFunction("static_test_call_cpp");
420    if (call4_func == NULL) {
421        fprintf(stderr, "Unable to find function \"cpp_test_util::call_cpp.\"\n");
422        exit(1);
423    }
424
425    BPatch_Vector<BPatch_snippet *> call4_args;
426    BPatch_constExpr expr4_0(4);
427    call4_args.push_back(&expr4_0);
428    BPatch_funcCallExpr call4Expr(*call4_func, call4_args);
429
430    checkCost(call4Expr);
431    appThread->insertSnippet(call4Expr, *point4_3);
432
433 #endif
434 }
435
436
437 //  
438 // Start Test Case #5 - (namespace)
439 // 
440 void mutatorTest5(BPatch_thread *appThread, BPatch_image *appImage)
441 {
442 #if defined(sparc_sun_solaris2_4)
443     BPatch_Vector<BPatch_point *> *point5_1 =
444       appImage->findProcedurePoint("namespace_test::func_cpp", BPatch_exit);
445
446     assert(point5_1);
447     BPatch_variableExpr *var1 = appImage->findVariable(*(*point5_1)[0],
448             "local_fn_var");
449     BPatch_variableExpr *var2 = appImage->findVariable(*(*point5_1)[0],
450             "local_file_var");
451     BPatch_variableExpr *var3 = appImage->findVariable(*(*point5_1)[0],
452             "CPP_DEFLT_ARG");
453
454     if (!var1 || !var2 || !var3) {
455         fprintf(stderr, "**Failed** test #5 (namespace)\n");
456         if (!var1)
457            fprintf(stderr, "  can't find local variable local_fn_var\n");
458         if (!var2)
459            fprintf(stderr, "  can't find local variable file local_file_var\n");
460         if (!var3)
461            fprintf(stderr, "  can't find global variable CPP_DEFLT_ARG\n");
462         return;
463     }
464     BPatch_Vector<BPatch_point *> *point5_2 =
465       appImage->findProcedurePoint("main", BPatch_allLocations);
466
467     if (!point5_2 || (point5_2->size() < 1)) {
468       fprintf(stderr, "Unable to find point in main.\n");
469       exit(-1);
470     }
471     BPatch_variableExpr *expr5_1=appImage->findVariable(*(*point5_2)[0], "test5");
472     if (!expr5_1) {
473          fprintf(stderr, "**Failed** test #5 (namespace)\n");
474          fprintf(stderr, "    Unable to locate test5 in main\n");
475     }
476
477     BPatch_Vector<BPatch_variableExpr *> *fields = expr5_1->getComponents();
478     if (!fields || fields->size() == 0 ) {
479        fprintf(stderr, "**Failed** test #5 (namespace)\n");
480        fprintf(stderr, "  struct lacked correct number of elements\n");
481        exit(-1);
482     }
483
484     int index = 0;
485     while ( index < fields->size() ) {
486      if (!strcmp("class_variable", (*fields)[index]->getName()) ) {
487          BPatch_function *call5_func = appImage->findFunction("cpp_test_util::call_cpp");
488          if (call5_func == NULL) {
489              fprintf(stderr, "**Failed** test #5 (namespace)\n");
490              fprintf(stderr, "Unable to find function \"cpp_test_util::call_cpp.\"\n");
491              exit(1);
492          }
493
494          BPatch_variableExpr *this5 = appImage->findVariable("test5");
495          if (this5 == NULL) {
496              fprintf(stderr, "**Failed** test #5 (namespace)\n");
497              fprintf(stderr, "Unable to find variable \"test5\"\n");
498              exit(1);
499          }
500
501          BPatch_Vector<BPatch_snippet *> call5_args;
502
503          BPatch_constExpr expr5_0((unsigned long)this5->getBaseAddr());
504          call5_args.push_back(&expr5_0);
505          BPatch_constExpr expr5_1(5);
506          call5_args.push_back(&expr5_1);
507          BPatch_funcCallExpr call5Expr(*call5_func, call5_args);
508          checkCost(call5Expr);
509          appThread->insertSnippet(call5Expr, *point5_1);
510          return;
511      }
512      index ++;
513     }
514     fprintf(stderr, "**Failed** test #5 (namespace)\n");
515     fprintf(stderr, "    Can't find class member variables\n");
516 #endif
517 }
518
519
520 //  
521 // Start Test Case #6 - (exception)
522 // 
523 void mutatorTest6(BPatch_thread *appThread, BPatch_image *appImage)
524 {
525 #if defined(sparc_sun_solaris2_4)
526
527    BPatch_Vector<BPatch_point *> *point6_1 =
528      appImage->findProcedurePoint("exception_test::func_cpp", BPatch_subroutine);
529    assert(point6_1);
530
531    int index = 0;
532    BPatch_function *func;
533    int bound = point6_1->size();
534
535    BPatch_variableExpr *testno = appImage->findVariable(*(*point6_1)[0],
536             "testno");
537    if (!testno) {
538       fprintf(stderr, "**Failed** test #6 (exception)\n");
539       fprintf(stderr, "    Can't find the variable in try branch of exception statement\n");
540       exit(1);
541    }
542
543    while (index < bound) {
544      if ((func = (*point6_1)[index]->getCalledFunction()) == NULL) {
545         fprintf(stderr, "**Failed** test #6 (exception)\n");
546         fprintf(stderr, "    Can't find the invoked function\n");
547         exit(1);
548      }
549      char fn[256];
550      if (!strcmp("sample_exception::response", func->getName(fn, 256))) {
551          BPatch_Vector<BPatch_point *> *point6_2 = func->findPoint(BPatch_exit);
552          assert(point6_2);
553
554          BPatch_function *call6_func =
555            appImage->findFunction("exception_test_call_cpp");
556          if (call6_func == NULL) {
557              fprintf(stderr, "Unable to find function \"exception_test_call_cpp.\"\n");
558              exit(1);
559          }
560
561          BPatch_Vector<BPatch_snippet *> call6_args;
562          BPatch_constExpr expr6_0(6);
563          call6_args.push_back(&expr6_0);
564          BPatch_funcCallExpr call6Expr(*call6_func, call6_args);
565
566          checkCost(call6Expr);
567          appThread->insertSnippet(call6Expr, *point6_2);
568          return;
569      }
570      index++;
571    }
572
573 #endif
574 }
575
576 //
577 // Start Test Case #7 - (template)
578 //
579 void mutatorTest7(BPatch_thread *appThread, BPatch_image *appImage)
580 {
581 #if defined(sparc_sun_solaris2_4)
582    BPatch_Vector<BPatch_point *> *point7_1 =
583      appImage->findProcedurePoint("template_test::func_cpp", BPatch_subroutine);
584    assert(point7_1);
585
586    int index = 0;
587    int flag = 0;
588    BPatch_function *func;
589    int bound = point7_1->size();
590    BPatch_variableExpr *content7_1;
591    BPatch_variableExpr *content7_2;
592
593    while (index < bound) {
594      if ((func = (*point7_1)[index]->getCalledFunction()) == NULL) {
595         fprintf(stderr, "**Failed** test #7 (template)\n");
596         fprintf(stderr, "    Can't find the invoked function\n");
597         exit(1);
598      }
599
600      char fn[256];
601      if (!strcmp("sample_template<int>::content", func->getName(fn, 256))) {
602          BPatch_Vector<BPatch_point *> *point7_2 = func->findPoint(BPatch_entry);
603          assert(point7_2);
604
605          content7_1 = appImage->findVariable(*(*point7_2)[0], "ret");
606          if (!content7_1) {
607             fprintf(stderr, "**Failed** test #7 (template)\n");
608             fprintf(stderr, "  Can't find local variable ret\n");
609             return;
610          }
611          flag++;
612      } else if (!strcmp("sample_template<char>::content", func->getName(fn, 256))) {
613
614             BPatch_Vector<BPatch_point *> *point7_3 = func->findPoint(BPatch_entry);
615             assert(point7_3);
616
617             content7_2 = appImage->findVariable(*(*point7_3)[0], "ret");
618             if (!content7_2) {
619                fprintf(stderr, "**Failed** test #7 (template)\n");
620                fprintf(stderr, "  Can't find local variable ret\n");
621                return;
622             }
623             flag++;
624      }
625      index ++;
626   }
627
628   if (flag != 2) {
629      fprintf(stderr, "**Failed** test #7 (template)\n");
630      exit(1);
631   }
632
633    BPatch_type *type7_0 = appImage->findType("int");
634    BPatch_type *type7_1 = const_cast<BPatch_type *> (content7_1->getType());
635    BPatch_type *type7_2 = appImage->findType("char");
636    BPatch_type *type7_3 = const_cast<BPatch_type *> (content7_2->getType());
637
638    if (!type7_0->isCompatible(type7_1)) {
639       fprintf(stderr, "**Failed** test #7 (template)\n");
640       fprintf(stderr,"    type7_0 reported as incompatibile with type7_1\n");
641       return;
642    }
643
644    if (!type7_2->isCompatible(type7_3)) {
645       fprintf(stderr, "**Failed** test #7 (template)\n");
646       fprintf(stderr,"    type7_2 reported as incompatibile with type7_3\n");
647       return;
648    }
649    
650    BPatch_Vector<BPatch_point *> *point7_4 =
651    appImage->findProcedurePoint("template_test::func_cpp", BPatch_exit);
652    assert(point7_4);
653
654    BPatch_function *call7_func = appImage->findFunction("template_test_call_cpp");
655    if (call7_func == NULL) {
656        fprintf(stderr, "Unable to find function \"cpp_test_util::call_cpp.\"\n");
657        exit(1);
658    }
659
660    BPatch_Vector<BPatch_snippet *> call7_args;
661    BPatch_constExpr expr7_0(7);
662    call7_args.push_back(&expr7_0);
663    BPatch_funcCallExpr call7Expr(*call7_func, call7_args);
664
665    checkCost(call7Expr);
666    appThread->insertSnippet(call7Expr, *point7_4);
667 #endif
668 }
669
670 //
671 // Start Test Case #8 - (declaration)
672 //   
673 void mutatorTest8(BPatch_thread *appThread, BPatch_image *appImage)
674 {
675 #if defined(sparc_sun_solaris2_4)
676      // Find the exit point to the procedure "func_cpp"
677      BPatch_Vector<BPatch_point *> *point8_1 =
678          appImage->findProcedurePoint("decl_test::func_cpp", BPatch_exit);
679      if (!point8_1 || (point8_1->size() < 1)) {
680            fprintf(stderr, "Unable to find point decl_test::func_cpp - exit.\n");
681            exit(-1);
682      }
683
684      BPatch_Vector<BPatch_point *> *point8_2 =
685        appImage->findProcedurePoint("main", BPatch_allLocations);
686
687      if (!point8_2 || (point8_2->size() < 1)) {
688             fprintf(stderr, "Unable to find point in main.\n");
689             exit(-1);
690      }
691
692      BPatch_function *call8_func  = appImage->findFunction("decl_test::call_cpp");
693      if (call8_func == NULL ) {
694         fprintf(stderr, "**Failed** test #8 (declaration)\n");
695         fprintf(stderr, "Unable to find function \"decl_test::call_cpp\"\n");
696         exit(1);
697      }
698
699      BPatch_variableExpr *this8 = appImage->findVariable("test8");
700      if (this8 == NULL) {
701         fprintf(stderr, "**Failed** test #8 (declaration)\n");
702         fprintf(stderr, "Unable to find variable \"test8\"\n");
703         exit(1);
704      }
705
706      BPatch_Vector<BPatch_snippet *> call8_args;
707      BPatch_constExpr expr8_0((unsigned long)this8->getBaseAddr());
708      call8_args.push_back(&expr8_0);
709      BPatch_constExpr expr8_1(8);
710      call8_args.push_back(&expr8_1);
711      BPatch_funcCallExpr call8Expr(*call8_func, call8_args);
712
713      // find the variables of different scopes
714      BPatch_variableExpr *expr8_2=appImage->findVariable("CPP_DEFLT_ARG");
715      BPatch_variableExpr *expr8_3=appImage->findVariable(*(*point8_2)[0], "test8");
716      BPatch_variableExpr *expr8_4=appImage->findVariable(*(*point8_1)[0], "CPP_DEFLT_ARG");
717      if (!expr8_2 || !expr8_3 || !expr8_4) {
718            fprintf(stderr, "**Failed** test #8 (delcaration)\n");
719            fprintf(stderr, "    Unable to locate one of variables\n");
720            exit(1);
721      }
722
723     BPatch_Vector<BPatch_variableExpr *> *fields = expr8_3->getComponents();
724     if (!fields || fields->size() == 0 ) {
725           fprintf(stderr, "**Failed** test #8 (declaration)\n");
726           fprintf(stderr, "  struct lacked correct number of elements\n");
727           exit(-1);
728      }
729
730     int index = 0;
731     while ( index < fields->size() ) {
732         char fieldName[100];
733         strcpy(fieldName, (*fields)[index]->getName());
734        if ( !strcmp("CPP_TEST_UTIL_VAR", (*fields)[index]->getName()) ) {
735            dprintf("Inserted snippet2\n");
736            checkCost(call8Expr);
737            appThread->insertSnippet(call8Expr, *point8_1);
738            return;
739        }
740        index ++;
741     }
742     fprintf(stderr, "**Failed** test #8 (declaration)\n");
743     fprintf(stderr, "    Can't find inherited class member variables\n");
744 #endif
745 }
746
747 //
748 // Start Test Case #9 - (derivation)
749 //
750 void mutatorTest9(BPatch_thread *, BPatch_image *appImage)
751 {
752 #if defined(sparc_sun_solaris2_4)
753    bool found = false;
754    
755    // Find the exit point to the procedure "func_cpp"
756    BPatch_Vector<BPatch_point *> *point9_1 =
757       appImage->findProcedurePoint("derivation_test::func_cpp", BPatch_exit);
758    if (!point9_1 || (point9_1->size() < 1)) {
759          fprintf(stderr, "Unable to find point derivation_test::func_cpp - exit.\n");
760          exit(-1);
761    }
762
763    // access inherited class member variables has been examined in the test 8
764    // now let's try to access the inherited class member function.
765
766    BPatch_Vector<BPatch_point *> *point9_2 =
767       appImage->findProcedurePoint("main", BPatch_allLocations);
768
769    if (!point9_2 || (point9_2->size() < 1)) {
770           fprintf(stderr, "Unable to find point in main.\n");
771           exit(-1);
772    }
773
774    BPatch_variableExpr *expr9_0=appImage->findVariable(*(*point9_2)[0], "test9");
775    if (!expr9_0) {
776       fprintf(stderr, "**Failed** test #9 (derivation)\n");
777       fprintf(stderr, "    Unable to locate one of variables\n");
778       exit(1);
779    }
780
781    BPatch_Vector<BPatch_variableExpr *> *fields = expr9_0->getComponents();
782    if (!fields || fields->size() == 0 ) {
783          fprintf(stderr, "**Failed** test #9 (derivation)\n");
784          fprintf(stderr, "  struct lacked correct number of elements\n");
785          exit(-1);
786    }
787
788    int index = 0;
789    while ( index < fields->size() ) {
790        if ( !strcmp("call_cpp", (*fields)[index]->getName()) ) {
791            found = true;
792            break;
793        }
794        index ++;
795    }
796    
797    if ( !found ) {
798      fprintf(stderr, "**Failed** test #9 (derivation)\n");
799      fprintf(stderr, "    Can't find inherited class member functions\n");
800   }
801 #endif
802 }
803
804 //
805 // Start Test Case #10 - (find standard C++ library)
806 //
807 void mutatorTest10(BPatch_thread *appThread, BPatch_image *appImage)
808 {
809 #if defined(sparc_sun_solaris2_4) \
810  || defined(i386_unknown_solaris2_5) \
811  || defined(i386_unknown_linux2_0) \
812  || defined(mips_sgi_irix6_4) \
813  || defined(alpha_dec_osf4_0)
814
815    char libStdC[64];
816    BPatch_module *modStdC = NULL;
817    BPatch_Vector<BPatch_module *> *mods = appImage->getModules();
818
819    strcpy(libStdC, "libstdc++");
820
821    // Lookup the libstdc++.so standard library
822    if (!mods || mods->size() == 0) {
823      fprintf(stderr, "**Failed test #10 (find standard C++ library)\n");
824      fprintf(stderr, "  Mutator couldn't search modules of standard library\n");
825      exit(1);
826    }
827    for (int i = 0; i < mods->size() && !(modStdC); i++) {
828        char buf[1024];
829        BPatch_module *m = (*mods)[i];
830        m->getName(buf, 1024);
831        if (!strncmp(libStdC, buf, strlen(libStdC)))
832           modStdC = m;
833    }
834    if (! modStdC ) {
835       fprintf(stderr, "**Failed test #10 (find standard C++ library)\n");
836       fprintf(stderr, "  Mutator couldn't find shlib in standard library\n");
837       fflush(stdout);
838       exit(1);
839    }
840
841    // find ostream::operator<< function in the standard library
842    BPatch_function *func = modStdC->findFunction("ostream::operator<<");
843    if (! func) {
844        fprintf(stderr, "**Failed test #10 (find standard C++ library)\n");
845        fprintf(stderr, "  Mutator couldn't find a function in %s\n", libStdC);
846        exit(1);
847    }
848
849 #endif
850 }
851
852 //
853 // Start Test Case #11 - (replace function in standard C++ library)
854 //
855 void mutatorTest11(BPatch_thread *appThread, BPatch_image *appImage)
856 {
857 // There is no corresponding failure (test2) testing because the only
858 // bad input to replaceFunction is a non-existent BPatch_function.
859
860 #if defined(sparc_sun_solaris2_4) \
861  || defined(alpha_dec_osf4_0)
862
863    char libStdC[64];
864    BPatch_module *modStdC = NULL;
865    BPatch_Vector<BPatch_module *> *mods = appImage->getModules();
866
867    strcpy(libStdC, "libstdc++");
868
869    // Lookup the libstdc++.so standard library
870    if (!mods || mods->size() == 0) {
871      fprintf(stderr, "**Failed test #11 (replace function in standard C++ library)\n");
872      fprintf(stderr, "  Mutator couldn't search modules of standard library\n");
873      exit(1);
874    }
875    for (int i = 0; i < mods->size() && !(modStdC); i++) {
876        char buf[1024];
877        BPatch_module *m = (*mods)[i];
878        m->getName(buf, 1024);
879        if (!strncmp(libStdC, buf, strlen(libStdC)))
880           modStdC = m;
881    }
882    if (! modStdC ) {
883       fprintf(stderr, "**Failed test #11 (replace function in standard C++ library)\n");
884       fprintf(stderr, "  Mutator couldn't find shlib in standard library\n");
885       fflush(stdout);
886       exit(1);
887    }
888
889    // Replace a shlib function with a shlib function
890    char buf1[64], buf2[64];
891
892    BPatch_function *func1 = modStdC->findFunction("ostream::operator<<");
893    BPatch_function *func2 = modStdC->findFunction("istream::operator>>");
894    func1->getName(buf1, 64);
895    func2->getName(buf2, 64);
896
897    if (! func1 || ! func2) {
898        fprintf(stderr, "**Failed test #11 (replace function in standard C++ library)\n");
899        fprintf(stderr, "  Mutator couldn't find a function in %s\n", libStdC);
900        exit(1);
901    }
902    if (! appThread->replaceFunction(*func1, *func2)) {
903         fprintf(stderr, "**Failed test #11 (replace function in standard C++ library)\n");
904         fprintf(stderr, "  Mutator couldn't replaceFunction (shlib -> shlib)\n");
905    }
906
907    // Replace a shlib function with an a.out function
908    BPatch_function *func3 = appImage->findFunction("stdlib_test2::call_cpp");
909    if (! func3 ) {
910       fprintf(stderr, "**Failed test #11 (replace function in standard C++ library)\n");
911       fprintf(stderr, "Unable to find function \"stdlib_test2::call_cpp\"\n");
912       exit(1);
913    }
914    if (! appThread->replaceFunction(*func1, *func3)) {
915       fprintf(stderr, "**Failed test #11 (replace function in standard C++ library)\n");
916       fprintf(stderr, "  Mutator couldn't replaceFunction (shlib -> a.out)\n");
917       exit(1);
918    }
919
920    // Replace an a.out function with a shlib function
921     if (! appThread->replaceFunction(*func3, *func2) ) {
922       fprintf(stderr, "**Failed test #11 (replace function in standard C++ library)\n");
923       fprintf(stderr, "  Mutator couldn't replaceFunction (a.out -> shlib)\n");
924       exit(1);
925     }
926
927 #endif
928 }
929
930 //
931 // Start Test Case #12 - (C++ member function - virtual, const and inline)
932 //
933 void mutatorTest12(BPatch_thread *appThread, BPatch_image *appImage)
934 {
935   BPatch_Vector<BPatch_point *> *point12_0 =
936     appImage->findProcedurePoint("cpp_test::func2_cpp", BPatch_allLocations);
937
938   BPatch_Vector<BPatch_point *> *point12_1 =
939     appImage->findProcedurePoint("cpp_test::func_cpp", BPatch_allLocations);
940
941   BPatch_Vector<BPatch_point *> *point12_2 =
942     appImage->findProcedurePoint("func_test::func_cpp", BPatch_allLocations);
943
944   BPatch_Vector<BPatch_point *> *point12_3 =
945     appImage->findProcedurePoint("func_test::call_cpp", BPatch_allLocations);
946
947   if ( !point12_0 || (point12_0->size() < 1) ||
948        !point12_1 || (point12_1->size() < 1) ||
949        !point12_2 || (point12_2->size() < 1) ||
950        !point12_3 || (point12_3->size() < 1)  ) {
951
952        if ( !point12_0 || (point12_0->size() < 1) ) {
953          fprintf(stderr, "**Failed** test #12 (C++ member functions)\n");
954          fprintf(stderr, "     Unable to find point in an virtual function \"cpp_test::func2_cpp.\"\n");
955        }
956        if ( !point12_1 || (point12_1->size() < 1) ) {
957          fprintf(stderr, "**Warning** test #12 (C++ member functions)\n");
958          fprintf(stderr, "    Unable to find point in a pure virtual function \"cpp_test::func_cpp.\"\n");
959        }
960        if ( !point12_2 || (point12_2->size() < 1) ) {
961          fprintf(stderr, "**Failed** test #12 (C++ member functions)\n");
962          fprintf(stderr, "     Unable to find point in a const function \"func_test::func_cpp.\"\n");
963        }
964        if ( !point12_3 || (point12_3->size() < 1) ) {
965          fprintf(stderr, "**Failed** test #12 (C++ member functions)\n");
966          fprintf(stderr, "     Unable to find point in an inline function \"func_test::call_cpp.\"\n");
967        }
968   }
969
970   for (int n=0; n<point12_2->size(); n++) {
971      BPatch_function *func;
972
973       if ((func = (*point12_2)[n]->getCalledFunction()) == NULL) continue;
974
975       char fn[256];
976       if (func->getName(fn, 256) == NULL) {
977            fprintf(stderr, "**Failed** test #12 (C++ member function)\n");
978            fprintf(stderr, "    Can't get name of called function in func_test::func_cpp\n");
979            exit(1);
980       }
981
982       if (! strcmp(fn, "func_test::call_cpp") ) {
983         BPatch_Vector<BPatch_localVar *> *param = func->getParams();
984         assert(param);
985
986         if ( param->size() != 0 ) {
987           fprintf(stderr, "**Failed** test #12 (C++ member function)\n");
988           fprintf(stderr, "    The inline function is not inlined\n");
989           exit(1);
990         }
991
992         BPatch_variableExpr *var1 = appImage->findVariable(*(*point12_2)[0],
993                        "tmp");
994
995         if (var1 == NULL) {
996           fprintf(stderr, "**Failed** test #12 (C++ member function)\n");
997           fprintf(stderr, "    The inline function is not inlined\n");
998           exit(1);
999         }
1000        return;
1001       }
1002   }
1003
1004   fprintf(stderr, "**Failed** test #12 (C++ member function)\n");
1005   fprintf(stderr, "  Mutator couldn't find inline function in the caller\n");
1006   exit(1);
1007 }
1008
1009 /*******************************************************************************/
1010 /*******************************************************************************/
1011 /*******************************************************************************/
1012
1013 int mutatorMAIN(char *pathname, bool useAttach)
1014 {
1015     BPatch_thread *appThread;
1016
1017     // Create an instance of the BPatch library
1018     bpatch = new BPatch;
1019
1020     // Force functions to be relocated
1021     if (forceRelocation) {
1022       bpatch->setForcedRelocation_NP(true);
1023     }
1024
1025     // Register a callback function that prints any error messages
1026     bpatch->registerErrorCallback(errorFunc);
1027
1028     // Start the mutatee
1029     printf("Starting \"%s\"\n", pathname);
1030
1031     char *child_argv[MAX_TEST+5];
1032    
1033     int n = 0;
1034     child_argv[n++] = pathname;
1035     if (debugPrint) child_argv[n++] = "-verbose";
1036
1037     if (runAllTests) {
1038         child_argv[n++] = "-runall"; // signifies all tests
1039     } else {
1040         child_argv[n++] = "-run";
1041         for (unsigned int j=1; j <= MAX_TEST; j++) {
1042             if (runTest[j]) {
1043                 char str[5];
1044                 sprintf(str, "%d", j);
1045                 child_argv[n++] = strdup(str);
1046             }
1047         }
1048     }
1049
1050     child_argv[n] = NULL;
1051
1052     if (useAttach) {
1053         int pid = startNewProcessForAttach(pathname, child_argv);
1054         if (pid < 0) {
1055             printf("*ERROR*: unable to start tests due to error creating mutatee process\n");
1056             exit(-1);
1057         } else {
1058             dprintf("New mutatee process pid %d started; attaching...\n", pid);
1059         }
1060         P_sleep(1); // let the mutatee catch its breath for a moment
1061         appThread = bpatch->attachProcess(pathname, pid);
1062     } else {
1063         appThread = bpatch->createProcess(pathname, child_argv,NULL);
1064     }
1065
1066     if (appThread == NULL) {
1067         fprintf(stderr, "Unable to run test program.\n");
1068         exit(1);
1069     }
1070
1071     // Read the program's image and get an associated image object
1072     BPatch_image *appImage = appThread->getImage();
1073
1074     // Signal the child that we've attached
1075     if (useAttach) {
1076         signalAttached(appThread, appImage);
1077     }
1078
1079     int i;
1080     BPatch_Vector<BPatch_module *> *m = appImage->getModules();
1081     for (i=0; i < m->size(); i++) {
1082         // dprintf("func %s\n", (*m)[i]->name());
1083     }
1084     BPatch_Vector<BPatch_function *> *p = appImage->getProcedures();
1085     for (i=0; i < p->size(); i++) {
1086         // dprintf("func %s\n", (*p)[i]->name());
1087     }
1088
1089     if (runTest[1]) mutatorTest1(appThread, appImage);
1090     if (runTest[2]) mutatorTest2(appThread, appImage); 
1091     if (runTest[3]) mutatorTest3(appThread, appImage);
1092     if (runTest[4]) mutatorTest4(appThread, appImage); 
1093     if (runTest[5]) mutatorTest5(appThread, appImage); 
1094     if (runTest[6]) mutatorTest6(appThread, appImage); 
1095     if (runTest[7]) mutatorTest7(appThread, appImage);
1096     if (runTest[8]) mutatorTest8(appThread, appImage);
1097     if (runTest[9]) mutatorTest9(appThread, appImage);
1098
1099     // Start of code to continue the process.  All mutations made
1100     // above will be in place before the mutatee begins its tests.
1101
1102     dprintf("starting program execution.\n");
1103     appThread->continueExecution();
1104
1105     while (!appThread->isTerminated())
1106         bpatch->waitForStatusChange();
1107
1108     int exitCode = appThread->terminationStatus();
1109     if (exitCode || debugPrint) printf("Mutatee exit code 0x%x\n", exitCode);
1110
1111     dprintf("Done.\n");
1112     return(exitCode);
1113 }
1114
1115 //
1116 // main - decide our role and call the correct "main"
1117 //
1118 int
1119 main(unsigned int argc, char *argv[])
1120 {
1121     char mutateeName[128];
1122     char libRTname[256];
1123
1124     bool N32ABI = false;
1125     bool useAttach = false;
1126
1127     strcpy(mutateeName,mutateeNameRoot);
1128     libRTname[0]='\0';
1129
1130     if (!getenv("DYNINSTAPI_RT_LIB")) {
1131          fprintf(stderr,"Environment variable DYNINSTAPI_RT_LIB undefined:\n"
1132 #if defined(i386_unknown_nt4_0)
1133                  "    using standard search strategy for libdyninstAPI_RT.dll\n");
1134 #else
1135                  "    set it to the full pathname of libdyninstAPI_RT\n");   
1136          exit(-1);
1137 #endif
1138     } else
1139          strcpy((char *)libRTname, (char *)getenv("DYNINSTAPI_RT_LIB"));
1140
1141     unsigned int i;
1142     // by default run all tests
1143     for (i=1; i <= MAX_TEST; i++) {
1144         runTest[i] = true;
1145         passedTest[i] = false;
1146     }
1147
1148     for (i=1; i < argc; i++) {
1149         if (strncmp(argv[i], "-v+", 3) == 0)    errorPrint++;
1150         if (strncmp(argv[i], "-v++", 4) == 0)   errorPrint++;
1151         if (strncmp(argv[i], "-verbose", 2) == 0) {
1152             debugPrint = 1;
1153         } else if (!strcmp(argv[i], "-V")) {
1154             fprintf (stdout, "%s\n", V_libdyninstAPI);
1155             if (libRTname[0]) 
1156                 fprintf (stdout, "DYNINSTAPI_RT_LIB=%s\n", libRTname);
1157             fflush(stdout);
1158         } else if (!strcmp(argv[i], "-attach")) {
1159             useAttach = true;
1160         } else if (!strcmp(argv[i], "-skip")) {
1161             unsigned int j;
1162             runAllTests = false;
1163             for (j=i+1; j < argc; j++) {
1164                 unsigned int testId;
1165                 if ((testId = atoi(argv[j]))) {
1166                     if ((testId > 0) && (testId <= MAX_TEST)) {
1167                         runTest[testId] = false;
1168                     } else {
1169                         printf("invalid test %d requested\n", testId);
1170                         exit(-1);
1171                     }
1172                 } else {
1173                     // end of test list
1174                     break;
1175                 }
1176             }
1177             i=j-1;
1178         } else if (!strcmp(argv[i], "-run")) {
1179             unsigned int j;
1180             runAllTests = false;
1181             for (j=0; j <= MAX_TEST; j++) runTest[j] = false;
1182             for (j=i+1; j < argc; j++) {
1183                 unsigned int testId;
1184                 if ((testId = atoi(argv[j]))) {
1185                     if ((testId > 0) && (testId <= MAX_TEST)) {
1186                         runTest[testId] = true;
1187                     } else {
1188                         printf("invalid test %d requested\n", testId);
1189                         exit(-1);
1190                     }
1191                 } else {
1192                     // end of test list
1193                     break;
1194                 }
1195             }
1196             i=j-1;
1197         } else if (!strcmp(argv[i], "-mutatee")) {
1198             i++;
1199             if (*argv[i]=='_')
1200                 strcat(mutateeName,argv[i]);
1201             else
1202                 strcpy(mutateeName,argv[i]);
1203 #if defined(i386_unknown_nt4_0) || defined(i386_unknown_linux2_0) || defined(sparc_sun_solaris2_4)
1204         } else if (!strcmp(argv[i], "-relocate")) {
1205             forceRelocation = true;
1206 #endif
1207 #if defined(mips_sgi_irix6_4)
1208         } else if (!strcmp(argv[i], "-n32")) {
1209             N32ABI = true;
1210 #endif
1211         } else {
1212             fprintf(stderr, "Usage: test5 "
1213                     "[-V] [-verbose] [-attach] "
1214 #if defined(mips_sgi_irix6_4)
1215                     "[-n32] "
1216 #endif
1217                     "[-mutatee <test5.mutatee>] "
1218                     "[-run <test#> <test#> ...] "
1219                     "[-skip <test#> <test#> ...]\n");
1220             fprintf(stderr, "%d subtests\n", MAX_TEST);
1221             exit(-1);
1222         }
1223     }
1224
1225     if (!runAllTests) {
1226         printf("Running Tests: ");
1227         for (unsigned int j=1; j <= MAX_TEST; j++) {
1228             if (runTest[j]) printf("%d ", j);
1229         }
1230         printf("\n");
1231     }
1232
1233     // patch up the default compiler in mutatee name (if necessary)
1234     if (!strstr(mutateeName, "_"))
1235 #if defined(i386_unknown_nt4_0)
1236         strcat(mutateeName,"_VC++");
1237 #else
1238         strcat(mutateeName,"_g++");
1239 #endif
1240     if (N32ABI || strstr(mutateeName,"_n32")) {
1241         // patch up file names based on alternate ABI (as necessary)
1242         if (!strstr(mutateeName, "_n32")) strcat(mutateeName,"_n32");
1243     }
1244     // patch up the platform-specific filename extensions
1245 #if defined(i386_unknown_nt4_0)
1246     if (!strstr(mutateeName, ".exe")) strcat(mutateeName,".exe");
1247 #endif
1248     
1249     int exitCode = mutatorMAIN(mutateeName, useAttach);
1250
1251     return exitCode;
1252 }