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