LCOV - code coverage report
Current view: top level - mnt/wasteland/wcohen/systemtap_write/systemtap - buildrun.cxx (source / functions) Hit Total Coverage
Test: stap.info Lines: 351 501 70.1 %
Date: 2013-03-08 Functions: 18 23 78.3 %
Branches: 691 1956 35.3 %

           Branch data     Line data    Source code
       1                 :            : // build/run probes
       2                 :            : // Copyright (C) 2005-2013 Red Hat Inc.
       3                 :            : //
       4                 :            : // This file is part of systemtap, and is free software.  You can
       5                 :            : // redistribute it and/or modify it under the terms of the GNU General
       6                 :            : // Public License (GPL); either version 2, or (at your option) any
       7                 :            : // later version.
       8                 :            : 
       9                 :            : #include "config.h"
      10                 :            : #include "buildrun.h"
      11                 :            : #include "session.h"
      12                 :            : #include "util.h"
      13                 :            : #include "hash.h"
      14                 :            : #include "translate.h"
      15                 :            : 
      16                 :            : #include <cstdlib>
      17                 :            : #include <fstream>
      18                 :            : #include <sstream>
      19                 :            : 
      20                 :            : extern "C" {
      21                 :            : #include <signal.h>
      22                 :            : #include <sys/wait.h>
      23                 :            : #include <pwd.h>
      24                 :            : #include <grp.h>
      25                 :            : #include <sys/types.h>
      26                 :            : #include <sys/stat.h>
      27                 :            : #include <unistd.h>
      28                 :            : #include <string.h>
      29                 :            : #include <errno.h>
      30                 :            : }
      31                 :            : 
      32                 :            : 
      33                 :            : using namespace std;
      34                 :            : 
      35                 :            : /* Adjust and run make_cmd to build a kernel module. */
      36                 :            : static int
      37                 :        622 : run_make_cmd(systemtap_session& s, vector<string>& make_cmd,
      38                 :            :              bool null_out=false, bool null_err=false)
      39                 :            : {
      40                 :        622 :   assert_no_interrupts();
      41                 :            : 
      42                 :            :   // PR14168: we used to unsetenv values here; instead do it via
      43                 :            :   // env(1) in make_any_make_cmd().
      44                 :            : 
      45                 :            :   // Disable ccache to avoid saving files that will never be reused.
      46                 :            :   // (ccache is useless to us, because our compiler commands always
      47                 :            :   // include the randomized tmpdir path.)
      48                 :            :   // It's not critical if this fails, so the return is ignored.
      49                 :        622 :   (void) setenv("CCACHE_DISABLE", "1", 0);
      50                 :            : 
      51         [ +  + ]:        622 :   if (s.verbose > 2)
      52 [ +  - ][ +  - ]:          1 :     make_cmd.push_back("V=1");
                 [ +  - ]
      53         [ +  + ]:        621 :   else if (s.verbose > 1)
      54 [ +  - ][ +  - ]:         15 :     make_cmd.push_back("--no-print-directory");
                 [ +  - ]
      55                 :            :   else
      56                 :            :     {
      57 [ +  - ][ +  - ]:        606 :       make_cmd.push_back("-s");
                 [ +  - ]
      58 [ +  - ][ +  - ]:        606 :       make_cmd.push_back("--no-print-directory");
                 [ +  - ]
      59                 :            :     }
      60                 :            : 
      61                 :            :   // Exploit SMP parallelism, if available.
      62                 :        622 :   long smp = sysconf(_SC_NPROCESSORS_ONLN);
      63         [ +  - ]:        622 :   if (smp >= 1)
      64 [ +  - ][ +  - ]:        622 :     make_cmd.push_back("-j" + lex_cast(smp+1));
         [ +  - ][ +  - ]
                 [ +  - ]
      65                 :            : 
      66         [ -  + ]:        622 :   if (strverscmp (s.kernel_base_release.c_str(), "2.6.29") < 0)
      67                 :            :     {
      68                 :            :       // Older kernels, before linux commit #fd54f502841c1, include
      69                 :            :       // gratuitous "echo"s in their Makefile.  We need to suppress
      70                 :            :       // that with this bluntness.
      71                 :          0 :       null_out = true;
      72                 :            :     }
      73                 :            : 
      74 [ +  - ][ +  - ]:        622 :   int rc = stap_system (s.verbose, "kbuild", make_cmd, null_out, null_err);
                 [ +  - ]
      75         [ +  + ]:        622 :   if (rc != 0)
      76                 :          5 :     s.set_try_server ();
      77                 :        622 :   return rc;
      78                 :            : }
      79                 :            : 
      80                 :            : static vector<string>
      81                 :        622 : make_any_make_cmd(systemtap_session& s, const string& dir, const string& target)
      82                 :            : {
      83         [ +  - ]:        622 :   vector<string> make_cmd;
      84                 :            : 
      85                 :            :   // PR14168: sanitize environment variables for kbuild invocation
      86 [ +  - ][ +  - ]:        622 :   make_cmd.push_back("env");
                 [ +  - ]
      87 [ +  - ][ +  - ]:        622 :   make_cmd.push_back("-uARCH");
                 [ +  - ]
      88 [ +  - ][ +  - ]:        622 :   make_cmd.push_back("-uKBUILD_EXTMOD");
                 [ +  - ]
      89 [ +  - ][ +  - ]:        622 :   make_cmd.push_back("-uCROSS_COMPILE");
                 [ +  - ]
      90 [ +  - ][ +  - ]:        622 :   make_cmd.push_back("-uKBUILD_IMAGE");
                 [ +  - ]
      91 [ +  - ][ +  - ]:        622 :   make_cmd.push_back("-uKCONFIG_CONFIG");
                 [ +  - ]
      92 [ +  - ][ +  - ]:        622 :   make_cmd.push_back("-uINSTALL_PATH");
                 [ +  - ]
      93 [ +  - ][ +  - ]:        622 :   string newpath = string("PATH=/usr/bin:/bin:") + (getenv("PATH") ?: "");
         [ +  - ][ +  - ]
      94 [ +  - ][ +  - ]:        622 :   make_cmd.push_back(newpath.c_str());
         [ +  - ][ +  - ]
      95                 :            : 
      96 [ +  - ][ +  - ]:        622 :   make_cmd.push_back("make");
                 [ +  - ]
      97 [ +  - ][ +  - ]:        622 :   make_cmd.push_back("-C");
                 [ +  - ]
      98         [ +  - ]:        622 :   make_cmd.push_back(s.kernel_build_tree);
      99 [ +  - ][ +  - ]:        622 :   make_cmd.push_back("M=" + dir); // need make-quoting?
                 [ +  - ]
     100         [ +  - ]:        622 :   make_cmd.push_back(target);
     101                 :            : 
     102                 :            :   // Add architecture, except for old powerpc (RHBZ669082)
     103         [ +  - ]:        622 :   if (s.architecture != "powerpc" ||
           [ -  +  #  # ]
                 [ +  - ]
     104         [ #  # ]:          0 :       (strverscmp (s.kernel_base_release.c_str(), "2.6.15") >= 0))
     105 [ +  - ][ +  - ]:        622 :     make_cmd.push_back("ARCH=" + s.architecture); // need make-quoting?
                 [ +  - ]
     106                 :            : 
     107                 :            :   // PR13847: suppress debuginfo creation by default
     108 [ +  - ][ +  - ]:        622 :   make_cmd.insert(make_cmd.end(), "CONFIG_DEBUG_INFO=");
         [ +  - ][ +  - ]
     109                 :            : 
     110                 :            :   // Add any custom kbuild flags
     111 [ +  - ][ +  - ]:        622 :   make_cmd.insert(make_cmd.end(), s.kbuildflags.begin(), s.kbuildflags.end());
         [ +  - ][ +  - ]
     112                 :            : 
     113         [ +  - ]:        622 :   return make_cmd;
     114                 :            : }
     115                 :            : 
     116                 :            : static vector<string>
     117                 :        621 : make_make_cmd(systemtap_session& s, const string& dir)
     118                 :            : {
     119 [ +  - ][ +  - ]:        621 :   return make_any_make_cmd(s, dir, "modules");
                 [ +  - ]
     120                 :            : }
     121                 :            : 
     122                 :            : static vector<string>
     123                 :          1 : make_make_objs_cmd(systemtap_session& s, const string& dir)
     124                 :            : {
     125                 :            :   // Kbuild uses these rules to build external modules:
     126                 :            :   //
     127                 :            :   //   module-dirs := $(addprefix _module_,$(KBUILD_EXTMOD))
     128                 :            :   //   modules: $(module-dirs)
     129                 :            :   //       @$(kecho) '  Building modules, stage 2.';
     130                 :            :   //       $(Q)$(MAKE) -f $(srctree)/scripts/Makefile.modpost
     131                 :            :   //
     132                 :            :   // So if we're only interested in the stage 1 objects, we can
     133                 :            :   // cheat and make only the $(module-dirs) part.
     134         [ +  - ]:          1 :   return make_any_make_cmd(s, dir, "_module_" + dir);
     135                 :            : }
     136                 :            : 
     137                 :            : static void
     138                 :      30086 : output_autoconf(systemtap_session& s, ofstream& o, const char *autoconf_c,
     139                 :            :                 const char *deftrue, const char *deffalse)
     140                 :            : {
     141                 :      30086 :   o << "\t";
     142         [ +  - ]:      30086 :   if (s.verbose < 4)
     143                 :      30086 :     o << "@";
     144                 :      30086 :   o << "if $(CHECK_BUILD) $(SYSTEMTAP_RUNTIME)/linux/" << autoconf_c;
     145         [ +  - ]:      30086 :   if (s.verbose < 5)
     146                 :      30086 :     o << " > /dev/null 2>&1";
     147                 :      30086 :   o << "; then ";
     148         [ +  - ]:      30086 :   if (deftrue)
     149                 :      30086 :     o << "echo \"#define " << deftrue << " 1\"";
     150         [ -  + ]:      30086 :   if (deffalse)
     151                 :          0 :     o << "; else echo \"#define " << deffalse << " 1\"";
     152                 :      30086 :   o << "; fi >> $@" << endl;
     153                 :      30086 : }
     154                 :            : 
     155                 :            : 
     156                 :      11666 : void output_exportconf(systemtap_session& s, ofstream& o, const char *symbol,
     157                 :            :                      const char *deftrue)
     158                 :            : {
     159                 :      11666 :   o << "\t";
     160         [ +  - ]:      11666 :   if (s.verbose < 4)
     161                 :      11666 :     o << "@";
     162 [ +  - ][ +  - ]:      11666 :   if (s.kernel_exports.find(symbol) != s.kernel_exports.end())
         [ +  - ][ +  - ]
                 [ +  + ]
     163                 :       4298 :     o << "echo \"#define " << deftrue << " 1\"";
     164                 :      11666 :   o << ">> $@" << endl;
     165                 :      11666 : }
     166                 :            : 
     167                 :            : 
     168                 :       1842 : void output_dual_exportconf(systemtap_session& s, ofstream& o,
     169                 :            :                             const char *symbol1, const char *symbol2,
     170                 :            :                             const char *deftrue)
     171                 :            : {
     172                 :       1842 :   o << "\t";
     173         [ +  - ]:       1842 :   if (s.verbose < 4)
     174                 :       1842 :     o << "@";
     175 [ +  - ][ +  - ]:       5526 :   if (s.kernel_exports.find(symbol1) != s.kernel_exports.end()
                 [ +  - ]
           [ +  -  +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  -  
          #  #  #  #  #  
                #  #  # ]
     176 [ +  - ][ +  - ]:       3684 :       && s.kernel_exports.find(symbol2) != s.kernel_exports.end())
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
           [ #  #  #  #  
             #  #  #  # ]
     177                 :       1842 :     o << "echo \"#define " << deftrue << " 1\"";
     178                 :       1842 :   o << ">> $@" << endl;
     179                 :       1842 : }
     180                 :            : 
     181                 :            : 
     182                 :       1228 : void output_either_exportconf(systemtap_session& s, ofstream& o,
     183                 :            :                               const char *symbol1, const char *symbol2,
     184                 :            :                               const char *deftrue)
     185                 :            : {
     186                 :       1228 :   o << "\t";
     187         [ +  - ]:       1228 :   if (s.verbose < 4)
     188                 :       1228 :     o << "@";
     189 [ +  - ][ +  - ]:       3684 :   if (s.kernel_exports.find(symbol1) != s.kernel_exports.end()
                 [ +  - ]
           [ +  -  -  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ -  +  
          #  #  #  #  #  
                #  #  # ]
     190 [ +  - ][ +  - ]:       2456 :       || s.kernel_exports.find(symbol2) != s.kernel_exports.end())
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
           [ #  #  #  #  
             #  #  #  # ]
     191                 :          0 :     o << "echo \"#define " << deftrue << " 1\"";
     192                 :       1228 :   o << ">> $@" << endl;
     193                 :       1228 : }
     194                 :            : 
     195                 :            : 
     196                 :            : static int
     197                 :          0 : compile_dyninst (systemtap_session& s)
     198                 :            : {
     199 [ #  # ][ #  # ]:          0 :   const string module = s.tmpdir + "/" + s.module_filename();
         [ #  # ][ #  # ]
                 [ #  # ]
     200                 :            : 
     201         [ #  # ]:          0 :   vector<string> cmd;
     202 [ #  # ][ #  # ]:          0 :   cmd.push_back("gcc");
                 [ #  # ]
     203 [ #  # ][ #  # ]:          0 :   cmd.push_back("--std=gnu99");
                 [ #  # ]
     204 [ #  # ][ #  # ]:          0 :   cmd.push_back("-Wall");
                 [ #  # ]
     205 [ #  # ][ #  # ]:          0 :   cmd.push_back("-Werror");
                 [ #  # ]
     206 [ #  # ][ #  # ]:          0 :   cmd.push_back("-Wno-unused");
                 [ #  # ]
     207 [ #  # ][ #  # ]:          0 :   cmd.push_back("-Wno-strict-aliasing");
                 [ #  # ]
     208 [ #  # ][ #  # ]:          0 :   cmd.push_back("-O2");
                 [ #  # ]
     209 [ #  # ][ #  # ]:          0 :   cmd.push_back("-I" + s.runtime_path);
                 [ #  # ]
     210 [ #  # ][ #  # ]:          0 :   cmd.push_back("-D__DYNINST__");
                 [ #  # ]
     211         [ #  # ]:          0 :   for (size_t i = 0; i < s.c_macros.size(); ++i)
     212 [ #  # ][ #  # ]:          0 :     cmd.push_back("-D" + s.c_macros[i]);
                 [ #  # ]
     213         [ #  # ]:          0 :   cmd.push_back(s.translated_source);
     214 [ #  # ][ #  # ]:          0 :   cmd.push_back("-pthread");
                 [ #  # ]
     215 [ #  # ][ #  # ]:          0 :   cmd.push_back("-lrt");
                 [ #  # ]
     216 [ #  # ][ #  # ]:          0 :   cmd.push_back("-fPIC");
                 [ #  # ]
     217 [ #  # ][ #  # ]:          0 :   cmd.push_back("-shared");
                 [ #  # ]
     218 [ #  # ][ #  # ]:          0 :   cmd.push_back("-o");
                 [ #  # ]
     219         [ #  # ]:          0 :   cmd.push_back(module);
     220         [ #  # ]:          0 :   if (s.verbose > 3)
     221                 :            :     {
     222 [ #  # ][ #  # ]:          0 :       cmd.push_back("-ftime-report");
                 [ #  # ]
     223 [ #  # ][ #  # ]:          0 :       cmd.push_back("-Q");
                 [ #  # ]
     224                 :            :     }
     225                 :            : 
     226         [ #  # ]:          0 :   int rc = stap_system (s.verbose, cmd);
     227         [ #  # ]:          0 :   if (rc)
     228         [ #  # ]:          0 :     s.set_try_server ();
     229 [ #  # ][ #  # ]:          0 :   return rc;
     230                 :            : }
     231                 :            : 
     232                 :            : 
     233                 :            : int
     234                 :        624 : compile_pass (systemtap_session& s)
     235                 :            : {
     236         [ -  + ]:        624 :   if (s.runtime_usermode_p())
     237         [ #  # ]:          0 :     return compile_dyninst (s);
     238                 :            : 
     239         [ +  - ]:        624 :   int rc = uprobes_pass (s);
     240         [ +  + ]:        624 :   if (rc)
     241                 :            :     {
     242         [ +  - ]:         10 :       s.set_try_server ();
     243                 :         10 :       return rc;
     244                 :            :     }
     245                 :            : 
     246                 :            :   // fill in a quick Makefile
     247         [ +  - ]:        614 :   string makefile_nm = s.tmpdir + "/Makefile";
     248 [ +  - ][ +  - ]:        614 :   ofstream o (makefile_nm.c_str());
     249                 :            : 
     250                 :            :   // Create makefile
     251                 :            : 
     252                 :            :   // Clever hacks copied from vmware modules
     253         [ +  - ]:        614 :   string superverbose;
     254         [ -  + ]:        614 :   if (s.verbose > 3)
     255         [ #  # ]:          0 :     superverbose = "set -x;";
     256                 :            : 
     257         [ +  - ]:        614 :   string redirecterrors = "> /dev/null 2>&1";
     258         [ -  + ]:        614 :   if (s.verbose > 6)
     259         [ #  # ]:          0 :     redirecterrors = "";
     260                 :            : 
     261                 :            :   // Support O= (or KBUILD_OUTPUT) option
     262 [ +  - ][ +  - ]:        614 :   o << "_KBUILD_CFLAGS := $(call flags,KBUILD_CFLAGS)" << endl;
     263                 :            : 
     264 [ +  - ][ +  - ]:        614 :   o << "stap_check_gcc = $(shell " << superverbose << " if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo \"$(1)\"; else echo \"$(2)\"; fi)" << endl;
         [ +  - ][ +  - ]
     265 [ +  - ][ +  - ]:        614 :   o << "CHECK_BUILD := $(CC) $(NOSTDINC_FLAGS) $(KBUILD_CPPFLAGS) $(CPPFLAGS) $(LINUXINCLUDE) $(_KBUILD_CFLAGS) $(CFLAGS_KERNEL) $(EXTRA_CFLAGS) $(CFLAGS) -DKBUILD_BASENAME=\\\"" << s.module_name << "\\\"" << (s.omit_werror ? "" : " -Werror") << " -S -o /dev/null -xc " << endl;
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
                 [ +  - ]
     266 [ +  - ][ +  - ]:        614 :   o << "stap_check_build = $(shell " << superverbose << " if $(CHECK_BUILD) $(1) " << redirecterrors << " ; then echo \"$(2)\"; else echo \"$(3)\"; fi)" << endl;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     267                 :            : 
     268 [ +  - ][ +  - ]:        614 :   o << "SYSTEMTAP_RUNTIME = \"" << s.runtime_path << "\"" << endl;
         [ +  - ][ +  - ]
     269                 :            : 
     270                 :            :   // "autoconf" options go here
     271                 :            : 
     272                 :            :   // RHBZ 543529: early rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
     273 [ +  - ][ +  - ]:        614 :   o << "CONFIG_MODULE_SIG := n" << endl;
     274                 :            : 
     275         [ +  - ]:        614 :   string module_cflags = "EXTRA_CFLAGS";
     276 [ +  - ][ +  - ]:        614 :   o << module_cflags << " :=" << endl;
                 [ +  - ]
     277                 :            : 
     278                 :            :   // XXX: This gruesome hack is needed on some kernels built with separate O=directory,
     279                 :            :   // where files like 2.6.27 x86's asm/mach-*/mach_mpspec.h are not found on the cpp path.
     280                 :            :   // This could be a bug in arch/x86/Makefile that names
     281                 :            :   //      mflags-y += -Iinclude/asm-x86/mach-default
     282                 :            :   // but that path does not exist in an O= build tree.
     283 [ +  - ][ +  - ]:        614 :   o << module_cflags << " += -Iinclude2/asm/mach-default" << endl;
                 [ +  - ]
     284 [ +  - ][ +  + ]:        614 :   if (s.kernel_source_tree != "")
     285 [ +  - ][ +  - ]:         41 :     o << module_cflags << " += -I" + s.kernel_source_tree << endl;
         [ +  - ][ +  - ]
                 [ +  - ]
     286                 :            : 
     287                 :            :   // NB: don't try
     288                 :            :   // o << module_cflags << " += -Iusr/include" << endl;
     289                 :            :   // since such headers are cleansed of _KERNEL_ pieces that we need
     290                 :            : 
     291 [ +  - ][ +  - ]:        614 :   o << "STAPCONF_HEADER := " << s.tmpdir << "/" << s.stapconf_name << endl;
         [ +  - ][ +  - ]
                 [ +  - ]
     292 [ +  - ][ +  - ]:        614 :   o << "$(STAPCONF_HEADER):" << endl;
     293 [ +  - ][ +  - ]:        614 :   o << "\t@echo -n > $@" << endl;
     294         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-hrtimer-rel.c", "STAPCONF_HRTIMER_REL", NULL);
     295         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-generated-compile.c", "STAPCONF_GENERATED_COMPILE", NULL);
     296         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-hrtimer-getset-expires.c", "STAPCONF_HRTIMER_GETSET_EXPIRES", NULL);
     297         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-inode-private.c", "STAPCONF_INODE_PRIVATE", NULL);
     298         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-constant-tsc.c", "STAPCONF_CONSTANT_TSC", NULL);
     299         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-ktime-get-real.c", "STAPCONF_KTIME_GET_REAL", NULL);
     300         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-x86-uniregs.c", "STAPCONF_X86_UNIREGS", NULL);
     301         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-nameidata.c", "STAPCONF_NAMEIDATA_CLEANUP", NULL);
     302         [ +  - ]:        614 :   output_dual_exportconf(s, o, "unregister_kprobes", "unregister_kretprobes", "STAPCONF_UNREGISTER_KPROBES");
     303         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-kprobe-symbol-name.c", "STAPCONF_KPROBE_SYMBOL_NAME", NULL);
     304         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-real-parent.c", "STAPCONF_REAL_PARENT", NULL);
     305         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-uaccess.c", "STAPCONF_LINUX_UACCESS_H", NULL);
     306         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-oneachcpu-retry.c", "STAPCONF_ONEACHCPU_RETRY", NULL);
     307         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-dpath-path.c", "STAPCONF_DPATH_PATH", NULL);
     308         [ +  - ]:        614 :   output_exportconf(s, o, "synchronize_sched", "STAPCONF_SYNCHRONIZE_SCHED");
     309         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-task-uid.c", "STAPCONF_TASK_UID", NULL);
     310         [ +  - ]:        614 :   output_dual_exportconf(s, o, "alloc_vm_area", "free_vm_area", "STAPCONF_VM_AREA");
     311         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-procfs-owner.c", "STAPCONF_PROCFS_OWNER", NULL);
     312         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-alloc-percpu-align.c", "STAPCONF_ALLOC_PERCPU_ALIGN", NULL);
     313         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-x86-gs.c", "STAPCONF_X86_GS", NULL);
     314         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-grsecurity.c", "STAPCONF_GRSECURITY", NULL);
     315         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-trace-printk.c", "STAPCONF_TRACE_PRINTK", NULL);
     316         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-regset.c", "STAPCONF_REGSET", NULL);
     317         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-utrace-regset.c", "STAPCONF_UTRACE_REGSET", NULL);
     318         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-uprobe-get-pc.c", "STAPCONF_UPROBE_GET_PC", NULL);
     319         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-hlist-4args.c", "STAPCONF_HLIST_4ARGS", NULL);
     320         [ +  - ]:        614 :   output_exportconf(s, o, "tsc_khz", "STAPCONF_TSC_KHZ");
     321         [ +  - ]:        614 :   output_exportconf(s, o, "cpu_khz", "STAPCONF_CPU_KHZ");
     322         [ +  - ]:        614 :   output_exportconf(s, o, "__module_text_address", "STAPCONF_MODULE_TEXT_ADDRESS");
     323         [ +  - ]:        614 :   output_exportconf(s, o, "add_timer_on", "STAPCONF_ADD_TIMER_ON");
     324                 :            : 
     325         [ +  - ]:        614 :   output_dual_exportconf(s, o, "probe_kernel_read", "probe_kernel_write", "STAPCONF_PROBE_KERNEL");
     326                 :            :   output_autoconf(s, o, "autoconf-hw_breakpoint_context.c",
     327         [ +  - ]:        614 :                   "STAPCONF_HW_BREAKPOINT_CONTEXT", NULL);
     328                 :            :   output_autoconf(s, o, "autoconf-save-stack-trace.c",
     329         [ +  - ]:        614 :                   "STAPCONF_KERNEL_STACKTRACE", NULL);
     330                 :            :   output_autoconf(s, o, "autoconf-save-stack-trace-no-bp.c",
     331         [ +  - ]:        614 :                   "STAPCONF_KERNEL_STACKTRACE_NO_BP", NULL);
     332                 :            :   output_autoconf(s, o, "autoconf-asm-syscall.c",
     333         [ +  - ]:        614 :                   "STAPCONF_ASM_SYSCALL_H", NULL);
     334         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-ring_buffer-flags.c", "STAPCONF_RING_BUFFER_FLAGS", NULL);
     335         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-ring_buffer_lost_events.c", "STAPCONF_RING_BUFFER_LOST_EVENTS", NULL);
     336         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-ring_buffer_read_prepare.c", "STAPCONF_RING_BUFFER_READ_PREPARE", NULL);
     337         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-kallsyms-on-each-symbol.c", "STAPCONF_KALLSYMS_ON_EACH_SYMBOL", NULL);
     338         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-walk-stack.c", "STAPCONF_WALK_STACK", NULL);
     339                 :            :   output_autoconf(s, o, "autoconf-stacktrace_ops-warning.c",
     340         [ +  - ]:        614 :                   "STAPCONF_STACKTRACE_OPS_WARNING", NULL);
     341         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-mm-context-vdso.c", "STAPCONF_MM_CONTEXT_VDSO", NULL);
     342         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-mm-context-vdso-base.c", "STAPCONF_MM_CONTEXT_VDSO_BASE", NULL);
     343         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-blk-types.c", "STAPCONF_BLK_TYPES", NULL);
     344         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-perf-structpid.c", "STAPCONF_PERF_STRUCTPID", NULL);
     345                 :            :   output_autoconf(s, o, "perf_event_counter_context.c",
     346         [ +  - ]:        614 :                   "STAPCONF_PERF_COUNTER_CONTEXT", NULL);
     347                 :            :   output_autoconf(s, o, "perf_probe_handler_nmi.c",
     348         [ +  - ]:        614 :                   "STAPCONF_PERF_HANDLER_NMI", NULL);
     349         [ +  - ]:        614 :   output_exportconf(s, o, "path_lookup", "STAPCONF_PATH_LOOKUP");
     350         [ +  - ]:        614 :   output_exportconf(s, o, "kern_path_parent", "STAPCONF_KERN_PATH_PARENT");
     351         [ +  - ]:        614 :   output_exportconf(s, o, "vfs_path_lookup", "STAPCONF_VFS_PATH_LOOKUP");
     352         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-module-sect-attrs.c", "STAPCONF_MODULE_SECT_ATTRS", NULL);
     353                 :            : 
     354         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-utrace-via-tracepoints.c", "STAPCONF_UTRACE_VIA_TRACEPOINTS", NULL);
     355         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-task_work-struct.c", "STAPCONF_TASK_WORK_STRUCT", NULL);
     356         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-vm-area-pte.c", "STAPCONF_VM_AREA_PTE", NULL);
     357         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-relay-umode_t.c", "STAPCONF_RELAY_UMODE_T", NULL);
     358         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-fs_supers-hlist.c", "STAPCONF_FS_SUPERS_HLIST", NULL);
     359                 :            : 
     360                 :            :   // used by tapset/timestamp_monotonic.stp
     361         [ +  - ]:        614 :   output_exportconf(s, o, "cpu_clock", "STAPCONF_CPU_CLOCK");
     362         [ +  - ]:        614 :   output_exportconf(s, o, "local_clock", "STAPCONF_LOCAL_CLOCK");
     363                 :            : 
     364                 :            :   // used by runtime/uprobe-inode.c
     365                 :            :   output_either_exportconf(s, o, "uprobe_register", "register_uprobe",
     366         [ +  - ]:        614 :                            "STAPCONF_UPROBE_REGISTER_EXPORTED");
     367                 :            :   output_either_exportconf(s, o, "uprobe_unregister", "unregister_uprobe",
     368         [ +  - ]:        614 :                            "STAPCONF_UPROBE_UNREGISTER_EXPORTED");
     369         [ +  - ]:        614 :   output_exportconf(s, o, "uretprobe_register", "STAPCONF_URETPROBE_REGISTER_EXPORTED");
     370         [ +  - ]:        614 :   output_exportconf(s, o, "uretprobe_unregister", "STAPCONF_URETPROBE_UNREGISTER_EXPORTED");
     371         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-old-inode-uprobes.c", "STAPCONF_OLD_INODE_UPROBES", NULL);
     372         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-inode-uprobes-noaddr.c", "STAPCONF_INODE_UPROBES_NOADDR", NULL);
     373         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-inode-uretprobes.c", "STAPCONF_INODE_URETPROBES", NULL);
     374                 :            : 
     375                 :            :   // used by tapsets.cxx inode uprobe generated code
     376         [ +  - ]:        614 :   output_exportconf(s, o, "uprobe_get_swbp_addr", "STAPCONF_UPROBE_GET_SWBP_ADDR_EXPORTED");
     377                 :            : 
     378                 :            :   // used by runtime/loc2c-runtime.h
     379         [ +  - ]:        614 :   output_exportconf(s, o, "task_user_regset_view", "STAPCONF_TASK_USER_REGSET_VIEW_EXPORTED");
     380                 :            : 
     381                 :            :   // used by runtime/stp_utrace.c
     382         [ +  - ]:        614 :   output_exportconf(s, o, "task_work_add", "STAPCONF_TASK_WORK_ADD_EXPORTED");
     383         [ +  - ]:        614 :   output_exportconf(s, o, "signal_wake_up_state", "STAPCONF_SIGNAL_WAKE_UP_STATE_EXPORTED");
     384         [ +  - ]:        614 :   output_exportconf(s, o, "signal_wake_up", "STAPCONF_SIGNAL_WAKE_UP_EXPORTED");
     385         [ +  - ]:        614 :   output_exportconf(s, o, "__lock_task_sighand", "STAPCONF___LOCK_TASK_SIGHAND_EXPORTED");
     386                 :            : 
     387         [ +  - ]:        614 :   output_autoconf(s, o, "autoconf-pagefault_disable.c", "STAPCONF_PAGEFAULT_DISABLE", NULL);
     388         [ +  - ]:        614 :   output_exportconf(s, o, "kallsyms_lookup_name", "STAPCONF_KALLSYMS");
     389                 :            : 
     390 [ +  - ][ +  - ]:        614 :   o << module_cflags << " += -include $(STAPCONF_HEADER)" << endl;
                 [ +  - ]
     391                 :            : 
     392         [ +  + ]:        711 :   for (unsigned i=0; i<s.c_macros.size(); i++)
     393 [ +  - ][ +  - ]:         97 :     o << "EXTRA_CFLAGS += -D " << lex_cast_qstring(s.c_macros[i]) << endl; // XXX right quoting?
         [ +  - ][ +  - ]
                 [ +  - ]
     394                 :            : 
     395         [ -  + ]:        614 :   if (s.verbose > 3)
     396 [ #  # ][ #  # ]:          0 :     o << "EXTRA_CFLAGS += -ftime-report -Q" << endl;
     397                 :            : 
     398                 :            :   // XXX: unfortunately, -save-temps can't work since linux kbuild cwd
     399                 :            :   // is not writable.
     400                 :            :   //
     401                 :            :   // if (s.keep_tmpdir)
     402                 :            :   // o << "CFLAGS += -fverbose-asm -save-temps" << endl;
     403                 :            : 
     404                 :            :   // Kernels can be compiled with CONFIG_CC_OPTIMIZE_FOR_SIZE to select
     405                 :            :   // -Os, otherwise -O2 is the default.
     406 [ +  - ][ +  - ]:        614 :   o << "EXTRA_CFLAGS += -freorder-blocks" << endl; // improve on -Os
     407                 :            : 
     408                 :            :   // We used to allow the user to override default optimization when so
     409                 :            :   // requested by adding a -O[0123s] so they could determine the
     410                 :            :   // time/space/speed tradeoffs themselves, but we cannot guantantee that
     411                 :            :   // the (un)optimized code actually compiles and/or generates functional
     412                 :            :   // code, so we had to remove it.
     413                 :            :   // o << "EXTRA_CFLAGS += " << s.gcc_flags << endl; // Add -O[0123s]
     414                 :            : 
     415                 :            :   // o << "CFLAGS += -fno-unit-at-a-time" << endl;
     416                 :            : 
     417                 :            :   // 256 bytes should be enough for anybody
     418                 :            :   // XXX this doesn't validate varargs, per gcc bug #41633
     419 [ +  - ][ +  - ]:        614 :   o << "EXTRA_CFLAGS += $(call cc-option,-Wframe-larger-than=256)" << endl;
     420                 :            : 
     421                 :            :   // Assumes linux 2.6 kbuild
     422 [ +  - ][ -  + ]:        614 :   o << "EXTRA_CFLAGS += -Wno-unused" << (s.omit_werror ? "" : " -Werror") << endl;
         [ +  - ][ +  - ]
     423                 :            :   #if CHECK_POINTER_ARITH_PR5947
     424                 :            :   o << "EXTRA_CFLAGS += -Wpointer-arith" << endl;
     425                 :            :   #endif
     426 [ +  - ][ +  - ]:        614 :   o << "EXTRA_CFLAGS += -I\"" << s.runtime_path << "\"" << endl;
         [ +  - ][ +  - ]
     427                 :            :   // XXX: this may help ppc toc overflow
     428                 :            :   // o << "CFLAGS := $(subst -Os,-O2,$(CFLAGS)) -fminimal-toc" << endl;
     429 [ +  - ][ +  - ]:        614 :   o << "obj-m := " << s.module_name << ".o" << endl;
         [ +  - ][ +  - ]
     430                 :            : 
     431                 :            :   // print out all the auxiliary source (->object) file names
     432 [ +  - ][ +  - ]:        614 :   o << s.module_name << "-y := ";
     433         [ +  + ]:        724 :   for (unsigned i=0; i<s.auxiliary_outputs.size(); i++)
     434                 :            :     {
     435         [ +  - ]:        110 :       string srcname = s.auxiliary_outputs[i]->filename;
     436 [ +  - ][ +  - ]:        110 :       assert (srcname != "" && srcname.rfind('/') != string::npos);
         [ +  - ][ -  + ]
     437 [ +  - ][ +  - ]:        110 :       string objname = srcname.substr(srcname.rfind('/')+1); // basename
     438 [ +  - ][ +  - ]:        110 :       assert (objname != "" && objname[objname.size()-1] == 'c');
         [ +  - ][ +  - ]
                 [ -  + ]
     439 [ +  - ][ +  - ]:        110 :       objname[objname.size()-1] = 'o'; // now objname
     440 [ +  - ][ +  - ]:        110 :       o << " " + objname;
                 [ +  - ]
     441 [ +  - ][ +  - ]:        110 :     }
     442                 :            :   // and once again, for the translated_source file.  It can't simply
     443                 :            :   // be named MODULENAME.c, since kbuild doesn't allow a foo.ko file
     444                 :            :   // consisting of multiple .o's to have foo.o/foo.c as a source.
     445                 :            :   // (It uses ld -r -o foo.o EACH.o EACH.o).
     446                 :            :   {
     447         [ +  - ]:        614 :     string srcname = s.translated_source;
     448 [ +  - ][ +  - ]:        614 :     assert (srcname != "" && srcname.rfind('/') != string::npos);
         [ +  - ][ -  + ]
     449 [ +  - ][ +  - ]:        614 :     string objname = srcname.substr(srcname.rfind('/')+1); // basename
     450 [ +  - ][ +  - ]:        614 :     assert (objname != "" && objname[objname.size()-1] == 'c');
         [ +  - ][ +  - ]
                 [ -  + ]
     451 [ +  - ][ +  - ]:        614 :     objname[objname.size()-1] = 'o'; // now objname
     452 [ +  - ][ +  - ]:        614 :     o << " " + objname;
         [ +  - ][ +  - ]
                 [ +  - ]
     453                 :            :   }
     454         [ +  - ]:        614 :   o << endl;
     455                 :            : 
     456                 :            :   // add all stapconf dependencies
     457 [ +  - ][ +  - ]:        614 :   o << s.translated_source << ": $(STAPCONF_HEADER)" << endl;
                 [ +  - ]
     458         [ +  + ]:        724 :   for (unsigned i=0; i<s.auxiliary_outputs.size(); i++)
     459 [ +  - ][ +  - ]:        110 :     o << s.auxiliary_outputs[i]->filename << ": $(STAPCONF_HEADER)" << endl;  
                 [ +  - ]
     460                 :            : 
     461                 :            : 
     462         [ +  - ]:        614 :   o.close ();
     463                 :            : 
     464                 :            :   // Generate module directory pathname and make sure it exists.
     465         [ +  - ]:        614 :   string module_dir = s.kernel_build_tree;
     466         [ +  - ]:        614 :   string module_dir_makefile = module_dir + "/Makefile";
     467                 :            :   struct stat st;
     468         [ +  - ]:        614 :   rc = stat(module_dir_makefile.c_str(), &st);
     469         [ -  + ]:        614 :   if (rc != 0)
     470                 :            :     {
     471 [ #  # ][ #  # ]:          0 :         clog << _F("Checking \" %s \" failed with error: %s\nEnsure kernel development headers & makefiles are installed.",
         [ #  # ][ #  # ]
     472         [ #  # ]:          0 :                    module_dir_makefile.c_str(), strerror(errno)) << endl;
     473         [ #  # ]:          0 :         s.set_try_server ();
     474                 :          0 :         return rc;
     475                 :            :     }
     476                 :            : 
     477                 :            :   // Run make
     478         [ +  - ]:        614 :   vector<string> make_cmd = make_make_cmd(s, s.tmpdir);
     479         [ +  - ]:        614 :   rc = run_make_cmd(s, make_cmd);
     480         [ +  + ]:        614 :   if (rc)
     481         [ +  - ]:          5 :     s.set_try_server ();
     482 [ +  - ][ +  - ]:        624 :   return rc;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     483                 :            : }
     484                 :            : 
     485                 :            : /*
     486                 :            :  * If uprobes was built as part of the kernel build (either built-in
     487                 :            :  * or as a module), the uprobes exports should show up.  This is to be
     488                 :            :  * as distinct from the stap-built uprobes.ko from the runtime.
     489                 :            :  */
     490                 :            : static bool
     491                 :         10 : kernel_built_uprobes (systemtap_session& s)
     492                 :            : {
     493         [ -  + ]:         10 :   if (s.runtime_usermode_p())
     494                 :          0 :     return true; // sort of, via dyninst
     495                 :            : 
     496                 :            :   // see also tapsets.cxx:kernel_supports_inode_uprobes()
     497 [ +  - ][ +  - ]:         20 :   return ((s.kernel_config["CONFIG_ARCH_SUPPORTS_UPROBES"] == "y" && s.kernel_config["CONFIG_UPROBES"] == "y") ||
         [ +  - ][ #  # ]
         [ #  # ][ #  # ]
         [ -  + ][ #  # ]
         [ -  + ][ +  - ]
         [ +  - ][ +  - ]
           [ #  #  #  #  
             #  #  #  # ]
     498 [ -  + ][ #  # ]:         10 :           (s.kernel_exports.find("unregister_uprobe") != s.kernel_exports.end()));
         [ +  - ][ +  - ]
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ #  #  
          #  #  #  #  #  
                      # ]
     499                 :            : }
     500                 :            : 
     501                 :            : static int
     502                 :          0 : make_uprobes (systemtap_session& s)
     503                 :            : {
     504         [ #  # ]:          0 :   if (s.verbose > 1)
     505         [ #  # ]:          0 :     clog << _("Pass 4, preamble: (re)building SystemTap's version of uprobes.")
     506         [ #  # ]:          0 :          << endl;
     507                 :            : 
     508                 :            :   // create a subdirectory for the uprobes module
     509         [ #  # ]:          0 :   string dir(s.tmpdir + "/uprobes");
     510 [ #  # ][ #  # ]:          0 :   if (create_dir(dir.c_str()) != 0)
                 [ #  # ]
     511                 :            :     {
     512 [ #  # ][ #  # ]:          0 :       s.print_warning("failed to create directory for build uprobes.");
                 [ #  # ]
     513         [ #  # ]:          0 :       s.set_try_server ();
     514                 :          0 :       return 1;
     515                 :            :     }
     516                 :            : 
     517                 :            :   // create a simple Makefile
     518         [ #  # ]:          0 :   string makefile(dir + "/Makefile");
     519 [ #  # ][ #  # ]:          0 :   ofstream omf(makefile.c_str());
     520 [ #  # ][ #  # ]:          0 :   omf << "obj-m := uprobes.o" << endl;
     521                 :            :   // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
     522 [ #  # ][ #  # ]:          0 :   omf << "CONFIG_MODULE_SIG := n" << endl;
     523         [ #  # ]:          0 :   omf.close();
     524                 :            : 
     525                 :            :   // create a simple #include-chained source file
     526         [ #  # ]:          0 :   string runtimesourcefile(s.runtime_path + "/linux/uprobes/uprobes.c");
     527         [ #  # ]:          0 :   string sourcefile(dir + "/uprobes.c");
     528 [ #  # ][ #  # ]:          0 :   ofstream osrc(sourcefile.c_str());
     529 [ #  # ][ #  # ]:          0 :   osrc << "#include \"" << runtimesourcefile << "\"" << endl;
         [ #  # ][ #  # ]
     530                 :            : 
     531                 :            :   // pass --modinfo k=v to uprobes build too
     532         [ #  # ]:          0 :   for (unsigned i = 0; i < s.modinfos.size(); i++)
     533                 :            :     {
     534                 :          0 :       const string& mi = s.modinfos[i];
     535         [ #  # ]:          0 :       size_t loc = mi.find('=');
     536         [ #  # ]:          0 :       string tag = mi.substr (0, loc);
     537         [ #  # ]:          0 :       string value = mi.substr (loc+1);
     538 [ #  # ][ #  # ]:          0 :       osrc << "MODULE_INFO(" << tag << "," << lex_cast_qstring(value) << ");" << endl;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     539 [ #  # ][ #  # ]:          0 :     }
     540                 :            : 
     541         [ #  # ]:          0 :   osrc.close();
     542                 :            : 
     543                 :            :   // make the module
     544         [ #  # ]:          0 :   vector<string> make_cmd = make_make_cmd(s, dir);
     545         [ #  # ]:          0 :   int rc = run_make_cmd(s, make_cmd);
     546 [ #  # ][ #  # ]:          0 :   if (!rc && !copy_file(dir + "/Module.symvers",
                 [ #  # ]
     547 [ #  # ][ #  # ]:          0 :                         s.tmpdir + "/Module.symvers"))
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
           [ #  #  #  # ]
     548                 :          0 :     rc = -1;
     549                 :            : 
     550         [ #  # ]:          0 :   if (s.verbose > 1)
     551 [ #  # ][ #  # ]:          0 :     clog << _("uprobes rebuild exit code: ") << rc << endl;
                 [ #  # ]
     552         [ #  # ]:          0 :   if (rc)
     553         [ #  # ]:          0 :     s.set_try_server ();
     554                 :            :   else
     555 [ #  # ][ #  # ]:          0 :     s.uprobes_path = dir + "/uprobes.ko";
                 [ #  # ]
     556 [ #  # ][ #  # ]:          0 :   return rc;
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     557                 :            : }
     558                 :            : 
     559                 :            : static bool
     560                 :          0 : get_cached_uprobes(systemtap_session& s)
     561                 :            : {
     562 [ #  # ][ #  # ]:          0 :   s.uprobes_hash = s.use_cache ? find_uprobes_hash(s) : "";
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     563         [ #  # ]:          0 :   if (!s.uprobes_hash.empty())
     564                 :            :     {
     565                 :            :       // NB: We always put uprobes.ko in its own directory, especially so
     566                 :            :       // stap-serverd can more easily locate it.
     567         [ #  # ]:          0 :       string dir(s.tmpdir + "/uprobes");
     568 [ #  # ][ #  # ]:          0 :       if (create_dir(dir.c_str()) != 0)
                 [ #  # ]
     569                 :          0 :         return false;
     570                 :            : 
     571         [ #  # ]:          0 :       string cacheko = s.uprobes_hash + ".ko";
     572         [ #  # ]:          0 :       string tmpko = dir + "/uprobes.ko";
     573                 :            : 
     574                 :            :       // The symvers file still needs to go in the script module's directory.
     575         [ #  # ]:          0 :       string cachesyms = s.uprobes_hash + ".symvers";
     576         [ #  # ]:          0 :       string tmpsyms = s.tmpdir + "/Module.symvers";
     577                 :            : 
     578 [ #  # ][ #  # ]:          0 :       if (get_file_size(cacheko) > 0 && copy_file(cacheko, tmpko) &&
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     579 [ #  # ][ #  # ]:          0 :           get_file_size(cachesyms) > 0 && copy_file(cachesyms, tmpsyms))
     580                 :            :         {
     581         [ #  # ]:          0 :           s.uprobes_path = tmpko;
     582                 :          0 :           return true;
     583 [ #  # ][ #  # ]:          0 :         }
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     584                 :            :     }
     585                 :          0 :   return false;
     586                 :            : }
     587                 :            : 
     588                 :            : static void
     589                 :          0 : set_cached_uprobes(systemtap_session& s)
     590                 :            : {
     591 [ #  # ][ #  # ]:          0 :   if (s.use_cache && !s.uprobes_hash.empty())
                 [ #  # ]
     592                 :            :     {
     593         [ #  # ]:          0 :       string cacheko = s.uprobes_hash + ".ko";
     594         [ #  # ]:          0 :       string tmpko = s.tmpdir + "/uprobes/uprobes.ko";
     595         [ #  # ]:          0 :       copy_file(tmpko, cacheko);
     596                 :            : 
     597         [ #  # ]:          0 :       string cachesyms = s.uprobes_hash + ".symvers";
     598         [ #  # ]:          0 :       string tmpsyms = s.tmpdir + "/uprobes/Module.symvers";
     599 [ #  # ][ #  # ]:          0 :       copy_file(tmpsyms, cachesyms);
         [ #  # ][ #  # ]
                 [ #  # ]
     600                 :            :     }
     601                 :          0 : }
     602                 :            : 
     603                 :            : int
     604                 :        624 : uprobes_pass (systemtap_session& s)
     605                 :            : {
     606 [ +  + ][ -  + ]:        624 :   if (!s.need_uprobes || kernel_built_uprobes(s))
                 [ +  + ]
     607                 :        614 :     return 0;
     608                 :            : 
     609 [ +  - ][ +  - ]:         10 :   if (s.kernel_config["CONFIG_UTRACE"] != string("y"))
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     610                 :            :     {
     611                 :         10 :       clog << _("user-space process-tracking facilities not available [man error::process-tracking]") << endl;
     612                 :         10 :       s.set_try_server ();
     613                 :         10 :       return 1;
     614                 :            :     }
     615                 :            : 
     616                 :            :   /*
     617                 :            :    * We need to use the version of uprobes that comes with SystemTap.  Try to
     618                 :            :    * get it from the cache first.  If not found, build it and try to save it to
     619                 :            :    * the cache for future reuse.
     620                 :            :    */
     621                 :          0 :   int rc = 0;
     622         [ #  # ]:          0 :   if (!get_cached_uprobes(s))
     623                 :            :     {
     624                 :          0 :       rc = make_uprobes(s);
     625         [ #  # ]:          0 :       if (!rc)
     626                 :          0 :         set_cached_uprobes(s);
     627                 :            :     }
     628         [ #  # ]:          0 :   if (rc)
     629                 :          0 :     s.set_try_server ();
     630                 :        624 :   return rc;
     631                 :            : }
     632                 :            : 
     633                 :            : static
     634                 :            : vector<string>
     635                 :          0 : make_dyninst_run_command (systemtap_session& s, const string& remotedir,
     636                 :            :                           const string& version)
     637                 :            : {
     638                 :          0 :   vector<string> cmd;
     639 [ #  # ][ #  # ]:          0 :   cmd.push_back(getenv("SYSTEMTAP_STAPDYN") ?: BINDIR "/stapdyn");
         [ #  # ][ #  # ]
     640                 :            : 
     641                 :            :   // use slightly less verbosity
     642         [ #  # ]:          0 :   for (unsigned i=1; i<s.verbose; i++)
     643 [ #  # ][ #  # ]:          0 :     cmd.push_back("-v");
                 [ #  # ]
     644         [ #  # ]:          0 :   if (s.suppress_warnings)
     645 [ #  # ][ #  # ]:          0 :     cmd.push_back("-w");
                 [ #  # ]
     646                 :            : 
     647 [ #  # ][ #  # ]:          0 :   if (!s.cmd.empty())
     648                 :            :     {
     649 [ #  # ][ #  # ]:          0 :       cmd.push_back("-c");
                 [ #  # ]
     650         [ #  # ]:          0 :       cmd.push_back(s.cmd);
     651                 :            :     }
     652                 :            : 
     653         [ #  # ]:          0 :   if (s.target_pid)
     654                 :            :     {
     655 [ #  # ][ #  # ]:          0 :       cmd.push_back("-x");
                 [ #  # ]
     656 [ #  # ][ #  # ]:          0 :       cmd.push_back(lex_cast(s.target_pid));
                 [ #  # ]
     657                 :            :     }
     658                 :            : 
     659         [ #  # ]:          0 :   cmd.push_back((remotedir.empty() ? s.tmpdir : remotedir)
     660 [ #  # ][ #  # ]:          0 :                 + "/" + s.module_filename());
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     661                 :            : 
     662                 :          0 :   return cmd;
     663                 :            : }
     664                 :            : 
     665                 :            : vector<string>
     666                 :        476 : make_run_command (systemtap_session& s, const string& remotedir,
     667                 :            :                   const string& version)
     668                 :            : {
     669         [ -  + ]:        476 :   if (s.runtime_usermode_p())
     670         [ #  # ]:          0 :     return make_dyninst_run_command(s, remotedir, version);
     671                 :            : 
     672                 :            :   // for now, just spawn staprun
     673         [ +  - ]:        476 :   vector<string> staprun_cmd;
     674 [ -  + ][ +  - ]:        476 :   staprun_cmd.push_back(getenv("SYSTEMTAP_STAPRUN") ?: BINDIR "/staprun");
         [ +  - ][ +  - ]
     675                 :            : 
     676                 :            :   // use slightly less verbosity
     677         [ +  + ]:        490 :   for (unsigned i=1; i<s.verbose; i++)
     678 [ +  - ][ +  - ]:         14 :     staprun_cmd.push_back("-v");
                 [ +  - ]
     679         [ +  + ]:        476 :   if (s.suppress_warnings)
     680 [ +  - ][ +  - ]:         24 :     staprun_cmd.push_back("-w");
                 [ +  - ]
     681                 :            : 
     682 [ +  - ][ +  + ]:        476 :   if (!s.output_file.empty())
     683                 :            :     {
     684 [ +  - ][ +  - ]:         17 :       staprun_cmd.push_back("-o");
                 [ +  - ]
     685         [ +  - ]:         17 :       staprun_cmd.push_back(s.output_file);
     686                 :            :     }
     687                 :            : 
     688 [ +  - ][ +  + ]:        476 :   if (!s.cmd.empty())
     689                 :            :     {
     690 [ +  - ][ +  - ]:        172 :       staprun_cmd.push_back("-c");
                 [ +  - ]
     691         [ +  - ]:        172 :       staprun_cmd.push_back(s.cmd);
     692                 :            :     }
     693                 :            : 
     694         [ +  + ]:        476 :   if (s.target_pid)
     695                 :            :     {
     696 [ +  - ][ +  - ]:          2 :       staprun_cmd.push_back("-t");
                 [ +  - ]
     697 [ +  - ][ +  - ]:          2 :       staprun_cmd.push_back(lex_cast(s.target_pid));
                 [ +  - ]
     698                 :            :     }
     699                 :            : 
     700         [ -  + ]:        476 :   if (s.buffer_size)
     701                 :            :     {
     702 [ #  # ][ #  # ]:          0 :       staprun_cmd.push_back("-b");
                 [ #  # ]
     703 [ #  # ][ #  # ]:          0 :       staprun_cmd.push_back(lex_cast(s.buffer_size));
                 [ #  # ]
     704                 :            :     }
     705                 :            : 
     706 [ -  + ][ #  # ]:        476 :   if (s.need_uprobes && !kernel_built_uprobes(s))
         [ #  # ][ -  + ]
     707                 :            :     {
     708         [ #  # ]:          0 :       string opt_u = "-u";
     709         [ #  # ]:          0 :       if (!s.uprobes_path.empty() &&
           [ #  #  #  # ]
                 [ #  # ]
     710         [ #  # ]:          0 :           strverscmp("1.4", version.c_str()) <= 0)
     711                 :            :         {
     712 [ #  # ][ #  # ]:          0 :           if (remotedir.empty())
     713         [ #  # ]:          0 :             opt_u.append(s.uprobes_path);
     714                 :            :           else
     715 [ #  # ][ #  # ]:          0 :             opt_u.append(remotedir + "/" + basename(s.uprobes_path.c_str()));
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     716                 :            :         }
     717 [ #  # ][ #  # ]:          0 :       staprun_cmd.push_back(opt_u);
     718                 :            :     }
     719                 :            : 
     720         [ +  + ]:        476 :   if (s.load_only)
     721 [ +  - ][ -  + ]:          5 :     staprun_cmd.push_back(s.output_file.empty() ? "-L" : "-D");
         [ +  - ][ +  - ]
                 [ +  - ]
     722                 :            : 
     723 [ +  + ][ +  - ]:        476 :   if(!s.modname_given && (strverscmp("1.6", version.c_str()) <= 0))
         [ +  - ][ +  + ]
     724 [ +  - ][ +  - ]:        466 :     staprun_cmd.push_back("-R");
                 [ +  - ]
     725                 :            : 
     726 [ +  - ][ +  + ]:        476 :   if (!s.size_option.empty())
     727                 :            :     {
     728 [ +  - ][ +  - ]:          4 :       staprun_cmd.push_back("-S");
                 [ +  - ]
     729         [ +  - ]:          4 :       staprun_cmd.push_back(s.size_option);
     730                 :            :     }
     731                 :            : 
     732         [ +  - ]:        476 :   staprun_cmd.push_back((remotedir.empty() ? s.tmpdir : remotedir)
     733 [ +  + ][ +  - ]:        476 :                         + "/" + s.module_filename());
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     734                 :            : 
     735                 :            :   // add module arguments
     736                 :            :   staprun_cmd.insert(staprun_cmd.end(),
     737 [ +  - ][ +  - ]:        476 :                      s.globalopts.begin(), s.globalopts.end());
         [ +  - ][ +  - ]
     738                 :            : 
     739 [ +  - ][ +  - ]:        476 :   return staprun_cmd;
     740                 :            : }
     741                 :            : 
     742                 :            : 
     743                 :            : // Build tiny kernel modules to query tracepoints.
     744                 :            : // Given a (header-file -> test-contents) map, compile them ASAP, and return
     745                 :            : // a (header-file -> obj-filename) map.
     746                 :            : 
     747                 :            : map<string,string>
     748                 :          1 : make_tracequeries(systemtap_session& s, const map<string,string>& contents)
     749                 :            : {
     750                 :            :   static unsigned tick = 0;
     751 [ +  - ][ +  - ]:          1 :   string basename("tracequery_kmod_" + lex_cast(++tick));
                 [ +  - ]
     752         [ +  - ]:          1 :   map<string,string> objs;
     753                 :            : 
     754                 :            :   // create a subdirectory for the module
     755 [ +  - ][ +  - ]:          1 :   string dir(s.tmpdir + "/" + basename);
                 [ +  - ]
     756 [ +  - ][ +  - ]:          1 :   if (create_dir(dir.c_str()) != 0)
                 [ -  + ]
     757                 :            :     {
     758 [ #  # ][ #  # ]:          0 :       s.print_warning("failed to create directory for querying tracepoints.");
                 [ #  # ]
     759         [ #  # ]:          0 :       s.set_try_server ();
     760                 :            :       return objs;
     761                 :            :     }
     762                 :            : 
     763                 :            :   // create a simple Makefile
     764         [ +  - ]:          1 :   string makefile(dir + "/Makefile");
     765 [ +  - ][ +  - ]:          1 :   ofstream omf(makefile.c_str());
     766                 :            :   // force debuginfo generation, and relax implicit functions
     767 [ +  - ][ -  + ]:          1 :   omf << "EXTRA_CFLAGS := -g -Wno-implicit-function-declaration" << (s.omit_werror ? "" : " -Werror") << endl;
         [ +  - ][ +  - ]
     768                 :            :   // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
     769 [ +  - ][ +  - ]:          1 :   omf << "CONFIG_MODULE_SIG := n" << endl;
     770                 :            : 
     771 [ +  - ][ +  - ]:          1 :   if (s.kernel_source_tree != "")
     772 [ +  - ][ +  - ]:          1 :     omf << "EXTRA_CFLAGS += -I" + s.kernel_source_tree << endl;
         [ +  - ][ +  - ]
     773                 :            : 
     774 [ +  - ][ +  - ]:          1 :   omf << "obj-m := " << endl;
     775                 :            :   // write out each header-specific source file into a separate file
     776 [ +  - ][ +  - ]:         51 :   for (map<string,string>::const_iterator it = contents.begin(); it != contents.end(); it++)
                 [ +  + ]
     777                 :            :     {
     778 [ +  - ][ +  - ]:         50 :       string sbasename = basename + "_" + lex_cast(++tick); // suffixed
         [ +  - ][ +  - ]
                 [ +  - ]
     779                 :            : 
     780                 :            :       // write out source code
     781 [ +  - ][ +  - ]:         50 :       string srcname = dir + "/" + sbasename + ".c";
         [ +  - ][ +  - ]
                 [ +  - ]
     782 [ +  - ][ +  - ]:         50 :       string src = it->second;
     783 [ +  - ][ +  - ]:         50 :       ofstream osrc(srcname.c_str());
     784         [ +  - ]:         50 :       osrc << src;
     785         [ +  - ]:         50 :       osrc.close();
     786                 :            : 
     787         [ -  + ]:         50 :       if (s.verbose > 2)
     788 [ #  # ][ #  # ]:          0 :         clog << _F("Processing tracepoint header %s with query %s", 
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
     789                 :            :                    it->first.c_str(), srcname.c_str())
     790         [ #  # ]:          0 :              << endl;
     791                 :            : 
     792                 :            :       // arrange to build it
     793 [ +  - ][ +  - ]:         50 :       omf << "obj-m += " + sbasename + ".o" << endl; // NB: without <dir> prefix
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     794 [ +  - ][ +  - ]:         50 :       objs[it->first] = dir + "/" + sbasename + ".o";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     795 [ +  - ][ +  - ]:         50 :     }
         [ +  - ][ +  - ]
     796         [ +  - ]:          1 :   omf.close();
     797                 :            : 
     798                 :            :   // make the module
     799         [ +  - ]:          1 :   vector<string> make_cmd = make_make_objs_cmd(s, dir);
     800 [ +  - ][ +  - ]:          1 :   make_cmd.push_back ("-i"); // ignore errors, give rc 0 even in case of tracepoint header nits
                 [ +  - ]
     801                 :          1 :   bool quiet = (s.verbose < 4);
     802         [ +  - ]:          1 :   int rc = run_make_cmd(s, make_cmd, quiet, quiet);
     803         [ -  + ]:          1 :   if (rc)
     804         [ #  # ]:          0 :     s.set_try_server ();
     805                 :            : 
     806                 :            :   // Sometimes we fail a tracequery due to PR9993 / PR11649 type
     807                 :            :   // kernel trace header problems.  In this case, due to PR12729, we
     808                 :            :   // used to get a lovely "Warning: make exited with status: 2" but no
     809                 :            :   // other useful diagnostic.  -vvvv would let a user see what's up,
     810                 :            :   // but the user can't fix the problem even with that.
     811                 :            : 
     812 [ +  - ][ +  - ]:          1 :   return objs;
         [ +  - ][ +  - ]
                 [ +  - ]
     813                 :            : }
     814                 :            : 
     815                 :            : 
     816                 :            : // Build a tiny kernel module to query type information
     817                 :            : static int
     818                 :          7 : make_typequery_kmod(systemtap_session& s, const vector<string>& headers, string& name)
     819                 :            : {
     820                 :            :   static unsigned tick = 0;
     821 [ +  - ][ +  - ]:          7 :   string basename("typequery_kmod_" + lex_cast(++tick));
                 [ +  - ]
     822                 :            : 
     823                 :            :   // create a subdirectory for the module
     824 [ +  - ][ +  - ]:          7 :   string dir(s.tmpdir + "/" + basename);
                 [ +  - ]
     825 [ +  - ][ +  - ]:          7 :   if (create_dir(dir.c_str()) != 0)
                 [ -  + ]
     826                 :            :     {
     827 [ #  # ][ #  # ]:          0 :       s.print_warning("failed to create directory for querying types.");
                 [ #  # ]
     828         [ #  # ]:          0 :       s.set_try_server ();
     829                 :          0 :       return 1;
     830                 :            :     }
     831                 :            : 
     832 [ +  - ][ +  - ]:          7 :   name = dir + "/" + basename + ".ko";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     833                 :            : 
     834                 :            :   // create a simple Makefile
     835         [ +  - ]:          7 :   string makefile(dir + "/Makefile");
     836 [ +  - ][ +  - ]:          7 :   ofstream omf(makefile.c_str());
     837 [ +  - ][ +  - ]:          7 :   omf << "EXTRA_CFLAGS := -g -fno-eliminate-unused-debug-types" << endl;
     838                 :            : 
     839                 :            :   // RHBZ 655231: later rhel6 kernels' module-signing kbuild logic breaks out-of-tree modules
     840 [ +  - ][ +  - ]:          7 :   omf << "CONFIG_MODULE_SIG := n" << endl;
     841                 :            : 
     842                 :            :   // NB: We use -include instead of #include because that gives us more power.
     843                 :            :   // Using #include searches relative to the source's path, which in this case
     844                 :            :   // is /tmp/..., so that's not helpful.  Using -include will search relative
     845                 :            :   // to the cwd, which will be the kernel build root.  This means if you have a
     846                 :            :   // full kernel build tree, it's possible to get at types that aren't in the
     847                 :            :   // normal include path, e.g.:
     848                 :            :   //    @cast(foo, "bsd_acct_struct", "kernel<kernel/acct.c>")->...
     849 [ +  - ][ +  - ]:          7 :   omf << "CFLAGS_" << basename << ".o :=";
                 [ +  - ]
     850         [ +  + ]:         15 :   for (size_t i = 0; i < headers.size(); ++i)
     851 [ +  - ][ +  - ]:          8 :     omf << " -include " << lex_cast_qstring(headers[i]); // XXX right quoting?
         [ +  - ][ +  - ]
     852         [ +  - ]:          7 :   omf << endl;
     853                 :            : 
     854 [ +  - ][ +  - ]:          7 :   omf << "obj-m := " + basename + ".o" << endl;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     855         [ +  - ]:          7 :   omf.close();
     856                 :            : 
     857                 :            :   // create our empty source file
     858 [ +  - ][ +  - ]:          7 :   string source(dir + "/" + basename + ".c");
         [ +  - ][ +  - ]
                 [ +  - ]
     859 [ +  - ][ +  - ]:          7 :   ofstream osrc(source.c_str());
     860         [ +  - ]:          7 :   osrc.close();
     861                 :            : 
     862                 :            :   // make the module
     863         [ +  - ]:          7 :   vector<string> make_cmd = make_make_cmd(s, dir);
     864                 :          7 :   bool quiet = (s.verbose < 4);
     865         [ +  - ]:          7 :   int rc = run_make_cmd(s, make_cmd, quiet, quiet);
     866         [ -  + ]:          7 :   if (rc)
     867         [ #  # ]:          0 :     s.set_try_server ();
     868 [ +  - ][ +  - ]:          7 :   return rc;
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     869                 :            : }
     870                 :            : 
     871                 :            : 
     872                 :            : // Build a tiny user module to query type information
     873                 :            : static int
     874                 :          3 : make_typequery_umod(systemtap_session& s, const vector<string>& headers, string& name)
     875                 :            : {
     876                 :            :   static unsigned tick = 0;
     877                 :            : 
     878 [ +  - ][ +  - ]:          3 :   name = s.tmpdir + "/typequery_umod_" + lex_cast(++tick) + ".so";
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
                 [ +  - ]
     879                 :            : 
     880                 :            :   // make the module
     881                 :            :   //
     882                 :            :   // NB: As with kmod, using -include makes relative paths more useful.  The
     883                 :            :   // cwd in this case will be the cwd of stap itself though, which may be
     884                 :            :   // trickier to deal with.  It might be better to "cd `dirname $script`"
     885                 :            :   // first...
     886         [ +  - ]:          3 :   vector<string> cmd;
     887 [ +  - ][ +  - ]:          3 :   cmd.push_back("gcc");
                 [ +  - ]
     888 [ +  - ][ +  - ]:          3 :   cmd.push_back("-shared");
                 [ +  - ]
     889 [ +  - ][ +  - ]:          3 :   cmd.push_back("-g");
                 [ +  - ]
     890 [ +  - ][ +  - ]:          3 :   cmd.push_back("-fno-eliminate-unused-debug-types");
                 [ +  - ]
     891 [ +  - ][ +  - ]:          3 :   cmd.push_back("-xc");
                 [ +  - ]
     892 [ +  - ][ +  - ]:          3 :   cmd.push_back("/dev/null");
                 [ +  - ]
     893 [ +  - ][ +  - ]:          3 :   cmd.push_back("-o");
                 [ +  - ]
     894         [ +  - ]:          3 :   cmd.push_back(name);
     895         [ +  + ]:          6 :   for (size_t i = 0; i < headers.size(); ++i)
     896                 :            :     {
     897 [ +  - ][ +  - ]:          3 :       cmd.push_back("-include");
                 [ +  - ]
     898         [ +  - ]:          3 :       cmd.push_back(headers[i]);
     899                 :            :     }
     900                 :          3 :   bool quiet = (s.verbose < 4);
     901         [ +  - ]:          3 :   int rc = stap_system (s.verbose, cmd, quiet, quiet);
     902         [ -  + ]:          3 :   if (rc)
     903         [ #  # ]:          0 :     s.set_try_server ();
     904         [ +  - ]:          3 :   return rc;
     905                 :            : }
     906                 :            : 
     907                 :            : 
     908                 :            : int
     909                 :         10 : make_typequery(systemtap_session& s, string& module)
     910                 :            : {
     911                 :            :   int rc;
     912         [ +  - ]:         10 :   string new_module;
     913         [ +  - ]:         10 :   vector<string> headers;
     914         [ +  - ]:         10 :   bool kernel = startswith(module, "kernel");
     915                 :            : 
     916 [ +  + ][ +  - ]:         21 :   for (size_t end, i = kernel ? 6 : 0; i < module.size(); i = end + 1)
                 [ +  + ]
     917                 :            :     {
     918 [ +  - ][ -  + ]:         11 :       if (module[i] != '<')
     919                 :          0 :         return -1;
     920         [ +  - ]:         11 :       end = module.find('>', ++i);
     921         [ -  + ]:         11 :       if (end == string::npos)
     922                 :          0 :         return -1;
     923         [ +  - ]:         11 :       string header = module.substr(i, end - i);
     924         [ +  - ]:         11 :       vector<string> matches;
     925 [ +  - ][ +  - ]:         11 :       if (regexp_match(header, "^[a-zA-Z0-9/_.+-]+$", matches))
         [ +  - ][ -  + ]
     926 [ #  # ][ #  # ]:          0 :         s.print_warning("skipping malformed @cast header \""+ header + "\"");
         [ #  # ][ #  # ]
                 [ #  # ]
     927                 :            :       else
     928         [ +  - ]:         11 :         headers.push_back(header);
     929 [ +  - ][ +  - ]:         11 :     }
     930 [ +  - ][ -  + ]:         10 :   if (headers.empty())
     931                 :          0 :     return -1;
     932                 :            : 
     933         [ +  + ]:         10 :   if (kernel)
     934         [ +  - ]:          7 :       rc = make_typequery_kmod(s, headers, new_module);
     935                 :            :   else
     936         [ +  - ]:          3 :       rc = make_typequery_umod(s, headers, new_module);
     937                 :            : 
     938         [ +  - ]:         10 :   if (!rc)
     939         [ +  - ]:         10 :     module = new_module;
     940                 :            : 
     941 [ +  - ][ +  - ]:         10 :   return rc;
     942 [ +  - ][ +  - ]:       7242 : }
     943                 :            : 
     944                 :            : /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */

Generated by: LCOV version 1.9