Added BPatch_retExpr test case
[dyninst.git] / dyninstAPI / tests / src / test1.C
1
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 test1.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 <signal.h>
20
21 #include "BPatch.h"
22 #include "BPatch_Vector.h"
23 #include "BPatch_thread.h"
24 #include "BPatch_snippet.h"
25
26 int debugPrint = 0;
27
28 BPatch *bpatch;
29
30 // control debug printf statements
31 #define dprintf if (debugPrint) printf
32
33 /**************************************************************************
34  * Utility functions
35  **************************************************************************/
36
37 // check that the cost of a snippet is sane.  Due to differences between
38 //   platforms, it is impossible to check this exactly in a machine independent
39 //   manner.
40 void checkCost(BPatch_snippet snippet)
41 {
42     float cost;
43     BPatch_snippet copy;
44
45     // test copy constructor too.
46     copy = snippet;
47
48     cost = snippet.getCost();
49     if (cost < 0.0) {
50         printf("*Error*: negative snippet cost\n");
51     } else if (cost == 0.0) {
52         printf("*Warning*: zero snippet cost\n");
53     } else if (cost > 0.01) {
54         printf("*Error*: snippet cost of %f, exceeds max expected of 0.1",
55             cost);
56     }
57 }
58
59 //
60 // Replace all calls in "inFunction" to "callTo" with calls to "replacement."
61 // If "replacement" is NULL, them use removeFunctionCall instead of
62 // replaceFunctionCall.
63 // Returns the number of replacements that were performed.
64 //
65 int replaceFunctionCalls(BPatch_thread *appThread, BPatch_image *appImage,
66                          char *inFunction, char *callTo, char *replacement,
67                          int testNo, char *testName,
68                          int callsExpected = -1)
69 {
70     int numReplaced = 0;
71
72     BPatch_Vector<BPatch_point *> *points =
73         appImage->findProcedurePoint(inFunction, BPatch_subroutine);
74     if (!points) {
75         fprintf(stderr, "**Failed** test #%d (%s)\n", testNo, testName);
76         fprintf(stderr, "    Unable to find point %s - subroutine calls\n",
77                 inFunction);
78         exit(1);
79     }
80
81     BPatch_function *call_replacement;
82     if (replacement != NULL) {
83         call_replacement = appImage->findFunction(replacement);
84         if (call_replacement == NULL) {
85             fprintf(stderr, "**Failed** test #%d (%s)\n", testNo, testName);
86             fprintf(stderr, "    Unable to find function %s\n", replacement);
87             exit(1);
88         }
89     }
90
91     for (int n = 0; n < points->size(); n++) {
92         BPatch_function *func;
93         if ((func = (*points)[n]->getCalledFunction()) == NULL) {
94             fprintf(stderr, "**Failed** test #%d (%s)\n", testNo, testName);
95             fprintf(stderr, "    Can't get called function in %s\n",
96                     inFunction);
97             exit(1);
98         }
99         char fn[256];
100         if (func->getName(fn, 256) == NULL) {
101             fprintf(stderr, "**Failed** test #%d (%s)\n", testNo, testName);
102             fprintf(stderr, "    Can't get name of called function in %s\n",
103                     inFunction);
104             exit(1);
105         }
106         if (strcmp(fn, callTo) == 0) {
107             if (replacement == NULL)
108                 appThread->removeFunctionCall(*((*points)[n]));
109             else
110                 appThread->replaceFunctionCall(*((*points)[n]),
111                                                *call_replacement);
112             numReplaced++;
113         }
114     }
115
116     if (callsExpected > 0 && callsExpected != numReplaced) {
117         fprintf(stderr, "**Failed** test #%d (%s)\n", testNo, testName);
118         fprintf(stderr, "    Expected to find %d %s to %s in %s, found %d\n",
119                 callsExpected, callsExpected == 1 ? "call" : "calls",
120                 callTo, inFunction, numReplaced);
121         exit(1);
122     }
123
124
125     return numReplaced;
126 }
127
128
129 //
130 // Return a pointer to a string identifying a BPatch_procedureLocation
131 //
132 char *locationName(BPatch_procedureLocation l)
133 {
134     switch(l) {
135       case BPatch_entry:
136         return "entry";
137       case BPatch_exit:
138         return "exit";
139       case BPatch_subroutine:
140         return "call points";
141       case BPatch_longJump:
142         return "long jump";
143       case BPatch_allLocations:
144         return "all";
145       default:
146         return "<invalid BPatch_procedureLocation>";
147     };
148 }
149
150
151 //
152 // Insert "snippet" at the location "loc" in the function "inFunction."
153 // Returns the value returned by BPatch_thread::insertSnippet.
154 //
155 BPatchSnippetHandle *insertSnippetAt(BPatch_thread *appThread,
156         BPatch_image *appImage, char *inFunction, BPatch_procedureLocation loc,
157         BPatch_snippet &snippet, int testNo, char *testName)
158 {
159     // Find the point(s) we'll be instrumenting
160     BPatch_Vector<BPatch_point *> *points =
161         appImage->findProcedurePoint(inFunction, loc);
162
163     if (!points) {
164         fprintf(stderr, "**Failed** test #%d (%s)\n", testNo, testName);
165         fprintf(stderr, "    Unable to find point %s - %s\n",
166                 inFunction, locationName(loc));
167         exit(-1);
168     }
169
170     checkCost(snippet);
171     return appThread->insertSnippet(snippet, *points);
172 }
173
174 //
175 // Create a snippet that calls the function "funcName" with no arguments
176 //
177 BPatch_snippet *makeCallSnippet(BPatch_image *appImage, char *funcName,
178                                 int testNo, char *testName)
179 {
180     BPatch_function *call_func = appImage->findFunction(funcName);
181     if (call_func == NULL) {
182         fprintf(stderr, "**Failed** test #%d (%s)\n", testNo, testName);
183         fprintf(stderr, "    Unable to find function %s\n", funcName);
184         exit(1);
185     }
186
187     BPatch_Vector<BPatch_snippet *> nullArgs;
188     BPatch_snippet *ret = new BPatch_funcCallExpr(*call_func, nullArgs);
189
190     if (ret == NULL) {
191         fprintf(stderr, "**Failed** test #%d (%s)\n", testNo, testName);
192         fprintf(stderr, "    Unable to create snippet to call %s\n", funcName);
193         exit(1);
194     }
195
196     return ret;
197 }
198
199 //
200 // Insert a snippet to call function "funcName" with no arguments into the
201 // procedure "inFunction" at the points given by "loc."
202 //
203 BPatchSnippetHandle *insertCallSnippetAt(BPatch_thread *appThread,
204         BPatch_image *appImage, char *inFunction, BPatch_procedureLocation loc,
205         char *funcName, int testNo, char *testName)
206 {
207     BPatch_snippet *call_expr =
208         makeCallSnippet(appImage, funcName, testNo, testName);
209
210     BPatchSnippetHandle *ret = insertSnippetAt(appThread, appImage,
211                                                inFunction, loc, *call_expr,
212                                                testNo, testName);
213     if (ret == NULL) {
214         fprintf(stderr, "**Failed** test #%d (%s)\n", testNo, testName);
215         fprintf(stderr, "    Unable to insert snippet to call function %s\n",
216                 funcName);
217         exit(-1);
218     }
219
220     delete call_expr;
221     
222     return ret;
223 }
224
225 //
226 // Wait for the mutatee to stop.
227 //
228 void waitUntilStopped(BPatch_thread *appThread, int testnum, char *testname)
229 {
230     // Wait for process to stop
231     while (!appThread->isStopped() && !appThread->isTerminated()) ;
232     if (!appThread->isStopped()) {
233         printf("**Failed test #%d (%s)\n", testnum, testname);
234         printf("    process did not signal mutator via SIGSTOP\n");
235         exit(-1);
236     } else if (appThread->stopSignal() != SIGSTOP) {
237         printf("**Failed test #%d (%s)\n", testnum, testname);
238         printf("    process stopped on signal %d, not SIGSTOP\n", 
239                 appThread->stopSignal());
240         exit(-1);
241     }
242 }
243
244 /**************************************************************************
245  * Tests
246  **************************************************************************/
247
248 //
249 // Start Test Case #6 - mutator side (arithmetic operators)
250 //
251 void mutatorTest6(BPatch_thread *appThread, BPatch_image *appImage)
252 {
253     // Find the entry point to the procedure "func6_1"
254     BPatch_Vector<BPatch_point *> *point6_1 =
255         appImage->findProcedurePoint("func6_1", BPatch_entry);
256     BPatch_variableExpr *expr6_1 = appImage->findVariable("globalVariable6_1");
257     BPatch_variableExpr *expr6_2 = appImage->findVariable("globalVariable6_2");
258     BPatch_variableExpr *expr6_3 = appImage->findVariable("globalVariable6_3");
259     BPatch_variableExpr *expr6_4 = appImage->findVariable("globalVariable6_4");
260     BPatch_variableExpr *expr6_5 = appImage->findVariable("globalVariable6_5");
261     BPatch_variableExpr *expr6_6 = appImage->findVariable("globalVariable6_6");
262     if (!expr6_1 || !expr6_2 || !expr6_3 || !expr6_4 || 
263         !expr6_5 || !expr6_6) {
264         fprintf(stderr, "**Failed** test #6 (arithmetic operators)\n");
265         fprintf(stderr, "    Unable to locate one of globalVariable6_?\n");
266         exit(1);
267     }
268
269     BPatch_Vector<BPatch_snippet*> vect6_1;
270
271     // globalVariable6_1 = 60 + 2
272     BPatch_arithExpr arith6_1 (BPatch_assign, *expr6_1, 
273       BPatch_arithExpr(BPatch_plus,BPatch_constExpr(60), BPatch_constExpr(2)));
274     vect6_1.push_back(&arith6_1);
275
276     // globalVariable6_2 = 64 - 1
277     BPatch_arithExpr arith6_2 (BPatch_assign, *expr6_2, 
278       BPatch_arithExpr(BPatch_minus,BPatch_constExpr(64),BPatch_constExpr(1)));
279     vect6_1.push_back(&arith6_2);
280
281     // globalVariable6_3 = 66 / 3
282     BPatch_arithExpr arith6_3 (BPatch_assign, *expr6_3, BPatch_arithExpr(
283       BPatch_divide,BPatch_constExpr(66),BPatch_constExpr(3)));
284     vect6_1.push_back(&arith6_3);
285
286     // globalVariable6_4 = 67 / 3
287     BPatch_arithExpr arith6_4 (BPatch_assign, *expr6_4, BPatch_arithExpr(
288       BPatch_divide,BPatch_constExpr(67),BPatch_constExpr(3)));
289     vect6_1.push_back(&arith6_4);
290
291     // globalVariable6_5 = 6 * 5
292     BPatch_arithExpr arith6_5 (BPatch_assign, *expr6_5, BPatch_arithExpr(
293       BPatch_times,BPatch_constExpr(6),BPatch_constExpr(5)));
294     vect6_1.push_back(&arith6_5);
295
296     // globalVariable6_6 = 10,3
297     BPatch_arithExpr arith6_6 (BPatch_assign, *expr6_6, 
298         BPatch_arithExpr(BPatch_seq,BPatch_constExpr(10),BPatch_constExpr(3)));
299     vect6_1.push_back(&arith6_6);
300
301     checkCost(BPatch_sequence(vect6_1));
302     appThread->insertSnippet( BPatch_sequence(vect6_1), *point6_1);
303 }
304
305 void genRelTest(BPatch_image *appImage,BPatch_Vector<BPatch_snippet*> &vect7_1, 
306                 BPatch_relOp op, int r1, int r2, char *var1)
307 {
308     BPatch_variableExpr *varExpr1 = appImage->findVariable(var1);
309     if (!varExpr1) {
310         fprintf(stderr, "**Failed** test #7 (relational operators)\n");
311         fprintf(stderr, "    Unable to locate variable %s\n", var1);
312         exit(1);
313     }
314     BPatch_ifExpr *tempExpr1 = new BPatch_ifExpr(
315         BPatch_boolExpr(op, BPatch_constExpr(r1), BPatch_constExpr(r2)), 
316         BPatch_arithExpr(BPatch_assign, *varExpr1, BPatch_constExpr(72)));
317     vect7_1.push_back(tempExpr1);
318
319 }
320
321 //
322 // Start Test Case #7 - mutator side (relational operators)
323 //
324 void mutatorTest7(BPatch_thread *appThread, BPatch_image *appImage)
325 {
326     // Find the entry point to the procedure "func7_1"
327     BPatch_Vector<BPatch_point *> *point7_1 =
328         appImage->findProcedurePoint("func7_1", BPatch_entry);
329     BPatch_Vector<BPatch_snippet*> vect7_1;
330
331     genRelTest(appImage, vect7_1, BPatch_lt, 0, 1, "globalVariable7_1");
332     genRelTest(appImage, vect7_1, BPatch_lt, 1, 0, "globalVariable7_2");
333     genRelTest(appImage, vect7_1, BPatch_eq, 2, 2, "globalVariable7_3");
334     genRelTest(appImage, vect7_1, BPatch_eq, 2, 3, "globalVariable7_4");
335     genRelTest(appImage, vect7_1, BPatch_gt, 4, 3, "globalVariable7_5");
336     genRelTest(appImage, vect7_1, BPatch_gt, 3, 4, "globalVariable7_6");
337     genRelTest(appImage, vect7_1, BPatch_le, 3, 4, "globalVariable7_7");
338     genRelTest(appImage, vect7_1, BPatch_le, 4, 3, "globalVariable7_8");
339     genRelTest(appImage, vect7_1, BPatch_ne, 5, 6, "globalVariable7_9");
340     genRelTest(appImage, vect7_1, BPatch_ne, 5, 5, "globalVariable7_10");
341     genRelTest(appImage, vect7_1, BPatch_ge, 9, 7, "globalVariable7_11");
342     genRelTest(appImage, vect7_1, BPatch_ge, 7, 9, "globalVariable7_12");
343     genRelTest(appImage, vect7_1, BPatch_and, 1, 1, "globalVariable7_13");
344     genRelTest(appImage, vect7_1, BPatch_and, 1, 0, "globalVariable7_14");
345     genRelTest(appImage, vect7_1, BPatch_or, 1, 0, "globalVariable7_15");
346     genRelTest(appImage, vect7_1, BPatch_or, 0, 0, "globalVariable7_16");
347
348     dprintf("relops test vector length is %d\n", vect7_1.size());
349
350     checkCost(BPatch_sequence(vect7_1));
351     appThread->insertSnippet( BPatch_sequence(vect7_1), *point7_1);
352 }
353
354 //
355 // Start Test Case #8 - mutator side (preserve registers - expr)
356 //
357 void mutatorTest8(BPatch_thread *appThread, BPatch_image *appImage)
358 {
359     // Find the entry point to the procedure "func8_1"
360     BPatch_Vector<BPatch_point *> *point8_1 =
361         appImage->findProcedurePoint("func8_1", BPatch_entry);
362     BPatch_Vector<BPatch_snippet*> vect8_1;
363
364     BPatch_variableExpr *expr8_1 = appImage->findVariable("globalVariable8_1");
365     if (!expr8_1) {
366         fprintf(stderr, "**Failed** test #3 (passing variables)\n");
367         fprintf(stderr, "    Unable to locate variable globalVariable8_1\n");
368         exit(1);
369     }
370
371     BPatch_arithExpr arith8_1 (BPatch_assign, *expr8_1, 
372       BPatch_arithExpr(BPatch_plus, 
373             BPatch_arithExpr(BPatch_plus, 
374                 BPatch_arithExpr(BPatch_plus, BPatch_constExpr(81), 
375                                               BPatch_constExpr(82)),
376                 BPatch_arithExpr(BPatch_plus, BPatch_constExpr(83), 
377                                               BPatch_constExpr(84))),
378             BPatch_arithExpr(BPatch_plus, 
379                 BPatch_arithExpr(BPatch_plus, BPatch_constExpr(85), 
380                                               BPatch_constExpr(86)),
381                 BPatch_arithExpr(BPatch_plus, BPatch_constExpr(87), 
382                                               BPatch_constExpr(88)))));
383     vect8_1.push_back(&arith8_1);
384
385     checkCost(BPatch_sequence(vect8_1));
386     appThread->insertSnippet( BPatch_sequence(vect8_1), *point8_1);
387 }
388
389 //
390 // Start Test Case #9 - mutator side (preserve registers - funcCall)
391 //
392 void mutatorTest9(BPatch_thread *appThread, BPatch_image *appImage)
393 {
394     // Find the entry point to the procedure "func9_1"
395     BPatch_Vector<BPatch_point *> *point9_1 =
396         appImage->findProcedurePoint("func9_1", BPatch_entry);
397
398     BPatch_function *call9_func = appImage->findFunction("call9_1");
399     if (call9_func == NULL) {
400         fprintf(stderr, "Unable to find function \"call9_1.\"\n");
401         exit(1);
402     }
403
404     BPatch_Vector<BPatch_snippet *> call9_args;
405
406     BPatch_constExpr constExpr91(91);
407     call9_args.push_back(&constExpr91);
408
409     BPatch_constExpr constExpr92(92);
410     call9_args.push_back(&constExpr92);
411
412     BPatch_constExpr constExpr93(93);
413     call9_args.push_back(&constExpr93);
414
415     BPatch_constExpr constExpr94(94);
416     call9_args.push_back(&constExpr94);
417
418     BPatch_constExpr constExpr95(95);
419     call9_args.push_back(&constExpr95);
420
421     BPatch_funcCallExpr call9Expr(*call9_func, call9_args);
422
423     checkCost(call9Expr);
424     appThread->insertSnippet( call9Expr, *point9_1);
425 }
426
427
428 //
429 // Start Test Case #10 - mutator side (insert snippet order)
430 //
431 void mutatorTest10(BPatch_thread *appThread, BPatch_image *appImage)
432 {
433     // Find the entry point to the procedure "func10_1"
434     BPatch_Vector<BPatch_point *> *point10_1 =
435         appImage->findProcedurePoint("func10_1", BPatch_entry);
436
437     BPatch_function *call10_1_func = appImage->findFunction("call10_1");
438     if (call10_1_func == NULL) {
439         fprintf(stderr, "Unable to find function \"call10_1.\"\n");
440         exit(1);
441     }
442
443     BPatch_function *call10_2_func = appImage->findFunction("call10_2");
444     if (call10_2_func == NULL) {
445         fprintf(stderr, "Unable to find function \"call10_2.\"\n");
446         exit(1);
447     }
448
449     BPatch_function *call10_3_func = appImage->findFunction("call10_3");
450     if (call10_3_func == NULL) {
451         fprintf(stderr, "Unable to find function \"call10_3.\"\n");
452         exit(1);
453     }
454
455     BPatch_Vector<BPatch_snippet *> nullArgs;
456     BPatch_funcCallExpr call10_1Expr(*call10_1_func, nullArgs);
457     BPatch_funcCallExpr call10_2Expr(*call10_2_func, nullArgs);
458     BPatch_funcCallExpr call10_3Expr(*call10_3_func, nullArgs);
459
460     checkCost(call10_2Expr);
461     appThread->insertSnippet( call10_2Expr, *point10_1);
462
463     checkCost(call10_1Expr);
464     appThread->insertSnippet( call10_1Expr, *point10_1, BPatch_callBefore, 
465                                                         BPatch_firstSnippet);
466
467     checkCost(call10_3Expr);
468     appThread->insertSnippet( call10_3Expr, *point10_1, BPatch_callBefore, 
469                                                         BPatch_lastSnippet);
470 }
471
472
473 //
474 // Start Test Case #11 - mutator side (snippets at entry,exit,call)
475 //
476 void mutatorTest11(BPatch_thread *appThread, BPatch_image *appImage)
477 {
478     // Find the entry point to the procedure "func11_1"
479     BPatch_Vector<BPatch_point *> *point11_1 =
480         appImage->findProcedurePoint("func11_1", BPatch_entry);
481     if (!point11_1) {
482         fprintf(stderr, "Unable to find point func11_1 - entry.\n");
483         exit(-1);
484     }
485
486     // Find the subroutine points for the procedure "func11_1"
487     BPatch_Vector<BPatch_point *> *point11_2 =
488         appImage->findProcedurePoint("func11_1", BPatch_subroutine);
489     if (!point11_2) {
490         fprintf(stderr, "Unable to find point func11_1 - calls.\n");
491         exit(-1);
492     }
493
494     // Find the exit point to the procedure "func11_1"
495     BPatch_Vector<BPatch_point *> *point11_3 =
496         appImage->findProcedurePoint("func11_1", BPatch_exit);
497     if (!point11_3) {
498         fprintf(stderr, "Unable to find point func11_1 - exit.\n");
499         exit(-1);
500     }
501
502     BPatch_function *call11_1_func = appImage->findFunction("call11_1");
503     if (call11_1_func == NULL) {
504         fprintf(stderr, "Unable to find function \"call11_1.\"\n");
505         exit(1);
506     }
507
508     BPatch_function *call11_2_func = appImage->findFunction("call11_2");
509     if (call11_2_func == NULL) {
510         fprintf(stderr, "Unable to find function \"call11_2.\"\n");
511         exit(1);
512     }
513
514     BPatch_function *call11_3_func = appImage->findFunction("call11_3");
515     if (call11_3_func == NULL) {
516         fprintf(stderr, "Unable to find function \"call11_3.\"\n");
517         exit(1);
518     }
519
520     BPatch_function *call11_4_func = appImage->findFunction("call11_4");
521     if (call11_4_func == NULL) {
522         fprintf(stderr, "Unable to find function \"call11_4.\"\n");
523         exit(1);
524     }
525
526     BPatch_Vector<BPatch_snippet *> nullArgs;
527     BPatch_funcCallExpr call11_1Expr(*call11_1_func, nullArgs);
528     BPatch_funcCallExpr call11_2Expr(*call11_2_func, nullArgs);
529     BPatch_funcCallExpr call11_3Expr(*call11_3_func, nullArgs);
530     BPatch_funcCallExpr call11_4Expr(*call11_4_func, nullArgs);
531
532     checkCost(call11_1Expr);
533     appThread->insertSnippet(call11_1Expr, *point11_1);
534
535     checkCost(call11_2Expr);
536     appThread->insertSnippet(call11_2Expr, *point11_2, BPatch_callBefore);
537
538     checkCost(call11_3Expr);
539     appThread->insertSnippet(call11_3Expr, *point11_2, BPatch_callAfter);
540
541     checkCost(call11_4Expr);
542     appThread->insertSnippet(call11_4Expr, *point11_3);
543 }
544
545 BPatchSnippetHandle *snippetHandle12_1;
546 BPatch_variableExpr *varExpr12_1;
547
548 //
549 // Start Test Case #12 - mutator side (insert/remove and malloc/free)
550 //
551 void mutatorTest12a(BPatch_thread *appThread, BPatch_image *appImage)
552 {
553     // Find the entry point to the procedure "func12_2"
554     BPatch_Vector<BPatch_point *> *point12_2 =
555         appImage->findProcedurePoint("func12_2", BPatch_entry);
556     if (!point12_2) {
557         fprintf(stderr, "Unable to find point func12_2 - entry.\n");
558         exit(-1);
559     }
560
561     varExpr12_1 = appThread->malloc(100);
562     if (!varExpr12_1) {
563         fprintf(stderr, "Unable to allocate 100 bytes in mutatee\n");
564         exit(-1);
565     }
566
567     BPatch_function *call12_1_func = appImage->findFunction("call12_1");
568     if (call12_1_func == NULL) {
569         fprintf(stderr, "Unable to find function \"call12_1.\"\n");
570         exit(1);
571     }
572
573     BPatch_Vector<BPatch_snippet *> nullArgs;
574     BPatch_funcCallExpr call12_1Expr(*call12_1_func, nullArgs);
575
576     checkCost(call12_1Expr);
577     snippetHandle12_1 = appThread->insertSnippet(call12_1Expr, *point12_2);
578     if (!snippetHandle12_1) {
579         fprintf(stderr,
580                 "Unable to insert snippet to call function \"call12_1.\"\n");
581         exit(-1);
582     }
583 }
584
585 void mutatorTest12b(BPatch_thread *appThread, BPatch_image */*appImage*/)
586 {
587     while (!appThread->isStopped() && !appThread->isTerminated()) ;
588     if (appThread->stopSignal() == SIGSTOP) {
589         // remove instrumentation and free memory
590         if (!appThread->deleteSnippet(snippetHandle12_1)) {
591             printf("**Failed test #12 (insert/remove and malloc/free)\n");
592             printf("    deleteSnippet returned an error\n");
593             exit(-1);
594         }
595         appThread->free(*varExpr12_1);
596
597         // continue process
598         appThread->continueExecution();
599     } else if (appThread->isStopped()) {
600         printf("**Failed test #12 (insert/remove and malloc/free)\n");
601         printf("    process stopped on signal %d, not SIGSTOP\n", 
602                 appThread->stopSignal());
603         exit(-1);
604     } else {
605         printf("**Failed test #12 (insert/remove and malloc/free)\n");
606         printf("    process did not signal mutator via SIGSTOP\n");
607         exit(-1);
608     }
609 }
610
611
612 //
613 // Start Test Case #13 - mutator side (paramExpr,retExpr,nullExpr)
614 //
615 void mutatorTest13(BPatch_thread *appThread, BPatch_image *appImage)
616 {
617     // Find the entry point to the procedure "func13_1"
618     BPatch_Vector<BPatch_point *> *point13_1 =
619         appImage->findProcedurePoint("func13_1", BPatch_entry);
620     if (!point13_1) {
621         fprintf(stderr, "Unable to find point func13_1 - entry.\n");
622         exit(-1);
623     }
624
625     BPatch_function *call13_1_func = appImage->findFunction("call13_1");
626     if (call13_1_func == NULL) {
627         fprintf(stderr, "Unable to find function \"call13_1.\"\n");
628         exit(1);
629     }
630
631     BPatch_Vector<BPatch_snippet *> funcArgs;
632     funcArgs.push_back(new BPatch_paramExpr(0));
633     funcArgs.push_back(new BPatch_paramExpr(1));
634     funcArgs.push_back(new BPatch_paramExpr(2));
635     funcArgs.push_back(new BPatch_paramExpr(3));
636     funcArgs.push_back(new BPatch_paramExpr(4));
637     BPatch_funcCallExpr call13_1Expr(*call13_1_func, funcArgs);
638
639     checkCost(call13_1Expr);
640     appThread->insertSnippet(call13_1Expr, *point13_1);
641
642     BPatch_nullExpr call13_2Expr;
643     checkCost(call13_1Expr);
644     appThread->insertSnippet(call13_2Expr, *point13_1);
645
646     // now test that a return value can be read.
647     BPatch_Vector<BPatch_point *> *point13_2 =
648         appImage->findProcedurePoint("func13_2", BPatch_exit);
649     if (!point13_2) {
650         fprintf(stderr, "Unable to find point func13_2 - exit.\n");
651         exit(-1);
652     }
653
654     BPatch_function *call13_2_func = appImage->findFunction("call13_2");
655     if (call13_2_func == NULL) {
656         fprintf(stderr, "Unable to find function \"call13_1.\"\n");
657         exit(1);
658     }
659
660     BPatch_Vector<BPatch_snippet *> funcArgs2;
661     funcArgs2.push_back(new BPatch_retExpr());
662     BPatch_funcCallExpr call13_3Expr(*call13_2_func, funcArgs2);
663
664     checkCost(call13_1Expr);
665     appThread->insertSnippet(call13_3Expr, *point13_2);
666 }
667
668
669 //
670 // Start Test Case #14 - mutator side (replace function call)
671 //
672 void mutatorTest14(BPatch_thread *appThread, BPatch_image *appImage)
673 {
674     replaceFunctionCalls(appThread, appImage,
675                          "func14_1", "func14_2", "call14_1",
676                          14, "replace/remove function call", 1);
677     replaceFunctionCalls(appThread, appImage,
678                          "func14_1", "func14_3", NULL,
679                          14, "replace/remove function call", 1);
680 }
681
682
683 //
684 // Start Test Case #15 - mutator side (setMutationsActive)
685 //
686 void mutatorTest15a(BPatch_thread *appThread, BPatch_image *appImage)
687 {
688     insertCallSnippetAt(appThread, appImage, "func15_2", BPatch_entry,
689                         "call15_1", 15, "setMutationsActive");
690
691 #if defined(sparc_sun_sunos4_1_3) || defined(sparc_sun_solaris2_4)
692     // On the Sparc, functions containing system calls are relocated into the
693     // heap when instrumented, making a special case we should check.
694
695     // "access" makes the "access" system call, so we'll instrument it
696     insertCallSnippetAt(appThread, appImage, "access", BPatch_entry,
697                         "call15_2", 15, "setMutationsActive");
698     // We want to instrument more than one point, so do exit as well
699     insertCallSnippetAt(appThread, appImage, "access", BPatch_exit,
700                         "call15_2", 15, "setMutationsActive");
701 #endif
702
703     replaceFunctionCalls(appThread, appImage, "func15_4", "func15_3",
704                          "call15_3", 15, "setMutationsActive", 1);
705 }
706
707
708 void mutatorTest15b(BPatch_thread *appThread, BPatch_image */*appImage*/)
709 {
710     waitUntilStopped(appThread, 15, "setMutationsActive");
711
712     // disable mutations and continue process
713     appThread->setMutationsActive(false);
714     appThread->continueExecution();
715     
716     waitUntilStopped(appThread, 15, "setMutationsActive");
717
718     // re-enable mutations and continue process
719     appThread->setMutationsActive(true);
720     appThread->continueExecution();
721 }
722
723
724 //
725 // Start Test Case #16 - mutator side (if-else)
726 //
727 void mutatorTest16(BPatch_thread *appThread, BPatch_image *appImage)
728 {
729     BPatch_variableExpr *expr16_1=appImage->findVariable("globalVariable16_1");
730     BPatch_variableExpr *expr16_2=appImage->findVariable("globalVariable16_2");
731     BPatch_variableExpr *expr16_3=appImage->findVariable("globalVariable16_3");
732     BPatch_variableExpr *expr16_4=appImage->findVariable("globalVariable16_4");
733     if (!expr16_1 || !expr16_2 || !expr16_3 || !expr16_4) {
734         fprintf(stderr, "**Failed** test #16 (if-else)\n");
735         fprintf(stderr, "    Unable to locate one of globalVariable16_?\n");
736         exit(1);
737     }
738
739     BPatch_arithExpr assign16_1(BPatch_assign, *expr16_1, BPatch_constExpr(1));
740     BPatch_arithExpr assign16_2(BPatch_assign, *expr16_2, BPatch_constExpr(1));
741
742     BPatch_ifExpr if16_2(BPatch_boolExpr(BPatch_eq,
743                                          BPatch_constExpr(1),
744                                          BPatch_constExpr(1)),
745                          assign16_1, assign16_2);
746
747     BPatch_arithExpr assign16_3(BPatch_assign, *expr16_3, BPatch_constExpr(1));
748     BPatch_arithExpr assign16_4(BPatch_assign, *expr16_4, BPatch_constExpr(1));
749
750     BPatch_ifExpr if16_3(BPatch_boolExpr(BPatch_eq,
751                                          BPatch_constExpr(0),
752                                          BPatch_constExpr(1)),
753                          assign16_3, assign16_4);
754
755     insertSnippetAt(appThread, appImage, "func16_2", BPatch_entry, if16_2,
756                     16, "if-else");
757     insertSnippetAt(appThread, appImage, "func16_3", BPatch_entry, if16_3,
758                     16, "if-else");
759 }
760
761 //
762 // Start Test Case #17 - mutator side (return values from func calls)
763 //
764 void mutatorTest17(BPatch_thread *appThread, BPatch_image *appImage)
765 {
766     // Find the entry point to the procedure "func17_1"
767     BPatch_Vector<BPatch_point *> *point17_1 =
768         appImage->findProcedurePoint("func17_1", BPatch_exit);
769     if (!point17_1) {
770         fprintf(stderr, "Unable to find point func17_1 - entry.\n");
771         exit(-1);
772     }
773
774     BPatch_function *call17_1_func = appImage->findFunction("call17_1");
775     if (call17_1_func == NULL) {
776         fprintf(stderr, "Unable to find function \"call17_1.\"\n");
777         exit(1);
778     }
779
780     BPatch_Vector<BPatch_snippet *> funcArgs;
781     funcArgs.push_back(new BPatch_paramExpr(1));
782     BPatch_funcCallExpr call17_1Expr(*call17_1_func, funcArgs);
783     checkCost(call17_1Expr);
784     appThread->insertSnippet(call17_1Expr, *point17_1);
785
786     // Find the entry point to the procedure "func17_2"
787     BPatch_Vector<BPatch_point *> *point17_2 =
788         appImage->findProcedurePoint("func17_2", BPatch_subroutine);
789     if (!point17_2) {
790         fprintf(stderr, "Unable to find point func17_2 - entry.\n");
791         exit(-1);
792     }
793
794     BPatch_function *call17_2_func = appImage->findFunction("call17_2");
795     if (call17_2_func == NULL) {
796         fprintf(stderr, "Unable to find function \"call17_2.\"\n");
797         exit(1);
798     }
799
800     BPatch_Vector<BPatch_snippet *> funcArgs2;
801     // funcArgs2.push_back(new BPatch_paramExpr(0));
802     BPatch_funcCallExpr call17_2Expr(*call17_2_func, funcArgs2);
803     checkCost(call17_2Expr);
804     appThread->insertSnippet(call17_2Expr, *point17_2, 
805         BPatch_callAfter, BPatch_lastSnippet);
806 }
807
808 void mutatorMAIN(char *pathname, bool useAttach)
809 {
810     BPatch_thread *appThread;
811
812     // Create an instance of the bpatch library
813     bpatch = new BPatch;
814
815     // Start the mutatee
816     printf("Starting \"%s\"\n", pathname);
817
818     char *child_argv[] = { pathname, "-verbose", NULL };
819     if (!debugPrint) {
820         // null out the verbose mode if not enabled.
821         child_argv[1] = NULL;
822     }
823
824     if (useAttach) {
825         // fork and then attach
826         int pid = fork();
827         if (pid == 0) {
828             // child - so exec 
829             execl(pathname, child_argv[0], "-attach", child_argv[1], NULL);
830             _exit(-1);
831         } else if (pid > 0) {
832             // parrent so use attach
833             appThread = new BPatch_thread(pathname, pid);
834         } else {
835             printf("*ERROR*: unable to start tests due to fork failure\n");
836         }
837     } else {
838         appThread = new BPatch_thread(pathname, child_argv, NULL);
839     }
840
841     if (appThread->isTerminated()) {
842         fprintf(stderr, "Unable to run test program.\n");
843         exit(1);
844     }
845
846     // Read the program's image and get an associated image object
847     BPatch_image *appImage = appThread->getImage();
848
849     BPatch_Vector<BPatch_module *> *m = appImage->getModules();
850     for (int i=0; i < m->size(); i++) {
851         // dprintf("func %s\n", (*m)[i]->name());
852     }
853
854     BPatch_Vector<BPatch_function *> *p = appImage->getProcedures();
855     for (int i=0; i < p->size(); i++) {
856         // dprintf("func %s\n", (*p)[i]->name());
857     }
858
859     // Start Test Case #1 - mutator side (call a zero argument function)
860
861     // Find the entry point to the procedure "func1_1"
862     BPatch_Vector<BPatch_point *> *point1_1 =
863         appImage->findProcedurePoint("func1_1", BPatch_entry);
864
865     if ((*point1_1).size() == 0) {
866         fprintf(stderr, "**Failed** test #1 (zero arg function call)\n");
867         fprintf(stderr, "    Unable to find entry point to \"func1_1.\"\n");
868         exit(1);
869     }
870
871     BPatch_function *call1_func = appImage->findFunction("call1_1");
872     if (call1_func == NULL) {
873         fprintf(stderr, "**Failed** test #1 (zero arg function call)\n");
874         fprintf(stderr, "Unable to find function \"call1_1\"\n");
875         exit(1);
876     }
877
878     BPatch_Vector<BPatch_snippet *> call1_args;
879     BPatch_funcCallExpr call1Expr(*call1_func, call1_args);
880
881     dprintf("Inserted snippet2\n");
882     checkCost(call1Expr);
883     appThread->insertSnippet(call1Expr, *point1_1);
884
885
886     //
887     // Start Test Case #2 - mutator side (call a three argument function)
888     //
889
890     // Find the entry point to the procedure "func2_1"
891     BPatch_Vector<BPatch_point *> *point2_1 =
892         appImage->findProcedurePoint("func2_1", BPatch_entry);
893
894     if (!point2_1 || ((*point2_1).size() == 0)) {
895         fprintf(stderr, "**Failed** test #2 (three parameter function)\n");
896         fprintf(stderr, "    Unable to find entry point to \"func2_1.\"\n");
897         exit(1);
898     }
899
900     BPatch_function *call2_func = appImage->findFunction("call2_1");
901     if (call2_func == NULL) {
902         fprintf(stderr, "**Failed** test #2 (three parameter function)\n");
903         fprintf(stderr, "    Unable to find function \"call2_1.\"\n");
904         exit(1);
905     }
906
907     BPatch_Vector<BPatch_snippet *> call2_args;
908     BPatch_constExpr expr2_1(1);
909     BPatch_constExpr expr2_2(2);
910     BPatch_constExpr expr2_3("testString2_1");
911     call2_args.push_back(&expr2_1);
912     call2_args.push_back(&expr2_2);
913     call2_args.push_back(&expr2_3);
914
915     BPatch_funcCallExpr call2Expr(*call2_func, call2_args);
916
917     dprintf("Inserted snippet2\n");
918     checkCost(call2Expr);
919     appThread->insertSnippet(call2Expr, *point2_1);
920
921     //
922     // Start Test Case #3 - mutator side (passing variables to function)
923     //
924
925     // Find the entry point to the procedure "func3_1"
926     BPatch_Vector<BPatch_point *> *point3_1 =
927         appImage->findProcedurePoint("func3_1", BPatch_entry);
928
929     if (!point3_1 || ((*point3_1).size() == 0)) {
930         fprintf(stderr, "Unable to find entry point to \"func3_1.\"\n");
931         exit(1);
932     }
933
934     BPatch_function *call3_func = appImage->findFunction("call3_1");
935     if (call3_func == NULL) {
936         fprintf(stderr, "Unable to find function \"call3_1.\"\n");
937         exit(1);
938     }
939
940     BPatch_Vector<BPatch_snippet *> call3_args;
941
942     BPatch_variableExpr *expr3_1 = appImage->findVariable("globalVariable3_1");
943     if (!expr3_1) {
944         fprintf(stderr, "**Failed** test #3 (passing variables)\n");
945         fprintf(stderr, "    Unable to locate variable globalVariable3_1\n");
946         exit(1);
947     }
948
949     BPatch_variableExpr *expr3_2 = appThread->malloc(*appImage->findType("int"));
950     if (!expr3_2) {
951         fprintf(stderr, "**Failed** test #3 (passing variables)\n");
952         fprintf(stderr, "    Unable to create new int variable\n");
953         exit(1);
954     }
955
956     call3_args.push_back(expr3_1);
957     call3_args.push_back(expr3_2);
958
959     BPatch_funcCallExpr call3Expr(*call3_func, call3_args);
960     checkCost(call3Expr);
961     appThread->insertSnippet(call3Expr, *point3_1);
962
963     BPatch_arithExpr expr3_3(BPatch_assign, *expr3_2, BPatch_constExpr(32));
964     checkCost(expr3_3);
965     appThread->insertSnippet(expr3_3, *point3_1);
966
967     dprintf("Inserted snippet3\n");
968
969     //
970     // Start Test Case #4 - mutator side (sequence)
971     //
972
973     // Find the entry point to the procedure "func4_1"
974     BPatch_Vector<BPatch_point *> *point4_1 =
975         appImage->findProcedurePoint("func4_1", BPatch_entry);
976
977
978     BPatch_variableExpr *expr4_1 = appImage->findVariable("globalVariable4_1");
979     if (!expr4_1) {
980         fprintf(stderr, "**Failed** test #4 (sequence)\n");
981         fprintf(stderr, "    Unable to locate variable globalVariable4_1\n");
982         exit(1);
983     }
984
985     BPatch_arithExpr expr4_2(BPatch_assign, *expr4_1, BPatch_constExpr(42));
986     BPatch_arithExpr expr4_3(BPatch_assign, *expr4_1, BPatch_constExpr(43));
987
988     BPatch_Vector<BPatch_snippet*> vect4_1;
989     vect4_1.push_back(&expr4_2);
990     vect4_1.push_back(&expr4_3);
991
992     BPatch_sequence expr4_4(vect4_1);
993     checkCost(expr4_4);
994     appThread->insertSnippet(expr4_4, *point4_1);
995
996     //
997     // Start Test Case #5 - mutator side (if w.o. else)
998     //
999
1000     // Find the entry point to the procedure "func5_1"
1001     BPatch_Vector<BPatch_point *> *point5_1 =
1002         appImage->findProcedurePoint("func5_1", BPatch_entry);
1003     BPatch_variableExpr *expr5_1 = appImage->findVariable("globalVariable5_1");
1004     BPatch_variableExpr *expr5_2 = appImage->findVariable("globalVariable5_2");
1005     if (!expr5_1 || !expr5_2) {
1006         fprintf(stderr, "**Failed** test #5 (1f w.o. else)\n");
1007         fprintf(stderr, "    Unable to locate variable globalVariable5_1 or ");
1008         fprintf(stderr, "    variable globalVariable5_2\n");
1009         exit(1);
1010     }
1011
1012     BPatch_Vector<BPatch_snippet*> vect5_1;
1013
1014     // if (0 == 1) globalVariable5_1 = 52;
1015     BPatch_ifExpr expr5_3(
1016         BPatch_boolExpr(BPatch_eq, BPatch_constExpr(0), BPatch_constExpr(1)), 
1017         BPatch_arithExpr(BPatch_assign, *expr5_1, BPatch_constExpr(52)));
1018
1019     // if (1 == 1) globalVariable5_2 = 53;
1020     BPatch_ifExpr expr5_4(
1021         BPatch_boolExpr(BPatch_eq, BPatch_constExpr(1), BPatch_constExpr(1)), 
1022         BPatch_arithExpr(BPatch_assign, *expr5_2, BPatch_constExpr(53)));
1023
1024     vect5_1.push_back(&expr5_3);
1025     vect5_1.push_back(&expr5_4);
1026
1027     BPatch_sequence expr5_5(vect5_1);
1028     checkCost(expr5_5);
1029     appThread->insertSnippet(expr5_5, *point5_1);
1030
1031     mutatorTest6(appThread, appImage);
1032
1033     mutatorTest7(appThread, appImage);
1034
1035     mutatorTest8(appThread, appImage);
1036
1037     mutatorTest9(appThread, appImage);
1038
1039     mutatorTest10(appThread, appImage);
1040
1041     mutatorTest11(appThread, appImage);
1042
1043     mutatorTest12a(appThread, appImage);
1044
1045     mutatorTest13(appThread, appImage);
1046
1047     mutatorTest14(appThread, appImage);
1048
1049     mutatorTest15a(appThread, appImage);
1050
1051     mutatorTest16(appThread, appImage);
1052
1053     mutatorTest17(appThread, appImage);
1054
1055     // Start of code to continue the process.
1056     dprintf("starting program execution.\n");
1057     appThread->continueExecution();
1058
1059     mutatorTest12b(appThread, appImage);
1060
1061     mutatorTest15b(appThread, appImage);
1062
1063     while (!appThread->isTerminated()) ;
1064     dprintf("Done.\n");
1065 }
1066
1067 //
1068 // main - decide our role and call the correct "main"
1069 //
1070 main(int argc, char *argv[])
1071 {
1072     bool useAttach = false;
1073
1074     for (int i=1; i < argc; i++) {
1075         if (!strcmp(argv[i], "-verbose")) {
1076             debugPrint = 1;
1077         } else if (!strcmp(argv[i], "-attach")) {
1078             useAttach = true;
1079         } else {
1080             fprintf(stderr, "Usage: test1 [-attach] [-verbose]\n");
1081             exit(-1);
1082         }
1083     }
1084         
1085     mutatorMAIN("./test1.mutatee", useAttach);
1086
1087     return 0;
1088 }