LCOV - code coverage report
Current view: top level - mnt/wasteland/wcohen/systemtap_write/systemtap - setupdwfl.cxx (source / functions) Hit Total Coverage
Test: stap.info Lines: 218 348 62.6 %
Date: 2013-03-08 Functions: 14 18 77.8 %
Branches: 334 870 38.4 %

           Branch data     Line data    Source code
       1                 :            : // Setup routines for creating fully populated DWFLs. Used in pass 2 and 3.
       2                 :            : // Copyright (C) 2009-2011 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 "setupdwfl.h"
      11                 :            : 
      12                 :            : #include "dwarf_wrappers.h"
      13                 :            : #include "dwflpp.h"
      14                 :            : #include "session.h"
      15                 :            : #include "util.h"
      16                 :            : 
      17                 :            : #include <algorithm>
      18                 :            : #include <iostream>
      19                 :            : #include <fstream>
      20                 :            : #include <sstream>
      21                 :            : #include <set>
      22                 :            : #include <string>
      23                 :            : 
      24                 :            : extern "C" {
      25                 :            : #include <fnmatch.h>
      26                 :            : #include <stdlib.h>
      27                 :            : #include <assert.h>
      28                 :            : #include <time.h>
      29                 :            : #include <sys/times.h>
      30                 :            : #include <sys/time.h>
      31                 :            : #include <sys/types.h>
      32                 :            : #include <sys/wait.h>
      33                 :            : #include <fcntl.h>
      34                 :            : #include <limits.h>
      35                 :            : #include <sys/utsname.h>
      36                 :            : #include <unistd.h>
      37                 :            : }
      38                 :            : 
      39                 :            : // XXX: also consider adding $HOME/.debug/ for perf build-id-cache
      40                 :            : static const char *debuginfo_path_arr = "+:.debug:/usr/lib/debug:/var/cache/abrt-di/usr/lib/debug:build";
      41                 :       2414 : static const char *debuginfo_env_arr = getenv("SYSTEMTAP_DEBUGINFO_PATH");
      42         [ +  + ]:       2414 : static char *debuginfo_path = (char *)(debuginfo_env_arr ?: debuginfo_path_arr);
      43                 :            : 
      44                 :            : // NB: kernel_build_tree doesn't enter into this, as it's for
      45                 :            : // kernel-side modules only.
      46                 :            : // XXX: also consider adding $HOME/.debug/ for perf build-id-cache
      47                 :            : static const char *debuginfo_usr_path_arr = "+:.debug:/usr/lib/debug:/var/cache/abrt-di/usr/lib/debug";
      48         [ +  + ]:       2414 : static char *debuginfo_usr_path = (char *)(debuginfo_env_arr
      49                 :            :                                            ?: debuginfo_usr_path_arr);
      50                 :            : 
      51                 :            : // A pointer to the current systemtap session for use only by a few
      52                 :            : // dwfl calls. DO NOT rely on this, as it is cleared after use.
      53                 :            : // This is a kludge.
      54                 :            : static systemtap_session* current_session_for_find_debuginfo;
      55                 :            : 
      56                 :            : static const Dwfl_Callbacks kernel_callbacks =
      57                 :            :   {
      58                 :            :     dwfl_linux_kernel_find_elf,
      59                 :            :     internal_find_debuginfo,
      60                 :            :     dwfl_offline_section_address,
      61                 :            :     (char **) & debuginfo_path
      62                 :            :   };
      63                 :            : 
      64                 :            : static const Dwfl_Callbacks user_callbacks =
      65                 :            :   {
      66                 :            :     NULL,
      67                 :            :     internal_find_debuginfo,
      68                 :            :     NULL, /* ET_REL not supported for user space, only ET_EXEC and ET_DYN.
      69                 :            :              dwfl_offline_section_address, */
      70                 :            :     (char **) & debuginfo_usr_path
      71                 :            :   };
      72                 :            : 
      73                 :            : using namespace std;
      74                 :            : 
      75                 :            : // Store last kernel and user Dwfl for reuse since they are often
      76                 :            : // re-requested (in phase 2 and then in phase 3).
      77                 :       2414 : static DwflPtr kernel_dwfl;
      78                 :       2414 : static DwflPtr user_dwfl;
      79                 :            : 
      80                 :            : // Setup in setup_dwfl_kernel(), for use in setup_dwfl_report_kernel_p().
      81                 :            : // Either offline_search_modname or offline_search_names is
      82                 :            : // used. When offline_search_modname is not NULL then
      83                 :            : // offline_search_names is ignored.
      84                 :            : static const char *offline_search_modname;
      85                 :       2414 : static set<string> offline_search_names;
      86                 :            : static unsigned offline_modules_found;
      87                 :            : 
      88                 :            : // Whether or not we are done reporting kernel modules in
      89                 :            : // set_dwfl_report_kernel_p().
      90                 :            : static bool setup_dwfl_done;
      91                 :            : 
      92                 :            : // Kept for user_dwfl cache, user modules don't allow wildcards, so
      93                 :            : // just keep the set of module strings.
      94                 :       2414 : static set<string> user_modset;
      95                 :            : 
      96                 :            : // Determines whether or not we will make setup_dwfl_report_kernel_p
      97                 :            : // report true for all module dependencies. This is necessary for
      98                 :            : // correctly resolving some dwarf constructs that relocate against
      99                 :            : // symbols in vmlinux and/or other modules they depend on. See PR10678.
     100                 :            : static const bool setup_all_deps = true;
     101                 :            : 
     102                 :            : // Where to find the kernel (and the Modules.dep file).  Setup in
     103                 :            : // setup_dwfl_kernel(), used by dwfl_linux_kernel_report_offline() and
     104                 :            : // setup_mod_deps().
     105                 :       2414 : static string elfutils_kernel_path;
     106                 :            : 
     107 [ +  - ][ +  + ]:     830023 : static bool is_comma_dash(const char c) { return (c == ',' || c == '-'); }
     108                 :            : 
     109                 :            : // The path to the abrt-action-install-debuginfo-to-abrt-cache program.
     110   [ +  -  +  - ]:       4828 : static const string abrt_path =
                 [ +  - ]
     111                 :       2414 :                     (access ("/usr/bin/abrt-action-install-debuginfo-to-abrt-cache", X_OK) == 0
     112                 :            :                       ? "/usr/bin/abrt-action-install-debuginfo-to-abrt-cache"
     113                 :       2414 :                     : (access ("/usr/libexec/abrt-action-install-debuginfo-to-abrt-cache", X_OK) == 0
     114                 :            :                       ? "/usr/libexec/abrt-action-install-debuginfo-to-abrt-cache"
     115                 :            :                     : ""));
     116                 :            : 
     117                 :            : // The module name is the basename (without the extension) of the
     118                 :            : // module path, with ',' and '-' replaced by '_'.
     119                 :            : static string
     120                 :      91729 : modname_from_path(const string &path)
     121                 :            : {
     122         [ +  - ]:      91729 :   size_t dot = path.rfind('.');
     123         [ +  - ]:      91729 :   size_t slash = path.rfind('/');
     124 [ +  - ][ +  - ]:      91729 :   if (dot == string::npos || slash == string::npos || dot < slash)
                 [ -  + ]
     125         [ #  # ]:          0 :     return "";
     126         [ +  - ]:      91729 :   string name = path.substr(slash + 1, dot - slash - 1);
     127 [ +  - ][ +  - ]:      91729 :   replace_if(name.begin(), name.end(), is_comma_dash, '_');
                 [ +  - ]
     128 [ +  - ][ +  - ]:      91729 :   return name;
     129                 :            : }
     130                 :            : 
     131                 :            : // Try to parse modules.dep file,
     132                 :            : // Simple format: module path (either full or relative), colon,
     133                 :            : // (possibly empty) space delimited list of module (path)
     134                 :            : // dependencies.
     135                 :            : static void
     136                 :        617 : setup_mod_deps()
     137                 :            : {
     138         [ +  - ]:        617 :   string modulesdep;
     139         [ +  - ]:        617 :   ifstream in;
     140         [ +  - ]:        617 :   string l;
     141                 :            : 
     142 [ +  - ][ -  + ]:        617 :   if (elfutils_kernel_path[0] == '/')
     143                 :            :     {
     144         [ #  # ]:          0 :       modulesdep = elfutils_kernel_path;
     145         [ #  # ]:          0 :       modulesdep += "/modules.dep";
     146                 :            :     }
     147                 :            :   else
     148                 :            :     {
     149         [ +  - ]:        617 :       string sysroot = "";
     150         [ +  + ]:        617 :       if (current_session_for_find_debuginfo)
     151         [ +  - ]:        616 :         sysroot = current_session_for_find_debuginfo->sysroot;
     152 [ +  - ][ +  - ]:        617 :       modulesdep = sysroot + "/lib/modules/";
                 [ +  - ]
     153         [ +  - ]:        617 :       modulesdep += elfutils_kernel_path;
     154 [ +  - ][ +  - ]:        617 :       modulesdep += "/modules.dep";
     155                 :            :     }
     156 [ +  - ][ +  - ]:        617 :   in.open(modulesdep.c_str());
     157 [ +  - ][ -  + ]:        617 :   if (in.fail ())
     158                 :        617 :     return;
     159                 :            : 
     160 [ +  - ][ +  - ]:      91933 :   while (getline (in, l))
                 [ +  + ]
     161                 :            :     {
     162         [ +  - ]:      91316 :       size_t off = l.find (':');
     163         [ +  - ]:      91316 :       if (off != string::npos)
     164                 :            :         {
     165 [ +  - ][ +  - ]:      91316 :           string modpath, modname;
     166 [ +  - ][ +  - ]:      91316 :           modpath = l.substr (0, off);
                 [ +  - ]
     167 [ +  - ][ +  - ]:      91316 :           modname = modname_from_path (modpath);
                 [ +  - ]
     168 [ +  - ][ -  + ]:      91316 :           if (modname == "")
     169                 :          0 :             continue;
     170                 :            : 
     171                 :            :           bool dep_needed;
     172         [ +  + ]:      91316 :           if (offline_search_modname != NULL)
     173                 :            :             {
     174 [ +  - ][ +  - ]:        592 :               if (dwflpp::name_has_wildcard (offline_search_modname))
         [ +  - ][ +  - ]
     175                 :            :                 {
     176                 :            :                   dep_needed = !fnmatch (offline_search_modname,
     177 [ +  - ][ +  - ]:        592 :                                          modname.c_str (), 0);
     178         [ +  + ]:        592 :                   if (dep_needed)
     179         [ +  - ]:        298 :                     offline_search_names.insert (modname);
     180                 :            :                 }
     181                 :            :               else
     182                 :            :                 {
     183                 :            :                   dep_needed = ! strcmp(modname.c_str (),
     184         [ #  # ]:          0 :                                         offline_search_modname);
     185         [ #  # ]:          0 :                   if (dep_needed)
     186         [ #  # ]:          0 :                     offline_search_names.insert (modname);
     187                 :            :                 }
     188                 :            :             }
     189                 :            :           else
     190                 :            :             dep_needed = (offline_search_names.find (modname)
     191 [ +  - ][ +  - ]:      90724 :                           != offline_search_names.end ());
     192                 :            : 
     193         [ +  + ]:      91316 :           if (! dep_needed)
     194                 :      90778 :             continue;
     195                 :            : 
     196         [ +  - ]:        538 :           string depstring = l.substr (off + 1);
     197 [ +  - ][ +  + ]:        538 :           if (depstring.size () > 0)
     198                 :            :             {
     199         [ +  - ]:        246 :               stringstream ss (depstring);
     200         [ +  - ]:        246 :               string deppath;
     201 [ +  - ][ +  - ]:        659 :               while (ss >> deppath)
                 [ +  + ]
     202 [ +  - ][ +  - ]:        659 :                 offline_search_names.insert (modname_from_path(deppath));
         [ +  - ][ +  - ]
                 [ +  - ]
     203                 :            : 
     204 [ +  - ][ +  - ]:      91316 :             }
         [ +  + ][ +  - ]
                 [ +  + ]
     205                 :            :         }
     206                 :            :     }
     207                 :            : 
     208                 :            :   // We always want kernel (needed in list so size checks match).
     209                 :            :   // Everything needed now stored in offline_search_names.
     210 [ +  - ][ +  - ]:        617 :   offline_search_names.insert ("kernel");
                 [ +  - ]
     211 [ +  - ][ -  + ]:        617 :   offline_search_modname = NULL;
         [ +  - ][ -  + ]
         [ +  - ][ +  - ]
     212                 :            : }
     213                 :            : 
     214                 :            : // Set up our offline search for kernel modules.  We don't want the
     215                 :            : // offline search iteration to do a complete search of the kernel
     216                 :            : // build tree, since that's wasteful, so create a predicate that
     217                 :            : // filters and stops reporting as soon as we got everything.
     218                 :            : static int
     219                 :     169197 : setup_dwfl_report_kernel_p(const char* modname, const char* filename)
     220                 :            : {
     221                 :     169197 :   assert_no_interrupts();
     222         [ +  + ]:     169197 :   if (setup_dwfl_done)
     223                 :        735 :     return -1;
     224                 :            : 
     225                 :            :   // elfutils sends us NULL filenames sometimes if it can't find dwarf
     226         [ +  + ]:     168462 :   if (filename == NULL)
     227                 :          2 :     return 0;
     228                 :            : 
     229                 :            :   // Check kernel first since it is often the only thing needed,
     230                 :            :   // then we never have to parse and setup the module deps map.
     231                 :            :   // It will be reported as the very first thing.
     232         [ +  + ]:     168460 :   if (setup_all_deps && ! strcmp (modname, "kernel"))
     233                 :            :     {
     234 [ +  + ][ +  - ]:       4947 :       if ((offline_search_modname != NULL
         [ +  + ][ +  + ]
                 [ +  + ]
     235                 :          4 :            && ! strcmp (offline_search_modname, "kernel"))
     236         [ +  - ]:       1263 :           || (offline_search_names.size() == 1
     237 [ +  - ][ +  - ]:       2421 :               && *offline_search_names.begin() == "kernel"))
         [ +  + ][ #  # ]
     238                 :        646 :         setup_dwfl_done = true;
     239                 :            :       else
     240                 :        617 :         setup_mod_deps();
     241                 :            : 
     242                 :       1263 :       offline_modules_found++;
     243                 :       1263 :       return 1;
     244                 :            :     }
     245                 :            : 
     246                 :            :   // If offline_search_modname is setup use it (either as regexp or
     247                 :            :   // explicit module/kernel name) and ignore offline_search_names.
     248                 :            :   // Otherwise use offline_search_names exclusively.
     249         [ -  + ]:     167197 :   if (offline_search_modname != NULL)
     250                 :            :     {
     251 [ #  # ][ #  # ]:          0 :       if (dwflpp::name_has_wildcard (offline_search_modname))
         [ #  # ][ #  # ]
     252                 :            :         {
     253                 :          0 :           int match_p = !fnmatch(offline_search_modname, modname, 0);
     254                 :            :           // In the wildcard case, we don't short-circuit (return -1)
     255                 :            :           // analogously to dwflpp::module_name_final_match().
     256         [ #  # ]:          0 :           if (match_p)
     257                 :          0 :             offline_modules_found++;
     258                 :          0 :           return match_p;
     259                 :            :         }
     260                 :            :       else
     261                 :            :         { /* non-wildcard mode, reject mismatching module names */
     262         [ #  # ]:          0 :           if (strcmp(modname, offline_search_modname))
     263                 :          0 :             return 0;
     264                 :            :           else
     265                 :            :             {
     266                 :            :               // Done, only one name needed and found it.
     267                 :          0 :               offline_modules_found++;
     268                 :          0 :               setup_dwfl_done = true;
     269                 :          0 :               return 1;
     270                 :            :             }
     271                 :            :         }
     272                 :            :     }
     273                 :            :   else
     274                 :            :     { /* find all in set mode, reject mismatching module names */
     275 [ +  - ][ +  - ]:     167197 :       if (offline_search_names.find(modname) == offline_search_names.end())
         [ +  - ][ +  - ]
                 [ +  + ]
     276                 :     166586 :         return 0;
     277                 :            :       else
     278                 :            :         {
     279                 :        611 :           offline_modules_found++;
     280         [ +  + ]:        611 :           if (offline_search_names.size() == offline_modules_found)
     281                 :         89 :             setup_dwfl_done = true;
     282                 :     169197 :           return 1;
     283                 :            :         }
     284                 :            :     }
     285                 :            : }
     286                 :            : 
     287                 :          0 : static char * path_insert_sysroot(string sysroot, string path)
     288                 :            : {
     289                 :            :   char * path_new;
     290                 :          0 :   size_t pos = 1;
     291         [ #  # ]:          0 :   if (path[0] == '/')
     292                 :          0 :     path.replace(0, 1, sysroot);
     293                 :          0 :   while (true) {
     294                 :          0 :     pos = path.find(":/", pos);
     295         [ #  # ]:          0 :     if (pos == string::npos)
     296                 :          0 :       break;
     297         [ #  # ]:          0 :     path.replace(pos, 2, ":" + sysroot);
     298                 :          0 :     ++pos;
     299                 :            :   }
     300                 :          0 :   path_new = new char[path.size()+1];
     301                 :          0 :   strcpy (path_new, path.c_str());
     302                 :          0 :   return path_new;
     303                 :            : }
     304                 :            : 
     305                 :          0 : void debuginfo_path_insert_sysroot(string sysroot)
     306                 :            : {
     307 [ #  # ][ #  # ]:          0 :   debuginfo_path = path_insert_sysroot(sysroot, debuginfo_path);
                 [ #  # ]
     308 [ #  # ][ #  # ]:          0 :   debuginfo_usr_path = path_insert_sysroot(sysroot, debuginfo_usr_path);
                 [ #  # ]
     309                 :          0 : }
     310                 :            : 
     311                 :            : static DwflPtr
     312                 :       1265 : setup_dwfl_kernel (unsigned *modules_found, systemtap_session &s)
     313                 :            : {
     314         [ +  - ]:       1265 :   Dwfl *dwfl = dwfl_begin (&kernel_callbacks);
     315 [ +  - ][ +  - ]:       1265 :   dwfl_assert ("dwfl_begin", dwfl);
                 [ +  - ]
     316         [ +  - ]:       1265 :   dwfl_report_begin (dwfl);
     317                 :            : 
     318                 :            :   // We have a problem with -r REVISION vs -r BUILDDIR here.  If
     319                 :            :   // we're running against a fedora/rhel style kernel-debuginfo
     320                 :            :   // tree, s.kernel_build_tree is not the place where the unstripped
     321                 :            :   // vmlinux will be installed.  Rather, it's over yonder at
     322                 :            :   // /usr/lib/debug/lib/modules/$REVISION/.  It seems that there is
     323                 :            :   // no way to set the dwfl_callback.debuginfo_path and always
     324                 :            :   // passs the plain kernel_release here.  So instead we have to
     325                 :            :   // hard-code this magic here.
     326 [ +  - ][ +  - ]:       2530 :   if (s.kernel_build_tree == string(s.sysroot + "/lib/modules/"
     327                 :            :                                     + s.kernel_release
     328 [ +  - ][ +  - ]:       2530 :                                     + "/build"))
         [ +  - ][ +  - ]
         [ +  - ][ +  - ]
     329         [ +  - ]:       1265 :     elfutils_kernel_path = s.kernel_release;
     330                 :            :   else
     331         [ #  # ]:          0 :     elfutils_kernel_path = s.kernel_build_tree;
     332                 :            : 
     333                 :       1265 :   offline_modules_found = 0;
     334                 :            : 
     335                 :            :   // First try to report full path modules.
     336         [ +  - ]:       1265 :   set<string>::iterator it = offline_search_names.begin();
     337                 :       1265 :   int kernel = 0;
     338 [ +  - ][ +  + ]:       5827 :   while (it != offline_search_names.end())
     339                 :            :     {
     340 [ +  - ][ +  + ]:       4562 :       if ((*it)[0] == '/')
     341                 :            :         {
     342         [ +  - ]:       3676 :           const char *cname = (*it).c_str();
     343         [ +  - ]:       3676 :           Dwfl_Module *mod = dwfl_report_offline (dwfl, cname, cname, -1);
     344         [ +  - ]:       3676 :           if (mod)
     345                 :       3676 :             offline_modules_found++;
     346                 :            :         }
     347 [ +  - ][ +  + ]:        886 :       else if ((*it) == "kernel")
     348                 :        657 :         kernel = 1;
     349                 :       4562 :       it++;
     350                 :            :     }
     351                 :            : 
     352                 :            :     // We always need this, even when offline_search_modname is NULL
     353                 :            :     // and offline_search_names is empty because we still might want
     354                 :            :     // the kernel vmlinux reported.
     355                 :       1265 :   setup_dwfl_done = false;
     356                 :            :   int rc = dwfl_linux_kernel_report_offline (dwfl,
     357                 :            :                                              elfutils_kernel_path.c_str(),
     358 [ +  - ][ +  - ]:       1265 :                                              &setup_dwfl_report_kernel_p);
     359                 :            : 
     360                 :            :   (void) rc; /* Ignore since the predicate probably returned -1 at some point,
     361                 :            :                 And libdwfl interprets that as "whole query failed" rather than
     362                 :            :                 "found it already, stop looking". */
     363                 :            : 
     364                 :            :   // NB: the result of an _offline call is the assignment of
     365                 :            :   // virtualized addresses to relocatable objects such as
     366                 :            :   // modules.  These have to be converted to real addresses at
     367                 :            :   // run time.  See the dwarf_derived_probe ctor and its caller.
     368                 :            : 
     369                 :            :   // If no modules were found, and we are probing the kernel,
     370                 :            :   // attempt to download the kernel debuginfo.
     371         [ +  + ]:       1265 :   if(kernel)
     372                 :            :     {
     373                 :            :       // Get the kernel build ID. We still need to call this even if we
     374                 :            :       // already have the kernel debuginfo installed as it adds the
     375                 :            :       // build ID to the script hash.
     376         [ +  - ]:        657 :       string hex = get_kernel_build_id(s);
     377 [ +  + ][ -  + ]:        657 :       if (offline_modules_found == 0 && s.download_dbinfo != 0 && !hex.empty())
         [ #  # ][ #  # ]
                 [ -  + ]
     378                 :            :         {
     379 [ #  # ][ #  # ]:          0 :           rc = download_kernel_debuginfo(s, hex);
                 [ #  # ]
     380         [ #  # ]:          0 :           if(rc >= 0)
     381         [ #  # ]:        657 :             return setup_dwfl_kernel (modules_found, s);
     382 [ +  - ][ +  - ]:        657 :         }
     383                 :            :     }
     384                 :            : 
     385 [ +  - ][ +  - ]:       1265 :   dwfl_assert ("dwfl_report_end", dwfl_report_end(dwfl, NULL, NULL));
         [ +  - ][ +  - ]
     386                 :       1265 :   *modules_found = offline_modules_found;
     387                 :            : 
     388         [ +  - ]:       1265 :   StapDwfl *stap_dwfl = new StapDwfl(dwfl);
     389 [ +  - ][ +  - ]:       1265 :   kernel_dwfl = DwflPtr(stap_dwfl);
                 [ +  - ]
     390                 :            : 
     391         [ +  - ]:       1265 :   return kernel_dwfl;
     392                 :            : }
     393                 :            : 
     394                 :            : DwflPtr
     395                 :       1056 : setup_dwfl_kernel(const std::string &name,
     396                 :            :                   unsigned *found,
     397                 :            :                   systemtap_session &s)
     398                 :            : {
     399                 :       1056 :   current_session_for_find_debuginfo = &s;
     400         [ +  - ]:       1056 :   const char *modname = name.c_str();
     401         [ +  - ]:       1056 :   set<string> names; // Default to empty
     402                 :            : 
     403                 :            :   /* Support full path kernel modules, these cannot be regular
     404                 :            :      expressions, so just put them in the search set. */
     405 [ +  - ][ +  + ]:       1056 :   if (name[0] == '/' || ! dwflpp::name_has_wildcard (modname))
         [ +  - ][ +  - ]
         [ +  + ][ +  + ]
         [ +  - ][ +  + ]
           [ +  +  #  #  
                   #  # ]
     406                 :            :     {
     407         [ +  - ]:       1052 :       names.insert(name);
     408                 :       1052 :       modname = NULL;
     409                 :            :     }
     410                 :            : 
     411 [ +  + ][ +  + ]:       1511 :   if (kernel_dwfl != NULL
         [ +  + ][ +  + ]
     412                 :            :       && offline_search_modname == modname
     413         [ +  - ]:        455 :       && offline_search_names == names)
     414                 :            :     {
     415                 :         18 :       *found = offline_modules_found;
     416         [ +  - ]:         18 :       return kernel_dwfl;
     417                 :            :     }
     418                 :            : 
     419                 :       1038 :   offline_search_modname = modname;
     420         [ +  - ]:       1038 :   offline_search_names = names;
     421                 :            : 
     422 [ +  - ][ +  - ]:       1056 :   return setup_dwfl_kernel(found, s);
     423                 :            : }
     424                 :            : 
     425                 :            : DwflPtr
     426                 :        314 : setup_dwfl_kernel(const std::set<std::string> &names,
     427                 :            :                   unsigned *found,
     428                 :            :                   systemtap_session &s)
     429                 :            : {
     430         [ +  + ]:        609 :   if (kernel_dwfl != NULL
           [ +  -  +  + ]
                 [ +  + ]
     431                 :            :       && offline_search_modname == NULL
     432                 :        295 :       && offline_search_names == names)
     433                 :            :     {
     434                 :         87 :       *found = offline_modules_found;
     435                 :         87 :       return kernel_dwfl;
     436                 :            :     }
     437                 :            : 
     438                 :        227 :   offline_search_modname = NULL;
     439                 :        227 :   offline_search_names = names;
     440                 :        314 :   return setup_dwfl_kernel(found, s);
     441                 :            : }
     442                 :            : 
     443                 :            : DwflPtr
     444                 :         19 : setup_dwfl_user(const std::string &name)
     445                 :            : {
     446 [ +  + ][ +  - ]:         74 :   if (user_dwfl != NULL
         [ +  + ][ +  + ]
     447         [ +  - ]:         18 :       && user_modset.size() == 1
     448 [ +  - ][ +  - ]:         37 :       && (*user_modset.begin()) == name)
         [ +  + ][ #  # ]
     449                 :          6 :     return user_dwfl;
     450                 :            : 
     451                 :         13 :   user_modset.clear();
     452                 :         13 :   user_modset.insert(name);
     453                 :            : 
     454                 :         13 :   Dwfl *dwfl = dwfl_begin (&user_callbacks);
     455 [ +  - ][ +  - ]:         13 :   dwfl_assert("dwfl_begin", dwfl);
                 [ +  - ]
     456                 :         13 :   dwfl_report_begin (dwfl);
     457                 :            : 
     458                 :            :   // XXX: should support buildid-based naming
     459                 :         13 :   const char *cname = name.c_str();
     460                 :         13 :   Dwfl_Module *mod = dwfl_report_offline (dwfl, cname, cname, -1);
     461 [ +  - ][ +  - ]:         13 :   dwfl_assert ("dwfl_report_end", dwfl_report_end(dwfl, NULL, NULL));
         [ +  - ][ +  - ]
     462         [ -  + ]:         13 :   if (! mod)
     463                 :            :     {
     464                 :          0 :       dwfl_end(dwfl);
     465                 :          0 :       dwfl = NULL;
     466                 :            :     }
     467                 :            : 
     468                 :         13 :   StapDwfl *stap_dwfl = new StapDwfl(dwfl);
     469         [ +  - ]:         13 :   user_dwfl = DwflPtr(stap_dwfl);
     470                 :            : 
     471                 :         19 :   return user_dwfl;
     472                 :            : }
     473                 :            : 
     474                 :            : DwflPtr
     475                 :         69 : setup_dwfl_user(std::vector<std::string>::const_iterator &begin,
     476                 :            :                 const std::vector<std::string>::const_iterator &end,
     477                 :            :                 bool all_needed, systemtap_session &s)
     478                 :            : {
     479                 :         69 :   current_session_for_find_debuginfo = &s;
     480                 :            :   // See if we have this dwfl already cached
     481         [ +  - ]:         69 :   set<string> modset(begin, end);
     482 [ +  + ][ +  - ]:         69 :   if (user_dwfl != NULL && modset == user_modset)
         [ -  + ][ -  + ]
     483         [ #  # ]:          0 :     return user_dwfl;
     484                 :            : 
     485         [ +  - ]:         69 :   user_modset = modset;
     486                 :            : 
     487         [ +  - ]:         69 :   Dwfl *dwfl = dwfl_begin (&user_callbacks);
     488 [ +  - ][ +  - ]:         69 :   dwfl_assert("dwfl_begin", dwfl);
                 [ +  - ]
     489         [ +  - ]:         69 :   dwfl_report_begin (dwfl);
     490                 :         69 :   Dwfl_Module *mod = NULL;
     491                 :            :   // XXX: should support buildid-based naming
     492 [ +  - ][ +  + ]:        138 :   while (begin != end && dwfl != NULL)
         [ +  - ][ +  + ]
     493                 :            :     {
     494         [ +  - ]:         69 :       const char *cname = (*begin).c_str();
     495         [ +  - ]:         69 :       mod = dwfl_report_offline (dwfl, cname, cname, -1);
     496 [ +  + ][ +  - ]:         69 :       if (! mod && all_needed)
     497                 :            :         {
     498         [ +  - ]:          8 :           dwfl_end(dwfl);
     499                 :          8 :           dwfl = NULL;
     500                 :            :         }
     501         [ +  - ]:         69 :       begin++;
     502                 :            :     }
     503                 :            : 
     504                 :            :   /* Extract the build id and add it to the session variable
     505                 :            :    * so it will be added to the script hash */
     506         [ +  + ]:         69 :   if (mod)
     507                 :            :     {
     508                 :            :       const unsigned char *bits;
     509                 :            :       GElf_Addr vaddr;
     510         [ +  + ]:         61 :       if(s.verbose > 2)
     511 [ +  - ][ +  - ]:          1 :         clog << _("Extracting build ID.") << endl;
     512         [ +  - ]:         61 :       int bits_length = dwfl_module_build_id(mod, &bits, &vaddr);
     513                 :            : 
     514                 :            :       /* Convert the binary bits to a hex string */
     515         [ +  - ]:         61 :       string hex = hex_dump(bits, bits_length);
     516                 :            : 
     517                 :            :       //Store the build ID in the session
     518 [ +  - ][ +  - ]:         61 :       s.build_ids.push_back(hex);
     519                 :            :     }
     520                 :            : 
     521         [ +  + ]:         69 :   if (dwfl)
     522 [ +  - ][ +  - ]:         61 :     dwfl_assert ("dwfl_report_end", dwfl_report_end(dwfl, NULL, NULL));
         [ +  - ][ +  - ]
     523                 :            : 
     524         [ +  - ]:         69 :   StapDwfl *stap_dwfl = new StapDwfl(dwfl);
     525 [ +  - ][ +  - ]:         69 :   user_dwfl = DwflPtr(stap_dwfl);
                 [ +  - ]
     526                 :            : 
     527 [ +  - ][ +  - ]:         69 :   return user_dwfl;
     528                 :            : }
     529                 :            : 
     530                 :            : bool
     531                 :      10129 : is_user_module(const std::string &m)
     532                 :            : {
     533 [ +  + ][ +  + ]:      10129 :   return m[0] == '/' && m.rfind(".ko", m.length() - 1) != m.length() - 3;
     534                 :            : }
     535                 :            : 
     536                 :            : int
     537                 :         48 : internal_find_debuginfo (Dwfl_Module *mod,
     538                 :            :       void **userdata __attribute__ ((unused)),
     539                 :            :       const char *modname __attribute__ ((unused)),
     540                 :            :       GElf_Addr base __attribute__ ((unused)),
     541                 :            :       const char *file_name,
     542                 :            :       const char *debuglink_file,
     543                 :            :       GElf_Word debuglink_crc,
     544                 :            :       char **debuginfo_file_name)
     545                 :            : {
     546                 :            : 
     547                 :            :   int bits_length;
     548         [ +  - ]:         48 :   string hex;
     549                 :            : 
     550                 :            :   /* To Keep track of whether the abrt successfully installed the debuginfo */
     551                 :            :   static int install_dbinfo_failed = 0;
     552                 :            : 
     553                 :            :   /* Make sure the current session variable is not null */
     554         [ -  + ]:         48 :   if(current_session_for_find_debuginfo == NULL)
     555                 :          0 :     goto call_dwfl_standard_find_debuginfo;
     556                 :            : 
     557                 :            :   /* Check to see if download-debuginfo=0 was set */
     558 [ -  + ][ #  # ]:         48 :   if(!current_session_for_find_debuginfo->download_dbinfo || abrt_path.empty())
         [ #  # ][ +  - ]
     559                 :         48 :     goto call_dwfl_standard_find_debuginfo;
     560                 :            : 
     561                 :            :   /* Check that we haven't already run this */
     562         [ #  # ]:          0 :   if (install_dbinfo_failed < 0)
     563                 :            :     {
     564         [ #  # ]:          0 :       if(current_session_for_find_debuginfo->verbose > 1)
     565 [ #  # ][ #  # ]:          0 :         current_session_for_find_debuginfo->print_warning(_F("We already tried running '%s'", abrt_path.c_str()));
         [ #  # ][ #  # ]
     566                 :          0 :       goto call_dwfl_standard_find_debuginfo;
     567                 :            :     }
     568                 :            : 
     569                 :            :   /* Extract the build ID */
     570                 :            :   const unsigned char *bits;
     571                 :            :   GElf_Addr vaddr;
     572         [ #  # ]:          0 :   if(current_session_for_find_debuginfo->verbose > 2)
     573 [ #  # ][ #  # ]:          0 :     clog << _("Extracting build ID.") << endl;
     574         [ #  # ]:          0 :   bits_length = dwfl_module_build_id(mod, &bits, &vaddr);
     575                 :            : 
     576                 :            :   /* Convert the binary bits to a hex string */
     577 [ #  # ][ #  # ]:          0 :   hex = hex_dump(bits, bits_length);
                 [ #  # ]
     578                 :            : 
     579                 :            :   /* Search for the debuginfo with the build ID */
     580         [ #  # ]:          0 :   if(current_session_for_find_debuginfo->verbose > 2)
     581 [ #  # ][ #  # ]:          0 :     clog << _F("Searching for debuginfo with build ID: '%s'.", hex.c_str()) << endl;
         [ #  # ][ #  # ]
                 [ #  # ]
     582         [ #  # ]:          0 :   if (bits_length > 0)
     583                 :            :     {
     584                 :            :       int fd = dwfl_build_id_find_debuginfo(mod,
     585                 :            :              NULL, NULL, 0,
     586                 :            :              NULL, NULL, 0,
     587         [ #  # ]:          0 :              debuginfo_file_name);
     588         [ #  # ]:          0 :       if (fd >= 0)
     589                 :          0 :         return fd;
     590                 :            :     }
     591                 :            : 
     592                 :            :   /* The above failed, so call abrt-action-install-debuginfo-to-abrt-cache
     593                 :            :   to download and install the debuginfo */
     594         [ #  # ]:          0 :   if(current_session_for_find_debuginfo->verbose > 1)
     595 [ #  # ][ #  # ]:          0 :     clog << _F("Downloading and installing debuginfo with build ID: '%s' using %s.",
         [ #  # ][ #  # ]
                 [ #  # ]
     596         [ #  # ]:          0 :             hex.c_str(), abrt_path.c_str()) << endl;
     597                 :            : 
     598                 :            :   struct tms tms_before;
     599                 :          0 :   times (& tms_before);
     600                 :            :   struct timeval tv_before;
     601                 :            :   struct tms tms_after;
     602                 :            :   unsigned _sc_clk_tck;
     603                 :            :   struct timeval tv_after;
     604                 :          0 :   gettimeofday (&tv_before, NULL);
     605                 :            : 
     606 [ #  # ][ #  # ]:          0 :   if(execute_abrt_action_install_debuginfo_to_abrt_cache (hex) < 0)
         [ #  # ][ #  # ]
     607                 :            :     {
     608                 :          0 :       install_dbinfo_failed = -1;
     609 [ #  # ][ #  # ]:          0 :       current_session_for_find_debuginfo->print_warning(_F("%s failed.", abrt_path.c_str()));
         [ #  # ][ #  # ]
     610                 :          0 :       goto call_dwfl_standard_find_debuginfo;
     611                 :            :     }
     612                 :            : 
     613                 :          0 :   _sc_clk_tck = sysconf (_SC_CLK_TCK);
     614                 :          0 :   times (& tms_after);
     615                 :          0 :   gettimeofday (&tv_after, NULL);
     616         [ #  # ]:          0 :   if(current_session_for_find_debuginfo->verbose > 1)
     617         [ #  # ]:          0 :     clog << _("Download completed in ")
     618                 :            :               << ((tms_after.tms_cutime + tms_after.tms_utime
     619 [ #  # ][ #  # ]:          0 :               - tms_before.tms_cutime - tms_before.tms_utime) * 1000 / (_sc_clk_tck)) << "usr/"
     620                 :            :               << ((tms_after.tms_cstime + tms_after.tms_stime
     621 [ #  # ][ #  # ]:          0 :               - tms_before.tms_cstime - tms_before.tms_stime) * 1000 / (_sc_clk_tck)) << "sys/"
     622                 :            :               << ((tv_after.tv_sec - tv_before.tv_sec) * 1000 +
     623 [ #  # ][ #  # ]:          0 :               ((long)tv_after.tv_usec - (long)tv_before.tv_usec) / 1000) << "real ms"<< endl;
                 [ #  # ]
     624                 :            : 
     625                 :            :   call_dwfl_standard_find_debuginfo:
     626                 :            : 
     627                 :            :   /* Call the original dwfl_standard_find_debuginfo */
     628                 :            :   return dwfl_standard_find_debuginfo(mod, userdata, modname, base,
     629                 :            :               file_name, debuglink_file,
     630 [ +  - ][ +  - ]:         48 :               debuglink_crc, debuginfo_file_name);
     631                 :            : 
     632                 :            : }
     633                 :            : 
     634                 :            : int
     635                 :          0 : execute_abrt_action_install_debuginfo_to_abrt_cache (string hex)
     636                 :            : {
     637                 :            :   /* Be sure that abrt exists */
     638 [ #  # ][ #  # ]:          0 :   if (abrt_path.empty())
     639                 :          0 :     return -1;
     640                 :            : 
     641                 :          0 :   int timeout = current_session_for_find_debuginfo->download_dbinfo;;
     642         [ #  # ]:          0 :   vector<string> cmd;
     643 [ #  # ][ #  # ]:          0 :   cmd.push_back ("/bin/sh");
                 [ #  # ]
     644 [ #  # ][ #  # ]:          0 :   cmd.push_back ("-c");
                 [ #  # ]
     645                 :            :   
     646                 :            :   /* NOTE: abrt does not currently work with asking for confirmation
     647                 :            :    * in version abrt-2.0.3-1.fc15.x86_64, Bugzilla: BZ726192 */
     648         [ #  # ]:          0 :   if(current_session_for_find_debuginfo->download_dbinfo == -1)
     649                 :            :     {
     650 [ #  # ][ #  # ]:          0 :       cmd.push_back ("echo " + hex + " | " + abrt_path + " --ids=-");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     651                 :          0 :       timeout = INT_MAX; 
     652 [ #  # ][ #  # ]:          0 :       current_session_for_find_debuginfo->print_warning(_("Due to bug in abrt, it may continue downloading anyway without asking for confirmation."));
                 [ #  # ]
     653                 :            :     }
     654                 :            :   else
     655 [ #  # ][ #  # ]:          0 :     cmd.push_back ("echo " + hex + " | " + abrt_path + " -y --ids=-");
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
         [ #  # ][ #  # ]
                 [ #  # ]
     656                 :            :  
     657                 :            :   /* NOTE: abrt does not allow canceling the download process at the moment
     658                 :            :    * in version abrt-2.0.3-1.fc15.x86_64, Bugzilla: BZ730107 */
     659         [ #  # ]:          0 :   if(timeout != INT_MAX)
     660 [ #  # ][ #  # ]:          0 :     current_session_for_find_debuginfo->print_warning(_("Due to a bug in abrt, it  may continue downloading after stopping stap if download times out."));
                 [ #  # ]
     661                 :            :   
     662                 :            :   int pid;
     663 [ #  # ][ #  # ]:          0 :   if(current_session_for_find_debuginfo->verbose > 1 ||  current_session_for_find_debuginfo->download_dbinfo == -1)
     664                 :            :     /* Execute abrt-action-install-debuginfo-to-abrt-cache, 
     665                 :            :      * showing output from abrt */
     666 [ #  # ][ #  # ]:          0 :     pid = stap_spawn(current_session_for_find_debuginfo->verbose, cmd, NULL);
                 [ #  # ]
     667                 :            :   else
     668                 :            :     {
     669                 :            :       /* Execute abrt-action-install-debuginfo-to-abrt-cache,
     670                 :            :        * without showing output from abrt */
     671                 :            :       posix_spawn_file_actions_t fa;
     672         [ #  # ]:          0 :       if (posix_spawn_file_actions_init(&fa) != 0)
     673                 :          0 :         return -1;
     674         [ #  # ]:          0 :       if(posix_spawn_file_actions_addopen(&fa, 1, "/dev/null", O_WRONLY, 0) != 0)
     675                 :            :         {
     676                 :          0 :           posix_spawn_file_actions_destroy(&fa);
     677                 :          0 :           return -1;
     678                 :            :         }
     679 [ #  # ][ #  # ]:          0 :       pid = stap_spawn(current_session_for_find_debuginfo->verbose, cmd, &fa);
                 [ #  # ]
     680                 :          0 :       posix_spawn_file_actions_destroy(&fa);
     681                 :            :     }
     682                 :            : 
     683                 :            :   /* Check to see if either the program successfully completed, or if it timed out. */
     684                 :          0 :   int rstatus = 0;
     685                 :          0 :   int timer = 0;
     686                 :          0 :   int rc = 0;
     687         [ #  # ]:          0 :   while(timer < timeout)
     688                 :            :     {
     689         [ #  # ]:          0 :       sleep(1); 
     690         [ #  # ]:          0 :       rc = waitpid(pid, &rstatus, WNOHANG);
     691         [ #  # ]:          0 :       if(rc < 0)
     692                 :          0 :         return -1;
     693 [ #  # ][ #  # ]:          0 :       if (rc > 0 && WIFEXITED(rstatus)) 
     694                 :          0 :         break;
     695         [ #  # ]:          0 :       assert_no_interrupts();
     696                 :          0 :       timer++;
     697                 :            :     }
     698         [ #  # ]:          0 :   if(timer == timeout)
     699                 :            :     {
     700                 :            :       /* Timed out! */
     701                 :          0 :       kill(-pid, SIGINT);
     702 [ #  # ][ #  # ]:          0 :       current_session_for_find_debuginfo->print_warning(_("Aborted downloading debuginfo: timed out."));
                 [ #  # ]
     703                 :          0 :       return -1;
     704                 :            :     }
     705                 :            : 
     706                 :            :   /* Successfully finished downloading! */
     707                 :            :   #if 0 // Should not print this until BZ733690 is fixed as abrt could fail to download
     708                 :            :         // and it would still print success.
     709                 :            :   if(current_session_for_find_debuginfo->verbose > 1 || current_session_for_find_debuginfo->download_dbinfo == -1)
     710                 :            :      clog << _("Download Completed Successfully!") << endl;
     711                 :            :   #endif
     712 [ #  # ][ #  # ]:          0 :   if(current_session_for_find_debuginfo->verbose > 1 || current_session_for_find_debuginfo->download_dbinfo == -1)
     713 [ #  # ][ #  # ]:          0 :     clog << _("ABRT finished attempting to download debuginfo.") << endl;
     714                 :            : 
     715         [ #  # ]:          0 :   return 0;
     716                 :            : }
     717                 :            : 
     718                 :            : /* Get the kernel build ID */
     719                 :            : string
     720                 :        657 : get_kernel_build_id(systemtap_session &s)
     721                 :            : {
     722                 :        657 :   bool found = false;
     723         [ +  - ]:        657 :   string hex;
     724                 :            : 
     725                 :            :   // Try to find BuildID from vmlinux.id
     726         [ +  - ]:        657 :   string kernel_buildID_path = s.kernel_build_tree + "/vmlinux.id";
     727         [ +  + ]:        657 :   if(s.verbose > 1)
     728 [ +  - ][ +  - ]:          9 :     clog << _F("Attempting to extract kernel debuginfo build ID from %s", kernel_buildID_path.c_str()) << endl;
         [ +  - ][ +  - ]
                 [ +  - ]
     729         [ +  - ]:        657 :   ifstream buildIDfile;
     730 [ +  - ][ +  - ]:        657 :   buildIDfile.open(kernel_buildID_path.c_str());
     731 [ +  - ][ -  + ]:        657 :   if(buildIDfile.is_open())
     732                 :            :     {
     733         [ #  # ]:          0 :       getline(buildIDfile, hex);
     734 [ #  # ][ #  # ]:          0 :       if(buildIDfile.good())
     735                 :            :         {
     736                 :          0 :           found = true;
     737                 :            :         }
     738         [ #  # ]:          0 :       buildIDfile.close();
     739                 :            :     }
     740                 :            : 
     741                 :            :   // Try to find BuildID from the notes file if the above didn't work and we are
     742                 :            :   // building a native module
     743 [ +  - ][ +  - ]:        657 :   if(found == false && s.native_build)
     744                 :            :     {
     745         [ +  + ]:        657 :       if(s.verbose > 1)
     746 [ +  - ][ +  - ]:          9 :         clog << _("Attempting to extract kernel debuginfo build ID from /sys/kernel/notes") << endl;
     747                 :            : 
     748                 :        657 :       const char *notesfile = "/sys/kernel/notes";
     749         [ +  - ]:        657 :       int fd = open64 (notesfile, O_RDONLY);
     750         [ -  + ]:        657 :       if (fd < 0)
     751         [ #  # ]:          0 :       return "";
     752                 :            : 
     753                 :            :       assert (sizeof (Elf32_Nhdr) == sizeof (GElf_Nhdr));
     754                 :            :       assert (sizeof (Elf64_Nhdr) == sizeof (GElf_Nhdr));
     755                 :            : 
     756                 :            :       union
     757                 :            :       {
     758                 :            :         GElf_Nhdr nhdr;
     759                 :            :         unsigned char data[8192];
     760                 :            :       } buf;
     761                 :            : 
     762         [ +  - ]:        657 :       ssize_t n = read (fd, buf.data, sizeof buf);
     763         [ +  - ]:        657 :       close (fd);
     764                 :            : 
     765         [ -  + ]:        657 :       if (n <= 0)
     766         [ #  # ]:          0 :         return "";
     767                 :            : 
     768                 :        657 :       unsigned char *p = buf.data;
     769         [ +  + ]:       1314 :       while (p < &buf.data[n])
     770                 :            :         {
     771                 :            :           /* No translation required since we are reading the native kernel.  */
     772                 :        657 :           GElf_Nhdr *nhdr = (GElf_Nhdr *) p;
     773                 :        657 :           p += sizeof *nhdr;
     774                 :        657 :           unsigned char *name = p;
     775                 :        657 :           p += (nhdr->n_namesz + 3) & -4U;
     776                 :        657 :           unsigned char *bits = p;
     777                 :        657 :           p += (nhdr->n_descsz + 3) & -4U;
     778                 :            : 
     779 [ +  - ][ +  - ]:        657 :           if (p <= &buf.data[n]
         [ +  - ][ +  - ]
     780                 :            :               && nhdr->n_type == NT_GNU_BUILD_ID
     781                 :            :               && nhdr->n_namesz == sizeof "GNU"
     782                 :        657 :               && !memcmp (name, "GNU", sizeof "GNU"))
     783                 :            :             {
     784                 :            :               // Found it.
     785 [ +  - ][ +  - ]:        657 :               hex = hex_dump(bits, nhdr->n_descsz);
                 [ +  - ]
     786                 :        657 :               found = true;
     787                 :            :             }
     788                 :            :         }
     789                 :            :     }
     790         [ +  - ]:        657 :   if(found)
     791                 :            :     {
     792         [ +  - ]:        657 :       return hex;
     793                 :            :     }
     794                 :            :   else
     795 [ #  # ][ +  - ]:        657 :     return "";
         [ +  - ][ +  - ]
     796                 :            : }
     797                 :            : 
     798                 :            : /* Find the kernel build ID and attempt to download the matching debuginfo */
     799                 :          0 : int download_kernel_debuginfo (systemtap_session &s, string hex)
     800                 :            : {
     801                 :            :   // NOTE: At some point we want to base the
     802                 :            :   // already_tried_downloading_kernel_debuginfo flag on the build ID rather
     803                 :            :   // than just the stap process.
     804                 :            : 
     805                 :            :   // Don't try this again if we already did.
     806                 :            :   static int already_tried_downloading_kernel_debuginfo = 0;
     807         [ #  # ]:          0 :   if(already_tried_downloading_kernel_debuginfo)
     808                 :          0 :     return -1;
     809                 :            : 
     810                 :            :   // Attempt to download the debuginfo
     811         [ #  # ]:          0 :   if(s.verbose > 1)
     812 [ #  # ][ #  # ]:          0 :     clog << _F("Success! Extracted kernel debuginfo build ID: %s", hex.c_str()) << endl;
     813         [ #  # ]:          0 :   int rc = execute_abrt_action_install_debuginfo_to_abrt_cache(hex);
     814                 :          0 :   already_tried_downloading_kernel_debuginfo = 1;
     815         [ #  # ]:          0 :   if (rc < 0)
     816                 :          0 :     return -1;
     817                 :            : 
     818                 :            :   // Success!
     819                 :          0 :   return 0;
     820 [ +  - ][ +  - ]:       7242 : }

Generated by: LCOV version 1.9