/* * Copyright (c) 1983 Regents of the University of California. * All rights reserved. The Berkeley software License Agreement * specifies the terms and conditions for redistribution. */ #ifndef lint static char sccsid[] = "@(#)coredump.c 5.1 (Berkeley) 5/31/85"; #endif not lint static char rcsid[] = "$Header: coredump.c,v 1.5 84/12/26 10:38:56 linton Exp $"; /* * Deal with the core dump anachronism. */ #include "defs.h" #include "coredump.h" #include "machine.h" #include "object.h" #include "main.h" #include #include #include #include #include #include #include #include #ifndef public #define coredump_readin(m, r, s) coredump_xreadin(&(m), r, &(s)) #include "machine.h" #endif #define MAXSTKADDR (0x80000000 - ctob(UPAGES)) /* highest stack address */ typedef struct { Address begin; Address end; Address seekaddr; } Map; private Map datamap, stkmap; private File objfile; private struct exec hdr; /* * Special variables for debugging the kernel. */ private integer masterpcbb; private integer slr; private struct pte *sbr; private struct pcb pcb; private getpcb () { fseek(corefile, masterpcbb & ~0x80000000, 0); get(corefile, pcb); pcb.pcb_p0lr &= ~AST_CLR; printf("p0br %lx p0lr %lx p1br %lx p1lr %lx\n", pcb.pcb_p0br, pcb.pcb_p0lr, pcb.pcb_p1br, pcb.pcb_p1lr ); setreg(0, pcb.pcb_r0); setreg(1, pcb.pcb_r1); setreg(2, pcb.pcb_r2); setreg(3, pcb.pcb_r3); setreg(4, pcb.pcb_r4); setreg(5, pcb.pcb_r5); setreg(6, pcb.pcb_r6); setreg(7, pcb.pcb_r7); setreg(8, pcb.pcb_r8); setreg(9, pcb.pcb_r9); setreg(10, pcb.pcb_r10); setreg(11, pcb.pcb_r11); setreg(ARGP, pcb.pcb_ap); setreg(FRP, pcb.pcb_fp); setreg(STKP, pcb.pcb_ksp); setreg(PROGCTR, pcb.pcb_pc); } public coredump_getkerinfo () { Symbol s; s = lookup(identname("Sysmap", true)); if (s == nil) { panic("can't find 'Sysmap'"); } sbr = (struct pte *) (s->symvalue.offset); s = lookup(identname("Syssize", true)); if (s == nil) { panic("can't find 'Syssize'"); } slr = (integer) (s->symvalue.offset); printf("sbr %lx slr %lx\n", sbr, slr); s = lookup(identname("masterpaddr", true)); if (s == nil) { panic("can't find 'masterpaddr'"); } fseek( corefile, datamap.seekaddr + s->symvalue.offset&0x7fffffff - datamap.begin, 0 ); get(corefile, masterpcbb); masterpcbb = (masterpcbb&PG_PFNUM)*512; getpcb(); } private copyregs (savreg, reg) Word savreg[], reg[]; { reg[0] = savreg[R0]; reg[1] = savreg[R1]; reg[2] = savreg[R2]; reg[3] = savreg[R3]; reg[4] = savreg[R4]; reg[5] = savreg[R5]; reg[6] = savreg[R6]; reg[7] = savreg[R7]; reg[8] = savreg[R8]; reg[9] = savreg[R9]; reg[10] = savreg[R10]; reg[11] = savreg[R11]; reg[ARGP] = savreg[AP]; reg[FRP] = savreg[FP]; reg[STKP] = savreg[SP]; reg[PROGCTR] = savreg[PC]; } /* * Read the user area information from the core dump. */ public coredump_xreadin(mask, reg, signo) int *mask; Word reg[]; int *signo; { register struct user *up; register Word *savreg; union { struct user u; char dummy[ctob(UPAGES)]; } ustruct; Symbol s; objfile = fopen(objname, "r"); if (objfile == nil) { fatal("can't read \"%s\"", objname); } get(objfile, hdr); if (vaddrs) { datamap.begin = 0; datamap.end = 0xffffffff; stkmap.begin = 0xffffffff; stkmap.end = 0xffffffff; } else { up = &(ustruct.u); fread(up, ctob(UPAGES), 1, corefile); savreg = (Word *) &(ustruct.dummy[ctob(UPAGES)]); *mask = savreg[PS]; copyregs(savreg, reg); *signo = up->u_arg[0]; datamap.seekaddr = ctob(UPAGES); stkmap.begin = MAXSTKADDR - ctob(up->u_ssize); stkmap.end = MAXSTKADDR; stkmap.seekaddr = datamap.seekaddr + ctob(up->u_dsize); switch (hdr.a_magic) { case OMAGIC: datamap.begin = 0; datamap.end = ctob(up->u_tsize) + ctob(up->u_dsize); break; case NMAGIC: case ZMAGIC: datamap.begin = (Address) ptob(btop(ctob(up->u_tsize) - 1) + 1); datamap.end = datamap.begin + ctob(up->u_dsize); break; default: fatal("bad magic number 0x%x", hdr.a_magic); } #ifdef UXMAG /* * Core dump not from this object file? */ if (hdr.a_magic != 0 and up->u_exdata.ux_mag != 0 and hdr.a_magic != up->u_exdata.ux_mag) { warning("core dump ignored"); coredump = false; fclose(corefile); fclose(objfile); start(nil, nil, nil); } #endif } } public coredump_close() { fclose(objfile); } public coredump_readtext(buff, addr, nbytes) char *buff; Address addr; int nbytes; { if (hdr.a_magic == OMAGIC or vaddrs) { coredump_readdata(buff, addr, nbytes); } else { fseek(objfile, N_TXTOFF(hdr) + addr, 0); fread(buff, nbytes, sizeof(Byte), objfile); } } /* * Map a virtual address to a physical address. */ private Address vmap (addr) Address addr; { Address r; integer v, n; struct pte pte; r = addr & ~0xc0000000; v = btop(r); switch (addr&0xc0000000) { case 0xc0000000: case 0x80000000: /* * In system space, so get system pte. * If it is valid or reclaimable then the physical address * is the combination of its page number and the page offset * of the original address. */ if (v >= slr) { error("address %x out of segment", addr); } r = ((long) (sbr + v)) & ~0x80000000; goto simple; case 0x40000000: /* * In p1 space, must not be in shadow region. */ if (v < pcb.pcb_p1lr) { error("address %x out of segment", addr); } r = (Address) (pcb.pcb_p1br + v); break; case 0x00000000: /* * In p0 space, must not be off end of region. */ if (v >= pcb.pcb_p0lr) { error("address %x out of segment", addr); } r = (Address) (pcb.pcb_p0br + v); break; default: /* do nothing */ break; } /* * For p0/p1 address, user-level page table should be in * kernel virtual memory. Do second-level indirect by recursing. */ if ((r & 0x80000000) == 0) { error("bad p0br or p1br in pcb"); } r = vmap(r); simple: /* * "r" is now the address of the pte of the page * we are interested in; get the pte and paste up the physical address. */ fseek(corefile, r, 0); n = fread(&pte, sizeof(pte), 1, corefile); if (n != 1) { error("page table botch (fread at %x returns %d)", r, n); } if (pte.pg_v == 0 and (pte.pg_fod != 0 or pte.pg_pfnum == 0)) { error("page no valid or reclamable"); } return (addr&PGOFSET) + ((Address) ptob(pte.pg_pfnum)); } public coredump_readdata(buff, addr, nbytes) char *buff; Address addr; int nbytes; { Address a; a = addr; if (a < datamap.begin) { if (hdr.a_magic == OMAGIC) { error("[data address 0x%x too low (lb = 0x%x)]", a, datamap.begin); } else { coredump_readtext(buff, a, nbytes); } } else if (a > stkmap.end) { error("data address 0x%x too high (ub = 0x%x)", a, stkmap.end); } else { if (vaddrs) { vreadfromfile(corefile, a, buff, nbytes); } else { readfromfile(corefile, a, buff, nbytes); } } } /* * Read a block of data from a memory image, mapping virtual addresses. * Have to watch out for page boundaries. */ private vreadfromfile (corefile, v, buff, nbytes) File corefile; Address v; char *buff; integer nbytes; { Address a; integer i, remainder, pagesize; char *bufp; a = v; pagesize = (integer) ptob(1); remainder = pagesize - (a mod pagesize); if (remainder >= nbytes) { readfromfile(corefile, vmap(a), buff, nbytes); } else { readfromfile(corefile, vmap(a), buff, remainder); a += remainder; i = nbytes - remainder; bufp = buff + remainder; while (i > pagesize) { readfromfile(corefile, vmap(a), bufp, pagesize); a += pagesize; bufp += pagesize; i -= pagesize; } readfromfile(corefile, vmap(a), bufp, i); } } private readfromfile (f, a, buff, nbytes) File f; Address a; char *buff; integer nbytes; { integer fileaddr; if (a < stkmap.begin) { fileaddr = datamap.seekaddr + a - datamap.begin; } else { fileaddr = stkmap.seekaddr + a - stkmap.begin; } fseek(f, fileaddr, 0); fread(buff, nbytes, sizeof(Byte), f); }