diff options
author | markj <markj@FreeBSD.org> | 2015-04-08 02:36:37 +0000 |
---|---|---|
committer | markj <markj@FreeBSD.org> | 2015-04-08 02:36:37 +0000 |
commit | 1d6ffde4f49799c1d95f31875779237c214fc09c (patch) | |
tree | 48267c7be89f3f03d035711a7b82b3453bab848e /cddl/contrib/opensolaris/lib/libdtrace/common | |
parent | 245de71cf80d02d4ff02fcf352fb7f056c686821 (diff) | |
download | FreeBSD-src-1d6ffde4f49799c1d95f31875779237c214fc09c.zip FreeBSD-src-1d6ffde4f49799c1d95f31875779237c214fc09c.tar.gz |
libdtrace: add support for lazyload mode.
Passing "-x lazyload" to dtrace -G during compilation causes dtrace(1) to
not link drti.o into the output object file, so the USDT probes are not created
during process startup. Instead, dtrace(1) will automatically discover and
create probes on the process' behalf when attaching.
Differential Revision: https://reviews.freebsd.org/D2203
Reviewed by: rpaulo
MFC after: 1 month
Diffstat (limited to 'cddl/contrib/opensolaris/lib/libdtrace/common')
-rw-r--r-- | cddl/contrib/opensolaris/lib/libdtrace/common/drti.c | 5 | ||||
-rw-r--r-- | cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c | 16 | ||||
-rw-r--r-- | cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c | 75 |
3 files changed, 79 insertions, 17 deletions
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c b/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c index a75dc02..5fab935 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c @@ -147,6 +147,9 @@ dtrace_dof_init(void) dh.dofhp_dof = (uintptr_t)dof; dh.dofhp_addr = elf->e_type == ET_DYN ? (uintptr_t) lmp->l_addr : 0; +#ifdef __FreeBSD__ + dh.dofhp_pid = getpid(); +#endif if (lmid == 0) { (void) snprintf(dh.dofhp_mod, sizeof (dh.dofhp_mod), @@ -184,7 +187,7 @@ dtrace_dof_init(void) else { dprintf(1, "DTrace ioctl succeeded for DOF at %p\n", dof); #ifdef __FreeBSD__ - gen = dh.gen; + gen = dh.dofhp_gen; #endif } diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c index ae41269..eaf0961 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c @@ -1785,11 +1785,17 @@ dtrace_program_link(dtrace_hdl_t *dtp, dtrace_prog_t *pgp, uint_t dflags, "failed to open %s: %s", file, strerror(errno))); } #else - snprintf(tfile, sizeof(tfile), "%s.XXXXXX", file); - if ((fd = mkstemp(tfile)) == -1) - return (dt_link_error(dtp, NULL, -1, NULL, - "failed to create temporary file %s: %s", - tfile, strerror(errno))); + if (dtp->dt_lazyload) { + if ((fd = open(file, O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0) + return (dt_link_error(dtp, NULL, -1, NULL, + "failed to open %s: %s", file, strerror(errno))); + } else { + snprintf(tfile, sizeof(tfile), "%s.XXXXXX", file); + if ((fd = mkstemp(tfile)) == -1) + return (dt_link_error(dtp, NULL, -1, NULL, + "failed to create temporary file %s: %s", + tfile, strerror(errno))); + } #endif /* diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c index e628e62..c61a710 100644 --- a/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c +++ b/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c @@ -44,10 +44,15 @@ #include <dt_program.h> #include <dt_pid.h> #include <dt_string.h> +#include <dt_module.h> + #ifndef illumos +#include <sys/sysctl.h> +#include <unistd.h> #include <libproc_compat.h> +#include <libelf.h> +#include <gelf.h> #endif -#include <dt_module.h> typedef struct dt_pid_probe { dtrace_hdl_t *dpp_dtp; @@ -566,6 +571,12 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname) prsyminfo_t sip; dof_helper_t dh; GElf_Half e_type; +#ifdef __FreeBSD__ + dof_hdr_t hdr; + size_t sz; + uint64_t dofmax; + void *dof; +#endif const char *mname; const char *syms[] = { "___SUNW_dof", "__SUNW_dof" }; int i, fd = -1; @@ -595,17 +606,61 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname) continue; } - dh.dofhp_dof = sym.st_value; +#ifdef __FreeBSD__ dh.dofhp_addr = (e_type == ET_EXEC) ? 0 : pmp->pr_vaddr; + if (Pread(P, &hdr, sizeof (hdr), sym.st_value) != + sizeof (hdr)) { + dt_dprintf("read of DOF header failed\n"); + continue; + } + + sz = sizeof(dofmax); + if (sysctlbyname("kern.dtrace.dof_maxsize", &dofmax, &sz, + NULL, 0) != 0) { + dt_dprintf("failed to read dof_maxsize: %s\n", + strerror(errno)); + continue; + } + if (dofmax < hdr.dofh_loadsz) { + dt_dprintf("DOF load size exceeds maximum\n"); + continue; + } + + if ((dof = malloc(hdr.dofh_loadsz)) == NULL) + return (-1); + + if (Pread(P, dof, hdr.dofh_loadsz, sym.st_value) != + hdr.dofh_loadsz) { + free(dof); + dt_dprintf("read of DOF section failed\n"); + continue; + } + + dh.dofhp_dof = (uintptr_t)dof; + dh.dofhp_pid = proc_getpid(P); dt_pid_objname(dh.dofhp_mod, sizeof (dh.dofhp_mod), -#ifdef illumos sip.prs_lmid, mname); + + if (fd == -1 && + (fd = open("/dev/dtrace/helper", O_RDWR, 0)) < 0) { + dt_dprintf("open of helper device failed: %s\n", + strerror(errno)); + free(dof); + return (-1); /* errno is set for us */ + } + + if (ioctl(fd, DTRACEHIOC_ADDDOF, &dh, sizeof (dh)) < 0) + dt_dprintf("DOF was rejected for %s\n", dh.dofhp_mod); + + free(dof); #else - 0, mname); -#endif + dh.dofhp_dof = sym.st_value; + dh.dofhp_addr = (e_type == ET_EXEC) ? 0 : pmp->pr_vaddr; + + dt_pid_objname(dh.dofhp_mod, sizeof (dh.dofhp_mod), + sip.prs_lmid, mname); -#ifdef illumos if (fd == -1 && (fd = pr_open(P, "/dev/dtrace/helper", O_RDWR, 0)) < 0) { dt_dprintf("pr_open of helper device failed: %s\n", @@ -618,8 +673,10 @@ dt_pid_usdt_mapping(void *data, const prmap_t *pmp, const char *oname) #endif } -#ifdef illumos if (fd != -1) +#ifdef __FreeBSD__ + (void) close(fd); +#else (void) pr_close(P, fd); #endif @@ -634,7 +691,6 @@ dt_pid_create_usdt_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, int ret = 0; assert(DT_MUTEX_HELD(&dpr->dpr_lock)); -#ifdef illumos (void) Pupdate_maps(P); if (Pobject_iter(P, dt_pid_usdt_mapping, P) != 0) { ret = -1; @@ -646,9 +702,6 @@ dt_pid_create_usdt_probes(dtrace_probedesc_t *pdp, dtrace_hdl_t *dtp, (int)proc_getpid(P), strerror(errno)); #endif } -#else - ret = 0; -#endif /* * Put the module name in its canonical form. |