Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F164586317
D58048.id181323.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
4 KB
Referenced Files
None
Subscribers
None
D58048.id181323.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D58048: kldstat: Add ldd feature
Attached
Detach File
Event Timeline
Log In to Comment