xref: /freebsd/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c (revision 0f2bd1e89db1a2f09268edea21e0ead329e092df)
16ff6d951SJohn Birrell /*
26ff6d951SJohn Birrell  * CDDL HEADER START
36ff6d951SJohn Birrell  *
46ff6d951SJohn Birrell  * The contents of this file are subject to the terms of the
51670a1c2SRui Paulo  * Common Development and Distribution License (the "License").
61670a1c2SRui Paulo  * You may not use this file except in compliance with the License.
76ff6d951SJohn Birrell  *
86ff6d951SJohn Birrell  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96ff6d951SJohn Birrell  * or http://www.opensolaris.org/os/licensing.
106ff6d951SJohn Birrell  * See the License for the specific language governing permissions
116ff6d951SJohn Birrell  * and limitations under the License.
126ff6d951SJohn Birrell  *
136ff6d951SJohn Birrell  * When distributing Covered Code, include this CDDL HEADER in each
146ff6d951SJohn Birrell  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156ff6d951SJohn Birrell  * If applicable, add the following below this CDDL HEADER, with the
166ff6d951SJohn Birrell  * fields enclosed by brackets "[]" replaced with your own identifying
176ff6d951SJohn Birrell  * information: Portions Copyright [yyyy] [name of copyright owner]
186ff6d951SJohn Birrell  *
196ff6d951SJohn Birrell  * CDDL HEADER END
206ff6d951SJohn Birrell  */
216ff6d951SJohn Birrell /*
221670a1c2SRui Paulo  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
236ff6d951SJohn Birrell  * Use is subject to license terms.
246ff6d951SJohn Birrell  */
256ff6d951SJohn Birrell 
266ff6d951SJohn Birrell #include <unistd.h>
276ff6d951SJohn Birrell #include <fcntl.h>
286ff6d951SJohn Birrell #include <dlfcn.h>
296ff6d951SJohn Birrell #include <link.h>
306ff6d951SJohn Birrell #include <sys/dtrace.h>
316ff6d951SJohn Birrell 
326ff6d951SJohn Birrell #include <stdarg.h>
336ff6d951SJohn Birrell #include <stdio.h>
346ff6d951SJohn Birrell #include <stdlib.h>
356ff6d951SJohn Birrell #include <string.h>
366ff6d951SJohn Birrell #include <errno.h>
37*0f2bd1e8SRui Paulo #include <libelf.h>
38*0f2bd1e8SRui Paulo #include <gelf.h>
396ff6d951SJohn Birrell 
406ff6d951SJohn Birrell /*
416ff6d951SJohn Birrell  * In Solaris 10 GA, the only mechanism for communicating helper information
426ff6d951SJohn Birrell  * is through the DTrace helper pseudo-device node in /devices; there is
436ff6d951SJohn Birrell  * no /dev link. Because of this, USDT providers and helper actions don't
446ff6d951SJohn Birrell  * work inside of non-global zones. This issue was addressed by adding
456ff6d951SJohn Birrell  * the /dev and having this initialization code use that /dev link. If the
466ff6d951SJohn Birrell  * /dev link doesn't exist it falls back to looking for the /devices node
476ff6d951SJohn Birrell  * as this code may be embedded in a binary which runs on Solaris 10 GA.
486ff6d951SJohn Birrell  *
496ff6d951SJohn Birrell  * Users may set the following environment variable to affect the way
506ff6d951SJohn Birrell  * helper initialization takes place:
516ff6d951SJohn Birrell  *
526ff6d951SJohn Birrell  *	DTRACE_DOF_INIT_DEBUG		enable debugging output
536ff6d951SJohn Birrell  *	DTRACE_DOF_INIT_DISABLE		disable helper loading
546ff6d951SJohn Birrell  *	DTRACE_DOF_INIT_DEVNAME		set the path to the helper node
556ff6d951SJohn Birrell  */
566ff6d951SJohn Birrell 
575fe26f7cSJohn Birrell static const char *devnamep = "/dev/dtrace/helper";
58*0f2bd1e8SRui Paulo #if defined(sun)
596ff6d951SJohn Birrell static const char *olddevname = "/devices/pseudo/dtrace@0:helper";
60*0f2bd1e8SRui Paulo #endif
616ff6d951SJohn Birrell 
626ff6d951SJohn Birrell static const char *modname;	/* Name of this load object */
636ff6d951SJohn Birrell static int gen;			/* DOF helper generation */
64*0f2bd1e8SRui Paulo #if defined(sun)
656ff6d951SJohn Birrell extern dof_hdr_t __SUNW_dof;	/* DOF defined in the .SUNW_dof section */
66*0f2bd1e8SRui Paulo #endif
67*0f2bd1e8SRui Paulo static boolean_t dof_init_debug = B_TRUE;	/* From DTRACE_DOF_INIT_DEBUG */
686ff6d951SJohn Birrell 
696ff6d951SJohn Birrell static void
706ff6d951SJohn Birrell dprintf(int debug, const char *fmt, ...)
716ff6d951SJohn Birrell {
726ff6d951SJohn Birrell 	va_list ap;
736ff6d951SJohn Birrell 
741670a1c2SRui Paulo 	if (debug && !dof_init_debug)
756ff6d951SJohn Birrell 		return;
766ff6d951SJohn Birrell 
776ff6d951SJohn Birrell 	va_start(ap, fmt);
786ff6d951SJohn Birrell 
796ff6d951SJohn Birrell 	if (modname == NULL)
806ff6d951SJohn Birrell 		(void) fprintf(stderr, "dtrace DOF: ");
816ff6d951SJohn Birrell 	else
826ff6d951SJohn Birrell 		(void) fprintf(stderr, "dtrace DOF %s: ", modname);
836ff6d951SJohn Birrell 
846ff6d951SJohn Birrell 	(void) vfprintf(stderr, fmt, ap);
856ff6d951SJohn Birrell 
866ff6d951SJohn Birrell 	if (fmt[strlen(fmt) - 1] != '\n')
876ff6d951SJohn Birrell 		(void) fprintf(stderr, ": %s\n", strerror(errno));
886ff6d951SJohn Birrell 
896ff6d951SJohn Birrell 	va_end(ap);
906ff6d951SJohn Birrell }
916ff6d951SJohn Birrell 
92*0f2bd1e8SRui Paulo #if !defined(sun)
93*0f2bd1e8SRui Paulo static void
94*0f2bd1e8SRui Paulo fixsymbol(Elf *e, Elf_Data *data, size_t idx, int nprobes, char *buf,
95*0f2bd1e8SRui Paulo     dof_sec_t *sec, int *fixedprobes, char *dofstrtab)
96*0f2bd1e8SRui Paulo {
97*0f2bd1e8SRui Paulo 	GElf_Sym sym;
98*0f2bd1e8SRui Paulo 	char *s;
99*0f2bd1e8SRui Paulo 	unsigned char *funcname;
100*0f2bd1e8SRui Paulo 	dof_probe_t *prb;
101*0f2bd1e8SRui Paulo 	int j = 0;
102*0f2bd1e8SRui Paulo 	int ndx;
103*0f2bd1e8SRui Paulo 
104*0f2bd1e8SRui Paulo 	while (gelf_getsym(data, j++, &sym) != NULL) {
105*0f2bd1e8SRui Paulo 		prb = (dof_probe_t *)(buf + sec->dofs_offset);
106*0f2bd1e8SRui Paulo 
107*0f2bd1e8SRui Paulo 		for (ndx = nprobes; ndx; ndx--, prb += 1) {
108*0f2bd1e8SRui Paulo 			funcname = dofstrtab + prb->dofpr_func;
109*0f2bd1e8SRui Paulo 			s = elf_strptr(e, idx, sym.st_name);
110*0f2bd1e8SRui Paulo 			if (strcmp(s, funcname) == 0) {
111*0f2bd1e8SRui Paulo 				dprintf(1, "fixing %s() symbol\n", s);
112*0f2bd1e8SRui Paulo 				prb->dofpr_addr = sym.st_value;
113*0f2bd1e8SRui Paulo 				(*fixedprobes)++;
114*0f2bd1e8SRui Paulo 			}
115*0f2bd1e8SRui Paulo 		}
116*0f2bd1e8SRui Paulo 		if (*fixedprobes == nprobes)
117*0f2bd1e8SRui Paulo 			break;
118*0f2bd1e8SRui Paulo 	}
119*0f2bd1e8SRui Paulo }
120*0f2bd1e8SRui Paulo #endif
121*0f2bd1e8SRui Paulo 
1225fe26f7cSJohn Birrell #if defined(sun)
1236ff6d951SJohn Birrell #pragma init(dtrace_dof_init)
1245fe26f7cSJohn Birrell #else
1255fe26f7cSJohn Birrell static void dtrace_dof_init(void) __attribute__ ((constructor));
1265fe26f7cSJohn Birrell #endif
1275fe26f7cSJohn Birrell 
1286ff6d951SJohn Birrell static void
1296ff6d951SJohn Birrell dtrace_dof_init(void)
1306ff6d951SJohn Birrell {
131*0f2bd1e8SRui Paulo #if defined(sun)
1326ff6d951SJohn Birrell 	dof_hdr_t *dof = &__SUNW_dof;
133*0f2bd1e8SRui Paulo #else
134*0f2bd1e8SRui Paulo 	dof_hdr_t *dof = NULL;
135*0f2bd1e8SRui Paulo #endif
1366ff6d951SJohn Birrell #ifdef _LP64
1376ff6d951SJohn Birrell 	Elf64_Ehdr *elf;
1386ff6d951SJohn Birrell #else
1396ff6d951SJohn Birrell 	Elf32_Ehdr *elf;
1406ff6d951SJohn Birrell #endif
1416ff6d951SJohn Birrell 	dof_helper_t dh;
1426ff6d951SJohn Birrell 	Link_map *lmp;
143*0f2bd1e8SRui Paulo #if defined(sun)
1446ff6d951SJohn Birrell 	Lmid_t lmid;
1455fe26f7cSJohn Birrell #else
1465fe26f7cSJohn Birrell 	u_long lmid = 0;
147*0f2bd1e8SRui Paulo 	dof_sec_t *sec;
148*0f2bd1e8SRui Paulo 	size_t i;
1495fe26f7cSJohn Birrell #endif
1506ff6d951SJohn Birrell 	int fd;
1516ff6d951SJohn Birrell 	const char *p;
152*0f2bd1e8SRui Paulo #if !defined(sun)
153*0f2bd1e8SRui Paulo 	Elf *e;
154*0f2bd1e8SRui Paulo 	Elf_Scn *scn = NULL;
155*0f2bd1e8SRui Paulo 	Elf_Data *symtabdata = NULL, *dynsymdata = NULL;
156*0f2bd1e8SRui Paulo 	GElf_Shdr shdr;
157*0f2bd1e8SRui Paulo 	int efd, nprobes;
158*0f2bd1e8SRui Paulo 	char *s;
159*0f2bd1e8SRui Paulo 	size_t shstridx, symtabidx = 0, dynsymidx = 0;
160*0f2bd1e8SRui Paulo 	unsigned char *dofstrtab = NULL;
161*0f2bd1e8SRui Paulo 	unsigned char *buf;
162*0f2bd1e8SRui Paulo 	int fixedprobes = 0;
163*0f2bd1e8SRui Paulo #endif
1646ff6d951SJohn Birrell 
1656ff6d951SJohn Birrell 	if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL)
1666ff6d951SJohn Birrell 		return;
1676ff6d951SJohn Birrell 
1681670a1c2SRui Paulo 	if (getenv("DTRACE_DOF_INIT_DEBUG") != NULL)
1691670a1c2SRui Paulo 		dof_init_debug = B_TRUE;
1701670a1c2SRui Paulo 
1716ff6d951SJohn Birrell 	if (dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &lmp) == -1 || lmp == NULL) {
1726ff6d951SJohn Birrell 		dprintf(1, "couldn't discover module name or address\n");
1736ff6d951SJohn Birrell 		return;
1746ff6d951SJohn Birrell 	}
1756ff6d951SJohn Birrell 
1765fe26f7cSJohn Birrell #if defined(sun)
1776ff6d951SJohn Birrell 	if (dlinfo(RTLD_SELF, RTLD_DI_LMID, &lmid) == -1) {
1786ff6d951SJohn Birrell 		dprintf(1, "couldn't discover link map ID\n");
1796ff6d951SJohn Birrell 		return;
1806ff6d951SJohn Birrell 	}
1815fe26f7cSJohn Birrell #endif
1826ff6d951SJohn Birrell 
183*0f2bd1e8SRui Paulo 
1846ff6d951SJohn Birrell 	if ((modname = strrchr(lmp->l_name, '/')) == NULL)
1856ff6d951SJohn Birrell 		modname = lmp->l_name;
1866ff6d951SJohn Birrell 	else
1876ff6d951SJohn Birrell 		modname++;
188*0f2bd1e8SRui Paulo #if !defined(sun)
189*0f2bd1e8SRui Paulo 	elf_version(EV_CURRENT);
190*0f2bd1e8SRui Paulo 	if ((efd = open(lmp->l_name, O_RDONLY, 0)) < 0) {
191*0f2bd1e8SRui Paulo 		dprintf(1, "couldn't open file for reading\n");
192*0f2bd1e8SRui Paulo 		return;
193*0f2bd1e8SRui Paulo 	}
194*0f2bd1e8SRui Paulo 	if ((e = elf_begin(efd, ELF_C_READ, NULL)) == NULL) {
195*0f2bd1e8SRui Paulo 		dprintf(1, "elf_begin failed\n");
196*0f2bd1e8SRui Paulo 		close(efd);
197*0f2bd1e8SRui Paulo 		return;
198*0f2bd1e8SRui Paulo 	}
199*0f2bd1e8SRui Paulo 	elf_getshdrstrndx(e, &shstridx);
200*0f2bd1e8SRui Paulo 	dof = NULL;
201*0f2bd1e8SRui Paulo 	while ((scn = elf_nextscn(e, scn)) != NULL) {
202*0f2bd1e8SRui Paulo 		gelf_getshdr(scn, &shdr);
203*0f2bd1e8SRui Paulo 		if (shdr.sh_type == SHT_SYMTAB) {
204*0f2bd1e8SRui Paulo 			symtabidx = shdr.sh_link;
205*0f2bd1e8SRui Paulo 			symtabdata = elf_getdata(scn, NULL);
206*0f2bd1e8SRui Paulo 		} else if (shdr.sh_type == SHT_DYNSYM) {
207*0f2bd1e8SRui Paulo 			dynsymidx = shdr.sh_link;
208*0f2bd1e8SRui Paulo 			dynsymdata = elf_getdata(scn, NULL);
209*0f2bd1e8SRui Paulo 		} else if (shdr.sh_type == SHT_PROGBITS) {
210*0f2bd1e8SRui Paulo 			s = elf_strptr(e, shstridx, shdr.sh_name);
211*0f2bd1e8SRui Paulo 			if  (s && strcmp(s, ".SUNW_dof") == 0) {
212*0f2bd1e8SRui Paulo 				dof = elf_getdata(scn, NULL)->d_buf;
213*0f2bd1e8SRui Paulo 			}
214*0f2bd1e8SRui Paulo 		}
215*0f2bd1e8SRui Paulo 	}
216*0f2bd1e8SRui Paulo 	if (dof == NULL) {
217*0f2bd1e8SRui Paulo 		dprintf(1, "SUNW_dof section not found\n");
218*0f2bd1e8SRui Paulo 		elf_end(e);
219*0f2bd1e8SRui Paulo 		close(efd);
220*0f2bd1e8SRui Paulo 		return;
221*0f2bd1e8SRui Paulo 	}
222*0f2bd1e8SRui Paulo #endif
2236ff6d951SJohn Birrell 
2246ff6d951SJohn Birrell 	if (dof->dofh_ident[DOF_ID_MAG0] != DOF_MAG_MAG0 ||
2256ff6d951SJohn Birrell 	    dof->dofh_ident[DOF_ID_MAG1] != DOF_MAG_MAG1 ||
2266ff6d951SJohn Birrell 	    dof->dofh_ident[DOF_ID_MAG2] != DOF_MAG_MAG2 ||
2276ff6d951SJohn Birrell 	    dof->dofh_ident[DOF_ID_MAG3] != DOF_MAG_MAG3) {
2286ff6d951SJohn Birrell 		dprintf(0, ".SUNW_dof section corrupt\n");
2296ff6d951SJohn Birrell 		return;
2306ff6d951SJohn Birrell 	}
2316ff6d951SJohn Birrell 
2326ff6d951SJohn Birrell 	elf = (void *)lmp->l_addr;
2336ff6d951SJohn Birrell 
2346ff6d951SJohn Birrell 	dh.dofhp_dof = (uintptr_t)dof;
2355fe26f7cSJohn Birrell 	dh.dofhp_addr = elf->e_type == ET_DYN ? (uintptr_t) lmp->l_addr : 0;
2366ff6d951SJohn Birrell 
2376ff6d951SJohn Birrell 	if (lmid == 0) {
2386ff6d951SJohn Birrell 		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
2396ff6d951SJohn Birrell 		    "%s", modname);
2406ff6d951SJohn Birrell 	} else {
2416ff6d951SJohn Birrell 		(void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod),
2426ff6d951SJohn Birrell 		    "LM%lu`%s", lmid, modname);
2436ff6d951SJohn Birrell 	}
2446ff6d951SJohn Birrell 
2456ff6d951SJohn Birrell 	if ((p = getenv("DTRACE_DOF_INIT_DEVNAME")) != NULL)
2465fe26f7cSJohn Birrell 		devnamep = p;
2476ff6d951SJohn Birrell 
2485fe26f7cSJohn Birrell 	if ((fd = open64(devnamep, O_RDWR)) < 0) {
2495fe26f7cSJohn Birrell 		dprintf(1, "failed to open helper device %s", devnamep);
250*0f2bd1e8SRui Paulo #if defined(sun)
2516ff6d951SJohn Birrell 		/*
2526ff6d951SJohn Birrell 		 * If the device path wasn't explicitly set, try again with
2536ff6d951SJohn Birrell 		 * the old device path.
2546ff6d951SJohn Birrell 		 */
2556ff6d951SJohn Birrell 		if (p != NULL)
2566ff6d951SJohn Birrell 			return;
2576ff6d951SJohn Birrell 
2585fe26f7cSJohn Birrell 		devnamep = olddevname;
2596ff6d951SJohn Birrell 
2605fe26f7cSJohn Birrell 		if ((fd = open64(devnamep, O_RDWR)) < 0) {
2615fe26f7cSJohn Birrell 			dprintf(1, "failed to open helper device %s", devnamep);
2626ff6d951SJohn Birrell 			return;
2636ff6d951SJohn Birrell 		}
264*0f2bd1e8SRui Paulo #else
265*0f2bd1e8SRui Paulo 		return;
266*0f2bd1e8SRui Paulo #endif
2676ff6d951SJohn Birrell 	}
268*0f2bd1e8SRui Paulo #if !defined(sun)
269*0f2bd1e8SRui Paulo 	/*
270*0f2bd1e8SRui Paulo 	 * We need to fix the base address of each probe since this wasn't
271*0f2bd1e8SRui Paulo 	 * done by ld(1). (ld(1) needs to grow support for parsing the
272*0f2bd1e8SRui Paulo 	 * SUNW_dof section).
273*0f2bd1e8SRui Paulo 	 *
274*0f2bd1e8SRui Paulo 	 * The complexity of this is not that great. The first for loop
275*0f2bd1e8SRui Paulo 	 * iterates over the sections inside the DOF file. There are usually
276*0f2bd1e8SRui Paulo 	 * 10 sections here. We asume the STRTAB section comes first and the
277*0f2bd1e8SRui Paulo 	 * PROBES section comes after. Since we are only interested in fixing
278*0f2bd1e8SRui Paulo 	 * data inside the PROBES section we quit the for loop after processing
279*0f2bd1e8SRui Paulo 	 * the PROBES section. It's usually the case that the first section
280*0f2bd1e8SRui Paulo 	 * is the STRTAB section and the second section is the PROBES section,
281*0f2bd1e8SRui Paulo 	 * so this for loop is not meaningful when doing complexity analysis.
282*0f2bd1e8SRui Paulo 	 *
283*0f2bd1e8SRui Paulo 	 * After finding the probes section, we iterate over the symbols
284*0f2bd1e8SRui Paulo 	 * in the symtab section. When we find a symbol name that matches
285*0f2bd1e8SRui Paulo 	 * the probe function name, we fix it. If we have fixed all the
286*0f2bd1e8SRui Paulo 	 * probes, we exit all the loops and we are done.
287*0f2bd1e8SRui Paulo 	 * The number of probes is given by the variable 'nprobes' and this
288*0f2bd1e8SRui Paulo 	 * depends entirely on the user, but some optimizations were done.
289*0f2bd1e8SRui Paulo 	 *
290*0f2bd1e8SRui Paulo 	 * We are assuming the number of probes is less than the number of
291*0f2bd1e8SRui Paulo 	 * symbols (libc can have 4k symbols, for example).
292*0f2bd1e8SRui Paulo 	 */
293*0f2bd1e8SRui Paulo 	sec = (dof_sec_t *)(dof + 1);
294*0f2bd1e8SRui Paulo 	buf = (char *)dof;
295*0f2bd1e8SRui Paulo 	for (i = 0; i < dof->dofh_secnum; i++, sec++) {
296*0f2bd1e8SRui Paulo 		if (sec->dofs_type == DOF_SECT_STRTAB)
297*0f2bd1e8SRui Paulo 			dofstrtab = (unsigned char *)(buf + sec->dofs_offset);
298*0f2bd1e8SRui Paulo 		else if (sec->dofs_type == DOF_SECT_PROBES && dofstrtab)
299*0f2bd1e8SRui Paulo 			break;
3006ff6d951SJohn Birrell 
301*0f2bd1e8SRui Paulo 	}
302*0f2bd1e8SRui Paulo 	nprobes = sec->dofs_size / sec->dofs_entsize;
303*0f2bd1e8SRui Paulo 	fixsymbol(e, symtabdata, symtabidx, nprobes, buf, sec, &fixedprobes,
304*0f2bd1e8SRui Paulo 	    dofstrtab);
305*0f2bd1e8SRui Paulo 	if (fixedprobes != nprobes) {
306*0f2bd1e8SRui Paulo 		/*
307*0f2bd1e8SRui Paulo 		 * If we haven't fixed all the probes using the
308*0f2bd1e8SRui Paulo 		 * symtab section, look inside the dynsym
309*0f2bd1e8SRui Paulo 		 * section.
310*0f2bd1e8SRui Paulo 		 */
311*0f2bd1e8SRui Paulo 		fixsymbol(e, dynsymdata, dynsymidx, nprobes, buf, sec,
312*0f2bd1e8SRui Paulo 		    &fixedprobes, dofstrtab);
313*0f2bd1e8SRui Paulo 	}
314*0f2bd1e8SRui Paulo 	if (fixedprobes != nprobes) {
315*0f2bd1e8SRui Paulo 		fprintf(stderr, "WARNING: number of probes "
316*0f2bd1e8SRui Paulo 		    "fixed does not match the number of "
317*0f2bd1e8SRui Paulo 		    "defined probes (%d != %d, "
318*0f2bd1e8SRui Paulo 		    "respectively)\n", fixedprobes, nprobes);
319*0f2bd1e8SRui Paulo 		fprintf(stderr, "WARNING: some probes might "
320*0f2bd1e8SRui Paulo 		    "not fire or your program might crash\n");
321*0f2bd1e8SRui Paulo 	}
322*0f2bd1e8SRui Paulo #endif
3236ff6d951SJohn Birrell 	if ((gen = ioctl(fd, DTRACEHIOC_ADDDOF, &dh)) == -1)
3246ff6d951SJohn Birrell 		dprintf(1, "DTrace ioctl failed for DOF at %p", dof);
325*0f2bd1e8SRui Paulo 	else {
3266ff6d951SJohn Birrell 		dprintf(1, "DTrace ioctl succeeded for DOF at %p\n", dof);
327*0f2bd1e8SRui Paulo #if !defined(sun)
328*0f2bd1e8SRui Paulo 		gen = dh.gen;
329*0f2bd1e8SRui Paulo #endif
330*0f2bd1e8SRui Paulo 	}
3316ff6d951SJohn Birrell 
3326ff6d951SJohn Birrell 	(void) close(fd);
333*0f2bd1e8SRui Paulo #if !defined(sun)
334*0f2bd1e8SRui Paulo 	elf_end(e);
335*0f2bd1e8SRui Paulo 	(void) close(efd);
336*0f2bd1e8SRui Paulo #endif
3376ff6d951SJohn Birrell }
3386ff6d951SJohn Birrell 
3395fe26f7cSJohn Birrell #if defined(sun)
3406ff6d951SJohn Birrell #pragma fini(dtrace_dof_fini)
3415fe26f7cSJohn Birrell #else
3425fe26f7cSJohn Birrell static void dtrace_dof_fini(void) __attribute__ ((destructor));
3435fe26f7cSJohn Birrell #endif
3445fe26f7cSJohn Birrell 
3456ff6d951SJohn Birrell static void
3466ff6d951SJohn Birrell dtrace_dof_fini(void)
3476ff6d951SJohn Birrell {
3486ff6d951SJohn Birrell 	int fd;
3496ff6d951SJohn Birrell 
3505fe26f7cSJohn Birrell 	if ((fd = open64(devnamep, O_RDWR)) < 0) {
3515fe26f7cSJohn Birrell 		dprintf(1, "failed to open helper device %s", devnamep);
3526ff6d951SJohn Birrell 		return;
3536ff6d951SJohn Birrell 	}
3546ff6d951SJohn Birrell 
355*0f2bd1e8SRui Paulo 	if ((gen = ioctl(fd, DTRACEHIOC_REMOVE, &gen)) == -1)
3566ff6d951SJohn Birrell 		dprintf(1, "DTrace ioctl failed to remove DOF (%d)\n", gen);
3576ff6d951SJohn Birrell 	else
3586ff6d951SJohn Birrell 		dprintf(1, "DTrace ioctl removed DOF (%d)\n", gen);
3596ff6d951SJohn Birrell 
3606ff6d951SJohn Birrell 	(void) close(fd);
3616ff6d951SJohn Birrell }
362