Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 6 Jun 2015 16:47:45 +0000 (UTC)
From:      Mark Johnston <markj@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r284085 - head/cddl/contrib/opensolaris/lib/libdtrace/common
Message-ID:  <201506061647.t56GljPD041378@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: markj
Date: Sat Jun  6 16:47:45 2015
New Revision: 284085
URL: https://svnweb.freebsd.org/changeset/base/284085

Log:
  libdtrace: allow D libraries to declare dependencies on kernel modules
  
  The "depends_on module" pragma can be used to declare a dependency on a
  DTrace module, which for kernel probes corresponds to a KLD. Such
  dependencies cannot be checked if the KLD is compiled into the kernel.
  Therefore, allow a module dependency to be satisfied if either a kernel
  module or a KLD with the specified name is loaded.
  
  Differential Revision:	https://reviews.freebsd.org/D2653
  Reviewed by:	gnn, rpaulo
  Reported by:	gnn

Modified:
  head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
  head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
  head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.h
  head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
  head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h	Sat Jun  6 16:45:59 2015	(r284084)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_impl.h	Sat Jun  6 16:47:45 2015	(r284085)
@@ -156,6 +156,21 @@ typedef struct dt_module {
 #define	DT_DM_KERNEL	0x2	/* module is associated with a kernel object */
 #define	DT_DM_PRIMARY	0x4	/* module is a krtld primary kernel object */
 
+#ifdef __FreeBSD__
+/*
+ * A representation of a FreeBSD kernel module, used when checking module
+ * dependencies.  This differs from dt_module_t, which refers to a KLD in the
+ * case of kernel probes.  Since modules can be identified regardless of whether
+ * they've been compiled into the kernel, we use them to identify DTrace
+ * modules.
+ */
+typedef struct dt_kmodule {
+	struct dt_kmodule *dkm_next;	/* hash table entry */
+	char *dkm_name;			/* string name of module */
+	dt_module_t *dkm_module;	/* corresponding KLD module */
+} dt_kmodule_t;
+#endif
+
 typedef struct dt_provmod {
 	char *dp_name;				/* name of provider module */
 	struct dt_provmod *dp_next;		/* next module */
@@ -235,6 +250,9 @@ struct dtrace_hdl {
 	dt_idhash_t *dt_tls;	/* hash table of thread-local identifiers */
 	dt_list_t dt_modlist;	/* linked list of dt_module_t's */
 	dt_module_t **dt_mods;	/* hash table of dt_module_t's */
+#ifdef __FreeBSD__
+	dt_kmodule_t **dt_kmods; /* hash table of dt_kmodule_t's */
+#endif
 	uint_t dt_modbuckets;	/* number of module hash buckets */
 	uint_t dt_nmods;	/* number of modules in hash and list */
 	dt_provmod_t *dt_provmod; /* linked list of provider modules */

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c	Sat Jun  6 16:45:59 2015	(r284084)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.c	Sat Jun  6 16:47:45 2015	(r284085)
@@ -37,6 +37,7 @@
 #else
 #include <sys/param.h>
 #include <sys/linker.h>
+#include <sys/module.h>
 #include <sys/stat.h>
 #endif
 
@@ -542,6 +543,22 @@ dt_module_lookup_by_ctf(dtrace_hdl_t *dt
 	return (ctfp ? ctf_getspecific(ctfp) : NULL);
 }
 
+#ifdef __FreeBSD__
+dt_kmodule_t *
+dt_kmodule_lookup(dtrace_hdl_t *dtp, const char *name)
+{
+	uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_modbuckets;
+	dt_kmodule_t *dkmp;
+
+	for (dkmp = dtp->dt_kmods[h]; dkmp != NULL; dkmp = dkmp->dkm_next) {
+		if (strcmp(dkmp->dkm_name, name) == 0)
+			return (dkmp);
+	}
+
+	return (NULL);
+}
+#endif
+
 static int
 dt_module_load_sect(dtrace_hdl_t *dtp, dt_module_t *dmp, ctf_sect_t *ctsp)
 {
@@ -1124,6 +1141,12 @@ dt_module_update(dtrace_hdl_t *dtp, stru
 	char fname[MAXPATHLEN];
 	struct stat64 st;
 	int fd, err, bits;
+#ifdef __FreeBSD__
+	struct module_stat ms;
+	dt_kmodule_t *dkmp;
+	uint_t h;
+	int modid;
+#endif
 
 	dt_module_t *dmp;
 	const char *s;
@@ -1270,6 +1293,33 @@ dt_module_update(dtrace_hdl_t *dtp, stru
 	if (dmp->dm_info.objfs_info_primary)
 		dmp->dm_flags |= DT_DM_PRIMARY;
 
+#ifdef __FreeBSD__
+	ms.version = sizeof(ms);
+	for (modid = kldfirstmod(k_stat->id); modid > 0;
+	    modid = modnext(modid)) {
+		if (modstat(modid, &ms) != 0) {
+			dt_dprintf("modstat failed for id %d in %s: %s\n",
+			    modid, k_stat->name, strerror(errno));
+			continue;
+		}
+		if (dt_kmodule_lookup(dtp, ms.name) != NULL)
+			continue;
+
+		dkmp = malloc(sizeof (*dkmp));
+		if (dkmp == NULL) {
+			dt_dprintf("failed to allocate memory\n");
+			dt_module_destroy(dtp, dmp);
+			return;
+		}
+
+		h = dt_strtab_hash(ms.name, NULL) % dtp->dt_modbuckets;
+		dkmp->dkm_next = dtp->dt_kmods[h];
+		dkmp->dkm_name = strdup(ms.name);
+		dkmp->dkm_module = dmp;
+		dtp->dt_kmods[h] = dkmp;
+	}
+#endif
+
 	dt_dprintf("opened %d-bit module %s (%s) [%d]\n",
 	    bits, dmp->dm_name, dmp->dm_file, dmp->dm_modid);
 }

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.h
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.h	Sat Jun  6 16:45:59 2015	(r284084)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_module.h	Sat Jun  6 16:47:45 2015	(r284085)
@@ -44,6 +44,10 @@ extern void dt_module_destroy(dtrace_hdl
 extern dt_module_t *dt_module_lookup_by_name(dtrace_hdl_t *, const char *);
 extern dt_module_t *dt_module_lookup_by_ctf(dtrace_hdl_t *, ctf_file_t *);
 
+#ifdef __FreeBSD__
+extern dt_kmodule_t *dt_kmodule_lookup(dtrace_hdl_t *, const char *);
+#endif
+
 extern int dt_module_hasctf(dtrace_hdl_t *, dt_module_t *);
 extern ctf_file_t *dt_module_getctf(dtrace_hdl_t *, dt_module_t *);
 extern dt_ident_t *dt_module_extern(dtrace_hdl_t *, dt_module_t *,

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c	Sat Jun  6 16:45:59 2015	(r284084)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_open.c	Sat Jun  6 16:47:45 2015	(r284085)
@@ -1178,6 +1178,9 @@ alloc:
 #endif
 	dtp->dt_modbuckets = _dtrace_strbuckets;
 	dtp->dt_mods = calloc(dtp->dt_modbuckets, sizeof (dt_module_t *));
+#ifdef __FreeBSD__
+	dtp->dt_kmods = calloc(dtp->dt_modbuckets, sizeof (dt_module_t *));
+#endif
 	dtp->dt_provbuckets = _dtrace_strbuckets;
 	dtp->dt_provs = calloc(dtp->dt_provbuckets, sizeof (dt_provider_t *));
 	dt_proc_hash_create(dtp);
@@ -1199,6 +1202,7 @@ alloc:
 	if (dtp->dt_mods == NULL || dtp->dt_provs == NULL ||
 	    dtp->dt_procs == NULL || dtp->dt_ld_path == NULL ||
 #ifdef __FreeBSD__
+	    dtp->dt_kmods == NULL ||
 	    dtp->dt_objcopy_path == NULL ||
 #endif
 	    dtp->dt_cpp_path == NULL || dtp->dt_cpp_argv == NULL)
@@ -1621,6 +1625,10 @@ dtrace_close(dtrace_hdl_t *dtp)
 	dtrace_prog_t *pgp;
 	dt_xlator_t *dxp;
 	dt_dirpath_t *dirp;
+#ifdef __FreeBSD__
+	dt_kmodule_t *dkm;
+	uint_t h;
+#endif
 	int i;
 
 	if (dtp->dt_procs != NULL)
@@ -1648,6 +1656,15 @@ dtrace_close(dtrace_hdl_t *dtp)
 	if (dtp->dt_tls != NULL)
 		dt_idhash_destroy(dtp->dt_tls);
 
+#ifdef __FreeBSD__
+	for (h = 0; h < dtp->dt_modbuckets; h++)
+		while ((dkm = dtp->dt_kmods[h]) != NULL) {
+			dtp->dt_kmods[h] = dkm->dkm_next;
+			free(dkm->dkm_name);
+			free(dkm);
+		}
+#endif
+
 	while ((dmp = dt_list_next(&dtp->dt_modlist)) != NULL)
 		dt_module_destroy(dtp, dmp);
 
@@ -1697,6 +1714,9 @@ dtrace_close(dtrace_hdl_t *dtp)
 #endif
 
 	free(dtp->dt_mods);
+#ifdef __FreeBSD__
+	free(dtp->dt_kmods);
+#endif
 	free(dtp->dt_provs);
 	free(dtp);
 }

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c	Sat Jun  6 16:45:59 2015	(r284084)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pragma.c	Sat Jun  6 16:47:45 2015	(r284085)
@@ -278,6 +278,14 @@ dt_pragma_depends(const char *prname, dt
 	} else if (strcmp(cnp->dn_string, "module") == 0) {
 		dt_module_t *mp = dt_module_lookup_by_name(dtp, nnp->dn_string);
 		found = mp != NULL && dt_module_getctf(dtp, mp) != NULL;
+#ifdef __FreeBSD__
+		if (!found) {
+			dt_kmodule_t *dkmp = dt_kmodule_lookup(dtp,
+			    nnp->dn_string);
+			found = dkmp != NULL &&
+			    dt_module_getctf(dtp, dkmp->dkm_module) != NULL;
+		}
+#endif
 	} else if (strcmp(cnp->dn_string, "library") == 0) {
 		if (yypcb->pcb_cflags & DTRACE_C_CTL) {
 			assert(dtp->dt_filetag != NULL);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201506061647.t56GljPD041378>