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