stailey@iris613.gsfc.nasa.gov (Ken Stailey) (03/05/90)
I recently received an upgraded copy of mdb that incorporated "anm.c" to find the symbol tables in ".o" files. This approach is brain-damaged because the libc.a routines would need to be extracted in order to get their symbols. So I have re-written the symbol gathering part to use "nm.c" instead. In order to use this you need a "cv" that preserves the symbol table that the linker "ld" has always made, such as the 1.5.0 1.5.3 or "sym_cv" or the "ld" that generates real ST MINIX executables. Do not use the "cc -s" option or "strip" on the executable until you are done with debugging. In order to save net.bandwidth.consumption this post only includes the file "mdbexp.c" which is the only part that I changed from the previous posting. If you need the rest of it either find it on some archive site or mail me a request. ----------------------------------------------------------------------- /* 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. */ #include <sys/types.h> #include <fcntl.h> #include <ctype.h> #include <setjmp.h> #include <a.out.h> #include <stdlib.h> #include <unistd.h> #include <stdio.h> #include "user.h" extern jmp_buf mainlp; extern curpid; int nsyms; struct nlist *nlistp; long value(), lookup(); #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 < nlistp[i].n_value) r = i; else if (rel_addr > nlistp[i].n_value) l = i + 1; else break; } if (l == nsyms || r == 0) { *off_p = rel_addr; return "_start"; } if (rel_addr < nlistp[i].n_value) i--; *off_p = rel_addr - nlistp[i].n_value; return nlistp[i].n_name; } 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 1; } fputs(addr_to_name(addr - saddr, &off), stdout); if (off) printf("+0x%lx", off); fputc(sep, stdout); return 1; } 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); --jrb */ longjmp(mainlp, 1); /* ++jrb */ } 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(nlistp[i].n_name, s) == 0) { *seg_p = (nlistp[i].n_sclass & N_SECT) == N_TEXT ? T : D; *(*s_p = s + l) = c; return nlistp[i].n_value + saddr; } printf("%s: symbol not found\n", s); /* longjmp(mainlp); -- jrb */ longjmp(mainlp, 1); /* ++jrb */ } /******************END OF ORIGINAL CODE***********************/ /* The following code is a hack-up copy of nm(1) */ /* Nm - print name list. Author: Dick van Veen */ /* Dick van Veen: veench@cs.vu.nl */ getsyms(file) char *file; { nm(file); } char io_buf[BUFSIZ]; /* io buffer */ struct exec header; /* header of a.out file */ nm_sort(stbl1, stbl2) struct nlist *stbl1, *stbl2; { int cmp; if ((stbl1->n_sclass & N_SECT) < (stbl2->n_sclass & N_SECT)) cmp = -1; else if ((stbl1->n_sclass & N_SECT) > (stbl2->n_sclass & N_SECT)) cmp = 1; else if (stbl1->n_value < stbl2->n_value) cmp = -1; else if (stbl1->n_value > stbl2->n_value) cmp = 1; else cmp = strncmp(stbl1->n_name, stbl2->n_name, 8); return(cmp); } nm(file) char *file; { int fd; fd = open(file, O_RDONLY); if (fd == -1) { fprintf(stderr, "can't open %s\n", file); return; } if (read_header(fd)) { fprintf(stderr, "%s: no executable file\n", file); close(fd); return; } if (header.a_syms != 0) { nlistp = (struct nlist *) malloc((int) (header.a_syms & 0xFFFF)); if (nlistp == NULL) { fprintf(stderr, "%s: can't allocate symbol table\n", file); return; } if (read(fd, (char *) nlistp, (int) (header.a_syms & 0xFFFF)) != (int) (header.a_syms & 0xFFFF)) { fprintf(stderr, "%s: can't read symbol table\n", file); return; } nsyms = (int) header.a_syms / sizeof(struct nlist); qsort(nlistp, nsyms, sizeof(struct nlist), nm_sort); close(fd); } } read_header(fd) int fd; { if (read(fd, (char *) &header, sizeof(struct exec)) != sizeof(struct exec)) return(1); if (BADMAG(header)) return(1); lseek(fd, A_SYMPOS(header), SEEK_SET); return(0); } ---------------------------------------------------------------------------- INET stailey@iris613.gsfc.nasa.gov UUCP {backbone}!dftsrv!iris613!stailey