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