diff --git a/sys/amd64/linux/linux_dummy.c b/sys/amd64/linux/linux_dummy.c index 96cf8d9..7989b52 100644 --- a/sys/amd64/linux/linux_dummy.c +++ b/sys/amd64/linux/linux_dummy.c @@ -28,7 +28,6 @@ __FBSDID("$FreeBSD$"); #include "opt_compat.h" -#include "opt_kdtrace.h" #include #include diff --git a/sys/arm/arm/exception.S b/sys/arm/arm/exception.S index 5f1dff7..dc727d1 100644 --- a/sys/arm/arm/exception.S +++ b/sys/arm/arm/exception.S @@ -48,7 +48,6 @@ #include "assym.s" -#include "opt_kdtrace.h" #include #include #include diff --git a/sys/cam/ctl/ctl_backend_block.c b/sys/cam/ctl/ctl_backend_block.c index df65ffd..7671132 100644 --- a/sys/cam/ctl/ctl_backend_block.c +++ b/sys/cam/ctl/ctl_backend_block.c @@ -610,10 +610,10 @@ ctl_be_block_flush_file(struct ctl_be_block_lun *be_lun, ctl_complete_beio(beio); } -SDT_PROBE_DEFINE1(cbb, kernel, read, file_start, "uint64_t"); -SDT_PROBE_DEFINE1(cbb, kernel, write, file_start, "uint64_t"); -SDT_PROBE_DEFINE1(cbb, kernel, read, file_done,"uint64_t"); -SDT_PROBE_DEFINE1(cbb, kernel, write, file_done, "uint64_t"); +SDT_PROBE_DEFINE1(cbb, , read, file_start, "uint64_t"); +SDT_PROBE_DEFINE1(cbb, , write, file_start, "uint64_t"); +SDT_PROBE_DEFINE1(cbb, , read, file_done,"uint64_t"); +SDT_PROBE_DEFINE1(cbb, , write, file_done, "uint64_t"); static void ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun, @@ -638,10 +638,10 @@ ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun, bzero(&xuio, sizeof(xuio)); if (beio->bio_cmd == BIO_READ) { - SDT_PROBE(cbb, kernel, read, file_start, 0, 0, 0, 0, 0); + SDT_PROBE0(cbb, , read, file_start); xuio.uio_rw = UIO_READ; } else { - SDT_PROBE(cbb, kernel, write, file_start, 0, 0, 0, 0, 0); + SDT_PROBE0(cbb, , write, file_start); xuio.uio_rw = UIO_WRITE; } xuio.uio_offset = beio->io_offset; @@ -684,7 +684,7 @@ ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun, error = VOP_READ(be_lun->vn, &xuio, flags, file_data->cred); VOP_UNLOCK(be_lun->vn, 0); - SDT_PROBE(cbb, kernel, read, file_done, 0, 0, 0, 0, 0); + SDT_PROBE0(cbb, , read, file_done); if (error == 0 && xuio.uio_resid > 0) { /* * If we red less then requested (EOF), then @@ -733,7 +733,7 @@ ctl_be_block_dispatch_file(struct ctl_be_block_lun *be_lun, VOP_UNLOCK(be_lun->vn, 0); vn_finished_write(mountpoint); - SDT_PROBE(cbb, kernel, write, file_done, 0, 0, 0, 0, 0); + SDT_PROBE0(cbb, , write, file_done); } mtx_lock(&be_lun->io_lock); @@ -869,10 +869,10 @@ ctl_be_block_dispatch_zvol(struct ctl_be_block_lun *be_lun, bzero(&xuio, sizeof(xuio)); if (beio->bio_cmd == BIO_READ) { - SDT_PROBE(cbb, kernel, read, file_start, 0, 0, 0, 0, 0); + SDT_PROBE0(cbb, , read, file_start); xuio.uio_rw = UIO_READ; } else { - SDT_PROBE(cbb, kernel, write, file_start, 0, 0, 0, 0, 0); + SDT_PROBE0(cbb, , write, file_start); xuio.uio_rw = UIO_WRITE; } xuio.uio_offset = beio->io_offset; @@ -903,9 +903,9 @@ ctl_be_block_dispatch_zvol(struct ctl_be_block_lun *be_lun, error = ENXIO; if (beio->bio_cmd == BIO_READ) - SDT_PROBE(cbb, kernel, read, file_done, 0, 0, 0, 0, 0); + SDT_PROBE0(cbb, , read, file_done); else - SDT_PROBE(cbb, kernel, write, file_done, 0, 0, 0, 0, 0); + SDT_PROBE0(cbb, , write, file_done); mtx_lock(&be_lun->io_lock); devstat_end_transaction(beio->lun->disk_stats, beio->io_len, @@ -1501,10 +1501,10 @@ ctl_be_block_cw_dispatch(struct ctl_be_block_lun *be_lun, } } -SDT_PROBE_DEFINE1(cbb, kernel, read, start, "uint64_t"); -SDT_PROBE_DEFINE1(cbb, kernel, write, start, "uint64_t"); -SDT_PROBE_DEFINE1(cbb, kernel, read, alloc_done, "uint64_t"); -SDT_PROBE_DEFINE1(cbb, kernel, write, alloc_done, "uint64_t"); +SDT_PROBE_DEFINE1(cbb, , read, start, "uint64_t"); +SDT_PROBE_DEFINE1(cbb, , write, start, "uint64_t"); +SDT_PROBE_DEFINE1(cbb, , read, alloc_done, "uint64_t"); +SDT_PROBE_DEFINE1(cbb, , write, alloc_done, "uint64_t"); static void ctl_be_block_next(struct ctl_be_block_io *beio) @@ -1549,9 +1549,9 @@ ctl_be_block_dispatch(struct ctl_be_block_lun *be_lun, lbalen = ARGS(io); if (lbalen->flags & CTL_LLF_WRITE) { - SDT_PROBE(cbb, kernel, write, start, 0, 0, 0, 0, 0); + SDT_PROBE0(cbb, , write, start); } else { - SDT_PROBE(cbb, kernel, read, start, 0, 0, 0, 0, 0); + SDT_PROBE0(cbb, , read, start); } beio = ctl_alloc_beio(softc); @@ -1638,10 +1638,10 @@ ctl_be_block_dispatch(struct ctl_be_block_lun *be_lun, * need to get the data from the user first. */ if (beio->bio_cmd == BIO_READ) { - SDT_PROBE(cbb, kernel, read, alloc_done, 0, 0, 0, 0, 0); + SDT_PROBE0(cbb, , read, alloc_done); be_lun->dispatch(be_lun, beio); } else { - SDT_PROBE(cbb, kernel, write, alloc_done, 0, 0, 0, 0, 0); + SDT_PROBE0(cbb, , write, alloc_done); #ifdef CTL_TIME_IO getbinuptime(&io->io_hdr.dma_start_bt); #endif diff --git a/sys/cddl/compat/opensolaris/sys/sdt.h b/sys/cddl/compat/opensolaris/sys/sdt.h index 04e4abb..ad192b0 100644 --- a/sys/cddl/compat/opensolaris/sys/sdt.h +++ b/sys/cddl/compat/opensolaris/sys/sdt.h @@ -32,14 +32,21 @@ #include_next #ifdef KDTRACE_HOOKS + SDT_PROBE_DECLARE(sdt, , , set__error); -#define SET_ERROR(err) \ - ((sdt_sdt___set__error->id ? \ - (*sdt_probe_func)(sdt_sdt___set__error->id, \ - (uintptr_t)err, 0, 0, 0, 0) : 0), err) +static inline int +__sdt_set_error(int err) +{ + + SDT_PROBE1(sdt, , , set__error, err); + return (err); +} + +#define SET_ERROR(err) (__sdt_set_error(err)) + #else #define SET_ERROR(err) (err) #endif -#endif /* _OPENSOLARIS_SYS_SDT_H_ */ +#endif /* _OPENSOLARIS_SYS_SDT_H_ */ diff --git a/sys/cddl/dev/sdt/sdt.c b/sys/cddl/dev/sdt/sdt.c index 4e5dd71..e90071c 100644 --- a/sys/cddl/dev/sdt/sdt.c +++ b/sys/cddl/dev/sdt/sdt.c @@ -19,9 +19,6 @@ * CDDL HEADER END * * Portions Copyright 2006-2008 John Birrell jb@freebsd.org - * - * $FreeBSD$ - * */ /* @@ -40,6 +37,8 @@ */ #include +__FBSDID("$FreeBSD$"); + #include #include @@ -60,6 +59,18 @@ #include #include +/* XXX */ +#include "sdt.h" + +#define SDT_TABENTRIES 0x2000 +#define SDT_HADDR(addr) ((u_long)(((addr) >> 4) & sdt_hashmask)) +#define SDT_HENTRY(addr) (&sdt_probetab[SDT_HADDR(addr)]) + +LIST_HEAD(, sdt_invoprec) *sdt_probetab; +u_long sdt_hashmask; + +MALLOC_DECLARE(M_SDT); + /* DTrace methods. */ static void sdt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *); static void sdt_provide_probes(void *, dtrace_probedesc_t *); @@ -69,19 +80,18 @@ static void sdt_disable(void *, dtrace_id_t, void *); static void sdt_load(void); static int sdt_unload(void); +static void sdt_create_invoprec(struct sdt_probedesc *, dtrace_id_t); static void sdt_create_provider(struct sdt_provider *); -static void sdt_create_probe(struct sdt_probe *); +static void sdt_create_probe(struct sdt_probe *, struct linker_file *); static void sdt_kld_load(void *, struct linker_file *); static void sdt_kld_unload_try(void *, struct linker_file *, int *); -static MALLOC_DEFINE(M_SDT, "SDT", "DTrace SDT providers"); - static dtrace_pattr_t sdt_attr = { { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON }, { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN }, { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA }, { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON }, -{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA }, +{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA }, }; static dtrace_pops_t sdt_pops = { @@ -102,6 +112,29 @@ static TAILQ_HEAD(, sdt_provider) sdt_prov_list; static eventhandler_tag sdt_kld_load_tag; static eventhandler_tag sdt_kld_unload_try_tag; +struct sdt_invoprec * +sdt_lookup_site(uint64_t offset) +{ + struct sdt_invoprec *rec; + + LIST_FOREACH(rec, &sdt_probetab[SDT_HADDR(offset)], sr_next) { + if (rec->sr_desc->spd_offset == offset) + return (rec); + } + return (NULL); +} + +void +sdt_create_invoprec(struct sdt_probedesc *desc, dtrace_id_t id) +{ + struct sdt_invoprec *rec; + + rec = malloc(sizeof(*rec), M_SDT, M_WAITOK); + rec->sr_desc = desc; + rec->sr_id = id; + LIST_INSERT_HEAD(SDT_HENTRY(desc->spd_offset), rec, sr_next); +} + static void sdt_create_provider(struct sdt_provider *prov) { @@ -130,31 +163,63 @@ sdt_create_provider(struct sdt_provider *prov) prov->id = newprov->id; } +struct sdt_descmatch { + struct sdt_probedesc *desc; + char *func; +}; + +static int +sdt_desc_match(struct linker_file *lf, int symidx, linker_symval_t *sym, + void *arg) +{ + struct sdt_descmatch *match; + uint64_t offset; + + match = arg; + offset = match->desc->spd_offset; + if (offset >= (uint64_t)sym->value && offset < (uint64_t)sym->value + + sym->size) { + strlcpy(match->func, sym->name, DTRACE_FUNCNAMELEN); + /* Found a match, stop iterating. */ + return (EJUSTRETURN); + } + return (0); +} + static void -sdt_create_probe(struct sdt_probe *probe) +sdt_create_probe(struct sdt_probe *probe, struct linker_file *lf) { + struct sdt_probedesc *desc; + struct sdt_descmatch match; struct sdt_provider *prov; char mod[DTRACE_MODNAMELEN]; char func[DTRACE_FUNCNAMELEN]; char name[DTRACE_NAMELEN]; + dtrace_id_t id; const char *from; char *to; size_t len; + int aframes, error; if (probe->version != (int)sizeof(*probe)) { - printf("ignoring probe %p, version %u expected %u\n", + printf("sdt: ignoring probe %p, version %u expected %u\n", probe, probe->version, (int)sizeof(*probe)); return; } + aframes = 3; + probe->sdtp_lf = lf; + TAILQ_FOREACH(prov, &sdt_prov_list, prov_entry) if (strcmp(prov->name, probe->prov->name) == 0) break; KASSERT(prov != NULL, ("probe defined without a provider")); - /* If no module name was specified, use the module filename. */ - if (*probe->mod == 0) { + /* + * If no module name was specified, use the module filename. + */ + if (probe->mod[0] == '\0') { len = strlcpy(mod, probe->sdtp_lf->filename, sizeof(mod)); if (len > 3 && strcmp(mod + len - 3, ".ko") == 0) mod[len - 3] = '\0'; @@ -162,18 +227,11 @@ sdt_create_probe(struct sdt_probe *probe) strlcpy(mod, probe->mod, sizeof(mod)); /* - * Unfortunately this is necessary because the Solaris DTrace - * code mixes consts and non-consts with casts to override - * the incompatibilies. On FreeBSD, we use strict warnings - * in the C compiler, so we have to respect const vs non-const. + * Demangle the probe name: two consecutive underscores become a dash. */ - strlcpy(func, probe->func, sizeof(func)); - if (func[0] == '\0') - strcpy(func, "none"); - from = probe->name; to = name; - for (len = 0; len < (sizeof(name) - 1) && *from != '\0'; + for (len = 0; len < sizeof(name) - 1 && *from != '\0'; len++, from++, to++) { if (from[0] == '_' && from[1] == '_') { *to = '-'; @@ -183,10 +241,39 @@ sdt_create_probe(struct sdt_probe *probe) } *to = '\0'; - if (dtrace_probe_lookup(prov->id, mod, func, name) != DTRACE_IDNONE) - return; - - (void)dtrace_probe_create(prov->id, mod, func, name, 1, probe); + /* + * Finally, create the probe. If a function name is hard-coded, we + * register a single probe and use its ID for each site. Otherwise, we + * proceed normally and create a probe for each site. + */ + if (probe->func[0] != '\0') { + strlcpy(func, probe->func, sizeof(func)); + + desc = malloc(sizeof(*desc), M_SDT, M_WAITOK); + desc->li.spd_probe = probe; + desc->spd_offset = 0; + + id = dtrace_probe_create(prov->id, mod, func, name, aframes, + desc); + SLIST_FOREACH(desc, &probe->site_list, li.spd_entry) + sdt_create_invoprec(desc, id); + } else { + match.func = &func[0]; + while ((desc = SLIST_FIRST(&probe->site_list)) != NULL) { + match.desc = desc; + error = linker_file_function_listall(lf, sdt_desc_match, + &match); + if (error != EJUSTRETURN) + printf("sdt: no function found at %#lx (%d)\n", + desc->spd_offset, error); + SLIST_REMOVE_HEAD(&probe->site_list, li.spd_entry); + desc->li.spd_probe = probe; + + id = dtrace_probe_create(prov->id, mod, func, name, + aframes, desc); + sdt_create_invoprec(desc, id); + } + } } /* @@ -202,51 +289,57 @@ sdt_provide_probes(void *arg, dtrace_probedesc_t *desc) static void sdt_enable(void *arg __unused, dtrace_id_t id, void *parg) { - struct sdt_probe *probe = parg; + struct sdt_probedesc *desc = parg; + struct sdt_probe *probe = desc->li.spd_probe; - probe->id = id; probe->sdtp_lf->nenabled++; if (strcmp(probe->prov->name, "lockstat") == 0) lockstat_enabled++; + sdt_probe_enable(desc); } static void sdt_disable(void *arg __unused, dtrace_id_t id, void *parg) { - struct sdt_probe *probe = parg; + struct sdt_probedesc *desc = parg; + struct sdt_probe *probe = desc->li.spd_probe; KASSERT(probe->sdtp_lf->nenabled > 0, ("no probes enabled")); + sdt_probe_disable(desc); if (strcmp(probe->prov->name, "lockstat") == 0) lockstat_enabled--; - probe->id = 0; probe->sdtp_lf->nenabled--; } static void -sdt_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc) +sdt_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *argdesc) { struct sdt_argtype *argtype; - struct sdt_probe *probe = parg; + struct sdt_probedesc *desc; + struct sdt_probe *probe; - if (desc->dtargd_ndx >= probe->n_args) { - desc->dtargd_ndx = DTRACE_ARGNONE; + desc = parg; + probe = desc->li.spd_probe; + if (argdesc->dtargd_ndx >= probe->n_args) { + argdesc->dtargd_ndx = DTRACE_ARGNONE; return; } TAILQ_FOREACH(argtype, &probe->argtype_list, argtype_entry) { - if (desc->dtargd_ndx == argtype->ndx) { - desc->dtargd_mapping = desc->dtargd_ndx; + if (argdesc->dtargd_ndx == argtype->ndx) { + argdesc->dtargd_mapping = argdesc->dtargd_ndx; if (argtype->type == NULL) { - desc->dtargd_native[0] = '\0'; - desc->dtargd_xlate[0] = '\0'; + argdesc->dtargd_native[0] = '\0'; + argdesc->dtargd_xlate[0] = '\0'; continue; } - strlcpy(desc->dtargd_native, argtype->type, - sizeof(desc->dtargd_native)); + strlcpy(argdesc->dtargd_native, argtype->type, + sizeof(argdesc->dtargd_native)); if (argtype->xtype != NULL) - strlcpy(desc->dtargd_xlate, argtype->xtype, - sizeof(desc->dtargd_xlate)); + strlcpy(argdesc->dtargd_xlate, argtype->xtype, + sizeof(argdesc->dtargd_xlate)); + break; } } } @@ -254,8 +347,25 @@ sdt_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc) static void sdt_destroy(void *arg, dtrace_id_t id, void *parg) { + struct sdt_probedesc *desc; + struct sdt_probe *probe; + + desc = parg; + if (desc->spd_offset == 0) { + probe = desc->li.spd_probe; + KASSERT(strlen(probe->func) > 0, + ("probefunc is empty for %s:::%s", probe->prov->name, + probe->name)); + free(desc, M_SDT); + } } +#define SDT_LINKER_SET_FOREACH(lf, set, it) \ + __typeof(it) __##set##_start, __##set##_end; \ + if (linker_file_lookup_set(lf, #set, &__##set##_start, \ + &__##set##_end, NULL) == 0) \ + for (it = __##set##_start; it < __##set##_end; it++) + /* * Called from the kernel linker when a module is loaded, before * dtrace_module_loaded() is called. This is done so that it's possible to @@ -266,53 +376,40 @@ sdt_destroy(void *arg, dtrace_id_t id, void *parg) static void sdt_kld_load(void *arg __unused, struct linker_file *lf) { - struct sdt_provider **prov, **begin, **end; - struct sdt_probe **probe, **p_begin, **p_end; - struct sdt_argtype **argtype, **a_begin, **a_end; - - if (linker_file_lookup_set(lf, "sdt_providers_set", &begin, &end, - NULL) == 0) { - for (prov = begin; prov < end; prov++) - sdt_create_provider(*prov); + struct sdt_provider **prov; + struct sdt_probe **probe; + struct sdt_argtype **argtype; + + SDT_LINKER_SET_FOREACH(lf, sdt_providers_set, prov) { + sdt_create_provider(*prov); } - if (linker_file_lookup_set(lf, "sdt_probes_set", &p_begin, &p_end, - NULL) == 0) { - for (probe = p_begin; probe < p_end; probe++) { - (*probe)->sdtp_lf = lf; - sdt_create_probe(*probe); - TAILQ_INIT(&(*probe)->argtype_list); - } + SDT_LINKER_SET_FOREACH(lf, sdt_probes_set, probe) { + sdt_create_probe(*probe, lf); + TAILQ_INIT(&(*probe)->argtype_list); } - if (linker_file_lookup_set(lf, "sdt_argtypes_set", &a_begin, &a_end, - NULL) == 0) { - for (argtype = a_begin; argtype < a_end; argtype++) { - (*argtype)->probe->n_args++; - TAILQ_INSERT_TAIL(&(*argtype)->probe->argtype_list, - *argtype, argtype_entry); - } + SDT_LINKER_SET_FOREACH(lf, sdt_argtypes_set, argtype) { + (*argtype)->probe->n_args++; + TAILQ_INSERT_TAIL(&(*argtype)->probe->argtype_list, *argtype, + argtype_entry); } } static void sdt_kld_unload_try(void *arg __unused, struct linker_file *lf, int *error) { - struct sdt_provider *prov, **curr, **begin, **end, *tmp; + struct sdt_provider *prov, **curr, *tmp; if (*error != 0) /* We already have an error, so don't do anything. */ return; - else if (linker_file_lookup_set(lf, "sdt_providers_set", &begin, &end, - NULL)) - /* No DTrace providers are declared in this file. */ - return; /* * Go through all the providers declared in this linker file and * unregister any that aren't declared in another loaded file. */ - for (curr = begin; curr < end; curr++) { + SDT_LINKER_SET_FOREACH(lf, sdt_providers_set, curr) { TAILQ_FOREACH_SAFE(prov, &sdt_prov_list, prov_entry, tmp) { if (strcmp(prov->name, (*curr)->name) != 0) continue; @@ -337,7 +434,6 @@ sdt_linker_file_cb(linker_file_t lf, void *arg __unused) { sdt_kld_load(NULL, lf); - return (0); } @@ -347,7 +443,7 @@ sdt_load() TAILQ_INIT(&sdt_prov_list); - sdt_probe_func = dtrace_probe; + sdt_probetab = hashinit(SDT_TABENTRIES, M_SDT, &sdt_hashmask); sdt_kld_load_tag = EVENTHANDLER_REGISTER(kld_load, sdt_kld_load, NULL, EVENTHANDLER_PRI_ANY); @@ -356,6 +452,8 @@ sdt_load() /* Pick up probes from the kernel and already-loaded linker files. */ linker_file_foreach(sdt_linker_file_cb, NULL); + + dtrace_invop_add(sdt_invop); } static int @@ -364,10 +462,13 @@ sdt_unload() struct sdt_provider *prov, *tmp; int ret; + dtrace_invop_remove(sdt_invop); + EVENTHANDLER_DEREGISTER(kld_load, sdt_kld_load_tag); EVENTHANDLER_DEREGISTER(kld_unload_try, sdt_kld_unload_try_tag); - sdt_probe_func = sdt_probe_stub; + /* XXX need to free recs. */ + hashdestroy(sdt_probetab, M_SDT, sdt_hashmask); TAILQ_FOREACH_SAFE(prov, &sdt_prov_list, prov_entry, tmp) { ret = dtrace_unregister(prov->id); @@ -377,7 +478,6 @@ sdt_unload() free(prov->name, M_SDT); free(prov, M_SDT); } - return (0); } @@ -390,19 +490,15 @@ sdt_modevent(module_t mod __unused, int type, void *data __unused) case MOD_LOAD: sdt_load(); break; - case MOD_UNLOAD: error = sdt_unload(); break; - case MOD_SHUTDOWN: break; - default: error = EOPNOTSUPP; break; } - return (error); } diff --git a/sys/cddl/dev/sdt/sdt.h b/sys/cddl/dev/sdt/sdt.h new file mode 100644 index 0000000..ca95c21 --- /dev/null +++ b/sys/cddl/dev/sdt/sdt.h @@ -0,0 +1,24 @@ +#ifndef _SDT_H_ +#define _SDT_H_ + +struct sdt_probedesc; + +/* + * An entry in the SDT hash table. These records exist one-to-one with SDT probe + * descriptors, but are split into a separate struct to avoid bloat: descriptors + * are created at compile-time and always reside in memory. Note that multiple + * records may have the same id if the probe definition hard-codes a function + * name. + */ +struct sdt_invoprec { + struct sdt_probedesc *sr_desc; + LIST_ENTRY(sdt_invoprec) sr_next; + dtrace_id_t sr_id; +}; + +struct sdt_invoprec *sdt_lookup_site(uint64_t); +int sdt_invop(uintptr_t, uintptr_t *, uintptr_t); +void sdt_probe_enable(struct sdt_probedesc *); +void sdt_probe_disable(struct sdt_probedesc *); + +#endif /* _SDT_H_ */ diff --git a/sys/cddl/dev/sdt/x86/sdt_isa.c b/sys/cddl/dev/sdt/x86/sdt_isa.c new file mode 100644 index 0000000..53c2bcd --- /dev/null +++ b/sys/cddl/dev/sdt/x86/sdt_isa.c @@ -0,0 +1,74 @@ +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include + +#include + +#include + +#include "sdt.h" + +#define AMD64_BP 0xcc +#define AMD64_NOP 0x90 + +int +sdt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval) +{ + struct sdt_invoprec *rec; + struct trapframe *tf; + + rec = sdt_lookup_site(addr); + if (rec == NULL) + return (0); + + tf = (struct trapframe *)(stack + 1); +#ifdef __amd64__ + dtrace_probe(rec->sr_id, tf->tf_rdi, tf->tf_rsi, tf->tf_rdx, tf->tf_rcx, + tf->tf_r8); +#else + dtrace_probe(rec->sr_id, stack[0], stack[1], stack[2], stack[3], + stack[4]); +#endif + return (DTRACE_INVOP_NOP); +} + +void +sdt_probe_enable(struct sdt_probedesc *desc) +{ + struct sdt_probe *probe; + uint8_t *callsite; + + if (desc->spd_offset == 0) { + probe = desc->li.spd_probe; + MPASS(strlen(probe->func) > 0); + SLIST_FOREACH(desc, &probe->site_list, li.spd_entry) { + callsite = (uint8_t *)desc->spd_offset; + callsite[0] = AMD64_BP; + } + } else { + callsite = (uint8_t *)desc->spd_offset; + callsite[0] = AMD64_BP; + } +} + +void +sdt_probe_disable(struct sdt_probedesc *desc) +{ + struct sdt_probe *probe; + uint8_t *callsite; + + if (desc->spd_offset == 0) { + probe = desc->li.spd_probe; + MPASS(strlen(probe->func) > 0); + SLIST_FOREACH(desc, &probe->site_list, li.spd_entry) { + callsite = (uint8_t *)desc->spd_offset; + callsite[0] = AMD64_NOP; + } + } else { + callsite = (uint8_t *)desc->spd_offset; + callsite[0] = AMD64_NOP; + } +} diff --git a/sys/compat/linux/linux_dtrace.h b/sys/compat/linux/linux_dtrace.h index c446b3e..6e91327 100644 --- a/sys/compat/linux/linux_dtrace.h +++ b/sys/compat/linux/linux_dtrace.h @@ -72,8 +72,8 @@ #define LIN_SDT_PROBE_DEFINE5(a, b, c, d, e, f, g, h) _LIN_SDT_PROBE_DEFINE5(\ LINUX_DTRACE, a, b, c, d, e, f, g, h) -#define LIN_SDT_PROBE0(a, b, c) SDT_PROBE1(LINUX_DTRACE, a, b, \ - c, 0) +#define LIN_SDT_PROBE0(a, b, c) SDT_PROBE0(LINUX_DTRACE, a, b, \ + c) #define LIN_SDT_PROBE1(a, b, c, d) SDT_PROBE1(LINUX_DTRACE, a, b, \ c, d) #define LIN_SDT_PROBE2(a, b, c, d, e) SDT_PROBE2(LINUX_DTRACE, a, b, \ diff --git a/sys/conf/Makefile.arm b/sys/conf/Makefile.arm index af5f7da..0e51e3b 100644 --- a/sys/conf/Makefile.arm +++ b/sys/conf/Makefile.arm @@ -58,7 +58,7 @@ genassym.o: bus_if.h device_if.h SYSTEM_LD_ = ${LD} -Bdynamic -T ldscript.$M.noheader ${_LDFLAGS} \ -warn-common -export-dynamic -dynamic-linker /red/herring -o \ - ${FULLKERNEL}.noheader -X ${SYSTEM_OBJS} vers.o + ${FULLKERNEL}.noheader -X ${FULLKERNEL}.reloc vers.o hack.So SYSTEM_LD_TAIL +=;sed s/" + SIZEOF_HEADERS"// ldscript.$M\ >ldscript.$M.noheader; \ ${SYSTEM_LD_}; \ diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index 0788b46..f579cbb 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -610,6 +610,7 @@ x86/x86/mp_x86.c optional smp x86/x86/msi.c optional pci x86/x86/nexus.c standard x86/x86/pvclock.c standard +x86/x86/sdt_machdep.c optional kdtrace_hooks x86/x86/stack_machdep.c optional ddb | stack x86/x86/tsc.c standard x86/x86/delay.c standard diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index ffe272e..00bbd3b 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -604,6 +604,7 @@ x86/x86/mptable_pci.c optional apic pci x86/x86/mp_x86.c optional smp x86/x86/msi.c optional apic pci x86/x86/nexus.c standard +x86/x86/sdt_machdep.c optional kdtrace_hooks x86/x86/stack_machdep.c optional ddb | stack x86/x86/tsc.c standard x86/x86/pvclock.c standard diff --git a/sys/conf/kern.post.mk b/sys/conf/kern.post.mk index ddf828e..255827e 100644 --- a/sys/conf/kern.post.mk +++ b/sys/conf/kern.post.mk @@ -126,7 +126,14 @@ gdbinit: .endif .endif -${FULLKERNEL}: ${SYSTEM_DEP} vers.o +sdtstubs.c: ${FULLKERNEL}.reloc + AWK='${AWK}' OBJDUMP='${OBJDUMP}' NM='${NM}' \ + sh $S/tools/sdtstubs.sh ${.ALLSRC} > ${.TARGET} + +${FULLKERNEL}.reloc: ${SYSTEM_DEP} + @${LD} --relocatable -o ${.TARGET} ${SYSTEM_OBJS} + +${FULLKERNEL}: ${FULLKERNEL}.reloc sdtstubs.o vers.o @rm -f ${.TARGET} @echo linking ${.TARGET} ${SYSTEM_LD} @@ -137,6 +144,8 @@ ${FULLKERNEL}: ${SYSTEM_DEP} vers.o .if !defined(DEBUG) ${OBJCOPY} --strip-debug ${.TARGET} .endif + @AWK='${AWK}' OBJCOPY='${OBJCOPY}' OBJDUMP='${OBJDUMP}' \ + sh $S/tools/sdtstrip.sh ${.TARGET} ${SYSTEM_LD_TAIL} .if !exists(${.OBJDIR}/.depend) diff --git a/sys/conf/kern.pre.mk b/sys/conf/kern.pre.mk index 4328749..3014bc2 100644 --- a/sys/conf/kern.pre.mk +++ b/sys/conf/kern.pre.mk @@ -33,6 +33,7 @@ CP?= cp LINT?= lint NM?= nm OBJCOPY?= objcopy +OBJDUMP?= objdump SIZE?= size .if defined(DEBUG) @@ -191,16 +192,15 @@ OFED_C= ${OFED_C_NOIMP} ${.IMPSRC} GEN_CFILES= $S/$M/$M/genassym.c ${MFILES:T:S/.m$/.c/} SYSTEM_CFILES= config.c env.c hints.c vnode_if.c -SYSTEM_DEP= Makefile ${SYSTEM_OBJS} +SYSTEM_DEP= Makefile ${SYSTEM_OBJS} hack.So SYSTEM_OBJS= locore.o ${MDOBJS} ${OBJS} SYSTEM_OBJS+= ${SYSTEM_CFILES:.c=.o} -SYSTEM_OBJS+= hack.So .if ${MFS_IMAGE:Uno} != "no" SYSTEM_OBJS+= embedfs_${MFS_IMAGE:T:R}.o .endif SYSTEM_LD= @${LD} -Bdynamic -T ${LDSCRIPT} ${_LDFLAGS} --no-warn-mismatch \ --warn-common --export-dynamic --dynamic-linker /red/herring \ - -o ${.TARGET} -X ${SYSTEM_OBJS} vers.o + -o ${.TARGET} -X ${.TARGET}.reloc sdtstubs.o vers.o hack.So SYSTEM_LD_TAIL= @${OBJCOPY} --strip-symbol gcc2_compiled. ${.TARGET} ; \ ${SIZE} ${.TARGET} ; chmod 755 ${.TARGET} SYSTEM_DEP+= ${LDSCRIPT} diff --git a/sys/conf/kmod.mk b/sys/conf/kmod.mk index 8bbcfcb..8693ce5 100644 --- a/sys/conf/kmod.mk +++ b/sys/conf/kmod.mk @@ -61,6 +61,7 @@ AWK?= awk KMODLOAD?= /sbin/kldload KMODUNLOAD?= /sbin/kldunload OBJCOPY?= objcopy +OBJDUMP?= objdump .include # Grab all the options for a kernel build. For backwards compat, we need to @@ -225,7 +226,7 @@ ${FULLPROG}: ${OBJS} .else grep -v '^#' < ${EXPORT_SYMS} > export_syms .endif - awk -f ${SYSDIR}/conf/kmod_syms.awk ${.TARGET} \ + ${AWK} -f ${SYSDIR}/conf/kmod_syms.awk ${.TARGET} \ export_syms | xargs -J% ${OBJCOPY} % ${.TARGET} .endif .endif diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c index a0eb069..b75d951 100644 --- a/sys/kern/kern_exec.c +++ b/sys/kern/kern_exec.c @@ -94,9 +94,9 @@ dtrace_execexit_func_t dtrace_fasttrap_exec; #endif SDT_PROVIDER_DECLARE(proc); -SDT_PROBE_DEFINE1(proc, kernel, , exec, "char *"); -SDT_PROBE_DEFINE1(proc, kernel, , exec__failure, "int"); -SDT_PROBE_DEFINE1(proc, kernel, , exec__success, "char *"); +SDT_PROBE_DEFINE1(proc, , , exec, "char *"); +SDT_PROBE_DEFINE1(proc, , , exec__failure, "int"); +SDT_PROBE_DEFINE1(proc, , , exec__success, "char *"); MALLOC_DEFINE(M_PARGS, "proc-args", "Process arguments"); @@ -423,7 +423,7 @@ do_execve(td, args, mac_p) | AUDITVNODE1, UIO_SYSSPACE, args->fname, td); } - SDT_PROBE1(proc, kernel, , exec, args->fname); + SDT_PROBE1(proc, , , exec, args->fname); interpret: if (args->fname != NULL) { @@ -851,7 +851,7 @@ interpret: vfs_mark_atime(imgp->vp, td->td_ucred); - SDT_PROBE1(proc, kernel, , exec__success, args->fname); + SDT_PROBE1(proc, , , exec__success, args->fname); VOP_UNLOCK(imgp->vp, 0); done1: @@ -923,7 +923,7 @@ exec_fail: p->p_flag &= ~P_INEXEC; PROC_UNLOCK(p); - SDT_PROBE1(proc, kernel, , exec__failure, error); + SDT_PROBE1(proc, , , exec__failure, error); done2: #ifdef MAC diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c index 6215ecb..ee87e58 100644 --- a/sys/kern/kern_exit.c +++ b/sys/kern/kern_exit.c @@ -94,7 +94,7 @@ dtrace_execexit_func_t dtrace_fasttrap_exit; #endif SDT_PROVIDER_DECLARE(proc); -SDT_PROBE_DEFINE1(proc, kernel, , exit, "int"); +SDT_PROBE_DEFINE1(proc, , , exit, "int"); /* Hook for NFS teardown procedure. */ void (*nlminfo_release_p)(struct proc *p); @@ -569,7 +569,7 @@ exit1(struct thread *td, int rval, int signo) reason = CLD_DUMPED; else if (WIFSIGNALED(signo)) reason = CLD_KILLED; - SDT_PROBE1(proc, kernel, , exit, reason); + SDT_PROBE1(proc, , , exit, reason); #endif /* diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c index 1b556be..a395fdd 100644 --- a/sys/kern/kern_fork.c +++ b/sys/kern/kern_fork.c @@ -89,8 +89,7 @@ dtrace_fork_func_t dtrace_fasttrap_fork; #endif SDT_PROVIDER_DECLARE(proc); -SDT_PROBE_DEFINE3(proc, kernel, , create, "struct proc *", - "struct proc *", "int"); +SDT_PROBE_DEFINE3(proc, , , create, "struct proc *", "struct proc *", "int"); #ifndef _SYS_SYSPROTO_H_ struct fork_args { @@ -748,7 +747,7 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2, * Tell any interested parties about the new process. */ knote_fork(&p1->p_klist, p2->p_pid); - SDT_PROBE3(proc, kernel, , create, p2, p1, flags); + SDT_PROBE3(proc, , , create, p2, p1, flags); /* * Wait until debugger is attached to child. diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c index aa09a85..0f8d662 100644 --- a/sys/kern/kern_proc.c +++ b/sys/kern/kern_proc.c @@ -92,18 +92,6 @@ __FBSDID("$FreeBSD$"); #endif SDT_PROVIDER_DEFINE(proc); -SDT_PROBE_DEFINE4(proc, kernel, ctor, entry, "struct proc *", "int", - "void *", "int"); -SDT_PROBE_DEFINE4(proc, kernel, ctor, return, "struct proc *", "int", - "void *", "int"); -SDT_PROBE_DEFINE4(proc, kernel, dtor, entry, "struct proc *", "int", - "void *", "struct thread *"); -SDT_PROBE_DEFINE3(proc, kernel, dtor, return, "struct proc *", "int", - "void *"); -SDT_PROBE_DEFINE3(proc, kernel, init, entry, "struct proc *", "int", - "int"); -SDT_PROBE_DEFINE3(proc, kernel, init, return, "struct proc *", "int", - "int"); MALLOC_DEFINE(M_PGRP, "pgrp", "process group header"); MALLOC_DEFINE(M_SESSION, "session", "session header"); @@ -181,9 +169,7 @@ proc_ctor(void *mem, int size, void *arg, int flags) struct proc *p; p = (struct proc *)mem; - SDT_PROBE4(proc, kernel, ctor , entry, p, size, arg, flags); EVENTHANDLER_INVOKE(process_ctor, p); - SDT_PROBE4(proc, kernel, ctor , return, p, size, arg, flags); return (0); } @@ -199,7 +185,6 @@ proc_dtor(void *mem, int size, void *arg) /* INVARIANTS checks go here */ p = (struct proc *)mem; td = FIRST_THREAD_IN_PROC(p); - SDT_PROBE4(proc, kernel, dtor, entry, p, size, arg, td); if (td != NULL) { #ifdef INVARIANTS KASSERT((p->p_numthreads == 1), @@ -212,7 +197,6 @@ proc_dtor(void *mem, int size, void *arg) EVENTHANDLER_INVOKE(process_dtor, p); if (p->p_ksi != NULL) KASSERT(! KSI_ONQ(p->p_ksi), ("SIGCHLD queue")); - SDT_PROBE3(proc, kernel, dtor, return, p, size, arg); } /* @@ -224,7 +208,6 @@ proc_init(void *mem, int size, int flags) struct proc *p; p = (struct proc *)mem; - SDT_PROBE3(proc, kernel, init, entry, p, size, flags); p->p_sched = (struct p_sched *)&p[1]; mtx_init(&p->p_mtx, "process lock", NULL, MTX_DEF | MTX_DUPOK | MTX_NEW); mtx_init(&p->p_slock, "process slock", NULL, MTX_SPIN | MTX_NEW); @@ -236,7 +219,6 @@ proc_init(void *mem, int size, int flags) TAILQ_INIT(&p->p_threads); /* all threads in proc */ EVENTHANDLER_INVOKE(process_init, p); p->p_stats = pstats_alloc(); - SDT_PROBE3(proc, kernel, init, return, p, size, flags); return (0); } diff --git a/sys/kern/kern_racct.c b/sys/kern/kern_racct.c index d32b432..3777f50 100644 --- a/sys/kern/kern_racct.c +++ b/sys/kern/kern_racct.c @@ -102,30 +102,32 @@ static void racct_add_cred_locked(struct ucred *cred, int resource, uint64_t amount); SDT_PROVIDER_DEFINE(racct); -SDT_PROBE_DEFINE3(racct, kernel, rusage, add, "struct proc *", "int", - "uint64_t"); -SDT_PROBE_DEFINE3(racct, kernel, rusage, add__failure, +SDT_PROBE_DEFINE3(racct, , rusage, add, "struct proc *", "int", "uint64_t"); -SDT_PROBE_DEFINE3(racct, kernel, rusage, add__cred, "struct ucred *", - "int", "uint64_t"); -SDT_PROBE_DEFINE3(racct, kernel, rusage, add__force, "struct proc *", - "int", "uint64_t"); -SDT_PROBE_DEFINE3(racct, kernel, rusage, set, "struct proc *", "int", - "uint64_t"); -SDT_PROBE_DEFINE3(racct, kernel, rusage, set__failure, +SDT_PROBE_DEFINE3(racct, , rusage, add__failure, "struct proc *", "int", "uint64_t"); -SDT_PROBE_DEFINE3(racct, kernel, rusage, sub, "struct proc *", "int", - "uint64_t"); -SDT_PROBE_DEFINE3(racct, kernel, rusage, sub__cred, "struct ucred *", - "int", "uint64_t"); -SDT_PROBE_DEFINE1(racct, kernel, racct, create, "struct racct *"); -SDT_PROBE_DEFINE1(racct, kernel, racct, destroy, "struct racct *"); -SDT_PROBE_DEFINE2(racct, kernel, racct, join, "struct racct *", +SDT_PROBE_DEFINE3(racct, , rusage, add__cred, + "struct ucred *", "int", "uint64_t"); +SDT_PROBE_DEFINE3(racct, , rusage, add__force, + "struct proc *", "int", "uint64_t"); +SDT_PROBE_DEFINE3(racct, , rusage, set, + "struct proc *", "int", "uint64_t"); +SDT_PROBE_DEFINE3(racct, , rusage, set__failure, + "struct proc *", "int", "uint64_t"); +SDT_PROBE_DEFINE3(racct, , rusage, sub, + "struct proc *", "int", "uint64_t"); +SDT_PROBE_DEFINE3(racct, , rusage, sub__cred, + "struct ucred *", "int", "uint64_t"); +SDT_PROBE_DEFINE1(racct, , racct, create, "struct racct *"); -SDT_PROBE_DEFINE2(racct, kernel, racct, join__failure, - "struct racct *", "struct racct *"); -SDT_PROBE_DEFINE2(racct, kernel, racct, leave, "struct racct *", +SDT_PROBE_DEFINE1(racct, , racct, destroy, "struct racct *"); +SDT_PROBE_DEFINE2(racct, , racct, join, + "struct racct *", "struct racct *"); +SDT_PROBE_DEFINE2(racct, , racct, join__failure, + "struct racct *", "struct racct *"); +SDT_PROBE_DEFINE2(racct, , racct, leave, + "struct racct *", "struct racct *"); int racct_types[] = { [RACCT_CPU] = @@ -445,7 +447,7 @@ racct_create(struct racct **racctp) if (!racct_enable) return; - SDT_PROBE1(racct, kernel, racct, create, racctp); + SDT_PROBE1(racct, , racct, create, racctp); KASSERT(*racctp == NULL, ("racct already allocated")); @@ -460,7 +462,7 @@ racct_destroy_locked(struct racct **racctp) ASSERT_RACCT_ENABLED(); - SDT_PROBE1(racct, kernel, racct, destroy, racctp); + SDT_PROBE1(racct, , racct, destroy, racctp); mtx_assert(&racct_lock, MA_OWNED); KASSERT(racctp != NULL, ("NULL racctp")); @@ -538,7 +540,7 @@ racct_add_locked(struct proc *p, int resource, uint64_t amount) ASSERT_RACCT_ENABLED(); - SDT_PROBE3(racct, kernel, rusage, add, p, resource, amount); + SDT_PROBE3(racct, , rusage, add, p, resource, amount); /* * We need proc lock to dereference p->p_ucred. @@ -548,8 +550,7 @@ racct_add_locked(struct proc *p, int resource, uint64_t amount) #ifdef RCTL error = rctl_enforce(p, resource, amount); if (error && RACCT_IS_DENIABLE(resource)) { - SDT_PROBE3(racct, kernel, rusage, add__failure, p, resource, - amount); + SDT_PROBE3(racct, , rusage, add__failure, p, resource, amount); return (error); } #endif @@ -584,7 +585,7 @@ racct_add_cred_locked(struct ucred *cred, int resource, uint64_t amount) ASSERT_RACCT_ENABLED(); - SDT_PROBE3(racct, kernel, rusage, add__cred, cred, resource, amount); + SDT_PROBE3(racct, , rusage, add__cred, cred, resource, amount); racct_adjust_resource(cred->cr_ruidinfo->ui_racct, resource, amount); for (pr = cred->cr_prison; pr != NULL; pr = pr->pr_parent) @@ -622,7 +623,7 @@ racct_add_force(struct proc *p, int resource, uint64_t amount) if (!racct_enable) return; - SDT_PROBE3(racct, kernel, rusage, add__force, p, resource, amount); + SDT_PROBE3(racct, , rusage, add__force, p, resource, amount); /* * We need proc lock to dereference p->p_ucred. @@ -646,7 +647,7 @@ racct_set_locked(struct proc *p, int resource, uint64_t amount) ASSERT_RACCT_ENABLED(); - SDT_PROBE3(racct, kernel, rusage, set, p, resource, amount); + SDT_PROBE3(racct, , rusage, set, p, resource, amount); /* * We need proc lock to dereference p->p_ucred. @@ -678,8 +679,8 @@ racct_set_locked(struct proc *p, int resource, uint64_t amount) if (diff_proc > 0) { error = rctl_enforce(p, resource, diff_proc); if (error && RACCT_IS_DENIABLE(resource)) { - SDT_PROBE3(racct, kernel, rusage, set__failure, p, - resource, amount); + SDT_PROBE3(racct, , rusage, set__failure, p, resource, + amount); return (error); } } @@ -722,7 +723,7 @@ racct_set_force_locked(struct proc *p, int resource, uint64_t amount) ASSERT_RACCT_ENABLED(); - SDT_PROBE3(racct, kernel, rusage, set, p, resource, amount); + SDT_PROBE3(racct, , rusage, set, p, resource, amount); /* * We need proc lock to dereference p->p_ucred. @@ -833,7 +834,7 @@ racct_sub(struct proc *p, int resource, uint64_t amount) if (!racct_enable) return; - SDT_PROBE3(racct, kernel, rusage, sub, p, resource, amount); + SDT_PROBE3(racct, , rusage, sub, p, resource, amount); /* * We need proc lock to dereference p->p_ucred. @@ -860,7 +861,7 @@ racct_sub_cred_locked(struct ucred *cred, int resource, uint64_t amount) ASSERT_RACCT_ENABLED(); - SDT_PROBE3(racct, kernel, rusage, sub__cred, cred, resource, amount); + SDT_PROBE3(racct, , rusage, sub__cred, cred, resource, amount); #ifdef notyet KASSERT(RACCT_CAN_DROP(resource), diff --git a/sys/kern/kern_sdt.c b/sys/kern/kern_sdt.c index 5191a88..b9b2f43 100644 --- a/sys/kern/kern_sdt.c +++ b/sys/kern/kern_sdt.c @@ -1,5 +1,6 @@ /*- * Copyright 2006-2008 John Birrell + * Copyright 2015 Mark Johnston * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -21,33 +22,129 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - * - * $FreeBSD$ */ +#include +__FBSDID("$FreeBSD$"); + #include #include -#include + +#include +#include +#include +#include +#include #include +#include + SDT_PROVIDER_DEFINE(sdt); +static MALLOC_DEFINE(M_SDT, "sdt", "statically-defined tracing"); + +static eventhandler_tag sdt_kld_unload_try_tag; + +static void +sdt_kld_unload_try(void *arg __unused, linker_file_t lf, int *error) +{ + struct sdt_probe **probe, **start, **end; + struct sdt_probedesc *desc; + + if (*error != 0) + return; + if (linker_file_lookup_set(lf, "sdt_probes_set", &start, &end, + NULL) != 0) + return; + + for (probe = start; probe < end; probe++) { + while ((desc = SLIST_FIRST(&(*probe)->site_list)) != NULL) { + SLIST_REMOVE_HEAD(&(*probe)->site_list, li.spd_entry); + free(*probe, M_SDT); + } + } +} + +static void +sdt_patch_callsite(struct sdt_probe *probe, struct sdt_probedesc *desc, + uint64_t offset) +{ + + offset = sdt_md_patch_callsite(probe, offset, desc == NULL); + if (offset == 0) + return; + + /* + * The probe site is patched; now we can associate the site with + * the probe itself. Descriptors allocated here are freed in the + * kld_unload event handler. + */ + if (desc == NULL) + desc = malloc(sizeof(*desc), M_SDT, M_WAITOK); + desc->spd_offset = offset; + SLIST_INSERT_HEAD(&probe->site_list, desc, li.spd_entry); +} + /* - * Hook for the DTrace probe function. The SDT provider will set this to - * dtrace_probe() when it loads. + * Use the SDT probe sites specified in the probe site linker set to overwrite + * each probe site with NOPs. At the moment, only the kernel will contain such a + * set - probe sites in KLDs are patched when the load-time linker sees a + * relocation against a symbol with a prefix of "__dtrace_sdt_". */ -sdt_probe_func_t sdt_probe_func = sdt_probe_stub; +static int +sdt_patch_linker_file(linker_file_t lf, void *arg __unused) +{ + struct sdt_probedesc *desc, *start, *end; + struct sdt_probe *probe; + + if (linker_file_lookup_set(lf, "sdt_probe_site_set", &start, &end, + NULL) != 0) + return (0); + + /* + * Linker set iteration here deviates from the normal pattern because + * this linker set is special: it contains the probe descriptor structs + * themselves rather than pointers. + */ + for (desc = start; desc < end; desc++) { + probe = desc->li.spd_probe; + sdt_patch_callsite(probe, desc, desc->spd_offset + + (uintptr_t)btext); + } + return (0); +} /* - * This is a stub for probe calls in case kernel DTrace support isn't - * enabled. It should never get called because there is no DTrace support - * to enable it. + * Patch the kernel's probe sites. */ +static void +sdt_patch_kernel(void *arg __unused) +{ + + linker_file_foreach(sdt_patch_linker_file, NULL); + sdt_kld_unload_try_tag = EVENTHANDLER_REGISTER(kld_unload_try, + sdt_kld_unload_try, NULL, EVENTHANDLER_PRI_ANY); +} +SYSINIT(sdt_hotpatch, SI_SUB_KDTRACE, SI_ORDER_FIRST, sdt_patch_kernel, NULL); + void -sdt_probe_stub(uint32_t id, uintptr_t arg0, uintptr_t arg1, - uintptr_t arg2, uintptr_t arg3, uintptr_t arg4) +sdt_patch_reloc(linker_file_t lf, const char *symname, uint64_t base, + uint64_t offset) { + struct sdt_probe *probe; + caddr_t sym; + + KASSERT(strncmp(symname, SDT_PROBE_STUB_PREFIX, + sizeof(SDT_PROBE_STUB_PREFIX) - 1) == 0, + ("invalid reloc sym %s", symname)); + + symname += sizeof("__dtrace_") - 1; /* XXX */ + sym = linker_file_lookup_symbol(lf, symname, 0); + if (sym == 0) { + printf("sdt: couldn't find symbol %s\n", symname); + return; + } - printf("sdt_probe_stub: unexpectedly called\n"); - kdb_backtrace(); + probe = (struct sdt_probe *)sym; + sdt_patch_callsite(probe, NULL, base + offset); } diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c index 767eff0..510b920 100644 --- a/sys/kern/kern_sig.c +++ b/sys/kern/kern_sig.c @@ -94,11 +94,11 @@ __FBSDID("$FreeBSD$"); #define ONSIG 32 /* NSIG for osig* syscalls. XXX. */ SDT_PROVIDER_DECLARE(proc); -SDT_PROBE_DEFINE3(proc, kernel, , signal__send, "struct thread *", - "struct proc *", "int"); -SDT_PROBE_DEFINE2(proc, kernel, , signal__clear, "int", - "ksiginfo_t *"); -SDT_PROBE_DEFINE3(proc, kernel, , signal__discard, +SDT_PROBE_DEFINE3(proc, , , signal__send, + "struct thread *", "struct proc *", "int"); +SDT_PROBE_DEFINE2(proc, , , signal__clear, + "int", "ksiginfo_t *"); +SDT_PROBE_DEFINE3(proc, , , signal__discard, "struct thread *", "struct proc *", "int"); static int coredump(struct thread *); @@ -1308,7 +1308,7 @@ kern_sigtimedwait(struct thread *td, sigset_t waitset, ksiginfo_t *ksi, reschedule_signals(p, new_block, 0); if (error == 0) { - SDT_PROBE2(proc, kernel, , signal__clear, sig, ksi); + SDT_PROBE2(proc, , , signal__clear, sig, ksi); if (ksi->ksi_code == SI_TIMER) itimer_accept(p, ksi->ksi_timerid, ksi); @@ -2121,7 +2121,7 @@ tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi) } else sigqueue = &td->td_sigqueue; - SDT_PROBE3(proc, kernel, , signal__send, td, p, sig); + SDT_PROBE3(proc, , , signal__send, td, p, sig); /* * If the signal is being ignored, @@ -2132,7 +2132,7 @@ tdsendsignal(struct proc *p, struct thread *td, int sig, ksiginfo_t *ksi) */ mtx_lock(&ps->ps_mtx); if (SIGISMEMBER(ps->ps_sigignore, sig)) { - SDT_PROBE3(proc, kernel, , signal__discard, td, p, sig); + SDT_PROBE3(proc, , , signal__discard, td, p, sig); mtx_unlock(&ps->ps_mtx); if (ksi && (ksi->ksi_flags & KSI_INS)) diff --git a/sys/kern/kern_timeout.c b/sys/kern/kern_timeout.c index 01cf176..3c1b7e1 100644 --- a/sys/kern/kern_timeout.c +++ b/sys/kern/kern_timeout.c @@ -69,10 +69,8 @@ DPCPU_DECLARE(sbintime_t, hardclocktime); #endif SDT_PROVIDER_DEFINE(callout_execute); -SDT_PROBE_DEFINE1(callout_execute, kernel, , callout__start, - "struct callout *"); -SDT_PROBE_DEFINE1(callout_execute, kernel, , callout__end, - "struct callout *"); +SDT_PROBE_DEFINE1(callout_execute, , , callout__start, "struct callout *"); +SDT_PROBE_DEFINE1(callout_execute, , , callout__end, "struct callout *"); #ifdef CALLOUT_PROFILING static int avg_depth; @@ -718,9 +716,9 @@ softclock_call_cc(struct callout *c, struct callout_cpu *cc, sbt1 = sbinuptime(); #endif THREAD_NO_SLEEPING(); - SDT_PROBE1(callout_execute, kernel, , callout__start, c); + SDT_PROBE1(callout_execute, , , callout__start, c); c_func(c_arg); - SDT_PROBE1(callout_execute, kernel, , callout__end, c); + SDT_PROBE1(callout_execute, , , callout__end, c); THREAD_SLEEPING_OK(); #if defined(DIAGNOSTIC) || defined(CALLOUT_PROFILING) sbt2 = sbinuptime(); diff --git a/sys/kern/link_elf.c b/sys/kern/link_elf.c index c931ae9..eae40b2 100644 --- a/sys/kern/link_elf.c +++ b/sys/kern/link_elf.c @@ -42,6 +42,9 @@ __FBSDID("$FreeBSD$"); #include #include #include +#ifdef KDTRACE_HOOKS +#include +#endif #include #include #include @@ -1007,9 +1010,6 @@ link_elf_load_file(linker_class_t cls, const char* filename, vn_lock(nd.ni_vp, LK_EXCLUSIVE | LK_RETRY); if (error != 0) goto out; - error = relocate_file(ef); - if (error != 0) - goto out; /* * Try and load the symbol table if it's present. (you can @@ -1078,6 +1078,10 @@ link_elf_load_file(linker_class_t cls, const char* filename, ef->ddbstrcnt = strcnt; ef->ddbstrtab = ef->strbase; + error = relocate_file(ef); + if (error != 0) + goto out; + nosyms: error = link_elf_link_common_finish(lf); if (error != 0) @@ -1191,6 +1195,25 @@ symbol_name(elf_file_t ef, Elf_Size r_info) return (NULL); } +#ifdef KDTRACE_HOOKS +/* + * Relocations against symbols whose names start with "__dtrace_sdt_" + * correspond to static DTrace probe sites and are handled specially. + */ +static int +sdt_taste_reloc(elf_file_t ef, const char *symname, Elf_Addr offset) +{ + + if (symname != NULL && strncmp(symname, SDT_PROBE_STUB_PREFIX, + sizeof(SDT_PROBE_STUB_PREFIX) - 1) == 0) { + sdt_patch_reloc(&ef->lf, symname, (uint64_t)ef->address, + offset); + return (1); + } + return (0); +} +#endif /* KDTRACE_HOOKS */ + static int relocate_file(elf_file_t ef) { @@ -1205,14 +1228,17 @@ relocate_file(elf_file_t ef) if (rel != NULL) { rellim = (const Elf_Rel *) ((const char *)ef->rel + ef->relsize); - while (rel < rellim) { + for (; rel < rellim; rel++) { if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rel, ELF_RELOC_REL, elf_lookup)) { symname = symbol_name(ef, rel->r_info); +#ifdef KDTRACE_HOOKS + if (sdt_taste_reloc(ef, symname, rel->r_offset)) + continue; +#endif printf("link_elf: symbol %s undefined\n", symname); return (ENOENT); } - rel++; } } @@ -1221,15 +1247,19 @@ relocate_file(elf_file_t ef) if (rela != NULL) { relalim = (const Elf_Rela *) ((const char *)ef->rela + ef->relasize); - while (rela < relalim) { + for (; rela < relalim; rela++) { if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rela, ELF_RELOC_RELA, elf_lookup)) { symname = symbol_name(ef, rela->r_info); +#ifdef KDTRACE_HOOKS + if (sdt_taste_reloc(ef, symname, + rela->r_offset)) + continue; +#endif printf("link_elf: symbol %s undefined\n", symname); return (ENOENT); } - rela++; } } @@ -1238,15 +1268,18 @@ relocate_file(elf_file_t ef) if (rel != NULL) { rellim = (const Elf_Rel *) ((const char *)ef->pltrel + ef->pltrelsize); - while (rel < rellim) { + for (; rel < rellim; rel++) { if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rel, ELF_RELOC_REL, elf_lookup)) { symname = symbol_name(ef, rel->r_info); +#ifdef KDTRACE_HOOKS + if (sdt_taste_reloc(ef, symname, rel->r_offset)) + continue; +#endif printf("link_elf: symbol %s undefined\n", symname); return (ENOENT); } - rel++; } } @@ -1255,15 +1288,19 @@ relocate_file(elf_file_t ef) if (rela != NULL) { relalim = (const Elf_Rela *) ((const char *)ef->pltrela + ef->pltrelasize); - while (rela < relalim) { + for (; rela < relalim; rela++) { if (elf_reloc(&ef->lf, (Elf_Addr)ef->address, rela, ELF_RELOC_RELA, elf_lookup)) { symname = symbol_name(ef, rela->r_info); +#ifdef KDTRACE_HOOKS + if (sdt_taste_reloc(ef, symname, + rela->r_offset)) + continue; +#endif printf("link_elf: symbol %s undefined\n", symname); return (ENOENT); } - rela++; } } @@ -1594,6 +1631,10 @@ elf_lookup(linker_file_t lf, Elf_Size symidx, int deps, Elf_Addr *res) } addr = ((Elf_Addr)linker_file_lookup_symbol(lf, symbol, deps)); + if (addr == 0) { + *res = 0; + return (EINVAL); + } if (elf_set_find(&set_pcpu_list, addr, &start, &base)) addr = addr - start + base; diff --git a/sys/kern/link_elf_obj.c b/sys/kern/link_elf_obj.c index 00fe1e4..c7be201 100644 --- a/sys/kern/link_elf_obj.c +++ b/sys/kern/link_elf_obj.c @@ -32,16 +32,22 @@ __FBSDID("$FreeBSD$"); #include #include +#include #include #include #include +#include #include #include -#include #include -#include +#ifdef KDTRACE_HOOKS +#include +#endif +#include #include -#include +#ifdef DDB_CTF +#include +#endif #include @@ -59,10 +65,6 @@ __FBSDID("$FreeBSD$"); #include -#ifdef DDB_CTF -#include -#endif - #include "linker_if.h" typedef struct { @@ -1009,6 +1011,25 @@ findbase(elf_file_t ef, int sec) return base; } +#ifdef KDTRACE_HOOKS +/* + * Relocations against symbols whose names start with "__dtrace_sdt_" + * correspond to static DTrace probe sites and are handled specially. + */ +static int +sdt_taste_reloc(elf_file_t ef, const char *symname, Elf_Addr offset, + Elf_Addr base) +{ + + if (symname != NULL && strncmp(symname, SDT_PROBE_STUB_PREFIX, + sizeof(SDT_PROBE_STUB_PREFIX) - 1) == 0) { + sdt_patch_reloc(&ef->lf, symname, base, offset); + return (1); + } + return (0); +} +#endif /* KDTRACE_HOOKS */ + static int relocate_file(elf_file_t ef) { @@ -1022,7 +1043,6 @@ relocate_file(elf_file_t ef) Elf_Size symidx; Elf_Addr base; - /* Perform relocations without addend if there are any: */ for (i = 0; i < ef->nreltab; i++) { rel = ef->reltab[i].rel; @@ -1043,6 +1063,11 @@ relocate_file(elf_file_t ef) if (elf_reloc(&ef->lf, base, rel, ELF_RELOC_REL, elf_obj_lookup)) { symname = symbol_name(ef, rel->r_info); +#ifdef KDTRACE_HOOKS + if (sdt_taste_reloc(ef, symname, rel->r_offset, + base)) + continue; +#endif printf("link_elf_obj: symbol %s undefined\n", symname); return ENOENT; @@ -1070,6 +1095,11 @@ relocate_file(elf_file_t ef) if (elf_reloc(&ef->lf, base, rela, ELF_RELOC_RELA, elf_obj_lookup)) { symname = symbol_name(ef, rela->r_info); +#ifdef KDTRACE_HOOKS + if (sdt_taste_reloc(ef, symname, rela->r_offset, + base)) + continue; +#endif printf("link_elf_obj: symbol %s undefined\n", symname); return ENOENT; diff --git a/sys/kern/vfs_cache.c b/sys/kern/vfs_cache.c index ca9f054..ff3736d 100644 --- a/sys/kern/vfs_cache.c +++ b/sys/kern/vfs_cache.c @@ -417,7 +417,6 @@ cache_zap(ncp) rw_assert(&cache_lock, RA_WLOCKED); CTR2(KTR_VFS, "cache_zap(%p) vp %p", ncp, ncp->nc_vp); -#ifdef KDTRACE_HOOKS if (ncp->nc_vp != NULL) { SDT_PROBE3(vfs, namecache, zap, done, ncp->nc_dvp, nc_get_name(ncp), ncp->nc_vp); @@ -425,7 +424,6 @@ cache_zap(ncp) SDT_PROBE2(vfs, namecache, zap_negative, done, ncp->nc_dvp, nc_get_name(ncp)); } -#endif vp = NULL; LIST_REMOVE(ncp, nc_hash); if (ncp->nc_flag & NCF_ISDOTDOT) { diff --git a/sys/modules/cryptodev/Makefile b/sys/modules/cryptodev/Makefile index cc5ca12..a82517d 100644 --- a/sys/modules/cryptodev/Makefile +++ b/sys/modules/cryptodev/Makefile @@ -3,6 +3,6 @@ .PATH: ${.CURDIR}/../../opencrypto KMOD = cryptodev SRCS = cryptodev.c -SRCS += bus_if.h device_if.h opt_compat.h opt_kdtrace.h +SRCS += bus_if.h device_if.h opt_compat.h .include diff --git a/sys/modules/dtrace/sdt/Makefile b/sys/modules/dtrace/sdt/Makefile index b77299d..0a57186 100644 --- a/sys/modules/dtrace/sdt/Makefile +++ b/sys/modules/dtrace/sdt/Makefile @@ -5,10 +5,17 @@ SYSDIR?= ${.CURDIR}/../../.. .PATH: ${SYSDIR}/cddl/dev/sdt KMOD= sdt -SRCS= sdt.c +SRCS= sdt.c sdt_isa.c SRCS+= vnode_if.h -CFLAGS+= -I${SYSDIR}/cddl/compat/opensolaris \ +.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" +.PATH: ${SYSDIR}/cddl/dev/sdt/x86 +.else +.PATH: ${SYSDIR}/cddl/dev/sdt/${MACHINE_CPUARCH} +.endif + +CFLAGS+= -I${SYSDIR}/cddl/dev/sdt \ + -I${SYSDIR}/cddl/compat/opensolaris \ -I${SYSDIR}/cddl/contrib/opensolaris/uts/common \ -I${SYSDIR} diff --git a/sys/modules/linux64/Makefile b/sys/modules/linux64/Makefile index 1656323..3ee9985 100644 --- a/sys/modules/linux64/Makefile +++ b/sys/modules/linux64/Makefile @@ -10,7 +10,7 @@ SRCS= linux_fork.c linux_dummy.c linux_file.c linux_event.c \ linux_machdep.c linux_misc.c linux_signal.c \ linux_socket.c linux_stats.c linux_sysctl.c linux_sysent.c \ linux_sysvec.c linux_time.c linux_vdso.c linux_timer.c \ - opt_inet6.h opt_compat.h opt_kdtrace.h opt_posix.h opt_usb.h \ + opt_inet6.h opt_compat.h opt_posix.h opt_usb.h \ vnode_if.h device_if.h bus_if.h assym.s \ linux_support.s DPSRCS= linux_genassym.c diff --git a/sys/netinet/in_kdtrace.c b/sys/netinet/in_kdtrace.c index f39f0e8..0efe403 100644 --- a/sys/netinet/in_kdtrace.c +++ b/sys/netinet/in_kdtrace.c @@ -122,7 +122,7 @@ SDT_PROBE_DEFINE2_XLATE(tcp, , , debug__user, SDT_PROBE_DEFINE3_XLATE(tcp, , , debug__drop, "struct tcpcb *", "tcpsinfo_t *" , "struct tcphdr *", "tcpinfo_t *", - "uint8_t *", "ipinfo_t *") + "uint8_t *", "ipinfo_t *"); SDT_PROBE_DEFINE6_XLATE(tcp, , , state__change, "void *", "void *", diff --git a/sys/netinet/sctp_cc_functions.c b/sys/netinet/sctp_cc_functions.c index d616d19..0bddcfd 100644 --- a/sys/netinet/sctp_cc_functions.c +++ b/sys/netinet/sctp_cc_functions.c @@ -95,7 +95,7 @@ sctp_set_initial_cc_param(struct sctp_tcb *stcb, struct sctp_nets *net) } sctp_enforce_cwnd_limit(assoc, net); net->ssthresh = assoc->peers_rwnd; - SDT_PROBE(sctp, cwnd, net, init, + SDT_PROBE5(sctp, cwnd, net, init, stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net, 0, net->cwnd); if (SCTP_BASE_SYSCTL(sctp_logging_level) & @@ -193,7 +193,7 @@ sctp_cwnd_update_after_fr(struct sctp_tcb *stcb, } net->cwnd = net->ssthresh; sctp_enforce_cwnd_limit(asoc, net); - SDT_PROBE(sctp, cwnd, net, fr, + SDT_PROBE5(sctp, cwnd, net, fr, stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net, old_cwnd, net->cwnd); if (SCTP_BASE_SYSCTL(sctp_logging_level) & SCTP_CWND_MONITOR_ENABLE) { @@ -261,7 +261,7 @@ cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, */ /* Probe point 5 */ probepoint |= ((5 << 16) | 1); - SDT_PROBE(sctp, cwnd, net, rttvar, + SDT_PROBE5(sctp, cwnd, net, rttvar, vtag, ((net->cc_mod.rtcc.lbw << 32) | nbw), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -282,7 +282,7 @@ cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, oth |= net->cc_mod.rtcc.step_cnt; oth <<= 16; oth |= net->cc_mod.rtcc.last_step_state; - SDT_PROBE(sctp, cwnd, net, rttstep, + SDT_PROBE5(sctp, cwnd, net, rttstep, vtag, ((net->cc_mod.rtcc.lbw << 32) | nbw), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -306,7 +306,7 @@ cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, */ /* Probe point 6 */ probepoint |= ((6 << 16) | 0); - SDT_PROBE(sctp, cwnd, net, rttvar, + SDT_PROBE5(sctp, cwnd, net, rttvar, vtag, ((net->cc_mod.rtcc.lbw << 32) | nbw), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -318,7 +318,7 @@ cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, oth |= net->cc_mod.rtcc.step_cnt; oth <<= 16; oth |= net->cc_mod.rtcc.last_step_state; - SDT_PROBE(sctp, cwnd, net, rttstep, + SDT_PROBE5(sctp, cwnd, net, rttstep, vtag, ((net->cc_mod.rtcc.lbw << 32) | nbw), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -349,7 +349,7 @@ cc_bw_same(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, */ /* Probe point 7 */ probepoint |= ((7 << 16) | net->cc_mod.rtcc.ret_from_eq); - SDT_PROBE(sctp, cwnd, net, rttvar, + SDT_PROBE5(sctp, cwnd, net, rttvar, vtag, ((net->cc_mod.rtcc.lbw << 32) | nbw), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -398,7 +398,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6 /* We caused it maybe.. back off? */ /* PROBE POINT 1 */ probepoint |= ((1 << 16) | 1); - SDT_PROBE(sctp, cwnd, net, rttvar, + SDT_PROBE5(sctp, cwnd, net, rttvar, vtag, ((net->cc_mod.rtcc.lbw << 32) | nbw), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -416,7 +416,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6 } /* Probe point 2 */ probepoint |= ((2 << 16) | 0); - SDT_PROBE(sctp, cwnd, net, rttvar, + SDT_PROBE5(sctp, cwnd, net, rttvar, vtag, ((net->cc_mod.rtcc.lbw << 32) | nbw), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -429,7 +429,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6 oth |= net->cc_mod.rtcc.step_cnt; oth <<= 16; oth |= net->cc_mod.rtcc.last_step_state; - SDT_PROBE(sctp, cwnd, net, rttstep, + SDT_PROBE5(sctp, cwnd, net, rttstep, vtag, ((net->cc_mod.rtcc.lbw << 32) | nbw), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -453,7 +453,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6 /* bw & rtt decreased */ /* Probe point 3 */ probepoint |= ((3 << 16) | 0); - SDT_PROBE(sctp, cwnd, net, rttvar, + SDT_PROBE5(sctp, cwnd, net, rttvar, vtag, ((net->cc_mod.rtcc.lbw << 32) | nbw), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -465,7 +465,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6 oth |= net->cc_mod.rtcc.step_cnt; oth <<= 16; oth |= net->cc_mod.rtcc.last_step_state; - SDT_PROBE(sctp, cwnd, net, rttstep, + SDT_PROBE5(sctp, cwnd, net, rttstep, vtag, ((net->cc_mod.rtcc.lbw << 32) | nbw), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -485,7 +485,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6 /* The bw decreased but rtt stayed the same */ /* Probe point 4 */ probepoint |= ((4 << 16) | 0); - SDT_PROBE(sctp, cwnd, net, rttvar, + SDT_PROBE5(sctp, cwnd, net, rttvar, vtag, ((net->cc_mod.rtcc.lbw << 32) | nbw), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -497,7 +497,7 @@ cc_bw_decrease(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6 oth |= net->cc_mod.rtcc.step_cnt; oth <<= 16; oth |= net->cc_mod.rtcc.last_step_state; - SDT_PROBE(sctp, cwnd, net, rttstep, + SDT_PROBE5(sctp, cwnd, net, rttstep, vtag, ((net->cc_mod.rtcc.lbw << 32) | nbw), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -535,7 +535,7 @@ cc_bw_increase(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6 */ /* PROBE POINT 0 */ probepoint = (((uint64_t) net->cwnd) << 32); - SDT_PROBE(sctp, cwnd, net, rttvar, + SDT_PROBE5(sctp, cwnd, net, rttvar, vtag, ((net->cc_mod.rtcc.lbw << 32) | nbw), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -547,7 +547,7 @@ cc_bw_increase(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw, uint6 oth |= net->cc_mod.rtcc.step_cnt; oth <<= 16; oth |= net->cc_mod.rtcc.last_step_state; - SDT_PROBE(sctp, cwnd, net, rttstep, + SDT_PROBE5(sctp, cwnd, net, rttstep, vtag, ((net->cc_mod.rtcc.lbw << 32) | nbw), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -647,7 +647,7 @@ cc_bw_limit(struct sctp_tcb *stcb, struct sctp_nets *net, uint64_t nbw) /* Can't determine do not change */ probepoint |= ((0xd << 16) | inst_ind); } - SDT_PROBE(sctp, cwnd, net, rttvar, + SDT_PROBE5(sctp, cwnd, net, rttvar, vtag, ((nbw << 32) | inst_bw), ((net->cc_mod.rtcc.lbw_rtt << 32) | rtt), @@ -807,7 +807,7 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb, (((uint32_t) (stcb->sctp_ep->sctp_lport)) << 16) | (stcb->rport); - SDT_PROBE(sctp, cwnd, net, rttvar, + SDT_PROBE5(sctp, cwnd, net, rttvar, vtag, nbw, ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -906,7 +906,7 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb, sctp_log_cwnd(stcb, net, incr, SCTP_CWND_LOG_FROM_SS); } - SDT_PROBE(sctp, cwnd, net, ack, + SDT_PROBE5(sctp, cwnd, net, ack, stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net, @@ -969,7 +969,7 @@ sctp_cwnd_update_after_sack_common(struct sctp_tcb *stcb, } net->cwnd += incr; sctp_enforce_cwnd_limit(asoc, net); - SDT_PROBE(sctp, cwnd, net, ack, + SDT_PROBE5(sctp, cwnd, net, ack, stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net, @@ -1001,7 +1001,7 @@ sctp_cwnd_update_exit_pf_common(struct sctp_tcb *stcb, struct sctp_nets *net) old_cwnd = net->cwnd; net->cwnd = net->mtu; - SDT_PROBE(sctp, cwnd, net, ack, + SDT_PROBE5(sctp, cwnd, net, ack, stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net, old_cwnd, net->cwnd); SCTPDBG(SCTP_DEBUG_INDATA1, "Destination %p moved from PF to reachable with cwnd %d.\n", @@ -1072,7 +1072,7 @@ sctp_cwnd_update_after_timeout(struct sctp_tcb *stcb, struct sctp_nets *net) } net->cwnd = net->mtu; net->partial_bytes_acked = 0; - SDT_PROBE(sctp, cwnd, net, to, + SDT_PROBE5(sctp, cwnd, net, to, stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net, @@ -1132,7 +1132,7 @@ sctp_cwnd_update_after_ecn_echo_common(struct sctp_tcb *stcb, struct sctp_nets * net->RTO <<= 1; } net->cwnd = net->ssthresh; - SDT_PROBE(sctp, cwnd, net, ecn, + SDT_PROBE5(sctp, cwnd, net, ecn, stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net, @@ -1251,7 +1251,7 @@ sctp_cwnd_update_after_packet_dropped(struct sctp_tcb *stcb, sctp_enforce_cwnd_limit(&stcb->asoc, net); if (net->cwnd - old_cwnd != 0) { /* log only changes */ - SDT_PROBE(sctp, cwnd, net, pd, + SDT_PROBE5(sctp, cwnd, net, pd, stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net, @@ -1274,7 +1274,7 @@ sctp_cwnd_update_after_output(struct sctp_tcb *stcb, if (burst_limit) { net->cwnd = (net->flight_size + (burst_limit * net->mtu)); sctp_enforce_cwnd_limit(&stcb->asoc, net); - SDT_PROBE(sctp, cwnd, net, bl, + SDT_PROBE5(sctp, cwnd, net, bl, stcb->asoc.my_vtag, ((stcb->sctp_ep->sctp_lport << 16) | (stcb->rport)), net, @@ -1350,7 +1350,7 @@ sctp_cwnd_new_rtcc_transmission_begins(struct sctp_tcb *stcb, probepoint = (((uint64_t) net->cwnd) << 32); /* Probe point 8 */ probepoint |= ((8 << 16) | 0); - SDT_PROBE(sctp, cwnd, net, rttvar, + SDT_PROBE5(sctp, cwnd, net, rttvar, vtag, ((net->cc_mod.rtcc.lbw << 32) | 0), ((net->cc_mod.rtcc.lbw_rtt << 32) | net->rtt), @@ -1413,7 +1413,7 @@ sctp_set_rtcc_initial_cc_param(struct sctp_tcb *stcb, vtag = (net->rtt << 32) | (((uint32_t) (stcb->sctp_ep->sctp_lport)) << 16) | (stcb->rport); - SDT_PROBE(sctp, cwnd, net, rttvar, + SDT_PROBE5(sctp, cwnd, net, rttvar, vtag, 0, 0, diff --git a/sys/opencrypto/cryptodev.c b/sys/opencrypto/cryptodev.c index 1401504..bda77c7 100644 --- a/sys/opencrypto/cryptodev.c +++ b/sys/opencrypto/cryptodev.c @@ -42,7 +42,6 @@ __FBSDID("$FreeBSD$"); #include "opt_compat.h" -#include "opt_kdtrace.h" #include #include diff --git a/sys/security/mac/mac_framework.c b/sys/security/mac/mac_framework.c index 0f0a2ff..d76b280 100644 --- a/sys/security/mac/mac_framework.c +++ b/sys/security/mac/mac_framework.c @@ -93,11 +93,11 @@ __FBSDID("$FreeBSD$"); SDT_PROVIDER_DEFINE(mac); SDT_PROVIDER_DEFINE(mac_framework); -SDT_PROBE_DEFINE2(mac, kernel, policy, modevent, "int", +SDT_PROBE_DEFINE2(mac, , policy, modevent, "int", "struct mac_policy_conf *"); -SDT_PROBE_DEFINE1(mac, kernel, policy, register, +SDT_PROBE_DEFINE1(mac, , policy, register, "struct mac_policy_conf *"); -SDT_PROBE_DEFINE1(mac, kernel, policy, unregister, +SDT_PROBE_DEFINE1(mac, , policy, unregister, "struct mac_policy_conf *"); /* @@ -444,7 +444,7 @@ mac_policy_register(struct mac_policy_conf *mpc) (*(mpc->mpc_ops->mpo_init))(mpc); mac_policy_update(); - SDT_PROBE(mac, kernel, policy, register, mpc, 0, 0, 0, 0); + SDT_PROBE1(mac, , policy, register, mpc); printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname, mpc->mpc_name); @@ -491,7 +491,7 @@ mac_policy_unregister(struct mac_policy_conf *mpc) mac_policy_update(); mac_policy_xunlock(); - SDT_PROBE(mac, kernel, policy, unregister, mpc, 0, 0, 0, 0); + SDT_PROBE1(mac, , policy, unregister, mpc); printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname, mpc->mpc_name); @@ -517,7 +517,7 @@ mac_policy_modevent(module_t mod, int type, void *data) } #endif - SDT_PROBE(mac, kernel, policy, modevent, type, mpc, 0, 0, 0); + SDT_PROBE2(mac, , policy, modevent, type, mpc); switch (type) { case MOD_LOAD: if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE && diff --git a/sys/security/mac/mac_internal.h b/sys/security/mac/mac_internal.h index ceb1e87..2ecffc6 100644 --- a/sys/security/mac/mac_internal.h +++ b/sys/security/mac/mac_internal.h @@ -74,35 +74,35 @@ SDT_PROVIDER_DECLARE(mac); /* MAC Framework-level events. */ SDT_PROVIDER_DECLARE(mac_framework); /* Entry points to MAC. */ #define MAC_CHECK_PROBE_DEFINE4(name, arg0, arg1, arg2, arg3) \ - SDT_PROBE_DEFINE5(mac_framework, kernel, name, mac__check__err, \ + SDT_PROBE_DEFINE5(mac_framework, , name, mac__check__err, \ "int", arg0, arg1, arg2, arg3); \ - SDT_PROBE_DEFINE5(mac_framework, kernel, name, mac__check__ok, \ + SDT_PROBE_DEFINE5(mac_framework, , name, mac__check__ok, \ "int", arg0, arg1, arg2, arg3); #define MAC_CHECK_PROBE_DEFINE3(name, arg0, arg1, arg2) \ - SDT_PROBE_DEFINE4(mac_framework, kernel, name, mac__check__err, \ + SDT_PROBE_DEFINE4(mac_framework, , name, mac__check__err, \ "int", arg0, arg1, arg2); \ - SDT_PROBE_DEFINE4(mac_framework, kernel, name, mac__check__ok, \ + SDT_PROBE_DEFINE4(mac_framework, , name, mac__check__ok, \ "int", arg0, arg1, arg2); #define MAC_CHECK_PROBE_DEFINE2(name, arg0, arg1) \ - SDT_PROBE_DEFINE3(mac_framework, kernel, name, mac__check__err, \ + SDT_PROBE_DEFINE3(mac_framework, , name, mac__check__err, \ "int", arg0, arg1); \ - SDT_PROBE_DEFINE3(mac_framework, kernel, name, mac__check__ok, \ + SDT_PROBE_DEFINE3(mac_framework, , name, mac__check__ok, \ "int", arg0, arg1); #define MAC_CHECK_PROBE_DEFINE1(name, arg0) \ - SDT_PROBE_DEFINE2(mac_framework, kernel, name, mac__check__err, \ + SDT_PROBE_DEFINE2(mac_framework, , name, mac__check__err, \ "int", arg0); \ - SDT_PROBE_DEFINE2(mac_framework, kernel, name, mac__check__ok, \ + SDT_PROBE_DEFINE2(mac_framework, , name, mac__check__ok, \ "int", arg0); #define MAC_CHECK_PROBE4(name, error, arg0, arg1, arg2, arg3) do { \ if (error) { \ - SDT_PROBE(mac_framework, kernel, name, mac__check__err, \ + SDT_PROBE5(mac_framework, , name, mac__check__err, \ error, arg0, arg1, arg2, arg3); \ } else { \ - SDT_PROBE(mac_framework, kernel, name, mac__check__ok, \ + SDT_PROBE5(mac_framework, , name, mac__check__ok, \ 0, arg0, arg1, arg2, arg3); \ } \ } while (0) @@ -116,18 +116,18 @@ SDT_PROVIDER_DECLARE(mac_framework); /* Entry points to MAC. */ #endif #define MAC_GRANT_PROBE_DEFINE2(name, arg0, arg1) \ - SDT_PROBE_DEFINE3(mac_framework, kernel, name, mac__grant__err, \ + SDT_PROBE_DEFINE3(mac_framework, , name, mac__grant__err, \ "int", arg0, arg1); \ - SDT_PROBE_DEFINE3(mac_framework, kernel, name, mac__grant__ok, \ + SDT_PROBE_DEFINE3(mac_framework, , name, mac__grant__ok, \ "int", arg0, arg1); #define MAC_GRANT_PROBE2(name, error, arg0, arg1) do { \ if (error) { \ - SDT_PROBE(mac_framework, kernel, name, mac__grant__err, \ - error, arg0, arg1, 0, 0); \ + SDT_PROBE3(mac_framework, , name, mac__grant__err, \ + error, arg0, arg1); \ } else { \ - SDT_PROBE(mac_framework, kernel, name, mac__grant__ok, \ - error, arg0, arg1, 0, 0); \ + SDT_PROBE3(mac_framework, , name, mac__grant__ok, \ + error, arg0, arg1); \ } \ } while (0) diff --git a/sys/sys/sdt.h b/sys/sys/sdt.h index 5dd0b67..e3d0a79 100644 --- a/sys/sys/sdt.h +++ b/sys/sys/sdt.h @@ -1,5 +1,6 @@ /*- * Copyright 2006-2008 John Birrell + * Copyright (c) 2015 Mark Johnston * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -23,232 +24,170 @@ * SUCH DAMAGE. * * $FreeBSD$ - * + */ + +/* * Statically Defined Tracing (SDT) definitions. * + * This file contains macros for defining DTrace SDT probes and probe sites. + * It also contains the macros used to create userland SDT probes (USDT). */ #ifndef _SYS_SDT_H #define _SYS_SDT_H -#ifndef _KERNEL +#ifdef _KERNEL -#define _DTRACE_VERSION 1 +#ifdef KDTRACE_HOOKS -#define DTRACE_PROBE(prov, name) { \ - extern void __dtrace_##prov##___##name(void); \ - __dtrace_##prov##___##name(); \ -} +#include +#include -#define DTRACE_PROBE1(prov, name, arg1) { \ - extern void __dtrace_##prov##___##name(unsigned long); \ - __dtrace_##prov##___##name((unsigned long)arg1); \ -} +/* + * Utility macros used further down in this file. + */ -#define DTRACE_PROBE2(prov, name, arg1, arg2) { \ - extern void __dtrace_##prov##___##name(unsigned long, \ - unsigned long); \ - __dtrace_##prov##___##name((unsigned long)arg1, \ - (unsigned long)arg2); \ -} +#define _SDT_PROBE_STUB_PREFIX __dtrace_sdt_ -#define DTRACE_PROBE3(prov, name, arg1, arg2, arg3) { \ - extern void __dtrace_##prov##___##name(unsigned long, \ - unsigned long, unsigned long); \ - __dtrace_##prov##___##name((unsigned long)arg1, \ - (unsigned long)arg2, (unsigned long)arg3); \ -} +#define SDT_PROBE_STUB_PREFIX __XSTRING(_SDT_PROBE_STUB_PREFIX) -#define DTRACE_PROBE4(prov, name, arg1, arg2, arg3, arg4) { \ - extern void __dtrace_##prov##___##name(unsigned long, \ - unsigned long, unsigned long, unsigned long); \ - __dtrace_##prov##___##name((unsigned long)arg1, \ - (unsigned long)arg2, (unsigned long)arg3, \ - (unsigned long)arg4); \ -} +#define _SDT_PROBE_STUB(prov, mod, func, name) \ + __dtrace_sdt_##prov##_##mod##_##func##_##name -#define DTRACE_PROBE5(prov, name, arg1, arg2, arg3, arg4, arg5) { \ - extern void __dtrace_##prov##___##name(unsigned long, \ - unsigned long, unsigned long, unsigned long, unsigned long);\ - __dtrace_##prov##___##name((unsigned long)arg1, \ - (unsigned long)arg2, (unsigned long)arg3, \ - (unsigned long)arg4, (unsigned long)arg5); \ -} - -#else /* _KERNEL */ - -#include -#include +#define _SDT_PROBE_NAME(prov, mod, func, name) \ + sdt_##prov##_##mod##_##func##_##name -#ifndef KDTRACE_HOOKS - -#define SDT_PROVIDER_DEFINE(prov) -#define SDT_PROVIDER_DECLARE(prov) -#define SDT_PROBE_DEFINE(prov, mod, func, name) -#define SDT_PROBE_DECLARE(prov, mod, func, name) -#define SDT_PROBE(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) -#define SDT_PROBE_ARGTYPE(prov, mod, func, name, num, type, xtype) +/* + * Macros for defining SDT probes and argument info. + */ -#define SDT_PROBE_DEFINE0(prov, mod, func, name) -#define SDT_PROBE_DEFINE1(prov, mod, func, name, arg0) -#define SDT_PROBE_DEFINE2(prov, mod, func, name, arg0, arg1) -#define SDT_PROBE_DEFINE3(prov, mod, func, name, arg0, arg1, arg2) -#define SDT_PROBE_DEFINE4(prov, mod, func, name, arg0, arg1, arg2, arg3) -#define SDT_PROBE_DEFINE5(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) -#define SDT_PROBE_DEFINE6(prov, mod, func, name, arg0, arg1, arg2, \ - arg3, arg4, arg5) -#define SDT_PROBE_DEFINE7(prov, mod, func, name, arg0, arg1, arg2, \ - arg3, arg4, arg5, arg6) +#define SDT_PROVIDER_DEFINE(prov) \ + struct sdt_provider sdt_provider_##prov[1] = { \ + { #prov, { NULL, NULL }, 0, 0 } \ + }; \ + DATA_SET(sdt_providers_set, sdt_provider_##prov); -#define SDT_PROBE0(prov, mod, func, name) -#define SDT_PROBE1(prov, mod, func, name, arg0) -#define SDT_PROBE2(prov, mod, func, name, arg0, arg1) -#define SDT_PROBE3(prov, mod, func, name, arg0, arg1, arg2) -#define SDT_PROBE4(prov, mod, func, name, arg0, arg1, arg2, arg3) -#define SDT_PROBE5(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) -#define SDT_PROBE6(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4, arg5) -#define SDT_PROBE7(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4, arg5, \ - arg6) +#define SDT_PROVIDER_DECLARE(prov) \ + extern struct sdt_provider sdt_provider_##prov[1] -#define SDT_PROBE_DEFINE0_XLATE(prov, mod, func, name) -#define SDT_PROBE_DEFINE1_XLATE(prov, mod, func, name, arg0, xarg0) -#define SDT_PROBE_DEFINE2_XLATE(prov, mod, func, name, arg0, xarg0, \ - arg1, xarg1) -#define SDT_PROBE_DEFINE3_XLATE(prov, mod, func, name, arg0, xarg0, \ - arg1, xarg1, arg2, xarg2) -#define SDT_PROBE_DEFINE4_XLATE(prov, mod, func, name, arg0, xarg0, \ - arg1, xarg1, arg2, xarg2, arg3, xarg3) -#define SDT_PROBE_DEFINE5_XLATE(prov, mod, func, name, arg0, xarg0, \ - arg1, xarg1, arg2, xarg2, arg3, xarg3, arg4, xarg4) -#define SDT_PROBE_DEFINE6_XLATE(prov, mod, func, name, arg0, xarg0, \ - arg1, xarg1, arg2, xarg2, arg3, xarg3, arg4, xarg4, arg5, xarg5) -#define SDT_PROBE_DEFINE7_XLATE(prov, mod, func, name, arg0, xarg0, \ - arg1, xarg1, arg2, xarg2, arg3, xarg3, arg4, xarg4, arg5, xarg5, arg6, \ - xarg6) +#define SDT_PROBE_DEFINE(prov, mod, func, name) \ + struct sdt_probe _SDT_PROBE_NAME(prov, mod, func, name)[1] = { \ + { sizeof(struct sdt_probe), sdt_provider_##prov, \ + { NULL, NULL }, { NULL }, { NULL, NULL }, \ + #mod, #func, #name, 0, NULL } \ + }; \ + DATA_SET(sdt_probes_set, _SDT_PROBE_NAME(prov, mod, func, name)) -#define DTRACE_PROBE(name) -#define DTRACE_PROBE1(name, type0, arg0) -#define DTRACE_PROBE2(name, type0, arg0, type1, arg1) -#define DTRACE_PROBE3(name, type0, arg0, type1, arg1, type2, arg2) -#define DTRACE_PROBE4(name, type0, arg0, type1, arg1, type2, arg2, type3, arg3) -#define DTRACE_PROBE5(name, type0, arg0, type1, arg1, type2, arg2, type3, arg3,\ - type4, arg4) +#define SDT_PROBE_DECLARE(prov, mod, func, name) \ + extern struct sdt_probe _SDT_PROBE_NAME(prov, mod, func, name)[1] -#else +#define SDT_PROBE_ARGTYPE(prov, mod, func, name, num, type, xtype) \ + static struct sdt_argtype sdta_##prov##_##mod##_##func##_##name##num[1] \ + = { { num, type, xtype, { NULL, NULL }, \ + _SDT_PROBE_NAME(prov, mod, func, name) } \ + }; \ + DATA_SET(sdt_argtypes_set, sdta_##prov##_##mod##_##func##_##name##num) SET_DECLARE(sdt_providers_set, struct sdt_provider); SET_DECLARE(sdt_probes_set, struct sdt_probe); SET_DECLARE(sdt_argtypes_set, struct sdt_argtype); -#define SDT_PROVIDER_DEFINE(prov) \ - struct sdt_provider sdt_provider_##prov[1] = { \ - { #prov, { NULL, NULL }, 0, 0 } \ - }; \ - DATA_SET(sdt_providers_set, sdt_provider_##prov); - -#define SDT_PROVIDER_DECLARE(prov) \ - extern struct sdt_provider sdt_provider_##prov[1] - -#define SDT_PROBE_DEFINE(prov, mod, func, name) \ - struct sdt_probe sdt_##prov##_##mod##_##func##_##name[1] = { \ - { sizeof(struct sdt_probe), sdt_provider_##prov, \ - { NULL, NULL }, { NULL, NULL }, #mod, #func, #name, 0, 0, \ - NULL } \ - }; \ - DATA_SET(sdt_probes_set, sdt_##prov##_##mod##_##func##_##name); - -#define SDT_PROBE_DECLARE(prov, mod, func, name) \ - extern struct sdt_probe sdt_##prov##_##mod##_##func##_##name[1] - -#define SDT_PROBE(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) do { \ - if (sdt_##prov##_##mod##_##func##_##name->id) \ - (*sdt_probe_func)(sdt_##prov##_##mod##_##func##_##name->id, \ - (uintptr_t) arg0, (uintptr_t) arg1, (uintptr_t) arg2, \ - (uintptr_t) arg3, (uintptr_t) arg4); \ -} while (0) - -#define SDT_PROBE_ARGTYPE(prov, mod, func, name, num, type, xtype) \ - static struct sdt_argtype sdta_##prov##_##mod##_##func##_##name##num[1] \ - = { { num, type, xtype, { NULL, NULL }, \ - sdt_##prov##_##mod##_##func##_##name } \ - }; \ - DATA_SET(sdt_argtypes_set, sdta_##prov##_##mod##_##func##_##name##num); - #define SDT_PROBE_DEFINE0(prov, mod, func, name) \ SDT_PROBE_DEFINE(prov, mod, func, name) +#define _SDT_PROBE_DEFINE0(prov, mod, func, name) \ + SDT_PROBE_DEFINE0(prov, mod, func, name) -#define SDT_PROBE_DEFINE1(prov, mod, func, name, arg0) \ +#define SDT_PROBE_DEFINE1(prov, mod, func, name, t0) \ SDT_PROBE_DEFINE(prov, mod, func, name); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, NULL) + SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, t0, NULL) +#define _SDT_PROBE_DEFINE1(prov, mod, func, name, t0) \ + SDT_PROBE_DEFINE1(prov, mod, func, name, #t0) -#define SDT_PROBE_DEFINE2(prov, mod, func, name, arg0, arg1) \ +#define SDT_PROBE_DEFINE2(prov, mod, func, name, t0, t1) \ SDT_PROBE_DEFINE(prov, mod, func, name); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1, NULL) + SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, t0, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, t1, NULL) +#define _SDT_PROBE_DEFINE2(prov, mod, func, name, t0, t1) \ + SDT_PROBE_DEFINE2(prov, mod, func, name, #t0, #t1) -#define SDT_PROBE_DEFINE3(prov, mod, func, name, arg0, arg1, arg2)\ +#define SDT_PROBE_DEFINE3(prov, mod, func, name, t0, t1, t2) \ SDT_PROBE_DEFINE(prov, mod, func, name); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, arg2, NULL) + SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, t0, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, t1, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, t2, NULL) +#define _SDT_PROBE_DEFINE3(prov, mod, func, name, t0, t1, t2) \ + SDT_PROBE_DEFINE3(prov, mod, func, name, #t0, #t1, #t2) -#define SDT_PROBE_DEFINE4(prov, mod, func, name, arg0, arg1, arg2, arg3) \ +#define SDT_PROBE_DEFINE4(prov, mod, func, name, t0, t1, t2, t3) \ SDT_PROBE_DEFINE(prov, mod, func, name); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, arg2, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 3, arg3, NULL) - -#define SDT_PROBE_DEFINE5(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, t0, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, t1, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, t2, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 3, t3, NULL) +#define _SDT_PROBE_DEFINE4(prov, mod, func, name, t0, t1, t2, t3) \ + SDT_PROBE_DEFINE4(prov, mod, func, name, #t0, #t1, #t2, #t3) + +#define SDT_PROBE_DEFINE5(prov, mod, func, name, t0, t1, t2, t3, t4) \ SDT_PROBE_DEFINE(prov, mod, func, name); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, arg2, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 3, arg3, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 4, arg4, NULL) - -#define SDT_PROBE_DEFINE6(prov, mod, func, name, arg0, arg1, arg2, arg3,\ - arg4, arg5) \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, t0, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, t1, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, t2, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 3, t3, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 4, t4, NULL) +#define _SDT_PROBE_DEFINE5(prov, mod, func, name, t0, t1, t2, t3, t4) \ + SDT_PROBE_DEFINE5(prov, mod, func, name, #t0, #t1, #t2, #t3, \ + #t4) + +#define SDT_PROBE_DEFINE6(prov, mod, func, name, t0, t1, t2, t3, t4, \ + t5) \ SDT_PROBE_DEFINE(prov, mod, func, name); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, arg2, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 3, arg3, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 4, arg4, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 5, arg5, NULL) - -#define SDT_PROBE_DEFINE7(prov, mod, func, name, arg0, arg1, arg2, arg3,\ - arg4, arg5, arg6) \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, t0, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, t1, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, t2, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 3, t3, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 4, t4, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 5, t5, NULL) +#define _SDT_PROBE_DEFINE6(prov, mod, func, name, t0, t1, t2, t3, t4, \ + t5) \ + SDT_PROBE_DEFINE6(prov, mod, func, name, #t0, #t1, #t2, #t3, \ + #t4, #t5) + +#define SDT_PROBE_DEFINE7(prov, mod, func, name, t0, t1, t2, t3, t4, \ + t5, t6) \ SDT_PROBE_DEFINE(prov, mod, func, name); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, arg2, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 3, arg3, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 4, arg4, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 5, arg5, NULL); \ - SDT_PROBE_ARGTYPE(prov, mod, func, name, 6, arg6, NULL) - -#define SDT_PROBE_DEFINE0_XLATE(prov, mod, func, name) \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, t0, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, t1, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, t2, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 3, t3, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 4, t4, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 5, t5, NULL); \ + SDT_PROBE_ARGTYPE(prov, mod, func, name, 6, t6, NULL) +#define _SDT_PROBE_DEFINE7(prov, mod, func, name, t0, t1, t2, t3, t4, \ + t5, t6) \ + SDT_PROBE_DEFINE7(prov, mod, func, name, #t0, #t1, #t2, #t3, \ + #t4, #t5, #t6) + +#define SDT_PROBE_DEFINE0_XLATE(prov, mod, func, name) \ SDT_PROBE_DEFINE(prov, mod, func, name) -#define SDT_PROBE_DEFINE1_XLATE(prov, mod, func, name, arg0, xarg0) \ +#define SDT_PROBE_DEFINE1_XLATE(prov, mod, func, name, arg0, xarg0) \ SDT_PROBE_DEFINE(prov, mod, func, name); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, xarg0) -#define SDT_PROBE_DEFINE2_XLATE(prov, mod, func, name, arg0, xarg0, \ +#define SDT_PROBE_DEFINE2_XLATE(prov, mod, func, name, arg0, xarg0, \ arg1, xarg1) \ SDT_PROBE_DEFINE(prov, mod, func, name); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, xarg0); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1, xarg1) -#define SDT_PROBE_DEFINE3_XLATE(prov, mod, func, name, arg0, xarg0, \ +#define SDT_PROBE_DEFINE3_XLATE(prov, mod, func, name, arg0, xarg0, \ arg1, xarg1, arg2, xarg2) \ SDT_PROBE_DEFINE(prov, mod, func, name); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, xarg0); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1, xarg1); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, arg2, xarg2) -#define SDT_PROBE_DEFINE4_XLATE(prov, mod, func, name, arg0, xarg0, \ +#define SDT_PROBE_DEFINE4_XLATE(prov, mod, func, name, arg0, xarg0, \ arg1, xarg1, arg2, xarg2, arg3, xarg3) \ SDT_PROBE_DEFINE(prov, mod, func, name); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, xarg0); \ @@ -256,7 +195,7 @@ SET_DECLARE(sdt_argtypes_set, struct sdt_argtype); SDT_PROBE_ARGTYPE(prov, mod, func, name, 2, arg2, xarg2); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 3, arg3, xarg3) -#define SDT_PROBE_DEFINE5_XLATE(prov, mod, func, name, arg0, xarg0, \ +#define SDT_PROBE_DEFINE5_XLATE(prov, mod, func, name, arg0, xarg0, \ arg1, xarg1, arg2, xarg2, arg3, xarg3, arg4, xarg4) \ SDT_PROBE_DEFINE(prov, mod, func, name); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, xarg0); \ @@ -265,7 +204,7 @@ SET_DECLARE(sdt_argtypes_set, struct sdt_argtype); SDT_PROBE_ARGTYPE(prov, mod, func, name, 3, arg3, xarg3); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 4, arg4, xarg4) -#define SDT_PROBE_DEFINE6_XLATE(prov, mod, func, name, arg0, xarg0, \ +#define SDT_PROBE_DEFINE6_XLATE(prov, mod, func, name, arg0, xarg0, \ arg1, xarg1, arg2, xarg2, arg3, xarg3, arg4, xarg4, arg5, xarg5) \ SDT_PROBE_DEFINE(prov, mod, func, name); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, xarg0); \ @@ -275,9 +214,9 @@ SET_DECLARE(sdt_argtypes_set, struct sdt_argtype); SDT_PROBE_ARGTYPE(prov, mod, func, name, 4, arg4, xarg4); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 5, arg5, xarg5) -#define SDT_PROBE_DEFINE7_XLATE(prov, mod, func, name, arg0, xarg0, \ - arg1, xarg1, arg2, xarg2, arg3, xarg3, arg4, xarg4, arg5, xarg5, arg6, \ - xarg6) \ +#define SDT_PROBE_DEFINE7_XLATE(prov, mod, func, name, arg0, xarg0, \ + arg1, xarg1, arg2, xarg2, arg3, xarg3, arg4, xarg4, arg5, xarg5, \ + arg6, xarg6) \ SDT_PROBE_DEFINE(prov, mod, func, name); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 0, arg0, xarg0); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 1, arg1, xarg1); \ @@ -287,139 +226,267 @@ SET_DECLARE(sdt_argtypes_set, struct sdt_argtype); SDT_PROBE_ARGTYPE(prov, mod, func, name, 5, arg5, xarg5); \ SDT_PROBE_ARGTYPE(prov, mod, func, name, 6, arg6, xarg6) -#define SDT_PROBE0(prov, mod, func, name) \ - SDT_PROBE(prov, mod, func, name, 0, 0, 0, 0, 0) -#define SDT_PROBE1(prov, mod, func, name, arg0) \ - SDT_PROBE(prov, mod, func, name, arg0, 0, 0, 0, 0) -#define SDT_PROBE2(prov, mod, func, name, arg0, arg1) \ - SDT_PROBE(prov, mod, func, name, arg0, arg1, 0, 0, 0) -#define SDT_PROBE3(prov, mod, func, name, arg0, arg1, arg2) \ - SDT_PROBE(prov, mod, func, name, arg0, arg1, arg2, 0, 0) -#define SDT_PROBE4(prov, mod, func, name, arg0, arg1, arg2, arg3) \ - SDT_PROBE(prov, mod, func, name, arg0, arg1, arg2, arg3, 0) -#define SDT_PROBE5(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) \ - SDT_PROBE(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) -#define SDT_PROBE6(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4, arg5) \ - do { \ - if (sdt_##prov##_##mod##_##func##_##name->id) \ - (*(void (*)(uint32_t, uintptr_t, uintptr_t, uintptr_t, \ - uintptr_t, uintptr_t, uintptr_t))sdt_probe_func)( \ - sdt_##prov##_##mod##_##func##_##name->id, \ - (uintptr_t)arg0, (uintptr_t)arg1, (uintptr_t)arg2, \ - (uintptr_t)arg3, (uintptr_t)arg4, (uintptr_t)arg5);\ - } while (0) -#define SDT_PROBE7(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4, arg5, \ - arg6) \ - do { \ - if (sdt_##prov##_##mod##_##func##_##name->id) \ - (*(void (*)(uint32_t, uintptr_t, uintptr_t, uintptr_t, \ - uintptr_t, uintptr_t, uintptr_t, uintptr_t)) \ - sdt_probe_func)( \ - sdt_##prov##_##mod##_##func##_##name->id, \ - (uintptr_t)arg0, (uintptr_t)arg1, (uintptr_t)arg2, \ - (uintptr_t)arg3, (uintptr_t)arg4, (uintptr_t)arg5, \ - (uintptr_t)arg6); \ - } while (0) - -#define DTRACE_PROBE_IMPL_START(name, arg0, arg1, arg2, arg3, arg4) do { \ - static SDT_PROBE_DEFINE(sdt, , , name); \ - SDT_PROBE(sdt, , , name, arg0, arg1, arg2, arg3, arg4); -#define DTRACE_PROBE_IMPL_END } while (0) - -#define DTRACE_PROBE(name) \ - DTRACE_PROBE_IMPL_START(name, 0, 0, 0, 0, 0) \ - DTRACE_PROBE_IMPL_END - -#define DTRACE_PROBE1(name, type0, arg0) \ - DTRACE_PROBE_IMPL_START(name, arg0, 0, 0, 0, 0) \ - SDT_PROBE_ARGTYPE(sdt, , , name, 0, #type0, NULL); \ - DTRACE_PROBE_IMPL_END - -#define DTRACE_PROBE2(name, type0, arg0, type1, arg1) \ - DTRACE_PROBE_IMPL_START(name, arg0, arg1, 0, 0, 0) \ - SDT_PROBE_ARGTYPE(sdt, , , name, 0, #type0, NULL); \ - SDT_PROBE_ARGTYPE(sdt, , , name, 1, #type1, NULL); \ - DTRACE_PROBE_IMPL_END - -#define DTRACE_PROBE3(name, type0, arg0, type1, arg1, type2, arg2) \ - DTRACE_PROBE_IMPL_START(name, arg0, arg1, arg2, 0, 0) \ - SDT_PROBE_ARGTYPE(sdt, , , name, 0, #type0, NULL); \ - SDT_PROBE_ARGTYPE(sdt, , , name, 1, #type1, NULL); \ - SDT_PROBE_ARGTYPE(sdt, , , name, 2, #type2, NULL); \ - DTRACE_PROBE_IMPL_END - -#define DTRACE_PROBE4(name, type0, arg0, type1, arg1, type2, arg2, type3, arg3) \ - DTRACE_PROBE_IMPL_START(name, arg0, arg1, arg2, arg3, 0) \ - SDT_PROBE_ARGTYPE(sdt, , , name, 0, #type0, NULL); \ - SDT_PROBE_ARGTYPE(sdt, , , name, 1, #type1, NULL); \ - SDT_PROBE_ARGTYPE(sdt, , , name, 2, #type2, NULL); \ - SDT_PROBE_ARGTYPE(sdt, , , name, 3, #type3, NULL); \ - DTRACE_PROBE_IMPL_END - -#define DTRACE_PROBE5(name, type0, arg0, type1, arg1, type2, arg2, type3, arg3, \ - type4, arg4) \ - DTRACE_PROBE_IMPL_START(name, arg0, arg1, arg2, arg3, arg4) \ - SDT_PROBE_ARGTYPE(sdt, , , name, 0, #type0, NULL); \ - SDT_PROBE_ARGTYPE(sdt, , , name, 1, #type1, NULL); \ - SDT_PROBE_ARGTYPE(sdt, , , name, 2, #type2, NULL); \ - SDT_PROBE_ARGTYPE(sdt, , , name, 3, #type3, NULL); \ - SDT_PROBE_ARGTYPE(sdt, , , name, 4, #type4, NULL); \ - DTRACE_PROBE_IMPL_END - -#endif /* KDTRACE_HOOKS */ - /* - * This type definition must match that of dtrace_probe. It is defined this - * way to avoid having to rely on CDDL code. + * Macros for defining probe sites. */ -typedef void (*sdt_probe_func_t)(uint32_t, uintptr_t arg0, uintptr_t arg1, - uintptr_t arg2, uintptr_t arg3, uintptr_t arg4); + +#define SDT_PROBE0(prov, mod, func, name) do { \ + extern void _SDT_PROBE_STUB(prov, mod, func, name)(void); \ + _SDT_PROBE_STUB(prov, mod, func, name)(); \ +} while (0) + +#define SDT_PROBE1(prov, mod, func, name, arg0) do { \ + extern void _SDT_PROBE_STUB(prov, mod, func, name)(uintptr_t); \ + _SDT_PROBE_STUB(prov, mod, func, name)((uintptr_t)arg0); \ +} while (0) + +#define SDT_PROBE2(prov, mod, func, name, arg0, arg1) do { \ + extern void _SDT_PROBE_STUB(prov, mod, func, name)(uintptr_t, \ + uintptr_t); \ + _SDT_PROBE_STUB(prov, mod, func, name)((uintptr_t)arg0, \ + (uintptr_t)arg1); \ +} while (0) + +#define SDT_PROBE3(prov, mod, func, name, arg0, arg1, arg2) do { \ + extern void _SDT_PROBE_STUB(prov, mod, func, name)(uintptr_t, \ + uintptr_t, uintptr_t); \ + _SDT_PROBE_STUB(prov, mod, func, name)((uintptr_t)arg0, \ + (uintptr_t)arg1, (uintptr_t)arg2); \ +} while (0) + +#define SDT_PROBE4(prov, mod, func, name, arg0, arg1, arg2, arg3) do { \ + extern void _SDT_PROBE_STUB(prov, mod, func, name)(uintptr_t, \ + uintptr_t, uintptr_t, uintptr_t); \ + _SDT_PROBE_STUB(prov, mod, func, name)((uintptr_t)arg0, \ + (uintptr_t)arg1, (uintptr_t)arg2, (uintptr_t)arg3); \ +} while (0) + +#define SDT_PROBE5(prov, mod, func, name, arg0, arg1, arg2, arg3, \ + arg4) do { \ + extern void _SDT_PROBE_STUB(prov, mod, func, name)(uintptr_t, \ + uintptr_t, uintptr_t, uintptr_t, uintptr_t); \ + _SDT_PROBE_STUB(prov, mod, func, name)((uintptr_t)arg0, \ + (uintptr_t)arg1, (uintptr_t)arg2, (uintptr_t)arg3, \ + (uintptr_t)arg4); \ +} while (0) + +#define SDT_PROBE6(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4, \ + arg5) do { \ + extern void _SDT_PROBE_STUB(prov, mod, func, name)(uintptr_t, \ + uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t); \ + _SDT_PROBE_STUB(prov, mod, func, name)((uintptr_t)arg0, \ + (uintptr_t)arg1, (uintptr_t)arg2, (uintptr_t)arg3, \ + (uintptr_t)arg4, (uintptr_t)arg5); \ +} while (0) + +#define SDT_PROBE7(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4, \ + arg5, arg6) do { \ + extern void _SDT_PROBE_STUB(prov, mod, func, name)(uintptr_t, \ + uintptr_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, \ + uintptr_t); \ + _SDT_PROBE_STUB(prov, mod, func, name)((uintptr_t)arg0, \ + (uintptr_t)arg1, (uintptr_t)arg2, (uintptr_t)arg3, \ + (uintptr_t)arg4, (uintptr_t)arg5, (uintptr_t)arg6); \ +} while (0) /* - * The 'sdt' provider will set it to dtrace_probe when it loads. + * SDT macros for compatibility with illumos. These define the probe + * at the probe site and use the "sdt" provider, and are thus intended + * for use in ad-hoc debugging and analysis. */ -extern sdt_probe_func_t sdt_probe_func; +#define DTRACE_PROBE(name) DTRACE_PROBE0(name) + +#define DTRACE_PROBE0(name) do { \ + static _SDT_PROBE_DEFINE0(sdt, , , name); \ + SDT_PROBE0(sdt, , , name); \ +} while (0) + +#define DTRACE_PROBE1(name, t0, arg0) do { \ + static _SDT_PROBE_DEFINE1(sdt, , , name, t0); \ + SDT_PROBE1(sdt, , , name, arg0); \ +} while (0) + +#define DTRACE_PROBE2(name, t0, arg0, t1, arg1) do { \ + static _SDT_PROBE_DEFINE2(sdt, , , name, t0, t1); \ + SDT_PROBE2(sdt, , , name, arg0, arg1); \ +} while (0) + +#define DTRACE_PROBE3(name, t0, arg0, t1, arg1, t2, arg2) do { \ + static _SDT_PROBE_DEFINE3(sdt, , , name, t0, t1, t2); \ + SDT_PROBE3(sdt, , , name, arg0, arg1, arg2); \ +} while (0) + +#define DTRACE_PROBE4(name, t0, arg0, t1, arg1, t2, arg2, t3, arg3) do { \ + static _SDT_PROBE_DEFINE4(sdt, , , name, t0, t1, t2, t3); \ + SDT_PROBE4(sdt, , , name, arg0, arg1, arg2, arg3); \ +} while (0) + +#define DTRACE_PROBE5(name, t0, arg0, t1, arg1, t2, arg2, t3, arg3, t4, \ + arg4) do { \ + static _SDT_PROBE_DEFINE5(sdt, , , name, t0, t1, t2, t3, t4); \ + SDT_PROBE5(sdt, , , name, arg0, arg1, arg2, arg3, arg4); \ +} while (0) + +#define DTRACE_PROBE6(name, t0, arg0, t1, arg1, t2, arg2, t3, arg3, t4, \ + arg4, t5, arg5) do { \ + static _SDT_PROBE_DEFINE6(sdt, , , name, t0, t1, t2, t3, t4, \ + t5); \ + SDT_PROBE5(sdt, , , name, arg0, arg1, arg2, arg3, arg4, arg5); \ +} while (0) + +#define DTRACE_PROBE7(name, t0, arg0, t1, arg1, t2, arg2, t3, arg3, t4, \ + arg4, t5, arg5, t6, arg6) do { \ + static _SDT_PROBE_DEFINE7(sdt, , , name, t0, t1, t2, t3, t4, \ + t5, t6); \ + SDT_PROBE5(sdt, , , name, arg0, arg1, arg2, arg3, arg4, arg5, \ + arg6); \ +} while (0) + +#else /* !KDTRACE_HOOKS */ + +#define SDT_PROVIDER_DEFINE(prov) +#define SDT_PROVIDER_DECLARE(prov) +#define SDT_PROBE_DEFINE(prov, mod, func, name) +#define SDT_PROBE_DECLARE(prov, mod, func, name) +#define SDT_PROBE(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) +#define SDT_PROBE_ARGTYPE(prov, mod, func, name, num, type, xtype) + +#define SDT_PROBE_DEFINE0(prov, mod, func, name) +#define SDT_PROBE_DEFINE1(prov, mod, func, name, arg0) +#define SDT_PROBE_DEFINE2(prov, mod, func, name, arg0, arg1) +#define SDT_PROBE_DEFINE3(prov, mod, func, name, arg0, arg1, arg2) +#define SDT_PROBE_DEFINE4(prov, mod, func, name, arg0, arg1, arg2, arg3) +#define SDT_PROBE_DEFINE5(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) +#define SDT_PROBE_DEFINE6(prov, mod, func, name, arg0, arg1, arg2, arg3, \ + arg4, arg5) +#define SDT_PROBE_DEFINE7(prov, mod, func, name, arg0, arg1, arg2, arg3, \ + arg4, arg5, arg6) + +#define SDT_PROBE0(prov, mod, func, name) +#define SDT_PROBE1(prov, mod, func, name, arg0) +#define SDT_PROBE2(prov, mod, func, name, arg0, arg1) +#define SDT_PROBE3(prov, mod, func, name, arg0, arg1, arg2) +#define SDT_PROBE4(prov, mod, func, name, arg0, arg1, arg2, arg3) +#define SDT_PROBE5(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4) +#define SDT_PROBE6(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4, arg5) +#define SDT_PROBE7(prov, mod, func, name, arg0, arg1, arg2, arg3, arg4, \ + arg5, arg6) + +#define SDT_PROBE_DEFINE0_XLATE(prov, mod, func, name) +#define SDT_PROBE_DEFINE1_XLATE(prov, mod, func, name, arg0, xarg0) +#define SDT_PROBE_DEFINE2_XLATE(prov, mod, func, name, arg0, xarg0, \ + arg1, xarg1) +#define SDT_PROBE_DEFINE3_XLATE(prov, mod, func, name, arg0, xarg0, \ + arg1, xarg1, arg2, xarg2) +#define SDT_PROBE_DEFINE4_XLATE(prov, mod, func, name, arg0, xarg0, \ + arg1, xarg1, arg2, xarg2, arg3, xarg3) +#define SDT_PROBE_DEFINE5_XLATE(prov, mod, func, name, arg0, xarg0, \ + arg1, xarg1, arg2, xarg2, arg3, xarg3, arg4, xarg4) +#define SDT_PROBE_DEFINE6_XLATE(prov, mod, func, name, arg0, xarg0, \ + arg1, xarg1, arg2, xarg2, arg3, xarg3, arg4, xarg4, arg5, xarg5) +#define SDT_PROBE_DEFINE7_XLATE(prov, mod, func, name, arg0, xarg0, \ + arg1, xarg1, arg2, xarg2, arg3, xarg3, arg4, xarg4, arg5, xarg5, \ + arg6, xarg6) + +#define DTRACE_PROBE(name) +#define DTRACE_PROBE1(name, t0, arg0) +#define DTRACE_PROBE2(name, t0, arg0, t1, arg1) +#define DTRACE_PROBE3(name, t0, arg0, t1, arg1, t2, arg2) +#define DTRACE_PROBE4(name, t0, arg0, t1, arg1, t2, arg2, t3, arg3) +#define DTRACE_PROBE5(name, t0, arg0, t1, arg1, t2, arg2, t3, arg3, t4, arg4) + +#endif /* KDTRACE_HOOKS */ + +struct linker_file; struct sdt_probe; struct sdt_provider; -struct linker_file; struct sdt_argtype { int ndx; /* Argument index. */ const char *type; /* Argument type string. */ const char *xtype; /* Translated argument type. */ - TAILQ_ENTRY(sdt_argtype) - argtype_entry; /* Argument type list entry. */ + TAILQ_ENTRY(sdt_argtype) argtype_entry; /* Argument type list entry. */ struct sdt_probe *probe; /* Ptr to the probe structure. */ }; struct sdt_probe { int version; /* Set to sizeof(struct sdt_probe). */ struct sdt_provider *prov; /* Ptr to the provider structure. */ - TAILQ_ENTRY(sdt_probe) - probe_entry; /* SDT probe list entry. */ + TAILQ_ENTRY(sdt_probe) probe_entry; /* SDT probe list entry. */ + SLIST_HEAD(, sdt_probedesc) site_list; /* probe sites */ TAILQ_HEAD(, sdt_argtype) argtype_list; const char *mod; const char *func; const char *name; - id_t id; /* DTrace probe ID. */ int n_args; /* Number of arguments. */ struct linker_file *sdtp_lf; /* Module in which we're defined. */ }; struct sdt_provider { char *name; /* Provider name. */ - TAILQ_ENTRY(sdt_provider) - prov_entry; /* SDT provider list entry. */ + TAILQ_ENTRY(sdt_provider) prov_entry; /* SDT provider list entry. */ uintptr_t id; /* DTrace provider ID. */ int sdt_refs; /* Number of module references. */ }; -void sdt_probe_stub(uint32_t, uintptr_t, uintptr_t, uintptr_t, uintptr_t, - uintptr_t); +struct sdt_probedesc { + union { + SLIST_ENTRY(sdt_probedesc) spd_entry; + struct sdt_probe *spd_probe; + } li; + u_long spd_offset; +}; SDT_PROVIDER_DECLARE(sdt); -#endif /* _KERNEL */ +uint64_t sdt_md_patch_callsite(struct sdt_probe *, uint64_t, bool); +void sdt_patch_reloc(struct linker_file *, const char *, uint64_t, uint64_t); + +#else /* !_KERNEL */ + +#define _DTRACE_VERSION 1 + +#define DTRACE_PROBE(prov, name) { \ + extern void __dtrace_##prov##___##name(void); \ + __dtrace_##prov##___##name(); \ +} + +#define DTRACE_PROBE1(prov, name, arg1) { \ + extern void __dtrace_##prov##___##name(unsigned long); \ + __dtrace_##prov##___##name((unsigned long)arg1); \ +} + +#define DTRACE_PROBE2(prov, name, arg1, arg2) { \ + extern void __dtrace_##prov##___##name(unsigned long, \ + unsigned long); \ + __dtrace_##prov##___##name((unsigned long)arg1, \ + (unsigned long)arg2); \ +} + +#define DTRACE_PROBE3(prov, name, arg1, arg2, arg3) { \ + extern void __dtrace_##prov##___##name(unsigned long, \ + unsigned long, unsigned long); \ + __dtrace_##prov##___##name((unsigned long)arg1, \ + (unsigned long)arg2, (unsigned long)arg3); \ +} + +#define DTRACE_PROBE4(prov, name, arg1, arg2, arg3, arg4) { \ + extern void __dtrace_##prov##___##name(unsigned long, \ + unsigned long, unsigned long, unsigned long); \ + __dtrace_##prov##___##name((unsigned long)arg1, \ + (unsigned long)arg2, (unsigned long)arg3, \ + (unsigned long)arg4); \ +} + +#define DTRACE_PROBE5(prov, name, arg1, arg2, arg3, arg4, arg5) { \ + extern void __dtrace_##prov##___##name(unsigned long, \ + unsigned long, unsigned long, unsigned long, unsigned long);\ + __dtrace_##prov##___##name((unsigned long)arg1, \ + (unsigned long)arg2, (unsigned long)arg3, \ + (unsigned long)arg4, (unsigned long)arg5); \ +} + +#endif /* !_KERNEL */ #endif /* _SYS_SDT_H */ diff --git a/sys/tools/sdtstrip.sh b/sys/tools/sdtstrip.sh new file mode 100644 index 0000000..88d1baa --- /dev/null +++ b/sys/tools/sdtstrip.sh @@ -0,0 +1,51 @@ +#!/bin/sh +# +# Copyright (c) 2015 Mark Johnston +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +# +# Strip SDT probe stub symbols. After the kernel has been linked, they +# are not needed. +# +# Ideally we'd be able to do this with a simple pipeline in which we use +# objcopy --strip-symbols=/dev/stdin, but objcopy pouts if the argument +# to --strip-symbols isn't a regular file. +# + +obj=$1 +if [ ! -f "$obj" -o $# -ne 1 ]; then + echo "usage: $(basename $0) " >&2 + exit 1 +fi + +set -e + +symfile=$(mktemp) +${OBJDUMP} -j .text -t $obj | \ + ${AWK} '$NF ~ /^__dtrace_sdt_/{print $NF}' > $symfile +${OBJCOPY} --strip-symbols=${symfile} $obj +rm -f $symfile diff --git a/sys/tools/sdtstubs.sh b/sys/tools/sdtstubs.sh new file mode 100644 index 0000000..5b3f2d5 --- /dev/null +++ b/sys/tools/sdtstubs.sh @@ -0,0 +1,104 @@ +#!/bin/sh +# +# Copyright (c) 2015 Mark Johnston +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $FreeBSD$ +# + +# +# Generate SDT probe stubs and record stub relocation info. +# + +obj=$1 +if [ ! -f "$obj" -o $# -ne 1 ]; then + echo "usage: $(basename $0) " >&2 + exit 1 +fi + +set -e + +case $(elfdump -e "$obj" | ${AWK} '/e_machine: /{print $2}') in +EM_386) + extype=long + ;; +EM_X86_64) + extype=quad + ;; +*) + echo "$(basename $0): unknown machine type" >&2 + exit 1 + ;; +esac + +# Emit the preamble. +cat <<__EOF__ +/* + * This is a machine-generated file - do not edit it! + */ +#include + +void _sdt_probe_stub(void); + +/* + * A no-op stub used as an alias for all SDT probe site stubs. + */ +void +_sdt_probe_stub(void) +{ +} + +__EOF__ + +# Generate aliases for each probe stub so that relocations against them +# can be resolved in the final link. These symbols will be removed by +# sdtstrip.sh after linking. +${NM} -u "$obj" | \ + ${AWK} '/^[[:space:]]*U __dtrace_sdt_[_[:alpha:]]+[_[:alnum:]]*$/ { + printf "__strong_reference(_sdt_probe_stub, %s);\n", $2; + }' + +# Emit a linker set containing a struct sdt_probedesc for each relocation +# against an SDT probe stub. +${OBJDUMP} -r -j .text "$obj" | \ + ${AWK} 'BEGIN { + print "__asm__("; + print " \".pushsection set_sdt_probe_site_set, \\\"a\\\"\\n\""; + print " \".align 8\\n\""; + print " \".globl __start_set_sdt_probe_site_set\\n\""; + print " \".globl __stop_set_sdt_probe_site_set\\n\""; + } + + $3 ~ /^__dtrace_sdt_[_[:alpha:]]+[_[:alnum:]]*\+?/ { + match($3, /sdt_[_[:alpha:]]+[_[:alnum:]]*/); + symname = substr($3, 10, RLENGTH); + directive = "'${extype}'"; + printf " \".globl %s\\n\"\n", symname; + printf " \".%s %s\\n\"\n \".%s 0x%s\\n\"\n", + directive, symname, directive, $1; + } + + END { + print " \".popsection\");"; + }' diff --git a/sys/vm/vm_pageout.c b/sys/vm/vm_pageout.c index 188866e..c2514b7 100644 --- a/sys/vm/vm_pageout.c +++ b/sys/vm/vm_pageout.c @@ -76,7 +76,7 @@ __FBSDID("$FreeBSD$"); #include "opt_vm.h" -#include "opt_kdtrace.h" + #include #include #include diff --git a/sys/x86/x86/sdt_machdep.c b/sys/x86/x86/sdt_machdep.c new file mode 100644 index 0000000..f0f8c6f --- /dev/null +++ b/sys/x86/x86/sdt_machdep.c @@ -0,0 +1,92 @@ +/*- + * Copyright 2015 Mark Johnston + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include + +#define CALL_SITE_LEN 5 + +#define X86_OPC_CALL32 0xe8 +#define X86_OPC_JMP32 0xe9 +#define X86_OPC_NOP 0x90 +#define X86_OPC_RET 0xc3 + +/* + * Defined by sdtstubs.sh at compile-time. + */ +void _sdt_probe_stub(void); + +uint64_t +sdt_md_patch_callsite(struct sdt_probe *probe, uint64_t offset, bool reloc) +{ + uintptr_t stubaddr; + uint32_t target; + uint8_t *callinstr, opcode; + + callinstr = (uint8_t *)(uintptr_t)(offset - 1); + opcode = callinstr[0]; + if (opcode != X86_OPC_CALL32 && opcode != X86_OPC_JMP32) { + printf("sdt: opcode mismatch (0x%x) for %s:::%s@%p\n", + callinstr[0], probe->prov->name, probe->name, + (void *)(uintptr_t)offset); + return (0); + } + + /* + * If we've been passed a probe descriptor, verify that the call/jmp + * target is in fact the SDT stub. If it's not, something's wrong and + * we shouldn't touch anything. + */ + stubaddr = (uintptr_t)_sdt_probe_stub; + memcpy(&target, &callinstr[1], sizeof(target)); + if (!reloc && roundup2(target + (uintptr_t)callinstr, 16) != stubaddr) { + printf("sdt: offset mismatch: %p vs. %p\n", + (void *)roundup2(target + (uintptr_t)callinstr, 16), + (void *)stubaddr); + return (0); + } + + switch (opcode) { + case X86_OPC_CALL32: + memset(callinstr, X86_OPC_NOP, CALL_SITE_LEN); + break; + case X86_OPC_JMP32: + /* + * The probe site is a tail call, so we need a "ret" + * when the probe isn't enabled. We overwrite the second + * byte instead of the first: the first byte will be + * replaced with a breakpoint when the probe is enabled. + */ + memset(callinstr, X86_OPC_NOP, CALL_SITE_LEN); + callinstr[1] = X86_OPC_RET; + break; + } + return ((uint64_t)(uintptr_t)callinstr); +}