core/debug.c

Go to the documentation of this file.
00001 
00210 #include <signal.h>
00211 #include <ctype.h>
00212 #include <string.h>
00213 
00214 #include "output.h"
00215 #include "exec.h"
00216 #include "class.h"
00217 #include "convert.h"
00218 #include "object.h"
00219 #include "index.h"
00220 #include "realtime.h"
00221 #include "module.h"
00222 #include "threadpool.h"
00223 #include "debug.h"
00224 #include "kill.h"
00225 
00226 #ifndef _MAX_PATH
00227 #include <linux/limits.h>
00228 #define _MAX_PATH PATH_MAX
00229 #endif
00230 
00231 /* these are defined in exec.c */
00232 extern const PASSCONFIG passtype[];
00233 extern int iteration_counter;
00234 
00235 /* these are the signals that will trigger the debugger to start */
00236 int siglist[] = {SIGINT, SIGFPE, SIGSEGV, SIGTERM};
00237 
00238 static char *get_objname(OBJECT *obj)
00239 {
00240     static char buf[1024];
00241     if (obj->name) return obj->name;
00242     sprintf(buf,"%s:%d", obj->oclass->name, obj->id);
00243     return buf;
00244 }
00245 
00246 /*****************************************************************************************/
00247 static int debug_active = 1; 
00248 static int error_caught = 0; 
00249 static int watch_sync = 0; 
00250 int stop_now = 0; 
00251 static int sigint_caught = 0; 
00253 void debug_notify_error(void)
00254 {
00255     error_caught = 1;
00256 }
00257 
00264 void exec_sighandler(int sig) 
00265 {
00266     sigint_caught=1;
00267     output_debug("signal %s caught", strsignal(sig));
00268     if (sig==SIGTERM)
00269     {
00270         output_error("received SIGTERM; exiting now");
00271         exit(1);
00272     }
00273     else if (sig==SIGINT)
00274     {
00275         if (global_debug_mode)
00276         {
00277             if (debug_active==0)
00278             {
00279                 output_debug("debugger activated");
00280                 debug_active=1;
00281             }
00282             else
00283             {
00284                 output_debug("debugger activation failed, signal processing disabled");
00285                 signal(sig,NULL);
00286             }
00287         }
00288     }
00289     else
00290     {
00291         output_error("processing signal %d", sig);
00292         stop_now=1;
00293     }
00294 }
00295 
00296 #ifdef WIN32
00297 char *strsignal(int sig)
00298 {
00299     switch(sig) {
00300     case SIGABRT: return "SIGABRT";
00301     case SIGFPE: return "SIGFPE";
00302     case SIGILL: return "SIGILL";
00303     case SIGINT: return "SIGINT";
00304     case SIGSEGV: return "SIGSEGV";
00305     case SIGTERM: return "SIGTERM";
00306     default: return "SIGUNKNOWN";
00307     }
00308 }
00309 #endif
00310 
00311 typedef enum {DBG_QUIT,DBG_RUN,DBG_NEXT} DEBUGCMD; 
00312 typedef enum {BP_MODULE, BP_CLASS, BP_OBJECT, BP_PASS, BP_RANK, BP_TIME, BP_CLOCK, BP_ERROR} BREAKPOINTTYPE; 
00313 typedef struct s_breakpoint {
00314     BREAKPOINTTYPE type; 
00315     int enabled; 
00316     int num; 
00317     union {
00318         MODULE *mod; 
00319         CLASS *oclass; 
00320         OBJECT *obj; 
00321         int64 pass; 
00322         int64 rank; 
00323         TIMESTAMP ts; 
00324         int64 data; 
00325     }; 
00326     struct s_breakpoint *next; 
00327 } BREAKPOINT; 
00328 static BREAKPOINT *first_breakpoint=NULL, 
00329     *last_breakpoint=NULL; 
00330 static int breakpoint_count=0; 
00334 static int exec_add_breakpoint(BREAKPOINTTYPE type, 
00335                                int64 data) 
00336 {
00337     BREAKPOINT *bp = (BREAKPOINT*)malloc(sizeof(BREAKPOINT));
00338     if (bp==NULL)
00339     {
00340         output_error("memory allocation failed");
00341         return 0;
00342     }
00343     bp->type = type;
00344     bp->data = data;
00345     bp->enabled = 1;
00346     bp->num = breakpoint_count++;
00347     bp->next = NULL;
00348     if (last_breakpoint!=NULL) 
00349         last_breakpoint->next=bp;
00350     else 
00351         first_breakpoint=bp;
00352     last_breakpoint = bp;
00353     return 1;
00354 }
00355 
00356 typedef struct s_watchpoint {
00357     int enabled; 
00358     int num; 
00359     OBJECT *obj; 
00360     PROPERTY *prop; 
00361     char buffer[4096]; 
00362     struct s_watchpoint *next; 
00363 } WATCHPOINT; 
00364 static WATCHPOINT *first_watchpoint=NULL, 
00365     *last_watchpoint=NULL; 
00366 static int watchpoint_count=0; 
00370 static int exec_add_watchpoint(OBJECT *obj, 
00371                                PROPERTY *prop) 
00372 {
00373     WATCHPOINT *wp = (WATCHPOINT*)malloc(sizeof(WATCHPOINT));
00374     if (wp==NULL)
00375     {
00376         output_error("memory allocation failed");
00377         return 0;
00378     }
00379     wp->enabled = 1;
00380     wp->num = watchpoint_count++;
00381     wp->obj = obj;
00382     wp->prop = prop;
00383     if (prop==NULL)
00384         object_dump(wp->buffer,sizeof(wp->buffer),obj);
00385     else
00386         strcpy(wp->buffer,object_property_to_string(obj,prop->name));
00387     wp->next = NULL;
00388     if (last_watchpoint!=NULL) 
00389         last_watchpoint->next=wp;
00390     else 
00391         first_watchpoint=wp;
00392     last_watchpoint = wp;
00393     return 1;
00394 }
00395 
00396 FILE *load_fp; 
00397 int load_from_file = 0; 
00401 DEBUGCMD exec_debug_cmd(struct sync_data *data, 
00402                         int pass, 
00403                         int index, 
00404                         OBJECT *obj) 
00405 {
00406     static DEBUGCMD last = DBG_NEXT;
00407     char tmp[64];
00408     char* read_val;
00409     
00410     output_debug("time %s\r", convert_from_timestamp(global_clock,tmp,sizeof(tmp))?tmp:"(invalid)");
00411     output_debug("pass %s, rank %d, object %s, iteration %d", 
00412         passtype[pass]==PC_PRETOPDOWN?"PRETOPDOWN":(passtype[pass]==PC_BOTTOMUP?"BOTTOMUP":(passtype[pass]==PC_POSTTOPDOWN?"POSTTOPDOWN":"(invalid)")),
00413         index, get_objname(obj),
00414         global_iteration_limit-iteration_counter+1);
00415     {
00416         extern void (*notify_error)(void);
00417         if (notify_error != NULL)
00418             output_debug("output errors are trapped");
00419     }
00420     while (1)
00421     {
00422         char cmd[32]=""; 
00423         char buffer[1024]="";
00424         int i;
00425 Retry:
00426         /* add signals to signal handler */
00427         for (i=0; i<sizeof(siglist)/sizeof(siglist[0]); i++)
00428             signal(siglist[i],exec_sighandler);
00429 
00430         if(load_from_file == 0){
00431             fprintf(stdout,"GLD> ");
00432             sigint_caught=0;
00433             fflush(stdout);
00434         
00435             gets(buffer);   /* "gets() is dangerous and should not be used" -gcc */
00436             output_verbose("debug command '%s'", buffer);
00437         }
00438         else{ /* Load from file */
00439             char* nl;
00440             read_val = fgets(buffer,1024,load_fp);
00441             
00442             /* check the returned value.  If NULL, drop out of file load mode */
00443             if(read_val == NULL)
00444             {
00445                 load_from_file = 0;
00446                 fclose(load_fp);
00447                 goto Retry;
00448             }
00449             /* Strip out the newline characters */
00450             nl = strrchr(buffer,'\r');
00451             if(nl)
00452                 *nl = '\0';
00453             nl = strrchr(buffer,'\n');
00454             if(nl)
00455                 *nl = '\0';
00456         }
00457         sscanf(buffer,"%s",cmd);
00458         if (sigint_caught==1)
00459         {
00460             fprintf(stdout,"<Ctrl-C>\n");
00461             goto Retry;
00462         }
00463         if (strncmp(cmd,"quit",max(1,strlen(cmd)))==0)
00464             return DBG_QUIT;
00465         else if (strncmp(cmd,"run",max(1,strlen(cmd)))==0 || (strlen(cmd)==0&&last==DBG_RUN))
00466         {
00467             output_debug("resuming simulation, Ctrl-C interrupts");
00468             debug_active=0;
00469             return last = DBG_RUN;
00470         }
00471         else if (strncmp(cmd,"next",max(1,strlen(cmd)))==0 || (strlen(cmd)==0&&last==DBG_NEXT))
00472             return last = DBG_NEXT;
00473         else if (strncmp(cmd,"list",max(1,strlen(cmd)))==0)
00474         {
00475             char lclass[256]="";
00476             OBJECT *obj = object_get_first();
00477             sscanf(buffer,"%*s %s", lclass);
00478             /* output_message("%-16.16s %4s %6s %-16.16s %-32.32s", "Object name","Rank","Status","Parent","Clock");
00479                output_message("%-16.16s %4s %6s %-16.16s %-32.32s", "----------------","----","------","----------------","--------------------------------");
00480              */
00481             /* NOTE ~ this has been copy/paste-ed for "find" as well! */
00482             for (obj=object_get_first(); obj!=NULL; obj=obj->next) 
00483             {
00484                 if (lclass[0]=='\0' || strcmp(lclass,obj->oclass->name)==0)
00485                 {
00486                     char buf1[16],buf2[16],buf3[32];
00487                     output_message("%1s%1s%1s%1s%1s%1s %4d %-24.24s %-16.16s %-16.16s", 
00488                         global_clock<obj->in_svc?"P":(global_clock<obj->out_svc?"A":"R"), /* service status: P=planned, A=active, R=retired */
00489                         (obj->oclass->passconfig&PC_PRETOPDOWN)?(pass<PC_PRETOPDOWN?"t":"T"):"-", /* pre-topdown sync status */
00490                         (obj->oclass->passconfig&PC_BOTTOMUP)?(pass<PC_BOTTOMUP?"b":"B"):"-", /* bottom-up sync status */
00491                         (obj->oclass->passconfig&PC_POSTTOPDOWN)?(pass<PC_POSTTOPDOWN?"t":"T"):"-", /* post-topdown sync status */
00492                         (obj->flags&OF_LOCKED)==OF_LOCKED?"l":"-", /* object lock status */
00493                         (obj->flags&OF_HASPLC)==OF_HASPLC?"x":"-", /* object PLC status */
00494                         obj->rank, 
00495                         obj->clock>0?(convert_from_timestamp(obj->clock,buf3,sizeof(buf3))?buf3:"(error)"):"INIT",
00496                         obj->name?obj->name:convert_from_object(buf1,sizeof(buf1),&obj,NULL)?buf1:"(error)",
00497                         obj->parent?(obj->parent->name?obj->parent->name:convert_from_object(buf2,sizeof(buf2),&(obj->parent),NULL)?buf2:"(error)"):"ROOT");
00498                 }
00499             }
00500         }
00501         else if (strncmp(cmd,"script",max(1,strlen(cmd)))==0)
00502         {
00503             char load_filename[_MAX_PATH+32]; /* Made it a little longer than max_path to be safe */
00504             if(sscanf(buffer,"%*s %[^\x20]",load_filename) <=0) /* use \n since we are using fgets to load buffer */
00505             {
00506                 output_error("Missing file name for script command");
00507             }
00508             load_fp = fopen(load_filename,"r");
00509             if(load_fp == NULL)
00510             {
00511                 output_error("Unable to open file %s for reading",load_filename);
00512             }
00513             load_from_file = 1;
00514         }
00515         else if (strncmp(cmd,"system",max(2,strlen(cmd)))==0)
00516         {
00517             char cmd[1024];
00518             if (sscanf(buffer,"%*s %[^\0]", cmd)==1)
00519                 system(cmd);
00520 #ifdef WIN32
00521             else if (getenv("COMSPEC")!=NULL)
00522                 system(getenv("COMSPEC"));
00523             else
00524                 system("cmd");
00525 #else
00526             else if (getenv("SHELL")!=NULL)
00527                 system(getenv("SHELL"));
00528             else
00529                 system("/bin/sh");
00530 #endif
00531         }
00532         else if (strncmp(cmd,"break",max(1,strlen(cmd)))==0)
00533         {
00534             char bptype[256]="";
00535             char bpval[256]="";
00536             if (sscanf(buffer,"%*s %s %[^\0]", bptype, bpval)==0)
00537             {
00538                 /* display all breakpoints */
00539                 BREAKPOINT *bp;
00540                 if (last_breakpoint==NULL)
00541                     output_debug("no breakpoints");
00542                 for (bp=first_breakpoint; bp!=NULL; bp=bp->next)
00543                 {
00544                     char tmp[64];
00545                     switch (bp->type) {
00546                     case BP_MODULE:
00547                         output_debug("breakpoint %2d - module %s %s", bp->num, bp->mod->name, bp->enabled?"":"(disabled)");
00548                         break;
00549                     case BP_CLASS:
00550                         output_debug("breakpoint %2d - class %s %s", bp->num, bp->oclass->name, bp->enabled?"":"(disabled)");
00551                         break;
00552                     case BP_OBJECT:
00553                         output_debug("breakpoint %2d object %s %s", bp->num, get_objname(bp->obj), bp->enabled?"":"(disabled)");
00554                         break;
00555                     case BP_PASS:
00556                         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)");
00557                         break;
00558                     case BP_RANK:
00559                         output_debug("breakpoint %2d rank %d %s", bp->num, (int)bp->rank, bp->enabled?"":"(disabled)");
00560                         break;
00561                     case BP_TIME:
00562                         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)");
00563                         break;
00564                     case BP_CLOCK:
00565                         output_debug("breakpoint %2d clock %s", bp->num, bp->enabled?"":"(disabled)");
00566                         break;
00567                     case BP_ERROR:
00568                         output_debug("breakpoint %2d on error", bp->num, bp->enabled?"":"(disabled)");
00569                         break;
00570                     default:
00571                         break;
00572                     }
00573                 }
00574             }
00575             else if (strncmp(bptype,"error",strlen(bptype))==0)
00576             {
00577                 if (!exec_add_breakpoint(BP_ERROR,0))
00578                     output_error("unable to add error breakpoint");
00579                 error_caught = 0;
00580                 output_notify_error(debug_notify_error);
00581             }
00582             else if (strncmp(bptype,"clock",strlen(bptype))==0)
00583             {
00584                 if (!exec_add_breakpoint(BP_CLOCK,global_clock))
00585                     output_error("unable to add clock breakpoint");
00586             }
00587             else if (strncmp(bptype,"object",strlen(bptype))==0)
00588             {   /* create object breakpoint */
00589                 OBJECT *obj = object_find_name(bpval);
00590                 if (obj!=NULL || convert_to_object(bpval,&obj,NULL))
00591                 {
00592                     if (!exec_add_breakpoint(BP_OBJECT,(int64)obj)) /* warning: cast from pointer to integer of different size */
00593                         output_error("unable to add object breakpoint");
00594                 }
00595                 else
00596                     output_error("object %s does not exist",bpval);
00597             }
00598             else if (strncmp(bptype,"module",strlen(bptype))==0)
00599             {   /* create module breakpoint */
00600                 MODULE *mod = module_find(bpval);
00601                 if (mod!=NULL)
00602                 {
00603                     if (!exec_add_breakpoint(BP_MODULE,(int64)mod)) /* warning: cast from pointer to integer of different size */
00604                         output_error("unable to add module breakpoint");
00605                 }
00606                 else
00607                     output_error("module %s does not exist",bpval);
00608             }
00609             else if (strncmp(bptype,"class",strlen(bptype))==0)
00610             {   /* create class breakpoint */
00611                 CLASS *oclass = class_get_class_from_classname(bpval);
00612                 if (oclass!=NULL)
00613                 {
00614                     if (!exec_add_breakpoint(BP_CLASS,(int64)oclass)) /* warning: cast from pointer to integer of different size */
00615                         output_error("unable to add class breakpoint");
00616                 }
00617                 else
00618                     output_debug("class %s does not exist",bpval);
00619             }
00620             else if (strncmp(bptype,"pass",strlen(bptype))==0)
00621             {   /* create pass breakpoint */
00622                 int pass;
00623                 if (strnicmp(bpval,"pretopdown",max(2,strlen(bpval)))==0) pass=PC_PRETOPDOWN;
00624                 else if (strnicmp(bpval,"bottomup",strlen(bpval))==0) pass=PC_BOTTOMUP;
00625                 else if (strnicmp(bpval,"posttopdown",max(2,strlen(bpval)))==0) pass=PC_POSTTOPDOWN;
00626                 else
00627                 {
00628                     output_error("undefined pass type");
00629                     continue;
00630                 }
00631                 if (!exec_add_breakpoint(BP_PASS,(int64)pass))
00632                     output_error("unable to add pass breakpoint");
00633             }
00634             else if (strncmp(bptype,"rank",strlen(bptype))==0)
00635             {   /* create rank breakpoint */
00636                 if (!exec_add_breakpoint(BP_RANK,(int64)atoi(bpval)))
00637                     output_error("unable to add rank breakpoint");
00638             }
00639             else if (strncmp(bptype,"time",strlen(bptype))==0)
00640             {   /* create time breakpoint */
00641                 TIMESTAMP ts = convert_to_timestamp(bpval);
00642                 if (ts==TS_NEVER)
00643                     output_error("invalid time");
00644                 else if (!exec_add_breakpoint(BP_TIME,(int64)ts))
00645                     output_error("unable to add timestamp breakpoint");
00646             }
00647             else if (strncmp(bptype,"disable",strlen(bptype))==0)
00648             {
00649                 int n=-1;
00650                 BREAKPOINT *bp;
00651                 if (strcmp(bpval,"")!=0)
00652                 {
00653                     if (isdigit(bpval[0]))
00654                         n=atoi(bpval);
00655                     else
00656                     {
00657                         output_error("invalid breakpoint number");
00658                         continue;
00659                     }
00660                 }
00661                 for (bp=first_breakpoint; bp!=NULL; bp=bp->next)
00662                 {
00663                     if (bp->num==n || n==-1)
00664                         bp->enabled = 0;
00665                 }
00666             }
00667             else if (strncmp(bptype,"enable",strlen(bptype))==0)
00668             {
00669                 int n=-1;
00670                 BREAKPOINT *bp;
00671                 if (strcmp(bpval,"")!=0)
00672                 {
00673                     if (isdigit(bpval[0]))
00674                         n=atoi(bpval);
00675                     else
00676                     {
00677                         output_error("invalid breakpoint number");
00678                         continue;
00679                     }
00680                 }
00681                 for (bp=first_breakpoint; bp!=NULL; bp=bp->next)
00682                 {
00683                     if (bp->num==n || n==-1)
00684                         bp->enabled = 1;
00685                 }
00686             }
00687             else
00688                 output_error("%s is not recognized", bptype);
00689         }
00690         else if (strncmp(cmd,"watch",max(2,strlen(cmd)))==0)
00691         {
00692             char wptype[256]="";
00693             char wpval[256]="";
00694             OBJECT *obj;
00695             if (sscanf(buffer,"%*s %s %[^\0]", wptype, wpval)==0)
00696             {
00697                 /* display all watchpoints */
00698                 WATCHPOINT *wp;
00699                 if (last_watchpoint==NULL)
00700                     output_debug("no watchpoints");
00701                 for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
00702                     output_debug("watchpoint %d - object %s %s", wp->num, get_objname(wp->obj), wp->enabled?"":"(disabled)");
00703             }
00704             else if (isdigit(wptype[0]))
00705             {
00706                 int n=atoi(wptype);
00707                 WATCHPOINT *wp;
00708                 for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
00709                 {
00710                     if (wp->num==n)
00711                         output_debug("watchpoint %d - object %s %s\n%s", 
00712                             wp->num, get_objname(wp->obj), wp->enabled?"":"(disabled)",wp->buffer);
00713                 }
00714             }
00715             else if (strcmp(wptype,"sync")==0)
00716             {
00717                 watch_sync = !watch_sync;
00718                 output_debug("sync watch is %s",watch_sync?"enabled":"disabled");
00719             }
00720             else if (strncmp(wptype,"disable",strlen(wptype))==0)
00721             {
00722                 int n=-1;
00723                 WATCHPOINT *wp;
00724                 if (strcmp(wpval,"")!=0)
00725                 {
00726                     if (isdigit(wpval[0]))
00727                         n=atoi(wpval);
00728                     else
00729                     {
00730                         output_error("invalid watchpoint number");
00731                         continue;
00732                     }
00733                 }
00734                 for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
00735                 {
00736                     if (wp->num==n || n==-1)
00737                         wp->enabled = 0;
00738                 }
00739             }
00740             else if (strncmp(wptype,"enable",strlen(wptype))==0)
00741             {
00742                 int n=-1;
00743                 WATCHPOINT *wp;
00744                 if (strcmp(wpval,"")!=0)
00745                 {
00746                     if (isdigit(wpval[0]))
00747                         n=atoi(wpval);
00748                     else
00749                     {
00750                         output_error("invalid watchpoint number");
00751                         continue;
00752                     }
00753                 }
00754                 for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
00755                 {
00756                     if (wp->num==n || n==-1)
00757                         wp->enabled = 1;
00758                 }
00759             }
00760             else if ((obj=object_find_name(wptype)) || convert_to_object(wptype,&obj,NULL))
00761             {
00762                 if (strcmp(wpval,"")!=0)
00763                 {
00764                     PROPERTY *prop = object_get_property(obj,wpval);
00765                     if (prop==NULL)
00766                         output_error("object %s does not have a property named '%s'", wptype,wpval);
00767                     else if (!exec_add_watchpoint(obj,prop))
00768                         output_error("unable to add object watchpoint");
00769                 }
00770                 else if (!exec_add_watchpoint(obj,NULL))
00771                     output_error("unable to add object watchpoint");
00772             }
00773             else
00774                 output_error("%s is not recognized", wptype);       
00775         }
00776         else if (strncmp(cmd,"where",max(1,strlen(cmd)))==0)
00777         {
00778             char ts[64];
00779             output_debug("Global clock... %s (%" FMT_INT64 "d)", convert_from_timestamp(global_clock,ts,sizeof(ts))?ts:"(invalid)",global_clock);
00780             output_debug("Hard events.... %d", data->hard_event);
00781             output_debug("Sync status.... %s", data->status==FAILED?"FAILED":"SUCCESS");
00782             output_debug("Step to time... %s (%" FMT_INT64 "d)", convert_from_timestamp(data->step_to,ts,sizeof(ts))?ts:"(invalid)",data->step_to);
00783             output_debug("Pass........... %d", pass);
00784             output_debug("Rank........... %d", index);
00785             output_debug("Object......... %s",get_objname(obj));
00786         }
00787         else if (strncmp(cmd,"print",max(1,strlen(cmd)))==0)
00788         {
00789             char tmp[4096];
00790             if (sscanf(buffer,"%*s %s",tmp)==0)
00791             {
00792                 if (object_dump(tmp,sizeof(tmp),obj))
00793                     output_debug("%s",tmp);
00794                 else
00795                     output_error("object dump failed");
00796             }
00797             else
00798             {
00799                 OBJECT *obj = object_find_name(tmp);
00800                 if (obj!=NULL || convert_to_object(tmp,&obj,NULL))
00801                 {
00802                     if (object_dump(tmp,sizeof(tmp),obj))
00803                         output_debug("%s",tmp);
00804                     else
00805                         output_error("object dump failed");
00806                 }
00807                 else
00808                     output_error("object %s undefined", tmp);
00809             }
00810         }
00811         else if (strncmp(cmd,"globals",max(1,strlen(cmd)))==0)
00812         {
00813             GLOBALVAR *var;
00814             for (var=global_getnext(NULL); var!=NULL; var=global_getnext(var))
00815             {
00816                 char *val = global_getvar(var->name, NULL, 0);
00817                 if (val!=NULL && strlen(val)>64)
00818                     strcpy(val+28,"...");
00819                 output_message("%-32.32s: \"%s\"", var->name, val==NULL?"(error)":val);
00820             }
00821         }
00822         else if (strncmp(cmd,"set",max(1,strlen(cmd)))==0)
00823         {
00824             char256 objname;
00825             char256 propname;
00826             char256 value;
00827             int scanct = 0;
00828             value[0] = '\0';
00829             if ((scanct=sscanf(buffer,"%*s %s %s %s",objname,propname,value))>=2)
00830             {
00831                 OBJECT *obj;
00832                 if (strcmp(objname,"global")==0)
00833                 {
00834                     if (global_setvar(propname,value)==FAILED)
00835                         output_error("unable to set global value %s", propname);
00836                 }
00837                 else if ((obj=object_find_name(objname)) || convert_to_object(objname,&obj,NULL))
00838                 {
00839                     if (!object_set_value_by_name(obj,propname,value))
00840                         output_error("unable to set value of object %s property %s", objname,propname);
00841                     else if (!object_get_property(obj,propname))
00842                         output_error("invalid property for object %s",objname);
00843                 }
00844                 else
00845                     output_error("invalid object");
00846             }
00847             else{
00848                 output_error("set syntax error (%i items)", scanct);
00849             }
00850         }
00851         else if (strncmp(cmd,"find ",max(1,strlen(cmd)))==0)
00852         {
00853             FINDLIST *fl = NULL;
00854             OBJECT *obj = NULL;
00855             output_debug("running search with \"%s\"", buffer+5);
00856             fl = find_objects(FL_GROUP, buffer+5);
00857             obj = find_first(fl);
00858             //while(obj != NULL){
00859             //  output_debug(" * %s (%s)", get_objname(obj), obj->oclass->name);
00860             //  obj = find_next(fl, obj);
00861             for (obj=find_first(fl); obj!=NULL; obj=find_next(fl, obj)) 
00862             {
00863                 char buf1[16],buf2[16],buf3[32];
00864                 output_message("%1s%1s%1s%1s%1s%1s %4d %-24.24s %-16.16s %-16.16s", 
00865                     global_clock<obj->in_svc?"P":(global_clock<obj->out_svc?"A":"R"), /* service status: P=planned, A=active, R=retired */
00866                     (obj->oclass->passconfig&PC_PRETOPDOWN)?(pass<PC_PRETOPDOWN?"t":"T"):"-", /* pre-topdown sync status */
00867                     (obj->oclass->passconfig&PC_BOTTOMUP)?(pass<PC_BOTTOMUP?"b":"B"):"-", /* bottom-up sync status */
00868                     (obj->oclass->passconfig&PC_POSTTOPDOWN)?(pass<PC_POSTTOPDOWN?"t":"T"):"-", /* post-topdown sync status */
00869                     (obj->flags&OF_LOCKED)==OF_LOCKED?"l":"-", /* object lock status */
00870                     (obj->flags&OF_HASPLC)==OF_HASPLC?"x":"-", /* object PLC status */
00871                     obj->rank, 
00872                     obj->clock>0?(convert_from_timestamp(obj->clock,buf3,sizeof(buf3))?buf3:"(error)"):"INIT",
00873                     obj->name?obj->name:convert_from_object(buf1,sizeof(buf1),&obj,NULL)?buf1:"(error)",
00874                     obj->parent?(obj->parent->name?obj->parent->name:convert_from_object(buf2,sizeof(buf2),&(obj->parent),NULL)?buf2:"(error)"):"ROOT");
00875             }
00876         }
00877         else if (strncmp(cmd,"help",max(1,strlen(cmd)))==0)
00878         {
00879             output_debug("Summary of debug commands\n"
00880                 "   break             prints all breakpoints\n"
00881                 "         clock       stop the simulator on clock advance\n"
00882                 "         error       stop the simulator is an error occurs\n"
00883                 "         object <X>  stop the simulator on sync of object X\n"
00884                 "         module <X>  stop the simulator on sync of module X\n"
00885                 "         class <X>   stop the simulator on sync of class X\n"
00886                 "         pass <X>    stop the simulator on the start of pass X\n"
00887                 "         rank <X>    stop the simulation on the start of rank X\n"
00888                 "         time <X>    stop the simulation at the time time X\n"
00889                 "         disable     disables all breakpoints\n"
00890                 "         enable      enables all breakpoints\n"
00891                 "         disable <#> disables breakpoint #\n"
00892                 "         enable <#>  enables breakpoint #\n"
00893                 "   globals           print global variables\n"
00894                 "   list              list objects\n"
00895                 "        <X>          list objects of class X\n"
00896                 "   next              advances to the next object sync\n"
00897                 "   print <X>         prints object X\n"
00898                 "   quit              quits the simulator\n"
00899                 "   run               runs the simulator until the next break point\n"
00900                 "   set <X> <Y> <val> set object X property Y to <val>\n"
00901                 "   script <filename> read a script file containing debugger commands\n"
00902                 "   system            opens a shell on the current OS\n"
00903                 "          <command>  executes the command on the current OS\n"
00904                 "   watch             prints all watchpoints\n"
00905                 "         <#>         prints watchpoint #\n"
00906                 "         <X>         stop the simulation if object X changes\n"
00907                 "         <X> <Y>     stop the simulation if object X property Y changes\n"
00908                 "         disable     disables all watchpoints #\n"
00909                 "         disable <#> disables watchpoint #\n"
00910                 "         enable      enables all watchpoint #\n"
00911                 "         enable <#>  enables watchpoint #\n"
00912                 "         sync        toggles sync watch\n"
00913                 "   where             displays the current context\n"
00914                 );
00915         }
00916         else if (strcmp(buffer,"")!=0)
00917             output_error("invalid debug command, try 'help'");
00918         else
00919             return last;
00920     }
00921 }
00922 
00925 int exec_debug(struct sync_data *data, 
00926                int pass, 
00927                int index, 
00928                OBJECT *obj) 
00929 {
00930     TIMESTAMP this_t;
00931 #ifdef WIN32
00932     static int firstcall=1;
00933     if (firstcall)
00934     {
00935         kill_starthandler();
00936         atexit(kill_stophandler);
00937         firstcall=0;
00938     }
00939 #endif
00940 
00941     if (debug_active==0)
00942     {
00943         BREAKPOINT *bp;
00944         WATCHPOINT *wp;
00945         static char timebuf[64]="";
00946         char buffer[64];
00947 
00948         /* only output time update if it differs from last one */
00949         if (convert_from_timestamp(global_clock,buffer,sizeof(buffer)) && strcmp(buffer,timebuf)!=0)
00950         {
00951             output_raw("DEBUG: global_clock = '%s' (%"FMT_INT64"d)\r", buffer,global_clock);
00952             strcpy(timebuf,buffer);
00953         }
00954 
00955         /* check watchpoints */
00956         for (wp=first_watchpoint; wp!=NULL; wp=wp->next)
00957         {
00958             if (wp->enabled==0)
00959                 continue;
00960             if (obj==wp->obj)
00961             {
00962                 if (wp->prop==NULL)
00963                 {
00964                     char tmp[4096];
00965                     if (object_dump(tmp,sizeof(tmp),obj) && strcmp(tmp,wp->buffer)!=0)
00966                     {
00967                         output_debug("watchpoint %d stopped on object %s", wp->num, get_objname(obj));
00968                         output_debug("%s",tmp);
00969                         strcpy(wp->buffer,tmp);
00970                         debug_active=1;
00971                     }
00972                 }
00973                 else
00974                 {
00975                     char *tmp = object_property_to_string(obj,wp->prop->name);
00976                     if (tmp!=NULL && strcmp(tmp,wp->buffer)!=0)
00977                     {
00978                         output_debug("watchpoint %d stopped on object %s property %s", wp->num, get_objname(obj), wp->prop->name);
00979                         output_debug("from... %s",wp->buffer);
00980                         output_debug("to..... %s",tmp);
00981                         strcpy(wp->buffer,tmp);
00982                         debug_active=1;
00983                     }
00984                 }
00985             }
00986         }
00987 
00988         /* check breakpoints */
00989         for (bp=first_breakpoint; bp!=NULL; bp=bp->next)
00990         {
00991             if (bp->enabled==0)
00992                 continue;
00993             if (bp->type==BP_ERROR && error_caught)
00994             {
00995                 output_debug("breakpoint %d (error) stopped on object %s", bp->num, get_objname(obj));
00996                 error_caught=0;
00997                 debug_active=1;
00998             }
00999             if (bp->type==BP_MODULE && bp->mod==obj->oclass->module)
01000             {
01001                 output_debug("breakpoint %d (module %s) stopped on object %s", bp->num, bp->mod->name, get_objname(obj));
01002                 debug_active=1;
01003             }
01004             else if (bp->type==BP_CLASS && bp->oclass==obj->oclass)
01005             {
01006                 output_debug("breakpoint %d (class %s) stopped on object %s", bp->num, bp->oclass->name, get_objname(obj));
01007                 debug_active=1;
01008             }
01009             else if (bp->type==BP_OBJECT && bp->obj==obj)
01010             {
01011                 char buf1[1024];
01012                 strcpy(buf1,get_objname(bp->obj));
01013                 output_debug("breakpoint %d (object %s) stopped on object %s", bp->num, buf1, get_objname(obj));
01014                 debug_active=1;
01015             }
01016             else if (bp->type==BP_RANK && bp->rank==(int64)obj->rank)
01017             {
01018                 output_debug("breakpoint %d (rank %d) stopped on object %s", bp->num, (int)bp->rank, get_objname(obj));
01019                 debug_active=1;
01020             }
01021             else if (bp->type==BP_PASS && bp->pass==(int64)pass)
01022             {
01023                 output_debug("breakpoint %d (pass %d) stopped on object %s", bp->num, (int)bp->pass, get_objname(obj));
01024                 debug_active=1;
01025             }
01026             else if (bp->type==BP_TIME && global_clock>=bp->ts)
01027             {
01028                 char tmp[64];
01029                 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);
01030                 debug_active=1;
01031             }
01032             else if (bp->type==BP_CLOCK && global_clock!=bp->ts)
01033             {
01034                 char tmp[64];
01035                 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);
01036                 bp->ts = global_clock; /* now use this time as bp */
01037                 debug_active=1;
01038             }
01039         }
01040     }
01041     if (debug_active==1)
01042     {
01043         DEBUGCMD dbgcmd = exec_debug_cmd(data,pass,index,obj);
01044         switch (dbgcmd) {
01045         case DBG_QUIT: return FAILED;
01046         case DBG_RUN: break;
01047         case DBG_NEXT: break;
01048         default: 
01049             output_error("invalid debug state");
01050             return FAILED;
01051             break;
01052         }
01053     }
01054 
01055     /* check in and out-of-service dates */
01056     if (global_clock<obj->in_svc)
01057     {
01058         if (debug_active) output_debug("%s not in service yet", get_objname(obj));
01059         this_t = obj->in_svc; /* yet to go in service */
01060     }
01061     else if (global_clock<=obj->out_svc)
01062     {
01063         char buffer[64]="(error)";
01064         this_t = object_sync(obj, global_clock, passtype[pass]);
01065         convert_from_timestamp(this_t<0?-this_t:this_t,buffer,sizeof(buffer));
01066         if (debug_active || watch_sync) output_debug("%s next sync %s %s", get_objname(obj),buffer,this_t<0?"(soft sync)":"");
01067     }
01068     else 
01069     {
01070         if (debug_active) output_debug("%s out of service", get_objname(obj));
01071         this_t = TS_NEVER; /* already out of service */
01072     }
01073 
01074     /* check for "soft" event (events that are ignored when stopping) */
01075     if (this_t < -1)
01076         this_t = -this_t;
01077     else if (this_t != TS_NEVER)
01078         data->hard_event++;  /* this counts the number of hard events */
01079 
01080     /* check for stopped clock */
01081     if (this_t < global_clock) {
01082         output_error("%s: object %s stopped its clock!", simtime(), object_name(obj));
01083         if (error_caught)
01084             data->status = SUCCESS; /* this will let the debugger handle the error */
01085         else
01086             data->status = FAILED; /* the debugger isn't going to handle the error so make exec handle it */
01087     } else {
01088         /* check for iteration limit approach */
01089         if (iteration_counter == 2 && this_t == global_clock) {
01090             output_verbose("%s: object %s iteration limit imminent",
01091                                 simtime(), object_name(obj));
01092         }
01093         else if (iteration_counter == 1 && this_t == global_clock) {
01094             output_error("convergence iteration limit reached for object %s", get_objname(obj));
01095         }
01096 
01097         /* if this event precedes next step, next step is now this event */
01098         if (data->step_to > this_t)
01099             data->step_to = this_t;
01100         data->status = SUCCESS;
01101     }
01102     return data->status;
01103 }
01104 

GridLAB-DTM Version 1.0
An open-source project initiated by the US Department of Energy