Page MenuHomeFreeBSD

D58048.id181323.diff
No OneTemporary

D58048.id181323.diff

diff --git a/sbin/kldstat/Makefile b/sbin/kldstat/Makefile
--- a/sbin/kldstat/Makefile
+++ b/sbin/kldstat/Makefile
@@ -29,6 +29,8 @@
PROG= kldstat
MAN= kldstat.8
-LIBADD= util
+CFLAGS+=-I${SRCTOP}/lib/libkldelf
+
+LIBADD= util elf kldelf
.include <bsd.prog.mk>
diff --git a/sbin/kldstat/kldstat.c b/sbin/kldstat/kldstat.c
--- a/sbin/kldstat/kldstat.c
+++ b/sbin/kldstat/kldstat.c
@@ -28,11 +28,15 @@
#include <sys/types.h>
#include <sys/param.h>
-#include <sys/module.h>
#include <sys/linker.h>
+#include <sys/module.h>
+#include <sys/queue.h>
#include <err.h>
+#include <gelf.h>
+#include <kldelf.h>
#include <libutil.h>
+#include <search.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -46,6 +50,95 @@
static int showdata = 0;
+struct module_map_entry {
+ char *module_name;
+ char *ko_path;
+ char *prefix;
+ SLIST_ENTRY(module_map_entry) entry;
+};
+SLIST_HEAD(module_map_list, module_map_entry);
+static struct module_map_list list = { NULL };
+
+static void
+clean_modules_mapping(void)
+{
+ struct module_map_entry *entry, *temp;
+ char *cur_mod_path = NULL;
+
+ SLIST_FOREACH_SAFE(entry, &list, entry, temp) {
+ SLIST_REMOVE_HEAD(&list, entry);
+ if (cur_mod_path != entry->ko_path) {
+ free(entry->ko_path);
+ cur_mod_path = entry->ko_path;
+ }
+ free(entry->prefix);
+ free(entry->module_name);
+ free(entry);
+ }
+}
+
+static void
+init_modules_mapping(void)
+{
+ struct module_map_entry *entp;
+ struct kld_file_stat stat;
+ struct module_stat mod_stat;
+ char *ko_path, *child_name;
+ int fileid, modid = 0, nmod;
+
+ if (SLIST_FIRST(&list) != NULL)
+ return;
+ for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
+ stat.version = sizeof(struct kld_file_stat);
+ if (kldstat(fileid, &stat) < 0)
+ continue;
+ ko_path = strdup(stat.pathname);
+ nmod = 0;
+ if (strcmp(stat.name, "kernel") == 0) {
+ entp = calloc(sizeof(struct module_map_entry), 1);
+ entp->ko_path = ko_path;
+ entp->module_name = strdup("kernel");
+ SLIST_INSERT_HEAD(&list, entp, entry);
+ nmod++;
+ }
+ for (modid = kldfirstmod(fileid); modid > 0;
+ modid = modfnext(modid)) {
+ nmod++;
+ mod_stat.version = sizeof(struct module_stat);
+ if (modstat(modid, &mod_stat) < 0)
+ continue;
+ entp = calloc(sizeof(struct module_map_entry), 1);
+ entp->ko_path = ko_path;
+ if ((child_name = strchr(mod_stat.name, '/')) != NULL) {
+ entp->prefix = strndup(mod_stat.name,
+ child_name - mod_stat.name - 1);
+ entp->module_name = strdup(child_name + 1);
+ } else
+ entp->module_name = strdup(mod_stat.name);
+ SLIST_INSERT_HEAD(&list, entp, entry);
+ }
+ if (nmod == 0)
+ free(ko_path);
+ }
+ if (SLIST_FIRST(&list) != NULL)
+ atexit(clean_modules_mapping);
+}
+
+static const char *
+print_module_dependency(const char *modname, struct Gmod_depend *mdp)
+{
+ struct module_map_entry *entry;
+
+ SLIST_FOREACH(entry, &list, entry) {
+ if (strcmp(entry->module_name, modname) == 0) {
+ printf("\t\t depends on %s.%d (%d,%d) => %s (%s)\n",
+ modname, mdp->md_ver_preferred, mdp->md_ver_minimum,
+ mdp->md_ver_maximum, entry->ko_path, entry->prefix);
+ }
+ }
+ return (NULL);
+}
+
static void
printmod(int modid)
{
@@ -65,6 +158,41 @@
printf("\t\t%3d %s\n", stat.id, stat.name);
}
+static int
+print_file_dependency(const char *full_path)
+{
+ struct elf_file ef;
+ struct Gmod_metadata md;
+ struct Gmod_depend mdp;
+ GElf_Addr *entries = NULL;
+ char cval[MAXMODNAME + 4];
+ long n;
+ int err, idx;
+
+ init_modules_mapping();
+
+ if ((err = elf_open_file(&ef, full_path, 1)) != 0)
+ return (err);
+ if ((err = elf_read_linker_set(&ef, MDT_SETNAME, &entries, &n)) != 0)
+ goto cleanup;
+ for (idx = 0; idx < n; ++idx) {
+ if ((err = elf_read_mod_metadata(&ef, entries[idx], &md)) != 0)
+ goto cleanup;
+ if (md.md_type != MDT_DEPEND)
+ continue;
+ if ((err = elf_read_string(&ef, md.md_cval, cval,
+ MAXMODNAME)) != 0)
+ goto cleanup;
+ if ((err = elf_read_mod_depend(&ef, md.md_data, &mdp)) != 0)
+ goto cleanup;
+ print_module_dependency(cval, &mdp);
+ }
+cleanup:
+ free(entries);
+ elf_close_file(&ef);
+ return (0);
+}
+
static void
printfile(int fileid, int verbose, int humanized)
{
@@ -94,6 +222,8 @@
printf("\t\t Id Name\n");
for (modid = kldfirstmod(fileid); modid > 0; modid = modfnext(modid))
printmod(modid);
+ printf("\tDependency: \n");
+ print_file_dependency(stat.pathname);
} else
printf("\n");
}
@@ -154,6 +284,9 @@
if (argc != 0)
usage();
+ if (verbose && elf_version(EV_CURRENT) == EV_NONE)
+ errx(1, "unsupported libelf");
+
if (modname != NULL) {
if ((modid = modfind(modname)) < 0) {
if (!quiet)
@@ -198,6 +331,7 @@
printf("Id Refs Address%*c %8s Name\n", PTR_WIDTH - 7,
' ', "Size");
}
+
if (fileid != 0)
printfile(fileid, verbose, humanized);
else

File Metadata

Mime Type
text/plain
Expires
Mon, Aug 3, 5:29 AM (21 h, 44 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
35898262
Default Alt Text
D58048.id181323.diff (4 KB)

Event Timeline