fix some things
[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     if ((ctxt) && (ctxt->func) &&
548         (ctxt->func->sym) && (ctxt->func->sym->name)) {
549       /* first try & find a local variable for the given name */
550       if ( applyToSet(symbols,symLocal,
551         name,
552         ctxt->func->sym->name,
553         ctxt->block,
554         ctxt->level,
555         &sym))
556          return sym;
557       sym = NULL;
558     }
559
560     if ((ctxt) && (ctxt->func) &&
561         (ctxt->func->mod) && (ctxt->func->mod->name)) {
562       /* then try local to this module */
563       if (applyToSet(symbols,symLocal,
564           name,
565           ctxt->func->mod->name,
566           0,0,&sym))
567              return sym;
568       sym = NULL;
569     }
570
571     /* no:: try global */
572     if ( applyToSet(symbols,symGlobal,name,&sym))
573       return sym;
574
575     /* cannot find return null */
576     return NULL;
577 }
578
579 /*-----------------------------------------------------------------*/
580 /* lnkFuncEnd - link record for end of function                    */
581 /*-----------------------------------------------------------------*/
582 static void lnkFuncEnd (char *s)
583 {
584     char sname[128], *bp = sname;
585     function *func;
586
587     /* copy till we get to a ':' */
588     while ( *s != ':' )
589   *bp++ = *s++;
590     bp -= 1;
591     *bp = '\0';
592
593     func = NULL;
594     if (!applyToSet(functions,funcWithRName,sname,&func))
595   return ;
596
597     s++;
598     sscanf(s,"%x",&func->sym->eaddr);
599
600     Dprintf(D_symtab, ("%s(eaddr%x)\n",func->sym->name,func->sym->eaddr));
601 }
602
603 /*-----------------------------------------------------------------*/
604 /* lnkSymRec - record for a symbol                                 */
605 /*-----------------------------------------------------------------*/
606 static void lnkSymRec (char *s)
607 {
608     char sname[128], *bp = sname;
609     symbol *sym;
610
611     /* copy till we get to a ':' */
612     while ( *s != ':')
613   *bp++ = *s++;
614     bp -= 1;
615     *bp = '\0';
616
617
618     sym = NULL;
619     if (!applyToSet(symbols,symWithRName,sname,&sym))
620   return ;
621
622     s++;
623     sscanf(s,"%x",&sym->addr);
624
625     Dprintf(D_symtab, ("%s(%x)\n",sym->name,sym->addr));
626 }
627
628 /*-----------------------------------------------------------------*/
629 /* lnkAsmSrc - process linker record for asm sources               */
630 /*-----------------------------------------------------------------*/
631 static void lnkAsmSrc (char *s)
632 {
633     char mname[128], *bp = mname;
634     int line ;
635     unsigned addr;
636     module *mod = NULL;
637
638     /* input will be of format
639        filename$<line>:<address> */
640     while (*s != '$' && *s != '.')
641   *bp++ = *s++;
642     *bp = '\0';
643     /* skip to line stuff */
644     while (*s != '$') s++;
645
646     if (!applyToSet(modules,moduleWithName,mname,&mod))
647   return ;
648
649     if (sscanf(s,"$%d:%x",&line,&addr) != 2)
650   return ;
651
652     line--;
653     if (line < mod->nasmLines) {
654   mod->asmLines[line]->addr = addr;
655   Dprintf(D_symtab, ("%s(%d:%x) %s",mod->asm_name,line,addr,mod->asmLines[line]->src));
656     }
657 }
658
659 /*-----------------------------------------------------------------*/
660 /* lnkCSrc - process linker output for c source                    */
661 /*-----------------------------------------------------------------*/
662 static void lnkCSrc (char *s)
663 {
664     char mname[128], *bp = mname;
665     int block,level,line;
666     unsigned int addr;
667     module *mod ;
668
669     /* input will be of format
670        filename.ext$<level>$<block>$<line>:<address> */
671     /* get the module name */
672     while (*s != '$' )
673   *bp++ = *s++;
674     *bp = '\0';
675     /* skip the extension */
676     while (*s != '$') s++;
677
678     if (sscanf(s,"$%d$%d$%d:%x",
679          &line,&level,&block,&addr) != 4)
680   return ;
681
682     mod = NULL;
683     if (!applyToSet(modules,moduleWithCName,mname,&mod)) {
684   mod = parseModule(mname,FALSE);
685   mod->c_name = alloccpy(mname,strlen(mname));
686   mod->cfullname=searchDirsFname(mod->c_name);
687   mod->cLines = loadFile(mod->c_name,&mod->ncLines);
688     }
689
690     line--;
691     if (line < mod->ncLines && line > 0) {
692   mod->cLines[line]->addr = addr;
693   mod->cLines[line]->block = block;
694   mod->cLines[line]->level = level;
695   Dprintf(D_symtab, ("%s(%d:%x) %s",mod->c_name,
696          line+1,addr,mod->cLines[line]->src));
697     }
698     return;
699
700 }
701
702 /*-----------------------------------------------------------------*/
703 /* parseLnkRec - parses a linker generated record                  */
704 /*-----------------------------------------------------------------*/
705 void parseLnkRec (char *s)
706 {
707     /* link records can be several types
708        dpeneding on the type do */
709
710     switch (*s) {
711
712   /* c source line address */
713     case 'C':
714   lnkCSrc(s+2);
715   break;
716   /* assembler source address */
717     case 'A':
718   lnkAsmSrc(s+2);
719   break;
720
721     case 'X':
722   lnkFuncEnd(s+1);
723   break;
724
725     default :
726   lnkSymRec(s);
727   break;
728     }
729 }