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