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