diff options
author | Mark Johnston <markj@FreeBSD.org> | 2015-04-08 02:36:37 +0000 |
---|---|---|
committer | Mark Johnston <markj@FreeBSD.org> | 2015-04-08 02:36:37 +0000 |
commit | 67cf27b70f80c25edfc6f0c57be9b2dd413ea97c (patch) | |
tree | 48267c7be89f3f03d035711a7b82b3453bab848e /cddl | |
parent | 5f01ba81aefd6e2be3bd010d12a7c207a362bfb4 (diff) | |
download | src-67cf27b70f80c25edfc6f0c57be9b2dd413ea97c.tar.gz src-67cf27b70f80c25edfc6f0c57be9b2dd413ea97c.zip |
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
Notes
Notes:
svn path=/head/; revision=281257
Diffstat (limited to 'cddl')
-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 | ||||
-rw-r--r-- | cddl/lib/libdtrace/libproc_compat.h | 2 |
4 files changed, 80 insertions, 18 deletions
diff --git a/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c b/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c index a75dc02d5ad9..5fab935ee94e 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 ae41269afa16..eaf0961c90c8 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 e628e62e9cc4..c61a7106e239 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. diff --git a/cddl/lib/libdtrace/libproc_compat.h b/cddl/lib/libdtrace/libproc_compat.h index 0d99d967553a..8704b820df58 100644 --- a/cddl/lib/libdtrace/libproc_compat.h +++ b/cddl/lib/libdtrace/libproc_compat.h @@ -59,6 +59,6 @@ #define Pstate proc_state #define Psymbol_iter_by_addr proc_iter_symbyaddr #define Punsetflags proc_clearflags -#define Pupdate_maps(p) do { } while (0) +#define Pupdate_maps proc_rdagent #define Pupdate_syms proc_updatesyms #define Pxecbkpt proc_bkptexec |