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