bds@lzaz.ATT.COM (B.SZABLAK) (03/30/89)
/* * mdbexp.c - MINIX expresion parser * * Written by Bruce D. Szablak * * This free software is provided for non-commerical use. No warrantee * of fitness for any use is implied. You get what you pay for. Anyone * may make modifications and distribute them, but please keep this header * in the distribution. NOTE: A PORTION OF THIS FILE IS DERIVED FROM THE * SOURCE TO ANM.C WHOSE AUTHOR IS UNKNOWN TO ME (AST?). BEWARE THAT * OTHER RESTRICTIONS MAY APPLY. */ #include <ctype.h> #include <setjmp.h> #include <stdio.h> #include "user.h" #include "out.h" extern jmp_buf mainlp; extern curpid; int nsyms; struct outname *nbufp = NULL; long value(), strtol(), lookup(), ptrace(); #define idchar(c) (isalpha(c) || isdigit(c) || (c) == '_') char * addr_to_name(rel_addr, off_p) long rel_addr, *off_p; { register int i, l = 0, r = nsyms; while (l < r) { i = (l + r) >> 1; if (rel_addr < nbufp[i].on_valu) r = i; else if (rel_addr > nbufp[i].on_valu) l = i + 1; else break; } if (l == nsyms || r == 0) { *off_p = rel_addr; return "_start"; } if (rel_addr < nbufp[i].on_valu) i--; *off_p = rel_addr - nbufp[i].on_valu; return nbufp[i].on_mptr; } symbolic(addr, sep) long addr; char sep; { long off; extern long saddr, eaddr; if (addr < saddr || addr > eaddr) { printf("0x%lx%c", addr, sep); return; } fputs(addr_to_name(addr - saddr, &off), stdout); if (off) printf("+0x%lx", off); fputc(sep, stdout); } char * getexp(buf, exp_p, seg_p) char *buf; int *seg_p; long *exp_p; { extern char *skip(); long v = 0L; buf = skip(buf); if ((isalpha(*buf) && (isspace(buf[1]) || buf[1]==';')) || *buf=='\n' || *buf==';' || *buf=='/' || *buf == '!') { *exp_p = 0L; return buf; } v = value(buf, &buf, seg_p); buf = skip(buf); if (*buf == '+') { v += value(skip(buf+1), &buf, seg_p); } else if (*buf == '-') { v -= value(skip(buf+1), &buf, seg_p); } *exp_p = v; return skip(buf); } long reg_addr(s) char *s; { long val; switch (*s++) { case 'a': case 'A': val = 32; break; case 'd': case 'D': val = 0; break; default: goto error; } if (*s >= '0' && *s <= '7') { return val + 4*(*s - '0'); } error: printf("Unknown register: %2.2s\n", s); longjmp(mainlp); } long value(s, s_p, seg_p) char *s, **s_p; int *seg_p; { long k; if (*s == '\'') /* handle character constants here */ { *s_p = s + 2; return s[1]; } if (*s == '-' || isdigit(*s)) { return strtol(s, s_p, 0); } if (*s == '$') { k = reg_addr(s+1); *s_p = s + 3; return ptrace(3, curpid, k, 0L); } return lookup(s, s_p, seg_p); } long lookup(s, s_p, seg_p) char *s, **s_p; int *seg_p; { extern long saddr; char c; int i, l; for (l = 1; idchar(s[l]); ++l ) {} c = s[l]; s[l] = 0; if (strcmp("_start", s) == 0) { *seg_p = T; *(*s_p = s + 6) = c; return saddr; } for (i = 0; i < nsyms; i++) if (strcmp(nbufp[i].on_mptr, s) == 0) { *seg_p = (nbufp[i].on_type & S_TYP) == S_MIN ? T : D; *(*s_p = s + l) = c; return nbufp[i].on_valu + saddr; } printf("%s: symbol not found\n", s); longjmp(mainlp); } /******************END OF ORIGINAL CODE***********************/ /* * The following code is actually a highly edited * version of anm.c - The ACK version of nm * That file's header follows: */ /* @(#)anm.c 1.6 */ /* ** print symbol tables for ** ACK object files ** ** anm [-gopruns] [name ...] */ #define ushort unsigned short long off; char *malloc(); char *realloc(); long s_base[S_MAX]; /* for specially encoded bases */ getsyms(file) char *file; { int compare(); FILE *fi; struct outsect sbuf; struct outhead hbuf; struct outname nbuf; char *cbufp; long fi_to_co; long n; unsigned readcount; int j; fi = fopen(file,"r"); if (fi == NULL) { fprintf(stderr, "db: cannot open %s\n", file); return; } getofmt((char *)&hbuf, SF_HEAD, fi); if (BADMAGIC(hbuf)) { fprintf(stderr, "db: %s-- bad format\n", file); fclose(fi); return; } n = hbuf.oh_nname; if (n == 0) { fprintf(stderr, "db: %s-- no name list\n", file); fclose(fi); return; } if (hbuf.oh_nchar == 0) { fprintf(stderr, "db: %s-- no names\n", file); fclose(fi); return; } if ((readcount = hbuf.oh_nchar) != hbuf.oh_nchar) { fprintf(stderr, "db: string area too big in %s\n", file); exit(2); } /* store special section bases */ if (hbuf.oh_flags & HF_8086) { int i; for (i=0; i<hbuf.oh_nsect; i++) { getofmt((char *)&sbuf, SF_SECT, fi); s_base[i+S_MIN] = (sbuf.os_base>>12) & 03777760; } } if ((cbufp = (char *)malloc(readcount)) == NULL) { fprintf(stderr, "db: out of memory on %s\n", file); exit(2); } fseek(fi, OFF_CHAR(hbuf), 0); if (fread(cbufp, 1, readcount, fi) == 0) { fprintf(stderr, "db: read error on %s\n", file); exit(2); } fi_to_co = (long)cbufp - OFF_CHAR(hbuf); fseek(fi, OFF_NAME(hbuf), 0); nsyms = 0; while (--n >= 0) { getofmt((char *)&nbuf, SF_NAME, fi); if (nbuf.on_foff == 0) continue; /* skip entries without names */ if ((nbuf.on_type&S_EXT)==0) continue; nbuf.on_mptr = (char *)(nbuf.on_foff + fi_to_co); /* adjust value for specially encoded bases */ if (hbuf.oh_flags & HF_8086) { if (((nbuf.on_type&S_ETC) == 0) || ((nbuf.on_type&S_ETC) == S_SCT)) { j = nbuf.on_type&S_TYP; if ((j>=S_MIN) && (j<=S_MAX)) nbuf.on_valu += s_base[j]; } } if (nbufp == NULL) nbufp = (struct outname *)malloc(sizeof(struct outname)); else nbufp = (struct outname *)realloc(nbufp, (nsyms+1)*sizeof(struct outname)); if (nbufp == NULL) { fprintf(stderr, "db: out of memory on %s\n", file); exit(2); } nbufp[nsyms++] = nbuf; } qsort(nbufp, nsyms, sizeof(struct outname), compare); fclose(fi); } compare(p1, p2) struct outname *p1, *p2; { if (p1->on_valu < p2->on_valu) return -1; if (p1->on_valu > p2->on_valu) return 1; return 0; } getofmt(p, s, f) register char *p; register char *s; register FILE *f; { register i; register long l; for (;;) { switch (*s++) { /* case '0': p++; continue; */ case '1': *p++ = getc(f); continue; case '2': i = getc(f); i |= (getc(f) << 8); *((short *)p) = i; p += sizeof(short); continue; case '4': l = (long)getc(f); l |= ((long)getc(f) << 8); l |= ((long)getc(f) << 16); l |= ((long)getc(f) << 24); *((long *)p) = l; p += sizeof(long); continue; default: case '\0': break; } break; } }