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
This commit is contained in:
parent
3981a55d9d
commit
8436cb81cd
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=284085
@ -156,6 +156,21 @@ typedef struct dt_module {
|
|||||||
#define DT_DM_KERNEL 0x2 /* module is associated with a kernel object */
|
#define DT_DM_KERNEL 0x2 /* module is associated with a kernel object */
|
||||||
#define DT_DM_PRIMARY 0x4 /* module is a krtld primary 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 {
|
typedef struct dt_provmod {
|
||||||
char *dp_name; /* name of provider module */
|
char *dp_name; /* name of provider module */
|
||||||
struct dt_provmod *dp_next; /* next 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_idhash_t *dt_tls; /* hash table of thread-local identifiers */
|
||||||
dt_list_t dt_modlist; /* linked list of dt_module_t's */
|
dt_list_t dt_modlist; /* linked list of dt_module_t's */
|
||||||
dt_module_t **dt_mods; /* hash table 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_modbuckets; /* number of module hash buckets */
|
||||||
uint_t dt_nmods; /* number of modules in hash and list */
|
uint_t dt_nmods; /* number of modules in hash and list */
|
||||||
dt_provmod_t *dt_provmod; /* linked list of provider modules */
|
dt_provmod_t *dt_provmod; /* linked list of provider modules */
|
||||||
|
@ -37,6 +37,7 @@
|
|||||||
#else
|
#else
|
||||||
#include <sys/param.h>
|
#include <sys/param.h>
|
||||||
#include <sys/linker.h>
|
#include <sys/linker.h>
|
||||||
|
#include <sys/module.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -542,6 +543,22 @@ dt_module_lookup_by_ctf(dtrace_hdl_t *dtp, ctf_file_t *ctfp)
|
|||||||
return (ctfp ? ctf_getspecific(ctfp) : NULL);
|
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
|
static int
|
||||||
dt_module_load_sect(dtrace_hdl_t *dtp, dt_module_t *dmp, ctf_sect_t *ctsp)
|
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, struct kld_file_stat *k_stat)
|
|||||||
char fname[MAXPATHLEN];
|
char fname[MAXPATHLEN];
|
||||||
struct stat64 st;
|
struct stat64 st;
|
||||||
int fd, err, bits;
|
int fd, err, bits;
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
struct module_stat ms;
|
||||||
|
dt_kmodule_t *dkmp;
|
||||||
|
uint_t h;
|
||||||
|
int modid;
|
||||||
|
#endif
|
||||||
|
|
||||||
dt_module_t *dmp;
|
dt_module_t *dmp;
|
||||||
const char *s;
|
const char *s;
|
||||||
@ -1270,6 +1293,33 @@ dt_module_update(dtrace_hdl_t *dtp, struct kld_file_stat *k_stat)
|
|||||||
if (dmp->dm_info.objfs_info_primary)
|
if (dmp->dm_info.objfs_info_primary)
|
||||||
dmp->dm_flags |= DT_DM_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",
|
dt_dprintf("opened %d-bit module %s (%s) [%d]\n",
|
||||||
bits, dmp->dm_name, dmp->dm_file, dmp->dm_modid);
|
bits, dmp->dm_name, dmp->dm_file, dmp->dm_modid);
|
||||||
}
|
}
|
||||||
|
@ -44,6 +44,10 @@ extern void dt_module_destroy(dtrace_hdl_t *, dt_module_t *);
|
|||||||
extern dt_module_t *dt_module_lookup_by_name(dtrace_hdl_t *, const char *);
|
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 *);
|
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 int dt_module_hasctf(dtrace_hdl_t *, dt_module_t *);
|
||||||
extern ctf_file_t *dt_module_getctf(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 *,
|
extern dt_ident_t *dt_module_extern(dtrace_hdl_t *, dt_module_t *,
|
||||||
|
@ -1178,6 +1178,9 @@ dt_vopen(int version, int flags, int *errp,
|
|||||||
#endif
|
#endif
|
||||||
dtp->dt_modbuckets = _dtrace_strbuckets;
|
dtp->dt_modbuckets = _dtrace_strbuckets;
|
||||||
dtp->dt_mods = calloc(dtp->dt_modbuckets, sizeof (dt_module_t *));
|
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_provbuckets = _dtrace_strbuckets;
|
||||||
dtp->dt_provs = calloc(dtp->dt_provbuckets, sizeof (dt_provider_t *));
|
dtp->dt_provs = calloc(dtp->dt_provbuckets, sizeof (dt_provider_t *));
|
||||||
dt_proc_hash_create(dtp);
|
dt_proc_hash_create(dtp);
|
||||||
@ -1199,6 +1202,7 @@ dt_vopen(int version, int flags, int *errp,
|
|||||||
if (dtp->dt_mods == NULL || dtp->dt_provs == NULL ||
|
if (dtp->dt_mods == NULL || dtp->dt_provs == NULL ||
|
||||||
dtp->dt_procs == NULL || dtp->dt_ld_path == NULL ||
|
dtp->dt_procs == NULL || dtp->dt_ld_path == NULL ||
|
||||||
#ifdef __FreeBSD__
|
#ifdef __FreeBSD__
|
||||||
|
dtp->dt_kmods == NULL ||
|
||||||
dtp->dt_objcopy_path == NULL ||
|
dtp->dt_objcopy_path == NULL ||
|
||||||
#endif
|
#endif
|
||||||
dtp->dt_cpp_path == NULL || dtp->dt_cpp_argv == NULL)
|
dtp->dt_cpp_path == NULL || dtp->dt_cpp_argv == NULL)
|
||||||
@ -1621,6 +1625,10 @@ dtrace_close(dtrace_hdl_t *dtp)
|
|||||||
dtrace_prog_t *pgp;
|
dtrace_prog_t *pgp;
|
||||||
dt_xlator_t *dxp;
|
dt_xlator_t *dxp;
|
||||||
dt_dirpath_t *dirp;
|
dt_dirpath_t *dirp;
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
dt_kmodule_t *dkm;
|
||||||
|
uint_t h;
|
||||||
|
#endif
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
if (dtp->dt_procs != NULL)
|
if (dtp->dt_procs != NULL)
|
||||||
@ -1648,6 +1656,15 @@ dtrace_close(dtrace_hdl_t *dtp)
|
|||||||
if (dtp->dt_tls != NULL)
|
if (dtp->dt_tls != NULL)
|
||||||
dt_idhash_destroy(dtp->dt_tls);
|
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)
|
while ((dmp = dt_list_next(&dtp->dt_modlist)) != NULL)
|
||||||
dt_module_destroy(dtp, dmp);
|
dt_module_destroy(dtp, dmp);
|
||||||
|
|
||||||
@ -1697,6 +1714,9 @@ dtrace_close(dtrace_hdl_t *dtp)
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
free(dtp->dt_mods);
|
free(dtp->dt_mods);
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
free(dtp->dt_kmods);
|
||||||
|
#endif
|
||||||
free(dtp->dt_provs);
|
free(dtp->dt_provs);
|
||||||
free(dtp);
|
free(dtp);
|
||||||
}
|
}
|
||||||
|
@ -278,6 +278,14 @@ dt_pragma_depends(const char *prname, dt_node_t *cnp)
|
|||||||
} else if (strcmp(cnp->dn_string, "module") == 0) {
|
} else if (strcmp(cnp->dn_string, "module") == 0) {
|
||||||
dt_module_t *mp = dt_module_lookup_by_name(dtp, nnp->dn_string);
|
dt_module_t *mp = dt_module_lookup_by_name(dtp, nnp->dn_string);
|
||||||
found = mp != NULL && dt_module_getctf(dtp, mp) != NULL;
|
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) {
|
} else if (strcmp(cnp->dn_string, "library") == 0) {
|
||||||
if (yypcb->pcb_cflags & DTRACE_C_CTL) {
|
if (yypcb->pcb_cflags & DTRACE_C_CTL) {
|
||||||
assert(dtp->dt_filetag != NULL);
|
assert(dtp->dt_filetag != NULL);
|
||||||
|
Loading…
Reference in New Issue
Block a user