/* * We've been asked to load data that belongs to another process. As such we're * going to pgrab it at this instant, load everything that we might ever care * about, and then drive on. The reason for this is that the process that we're * interested in might be changing. As long as we have grabbed it, then this * can't be a problem for us. * * For now, we're actually going to punt on most things and just try to get CTF * data, nothing else. Basically this is only useful as a source of type * information, we can't go and do the stacktrace lookups, etc. */ static int dt_module_load_proc(dtrace_hdl_t *dtp, dt_module_t *dmp) { struct ps_prochandle *p; dt_module_cb_arg_t arg; /* * Note that on success we do not release this hold. We must hold this * for our life time. */ p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE); if (p == NULL) { dt_dprintf("failed to grab pid: %d\n", (int)dmp->dm_pid); return (dt_set_errno(dtp, EDT_CANTLOAD)); } dt_proc_lock(dtp, p); arg.dpa_proc = p; arg.dpa_dtp = dtp; arg.dpa_dmp = dmp; arg.dpa_count = 0; if (Pobject_iter_resolved(p, dt_module_load_proc_count, &arg) != 0) { dt_dprintf("failed to iterate objects\n"); dt_proc_release(dtp, p); return (dt_set_errno(dtp, EDT_CANTLOAD)); } if (arg.dpa_count == 0) { dt_dprintf("no ctf data present\n"); dt_proc_unlock(dtp, p); dt_proc_release(dtp, p); return (dt_set_errno(dtp, EDT_CANTLOAD)); } dmp->dm_libctfp = malloc(sizeof (ctf_file_t *) * arg.dpa_count); if (dmp->dm_libctfp == NULL) { dt_proc_unlock(dtp, p); dt_proc_release(dtp, p); return (dt_set_errno(dtp, EDT_NOMEM)); } bzero(dmp->dm_libctfp, sizeof (ctf_file_t *) * arg.dpa_count); dmp->dm_libctfn = malloc(sizeof (char *) * arg.dpa_count); if (dmp->dm_libctfn == NULL) { free(dmp->dm_libctfp); dt_proc_unlock(dtp, p); dt_proc_release(dtp, p); return (dt_set_errno(dtp, EDT_NOMEM)); } bzero(dmp->dm_libctfn, sizeof (char *) * arg.dpa_count); dmp->dm_nctflibs = arg.dpa_count; arg.dpa_count = 0; if (Pobject_iter_resolved(p, dt_module_load_proc_build, &arg) != 0) { dt_proc_unlock(dtp, p); dt_module_unload(dtp, dmp); dt_proc_release(dtp, p); return (dt_set_errno(dtp, EDT_CANTLOAD)); } assert(arg.dpa_count == dmp->dm_nctflibs); dt_dprintf("loaded %d ctf modules for pid %d\n", arg.dpa_count, (int)dmp->dm_pid); dt_proc_unlock(dtp, p); dt_proc_release(dtp, p); dmp->dm_flags |= DT_DM_LOADED; return (0); }
void dtrace_proc_release(dtrace_hdl_t *dtp, struct ps_prochandle *P) { dt_proc_release(dtp, P); }
int dt_pid_create_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, dt_pcb_t *pcb) { char provname[DTRACE_PROVNAMELEN]; struct ps_prochandle *P; dt_proc_t *dpr; pid_t pid; int err = 0; assert(pcb != NULL); if ((pid = dt_pid_get_pid(pdp, dtp, pcb, NULL)) == -1) return (-1); if (dtp->dt_ftfd == -1) { if (dtp->dt_fterr == ENOENT) { (void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV, "pid provider is not installed on this system"); } else { (void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_NODEV, "pid provider is not available: %s", strerror(dtp->dt_fterr)); } return (-1); } (void) snprintf(provname, sizeof (provname), "pid%d", (int)pid); if (gmatch(provname, pdp->dtpd_provider) != 0) { if ((P = dt_proc_grab(dtp, pid, PGRAB_RDONLY | PGRAB_FORCE, 0)) == NULL) { (void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB, "failed to grab process %d", (int)pid); return (-1); } dpr = dt_proc_lookup(dtp, P, 0); assert(dpr != NULL); (void) pthread_mutex_lock(&dpr->dpr_lock); if ((err = dt_pid_create_pid_probes(pdp, dtp, pcb, dpr)) == 0) { /* * Alert other retained enablings which may match * against the newly created probes. */ (void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL); } (void) pthread_mutex_unlock(&dpr->dpr_lock); dt_proc_release(dtp, P); } /* * If it's not strictly a pid provider, we might match a USDT provider. */ if (strcmp(provname, pdp->dtpd_provider) != 0) { if ((P = dt_proc_grab(dtp, pid, 0, 1)) == NULL) { (void) dt_pid_error(dtp, pcb, NULL, NULL, D_PROC_GRAB, "failed to grab process %d", (int)pid); return (-1); } dpr = dt_proc_lookup(dtp, P, 0); assert(dpr != NULL); (void) pthread_mutex_lock(&dpr->dpr_lock); if (!dpr->dpr_usdt) { err = dt_pid_create_usdt_probes(pdp, dtp, pcb, dpr); dpr->dpr_usdt = B_TRUE; } (void) pthread_mutex_unlock(&dpr->dpr_lock); dt_proc_release(dtp, P); } return (err ? -1 : 0); }