/*ARGSUSED*/ static void __sdt_provide_module(void *arg, struct modctl *ctl) { #pragma unused(arg) struct module *mp = (struct module *)ctl->mod_address; char *modname = ctl->mod_modname; sdt_probedesc_t *sdpd; sdt_probe_t *sdp, *old; sdt_provider_t *prov; int len; /* * One for all, and all for one: if we haven't yet registered all of * our providers, we'll refuse to provide anything. */ for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) { if (prov->sdtp_id == DTRACE_PROVNONE) return; } if (!mp || mp->sdt_nprobes != 0 || (sdpd = mp->sdt_probes) == NULL) return; for (sdpd = mp->sdt_probes; sdpd != NULL; sdpd = sdpd->sdpd_next) { const char *name = sdpd->sdpd_name, *func; char *nname; int i, j; dtrace_id_t id; for (prov = sdt_providers; prov->sdtp_prefix != NULL; prov++) { const char *prefpart, *prefix = prov->sdtp_prefix; if ((prefpart = strstr(name, prefix))) { name = prefpart + strlen(prefix); break; } } nname = kmem_alloc(len = strlen(name) + 1, KM_SLEEP); for (i = 0, j = 0; name[j] != '\0'; i++) { if (name[j] == '_' && name[j + 1] == '_') { nname[i] = '-'; j += 2; } else { nname[i] = name[j++]; } } nname[i] = '\0'; sdp = kmem_zalloc(sizeof (sdt_probe_t), KM_SLEEP); sdp->sdp_loadcnt = ctl->mod_loadcnt; sdp->sdp_ctl = ctl; sdp->sdp_name = nname; sdp->sdp_namelen = len; sdp->sdp_provider = prov; func = sdpd->sdpd_func; if (func == NULL) func = "<unknown>"; /* * We have our provider. Now create the probe. */ if ((id = dtrace_probe_lookup(prov->sdtp_id, modname, func, nname)) != DTRACE_IDNONE) { old = dtrace_probe_arg(prov->sdtp_id, id); ASSERT(old != NULL); sdp->sdp_next = old->sdp_next; sdp->sdp_id = id; old->sdp_next = sdp; } else { sdp->sdp_id = dtrace_probe_create(prov->sdtp_id, modname, func, nname, SDT_AFRAMES, sdp); mp->sdt_nprobes++; } #if 0 printf ("__sdt_provide_module: sdpd=0x%p sdp=0x%p name=%s, id=%d\n", sdpd, sdp, nname, sdp->sdp_id); #endif sdp->sdp_hashnext = sdt_probetab[SDT_ADDR2NDX(sdpd->sdpd_offset)]; sdt_probetab[SDT_ADDR2NDX(sdpd->sdpd_offset)] = sdp; sdp->sdp_patchval = SDT_PATCHVAL; sdp->sdp_patchpoint = (sdt_instr_t *)sdpd->sdpd_offset; sdp->sdp_savedval = *sdp->sdp_patchpoint; } }
/*ARGSUSED*/ static void sdt_provide_module(void *arg, struct modctl *ctl) { struct module *mp = ctl->mod_mp; char *modname = ctl->mod_modname; int primary, nprobes = 0; sdt_probedesc_t *sdpd; sdt_probe_t *sdp, *old; uint32_t *tab; sdt_provider_t *prov; int len; /* * One for all, and all for one: if we haven't yet registered all of * our providers, we'll refuse to provide anything. */ for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) { if (prov->sdtp_id == DTRACE_PROVNONE) return; } if (mp->sdt_nprobes != 0 || (sdpd = mp->sdt_probes) == NULL) return; kobj_textwin_alloc(mp); /* * Hack to identify unix/genunix/krtld. */ primary = vmem_contains(heap_arena, (void *)ctl, sizeof (struct modctl)) == 0; /* * If there hasn't been an sdt table allocated, we'll do so now. */ if (mp->sdt_tab == NULL) { for (; sdpd != NULL; sdpd = sdpd->sdpd_next) { nprobes++; } /* * We could (should?) determine precisely the size of the * table -- but a reasonable maximum will suffice. */ mp->sdt_size = nprobes * SDT_ENTRY_SIZE; mp->sdt_tab = kobj_texthole_alloc(mp->text, mp->sdt_size); if (mp->sdt_tab == NULL) { cmn_err(CE_WARN, "couldn't allocate SDT table " "for module %s", modname); return; } } tab = (uint32_t *)mp->sdt_tab; for (sdpd = mp->sdt_probes; sdpd != NULL; sdpd = sdpd->sdpd_next) { char *name = sdpd->sdpd_name, *func, *nname; int i, j; sdt_provider_t *prov; ulong_t offs; dtrace_id_t id; for (prov = sdt_providers; prov->sdtp_prefix != NULL; prov++) { char *prefix = prov->sdtp_prefix; if (strncmp(name, prefix, strlen(prefix)) == 0) { name += strlen(prefix); break; } } nname = kmem_alloc(len = strlen(name) + 1, KM_SLEEP); for (i = 0, j = 0; name[j] != '\0'; i++) { if (name[j] == '_' && name[j + 1] == '_') { nname[i] = '-'; j += 2; } else { nname[i] = name[j++]; } } nname[i] = '\0'; sdp = kmem_zalloc(sizeof (sdt_probe_t), KM_SLEEP); sdp->sdp_loadcnt = ctl->mod_loadcnt; sdp->sdp_primary = primary; sdp->sdp_ctl = ctl; sdp->sdp_name = nname; sdp->sdp_namelen = len; sdp->sdp_provider = prov; func = kobj_searchsym(mp, sdpd->sdpd_offset + (uintptr_t)mp->text, &offs); if (func == NULL) func = "<unknown>"; /* * We have our provider. Now create the probe. */ if ((id = dtrace_probe_lookup(prov->sdtp_id, modname, func, nname)) != DTRACE_IDNONE) { old = dtrace_probe_arg(prov->sdtp_id, id); ASSERT(old != NULL); sdp->sdp_next = old->sdp_next; sdp->sdp_id = id; old->sdp_next = sdp; } else { sdp->sdp_id = dtrace_probe_create(prov->sdtp_id, modname, func, nname, 1, sdp); mp->sdt_nprobes++; } sdp->sdp_patchval = SDT_CALL((uintptr_t)mp->text + sdpd->sdpd_offset, tab); sdp->sdp_patchpoint = (uint32_t *)((uintptr_t)mp->textwin + sdpd->sdpd_offset); sdp->sdp_savedval = *sdp->sdp_patchpoint; sdt_initialize(sdp, &tab); } }
/*ARGSUSED*/ static void sdt_provide_module(void *arg, struct modctl *ctl) { # if defined(sun) struct module *mp = ctl->mod_mp; char *modname = ctl->mod_modname; sdt_probedesc_t *sdpd; sdt_probe_t *sdp, *old; sdt_provider_t *prov; /* * One for all, and all for one: if we haven't yet registered all of * our providers, we'll refuse to provide anything. */ for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) { if (prov->sdtp_id == DTRACE_PROVNONE) return; } if (mp->sdt_nprobes != 0 || (sdpd = mp->sdt_probes) == NULL) return; for (sdpd = mp->sdt_probes; sdpd != NULL; sdpd = sdpd->sdpd_next) { char *name = sdpd->sdpd_name, *func, *nname; int i, j, len; sdt_provider_t *prov; ulong_t offs; dtrace_id_t id; for (prov = sdt_providers; prov->sdtp_prefix != NULL; prov++) { char *prefix = prov->sdtp_prefix; if (strncmp(name, prefix, strlen(prefix)) == 0) { name += strlen(prefix); break; } } nname = kmem_alloc(len = strlen(name) + 1, KM_SLEEP); for (i = 0, j = 0; name[j] != '\0'; i++) { if (name[j] == '_' && name[j + 1] == '_') { nname[i] = '-'; j += 2; } else { nname[i] = name[j++]; } } nname[i] = '\0'; sdp = kmem_zalloc(sizeof (sdt_probe_t), KM_SLEEP); sdp->sdp_loadcnt = ctl->mod_loadcnt; sdp->sdp_ctl = ctl; sdp->sdp_name = nname; sdp->sdp_namelen = len; sdp->sdp_provider = prov; func = kobj_searchsym(mp, sdpd->sdpd_offset, &offs); if (func == NULL) func = "<unknown>"; /* * We have our provider. Now create the probe. */ if ((id = dtrace_probe_lookup(prov->sdtp_id, modname, func, nname)) != DTRACE_IDNONE) { old = dtrace_probe_arg(prov->sdtp_id, id); ASSERT(old != NULL); sdp->sdp_next = old->sdp_next; sdp->sdp_id = id; old->sdp_next = sdp; } else { sdp->sdp_id = dtrace_probe_create(prov->sdtp_id, modname, func, nname, 3, sdp); mp->sdt_nprobes++; } sdp->sdp_hashnext = sdt_probetab[SDT_ADDR2NDX(sdpd->sdpd_offset)]; sdt_probetab[SDT_ADDR2NDX(sdpd->sdpd_offset)] = sdp; sdp->sdp_patchval = SDT_PATCHVAL; sdp->sdp_patchpoint = (uint8_t *)sdpd->sdpd_offset; sdp->sdp_savedval = *sdp->sdp_patchpoint; } # endif }
void sdt_provide_module(void *arg, struct module *mp) { char *modname = mp->name; dtrace_mprovider_t *prov; sdt_probedesc_t *sdpd; sdt_probe_t *sdp, *prv; int idx, len; /* * Nothing to do if the module SDT probes were already created. */ if (PDATA(mp)->sdt_probe_cnt != 0) return; /* * Nothing to do if there are no SDT probes. */ if (mp->sdt_probec == 0) return; /* * Do not provide any probes unless all SDT providers have been created * for this meta-provider. */ for (prov = sdt_providers; prov->dtmp_name != NULL; prov++) { if (prov->dtmp_id == DTRACE_PROVNONE) return; } if (!sdt_provide_module_arch(arg, mp)) return; for (idx = 0, sdpd = mp->sdt_probes; idx < mp->sdt_probec; idx++, sdpd++) { char *name = sdpd->sdpd_name, *nname; int i, j; dtrace_mprovider_t *prov; dtrace_id_t id; for (prov = sdt_providers; prov->dtmp_pref != NULL; prov++) { char *prefix = prov->dtmp_pref; int len = strlen(prefix); if (strncmp(name, prefix, len) == 0) { name += len; break; } } nname = kmalloc(len = strlen(name) + 1, GFP_KERNEL); if (nname == NULL) { pr_warn("Unable to create probe %s: out-of-memory\n", name); continue; } for (i = j = 0; name[j] != '\0'; i++) { if (name[j] == '_' && name[j + 1] == '_') { nname[i] = '-'; j += 2; } else nname[i] = name[j++]; } nname[i] = '\0'; sdp = kzalloc(sizeof(sdt_probe_t), GFP_KERNEL); if (sdp == NULL) { pr_warn("Unable to create probe %s: out-of-memory\n", nname); continue; } sdp->sdp_loadcnt = 1; /* FIXME */ sdp->sdp_module = mp; sdp->sdp_name = nname; sdp->sdp_namelen = len; sdp->sdp_provider = prov; if ((id = dtrace_probe_lookup(prov->dtmp_id, modname, sdpd->sdpd_func, nname)) != DTRACE_IDNONE) { prv = dtrace_probe_arg(prov->dtmp_id, id); ASSERT(prv != NULL); sdp->sdp_next = prv->sdp_next; sdp->sdp_id = id; prv->sdp_next = sdp; } else { sdp->sdp_id = dtrace_probe_create(prov->dtmp_id, modname, sdpd->sdpd_func, nname, SDT_AFRAMES, sdp); PDATA(mp)->sdt_probe_cnt++; } sdp->sdp_hashnext = sdt_probetab[ SDT_ADDR2NDX(sdpd->sdpd_offset)]; sdt_probetab[SDT_ADDR2NDX(sdpd->sdpd_offset)] = sdp; sdp->sdp_patchpoint = (asm_instr_t *)sdpd->sdpd_offset; sdt_provide_probe_arch(sdp, mp, idx); } }