diff --git a/cmd/dtrace/test/tst/common/drops/drp.DTRACEDROP_STKSTROVERFLOW.d b/cmd/dtrace/test/tst/common/drops/drp.DTRACEDROP_STKSTROVERFLOW.d index f5d6416bce8..0911addaa61 100644 --- a/cmd/dtrace/test/tst/common/drops/drp.DTRACEDROP_STKSTROVERFLOW.d +++ b/cmd/dtrace/test/tst/common/drops/drp.DTRACEDROP_STKSTROVERFLOW.d @@ -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 diff --git a/cmd/dtrace/test/tst/common/pid/tst.emptystack.exe b/cmd/dtrace/test/tst/common/pid/tst.emptystack.exe index a8bc8cb351e..173c44d82c8 100644 --- a/cmd/dtrace/test/tst/common/pid/tst.emptystack.exe +++ b/cmd/dtrace/test/tst/common/pid/tst.emptystack.exe @@ -24,6 +24,13 @@ # Copyright 2006 Sun Microsystems, Inc. All rights reserved. # Use is subject to license terms. # -#ident "%Z%%M% %I% %E% SMI" -exec find / > /dev/null 2>&1 +# +# Copyright (c) 2012 by Delphix. All rights reserved. +# + +# +# 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 diff --git a/cmd/dtrace/test/tst/common/usdt/lazyprobe.d b/cmd/dtrace/test/tst/common/usdt/lazyprobe.d new file mode 100644 index 00000000000..86c5742a188 --- /dev/null +++ b/cmd/dtrace/test/tst/common/usdt/lazyprobe.d @@ -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(); +}; diff --git a/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe.c b/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe.c new file mode 100644 index 00000000000..ef88321807c --- /dev/null +++ b/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe.c @@ -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); +} diff --git a/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe1.ksh b/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe1.ksh new file mode 100644 index 00000000000..ee77cc2fa33 --- /dev/null +++ b/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe1.ksh @@ -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 diff --git a/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe2.ksh b/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe2.ksh new file mode 100644 index 00000000000..d0a9ca8e1f0 --- /dev/null +++ b/cmd/dtrace/test/tst/common/usdt/tst.lazyprobe2.ksh @@ -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 diff --git a/lib/libdtrace/common/dlink.h b/lib/libdtrace/common/dlink.h new file mode 100644 index 00000000000..16f0bd892d3 --- /dev/null +++ b/lib/libdtrace/common/dlink.h @@ -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 +#include + +#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 */ diff --git a/lib/libdtrace/common/dlink_audit.c b/lib/libdtrace/common/dlink_audit.c new file mode 100644 index 00000000000..57ca8d7fb7a --- /dev/null +++ b/lib/libdtrace/common/dlink_audit.c @@ -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 +#include +#include +#include + +#include + +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); + } +} diff --git a/lib/libdtrace/common/dlink_init.c b/lib/libdtrace/common/dlink_init.c new file mode 100644 index 00000000000..7c00a49c213 --- /dev/null +++ b/lib/libdtrace/common/dlink_init.c @@ -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 +#include +#include +#include + +#include + +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); +} diff --git a/lib/libdtrace/common/drti.c b/lib/libdtrace/common/drti.c deleted file mode 100644 index 3b5f0cbbdf3..00000000000 --- a/lib/libdtrace/common/drti.c +++ /dev/null @@ -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 -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -/* - * 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); -}