]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.sbin/asf/asf_kvm.c
Add deprecation notice in asf.8
[FreeBSD/FreeBSD.git] / usr.sbin / asf / asf_kvm.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3  *
4  * Copyright (c) 2006 The FreeBSD Project
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/queue.h>  /* for <sys/linker.h> with _KERNEL defined */
35 #include <err.h>
36 #include <fcntl.h>
37 #include <kvm.h>
38 #include <limits.h>
39 #include <nlist.h>
40 #include <stdlib.h>
41 #include <string.h>
42
43 #define _KERNEL
44 #include <sys/linker.h>
45 #undef  _KERNEL
46
47 #include "asf.h"
48
49 /* Name of the head of the linker file list in /sys/kern/kern_linker.c */
50 #define LINKER_HEAD     "linker_files"
51
52 /*
53  * Get the list of linker files using kvm(3).
54  * Can work with a live kernel as well as with a crash dump.
55  */
56 void
57 asf_kvm(const char *kernfile, const char *corefile)
58 {
59         char errbuf[LINE_MAX];
60         char name[PATH_MAX];
61         kvm_t *kd;
62         struct nlist nl[2];
63         struct linker_file lf;
64         linker_file_list_t linker_files;
65         ssize_t n;
66         void *kp;
67
68         kd = kvm_openfiles(kernfile, corefile, NULL, O_RDONLY, errbuf);
69         if (kd == NULL)
70                 errx(2, "open kernel memory: %s", errbuf);
71
72         /*
73          * Locate the head of the linker file list using kernel symbols.
74          */
75         strcpy(name, LINKER_HEAD);
76         nl[0].n_name = name; /* can't use LINKER_HEAD here because it's const */
77         nl[1].n_name = NULL; /* terminate the array for kvm_nlist() */
78         switch (kvm_nlist(kd, nl)) {
79         case 0:
80                 break;
81         case -1:
82                 warnx("%s: %s", LINKER_HEAD, kvm_geterr(kd));
83                 kvm_close(kd);
84                 exit(2);
85         default:
86                 kvm_close(kd);
87                 errx(2, "%s: symbol not found", LINKER_HEAD);
88         }
89
90         /*
91          * Read the head of the linker file list from kernel memory.
92          */
93         n = kvm_read(kd, nl[0].n_value, &linker_files, sizeof(linker_files));
94         if (n == -1)
95                 goto read_err;
96         if (n != sizeof(linker_files)) {
97                 kvm_close(kd);
98                 errx(2, "%s: short read", LINKER_HEAD);
99         }
100
101         /*
102          * Traverse the linker file list starting at its head.
103          */
104         for (kp = linker_files.tqh_first; kp; kp = lf.link.tqe_next) {
105                 /* Read a linker file structure */
106                 n = kvm_read(kd, (u_long)kp, &lf, sizeof(lf));
107                 if (n == -1)
108                         goto read_err;
109                 if (n != sizeof(lf)) {
110                         kvm_close(kd);
111                         errx(2, "kvm: short read");
112                 }
113                 /* Read the name of the file stored separately */
114                 bzero(name, sizeof(name));
115                 n = kvm_read(kd, (u_long)lf.filename, name, sizeof(name) - 1);
116                 if (n == -1)
117                         goto read_err;
118                 if (strcmp(name, KERNFILE) == 0)
119                         continue;
120                 /* Add this file to our list of linker files */
121                 kfile_add(name, lf.address);
122         }
123         kvm_close(kd);
124         return;
125
126 read_err:       /* A common error case */
127         warnx("read kernel memory: %s", kvm_geterr(kd));
128         kvm_close(kd);
129         exit(2);
130 }