/* prof_FuncConfig(): * This function builds a table of pdata structures based on the * content of the symbol table. * It assumes the file is a list of symbols and addresses listed * in ascending address order. */ void prof_FuncConfig(void) { int tfd, i; struct pdata *pfp; char line[80], *space; tfd = prof_GetSymFile(); if(tfd < 0) { return; } prof_FuncTot = 0; pfp = prof_FuncTbl; while(tfsgetline(tfd,line,sizeof(line)-1)) { space = strpbrk(line,"\t "); if(!space) { continue; } *space++ = 0; while(isspace(*space)) { space++; } pfp->data = strtoul(space,0,0); pfp->pcount = 0; pfp++; prof_FuncTot++; } tfsclose(tfd,0); /* Add one last item to the list so that there is an upper limit for * the final symbol in the table: */ pfp->data = 0xffffffff; pfp->pcount = 0; /* Test to verify that all symbols are in ascending address order... */ for(i=0; i<prof_FuncTot; i++) { if(prof_FuncTbl[i].data > prof_FuncTbl[i+1].data) { printf("Warning: function addresses not in order\n"); break; } } prof_FuncTot++; }
int Strace(int argc,char *argv[]) { char *symfile, fname[64]; TFILE *tfp; ulong *framepointer, pc, fp, offset; int tfd, opt, maxdepth, pass, verbose, bullseye; tfd = fp = 0; maxdepth = 20; verbose = 0; pc = ExceptionAddr; while ((opt=getopt(argc,argv,"d:F:P:rs:v")) != -1) { switch(opt) { case 'd': maxdepth = atoi(optarg); break; case 'F': fp = strtoul(optarg,0,0); break; case 'P': pc = strtoul(optarg,0,0); break; case 'r': showregs(); break; case 'v': verbose = 1; break; default: return(0); } } if (!fp) getreg("A6", (ulong *)&framepointer); else framepointer = (ulong *)fp; /* Start by detecting the presence of a symbol table file... */ symfile = getenv("SYMFILE"); if (!symfile) symfile = SYMFILE; tfp = tfsstat(symfile); if (tfp) { tfd = tfsopen(symfile,TFS_RDONLY,0); if (tfd < 0) tfp = (TFILE *)0; } /* Show current position: */ printf(" 0x%08lx",pc); if (tfp) { AddrToSym(tfd,pc,fname,&offset); printf(": %s()",fname); if (offset) printf(" + 0x%lx",offset); } putchar('\n'); /* Now step through the stack frame... */ bullseye = pass = 0; while(maxdepth) { /* ADD_CODE_HERE */ } if (!maxdepth) printf("Max depth termination\n"); if (tfp) { tfsclose(tfd,0); } return(0); }
void tfslog(int action, char *string) { #if TFS_CHANGELOG_SIZE static char *tfslogaction[] = { "ADD", "DEL", "IPM", " ON", "OFF" }; extern void *setTmpMaxUsrLvl(); static char buf[TFS_CHANGELOG_SIZE]; TFILE *tfp; int (*fptr)(); char *eol, *eob, *logaction, tbuf[32]; int newfsize, fsize, lsize, tfd, err, len, tbuflen; switch(action) { case TFSLOG_ADD: /* Return here if logging is off, */ case TFSLOG_DEL: /* or this tfslog() call is on the */ case TFSLOG_IPM: /* TFS_CHANGELOG_FILE itself. */ if (!tfsLogging || !strcmp(string,TFS_CHANGELOG_FILE)) return; break; case TFSLOG_ON: if (tfsLogging == 1) return; tfsLogging = 1; break; case TFSLOG_OFF: if (tfsLogging == 0) return; tfsLogging = 0; break; } /* Force the getUsrLvl() function to return MAX: */ fptr = (int(*)())setTmpMaxUsrLvl(); logaction = tfslogaction[action]; tfp = tfsstat(TFS_CHANGELOG_FILE); tfsGetAtime(0,tbuf,sizeof(tbuf)); tbuflen = strlen(tbuf); if (tfp) { tfd = tfsopen(TFS_CHANGELOG_FILE,TFS_RDONLY,0); fsize = tfsread(tfd,buf,TFS_CHANGELOG_SIZE); tfsclose(tfd,0); newfsize = (fsize+strlen(logaction)+strlen(string)+3); if (tbuflen) newfsize += tbuflen + 3; eob = buf + fsize; /* If newfsize is greater than the maximum size the file is * allowed to grow, then keep removing the first line * (oldest entry) until new size is within the limit... */ if (newfsize > TFS_CHANGELOG_SIZE) { lsize = 0; eol = buf; while ((newfsize-lsize) > TFS_CHANGELOG_SIZE) { while((*eol != '\r') && (*eol != '\n')) eol++; while((*eol == '\r') || (*eol == '\n')) eol++; lsize = eol-buf; } fsize -= lsize; newfsize -= lsize; eob -= lsize; memcpy(buf,eol,fsize); } if (tbuflen) sprintf(eob,"%s: %s @ %s\n",logaction,string,tbuf); else sprintf(eob,"%s: %s\n",logaction,string); err = _tfsunlink(TFS_CHANGELOG_FILE); if (err < 0) printf("%s: %s\n",TFS_CHANGELOG_FILE, (char *)tfsctrl(TFS_ERRMSG,err,0)); err = tfsadd(TFS_CHANGELOG_FILE,0,"u3",buf,newfsize); if (err < 0) printf("%s: %s\n",TFS_CHANGELOG_FILE, (char *)tfsctrl(TFS_ERRMSG,err,0)); } else { if (tbuflen) len = sprintf(buf,"%s: %s @ %s\n",logaction,string,tbuf); else len = sprintf(buf,"%s: %s\n",logaction,string); err = tfsadd(TFS_CHANGELOG_FILE,0,"u3",buf,len); if (err < 0) printf("%s: %s\n",TFS_CHANGELOG_FILE, (char *)tfsctrl(TFS_ERRMSG,err,0)); } /* Restore the original getUsrLvl() functionality: */ clrTmpMaxUsrLvl(fptr); #endif }
int Cast(int argc,char *argv[]) { long flags; int opt, tfd, index; char *structtype, *structfile, *tablename, *linkname, *name; flags = 0; name = (char *)0; linkname = (char *)0; tablename = (char *)0; while((opt=getopt(argc,argv,"apl:n:t:")) != -1) { switch(opt) { case 'a': flags |= STRUCT_SHOWADD; break; case 'l': linkname = optarg; break; case 'n': name = optarg; break; case 'p': flags |= STRUCT_SHOWPAD; break; case 't': tablename = optarg; break; default: return(CMD_PARAM_ERROR); } } if (argc != optind + 2) return(CMD_PARAM_ERROR); structtype = argv[optind]; memAddr = strtoul(argv[optind+1],0,0); /* Start by detecting the presence of a structure definition file... */ structfile = getenv("STRUCTFILE"); if (!structfile) structfile = STRUCTFILE; tfd = tfsopen(structfile,TFS_RDONLY,0); if (tfd < 0) { printf("Structure definition file '%s' not found\n",structfile); return(CMD_FAILURE); } index = 0; do { castDepth = 0; showStruct(tfd,flags,structtype,name,linkname); index++; if (linkname) printf("Link #%d = 0x%lx\n",index,memAddr); if (tablename || linkname) { if (askuser("next?")) { if (tablename) printf("%s[%d]:\n",tablename,index); } else tablename = linkname = (char *)0; } } while(tablename || linkname); tfsclose(tfd,0); return(CMD_SUCCESS); }
int tfsscript(TFILE *fp,int verbose) { char lcpy[CMDLINESIZE], *sv; int tfd, lnsize, lno, verbosity, ignoreerror, cmdstat; tfd = tfsopen(fp->name,TFS_RDONLY,0); if (tfd < 0) return(tfd); lno = 0; /* If ScriptIsRunning is zero, then we know that this is the top-level * script, so we can initialize state here... */ if (ScriptIsRunning == 0) ReturnToDepth = 0; CurrentScriptfdTbl[++ScriptIsRunning] = tfd; while(1) { lno++; lnsize = tfsgetline(tfd,lcpy,CMDLINESIZE); if (lnsize == 0) /* end of file? */ break; if (lnsize < 0) { printf("tfsscript(): %s\n",tfserrmsg(lnsize)); break; } if ((lcpy[0] == '\r') || (lcpy[0] == '\n')) /* empty line? */ continue; lcpy[lnsize-1] = 0; /* Remove the newline */ /* Just in case the goto tag was set outside a script, */ /* clear it now. */ if (ScriptGotoTag) { free(ScriptGotoTag); ScriptGotoTag = (char *)0; } ScriptExitFlag = 0; /* Execute the command line. * If the shell variable "SCRIPTVERBOSE" is set, then enable * verbosity for this command; else use what was passed in * the parameter list of the function. Note that the variable * is tested for each command so that verbosity can be enabled * or disabled within a script. * If the command returns a status that indicates that there was * some parameter error, then exit the script. */ sv = getenv("SCRIPTVERBOSE"); if (sv) verbosity = atoi(sv); else verbosity = verbose; if ((lcpy[0] == '-') || (getenv("SCRIPT_IGNORE_ERROR"))) ignoreerror = 1; else ignoreerror = 0; if (verbosity) printf("[%02d]: %s\n",lno,lcpy); cmdstat = tfsDocommand(lcpy[0] == '-' ? lcpy+1 : lcpy, 0); if (cmdstat != CMD_SUCCESS) { setenv("CMDSTAT","FAIL"); if (ignoreerror == 0) { printf("Terminating script '%s' at line %d\n", TFS_NAME(fp),lno); ScriptExitFlag = EXIT_SCRIPT; break; } } else { setenv("CMDSTAT","PASS"); } /* Check for exit flag. If set, then in addition to terminating the * script, clear the return depth here so that the "missing return" * warning is not printed. This is done because there is likely * to be a subroutine with an exit in it and this should not * cause a warning. */ if (ScriptExitFlag) { ReturnToDepth = 0; break; } /* If ScriptGotoTag is set, then attempt to reposition the line * pointer to the line that contains the tag. */ if (ScriptGotoTag) { int tlen; tlen = strlen(ScriptGotoTag); lno = 0; tfsseek(tfd,0,TFS_BEGIN); while(1) { lnsize = tfsgetline(tfd,lcpy,CMDLINESIZE); if (lnsize == 0) { printf("Tag '%s' not found\n",ScriptGotoTag+2); free(ScriptGotoTag); ScriptGotoTag = (char *)0; tfsclose(tfd,0); return(TFS_OKAY); } lno++; if (!strncmp(lcpy,ScriptGotoTag,tlen) && (isspace(lcpy[tlen]) || (lcpy[tlen] == ':'))) { free(ScriptGotoTag); ScriptGotoTag = (char *)0; break; } } } /* After each line, poll ethernet interface. */ pollethernet(); } tfsclose(tfd,0); if (ScriptExitFlag & REMOVE_SCRIPT) tfsunlink(fp->name); if (ScriptIsRunning > 0) { ScriptIsRunning--; if ((ScriptIsRunning == 0) && (ReturnToDepth != 0)) { printf("Error: script is done, but return-to-depth != 0\n"); printf("(possible gosub/return imbalance)\n"); } } else { printf("Script run-depth error\n"); } /* If the EXECUTE_AFTER_EXIT flag is set (by exit -e), then automatically * start up the file specified in ExecuteAfterExit[]... */ if (ScriptExitFlag & EXECUTE_AFTER_EXIT) { char *argv[2]; argv[0] = ExecuteAfterExit; argv[1] = 0; ScriptExitFlag = 0; tfsrun(argv,0); } /* Upon completion of a script, clear the ScriptExitFlag variable so * that it is not accidentally applied to another script that may have * called this script. */ if ((ScriptExitFlag & EXIT_ALL_SCRIPTS) != EXIT_ALL_SCRIPTS) ScriptExitFlag = 0; return(TFS_OKAY); }
void prof_ShowStats(int minhit, int more) { int i, tfd, linecount; ulong notused; char symname[64]; struct pdata *pptr; printf("FuncCount Cfg: tbl: 0x%08lx, size: 0x%x\n", (ulong)prof_FuncTbl, prof_FuncTot); printf("TidCount Cfg: tbl: 0x%08lx, size: 0x%x\n", (ulong)prof_TidTbl, prof_TidTot); printf("PcCount Cfg: tbl: 0x%08lx, size: 0x%x\n", (ulong)prof_PcTbl, prof_PcTot*prof_PcWidth); if(prof_CallCnt == 0) { printf("No data collected%s", prof_Enabled == 0 ? " (profiling disabled)\n" : "\n"); return; } linecount = 0; tfd = prof_GetSymFile(); if((prof_FuncTbl) && (prof_FuncTot > 0)) { printf("\nFUNC_PROF stats:\n"); pptr = prof_FuncTbl; for(i=0; i<prof_FuncTot; pptr++,i++) { if(pptr->pcount < minhit) { continue; } if((tfd < 0) || (AddrToSym(tfd,pptr->data,symname,¬used) == 0)) { printf(" %08lx : %d\n",pptr->data,pptr->pcount); } else { printf(" %-25s: %d\n",symname,pptr->pcount); } if((more) && (++linecount >= more)) { linecount = 0; if(More() == 0) { goto showdone; } } } } if((prof_TidTbl) && (prof_TidTot > 0)) { printf("\nTID_PROF stats:\n"); pptr = prof_TidTbl; for(i=0; i<prof_TidTot; pptr++,i++) { if(pptr->pcount < minhit) { continue; } printf(" %08lx : %d\n",pptr->data,pptr->pcount); if((more) && (++linecount >= more)) { linecount = 0; if(More() == 0) { goto showdone; } } } } if(prof_PcTbl) { ushort *sp; ulong *lp; sp = (ushort *)prof_PcTbl; lp = (ulong *)prof_PcTbl; printf("\nPC_PROF stats:\n"); for(i=0; i<prof_PcTot; i++) { switch(prof_PcWidth) { case 2: if(*sp >= minhit) { printf(" %08x : %d\n", (int)sp + prof_PcDelta,*sp); linecount++; } sp++; break; case 4: if(*lp >= minhit) { printf(" %08x : %ld\n", (int)lp + prof_PcDelta,*lp); linecount++; } lp++; break; } if((more) && (linecount >= more)) { linecount = 0; if(More() == 0) { goto showdone; } } } } showdone: putchar('\n'); if(prof_BadSymCnt) { printf("%d out-of-range symbols\n",prof_BadSymCnt); } if(prof_TidOverflow) { printf("%d tid overflow attempts\n",prof_TidOverflow); } if(prof_PcOORCnt) { printf("%d pc out-of-range hits\n",prof_PcOORCnt); } printf("%d total profiler calls\n",prof_CallCnt); if(tfd >= 0) { tfsclose(tfd,0); } return; }