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