diff options
| author | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
|---|---|---|
| committer | Xavier ASUS <xavi92psx@gmail.com> | 2019-10-18 00:31:54 +0200 |
| commit | 268a53de823a6750d6256ee1fb1e7707b4b45740 (patch) | |
| tree | 42c1799a9a82b2f7d9790ee9fe181d72a7274751 /debugger/mcs51/symtab.c | |
| download | sdcc-gas-268a53de823a6750d6256ee1fb1e7707b4b45740.tar.gz | |
sdcc-3.9.0 fork implementing GNU assembler syntax
This fork aims to provide better support for stm8-binutils
Diffstat (limited to 'debugger/mcs51/symtab.c')
| -rw-r--r-- | debugger/mcs51/symtab.c | 842 |
1 files changed, 842 insertions, 0 deletions
diff --git a/debugger/mcs51/symtab.c b/debugger/mcs51/symtab.c new file mode 100644 index 0000000..fd4e586 --- /dev/null +++ b/debugger/mcs51/symtab.c @@ -0,0 +1,842 @@ +/*------------------------------------------------------------------------- + symtab.c - Header file for symbol table for sdcdb ( debugger ) + Written By - Sandeep Dutta . sandeep.dutta@usa.net (1999) + + This program is free software; you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by the + Free Software Foundation; either version 2, or (at your option) any + later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + + In other words, you are welcome to use, share and improve this program. + You are forbidden to forbid anyone else to use, share and improve + what you give them. Help stamp out software-hoarding! +-------------------------------------------------------------------------*/ + +#include "sdcdb.h" +#include "symtab.h" +#include "newalloc.h" + +structdef *structWithName (char *); +DEFSETFUNC(symWithRName); + +/*-----------------------------------------------------------------*/ +/* gc_strcat - allocate and return concatenated strings */ +/*-----------------------------------------------------------------*/ +char *gc_strcat(const char *s1, const char *s2, const char *s3) +{ + char *p = Safe_malloc(strlen(s1) + strlen(s2) + strlen(s3) + 1); + strcat(strcat(strcpy(p, s1), s2), s3); + return p; +} + +/*------------------------------------------------------------------*/ +/* getSize - returns size of a type chain in bits */ +/*------------------------------------------------------------------*/ +unsigned int getSize ( st_link *p ) +{ + /* if nothing return 0 */ + if ( ! p ) + return 0; + + if ( IS_SPEC(p) ) /* if this is the specifier then */ + { + switch (SPEC_NOUN(p)) /* depending on the specifier type */ + { + case V_INT: + return (IS_LONG(p) ? LONGSIZE : ( IS_SHORT(p) ? SHORTSIZE: INTSIZE)); + case V_FLOAT: + return FLOATSIZE; + case V_CHAR: + return CHARSIZE; + case V_VOID: + return 0; + case V_STRUCT: + return SPEC_STRUCT(p)->size; + case V_LABEL: + return 0 ; + case V_SBIT: + return BITSIZE; + case V_BIT: + return ((SPEC_BLEN(p) / 8) + (SPEC_BLEN(p) % 8 ? 1 : 0)); + default: + return 0; + } + } + + /* this is a specifier */ + switch (DCL_TYPE(p)) + { + case FUNCTION: + return 2; + case ARRAY: + return DCL_ELEM(p) * getSize (p->next); + case IPOINTER: + case PPOINTER: + case POINTER: + return ( PTRSIZE ); + case FPOINTER: + case CPOINTER: + return ( FPTRSIZE ); + case GPOINTER: + return ( GPTRSIZE ); + + default: + return 0; + } +} + +/*-----------------------------------------------------------------*/ +/* parseFunc - creates a function record entry */ +/*-----------------------------------------------------------------*/ +void parseFunc (char *line) +{ + function *func; + char *rs = line; + int i; + + while (*rs && *rs != '(') + rs++; + *--rs = '\0'; + + func = Safe_calloc(1, sizeof(function)); + func->sym = NULL; + applyToSetFTrue(symbols, symWithRName, line, &func->sym); + *rs++ = '0'; + if (! func->sym) + func->sym = parseSymbol(line, &rs, 1); + func->sym->isfunc = 1; + func->modName = currModName; + while(*rs && *rs != ',') + rs++; + rs++; + sscanf(rs, "%d,%d,%hd", &i, + &(SPEC_INTN(func->sym->etype)), + &(SPEC_BANK(func->sym->etype))); + SPEC_INTRTN(func->sym->etype) = i; + addSet(&functions, func); +} + +/*-----------------------------------------------------------------*/ +/* parseTypeInfo - parse the type info of a symbol expects the type*/ +/* info to be of the form */ +/* ({<size>}<type info chain) */ +/*-----------------------------------------------------------------*/ +static char *parseTypeInfo (symbol *sym, char *s) +{ + char *bp; + + s += 2; /* go past the ({ */ + /* get the size */ + sym->size = (short)strtol (s, &bp, 10); + /* bp now points to '}' ... go past it */ + s = ++bp; + while (*s != ')') /* till we reach the end */ + { + st_link *type; + type = Safe_calloc(1, sizeof(st_link)); + if (*s == ',') + s++; + + /* is a declarator */ + if (*s == 'D') + { + s++; + switch (*s) + { + case 'F': + DCL_TYPE(type) = FUNCTION; + s++; + break; + case 'G': + DCL_TYPE(type) = GPOINTER; + s++; + break; + case 'C': + DCL_TYPE(type) = CPOINTER; + s++; + break; + case 'X': + DCL_TYPE(type) = FPOINTER; + s++; + break; + case 'D': + DCL_TYPE(type) = POINTER; + s++; + break; + case 'I': + DCL_TYPE(type) = IPOINTER; + s++; + break; + case 'P': + DCL_TYPE(type) = PPOINTER; + s++; + break; + case 'A': + s++; + DCL_TYPE(type) = ARRAY ; + DCL_ELEM(type) = (short)strtol(s,&s,10); + break; + } + } + else + { + /* is a specifier */ + type->class = SPECIFIER; + s++; + switch (*s) + { + case 'L': + SPEC_NOUN(type) = V_INT; + SPEC_LONG(type) = 1; + s++; + break; + case 'I': + SPEC_NOUN(type) = V_INT; + s++; + break; + case 'S': + case 'C': + SPEC_NOUN(type) = V_CHAR ; + s++; + break; + case 'V': + SPEC_NOUN(type) = V_VOID; + s++; + break; + case 'F': + SPEC_NOUN(type) = V_FLOAT; + s++; + break; + case 'T': + s++; + SPEC_NOUN(type) = V_STRUCT; + { + char *ss = strtok(strdup(s), ",):"); + + SPEC_STRUCT(type) = structWithName(ss); + free(ss); + } + break; + case 'X': + s++; + SPEC_NOUN(type) = V_SBIT; + break; + case 'B': + SPEC_NOUN(type) = V_BIT; + s++; + SPEC_BSTR(type) = strtol(s, &s, 10); + s++; + SPEC_BLEN(type) = strtol(s, &s, 10); + break; + } + while (*s != ':') + s++; + s++; + if (*s++ == 'S') + SPEC_USIGN(type) = 0; + else + SPEC_USIGN(type) = 1; + } + + /* add the type to the symbol's type chain */ + if (sym->type) + sym->etype = sym->etype->next = type; + else + sym->type = sym->etype = type; + } + + return ++s; +} + +/*-----------------------------------------------------------------*/ +/* symFromRec - parse a symbol record and extract and create a sym */ +/* expects the input string to be of the form */ +/* {G|F<filename>|L<filename>'.'<functionName>}'$' */ +/* <name>'$'<level>'$'<block><type info> */ +/*-----------------------------------------------------------------*/ +symbol *parseSymbol (char *s, char **rs, int doadd) +{ + symbol *nsym; + char save_ch; + char *bp = s; + + /* go the mangled name */ + for ( bp = s; *bp && *bp != '('; bp++ ) + ; + save_ch = *--bp; + *bp = '\0'; + nsym = NULL; + if ( doadd == 2 ) + { + /* add only if not present and if linkrecord before symbol record */ + if ( applyToSetFTrue(symbols, symWithRName, s, &nsym)) + { + if ( nsym->rname != nsym->name ) + return NULL; + doadd = 0; + } + } + if ( ! nsym ) + { + nsym = Safe_calloc(1, sizeof(symbol)); + nsym->rname = alloccpy(s, bp - s); + } + *bp = save_ch; + /* if this is a Global Symbol */ + nsym->scopetype = *s; + s++; + if (nsym->scopetype != 'G') + { + /* get the function name it is local to */ + bp = s; + while (*s != '$') + s++; + nsym->sname = alloccpy(bp, s - bp); + } + + /* next get the name */ + bp = ++s; + while ( *s != '$' ) + s++; + nsym->name = alloccpy(bp, s - bp); + + s++; + /* get the level number */ + nsym->level = (short)strtol (s, &bp, 10); + s = ++bp; + /* skip the '$' & get the block number */ + nsym->block = (short)strtol (s, &bp, 10); + + s = parseTypeInfo(nsym, bp); + + /* get the address space after going past the comma */ + s++; + nsym->addrspace = *s; + + s+= 2; + nsym->isonstack = (short)strtol(s, &s, 10); + /* get the stack offset */ + s++; + nsym->offset = strtol(s, &s, 10); + + if ( nsym->addrspace == 'R' ) + { + /* get registeroffset */ + while (*s && *s != '[') + s++; + s++; + if ( *s == 'r' ) + { + nsym->addr = strtol(s+1, &s, 10); + } + while (*s && *s != ']') + s++; + } + + *rs = s; + if ( doadd ) + addSet(&symbols, nsym); + + Dprintf(D_symtab, ("symtab: par %s(0x%x) add=%d sym=%p\n", + nsym->name, nsym->addr, doadd, nsym)); + + return nsym; +} + +/*-----------------------------------------------------------------*/ +/* parseStruct - parses a structure record expected in format */ +/* {F<filename>}$<tag>[()()()...] */ +/*-----------------------------------------------------------------*/ +structdef *parseStruct (char *s) +{ + structdef *nsdef ; + char *bp; + char *name; + symbol *fields = NULL; + + while (*s != '$') + s++; + + bp =++s; + while (*s != '[') + s++; + name = alloccpy(bp,s - bp); + nsdef = structWithName(name); + nsdef->fields = NULL; + nsdef->size = 0; + s++; + while (*s && *s != ']') + { + int offset ; + symbol *sym ; + while (!isdigit(*s)) + s++; + offset = strtol(s,&s,10); + while (*s != ':') + s++; + s++; + sym = parseSymbol(s,&s,0); + sym->offset = offset ; + s += 3; + if (!fields) + fields = nsdef->fields = sym; + else + fields = fields->next = sym; + nsdef->size += sym->size; + } + + return nsdef; +} + +/*-----------------------------------------------------------------*/ +/* parseModule - creates a module with a given name */ +/*-----------------------------------------------------------------*/ +module *parseModule (char *s, bool createName ) +{ + module *nmod ; + char buffer[512]; + + nmod = Safe_calloc(1, sizeof(module)); + + addSet (&modules, nmod); + + /* create copy file name */ + nmod->name = s; + + if (createName) + { + sprintf(buffer, "%s.c", s); + nmod->c_name = Safe_malloc(strlen(buffer)+1); + strcpy(nmod->c_name, buffer); + + sprintf(buffer, "%s.asm", s); + nmod->asm_name = Safe_malloc(strlen(buffer)+1); + strcpy(nmod->asm_name, buffer); + } + + return nmod; +} + +/*-----------------------------------------------------------------*/ +/* moduleWithName - finds and returns a module with a given name */ +/*-----------------------------------------------------------------*/ +DEFSETFUNC(moduleWithName) +{ + module *mod = item; + V_ARG(char *, s); + V_ARG(module **, rmod); + + if (*rmod) + return 0; + + if (strcmp(mod->name, s) == 0) + { + *rmod = mod; + return 1; + } + + return 0; +} + +/*-----------------------------------------------------------------*/ +/* moduleWithCName - finds and returns a module with a given c_name*/ +/*-----------------------------------------------------------------*/ +DEFSETFUNC(moduleWithCName) +{ + module *mod = item; + V_ARG(char *, s); + V_ARG(module **, rmod); + + if (*rmod) + return 0; + + if (strcmp(mod->c_name, s) == 0) + { + *rmod = mod; + return 1; + } + + return 0; +} + +/*-----------------------------------------------------------------*/ +/* moduleWithAsmName - finds & returns a module with given asm_name*/ +/*-----------------------------------------------------------------*/ +DEFSETFUNC(moduleWithAsmName) +{ + module *mod = item; + V_ARG(char *, s); + V_ARG(module **, rmod); + + if (*rmod) + return 0; + + if (strcmp(mod->asm_name, s) == 0) + { + *rmod = mod; + return 1; + } + + return 0; +} + +/*-----------------------------------------------------------------*/ +/* structWithName - returns a structure with a given name */ +/*-----------------------------------------------------------------*/ +structdef *structWithName (char *s) +{ + int i; + structdef *nsdef ; + + /* go thru the struct table looking for a match */ + for ( i = 0 ; i < nStructs ; i++ ) + { + if (strcmp(currModName,structs[i]->sname) == 0 && + strcmp(s,structs[i]->tag) == 0) + { + return structs[i]; + } + } + + nsdef = Safe_calloc(1,sizeof(structdef)); + nsdef->tag = alloccpy(s,strlen(s)); + nsdef->sname = currModName ; + + nStructs++; + structs = (struct structdef **)resize((void **)structs,nStructs); + structs[nStructs-1] = nsdef; + return nsdef; +} + +/*-----------------------------------------------------------------*/ +/* symWithRName - look for symbol with mangled name = parm */ +/*-----------------------------------------------------------------*/ +DEFSETFUNC(symWithRName) +{ + symbol *sym = item; + V_ARG(char *, s); + V_ARG(symbol **, rsym); + + if (*rsym) + return 0; + + if (strcmp(sym->rname, s) == 0) + { + *rsym = sym; + return 1; + } + + return 0; +} + +/*-----------------------------------------------------------------*/ +/* funcWithRName - look for function with name */ +/*-----------------------------------------------------------------*/ +DEFSETFUNC(funcWithRName) +{ + function *func = item; + V_ARG(char *,s); + V_ARG(function **,rfunc); + + if (*rfunc) + return 0; + + if (strcmp(func->sym->rname,s) == 0) + { + *rfunc = func; + return 1; + } + + return 0; +} + +/*-----------------------------------------------------------------*/ +/* symLocal - local symbol respecting blocks & levels */ +/*-----------------------------------------------------------------*/ +DEFSETFUNC(symLocal) +{ + symbol *sym = item; + V_ARG(char *, name); + V_ARG(char *, sname); + V_ARG(int, block); + V_ARG(int, level); + V_ARG(symbol **, rsym); + + if (strcmp(name, sym->name) == 0 && /* name matches */ + sym->scopetype != 'G' && /* local scope */ + sym->sname && + strcmp(sym->sname, sname) == 0 && /* scope == specified scope */ + sym->block <= block && /* block & level kindo matches */ + sym->level <= level) + { + /* if a symbol was previously found then + sure that ones block & level are less + then this one */ + if (*rsym && (*rsym)->block >= block && (*rsym)->level >= level) + return 0; + + *rsym = sym; + return 1; + } + + return 0; +} + +/*-----------------------------------------------------------------*/ +/* symGlobal - return global symbol of name */ +/*-----------------------------------------------------------------*/ +DEFSETFUNC(symGlobal) +{ + symbol *sym = item; + V_ARG(char *, name); + V_ARG(symbol **, rsym); + + if (*rsym) + return 0; + + /* simple :: global & name matches */ + if (sym->scopetype == 'G' && + strcmp(sym->name, name) == 0) + { + *rsym = sym; + return 1; + } + + return 0; +} + +/*-----------------------------------------------------------------*/ +/* symLookup - determine symbol from name & context */ +/*-----------------------------------------------------------------*/ +symbol *symLookup (char *name, context *ctxt) +{ + symbol *sym = NULL; + + if ((ctxt) && (ctxt->func) && + (ctxt->func->sym) && (ctxt->func->sym->name)) + { + char *sname = gc_strcat(ctxt->func->mod->name, ".", ctxt->func->sym->name); + /* first try & find a local variable for the given name */ + if ( applyToSet(symbols, symLocal, + name, + sname, + ctxt->block, + ctxt->level, + &sym)) + { + Safe_free(sname); + return sym; + } + Safe_free(sname); + sym = NULL; + } + + if ((ctxt) && (ctxt->func) && + (ctxt->func->mod) && (ctxt->func->mod->name)) + { + /* then try local to this module */ + if (applyToSet(symbols, symLocal, + name, + ctxt->func->mod->name, + 0, + 0, + &sym)) + { + return sym; + } + sym = NULL; + } + + /* no:: try global */ + if ( applyToSet(symbols, symGlobal, name, &sym)) + return sym; + + /* cannot find return null */ + return NULL; +} + +/*-----------------------------------------------------------------*/ +/* lnkFuncEnd - link record for end of function */ +/*-----------------------------------------------------------------*/ +static void lnkFuncEnd (char *s) +{ + char sname[128], *bp = sname; + function *func; + + /* copy till we get to a ':' */ + while ( *s != ':' ) + *bp++ = *s++; + bp -= 1; + *bp = '\0'; + + func = NULL; + if (!applyToSet(functions,funcWithRName,sname,&func)) + return ; + + s++; + sscanf(s,"%x",&func->sym->eaddr); + + Dprintf(D_symtab, ("symtab: ead %s(0x%x)\n",func->sym->name,func->sym->eaddr)); +} + +/*-----------------------------------------------------------------*/ +/* lnkSymRec - record for a symbol */ +/*-----------------------------------------------------------------*/ +static void lnkSymRec (char *s) +{ + char *bp, save_ch ; + symbol *sym; + + /* search to a ':' */ + for ( bp = s; *bp && *bp != ':'; bp++ ); + save_ch = *--bp; + *bp = '\0'; + + sym = NULL; + applyToSetFTrue(symbols,symWithRName,s,&sym); + if (! sym) + { + sym = Safe_calloc(1,sizeof(symbol)); + sym->rname = alloccpy(s,bp - s); + sym->scopetype = *s; + sym->name = sym->rname; + addSet(&symbols,sym); + } + *bp = save_ch; + if ( *bp ) + { + sscanf(bp+2,"%x",&sym->addr); + } + Dprintf(D_symtab, ("symtab: lnk %s(0x%x)\n",sym->name,sym->addr)); +} + +/*-----------------------------------------------------------------*/ +/* lnkAsmSrc - process linker record for asm sources */ +/*-----------------------------------------------------------------*/ +static void lnkAsmSrc (char *s) +{ + char mname[128], *bp = mname; + int line ; + unsigned addr; + module *mod = NULL; + + /* input will be of format + filename$<line>:<address> */ + while (*s != '$' && *s != '.') + *bp++ = *s++; + *bp = '\0'; + /* skip to line stuff */ + while (*s != '$') + s++; + + if (!applyToSet(modules, moduleWithName, mname, &mod)) + return ; + + if (sscanf(s, "$%d:%x", &line, &addr) != 2) + return ; + + line--; + if (line < mod->nasmLines) + { + mod->asmLines[line]->addr = addr; + Dprintf(D_symtab, ("symtab: asm %s(%d:0x%x) %s", mod->asm_name, line, addr, mod->asmLines[line]->src)); + } +} + +/*-----------------------------------------------------------------*/ +/* lnkCSrc - process linker output for c source */ +/*-----------------------------------------------------------------*/ +static void lnkCSrc (char *s) +{ + char mname[128], *bp = mname; + int block,level,line; + unsigned int addr; + module *mod ; + + /* input will be of format + filename.ext$<line>$<level>$<block>:<address> */ + /* get the module name */ + while (*s != '$' ) + *bp++ = *s++; + *bp = '\0'; + /* skip the extension */ + while (*s != '$') + s++; + + if (sscanf(s,"$%d$%d$%d:%x", &line,&level,&block,&addr) != 4) + return ; + + mod = NULL; + if (!applyToSet(modules,moduleWithCName,mname,&mod)) + { + mod = parseModule(mname, FALSE); + mod->c_name = alloccpy(mname,strlen(mname)); + mod->cfullname=searchDirsFname(mod->c_name); + mod->cLines = loadFile(mod->c_name,&mod->ncLines); + } + + line--; + /* one line can have more than one address : (for loops !)*/ + if (line < mod->ncLines && line > 0 /*&& + ( !mod->cLines[line]->addr || + mod->cLines[line]->level > level )*/ ) + { + if ( mod->cLines[line]->addr != INT_MAX ) + { + /* save double line information for exepoints */ + exePoint *ep ; + ep = Safe_calloc(1,sizeof(exePoint)); + ep->addr = mod->cLines[line]->addr ; + ep->line = line; + ep->block= mod->cLines[line]->block; + ep->level= mod->cLines[line]->level; + addSet(&mod->cfpoints,ep); + Dprintf(D_symtab, ("symtab: exe %s(%d:0x%x) %s", mod->c_name, + line+1, addr, mod->cLines[line]->src)); + } + mod->cLines[line]->addr = addr; + mod->cLines[line]->block = block; + mod->cLines[line]->level = level; + Dprintf(D_symtab, ("symtab: ccc %s(%d:0x%x) %s", mod->c_name, + line+1, addr, mod->cLines[line]->src)); + } + return; +} + +/*-----------------------------------------------------------------*/ +/* parseLnkRec - parses a linker generated record */ +/*-----------------------------------------------------------------*/ +void parseLnkRec (char *s) +{ + /* link records can be several types + dpeneding on the type do */ + + switch (*s) + { + /* c source line address */ + case 'C': + lnkCSrc(s+2); + break; + /* assembler source address */ + case 'A': + lnkAsmSrc(s+2); + break; + + case 'X': + lnkFuncEnd(s+1); + break; + + default : + lnkSymRec(s); + break; + } +} |
