Imported Upstream version 2.9.0
[debian/cc1111] / 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,%hd",&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 NULL;
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$<line>$<level>$<block>:<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 != INT_MAX )
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 }