Correct BSD License clause numbering from 1-2-4 to 1-2-3.
[dragonfly.git] / lib / libkvm / kvm.c
1 /*-
2  * Copyright (c) 1989, 1992, 1993
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * This code is derived from software developed by the Computer Systems
6  * Engineering group at Lawrence Berkeley Laboratory under DARPA contract
7  * BG 91-66 and contributed to Berkeley.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * @(#)kvm.c    8.2 (Berkeley) 2/13/94
34  * $FreeBSD: src/lib/libkvm/kvm.c,v 1.12.2.3 2002/09/13 14:53:43 nectar Exp $
35  */
36
37 #include <sys/user.h>   /* MUST BE FIRST */
38 #include <sys/param.h>
39 #include <sys/proc.h>
40 #include <sys/ioctl.h>
41 #include <sys/stat.h>
42 #include <sys/sysctl.h>
43 #include <sys/linker.h>
44
45 #include <vm/vm.h>
46 #include <vm/vm_param.h>
47 #include <vm/swap_pager.h>
48
49 #include <machine/vmparam.h>
50
51 #include <ctype.h>
52 #include <fcntl.h>
53 #include <kvm.h>
54 #include <limits.h>
55 #include <nlist.h>
56 #include <paths.h>
57 #include <stdio.h>
58 #include <stdlib.h>
59 #include <string.h>
60 #include <stdarg.h>
61 #include <unistd.h>
62
63 #include "kvm_private.h"
64
65 /* from src/lib/libc/gen/nlist.c */
66 int __fdnlist           (int, struct nlist *);
67
68 char *
69 kvm_geterr(kvm_t *kd)
70 {
71         return (kd->errbuf);
72 }
73
74 /*
75  * Report an error using printf style arguments.  "program" is kd->program
76  * on hard errors, and 0 on soft errors, so that under sun error emulation,
77  * only hard errors are printed out (otherwise, programs like gdb will
78  * generate tons of error messages when trying to access bogus pointers).
79  */
80 void
81 _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...)
82 {
83         va_list ap;
84
85         va_start(ap, fmt);
86         if (program != NULL) {
87                 (void)fprintf(stderr, "%s: ", program);
88                 (void)vfprintf(stderr, fmt, ap);
89                 (void)fputc('\n', stderr);
90         } else
91                 (void)vsnprintf(kd->errbuf,
92                     sizeof(kd->errbuf), (char *)fmt, ap);
93
94         va_end(ap);
95 }
96
97 void
98 _kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...)
99 {
100         va_list ap;
101         int n;
102
103         va_start(ap, fmt);
104         if (program != NULL) {
105                 (void)fprintf(stderr, "%s: ", program);
106                 (void)vfprintf(stderr, fmt, ap);
107                 (void)fprintf(stderr, ": %s\n", strerror(errno));
108         } else {
109                 char *cp = kd->errbuf;
110
111                 (void)vsnprintf(cp, sizeof(kd->errbuf), (char *)fmt, ap);
112                 n = strlen(cp);
113                 (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s",
114                     strerror(errno));
115         }
116         va_end(ap);
117 }
118
119 void *
120 _kvm_malloc(kvm_t *kd, size_t n)
121 {
122         void *p;
123
124         if ((p = calloc(n, sizeof(char))) == NULL)
125                 _kvm_err(kd, kd->program, "can't allocate %zd bytes: %s",
126                          n, strerror(errno));
127         return (p);
128 }
129
130 static int
131 is_proc_mem(const char *p)
132 {
133         static char proc[] = "/proc/";
134         static char mem[] = "/mem";
135         if (strncmp(proc, p, sizeof(proc) - 1))
136                 return 0;
137         p += sizeof(proc) - 1;
138         for (; p != '\0'; ++p)
139                 if (!isdigit(*p))
140                         break;
141         if (!isdigit(*(p - 1)))
142                 return 0;
143         return !strncmp(p, mem, sizeof(mem) - 1);
144 }
145
146 static kvm_t *
147 _kvm_open(kvm_t *kd, const char *uf, const char *mf, int flag, char *errout)
148 {
149         struct stat st;
150
151         kd->vmfd = -1;
152         kd->pmfd = -1;
153         kd->nlfd = -1;
154         kd->vmst = 0;
155         kd->procbase = NULL;
156         kd->procend = NULL;
157         kd->argspc = 0;
158         kd->argv = 0;
159         kd->flags = 0;
160
161         if (uf == NULL)
162                 uf = getbootfile();
163         else if (strlen(uf) >= MAXPATHLEN) {
164                 _kvm_err(kd, kd->program, "exec file name too long");
165                 goto failed;
166         }
167         if (flag & ~O_RDWR) {
168                 _kvm_err(kd, kd->program, "bad flags arg");
169                 goto failed;
170         }
171         if (mf == NULL)
172                 mf = _PATH_MEM;
173
174         if ((kd->pmfd = open(mf, flag, 0)) < 0) {
175                 _kvm_syserr(kd, kd->program, "%s", mf);
176                 goto failed;
177         }
178         if (fstat(kd->pmfd, &st) < 0) {
179                 _kvm_syserr(kd, kd->program, "%s", mf);
180                 goto failed;
181         }
182         if (fcntl(kd->pmfd, F_SETFD, FD_CLOEXEC) < 0) {
183                 _kvm_syserr(kd, kd->program, "%s", mf);
184                 goto failed;
185         }
186         if (S_ISCHR(st.st_mode)) {
187                 /*
188                  * If this is a character special device, then check that
189                  * it's /dev/mem.  If so, open kmem too.  (Maybe we should
190                  * make it work for either /dev/mem or /dev/kmem -- in either
191                  * case you're working with a live kernel.)
192                  */
193                 if (strcmp(mf, _PATH_DEVNULL) == 0) {
194                         kd->vmfd = open(_PATH_DEVNULL, O_RDONLY);
195                 } else {
196                         if ((kd->vmfd = open(_PATH_KMEM, flag)) < 0) {
197                                 _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
198                                 goto failed;
199                         }
200                         if (fcntl(kd->vmfd, F_SETFD, FD_CLOEXEC) < 0) {
201                                 _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
202                                 goto failed;
203                         }
204                 }
205                 kd->flags |= KVMF_HOST;
206         } else {
207                 /*
208                  * Crash dump or vkernel /proc/$pid/mem file:
209                  * can't use kldsym, we are going to need ->nlfd
210                  */
211                 if ((kd->nlfd = open(uf, O_RDONLY, 0)) < 0) {
212                         _kvm_syserr(kd, kd->program, "%s", uf);
213                         goto failed;
214                 }
215                 if (fcntl(kd->nlfd, F_SETFD, FD_CLOEXEC) < 0) {
216                         _kvm_syserr(kd, kd->program, "%s", uf);
217                         goto failed;
218                 }
219                 if(is_proc_mem(mf)) {
220                         /*
221                          * It's /proc/$pid/mem, so we rely on the host
222                          * kernel to do address translation for us.
223                          */
224                         kd->vmfd = kd->pmfd;
225                         kd->pmfd = -1;
226                         kd->flags |= KVMF_VKERN;
227                 } else {
228                         if (st.st_size <= 0) {
229                                 errno = EINVAL;
230                                 _kvm_syserr(kd, kd->program, "empty file");
231                                 goto failed;
232                         }
233                         
234                         /*
235                          * This is a crash dump.
236                          * Initialize the virtual address translation machinery,
237                          * but first setup the namelist fd.
238                          */
239                         if (_kvm_initvtop(kd) < 0)
240                                 goto failed;
241                 }
242         }
243         return (kd);
244 failed:
245         /*
246          * Copy out the error if doing sane error semantics.
247          */
248         if (errout != NULL)
249                 strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX);
250         (void)kvm_close(kd);
251         return (0);
252 }
253
254 kvm_t *
255 kvm_openfiles(const char *uf, const char *mf, const char *sf, int flag,
256               char *errout)
257 {
258         kvm_t *kd;
259
260         if ((kd = malloc(sizeof(*kd))) == NULL) {
261                 (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX);
262                 return (0);
263         }
264         memset(kd, 0, sizeof(*kd));
265         kd->program = 0;
266         return (_kvm_open(kd, uf, mf, flag, errout));
267 }
268
269 kvm_t *
270 kvm_open(const char *uf, const char *mf, const char *sf, int flag,
271          const char *errstr)
272 {
273         kvm_t *kd;
274
275         if ((kd = malloc(sizeof(*kd))) == NULL) {
276                 if (errstr != NULL)
277                         (void)fprintf(stderr, "%s: %s\n",
278                                       errstr, strerror(errno));
279                 return (0);
280         }
281         memset(kd, 0, sizeof(*kd));
282         kd->program = errstr;
283         return (_kvm_open(kd, uf, mf, flag, NULL));
284 }
285
286 int
287 kvm_close(kvm_t *kd)
288 {
289         int error = 0;
290
291         if (kd->pmfd >= 0)
292                 error |= close(kd->pmfd);
293         if (kd->vmfd >= 0)
294                 error |= close(kd->vmfd);
295         if (kd->nlfd >= 0)
296                 error |= close(kd->nlfd);
297         if (kd->vmst)
298                 _kvm_freevtop(kd);
299         if (kd->procbase != NULL)
300                 free(kd->procbase);
301         if (kd->argv != 0)
302                 free((void *)kd->argv);
303         free((void *)kd);
304
305         return (0);
306 }
307
308 int
309 kvm_nlist(kvm_t *kd, struct nlist *nl)
310 {
311         struct nlist *p;
312         int nvalid;
313         struct kld_sym_lookup lookup;
314         int error;
315
316         /*
317          * If we can't use the kld symbol lookup, revert to the
318          * slow library call.
319          */
320         if (!kvm_ishost(kd))
321                 return (__fdnlist(kd->nlfd, nl));
322
323         /*
324          * We can use the kld lookup syscall.  Go through each nlist entry
325          * and look it up with a kldsym(2) syscall.
326          */
327         nvalid = 0;
328         for (p = nl; p->n_name && p->n_name[0]; ++p) {
329                 lookup.version = sizeof(lookup);
330                 lookup.symname = p->n_name;
331                 lookup.symvalue = 0;
332                 lookup.symsize = 0;
333
334                 if (lookup.symname[0] == '_')
335                         lookup.symname++;
336
337                 if (kldsym(0, KLDSYM_LOOKUP, &lookup) != -1) {
338                         p->n_type = N_TEXT;
339                         p->n_other = 0;
340                         p->n_desc = 0;
341                         p->n_value = lookup.symvalue;
342                         ++nvalid;
343                         /* lookup.symsize */
344                 }
345         }
346         /*
347          * Return the number of entries that weren't found. If they exist,
348          * also fill internal error buffer.
349          */
350         error = ((p - nl) - nvalid);
351         if (error)
352                 _kvm_syserr(kd, kd->program, "kvm_nlist");
353         return (error);
354 }
355
356 ssize_t
357 kvm_read(kvm_t *kd, u_long kva, void *buf, size_t len)
358 {
359         int cc;
360         void *cp;
361
362         if (kvm_notrans(kd)) {
363                 /*
364                  * We're using /dev/kmem.  Just read straight from the
365                  * device and let the active kernel do the address translation.
366                  */
367                 errno = 0;
368                 if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) {
369                         _kvm_err(kd, 0, "invalid address (%lx)", kva);
370                         return (-1);
371                 }
372
373                 /*
374                  * Try to pre-fault the user memory to reduce instances of
375                  * races within the kernel.  XXX workaround for kernel bug
376                  * where kernel does a sanity check, but user faults during
377                  * the copy can block and race against another kernel entity
378                  * unmapping the memory in question.
379                  */
380                 bzero(buf, len);
381                 cc = read(kd->vmfd, buf, len);
382                 if (cc < 0) {
383                         _kvm_syserr(kd, 0, "kvm_read");
384                         return (-1);
385                 } else if (cc < len)
386                         _kvm_err(kd, kd->program, "short read");
387                 return (cc);
388         } else {
389                 cp = buf;
390                 while (len > 0) {
391                         off_t pa;
392
393                         cc = _kvm_kvatop(kd, kva, &pa);
394                         if (cc == 0)
395                                 return (-1);
396                         if (cc > len)
397                                 cc = len;
398                         errno = 0;
399                         if (lseek(kd->pmfd, pa, 0) == -1 && errno != 0) {
400                                 _kvm_syserr(kd, 0, _PATH_MEM);
401                                 break;
402                         }
403                         bzero(cp, cc);
404                         cc = read(kd->pmfd, cp, cc);
405                         if (cc < 0) {
406                                 _kvm_syserr(kd, kd->program, "kvm_read");
407                                 break;
408                         }
409                         /*
410                          * If kvm_kvatop returns a bogus value or our core
411                          * file is truncated, we might wind up seeking beyond
412                          * the end of the core file in which case the read will
413                          * return 0 (EOF).
414                          */
415                         if (cc == 0)
416                                 break;
417                         cp = (char *)cp + cc;
418                         kva += cc;
419                         len -= cc;
420                 }
421                 return ((char *)cp - (char *)buf);
422         }
423         /* NOTREACHED */
424 }
425
426 char *
427 kvm_readstr(kvm_t *kd, u_long kva, char *buf, size_t *lenp)
428 {
429         size_t len, cc, pos;
430         char ch;
431         int asize = -1;
432
433         if (buf == NULL) {
434                 asize = len = 16;
435                 buf = malloc(len);
436                 if (buf == NULL) {
437                         _kvm_syserr(kd, kd->program, "kvm_readstr");
438                         return NULL;
439                 }
440         } else {
441                 len = *lenp;
442         }
443
444         if (kvm_notrans(kd)) {
445                 /*
446                  * We're using /dev/kmem.  Just read straight from the
447                  * device and let the active kernel do the address translation.
448                  */
449                 errno = 0;
450                 if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) {
451                         _kvm_err(kd, 0, "invalid address (%lx)", kva);
452                         return NULL;
453                 }
454
455                 for (pos = 0, ch = -1; ch != 0; pos++) {
456                         cc = read(kd->vmfd, &ch, 1);
457                         if ((ssize_t)cc < 0) {
458                                 _kvm_syserr(kd, 0, "kvm_readstr");
459                                 return NULL;
460                         } else if (cc < 1)
461                                 _kvm_err(kd, kd->program, "short read");
462                         if (pos == asize) {
463                                 buf = realloc(buf, asize *= 2);
464                                 if (buf == NULL) {
465                                         _kvm_syserr(kd, kd->program, "kvm_readstr");
466                                         return NULL;
467                                 }
468                                 len = asize;
469                         }
470                         if (pos < len)
471                                 buf[pos] = ch;
472                 }
473
474                 if (lenp != NULL)
475                         *lenp = pos;
476                 if (pos > len)
477                         return NULL;
478                 else
479                         return buf;
480         } else {
481                 size_t left = 0;
482                 for (pos = 0, ch = -1; ch != 0; pos++, left--, kva++) {
483                         if (left == 0) {
484                                 off_t pa;
485
486                                 left = _kvm_kvatop(kd, kva, &pa);
487                                 if (left == 0)
488                                         return NULL;
489                                 errno = 0;
490                                 if (lseek(kd->pmfd, (off_t)pa, 0) == -1 && errno != 0) {
491                                         _kvm_syserr(kd, 0, _PATH_MEM);
492                                         return NULL;
493                                 }
494                         }
495                         cc = read(kd->pmfd, &ch, 1);
496                         if ((ssize_t)cc < 0) {
497                                 _kvm_syserr(kd, 0, "kvm_readstr");
498                                 return NULL;
499                         } else if (cc < 1)
500                                 _kvm_err(kd, kd->program, "short read");
501                         if (pos == asize) {
502                                 buf = realloc(buf, asize *= 2);
503                                 if (buf == NULL) {
504                                         _kvm_syserr(kd, kd->program, "kvm_readstr");
505                                         return NULL;
506                                 }
507                                 len = asize;
508                         }
509                         if (pos < len)
510                                 buf[pos] = ch;
511                 }
512
513                 if (lenp != NULL)
514                         *lenp = pos;
515                 if (pos > len)
516                         return NULL;
517                 else
518                         return buf;
519         }
520         /* NOTREACHED */
521 }
522
523 ssize_t
524 kvm_write(kvm_t *kd, u_long kva, const void *buf, size_t len)
525 {
526         int cc;
527
528         if (kvm_notrans(kd)) {
529                 /*
530                  * Just like kvm_read, only we write.
531                  */
532                 errno = 0;
533                 if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) {
534                         _kvm_err(kd, 0, "invalid address (%lx)", kva);
535                         return (-1);
536                 }
537                 cc = write(kd->vmfd, buf, len);
538                 if (cc < 0) {
539                         _kvm_syserr(kd, 0, "kvm_write");
540                         return (-1);
541                 } else if (cc < len)
542                         _kvm_err(kd, kd->program, "short write");
543                 return (cc);
544         } else {
545                 _kvm_err(kd, kd->program,
546                     "kvm_write not implemented for dead kernels");
547                 return (-1);
548         }
549         /* NOTREACHED */
550 }