Xinu7/src/cmd/pm/pm.c

Compare this file to the similar file:
Show the results in this format:

#include "pm.h"

/*
 *	pm - a post mortem analyzer of core11 files
 *	that come from the Xinu operating system.
 *
 *	Chris Kent - October 1981, lots of changes
 *	by D. Comer & Droms 82-86
 */

/*
 *	Arguments/options:
 *
 *		pm [-t] [-p] [-s] [ objfile [ corefile ] ]
 *
 *	where objfile is the text that was downloaded, and corefile
 *	is the result of upload. Defaults are a.out and core11.
 *
 */

#define		INTVECTOR	01000	/* # bytes of interrupt vectors	*/

char		*corefile;
FILE		*corefd;	/* the core image			 */
char		*txtfile;
FILE		*txtfd;		/* the system				 */
short		*text;		/* pointer to system image		 */
short		*core;		/* pointer to core image		 */
struct nlist	*symtab;	/* symbol table space 			 */
struct nlist	*esymtab;	/* end of same				 */
struct nlist	*ssymtab;	/* sorted external symbol table space	 */
struct nlist	*essymtab;	/* end of same				 */
struct core11	c_header;	/* registers at time of dump		 */
struct exec	a_out;		/* a.out header				 */
int		errflg;		/* global error indicator		 */
int		allopts, popt, sopt, topt;	/* option indicators	 */
int		verbose;	/* print verbose description or not	 */
char   *vers;			/* pointer to version string		 */
long   clktim;			/* pointer to time variable		 */
struct pentry	*proctb;	/* pointer to image of proc table	 */
struct qent	*Q;		/*    "     "   "   "  q		 */
struct sentry	*semtab;	/*    "     "   "   "  semaphore table	 */
struct tty	*tptr;		/*    "     "   "   "  tty structures	 */
short  currpid;			/* current process id number		 */
main(argc, argv)
int	argc;
char	*argv[];
{

	int		FirstDiff, FirstIDiff;
	register INT	*TextPtr, *CorPtr;
	INT		base;
	char		*pidname;
	char		datestr[80];

	register	i, j;

	setup(argc, argv);	/* open files, etc. */

	/* 
	 * compare the core image text segment and the 
	 * original text segment from the system
	 */
			
	printf("Postmortum for Xinu version %s\n", vers);
	if (clktim > SECPERHR) {
		ascdate(ut2ltim(clktim), datestr);
		printf("Clock was stopped on %s\n",
			datestr);
	}
	FirstDiff = FirstIDiff = 0;
	TextPtr = text;
	CorPtr = core;
	while((char *)CorPtr - (char *)core < INTVECTOR) {
		if(*( (int *)CorPtr) != *( (int *)TextPtr) ) {
			register s, c;

			if(!FirstIDiff){
				printf("Interrupt vectors changed:\n");
				printf("\t\tProgram\t\tCore\n");
				FirstIDiff = 1;
			}
			s = *( (int *)TextPtr);
			c = *( (int *)CorPtr);
			printf("%07o:\t%07o/%04o\t%07o/%04o\n",
			   ((char *)CorPtr - (char *)core),
			   s&0xffff, (s>>16)&0xffff,
			   c&0xffff, (c>>16)&0xffff);
		}
		TextPtr += 2;			/* move past pc & ps	*/
		CorPtr += 2;
	}

	while((char *)CorPtr - (char *)core < a_out.a_text){
		if(*CorPtr != *TextPtr){
			register s, c;

			if(!FirstDiff){
				printf("Text has been changed:\n");
				printf("\t\tProgram\tCore\n");
				FirstDiff = 1;
			}
			s = (int) *TextPtr;
			c = (int) *CorPtr;
			printf("%07o:\t%07o\t%07o\n",
			  ((char *)CorPtr - (char *)core), s&0xffff, c&0xffff);
			/* would be nice to do opcode lookup here */
		}
		TextPtr++;CorPtr++;
	}
	
	/*
	 *	current process info
	 */

	if (currpid<0 || currpid>NPROC) {
		printf("Invalid current process id (currpid==%d)\n",
			currpid);
	} else {
		pidname = proctb[currpid].pname;
		printf("process # %d ( %s ) was running\n", currpid, pidname);
		printf("\tat priority %d ", proctb[currpid].pprio);
		if (	((unsigned)c_header.c_regs[SP]) <
			((unsigned)proctb[currpid].plimit) )
			printf("Stack has OVERFLOWED actual=0%o, limit=0%o\n",
				((unsigned)c_header.c_regs[SP]),
				((unsigned)proctb[currpid].plimit) );
		else
			printf("stack is currently %d words long\n", 
			(proctb[currpid].pbase-c_header.c_regs[SP])/2);
		printf("\tstack range: %0o to %0o\n",
			0177777&proctb[currpid].plimit,
			0177777&proctb[currpid].pbase);
		printregs(c_header.c_regs);
		printf("traceback:\n\n");
		printtrace(c_header.c_regs, proctb[currpid].pbase, currpid);
	}

	if(allopts || popt)
		procdump(currpid);

	if(allopts || sopt)
		semdump();

	if(allopts || topt)
		ttydump();
}

/*
 *	dump the proc table
 */

procdump(currpid)
{

	char		*pidname;
	register int	i;


	for(i = 0; i < NPROC; i++){
		if(i == currpid)
			continue;
		pidname = proctb[i].pname;
		printf("\nprocess # %d ( %s ):\tstate=", i, pidname);
		switch(proctb[i].pstate){
		case PRFREE:
			printf("free\n");
			continue;
		case PRREADY:
			printf("ready\n");
			break;
		case PRCURR:	/* shouldn't happen! */
			printf("CURRENTLY RUNNING???\n");
			break;
		case PRSUSP:
			printf("suspended\n");
			break;
		case PRWAIT:
			printf("waiting on semaphore %d\n", proctb[i].psem);
			break;
		case PRSLEEP:
			printf("sleeping\n");
			break;
		case PRRECV:
			printf("receiving\n");
			break;
		case PRTRECV:
			printf("timing recv.\n");
			break;
		default:
			printf("garbage state 0%o\n", proctb[i].pstate&0xff);
		}
		if (proctb[i].pstate == PRFREE)
			continue;
		printf("\tat priority %d ", proctb[i].pprio);
		printf("stack is %d words long\n", 
			(proctb[i].pbase - proctb[i].pregs[SP])/2);
		printf("\tstack range: %0o to %0o\n",
			0177777&proctb[i].plimit,
			0177777&proctb[i].pbase);
		printregs(proctb[i].pregs);
		printf("traceback:\n\n");
		printtrace(proctb[i].pregs, proctb[i].pbase, i);
		printf("\n");
	}
}

/*
 *	dump the semaphore table and queues
 */

semdump()
{
	short		qptr;
	register int	i, j;
	
	printf("\nSemaphores:\n\n");
	for(i = 0; i < NSEM; i++){
		if (semtab[i].sstate == SFREE)
			continue;
		printf("semaphore # %d : ", i);
		if (semtab[i].sstate != SUSED) {
			printf("garbage state 0%o\n",
				semtab[i].sstate&0xff);
			continue;
		}
		printf("count is %d\n", semtab[i].semcnt);
		if(Q[semtab[i].sqhead].qnext < NPROC) {
			printf("\tqueued proc(s) are: ");
			qptr = semtab[i].sqhead; 
			j = 0;
			do {
				printf("%d ", Q[qptr].qnext);
				qptr = Q[qptr].qnext;
				j++;
			} while(Q[qptr].qnext < NPROC && j<=NPROC );
			if (Q[qptr].qnext != semtab[i].sqtail)
				printf("...QUEUE MALFORMED");
			printf("\n\t%d proc%s actually on queue\n", j,
				j!=1?"s":"");
		}
	}
}

/*
 * routines to print contents of Xinu IO control block
 */
char	*unctrl[]	= {	/* unctrl codes for ttys		*/
	"^@", "^A", "^B", "^C", "^D", "^E", "^F", "^G", "^H", "^I", "^J", "^K",
	"^L", "^M", "^N", "^O", "^P", "^Q", "^R", "^S", "^T", "^U", "^V", "^W",
	"^X", "^Y", "^Z", "^[", "^\\", "^]", "^~", "^_",
	" ", "!", "\"", "#", "$",  "%", "&", "'", "(", ")", "*", "+", ",", "-",
	".", "/", "0",  "1", "2",  "3", "4", "5", "6", "7", "8", "9", ":", ";",
	"<", "=", ">",  "?", "@",  "A", "B", "C", "D", "E", "F", "G", "H", "I",
	"J", "K", "L",  "M", "N",  "O", "P", "Q", "R", "S", "T", "U", "V", "W",
	"X", "Y", "Z",  "[", "\\", "]", "^", "_", "`", "a", "b", "c", "d", "e",
	"f", "g", "h",  "i", "j",  "k", "l", "m", "n", "o", "p", "q", "r", "s",
	"t", "u", "v",  "w", "x",  "y", "z", "{", "|", "}", "~", "^?"
};
ttydump()
{
	register int i;

	for (i=0 ; i<Ntty ; i++)
		tty1dmp(i);
}
tty1dmp(ttynum)
int ttynum;
{
	int len;
	int i;
	struct tty *tp;

	tp = (struct tty *) (
		(unsigned)(tptr) +
		(unsigned)(ttynum* (sizeof(struct tty) - 2) ) );
		/* adjusted for VAX sizes */
	printf("\nTty device %d CSR at 0%o\n",
		ttynum, (*( (short *)(( (char *)(&tp->ifullc))+1))) &0xffff);
		/* actually tp->ioaddr, but Vax aligns differently */
        printf("INPUT -- tail at %d head at %d sem # %d value %d\n",
		tp->itail,tp->ihead,tp->isem,i = semtab[tp->isem].semcnt);
	if(i < 0)
		i = 0;
	else if(i > IBUFLEN)
		i = IBUFLEN;
	ioqdump(tp->itail,i,IBUFLEN,tp->ibuff);
        printf("OUTPUT -- tail at %d head at %d sem # %d value %d\n",
		tp->otail,tp->ohead,tp->osem,i = semtab[tp->osem].semcnt);
	i = OBUFLEN - i;
	if(i < 0)
		i = 0;
	else if(i > OBUFLEN)
		i = OBUFLEN;
	ioqdump(tp->otail,i,OBUFLEN,tp->obuff);
}

ioqdump(start,len,maxlen,buff)
short start,len,maxlen;
char *buff;
{
	register int i;

        for(i=start; len>0; len--){
                if(buff[i]&0200)printf("M-");
                printf("%s", unctrl[buff[i]&0177]);
		if(++i >= maxlen)
			i = 0;
        }
	printf("\n");
}