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