LCOV - code coverage report
Current view: top level - mnt/wasteland/wcohen/systemtap_write/systemtap - tapset-mark.cxx (source / functions) Hit Total Coverage
Test: stap.info Lines: 34 338 10.1 %
Date: 2013-03-08 Functions: 6 30 20.0 %
Branches: 35 803 4.4 %

           Branch data     Line data    Source code
       1                 :            : // tapset for kernel static markers
       2                 :            : // Copyright (C) 2005-2010 Red Hat Inc.
       3                 :            : // Copyright (C) 2005-2007 Intel Corporation.
       4                 :            : //
       5                 :            : // This file is part of systemtap, and is free software.  You can
       6                 :            : // redistribute it and/or modify it under the terms of the GNU General
       7                 :            : // Public License (GPL); either version 2, or (at your option) any
       8                 :            : // later version.
       9                 :            : 
      10                 :            : #include "session.h"
      11                 :            : #include "tapsets.h"
      12                 :            : #include "translate.h"
      13                 :            : #include "util.h"
      14                 :            : 
      15                 :            : #include <cerrno>
      16                 :            : #include <cstdlib>
      17                 :            : #include <cstring>
      18                 :            : #include <string>
      19                 :            : 
      20                 :            : extern "C" {
      21                 :            : #include <fnmatch.h>
      22                 :            : }
      23                 :            : 
      24                 :            : 
      25                 :            : using namespace std;
      26                 :            : using namespace __gnu_cxx;
      27                 :            : 
      28                 :            : 
      29         [ +  - ]:       2414 : static const string TOK_KERNEL("kernel");
      30         [ +  - ]:       2414 : static const string TOK_MARK("mark");
      31         [ +  - ]:       2414 : static const string TOK_FORMAT("format");
      32                 :            : 
      33                 :            : 
      34                 :            : // ------------------------------------------------------------------------
      35                 :            : // statically inserted macro-based derived probes
      36                 :            : // ------------------------------------------------------------------------
      37                 :            : 
      38                 :          0 : struct mark_arg
      39                 :            : {
      40                 :            :   bool str;
      41                 :            :   bool isptr;
      42                 :            :   string c_type;
      43                 :            :   exp_type stp_type;
      44                 :            : };
      45                 :            : 
      46 [ #  # ][ #  # ]:          0 : struct mark_derived_probe: public derived_probe
         [ #  # ][ #  # ]
      47                 :            : {
      48                 :            :   mark_derived_probe (systemtap_session &s,
      49                 :            :                       const string& probe_name, const string& probe_format,
      50                 :            :                       probe* base_probe, probe_point* location);
      51                 :            : 
      52                 :            :   systemtap_session& sess;
      53                 :            :   string probe_name, probe_format;
      54                 :            :   vector <struct mark_arg *> mark_args;
      55                 :            :   bool target_symbol_seen;
      56                 :            : 
      57                 :            :   void join_group (systemtap_session& s);
      58                 :            :   void print_dupe_stamp (ostream& o);
      59                 :            :   void initialize_probe_context_vars (translator_output* o);
      60                 :            :   void getargs (std::list<std::string> &arg_set) const;
      61                 :            : 
      62                 :            :   void parse_probe_format ();
      63                 :            : };
      64                 :            : 
      65                 :            : 
      66         [ #  # ]:          0 : struct mark_derived_probe_group: public generic_dpg<mark_derived_probe>
      67                 :            : {
      68                 :            : public:
      69                 :            :   void emit_module_decls (systemtap_session& s);
      70                 :            :   void emit_module_init (systemtap_session& s);
      71                 :            :   void emit_module_exit (systemtap_session& s);
      72                 :            : };
      73                 :            : 
      74                 :            : 
      75 [ #  # ][ #  # ]:          0 : struct mark_var_expanding_visitor: public var_expanding_visitor
      76                 :            : {
      77                 :          0 :   mark_var_expanding_visitor(systemtap_session& s, const string& pn,
      78                 :            :                              vector <struct mark_arg *> &mark_args):
      79                 :            :     sess (s), probe_name (pn), mark_args (mark_args),
      80         [ #  # ]:          0 :     target_symbol_seen (false) {}
      81                 :            :   systemtap_session& sess;
      82                 :            :   string probe_name;
      83                 :            :   vector <struct mark_arg *> &mark_args;
      84                 :            :   bool target_symbol_seen;
      85                 :            : 
      86                 :            :   void visit_target_symbol (target_symbol* e);
      87                 :            :   void visit_target_symbol_arg (target_symbol* e);
      88                 :            :   void visit_target_symbol_context (target_symbol* e);
      89                 :            : };
      90                 :            : 
      91                 :            : 
      92                 :            : void
      93                 :          0 : mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
      94                 :            : {
      95 [ #  # ][ #  # ]:          0 :   string argnum_s = e->name.substr(4,e->name.length()-4);
      96         [ #  # ]:          0 :   int argnum = atoi (argnum_s.c_str());
      97                 :            : 
      98 [ #  # ][ #  # ]:          0 :   if (argnum < 1 || argnum > (int)mark_args.size())
                 [ #  # ]
      99 [ #  # ][ #  # ]:          0 :     throw semantic_error (_("invalid marker argument number"), e->tok);
     100                 :            : 
     101 [ #  # ][ #  # ]:          0 :   if (is_active_lvalue (e))
     102 [ #  # ][ #  # ]:          0 :     throw semantic_error(_("write to marker parameter not permitted"), e->tok);
     103                 :            : 
     104 [ #  # ][ #  # ]:          0 :   e->assert_no_components("marker");
                 [ #  # ]
     105                 :            : 
     106                 :            :   // Remember that we've seen a target variable.
     107                 :          0 :   target_symbol_seen = true;
     108                 :            : 
     109 [ #  # ][ #  # ]:          0 :   symbol* sym = new symbol;
     110                 :          0 :   sym->tok = e->tok;
     111 [ #  # ][ #  # ]:          0 :   sym->name = "__mark_arg" + lex_cast(argnum);
         [ #  # ][ #  # ]
                 [ #  # ]
     112 [ #  # ][ #  # ]:          0 :   provide (sym);
     113                 :          0 : }
     114                 :            : 
     115                 :            : 
     116                 :            : void
     117                 :          0 : mark_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
     118                 :            : {
     119         [ #  # ]:          0 :   string sname = e->name;
     120                 :            : 
     121 [ #  # ][ #  # ]:          0 :   if (is_active_lvalue (e))
     122 [ #  # ][ #  # ]:          0 :     throw semantic_error(_F("write to marker '%s' not permitted", sname.c_str()), e->tok);
                 [ #  # ]
     123                 :            : 
     124 [ #  # ][ #  # ]:          0 :   e->assert_no_components("marker");
                 [ #  # ]
     125                 :            : 
     126 [ #  # ][ #  # ]:          0 :   if (e->name == "$format" || e->name == "$name") {
         [ #  # ][ #  # ]
                 [ #  # ]
     127                 :            :     // Synthesize an embedded expression.
     128 [ #  # ][ #  # ]:          0 :     embedded_expr *expr = new embedded_expr;
     129                 :          0 :     expr->tok = e->tok;
     130                 :            : 
     131 [ #  # ][ #  # ]:          0 :     if (e->name == "$format")
     132                 :            :       expr->code = string("/* string */ /* pure */ ")
     133 [ #  # ][ #  # ]:          0 :         + string("c->ips.kmark.marker_format ? c->ips.kmark.marker_format : \"\"");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     134                 :            :     else
     135                 :            :       expr->code = string("/* string */ /* pure */ ")
     136 [ #  # ][ #  # ]:          0 :         + string("c->ips.kmark.marker_name ? c->ips.kmark.marker_name : \"\"");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     137                 :            : 
     138         [ #  # ]:          0 :     provide (expr);
     139                 :            :   }
     140 [ #  # ][ #  # ]:          0 :  else if (e->name == "$$vars" || e->name == "$$parms")
         [ #  # ][ #  # ]
                 [ #  # ]
     141                 :            :   {
     142                 :            :      //copy from tracepoint
     143 [ #  # ][ #  # ]:          0 :      token* pf_tok = new token(*e->tok);
     144         [ #  # ]:          0 :      pf_tok->content = "sprintf";
     145         [ #  # ]:          0 :      print_format* pf = print_format::create(pf_tok);
     146                 :            : 
     147         [ #  # ]:          0 :      for (unsigned i = 0; i < mark_args.size(); ++i)
     148                 :            :         {
     149         [ #  # ]:          0 :           if (i > 0)
     150         [ #  # ]:          0 :             pf->raw_components += " ";
     151 [ #  # ][ #  # ]:          0 :           pf->raw_components += "$arg" + lex_cast(i+1);
         [ #  # ][ #  # ]
                 [ #  # ]
     152 [ #  # ][ #  # ]:          0 :           target_symbol *tsym = new target_symbol;
     153                 :          0 :           tsym->tok = e->tok;
     154 [ #  # ][ #  # ]:          0 :           tsym->name = "$arg" + lex_cast(i+1);
         [ #  # ][ #  # ]
                 [ #  # ]
     155                 :            : 
     156                 :          0 :           tsym->saved_conversion_error = 0;
     157         [ #  # ]:          0 :           expression *texp = require (tsym); //same treatment as tracepoint
     158         [ #  # ]:          0 :           assert (!tsym->saved_conversion_error);
     159      [ #  #  # ]:          0 :           switch (mark_args[i]->stp_type)
     160                 :            :            {
     161                 :            :              case pe_long:
     162 [ #  # ][ #  # ]:          0 :                pf->raw_components += mark_args[i]->isptr ? "=%p" : "=%#x";
     163                 :          0 :                break;
     164                 :            :              case pe_string:
     165         [ #  # ]:          0 :                pf->raw_components += "=%s";
     166                 :          0 :                break;
     167                 :            :              default:
     168         [ #  # ]:          0 :                pf->raw_components += "=%#x";
     169                 :          0 :                break;
     170                 :            :             }
     171         [ #  # ]:          0 :           pf->args.push_back(texp);
     172                 :            :         }
     173 [ #  # ][ #  # ]:          0 :      pf->components = print_format::string_to_components(pf->raw_components);
                 [ #  # ]
     174         [ #  # ]:          0 :      provide (pf);
     175         [ #  # ]:          0 :   }
     176                 :          0 : }
     177                 :            : 
     178                 :            : void
     179                 :          0 : mark_var_expanding_visitor::visit_target_symbol (target_symbol* e)
     180                 :            : {
     181 [ #  # ][ #  # ]:          0 :   assert(e->name.size() > 0 && e->name[0] == '$');
     182                 :            : 
     183                 :            :   try
     184                 :            :     {
     185         [ #  # ]:          0 :       if (e->addressof)
     186 [ #  # ][ #  # ]:          0 :         throw semantic_error(_("cannot take address of marker variable"), e->tok);
     187                 :            : 
     188 [ #  # ][ #  # ]:          0 :       if (startswith(e->name, "$arg"))
     189         [ #  # ]:          0 :         visit_target_symbol_arg (e);
     190 [ #  # ][ #  # ]:          0 :       else if (e->name == "$format" || e->name == "$name"
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     191 [ #  # ][ #  # ]:          0 :                || e->name == "$$parms" || e->name == "$$vars")
     192         [ #  # ]:          0 :         visit_target_symbol_context (e);
     193                 :            :       else
     194                 :          0 :         throw semantic_error (_("invalid target symbol for marker, $argN, $name, $format, $$parms or $$vars expected"),
     195 [ #  # ][ #  # ]:          0 :                               e->tok);
     196                 :            :     }
     197         [ #  # ]:            :   catch (const semantic_error &er)
     198                 :            :     {
     199         [ #  # ]:            :       e->chain (er);
     200         [ #  # ]:            :       provide (e);
     201                 :            :     }
     202                 :          0 : }
     203                 :            : 
     204                 :            : 
     205                 :          0 : mark_derived_probe::mark_derived_probe (systemtap_session &s,
     206                 :            :                                         const string& p_n,
     207                 :            :                                         const string& p_f,
     208                 :            :                                         probe* base, probe_point* loc):
     209                 :            :   derived_probe (base, loc, true /* .components soon rewritten */),
     210                 :            :   sess (s), probe_name (p_n), probe_format (p_f),
     211 [ #  # ][ #  # ]:          0 :   target_symbol_seen (false)
                 [ #  # ]
     212                 :            : {
     213                 :            :   // create synthetic probe point name; preserve condition
     214         [ #  # ]:          0 :   vector<probe_point::component*> comps;
     215 [ #  # ][ #  # ]:          0 :   comps.push_back (new probe_point::component (TOK_KERNEL));
                 [ #  # ]
     216 [ #  # ][ #  # ]:          0 :   comps.push_back (new probe_point::component (TOK_MARK, new literal_string (probe_name)));
         [ #  # ][ #  # ]
                 [ #  # ]
     217 [ #  # ][ #  # ]:          0 :   comps.push_back (new probe_point::component (TOK_FORMAT, new literal_string (probe_format)));
         [ #  # ][ #  # ]
                 [ #  # ]
     218 [ #  # ][ #  # ]:          0 :   this->sole_location()->components = comps;
     219                 :            : 
     220                 :            :   // expand the marker format
     221         [ #  # ]:          0 :   parse_probe_format();
     222                 :            : 
     223                 :            :   // Now expand the local variables in the probe body
     224         [ #  # ]:          0 :   mark_var_expanding_visitor v (sess, name, mark_args);
     225         [ #  # ]:          0 :   v.replace (this->body);
     226                 :          0 :   target_symbol_seen = v.target_symbol_seen;
     227         [ #  # ]:          0 :   if (target_symbol_seen)
     228         [ #  # ]:          0 :     for (unsigned i = 0; i < mark_args.size(); ++i)
     229                 :            :       {
     230 [ #  # ][ #  # ]:          0 :         vardecl* v = new vardecl;
     231 [ #  # ][ #  # ]:          0 :         v->name = "__mark_arg" + lex_cast(i+1);
         [ #  # ][ #  # ]
                 [ #  # ]
     232                 :          0 :         v->tok = this->tok;
     233         [ #  # ]:          0 :         v->set_arity(0, this->tok);
     234                 :          0 :         v->type = mark_args[i]->stp_type;
     235                 :          0 :         v->synthetic = true;
     236         [ #  # ]:          0 :         this->locals.push_back (v);
     237                 :            :       }
     238                 :            : 
     239         [ #  # ]:          0 :   if (sess.verbose > 2)
     240 [ #  # ][ #  # ]:          0 :     clog << "marker-based " << name << " mark=" << probe_name << " fmt='" << probe_format
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     241 [ #  # ][ #  # ]:          0 :          << "'" << endl;
         [ #  # ][ #  # ]
     242                 :          0 : }
     243                 :            : 
     244                 :            : 
     245                 :            : static int
     246                 :          0 : skip_atoi(const char **s)
     247                 :            : {
     248                 :          0 :   int i = 0;
     249         [ #  # ]:          0 :   while (isdigit(**s))
     250                 :          0 :     i = i * 10 + *((*s)++) - '0';
     251                 :          0 :   return i;
     252                 :            : }
     253                 :            : 
     254                 :            : 
     255                 :            : void
     256                 :          0 : mark_derived_probe::parse_probe_format()
     257                 :            : {
     258         [ #  # ]:          0 :   const char *fmt = probe_format.c_str();
     259                 :            :   int qualifier;                // 'h', 'l', or 'L' for integer fields
     260                 :            :   mark_arg *arg;
     261                 :            : 
     262         [ #  # ]:          0 :   for (; *fmt ; ++fmt)
     263                 :            :     {
     264         [ #  # ]:          0 :       if (*fmt != '%')
     265                 :            :         {
     266                 :            :           /* Skip text */
     267                 :          0 :           continue;
     268                 :            :         }
     269                 :            : 
     270                 :            : repeat:
     271                 :          0 :       ++fmt;
     272                 :            : 
     273                 :            :       // skip conversion flags (if present)
     274         [ #  # ]:          0 :       switch (*fmt)
     275                 :            :         {
     276                 :            :         case '-':
     277                 :            :         case '+':
     278                 :            :         case ' ':
     279                 :            :         case '#':
     280                 :            :         case '0':
     281                 :          0 :           goto repeat;
     282                 :            :         }
     283                 :            : 
     284                 :            :       // skip minimum field witdh (if present)
     285         [ #  # ]:          0 :       if (isdigit(*fmt))
     286                 :          0 :         skip_atoi(&fmt);
     287                 :            : 
     288                 :            :       // skip precision (if present)
     289         [ #  # ]:          0 :       if (*fmt == '.')
     290                 :            :         {
     291                 :          0 :           ++fmt;
     292         [ #  # ]:          0 :           if (isdigit(*fmt))
     293                 :          0 :             skip_atoi(&fmt);
     294                 :            :         }
     295                 :            : 
     296                 :            :       // get the conversion qualifier (if present)
     297                 :          0 :       qualifier = -1;
     298 [ #  # ][ #  # ]:          0 :       if (*fmt == 'h' || *fmt == 'l' || *fmt == 'L')
                 [ #  # ]
     299                 :            :         {
     300                 :          0 :           qualifier = *fmt;
     301                 :          0 :           ++fmt;
     302 [ #  # ][ #  # ]:          0 :           if (qualifier == 'l' && *fmt == 'l')
     303                 :            :             {
     304                 :          0 :               qualifier = 'L';
     305                 :          0 :               ++fmt;
     306                 :            :             }
     307                 :            :         }
     308                 :            : 
     309                 :            :       // get the conversion type
     310   [ #  #  #  #  :          0 :       switch (*fmt)
                   #  # ]
     311                 :            :         {
     312                 :            :         case 'c':
     313 [ #  # ][ #  # ]:          0 :           arg = new mark_arg;
     314                 :          0 :           arg->str = false;
     315                 :          0 :           arg->isptr = false;
     316         [ #  # ]:          0 :           arg->c_type = "int";
     317                 :          0 :           arg->stp_type = pe_long;
     318         [ #  # ]:          0 :           mark_args.push_back(arg);
     319                 :          0 :           continue;
     320                 :            : 
     321                 :            :         case 's':
     322 [ #  # ][ #  # ]:          0 :           arg = new mark_arg;
     323                 :          0 :           arg->str = true;
     324                 :          0 :           arg->isptr = false;
     325         [ #  # ]:          0 :           arg->c_type = "char *";
     326                 :          0 :           arg->stp_type = pe_string;
     327         [ #  # ]:          0 :           mark_args.push_back(arg);
     328                 :          0 :           continue;
     329                 :            : 
     330                 :            :         case 'p':
     331 [ #  # ][ #  # ]:          0 :           arg = new mark_arg;
     332                 :          0 :           arg->str = false;
     333                 :          0 :           arg->isptr = true;
     334                 :            :           // This should really be 'void *'.  But, then we'll get a
     335                 :            :           // compile error when we assign the void pointer to an
     336                 :            :           // integer without a cast.  So, we use 'long' instead, since
     337                 :            :           // it should have the same size as 'void *'.
     338         [ #  # ]:          0 :           arg->c_type = "long";
     339                 :          0 :           arg->stp_type = pe_long;
     340         [ #  # ]:          0 :           mark_args.push_back(arg);
     341                 :          0 :           continue;
     342                 :            : 
     343                 :            :         case '%':
     344                 :          0 :           continue;
     345                 :            : 
     346                 :            :         case 'o':
     347                 :            :         case 'X':
     348                 :            :         case 'x':
     349                 :            :         case 'd':
     350                 :            :         case 'i':
     351                 :            :         case 'u':
     352                 :            :           // fall through...
     353                 :          0 :           break;
     354                 :            : 
     355                 :            :         default:
     356         [ #  # ]:          0 :           if (!*fmt)
     357                 :          0 :             --fmt;
     358                 :          0 :           continue;
     359                 :            :         }
     360                 :            : 
     361 [ #  # ][ #  # ]:          0 :       arg = new mark_arg;
     362                 :          0 :       arg->str = false;
     363                 :          0 :       arg->isptr = false;
     364                 :          0 :       arg->stp_type = pe_long;
     365   [ #  #  #  # ]:          0 :       switch (qualifier)
     366                 :            :         {
     367                 :            :         case 'L':
     368         [ #  # ]:          0 :           arg->c_type = "long long";
     369                 :          0 :           break;
     370                 :            : 
     371                 :            :         case 'l':
     372         [ #  # ]:          0 :           arg->c_type = "long";
     373                 :          0 :           break;
     374                 :            : 
     375                 :            :         case 'h':
     376         [ #  # ]:          0 :           arg->c_type = "short";
     377                 :          0 :           break;
     378                 :            : 
     379                 :            :         default:
     380         [ #  # ]:          0 :           arg->c_type = "int";
     381                 :          0 :           break;
     382                 :            :         }
     383         [ #  # ]:          0 :       mark_args.push_back(arg);
     384                 :            :     }
     385                 :          0 : }
     386                 :            : 
     387                 :            : 
     388                 :            : void
     389                 :          0 : mark_derived_probe::join_group (systemtap_session& s)
     390                 :            : {
     391         [ #  # ]:          0 :   if (! s.mark_derived_probes)
     392                 :            :     {
     393 [ #  # ][ #  # ]:          0 :       s.mark_derived_probes = new mark_derived_probe_group ();
     394                 :            : 
     395                 :            :       // Make sure <linux/marker.h> is included early.
     396 [ #  # ][ #  # ]:          0 :       embeddedcode *ec = new embeddedcode;
     397                 :          0 :       ec->tok = NULL;
     398                 :            :       ec->code = string("#if ! defined(CONFIG_MARKERS)\n")
     399                 :            :         + string("#error \"Need CONFIG_MARKERS!\"\n")
     400                 :            :         + string("#endif\n")
     401 [ #  # ][ #  # ]:          0 :         + string("#include <linux/marker.h>\n");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     402                 :            : 
     403         [ #  # ]:          0 :       s.embeds.push_back(ec);
     404                 :            :     }
     405                 :          0 :   s.mark_derived_probes->enroll (this);
     406                 :          0 : }
     407                 :            : 
     408                 :            : 
     409                 :            : void
     410                 :          0 : mark_derived_probe::print_dupe_stamp (ostream& o)
     411                 :            : {
     412         [ #  # ]:          0 :   if (target_symbol_seen)
     413         [ #  # ]:          0 :     for (unsigned i = 0; i < mark_args.size(); i++)
     414                 :          0 :       o << mark_args[i]->c_type << " __mark_arg" << (i+1) << endl;
     415                 :          0 : }
     416                 :            : 
     417                 :            : 
     418                 :            : void
     419                 :          0 : mark_derived_probe::initialize_probe_context_vars (translator_output* o)
     420                 :            : {
     421                 :            :   // If we haven't seen a target symbol for this probe, quit.
     422         [ #  # ]:          0 :   if (! target_symbol_seen)
     423                 :          0 :     return;
     424                 :            : 
     425                 :          0 :   bool deref_fault_needed = false;
     426         [ #  # ]:          0 :   for (unsigned i = 0; i < mark_args.size(); i++)
     427                 :            :     {
     428                 :            :       string localname = "l->" +
     429 [ #  # ][ #  # ]:          0 :         sess.up->c_localname("__mark_arg" + lex_cast(i+1));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     430      [ #  #  # ]:          0 :       switch (mark_args[i]->stp_type)
     431                 :            :         {
     432                 :            :         case pe_long:
     433 [ #  # ][ #  # ]:          0 :           o->newline() << localname << " = va_arg(*c->ips.kmark.mark_va_list, "
                 [ #  # ]
     434 [ #  # ][ #  # ]:          0 :                        << mark_args[i]->c_type << ");";
     435                 :          0 :           break;
     436                 :            : 
     437                 :            :         case pe_string:
     438                 :            :           // We're assuming that this is a kernel string (this code is
     439                 :            :           // basically the guts of kernel_string), not a user string.
     440 [ #  # ][ #  # ]:          0 :           o->newline() << "{ " << mark_args[i]->c_type
                 [ #  # ]
     441         [ #  # ]:          0 :                        << " tmp_str = va_arg(*c->ips.kmark.mark_va_list, "
     442 [ #  # ][ #  # ]:          0 :                        << mark_args[i]->c_type << ");";
     443 [ #  # ][ #  # ]:          0 :           o->newline() << "kderef_string (" << localname
                 [ #  # ]
     444         [ #  # ]:          0 :                        << ", tmp_str, MAXSTRINGLEN); }";
     445                 :          0 :           deref_fault_needed = true;
     446                 :          0 :           break;
     447                 :            : 
     448                 :            :         default:
     449 [ #  # ][ #  # ]:          0 :           throw semantic_error (_("cannot expand unknown type"));
     450                 :            :           break;
     451                 :            :         }
     452         [ #  # ]:          0 :     }
     453         [ #  # ]:          0 :   if (deref_fault_needed)
     454                 :            :     // Need to report errors?
     455                 :          0 :     o->newline() << "deref_fault: ;";
     456                 :            : }
     457                 :            : 
     458                 :            : void
     459                 :          0 : mark_derived_probe::getargs(std::list<std::string> &arg_set) const
     460                 :            : {
     461                 :            :   //PR11761: hard-coded the basic variables
     462 [ #  # ][ #  # ]:          0 :   arg_set.push_back("$name:string");
                 [ #  # ]
     463 [ #  # ][ #  # ]:          0 :   arg_set.push_back("$format:string");
                 [ #  # ]
     464         [ #  # ]:          0 :   for (unsigned i = 0; i < mark_args.size(); i++)
     465                 :            :     {
     466 [ #  # ][ #  # ]:          0 :       string localname = "$arg" + lex_cast(i+1);
                 [ #  # ]
     467      [ #  #  # ]:          0 :       switch (mark_args[i]->stp_type)
     468                 :            :         {
     469                 :            :         case pe_long:
     470 [ #  # ][ #  # ]:          0 :           arg_set.push_back(localname+":long");
                 [ #  # ]
     471                 :          0 :           break;
     472                 :            :         case pe_string:
     473 [ #  # ][ #  # ]:          0 :           arg_set.push_back(localname+":string");
                 [ #  # ]
     474                 :          0 :           break;
     475                 :            :         default:
     476 [ #  # ][ #  # ]:          0 :           arg_set.push_back(localname+":unknown");
                 [ #  # ]
     477                 :          0 :           break;
     478                 :            :         }
     479         [ #  # ]:          0 :     }
     480                 :          0 : }
     481                 :            : 
     482                 :            : 
     483                 :            : void
     484                 :          0 : mark_derived_probe_group::emit_module_decls (systemtap_session& s)
     485                 :            : {
     486         [ #  # ]:          0 :   if (probes.empty())
     487                 :          0 :     return;
     488                 :            : 
     489                 :          0 :   s.op->newline() << "/* ---- marker probes ---- */";
     490                 :            : 
     491                 :          0 :   s.op->newline() << "static struct stap_marker_probe {";
     492                 :          0 :   s.op->newline(1) << "const char * const name;";
     493                 :          0 :   s.op->newline() << "const char * const format;";
     494                 :          0 :   s.op->newline() << "const struct stap_probe * const probe;";
     495                 :          0 :   s.op->newline(-1) << "} stap_marker_probes [" << probes.size() << "] = {";
     496                 :          0 :   s.op->indent(1);
     497         [ #  # ]:          0 :   for (unsigned i=0; i < probes.size(); i++)
     498                 :            :     {
     499                 :          0 :       s.op->newline () << "{";
     500 [ #  # ][ #  # ]:          0 :       s.op->line() << " .name=" << lex_cast_qstring(probes[i]->probe_name) << ",";
     501 [ #  # ][ #  # ]:          0 :       s.op->line() << " .format=" << lex_cast_qstring(probes[i]->probe_format) << ",";
     502 [ #  # ][ #  # ]:          0 :       s.op->line() << " .probe=" << common_probe_init (probes[i]) << ",";
     503                 :          0 :       s.op->line() << " },";
     504                 :            :     }
     505                 :          0 :   s.op->newline(-1) << "};";
     506                 :          0 :   s.op->newline();
     507                 :            : 
     508                 :            : 
     509                 :            :   // Emit the marker callback function
     510                 :          0 :   s.op->newline();
     511                 :          0 :   s.op->newline() << "static void enter_marker_probe (void *probe_data, void *call_data, const char *fmt, va_list *args) {";
     512                 :          0 :   s.op->newline(1) << "struct stap_marker_probe *smp = (struct stap_marker_probe *)probe_data;";
     513                 :            :   common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "smp->probe",
     514 [ #  # ][ #  # ]:          0 :                                  "stp_probe_type_marker");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     515                 :          0 :   s.op->newline() << "c->ips.kmark.marker_name = smp->name;";
     516                 :          0 :   s.op->newline() << "c->ips.kmark.marker_format = smp->format;";
     517                 :          0 :   s.op->newline() << "c->ips.kmark.mark_va_list = args;";
     518                 :          0 :   s.op->newline() << "(*smp->probe->ph) (c);";
     519                 :          0 :   s.op->newline() << "c->ips.kmark.mark_va_list = NULL;";
     520                 :            : 
     521                 :          0 :   common_probe_entryfn_epilogue (s, true);
     522                 :          0 :   s.op->newline(-1) << "}";
     523                 :            : 
     524                 :          0 :   return;
     525                 :            : }
     526                 :            : 
     527                 :            : 
     528                 :            : void
     529                 :          0 : mark_derived_probe_group::emit_module_init (systemtap_session &s)
     530                 :            : {
     531         [ #  # ]:          0 :   if (probes.size () == 0)
     532                 :          0 :     return;
     533                 :            : 
     534                 :          0 :   s.op->newline() << "/* init marker probes */";
     535                 :          0 :   s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
     536                 :          0 :   s.op->newline(1) << "struct stap_marker_probe *smp = &stap_marker_probes[i];";
     537                 :          0 :   s.op->newline() << "probe_point = smp->probe->pp;";
     538                 :          0 :   s.op->newline() << "rc = marker_probe_register(smp->name, smp->format, enter_marker_probe, smp);";
     539                 :          0 :   s.op->newline() << "if (rc) {";
     540                 :          0 :   s.op->newline(1) << "for (j=i-1; j>=0; j--) {"; // partial rollback
     541                 :          0 :   s.op->newline(1) << "struct stap_marker_probe *smp2 = &stap_marker_probes[j];";
     542                 :          0 :   s.op->newline() << "marker_probe_unregister(smp2->name, enter_marker_probe, smp2);";
     543                 :          0 :   s.op->newline(-1) << "}";
     544                 :          0 :   s.op->newline() << "break;"; // don't attempt to register any more probes
     545                 :          0 :   s.op->newline(-1) << "}";
     546                 :          0 :   s.op->newline(-1) << "}"; // for loop
     547                 :            : }
     548                 :            : 
     549                 :            : 
     550                 :            : void
     551                 :          0 : mark_derived_probe_group::emit_module_exit (systemtap_session& s)
     552                 :            : {
     553         [ #  # ]:          0 :   if (probes.empty())
     554                 :          0 :     return;
     555                 :            : 
     556                 :          0 :   s.op->newline() << "/* deregister marker probes */";
     557                 :          0 :   s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {";
     558                 :          0 :   s.op->newline(1) << "struct stap_marker_probe *smp = &stap_marker_probes[i];";
     559                 :          0 :   s.op->newline() << "marker_probe_unregister(smp->name, enter_marker_probe, smp);";
     560                 :          0 :   s.op->newline(-1) << "}"; // for loop
     561                 :            : }
     562                 :            : 
     563                 :            : 
     564 [ #  # ][ #  # ]:          0 : struct mark_builder: public derived_probe_builder
     565                 :            : {
     566                 :            : private:
     567                 :            :   bool cache_initialized;
     568                 :            :   typedef multimap<string, string> mark_cache_t;
     569                 :            :   typedef multimap<string, string>::const_iterator mark_cache_const_iterator_t;
     570                 :            :   typedef pair<mark_cache_const_iterator_t, mark_cache_const_iterator_t>
     571                 :            :     mark_cache_const_iterator_pair_t;
     572                 :            :   mark_cache_t mark_cache;
     573                 :            : 
     574                 :            : public:
     575         [ +  - ]:       1218 :   mark_builder(): cache_initialized(false) {}
     576                 :            : 
     577                 :       2436 :   void build_no_more (systemtap_session &s)
     578                 :            :   {
     579         [ -  + ]:       2436 :     if (! mark_cache.empty())
     580                 :            :       {
     581         [ #  # ]:          0 :         if (s.verbose > 3)
     582                 :          0 :           clog << _("mark_builder releasing cache") << endl;
     583                 :          0 :         mark_cache.clear();
     584                 :            :       }
     585                 :       2436 :   }
     586                 :            : 
     587                 :            :   void build(systemtap_session & sess,
     588                 :            :              probe * base,
     589                 :            :              probe_point * location,
     590                 :            :              literal_map_t const & parameters,
     591                 :            :              vector<derived_probe *> & finished_results);
     592                 :            : };
     593                 :            : 
     594                 :            : 
     595                 :            : void
     596                 :          5 : mark_builder::build(systemtap_session & sess,
     597                 :            :                     probe * base,
     598                 :            :                     probe_point *loc,
     599                 :            :                     literal_map_t const & parameters,
     600                 :            :                     vector<derived_probe *> & finished_results)
     601                 :            : {
     602         [ +  - ]:          5 :   string mark_str_val;
     603         [ +  - ]:          5 :   bool has_mark_str = get_param (parameters, TOK_MARK, mark_str_val);
     604         [ +  - ]:          5 :   string mark_format_val;
     605         [ +  - ]:          5 :   bool has_mark_format = get_param (parameters, TOK_FORMAT, mark_format_val);
     606         [ -  + ]:          5 :   assert (has_mark_str);
     607                 :            :   (void) has_mark_str;
     608                 :            : 
     609         [ +  + ]:          5 :   if (! cache_initialized)
     610                 :            :     {
     611                 :          3 :       cache_initialized = true;
     612         [ +  - ]:          3 :       string module_markers_path = sess.kernel_build_tree + "/Module.markers";
     613                 :            :       
     614         [ +  - ]:          3 :       ifstream module_markers;
     615 [ +  - ][ +  - ]:          3 :       module_markers.open(module_markers_path.c_str(), ifstream::in);
     616 [ +  - ][ +  - ]:          3 :       if (! module_markers)
     617                 :            :         {
     618         [ -  + ]:          3 :           if (sess.verbose>3)
     619                 :            :             //TRANSLATORS: specific path cannot be opened
     620 [ #  # ][ #  # ]:          0 :             clog << module_markers_path << _(" cannot be opened: ")
     621 [ #  # ][ #  # ]:          3 :                  << strerror(errno) << endl;
     622                 :          5 :           return;
     623                 :            :         }
     624                 :            : 
     625 [ #  # ][ #  # ]:          0 :       string name, module, format;
                 [ #  # ]
     626         [ #  # ]:          0 :       do
     627                 :            :         {
     628 [ #  # ][ #  # ]:          0 :           module_markers >> name >> module;
     629         [ #  # ]:          0 :           getline(module_markers, format);
     630                 :            : 
     631                 :            :           // trim leading whitespace
     632         [ #  # ]:          0 :           string::size_type notwhite = format.find_first_not_of(" \t");
     633         [ #  # ]:          0 :           format.erase(0, notwhite);
     634                 :            : 
     635                 :            :           // If the format is empty, make sure we add back a space
     636                 :            :           // character, which is what MARK_NOARGS expands to.
     637 [ #  # ][ #  # ]:          0 :           if (format.length() == 0)
     638         [ #  # ]:          0 :             format = " ";
     639                 :            : 
     640         [ #  # ]:          0 :           if (sess.verbose>3)
     641 [ #  # ][ #  # ]:          0 :             clog << "'" << name << "' '" << module << "' '" << format
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     642 [ #  # ][ #  # ]:          0 :                  << "'" << endl;
     643                 :            : 
     644 [ #  # ][ #  # ]:          0 :           if (mark_cache.count(name) > 0)
     645                 :            :             {
     646                 :            :               // If we have 2 markers with the same we've got 2 cases:
     647                 :            :               // different format strings or duplicate format strings.
     648                 :            :               // If an existing marker in the cache doesn't have the
     649                 :            :               // same format string, add this marker.
     650         [ #  # ]:          0 :               mark_cache_const_iterator_pair_t ret;
     651                 :          0 :               mark_cache_const_iterator_t it;
     652                 :          0 :               bool matching_format_string = false;
     653                 :            : 
     654 [ #  # ][ #  # ]:          0 :               ret = mark_cache.equal_range(name);
     655         [ #  # ]:          0 :               for (it = ret.first; it != ret.second; ++it)
     656                 :            :                 {
     657 [ #  # ][ #  # ]:          0 :                   if (format == it->second)
                 [ #  # ]
     658                 :            :                     {
     659                 :          0 :                       matching_format_string = true;
     660                 :          0 :                       break;
     661                 :            :                     }
     662                 :            :                 }
     663                 :            : 
     664         [ #  # ]:          0 :               if (! matching_format_string)
     665 [ #  # ][ #  # ]:          0 :                 mark_cache.insert(pair<string,string>(name, format));
         [ #  # ][ #  # ]
                 [ #  # ]
     666                 :            :           }
     667                 :            :           else
     668 [ #  # ][ #  # ]:          0 :             mark_cache.insert(pair<string,string>(name, format));
         [ #  # ][ #  # ]
                 [ #  # ]
     669                 :            :         }
     670         [ #  # ]:          0 :       while (! module_markers.eof());
     671 [ #  # ][ #  # ]:          3 :       module_markers.close();
         [ #  # ][ #  # ]
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
     672                 :            :     }
     673                 :            : 
     674                 :            :   // Search marker list for matching markers
     675 [ +  - ][ -  + ]:          4 :   for (mark_cache_const_iterator_t it = mark_cache.begin();
     676         [ +  - ]:          2 :        it != mark_cache.end(); it++)
     677                 :            :     {
     678                 :            :       // Below, "rc" has negative polarity: zero iff matching.
     679 [ #  # ][ #  # ]:          0 :       int rc = fnmatch(mark_str_val.c_str(), it->first.c_str(), 0);
         [ #  # ][ #  # ]
     680         [ #  # ]:          0 :       if (! rc)
     681                 :            :         {
     682                 :          0 :           bool add_result = true;
     683                 :            : 
     684                 :            :           // Match format strings (if the user specified one)
     685 [ #  # ][ #  # ]:          0 :           if (has_mark_format && fnmatch(mark_format_val.c_str(),
                 [ #  # ]
     686 [ #  # ][ #  # ]:          0 :                                          it->second.c_str(), 0))
         [ #  # ][ #  # ]
     687                 :          0 :             add_result = false;
     688                 :            : 
     689         [ #  # ]:          0 :           if (add_result)
     690                 :            :             {
     691                 :            :               derived_probe *dp
     692                 :            :                 = new mark_derived_probe (sess,
     693 [ #  # ][ #  # ]:          0 :                                           it->first, it->second,
     694 [ #  # ][ #  # ]:          0 :                                           base, loc);
     695         [ #  # ]:          0 :               finished_results.push_back (dp);
     696                 :            :             }
     697                 :            :         }
     698 [ +  - ][ +  + ]:          5 :     }
         [ +  - ][ +  + ]
     699                 :            : }
     700                 :            : 
     701                 :            : 
     702                 :            : 
     703                 :            : void
     704                 :       1218 : register_tapset_mark(systemtap_session& s)
     705                 :            : {
     706                 :       1218 :   match_node* root = s.pattern_root;
     707         [ +  - ]:       1218 :   derived_probe_builder *builder = new mark_builder();
     708                 :            : 
     709                 :       1218 :   root = root->bind(TOK_KERNEL);
     710                 :       1218 :   root = root->bind_str(TOK_MARK);
     711                 :            : 
     712                 :       1218 :   root->bind(builder);
     713                 :       1218 :   root->bind_str(TOK_FORMAT)->bind(builder);
     714 [ +  - ][ +  - ]:       8460 : }
     715                 :            : 
     716                 :            : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */

Generated by: LCOV version 1.9