00001
00211 #include <signal.h>
00212 #include <ctype.h>
00213 #include <string.h>
00214
00215 #include "platform.h"
00216 #include "output.h"
00217 #include "exec.h"
00218 #include "class.h"
00219 #include "convert.h"
00220 #include "object.h"
00221 #include "index.h"
00222 #include "realtime.h"
00223 #include "module.h"
00224 #include "threadpool.h"
00225 #include "debug.h"
00226 #include "kill.h"
00227
00228 #ifndef _MAX_PATH
00229 #define _MAX_PATH 1024
00230 #endif
00231
00232
00233 extern const PASSCONFIG passtype[];
00234 extern int iteration_counter;
00235
00236
00237 int siglist[] = {SIGABRT, SIGINT, SIGFPE, SIGSEGV, SIGTERM};
00238
00239 static char *get_objname(OBJECT *obj)
00240 {
00241 static char buf[1024];
00242 if (obj->name) return obj->name;
00243 sprintf(buf,"%s:%d", obj->oclass->name, obj->id);
00244 return buf;
00245 }
00246
00247
00248 static int debug_active = 1;
00249 static int error_caught = 0;
00250 static int watch_sync = 0;
00251 int stop_now = 0;
00252 static int sigint_caught = 0;
00253 static int sigterm_caught = 0;
00254 static int list_details = 0;
00255 static int list_unnamed = 1;
00256 static int list_inactive = 1;
00257 static int list_sync = 1;
00259 static STATUS exec(char *format,...)
00260 {
00261 char cmd[1024];
00262 va_list ptr;
00263 va_start(ptr,format);
00264 vsprintf(cmd,format,ptr);
00265 va_end(ptr);
00266 output_debug("Running '%s'", cmd);
00267 return system(cmd)==0?SUCCESS:FAILED;
00268 }
00269
00270 void debug_notify_error(void)
00271 {
00272 error_caught = 1;
00273 }
00274
00281 void exec_sighandler(int sig)
00282 {
00283 output_debug("signal %s caught", strsignal(sig));
00284 if (sig==SIGTERM)
00285 {
00286 output_error("received SIGTERM; exiting now");
00287
00288
00289
00290
00291
00292
00293 exit(1);
00294 }
00295 else if (sig==SIGABRT)
00296 {
00297 output_error("received SIGABRT; exiting now");
00298
00299
00300
00301
00302
00303
00304 exit(1);
00305 }
00306 else if (sig==SIGINT)
00307 {
00308 sigint_caught=1;
00309 if (global_debug_mode)
00310 {
00311 if (debug_active==0)
00312 {
00313 output_debug("debugger activated");
00314 debug_active=1;
00315 }
00316 else
00317 {
00318 output_debug("debugger activation failed, signal processing disabled");
00319 debug_active=1;
00320 signal(sig,NULL);
00321 }
00322 }
00323 else
00324 stop_now=1;
00325 }
00326 else
00327 output_error("ignored signal %d", sig);
00328
00329
00330
00331
00332
00333
00334 }
00335
00336 #ifdef WIN32
00337 char *strsignal(int sig)
00338 {
00339 switch(sig) {
00340 case SIGABRT: return "SIGABRT";
00341 case SIGFPE: return "SIGFPE";
00342 case SIGILL: return "SIGILL";
00343 case SIGINT: return "SIGINT";
00344 case SIGSEGV: return "SIGSEGV";
00345 case SIGTERM: return "SIGTERM";
00346 default: return "SIGUNKNOWN";
00347 }
00348 }
00349 #endif
00350
00351 typedef enum {DBG_QUIT,DBG_RUN,DBG_NEXT} DEBUGCMD;
00352 typedef enum {BP_MODULE, BP_CLASS, BP_OBJECT, BP_PASS, BP_RANK, BP_TIME, BP_CLOCK, BP_ERROR} BREAKPOINTTYPE;
00353 typedef struct s_breakpoint {
00354 BREAKPOINTTYPE type;
00355 int enabled;
00356 int num;
00357 union {
00358 MODULE *mod;
00359 CLASS *oclass;
00360 OBJECT *obj;
00361 int64 pass;
00362 int64 rank;
00363 TIMESTAMP ts;
00364 int64 data;
00365 };
00366 struct s_breakpoint *next;
00367 } BREAKPOINT;
00368 static BREAKPOINT *first_breakpoint=NULL,
00369 *last_breakpoint=NULL;
00370 static int breakpoint_count=0;
00374 static int exec_add_breakpoint(BREAKPOINTTYPE type,
00375 int64 data)
00376 {
00377 BREAKPOINT *bp = (BREAKPOINT*)malloc(sizeof(BREAKPOINT));
00378 if (bp==NULL)
00379 {
00380 output_error("exec_add_breakpoint() - memory allocation failed");
00381
00382
00383
00384
00385
00386 return 0;
00387 }
00388 bp->type = type;
00389 bp->data = data;
00390 bp->enabled = 1;
00391 bp->num = breakpoint_count++;
00392 bp->next = NULL;
00393 if (last_breakpoint!=NULL)
00394 last_breakpoint->next=bp;
00395 else
00396 first_breakpoint=bp;
00397 last_breakpoint = bp;
00398 return 1;
00399 }
00400
00401 typedef struct s_watchpoint {
00402 int enabled;
00403 int num;
00404 OBJECT *obj;
00405 PROPERTY *prop;
00406 char buffer[4096];
00407 struct s_watchpoint *next;
00408 } WATCHPOINT;
00409 static WATCHPOINT *first_watchpoint=NULL,
00410 *last_watchpoint=NULL;
00411 static int watchpoint_count=0;
00415 static int exec_add_watchpoint(OBJECT *obj,
00416 PROPERTY *prop)
00417 {
00418 WATCHPOINT *wp = (WATCHPOINT*)malloc(sizeof(WATCHPOINT));
00419 if (wp==NULL)
00420 {
00421 output_error("exec_add_watchpoint() - memory allocation failed");
00422
00423
00424
00425
00426
00427 return 0;
00428 }
00429 wp->enabled = 1;
00430 wp->num = watchpoint_count++;
00431 wp->obj = obj;
00432 wp->prop = prop;
00433 if (prop==NULL)
00434 object_dump(wp->buffer,sizeof(wp->buffer),obj);
00435 else
00436 strcpy(wp->buffer,object_property_to_string(obj,prop->name));
00437 wp->next = NULL;
00438 if (last_watchpoint!=NULL)
00439 last_watchpoint->next=wp;
00440 else
00441 first_watchpoint=wp;
00442 last_watchpoint = wp;
00443 return 1;
00444 }
00445
00446 static void list_object(OBJECT *obj, PASSCONFIG pass)
00447 {
00448 char details[132] = "";
00449 char buf1[64],buf2[64],buf3[64];
00450 if (list_unnamed==0 && obj->name==NULL)
00451 return;
00452 if (list_inactive==0 && (global_clock<obj->in_svc || global_clock>obj->out_svc))
00453 return;
00454 if (list_sync==0 && obj->oclass->sync==NULL)
00455 return;
00456 if (list_details)
00457 {
00458 char valid_to[64] = "";
00459 convert_from_timestamp(obj->valid_to,valid_to,sizeof(valid_to));
00460 sprintf(details,"%s %c%c%c %s/%s/%d ", valid_to,
00461 obj->flags&OF_RECALC?'c':'-', obj->flags&OF_RERANK?'r':'-', obj->flags&OF_FOREIGN?'f':'-',
00462 obj->oclass->module->name, obj->oclass->name, obj->id);
00463 }
00464 output_message("%1s%1s%1s%1s%1s%1s %4d %-24s %-16s %-16s %s",
00465 global_clock<obj->in_svc?"P":(global_clock<obj->out_svc?"A":"R"),
00466 (obj->oclass->passconfig&PC_PRETOPDOWN)?(pass<PC_PRETOPDOWN?"t":"T"):"-",
00467 (obj->oclass->passconfig&PC_BOTTOMUP)?(pass<PC_BOTTOMUP?"b":"B"):"-",
00468 (obj->oclass->passconfig&PC_POSTTOPDOWN)?(pass<PC_POSTTOPDOWN?"t":"T"):"-",
00469 (obj->flags&OF_LOCKED)==OF_LOCKED?"l":"-",
00470 (obj->flags&OF_HASPLC)==OF_HASPLC?"x":"-",
00471 obj->rank,
00472 obj->clock>0?(convert_from_timestamp(obj->clock,buf3,sizeof(buf3))?buf3:"(error)"):"INIT",
00473 obj->name?obj->name:convert_from_object(buf1,sizeof(buf1),&obj,NULL)?buf1:"(error)",
00474 obj->parent?(obj->parent->name?obj->parent->name:convert_from_object(buf2,sizeof(buf2),&(obj->parent),NULL)?buf2:"(error)"):"ROOT",
00475 details);
00476 }
00477
00478 FILE *load_fp;
00479 int load_from_file = 0;
00483 DEBUGCMD exec_debug_cmd(struct sync_data *data,
00484 int pass,
00485 int index,
00486 OBJECT *obj)
00487 {
00488 static DEBUGCMD last = DBG_NEXT;
00489 char tmp[64];
00490 char* read_val;
00491
00492 output_debug("time %s\r", convert_from_timestamp(global_clock,tmp,sizeof(tmp))?tmp:"(invalid)");
00493 output_debug("pass %s, rank %d, object %s, iteration %d",
00494 passtype[pass]==PC_PRETOPDOWN?"PRETOPDOWN":(passtype[pass]==PC_BOTTOMUP?"BOTTOMUP":(passtype[pass]==PC_POSTTOPDOWN?"POSTTOPDOWN":"(invalid)")),
00495 index, get_objname(obj),
00496 global_iteration_limit-iteration_counter+1);
00497 {
00498 extern void (*notify_error)(void);
00499 if (notify_error != NULL)
00500 output_debug("output errors are trapped");
00501 }
00502 while (1)
00503 {
00504 char cmd[32]="";
00505 char buffer[1024]="";
00506 int i;
00507 Retry:
00508
00509 for (i=0; i<sizeof(siglist)/sizeof(siglist[0]); i++)
00510 signal(siglist[i],exec_sighandler);
00511
00512 if(load_from_file == 0){
00513 fprintf(stdout,"GLD> ");
00514 sigint_caught=0;
00515 fflush(stdout);
00516
00517 gets(buffer);
00518 output_verbose("debug command '%s'", buffer);
00519 }
00520 else{
00521 char* nl;
00522 read_val = fgets(buffer,1024,load_fp);
00523
00524
00525 if(read_val == NULL)
00526 {
00527 load_from_file = 0;
00528 fclose(load_fp);
00529 goto Retry;
00530 }
00531
00532 nl = strrchr(buffer,'\r');
00533 if(nl)
00534 *nl = '\0';
00535 nl = strrchr(buffer,'\n');
00536 if(nl)
00537 *nl = '\0';
00538 }
00539 sscanf(buffer,"%s",cmd);
00540 if (sigint_caught==1)
00541 {
00542 fprintf(stdout,"<Ctrl-C>\n");
00543 goto Retry;
00544 }
00545 if (strncmp(cmd,"quit",max(1,strlen(cmd)))==0)
00546 return DBG_QUIT;
00547 else if (strncmp(cmd,"run",max(1,strlen(cmd)))==0 || (strlen(cmd)==0&&last==DBG_RUN))
00548 {
00549 output_debug("resuming simulation, Ctrl-C interrupts");
00550 debug_active=0;
00551 return last = DBG_RUN;
00552 }
00553 else if (strncmp(cmd,"next",max(1,strlen(cmd)))==0 || (strlen(cmd)==0&&last==DBG_NEXT))
00554 {
00555 return last = DBG_NEXT;
00556 }
00557 else if (strncmp(cmd,"module",max(1,strlen(cmd)))==0)
00558 {
00559 char modname[128];
00560
00561 if(sscanf(buffer,"%*s %s", modname)){
00562 output_message("Loading module %s...", modname);
00563 module_load(modname, 0, NULL);
00564 } else {
00565 MODULE *mod = module_get_first();
00566 output_message("Loaded modules:");
00567 while(mod != NULL){
00568 output_message(" * %s v%i.%i", mod->name, mod->major, mod->minor);
00569 mod = mod->next;
00570 }
00571 }
00572 }
00573 else if (strncmp(cmd,"namespace",max(2,strlen(cmd)))==0)
00574 {
00575 char space[1024];
00576 if (sscanf(buffer,"%*s %s", space)==0)
00577 {
00578 object_namespace(space,sizeof(space));
00579 output_debug("%s",space[0]=='\0'?space:"(global)");
00580 }
00581 else if (!object_select_namespace(space))
00582 output_debug("unable to select namespace '%s'", space);
00583 }
00584 else if (strncmp(cmd,"list",max(1,strlen(cmd)))==0)
00585 {
00586 char lclass[256]="";
00587 OBJECT *obj = object_get_first();
00588 sscanf(buffer,"%*s %s", lclass);
00589
00590
00591
00592
00593 for (obj=object_get_first(); obj!=NULL; obj=obj->next)
00594 {
00595 if (lclass[0]=='\0' || strcmp(lclass,obj->oclass->name)==0)
00596 list_object(obj,pass);
00597 }
00598 }
00599 else if (strncmp(cmd,"details",max(1,strlen(cmd)))==0)
00600 {
00601 char cmd[1024];
00602 int n = sscanf(buffer,"%*s %[^\0]", cmd);
00603 if (n==1)
00604 {
00605 if (strcmp(cmd,"on")==0)
00606 list_details = 1;
00607 else if (strcmp(cmd,"off")==0)
00608 list_details = 0;
00609 else
00610 output_error("'%s' is an invalid option to details command", cmd);
00611
00612
00613
00614
00615 }
00616 else if (n==0)
00617 output_debug("Details are %s", list_details?"on":"off");
00618 else
00619 output_error("details command syntax error");
00620
00621
00622
00623
00624
00625 }
00626 else if (strncmp(cmd,"inactive",max(1,strlen(cmd)))==0)
00627 {
00628 char cmd[1024];
00629 int n = sscanf(buffer,"%*s %[^\0]", cmd);
00630 if (n==1)
00631 {
00632 if (strcmp(cmd,"on")==0)
00633 list_inactive = 1;
00634 else if (strcmp(cmd,"off")==0)
00635 list_inactive = 0;
00636 else
00637 output_error("'%s' is an invalid option to inactive command", cmd);
00638
00639
00640
00641
00642 }
00643 else if (n==0)
00644 output_debug("Inactive objects are %s", list_details?"on":"off");
00645 else
00646 output_error("inactive command syntax error");
00647
00648
00649
00650
00651
00652 }
00653 else if (strncmp(cmd,"unnamed",max(1,strlen(cmd)))==0)
00654 {
00655 char cmd[1024];
00656 int n = sscanf(buffer,"%*s %[^\0]", cmd);
00657 if (n==1)
00658 {
00659 if (strcmp(cmd,"on")==0)
00660 list_unnamed = 1;
00661 else if (strcmp(cmd,"off")==0)
00662 list_unnamed = 0;
00663 else
00664 output_error("'%s' is an invalid option to unnamed command", cmd);
00665
00666
00667
00668
00669 }
00670 else if (n==0)
00671 output_debug("Unnamed objects are %s", list_details?"on":"off");
00672 else
00673 output_error("unnamed command syntax error");
00674
00675
00676
00677
00678
00679 }
00680 else if (strncmp(cmd,"nsync",max(2,strlen(cmd)))==0)
00681 {
00682 char cmd[1024];
00683 int n = sscanf(buffer,"%*s %[^\0]", cmd);
00684 if (n==1)
00685 {
00686 if (strcmp(cmd,"on")==0)
00687 list_sync = 1;
00688 else if (strcmp(cmd,"off")==0)
00689 list_sync = 0;
00690 else
00691 output_error("'%s' is an invalid nsync command", cmd);
00692
00693
00694
00695
00696 }
00697 else if (n==0)
00698 output_debug("Sync objects are %s", list_details?"on":"off");
00699 else
00700 output_error("nsync command syntax error");
00701
00702
00703
00704
00705
00706 }
00707 else if (strncmp(cmd,"script",max(1,strlen(cmd)))==0)
00708 {
00709 char load_filename[_MAX_PATH+32];
00710 if(sscanf(buffer,"%*s %[^\x20]",load_filename) <=0)
00711 {
00712 output_error("missing file name for script command");
00713
00714
00715
00716
00717 }
00718 load_fp = fopen(load_filename,"r");
00719 if(load_fp == NULL)
00720 {
00721 output_error("unable to open file %s for reading",load_filename);
00722
00723
00724
00725
00726 }
00727 load_from_file = 1;
00728 }
00729 else if (strncmp(cmd,"system",max(2,strlen(cmd)))==0)
00730 {
00731 char cmd[1024];
00732 if (sscanf(buffer,"%*s %[^\0]", cmd)==1)
00733 system(cmd);
00734 #ifdef WIN32
00735 else if (getenv("COMSPEC")!=NULL)
00736 system(getenv("COMSPEC"));
00737 else
00738 system("cmd");
00739 #else
00740 else if (getenv("SHELL")!=NULL)
00741 system(getenv("SHELL"));
00742 else
00743 system("/bin/sh");
00744 #endif
00745 }
00746 else if (strncmp(cmd,"break",max(1,strlen(cmd)))==0)
00747 {
00748 char bptype[256]="";
00749 char bpval[256]="";
00750 if (sscanf(buffer,"%*s %s %[^\0]", bptype, bpval)==0)
00751 {
00752
00753 BREAKPOINT *bp;
00754 if (last_breakpoint==NULL)
00755 output_debug("no breakpoints");
00756 for (bp=first_breakpoint; bp!=NULL; bp=bp->next)
00757 {
00758 char tmp[64];
00759 switch (bp->type) {
00760 case BP_MODULE:
00761 output_debug("breakpoint %2d - module %s %s", bp->num, bp->mod->name, bp->enabled?"":"(disabled)");
00762 break;
00763 case BP_CLASS:
00764 output_debug("breakpoint %2d - class %s %s", bp->num, bp->oclass->name, bp->enabled?"":"(disabled)");
00765 break;
00766 case BP_OBJECT:
00767 output_debug("breakpoint %2d object %s %s", bp->num, get_objname(bp->obj), bp->enabled?"":"(disabled)");
00768 break;
00769 case BP_PASS:
00770 output_debug("breakpoint %2d pass %s %s", bp->num, (int)bp->pass==PC_PRETOPDOWN?"pretopdown":((int)bp->pass==PC_BOTTOMUP?"bottomup":((int)bp->pass==PC_POSTTOPDOWN?"posttopdown":"(invalid)")), bp->enabled?"":"(disabled)");
00771 break;
00772 case BP_RANK:
00773 output_debug("breakpoint %2d rank %d %s", bp->num, (int)bp->rank, bp->enabled?"":"(disabled)");
00774 break;
00775 case BP_TIME:
00776 output_debug("breakpoint %2d time %s (%"FMT_INT64"d) %s", bp->num, convert_from_timestamp(bp->ts,tmp,sizeof(tmp))?tmp:"(invalid)", bp->ts, bp->enabled?"":"(disabled)");
00777 break;
00778 case BP_CLOCK:
00779 output_debug("breakpoint %2d clock %s", bp->num, bp->enabled?"":"(disabled)");
00780 break;
00781 case BP_ERROR:
00782 output_debug("breakpoint %2d on error", bp->num, bp->enabled?"":"(disabled)");
00783 break;
00784 default:
00785 break;
00786 }
00787 }
00788 }
00789 else if (strncmp(bptype,"error",strlen(bptype))==0)
00790 {
00791 if (!exec_add_breakpoint(BP_ERROR,0))
00792 output_error("unable to add error breakpoint");
00793
00794
00795
00796
00797
00798
00799 error_caught = 0;
00800 output_notify_error(debug_notify_error);
00801 }
00802 else if (strncmp(bptype,"clock",strlen(bptype))==0)
00803 {
00804 if (!exec_add_breakpoint(BP_CLOCK,global_clock))
00805 output_error("unable to add clock breakpoint");
00806
00807
00808
00809
00810
00811
00812 }
00813 else if (strncmp(bptype,"object",strlen(bptype))==0)
00814 {
00815 OBJECT *obj = object_find_name(bpval);
00816 if (obj!=NULL || convert_to_object(bpval,&obj,NULL))
00817 {
00818 if (!exec_add_breakpoint(BP_OBJECT,(int64)obj))
00819 output_error("unable to add object breakpoint");
00820
00821
00822
00823
00824
00825
00826 }
00827 else
00828 output_error("object %s does not exist",bpval);
00829
00830
00831
00832
00833 }
00834 else if (strncmp(bptype,"module",strlen(bptype))==0)
00835 {
00836 MODULE *mod = module_find(bpval);
00837 if (mod!=NULL)
00838 {
00839 if (!exec_add_breakpoint(BP_MODULE,(int64)mod))
00840 output_error("unable to add module breakpoint");
00841
00842
00843
00844
00845
00846
00847 }
00848 else
00849 output_error("module %s does not exist",bpval);
00850
00851
00852
00853
00854 }
00855 else if (strncmp(bptype,"class",strlen(bptype))==0)
00856 {
00857 CLASS *oclass = class_get_class_from_classname(bpval);
00858 if (oclass!=NULL)
00859 {
00860 if (!exec_add_breakpoint(BP_CLASS,(int64)oclass))
00861 output_error("unable to add class breakpoint");
00862
00863
00864
00865
00866
00867
00868 }
00869 else
00870 output_debug("class %s does not exist",bpval);
00871 }
00872 else if (strncmp(bptype,"pass",strlen(bptype))==0)
00873 {
00874 int pass;
00875 if (strnicmp(bpval,"pretopdown",max(2,strlen(bpval)))==0) pass=PC_PRETOPDOWN;
00876 else if (strnicmp(bpval,"bottomup",strlen(bpval))==0) pass=PC_BOTTOMUP;
00877 else if (strnicmp(bpval,"posttopdown",max(2,strlen(bpval)))==0) pass=PC_POSTTOPDOWN;
00878 else
00879 {
00880 output_error("undefined pass type for add breakpoint");
00881
00882
00883
00884
00885
00886 continue;
00887 }
00888 if (!exec_add_breakpoint(BP_PASS,(int64)pass))
00889 output_error("unable to add pass breakpoint");
00890
00891
00892
00893
00894
00895
00896 }
00897 else if (strncmp(bptype,"rank",strlen(bptype))==0)
00898 {
00899 if (!exec_add_breakpoint(BP_RANK,(int64)atoi(bpval)))
00900 output_error("unable to add rank breakpoint");
00901
00902
00903
00904
00905 }
00906 else if (strncmp(bptype,"time",strlen(bptype))==0)
00907 {
00908 TIMESTAMP ts = convert_to_timestamp(bpval);
00909 if (ts==TS_NEVER)
00910 output_error("invalid time");
00911
00912
00913
00914
00915 else if (!exec_add_breakpoint(BP_TIME,(int64)ts))
00916 output_error("unable to add timestamp breakpoint");
00917
00918
00919
00920
00921
00922
00923 }
00924 else if (strncmp(bptype,"disable",strlen(bptype))==0)
00925 {
00926 int n=-1;
00927 BREAKPOINT *bp;
00928 if (strcmp(bpval,"")!=0)
00929 {
00930 if (isdigit(bpval[0]))
00931 n=atoi(bpval);
00932 else
00933 {
00934 output_error("invalid breakpoint number");
00935
00936
00937
00938
00939 continue;
00940 }
00941 }
00942 for (bp=first_breakpoint; bp!=NULL; bp=bp->next)
00943 {
00944 if (bp->num==n || n==-1)
00945 bp->enabled = 0;
00946 }
00947 }
00948 else if (strncmp(bptype,"enable",strlen(bptype))==0)
00949 {
00950 int n=-1;
00951 BREAKPOINT *bp;
00952 if (strcmp(bpval,"")!=0)
00953 {
00954 if (isdigit(bpval[0]))
00955 n=atoi(bpval);
00956 else
00957 {
00958 output_error("invalid breakpoint number");
00959
00960 continue;
00961 }
00962 }
00963 for (bp=first_breakpoint; bp!=NULL; bp=bp->next)
00964 {
00965 if (bp->num==n || n==-1)
00966 bp->enabled = 1;
00967 }
00968 }
00969 else
00970 output_error("%s is not a recognized breakpoint subcommand", bptype);
00971
00972
00973
00974
00975 }
00976 else if (strncmp(cmd,"watch",max(2,strlen(cmd)))==0)
00977 {
00978 char wptype[256]="";
00979 char wpval[256]="";
00980 OBJECT *obj;
00981 if (sscanf(buffer,"%*s %s %[^\0]", wptype, wpval)==0)
00982 {
00983
00984 WATCHPOINT *wp;
00985 if (last_watchpoint==NULL)
00986 output_debug("no watchpoints");
00987 for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
00988 {
00989 if (wp->prop==NULL)
00990 output_debug("watchpoint %d - object %s %s", wp->num, get_objname(wp->obj), wp->enabled?"":"(disabled)");
00991 else
00992 output_debug("watchpoint %d - object %s %s - property %s", wp->num, get_objname(wp->obj), wp->enabled?"":"(disabled)", wp->prop->name);
00993 }
00994 }
00995 else if (isdigit(wptype[0]))
00996 {
00997 int n=atoi(wptype);
00998 WATCHPOINT *wp;
00999 for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
01000 {
01001 if (wp->num==n)
01002 output_debug("watchpoint %d - object %s %s\n%s",
01003 wp->num, get_objname(wp->obj), wp->enabled?"":"(disabled)",wp->buffer);
01004 }
01005 }
01006 else if (strcmp(wptype,"sync")==0)
01007 {
01008 watch_sync = !watch_sync;
01009 output_debug("sync watch is %s",watch_sync?"enabled":"disabled");
01010 }
01011 else if (strncmp(wptype,"disable",strlen(wptype))==0)
01012 {
01013 int n=-1;
01014 WATCHPOINT *wp;
01015 if (strcmp(wpval,"")!=0)
01016 {
01017 if (isdigit(wpval[0]))
01018 n=atoi(wpval);
01019 else
01020 {
01021 output_error("invalid watchpoint number");
01022
01023
01024
01025
01026 continue;
01027 }
01028 }
01029 for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
01030 {
01031 if (wp->num==n || n==-1)
01032 wp->enabled = 0;
01033 }
01034 }
01035 else if (strncmp(wptype,"enable",strlen(wptype))==0)
01036 {
01037 int n=-1;
01038 WATCHPOINT *wp;
01039 if (strcmp(wpval,"")!=0)
01040 {
01041 if (isdigit(wpval[0]))
01042 n=atoi(wpval);
01043 else
01044 {
01045 output_error("invalid watchpoint number");
01046
01047 continue;
01048 }
01049 }
01050 for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
01051 {
01052 if (wp->num==n || n==-1)
01053 wp->enabled = 1;
01054 }
01055 }
01056 else if ((obj=object_find_name(wptype)) || convert_to_object(wptype,&obj,NULL))
01057 {
01058 if (strcmp(wpval,"")!=0)
01059 {
01060 PROPERTY *prop = object_get_property(obj,wpval);
01061 if (prop==NULL)
01062 output_error("object %s does not have a property named '%s'", wptype,wpval);
01063
01064
01065
01066
01067 else if (!exec_add_watchpoint(obj,prop))
01068 output_error("unable to add object watchpoint");
01069
01070
01071
01072
01073
01074
01075 }
01076 else if (!exec_add_watchpoint(obj,NULL))
01077 output_error("unable to add object watchpoint");
01078
01079 }
01080 else
01081 output_error("%s is not recognized", wptype);
01082
01083
01084
01085
01086 }
01087 else if (strncmp(cmd,"where",max(1,strlen(cmd)))==0)
01088 {
01089 char ts[64];
01090 output_debug("Global clock... %s (%" FMT_INT64 "d)", convert_from_timestamp(global_clock,ts,sizeof(ts))?ts:"(invalid)",global_clock);
01091 output_debug("Hard events.... %d", data->hard_event);
01092 output_debug("Sync status.... %s", data->status==FAILED?"FAILED":"SUCCESS");
01093 output_debug("Step to time... %s (%" FMT_INT64 "d)", convert_from_timestamp(data->step_to,ts,sizeof(ts))?ts:"(invalid)",data->step_to);
01094 output_debug("Pass........... %d", pass);
01095 output_debug("Rank........... %d", index);
01096 output_debug("Object......... %s",get_objname(obj));
01097 }
01098 else if (strncmp(cmd,"print",max(1,strlen(cmd)))==0)
01099 {
01100 char tmp[4096];
01101 if (sscanf(buffer,"%*s %s",tmp)==0)
01102 {
01103 if (object_dump(tmp,sizeof(tmp),obj))
01104 output_debug("%s",tmp);
01105 else
01106 output_error("object dump failed");
01107
01108
01109
01110
01111
01112 }
01113 else
01114 {
01115 OBJECT *obj = object_find_name(tmp);
01116 if (obj!=NULL || convert_to_object(tmp,&obj,NULL))
01117 {
01118 if (object_dump(tmp,sizeof(tmp),obj))
01119 output_debug("%s",tmp);
01120 else
01121 output_error("object dump failed");
01122
01123 }
01124 else
01125 output_error("object %s undefined", tmp);
01126
01127
01128
01129
01130 }
01131 }
01132 else if (strncmp(cmd,"globals",max(1,strlen(cmd)))==0)
01133 {
01134 GLOBALVAR *var;
01135 for (var=global_getnext(NULL); var!=NULL; var=global_getnext(var))
01136 {
01137 char *val = global_getvar(var->name, NULL, 0);
01138 if (val!=NULL && strlen(val)>64)
01139 strcpy(val+28,"...");
01140 output_message("%-32.32s: \"%s\"", var->name, val==NULL?"(error)":val);
01141 }
01142 }
01143 else if (strncmp(cmd,"set",max(1,strlen(cmd)))==0)
01144 {
01145 char256 objname;
01146 char256 propname;
01147 char256 value;
01148 int scanct = 0;
01149 value[0] = '\0';
01150 if ((scanct=sscanf(buffer,"%*s %s %s %s",objname,propname,value))>=2)
01151 {
01152 OBJECT *obj;
01153 if (strcmp(objname,"global")==0)
01154 {
01155 if (global_setvar(propname,value)==FAILED)
01156 output_error("unable to set global value %s", propname);
01157
01158
01159
01160
01161
01162
01163 }
01164 else if ((obj=object_find_name(objname)) || convert_to_object(objname,&obj,NULL))
01165 {
01166 if (!object_set_value_by_name(obj,propname,value))
01167 output_error("unable to set value of object %s property %s", objname,propname);
01168
01169
01170
01171
01172
01173 else if (!object_get_property(obj,propname))
01174 output_error("invalid property for object %s",objname);
01175
01176
01177
01178
01179 }
01180 else
01181 output_error("invalid object or value");
01182
01183
01184
01185
01186
01187
01188 }
01189 else{
01190 output_error("set syntax error (%i items)", scanct);
01191
01192
01193
01194
01195 }
01196 }
01197 else if (strncmp(cmd,"find ",max(1,strlen(cmd)))==0)
01198 {
01199 FINDLIST *fl = NULL;
01200 OBJECT *obj = NULL;
01201 output_debug("running search with \"%s\"", buffer+5);
01202 fl = find_objects(FL_GROUP, buffer+5);
01203 obj = find_first(fl);
01204
01205
01206
01207 for (obj=find_first(fl); obj!=NULL; obj=find_next(fl, obj))
01208 list_object(obj,pass);
01209 }
01210 else if (strncmp(cmd,"gdb",3)==0)
01211 {
01212 if (exec("gdb --quiet %s --pid=%d",global_execname,global_process_id)<=0)
01213 output_debug("unable to start gdb");
01214 }
01215 else if (strncmp(cmd,"help",max(1,strlen(cmd)))==0)
01216 {
01217 output_debug("Summary of debug commands\n"
01218 " break prints all breakpoints\n"
01219 " clock stop the simulator on clock advance\n"
01220 " error stop the simulator is an error occurs\n"
01221 " object <X> stop the simulator on sync of object X\n"
01222 " module <X> stop the simulator on sync of module X\n"
01223 " class <X> stop the simulator on sync of class X\n"
01224 " pass <X> stop the simulator on the start of pass X\n"
01225 " rank <X> stop the simulation on the start of rank X\n"
01226 " time <X> stop the simulation at the time time X\n"
01227 " disable disables all breakpoints\n"
01228 " enable enables all breakpoints\n"
01229 " disable <#> disables breakpoint #\n"
01230 " enable <#> enables breakpoint #\n"
01231 " details on|off enables/disables details in list\n"
01232 " globals print global variables\n"
01233 " inactive on|off enables/disables listing of inactive objects\n"
01234 " list list objects\n"
01235 " <X> list objects of class X\n"
01236 " module list loaded modules\n"
01237 " <X> load module X\n"
01238 " next advances to the next object sync\n"
01239 " print <X> prints object X\n"
01240 " quit quits the simulator\n"
01241 " run runs the simulator until the next break point\n"
01242 " set <X> <Y> <val> set object X property Y to <val>\n"
01243 " script <filename> read a script file containing debugger commands\n"
01244 " nsync on|off enables/disables listing of non-synchronizing objects\n"
01245 " system opens a shell on the current OS\n"
01246 " <command> executes the command on the current OS\n"
01247 " unnamed on|off enables/disables listing of unnamed objects\n"
01248 " watch prints all watchpoints\n"
01249 " <#> prints watchpoint #\n"
01250 " <X> stop the simulation if object X changes\n"
01251 " <X> <Y> stop the simulation if object X property Y changes\n"
01252 " disable disables all watchpoints #\n"
01253 " disable <#> disables watchpoint #\n"
01254 " enable enables all watchpoint #\n"
01255 " enable <#> enables watchpoint #\n"
01256 " sync toggles sync watch\n"
01257 " where displays the current context\n"
01258 );
01259 }
01260 else if (strcmp(buffer,"")!=0)
01261 output_error("invalid debug command, try 'help'");
01262
01263
01264
01265
01266 else
01267 return last;
01268 }
01269 }
01270
01273 int exec_debug(struct sync_data *data,
01274 int pass,
01275 int index,
01276 OBJECT *obj)
01277 {
01278 TIMESTAMP this_t;
01279 #ifdef WIN32
01280 static int firstcall=1;
01281 if (firstcall)
01282 {
01283 kill_starthandler();
01284 atexit(kill_stophandler);
01285 firstcall=0;
01286
01287
01288 global_suppress_repeat_messages = 0;
01289 }
01290 #endif
01291
01292 global_debug_output = 1;
01293 global_suppress_repeat_messages = 0;
01294
01295 if (debug_active==0)
01296 {
01297 BREAKPOINT *bp;
01298 WATCHPOINT *wp;
01299 static char timebuf[64]="";
01300 char buffer[64];
01301
01302
01303 if (convert_from_timestamp(global_clock,buffer,sizeof(buffer)) && strcmp(buffer,timebuf)!=0)
01304 {
01305 output_raw("DEBUG: global_clock = '%s' (%"FMT_INT64"d)\r", buffer,global_clock);
01306 strcpy(timebuf,buffer);
01307 }
01308
01309
01310 for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
01311 {
01312 if (wp->enabled==0)
01313 continue;
01314 if (obj==wp->obj)
01315 {
01316 if (wp->prop==NULL)
01317 {
01318 char tmp[4096];
01319 if (object_dump(tmp,sizeof(tmp),obj) && strcmp(tmp,wp->buffer)!=0)
01320 {
01321 output_debug("watchpoint %d stopped on object %s", wp->num, get_objname(obj));
01322 output_debug("%s",tmp);
01323 strcpy(wp->buffer,tmp);
01324 debug_active=1;
01325 }
01326 }
01327 else
01328 {
01329 char *tmp = object_property_to_string(obj,wp->prop->name);
01330 if (tmp!=NULL && strcmp(tmp,wp->buffer)!=0)
01331 {
01332 output_debug("watchpoint %d stopped on object %s property %s", wp->num, get_objname(obj), wp->prop->name);
01333 output_debug("from... %s",wp->buffer);
01334 output_debug("to..... %s",tmp);
01335 strcpy(wp->buffer,tmp);
01336 debug_active=1;
01337 }
01338 }
01339 }
01340 }
01341
01342
01343 for (bp=first_breakpoint; bp!=NULL; bp=bp->next)
01344 {
01345 if (bp->enabled==0)
01346 continue;
01347 if (bp->type==BP_ERROR && error_caught)
01348 {
01349 output_debug("breakpoint %d (error) stopped on object %s", bp->num, get_objname(obj));
01350 error_caught=0;
01351 debug_active=1;
01352 }
01353 if (bp->type==BP_MODULE && bp->mod==obj->oclass->module)
01354 {
01355 output_debug("breakpoint %d (module %s) stopped on object %s", bp->num, bp->mod->name, get_objname(obj));
01356 debug_active=1;
01357 }
01358 else if (bp->type==BP_CLASS && bp->oclass==obj->oclass)
01359 {
01360 output_debug("breakpoint %d (class %s) stopped on object %s", bp->num, bp->oclass->name, get_objname(obj));
01361 debug_active=1;
01362 }
01363 else if (bp->type==BP_OBJECT && bp->obj==obj)
01364 {
01365 char buf1[1024];
01366 strcpy(buf1,get_objname(bp->obj));
01367 output_debug("breakpoint %d (object %s) stopped on object %s", bp->num, buf1, get_objname(obj));
01368 debug_active=1;
01369 }
01370 else if (bp->type==BP_RANK && bp->rank==(int64)obj->rank)
01371 {
01372 output_debug("breakpoint %d (rank %d) stopped on object %s", bp->num, (int)bp->rank, get_objname(obj));
01373 debug_active=1;
01374 }
01375 else if (bp->type==BP_PASS && bp->pass==(int64)pass)
01376 {
01377 output_debug("breakpoint %d (pass %d) stopped on object %s", bp->num, (int)bp->pass, get_objname(obj));
01378 debug_active=1;
01379 }
01380 else if (bp->type==BP_TIME && global_clock>=bp->ts)
01381 {
01382 char tmp[64];
01383 output_debug("breakpoint %d (time %s (%d)) stopped on object %s:%" FMT_INT64 "d", bp->num, convert_from_timestamp(bp->ts,tmp,sizeof(tmp))?tmp:"(invalid)", bp->ts, obj->oclass->name, obj->id);
01384 debug_active=1;
01385 }
01386 else if (bp->type==BP_CLOCK && global_clock!=bp->ts)
01387 {
01388 char tmp[64];
01389 output_debug("breakpoint %d (clock %s (%d)) stopped on clock update", bp->num, convert_from_timestamp(bp->ts,tmp,sizeof(tmp))?tmp:"(invalid)", bp->ts);
01390 bp->ts = global_clock;
01391 debug_active=1;
01392 }
01393 }
01394 }
01395 if (debug_active==1)
01396 {
01397 DEBUGCMD dbgcmd = exec_debug_cmd(data,pass,index,obj);
01398 switch (dbgcmd) {
01399 case DBG_QUIT: return FAILED;
01400 case DBG_RUN: break;
01401 case DBG_NEXT: break;
01402 default:
01403 output_error("invalid debug state");
01404
01405
01406
01407
01408
01409
01410 return FAILED;
01411 break;
01412 }
01413 }
01414
01415
01416 if (global_clock<obj->in_svc)
01417 {
01418 if (debug_active) output_debug("%s not in service yet", get_objname(obj));
01419 this_t = obj->in_svc;
01420 }
01421 else if (global_clock<=obj->out_svc)
01422 {
01423 this_t = object_sync(obj, global_clock, passtype[pass]);
01424 if (debug_active || watch_sync)
01425 {
01426 char buffer[64]="(error)";
01427 convert_from_timestamp(this_t<0?-this_t:this_t,buffer,sizeof(buffer));
01428 output_debug("%s next sync %s %s", get_objname(obj),buffer,this_t<0?"(soft sync)":"");
01429 }
01430 }
01431 else
01432 {
01433 if (debug_active) output_debug("%s out of service", get_objname(obj));
01434 this_t = TS_NEVER;
01435 }
01436
01437
01438 if (this_t < -1)
01439 this_t = -this_t;
01440 else if (this_t != TS_NEVER)
01441 data->hard_event++;
01442
01443
01444 if (this_t < global_clock) {
01445 output_error("%s: object %s stopped its clock (debug)!", simtime(), object_name(obj));
01446
01447
01448
01449
01450
01451 if (error_caught)
01452 data->status = SUCCESS;
01453 else
01454 data->status = FAILED;
01455 } else {
01456
01457 if (iteration_counter == 2 && this_t == global_clock) {
01458 output_verbose("%s: object %s iteration limit imminent",
01459 simtime(), object_name(obj));
01460 }
01461 else if (iteration_counter == 1 && this_t == global_clock) {
01462 output_error("convergence iteration limit reached for object %s (debug)", get_objname(obj));
01463
01464
01465
01466
01467
01468
01469 }
01470
01471
01472 if (global_minimum_timestep>1 && this_t>global_clock && this_t<TS_NEVER)
01473 this_t = ((this_t/global_minimum_timestep)+1)*global_minimum_timestep;
01474
01475
01476 if (data->step_to > this_t)
01477 data->step_to = this_t;
01478 data->status = SUCCESS;
01479 }
01480 return data->status;
01481 }
01482