Get debugger working
[fw/sdcc] / debugger / mcs51 / symtab.c
1 /*-------------------------------------------------------------------------
2   symtab.c - Header file for symbol table for sdcdb ( debugger )
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 "newalloc.h"
27
28 extern char *currModName ;
29 structdef *structWithName (char *);
30
31 /*------------------------------------------------------------------*/
32 /* getSize - returns size of a type chain in bits                   */
33 /*------------------------------------------------------------------*/
34 unsigned int   getSize ( link *p )
35 {
36     /* if nothing return 0 */
37     if ( ! p )
38   return 0 ;
39
40     if ( IS_SPEC(p) ) { /* if this is the specifier then */
41
42   switch (SPEC_NOUN(p)) { /* depending on the specifier type */
43   case V_INT:
44       return (IS_LONG(p) ? LONGSIZE : ( IS_SHORT(p) ? SHORTSIZE: INTSIZE)) ;
45   case V_FLOAT:
46       return FLOATSIZE ;
47   case V_CHAR:
48       return   CHARSIZE ;
49   case V_VOID:
50       return   0 ;
51   case V_STRUCT:
52       return   SPEC_STRUCT(p)->size ;
53   case V_LABEL:
54       return 0 ;
55   case V_SBIT:
56       return BITSIZE ;
57   case V_BIT:
58       return ((SPEC_BLEN(p) / 8) + (SPEC_BLEN(p) % 8 ? 1 : 0)) ;
59   default  :
60       return 0 ;
61   }
62     }
63
64     /* this is a specifier  */
65     switch (DCL_TYPE(p))  {
66     case FUNCTION:
67   return 2;
68     case ARRAY:
69   return DCL_ELEM(p) * getSize (p->next) ;
70     case IPOINTER:
71     case PPOINTER:
72     case POINTER:
73   return ( PTRSIZE ) ;
74     case FPOINTER:
75     case CPOINTER:
76   return ( FPTRSIZE );
77     case GPOINTER:
78   return ( GPTRSIZE );
79
80     default     :
81   return  0 ;
82     }
83 }
84
85
86 /*-----------------------------------------------------------------*/
87 /* parseFunc - creates a function record entry                     */
88 /*-----------------------------------------------------------------*/
89 void parseFunc (char *line)
90 {
91     function *func ;
92     char *rs;
93     int i;
94     func = Safe_calloc(1,sizeof(function));
95     func->sym = parseSymbol(line,&rs);
96     func->sym->isfunc = 1;
97     func->modName = currModName ;
98     while(*rs != ',') rs++;
99     rs++;
100     sscanf(rs,"%d,%d,%d",&i,
101      &(SPEC_INTN(func->sym->etype)),
102      &(SPEC_BANK(func->sym->etype)));
103     SPEC_INTRTN(func->sym->etype) = i;
104     addSet(&functions,func);
105 }
106
107 /*-----------------------------------------------------------------*/
108 /* parseTypeInfo - parse the type info of a symbol expects the type*/
109 /*                 info to be of the form                          */
110 /*                 ({<size>}<type info chain)                      */
111 /*-----------------------------------------------------------------*/
112 static char  *parseTypeInfo (symbol *sym, char *s)
113 {
114     char *bp;
115
116     s += 2; /* go past the ({ */
117     /* get the size */
118     sym->size = strtol (s,&bp,10);
119     /* bp now points to '}' ... go past it */
120     s = ++bp;
121     while (*s != ')') { /* till we reach the end */
122   link *type;
123   type = Safe_calloc(1,sizeof(link));
124   if (*s == ',') s++;
125
126   /* is a declarator */
127   if (*s == 'D') {
128       s++;
129       switch (*s) {
130       case 'F':
131     DCL_TYPE(type) = FUNCTION;
132     s++;
133     break;
134       case 'G':
135     DCL_TYPE(type) = GPOINTER;
136     s++;
137     break;
138       case 'C':
139     DCL_TYPE(type) = CPOINTER;
140     s++;
141     break;
142       case 'X':
143     DCL_TYPE(type) = FPOINTER;
144     s++;
145     break;
146       case 'D':
147     DCL_TYPE(type) = POINTER;
148     s++;
149     break;
150       case 'I':
151     DCL_TYPE(type) = IPOINTER;
152     s++;
153     break;
154       case 'P':
155     DCL_TYPE(type) = PPOINTER;
156     s++;
157     break;
158       case 'A':
159     s++;
160     DCL_TYPE(type) = ARRAY ;
161     DCL_ELEM(type) = strtol(s,&s,10);
162     break;
163       }
164   } else {
165       /* is a specifier */
166       type->class = SPECIFIER ;
167       s++;
168       switch (*s) {
169       case 'L':
170     SPEC_NOUN(type) = V_INT;
171     SPEC_LONG(type) = 1;
172     s++;
173     break;
174       case 'I':
175     SPEC_NOUN(type) = V_INT;
176     s++;
177     break;
178       case 'S':
179       case 'C':
180     SPEC_NOUN(type) = V_CHAR ;
181     s++;
182     break;
183       case 'V':
184     SPEC_NOUN(type) = V_VOID;
185     s++;
186     break;
187       case 'F':
188     SPEC_NOUN(type) = V_FLOAT;
189     s++;
190     break;
191       case 'T':
192     s++;
193     SPEC_NOUN(type) = V_STRUCT;
194     {
195         char *ss = strtok(strdup(s),",):");
196
197         SPEC_STRUCT(type) = structWithName(ss);
198         free(ss);
199     }
200     break;
201       case 'X':
202     s++;
203     SPEC_NOUN(type) = V_SBIT;
204     break;
205       case 'B':
206     SPEC_NOUN(type) = V_BIT;
207     s++;
208     SPEC_BSTR(type) = strtol(s,&s,10);
209     s++;
210     SPEC_BLEN(type) = strtol(s,&s,10);
211     break;
212       }
213       while (*s != ':') s++;
214       s++;
215       if (*s++ == 'S')
216     SPEC_USIGN(type) = 0;
217       else
218     SPEC_USIGN(type) = 1;
219
220   }
221
222   /* add the type to the symbol's type chain */
223   if (sym->type)
224       sym->etype = sym->etype->next = type;
225   else
226       sym->type = sym->etype = type;
227     }
228
229     return ++s;
230
231 }
232
233 /*-----------------------------------------------------------------*/
234 /* symFromRec - parse a symbol record and extract and create a sym */
235 /*              expects the input string to be of the form         */
236 /*              {G|F<filename>|L<functionName>}'$'<name>'$'<level> */
237 /*              '$'<block><type info>                              */
238 /*-----------------------------------------------------------------*/
239 symbol *parseSymbol (char *s, char **rs)
240 {
241     symbol *nsym ;
242     char *bp = s;
243
244     nsym = Safe_calloc(1,sizeof(symbol));
245
246     /* copy over the mangled name */
247     while (*bp != '(') bp++;
248      bp -= 1;
249     nsym->rname = alloccpy(s,bp - s);
250
251     /* if this is a Global Symbol */
252     nsym->scopetype = *s;
253     s++ ;
254     if (nsym->scopetype != 'G') {
255   /* get the function name it is local to */
256   bp = s;
257   while (*s != '$') s++;
258   nsym->sname = alloccpy(bp,s - bp);
259     }
260
261     /* next get the name */
262     bp = ++s;
263     while ( *s != '$' ) s++;
264     nsym->name = alloccpy(bp,s - bp);
265
266     s++;
267     /* get the level number */
268     nsym->level = strtol (s,&bp,10);
269     s = ++bp;
270     /* skip the '$' & get the block number */
271     nsym->block = strtol (s,&bp,10);
272
273     s = parseTypeInfo(nsym,bp);
274
275     /* get the address space after going past the comma */
276     s++;
277     nsym->addrspace =*s;
278
279     s+= 2;
280     nsym->isonstack = strtol(s,&s,10);
281     /* get the stack offset */
282     s++;
283     nsym->offset = strtol(s,&s,10);
284     *rs = s;
285
286     addSet(&symbols,nsym);
287
288     return nsym;
289 }
290
291
292 /*-----------------------------------------------------------------*/
293 /* parseStruct - parses a structure record expected in format      */
294 /*         {F<filename>}$<tag>[()()()...]                          */
295 /*-----------------------------------------------------------------*/
296 structdef *parseStruct (char *s)
297 {
298     structdef *nsdef ;
299     char *bp;
300     char *name;
301     symbol *fields = NULL;
302
303     while (*s != '$') s++;
304
305     bp =++s;
306     while (*s != '[') s++ ;
307     name = alloccpy(bp,s - bp);
308     nsdef = structWithName(name);
309     nsdef->fields = NULL;
310     s++;
311     while (*s && *s != ']') {
312   int offset ;
313   symbol *sym ;
314   while (!isdigit(*s)) s++;
315   offset = strtol(s,&s,10);
316   while (*s != ':') s++;
317   s++;
318   sym = parseSymbol(s,&s);
319   sym->offset = offset ;
320   s += 3;
321   if (!fields)
322       fields = nsdef->fields = sym;
323   else
324       fields = fields->next = sym;
325
326     }
327
328     return nsdef;
329 }
330
331 /*-----------------------------------------------------------------*/
332 /* parseModule - creates a module with a given name                */
333 /*-----------------------------------------------------------------*/
334 module *parseModule (char *s, bool createName )
335 {
336     module *nmod ;
337     char buffer[512];
338
339     nmod = Safe_calloc(1,sizeof(module));
340
341     addSet (&modules,nmod);
342
343
344     /* create copy file name */
345     nmod->name = s;
346
347     if (createName) {
348   sprintf(buffer,"%s.c",s);
349
350   nmod->c_name = Safe_malloc(strlen(buffer)+1);
351   strcpy(nmod->c_name,buffer);
352
353   sprintf(buffer,"%s.asm",s);
354   nmod->asm_name = Safe_malloc(strlen(buffer)+1);
355   strcpy(nmod->asm_name,buffer);
356     }
357
358     return nmod;
359 }
360
361 /*-----------------------------------------------------------------*/
362 /* moduleWithName - finds and returns a module with a given name   */
363 /*-----------------------------------------------------------------*/
364 DEFSETFUNC(moduleWithName)
365 {
366     module *mod = item;
367     V_ARG(char *,s);
368     V_ARG(module **,rmod);
369
370     if (*rmod)
371   return 0;
372
373     if (strcmp(mod->name,s) == 0) {
374   *rmod = mod ;
375   return 1;
376     }
377
378     return 0;
379 }
380
381 /*-----------------------------------------------------------------*/
382 /* moduleWithCName - finds and returns a module with a given c_name*/
383 /*-----------------------------------------------------------------*/
384 DEFSETFUNC(moduleWithCName)
385 {
386     module *mod = item;
387     V_ARG(char *,s);
388     V_ARG(module **,rmod);
389
390     if (*rmod)
391   return 0;
392     if (strcmp(mod->c_name,s) == 0) {
393   *rmod = mod;
394   return 1;
395     }
396
397     return 0;
398 }
399
400 /*-----------------------------------------------------------------*/
401 /* moduleWithAsmName - finds & returns a module with given asm_name*/
402 /*-----------------------------------------------------------------*/
403 DEFSETFUNC(moduleWithAsmName)
404 {
405     module *mod = item;
406     V_ARG(char *,s);
407     V_ARG(module **,rmod);
408
409     if (*rmod)
410   return 0;
411     if (strcmp(mod->asm_name,s) == 0) {
412   *rmod = mod;
413   return 1;
414     }
415
416     return 0;
417 }
418
419
420 /*-----------------------------------------------------------------*/
421 /* structWithName - returns a structure with a given name          */
422 /*-----------------------------------------------------------------*/
423 structdef *structWithName (char *s)
424 {
425     int i;
426     structdef *nsdef ;
427
428     /* go thru the struct table looking for a match */
429     for ( i = 0 ; i < nStructs ; i++ ) {
430
431   if (strcmp(currModName,structs[i]->sname) == 0 &&
432       strcmp(s,structs[i]->tag) == 0)
433       return structs[i];
434     }
435
436     nsdef = Safe_calloc(1,sizeof(structdef));
437     nsdef->tag = alloccpy(s,strlen(s));
438     nsdef->sname = currModName ;
439
440     nStructs++;
441     structs = (struct structdef **)resize((void **)structs,nStructs);
442     structs[nStructs-1] = nsdef;
443     return nsdef;
444 }
445
446 /*-----------------------------------------------------------------*/
447 /* symWithRName - look for symbol with mangled name = parm         */
448 /*-----------------------------------------------------------------*/
449 DEFSETFUNC(symWithRName)
450 {
451     symbol *sym = item;
452     V_ARG(char *,s);
453     V_ARG(symbol **,rsym);
454
455     if (*rsym)
456   return 0;
457
458     if (strcmp(sym->rname,s) == 0) {
459   *rsym = sym;
460   return 1;
461     }
462
463     return 0;
464 }
465
466 /*-----------------------------------------------------------------*/
467 /* funcWithRName - look for function with name                     */
468 /*-----------------------------------------------------------------*/
469 DEFSETFUNC(funcWithRName)
470 {
471     function *func = item;
472     V_ARG(char *,s);
473     V_ARG(function **,rfunc);
474
475     if (*rfunc)
476   return 0;
477
478     if (strcmp(func->sym->rname,s) == 0) {
479   *rfunc = func;
480   return 1;
481     }
482
483     return 0;
484 }
485
486 /*-----------------------------------------------------------------*/
487 /* symLocal - local symbol respecting blocks & levels              */
488 /*-----------------------------------------------------------------*/
489 DEFSETFUNC(symLocal)
490 {
491     symbol *sym = item;
492     V_ARG(char *,name);
493     V_ARG(char *,sname);
494     V_ARG(int   ,block);
495     V_ARG(int   ,level);
496     V_ARG(symbol **,rsym);
497
498     if (strcmp(name,sym->name) == 0 && /* name matches */
499   sym->scopetype != 'G'       && /* local scope  */
500   (sym->sname && strcmp(sym->sname,sname) == 0) && /* scope == specified scope */
501   sym->block <= block         && /* block & level kindo matches */
502   sym->level <= level) {
503
504   /* if a symbol was previously found then
505      sure that ones block & level are less
506      then this one */
507   if (*rsym && (*rsym)->block >= block &&
508       (*rsym)->level >= level)
509       return 0;
510
511   *rsym = sym;
512   return 1;
513     }
514
515     return 0;
516 }
517
518 /*-----------------------------------------------------------------*/
519 /* symGlobal - return global symbol of name                        */
520 /*-----------------------------------------------------------------*/
521 DEFSETFUNC(symGlobal)
522 {
523     symbol *sym = item;
524     V_ARG(char *,name);
525     V_ARG(symbol **,rsym);
526
527     if (*rsym)
528   return 0;
529
530     /* simple :: global & name matches */
531     if (sym->scopetype == 'G' &&
532   strcmp(sym->name,name) == 0) {
533   *rsym = sym;
534   return 1;
535     }
536
537     return 0;
538 }
539
540 /*-----------------------------------------------------------------*/
541 /* symLookup - determine symbol from name & context                */
542 /*-----------------------------------------------------------------*/
543 symbol *symLookup (char *name, context *ctxt)
544 {
545     symbol *sym = NULL ;
546
547     /* first try & find a local variable for the
548        given name */
549     if ( applyToSet(symbols,symLocal,
550         name,
551         ctxt->func->sym->name,
552         ctxt->block,
553         ctxt->level,
554         &sym))
555   return sym;
556
557     sym = NULL;
558     /* then try local to this module */
559     if (applyToSet(symbols,symLocal,
560        name,
561        ctxt->func->mod->name,
562        0,0,&sym))
563   return sym;
564     sym = NULL;
565     /* no:: try global */
566     if ( applyToSet(symbols,symGlobal,name,&sym))
567   return sym;
568
569     /* cannot find return null */
570     return NULL;
571 }
572
573 /*-----------------------------------------------------------------*/
574 /* lnkFuncEnd - link record for end of function                    */
575 /*-----------------------------------------------------------------*/
576 static void lnkFuncEnd (char *s)
577 {
578     char sname[128], *bp = sname;
579     function *func;
580
581     /* copy till we get to a ':' */
582     while ( *s != ':' )
583   *bp++ = *s++;
584     bp -= 1;
585     *bp = '\0';
586
587     func = NULL;
588     if (!applyToSet(functions,funcWithRName,sname,&func))
589   return ;
590
591     s++;
592     sscanf(s,"%x",&func->sym->eaddr);
593
594     Dprintf(D_symtab, ("%s(eaddr%x)\n",func->sym->name,func->sym->eaddr));
595 }
596
597 /*-----------------------------------------------------------------*/
598 /* lnkSymRec - record for a symbol                                 */
599 /*-----------------------------------------------------------------*/
600 static void lnkSymRec (char *s)
601 {
602     char sname[128], *bp = sname;
603     symbol *sym;
604
605     /* copy till we get to a ':' */
606     while ( *s != ':')
607   *bp++ = *s++;
608     bp -= 1;
609     *bp = '\0';
610
611
612     sym = NULL;
613     if (!applyToSet(symbols,symWithRName,sname,&sym))
614   return ;
615
616     s++;
617     sscanf(s,"%x",&sym->addr);
618
619     Dprintf(D_symtab, ("%s(%x)\n",sym->name,sym->addr));
620 }
621
622 /*-----------------------------------------------------------------*/
623 /* lnkAsmSrc - process linker record for asm sources               */
624 /*-----------------------------------------------------------------*/
625 static void lnkAsmSrc (char *s)
626 {
627     char mname[128], *bp = mname;
628     int line ;
629     unsigned addr;
630     module *mod = NULL;
631
632     /* input will be of format
633        filename$<line>:<address> */
634     while (*s != '$' && *s != '.')
635   *bp++ = *s++;
636     *bp = '\0';
637     /* skip to line stuff */
638     while (*s != '$') s++;
639
640     if (!applyToSet(modules,moduleWithName,mname,&mod))
641   return ;
642
643     if (sscanf(s,"$%d:%x",&line,&addr) != 2)
644   return ;
645
646     line--;
647     if (line < mod->nasmLines) {
648   mod->asmLines[line]->addr = addr;
649   Dprintf(D_symtab, ("%s(%d:%x) %s",mod->asm_name,line,addr,mod->asmLines[line]->src));
650     }
651 }
652
653 /*-----------------------------------------------------------------*/
654 /* lnkCSrc - process linker output for c source                    */
655 /*-----------------------------------------------------------------*/
656 static void lnkCSrc (char *s)
657 {
658     char mname[128], *bp = mname;
659     int block,level,line;
660     unsigned int addr;
661     module *mod ;
662
663     /* input will be of format
664        filename.ext$<level>$<block>$<line>:<address> */
665     /* get the module name */
666     while (*s != '$' )
667   *bp++ = *s++;
668     *bp = '\0';
669     /* skip the extension */
670     while (*s != '$') s++;
671
672     if (sscanf(s,"$%d$%d$%d:%x",
673          &line,&level,&block,&addr) != 4)
674   return ;
675
676     mod = NULL;
677     if (!applyToSet(modules,moduleWithCName,mname,&mod)) {
678   mod = parseModule(mname,FALSE);
679   mod->c_name = alloccpy(mname,strlen(mname));
680   mod->cfullname=searchDirsFname(mod->c_name);
681   mod->cLines = loadFile(mod->c_name,&mod->ncLines);
682     }
683
684     line--;
685     if (line < mod->ncLines && line > 0) {
686   mod->cLines[line]->addr = addr;
687   mod->cLines[line]->block = block;
688   mod->cLines[line]->level = level;
689   Dprintf(D_symtab, ("%s(%d:%x) %s",mod->c_name,
690          line+1,addr,mod->cLines[line]->src));
691     }
692     return;
693
694 }
695
696 /*-----------------------------------------------------------------*/
697 /* parseLnkRec - parses a linker generated record                  */
698 /*-----------------------------------------------------------------*/
699 void parseLnkRec (char *s)
700 {
701     /* link records can be several types
702        dpeneding on the type do */
703
704     switch (*s) {
705
706   /* c source line address */
707     case 'C':
708   lnkCSrc(s+2);
709   break;
710   /* assembler source address */
711     case 'A':
712   lnkAsmSrc(s+2);
713   break;
714
715     case 'X':
716   lnkFuncEnd(s+1);
717   break;
718
719     default :
720   lnkSymRec(s);
721   break;
722     }
723 }