xref: /csrg-svn/old/dbx/coredump.c (revision 21627)
1*21627Sdist /*
2*21627Sdist  * Copyright (c) 1983 Regents of the University of California.
3*21627Sdist  * All rights reserved.  The Berkeley software License Agreement
4*21627Sdist  * specifies the terms and conditions for redistribution.
5*21627Sdist  */
69661Slinton 
7*21627Sdist #ifndef lint
8*21627Sdist static char sccsid[] = "@(#)coredump.c	5.1 (Berkeley) 05/31/85";
9*21627Sdist #endif not lint
109661Slinton 
1118215Slinton static char rcsid[] = "$Header: coredump.c,v 1.5 84/12/26 10:38:56 linton Exp $";
1218215Slinton 
139661Slinton /*
149661Slinton  * Deal with the core dump anachronism.
159661Slinton  */
169661Slinton 
179661Slinton #include "defs.h"
189661Slinton #include "coredump.h"
199661Slinton #include "machine.h"
209661Slinton #include "object.h"
219661Slinton #include "main.h"
229661Slinton #include <sys/param.h>
239661Slinton #include <sys/dir.h>
249839Slinton #include <machine/psl.h>
259839Slinton #include <machine/pte.h>
269661Slinton #include <sys/user.h>
279661Slinton #include <sys/vm.h>
289839Slinton #include <machine/reg.h>
299661Slinton #include <a.out.h>
309661Slinton 
319661Slinton #ifndef public
329661Slinton #define coredump_readin(m, r, s) coredump_xreadin(&(m), r, &(s))
339661Slinton 
349661Slinton #include "machine.h"
359661Slinton #endif
369661Slinton 
379661Slinton #define MAXSTKADDR (0x80000000 - ctob(UPAGES))	/* highest stack address */
389661Slinton 
399661Slinton typedef struct {
409661Slinton     Address begin;
419661Slinton     Address end;
429661Slinton     Address seekaddr;
439661Slinton } Map;
449661Slinton 
459661Slinton private Map datamap, stkmap;
469661Slinton private File objfile;
479661Slinton private struct exec hdr;
489661Slinton 
499661Slinton /*
5018215Slinton  * Special variables for debugging the kernel.
519661Slinton  */
529661Slinton 
5318215Slinton private integer masterpcbb;
5418215Slinton private integer slr;
5518215Slinton private struct pte *sbr;
5618215Slinton private struct pcb pcb;
5718215Slinton 
5818215Slinton private getpcb ()
599661Slinton {
6018215Slinton     fseek(corefile, masterpcbb & ~0x80000000, 0);
6118215Slinton     get(corefile, pcb);
6218215Slinton     pcb.pcb_p0lr &= ~AST_CLR;
6318215Slinton     printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n",
6418215Slinton 	pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr
6518215Slinton     );
6618215Slinton     setreg(0, pcb.pcb_r0);
6718215Slinton     setreg(1, pcb.pcb_r1);
6818215Slinton     setreg(2, pcb.pcb_r2);
6918215Slinton     setreg(3, pcb.pcb_r3);
7018215Slinton     setreg(4, pcb.pcb_r4);
7118215Slinton     setreg(5, pcb.pcb_r5);
7218215Slinton     setreg(6, pcb.pcb_r6);
7318215Slinton     setreg(7, pcb.pcb_r7);
7418215Slinton     setreg(8, pcb.pcb_r8);
7518215Slinton     setreg(9, pcb.pcb_r9);
7618215Slinton     setreg(10, pcb.pcb_r10);
7718215Slinton     setreg(11, pcb.pcb_r11);
7818215Slinton     setreg(ARGP, pcb.pcb_ap);
7918215Slinton     setreg(FRP, pcb.pcb_fp);
8018215Slinton     setreg(STKP, pcb.pcb_ksp);
8118215Slinton     setreg(PROGCTR, pcb.pcb_pc);
8218215Slinton }
839661Slinton 
8418215Slinton public coredump_getkerinfo ()
8518215Slinton {
8618215Slinton     Symbol s;
8718215Slinton 
8818215Slinton     s = lookup(identname("Sysmap", true));
8918215Slinton     if (s == nil) {
9018215Slinton 	panic("can't find 'Sysmap'");
919661Slinton     }
9218215Slinton     sbr = (struct pte *) (s->symvalue.offset);
9318215Slinton     s = lookup(identname("Syssize", true));
9418215Slinton     if (s == nil) {
9518215Slinton 	panic("can't find 'Syssize'");
9618215Slinton     }
9718215Slinton     slr = (integer) (s->symvalue.offset);
9818215Slinton     printf("sbr %lx slr %lx\n", sbr, slr);
9918215Slinton     s = lookup(identname("masterpaddr", true));
10018215Slinton     if (s == nil) {
10118215Slinton 	panic("can't find 'masterpaddr'");
10218215Slinton     }
10318215Slinton     fseek(
10418215Slinton 	corefile,
10518215Slinton 	datamap.seekaddr + s->symvalue.offset&0x7fffffff - datamap.begin,
10618215Slinton 	0
10718215Slinton     );
10818215Slinton     get(corefile, masterpcbb);
10918215Slinton     masterpcbb = (masterpcbb&PG_PFNUM)*512;
11018215Slinton     getpcb();
11118215Slinton }
11218215Slinton 
11318215Slinton private copyregs (savreg, reg)
11418215Slinton Word savreg[], reg[];
11518215Slinton {
1169661Slinton     reg[0] = savreg[R0];
1179661Slinton     reg[1] = savreg[R1];
1189661Slinton     reg[2] = savreg[R2];
1199661Slinton     reg[3] = savreg[R3];
1209661Slinton     reg[4] = savreg[R4];
1219661Slinton     reg[5] = savreg[R5];
1229661Slinton     reg[6] = savreg[R6];
1239661Slinton     reg[7] = savreg[R7];
1249661Slinton     reg[8] = savreg[R8];
1259661Slinton     reg[9] = savreg[R9];
1269661Slinton     reg[10] = savreg[R10];
1279661Slinton     reg[11] = savreg[R11];
1289661Slinton     reg[ARGP] = savreg[AP];
1299661Slinton     reg[FRP] = savreg[FP];
1309661Slinton     reg[STKP] = savreg[SP];
1319661Slinton     reg[PROGCTR] = savreg[PC];
13218215Slinton }
1339661Slinton 
13418215Slinton /*
13518215Slinton  * Read the user area information from the core dump.
13618215Slinton  */
1379661Slinton 
13818215Slinton public coredump_xreadin(mask, reg, signo)
13918215Slinton int *mask;
14018215Slinton Word reg[];
14118215Slinton int *signo;
14218215Slinton {
14318215Slinton     register struct user *up;
14418215Slinton     register Word *savreg;
14518215Slinton     union {
14618215Slinton 	struct user u;
14718215Slinton 	char dummy[ctob(UPAGES)];
14818215Slinton     } ustruct;
14918215Slinton     Symbol s;
15018215Slinton 
15118215Slinton     objfile = fopen(objname, "r");
15218215Slinton     if (objfile == nil) {
15318215Slinton 	fatal("can't read \"%s\"", objname);
1549661Slinton     }
15518215Slinton     get(objfile, hdr);
15618215Slinton     if (vaddrs) {
15718215Slinton 	datamap.begin = 0;
15818215Slinton 	datamap.end = 0xffffffff;
15918215Slinton 	stkmap.begin = 0xffffffff;
16018215Slinton 	stkmap.end = 0xffffffff;
16118215Slinton     } else {
16218215Slinton 	up = &(ustruct.u);
16318215Slinton 	fread(up, ctob(UPAGES), 1, corefile);
16418215Slinton 	savreg = (Word *) &(ustruct.dummy[ctob(UPAGES)]);
16518215Slinton 	*mask = savreg[PS];
16618215Slinton 	copyregs(savreg, reg);
16718215Slinton 	*signo = up->u_arg[0];
16818215Slinton 	datamap.seekaddr = ctob(UPAGES);
16918215Slinton 	stkmap.begin = MAXSTKADDR - ctob(up->u_ssize);
17018215Slinton 	stkmap.end = MAXSTKADDR;
17118215Slinton 	stkmap.seekaddr = datamap.seekaddr + ctob(up->u_dsize);
17218215Slinton 	switch (hdr.a_magic) {
17318215Slinton 	    case OMAGIC:
17418215Slinton 		datamap.begin = 0;
17518215Slinton 		datamap.end = ctob(up->u_tsize) + ctob(up->u_dsize);
17618215Slinton 		break;
17718215Slinton 
17818215Slinton 	    case NMAGIC:
17918215Slinton 	    case ZMAGIC:
18018215Slinton 		datamap.begin = (Address) ptob(btop(ctob(up->u_tsize) - 1) + 1);
18118215Slinton 		datamap.end = datamap.begin + ctob(up->u_dsize);
18218215Slinton 		break;
18318215Slinton 
18418215Slinton 	    default:
18518215Slinton 		fatal("bad magic number 0x%x", hdr.a_magic);
18618215Slinton 	}
18718215Slinton #ifdef UXMAG
18818215Slinton 	/*
18918215Slinton 	 * Core dump not from this object file?
19018215Slinton 	 */
19118215Slinton 	if (hdr.a_magic != 0 and up->u_exdata.ux_mag  != 0 and
19218215Slinton 	  hdr.a_magic != up->u_exdata.ux_mag) {
19318215Slinton 	    warning("core dump ignored");
19418215Slinton 	    coredump = false;
19518215Slinton 	    fclose(corefile);
19618215Slinton 	    fclose(objfile);
19718215Slinton 	    start(nil, nil, nil);
19818215Slinton 	}
19918215Slinton #endif
20018215Slinton     }
2019661Slinton }
2029661Slinton 
2039661Slinton public coredump_close()
2049661Slinton {
2059661Slinton     fclose(objfile);
2069661Slinton }
2079661Slinton 
2089661Slinton public coredump_readtext(buff, addr, nbytes)
2099661Slinton char *buff;
2109661Slinton Address addr;
2119661Slinton int nbytes;
2129661Slinton {
21318215Slinton     if (hdr.a_magic == OMAGIC or vaddrs) {
2149661Slinton 	coredump_readdata(buff, addr, nbytes);
2159661Slinton     } else {
2169661Slinton 	fseek(objfile, N_TXTOFF(hdr) + addr, 0);
2179661Slinton 	fread(buff, nbytes, sizeof(Byte), objfile);
2189661Slinton     }
2199661Slinton }
2209661Slinton 
22118215Slinton /*
22218215Slinton  * Map a virtual address to a physical address.
22318215Slinton  */
22418215Slinton 
22518215Slinton private Address vmap (addr)
22618215Slinton Address addr;
22718215Slinton {
22818215Slinton     Address r;
22918215Slinton     integer v, n;
23018215Slinton     struct pte pte;
23118215Slinton 
23218215Slinton     r = addr & ~0xc0000000;
23318215Slinton     v = btop(r);
23418215Slinton     switch (addr&0xc0000000) {
23518215Slinton 	case 0xc0000000:
23618215Slinton 	case 0x80000000:
23718215Slinton 	    /*
23818215Slinton 	     * In system space, so get system pte.
23918215Slinton 	     * If it is valid or reclaimable then the physical address
24018215Slinton 	     * is the combination of its page number and the page offset
24118215Slinton 	     * of the original address.
24218215Slinton 	     */
24318215Slinton 	    if (v >= slr) {
24418215Slinton 		error("address %x out of segment", addr);
24518215Slinton 	    }
24618215Slinton 	    r = ((long) (sbr + v)) & ~0x80000000;
24718215Slinton 	    goto simple;
24818215Slinton 
24918215Slinton 	case 0x40000000:
25018215Slinton 	    /*
25118215Slinton 	     * In p1 space, must not be in shadow region.
25218215Slinton 	     */
25318215Slinton 	    if (v < pcb.pcb_p1lr) {
25418215Slinton 		error("address %x out of segment", addr);
25518215Slinton 	    }
25618215Slinton 	    r = (Address) (pcb.pcb_p1br + v);
25718215Slinton 	    break;
25818215Slinton 
25918215Slinton 	case 0x00000000:
26018215Slinton 	    /*
26118215Slinton 	     * In p0 space, must not be off end of region.
26218215Slinton 	     */
26318215Slinton 	    if (v >= pcb.pcb_p0lr) {
26418215Slinton 		error("address %x out of segment", addr);
26518215Slinton 	    }
26618215Slinton 	    r = (Address) (pcb.pcb_p0br + v);
26718215Slinton 	    break;
26818215Slinton 
26918215Slinton 	default:
27018215Slinton 	    /* do nothing */
27118215Slinton 	    break;
27218215Slinton     }
27318215Slinton     /*
27418215Slinton      * For p0/p1 address, user-level page table should be in
27518215Slinton      * kernel virtual memory.  Do second-level indirect by recursing.
27618215Slinton      */
27718215Slinton     if ((r & 0x80000000) == 0) {
27818215Slinton 	error("bad p0br or p1br in pcb");
27918215Slinton     }
28018215Slinton     r = vmap(r);
28118215Slinton simple:
28218215Slinton     /*
28318215Slinton      * "r" is now the address of the pte of the page
28418215Slinton      * we are interested in; get the pte and paste up the physical address.
28518215Slinton      */
28618215Slinton     fseek(corefile, r, 0);
28718215Slinton     n = fread(&pte, sizeof(pte), 1, corefile);
28818215Slinton     if (n != 1) {
28918215Slinton 	error("page table botch (fread at %x returns %d)", r, n);
29018215Slinton     }
29118215Slinton     if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) {
29218215Slinton 	error("page no valid or reclamable");
29318215Slinton     }
29418215Slinton     return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum));
29518215Slinton }
29618215Slinton 
2979661Slinton public coredump_readdata(buff, addr, nbytes)
2989661Slinton char *buff;
2999661Slinton Address addr;
3009661Slinton int nbytes;
3019661Slinton {
30218215Slinton     Address a;
30318215Slinton 
30418215Slinton     a = addr;
30518215Slinton     if (a < datamap.begin) {
30616608Ssam 	if (hdr.a_magic == OMAGIC) {
30718215Slinton 	    error("[data address 0x%x too low (lb = 0x%x)]", a, datamap.begin);
30816608Ssam 	} else {
30918215Slinton 	    coredump_readtext(buff, a, nbytes);
31016608Ssam 	}
31118215Slinton     } else if (a > stkmap.end) {
31218215Slinton 	error("data address 0x%x too high (ub = 0x%x)", a, stkmap.end);
3139661Slinton     } else {
31418215Slinton 	if (vaddrs) {
31518215Slinton 	    vreadfromfile(corefile, a, buff, nbytes);
31618215Slinton 	} else {
31718215Slinton 	    readfromfile(corefile, a, buff, nbytes);
31818215Slinton 	}
3199661Slinton     }
3209661Slinton }
32118215Slinton 
32218215Slinton /*
32318215Slinton  * Read a block of data from a memory image, mapping virtual addresses.
32418215Slinton  * Have to watch out for page boundaries.
32518215Slinton  */
32618215Slinton 
32718215Slinton private vreadfromfile (corefile, v, buff, nbytes)
32818215Slinton File corefile;
32918215Slinton Address v;
33018215Slinton char *buff;
33118215Slinton integer nbytes;
33218215Slinton {
33318215Slinton     Address a;
33418215Slinton     integer i, remainder, pagesize;
33518215Slinton     char *bufp;
33618215Slinton 
33718215Slinton     a = v;
33818215Slinton     pagesize = (integer) ptob(1);
33918215Slinton     remainder = pagesize - (a mod pagesize);
34018215Slinton     if (remainder >= nbytes) {
34118215Slinton 	readfromfile(corefile, vmap(a), buff, nbytes);
34218215Slinton     } else {
34318215Slinton 	readfromfile(corefile, vmap(a), buff, remainder);
34418215Slinton 	a += remainder;
34518215Slinton 	i = nbytes - remainder;
34618215Slinton 	bufp = buff + remainder;
34718215Slinton 	while (i > pagesize) {
34818215Slinton 	    readfromfile(corefile, vmap(a), bufp, pagesize);
34918215Slinton 	    a += pagesize;
35018215Slinton 	    bufp += pagesize;
35118215Slinton 	    i -= pagesize;
35218215Slinton 	}
35318215Slinton 	readfromfile(corefile, vmap(a), bufp, i);
35418215Slinton     }
35518215Slinton }
35618215Slinton 
35718215Slinton private readfromfile (f, a, buff, nbytes)
35818215Slinton File f;
35918215Slinton Address a;
36018215Slinton char *buff;
36118215Slinton integer nbytes;
36218215Slinton {
36318215Slinton     integer fileaddr;
36418215Slinton 
36518215Slinton     if (a < stkmap.begin) {
36618215Slinton 	fileaddr = datamap.seekaddr + a - datamap.begin;
36718215Slinton     } else {
36818215Slinton 	fileaddr = stkmap.seekaddr + a - stkmap.begin;
36918215Slinton     }
37018215Slinton     fseek(f, fileaddr, 0);
37118215Slinton     fread(buff, nbytes, sizeof(Byte), f);
37218215Slinton }
373