]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - lib/libkvm/kvm.c
MFC r347990:
[FreeBSD/stable/10.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  * 4. 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
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #if defined(LIBC_SCCS) && !defined(lint)
38 #if 0
39 static char sccsid[] = "@(#)kvm.c       8.2 (Berkeley) 2/13/94";
40 #endif
41 #endif /* LIBC_SCCS and not lint */
42
43 #include <sys/param.h>
44
45 #define _WANT_VNET
46
47 #include <sys/user.h>
48 #include <sys/proc.h>
49 #include <sys/ioctl.h>
50 #include <sys/stat.h>
51 #include <sys/sysctl.h>
52 #include <sys/linker.h>
53 #include <sys/pcpu.h>
54
55 #include <net/vnet.h>
56
57 #include <vm/vm.h>
58 #include <vm/vm_param.h>
59
60 #include <machine/vmparam.h>
61
62 #include <ctype.h>
63 #include <fcntl.h>
64 #include <kvm.h>
65 #include <limits.h>
66 #include <nlist.h>
67 #include <paths.h>
68 #include <stdio.h>
69 #include <stdlib.h>
70 #include <string.h>
71 #include <strings.h>
72 #include <unistd.h>
73
74 #include "kvm_private.h"
75
76 /* from src/lib/libc/gen/nlist.c */
77 int __fdnlist(int, struct nlist *);
78
79 static char _kd_is_null[] = "";
80
81 char *
82 kvm_geterr(kvm_t *kd)
83 {
84
85         if (kd == NULL)
86                 return (_kd_is_null);
87         return (kd->errbuf);
88 }
89
90 #include <stdarg.h>
91
92 /*
93  * Report an error using printf style arguments.  "program" is kd->program
94  * on hard errors, and 0 on soft errors, so that under sun error emulation,
95  * only hard errors are printed out (otherwise, programs like gdb will
96  * generate tons of error messages when trying to access bogus pointers).
97  */
98 void
99 _kvm_err(kvm_t *kd, const char *program, const char *fmt, ...)
100 {
101         va_list ap;
102
103         va_start(ap, fmt);
104         if (program != NULL) {
105                 (void)fprintf(stderr, "%s: ", program);
106                 (void)vfprintf(stderr, fmt, ap);
107                 (void)fputc('\n', stderr);
108         } else
109                 (void)vsnprintf(kd->errbuf,
110                     sizeof(kd->errbuf), fmt, ap);
111
112         va_end(ap);
113 }
114
115 void
116 _kvm_syserr(kvm_t *kd, const char *program, const char *fmt, ...)
117 {
118         va_list ap;
119         int n;
120
121         va_start(ap, fmt);
122         if (program != NULL) {
123                 (void)fprintf(stderr, "%s: ", program);
124                 (void)vfprintf(stderr, fmt, ap);
125                 (void)fprintf(stderr, ": %s\n", strerror(errno));
126         } else {
127                 char *cp = kd->errbuf;
128
129                 (void)vsnprintf(cp, sizeof(kd->errbuf), fmt, ap);
130                 n = strlen(cp);
131                 (void)snprintf(&cp[n], sizeof(kd->errbuf) - n, ": %s",
132                     strerror(errno));
133         }
134         va_end(ap);
135 }
136
137 void *
138 _kvm_malloc(kvm_t *kd, size_t n)
139 {
140         void *p;
141
142         if ((p = calloc(n, sizeof(char))) == NULL)
143                 _kvm_err(kd, kd->program, "can't allocate %zu bytes: %s",
144                          n, strerror(errno));
145         return (p);
146 }
147
148 static kvm_t *
149 _kvm_open(kvm_t *kd, const char *uf, const char *mf, int flag, char *errout)
150 {
151         struct stat st;
152
153         kd->vmfd = -1;
154         kd->pmfd = -1;
155         kd->nlfd = -1;
156         kd->vmst = 0;
157         kd->procbase = 0;
158         kd->argspc = 0;
159         kd->argv = 0;
160
161         if (uf == 0)
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 == 0)
172                 mf = _PATH_MEM;
173
174         if ((kd->pmfd = open(mf, flag | O_CLOEXEC, 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 (S_ISREG(st.st_mode) && st.st_size <= 0) {
183                 errno = EINVAL;
184                 _kvm_syserr(kd, kd->program, "empty file");
185                 goto failed;
186         }
187         if (S_ISCHR(st.st_mode)) {
188                 /*
189                  * If this is a character special device, then check that
190                  * it's /dev/mem.  If so, open kmem too.  (Maybe we should
191                  * make it work for either /dev/mem or /dev/kmem -- in either
192                  * case you're working with a live kernel.)
193                  */
194                 if (strcmp(mf, _PATH_DEVNULL) == 0) {
195                         kd->vmfd = open(_PATH_DEVNULL, O_RDONLY | O_CLOEXEC);
196                         return (kd);
197                 } else if (strcmp(mf, _PATH_MEM) == 0) {
198                         if ((kd->vmfd = open(_PATH_KMEM, flag | O_CLOEXEC)) <
199                             0) {
200                                 _kvm_syserr(kd, kd->program, "%s", _PATH_KMEM);
201                                 goto failed;
202                         }
203                         return (kd);
204                 }
205         }
206
207         /*
208          * This is either a crash dump or a remote live system with its physical
209          * memory fully accessible via a special device.
210          * Initialize the virtual address translation machinery,
211          * but first setup the namelist fd.
212          */
213         if ((kd->nlfd = open(uf, O_RDONLY | O_CLOEXEC, 0)) < 0) {
214                 _kvm_syserr(kd, kd->program, "%s", uf);
215                 goto failed;
216         }
217         if (strncmp(mf, _PATH_FWMEM, strlen(_PATH_FWMEM)) == 0 ||
218             strncmp(mf, _PATH_DEVVMM, strlen(_PATH_DEVVMM)) == 0) {
219                 kd->rawdump = 1;
220                 kd->writable = 1;
221         }
222         if (_kvm_initvtop(kd) < 0)
223                 goto failed;
224         return (kd);
225 failed:
226         /*
227          * Copy out the error if doing sane error semantics.
228          */
229         if (errout != 0)
230                 strlcpy(errout, kd->errbuf, _POSIX2_LINE_MAX);
231         (void)kvm_close(kd);
232         return (NULL);
233 }
234
235 kvm_t *
236 kvm_openfiles(const char *uf, const char *mf, const char *sf __unused, int flag,
237     char *errout)
238 {
239         kvm_t *kd;
240
241         if ((kd = calloc(1, sizeof(*kd))) == NULL) {
242                 (void)strlcpy(errout, strerror(errno), _POSIX2_LINE_MAX);
243                 return (NULL);
244         }
245         kd->program = 0;
246         return (_kvm_open(kd, uf, mf, flag, errout));
247 }
248
249 kvm_t *
250 kvm_open(const char *uf, const char *mf, const char *sf __unused, int flag,
251     const char *errstr)
252 {
253         kvm_t *kd;
254
255         if ((kd = calloc(1, sizeof(*kd))) == NULL) {
256                 if (errstr != NULL)
257                         (void)fprintf(stderr, "%s: %s\n",
258                                       errstr, strerror(errno));
259                 return (NULL);
260         }
261         kd->program = errstr;
262         return (_kvm_open(kd, uf, mf, flag, NULL));
263 }
264
265 int
266 kvm_close(kvm_t *kd)
267 {
268         int error = 0;
269
270         if (kd == NULL) {
271                 errno = EINVAL;
272                 return (-1);
273         }
274         if (kd->pmfd >= 0)
275                 error |= close(kd->pmfd);
276         if (kd->vmfd >= 0)
277                 error |= close(kd->vmfd);
278         if (kd->nlfd >= 0)
279                 error |= close(kd->nlfd);
280         if (kd->vmst)
281                 _kvm_freevtop(kd);
282         if (kd->procbase != 0)
283                 free((void *)kd->procbase);
284         if (kd->argbuf != 0)
285                 free((void *) kd->argbuf);
286         if (kd->argspc != 0)
287                 free((void *) kd->argspc);
288         if (kd->argv != 0)
289                 free((void *)kd->argv);
290         free((void *)kd);
291
292         return (error);
293 }
294
295 /*
296  * Walk the list of unresolved symbols, generate a new list and prefix the
297  * symbol names, try again, and merge back what we could resolve.
298  */
299 static int
300 kvm_fdnlist_prefix(kvm_t *kd, struct nlist *nl, int missing, const char *prefix,
301     uintptr_t (*validate_fn)(kvm_t *, uintptr_t))
302 {
303         struct nlist *n, *np, *p;
304         char *cp, *ce;
305         const char *ccp;
306         size_t len;
307         int slen, unresolved;
308
309         /*
310          * Calculate the space we need to malloc for nlist and names.
311          * We are going to store the name twice for later lookups: once
312          * with the prefix and once the unmodified name delmited by \0.
313          */
314         len = 0;
315         unresolved = 0;
316         for (p = nl; p->n_name && p->n_name[0]; ++p) {
317                 if (p->n_type != N_UNDF)
318                         continue;
319                 len += sizeof(struct nlist) + strlen(prefix) +
320                     2 * (strlen(p->n_name) + 1);
321                 unresolved++;
322         }
323         if (unresolved == 0)
324                 return (unresolved);
325         /* Add space for the terminating nlist entry. */
326         len += sizeof(struct nlist);
327         unresolved++;
328
329         /* Alloc one chunk for (nlist, [names]) and setup pointers. */
330         n = np = malloc(len);
331         bzero(n, len);
332         if (n == NULL)
333                 return (missing);
334         cp = ce = (char *)np;
335         cp += unresolved * sizeof(struct nlist);
336         ce += len;
337
338         /* Generate shortened nlist with special prefix. */
339         unresolved = 0;
340         for (p = nl; p->n_name && p->n_name[0]; ++p) {
341                 if (p->n_type != N_UNDF)
342                         continue;
343                 bcopy(p, np, sizeof(struct nlist));
344                 /* Save the new\0orig. name so we can later match it again. */
345                 slen = snprintf(cp, ce - cp, "%s%s%c%s", prefix,
346                     (prefix[0] != '\0' && p->n_name[0] == '_') ?
347                         (p->n_name + 1) : p->n_name, '\0', p->n_name);
348                 if (slen < 0 || slen >= ce - cp)
349                         continue;
350                 np->n_name = cp;
351                 cp += slen + 1;
352                 np++;
353                 unresolved++;
354         }
355
356         /* Do lookup on the reduced list. */
357         np = n;
358         unresolved = __fdnlist(kd->nlfd, np);
359
360         /* Check if we could resolve further symbols and update the list. */
361         if (unresolved >= 0 && unresolved < missing) {
362                 /* Find the first freshly resolved entry. */
363                 for (; np->n_name && np->n_name[0]; np++)
364                         if (np->n_type != N_UNDF)
365                                 break;
366                 /*
367                  * The lists are both in the same order,
368                  * so we can walk them in parallel.
369                  */
370                 for (p = nl; np->n_name && np->n_name[0] &&
371                     p->n_name && p->n_name[0]; ++p) {
372                         if (p->n_type != N_UNDF)
373                                 continue;
374                         /* Skip expanded name and compare to orig. one. */
375                         ccp = np->n_name + strlen(np->n_name) + 1;
376                         if (strcmp(ccp, p->n_name) != 0)
377                                 continue;
378                         /* Update nlist with new, translated results. */
379                         p->n_type = np->n_type;
380                         p->n_other = np->n_other;
381                         p->n_desc = np->n_desc;
382                         if (validate_fn)
383                                 p->n_value = (*validate_fn)(kd, np->n_value);
384                         else
385                                 p->n_value = np->n_value;
386                         missing--;
387                         /* Find next freshly resolved entry. */
388                         for (np++; np->n_name && np->n_name[0]; np++)
389                                 if (np->n_type != N_UNDF)
390                                         break;
391                 }
392         }
393         /* We could assert missing = unresolved here. */
394
395         free(n);
396         return (unresolved);
397 }
398
399 int
400 _kvm_nlist(kvm_t *kd, struct nlist *nl, int initialize)
401 {
402         struct nlist *p;
403         int nvalid;
404         struct kld_sym_lookup lookup;
405         int error;
406         const char *prefix = "";
407         char symname[1024]; /* XXX-BZ symbol name length limit? */
408         int tried_vnet, tried_dpcpu;
409
410         /*
411          * If we can't use the kld symbol lookup, revert to the
412          * slow library call.
413          */
414         if (!ISALIVE(kd)) {
415                 error = __fdnlist(kd->nlfd, nl);
416                 if (error <= 0)                 /* Hard error or success. */
417                         return (error);
418
419                 if (_kvm_vnet_initialized(kd, initialize))
420                         error = kvm_fdnlist_prefix(kd, nl, error,
421                             VNET_SYMPREFIX, _kvm_vnet_validaddr);
422
423                 if (error > 0 && _kvm_dpcpu_initialized(kd, initialize))
424                         error = kvm_fdnlist_prefix(kd, nl, error,
425                             DPCPU_SYMPREFIX, _kvm_dpcpu_validaddr);
426
427                 return (error);
428         }
429
430         /*
431          * We can use the kld lookup syscall.  Go through each nlist entry
432          * and look it up with a kldsym(2) syscall.
433          */
434         nvalid = 0;
435         tried_vnet = 0;
436         tried_dpcpu = 0;
437 again:
438         for (p = nl; p->n_name && p->n_name[0]; ++p) {
439                 if (p->n_type != N_UNDF)
440                         continue;
441
442                 lookup.version = sizeof(lookup);
443                 lookup.symvalue = 0;
444                 lookup.symsize = 0;
445
446                 error = snprintf(symname, sizeof(symname), "%s%s", prefix,
447                     (prefix[0] != '\0' && p->n_name[0] == '_') ?
448                         (p->n_name + 1) : p->n_name);
449                 if (error < 0 || error >= (int)sizeof(symname))
450                         continue;
451                 lookup.symname = symname;
452                 if (lookup.symname[0] == '_')
453                         lookup.symname++;
454
455                 if (kldsym(0, KLDSYM_LOOKUP, &lookup) != -1) {
456                         p->n_type = N_TEXT;
457                         p->n_other = 0;
458                         p->n_desc = 0;
459                         if (_kvm_vnet_initialized(kd, initialize) &&
460                             strcmp(prefix, VNET_SYMPREFIX) == 0)
461                                 p->n_value =
462                                     _kvm_vnet_validaddr(kd, lookup.symvalue);
463                         else if (_kvm_dpcpu_initialized(kd, initialize) &&
464                             strcmp(prefix, DPCPU_SYMPREFIX) == 0)
465                                 p->n_value =
466                                     _kvm_dpcpu_validaddr(kd, lookup.symvalue);
467                         else
468                                 p->n_value = lookup.symvalue;
469                         ++nvalid;
470                         /* lookup.symsize */
471                 }
472         }
473
474         /*
475          * Check the number of entries that weren't found. If they exist,
476          * try again with a prefix for virtualized or DPCPU symbol names.
477          */
478         error = ((p - nl) - nvalid);
479         if (error && _kvm_vnet_initialized(kd, initialize) && !tried_vnet) {
480                 tried_vnet = 1;
481                 prefix = VNET_SYMPREFIX;
482                 goto again;
483         }
484         if (error && _kvm_dpcpu_initialized(kd, initialize) && !tried_dpcpu) {
485                 tried_dpcpu = 1;
486                 prefix = DPCPU_SYMPREFIX;
487                 goto again;
488         }
489
490         /*
491          * Return the number of entries that weren't found. If they exist,
492          * also fill internal error buffer.
493          */
494         error = ((p - nl) - nvalid);
495         if (error)
496                 _kvm_syserr(kd, kd->program, "kvm_nlist");
497         return (error);
498 }
499
500 int
501 kvm_nlist(kvm_t *kd, struct nlist *nl)
502 {
503
504         /*
505          * If called via the public interface, permit intialization of
506          * further virtualized modules on demand.
507          */
508         return (_kvm_nlist(kd, nl, 1));
509 }
510
511 ssize_t
512 kvm_read(kvm_t *kd, u_long kva, void *buf, size_t len)
513 {
514         int cc;
515         ssize_t cr;
516         off_t pa;
517         char *cp;
518
519         if (ISALIVE(kd)) {
520                 /*
521                  * We're using /dev/kmem.  Just read straight from the
522                  * device and let the active kernel do the address translation.
523                  */
524                 errno = 0;
525                 if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) {
526                         _kvm_err(kd, 0, "invalid address (%lx)", kva);
527                         return (-1);
528                 }
529                 cr = read(kd->vmfd, buf, len);
530                 if (cr < 0) {
531                         _kvm_syserr(kd, 0, "kvm_read");
532                         return (-1);
533                 } else if (cr < (ssize_t)len)
534                         _kvm_err(kd, kd->program, "short read");
535                 return (cr);
536         }
537
538         cp = buf;
539         while (len > 0) {
540                 cc = _kvm_kvatop(kd, kva, &pa);
541                 if (cc == 0)
542                         return (-1);
543                 if (cc > (ssize_t)len)
544                         cc = len;
545                 errno = 0;
546                 if (lseek(kd->pmfd, pa, 0) == -1 && errno != 0) {
547                         _kvm_syserr(kd, 0, _PATH_MEM);
548                         break;
549                 }
550                 cr = read(kd->pmfd, cp, cc);
551                 if (cr < 0) {
552                         _kvm_syserr(kd, kd->program, "kvm_read");
553                         break;
554                 }
555                 /*
556                  * If kvm_kvatop returns a bogus value or our core file is
557                  * truncated, we might wind up seeking beyond the end of the
558                  * core file in which case the read will return 0 (EOF).
559                  */
560                 if (cr == 0)
561                         break;
562                 cp += cr;
563                 kva += cr;
564                 len -= cr;
565         }
566
567         return (cp - (char *)buf);
568 }
569
570 ssize_t
571 kvm_write(kvm_t *kd, u_long kva, const void *buf, size_t len)
572 {
573         int cc;
574         ssize_t cw;
575         off_t pa;
576         const char *cp;
577
578         if (!ISALIVE(kd) && !kd->writable) {
579                 _kvm_err(kd, kd->program,
580                     "kvm_write not implemented for dead kernels");
581                 return (-1);
582         }
583
584         if (ISALIVE(kd)) {
585                 /*
586                  * Just like kvm_read, only we write.
587                  */
588                 errno = 0;
589                 if (lseek(kd->vmfd, (off_t)kva, 0) == -1 && errno != 0) {
590                         _kvm_err(kd, 0, "invalid address (%lx)", kva);
591                         return (-1);
592                 }
593                 cc = write(kd->vmfd, buf, len);
594                 if (cc < 0) {
595                         _kvm_syserr(kd, 0, "kvm_write");
596                         return (-1);
597                 } else if ((size_t)cc < len)
598                         _kvm_err(kd, kd->program, "short write");
599                 return (cc);
600         }
601
602         cp = buf;
603         while (len > 0) {
604                 cc = _kvm_kvatop(kd, kva, &pa);
605                 if (cc == 0)
606                         return (-1);
607                 if (cc > (ssize_t)len)
608                         cc = len;
609                 errno = 0;
610                 if (lseek(kd->pmfd, pa, 0) == -1 && errno != 0) {
611                         _kvm_syserr(kd, 0, _PATH_MEM);
612                         break;
613                 }
614                 cw = write(kd->pmfd, cp, cc);
615                 if (cw < 0) {
616                         _kvm_syserr(kd, kd->program, "kvm_write");
617                         break;
618                 }
619                 /*
620                  * If ka_kvatop returns a bogus value or our core file is
621                  * truncated, we might wind up seeking beyond the end of the
622                  * core file in which case the read will return 0 (EOF).
623                  */
624                 if (cw == 0)
625                         break;
626                 cp += cw;
627                 kva += cw;
628                 len -= cw;
629         }
630
631         return (cp - (const char *)buf);
632 }