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