--- old/usr/src/lib/libdtrace/common/dt_pid.c	2014-01-14 20:12:30.619898994 -0500
+++ new/usr/src/lib/libdtrace/common/dt_pid.c	2014-01-14 20:12:30.637324757 -0500
@@ -23,6 +23,9 @@
  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
+ */
 
 #include <assert.h>
 #include <strings.h>
@@ -33,11 +36,13 @@
 #include <alloca.h>
 #include <libgen.h>
 #include <stddef.h>
+#include <sys/sysmacros.h>
 
 #include <dt_impl.h>
 #include <dt_program.h>
 #include <dt_pid.h>
 #include <dt_string.h>
+#include <dt_module.h>
 
 typedef struct dt_pid_probe {
 	dtrace_hdl_t *dpp_dtp;
@@ -755,3 +760,162 @@
 
 	return (ret);
 }
+
+/*
+ * libdtrace has a backroom deal with us to ask us for type information on
+ * behalf of pid provider probes when fasttrap doesn't return any type
+ * information. Instead we'll look up the module and see if there is type
+ * information available. However, if there is no type information available due
+ * to a lack of CTF data, then we want to make sure that DTrace still carries on
+ * in face of that. As such we don't have a meaningful exit code about failure.
+ * We emit information about why we failed to the dtrace debug log so someone
+ * can figure it out by asking nicely for DTRACE_DEBUG.
+ */
+void
+dt_pid_get_types(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp,
+    dtrace_argdesc_t *adp, int *nargs)
+{
+	dt_module_t *dmp;
+	ctf_file_t *fp;
+	ctf_funcinfo_t f;
+	ctf_id_t argv[32];
+	GElf_Sym sym;
+	prsyminfo_t si;
+	struct ps_prochandle *p;
+	int i, args;
+	char buf[DTRACE_ARGTYPELEN];
+	const char *mptr;
+	char *eptr;
+	int ret = 0;
+	int argc = sizeof (argv) / sizeof (ctf_id_t);
+	Lmid_t lmid;
+
+	/* Set up a potential outcome */
+	args = *nargs;
+	*nargs = 0;
+
+	/*
+	 * If we don't have an entry or return probe then we can just stop right
+	 * now as we don't have arguments for offset probes.
+	 */
+	if (strcmp(pdp->dtpd_name, "entry") != 0 &&
+	    strcmp(pdp->dtpd_name, "return") != 0)
+		return;
+
+	dmp = dt_module_create(dtp, pdp->dtpd_provider);
+	if (dmp == NULL) {
+		dt_dprintf("failed to find module for %s\n",
+		    pdp->dtpd_provider);
+		return;
+	}
+	if (dt_module_load(dtp, dmp) != 0) {
+		dt_dprintf("failed to load module for %s\n",
+		    pdp->dtpd_provider);
+		return;
+	}
+
+	/*
+	 * We may be working with a module that doesn't have ctf. If that's the
+	 * case then we just return now and move on with life.
+	 */
+	fp = dt_module_getctflib(dtp, dmp, pdp->dtpd_mod);
+	if (fp == NULL) {
+		dt_dprintf("no ctf container for  %s\n",
+		    pdp->dtpd_mod);
+		return;
+	}
+	p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE);
+	if (p == NULL) {
+		dt_dprintf("failed to grab pid\n");
+		return;
+	}
+	dt_proc_lock(dtp, p);
+
+	/*
+	 * Check to see if the D module has a link map ID and separate that out
+	 * for properly interrogating libproc.
+	 */
+	if ((mptr = strchr(pdp->dtpd_mod, '`')) != NULL) {
+		if (strlen(pdp->dtpd_mod) < 3) {
+			dt_dprintf("found weird modname with linkmap, "
+			    "aborting: %s\n", pdp->dtpd_mod);
+			goto out;
+		}
+		if (pdp->dtpd_mod[0] != 'L' || pdp->dtpd_mod[1] != 'M') {
+			dt_dprintf("missing leading 'LM', "
+			    "aborting: %s\n", pdp->dtpd_mod);
+			goto out;
+		}
+		errno = 0;
+		lmid = strtol(pdp->dtpd_mod + 2, &eptr, 16);
+		if (errno == ERANGE || eptr != mptr) {
+			dt_dprintf("failed to parse out lmid, aborting: %s\n",
+			    pdp->dtpd_mod);
+			goto out;
+		}
+		mptr++;
+	} else {
+		mptr = pdp->dtpd_mod;
+		lmid = 0;
+	}
+
+	if (Pxlookup_by_name(p, lmid, mptr, pdp->dtpd_func,
+	    &sym, &si) != 0) {
+		dt_dprintf("failed to find function %s in %s`%s\n",
+		    pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);
+		goto out;
+	}
+	if (ctf_func_info(fp, si.prs_id, &f) == CTF_ERR) {
+		dt_dprintf("failed to get ctf information for %s in %s`%s\n",
+		    pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);
+		goto out;
+	}
+
+	(void) snprintf(buf, sizeof (buf), "%s`%s", pdp->dtpd_provider,
+	    pdp->dtpd_mod);
+
+	if (strcmp(pdp->dtpd_name, "return") == 0) {
+		if (args < 2)
+			goto out;
+
+		bzero(adp, sizeof (dtrace_argdesc_t));
+		adp->dtargd_ndx = 0;
+		adp->dtargd_id = pdp->dtpd_id;
+		adp->dtargd_mapping = adp->dtargd_ndx;
+		/*
+		 * We explicitly leave out the library here, we only care that
+		 * it is some int. We are assuming that there is no ctf
+		 * container in here that is lying about what an int is.
+		 */
+		(void) snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
+		    "user %s`%s", pdp->dtpd_provider, "int");
+		adp++;
+		bzero(adp, sizeof (dtrace_argdesc_t));
+		adp->dtargd_ndx = 1;
+		adp->dtargd_id = pdp->dtpd_id;
+		adp->dtargd_mapping = adp->dtargd_ndx;
+		ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
+		    "userland ");
+		(void) ctf_type_qname(fp, f.ctc_return, adp->dtargd_native +
+		    ret, DTRACE_ARGTYPELEN - ret, buf);
+		*nargs = 2;
+	} else {
+		if (ctf_func_args(fp, si.prs_id, argc, argv) == CTF_ERR)
+			goto out;
+
+		*nargs = MIN(args, f.ctc_argc);
+		for (i = 0; i < *nargs; i++, adp++) {
+			bzero(adp, sizeof (dtrace_argdesc_t));
+			adp->dtargd_ndx = i;
+			adp->dtargd_id = pdp->dtpd_id;
+			adp->dtargd_mapping = adp->dtargd_ndx;
+			ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
+			    "userland ");
+			(void) ctf_type_qname(fp, argv[i], adp->dtargd_native +
+			    ret, DTRACE_ARGTYPELEN - ret, buf);
+		}
+	}
+out:
+	dt_proc_unlock(dtp, p);
+	dt_proc_release(dtp, p);
+}
