📄 mal_debugger.mx
字号:
mal_export str optimizeMALBlock(MalBlkPtr mb);mal_export str debugOptimizers(MalBlkPtr mb, MalStkPtr stk, InstrPtr pci);#endif /* _MAL_DEBUGGER_h */@+ Debugger frameworkBefore the interpreter is allowed to proceed we give controlto the user to alter the trace/debugger options.@c#include "mal_config.h"#include "mal_readline.h"#include "mal_debugger.h"#include "mal_atom.h" /* for showAtoms() */#include "mal_interpreter.h" /* for getArgReference() */#include "mal_linker.h" /* for getAddress() */#include "mal_module.h" /* for showModuleStatistics() */#include "mal_parser.h"#include "mal_namespace.h"int MDBdelay; /* do not immediately react */#define skipBlanc(c,X) while(*(X) && isspace((int)*X)){ X++; }#define skipNonBlanc(c,X) while(*(X) && !isspace((int) *X)){ X++; }#define skipWord(c,X) skipNonBlanc(c,X); skipBlanc(c,X);@-Each client has its own breakpoint administration, kept in a global table.Although a little space consumptive, it is the easiest to maintainand much less expensive as reserving debugger space in each instruction.@cmdbStateRecord mdbTable[MAL_MAXCLIENTS];charisBreakpoint(Client cntxt, MalBlkPtr mb, InstrPtr p, int pc){ int i, j; for (i = 0; i < mdbTable[cntxt->idx].brkTop; i++) { if( mdbTable[cntxt->idx].brkBlock[i] != mb) continue; if( mdbTable[cntxt->idx].brkPc[i] == pc ) return mdbTable[cntxt->idx].brkCmd[i]; if( mdbTable[cntxt->idx].brkMod[i] && getModuleId(p) && mdbTable[cntxt->idx].brkFcn[i] && getFunctionId(p) && strcmp(mdbTable[cntxt->idx].brkMod[i], getModuleId(p))==0 && strcmp(mdbTable[cntxt->idx].brkFcn[i], getFunctionId(p))==0) return mdbTable[cntxt->idx].brkCmd[i]; if( mdbTable[cntxt->idx].brkVar[i] >= 0 ) for (j = 0; j < p->retc; j++) if (mdbTable[cntxt->idx].brkVar[i] == getArg(p,j)) return mdbTable[cntxt->idx].brkCmd[i]; } return 0;}@-Break points can be set on assignment to a specific variable,specific operation, or a instruction line@cvoidmdbSetBreakRequest(Client cntxt, MalBlkPtr mb, str request, char cmd){ int i; str modnme, fcnnme; mdbState mdb = mdbTable + cntxt->idx; Symbol sym; /* set breakpoint on specific line */ if( *request == '#' ){ i= atoi(request+1); if( i<0 || i>= mb->stop) stream_printf(cntxt->fdout, "breakpoint on #%d (<%d) not set\n", i, mb->stop); else { mdb->brkBlock[mdb->brkTop] = mb; mdb->brkPc[mdb->brkTop] = i; mdb->brkVar[mdb->brkTop] = -1; mdb->brkMod[mdb->brkTop] = 0; mdb->brkFcn[mdb->brkTop] = 0; mdb->brkRequest[mdb->brkTop] = GDKstrdup(request); mdb->brkCmd[mdb->brkTop] = cmd; if (mdb->brkTop + 1 < MAXBREAKS) mdb->brkTop++; } return; } /* check for a [module.]function request */ fcnnme= strchr(request,'.'); if( fcnnme){ modnme= request; *fcnnme= 0; fcnnme++; sym= findMALSymbol(modnme,fcnnme); mdb->brkBlock[mdb->brkTop] = sym? sym->def: mb; mdb->brkPc[mdb->brkTop] = -1; mdb->brkVar[mdb->brkTop] = -1; mdb->brkMod[mdb->brkTop] = putName(modnme,strlen(modnme)); mdb->brkFcn[mdb->brkTop] = putName(fcnnme,strlen(fcnnme)); fcnnme--; *fcnnme= '.'; mdb->brkRequest[mdb->brkTop] = GDKstrdup(request); mdb->brkCmd[mdb->brkTop] = cmd; if (mdb->brkTop + 1 < MAXBREAKS) mdb->brkTop++; return; } /* the final step is to break on a variable */ i= findVariable(mb,request); if( i< 0) stream_printf(cntxt->fdout, "breakpoint on %s not set\n", request); else { mdb->brkBlock[mdb->brkTop] = mb; mdb->brkPc[mdb->brkTop] = -1; mdb->brkVar[mdb->brkTop] = i; mdb->brkMod[mdb->brkTop] = 0; mdb->brkFcn[mdb->brkTop] = 0; mdb->brkRequest[mdb->brkTop] = GDKstrdup(request); mdb->brkCmd[mdb->brkTop] = cmd; if (mdb->brkTop + 1 < MAXBREAKS) mdb->brkTop++; }}@-A breakpoint should be set once for each combination@cvoidmdbSetBreakpoint(Client cntxt, MalBlkPtr mb, int pc, char cmd){ mdbState mdb = mdbTable + cntxt->idx; char buf[20]; snprintf(buf,20,"#%d",pc); mdb->brkBlock[mdb->brkTop] = mb; mdb->brkPc[mdb->brkTop] = pc; mdb->brkVar[mdb->brkTop] = -1; mdb->brkMod[mdb->brkTop] = 0; mdb->brkFcn[mdb->brkTop] = 0; mdb->brkRequest[mdb->brkTop] = GDKstrdup(buf); mdb->brkCmd[mdb->brkTop] = cmd; if (mdb->brkTop + 1 < MAXBREAKS) mdb->brkTop++;}voidmdbShowBreakpoints(Client cntxt){ int i; mdbState mdb = mdbTable + cntxt->idx; for (i = 0; i < mdb->brkTop; i++) stream_printf(cntxt->fdout, "breakpoint on '%s'\n", mdb->brkRequest[i]);}voidmdbClrBreakpoint(Client cntxt, int pc){ int i, j = 0; mdbState mdb = mdbTable + cntxt->idx; for (i = 0; i < mdb->brkTop; i++) { mdb->brkBlock[j] = mdb->brkBlock[i]; mdb->brkPc[j] = mdb->brkPc[i]; mdb->brkVar[j] = mdb->brkVar[i]; mdb->brkMod[j] = mdb->brkMod[i]; mdb->brkFcn[j] = mdb->brkFcn[i]; mdb->brkRequest[j] = mdb->brkRequest[i]; mdb->brkCmd[j] = mdb->brkCmd[i]; if (mdb->brkPc[i] != pc) j++; else { GDKfree(mdb->brkRequest[i]); mdb->brkRequest[i] = 0; } } mdb->brkTop = j;}voidmdbClrBreakRequest(Client cntxt, str request){ int i, j = 0; mdbState mdb = mdbTable + cntxt->idx; for (i=0; i < mdb->brkTop; i++) { mdb->brkBlock[j] = mdb->brkBlock[i]; mdb->brkPc[j] = mdb->brkPc[i]; mdb->brkVar[j] = mdb->brkVar[i]; mdb->brkMod[j] = mdb->brkMod[i]; mdb->brkFcn[j] = mdb->brkFcn[i]; mdb->brkRequest[j] = mdb->brkRequest[i]; mdb->brkCmd[j] = mdb->brkCmd[i]; if (strcmp(mdb->brkRequest[i], request)) j++; else { GDKfree(mdb->brkRequest[i]); mdb->brkRequest[i] = 0; } } mdb->brkTop = j;}@-The instruction call stack is the most common command.Prepare a string for an instruction call. We rely on the buffersize of instruction2str.@cstrcall2str(Client cntxt, MalBlkPtr mb, MalStkPtr stk, int pc){ int k,len; str msg,w; str s; InstrPtr p; p= getInstrPtr(mb,pc); msg = instruction2str(mb, p, FALSE); s = strchr(msg, '('); if (p->retc > 1 && s) { s = strchr(s + 1, '('); } if (s) { s++; *s = 0; len = strlen(msg); for (k = p->retc; k < p->argc; k++) { VarPtr v = getVar(mb, getArg(p, k)); ValPtr val = &stk->stk[getArg(p, k)]; if (v->tmpindex == 0) sprintf(msg+len, "%s=", v->name); else sprintf(msg+len, "%c%d=", TMPMARKER, v->tmpindex); w = 0; ATOMformat(val->vtype, VALptr(val), &w); strcat(msg,w); if( ATOMcmp(val->vtype, ATOMnilptr(val->vtype), VALptr(val))==0){ str tpe= getTypeName(v->type); strcat(msg,":"); strcat(msg,tpe); GDKfree(tpe); } /* in performance monitoring mode we show more details */ if( cntxt->flags && isaBatType(v->type)){ str tpe= getTypeName(v->type); BAT *b; strcat(msg,tpe); b= BATdescriptor(val->val.ival); if( b){ len= strlen(msg); sprintf(msg+len,"{%d}",(int)BATcount(b)); BBPunfix(b->batCacheid); } GDKfree(tpe); } GDKfree(w); if (k < p->argc - 1) strcat(msg,", "); len= strlen(msg); } strcat(msg,")"); } return msg;}voidprintCall(Client cntxt, MalBlkPtr mb, MalStkPtr stk, int pc){ str msg; msg = call2str(cntxt,mb, stk, pc); stream_printf(cntxt->fdout, "%s at %s.%s[%d]\n", msg, getModuleId(getInstrPtr(mb,0)), getFunctionId(getInstrPtr(mb,0)),pc); GDKfree(msg);}@-Beware, the printTraceCall is a rather expensive routine and obscuresthe actual timing. We therefore compensate the global timing maintained@cvoidprintTraceCall(Client cntxt, MalBlkPtr mb, MalStkPtr stk, int pc){ str msg; msg= call2str(cntxt,mb,stk,pc); stream_printf(cntxt->fdout, "%s\n", msg); GDKfree(msg);}@+ MAL parserThe debugger structure is inherited from GDB.The routine mdbCommand is called with p=0 after finishing a mal- function calland before continuing at the next level of invocation.The commands are self-explanatory.The prompt string sent to the user indicates the debugger mode.@c#define MDBstatus(X) if(cntxt->fdout) \ stream_printf(cntxt->fdout,"#MonetDB Debugger %s\n", (X?"on":"off"));static MalBlkPtrmdbLocateMalBlk(MalBlkPtr mb, str b, stream *out){ MalBlkPtr m=mb; char *h=0; int idx=0; if( *b == '['){ idx= atoi(b+1); return getMalBlkHistory(mb,idx); } else if( isdigit((int) *b)){ return getMalBlkHistory(mb,atoi(b)); } else if (*b != 0) { char *fcnname = strchr(b, '.'); Symbol fsym; if (fcnname == NULL ) { stream_printf(out, "<mod>.<fcn>[<nr>] expected\n", b); return NULL; } *fcnname = 0; fcnname++; if( (h= strchr(fcnname,'[')) ){ *h=0; idx= atoi(h+1); } fsym= findMALSymbol(b,fcnname); if (fsym == 0) { stream_printf(out, "'%s.%s' not found\n", b,fcnname); return NULL; } m= fsym->def; } if( m->history== NULL){ stream_printf(out,"No history available\n"); return NULL; } return m;}voidmdbCommand(Client cntxt, MalBlkPtr mb, MalStkPtr stk, InstrPtr p, int pc){ int m = 1; char *b, *c; stream *out = cntxt->fdout; /* int listing = cntxt->listing;*/ char *oldprompt = cntxt->prompt; int oldpromptlength = cntxt->promptlength; if (p != NULL) { if (cntxt != mal_clients) /* help MapiClients with fake prompt */ stream_printf(out,"mdb>"); printTraceCall(cntxt,mb,stk,pc); } if (cntxt == mal_clients) { cntxt->prompt = "mdb>"; cntxt->promptlength = 4; } do { if (cntxt->phase[READER]) { if ((*cntxt->phase[READER]) (cntxt)) { break; } } else if (readConsole(cntxt) <= 0) { break; } b = CURRENT(cntxt); /* terminate the line with zero */ c = strchr(b, '\n'); if (c) { *c = 0; cntxt->fdin->pos += (c - b) + 1; } else { cntxt->fdin->pos = cntxt->fdin->len; } skipBlanc(cntxt, b); switch (*b) { case 0: m = 0; break; case 'a': if (strncmp("atom", b, 1) == 0) showAtoms(out); break; case 'c': if (strncmp("catch", b, 3) == 0) { /* catch the next exception */ stk->cmd = 'C'; break; } if (strncmp("call", b, 3) == 0) { showException(MAL,"mdb.command", "call instruction not yet implemented"); break; } stk->cmd = 'c'; skipWord(cntxt, b); m = 0; break; case 'h': if (strncmp("help", b, 2) == 0) mdbHelp(out); break; case 'e': { /* terminate the execution for ordinary functions only */ if (strncmp("exit", b, 4) == 0) { case 'x': if (!(getInstrPtr(mb, 0)->token == FACcall)) { stk->cmd = 'x'; cntxt->prompt = oldprompt; cntxt->promptlength = oldpromptlength; } } return; } case 'q': { MalStkPtr su; /* return from this debugger */ for (su = stk; su; su = su->up) su->cmd = 0; cntxt->itrace = 0; cntxt->flags = 0; /* MDBstatus(0); */ cntxt->prompt = oldprompt; cntxt->promptlength = oldpromptlength; return; } case 'f': /* finish */ case 'n': /* next */ case 's': /* step */ if (strncmp("scenarios", b, 9) == 0) { showAllScenarios(out); continue; } else if (strncmp("scenario", b, 3) == 0) { showScenarioByName(out, cntxt->scenario); continue; } else if (strncmp("scope", b, 3) == 0) { /* used to inspect the identifier distribution */ showModuleStatistics(out, cntxt->nspace); continue; } else if (strncmp("set", b, 3) == 0) { skipWord(cntxt, b);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -