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>


   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2011, Joyent Inc. All rights reserved.
  25  * Copyright (c) 2012 by Delphix. All rights reserved.
  26  */
  27 
  28 /*
  29  * DTrace D Language Compiler
  30  *
  31  * The code in this source file implements the main engine for the D language
  32  * compiler.  The driver routine for the compiler is dt_compile(), below.  The
  33  * compiler operates on either stdio FILEs or in-memory strings as its input
  34  * and can produce either dtrace_prog_t structures from a D program or a single
  35  * dtrace_difo_t structure from a D expression.  Multiple entry points are
  36  * provided as wrappers around dt_compile() for the various input/output pairs.
  37  * The compiler itself is implemented across the following source files:
  38  *
  39  * dt_lex.l - lex scanner
  40  * dt_grammar.y - yacc grammar
  41  * dt_parser.c - parse tree creation and semantic checking
  42  * dt_decl.c - declaration stack processing
  43  * dt_xlator.c - D translator lookup and creation
  44  * dt_ident.c - identifier and symbol table routines


 645                 dp->dtdo_len = 1;
 646                 dp->dtdo_rtype = dt_int_rtype;
 647 
 648                 ap = dt_stmt_action(dtp, sdp);
 649                 ap->dtad_difo = dp;
 650                 ap->dtad_kind = kind;
 651                 return;
 652         }
 653 
 654         for (anp = arg1; anp != NULL; anp = anp->dn_list) {
 655                 ap = dt_stmt_action(dtp, sdp);
 656                 dt_cg(yypcb, anp);
 657                 ap->dtad_difo = dt_as(yypcb);
 658                 ap->dtad_kind = kind;
 659         }
 660 }
 661 
 662 static void
 663 dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
 664 {


 665         dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
 666         boolean_t istrace = (dnp->dn_ident->di_id == DT_ACT_TRACE);
 667         const char *act = istrace ?  "trace" : "print";
 668 
 669         if (dt_node_is_void(dnp->dn_args)) {
 670                 dnerror(dnp->dn_args, istrace ? D_TRACE_VOID : D_PRINT_VOID,
 671                     "%s( ) may not be applied to a void expression\n", act);
 672         }
 673 
 674         if (dt_node_resolve(dnp->dn_args, DT_IDENT_XLPTR) != NULL) {
 675                 dnerror(dnp->dn_args, istrace ? D_TRACE_DYN : D_PRINT_DYN,
 676                     "%s( ) may not be applied to a translated pointer\n", act);
 677         }
 678 
 679         if (dnp->dn_args->dn_kind == DT_NODE_AGG) {
 680                 dnerror(dnp->dn_args, istrace ? D_TRACE_AGG : D_PRINT_AGG,
 681                     "%s( ) may not be applied to an aggregation%s\n", act,
 682                     istrace ? "" : " -- did you mean printa()?");
 683         }
 684 
 685         dt_cg(yypcb, dnp->dn_args);
 686 
 687         /*
 688          * The print() action behaves identically to trace(), except that it
 689          * stores the CTF type of the argument (if present) within the DOF for
 690          * the DIFEXPR action.  To do this, we set the 'dtsd_strdata' to point
 691          * to the fully-qualified CTF type ID for the result of the DIF
 692          * action.  We use the ID instead of the name to handles complex types
 693          * like arrays and function pointers that can't be resolved by
 694          * ctf_type_lookup().  This is later processed by dtrace_dof_create()
 695          * and turned into a reference into the string table so that we can
 696          * get the type information when we process the data after the fact.



 697          */
 698         if (dnp->dn_ident->di_id == DT_ACT_PRINT) {
 699                 dt_node_t *dret;
 700                 size_t n;
 701                 dt_module_t *dmp;
 702 
 703                 dret = yypcb->pcb_dret;
 704                 dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
 705 
 706                 n = snprintf(NULL, 0, "%s`%d", dmp->dm_name, dret->dn_type) + 1;








 707                 sdp->dtsd_strdata = dt_alloc(dtp, n);
 708                 if (sdp->dtsd_strdata == NULL)
 709                         longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
 710                 (void) snprintf(sdp->dtsd_strdata, n, "%s`%d", dmp->dm_name,
 711                     dret->dn_type);





 712         }
 713 
 714         ap->dtad_difo = dt_as(yypcb);
 715         ap->dtad_kind = DTRACEACT_DIFEXPR;
 716 }
 717 
 718 static void
 719 dt_action_tracemem(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
 720 {
 721         dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
 722 
 723         dt_node_t *addr = dnp->dn_args;
 724         dt_node_t *max = dnp->dn_args->dn_list;
 725         dt_node_t *size;
 726 
 727         char n[DT_TYPE_NAMELEN];
 728 
 729         if (dt_node_is_integer(addr) == 0 && dt_node_is_pointer(addr) == 0) {
 730                 dnerror(addr, D_TRACEMEM_ADDR,
 731                     "tracemem( ) argument #1 is incompatible with "




   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   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 (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
  24  * Copyright (c) 2013, Joyent Inc. All rights reserved.
  25  * Copyright (c) 2012 by Delphix. All rights reserved.
  26  */
  27 
  28 /*
  29  * DTrace D Language Compiler
  30  *
  31  * The code in this source file implements the main engine for the D language
  32  * compiler.  The driver routine for the compiler is dt_compile(), below.  The
  33  * compiler operates on either stdio FILEs or in-memory strings as its input
  34  * and can produce either dtrace_prog_t structures from a D program or a single
  35  * dtrace_difo_t structure from a D expression.  Multiple entry points are
  36  * provided as wrappers around dt_compile() for the various input/output pairs.
  37  * The compiler itself is implemented across the following source files:
  38  *
  39  * dt_lex.l - lex scanner
  40  * dt_grammar.y - yacc grammar
  41  * dt_parser.c - parse tree creation and semantic checking
  42  * dt_decl.c - declaration stack processing
  43  * dt_xlator.c - D translator lookup and creation
  44  * dt_ident.c - identifier and symbol table routines


 645                 dp->dtdo_len = 1;
 646                 dp->dtdo_rtype = dt_int_rtype;
 647 
 648                 ap = dt_stmt_action(dtp, sdp);
 649                 ap->dtad_difo = dp;
 650                 ap->dtad_kind = kind;
 651                 return;
 652         }
 653 
 654         for (anp = arg1; anp != NULL; anp = anp->dn_list) {
 655                 ap = dt_stmt_action(dtp, sdp);
 656                 dt_cg(yypcb, anp);
 657                 ap->dtad_difo = dt_as(yypcb);
 658                 ap->dtad_kind = kind;
 659         }
 660 }
 661 
 662 static void
 663 dt_action_trace(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
 664 {
 665         int ctflib;
 666 
 667         dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
 668         boolean_t istrace = (dnp->dn_ident->di_id == DT_ACT_TRACE);
 669         const char *act = istrace ?  "trace" : "print";
 670 
 671         if (dt_node_is_void(dnp->dn_args)) {
 672                 dnerror(dnp->dn_args, istrace ? D_TRACE_VOID : D_PRINT_VOID,
 673                     "%s( ) may not be applied to a void expression\n", act);
 674         }
 675 
 676         if (dt_node_resolve(dnp->dn_args, DT_IDENT_XLPTR) != NULL) {
 677                 dnerror(dnp->dn_args, istrace ? D_TRACE_DYN : D_PRINT_DYN,
 678                     "%s( ) may not be applied to a translated pointer\n", act);
 679         }
 680 
 681         if (dnp->dn_args->dn_kind == DT_NODE_AGG) {
 682                 dnerror(dnp->dn_args, istrace ? D_TRACE_AGG : D_PRINT_AGG,
 683                     "%s( ) may not be applied to an aggregation%s\n", act,
 684                     istrace ? "" : " -- did you mean printa()?");
 685         }
 686 
 687         dt_cg(yypcb, dnp->dn_args);
 688 
 689         /*
 690          * The print() action behaves identically to trace(), except that it
 691          * stores the CTF type of the argument (if present) within the DOF for
 692          * the DIFEXPR action.  To do this, we set the 'dtsd_strdata' to point
 693          * to the fully-qualified CTF type ID for the result of the DIF
 694          * action.  We use the ID instead of the name to handles complex types
 695          * like arrays and function pointers that can't be resolved by
 696          * ctf_type_lookup().  This is later processed by dtrace_dof_create()
 697          * and turned into a reference into the string table so that we can
 698          * get the type information when we process the data after the fact.  In
 699          * the case where we are referring to userland CTF data, we also need to
 700          * to identify which ctf container in question we care about and encode
 701          * that within the name.
 702          */
 703         if (dnp->dn_ident->di_id == DT_ACT_PRINT) {
 704                 dt_node_t *dret;
 705                 size_t n;
 706                 dt_module_t *dmp;
 707 
 708                 dret = yypcb->pcb_dret;
 709                 dmp = dt_module_lookup_by_ctf(dtp, dret->dn_ctfp);
 710 
 711                 if (dmp->dm_pid != 0) {
 712                         ctflib = dt_module_getlibid(dtp, dmp, dret->dn_ctfp);
 713                         assert(ctflib >= 0);
 714                         n = snprintf(NULL, 0, "%s`%d`%d", dmp->dm_name,
 715                             ctflib, dret->dn_type) + 1;
 716                 } else {
 717                         n = snprintf(NULL, 0, "%s`%d", dmp->dm_name,
 718                             dret->dn_type) + 1;
 719                 }
 720                 sdp->dtsd_strdata = dt_alloc(dtp, n);
 721                 if (sdp->dtsd_strdata == NULL)
 722                         longjmp(yypcb->pcb_jmpbuf, EDT_NOMEM);
 723                 if (dmp->dm_pid != 0) {
 724                         (void) snprintf(sdp->dtsd_strdata, n, "%s`%d`%d",
 725                             dmp->dm_name, ctflib, dret->dn_type);
 726                 } else {
 727                         (void) snprintf(sdp->dtsd_strdata, n, "%s`%d",
 728                             dmp->dm_name, dret->dn_type);
 729                 }
 730         }
 731 
 732         ap->dtad_difo = dt_as(yypcb);
 733         ap->dtad_kind = DTRACEACT_DIFEXPR;
 734 }
 735 
 736 static void
 737 dt_action_tracemem(dtrace_hdl_t *dtp, dt_node_t *dnp, dtrace_stmtdesc_t *sdp)
 738 {
 739         dtrace_actdesc_t *ap = dt_stmt_action(dtp, sdp);
 740 
 741         dt_node_t *addr = dnp->dn_args;
 742         dt_node_t *max = dnp->dn_args->dn_list;
 743         dt_node_t *size;
 744 
 745         char n[DT_TYPE_NAMELEN];
 746 
 747         if (dt_node_is_integer(addr) == 0 && dt_node_is_pointer(addr) == 0) {
 748                 dnerror(addr, D_TRACEMEM_ADDR,
 749                     "tracemem( ) argument #1 is incompatible with "