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