diff options
-rw-r--r-- | setupdwfl.cxx | 108 | ||||
-rw-r--r-- | testsuite/buildok/pr10678.stp | 4 |
2 files changed, 111 insertions, 1 deletions
diff --git a/setupdwfl.cxx b/setupdwfl.cxx index 554f4e54..32274615 100644 --- a/setupdwfl.cxx +++ b/setupdwfl.cxx @@ -13,6 +13,10 @@ #include "dwflpp.h" #include "session.h" +#include <algorithm> +#include <iostream> +#include <fstream> +#include <sstream> #include <set> #include <string> @@ -77,6 +81,107 @@ static set<string> user_modset; // symbols in vmlinux and/or other modules they depend on. See PR10678. static const bool setup_all_deps = true; +// Where to find the kernel (and the Modules.dep file). Setup in +// setup_dwfl_kernel(), used by dwfl_linux_kernel_report_offline() and +// setup_mod_deps(). +static string elfutils_kernel_path; + +static bool is_comma_dash(const char c) { return (c == ',' || c == '-'); } + +// The module name is the basename (without the extension) of the +// module path, with ',' and '-' replaced by '_'. +static string +modname_from_path(const string &path) +{ + size_t dot = path.rfind('.'); + size_t slash = path.rfind('/'); + if (dot == string::npos || slash == string::npos || dot < slash) + return ""; + string name = path.substr(slash + 1, dot - slash - 1); + replace_if(name.begin(), name.end(), is_comma_dash, '_'); + return name; +} + +// Try to parse modules.dep file, +// Simple format: module path (either full or relative), colon, +// (possibly empty) space delimited list of module (path) +// dependencies. +static void +setup_mod_deps() +{ + string modulesdep; + ifstream in; + string l; + + if (elfutils_kernel_path[0] == '/') + { + modulesdep = elfutils_kernel_path; + modulesdep += "/modules.dep"; + } + else + { + modulesdep = "/lib/modules/"; + modulesdep += elfutils_kernel_path; + modulesdep += "/modules.dep"; + } + in.open(modulesdep.c_str()); + if (in.fail ()) + return; + + while (getline (in, l)) + { + size_t off = l.find (':'); + if (off != string::npos) + { + string modpath, modname; + modpath = l.substr (0, off); + modname = modname_from_path (modpath); + if (modname == "") + continue; + + bool dep_needed; + if (offline_search_modname != NULL) + { + if (dwflpp::name_has_wildcard (offline_search_modname)) + { + dep_needed = !fnmatch (offline_search_modname, + modname.c_str (), 0); + if (dep_needed) + offline_search_names.insert (modname); + } + else + { + dep_needed = ! strcmp(modname.c_str (), + offline_search_modname); + if (dep_needed) + offline_search_names.insert (modname); + } + } + else + dep_needed = (offline_search_names.find (modname) + != offline_search_names.end ()); + + if (! dep_needed) + continue; + + string depstring = l.substr (off + 1); + if (depstring.size () > 0) + { + stringstream ss (depstring); + string deppath; + while (ss >> deppath) + offline_search_names.insert (modname_from_path(deppath)); + + } + } + } + + // We always want kernel (needed in list so size checks match). + // Everything needed now stored in offline_search_names. + offline_search_names.insert ("kernel"); + offline_search_modname = NULL; +} + // Set up our offline search for kernel modules. We don't want the // offline search iteration to do a complete search of the kernel // build tree, since that's wasteful, so create a predicate that @@ -101,6 +206,8 @@ setup_dwfl_report_kernel_p(const char* modname, const char* filename) || (offline_search_names.size() == 1 && *offline_search_names.begin() == "kernel")) setup_dwfl_done = true; + else + setup_mod_deps(); offline_modules_found++; return 1; @@ -162,7 +269,6 @@ setup_dwfl_kernel (unsigned *modules_found, systemtap_session &s) // no way to set the dwfl_callback.debuginfo_path and always // passs the plain kernel_release here. So instead we have to // hard-code this magic here. - string elfutils_kernel_path; if (s.kernel_build_tree == string("/lib/modules/" + s.kernel_release + "/build")) diff --git a/testsuite/buildok/pr10678.stp b/testsuite/buildok/pr10678.stp new file mode 100644 index 00000000..4ce8fb99 --- /dev/null +++ b/testsuite/buildok/pr10678.stp @@ -0,0 +1,4 @@ +#! stap -p4 + +# The ne2k_pci module dwarf refers to both kernel and 8390 module symbols +probe module("ne2k_pci").function("ne2k_pci_open") { log($$parms); }
\ No newline at end of file |