LCOV - code coverage report
Current view: top level - mnt/wasteland/wcohen/systemtap_write/systemtap - main.cxx (source / functions) Hit Total Coverage
Test: stap.info Lines: 486 557 87.3 %
Date: 2013-03-08 Functions: 10 11 90.9 %
Branches: 774 1494 51.8 %

           Branch data     Line data    Source code
       1                 :            : // systemtap translator/driver
       2                 :            : // Copyright (C) 2005-2013 Red Hat Inc.
       3                 :            : // Copyright (C) 2005 IBM Corp.
       4                 :            : // Copyright (C) 2006 Intel Corporation.
       5                 :            : //
       6                 :            : // This file is part of systemtap, and is free software.  You can
       7                 :            : // redistribute it and/or modify it under the terms of the GNU General
       8                 :            : // Public License (GPL); either version 2, or (at your option) any
       9                 :            : // later version.
      10                 :            : 
      11                 :            : #include "config.h"
      12                 :            : #include "staptree.h"
      13                 :            : #include "parse.h"
      14                 :            : #include "elaborate.h"
      15                 :            : #include "translate.h"
      16                 :            : #include "buildrun.h"
      17                 :            : #include "session.h"
      18                 :            : #include "hash.h"
      19                 :            : #include "cache.h"
      20                 :            : #include "util.h"
      21                 :            : #include "coveragedb.h"
      22                 :            : #include "rpm_finder.h"
      23                 :            : #include "task_finder.h"
      24                 :            : #include "csclient.h"
      25                 :            : #include "remote.h"
      26                 :            : #include "tapsets.h"
      27                 :            : #include "setupdwfl.h"
      28                 :            : 
      29                 :            : #include <libintl.h>
      30                 :            : #include <locale.h>
      31                 :            : 
      32                 :            : #include "stap-probe.h"
      33                 :            : 
      34                 :            : #include <cstdlib>
      35                 :            : 
      36                 :            : extern "C" {
      37                 :            : #include <glob.h>
      38                 :            : #include <unistd.h>
      39                 :            : #include <signal.h>
      40                 :            : #include <sys/utsname.h>
      41                 :            : #include <sys/times.h>
      42                 :            : #include <sys/time.h>
      43                 :            : #include <sys/stat.h>
      44                 :            : #include <time.h>
      45                 :            : #include <unistd.h>
      46                 :            : #include <wordexp.h>
      47                 :            : }
      48                 :            : 
      49                 :            : using namespace std;
      50                 :            : 
      51                 :            : static void
      52                 :       9536 : uniq_list(list<string>& l)
      53                 :            : {
      54         [ +  - ]:       9536 :   set<string> s;
      55         [ +  - ]:       9536 :   list<string>::iterator i = l.begin();
      56 [ +  - ][ +  + ]:      30144 :   while (i != l.end())
      57 [ +  - ][ +  + ]:      20608 :     if (s.insert(*i).second)
      58                 :      16830 :       ++i;
      59                 :            :     else
      60 [ +  - ][ +  - ]:      13314 :       i = l.erase(i);
      61                 :       9536 : }
      62                 :            : 
      63                 :            : static void
      64                 :       1015 : printscript(systemtap_session& s, ostream& o)
      65                 :            : {
      66         [ +  + ]:       1015 :   if (s.listing_mode)
      67                 :            :     {
      68                 :            :       // We go through some heroic measures to produce clean output.
      69                 :            :       // Record the alias and probe pointer as <name, set<derived_probe *> >
      70         [ +  - ]:         62 :       map<string,set<derived_probe *> > probe_list;
      71                 :            : 
      72                 :            :       // Pre-process the probe alias
      73         [ +  + ]:      12271 :       for (unsigned i=0; i<s.probes.size(); i++)
      74                 :            :         {
      75         [ +  - ]:      12209 :           assert_no_interrupts();
      76                 :            : 
      77                 :      12209 :           derived_probe* p = s.probes[i];
      78                 :            :           // NB: p->basest() is not so interesting;
      79                 :            :           // p->almost_basest() doesn't quite work, so ...
      80         [ +  - ]:      12209 :           vector<probe*> chain;
      81         [ +  - ]:      12209 :           p->collect_derivation_chain (chain);
      82         [ +  - ]:      12209 :           probe* second = (chain.size()>1) ? chain[chain.size()-2] : chain[0];
      83                 :            : 
      84         [ -  + ]:      12209 :           if (s.verbose > 5) {
      85 [ #  # ][ #  # ]:          0 :           p->printsig(cerr); cerr << endl;
      86 [ #  # ][ #  # ]:          0 :           cerr << "chain[" << chain.size() << "]:" << endl;
         [ #  # ][ #  # ]
      87         [ #  # ]:          0 :           for (unsigned j=0; j<chain.size(); j++)
      88                 :            :             {
      89 [ #  # ][ #  # ]:          0 :               cerr << "  [" << j << "]: " << endl;
         [ #  # ][ #  # ]
      90 [ #  # ][ #  # ]:          0 :               cerr << "\tlocations[" << chain[j]->locations.size() << "]:" << endl;
         [ #  # ][ #  # ]
      91         [ #  # ]:          0 :               for (unsigned k=0; k<chain[j]->locations.size(); k++)
      92                 :            :                 {
      93 [ #  # ][ #  # ]:          0 :                   cerr << "\t  [" << k << "]: ";
                 [ #  # ]
      94         [ #  # ]:          0 :                   chain[j]->locations[k]->print(cerr);
      95         [ #  # ]:          0 :                   cerr << endl;
      96                 :            :                 }
      97         [ #  # ]:          0 :               const probe_alias *a = chain[j]->get_alias();
      98         [ #  # ]:          0 :               if (a)
      99                 :            :                 {
     100 [ #  # ][ #  # ]:          0 :                   cerr << "\taliases[" << a->alias_names.size() << "]:" << endl;
         [ #  # ][ #  # ]
     101         [ #  # ]:          0 :                   for (unsigned k=0; k<a->alias_names.size(); k++)
     102                 :            :                     {
     103 [ #  # ][ #  # ]:          0 :                       cerr << "\t  [" << k << "]: ";
                 [ #  # ]
     104         [ #  # ]:          0 :                       a->alias_names[k]->print(cerr);
     105         [ #  # ]:          0 :                       cerr << endl;
     106                 :            :                     }
     107                 :            :                 }
     108                 :            :             }
     109                 :            :           }
     110                 :            : 
     111         [ +  - ]:      12209 :           stringstream tmps;
     112                 :            :           // XXX PR14297 make this more accurate wrt complex wildcard expansions
     113         [ +  - ]:      12209 :           const probe_point *a = second->get_alias_loc();
     114         [ +  + ]:      12209 :           if (a)
     115                 :            :             {
     116         [ +  - ]:         81 :               a->print(tmps);
     117                 :            :             }
     118                 :            :           else
     119                 :            :             {
     120         [ -  + ]:      12128 :               assert (second->locations.size() >= 1);
     121         [ +  - ]:      12128 :               second->locations[0]->print(tmps); // XXX: choosing only one location is less arbitrary here than in get_alias_loc(), but still ...
     122                 :            :             }
     123         [ +  - ]:      12209 :           string pp = tmps.str();
     124                 :            : 
     125                 :            :           // Now duplicate-eliminate.  An alias may have expanded to
     126                 :            :           // several actual derived probe points, but we only want to
     127                 :            :           // print the alias head name once.
     128 [ +  - ][ +  - ]:      12209 :           probe_list[pp].insert(p);
     129 [ +  - ][ +  - ]:      12209 :         }
                 [ +  - ]
     130                 :            : 
     131                 :            :       // print probe name and variables if there
     132 [ +  - ][ +  - ]:       5211 :       for (map<string, set<derived_probe *> >::iterator it=probe_list.begin(); it!=probe_list.end(); ++it)
                 [ +  + ]
     133                 :            :         {
     134 [ +  - ][ +  - ]:       5149 :           o << it->first; // probe name or alias
     135                 :            : 
     136                 :            :           // Print the locals and arguments for -L mode only
     137         [ +  + ]:       5149 :           if (s.listing_mode_vars)
     138                 :            :             {
     139         [ +  - ]:       4768 :               map<string,unsigned> var_count; // format <"name:type",count>
     140         [ +  - ]:       4768 :               map<string,unsigned> arg_count;
     141         [ +  - ]:       4768 :               list<string> var_list;
     142         [ +  - ]:       4768 :               list<string> arg_list;
     143                 :            :               // traverse set<derived_probe *> to collect all locals and arguments
     144 [ +  - ][ +  - ]:      16593 :               for (set<derived_probe *>::iterator ix=it->second.begin(); ix!=it->second.end(); ++ix)
         [ +  - ][ +  - ]
                 [ +  + ]
     145                 :            :                 {
     146                 :      11825 :                   derived_probe* p = *ix;
     147                 :            :                   // collect available locals of the probe
     148         [ +  + ]:      11850 :                   for (unsigned j=0; j<p->locals.size(); j++)
     149                 :            :                     {
     150         [ +  - ]:         25 :                       stringstream tmps;
     151                 :         25 :                       vardecl* v = p->locals[j];
     152         [ +  - ]:         25 :                       v->printsig (tmps);
     153 [ +  - ][ +  - ]:         25 :                       var_count[tmps.str()]++;
                 [ +  - ]
     154 [ +  - ][ +  - ]:         25 :                       var_list.push_back(tmps.str());
                 [ +  - ]
     155         [ +  - ]:         25 :                     }
     156                 :            :                   // collect arguments of the probe if there
     157         [ +  - ]:      11825 :                   list<string> arg_set;
     158         [ +  - ]:      11825 :                   p->getargs(arg_set);
     159 [ +  - ][ +  - ]:      32408 :                   for (list<string>::iterator ia=arg_set.begin(); ia!=arg_set.end(); ++ia) {
                 [ +  + ]
     160         [ +  - ]:      20583 :                     arg_count[*ia]++;
     161         [ +  - ]:      20583 :                     arg_list.push_back(*ia);
     162                 :            :                   }
     163         [ +  - ]:      11825 :                 }
     164                 :            : 
     165         [ +  - ]:       4768 :               uniq_list(arg_list);
     166         [ +  - ]:       4768 :               uniq_list(var_list);
     167                 :            : 
     168                 :            :               // print the set-intersection only
     169 [ +  - ][ +  - ]:       4793 :               for (list<string>::iterator ir=var_list.begin(); ir!=var_list.end(); ++ir)
                 [ +  + ]
     170 [ +  - ][ +  - ]:         25 :                 if (var_count.find(*ir)->second == it->second.size()) // print locals
         [ +  - ][ +  - ]
                 [ +  - ]
     171 [ +  - ][ +  - ]:         25 :                   o << " " << *ir;
     172 [ +  - ][ +  - ]:      21573 :               for (list<string>::iterator ir=arg_list.begin(); ir!=arg_list.end(); ++ir)
                 [ +  + ]
     173 [ +  - ][ +  - ]:      16805 :                 if (arg_count.find(*ir)->second == it->second.size()) // print arguments
         [ +  - ][ +  - ]
                 [ +  + ]
     174 [ +  - ][ +  - ]:      14391 :                   o << " " << *ir;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     175                 :            :             }
     176         [ +  - ]:       5149 :           o << endl;
     177         [ +  - ]:         62 :         }
     178                 :            :     }
     179                 :            :   else
     180                 :            :     {
     181         [ +  + ]:        953 :       if (s.embeds.size() > 0)
     182                 :        459 :         o << _("# global embedded code") << endl;
     183         [ +  + ]:       5065 :       for (unsigned i=0; i<s.embeds.size(); i++)
     184                 :            :         {
     185                 :       4112 :           assert_no_interrupts();
     186                 :       4112 :           embeddedcode* ec = s.embeds[i];
     187                 :       4112 :           ec->print (o);
     188                 :       4112 :           o << endl;
     189                 :            :         }
     190                 :            : 
     191         [ +  + ]:        953 :       if (s.globals.size() > 0)
     192                 :        430 :         o << _("# globals") << endl;
     193         [ +  + ]:       4725 :       for (unsigned i=0; i<s.globals.size(); i++)
     194                 :            :         {
     195                 :       3772 :           assert_no_interrupts();
     196                 :       3772 :           vardecl* v = s.globals[i];
     197                 :       3772 :           v->printsig (o);
     198 [ +  + ][ +  + ]:       3772 :           if (s.verbose && v->init)
     199                 :            :             {
     200                 :        216 :               o << " = ";
     201                 :        216 :               v->init->print(o);
     202                 :            :             }
     203                 :       3772 :           o << endl;
     204                 :            :         }
     205                 :            : 
     206         [ +  + ]:        953 :       if (s.functions.size() > 0)
     207                 :        779 :         o << _("# functions") << endl;
     208 [ +  - ][ +  - ]:      20307 :       for (map<string,functiondecl*>::iterator it = s.functions.begin(); it != s.functions.end(); it++)
                 [ +  + ]
     209                 :            :         {
     210         [ +  - ]:      19354 :           assert_no_interrupts();
     211         [ +  - ]:      19354 :           functiondecl* f = it->second;
     212         [ +  - ]:      19354 :           f->printsig (o);
     213         [ +  - ]:      19354 :           o << endl;
     214         [ +  + ]:      19354 :           if (f->locals.size() > 0)
     215 [ +  - ][ +  - ]:       1560 :             o << _("  # locals") << endl;
     216         [ +  + ]:      21629 :           for (unsigned j=0; j<f->locals.size(); j++)
     217                 :            :             {
     218                 :       2275 :               vardecl* v = f->locals[j];
     219         [ +  - ]:       2275 :               o << "  ";
     220         [ +  - ]:       2275 :               v->printsig (o);
     221         [ +  - ]:       2275 :               o << endl;
     222                 :            :             }
     223         [ +  + ]:      19354 :           if (s.verbose)
     224                 :            :             {
     225         [ +  - ]:      18359 :               f->body->print (o);
     226         [ +  - ]:      18359 :               o << endl;
     227                 :            :             }
     228                 :            :         }
     229                 :            : 
     230         [ +  - ]:        953 :       if (s.probes.size() > 0)
     231                 :        953 :         o << _("# probes") << endl;
     232         [ +  + ]:     342736 :       for (unsigned i=0; i<s.probes.size(); i++)
     233                 :            :         {
     234                 :     341783 :           assert_no_interrupts();
     235                 :     341783 :           derived_probe* p = s.probes[i];
     236                 :     341783 :           p->printsig (o);
     237                 :     341783 :           o << endl;
     238         [ +  + ]:     341783 :           if (p->locals.size() > 0)
     239                 :      48816 :             o << _("  # locals") << endl;
     240         [ +  + ]:     451601 :           for (unsigned j=0; j<p->locals.size(); j++)
     241                 :            :             {
     242                 :     109818 :               vardecl* v = p->locals[j];
     243                 :     109818 :               o << "  ";
     244                 :     109818 :               v->printsig (o);
     245                 :     109818 :               o << endl;
     246                 :            :             }
     247         [ +  + ]:     341783 :           if (s.verbose)
     248                 :            :             {
     249                 :      78440 :               p->body->print (o);
     250                 :      78440 :               o << endl;
     251                 :            :             }
     252                 :            :         }
     253                 :            :     }
     254                 :       1015 : }
     255                 :            : 
     256                 :            : 
     257                 :            : int pending_interrupts;
     258                 :            : 
     259                 :            : extern "C"
     260                 :        250 : void handle_interrupt (int sig)
     261                 :            : {
     262                 :            :   // This might be nice, but we don't know our current verbosity...
     263                 :            :   // clog << _F("Received signal %d", sig) << endl << flush;
     264                 :        250 :   kill_stap_spawn(SIGTERM);
     265                 :            : 
     266                 :        250 :   pending_interrupts ++;
     267                 :            :   // Absorb the first two signals.   This used to be one, but when
     268                 :            :   // stap is run under sudo, and then interrupted, sudo relays a
     269                 :            :   // redundant copy of the signal to stap, leading to an unclean shutdown.
     270         [ -  + ]:        250 :   if (pending_interrupts > 2) // XXX: should be configurable? time-based?
     271                 :            :     {
     272                 :          0 :       char msg[] = "Too many interrupts received, exiting.\n";
     273         [ #  # ]:          0 :       int rc = write (2, msg, sizeof(msg)-1);
     274                 :            :       if (rc) {/* Do nothing; we don't care if our last gasp went out. */ ;}
     275                 :          0 :       _exit (1);
     276                 :            :     }
     277                 :        250 : }
     278                 :            : 
     279                 :            : 
     280                 :            : void
     281                 :       2413 : setup_signals (sighandler_t handler)
     282                 :            : {
     283                 :            :   struct sigaction sa;
     284                 :            : 
     285                 :       2413 :   memset(&sa, 0, sizeof(sa));
     286                 :       2413 :   sa.sa_handler = handler;
     287                 :       2413 :   sigemptyset (&sa.sa_mask);
     288         [ +  - ]:       2413 :   if (handler != SIG_IGN)
     289                 :            :     {
     290                 :       2413 :       sigaddset (&sa.sa_mask, SIGHUP);
     291                 :       2413 :       sigaddset (&sa.sa_mask, SIGPIPE);
     292                 :       2413 :       sigaddset (&sa.sa_mask, SIGINT);
     293                 :       2413 :       sigaddset (&sa.sa_mask, SIGTERM);
     294                 :       2413 :       sigaddset (&sa.sa_mask, SIGXFSZ);
     295                 :       2413 :       sigaddset (&sa.sa_mask, SIGXCPU);
     296                 :            :     }
     297                 :       2413 :   sa.sa_flags = SA_RESTART;
     298                 :            : 
     299                 :       2413 :   sigaction (SIGHUP, &sa, NULL);
     300                 :       2413 :   sigaction (SIGPIPE, &sa, NULL);
     301                 :       2413 :   sigaction (SIGINT, &sa, NULL);
     302                 :       2413 :   sigaction (SIGTERM, &sa, NULL);
     303                 :       2413 :   sigaction (SIGXFSZ, &sa, NULL);
     304                 :       2413 :   sigaction (SIGXCPU, &sa, NULL);
     305                 :       2413 : }
     306                 :            : 
     307                 :            : 
     308                 :            : // Compilation passes 0 through 4
     309                 :            : static int
     310                 :       2194 : passes_0_4 (systemtap_session &s)
     311                 :            : {
     312                 :       2194 :   int rc = 0;
     313                 :            : 
     314                 :            :   // If we don't know the release, there's no hope either locally or on a server.
     315 [ +  - ][ -  + ]:       2194 :   if (s.kernel_release.empty())
     316                 :            :     {
     317 [ #  # ][ #  # ]:          0 :       if (s.kernel_build_tree.empty())
     318 [ #  # ][ #  # ]:          0 :         cerr << _("ERROR: kernel release isn't specified") << endl;
     319                 :            :       else
     320 [ #  # ][ #  # ]:          0 :         cerr << _F("ERROR: kernel release isn't found in \"%s\"",
         [ #  # ][ #  # ]
     321         [ #  # ]:          0 :                    s.kernel_build_tree.c_str()) << endl;
     322                 :          0 :       return 1;
     323                 :            :     }
     324                 :            : 
     325                 :            :   // Perform passes 0 through 4 using a compile server?
     326 [ +  - ][ +  + ]:       2194 :   if (! s.specified_servers.empty ())
     327                 :            :     {
     328                 :            : #if HAVE_NSS
     329         [ +  - ]:         39 :       compile_server_client client (s);
     330         [ +  + ]:         39 :       int rc = client.passes_0_4 ();
     331                 :            :       // Need to give a user a better diagnostic, if she didn't
     332                 :            :       // even ask for a server
     333 [ +  + ][ -  + ]:         36 :       if (rc && s.automatic_server_mode) {
     334 [ #  # ][ #  # ]:          0 :         cerr << _("Note: --use-server --unprivileged was selected because of stapusr membership.") << endl;
     335                 :            :       }
     336         [ +  - ]:         39 :       return rc;
     337                 :            : #else
     338                 :            :       s.print_warning("Without NSS, using a compile-server is not supported by this version of systemtap");
     339                 :            :       // This cannot be an attempt to use a server after a local compile failed
     340                 :            :       // since --use-server-on-error is locked to 'no' if we don't have
     341                 :            :       // NSS.
     342                 :            :       assert (! s.try_server ());
     343                 :            : #endif
     344                 :            :     }
     345                 :            : 
     346                 :            :   // PASS 0: setting up
     347                 :       2155 :   s.verbose = s.perpass_verbose[0];
     348                 :       2155 :   PROBE1(stap, pass0__start, &s);
     349                 :            : 
     350                 :            :   // For PR1477, we used to override $PATH and $LC_ALL and other stuff
     351                 :            :   // here.  We seem to use complete pathnames in
     352                 :            :   // buildrun.cxx/tapsets.cxx now, so this is not necessary.  Further,
     353                 :            :   // it interferes with util.cxx:find_executable(), used for $PATH
     354                 :            :   // resolution.
     355                 :            : 
     356 [ +  - ][ +  - ]:       2155 :   s.kernel_base_release.assign(s.kernel_release, 0, s.kernel_release.find('-'));
     357                 :            : 
     358                 :            :   // Update various paths to include the sysroot, if provided.
     359 [ +  - ][ -  + ]:       2155 :   if (!s.sysroot.empty())
     360                 :            :     {
     361 [ #  # ][ #  # ]:          0 :       if (s.update_release_sysroot && !s.sysroot.empty())
         [ #  # ][ #  # ]
     362 [ #  # ][ #  # ]:          0 :         s.kernel_build_tree = s.sysroot + s.kernel_build_tree;
                 [ #  # ]
     363 [ #  # ][ #  # ]:          0 :       debuginfo_path_insert_sysroot(s.sysroot);
                 [ #  # ]
     364                 :            :     }
     365                 :            : 
     366                 :            :   // Now that no further changes to s.kernel_build_tree can occur, let's use it.
     367 [ +  + ][ +  - ]:       2155 :   if ((rc = s.parse_kernel_config ()) != 0
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
                 [ -  + ]
     368                 :            :       || (rc = s.parse_kernel_exports ()) != 0
     369                 :            :       || (rc = s.parse_kernel_functions ()) != 0)
     370                 :            :     {
     371                 :            :       // Try again with a server
     372         [ #  # ]:          0 :       s.set_try_server ();
     373                 :          0 :       return rc;
     374                 :            :     }
     375                 :            : 
     376                 :            :   // Create the name of the C source file within the temporary
     377                 :            :   // directory.  Note the _src prefix, explained in
     378                 :            :   // buildrun.cxx:compile_pass()
     379 [ +  - ][ +  - ]:       2154 :   s.translated_source = string(s.tmpdir) + "/" + s.module_name + "_src.c";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     380                 :            : 
     381                 :       2154 :   PROBE1(stap, pass0__end, &s);
     382                 :            : 
     383                 :            :   struct tms tms_before;
     384                 :       2154 :   times (& tms_before);
     385                 :            :   struct timeval tv_before;
     386                 :       2154 :   gettimeofday (&tv_before, NULL);
     387                 :            : 
     388                 :            :   // PASS 1a: PARSING LIBRARY SCRIPTS
     389                 :       2154 :   PROBE1(stap, pass1a__start, &s);
     390                 :            : 
     391                 :            :   // We need to handle the library scripts first because this pass
     392                 :            :   // gathers information on .stpm files that might be needed to
     393                 :            :   // parse the user script.
     394                 :            : 
     395                 :            :   // We need to first ascertain the status of the user script, though.
     396                 :            :   struct stat user_file_stat;
     397                 :       2154 :   int user_file_stat_rc = -1;
     398                 :            : 
     399 [ +  - ][ +  + ]:       2154 :   if (s.script_file == "-")
     400                 :            :     {
     401                 :        277 :       user_file_stat_rc = fstat (STDIN_FILENO, & user_file_stat);
     402                 :            :     }
     403 [ +  - ][ +  + ]:       1877 :   else if (s.script_file != "")
     404                 :            :     {
     405         [ +  - ]:       1614 :       user_file_stat_rc = stat (s.script_file.c_str(), & user_file_stat);
     406                 :            :     }
     407                 :            :   // otherwise, rc is 0 for a command line script
     408                 :            : 
     409         [ +  - ]:       2154 :   vector<string> version_suffixes;
     410         [ +  - ]:       2154 :   if (s.runtime_mode == systemtap_session::kernel_runtime)
     411                 :            :     {
     412                 :            :       // Construct kernel-versioning search path
     413         [ +  - ]:       2154 :       string kvr = s.kernel_release;
     414                 :            : 
     415                 :            :       // add full kernel-version-release (2.6.NN-FOOBAR)
     416 [ +  - ][ +  - ]:       2154 :       version_suffixes.push_back ("/" + kvr);
                 [ +  - ]
     417                 :            : 
     418                 :            :       // add kernel version (2.6.NN)
     419 [ +  - ][ -  + ]:       2154 :       if (kvr != s.kernel_base_release)
     420                 :            :         {
     421         [ #  # ]:          0 :           kvr = s.kernel_base_release;
     422 [ #  # ][ #  # ]:          0 :           version_suffixes.push_back ("/" + kvr);
                 [ #  # ]
     423                 :            :         }
     424                 :            : 
     425                 :            :       // add kernel family (2.6)
     426         [ +  - ]:       2154 :       string::size_type dot1_index = kvr.find ('.');
     427         [ +  - ]:       2154 :       string::size_type dot2_index = kvr.rfind ('.');
     428 [ +  + ][ +  - ]:       6462 :       while (dot2_index > dot1_index && dot2_index != string::npos)
                 [ +  + ]
     429                 :            :         {
     430         [ +  - ]:       4308 :           kvr.erase(dot2_index);
     431 [ +  - ][ +  - ]:       4308 :           version_suffixes.push_back ("/" + kvr);
                 [ +  - ]
     432         [ +  - ]:       4308 :           dot2_index = kvr.rfind ('.');
     433         [ +  - ]:       2154 :         }
     434                 :            :     }
     435                 :            : 
     436                 :            :   // add empty string as last element
     437 [ +  - ][ +  - ]:       2154 :   version_suffixes.push_back ("");
                 [ +  - ]
     438                 :            : 
     439                 :            :   // Add arch variants of every path, just before each
     440                 :       2154 :   const string& arch = s.architecture;
     441         [ +  + ]:      10770 :   for (unsigned i=0; i<version_suffixes.size(); i+=2)
     442                 :            :     version_suffixes.insert(version_suffixes.begin() + i,
     443 [ +  - ][ +  - ]:       8616 :                             version_suffixes[i] + "/" + arch);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     444                 :            : 
     445                 :            :   // Add runtime variants of every path, before everything else
     446         [ +  - ]:       2154 :   string runtime_prefix;
     447         [ +  - ]:       2154 :   if (s.runtime_mode == systemtap_session::kernel_runtime)
     448         [ +  - ]:       2154 :     runtime_prefix = "/linux";
     449         [ #  # ]:          0 :   else if (s.runtime_mode == systemtap_session::dyninst_runtime)
     450         [ #  # ]:          0 :     runtime_prefix = "/dyninst";
     451 [ +  - ][ +  - ]:       2154 :   if (!runtime_prefix.empty())
     452         [ +  + ]:      19386 :     for (unsigned i=0; i<version_suffixes.size(); i+=2)
     453                 :            :       version_suffixes.insert(version_suffixes.begin() + i/2,
     454 [ +  - ][ +  - ]:      17232 :                               runtime_prefix + version_suffixes[i]);
         [ +  - ][ +  - ]
                 [ +  - ]
     455                 :            : 
     456                 :            :   // First, parse .stpm files on the include path. We need to have the
     457                 :            :   // resulting macro definitions available for parsing library files,
     458                 :            :   // but since .stpm files can consist only of '@define' constructs,
     459                 :            :   // we can parse each one without reference to the others.
     460         [ +  - ]:       2154 :   set<pair<dev_t, ino_t> > seen_library_macro_files;
     461         [ +  - ]:       2154 :   set<string> seen_library_macro_files_names;
     462                 :            : 
     463         [ +  + ]:       4355 :   for (unsigned i=0; i<s.include_path.size(); i++)
     464                 :            :     {
     465                 :            :       // now iterate upon it
     466         [ +  + ]:      37417 :       for (unsigned k=0; k<version_suffixes.size(); k++)
     467                 :            :         {
     468                 :            :           glob_t globbuf;
     469 [ +  - ][ +  - ]:      35216 :           string dir = s.include_path[i] + version_suffixes[k] + "/*.stpm";
                 [ +  - ]
     470         [ +  - ]:      35216 :           int r = glob(dir.c_str (), 0, NULL, & globbuf);
     471 [ +  - ][ -  + ]:      35216 :           if (r == GLOB_NOSPACE || r == GLOB_ABORTED)
     472                 :          0 :             rc ++;
     473                 :            :           // GLOB_NOMATCH is acceptable
     474                 :            : 
     475                 :      35216 :           unsigned prev_s_library_files = s.library_files.size();
     476                 :            : 
     477         [ +  + ]:      39524 :           for (unsigned j=0; j<globbuf.gl_pathc; j++)
     478                 :            :             {
     479         [ +  - ]:       4308 :               assert_no_interrupts();
     480                 :            : 
     481                 :            :               struct stat tapset_file_stat;
     482                 :       4308 :               int stat_rc = stat (globbuf.gl_pathv[j], & tapset_file_stat);
     483 [ +  - ][ +  + ]:       4308 :               if (stat_rc == 0 && user_file_stat_rc == 0 &&
         [ +  + ][ -  + ]
     484                 :            :                   user_file_stat.st_dev == tapset_file_stat.st_dev &&
     485                 :            :                   user_file_stat.st_ino == tapset_file_stat.st_ino)
     486                 :            :                 {
     487                 :            :                   cerr
     488 [ #  # ][ #  # ]:          0 :                   << _F("usage error: macro tapset file '%s' cannot be run directly as a session script.",
                 [ #  # ]
     489         [ #  # ]:          0 :                         globbuf.gl_pathv[j]) << endl;
     490                 :          0 :                   rc ++;
     491                 :            :                 }
     492                 :            : 
     493                 :            :               // PR11949: duplicate-eliminate tapset files
     494         [ +  - ]:       4308 :               if (stat_rc == 0)
     495                 :            :                 {
     496                 :            :                   pair<dev_t,ino_t> here = make_pair(tapset_file_stat.st_dev,
     497         [ +  - ]:       4308 :                                                      tapset_file_stat.st_ino);
     498 [ +  - ][ +  - ]:       4308 :                   if (seen_library_macro_files.find(here) != seen_library_macro_files.end()) {
                 [ -  + ]
     499         [ #  # ]:          0 :                     if (s.verbose>2)
     500 [ #  # ][ #  # ]:          0 :                       clog << _F("Skipping tapset \"%s\", duplicate inode.", globbuf.gl_pathv[j]) << endl;
         [ #  # ][ #  # ]
     501                 :          0 :                     continue; 
     502                 :            :                   }
     503         [ +  - ]:       4308 :                   seen_library_macro_files.insert (here);
     504                 :            :                 }
     505                 :            : 
     506                 :            :               // PR12443: duplicate-eliminate harder
     507         [ +  - ]:       4308 :               string full_path = globbuf.gl_pathv[j];
     508         [ +  - ]:       4308 :               string tapset_base = s.include_path[i]; // not dir; it has arch suffixes too
     509 [ +  - ][ +  - ]:       4308 :               if (full_path.size() > tapset_base.size()) {
                 [ +  - ]
     510 [ +  - ][ +  - ]:       4308 :                 string tail_part = full_path.substr(tapset_base.size());
     511 [ +  - ][ +  - ]:       4308 :                 if (seen_library_macro_files_names.find (tail_part) != seen_library_macro_files_names.end()) {
                 [ -  + ]
     512         [ #  # ]:          0 :                   if (s.verbose>2)
     513 [ #  # ][ #  # ]:          0 :                       clog << _F("Skipping tapset \"%s\", duplicate name.", globbuf.gl_pathv[j]) << endl;
         [ #  # ][ #  # ]
     514                 :          0 :                   continue;
     515                 :            :                 }
     516 [ +  - ][ +  - ]:       4308 :                 seen_library_macro_files_names.insert (tail_part);
                 [ +  - ]
     517                 :            :               }
     518                 :            : 
     519         [ +  + ]:       4308 :               if (s.verbose>2)
     520 [ +  - ][ +  - ]:          2 :                 clog << _F("Processing tapset \"%s\"", globbuf.gl_pathv[j]) << endl;
         [ +  - ][ +  - ]
     521                 :            : 
     522 [ +  - ][ +  - ]:       4308 :               stapfile* f = parse_library_macros (s, globbuf.gl_pathv[j]);
                 [ +  - ]
     523         [ -  + ]:       4308 :               if (f == 0)
     524                 :          0 :                 s.print_warning("macro tapset '" + string(globbuf.gl_pathv[j])
     525 [ #  # ][ #  # ]:          0 :                                 + "' has errors, and will be skipped."); // TODOXXX internationalization?
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     526                 :            :               else
     527         [ +  - ]:       4308 :                 s.library_files.push_back (f);
     528 [ +  - ][ -  + ]:       4308 :             }
         [ +  - ][ +  - ]
     529                 :            : 
     530                 :      35216 :           unsigned next_s_library_files = s.library_files.size();
     531 [ +  + ][ +  + ]:      35216 :           if (s.verbose>1 && globbuf.gl_pathc > 0)
     532                 :            :             //TRANSLATORS: Searching through directories, 'processed' means 'examined so far'
     533 [ +  - ][ +  - ]:         80 :             clog << _F("Searched for library macro files: \"%s\", found: %zu, processed: %u",
         [ +  - ][ +  - ]
     534                 :            :                        dir.c_str(), globbuf.gl_pathc,
     535         [ +  - ]:         40 :                        (next_s_library_files-prev_s_library_files)) << endl;
     536                 :            : 
     537                 :      35216 :           globfree (&globbuf);
     538         [ +  - ]:      35216 :         }
     539                 :            :     }
     540                 :            : 
     541                 :            :   // Next, gather and parse the library files.
     542         [ +  - ]:       2154 :   set<pair<dev_t, ino_t> > seen_library_files;
     543         [ +  - ]:       2154 :   set<string> seen_library_files_names;
     544                 :            : 
     545         [ +  + ]:       4355 :   for (unsigned i=0; i<s.include_path.size(); i++)
     546                 :            :     {
     547                 :            :       // now iterate upon it
     548         [ +  + ]:      37417 :       for (unsigned k=0; k<version_suffixes.size(); k++)
     549                 :            :         {
     550                 :            :           glob_t globbuf;
     551 [ +  - ][ +  - ]:      35216 :           string dir = s.include_path[i] + version_suffixes[k] + "/*.stp";
                 [ +  - ]
     552         [ +  - ]:      35216 :           int r = glob(dir.c_str (), 0, NULL, & globbuf);
     553 [ +  - ][ -  + ]:      35216 :           if (r == GLOB_NOSPACE || r == GLOB_ABORTED)
     554                 :          0 :             rc ++;
     555                 :            :           // GLOB_NOMATCH is acceptable
     556                 :            : 
     557                 :      35216 :           unsigned prev_s_library_files = s.library_files.size();
     558                 :            : 
     559         [ +  + ]:     220574 :           for (unsigned j=0; j<globbuf.gl_pathc; j++)
     560                 :            :             {
     561         [ +  - ]:     185358 :               assert_no_interrupts();
     562                 :            : 
     563                 :            :               struct stat tapset_file_stat;
     564                 :     185358 :               int stat_rc = stat (globbuf.gl_pathv[j], & tapset_file_stat);
     565 [ +  - ][ +  + ]:     185358 :               if (stat_rc == 0 && user_file_stat_rc == 0 &&
         [ +  + ][ +  + ]
     566                 :            :                   user_file_stat.st_dev == tapset_file_stat.st_dev &&
     567                 :            :                   user_file_stat.st_ino == tapset_file_stat.st_ino)
     568                 :            :                 {
     569                 :            :                   cerr 
     570 [ +  - ][ +  - ]:          2 :                   << _F("usage error: tapset file '%s' cannot be run directly as a session script.",
                 [ +  - ]
     571         [ +  - ]:          1 :                         globbuf.gl_pathv[j]) << endl;
     572                 :          1 :                   rc ++;
     573                 :            :                 }
     574                 :            : 
     575                 :            :               // PR11949: duplicate-eliminate tapset files
     576         [ +  - ]:     185358 :               if (stat_rc == 0)
     577                 :            :                 {
     578                 :            :                   pair<dev_t,ino_t> here = make_pair(tapset_file_stat.st_dev,
     579         [ +  - ]:     185358 :                                                      tapset_file_stat.st_ino);
     580 [ +  - ][ +  - ]:     185358 :                   if (seen_library_files.find(here) != seen_library_files.end()) {
                 [ -  + ]
     581         [ #  # ]:          0 :                     if (s.verbose>2)
     582 [ #  # ][ #  # ]:          0 :                       clog << _F("Skipping tapset \"%s\", duplicate inode.", globbuf.gl_pathv[j]) << endl;
         [ #  # ][ #  # ]
     583                 :          0 :                     continue; 
     584                 :            :                   }
     585         [ +  - ]:     185358 :                   seen_library_files.insert (here);
     586                 :            :                 }
     587                 :            : 
     588                 :            :               // PR12443: duplicate-eliminate harder
     589         [ +  - ]:     185358 :               string full_path = globbuf.gl_pathv[j];
     590         [ +  - ]:     185358 :               string tapset_base = s.include_path[i]; // not dir; it has arch suffixes too
     591 [ +  - ][ +  - ]:     185358 :               if (full_path.size() > tapset_base.size()) {
                 [ +  - ]
     592 [ +  - ][ +  - ]:     185358 :                 string tail_part = full_path.substr(tapset_base.size());
     593 [ +  - ][ +  - ]:     185358 :                 if (seen_library_files_names.find (tail_part) != seen_library_files_names.end()) {
                 [ -  + ]
     594         [ #  # ]:          0 :                   if (s.verbose>2)
     595 [ #  # ][ #  # ]:          0 :                       clog << _F("Skipping tapset \"%s\", duplicate name.", globbuf.gl_pathv[j]) << endl;
         [ #  # ][ #  # ]
     596                 :          0 :                   continue;
     597                 :            :                 }
     598 [ +  - ][ +  - ]:     185358 :                 seen_library_files_names.insert (tail_part);
                 [ +  - ]
     599                 :            :               }
     600                 :            : 
     601         [ +  + ]:     185358 :               if (s.verbose>2)
     602 [ +  - ][ +  - ]:         86 :                 clog << _F("Processing tapset \"%s\"", globbuf.gl_pathv[j]) << endl;
         [ +  - ][ +  - ]
     603                 :            : 
     604                 :            :               // NB: we don't need to restrict privilege only for /usr/share/systemtap, i.e., 
     605                 :            :               // excluding user-specified $XDG_DATA_DIRS.  That's because stapdev gets
     606                 :            :               // root-equivalent privileges anyway; stapsys and stapusr use a remote compilation
     607                 :            :               // with a trusted environment, where client-side $XDG_DATA_DIRS are not passed.
     608                 :            : 
     609 [ +  - ][ +  - ]:     185358 :               stapfile* f = parse (s, globbuf.gl_pathv[j], true /* privileged */);
                 [ +  - ]
     610         [ +  + ]:     185358 :               if (f == 0)
     611                 :          2 :                 s.print_warning("tapset '" + string(globbuf.gl_pathv[j])
     612 [ +  - ][ +  - ]:          2 :                                 + "' has errors, and will be skipped."); // TODOXXX internationalization?
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     613                 :            :               else
     614         [ +  - ]:     185358 :                 s.library_files.push_back (f);
     615 [ +  - ][ -  + ]:     185358 :             }
         [ +  - ][ +  - ]
     616                 :            : 
     617                 :      35216 :           unsigned next_s_library_files = s.library_files.size();
     618 [ +  + ][ +  + ]:      35216 :           if (s.verbose>1 && globbuf.gl_pathc > 0)
     619                 :            :             //TRANSLATORS: Searching through directories, 'processed' means 'examined so far'
     620 [ +  - ][ +  - ]:        160 :             clog << _F("Searched: \"%s\", found: %zu, processed: %u",
         [ +  - ][ +  - ]
     621                 :            :                        dir.c_str(), globbuf.gl_pathc,
     622         [ +  - ]:         80 :                        (next_s_library_files-prev_s_library_files)) << endl;
     623                 :            : 
     624                 :      35216 :           globfree (& globbuf);
     625         [ +  - ]:      35216 :         }
     626                 :            :     }
     627 [ +  - ][ +  + ]:       2154 :   if (s.num_errors())
     628                 :          1 :     rc ++;
     629                 :            : 
     630                 :            :   // PASS 1b: PARSING USER SCRIPT
     631                 :       2154 :   PROBE1(stap, pass1b__start, &s);
     632                 :            : 
     633 [ +  - ][ +  + ]:       2154 :   if (s.script_file == "-")
     634                 :            :     {
     635         [ +  - ]:        277 :       s.user_file = parse (s, cin, s.guru_mode);
     636                 :            :     }
     637 [ +  - ][ +  + ]:       1877 :   else if (s.script_file != "")
     638                 :            :     {
     639         [ +  - ]:       1614 :       s.user_file = parse (s, s.script_file, s.guru_mode);
     640                 :            :     }
     641                 :            :   else
     642                 :            :     {
     643         [ +  - ]:        263 :       istringstream ii (s.cmdline_script);
     644 [ +  - ][ +  - ]:        263 :       s.user_file = parse (s, ii, s.guru_mode);
     645                 :            :     }
     646         [ +  + ]:       2154 :   if (s.user_file == 0)
     647                 :            :     {
     648                 :            :       // Syntax errors already printed.
     649                 :        118 :       rc ++;
     650                 :            :     }
     651                 :            : 
     652 [ +  + ][ +  + ]:       2154 :   if (rc == 0 && s.last_pass == 1)
     653                 :            :     {
     654 [ +  - ][ +  - ]:        816 :       cout << _("# parse tree dump") << endl;
     655         [ +  - ]:        816 :       s.user_file->print (cout);
     656         [ +  - ]:        816 :       cout << endl;
     657         [ +  + ]:        816 :       if (s.verbose)
     658         [ +  + ]:         89 :         for (unsigned i=0; i<s.library_files.size(); i++)
     659                 :            :           {
     660         [ +  - ]:         88 :             s.library_files[i]->print (cout);
     661         [ +  - ]:         88 :             cout << endl;
     662                 :            :           }
     663                 :            :     }
     664                 :            : 
     665                 :            :   struct tms tms_after;
     666                 :       2154 :   times (& tms_after);
     667                 :       2154 :   unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK);
     668                 :            :   struct timeval tv_after;
     669                 :       2154 :   gettimeofday (&tv_after, NULL);
     670                 :            : 
     671                 :            : #define TIMESPRINT "in " << \
     672                 :            :            (tms_after.tms_cutime + tms_after.tms_utime \
     673                 :            :             - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
     674                 :            :         << (tms_after.tms_cstime + tms_after.tms_stime \
     675                 :            :             - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
     676                 :            :         << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
     677                 :            :             ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
     678                 :            : 
     679                 :            :   // syntax errors, if any, are already printed
     680         [ +  + ]:       2154 :   if (s.verbose)
     681                 :            :     {
     682                 :            :       // XXX also include a count of helper macro files loaded (.stpm)?
     683         [ +  - ]:        106 :       clog << "Pass 1: parsed user script and "
     684         [ +  - ]:        106 :            << s.library_files.size()
     685         [ +  - ]:        106 :            << " library script(s) "
     686 [ +  - ][ +  - ]:        212 :            << getmemusage()
                 [ +  - ]
     687 [ +  - ][ +  - ]:        106 :            << TIMESPRINT
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     688         [ +  - ]:        106 :            << endl;
     689                 :            :     }
     690                 :            : 
     691 [ +  + ][ +  - ]:       2154 :   if (rc && !s.listing_mode)
     692 [ +  - ][ +  - ]:        120 :     cerr << _("Pass 1: parse failed.  [man error::pass1]") << endl;
     693                 :            : 
     694                 :       2154 :   PROBE1(stap, pass1__end, &s);
     695                 :            : 
     696         [ +  - ]:       2154 :   assert_no_interrupts();
     697 [ +  + ][ +  + ]:       2154 :   if (rc || s.last_pass == 1) return rc;
     698                 :            : 
     699                 :       1218 :   times (& tms_before);
     700                 :       1218 :   gettimeofday (&tv_before, NULL);
     701                 :            : 
     702                 :            :   // PASS 2: ELABORATION
     703                 :       1218 :   s.verbose = s.perpass_verbose[1];
     704                 :       1218 :   PROBE1(stap, pass2__start, &s);
     705         [ +  - ]:       1218 :   rc = semantic_pass (s);
     706                 :            : 
     707                 :            :   // Dump a list of known probe point types, if requested.
     708         [ -  + ]:       1218 :   if (s.dump_probe_types)
     709 [ #  # ][ #  # ]:          0 :     s.pattern_root->dump (s);
                 [ #  # ]
     710                 :            : 
     711 [ +  + ][ +  + ]:       1218 :   if (s.listing_mode || (rc == 0 && s.last_pass == 2))
                 [ +  + ]
     712         [ +  - ]:        201 :     printscript(s, cout);
     713                 :            : 
     714                 :       1218 :   times (& tms_after);
     715                 :       1218 :   gettimeofday (&tv_after, NULL);
     716                 :            : 
     717 [ +  + ][ +  - ]:       1218 :   if (s.verbose) clog << "Pass 2: analyzed script: "
     718 [ +  - ][ +  - ]:        105 :                       << s.probes.size() << " probe(s), "
     719 [ +  - ][ +  - ]:        105 :                       << s.functions.size() << " function(s), "
                 [ +  - ]
     720 [ +  - ][ +  - ]:        105 :                       << s.embeds.size() << " embed(s), "
     721 [ +  - ][ +  - ]:        105 :                       << s.globals.size() << " global(s) "
     722 [ +  - ][ +  - ]:        210 :                       << getmemusage()
                 [ +  - ]
     723 [ +  - ][ +  - ]:        105 :                       << TIMESPRINT
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     724         [ +  - ]:        105 :                       << endl;
     725                 :            : 
     726 [ +  + ][ +  + ]:       1218 :   if (rc && !s.listing_mode && !s.try_server ())
         [ +  - ][ +  + ]
     727 [ +  - ][ +  - ]:        186 :     cerr << _("Pass 2: analysis failed.  [man error::pass2]") << endl;
     728                 :            : 
     729                 :       1218 :   PROBE1(stap, pass2__end, &s);
     730                 :            : 
     731         [ +  + ]:       1218 :   assert_no_interrupts();
     732 [ +  + ][ +  + ]:       1213 :   if (rc || s.listing_mode || s.last_pass == 2) return rc;
                 [ +  + ]
     733                 :            : 
     734         [ +  - ]:        831 :   rc = prepare_translate_pass (s);
     735         [ +  - ]:        831 :   assert_no_interrupts();
     736         [ -  + ]:        831 :   if (rc) return rc;
     737                 :            : 
     738                 :            :   // Generate hash.  There isn't any point in generating the hash
     739                 :            :   // if last_pass is 2, since we'll quit before using it.
     740         [ +  + ]:        831 :   if (s.use_script_cache)
     741                 :            :     {
     742         [ +  - ]:        814 :       ostringstream o;
     743                 :            :       unsigned saved_verbose;
     744                 :            : 
     745                 :            :       {
     746                 :            :         // Make sure we're in verbose mode, so that printscript()
     747                 :            :         // will output function/probe bodies.
     748                 :        814 :         saved_verbose = s.verbose;
     749                 :        814 :         s.verbose = 3;
     750         [ +  - ]:        814 :         printscript(s, o);  // Print script to 'o'
     751                 :        814 :         s.verbose = saved_verbose;
     752                 :            :       }
     753                 :            : 
     754                 :            :       // Generate hash
     755 [ +  - ][ +  - ]:        814 :       find_script_hash (s, o.str());
                 [ +  - ]
     756                 :            : 
     757                 :            :       // See if we can use cached source/module.
     758 [ +  - ][ +  + ]:        814 :       if (get_script_from_cache(s))
     759                 :            :         {
     760                 :            :           // We may still need to build uprobes, if it's not also cached.
     761         [ -  + ]:        186 :           if (s.need_uprobes)
     762         [ #  # ]:          0 :             rc = uprobes_pass(s);
     763                 :            : 
     764                 :            :           // If our last pass isn't 5, we're done (since passes 3 and
     765                 :            :           // 4 just generate what we just pulled out of the cache).
     766         [ +  - ]:        186 :           assert_no_interrupts();
     767 [ +  - ][ +  + ]:        186 :           if (rc || s.last_pass < 5) return rc;
     768                 :            : 
     769                 :            :           // Short-circuit to pass 5.
     770                 :        791 :           return 0;
     771 [ +  - ][ +  + ]:        814 :         }
     772                 :            :     }
     773                 :            : 
     774                 :            :   // PASS 3: TRANSLATION
     775                 :        645 :   s.verbose = s.perpass_verbose[2];
     776                 :        645 :   times (& tms_before);
     777                 :        645 :   gettimeofday (&tv_before, NULL);
     778                 :        645 :   PROBE1(stap, pass3__start, &s);
     779                 :            : 
     780         [ +  - ]:        645 :   rc = translate_pass (s);
     781 [ +  + ][ +  + ]:        645 :   if (! rc && s.last_pass == 3)
     782                 :            :     {
     783 [ +  - ][ +  - ]:         19 :       ifstream i (s.translated_source.c_str());
     784 [ +  - ][ +  - ]:         19 :       cout << i.rdbuf();
                 [ +  - ]
     785                 :            :     }
     786                 :            : 
     787                 :        645 :   times (& tms_after);
     788                 :        645 :   gettimeofday (&tv_after, NULL);
     789                 :            : 
     790         [ +  + ]:        645 :   if (s.verbose) 
     791         [ +  - ]:         83 :     clog << "Pass 3: translated to C into \""
     792         [ +  - ]:         83 :          << s.translated_source
     793         [ +  - ]:         83 :          << "\" "
     794 [ +  - ][ +  - ]:        166 :          << getmemusage()
                 [ +  - ]
     795 [ +  - ][ +  - ]:         83 :          << TIMESPRINT
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     796         [ +  - ]:         83 :          << endl;
     797                 :            : 
     798 [ +  + ][ +  - ]:        645 :   if (rc && ! s.try_server ())
                 [ +  + ]
     799 [ +  - ][ +  - ]:          2 :     cerr << _("Pass 3: translation failed.  [man error::pass3]") << endl;
     800                 :            : 
     801                 :        645 :   PROBE1(stap, pass3__end, &s);
     802                 :            : 
     803         [ +  - ]:        645 :   assert_no_interrupts();
     804 [ +  + ][ +  + ]:        645 :   if (rc || s.last_pass == 3) return rc;
     805                 :            : 
     806                 :            :   // PASS 4: COMPILATION
     807                 :        624 :   s.verbose = s.perpass_verbose[3];
     808                 :        624 :   times (& tms_before);
     809                 :        624 :   gettimeofday (&tv_before, NULL);
     810                 :        624 :   PROBE1(stap, pass4__start, &s);
     811                 :            : 
     812         [ +  + ]:        624 :   if (s.use_cache)
     813                 :            :     {
     814         [ +  - ]:        622 :       find_stapconf_hash(s);
     815         [ +  - ]:        622 :       get_stapconf_from_cache(s);
     816                 :            :     }
     817         [ +  - ]:        624 :   rc = compile_pass (s);
     818 [ +  + ][ +  + ]:        624 :   if (! rc && s.last_pass == 4)
     819                 :            :     {
     820 [ +  - ][ +  + ]:        297 :       cout << ((s.hash_path == "") ? s.module_filename() : s.hash_path);
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     821         [ +  - ]:        297 :       cout << endl;
     822                 :            :     }
     823                 :            : 
     824                 :        624 :   times (& tms_after);
     825                 :        624 :   gettimeofday (&tv_after, NULL);
     826                 :            : 
     827 [ +  + ][ +  - ]:        624 :   if (s.verbose) clog << "Pass 4: compiled C into \""
     828 [ +  - ][ +  - ]:        166 :                       << s.module_filename()
                 [ +  - ]
     829         [ +  - ]:         83 :                       << "\" "
     830 [ +  - ][ +  - ]:         83 :                       << TIMESPRINT
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     831         [ +  - ]:         83 :                       << endl;
     832                 :            : 
     833 [ +  + ][ +  - ]:        624 :   if (rc && ! s.try_server ())
                 [ +  + ]
     834 [ +  - ][ +  - ]:         15 :     cerr << _("Pass 4: compilation failed.  [man error::pass4]") << endl;
     835                 :            : 
     836                 :            :   else
     837                 :            :     {
     838                 :            :       // Update cache. Cache cleaning is kicked off at the beginning of this function.
     839         [ +  + ]:        609 :       if (s.use_script_cache)
     840         [ +  - ]:        592 :         add_script_to_cache(s);
     841 [ +  + ][ +  - ]:        609 :       if (s.use_cache && !s.runtime_usermode_p())
                 [ +  + ]
     842         [ +  - ]:        607 :         add_stapconf_to_cache(s);
     843                 :            : 
     844                 :            :       // We may need to save the module in $CWD if the cache was
     845                 :            :       // inaccessible for some reason.
     846 [ +  + ][ +  + ]:        609 :       if (! s.use_script_cache && s.last_pass == 4)
     847                 :          7 :         s.save_module = true;
     848                 :            : 
     849                 :            :       // Copy module to the current directory.
     850 [ +  + ][ +  - ]:        609 :       if (s.save_module && !pending_interrupts)
     851                 :            :         {
     852 [ +  - ][ +  - ]:         17 :           string module_src_path = s.tmpdir + "/" + s.module_filename();
         [ +  - ][ +  - ]
                 [ +  - ]
     853         [ +  - ]:         17 :           string module_dest_path = s.module_filename();
     854 [ +  - ][ +  - ]:         17 :           copy_file(module_src_path, module_dest_path, s.verbose > 1);
                 [ +  - ]
     855                 :            :         }
     856                 :            :     }
     857                 :            : 
     858                 :        624 :   PROBE1(stap, pass4__end, &s);
     859                 :            : 
     860 [ +  - ][ +  - ]:       2194 :   return rc;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     861                 :            : }
     862                 :            : 
     863                 :            : static int
     864                 :        475 : pass_5 (systemtap_session &s, vector<remote*> targets)
     865                 :            : {
     866                 :            :   // PASS 5: RUN
     867                 :        475 :   s.verbose = s.perpass_verbose[4];
     868                 :            :   struct tms tms_before;
     869                 :        475 :   times (& tms_before);
     870                 :            :   struct timeval tv_before;
     871                 :        475 :   gettimeofday (&tv_before, NULL);
     872                 :            :   // NB: this message is a judgement call.  The other passes don't emit
     873                 :            :   // a "hello, I'm starting" message, but then the others aren't interactive
     874                 :            :   // and don't take an indefinite amount of time.
     875                 :        475 :   PROBE1(stap, pass5__start, &s);
     876 [ +  + ][ +  - ]:        475 :   if (s.verbose) clog << _("Pass 5: starting run.") << endl;
                 [ +  - ]
     877         [ +  - ]:        475 :   int rc = remote::run(targets);
     878                 :            :   struct tms tms_after;
     879                 :        475 :   times (& tms_after);
     880                 :        475 :   unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK);
     881                 :            :   struct timeval tv_after;
     882                 :        475 :   gettimeofday (&tv_after, NULL);
     883 [ +  + ][ +  - ]:        475 :   if (s.verbose) clog << "Pass 5: run completed "
     884 [ +  - ][ +  - ]:         72 :                       << TIMESPRINT
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     885         [ +  - ]:         72 :                       << endl;
     886                 :            : 
     887         [ +  + ]:        475 :   if (rc)
     888 [ +  - ][ +  - ]:        101 :     cerr << _("Pass 5: run failed.  [man error::pass5]") << endl;
     889                 :            :   else
     890                 :            :     // Interrupting pass-5 to quit is normal, so we want an EXIT_SUCCESS below.
     891                 :        374 :     pending_interrupts = 0;
     892                 :            : 
     893                 :        475 :   PROBE1(stap, pass5__end, &s);
     894                 :            : 
     895                 :        475 :   return rc;
     896                 :            : }
     897                 :            : 
     898                 :            : static void
     899                 :       2204 : cleanup (systemtap_session &s, int rc)
     900                 :            : {
     901                 :            :   // PASS 6: cleaning up
     902                 :       2204 :   PROBE1(stap, pass6__start, &s);
     903                 :            : 
     904 [ +  - ][ -  + ]:       4408 :   for (systemtap_session::session_map_t::iterator it = s.subsessions.begin();
     905         [ +  - ]:       2204 :        it != s.subsessions.end(); ++it)
     906 [ #  # ][ #  # ]:          0 :     cleanup (*it->second, rc);
     907                 :            : 
     908                 :            :   // update the database information
     909 [ +  + ][ -  + ]:       2204 :   if (!rc && s.tapset_compile_coverage && !pending_interrupts) {
                 [ #  # ]
     910                 :            : #ifdef HAVE_LIBSQLITE3
     911                 :          0 :     update_coverage_db(s);
     912                 :            : #else
     913                 :            :     cerr << _("Coverage database not available without libsqlite3") << endl;
     914                 :            : #endif
     915                 :            :   }
     916                 :            : 
     917                 :       2204 :   PROBE1(stap, pass6__end, &s);
     918                 :       2204 : }
     919                 :            : 
     920                 :            : static int
     921                 :          0 : passes_0_4_again_with_server (systemtap_session &s)
     922                 :            : {
     923                 :            :   // Not a server and not already using a server.
     924         [ #  # ]:          0 :   assert (! s.client_options);
     925         [ #  # ]:          0 :   assert (s.specified_servers.empty ());
     926                 :            : 
     927                 :            :   // Specify default server(s).
     928 [ #  # ][ #  # ]:          0 :   s.specified_servers.push_back ("");
                 [ #  # ]
     929                 :            : 
     930                 :            :   // Reset the previous temporary directory and start fresh
     931                 :          0 :   s.reset_tmp_dir();
     932                 :            : 
     933                 :            :   // Try to compile again, using the server
     934                 :          0 :   clog << _("Attempting compilation using a compile server")
     935                 :          0 :        << endl;
     936                 :            : 
     937                 :          0 :   int rc = passes_0_4 (s);
     938                 :          0 :   return rc;
     939                 :            : }
     940                 :            : 
     941                 :            : int
     942                 :       2414 : main (int argc, char * const argv [])
     943                 :            : {
     944                 :            :   // Initialize defaults.
     945                 :            :   try {
     946         [ +  + ]:       2414 :     systemtap_session s;
     947                 :            : 
     948                 :       2413 :     setlocale (LC_ALL, "");
     949                 :       2413 :     bindtextdomain (PACKAGE, LOCALEDIR);
     950                 :       2413 :     textdomain (PACKAGE);
     951                 :            : 
     952                 :            :     // Set up our handler to catch routine signals, to allow clean
     953                 :            :     // and reasonably timely exit.
     954                 :       2413 :     setup_signals(&handle_interrupt);
     955                 :            : 
     956                 :            :     // PR13520: Parse $SYSTEMTAP_DIR/rc for extra options
     957         [ +  - ]:       2413 :     string rc_file = s.data_path + "/rc";
     958 [ +  - ][ +  - ]:       2413 :     ifstream rcf (rc_file.c_str());
     959         [ +  - ]:       2413 :     string rcline;
     960                 :            :     wordexp_t words;
     961                 :       2413 :     memset (& words, 0, sizeof(words));
     962                 :       2413 :     int rc = 0;
     963                 :       2413 :     int linecount = 0;
     964 [ +  - ][ +  - ]:       9592 :     while (getline (rcf, rcline))
                 [ +  + ]
     965                 :            :       {
     966                 :            :         rc = wordexp (rcline.c_str(), & words, WRDE_NOCMD|WRDE_UNDEF|
     967 [ +  - ][ +  + ]:       7179 :                       (linecount > 0 ? WRDE_APPEND : 0)); 
                 [ +  - ]
     968                 :            :         // NB: WRDE_APPEND automagically reallocates words.* as more options are added.
     969                 :       7179 :         linecount ++;
     970         [ -  + ]:       7179 :         if (rc) break;
     971                 :            :       }
     972                 :       2413 :     int extended_argc = words.we_wordc + argc;
     973                 :       2413 :     char **extended_argv = (char**) calloc (extended_argc + 1, sizeof(char*));
     974 [ +  - ][ -  + ]:       2413 :     if (rc || !extended_argv)
     975                 :            :       {
     976 [ #  # ][ #  # ]:          0 :         clog << _F("Error processing extra options in %s", rc_file.c_str());
         [ #  # ][ #  # ]
     977                 :          0 :         return EXIT_FAILURE;
     978                 :            :       }
     979                 :            :     // Copy over the arguments *by reference*, first the ones from the rc file.
     980                 :       2413 :     char **p = & extended_argv[0];
     981                 :       2413 :     *p++ = argv[0];
     982         [ +  + ]:      14378 :     for (unsigned i=0; i<words.we_wordc; i++) *p++ = words.we_wordv[i];
     983         [ +  + ]:       9609 :     for (int j=1; j<argc; j++) *p++ = argv[j];
     984                 :       2413 :     *p++ = NULL;
     985                 :            : 
     986                 :            :     // Process the command line.
     987         [ +  + ]:       2413 :     rc = s.parse_cmdline (extended_argc, extended_argv);
     988         [ +  + ]:       2341 :     if (rc != 0)
     989                 :         91 :       return rc;
     990                 :            : 
     991 [ +  + ][ +  + ]:       2250 :     if (words.we_wordc > 0 && s.verbose > 1)
     992 [ +  - ][ +  - ]:         18 :       clog << _F("Extra options in %s: %d\n", rc_file.c_str(), (int)words.we_wordc);
         [ +  - ][ +  - ]
     993                 :            : 
     994                 :            :     // Check for options conflicts. Exits if errors are detected.
     995         [ +  + ]:       2250 :     s.check_options (extended_argc, extended_argv);
     996                 :            : 
     997                 :            :     // We don't need these strings any more.
     998                 :       2213 :     wordfree (& words);
     999                 :       2213 :     free (extended_argv);
    1000                 :            : 
    1001                 :            :     // arguments parsed; get down to business
    1002         [ +  + ]:       2213 :     if (s.verbose > 1)
    1003         [ +  - ]:         20 :       s.version ();
    1004                 :            : 
    1005                 :            :     // Need to send the verbose message here, rather than in the session ctor, since
    1006                 :            :     // we didn't know if verbose was set.
    1007 [ +  - ][ +  + ]:       2213 :     if (rc == 0 && s.verbose>1)
    1008 [ +  - ][ +  - ]:         20 :       clog << _F("Created temporary directory \"%s\"", s.tmpdir.c_str()) << endl;
         [ +  - ][ +  - ]
                 [ +  - ]
    1009                 :            : 
    1010                 :            :     // Prepare connections for each specified remote target.
    1011         [ +  - ]:       2213 :     vector<remote*> targets;
    1012                 :       2213 :     bool fake_remote=false;
    1013 [ +  - ][ +  + ]:       2213 :     if (s.remote_uris.empty())
    1014                 :            :       {
    1015                 :       2206 :         fake_remote=true;
    1016 [ +  - ][ +  - ]:       2206 :         s.remote_uris.push_back("direct:");
                 [ +  - ]
    1017                 :            :       }
    1018 [ +  + ][ +  + ]:       4427 :     for (unsigned i = 0; rc == 0 && i < s.remote_uris.size(); ++i)
                 [ +  + ]
    1019                 :            :       {
    1020                 :            :         // PR13354: pass remote id#/url only in non --remote=HOST cases
    1021                 :       2214 :         remote *target = remote::create(s, s.remote_uris[i],
    1022 [ +  + ][ +  - ]:       2214 :                                         fake_remote ? -1 : (int)i);
    1023         [ +  + ]:       2214 :         if (target)
    1024         [ +  - ]:       2213 :           targets.push_back(target);
    1025                 :            :         else
    1026                 :          1 :           rc = 1;
    1027                 :            :       }
    1028                 :            : 
    1029                 :            :     // Discover and loop over each unique session created by the remote targets.
    1030         [ +  - ]:       2213 :     set<systemtap_session*> sessions;
    1031         [ +  + ]:       4426 :     for (unsigned i = 0; i < targets.size(); ++i)
    1032         [ +  - ]:       2213 :       sessions.insert(targets[i]->get_session());
    1033 [ +  - ][ +  + ]:      12865 :     for (set<systemtap_session*>::iterator it = sessions.begin();
           [ +  +  +  + ]
                 [ +  + ]
    1034 [ +  - ][ +  + ]:       8458 :          rc == 0 && !pending_interrupts && it != sessions.end(); ++it)
                 [ #  # ]
    1035                 :            :       {
    1036                 :       2212 :         systemtap_session& ss = **it;
    1037         [ +  + ]:       2212 :         if (ss.verbose > 1)
    1038 [ +  - ][ +  - ]:         40 :           clog << _F("Session arch: %s release: %s",
         [ +  - ][ +  - ]
                 [ +  - ]
    1039         [ +  - ]:         20 :                      ss.architecture.c_str(), ss.kernel_release.c_str()) << endl;
    1040                 :            : 
    1041                 :            : #if HAVE_NSS
    1042                 :            :         // If requested, query server status. This is independent of other tasks.
    1043         [ +  - ]:       2212 :         query_server_status (ss);
    1044                 :            : 
    1045                 :            :         // If requested, manage trust of servers. This is independent of other tasks.
    1046         [ +  - ]:       2212 :         manage_server_trust (ss);
    1047                 :            : #endif
    1048                 :            : 
    1049                 :            :         // Run the passes only if a script has been specified. The requirement for
    1050                 :            :         // a script has already been checked in systemtap_session::check_options.
    1051                 :            :         // Run the passes also if a dump of supported probe types has been requested via a server.
    1052 [ +  + ][ -  + ]:       2212 :         if (ss.have_script || (ss.dump_probe_types && ! s.specified_servers.empty ()))
         [ #  # ][ #  # ]
                 [ +  + ]
    1053                 :            :           {
    1054                 :            :             // Run passes 0-4 for each unique session,
    1055                 :            :             // either locally or using a compile-server.
    1056         [ +  - ]:       2194 :             ss.init_try_server ();
    1057 [ +  + ][ +  + ]:       2194 :             if ((rc = passes_0_4 (ss)))
    1058                 :            :               {
    1059                 :            :                 // Compilation failed.
    1060                 :            :                 // Try again using a server if appropriate.
    1061         [ -  + ]:        377 :                 if (ss.try_server ())
    1062         [ #  # ]:          0 :                   rc = passes_0_4_again_with_server (ss);
    1063                 :            :               }
    1064                 :            :           }
    1065         [ -  + ]:         18 :         else if (ss.dump_probe_types)
    1066                 :            :           {
    1067                 :            :             // Dump a list of known probe point types, if requested.
    1068         [ #  # ]:          0 :             register_standard_tapsets(ss);
    1069 [ #  # ][ #  # ]:          0 :             ss.pattern_root->dump (ss);
                 [ #  # ]
    1070                 :            :           }
    1071                 :            :       }
    1072                 :            : 
    1073                 :            :     // Run pass 5, if requested
    1074 [ +  + ][ +  + ]:       2204 :     if (rc == 0 && s.have_script && s.last_pass >= 5 && ! pending_interrupts)
         [ +  + ][ +  - ]
    1075 [ +  - ][ +  - ]:        475 :       rc = pass_5 (s, targets);
                 [ +  - ]
    1076                 :            : 
    1077                 :            :     // Pass 6. Cleanup
    1078         [ +  + ]:       4408 :     for (unsigned i = 0; i < targets.size(); ++i)
    1079 [ +  - ][ +  - ]:       2204 :       delete targets[i];
    1080         [ +  - ]:       2204 :     cleanup (s, rc);
    1081                 :            : 
    1082         [ +  + ]:       2204 :     assert_no_interrupts();
    1083 [ +  + ][ +  - ]:       2543 :     return (rc) ? EXIT_FAILURE : EXIT_SUCCESS;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
    1084                 :            :   }
    1085                 :         18 :   catch (const interrupt_exception& e) {
    1086                 :            :       // User entered ctrl-c, exit quietly.
    1087                 :         18 :       return EXIT_FAILURE;
    1088                 :            :   }
    1089                 :         47 :   catch (const exit_exception& e) {
    1090                 :            :       // Exiting for any quiet reason.
    1091                 :         47 :       return e.rc;
    1092                 :            :   }
    1093                 :        126 :   catch (const runtime_error &e) {
    1094                 :            :       // Some other uncaught runtime_error exception.
    1095 [ -  + ][ -  + ]:         63 :       cerr << e.what() << endl;
    1096                 :         63 :       return EXIT_FAILURE;
    1097                 :            :   }
    1098   [ +  +  +  + ]:        130 :   catch (...) {
    1099                 :            :       // Catch all other unknown exceptions.
    1100 [ -  + ][ -  + ]:          1 :       cerr << _("ERROR: caught unknown exception!") << endl;
    1101                 :          1 :       return EXIT_FAILURE;
    1102                 :            :   }
    1103 [ +  - ][ +  - ]:       7242 : }
    1104                 :            : 
    1105                 :            : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */

Generated by: LCOV version 1.9