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 -------------------------------------------------------------------------*/
33 char userBpPresent
= 0;
35 /* call stack can be 1024 deep */
36 STACK_DCL(callStack
,function
*,1024)
39 char *debug_bp_type_strings
[] =
48 "FEXIT", "TMPUSER", ""};
51 static long bpnum
= 0;
53 long getLastBreakptNumber()
62 for ( bp
= hTabFirstItem(bptable
,&k
); bp
;
63 bp
= hTabNextItem(bptable
,&k
))
70 /*-----------------------------------------------------------------*/
71 /* setBreakPoint - creates an entry in the break point table */
72 /*-----------------------------------------------------------------*/
73 int setBreakPoint (unsigned addr
, char addrType
, char bpType
,
74 int (*callBack
)(unsigned,breakp
*,context
*) ,
75 char *fileName
, int lineno
)
79 Dprintf(D_break
, ("setBreakPoint: addr:%x atype:%s bpType:%s [%s:%d]\n",
81 debug_bp_type_strings
[(int)addrType
],
82 debug_bp_type_strings
[(int)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 /*-----------------------------------------------------------------*/
162 Dprintf(D_break
, ("break: Deleting all NEXT BPs\n"));
164 /* for break points delete if they are NEXT */
165 for ( bp
= hTabFirstItem(bptable
,&k
); bp
;
166 bp
= hTabNextItem(bptable
,&k
))
169 /* if this is a step then delete */
170 if (bp
->bpType
== NEXT
)
172 hTabDeleteItem(&bptable
,bp
->addr
,bp
,DELETE_ITEM
,NULL
);
179 static void freeUSERbp(breakp
*bp
)
182 Safe_free(bp
->commands
);
184 Safe_free(bp
->condition
);
188 /*-----------------------------------------------------------------*/
189 /* deleteUSERbp - deletes USER break point with number */
190 /*-----------------------------------------------------------------*/
191 void deleteUSERbp (int bpnum
)
196 Dprintf(D_break
, ("break: deleteUSERbp %d\n", bpnum
));
198 /* for break points delete if they are STEP */
199 for ( bp
= hTabFirstItem(bptable
,&k
); bp
;
200 bp
= hTabNextItem(bptable
,&k
)) {
202 /* if this is a user then delete if break
203 point matches or bpnumber == -1 (meaning delete
204 all user break points */
205 if ((bp
->bpType
== USER
|| bp
->bpType
== TMPUSER
)
206 && ( bp
->bpnum
== bpnum
|| bpnum
== -1))
208 hTabDeleteItem(&bptable
,bp
->addr
,bp
,DELETE_ITEM
,NULL
);
210 /* if this leaves no other break points then
211 send command to simulator to delete bp from this addr */
212 if (hTabSearch(bptable
,bp
->addr
) == NULL
) {
213 simClearBP (bp
->addr
);
214 Dprintf(D_break
, ("break: deleteUSERbp:simClearBP 0x%x\n", bp
->addr
));
217 fprintf(stdout
,"Deleted breakpoint %d\n",bp
->bpnum
);
227 if (!bp
&& bpnum
!= -1)
228 fprintf(stderr
,"No breakpoint number %d.\n",bpnum
);
231 /*-----------------------------------------------------------------*/
232 /* setUserbpCommand - set commandstring for breakpoint */
233 /*-----------------------------------------------------------------*/
234 void setUserbpCommand (int bpnum
, char *cmds
)
238 Dprintf(D_break
, ("break: setUserbpCommand %d: commands:\n%send\n",
241 for ( bp
= hTabFirstItem(bptable
,&k
); bp
;
242 bp
= hTabNextItem(bptable
,&k
))
244 if ((bp
->bpType
== USER
|| bp
->bpType
== TMPUSER
)
245 && ( bp
->bpnum
== bpnum
))
248 Safe_free(bp
->commands
);
253 fprintf(stderr
,"No breakpoint number %d.\n",bpnum
);
256 /*-----------------------------------------------------------------*/
257 /* setUserbpCondition - set condition string for breakpoint */
258 /*-----------------------------------------------------------------*/
259 void setUserbpCondition (int bpnum
, char *cond
)
263 Dprintf(D_break
, ("break: setUserbpCondition %d: condition:'%s'\n",
264 bpnum
, cond
?cond
:""));
266 for ( bp
= hTabFirstItem(bptable
,&k
); bp
;
267 bp
= hTabNextItem(bptable
,&k
))
269 if ((bp
->bpType
== USER
|| bp
->bpType
== TMPUSER
)
270 && ( bp
->bpnum
== bpnum
))
273 Safe_free(bp
->condition
);
274 bp
->condition
= cond
;
278 fprintf(stderr
,"No breakpoint number %d.\n",bpnum
);
281 /*-----------------------------------------------------------------*/
282 /* setUserbpIgnCount - set ignorecount for breakpoint */
283 /*-----------------------------------------------------------------*/
284 void setUserbpIgnCount (int bpnum
, int ignorecnt
)
288 Dprintf(D_break
, ("break: setUserbpIgnCount %d: ignorecnt=%d\n",
291 for ( bp
= hTabFirstItem(bptable
,&k
); bp
;
292 bp
= hTabNextItem(bptable
,&k
))
294 if ((bp
->bpType
== USER
|| bp
->bpType
== TMPUSER
)
295 && ( bp
->bpnum
== bpnum
))
297 bp
->ignoreCnt
= bp
->hitCnt
+ ignorecnt
;
301 fprintf(stderr
,"No breakpoint number %d.\n",bpnum
);
304 /*-----------------------------------------------------------------*/
305 /* listUSERbp - list all user break points */
306 /*-----------------------------------------------------------------*/
312 /* if there are none then say so & return */
313 if (!userBpPresent
) {
314 fprintf(stdout
,"No breakpoints.\n");
317 fprintf(stdout
,"Num Type Disp Enb Address What\n");
318 for ( bp
= hTabFirstItem(bptable
,&k
) ; bp
;
319 bp
= hTabNextItem(bptable
,&k
)) {
322 if (bp
->bpType
== USER
) {
323 fprintf(stdout
,"%-3d breakpoint keep y 0x%08x at %s:%d\n",
325 bp
->filename
,bp
->lineno
+1);
328 else if (bp
->bpType
== TMPUSER
) {
329 fprintf(stdout
,"%-3d breakpoint del y 0x%08x at %s:%d\n",
331 bp
->filename
,bp
->lineno
+1);
336 if ( bp
->ignoreCnt
> bp
->hitCnt
)
337 fprintf(stdout
,"\tignore next %d hits\n",
338 bp
->ignoreCnt
- bp
->hitCnt
);
340 fprintf(stdout
,"\tstop only if %s\n",bp
->condition
);
341 if ( bp
->hitCnt
> 0 )
342 fprintf(stdout
,"\tbreakpoint already hit %d time%s\n",
343 bp
->hitCnt
,bp
->hitCnt
>1?"s":"" );
349 /*-----------------------------------------------------------------*/
350 /* simStopBPCB - simulator stopped break point */
351 /*-----------------------------------------------------------------*/
352 static int simStopBPCB( unsigned int addr
)
354 fprintf(stdout
,"Simulator stopped at Address 0x%04x\n",addr
);
355 fprintf(stdout
,"%s",simResponse());
359 /*-----------------------------------------------------------------*/
360 /* clearUSERbp - deletes USER break point at address */
361 /*-----------------------------------------------------------------*/
362 void clearUSERbp ( unsigned int addr
)
366 /* for break points delete if they are STEP */
367 for ( bp
= hTabFirstItemWK(bptable
,addr
); bp
;
368 bp
= hTabNextItemWK(bptable
)) {
370 /* if this is a step then delete */
371 if (bp
->bpType
== USER
|| bp
->bpType
== TMPUSER
)
373 hTabDeleteItem(&bptable
,bp
->addr
,bp
,DELETE_ITEM
,NULL
);
375 /* if this leaves no other break points then
376 send command to simulator to delete bp from this addr */
377 if (hTabSearch(bptable
,bp
->addr
) == NULL
)
379 simClearBP(bp
->addr
);
381 fprintf(stdout
,"Deleted breakpoint %d\n",
390 fprintf(stderr
,"No breakpoint at address 0x%x.\n",addr
);
393 /*-----------------------------------------------------------------*/
394 /* dispatchCB - will lookup the bp table and dispatch the cb funcs */
395 /*-----------------------------------------------------------------*/
396 int dispatchCB (unsigned addr
, context
*ctxt
)
401 Dprintf(D_break
, ("break: dispatchCB: addr:0x%x \n", addr
));
403 /* if no break points set for this address
404 then use a simulator stop break point */
405 if ((bp
= hTabFirstItemWK(bptable
,addr
)) == NULL
) {
406 if ( doingSteps
== 2 ) return 1;
407 if ( doingSteps
) return 0;
408 if ( contsim
) return 0;
409 return simStopBPCB(addr
);
412 /* dispatch the call back functions */
413 for (; bp
; bp
= hTabNextItemWK(bptable
))
415 rv
+= (*bp
->callBack
)(addr
,bp
,ctxt
);
419 Dprintf(D_break
, ("break: dispatchCB: WARNING rv==0\n"));
425 /*-----------------------------------------------------------------*/
426 /* fentryCB - callback function for function entry */
427 /*-----------------------------------------------------------------*/
428 BP_CALLBACK(fentryCB
)
432 /* we save the value of SP
433 which will be used to display the value of local variables
434 and parameters on the stack */
435 ctxt
->func
->stkaddr
= simGetValue (0x81,'I',1);
437 Dprintf(D_break
, ("break: fentryCB: BP_CALLBACK entry %s sp=0x%02x %p\n",
438 ctxt
->func
->sym
->name
,
439 ctxt
->func
->stkaddr
, p_callStack
));
441 /* and set laddr of calling function to return addr from stack */
442 if ((func
= STACK_PEEK(callStack
)))
444 /* extern stack ?? 'A' */
445 func
->laddr
= simGetValue (ctxt
->func
->stkaddr
-1,'B',2);
447 /* add the current function into the call stack */
448 STACK_PUSH(callStack
,ctxt
->func
);
453 /*-----------------------------------------------------------------*/
454 /* fexitCB - call back for function exit */
455 /*-----------------------------------------------------------------*/
459 /* pop the top most from the call stack */
460 func
= STACK_POP(callStack
);
464 fprintf(stdout
, "Stack underflow\n");
468 Dprintf(D_break
, ("break: fexitCB: BP_CALLBACK entry %s %p\n", func
->sym
->name
, p_callStack
));
470 /* check main function */
471 if ( !strcmp(func
->sym
->name
, "main"))
473 fprintf(stdout
, "Program exited with code %lu.\n", simGetValue (0x82,'I',2));
478 /*-----------------------------------------------------------------*/
479 /* userBpCB - call back function for user break points */
480 /*-----------------------------------------------------------------*/
481 BP_CALLBACK(userBpCB
)
484 Dprintf(D_break
, ("break: userBpCB: BP_CALLBACK entry hit=%d ignor=%d\n",
485 bp
->hitCnt
, bp
->ignoreCnt
));
487 if ( bp
->ignoreCnt
> bp
->hitCnt
)
492 if (! conditionIsTrue( bp
->condition
, ctxt
))
498 Dprintf(D_break
, ("break: userBpCB: commands:%p\n", bp
->commands
));
499 setCmdLine(bp
->commands
);
502 if (srcMode
== SRC_CMODE
) {
503 fprintf(stdout
,"Breakpoint %d, %s() at %s:%d\n",
505 ctxt
->func
->sym
->name
,
506 ctxt
->func
->mod
->c_name
,
508 if (ctxt
->func
->mod
&& ctxt
->cline
> 0)
509 fprintf(stdout
,"%d\t%s",ctxt
->cline
+1,
510 ctxt
->func
->mod
->cLines
[ctxt
->cline
]->src
);
512 fprintf(stdout
,"Breakpoint %d, %s() at %s:%d\n",
514 ctxt
->func
->sym
->name
,
515 ctxt
->func
->mod
->asm_name
,
517 if (ctxt
->func
->mod
&& ctxt
->asmline
> 0)
518 fprintf(stdout
,"%d\t%s",ctxt
->asmline
+1,
519 ctxt
->func
->mod
->asmLines
[ctxt
->asmline
]->src
);
522 if ( bp
->bpType
== TMPUSER
&& bp
->bpnum
> 0 )
524 hTabDeleteItem(&bptable
,bp
->addr
,bp
,DELETE_ITEM
,NULL
);
526 /* if this leaves no other break points then
527 send command to simulator to delete bp from this addr */
528 if (hTabSearch(bptable
,bp
->addr
) == NULL
)
530 simClearBP (bp
->addr
);
531 Dprintf(D_break
, ("break: simClearBP 0x%x\n", bp
->addr
));
540 /*-----------------------------------------------------------------*/
541 /* stepBpCB - call back function for step break points */
542 /*-----------------------------------------------------------------*/
543 BP_CALLBACK(stepBpCB
)
545 static function
*lfunc
= NULL
;
547 Dprintf(D_break
, ("break: stepBpCB: BP_CALLBACK entry\n"));
549 if (srcMode
== SRC_CMODE
) {
550 if ((lfunc
&& lfunc
!= ctxt
->func
) || !lfunc
)
551 fprintf(stdout
,"%s () at %s:%d\n",
552 ctxt
->func
->sym
->name
,
553 ctxt
->func
->mod
->c_name
,
556 if (ctxt
->func
->mod
&& ctxt
->cline
> 0) {
557 fprintf(stdout
,"%d\t%s",ctxt
->cline
+1 ,
558 ctxt
->func
->mod
->cLines
[ctxt
->cline
]->src
);
561 if ((lfunc
&& lfunc
!= ctxt
->func
) || !lfunc
)
562 fprintf(stdout
,"%s () at %s:%d\n",
563 ctxt
->func
->sym
->name
,
564 ctxt
->func
->mod
->asm_name
,
567 if (ctxt
->func
->mod
&& ctxt
->cline
> 0) {
568 fprintf(stdout
,"%d\t%s",ctxt
->asmline
,
569 ctxt
->func
->mod
->asmLines
[ctxt
->asmline
]->src
);
578 /*-----------------------------------------------------------------*/
579 /* nextBpCB - call back function for next break points */
580 /*-----------------------------------------------------------------*/
581 BP_CALLBACK(nextBpCB
)
583 static function
*lfunc
= NULL
;
585 Dprintf(D_break
, ("break: nextBpCB: BP_CALLBACK entry\n"));
587 if (srcMode
== SRC_CMODE
) {
588 if ((lfunc
&& lfunc
!= ctxt
->func
) || !lfunc
)
589 fprintf(stdout
,"%s () at %s:%d\n",
590 ctxt
->func
->sym
->name
,
591 ctxt
->func
->mod
->c_name
,
594 if (ctxt
->func
->mod
&& ctxt
->cline
> 0)
595 fprintf(stdout
,"%d\t%s",ctxt
->cline
+1,
596 ctxt
->func
->mod
->cLines
[ctxt
->cline
]->src
);
598 if ((lfunc
&& lfunc
!= ctxt
->func
) || !lfunc
)
599 fprintf(stdout
,"%s () at %s:%d\n",
600 ctxt
->func
->sym
->name
,
601 ctxt
->func
->mod
->asm_name
,
604 if (ctxt
->func
->mod
&& ctxt
->asmline
> 0)
605 fprintf(stdout
,"%d\t%s",ctxt
->asmline
,
606 ctxt
->func
->mod
->asmLines
[ctxt
->asmline
]->src
);