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 -------------------------------------------------------------------------*/
29 static hTab *bptable = NULL;
31 char userBpPresent = 0;
33 /* call stack can be 1024 deep */
34 STACK_DCL(callStack,function *,1024);
37 char *debug_bp_type_strings[] =
46 "FEXIT", "TMPUSER", ""};
49 /*-----------------------------------------------------------------*/
50 /* setBreakPoint - creates an entry in the break point table */
51 /*-----------------------------------------------------------------*/
52 int setBreakPoint (unsigned addr, char addrType, char bpType,
53 int (*callBack)(unsigned,char,char,int,context *) ,
54 char *fileName, int lineno)
57 static long bpnum = 0;
60 Dprintf(D_break, ("setBreakPoint: addr:%x atype:%s bpType:%s [%s:%d]\n",
62 debug_bp_type_strings[addrType],
63 debug_bp_type_strings[bpType],
66 /* allocate & init a new bp */
67 bp = Safe_calloc(1,sizeof(breakp));
69 bp->addrType = addrType;
71 bp->callBack = callBack;
72 bp->bpnum = ((bpType == USER || bpType == TMPUSER)? ++bpnum : 0);
73 bp->filename = fileName;
76 /* if this is an user break point then
77 check if there already exists one for this address */
78 if (bpType == USER || bpType == TMPUSER)
80 for ( bpl = hTabFirstItemWK(bptable,addr) ; bpl;
81 bpl = hTabNextItemWK(bptable))
84 /* if also a user break point then issue Note : */
85 if (bpl->bpType == USER || bpType == TMPUSER)
86 fprintf(stderr,"Note: breakpoint %d also set at pc 0x%x\n",
87 bpl->bpnum,bpl->addr);
90 fprintf(stderr,"Breakpoint %d at 0x%x: file %s, line %d.\n",
91 bp->bpnum, addr, fileName, lineno+1);
96 if (bpType != STEP && bpType != NEXT)
98 /* if a break point does not already exist then
99 send command to simulator to add one */
100 if (!hTabSearch(bptable,addr))
101 /* send the break command to the simulator */
105 /* now add the break point to list */
106 hTabAddItem(&bptable,addr,bp);
111 /*-----------------------------------------------------------------*/
112 /* deleteSTEPbp - deletes all step break points */
113 /*-----------------------------------------------------------------*/
119 Dprintf(D_break, ("break: Deleting all STEP BPs\n"));
120 /* for break points delete if they are STEP */
121 for ( bp = hTabFirstItem(bptable,&k); bp ;
122 bp = hTabNextItem(bptable,&k)) {
124 /* if this is a step then delete */
125 if (bp->bpType == STEP) {
126 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
134 /*-----------------------------------------------------------------*/
135 /* deleteNEXTbp - deletes all step break points */
136 /*-----------------------------------------------------------------*/
143 Dprintf(D_break, ("break: Deleting all NEXT BPs\n"));
145 /* for break points delete if they are NEXT */
146 for ( bp = hTabFirstItem(bptable,&k); bp ;
147 bp = hTabNextItem(bptable,&k)) {
149 /* if this is a step then delete */
150 if (bp->bpType == NEXT) {
151 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
159 /*-----------------------------------------------------------------*/
160 /* deleteUSERbp - deletes USER break point with number */
161 /*-----------------------------------------------------------------*/
162 void deleteUSERbp (int bpnum)
168 Dprintf(D_break, ("break: deleteUSERbp %d\n", bpnum));
170 /* for break points delete if they are STEP */
171 for ( bp = hTabFirstItem(bptable,&k); bp ;
172 bp = hTabNextItem(bptable,&k)) {
174 /* if this is a user then delete if break
175 point matches or bpnumber == -1 (meaning delete
176 all user break points */
177 if ((bp->bpType == USER || bp->bpType == TMPUSER )
178 && ( bp->bpnum == bpnum || bpnum == -1)) {
179 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
181 /* if this leaves no other break points then
182 send command to simulator to delete bp from this addr */
183 if (hTabSearch(bptable,bp->addr) == NULL) {
184 simClearBP (bp->addr);
185 Dprintf(D_break, ("break: deleteUSERbp:simClearBP 0x%x\n", bp->addr));
188 fprintf(stdout,"Deleted breakpoint %d\n",
198 if (!bp && bpnum != -1)
199 fprintf(stderr,"No breakpoint number %d.\n",bpnum);
202 /*-----------------------------------------------------------------*/
203 /* listUSERbp - list all user break points */
204 /*-----------------------------------------------------------------*/
210 /* if there are none then say so & return */
211 if (!userBpPresent) {
212 fprintf(stdout,"No breakpoints.\n");
215 fprintf(stdout,"Num Type Disp Enb Address What\n");
216 for ( bp = hTabFirstItem(bptable,&k) ; bp ;
217 bp = hTabNextItem(bptable,&k)) {
219 if (bp->bpType == USER ) {
220 fprintf(stdout,"%-3d breakpoint keep y 0x%08x at %s:%d\n",
222 bp->filename,bp->lineno+1);
225 else if (bp->bpType == TMPUSER ) {
226 fprintf(stdout,"%-3d breakpoint del y 0x%08x at %s:%d\n",
228 bp->filename,bp->lineno+1);
234 /*-----------------------------------------------------------------*/
235 /* simStopBPCB - simulator stopped break point */
236 /*-----------------------------------------------------------------*/
237 static int simStopBPCB( unsigned int addr)
239 fprintf(stdout,"Simulator stopped at Address 0x%04x\n",addr);
240 fprintf(stdout,"%s",simResponse());
244 /*-----------------------------------------------------------------*/
245 /* clearUSERbp - deletes USER break point at address */
246 /*-----------------------------------------------------------------*/
247 void clearUSERbp ( unsigned int addr )
252 /* for break points delete if they are STEP */
253 for ( bp = hTabFirstItemWK(bptable,addr); bp ;
254 bp = hTabNextItemWK(bptable)) {
256 /* if this is a step then delete */
257 if (bp->bpType == USER || bp->bpType == TMPUSER) {
258 hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
260 /* if this leaves no other break points then
261 send command to simulator to delete bp from this addr */
262 if (hTabSearch(bptable,bp->addr) == NULL) {
263 simClearBP(bp->addr);
266 fprintf(stdout,"Deleted breakpoint %d\n",
274 fprintf(stderr,"No breakpoint at address 0x%x.\n",addr);
277 /*-----------------------------------------------------------------*/
278 /* dispatchCB - will lookup the bp table and dispatch the cb funcs */
279 /*-----------------------------------------------------------------*/
280 int dispatchCB (unsigned addr, context *ctxt)
285 Dprintf(D_break, ("break: dispatchCB: addr:0x%x \n", addr));
287 /* if no break points set for this address
288 then use a simulator stop break point */
289 if ((bp = hTabFirstItemWK(bptable,addr)) == NULL) {
290 if ( doingSteps == 2 ) return 1;
291 if ( doingSteps ) return 0;
292 if ( contsim ) return 0;
293 return simStopBPCB(addr);
296 /* dispatch the call back functions */
297 for (; bp; bp = hTabNextItemWK(bptable)) {
299 rv += (*bp->callBack)(addr,bp->addrType,
300 bp->bpType,bp->bpnum,ctxt);
305 Dprintf(D_break, ("break: dispatchCB: WARNING rv==0\n", rv));
311 /*-----------------------------------------------------------------*/
312 /* fentryCB - callback function for function entry */
313 /*-----------------------------------------------------------------*/
314 BP_CALLBACK(fentryCB)
318 /* we save the value of SP
319 which will be used to display the value of local variables
320 and parameters on the stack */
321 ctxt->func->stkaddr = simGetValue (0x81,'I',1);
323 Dprintf(D_break, ("break: fentryCB: BP_CALLBACK entry %s sp=0x%02x %p\n",
324 ctxt->func->sym->name,
325 ctxt->func->stkaddr, p_callStack));
327 /* and set laddr of calling function to return addr from stack */
328 if ((func = STACK_PEEK(callStack)))
330 /* extern stack ?? 'A' */
331 func->laddr = simGetValue (ctxt->func->stkaddr-1,'B',2);
333 /* add the current function into the call stack */
334 STACK_PUSH(callStack,ctxt->func);
339 /*-----------------------------------------------------------------*/
340 /* fexitCB - call back for function exit */
341 /*-----------------------------------------------------------------*/
345 /* pop the top most from the call stack */
346 func = STACK_POP(callStack);
348 Dprintf(D_break, ("break: fexitCB: BP_CALLBACK entry %s %p\n",func->sym->name, p_callStack));
350 /* check main function */
351 if ( STACK_EMPTY(callStack))
353 fprintf(stdout,"Program exited with code %d.\n",simGetValue (0x82,'I',2));
358 /*-----------------------------------------------------------------*/
359 /* userBpCB - call back function for user break points */
360 /*-----------------------------------------------------------------*/
361 BP_CALLBACK(userBpCB)
363 Dprintf(D_break, ("break: userBpCB: BP_CALLBACK entry\n"));
365 if (srcMode == SRC_CMODE) {
366 fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n",
368 ctxt->func->sym->name,
369 ctxt->func->mod->c_name,
371 if (ctxt->func->mod && ctxt->cline > 0)
372 fprintf(stdout,"%d\t%s",ctxt->cline+1,
373 ctxt->func->mod->cLines[ctxt->cline]->src);
375 fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n",
377 ctxt->func->sym->name,
378 ctxt->func->mod->asm_name,
380 if (ctxt->func->mod && ctxt->asmline > 0)
381 fprintf(stdout,"%d\t%s",ctxt->asmline+1,
382 ctxt->func->mod->asmLines[ctxt->asmline]->src);
384 if ( bpType == TMPUSER && bpnum > 0 )
385 deleteUSERbp (bpnum);
389 /*-----------------------------------------------------------------*/
390 /* stepBpCB - call back function for step break points */
391 /*-----------------------------------------------------------------*/
392 BP_CALLBACK(stepBpCB)
394 static function *lfunc = NULL;
396 Dprintf(D_break, ("break: stepBpCB: BP_CALLBACK entry\n"));
398 if (srcMode == SRC_CMODE) {
399 if ((lfunc && lfunc != ctxt->func) || !lfunc)
400 fprintf(stdout,"%s () at %s:%d\n",
401 ctxt->func->sym->name,
402 ctxt->func->mod->c_name,
405 if (ctxt->func->mod && ctxt->cline > 0) {
406 fprintf(stdout,"%d\t%s",ctxt->cline+1 ,
407 ctxt->func->mod->cLines[ctxt->cline]->src);
410 if ((lfunc && lfunc != ctxt->func) || !lfunc)
411 fprintf(stdout,"%s () at %s:%d\n",
412 ctxt->func->sym->name,
413 ctxt->func->mod->asm_name,
416 if (ctxt->func->mod && ctxt->cline > 0) {
417 fprintf(stdout,"%d\t%s",ctxt->asmline ,
418 ctxt->func->mod->asmLines[ctxt->asmline]->src);
427 /*-----------------------------------------------------------------*/
428 /* nextBpCB - call back function for next break points */
429 /*-----------------------------------------------------------------*/
430 BP_CALLBACK(nextBpCB)
432 static function *lfunc = NULL;
434 Dprintf(D_break, ("break: nextBpCB: BP_CALLBACK entry\n"));
436 if (srcMode == SRC_CMODE) {
437 if ((lfunc && lfunc != ctxt->func) || !lfunc)
438 fprintf(stdout,"%s () at %s:%d\n",
439 ctxt->func->sym->name,
440 ctxt->func->mod->c_name,
443 if (ctxt->func->mod && ctxt->cline > 0)
444 fprintf(stdout,"%d\t%s",ctxt->cline+1,
445 ctxt->func->mod->cLines[ctxt->cline]->src);
447 if ((lfunc && lfunc != ctxt->func) || !lfunc)
448 fprintf(stdout,"%s () at %s:%d\n",
449 ctxt->func->sym->name,
450 ctxt->func->mod->asm_name,
453 if (ctxt->func->mod && ctxt->asmline > 0)
454 fprintf(stdout,"%d\t%s",ctxt->asmline,
455 ctxt->func->mod->asmLines[ctxt->asmline]->src);