Author: markj
Date: Wed Apr  8 02:36:37 2015
New Revision: 281257
URL: https://svnweb.freebsd.org/changeset/base/281257

Log:
  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

Modified:
  head/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c
  head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
  head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c
  head/cddl/lib/libdtrace/libproc_compat.h
  head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
  head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
  head/sys/cddl/dev/dtrace/dtrace_ioctl.c

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c   Wed Apr  8 
02:21:44 2015        (r281256)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/drti.c   Wed Apr  8 
02:36:37 2015        (r281257)
@@ -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
        }
 

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c        Wed Apr 
 8 02:21:44 2015        (r281256)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_link.c        Wed Apr 
 8 02:36:37 2015        (r281257)
@@ -1785,11 +1785,17 @@ dtrace_program_link(dtrace_hdl_t *dtp, d
                    "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
 
        /*

Modified: head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c
==============================================================================
--- head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c Wed Apr  8 
02:21:44 2015        (r281256)
+++ head/cddl/contrib/opensolaris/lib/libdtrace/common/dt_pid.c Wed Apr  8 
02:36:37 2015        (r281257)
@@ -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 pr
        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 pr
                        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 pr
 #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_probede
        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_probede
                    (int)proc_getpid(P), strerror(errno));
 #endif
        }
-#else
-       ret = 0;
-#endif
 
        /*
         * Put the module name in its canonical form.

Modified: head/cddl/lib/libdtrace/libproc_compat.h
==============================================================================
--- head/cddl/lib/libdtrace/libproc_compat.h    Wed Apr  8 02:21:44 2015        
(r281256)
+++ head/cddl/lib/libdtrace/libproc_compat.h    Wed Apr  8 02:36:37 2015        
(r281257)
@@ -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

Modified: head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c        Wed Apr 
 8 02:21:44 2015        (r281256)
+++ head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c        Wed Apr 
 8 02:36:37 2015        (r281257)
@@ -15374,13 +15374,15 @@ dtrace_helper_action_destroy(dtrace_help
 }
 
 static int
-dtrace_helper_destroygen(int gen)
+dtrace_helper_destroygen(dtrace_helpers_t *help, int gen)
 {
        proc_t *p = curproc;
-       dtrace_helpers_t *help = p->p_dtrace_helpers;
        dtrace_vstate_t *vstate;
        int i;
 
+       if (help == NULL)
+               help = p->p_dtrace_helpers;
+
        ASSERT(MUTEX_HELD(&dtrace_lock));
 
        if (help == NULL || gen > help->dthps_generation)
@@ -15478,9 +15480,9 @@ dtrace_helper_validate(dtrace_helper_act
 }
 
 static int
-dtrace_helper_action_add(int which, dtrace_ecbdesc_t *ep)
+dtrace_helper_action_add(int which, dtrace_ecbdesc_t *ep,
+    dtrace_helpers_t *help)
 {
-       dtrace_helpers_t *help;
        dtrace_helper_action_t *helper, *last;
        dtrace_actdesc_t *act;
        dtrace_vstate_t *vstate;
@@ -15490,7 +15492,6 @@ dtrace_helper_action_add(int which, dtra
        if (which < 0 || which >= DTRACE_NHELPER_ACTIONS)
                return (EINVAL);
 
-       help = curproc->p_dtrace_helpers;
        last = help->dthps_actions[which];
        vstate = &help->dthps_vstate;
 
@@ -15614,15 +15615,12 @@ dtrace_helper_provider_register(proc_t *
 }
 
 static int
-dtrace_helper_provider_add(dof_helper_t *dofhp, int gen)
+dtrace_helper_provider_add(dof_helper_t *dofhp, dtrace_helpers_t *help, int 
gen)
 {
-       dtrace_helpers_t *help;
        dtrace_helper_provider_t *hprov, **tmp_provs;
        uint_t tmp_maxprovs, i;
 
        ASSERT(MUTEX_HELD(&dtrace_lock));
-
-       help = curproc->p_dtrace_helpers;
        ASSERT(help != NULL);
 
        /*
@@ -15914,13 +15912,28 @@ dtrace_helper_slurp(dof_hdr_t *dof, dof_
        dtrace_helpers_t *help;
        dtrace_vstate_t *vstate;
        dtrace_enabling_t *enab = NULL;
+       proc_t *p = curproc;
        int i, gen, rv, nhelpers = 0, nprovs = 0, destroy = 1;
        uintptr_t daddr = (uintptr_t)dof;
 
        ASSERT(MUTEX_HELD(&dtrace_lock));
 
-       if ((help = curproc->p_dtrace_helpers) == NULL)
-               help = dtrace_helpers_create(curproc);
+#ifdef __FreeBSD__
+       if (dhp->dofhp_pid != p->p_pid) {
+               if ((p = pfind(dhp->dofhp_pid)) == NULL)
+                       return (-1);
+               if (!P_SHOULDSTOP(p) ||
+                   (p->p_flag & P_TRACED) == 0 ||
+                   p->p_pptr->p_pid != curproc->p_pid) {
+                       PROC_UNLOCK(p);
+                       return (-1);
+               }
+               PROC_UNLOCK(p);
+       }
+#endif
+
+       if ((help = p->p_dtrace_helpers) == NULL)
+               help = dtrace_helpers_create(p);
 
        vstate = &help->dthps_vstate;
 
@@ -15968,12 +15981,13 @@ dtrace_helper_slurp(dof_hdr_t *dof, dof_
                        continue;
 
                if ((rv = dtrace_helper_action_add(DTRACE_HELPER_ACTION_USTACK,
-                   ep)) != 0) {
+                   ep, help)) != 0) {
                        /*
                         * Adding this helper action failed -- we are now going
                         * to rip out the entire generation and return failure.
                         */
-                       (void) dtrace_helper_destroygen(help->dthps_generation);
+                       (void) dtrace_helper_destroygen(help,
+                           help->dthps_generation);
                        dtrace_enabling_destroy(enab);
                        dtrace_dof_destroy(dof);
                        return (-1);
@@ -15990,9 +16004,9 @@ dtrace_helper_slurp(dof_hdr_t *dof, dof_
 
        if (dhp != NULL && nprovs > 0) {
                dhp->dofhp_dof = (uint64_t)(uintptr_t)dof;
-               if (dtrace_helper_provider_add(dhp, gen) == 0) {
+               if (dtrace_helper_provider_add(dhp, help, gen) == 0) {
                        mutex_exit(&dtrace_lock);
-                       dtrace_helper_provider_register(curproc, help, dhp);
+                       dtrace_helper_provider_register(p, help, dhp);
                        mutex_enter(&dtrace_lock);
 
                        destroy = 0;
@@ -16956,7 +16970,7 @@ dtrace_ioctl_helper(int cmd, intptr_t ar
 
        case DTRACEHIOC_REMOVE: {
                mutex_enter(&dtrace_lock);
-               rval = dtrace_helper_destroygen(arg);
+               rval = dtrace_helper_destroygen(NULL, arg);
                mutex_exit(&dtrace_lock);
 
                return (rval);

Modified: head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h   Wed Apr  8 
02:21:44 2015        (r281256)
+++ head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h   Wed Apr  8 
02:36:37 2015        (r281257)
@@ -1423,8 +1423,9 @@ typedef struct dof_helper {
        char dofhp_mod[DTRACE_MODNAMELEN];      /* executable or library name */
        uint64_t dofhp_addr;                    /* base address of object */
        uint64_t dofhp_dof;                     /* address of helper DOF */
-#ifndef illumos
-       int gen;
+#ifdef __FreeBSD__
+       pid_t dofhp_pid;                        /* target process ID */
+       int dofhp_gen;
 #endif
 } dof_helper_t;
 

Modified: head/sys/cddl/dev/dtrace/dtrace_ioctl.c
==============================================================================
--- head/sys/cddl/dev/dtrace/dtrace_ioctl.c     Wed Apr  8 02:21:44 2015        
(r281256)
+++ head/sys/cddl/dev/dtrace/dtrace_ioctl.c     Wed Apr  8 02:36:37 2015        
(r281257)
@@ -32,9 +32,9 @@ static int
 dtrace_ioctl_helper(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
     struct thread *td)
 {
-       int rval;
        dof_helper_t *dhp = NULL;
        dof_hdr_t *dof = NULL;
+       int rval;
 
        switch (cmd) {
        case DTRACEHIOC_ADDDOF:
@@ -51,7 +51,7 @@ dtrace_ioctl_helper(struct cdev *dev, u_
                mutex_enter(&dtrace_lock);
                if ((rval = dtrace_helper_slurp((dof_hdr_t *)dof, dhp)) != -1) {
                        if (dhp) {
-                               dhp->gen = rval;
+                               dhp->dofhp_gen = rval;
                                copyout(dhp, addr, sizeof(*dhp));
                        }
                        rval = 0;
@@ -59,10 +59,11 @@ dtrace_ioctl_helper(struct cdev *dev, u_
                        rval = EINVAL;
                }
                mutex_exit(&dtrace_lock);
+
                return (rval);
        case DTRACEHIOC_REMOVE:
                mutex_enter(&dtrace_lock);
-               rval = dtrace_helper_destroygen((int)*addr);
+               rval = dtrace_helper_destroygen(NULL, (int)*addr);
                mutex_exit(&dtrace_lock);
 
                return (rval);
_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to