This is an intermediary commit, not the final version of dyner.
[dyninst.git] / dyner / src / dyner.C
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include "tcl.h"
4 #include "dynerList.h"
5 #include "BPatch.h"
6 #include "BPatch_type.h"
7 #include "BPatch_collections.h"
8 #include "BPatch_Vector.h"
9 #include "BPatch_thread.h"
10 #include "BPatch_snippet.h"
11 #include "breakpoint.h"
12
13 extern "C" {
14         int usleep(useconds_t);
15
16         void set_lex_input(char *s);
17         int dynerparse();
18 }
19
20 extern "C" int dynerdebug;
21
22 int debugPrint = 0;
23 BPatch_point *targetPoint;
24 bool errorLoggingOff = false;
25
26 // control debug printf statements
27 #define dprintf if (debugPrint) printf
28
29 class ListElem {
30 public:
31     int                      number;
32     char                     *function;
33     BPatch_procedureLocation where;
34     BPatch_callWhen          when;
35     BPatchSnippetHandle      *handle;
36 };
37
38 class BPListElem: public ListElem {
39 public:
40     char                     *condition;
41     int                      lineNum;
42
43     BPListElem(int _number, char *_function, BPatch_procedureLocation _where,
44                BPatch_callWhen _when, char *_condition,
45                BPatchSnippetHandle *_handle, int _lineNum);
46     ~BPListElem();
47     void Print();
48 };
49
50 class runtimeVar {
51 public:
52     runtimeVar(BPatch_variableExpr *v, char *n) { var = v, name = strdup(n); }
53     BPatch_variableExpr *var;
54     char *name;
55     bool readValue(void *buf) { return var->readValue(buf); }
56 };
57
58 class IPListElem: public ListElem {
59 public:
60     char                     *statement;
61     bool                     trace;
62
63     IPListElem(int _number, char *_function, BPatch_procedureLocation _where,
64                BPatch_callWhen _when, char *_condition,
65                BPatchSnippetHandle *_handle, bool forTrace);
66     ~IPListElem();
67 };
68
69 BPatch bpatch;
70 BPatch_thread *appThread = NULL;
71 BPatch_image *appImage = NULL;
72 static BPatch_variableExpr *bpNumber = NULL;
73 static int bpCtr = 1;
74 static int ipCtr = 1;
75 static DynerList<BPListElem *> bplist;
76 static DynerList<IPListElem *> iplist;
77 static DynerList<runtimeVar *> varList;
78
79
80 bool name2loc(char *s, BPatch_procedureLocation &where,
81               BPatch_callWhen &when)
82 {
83     if (!strcmp(s, "entry")) {
84         where = BPatch_entry;
85         when = BPatch_callBefore;
86     } else if (!strcmp(s, "exit")) {
87         where = BPatch_exit;
88         /* This is not supported anymore!
89         when = BPatch_callBefore;
90         */
91         when = BPatch_callAfter;
92     } else if (!strcmp(s, "preCall")) {
93         where = BPatch_subroutine;
94         when = BPatch_callBefore;
95     } else if (!strcmp(s, "postCall")) {
96         where = BPatch_subroutine;
97         when = BPatch_callAfter;
98     } else {
99         return false;
100     }
101     return true;
102 }
103
104 char *loc2name(BPatch_procedureLocation where, BPatch_callWhen when)
105 {
106     switch (where) {
107       case BPatch_entry:
108         return "entry";
109       case BPatch_exit:
110         return "exit";
111       case BPatch_subroutine:
112         if (when == BPatch_callBefore) return "preCall";
113         else return "postCall";
114       default:
115         return "<error>";
116     };
117 }
118
119 BPListElem::BPListElem(int _number, char *_function,
120     BPatch_procedureLocation _where, BPatch_callWhen _when, char *_condition,
121     BPatchSnippetHandle *_handle, int _lineNum)
122 {
123     number = _number;
124     function = strdup(_function);
125     where = _where;
126     when = _when;
127     if (_condition)
128         condition = strdup(_condition);
129     else
130         condition = NULL;
131     handle = _handle;
132     lineNum = _lineNum;
133 }
134
135 BPListElem::~BPListElem()
136 {
137     free(function);
138     if (condition) free(condition);
139 }
140
141 void BPListElem::Print()
142 {
143     printf("%2d: ", number);
144     if (lineNum) 
145         printf("%s:%d", function, lineNum);
146     else
147         printf("%s (%s)", function,
148                 loc2name(where, when));
149
150     if (condition)
151         printf(", condition %s\n", condition);
152     else
153         printf("\n");
154 }
155
156 IPListElem::IPListElem(int _number, char *_function,
157     BPatch_procedureLocation _where, BPatch_callWhen _when, char *_statement,
158     BPatchSnippetHandle *_handle, bool _trace)
159 {
160     number = _number;
161     function = strdup(_function);
162     where = _where;
163     when = _when;
164     statement = strdup(_statement);
165     handle = _handle;
166     trace = _trace;
167 }
168
169 IPListElem::~IPListElem()
170 {
171     free(function);
172     free(statement);
173     if (handle) {
174         if (appThread)
175                 appThread->deleteSnippet(handle);
176
177         delete handle;
178     }
179 }
180
181 BPListElem *findBP(int n)
182 {
183     DynerList<BPListElem *>::iterator i;
184
185     for (i = bplist.begin(); i != bplist.end(); i++) {
186         if ((*i)->number == n) return (*i);
187     }
188
189     return NULL;
190 }
191
192 int help(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
193 {
194
195     printf("at <function> [entry|exit|preCall|postCall] <statement> - insert statement\n");
196     printf("at termination <statement> - Execute <statement> at program exit callback\n");
197     printf("declare <variable> <type> - create a new variable of type <type>\n");
198     printf("deletebreak <breakpoint number ...> - delete breakpoint(s)\n");
199     printf("break <function> [entry|exit|preCall|postCall] [<condition>] - set a (conditional)\n");
200     printf("     break point at specified points of <function>\n");
201     printf("break <file name:line number> [<condition>] - set an arbitrary (conditional) break\n");
202     printf("     point at <line number> of <file name>\n");
203     printf("listbreak - list break points\n");
204     printf("load <program> [arguments] [< filename] [> filename] - load a program\n");
205     printf("     library <lib name> - load a dynamically linked library\n");
206     printf("run - run or continue the loaded program\n");
207     printf("show [modules|functions|variables] - display module names, global functions\n");
208     printf("      and variables\n");
209     printf("show functions in <module> - display function names declared in <module>\n");
210     printf("show [parameters|variables] in <function> - display local variables or parameters of\n");
211     printf("     <function>\n");
212     printf("count <function> - At the end of execution display how many times <function> is called\n");
213     printf("replace function <function1> with <function2> - Replace all calls to <function1> with\n");
214     printf("     calls to <function2>\n");
215     printf("replace call <function1>[:n] with <function2> - All the calls or the nth function call \n");
216     printf("     in <function1> are/is changed to the function <function2>\n");
217     printf("trace <function> - Print a message at the entry and exit of <function>\n");
218     printf("trace functions in <module> - Print a message at the entry and exit of all functions\n");
219     printf("     declared in <module>\n");
220     printf("untrace <function> - Undo the effects of trace command for <function>\n");
221     printf("untrace functions in <module> - Undo the effects of trace command for all functions\n");
222     printf("     declared in <module>\n");
223     printf("add <C++ file> - Create a dynamically linked library from a C++ source file and load\n");
224     printf("     it to address space. All the functions and variables will be available for \n");
225     printf("     instrumentation\n");
226     printf("mutations [enable|disable] - Enable or disable the execution of snippets\n");
227     printf("removecall <function>[:n] - Remove all the calls or n'th call in <function>\n");
228     //printf("dump <file name> - Write the in-memory version of the program to the specified file\n");
229     printf("detach - remove all the code inserted into target program\n");
230     printf("source <file name> - Execute dyner commands stored in the file <file name>\n");
231     return TCL_OK;
232 }
233
234 bool haveApp()
235 {
236     if (appThread == NULL) {
237         fprintf(stderr, "No application loaded.\n");
238         return false;
239     }
240
241     if (appThread->isTerminated()) {
242         fprintf(stderr, "The application has exited.\n");
243         return false;
244     }
245
246     return true;
247 }
248
249 BPatch_module *FindModule(char *name) {
250
251     //Locate the module using module name 
252     BPatch_Vector<BPatch_module *> *modules = appImage->getModules();
253
254     if (!modules) {
255         printf("Can not get module info !\n");
256         return NULL;
257     }
258
259     char modName[1024];
260     BPatch_module *module = NULL;
261
262     for(int i=0; i<modules->size(); ++i) {
263         (*modules)[i]->getName(modName, 1024);
264
265         if (!strcmp(modName, name)) {
266                 module = (*modules)[i];
267                 break;
268         }
269     }
270
271     if (!module) {
272         printf("Module %s is not found !\n", name);
273         return NULL;
274     }
275
276     return module;
277 }
278
279 int loadApp(char *pathname, char **args)
280 {
281     printf("Loading \"%s\"\n", pathname);
282
283     if (appThread != NULL) delete appThread;
284     bplist.clear();
285     iplist.clear();
286     varList.clear();
287     appThread = bpatch.createProcess(pathname, args);
288     bpNumber = NULL;
289
290     if (!appThread || appThread->isTerminated()) {
291         fprintf(stderr, "Unable to run test program.\n");
292         appThread = NULL;
293         return TCL_ERROR;
294     }
295
296     // Read the program's image and get an associated image object
297     appImage = appThread->getImage();
298
299     if (!appImage) return TCL_ERROR;
300
301     //Create type info
302     appImage->getModules();
303
304     return TCL_OK;
305
306 }
307
308
309 int loadLib(char *libName) {
310     if (!haveApp()) return TCL_ERROR;
311
312     if (appThread->loadLibrary(libName))
313         return TCL_OK;
314
315     return TCL_ERROR;
316 }
317
318 int loadCommand(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
319 {
320     if ( (argc == 3) && (!strcmp(argv[1], "library")) )
321         return loadLib(argv[2]);
322
323     if (argc < 2) {
324         printf("Usage load <program> [<arguments>]\n");
325         printf("or    load library <lib name>\n");
326         return TCL_ERROR;
327     }
328
329     return loadApp(argv[1], &argv[1]);
330 }
331
332 int listBreak(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
333 {
334     if (!haveApp()) return TCL_ERROR;
335
336     BPListElem *curr;
337     DynerList<BPListElem *>::iterator i;
338
339     for (i = bplist.begin(); i != bplist.end(); i++) {
340         curr = (BPListElem *) *i;
341         curr->Print();
342     }
343 }
344
345 int deleteBreak(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
346 {
347     if (!haveApp()) return TCL_ERROR;
348
349     if (argc < 2) {
350         printf("Specify breakpoint(s) to delete.\n");
351         return TCL_ERROR;
352     }
353
354     int ret = TCL_OK;
355     for (int j = 1; j < argc; j++) {
356         int n = atoi(argv[j]);
357
358         BPListElem *i = findBP(n);
359         if (i == NULL) {
360             printf("No such breakpoint: %d\n", n);
361             ret = TCL_ERROR;
362         } else {
363             appThread->deleteSnippet(i->handle);
364             bplist.erase(i);
365             delete i;
366             printf("Breakpoint %d deleted.\n", n);
367         }
368     }
369
370     return ret;
371 }
372
373 int runApp(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
374 {
375     if (!haveApp()) return TCL_ERROR;
376
377     if (bpNumber) {
378         int inval = -1;
379         bpNumber->writeValue(&inval);
380     }
381
382     // Start of code to continue the process.
383     dprintf("starting program execution.\n");
384     appThread->continueExecution();
385
386     while (!appThread->isStopped() && !appThread->isTerminated())
387         usleep(250);
388
389     int bp = -1;
390     if (bpNumber) bpNumber->readValue(&bp);
391
392     if (appThread->isTerminated()) {
393         printf("\nApplication exited.\n");
394     } else if (appThread->isStopped() && bp > 0) {
395         printf("\nStopped at break point %d.\n", bp);
396         ListElem *i = findBP(bp);
397         if (i != NULL) {
398             BPListElem *curr = (BPListElem *) i;
399             curr->Print();
400         }
401     } else {
402         printf("\nStopped.\n");
403     }
404
405     return TCL_OK;
406 }
407
408 int killApp(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
409 {
410     if (!haveApp()) return TCL_ERROR;
411
412     appThread->terminateExecution();
413
414     return TCL_OK;
415 }
416
417 extern BPatch_snippet *parse_result;
418 int condBreak(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
419 {
420     if (argc < 2) {
421         printf("Usage: break <function> [entry|exit|preCall|postCall] [<condition>]\n");
422         printf("or     break <file name:line number> [<condition>]\n");
423         return TCL_ERROR;
424     }
425
426     if (!haveApp()) return TCL_ERROR;
427
428     if (bpNumber == NULL) {
429         bpNumber = appThread->malloc(*appImage->findType("int"));
430         if (bpNumber == NULL) {
431             fprintf(stderr, "Unable to allocate memory in the inferior process.\n");
432             exit(1);
433         }
434     }
435
436     int expr_start = 2;
437     int lineNum = 0;
438     BPatch_procedureLocation where;
439     BPatch_callWhen when;
440
441     BPatch_Vector<BPatch_point *> *points;
442     char *ptr = strchr(argv[1],':');
443     if (ptr) {
444         //Arbitrary break point, first find module name
445         expr_start = 2;
446         where = BPatch_entry;
447         when = BPatch_callBefore;
448         *ptr = '\0';
449         lineNum = atoi(ptr+1);
450         BPatch_Vector<unsigned long> absAddrVec;
451
452         if (!appImage->getLineToAddr(argv[1], lineNum, absAddrVec, true)) {
453                 printf("Can not get arbitrary break point address!\n");
454                 return TCL_ERROR;
455         }
456         points = new BPatch_Vector<BPatch_point *>;
457         //Find BPatch_point from the first absolute address
458         points->push_back(appImage->createInstPointAtAddr((void *)absAddrVec[0]));
459     }
460     else {
461         if ( (argc > 2) && name2loc(argv[2], where, when)) {
462                 expr_start = 3;
463         } else {
464                 where = BPatch_entry;
465                 when = BPatch_callBefore;
466         }
467
468         points = appImage->findProcedurePoint(argv[1], where);
469
470         if (points == NULL) {
471                 printf("Unable to locate function %s\n", argv[1]);
472                 return TCL_ERROR;
473         }
474     }
475
476     char *line_buf = NULL;
477
478     if (argc > 3) {
479         // Count up how large a buffer we need for the whole line
480         int line_len = 0;
481         for (int i = expr_start; i < argc; i++)
482                 line_len += strlen(argv[i]) + 1;
483         line_len++;
484         // Make the buffer and copy the line into it
485         line_buf = new char[line_len];
486         *line_buf = '\0';
487         for (int i = expr_start; i < argc; i++) {
488                 strcat(line_buf, argv[i]);
489                 if (i != argc-1) strcat(line_buf, " ");
490         }
491
492         set_lex_input(line_buf);
493         if (dynerparse() != 0) {
494                 fprintf(stderr, "Breakpoint not set due to error.\n");
495                 delete line_buf;
496                 return TCL_ERROR;
497         }
498
499         if (parse_type != parsed_bool) {
500                 fprintf(stderr, "Breakpoint not set due error, expression not boolean.\n");
501                 delete line_buf;
502                 delete parse_result;
503                 return TCL_ERROR;
504         }
505     }
506
507     // Make a snippet to tell us which breakpoint it is
508     BPatch_arithExpr storeBPNum(BPatch_assign,
509                                 *bpNumber, BPatch_constExpr(bpCtr));
510
511     // Make a snippet to break at the breakpoint
512     BPatch_function *breakFunc = appImage->findFunction("DYNINSTbreakPoint");
513     if (breakFunc == NULL) {
514         fprintf(stderr, "Unable to find function DYNINSTbreakPoint (required for setting break points)\n");
515         if (argc > 3) {
516                 delete parse_result;
517                 delete line_buf;
518         }
519         return TCL_ERROR;
520     }
521
522     BPatch_Vector<BPatch_snippet *> nullArgs;
523     BPatch_funcCallExpr callBreak(*breakFunc, nullArgs);
524
525     // store the break point number, then  break
526     BPatch_arithExpr doBreak(BPatch_seq, storeBPNum, callBreak);
527     
528     BPatch_snippet *brSnippet = (BPatch_snippet *) &doBreak;
529
530     if (argc > 3) {
531         // Call the break snippet conditionally
532         BPatch_ifExpr condBreak(*(BPatch_boolExpr *)parse_result, doBreak); 
533         brSnippet = (BPatch_snippet *) &condBreak; 
534         delete parse_result;
535         delete line_buf;
536     }
537
538     BPatchSnippetHandle *handle =
539         appThread->insertSnippet(*brSnippet, *points, when,BPatch_lastSnippet);
540     if (handle == 0) {
541         fprintf(stderr, "Error inserting snippet.\n");
542         if (line_buf) delete line_buf;
543         return TCL_ERROR;
544     }
545
546     BPListElem *bpl =
547         new BPListElem(bpCtr, argv[1], where, when, line_buf, handle, lineNum);
548     if (line_buf) delete line_buf;
549
550     bplist.push_back(bpl);
551
552     printf("Breakpoint %d set.\n", bpCtr);
553     bpCtr++;
554
555     return TCL_OK;
556 }
557 /*
558  * void printPtr( )
559  *
560  * This function recursively goes through the BPatch_type pointers until
561  * it gets to the base type and prints that name.  The base type can be
562  * a builtin type or an enum, struct, or union.  The default case handles
563  * unknown pointer types.  -- jdd 5/27/99
564  */
565 void printPtr( BPatch_type * type )
566 {
567   if( type->getDataClass() == BPatch_pointer ){
568     printPtr( type->getConstituentType() );
569     printf("*");
570   }
571   else if((type->getDataClass() == BPatch_scalar)||(type->getDataClass() == BPatch_built_inType)||
572         (type->getDataClass() == BPatchSymTypeRange)){
573     printf("%s ", type->getName());
574   }
575   else{
576     switch( type->getDataClass() ){
577     case BPatch_enumerated:
578       printf("enum %s ", type->getName());
579       break;
580     case BPatch_structure:
581       printf("struct %s ", type->getName());
582       break;
583     case BPatch_union:
584       printf("union %s ", type->getName());
585       break;
586     default:
587       printf("Undefined POINTER: %s", type->getName());
588       break;
589     }
590   }
591   
592 }
593 /*
594  * printArray()
595  *
596  * This function prints arrays of various dimension, 1D to 3D. It first
597  * checks how many dimensions the array is and then prints it out.
598  * The default case handles the unknown. --jdd 5/27/99
599  */
600  
601 void printArray(BPatch_type * type )
602 {
603   int j = 0;
604   if(type->getConstituentType()){
605     j++;
606     if(type->getConstituentType()->getConstituentType()){
607       j++;
608       if(type->getConstituentType()->getConstituentType()->getConstituentType()){
609         j++;
610       }
611     }
612   }
613   switch(j){
614   case 3:
615     
616     //3D array
617     printf("    %s is an array [%s..%s][%s..%s][%s..%s] of %s\n",
618            type->getName(), type->getLow(), type->getHigh(),
619            type->getConstituentType()->getLow(),
620            type->getConstituentType()->getHigh(),
621            type->getConstituentType()->getConstituentType()->getLow(),
622            type->getConstituentType()->getConstituentType()->getHigh(),
623            type->getConstituentType()->getConstituentType()->getConstituentType()->getName());
624     break;
625   case 2:
626         
627     //2D array
628     printf("    %s is an array [%s..%s][%s..%s] of %s\n", type->getName(), 
629            type->getLow(), type->getHigh(),
630            type->getConstituentType()->getLow(),
631            type->getConstituentType()->getHigh(),
632            type->getConstituentType()->getConstituentType()->getName());
633     break;
634   case 1:
635     printf("    %s is an array [%s..%s] of %s\n", type->getName(),
636            type->getLow(), type->getHigh(), 
637            type->getConstituentType()->getName());
638     break;
639   default:
640     printf("Unable to process array %s\n", type->getName());
641     break;
642   }
643 }
644
645 BPatch_snippet *termStatement = NULL;
646
647 void exitCallback(BPatch_thread *thread, int code) {
648     if (termStatement == NULL)
649         return;
650
651     BPatch_snippet *stmt = termStatement;
652     termStatement = NULL;
653     thread->oneTimeCode(*stmt);
654     delete stmt;
655 }
656
657 int instTermStatement(int argc, char *argv[])
658 {
659     int expr_start = 2;
660
661     // Count up how large a buffer we need for the whole line
662     int line_len = 0;
663     for (int i = expr_start; i < argc; i++)
664         line_len += strlen(argv[i]) + 1;
665     line_len += 2;
666     // Make the buffer and copy the line into it
667     char *line_buf = new char[line_len];
668     *line_buf = '\0';
669     for (int i = expr_start; i < argc; i++) {
670         strcat(line_buf, argv[i]);
671         if (i != argc-1) strcat(line_buf, " ");
672     }
673     strcat(line_buf, "\n");
674
675     // printf("calling parse of %s\n", line_buf);
676     set_lex_input(line_buf);
677     if (dynerparse() != 0) {
678         fprintf(stderr, "Instrumentation not set due to error.\n");
679         delete line_buf;
680         return TCL_ERROR;
681     }
682
683     if (parse_type != parsed_statement) {
684         fprintf(stderr, "code not inserted, expression is not a statement.\n");
685         delete line_buf;
686         delete parse_result;
687         return TCL_ERROR;
688     }
689
690     termStatement = parse_result;
691     return TCL_OK;
692 }
693
694 int instStatement(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
695 {
696     if (!haveApp()) return TCL_ERROR;
697
698     if (argc < 3) {
699         printf("Usage: at <function> [entry|exit|preCall|postCall] <statement>\n");
700         printf("or     at termination <statement>\n");
701         return TCL_ERROR;
702     }
703
704     if (!strcmp(argv[1], "termination"))
705         return instTermStatement(argc, argv);
706
707     int expr_start = 2;
708     BPatch_procedureLocation where;
709     BPatch_callWhen when;
710
711     if (name2loc(argv[2], where, when)) {
712         expr_start = 3;
713     } else {
714         where = BPatch_entry;
715         when = BPatch_callBefore;
716     }
717
718     BPatch_function *func = appImage->findFunction(argv[1]);
719     if (func == NULL) {
720         fprintf(stderr, "Unable to locate function: %s\n", argv[1]);
721         return TCL_ERROR;
722     }
723
724     BPatch_Vector<BPatch_point *> *points = func->findPoint(where);
725                                 // appImage->findProcedurePoint(argv[1], where);
726
727     if (points == NULL) {
728         fprintf(stderr, "Unable to locate function: %s\n", argv[1]);
729         return TCL_ERROR;
730     }
731
732     //Assign targetPoint using function entry point
733     targetPoint = (*(func->findPoint(BPatch_entry)))[0];
734
735     bool trace = false;
736     if (!strcmp(argv[argc-1], "trace")) {
737         //This statement is used for tracing the functions
738         trace = true;
739         argc--;
740     }
741
742     // Count up how large a buffer we need for the whole line
743     int line_len = 0;
744     for (int i = expr_start; i < argc; i++)
745         line_len += strlen(argv[i]) + 1;
746     line_len += 2;
747     // Make the buffer and copy the line into it
748     char *line_buf = new char[line_len];
749     *line_buf = '\0';
750     for (int i = expr_start; i < argc; i++) {
751         strcat(line_buf, argv[i]);
752         if (i != argc-1) strcat(line_buf, " ");
753     }
754     strcat(line_buf, "\n");
755
756     // printf("calling parse of %s\n", line_buf);
757     set_lex_input(line_buf);
758     if (dynerparse() != 0) {
759         fprintf(stderr, "Instrumentation not set due to error.\n");
760         delete line_buf;
761         targetPoint = NULL;
762         return TCL_ERROR;
763     }
764
765     targetPoint = NULL;
766
767     if (parse_type != parsed_statement) {
768         fprintf(stderr, "code not inserted, expression is not a statement.\n");
769         delete line_buf;
770         delete parse_result;
771         return TCL_ERROR;
772     }
773
774     BPatchSnippetHandle *handle =
775         appThread->insertSnippet(*parse_result, *points, when,BPatch_lastSnippet);
776     if (handle == 0) {
777         fprintf(stderr, "Error inserting snippet.\n");
778         delete line_buf;
779         return TCL_ERROR;
780     }
781
782     IPListElem *snl =
783         new IPListElem(ipCtr, argv[1], where, when, line_buf, handle, trace);
784     delete line_buf;
785
786     iplist.push_back(snl);
787
788     // printf("Inst point %d set.\n", ipCtr);
789     ipCtr++;
790
791     return TCL_OK;
792 }
793
794 void printVarRecursive(BPatch_variableExpr *var, int level)
795 {
796     int iVal;
797     int pVal;
798     float fVal;
799
800     BPatch_dataClass dc;
801     BPatch_type *type = (BPatch_type *) var->getType();
802
803     dc = type->getDataClass();
804     if (!strcmp(type->getName(), "int")) {
805         /* print out the integer */
806         var->readValue((void *) &iVal);
807         printf("%d\n", iVal);
808     } else if (!strcmp(type->getName(), "float")) {
809         /* print out the float */
810         var->readValue((void *) &fVal);
811         printf("%f\n", fVal);
812     } else if (dc == BPatch_pointer) {
813         /* print out the float */
814         var->readValue((void *) &pVal);
815         printf("0x%x\n", pVal);
816     } else if (dc == BPatch_structure) {
817         printf("struct {\n");
818         level++;
819         BPatch_Vector<BPatch_variableExpr *> *fields = var->getComponents();
820         for (int i=0; i < fields->size(); i++) {
821              BPatch_variableExpr *fieldVar = (*fields)[i];
822              for (int i=0;i < level; i++) printf("    ");
823              printf("%s = ", fieldVar->getName());
824              printVarRecursive(fieldVar, level);
825         }
826         level--;
827         printf("}\n");
828     } else if (dc == BPatch_array) {
829         printf("<arrays not yet implemented>\n");
830     } else {
831         printf("<unknown type>\n");
832     }
833 }
834
835 int printVar(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
836 {
837     //if (!haveApp()) return TCL_ERROR;
838
839     BPatch_variableExpr *var = findVariable(argv[1]);
840     if (!var) {
841         printf("%s is not defined\n", argv[1]);
842         return TCL_ERROR;
843     }
844
845     printf("    %s = ", argv[1]);
846     printVarRecursive(var, 1);
847
848     return TCL_OK;
849 }
850
851 /*
852  * declare <type> <variable name>
853  */
854 int newVar(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
855 {
856     if (argc != 3) {
857         printf("Usage: declare <type> <variable name>\n");
858         return TCL_ERROR;
859     }
860
861     if (!haveApp()) return TCL_ERROR;
862
863     BPatch_type *type = appImage->findType(argv[1]);
864     if (!type) {
865         printf("type %s is not defined\n", argv[1]);
866         return TCL_ERROR;
867     }
868
869     BPatch_variableExpr *newVar = appThread->malloc(*type);
870     if (!newVar) {
871         printf("unable to create variable.\n");
872         return TCL_ERROR;
873     }
874
875     varList.push_back(new runtimeVar(newVar, argv[2]));
876 }
877
878 BPatch_variableExpr *findVariable(char *name)
879 {
880     BPatch_variableExpr *var;
881     DynerList<runtimeVar *>::iterator i;
882
883     // First look for runtime created variables
884     for (i = varList.begin(); i != varList.end(); i++) {
885         if (!strcmp(name, (*i)->name)) {
886             var = new BPatch_variableExpr(*((*i)->var));
887             return (var);
888         }
889     }
890
891     // Now check the function locals
892     if (targetPoint) {
893         var = appImage->findVariable(*targetPoint, name);
894         if (var) return var;
895     }
896
897     // Check global vars in the mutatee
898     errorLoggingOff = true;
899     var = appImage->findVariable(name);
900     errorLoggingOff = false;
901
902     if (var) return var;
903
904     printf("Unable to locate variable %s\n", name);
905     return NULL;
906 }
907
908 /* 
909  * int whatisParam()
910  *
911  * This function is an extension to the "whatis" command.  This function
912  * processes the command: whatis -scope <function> <variable>. If the
913  * <function> is undefined then TCL_ERROR is returned.  Otherwise, the
914  * local variable collection is searched first; followed by the parameter
915  * collection; and finally the Global collection is searched last. If the
916  * <variable> is not found, then "<variable> is not defined" is reported
917  * to the user. --jdd 5/27/98
918  */
919 int whatisParam(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
920 {
921   if (!haveApp()) return TCL_ERROR;
922   BPatch_function * func = appImage->findBPFunction(argv[2]);
923   printf("func is %x\n", func);
924   if(!func){
925     printf("%s is not defined\n", argv[3]);
926     return TCL_ERROR;
927   }
928   
929   
930   BPatch_localVar * lvar = func->findLocalVar(argv[3]);
931   if(lvar){
932     BPatch_type *type = lvar->getType();
933     if( type ){
934       switch (type->getDataClass()) {
935       case BPatch_array:
936         printArray( type );
937         break;
938         
939       case BPatch_pointer:
940         printPtr( type );
941         printf("\t %s\n", argv[3]);
942         break;
943         
944       default:
945         printf("    %s is of type %s \n", argv[3], type->getName());
946         break;
947       }
948     }
949     //print local variable info
950     printf("        %s is a local variable in function %s\n", lvar->getName(),
951            argv[2]);
952     printf("        Declared on line %d and has a Frame offset of %d\n",
953            lvar->getLineNum(), lvar->getFrameOffset());
954   }
955   else{
956     lvar = func->findLocalParam(argv[3]);
957     
958     if (!lvar) {
959       BPatch_variableExpr *var = findVariable(argv[3]);
960       if(!var){
961         // do something else ??
962         //int ret = whatisType(cd, interp, argc, argv);
963         return TCL_OK;
964       }
965       BPatch_type *type = (BPatch_type *) var->getType();
966       switch (type->getDataClass()) {
967       case BPatch_array:
968         printArray( type );
969         break;
970         
971       case BPatch_pointer:
972         printPtr( type );
973         printf("\t %s\n", argv[3]);
974         break;
975         
976       default:
977         printf("    %s is of type %s \n", argv[3], type->getName());
978         break;
979       }
980      printf("      %s is a Global variable\n", argv[3]);
981     }
982     else{
983       BPatch_type *lType = (BPatch_type *) lvar->getType();
984       if (lType){
985         switch (lType->getDataClass()) {
986         case BPatch_array:
987           printArray( lType );
988           break;
989           
990         case BPatch_pointer:
991           printPtr( lType );
992           printf("\t %s\n", argv[3]);
993           break;
994           
995         default:
996           printf("    %s is of type %s \n", argv[3], lType->getName());
997           break;
998         }
999         printf("       %s is a parameter of the function %s\n",lvar->getName(),
1000            argv[2]);
1001         printf("       Declared on line %d and has a Frame offset of %d\n",
1002            lvar->getLineNum(), lvar->getFrameOffset());
1003       }
1004       else{
1005         printf("   unknown type %s\n", lvar->getName());
1006       }
1007     }   
1008   }
1009   return TCL_OK;
1010 }
1011
1012 /*
1013  * int whatisFunc()
1014  *
1015  * This function is an extension to the "whatis" command.  This function
1016  * searches all of the modules to find the BPatch_function with the name
1017  * given be argv[1]. If no such function is found, then TCL_ERROR is returned.
1018  * This is the last function in the chain of "whatis" command functions to
1019  * be executed in the search for argv[1]. --jdd 5/27/99
1020  */
1021  
1022 int whatisFunc(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
1023 {
1024     if (!haveApp()) return TCL_ERROR;
1025     // If the function is found it returns the BPatch_function.
1026     // findFunction() creates a new BPatch_function so it is not
1027     // used here. --jdd 5/27/99
1028     BPatch_function * func = appImage->findBPFunction(argv[1]);
1029     
1030     if(!func){
1031       printf("%s is not defined\n", argv[1]);
1032       return TCL_ERROR;
1033     }
1034     printf("    Function %s ", argv[1]);
1035     BPatch_type * retType = func->getReturnType();
1036     if(retType)
1037       switch(retType->getDataClass()){
1038       case BPatch_scalar:
1039       case BPatch_built_inType:
1040       case BPatchSymTypeRange:
1041         printf("  with return type %s\n",retType->getName() );
1042         break;
1043       case BPatch_array:
1044         printf("  with return type ");
1045         printArray( retType );
1046         printf("\n");
1047         break;
1048           
1049       case BPatch_pointer:
1050         printf("  with return type ");
1051         printPtr( retType );
1052         printf("\n");
1053         break;
1054         
1055       default:
1056         printf("    %s has unknown return type %s %d\n",argv[1],
1057                retType->getName(), retType->getID());
1058         break;
1059       }
1060     else
1061       printf("   unknown return type for %s\n", argv[1]);
1062     BPatch_Vector<BPatch_localVar *> *params = func->getParams();
1063     if( params->size())
1064       printf("        Parameters: \n");
1065     for (int i=0; i < params->size(); i++) {
1066       BPatch_localVar *localVar = (*params)[i];
1067       BPatch_type *lType = (BPatch_type *) localVar->getType();
1068       if (lType){
1069         if( (lType->getDataClass())  == BPatch_pointer){
1070           printPtr(lType);
1071           printf(" \t %s\n", localVar->getName());
1072         }
1073         else if( (lType->getDataClass()) == BPatch_array){
1074           printArray( lType );
1075         }
1076         else
1077           printf("        %s %s\n",lType->getName(), localVar->getName());
1078         
1079       }
1080       else{
1081         printf("   unknown type %s\n", localVar->getName());
1082       }
1083     }    
1084     return TCL_OK;
1085 }
1086
1087 /*
1088  * int whatisType()
1089  *
1090  * This function is an extension to the "whatis" command.  This function
1091  * searches for the type collection of the all the modules looking for
1092  * the type specified by argv[1]. If it is not found, then whatisFunc()
1093  * is called. This is function is called by whatisVar if a variable is
1094  * not found. -- jdd 5/27/99
1095  */
1096  
1097 int whatisType(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
1098 {
1099     if (!haveApp()) return TCL_ERROR;
1100     
1101     BPatch_type *type = appImage->findType(argv[1]);
1102     if (!type) {
1103       int ret = whatisFunc(cd, interp, argc, argv);
1104       return ret;
1105     }
1106
1107     BPatch_dataClass dc = type->getDataClass();
1108     switch (dc) {
1109     case BPatch_structure: {
1110       printf("    struct %s {\n", argv[1]);
1111       BPatch_Vector<BPatch_field *> *fields = type->getComponents();
1112       for (int i=0; i < fields->size(); i++) {
1113         BPatch_field *field = (*fields)[i];
1114         BPatch_type *fType = (BPatch_type *) field->getType();
1115         if (fType){
1116           switch (fType->getDataClass()) {
1117           case BPatch_array:
1118             printArray( fType );
1119             printf("  %s\n", field->getName());
1120             break;
1121         
1122           case BPatch_pointer:
1123             printPtr( fType );
1124             printf("  %s\n", field->getName());
1125             break;
1126         
1127           default:
1128             printf("        %s %s\n", fType->getName(), field->getName());
1129             break;
1130           }
1131         }
1132         else{
1133           printf("   unknown type %s\n", field->getName());
1134         }
1135       }
1136       printf("    }\n");
1137       break;
1138     }
1139     case BPatch_union: {
1140       printf("    union %s {\n", argv[1]);
1141       BPatch_Vector<BPatch_field *> *fields = type->getComponents();
1142       for (int i=0; i < fields->size(); i++) {
1143         BPatch_field *field = (*fields)[i];
1144         BPatch_type *fType = (BPatch_type *) field->getType();
1145         if (fType){
1146           switch (fType->getDataClass()) {
1147           case BPatch_array:
1148             printArray( fType );
1149             printf("  %s\n", field->getName());
1150             break;
1151         
1152           case BPatch_pointer:
1153             printPtr( fType );
1154             printf("  %s\n", field->getName());
1155             break;
1156             
1157           default:
1158             printf("        %s %s\n", fType->getName(), field->getName());
1159             break;
1160           }
1161         }
1162         else{
1163           printf("        unknown type %s\n", field->getName());
1164         }
1165       }
1166       printf("    }\n");
1167       break;
1168     }
1169     case BPatch_enumerated: {
1170       printf("    enum %s {\n", argv[1]);
1171       BPatch_Vector<BPatch_field *> *fields = type->getComponents();
1172       for (int i=0; i < fields->size(); i++) {
1173         BPatch_field *field = (*fields)[i];
1174         printf("        %s    \t%d\n", field->getName(),
1175                field->getValue());
1176       }
1177       printf("    }\n");
1178       break;
1179     }
1180     case BPatch_array:
1181       printArray( type );
1182       break;
1183       
1184     case BPatch_scalar:
1185     case BPatch_built_inType:
1186       printf("    %s is a scalar of size %d\n",argv[1],type->getSize());
1187       break;
1188       
1189     case BPatch_pointer:
1190       printPtr( type );
1191       printf("\t %s\n", argv[1]);
1192       /*
1193       printf("    %s is pointer to type %s\n", argv[1], 
1194              type->getConstituentType()->getName());*/
1195       break;
1196     case BPatchSymTypeRange:
1197       if(type->getConstituentType())
1198         printf("    %s is a %s of size %d\n",argv[1],
1199                (type->getConstituentType())->getName(),type->getSize());
1200       else
1201         printf("    %s is a scalar of size %d\n",argv[1],type->getSize());
1202       if( type->getLow() ){
1203          printf("        with range %s to %s\n", type->getLow(),
1204                 type->getHigh());
1205       }
1206       break;
1207     default:
1208       printf("%s is of an unknown data class %d\n", argv[1],
1209              dc);
1210       break;
1211     }
1212     
1213     return TCL_OK;
1214 }
1215
1216 /*
1217  * int whatisVar()
1218  *
1219  * This function is an extension to the "whatis" command.  This function
1220  * searches the process for the variable named by argv[1] and then searches
1221  * all the Global variables for all the modules to find the variable
1222  * specified by argv[1].  If nothing is found, then whatisType() is called. If
1223  * whatisType() finds nothing, whatisFunc() is called.  If the command is
1224  * of the form "whatis -scope <function> <variable>", then whatisParam() is
1225  * called skipping all other attempts to find the variable. -- jdd 5/27/99
1226  */
1227
1228 int whatisVar(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
1229 {
1230     if (!haveApp()) return TCL_ERROR;
1231     
1232     if (argc == 4){ //looking for a local variable
1233       if(!(strcmp(argv[1], "-scope"))){
1234         int ret = whatisParam(cd, interp, argc, argv );
1235         return ret;
1236       } else {
1237         printf("inavlid argument %s\n", argv[1]);
1238         return TCL_ERROR;
1239       }
1240     }
1241
1242     BPatch_variableExpr *var = findVariable(argv[1]);
1243     if (!var) {
1244         int ret = whatisType(cd, interp, argc, argv);
1245         return ret;
1246     }
1247
1248     BPatch_type *type = (BPatch_type *) var->getType();
1249     switch (type->getDataClass()) {
1250     case BPatch_structure: {
1251       printf("    struct %s {\n", argv[1]);
1252       BPatch_Vector<BPatch_field *> *fields = type->getComponents();
1253       for (int i=0; i < fields->size(); i++) {
1254         BPatch_field *field = (BPatch_field *) (*fields)[i];
1255         BPatch_type *fType = (BPatch_type *) field->getType();
1256         if (fType){
1257           printf("        %s %s\n", fType->getName(), field->getName());
1258         }
1259         else{
1260           printf("   unknown type %s\n", field->getName());
1261         }
1262       }
1263       printf("    }\n");
1264       break;
1265     }
1266     case BPatch_union: {
1267       printf("    union %s {\n", argv[1]);
1268       BPatch_Vector<BPatch_field *> *fields = type->getComponents();
1269       for (int i=0; i < fields->size(); i++) {
1270         BPatch_field *field = (*fields)[i];
1271         BPatch_type *fType = (BPatch_type *) field->getType();
1272         if (fType){
1273           printf("        %s %s\n", fType->getName(), field->getName());
1274         }
1275         else{
1276           printf("        unknown type %s\n", field->getName());
1277         }
1278       }
1279       printf("    }\n");
1280       break;
1281     }
1282     case BPatch_enumerated: {
1283       printf("    enum %s {\n", argv[1]);
1284       BPatch_Vector<BPatch_field *> *fields = type->getComponents();
1285       for (int i=0; i < fields->size(); i++) {
1286         BPatch_field *field = (*fields)[i];
1287         printf("        %s    \t%d\n", field->getName(),
1288                field->getValue());
1289       }
1290       printf("    }\n");
1291       break;
1292     }
1293     case BPatch_array:
1294       printArray(type);
1295       break;
1296    
1297     case BPatch_pointer:
1298       printPtr( type );
1299       printf("\t %s\n", argv[1]);
1300       /*
1301       printf("    %s is pointer to type %s\n", argv[1], 
1302              type->getConstituentType()->getName());*/
1303       break;
1304     case BPatchSymTypeRange:
1305       if(type->getConstituentType())
1306         printf("    %s is a %s of size %d\n",argv[1],
1307                (type->getConstituentType())->getName(),type->getSize());
1308       else
1309         printf("    %s is a scalar of size %d\n",argv[1],type->getSize());
1310       if( type->getLow() ){
1311         printf("        with range %s to %s\n", type->getLow(),
1312                type->getHigh());
1313       }
1314       break;
1315     case BPatch_scalar:
1316     case BPatch_built_inType:
1317       printf("    %s is a scalar of size %d\n",argv[1],type->getSize());
1318       break;
1319       
1320     default:
1321       printf("    %s is of type %s \n", argv[1], type->getName());
1322       //int ret = whatisType(cd, interp, argc, argv);
1323       break;
1324     }
1325     
1326     return TCL_OK;
1327 }
1328
1329 const int DYNINST_NO_ERROR = -1;
1330
1331 void errorFunc(BPatchErrorLevel level, int num, const char **params)
1332 {
1333     char line[256];
1334
1335     if (errorLoggingOff) return;
1336
1337     if ((num == 0) && ((level == BPatchWarning) || (level == BPatchInfo))) {
1338          // these are old warnings/status info from paradyn
1339          return;
1340     }
1341
1342     const char *msg = bpatch.getEnglishErrorString(num);
1343     bpatch.formatErrorString(line, sizeof(line), msg, params);
1344
1345     if (num != DYNINST_NO_ERROR) {
1346         printf("Error #%d (level %d): %s\n", num, level, line);
1347
1348         // We consider some errors fatal.
1349         if (num == 101) {
1350             exit(-1);
1351         }
1352     }
1353 }
1354
1355 /* This function prints type information. */
1356 void PrintTypeInfo(char *var, BPatch_type *type) {
1357       if (!type) {
1358         printf("NO RETURN TYPE INFO for %s\n", var);
1359         return;
1360       }
1361
1362       switch(type->getDataClass()){
1363       case BPatch_array:
1364         printArray( type );
1365         printf(" %s\n", var);
1366         break;
1367           
1368       case BPatch_pointer:
1369         printPtr( type );
1370         printf(" %s\n", var);
1371         break;
1372         
1373       default:
1374         printf("%s %s\n", type->getName(), var);
1375         break;
1376       }
1377 }
1378
1379 /* This function displays all the functions in the executable or the functions in a module
1380  * if a module name is provided.
1381  */
1382 int ShowFunctions(int argc, char *argv[]) {
1383     BPatch_Vector<BPatch_function *> *functions = NULL;
1384
1385     if (argc == 2) 
1386         functions = appImage->getProcedures();
1387     else if ( (argc == 4) && (!strcmp(argv[2], "in")) ) {
1388         BPatch_module *module = FindModule(argv[3]);
1389         if (!module)
1390                 return TCL_ERROR;
1391
1392         //Get the module functions
1393         functions = module->getProcedures();
1394     }
1395     else {
1396         printf("Syntax error !\n");
1397         return TCL_ERROR;
1398     }
1399
1400     if (!functions) {
1401         printf("Can not get function list!\n");
1402         return TCL_ERROR;
1403     }
1404
1405     //Now print all the functions in the module
1406     char funcName[1024];
1407     for(int i=0; i<functions->size(); ++i) {
1408         (*functions)[i]->getName(funcName, 1024);
1409         PrintTypeInfo(funcName, (*functions)[i]->getReturnType());
1410     }
1411
1412     return TCL_OK;
1413 }
1414
1415 /* Finds all the modules in the executable and displays the module names */
1416 int ShowModules()
1417 {
1418     char modName[1024];
1419     BPatch_Vector<BPatch_module *> *modules = appImage->getModules();
1420
1421     if (!modules) {
1422         printf("Can not get module info !\n");
1423         return TCL_ERROR;
1424     }
1425
1426     for(int i=0; i<modules->size(); ++i) {
1427         (*modules)[i]->getName(modName, 1024);
1428         printf("%s\n", modName);
1429     }
1430
1431     return TCL_OK;
1432 }
1433
1434 /*
1435  * This function finds and prints all the parameters
1436  * of a function whose name is given as input.
1437  */
1438 int ShowParameters(int argc, char *argv[]) {
1439     if ( (argc != 4) || (strcmp(argv[2], "in")) ) {
1440         printf("Usage: show parameters in <function>\n");
1441         return TCL_ERROR;
1442     }
1443
1444     BPatch_function *fp = appImage->findFunction(argv[3]);
1445
1446     if (!fp) {
1447         printf("Invalid function name: %s\n", argv[3]);
1448         return TCL_ERROR;
1449     }
1450
1451     BPatch_Vector<BPatch_localVar *> *params = fp->getParams();
1452     for(int i=0; i<params->size(); ++i) {
1453         PrintTypeInfo((char *) (*params)[i]->getName(), (*params)[i]->getType());
1454     }
1455
1456     return TCL_OK;
1457 }
1458
1459 /*
1460  * This function finds and prints all the local variables
1461  * of a function whose name is given as input.
1462  */
1463 int ShowLocalVars(char *funcName) {
1464     BPatch_function *fp = appImage->findFunction(funcName);
1465
1466     if (!fp) {
1467         printf("Invalid function name: %s\n", funcName);
1468         return TCL_ERROR;
1469     }
1470
1471     BPatch_Vector<BPatch_localVar *> *vars = fp->localVariables->getAllVars();
1472     for(int i=0; i<vars->size(); ++i) {
1473         PrintTypeInfo((char *) (*vars)[i]->getName(), (*vars)[i]->getType());
1474     }
1475
1476     delete vars;
1477
1478     return TCL_OK;
1479 }
1480
1481 /* Finds all the global vars in the executable and prints their names. */
1482 int ShowGlobalVars() {
1483     BPatch_Vector<BPatch_variableExpr *> *vars = appImage->getGlobalVariables();
1484
1485     if (!vars) {
1486         printf("Can not get global variable info !\n");
1487         return TCL_ERROR;
1488     }
1489
1490     for(int i=0; i<vars->size(); ++i) {
1491         PrintTypeInfo((*vars)[i]->getName(), (BPatch_type *) (*vars)[i]->getType());
1492     }
1493
1494     return TCL_OK;
1495 }
1496
1497 /* Finds all global variables or local variables in the function */
1498 int ShowVariables(int argc, char *argv[])
1499 {
1500     if (argc == 2)
1501         return ShowGlobalVars();
1502
1503     if ( (argc == 4) && (!strcmp(argv[2], "in")) )
1504         return ShowLocalVars(argv[3]);
1505
1506     //Should not reach here!
1507     return TCL_ERROR;
1508 }
1509
1510 /* Displays either modules or functions in a specific module in the executable */
1511
1512 int showCommand(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
1513 {
1514     if (!haveApp()) return TCL_ERROR;
1515
1516     if (argc == 1) {
1517         printf("Usage: show [modules|functions|variables]\n");
1518         printf("or     show functions in <module>\n");
1519         printf("or     show [variables|parameters] in <function>\n");
1520         return TCL_ERROR;
1521     }
1522
1523     if (!strcmp(argv[1], "modules"))
1524         return ShowModules();
1525
1526     if (!strcmp(argv[1], "functions"))
1527         return ShowFunctions(argc, argv);
1528
1529     if (!strcmp(argv[1], "variables"))
1530         return ShowVariables(argc, argv);
1531
1532     if (!strcmp(argv[1], "parameters"))
1533         return ShowParameters(argc, argv);
1534
1535     printf("Syntax error!\n");
1536     return TCL_ERROR;
1537 }
1538
1539 /* Displays how many times input fcn is called */
1540 int countCommand(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
1541 {
1542     if (!haveApp()) return TCL_ERROR;
1543
1544     if (argc != 2) {
1545         printf("Usage: count <function>\n");
1546         return TCL_ERROR;
1547     }
1548
1549     BPatch_function *fp = appImage->findFunction(argv[1]);
1550
1551     if (!fp) {
1552         printf("Invalid function name: %s\n", argv[1]);
1553         return TCL_ERROR;
1554     }
1555
1556     char *fcnName = argv[1];
1557     char cmdBuf[1024];
1558
1559     sprintf(cmdBuf, "declare int _%s_cnt", fcnName);
1560     if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
1561         return TCL_ERROR;
1562
1563     sprintf(cmdBuf, "at main entry { _%s_cnt = 0; }", fcnName);
1564     if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
1565         return TCL_ERROR;
1566
1567     sprintf(cmdBuf, "at %s entry { _%s_cnt++; }", fcnName, fcnName);
1568     if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
1569         return TCL_ERROR;
1570
1571     sprintf(cmdBuf, "at main exit { printf(\"%s called %%d times\\n\", _%s_cnt); }", 
1572                                                                         fcnName, fcnName);
1573     if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
1574         return TCL_ERROR;
1575
1576     return TCL_OK;
1577 }
1578
1579 /*
1580  * Replace all calls to fcn1 with calls fcn2
1581  */
1582 int repFunc(char *name1, char *name2) {
1583
1584     BPatch_function *func1 = appImage->findFunction(name1);
1585     if (!func1) {
1586         printf("Invalid function name: %s\n", name1);
1587         return TCL_ERROR;
1588     }
1589
1590     BPatch_function *func2 = appImage->findFunction(name2);
1591     if (!func2) {
1592         printf("Invalid function name: %s\n", name2);
1593         return TCL_ERROR;
1594     }
1595
1596     if (appThread->replaceFunction(*func1, *func2))
1597         return TCL_OK;
1598
1599     return TCL_ERROR;
1600 }
1601
1602 /*
1603  * Replace all or n'th call in func1 with a call to func2
1604  */
1605 int repCall(char *func1, char *func2) {
1606
1607     // Replace function calls
1608     int n = -1;
1609     char *ptr = strchr(func1,':');
1610     if (ptr) {
1611         *ptr = '\0';
1612         n = atoi(ptr+1) - 1;
1613         if (n == -1) {
1614                 printf("Invalid number is entered!\n");
1615                 return TCL_ERROR;
1616         }
1617     }
1618
1619     BPatch_function *newFunc = appImage->findFunction(func2);
1620     if (func2 == NULL) {
1621         printf("Invalid function name: %s\n", func2);
1622         return TCL_ERROR;
1623     }
1624
1625     BPatch_Vector<BPatch_point *> *points = appImage->findProcedurePoint(func1, 
1626                                                                         BPatch_subroutine);
1627     if (points == NULL) {
1628         printf("Could not locate function %s\n", func1);
1629         return TCL_ERROR;
1630     }
1631
1632     if (points->size() == 0) {
1633         printf("Function %s has no calls!\n", func1);
1634         return TCL_ERROR;
1635     }
1636
1637     if (n > points->size()) {
1638         printf("Function %s does not have %d calls!\n", func1, n);
1639         return TCL_ERROR;
1640     }
1641
1642     if (n == -1) {
1643         //Remove all function calls
1644         for(int i=0; i<points->size(); ++i) {
1645                 if (!appThread->replaceFunctionCall(*((*points)[i]), *newFunc) ) {
1646                         printf("Unable to replace call %d !\n", i);
1647                         return TCL_ERROR;
1648                 }
1649         }
1650         return TCL_OK;
1651     }
1652
1653     //Replace n'th function call
1654     if (!appThread->replaceFunctionCall(*((*points)[n]), *newFunc) ) {
1655         printf("Unable to replace call %d !\n", n);
1656         return TCL_ERROR;
1657     }
1658
1659     return TCL_OK;
1660 }
1661
1662 /*
1663  * Replaces functions or function calls with input function
1664  */
1665 int replaceCommand(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
1666 {
1667     if (!haveApp()) return TCL_ERROR;
1668
1669     if ( (argc != 5) || ( (strcmp(argv[1], "function")) && (strcmp(argv[1], "call")) )
1670                          || (strcmp(argv[3], "with")) ) 
1671     {
1672         printf("Usage: replace function <function1> with <function2>\n");
1673         printf("or     replace call <function1>[:n] with <function2>\n");
1674         return TCL_ERROR;
1675     }
1676
1677     if (!strcmp(argv[1], "function"))
1678         return repFunc(argv[2], argv[4]);
1679
1680     if (!strcmp(argv[1], "call"))
1681         return repCall(argv[2], argv[4]);
1682
1683     printf("Invalid option %s\n", argv[1]);
1684     return TCL_ERROR;
1685 }
1686
1687 /*
1688  * Print a message while entering a function
1689  */
1690 int traceFunc(Tcl_Interp *interp, char *name) {
1691     BPatch_function *func = appImage->findFunction(name);
1692     if (!func) {
1693         printf("Invalid function name: %s\n", name);
1694         return TCL_ERROR;
1695     }
1696
1697     char cmdBuf[1024];
1698     sprintf(cmdBuf, 
1699         "at %s entry { printf(\"Entering function %s\\n\"); } trace", name, name);
1700     if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
1701         return TCL_ERROR;
1702
1703     sprintf(cmdBuf, 
1704         "at %s exit { printf(\"Exiting function %s\\n\"); } trace", name, name);
1705     return Tcl_Eval(interp, cmdBuf);
1706 }
1707
1708 /*
1709  * Trace all the function in a module
1710  */
1711 int traceMod(Tcl_Interp *interp, char *name) {
1712     BPatch_Vector<BPatch_function *> *functions = NULL;
1713
1714     BPatch_module *module = FindModule(name);
1715     if (!module)
1716         return TCL_ERROR;
1717
1718     //Get the module functions
1719     functions = module->getProcedures();
1720
1721     if (!functions) {
1722         printf("Can not get function list!\n");
1723         return TCL_ERROR;
1724     }
1725
1726     //Now print all the functions in the module
1727     char funcName[1024];
1728     for(int i=0; i<functions->size(); ++i) {
1729         (*functions)[i]->getName(funcName, 1024);
1730         if (traceFunc(interp, funcName) == TCL_ERROR)
1731                 return TCL_ERROR;
1732     }
1733
1734     return TCL_OK;
1735 }
1736
1737 /*
1738  * Trace functions alone or in a module
1739  */
1740 int traceCommand(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
1741 {
1742     if (!haveApp()) return TCL_ERROR;
1743
1744     if (argc < 3) {
1745         printf("Usage: trace <function>\n");
1746         printf("or     trace functions in <module>\n");
1747         return TCL_ERROR;
1748     }
1749
1750     if (!strcmp(argv[1], "function"))
1751         return traceFunc(interp, argv[2]);
1752
1753     if (!strcmp(argv[1], "functions") && !strcmp(argv[2], "in"))
1754         return traceMod(interp, argv[3]);
1755
1756     return TCL_ERROR;
1757 }
1758
1759 int untraceFunc(char *name)
1760 {
1761     DynerList<IPListElem *>::iterator i;
1762
1763     i = iplist.begin(); 
1764
1765     while(i != iplist.end()) {
1766         IPListElem *ip = *i;
1767
1768         i++;
1769
1770         if (ip->trace && !strcmp(name, ip->function)) {
1771                 iplist.erase(ip);
1772                 delete ip;
1773         }
1774     }
1775
1776     return TCL_OK;
1777 }
1778
1779 int untraceMod(char *name)
1780 {
1781     BPatch_Vector<BPatch_function *> *functions = NULL;
1782
1783     BPatch_module *module = FindModule(name);
1784     if (!module)
1785         return TCL_ERROR;
1786
1787     //Get the module functions
1788     functions = module->getProcedures();
1789
1790     if (!functions) {
1791         printf("Can not get function list in the module!\n");
1792         return TCL_ERROR;
1793     }
1794
1795     //Now print all the functions in the module
1796     char funcName[1024];
1797     for(int i=0; i<functions->size(); ++i) {
1798         (*functions)[i]->getName(funcName, 1024);
1799         if (untraceFunc(funcName) == TCL_ERROR)
1800                 return TCL_ERROR;
1801     }
1802
1803     return TCL_OK;
1804 }
1805
1806 /*
1807  * Deletes trace effects
1808  */
1809 int untraceCommand(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
1810 {
1811     if (!haveApp()) return TCL_ERROR;
1812
1813     if (argc < 3) {
1814         printf("Usage: untrace <function>\n");
1815         printf("or     untrace functions in <module>\n");
1816         return TCL_ERROR;
1817     }
1818
1819     if (!strcmp(argv[1], "function"))
1820         return untraceFunc(argv[2]);
1821
1822     if (!strcmp(argv[1], "functions") && !strcmp(argv[2], "in"))
1823         return untraceMod(argv[3]);
1824
1825     return TCL_ERROR;
1826 }
1827
1828 /*
1829  * Compiles a C++ source file and dynamically adds it to address space
1830  */
1831 int addCommand(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
1832 {
1833     if (argc != 2) {
1834         printf("Usage: add <C++ file>\n");
1835         return TCL_ERROR;
1836     }
1837
1838     if (!haveApp()) return TCL_ERROR;
1839
1840     //Create shared object file name
1841     char *ptr = strrchr(argv[1], '/');
1842     if (ptr)
1843         ptr++;
1844     else
1845         ptr = argv[1];
1846
1847     char fname[1024];
1848     strcpy(fname, ptr);
1849
1850     ptr = strrchr(fname, '.');
1851     if (ptr)
1852         sprintf(ptr+1,"so");
1853     else
1854         strcat(fname,".so");
1855
1856     //First ensure that there is no .so file for the input file
1857     unlink(fname);
1858     
1859     //Create a shared object from input file
1860     char cmdBuf[1024];
1861     sprintf(cmdBuf,"g++ -g -fPIC -shared -o %s %s", fname, argv[1]);
1862
1863     system(cmdBuf);
1864
1865     //Test whether or not shared object is created
1866     FILE *fp = fopen(fname,"rb");
1867     if (!fp) {
1868         printf("Error in compilation of %s\n", argv[1]);
1869         return TCL_ERROR;
1870     }
1871     fclose(fp);
1872
1873     //Now dynamically link the file
1874     sprintf(cmdBuf,"load library ./%s", fname);
1875     return Tcl_Eval(interp, cmdBuf);
1876 }
1877
1878 /*
1879  * Enable or disable the execution of snippets
1880  */
1881 int mutationsCommand(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
1882 {
1883     if (argc != 2) {
1884         printf("Usage: mutations [enable|disable]\n");
1885         return TCL_ERROR;
1886     }
1887
1888     if (!haveApp()) return TCL_ERROR;
1889
1890     if (!strcmp(argv[1], "enable")) {
1891         appThread->setMutationsActive(true);
1892         return TCL_OK;
1893     }
1894
1895     if (!strcmp(argv[1], "disable")) {
1896         appThread->setMutationsActive(false);
1897         return TCL_OK;
1898     }
1899
1900     printf("Invalid option!\n"); 
1901     return TCL_ERROR;
1902 }
1903
1904 /*
1905  * Remove all or n'th function call in the input function
1906  */
1907 int removeCommand(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
1908 {
1909     if (argc != 2) {
1910         printf("Usage: removecall <function>[:n]\n");
1911         return TCL_ERROR;
1912     }
1913
1914     if (!haveApp()) return TCL_ERROR;
1915
1916     int n = -1;
1917     char *ptr = strchr(argv[1],':');
1918     if (ptr) {
1919         *ptr = '\0';
1920         n = atoi(ptr+1) - 1;
1921         if (n == -1) {
1922                 printf("Invalid number is entered!\n");
1923                 return TCL_ERROR;
1924         }
1925     }
1926
1927     BPatch_Vector<BPatch_point *> *points = appImage->findProcedurePoint(argv[1], 
1928                                                                         BPatch_subroutine);
1929     if (points == NULL) {
1930         printf("Could not locate function %s\n", argv[1]);
1931         return TCL_ERROR;
1932     }
1933
1934     if (points->size() == 0) {
1935         printf("Function %s has no calls!\n", argv[1]);
1936         return TCL_ERROR;
1937     }
1938
1939     if (n > points->size()) {
1940         printf("Function %s does not have %d calls!\n", argv[1], n);
1941         return TCL_ERROR;
1942     }
1943
1944     if (n == -1) {
1945         //Remove all function calls
1946         for(int i=0; i<points->size(); ++i) {
1947                 if (!appThread->removeFunctionCall(*((*points)[i])) ) {
1948                         printf("Unable to remove call %d !\n", i);
1949                         return TCL_ERROR;
1950                 }
1951         }
1952         return TCL_OK;
1953     }
1954
1955     //Remove n'th function call
1956     if (!appThread->removeFunctionCall(*((*points)[n])) ) {
1957         printf("Unable to remove call %d !\n", n);
1958         return TCL_ERROR;
1959     }
1960
1961     return TCL_OK;
1962 }
1963
1964 /*
1965  * Write the in-memory version of the program to the specified file
1966  */
1967 int dumpCommand(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
1968 {
1969     if (argc != 2) {
1970         printf("Usage: dump <file name>\n");
1971         return TCL_ERROR;
1972     }
1973
1974     if (!haveApp()) return TCL_ERROR;
1975
1976     appThread->dumpImage(argv[1]);
1977
1978     return TCL_OK;
1979 }
1980
1981 /*
1982  * remove all the code inserted into target program
1983  */
1984 int detachCommand(ClientData cd, Tcl_Interp *interp, int argc, char *argv[])
1985 {
1986     if (argc != 1) {
1987         printf("Usage: detach\n");
1988         return TCL_ERROR;
1989     }
1990
1991     if (!haveApp()) return TCL_ERROR;
1992
1993     appThread->detach(true);
1994
1995     return TCL_OK;
1996 }
1997
1998 //
1999 //
2000 int Tcl_AppInit(Tcl_Interp *interp)
2001 {
2002     if (Tcl_Init(interp) == TCL_ERROR) {
2003         return TCL_ERROR;
2004     }
2005     
2006     Tcl_CreateCommand(interp, "at", instStatement, NULL, NULL);
2007     Tcl_CreateCommand(interp, "break", condBreak, NULL, NULL);
2008     Tcl_CreateCommand(interp, "declare", newVar, NULL, NULL);
2009     Tcl_CreateCommand(interp, "listbreak", listBreak, NULL, NULL);
2010     Tcl_CreateCommand(interp, "deletebreak", deleteBreak, NULL, NULL);
2011     Tcl_CreateCommand(interp, "help", help, NULL, NULL);
2012     Tcl_CreateCommand(interp, "kill", killApp, NULL, NULL);
2013     Tcl_CreateCommand(interp, "load", loadCommand, NULL, NULL);
2014     Tcl_CreateCommand(interp, "run", runApp, NULL, NULL);
2015     Tcl_CreateCommand(interp, "print", printVar, NULL, NULL);
2016     Tcl_CreateCommand(interp, "whatis", whatisVar, NULL, NULL);
2017     Tcl_CreateCommand(interp, "show", showCommand, NULL, NULL);
2018     Tcl_CreateCommand(interp, "count", countCommand, NULL, NULL);
2019     Tcl_CreateCommand(interp, "replace", replaceCommand, NULL, NULL);
2020     Tcl_CreateCommand(interp, "trace", traceCommand, NULL, NULL);
2021     Tcl_CreateCommand(interp, "untrace", untraceCommand, NULL, NULL);
2022     Tcl_CreateCommand(interp, "add", addCommand, NULL, NULL);
2023     Tcl_CreateCommand(interp, "mutations", mutationsCommand, NULL, NULL);
2024     Tcl_CreateCommand(interp, "removecall", removeCommand, NULL, NULL);
2025     //Tcl_CreateCommand(interp, "dump", dumpCommand, NULL, NULL);
2026     Tcl_CreateCommand(interp, "detach", detachCommand, NULL, NULL);
2027
2028     bpatch.registerErrorCallback(errorFunc);
2029     bpatch.setTypeChecking(false);
2030     bpatch.registerExitCallback(&exitCallback);
2031
2032     return TCL_OK;
2033 }
2034
2035 int main(int argc, char *argv[])
2036 {
2037     if (argc >= 2 && !strcmp(argv[1], "-debug")) {
2038         printf("parser debug enabled\n");
2039         dynerdebug = 1;
2040     }
2041
2042     Tcl_Main(argc, argv, Tcl_AppInit);
2043     return 0;
2044 }