--- old/usr/src/cmd/dtrace/Makefile.com	2014-01-14 20:11:58.137350540 -0500
+++ new/usr/src/cmd/dtrace/Makefile.com	2014-01-14 20:11:58.169055745 -0500
@@ -29,6 +29,7 @@
 SRCS = $(OBJS:%.o=../%.c)
 
 include ../../Makefile.cmd
+include ../../Makefile.ctf
 
 CFLAGS += $(CCVERBOSE)
 CFLAGS64 += $(CCVERBOSE)
@@ -53,5 +54,6 @@
 
 %.o: ../%.c
 	$(COMPILE.c) $<
+	$(POST_PROCESS_O)
 
 include ../../Makefile.targ
--- old/usr/src/cmd/dtrace/dtrace.c	2014-01-14 20:11:58.653874277 -0500
+++ new/usr/src/cmd/dtrace/dtrace.c	2014-01-14 20:11:58.669937043 -0500
@@ -25,6 +25,7 @@
  */
 /*
  * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  */
 
 #include <sys/types.h>
@@ -488,6 +489,7 @@
 print_probe_info(const dtrace_probeinfo_t *p)
 {
 	char buf[BUFSIZ];
+	char *user;
 	int i;
 
 	oprintf("\n\tProbe Description Attributes\n");
@@ -511,10 +513,14 @@
 	oprintf("\n\tArgument Types\n");
 
 	for (i = 0; i < p->dtp_argc; i++) {
+		if (p->dtp_argv[i].dtt_flags & DTT_FL_USER)
+			user = "userland ";
+		else
+			user = "";
 		if (ctf_type_name(p->dtp_argv[i].dtt_ctfp,
 		    p->dtp_argv[i].dtt_type, buf, sizeof (buf)) == NULL)
 			(void) strlcpy(buf, "(unknown)", sizeof (buf));
-		oprintf("\t\targs[%d]: %s\n", i, buf);
+		oprintf("\t\targs[%d]: %s%s\n", i, user, buf);
 	}
 
 	if (p->dtp_argc == 0)
--- old/usr/src/cmd/dtrace/test/tst/common/Makefile	2014-01-14 20:11:59.303662427 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/Makefile	2014-01-14 20:11:59.318674928 -0500
@@ -26,7 +26,12 @@
 
 #
 # Copyright (c) 2012 by Delphix. All rights reserved.
-# Copyright (c) 2012, Joyent, Inc. All rights reserved.
+# Copyright (c) 2013, Joyent, Inc. All rights reserved.
+#
+
+#
+# WARNING: Do not include Makefile.ctf here. That will cause tests to
+# break.
 #
 
 include $(SRC)/Makefile.master
@@ -85,6 +90,38 @@
 	$(LINK.c) -o json/tst.usdt.exe json/tst.usdt.o json/usdt.o $(LDLIBS)
 	$(POST_PROCESS) ; $(STRIP_STABS)
 
+#
+# Tests that use the next three programs rely on the binaries having
+# valid CTF data.
+#
+uctf/tst.aouttype.exe: uctf/tst.aouttype.c
+	$(COMPILE.c) $(CTF_FLAGS) -o uctf/tst.aouttype.o uctf/tst.aouttype.c
+	$(CTFCONVERT) -i -L VERSION uctf/tst.aouttype.o
+	$(LINK.c) -o uctf/tst.aouttype.exe uctf/tst.aouttype.o $(LDLIBS)
+	$(CTFMERGE) -L VERSION -o $@ uctf/tst.aouttype.o
+	$(POST_PROCESS) ; $(STRIP_STABS)
+
+uctf/tst.chasestrings.exe: uctf/tst.chasestrings.c
+	$(COMPILE.c) $(CTF_FLAGS) -o uctf/tst.chasestrings.o uctf/tst.chasestrings.c
+	$(CTFCONVERT) -i -L VERSION uctf/tst.chasestrings.o
+	$(LINK.c) -o uctf/tst.chasestrings.exe uctf/tst.chasestrings.o $(LDLIBS)
+	$(CTFMERGE) -L VERSION -o $@ uctf/tst.chasestrings.o
+	$(POST_PROCESS) ; $(STRIP_STABS)
+
+uctf/tst.printtype.exe: uctf/tst.printtype.c
+	$(COMPILE.c) $(CTF_FLAGS) -o uctf/tst.printtype.o uctf/tst.printtype.c
+	$(CTFCONVERT) -i -L VERSION uctf/tst.printtype.o
+	$(LINK.c) -o uctf/tst.printtype.exe uctf/tst.printtype.o $(LDLIBS)
+	$(CTFMERGE) -L VERSION -o $@ uctf/tst.printtype.o
+	$(POST_PROCESS) ; $(STRIP_STABS)
+
+#
+# This program should never have any ctf data in it.
+#
+uctf/tst.libtype.exe:
+	$(LINK.c) -o uctf/tst.libtype.exe uctf/tst.libtype.c $(LDLIBS)
+	$(POST_PROCESS) ; $(STRIP_STABS)
+
 usdt/tst.args.exe: usdt/tst.args.o usdt/args.o
 	$(LINK.c) -o usdt/tst.args.exe usdt/tst.args.o usdt/args.o $(LDLIBS)
 	$(POST_PROCESS) ; $(STRIP_STABS)
--- old/usr/src/cmd/dtrace/test/tst/common/pid/tst.provregex1.ksh	2014-01-14 20:11:59.810005289 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/pid/tst.provregex1.ksh	2014-01-14 20:11:59.841851923 -0500
@@ -45,10 +45,10 @@
 all: main
 
 main: main.o
-	gcc -o main main.o
+	gcc -m32 -o main main.o
 
 main.o: main.c
-	gcc -c main.c
+	gcc -m32 -c main.c
 EOF
 
 cat > main.c <<EOF
--- old/usr/src/cmd/dtrace/test/tst/common/pid/tst.provregex2.ksh	2014-01-14 20:12:00.615764387 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/pid/tst.provregex2.ksh	2014-01-14 20:12:00.829549486 -0500
@@ -45,16 +45,16 @@
 all: main altlib.so
 
 main: main.o
-	gcc -o main main.o
+	gcc -m32 -o main main.o
 
 main.o: main.c
-	gcc -c main.c
+	gcc -m32 -c main.c
 
 altlib.so: altlib.o
-	gcc -shared -o altlib.so altlib.o -lc
+	gcc -m32 -shared -o altlib.so altlib.o -lc
 
 altlib.o: altlib.c
-	gcc -c altlib.c
+	gcc -m32 -fPIC -c altlib.c
 EOF
 
 cat > altlib.c <<EOF
--- old/usr/src/cmd/dtrace/test/tst/common/pid/tst.provregex3.ksh	2014-01-14 20:12:01.553133686 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/pid/tst.provregex3.ksh	2014-01-14 20:12:01.568520863 -0500
@@ -46,10 +46,10 @@
 all: main
 
 main: main.o prov.o
-	gcc -o main main.o prov.o
+	gcc -m32 -o main main.o prov.o
 
 main.o: main.c prov.h
-	gcc -c main.c
+	gcc -m32 -c main.c
 
 prov.h: prov.d
 	$dtrace -h -s prov.d
--- old/usr/src/cmd/dtrace/test/tst/common/pid/tst.provregex4.ksh	2014-01-14 20:12:02.006337952 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/pid/tst.provregex4.ksh	2014-01-14 20:12:02.024679544 -0500
@@ -46,10 +46,10 @@
 all: main altlib.so
 
 main: main.o provmain.o
-	gcc -o main main.o provmain.o
+	gcc -m32 -o main main.o provmain.o
 
 main.o: main.c prov.h
-	gcc -c main.c
+	gcc -m32 -c main.c
 
 prov.h: prov.d
 	$dtrace -h -s prov.d
@@ -58,10 +58,10 @@
 	$dtrace -G -32 -o provmain.o -s prov.d main.o
 
 altlib.so: altlib.o provalt.o
-	gcc -shared -o altlib.so altlib.o provalt.o -lc
+	gcc -m32 -shared -o altlib.so altlib.o provalt.o -lc
 
 altlib.o: altlib.c prov.h
-	gcc -c altlib.c
+	gcc -m32 -c altlib.c
 
 provalt.o: prov.d altlib.o
 	$dtrace -G -32 -o provalt.o -s prov.d altlib.o
--- old/usr/src/cmd/dtrace/test/tst/common/printa/tst.largeusersym.ksh	2014-01-14 20:12:02.602910818 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/printa/tst.largeusersym.ksh	2014-01-14 20:12:02.637438043 -0500
@@ -50,7 +50,7 @@
 }
 EOF
 
-gcc -o test test.c
+gcc -m32 -o test test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
--- /dev/null	2014-01-14 20:12:03.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/err.invalidpid.d	2014-01-14 20:12:03.178127654 -0500
@@ -0,0 +1,21 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2013 Joyent, Inc.  All rights reserved.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	trace((pidfoo`int)0);
+}
--- /dev/null	2014-01-14 20:12:03.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/err.invalidpid2.d	2014-01-14 20:12:03.496420120 -0500
@@ -0,0 +1,21 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2013 Joyent, Inc.  All rights reserved.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	trace((pid8foo`int)0);
+}
--- /dev/null	2014-01-14 20:12:03.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/err.invalidpid3.d	2014-01-14 20:12:03.713282791 -0500
@@ -0,0 +1,21 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright (c) 2013 Joyent, Inc.  All rights reserved.
+ */
+
+#pragma D option quiet
+
+BEGIN
+{
+	trace((pid0`int)0);
+}
--- /dev/null	2014-01-14 20:12:03.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/err.invalidtype.ksh	2014-01-14 20:12:03.930629250 -0500
@@ -0,0 +1,34 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# While it's hard to be completely certain that a type of the name we want
+# doesn't exist, we're going to try to pick a name which is rather unique.
+#
+
+if [ $# != 1 ]; then
+        echo expected one argument: '<'dtrace-path'>'
+        exit 2
+fi
+
+dtrace=$1
+t="season_8_mountain_of_madness_t"
+pid=$$
+
+rc=`$dtrace -n "BEGIN{ trace(pid$pid`$t)0); }"`
+
+exit $rc
--- /dev/null	2014-01-14 20:12:04.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/err.invalidtype2.ksh	2014-01-14 20:12:04.153895710 -0500
@@ -0,0 +1,35 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# While it's hard to be completely certain that a type of the name we want
+# doesn't exist, we're going to try to pick a name which is rather
+# unique. This time we're also going to use the pid$target alias.
+#
+
+if [ $# != 1 ]; then
+        echo expected one argument: '<'dtrace-path'>'
+        exit 2
+fi
+
+dtrace=$1
+t="season_8_mountain_of_madness_t"
+pid=$$
+
+rc=`$dtrace -n "BEGIN{ trace(pid`$t)0); }"` -p $pid
+
+exit $rc
--- /dev/null	2014-01-14 20:12:04.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/err.user64mode.ksh	2014-01-14 20:12:04.376241190 -0500
@@ -0,0 +1,90 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# This test is purposefully using a 64-bit DTrace and thus 64-bit types
+# when compared with a 32-bit process. This test uses the userland
+# keyword and so the implicit copyin should access illegal memory and
+# thus exit.
+#
+
+if [ $# != 1 ]; then
+        echo expected one argument: '<'dtrace-path'>'
+        exit 2
+fi
+
+dtrace=$1
+t="zelda_info_t"
+exe="tst.chasestrings.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf' 
+if [[ $? -ne 0 ]]; then
+	echo "CTF does not exist in $exe, that's a bug" >&2
+	exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -64 -qs /dev/stdin <<EOF
+typedef struct info {
+        char    *zi_gamename;
+        int     zi_ndungeons;
+        char    *zi_villain;
+        int     zi_haszelda;
+} info_t;
+
+pid$pid::has_princess:entry
+/next == 0/
+{
+	this->t = (userland info_t *)arg0;
+	printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+	    stringof(this->t->zi_gamename), this->t->zi_ndungeons,
+	    stringof(this->t->zi_villain), this->t->zi_haszelda);
+	next = 1;
+}
+
+pid$pid::has_dungeons:entry
+/next == 1/
+{
+	this->t = (userland info_t *)arg0;
+	printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+	    stringof(this->t->zi_gamename), this->t->zi_ndungeons,
+	    stringof(this->t->zi_villain), this->t->zi_haszelda);
+	next = 2;
+}
+
+pid$pid::has_villain:entry
+/next == 2/
+{
+	this->t = (userland info_t *)arg0;
+	printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+	    stringof(this->t->zi_gamename), this->t->zi_ndungeons,
+	    stringof(this->t->zi_villain), this->t->zi_haszelda);
+	exit(0);
+}
+
+ERROR
+{
+	exit(1);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
--- /dev/null	2014-01-14 20:12:04.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.aouttype.c	2014-01-14 20:12:04.598224037 -0500
@@ -0,0 +1,46 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 (c) Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * This test tries to make sure that we have CTF data for a type that only this
+ * binary would reasonably have. In this case, the
+ * season_7_lisa_the_vegetarian_t.
+ */
+#include <unistd.h>
+
+typedef struct season_7_lisa_the_vegetarian {
+	int fr_salad;
+} season_7_lisa_the_vegetarian_t;
+
+int
+sleeper(season_7_lisa_the_vegetarian_t *lp)
+{
+	for (;;) {
+		sleep(lp->fr_salad);
+	}
+	/*NOTREACHED*/
+	return (0);
+}
+
+int
+main(void)
+{
+	season_7_lisa_the_vegetarian_t l;
+	l.fr_salad = 100;
+
+	sleeper(&l);
+
+	return (0);
+}
--- /dev/null	2014-01-14 20:12:04.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.aouttype.ksh	2014-01-14 20:12:04.820219628 -0500
@@ -0,0 +1,44 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# Lookup a type that is inside a.out.
+#
+
+if [ $# != 1 ]; then
+        echo expected one argument: '<'dtrace-path'>'
+        exit 2
+fi
+
+dtrace=$1
+t="season_7_lisa_the_vegetrian_t *"
+exe="tst.aouttype.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf' 
+if [[ $? -ne 0 ]]; then
+	echo "CTF does not exist in $exe, that's a bug" >&2
+	exit 1
+fi
+
+./$exe &
+pid=$!
+
+rc=`$dtrace -n "BEGIN{ trace((pid$pid\`$t)0); exit(0); }"`
+
+kill -9 $pid
+
+exit $rc
--- /dev/null	2014-01-14 20:12:05.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.c	2014-01-14 20:12:05.070653554 -0500
@@ -0,0 +1,79 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 (c) Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * This test takes data from the current binary which is basically running in a
+ * loop between two functions and our goal is to have two unique types that they
+ * contain which we can print.
+ */
+
+#include <unistd.h>
+
+typedef struct zelda_info {
+	char	*zi_gamename;
+	int	zi_ndungeons;
+	char	*zi_villain;
+	int	zi_haszelda;
+} zelda_info_t;
+
+static int
+has_princess(zelda_info_t *z)
+{
+	return (z->zi_haszelda);
+}
+
+static int
+has_dungeons(zelda_info_t *z)
+{
+	return (z->zi_ndungeons != 0);
+}
+
+static const char *
+has_villain(zelda_info_t *z)
+{
+	return (z->zi_villain);
+}
+
+int
+main(void)
+{
+	zelda_info_t oot;
+	zelda_info_t la;
+	zelda_info_t lttp;
+
+	oot.zi_gamename = "Ocarina of Time";
+	oot.zi_ndungeons = 10;
+	oot.zi_villain = "Ganondorf";
+	oot.zi_haszelda = 1;
+
+	la.zi_gamename = "Link's Awakening";
+	la.zi_ndungeons = 9;
+	la.zi_villain = "Nightmare";
+	la.zi_haszelda = 0;
+
+	lttp.zi_gamename = "A Link to the Past";
+	lttp.zi_ndungeons = 12;
+	lttp.zi_villain = "Ganon";
+	lttp.zi_haszelda = 1;
+
+	for (;;) {
+		(void) has_princess(&oot);
+		(void) has_dungeons(&la);
+		(void) has_villain(&lttp);
+		sleep(1);
+	}
+
+	return (0);
+}
--- /dev/null	2014-01-14 20:12:05.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.ksh	2014-01-14 20:12:05.411999639 -0500
@@ -0,0 +1,76 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# This test is checking that we can read members and that pointers inside
+# members point to valid data that is intelligible, eg. strings.
+#
+
+if [ $# != 1 ]; then
+        echo expected one argument: '<'dtrace-path'>'
+        exit 2
+fi
+
+dtrace=$1
+t="zelda_info_t"
+exe="tst.chasestrings.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf' 
+if [[ $? -ne 0 ]]; then
+	echo "CTF does not exist in $exe, that's a bug" >&2
+	exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -qs /dev/stdin <<EOF
+pid$pid::has_princess:entry
+/next == 0/
+{
+	this->t = (pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t)));
+	printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+	    copyinstr((uintptr_t)this->t->zi_gamename), this->t->zi_ndungeons,
+	    copyinstr((uintptr_t)this->t->zi_villain), this->t->zi_haszelda);
+	next = 1;
+}
+
+pid$pid::has_dungeons:entry
+/next == 1/
+{
+	this->t = (pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t)));
+	printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+	    copyinstr((uintptr_t)this->t->zi_gamename), this->t->zi_ndungeons,
+	    copyinstr((uintptr_t)this->t->zi_villain), this->t->zi_haszelda);
+	next = 2;
+}
+
+pid$pid::has_villain:entry
+/next == 2/
+{
+	this->t = (pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t)));
+	printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+	    copyinstr((uintptr_t)this->t->zi_gamename), this->t->zi_ndungeons,
+	    copyinstr((uintptr_t)this->t->zi_villain), this->t->zi_haszelda);
+	exit(0);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
--- /dev/null	2014-01-14 20:12:05.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.chasestrings.ksh.out	2014-01-14 20:12:05.626974567 -0500
@@ -0,0 +1,4 @@
+game: Ocarina of Time, dungeon: 10, villain: Ganondorf, zelda: 1
+game: Link's Awakening, dungeon: 9, villain: Nightmare, zelda: 0
+game: A Link to the Past, dungeon: 12, villain: Ganon, zelda: 1
+
--- /dev/null	2014-01-14 20:12:05.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.libtype.c	2014-01-14 20:12:05.833672700 -0500
@@ -0,0 +1,29 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 (c) Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * We're linked against libc which has types, though we do not.
+ */
+#include <unistd.h>
+
+int
+main(void)
+{
+	for (;;) {
+		sleep(1000);
+	}
+	/*NOTREACHED*/
+	return (0);
+}
--- /dev/null	2014-01-14 20:12:06.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.libtype.ksh	2014-01-14 20:12:06.049970630 -0500
@@ -0,0 +1,45 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# Here we want to make sure that the program in question does not have ctf data
+# in its a.out; however, we can get types out of a linked libc.
+#
+
+if [ $# != 1 ]; then
+        echo expected one argument: '<'dtrace-path'>'
+        exit 2
+fi
+
+dtrace=$1
+t="int"
+exe="tst.libtype.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf' 
+if [[ $? -eq 0 ]]; then
+	echo "CTF exists in $exe, that's a bug" >&2
+	exit 1
+fi
+
+./$exe &
+pid=$!
+
+rc=`$dtrace -n "BEGIN{ trace((pid$pid\`$t)0); exit(0); }"`
+
+kill -9 $pid
+
+exit $rc
--- /dev/null	2014-01-14 20:12:06.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.linkmap.ksh	2014-01-14 20:12:06.340290518 -0500
@@ -0,0 +1,44 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# We should be able to see both strstr from libc and from ld on an
+# alternate linkmap.
+#
+
+if [ $# != 1 ]; then
+        echo expected one argument: '<'dtrace-path'>'
+        exit 2
+fi
+
+dtrace=$1
+
+$dtrace -q -p $$ -s /dev/stdin  <<EOF
+pid\$target:LM1\`ld.so.1:strstr:entry,
+pid\$target:libc.so.1:strstr:entry
+{
+	exit (0);
+}
+
+BEGIN
+{
+	exit (0);
+}
+EOF
+rc=$?
+
+exit $rc
--- /dev/null	2014-01-14 20:12:06.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.pidprint.ksh	2014-01-14 20:12:06.572628997 -0500
@@ -0,0 +1,69 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# Use print() on userland CTF types and verify we get the data we expect.
+#
+
+if [ $# != 1 ]; then
+        echo expected one argument: '<'dtrace-path'>'
+        exit 2
+fi
+
+dtrace=$1
+t="final_fantasy_info_t"
+exe="tst.printtype.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf' 
+if [[ $? -ne 0 ]]; then
+	echo "CTF does not exist in $exe, that's a bug" >&2
+	exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -qs /dev/stdin <<EOF
+pid$pid::ff_getgameid:entry
+/next == 0/
+{
+	print(*args[0]);
+	printf("\n");
+	next = 1;
+}
+
+pid$pid::ff_getpartysize:entry
+/next == 1/
+{
+	print(*args[0]);
+	printf("\n");
+	next = 2;
+}
+
+pid$pid::ff_getsummons:entry
+/next == 2/
+{
+	print(*args[0]);
+	printf("\n");
+	exit(0);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
--- /dev/null	2014-01-14 20:12:06.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.pidprinttarg.ksh	2014-01-14 20:12:06.797276558 -0500
@@ -0,0 +1,70 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# Use print() on userland CTF types and verify we get the data we
+# expect. This time, use $target to make sure that path works correctly.
+#
+
+if [ $# != 1 ]; then
+        echo expected one argument: '<'dtrace-path'>'
+        exit 2
+fi
+
+dtrace=$1
+t="final_fantasy_info_t"
+exe="tst.printtype.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf' 
+if [[ $? -ne 0 ]]; then
+	echo "CTF does not exist in $exe, that's a bug" >&2
+	exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -p $pid -qs /dev/stdin <<EOF
+pid\$target::ff_getgameid:entry
+/next == 0/
+{
+	print(*args[0]);
+	printf("\n");
+	next = 1;
+}
+
+pid\$target::ff_getpartysize:entry
+/next == 1/
+{
+	print(*args[0]);
+	printf("\n");
+	next = 2;
+}
+
+pid\$target::ff_getsummons:entry
+/next == 2/
+{
+	print(*args[0]);
+	printf("\n");
+	exit(0);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
--- /dev/null	2014-01-14 20:12:07.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.printtype.c	2014-01-14 20:12:07.032553044 -0500
@@ -0,0 +1,72 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 (c) Joyent, Inc. All rights reserved.
+ */
+
+/*
+ * The point of this is to use print() on various functions to make sure that we
+ * can print basic structures. Note that we purposefully are making sure that
+ * there are no pointers here.
+ */
+#include <unistd.h>
+
+typedef struct final_fantasy_info {
+	int ff_gameid;
+	int ff_partysize;
+	int ff_hassummons;
+} final_fantasy_info_t;
+
+static int
+ff_getgameid(final_fantasy_info_t *f)
+{
+	return (0);
+}
+
+static int
+ff_getpartysize(final_fantasy_info_t *f)
+{
+	return (0);
+}
+
+static int
+ff_getsummons(final_fantasy_info_t *f)
+{
+	return (0);
+}
+
+int
+main(void)
+{
+	final_fantasy_info_t ffiii, ffx, ffi;
+
+	ffi.ff_gameid = 1;
+	ffi.ff_partysize = 4;
+	ffi.ff_hassummons = 0;
+
+	ffiii.ff_gameid = 6;
+	ffiii.ff_partysize = 4;
+	ffiii.ff_hassummons = 1;
+
+	ffx.ff_gameid = 10;
+	ffx.ff_partysize = 3;
+	ffx.ff_hassummons = 1;
+
+	for (;;) {
+		ff_getgameid(&ffi);
+		ff_getpartysize(&ffx);
+		ff_getsummons(&ffiii);
+		sleep(1);
+	}
+	/*NOTREACHED*/
+	return (0);
+}
--- /dev/null	2014-01-14 20:12:07.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.printtype.ksh	2014-01-14 20:12:07.260776215 -0500
@@ -0,0 +1,69 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# Use print() on userland CTF types and verify we get the data we expect.
+#
+
+if [ $# != 1 ]; then
+        echo expected one argument: '<'dtrace-path'>'
+        exit 2
+fi
+
+dtrace=$1
+t="final_fantasy_info_t"
+exe="tst.printtype.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf' 
+if [[ $? -ne 0 ]]; then
+	echo "CTF does not exist in $exe, that's a bug" >&2
+	exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -qs /dev/stdin <<EOF
+pid$pid::ff_getgameid:entry
+/next == 0/
+{
+	print(*(pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t))));
+	printf("\n");
+	next = 1;
+}
+
+pid$pid::ff_getpartysize:entry
+/next == 1/
+{
+	print(*(pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t))));
+	printf("\n");
+	next = 2;
+}
+
+pid$pid::ff_getsummons:entry
+/next == 2/
+{
+	print(*(pid$pid\`$t *)(copyin(arg0, sizeof (pid$pid\`$t))));
+	printf("\n");
+	exit(0);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
--- /dev/null	2014-01-14 20:12:07.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.printtype.ksh.out	2014-01-14 20:12:07.489842635 -0500
@@ -0,0 +1,16 @@
+final_fantasy_info_t {
+    int ff_gameid = 0x1
+    int ff_partysize = 0x4
+    int ff_hassummons = 0
+}
+final_fantasy_info_t {
+    int ff_gameid = 0xa
+    int ff_partysize = 0x3
+    int ff_hassummons = 0x1
+}
+final_fantasy_info_t {
+    int ff_gameid = 0x6
+    int ff_partysize = 0x4
+    int ff_hassummons = 0x1
+}
+
--- /dev/null	2014-01-14 20:12:07.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.printtypetarg.ksh	2014-01-14 20:12:07.719894115 -0500
@@ -0,0 +1,70 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# Use print() on userland CTF types and verify we get the data we
+# expect. Use the pid` alias for $target.
+#
+
+if [ $# != 1 ]; then
+        echo expected one argument: '<'dtrace-path'>'
+        exit 2
+fi
+
+dtrace=$1
+t="final_fantasy_info_t"
+exe="tst.printtype.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf' 
+if [[ $? -ne 0 ]]; then
+	echo "CTF does not exist in $exe, that's a bug" >&2
+	exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -p $pid -qs /dev/stdin <<EOF
+pid\$target::ff_getgameid:entry
+/next == 0/
+{
+	print(*(pid\`$t *)(copyin(arg0, sizeof (pid\`$t))));
+	printf("\n");
+	next = 1;
+}
+
+pid\$target::ff_getpartysize:entry
+/next == 1/
+{
+	print(*(pid\`$t *)(copyin(arg0, sizeof (pid\`$t))));
+	printf("\n");
+	next = 2;
+}
+
+pid\$target::ff_getsummons:entry
+/next == 2/
+{
+	print(*(pid\`$t *)(copyin(arg0, sizeof (pid\`$t))));
+	printf("\n");
+	exit(0);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
--- /dev/null	2014-01-14 20:12:07.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh	2014-01-14 20:12:07.951296482 -0500
@@ -0,0 +1,83 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# Simple test that if we manually use the userland keyword that it
+# works.
+#
+
+if [ $# != 1 ]; then
+        echo expected one argument: '<'dtrace-path'>'
+        exit 2
+fi
+
+dtrace=$1
+t="zelda_info_t"
+exe="tst.chasestrings.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf' 
+if [[ $? -ne 0 ]]; then
+	echo "CTF does not exist in $exe, that's a bug" >&2
+	exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -32 -qs /dev/stdin <<EOF
+typedef struct info {
+        char    *zi_gamename;
+        int     zi_ndungeons;
+        char    *zi_villain;
+        int     zi_haszelda;
+} info_t;
+
+pid$pid::has_princess:entry
+/next == 0/
+{
+	this->t = (userland info_t *)arg0;
+	printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+	    stringof(this->t->zi_gamename), this->t->zi_ndungeons,
+	    stringof(this->t->zi_villain), this->t->zi_haszelda);
+	next = 1;
+}
+
+pid$pid::has_dungeons:entry
+/next == 1/
+{
+	this->t = (userland info_t *)arg0;
+	printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+	    stringof(this->t->zi_gamename), this->t->zi_ndungeons,
+	    stringof(this->t->zi_villain), this->t->zi_haszelda);
+	next = 2;
+}
+
+pid$pid::has_villain:entry
+/next == 2/
+{
+	this->t = (userland info_t *)arg0;
+	printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+	    stringof(this->t->zi_gamename), this->t->zi_ndungeons,
+	    stringof(this->t->zi_villain), this->t->zi_haszelda);
+	exit(0);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
--- /dev/null	2014-01-14 20:12:08.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.userlandkey.ksh.out	2014-01-14 20:12:08.183820785 -0500
@@ -0,0 +1,4 @@
+game: Ocarina of Time, dungeon: 10, villain: Ganondorf, zelda: 1
+game: Link's Awakening, dungeon: 9, villain: Nightmare, zelda: 0
+game: A Link to the Past, dungeon: 12, villain: Ganon, zelda: 1
+
--- /dev/null	2014-01-14 20:12:08.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.userstrings.ksh	2014-01-14 20:12:08.424528514 -0500
@@ -0,0 +1,72 @@
+#! /usr/bin/ksh
+#
+#
+# This file and its contents are supplied under the terms of the
+# Common Development and Distribution License ("CDDL"), version 1.0.
+# You may only use this file in accordance with the terms of version
+# 1.0 of the CDDL.
+#
+# A full copy of the text of the CDDL should have accompanied this
+# source.  A copy of the CDDL is also available via the Internet at
+# http://www.illumos.org/license/CDDL.
+#
+
+#
+# Copyright (c) 2013 Joyent, Inc. All rights reserved.
+#
+
+#
+# This test is checking that we can read members and that pointers inside
+# members point to valid data that is intelligible, eg. strings.
+#
+
+if [ $# != 1 ]; then
+        echo expected one argument: '<'dtrace-path'>'
+        exit 2
+fi
+
+dtrace=$1
+exe="tst.chasestrings.exe"
+
+elfdump "./$exe" | grep -q '.SUNW_ctf' 
+if [[ $? -ne 0 ]]; then
+	echo "CTF does not exist in $exe, that's a bug" >&2
+	exit 1
+fi
+
+./$exe &
+pid=$!
+
+$dtrace -qs /dev/stdin <<EOF
+pid$pid::has_princess:entry
+/next == 0/
+{
+	printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+	    stringof(args[0]->zi_gamename), args[0]->zi_ndungeons,
+	    stringof(args[0]->zi_villain), args[0]->zi_haszelda);
+	next = 1;
+}
+
+pid$pid::has_dungeons:entry
+/next == 1/
+{
+	printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+	    stringof(args[0]->zi_gamename), args[0]->zi_ndungeons,
+	    stringof(args[0]->zi_villain), args[0]->zi_haszelda);
+	next = 2;
+}
+
+pid$pid::has_villain:entry
+/next == 2/
+{
+	printf("game: %s, dungeon: %d, villain: %s, zelda: %d\n",
+	    stringof(args[0]->zi_gamename), args[0]->zi_ndungeons,
+	    stringof(args[0]->zi_villain), args[0]->zi_haszelda);
+	exit(0);
+}
+EOF
+rc=$?
+
+kill -9 $pid
+
+exit $rc
--- /dev/null	2014-01-14 20:12:08.000000000 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/uctf/tst.userstrings.ksh.out	2014-01-14 20:12:08.655615810 -0500
@@ -0,0 +1,4 @@
+game: Ocarina of Time, dungeon: 10, villain: Ganondorf, zelda: 1
+game: Link's Awakening, dungeon: 9, villain: Nightmare, zelda: 0
+game: A Link to the Past, dungeon: 12, villain: Ganon, zelda: 1
+
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.corruptenv.ksh	2014-01-14 20:12:08.896489047 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.corruptenv.ksh	2014-01-14 20:12:08.932929988 -0500
@@ -60,10 +60,10 @@
 all: main
 
 main: main.o prov.o
-	gcc -o main main.o prov.o
+	gcc -m32 -o main main.o prov.o
 
 main.o: main.c prov.h
-	gcc -c main.c
+	gcc -m32 -c main.c
 
 prov.h: prov.d
 	$dtrace -h -s prov.d
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.dlclose1.ksh	2014-01-14 20:12:09.383729470 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.dlclose1.ksh	2014-01-14 20:12:09.398725058 -0500
@@ -45,17 +45,17 @@
 all: main livelib.so deadlib.so
 
 main: main.o prov.o
-	gcc -o main main.o
+	gcc -m32 -o main main.o
 
 main.o: main.c
-	gcc -c main.c
+	gcc -m32 -c main.c
 
 
 livelib.so: livelib.o prov.o
-	gcc -shared -o livelib.so livelib.o prov.o -lc
+	gcc -m32 -shared -o livelib.so livelib.o prov.o -lc
 
 livelib.o: livelib.c prov.h
-	gcc -c livelib.c
+	gcc -m32 -fPIC -c livelib.c
 
 prov.o: livelib.o prov.d
 	$dtrace -G -s prov.d livelib.o
@@ -65,10 +65,10 @@
 
 
 deadlib.so: deadlib.o
-	gcc -shared -o deadlib.so deadlib.o -lc
+	gcc -m32 -shared -o deadlib.so deadlib.o -lc
 
 deadlib.o: deadlib.c
-	gcc -c deadlib.c
+	gcc -m32 -fPIC -c deadlib.c
 
 clean:
 	rm -f main.o livelib.o prov.o prov.h deadlib.o
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.dlclose2.ksh	2014-01-14 20:12:09.837401222 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.dlclose2.ksh	2014-01-14 20:12:09.850673251 -0500
@@ -40,17 +40,17 @@
 all: main livelib.so deadlib.so
 
 main: main.o prov.o
-	gcc -o main main.o
+	gcc -m32 -o main main.o
 
 main.o: main.c
-	gcc -c main.c
+	gcc -m32 -c main.c
 
 
 livelib.so: livelib.o prov.o
-	gcc -shared -o livelib.so livelib.o prov.o -lc
+	gcc -m32 -shared -o livelib.so livelib.o prov.o -lc
 
 livelib.o: livelib.c prov.h
-	gcc -c livelib.c
+	gcc -m32 -fPIC -c livelib.c
 
 prov.o: livelib.o prov.d
 	$dtrace -G -s prov.d livelib.o
@@ -60,10 +60,10 @@
 
 
 deadlib.so: deadlib.o
-	gcc -shared -o deadlib.so deadlib.o -lc
+	gcc -m32 -shared -o deadlib.so deadlib.o -lc
 
 deadlib.o: deadlib.c
-	gcc -c deadlib.c
+	gcc -m32 -fPIC -c deadlib.c
 
 clean:
 	rm -f main.o livelib.o prov.o prov.h deadlib.o
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.dlclose3.ksh	2014-01-14 20:12:10.438222623 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.dlclose3.ksh	2014-01-14 20:12:10.451425589 -0500
@@ -45,17 +45,17 @@
 all: main livelib.so deadlib.so
 
 main: main.o prov.o
-	gcc -o main main.o
+	gcc -m32 -o main main.o
 
 main.o: main.c
-	gcc -c main.c
+	gcc -m32 -c main.c
 
 
 livelib.so: livelib.o prov.o
-	gcc -shared -o livelib.so livelib.o prov.o -lc
+	gcc -m32 -shared -o livelib.so livelib.o prov.o -lc
 
 livelib.o: livelib.c prov.h
-	gcc -c livelib.c
+	gcc -m32 -fPIC -c livelib.c
 
 prov.o: livelib.o prov.d
 	$dtrace -G -s prov.d livelib.o
@@ -65,10 +65,10 @@
 
 
 deadlib.so: deadlib.o
-	gcc -shared -o deadlib.so deadlib.o -lc
+	gcc -m32 -shared -o deadlib.so deadlib.o -lc
 
 deadlib.o: deadlib.c
-	gcc -c deadlib.c
+	gcc -m32 -fPIC -c deadlib.c
 
 clean:
 	rm -f main.o livelib.o prov.o prov.h deadlib.o
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.eliminate.ksh	2014-01-14 20:12:10.858698801 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.eliminate.ksh	2014-01-14 20:12:10.890688388 -0500
@@ -71,7 +71,7 @@
 }
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -81,7 +81,7 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.enabled.ksh	2014-01-14 20:12:11.396859246 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.enabled.ksh	2014-01-14 20:12:11.410066099 -0500
@@ -60,7 +60,7 @@
 }
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -70,7 +70,7 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.enabled2.ksh	2014-01-14 20:12:11.822144546 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.enabled2.ksh	2014-01-14 20:12:11.853336331 -0500
@@ -76,7 +76,7 @@
 }
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -86,7 +86,8 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.entryreturn.ksh	2014-01-14 20:12:12.303207190 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.entryreturn.ksh	2014-01-14 20:12:12.317721741 -0500
@@ -69,7 +69,7 @@
 };
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -79,7 +79,7 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.fork.ksh	2014-01-14 20:12:12.754442053 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.fork.ksh	2014-01-14 20:12:12.779376007 -0500
@@ -70,7 +70,7 @@
 }
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -80,7 +80,7 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.header.ksh	2014-01-14 20:12:13.210708906 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.header.ksh	2014-01-14 20:12:13.224464256 -0500
@@ -64,7 +64,7 @@
 }
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -74,7 +74,7 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.linkpriv.ksh	2014-01-14 20:12:13.656873821 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.linkpriv.ksh	2014-01-14 20:12:13.671487722 -0500
@@ -61,7 +61,7 @@
 };
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -71,7 +71,7 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.linkunpriv.ksh	2014-01-14 20:12:14.117458816 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.linkunpriv.ksh	2014-01-14 20:12:14.130733270 -0500
@@ -63,7 +63,7 @@
 };
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -73,7 +73,7 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.multiple.ksh	2014-01-14 20:12:14.539474559 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.multiple.ksh	2014-01-14 20:12:14.552758487 -0500
@@ -64,7 +64,7 @@
 }
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -74,7 +74,7 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.multiprov.ksh	2014-01-14 20:12:15.069572045 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.multiprov.ksh	2014-01-14 20:12:15.083120304 -0500
@@ -64,7 +64,7 @@
 };
 EOF
 
-	cc -c $oogle.c
+	gcc -m32 -c $oogle.c
 
 	if [ $? -ne 0 ]; then
 		print -u2 "failed to compile $oogle.c"
@@ -87,7 +87,7 @@
 
 echo 'END{printa("%-10s %@d\\n", @)}' >> test.d
 
-cc -o test test.c $objs
+gcc -m32 -o test test.c $objs
 
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.noprobes.ksh	2014-01-14 20:12:15.574066963 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.noprobes.ksh	2014-01-14 20:12:15.587463505 -0500
@@ -46,7 +46,7 @@
 };
 EOF
 
-cc -c test.c
+gcc -m32 -c test.c
 $dtrace -G -32 -s doogle.d test.o -o doogle.d.o
 
 if [ $? -eq 0 ]; then
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.noreap.ksh	2014-01-14 20:12:16.001778611 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.noreap.ksh	2014-01-14 20:12:16.029742760 -0500
@@ -51,7 +51,7 @@
 };
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -61,7 +61,8 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.noreapring.ksh	2014-01-14 20:12:16.480176521 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.noreapring.ksh	2014-01-14 20:12:16.494576387 -0500
@@ -51,7 +51,7 @@
 };
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -61,7 +61,8 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.onlyenabled.ksh	2014-01-14 20:12:16.932454632 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.onlyenabled.ksh	2014-01-14 20:12:16.957723694 -0500
@@ -61,7 +61,7 @@
 }
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -71,7 +71,7 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.reap.ksh	2014-01-14 20:12:17.386790550 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.reap.ksh	2014-01-14 20:12:17.401239567 -0500
@@ -51,7 +51,7 @@
 };
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -61,7 +61,8 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.reeval.ksh	2014-01-14 20:12:17.850615844 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.reeval.ksh	2014-01-14 20:12:17.865456625 -0500
@@ -51,7 +51,7 @@
 };
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -61,7 +61,7 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.static.ksh	2014-01-14 20:12:18.340731822 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.static.ksh	2014-01-14 20:12:18.356996667 -0500
@@ -62,7 +62,7 @@
 };
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -72,7 +72,7 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.static2.ksh	2014-01-14 20:12:18.809797585 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.static2.ksh	2014-01-14 20:12:18.835674116 -0500
@@ -66,7 +66,7 @@
 };
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -82,7 +82,7 @@
 	print -u2 "failed to create final DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/common/usdt/tst.user.ksh	2014-01-14 20:12:19.266702596 -0500
+++ new/usr/src/cmd/dtrace/test/tst/common/usdt/tst.user.ksh	2014-01-14 20:12:19.287418058 -0500
@@ -61,7 +61,7 @@
 }
 EOF
 
-gcc -c test.c
+gcc -m32 -c test.c
 if [ $? -ne 0 ]; then
 	print -u2 "failed to compile test.c"
 	exit 1
@@ -71,7 +71,7 @@
 	print -u2 "failed to create DOF"
 	exit 1
 fi
-gcc -o test test.o prov.o
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/cmd/dtrace/test/tst/sparc/usdt/tst.tailcall.ksh	2014-01-14 20:12:19.730955330 -0500
+++ new/usr/src/cmd/dtrace/test/tst/sparc/usdt/tst.tailcall.ksh	2014-01-14 20:12:19.745358230 -0500
@@ -87,7 +87,7 @@
 	exit 1
 fi
 
-gcc -o test test.o prov.o
+gcc -m32 -o test test.o prov.o
 if [ $? -ne 0 ]; then
 	print -u2 "failed to link final executable"
 	exit 1
--- old/usr/src/common/ctf/ctf_open.c	2014-01-14 20:12:20.469498660 -0500
+++ new/usr/src/common/ctf/ctf_open.c	2014-01-14 20:12:20.483202787 -0500
@@ -25,7 +25,7 @@
  * Use is subject to license terms.
  */
 /*
- * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
  */
 
 #include <ctf_impl.h>
@@ -788,6 +788,92 @@
 }
 
 /*
+ * Dupliate a ctf_file_t and its underlying section information into a new
+ * container. This works by copying the three ctf_sect_t's of the original
+ * container if they exist and passing those into ctf_bufopen. To copy those, we
+ * mmap anonymous memory with ctf_data_alloc and bcopy the data across. It's not
+ * the cheapest thing, but it's what we've got.
+ */
+ctf_file_t *
+ctf_dup(ctf_file_t *ofp)
+{
+	ctf_file_t *fp;
+	ctf_sect_t ctfsect, symsect, strsect;
+	ctf_sect_t *ctp, *symp, *strp;
+	void *cbuf, *symbuf, *strbuf;
+	int err;
+
+	cbuf = symbuf = strbuf = NULL;
+	/*
+	 * The ctfsect isn't allowed to not exist, but the symbol and string
+	 * section might not. We only need to copy the data of the section, not
+	 * the name, as ctf_bufopen will take care of that.
+	 */
+	bcopy(&ofp->ctf_data, &ctfsect, sizeof (ctf_sect_t));
+	cbuf = ctf_data_alloc(ctfsect.cts_size);
+	if (cbuf == NULL) {
+		(void) ctf_set_errno(ofp, ECTF_MMAP);
+		return (NULL);
+	}
+
+	bcopy(ctfsect.cts_data, cbuf, ctfsect.cts_size);
+	ctf_data_protect(cbuf, ctfsect.cts_size);
+	ctfsect.cts_data = cbuf;
+	ctfsect.cts_offset = 0;
+	ctp = &ctfsect;
+
+	if (ofp->ctf_symtab.cts_data != NULL) {
+		bcopy(&ofp->ctf_symtab, &symsect, sizeof (ctf_sect_t));
+		symbuf = ctf_data_alloc(symsect.cts_size);
+		if (symbuf == NULL) {
+			(void) ctf_set_errno(ofp, ECTF_MMAP);
+			goto err;
+		}
+		bcopy(symsect.cts_data, symbuf, symsect.cts_size);
+		ctf_data_protect(symbuf, symsect.cts_size);
+		symsect.cts_data = symbuf;
+		symsect.cts_offset = 0;
+		symp = &symsect;
+	} else {
+		symp = NULL;
+	}
+
+	if (ofp->ctf_strtab.cts_data != NULL) {
+		bcopy(&ofp->ctf_strtab, &strsect, sizeof (ctf_sect_t));
+		strbuf = ctf_data_alloc(strsect.cts_size);
+		if (strbuf == NULL) {
+			(void) ctf_set_errno(ofp, ECTF_MMAP);
+			goto err;
+		}
+		bcopy(strsect.cts_data, strbuf, strsect.cts_size);
+		ctf_data_protect(strbuf, strsect.cts_size);
+		strsect.cts_data = strbuf;
+		strsect.cts_offset = 0;
+		strp = &strsect;
+	} else {
+		strp = NULL;
+	}
+
+	fp = ctf_bufopen(ctp, symp, strp, &err);
+	if (fp == NULL) {
+		(void) ctf_set_errno(ofp, err);
+		goto err;
+	}
+
+	fp->ctf_flags |= LCTF_MMAP;
+
+	return (fp);
+
+err:
+	ctf_data_free(cbuf, ctfsect.cts_size);
+	if (symbuf != NULL)
+		ctf_data_free(symbuf, symsect.cts_size);
+	if (strbuf != NULL)
+		ctf_data_free(strbuf, strsect.cts_size);
+	return (NULL);
+}
+
+/*
  * Close the specified CTF container and free associated data structures.  Note
  * that ctf_close() is a reference counted operation: if the specified file is
  * the parent of other active containers, its reference count will be greater
--- old/usr/src/common/ctf/ctf_types.c	2014-01-14 20:12:20.973610356 -0500
+++ new/usr/src/common/ctf/ctf_types.c	2014-01-14 20:12:20.987860644 -0500
@@ -25,8 +25,6 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <ctf_impl.h>
 
 ssize_t
@@ -199,8 +197,9 @@
  * Lookup the given type ID and print a string name for it into buf.  Return
  * the actual number of bytes (not including \0) needed to format the name.
  */
-ssize_t
-ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
+static ssize_t
+ctf_type_qlname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
+    const char *qname)
 {
 	ctf_decl_t cd;
 	ctf_decl_node_t *cdp;
@@ -255,6 +254,8 @@
 			case CTF_K_INTEGER:
 			case CTF_K_FLOAT:
 			case CTF_K_TYPEDEF:
+				if (qname != NULL)
+					ctf_decl_sprintf(&cd, "%s`", qname);
 				ctf_decl_sprintf(&cd, "%s", name);
 				break;
 			case CTF_K_POINTER:
@@ -268,13 +269,22 @@
 				break;
 			case CTF_K_STRUCT:
 			case CTF_K_FORWARD:
-				ctf_decl_sprintf(&cd, "struct %s", name);
+				ctf_decl_sprintf(&cd, "struct ");
+				if (qname != NULL)
+					ctf_decl_sprintf(&cd, "%s`", qname);
+				ctf_decl_sprintf(&cd, "%s", name);
 				break;
 			case CTF_K_UNION:
-				ctf_decl_sprintf(&cd, "union %s", name);
+				ctf_decl_sprintf(&cd, "union ");
+				if (qname != NULL)
+					ctf_decl_sprintf(&cd, "%s`", qname);
+				ctf_decl_sprintf(&cd, "%s", name);
 				break;
 			case CTF_K_ENUM:
-				ctf_decl_sprintf(&cd, "enum %s", name);
+				ctf_decl_sprintf(&cd, "enum ");
+				if (qname != NULL)
+					ctf_decl_sprintf(&cd, "%s`", qname);
+				ctf_decl_sprintf(&cd, "%s", name);
 				break;
 			case CTF_K_VOLATILE:
 				ctf_decl_sprintf(&cd, "volatile");
@@ -301,6 +311,12 @@
 	return (cd.cd_len);
 }
 
+ssize_t
+ctf_type_lname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
+{
+	return (ctf_type_qlname(fp, type, buf, len, NULL));
+}
+
 /*
  * Lookup the given type ID and print a string name for it into buf.  If buf
  * is too small, return NULL: the ECTF_NAMELEN error is set on 'fp' for us.
@@ -308,10 +324,19 @@
 char *
 ctf_type_name(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len)
 {
-	ssize_t rv = ctf_type_lname(fp, type, buf, len);
+	ssize_t rv = ctf_type_qlname(fp, type, buf, len, NULL);
+	return (rv >= 0 && rv < len ? buf : NULL);
+}
+
+char *
+ctf_type_qname(ctf_file_t *fp, ctf_id_t type, char *buf, size_t len,
+    const char *qname)
+{
+	ssize_t rv = ctf_type_qlname(fp, type, buf, len, qname);
 	return (rv >= 0 && rv < len ? buf : NULL);
 }
 
+
 /*
  * Resolve the type down to a base type node, and then return the size
  * of the type storage in bytes.
--- old/usr/src/lib/libctf/common/mapfile-vers	2014-01-14 20:12:21.559438067 -0500
+++ new/usr/src/lib/libctf/common/mapfile-vers	2014-01-14 20:12:21.589519355 -0500
@@ -23,6 +23,10 @@
 #
 
 #
+# Copyright (c) 2013, Joyent, Inc.  All rights reserved.
+#
+
+#
 # MAPFILE HEADER START
 #
 # WARNING:  STOP NOW.  DO NOT MODIFY THIS FILE.
@@ -62,6 +66,7 @@
 	ctf_create;
 	ctf_delete_type;
 	ctf_discard;
+	ctf_dup;
 	ctf_enum_value;
 	ctf_label_info;
 	ctf_label_iter;
@@ -104,6 +109,7 @@
 	ctf_type_kind;
 	ctf_type_lname;
 	ctf_type_name;
+	ctf_type_qname;
 	ctf_type_reference;
 	ctf_type_resolve;
 	ctf_type_size;
--- old/usr/src/lib/libdtrace/common/dt_as.c	2014-01-14 20:12:22.037994841 -0500
+++ new/usr/src/lib/libdtrace/common/dt_as.c	2014-01-14 20:12:22.066053275 -0500
@@ -23,8 +23,10 @@
  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
 
 #include <sys/types.h>
 #include <strings.h>
@@ -125,7 +127,7 @@
 		dvp->dtdv_flags |= DIFV_F_MOD;
 
 	bzero(&dn, sizeof (dn));
-	dt_node_type_assign(&dn, idp->di_ctfp, idp->di_type);
+	dt_node_type_assign(&dn, idp->di_ctfp, idp->di_type, B_FALSE);
 	dt_node_diftype(pcb->pcb_hdl, &dn, &dvp->dtdv_type);
 
 	idp->di_flags &= ~(DT_IDFLG_DIFR | DT_IDFLG_DIFW);
--- old/usr/src/lib/libdtrace/common/dt_cc.c	2014-01-14 20:12:22.542704521 -0500
+++ new/usr/src/lib/libdtrace/common/dt_cc.c	2014-01-14 20:12:22.572327114 -0500
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent Inc. All rights reserved.
  * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
@@ -662,6 +662,8 @@
 static void
 dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
 {
+	int ctflib;
+
 	dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
 	boolean_t istrace = (dnp->dn_ident->di_id == DT_ACT_TRACE);
 	const char *act = istrace ?  "trace" : "print";
@@ -693,7 +695,10 @@
 	 * like arrays and function pointers that can't be resolved by
 	 * ctf_type_lookup().  This is later processed by dtrace_dof_create()
 	 * and turned into a reference into the string table so that we can
-	 * get the type information when we process the data after the fact.
+	 * get the type information when we process the data after the fact.  In
+	 * the case where we are referring to userland CTF data, we also need to
+	 * to identify which ctf container in question we care about and encode
+	 * that within the name.
 	 */
 	if (dnp->dn_ident->di_id == DT_ACT_PRINT) {
 		dt_node_t *dret;
@@ -703,12 +708,25 @@
 		dret = yypcb->pcb_dret;
 		dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
 
-		n = snprintf(NULL, 0, "%s`%d", dmp->dm_name, dret->dn_type) + 1;
+		if (dmp->dm_pid != 0) {
+			ctflib = dt_module_getlibid(dtp, dmp, dret->dn_ctfp);
+			assert(ctflib >= 0);
+			n = snprintf(NULL, 0, "%s`%d`%d", dmp->dm_name,
+			    ctflib, dret->dn_type) + 1;
+		} else {
+			n = snprintf(NULL, 0, "%s`%d", dmp->dm_name,
+			    dret->dn_type) + 1;
+		}
 		sdp->dtsd_strdata = dt_alloc(dtp, n);
 		if (sdp->dtsd_strdata == NULL)
 			longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
-		(void) snprintf(sdp->dtsd_strdata, n, "%s`%d", dmp->dm_name,
-		    dret->dn_type);
+		if (dmp->dm_pid != 0) {
+			(void) snprintf(sdp->dtsd_strdata, n, "%s`%d`%d",
+			    dmp->dm_name, ctflib, dret->dn_type);
+		} else {
+			(void) snprintf(sdp->dtsd_strdata, n, "%s`%d",
+			    dmp->dm_name, dret->dn_type);
+		}
 	}
 
 	ap->dtad_difo = dt_as(yypcb);
--- old/usr/src/lib/libdtrace/common/dt_decl.c	2014-01-14 20:12:23.200048018 -0500
+++ new/usr/src/lib/libdtrace/common/dt_decl.c	2014-01-14 20:12:23.215779033 -0500
@@ -21,7 +21,8 @@
 
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
  */
 
 #include <strings.h>
@@ -775,7 +776,7 @@
 	yyintdecimal = 0;
 
 	dnp = dt_node_int(value);
-	dt_node_type_assign(dnp, dsp->ds_ctfp, dsp->ds_type);
+	dt_node_type_assign(dnp, dsp->ds_ctfp, dsp->ds_type, B_FALSE);
 
 	if ((inp = malloc(sizeof (dt_idnode_t))) == NULL)
 		longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
@@ -817,6 +818,8 @@
 	char *name;
 	int rv;
 
+	tip->dtt_flags = 0;
+
 	/*
 	 * Based on our current #include depth and decl stack depth, determine
 	 * which dynamic CTF module and scope to use when adding any new types.
@@ -824,6 +827,9 @@
 	dmp = yypcb->pcb_idepth ? dtp->dt_cdefs : dtp->dt_ddefs;
 	flag = yypcb->pcb_dstack.ds_next ? CTF_ADD_NONROOT : CTF_ADD_ROOT;
 
+	if (ddp->dd_attr & DT_DA_USER)
+		tip->dtt_flags = DTT_FL_USER;
+
 	/*
 	 * If we have already cached a CTF type for this decl, then we just
 	 * return the type information for the cached type.
--- old/usr/src/lib/libdtrace/common/dt_decl.h	2014-01-14 20:12:23.726588375 -0500
+++ new/usr/src/lib/libdtrace/common/dt_decl.h	2014-01-14 20:12:23.747436960 -0500
@@ -23,12 +23,14 @@
  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
 
 #ifndef	_DT_DECL_H
 #define	_DT_DECL_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <libctf.h>
 #include <dtrace.h>
@@ -59,6 +61,7 @@
 #define	DT_DA_RESTRICT	0x0040		/* qualify type as restrict */
 #define	DT_DA_VOLATILE	0x0080		/* qualify type as volatile */
 #define	DT_DA_PAREN	0x0100		/* parenthesis tag */
+#define	DT_DA_USER	0x0200		/* user-land type specifier */
 
 typedef enum dt_dclass {
 	DT_DC_DEFAULT,			/* no storage class specified */
--- old/usr/src/lib/libdtrace/common/dt_dis.c	2014-01-14 20:12:24.163005795 -0500
+++ new/usr/src/lib/libdtrace/common/dt_dis.c	2014-01-14 20:12:24.176463365 -0500
@@ -26,7 +26,8 @@
  */
 
 /*
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
  */
 
 #include <strings.h>
@@ -312,9 +313,10 @@
 		(void) snprintf(ckind, sizeof (ckind), "0x%x", t->dtdt_ckind);
 	}
 
-	if (t->dtdt_flags & DIF_TF_BYREF) {
-		(void) snprintf(buf, len, "%s (%s) by ref (size %lu)",
-		    kind, ckind, (ulong_t)t->dtdt_size);
+	if (t->dtdt_flags & (DIF_TF_BYREF | DIF_TF_BYUREF)) {
+		(void) snprintf(buf, len, "%s (%s) by %sref (size %lu)",
+		    kind, ckind, (t->dtdt_flags & DIF_TF_BYUREF) ? "user " : "",
+		    (ulong_t)t->dtdt_size);
 	} else {
 		(void) snprintf(buf, len, "%s (%s) (size %lu)",
 		    kind, ckind, (ulong_t)t->dtdt_size);
--- old/usr/src/lib/libdtrace/common/dt_error.c	2014-01-14 20:12:24.615041630 -0500
+++ new/usr/src/lib/libdtrace/common/dt_error.c	2014-01-14 20:12:24.628463144 -0500
@@ -110,7 +110,8 @@
 	{ EDT_BADAGGVAR, "Invalid aggregation variable identifier" },
 	{ EDT_OVERSION,	"Client requested deprecated version of library" },
 	{ EDT_ENABLING_ERR, "Failed to enable probe" },
-	{ EDT_NOPROBES, "No probe sites found for declared provider" }
+	{ EDT_NOPROBES, "No probe sites found for declared provider" },
+	{ EDT_CANTLOAD, "Failed to load module" },
 };
 
 static const int _dt_nerr = sizeof (_dt_errlist) / sizeof (_dt_errlist[0]);
--- old/usr/src/lib/libdtrace/common/dt_grammar.y	2014-01-14 20:12:25.107813525 -0500
+++ new/usr/src/lib/libdtrace/common/dt_grammar.y	2014-01-14 20:12:25.180747141 -0500
@@ -23,8 +23,10 @@
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
 
 #include <dt_impl.h>
 
@@ -102,6 +104,7 @@
 %token	DT_KEY_TYPEDEF
 %token	DT_KEY_UNION
 %token	DT_KEY_UNSIGNED
+%token	DT_KEY_USERLAND
 %token	DT_KEY_VOID
 %token	DT_KEY_VOLATILE
 %token	DT_KEY_WHILE
@@ -633,6 +636,7 @@
 	|	DT_KEY_DOUBLE { $$ = dt_decl_spec(CTF_K_FLOAT, DUP("double")); }
 	|	DT_KEY_SIGNED { $$ = dt_decl_attr(DT_DA_SIGNED); }
 	|	DT_KEY_UNSIGNED { $$ = dt_decl_attr(DT_DA_UNSIGNED); }
+	|	DT_KEY_USERLAND { $$ = dt_decl_attr(DT_DA_USER); }
 	|	DT_KEY_STRING {
 			$$ = dt_decl_spec(CTF_K_TYPEDEF, DUP("string"));
 		}
--- old/usr/src/lib/libdtrace/common/dt_ident.c	2014-01-14 20:12:25.706637117 -0500
+++ new/usr/src/lib/libdtrace/common/dt_ident.c	2014-01-14 20:12:25.721896685 -0500
@@ -21,6 +21,8 @@
 
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
  */
 
 #include <sys/sysmacros.h>
@@ -95,7 +97,7 @@
 		}
 	}
 
-	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
 }
 
 /*
@@ -154,7 +156,7 @@
 		if (argc != 0)
 			isp->dis_args[argc - 1].dn_list = NULL;
 
-		dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+		dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
 
 	} else {
 		dt_idcook_sign(dnp, idp, argc, args,
@@ -294,7 +296,7 @@
 			}
 
 			dt_node_type_assign(&isp->dis_args[i],
-			    dtt.dtt_ctfp, dtt.dtt_type);
+			    dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
 		}
 	}
 
@@ -381,7 +383,9 @@
 
 		dt_node_type_assign(dnp,
 		    prp->pr_argv[ap->dn_value].dtt_ctfp,
-		    prp->pr_argv[ap->dn_value].dtt_type);
+		    prp->pr_argv[ap->dn_value].dtt_type,
+		    prp->pr_argv[ap->dn_value].dtt_flags & DTT_FL_USER ?
+		    B_TRUE : B_FALSE);
 
 	} else if ((dxp = dt_xlator_lookup(dtp,
 	    nnp, xnp, DT_XLATE_FUZZY)) != NULL || (
@@ -409,7 +413,8 @@
 		dnp->dn_ident->di_ctfp = xidp->di_ctfp;
 		dnp->dn_ident->di_type = xidp->di_type;
 
-		dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+		dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
+		    B_FALSE);
 
 	} else {
 		xyerror(D_ARGS_XLATOR, "translator for %s[%lld] from %s to %s "
@@ -455,7 +460,7 @@
 	idp->di_ctfp = dtt.dtt_ctfp;
 	idp->di_type = dtt.dtt_type;
 
-	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
 }
 
 /*ARGSUSED*/
@@ -477,7 +482,7 @@
 		idp->di_type = dtt.dtt_type;
 	}
 
-	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+	dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
 }
 
 /*ARGSUSED*/
@@ -485,7 +490,7 @@
 dt_idcook_thaw(dt_node_t *dnp, dt_ident_t *idp, int argc, dt_node_t *args)
 {
 	if (idp->di_ctfp != NULL && idp->di_type != CTF_ERR)
-		dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type);
+		dt_node_type_assign(dnp, idp->di_ctfp, idp->di_type, B_FALSE);
 }
 
 static void
--- old/usr/src/lib/libdtrace/common/dt_impl.h	2014-01-14 20:12:26.337845791 -0500
+++ new/usr/src/lib/libdtrace/common/dt_impl.h	2014-01-14 20:12:26.352746789 -0500
@@ -133,6 +133,10 @@
 	GElf_Addr dm_bss_va;	/* virtual address of BSS */
 	GElf_Xword dm_bss_size;	/* size in bytes of BSS */
 	dt_idhash_t *dm_extern;	/* external symbol definitions */
+	pid_t dm_pid;		/* pid for this module */
+	uint_t dm_nctflibs;	/* number of ctf children libraries */
+	ctf_file_t **dm_libctfp; /* process library ctf pointers */
+	char **dm_libctfn;	/* names of process ctf containers */
 } dt_module_t;
 
 #define	DT_DM_LOADED	0x1	/* module symbol and type data is loaded */
@@ -513,7 +517,8 @@
 	EDT_BADAGGVAR,		/* invalid aggregation variable identifier */
 	EDT_OVERSION,		/* client is requesting deprecated version */
 	EDT_ENABLING_ERR,	/* failed to enable probe */
-	EDT_NOPROBES		/* no probes sites for declared provider */
+	EDT_NOPROBES,		/* no probes sites for declared provider */
+	EDT_CANTLOAD		/* failed to load a module */
 };
 
 /*
--- old/usr/src/lib/libdtrace/common/dt_lex.l	2014-01-14 20:12:26.847568867 -0500
+++ new/usr/src/lib/libdtrace/common/dt_lex.l	2014-01-14 20:12:26.864293153 -0500
@@ -23,6 +23,10 @@
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  */
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ */
 
 #include <string.h>
 #include <stdlib.h>
@@ -60,13 +64,17 @@
 %}
 
 %e 1500		/* maximum nodes */
-%p 3700		/* maximum positions */
+%p 4900		/* maximum positions */
 %n 600		/* maximum states */
+%a 3000		/* maximum transitions */
 
 %s S0 S1 S2 S3 S4
 
 RGX_AGG		"@"[a-zA-Z_][0-9a-zA-Z_]*
 RGX_PSPEC	[-$:a-zA-Z_.?*\\\[\]!][-$:0-9a-zA-Z_.`?*\\\[\]!]*
+RGX_ALTIDENT	[a-zA-Z_][0-9a-zA-Z_]*
+RGX_LMID	LM[0-9a-fA-F]+`
+RGX_MOD_IDENT	[a-zA-Z_`][0-9a-z.A-Z_`]*`
 RGX_IDENT	[a-zA-Z_`][0-9a-zA-Z_`]*
 RGX_INT		([0-9]+|0[xX][0-9A-Fa-f]+)[uU]?[lL]?[lL]?
 RGX_FP		([0-9]+("."?)[0-9]*|"."[0-9]+)((e|E)("+"|-)?[0-9]+)?[fFlL]?
@@ -136,6 +144,7 @@
 <S0>typedef	return (DT_KEY_TYPEDEF);
 <S0>union	return (DT_KEY_UNION);
 <S0>unsigned	return (DT_KEY_UNSIGNED);
+<S0>userland	return (DT_KEY_USERLAND);
 <S0>void	return (DT_KEY_VOID);
 <S0>volatile	return (DT_KEY_VOLATILE);
 <S0>while	return (DT_KEY_WHILE);
@@ -314,7 +323,9 @@
 			return (DT_TOK_INT);
 		}
 
-<S0>{RGX_IDENT}	{
+<S0>{RGX_IDENT} |
+<S0>{RGX_MOD_IDENT}{RGX_IDENT} |
+<S0>{RGX_MOD_IDENT} {
 			return (id_or_type(yytext));
 		}
 
--- old/usr/src/lib/libdtrace/common/dt_module.c	2014-01-14 20:12:27.386917832 -0500
+++ new/usr/src/lib/libdtrace/common/dt_module.c	2014-01-14 20:12:27.402789487 -0500
@@ -22,6 +22,9 @@
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  */
+/*
+ * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
+ */
 
 #include <sys/types.h>
 #include <sys/modctl.h>
@@ -418,6 +421,9 @@
 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;
 
@@ -441,6 +447,32 @@
 	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);
 }
 
@@ -504,12 +536,169 @@
 	return (0);
 }
 
+typedef struct dt_module_cb_arg {
+	struct ps_prochandle *dpa_proc;
+	dtrace_hdl_t *dpa_dtp;
+	dt_module_t *dpa_dmp;
+	uint_t dpa_count;
+} dt_module_cb_arg_t;
+
+/* ARGSUSED */
+static int
+dt_module_load_proc_count(void *arg, const prmap_t *prmap, const char *obj)
+{
+	ctf_file_t *fp;
+	dt_module_cb_arg_t *dcp = arg;
+
+	/* Try to grab a ctf container if it exists */
+	fp = Pname_to_ctf(dcp->dpa_proc, obj);
+	if (fp != NULL)
+		dcp->dpa_count++;
+	return (0);
+}
+
+/* ARGSUSED */
+static int
+dt_module_load_proc_build(void *arg, const prmap_t *prmap, const char *obj)
+{
+	ctf_file_t *fp;
+	char buf[MAXPATHLEN], *p;
+	dt_module_cb_arg_t *dcp = arg;
+	int count = dcp->dpa_count;
+	Lmid_t lmid;
+
+	fp = Pname_to_ctf(dcp->dpa_proc, obj);
+	if (fp == NULL)
+		return (0);
+	fp = ctf_dup(fp);
+	if (fp == NULL)
+		return (0);
+	dcp->dpa_dmp->dm_libctfp[count] = fp;
+	/*
+	 * While it'd be nice to simply use objname here, because of our prior
+	 * actions we'll always get a resolved object name to its on disk file.
+	 * Like the pid provider, we need to tell a bit of a lie here. The type
+	 * that the user thinks of is in terms of the libraries they requested,
+	 * eg. libc.so.1, they don't care about the fact that it's
+	 * libc_hwcap.so.1.
+	 */
+	(void) Pobjname(dcp->dpa_proc, prmap->pr_vaddr, buf, sizeof (buf));
+	if ((p = strrchr(buf, '/')) == NULL)
+		p = buf;
+	else
+		p++;
+
+	/*
+	 * If for some reason we can't find a link map id for this module, which
+	 * would be really quite weird. We instead just say the link map id is
+	 * zero.
+	 */
+	if (Plmid(dcp->dpa_proc, prmap->pr_vaddr, &lmid) != 0)
+		lmid = 0;
+
+	if (lmid == 0)
+		dcp->dpa_dmp->dm_libctfn[count] = strdup(p);
+	else
+		(void) asprintf(&dcp->dpa_dmp->dm_libctfn[count],
+		    "LM%lx`%s", lmid, p);
+	if (dcp->dpa_dmp->dm_libctfn[count] == NULL)
+		return (1);
+	ctf_setspecific(fp, dcp->dpa_dmp);
+	dcp->dpa_count++;
+	return (0);
+}
+
+/*
+ * 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);
+}
+
 int
 dt_module_load(dtrace_hdl_t *dtp, dt_module_t *dmp)
 {
 	if (dmp->dm_flags & DT_DM_LOADED)
 		return (0); /* module is already loaded */
 
+	if (dmp->dm_pid != 0)
+		return (dt_module_load_proc(dtp, dmp));
+
 	dmp->dm_ctdata.cts_name = ".SUNW_ctf";
 	dmp->dm_ctdata.cts_type = SHT_PROGBITS;
 	dmp->dm_ctdata.cts_flags = 0;
@@ -595,6 +784,14 @@
 	return (0);
 }
 
+int
+dt_module_hasctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
+{
+	if (dmp->dm_pid != 0 && dmp->dm_nctflibs > 0)
+		return (1);
+	return (dt_module_getctf(dtp, dmp) != NULL);
+}
+
 ctf_file_t *
 dt_module_getctf(dtrace_hdl_t *dtp, dt_module_t *dmp)
 {
@@ -668,9 +865,22 @@
 void
 dt_module_unload(dtrace_hdl_t *dtp, dt_module_t *dmp)
 {
+	int i;
+
 	ctf_close(dmp->dm_ctfp);
 	dmp->dm_ctfp = NULL;
 
+	if (dmp->dm_libctfp != NULL) {
+		for (i = 0; i < dmp->dm_nctflibs; i++) {
+			ctf_close(dmp->dm_libctfp[i]);
+			free(dmp->dm_libctfn[i]);
+		}
+		free(dmp->dm_libctfp);
+		free(dmp->dm_libctfn);
+		dmp->dm_libctfp = NULL;
+		dmp->dm_nctflibs = 0;
+	}
+
 	bzero(&dmp->dm_ctdata, sizeof (ctf_sect_t));
 	bzero(&dmp->dm_symtab, sizeof (ctf_sect_t));
 	bzero(&dmp->dm_strtab, sizeof (ctf_sect_t));
@@ -711,6 +921,8 @@
 	(void) elf_end(dmp->dm_elf);
 	dmp->dm_elf = NULL;
 
+	dmp->dm_pid = 0;
+
 	dmp->dm_flags &= ~DT_DM_LOADED;
 }
 
@@ -799,6 +1011,34 @@
 		return ("32-bit");
 }
 
+/* ARGSUSED */
+int
+dt_module_getlibid(dtrace_hdl_t *dtp, dt_module_t *dmp, const ctf_file_t *fp)
+{
+	int i;
+
+	for (i = 0; i < dmp->dm_nctflibs; i++) {
+		if (dmp->dm_libctfp[i] == fp)
+			return (i);
+	}
+
+	return (-1);
+}
+
+/* ARGSUSED */
+ctf_file_t *
+dt_module_getctflib(dtrace_hdl_t *dtp, dt_module_t *dmp, const char *name)
+{
+	int i;
+
+	for (i = 0; i < dmp->dm_nctflibs; i++) {
+		if (strcmp(dmp->dm_libctfn[i], name) == 0)
+			return (dmp->dm_libctfp[i]);
+	}
+
+	return (NULL);
+}
+
 /*
  * Update our module cache by adding an entry for the specified module 'name'.
  * We create the dt_module_t and populate it using /system/object/<name>/.
@@ -1140,8 +1380,10 @@
 	dt_module_t *dmp;
 	int found = 0;
 	ctf_id_t id;
-	uint_t n;
+	uint_t n, i;
 	int justone;
+	ctf_file_t *fp;
+	char *buf, *p, *q;
 
 	uint_t mask = 0; /* mask of dt_module flags to match */
 	uint_t bits = 0; /* flag bits that must be present */
@@ -1156,7 +1398,6 @@
 			return (-1); /* dt_errno is set for us */
 		n = 1;
 		justone = 1;
-
 	} else {
 		if (object == DTRACE_OBJ_KMODS)
 			mask = bits = DT_DM_KERNEL;
@@ -1180,7 +1421,7 @@
 		 * module.  If our search was scoped to only one module then
 		 * return immediately leaving dt_errno unmodified.
 		 */
-		if (dt_module_getctf(dtp, dmp) == NULL) {
+		if (dt_module_hasctf(dtp, dmp) == 0) {
 			if (justone)
 				return (-1);
 			continue;
@@ -1192,13 +1433,38 @@
 		 * 'tip' and keep going in the hope that we will locate the
 		 * underlying structure definition.  Otherwise just return.
 		 */
-		if ((id = ctf_lookup_by_name(dmp->dm_ctfp, name)) != CTF_ERR) {
+		if (dmp->dm_pid == 0) {
+			id = ctf_lookup_by_name(dmp->dm_ctfp, name);
+			fp = dmp->dm_ctfp;
+		} else {
+			if ((p = strchr(name, '`')) != NULL) {
+				buf = strdup(name);
+				if (buf == NULL)
+					return (dt_set_errno(dtp, EDT_NOMEM));
+				p = strchr(buf, '`');
+				if ((q = strchr(p + 1, '`')) != NULL)
+					p = q;
+				*p = '\0';
+				fp = dt_module_getctflib(dtp, dmp, buf);
+				if (fp == NULL || (id = ctf_lookup_by_name(fp,
+				    p + 1)) == CTF_ERR)
+					id = CTF_ERR;
+				free(buf);
+			} else {
+				for (i = 0; i < dmp->dm_nctflibs; i++) {
+					fp = dmp->dm_libctfp[i];
+					id = ctf_lookup_by_name(fp, name);
+					if (id != CTF_ERR)
+						break;
+				}
+			}
+		}
+		if (id != CTF_ERR) {
 			tip->dtt_object = dmp->dm_name;
-			tip->dtt_ctfp = dmp->dm_ctfp;
+			tip->dtt_ctfp = fp;
 			tip->dtt_type = id;
-
-			if (ctf_type_kind(dmp->dm_ctfp, ctf_type_resolve(
-			    dmp->dm_ctfp, id)) != CTF_K_FORWARD)
+			if (ctf_type_kind(fp, ctf_type_resolve(fp, id)) !=
+			    CTF_K_FORWARD)
 				return (0);
 
 			found++;
@@ -1220,6 +1486,7 @@
 	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));
--- old/usr/src/lib/libdtrace/common/dt_module.h	2014-01-14 20:12:27.991338146 -0500
+++ new/usr/src/lib/libdtrace/common/dt_module.h	2014-01-14 20:12:28.008795968 -0500
@@ -23,12 +23,13 @@
  * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
+ */
 
 #ifndef	_DT_MODULE_H
 #define	_DT_MODULE_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <dt_impl.h>
 
 #ifdef	__cplusplus
@@ -43,11 +44,16 @@
 extern dt_module_t *dt_module_lookup_by_name(dtrace_hdl_t *, const char *);
 extern dt_module_t *dt_module_lookup_by_ctf(dtrace_hdl_t *, ctf_file_t *);
 
+extern int dt_module_hasctf(dtrace_hdl_t *, dt_module_t *);
 extern ctf_file_t *dt_module_getctf(dtrace_hdl_t *, dt_module_t *);
 extern dt_ident_t *dt_module_extern(dtrace_hdl_t *, dt_module_t *,
     const char *, const dtrace_typeinfo_t *);
 
 extern const char *dt_module_modelname(dt_module_t *);
+extern int dt_module_getlibid(dtrace_hdl_t *, dt_module_t *,
+    const ctf_file_t *);
+extern ctf_file_t *dt_module_getctflib(dtrace_hdl_t *, dt_module_t *,
+    const char *);
 
 #ifdef	__cplusplus
 }
--- old/usr/src/lib/libdtrace/common/dt_open.c	2014-01-14 20:12:28.485257314 -0500
+++ new/usr/src/lib/libdtrace/common/dt_open.c	2014-01-14 20:12:28.499395972 -0500
@@ -21,7 +21,7 @@
 
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  * Copyright (c) 2012 by Delphix. All rights reserved.
  */
 
@@ -113,8 +113,9 @@
 #define	DT_VERS_1_9_1	DT_VERSION_NUMBER(1, 9, 1)
 #define	DT_VERS_1_10	DT_VERSION_NUMBER(1, 10, 0)
 #define	DT_VERS_1_11	DT_VERSION_NUMBER(1, 11, 0)
-#define	DT_VERS_LATEST	DT_VERS_1_11
-#define	DT_VERS_STRING	"Sun D 1.11"
+#define	DT_VERS_1_12	DT_VERSION_NUMBER(1, 12, 0)
+#define	DT_VERS_LATEST	DT_VERS_1_12
+#define	DT_VERS_STRING	"Sun D 1.12"
 
 const dt_version_t _dtrace_versions[] = {
 	DT_VERS_1_0,	/* D API 1.0.0 (PSARC 2001/466) Solaris 10 FCS */
@@ -138,6 +139,7 @@
 	DT_VERS_1_9_1,	/* D API 1.9.1 */
 	DT_VERS_1_10,	/* D API 1.10 */
 	DT_VERS_1_11,	/* D API 1.11 */
+	DT_VERS_1_12,	/* D API 1.12 */
 	0
 };
 
--- old/usr/src/lib/libdtrace/common/dt_parser.c	2014-01-14 20:12:29.007893107 -0500
+++ new/usr/src/lib/libdtrace/common/dt_parser.c	2014-01-14 20:12:29.043230517 -0500
@@ -21,8 +21,8 @@
 
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
 /*
@@ -192,7 +192,7 @@
 {
 	static const char delimiters[] = " \t\n\r\v\f*`";
 	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
-	const char *p, *q, *end, *obj;
+	const char *p, *q, *r, *end, *obj;
 
 	for (p = s, end = s + strlen(s); *p != '\0'; p = q) {
 		while (isspace(*p))
@@ -220,8 +220,23 @@
 			bcopy(s, type, (size_t)(p - s));
 			bcopy(q + 1, type + (size_t)(p - s), strlen(q + 1) + 1);
 
-			if (strchr(q + 1, '`') != NULL)
-				return (dt_set_errno(dtp, EDT_BADSCOPE));
+			/*
+			 * There may be at most three delimeters. The second
+			 * delimeter is usually used to distinguish the type
+			 * within a given module, however, there could be a link
+			 * map id on the scene in which case that delimeter
+			 * would be the third. We determine presence of the lmid
+			 * if it rouglhly meets the from LM[0-9]
+			 */
+			if ((r = strchr(q + 1, '`')) != NULL &&
+			    ((r = strchr(r + 1, '`')) != NULL)) {
+				if (strchr(r + 1, '`') != NULL)
+					return (dt_set_errno(dtp,
+					    EDT_BADSCOPE));
+				if (q[1] != 'L' || q[2] != 'M')
+					return (dt_set_errno(dtp,
+					    EDT_BADSCOPE));
+			}
 
 			return (dtrace_lookup_by_type(dtp, object, type, tip));
 		}
@@ -251,6 +266,7 @@
 	ctf_file_t *ctfp = tip->dtt_ctfp;
 	ctf_id_t type = tip->dtt_type;
 	ctf_id_t base = ctf_type_resolve(ctfp, type);
+	uint_t bflags = tip->dtt_flags;
 
 	dt_module_t *dmp;
 	ctf_id_t ptr;
@@ -282,6 +298,7 @@
 	tip->dtt_object = dmp->dm_name;
 	tip->dtt_ctfp = dmp->dm_ctfp;
 	tip->dtt_type = ptr;
+	tip->dtt_flags = bflags;
 
 	return (0);
 }
@@ -385,7 +402,7 @@
 dt_node_promote(dt_node_t *lp, dt_node_t *rp, dt_node_t *dnp)
 {
 	dt_type_promote(lp, rp, &dnp->dn_ctfp, &dnp->dn_type);
-	dt_node_type_assign(dnp, dnp->dn_ctfp, dnp->dn_type);
+	dt_node_type_assign(dnp, dnp->dn_ctfp, dnp->dn_type, B_FALSE);
 	dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
 }
 
@@ -654,7 +671,8 @@
 }
 
 void
-dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type)
+dt_node_type_assign(dt_node_t *dnp, ctf_file_t *fp, ctf_id_t type,
+    boolean_t user)
 {
 	ctf_id_t base = ctf_type_resolve(fp, type);
 	uint_t kind = ctf_type_kind(fp, base);
@@ -686,6 +704,9 @@
 	    type == DT_DYN_TYPE(yypcb->pcb_hdl))
 		dnp->dn_flags |= DT_NF_REF;
 
+	if (user)
+		dnp->dn_flags |= DT_NF_USERLAND;
+
 	dnp->dn_flags |= DT_NF_COOKED;
 	dnp->dn_ctfp = fp;
 	dnp->dn_type = type;
@@ -723,6 +744,7 @@
 dt_node_type_size(const dt_node_t *dnp)
 {
 	ctf_id_t base;
+	dtrace_hdl_t *dtp = yypcb->pcb_hdl;
 
 	if (dnp->dn_kind == DT_NODE_STRING)
 		return (strlen(dnp->dn_string) + 1);
@@ -735,6 +757,20 @@
 	if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_FORWARD)
 		return (0);
 
+	/*
+	 * Here we have a 32-bit user pointer that is being used with a 64-bit
+	 * kernel. When we're using it and its tagged as a userland reference --
+	 * then we need to keep it as a 32-bit pointer. However, if we are
+	 * referring to it as a kernel address, eg. being used after a copyin()
+	 * then we need to make sure that we actually return the kernel's size
+	 * of a pointer, 8 bytes.
+	 */
+	if (ctf_type_kind(dnp->dn_ctfp, base) == CTF_K_POINTER &&
+	    ctf_getmodel(dnp->dn_ctfp) == CTF_MODEL_ILP32 &&
+	    !(dnp->dn_flags & DT_NF_USERLAND) &&
+	    dtp->dt_conf.dtc_ctfmodel == CTF_MODEL_LP64)
+			return (8);
+
 	return (ctf_type_size(dnp->dn_ctfp, dnp->dn_type));
 }
 
@@ -1221,7 +1257,7 @@
 		if (value <= dtp->dt_ints[i].did_limit) {
 			dt_node_type_assign(dnp,
 			    dtp->dt_ints[i].did_ctfp,
-			    dtp->dt_ints[i].did_type);
+			    dtp->dt_ints[i].did_type, B_FALSE);
 
 			/*
 			 * If a prefix character is present in macro text, add
@@ -1256,7 +1292,7 @@
 	dnp = dt_node_alloc(DT_NODE_STRING);
 	dnp->dn_op = DT_TOK_STRING;
 	dnp->dn_string = string;
-	dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp));
+	dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp), B_FALSE);
 
 	return (dnp);
 }
@@ -1332,7 +1368,8 @@
 	dnp = dt_node_alloc(DT_NODE_TYPE);
 	dnp->dn_op = DT_TOK_IDENT;
 	dnp->dn_string = name;
-	dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+
+	dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, dtt.dtt_flags);
 
 	if (dtt.dtt_ctfp == dtp->dt_cdefs->dm_ctfp ||
 	    dtt.dtt_ctfp == dtp->dt_ddefs->dm_ctfp)
@@ -1576,7 +1613,8 @@
 		bzero(&idn, sizeof (dt_node_t));
 
 		if (idp != NULL && idp->di_type != CTF_ERR)
-			dt_node_type_assign(&idn, idp->di_ctfp, idp->di_type);
+			dt_node_type_assign(&idn, idp->di_ctfp, idp->di_type,
+			    B_FALSE);
 		else if (idp != NULL)
 			(void) dt_ident_cook(&idn, idp, NULL);
 
@@ -1785,7 +1823,7 @@
 	}
 
 	bzero(&dn, sizeof (dn));
-	dt_node_type_assign(&dn, dtt.dtt_ctfp, ctm.ctm_type);
+	dt_node_type_assign(&dn, dtt.dtt_ctfp, ctm.ctm_type, B_FALSE);
 
 	if (dn.dn_flags & DT_NF_BITFIELD) {
 		xyerror(D_OFFSETOF_BITFIELD,
@@ -1841,7 +1879,8 @@
 		}
 
 		dt_node_type_assign(cp, dtp->dt_ddefs->dm_ctfp,
-		    ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"));
+		    ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"),
+		    B_FALSE);
 
 		cp->dn_kind = DT_NODE_INT;
 		cp->dn_op = DT_TOK_INT;
@@ -1919,17 +1958,17 @@
 		case DT_TOK_LOR:
 			dnp->dn_value = l || r;
 			dt_node_type_assign(dnp,
-			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
 			break;
 		case DT_TOK_LXOR:
 			dnp->dn_value = (l != 0) ^ (r != 0);
 			dt_node_type_assign(dnp,
-			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
 			break;
 		case DT_TOK_LAND:
 			dnp->dn_value = l && r;
 			dt_node_type_assign(dnp,
-			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
 			break;
 		case DT_TOK_BOR:
 			dnp->dn_value = l | r;
@@ -1946,12 +1985,12 @@
 		case DT_TOK_EQU:
 			dnp->dn_value = l == r;
 			dt_node_type_assign(dnp,
-			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
 			break;
 		case DT_TOK_NEQ:
 			dnp->dn_value = l != r;
 			dt_node_type_assign(dnp,
-			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
 			break;
 		case DT_TOK_LT:
 			dt_node_promote(lp, rp, dnp);
@@ -1960,7 +1999,7 @@
 			else
 				dnp->dn_value = l < r;
 			dt_node_type_assign(dnp,
-			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
 			break;
 		case DT_TOK_LE:
 			dt_node_promote(lp, rp, dnp);
@@ -1969,7 +2008,7 @@
 			else
 				dnp->dn_value = l <= r;
 			dt_node_type_assign(dnp,
-			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
 			break;
 		case DT_TOK_GT:
 			dt_node_promote(lp, rp, dnp);
@@ -1978,7 +2017,7 @@
 			else
 				dnp->dn_value = l > r;
 			dt_node_type_assign(dnp,
-			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
 			break;
 		case DT_TOK_GE:
 			dt_node_promote(lp, rp, dnp);
@@ -1987,7 +2026,7 @@
 			else
 				dnp->dn_value = l >= r;
 			dt_node_type_assign(dnp,
-			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+			    DT_INT_CTFP(dtp), DT_INT_TYPE(dtp), B_FALSE);
 			break;
 		case DT_TOK_LSH:
 			dnp->dn_value = l << r;
@@ -2228,7 +2267,7 @@
 	 * until we have successfully cooked the right-hand expression, below.
 	 */
 	dnp = dt_node_alloc(DT_NODE_INLINE);
-	dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+	dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
 	dt_node_attr_assign(dnp, _dtrace_defattr);
 
 	if (dt_node_is_void(dnp)) {
@@ -2383,7 +2422,8 @@
 	dnp->dn_membexpr = expr;
 
 	if (ddp != NULL)
-		dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+		dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
+		    dtt.dtt_flags);
 
 	return (dnp);
 }
@@ -2414,10 +2454,10 @@
 	}
 
 	bzero(&sn, sizeof (sn));
-	dt_node_type_assign(&sn, src.dtt_ctfp, src.dtt_type);
+	dt_node_type_assign(&sn, src.dtt_ctfp, src.dtt_type, B_FALSE);
 
 	bzero(&dn, sizeof (dn));
-	dt_node_type_assign(&dn, dst.dtt_ctfp, dst.dtt_type);
+	dt_node_type_assign(&dn, dst.dtt_ctfp, dst.dtt_type, B_FALSE);
 
 	if (dt_xlator_lookup(dtp, &sn, &dn, DT_XLATE_EXACT) != NULL) {
 		xyerror(D_XLATE_REDECL,
@@ -2663,7 +2703,7 @@
 			attr = dt_ident_cook(dnp, idp, NULL);
 		else {
 			dt_node_type_assign(dnp,
-			    DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+			    DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
 			attr = idp->di_attr;
 		}
 
@@ -2739,7 +2779,8 @@
 		dnp->dn_ident = idp;
 		dnp->dn_flags |= DT_NF_LVALUE;
 
-		dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+		dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
+		    dtt.dtt_flags);
 		dt_node_attr_assign(dnp, _dtrace_symattr);
 
 		if (uref) {
@@ -2787,7 +2828,7 @@
 			attr = dt_ident_cook(dnp, idp, NULL);
 		else {
 			dt_node_type_assign(dnp,
-			    DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+			    DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
 			attr = idp->di_attr;
 		}
 
@@ -2890,7 +2931,8 @@
 			xyerror(D_TYPE_ERR, "failed to lookup int64_t\n");
 
 		dt_ident_type_assign(cp->dn_ident, dtt.dtt_ctfp, dtt.dtt_type);
-		dt_node_type_assign(cp, dtt.dtt_ctfp, dtt.dtt_type);
+		dt_node_type_assign(cp, dtt.dtt_ctfp, dtt.dtt_type,
+		    dtt.dtt_flags);
 	}
 
 	if (cp->dn_kind == DT_NODE_VAR)
@@ -2907,7 +2949,8 @@
 
 			dnp->dn_ident = &dxp->dx_souid;
 			dt_node_type_assign(dnp,
-			    dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type);
+			    dnp->dn_ident->di_ctfp, dnp->dn_ident->di_type,
+			    cp->dn_flags & DT_NF_USERLAND);
 			break;
 		}
 
@@ -2927,7 +2970,8 @@
 			    "cannot dereference non-pointer type\n");
 		}
 
-		dt_node_type_assign(dnp, cp->dn_ctfp, type);
+		dt_node_type_assign(dnp, cp->dn_ctfp, type,
+		    cp->dn_flags & DT_NF_USERLAND);
 		base = ctf_type_resolve(cp->dn_ctfp, type);
 		kind = ctf_type_kind(cp->dn_ctfp, base);
 
@@ -2984,7 +3028,8 @@
 			xyerror(D_OP_SCALAR, "operator %s requires an operand "
 			    "of scalar type\n", opstr(dnp->dn_op));
 		}
-		dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+		dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
+		    B_FALSE);
 		break;
 
 	case DT_TOK_ADDROF:
@@ -3017,10 +3062,8 @@
 			    dt_node_type_name(cp, n, sizeof (n)));
 		}
 
-		dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
-
-		if (cp->dn_flags & DT_NF_USERLAND)
-			dnp->dn_flags |= DT_NF_USERLAND;
+		dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type,
+		    cp->dn_flags & DT_NF_USERLAND);
 		break;
 
 	case DT_TOK_SIZEOF:
@@ -3035,7 +3078,8 @@
 		}
 
 		dt_node_type_assign(dnp, dtp->dt_ddefs->dm_ctfp,
-		    ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"));
+		    ctf_lookup_by_name(dtp->dt_ddefs->dm_ctfp, "size_t"),
+		    B_FALSE);
 		break;
 
 	case DT_TOK_STRINGOF:
@@ -3045,7 +3089,8 @@
 			    "cannot apply stringof to a value of type %s\n",
 			    dt_node_type_name(cp, n, sizeof (n)));
 		}
-		dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp));
+		dt_node_type_assign(dnp, DT_STR_CTFP(dtp), DT_STR_TYPE(dtp),
+		    cp->dn_flags & DT_NF_USERLAND);
 		break;
 
 	case DT_TOK_PREINC:
@@ -3238,7 +3283,8 @@
 			    "of scalar type\n", opstr(op));
 		}
 
-		dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+		dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
+		    B_FALSE);
 		dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
 		break;
 
@@ -3282,7 +3328,8 @@
 			rp->dn_op = DT_TOK_INT;
 			rp->dn_value = (intmax_t)val;
 
-			dt_node_type_assign(rp, lp->dn_ctfp, lp->dn_type);
+			dt_node_type_assign(rp, lp->dn_ctfp, lp->dn_type,
+			    B_FALSE);
 			dt_node_attr_assign(rp, _dtrace_symattr);
 		}
 
@@ -3314,7 +3361,8 @@
 			    dt_node_type_name(rp, n2, sizeof (n2)));
 		}
 
-		dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp));
+		dt_node_type_assign(dnp, DT_INT_CTFP(dtp), DT_INT_TYPE(dtp),
+		    B_FALSE);
 		dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
 		break;
 
@@ -3362,7 +3410,7 @@
 			    dt_node_type_name(rp, n2, sizeof (n2)));
 		}
 
-		dt_node_type_assign(dnp, ctfp, type);
+		dt_node_type_assign(dnp, ctfp, type, B_FALSE);
 		dt_node_attr_assign(dnp, dt_attr_min(lp->dn_attr, rp->dn_attr));
 
 		if (uref)
@@ -3503,7 +3551,7 @@
 		 */
 		if (lp->dn_kind == DT_NODE_VAR &&
 		    dt_ident_unref(lp->dn_ident)) {
-			dt_node_type_assign(lp, ctfp, type);
+			dt_node_type_assign(lp, ctfp, type, B_FALSE);
 			dt_ident_type_assign(lp->dn_ident, ctfp, type);
 
 			if (uref) {
@@ -3717,7 +3765,7 @@
 		type = ctf_type_resolve(ctfp, m.ctm_type);
 		kind = ctf_type_kind(ctfp, type);
 
-		dt_node_type_assign(dnp, ctfp, m.ctm_type);
+		dt_node_type_assign(dnp, ctfp, m.ctm_type, B_FALSE);
 		dt_node_attr_assign(dnp, lp->dn_attr);
 
 		if (op == DT_TOK_PTR && (kind != CTF_K_ARRAY ||
@@ -3843,7 +3891,8 @@
 		}
 
 		dnp->dn_ident = dt_xlator_ident(dxp, lp->dn_ctfp, lp->dn_type);
-		dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+		dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
+		    B_FALSE);
 		dt_node_attr_assign(dnp,
 		    dt_attr_min(rp->dn_attr, dnp->dn_ident->di_attr));
 		break;
@@ -4008,7 +4057,7 @@
 		    "used in a conditional context\n");
 	}
 
-	dt_node_type_assign(dnp, ctfp, type);
+	dt_node_type_assign(dnp, ctfp, type, B_FALSE);
 	dt_node_attr_assign(dnp, dt_attr_min(dnp->dn_expr->dn_attr,
 	    dt_attr_min(lp->dn_attr, rp->dn_attr)));
 
@@ -4041,7 +4090,8 @@
 		dt_node_attr_assign(dnp, dt_ident_cook(dnp,
 		    dnp->dn_ident, &dnp->dn_aggtup));
 	} else {
-		dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+		dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp),
+		    B_FALSE);
 		dt_node_attr_assign(dnp, dnp->dn_ident->di_attr);
 	}
 
@@ -4243,7 +4293,8 @@
 		}
 
 		(void) dt_node_cook(mnp, DT_IDFLG_REF);
-		dt_node_type_assign(mnp, dxp->dx_dst_ctfp, ctm.ctm_type);
+		dt_node_type_assign(mnp, dxp->dx_dst_ctfp, ctm.ctm_type,
+		    B_FALSE);
 		attr = dt_attr_min(attr, mnp->dn_attr);
 
 		if (dt_node_is_argcompat(mnp, mnp->dn_membexpr) == 0) {
@@ -4262,7 +4313,7 @@
 	dxp->dx_souid.di_attr = attr;
 	dxp->dx_ptrid.di_attr = attr;
 
-	dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp));
+	dt_node_type_assign(dnp, DT_DYN_CTFP(dtp), DT_DYN_TYPE(dtp), B_FALSE);
 	dt_node_attr_assign(dnp, _dtrace_defattr);
 
 	return (dnp);
@@ -4555,7 +4606,9 @@
 		    ctf_type_resolve(dnp->dn_ctfp, dnp->dn_type));
 	}
 
-	tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ? DIF_TF_BYREF : 0;
+	tp->dtdt_flags = (dnp->dn_flags & DT_NF_REF) ?
+	    (dnp->dn_flags & DT_NF_USERLAND) ? DIF_TF_BYUREF :
+	    DIF_TF_BYREF : 0;
 	tp->dtdt_pad = 0;
 	tp->dtdt_size = ctf_type_size(dnp->dn_ctfp, dnp->dn_type);
 }
--- old/usr/src/lib/libdtrace/common/dt_parser.h	2014-01-14 20:12:29.861925106 -0500
+++ new/usr/src/lib/libdtrace/common/dt_parser.h	2014-01-14 20:12:29.877172363 -0500
@@ -22,12 +22,14 @@
  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
 
 #ifndef	_DT_PARSER_H
 #define	_DT_PARSER_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <sys/types.h>
 #include <sys/dtrace.h>
 
@@ -223,7 +225,7 @@
 extern void dt_node_link_free(dt_node_t **);
 
 extern void dt_node_attr_assign(dt_node_t *, dtrace_attribute_t);
-extern void dt_node_type_assign(dt_node_t *, ctf_file_t *, ctf_id_t);
+extern void dt_node_type_assign(dt_node_t *, ctf_file_t *, ctf_id_t, boolean_t);
 extern void dt_node_type_propagate(const dt_node_t *, dt_node_t *);
 extern const char *dt_node_type_name(const dt_node_t *, char *, size_t);
 extern size_t dt_node_type_size(const dt_node_t *);
--- 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);
+}
--- old/usr/src/lib/libdtrace/common/dt_pid.h	2014-01-14 20:12:31.372768580 -0500
+++ new/usr/src/lib/libdtrace/common/dt_pid.h	2014-01-14 20:12:31.403925523 -0500
@@ -24,12 +24,13 @@
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
+/*
+ * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
+ */
 
 #ifndef	_DT_PID_H
 #define	_DT_PID_H
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
-
 #include <libproc.h>
 #include <sys/fasttrap.h>
 #include <dt_impl.h>
@@ -57,6 +58,9 @@
 extern int dt_pid_create_glob_offset_probes(struct ps_prochandle *,
     dtrace_hdl_t *, fasttrap_probe_spec_t *, const GElf_Sym *, const char *);
 
+extern void dt_pid_get_types(dtrace_hdl_t *, const dtrace_probedesc_t *,
+    dtrace_argdesc_t *, int *);
+
 #ifdef	__cplusplus
 }
 #endif
--- old/usr/src/lib/libdtrace/common/dt_print.c	2014-01-14 20:12:31.900953993 -0500
+++ new/usr/src/lib/libdtrace/common/dt_print.c	2014-01-14 20:12:31.927664075 -0500
@@ -649,12 +649,16 @@
 	dt_printarg_t pa;
 	ctf_id_t id;
 	dt_module_t *dmp;
+	ctf_file_t *ctfp;
+	int libid;
 
 	/*
 	 * Split the fully-qualified type ID (module`id).  This should
 	 * always be the format, but if for some reason we don't find the
 	 * expected value, return 0 to fall back to the generic trace()
-	 * behavior.
+	 * behavior. In the case of userland CTF modules this will actually be
+	 * of the format (module`lib`id). This is due to the fact that those
+	 * modules have multiple CTF containers which `lib` identifies.
 	 */
 	for (s = typename; *s != '\0' && *s != '`'; s++)
 		;
@@ -665,6 +669,20 @@
 	object = alloca(s - typename + 1);
 	bcopy(typename, object, s - typename);
 	object[s - typename] = '\0';
+	dmp = dt_module_lookup_by_name(dtp, object);
+	if (dmp == NULL)
+		return (0);
+
+	if (dmp->dm_pid != 0) {
+		libid = atoi(s + 1);
+		s = strchr(s + 1, '`');
+		if (s == NULL || libid > dmp->dm_nctflibs)
+			return (0);
+		ctfp = dmp->dm_libctfp[libid];
+	} else {
+		ctfp = dt_module_getctf(dtp, dmp);
+	}
+
 	id = atoi(s + 1);
 
 	/*
@@ -672,16 +690,13 @@
 	 * wrong and we can't resolve the ID, bail out and let trace() do the
 	 * work.
 	 */
-	dmp = dt_module_lookup_by_name(dtp, object);
-	if (dmp == NULL || ctf_type_kind(dt_module_getctf(dtp, dmp),
-	    id) == CTF_ERR) {
+	if (ctfp == NULL || ctf_type_kind(ctfp, id) == CTF_ERR)
 		return (0);
-	}
 
 	/* setup the print structure and kick off the main print routine */
 	pa.pa_dtp = dtp;
 	pa.pa_addr = addr;
-	pa.pa_ctfp = dt_module_getctf(dtp, dmp);
+	pa.pa_ctfp = ctfp;
 	pa.pa_nest = 0;
 	pa.pa_depth = 0;
 	pa.pa_file = fp;
--- old/usr/src/lib/libdtrace/common/dt_printf.c	2014-01-14 20:12:32.458727557 -0500
+++ new/usr/src/lib/libdtrace/common/dt_printf.c	2014-01-14 20:12:32.473629210 -0500
@@ -21,8 +21,8 @@
 
 /*
  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
 #include <sys/sysmacros.h>
@@ -1048,7 +1048,7 @@
 		xyerror(D_TYPE_ERR, "failed to lookup agg type %s\n", aggtype);
 
 	bzero(&aggnode, sizeof (aggnode));
-	dt_node_type_assign(&aggnode, dtt.dtt_ctfp, dtt.dtt_type);
+	dt_node_type_assign(&aggnode, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
 
 	for (i = 0, j = 0; i < pfv->pfv_argc; i++, pfd = pfd->pfd_next) {
 		const dt_pfconv_t *pfc = pfd->pfd_conv;
--- old/usr/src/lib/libdtrace/common/dt_provider.c	2014-01-14 20:12:33.053264863 -0500
+++ new/usr/src/lib/libdtrace/common/dt_provider.c	2014-01-14 20:12:33.066772930 -0500
@@ -23,8 +23,9 @@
  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
+ */
 
 #include <sys/types.h>
 #include <sys/sysmacros.h>
@@ -41,6 +42,8 @@
 #include <dt_module.h>
 #include <dt_string.h>
 #include <dt_list.h>
+#include <dt_pid.h>
+#include <dtrace.h>
 
 static dt_provider_t *
 dt_provider_insert(dtrace_hdl_t *dtp, dt_provider_t *pvp, uint_t h)
@@ -269,6 +272,21 @@
 	nc++;
 
 	/*
+	 * The pid provider believes in giving the kernel a break. No reason to
+	 * give the kernel all the ctf containers that we're keeping ourselves
+	 * just to get it back from it. So if we're coming from a pid provider
+	 * probe and the kernel gave us no argument information we'll get some
+	 * here. If for some crazy reason the kernel knows about our userland
+	 * types then we just ignore this.
+	 */
+	if (xc == 0 && nc == 0 &&
+	    strncmp(pvp->pv_desc.dtvd_name, "pid", 3) == 0) {
+		nc = adc;
+		dt_pid_get_types(dtp, pdp, adv, &nc);
+		xc = nc;
+	}
+
+	/*
 	 * Now that we have discovered the number of native and translated
 	 * arguments from the argument descriptions, allocate a new probe ident
 	 * and corresponding dt_probe_t and hash it into the provider.
@@ -314,7 +332,8 @@
 			dtt.dtt_type = CTF_ERR;
 		} else {
 			dt_node_type_assign(prp->pr_nargv[adp->dtargd_mapping],
-			    dtt.dtt_ctfp, dtt.dtt_type);
+			    dtt.dtt_ctfp, dtt.dtt_type,
+			    dtt.dtt_flags & DTT_FL_USER ? B_TRUE : B_FALSE);
 		}
 
 		if (dtt.dtt_type != CTF_ERR && (adp->dtargd_xlate[0] == '\0' ||
@@ -333,7 +352,7 @@
 			dtt.dtt_type = CTF_ERR;
 		} else {
 			dt_node_type_assign(prp->pr_xargv[i],
-			    dtt.dtt_ctfp, dtt.dtt_type);
+			    dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
 		}
 
 		prp->pr_mapping[i] = adp->dtargd_mapping;
@@ -634,7 +653,7 @@
 	bzero(dnp, sizeof (dt_node_t));
 	dnp->dn_kind = DT_NODE_TYPE;
 
-	dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type);
+	dt_node_type_assign(dnp, dtt.dtt_ctfp, dtt.dtt_type, B_FALSE);
 	dt_node_attr_assign(dnp, _dtrace_defattr);
 
 	return (dnp);
--- old/usr/src/lib/libdtrace/common/dt_xlator.c	2014-01-14 20:12:33.532975211 -0500
+++ new/usr/src/lib/libdtrace/common/dt_xlator.c	2014-01-14 20:12:33.567830919 -0500
@@ -23,8 +23,10 @@
  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
-
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013 Joyent, Inc. All rights reserved.
+ */
 
 #include <strings.h>
 #include <assert.h>
@@ -69,7 +71,7 @@
 	enp->dn_op = DT_TOK_XLATE;
 	enp->dn_xlator = dxp;
 	enp->dn_xmember = mnp;
-	dt_node_type_assign(enp, dxp->dx_dst_ctfp, type);
+	dt_node_type_assign(enp, dxp->dx_dst_ctfp, type, B_FALSE);
 
 	/*
 	 * For the member itself, we use a DT_NODE_MEMBER as usual with the
@@ -83,7 +85,7 @@
 
 	mnp->dn_membname = strdup(name);
 	mnp->dn_membexpr = enp;
-	dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type);
+	dt_node_type_assign(mnp, dxp->dx_dst_ctfp, type, B_FALSE);
 
 	if (mnp->dn_membname == NULL)
 		return (dt_set_errno(dtp, EDT_NOMEM));
@@ -318,7 +320,8 @@
 
 	for (dxp = dt_list_next(&dtp->dt_xlators); dxp != NULL;
 	    dxp = dt_list_next(dxp)) {
-		dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type);
+		dt_node_type_assign(&xn, dxp->dx_src_ctfp, dxp->dx_src_type,
+		    B_FALSE);
 		if (ctf_type_compat(dxp->dx_dst_ctfp, dxp->dx_dst_base,
 		    dst_ctfp, dst_base) && dt_node_is_argcompat(src, &xn))
 			goto out;
--- old/usr/src/lib/libdtrace/common/dtrace.h	2014-01-14 20:12:33.998343916 -0500
+++ new/usr/src/lib/libdtrace/common/dtrace.h	2014-01-14 20:12:34.013842303 -0500
@@ -25,7 +25,8 @@
  */
 
 /*
- * Copyright (c) 2011, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
  */
 
 #ifndef	_DTRACE_H
@@ -491,8 +492,11 @@
 	const char *dtt_object;			/* object containing type */
 	ctf_file_t *dtt_ctfp;			/* CTF container handle */
 	ctf_id_t dtt_type;			/* CTF type identifier */
+	uint_t dtt_flags;			/* Misc. flags */
 } dtrace_typeinfo_t;
 
+#define	DTT_FL_USER	0x1			/* user type */
+
 extern int dtrace_lookup_by_type(dtrace_hdl_t *, const char *, const char *,
     dtrace_typeinfo_t *);
 
--- old/usr/src/pkg/manifests/system-dtrace-tests.mf	2014-01-14 20:12:34.461438738 -0500
+++ new/usr/src/pkg/manifests/system-dtrace-tests.mf	2014-01-14 20:12:34.475101906 -0500
@@ -119,6 +119,7 @@
 dir path=opt/SUNWdtrt/tst/common/translators
 dir path=opt/SUNWdtrt/tst/common/typedef
 dir path=opt/SUNWdtrt/tst/common/types
+dir path=opt/SUNWdtrt/tst/common/uctf
 dir path=opt/SUNWdtrt/tst/common/union
 dir path=opt/SUNWdtrt/tst/common/usdt
 dir path=opt/SUNWdtrt/tst/common/ustack
@@ -1977,6 +1978,30 @@
 file path=opt/SUNWdtrt/tst/common/types/tst.struct.d mode=0444
 file path=opt/SUNWdtrt/tst/common/types/tst.typedef.d mode=0444
 file path=opt/SUNWdtrt/tst/common/types/tst.unaryop.d mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/err.invalidpid.d mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/err.invalidpid2.d mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/err.invalidpid3.d mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/err.invalidtype.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/err.invalidtype2.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/err.user64mode.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/tst.aouttype.exe mode=0555
+file path=opt/SUNWdtrt/tst/common/uctf/tst.aouttype.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/tst.chasestrings.exe mode=0555
+file path=opt/SUNWdtrt/tst/common/uctf/tst.chasestrings.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/tst.chasestrings.ksh.out mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/tst.libtype.exe mode=0555
+file path=opt/SUNWdtrt/tst/common/uctf/tst.libtype.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/tst.linkmap.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/tst.pidprint.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/tst.pidprinttarg.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/tst.printtype.exe mode=0555
+file path=opt/SUNWdtrt/tst/common/uctf/tst.printtype.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/tst.printtype.ksh.out mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/tst.printtypetarg.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/tst.userlandkey.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/tst.userlandkey.ksh.out mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/tst.userstrings.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/uctf/tst.userstrings.ksh.out mode=0444
 file path=opt/SUNWdtrt/tst/common/union/err.D_ADDROF_VAR.UnionPointer.d \
     mode=0444
 file path=opt/SUNWdtrt/tst/common/union/err.D_DECL_COMBO.UnionWithoutColon.d \
--- old/usr/src/uts/common/dtrace/dtrace.c	2014-01-14 20:12:35.207744965 -0500
+++ new/usr/src/uts/common/dtrace/dtrace.c	2014-01-14 20:12:35.223890084 -0500
@@ -5719,32 +5719,46 @@
 			regs[rd] = dtrace_load64(regs[r1]);
 			break;
 		case DIF_OP_ULDSB:
+			DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
 			regs[rd] = (int8_t)
 			    dtrace_fuword8((void *)(uintptr_t)regs[r1]);
+			DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
 			break;
 		case DIF_OP_ULDSH:
+			DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
 			regs[rd] = (int16_t)
 			    dtrace_fuword16((void *)(uintptr_t)regs[r1]);
+			DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
 			break;
 		case DIF_OP_ULDSW:
+			DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
 			regs[rd] = (int32_t)
 			    dtrace_fuword32((void *)(uintptr_t)regs[r1]);
+			DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
 			break;
 		case DIF_OP_ULDUB:
+			DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
 			regs[rd] =
 			    dtrace_fuword8((void *)(uintptr_t)regs[r1]);
+			DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
 			break;
 		case DIF_OP_ULDUH:
+			DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
 			regs[rd] =
 			    dtrace_fuword16((void *)(uintptr_t)regs[r1]);
+			DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
 			break;
 		case DIF_OP_ULDUW:
+			DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
 			regs[rd] =
 			    dtrace_fuword32((void *)(uintptr_t)regs[r1]);
+			DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
 			break;
 		case DIF_OP_ULDX:
+			DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
 			regs[rd] =
 			    dtrace_fuword64((void *)(uintptr_t)regs[r1]);
+			DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
 			break;
 		case DIF_OP_RET:
 			rval = regs[rd];
@@ -6552,6 +6566,63 @@
 	mstate->dtms_scratch_ptr = old;
 }
 
+static void
+dtrace_store_by_ref(dtrace_difo_t *dp, caddr_t tomax, size_t size,
+    size_t *valoffsp, uint64_t *valp, uint64_t end, int intuple, int dtkind)
+{
+	volatile uint16_t *flags;
+	uint64_t val = *valp;
+	size_t valoffs = *valoffsp;
+
+	flags = (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
+	ASSERT(dtkind == DIF_TF_BYREF || dtkind == DIF_TF_BYUREF);
+
+	/*
+	 * If this is a string, we're going to only load until we find the zero
+	 * byte -- after which we'll store zero bytes.
+	 */
+	if (dp->dtdo_rtype.dtdt_kind == DIF_TYPE_STRING) {
+		char c = '\0' + 1;
+		size_t s;
+
+		for (s = 0; s < size; s++) {
+			if (c != '\0' && dtkind == DIF_TF_BYREF) {
+				c = dtrace_load8(val++);
+			} else if (c != '\0' && dtkind == DIF_TF_BYUREF) {
+				DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+				c = dtrace_fuword8((void *)(uintptr_t)val++);
+				DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
+				if (*flags & CPU_DTRACE_FAULT)
+					break;
+			}
+
+			DTRACE_STORE(uint8_t, tomax, valoffs++, c);
+
+			if (c == '\0' && intuple)
+				break;
+		}
+	} else {
+		uint8_t c;
+		while (valoffs < end) {
+			if (dtkind == DIF_TF_BYREF) {
+				c = dtrace_load8(val++);
+			} else if (dtkind == DIF_TF_BYUREF) {
+				DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+				c = dtrace_fuword8((void *)(uintptr_t)val++);
+				DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
+				if (*flags & CPU_DTRACE_FAULT)
+					break;
+			}
+
+			DTRACE_STORE(uint8_t, tomax,
+			    valoffs++, c);
+		}
+	}
+
+	*valp = val;
+	*valoffsp = valoffs;
+}
+
 /*
  * If you're looking for the epicenter of DTrace, you just found it.  This
  * is the function called by the provider to fire a probe -- from which all
@@ -7043,7 +7114,8 @@
 				ASSERT(0);
 			}
 
-			if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF) {
+			if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF ||
+			    dp->dtdo_rtype.dtdt_flags & DIF_TF_BYUREF) {
 				uintptr_t end = valoffs + size;
 
 				if (tracememsize != 0 &&
@@ -7052,40 +7124,15 @@
 					tracememsize = 0;
 				}
 
-				if (!dtrace_vcanload((void *)(uintptr_t)val,
+				if (dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF &&
+				    !dtrace_vcanload((void *)(uintptr_t)val,
 				    &dp->dtdo_rtype, &mstate, vstate))
 					continue;
 
-				/*
-				 * If this is a string, we're going to only
-				 * load until we find the zero byte -- after
-				 * which we'll store zero bytes.
-				 */
-				if (dp->dtdo_rtype.dtdt_kind ==
-				    DIF_TYPE_STRING) {
-					char c = '\0' + 1;
-					int intuple = act->dta_intuple;
-					size_t s;
-
-					for (s = 0; s < size; s++) {
-						if (c != '\0')
-							c = dtrace_load8(val++);
-
-						DTRACE_STORE(uint8_t, tomax,
-						    valoffs++, c);
-
-						if (c == '\0' && intuple)
-							break;
-					}
-
-					continue;
-				}
-
-				while (valoffs < end) {
-					DTRACE_STORE(uint8_t, tomax, valoffs++,
-					    dtrace_load8(val++));
-				}
-
+				dtrace_store_by_ref(dp, tomax, size, &valoffs,
+				    &val, end, act->dta_intuple,
+				    dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF ?
+				    DIF_TF_BYREF: DIF_TF_BYUREF);
 				continue;
 			}
 
@@ -9203,7 +9250,7 @@
 		    "expected 'ret' as last DIF instruction\n");
 	}
 
-	if (!(dp->dtdo_rtype.dtdt_flags & DIF_TF_BYREF)) {
+	if (!(dp->dtdo_rtype.dtdt_flags & (DIF_TF_BYREF | DIF_TF_BYUREF))) {
 		/*
 		 * If we're not returning by reference, the size must be either
 		 * 0 or the size of one of the base types.
--- old/usr/src/uts/common/sys/ctf_api.h	2014-01-14 20:12:36.838046618 -0500
+++ new/usr/src/uts/common/sys/ctf_api.h	2014-01-14 20:12:36.852093375 -0500
@@ -24,7 +24,7 @@
  * Use is subject to license terms.
  */
 /*
- * Copyright (c) 2012, Joyent, Inc.  All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
  */
 
 /*
@@ -151,6 +151,7 @@
 extern ctf_file_t *ctf_fdopen(int, int *);
 extern ctf_file_t *ctf_open(const char *, int *);
 extern ctf_file_t *ctf_create(int *);
+extern ctf_file_t *ctf_dup(ctf_file_t *);
 extern void ctf_close(ctf_file_t *);
 
 extern ctf_file_t *ctf_parent_file(ctf_file_t *);
@@ -176,6 +177,8 @@
 extern ctf_id_t ctf_type_resolve(ctf_file_t *, ctf_id_t);
 extern ssize_t ctf_type_lname(ctf_file_t *, ctf_id_t, char *, size_t);
 extern char *ctf_type_name(ctf_file_t *, ctf_id_t, char *, size_t);
+extern char *ctf_type_qname(ctf_file_t *, ctf_id_t, char *, size_t,
+    const char *);
 extern ssize_t ctf_type_size(ctf_file_t *, ctf_id_t);
 extern ssize_t ctf_type_align(ctf_file_t *, ctf_id_t);
 extern int ctf_type_kind(ctf_file_t *, ctf_id_t);
--- old/usr/src/uts/common/sys/dtrace.h	2014-01-14 20:12:37.355430028 -0500
+++ new/usr/src/uts/common/sys/dtrace.h	2014-01-14 20:12:37.371440913 -0500
@@ -25,8 +25,8 @@
  */
 
 /*
- * Copyright (c) 2012, Joyent, Inc. All rights reserved.
- * Copyright (c) 2012 by Delphix. All rights reserved.
+ * Copyright (c) 2013, Joyent, Inc. All rights reserved.
+ * Copyright (c) 2013 by Delphix. All rights reserved.
  */
 
 #ifndef _SYS_DTRACE_H
@@ -354,6 +354,7 @@
 #define	DIF_TYPE_STRING		1	/* type is a D string */
 
 #define	DIF_TF_BYREF		0x1	/* type is passed by reference */
+#define	DIF_TF_BYUREF		0x2	/* user type is passed by reference */
 
 /*
  * A DTrace Intermediate Format variable record is used to describe each of the
