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;
}
}