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