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