Esempio n. 1
0
/*
 * Unload all the loaded modules and then refresh the module cache with the
 * latest list of loaded modules and their address ranges.
 */
void
dtrace_update(dtrace_hdl_t *dtp)
{
	dt_module_t *dmp;
	DIR *dirp;

	for (dmp = dt_list_next(&dtp->dt_modlist);
	    dmp != NULL; dmp = dt_list_next(dmp))
		dt_module_unload(dtp, dmp);

	if (!(dtp->dt_oflags & DTRACE_O_NOSYS)) {
		dt_module_update(dtp, "mach_kernel");
	}

	/*
	 * Look up all the macro identifiers and set di_id to the latest value.
	 * This code collaborates with dt_lex.l on the use of di_id.  We will
	 * need to implement something fancier if we need to support non-ints.
	 */
	dt_idhash_lookup(dtp->dt_macros, "egid")->di_id = getegid();
	dt_idhash_lookup(dtp->dt_macros, "euid")->di_id = geteuid();
	dt_idhash_lookup(dtp->dt_macros, "gid")->di_id = getgid();
	dt_idhash_lookup(dtp->dt_macros, "pid")->di_id = getpid();
	dt_idhash_lookup(dtp->dt_macros, "pgid")->di_id = getpgid(0);
	dt_idhash_lookup(dtp->dt_macros, "ppid")->di_id = getppid();
	dt_idhash_lookup(dtp->dt_macros, "projid")->di_id = getprojid();
	dt_idhash_lookup(dtp->dt_macros, "sid")->di_id = getsid(0);
	dt_idhash_lookup(dtp->dt_macros, "taskid")->di_id = gettaskid();
	dt_idhash_lookup(dtp->dt_macros, "uid")->di_id = getuid();

	/*
	 * Cache the pointers to the modules representing the base executable
	 * and the run-time linker in the dtrace client handle. Note that on
	 * x86 krtld is folded into unix, so if we don't find it, use unix
	 * instead.
	 */
	dtp->dt_exec = dt_module_lookup_by_name(dtp, "mach_kernel");
	dtp->dt_rtld = dt_module_lookup_by_name(dtp, "dyld"); /* XXX to what purpose? */

	/*
	 * If this is the first time we are initializing the module list,
	 * remove the module for genunix from the module list and then move it
	 * to the front of the module list.  We do this so that type and symbol
	 * queries encounter genunix and thereby optimize for the common case
	 * in dtrace_lookup_by_name() and dtrace_lookup_by_type(), below.
	 */
	if (dtp->dt_exec != NULL &&
	    dtp->dt_cdefs == NULL && dtp->dt_ddefs == NULL) {
		dt_list_delete(&dtp->dt_modlist, dtp->dt_exec);
		dt_list_prepend(&dtp->dt_modlist, dtp->dt_exec);
	}
}
Esempio n. 2
0
dt_module_t *
dt_module_create(dtrace_hdl_t *dtp, const char *name)
{
	long pid;
	char *eptr;
	dt_ident_t *idp;
	uint_t h = dt_strtab_hash(name, NULL) % dtp->dt_modbuckets;
	dt_module_t *dmp;

	for (dmp = dtp->dt_mods[h]; dmp != NULL; dmp = dmp->dm_next) {
		if (strcmp(dmp->dm_name, name) == 0)
			return (dmp);
	}

	if ((dmp = malloc(sizeof (dt_module_t))) == NULL)
		return (NULL); /* caller must handle allocation failure */

	bzero(dmp, sizeof (dt_module_t));
	(void) strlcpy(dmp->dm_name, name, sizeof (dmp->dm_name));
	dt_list_append(&dtp->dt_modlist, dmp);
	dmp->dm_next = dtp->dt_mods[h];
	dtp->dt_mods[h] = dmp;
	dtp->dt_nmods++;

	if (dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)
		dmp->dm_ops = &dt_modops_64;
	else
		dmp->dm_ops = &dt_modops_32;

	/*
	 * Modules for userland processes are special. They always refer to a
	 * specific process and have a copy of their CTF data from a specific
	 * instant in time. Any dt_module_t that begins with 'pid' is a module
	 * for a specific process, much like how any probe description that
	 * begins with 'pid' is special. pid123 refers to process 123. A module
	 * that is just 'pid' refers specifically to pid$target. This is
	 * generally done as D does not currently allow for macros to be
	 * evaluated when working with types.
	 */
	if (strncmp(dmp->dm_name, "pid", 3) == 0) {
		errno = 0;
		if (dmp->dm_name[3] == '\0') {
			idp = dt_idhash_lookup(dtp->dt_macros, "target");
			if (idp != NULL && idp->di_id != 0)
				dmp->dm_pid = idp->di_id;
		} else {
			pid = strtol(dmp->dm_name + 3, &eptr, 10);
			if (errno == 0 && *eptr == '\0')
				dmp->dm_pid = (pid_t)pid;
			else
				dt_dprintf("encountered malformed pid "
				    "module: %s\n", dmp->dm_name);
		}
	}

	return (dmp);
}
Esempio n. 3
0
struct ps_prochandle *
dtrace_proc_grab(dtrace_hdl_t *dtp, pid_t pid, int flags)
{
	dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target");
	struct ps_prochandle *P = dt_proc_grab(dtp, pid, flags, 0);

	if (P != NULL && idp != NULL && idp->di_id == 0)
		idp->di_id = pid; /* $target = grabbed pid */

	return (P);
}
Esempio n. 4
0
struct ps_prochandle *
dtrace_proc_create(dtrace_hdl_t *dtp, const char *file, char *const *argv)
{
	dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target");
	struct ps_prochandle *P = dt_proc_create(dtp, file, argv);

	if (P != NULL && idp != NULL && idp->di_id == 0)
		idp->di_id = Pstatus(P)->pr_pid; /* $target = created pid */

	return (P);
}
Esempio n. 5
0
dt_ident_t *
dt_idstack_lookup(dt_idstack_t *sp, const char *name)
{
	dt_idhash_t *dhp;
	dt_ident_t *idp;

	for (dhp = dt_list_prev(&sp->dids_list);
	    dhp != NULL; dhp = dt_list_prev(dhp)) {
		if ((idp = dt_idhash_lookup(dhp, name)) != NULL)
			return (idp);
	}

	return (NULL);
}
Esempio n. 6
0
struct ps_prochandle *
dtrace_proc_waitfor(dtrace_hdl_t *dtp, char const *pname)
{
	dt_ident_t *idp = dt_idhash_lookup(dtp->dt_macros, "target");
	struct ps_prochandle *P = NULL;
	int err;

	dtrace_procdesc_t pdesc;

	assert(dtp);
	assert(pname);
	assert(*pname != '\0');

	size_t max_len = sizeof(pdesc.p_comm);
	if (strlcpy(pdesc.p_comm, pname, max_len) >= max_len) {
		fprintf(stderr, "Error, the process name (%s) exceeded the %lu characters limit\n",
		       pname, sizeof(pdesc.p_comm) - 1);
		return NULL;
	}

	if ((err = dt_ioctl(dtp, DTRACEIOC_PROCWAITFOR, &pdesc)) != 0) {
		fprintf(stderr, "Error, dt_ioctl() failed (%s)\n", strerror(errno));
		return NULL;
	}

	assert(pdesc.p_pid != -1);

	/*
 	 * The process is already stopped by the previous ioctl call.
	 * The function dt_proc_grab() will stop and resume the process,
	 * but the process will remain stopped until we call pid_resume().
	 */
	P = dt_proc_grab(dtp, pdesc.p_pid, 0, 0);

	/* Waking-up a process can fail if there is another client waiting for the same process. */
	if ((err = pid_resume(pdesc.p_pid)) != 0) {
		dt_dprintf("Unable to resume the process (pid=%d), the process is still suspended\n",
		           pdesc.p_pid);
	}

	if (P != NULL && idp != NULL && idp->di_id == 0)
		idp->di_id = pdesc.p_pid; /* $target = grabbed pid */

	return P;
}
Esempio n. 7
0
int
dtrace_symbol_type(dtrace_hdl_t *dtp, const GElf_Sym *symp,
    const dtrace_syminfo_t *sip, dtrace_typeinfo_t *tip)
{
	dt_module_t *dmp;

	tip->dtt_object = NULL;
	tip->dtt_ctfp = NULL;
	tip->dtt_type = CTF_ERR;
	tip->dtt_flags = 0;

	if ((dmp = dt_module_lookup_by_name(dtp, sip->dts_object)) == NULL)
		return (dt_set_errno(dtp, EDT_NOMOD));

	if (symp->st_shndx == SHN_UNDEF && dmp->dm_extern != NULL) {
		dt_ident_t *idp =
		    dt_idhash_lookup(dmp->dm_extern, sip->dts_name);

		if (idp == NULL)
			return (dt_set_errno(dtp, EDT_NOSYM));

		tip->dtt_ctfp = idp->di_ctfp;
		tip->dtt_type = idp->di_type;

	} else if (GELF_ST_TYPE(symp->st_info) != STT_FUNC) {
		if (dt_module_getctf(dtp, dmp) == NULL)
			return (-1); /* errno is set for us */

		tip->dtt_ctfp = dmp->dm_ctfp;
		tip->dtt_type = ctf_lookup_by_symbol(dmp->dm_ctfp, sip->dts_id);

		if (tip->dtt_type == CTF_ERR) {
			dtp->dt_ctferr = ctf_errno(tip->dtt_ctfp);
			return (dt_set_errno(dtp, EDT_CTF));
		}

	} else {
		tip->dtt_ctfp = DT_FPTR_CTFP(dtp);
		tip->dtt_type = DT_FPTR_TYPE(dtp);
	}

	tip->dtt_object = dmp->dm_name;
	return (0);
}
Esempio n. 8
0
/*ARGSUSED*/
static void
dt_pragma_apply(dt_idhash_t *dhp, dt_ident_t *idp)
{
	dt_idhash_t *php;
	dt_ident_t *pdp;

	if ((php = yypcb->pcb_pragmas) == NULL)
		return; /* no pragmas pending for current compilation pass */

	while ((pdp = dt_idhash_lookup(php, idp->di_name)) != NULL) {
		switch (pdp->di_kind) {
		case DT_IDENT_PRAGAT:
			idp->di_attr = pdp->di_attr;
			break;
		case DT_IDENT_PRAGBN:
			idp->di_vers = pdp->di_vers;
			break;
		}
		dt_idhash_delete(php, pdp);
	}
}
Esempio n. 9
0
/*
 * Lookup a probe declaration based on a known provider and full or partially
 * specified module, function, and name.  If the probe is not known to us yet,
 * ask dtrace(7D) to match the description and then cache any useful results.
 */
dt_probe_t *
dt_probe_lookup(dt_provider_t *pvp, const char *s)
{
	dtrace_hdl_t *dtp = pvp->pv_hdl;
	dtrace_probedesc_t pd;
	dt_ident_t *idp;
	size_t keylen;
	char *key;

	if (dtrace_str2desc(dtp, DTRACE_PROBESPEC_NAME, s, &pd) != 0)
		return (NULL); /* dt_errno is set for us */

	keylen = dt_probe_keylen(&pd);
	key = dt_probe_key(&pd, alloca(keylen));

	/*
	 * If the probe is already declared, then return the dt_probe_t from
	 * the existing identifier.  This could come from a static declaration
	 * or it could have been cached from an earlier call to this function.
	 */
	if ((idp = dt_idhash_lookup(pvp->pv_probes, key)) != NULL)
		return (idp->di_data);

	/*
	 * If the probe isn't known, use the probe description computed above
	 * to ask dtrace(7D) to find the first matching probe.
	 */
	if (dt_ioctl(dtp, DTRACEIOC_PROBEMATCH, &pd) == 0)
		return (dt_probe_discover(pvp, &pd));

	if (errno == ESRCH || errno == EBADF)
		(void) dt_set_errno(dtp, EDT_NOPROBE);
	else
		(void) dt_set_errno(dtp, errno);

	return (NULL);
}
Esempio n. 10
0
dt_probe_t *
dt_probe_info(dtrace_hdl_t *dtp,
    const dtrace_probedesc_t *pdp, dtrace_probeinfo_t *pip)
{
	int m_is_glob = pdp->dtpd_mod[0] == '\0' || strisglob(pdp->dtpd_mod);
	int f_is_glob = pdp->dtpd_func[0] == '\0' || strisglob(pdp->dtpd_func);
	int n_is_glob = pdp->dtpd_name[0] == '\0' || strisglob(pdp->dtpd_name);

	dt_probe_t *prp = NULL;
	const dtrace_pattr_t *pap;
	dt_provider_t *pvp;
	dt_ident_t *idp;

	/*
	 * Attempt to lookup the probe in our existing cache for this provider.
	 * If none is found and an explicit probe ID was specified, discover
	 * that specific probe and cache its description and arguments.
	 */
	if ((pvp = dt_provider_lookup(dtp, pdp->dtpd_provider)) != NULL) {
		size_t keylen = dt_probe_keylen(pdp);
		char *key = dt_probe_key(pdp, alloca(keylen));

		if ((idp = dt_idhash_lookup(pvp->pv_probes, key)) != NULL)
			prp = idp->di_data;
		else if (pdp->dtpd_id != DTRACE_IDNONE)
			prp = dt_probe_discover(pvp, pdp);
	}

	/*
	 * If no probe was found in our cache, convert the caller's partial
	 * probe description into a fully-formed matching probe description by
	 * iterating over up to at most two probes that match 'pdp'.  We then
	 * call dt_probe_discover() on the resulting probe identifier.
	 */
	if (prp == NULL) {
		dtrace_probedesc_t pd;
		int m;

		bzero(&pd, sizeof (pd));
		pd.dtpd_id = DTRACE_IDNONE;

		/*
		 * Call dtrace_probe_iter() to find matching probes.  Our
		 * dt_probe_desc() callback will produce the following results:
		 *
		 * m < 0 dtrace_probe_iter() found zero matches (or failed).
		 * m > 0 dtrace_probe_iter() found more than one match.
		 * m = 0 dtrace_probe_iter() found exactly one match.
		 */
		if ((m = dtrace_probe_iter(dtp, pdp, dt_probe_desc, &pd)) < 0)
			return (NULL); /* dt_errno is set for us */

		if ((pvp = dt_provider_lookup(dtp, pd.dtpd_provider)) == NULL)
			return (NULL); /* dt_errno is set for us */

		/*
		 * If more than one probe was matched, then do not report probe
		 * information if either of the following conditions is true:
		 *
		 * (a) The Arguments Data stability of the matched provider is
		 *	less than Evolving.
		 *
		 * (b) Any description component that is at least Evolving is
		 *	empty or is specified using a globbing expression.
		 *
		 * These conditions imply that providers that provide Evolving
		 * or better Arguments Data stability must guarantee that all
		 * probes with identical field names in a field of Evolving or
		 * better Name stability have identical argument signatures.
		 */
		if (m > 0) {
			if (pvp->pv_desc.dtvd_attr.dtpa_args.dtat_data <
			    DTRACE_STABILITY_EVOLVING) {
				(void) dt_set_errno(dtp, EDT_UNSTABLE);
				return (NULL);
			}


			if (pvp->pv_desc.dtvd_attr.dtpa_mod.dtat_name >=
			    DTRACE_STABILITY_EVOLVING && m_is_glob) {
				(void) dt_set_errno(dtp, EDT_UNSTABLE);
				return (NULL);
			}

			if (pvp->pv_desc.dtvd_attr.dtpa_func.dtat_name >=
			    DTRACE_STABILITY_EVOLVING && f_is_glob) {
				(void) dt_set_errno(dtp, EDT_UNSTABLE);
				return (NULL);
			}

			if (pvp->pv_desc.dtvd_attr.dtpa_name.dtat_name >=
			    DTRACE_STABILITY_EVOLVING && n_is_glob) {
				(void) dt_set_errno(dtp, EDT_UNSTABLE);
				return (NULL);
			}
		}

		/*
		 * If we matched a probe exported by dtrace(7D), then discover
		 * the real attributes.  Otherwise grab the static declaration.
		 */
		if (pd.dtpd_id != DTRACE_IDNONE)
			prp = dt_probe_discover(pvp, &pd);
		else
			prp = dt_probe_lookup(pvp, pd.dtpd_name);

		if (prp == NULL)
			return (NULL); /* dt_errno is set for us */
	}

	assert(pvp != NULL && prp != NULL);

	/*
	 * Compute the probe description attributes by taking the minimum of
	 * the attributes of the specified fields.  If no provider is specified
	 * or a glob pattern is used for the provider, use Unstable attributes.
	 */
	if (pdp->dtpd_provider[0] == '\0' || strisglob(pdp->dtpd_provider))
		pap = &_dtrace_prvdesc;
	else
		pap = &pvp->pv_desc.dtvd_attr;

	pip->dtp_attr = pap->dtpa_provider;

	if (!m_is_glob)
		pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_mod);
	if (!f_is_glob)
		pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_func);
	if (!n_is_glob)
		pip->dtp_attr = dt_attr_min(pip->dtp_attr, pap->dtpa_name);

	pip->dtp_arga = pap->dtpa_args;
	pip->dtp_argv = prp->pr_argv;
	pip->dtp_argc = prp->pr_argc;

	return (prp);
}
Esempio n. 11
0
/*
 * Exported interface to look up a symbol by name.  We return the GElf_Sym and
 * complete symbol information for the matching symbol.
 */
int
dtrace_lookup_by_name(dtrace_hdl_t *dtp, const char *object, const char *name,
    GElf_Sym *symp, dtrace_syminfo_t *sip)
{
	dt_module_t *dmp;
	dt_ident_t *idp;
	uint_t n, id;
	GElf_Sym sym;

	uint_t mask = 0; /* mask of dt_module flags to match */
	uint_t bits = 0; /* flag bits that must be present */

	if (object != DTRACE_OBJ_EVERY &&
	    object != DTRACE_OBJ_KMODS &&
	    object != DTRACE_OBJ_UMODS) {
		if ((dmp = dt_module_from_object(dtp, object)) == NULL)
			return (-1); /* dt_errno is set for us */

		if (dt_module_load(dtp, dmp) == -1)
			return (-1); /* dt_errno is set for us */
		n = 1;

	} else {
		if (object == DTRACE_OBJ_KMODS)
			mask = bits = DT_DM_KERNEL;
		else if (object == DTRACE_OBJ_UMODS)
			mask = DT_DM_KERNEL;

		dmp = dt_list_next(&dtp->dt_modlist);
		n = dtp->dt_nmods;
	}

	if (symp == NULL)
		symp = &sym;

	for (; n > 0; n--, dmp = dt_list_next(dmp)) {
		if ((dmp->dm_flags & mask) != bits)
			continue; /* failed to match required attributes */

		if (dt_module_load(dtp, dmp) == -1)
			continue; /* failed to load symbol table */

		if (dmp->dm_ops->do_symname(dmp, name, symp, &id) != NULL) {
			if (sip != NULL) {
				sip->dts_object = dmp->dm_name;
				sip->dts_name = (const char *)
				    dmp->dm_strtab.cts_data + symp->st_name;
				sip->dts_id = id;
			}
			return (0);
		}

		if (dmp->dm_extern != NULL &&
		    (idp = dt_idhash_lookup(dmp->dm_extern, name)) != NULL) {
			if (symp != &sym) {
				symp->st_name = (uintptr_t)idp->di_name;
				symp->st_info =
				    GELF_ST_INFO(STB_GLOBAL, STT_NOTYPE);
				symp->st_other = 0;
				symp->st_shndx = SHN_UNDEF;
				symp->st_value = 0;
				symp->st_size =
				    ctf_type_size(idp->di_ctfp, idp->di_type);
			}

			if (sip != NULL) {
				sip->dts_object = dmp->dm_name;
				sip->dts_name = idp->di_name;
				sip->dts_id = idp->di_id;
			}

			return (0);
		}
	}

	return (dt_set_errno(dtp, EDT_NOSYM));
}
Esempio n. 12
0
/*
 * Unload all the loaded modules and then refresh the module cache with the
 * latest list of loaded modules and their address ranges.
 */
void
dtrace_update(dtrace_hdl_t *dtp)
{
	dt_module_t *dmp;
	DIR *dirp;
#if defined(__FreeBSD__)
	int fileid;
#endif

	for (dmp = dt_list_next(&dtp->dt_modlist);
	    dmp != NULL; dmp = dt_list_next(dmp))
		dt_module_unload(dtp, dmp);

#if defined(sun)
	/*
	 * Open /system/object and attempt to create a libdtrace module for
	 * each kernel module that is loaded on the current system.
	 */
	if (!(dtp->dt_oflags & DTRACE_O_NOSYS) &&
	    (dirp = opendir(OBJFS_ROOT)) != NULL) {
		struct dirent *dp;

		while ((dp = readdir(dirp)) != NULL) {
			if (dp->d_name[0] != '.')
				dt_module_update(dtp, dp->d_name);
		}

		(void) closedir(dirp);
	}
#elif defined(__FreeBSD__)
	/*
	 * Use FreeBSD's kernel loader interface to discover what kernel
	 * modules are loaded and create a libdtrace module for each one.
	 */
	for (fileid = kldnext(0); fileid > 0; fileid = kldnext(fileid)) {
		struct kld_file_stat k_stat;
		k_stat.version = sizeof(k_stat);
		if (kldstat(fileid, &k_stat) == 0)
			dt_module_update(dtp, &k_stat);
	}
#endif

	/*
	 * Look up all the macro identifiers and set di_id to the latest value.
	 * This code collaborates with dt_lex.l on the use of di_id.  We will
	 * need to implement something fancier if we need to support non-ints.
	 */
	dt_idhash_lookup(dtp->dt_macros, "egid")->di_id = getegid();
	dt_idhash_lookup(dtp->dt_macros, "euid")->di_id = geteuid();
	dt_idhash_lookup(dtp->dt_macros, "gid")->di_id = getgid();
	dt_idhash_lookup(dtp->dt_macros, "pid")->di_id = getpid();
	dt_idhash_lookup(dtp->dt_macros, "pgid")->di_id = getpgid(0);
	dt_idhash_lookup(dtp->dt_macros, "ppid")->di_id = getppid();
#if defined(sun)
	dt_idhash_lookup(dtp->dt_macros, "projid")->di_id = getprojid();
#endif
	dt_idhash_lookup(dtp->dt_macros, "sid")->di_id = getsid(0);
#if defined(sun)
	dt_idhash_lookup(dtp->dt_macros, "taskid")->di_id = gettaskid();
#endif
	dt_idhash_lookup(dtp->dt_macros, "uid")->di_id = getuid();

	/*
	 * Cache the pointers to the modules representing the base executable
	 * and the run-time linker in the dtrace client handle. Note that on
	 * x86 krtld is folded into unix, so if we don't find it, use unix
	 * instead.
	 */
	dtp->dt_exec = dt_module_lookup_by_name(dtp, "genunix");
	dtp->dt_rtld = dt_module_lookup_by_name(dtp, "krtld");
	if (dtp->dt_rtld == NULL)
		dtp->dt_rtld = dt_module_lookup_by_name(dtp, "unix");

	/*
	 * If this is the first time we are initializing the module list,
	 * remove the module for genunix from the module list and then move it
	 * to the front of the module list.  We do this so that type and symbol
	 * queries encounter genunix and thereby optimize for the common case
	 * in dtrace_lookup_by_name() and dtrace_lookup_by_type(), below.
	 */
	if (dtp->dt_exec != NULL &&
	    dtp->dt_cdefs == NULL && dtp->dt_ddefs == NULL) {
		dt_list_delete(&dtp->dt_modlist, dtp->dt_exec);
		dt_list_prepend(&dtp->dt_modlist, dtp->dt_exec);
	}
}
Esempio n. 13
0
dt_xlator_t *
dt_xlator_create(dtrace_hdl_t *dtp,
    const dtrace_typeinfo_t *src, const dtrace_typeinfo_t *dst,
    const char *name, dt_node_t *members, dt_node_t *nodes)
{
	dt_xlator_t *dxp = dt_zalloc(dtp, sizeof (dt_xlator_t));
	dtrace_typeinfo_t ptr = *dst;
	dt_xlator_t **map;
	dt_node_t *dnp;
	uint_t kind;

	if (dxp == NULL)
		return (NULL);

	dxp->dx_hdl = dtp;
	dxp->dx_id = dtp->dt_xlatorid++;
	dxp->dx_gen = dtp->dt_gen;
	dxp->dx_arg = -1;

	if ((map = dt_alloc(dtp, sizeof (void *) * (dxp->dx_id + 1))) == NULL) {
		dt_free(dtp, dxp);
		return (NULL);
	}

	dt_list_append(&dtp->dt_xlators, dxp);
	bcopy(dtp->dt_xlatormap, map, sizeof (void *) * dxp->dx_id);
	dt_free(dtp, dtp->dt_xlatormap);
	dtp->dt_xlatormap = map;
	dtp->dt_xlatormap[dxp->dx_id] = dxp;

	if (dt_type_pointer(&ptr) == -1) {
		ptr.dtt_ctfp = NULL;
		ptr.dtt_type = CTF_ERR;
	}

	dxp->dx_ident = dt_ident_create(name ? name : "T",
	    DT_IDENT_SCALAR, DT_IDFLG_REF | DT_IDFLG_ORPHAN, 0,
	    _dtrace_defattr, 0, &dt_idops_thaw, NULL, dtp->dt_gen);

	if (dxp->dx_ident == NULL)
		goto err; /* no memory for identifier */

	dxp->dx_ident->di_ctfp = src->dtt_ctfp;
	dxp->dx_ident->di_type = src->dtt_type;

	/*
	 * If an input parameter name is given, this is a static translator
	 * definition: create an idhash and identifier for the parameter.
	 */
	if (name != NULL) {
		dxp->dx_locals = dt_idhash_create("xlparams", NULL, 0, 0);

		if (dxp->dx_locals == NULL)
			goto err; /* no memory for identifier hash */

		dt_idhash_xinsert(dxp->dx_locals, dxp->dx_ident);
	}

	dxp->dx_souid.di_name = "translator";
	dxp->dx_souid.di_kind = DT_IDENT_XLSOU;
	dxp->dx_souid.di_flags = DT_IDFLG_REF;
	dxp->dx_souid.di_id = dxp->dx_id;
	dxp->dx_souid.di_attr = _dtrace_defattr;
	dxp->dx_souid.di_ops = &dt_idops_thaw;
	dxp->dx_souid.di_data = dxp;
	dxp->dx_souid.di_ctfp = dst->dtt_ctfp;
	dxp->dx_souid.di_type = dst->dtt_type;
	dxp->dx_souid.di_gen = dtp->dt_gen;

	dxp->dx_ptrid.di_name = "translator";
	dxp->dx_ptrid.di_kind = DT_IDENT_XLPTR;
	dxp->dx_ptrid.di_flags = DT_IDFLG_REF;
	dxp->dx_ptrid.di_id = dxp->dx_id;
	dxp->dx_ptrid.di_attr = _dtrace_defattr;
	dxp->dx_ptrid.di_ops = &dt_idops_thaw;
	dxp->dx_ptrid.di_data = dxp;
	dxp->dx_ptrid.di_ctfp = ptr.dtt_ctfp;
	dxp->dx_ptrid.di_type = ptr.dtt_type;
	dxp->dx_ptrid.di_gen = dtp->dt_gen;

	/*
	 * If a deferred pragma is pending on the keyword "translator", run all
	 * the deferred pragmas on dx_souid and then copy results to dx_ptrid.
	 * See the code in dt_pragma.c for details on deferred ident pragmas.
	 */
	if (dtp->dt_globals->dh_defer != NULL && yypcb->pcb_pragmas != NULL &&
	    dt_idhash_lookup(yypcb->pcb_pragmas, "translator") != NULL) {
		dtp->dt_globals->dh_defer(dtp->dt_globals, &dxp->dx_souid);
		dxp->dx_ptrid.di_attr = dxp->dx_souid.di_attr;
		dxp->dx_ptrid.di_vers = dxp->dx_souid.di_vers;
	}

	dxp->dx_src_ctfp = src->dtt_ctfp;
	dxp->dx_src_type = src->dtt_type;
	dxp->dx_src_base = ctf_type_resolve(src->dtt_ctfp, src->dtt_type);

	dxp->dx_dst_ctfp = dst->dtt_ctfp;
	dxp->dx_dst_type = dst->dtt_type;
	dxp->dx_dst_base = ctf_type_resolve(dst->dtt_ctfp, dst->dtt_type);

	kind = ctf_type_kind(dst->dtt_ctfp, dxp->dx_dst_base);
	assert(kind == CTF_K_STRUCT || kind == CTF_K_UNION);

	/*
	 * If no input parameter is given, we're making a dynamic translator:
	 * create member nodes for every member of the output type.  Otherwise
	 * retain the member and allocation node lists presented by the parser.
	 */
	if (name == NULL) {
		if (ctf_member_iter(dxp->dx_dst_ctfp, dxp->dx_dst_base,
		    dt_xlator_create_member, dxp) != 0)
			goto err;
	} else {
		dxp->dx_members = members;
		dxp->dx_nodes = nodes;
	}

	/*
	 * Assign member IDs to each member and allocate space for DIFOs
	 * if and when this translator is eventually compiled.
	 */
	for (dnp = dxp->dx_members; dnp != NULL; dnp = dnp->dn_list) {
		dnp->dn_membxlator = dxp;
		dnp->dn_membid = dxp->dx_nmembers++;
	}

	dxp->dx_membdif = dt_zalloc(dtp,
	    sizeof (dtrace_difo_t *) * dxp->dx_nmembers);

	if (dxp->dx_membdif == NULL) {
		dxp->dx_nmembers = 0;
		goto err;
	}

	return (dxp);

err:
	dt_xlator_destroy(dtp, dxp);
	return (NULL);
}