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