Sun Mar 8 00:06:42 2020 UTC ()
only do bounce buffering for character devices.


(chs)
diff -r1.104 -r1.105 src/lib/libkvm/kvm.c

cvs diff -r1.104 -r1.105 src/lib/libkvm/kvm.c (switch to unified diff)

--- src/lib/libkvm/kvm.c 2018/11/05 00:43:30 1.104
+++ src/lib/libkvm/kvm.c 2020/03/08 00:06:42 1.105
@@ -1,912 +1,917 @@ @@ -1,912 +1,917 @@
1/* $NetBSD: kvm.c,v 1.104 2018/11/05 00:43:30 mrg Exp $ */ 1/* $NetBSD: kvm.c,v 1.105 2020/03/08 00:06:42 chs Exp $ */
2 2
3/*- 3/*-
4 * Copyright (c) 1989, 1992, 1993 4 * Copyright (c) 1989, 1992, 1993
5 * The Regents of the University of California. All rights reserved. 5 * The Regents of the University of California. All rights reserved.
6 * 6 *
7 * This code is derived from software developed by the Computer Systems 7 * This code is derived from software developed by the Computer Systems
8 * Engineering group at Lawrence Berkeley Laboratory under DARPA contract 8 * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
9 * BG 91-66 and contributed to Berkeley. 9 * BG 91-66 and contributed to Berkeley.
10 * 10 *
11 * Redistribution and use in source and binary forms, with or without 11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions 12 * modification, are permitted provided that the following conditions
13 * are met: 13 * are met:
14 * 1. Redistributions of source code must retain the above copyright 14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer. 15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright 16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the 17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution. 18 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the University nor the names of its contributors 19 * 3. Neither the name of the University nor the names of its contributors
20 * may be used to endorse or promote products derived from this software 20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission. 21 * without specific prior written permission.
22 * 22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE. 33 * SUCH DAMAGE.
34 */ 34 */
35 35
36#include <sys/cdefs.h> 36#include <sys/cdefs.h>
37#if defined(LIBC_SCCS) && !defined(lint) 37#if defined(LIBC_SCCS) && !defined(lint)
38#if 0 38#if 0
39static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94"; 39static char sccsid[] = "@(#)kvm.c 8.2 (Berkeley) 2/13/94";
40#else 40#else
41__RCSID("$NetBSD: kvm.c,v 1.104 2018/11/05 00:43:30 mrg Exp $"); 41__RCSID("$NetBSD: kvm.c,v 1.105 2020/03/08 00:06:42 chs Exp $");
42#endif 42#endif
43#endif /* LIBC_SCCS and not lint */ 43#endif /* LIBC_SCCS and not lint */
44 44
45#include <sys/param.h> 45#include <sys/param.h>
46#include <sys/lwp.h> 46#include <sys/lwp.h>
47#include <sys/proc.h> 47#include <sys/proc.h>
48#include <sys/ioctl.h> 48#include <sys/ioctl.h>
49#include <sys/stat.h> 49#include <sys/stat.h>
50#include <sys/sysctl.h> 50#include <sys/sysctl.h>
51 51
52#include <sys/core.h> 52#include <sys/core.h>
53#include <sys/exec.h> 53#include <sys/exec.h>
54#include <sys/kcore.h> 54#include <sys/kcore.h>
55#include <sys/ksyms.h> 55#include <sys/ksyms.h>
56#include <sys/types.h> 56#include <sys/types.h>
57 57
58#include <uvm/uvm_extern.h> 58#include <uvm/uvm_extern.h>
59 59
60#include <machine/cpu.h> 60#include <machine/cpu.h>
61 61
62#include <ctype.h> 62#include <ctype.h>
63#include <errno.h> 63#include <errno.h>
64#include <fcntl.h> 64#include <fcntl.h>
65#include <limits.h> 65#include <limits.h>
66#include <nlist.h> 66#include <nlist.h>
67#include <paths.h> 67#include <paths.h>
68#include <stdarg.h> 68#include <stdarg.h>
69#include <stdio.h> 69#include <stdio.h>
70#include <stdlib.h> 70#include <stdlib.h>
71#include <string.h> 71#include <string.h>
72#include <unistd.h> 72#include <unistd.h>
73#include <kvm.h> 73#include <kvm.h>
74 74
75#include "kvm_private.h" 75#include "kvm_private.h"
76 76
77static int _kvm_get_header(kvm_t *); 77static int _kvm_get_header(kvm_t *);
78static kvm_t *_kvm_open(kvm_t *, const char *, const char *, 78static kvm_t *_kvm_open(kvm_t *, const char *, const char *,
79 const char *, int, char *); 79 const char *, int, char *);
80static int clear_gap(kvm_t *, bool (*)(void *, const void *, size_t), 80static int clear_gap(kvm_t *, bool (*)(void *, const void *, size_t),
81 void *, size_t); 81 void *, size_t);
82static off_t Lseek(kvm_t *, int, off_t, int); 82static off_t Lseek(kvm_t *, int, off_t, int);
83static ssize_t Pread(kvm_t *, int, void *, size_t, off_t); 83static ssize_t Pread(kvm_t *, int, void *, size_t, off_t);
84 84
85char * 85char *
86kvm_geterr(kvm_t *kd) 86kvm_geterr(kvm_t *kd)
87{ 87{
88 return (kd->errbuf); 88 return (kd->errbuf);
89} 89}
90 90
91const char * 91const char *
92kvm_getkernelname(kvm_t *kd) 92kvm_getkernelname(kvm_t *kd)
93{ 93{
94 return kd->kernelname; 94 return kd->kernelname;
95} 95}
96 96
97/* 97/*
98 * Report an error using printf style arguments. "program" is kd->program 98 * Report an error using printf style arguments. "program" is kd->program
99 * on hard errors, and 0 on soft errors, so that under sun error emulation, 99 * on hard errors, and 0 on soft errors, so that under sun error emulation,
100 * only hard errors are printed out (otherwise, programs like gdb will 100 * only hard errors are printed out (otherwise, programs like gdb will
101 * generate tons of error messages when trying to access bogus pointers). 101 * generate tons of error messages when trying to access bogus pointers).
102 */ 102 */
103void 103void
104_kvm_err(kvm_t *kd, const char *program, const char *fmt, ...) 104_kvm_err(kvm_t *kd, const char *program, const char *fmt, ...)
105{ 105{
106 va_list ap; 106 va_list ap;
107 107
108 va_start(ap, fmt); 108 va_start(ap, fmt);
109 if (program != NULL) { 109 if (program != NULL) {
110 (void)fprintf(stderr, "%s: ", program); 110 (void)fprintf(stderr, "%s: ", program);
111 (void)vfprintf(stderr, fmt, ap); 111 (void)vfprintf(stderr, fmt, ap);
112 (void)fputc('\n', stderr); 112 (void)fputc('\n', stderr);
113 } else 113 } else
114 (void)vsnprintf(kd->errbuf, 114 (void)vsnprintf(kd->errbuf,
115 sizeof(kd->errbuf), fmt, ap); 115 sizeof(kd->errbuf), fmt, ap);
116 116
117 va_end(ap); 117 va_end(ap);
118} 118}
119 119
120void 120void
121_kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...) 121_kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...)
122{ 122{
123 va_list ap; 123 va_list ap;
124 size_t n; 124 size_t n;
125 125
126 va_start(ap, fmt); 126 va_start(ap, fmt);
127 if (program != NULL) { 127 if (program != NULL) {
128 (void)fprintf(stderr, "%s: ", program); 128 (void)fprintf(stderr, "%s: ", program);
129 (void)vfprintf(stderr, fmt, ap); 129 (void)vfprintf(stderr, fmt, ap);
130 (void)fprintf(stderr, ": %s\n", strerror(errno)); 130 (void)fprintf(stderr, ": %s\n", strerror(errno));
131 } else { 131 } else {
132 char *cp = kd->errbuf; 132 char *cp = kd->errbuf;
133 133
134 (void)vsnprintf(cp, sizeof(kd->errbuf), fmt, ap); 134 (void)vsnprintf(cp, sizeof(kd->errbuf), fmt, ap);
135 n = strlen(cp); 135 n = strlen(cp);
136 (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s", 136 (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s",
137 strerror(errno)); 137 strerror(errno));
138 } 138 }
139 va_end(ap); 139 va_end(ap);
140} 140}
141 141
142void * 142void *
143_kvm_malloc(kvm_t *kd, size_t n) 143_kvm_malloc(kvm_t *kd, size_t n)
144{ 144{
145 void *p; 145 void *p;
146 146
147 if ((p = malloc(n)) == NULL) 147 if ((p = malloc(n)) == NULL)
148 _kvm_err(kd, kd->program, "%s", strerror(errno)); 148 _kvm_err(kd, kd->program, "%s", strerror(errno));
149 return (p); 149 return (p);
150} 150}
151 151
152/* 152/*
153 * Wrapper around the lseek(2) system call; calls _kvm_syserr() for us 153 * Wrapper around the lseek(2) system call; calls _kvm_syserr() for us
154 * in the event of emergency. 154 * in the event of emergency.
155 */ 155 */
156static off_t 156static off_t
157Lseek(kvm_t *kd, int fd, off_t offset, int whence) 157Lseek(kvm_t *kd, int fd, off_t offset, int whence)
158{ 158{
159 off_t off; 159 off_t off;
160 160
161 errno = 0; 161 errno = 0;
162 162
163 if ((off = lseek(fd, offset, whence)) == -1 && errno != 0) { 163 if ((off = lseek(fd, offset, whence)) == -1 && errno != 0) {
164 _kvm_syserr(kd, kd->program, "Lseek"); 164 _kvm_syserr(kd, kd->program, "Lseek");
165 return ((off_t)-1); 165 return ((off_t)-1);
166 } 166 }
167 return (off); 167 return (off);
168} 168}
169 169
170ssize_t 170ssize_t
171_kvm_pread(kvm_t *kd, int fd, void *buf, size_t size, off_t off) 171_kvm_pread(kvm_t *kd, int fd, void *buf, size_t size, off_t off)
172{ 172{
173 ptrdiff_t moff; 173 ptrdiff_t moff;
174 void *newbuf; 174 void *newbuf;
175 size_t dsize; 175 size_t dsize;
176 ssize_t rv; 176 ssize_t rv;
177 off_t doff; 177 off_t doff;
178 178
179 /* If aligned nothing to do. */ 179 /* If aligned nothing to do. */
180 if (((off % kd->fdalign) | (size % kd->fdalign)) == 0) { 180 if (((off % kd->fdalign) | (size % kd->fdalign)) == 0) {
181 return pread(fd, buf, size, off); 181 return pread(fd, buf, size, off);
182 } 182 }
183 183
184 /* 184 /*
185 * Otherwise must buffer. We can't tolerate short reads in this 185 * Otherwise must buffer. We can't tolerate short reads in this
186 * case (lazy bum). 186 * case (lazy bum).
187 */ 187 */
188 moff = (ptrdiff_t)off % kd->fdalign; 188 moff = (ptrdiff_t)off % kd->fdalign;
189 doff = off - moff; 189 doff = off - moff;
190 dsize = moff + size + kd->fdalign - 1; 190 dsize = moff + size + kd->fdalign - 1;
191 dsize -= dsize % kd->fdalign; 191 dsize -= dsize % kd->fdalign;
192 if (kd->iobufsz < dsize) { 192 if (kd->iobufsz < dsize) {
193 newbuf = realloc(kd->iobuf, dsize); 193 newbuf = realloc(kd->iobuf, dsize);
194 if (newbuf == NULL) { 194 if (newbuf == NULL) {
195 _kvm_syserr(kd, 0, "cannot allocate I/O buffer"); 195 _kvm_syserr(kd, 0, "cannot allocate I/O buffer");
196 return (-1); 196 return (-1);
197 } 197 }
198 kd->iobuf = newbuf; 198 kd->iobuf = newbuf;
199 kd->iobufsz = dsize; 199 kd->iobufsz = dsize;
200 } 200 }
201 rv = pread(fd, kd->iobuf, dsize, doff); 201 rv = pread(fd, kd->iobuf, dsize, doff);
202 if (rv < size + moff) 202 if (rv < size + moff)
203 return -1; 203 return -1;
204 memcpy(buf, kd->iobuf + moff, size); 204 memcpy(buf, kd->iobuf + moff, size);
205 return size; 205 return size;
206} 206}
207 207
208/* 208/*
209 * Wrapper around the pread(2) system call; calls _kvm_syserr() for us 209 * Wrapper around the pread(2) system call; calls _kvm_syserr() for us
210 * in the event of emergency. 210 * in the event of emergency.
211 */ 211 */
212static ssize_t 212static ssize_t
213Pread(kvm_t *kd, int fd, void *buf, size_t nbytes, off_t offset) 213Pread(kvm_t *kd, int fd, void *buf, size_t nbytes, off_t offset)
214{ 214{
215 ssize_t rv; 215 ssize_t rv;
216 216
217 errno = 0; 217 errno = 0;
218 218
219 if ((rv = _kvm_pread(kd, fd, buf, nbytes, offset)) != nbytes && 219 if ((rv = _kvm_pread(kd, fd, buf, nbytes, offset)) != nbytes &&
220 errno != 0) 220 errno != 0)
221 _kvm_syserr(kd, kd->program, "Pread"); 221 _kvm_syserr(kd, kd->program, "Pread");
222 return (rv); 222 return (rv);
223} 223}
224 224
225static kvm_t * 225static kvm_t *
226_kvm_open(kvm_t *kd, const char *uf, const char *mf, const char *sf, int flag, 226_kvm_open(kvm_t *kd, const char *uf, const char *mf, const char *sf, int flag,
227 char *errout) 227 char *errout)
228{ 228{
229 struct stat st; 229 struct stat st;
230 int ufgiven; 230 int ufgiven;
231 231
232 kd->pmfd = -1; 232 kd->pmfd = -1;
233 kd->vmfd = -1; 233 kd->vmfd = -1;
234 kd->swfd = -1; 234 kd->swfd = -1;
235 kd->nlfd = -1; 235 kd->nlfd = -1;
236 kd->alive = KVM_ALIVE_DEAD; 236 kd->alive = KVM_ALIVE_DEAD;
237 kd->procbase = NULL; 237 kd->procbase = NULL;
238 kd->procbase_len = 0; 238 kd->procbase_len = 0;
239 kd->procbase2 = NULL; 239 kd->procbase2 = NULL;
240 kd->procbase2_len = 0; 240 kd->procbase2_len = 0;
241 kd->lwpbase = NULL; 241 kd->lwpbase = NULL;
242 kd->lwpbase_len = 0; 242 kd->lwpbase_len = 0;
243 kd->nbpg = getpagesize(); 243 kd->nbpg = getpagesize();
244 kd->swapspc = NULL; 244 kd->swapspc = NULL;
245 kd->argspc = NULL; 245 kd->argspc = NULL;
246 kd->argspc_len = 0; 246 kd->argspc_len = 0;
247 kd->argbuf = NULL; 247 kd->argbuf = NULL;
248 kd->argv = NULL; 248 kd->argv = NULL;
249 kd->vmst = NULL; 249 kd->vmst = NULL;
250 kd->vm_page_buckets = NULL; 250 kd->vm_page_buckets = NULL;
251 kd->kcore_hdr = NULL; 251 kd->kcore_hdr = NULL;
252 kd->cpu_dsize = 0; 252 kd->cpu_dsize = 0;
253 kd->cpu_data = NULL; 253 kd->cpu_data = NULL;
254 kd->dump_off = 0; 254 kd->dump_off = 0;
255 kd->fdalign = 1; 255 kd->fdalign = 1;
256 kd->iobuf = NULL; 256 kd->iobuf = NULL;
257 kd->iobufsz = 0; 257 kd->iobufsz = 0;
258 kd->errbuf[0] = '\0'; 258 kd->errbuf[0] = '\0';
259 259
260 if (flag & KVM_NO_FILES) { 260 if (flag & KVM_NO_FILES) {
261 kd->alive = KVM_ALIVE_SYSCTL; 261 kd->alive = KVM_ALIVE_SYSCTL;
262 return(kd); 262 return(kd);
263 } 263 }
264 264
265 /* 265 /*
266 * Call the MD open hook. This sets: 266 * Call the MD open hook. This sets:
267 * usrstack, min_uva, max_uva 267 * usrstack, min_uva, max_uva
268 */ 268 */
269 if (_kvm_mdopen(kd)) { 269 if (_kvm_mdopen(kd)) {
270 _kvm_err(kd, kd->program, "md init failed"); 270 _kvm_err(kd, kd->program, "md init failed");
271 goto failed; 271 goto failed;
272 } 272 }
273 273
274 ufgiven = (uf != NULL); 274 ufgiven = (uf != NULL);
275 if (!ufgiven) { 275 if (!ufgiven) {
276#ifdef CPU_BOOTED_KERNEL 276#ifdef CPU_BOOTED_KERNEL
277 /* 130 is 128 + '/' + '\0' */ 277 /* 130 is 128 + '/' + '\0' */
278 static char booted_kernel[130]; 278 static char booted_kernel[130];
279 int mib[2], rc; 279 int mib[2], rc;
280 size_t len; 280 size_t len;
281 281
282 mib[0] = CTL_MACHDEP; 282 mib[0] = CTL_MACHDEP;
283 mib[1] = CPU_BOOTED_KERNEL; 283 mib[1] = CPU_BOOTED_KERNEL;
284 booted_kernel[0] = '/'; 284 booted_kernel[0] = '/';
285 booted_kernel[1] = '\0'; 285 booted_kernel[1] = '\0';
286 len = sizeof(booted_kernel) - 2; 286 len = sizeof(booted_kernel) - 2;
287 rc = sysctl(&mib[0], 2, &booted_kernel[1], &len, NULL, 0); 287 rc = sysctl(&mib[0], 2, &booted_kernel[1], &len, NULL, 0);
288 booted_kernel[sizeof(booted_kernel) - 1] = '\0'; 288 booted_kernel[sizeof(booted_kernel) - 1] = '\0';
289 uf = (booted_kernel[1] == '/') ? 289 uf = (booted_kernel[1] == '/') ?
290 &booted_kernel[1] : &booted_kernel[0]; 290 &booted_kernel[1] : &booted_kernel[0];
291 if (rc != -1) 291 if (rc != -1)
292 rc = stat(uf, &st); 292 rc = stat(uf, &st);
293 if (rc != -1 && !S_ISREG(st.st_mode)) 293 if (rc != -1 && !S_ISREG(st.st_mode))
294 rc = -1; 294 rc = -1;
295 if (rc == -1) 295 if (rc == -1)
296#endif /* CPU_BOOTED_KERNEL */ 296#endif /* CPU_BOOTED_KERNEL */
297 uf = _PATH_UNIX; 297 uf = _PATH_UNIX;
298 } 298 }
299 else if (strlen(uf) >= MAXPATHLEN) { 299 else if (strlen(uf) >= MAXPATHLEN) {
300 _kvm_err(kd, kd->program, "exec file name too long"); 300 _kvm_err(kd, kd->program, "exec file name too long");
301 goto failed; 301 goto failed;
302 } 302 }
303 if (flag & ~O_RDWR) { 303 if (flag & ~O_RDWR) {
304 _kvm_err(kd, kd->program, "bad flags arg"); 304 _kvm_err(kd, kd->program, "bad flags arg");
305 goto failed; 305 goto failed;
306 } 306 }
307 if (mf == 0) 307 if (mf == 0)
308 mf = _PATH_MEM; 308 mf = _PATH_MEM;
309 if (sf == 0) 309 if (sf == 0)
310 sf = _PATH_DRUM; 310 sf = _PATH_DRUM;
311 311
312 /* 312 /*
313 * Open the kernel namelist. If /dev/ksyms doesn't 313 * Open the kernel namelist. If /dev/ksyms doesn't
314 * exist, open the current kernel. 314 * exist, open the current kernel.
315 */ 315 */
316 if (ufgiven == 0) 316 if (ufgiven == 0)
317 kd->nlfd = open(_PATH_KSYMS, O_RDONLY | O_CLOEXEC, 0); 317 kd->nlfd = open(_PATH_KSYMS, O_RDONLY | O_CLOEXEC, 0);
318 if (kd->nlfd < 0) { 318 if (kd->nlfd < 0) {
319 if ((kd->nlfd = open(uf, O_RDONLY | O_CLOEXEC, 0)) < 0) { 319 if ((kd->nlfd = open(uf, O_RDONLY | O_CLOEXEC, 0)) < 0) {
320 _kvm_syserr(kd, kd->program, "%s", uf); 320 _kvm_syserr(kd, kd->program, "%s", uf);
321 goto failed; 321 goto failed;
322 } 322 }
323 strlcpy(kd->kernelname, uf, sizeof(kd->kernelname)); 323 strlcpy(kd->kernelname, uf, sizeof(kd->kernelname));
324 } else { 324 } else {
325 strlcpy(kd->kernelname, _PATH_KSYMS, sizeof(kd->kernelname)); 325 strlcpy(kd->kernelname, _PATH_KSYMS, sizeof(kd->kernelname));
326 } 326 }
327 327
328 if ((kd->pmfd = open(mf, flag | O_CLOEXEC, 0)) < 0) { 328 if ((kd->pmfd = open(mf, flag | O_CLOEXEC, 0)) < 0) {
329 _kvm_syserr(kd, kd->program, "%s", mf); 329 _kvm_syserr(kd, kd->program, "%s", mf);
330 goto failed; 330 goto failed;
331 } 331 }
332 if (fstat(kd->pmfd, &st) < 0) { 332 if (fstat(kd->pmfd, &st) < 0) {
333 _kvm_syserr(kd, kd->program, "%s", mf); 333 _kvm_syserr(kd, kd->program, "%s", mf);
334 goto failed; 334 goto failed;
335 } 335 }
336 if (S_ISCHR(st.st_mode) && strcmp(mf, _PATH_MEM) == 0) { 336 if (S_ISCHR(st.st_mode) && strcmp(mf, _PATH_MEM) == 0) {
337 /* 337 /*
338 * If this is /dev/mem, open kmem too. (Maybe we should 338 * If this is /dev/mem, open kmem too. (Maybe we should
339 * make it work for either /dev/mem or /dev/kmem -- in either 339 * make it work for either /dev/mem or /dev/kmem -- in either
340 * case you're working with a live kernel.) 340 * case you're working with a live kernel.)
341 */ 341 */
342 if ((kd->vmfd = open(_PATH_KMEM, flag | O_CLOEXEC, 0)) < 0) { 342 if ((kd->vmfd = open(_PATH_KMEM, flag | O_CLOEXEC, 0)) < 0) {
343 _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM); 343 _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
344 goto failed; 344 goto failed;
345 } 345 }
346 kd->alive = KVM_ALIVE_FILES; 346 kd->alive = KVM_ALIVE_FILES;
347 if ((kd->swfd = open(sf, flag | O_CLOEXEC, 0)) < 0) { 347 if ((kd->swfd = open(sf, flag | O_CLOEXEC, 0)) < 0) {
348 if (errno != ENXIO) { 348 if (errno != ENXIO) {
349 _kvm_syserr(kd, kd->program, "%s", sf); 349 _kvm_syserr(kd, kd->program, "%s", sf);
350 goto failed; 350 goto failed;
351 } 351 }
352 /* swap is not configured? not fatal */ 352 /* swap is not configured? not fatal */
353 } 353 }
354 } else { 354 } else {
355 kd->fdalign = DEV_BSIZE; /* XXX */ 355 if (S_ISCHR(st.st_mode)) {
 356 kd->fdalign = DEV_BSIZE;
 357 } else {
 358 kd->fdalign = 1;
 359 }
 360
356 /* 361 /*
357 * This is a crash dump. 362 * This is a crash dump.
358 * Initialize the virtual address translation machinery. 363 * Initialize the virtual address translation machinery.
359 * 364 *
360 * If there is no valid core header, fail silently here. 365 * If there is no valid core header, fail silently here.
361 * The address translations however will fail without 366 * The address translations however will fail without
362 * header. Things can be made to run by calling 367 * header. Things can be made to run by calling
363 * kvm_dump_mkheader() before doing any translation. 368 * kvm_dump_mkheader() before doing any translation.
364 */ 369 */
365 if (_kvm_get_header(kd) == 0) { 370 if (_kvm_get_header(kd) == 0) {
366 if (_kvm_initvtop(kd) < 0) 371 if (_kvm_initvtop(kd) < 0)
367 goto failed; 372 goto failed;
368 } 373 }
369 } 374 }
370 return (kd); 375 return (kd);
371failed: 376failed:
372 /* 377 /*
373 * Copy out the error if doing sane error semantics. 378 * Copy out the error if doing sane error semantics.
374 */ 379 */
375 if (errout != 0) 380 if (errout != 0)
376 (void)strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX); 381 (void)strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX);
377 (void)kvm_close(kd); 382 (void)kvm_close(kd);
378 return (0); 383 return (0);
379} 384}
380 385
381/* 386/*
382 * The kernel dump file (from savecore) contains: 387 * The kernel dump file (from savecore) contains:
383 * kcore_hdr_t kcore_hdr; 388 * kcore_hdr_t kcore_hdr;
384 * kcore_seg_t cpu_hdr; 389 * kcore_seg_t cpu_hdr;
385 * (opaque) cpu_data; (size is cpu_hdr.c_size) 390 * (opaque) cpu_data; (size is cpu_hdr.c_size)
386 * kcore_seg_t mem_hdr; 391 * kcore_seg_t mem_hdr;
387 * (memory) mem_data; (size is mem_hdr.c_size) 392 * (memory) mem_data; (size is mem_hdr.c_size)
388 * 393 *
389 * Note: khdr is padded to khdr.c_hdrsize; 394 * Note: khdr is padded to khdr.c_hdrsize;
390 * cpu_hdr and mem_hdr are padded to khdr.c_seghdrsize 395 * cpu_hdr and mem_hdr are padded to khdr.c_seghdrsize
391 */ 396 */
392static int 397static int
393_kvm_get_header(kvm_t *kd) 398_kvm_get_header(kvm_t *kd)
394{ 399{
395 kcore_hdr_t kcore_hdr; 400 kcore_hdr_t kcore_hdr;
396 kcore_seg_t cpu_hdr; 401 kcore_seg_t cpu_hdr;
397 kcore_seg_t mem_hdr; 402 kcore_seg_t mem_hdr;
398 size_t offset; 403 size_t offset;
399 ssize_t sz; 404 ssize_t sz;
400 405
401 /* 406 /*
402 * Read the kcore_hdr_t 407 * Read the kcore_hdr_t
403 */ 408 */
404 sz = Pread(kd, kd->pmfd, &kcore_hdr, sizeof(kcore_hdr), (off_t)0); 409 sz = Pread(kd, kd->pmfd, &kcore_hdr, sizeof(kcore_hdr), (off_t)0);
405 if (sz != sizeof(kcore_hdr)) 410 if (sz != sizeof(kcore_hdr))
406 return (-1); 411 return (-1);
407 412
408 /* 413 /*
409 * Currently, we only support dump-files made by the current 414 * Currently, we only support dump-files made by the current
410 * architecture... 415 * architecture...
411 */ 416 */
412 if ((CORE_GETMAGIC(kcore_hdr) != KCORE_MAGIC) || 417 if ((CORE_GETMAGIC(kcore_hdr) != KCORE_MAGIC) ||
413 (CORE_GETMID(kcore_hdr) != MID_MACHINE)) 418 (CORE_GETMID(kcore_hdr) != MID_MACHINE))
414 return (-1); 419 return (-1);
415 420
416 /* 421 /*
417 * Currently, we only support exactly 2 segments: cpu-segment 422 * Currently, we only support exactly 2 segments: cpu-segment
418 * and data-segment in exactly that order. 423 * and data-segment in exactly that order.
419 */ 424 */
420 if (kcore_hdr.c_nseg != 2) 425 if (kcore_hdr.c_nseg != 2)
421 return (-1); 426 return (-1);
422 427
423 /* 428 /*
424 * Save away the kcore_hdr. All errors after this 429 * Save away the kcore_hdr. All errors after this
425 * should do a to "goto fail" to deallocate things. 430 * should do a to "goto fail" to deallocate things.
426 */ 431 */
427 kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr)); 432 kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr));
428 memcpy(kd->kcore_hdr, &kcore_hdr, sizeof(kcore_hdr)); 433 memcpy(kd->kcore_hdr, &kcore_hdr, sizeof(kcore_hdr));
429 offset = kcore_hdr.c_hdrsize; 434 offset = kcore_hdr.c_hdrsize;
430 435
431 /* 436 /*
432 * Read the CPU segment header 437 * Read the CPU segment header
433 */ 438 */
434 sz = Pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), (off_t)offset); 439 sz = Pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), (off_t)offset);
435 if (sz != sizeof(cpu_hdr)) 440 if (sz != sizeof(cpu_hdr))
436 goto fail; 441 goto fail;
437 if ((CORE_GETMAGIC(cpu_hdr) != KCORESEG_MAGIC) || 442 if ((CORE_GETMAGIC(cpu_hdr) != KCORESEG_MAGIC) ||
438 (CORE_GETFLAG(cpu_hdr) != CORE_CPU)) 443 (CORE_GETFLAG(cpu_hdr) != CORE_CPU))
439 goto fail; 444 goto fail;
440 offset += kcore_hdr.c_seghdrsize; 445 offset += kcore_hdr.c_seghdrsize;
441 446
442 /* 447 /*
443 * Read the CPU segment DATA. 448 * Read the CPU segment DATA.
444 */ 449 */
445 kd->cpu_dsize = cpu_hdr.c_size; 450 kd->cpu_dsize = cpu_hdr.c_size;
446 kd->cpu_data = _kvm_malloc(kd, cpu_hdr.c_size); 451 kd->cpu_data = _kvm_malloc(kd, cpu_hdr.c_size);
447 if (kd->cpu_data == NULL) 452 if (kd->cpu_data == NULL)
448 goto fail; 453 goto fail;
449 sz = Pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size, (off_t)offset); 454 sz = Pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size, (off_t)offset);
450 if (sz != cpu_hdr.c_size) 455 if (sz != cpu_hdr.c_size)
451 goto fail; 456 goto fail;
452 offset += cpu_hdr.c_size; 457 offset += cpu_hdr.c_size;
453 458
454 /* 459 /*
455 * Read the next segment header: data segment 460 * Read the next segment header: data segment
456 */ 461 */
457 sz = Pread(kd, kd->pmfd, &mem_hdr, sizeof(mem_hdr), (off_t)offset); 462 sz = Pread(kd, kd->pmfd, &mem_hdr, sizeof(mem_hdr), (off_t)offset);
458 if (sz != sizeof(mem_hdr)) 463 if (sz != sizeof(mem_hdr))
459 goto fail; 464 goto fail;
460 offset += kcore_hdr.c_seghdrsize; 465 offset += kcore_hdr.c_seghdrsize;
461 466
462 if ((CORE_GETMAGIC(mem_hdr) != KCORESEG_MAGIC) || 467 if ((CORE_GETMAGIC(mem_hdr) != KCORESEG_MAGIC) ||
463 (CORE_GETFLAG(mem_hdr) != CORE_DATA)) 468 (CORE_GETFLAG(mem_hdr) != CORE_DATA))
464 goto fail; 469 goto fail;
465 470
466 kd->dump_off = offset; 471 kd->dump_off = offset;
467 return (0); 472 return (0);
468 473
469fail: 474fail:
470 if (kd->kcore_hdr != NULL) { 475 if (kd->kcore_hdr != NULL) {
471 free(kd->kcore_hdr); 476 free(kd->kcore_hdr);
472 kd->kcore_hdr = NULL; 477 kd->kcore_hdr = NULL;
473 } 478 }
474 if (kd->cpu_data != NULL) { 479 if (kd->cpu_data != NULL) {
475 free(kd->cpu_data); 480 free(kd->cpu_data);
476 kd->cpu_data = NULL; 481 kd->cpu_data = NULL;
477 kd->cpu_dsize = 0; 482 kd->cpu_dsize = 0;
478 } 483 }
479 return (-1); 484 return (-1);
480} 485}
481 486
482/* 487/*
483 * The format while on the dump device is: (new format) 488 * The format while on the dump device is: (new format)
484 * kcore_seg_t cpu_hdr; 489 * kcore_seg_t cpu_hdr;
485 * (opaque) cpu_data; (size is cpu_hdr.c_size) 490 * (opaque) cpu_data; (size is cpu_hdr.c_size)
486 * kcore_seg_t mem_hdr; 491 * kcore_seg_t mem_hdr;
487 * (memory) mem_data; (size is mem_hdr.c_size) 492 * (memory) mem_data; (size is mem_hdr.c_size)
488 */ 493 */
489int 494int
490kvm_dump_mkheader(kvm_t *kd, off_t dump_off) 495kvm_dump_mkheader(kvm_t *kd, off_t dump_off)
491{ 496{
492 kcore_seg_t cpu_hdr; 497 kcore_seg_t cpu_hdr;
493 size_t hdr_size; 498 size_t hdr_size;
494 ssize_t sz; 499 ssize_t sz;
495 500
496 if (kd->kcore_hdr != NULL) { 501 if (kd->kcore_hdr != NULL) {
497 _kvm_err(kd, kd->program, "already has a dump header"); 502 _kvm_err(kd, kd->program, "already has a dump header");
498 return (-1); 503 return (-1);
499 } 504 }
500 if (ISALIVE(kd)) { 505 if (ISALIVE(kd)) {
501 _kvm_err(kd, kd->program, "don't use on live kernel"); 506 _kvm_err(kd, kd->program, "don't use on live kernel");
502 return (-1); 507 return (-1);
503 } 508 }
504 509
505 /* 510 /*
506 * Validate new format crash dump 511 * Validate new format crash dump
507 */ 512 */
508 sz = Pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), dump_off); 513 sz = Pread(kd, kd->pmfd, &cpu_hdr, sizeof(cpu_hdr), dump_off);
509 if (sz != sizeof(cpu_hdr)) { 514 if (sz != sizeof(cpu_hdr)) {
510 if (sz == -1) 515 if (sz == -1)
511 _kvm_err(kd, 0, "read %zx bytes at offset %"PRIx64 516 _kvm_err(kd, 0, "read %zx bytes at offset %"PRIx64
512 " for cpu_hdr failed: %s", sizeof(cpu_hdr), 517 " for cpu_hdr failed: %s", sizeof(cpu_hdr),
513 dump_off, strerror(errno)); 518 dump_off, strerror(errno));
514 else 519 else
515 _kvm_err(kd, 0, "read %zx bytes at offset %"PRIx64 520 _kvm_err(kd, 0, "read %zx bytes at offset %"PRIx64
516 " for cpu_hdr instead of requested %zu", 521 " for cpu_hdr instead of requested %zu",
517 sz, dump_off, sizeof(cpu_hdr)); 522 sz, dump_off, sizeof(cpu_hdr));
518 return (-1); 523 return (-1);
519 } 524 }
520 if ((CORE_GETMAGIC(cpu_hdr) != KCORE_MAGIC) 525 if ((CORE_GETMAGIC(cpu_hdr) != KCORE_MAGIC)
521 || (CORE_GETMID(cpu_hdr) != MID_MACHINE)) { 526 || (CORE_GETMID(cpu_hdr) != MID_MACHINE)) {
522 _kvm_err(kd, 0, "invalid magic in cpu_hdr"); 527 _kvm_err(kd, 0, "invalid magic in cpu_hdr");
523 return (0); 528 return (0);
524 } 529 }
525 hdr_size = ALIGN(sizeof(cpu_hdr)); 530 hdr_size = ALIGN(sizeof(cpu_hdr));
526 531
527 /* 532 /*
528 * Read the CPU segment. 533 * Read the CPU segment.
529 */ 534 */
530 kd->cpu_dsize = cpu_hdr.c_size; 535 kd->cpu_dsize = cpu_hdr.c_size;
531 kd->cpu_data = _kvm_malloc(kd, kd->cpu_dsize); 536 kd->cpu_data = _kvm_malloc(kd, kd->cpu_dsize);
532 if (kd->cpu_data == NULL) { 537 if (kd->cpu_data == NULL) {
533 _kvm_err(kd, kd->program, "no cpu_data"); 538 _kvm_err(kd, kd->program, "no cpu_data");
534 goto fail; 539 goto fail;
535 } 540 }
536 sz = Pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size, 541 sz = Pread(kd, kd->pmfd, kd->cpu_data, cpu_hdr.c_size,
537 dump_off + hdr_size); 542 dump_off + hdr_size);
538 if (sz != cpu_hdr.c_size) { 543 if (sz != cpu_hdr.c_size) {
539 _kvm_err(kd, kd->program, "size %zu != cpu_hdr.csize %"PRIu32, 544 _kvm_err(kd, kd->program, "size %zu != cpu_hdr.csize %"PRIu32,
540 sz, cpu_hdr.c_size); 545 sz, cpu_hdr.c_size);
541 goto fail; 546 goto fail;
542 } 547 }
543 hdr_size += kd->cpu_dsize; 548 hdr_size += kd->cpu_dsize;
544 549
545 /* 550 /*
546 * Leave phys mem pointer at beginning of memory data 551 * Leave phys mem pointer at beginning of memory data
547 */ 552 */
548 kd->dump_off = dump_off + hdr_size; 553 kd->dump_off = dump_off + hdr_size;
549 if (Lseek(kd, kd->pmfd, kd->dump_off, SEEK_SET) == -1) { 554 if (Lseek(kd, kd->pmfd, kd->dump_off, SEEK_SET) == -1) {
550 _kvm_err(kd, kd->program, "failed to seek to %" PRId64, 555 _kvm_err(kd, kd->program, "failed to seek to %" PRId64,
551 (int64_t)kd->dump_off); 556 (int64_t)kd->dump_off);
552 goto fail; 557 goto fail;
553 } 558 }
554 559
555 /* 560 /*
556 * Create a kcore_hdr. 561 * Create a kcore_hdr.
557 */ 562 */
558 kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr_t)); 563 kd->kcore_hdr = _kvm_malloc(kd, sizeof(kcore_hdr_t));
559 if (kd->kcore_hdr == NULL) { 564 if (kd->kcore_hdr == NULL) {
560 _kvm_err(kd, kd->program, "failed to allocate header"); 565 _kvm_err(kd, kd->program, "failed to allocate header");
561 goto fail; 566 goto fail;
562 } 567 }
563 568
564 kd->kcore_hdr->c_hdrsize = ALIGN(sizeof(kcore_hdr_t)); 569 kd->kcore_hdr->c_hdrsize = ALIGN(sizeof(kcore_hdr_t));
565 kd->kcore_hdr->c_seghdrsize = ALIGN(sizeof(kcore_seg_t)); 570 kd->kcore_hdr->c_seghdrsize = ALIGN(sizeof(kcore_seg_t));
566 kd->kcore_hdr->c_nseg = 2; 571 kd->kcore_hdr->c_nseg = 2;
567 CORE_SETMAGIC(*(kd->kcore_hdr), KCORE_MAGIC, MID_MACHINE,0); 572 CORE_SETMAGIC(*(kd->kcore_hdr), KCORE_MAGIC, MID_MACHINE,0);
568 573
569 /* 574 /*
570 * Now that we have a valid header, enable translations. 575 * Now that we have a valid header, enable translations.
571 */ 576 */
572 if (_kvm_initvtop(kd) == 0) 577 if (_kvm_initvtop(kd) == 0)
573 /* Success */ 578 /* Success */
574 return (hdr_size); 579 return (hdr_size);
575 580
576fail: 581fail:
577 if (kd->kcore_hdr != NULL) { 582 if (kd->kcore_hdr != NULL) {
578 free(kd->kcore_hdr); 583 free(kd->kcore_hdr);
579 kd->kcore_hdr = NULL; 584 kd->kcore_hdr = NULL;
580 } 585 }
581 if (kd->cpu_data != NULL) { 586 if (kd->cpu_data != NULL) {
582 free(kd->cpu_data); 587 free(kd->cpu_data);
583 kd->cpu_data = NULL; 588 kd->cpu_data = NULL;
584 kd->cpu_dsize = 0; 589 kd->cpu_dsize = 0;
585 } 590 }
586 return (-1); 591 return (-1);
587} 592}
588 593
589static int 594static int
590clear_gap(kvm_t *kd, bool (*write_buf)(void *, const void *, size_t), 595clear_gap(kvm_t *kd, bool (*write_buf)(void *, const void *, size_t),
591 void *cookie, size_t size) 596 void *cookie, size_t size)
592{ 597{
593 char buf[1024]; 598 char buf[1024];
594 size_t len; 599 size_t len;
595 600
596 (void)memset(buf, 0, size > sizeof(buf) ? sizeof(buf) : size); 601 (void)memset(buf, 0, size > sizeof(buf) ? sizeof(buf) : size);
597 602
598 while (size > 0) { 603 while (size > 0) {
599 len = size > sizeof(buf) ? sizeof(buf) : size; 604 len = size > sizeof(buf) ? sizeof(buf) : size;
600 if (!(*write_buf)(cookie, buf, len)) { 605 if (!(*write_buf)(cookie, buf, len)) {
601 _kvm_syserr(kd, kd->program, "clear_gap"); 606 _kvm_syserr(kd, kd->program, "clear_gap");
602 return -1; 607 return -1;
603 } 608 }
604 size -= len; 609 size -= len;
605 }  610 }
606 611
607 return 0; 612 return 0;
608} 613}
609 614
610/* 615/*
611 * Write the dump header by calling write_buf with cookie as first argument. 616 * Write the dump header by calling write_buf with cookie as first argument.
612 */ 617 */
613int 618int
614kvm_dump_header(kvm_t *kd, bool (*write_buf)(void *, const void *, size_t), 619kvm_dump_header(kvm_t *kd, bool (*write_buf)(void *, const void *, size_t),
615 void *cookie, int dumpsize) 620 void *cookie, int dumpsize)
616{ 621{
617 kcore_seg_t seghdr; 622 kcore_seg_t seghdr;
618 long offset; 623 long offset;
619 size_t gap; 624 size_t gap;
620 625
621 if (kd->kcore_hdr == NULL || kd->cpu_data == NULL) { 626 if (kd->kcore_hdr == NULL || kd->cpu_data == NULL) {
622 _kvm_err(kd, kd->program, "no valid dump header(s)"); 627 _kvm_err(kd, kd->program, "no valid dump header(s)");
623 return (-1); 628 return (-1);
624 } 629 }
625 630
626 /* 631 /*
627 * Write the generic header 632 * Write the generic header
628 */ 633 */
629 offset = 0; 634 offset = 0;
630 if (!(*write_buf)(cookie, kd->kcore_hdr, sizeof(kcore_hdr_t))) { 635 if (!(*write_buf)(cookie, kd->kcore_hdr, sizeof(kcore_hdr_t))) {
631 _kvm_syserr(kd, kd->program, "kvm_dump_header"); 636 _kvm_syserr(kd, kd->program, "kvm_dump_header");
632 return (-1); 637 return (-1);
633 } 638 }
634 offset += kd->kcore_hdr->c_hdrsize; 639 offset += kd->kcore_hdr->c_hdrsize;
635 gap = kd->kcore_hdr->c_hdrsize - sizeof(kcore_hdr_t); 640 gap = kd->kcore_hdr->c_hdrsize - sizeof(kcore_hdr_t);
636 if (clear_gap(kd, write_buf, cookie, gap) == -1) 641 if (clear_gap(kd, write_buf, cookie, gap) == -1)
637 return (-1); 642 return (-1);
638 643
639 /* 644 /*
640 * Write the CPU header 645 * Write the CPU header
641 */ 646 */
642 CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_CPU); 647 CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_CPU);
643 seghdr.c_size = ALIGN(kd->cpu_dsize); 648 seghdr.c_size = ALIGN(kd->cpu_dsize);
644 if (!(*write_buf)(cookie, &seghdr, sizeof(seghdr))) { 649 if (!(*write_buf)(cookie, &seghdr, sizeof(seghdr))) {
645 _kvm_syserr(kd, kd->program, "kvm_dump_header"); 650 _kvm_syserr(kd, kd->program, "kvm_dump_header");
646 return (-1); 651 return (-1);
647 } 652 }
648 offset += kd->kcore_hdr->c_seghdrsize; 653 offset += kd->kcore_hdr->c_seghdrsize;
649 gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr); 654 gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr);
650 if (clear_gap(kd, write_buf, cookie, gap) == -1) 655 if (clear_gap(kd, write_buf, cookie, gap) == -1)
651 return (-1); 656 return (-1);
652 657
653 if (!(*write_buf)(cookie, kd->cpu_data, kd->cpu_dsize)) { 658 if (!(*write_buf)(cookie, kd->cpu_data, kd->cpu_dsize)) {
654 _kvm_syserr(kd, kd->program, "kvm_dump_header"); 659 _kvm_syserr(kd, kd->program, "kvm_dump_header");
655 return (-1); 660 return (-1);
656 } 661 }
657 offset += seghdr.c_size; 662 offset += seghdr.c_size;
658 gap = seghdr.c_size - kd->cpu_dsize; 663 gap = seghdr.c_size - kd->cpu_dsize;
659 if (clear_gap(kd, write_buf, cookie, gap) == -1) 664 if (clear_gap(kd, write_buf, cookie, gap) == -1)
660 return (-1); 665 return (-1);
661 666
662 /* 667 /*
663 * Write the actual dump data segment header 668 * Write the actual dump data segment header
664 */ 669 */
665 CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_DATA); 670 CORE_SETMAGIC(seghdr, KCORESEG_MAGIC, 0, CORE_DATA);
666 seghdr.c_size = dumpsize; 671 seghdr.c_size = dumpsize;
667 if (!(*write_buf)(cookie, &seghdr, sizeof(seghdr))) { 672 if (!(*write_buf)(cookie, &seghdr, sizeof(seghdr))) {
668 _kvm_syserr(kd, kd->program, "kvm_dump_header"); 673 _kvm_syserr(kd, kd->program, "kvm_dump_header");
669 return (-1); 674 return (-1);
670 } 675 }
671 offset += kd->kcore_hdr->c_seghdrsize; 676 offset += kd->kcore_hdr->c_seghdrsize;
672 gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr); 677 gap = kd->kcore_hdr->c_seghdrsize - sizeof(seghdr);
673 if (clear_gap(kd, write_buf, cookie, gap) == -1) 678 if (clear_gap(kd, write_buf, cookie, gap) == -1)
674 return (-1); 679 return (-1);
675 680
676 return (int)offset; 681 return (int)offset;
677} 682}
678 683
679static bool 684static bool
680kvm_dump_header_stdio(void *cookie, const void *buf, size_t len) 685kvm_dump_header_stdio(void *cookie, const void *buf, size_t len)
681{ 686{
682 return fwrite(buf, len, 1, (FILE *)cookie) == 1; 687 return fwrite(buf, len, 1, (FILE *)cookie) == 1;
683} 688}
684 689
685int 690int
686kvm_dump_wrtheader(kvm_t *kd, FILE *fp, int dumpsize) 691kvm_dump_wrtheader(kvm_t *kd, FILE *fp, int dumpsize)
687{ 692{
688 return kvm_dump_header(kd, kvm_dump_header_stdio, fp, dumpsize); 693 return kvm_dump_header(kd, kvm_dump_header_stdio, fp, dumpsize);
689} 694}
690 695
691kvm_t * 696kvm_t *
692kvm_openfiles(const char *uf, const char *mf, const char *sf, 697kvm_openfiles(const char *uf, const char *mf, const char *sf,
693 int flag, char *errout) 698 int flag, char *errout)
694{ 699{
695 kvm_t *kd; 700 kvm_t *kd;
696 701
697 if ((kd = malloc(sizeof(*kd))) == NULL) { 702 if ((kd = malloc(sizeof(*kd))) == NULL) {
698 (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX); 703 (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX);
699 return (0); 704 return (0);
700 } 705 }
701 kd->program = 0; 706 kd->program = 0;
702 return (_kvm_open(kd, uf, mf, sf, flag, errout)); 707 return (_kvm_open(kd, uf, mf, sf, flag, errout));
703} 708}
704 709
705kvm_t * 710kvm_t *
706kvm_open(const char *uf, const char *mf, const char *sf, int flag, 711kvm_open(const char *uf, const char *mf, const char *sf, int flag,
707 const char *program) 712 const char *program)
708{ 713{
709 kvm_t *kd; 714 kvm_t *kd;
710 715
711 if ((kd = malloc(sizeof(*kd))) == NULL) { 716 if ((kd = malloc(sizeof(*kd))) == NULL) {
712 (void)fprintf(stderr, "%s: %s\n", 717 (void)fprintf(stderr, "%s: %s\n",
713 program ? program : getprogname(), strerror(errno)); 718 program ? program : getprogname(), strerror(errno));
714 return (0); 719 return (0);
715 } 720 }
716 kd->program = program; 721 kd->program = program;
717 return (_kvm_open(kd, uf, mf, sf, flag, NULL)); 722 return (_kvm_open(kd, uf, mf, sf, flag, NULL));
718} 723}
719 724
720int 725int
721kvm_close(kvm_t *kd) 726kvm_close(kvm_t *kd)
722{ 727{
723 int error = 0; 728 int error = 0;
724 729
725 if (kd->pmfd >= 0) 730 if (kd->pmfd >= 0)
726 error |= close(kd->pmfd); 731 error |= close(kd->pmfd);
727 if (kd->vmfd >= 0) 732 if (kd->vmfd >= 0)
728 error |= close(kd->vmfd); 733 error |= close(kd->vmfd);
729 if (kd->nlfd >= 0) 734 if (kd->nlfd >= 0)
730 error |= close(kd->nlfd); 735 error |= close(kd->nlfd);
731 if (kd->swfd >= 0) 736 if (kd->swfd >= 0)
732 error |= close(kd->swfd); 737 error |= close(kd->swfd);
733 if (kd->vmst) 738 if (kd->vmst)
734 _kvm_freevtop(kd); 739 _kvm_freevtop(kd);
735 kd->cpu_dsize = 0; 740 kd->cpu_dsize = 0;
736 if (kd->cpu_data != NULL) 741 if (kd->cpu_data != NULL)
737 free(kd->cpu_data); 742 free(kd->cpu_data);
738 if (kd->kcore_hdr != NULL) 743 if (kd->kcore_hdr != NULL)
739 free(kd->kcore_hdr); 744 free(kd->kcore_hdr);
740 if (kd->procbase != 0) 745 if (kd->procbase != 0)
741 free(kd->procbase); 746 free(kd->procbase);
742 if (kd->procbase2 != 0) 747 if (kd->procbase2 != 0)
743 free(kd->procbase2); 748 free(kd->procbase2);
744 if (kd->lwpbase != 0) 749 if (kd->lwpbase != 0)
745 free(kd->lwpbase); 750 free(kd->lwpbase);
746 if (kd->swapspc != 0) 751 if (kd->swapspc != 0)
747 free(kd->swapspc); 752 free(kd->swapspc);
748 if (kd->argspc != 0) 753 if (kd->argspc != 0)
749 free(kd->argspc); 754 free(kd->argspc);
750 if (kd->argbuf != 0) 755 if (kd->argbuf != 0)
751 free(kd->argbuf); 756 free(kd->argbuf);
752 if (kd->argv != 0) 757 if (kd->argv != 0)
753 free(kd->argv); 758 free(kd->argv);
754 if (kd->iobuf != 0) 759 if (kd->iobuf != 0)
755 free(kd->iobuf); 760 free(kd->iobuf);
756 free(kd); 761 free(kd);
757 762
758 return (error); 763 return (error);
759} 764}
760 765
761int 766int
762kvm_nlist(kvm_t *kd, struct nlist *nl) 767kvm_nlist(kvm_t *kd, struct nlist *nl)
763{ 768{
764 int rv; 769 int rv;
765 770
766 /* 771 /*
767 * Call the nlist(3) routines to retrieve the given namelist. 772 * Call the nlist(3) routines to retrieve the given namelist.
768 */ 773 */
769 rv = __fdnlist(kd->nlfd, nl); 774 rv = __fdnlist(kd->nlfd, nl);
770 775
771 if (rv == -1) 776 if (rv == -1)
772 _kvm_err(kd, 0, "bad namelist"); 777 _kvm_err(kd, 0, "bad namelist");
773 778
774 return (rv); 779 return (rv);
775} 780}
776 781
777int 782int
778kvm_dump_inval(kvm_t *kd) 783kvm_dump_inval(kvm_t *kd)
779{ 784{
780 struct nlist nl[2]; 785 struct nlist nl[2];
781 paddr_t pa; 786 paddr_t pa;
782 size_t dsize; 787 size_t dsize;
783 off_t doff; 788 off_t doff;
784 void *newbuf; 789 void *newbuf;
785 790
786 if (ISALIVE(kd)) { 791 if (ISALIVE(kd)) {
787 _kvm_err(kd, kd->program, "clearing dump on live kernel"); 792 _kvm_err(kd, kd->program, "clearing dump on live kernel");
788 return (-1); 793 return (-1);
789 } 794 }
790 nl[0].n_name = "_dumpmag"; 795 nl[0].n_name = "_dumpmag";
791 nl[1].n_name = NULL; 796 nl[1].n_name = NULL;
792 797
793 if (kvm_nlist(kd, nl) == -1) { 798 if (kvm_nlist(kd, nl) == -1) {
794 _kvm_err(kd, 0, "bad namelist"); 799 _kvm_err(kd, 0, "bad namelist");
795 return (-1); 800 return (-1);
796 } 801 }
797 if (_kvm_kvatop(kd, (vaddr_t)nl[0].n_value, &pa) == 0) 802 if (_kvm_kvatop(kd, (vaddr_t)nl[0].n_value, &pa) == 0)
798 return (-1); 803 return (-1);
799 804
800 errno = 0; 805 errno = 0;
801 dsize = MAX(kd->fdalign, sizeof(u_long)); 806 dsize = MAX(kd->fdalign, sizeof(u_long));
802 if (kd->iobufsz < dsize) { 807 if (kd->iobufsz < dsize) {
803 newbuf = realloc(kd->iobuf, dsize); 808 newbuf = realloc(kd->iobuf, dsize);
804 if (newbuf == NULL) { 809 if (newbuf == NULL) {
805 _kvm_syserr(kd, 0, "cannot allocate I/O buffer"); 810 _kvm_syserr(kd, 0, "cannot allocate I/O buffer");
806 return (-1); 811 return (-1);
807 } 812 }
808 kd->iobuf = newbuf; 813 kd->iobuf = newbuf;
809 kd->iobufsz = dsize; 814 kd->iobufsz = dsize;
810 } 815 }
811 memset(kd->iobuf, 0, dsize); 816 memset(kd->iobuf, 0, dsize);
812 doff = _kvm_pa2off(kd, pa); 817 doff = _kvm_pa2off(kd, pa);
813 doff -= doff % kd->fdalign; 818 doff -= doff % kd->fdalign;
814 if (pwrite(kd->pmfd, kd->iobuf, dsize, doff) == -1) { 819 if (pwrite(kd->pmfd, kd->iobuf, dsize, doff) == -1) {
815 _kvm_syserr(kd, 0, "cannot invalidate dump - pwrite"); 820 _kvm_syserr(kd, 0, "cannot invalidate dump - pwrite");
816 return (-1); 821 return (-1);
817 } 822 }
818 return (0); 823 return (0);
819} 824}
820 825
821ssize_t 826ssize_t
822kvm_read(kvm_t *kd, u_long kva, void *buf, size_t len) 827kvm_read(kvm_t *kd, u_long kva, void *buf, size_t len)
823{ 828{
824 int cc; 829 int cc;
825 void *cp; 830 void *cp;
826 831
827 if (ISKMEM(kd)) { 832 if (ISKMEM(kd)) {
828 /* 833 /*
829 * We're using /dev/kmem. Just read straight from the 834 * We're using /dev/kmem. Just read straight from the
830 * device and let the active kernel do the address translation. 835 * device and let the active kernel do the address translation.
831 */ 836 */
832 errno = 0; 837 errno = 0;
833 cc = _kvm_pread(kd, kd->vmfd, buf, len, (off_t)kva); 838 cc = _kvm_pread(kd, kd->vmfd, buf, len, (off_t)kva);
834 if (cc < 0) { 839 if (cc < 0) {
835 _kvm_syserr(kd, 0, "kvm_read"); 840 _kvm_syserr(kd, 0, "kvm_read");
836 return (-1); 841 return (-1);
837 } else if (cc < len) 842 } else if (cc < len)
838 _kvm_err(kd, kd->program, "short read"); 843 _kvm_err(kd, kd->program, "short read");
839 return (cc); 844 return (cc);
840 } else if (ISSYSCTL(kd)) { 845 } else if (ISSYSCTL(kd)) {
841 _kvm_err(kd, kd->program, "kvm_open called with KVM_NO_FILES, " 846 _kvm_err(kd, kd->program, "kvm_open called with KVM_NO_FILES, "
842 "can't use kvm_read"); 847 "can't use kvm_read");
843 return (-1); 848 return (-1);
844 } else { 849 } else {
845 if ((kd->kcore_hdr == NULL) || (kd->cpu_data == NULL)) { 850 if ((kd->kcore_hdr == NULL) || (kd->cpu_data == NULL)) {
846 _kvm_err(kd, kd->program, "no valid dump header"); 851 _kvm_err(kd, kd->program, "no valid dump header");
847 return (-1); 852 return (-1);
848 } 853 }
849 cp = buf; 854 cp = buf;
850 while (len > 0) { 855 while (len > 0) {
851 paddr_t pa; 856 paddr_t pa;
852 off_t foff; 857 off_t foff;
853 858
854 cc = _kvm_kvatop(kd, (vaddr_t)kva, &pa); 859 cc = _kvm_kvatop(kd, (vaddr_t)kva, &pa);
855 if (cc == 0) { 860 if (cc == 0) {
856 _kvm_err(kd, kd->program, "_kvm_kvatop(%lx)", kva); 861 _kvm_err(kd, kd->program, "_kvm_kvatop(%lx)", kva);
857 return (-1); 862 return (-1);
858 } 863 }
859 if (cc > len) 864 if (cc > len)
860 cc = len; 865 cc = len;
861 foff = _kvm_pa2off(kd, pa); 866 foff = _kvm_pa2off(kd, pa);
862 errno = 0; 867 errno = 0;
863 cc = _kvm_pread(kd, kd->pmfd, cp, (size_t)cc, foff); 868 cc = _kvm_pread(kd, kd->pmfd, cp, (size_t)cc, foff);
864 if (cc < 0) { 869 if (cc < 0) {
865 _kvm_syserr(kd, kd->program, "kvm_read"); 870 _kvm_syserr(kd, kd->program, "kvm_read");
866 break; 871 break;
867 } 872 }
868 /* 873 /*
869 * If kvm_kvatop returns a bogus value or our core 874 * If kvm_kvatop returns a bogus value or our core
870 * file is truncated, we might wind up seeking beyond 875 * file is truncated, we might wind up seeking beyond
871 * the end of the core file in which case the read will 876 * the end of the core file in which case the read will
872 * return 0 (EOF). 877 * return 0 (EOF).
873 */ 878 */
874 if (cc == 0) 879 if (cc == 0)
875 break; 880 break;
876 cp = (char *)cp + cc; 881 cp = (char *)cp + cc;
877 kva += cc; 882 kva += cc;
878 len -= cc; 883 len -= cc;
879 } 884 }
880 return ((char *)cp - (char *)buf); 885 return ((char *)cp - (char *)buf);
881 } 886 }
882 /* NOTREACHED */ 887 /* NOTREACHED */
883} 888}
884 889
885ssize_t 890ssize_t
886kvm_write(kvm_t *kd, u_long kva, const void *buf, size_t len) 891kvm_write(kvm_t *kd, u_long kva, const void *buf, size_t len)
887{ 892{
888 int cc; 893 int cc;
889 894
890 if (ISKMEM(kd)) { 895 if (ISKMEM(kd)) {
891 /* 896 /*
892 * Just like kvm_read, only we write. 897 * Just like kvm_read, only we write.
893 */ 898 */
894 errno = 0; 899 errno = 0;
895 cc = pwrite(kd->vmfd, buf, len, (off_t)kva); 900 cc = pwrite(kd->vmfd, buf, len, (off_t)kva);
896 if (cc < 0) { 901 if (cc < 0) {
897 _kvm_syserr(kd, 0, "kvm_write"); 902 _kvm_syserr(kd, 0, "kvm_write");
898 return (-1); 903 return (-1);
899 } else if (cc < len) 904 } else if (cc < len)
900 _kvm_err(kd, kd->program, "short write"); 905 _kvm_err(kd, kd->program, "short write");
901 return (cc); 906 return (cc);
902 } else if (ISSYSCTL(kd)) { 907 } else if (ISSYSCTL(kd)) {
903 _kvm_err(kd, kd->program, "kvm_open called with KVM_NO_FILES, " 908 _kvm_err(kd, kd->program, "kvm_open called with KVM_NO_FILES, "
904 "can't use kvm_write"); 909 "can't use kvm_write");
905 return (-1); 910 return (-1);
906 } else { 911 } else {
907 _kvm_err(kd, kd->program, 912 _kvm_err(kd, kd->program,
908 "kvm_write not implemented for dead kernels"); 913 "kvm_write not implemented for dead kernels");
909 return (-1); 914 return (-1);
910 } 915 }
911 /* NOTREACHED */ 916 /* NOTREACHED */
912} 917}