1 /*- 2 * Copyright (c) 1992 The Regents of the University of California. 3 * All rights reserved. 4 * 5 * This software was developed by the Computer Systems Engineering group 6 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 7 * contributed to Berkeley. 8 * 9 * %sccs.include.redist.c% 10 */ 11 12 #ifndef lint 13 static char sccsid[] = "@(#)md-sparc.c 5.4 (Berkeley) 05/15/93"; 14 #endif /* not lint */ 15 16 #include <sys/param.h> 17 #include <sys/time.h> 18 #include <sys/file.h> 19 #include <sys/stat.h> 20 #include <sys/proc.h> 21 #include <sys/user.h> 22 #include <sys/sysctl.h> 23 #include <machine/vmparam.h> 24 25 #include <kvm.h> 26 #include <unistd.h> 27 #include <stdio.h> 28 #include <string.h> 29 #include "extern.h" 30 31 #ifndef offsetof 32 #define offsetof(s, f) ((int)&((s *)0)->f) 33 #endif 34 35 static void 36 shift_page(fd, off, ssize) 37 register int fd; 38 register off_t off; 39 register int ssize; 40 { 41 char buffer[NBPG]; 42 43 (void)lseek(fd, (off_t)-NBPG, SEEK_END); 44 for (; ssize > 0; ssize -= NBPG) { 45 (void)read(fd, buffer, NBPG); 46 (void)write(fd, buffer, NBPG); 47 (void)lseek(fd, (off_t)-2 * NBPG, SEEK_CUR); 48 } 49 } 50 51 /* 52 * Fix up the core image for the sparc. We need to flush any register 53 * windows that are cached in the pcb out to the user stack. 54 * Also, we need to get the trap frame and possible floating point state 55 * from the top of the kernel stack and store it in the pcb. 56 */ 57 void 58 md_core(kd, fd, ki) 59 kvm_t *kd; 60 int fd; 61 struct kinfo_proc *ki; 62 { 63 register struct rwindow *rw; 64 register int nsaved, cc, ssize; 65 register off_t off, s; 66 register u_long sp; 67 struct pcb pcb; 68 struct trapframe tf; 69 70 /* 71 * Before anything else read the trapframe. Synchronizing here 72 * is impossible if the process is running. 73 */ 74 cc = kvm_read(kd, (u_long)ki->kp_proc.p_md.md_tf, 75 /* XXX */ 76 (void *)&tf, sizeof(tf)); 77 if (cc < 0) 78 err(1, "kvm_read: %s (reading kernel trapframe)", 79 kvm_geterr(kd)); 80 if (cc != sizeof(tf)) 81 err(1, "cannot read kernel trapframe"); 82 83 /* 84 * Write out the real trap frame. 85 */ 86 off = offsetof(struct user, u_md); 87 off += offsetof(struct md_coredump, md_tf); 88 if (lseek(fd, off, SEEK_SET) == -1) 89 err(1, "lseek: %s", strerror(errno)); 90 (void)write(fd, &tf, sizeof(tf)); 91 92 if (ki->kp_proc.p_md.md_fpstate != 0) { 93 /* 94 * If floating point state is present, write it out too. 95 * It comes right after the trapframe so we don't need to seek. 96 */ 97 struct fpstate fs; 98 cc = kvm_read(kd, (u_long)ki->kp_proc.p_md.md_fpstate, 99 (void *)&fs, sizeof(fs)); 100 if (cc < 0) 101 err(1, "kvm_read: %s (fpu state)", kvm_geterr(kd)); 102 if (cc != sizeof(fs)) 103 err(1, "cannot read fpu state"); 104 (void)write(fd, (char *)&fs, sizeof(fs)); 105 } 106 /* 107 * Read pcb. 108 */ 109 if (lseek(fd, (off_t)offsetof(struct user, u_pcb), SEEK_SET) == -1) 110 err(1, "lseek: %s", strerror(errno)); 111 cc = read(fd, (char *)&pcb, sizeof(pcb)); 112 if (cc != sizeof(pcb)) { 113 if (cc < 0) 114 err(1, "read: %s", strerror(errno)); 115 err(1, "couldn't read pcb from core file"); 116 } 117 118 /* 119 * Write any unsaved windows to the appropriate stack locations. 120 */ 121 nsaved = pcb.pcb_nsaved; 122 if (nsaved == 0) 123 return; 124 125 rw = &pcb.pcb_rw[0]; 126 off = ctob(UPAGES + ki->kp_eproc.e_vm.vm_dsize); 127 ssize = ctob(ki->kp_eproc.e_vm.vm_ssize); 128 sp = tf.tf_out[6]; 129 for (; --nsaved >= 0; ++rw) { 130 /* 131 * Copy register window into appropriate stack location. 132 */ 133 s = ssize - (USRSTACK - sp); 134 if (s < 0) { 135 if (s < -NBPG) 136 err(1, "cannot copy pcb windows to stack"); 137 /* 138 * It's possible to be missing the bottomost 139 * page because a stack page hasn't been allocated 140 * for the register save area. Shift over 141 * the stack segment by a page, and update 142 * the u-area to reflect the new stack size. YECH! 143 */ 144 shift_page(fd, off, ssize); 145 ssize += NBPG; 146 s += NBPG; 147 ++ki->kp_eproc.e_vm.vm_ssize; 148 (void)lseek(fd, 149 (off_t)offsetof(struct user, u_kproc.kp_eproc.e_vm), 150 SEEK_SET); 151 (void)write(fd, 152 &ki->kp_eproc.e_vm, sizeof(ki->kp_eproc.e_vm)); 153 } 154 if (lseek(fd, off + s, SEEK_SET) == -1) 155 err(1, "cannot copy pcb windows to stack"); 156 157 (void)write(fd, rw, sizeof(*rw)); 158 sp = rw->rw_in[6]; 159 } 160 } 161