2 * Copyright (c) 1996-2004 Barton P. Miller
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.
11 * This license is for research uses. For such uses, there is no
12 * charge. We define "research use" to mean you may freely use it
13 * inside your organization for whatever purposes you see fit. But you
14 * may not re-distribute Paradyn or parts of Paradyn, in any form
15 * source or binary (including derivatives), electronic or otherwise,
16 * to any other organization or entity without our permission.
18 * (for other uses, please contact us at paradyn@cs.wisc.edu)
20 * All warranties, including without limitation, any warranty of
21 * merchantability or fitness for a particular purpose, are hereby
24 * By your use of Paradyn, you understand and agree that we (or any
25 * other person or entity with proprietary rights in Paradyn) are
26 * under no obligation to provide either maintenance services,
27 * update services, notices of latent defects, or correction of
28 * defects for Paradyn.
30 * Even if advised of the possibility of such damages, under no
31 * circumstances shall we (or any other person or entity with
32 * proprietary rights in the software licensed hereunder) be liable
33 * to you or any third party for direct, indirect, or consequential
34 * damages of any character regardless of type of action, including,
35 * without limitation, loss of profits, loss of use, loss of good
36 * will, or computer failure or malfunction. You agree to indemnify
37 * us (and any other person or entity with proprietary rights in the
38 * software licensed hereunder) for any and all liability it may
39 * incur to third parties resulting from your use of Paradyn.
47 #if defined(i386_unknown_nt4_0)
48 #define WIN32_LEAN_AND_MEAN
57 #include "dynerList.h"
59 #include "BPatch_type.h"
60 #include "BPatch_Vector.h"
61 #include "BPatch_thread.h"
62 #include "BPatch_snippet.h"
63 #include "breakpoint.h"
66 #if !defined(i386_unknown_nt4_0)
67 #if !defined(i386_unknown_linux2_0)
68 #if !defined(ia64_unknown_linux2_4)
69 int usleep(useconds_t);
74 void set_lex_input(char *s);
78 bool stopFlag = false;
79 extern int dynerdebug;
82 BPatch_point *targetPoint;
83 bool errorLoggingOff = false;
86 // control debug printf statements
87 #define dprintf if (debugPrint) printf
93 BPatch_procedureLocation where;
95 BPatchSnippetHandle *handle;
98 class BPListElem: public ListElem {
103 BPListElem(int _number, const char *_function,
104 BPatch_procedureLocation _where,
105 BPatch_callWhen _when, const char *_condition,
106 BPatchSnippetHandle *_handle, int _lineNum);
113 runtimeVar(BPatch_variableExpr *v, const char *n) {
114 var = v, name = strdup(n);
116 BPatch_variableExpr *var;
118 bool readValue(void *buf) { return var->readValue(buf); }
121 typedef enum { NORMAL, TRACE, COUNT } InstPointType;
123 class IPListElem: public ListElem {
126 InstPointType instType;
128 IPListElem(int _number, const char *_function,
129 BPatch_procedureLocation _where,
130 BPatch_callWhen _when, const char *_condition,
131 BPatchSnippetHandle *_handle, InstPointType _instType);
137 BPatch_thread *appThread = NULL;
138 BPatch_image *appImage = NULL;
139 static BPatch_variableExpr *bpNumber = NULL;
140 static int bpCtr = 1;
141 static int ipCtr = 1;
142 static DynerList<BPListElem *> bplist;
143 static DynerList<IPListElem *> iplist;
144 static DynerList<runtimeVar *> varList;
145 int whereAmINow = -1;/*ccw 10 mar 2004 : this holds the index of the current stackframe for where, up, down*/
147 #if !defined(i386_unknown_nt4_0)
149 //Ctrl-C signal handler
150 void INThandler(int sig)
152 signal(sig, SIG_IGN);
153 signal(SIGINT, INThandler);
158 bool name2loc(const char *s, BPatch_procedureLocation &where,
159 BPatch_callWhen &when)
161 if (!strcmp(s, "entry")) {
162 where = BPatch_entry;
163 when = BPatch_callBefore;
164 } else if (!strcmp(s, "exit")) {
166 /* This is not supported anymore!
167 when = BPatch_callBefore;
169 when = BPatch_callAfter;
170 } else if (!strcmp(s, "preCall")) {
171 where = BPatch_subroutine;
172 when = BPatch_callBefore;
173 } else if (!strcmp(s, "postCall")) {
174 where = BPatch_subroutine;
175 when = BPatch_callAfter;
182 char *loc2name(BPatch_procedureLocation where, BPatch_callWhen when)
189 case BPatch_subroutine:
190 if (when == BPatch_callBefore) return "preCall";
191 else return "postCall";
197 BPListElem::BPListElem(int _number, const char *_function,
198 BPatch_procedureLocation _where, BPatch_callWhen _when,
199 const char *_condition,
200 BPatchSnippetHandle *_handle, int _lineNum)
203 function = strdup(_function);
207 condition = strdup(_condition);
214 BPListElem::~BPListElem()
217 if (condition) free(condition);
220 void BPListElem::Print()
222 printf("%2d: ", number);
224 printf("%s:%d", function, lineNum);
226 printf("%s (%s)", function,
227 loc2name(where, when));
230 printf(", condition %s\n", condition);
235 IPListElem::IPListElem(int _number, const char *_function,
236 BPatch_procedureLocation _where, BPatch_callWhen _when,
237 const char *_statement,
238 BPatchSnippetHandle *_handle, InstPointType _instType)
240 if (_instType == NORMAL)
244 function = strdup(_function);
247 statement = strdup(_statement);
249 instType = _instType;
252 IPListElem::~IPListElem()
258 appThread->deleteSnippet(handle);
264 void IPListElem::Print()
266 printf("%2d: %s (%s)-->%s\n", number, function, loc2name(where, when), statement);
269 BPListElem *removeBPlist(int n)
271 DynerList<BPListElem *>::iterator i;
272 BPListElem *ret = NULL;
273 for (i = bplist.begin(); i != bplist.end(); i++) {
274 if ((*i)->number == n) {
283 BPListElem *findBP(int n)
285 DynerList<BPListElem *>::iterator i;
287 for (i = bplist.begin(); i != bplist.end(); i++) {
288 if ((*i)->number == n) return (*i);
294 IPListElem *removeIP(int n)
296 DynerList<IPListElem *>::iterator i;
297 IPListElem *ret = NULL;
299 for (i = iplist.begin(); i != iplist.end(); i++) {
300 if ((*i)->number == n) {
310 IPListElem *findIP(int n)
312 DynerList<IPListElem *>::iterator i;
314 for (i = iplist.begin(); i != iplist.end(); i++) {
315 if ((*i)->number == n) return (*i);
321 #define LIMIT_TO(name) if (argc < 2 || !strncmp(argv[1], name, strlen(name)))
323 int help(ClientData, Tcl_Interp *, int argc, TCLCONST char **argv)
327 printf("at <function> [entry|exit|preCall|postCall] <statement> - insert statement\n");
328 printf("at termination <statement> - Execute <statement> at program exit callback\n");
332 printf("attach <pid> <program> - attach dyner to a running program\n");
335 LIMIT_TO("declare") {
336 printf("declare <type> <variable> - create a new variable of type <type>\n");
340 printf("deletebreak <breakpoint number ...> - delete breakpoint(s)\n");
341 printf("deleteinst <instpoint number ...> - delete intrumentation point(s)\n");
345 printf("break <function> [entry|exit|preCall|postCall] [<condition>] - set a (conditional)\n");
346 printf(" break point at specified points of <function>\n");
347 printf("break <file name:line number> [<condition>] - set an arbitrary (conditional) break\n");
348 printf(" point at <line number> of <file name>\n");
351 LIMIT_TO("debugparse") {
352 printf("debugparse [enable | disable] - Turn on/off debug parsing of the mutatee programs\n");
355 LIMIT_TO("execute") {
356 printf("execute <statement> - Execute <statement> at the current point\n");
360 printf("listbreak - list break points\n");
361 printf("listinst - list intrumentation points\n");
365 printf("load <program> [arguments] [< filename] [> filename] - load a program\n");
366 printf("load library <lib name> - load a dynamically linked library\n");
367 printf("load source <C++ file name> - Create a dynamically linked library from a \n");
368 printf(" C++ source file and load it to address space. All the functions and variables \n");
369 printf(" in the source file will be available for instrumentation\n");
373 printf("run - run or continue the loaded program\n");
377 printf("show [modules|functions|variables] - display module names, global functions\n");
378 printf(" and variables\n");
379 printf("show functions in <module> - display function names declared in <module>\n");
380 printf("show [parameters|variables] in <function> - display local variables or parameters of\n");
381 printf(" <function>\n");
385 printf("count <function> - At the end of execution display how many times <function> is called\n");
388 LIMIT_TO("replace") {
389 printf("replace function <function1> with <function2> - Replace all calls to <function1> with\n");
390 printf(" calls to <function2>\n");
391 printf("replace call <function1>[:n] with <function2> - All the calls or the nth function call \n");
392 printf(" in <function1> are/is changed to the function <function2>\n");
396 printf("trace function <function> - Print a message at the entry and exit of <function>\n");
397 printf("trace functions in <module> - Print a message at the entry and exit of all functions\n");
398 printf(" declared in <module>\n");
401 LIMIT_TO("untrace") {
402 printf("untrace function <function> - Undo the effects of trace command for <function>\n");
403 printf("untrace functions in <module> - Undo the effects of trace command for all functions\n");
404 printf(" declared in <module>\n");
407 LIMIT_TO("mutations") {
408 printf("mutations [enable|disable] - Enable or disable the execution of snippets\n");
411 LIMIT_TO("removecall") {
412 printf("removecall <function>[:n] - Remove all the calls or n'th call in <function>\n");
416 printf("detach - remove all the code inserted into target program\n");
420 printf("source <file name> - Execute dyner commands stored in the file <file name>\n");
424 printf("kill - Terminate the execution of target program\n");
428 printf("print <Variable> - Display the data type and value of dyner variable\n");
432 printf("find function <pattern> [in <module>] - Display a list of functions in the image matching <pattern>. Regex search will be performed if <pattern> contains regex, with some limitations\n");
435 LIMIT_TO("verbose") {
436 printf("verbose - toggles verbose mode error reporting\n");
439 printf("whatis <variable> [in <function>] - Display detailed information about\n");
440 printf(" variables in the target program. Local variables and parameters are\n");
441 printf(" searched in the <function>.\n");
443 #if defined(rs6000_ibm_aix4_1) || defined(sparc_sun_solaris2_4) || defined(i386_unknown_linux2_0)
445 printf("where - Print stack trace.\n");
448 printf("up - Move up the stack trace\n");
451 printf("down - Move down the stack trace\n");
454 LIMIT_TO("saveStart"){
455 printf("saveStart - Call saveStart before 'save' to begin marking instrumentation\n");
456 printf(" to be saved to the mutated binary. This must be called before save is\n");
457 printf(" called. Only instrumentation inserted after saveStart is called will be\n");
458 printf(" saved in the mutated binary.\n");
461 printf("save <file name> - Save the currently loaded mutatee and its mutations to the\n");
462 printf(" file <file name>. Call 'saveStart' before 'save' to begin marking \n");
463 printf(" instrumentation to be saved to the mutated binary\n");
472 if (appThread == NULL) {
473 fprintf(stderr, "No application loaded.\n");
477 if (appThread->isTerminated()) {
478 fprintf(stderr, "The application has exited.\n");
485 BPatch_module *FindModule(const char *name) {
487 //Locate the module using module name
488 BPatch_Vector<BPatch_module *> *modules = appImage->getModules();
491 printf("Can not get module info !\n");
496 BPatch_module *module = NULL;
498 for(unsigned int i=0; i<modules->size(); ++i) {
499 (*modules)[i]->getName(modName, 1024);
501 if (!strcmp(modName, name)) {
502 module = (*modules)[i];
508 printf("Module %s is not found !\n", name);
515 int loadApp(const char *pathname, TCLCONST char **args)
517 printf("Loading \"%s\"\n", pathname);
519 if (appThread != NULL) delete appThread;
523 appThread = bpatch->createProcess((char*)pathname, (const char**)args);
526 if (!appThread || appThread->isTerminated()) {
527 fprintf(stderr, "Unable to run test program.\n");
532 // Read the program's image and get an associated image object
533 appImage = appThread->getImage();
535 if (!appImage) return TCL_ERROR;
538 appImage->getModules();
540 #if !defined(i386_unknown_nt4_0)
541 // make it a member of its own process group
542 int ret = setpgid(0, getpid());
553 int loadLib(const char *libName) {
554 if (!haveApp()) return TCL_ERROR;
556 if (appThread->loadLibrary(libName))
562 int loadSource(const char *inp) {
563 if (!haveApp()) return TCL_ERROR;
565 //Create shared object file name
566 char* dupstr = strdup( inp );
567 char *ptr = strrchr(dupstr, '/');
574 sprintf(fname, "./%s", ptr);
576 ptr = strrchr(fname+2, '.'); //Ignore first 2 chars ('./')
582 //First ensure that there is no .so file for the input file
585 //Create a shared object from input file
587 sprintf(cmdBuf,"g++ -g -fPIC -shared -o %s %s", fname, dupstr);
591 //Test whether or not shared object is created
592 FILE *fp = fopen(fname,"rb");
594 printf("Error in compilation of %s\n", dupstr);
600 //Now dynamically link the file
602 return loadLib(fname);
605 int loadCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
608 if (!strcmp(argv[1], "library"))
609 return loadLib(argv[2]);
610 if (!strcmp(argv[1], "source"))
611 return loadSource(argv[2]);
615 printf("Usage load <program> [<arguments>]\n");
616 printf("or load library <lib name>\n");
617 printf("or load source <C++ file name>\n");
621 return loadApp(argv[1], &argv[1]);
624 int attachPid(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
627 const char *pathName = "";
629 if ((argc < 2) || (argc > 3)) {
630 printf("Usage attach <pid> <program>\n");
634 if (appThread != NULL) delete appThread;
640 if (argc == 3) pathName = argv[2];
642 appThread = bpatch->attachProcess(pathName, pid);
645 if (!appThread || !appThread->getImage() || appThread->isTerminated()) {
646 fprintf(stderr, "Unable to attach to pid %d\n", pid);
651 // Read the program's image and get an associated image object
652 appImage = appThread->getImage();
654 if (!appImage) return TCL_ERROR;
657 appImage->getModules();
663 int listBreak(ClientData, Tcl_Interp *, int, TCLCONST char **)
665 if (!haveApp()) return TCL_ERROR;
668 DynerList<BPListElem *>::iterator i;
670 for (i = bplist.begin(); i != bplist.end(); i++) {
671 curr = (BPListElem *) *i;
678 int listInstrument(ClientData, Tcl_Interp *, int, TCLCONST char **)
680 if (!haveApp()) return TCL_ERROR;
683 DynerList<IPListElem *>::iterator i;
685 for (i = iplist.begin(); i != iplist.end(); i++) {
686 curr = (IPListElem *) *i;
687 if (curr->instType == NORMAL)
694 int deleteBreak(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
696 if (!haveApp()) return TCL_ERROR;
699 printf("Specify breakpoint(s) to delete.\n");
704 for (int j = 1; j < argc; j++) {
705 int n = atoi(argv[j]);
707 BPListElem *i = removeBPlist(n);
709 printf("No such breakpoint: %d\n", n);
712 appThread->deleteSnippet(i->handle);
714 printf("Breakpoint %d deleted.\n", n);
721 int deleteInstrument(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
723 if (!haveApp()) return TCL_ERROR;
726 printf("Specify intrument number(s) to delete.\n");
731 for (int j = 1; j < argc; j++) {
732 int n = atoi(argv[j]);
734 IPListElem *i = removeIP(n);
736 printf("No such intrument point: %d\n", n);
740 printf("Instrument number %d deleted.\n", n);
747 void setWhereAmINow(){
748 BPatch_Vector<BPatch_frame> callStack;
750 appThread->getCallStack(callStack);
752 whereAmINow = callStack.size()-1;
757 int runApp(ClientData, Tcl_Interp *, int, TCLCONST char **)
759 if (!haveApp()) return TCL_ERROR;
763 bpNumber->writeValue(&inval);
766 // Start of code to continue the process.
767 dprintf("starting program execution.\n");
768 appThread->continueExecution();
770 whereAmINow = -1 ; //ccw 10 mar 2004 : i dont know where i will be when i stop
772 while (!appThread->isStopped() && !appThread->isTerminated() && !stopFlag)
773 #if defined(i386_unknown_nt4_0)
781 appThread->stopExecution();
782 setWhereAmINow(); //ccw 10 mar 2004 : find myself
786 if (bpNumber) bpNumber->readValue(&bp);
788 if (appThread->isTerminated()) {
789 printf("\nApplication exited.\n");
790 } else if (appThread->isStopped() && bp > 0) {
791 printf("\nStopped at break point %d.\n", bp);
792 ListElem *i = findBP(bp);
794 BPListElem *curr = (BPListElem *) i;
798 printf("\nStopped.\n");
804 int killApp(ClientData, Tcl_Interp *, int, TCLCONST char **)
806 if (!haveApp()) return TCL_ERROR;
808 appThread->terminateExecution();
813 #if defined(sparc_sun_solaris2_4) || defined(i386_unknown_linux2_0) || defined(rs6000_ibm_aix4_1)
815 bool saveWorldStart =false;
817 int saveStart(ClientData, Tcl_Interp *, int argc, TCLCONST char **argv){
819 if (!haveApp()) return TCL_ERROR;
823 appThread->enableDumpPatchedImage();
828 int saveWorld(ClientData, Tcl_Interp *, int argc, TCLCONST char **argv){
830 printf(" Usage: save <filename>\n");
834 printf("Call saveStart before issuing instrumentation to save\n");
837 char* directoryName = appThread->dumpPatchedImage(argv[1]);
838 printf(" saved in %s \n", directoryName);
839 delete [] directoryName;
845 extern BPatch_snippet *parse_result;
846 int condBreak(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
849 printf("Usage: break <function> [entry|exit|preCall|postCall] [<condition>]\n");
850 printf("or break <file name:line number> [<condition>]\n");
854 if (!haveApp()) return TCL_ERROR;
856 if (bpNumber == NULL) {
857 bpNumber = appThread->malloc(*appImage->findType("int"));
858 if (bpNumber == NULL) {
859 fprintf(stderr, "Unable to allocate memory in the inferior process.\n");
866 BPatch_procedureLocation where;
867 BPatch_callWhen when;
869 BPatch_Vector<BPatch_point *> *points;
870 char *ptr = strchr(argv[1],':');
872 //Arbitrary break point, first find module name
874 where = BPatch_entry;
875 when = BPatch_callBefore;
877 lineNum = atoi(ptr+1);
878 BPatch_Vector<unsigned long> absAddrVec;
880 if (!appImage->getLineToAddr(argv[1], lineNum, absAddrVec, true)) {
881 printf("Can not get arbitrary break point address!\n");
884 points = new BPatch_Vector<BPatch_point *>;
885 //Find BPatch_point from the first absolute address
886 points->push_back(appImage->createInstPointAtAddr((void *)absAddrVec[0]));
889 if ( (argc > 2) && name2loc(argv[2], where, when)) {
892 where = BPatch_entry;
893 when = BPatch_callBefore;
896 BPatch_Vector<BPatch_function *> found_funcs;
897 if ((NULL == appImage->findFunction(argv[1], found_funcs))
898 || (0 == found_funcs.size())) {
899 printf("%s[%d]: CANNOT CONTINUE : %s not found\n", __FILE__, __LINE__, argv[1]);
903 if (1 < found_funcs.size()) {
904 printf("%s[%d]: WARNING : %d functions called '%s'found. Using the first\n",
906 found_funcs.size(), argv[1]);
909 points = found_funcs[0]->findPoint(where);
911 if (points == NULL) {
912 printf("Unable to locate points for function %s\n", argv[1]);
917 char *line_buf = NULL;
920 // Count up how large a buffer we need for the whole line
923 for (i = expr_start; i < argc; i++)
924 line_len += strlen(argv[i]) + 1;
926 // Make the buffer and copy the line into it
927 line_buf = new char[line_len];
929 for (i = expr_start; i < argc; i++) {
930 strcat(line_buf, argv[i]);
931 if (i != argc-1) strcat(line_buf, " ");
934 set_lex_input(line_buf);
935 if (dynerparse() != 0) {
936 fprintf(stderr, "Breakpoint not set due to error.\n");
941 if (parse_type != parsed_bool) {
942 fprintf(stderr, "Breakpoint not set due error, expression not boolean.\n");
949 // Make a snippet to tell us which breakpoint it is
950 BPatch_arithExpr storeBPNum(BPatch_assign,
951 *bpNumber, BPatch_constExpr(bpCtr));
953 // Make a snippet to break at the breakpoint
954 BPatch_Vector<BPatch_function *> bpfv;
955 if (NULL == appImage->findFunction("DYNINSTbreakPoint", bpfv) || ! bpfv.size()) {
956 fprintf(stderr, "Unable to find function DYNINSTbreakPoint "
957 "(required for setting break points)\n");
965 BPatch_function *breakFunc = bpfv[0];
966 if (breakFunc == NULL) {
967 fprintf(stderr, "Unable to find function DYNINSTbreakPoint "
968 "(required for setting break points)\n");
976 BPatch_Vector<BPatch_snippet *> nullArgs;
977 BPatch_funcCallExpr callBreak(*breakFunc, nullArgs);
979 // store the break point number, then break
980 BPatch_arithExpr doBreak(BPatch_seq, storeBPNum, callBreak);
982 BPatch_snippet *brSnippet = (BPatch_snippet *) &doBreak;
985 // Call the break snippet conditionally
986 BPatch_ifExpr condBreak(*(BPatch_boolExpr *)parse_result, doBreak);
987 brSnippet = (BPatch_snippet *) &condBreak;
991 BPatchSnippetHandle *handle =
992 appThread->insertSnippet(*brSnippet, *points, when,BPatch_lastSnippet);
994 fprintf(stderr, "Error inserting snippet.\n");
995 if (line_buf) delete line_buf;
1000 new BPListElem(bpCtr, argv[1], where, when, line_buf, handle, lineNum);
1001 if (line_buf) delete line_buf;
1003 bplist.push_back(bpl);
1005 printf("Breakpoint %d set.\n", bpCtr);
1013 * This function recursively goes through the BPatch_type pointers until
1014 * it gets to the base type and prints that name. The base type can be
1015 * a builtin type or an enum, struct, or union. The default case handles
1016 * unknown pointer types. -- jdd 5/27/99
1018 void printPtr( BPatch_type * type )
1020 if( type->getDataClass() == BPatch_pointer ){
1021 printPtr( type->getConstituentType() );
1024 else if((type->getDataClass() == BPatch_scalar)||
1025 (type->getDataClass() == BPatchSymTypeRange)){
1026 printf("%s ", type->getName());
1029 switch( type->getDataClass() ){
1030 case BPatch_enumerated:
1031 printf("enum %s ", type->getName());
1033 case BPatch_structure:
1034 printf("struct %s ", type->getName());
1037 printf("union %s ", type->getName());
1040 printf("Undefined POINTER: %s", type->getName());
1049 * This function prints arrays of various dimension, 1D to 3D. It first
1050 * checks how many dimensions the array is and then prints it out.
1051 * The default case handles the unknown. --jdd 5/27/99
1054 void printArray(BPatch_type * type )
1057 if(type->getConstituentType()){
1059 if(type->getConstituentType()->getConstituentType()){
1061 if(type->getConstituentType()->getConstituentType()->getConstituentType()){
1070 printf(" %s is an array [%s..%s][%s..%s][%s..%s] of %s\n",
1071 type->getName(), type->getLow(), type->getHigh(),
1072 type->getConstituentType()->getLow(),
1073 type->getConstituentType()->getHigh(),
1074 type->getConstituentType()->getConstituentType()->getLow(),
1075 type->getConstituentType()->getConstituentType()->getHigh(),
1076 type->getConstituentType()->getConstituentType()->getConstituentType()->getName());
1081 printf(" %s is an array [%s..%s][%s..%s] of %s\n", type->getName(),
1082 type->getLow(), type->getHigh(),
1083 type->getConstituentType()->getLow(),
1084 type->getConstituentType()->getHigh(),
1085 type->getConstituentType()->getConstituentType()->getName());
1088 printf(" %s is an array [%s..%s] of %s\n", type->getName(),
1089 type->getLow(), type->getHigh(),
1090 type->getConstituentType()->getName());
1093 printf("Unable to process array %s\n", type->getName());
1098 BPatch_snippet *termStatement = NULL;
1100 void exitCallback(BPatch_thread *thread, BPatch_exitType) {
1101 if (termStatement == NULL)
1104 BPatch_snippet *stmt = termStatement;
1105 termStatement = NULL;
1106 thread->oneTimeCode(*stmt);
1110 int instTermStatement(int argc, TCLCONST char *argv[])
1114 // Count up how large a buffer we need for the whole line
1117 for (i = expr_start; i < argc; i++)
1118 line_len += strlen(argv[i]) + 1;
1120 // Make the buffer and copy the line into it
1121 char *line_buf = new char[line_len];
1123 for (i = expr_start; i < argc; i++) {
1124 strcat(line_buf, argv[i]);
1125 if (i != argc-1) strcat(line_buf, " ");
1127 strcat(line_buf, "\n");
1129 // printf("calling parse of %s\n", line_buf);
1130 set_lex_input(line_buf);
1131 if (dynerparse() != 0) {
1132 fprintf(stderr, "Instrumentation not set due to error.\n");
1137 if (parse_type != parsed_statement) {
1138 fprintf(stderr, "code not inserted, expression is not a statement.\n");
1140 delete parse_result;
1144 termStatement = parse_result;
1148 int instStatement(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
1150 if (!haveApp()) return TCL_ERROR;
1153 printf("Usage: at <function> [entry|exit|preCall|postCall] <statement>\n");
1154 printf("or at termination <statement>\n");
1158 if (!strcmp(argv[1], "termination"))
1159 return instTermStatement(argc, argv);
1162 BPatch_procedureLocation where;
1163 BPatch_callWhen when;
1165 if (name2loc(argv[2], where, when)) {
1168 where = BPatch_entry;
1169 when = BPatch_callBefore;
1171 BPatch_Vector<BPatch_function *> bpfv;
1172 if (NULL == appImage->findFunction(argv[1], bpfv) || !bpfv.size()) {
1173 fprintf(stderr, "Unable to locate function: %s\n", argv[1]);
1177 BPatch_function *func = bpfv[0];
1179 fprintf(stderr, "Unable to locate function: %s\n", argv[1]);
1183 BPatch_Vector<BPatch_point *> *points = func->findPoint(where);
1185 if (points == NULL) {
1186 fprintf(stderr, "Unable to locate function: %s\n", argv[1]);
1190 //Assign targetPoint using function entry point
1191 targetPoint = (*(func->findPoint(BPatch_entry)))[0];
1193 InstPointType instType = NORMAL;
1194 if (!strcmp(argv[argc-1], "trace")) {
1195 //This statement is used for tracing the functions
1199 else if (!strcmp(argv[argc-1], "count")) {
1200 //This statement is used for counting the functions
1205 // Count up how large a buffer we need for the whole line
1208 for (i = expr_start; i < argc; i++)
1209 line_len += strlen(argv[i]) + 1;
1211 // Make the buffer and copy the line into it
1212 char *line_buf = new char[line_len];
1214 for (i = expr_start; i < argc; i++) {
1215 strcat(line_buf, argv[i]);
1216 if (i != argc-1) strcat(line_buf, " ");
1218 // strcat(line_buf, "\n");
1220 // printf("calling parse of %s\n", line_buf);
1221 set_lex_input(line_buf);
1222 if (dynerparse() != 0) {
1223 fprintf(stderr, "Instrumentation not set due to error.\n");
1231 if (parse_type != parsed_statement) {
1232 fprintf(stderr, "code not inserted, expression is not a statement.\n");
1234 delete parse_result;
1238 BPatchSnippetHandle *handle =
1239 appThread->insertSnippet(*parse_result, *points, when,BPatch_lastSnippet);
1241 fprintf(stderr, "Error inserting snippet.\n");
1247 new IPListElem(ipCtr, argv[1], where, when, line_buf, handle, instType);
1250 iplist.push_back(snl);
1252 if (instType == NORMAL) {
1253 printf("Instrument point %d set.\n", ipCtr);
1260 int execStatement(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
1262 if (!haveApp()) return TCL_ERROR;
1265 printf("Usage: execute <statement>\n");
1271 // Count up how large a buffer we need for the whole line
1274 for (i = expr_start; i < argc; i++)
1275 line_len += strlen(argv[i]) + 1;
1277 // Make the buffer and copy the line into it
1278 char *line_buf = new char[line_len];
1280 for (i = expr_start; i < argc; i++) {
1281 strcat(line_buf, argv[i]);
1282 if (i != argc-1) strcat(line_buf, " ");
1284 strcat(line_buf, "\n");
1286 //printf("calling parse of %s\n", line_buf);
1287 set_lex_input(line_buf);
1288 if (dynerparse() != 0) {
1289 fprintf(stderr, "Execution can not be done due to error.\n");
1294 if (parse_type != parsed_statement) {
1295 fprintf(stderr, "Syntax error, expression is not a statement.\n");
1297 delete parse_result;
1301 appThread->oneTimeCode(*parse_result);
1302 delete parse_result;
1308 void printVarRecursive(BPatch_variableExpr *var, int level)
1315 BPatch_dataClass dc;
1316 BPatch_type *type = (BPatch_type *) var->getType();
1319 fprintf(stderr," var is NULL\n");
1322 dc = type->getDataClass();
1323 if (!strcmp(type->getName(), "int")) {
1324 /* print out the integer */
1325 var->readValue((void *) &iVal);
1326 printf("%d\n", iVal);
1327 } else if (!strcmp(type->getName(), "float")) {
1328 /* print out the float */
1329 var->readValue((void *) &fVal);
1330 printf("%f\n", fVal);
1331 }else if(!strcmp(type->getName(), "char")) {
1332 /* print out the char*/
1333 var->readValue((void *) &cVal);
1334 printf("%c\n", cVal);
1336 } else if (dc == BPatch_pointer) {
1337 /* print out the float */
1338 var->readValue((void *) &pVal);
1339 printf("0x%x\n", pVal);
1340 } else if (dc == BPatch_structure) {
1341 printf("struct {\n");
1343 BPatch_Vector<BPatch_variableExpr *> *fields = var->getComponents();
1344 for (unsigned int i=0; i < fields->size(); i++) {
1345 BPatch_variableExpr *fieldVar = (*fields)[i];
1346 for (int i=0;i < level; i++) printf(" ");
1347 printf("%s = ", fieldVar->getName());
1348 printVarRecursive(fieldVar, level);
1352 } else if (dc == BPatch_array) {
1353 printf("<arrays not yet implemented>\n");
1355 printf("<unknown type>\n" );
1359 #if defined(rs6000_ibm_aix4_1) || defined(sparc_sun_solaris2_4) || defined(i386_unknown_linux2_0)
1360 void printStackFrame(int index, BPatch_Vector<BPatch_frame> &callStack, char *funcName){
1362 printf("#%d: (0x%x)\t%s (fp: 0x%x)\n", index,callStack[index].getPC(),funcName ,callStack[index].getFP());
1366 int whereUp(ClientData, Tcl_Interp *, int, TCLCONST char *argv[])
1368 BPatch_Vector<BPatch_frame> callStack;
1369 char funcName [1024];
1373 appThread->getCallStack(callStack);
1375 if(whereAmINow < (callStack.size()-1) ){
1381 if(callStack[whereAmINow].findFunction()){
1383 BPatch_Vector<BPatch_point *> *points = callStack[index].findFunction()->findPoint(BPatch_subroutine);
1385 if ( points && points->size() > 0){ //linux gets weird here
1387 targetPoint = (*points)[0];
1389 callStack[whereAmINow].findFunction()->getName(funcName, 1024);
1391 printStackFrame(whereAmINow, callStack, funcName);
1395 printStackFrame(whereAmINow, callStack, "<<FAILED TO FIND FUNCTION>>");
1400 int whereDown(ClientData, Tcl_Interp *, int, TCLCONST char *argv[])
1402 BPatch_Vector<BPatch_frame> callStack;
1403 char funcName [1024];
1406 if( whereAmINow > 1) {
1411 appThread->getCallStack(callStack);
1414 if(callStack[whereAmINow].findFunction()){
1416 BPatch_Vector<BPatch_point *> *points = callStack[index].findFunction()->findPoint(BPatch_subroutine);
1418 if ( points && points->size() > 0){ //linux gets weird here
1420 targetPoint = (*points)[0];
1423 callStack[whereAmINow].findFunction()->getName(funcName, 1024);
1425 printStackFrame(whereAmINow, callStack, funcName);
1429 printStackFrame(whereAmINow, callStack, "<<FAILED TO FIND FUNCTION>>");
1434 int where(ClientData, Tcl_Interp *, int, TCLCONST char *argv[])
1436 BPatch_Vector<BPatch_frame> callStack;
1437 char funcName [1024];
1440 appThread->getCallStack(callStack);
1442 while(index < callStack.size() -1){
1444 if( (whereAmINow == -1 && index == 1) || ( whereAmINow == index ) ){
1446 whereAmINow = index;
1451 if(callStack[index].findFunction()){
1452 BPatch_Vector<BPatch_point *> *points = callStack[index].findFunction()->findPoint(BPatch_subroutine);
1454 if ( points && points->size() > 0){ //linux gets weird here
1456 targetPoint = (*points)[0];
1460 callStack[index].findFunction()->getName(funcName, 1024);
1462 printStackFrame(index, callStack, funcName);
1467 printStackFrame(index, callStack, "<<FAILED TO FIND FUNCTION>>");
1475 #if defined(rs6000_ibm_aix4_1) || defined(sparc_sun_solaris2_4) || defined(i386_unknown_linux2_0)
1477 BPatch_variableExpr *findLocalVariable(const char *name, bool printError)
1479 BPatch_variableExpr *var=NULL;
1480 #ifdef mips_sgi_irix6_4
1481 /* mips_sgi_irix6_4 does not support local vars but if it does we are ready! */
1483 #define CASTOFFSET long
1487 #define CASTOFFSET int
1492 /* if we have a local context, use that. otherwise use the top of the call stack */
1493 if( whereAmINow == -1 ){
1497 index = whereAmINow;
1500 BPatch_Vector<BPatch_frame> callStack;
1501 char funcName [1024];
1502 BPatch_variableExpr *tmpVar;
1504 appThread->getCallStack(callStack);
1506 if( callStack[index].findFunction()){
1508 BPatch_Vector<BPatch_point *> *points = callStack[index].findFunction()->findPoint(BPatch_entry);//ccw 10 mar 2004 was subroutine
1510 if ( points && points->size() > 0){
1512 targetPoint = (*points)[0];
1514 callStack[index].findFunction()->getName(funcName, 1024);
1516 tmpVar = appImage->findVariable(*targetPoint, name);
1521 #ifdef rs6000_ibm_aix4_1
1522 (((int)tmpVar->getBaseAddr()) < 0x1000) ) {
1525 ( ((CASTOFFSET) (tmpVar->getBaseAddr())) < 0) ) {
1528 offset = (CASTOFFSET) (tmpVar->getBaseAddr());
1532 #ifdef sparc_sun_solaris2_4
1533 index ++; /* ccw 9 mar 2004 WHY DO I NEED TO DO THIS ?*/
1536 /* WARNING: the function BPatch_thread::lowlevel_process() is risky, it should go away
1537 But i need to build a variable that points to a specific address, and I can not find
1538 a better way to do it right now
1540 var = new BPatch_variableExpr(tmpVar->getName(), appThread,
1541 (void*) ( ((CASTOFFSET) (callStack[index].getFP())) +offset), tmpVar->getType() );
1543 #ifdef sparc_sun_solaris2_4
1546 whereAmINow = index; /* set local context just in case */
1556 if (printError) printf("Unable to locate local variable %s\n", name);
1561 int printVar(ClientData, Tcl_Interp *, int, TCLCONST char *argv[])
1563 //if (!haveApp()) return TCL_ERROR;
1565 BPatch_variableExpr *var;
1566 #if defined(rs6000_ibm_aix4_1) || defined(sparc_sun_solaris2_4) || defined(i386_unknown_linux2_0)
1568 var = findLocalVariable(argv[1],false);
1572 printf("Local Variable:\t%s = ", argv[1]);
1573 printVarRecursive(var, 1);
1579 var = findVariable(argv[1],false);
1581 printf("Global Variable:\t%s = ", argv[1]);
1582 printVarRecursive(var, 1);
1587 printf("%s is not defined\n", argv[1]);
1595 * declare <type> <variable name>
1597 int newVar(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
1600 printf("Usage: declare <type> <variable name>\n");
1604 if (!haveApp()) return TCL_ERROR;
1606 BPatch_type *type = appImage->findType(argv[1]);
1608 printf("type %s is not defined\n", argv[1]);
1612 BPatch_variableExpr *newVar = appThread->malloc(*type);
1614 printf("Unable to create variable.\n");
1618 varList.push_back(new runtimeVar(newVar, argv[2]));
1624 BPatch_variableExpr *findVariable(const char *name, bool printError)
1626 BPatch_variableExpr *var;
1627 DynerList<runtimeVar *>::iterator i;
1629 // First look for runtime created variables
1630 for (i = varList.begin(); i != varList.end(); i++) {
1631 if (!strcmp(name, (*i)->name)) {
1632 var = new BPatch_variableExpr(*((*i)->var));
1638 var = appImage->findVariable(*targetPoint, name);
1644 // Check global vars in the mutatee
1645 errorLoggingOff = true;
1646 var = appImage->findVariable(name);
1647 errorLoggingOff = false;
1649 if (var) return var;
1651 if (printError) printf("Unable to locate variable %s\n", name);
1658 * This function is an extension to the "whatis" command. This function
1659 * processes the command: whatis -scope <function> <variable>. If the
1660 * <function> is undefined then TCL_ERROR is returned. Otherwise, the
1661 * local variable collection is searched first; followed by the parameter
1662 * collection; and finally the Global collection is searched last. If the
1663 * <variable> is not found, then "<variable> is not defined" is reported
1664 * to the user. --jdd 5/27/98
1666 int whatisParam(ClientData, Tcl_Interp *, int, TCLCONST char *argv[])
1668 if (!haveApp()) return TCL_ERROR;
1669 BPatch_Vector<BPatch_function *> pdfv;
1670 if (NULL == appImage->findFunction(argv[3], pdfv) || !pdfv.size()) {
1671 printf("%s is not defined\n", argv[3]);
1675 if (pdfv.size() > 1) {
1676 printf("%s[%d]: WARNING, found %d functions called %s, using the first\n",
1677 __FILE__, __LINE__, pdfv.size(), argv[3]);
1680 BPatch_function * func = pdfv[0];
1682 //printf("func is %x\n", func);
1684 printf("%s is not defined\n", argv[3]);
1689 BPatch_localVar * lvar = func->findLocalVar(argv[1]);
1691 BPatch_type *type = lvar->getType();
1693 switch (type->getDataClass()) {
1698 case BPatch_pointer:
1700 printf("\t %s\n", argv[1]);
1704 printf(" %s is of type %s \n", argv[1], type->getName());
1708 //print local variable info
1709 printf(" %s is a local variable in function %s\n", lvar->getName(),
1711 printf(" Declared on line %d and has a Frame offset of %d\n",
1712 lvar->getLineNum(), lvar->getFrameOffset());
1715 lvar = func->findLocalParam(argv[1]);
1718 BPatch_variableExpr *var = findVariable(argv[1]);
1720 // do something else ??
1721 //int ret = whatisType(cd, interp, argc, argv);
1724 BPatch_type *type = (BPatch_type *) var->getType();
1725 switch (type->getDataClass()) {
1730 case BPatch_pointer:
1732 printf("\t %s\n", argv[3]);
1736 printf(" %s is of type %s \n", argv[1], type->getName());
1739 printf(" %s is a Global variable\n", argv[1]);
1742 BPatch_type *lType = (BPatch_type *) lvar->getType();
1744 switch (lType->getDataClass()) {
1746 printArray( lType );
1749 case BPatch_pointer:
1751 printf("\t %s\n", argv[1]);
1755 printf(" %s is of type %s \n", argv[1], lType->getName());
1758 printf(" %s is a parameter of the function %s\n",lvar->getName(),
1760 printf(" Declared on line %d and has a Frame offset of %d\n",
1761 lvar->getLineNum(), lvar->getFrameOffset());
1764 printf(" unknown type %s\n", lvar->getName());
1774 * This function is an extension to the "whatis" command. This function
1775 * searches all of the modules to find the BPatch_function with the name
1776 * given be argv[1]. If no such function is found, then TCL_ERROR is returned.
1777 * This is the last function in the chain of "whatis" command functions to
1778 * be executed in the search for argv[1]. --jdd 5/27/99
1781 int whatisFunc(ClientData, Tcl_Interp *, int, TCLCONST char *argv[])
1783 if (!haveApp()) return TCL_ERROR;
1785 BPatch_Vector<BPatch_function *> pdfv;
1786 if (NULL == appImage->findFunction(argv[3], pdfv) || ! pdfv.size()) {
1787 printf("%s is not defined\n", argv[1]);
1791 if (pdfv.size() > 1) {
1792 printf("%s[%d]: WARNING, found %d functions called %s, using the first\n",
1793 __FILE__, __LINE__, pdfv.size(), argv[3]);
1796 BPatch_function * func = pdfv[0];
1799 printf("%s is not defined\n", argv[1]);
1802 BPatch_type * retType = func->getReturnType();
1804 switch(retType->getDataClass()){
1806 case BPatchSymTypeRange:
1807 printf("%s",retType->getName() );
1810 printArray( retType );
1813 case BPatch_pointer:
1814 printPtr( retType );
1818 printf("*unknown return type %s %d*\n",
1819 retType->getName(), retType->getID());
1823 printf("*unknown*");
1824 printf(" %s(", argv[1]);
1825 BPatch_Vector<BPatch_localVar *> *params = func->getParams();
1826 for (unsigned int i=0; i < params->size(); i++) {
1827 BPatch_localVar *localVar = (*params)[i];
1828 BPatch_type *lType = (BPatch_type *) localVar->getType();
1830 if( (lType->getDataClass()) == BPatch_pointer){
1832 printf("%s", localVar->getName());
1833 } else if( (lType->getDataClass()) == BPatch_array){
1834 printArray( lType );
1836 printf("%s %s",lType->getName(), localVar->getName());
1839 printf("unknown type %s", localVar->getName());
1841 if (i < params->size()-1) printf(", ");
1844 if (func->getBaseAddr()) {
1845 unsigned int firstLine, lastLine;
1847 printf(" starts at 0x%lx", (long)func->getBaseAddr());
1848 unsigned int size = sizeof(file);
1849 if (func->getLineAndFile(firstLine, lastLine, file, size)) {
1850 printf(" defined at %s:%d-%d\n", file, firstLine, lastLine);
1861 * This function is an extension to the "whatis" command. This function
1862 * searches for the type collection of the all the modules looking for
1863 * the type specified by argv[1]. If it is not found, then whatisFunc()
1864 * is called. This is function is called by whatisVar if a variable is
1865 * not found. -- jdd 5/27/99
1868 int whatisType(ClientData cd, Tcl_Interp *interp, int argc, TCLCONST char *argv[])
1870 if (!haveApp()) return TCL_ERROR;
1872 BPatch_type *type = appImage->findType(argv[1]);
1874 int ret = whatisFunc(cd, interp, argc, argv);
1878 BPatch_dataClass dc = type->getDataClass();
1880 case BPatch_structure: {
1881 printf(" struct %s {\n", argv[1]);
1882 BPatch_Vector<BPatch_field *> *fields = type->getComponents();
1883 for (unsigned int i=0; i < fields->size(); i++) {
1884 BPatch_field *field = (*fields)[i];
1885 BPatch_type *fType = (BPatch_type *) field->getType();
1887 switch (fType->getDataClass()) {
1889 printArray( fType );
1890 printf(" %s\n", field->getName());
1893 case BPatch_pointer:
1895 printf(" %s\n", field->getName());
1899 printf(" %s %s\n", fType->getName(), field->getName());
1904 printf(" unknown type %s\n", field->getName());
1910 case BPatch_union: {
1911 printf(" union %s {\n", argv[1]);
1912 BPatch_Vector<BPatch_field *> *fields = type->getComponents();
1913 for (unsigned int i=0; i < fields->size(); i++) {
1914 BPatch_field *field = (*fields)[i];
1915 BPatch_type *fType = (BPatch_type *) field->getType();
1917 switch (fType->getDataClass()) {
1919 printArray( fType );
1920 printf(" %s\n", field->getName());
1923 case BPatch_pointer:
1925 printf(" %s\n", field->getName());
1929 printf(" %s %s\n", fType->getName(), field->getName());
1934 printf(" unknown type %s\n", field->getName());
1940 case BPatch_enumerated: {
1941 printf(" enum %s {\n", argv[1]);
1942 BPatch_Vector<BPatch_field *> *fields = type->getComponents();
1943 for (unsigned int i=0; i < fields->size(); i++) {
1944 BPatch_field *field = (*fields)[i];
1945 printf(" %s \t%d\n", field->getName(),
1956 printf(" %s is a scalar of size %d\n",argv[1],type->getSize());
1959 case BPatch_pointer:
1961 printf("\t %s\n", argv[1]);
1963 printf(" %s is pointer to type %s\n", argv[1],
1964 type->getConstituentType()->getName());*/
1966 case BPatchSymTypeRange:
1967 if(type->getConstituentType())
1968 printf(" %s is a %s of size %d\n",argv[1],
1969 (type->getConstituentType())->getName(),type->getSize());
1971 printf(" %s is a scalar of size %d\n",argv[1],type->getSize());
1972 if( type->getLow() ){
1973 printf(" with range %s to %s\n", type->getLow(),
1978 printf("%s is of an unknown data class %d\n", argv[1],
1989 * This function is an extension to the "whatis" command. This function
1990 * searches the process for the variable named by argv[1] and then searches
1991 * all the Global variables for all the modules to find the variable
1992 * specified by argv[1]. If nothing is found, then whatisType() is called. If
1993 * whatisType() finds nothing, whatisFunc() is called. If the command is
1994 * of the form "whatis -scope <function> <variable>", then whatisParam() is
1995 * called skipping all other attempts to find the variable. -- jdd 5/27/99
1998 int whatisVar(ClientData cd, Tcl_Interp *interp, int argc, TCLCONST char *argv[])
2000 if (!haveApp()) return TCL_ERROR;
2002 if (argc == 4){ //looking for a local variable
2003 if(!(strcmp(argv[2], "in"))){
2004 int ret = whatisParam(cd, interp, argc, argv );
2007 printf("inavlid argument %s\n", argv[1]);
2012 BPatch_variableExpr *var = findVariable(argv[1], false);
2014 int ret = whatisType(cd, interp, argc, argv);
2018 BPatch_type *type = (BPatch_type *) var->getType();
2019 switch (type->getDataClass()) {
2020 case BPatch_structure: {
2021 printf(" struct %s {\n", argv[1]);
2022 BPatch_Vector<BPatch_field *> *fields = type->getComponents();
2023 for (unsigned int i=0; i < fields->size(); i++) {
2024 BPatch_field *field = (BPatch_field *) (*fields)[i];
2025 BPatch_type *fType = (BPatch_type *) field->getType();
2027 printf(" %s %s\n", fType->getName(), field->getName());
2030 printf(" unknown type %s\n", field->getName());
2036 case BPatch_union: {
2037 printf(" union %s {\n", argv[1]);
2038 BPatch_Vector<BPatch_field *> *fields = type->getComponents();
2039 for (unsigned int i=0; i < fields->size(); i++) {
2040 BPatch_field *field = (*fields)[i];
2041 BPatch_type *fType = (BPatch_type *) field->getType();
2043 printf(" %s %s\n", fType->getName(), field->getName());
2046 printf(" unknown type %s\n", field->getName());
2052 case BPatch_enumerated: {
2053 printf(" enum %s {\n", argv[1]);
2054 BPatch_Vector<BPatch_field *> *fields = type->getComponents();
2055 for (unsigned int i=0; i < fields->size(); i++) {
2056 BPatch_field *field = (*fields)[i];
2057 printf(" %s \t%d\n", field->getName(),
2067 case BPatch_pointer:
2069 printf("\t %s\n", argv[1]);
2071 printf(" %s is pointer to type %s\n", argv[1],
2072 type->getConstituentType()->getName());*/
2074 case BPatchSymTypeRange:
2075 if(type->getConstituentType())
2076 printf(" %s is a %s of size %d\n",argv[1],
2077 (type->getConstituentType())->getName(),type->getSize());
2079 printf(" %s is a scalar of size %d\n",argv[1],type->getSize());
2080 if( type->getLow() ){
2081 printf(" with range %s to %s\n", type->getLow(),
2086 printf(" %s is a scalar of size %d\n",argv[1],type->getSize());
2090 printf(" %s is of type %s \n", argv[1], type->getName());
2091 //int ret = whatisType(cd, interp, argc, argv);
2098 const int DYNINST_NO_ERROR = -1;
2100 void errorFunc(BPatchErrorLevel level, int num, const char **params)
2104 if (errorLoggingOff) return;
2106 if ((num == 0) && ((level == BPatchWarning) || (level == BPatchInfo))) {
2107 // these are old warnings/status info from paradyn
2108 if (!verbose) return;
2111 const char *msg = bpatch->getEnglishErrorString(num);
2112 bpatch->formatErrorString(line, sizeof(line), msg, params);
2114 if (num != DYNINST_NO_ERROR) {
2116 /*error call back 100 seems to be a variable not found error
2117 OR Dyninst assert(0) right after it is thrown, so in either case
2118 we dont need to tell the user from here, they will get a message
2121 if(num != 100 ){ //ccw 9 mar 2004
2122 printf("Error #%d (level %d): %s\n", num, level, line);
2125 // We consider some errors fatal.
2132 /* This function prints type information. */
2133 void PrintTypeInfo(char *var, BPatch_type *type) {
2135 printf("NO RETURN TYPE INFO for %s\n", var);
2139 switch(type->getDataClass()){
2142 printf(" %s\n", var);
2145 case BPatch_pointer:
2147 printf(" %s\n", var);
2151 printf("%s %s\n", type->getName(), var);
2155 int findAndShowCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2157 BPatch_Vector<BPatch_function *> functions;// = NULL;
2158 if ((argc != 3) && (argc!=5)) {
2159 printf("Syntax error !\n");
2163 if (strcmp(argv[1], "function")){
2164 printf("Usage: 'find function <name>' or 'find function <name> in <module>'\n");
2169 if (NULL == appImage->findFunction(argv[2], functions) || !functions.size()) {
2170 printf("No matches for %s\n", argv[2]);
2174 else if (argc == 5) {
2175 BPatch_module *module = FindModule(argv[4]);
2177 printf("No matches for module %s\n", argv[4]);
2181 if (NULL == module->findFunction(argv[2], functions)) {
2182 printf("Error finding %s in module %s\n", argv[2], argv[4]);
2187 //Now print all the functions in the set
2188 char funcName[1024];
2189 for(unsigned int i=0; i<functions.size(); ++i) {
2190 (functions)[i]->getName(funcName, 1024);
2191 PrintTypeInfo(funcName, (functions)[i]->getReturnType());
2196 /* This function displays all the functions in the executable or the functions in a module
2197 * if a module name is provided.
2199 int ShowFunctions(int argc, TCLCONST char *argv[]) {
2200 BPatch_Vector<BPatch_function *> *functions = NULL;
2203 functions = appImage->getProcedures();
2204 else if ( (argc == 4) && (!strcmp(argv[2], "in")) ) {
2205 BPatch_module *module = FindModule(argv[3]);
2209 //Get the module functions
2210 functions = module->getProcedures();
2213 printf("Syntax error !\n");
2218 printf("Can not get function list!\n");
2222 //Now print all the functions in the module
2223 char funcName[1024];
2224 for(unsigned int i=0; i<functions->size(); ++i) {
2225 (*functions)[i]->getName(funcName, 1024);
2226 PrintTypeInfo(funcName, (*functions)[i]->getReturnType());
2232 int verboseCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2235 printf("verbose mode is %s\n", verbose ? "on" : "off");
2238 static int stringCompare(const void *a, const void *b)
2240 return strcmp(*(char **) a, *(char **) b);
2243 /* Finds all the modules in the executable and displays the module names */
2249 BPatch_Vector<BPatch_module *> *modules = appImage->getModules();
2252 printf("Can not get module info !\n");
2256 names = (char **) calloc(modules->size(), sizeof(char *));
2257 for(unsigned int m=0; m<modules->size(); ++m) {
2258 (*modules)[m]->getName(modName, 1024);
2259 names[m] = strdup(modName);
2262 qsort(names, modules->size(), sizeof(char *), stringCompare);
2263 prevName = strdup("");
2264 for (unsigned int i=0; i<modules->size(); ++i) {
2265 if (strcmp(prevName, names[i])) {
2266 printf("%s\n", names[i]);
2268 if (prevName) free(prevName);
2269 prevName = names[i];
2271 if (prevName) free(prevName);
2278 * This function finds and prints all the parameters
2279 * of a function whose name is given as input.
2281 int ShowParameters(int argc, TCLCONST char *argv[]) {
2282 if ( (argc != 4) || (strcmp(argv[2], "in")) ) {
2283 printf("Usage: show parameters in <function>\n");
2287 BPatch_Vector<BPatch_function *> bpfv;
2288 if (NULL == appImage->findFunction(argv[3], bpfv) || !bpfv.size()) {
2289 printf("Invalid function name: %s\n", argv[3]);
2293 if (bpfv.size() > 1) {
2294 printf("warning: found %d functions called %s, picking the first\n",
2295 bpfv.size(), argv[3]);
2298 BPatch_function *fp = bpfv[0];
2301 printf("Invalid function name: %s\n", argv[3]);
2305 BPatch_Vector<BPatch_localVar *> *params = fp->getParams();
2306 for(unsigned int i=0; i<params->size(); ++i) {
2307 PrintTypeInfo((char *) (*params)[i]->getName(), (*params)[i]->getType());
2314 * This function finds and prints all the local variables
2315 * of a function whose name is given as input.
2317 int ShowLocalVars(const char *funcName) {
2318 BPatch_Vector<BPatch_function *> bpfv;
2320 if (NULL == appImage->findFunction(funcName, bpfv) || !bpfv.size()) {
2321 printf("Invalid function name: %s\n", funcName);
2325 if (bpfv.size() > 1) {
2326 printf("warning: found %d functions called %s, picking the first\n",
2327 bpfv.size(), funcName);
2330 BPatch_function *fp = bpfv[0];
2333 printf("Invalid function name: %s\n", funcName);
2337 BPatch_Vector<BPatch_localVar *> *vars = fp->getVars();
2338 for(unsigned int i=0; i<vars->size(); ++i) {
2339 PrintTypeInfo((char *) (*vars)[i]->getName(), (*vars)[i]->getType());
2347 /* Finds all the global vars in the executable and prints their names. */
2348 int ShowGlobalVars() {
2349 BPatch_Vector<BPatch_variableExpr *> *vars = appImage->getGlobalVariables();
2352 printf("Can not get global variable info !\n");
2356 for(unsigned int i=0; i<vars->size(); ++i) {
2357 PrintTypeInfo((*vars)[i]->getName(), (BPatch_type *) (*vars)[i]->getType());
2363 /* Finds all global variables or local variables in the function */
2364 int ShowVariables(int argc, TCLCONST char *argv[])
2367 return ShowGlobalVars();
2369 if ( (argc == 4) && (!strcmp(argv[2], "in")) )
2370 return ShowLocalVars(argv[3]);
2372 //Should not reach here!
2376 /* Displays either modules or functions in a specific module in the executable */
2378 int showCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2380 if (!haveApp()) return TCL_ERROR;
2383 printf("Usage: show [modules|functions|variables]\n");
2384 printf("or show functions in <module>\n");
2385 printf("or show [variables|parameters] in <function>\n");
2389 if (!strcmp(argv[1], "modules"))
2390 return ShowModules();
2392 if (!strcmp(argv[1], "functions"))
2393 return ShowFunctions(argc, argv);
2395 if (!strcmp(argv[1], "variables"))
2396 return ShowVariables(argc, argv);
2398 if (!strcmp(argv[1], "parameters"))
2399 return ShowParameters(argc, argv);
2401 printf("Syntax error!\n");
2405 int dsetCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2408 printf("Usage: dset <variable> <value>");
2412 if (!strcmp(argv[1], "recTramps")) {
2413 if (!strcmp(argv[2], "false")) {
2414 bpatch->setTrampRecursive(false);
2416 } else if (!strcmp(argv[2], "true")) {
2417 bpatch->setTrampRecursive(true);
2420 printf("Usage: dset recTramps [true|false]\n");
2425 printf("Syntax error!\n");
2429 /* Displays how many times input fcn is called */
2430 int countCommand(ClientData, Tcl_Interp *interp, int argc, TCLCONST char *argv[])
2432 if (!haveApp()) return TCL_ERROR;
2435 printf("Usage: count <function>\n");
2439 BPatch_Vector<BPatch_function *> bpfv;
2440 if (NULL == appImage->findFunction(argv[1], bpfv) || !bpfv.size()) {
2441 printf("Invalid function name: %s\n", argv[1]);
2445 if (bpfv.size() > 1) {
2446 printf("warning: found %d functions called %s, picking the first\n",
2447 bpfv.size(), argv[1]);
2450 BPatch_function *fp = bpfv[0];
2453 printf("Invalid function name: %s\n", argv[1]);
2457 const char *fcnName = argv[1];
2460 sprintf(cmdBuf, "declare int _%s_cnt", fcnName);
2461 if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
2464 sprintf(cmdBuf, "at main entry { _%s_cnt = 0; } count", fcnName);
2465 if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
2468 sprintf(cmdBuf, "at %s entry { _%s_cnt++; } count", fcnName, fcnName);
2469 if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
2472 sprintf(cmdBuf, "at main exit { printf(\"%s called %%d times\\n\", _%s_cnt); } count",
2474 if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
2481 * Replace all calls to fcn1 with calls fcn2
2483 int repFunc(const char *name1, const char *name2) {
2485 BPatch_Vector<BPatch_function *> bpfv;
2486 if (NULL == appImage->findFunction(name1, bpfv) || !bpfv.size()) {
2487 printf("Invalid function name: %s\n", name1);
2491 if (bpfv.size() > 1) {
2492 printf("warning: found %d functions called %s, picking the first\n",
2493 bpfv.size(), name1);
2496 BPatch_function *func1 = bpfv[0];
2499 printf("Invalid function name: %s\n", name1);
2503 BPatch_Vector<BPatch_function *> bpfv2;
2504 if (NULL == appImage->findFunction(name2, bpfv2) || !bpfv2.size()) {
2505 printf("Invalid function name: %s\n", name2);
2509 if (bpfv2.size() > 1) {
2510 printf("warning: found %d functions called %s, picking the first\n",
2511 bpfv2.size(), name2);
2514 BPatch_function *func2 = bpfv2[0];
2517 printf("Invalid function name: %s\n", name2);
2521 if (appThread->replaceFunction(*func1, *func2))
2528 * Replace all or n'th call in func1 with a call to func2
2530 int repCall(const char *func1, const char *func2) {
2532 // Replace function calls
2534 char *ptr = strchr(func1,':');
2537 n = atoi(ptr+1) - 1;
2539 printf("Invalid number is entered!\n");
2544 BPatch_Vector<BPatch_function *> bpfv2;
2545 if (NULL == appImage->findFunction(func2, bpfv2) || !bpfv2.size()) {
2546 printf("Invalid function name: %s\n", func2);
2550 if (bpfv2.size() > 1) {
2551 printf("warning: found %d functions called %s, picking the first\n",
2552 bpfv2.size(), func2);
2555 BPatch_function *newFunc = bpfv2[0];
2556 if (newFunc == NULL) {
2557 printf("Invalid function name: %s\n", func2);
2561 BPatch_Vector<BPatch_function *> found_funcs;
2562 if ((NULL == appImage->findFunction(func1, found_funcs, 1)) || !found_funcs.size()) {
2563 printf("%s[%d]: CANNOT CONTINUE : %s not found\n", __FILE__, __LINE__, func1);
2567 if (1 < found_funcs.size()) {
2568 printf("%s[%d]: WARNING : %d functions called '%s'found. Using the first\n",
2570 found_funcs.size(), func1);
2573 BPatch_Vector<BPatch_point *> *points = found_funcs[0]->findPoint(BPatch_subroutine);
2575 if (points == NULL) {
2576 printf("Could not locate function %s\n", func1);
2580 if (points->size() == 0) {
2581 printf("Function %s has no calls!\n", func1);
2585 if (n > (int) points->size()) {
2586 printf("Function %s does not have %d calls!\n", func1, n);
2591 //Remove all function calls
2592 for(unsigned int i=0; i<points->size(); ++i) {
2593 if (!appThread->replaceFunctionCall(*((*points)[i]), *newFunc) ) {
2594 printf("Unable to replace call %d !\n", i);
2601 //Replace n'th function call
2602 if (!appThread->replaceFunctionCall(*((*points)[n]), *newFunc) ) {
2603 printf("Unable to replace call %d !\n", n);
2611 * Replaces functions or function calls with input function
2613 int replaceCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2615 if (!haveApp()) return TCL_ERROR;
2617 if ( (argc != 5) || ( (strcmp(argv[1], "function")) && (strcmp(argv[1], "call")) )
2618 || (strcmp(argv[3], "with")) )
2620 printf("Usage: replace function <function1> with <function2>\n");
2621 printf("or replace call <function1>[:n] with <function2>\n");
2625 if (!strcmp(argv[1], "function"))
2626 return repFunc(argv[2], argv[4]);
2628 if (!strcmp(argv[1], "call"))
2629 return repCall(argv[2], argv[4]);
2631 printf("Invalid option %s\n", argv[1]);
2636 * Print a message while entering a function
2638 int traceFunc(Tcl_Interp *interp, const char *name)
2640 BPatch_Vector<BPatch_function *> bpfv2;
2641 if (NULL == appImage->findFunction(name, bpfv2) || !bpfv2.size()) {
2642 printf("Invalid function name: %s\n", name);
2646 if (bpfv2.size() > 1) {
2647 printf("warning: found %d functions called %s, picking the first\n",
2648 bpfv2.size(), name);
2651 BPatch_function *func = bpfv2[0];
2653 printf("Invalid function name: %s\n", name);
2659 "at %s entry { printf(\"Entering function %s\\n\"); } trace", name, name);
2660 if (Tcl_Eval(interp, cmdBuf) == TCL_ERROR)
2664 "at %s exit { printf(\"Exiting function %s\\n\"); } trace", name, name);
2665 return Tcl_Eval(interp, cmdBuf);
2669 * Trace all the function in a module
2671 int traceMod(Tcl_Interp *interp, const char *name) {
2672 BPatch_Vector<BPatch_function *> *functions = NULL;
2674 BPatch_module *module = FindModule(name);
2678 //Get the module functions
2679 functions = module->getProcedures();
2682 printf("Can not get function list!\n");
2686 //Now print all the functions in the module
2687 char funcName[1024];
2688 for(unsigned int i=0; i<functions->size(); ++i) {
2689 (*functions)[i]->getName(funcName, 1024);
2690 if (traceFunc(interp, funcName) == TCL_ERROR)
2698 * Trace functions alone or in a module
2700 int traceCommand(ClientData, Tcl_Interp *interp, int argc, TCLCONST char *argv[])
2702 if (!haveApp()) return TCL_ERROR;
2705 printf("Usage: trace function <function>\n");
2706 printf("or trace functions in <module>\n");
2710 if (!strcmp(argv[1], "function"))
2711 return traceFunc(interp, argv[2]);
2713 if (!strcmp(argv[1], "functions") && !strcmp(argv[2], "in"))
2714 return traceMod(interp, argv[3]);
2720 int untraceFunc(const char *name)
2722 DynerList<IPListElem *>::iterator i;
2723 int removed_a_point = 0;
2727 while(i != iplist.end()) {
2730 if ((ip->instType == TRACE) && !strcmp(name, ip->function)) {
2731 printf("removing tracing for function %s\n", ip->function);
2735 removed_a_point = 1;
2741 if (removed_a_point)
2744 printf("function %s is not currently traced\n", name);
2748 int untraceMod(const char *name)
2750 BPatch_Vector<BPatch_function *> *functions = NULL;
2752 BPatch_module *module = FindModule(name);
2756 //Get the module functions
2757 functions = module->getProcedures();
2760 printf("Can not get function list in the module!\n");
2764 //Now print all the functions in the module
2765 char funcName[1024];
2766 for(unsigned int i=0; i<functions->size(); ++i) {
2767 (*functions)[i]->getName(funcName, 1024);
2768 if (untraceFunc(funcName) == TCL_ERROR)
2776 * Deletes trace effects
2778 int untraceCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2780 if (!haveApp()) return TCL_ERROR;
2783 printf("Usage: untrace function <function>\n");
2784 printf("or untrace functions in <module>\n");
2788 if (!strcmp(argv[1], "function"))
2789 return untraceFunc(argv[2]);
2791 if (!strcmp(argv[1], "functions") && !strcmp(argv[2], "in"))
2792 return untraceMod(argv[3]);
2798 * Enable or disable the execution of snippets
2800 int mutationsCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2803 printf("Usage: mutations [enable|disable]\n");
2807 if (!haveApp()) return TCL_ERROR;
2809 if (!strcmp(argv[1], "enable")) {
2810 appThread->setMutationsActive(true);
2814 if (!strcmp(argv[1], "disable")) {
2815 appThread->setMutationsActive(false);
2819 printf("Invalid option!\n");
2824 * Remove all or n'th function call in the input function
2826 int removeCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2829 printf("Usage: removecall <function>[:n]\n");
2833 if (!haveApp()) return TCL_ERROR;
2836 char *ptr = strchr(argv[1],':');
2839 n = atoi(ptr+1) - 1;
2841 printf("Invalid number is entered!\n");
2846 BPatch_Vector<BPatch_function *> found_funcs;
2847 if ((NULL == appImage->findFunction(argv[1], found_funcs, 1)) || !found_funcs.size()) {
2848 printf("%s[%d]: CANNOT CONTINUE : %s not found\n", __FILE__, __LINE__, argv[1]);
2852 if (1 < found_funcs.size()) {
2853 printf("%s[%d]: WARNING : %d functions called '%s'found. Using the first\n",
2855 found_funcs.size(), argv[1]);
2858 BPatch_Vector<BPatch_point *> *points = found_funcs[0]->findPoint(BPatch_subroutine);
2860 if (points == NULL) {
2861 printf("Could not locate function %s\n", argv[1]);
2865 if (points->size() == 0) {
2866 printf("Function %s has no calls!\n", argv[1]);
2870 if (n > (int) points->size()) {
2871 printf("Function %s does not have %d calls!\n", argv[1], n);
2876 //Remove all function calls
2877 for(unsigned int i=0; i<points->size(); ++i) {
2878 if (!appThread->removeFunctionCall(*((*points)[i])) ) {
2879 printf("Unable to remove call %d !\n", i);
2886 //Remove n'th function call
2887 if (!appThread->removeFunctionCall(*((*points)[n])) ) {
2888 printf("Unable to remove call %d !\n", n);
2896 * Write the in-memory version of the program to the specified file
2898 int dumpCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char *argv[])
2901 printf("Usage: dump <file name>\n");
2905 if (!haveApp()) return TCL_ERROR;
2907 appThread->dumpImage(argv[1]);
2913 * remove all the code inserted into target program
2915 int detachCommand(ClientData, Tcl_Interp *, int argc, TCLCONST char **)
2918 printf("Usage: detach\n");
2922 if (!haveApp()) return TCL_ERROR;
2924 appThread->detach(true);
2930 * enable or disable debug parse of the mutatee
2932 int debugParse(ClientData, Tcl_Interp *, int argc, TCLCONST char **argv)
2935 printf("Usage: debugparse [enable | disable]");
2940 printf("Debug parsing is %s\n", (bpatch->parseDebugInfo()?"on":"off") );
2941 printf("Usage: debugparse [enable | disable]\n");
2946 if ( !strcmp(argv[1], "enable") )
2948 else if ( !strcmp(argv[1], "disable") )
2951 printf("Invalid option for debugparse command.\n");
2952 printf("Usage: debugparse [enable | disable]");
2956 bpatch->setDebugParsing(flag);
2961 int exitDyner(ClientData, Tcl_Interp *, int, TCLCONST char **)
2965 // this forces terminatation if the app has not been detached
2966 if (appThread) delete appThread;
2973 int Tcl_AppInit(Tcl_Interp *interp)
2975 if (Tcl_Init(interp) == TCL_ERROR) {
2979 //Create BPatch library
2980 bpatch = new BPatch;
2984 Tcl_CreateCommand(interp, "at", (Tcl_CmdProc*)instStatement, NULL, NULL);
2985 Tcl_CreateCommand(interp, "attach", (Tcl_CmdProc*)attachPid, NULL, NULL);
2986 Tcl_CreateCommand(interp, "break", (Tcl_CmdProc*)condBreak, NULL, NULL);
2987 Tcl_CreateCommand(interp, "declare", (Tcl_CmdProc*)newVar, NULL, NULL);
2988 Tcl_CreateCommand(interp, "listbreak", (Tcl_CmdProc*)listBreak, NULL, NULL);
2989 Tcl_CreateCommand(interp, "deletebreak", (Tcl_CmdProc*)deleteBreak, NULL, NULL);
2990 Tcl_CreateCommand(interp, "dset", (Tcl_CmdProc*)dsetCommand, NULL, NULL);
2991 Tcl_CreateCommand(interp, "help", (Tcl_CmdProc*)help, NULL, NULL);
2992 Tcl_CreateCommand(interp, "exit", (Tcl_CmdProc*)exitDyner, NULL, NULL);
2993 Tcl_CreateCommand(interp, "kill", (Tcl_CmdProc*)killApp, NULL, NULL);
2994 Tcl_CreateCommand(interp, "load", (Tcl_CmdProc*)loadCommand, NULL, NULL);
2995 Tcl_CreateCommand(interp, "run", (Tcl_CmdProc*)runApp, NULL, NULL);
2996 Tcl_CreateCommand(interp, "print", (Tcl_CmdProc*)printVar, NULL, NULL);
2997 Tcl_CreateCommand(interp, "whatis", (Tcl_CmdProc*)whatisVar, NULL, NULL);
2998 Tcl_CreateCommand(interp, "show", (Tcl_CmdProc*)showCommand, NULL, NULL);
2999 Tcl_CreateCommand(interp, "find", (Tcl_CmdProc*)findAndShowCommand, NULL, NULL);
3000 Tcl_CreateCommand(interp, "verbose", (Tcl_CmdProc*)verboseCommand, NULL, NULL);
3001 Tcl_CreateCommand(interp, "count", (Tcl_CmdProc*)countCommand, NULL, NULL);
3002 Tcl_CreateCommand(interp, "replace", (Tcl_CmdProc*)replaceCommand, NULL, NULL);
3003 Tcl_CreateCommand(interp, "trace", (Tcl_CmdProc*)traceCommand, NULL, NULL);
3004 Tcl_CreateCommand(interp, "untrace", (Tcl_CmdProc*)untraceCommand, NULL, NULL);
3005 Tcl_CreateCommand(interp, "mutations", (Tcl_CmdProc*)mutationsCommand, NULL, NULL);
3006 Tcl_CreateCommand(interp, "removecall", (Tcl_CmdProc*)removeCommand, NULL, NULL);
3007 //Tcl_CreateCommand(interp, "dump", (Tcl_CmdProc*)dumpCommand, NULL, NULL);
3008 Tcl_CreateCommand(interp, "detach", (Tcl_CmdProc*)detachCommand, NULL, NULL);
3009 Tcl_CreateCommand(interp, "execute", (Tcl_CmdProc*)execStatement, NULL, NULL);
3010 Tcl_CreateCommand(interp, "listinst", (Tcl_CmdProc*)listInstrument, NULL, NULL);
3011 Tcl_CreateCommand(interp, "deleteinst", (Tcl_CmdProc*)deleteInstrument, NULL, NULL);
3012 Tcl_CreateCommand(interp, "debugparse", (Tcl_CmdProc*)debugParse, NULL, NULL);
3013 #if defined(rs6000_ibm_aix4_1) || defined(sparc_sun_solaris2_4) || defined(i386_unknown_linux2_0)
3015 Tcl_CreateCommand(interp, "where", (Tcl_CmdProc*)where, NULL, NULL);
3016 Tcl_CreateCommand(interp, "up", (Tcl_CmdProc*)whereUp, NULL, NULL);
3017 Tcl_CreateCommand(interp, "down", (Tcl_CmdProc*)whereDown, NULL, NULL);
3019 Tcl_CreateCommand(interp, "save", (Tcl_CmdProc*)saveWorld, NULL, NULL);
3020 Tcl_CreateCommand(interp, "saveStart", (Tcl_CmdProc*)saveStart, NULL, NULL);
3024 Tcl_AllowExceptions(interp);
3026 bpatch->registerErrorCallback(errorFunc);
3027 bpatch->setTypeChecking(false);
3028 bpatch->registerExitCallback(&exitCallback);
3033 int main(int argc, char *argv[])
3035 if (argc >= 2 && !strcmp(argv[1], "-debug")) {
3036 printf("parser debug enabled\n");
3041 #if !defined(i386_unknown_nt4_0)
3042 signal(SIGINT, INThandler);
3045 Tcl_Main(argc, argv, Tcl_AppInit);
3050 template class DynerList<BPListElem*>;
3051 template class DynerList<IPListElem*>;
3052 template class DynerList<runtimeVar*>;