home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, John F. Haugh II
- * An unpublished work.
- * All rights reserved.
- *
- * Permission is granted to copy and create derivative works for any
- * non-commercial purpose, provided this copyright notice is preserved
- * in all copies of source code, or included in human readable form
- * and conspicuously displayed on all copies of object code or
- * distribution media.
- */
-
- #ifndef lint
- static char sccsid[] = "@(#)syms.c 2.1 07:15:42 2/27/91";
- #endif
-
- #include <sys/types.h>
- #include <sys/a.out.h>
- #include <sys/relsym.h>
- #include <stdio.h>
-
- struct xlist3 {
- unsigned short xl3_type;
- unsigned short xl3_seg;
- unsigned long xl3_value;
- };
-
- struct xlist **symbols;
- int nsymbols;
- int maxsymbols;
-
- extern char *strdup();
-
- int
- initsyms (file)
- char *file;
- {
- FILE *fp;
- long segsize;
- long pad;
- struct xexec xexec;
- struct xext xext;
- struct xseg xseg;
- struct xlist xlist;
- char buf[BUFSIZ];
- char *cp;
-
- if (! (fp = fopen (file, "r"))) {
- perror (file);
- return -1;
- }
- if (fread (&xexec, sizeof xexec, 1, fp) != 1) {
- printf ("error reading xexec header\n");
- return -1;
- }
- if (xexec.x_magic != X_MAGIC) {
- printf ("not a valid x.out header\n");
- return -1;
- }
- if (! (xexec.x_renv & XE_SEG)) {
- printf ("not a segmented object\n");
- return -1;
- }
- if (fread (&xext, sizeof xext, 1, fp) != 1) {
- printf ("error reading xext record\n");
- return -1;
- }
- if (fseek (fp, xext.xe_segpos, 0) == -1) {
- printf ("error seeking to segment table\n");
- return -1;
- }
- while (fread (&xseg, sizeof xseg, 1, fp) == 1 && xext.xe_segsize > 0) {
- if (xseg.xs_type == XS_TSYMS)
- break;
-
- xext.xe_segsize -= sizeof xseg;
- }
- if (xext.xe_segsize <= 0) {
- printf ("error locating symbol table\n");
- return -1;
- }
- if (fseek (fp, xseg.xs_filpos, 0) == -1) {
- printf ("error seeking to symbol table\n");
- return -1;
- }
- while (ftell (fp) < xseg.xs_filpos + xseg.xs_psize) {
- if (nsymbols == maxsymbols) {
- if (nsymbols == 0) {
- maxsymbols = 10;
- symbols = (struct xlist **)
- malloc (maxsymbols * sizeof *symbols);
- } else {
- maxsymbols *= 2;
- symbols = (struct xlist **) realloc (symbols,
- maxsymbols * sizeof *symbols);
- }
- }
- if (symbols == 0) {
- printf ("error allocating memory for symbol table\n");
- return -1;
- }
- fread (&xlist, sizeof (struct xlist3), 1, fp);
- for (cp = buf;*cp++ = getc (fp);)
- ;
-
- xlist.xl_name = strdup (buf);
-
- symbols[nsymbols] = (struct xlist *)
- malloc (sizeof (struct xlist));
- *(symbols[nsymbols++]) = xlist;
- }
- fclose (fp);
- return 0;
- }
-
- long
- sym2addr (sym, type)
- char *sym;
- int type;
- {
- int i;
- int symbol_type;
-
- if (symbols == 0)
- return -1;
-
- for (i = 0;i < nsymbols;i++) {
- symbol_type = symbols[i]->xl_type & S_TYPE;
-
- if (type == 0 && strcmp (sym, symbols[i]->xl_name) == 0)
- return symbols[i]->xl_value;
-
- if (type == symbol_type && ! strcmp (sym, symbols[i]->xl_name))
- return symbols[i]->xl_value;
- }
- return -1;
- }
-
- char *
- addr2sym (addr, diffp, type)
- long addr;
- long *diffp;
- int type;
- {
- int guess = -1;
- int i;
- int symbol_type;
-
- if (symbols == 0)
- return 0;
-
- for (i = 0;i < nsymbols;i++) {
- symbol_type = symbols[i]->xl_type & S_TYPE;
-
- if (type == 0 && addr >= symbols[i]->xl_value &&
- (guess == -1 ||
- symbols[i]->xl_value > symbols[guess]->xl_value))
- guess = i;
-
- if (type == symbol_type && addr >= symbols[i]->xl_value &&
- (guess == -1 ||
- symbols[i]->xl_value > symbols[guess]->xl_value))
- guess = i;
- }
- if (guess == -1)
- return 0;
-
- *diffp = addr - symbols[guess]->xl_value;
- return symbols[guess]->xl_name;
- }
-
- char *
- text2sym (addr, diffp)
- long addr;
- long *diffp;
- {
- return addr2sym (addr, diffp, S_TEXT);
- }
-
- char *
- data2sym (addr, diffp)
- long addr;
- long *diffp;
- {
- char *sym1, *sym2;
- long diff1, diff2;
-
- sym1 = addr2sym (addr, &diff1, S_DATA);
- sym2 = addr2sym (addr, &diff2, S_BSS);
-
- if (sym1 && sym2) {
- if (diff1 < diff2) {
- *diffp = diff1;
- return sym1;
- } else {
- *diffp = diff2;
- return sym2;
- }
- }
- if (sym1) {
- *diffp = diff1;
- return sym1;
- } else if (sym2) {
- *diffp = diff2;
- return sym2;
- } else
- return 0;
- }
-
- prtextaddr (cp)
- char *cp;
- {
- long addr;
- char *sym;
- long diff;
-
- if (expr (&cp, &addr)) {
- printf ("error in '%.15s'\n", cp);
- return;
- }
- if (! (sym = text2sym (addr, &diff))) {
- printf ("no text address for %d (%x)\n", addr, addr);
- return;
- }
- if (diff != 0)
- printf ("%d (%x) = %s+%d (%x)\n", addr, addr, sym, diff, diff);
- else
- printf ("%d (%x) = %s\n", addr, addr, sym);
- }
-
- prdataaddr (cp)
- char *cp;
- {
- long addr;
- char *sym;
- long diff;
-
- if (expr (&cp, &addr)) {
- printf ("error in '%.15s'\n", cp);
- return;
- }
- if (! (sym = data2sym (addr, &diff))) {
- printf ("no data address for %d (%x)\n", addr, addr);
- return;
- }
- if (diff != 0)
- printf ("%d (%x) = %s+%d (%x)\n", addr, addr, sym, diff, diff);
- else
- printf ("%d (%x) = %s\n", addr, addr, sym);
- }
-
- prsymbol (cp)
- char *cp;
- {
- char buf[BUFSIZ];
- long addr;
- int type;
- char *sym;
-
- buf[0] = '_';
- strcpy (buf + 1, cp);
-
- if ((addr = sym2addr (sym = buf + 1, type = S_TEXT)) == -1 &&
- (addr = sym2addr (sym = buf, type = S_TEXT)) == -1 &&
- (addr = sym2addr (sym = buf + 1, type = S_DATA)) == -1 &&
- (addr = sym2addr (sym = buf, type = S_DATA)) == -1 &&
- (addr = sym2addr (sym = buf + 1, type = S_BSS)) == -1 &&
- (addr = sym2addr (sym = buf, type = S_BSS)) == -1) {
- printf ("%s not found\n", cp);
- return;
- }
- printf ("%s (%s) = %d (%x)\n", sym, type == S_TEXT ? "text":
- (type == S_DATA ? "data":
- (type == S_BSS ? "bss":"unknown")), addr, addr);
- }
-
- #ifdef TEST
- main (argc, argv)
- int argc;
- char **argv;
- {
- int i;
- long addr;
- long diff;
- char *sym;
- char buf[BUFSIZ];
- char *cp;
-
- if (initsyms (argv[1]))
- exit (1);
-
- printf ("allocated %d slots for %d symbols\n", maxsymbols, nsymbols);
-
- while (gets (buf)) {
- if (buf[0] >= '0' && buf[0] <= '9') {
- cp = buf;
- if (expr (&cp, &addr)) {
- printf ("error at '%.15s'\n", cp);
- continue;
- }
- sym = addr2sym (addr, &diff, 0);
- printf ("name of %s (%x) is %s+%d\n",
- buf, addr, sym, diff);
- } else {
- addr = sym2addr (buf, 0);
- printf ("address of %s is %d (%x)\n", buf, addr, addr);
- }
- }
- }
- #endif
-