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)
78 Dprintf(D_break, ("setBreakPoint: addr:%x atype:%s bpType:%s [%s:%d]\n",
80 debug_bp_type_strings[addrType],
81 debug_bp_type_strings[bpType],
84 /* allocate & init a new bp */
85 bp = Safe_calloc(1,sizeof(breakp));
87 bp->addrType = addrType;
89 bp->callBack = callBack;
90 bp->bpnum = ((bpType == USER || bpType == TMPUSER)? ++bpnum : 0);
91 bp->filename = fileName;
94 /* if this is an user break point then
95 check if there already exists one for this address */
96 if (bpType == USER || bpType == TMPUSER)
98 for ( bpl = hTabFirstItemWK(bptable,addr) ; bpl;
99 bpl = hTabNextItemWK(bptable))
102 /* if also a user break point then issue Note : */
103 if (bpl->bpType == USER || bpType == TMPUSER)
104 fprintf(stderr,"Note: breakpoint %d also set at pc 0x%x\n",
105 bpl->bpnum,bpl->addr);
108 fprintf(stderr,"Breakpoint %d at 0x%x: file %s, line %d.\n",
109 bp->bpnum, addr, fileName, lineno+1);
114 if (bpType != STEP && bpType != NEXT)
116 /* if a break point does not already exist then
117 send command to simulator to add one */
118 if (!hTabSearch(bptable,addr))
119 /* send the break command to the simulator */
123 /* now add the break point to list */
124 hTabAddItem(&bptable,addr,bp);
129 /*-----------------------------------------------------------------*/
130 /* deleteSTEPbp - deletes all step break points */
131 /*-----------------------------------------------------------------*/
137 Dprintf(D_break, ("break: Deleting all STEP BPs\n"));
138 /* for break points delete if they are STEP */
139 for ( bp = hTabFirstItem(bptable,&k); bp ;
140 bp = hTabNextItem(bptable,&k))
143 /* if this is a step then delete */
144 if (bp->bpType == STEP)
146 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
153 /*-----------------------------------------------------------------*/
154 /* deleteNEXTbp - deletes all step break points */
155 /*-----------------------------------------------------------------*/
161 Dprintf(D_break, ("break: Deleting all NEXT BPs\n"));
163 /* for break points delete if they are NEXT */
164 for ( bp = hTabFirstItem(bptable,&k); bp ;
165 bp = hTabNextItem(bptable,&k))
168 /* if this is a step then delete */
169 if (bp->bpType == NEXT)
171 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
178 static void freeUSERbp(breakp *bp)
181 Safe_free(bp->commands);
183 Safe_free(bp->condition);
187 /*-----------------------------------------------------------------*/
188 /* deleteUSERbp - deletes USER break point with number */
189 /*-----------------------------------------------------------------*/
190 void deleteUSERbp (int bpnum)
195 Dprintf(D_break, ("break: deleteUSERbp %d\n", bpnum));
197 /* for break points delete if they are STEP */
198 for ( bp = hTabFirstItem(bptable,&k); bp ;
199 bp = hTabNextItem(bptable,&k)) {
201 /* if this is a user then delete if break
202 point matches or bpnumber == -1 (meaning delete
203 all user break points */
204 if ((bp->bpType == USER || bp->bpType == TMPUSER )
205 && ( bp->bpnum == bpnum || bpnum == -1))
207 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
209 /* if this leaves no other break points then
210 send command to simulator to delete bp from this addr */
211 if (hTabSearch(bptable,bp->addr) == NULL) {
212 simClearBP (bp->addr);
213 Dprintf(D_break, ("break: deleteUSERbp:simClearBP 0x%x\n", bp->addr));
216 fprintf(stdout,"Deleted breakpoint %d\n",bp->bpnum);
226 if (!bp && bpnum != -1)
227 fprintf(stderr,"No breakpoint number %d.\n",bpnum);
230 /*-----------------------------------------------------------------*/
231 /* setUserbpCommand - set commandstring for breakpoint */
232 /*-----------------------------------------------------------------*/
233 void setUserbpCommand (int bpnum, char *cmds)
237 Dprintf(D_break, ("break: setUserbpCommand %d: commands:\n%send\n",
240 for ( bp = hTabFirstItem(bptable,&k); bp ;
241 bp = hTabNextItem(bptable,&k))
243 if ((bp->bpType == USER || bp->bpType == TMPUSER )
244 && ( bp->bpnum == bpnum ))
247 Safe_free(bp->commands);
252 fprintf(stderr,"No breakpoint number %d.\n",bpnum);
255 /*-----------------------------------------------------------------*/
256 /* setUserbpCondition - set condition string for breakpoint */
257 /*-----------------------------------------------------------------*/
258 void setUserbpCondition (int bpnum, char *cond)
262 Dprintf(D_break, ("break: setUserbpCondition %d: condition:'%s'\n",
263 bpnum, cond?cond:""));
265 for ( bp = hTabFirstItem(bptable,&k); bp ;
266 bp = hTabNextItem(bptable,&k))
268 if ((bp->bpType == USER || bp->bpType == TMPUSER )
269 && ( bp->bpnum == bpnum ))
272 Safe_free(bp->condition);
273 bp->condition = cond;
277 fprintf(stderr,"No breakpoint number %d.\n",bpnum);
280 /*-----------------------------------------------------------------*/
281 /* setUserbpIgnCount - set ignorecount for breakpoint */
282 /*-----------------------------------------------------------------*/
283 void setUserbpIgnCount (int bpnum, int ignorecnt )
287 Dprintf(D_break, ("break: setUserbpIgnCount %d: ignorecnt=%d\n",
290 for ( bp = hTabFirstItem(bptable,&k); bp ;
291 bp = hTabNextItem(bptable,&k))
293 if ((bp->bpType == USER || bp->bpType == TMPUSER )
294 && ( bp->bpnum == bpnum ))
296 bp->ignoreCnt = bp->hitCnt + ignorecnt;
300 fprintf(stderr,"No breakpoint number %d.\n",bpnum);
303 /*-----------------------------------------------------------------*/
304 /* listUSERbp - list all user break points */
305 /*-----------------------------------------------------------------*/
311 /* if there are none then say so & return */
312 if (!userBpPresent) {
313 fprintf(stdout,"No breakpoints.\n");
316 fprintf(stdout,"Num Type Disp Enb Address What\n");
317 for ( bp = hTabFirstItem(bptable,&k) ; bp ;
318 bp = hTabNextItem(bptable,&k)) {
321 if (bp->bpType == USER ) {
322 fprintf(stdout,"%-3d breakpoint keep y 0x%08x at %s:%d\n",
324 bp->filename,bp->lineno+1);
327 else if (bp->bpType == TMPUSER ) {
328 fprintf(stdout,"%-3d breakpoint del y 0x%08x at %s:%d\n",
330 bp->filename,bp->lineno+1);
335 if ( bp->ignoreCnt > bp->hitCnt )
336 fprintf(stdout,"\tignore next %d hits\n",
337 bp->ignoreCnt - bp->hitCnt );
339 fprintf(stdout,"\tstop only if %s\n",bp->condition );
340 if ( bp->hitCnt > 0 )
341 fprintf(stdout,"\tbreakpoint already hit %d time%s\n",
342 bp->hitCnt,bp->hitCnt>1?"s":"" );
348 /*-----------------------------------------------------------------*/
349 /* simStopBPCB - simulator stopped break point */
350 /*-----------------------------------------------------------------*/
351 static int simStopBPCB( unsigned int addr)
353 fprintf(stdout,"Simulator stopped at Address 0x%04x\n",addr);
354 fprintf(stdout,"%s",simResponse());
358 /*-----------------------------------------------------------------*/
359 /* clearUSERbp - deletes USER break point at address */
360 /*-----------------------------------------------------------------*/
361 void clearUSERbp ( unsigned int addr )
365 /* for break points delete if they are STEP */
366 for ( bp = hTabFirstItemWK(bptable,addr); bp ;
367 bp = hTabNextItemWK(bptable)) {
369 /* if this is a step then delete */
370 if (bp->bpType == USER || bp->bpType == TMPUSER)
372 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
374 /* if this leaves no other break points then
375 send command to simulator to delete bp from this addr */
376 if (hTabSearch(bptable,bp->addr) == NULL)
378 simClearBP(bp->addr);
380 fprintf(stdout,"Deleted breakpoint %d\n",
389 fprintf(stderr,"No breakpoint at address 0x%x.\n",addr);
392 /*-----------------------------------------------------------------*/
393 /* dispatchCB - will lookup the bp table and dispatch the cb funcs */
394 /*-----------------------------------------------------------------*/
395 int dispatchCB (unsigned addr, context *ctxt)
400 Dprintf(D_break, ("break: dispatchCB: addr:0x%x \n", addr));
402 /* if no break points set for this address
403 then use a simulator stop break point */
404 if ((bp = hTabFirstItemWK(bptable,addr)) == NULL) {
405 if ( doingSteps == 2 ) return 1;
406 if ( doingSteps ) return 0;
407 if ( contsim ) return 0;
408 return simStopBPCB(addr);
411 /* dispatch the call back functions */
412 for (; bp; bp = hTabNextItemWK(bptable))
414 rv += (*bp->callBack)(addr,bp,ctxt);
418 Dprintf(D_break, ("break: dispatchCB: WARNING rv==0\n", rv));
424 /*-----------------------------------------------------------------*/
425 /* fentryCB - callback function for function entry */
426 /*-----------------------------------------------------------------*/
427 BP_CALLBACK(fentryCB)
431 /* we save the value of SP
432 which will be used to display the value of local variables
433 and parameters on the stack */
434 ctxt->func->stkaddr = simGetValue (0x81,'I',1);
436 Dprintf(D_break, ("break: fentryCB: BP_CALLBACK entry %s sp=0x%02x %p\n",
437 ctxt->func->sym->name,
438 ctxt->func->stkaddr, p_callStack));
440 /* and set laddr of calling function to return addr from stack */
441 if ((func = STACK_PEEK(callStack)))
443 /* extern stack ?? 'A' */
444 func->laddr = simGetValue (ctxt->func->stkaddr-1,'B',2);
446 /* add the current function into the call stack */
447 STACK_PUSH(callStack,ctxt->func);
452 /*-----------------------------------------------------------------*/
453 /* fexitCB - call back for function exit */
454 /*-----------------------------------------------------------------*/
458 /* pop the top most from the call stack */
459 func = STACK_POP(callStack);
463 fprintf(stdout,"Stack underflow\n");
467 Dprintf(D_break, ("break: fexitCB: BP_CALLBACK entry %s %p\n",func->sym->name, p_callStack));
469 /* check main function */
470 if ( STACK_EMPTY(callStack) && !strcmp(func->sym->name,"main"))
472 fprintf(stdout,"Program exited with code %d.\n",simGetValue (0x82,'I',2));
477 /*-----------------------------------------------------------------*/
478 /* userBpCB - call back function for user break points */
479 /*-----------------------------------------------------------------*/
480 BP_CALLBACK(userBpCB)
483 Dprintf(D_break, ("break: userBpCB: BP_CALLBACK entry hit=%d ignor=%d\n",
484 bp->hitCnt, bp->ignoreCnt));
486 if ( bp->ignoreCnt > bp->hitCnt )
491 if (! conditionIsTrue( bp->condition, ctxt ))
497 Dprintf(D_break, ("break: userBpCB: commands:%p\n", bp->commands));
498 setCmdLine(bp->commands);
501 if (srcMode == SRC_CMODE) {
502 fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n",
504 ctxt->func->sym->name,
505 ctxt->func->mod->c_name,
507 if (ctxt->func->mod && ctxt->cline > 0)
508 fprintf(stdout,"%d\t%s",ctxt->cline+1,
509 ctxt->func->mod->cLines[ctxt->cline]->src);
511 fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n",
513 ctxt->func->sym->name,
514 ctxt->func->mod->asm_name,
516 if (ctxt->func->mod && ctxt->asmline > 0)
517 fprintf(stdout,"%d\t%s",ctxt->asmline+1,
518 ctxt->func->mod->asmLines[ctxt->asmline]->src);
521 if ( bp->bpType == TMPUSER && bp->bpnum > 0 )
523 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
525 /* if this leaves no other break points then
526 send command to simulator to delete bp from this addr */
527 if (hTabSearch(bptable,bp->addr) == NULL)
529 simClearBP (bp->addr);
530 Dprintf(D_break, ("break: simClearBP 0x%x\n", bp->addr));
539 /*-----------------------------------------------------------------*/
540 /* stepBpCB - call back function for step break points */
541 /*-----------------------------------------------------------------*/
542 BP_CALLBACK(stepBpCB)
544 static function *lfunc = NULL;
546 Dprintf(D_break, ("break: stepBpCB: BP_CALLBACK entry\n"));
548 if (srcMode == SRC_CMODE) {
549 if ((lfunc && lfunc != ctxt->func) || !lfunc)
550 fprintf(stdout,"%s () at %s:%d\n",
551 ctxt->func->sym->name,
552 ctxt->func->mod->c_name,
555 if (ctxt->func->mod && ctxt->cline > 0) {
556 fprintf(stdout,"%d\t%s",ctxt->cline+1 ,
557 ctxt->func->mod->cLines[ctxt->cline]->src);
560 if ((lfunc && lfunc != ctxt->func) || !lfunc)
561 fprintf(stdout,"%s () at %s:%d\n",
562 ctxt->func->sym->name,
563 ctxt->func->mod->asm_name,
566 if (ctxt->func->mod && ctxt->cline > 0) {
567 fprintf(stdout,"%d\t%s",ctxt->asmline ,
568 ctxt->func->mod->asmLines[ctxt->asmline]->src);
577 /*-----------------------------------------------------------------*/
578 /* nextBpCB - call back function for next break points */
579 /*-----------------------------------------------------------------*/
580 BP_CALLBACK(nextBpCB)
582 static function *lfunc = NULL;
584 Dprintf(D_break, ("break: nextBpCB: BP_CALLBACK entry\n"));
586 if (srcMode == SRC_CMODE) {
587 if ((lfunc && lfunc != ctxt->func) || !lfunc)
588 fprintf(stdout,"%s () at %s:%d\n",
589 ctxt->func->sym->name,
590 ctxt->func->mod->c_name,
593 if (ctxt->func->mod && ctxt->cline > 0)
594 fprintf(stdout,"%d\t%s",ctxt->cline+1,
595 ctxt->func->mod->cLines[ctxt->cline]->src);
597 if ((lfunc && lfunc != ctxt->func) || !lfunc)
598 fprintf(stdout,"%s () at %s:%d\n",
599 ctxt->func->sym->name,
600 ctxt->func->mod->asm_name,
603 if (ctxt->func->mod && ctxt->asmline > 0)
604 fprintf(stdout,"%d\t%s",ctxt->asmline,
605 ctxt->func->mod->asmLines[ctxt->asmline]->src);