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