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