sdcdb updates,ddd
[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
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     func = Safe_calloc(1,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   type = Safe_calloc(1,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     nsym = Safe_calloc(1,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
284     if ( nsym->addrspace == 'R' )
285     {
286         /* get registeroffset */
287         while (*s && *s != '[') s++ ;
288         s++ ;
289         if ( *s == 'r' )
290         {
291             nsym->addr = strtol(s+1,&s,10);
292         }
293         while (*s && *s != ']') s++ ;
294     }
295
296     *rs = s;
297     addSet(&symbols,nsym);
298
299     return nsym;
300 }
301
302
303 /*-----------------------------------------------------------------*/
304 /* parseStruct - parses a structure record expected in format      */
305 /*         {F<filename>}$<tag>[()()()...]                          */
306 /*-----------------------------------------------------------------*/
307 structdef *parseStruct (char *s)
308 {
309     structdef *nsdef ;
310     char *bp;
311     char *name;
312     symbol *fields = NULL;
313
314     while (*s != '$') s++;
315
316     bp =++s;
317     while (*s != '[') s++ ;
318     name = alloccpy(bp,s - bp);
319     nsdef = structWithName(name);
320     nsdef->fields = NULL;
321     s++;
322     while (*s && *s != ']') {
323   int offset ;
324   symbol *sym ;
325   while (!isdigit(*s)) s++;
326   offset = strtol(s,&s,10);
327   while (*s != ':') s++;
328   s++;
329   sym = parseSymbol(s,&s);
330   sym->offset = offset ;
331   s += 3;
332   if (!fields)
333       fields = nsdef->fields = sym;
334   else
335       fields = fields->next = sym;
336
337     }
338
339     return nsdef;
340 }
341
342 /*-----------------------------------------------------------------*/
343 /* parseModule - creates a module with a given name                */
344 /*-----------------------------------------------------------------*/
345 module *parseModule (char *s, bool createName )
346 {
347     module *nmod ;
348     char buffer[512];
349
350     nmod = Safe_calloc(1,sizeof(module));
351
352     addSet (&modules,nmod);
353
354
355     /* create copy file name */
356     nmod->name = s;
357
358     if (createName) {
359   sprintf(buffer,"%s.c",s);
360
361   nmod->c_name = Safe_malloc(strlen(buffer)+1);
362   strcpy(nmod->c_name,buffer);
363
364   sprintf(buffer,"%s.asm",s);
365   nmod->asm_name = Safe_malloc(strlen(buffer)+1);
366   strcpy(nmod->asm_name,buffer);
367     }
368
369     return nmod;
370 }
371
372 /*-----------------------------------------------------------------*/
373 /* moduleWithName - finds and returns a module with a given name   */
374 /*-----------------------------------------------------------------*/
375 DEFSETFUNC(moduleWithName)
376 {
377     module *mod = item;
378     V_ARG(char *,s);
379     V_ARG(module **,rmod);
380
381     if (*rmod)
382   return 0;
383
384     if (strcmp(mod->name,s) == 0) {
385   *rmod = mod ;
386   return 1;
387     }
388
389     return 0;
390 }
391
392 /*-----------------------------------------------------------------*/
393 /* moduleWithCName - finds and returns a module with a given c_name*/
394 /*-----------------------------------------------------------------*/
395 DEFSETFUNC(moduleWithCName)
396 {
397     module *mod = item;
398     V_ARG(char *,s);
399     V_ARG(module **,rmod);
400
401     if (*rmod)
402   return 0;
403     if (strcmp(mod->c_name,s) == 0) {
404   *rmod = mod;
405   return 1;
406     }
407
408     return 0;
409 }
410
411 /*-----------------------------------------------------------------*/
412 /* moduleWithAsmName - finds & returns a module with given asm_name*/
413 /*-----------------------------------------------------------------*/
414 DEFSETFUNC(moduleWithAsmName)
415 {
416     module *mod = item;
417     V_ARG(char *,s);
418     V_ARG(module **,rmod);
419
420     if (*rmod)
421   return 0;
422     if (strcmp(mod->asm_name,s) == 0) {
423   *rmod = mod;
424   return 1;
425     }
426
427     return 0;
428 }
429
430
431 /*-----------------------------------------------------------------*/
432 /* structWithName - returns a structure with a given name          */
433 /*-----------------------------------------------------------------*/
434 structdef *structWithName (char *s)
435 {
436     int i;
437     structdef *nsdef ;
438
439     /* go thru the struct table looking for a match */
440     for ( i = 0 ; i < nStructs ; i++ ) {
441
442   if (strcmp(currModName,structs[i]->sname) == 0 &&
443       strcmp(s,structs[i]->tag) == 0)
444       return structs[i];
445     }
446
447     nsdef = Safe_calloc(1,sizeof(structdef));
448     nsdef->tag = alloccpy(s,strlen(s));
449     nsdef->sname = currModName ;
450
451     nStructs++;
452     structs = (struct structdef **)resize((void **)structs,nStructs);
453     structs[nStructs-1] = nsdef;
454     return nsdef;
455 }
456
457 /*-----------------------------------------------------------------*/
458 /* symWithRName - look for symbol with mangled name = parm         */
459 /*-----------------------------------------------------------------*/
460 DEFSETFUNC(symWithRName)
461 {
462     symbol *sym = item;
463     V_ARG(char *,s);
464     V_ARG(symbol **,rsym);
465
466     if (*rsym)
467   return 0;
468
469     if (strcmp(sym->rname,s) == 0) {
470   *rsym = sym;
471   return 1;
472     }
473
474     return 0;
475 }
476
477 /*-----------------------------------------------------------------*/
478 /* funcWithRName - look for function with name                     */
479 /*-----------------------------------------------------------------*/
480 DEFSETFUNC(funcWithRName)
481 {
482     function *func = item;
483     V_ARG(char *,s);
484     V_ARG(function **,rfunc);
485
486     if (*rfunc)
487   return 0;
488
489     if (strcmp(func->sym->rname,s) == 0) {
490   *rfunc = func;
491   return 1;
492     }
493
494     return 0;
495 }
496
497 /*-----------------------------------------------------------------*/
498 /* symLocal - local symbol respecting blocks & levels              */
499 /*-----------------------------------------------------------------*/
500 DEFSETFUNC(symLocal)
501 {
502     symbol *sym = item;
503     V_ARG(char *,name);
504     V_ARG(char *,sname);
505     V_ARG(int   ,block);
506     V_ARG(int   ,level);
507     V_ARG(symbol **,rsym);
508
509     if (strcmp(name,sym->name) == 0 && /* name matches */
510   sym->scopetype != 'G'       && /* local scope  */
511   (sym->sname && strcmp(sym->sname,sname) == 0) && /* scope == specified scope */
512   sym->block <= block         && /* block & level kindo matches */
513   sym->level <= level) {
514
515   /* if a symbol was previously found then
516      sure that ones block & level are less
517      then this one */
518   if (*rsym && (*rsym)->block >= block &&
519       (*rsym)->level >= level)
520       return 0;
521
522   *rsym = sym;
523   return 1;
524     }
525
526     return 0;
527 }
528
529 /*-----------------------------------------------------------------*/
530 /* symGlobal - return global symbol of name                        */
531 /*-----------------------------------------------------------------*/
532 DEFSETFUNC(symGlobal)
533 {
534     symbol *sym = item;
535     V_ARG(char *,name);
536     V_ARG(symbol **,rsym);
537
538     if (*rsym)
539   return 0;
540
541     /* simple :: global & name matches */
542     if (sym->scopetype == 'G' &&
543   strcmp(sym->name,name) == 0) {
544   *rsym = sym;
545   return 1;
546     }
547
548     return 0;
549 }
550
551 /*-----------------------------------------------------------------*/
552 /* symLookup - determine symbol from name & context                */
553 /*-----------------------------------------------------------------*/
554 symbol *symLookup (char *name, context *ctxt)
555 {
556     symbol *sym = NULL ;
557
558     if ((ctxt) && (ctxt->func) &&
559         (ctxt->func->sym) && (ctxt->func->sym->name)) {
560       /* first try & find a local variable for the given name */
561       if ( applyToSet(symbols,symLocal,
562         name,
563         ctxt->func->sym->name,
564         ctxt->block,
565         ctxt->level,
566         &sym))
567          return sym;
568       sym = NULL;
569     }
570
571     if ((ctxt) && (ctxt->func) &&
572         (ctxt->func->mod) && (ctxt->func->mod->name)) {
573       /* then try local to this module */
574       if (applyToSet(symbols,symLocal,
575           name,
576           ctxt->func->mod->name,
577           0,0,&sym))
578              return sym;
579       sym = NULL;
580     }
581
582     /* no:: try global */
583     if ( applyToSet(symbols,symGlobal,name,&sym))
584       return sym;
585
586     /* cannot find return null */
587     return NULL;
588 }
589
590 /*-----------------------------------------------------------------*/
591 /* lnkFuncEnd - link record for end of function                    */
592 /*-----------------------------------------------------------------*/
593 static void lnkFuncEnd (char *s)
594 {
595     char sname[128], *bp = sname;
596     function *func;
597
598     /* copy till we get to a ':' */
599     while ( *s != ':' )
600   *bp++ = *s++;
601     bp -= 1;
602     *bp = '\0';
603
604     func = NULL;
605     if (!applyToSet(functions,funcWithRName,sname,&func))
606   return ;
607
608     s++;
609     sscanf(s,"%x",&func->sym->eaddr);
610
611     Dprintf(D_symtab, ("%s(eaddr%x)\n",func->sym->name,func->sym->eaddr));
612 }
613
614 /*-----------------------------------------------------------------*/
615 /* lnkSymRec - record for a symbol                                 */
616 /*-----------------------------------------------------------------*/
617 static void lnkSymRec (char *s)
618 {
619     char sname[128], *bp = sname;
620     symbol *sym;
621
622     /* copy till we get to a ':' */
623     while ( *s != ':')
624   *bp++ = *s++;
625     bp -= 1;
626     *bp = '\0';
627
628
629     sym = NULL;
630     if (!applyToSet(symbols,symWithRName,sname,&sym))
631   return ;
632
633     s++;
634     sscanf(s,"%x",&sym->addr);
635
636     Dprintf(D_symtab, ("%s(%x)\n",sym->name,sym->addr));
637 }
638
639 /*-----------------------------------------------------------------*/
640 /* lnkAsmSrc - process linker record for asm sources               */
641 /*-----------------------------------------------------------------*/
642 static void lnkAsmSrc (char *s)
643 {
644     char mname[128], *bp = mname;
645     int line ;
646     unsigned addr;
647     module *mod = NULL;
648
649     /* input will be of format
650        filename$<line>:<address> */
651     while (*s != '$' && *s != '.')
652   *bp++ = *s++;
653     *bp = '\0';
654     /* skip to line stuff */
655     while (*s != '$') s++;
656
657     if (!applyToSet(modules,moduleWithName,mname,&mod))
658   return ;
659
660     if (sscanf(s,"$%d:%x",&line,&addr) != 2)
661   return ;
662
663     line--;
664     if (line < mod->nasmLines) {
665   mod->asmLines[line]->addr = addr;
666   Dprintf(D_symtab, ("%s(%d:%x) %s",mod->asm_name,line,addr,mod->asmLines[line]->src));
667     }
668 }
669
670 /*-----------------------------------------------------------------*/
671 /* lnkCSrc - process linker output for c source                    */
672 /*-----------------------------------------------------------------*/
673 static void lnkCSrc (char *s)
674 {
675     char mname[128], *bp = mname;
676     int block,level,line;
677     unsigned int addr;
678     module *mod ;
679
680     /* input will be of format
681        filename.ext$<level>$<block>$<line>:<address> */
682     /* get the module name */
683     while (*s != '$' )
684   *bp++ = *s++;
685     *bp = '\0';
686     /* skip the extension */
687     while (*s != '$') s++;
688
689     if (sscanf(s,"$%d$%d$%d:%x",
690          &line,&level,&block,&addr) != 4)
691   return ;
692
693     mod = NULL;
694     if (!applyToSet(modules,moduleWithCName,mname,&mod)) {
695   mod = parseModule(mname,FALSE);
696   mod->c_name = alloccpy(mname,strlen(mname));
697   mod->cfullname=searchDirsFname(mod->c_name);
698   mod->cLines = loadFile(mod->c_name,&mod->ncLines);
699     }
700
701     line--;
702     if (line < mod->ncLines && line > 0) {
703   mod->cLines[line]->addr = addr;
704   mod->cLines[line]->block = block;
705   mod->cLines[line]->level = level;
706   Dprintf(D_symtab, ("%s(%d:%x) %s",mod->c_name,
707          line+1,addr,mod->cLines[line]->src));
708     }
709     return;
710
711 }
712
713 /*-----------------------------------------------------------------*/
714 /* parseLnkRec - parses a linker generated record                  */
715 /*-----------------------------------------------------------------*/
716 void parseLnkRec (char *s)
717 {
718     /* link records can be several types
719        dpeneding on the type do */
720
721     switch (*s) {
722
723   /* c source line address */
724     case 'C':
725   lnkCSrc(s+2);
726   break;
727   /* assembler source address */
728     case 'A':
729   lnkAsmSrc(s+2);
730   break;
731
732     case 'X':
733   lnkFuncEnd(s+1);
734   break;
735
736     default :
737   lnkSymRec(s);
738   break;
739     }
740 }