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