xref: /titanic_52/usr/src/lib/libdtrace/common/dlink_common.c (revision edb348833aaacfa1176e502ad38875fd0b2717ab)
1*edb34883SAdam H. Leventhal /*
2*edb34883SAdam H. Leventhal  * CDDL HEADER START
3*edb34883SAdam H. Leventhal  *
4*edb34883SAdam H. Leventhal  * The contents of this file are subject to the terms of the
5*edb34883SAdam H. Leventhal  * Common Development and Distribution License (the "License").
6*edb34883SAdam H. Leventhal  * You may not use this file except in compliance with the License.
7*edb34883SAdam H. Leventhal  *
8*edb34883SAdam H. Leventhal  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*edb34883SAdam H. Leventhal  * or http://www.opensolaris.org/os/licensing.
10*edb34883SAdam H. Leventhal  * See the License for the specific language governing permissions
11*edb34883SAdam H. Leventhal  * and limitations under the License.
12*edb34883SAdam H. Leventhal  *
13*edb34883SAdam H. Leventhal  * When distributing Covered Code, include this CDDL HEADER in each
14*edb34883SAdam H. Leventhal  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*edb34883SAdam H. Leventhal  * If applicable, add the following below this CDDL HEADER, with the
16*edb34883SAdam H. Leventhal  * fields enclosed by brackets "[]" replaced with your own identifying
17*edb34883SAdam H. Leventhal  * information: Portions Copyright [yyyy] [name of copyright owner]
18*edb34883SAdam H. Leventhal  *
19*edb34883SAdam H. Leventhal  * CDDL HEADER END
20*edb34883SAdam H. Leventhal  */
21*edb34883SAdam H. Leventhal 
22*edb34883SAdam H. Leventhal /*
23*edb34883SAdam H. Leventhal  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24*edb34883SAdam H. Leventhal  * Use is subject to license terms.
25*edb34883SAdam H. Leventhal  */
26*edb34883SAdam H. Leventhal 
27*edb34883SAdam H. Leventhal /*
28*edb34883SAdam H. Leventhal  * Copyright (c) 2012 by Delphix. All rights reserved.
29*edb34883SAdam H. Leventhal  */
30*edb34883SAdam H. Leventhal 
31*edb34883SAdam H. Leventhal /*
32*edb34883SAdam H. Leventhal  * Common functions for helper provider loading both compiled into the
33*edb34883SAdam H. Leventhal  * executable via drti.o and dtrace(1M) -G, and the libdaudit.so library.
34*edb34883SAdam H. Leventhal  */
35*edb34883SAdam H. Leventhal 
36*edb34883SAdam H. Leventhal #include <errno.h>
37*edb34883SAdam H. Leventhal #include <fcntl.h>
38*edb34883SAdam H. Leventhal #include <stdarg.h>
39*edb34883SAdam H. Leventhal #include <stdio.h>
40*edb34883SAdam H. Leventhal #include <stdlib.h>
41*edb34883SAdam H. Leventhal #include <string.h>
42*edb34883SAdam H. Leventhal #include <unistd.h>
43*edb34883SAdam H. Leventhal 
44*edb34883SAdam H. Leventhal #include <dlink.h>
45*edb34883SAdam H. Leventhal 
46*edb34883SAdam H. Leventhal /*
47*edb34883SAdam H. Leventhal  * In Solaris 10 GA, the only mechanism for communicating helper information
48*edb34883SAdam H. Leventhal  * is through the DTrace helper pseudo-device node in /devices; there is
49*edb34883SAdam H. Leventhal  * no /dev link. Because of this, USDT providers and helper actions don't
50*edb34883SAdam H. Leventhal  * work inside of non-global zones. This issue was addressed by adding
51*edb34883SAdam H. Leventhal  * the /dev and having this initialization code use that /dev link. If the
52*edb34883SAdam H. Leventhal  * /dev link doesn't exist it falls back to looking for the /devices node
53*edb34883SAdam H. Leventhal  * as this code may be embedded in a binary which runs on Solaris 10 GA.
54*edb34883SAdam H. Leventhal  */
55*edb34883SAdam H. Leventhal const char *devname = "/dev/dtrace/helper";
56*edb34883SAdam H. Leventhal static const char *olddevname = "/devices/pseudo/dtrace@0:helper";
57*edb34883SAdam H. Leventhal 
58*edb34883SAdam H. Leventhal static boolean_t dof_init_debug = B_FALSE;
59*edb34883SAdam H. Leventhal 
60*edb34883SAdam H. Leventhal void
61*edb34883SAdam H. Leventhal dprintf(int debug, const char *fmt, ...)
62*edb34883SAdam H. Leventhal {
63*edb34883SAdam H. Leventhal 	va_list ap;
64*edb34883SAdam H. Leventhal 
65*edb34883SAdam H. Leventhal 	if (debug && !dof_init_debug)
66*edb34883SAdam H. Leventhal 		return;
67*edb34883SAdam H. Leventhal 
68*edb34883SAdam H. Leventhal 	va_start(ap, fmt);
69*edb34883SAdam H. Leventhal 
70*edb34883SAdam H. Leventhal 	(void) fprintf(stderr, "dtrace DOF: ");
71*edb34883SAdam H. Leventhal 
72*edb34883SAdam H. Leventhal 	(void) vfprintf(stderr, fmt, ap);
73*edb34883SAdam H. Leventhal 
74*edb34883SAdam H. Leventhal 	if (fmt[strlen(fmt) - 1] != '\n')
75*edb34883SAdam H. Leventhal 		(void) fprintf(stderr, ": %s\n", strerror(errno));
76*edb34883SAdam H. Leventhal 
77*edb34883SAdam H. Leventhal 	va_end(ap);
78*edb34883SAdam H. Leventhal }
79*edb34883SAdam H. Leventhal 
80*edb34883SAdam H. Leventhal /*
81*edb34883SAdam H. Leventhal  * Users may set the following environment variable to affect the way
82*edb34883SAdam H. Leventhal  * helper initialization takes place:
83*edb34883SAdam H. Leventhal  *
84*edb34883SAdam H. Leventhal  *	DTRACE_DOF_INIT_DEBUG		enable debugging output
85*edb34883SAdam H. Leventhal  *	DTRACE_DOF_INIT_DISABLE		disable helper loading
86*edb34883SAdam H. Leventhal  *	DTRACE_DOF_INIT_DEVNAME		set the path to the helper node
87*edb34883SAdam H. Leventhal  */
88*edb34883SAdam H. Leventhal void
89*edb34883SAdam H. Leventhal dtrace_link_init(void)
90*edb34883SAdam H. Leventhal {
91*edb34883SAdam H. Leventhal 	if (getenv("DTRACE_DOF_INIT_DEBUG") != NULL)
92*edb34883SAdam H. Leventhal 		dof_init_debug = B_TRUE;
93*edb34883SAdam H. Leventhal }
94*edb34883SAdam H. Leventhal 
95*edb34883SAdam H. Leventhal void
96*edb34883SAdam H. Leventhal dtrace_link_dof(dof_hdr_t *dof, Lmid_t lmid, const char *name, uintptr_t addr)
97*edb34883SAdam H. Leventhal {
98*edb34883SAdam H. Leventhal 	const char *modname;
99*edb34883SAdam H. Leventhal 	const char *p;
100*edb34883SAdam H. Leventhal #ifdef _LP64
101*edb34883SAdam H. Leventhal 	Elf64_Ehdr *elf;
102*edb34883SAdam H. Leventhal #else
103*edb34883SAdam H. Leventhal 	Elf32_Ehdr *elf;
104*edb34883SAdam H. Leventhal #endif
105*edb34883SAdam H. Leventhal 	dof_helper_t dh;
106*edb34883SAdam H. Leventhal 	int fd;
107*edb34883SAdam H. Leventhal 
108*edb34883SAdam H. Leventhal 	if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL)
109*edb34883SAdam H. Leventhal 		return;
110*edb34883SAdam H. Leventhal 
111*edb34883SAdam H. Leventhal 	if ((modname = strrchr(name, '/')) == NULL)
112*edb34883SAdam H. Leventhal 		modname = name;
113*edb34883SAdam H. Leventhal 	else
114*edb34883SAdam H. Leventhal 		modname++;
115*edb34883SAdam H. Leventhal 
116*edb34883SAdam H. Leventhal 	if (dof->dofh_ident[DOF_ID_MAG0] != DOF_MAG_MAG0 ||
117*edb34883SAdam H. Leventhal 	    dof->dofh_ident[DOF_ID_MAG1] != DOF_MAG_MAG1 ||
118*edb34883SAdam H. Leventhal 	    dof->dofh_ident[DOF_ID_MAG2] != DOF_MAG_MAG2 ||
119*edb34883SAdam H. Leventhal 	    dof->dofh_ident[DOF_ID_MAG3] != DOF_MAG_MAG3) {
120*edb34883SAdam H. Leventhal 		dprintf(0, ".SUNW_dof section corrupt for %s\n", modname);
121*edb34883SAdam H. Leventhal 		return;
122*edb34883SAdam H. Leventhal 	}
123*edb34883SAdam H. Leventhal 
124*edb34883SAdam H. Leventhal 	elf = (void *)addr;
125*edb34883SAdam H. Leventhal 
126*edb34883SAdam H. Leventhal 	dh.dofhp_dof = (uintptr_t)dof;
127*edb34883SAdam H. Leventhal 	dh.dofhp_addr = elf->e_type == ET_DYN ? addr : 0;
128*edb34883SAdam H. Leventhal 
129*edb34883SAdam H. Leventhal 	if (lmid == LM_ID_BASE) {
130*edb34883SAdam H. Leventhal 		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
131*edb34883SAdam H. Leventhal 		    "%s", modname);
132*edb34883SAdam H. Leventhal 	} else {
133*edb34883SAdam H. Leventhal 		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
134*edb34883SAdam H. Leventhal 		    "LM%lu`%s", lmid, modname);
135*edb34883SAdam H. Leventhal 	}
136*edb34883SAdam H. Leventhal 
137*edb34883SAdam H. Leventhal 	if ((p = getenv("DTRACE_DOF_INIT_DEVNAME")) != NULL)
138*edb34883SAdam H. Leventhal 		devname = p;
139*edb34883SAdam H. Leventhal 
140*edb34883SAdam H. Leventhal 	if ((fd = open64(devname, O_RDWR)) < 0) {
141*edb34883SAdam H. Leventhal 		dprintf(1, "failed to open helper device %s", devname);
142*edb34883SAdam H. Leventhal 
143*edb34883SAdam H. Leventhal 		/*
144*edb34883SAdam H. Leventhal 		 * If the device path wasn't explicitly set, try again with
145*edb34883SAdam H. Leventhal 		 * the old device path.
146*edb34883SAdam H. Leventhal 		 */
147*edb34883SAdam H. Leventhal 		if (p != NULL)
148*edb34883SAdam H. Leventhal 			return;
149*edb34883SAdam H. Leventhal 
150*edb34883SAdam H. Leventhal 		devname = olddevname;
151*edb34883SAdam H. Leventhal 
152*edb34883SAdam H. Leventhal 		if ((fd = open64(devname, O_RDWR)) < 0) {
153*edb34883SAdam H. Leventhal 			dprintf(1, "failed to open helper device %s", devname);
154*edb34883SAdam H. Leventhal 			return;
155*edb34883SAdam H. Leventhal 		}
156*edb34883SAdam H. Leventhal 	}
157*edb34883SAdam H. Leventhal 
158*edb34883SAdam H. Leventhal 	if (ioctl(fd, DTRACEHIOC_ADDDOF, &dh) == -1) {
159*edb34883SAdam H. Leventhal 		dprintf(1, "DTrace ioctl failed for DOF at %p in %s", dof,
160*edb34883SAdam H. Leventhal 		    name);
161*edb34883SAdam H. Leventhal 	} else {
162*edb34883SAdam H. Leventhal 		dprintf(1, "DTrace ioctl succeeded for DOF at %p in %s\n", dof,
163*edb34883SAdam H. Leventhal 		    name);
164*edb34883SAdam H. Leventhal 	}
165*edb34883SAdam H. Leventhal 	(void) close(fd);
166*edb34883SAdam H. Leventhal }
167