LCOV - code coverage report
Current view: top level - mnt/wasteland/wcohen/systemtap_write/systemtap - tapset-utrace.cxx (source / functions) Hit Total Coverage
Test: stap.info Lines: 460 624 73.7 %
Date: 2013-03-08 Functions: 24 36 66.7 %
Branches: 408 1038 39.3 %

           Branch data     Line data    Source code
       1                 :            : // utrace tapset
       2                 :            : // Copyright (C) 2005-2013 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                 :            : 
      11                 :            : #include "session.h"
      12                 :            : #include "tapsets.h"
      13                 :            : #include "task_finder.h"
      14                 :            : #include "tapset-dynprobe.h"
      15                 :            : #include "translate.h"
      16                 :            : #include "util.h"
      17                 :            : 
      18                 :            : #include <cstring>
      19                 :            : #include <string>
      20                 :            : 
      21                 :            : 
      22                 :            : using namespace std;
      23                 :            : using namespace __gnu_cxx;
      24                 :            : 
      25                 :            : 
      26         [ +  - ]:       2414 : static const string TOK_PROCESS("process");
      27         [ +  - ]:       2414 : static const string TOK_BEGIN("begin");
      28         [ +  - ]:       2414 : static const string TOK_END("end");
      29         [ +  - ]:       2414 : static const string TOK_THREAD("thread");
      30         [ +  - ]:       2414 : static const string TOK_SYSCALL("syscall");
      31         [ +  - ]:       2414 : static const string TOK_RETURN("return");
      32                 :            : 
      33                 :            : 
      34                 :            : // ------------------------------------------------------------------------
      35                 :            : // utrace user-space probes
      36                 :            : // ------------------------------------------------------------------------
      37                 :            : 
      38                 :            : // Note that these flags don't match up exactly with UTRACE_EVENT
      39                 :            : // flags (and that's OK).
      40                 :            : enum utrace_derived_probe_flags {
      41                 :            :   UDPF_NONE,
      42                 :            :   UDPF_BEGIN,                           // process begin
      43                 :            :   UDPF_END,                             // process end
      44                 :            :   UDPF_THREAD_BEGIN,                    // thread begin
      45                 :            :   UDPF_THREAD_END,                      // thread end
      46                 :            :   UDPF_SYSCALL,                         // syscall entry
      47                 :            :   UDPF_SYSCALL_RETURN,                  // syscall exit
      48                 :            :   UDPF_NFLAGS
      49                 :            : };
      50                 :            : 
      51 [ #  # ][ #  # ]:          0 : struct utrace_derived_probe: public derived_probe
                 [ #  # ]
      52                 :            : {
      53                 :            :   bool has_path;
      54                 :            :   string path;
      55                 :            :   bool has_library;
      56                 :            :   string library;
      57                 :            :   int64_t pid;
      58                 :            :   enum utrace_derived_probe_flags flags;
      59                 :            :   bool target_symbol_seen;
      60                 :            : 
      61                 :            :   utrace_derived_probe (systemtap_session &s, probe* p, probe_point* l,
      62                 :            :                         bool hp, string &pn, int64_t pd,
      63                 :            :                         enum utrace_derived_probe_flags f);
      64                 :            :   void join_group (systemtap_session& s);
      65                 :            : 
      66                 :            :   void emit_privilege_assertion (translator_output*);
      67                 :            :   void print_dupe_stamp(ostream& o);
      68                 :            :   void getargs (std::list<std::string> &arg_set) const;
      69                 :            : };
      70                 :            : 
      71                 :            : 
      72 [ #  # ][ #  # ]:          0 : struct utrace_derived_probe_group: public generic_dpg<utrace_derived_probe>
                 [ #  # ]
      73                 :            : {
      74                 :            : private:
      75                 :            :   map<string, vector<utrace_derived_probe*> > probes_by_path;
      76                 :            :   typedef map<string, vector<utrace_derived_probe*> >::iterator p_b_path_iterator;
      77                 :            :   map<int64_t, vector<utrace_derived_probe*> > probes_by_pid;
      78                 :            :   typedef map<int64_t, vector<utrace_derived_probe*> >::iterator p_b_pid_iterator;
      79                 :            :   unsigned num_probes;
      80                 :            :   bool flags_seen[UDPF_NFLAGS];
      81                 :            : 
      82                 :            :   // Using the linux backend
      83                 :            :   void emit_linux_probe_decl (systemtap_session& s, utrace_derived_probe *p);
      84                 :            :   void emit_module_linux_decls (systemtap_session& s);
      85                 :            :   void emit_module_linux_init (systemtap_session& s);
      86                 :            :   void emit_module_linux_exit (systemtap_session& s);
      87                 :            : 
      88                 :            :   // Using the dyninst backend (via stapdyn)
      89                 :            :   void emit_dyninst_probe_decl (systemtap_session& s, const string& path,
      90                 :            :                                 utrace_derived_probe *p);
      91                 :            :   void emit_module_dyninst_decls (systemtap_session& s);
      92                 :            :   void emit_module_dyninst_init (systemtap_session& s);
      93                 :            :   void emit_module_dyninst_exit (systemtap_session& s);
      94                 :            : 
      95                 :            : public:
      96 [ +  - ][ +  - ]:        128 :   utrace_derived_probe_group(): num_probes(0), flags_seen() { }
                 [ +  + ]
      97                 :            : 
      98                 :            :   void enroll (utrace_derived_probe* probe);
      99                 :            :   void emit_module_decls (systemtap_session& s);
     100                 :            :   void emit_module_init (systemtap_session& s);
     101                 :            :   void emit_module_exit (systemtap_session& s);
     102                 :            : };
     103                 :            : 
     104                 :            : 
     105 [ +  - ][ +  - ]:         18 : struct utrace_var_expanding_visitor: public var_expanding_visitor
                 [ -  + ]
     106                 :            : {
     107                 :         18 :   utrace_var_expanding_visitor(systemtap_session& s, probe_point* l,
     108                 :            :                                const string& pn,
     109                 :            :                                enum utrace_derived_probe_flags f):
     110                 :            :     sess (s), base_loc (l), probe_name (pn), flags (f),
     111 [ +  - ][ +  - ]:         18 :     target_symbol_seen (false), add_block(NULL), add_probe(NULL) {}
     112                 :            : 
     113                 :            :   systemtap_session& sess;
     114                 :            :   probe_point* base_loc;
     115                 :            :   string probe_name;
     116                 :            :   enum utrace_derived_probe_flags flags;
     117                 :            :   bool target_symbol_seen;
     118                 :            :   block *add_block;
     119                 :            :   probe *add_probe;
     120                 :            :   std::map<std::string, symbol *> return_ts_map;
     121                 :            : 
     122                 :            :   void visit_target_symbol_arg (target_symbol* e);
     123                 :            :   void visit_target_symbol_context (target_symbol* e);
     124                 :            :   void visit_target_symbol_cached (target_symbol* e);
     125                 :            :   void visit_target_symbol (target_symbol* e);
     126                 :            : };
     127                 :            : 
     128                 :            : 
     129                 :            : 
     130                 :         18 : utrace_derived_probe::utrace_derived_probe (systemtap_session &s,
     131                 :            :                                             probe* p, probe_point* l,
     132                 :            :                                             bool hp, string &pn, int64_t pd,
     133                 :            :                                             enum utrace_derived_probe_flags f):
     134                 :            :   derived_probe (p, l, true /* .components soon rewritten */ ),
     135                 :            :   has_path(hp), path(pn), has_library(false), pid(pd), flags(f),
     136 [ +  - ][ +  - ]:         18 :   target_symbol_seen(false)
     137                 :            : {
     138         [ +  - ]:         18 :   check_process_probe_kernel_support(s);
     139                 :            : 
     140                 :            :   // Expand local variables in the probe body
     141         [ +  - ]:         18 :   utrace_var_expanding_visitor v (s, l, name, flags);
     142         [ +  - ]:         18 :   v.replace (this->body);
     143                 :         18 :   target_symbol_seen = v.target_symbol_seen;
     144                 :            : 
     145                 :            :   // If during target-variable-expanding the probe, we added a new block
     146                 :            :   // of code, add it to the start of the probe.
     147         [ +  + ]:         18 :   if (v.add_block)
     148 [ +  - ][ +  - ]:          1 :     this->body = new block(v.add_block, this->body);
     149                 :            :   // If when target-variable-expanding the probe, we added a new
     150                 :            :   // probe, add it in a new file to the list of files to be processed.
     151         [ +  + ]:         18 :   if (v.add_probe)
     152                 :            :     {
     153 [ +  - ][ +  - ]:          1 :       stapfile *f = new stapfile;
     154         [ +  - ]:          1 :       f->probes.push_back(v.add_probe);
     155         [ +  - ]:          1 :       s.files.push_back(f);
     156                 :            :     }
     157                 :            : 
     158                 :            :   // Reset the sole element of the "locations" vector as a
     159                 :            :   // "reverse-engineered" form of the incoming (q.base_loc) probe
     160                 :            :   // point.  This allows a user to see what program etc.
     161                 :            :   // number any particular match of the wildcards.
     162                 :            : 
     163         [ +  - ]:         18 :   vector<probe_point::component*> comps;
     164         [ +  + ]:         18 :   if (hp)
     165 [ +  - ][ +  - ]:         13 :     comps.push_back (new probe_point::component(TOK_PROCESS, new literal_string(path)));
         [ +  - ][ +  - ]
                 [ +  - ]
     166         [ -  + ]:          5 :   else if (pid != 0)
     167 [ #  # ][ #  # ]:          0 :     comps.push_back (new probe_point::component(TOK_PROCESS, new literal_number(pid)));
         [ #  # ][ #  # ]
                 [ #  # ]
     168                 :            :   else
     169 [ +  - ][ +  - ]:          5 :     comps.push_back (new probe_point::component(TOK_PROCESS));
                 [ +  - ]
     170                 :            : 
     171   [ -  -  +  +  :         18 :   switch (flags)
                +  +  - ]
     172                 :            :     {
     173                 :            :     case UDPF_THREAD_BEGIN:
     174 [ #  # ][ #  # ]:          0 :       comps.push_back (new probe_point::component(TOK_THREAD));
                 [ #  # ]
     175 [ #  # ][ #  # ]:          0 :       comps.push_back (new probe_point::component(TOK_BEGIN));
                 [ #  # ]
     176                 :          0 :       break;
     177                 :            :     case UDPF_THREAD_END:
     178 [ #  # ][ #  # ]:          0 :       comps.push_back (new probe_point::component(TOK_THREAD));
                 [ #  # ]
     179 [ #  # ][ #  # ]:          0 :       comps.push_back (new probe_point::component(TOK_END));
                 [ #  # ]
     180                 :          0 :       break;
     181                 :            :     case UDPF_SYSCALL:
     182 [ +  - ][ +  - ]:         10 :       comps.push_back (new probe_point::component(TOK_SYSCALL));
                 [ +  - ]
     183                 :         10 :       break;
     184                 :            :     case UDPF_SYSCALL_RETURN:
     185 [ +  - ][ +  - ]:          4 :       comps.push_back (new probe_point::component(TOK_SYSCALL));
                 [ +  - ]
     186 [ +  - ][ +  - ]:          4 :       comps.push_back (new probe_point::component(TOK_RETURN));
                 [ +  - ]
     187                 :          4 :       break;
     188                 :            :     case UDPF_BEGIN:
     189 [ +  - ][ +  - ]:          3 :       comps.push_back (new probe_point::component(TOK_BEGIN));
                 [ +  - ]
     190                 :          3 :       break;
     191                 :            :     case UDPF_END:
     192 [ +  - ][ +  - ]:          1 :       comps.push_back (new probe_point::component(TOK_END));
                 [ +  - ]
     193                 :          1 :       break;
     194                 :            :     default:
     195                 :          0 :       assert (0);
     196                 :            :     }
     197                 :            : 
     198                 :            :   // Overwrite it.
     199 [ +  - ][ +  - ]:         18 :   this->sole_location()->components = comps;
         [ +  - ][ +  - ]
     200                 :         18 : }
     201                 :            : 
     202                 :            : 
     203                 :            : void
     204                 :         18 : utrace_derived_probe::join_group (systemtap_session& s)
     205                 :            : {
     206         [ +  + ]:         18 :   if (! s.utrace_derived_probes)
     207                 :            :     {
     208         [ +  - ]:         16 :       s.utrace_derived_probes = new utrace_derived_probe_group ();
     209                 :            :     }
     210                 :         18 :   s.utrace_derived_probes->enroll (this);
     211                 :            : 
     212         [ -  + ]:         18 :   if (s.runtime_usermode_p())
     213                 :          0 :     enable_dynprobes(s);
     214                 :            :   else
     215                 :         18 :     enable_task_finder(s);
     216                 :         18 : }
     217                 :            : 
     218                 :            : 
     219                 :            : void
     220                 :          4 : utrace_derived_probe::emit_privilege_assertion (translator_output* o)
     221                 :            : {
     222                 :            :   // Process end probes can fire for unprivileged users even if the process
     223                 :            :   // does not belong to the user. On example is that process.end will fire
     224                 :            :   // at the end of a process which executes execve on an executable which
     225                 :            :   // has the setuid bit set. When the setuid executable ends, the process.end
     226                 :            :   // will fire even though the owner of the process is different than the
     227                 :            :   // original owner.
     228                 :            :   // Unprivileged users must use check is_myproc() from within any
     229                 :            :   // process.end variant in their script before doing anything "dangerous".
     230         [ -  + ]:          4 :   if (flags == UDPF_END)
     231                 :          4 :     return;
     232                 :            : 
     233                 :            :   // Other process probes should only fire for unprivileged users in the
     234                 :            :   // context of processes which they own. Generate an assertion to this effect
     235                 :            :   // as a safety net.
     236                 :          4 :   emit_process_owner_assertion (o);
     237                 :            : }
     238                 :            : 
     239                 :            : void
     240                 :          8 : utrace_derived_probe::print_dupe_stamp(ostream& o)
     241                 :            : {
     242                 :            :   // Process end probes can fire for unprivileged users even if the process
     243                 :            :   // does not belong to the user. On example is that process.end will fire
     244                 :            :   // at the end of a process which executes execve on an executable which
     245                 :            :   // has the setuid bit set. When the setuid executable ends, the process.end
     246                 :            :   // will fire even though the owner of the process is different than the
     247                 :            :   // original owner.
     248                 :            :   // Unprivileged users must use check is_myproc() from within any
     249                 :            :   // process.end variant in their script before doing anything "dangerous".
     250                 :            :   //
     251                 :            :   // Other process probes should only fire for unprivileged users in the
     252                 :            :   // context of processes which they own.
     253         [ -  + ]:          8 :   if (flags == UDPF_END)
     254                 :          0 :     print_dupe_stamp_unprivileged (o);
     255                 :            :   else
     256                 :          8 :     print_dupe_stamp_unprivileged_process_owner (o);
     257                 :          8 : }
     258                 :            : 
     259                 :            : void
     260                 :          0 : utrace_derived_probe::getargs(std::list<std::string> &arg_set) const
     261                 :            : {
     262 [ #  # ][ #  # ]:          0 :   arg_set.push_back("$syscall:long");
                 [ #  # ]
     263 [ #  # ][ #  # ]:          0 :   arg_set.push_back("$arg1:long");
                 [ #  # ]
     264 [ #  # ][ #  # ]:          0 :   arg_set.push_back("$arg2:long");
                 [ #  # ]
     265 [ #  # ][ #  # ]:          0 :   arg_set.push_back("$arg3:long");
                 [ #  # ]
     266 [ #  # ][ #  # ]:          0 :   arg_set.push_back("$arg4:long");
                 [ #  # ]
     267 [ #  # ][ #  # ]:          0 :   arg_set.push_back("$arg5:long");
                 [ #  # ]
     268 [ #  # ][ #  # ]:          0 :   arg_set.push_back("$arg6:long");
                 [ #  # ]
     269                 :          0 : }
     270                 :            : 
     271                 :            : void
     272                 :          1 : utrace_var_expanding_visitor::visit_target_symbol_cached (target_symbol* e)
     273                 :            : {
     274                 :            :       // Get the full name of the target symbol.
     275         [ +  - ]:          1 :       stringstream ts_name_stream;
     276         [ +  - ]:          1 :       e->print(ts_name_stream);
     277         [ +  - ]:          1 :       string ts_name = ts_name_stream.str();
     278                 :            : 
     279                 :            :       // Check and make sure we haven't already seen this target
     280                 :            :       // variable in this return probe.  If we have, just return our
     281                 :            :       // last replacement.
     282         [ +  - ]:          1 :       map<string, symbol *>::iterator i = return_ts_map.find(ts_name);
     283 [ +  - ][ -  + ]:          1 :       if (i != return_ts_map.end())
     284                 :            :         {
     285 [ #  # ][ #  # ]:          0 :           provide (i->second);
     286                 :            :           return;
     287                 :            :         }
     288                 :            : 
     289                 :            :       // We've got to do several things here to handle target
     290                 :            :       // variables in return probes.
     291                 :            : 
     292                 :            :       // (1) Synthesize a global array which is the cache of the
     293                 :            :       // target variable value.  We don't need a nesting level counter
     294                 :            :       // like the dwarf_var_expanding_visitor::visit_target_symbol()
     295                 :            :       // does since a particular thread can only be in one system
     296                 :            :       // calls at a time. The array will look like this:
     297                 :            :       //
     298                 :            :       //   _utrace_tvar_{name}_{num}
     299                 :            :       string aname = (string("_utrace_tvar_")
     300                 :            :                       + e->sym_name()
     301 [ +  - ][ +  - ]:          1 :                       + "_" + lex_cast(tick++));
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     302 [ +  - ][ +  - ]:          1 :       vardecl* vd = new vardecl;
     303         [ +  - ]:          1 :       vd->name = aname;
     304                 :          1 :       vd->tok = e->tok;
     305         [ +  - ]:          1 :       sess.globals.push_back (vd);
     306                 :            : 
     307                 :            :       // (2) Create a new code block we're going to insert at the
     308                 :            :       // beginning of this probe to get the cached value into a
     309                 :            :       // temporary variable.  We'll replace the target variable
     310                 :            :       // reference with the temporary variable reference.  The code
     311                 :            :       // will look like this:
     312                 :            :       //
     313                 :            :       //   _utrace_tvar_tid = tid()
     314                 :            :       //   _utrace_tvar_{name}_{num}_tmp
     315                 :            :       //       = _utrace_tvar_{name}_{num}[_utrace_tvar_tid]
     316                 :            :       //   delete _utrace_tvar_{name}_{num}[_utrace_tvar_tid]
     317                 :            : 
     318                 :            :       // (2a) Synthesize the tid temporary expression, which will look
     319                 :            :       // like this:
     320                 :            :       //
     321                 :            :       //   _utrace_tvar_tid = tid()
     322 [ +  - ][ +  - ]:          1 :       symbol* tidsym = new symbol;
     323 [ +  - ][ +  - ]:          1 :       tidsym->name = string("_utrace_tvar_tid");
                 [ +  - ]
     324                 :          1 :       tidsym->tok = e->tok;
     325                 :            : 
     326         [ +  - ]:          1 :       if (add_block == NULL)
     327                 :            :         {
     328 [ +  - ][ +  - ]:          1 :            add_block = new block;
     329                 :          1 :            add_block->tok = e->tok;
     330                 :            : 
     331                 :            :            // Synthesize a functioncall to grab the thread id.
     332 [ +  - ][ +  - ]:          1 :            functioncall* fc = new functioncall;
     333                 :          1 :            fc->tok = e->tok;
     334 [ +  - ][ +  - ]:          1 :            fc->function = string("tid");
                 [ +  - ]
     335                 :            : 
     336                 :            :            // Assign the tid to '_utrace_tvar_tid'.
     337 [ +  - ][ +  - ]:          1 :            assignment* a = new assignment;
     338                 :          1 :            a->tok = e->tok;
     339         [ +  - ]:          1 :            a->op = "=";
     340                 :          1 :            a->left = tidsym;
     341                 :          1 :            a->right = fc;
     342                 :            : 
     343 [ +  - ][ +  - ]:          1 :            expr_statement* es = new expr_statement;
     344                 :          1 :            es->tok = e->tok;
     345                 :          1 :            es->value = a;
     346         [ +  - ]:          1 :            add_block->statements.push_back (es);
     347                 :            :         }
     348                 :            : 
     349                 :            :       // (2b) Synthesize an array reference and assign it to a
     350                 :            :       // temporary variable (that we'll use as replacement for the
     351                 :            :       // target variable reference).  It will look like this:
     352                 :            :       //
     353                 :            :       //   _utrace_tvar_{name}_{num}_tmp
     354                 :            :       //       = _utrace_tvar_{name}_{num}[_utrace_tvar_tid]
     355                 :            : 
     356 [ +  - ][ +  - ]:          1 :       arrayindex* ai_tvar = new arrayindex;
     357                 :          1 :       ai_tvar->tok = e->tok;
     358                 :            : 
     359 [ +  - ][ +  - ]:          1 :       symbol* sym = new symbol;
     360         [ +  - ]:          1 :       sym->name = aname;
     361                 :          1 :       sym->tok = e->tok;
     362                 :          1 :       ai_tvar->base = sym;
     363                 :            : 
     364         [ +  - ]:          1 :       ai_tvar->indexes.push_back(tidsym);
     365                 :            : 
     366 [ +  - ][ +  - ]:          1 :       symbol* tmpsym = new symbol;
     367 [ +  - ][ +  - ]:          1 :       tmpsym->name = aname + "_tmp";
                 [ +  - ]
     368                 :          1 :       tmpsym->tok = e->tok;
     369                 :            : 
     370 [ +  - ][ +  - ]:          1 :       assignment* a = new assignment;
     371                 :          1 :       a->tok = e->tok;
     372         [ +  - ]:          1 :       a->op = "=";
     373                 :          1 :       a->left = tmpsym;
     374                 :          1 :       a->right = ai_tvar;
     375                 :            : 
     376 [ +  - ][ +  - ]:          1 :       expr_statement* es = new expr_statement;
     377                 :          1 :       es->tok = e->tok;
     378                 :          1 :       es->value = a;
     379                 :            : 
     380         [ +  - ]:          1 :       add_block->statements.push_back (es);
     381                 :            : 
     382                 :            :       // (2c) Delete the array value.  It will look like this:
     383                 :            :       //
     384                 :            :       //   delete _utrace_tvar_{name}_{num}[_utrace_tvar_tid]
     385                 :            : 
     386 [ +  - ][ +  - ]:          1 :       delete_statement* ds = new delete_statement;
     387                 :          1 :       ds->tok = e->tok;
     388                 :          1 :       ds->value = ai_tvar;
     389         [ +  - ]:          1 :       add_block->statements.push_back (ds);
     390                 :            : 
     391                 :            :       // (3) We need an entry probe that saves the value for us in the
     392                 :            :       // global array we created.  Create the entry probe, which will
     393                 :            :       // look like this:
     394                 :            :       //
     395                 :            :       //   probe process(PATH_OR_PID).syscall {
     396                 :            :       //     _utrace_tvar_tid = tid()
     397                 :            :       //     _utrace_tvar_{name}_{num}[_utrace_tvar_tid] = ${param}
     398                 :            :       //   }
     399                 :            :       //
     400                 :            :       // Why the temporary for tid()?  If we end up caching more
     401                 :            :       // than one target variable, we can reuse the temporary instead
     402                 :            :       // of calling tid() multiple times.
     403                 :            : 
     404         [ +  - ]:          1 :       if (add_probe == NULL)
     405                 :            :         {
     406 [ +  - ][ +  - ]:          1 :            add_probe = new probe;
     407                 :          1 :            add_probe->tok = e->tok;
     408                 :            : 
     409                 :            :            // We need the name of the current probe point, minus the
     410                 :            :            // ".return".  Create a new probe point, copying all the
     411                 :            :            // components, stopping when we see the ".return"
     412                 :            :            // component.
     413 [ +  - ][ +  - ]:          1 :            probe_point* pp = new probe_point;
     414         [ +  - ]:          3 :            for (unsigned c = 0; c < base_loc->components.size(); c++)
     415                 :            :              {
     416 [ +  - ][ +  + ]:          3 :                 if (base_loc->components[c]->functor == "return")
     417                 :          1 :                   break;
     418                 :            :                 else
     419         [ +  - ]:          2 :                   pp->components.push_back(base_loc->components[c]);
     420                 :            :              }
     421                 :          1 :            pp->optional = base_loc->optional;
     422         [ +  - ]:          1 :            add_probe->locations.push_back(pp);
     423                 :            : 
     424 [ +  - ][ +  - ]:          1 :            add_probe->body = new block;
     425                 :          1 :            add_probe->body->tok = e->tok;
     426                 :            : 
     427                 :            :            // Synthesize a functioncall to grab the thread id.
     428 [ +  - ][ +  - ]:          1 :            functioncall* fc = new functioncall;
     429                 :          1 :            fc->tok = e->tok;
     430 [ +  - ][ +  - ]:          1 :            fc->function = string("tid");
                 [ +  - ]
     431                 :            : 
     432                 :            :            // Assign the tid to '_utrace_tvar_tid'.
     433 [ +  - ][ +  - ]:          1 :            assignment* a = new assignment;
     434                 :          1 :            a->tok = e->tok;
     435         [ +  - ]:          1 :            a->op = "=";
     436                 :          1 :            a->left = tidsym;
     437                 :          1 :            a->right = fc;
     438                 :            : 
     439 [ +  - ][ +  - ]:          1 :            expr_statement* es = new expr_statement;
     440                 :          1 :            es->tok = e->tok;
     441                 :          1 :            es->value = a;
     442 [ +  - ][ +  - ]:          1 :            add_probe->body = new block(add_probe->body, es);
     443                 :            : 
     444 [ +  - ][ +  - ]:          1 :            vardecl* vd = new vardecl;
     445                 :          1 :            vd->tok = e->tok;
     446         [ +  - ]:          1 :            vd->name = tidsym->name;
     447                 :          1 :            vd->type = pe_long;
     448         [ +  - ]:          1 :            vd->set_arity(0, e->tok);
     449         [ +  - ]:          1 :            add_probe->locals.push_back(vd);
     450                 :            :         }
     451                 :            : 
     452                 :            :       // Save the value, like this:
     453                 :            :       //
     454                 :            :       //   _utrace_tvar_{name}_{num}[_utrace_tvar_tid] = ${param}
     455 [ +  - ][ +  - ]:          1 :       a = new assignment;
     456                 :          1 :       a->tok = e->tok;
     457         [ +  - ]:          1 :       a->op = "=";
     458                 :          1 :       a->left = ai_tvar;
     459                 :          1 :       a->right = e;
     460                 :            : 
     461 [ +  - ][ +  - ]:          1 :       es = new expr_statement;
     462                 :          1 :       es->tok = e->tok;
     463                 :          1 :       es->value = a;
     464                 :            : 
     465 [ +  - ][ +  - ]:          1 :       add_probe->body = new block(add_probe->body, es);
     466                 :            : 
     467                 :            :       // (4) Provide the '_utrace_tvar_{name}_{num}_tmp' variable to
     468                 :            :       // our parent so it can be used as a substitute for the target
     469                 :            :       // symbol.
     470         [ +  - ]:          1 :       provide (tmpsym);
     471                 :            : 
     472                 :            :       // (5) Remember this replacement since we might be able to reuse
     473                 :            :       // it later if the same return probe references this target
     474                 :            :       // symbol again.
     475         [ +  - ]:          1 :       return_ts_map[ts_name] = tmpsym;
     476 [ +  - ][ +  - ]:          1 :       return;
                 [ +  - ]
     477                 :            : }
     478                 :            : 
     479                 :            : 
     480                 :            : void
     481                 :         10 : utrace_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e)
     482                 :            : {
     483         [ +  + ]:         10 :   if (flags != UDPF_SYSCALL)
     484 [ +  - ][ +  - ]:          1 :     throw semantic_error (_("only \"process(PATH_OR_PID).syscall\" support $argN or $$parms."), e->tok);
     485                 :            : 
     486         [ -  + ]:          9 :   if (e->name == "$$parms")
     487                 :            :     {
     488                 :            :       // copy from tracepoint
     489         [ #  # ]:          0 :       token* pf_tok = new token(*e->tok);
     490                 :          0 :       pf_tok->content = "sprintf";
     491                 :          0 :       print_format* pf = print_format::create(pf_tok);
     492                 :            : 
     493                 :          0 :       target_symbol_seen = true;
     494                 :            : 
     495         [ #  # ]:          0 :       for (unsigned i = 0; i < 6; ++i)
     496                 :            :         {
     497         [ #  # ]:          0 :           if (i > 0)
     498                 :          0 :             pf->raw_components += " ";
     499 [ #  # ][ #  # ]:          0 :           pf->raw_components += "$arg" + lex_cast(i+1);
         [ #  # ][ #  # ]
                 [ #  # ]
     500         [ #  # ]:          0 :           target_symbol *tsym = new target_symbol;
     501                 :          0 :           tsym->tok = e->tok;
     502 [ #  # ][ #  # ]:          0 :           tsym->name = "$arg" + lex_cast(i+1);
         [ #  # ][ #  # ]
                 [ #  # ]
     503                 :          0 :           tsym->saved_conversion_error = 0;
     504                 :          0 :           pf->raw_components += "=%#x"; //FIXME: missing type info
     505                 :            : 
     506         [ #  # ]:          0 :           functioncall* n = new functioncall; //same as the following
     507                 :          0 :           n->tok = e->tok;
     508                 :          0 :           n->function = "_utrace_syscall_arg";
     509                 :          0 :           n->referent = 0;
     510         [ #  # ]:          0 :           literal_number *num = new literal_number(i);
     511                 :          0 :           num->tok = e->tok;
     512         [ #  # ]:          0 :           n->args.push_back(num);
     513                 :            : 
     514         [ #  # ]:          0 :           pf->args.push_back(n);
     515                 :            :         }
     516         [ #  # ]:          0 :       pf->components = print_format::string_to_components(pf->raw_components);
     517                 :            : 
     518                 :          0 :       provide (pf);
     519                 :            :      }
     520                 :            :    else // $argN
     521                 :            :      {
     522 [ +  - ][ +  - ]:          9 :         string argnum_s = e->name.substr(4,e->name.length()-4);
     523                 :          9 :         int argnum = 0;
     524                 :            :         try
     525                 :            :           {
     526         [ +  - ]:          9 :             argnum = lex_cast<int>(argnum_s);
     527                 :            :           }
     528         [ #  # ]:            :         catch (const runtime_error& f) // non-integral $arg suffix: e.g. $argKKKSDF
     529                 :            :           {
     530   [ #  #  #  # ]:            :            throw semantic_error (_("invalid syscall argument number (1-6)"), e->tok);
     531                 :            :           }
     532                 :            : 
     533 [ +  - ][ +  + ]:          9 :         e->assert_no_components("utrace");
                 [ +  - ]
     534                 :            : 
     535                 :            :         // FIXME: max argnument number should not be hardcoded.
     536 [ +  - ][ -  + ]:          7 :         if (argnum < 1 || argnum > 6)
     537 [ #  # ][ #  # ]:          0 :            throw semantic_error (_("invalid syscall argument number (1-6)"), e->tok);
     538                 :            : 
     539         [ +  - ]:          7 :         bool lvalue = is_active_lvalue(e);
     540         [ +  + ]:          7 :         if (lvalue)
     541 [ +  - ][ +  - ]:          1 :            throw semantic_error(_("utrace '$argN' variable is read-only"), e->tok);
     542                 :            : 
     543                 :            :         // Remember that we've seen a target variable.
     544                 :          6 :         target_symbol_seen = true;
     545                 :            : 
     546                 :            :         // We're going to substitute a synthesized '_utrace_syscall_arg'
     547                 :            :         // function call for the '$argN' reference.
     548 [ +  - ][ +  - ]:          6 :         functioncall* n = new functioncall;
     549                 :          6 :         n->tok = e->tok;
     550         [ +  - ]:          6 :         n->function = "_utrace_syscall_arg";
     551                 :          6 :         n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session
     552                 :            : 
     553 [ +  - ][ +  - ]:          6 :         literal_number *num = new literal_number(argnum - 1);
     554                 :          6 :         num->tok = e->tok;
     555         [ +  - ]:          6 :         n->args.push_back(num);
     556                 :            : 
     557 [ +  - ][ +  - ]:          9 :         provide (n);
     558                 :            :      }
     559                 :          6 : }
     560                 :            : 
     561                 :            : void
     562                 :         11 : utrace_var_expanding_visitor::visit_target_symbol_context (target_symbol* e)
     563                 :            : {
     564                 :         11 :   const string& sname = e->name;
     565                 :            : 
     566 [ +  - ][ +  + ]:         11 :   e->assert_no_components("utrace");
                 [ +  - ]
     567                 :            : 
     568         [ +  - ]:          7 :   bool lvalue = is_active_lvalue(e);
     569         [ +  + ]:          7 :   if (lvalue)
     570 [ +  - ][ +  - ]:          2 :     throw semantic_error(_F("utrace '%s' variable is read-only", sname.c_str()), e->tok);
                 [ +  - ]
     571                 :            : 
     572         [ +  - ]:          5 :   string fname;
     573 [ +  - ][ +  + ]:          5 :   if (sname == "$return")
     574                 :            :     {
     575         [ +  + ]:          2 :       if (flags != UDPF_SYSCALL_RETURN)
     576 [ +  - ][ +  - ]:          1 :         throw semantic_error (_("only \"process(PATH_OR_PID).syscall.return\" support $return."), e->tok);
     577         [ +  - ]:          1 :       fname = "_utrace_syscall_return";
     578                 :            :     }
     579 [ +  - ][ +  - ]:          3 :   else if (sname == "$syscall")
     580                 :            :     {
     581                 :            :       // If we've got a syscall entry probe, we can just call the
     582                 :            :       // right function.
     583         [ +  + ]:          3 :       if (flags == UDPF_SYSCALL) {
     584         [ +  - ]:          2 :         fname = "_utrace_syscall_nr";
     585                 :            :       }
     586                 :            :       // If we're in a syscal return probe, we can't really access
     587                 :            :       // $syscall.  So, similar to what
     588                 :            :       // dwarf_var_expanding_visitor::visit_target_symbol() does,
     589                 :            :       // we'll create an syscall entry probe to cache $syscall, then
     590                 :            :       // we'll access the cached value in the syscall return probe.
     591                 :            :       else {
     592         [ +  - ]:          1 :         visit_target_symbol_cached (e);
     593                 :            : 
     594                 :            :         // Remember that we've seen a target variable.
     595                 :          1 :         target_symbol_seen = true;
     596                 :          4 :         return;
     597                 :            :       }
     598                 :            :     }
     599                 :            :   else
     600                 :            :     {
     601 [ #  # ][ #  # ]:          0 :       throw semantic_error (_("unknown target variable"), e->tok);
     602                 :            :     }
     603                 :            : 
     604                 :            :   // Remember that we've seen a target variable.
     605                 :          3 :   target_symbol_seen = true;
     606                 :            : 
     607                 :            :   // We're going to substitute a synthesized '_utrace_syscall_nr'
     608                 :            :   // function call for the '$syscall' reference.
     609 [ +  - ][ +  - ]:          3 :   functioncall* n = new functioncall;
     610                 :          3 :   n->tok = e->tok;
     611         [ +  - ]:          3 :   n->function = fname;
     612                 :          3 :   n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session
     613                 :            : 
     614 [ +  - ][ +  - ]:         11 :   provide (n);
                 [ +  + ]
     615                 :            : }
     616                 :            : 
     617                 :            : void
     618                 :         22 : utrace_var_expanding_visitor::visit_target_symbol (target_symbol* e)
     619                 :            : {
     620 [ +  - ][ -  + ]:         22 :   assert(e->name.size() > 0 && e->name[0] == '$');
     621                 :            : 
     622                 :            :   try
     623                 :            :     {
     624 [ +  + ][ +  + ]:         22 :       if (flags != UDPF_SYSCALL && flags != UDPF_SYSCALL_RETURN)
     625                 :          1 :         throw semantic_error (_("only \"process(PATH_OR_PID).syscall\""
     626                 :            :                                 " and \"process(PATH_OR_PID).syscall.return\" probes support target symbols"),
     627 [ +  - ][ +  - ]:          1 :                               e->tok);
     628                 :            : 
     629         [ -  + ]:         21 :       if (e->addressof)
     630 [ #  # ][ #  # ]:          0 :         throw semantic_error(_("cannot take address of utrace variable"), e->tok);
     631                 :            : 
     632 [ +  - ][ +  + ]:         21 :       if (startswith(e->name, "$arg") || e->name == "$$parms")
         [ +  - ][ -  + ]
                 [ +  + ]
     633         [ +  + ]:         10 :         visit_target_symbol_arg(e);
     634 [ +  - ][ +  + ]:         11 :       else if (e->name == "$syscall" || e->name == "$return")
         [ +  - ][ +  - ]
                 [ +  - ]
     635         [ +  + ]:         11 :         visit_target_symbol_context(e);
     636                 :            :       else
     637                 :          0 :         throw semantic_error (_("invalid target symbol for utrace probe,"
     638                 :            :                                 " $syscall, $return, $argN or $$parms expected"),
     639 [ #  # ][ #  # ]:          0 :                               e->tok);
     640                 :            :     }
     641         [ -  + ]:         24 :   catch (const semantic_error &er)
     642                 :            :     {
     643         [ -  + ]:         12 :       e->chain (er);
     644         [ -  + ]:         12 :       provide(e);
     645                 :         22 :       return;
     646                 :            :     }
     647                 :            : }
     648                 :            : 
     649                 :            : 
     650         [ #  # ]:          0 : struct utrace_builder: public derived_probe_builder
     651                 :            : {
     652                 :       1218 :   utrace_builder() {}
     653                 :         19 :   virtual void build(systemtap_session & sess,
     654                 :            :                      probe * base,
     655                 :            :                      probe_point * location,
     656                 :            :                      literal_map_t const & parameters,
     657                 :            :                      vector<derived_probe *> & finished_results)
     658                 :            :   {
     659 [ +  - ][ +  - ]:         19 :     string path, path_tgt;
     660                 :            :     int64_t pid;
     661                 :            : 
     662         [ +  - ]:         19 :     bool has_path = get_param (parameters, TOK_PROCESS, path);
     663         [ +  - ]:         19 :     bool has_pid = get_param (parameters, TOK_PROCESS, pid);
     664                 :         19 :     enum utrace_derived_probe_flags flags = UDPF_NONE;
     665                 :            : 
     666 [ +  - ][ -  + ]:         19 :     if (has_null_param (parameters, TOK_THREAD))
     667                 :            :       {
     668 [ #  # ][ #  # ]:          0 :         if (has_null_param (parameters, TOK_BEGIN))
     669                 :          0 :           flags = UDPF_THREAD_BEGIN;
     670 [ #  # ][ #  # ]:          0 :         else if (has_null_param (parameters, TOK_END))
     671                 :          0 :           flags = UDPF_THREAD_END;
     672                 :            :       }
     673 [ +  - ][ +  + ]:         19 :     else if (has_null_param (parameters, TOK_SYSCALL))
     674                 :            :       {
     675         [ -  + ]:         14 :         if (sess.runtime_usermode_p())
     676 [ #  # ][ #  # ]:          0 :           throw semantic_error (_("process.syscall probes not available with the dyninst runtime"));
     677                 :            : 
     678 [ +  - ][ +  + ]:         14 :         if (has_null_param (parameters, TOK_RETURN))
     679                 :          4 :           flags = UDPF_SYSCALL_RETURN;
     680                 :            :         else
     681                 :         10 :           flags = UDPF_SYSCALL;
     682                 :            :       }
     683 [ +  - ][ +  + ]:          5 :     else if (has_null_param (parameters, TOK_BEGIN))
     684                 :          4 :       flags = UDPF_BEGIN;
     685 [ +  - ][ +  - ]:          1 :     else if (has_null_param (parameters, TOK_END))
     686                 :          1 :       flags = UDPF_END;
     687                 :            : 
     688                 :            :     // If we didn't get a path or pid, this means to probe everything.
     689                 :            :     // Convert this to a pid-based probe.
     690 [ +  + ][ +  + ]:         19 :     if (! has_path && ! has_pid)
     691                 :            :       {
     692                 :          5 :         has_path = false;
     693         [ +  - ]:          5 :         path.clear();
     694                 :          5 :         has_pid = true;
     695                 :          5 :         pid = 0;
     696                 :            :       }
     697         [ +  + ]:         14 :     else if (has_path)
     698                 :            :       {
     699 [ +  - ][ +  - ]:         13 :         path = find_executable (path, sess.sysroot, sess.sysenv);
         [ +  - ][ +  - ]
                 [ +  - ]
     700         [ +  - ]:         13 :         sess.unwindsym_modules.insert (path);
     701 [ +  - ][ +  - ]:         13 :         path_tgt = path_remove_sysroot(sess, path);
                 [ +  - ]
     702                 :            :       }
     703         [ +  - ]:          1 :     else if (has_pid)
     704                 :            :       {
     705                 :            :         // We can't probe 'init' (pid 1).  XXX: where does this limitation come from?
     706         [ +  - ]:          1 :         if (pid < 2)
     707                 :          1 :           throw semantic_error (_("process pid must be greater than 1"),
     708 [ +  - ][ +  - ]:          1 :                                 location->components.front()->tok);
                 [ +  - ]
     709                 :            : 
     710                 :            :         // XXX: could we use /proc/$pid/exe in unwindsym_modules and elsewhere?
     711                 :            :       }
     712                 :            : 
     713                 :            :     finished_results.push_back(new utrace_derived_probe(sess, base, location,
     714                 :            :                                                         has_path, path_tgt, pid,
     715 [ +  - ][ +  - ]:         19 :                                                         flags));
         [ +  - ][ +  - ]
                 [ +  - ]
     716                 :         18 :   }
     717                 :            : };
     718                 :            : 
     719                 :            : 
     720                 :            : void
     721                 :         18 : utrace_derived_probe_group::enroll (utrace_derived_probe* p)
     722                 :            : {
     723         [ +  + ]:         18 :   if (p->has_path)
     724                 :         13 :     probes_by_path[p->path].push_back(p);
     725                 :            :   else
     726                 :          5 :     probes_by_pid[p->pid].push_back(p);
     727                 :         18 :   num_probes++;
     728                 :         18 :   flags_seen[p->flags] = true;
     729                 :            : 
     730                 :            :   // XXX: multiple exec probes (for instance) for the same path (or
     731                 :            :   // pid) should all share a utrace report function, and have their
     732                 :            :   // handlers executed sequentially.
     733                 :         18 : }
     734                 :            : 
     735                 :            : 
     736                 :            : void
     737                 :          4 : utrace_derived_probe_group::emit_linux_probe_decl (systemtap_session& s,
     738                 :            :                                                    utrace_derived_probe *p)
     739                 :            : {
     740                 :          4 :   s.op->newline() << "{";
     741                 :          4 :   s.op->line() << " .tgt={";
     742                 :          4 :   s.op->line() << " .purpose=\"lifecycle tracking\",";
     743         [ -  + ]:          4 :   if (p->has_path)
     744                 :            :     {
     745                 :          0 :       s.op->line() << " .procname=\"" << p->path << "\",";
     746                 :          0 :       s.op->line() << " .pid=0,";
     747                 :            :     }
     748                 :            :   else
     749                 :            :     {
     750                 :          4 :       s.op->line() << " .procname=NULL,";
     751                 :          4 :       s.op->line() << " .pid=" << p->pid << ",";
     752                 :            :     }
     753                 :            : 
     754                 :          4 :   s.op->line() << " .callback=&_stp_utrace_probe_cb,";
     755                 :          4 :   s.op->line() << " .mmap_callback=NULL,";
     756                 :          4 :   s.op->line() << " .munmap_callback=NULL,";
     757                 :          4 :   s.op->line() << " .mprotect_callback=NULL,";
     758                 :          4 :   s.op->line() << " },";
     759 [ +  - ][ +  - ]:          4 :   s.op->line() << " .probe=" << common_probe_init (p) << ",";
     760                 :            : 
     761                 :            :   // Handle flags
     762   [ +  -  -  -  :          4 :   switch (p->flags)
             +  +  -  - ]
     763                 :            :     {
     764                 :            :     // Notice that we'll just call the probe directly when we get
     765                 :            :     // notified, since the task_finder layer stops the thread for us.
     766                 :            :     case UDPF_BEGIN:                            // process begin
     767                 :          1 :       s.op->line() << " .flags=(UDPF_BEGIN),";
     768                 :          1 :       break;
     769                 :            :     case UDPF_THREAD_BEGIN:                     // thread begin
     770                 :          0 :       s.op->line() << " .flags=(UDPF_THREAD_BEGIN),";
     771                 :          0 :       break;
     772                 :            : 
     773                 :            :     // Notice we're not setting up a .ops/.report_death handler for
     774                 :            :     // either UDPF_END or UDPF_THREAD_END.  Instead, we'll just call
     775                 :            :     // the probe directly when we get notified.
     776                 :            :     case UDPF_END:                              // process end
     777                 :          0 :       s.op->line() << " .flags=(UDPF_END),";
     778                 :          0 :       break;
     779                 :            :     case UDPF_THREAD_END:                       // thread end
     780                 :          0 :       s.op->line() << " .flags=(UDPF_THREAD_END),";
     781                 :          0 :       break;
     782                 :            : 
     783                 :            :     // For UDPF_SYSCALL/UDPF_SYSCALL_RETURN probes, the .report_death
     784                 :            :     // handler isn't strictly necessary.  However, it helps to keep
     785                 :            :     // our attaches/detaches symmetrical.  Since the task_finder layer
     786                 :            :     // stops the thread, that works around bug 6841.
     787                 :            :     case UDPF_SYSCALL:
     788                 :          2 :       s.op->line() << " .flags=(UDPF_SYSCALL),";
     789                 :          2 :       s.op->line() << " .ops={ .report_syscall_entry=stap_utrace_probe_syscall,  .report_death=stap_utrace_task_finder_report_death },";
     790                 :          2 :       s.op->line() << " .events=(UTRACE_EVENT(SYSCALL_ENTRY)|UTRACE_EVENT(DEATH)),";
     791                 :          2 :       break;
     792                 :            :     case UDPF_SYSCALL_RETURN:
     793                 :          1 :       s.op->line() << " .flags=(UDPF_SYSCALL_RETURN),";
     794                 :          1 :       s.op->line() << " .ops={ .report_syscall_exit=stap_utrace_probe_syscall, .report_death=stap_utrace_task_finder_report_death },";
     795                 :          1 :       s.op->line() << " .events=(UTRACE_EVENT(SYSCALL_EXIT)|UTRACE_EVENT(DEATH)),";
     796                 :          1 :       break;
     797                 :            : 
     798                 :            :     case UDPF_NONE:
     799                 :          0 :       s.op->line() << " .flags=(UDPF_NONE),";
     800                 :          0 :       s.op->line() << " .ops={ },";
     801                 :          0 :       s.op->line() << " .events=0,";
     802                 :          0 :       break;
     803                 :            :     default:
     804 [ #  # ][ #  # ]:          0 :       throw semantic_error ("bad utrace probe flag");
     805                 :            :       break;
     806                 :            :     }
     807                 :          4 :   s.op->line() << " .engine_attached=0,";
     808                 :          4 :   s.op->line() << " },";
     809                 :          4 : }
     810                 :            : 
     811                 :            : 
     812                 :            : void
     813                 :          2 : utrace_derived_probe_group::emit_module_linux_decls (systemtap_session& s)
     814                 :            : {
     815 [ +  - ][ -  + ]:          2 :   if (probes_by_path.empty() && probes_by_pid.empty())
                 [ -  + ]
     816                 :          2 :     return;
     817                 :            : 
     818                 :          2 :   s.op->newline();
     819                 :          2 :   s.op->newline() << "/* ---- utrace probes ---- */";
     820                 :            : 
     821                 :          2 :   s.op->newline() << "enum utrace_derived_probe_flags {";
     822                 :          2 :   s.op->indent(1);
     823                 :          2 :   s.op->newline() << "UDPF_NONE,";
     824                 :          2 :   s.op->newline() << "UDPF_BEGIN,";
     825                 :          2 :   s.op->newline() << "UDPF_END,";
     826                 :          2 :   s.op->newline() << "UDPF_THREAD_BEGIN,";
     827                 :          2 :   s.op->newline() << "UDPF_THREAD_END,";
     828                 :          2 :   s.op->newline() << "UDPF_SYSCALL,";
     829                 :          2 :   s.op->newline() << "UDPF_SYSCALL_RETURN,";
     830                 :          2 :   s.op->newline() << "UDPF_NFLAGS";
     831                 :          2 :   s.op->newline(-1) << "};";
     832                 :            : 
     833                 :          2 :   s.op->newline() << "struct stap_utrace_probe {";
     834                 :          2 :   s.op->indent(1);
     835                 :          2 :   s.op->newline() << "struct stap_task_finder_target tgt;";
     836                 :          2 :   s.op->newline() << "const struct stap_probe * const probe;";
     837                 :          2 :   s.op->newline() << "int engine_attached;";
     838                 :          2 :   s.op->newline() << "enum utrace_derived_probe_flags flags;";
     839                 :          2 :   s.op->newline() << "struct utrace_engine_ops ops;";
     840                 :          2 :   s.op->newline() << "unsigned long events;";
     841                 :          2 :   s.op->newline(-1) << "};";
     842                 :            : 
     843                 :            : 
     844                 :            :   // Output handler function for UDPF_BEGIN, UDPF_THREAD_BEGIN,
     845                 :            :   // UDPF_END, and UDPF_THREAD_END
     846 [ +  + ][ +  - ]:          2 :   if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN]
         [ +  - ][ -  + ]
     847                 :          2 :       || flags_seen[UDPF_END] || flags_seen[UDPF_THREAD_END])
     848                 :            :     {
     849                 :          1 :       s.op->newline() << "static void stap_utrace_probe_handler(struct task_struct *tsk, struct stap_utrace_probe *p) {";
     850                 :          1 :       s.op->indent(1);
     851                 :            : 
     852                 :            :       common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "p->probe",
     853 [ +  - ][ +  - ]:          1 :                                      "stp_probe_type_utrace");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     854                 :            : 
     855                 :            :       // call probe function
     856                 :          1 :       s.op->newline() << "(*p->probe->ph) (c);";
     857                 :          1 :       common_probe_entryfn_epilogue (s, true);
     858                 :            : 
     859                 :          1 :       s.op->newline() << "return;";
     860                 :          1 :       s.op->newline(-1) << "}";
     861                 :            :     }
     862                 :            : 
     863                 :            :   // Output handler function for SYSCALL_ENTRY and SYSCALL_EXIT events
     864 [ +  + ][ -  + ]:          2 :   if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN])
     865                 :            :     {
     866                 :          1 :       s.op->newline() << "#ifdef UTRACE_ORIG_VERSION";
     867                 :          1 :       s.op->newline() << "static u32 stap_utrace_probe_syscall(struct utrace_engine *engine, struct task_struct *tsk, struct pt_regs *regs) {";
     868                 :          1 :       s.op->newline() << "#else";
     869                 :          1 :       s.op->newline() << "#if defined(UTRACE_API_VERSION) && (UTRACE_API_VERSION >= 20091216)";
     870                 :          1 :       s.op->newline() << "static u32 stap_utrace_probe_syscall(u32 action, struct utrace_engine *engine, struct pt_regs *regs) {";
     871                 :          1 :       s.op->newline() << "#else";
     872                 :          1 :       s.op->newline() << "static u32 stap_utrace_probe_syscall(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *tsk, struct pt_regs *regs) {";
     873                 :          1 :       s.op->newline() << "#endif";
     874                 :          1 :       s.op->newline() << "#endif";
     875                 :            : 
     876                 :          1 :       s.op->indent(1);
     877                 :          1 :       s.op->newline() << "struct stap_utrace_probe *p = (struct stap_utrace_probe *)engine->data;";
     878                 :            : 
     879                 :            :       common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "p->probe",
     880 [ +  - ][ +  - ]:          1 :                                      "stp_probe_type_utrace_syscall");
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     881                 :          1 :       s.op->newline() << "c->uregs = regs;";
     882                 :          1 :       s.op->newline() << "c->user_mode_p = 1;";
     883                 :            : 
     884                 :            :       // call probe function
     885                 :          1 :       s.op->newline() << "(*p->probe->ph) (c);";
     886                 :          1 :       common_probe_entryfn_epilogue (s, true);
     887                 :            : 
     888                 :          1 :       s.op->newline() << "if ((atomic_read (session_state()) != STAP_SESSION_STARTING) && (atomic_read (session_state()) != STAP_SESSION_RUNNING)) {";
     889                 :          1 :       s.op->indent(1);
     890                 :          1 :       s.op->newline() << "debug_task_finder_detach();";
     891                 :          1 :       s.op->newline() << "return UTRACE_DETACH;";
     892                 :          1 :       s.op->newline(-1) << "}";
     893                 :          1 :       s.op->newline() << "return UTRACE_RESUME;";
     894                 :          1 :       s.op->newline(-1) << "}";
     895                 :            :     }
     896                 :            : 
     897                 :            :   // Output task_finder callback routine that gets called for all
     898                 :            :   // utrace probe types.
     899                 :          2 :   s.op->newline() << "static int _stp_utrace_probe_cb(struct stap_task_finder_target *tgt, struct task_struct *tsk, int register_p, int process_p) {";
     900                 :          2 :   s.op->indent(1);
     901                 :          2 :   s.op->newline() << "int rc = 0;";
     902                 :          2 :   s.op->newline() << "struct stap_utrace_probe *p = container_of(tgt, struct stap_utrace_probe, tgt);";
     903                 :          2 :   s.op->newline() << "struct utrace_engine *engine;";
     904                 :            : 
     905                 :          2 :   s.op->newline() << "if (register_p) {";
     906                 :          2 :   s.op->indent(1);
     907                 :            : 
     908                 :          2 :   s.op->newline() << "switch (p->flags) {";
     909                 :          2 :   s.op->indent(1);
     910                 :            : 
     911                 :            :   // When receiving a UTRACE_EVENT(CLONE) event, we can't call the
     912                 :            :   // begin/thread.begin probe directly.  So, we'll just attach an
     913                 :            :   // engine that waits for the thread to quiesce.  When the thread
     914                 :            :   // quiesces, then call the probe.
     915         [ +  + ]:          2 :   if (flags_seen[UDPF_BEGIN])
     916                 :            :   {
     917                 :          1 :       s.op->newline() << "case UDPF_BEGIN:";
     918                 :          1 :       s.op->indent(1);
     919                 :          1 :       s.op->newline() << "if (process_p) {";
     920                 :          1 :       s.op->indent(1);
     921                 :          1 :       s.op->newline() << "stap_utrace_probe_handler(tsk, p);";
     922                 :          1 :       s.op->newline(-1) << "}";
     923                 :          1 :       s.op->newline() << "break;";
     924                 :          1 :       s.op->indent(-1);
     925                 :            :   }
     926         [ -  + ]:          2 :   if (flags_seen[UDPF_THREAD_BEGIN])
     927                 :            :   {
     928                 :          0 :       s.op->newline() << "case UDPF_THREAD_BEGIN:";
     929                 :          0 :       s.op->indent(1);
     930                 :          0 :       s.op->newline() << "if (! process_p) {";
     931                 :          0 :       s.op->indent(1);
     932                 :          0 :       s.op->newline() << "stap_utrace_probe_handler(tsk, p);";
     933                 :          0 :       s.op->newline(-1) << "}";
     934                 :          0 :       s.op->newline() << "break;";
     935                 :          0 :       s.op->indent(-1);
     936                 :            :   }
     937                 :            : 
     938                 :            :   // For end/thread_end probes, do nothing at registration time.
     939                 :            :   // We'll handle these in the 'register_p == 0' case.
     940 [ +  - ][ -  + ]:          2 :   if (flags_seen[UDPF_END] || flags_seen[UDPF_THREAD_END])
     941                 :            :     {
     942                 :          0 :       s.op->newline() << "case UDPF_END:";
     943                 :          0 :       s.op->newline() << "case UDPF_THREAD_END:";
     944                 :          0 :       s.op->indent(1);
     945                 :          0 :       s.op->newline() << "break;";
     946                 :          0 :       s.op->indent(-1);
     947                 :            :     }
     948                 :            : 
     949                 :            :   // Attach an engine for SYSCALL_ENTRY and SYSCALL_EXIT events.
     950 [ +  + ][ -  + ]:          2 :   if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN])
     951                 :            :     {
     952                 :          1 :       s.op->newline() << "case UDPF_SYSCALL:";
     953                 :          1 :       s.op->newline() << "case UDPF_SYSCALL_RETURN:";
     954                 :          1 :       s.op->indent(1);
     955                 :          1 :       s.op->newline() << "rc = stap_utrace_attach(tsk, &p->ops, p, p->events);";
     956                 :          1 :       s.op->newline() << "if (rc == 0) {";
     957                 :          1 :       s.op->indent(1);
     958                 :          1 :       s.op->newline() << "p->engine_attached = 1;";
     959                 :          1 :       s.op->newline(-1) << "}";
     960                 :          1 :       s.op->newline() << "break;";
     961                 :          1 :       s.op->indent(-1);
     962                 :            :     }
     963                 :            : 
     964                 :          2 :   s.op->newline() << "default:";
     965                 :          2 :   s.op->indent(1);
     966                 :          2 :   s.op->newline() << "_stp_error(\"unhandled flag value %d at %s:%d\", p->flags, __FUNCTION__, __LINE__);";
     967                 :          2 :   s.op->newline() << "break;";
     968                 :          2 :   s.op->indent(-1);
     969                 :          2 :   s.op->newline(-1) << "}";
     970                 :          2 :   s.op->newline(-1) << "}";
     971                 :            : 
     972                 :            :   // Since this engine could be attached to multiple threads, don't
     973                 :            :   // call stap_utrace_detach_ops() here, only call
     974                 :            :   // stap_utrace_detach() as necessary.
     975                 :          2 :   s.op->newline() << "else {";
     976                 :          2 :   s.op->indent(1);
     977                 :          2 :   s.op->newline() << "switch (p->flags) {";
     978                 :          2 :   s.op->indent(1);
     979                 :            :   // For end probes, go ahead and call the probe directly.
     980         [ -  + ]:          2 :   if (flags_seen[UDPF_END])
     981                 :            :     {
     982                 :          0 :       s.op->newline() << "case UDPF_END:";
     983                 :          0 :       s.op->indent(1);
     984                 :          0 :       s.op->newline() << "if (process_p) {";
     985                 :          0 :       s.op->indent(1);
     986                 :          0 :       s.op->newline() << "stap_utrace_probe_handler(tsk, p);";
     987                 :          0 :       s.op->newline(-1) << "}";
     988                 :          0 :       s.op->newline() << "break;";
     989                 :          0 :       s.op->indent(-1);
     990                 :            :     }
     991         [ -  + ]:          2 :   if (flags_seen[UDPF_THREAD_END])
     992                 :            :     {
     993                 :          0 :       s.op->newline() << "case UDPF_THREAD_END:";
     994                 :          0 :       s.op->indent(1);
     995                 :          0 :       s.op->newline() << "if (! process_p) {";
     996                 :          0 :       s.op->indent(1);
     997                 :          0 :       s.op->newline() << "stap_utrace_probe_handler(tsk, p);";
     998                 :          0 :       s.op->newline(-1) << "}";
     999                 :          0 :       s.op->newline() << "break;";
    1000                 :          0 :       s.op->indent(-1);
    1001                 :            :     }
    1002                 :            : 
    1003                 :            :   // For begin/thread_begin probes, we don't need to do anything.
    1004 [ +  + ][ -  + ]:          2 :   if (flags_seen[UDPF_BEGIN] || flags_seen[UDPF_THREAD_BEGIN])
    1005                 :            :   {
    1006                 :          1 :       s.op->newline() << "case UDPF_BEGIN:";
    1007                 :          1 :       s.op->newline() << "case UDPF_THREAD_BEGIN:";
    1008                 :          1 :       s.op->indent(1);
    1009                 :          1 :       s.op->newline() << "break;";
    1010                 :          1 :       s.op->indent(-1);
    1011                 :            :   }
    1012                 :            : 
    1013 [ +  + ][ -  + ]:          2 :   if (flags_seen[UDPF_SYSCALL] || flags_seen[UDPF_SYSCALL_RETURN])
    1014                 :            :     {
    1015                 :          1 :       s.op->newline() << "case UDPF_SYSCALL:";
    1016                 :          1 :       s.op->newline() << "case UDPF_SYSCALL_RETURN:";
    1017                 :          1 :       s.op->indent(1);
    1018                 :          1 :       s.op->newline() << "stap_utrace_detach(tsk, &p->ops);";
    1019                 :          1 :       s.op->newline() << "break;";
    1020                 :          1 :       s.op->indent(-1);
    1021                 :            :     }
    1022                 :            : 
    1023                 :          2 :   s.op->newline() << "default:";
    1024                 :          2 :   s.op->indent(1);
    1025                 :          2 :   s.op->newline() << "_stp_error(\"unhandled flag value %d at %s:%d\", p->flags, __FUNCTION__, __LINE__);";
    1026                 :          2 :   s.op->newline() << "break;";
    1027                 :          2 :   s.op->indent(-1);
    1028                 :          2 :   s.op->newline(-1) << "}";
    1029                 :          2 :   s.op->newline(-1) << "}";
    1030                 :          2 :   s.op->newline() << "return rc;";
    1031                 :          2 :   s.op->newline(-1) << "}";
    1032                 :            : 
    1033                 :          2 :   s.op->newline() << "static struct stap_utrace_probe stap_utrace_probes[] = {";
    1034                 :          2 :   s.op->indent(1);
    1035                 :            : 
    1036                 :            :   // Set up 'process(PATH)' probes
    1037         [ -  + ]:          2 :   if (! probes_by_path.empty())
    1038                 :            :     {
    1039 [ #  # ][ #  # ]:          0 :       for (p_b_path_iterator it = probes_by_path.begin();
    1040         [ #  # ]:          0 :            it != probes_by_path.end(); it++)
    1041                 :            :         {
    1042 [ #  # ][ #  # ]:          0 :           for (unsigned i = 0; i < it->second.size(); i++)
    1043                 :            :             {
    1044         [ #  # ]:          0 :               utrace_derived_probe *p = it->second[i];
    1045         [ #  # ]:          0 :               emit_linux_probe_decl(s, p);
    1046                 :            :             }
    1047                 :            :         }
    1048                 :            :     }
    1049                 :            : 
    1050                 :            :   // Set up 'process(PID)' probes
    1051         [ +  - ]:          2 :   if (! probes_by_pid.empty())
    1052                 :            :     {
    1053 [ +  - ][ +  + ]:          8 :       for (p_b_pid_iterator it = probes_by_pid.begin();
    1054         [ +  - ]:          4 :            it != probes_by_pid.end(); it++)
    1055                 :            :         {
    1056 [ +  - ][ +  + ]:          6 :           for (unsigned i = 0; i < it->second.size(); i++)
    1057                 :            :             {
    1058         [ +  - ]:          4 :               utrace_derived_probe *p = it->second[i];
    1059         [ +  - ]:          4 :               emit_linux_probe_decl(s, p);
    1060                 :            :             }
    1061                 :            :         }
    1062                 :            :     }
    1063                 :          2 :   s.op->newline(-1) << "};";
    1064                 :            : }
    1065                 :            : 
    1066                 :            : 
    1067                 :            : void
    1068                 :          0 : utrace_derived_probe_group::emit_dyninst_probe_decl (systemtap_session& s,
    1069                 :            :                                                      const string& path,
    1070                 :            :                                                      utrace_derived_probe *p)
    1071                 :            : {
    1072         [ #  # ]:          0 :   string flags_str;
    1073                 :            : 
    1074                 :            :   // Handle flags
    1075   [ #  #  #  #  :          0 :   switch (p->flags)
                      # ]
    1076                 :            :     {
    1077                 :            :     case UDPF_BEGIN:    // process begin
    1078         [ #  # ]:          0 :       flags_str = "STAPDYN_PROBE_FLAG_PROC_BEGIN";
    1079                 :          0 :       break;
    1080                 :            :     case UDPF_THREAD_BEGIN:     // thread begin
    1081         [ #  # ]:          0 :       flags_str = "STAPDYN_PROBE_FLAG_THREAD_BEGIN";
    1082                 :          0 :       break;
    1083                 :            :     case UDPF_END:              // process end
    1084         [ #  # ]:          0 :       flags_str = "STAPDYN_PROBE_FLAG_PROC_END";
    1085                 :          0 :       break;
    1086                 :            :     case UDPF_THREAD_END:       // thread end
    1087         [ #  # ]:          0 :       flags_str = "STAPDYN_PROBE_FLAG_THREAD_END";
    1088                 :          0 :       break;
    1089                 :            : 
    1090                 :            :       // FIXME: No handling of syscall probes for dyninst yet.
    1091                 :            : #if 0
    1092                 :            :     case UDPF_SYSCALL:
    1093                 :            :       break;
    1094                 :            :     case UDPF_SYSCALL_RETURN:
    1095                 :            :       break;
    1096                 :            : 
    1097                 :            :     case UDPF_NONE:
    1098                 :            :       s.op->line() << " .flags=(UDPF_NONE),";
    1099                 :            :       s.op->line() << " .ops={ },";
    1100                 :            :       s.op->line() << " .events=0,";
    1101                 :            :       break;
    1102                 :            : #endif
    1103                 :            :     default:
    1104 [ #  # ][ #  # ]:          0 :       throw semantic_error ("bad utrace probe flag");
    1105                 :            :       break;
    1106                 :            :     }
    1107                 :            : 
    1108         [ #  # ]:          0 :   if (p->has_path)
    1109 [ #  # ][ #  # ]:          0 :     dynprobe_add_utrace_path(s, path, flags_str, common_probe_init(p));
         [ #  # ][ #  # ]
                 [ #  # ]
    1110                 :            :   else
    1111 [ #  # ][ #  # ]:          0 :     dynprobe_add_utrace_pid(s, p->pid, flags_str, common_probe_init(p));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
    1112                 :          0 : }
    1113                 :            : 
    1114                 :            : void
    1115                 :          0 : utrace_derived_probe_group::emit_module_dyninst_decls (systemtap_session& s)
    1116                 :            : {
    1117 [ #  # ][ #  # ]:          0 :   if (probes_by_path.empty() && probes_by_pid.empty())
                 [ #  # ]
    1118                 :          0 :     return;
    1119                 :            : 
    1120                 :          0 :   s.op->newline();
    1121                 :          0 :   s.op->newline() << "/* ---- dyninst utrace probes ---- */";
    1122                 :          0 :   s.op->newline() << "#include \"dyninst/uprobes.h\"";
    1123                 :          0 :   s.op->newline() << "#define STAPDYN_UTRACE_PROBES";
    1124                 :            : 
    1125                 :            :   // Let the dynprobe_derived_probe_group handle outputting targets
    1126                 :            :   // and probes. This allows us to merge different types of probes.
    1127                 :          0 :   s.op->newline() << "static struct stapdu_probe stapdu_probes[];";
    1128                 :            : 
    1129                 :            :   // Set up 'process(PATH)' probes
    1130         [ #  # ]:          0 :   if (! probes_by_path.empty())
    1131                 :            :     {
    1132 [ #  # ][ #  # ]:          0 :       for (p_b_path_iterator it = probes_by_path.begin();
    1133         [ #  # ]:          0 :            it != probes_by_path.end(); it++)
    1134                 :            :         {
    1135 [ #  # ][ #  # ]:          0 :           for (unsigned i = 0; i < it->second.size(); i++)
    1136                 :            :             {
    1137         [ #  # ]:          0 :               utrace_derived_probe *p = it->second[i];
    1138 [ #  # ][ #  # ]:          0 :               emit_dyninst_probe_decl(s, it->first, p);
    1139                 :            :             }
    1140                 :            :         }
    1141                 :            :     }
    1142                 :            :   // Set up 'process(PID)' probes
    1143         [ #  # ]:          0 :   if (! probes_by_pid.empty())
    1144                 :            :     {
    1145 [ #  # ][ #  # ]:          0 :       for (p_b_pid_iterator it = probes_by_pid.begin();
    1146         [ #  # ]:          0 :            it != probes_by_pid.end(); it++)
    1147                 :            :         {
    1148 [ #  # ][ #  # ]:          0 :           for (unsigned i = 0; i < it->second.size(); i++)
    1149                 :            :             {
    1150         [ #  # ]:          0 :               utrace_derived_probe *p = it->second[i];
    1151 [ #  # ][ #  # ]:          0 :               emit_dyninst_probe_decl(s, "", p);
                 [ #  # ]
    1152                 :            :             }
    1153                 :            :         }
    1154                 :            :     }
    1155                 :            : 
    1156                 :            :   // loc2c-generated code assumes pt_regs are available, so use this to make
    1157                 :            :   // sure we always have *something* for it to dereference...
    1158                 :          0 :   s.op->newline() << "static struct pt_regs stapdu_dummy_uregs;";
    1159                 :            : 
    1160                 :            :   // Write the probe handler.
    1161                 :            :   // NB: not static, so dyninst can find it
    1162                 :          0 :   s.op->newline() << "int enter_dyninst_utrace_probe "
    1163                 :          0 :                   << "(uint64_t index, struct pt_regs *regs) {";
    1164                 :          0 :   s.op->newline(1) << "struct stapdu_probe *sup = &stapdu_probes[index];";
    1165                 :            : 
    1166                 :            :   common_probe_entryfn_prologue (s, "STAP_SESSION_RUNNING", "sup->probe",
    1167 [ #  # ][ #  # ]:          0 :                                  "stp_probe_type_utrace");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
    1168                 :          0 :   s.op->newline() << "c->uregs = regs ?: &stapdu_dummy_uregs;";
    1169                 :          0 :   s.op->newline() << "c->user_mode_p = 1;";
    1170                 :            :   // XXX: once we have regs, check how dyninst sets the IP
    1171                 :            :   // XXX: the way that dyninst rewrites stuff is probably going to be
    1172                 :            :   // ...  very confusing to our backtracer (at least if we stay in process)
    1173                 :          0 :   s.op->newline() << "(*sup->probe->ph) (c);";
    1174                 :          0 :   common_probe_entryfn_epilogue (s, true);
    1175                 :          0 :   s.op->newline() << "return 0;";
    1176                 :          0 :   s.op->newline(-1) << "}";
    1177                 :          0 :   s.op->assert_0_indent();
    1178                 :            : }
    1179                 :            : 
    1180                 :            : 
    1181                 :            : void
    1182                 :          2 : utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
    1183                 :            : {
    1184         [ -  + ]:          2 :   if (s.runtime_usermode_p())
    1185                 :          0 :     emit_module_dyninst_decls (s);
    1186                 :            :   else
    1187                 :          2 :     emit_module_linux_decls (s);
    1188                 :          2 : }
    1189                 :            : 
    1190                 :            : 
    1191                 :            : void
    1192                 :          2 : utrace_derived_probe_group::emit_module_linux_init (systemtap_session& s)
    1193                 :            : {
    1194 [ +  - ][ -  + ]:          2 :   if (probes_by_path.empty() && probes_by_pid.empty())
                 [ -  + ]
    1195                 :          2 :     return;
    1196                 :            : 
    1197                 :          2 :   s.op->newline() << "/* ---- utrace probes ---- */";
    1198                 :          2 :   s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_utrace_probes); i++) {";
    1199                 :          2 :   s.op->newline(1) << "struct stap_utrace_probe *p = &stap_utrace_probes[i];";
    1200                 :          2 :   s.op->newline() << "probe_point = p->probe->pp;"; // for error messages
    1201                 :          2 :   s.op->newline() << "rc = stap_register_task_finder_target(&p->tgt);";
    1202                 :            : 
    1203                 :            :   // NB: if (rc), there is no need (XXX: nor any way) to clean up any
    1204                 :            :   // finders already registered, since mere registration does not
    1205                 :            :   // cause any utrace or memory allocation actions.  That happens only
    1206                 :            :   // later, once the task finder engine starts running.  So, for a
    1207                 :            :   // partial initialization requiring unwind, we need do nothing.
    1208                 :          2 :   s.op->newline() << "if (rc) break;";
    1209                 :            : 
    1210                 :          2 :   s.op->newline(-1) << "}";
    1211                 :            : }
    1212                 :            : 
    1213                 :            : 
    1214                 :            : void
    1215                 :          0 : utrace_derived_probe_group::emit_module_dyninst_init (systemtap_session& s)
    1216                 :            : {
    1217 [ #  # ][ #  # ]:          0 :   if (probes_by_path.empty() && probes_by_pid.empty())
                 [ #  # ]
    1218                 :          0 :     return;
    1219                 :            : 
    1220                 :            :   /* stapdyn handles the dirty work via dyninst */
    1221                 :          0 :   s.op->newline() << "/* ---- dyninst utrace probes ---- */";
    1222                 :          0 :   s.op->newline() << "/* this section left intentionally blank */";
    1223                 :            : }
    1224                 :            : 
    1225                 :            : 
    1226                 :            : void
    1227                 :          2 : utrace_derived_probe_group::emit_module_init (systemtap_session& s)
    1228                 :            : {
    1229         [ -  + ]:          2 :   if (s.runtime_usermode_p())
    1230                 :          0 :     emit_module_dyninst_init (s);
    1231                 :            :   else
    1232                 :          2 :     emit_module_linux_init(s);
    1233                 :          2 : }
    1234                 :            : 
    1235                 :            : 
    1236                 :            : void
    1237                 :          4 : utrace_derived_probe_group::emit_module_linux_exit (systemtap_session& s)
    1238                 :            : {
    1239 [ +  - ][ -  + ]:          8 :   if (probes_by_path.empty() && probes_by_pid.empty()) return;
                 [ -  + ]
    1240                 :            : 
    1241                 :          4 :   s.op->newline();
    1242                 :          4 :   s.op->newline() << "/* ---- utrace probes ---- */";
    1243                 :          4 :   s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_utrace_probes); i++) {";
    1244                 :          4 :   s.op->newline(1) << "struct stap_utrace_probe *p = &stap_utrace_probes[i];";
    1245                 :            : 
    1246                 :          4 :   s.op->newline() << "if (p->engine_attached) {";
    1247                 :          4 :   s.op->newline(1) << "stap_utrace_detach_ops(&p->ops);";
    1248                 :            : 
    1249                 :          4 :   s.op->newline(-1) << "}";
    1250                 :          4 :   s.op->newline(-1) << "}";
    1251                 :            : }
    1252                 :            : 
    1253                 :            : 
    1254                 :            : void
    1255                 :          0 : utrace_derived_probe_group::emit_module_dyninst_exit (systemtap_session& s)
    1256                 :            : {
    1257 [ #  # ][ #  # ]:          0 :   if (probes_by_path.empty() && probes_by_pid.empty())
                 [ #  # ]
    1258                 :          0 :     return;
    1259                 :            : 
    1260                 :            :   /* stapdyn handles the dirty work via dyninst */
    1261                 :          0 :   s.op->newline() << "/* ---- dyninst utrace probes ---- */";
    1262                 :          0 :   s.op->newline() << "/* this section left intentionally blank */";
    1263                 :            : }
    1264                 :            : 
    1265                 :            : 
    1266                 :            : void
    1267                 :          4 : utrace_derived_probe_group::emit_module_exit (systemtap_session& s)
    1268                 :            : {
    1269         [ -  + ]:          4 :   if (s.runtime_usermode_p())
    1270                 :          0 :     emit_module_dyninst_exit (s);
    1271                 :            :   else
    1272                 :          4 :     emit_module_linux_exit(s);
    1273                 :          4 : }
    1274                 :            : 
    1275                 :            : 
    1276                 :            : void
    1277                 :       1218 : register_tapset_utrace(systemtap_session& s)
    1278                 :            : {
    1279                 :       1218 :   match_node* root = s.pattern_root;
    1280         [ +  - ]:       1218 :   derived_probe_builder *builder = new utrace_builder();
    1281                 :            : 
    1282         [ +  - ]:       1218 :   vector<match_node*> roots;
    1283 [ +  - ][ +  - ]:       1218 :   roots.push_back(root->bind(TOK_PROCESS));
    1284 [ +  - ][ +  - ]:       1218 :   roots.push_back(root->bind_str(TOK_PROCESS));
    1285 [ +  - ][ +  - ]:       1218 :   roots.push_back(root->bind_num(TOK_PROCESS));
    1286                 :            : 
    1287         [ +  + ]:       4872 :   for (unsigned i = 0; i < roots.size(); ++i)
    1288                 :            :     {
    1289                 :       3654 :       roots[i]->bind(TOK_BEGIN)
    1290                 :            :         ->bind_privilege(pr_all)
    1291 [ +  - ][ +  - ]:       3654 :         ->bind(builder);
                 [ +  - ]
    1292                 :       3654 :       roots[i]->bind(TOK_END)
    1293                 :            :         ->bind_privilege(pr_all)
    1294 [ +  - ][ +  - ]:       3654 :         ->bind(builder);
                 [ +  - ]
    1295                 :       3654 :       roots[i]->bind(TOK_THREAD)->bind(TOK_BEGIN)
    1296                 :            :         ->bind_privilege(pr_all)
    1297 [ +  - ][ +  - ]:       3654 :         ->bind(builder);
         [ +  - ][ +  - ]
    1298                 :       3654 :       roots[i]->bind(TOK_THREAD)->bind(TOK_END)
    1299                 :            :         ->bind_privilege(pr_all)
    1300 [ +  - ][ +  - ]:       3654 :         ->bind(builder);
         [ +  - ][ +  - ]
    1301                 :       3654 :       roots[i]->bind(TOK_SYSCALL)
    1302                 :            :         ->bind_privilege(pr_all)
    1303 [ +  - ][ +  - ]:       3654 :         ->bind(builder);
                 [ +  - ]
    1304                 :       3654 :       roots[i]->bind(TOK_SYSCALL)->bind(TOK_RETURN)
    1305                 :            :         ->bind_privilege(pr_all)
    1306 [ +  - ][ +  - ]:       3654 :         ->bind(builder);
         [ +  - ][ +  - ]
    1307         [ +  - ]:       1218 :     }
    1308 [ +  - ][ +  - ]:       8460 : }
    1309                 :            : 
    1310                 :            : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */

Generated by: LCOV version 1.9