changeset 13788:0cb9e2232ae0

3123 need a way to force loading of DTrace helpers Reviewed by: Richard Lowe <richlowe@richlowe.net> Reviewed by: Robert Mustacchi <rm@joyent.com> Reviewed by: Bryan Cantrill <bmc@joyent.com> Approved by: Richard Lowe <richlowe@richlowe.net>
author Adam H. Leventhal <ahl@delphix.com>
date Tue, 28 Aug 2012 21:33:17 -0400
parents b4edc3a4e855
children f0c17d471b7a
files usr/src/cmd/dtrace/test/tst/common/Makefile usr/src/cmd/dtrace/test/tst/common/drops/drp.DTRACEDROP_STKSTROVERFLOW.d usr/src/cmd/dtrace/test/tst/common/pid/tst.emptystack.exe usr/src/cmd/dtrace/test/tst/common/usdt/lazyprobe.d usr/src/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe.c usr/src/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe1.ksh usr/src/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe2.ksh usr/src/lib/libdtrace/Makefile.com usr/src/lib/libdtrace/common/dlink.h usr/src/lib/libdtrace/common/dlink_audit.c usr/src/lib/libdtrace/common/dlink_common.c usr/src/lib/libdtrace/common/dlink_init.c usr/src/lib/libdtrace/common/drti.c usr/src/pkg/manifests/developer-dtrace.mf usr/src/pkg/manifests/system-dtrace-tests.mf
diffstat 15 files changed, 702 insertions(+), 229 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/cmd/dtrace/test/tst/common/Makefile	Mon Aug 27 16:36:13 2012 -0400
+++ b/usr/src/cmd/dtrace/test/tst/common/Makefile	Tue Aug 28 21:33:17 2012 -0400
@@ -23,7 +23,9 @@
 # Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-# ident	"%Z%%M%	%I%	%E% SMI"
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
 #
 
 include $(SRC)/Makefile.master
@@ -77,16 +79,16 @@
 	$(COMPILE.d) -o usdt/args.o -s usdt/args.d usdt/tst.args.o
 
 usdt/tst.argmap.exe: usdt/tst.argmap.o usdt/argmap.o
-	$(LINK.c) -o usdt/tst.argmap.exe usdt/tst.argmap.o usdt/argmap.o \
-		$(LDLIBS)
+	$(LINK.c) -o usdt/tst.argmap.exe \
+	    usdt/tst.argmap.o usdt/argmap.o $(LDLIBS)
 	$(POST_PROCESS) ; $(STRIP_STABS)
 
 usdt/argmap.o: usdt/argmap.d usdt/tst.argmap.o
 	$(COMPILE.d) -o usdt/argmap.o -s usdt/argmap.d usdt/tst.argmap.o
 
 usdt/tst.forker.exe: usdt/tst.forker.o usdt/forker.o
-	$(LINK.c) -o usdt/tst.forker.exe usdt/tst.forker.o usdt/forker.o \
-		$(LDLIBS)
+	$(LINK.c) -o usdt/tst.forker.exe \
+	    usdt/tst.forker.o usdt/forker.o $(LDLIBS)
 	$(POST_PROCESS) ; $(STRIP_STABS)
 
 usdt/forker.o: usdt/forker.d usdt/tst.forker.o
@@ -97,5 +99,19 @@
 usdt/forker.h: usdt/forker.d
 	$(DTRACE) -h -s usdt/forker.d -o usdt/forker.h
 
+usdt/tst.lazyprobe.exe: usdt/tst.lazyprobe.o usdt/lazyprobe.o
+	$(LINK.c) -o usdt/tst.lazyprobe.exe \
+	    usdt/tst.lazyprobe.o usdt/lazyprobe.o $(LDLIBS)
+	$(POST_PROCESS) ; $(STRIP_STABS)
+
+usdt/lazyprobe.o: usdt/lazyprobe.d usdt/tst.lazyprobe.o
+	$(COMPILE.d) -xlazyload -o usdt/lazyprobe.o \
+	    -s usdt/lazyprobe.d usdt/tst.lazyprobe.o
+
+usdt/tst.lazyprobe.o: usdt/lazyprobe.h
+
+usdt/lazyprobe.h: usdt/lazyprobe.d
+	$(DTRACE) -h -s usdt/lazyprobe.d -o usdt/lazyprobe.h
+
 SUBDIRS = java_api
 include ../../Makefile.subdirs
--- a/usr/src/cmd/dtrace/test/tst/common/drops/drp.DTRACEDROP_STKSTROVERFLOW.d	Mon Aug 27 16:36:13 2012 -0400
+++ b/usr/src/cmd/dtrace/test/tst/common/drops/drp.DTRACEDROP_STKSTROVERFLOW.d	Tue Aug 28 21:33:17 2012 -0400
@@ -24,7 +24,9 @@
  * Use is subject to license terms.
  */
 
-#pragma ident	"%Z%%M%	%I%	%E% SMI"
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
 
 #pragma D option destructive
 #pragma D option jstackstrsize=1
@@ -32,7 +34,13 @@
 
 BEGIN
 {
-	system("java -version");
+	/*
+	 * Since some java versions are erroneously compiled with -xlazyload
+	 * and therefore don't activate their ustack() helper by default, we
+	 * use the DTrace helper audit library to activate it.
+	 */
+	system("LD_AUDIT_32=/usr/lib/dtrace/libdtrace_forceload.so %s",
+	    "java -version");
 }
 
 syscall:::entry
--- a/usr/src/cmd/dtrace/test/tst/common/pid/tst.emptystack.exe	Mon Aug 27 16:36:13 2012 -0400
+++ b/usr/src/cmd/dtrace/test/tst/common/pid/tst.emptystack.exe	Tue Aug 28 21:33:17 2012 -0400
@@ -24,6 +24,13 @@
 # Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"%Z%%M%	%I%	%E% SMI"
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
 
-exec find / > /dev/null 2>&1
+#
+# For this test we simply require a process that will generate a bunch of
+# activity and run for a little while.
+#
+exec find / -type f -exec sleep 1 \; >/dev/null 2>&1
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/usdt/lazyprobe.d	Tue Aug 28 21:33:17 2012 -0400
@@ -0,0 +1,22 @@
+/*
+ * CDDL HEADER START
+ *
+ * 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.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+provider lazyprobe {
+	probe fire();
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe.c	Tue Aug 28 21:33:17 2012 -0400
@@ -0,0 +1,30 @@
+/*
+ * CDDL HEADER START
+ *
+ * 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.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#include "lazyprobe.h"
+
+int
+main(int argc, char **argv)
+{
+	for (;;) {
+		LAZYPROBE_FIRE();
+	}
+
+	return (0);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe1.ksh	Tue Aug 28 21:33:17 2012 -0400
@@ -0,0 +1,63 @@
+#!/usr/bin/ksh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+if [ $# != 1 ]; then
+	echo expected one argument: '<'dtrace-path'>'
+	exit 2
+fi
+
+dtrace=$1
+
+#
+# Verify that USDT objects built with -xlazyload don't fire by default.
+#
+
+./tst.lazyprobe.exe &
+id=$!
+
+ret=1
+
+$dtrace -Z -s /dev/stdin <<-EOF
+	lazyprobe*:::fire
+	{
+		exit(1);
+	}
+	tick-10hz
+	/i++ > 20/
+	{
+		exit(0);
+	}
+EOF
+ret=$?
+
+kill -9 $id
+
+exit $ret
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe2.ksh	Tue Aug 28 21:33:17 2012 -0400
@@ -0,0 +1,64 @@
+#!/usr/bin/ksh
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+# Use is subject to license terms.
+#
+
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
+if [ $# != 1 ]; then
+	echo expected one argument: '<'dtrace-path'>'
+	exit 2
+fi
+
+dtrace=$1
+
+#
+# Verify that USDT objects built with -xlazyload fire by default when using
+# the DTrace audit library.
+#
+
+LD_AUDIT_32=/usr/lib/dtrace/libdtrace_forceload.so ./tst.lazyprobe.exe &
+id=$!
+
+ret=1
+
+$dtrace -Z -s /dev/stdin <<-EOF
+	lazyprobe*:::fire
+	{
+		exit(0);
+	}
+	tick-10hz
+	/i++ > 20/
+	{
+		exit(1);
+	}
+EOF
+ret=$?
+
+kill -9 $id
+
+exit $ret
--- a/usr/src/lib/libdtrace/Makefile.com	Mon Aug 27 16:36:13 2012 -0400
+++ b/usr/src/lib/libdtrace/Makefile.com	Tue Aug 28 21:33:17 2012 -0400
@@ -70,8 +70,15 @@
 
 OBJECTS = dt_lex.o dt_grammar.o $(MACHOBJS) $(LIBSRCS:%.c=%.o) $(LIBISASRCS:%.c=%.o)
 
-DRTISRC = drti.c
-DRTIOBJ = $(DRTISRC:%.c=%.o)
+DRTISRCS = dlink_init.c dlink_common.c
+DRTIOBJS = $(DRTISRCS:%.c=pics/%.o)
+DRTIOBJ = drti.o
+
+LIBDAUDITSRCS = dlink_audit.c dlink_common.c
+LIBDAUDITOBJS = $(LIBDAUDITSRCS:%.c=pics/%.o)
+LIBDAUDIT = libdtrace_forceload.so
+
+DLINKSRCS = dlink_common.c dlink_init.c dlink_audit.c
 
 DLIBSRCS += \
 	errno.d \
@@ -131,17 +138,23 @@
 ROOTDLIBDIR64 = $(ROOT)/usr/lib/dtrace/64
 
 ROOTDLIBS = $(DLIBSRCS:%=$(ROOTDLIBDIR)/%)
-ROOTDOBJS = $(ROOTDLIBDIR)/$(DRTIOBJ)
-ROOTDOBJS64 = $(ROOTDLIBDIR64)/$(DRTIOBJ)
+ROOTDOBJS = $(ROOTDLIBDIR)/$(DRTIOBJ) $(ROOTDLIBDIR)/$(LIBDAUDIT)
+ROOTDOBJS64 = $(ROOTDLIBDIR64)/$(DRTIOBJ) $(ROOTDLIBDIR64)/$(LIBDAUDIT)
+
+$(ROOTDLIBDIR)/%.d := FILEMODE=444
+$(ROOTDLIBDIR)/%.o := FILEMODE=444
+$(ROOTDLIBDIR64)/%.o :=	FILEMODE=444
+$(ROOTDLIBDIR)/%.so := FILEMODE=555
+$(ROOTDLIBDIR64)/%.so := FILEMODE=555
 
 .KEEP_STATE:
 
-all: $(LIBS) $(DRTIOBJ)
+all: $(LIBS) $(DRTIOBJ) $(LIBDAUDIT)
 
-lint: lintdrti lintcheck
+lint: lintdlink lintcheck
 
-lintdrti: ../common/$(DRTISRC)
-	$(LINT.c) ../common/$(DRTISRC) $(DRTILDLIBS)
+lintdlink: $(DLINKSRCS:%.c=../common/%.c)
+	$(LINT.c) $(DLINKSRCS:%.c=../common/%.c) $(DRTILDLIBS)
 
 dt_lex.c: $(SRCDIR)/dt_lex.l dt_grammar.h
 	$(LEX) $(LFLAGS) $(SRCDIR)/dt_lex.l > $@
@@ -202,10 +215,16 @@
 	$(COMPILE.s) -o $@ $<
 	$(POST_PROCESS_O)
 
-%.o: ../common/%.c
-	$(COMPILE.c) -o $@ $<
+$(DRTIOBJ): $(DRTIOBJS)
+	$(LD) -o $@ -r -Blocal -Breduce $(DRTIOBJS)
 	$(POST_PROCESS_O)
 
+$(LIBDAUDIT): $(LIBDAUDITOBJS)
+	$(LINK.c) -o $@ $(GSHARED) -h$(LIBDAUDIT) $(ZTEXT) $(ZDEFS) $(BDIRECT) \
+	    $(MAPFILE.PGA:%=-M%) $(MAPFILE.NED:%=-M%) $(LIBDAUDITOBJS) \
+	    -lmapmalloc -lc -lproc
+	$(POST_PROCESS_SO)
+
 $(ROOTDLIBDIR):
 	$(INS.dir)
 
@@ -227,6 +246,12 @@
 $(ROOTDLIBDIR64)/%.o: %.o
 	$(INS.file)
 
+$(ROOTDLIBDIR)/%.so: %.so
+	$(INS.file)
+
+$(ROOTDLIBDIR64)/%.so: %.so
+	$(INS.file)
+
 $(ROOTDLIBS): $(ROOTDLIBDIR)
 
 $(ROOTDOBJS): $(ROOTDLIBDIR)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdtrace/common/dlink.h	Tue Aug 28 21:33:17 2012 -0400
@@ -0,0 +1,40 @@
+/*
+ * CDDL HEADER START
+ *
+ * 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.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+#ifndef	_DLINK_H
+#define	_DLINK_H
+
+#include <link.h>
+#include <sys/dtrace.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+
+extern const char *devname;
+
+extern void dprintf(int, const char *, ...);
+extern void dtrace_link_init(void);
+extern void dtrace_link_dof(dof_hdr_t *, Lmid_t, const char *, uintptr_t);
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _DLINK_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdtrace/common/dlink_audit.c	Tue Aug 28 21:33:17 2012 -0400
@@ -0,0 +1,128 @@
+/*
+ * CDDL HEADER START
+ *
+ * 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.
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * This file implements an audit library that can be used to force the loading
+ * of helper providers. The default disposition for a helper provider -- USDT
+ * and ustack helpers -- is to load itself from it's containing object's .init
+ * section. In cases where startup time is deemed critical, USDT authors can
+ * use the -xlazyload option to dtrace(1M) to disable automatic loading (it's
+ * difficult to make the case for the utility of this feature for anything
+ * other than libc which, indeed, was the sole motivation). If a binary has
+ * been compiled with automatic loading disabled, this audit library may be
+ * used to force automatic loading:
+ *
+ *	LD_AUDIT_32=/usr/lib/dtrace/libdaudit.so
+ *	LD_AUDIT_64=/usr/lib/dtrace/64/libdaudit.so
+ */
+
+#include <link.h>
+#include <stdio.h>
+#include <libproc.h>
+#include <strings.h>
+
+#include <dlink.h>
+
+typedef struct obj_list {
+	struct obj_list *ol_next;
+	char *ol_name;
+	uintptr_t ol_addr;
+	Lmid_t ol_lmid;
+} obj_list_t;
+
+static obj_list_t *list;
+
+#pragma init(dtrace_daudit_init)
+static void
+dtrace_daudit_init(void)
+{
+	dtrace_link_init();
+}
+
+/*ARGSUSED*/
+uint_t
+la_version(uint_t version)
+{
+	return (LAV_CURRENT);
+}
+
+/*
+ * Record objects into our linked list as they're loaded.
+ */
+/*ARGSUSED*/
+uint_t
+la_objopen(Link_map *lmp, Lmid_t lmid, uintptr_t *cookie)
+{
+	obj_list_t *node;
+
+	/*
+	 * If we can't allocate the next node in our list, we'll try to emit a
+	 * message, but it's possible that might fail as well.
+	 */
+	if ((node = malloc(sizeof (obj_list_t))) == NULL) {
+		dprintf(0, "libdaudit: failed to allocate");
+		return (0);
+	}
+	node->ol_next = list;
+	node->ol_name = strdup(lmp->l_name);
+	node->ol_addr = lmp->l_addr;
+	node->ol_lmid = lmid;
+	list = node;
+
+	return (0);
+}
+
+/*
+ * Once the link maps have reached a consistent state, process the list of
+ * objects that were loaded. We need to use libproc to search for the
+ * ___SUNW_dof symbol rather than dlsym(3C) since the symbol is not in the
+ * dynamic (run-time) symbol table (though it is, of course, in the symtab).
+ * Once we find it, we ioctl(2) it to the kernel just as we would have from
+ * the .init section if automatic loading were enabled.
+ */
+/*ARGSUSED*/
+void
+la_activity(uintptr_t *cookie, uint_t flags)
+{
+	struct ps_prochandle *P;
+	int err, ret;
+	GElf_Sym sym;
+
+	if (flags != LA_ACT_CONSISTENT)
+		return;
+
+	while (list != NULL) {
+		obj_list_t *node = list;
+		char *name = node->ol_name;
+
+		list = node->ol_next;
+
+		P = Pgrab(getpid(), PGRAB_RDONLY, &err);
+		ret = Plookup_by_name(P, name, "___SUNW_dof", &sym);
+		Prelease(P, 0);
+
+		if (ret == 0) {
+			dtrace_link_dof((void *)(uintptr_t)sym.st_value,
+			    node->ol_lmid, node->ol_name, node->ol_addr);
+		}
+
+		free(node->ol_name);
+		free(node);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdtrace/common/dlink_common.c	Tue Aug 28 21:33:17 2012 -0400
@@ -0,0 +1,166 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * Common functions for helper provider loading both compiled into the
+ * executable via drti.o and dtrace(1M) -G, and the libdaudit.so library.
+ */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <dlink.h>
+
+/*
+ * In Solaris 10 GA, the only mechanism for communicating helper information
+ * is through the DTrace helper pseudo-device node in /devices; there is
+ * no /dev link. Because of this, USDT providers and helper actions don't
+ * work inside of non-global zones. This issue was addressed by adding
+ * the /dev and having this initialization code use that /dev link. If the
+ * /dev link doesn't exist it falls back to looking for the /devices node
+ * as this code may be embedded in a binary which runs on Solaris 10 GA.
+ */
+const char *devname = "/dev/dtrace/helper";
+static const char *olddevname = "/devices/pseudo/dtrace@0:helper";
+
+static boolean_t dof_init_debug = B_FALSE;
+
+void
+dprintf(int debug, const char *fmt, ...)
+{
+	va_list ap;
+
+	if (debug && !dof_init_debug)
+		return;
+
+	va_start(ap, fmt);
+
+	(void) fprintf(stderr, "dtrace DOF: ");
+
+	(void) vfprintf(stderr, fmt, ap);
+
+	if (fmt[strlen(fmt) - 1] != '\n')
+		(void) fprintf(stderr, ": %s\n", strerror(errno));
+
+	va_end(ap);
+}
+
+/*
+ * Users may set the following environment variable to affect the way
+ * helper initialization takes place:
+ *
+ *	DTRACE_DOF_INIT_DEBUG		enable debugging output
+ *	DTRACE_DOF_INIT_DISABLE		disable helper loading
+ *	DTRACE_DOF_INIT_DEVNAME		set the path to the helper node
+ */
+void
+dtrace_link_init(void)
+{
+	if (getenv("DTRACE_DOF_INIT_DEBUG") != NULL)
+		dof_init_debug = B_TRUE;
+}
+
+void
+dtrace_link_dof(dof_hdr_t *dof, Lmid_t lmid, const char *name, uintptr_t addr)
+{
+	const char *modname;
+	const char *p;
+#ifdef _LP64
+	Elf64_Ehdr *elf;
+#else
+	Elf32_Ehdr *elf;
+#endif
+	dof_helper_t dh;
+	int fd;
+
+	if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL)
+		return;
+
+	if ((modname = strrchr(name, '/')) == NULL)
+		modname = name;
+	else
+		modname++;
+
+	if (dof->dofh_ident[DOF_ID_MAG0] != DOF_MAG_MAG0 ||
+	    dof->dofh_ident[DOF_ID_MAG1] != DOF_MAG_MAG1 ||
+	    dof->dofh_ident[DOF_ID_MAG2] != DOF_MAG_MAG2 ||
+	    dof->dofh_ident[DOF_ID_MAG3] != DOF_MAG_MAG3) {
+		dprintf(0, ".SUNW_dof section corrupt for %s\n", modname);
+		return;
+	}
+
+	elf = (void *)addr;
+
+	dh.dofhp_dof = (uintptr_t)dof;
+	dh.dofhp_addr = elf->e_type == ET_DYN ? addr : 0;
+
+	if (lmid == LM_ID_BASE) {
+		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
+		    "%s", modname);
+	} else {
+		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
+		    "LM%lu`%s", lmid, modname);
+	}
+
+	if ((p = getenv("DTRACE_DOF_INIT_DEVNAME")) != NULL)
+		devname = p;
+
+	if ((fd = open64(devname, O_RDWR)) < 0) {
+		dprintf(1, "failed to open helper device %s", devname);
+
+		/*
+		 * If the device path wasn't explicitly set, try again with
+		 * the old device path.
+		 */
+		if (p != NULL)
+			return;
+
+		devname = olddevname;
+
+		if ((fd = open64(devname, O_RDWR)) < 0) {
+			dprintf(1, "failed to open helper device %s", devname);
+			return;
+		}
+	}
+
+	if (ioctl(fd, DTRACEHIOC_ADDDOF, &dh) == -1) {
+		dprintf(1, "DTrace ioctl failed for DOF at %p in %s", dof,
+		    name);
+	} else {
+		dprintf(1, "DTrace ioctl succeeded for DOF at %p in %s\n", dof,
+		    name);
+	}
+	(void) close(fd);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/usr/src/lib/libdtrace/common/dlink_init.c	Tue Aug 28 21:33:17 2012 -0400
@@ -0,0 +1,85 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*
+ * Copyright (c) 2012 by Delphix. All rights reserved.
+ */
+
+/*
+ * This is the basis for drti.o which dt_link.c links into the object file
+ * generated by dtrace(1M) -G by default (note that -xlazyload disables this).
+ */
+
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <dlink.h>
+
+static int gen;			/* DOF helper generation */
+extern dof_hdr_t __SUNW_dof;	/* DOF defined in the .SUNW_dof section */
+
+#pragma init(dtrace_drti_init)
+static void
+dtrace_drti_init(void)
+{
+	Link_map *lmp;
+	Lmid_t lmid;
+
+	dtrace_link_init();
+
+	if (dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &lmp) == -1 || lmp == NULL) {
+		dprintf(1, "couldn't discover module name or address\n");
+		return;
+	}
+
+	if (dlinfo(RTLD_SELF, RTLD_DI_LMID, &lmid) == -1) {
+		dprintf(1, "couldn't discover link map ID\n");
+		return;
+	}
+
+	dtrace_link_dof(&__SUNW_dof, lmid, lmp->l_name, lmp->l_addr);
+}
+
+#pragma fini(dtrace_drti_fini)
+static void
+dtrace_drti_fini(void)
+{
+	int fd;
+
+	if ((fd = open64(devname, O_RDWR)) < 0) {
+		dprintf(1, "failed to open helper device %s", devname);
+		return;
+	}
+
+	if ((gen = ioctl(fd, DTRACEHIOC_REMOVE, gen)) == -1)
+		dprintf(1, "DTrace ioctl failed to remove DOF (%d)\n", gen);
+	else
+		dprintf(1, "DTrace ioctl removed DOF (%d)\n", gen);
+
+	(void) close(fd);
+}
--- a/usr/src/lib/libdtrace/common/drti.c	Mon Aug 27 16:36:13 2012 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,190 +0,0 @@
-/*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
-/*
- * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#include <unistd.h>
-#include <fcntl.h>
-#include <dlfcn.h>
-#include <link.h>
-#include <sys/dtrace.h>
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-/*
- * In Solaris 10 GA, the only mechanism for communicating helper information
- * is through the DTrace helper pseudo-device node in /devices; there is
- * no /dev link. Because of this, USDT providers and helper actions don't
- * work inside of non-global zones. This issue was addressed by adding
- * the /dev and having this initialization code use that /dev link. If the
- * /dev link doesn't exist it falls back to looking for the /devices node
- * as this code may be embedded in a binary which runs on Solaris 10 GA.
- *
- * Users may set the following environment variable to affect the way
- * helper initialization takes place:
- *
- *	DTRACE_DOF_INIT_DEBUG		enable debugging output
- *	DTRACE_DOF_INIT_DISABLE		disable helper loading
- *	DTRACE_DOF_INIT_DEVNAME		set the path to the helper node
- */
-
-static const char *devname = "/dev/dtrace/helper";
-static const char *olddevname = "/devices/pseudo/dtrace@0:helper";
-
-static const char *modname;	/* Name of this load object */
-static int gen;			/* DOF helper generation */
-extern dof_hdr_t __SUNW_dof;	/* DOF defined in the .SUNW_dof section */
-static boolean_t dof_init_debug = B_FALSE;	/* From DTRACE_DOF_INIT_DEBUG */
-
-static void
-dprintf(int debug, const char *fmt, ...)
-{
-	va_list ap;
-
-	if (debug && !dof_init_debug)
-		return;
-
-	va_start(ap, fmt);
-
-	if (modname == NULL)
-		(void) fprintf(stderr, "dtrace DOF: ");
-	else
-		(void) fprintf(stderr, "dtrace DOF %s: ", modname);
-
-	(void) vfprintf(stderr, fmt, ap);
-
-	if (fmt[strlen(fmt) - 1] != '\n')
-		(void) fprintf(stderr, ": %s\n", strerror(errno));
-
-	va_end(ap);
-}
-
-#pragma init(dtrace_dof_init)
-static void
-dtrace_dof_init(void)
-{
-	dof_hdr_t *dof = &__SUNW_dof;
-#ifdef _LP64
-	Elf64_Ehdr *elf;
-#else
-	Elf32_Ehdr *elf;
-#endif
-	dof_helper_t dh;
-	Link_map *lmp;
-	Lmid_t lmid;
-	int fd;
-	const char *p;
-
-	if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL)
-		return;
-
-	if (getenv("DTRACE_DOF_INIT_DEBUG") != NULL)
-		dof_init_debug = B_TRUE;
-
-	if (dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &lmp) == -1 || lmp == NULL) {
-		dprintf(1, "couldn't discover module name or address\n");
-		return;
-	}
-
-	if (dlinfo(RTLD_SELF, RTLD_DI_LMID, &lmid) == -1) {
-		dprintf(1, "couldn't discover link map ID\n");
-		return;
-	}
-
-	if ((modname = strrchr(lmp->l_name, '/')) == NULL)
-		modname = lmp->l_name;
-	else
-		modname++;
-
-	if (dof->dofh_ident[DOF_ID_MAG0] != DOF_MAG_MAG0 ||
-	    dof->dofh_ident[DOF_ID_MAG1] != DOF_MAG_MAG1 ||
-	    dof->dofh_ident[DOF_ID_MAG2] != DOF_MAG_MAG2 ||
-	    dof->dofh_ident[DOF_ID_MAG3] != DOF_MAG_MAG3) {
-		dprintf(0, ".SUNW_dof section corrupt\n");
-		return;
-	}
-
-	elf = (void *)lmp->l_addr;
-
-	dh.dofhp_dof = (uintptr_t)dof;
-	dh.dofhp_addr = elf->e_type == ET_DYN ? lmp->l_addr : 0;
-
-	if (lmid == 0) {
-		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
-		    "%s", modname);
-	} else {
-		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
-		    "LM%lu`%s", lmid, modname);
-	}
-
-	if ((p = getenv("DTRACE_DOF_INIT_DEVNAME")) != NULL)
-		devname = p;
-
-	if ((fd = open64(devname, O_RDWR)) < 0) {
-		dprintf(1, "failed to open helper device %s", devname);
-
-		/*
-		 * If the device path wasn't explicitly set, try again with
-		 * the old device path.
-		 */
-		if (p != NULL)
-			return;
-
-		devname = olddevname;
-
-		if ((fd = open64(devname, O_RDWR)) < 0) {
-			dprintf(1, "failed to open helper device %s", devname);
-			return;
-		}
-	}
-
-	if ((gen = ioctl(fd, DTRACEHIOC_ADDDOF, &dh)) == -1)
-		dprintf(1, "DTrace ioctl failed for DOF at %p", dof);
-	else
-		dprintf(1, "DTrace ioctl succeeded for DOF at %p\n", dof);
-
-	(void) close(fd);
-}
-
-#pragma fini(dtrace_dof_fini)
-static void
-dtrace_dof_fini(void)
-{
-	int fd;
-
-	if ((fd = open64(devname, O_RDWR)) < 0) {
-		dprintf(1, "failed to open helper device %s", devname);
-		return;
-	}
-
-	if ((gen = ioctl(fd, DTRACEHIOC_REMOVE, gen)) == -1)
-		dprintf(1, "DTrace ioctl failed to remove DOF (%d)\n", gen);
-	else
-		dprintf(1, "DTrace ioctl removed DOF (%d)\n", gen);
-
-	(void) close(fd);
-}
--- a/usr/src/pkg/manifests/developer-dtrace.mf	Mon Aug 27 16:36:13 2012 -0400
+++ b/usr/src/pkg/manifests/developer-dtrace.mf	Tue Aug 28 21:33:17 2012 -0400
@@ -23,6 +23,10 @@
 # Copyright (c) 2010, Oracle and/or its affiliates. All rights reserved.
 #
 
+#
+# Copyright (c) 2012 by Delphix. All rights reserved.
+#
+
 set name=pkg.fmri value=pkg:/developer/dtrace@$(PKGVERS)
 set name=pkg.description value="Dynamic Tracing (DTrace) Clients"
 set name=pkg.summary value="DTrace Clients"
@@ -178,26 +182,28 @@
 file path=usr/lib/$(ARCH64)/libdtrace_jni.so.1
 file path=usr/lib/$(ARCH64)/llib-ldtrace.ln
 file path=usr/lib/devfsadm/linkmod/SUNW_dtrace_link.so group=sys
-file path=usr/lib/dtrace/64/drti.o
-file path=usr/lib/dtrace/drti.o
-file path=usr/lib/dtrace/errno.d
-file path=usr/lib/dtrace/fc.d
-file path=usr/lib/dtrace/io.d
-file path=usr/lib/dtrace/ip.d
-file path=usr/lib/dtrace/iscsit.d
-file path=usr/lib/dtrace/net.d
-file path=usr/lib/dtrace/nfs.d
-file path=usr/lib/dtrace/nfssrv.d
-file path=usr/lib/dtrace/procfs.d
-file path=usr/lib/dtrace/regs.d
-file path=usr/lib/dtrace/sched.d
-file path=usr/lib/dtrace/scsi.d
-file path=usr/lib/dtrace/signal.d
-file path=usr/lib/dtrace/srp.d
-file path=usr/lib/dtrace/sysevent.d
-file path=usr/lib/dtrace/tcp.d
-file path=usr/lib/dtrace/udp.d
-file path=usr/lib/dtrace/unistd.d
+file path=usr/lib/dtrace/64/drti.o mode=0444
+file path=usr/lib/dtrace/64/libdtrace_forceload.so mode=0555
+file path=usr/lib/dtrace/drti.o mode=0444
+file path=usr/lib/dtrace/errno.d mode=0444
+file path=usr/lib/dtrace/fc.d mode=0444
+file path=usr/lib/dtrace/io.d mode=0444
+file path=usr/lib/dtrace/ip.d mode=0444
+file path=usr/lib/dtrace/iscsit.d mode=0444
+file path=usr/lib/dtrace/libdtrace_forceload.so mode=0555
+file path=usr/lib/dtrace/net.d mode=0444
+file path=usr/lib/dtrace/nfs.d mode=0444
+file path=usr/lib/dtrace/nfssrv.d mode=0444
+file path=usr/lib/dtrace/procfs.d mode=0444
+file path=usr/lib/dtrace/regs.d mode=0444
+file path=usr/lib/dtrace/sched.d mode=0444
+file path=usr/lib/dtrace/scsi.d mode=0444
+file path=usr/lib/dtrace/signal.d mode=0444
+file path=usr/lib/dtrace/srp.d mode=0444
+file path=usr/lib/dtrace/sysevent.d mode=0444
+file path=usr/lib/dtrace/tcp.d mode=0444
+file path=usr/lib/dtrace/udp.d mode=0444
+file path=usr/lib/dtrace/unistd.d mode=0444
 file path=usr/lib/libdtrace.so.1
 file path=usr/lib/libdtrace_jni.so.1
 file path=usr/lib/llib-ldtrace
--- a/usr/src/pkg/manifests/system-dtrace-tests.mf	Mon Aug 27 16:36:13 2012 -0400
+++ b/usr/src/pkg/manifests/system-dtrace-tests.mf	Tue Aug 28 21:33:17 2012 -0400
@@ -1997,6 +1997,9 @@
 file path=opt/SUNWdtrt/tst/common/usdt/tst.guess64.ksh mode=0444
 file path=opt/SUNWdtrt/tst/common/usdt/tst.header.ksh mode=0444
 file path=opt/SUNWdtrt/tst/common/usdt/tst.include.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/usdt/tst.lazyprobe.exe mode=0555
+file path=opt/SUNWdtrt/tst/common/usdt/tst.lazyprobe1.ksh mode=0444
+file path=opt/SUNWdtrt/tst/common/usdt/tst.lazyprobe2.ksh mode=0444
 file path=opt/SUNWdtrt/tst/common/usdt/tst.linkpriv.ksh mode=0444
 file path=opt/SUNWdtrt/tst/common/usdt/tst.linkunpriv.ksh mode=0444
 file path=opt/SUNWdtrt/tst/common/usdt/tst.multiple.ksh mode=0444