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