These changes only apply to Solaris, Linux x86 and AIX.
[dyninst.git] / dyner / src / dyner.C
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <tcl.h>
5
6 #if defined(i386_unknown_nt4_0)
7 #include <windows.h>
8 #include <winbase.h>
9 #else
10 #include <unistd.h>
11 #include <signal.h>
12 #endif
13
14 #include "dynerList.h"
15 #include "BPatch.h"
16 #include "BPatch_type.h"
17 #include "BPatch_Vector.h"
18 #include "BPatch_thread.h"
19 #include "BPatch_snippet.h"
20 #include "breakpoint.h"
21
22 extern "C" {
23 #if !defined(i386_unknown_nt4_0)
24 #if !defined(i386_unknown_linux2_0)
25 #if !defined(ia64_unknown_linux2_4)
26         int usleep(useconds_t);
27 #endif
28 #endif
29 #endif
30
31         void set_lex_input(char *s);
32         int dynerparse();
33 }
34
35 bool stopFlag = false;
36 extern int dynerdebug;
37
38 int debugPrint = 0;
39 BPatch_point *targetPoint;
40 bool errorLoggingOff = false;
41 bool verbose = false;
42
43 // control debug printf statements
44 #define dprintf if (debugPrint) printf
45
46 class ListElem {
47 public:
48     int                      number;
49     char                     *function;
50     BPatch_procedureLocation where;
51     BPatch_callWhen          when;
52     BPatchSnippetHandle      *handle;
53 };
54
55 class BPListElem: public ListElem {
56 public:
57     char                 *condition;
58     int                      lineNum;
59
60     BPListElem(int _number, const char *_function,
61            BPatch_procedureLocation _where,
62                BPatch_callWhen _when, const char *_condition,
63                BPatchSnippetHandle *_handle, int _lineNum);
64     ~BPListElem();
65     void Print();
66 };
67
68 class runtimeVar {
69 public:
70     runtimeVar(BPatch_variableExpr *v, const char *n) { 
71         var = v, name = strdup(n);
72     }
73     BPatch_variableExpr *var;
74     char *name;
75     bool readValue(void *buf) { return var->readValue(buf); }
76 };
77
78 typedef enum { NORMAL, TRACE, COUNT } InstPointType;
79
80 class IPListElem: public ListElem {
81 public:
82     char                     *statement;
83     InstPointType            instType;
84
85     IPListElem(int _number, const char *_function,
86            BPatch_procedureLocation _where,
87                BPatch_callWhen _when, const char *_condition,
88                BPatchSnippetHandle *_handle, InstPointType _instType);
89     ~IPListElem();
90     void Print();
91 };
92
93 BPatch *bpatch;
94 BPatch_thread *appThread = NULL;
95 BPatch_image *appImage = NULL;
96 static BPatch_variableExpr *bpNumber = NULL;
97 static int bpCtr = 1;
98 static int ipCtr = 1;
99 static DynerList<BPListElem *> bplist;
100 static DynerList<IPListElem *> iplist;
101 static DynerList<runtimeVar *> varList;
102 int whereAmINow = -1;/*ccw 10 mar 2004 : this holds the index of the current stackframe for where, up, down*/
103
104 #if !defined(i386_unknown_nt4_0)
105
106 //Ctrl-C signal handler
107 void  INThandler(int sig)
108 {
109      signal(sig, SIG_IGN);
110      signal(SIGINT, INThandler);
111      stopFlag = true;
112 }
113 #endif
114
115 bool name2loc(const char *s, BPatch_procedureLocation &where,
116               BPatch_callWhen &when)
117 {
118     if (!strcmp(s, "entry")) {
119         where = BPatch_entry;
120         when = BPatch_callBefore;
121     } else if (!strcmp(s, "exit")) {
122         where = BPatch_exit;
123         /* This is not supported anymore!
124         when = BPatch_callBefore;
125         */
126         when = BPatch_callAfter;
127     } else if (!strcmp(s, "preCall")) {
128         where = BPatch_subroutine;
129         when = BPatch_callBefore;
130     } else if (!strcmp(s, "postCall")) {
131         where = BPatch_subroutine;
132         when = BPatch_callAfter;
133     } else {
134         return false;
135     }
136     return true;
137 }
138
139 char *loc2name(BPatch_procedureLocation where, BPatch_callWhen when)
140 {
141     switch (where) {
142       case BPatch_entry:
143         return "entry";
144       case BPatch_exit:
145         return "exit";
146       case BPatch_subroutine:
147         if (when == BPatch_callBefore) return "preCall";
148         else return "postCall";
149       default:
150         return "<error>";
151     };
152 }
153
154 BPListElem::BPListElem(int _number, const char *_function,
155     BPatch_procedureLocation _where, BPatch_callWhen _when,
156     const char *_condition,
157     BPatchSnippetHandle *_handle, int _lineNum)
158 {
159     number = _number;
160     function = strdup(_function);
161     where = _where;
162     when = _when;
163     if (_condition)
164         condition = strdup(_condition);
165     else
166         condition = NULL;
167     handle = _handle;
168     lineNum = _lineNum;
169 }
170
171 BPListElem::~BPListElem()
172 {
173     free(function);
174     if (condition) free(condition);
175 }
176
177 void BPListElem::Print()
178 {
179     printf("%2d: ", number);
180     if (lineNum) 
181         printf("%s:%d", function, lineNum);
182     else
183         printf("%s (%s)", function,
184                 loc2name(where, when));
185
186     if (condition)
187         printf(", condition %s\n", condition);
188     else
189         printf("\n");
190 }
191
192 IPListElem::IPListElem(int _number, const char *_function,
193     BPatch_procedureLocation _where, BPatch_callWhen _when, 
194     const char *_statement,
195     BPatchSnippetHandle *_handle, InstPointType _instType)
196 {
197     if (_instType == NORMAL)
198         number = _number;
199     else
200         number = -1;
201     function = strdup(_function);
202     where = _where;
203     when = _when;
204     statement = strdup(_statement);
205     handle = _handle;
206     instType = _instType;
207 }
208
209 IPListElem::~IPListElem()
210 {
211     free(function);
212     free(statement);
213     if (handle) {
214         if (appThread)
215                 appThread->deleteSnippet(handle);
216
217         delete handle;
218     }
219 }
220
221 void IPListElem::Print()
222 {
223     printf("%2d: %s (%s)-->%s\n", number, function, loc2name(where, when), statement);
224 }
225
226 BPListElem *removeBPlist(int n)
227 {
228   DynerList<BPListElem *>::iterator i;
229   BPListElem *ret = NULL;
230   for (i = bplist.begin(); i != bplist.end(); i++) {
231     if ((*i)->number == n) {
232       ret = *i;
233       bplist.erase(i);
234       break;
235     }
236   }
237   return NULL;
238 }
239
240 BPListElem *findBP(int n)
241 {
242     DynerList<BPListElem *>::iterator i;
243
244     for (i = bplist.begin(); i != bplist.end(); i++) {
245         if ((*i)->number == n) return (*i);
246     }
247
248     return NULL;
249 }
250
251 IPListElem *removeIP(int n)
252 {
253     DynerList<IPListElem *>::iterator i;
254     IPListElem *ret = NULL;
255
256     for (i = iplist.begin(); i != iplist.end(); i++) {
257         if ((*i)->number == n) {
258           ret = *i;
259           iplist.erase(i);
260           break;
261         }
262     }
263
264     return ret;
265 }
266
267 IPListElem *findIP(int n)
268 {
269     DynerList<IPListElem *>::iterator i;
270
271     for (i = iplist.begin(); i != iplist.end(); i++) {
272         if ((*i)->number == n) return (*i);
273     }
274
275     return NULL;
276 }
277
278 #define LIMIT_TO(name) if (argc < 2 || !strncmp(argv[1], name, strlen(name)))
279
280 int help(ClientData, Tcl_Interp *, int argc, TCLCONST char **argv)
281 {
282
283     LIMIT_TO("at") {
284         printf("at <function> [entry|exit|preCall|postCall] <statement> - insert statement\n");
285         printf("at termination <statement> - Execute <statement> at program exit callback\n");
286     }
287
288     LIMIT_TO("attach") {
289         printf("attach <pid> <program> - attach dyner to a running program\n");
290     }
291
292     LIMIT_TO("declare") {
293         printf("declare <type> <variable> - create a new variable of type <type>\n");
294     }
295
296     LIMIT_TO("delete") {
297         printf("deletebreak <breakpoint number ...> - delete breakpoint(s)\n");
298         printf("deleteinst <instpoint number ...> - delete intrumentation point(s)\n");
299     }
300
301     LIMIT_TO("break") {
302         printf("break <function> [entry|exit|preCall|postCall] [<condition>] - set a (conditional)\n");
303         printf("     break point at specified points of <function>\n");
304         printf("break <file name:line number> [<condition>] - set an arbitrary (conditional) break\n");
305         printf("     point at <line number> of <file name>\n");
306     }
307
308     LIMIT_TO("debugparse") {
309         printf("debugparse [enable | disable] - Turn on/off debug parsing of the mutatee programs\n");
310     }
311
312     LIMIT_TO("execute") {
313         printf("execute <statement> - Execute <statement> at the current point\n");
314     }
315
316     LIMIT_TO("list") {
317         printf("listbreak - list break points\n");
318         printf("listinst - list intrumentation points\n");
319     }
320         
321     LIMIT_TO("load") {
322         printf("load <program> [arguments] [< filename] [> filename] - load a program\n");
323         printf("load library <lib name> - load a dynamically linked library\n");
324         printf("load source <C++ file name> - Create a dynamically linked library from a \n");
325         printf("     C++ source file and load it to address space. All the functions and variables \n");
326         printf("     in the source file will be available for instrumentation\n");
327     }
328
329     LIMIT_TO("run") {
330         printf("run - run or continue the loaded program\n");
331     }
332
333     LIMIT_TO("show") {
334         printf("show [modules|functions|variables] - display module names, global functions\n");
335         printf("      and variables\n");
336         printf("show functions in <module> - display function names declared in <module>\n");
337         printf("show [parameters|variables] in <function> - display local variables or parameters of\n");
338         printf("     <function>\n");
339     }
340
341     LIMIT_TO("count") {
342         printf("count <function> - At the end of execution display how many times <function> is called\n");
343     }
344
345     LIMIT_TO("replace") {
346         printf("replace function <function1> with <function2> - Replace all calls to <function1> with\n");
347         printf("     calls to <function2>\n");
348         printf("replace call <function1>[:n] with <function2> - All the calls or the nth function call \n");
349         printf("     in <function1> are/is changed to the function <function2>\n");
350     }
351
352     LIMIT_TO("trace") {
353         printf("trace function <function> - Print a message at the entry and exit of <function>\n");
354         printf("trace functions in <module> - Print a message at the entry and exit of all functions\n");
355         printf("     declared in <module>\n");
356     }
357
358     LIMIT_TO("untrace") {
359         printf("untrace function <function> - Undo the effects of trace command for <function>\n");
360         printf("untrace functions in <module> - Undo the effects of trace command for all functions\n");
361         printf("     declared in <module>\n");
362     }
363
364     LIMIT_TO("mutations") {
365         printf("mutations [enable|disable] - Enable or disable the execution of snippets\n");
366     }
367
368     LIMIT_TO("removecall") {
369         printf("removecall <function>[:n] - Remove all the calls or n'th call in <function>\n");
370     }
371
372     LIMIT_TO("detach") {
373         printf("detach - remove all the code inserted into target program\n");
374     }
375
376     LIMIT_TO("source") {
377         printf("source <file name> - Execute dyner commands stored in the file <file name>\n");
378     }
379
380     LIMIT_TO("kill") {
381         printf("kill - Terminate the execution of target program\n");
382     }
383
384     LIMIT_TO("print") {
385         printf("print <Variable> - Display the data type and value of dyner variable\n");
386     }
387
388     LIMIT_TO("find") {
389         printf("find function <pattern> [in <module>] - Display a list of functions in the image matching <pattern>.  Regex search will be performed if <pattern> contains regex, with some limitations\n");
390     }
391
392     LIMIT_TO("verbose") {
393         printf("verbose - toggles verbose mode error reporting\n");
394     }
395     LIMIT_TO("whatis") {
396         printf("whatis <variable> [in <function>] - Display detailed information about\n");
397         printf("     variables in the target program. Local variables and parameters are\n");
398         printf("     searched in the <function>.\n");
399     }
400 #if defined(rs6000_ibm_aix4_1) || defined(sparc_sun_solaris2_4) || defined(i386_unknown_linux2_0) 
401     LIMIT_TO("where") {
402         printf("where - Print stack trace.\n");
403     }
404     LIMIT_TO("up"){
405         printf("up - Move up the stack trace\n");
406     }
407     LIMIT_TO("down"){
408         printf("down - Move down the stack trace\n");
409     }
410
411         LIMIT_TO("saveStart"){
412                 printf("saveStart - Call saveStart before 'save' to begin marking instrumentation\n");
413                 printf("        to be saved to the mutated binary. This must be called before save is\n");
414                 printf("        called.  Only instrumentation inserted after saveStart is called will be\n");
415                 printf("        saved in the mutated binary.\n");
416         }
417         LIMIT_TO("save"){
418                 printf("save <file name> - Save the currently loaded mutatee and its mutations to the\n");
419                 printf("        file <file name>.  Call 'saveStart' before 'save' to begin marking \n");
420                 printf("        instrumentation to be saved to the mutated binary\n");
421         } 
422 #endif
423
424     return TCL_OK;
425 }
426
427 bool haveApp()
428 {
429     if (appThread == NULL) {
430         fprintf(stderr, "No application loaded.\n");
431         return false;
432     }
433
434     if (appThread->isTerminated()) {
435         fprintf(stderr, "The application has exited.\n");
436         return false;
437     }
438
439     return true;
440 }
441
442 BPatch_module *FindModule(const char *name) {
443
444     //Locate the module using module name 
445     BPatch_Vector<BPatch_module *> *modules = appImage->getModules();
446
447     if (!modules) {
448         printf("Can not get module info !\n");
449         return NULL;
450     }
451
452     char modName[1024];
453     BPatch_module *module = NULL;
454
455     for(unsigned int i=0; i<modules->size(); ++i) {
456         (*modules)[i]->getName(modName, 1024);
457
458         if (!strcmp(modName, name)) {
459                 module = (*modules)[i];
460                 break;
461         }
462     }
463
464     if (!module) {
465         printf("Module %s is not found !\n", name);
466         return NULL;
467     }
468
469     return module;
470 }
471
472 int loadApp(const char *pathname, TCLCONST char **args)
473 {
474     printf("Loading \"%s\"\n", pathname);
475
476     if (appThread != NULL) delete appThread;
477     bplist.clear();
478     iplist.clear();
479     varList.clear();
480     appThread = bpatch->createProcess((char*)pathname, (char**)args);
481     bpNumber = NULL;
482
483     if (!appThread || appThread->isTerminated()) {
484         fprintf(stderr, "Unable to run test program.\n");
485         appThread = NULL;
486         return TCL_ERROR;
487     }
488
489     // Read the program's image and get an associated image object
490     appImage = appThread->getImage();
491
492     if (!appImage) return TCL_ERROR;
493
494     //Create type info
495     appImage->getModules();
496
497 #if !defined(i386_unknown_nt4_0)
498     // make it a member of its own process group
499     int ret = setpgid(0, getpid());
500     if (ret != 0) {
501         perror("setpgid");
502     }
503 #endif
504
505     return TCL_OK;
506
507 }
508
509
510 int loadLib(const char *libName) {
511     if (!haveApp()) return TCL_ERROR;
512
513     if (appThread->loadLibrary(libName))
514         return TCL_OK;
515
516     return TCL_ERROR;
517 }
518
519 int loadSource(const char *inp) {
520     if (!haveApp()) return TCL_ERROR;
521
522     //Create shared object file name
523     char* dupstr = strdup( inp );
524     char *ptr = strrchr(dupstr, '/');
525     if (ptr)
526         ptr++;
527     else
528         ptr = dupstr;
529
530     char fname[1024];
531     sprintf(fname, "./%s", ptr);
532
533     ptr = strrchr(fname+2, '.'); //Ignore first 2 chars ('./')
534     if (ptr)
535         sprintf(ptr+1,"so");
536     else
537         strcat(fname,".so");
538
539     //First ensure that there is no .so file for the input file
540     unlink(fname);
541     
542     //Create a shared object from input file
543     char cmdBuf[1024];
544     sprintf(cmdBuf,"g++ -g -fPIC -shared -o %s %s", fname, dupstr);
545
546     system(cmdBuf);
547
548     //Test whether or not shared object is created
549     FILE *fp = fopen(fname,"rb");
550     if (!fp) {
551         printf("Error in compilation of %s\n", dupstr);
552     free(dupstr);
553         return TCL_ERROR;
554     }
555     fclose(fp);
556
557     //Now dynamically link the file
558     free(dupstr);
559     return loadLib(fname);
560 }
561
562 int loadCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
563 {
564     if (argc == 3) {
565         if (!strcmp(argv[1], "library"))
566                 return loadLib(argv[2]);
567         if (!strcmp(argv[1], "source"))
568                 return loadSource(argv[2]);
569     }
570
571     if (argc < 2) {
572         printf("Usage load <program> [<arguments>]\n");
573         printf("or    load library <lib name>\n");
574         printf("or    load source <C++ file name>\n");
575         return TCL_ERROR;
576     }
577
578     return loadApp(argv[1], &argv[1]);
579 }
580
581 int attachPid(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
582 {
583     int pid;
584     const char *pathName = "";
585
586     if ((argc < 2) || (argc > 3)) {
587         printf("Usage attach <pid> <program>\n");
588         return TCL_ERROR;
589     }
590
591     if (appThread != NULL) delete appThread;
592     bplist.clear();
593     iplist.clear();
594     varList.clear();
595
596     pid = atoi(argv[1]);
597     if (argc == 3) pathName = argv[2];
598
599     appThread = bpatch->attachProcess(pathName, pid);
600     bpNumber = NULL;
601
602     if (!appThread || !appThread->getImage() || appThread->isTerminated()) {
603         fprintf(stderr, "Unable to attach to pid %d\n", pid);
604         appThread = NULL;
605         return TCL_ERROR;
606     }
607
608     // Read the program's image and get an associated image object
609     appImage = appThread->getImage();
610
611     if (!appImage) return TCL_ERROR;
612
613     //Create type info
614     appImage->getModules();
615
616     return TCL_OK;
617 }
618
619
620 int listBreak(ClientData, Tcl_Interp *, int, TCLCONST char **)
621 {
622     if (!haveApp()) return TCL_ERROR;
623
624     BPListElem *curr;
625     DynerList<BPListElem *>::iterator i;
626
627     for (i = bplist.begin(); i != bplist.end(); i++) {
628         curr = (BPListElem *) *i;
629         curr->Print();
630     }
631
632     return TCL_OK;
633 }
634
635 int listInstrument(ClientData, Tcl_Interp *, int, TCLCONST char **)
636 {
637     if (!haveApp()) return TCL_ERROR;
638
639     IPListElem *curr;
640     DynerList<IPListElem *>::iterator i;
641
642     for (i = iplist.begin(); i != iplist.end(); i++) {
643         curr = (IPListElem *) *i;
644         if (curr->instType == NORMAL)
645                 curr->Print();
646     }
647
648     return TCL_OK;
649 }
650
651 int deleteBreak(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
652 {
653     if (!haveApp()) return TCL_ERROR;
654
655     if (argc < 2) {
656         printf("Specify breakpoint(s) to delete.\n");
657         return TCL_ERROR;
658     }
659
660     int ret = TCL_OK;
661     for (int j = 1; j < argc; j++) {
662         int n = atoi(argv[j]);
663
664         BPListElem *i = removeBPlist(n);
665         if (i == NULL) {
666             printf("No such breakpoint: %d\n", n);
667             ret = TCL_ERROR;
668         } else {
669             appThread->deleteSnippet(i->handle);
670             delete i;
671             printf("Breakpoint %d deleted.\n", n);
672         }
673     }
674
675     return ret;
676 }
677
678 int deleteInstrument(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
679 {
680     if (!haveApp()) return TCL_ERROR;
681
682     if (argc < 2) {
683         printf("Specify intrument number(s) to delete.\n");
684         return TCL_ERROR;
685     }
686
687     int ret = TCL_OK;
688     for (int j = 1; j < argc; j++) {
689         int n = atoi(argv[j]);
690
691         IPListElem *i = removeIP(n);
692         if (i == NULL) {
693             printf("No such intrument point: %d\n", n);
694             ret = TCL_ERROR;
695         } else {
696             delete i;
697             printf("Instrument number %d deleted.\n", n);
698         }
699     }
700
701     return ret;
702 }
703
704 void setWhereAmINow(){
705         BPatch_Vector<BPatch_frame> callStack;
706
707         appThread->getCallStack(callStack);
708
709         whereAmINow = callStack.size()-1;
710
711 }
712
713
714 int runApp(ClientData, Tcl_Interp *, int, TCLCONST char **)
715 {
716     if (!haveApp()) return TCL_ERROR;
717
718     if (bpNumber) {
719         int inval = -1;
720         bpNumber->writeValue(&inval);
721     }
722
723     // Start of code to continue the process.
724     dprintf("starting program execution.\n");
725     appThread->continueExecution();
726         
727         whereAmINow = -1 ; //ccw 10 mar 2004 : i dont know where i will be when i stop
728
729     while (!appThread->isStopped() && !appThread->isTerminated() && !stopFlag)
730 #if defined(i386_unknown_nt4_0)
731         Sleep(1);
732 #else
733         usleep(250);
734 #endif
735
736     if (stopFlag) {
737         stopFlag = false;
738         appThread->stopExecution();
739         setWhereAmINow(); //ccw 10 mar 2004 : find myself
740     }
741
742     int bp = -1;
743     if (bpNumber) bpNumber->readValue(&bp);
744
745     if (appThread->isTerminated()) {
746         printf("\nApplication exited.\n");
747     } else if (appThread->isStopped() && bp > 0) {
748                 printf("\nStopped at break point %d.\n", bp);
749                 ListElem *i = findBP(bp);
750                 if (i != NULL) {
751                 BPListElem *curr = (BPListElem *) i;
752                     curr->Print();
753                 }
754     } else {
755         printf("\nStopped.\n");
756     }
757         
758     return TCL_OK;
759 }
760
761 int killApp(ClientData, Tcl_Interp *, int, TCLCONST char **)
762 {
763     if (!haveApp()) return TCL_ERROR;
764
765     appThread->terminateExecution();
766
767     return TCL_OK;
768 }
769
770 #if defined(sparc_sun_solaris2_4) || defined(i386_unknown_linux2_0) || defined(rs6000_ibm_aix4_1)
771
772 bool saveWorldStart =false;
773
774 int saveStart(ClientData, Tcl_Interp *, int argc, TCLCONST char **argv){
775
776         if (!haveApp()) return TCL_ERROR;
777
778
779         saveWorldStart=true;
780         appThread->enableDumpPatchedImage();
781         return TCL_OK;
782
783 }
784
785 int saveWorld(ClientData, Tcl_Interp *, int argc, TCLCONST char **argv){
786         if(argc != 2){
787                 printf(" Usage: save <filename>\n");
788                 return TCL_ERROR;
789         }
790         if(!saveWorldStart){
791                 printf("Call saveStart before issuing instrumentation to save\n");
792                 return TCL_ERROR;
793         }
794         char* directoryName = appThread->dumpPatchedImage(argv[1]);
795         printf(" saved in %s \n", directoryName);
796         delete [] directoryName;
797         
798         return TCL_OK;
799 }
800 #endif
801
802 extern BPatch_snippet *parse_result;
803 int condBreak(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
804 {
805     if (argc < 2) {
806         printf("Usage: break <function> [entry|exit|preCall|postCall] [<condition>]\n");
807         printf("or     break <file name:line number> [<condition>]\n");
808         return TCL_ERROR;
809     }
810
811     if (!haveApp()) return TCL_ERROR;
812
813     if (bpNumber == NULL) {
814         bpNumber = appThread->malloc(*appImage->findType("int"));
815         if (bpNumber == NULL) {
816             fprintf(stderr, "Unable to allocate memory in the inferior process.\n");
817             exit(1);
818         }
819     }
820
821     int expr_start = 2;
822     int lineNum = 0;
823     BPatch_procedureLocation where;
824     BPatch_callWhen when;
825
826     BPatch_Vector<BPatch_point *> *points;
827     char *ptr = strchr(argv[1],':');
828     if (ptr) {
829         //Arbitrary break point, first find module name
830         expr_start = 2;
831         where = BPatch_entry;
832         when = BPatch_callBefore;
833         *ptr = '\0';
834         lineNum = atoi(ptr+1);
835         BPatch_Vector<unsigned long> absAddrVec;
836
837         if (!appImage->getLineToAddr(argv[1], lineNum, absAddrVec, true)) {
838                 printf("Can not get arbitrary break point address!\n");
839                 return TCL_ERROR;
840         }
841         points = new BPatch_Vector<BPatch_point *>;
842         //Find BPatch_point from the first absolute address
843         points->push_back(appImage->createInstPointAtAddr((void *)absAddrVec[0]));
844     }
845     else {
846         if ( (argc > 2) && name2loc(argv[2], where, when)) {
847                 expr_start = 3;
848         } else {
849                 where = BPatch_entry;
850                 when = BPatch_callBefore;
851         }
852
853         BPatch_Vector<BPatch_function *> found_funcs;
854         if ((NULL == appImage->findFunction(argv[1], found_funcs)) 
855             || (0 == found_funcs.size())) {
856           printf("%s[%d]:  CANNOT CONTINUE  :  %s not found\n", __FILE__, __LINE__, argv[1]);
857           return TCL_ERROR;
858         }
859
860         if (1 < found_funcs.size()) {
861           printf("%s[%d]:  WARNING  :  %d functions called '%s'found.  Using the first\n", 
862                  __FILE__, __LINE__, 
863                  found_funcs.size(), argv[1]);
864         }
865         
866         points = found_funcs[0]->findPoint(where);
867
868         if (points == NULL) {
869                 printf("Unable to locate points for function %s\n", argv[1]);
870                 return TCL_ERROR;
871         }
872     }
873
874     char *line_buf = NULL;
875
876     if (argc > 3) {
877         // Count up how large a buffer we need for the whole line
878         int line_len = 0;
879         int i = 0;
880         for (i = expr_start; i < argc; i++)
881                 line_len += strlen(argv[i]) + 1;
882         line_len++;
883         // Make the buffer and copy the line into it
884         line_buf = new char[line_len];
885         *line_buf = '\0';
886         for (i = expr_start; i < argc; i++) {
887                 strcat(line_buf, argv[i]);
888                 if (i != argc-1) strcat(line_buf, " ");
889         }
890
891         set_lex_input(line_buf);
892         if (dynerparse() != 0) {
893                 fprintf(stderr, "Breakpoint not set due to error.\n");
894                 delete line_buf;
895                 return TCL_ERROR;
896         }
897
898         if (parse_type != parsed_bool) {
899                 fprintf(stderr, "Breakpoint not set due error, expression not boolean.\n");
900                 delete line_buf;
901                 delete parse_result;
902                 return TCL_ERROR;
903         }
904     }
905
906     // Make a snippet to tell us which breakpoint it is
907     BPatch_arithExpr storeBPNum(BPatch_assign,
908                                 *bpNumber, BPatch_constExpr(bpCtr));
909
910     // Make a snippet to break at the breakpoint
911     BPatch_Vector<BPatch_function *> bpfv;
912     if (NULL == appImage->findFunction("DYNINSTbreakPoint", bpfv) || ! bpfv.size()) {
913       fprintf(stderr, "Unable to find function DYNINSTbreakPoint "
914               "(required for setting break points)\n");
915       if (argc > 3) {
916         delete parse_result;
917         delete line_buf;
918       }
919       return TCL_ERROR;
920     }
921
922     BPatch_function *breakFunc = bpfv[0];
923     if (breakFunc == NULL) {
924       fprintf(stderr, "Unable to find function DYNINSTbreakPoint "
925               "(required for setting break points)\n");
926       if (argc > 3) {
927         delete parse_result;
928         delete line_buf;
929       }
930       return TCL_ERROR;
931     }
932
933     BPatch_Vector<BPatch_snippet *> nullArgs;
934     BPatch_funcCallExpr callBreak(*breakFunc, nullArgs);
935
936     // store the break point number, then  break
937     BPatch_arithExpr doBreak(BPatch_seq, storeBPNum, callBreak);
938     
939     BPatch_snippet *brSnippet = (BPatch_snippet *) &doBreak;
940
941     if (argc > 3) {
942         // Call the break snippet conditionally
943         BPatch_ifExpr condBreak(*(BPatch_boolExpr *)parse_result, doBreak); 
944         brSnippet = (BPatch_snippet *) &condBreak; 
945         delete parse_result;
946     }
947
948     BPatchSnippetHandle *handle =
949         appThread->insertSnippet(*brSnippet, *points, when,BPatch_lastSnippet);
950     if (handle == 0) {
951         fprintf(stderr, "Error inserting snippet.\n");
952         if (line_buf) delete line_buf;
953         return TCL_ERROR;
954     }
955
956     BPListElem *bpl =
957         new BPListElem(bpCtr, argv[1], where, when, line_buf, handle, lineNum);
958     if (line_buf) delete line_buf;
959
960     bplist.push_back(bpl);
961
962     printf("Breakpoint %d set.\n", bpCtr);
963     bpCtr++;
964
965     return TCL_OK;
966 }
967 /*
968  * void printPtr( )
969  *
970  * This function recursively goes through the BPatch_type pointers until
971  * it gets to the base type and prints that name.  The base type can be
972  * a builtin type or an enum, struct, or union.  The default case handles
973  * unknown pointer types.  -- jdd 5/27/99
974  */
975 void printPtr( BPatch_type * type )
976 {
977   if( type->getDataClass() == BPatch_pointer ){
978     printPtr( type->getConstituentType() );
979     printf("*");
980   }
981   else if((type->getDataClass() == BPatch_scalar)||(type->getDataClass() == BPatch_built_inType)||
982         (type->getDataClass() == BPatchSymTypeRange)){
983     printf("%s ", type->getName());
984   }
985   else{
986     switch( type->getDataClass() ){
987     case BPatch_enumerated:
988       printf("enum %s ", type->getName());
989       break;
990     case BPatch_structure:
991       printf("struct %s ", type->getName());
992       break;
993     case BPatch_union:
994       printf("union %s ", type->getName());
995       break;
996     default:
997       printf("Undefined POINTER: %s", type->getName());
998       break;
999     }
1000   }
1001   
1002 }
1003 /*
1004  * printArray()
1005  *
1006  * This function prints arrays of various dimension, 1D to 3D. It first
1007  * checks how many dimensions the array is and then prints it out.
1008  * The default case handles the unknown. --jdd 5/27/99
1009  */
1010  
1011 void printArray(BPatch_type * type )
1012 {
1013   int j = 0;
1014   if(type->getConstituentType()){
1015     j++;
1016     if(type->getConstituentType()->getConstituentType()){
1017       j++;
1018       if(type->getConstituentType()->getConstituentType()->getConstituentType()){
1019         j++;
1020       }
1021     }
1022   }
1023   switch(j){
1024   case 3:
1025     
1026     //3D array
1027     printf("    %s is an array [%s..%s][%s..%s][%s..%s] of %s\n",
1028            type->getName(), type->getLow(), type->getHigh(),
1029            type->getConstituentType()->getLow(),
1030            type->getConstituentType()->getHigh(),
1031            type->getConstituentType()->getConstituentType()->getLow(),
1032            type->getConstituentType()->getConstituentType()->getHigh(),
1033            type->getConstituentType()->getConstituentType()->getConstituentType()->getName());
1034     break;
1035   case 2:
1036         
1037     //2D array
1038     printf("    %s is an array [%s..%s][%s..%s] of %s\n", type->getName(), 
1039            type->getLow(), type->getHigh(),
1040            type->getConstituentType()->getLow(),
1041            type->getConstituentType()->getHigh(),
1042            type->getConstituentType()->getConstituentType()->getName());
1043     break;
1044   case 1:
1045     printf("    %s is an array [%s..%s] of %s\n", type->getName(),
1046            type->getLow(), type->getHigh(), 
1047            type->getConstituentType()->getName());
1048     break;
1049   default:
1050     printf("Unable to process array %s\n", type->getName());
1051     break;
1052   }
1053 }
1054
1055 BPatch_snippet *termStatement = NULL;
1056
1057 void exitCallback(BPatch_thread *thread, BPatch_exitType) {
1058     if (termStatement == NULL)
1059         return;
1060
1061     BPatch_snippet *stmt = termStatement;
1062     termStatement = NULL;
1063     thread->oneTimeCode(*stmt);
1064     delete stmt;
1065 }
1066
1067 int instTermStatement(int argc, TCLCONST char *argv[])
1068 {
1069     int expr_start = 2;
1070
1071     // Count up how large a buffer we need for the whole line
1072     int line_len = 0;
1073     int i = 0;
1074     for (i = expr_start; i < argc; i++)
1075         line_len += strlen(argv[i]) + 1;
1076     line_len += 2;
1077     // Make the buffer and copy the line into it
1078     char *line_buf = new char[line_len];
1079     *line_buf = '\0';
1080     for (i = expr_start; i < argc; i++) {
1081         strcat(line_buf, argv[i]);
1082         if (i != argc-1) strcat(line_buf, " ");
1083     }
1084     strcat(line_buf, "\n");
1085
1086     // printf("calling parse of %s\n", line_buf);
1087     set_lex_input(line_buf);
1088     if (dynerparse() != 0) {
1089         fprintf(stderr, "Instrumentation not set due to error.\n");
1090         delete line_buf;
1091         return TCL_ERROR;
1092     }
1093
1094     if (parse_type != parsed_statement) {
1095         fprintf(stderr, "code not inserted, expression is not a statement.\n");
1096         delete line_buf;
1097         delete parse_result;
1098         return TCL_ERROR;
1099     }
1100
1101     termStatement = parse_result;
1102     return TCL_OK;
1103 }
1104
1105 int instStatement(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
1106 {
1107     if (!haveApp()) return TCL_ERROR;
1108
1109     if (argc < 3) {
1110         printf("Usage: at <function> [entry|exit|preCall|postCall] <statement>\n");
1111         printf("or     at termination <statement>\n");
1112         return TCL_ERROR;
1113     }
1114
1115     if (!strcmp(argv[1], "termination"))
1116         return instTermStatement(argc, argv);
1117
1118     int expr_start = 2;
1119     BPatch_procedureLocation where;
1120     BPatch_callWhen when;
1121
1122     if (name2loc(argv[2], where, when)) {
1123         expr_start = 3;
1124     } else {
1125         where = BPatch_entry;
1126         when = BPatch_callBefore;
1127     }
1128     BPatch_Vector<BPatch_function *> bpfv;
1129     if (NULL == appImage->findFunction(argv[1], bpfv) || !bpfv.size()) {
1130         fprintf(stderr, "Unable to locate function: %s\n", argv[1]);
1131         return TCL_ERROR;
1132     }
1133
1134     BPatch_function *func = bpfv[0]; 
1135     if (func == NULL) {
1136         fprintf(stderr, "Unable to locate function: %s\n", argv[1]);
1137         return TCL_ERROR;
1138     }
1139
1140     BPatch_Vector<BPatch_point *> *points = func->findPoint(where);
1141
1142     if (points == NULL) {
1143         fprintf(stderr, "Unable to locate function: %s\n", argv[1]);
1144         return TCL_ERROR;
1145     }
1146
1147     //Assign targetPoint using function entry point
1148     targetPoint = (*(func->findPoint(BPatch_entry)))[0];
1149
1150     InstPointType instType = NORMAL;
1151     if (!strcmp(argv[argc-1], "trace")) {
1152         //This statement is used for tracing the functions
1153         instType = TRACE;
1154         argc--;
1155     }
1156     else if (!strcmp(argv[argc-1], "count")) {
1157         //This statement is used for counting the functions
1158         instType = COUNT;
1159         argc--;
1160     }
1161
1162     // Count up how large a buffer we need for the whole line
1163     int line_len = 0;
1164     int i = 0;
1165     for (i = expr_start; i < argc; i++)
1166         line_len += strlen(argv[i]) + 1;
1167     line_len += 2;
1168     // Make the buffer and copy the line into it
1169     char *line_buf = new char[line_len];
1170     *line_buf = '\0';
1171     for (i = expr_start; i < argc; i++) {
1172         strcat(line_buf, argv[i]);
1173         if (i != argc-1) strcat(line_buf, " ");
1174     }
1175     // strcat(line_buf, "\n");
1176
1177     // printf("calling parse of %s\n", line_buf);
1178     set_lex_input(line_buf);
1179     if (dynerparse() != 0) {
1180         fprintf(stderr, "Instrumentation not set due to error.\n");
1181         delete line_buf;
1182         targetPoint = NULL;
1183         return TCL_ERROR;
1184     }
1185
1186     targetPoint = NULL;
1187
1188     if (parse_type != parsed_statement) {
1189         fprintf(stderr, "code not inserted, expression is not a statement.\n");
1190         delete line_buf;
1191         delete parse_result;
1192         return TCL_ERROR;
1193     }
1194
1195     BPatchSnippetHandle *handle =
1196         appThread->insertSnippet(*parse_result, *points, when,BPatch_lastSnippet);
1197     if (handle == 0) {
1198         fprintf(stderr, "Error inserting snippet.\n");
1199         delete line_buf;
1200         return TCL_ERROR;
1201     }
1202
1203     IPListElem *snl =
1204         new IPListElem(ipCtr, argv[1], where, when, line_buf, handle, instType);
1205     delete line_buf;
1206
1207     iplist.push_back(snl);
1208
1209     if (instType == NORMAL) {
1210         printf("Instrument point %d set.\n", ipCtr);
1211         ipCtr++;
1212     }
1213
1214     return TCL_OK;
1215 }
1216
1217 int execStatement(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
1218 {
1219     if (!haveApp()) return TCL_ERROR;
1220
1221     if (argc < 2) {
1222         printf("Usage: execute <statement>\n");
1223         return TCL_ERROR;
1224     }
1225
1226     int expr_start = 1;
1227
1228     // Count up how large a buffer we need for the whole line
1229     int line_len = 0;
1230     int i = 0;
1231     for (i = expr_start; i < argc; i++)
1232         line_len += strlen(argv[i]) + 1;
1233     line_len += 2;
1234     // Make the buffer and copy the line into it
1235     char *line_buf = new char[line_len];
1236     *line_buf = '\0';
1237     for (i = expr_start; i < argc; i++) {
1238         strcat(line_buf, argv[i]);
1239         if (i != argc-1) strcat(line_buf, " ");
1240     }
1241     strcat(line_buf, "\n");
1242
1243     //printf("calling parse of %s\n", line_buf);
1244     set_lex_input(line_buf);
1245     if (dynerparse() != 0) {
1246         fprintf(stderr, "Execution can not be done due to error.\n");
1247         delete line_buf;
1248         return TCL_ERROR;
1249     }
1250
1251     if (parse_type != parsed_statement) {
1252         fprintf(stderr, "Syntax error, expression is not a statement.\n");
1253         delete line_buf;
1254         delete parse_result;
1255         return TCL_ERROR;
1256     }
1257
1258     appThread->oneTimeCode(*parse_result);
1259     delete parse_result;
1260     delete line_buf;
1261
1262     return TCL_OK;
1263 }
1264
1265 void printVarRecursive(BPatch_variableExpr *var, int level)
1266 {
1267     int iVal;
1268     int pVal;
1269     char cVal;
1270     float fVal;
1271
1272     BPatch_dataClass dc;
1273     BPatch_type *type = (BPatch_type *) var->getType();
1274
1275         if( !var ){
1276                 fprintf(stderr," var is NULL\n");
1277                 return;
1278         }
1279     dc = type->getDataClass();
1280     if (!strcmp(type->getName(), "int")) {
1281         /* print out the integer */
1282         var->readValue((void *) &iVal);
1283         printf("%d\n", iVal);
1284     } else if (!strcmp(type->getName(), "float")) {
1285         /* print out the float */
1286         var->readValue((void *) &fVal);
1287         printf("%f\n", fVal);
1288     }else if(!strcmp(type->getName(), "char")) {
1289         /* print out the char*/
1290         var->readValue((void *) &cVal);
1291         printf("%c\n", cVal);
1292
1293     } else if (dc == BPatch_pointer) {
1294         /* print out the float */
1295         var->readValue((void *) &pVal);
1296         printf("0x%x\n", pVal);
1297     } else if (dc == BPatch_structure) {
1298         printf("struct {\n");
1299         level++;
1300         BPatch_Vector<BPatch_variableExpr *> *fields = var->getComponents();
1301         for (unsigned int i=0; i < fields->size(); i++) {
1302              BPatch_variableExpr *fieldVar = (*fields)[i];
1303              for (int i=0;i < level; i++) printf("    ");
1304              printf("%s = ", fieldVar->getName());
1305              printVarRecursive(fieldVar, level);
1306         }
1307         level--;
1308         printf("}\n");
1309     } else if (dc == BPatch_array) {
1310         printf("<arrays not yet implemented>\n");
1311     } else {
1312         printf("<unknown type>\n" );
1313     }
1314 }
1315
1316 #if defined(rs6000_ibm_aix4_1) || defined(sparc_sun_solaris2_4) || defined(i386_unknown_linux2_0)  
1317 void printStackFrame(int index, BPatch_Vector<BPatch_frame> &callStack, char *funcName){
1318
1319         printf("#%d: (0x%x)\t%s (fp: 0x%x)\n", index,callStack[index].getPC(),funcName ,callStack[index].getFP());
1320
1321 }
1322
1323 int whereUp(ClientData, Tcl_Interp *, int, TCLCONST char *argv[])
1324 {
1325         BPatch_Vector<BPatch_frame> callStack;
1326         char funcName [1024];
1327         int index=0;
1328
1329
1330         appThread->getCallStack(callStack);
1331
1332         if(whereAmINow < (callStack.size()-1) ){
1333                 whereAmINow++;
1334         }
1335
1336         printf("     ");
1337
1338         if(callStack[whereAmINow].findFunction()){
1339
1340                 BPatch_Vector<BPatch_point *> *points = callStack[index].findFunction()->findPoint(BPatch_subroutine);
1341
1342                 if ( points  && points->size() > 0){  //linux gets weird here
1343                                 
1344                         targetPoint = (*points)[0];
1345                 }
1346                 callStack[whereAmINow].findFunction()->getName(funcName, 1024);
1347
1348                 printStackFrame(whereAmINow, callStack, funcName);
1349
1350
1351         }else{
1352                 printStackFrame(whereAmINow, callStack, "<<FAILED TO FIND FUNCTION>>");
1353         }
1354         return TCL_OK;
1355 }
1356
1357 int whereDown(ClientData, Tcl_Interp *, int, TCLCONST char *argv[])
1358 {
1359         BPatch_Vector<BPatch_frame> callStack;
1360         char funcName [1024];
1361         int index=0;
1362
1363         if( whereAmINow > 1) {
1364                 whereAmINow-- ;
1365         }
1366
1367
1368         appThread->getCallStack(callStack);
1369         printf("     ");
1370
1371         if(callStack[whereAmINow].findFunction()){
1372
1373                 BPatch_Vector<BPatch_point *> *points = callStack[index].findFunction()->findPoint(BPatch_subroutine);
1374
1375                 if ( points  && points->size() > 0){  //linux gets weird here
1376                         
1377                         targetPoint = (*points)[0];
1378                 }
1379
1380                 callStack[whereAmINow].findFunction()->getName(funcName, 1024);
1381
1382                 printStackFrame(whereAmINow, callStack, funcName);
1383
1384
1385         }else{
1386                 printStackFrame(whereAmINow, callStack, "<<FAILED TO FIND FUNCTION>>");
1387         }
1388         return TCL_OK;
1389 }
1390
1391 int where(ClientData, Tcl_Interp *, int, TCLCONST char *argv[])
1392 {
1393         BPatch_Vector<BPatch_frame> callStack;
1394         char funcName [1024];
1395         int index=0;
1396
1397         appThread->getCallStack(callStack);
1398         index = 1; 
1399         while(index < callStack.size() -1){
1400
1401                 if( (whereAmINow == -1 && index == 1) || ( whereAmINow == index ) ){
1402                         printf(" --> ");
1403                         whereAmINow = index;
1404                 }else{
1405                         printf("     ");
1406                 }
1407
1408                 if(callStack[index].findFunction()){
1409                         BPatch_Vector<BPatch_point *> *points = callStack[index].findFunction()->findPoint(BPatch_subroutine);
1410
1411                         if ( points  && points->size() > 0){  //linux gets weird here
1412                                 
1413                                 targetPoint = (*points)[0];
1414                         }
1415
1416
1417                         callStack[index].findFunction()->getName(funcName, 1024);
1418
1419                         printStackFrame(index, callStack, funcName);
1420
1421
1422                 }else{
1423                         
1424                         printStackFrame(index, callStack, "<<FAILED TO FIND FUNCTION>>");
1425                 }
1426                 index ++;
1427         }
1428         return TCL_OK;
1429 }
1430 #endif
1431
1432 #if defined(rs6000_ibm_aix4_1) || defined(sparc_sun_solaris2_4) || defined(i386_unknown_linux2_0)   
1433
1434 BPatch_variableExpr *findLocalVariable(const char *name, bool printError)
1435 {
1436         BPatch_variableExpr *var=NULL;
1437 #ifdef mips_sgi_irix6_4
1438         /* mips_sgi_irix6_4 does not support local vars but if it does we are ready! */
1439         long index;
1440 #define CASTOFFSET long
1441
1442 #else
1443         int index;
1444 #define CASTOFFSET int
1445
1446 #endif
1447         int offset;
1448
1449         /* if we have a local context, use that. otherwise use the top of the call stack */
1450         if( whereAmINow == -1 ){
1451
1452                 index = 1;
1453         }else{
1454                 index = whereAmINow;
1455         }
1456
1457         BPatch_Vector<BPatch_frame> callStack;
1458         char funcName [1024];
1459         BPatch_variableExpr *tmpVar;
1460
1461         appThread->getCallStack(callStack);
1462
1463         if(     callStack[index].findFunction()){
1464
1465                 BPatch_Vector<BPatch_point *> *points = callStack[index].findFunction()->findPoint(BPatch_entry);//ccw 10 mar 2004 was subroutine
1466
1467                 if ( points  && points->size() > 0){ 
1468                                 
1469                         targetPoint = (*points)[0];
1470
1471                         callStack[index].findFunction()->getName(funcName, 1024);
1472
1473                         tmpVar = appImage->findVariable(*targetPoint, name);
1474                         targetPoint = NULL;
1475
1476
1477                         if (tmpVar && 
1478 #ifdef rs6000_ibm_aix4_1
1479                                 (((int)tmpVar->getBaseAddr()) < 0x1000) ) {
1480
1481 #else
1482                                 ( ((CASTOFFSET) (tmpVar->getBaseAddr())) < 0) ) {
1483
1484 #endif
1485                                 offset = (CASTOFFSET) (tmpVar->getBaseAddr());
1486
1487
1488
1489 #ifdef sparc_sun_solaris2_4
1490                                 index ++; /* ccw 9 mar 2004 WHY DO I NEED TO DO THIS ?*/
1491 #endif
1492                         
1493                                 /* WARNING: the function BPatch_thread::lowlevel_process() is risky, it should go away
1494                                    But i need to build a variable that points to a specific address, and I can not find
1495                                    a better way to do it right now
1496                                  */     
1497                                 var = new BPatch_variableExpr(tmpVar->getName(), appThread->lowlevel_process(),
1498                                         (void*) ( ((CASTOFFSET) (callStack[index].getFP())) +offset), tmpVar->getType() );      
1499
1500 #ifdef sparc_sun_solaris2_4 
1501                                 index --;  
1502 #endif
1503                                 whereAmINow = index; /* set local context just in case */
1504
1505                                 return var;
1506                         }
1507                         
1508                 }
1509
1510                 
1511         }
1512
1513         if (printError) printf("Unable to locate local variable %s\n", name);
1514         return NULL;
1515 }
1516 #endif
1517
1518 int printVar(ClientData, Tcl_Interp *, int, TCLCONST char *argv[])
1519 {
1520     //if (!haveApp()) return TCL_ERROR;
1521         bool found = false;
1522         BPatch_variableExpr *var; 
1523 #if defined(rs6000_ibm_aix4_1) || defined(sparc_sun_solaris2_4) || defined(i386_unknown_linux2_0)  
1524
1525         var = findLocalVariable(argv[1],false);
1526
1527         if( var) {
1528         
1529                 printf("Local  Variable:\t%s = ", argv[1]);
1530                 printVarRecursive(var, 1);
1531                 found = true;
1532         }
1533
1534 #endif
1535
1536         var = findVariable(argv[1],false);
1537         if( var ) {
1538                 printf("Global Variable:\t%s = ", argv[1]);
1539                 printVarRecursive(var, 1);
1540                 found = true;
1541         }
1542
1543         if( ! found  ){
1544                 printf("%s is not defined\n", argv[1]);
1545                 return TCL_ERROR;
1546         }
1547     
1548         return TCL_OK;
1549 }
1550
1551 /*
1552  * declare <type> <variable name>
1553  */
1554 int newVar(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
1555 {
1556     if (argc != 3) {
1557         printf("Usage: declare <type> <variable name>\n");
1558         return TCL_ERROR;
1559     }
1560
1561     if (!haveApp()) return TCL_ERROR;
1562
1563     BPatch_type *type = appImage->findType(argv[1]);
1564     if (!type) {
1565         printf("type %s is not defined\n", argv[1]);
1566         return TCL_ERROR;
1567     }
1568
1569     BPatch_variableExpr *newVar = appThread->malloc(*type);
1570     if (!newVar) {
1571         printf("Unable to create variable.\n");
1572         return TCL_ERROR;
1573     }
1574
1575     varList.push_back(new runtimeVar(newVar, argv[2]));
1576
1577     return TCL_OK;
1578 }
1579
1580
1581 BPatch_variableExpr *findVariable(const char *name, bool printError)
1582 {
1583     BPatch_variableExpr *var;
1584     DynerList<runtimeVar *>::iterator i;
1585
1586     // First look for runtime created variables
1587     for (i = varList.begin(); i != varList.end(); i++) {
1588         if (!strcmp(name, (*i)->name)) {
1589             var = new BPatch_variableExpr(*((*i)->var));
1590             return (var);
1591         }
1592     }
1593
1594     if(targetPoint){
1595         var = appImage->findVariable(*targetPoint, name);
1596         if(var) {
1597                 return var;
1598         }
1599     }
1600
1601     // Check global vars in the mutatee
1602     errorLoggingOff = true;
1603     var = appImage->findVariable(name);
1604     errorLoggingOff = false;
1605
1606     if (var) return var;
1607
1608     if (printError) printf("Unable to locate variable %s\n", name);
1609     return NULL;
1610 }
1611
1612 /* 
1613  * int whatisParam()
1614  *
1615  * This function is an extension to the "whatis" command.  This function
1616  * processes the command: whatis -scope <function> <variable>. If the
1617  * <function> is undefined then TCL_ERROR is returned.  Otherwise, the
1618  * local variable collection is searched first; followed by the parameter
1619  * collection; and finally the Global collection is searched last. If the
1620  * <variable> is not found, then "<variable> is not defined" is reported
1621  * to the user. --jdd 5/27/98
1622  */
1623 int whatisParam(ClientData, Tcl_Interp *, int, TCLCONST char *argv[])
1624 {
1625   if (!haveApp()) return TCL_ERROR;
1626   BPatch_Vector<BPatch_function *> pdfv;
1627   if (NULL == appImage->findFunction(argv[3], pdfv) || !pdfv.size()) {
1628     printf("%s is not defined\n", argv[3]);
1629     return TCL_ERROR;
1630   }
1631
1632   if (pdfv.size() > 1) {
1633     printf("%s[%d]:  WARNING, found %d functions called %s, using the first\n",
1634            __FILE__, __LINE__, pdfv.size(), argv[3]);
1635   }
1636   
1637   BPatch_function * func = pdfv[0];
1638
1639   //printf("func is %x\n", func);
1640   if(!func){
1641     printf("%s is not defined\n", argv[3]);
1642     return TCL_ERROR;
1643   }
1644   
1645   
1646   BPatch_localVar * lvar = func->findLocalVar(argv[1]);
1647   if(lvar){
1648     BPatch_type *type = lvar->getType();
1649     if( type ){
1650       switch (type->getDataClass()) {
1651       case BPatch_array:
1652         printArray( type );
1653         break;
1654         
1655       case BPatch_pointer:
1656         printPtr( type );
1657         printf("\t %s\n", argv[1]);
1658         break;
1659         
1660       default:
1661         printf("    %s is of type %s \n", argv[1], type->getName());
1662         break;
1663       }
1664     }
1665     //print local variable info
1666     printf("        %s is a local variable in function %s\n", lvar->getName(),
1667            argv[3]);
1668     printf("        Declared on line %d and has a Frame offset of %d\n",
1669            lvar->getLineNum(), lvar->getFrameOffset());
1670   }
1671   else{
1672     lvar = func->findLocalParam(argv[1]);
1673     
1674     if (!lvar) {
1675       BPatch_variableExpr *var = findVariable(argv[1]);
1676       if(!var){
1677         // do something else ??
1678         //int ret = whatisType(cd, interp, argc, argv);
1679         return TCL_OK;
1680       }
1681       BPatch_type *type = (BPatch_type *) var->getType();
1682       switch (type->getDataClass()) {
1683       case BPatch_array:
1684         printArray( type );
1685         break;
1686         
1687       case BPatch_pointer:
1688         printPtr( type );
1689         printf("\t %s\n", argv[3]);
1690         break;
1691         
1692       default:
1693         printf("    %s is of type %s \n", argv[1], type->getName());
1694         break;
1695       }
1696      printf("      %s is a Global variable\n", argv[1]);
1697     }
1698     else{
1699       BPatch_type *lType = (BPatch_type *) lvar->getType();
1700       if (lType){
1701         switch (lType->getDataClass()) {
1702         case BPatch_array:
1703           printArray( lType );
1704           break;
1705           
1706         case BPatch_pointer:
1707           printPtr( lType );
1708           printf("\t %s\n", argv[1]);
1709           break;
1710           
1711         default:
1712           printf("    %s is of type %s \n", argv[1], lType->getName());
1713           break;
1714         }
1715         printf("       %s is a parameter of the function %s\n",lvar->getName(),
1716            argv[3]);
1717         printf("       Declared on line %d and has a Frame offset of %d\n",
1718            lvar->getLineNum(), lvar->getFrameOffset());
1719       }
1720       else{
1721         printf("   unknown type %s\n", lvar->getName());
1722       }
1723     }   
1724   }
1725   return TCL_OK;
1726 }
1727
1728 /*
1729  * int whatisFunc()
1730  *
1731  * This function is an extension to the "whatis" command.  This function
1732  * searches all of the modules to find the BPatch_function with the name
1733  * given be argv[1]. If no such function is found, then TCL_ERROR is returned.
1734  * This is the last function in the chain of "whatis" command functions to
1735  * be executed in the search for argv[1]. --jdd 5/27/99
1736  */
1737  
1738 int whatisFunc(ClientData, Tcl_Interp *, int, TCLCONST char *argv[])
1739 {
1740   if (!haveApp()) return TCL_ERROR;
1741   
1742   BPatch_Vector<BPatch_function *> pdfv;
1743   if (NULL == appImage->findFunction(argv[3], pdfv) || ! pdfv.size()) {
1744     printf("%s is not defined\n", argv[1]);
1745     return TCL_ERROR;
1746   }
1747
1748   if (pdfv.size() > 1) {
1749     printf("%s[%d]:  WARNING, found %d functions called %s, using the first\n",
1750            __FILE__, __LINE__, pdfv.size(), argv[3]);
1751   }
1752   
1753   BPatch_function * func = pdfv[0];
1754     
1755     if(!func){
1756       printf("%s is not defined\n", argv[1]);
1757       return TCL_ERROR;
1758     }
1759     BPatch_type * retType = func->getReturnType();
1760     if(retType)
1761       switch(retType->getDataClass()){
1762       case BPatch_scalar:
1763       case BPatch_built_inType:
1764       case BPatchSymTypeRange:
1765         printf("%s",retType->getName() );
1766         break;
1767       case BPatch_array:
1768         printArray( retType );
1769         break;
1770           
1771       case BPatch_pointer:
1772         printPtr( retType );
1773         break;
1774         
1775       default:
1776         printf("*unknown return type %s %d*\n",
1777                retType->getName(), retType->getID());
1778         break;
1779       }
1780     else
1781       printf("*unknown*");
1782     printf(" %s(", argv[1]);
1783     BPatch_Vector<BPatch_localVar *> *params = func->getParams();
1784     for (unsigned int i=0; i < params->size(); i++) {
1785       BPatch_localVar *localVar = (*params)[i];
1786       BPatch_type *lType = (BPatch_type *) localVar->getType();
1787       if (lType){
1788         if( (lType->getDataClass())  == BPatch_pointer){
1789           printPtr(lType);
1790           printf("%s", localVar->getName());
1791         } else if( (lType->getDataClass()) == BPatch_array){
1792           printArray( lType );
1793         } else {
1794           printf("%s %s",lType->getName(), localVar->getName());
1795         }
1796       } else {
1797         printf("unknown type %s", localVar->getName());
1798       }
1799       if (i < params->size()-1) printf(", ");
1800     }    
1801     printf(") \n");
1802     if (func->getBaseAddr()) {
1803         unsigned int firstLine, lastLine;
1804         char file[1024];
1805         printf("   starts at 0x%lx", (long)func->getBaseAddr());
1806         unsigned int size = sizeof(file);
1807         if (func->getLineAndFile(firstLine, lastLine, file, size)) {
1808             printf(" defined at %s:%d-%d\n", file, firstLine, lastLine);
1809         } else {
1810             printf("\n");
1811         }
1812     }
1813     return TCL_OK;
1814 }
1815
1816 /*
1817  * int whatisType()
1818  *
1819  * This function is an extension to the "whatis" command.  This function
1820  * searches for the type collection of the all the modules looking for
1821  * the type specified by argv[1]. If it is not found, then whatisFunc()
1822  * is called. This is function is called by whatisVar if a variable is
1823  * not found. -- jdd 5/27/99
1824  */
1825  
1826 int whatisType(ClientData cd, Tcl_Interp *interp, int argc, TCLCONST char *argv[])
1827 {
1828     if (!haveApp()) return TCL_ERROR;
1829     
1830     BPatch_type *type = appImage->findType(argv[1]);
1831     if (!type) {
1832       int ret = whatisFunc(cd, interp, argc, argv);
1833       return ret;
1834     }
1835
1836     BPatch_dataClass dc = type->getDataClass();
1837     switch (dc) {
1838     case BPatch_structure: {
1839       printf("    struct %s {\n", argv[1]);
1840       BPatch_Vector<BPatch_field *> *fields = type->getComponents();
1841       for (unsigned int i=0; i < fields->size(); i++) {
1842         BPatch_field *field = (*fields)[i];
1843         BPatch_type *fType = (BPatch_type *) field->getType();
1844         if (fType){
1845           switch (fType->getDataClass()) {
1846           case BPatch_array:
1847             printArray( fType );
1848             printf("  %s\n", field->getName());
1849             break;
1850         
1851           case BPatch_pointer:
1852             printPtr( fType );
1853             printf("  %s\n", field->getName());
1854             break;
1855         
1856           default:
1857             printf("        %s %s\n", fType->getName(), field->getName());
1858             break;
1859           }
1860         }
1861         else{
1862           printf("   unknown type %s\n", field->getName());
1863         }
1864       }
1865       printf("    }\n");
1866       break;
1867     }
1868     case BPatch_union: {
1869       printf("    union %s {\n", argv[1]);
1870       BPatch_Vector<BPatch_field *> *fields = type->getComponents();
1871       for (unsigned int i=0; i < fields->size(); i++) {
1872         BPatch_field *field = (*fields)[i];
1873         BPatch_type *fType = (BPatch_type *) field->getType();
1874         if (fType){
1875           switch (fType->getDataClass()) {
1876           case BPatch_array:
1877             printArray( fType );
1878             printf("  %s\n", field->getName());
1879             break;
1880         
1881           case BPatch_pointer:
1882             printPtr( fType );
1883             printf("  %s\n", field->getName());
1884             break;
1885             
1886           default:
1887             printf("        %s %s\n", fType->getName(), field->getName());
1888             break;
1889           }
1890         }
1891         else{
1892           printf("        unknown type %s\n", field->getName());
1893         }
1894       }
1895       printf("    }\n");
1896       break;
1897     }
1898     case BPatch_enumerated: {
1899       printf("    enum %s {\n", argv[1]);
1900       BPatch_Vector<BPatch_field *> *fields = type->getComponents();
1901       for (unsigned int i=0; i < fields->size(); i++) {
1902         BPatch_field *field = (*fields)[i];
1903         printf("        %s    \t%d\n", field->getName(),
1904                field->getValue());
1905       }
1906       printf("    }\n");
1907       break;
1908     }
1909     case BPatch_array:
1910       printArray( type );
1911       break;
1912       
1913     case BPatch_scalar:
1914     case BPatch_built_inType:
1915       printf("    %s is a scalar of size %d\n",argv[1],type->getSize());
1916       break;
1917       
1918     case BPatch_pointer:
1919       printPtr( type );
1920       printf("\t %s\n", argv[1]);
1921       /*
1922       printf("    %s is pointer to type %s\n", argv[1], 
1923              type->getConstituentType()->getName());*/
1924       break;
1925     case BPatchSymTypeRange:
1926       if(type->getConstituentType())
1927         printf("    %s is a %s of size %d\n",argv[1],
1928                (type->getConstituentType())->getName(),type->getSize());
1929       else
1930         printf("    %s is a scalar of size %d\n",argv[1],type->getSize());
1931       if( type->getLow() ){
1932          printf("        with range %s to %s\n", type->getLow(),
1933                 type->getHigh());
1934       }
1935       break;
1936     default:
1937       printf("%s is of an unknown data class %d\n", argv[1],
1938              dc);
1939       break;
1940     }
1941     
1942     return TCL_OK;
1943 }
1944
1945 /*
1946  * int whatisVar()
1947  *
1948  * This function is an extension to the "whatis" command.  This function
1949  * searches the process for the variable named by argv[1] and then searches
1950  * all the Global variables for all the modules to find the variable
1951  * specified by argv[1].  If nothing is found, then whatisType() is called. If
1952  * whatisType() finds nothing, whatisFunc() is called.  If the command is
1953  * of the form "whatis -scope <function> <variable>", then whatisParam() is
1954  * called skipping all other attempts to find the variable. -- jdd 5/27/99
1955  */
1956
1957 int whatisVar(ClientData cd, Tcl_Interp *interp, int argc, TCLCONST char *argv[])
1958 {
1959     if (!haveApp()) return TCL_ERROR;
1960     
1961     if (argc == 4){ //looking for a local variable
1962       if(!(strcmp(argv[2], "in"))){
1963         int ret = whatisParam(cd, interp, argc, argv );
1964         return ret;
1965       } else {
1966         printf("inavlid argument %s\n", argv[1]);
1967         return TCL_ERROR;
1968       }
1969     }
1970
1971     BPatch_variableExpr *var = findVariable(argv[1], false);
1972     if (!var) {
1973         int ret = whatisType(cd, interp, argc, argv);
1974         return ret;
1975     }
1976
1977     BPatch_type *type = (BPatch_type *) var->getType();
1978     switch (type->getDataClass()) {
1979     case BPatch_structure: {
1980       printf("    struct %s {\n", argv[1]);
1981       BPatch_Vector<BPatch_field *> *fields = type->getComponents();
1982       for (unsigned int i=0; i < fields->size(); i++) {
1983         BPatch_field *field = (BPatch_field *) (*fields)[i];
1984         BPatch_type *fType = (BPatch_type *) field->getType();
1985         if (fType){
1986           printf("        %s %s\n", fType->getName(), field->getName());
1987         }
1988         else{
1989           printf("   unknown type %s\n", field->getName());
1990         }
1991       }
1992       printf("    }\n");
1993       break;
1994     }
1995     case BPatch_union: {
1996       printf("    union %s {\n", argv[1]);
1997       BPatch_Vector<BPatch_field *> *fields = type->getComponents();
1998       for (unsigned int i=0; i < fields->size(); i++) {
1999         BPatch_field *field = (*fields)[i];
2000         BPatch_type *fType = (BPatch_type *) field->getType();
2001         if (fType){
2002           printf("        %s %s\n", fType->getName(), field->getName());
2003         }
2004         else{
2005           printf("        unknown type %s\n", field->getName());
2006         }
2007       }
2008       printf("    }\n");
2009       break;
2010     }
2011     case BPatch_enumerated: {
2012       printf("    enum %s {\n", argv[1]);
2013       BPatch_Vector<BPatch_field *> *fields = type->getComponents();
2014       for (unsigned int i=0; i < fields->size(); i++) {
2015         BPatch_field *field = (*fields)[i];
2016         printf("        %s    \t%d\n", field->getName(),
2017                field->getValue());
2018       }
2019       printf("    }\n");
2020       break;
2021     }
2022     case BPatch_array:
2023       printArray(type);
2024       break;
2025    
2026     case BPatch_pointer:
2027       printPtr( type );
2028       printf("\t %s\n", argv[1]);
2029       /*
2030       printf("    %s is pointer to type %s\n", argv[1], 
2031              type->getConstituentType()->getName());*/
2032       break;
2033     case BPatchSymTypeRange:
2034       if(type->getConstituentType())
2035         printf("    %s is a %s of size %d\n",argv[1],
2036                (type->getConstituentType())->getName(),type->getSize());
2037       else
2038         printf("    %s is a scalar of size %d\n",argv[1],type->getSize());
2039       if( type->getLow() ){
2040         printf("        with range %s to %s\n", type->getLow(),
2041                type->getHigh());
2042       }
2043       break;
2044     case BPatch_scalar:
2045     case BPatch_built_inType:
2046       printf("    %s is a scalar of size %d\n",argv[1],type->getSize());
2047       break;
2048       
2049     default:
2050       printf("    %s is of type %s \n", argv[1], type->getName());
2051       //int ret = whatisType(cd, interp, argc, argv);
2052       break;
2053     }
2054     
2055     return TCL_OK;
2056 }
2057
2058 const int DYNINST_NO_ERROR = -1;
2059
2060 void errorFunc(BPatchErrorLevel level, int num, const char **params)
2061 {
2062     char line[256];
2063
2064     if (errorLoggingOff) return;
2065
2066     if ((num == 0) && ((level == BPatchWarning) || (level == BPatchInfo))) {
2067          // these are old warnings/status info from paradyn
2068          if (!verbose) return;
2069     }
2070
2071     const char *msg = bpatch->getEnglishErrorString(num);
2072     bpatch->formatErrorString(line, sizeof(line), msg, params);
2073
2074     if (num != DYNINST_NO_ERROR) {
2075
2076         /*error call back 100 seems to be a variable not found error
2077           OR Dyninst assert(0) right after it is thrown, so in either case
2078           we dont need to tell the user from here, they will get a message
2079           elsewhere
2080         */
2081         if(num != 100 ){ //ccw 9 mar 2004
2082                 printf("Error #%d (level %d): %s\n", num, level, line);
2083         }
2084
2085         // We consider some errors fatal.
2086         if (num == 101) {
2087             exit(-1);
2088         }
2089     }
2090 }
2091
2092 /* This function prints type information. */
2093 void PrintTypeInfo(char *var, BPatch_type *type) {
2094       if (!type) {
2095         printf("NO RETURN TYPE INFO for %s\n", var);
2096         return;
2097       }
2098
2099       switch(type->getDataClass()){
2100       case BPatch_array:
2101         printArray( type );
2102         printf(" %s\n", var);
2103         break;
2104           
2105       case BPatch_pointer:
2106         printPtr( type );
2107         printf(" %s\n", var);
2108         break;
2109         
2110       default:
2111         printf("%s %s\n", type->getName(), var);
2112         break;
2113       }
2114 }
2115 int findAndShowCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2116 {
2117   BPatch_Vector<BPatch_function *> functions;// = NULL;
2118   if ((argc != 3) && (argc!=5)) {
2119     printf("Syntax error !\n");
2120     return TCL_ERROR;
2121   }
2122
2123   if (strcmp(argv[1], "function")){
2124     printf("Usage:  'find function <name>' or 'find function <name> in <module>'\n");
2125     return TCL_ERROR;
2126   }
2127
2128   if (argc == 3) {
2129     if (NULL == appImage->findFunction(argv[2], functions) || !functions.size()) {
2130       printf("No matches for %s\n", argv[2]);
2131       return TCL_OK;
2132     }
2133   }
2134   else if (argc == 5) {
2135     BPatch_module *module = FindModule(argv[4]);
2136     if (!module) {
2137       printf("No matches for module %s\n", argv[4]);
2138       return TCL_ERROR;
2139     }
2140     
2141     if (NULL == module->findFunction(argv[2], functions)) {
2142       printf("Error finding %s in module %s\n", argv[2], argv[4]);
2143       return TCL_ERROR;
2144     }
2145   }
2146   
2147   //Now print all the functions in the set
2148   char funcName[1024];
2149   for(unsigned int i=0; i<functions.size(); ++i) {
2150     (functions)[i]->getName(funcName, 1024);
2151     PrintTypeInfo(funcName, (functions)[i]->getReturnType());
2152   }
2153
2154   return TCL_OK;
2155 }
2156 /* This function displays all the functions in the executable or the functions in a module
2157  * if a module name is provided.
2158  */
2159 int ShowFunctions(int argc, TCLCONST char *argv[]) {
2160     BPatch_Vector<BPatch_function *> *functions = NULL;
2161
2162     if (argc == 2) 
2163         functions = appImage->getProcedures();
2164     else if ( (argc == 4) && (!strcmp(argv[2], "in")) ) {
2165         BPatch_module *module = FindModule(argv[3]);
2166         if (!module)
2167                 return TCL_ERROR;
2168
2169         //Get the module functions
2170         functions = module->getProcedures();
2171     }
2172     else {
2173         printf("Syntax error !\n");
2174         return TCL_ERROR;
2175     }
2176
2177     if (!functions) {
2178         printf("Can not get function list!\n");
2179         return TCL_ERROR;
2180     }
2181
2182     //Now print all the functions in the module
2183     char funcName[1024];
2184     for(unsigned int i=0; i<functions->size(); ++i) {
2185         (*functions)[i]->getName(funcName, 1024);
2186         PrintTypeInfo(funcName, (*functions)[i]->getReturnType());
2187     }
2188
2189     return TCL_OK;
2190 }
2191
2192 int verboseCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2193 {
2194   verbose = !verbose;
2195   printf("verbose mode is %s\n", verbose ? "on" : "off");
2196   return TCL_OK;
2197 }
2198 static int stringCompare(const void *a, const void *b)
2199 {
2200     return strcmp(*(char **) a, *(char **) b);
2201 }
2202
2203 /* Finds all the modules in the executable and displays the module names */
2204 int ShowModules()
2205 {
2206     char *prevName;
2207     char modName[1024];
2208     char **names;
2209     BPatch_Vector<BPatch_module *> *modules = appImage->getModules();
2210
2211     if (!modules) {
2212         printf("Can not get module info !\n");
2213         return TCL_ERROR;
2214     }
2215
2216     names = (char **) calloc(modules->size(), sizeof(char *));
2217     for(unsigned int m=0; m<modules->size(); ++m) {
2218         (*modules)[m]->getName(modName, 1024);
2219         names[m] = strdup(modName);
2220     }
2221
2222     qsort(names, modules->size(), sizeof(char *), stringCompare);
2223     prevName = strdup("");
2224     for (unsigned int i=0; i<modules->size(); ++i) {
2225          if (strcmp(prevName, names[i])) {
2226              printf("%s\n", names[i]);
2227          }
2228          if (prevName) free(prevName);
2229          prevName = names[i];
2230     }
2231     if (prevName) free(prevName);
2232     free (names);
2233
2234     return TCL_OK;
2235 }
2236
2237 /*
2238  * This function finds and prints all the parameters
2239  * of a function whose name is given as input.
2240  */
2241 int ShowParameters(int argc, TCLCONST char *argv[]) {
2242     if ( (argc != 4) || (strcmp(argv[2], "in")) ) {
2243         printf("Usage: show parameters in <function>\n");
2244         return TCL_ERROR;
2245     }
2246
2247     BPatch_Vector<BPatch_function *> bpfv;
2248     if (NULL == appImage->findFunction(argv[3], bpfv) || !bpfv.size()) {
2249         printf("Invalid function name: %s\n", argv[3]);
2250         return TCL_ERROR;
2251     }
2252
2253     if (bpfv.size() > 1) {
2254       printf("warning:  found %d functions called %s, picking the first\n", 
2255              bpfv.size(), argv[3]);
2256     }
2257
2258     BPatch_function *fp = bpfv[0];
2259
2260     if (!fp) {
2261         printf("Invalid function name: %s\n", argv[3]);
2262         return TCL_ERROR;
2263     }
2264
2265     BPatch_Vector<BPatch_localVar *> *params = fp->getParams();
2266     for(unsigned int i=0; i<params->size(); ++i) {
2267         PrintTypeInfo((char *) (*params)[i]->getName(), (*params)[i]->getType());
2268     }
2269
2270     return TCL_OK;
2271 }
2272
2273 /*
2274  * This function finds and prints all the local variables
2275  * of a function whose name is given as input.
2276  */
2277 int ShowLocalVars(const char *funcName) {
2278   BPatch_Vector<BPatch_function *> bpfv;
2279
2280   if (NULL == appImage->findFunction(funcName, bpfv) || !bpfv.size()) {
2281     printf("Invalid function name: %s\n", funcName);
2282     return TCL_ERROR;
2283   }
2284
2285   if (bpfv.size() > 1) {
2286     printf("warning:  found %d functions called %s, picking the first\n", 
2287            bpfv.size(), funcName);
2288   }
2289
2290   BPatch_function *fp = bpfv[0];
2291   
2292   if (!fp) {
2293     printf("Invalid function name: %s\n", funcName);
2294     return TCL_ERROR;
2295   }
2296
2297   BPatch_Vector<BPatch_localVar *> *vars = fp->getVars();
2298   for(unsigned int i=0; i<vars->size(); ++i) {
2299     PrintTypeInfo((char *) (*vars)[i]->getName(), (*vars)[i]->getType());
2300   }
2301   
2302   delete vars;
2303   
2304   return TCL_OK;
2305 }
2306
2307 /* Finds all the global vars in the executable and prints their names. */
2308 int ShowGlobalVars() {
2309     BPatch_Vector<BPatch_variableExpr *> *vars = appImage->getGlobalVariables();
2310
2311     if (!vars) {
2312         printf("Can not get global variable info !\n");
2313         return TCL_ERROR;
2314     }
2315
2316     for(unsigned int i=0; i<vars->size(); ++i) {
2317         PrintTypeInfo((*vars)[i]->getName(), (BPatch_type *) (*vars)[i]->getType());
2318     }
2319
2320     return TCL_OK;
2321 }
2322
2323 /* Finds all global variables or local variables in the function */
2324 int ShowVariables(int argc, TCLCONST char *argv[])
2325 {
2326     if (argc == 2)
2327         return ShowGlobalVars();
2328
2329     if ( (argc == 4) && (!strcmp(argv[2], "in")) )
2330         return ShowLocalVars(argv[3]);
2331
2332     //Should not reach here!
2333     return TCL_ERROR;
2334 }
2335
2336 /* Displays either modules or functions in a specific module in the executable */
2337
2338 int showCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2339 {
2340     if (!haveApp()) return TCL_ERROR;
2341
2342     if (argc == 1) {
2343         printf("Usage: show [modules|functions|variables]\n");
2344         printf("or     show functions in <module>\n");
2345         printf("or     show [variables|parameters] in <function>\n");
2346         return TCL_ERROR;
2347     }
2348
2349     if (!strcmp(argv[1], "modules"))
2350         return ShowModules();
2351
2352     if (!strcmp(argv[1], "functions"))
2353         return ShowFunctions(argc, argv);
2354
2355     if (!strcmp(argv[1], "variables"))
2356         return ShowVariables(argc, argv);
2357
2358     if (!strcmp(argv[1], "parameters"))
2359         return ShowParameters(argc, argv);
2360
2361     printf("Syntax error!\n");
2362     return TCL_ERROR;
2363 }
2364
2365 int dsetCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2366 {
2367     if (argc == 1) {
2368         printf("Usage: dset <variable> <value>");
2369         return TCL_ERROR;
2370     }
2371
2372     if (!strcmp(argv[1], "recTramps")) {
2373         if (!strcmp(argv[2], "false")) {
2374             bpatch->setTrampRecursive(false);
2375             return TCL_OK;
2376         } else if (!strcmp(argv[2], "true")) {
2377             bpatch->setTrampRecursive(true);
2378             return TCL_OK;
2379         } else {
2380             printf("Usage: dset recTramps [true|false]\n");
2381             return TCL_ERROR;
2382         }
2383     }
2384
2385     printf("Syntax error!\n");
2386     return TCL_ERROR;
2387 }
2388
2389 /* Displays how many times input fcn is called */
2390 int countCommand(ClientData, Tcl_Interp *interp, int argc, TCLCONST char *argv[])
2391 {
2392     if (!haveApp()) return TCL_ERROR;
2393
2394     if (argc != 2) {
2395         printf("Usage: count <function>\n");
2396         return TCL_ERROR;
2397     }
2398
2399     BPatch_Vector<BPatch_function *> bpfv;
2400     if (NULL == appImage->findFunction(argv[1], bpfv) || !bpfv.size()) {
2401       printf("Invalid function name: %s\n", argv[1]);
2402       return TCL_ERROR;
2403     }
2404
2405     if (bpfv.size() > 1) {
2406       printf("warning:  found %d functions called %s, picking the first\n", 
2407              bpfv.size(), argv[1]);
2408     }
2409
2410     BPatch_function *fp = bpfv[0];
2411
2412     if (!fp) {
2413         printf("Invalid function name: %s\n", argv[1]);
2414         return TCL_ERROR;
2415     }
2416
2417     const char *fcnName = argv[1];
2418     char cmdBuf[1024];
2419
2420     sprintf(cmdBuf, "declare int _%s_cnt", fcnName);
2421     if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
2422         return TCL_ERROR;
2423
2424     sprintf(cmdBuf, "at main entry { _%s_cnt = 0; } count", fcnName);
2425     if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
2426         return TCL_ERROR;
2427
2428     sprintf(cmdBuf, "at %s entry { _%s_cnt++; } count", fcnName, fcnName);
2429     if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
2430         return TCL_ERROR;
2431
2432     sprintf(cmdBuf, "at main exit { printf(\"%s called %%d times\\n\", _%s_cnt); } count", 
2433                                                                         fcnName, fcnName);
2434     if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
2435         return TCL_ERROR;
2436
2437     return TCL_OK;
2438 }
2439
2440 /*
2441  * Replace all calls to fcn1 with calls fcn2
2442  */
2443 int repFunc(const char *name1, const char *name2) {
2444
2445   BPatch_Vector<BPatch_function *> bpfv;
2446   if (NULL == appImage->findFunction(name1, bpfv) || !bpfv.size()) {
2447     printf("Invalid function name: %s\n", name1);
2448     return TCL_ERROR;
2449   }
2450   
2451   if (bpfv.size() > 1) {
2452     printf("warning:  found %d functions called %s, picking the first\n", 
2453            bpfv.size(), name1);
2454   }
2455   
2456   BPatch_function *func1 = bpfv[0];
2457
2458   if (!func1) {
2459     printf("Invalid function name: %s\n", name1);
2460     return TCL_ERROR;
2461   }
2462
2463   BPatch_Vector<BPatch_function *> bpfv2;
2464   if (NULL == appImage->findFunction(name2, bpfv2) || !bpfv2.size()) {
2465     printf("Invalid function name: %s\n", name2);
2466     return TCL_ERROR;
2467   }
2468   
2469   if (bpfv2.size() > 1) {
2470     printf("warning:  found %d functions called %s, picking the first\n", 
2471            bpfv2.size(), name2);
2472   }
2473   
2474   BPatch_function *func2 = bpfv2[0];
2475
2476   if (!func2) {
2477     printf("Invalid function name: %s\n", name2);
2478     return TCL_ERROR;
2479   }
2480
2481   if (appThread->replaceFunction(*func1, *func2))
2482     return TCL_OK;
2483   
2484   return TCL_ERROR;
2485 }
2486
2487 /*
2488  * Replace all or n'th call in func1 with a call to func2
2489  */
2490 int repCall(const char *func1, const char *func2) {
2491
2492   // Replace function calls
2493   int n = 0;
2494   char *ptr = strchr(func1,':');
2495   if (ptr) {
2496     *ptr = '\0';
2497     n = atoi(ptr+1) - 1;
2498     if (n == -1) {
2499       printf("Invalid number is entered!\n");
2500       return TCL_ERROR;
2501     }
2502   }
2503   
2504   BPatch_Vector<BPatch_function *> bpfv2;
2505   if (NULL == appImage->findFunction(func2, bpfv2) || !bpfv2.size()) {
2506     printf("Invalid function name: %s\n", func2);
2507     return TCL_ERROR;
2508   }
2509   
2510   if (bpfv2.size() > 1) {
2511     printf("warning:  found %d functions called %s, picking the first\n", 
2512            bpfv2.size(), func2);
2513   }
2514
2515   BPatch_function *newFunc = bpfv2[0];
2516   if (newFunc == NULL) {
2517     printf("Invalid function name: %s\n", func2);
2518     return TCL_ERROR;
2519   }
2520
2521   BPatch_Vector<BPatch_function *> found_funcs;
2522   if ((NULL == appImage->findFunction(func1, found_funcs, 1)) || !found_funcs.size()) {
2523     printf("%s[%d]:  CANNOT CONTINUE  :  %s not found\n", __FILE__, __LINE__, func1);
2524     return TCL_ERROR;
2525   }
2526     
2527   if (1 < found_funcs.size()) {
2528     printf("%s[%d]:  WARNING  :  %d functions called '%s'found.  Using the first\n", 
2529            __FILE__, __LINE__, 
2530            found_funcs.size(), func1);
2531   }
2532     
2533   BPatch_Vector<BPatch_point *> *points = found_funcs[0]->findPoint(BPatch_subroutine);
2534
2535     if (points == NULL) {
2536         printf("Could not locate function %s\n", func1);
2537         return TCL_ERROR;
2538     }
2539
2540     if (points->size() == 0) {
2541         printf("Function %s has no calls!\n", func1);
2542         return TCL_ERROR;
2543     }
2544
2545     if (n > (int) points->size()) {
2546         printf("Function %s does not have %d calls!\n", func1, n);
2547         return TCL_ERROR;
2548     }
2549
2550     if (n == -1) {
2551         //Remove all function calls
2552         for(unsigned int i=0; i<points->size(); ++i) {
2553                 if (!appThread->replaceFunctionCall(*((*points)[i]), *newFunc) ) {
2554                         printf("Unable to replace call %d !\n", i);
2555                         return TCL_ERROR;
2556                 }
2557         }
2558         return TCL_OK;
2559     }
2560
2561     //Replace n'th function call
2562     if (!appThread->replaceFunctionCall(*((*points)[n]), *newFunc) ) {
2563         printf("Unable to replace call %d !\n", n);
2564         return TCL_ERROR;
2565     }
2566
2567     return TCL_OK;
2568 }
2569
2570 /*
2571  * Replaces functions or function calls with input function
2572  */
2573 int replaceCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2574 {
2575     if (!haveApp()) return TCL_ERROR;
2576
2577     if ( (argc != 5) || ( (strcmp(argv[1], "function")) && (strcmp(argv[1], "call")) )
2578                          || (strcmp(argv[3], "with")) ) 
2579     {
2580         printf("Usage: replace function <function1> with <function2>\n");
2581         printf("or     replace call <function1>[:n] with <function2>\n");
2582         return TCL_ERROR;
2583     }
2584
2585     if (!strcmp(argv[1], "function"))
2586         return repFunc(argv[2], argv[4]);
2587
2588     if (!strcmp(argv[1], "call"))
2589         return repCall(argv[2], argv[4]);
2590
2591     printf("Invalid option %s\n", argv[1]);
2592     return TCL_ERROR;
2593 }
2594
2595 /*
2596  * Print a message while entering a function
2597  */
2598 int traceFunc(Tcl_Interp *interp, const char *name) 
2599 {
2600   BPatch_Vector<BPatch_function *> bpfv2;
2601   if (NULL == appImage->findFunction(name, bpfv2) || !bpfv2.size()) {
2602     printf("Invalid function name: %s\n", name);
2603     return TCL_ERROR;
2604   }
2605   
2606   if (bpfv2.size() > 1) {
2607     printf("warning:  found %d functions called %s, picking the first\n", 
2608            bpfv2.size(), name);
2609   }
2610
2611   BPatch_function *func = bpfv2[0];
2612   if (!func) {
2613     printf("Invalid function name: %s\n", name);
2614     return TCL_ERROR;
2615   }
2616
2617     char cmdBuf[1024];
2618     sprintf(cmdBuf, 
2619         "at %s entry { printf(\"Entering function %s\\n\"); } trace", name, name);
2620     if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
2621         return TCL_ERROR;
2622
2623     sprintf(cmdBuf, 
2624         "at %s exit { printf(\"Exiting function %s\\n\"); } trace", name, name);
2625     return Tcl_Eval(interp, cmdBuf);
2626 }
2627
2628 /*
2629  * Trace all the function in a module
2630  */
2631 int traceMod(Tcl_Interp *interp, const char *name) {
2632     BPatch_Vector<BPatch_function *> *functions = NULL;
2633
2634     BPatch_module *module = FindModule(name);
2635     if (!module)
2636         return TCL_ERROR;
2637
2638     //Get the module functions
2639     functions = module->getProcedures();
2640
2641     if (!functions) {
2642         printf("Can not get function list!\n");
2643         return TCL_ERROR;
2644     }
2645
2646     //Now print all the functions in the module
2647     char funcName[1024];
2648     for(unsigned int i=0; i<functions->size(); ++i) {
2649         (*functions)[i]->getName(funcName, 1024);
2650         if (traceFunc(interp, funcName) == TCL_ERROR)
2651                 return TCL_ERROR;
2652     }
2653
2654     return TCL_OK;
2655 }
2656
2657 /*
2658  * Trace functions alone or in a module
2659  */
2660 int traceCommand(ClientData, Tcl_Interp *interp, int argc, TCLCONST char *argv[])
2661 {
2662     if (!haveApp()) return TCL_ERROR;
2663
2664     if (argc < 3) {
2665         printf("Usage: trace function <function>\n");
2666         printf("or     trace functions in <module>\n");
2667         return TCL_ERROR;
2668     }
2669
2670     if (!strcmp(argv[1], "function"))
2671         return traceFunc(interp, argv[2]);
2672
2673     if (!strcmp(argv[1], "functions") && !strcmp(argv[2], "in"))
2674         return traceMod(interp, argv[3]);
2675
2676     return TCL_ERROR;
2677 }
2678
2679
2680 int untraceFunc(const char *name)
2681 {
2682     DynerList<IPListElem *>::iterator i;
2683     int removed_a_point = 0;
2684     IPListElem *ip;
2685
2686     i = iplist.begin();
2687     while(i != iplist.end()) {
2688       ip = *i;
2689
2690       if ((ip->instType == TRACE) && !strcmp(name, ip->function)) {
2691         printf("removing tracing for function %s\n", ip->function);
2692         fflush(NULL);
2693         iplist.erase(i);
2694         delete ip;
2695         removed_a_point = 1;
2696       }
2697       else i++;
2698
2699     }
2700
2701     if (removed_a_point)
2702        return TCL_OK;
2703
2704     printf("function %s is not currently traced\n", name);
2705     return TCL_ERROR;
2706 }
2707
2708 int untraceMod(const char *name)
2709 {
2710     BPatch_Vector<BPatch_function *> *functions = NULL;
2711
2712     BPatch_module *module = FindModule(name);
2713     if (!module)
2714         return TCL_ERROR;
2715
2716     //Get the module functions
2717     functions = module->getProcedures();
2718
2719     if (!functions) {
2720         printf("Can not get function list in the module!\n");
2721         return TCL_ERROR;
2722     }
2723
2724     //Now print all the functions in the module
2725     char funcName[1024];
2726     for(unsigned int i=0; i<functions->size(); ++i) {
2727         (*functions)[i]->getName(funcName, 1024);
2728         if (untraceFunc(funcName) == TCL_ERROR)
2729                 return TCL_ERROR;
2730     }
2731
2732     return TCL_OK;
2733 }
2734
2735 /*
2736  * Deletes trace effects
2737  */
2738 int untraceCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2739 {
2740     if (!haveApp()) return TCL_ERROR;
2741
2742     if (argc < 3) {
2743         printf("Usage: untrace function <function>\n");
2744         printf("or     untrace functions in <module>\n");
2745         return TCL_ERROR;
2746     }
2747
2748     if (!strcmp(argv[1], "function"))
2749         return untraceFunc(argv[2]);
2750
2751     if (!strcmp(argv[1], "functions") && !strcmp(argv[2], "in"))
2752         return untraceMod(argv[3]);
2753
2754     return TCL_ERROR;
2755 }
2756
2757 /*
2758  * Enable or disable the execution of snippets
2759  */
2760 int mutationsCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2761 {
2762     if (argc != 2) {
2763         printf("Usage: mutations [enable|disable]\n");
2764         return TCL_ERROR;
2765     }
2766
2767     if (!haveApp()) return TCL_ERROR;
2768
2769     if (!strcmp(argv[1], "enable")) {
2770         appThread->setMutationsActive(true);
2771         return TCL_OK;
2772     }
2773
2774     if (!strcmp(argv[1], "disable")) {
2775         appThread->setMutationsActive(false);
2776         return TCL_OK;
2777     }
2778
2779     printf("Invalid option!\n"); 
2780     return TCL_ERROR;
2781 }
2782
2783 /*
2784  * Remove all or n'th function call in the input function
2785  */
2786 int removeCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2787 {
2788     if (argc != 2) {
2789         printf("Usage: removecall <function>[:n]\n");
2790         return TCL_ERROR;
2791     }
2792
2793     if (!haveApp()) return TCL_ERROR;
2794
2795     int n = -1;
2796     char *ptr = strchr(argv[1],':');
2797     if (ptr) {
2798         *ptr = '\0';
2799         n = atoi(ptr+1) - 1;
2800         if (n == -1) {
2801                 printf("Invalid number is entered!\n");
2802                 return TCL_ERROR;
2803         }
2804     }
2805
2806     BPatch_Vector<BPatch_function *> found_funcs;
2807     if ((NULL == appImage->findFunction(argv[1], found_funcs, 1)) || !found_funcs.size()) {
2808       printf("%s[%d]:  CANNOT CONTINUE  :  %s not found\n", __FILE__, __LINE__, argv[1]);
2809       return TCL_ERROR;
2810     }
2811     
2812     if (1 < found_funcs.size()) {
2813       printf("%s[%d]:  WARNING  :  %d functions called '%s'found.  Using the first\n", 
2814              __FILE__, __LINE__, 
2815              found_funcs.size(), argv[1]);
2816     }
2817     
2818     BPatch_Vector<BPatch_point *> *points = found_funcs[0]->findPoint(BPatch_subroutine);
2819
2820     if (points == NULL) {
2821         printf("Could not locate function %s\n", argv[1]);
2822         return TCL_ERROR;
2823     }
2824
2825     if (points->size() == 0) {
2826         printf("Function %s has no calls!\n", argv[1]);
2827         return TCL_ERROR;
2828     }
2829
2830     if (n > (int) points->size()) {
2831         printf("Function %s does not have %d calls!\n", argv[1], n);
2832         return TCL_ERROR;
2833     }
2834
2835     if (n == -1) {
2836         //Remove all function calls
2837         for(unsigned int i=0; i<points->size(); ++i) {
2838                 if (!appThread->removeFunctionCall(*((*points)[i])) ) {
2839                         printf("Unable to remove call %d !\n", i);
2840                         return TCL_ERROR;
2841                 }
2842         }
2843         return TCL_OK;
2844     }
2845
2846     //Remove n'th function call
2847     if (!appThread->removeFunctionCall(*((*points)[n])) ) {
2848         printf("Unable to remove call %d !\n", n);
2849         return TCL_ERROR;
2850     }
2851
2852     return TCL_OK;
2853 }
2854
2855 /*
2856  * Write the in-memory version of the program to the specified file
2857  */
2858 int dumpCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2859 {
2860     if (argc != 2) {
2861         printf("Usage: dump <file name>\n");
2862         return TCL_ERROR;
2863     }
2864
2865     if (!haveApp()) return TCL_ERROR;
2866
2867     appThread->dumpImage(argv[1]);
2868
2869     return TCL_OK;
2870 }
2871
2872 /*
2873  * remove all the code inserted into target program
2874  */
2875 int detachCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char **)
2876 {
2877     if (argc != 1) {
2878         printf("Usage: detach\n");
2879         return TCL_ERROR;
2880     }
2881
2882     if (!haveApp()) return TCL_ERROR;
2883
2884     appThread->detach(true);
2885
2886     return TCL_OK;
2887 }
2888
2889 /*
2890  * enable or disable debug parse of the mutatee
2891  */
2892 int debugParse(ClientData, Tcl_Interp *, int argc, TCLCONST char **argv)
2893 {
2894     if (argc > 2) {
2895         printf("Usage: debugparse [enable | disable]");
2896         return TCL_ERROR;
2897     }
2898
2899     if (argc == 1) {
2900         printf("Debug parsing is %s\n", (bpatch->parseDebugInfo()?"on":"off") );
2901         printf("Usage: debugparse [enable | disable]\n");
2902         return TCL_OK;
2903     }
2904
2905     bool flag;
2906     if ( !strcmp(argv[1], "enable") ) 
2907         flag = true;
2908     else if ( !strcmp(argv[1], "disable") )
2909         flag = false;
2910     else {
2911         printf("Invalid option for debugparse command.\n");
2912         printf("Usage: debugparse [enable | disable]");
2913         return TCL_ERROR;
2914     }
2915
2916     bpatch->setDebugParsing(flag);
2917
2918     return TCL_OK;
2919 }
2920         
2921 int exitDyner(ClientData, Tcl_Interp *, int, TCLCONST char **)
2922 {
2923
2924     if (haveApp()) {
2925         // this forces terminatation if the app has not been detached
2926         if (appThread) delete appThread;
2927     }
2928     exit(0);
2929 }
2930
2931 //
2932 //
2933 int Tcl_AppInit(Tcl_Interp *interp)
2934 {
2935     if (Tcl_Init(interp) == TCL_ERROR) {
2936         return TCL_ERROR;
2937     }
2938     
2939     //Create BPatch library
2940     bpatch = new BPatch;
2941     if (!bpatch)
2942         return TCL_ERROR;
2943
2944     Tcl_CreateCommand(interp, "at", (Tcl_CmdProc*)instStatement, NULL, NULL);
2945     Tcl_CreateCommand(interp, "attach", (Tcl_CmdProc*)attachPid, NULL, NULL);
2946     Tcl_CreateCommand(interp, "break", (Tcl_CmdProc*)condBreak, NULL, NULL);
2947     Tcl_CreateCommand(interp, "declare", (Tcl_CmdProc*)newVar, NULL, NULL);
2948     Tcl_CreateCommand(interp, "listbreak", (Tcl_CmdProc*)listBreak, NULL, NULL);
2949     Tcl_CreateCommand(interp, "deletebreak", (Tcl_CmdProc*)deleteBreak, NULL, NULL);
2950     Tcl_CreateCommand(interp, "dset", (Tcl_CmdProc*)dsetCommand, NULL, NULL);
2951     Tcl_CreateCommand(interp, "help", (Tcl_CmdProc*)help, NULL, NULL);
2952     Tcl_CreateCommand(interp, "exit", (Tcl_CmdProc*)exitDyner, NULL, NULL);
2953     Tcl_CreateCommand(interp, "kill", (Tcl_CmdProc*)killApp, NULL, NULL);
2954     Tcl_CreateCommand(interp, "load", (Tcl_CmdProc*)loadCommand, NULL, NULL);
2955     Tcl_CreateCommand(interp, "run", (Tcl_CmdProc*)runApp, NULL, NULL);
2956     Tcl_CreateCommand(interp, "print", (Tcl_CmdProc*)printVar, NULL, NULL);
2957     Tcl_CreateCommand(interp, "whatis", (Tcl_CmdProc*)whatisVar, NULL, NULL);
2958     Tcl_CreateCommand(interp, "show", (Tcl_CmdProc*)showCommand, NULL, NULL);
2959     Tcl_CreateCommand(interp, "find", (Tcl_CmdProc*)findAndShowCommand, NULL, NULL);
2960     Tcl_CreateCommand(interp, "verbose", (Tcl_CmdProc*)verboseCommand, NULL, NULL);
2961     Tcl_CreateCommand(interp, "count", (Tcl_CmdProc*)countCommand, NULL, NULL);
2962     Tcl_CreateCommand(interp, "replace", (Tcl_CmdProc*)replaceCommand, NULL, NULL);
2963     Tcl_CreateCommand(interp, "trace", (Tcl_CmdProc*)traceCommand, NULL, NULL);
2964     Tcl_CreateCommand(interp, "untrace", (Tcl_CmdProc*)untraceCommand, NULL, NULL);
2965     Tcl_CreateCommand(interp, "mutations", (Tcl_CmdProc*)mutationsCommand, NULL, NULL);
2966     Tcl_CreateCommand(interp, "removecall", (Tcl_CmdProc*)removeCommand, NULL, NULL);
2967     //Tcl_CreateCommand(interp, "dump", (Tcl_CmdProc*)dumpCommand, NULL, NULL);
2968     Tcl_CreateCommand(interp, "detach", (Tcl_CmdProc*)detachCommand, NULL, NULL);
2969     Tcl_CreateCommand(interp, "execute", (Tcl_CmdProc*)execStatement, NULL, NULL);
2970     Tcl_CreateCommand(interp, "listinst", (Tcl_CmdProc*)listInstrument, NULL, NULL);
2971     Tcl_CreateCommand(interp, "deleteinst", (Tcl_CmdProc*)deleteInstrument, NULL, NULL);
2972     Tcl_CreateCommand(interp, "debugparse", (Tcl_CmdProc*)debugParse, NULL, NULL);
2973 #if defined(rs6000_ibm_aix4_1) || defined(sparc_sun_solaris2_4) || defined(i386_unknown_linux2_0)  
2974
2975     Tcl_CreateCommand(interp, "where", (Tcl_CmdProc*)where, NULL, NULL);
2976     Tcl_CreateCommand(interp, "up", (Tcl_CmdProc*)whereUp, NULL, NULL);
2977     Tcl_CreateCommand(interp, "down", (Tcl_CmdProc*)whereDown, NULL, NULL);
2978
2979     Tcl_CreateCommand(interp, "save", (Tcl_CmdProc*)saveWorld, NULL, NULL);
2980     Tcl_CreateCommand(interp, "saveStart", (Tcl_CmdProc*)saveStart, NULL, NULL);
2981
2982 #endif
2983
2984     Tcl_AllowExceptions(interp);
2985
2986     bpatch->registerErrorCallback(errorFunc);
2987     bpatch->setTypeChecking(false);
2988     bpatch->registerExitCallback(&exitCallback);
2989
2990     return TCL_OK;
2991 }
2992
2993 int main(int argc, char *argv[])
2994 {
2995     if (argc >= 2 && !strcmp(argv[1], "-debug")) {
2996         printf("parser debug enabled\n");
2997         dynerdebug = 1;
2998         verbose = true;
2999     }
3000
3001 #if !defined(i386_unknown_nt4_0)
3002     signal(SIGINT, INThandler);
3003 #endif
3004
3005     Tcl_Main(argc, argv, Tcl_AppInit);
3006     return 0;
3007 }
3008
3009
3010 template class DynerList<BPListElem*>;
3011 template class DynerList<IPListElem*>;
3012 template class DynerList<runtimeVar*>;
3013