static char rcsid[] = "$Header: setup.c,v 800.2 85/10/08 14:31:48 root Exp $";
static char sccsid[]="%W% %Y% %Q% %G%";

/*
 * adb - routines to read a.out+core at startup
 */
#include "defs.h"
#include "machine.h"

#ifdef	KERNEL
/* Use the kernels own data structures. */
#include "../../h/stat.h"
#else	KERNEL
/*
 * Use standard data structures. Since
 * lots of things adb uses vary conditionally
 * with KERNEL makefile defines, making
 * adb this way will probably result in
 * cdb (cretinous debugger) syndrome. (bog)
 */
#include <sys/stat.h>
#endif	KERNEL

STRING		symfil = "a.out";

STRING		corfil = "core";

#undef ctob
/*
 * Save computrons
 */
#define ctob(c)			((c) << U_PGSHIFT)
/*
 * #define ctob(c)		((c)*u.u_pagesize)
 */

setsym()
{
	fsym = getfile(symfil, 1);
	txtmap.ufd = fsym;
	if( fsym > 0 )
		printf("%s file = %s\n", SYMNAME, symfil);
	if (read(fsym, (char *)&txthdr, sizeof txthdr) != sizeof txthdr ||
	    N_BADMAG(txthdr)) {
		txtmap.e1 = MAXFILE;
		return;
	}
#ifdef s32
	{
		/*
		 * So that the kernel debugger will work most
		 * kernel executable files have the symbol table
		 * size (ssize) added into the data segment size
		 * (dsize) so that they will be loaded into core
		 * by the bootstrap; in this case the size of the
		 * symbol table is also copied into the first
		 * longword of data space with the most significant
		 * bit set.  We check for this condition here and
		 * subtract out ssize from dsize so SYMPOS will
		 * give us the correct value.
		 */
		long slen;

#define filhdr txthdr
		lseek(fsym, (long)(DATAPOS), 0);
		if (read(fsym, (char *)&slen, sizeof(slen)) == sizeof(slen) &&
		    slen == (txthdr.ssize|0x80000000))
			txthdr.dsize -= txthdr.ssize;
		lseek(fsym, (long)sizeof(txthdr), 0);
	}
	if (txthdr.entry < U_VA)
		txtmap.b1 = txthdr.entry;
	else
		txtmap.b1 = U_VA;
#else s32
	txtmap.b1 = txthdr.entry;
#endif s32
	txtmap.f1 = N_TXTOFF(txthdr);
#ifdef ADB_DEBUG
	if (adbdebug)
	{
		fprintf(stderr,"Magic: 0%o\n", txthdr.fmagic);
		fprintf(stderr,"Text:  0%o\n", txthdr.tsize);
		fprintf(stderr,"Data:  0%o\n", txthdr.dsize);
		fprintf(stderr,"Entry: 0%o\n", txthdr.entry);
	}
#endif ADB_DEBUG
	switch (txthdr.fmagic) {

	case OMAGIC:
	case FMAGIC:
		txtmap.b2 = datbas = txtmap.b1;
		txtmap.e1 = txtmap.b1 + txthdr.tsize + txthdr.dsize;
		txtmap.e2 = txtmap.b2 + txthdr.tsize + txthdr.dsize;
		txtmap.f2 = N_TXTOFF(txthdr);
		break;

	case NMAGIC:
	case IMAGIC:
	case ZMAGIC:
		txtmap.e1 = txtmap.b1 + txthdr.tsize;
		txtmap.b2 = datbas = txtmap.b1 + round(txthdr.tsize,TXTRNDSIZ);
		txtmap.e2 = datbas + txthdr.dsize;
		txtmap.f2 = N_TXTOFF(txthdr) + txthdr.tsize;
	}
	txtsiz = txthdr.tsize;
	datsiz = txthdr.dsize;
	entrypt = txthdr.entry;
	symbas = N_SYMOFF(txthdr);

/* read in symbol table from b.out file */
	setupsym(txthdr.ssize);
	symset();
}

setcor()
{

	fcor = datmap.ufd = getfile(corfil,2);
	if( fcor > 0 )
		printf("core file = %s\n", corfil);
	if (fcor != -1 && INKERNEL(txthdr.entry)) {
		struct stat stb;

		fstat(fcor, &stb);
		datmap.b1 = 0;
		datmap.e1 = -1;
/*		if ((stb.st_mode&S_IFMT) == S_IFREG)
			datmap.b1 = 0x80000000;
 */		return;
	}

	/*
	 * Read the first part of the core file --
	 * the U. page of the image.
	 */
	if (read(fcor, (char *)&u, UPAGESZ ) == UPAGESZ )
	{
#ifdef ADB_DEBUG
		register int i;
		if (adbdebug)
		{
			fprintf(stderr,"u.u_usrtop=0x%x\n",u.u_usrtop);
			fprintf(stderr,
			"ar0 read as 0x%x, changing to 0x%x (u at 0x%x)\n",
				u.u_ar0,
#ifdef BIGUPAGE
				/*
				 * Should use ptob(UPAGENUM) (cf h/vmmac.h),
				 * but we get extra cruft in 8.2 release by
				 * doing that.  Rather that clean up the
				 * include file at this late date, we'll get
				 * to it in the next release.  Yeah.  That's
				 * the ticket.
				 */
				((ADDR)u.u_ar0 - (UPAGENUM)*(NBPG)) + (ADDR)&u,
#else  BIGUPAGE
				((ADDR)u.u_ar0 & (UPAGESZ-1)) + (ADDR)&u,
#endif BIGUPAGE
				(ADDR)&u);
			fprintf(stderr,"core was from \"%s\"\n",u.u_comm);
			fprintf(stderr,"\n\nUser stack in bits:\n");
			for (i=UPAGESZ-16; i>sizeof(struct user); i-=16)
			{
			  fprintf(stderr,"(@0x%X) %X: %10x %10x %10x %10x\t|\t",
				udot.UU+i,
				0xfd000+i,
				(((unsigned char)udot.UU[i+0])<<24) |
				(((unsigned char)udot.UU[i+1])<<16) |
				(((unsigned char)udot.UU[i+2])<<8)  |
				(((unsigned char)udot.UU[i+3])),
				(((unsigned char)udot.UU[i+4])<<24) |
				(((unsigned char)udot.UU[i+5])<<16) |
				(((unsigned char)udot.UU[i+6])<<8)  |
				(((unsigned char)udot.UU[i+7])),
				(((unsigned char)udot.UU[i+8])<<24) |
				(((unsigned char)udot.UU[i+9])<<16) |
				(((unsigned char)udot.UU[i+10])<<8)  |
				(((unsigned char)udot.UU[i+11])),
				(((unsigned char)udot.UU[i+12])<<24) |
				(((unsigned char)udot.UU[i+13])<<16) |
				(((unsigned char)udot.UU[i+14])<<8)  |
				(((unsigned char)udot.UU[i+15])));
			  fprintf(stderr,"%X: %10x %10x %10x %10x\n",
				0xfd000+i-2,
				(((unsigned char)udot.UU[i-2+0])<<24) |
				(((unsigned char)udot.UU[i-2+1])<<16) |
				(((unsigned char)udot.UU[i-2+2])<<8)  |
				(((unsigned char)udot.UU[i-2+3])),
				(((unsigned char)udot.UU[i-2+4])<<24) |
				(((unsigned char)udot.UU[i-2+5])<<16) |
				(((unsigned char)udot.UU[i-2+6])<<8)  |
				(((unsigned char)udot.UU[i-2+7])),
				(((unsigned char)udot.UU[i-2+8])<<24) |
				(((unsigned char)udot.UU[i-2+9])<<16) |
				(((unsigned char)udot.UU[i-2+10])<<8)  |
				(((unsigned char)udot.UU[i-2+11])),
				(((unsigned char)udot.UU[i-2+12])<<24) |
				(((unsigned char)udot.UU[i-2+13])<<16) |
				(((unsigned char)udot.UU[i-2+14])<<8)  |
				(((unsigned char)udot.UU[i-2+15])));
			}
		}
#endif ADB_DEBUG
		/* What a brutal hack! */
#ifndef BIGUPAGE
		/*
		 * Figure out the OFFSET in the upage of the saved registers,
		 * assuming the upage begins on a UPAGESZ-modular boundary
		 * (i.e. that modular division will work properly)
		 *
		 * This code works, for instance, if UPAGESZ is 0x2000 and
		 * the upage was originally located at fe000 (hypothetical
		 * example, of course...), because fe000 % 2000 == 0.  But
		 * if we were to do a silly thing like move the upage to
		 * fd000 (God knows why ANYONE would want to do THAT :-),
		 * fd000 % 2000 != 0, and this code will break.
		 *
		 * bog 121086
		 */
		u.u_ar0 = (int *)( ( (ADDR) u.u_ar0 & (UPAGESZ-1) ) + (ADDR) &u );
#else  BIGUPAGE
		/*
		 * Avoid the fragility of a modular divide by simply
		 * subtracting the kernel virtual address of the upage of
		 * a running process.  This code is uglier, but always
		 * works.
		 *
		 * bog 121086
		 */
		u.u_ar0 = (int *)( ( (ADDR) u.u_ar0 - (UPAGENUM)*(NBPG)) + (ADDR) &u );
#endif BIGUPAGE

#ifndef s32
		/*
		 * Get the value for usrtop since the core file
		 * may have been generated under a kernel that has
		 * the user stack at a different address.
		 *
		 * If on an s32, then we have already gotten usrtop. Don't
		 * do it again; you will blow up.
		 */
		usrtop = u.u_usrtop;
#endif not s32

		txtsiz = ctob(u.u_tsize); /* S.B. same as exec.tsize, yes? */
		datsiz = ctob(u.u_dsize); /* S.B. same as exec.dsize, yes? */
		stksiz = ctob(u.u_ssize);

		switch (txthdr.fmagic) {

		case OMAGIC:
		case FMAGIC:
			datmap.b1 = txthdr.entry;
			datmap.e1 = txthdr.entry + txtsiz + datsiz;
			datmap.f2 = UPAGESZ + txtsiz + datsiz;
			break;

		case NMAGIC:
		case IMAGIC:
		case ZMAGIC:
			datmap.b1 = txthdr.entry + round(txthdr.tsize, TXTRNDSIZ);
			datmap.e1 = datmap.b1 + datsiz;
			datmap.f2 = UPAGESZ + datsiz;
			break;
		}

		datbas = datmap.b1;
		datmap.f1 = UPAGESZ;
#ifdef s32
		datmap.b2 = ctob( usrtop ) - stksiz;
		datmap.e2 = ctob( usrtop );
#else s32
		datmap.b2 = ctob( U_USRTOP ) - stksiz;
		datmap.e2 = ctob( U_USRTOP );
#endif s32

#ifdef ADB_DEBUG
		if (adbdebug)
		{
			fprintf(stderr,"usrtop: 0x%x\n",usrtop);
			fprintf(stderr,"Magic:  0x%x\n",txthdr.fmagic);
			fprintf(stderr,"Textsize:  0x%x\n",txtsiz);
			fprintf(stderr,"Datasize:  0x%x\n",datsiz);
			fprintf(stderr,"Stacksize: 0x%x\n",stksiz);
			fprintf(stderr,"Datmap shit: (datbas= ~.b1)\n");
			fprintf(stderr,
				"\t1: file offset=0x%x, begin=0x%x, end=0x%x\n",
				datmap.f1, datmap.b1, datmap.e1);
			fprintf(stderr,
				"\t2: file offset=0x%x, begin=0x%x, end=0x%x\n",
				datmap.f2, datmap.b2, datmap.e2);
		}
#endif ADB_DEBUG
		if (txthdr.fmagic && u.u_exdata.ux_mag &&
		    txthdr.fmagic != u.u_exdata.ux_mag)
		{
			datmap.b1 = 0; datmap.e1 = maxfile; datmap.f1 = 0;
			printf(" - warning: bad magic number - are you sure this is a core? ");
		}
		else readregs(fcor);
	}
	else datmap.e1 = maxfile;
}

create(f)
STRING	f;
{
	int	fd;

	if ((fd = creat(f, 0644)) >= 0)
	{
		close(fd);
		return(open(f, wtflag));
	}
	else return(-1);
}

getfile(filnam, cnt)
	char *filnam;
{
	register int fd;

	if (eqstr(filnam, "-"))
		return (-1);
	fd = open(filnam, wtflag);
	if (fd < 0 && argcount > cnt) {
		if (wtflag)
			fd = create(filnam);
		if (fd < 0)
			printf("cannot open `%s'\n", filnam);
	}
	return (fd);
}

setvar()
{

	var[varchk('b')] = datbas;
	var[varchk('d')] = datsiz;
	var[varchk('e')] = txthdr.entry;
	var[varchk('m')] = txthdr.fmagic;
	var[varchk('s')] = stksiz;
	var[varchk('t')] = txtsiz;
}
