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