125540Sdfr/*-
2330449Seadler * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
3330449Seadler *
425540Sdfr * Copyright (c) 1997 Doug Rabson
525540Sdfr * All rights reserved.
625540Sdfr *
725540Sdfr * Redistribution and use in source and binary forms, with or without
825540Sdfr * modification, are permitted provided that the following conditions
925540Sdfr * are met:
1025540Sdfr * 1. Redistributions of source code must retain the above copyright
1125540Sdfr *    notice, this list of conditions and the following disclaimer.
1225540Sdfr * 2. Redistributions in binary form must reproduce the above copyright
1325540Sdfr *    notice, this list of conditions and the following disclaimer in the
1425540Sdfr *    documentation and/or other materials provided with the distribution.
1525540Sdfr *
1625540Sdfr * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1725540Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1825540Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1925540Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2025540Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2125540Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2225540Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2325540Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2425540Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2525540Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2625540Sdfr * SUCH DAMAGE.
2725540Sdfr */
2825540Sdfr
29114589Sobrien#include <sys/cdefs.h>
30114589Sobrien__FBSDID("$FreeBSD: stable/11/sbin/kldstat/kldstat.c 330449 2018-03-05 07:26:05Z eadler $");
3132270Scharnier
3230573Sjmg#include <err.h>
33294624Strasz#include <libutil.h>
3425540Sdfr#include <stdio.h>
3530573Sjmg#include <stdlib.h>
3625540Sdfr#include <unistd.h>
3725540Sdfr#include <sys/types.h>
3825540Sdfr#include <sys/param.h>
3925540Sdfr#include <sys/module.h>
4025540Sdfr#include <sys/linker.h>
41297023Sjulian#include <strings.h>
4225540Sdfr
43129866Sdwmalone#define	POINTER_WIDTH	((int)(sizeof(void *) * 2 + 2))
4454130Smarcel
45297023Sjulianstatic int showdata = 0;
46297023Sjulian
4730627Sjmgstatic void
4830627Sjmgprintmod(int modid)
4925540Sdfr{
5025540Sdfr    struct module_stat stat;
5125540Sdfr
52297023Sjulian    bzero(&stat, sizeof(stat));
5325540Sdfr    stat.version = sizeof(struct module_stat);
5425540Sdfr    if (modstat(modid, &stat) < 0)
5532270Scharnier	warn("can't stat module id %d", modid);
5625540Sdfr    else
57297023Sjulian	if (showdata) {
58297023Sjulian	    printf("\t\t%2d %s (%d, %u, 0x%lx)\n", stat.id, stat.name,
59297023Sjulian	        stat.data.intval, stat.data.uintval, stat.data.ulongval);
60297023Sjulian	} else {
61297023Sjulian		printf("\t\t%2d %s\n", stat.id, stat.name);
62297023Sjulian	}
6325540Sdfr}
6425540Sdfr
65215248Skibstatic void
66294624Straszprintfile(int fileid, int verbose, int humanized)
6725540Sdfr{
6825540Sdfr    struct kld_file_stat stat;
6925540Sdfr    int modid;
70294624Strasz    char buf[5];
7125540Sdfr
7225540Sdfr    stat.version = sizeof(struct kld_file_stat);
73294624Strasz    if (kldstat(fileid, &stat) < 0) {
74215248Skib	err(1, "can't stat file id %d", fileid);
75294624Strasz    } else {
76294624Strasz	if (humanized) {
77294624Strasz	       humanize_number(buf, sizeof(buf), stat.size,
78294624Strasz	           "", HN_AUTOSCALE, HN_DECIMAL | HN_NOSPACE);
7925540Sdfr
80294624Strasz	       printf("%2d %4d %p %5s %s",
81294624Strasz	           stat.id, stat.refs, stat.address, buf, stat.name);
82294624Strasz	} else {
83294624Strasz		printf("%2d %4d %p %-8zx %s",
84294624Strasz		    stat.id, stat.refs, stat.address, stat.size, stat.name);
85294624Strasz	}
86294624Strasz    }
87294624Strasz
8825540Sdfr    if (verbose) {
89186398Sthompsa	printf(" (%s)\n", stat.pathname);
9025540Sdfr	printf("\tContains modules:\n");
9162327Sps	printf("\t\tId Name\n");
9225540Sdfr	for (modid = kldfirstmod(fileid); modid > 0;
9325540Sdfr	     modid = modfnext(modid))
9425540Sdfr	    printmod(modid);
95186398Sthompsa    } else
96186398Sthompsa	printf("\n");
9725540Sdfr}
9825540Sdfr
9925540Sdfrstatic void
10030627Sjmgusage(void)
10125540Sdfr{
102315210Smarkj    fprintf(stderr, "usage: kldstat [-d] [-h] [-q] [-v] [-i id] [-n filename]\n");
103297023Sjulian    fprintf(stderr, "       kldstat [-d] [-q] [-m modname]\n");
10425540Sdfr    exit(1);
10525540Sdfr}
10625540Sdfr
10730627Sjmgint
10830627Sjmgmain(int argc, char** argv)
10925540Sdfr{
11025540Sdfr    int c;
111294624Strasz    int humanized = 0;
11225540Sdfr    int verbose = 0;
11325540Sdfr    int fileid = 0;
114150497Spjd    int quiet = 0;
115113936Sjohan    char* filename = NULL;
116145861Sfjoe    char* modname = NULL;
117127004Sjmallett    char* p;
11825540Sdfr
119297023Sjulian    while ((c = getopt(argc, argv, "dhi:m:n:qv")) != -1)
12025540Sdfr	switch (c) {
121297023Sjulian	case 'd':
122297023Sjulian	    showdata = 1;
123297023Sjulian	    break;
124294624Strasz	case 'h':
125294624Strasz	    humanized = 1;
126294624Strasz	    break;
12725540Sdfr	case 'i':
128127004Sjmallett	    fileid = (int)strtoul(optarg, &p, 10);
129127004Sjmallett	    if (*p != '\0')
130127004Sjmallett		usage();
13125540Sdfr	    break;
132145861Sfjoe	case 'm':
133145861Sfjoe	    modname = optarg;
134145861Sfjoe	    break;
13525540Sdfr	case 'n':
13625540Sdfr	    filename = optarg;
13725540Sdfr	    break;
138150497Spjd	case 'q':
139150497Spjd	    quiet = 1;
140150497Spjd	    break;
14130627Sjmg	case 'v':
14230627Sjmg	    verbose = 1;
14330627Sjmg	    break;
14425540Sdfr	default:
14525540Sdfr	    usage();
14625540Sdfr	}
14725540Sdfr    argc -= optind;
14825540Sdfr    argv += optind;
14925540Sdfr
15025540Sdfr    if (argc != 0)
15125540Sdfr	usage();
15225540Sdfr
153145861Sfjoe    if (modname != NULL) {
154145861Sfjoe	int modid;
155145861Sfjoe	struct module_stat stat;
156145861Sfjoe
157150497Spjd	if ((modid = modfind(modname)) < 0) {
158150497Spjd	    if (!quiet)
159150497Spjd		warn("can't find module %s", modname);
160150497Spjd	    return 1;
161150497Spjd	} else if (quiet) {
162150497Spjd	    return 0;
163150497Spjd	}
164145861Sfjoe
165145861Sfjoe	stat.version = sizeof(struct module_stat);
166145861Sfjoe	if (modstat(modid, &stat) < 0)
167145861Sfjoe	    warn("can't stat module id %d", modid);
168145861Sfjoe	else {
169297023Sjulian		if (showdata) {
170297023Sjulian		    printf("Id  Refs Name data..(int, uint, ulong)\n");
171297023Sjulian		    printf("%3d %4d %s (%d, %u, 0x%lx)\n", stat.id, stat.refs, stat.name,
172297023Sjulian		        stat.data.intval, stat.data.uintval, stat.data.ulongval);
173297023Sjulian		} else {
174297023Sjulian		    printf("Id  Refs Name\n");
175297023Sjulian		    printf("%3d %4d %s\n", stat.id, stat.refs, stat.name);
176297023Sjulian		}
177145861Sfjoe	}
178145861Sfjoe
179145861Sfjoe	return 0;
180145861Sfjoe    }
181145861Sfjoe
182113936Sjohan    if (filename != NULL) {
183261032Sbapt	if ((fileid = kldfind(filename)) < 0) {
184261032Sbapt	    if (!quiet)
185261032Sbapt		warn("can't find file %s", filename);
186261032Sbapt	    return 1;
187261032Sbapt	} else if (quiet) {
188261032Sbapt	    return 0;
189261032Sbapt	}
19025540Sdfr    }
19125540Sdfr
192294624Strasz    if (humanized)
193294624Strasz	    printf("Id Refs Address%*c  Size Name\n", POINTER_WIDTH - 7, ' ');
194294624Strasz    else
195294624Strasz	    printf("Id Refs Address%*c Size     Name\n", POINTER_WIDTH - 7, ' ');
196113936Sjohan    if (fileid != 0)
197294624Strasz	printfile(fileid, verbose, humanized);
19825540Sdfr    else
19925540Sdfr	for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid))
200294624Strasz	    printfile(fileid, verbose, humanized);
20125540Sdfr
20225540Sdfr    return 0;
20325540Sdfr}
204