|
|
coherent
/*
* A debugger.
* Initialisation, command line parsing.
*/
#include <stdio.h>
#include <ctype.h>
#include <canon.h>
#include "trace.h"
#if NOUT
#include <n.out.h>
#else
#include <l.out.h>
#endif
#include <sys/proc.h>
#include <signal.h>
#include <sys/uproc.h>
main(argc, argv)
char **argv;
{
initialise();
setup(argc, argv);
signal(SIGINT, &armsint);
signal(SIGQUIT, SIG_IGN);
process();
}
/*
* Leave.
*/
leave()
{
killc();
exit(0);
}
/*
* Initialise.
*/
initialise()
{
register int i;
for (i=0; i<NSEGM; i++)
strcpy(&segform[i][0], "aw");
strcpy(&segform[1][0], "ai");
bptinit();
}
/*
* Setup arguments.
*/
setup(argc, argv)
char **argv;
{
register char *cp;
register int c;
register int t;
register int u;
register int tflag;
t = '\0';
tflag = 0;
for (; argc>1; argc--, argv++) {
cp = argv[1];
if (*cp++ != '-')
break;
while ((c=*cp++) != '\0') {
switch (c) {
case 'c':
case 'd':
case 'e':
case 'f':
case 'k':
case 'o':
if (t != '\0')
usage();
t = c;
continue;
case 'h':
hflag = 1;
continue;
case 'r':
rflag = 1;
continue;
case 's':
sflag = 1;
continue;
case 't':
tflag = 1;
continue;
default:
usage();
}
}
}
switch (t) {
case '\0':
switch (argc) {
case 1:
setlout("l.out", 3);
setcore("core");
break;
case 2:
setlout(argv[1], 3);
break;
case 3:
setlout(argv[1], 3);
setcore(argv[2]);
break;
default:
usage();
}
break;
case 'c':
switch (argc) {
case 1:
setlout("l.out", 3);
setcore("core");
break;
case 2:
setcore(argv[1]);
break;
case 3:
setlout(argv[1], 3);
setcore(argv[2]);
break;
default:
usage();
}
break;
case 'd':
switch (argc) {
case 1:
setlout("/coherent", 3);
setdump("/dev/dump");
break;
case 3:
setlout(argv[1], 3);
setdump(argv[2]);
break;
default:
usage();
}
break;
case 'e':
if (argc < 2)
usage();
setlout(argv[1], 3);
if (startup(&argv[1], NULL, NULL, 0)==0 || shiftup()==0)
leave();
break;
case 'f':
fflag = 1;
switch (argc) {
case 2:
setfile(argv[1]);
break;
case 3:
setlout(argv[1], 1);
setfile(argv[2]);
break;
default:
usage();
}
break;
case 'k':
switch (argc) {
case 1:
setlout("/coherent", 1);
setkmem("/dev/mem");
break;
case 2:
setkmem(argv[1]);
break;
case 3:
setlout(argv[1], 1);
setkmem(argv[2]);
break;
default:
usage();
}
break;
case 'o':
switch (argc) {
case 1:
setlout("l.out", 3);
break;
case 2:
setlout(argv[1], 3);
break;
case 3:
setlout(argv[1], 1);
setlout(argv[2], 2);
break;
default:
usage();
}
}
if (tflag) {
if ((u=open("/dev/tty", 2)) < 0)
panic("Cannot open /dev/tty");
dup2(u, 0);
dup2(u, 1);
dup2(u, 2);
}
}
/*
* Generate a usage message.
*/
usage()
{
panic("Usage: db [-cdefort] [object file] [auxiliary file]");
}
/*
* Catch and flag interrupts.
*/
armsint()
{
signal(SIGINT, &armsint);
intflag++;
}
/*
* Check for interrupts and clear flag.
*/
testint()
{
register int n;
if ((n=intflag) != 0)
printe("Interrupt");
intflag = 0;
return (n);
}
/*
* Assume the file, `np', is the name of an l.out. If the bottom bit
* of the flag is set, set up the symbol table. If the next bit is set,
* set up segmentation for the l.out.
*/
setlout(np, f)
char *np;
{
struct ldheader ldh;
lfp = openfil(np, (f&2) ? rflag : 1);
if (fread(&ldh, sizeof(ldh), 1, lfp) != 1)
panic("Cannot read object file");
canlout(&ldh);
if (ldh.l_magic != L_MAGIC)
panic("Bad object file");
objflag = 1;
if ((f&1) != 0) {
#if NOUT
sbase = ldh.l_tbase;
#else
sbase = sizeof(ldh);
#endif
sbase += ldh.l_ssize[L_SHRI] + ldh.l_ssize[L_PRVI];
sbase += ldh.l_ssize[L_SHRD] + ldh.l_ssize[L_PRVD];
snsym = ldh.l_ssize[L_SYM] / sizeof(struct ldsym);
if (snsym != 0) {
sfp = lfp;
if (sflag == 0)
readsym(sfp);
}
}
if ((f&2) != 0) {
lfn = np;
setaseg(&ldh);
}
}
/*
* Canonize an l.out header.
*/
canlout(ldp)
struct ldheader *ldp;
{
register int i;
#if NOUT
canshort( ldp->l_magic);
canshort( ldp->l_flag);
canshort( ldp->l_machine);
canshort( ldp->l_tbase);
canlong( ldp->l_entry);
#else
canint( ldp->l_magic);
canint( ldp->l_flag);
canint( ldp->l_machine);
canvaddr( ldp->l_entry);
#endif
for (i=0; i<NLSEG; i++)
#if NOUT
canlong( ldp->l_ssize[i]);
#else
cansize( ldp->l_ssize[i]);
#endif
}
/*
* Read all global symbols into memory.
*/
readsym(fp)
FILE *fp;
{
register int n;
register SYM *sp;
struct ldsym lds;
if ((ssymp=nalloc((int)snsym * sizeof(SYM))) == NULL)
return;
fseek(fp, (long)sbase, 0);
for (n=snsym, sp=ssymp; n--; sp++) {
if (fread(&lds, sizeof(lds), 1, fp) != 1) {
nfree(ssymp);
ssymp = NULL;
return;
}
#if NOUT
canshort( lds.ls_type);
canlong( lds.ls_addr);
#else
canint( lds.ls_type);
canvaddr( lds.ls_addr);
#endif
sp->s_hash = hash(&lds);
sp->s_type = lds.ls_type;
sp->s_sval = lds.ls_addr;
}
}
/*
* Hash a symbol name.
*/
hash(ldp)
struct ldsym *ldp;
{
register int h, n;
register char *cp;
h = 0;
n = CCSSIZE;
cp = ldp->ls_id;
do {
if (*cp != '_')
h += *cp;
if (*cp++ == '\0')
break;
} while (--n);
return (h&0377);
}
/*
* Set up segmentation for a core dump. The registers are also read.
*/
MAP *
smapc( next, start, length, foffs)
MAP *next;
register tvaddr start;
fsize_t length, foffs;
{
return( setsmap( next, start, addr( size( start) + length) - start,
foffs, getf, putf, 1));
}
setcore(np)
char *np;
{
register unsigned i;
register MAP *mp;
register char *cp;
register char *lcp;
register fsize_t siz;
register fsize_t offt;
char ucomm[10];
SR usegs[NUSEG];
cfp = openfil(np, rflag);
fseek(cfp, (long)offset(uproc, u_comm[0]), 0);
if ((cp=lfn)!=NULL && fread(ucomm, sizeof(ucomm), 1, cfp)==1) {
lcp = cp;
while (*cp) {
if (*cp++ == '/')
lcp = cp;
}
if (strncmp(lcp, ucomm, sizeof(ucomm)) != 0)
printr("Core different from object");
}
fseek(cfp, (long)offset(uproc, u_segl[0]), 0);
if (fread(usegs, sizeof(usegs), 1, cfp) != 1)
panic("Bad core file");
USPACE = setsmap(NULL, (fsize_t)0, (fsize_t)UPASIZE, (fsize_t)0,
getf, putf, 1);
mp = clrsmap(DSPACE, endpure);
offt = usegs[0].sr_size;
for (i=1; i<NUSEG; i++) {
if (usegs[i].sr_segp == NULL)
continue;
if ((~usegs[i].sr_flag) & (SRFDUMP|SRFPMAP))
continue;
siz = usegs[i].sr_size;
mp = smapc(mp, usegs[i].sr_base, siz, offt);
offt += siz;
}
if (ISPACE == DSPACE)
ISPACE = mp;
DSPACE = mp;
settrap();
setregs();
}
/*
* Find out fault type.
*/
settrap()
{
int f;
trapstr = "???";
#if PDP11
add = 0724; /* old pdp11 cohos differs from src */
#else
add = offset(uproc, u_signo);
#endif
if (getb(2, (char *)&f, sizeof(f)) == 0) {
printr("Cannot read fault type");
return (0);
}
if (f<=0 || f>NSIG) {
printr("Bad fault type");
return (0);
}
trapstr = signame[f-1];
return (f);
}
/*
* Set up segmentation for an ordinary file.
* This is really easy.
*/
setfile(np)
char *np;
{
lfp = openfil(np, rflag);
DSPACE = setsmap(NULL, (fsize_t)0, (fsize_t)LI, (fsize_t)0,
getf, putf, 0);
ISPACE = DSPACE;
}
/*
* Open the given file. If `rflag' is set, the file is opened for
* read only.
*/
FILE *
openfil(np, rflag)
char *np;
{
register FILE *fp;
if (rflag) {
if ((fp=fopen(np, "r")) != NULL)
return (fp);
} else {
if ((fp=fopen(np, "r+w")) != NULL)
return (fp);
if ((fp=fopen(np, "r")) != NULL) {
printr("%s: opened read only", np);
return (fp);
}
}
panic("Cannot open %s", np);
}
/*
* Initialise an element of a segment map.
*/
MAP *
setsmap(next, base, siz, offt, getf, putf, segi)
MAP *next;
fsize_t base;
fsize_t siz;
fsize_t offt;
int (*getf)();
int (*putf)();
{
register MAP *mp;
mp = (MAP *)nalloc(sizeof(MAP));
mp->m_next = next;
mp->m_base = base;
mp->m_bend = base+siz;
mp->m_offt = offt;
mp->m_getf = getf;
mp->m_putf = putf;
mp->m_segi = segi;
return (mp);
}
/*
* Clear a section of a segment map.
*/
MAP *
clrsmap(mp, np)
register MAP *mp;
register MAP *np;
{
while (mp != np) {
nfree(mp);
mp = mp->m_next;
}
return (mp);
}
/*
* Clear all maps.
*/
clramap()
{
register int n;
n = 0;
if (segmapl[0] == segmapl[1])
segmapl[n++] = NULL;
while (n < NSEGM) {
segmapl[n] = clrsmap(segmapl[n], NULL);
n++;
}
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.