dclemans@mentor.com (Dave Clemans @ APD x1292) (06/15/89)
#! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 3 (of 4)." # Contents: symbolic.c # Wrapped by dclemans@dclemans on Wed Jun 14 14:59:43 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'symbolic.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'symbolic.c'\" else echo shar: Extracting \"'symbolic.c'\" \(22081 characters\) sed "s/^X//" >'symbolic.c' <<'END_OF_FILE' X/* X * Symbolic debug symbol converter for the X * GNU->COFF object file format conversion tool. X */ X#include <stdio.h> X#include <ctype.h> X#include <string.h> X#include <memory.h> Xextern char *malloc(); Xextern long atol(); X X#include "gnu2coff.h" Xextern struct syment *coff_symbol_addr(); Xextern struct syment *coff_symbol_space(); Xextern long coff_text_line(); X X#include <syms.h> X#undef n_name X#undef n_nptr X#undef n_zeroes X#undef n_offset X#undef N_ABS X#include <linenum.h> X X#include "/gnu/src/gdb/a.out.gnu.h" X#include "/gnu/src/gdb/stab.gnu.h" X Xstruct type_def X{ X char *name; X long size; X long low; X long high; X long typenum; X long typeof; X long flags; X#define IS_FUNC 0x0001 X#define IS_POINTER 0x0002 X#define IS_ARRAY 0x0004 X#define IS_STRUCT 0x0008 X#define IS_ENUM 0x0010 X struct type_def *members; X struct type_def *memend; X struct type_def *next; X}; X Xstruct sym_lvar X{ X char *name; X long value; X int is_register; X long typenum; X struct sym_lvar *next; X}; X Xstruct sym_line X{ X long number; X long address; X struct sym_line *next; X}; X Xstruct sym_func X{ X char *name; X long value; X long symbol; X long typenum; X long bstart,bline; X long estart,eline; X struct sym_line *lines; X struct sym_line *lines_bottom; X struct sym_lvar *parms; X struct sym_lvar *parms_bottom; X struct sym_lvar *lvars; X struct sym_lvar *lvars_bottom; X}; X Xstatic struct sym_func current; Xstatic struct type_def *types; Xstatic struct type_def *types_bottom; Xstatic struct type_def *globals; Xstatic struct type_def *globals_bottom; X Xstatic long get_typenum(p) Xchar *p; X{ X if (isdigit(*p)) X return atol(p); X else return atol(p+1); X} /* end of get_typenum */ X Xvoid get_name(td,f,l) Xstruct type_def *td; Xchar *f; Xchar *l; X{ X td->name = (char *)malloc((int)(l - f) + 1); X if (td->name == (char *)NULL) X { /* if no memory */ X fprintf(stderr,"gnu2coff: no memory for names\n"); X exit(1); X } X strncpy(td->name,f,(int)(l - f)); X td->name[(int)(l - f)] = '\0'; X} /* end of get_name */ X Xstatic struct type_def *want_continuation; X Xstatic char *get_enum(t,td) Xchar *t; Xstruct type_def *td; X{ X register char *l; X struct type_def *newtd; X X newtd = (struct type_def *)malloc(sizeof(struct type_def)); X if (newtd == (struct type_def *)NULL) X { /* if no memory */ X fprintf(stderr,"gnu2coff: no memory for types\n"); X exit(1); X } X newtd->low = newtd->high = newtd->flags = newtd->typenum = newtd->size = newtd->typeof = 0; X newtd->members = newtd->memend = newtd->next = (struct type_def *)NULL; X X l = strchr(t,':'); X if (l == (char *)NULL) X { /* if error */ X for (l = t; *l && *l != ','; l++) X /* do nothing */; X return l; X } X get_name(newtd,t,l); X newtd->size = atol(l+1); X if (td->members == (struct type_def *)NULL) X td->members = td->memend = newtd; X else X { /* tack onto end */ X td->memend->next = newtd; X td->memend = newtd; X } X X while (*l && *l != ',') X l++; X if (*l == ',') X l++; X return l; X} /* end of get_enum */ X Xstatic char *get_type(t,td) Xchar *t; Xstruct type_def **td; X{ X register char *l; X struct type_def *newtd; X char type; X X want_continuation = (struct type_def *)NULL; X X if (!isdigit(*t)) X { /* if a name present */ X l = strchr(t,':'); X if (l == (char *)NULL) X { /* if doesn't look good */ X fprintf(stderr,"gnu2coff: apparent bad type line(1): %s\n",t); X for (l = t; *l; l++) X /* do nothing */; X return l; X } X } X else l = t; X *td = (struct type_def *)malloc(sizeof(struct type_def)); X if (*td == (struct type_def *)NULL) X { /* if no memory */ X fprintf(stderr,"gnu2coff: no memory for types\n"); X exit(1); X } X (*td)->low = (*td)->high = (*td)->flags = (*td)->typenum = (*td)->size = (*td)->typeof = 0; X (*td)->members = (*td)->memend = (*td)->next = (struct type_def *)NULL; X if (l != t) X { /* if a name present */ X get_name(*td,t,l); X } X else (*td)->name = (char *)NULL; X type = *++l; X if (isdigit(type)) X (*td)->typenum = atol(--l); X else if (isdigit(*++l)) X (*td)->typenum = atol(l); X else X { /* bad type number */ X if (*l == '\\') X { /* really just a continuation */ X want_continuation = *td; X return l+1; X } X fprintf(stderr,"gnu2coff: apparent bad type line(2): %s\n",t); X for (l = t; *l; l++) X /* do nothing */; X return l; X } X while (isdigit(*l)) X l++; X if (*l != '=') X { /* check for use of existing type */ X (*td)->typeof = (*td)->typenum; X (*td)->typenum = 0; X while (*l && *l != ';') X l++; X if (*l == ';') X l++; X return l; X } X l++; X while (*l && *l != ';' && !isdigit(*l)) switch (*l) X { /* what kind of type */ X case 'r': X case 'R': X l++; X break; X case 's': X case 'S': X (*td)->flags |= IS_STRUCT; X l++; X (*td)->size = atol(l); X while (*l && isdigit(*l)) X l++; X while (*l && *l != ';' && *l != '\\') X { /* while struct members possible */ X l = get_type(l,&newtd); X if ((*td)->members == (struct type_def *)NULL) X (*td)->members = (*td)->memend = newtd; X else X { /* tack onto end */ X (*td)->memend->next = newtd; X (*td)->memend = newtd; X } X } X if (*l == '\\') X want_continuation = *td; X if (*l) l++; X break; X case 'e': X case 'E': X (*td)->flags |= IS_ENUM; X l++; X while (*l && *l != ';' && *l != '\\') X l = get_enum(l,*td); X if (*l == '\\') X want_continuation = *td; X if (*l) l++; X break; X case '*': X (*td)->flags |= IS_POINTER; X l++; X (*td)->typeof = atol(l); X while (*l && *l != ';') X l++; X break; X case 'a': X case 'A': X (*td)->flags |= IS_ARRAY; X l++; X break; X default: X fprintf(stderr,"gnu2coff: apparent bad type line(4): %s\n",t); X for (l = t; *l; l++) X /* do nothing */; X return l; X } X (*td)->size = atol(l); X while (*l && isdigit(*l)) X l++; X if ((*td)->flags & IS_ARRAY) X { /* get sizes */ X l++; X (*td)->low = atol(l); X while (*l && isdigit(*l)) X l++; X l++; X (*td)->high = atol(l); X while (*l && isdigit(*l)) X l++; X l++; X (*td)->typeof = atol(l); X while (*l && isdigit(*l)) X l++; X } X X while (*l && *l != ';') X l++; X if (*l == ';') X l++; X return l; X} /* end of get_type */ X Xstatic void decode_type(s) Xstruct nlist *s; X{ X register char *p,*n; X char *t; X struct type_def *td,*newtd; X X if (want_continuation) X { /* if continuing previous def */ X td = want_continuation; X want_continuation = (struct type_def *)NULL; X if (td->flags & IS_ENUM) X { /* fill an enum? */ X p = s->n_un.n_name; X while (*p && *p != ';' && *p != '\\') X p = get_enum(p,td); X if (*p == '\\') X want_continuation = td; X } X else if (td->flags & IS_STRUCT) X { /* a structure? */ X p = s->n_un.n_name; X while (*p && *p != ';' && *p != '\\') X { /* while members are possible */ X p = get_type(p,&newtd); X if (td->members == (struct type_def *)NULL) X td->members = td->memend = newtd; X else X { /* tack onto end */ X td->memend->next = newtd; X td->memend = newtd; X } X } X if (*p == '\\') X want_continuation = td; X } X else X { /* unknown */ X (void)get_type(s->n_un.n_name,&td); X } X return; X } X X (void) get_type(s->n_un.n_name,&td); X if (types == (struct type_def *)NULL) X types = types_bottom = td; X else X { /* tack onto end */ X types_bottom->next = td; X types_bottom = td; X } X} /* end of decode_type */ X Xstatic char *lookup_type(number) Xlong number; X{ X register struct type_def *td; X X for (td = types; td != (struct type_def *)NULL; td = td->next) X { /* do we know this type? */ X if (td->typenum == number) X return td->name; X } X return "unknown"; X} /* end of lookup_type */ X Xstatic void dump_current() X{ X struct sym_line *sl,*slp; X struct sym_lvar *lv,*lvp; X long symnum; X struct syment *func; X union auxent *func_aux; X struct syment *s; X union auxent *a; X X if (current.name == (char *)NULL || strcmp(current.name,".text") == 0) X return; X X if (current.lines != (struct sym_line *)NULL) X { /* if line number info */ X if (current.bline == 0) X { /* if not set yet */ X if (current.lines->next != (struct sym_line *)NULL) X { /* get info from guessed at start */ X current.bline = current.lines->next->number; X current.bstart = current.lines->next->address; X } X else X { /* get only info available */ X current.bline = current.lines->number; X current.bstart = current.lines->address; X } X } X if (current.eline == 0) X { /* if not set yet */ X for (sl = current.lines; sl != (struct sym_line *)NULL; sl = sl->next) X { /* copy in the info */ X current.eline = sl->number; X current.estart = sl->address; X } X } X s = coff_symbol_space(2L,&symnum); X func = coff_symbol_addr(current.symbol); X func_aux = (union auxent *)coff_symbol_addr(current.symbol+1); X func_aux->x_sym.x_tvndx = func->n_sclass; X func->n_sclass = C_FCN; X func_aux->x_sym.x_tagndx = symnum; X func_aux->x_sym.x_fcnary.x_fcn.x_lnnoptr = coff_text_line(current.symbol,(short)0)+1; X strcpy(s->_n._n_name,".bf"); X s->n_value = current.bstart; X s->n_scnum = STEXT; X s->n_type = T_NULL; X s->n_sclass = C_FCN; X s->n_numaux = 1; X a = (union auxent *)coff_symbol_addr(symnum+1); X a->x_sym.x_misc.x_lnsz.x_lnno = current.bline; X if (current.lines != (struct sym_line *)NULL) X { /* if some line numbers to insert */ X for (sl = current.lines->next; sl != (struct sym_line *)NULL; sl = sl->next) X { /* stick in the source lines */ X if (sl->number <= current.bline) X continue; X (void) coff_text_line(sl->address,(short)sl->number-current.bline); X } X } X s = coff_symbol_space(2L,&symnum); X strcpy(s->_n._n_name,".ef"); X s->n_value = current.estart; X s->n_scnum = STEXT; X s->n_type = T_NULL; X s->n_sclass = C_FCN; X s->n_numaux = 1; X a = (union auxent *)coff_symbol_addr(symnum+1); X a->x_sym.x_misc.x_lnsz.x_lnno = current.eline; X } X X if (show_func_structure) X { /* what does this function look like? */ X if (current.lines != (struct sym_line *)NULL) X printf("%d=0x%x:",current.lines->number-1,current.lines->address); X printf("%s ",lookup_type(current.typenum)); X printf("%s(",current.name); X for (lv = current.parms; lv != (struct sym_lvar *)NULL; lv = lv->next) X { /* check for parameters */ X if (lv->is_register) X printf("%s %s=r%d",lookup_type(lv->typenum),lv->name,lv->is_register); X else printf("%s %s=%d",lookup_type(lv->typenum),lv->name,lv->value); X if (lv->next != (struct sym_lvar *)NULL) X printf(","); X } X printf(")\n"); X printf("%d=%x:{\n",current.bline,current.bstart); X for (lv = current.lvars; lv != (struct sym_lvar *)NULL; lv = lv->next) X { /* check for local variables */ X if (lv->is_register) X printf("%s %s=r%d\n",lookup_type(lv->typenum),lv->name,lv->is_register); X else printf("%s %s=%d\n",lookup_type(lv->typenum),lv->name,lv->value); X } X if (current.lines != (struct sym_line *)NULL) X { /* if a line number chain */ X for (sl = current.lines->next; sl != (struct sym_line *)NULL; sl = sl->next) X { /* and the line number table */ X printf("\t%5d:0x%x\n",sl->number,sl->address); X } X } X printf("%d=%x:}\n",current.eline,current.estart); X } X X for (sl = current.lines; sl != (struct sym_line *)NULL; ) X { /* dump the old line chain */ X slp = sl; X sl = sl->next; X free(slp); X } X for (lv = current.parms; lv != (struct sym_lvar *)NULL; ) X { /* dump the old parms chain */ X lvp = lv; X lv = lv->next; X free(lvp->name); X free(lvp); X } X for (lv = current.lvars; lv != (struct sym_lvar *)NULL; ) X { /* dump the old lvars chain */ X lvp = lv; X lv = lv->next; X free(lvp->name); X free(lvp); X } X current.name = (char *)NULL; X current.value = 0; X current.typenum = 0; X current.lines = current.lines_bottom = (struct sym_line *)NULL; X current.parms = current.parms_bottom = (struct sym_lvar *)NULL; X current.lvars = current.lvars_bottom = (struct sym_lvar *)NULL; X current.bstart = current.bline = 0; X current.estart = current.eline = 0; X current.symbol = 0; X} /* end of dump_current */ X Xvoid sym_enter(s,symbol) Xstruct nlist *s; Xlong symbol; X{ X register char *p; X struct sym_line *sl; X struct sym_lvar *lv; X struct type_def *td; X X if (s == (struct nlist *)NULL) X { /* if just to dump pending stuff */ X dump_current(); X return; X } X if (s->n_value == 0) X { /* skip undefined or similar stuff; but check for typedef */ X if ((s->n_type & 0xFF) == N_LSYM) X decode_type(s); X return; X } X X switch ((s->n_type & 0xFF) & ~N_EXT) X { /* what do we need to do to the symbol? */ X case N_TEXT: /* start of function */ X dump_current(); X current.name = s->n_un.n_name; X if (s->n_type & N_EXT && s->n_un.n_name[0] == '_') X current.name++; X current.value = s->n_value; X current.symbol = symbol; X current.typenum = 0; X break; X case N_SLINE: /* line number */ X sl = (struct sym_line *)malloc(sizeof(struct sym_line)); X if (sl == (struct sym_line *)NULL) X { /* enough memory? */ X fprintf(stderr,"gnu2coff: no memory for source lines\n"); X exit(1); X } X sl->next = (struct sym_line *)NULL; X sl->number = s->n_desc; X sl->address = s->n_value; X if (current.lines == (struct sym_line *)NULL) X current.lines = current.lines_bottom = sl; X else X { /* tack onto end */ X current.lines_bottom->next = sl; X current.lines_bottom = sl; X } X break; X case N_FUN: /* end of function text; parms, local vars can follow */ X p = strchr(s->n_un.n_name,':'); X if (p == (char *)NULL || current.name == (char *)NULL || X strlen(current.name) != (int)(p - s->n_un.n_name) || X strncmp(current.name,s->n_un.n_name,(int)(p - s->n_un.n_name)) != 0) X { /* check to make sure we are still in sequence */ X printf("** function decode out of sequence: %s,%s\n", X current.name != (char *)NULL ? current.name : "(NULL)",s->n_un.n_name); X } X current.typenum = get_typenum(p + 1); X break; X case N_PSYM: /* a parameter */ X p = strchr(s->n_un.n_name,':'); X if (p == (char *)NULL) X { /* then something wrong */ X printf("** bad parameter: %s\n",s->n_un.n_name); X return; X } X lv = (struct sym_lvar *)malloc(sizeof(struct sym_lvar)); X if (lv == (struct sym_lvar *)NULL) X { /* enough memory? */ X fprintf(stderr,"gnu2coff: no memory for local vars\n"); X exit(1); X } X lv->next = (struct sym_lvar *)NULL; X lv->is_register = 0; X lv->name = (char *)malloc((int)(p - s->n_un.n_name) + 1); X if (lv->name == (char *)NULL) X { /* out of memory? */ X fprintf(stderr,"gnu2coff: no memory for names\n"); X exit(1); X } X strncpy(lv->name,s->n_un.n_name,(int)(p - s->n_un.n_name)); X lv->name[(int)(p - s->n_un.n_name)] = '\0'; X lv->value = s->n_value; X lv->typenum = get_typenum(p + 1); X if (current.parms == (struct sym_lvar *)NULL) X current.parms = current.parms_bottom = lv; X else X { /* tack onto end */ X current.parms_bottom->next = lv; X current.parms_bottom = lv; X } X break; X case N_GSYM: /* a global variable */ X (void) get_type(s->n_un.n_name,&td); X if (globals == (struct type_def *)NULL) X globals = globals_bottom = td; X else X { /* tack onto end */ X globals_bottom->next = td; X globals_bottom = td; X } X break; X case N_RSYM: /* local register variable, or mark a parm as a register */ X p = strchr(s->n_un.n_name,':'); X if (p == (char *)NULL) X { /* then something wrong */ X printf("** bad local symbol: %s\n",s->n_un.n_name); X return; X } X for (lv = current.parms; lv != (struct sym_lvar *)NULL; lv = lv->next) X { /* is this a parameter? */ X if (strlen(lv->name) == (int)(p - s->n_un.n_name) && X strncmp(lv->name,s->n_un.n_name,(int)(p - s->n_un.n_name)) == 0) X { /* a match means that it is a parameter */ X lv->is_register = s->n_value; X return; X } X } X /* FALL THROUGH! */ X case N_LSYM: /* local variable on stack */ X p = strchr(s->n_un.n_name,':'); X if (p == (char *)NULL) X { /* then something wrong */ X printf("** bad local symbol: %s\n",s->n_un.n_name); X return; X } X lv = (struct sym_lvar *)malloc(sizeof(struct sym_lvar)); X if (lv == (struct sym_lvar *)NULL) X { /* enough memory? */ X fprintf(stderr,"gnu2coff: no memory for local vars\n"); X exit(1); X } X lv->next = (struct sym_lvar *)NULL; X if (((s->n_type & 0xFF) & ~N_EXT) == N_LSYM) X lv->is_register = 0; X else lv->is_register = s->n_value; X lv->name = (char *)malloc((int)(p - s->n_un.n_name) + 1); X if (lv->name == (char *)NULL) X { /* out of memory? */ X fprintf(stderr,"gnu2coff: no memory for names\n"); X exit(1); X } X strncpy(lv->name,s->n_un.n_name,(int)(p - s->n_un.n_name)); X lv->name[(int)(p - s->n_un.n_name)] = '\0'; X lv->value = s->n_value; X lv->typenum = get_typenum(p + 1); X if (current.lvars == (struct sym_lvar *)NULL) X current.lvars = current.lvars_bottom = lv; X else X { /* tack onto end */ X current.lvars_bottom->next = lv; X current.lvars_bottom = lv; X } X break; X case N_LBRAC: /* start of basic block */ X if (current.bline == 0) X { /* if not set yet */ X current.bstart = s->n_value; X for (sl = current.lines; sl != (struct sym_line *)NULL; sl = sl->next) X { /* look for the right line number */ X if (sl->address == s->n_value) X { /* if we found the match */ X current.bline = sl->number; X break; X } X } X } X break; X case N_RBRAC: /* end of basic block */ X if (current.eline == 0) X { /* if not set yet */ X current.estart = s->n_value; X for (sl = current.lines; sl != (struct sym_line *)NULL; sl = sl->next) X { /* look for the right line number */ X if (sl->address == s->n_value) X { /* if we found the match */ X current.eline = sl->number; X break; X } X } X } X break; X default: /* just ignore it */ X break; X } X} /* end of sym_enter */ END_OF_FILE if test 22081 -ne `wc -c <'symbolic.c'`; then echo shar: \"'symbolic.c'\" unpacked with wrong size! fi # end of 'symbolic.c' fi echo shar: End of archive 3 \(of 4\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 4 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 4 archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0