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