xref: /dragonfly/sbin/kldstat/kldstat.c (revision 22cd51fe)
1 /*-
2  * Copyright (c) 1997 Doug Rabson
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sbin/kldstat/kldstat.c,v 1.20 2007/10/22 04:12:57 jb Exp $
27  */
28 
29 #include <err.h>
30 #include <libutil.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #include <unistd.h>
34 #include <sys/types.h>
35 #include <sys/param.h>
36 #include <sys/module.h>
37 #include <sys/linker.h>
38 
39 #define	POINTER_WIDTH	((int)(sizeof(void *) * 2 + 2))
40 
41 static int humanize = 0;
42 static int verbose = 0;
43 
44 
45 static void
46 printmod(int modid)
47 {
48     struct module_stat stat;
49 
50     stat.version = sizeof(struct module_stat);
51     if (modstat(modid, &stat) < 0)
52 	warn("can't stat module id %d", modid);
53     else
54 	printf("\t\t%2d %s\n", stat.id, stat.name);
55 }
56 
57 static void
58 printfile(int fileid)
59 {
60     struct kld_file_stat stat;
61     int modid;
62     char buf[5];
63 
64     stat.version = sizeof(struct kld_file_stat);
65     if (kldstat(fileid, &stat) < 0) {
66 	warn("can't stat file id %d", fileid);
67     } else {
68 	if (humanize) {
69 	    humanize_number(buf, sizeof(buf), stat.size, "",
70 			    HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE);
71 	    printf("%2d %4d %*p %5s %s",
72 		   stat.id, stat.refs, POINTER_WIDTH, stat.address,
73 		   buf, stat.name);
74 	} else {
75 	    printf("%2d %4d %*p %8zx %s",
76 		   stat.id, stat.refs, POINTER_WIDTH, stat.address,
77 		   stat.size, stat.name);
78 	}
79     }
80 
81     if (verbose) {
82 	printf(" (%s)\n", stat.pathname);
83 	printf("\tContains modules:\n");
84 	printf("\t\tId Name\n");
85 	for (modid = kldfirstmod(fileid); modid > 0; modid = modfnext(modid))
86 	    printmod(modid);
87     } else {
88 	printf("\n");
89     }
90 }
91 
92 static void __dead2
93 usage(void)
94 {
95     fprintf(stderr, "usage: kldstat [-hv] [-i id] [-n filename]\n");
96     fprintf(stderr, "       kldstat [-q] [-m modname]\n");
97     exit(1);
98 }
99 
100 int
101 main(int argc, char** argv)
102 {
103     int c;
104     int fileid = 0;
105     int quiet = 0;
106     char* filename = NULL;
107     char* modname = NULL;
108     char* p;
109 
110     while ((c = getopt(argc, argv, "hi:m:n:qv")) != -1) {
111 	switch (c) {
112 	case 'h':
113 	    humanize = 1;
114 	    break;
115 	case 'i':
116 	    fileid = (int)strtoul(optarg, &p, 10);
117 	    if (*p != '\0')
118 		usage();
119 	    break;
120 	case 'm':
121 	    modname = optarg;
122 	    break;
123 	case 'n':
124 	    filename = optarg;
125 	    break;
126 	case 'q':
127 	    quiet = 1;
128 	    break;
129 	case 'v':
130 	    verbose = 1;
131 	    break;
132 	default:
133 	    usage();
134 	}
135     }
136     argc -= optind;
137     argv += optind;
138 
139     if (argc != 0)
140 	usage();
141 
142     if (modname != NULL) {
143 	int modid;
144 	struct module_stat stat;
145 
146 	if ((modid = modfind(modname)) < 0) {
147 	    if (!quiet)
148 		warn("can't find module %s", modname);
149 	    return 1;
150 	} else if (quiet) {
151 	    return 0;
152 	}
153 
154 	stat.version = sizeof(struct module_stat);
155 	if (modstat(modid, &stat) < 0)
156 	    warn("can't stat module id %d", modid);
157 	else {
158 	    printf("Id  Refs Name\n");
159 	    printf("%3d %4d %s\n", stat.id, stat.refs, stat.name);
160 	}
161 
162 	return 0;
163     }
164 
165     if (filename != NULL) {
166 	if ((fileid = kldfind(filename)) < 0)
167 	    err(1, "can't find file %s", filename);
168     }
169 
170     printf("Id Refs Address%*c %*s Name\n", POINTER_WIDTH - 7, ' ',
171 	   (humanize ? 5 : 8), "Size");
172     if (fileid != 0) {
173 	printfile(fileid);
174     } else {
175 	for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid))
176 	    printfile(fileid);
177     }
178 
179     return 0;
180 }
181