44d412d4b569c96a6fad54f55fe8e03f5ab12927
[fw/sdcc] / debugger / mcs51 / break.c
1 /*-------------------------------------------------------------------------
2   break.c - Source file for break point management
3         Written By -  Sandeep Dutta . sandeep.dutta@usa.net (1999)
4
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
8    later version.
9
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.
14
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.
18
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 -------------------------------------------------------------------------*/
23
24 #include "sdcdb.h"
25 #include "symtab.h"
26 #include "break.h"
27 #include "newalloc.h"
28
29 static hTab *bptable = NULL;
30 char doingSteps    = 0;
31 char userBpPresent = 0;
32 /* call stack can be 1024 deep */
33 STACK_DCL(callStack,function *,1024);
34
35 #ifdef SDCDB_DEBUG
36 char *debug_bp_type_strings[] =
37     {"ERR-0",
38      "DATA",
39     "CODE"    ,
40     "A_CODE"  ,
41     "USER"    ,
42     "STEP"    ,
43     "NEXT"    ,
44     "FENTRY"  ,
45     "FEXIT", "", ""};
46 #endif
47
48 /*-----------------------------------------------------------------*/
49 /* setBreakPoint - creates an entry in the break point table       */
50 /*-----------------------------------------------------------------*/
51 int setBreakPoint (unsigned addr, char addrType, char bpType,
52         int (*callBack)(unsigned,char,char,int,context *) ,
53         char *fileName, int lineno)
54 {
55     breakp *bp, *bpl;
56     static long bpnum = 0;
57     char simbuf[50];
58
59     Dprintf(D_break, ("setBreakPoint: addr:%x atype:%s bpType:%s [%s:%d]\n",
60         addr,
61         debug_bp_type_strings[addrType],
62         debug_bp_type_strings[bpType],
63         fileName, lineno+1));
64
65     /* allocate & init a new bp */
66     bp = Safe_calloc(1,sizeof(breakp));
67     bp->addr = addr;
68     bp->addrType = addrType;
69     bp->bpType = bpType;
70     bp->callBack = callBack;
71     bp->bpnum = (bpType == USER ? ++bpnum : 0);
72     bp->filename = fileName;
73     bp->lineno = lineno;
74
75     /* if this is an user break point then
76        check if there already exists one for this address */
77     if (bpType == USER)
78     {
79         for ( bpl = hTabFirstItemWK(bptable,addr) ; bpl;
80               bpl = hTabNextItemWK(bptable)) 
81         {
82
83             /* if also a user break point then issue Note : */
84             if (bpl->bpType == USER)
85                 fprintf(stderr,"Note: breakpoint %d also set at pc 0x%x\n",
86                         bpl->bpnum,bpl->addr);
87         }
88
89         fprintf(stderr,"Breakpoint %d at 0x%x: file %s, line %d.\n",
90                 bp->bpnum, addr, fileName, lineno+1);
91
92         userBpPresent++;
93     }
94
95     if (bpType != STEP && bpType != NEXT)
96     {
97     /* if a break point does not already exist then
98        send command to simulator to add one */
99     if (!hTabSearch(bptable,addr))
100         /* send the break command to the simulator */
101         simSetBP (addr);
102     }
103
104     /* now add the break point to list */
105     hTabAddItem(&bptable,addr,bp);
106
107     return bp->bpnum ;
108 }
109
110 /*-----------------------------------------------------------------*/
111 /* deleteSTEPbp - deletes all step break points                    */
112 /*-----------------------------------------------------------------*/
113 void deleteSTEPbp ()
114 {
115     breakp *bp;
116     int k;
117
118     Dprintf(D_break, ("break: Deleting all STEP BPs\n"));
119     /* for break points delete if they are STEP */
120     for ( bp = hTabFirstItem(bptable,&k); bp ;
121     bp = hTabNextItem(bptable,&k)) {
122
123   /* if this is a step then delete */
124   if (bp->bpType == STEP) {
125       hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
126
127 #if 0
128       /* if this leaves no other break points then
129          send command to simulator to delete bp from this addr */
130       if (hTabSearch(bptable,bp->addr) == NULL)
131     simClearBP (bp->addr);
132 #endif
133       free(bp);
134   }
135     }
136
137 }
138
139 /*-----------------------------------------------------------------*/
140 /* deleteNEXTbp - deletes all step break points                    */
141 /*-----------------------------------------------------------------*/
142 void deleteNEXTbp ()
143 {
144     breakp *bp;
145     int k;
146     char simcmd[50];
147
148     Dprintf(D_break, ("break: Deleting all NEXT BPs\n"));
149
150     /* for break points delete if they are NEXT */
151     for ( bp = hTabFirstItem(bptable,&k); bp ;
152     bp = hTabNextItem(bptable,&k)) {
153
154   /* if this is a step then delete */
155   if (bp->bpType == NEXT) {
156       hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
157
158 #if 0
159       /* if this leaves no other break points then
160          send command to simulator to delete bp from this addr */
161       if (hTabSearch(bptable,bp->addr) == NULL) {
162     simClearBP(bp->addr);
163
164       }
165 #endif
166       free(bp);
167   }
168     }
169
170 }
171
172 /*-----------------------------------------------------------------*/
173 /* deleteUSERbp - deletes USER break point with number             */
174 /*-----------------------------------------------------------------*/
175 void deleteUSERbp (int bpnum)
176 {
177     breakp *bp;
178     int k;
179     char simcmd[50];
180
181     Dprintf(D_break, ("break: deleteUSERbp %d\n", bpnum));
182
183     /* for break points delete if they are STEP */
184     for ( bp = hTabFirstItem(bptable,&k); bp ;
185     bp = hTabNextItem(bptable,&k)) {
186
187   /* if this is a user then delete if break
188      point matches or bpnumber == -1 (meaning delete
189      all user break points */
190   if (bp->bpType == USER && ( bp->bpnum == bpnum || bpnum == -1)) {
191       hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
192
193       /* if this leaves no other break points then
194          send command to simulator to delete bp from this addr */
195       if (hTabSearch(bptable,bp->addr) == NULL) {
196     simClearBP (bp->addr);
197     Dprintf(D_break, ("break: deleteUSERbp:simClearBP 0x%x\n", bp->addr));
198
199       }
200       fprintf(stdout,"Deleted breakpoint %d\n",
201         bp->bpnum);
202       userBpPresent --;
203       if (bpnum == -1)
204     continue ;
205       else
206     break;
207   }
208     }
209
210     if (!bp && bpnum != -1)
211   fprintf(stderr,"No breakpoint number %d.\n",bpnum);
212 }
213
214 /*-----------------------------------------------------------------*/
215 /* listUSERbp - list all user break points                         */
216 /*-----------------------------------------------------------------*/
217 void listUSERbp ()
218 {
219     breakp *bp;
220     int k;
221
222     /* if there are none then say so & return */
223     if (!userBpPresent) {
224   fprintf(stdout,"No breakpoints.\n");
225   return ;
226     }
227     fprintf(stdout,"Num Type           Disp Enb Address    What\n");
228     for ( bp = hTabFirstItem(bptable,&k) ; bp ;
229     bp = hTabNextItem(bptable,&k)) {
230
231   if (bp->bpType == USER ) {
232       fprintf(stdout,"%-3d breakpoint     keep y   0x%08x at %s:%d\n",
233         bp->bpnum,bp->addr,
234         bp->filename,bp->lineno+1);
235
236   }
237     }
238 }
239
240 /*-----------------------------------------------------------------*/
241 /* simStopBPCB - simulator stopped break point                     */
242 /*-----------------------------------------------------------------*/
243 static int simStopBPCB( unsigned int addr)
244 {
245   fprintf(stdout,"Simulator stopped at Address 0x%04x\n",addr);
246   fprintf(stdout,"%s",simResponse());
247   return 1;
248 }
249
250 /*-----------------------------------------------------------------*/
251 /* clearUSERbp - deletes USER break point at address               */
252 /*-----------------------------------------------------------------*/
253 void clearUSERbp ( unsigned int addr )
254 {
255     breakp *bp;
256     char simcmd[50];
257
258     /* for break points delete if they are STEP */
259     for ( bp = hTabFirstItemWK(bptable,addr); bp ;
260     bp = hTabNextItemWK(bptable)) {
261
262   /* if this is a step then delete */
263   if (bp->bpType == USER) {
264       hTabDeleteItem(&bptable,bp->addr,bp,DELETE_ITEM,NULL);
265
266       /* if this leaves no other break points then
267          send command to simulator to delete bp from this addr */
268       if (hTabSearch(bptable,bp->addr) == NULL) {
269     simClearBP(bp->addr);
270
271       }
272       fprintf(stdout,"Deleted breakpoint %d\n",
273         bp->bpnum);
274       userBpPresent-- ;
275       break;
276   }
277     }
278
279     if (!bp)
280   fprintf(stderr,"No breakpoint at address 0x%x.\n",addr);
281 }
282
283 /*-----------------------------------------------------------------*/
284 /* dispatchCB - will lookup the bp table and dispatch the cb funcs */
285 /*-----------------------------------------------------------------*/
286 int dispatchCB (unsigned addr, context *ctxt)
287 {
288     breakp *bp;
289     int rv =0;
290
291     Dprintf(D_break, ("break: dispatchCB: addr:0x%x \n", addr));
292
293     /* if no break points set for this address
294        then use a simulator stop break point */
295     if ((bp = hTabFirstItemWK(bptable,addr)) == NULL) {
296       if ( doingSteps == 2 ) return 1;
297       if ( doingSteps ) return 0;
298       return simStopBPCB(addr);
299     }
300
301     /* dispatch the call back functions */
302     for (; bp; bp = hTabNextItemWK(bptable)) {
303
304       rv += (*bp->callBack)(addr,bp->addrType,
305           bp->bpType,bp->bpnum,ctxt);
306
307     }
308
309     if (rv == 0) {
310       Dprintf(D_break, ("break: dispatchCB: WARNING rv==0\n", rv));
311     }
312
313     return rv;
314 }
315
316 /*-----------------------------------------------------------------*/
317 /* fentryCB - callback function for function entry                 */
318 /*-----------------------------------------------------------------*/
319 BP_CALLBACK(fentryCB)
320 {
321     Dprintf(D_break, ("break: fentryCB: BP_CALLBACK entry\n"));
322
323     /* add the current function into the call stack */
324     STACK_PUSH(callStack,ctxt->func);
325
326     /* will have to add code here to get the value of SP
327        which will be used to display the value of local variables
328        and parameters on the stack */
329
330     return 0;
331 }
332
333 /*-----------------------------------------------------------------*/
334 /* fexitCB - call back for function exit                           */
335 /*-----------------------------------------------------------------*/
336 BP_CALLBACK(fexitCB)
337 {
338     Dprintf(D_break, ("break: fexitCB: BP_CALLBACK entry\n"));
339
340     /* pop the top most from the call stack */
341     STACK_POP(callStack);
342     return 0;
343 }
344 /*-----------------------------------------------------------------*/
345 /* userBpCB - call back function for user break points             */
346 /*-----------------------------------------------------------------*/
347 BP_CALLBACK(userBpCB)
348 {
349     Dprintf(D_break, ("break: userBpCB: BP_CALLBACK entry\n"));
350
351     if (srcMode == SRC_CMODE) {
352   fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n",
353     bpnum,
354     ctxt->func->sym->name,
355     ctxt->func->mod->c_name,
356     ctxt->cline+1);
357   if (ctxt->func->mod && ctxt->cline > 0)
358       fprintf(stdout,"%d\t%s",ctxt->cline+1,
359         ctxt->func->mod->cLines[ctxt->cline]->src);
360     } else {
361   fprintf(stdout,"Breakpoint %d, %s() at %s:%d\n",
362     bpnum,
363     ctxt->func->sym->name,
364     ctxt->func->mod->asm_name,
365     ctxt->asmline+1);
366   if (ctxt->func->mod && ctxt->asmline > 0)
367       fprintf(stdout,"%d\t%s",ctxt->asmline+1,
368         ctxt->func->mod->asmLines[ctxt->asmline]->src);
369     }
370
371     return 1;
372 }
373
374 /*-----------------------------------------------------------------*/
375 /* stepBpCB - call back function for step break points             */
376 /*-----------------------------------------------------------------*/
377 BP_CALLBACK(stepBpCB)
378 {
379     static function *lfunc = NULL;
380
381     Dprintf(D_break, ("break: stepBpCB: BP_CALLBACK entry\n"));
382
383     if (srcMode == SRC_CMODE) {
384   if ((lfunc && lfunc != ctxt->func) || !lfunc)
385       fprintf(stdout,"%s () at %s:%d\n",
386         ctxt->func->sym->name,
387         ctxt->func->mod->c_name,
388         ctxt->cline+1);
389
390   if (ctxt->func->mod && ctxt->cline > 0) {
391       fprintf(stdout,"%d\t%s",ctxt->cline+1 ,
392         ctxt->func->mod->cLines[ctxt->cline]->src);
393   }
394     } else {
395   if ((lfunc && lfunc != ctxt->func) || !lfunc)
396       fprintf(stdout,"%s () at %s:%d\n",
397         ctxt->func->sym->name,
398         ctxt->func->mod->asm_name,
399         ctxt->asmline);
400
401   if (ctxt->func->mod && ctxt->cline > 0) {
402       fprintf(stdout,"%d\t%s",ctxt->asmline ,
403         ctxt->func->mod->asmLines[ctxt->asmline]->src);
404   }
405     }
406     lfunc = ctxt->func;
407
408     deleteSTEPbp();
409     return 1;
410 }
411
412 /*-----------------------------------------------------------------*/
413 /* nextBpCB - call back function for next break points             */
414 /*-----------------------------------------------------------------*/
415 BP_CALLBACK(nextBpCB)
416 {
417     static function *lfunc = NULL;
418
419     Dprintf(D_break, ("break: nextBpCB: BP_CALLBACK entry\n"));
420
421     if (srcMode == SRC_CMODE) {
422   if ((lfunc && lfunc != ctxt->func) || !lfunc)
423       fprintf(stdout,"%s () at %s:%d\n",
424         ctxt->func->sym->name,
425         ctxt->func->mod->c_name,
426         ctxt->cline+1);
427
428   if (ctxt->func->mod && ctxt->cline > 0)
429       fprintf(stdout,"%d\t%s",ctxt->cline+1,
430         ctxt->func->mod->cLines[ctxt->cline]->src);
431     } else {
432   if ((lfunc && lfunc != ctxt->func) || !lfunc)
433       fprintf(stdout,"%s () at %s:%d\n",
434         ctxt->func->sym->name,
435         ctxt->func->mod->asm_name,
436         ctxt->asmline);
437
438   if (ctxt->func->mod && ctxt->asmline > 0)
439       fprintf(stdout,"%d\t%s",ctxt->asmline,
440         ctxt->func->mod->asmLines[ctxt->asmline]->src);
441
442     }
443     lfunc = ctxt->func;
444
445     deleteNEXTbp();
446     return 1;
447 }