xref: /csrg-svn/old/adb/adb.vax/setup.c (revision 16845)
1*16845Ssam static	char sccsid[] = "@(#)setup.c	4.8 (Berkeley) 84/08/05";
23766Sroot /*
33766Sroot  * adb - routines to read a.out+core at startup
43766Sroot  */
53766Sroot #include "defs.h"
6*16845Ssam #include <frame.h>
7*16845Ssam #include <ctype.h>
88927Srrh #include <sys/stat.h>
9*16845Ssam #include <sys/file.h>
10*16845Ssam #include <vax/rpb.h>
113766Sroot 
123766Sroot off_t	datbas;			/* offset of the base of the data segment */
133766Sroot off_t	stksiz;			/* stack size in the core image */
143766Sroot INT	sigcode;	/* belongs in head.h */
153766Sroot 
163766Sroot char	*symfil	= "a.out";
173766Sroot char	*corfil	= "core";
183766Sroot 
193766Sroot setsym()
203766Sroot {
213766Sroot 	off_t loc;
223766Sroot 	struct exec hdr;
233766Sroot 	register struct nlist *sp;
243766Sroot 	int ssiz;
253766Sroot 	char *strtab;
263766Sroot 
273766Sroot 	fsym = getfile(symfil, 1);
283766Sroot 	txtmap.ufd = fsym;
293766Sroot 	if (read(fsym, (char *)&hdr, sizeof hdr) != sizeof hdr ||
303766Sroot 	    N_BADMAG(hdr)) {
313766Sroot 		txtmap.e1 = MAXFILE;
323766Sroot 		return;
333766Sroot 	}
343766Sroot 	filhdr = hdr;
353766Sroot 	loc = filhdr.a_text+filhdr.a_data;
363766Sroot 	txtmap.f1 = txtmap.f2 = N_TXTOFF(filhdr);
373766Sroot 	txtmap.b1 = 0;
383766Sroot 	switch (filhdr.a_magic) {
393766Sroot 
403766Sroot 	case OMAGIC:
413766Sroot 		txtmap.b1 = txtmap.e1 = 0;
423766Sroot 		txtmap.b2 = datbas = 0;
433766Sroot 		txtmap.e2 = loc;
443766Sroot 		break;
453766Sroot 
463766Sroot 	case ZMAGIC:
473766Sroot 	case NMAGIC:
483766Sroot 		txtmap.e1 = filhdr.a_text;
493766Sroot 		txtmap.b2 = datbas = round(filhdr.a_text, PAGSIZ);
503766Sroot 		txtmap.e2 = datbas + filhdr.a_data;
513766Sroot 		txtmap.f2 += txtmap.e1;
523766Sroot 	}
533766Sroot 	loc = N_SYMOFF(filhdr);
543766Sroot 	symtab = (struct nlist *) malloc(filhdr.a_syms);
553766Sroot 	esymtab = &symtab[filhdr.a_syms / sizeof (struct nlist)];
563766Sroot 	if (symtab == NULL)
573766Sroot 		goto nospac;
58*16845Ssam 	lseek(fsym, loc, L_SET);
593766Sroot 	if (filhdr.a_syms == 0)
603766Sroot 		goto nosymt;
613766Sroot 	/* SHOULD SQUISH OUT STABS HERE!!! */
623766Sroot 	if (read(fsym, symtab, filhdr.a_syms) != filhdr.a_syms)
633766Sroot 		goto readerr;
643766Sroot 	if (read(fsym, &ssiz, sizeof (ssiz)) != sizeof (ssiz))
653766Sroot 		goto oldfmt;
663766Sroot 	strtab = (char *) malloc(ssiz);
673766Sroot 	if (strtab == 0)
683766Sroot 		goto nospac;
693766Sroot 	*(int *)strtab = ssiz;
703766Sroot 	ssiz -= sizeof (ssiz);
713766Sroot 	if (read(fsym, strtab + sizeof (ssiz), ssiz) != ssiz)
723766Sroot 		goto readerr;
733766Sroot 	for (sp = symtab; sp < esymtab; sp++)
743766Sroot 		if (sp->n_strx)
753766Sroot 			/* SHOULD PERFORM RANGE CHECK HERE */
763766Sroot 			sp->n_un.n_name = strtab + sp->n_un.n_strx;
773766Sroot nosymt:
783766Sroot 	if (INKERNEL(filhdr.a_entry)) {
793766Sroot 		txtmap.b1 += KERNOFF;
803766Sroot 		txtmap.e1 += KERNOFF;
813766Sroot 		txtmap.b2 += KERNOFF;
823766Sroot 		txtmap.e2 += KERNOFF;
833766Sroot 	}
843766Sroot 	return;
853766Sroot readerr:
863766Sroot 	printf("Error reading symbol|string table\n");
873766Sroot 	exit(1);
883766Sroot nospac:
893766Sroot 	printf("Not enough space for symbol|string table\n");
903766Sroot 	exit(1);
913766Sroot oldfmt:
923766Sroot 	printf("Old format a.out - no string table\n");
933766Sroot 	exit(1);
943766Sroot }
953766Sroot 
963766Sroot setcor()
973766Sroot {
983766Sroot 
993766Sroot 	fcor = datmap.ufd = getfile(corfil,2);
1006416Sroot 	if (kernel && fcor != -1 && INKERNEL(filhdr.a_entry)) {
1013766Sroot 		struct stat stb;
1023766Sroot 
1033779Sroot 		kcore = 1;
1043766Sroot 		fstat(fcor, &stb);
1053766Sroot 		datmap.b1 = 0;
1063766Sroot 		datmap.e1 = -1;
1073778Sroot 		if (kernel == 0 && (stb.st_mode & S_IFREG))
1083778Sroot 			datmap.b1 = 0x80000000;
1093777Sroot 		lookup("_Sysmap");
1103777Sroot 		sbr = cursym->n_value;
1113777Sroot 		lookup("_Syssize");
1123777Sroot 		slr = cursym->n_value;
1133777Sroot 		printf("sbr %X slr %X\n", sbr, slr);
1146416Sroot 		lookup("_masterpaddr");
115*16845Ssam 		physrw(fcor, cursym->n_value&~0x80000000, &masterpcbb, 1);
1166416Sroot 		masterpcbb = (masterpcbb&PG_PFNUM)*512;
1173777Sroot 		getpcb();
118*16845Ssam 		findstackframe();
1193766Sroot 		return;
1203766Sroot 	}
1213766Sroot 	if (read(fcor, (char *)&u, ctob(UPAGES))!=ctob(UPAGES) ||
1223766Sroot 	   !INUDOT(u.u_pcb.pcb_ksp) || !INSTACK(u.u_pcb.pcb_usp)) {
1233766Sroot 		datmap.e1 = MAXFILE;
1243766Sroot 		return;
1253766Sroot 	}
1263766Sroot 	signo = u.u_arg[0];
1273766Sroot 	sigcode = u.u_code;
1283766Sroot 	filhdr.a_text = ctob(u.u_tsize);
1293766Sroot 	filhdr.a_data = ctob(u.u_dsize);
1303766Sroot 	stksiz = ctob(u.u_ssize);
1313766Sroot 	switch (filhdr.a_magic) {
1323766Sroot 
1333766Sroot 	case OMAGIC:
1343766Sroot 		datmap.b1 = 0;
1353766Sroot 		datmap.e1 = filhdr.a_text+filhdr.a_data;
1363766Sroot 		datmap.f2 = ctob(UPAGES) + datmap.e1;
1373766Sroot 		break;
1383766Sroot 
1393766Sroot 	case NMAGIC:
1403766Sroot 	case ZMAGIC:
1413766Sroot 		datmap.b1 = round(filhdr.a_text, PAGSIZ);
1423766Sroot 		datmap.e1 = datmap.b1 + filhdr.a_data;
1433766Sroot 		datmap.f2 = ctob(UPAGES) + filhdr.a_data;
1443766Sroot 		break;
1453766Sroot 	}
1463766Sroot 	datbas = datmap.b1;
1473766Sroot 	datmap.f1 = ctob(UPAGES);
1483766Sroot 	datmap.b2 = MAXSTOR - stksiz;
1493766Sroot 	datmap.e2 = MAXSTOR;
1503766Sroot }
1513766Sroot 
1523777Sroot getpcb()
1533777Sroot {
1543779Sroot 
155*16845Ssam 	lseek(fcor, masterpcbb&~0x80000000, L_SET);
1563777Sroot 	read(fcor, &pcb, sizeof (struct pcb));
1573779Sroot 	pcb.pcb_p0lr &= ~AST_CLR;
1583777Sroot 	printf("p0br %X p0lr %X p1br %X p1lr %X\n",
1593777Sroot 	    pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr);
1603777Sroot }
1613777Sroot 
162*16845Ssam caddr_t	rpb, scb;
163*16845Ssam caddr_t	intstack, eintstack;
164*16845Ssam caddr_t	ustack, eustack;
165*16845Ssam struct	frame *getframe();
166*16845Ssam struct	frame *checkintstack();
167*16845Ssam 
168*16845Ssam /*
169*16845Ssam  * Find the current stack frame when debugging the kernel.
170*16845Ssam  * If we're looking at a crash dump and this was not a ``clean''
171*16845Ssam  * crash, then we must search the interrupt stack carefully
172*16845Ssam  * looking for a valid frame.
173*16845Ssam  */
174*16845Ssam findstackframe()
175*16845Ssam {
176*16845Ssam 	char *panicstr, buf[256];
177*16845Ssam 	register struct frame *fp;
178*16845Ssam 	caddr_t addr;
179*16845Ssam 	register char *cp;
180*16845Ssam 	int mask;
181*16845Ssam 
182*16845Ssam 	if (lookup("_panicstr") == 0)
183*16845Ssam 		return;
184*16845Ssam 	lseek(fcor, cursym->n_value&~0x80000000, L_SET);
185*16845Ssam 	read(fcor, &panicstr, sizeof (panicstr));
186*16845Ssam 	if (panicstr == 0)
187*16845Ssam 		return;
188*16845Ssam 	lseek(fcor, ((off_t)panicstr)&~0x80000000, L_SET);
189*16845Ssam 	read(fcor, buf, sizeof (buf));
190*16845Ssam 	for (cp = buf; cp < &buf[sizeof (buf)] && *cp; cp++)
191*16845Ssam 		if (!isascii(*cp) || !isprint(*cp))
192*16845Ssam 			*cp = '?';
193*16845Ssam 	if (*cp)
194*16845Ssam 		*cp = '\0';
195*16845Ssam 	printf("panic: %s\n", buf);
196*16845Ssam 	/*
197*16845Ssam 	 * After a panic, look at the top of the rpb stack to
198*16845Ssam 	 * find a stack frame.  If this was a clean crash,
199*16845Ssam 	 * i.e. one which left the interrupt and kernel stacks
200*16845Ssam 	 * in a reasonable state, then we should find a pointer
201*16845Ssam 	 * to the proper stack frame here (at location scb-4).
202*16845Ssam 	 * If we don't find a reasonable frame here, then we
203*16845Ssam 	 * must search down through the interrupt stack.
204*16845Ssam 	 */
205*16845Ssam 	intstack = lookup("_intstack")->n_value;
206*16845Ssam #define	NISP	3			/* from locore.s */
207*16845Ssam 	eintstack = intstack + NISP*NBPG;
208*16845Ssam 	rpb = lookup("_rpb")->n_value;
209*16845Ssam 	scb = lookup("_scb")->n_value;
210*16845Ssam 	lookup("_u");
211*16845Ssam 	ustack = cursym->n_value + (int)&((struct user *)0)->u_stack[0];
212*16845Ssam 	eustack = cursym->n_value + ctob(UPAGES);
213*16845Ssam 	physrw(fcor, ((int)scb - sizeof (caddr_t))&~0x80000000, &addr, 1);
214*16845Ssam 	fp = getframe(fcor, addr);
215*16845Ssam 	if (fp == 0)
216*16845Ssam 		fp = checkintstack();
217*16845Ssam 	/* search kernel stack? */
218*16845Ssam 	if (fp == 0) {
219*16845Ssam 		printf("can't locate stack frame\n");
220*16845Ssam 		return;
221*16845Ssam 	}
222*16845Ssam 	/* probably shouldn't clobber pcb, but for now this is easy */
223*16845Ssam 	pcb.pcb_fp = addr;
224*16845Ssam 	pcb.pcb_pc = fp->fr_savpc;
225*16845Ssam 	pcb.pcb_ap = addr + sizeof (struct frame) + fp->fr_spa;
226*16845Ssam 	for (mask = fp->fr_mask; mask; mask >>= 1)
227*16845Ssam 		if (mask & 01)
228*16845Ssam 			pcb.pcb_ap += sizeof (caddr_t);
229*16845Ssam }
230*16845Ssam 
231*16845Ssam /*
232*16845Ssam  * Search interrupt stack for a valid frame.
233*16845Ssam  */
234*16845Ssam struct frame *
235*16845Ssam checkintstack(fcor)
236*16845Ssam {
237*16845Ssam 	char stack[NISP*NBPG];
238*16845Ssam 	off_t off = vtophys(intstack);
239*16845Ssam 	struct frame *fp;
240*16845Ssam 	register caddr_t addr;
241*16845Ssam 
242*16845Ssam 	if (off == -1 || lseek(fcor, off, L_SET) != off ||
243*16845Ssam 	    read(fcor, stack, sizeof (stack)) != sizeof (stack))
244*16845Ssam 		return ((struct frame *)0);
245*16845Ssam 	addr = eintstack;
246*16845Ssam 	do {
247*16845Ssam 		addr -= sizeof (caddr_t);
248*16845Ssam 		fp = (struct frame *)&stack[addr - intstack];
249*16845Ssam 	} while (addr >= intstack + sizeof (struct frame) &&
250*16845Ssam 	    !checkframe(fp));
251*16845Ssam 	return (addr < intstack+sizeof (struct frame) ? (struct frame *)0 : fp);
252*16845Ssam }
253*16845Ssam 
254*16845Ssam /*
255*16845Ssam  * Get a stack frame and verify it looks like
256*16845Ssam  * something which might be on a kernel stack.
257*16845Ssam  */
258*16845Ssam struct frame *
259*16845Ssam getframe(fcor, fp)
260*16845Ssam 	int fcor;
261*16845Ssam 	caddr_t fp;
262*16845Ssam {
263*16845Ssam 	static struct frame frame;
264*16845Ssam 	off_t off;
265*16845Ssam 
266*16845Ssam 	if (!kstackaddr(fp) || (off = vtophys(fp)) == -1)
267*16845Ssam 		return ((struct frame *)0);
268*16845Ssam 	if (lseek(fcor, off, L_SET) != off ||
269*16845Ssam 	    read(fcor, &frame, sizeof (frame)) != sizeof (frame))
270*16845Ssam 		return ((struct frame *)0);
271*16845Ssam 	if (!checkframe(&frame))
272*16845Ssam 		return ((struct frame *)0);
273*16845Ssam 	return (&frame);
274*16845Ssam }
275*16845Ssam 
276*16845Ssam /*
277*16845Ssam  * Check a call frame to see if it's ok as
278*16845Ssam  * a kernel stack frame.
279*16845Ssam  */
280*16845Ssam checkframe(fp)
281*16845Ssam 	register struct frame *fp;
282*16845Ssam {
283*16845Ssam 
284*16845Ssam 	if (fp->fr_handler != 0 || fp->fr_s == 0)
285*16845Ssam 		return (0);
286*16845Ssam 	if (!kstackaddr(fp->fr_savap) || !kstackaddr(fp->fr_savfp))
287*16845Ssam 		return (0);
288*16845Ssam 	return (within(fp->fr_savpc, txtmap.b1, txtmap.e1));
289*16845Ssam }
290*16845Ssam 
291*16845Ssam /*
292*16845Ssam  * Check if an address is in one of the kernel's stacks:
293*16845Ssam  * interrupt stack, rpb stack (during restart sequence),
294*16845Ssam  * or u. stack.
295*16845Ssam  */
296*16845Ssam kstackaddr(addr)
297*16845Ssam 	caddr_t addr;
298*16845Ssam {
299*16845Ssam 
300*16845Ssam 	return (within(addr, intstack, eintstack) ||
301*16845Ssam 	    within(addr, rpb + sizeof (struct rpb), scb) ||
302*16845Ssam 	    within(addr, ustack, eustack));
303*16845Ssam }
304*16845Ssam 
3053766Sroot create(f)
3063766Sroot 	char *f;
3073766Sroot {
3083766Sroot 	register int fd;
3093766Sroot 
3103766Sroot 	fd = creat(f, 0644);
3113766Sroot 	if (fd < 0)
3123766Sroot 		return (-1);
3133766Sroot 	close(fd);
3143766Sroot 	return (open(f, wtflag));
3153766Sroot }
3163766Sroot 
3173766Sroot getfile(filnam, cnt)
3183766Sroot 	char *filnam;
3193766Sroot {
3203766Sroot 	register int fsym;
3213766Sroot 
3223766Sroot 	if (eqstr(filnam, "-"))
3233766Sroot 		return (-1);
3243766Sroot 	fsym = open(filnam, wtflag);
3253766Sroot 	if (fsym < 0 && xargc > cnt) {
3263766Sroot 		if (wtflag)
3273766Sroot 			fsym = create(filnam);
3283766Sroot 		if (fsym < 0)
3293766Sroot 			printf("cannot open `%s'\n", filnam);
3303766Sroot 	}
3313766Sroot 	return (fsym);
3323766Sroot }
3333766Sroot 
3343766Sroot setvar()
3353766Sroot {
3363766Sroot 
3373766Sroot 	var[varchk('b')] = datbas;
3383766Sroot 	var[varchk('d')] = filhdr.a_data;
3393766Sroot 	var[varchk('e')] = filhdr.a_entry;
3403766Sroot 	var[varchk('m')] = filhdr.a_magic;
3413766Sroot 	var[varchk('s')] = stksiz;
3423766Sroot 	var[varchk('t')] = filhdr.a_text;
3433766Sroot }
344