[comp.os.minix] mdb fix

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