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