📄 at.c
字号:
/* At description: * The 'at' command provides a state-machine-like ability * for breakpoints. It uses the breakpoint trap as a way * of entering the monitor from active application. Upon * entry into the monitor, a few different things can happen: * * 1. an action can be taken and then application is resumed; * 2. a condition is checked and if the condition is met, an * action is taken; * * It is basically an elaboration of the counting breakpoint (break * at address HHHH the Nth time). The counting breakpoint uses the * break trap to temporarily enter the monitor, change some debug * state, and, if the state meets some condition (in this case, the * count is met), then break; else resume application. * * Note that several action/condition combinations can be done for * a single address. This allows the state machine to be as complex * as necessary. The sequence of the action/conditions is changeable. * * General notice: * This code is part of a boot-monitor package developed as a generic base * platform for embedded system designs. As such, it is likely to be * distributed to various projects beyond the control of the original * author. Please notify the author of any enhancements made or bugs found * so that all may benefit from the changes. In addition, notification back * to the author will allow the new user to pick up changes that may have * been made by other users after this version of the code was distributed. * * Note1: the majority of this code was edited with 4-space tabs. * Note2: as more and more contributions are accepted, the term "author" * is becoming a mis-representation of credit. * * Original author: Ed Sutter * Email: esutter@lucent.com * Phone: 908-582-2351 */#include "config.h"#include "cpu.h"#include "cpuio.h"#include "genlib.h"#if INCLUDE_DEBUG#include "ctype.h"#include "stddefs.h"#include "cli.h"extern void StepOverTrap(), resume(), putreg();ulong PCatBreak; /* Copy of PC at the breakpoint */ushort settrap();/* Use TRAP for breakpoint */#define TRAPNUM 0#define TRAPU 0x4e#define TRAPL (0x40+TRAPNUM)#define ATVARTOT 8 /* Number of AT variables */#define ATLISTSIZE 8 /* Number of AT statements *//* Action definitions: */#define VAR_INC 1 /* increment variable: VAR++ */#define VAR_DEC 2 /* decrement variable: VAR-- */#define VAR_EQ 3 /* assign variable: VAR=vv */#define FLG_SET 4 /* set flag: FSETff */#define FLG_CLR 5 /* clear flag: FCLRff */#define FLG_EQ 6 /* set flag: FEQff */#define BREAK 8 /* break: BRK *//* Condition definitions: */#define VAR_EQ_CONST 20 /* Atvar equals constant */#define VAR_EQ_LOC 21 /* Atvar equals content of location */#define FLG_ALL_SET 22 /* Atflag has all specified bits set */#define FLG_ANY_SET 23 /* Atflag has any specified bits set */#define FLG_EQ_CONST 24 /* Atflag equals constant */#define PASS_COUNT 26 /* At passcount equals constant */#define FUNC_CALL 27 /* At function returns constant */int atinit(), atlist();int ata(), atca();int atvarset(), atflagset(), atdelete(), atswap();static ulong atvars[ATVARTOT];static ushort atflag;struct atstruct { uchar inuse; /* Set if this 'at' structure is in use. */ ushort origtext; /* Value in text prior to TRAP insertion */ ulong address; /* Address of breakpoint */ ushort Condition; /* Condition that will cause action */ ushort Cvar; /* Variable upon which condition is tested */ ulong Cconst; /* Constant used in condition */ ulong Cadd; /* Address used in condition */ ushort Csize; /* Size used in condition */ int Cpcnt; /* Pass count used in condition */ int (*Cfptr)(); /* Function pointer used in condition */ ushort Action; /* Action to be taken */ ushort Avar; /* Variable upon which action is taken */ ulong Aconst; /* Constant used in action */ int idx; /* index into attbl[] */} attbl[ATLISTSIZE];/* At(): * Command line syntax... * at address action # ata * at address ?condition action # atca */intAt(int argc,char *argv[]){ int opt, i; while((opt = getopt(argc,argv,"Dd:f:Ilirs:v:")) != -1) { switch(opt) { case 'D': atdelete(-1); break; case 'd': atdelete(atoi(optarg)); break; case 'f': atflagset(optarg); break; case 'I': atinit(); break; case 'i': installatpoints(); break; case 'l': atlist(1); break; case 'r': removeatpoints(); break; case 's': atswap(optarg); break; case 'v': atvarset(optarg); break; default: return(CMD_PARAM_ERROR); } } /* If any options were specified, then return now. */ if (optind != 1) return(CMD_SUCCESS); /* If no args, then display 'at' data. */ if (argc == 1) { atlist(0); return(CMD_SUCCESS); } /* Find an available slot in the atlist table: */ for(i=0;i<ATLISTSIZE;i++) { if (attbl[i].inuse == 0) break; } if (i == ATLISTSIZE) { printf("At-table full\n"); return(CMD_FAILURE); } /* Load the address: */ attbl[i].address = strtol(argv[optind],(char **)0,0); /* Establish the action: */ if (setupaction(&attbl[i],argc,argv) == -1) { printf("Syntax error in action\n"); return(CMD_PARAM_ERROR); } /* Establish the condition (if any): */ if (setupcondition(&attbl[i],argc,argv) == -1) { printf("Syntax error in condition\n"); return(CMD_PARAM_ERROR); } /* Copy the original text: */ attbl[i].origtext = *(ushort *)(attbl[i].address); /* Mark the 'at' entry as in use: */ attbl[i].inuse = 1; return(CMD_SUCCESS);}/* setupaction(): * Based on the incoming args, build the action. * The action will always be the last argument. */intsetupaction(struct atstruct *atp,int argc,char *argv[]){ char *action, *cp; action = argv[argc-1]; cp = action; while(*cp) toupper(*cp++); if (action[0] == '%') { atp->Avar = strtol(&action[1],&cp,0); if (!strcmp(cp,"++")) atp->Action = VAR_INC; else if (!strcmp(cp,"--")) atp->Action = VAR_DEC; else if (*cp == '=') { atp->Action = VAR_EQ; atp->Aconst = strtol(cp+1,(char **)0,0); } else return(-1); } else if (!strncmp(action,"FSET",4)) { atp->Action = FLG_SET; atp->Aconst = strtol(&action[4],(char **)0,0); } else if (!strncmp(action,"FCLR",4)) { atp->Aconst = strtol(&action[4],(char **)0,0); atp->Action = FLG_CLR; } else if (!strncmp(action,"FEQU",4)) { atp->Aconst = strtol(&action[4],(char **)0,0); atp->Action = FLG_EQ; } else if (!strcmp(action,"BREAK")) { atp->Action = BREAK; } else return(-1); return(0);}/* setupcondition(): * Based on the incoming args, build the condition. * The condition (if any) will always be the next-to-last argument * and will be preceded by a question mark. */intsetupcondition(struct atstruct *atp,int argc,char *argv[]){ char *condition, *cp, *op; int i; condition = (char *)0; for(i=0;i<argc;i++) { if (!strcmp(argv[i],"if")) { condition = argv[i+1]; break; } } cp = condition; while(*cp) toupper(*cp++); if (!condition) /* There may not be a condition specified. */ return(0); op = strchr(condition,'('); atp->Csize = 1; if (condition[0] == '%') { atp->Cvar = strtol(&condition[1],&cp,0); if (*cp == '.') atp->Csize = strtol(cp+1,&cp,0); if (!strncmp(cp,"==",2)) { atp->Condition = VAR_EQ_CONST; atp->Cconst = strtol(cp+2,(char **)0,0); } else if (!strcmp(cp,"==*")) { atp->Condition = VAR_EQ_LOC; atp->Cconst = strtol(cp+3,(char **)0,0); } else return(-1); } else if (!strncmp(condition,"FALL",4)) { atp->Condition = FLG_ALL_SET; atp->Aconst = strtol(&condition[4],(char **)0,0); } else if (!strncmp(condition,"FANY",4)) { atp->Condition = FLG_ANY_SET; atp->Cconst = strtol(&condition[4],(char **)0,0); } else if (!strncmp(condition,"FEQU",4)) { atp->Condition = FLG_EQ_CONST; atp->Cconst = strtol(&condition[4],(char **)0,0); } else if (!strncmp(condition,"PCNT==",6)) { atp->Condition = PASS_COUNT; atp->Cconst = strtol(&condition[6],(char **)0,0); atp->Cpcnt = 0; } else if (strncmp(op,"()==",4) == 0) { atp->Condition = FUNC_CALL; atp->Cfptr = (int(*)())strtol(condition,(char **)0,0); atp->Cconst = strtol(op+4,(char **)0,0); } else return(-1); return(0);}intatvarset(char *vset){ int vnum, val; char *cp; vnum = strtol(vset,&cp,0); if ((vnum < 0) || (vnum >= ATVARTOT)) { printf("Variable number (%d) out of range\n",vnum); return(-1); } if (*cp != '=') { printf("Variable set syntax error\n"); return(-1); } cp++; val = strtol(cp,(char **)0,0); atvars[vnum] = val; return(0);}intatflagset(char *fset){ atflag = strtol(fset,(char **)0,0); return(0);}char *AtHelp[] = { "Complex breakpoints", "-[Dd:f:Iilrs:v:] {address} [if condition] {action}", " -D delete all", " -d{#} delete specific", " -f{xx} set atflag to 'xx'", " -I initialize 'at' structures", " -i install atpoints", " -l list current state", " -r remove atpoints", " -s{x,y} swap at 'x' with at 'y'", " -v{xx=yy} set atvar 'xx' to 'yy'", "Conditions:", " %VV==## atvar 'VV' == '##'", " PCNT==## pass count == '##'", " 0xFFF()==## func at 0xFFF == '##'", " FEQUXX atflag equals 'XX'", " FALLXX atflag OR 'XX' equals 'XX'", " FANYXX atflag OR 'XX' is non-zero", " %VV[.s]==*YY atvar 'VV' (size 's') equals *'YY'", "Actions:", " %VV=YY set atvar 'VV' to 'YY'", " %VV++ increment atvar 'VV'", " %VV-- decrement atvar 'VV'", " FEQUXX set atflag to 'XX'", " FSETXX OR 'XX' with atflag", " FCLRXX AND ~'XX' with atflag", " BREAK break to monitor", "", "%VV ranges from %01 through %08", (char *)0,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -