1 /*-------------------------------------------------------------------------
2 break.c - Source file for break point management
3 Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999)
5 This program is free software; you can redistribute it and/or modify it
6 under the terms of the GNU General Public License as published by the
7 Free Software Foundation; either version 2, or (at your option) any
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 In other words, you are welcome to use, share and improve this program.
20 You are forbidden to forbid anyone else to use, share and improve
21 what you give them. Help stamp out software-hoarding!
22 -------------------------------------------------------------------------*/
30 static hTab *bptable = NULL;
32 char userBpPresent = 0;
34 /* call stack can be 1024 deep */
35 STACK_DCL(callStack,function *,1024);
38 char *debug_bp_type_strings[] =
47 "FEXIT", "TMPUSER", ""};
50 static long bpnum = 0;
52 long getLastBreakptNumber()
61 for ( bp = hTabFirstItem(bptable,&k); bp ;
62 bp = hTabNextItem(bptable,&k))
69 /*-----------------------------------------------------------------*/
70 /* setBreakPoint - creates an entry in the break point table */
71 /*-----------------------------------------------------------------*/
72 int setBreakPoint (unsigned addr, char addrType, char bpType,
73 int (*callBack)(unsigned,breakp *,context *) ,
74 char *fileName, int lineno)
79 Dprintf(D_break, ("setBreakPoint: addr:%x atype:%s bpType:%s [%s:%d]\n",
81 debug_bp_type_strings[addrType],
82 debug_bp_type_strings[bpType],
85 /* allocate & init a new bp */
86 bp = Safe_calloc(1,sizeof(breakp));
88 bp->addrType = addrType;
90 bp->callBack = callBack;
91 bp->bpnum = ((bpType == USER || bpType == TMPUSER)? ++bpnum : 0);
92 bp->filename = fileName;
95 /* if this is an user break point then
96 check if there already exists one for this address */
97 if (bpType == USER || bpType == TMPUSER)
99 for ( bpl = hTabFirstItemWK(bptable,addr) ; bpl;
100 bpl = hTabNextItemWK(bptable))
103 /* if also a user break point then issue Note : */
104 if (bpl->bpType == USER || bpType == TMPUSER)
105 fprintf(stderr,"Note: breakpoint %d also set at pc 0x%x\n",
106 bpl->bpnum,bpl->addr);
109 fprintf(stderr,"Breakpoint %d at 0x%x: file %s, line %d.\n",
110 bp->bpnum, addr, fileName, lineno+1);
115 if (bpType != STEP && bpType != NEXT)
117 /* if a break point does not already exist then
118 send command to simulator to add one */
119 if (!hTabSearch(bptable,addr))
120 /* send the break command to the simulator */
124 /* now add the break point to list */
125 hTabAddItem(&bptable,addr,bp);
130 /*-----------------------------------------------------------------*/
131 /* deleteSTEPbp - deletes all step break points */
132 /*-----------------------------------------------------------------*/
138 Dprintf(D_break, ("break: Deleting all STEP BPs\n"));
139 /* for break points delete if they are STEP */
140 for ( bp = hTabFirstItem(bptable,&k); bp ;
141 bp = hTabNextItem(bptable,&k))
144 /* if this is a step then delete */
145 if (bp->bpType == STEP)
147 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
154 /*-----------------------------------------------------------------*/
155 /* deleteNEXTbp - deletes all step break points */
156 /*-----------------------------------------------------------------*/
163 Dprintf(D_break, ("break: Deleting all NEXT BPs\n"));
165 /* for break points delete if they are NEXT */
166 for ( bp = hTabFirstItem(bptable,&k); bp ;
167 bp = hTabNextItem(bptable,&k))
170 /* if this is a step then delete */
171 if (bp->bpType == NEXT)
173 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
180 static void freeUSERbp(breakp *bp)
183 Safe_free(bp->commands);
185 Safe_free(bp->condition);
189 /*-----------------------------------------------------------------*/
190 /* deleteUSERbp - deletes USER break point with number */
191 /*-----------------------------------------------------------------*/
192 void deleteUSERbp (int bpnum)
198 Dprintf(D_break, ("break: deleteUSERbp %d\n", bpnum));
200 /* for break points delete if they are STEP */
201 for ( bp = hTabFirstItem(bptable,&k); bp ;
202 bp = hTabNextItem(bptable,&k)) {
204 /* if this is a user then delete if break
205 point matches or bpnumber == -1 (meaning delete
206 all user break points */
207 if ((bp->bpType == USER || bp->bpType == TMPUSER )
208 && ( bp->bpnum == bpnum || bpnum == -1))
210 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
212 /* if this leaves no other break points then
213 send command to simulator to delete bp from this addr */
214 if (hTabSearch(bptable,bp->addr) == NULL) {
215 simClearBP (bp->addr);
216 Dprintf(D_break, ("break: deleteUSERbp:simClearBP 0x%x\n", bp->addr));
219 fprintf(stdout,"Deleted breakpoint %d\n",bp->bpnum);
229 if (!bp && bpnum != -1)
230 fprintf(stderr,"No breakpoint number %d.\n",bpnum);
233 /*-----------------------------------------------------------------*/
234 /* setUserbpCommand - set commandstring for breakpoint */
235 /*-----------------------------------------------------------------*/
236 void setUserbpCommand (int bpnum, char *cmds)
240 Dprintf(D_break, ("break: setUserbpCommand %d: commands:\n%send\n",
243 for ( bp = hTabFirstItem(bptable,&k); bp ;
244 bp = hTabNextItem(bptable,&k))
246 if ((bp->bpType == USER || bp->bpType == TMPUSER )
247 && ( bp->bpnum == bpnum ))
250 Safe_free(bp->commands);
255 fprintf(stderr,"No breakpoint number %d.\n",bpnum);
258 /*-----------------------------------------------------------------*/
259 /* setUserbpCondition - set condition string for breakpoint */
260 /*-----------------------------------------------------------------*/
261 void setUserbpCondition (int bpnum, char *cond)
265 Dprintf(D_break, ("break: setUserbpCondition %d: condition:'%s'\n",
266 bpnum, cond?cond:""));
268 for ( bp = hTabFirstItem(bptable,&k); bp ;
269 bp = hTabNextItem(bptable,&k))
271 if ((bp->bpType == USER || bp->bpType == TMPUSER )
272 && ( bp->bpnum == bpnum ))
275 Safe_free(bp->condition);
276 bp->condition = cond;
280 fprintf(stderr,"No breakpoint number %d.\n",bpnum);
283 /*-----------------------------------------------------------------*/
284 /* setUserbpIgnCount - set ignorecount for breakpoint */
285 /*-----------------------------------------------------------------*/
286 void setUserbpIgnCount (int bpnum, int ignorecnt )
290 Dprintf(D_break, ("break: setUserbpIgnCount %d: ignorecnt=%d\n",
293 for ( bp = hTabFirstItem(bptable,&k); bp ;
294 bp = hTabNextItem(bptable,&k))
296 if ((bp->bpType == USER || bp->bpType == TMPUSER )
297 && ( bp->bpnum == bpnum ))
299 bp->ignoreCnt = bp->hitCnt + ignorecnt;
303 fprintf(stderr,"No breakpoint number %d.\n",bpnum);
306 /*-----------------------------------------------------------------*/
307 /* listUSERbp - list all user break points */
308 /*-----------------------------------------------------------------*/
314 /* if there are none then say so & return */
315 if (!userBpPresent) {
316 fprintf(stdout,"No breakpoints.\n");
319 fprintf(stdout,"Num Type Disp Enb Address What\n");
320 for ( bp = hTabFirstItem(bptable,&k) ; bp ;
321 bp = hTabNextItem(bptable,&k)) {
324 if (bp->bpType == USER ) {
325 fprintf(stdout,"%-3d breakpoint keep y 0x%08x at %s:%d\n",
327 bp->filename,bp->lineno+1);
330 else if (bp->bpType == TMPUSER ) {
331 fprintf(stdout,"%-3d breakpoint del y 0x%08x at %s:%d\n",
333 bp->filename,bp->lineno+1);
338 if ( bp->ignoreCnt > bp->hitCnt )
339 fprintf(stdout,"\tignore next %d hits\n",
340 bp->ignoreCnt - bp->hitCnt );
342 fprintf(stdout,"\tstop only if %s\n",bp->condition );
343 if ( bp->hitCnt > 0 )
344 fprintf(stdout,"\tbreakpoint already hit %d time%s\n",
345 bp->hitCnt,bp->hitCnt>1?"s":"" );
351 /*-----------------------------------------------------------------*/
352 /* simStopBPCB - simulator stopped break point */
353 /*-----------------------------------------------------------------*/
354 static int simStopBPCB( unsigned int addr)
356 fprintf(stdout,"Simulator stopped at Address 0x%04x\n",addr);
357 fprintf(stdout,"%s",simResponse());
361 /*-----------------------------------------------------------------*/
362 /* clearUSERbp - deletes USER break point at address */
363 /*-----------------------------------------------------------------*/
364 void clearUSERbp ( unsigned int addr )
369 /* for break points delete if they are STEP */
370 for ( bp = hTabFirstItemWK(bptable,addr); bp ;
371 bp = hTabNextItemWK(bptable)) {
373 /* if this is a step then delete */
374 if (bp->bpType == USER || bp->bpType == TMPUSER)
376 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
378 /* if this leaves no other break points then
379 send command to simulator to delete bp from this addr */
380 if (hTabSearch(bptable,bp->addr) == NULL)
382 simClearBP(bp->addr);
384 fprintf(stdout,"Deleted breakpoint %d\n",
393 fprintf(stderr,"No breakpoint at address 0x%x.\n",addr);
396 /*-----------------------------------------------------------------*/
397 /* dispatchCB - will lookup the bp table and dispatch the cb funcs */
398 /*-----------------------------------------------------------------*/
399 int dispatchCB (unsigned addr, context *ctxt)
404 Dprintf(D_break, ("break: dispatchCB: addr:0x%x \n", addr));
406 /* if no break points set for this address
407 then use a simulator stop break point */
408 if ((bp = hTabFirstItemWK(bptable,addr)) == NULL) {
409 if ( doingSteps == 2 ) return 1;
410 if ( doingSteps ) return 0;
411 if ( contsim ) return 0;
412 return simStopBPCB(addr);
415 /* dispatch the call back functions */
416 for (; bp; bp = hTabNextItemWK(bptable))
418 rv += (*bp->callBack)(addr,bp,ctxt);
422 Dprintf(D_break, ("break: dispatchCB: WARNING rv==0\n", rv));
428 /*-----------------------------------------------------------------*/
429 /* fentryCB - callback function for function entry */
430 /*-----------------------------------------------------------------*/
431 BP_CALLBACK(fentryCB)
435 /* we save the value of SP
436 which will be used to display the value of local variables
437 and parameters on the stack */
438 ctxt->func->stkaddr = simGetValue (0x81,'I',1);
440 Dprintf(D_break, ("break: fentryCB: BP_CALLBACK entry %s sp=0x%02x %p\n",
441 ctxt->func->sym->name,
442 ctxt->func->stkaddr, p_callStack));
444 /* and set laddr of calling function to return addr from stack */
445 if ((func = STACK_PEEK(callStack)))
447 /* extern stack ?? 'A' */
448 func->laddr = simGetValue (ctxt->func->stkaddr-1,'B',2);
450 /* add the current function into the call stack */
451 STACK_PUSH(callStack,ctxt->func);
456 /*-----------------------------------------------------------------*/
457 /* fexitCB - call back for function exit */
458 /*-----------------------------------------------------------------*/
462 /* pop the top most from the call stack */
463 func = STACK_POP(callStack);
467 fprintf(stdout,"Stack underflow\n");
471 Dprintf(D_break, ("break: fexitCB: BP_CALLBACK entry %s %p\n",func->sym->name, p_callStack));
473 /* check main function */
474 if ( STACK_EMPTY(callStack) && !strcmp(func->sym->name,"main"))
476 fprintf(stdout,"Program exited with code %d.\n",simGetValue (0x82,'I',2));
481 /*-----------------------------------------------------------------*/
482 /* userBpCB - call back function for user break points */
483 /*-----------------------------------------------------------------*/
484 BP_CALLBACK(userBpCB)
487 Dprintf(D_break, ("break: userBpCB: BP_CALLBACK entry hit=%d ignor=%d\n",
488 bp->hitCnt, bp->ignoreCnt));
490 if ( bp->ignoreCnt > bp->hitCnt )
495 if (! conditionIsTrue( bp->condition, ctxt ))
501 Dprintf(D_break, ("break: userBpCB: commands:%d\n", bp->commands));
502 setCmdLine(bp->commands);
505 if (srcMode == SRC_CMODE) {
506 fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n",
508 ctxt->func->sym->name,
509 ctxt->func->mod->c_name,
511 if (ctxt->func->mod && ctxt->cline > 0)
512 fprintf(stdout,"%d\t%s",ctxt->cline+1,
513 ctxt->func->mod->cLines[ctxt->cline]->src);
515 fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n",
517 ctxt->func->sym->name,
518 ctxt->func->mod->asm_name,
520 if (ctxt->func->mod && ctxt->asmline > 0)
521 fprintf(stdout,"%d\t%s",ctxt->asmline+1,
522 ctxt->func->mod->asmLines[ctxt->asmline]->src);
525 if ( bp->bpType == TMPUSER && bp->bpnum > 0 )
527 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
529 /* if this leaves no other break points then
530 send command to simulator to delete bp from this addr */
531 if (hTabSearch(bptable,bp->addr) == NULL)
533 simClearBP (bp->addr);
534 Dprintf(D_break, ("break: simClearBP 0x%x\n", bp->addr));
543 /*-----------------------------------------------------------------*/
544 /* stepBpCB - call back function for step break points */
545 /*-----------------------------------------------------------------*/
546 BP_CALLBACK(stepBpCB)
548 static function *lfunc = NULL;
550 Dprintf(D_break, ("break: stepBpCB: BP_CALLBACK entry\n"));
552 if (srcMode == SRC_CMODE) {
553 if ((lfunc && lfunc != ctxt->func) || !lfunc)
554 fprintf(stdout,"%s () at %s:%d\n",
555 ctxt->func->sym->name,
556 ctxt->func->mod->c_name,
559 if (ctxt->func->mod && ctxt->cline > 0) {
560 fprintf(stdout,"%d\t%s",ctxt->cline+1 ,
561 ctxt->func->mod->cLines[ctxt->cline]->src);
564 if ((lfunc && lfunc != ctxt->func) || !lfunc)
565 fprintf(stdout,"%s () at %s:%d\n",
566 ctxt->func->sym->name,
567 ctxt->func->mod->asm_name,
570 if (ctxt->func->mod && ctxt->cline > 0) {
571 fprintf(stdout,"%d\t%s",ctxt->asmline ,
572 ctxt->func->mod->asmLines[ctxt->asmline]->src);
581 /*-----------------------------------------------------------------*/
582 /* nextBpCB - call back function for next break points */
583 /*-----------------------------------------------------------------*/
584 BP_CALLBACK(nextBpCB)
586 static function *lfunc = NULL;
588 Dprintf(D_break, ("break: nextBpCB: BP_CALLBACK entry\n"));
590 if (srcMode == SRC_CMODE) {
591 if ((lfunc && lfunc != ctxt->func) || !lfunc)
592 fprintf(stdout,"%s () at %s:%d\n",
593 ctxt->func->sym->name,
594 ctxt->func->mod->c_name,
597 if (ctxt->func->mod && ctxt->cline > 0)
598 fprintf(stdout,"%d\t%s",ctxt->cline+1,
599 ctxt->func->mod->cLines[ctxt->cline]->src);
601 if ((lfunc && lfunc != ctxt->func) || !lfunc)
602 fprintf(stdout,"%s () at %s:%d\n",
603 ctxt->func->sym->name,
604 ctxt->func->mod->asm_name,
607 if (ctxt->func->mod && ctxt->asmline > 0)
608 fprintf(stdout,"%d\t%s",ctxt->asmline,
609 ctxt->func->mod->asmLines[ctxt->asmline]->src);