LTP GCOV extension - code coverage report
Current view: directory - src - main.cxx
Test: stap.info
Date: 2008-03-12 Instrumented lines: 412
Code covered: 89.3 % Executed lines: 368

       1                 : // systemtap translator/driver
       2                 : // Copyright (C) 2005-2008 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                 : 
      23                 : #include <iostream>
      24                 : #include <fstream>
      25                 : #include <sstream>
      26                 : #include <cerrno>
      27                 : #include <cstdlib>
      28                 : 
      29                 : extern "C" {
      30                 : #include <glob.h>
      31                 : #include <unistd.h>
      32                 : #include <signal.h>
      33                 : #include <sys/utsname.h>
      34                 : #include <sys/times.h>
      35                 : #include <sys/time.h>
      36                 : #include <sys/stat.h>
      37                 : #include <time.h>
      38                 : #include <elfutils/libdwfl.h>
      39                 : }
      40                 : 
      41                 : using namespace std;
      42                 : 
      43                 : 
      44                 : void
      45              13 : version ()
      46                 : {
      47                 :   clog
      48                 :     << "SystemTap translator/driver "
      49                 :     << "(version " << VERSION << "/" << dwfl_version (NULL)
      50                 :     << " built " << DATE << ")" << endl
      51                 :     << "Copyright (C) 2005-2008 Red Hat, Inc. and others" << endl
      52              13 :     << "This is free software; see the source for copying conditions." << endl;
      53              13 : }
      54                 : 
      55                 : void
      56               9 : usage (systemtap_session& s, int exitcode)
      57                 : {
      58               9 :   version ();
      59                 :   clog
      60                 :     << endl
      61                 :     << "Usage: stap [options] FILE         Run script in file."
      62                 :     << endl
      63                 :     << "   or: stap [options] -            Run script on stdin."
      64                 :     << endl
      65                 :     << "   or: stap [options] -e SCRIPT    Run given script."
      66                 :     << endl
      67                 :     << endl
      68                 :     << "Options:" << endl
      69                 :     << "   --         no more options after this" << endl
      70                 :     << "   -v         increase verbosity [" << s.verbose << "]" << endl
      71                 :     << "   -h         show help" << endl
      72                 :     << "   -V         show version" << endl
      73                 :     << "   -k         keep temporary directory" << endl
      74                 :     << "   -u         unoptimized translation" << (s.unoptimized ? " [set]" : "") << endl
      75                 :     << "   -w         suppress warnings" << (s.suppress_warnings ? " [set]" : "") << endl
      76                 :     << "   -g         guru mode" << (s.guru_mode ? " [set]" : "") << endl
      77                 :     << "   -P         prologue-searching for function probes" 
      78                 :     << (s.prologue_searching ? " [set]" : "") << endl
      79                 :     << "   -b         bulk (percpu file) mode" << (s.bulk_mode ? " [set]" : "") << endl
      80                 :     << "   -s NUM     buffer size in megabytes, instead of "
      81                 :     << s.buffer_size << endl
      82                 :     << "   -p NUM     stop after pass NUM 1-5, instead of "
      83                 :     << s.last_pass << endl
      84                 :     << "              (parse, elaborate, translate, compile, run)" << endl
      85               9 :     << "   -I DIR     look in DIR for additional .stp script files";
      86               9 :   if (s.include_path.size() == 0)
      87               0 :     clog << endl;
      88                 :   else
      89               9 :     clog << ", in addition to" << endl;
      90              18 :   for (unsigned i=0; i<s.include_path.size(); i++)
      91               9 :     clog << "              " << s.include_path[i] << endl;
      92                 :   clog
      93                 :     << "   -D NM=VAL  emit macro definition into generated C code" << endl
      94                 :     << "   -R DIR     look in DIR for runtime, instead of" << endl
      95                 :     <<      "              " << s.runtime_path << endl
      96                 :     << "   -r RELEASE cross-compile to kernel RELEASE, instead of "
      97                 :     << s.kernel_release << endl
      98                 :     << "   -m MODULE  set probe module name, instead of "
      99                 :     << s.module_name << endl
     100                 :     << "   -o FILE    send output to file, instead of stdout" << endl
     101                 :     << "   -c CMD     start the probes, run CMD, and exit when it finishes"
     102                 :     << endl
     103                 :     << "   -x PID     sets target() to PID" << endl
     104                 :     << "   -t         collect probe timing information" << endl
     105                 : #ifdef HAVE_LIBSQLITE3
     106                 :     << "   -q         generate information on tapset coverage"
     107                 : #endif /* HAVE_LIBSQLITE3 */
     108                 :     << endl
     109               9 :     ;
     110                 :   // -d: dump safety-related external references
     111                 : 
     112               9 :   exit (exitcode);
     113                 : }
     114                 : 
     115                 : 
     116                 : static void
     117             391 : printscript(systemtap_session& s, ostream& o)
     118                 : {
     119             391 :   if (s.embeds.size() > 0)
     120             119 :     o << "# global embedded code" << endl;
     121            1488 :   for (unsigned i=0; i<s.embeds.size(); i++)
     122                 :     {
     123            1097 :       embeddedcode* ec = s.embeds[i];
     124            1097 :       ec->print (o);
     125            1097 :       o << endl;
     126                 :     }
     127                 : 
     128             391 :   if (s.globals.size() > 0)
     129             195 :     o << "# globals" << endl;
     130            1065 :   for (unsigned i=0; i<s.globals.size(); i++)
     131                 :     {
     132             674 :       vardecl* v = s.globals[i];
     133             674 :       v->printsig (o);
     134             674 :       if (s.verbose && v->init)
     135                 :         {
     136              73 :           o << " = ";
     137              73 :           v->init->print(o);
     138                 :         }
     139             674 :       o << endl;
     140                 :     }
     141                 : 
     142             391 :   if (s.functions.size() > 0)
     143             289 :     o << "# functions" << endl;
     144            8033 :   for (unsigned i=0; i<s.functions.size(); i++)
     145                 :     {
     146            7642 :       functiondecl* f = s.functions[i];
     147            7642 :       f->printsig (o);
     148            7642 :       o << endl;
     149            7642 :       if (f->locals.size() > 0)
     150             626 :         o << "  # locals" << endl;
     151            8289 :       for (unsigned j=0; j<f->locals.size(); j++)
     152                 :         {
     153             647 :           vardecl* v = f->locals[j];
     154             647 :           o << "  ";
     155             647 :           v->printsig (o);
     156             647 :           o << endl;
     157                 :         }
     158            7642 :       if (s.verbose)
     159                 :         {
     160            7628 :           f->body->print (o);
     161            7628 :           o << endl;
     162                 :         }
     163                 :     }
     164                 : 
     165             391 :   if (s.probes.size() > 0)
     166             391 :     o << "# probes" << endl;
     167          488917 :   for (unsigned i=0; i<s.probes.size(); i++)
     168                 :     {
     169          488526 :       derived_probe* p = s.probes[i];
     170          488526 :       p->printsig (o);
     171          488526 :       o << endl;
     172          488526 :       if (p->locals.size() > 0)
     173           46887 :         o << "  # locals" << endl;
     174          570047 :       for (unsigned j=0; j<p->locals.size(); j++)
     175                 :         {
     176           81521 :           vardecl* v = p->locals[j];
     177           81521 :           o << "  ";
     178           81521 :           v->printsig (o);
     179           81521 :           o << endl;
     180                 :         }
     181          488526 :       if (s.verbose)
     182                 :         {
     183           52800 :           p->body->print (o);
     184           52800 :           o << endl;
     185                 :         }
     186                 :     }
     187             391 : }
     188                 : 
     189                 : 
     190                 : int pending_interrupts;
     191                 : 
     192                 : extern "C"
     193              39 : void handle_interrupt (int /* sig */) 
     194                 : {
     195              39 :   pending_interrupts ++;
     196              39 :   if (pending_interrupts > 1) // XXX: should be configurable? time-based?
     197                 :     {
     198               0 :       char msg[] = "Too many interrupts received, exiting.\n";
     199               0 :       int rc = write (2, msg, sizeof(msg)-1);
     200                 :       if (rc) {/* Do nothing; we don't care if our last gasp went out. */ ;}
     201               0 :       _exit (1);
     202                 :     }
     203              39 : }
     204                 : 
     205                 : 
     206                 : int
     207            1094 : main (int argc, char * const argv [])
     208                 : {
     209            1094 :   string cmdline_script; // -e PROGRAM
     210            1094 :   string script_file; // FILE
     211            1094 :   bool have_script = false;
     212            1094 :   bool release_changed = false;
     213            1094 :   bool save_module = false;
     214                 : 
     215                 :   // Initialize defaults
     216            1094 :   systemtap_session s;
     217                 :   struct utsname buf;
     218            1094 :   (void) uname (& buf);
     219            1094 :   s.kernel_release = string (buf.release);
     220            2188 :   s.architecture = string (buf.machine);
     221            1094 :   s.verbose = 0;
     222            1094 :   s.timing = false;
     223            1094 :   s.guru_mode = false;
     224            1094 :   s.bulk_mode = false;
     225            1094 :   s.unoptimized = false;
     226            1094 :   s.suppress_warnings = false;
     227                 : 
     228                 : #ifdef ENABLE_PROLOGUES
     229                 :   s.prologue_searching = true;
     230                 : #else
     231            1094 :   s.prologue_searching = false;
     232                 : #endif
     233                 : 
     234            1094 :   s.buffer_size = 0;
     235            1094 :   s.last_pass = 5;
     236            2188 :   s.module_name = "stap_" + stringify(getpid());
     237            1094 :   s.output_file = ""; // -o FILE
     238            1094 :   s.keep_tmpdir = false;
     239            1094 :   s.cmd = "";
     240            1094 :   s.target_pid = 0;
     241            1094 :   s.merge=true;
     242            1094 :   s.perfmon=0;
     243            1094 :   s.symtab = false;
     244            1094 :   s.use_cache = true;
     245            1094 :   s.tapset_compile_coverage = false;
     246            1094 :   s.need_uprobes = false;
     247                 : 
     248            1094 :   const char* s_p = getenv ("SYSTEMTAP_TAPSET");
     249            1094 :   if (s_p != NULL)  
     250                 :   {
     251            1094 :     s.include_path.push_back (s_p);
     252                 :   }
     253                 :   else
     254                 :   {
     255               0 :     s.include_path.push_back (string(PKGDATADIR) + "/tapset");
     256                 :   }
     257                 : 
     258            1094 :   const char* s_r = getenv ("SYSTEMTAP_RUNTIME");
     259            1094 :   if (s_r != NULL)
     260            1094 :     s.runtime_path = s_r;
     261                 :   else
     262               0 :     s.runtime_path = string(PKGDATADIR) + "/runtime";
     263                 : 
     264            1094 :   const char* s_d = getenv ("SYSTEMTAP_DIR");
     265            1094 :   if (s_d != NULL)
     266            1094 :     s.data_path = s_d;
     267                 :   else
     268               0 :     s.data_path = get_home_directory() + string("/.systemtap");
     269            1094 :   if (create_dir(s.data_path.c_str()) == 1)
     270                 :     {
     271               2 :       const char* e = strerror (errno);
     272                 :       cerr << "Warning: failed to create systemtap data directory (\""
     273               2 :            << s.data_path << "\"): " << e << endl;
     274               2 :       cerr << "Disabling cache support." << endl;
     275               2 :       s.use_cache = false;
     276                 :     }
     277                 : 
     278            1094 :   if (s.use_cache)
     279                 :     {
     280            1092 :       s.cache_path = s.data_path + "/cache";
     281            1092 :       if (create_dir(s.cache_path.c_str()) == 1)
     282                 :         {
     283               0 :           const char* e = strerror (errno);
     284                 :           cerr << "Warning: failed to create cache directory (\""
     285               0 :                << s.cache_path << "\"): " << e << endl;
     286               0 :           cerr << "Disabling cache support." << endl;
     287               0 :           s.use_cache = false;
     288                 :         }
     289                 :     }
     290                 : 
     291            1094 :   const char* s_tc = getenv ("SYSTEMTAP_COVERAGE");
     292            1094 :   if (s_tc != NULL)
     293               0 :     s.tapset_compile_coverage = true;
     294                 : 
     295            1233 :   while (true)
     296                 :     {
     297                 :       // NB: also see find_hash(), usage(), switch stmt below, stap.1 man page
     298            2327 :       int grc = getopt (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqw");
     299            2327 :       if (grc < 0)
     300            1086 :         break;
     301            1241 :       switch (grc)
     302                 :         {
     303                 :         case 'V':
     304               2 :           version ();
     305               2 :           exit (0);
     306                 : 
     307                 :         case 'M':
     308               4 :           s.merge = false;
     309               4 :           break;
     310                 : 
     311                 :         case 'v':
     312              57 :           s.verbose ++;
     313              57 :           break;
     314                 : 
     315                 :         case 't':
     316               2 :           s.timing = true;
     317               2 :           break;
     318                 : 
     319                 :         case 'w':
     320               0 :           s.suppress_warnings = true;
     321               0 :           break;
     322                 : 
     323                 :         case 'p':
     324             886 :           s.last_pass = atoi (optarg);
     325             886 :           if (s.last_pass < 1 || s.last_pass > 5)
     326                 :             {
     327               1 :               cerr << "Invalid pass number (should be 1-5)." << endl;
     328               1 :               usage (s, 1);
     329                 :             }
     330             885 :           break;
     331                 : 
     332                 :         case 'I':
     333               2 :           s.include_path.push_back (string (optarg));
     334               2 :           break;
     335                 : 
     336                 :         case 'e':
     337              71 :           if (have_script)
     338                 :             {
     339                 :               cerr << "Only one script can be given on the command line."
     340               1 :                    << endl;
     341               1 :               usage (s, 1);
     342                 :             }
     343              70 :           cmdline_script = string (optarg);
     344              70 :           have_script = true;
     345              70 :           break;
     346                 : 
     347                 :         case 'o':
     348              11 :           s.output_file = string (optarg);
     349              11 :           break;
     350                 : 
     351                 :         case 'R':
     352               2 :           s.runtime_path = string (optarg);
     353               2 :           break;
     354                 : 
     355                 :         case 'm':
     356               7 :           s.module_name = string (optarg);
     357               7 :           save_module = true;
     358                 :           {
     359              14 :             string::size_type len = s.module_name.length();
     360                 : 
     361                 :             // If the module name ends with '.ko', chop it off since
     362                 :             // modutils doesn't like modules named 'foo.ko.ko'.
     363               7 :             if (len > 3 && s.module_name.substr(len - 3, 3) == ".ko")
     364                 :               {
     365               0 :                 s.module_name.erase(len - 3);
     366               0 :                 len -= 3;
     367                 :                 cerr << "Truncating module name to '" << s.module_name
     368               0 :                      << "'" << endl;
     369                 :               }
     370                 : 
     371                 :             // Make sure an empty module name wasn't specified (-m "")
     372               7 :             if (len == 0)
     373                 :             {
     374               1 :                 cerr << "Module name cannot be empty." << endl;
     375               1 :                 usage (s, 1);
     376                 :             }
     377                 : 
     378                 :             // Make sure the module name is only composed of the
     379                 :             // following chars: [_a-zA-Z0-9]
     380                 :             const string identchars("_" "abcdefghijklmnopqrstuvwxyz"
     381               6 :                                     "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "0123456789");
     382              12 :             if (s.module_name.find_first_not_of(identchars) != string::npos)
     383                 :               {
     384                 :                 cerr << "Invalid module name (must only be composed of"
     385               1 :                     " characters [_a-zA-Z0-9])." << endl;
     386               1 :                 usage (s, 1);
     387                 :               }
     388                 : 
     389                 :             // Make sure module name isn't too long.
     390               5 :             if (s.module_name.size() >= (MODULE_NAME_LEN - 1))
     391                 :               {
     392               0 :                 s.module_name.resize(MODULE_NAME_LEN - 1);
     393                 :                 cerr << "Truncating module name to '" << s.module_name
     394               0 :                      << "'" << endl;
     395               5 :               }
     396                 :           }
     397                 : 
     398               5 :           cerr << "Warning: using '-m' disables cache support." << endl;
     399               5 :           s.use_cache = false;
     400               5 :           break;
     401                 : 
     402                 :         case 'r':
     403               0 :           s.kernel_release = string (optarg);
     404               0 :           release_changed = true;
     405               0 :           break;
     406                 : 
     407                 :         case 'k':
     408               1 :           s.keep_tmpdir = true;
     409               1 :           break;
     410                 : 
     411                 :         case 'g':
     412              36 :           s.guru_mode = true;
     413              36 :           break;
     414                 : 
     415                 :         case 'P':
     416               1 :           s.prologue_searching = true;
     417               1 :           break;
     418                 : 
     419                 :         case 'b':
     420              10 :           s.bulk_mode = true;
     421              10 :           break;
     422                 : 
     423                 :         case 'u':
     424              34 :           s.unoptimized = true;
     425              34 :           break;
     426                 : 
     427                 :         case 's':
     428               1 :           s.buffer_size = atoi (optarg);
     429               1 :           if (s.buffer_size < 1 || s.buffer_size > 64)
     430                 :             {
     431               1 :               cerr << "Invalid buffer size (should be 1-64)." << endl;
     432               1 :               usage (s, 1);
     433                 :             }
     434               0 :           break;
     435                 : 
     436                 :         case 'c':
     437              69 :           s.cmd = string (optarg);
     438              69 :           break;
     439                 : 
     440                 :         case 'x':
     441               2 :           s.target_pid = atoi(optarg);
     442               2 :           break;
     443                 : 
     444                 :         case 'D':
     445              42 :           s.macros.push_back (string (optarg));
     446              42 :           break;
     447                 : 
     448                 :         case 'q':
     449               0 :           s.tapset_compile_coverage = true;
     450               0 :           break;
     451                 : 
     452                 :         case 'h':
     453               1 :           usage (s, 0);
     454               0 :           break;
     455                 : 
     456                 :         default:
     457               0 :           usage (s, 1);
     458                 :           break;
     459                 :         }
     460                 :     }
     461                 : 
     462            1086 :   if(!s.bulk_mode && !s.merge)
     463                 :     {
     464               1 :       cerr << "-M option is valid only for bulk (relayfs) mode." <<endl;
     465               1 :       usage (s, 1);
     466                 :     }
     467                 : 
     468            1085 :   if(!s.output_file.empty() && s.bulk_mode && !s.merge)
     469                 :     {
     470               1 :       cerr << "You can't specify -M, -b and -o options together." <<endl;
     471               1 :       usage (s, 1);
     472                 :     }
     473                 : 
     474            1084 :   if((s.cmd != "") && (s.target_pid))
     475                 :     {
     476               1 :       cerr << "You can't specify -c and -x options together." <<endl;
     477               1 :       usage (s, 1);
     478                 :     }
     479                 : 
     480            1083 :   if (s.last_pass > 4 && release_changed)
     481                 :     {
     482               0 :       if (s.verbose)
     483               0 :         cerr << "Warning: changing last pass to 4 since cross-compiling" << endl;
     484               0 :       s.last_pass = 4;
     485                 :     }
     486                 : 
     487            2116 :   for (int i = optind; i < argc; i++)
     488                 :     {
     489            1033 :       if (! have_script)
     490                 :         {
     491            1017 :           script_file = string (argv[i]);
     492            1017 :           have_script = true;
     493                 :         }
     494                 :       else
     495              16 :         s.args.push_back (string (argv[i]));
     496                 :     }
     497                 : 
     498                 :   // need a user file
     499            1083 :   if (! have_script)
     500                 :     {
     501               0 :       cerr << "A script must be specified." << endl;
     502               0 :       usage(s, 1);
     503                 :     }
     504                 : 
     505            1083 :   int rc = 0;
     506                 : 
     507                 :   // override PATH and LC_ALL
     508            1083 :   const char *path = "/bin:/sbin:/usr/bin:/usr/sbin";
     509            1083 :   rc = setenv("PATH", path, 1) || setenv("LC_ALL", "C", 1);
     510            1083 :   if (rc)
     511                 :     {
     512               0 :       const char* e = strerror (errno);
     513                 :       cerr << "setenv (\"PATH=" << path << "\" + \"LC_ALL=C\"): "
     514               0 :            << e << endl;
     515                 :     }
     516                 : 
     517                 :   // Get rid of a few standard environment variables (which might
     518                 :   // cause us to do unintended things).
     519                 :   rc = unsetenv("IFS") || unsetenv("CDPATH") || unsetenv("ENV")
     520            1083 :       || unsetenv("BASH_ENV");
     521            1083 :   if (rc)
     522                 :     {
     523               0 :       const char* e = strerror (errno);
     524               0 :       cerr << "unsetenv failed: " << e << endl;
     525                 :     }
     526                 : 
     527            1083 :   s.kernel_base_release.assign(s.kernel_release, 0, s.kernel_release.find('-'));
     528                 : 
     529                 :   // arguments parsed; get down to business
     530            1083 :   if (s.verbose > 1)
     531               2 :     version ();
     532                 : 
     533                 :   // Create a temporary directory to build within.
     534                 :   // Be careful with this, as "s.tmpdir" is "rm -rf"'d at the end.
     535                 :   {
     536            1083 :     const char* tmpdir_env = getenv("TMPDIR");
     537            1083 :     if (! tmpdir_env)
     538            1082 :       tmpdir_env = "/tmp";
     539                 :     
     540            1083 :     string stapdir = "/stapXXXXXX";
     541            1083 :     string tmpdirt = tmpdir_env + stapdir;
     542            1083 :     mode_t mask = umask(0);
     543            1083 :     const char* tmpdir = mkdtemp((char *)tmpdirt.c_str());
     544            1083 :     umask(mask);
     545            1083 :     if (! tmpdir)
     546                 :       {
     547               1 :         const char* e = strerror (errno);
     548               1 :         cerr << "ERROR: cannot create temporary directory (\"" << tmpdirt << "\"): " << e << endl;
     549               1 :         exit (1); // die
     550                 :       }
     551                 :     else
     552            1082 :       s.tmpdir = tmpdir;
     553                 : 
     554            1082 :     if (s.verbose>1)
     555               2 :       clog << "Created temporary directory \"" << s.tmpdir << "\"" << endl;
     556                 :   }
     557                 : 
     558                 :   // Create the name of the C source file within the temporary
     559                 :   // directory.
     560            1082 :   s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c";
     561                 : 
     562                 :   // Set up our handler to catch routine signals, to allow clean 
     563                 :   // and reasonably timely exit.
     564            1082 :   signal (SIGHUP, handle_interrupt);
     565            1082 :   signal (SIGPIPE, handle_interrupt);
     566            1082 :   signal (SIGINT, handle_interrupt);
     567            1082 :   signal (SIGTERM, handle_interrupt);
     568                 : 
     569                 :   struct tms tms_before;
     570            1082 :   times (& tms_before);
     571                 :   struct timeval tv_before;
     572            1082 :   gettimeofday (&tv_before, NULL);
     573                 : 
     574                 :   // PASS 1a: PARSING USER SCRIPT
     575                 : 
     576                 :   struct stat user_file_stat;
     577            1082 :   int user_file_stat_rc = -1;
     578                 : 
     579            1082 :   if (script_file == "-")
     580                 :     {
     581             221 :       s.user_file = parser::parse (s, cin, s.guru_mode);
     582             221 :       user_file_stat_rc = fstat (STDIN_FILENO, & user_file_stat);
     583                 :     }
     584             861 :   else if (script_file != "")
     585                 :     {
     586             796 :       s.user_file = parser::parse (s, script_file, s.guru_mode);
     587             796 :       user_file_stat_rc = stat (script_file.c_str(), & user_file_stat);
     588                 :     }
     589                 :   else
     590                 :     {
     591              65 :       istringstream ii (cmdline_script);
     592              65 :       s.user_file = parser::parse (s, ii, s.guru_mode);
     593                 :     }
     594            1082 :   if (s.user_file == 0)
     595                 :     // syntax errors already printed
     596              80 :     rc ++;
     597                 : 
     598                 :   // Construct arch / kernel-versioning search path
     599            1082 :   vector<string> version_suffixes;
     600            1082 :   string kvr = s.kernel_release;
     601            1082 :   const string& arch = s.architecture;
     602                 :   // add full kernel-version-release (2.6.NN-FOOBAR) + arch
     603            1082 :   version_suffixes.push_back ("/" + kvr + "/" + arch);
     604            1082 :   version_suffixes.push_back ("/" + kvr);
     605                 :   // add kernel version (2.6.NN) + arch
     606            1082 :   if (kvr != s.kernel_base_release) {
     607            1082 :     kvr = s.kernel_base_release;
     608            1082 :     version_suffixes.push_back ("/" + kvr + "/" + arch);
     609            1082 :     version_suffixes.push_back ("/" + kvr);
     610                 :   }
     611                 :   // add kernel family (2.6) + arch
     612            1082 :   string::size_type dot1_index = kvr.find ('.');
     613            1082 :   string::size_type dot2_index = kvr.rfind ('.');
     614            3246 :   while (dot2_index > dot1_index && dot2_index != string::npos) {
     615            1082 :     kvr.erase(dot2_index);
     616            1082 :     version_suffixes.push_back ("/" + kvr + "/" + arch);
     617            1082 :     version_suffixes.push_back ("/" + kvr);
     618            1082 :     dot2_index = kvr.rfind ('.');
     619                 :   }
     620                 :   // add architecture search path
     621            1082 :   version_suffixes.push_back("/" + arch);
     622                 :   // add empty string as last element
     623            1082 :   version_suffixes.push_back ("");
     624                 : 
     625                 :   // PASS 1b: PARSING LIBRARY SCRIPTS
     626            2166 :   for (unsigned i=0; i<s.include_path.size(); i++)
     627                 :     {
     628                 :       // now iterate upon it
     629            9756 :       for (unsigned k=0; k<version_suffixes.size(); k++)
     630                 :         {
     631                 :           glob_t globbuf;
     632            8672 :           string dir = s.include_path[i] + version_suffixes[k] + "/*.stp";
     633            8672 :           int r = glob(dir.c_str (), 0, NULL, & globbuf);
     634            8672 :           if (r == GLOB_NOSPACE || r == GLOB_ABORTED)
     635               0 :             rc ++;
     636                 :           // GLOB_NOMATCH is acceptable
     637                 : 
     638            8672 :           if (s.verbose>1 && globbuf.gl_pathc > 0)
     639                 :             clog << "Searched '" << dir << "', "
     640               4 :                  << "found " << globbuf.gl_pathc << endl;
     641                 : 
     642           49794 :           for (unsigned j=0; j<globbuf.gl_pathc; j++)
     643                 :             {
     644           41122 :               if (pending_interrupts)
     645               0 :                 break;
     646                 : 
     647                 :               // XXX: privilege only for /usr/share/systemtap?
     648           41122 :               stapfile* f = parser::parse (s, globbuf.gl_pathv[j], true);
     649           41122 :               if (f == 0)
     650               0 :                 rc ++;
     651                 :               else
     652           41122 :                 s.library_files.push_back (f);
     653                 : 
     654                 :               struct stat tapset_file_stat;
     655           41122 :               int stat_rc = stat (globbuf.gl_pathv[j], & tapset_file_stat);
     656           41122 :               if (stat_rc == 0 && user_file_stat_rc == 0 &&
     657                 :                   user_file_stat.st_dev == tapset_file_stat.st_dev &&
     658                 :                   user_file_stat.st_ino == tapset_file_stat.st_ino)
     659                 :                 {
     660                 :                   clog << "usage error: tapset file '" << globbuf.gl_pathv[j]
     661               1 :                        << "' cannot be run directly as a session script." << endl;
     662               1 :                   rc ++;
     663                 :                 }
     664                 : 
     665                 :             }
     666                 : 
     667            8672 :           globfree (& globbuf);
     668                 :         }
     669                 :     }
     670                 : 
     671            1082 :   if (rc == 0 && s.last_pass == 1)
     672                 :     {
     673             516 :       cout << "# parse tree dump" << endl;
     674             516 :       s.user_file->print (cout);
     675             516 :       cout << endl;
     676             516 :       if (s.verbose)
     677              39 :         for (unsigned i=0; i<s.library_files.size(); i++)
     678                 :           {
     679              38 :             s.library_files[i]->print (cout);
     680              38 :             cout << endl;
     681                 :           }
     682                 :     }
     683                 : 
     684                 :   struct tms tms_after;
     685            1082 :   times (& tms_after);
     686            1082 :   unsigned _sc_clk_tck = sysconf (_SC_CLK_TCK);
     687                 :   struct timeval tv_after;
     688            1082 :   gettimeofday (&tv_after, NULL);
     689                 : 
     690                 : #define TIMESPRINT \
     691                 :            (tms_after.tms_cutime + tms_after.tms_utime \
     692                 :             - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck) << "usr/" \
     693                 :         << (tms_after.tms_cstime + tms_after.tms_stime \
     694                 :             - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck) << "sys/" \
     695                 :         << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 + \
     696                 :             ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms."
     697                 : 
     698                 :   // syntax errors, if any, are already printed
     699            1082 :   if (s.verbose)
     700                 :     {
     701                 :       clog << "Pass 1: parsed user script and "
     702                 :            << s.library_files.size()
     703                 :            << " library script(s) in "
     704                 :            << TIMESPRINT
     705              55 :            << endl;
     706                 :     }
     707                 : 
     708            1082 :   if (rc)
     709                 :     cerr << "Pass 1: parse failed.  "
     710                 :          << "Try again with more '-v' (verbose) options."
     711              81 :          << endl;
     712                 : 
     713            1082 :   if (rc || s.last_pass == 1 || pending_interrupts) goto cleanup;
     714                 : 
     715             485 :   times (& tms_before);
     716             485 :   gettimeofday (&tv_before, NULL);
     717                 : 
     718                 :   // PASS 2: ELABORATION
     719             485 :   rc = semantic_pass (s);
     720                 : 
     721             485 :   if (rc == 0 && s.last_pass == 2)
     722              44 :     printscript(s, cout);
     723                 : 
     724             485 :   times (& tms_after);
     725             485 :   gettimeofday (&tv_after, NULL);
     726                 : 
     727             485 :   if (s.verbose) clog << "Pass 2: analyzed script: "
     728                 :                       << s.probes.size() << " probe(s), "
     729                 :                       << s.functions.size() << " function(s), "
     730                 :                       << s.embeds.size() << " embed(s), "
     731                 :                       << s.globals.size() << " global(s) in "
     732                 :                       << TIMESPRINT
     733              54 :                       << endl;
     734                 : 
     735             485 :   if (rc)
     736                 :     cerr << "Pass 2: analysis failed.  "
     737                 :          << "Try again with more '-v' (verbose) options."
     738              87 :          << endl;
     739                 :   // Generate hash.  There isn't any point in generating the hash
     740                 :   // if last_pass is 2, since we'll quit before using it.
     741             398 :   else if (s.last_pass != 2 && s.use_cache)
     742                 :     {
     743             347 :       ostringstream o;
     744                 :       unsigned saved_verbose;
     745                 : 
     746                 :       {
     747                 :         // Make sure we're in verbose mode, so that printscript()
     748                 :         // will output function/probe bodies.
     749             347 :         saved_verbose = s.verbose;
     750             347 :         s.verbose = 3;
     751             347 :         printscript(s, o);  // Print script to 'o'
     752             347 :         s.verbose = saved_verbose;
     753                 :       }
     754                 : 
     755                 :       // Generate hash
     756             347 :       find_hash (s, o.str());
     757                 : 
     758                 :       // See if we can use cached source/module.
     759             347 :       if (get_from_cache(s))
     760                 :         {
     761                 :           // If our last pass isn't 5, we're done (since passes 3 and
     762                 :           // 4 just generate what we just pulled out of the cache).
     763              77 :           if (s.last_pass < 5 || pending_interrupts) goto cleanup;
     764                 : 
     765                 :           // Short-circuit to pass 5.
     766              65 :           goto pass_5;
     767               0 :         }
     768                 :     }
     769                 : 
     770             414 :   if (rc || s.last_pass == 2 || pending_interrupts) goto cleanup;
     771                 : 
     772                 :   // PASS 3: TRANSLATION
     773                 : 
     774             283 :   times (& tms_before);
     775             283 :   gettimeofday (&tv_before, NULL);
     776                 : 
     777             283 :   rc = translate_pass (s);
     778                 : 
     779             283 :   if (rc == 0 && s.last_pass == 3)
     780                 :     {
     781              10 :       ifstream i (s.translated_source.c_str());
     782              10 :       cout << i.rdbuf();
     783                 :     }
     784                 : 
     785             283 :   times (& tms_after);
     786             283 :   gettimeofday (&tv_after, NULL);
     787                 : 
     788             283 :   if (s.verbose) clog << "Pass 3: translated to C into \""
     789                 :                       << s.translated_source
     790                 :                       << "\" in "
     791                 :                       << TIMESPRINT
     792              41 :                       << endl;
     793                 : 
     794             283 :   if (rc)
     795                 :     cerr << "Pass 3: translation failed.  "
     796                 :          << "Try again with more '-v' (verbose) options."
     797               3 :          << endl;
     798                 : 
     799             283 :   if (rc || s.last_pass == 3 || pending_interrupts) goto cleanup;
     800                 : 
     801                 :   // PASS 4: COMPILATION
     802             270 :   times (& tms_before);
     803             270 :   gettimeofday (&tv_before, NULL);
     804             270 :   rc = compile_pass (s);
     805                 : 
     806             270 :   if (rc == 0 && s.last_pass == 4)
     807             129 :     cout << s.hash_path << endl;
     808                 : 
     809             270 :   times (& tms_after);
     810             270 :   gettimeofday (&tv_after, NULL);
     811                 : 
     812             270 :   if (s.verbose) clog << "Pass 4: compiled C into \""
     813                 :                       << s.module_name << ".ko"
     814                 :                       << "\" in "
     815                 :                       << TIMESPRINT
     816              41 :                       << endl;
     817                 : 
     818             270 :   if (rc)
     819                 :     cerr << "Pass 4: compilation failed.  "
     820                 :          << "Try again with more '-v' (verbose) options."
     821               2 :          << endl;
     822                 :   else
     823                 :     {
     824                 :       // Update cache.
     825             268 :       if (s.use_cache)
     826             261 :         add_to_cache(s);
     827                 : 
     828                 :       // Copy module to the current directory.
     829             268 :       if (save_module && !pending_interrupts)
     830                 :         {
     831               5 :           string module_src_path = s.tmpdir + "/" + s.module_name + ".ko";
     832               5 :           string module_dest_path = s.module_name + ".ko";
     833                 : 
     834               5 :           if (s.verbose > 1)
     835                 :             clog << "Copying " << module_src_path << " to "
     836               0 :                  << module_dest_path << endl;
     837               5 :           if (copy_file(module_src_path.c_str(), module_dest_path.c_str()) != 0)
     838                 :             cerr << "Copy failed (\"" << module_src_path << "\" to \""
     839               0 :                  << module_dest_path << "\"): " << strerror(errno) << endl;
     840                 :         }
     841                 :     }
     842                 : 
     843             270 :   if (rc || s.last_pass == 4 || pending_interrupts) goto cleanup;
     844                 : 
     845                 : 
     846                 :   // PASS 5: RUN
     847             204 : pass_5:
     848             204 :   times (& tms_before);
     849             204 :   gettimeofday (&tv_before, NULL);
     850                 :   // NB: this message is a judgement call.  The other passes don't emit
     851                 :   // a "hello, I'm starting" message, but then the others aren't interactive
     852                 :   // and don't take an indefinite amount of time.
     853             204 :   if (s.verbose) clog << "Pass 5: starting run." << endl;
     854             204 :   rc = run_pass (s);
     855             204 :   times (& tms_after);
     856             204 :   gettimeofday (&tv_after, NULL);
     857             204 :   if (s.verbose) clog << "Pass 5: run completed in "
     858                 :                       << TIMESPRINT
     859              31 :                       << endl;
     860                 : 
     861             204 :   if (rc)
     862                 :     cerr << "Pass 5: run failed.  "
     863                 :          << "Try again with more '-v' (verbose) options."
     864               1 :          << endl;
     865                 : 
     866                 :   // if (rc) goto cleanup;
     867                 : 
     868            1082 :  cleanup:
     869                 : 
     870                 :   // update the database information
     871            1082 :   if (!rc && s.tapset_compile_coverage && !pending_interrupts) {
     872                 : #ifdef HAVE_LIBSQLITE3
     873               0 :     update_coverage_db(s);
     874                 : #else
     875                 :     cerr << "Coverage database not available without libsqlite3" << endl;
     876                 : #endif
     877                 :   }
     878                 : 
     879                 :   // Clean up temporary directory.  Obviously, be careful with this.
     880            1082 :   if (s.tmpdir == "")
     881                 :     ; // do nothing
     882                 :   else
     883                 :     {
     884            1082 :       if (s.keep_tmpdir)
     885               1 :         clog << "Keeping temporary directory \"" << s.tmpdir << "\"" << endl;
     886                 :       else
     887                 :         {
     888            1081 :           string cleanupcmd = "rm -rf ";
     889            1081 :           cleanupcmd += s.tmpdir;
     890            1081 :           if (s.verbose>1) clog << "Running " << cleanupcmd << endl;
     891            1081 :           int status = system (cleanupcmd.c_str());
     892            1081 :           if (status != 0 && s.verbose>1)
     893               0 :             clog << "Cleanup command failed, status: " << status << endl;
     894                 :         }
     895                 :     }
     896                 : 
     897            1082 :   return (rc||pending_interrupts) ? EXIT_FAILURE : EXIT_SUCCESS;
     898            2188 : }

Generated by: LTP GCOV extension version 1.5