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
dprintf(int debug,const char * fmt,...)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
dtrace_link_init(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
dtrace_link_dof(dof_hdr_t * dof,Lmid_t lmid,const char * name,uintptr_t addr)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