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