Changeset View
Changeset View
Standalone View
Standalone View
head/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c
Show All 30 Lines | |||||
#include <sys/dtrace.h> | #include <sys/dtrace.h> | ||||
#include <stdarg.h> | #include <stdarg.h> | ||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <errno.h> | #include <errno.h> | ||||
#include <libelf.h> | #include <libelf.h> | ||||
#include <gelf.h> | |||||
/* | /* | ||||
* In Solaris 10 GA, the only mechanism for communicating helper information | * In Solaris 10 GA, the only mechanism for communicating helper information | ||||
* is through the DTrace helper pseudo-device node in /devices; there is | * 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 | * 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 | * 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 | * 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 | * /dev link doesn't exist it falls back to looking for the /devices node | ||||
Show All 9 Lines | |||||
static const char *devnamep = "/dev/dtrace/helper"; | static const char *devnamep = "/dev/dtrace/helper"; | ||||
#ifdef illumos | #ifdef illumos | ||||
static const char *olddevname = "/devices/pseudo/dtrace@0:helper"; | static const char *olddevname = "/devices/pseudo/dtrace@0:helper"; | ||||
#endif | #endif | ||||
static const char *modname; /* Name of this load object */ | static const char *modname; /* Name of this load object */ | ||||
static int gen; /* DOF helper generation */ | static int gen; /* DOF helper generation */ | ||||
#ifdef illumos | |||||
extern dof_hdr_t __SUNW_dof; /* DOF defined in the .SUNW_dof section */ | extern dof_hdr_t __SUNW_dof; /* DOF defined in the .SUNW_dof section */ | ||||
#endif | |||||
static boolean_t dof_init_debug = B_FALSE; /* From DTRACE_DOF_INIT_DEBUG */ | static boolean_t dof_init_debug = B_FALSE; /* From DTRACE_DOF_INIT_DEBUG */ | ||||
static void | static void | ||||
dprintf(int debug, const char *fmt, ...) | dprintf(int debug, const char *fmt, ...) | ||||
{ | { | ||||
va_list ap; | va_list ap; | ||||
if (debug && !dof_init_debug) | if (debug && !dof_init_debug) | ||||
Show All 18 Lines | |||||
#pragma init(dtrace_dof_init) | #pragma init(dtrace_dof_init) | ||||
#else | #else | ||||
static void dtrace_dof_init(void) __attribute__ ((constructor)); | static void dtrace_dof_init(void) __attribute__ ((constructor)); | ||||
#endif | #endif | ||||
static void | static void | ||||
dtrace_dof_init(void) | dtrace_dof_init(void) | ||||
{ | { | ||||
#ifdef illumos | |||||
dof_hdr_t *dof = &__SUNW_dof; | dof_hdr_t *dof = &__SUNW_dof; | ||||
#else | |||||
dof_hdr_t *dof = NULL; | |||||
#endif | |||||
#ifdef _LP64 | #ifdef _LP64 | ||||
Elf64_Ehdr *elf; | Elf64_Ehdr *elf; | ||||
#else | #else | ||||
Elf32_Ehdr *elf; | Elf32_Ehdr *elf; | ||||
#endif | #endif | ||||
dof_helper_t dh; | dof_helper_t dh; | ||||
Link_map *lmp = NULL; | Link_map *lmp = NULL; | ||||
#ifdef illumos | #ifdef illumos | ||||
Lmid_t lmid; | Lmid_t lmid; | ||||
#else | #else | ||||
u_long lmid = 0; | u_long lmid = 0; | ||||
#endif | #endif | ||||
int fd; | int fd; | ||||
const char *p; | const char *p; | ||||
#ifndef illumos | |||||
Elf *e; | |||||
Elf_Scn *scn = NULL; | |||||
Elf_Data *dofdata = NULL; | |||||
dof_hdr_t *dof_next = NULL; | |||||
GElf_Shdr shdr; | |||||
int efd; | |||||
char *s; | |||||
size_t shstridx; | |||||
uint64_t aligned_filesz; | |||||
#endif | |||||
if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL) | if (getenv("DTRACE_DOF_INIT_DISABLE") != NULL) | ||||
return; | return; | ||||
if (getenv("DTRACE_DOF_INIT_DEBUG") != NULL) | if (getenv("DTRACE_DOF_INIT_DEBUG") != NULL) | ||||
dof_init_debug = B_TRUE; | dof_init_debug = B_TRUE; | ||||
if (dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &lmp) == -1 || lmp == NULL) { | if (dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &lmp) == -1 || lmp == NULL) { | ||||
dprintf(1, "couldn't discover module name or address\n"); | dprintf(1, "couldn't discover module name or address\n"); | ||||
return; | return; | ||||
} | } | ||||
#ifdef illumos | #ifdef illumos | ||||
if (dlinfo(RTLD_SELF, RTLD_DI_LMID, &lmid) == -1) { | if (dlinfo(RTLD_SELF, RTLD_DI_LMID, &lmid) == -1) { | ||||
dprintf(1, "couldn't discover link map ID\n"); | dprintf(1, "couldn't discover link map ID\n"); | ||||
return; | return; | ||||
} | } | ||||
#endif | #endif | ||||
if ((modname = strrchr(lmp->l_name, '/')) == NULL) | if ((modname = strrchr(lmp->l_name, '/')) == NULL) | ||||
modname = lmp->l_name; | modname = lmp->l_name; | ||||
else | else | ||||
modname++; | modname++; | ||||
#ifndef illumos | |||||
elf_version(EV_CURRENT); | |||||
if ((efd = open(lmp->l_name, O_RDONLY, 0)) < 0) { | |||||
dprintf(1, "couldn't open file for reading\n"); | |||||
return; | |||||
} | |||||
if ((e = elf_begin(efd, ELF_C_READ, NULL)) == NULL) { | |||||
dprintf(1, "elf_begin failed\n"); | |||||
close(efd); | |||||
return; | |||||
} | |||||
elf_getshdrstrndx(e, &shstridx); | |||||
dof = NULL; | |||||
while ((scn = elf_nextscn(e, scn)) != NULL) { | |||||
gelf_getshdr(scn, &shdr); | |||||
if (shdr.sh_type == SHT_SUNW_dof) { | |||||
s = elf_strptr(e, shstridx, shdr.sh_name); | |||||
if (s != NULL && strcmp(s, ".SUNW_dof") == 0) { | |||||
dofdata = elf_getdata(scn, NULL); | |||||
dof = dofdata->d_buf; | |||||
break; | |||||
} | |||||
} | |||||
} | |||||
if (dof == NULL) { | |||||
dprintf(1, "SUNW_dof section not found\n"); | |||||
elf_end(e); | |||||
close(efd); | |||||
return; | |||||
} | |||||
while ((char *) dof < (char *) dofdata->d_buf + dofdata->d_size) { | |||||
aligned_filesz = (shdr.sh_addralign == 0 ? dof->dofh_filesz : | |||||
roundup2(dof->dofh_filesz, shdr.sh_addralign)); | |||||
dof_next = (void *) ((char *) dof + aligned_filesz); | |||||
#endif | |||||
if (dof->dofh_ident[DOF_ID_MAG0] != DOF_MAG_MAG0 || | if (dof->dofh_ident[DOF_ID_MAG0] != DOF_MAG_MAG0 || | ||||
dof->dofh_ident[DOF_ID_MAG1] != DOF_MAG_MAG1 || | dof->dofh_ident[DOF_ID_MAG1] != DOF_MAG_MAG1 || | ||||
dof->dofh_ident[DOF_ID_MAG2] != DOF_MAG_MAG2 || | dof->dofh_ident[DOF_ID_MAG2] != DOF_MAG_MAG2 || | ||||
dof->dofh_ident[DOF_ID_MAG3] != DOF_MAG_MAG3) { | dof->dofh_ident[DOF_ID_MAG3] != DOF_MAG_MAG3) { | ||||
dprintf(0, ".SUNW_dof section corrupt\n"); | dprintf(0, ".SUNW_dof section corrupt\n"); | ||||
return; | return; | ||||
} | } | ||||
Show All 32 Lines | |||||
#else | #else | ||||
return; | return; | ||||
#endif | #endif | ||||
} | } | ||||
if ((gen = ioctl(fd, DTRACEHIOC_ADDDOF, &dh)) == -1) | if ((gen = ioctl(fd, DTRACEHIOC_ADDDOF, &dh)) == -1) | ||||
dprintf(1, "DTrace ioctl failed for DOF at %p", dof); | dprintf(1, "DTrace ioctl failed for DOF at %p", dof); | ||||
else { | else { | ||||
dprintf(1, "DTrace ioctl succeeded for DOF at %p\n", dof); | dprintf(1, "DTrace ioctl succeeded for DOF at %p\n", dof); | ||||
#ifndef illumos | #ifdef __FreeBSD__ | ||||
gen = dh.gen; | gen = dh.gen; | ||||
#endif | #endif | ||||
} | } | ||||
(void) close(fd); | (void) close(fd); | ||||
#ifndef illumos | |||||
/* End of while loop */ | |||||
dof = dof_next; | |||||
} | |||||
elf_end(e); | |||||
(void) close(efd); | |||||
#endif | |||||
} | } | ||||
#ifdef illumos | #ifdef illumos | ||||
#pragma fini(dtrace_dof_fini) | #pragma fini(dtrace_dof_fini) | ||||
#else | #else | ||||
static void dtrace_dof_fini(void) __attribute__ ((destructor)); | static void dtrace_dof_fini(void) __attribute__ ((destructor)); | ||||
#endif | #endif | ||||
Show All 17 Lines |