Print this page
4474 DTrace Userland CTF Support
4475 DTrace userland Keyword
4476 DTrace tests should be better citizens
4479 pid provider types
4480 dof emulation missing checks
Reviewed by: Bryan Cantrill <bryan@joyent.com>


   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */



  26 
  27 #include <assert.h>
  28 #include <strings.h>
  29 #include <stdlib.h>
  30 #include <stdio.h>
  31 #include <errno.h>
  32 #include <ctype.h>
  33 #include <alloca.h>
  34 #include <libgen.h>
  35 #include <stddef.h>

  36 
  37 #include <dt_impl.h>
  38 #include <dt_program.h>
  39 #include <dt_pid.h>
  40 #include <dt_string.h>

  41 
  42 typedef struct dt_pid_probe {
  43         dtrace_hdl_t *dpp_dtp;
  44         dt_pcb_t *dpp_pcb;
  45         dt_proc_t *dpp_dpr;
  46         struct ps_prochandle *dpp_pr;
  47         const char *dpp_mod;
  48         char *dpp_func;
  49         const char *dpp_name;
  50         const char *dpp_obj;
  51         uintptr_t dpp_pc;
  52         size_t dpp_size;
  53         Lmid_t dpp_lmid;
  54         uint_t dpp_nmatches;
  55         uint64_t dpp_stret[4];
  56         GElf_Sym dpp_last;
  57         uint_t dpp_last_taken;
  58 } dt_pid_probe_t;
  59 
  60 /*


 738                         /*
 739                          * If it's not strictly a pid provider, we might match
 740                          * a USDT provider.
 741                          */
 742                         if (strcmp(provname, pdp->dtpd_provider) != 0 &&
 743                             dt_pid_create_usdt_probes(&pd, dtp, NULL, dpr) != 0)
 744                                 ret = 1;
 745                 }
 746         }
 747 
 748         if (found) {
 749                 /*
 750                  * Give DTrace a shot to the ribs to get it to check
 751                  * out the newly created probes.
 752                  */
 753                 (void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL);
 754         }
 755 
 756         return (ret);
 757 }

































































































































































   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 
  22 /*
  23  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24  * Use is subject to license terms.
  25  */
  26 /*
  27  * Copyright (c) 2013, Joyent, Inc.  All rights reserved.
  28  */
  29 
  30 #include <assert.h>
  31 #include <strings.h>
  32 #include <stdlib.h>
  33 #include <stdio.h>
  34 #include <errno.h>
  35 #include <ctype.h>
  36 #include <alloca.h>
  37 #include <libgen.h>
  38 #include <stddef.h>
  39 #include <sys/sysmacros.h>
  40 
  41 #include <dt_impl.h>
  42 #include <dt_program.h>
  43 #include <dt_pid.h>
  44 #include <dt_string.h>
  45 #include <dt_module.h>
  46 
  47 typedef struct dt_pid_probe {
  48         dtrace_hdl_t *dpp_dtp;
  49         dt_pcb_t *dpp_pcb;
  50         dt_proc_t *dpp_dpr;
  51         struct ps_prochandle *dpp_pr;
  52         const char *dpp_mod;
  53         char *dpp_func;
  54         const char *dpp_name;
  55         const char *dpp_obj;
  56         uintptr_t dpp_pc;
  57         size_t dpp_size;
  58         Lmid_t dpp_lmid;
  59         uint_t dpp_nmatches;
  60         uint64_t dpp_stret[4];
  61         GElf_Sym dpp_last;
  62         uint_t dpp_last_taken;
  63 } dt_pid_probe_t;
  64 
  65 /*


 743                         /*
 744                          * If it's not strictly a pid provider, we might match
 745                          * a USDT provider.
 746                          */
 747                         if (strcmp(provname, pdp->dtpd_provider) != 0 &&
 748                             dt_pid_create_usdt_probes(&pd, dtp, NULL, dpr) != 0)
 749                                 ret = 1;
 750                 }
 751         }
 752 
 753         if (found) {
 754                 /*
 755                  * Give DTrace a shot to the ribs to get it to check
 756                  * out the newly created probes.
 757                  */
 758                 (void) dt_ioctl(dtp, DTRACEIOC_ENABLE, NULL);
 759         }
 760 
 761         return (ret);
 762 }
 763 
 764 /*
 765  * libdtrace has a backroom deal with us to ask us for type information on
 766  * behalf of pid provider probes when fasttrap doesn't return any type
 767  * information. Instead we'll look up the module and see if there is type
 768  * information available. However, if there is no type information available due
 769  * to a lack of CTF data, then we want to make sure that DTrace still carries on
 770  * in face of that. As such we don't have a meaningful exit code about failure.
 771  * We emit information about why we failed to the dtrace debug log so someone
 772  * can figure it out by asking nicely for DTRACE_DEBUG.
 773  */
 774 void
 775 dt_pid_get_types(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp,
 776     dtrace_argdesc_t *adp, int *nargs)
 777 {
 778         dt_module_t *dmp;
 779         ctf_file_t *fp;
 780         ctf_funcinfo_t f;
 781         ctf_id_t argv[32];
 782         GElf_Sym sym;
 783         prsyminfo_t si;
 784         struct ps_prochandle *p;
 785         int i, args;
 786         char buf[DTRACE_ARGTYPELEN];
 787         const char *mptr;
 788         char *eptr;
 789         int ret = 0;
 790         int argc = sizeof (argv) / sizeof (ctf_id_t);
 791         Lmid_t lmid;
 792 
 793         /* Set up a potential outcome */
 794         args = *nargs;
 795         *nargs = 0;
 796 
 797         /*
 798          * If we don't have an entry or return probe then we can just stop right
 799          * now as we don't have arguments for offset probes.
 800          */
 801         if (strcmp(pdp->dtpd_name, "entry") != 0 &&
 802             strcmp(pdp->dtpd_name, "return") != 0)
 803                 return;
 804 
 805         dmp = dt_module_create(dtp, pdp->dtpd_provider);
 806         if (dmp == NULL) {
 807                 dt_dprintf("failed to find module for %s\n",
 808                     pdp->dtpd_provider);
 809                 return;
 810         }
 811         if (dt_module_load(dtp, dmp) != 0) {
 812                 dt_dprintf("failed to load module for %s\n",
 813                     pdp->dtpd_provider);
 814                 return;
 815         }
 816 
 817         /*
 818          * We may be working with a module that doesn't have ctf. If that's the
 819          * case then we just return now and move on with life.
 820          */
 821         fp = dt_module_getctflib(dtp, dmp, pdp->dtpd_mod);
 822         if (fp == NULL) {
 823                 dt_dprintf("no ctf container for  %s\n",
 824                     pdp->dtpd_mod);
 825                 return;
 826         }
 827         p = dt_proc_grab(dtp, dmp->dm_pid, 0, PGRAB_RDONLY | PGRAB_FORCE);
 828         if (p == NULL) {
 829                 dt_dprintf("failed to grab pid\n");
 830                 return;
 831         }
 832         dt_proc_lock(dtp, p);
 833 
 834         /*
 835          * Check to see if the D module has a link map ID and separate that out
 836          * for properly interrogating libproc.
 837          */
 838         if ((mptr = strchr(pdp->dtpd_mod, '`')) != NULL) {
 839                 if (strlen(pdp->dtpd_mod) < 3) {
 840                         dt_dprintf("found weird modname with linkmap, "
 841                             "aborting: %s\n", pdp->dtpd_mod);
 842                         goto out;
 843                 }
 844                 if (pdp->dtpd_mod[0] != 'L' || pdp->dtpd_mod[1] != 'M') {
 845                         dt_dprintf("missing leading 'LM', "
 846                             "aborting: %s\n", pdp->dtpd_mod);
 847                         goto out;
 848                 }
 849                 errno = 0;
 850                 lmid = strtol(pdp->dtpd_mod + 2, &eptr, 16);
 851                 if (errno == ERANGE || eptr != mptr) {
 852                         dt_dprintf("failed to parse out lmid, aborting: %s\n",
 853                             pdp->dtpd_mod);
 854                         goto out;
 855                 }
 856                 mptr++;
 857         } else {
 858                 mptr = pdp->dtpd_mod;
 859                 lmid = 0;
 860         }
 861 
 862         if (Pxlookup_by_name(p, lmid, mptr, pdp->dtpd_func,
 863             &sym, &si) != 0) {
 864                 dt_dprintf("failed to find function %s in %s`%s\n",
 865                     pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);
 866                 goto out;
 867         }
 868         if (ctf_func_info(fp, si.prs_id, &f) == CTF_ERR) {
 869                 dt_dprintf("failed to get ctf information for %s in %s`%s\n",
 870                     pdp->dtpd_func, pdp->dtpd_provider, pdp->dtpd_mod);
 871                 goto out;
 872         }
 873 
 874         (void) snprintf(buf, sizeof (buf), "%s`%s", pdp->dtpd_provider,
 875             pdp->dtpd_mod);
 876 
 877         if (strcmp(pdp->dtpd_name, "return") == 0) {
 878                 if (args < 2)
 879                         goto out;
 880 
 881                 bzero(adp, sizeof (dtrace_argdesc_t));
 882                 adp->dtargd_ndx = 0;
 883                 adp->dtargd_id = pdp->dtpd_id;
 884                 adp->dtargd_mapping = adp->dtargd_ndx;
 885                 /*
 886                  * We explicitly leave out the library here, we only care that
 887                  * it is some int. We are assuming that there is no ctf
 888                  * container in here that is lying about what an int is.
 889                  */
 890                 (void) snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
 891                     "user %s`%s", pdp->dtpd_provider, "int");
 892                 adp++;
 893                 bzero(adp, sizeof (dtrace_argdesc_t));
 894                 adp->dtargd_ndx = 1;
 895                 adp->dtargd_id = pdp->dtpd_id;
 896                 adp->dtargd_mapping = adp->dtargd_ndx;
 897                 ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
 898                     "userland ");
 899                 (void) ctf_type_qname(fp, f.ctc_return, adp->dtargd_native +
 900                     ret, DTRACE_ARGTYPELEN - ret, buf);
 901                 *nargs = 2;
 902         } else {
 903                 if (ctf_func_args(fp, si.prs_id, argc, argv) == CTF_ERR)
 904                         goto out;
 905 
 906                 *nargs = MIN(args, f.ctc_argc);
 907                 for (i = 0; i < *nargs; i++, adp++) {
 908                         bzero(adp, sizeof (dtrace_argdesc_t));
 909                         adp->dtargd_ndx = i;
 910                         adp->dtargd_id = pdp->dtpd_id;
 911                         adp->dtargd_mapping = adp->dtargd_ndx;
 912                         ret = snprintf(adp->dtargd_native, DTRACE_ARGTYPELEN,
 913                             "userland ");
 914                         (void) ctf_type_qname(fp, argv[i], adp->dtargd_native +
 915                             ret, DTRACE_ARGTYPELEN - ret, buf);
 916                 }
 917         }
 918 out:
 919         dt_proc_unlock(dtp, p);
 920         dt_proc_release(dtp, p);
 921 }