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