diff options
author | Mark Wielaard <mjw@redhat.com> | 2009-09-30 16:51:29 +0200 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2009-09-30 16:51:29 +0200 |
commit | 27993a166c3ff2c33f778da4d96726666aadfab9 (patch) | |
tree | 2fd5fab6c2ddc72d44b08b1c545bc427c893b865 /setupdwfl.cxx | |
parent | 469c1a1b2ef323030531b0ca05e6f9337c0bbbe6 (diff) | |
download | systemtap-steved-27993a166c3ff2c33f778da4d96726666aadfab9.tar.gz systemtap-steved-27993a166c3ff2c33f778da4d96726666aadfab9.tar.xz systemtap-steved-27993a166c3ff2c33f778da4d96726666aadfab9.zip |
PR10678 module reloc refers to symbol in dwarf refer to kernel symbols.
First part of a fix for PR10678. Always include the kernel in the dwfl.
This doesn't seem to impact performance noticable, so for now enable
always.
* setupdwfl.cxx (setup_dwfl_done): New variable, used to clean up logic
in setup_dwfl_report_kernel_p().
(setup_all_deps): New static bool to indicate we want all deps (just
the kernel for now, other modules coming).
(setup_dwfl_report_kernel_p): Use new variables, shortcut kernel
inclusion.
(setup_dwfl_kernel): Setup setup_dwfl_done (false).
Diffstat (limited to 'setupdwfl.cxx')
-rw-r--r-- | setupdwfl.cxx | 47 |
1 files changed, 35 insertions, 12 deletions
diff --git a/setupdwfl.cxx b/setupdwfl.cxx index c6cfba6e..554f4e54 100644 --- a/setupdwfl.cxx +++ b/setupdwfl.cxx @@ -63,10 +63,20 @@ static const char *offline_search_modname; static set<string> offline_search_names; static unsigned offline_modules_found; +// Whether or not we are done reporting kernel modules in +// set_dwfl_report_kernel_p(). +static bool setup_dwfl_done; + // Kept for user_dwfl cache, user modules don't allow wildcards, so // just keep the set of module strings. static set<string> user_modset; +// Determines whether or not we will make setup_dwfl_report_kernel_p +// report true for all module dependencies. This is necessary for +// correctly resolving some dwarf constructs that relocate against +// symbols in vmlinux and/or other modules they depend on. See PR10678. +static const bool setup_all_deps = true; + // 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 @@ -74,13 +84,28 @@ static set<string> user_modset; static int setup_dwfl_report_kernel_p(const char* modname, const char* filename) { - if (pending_interrupts) + if (pending_interrupts || setup_dwfl_done) return -1; // elfutils sends us NULL filenames sometimes if it can't find dwarf if (filename == NULL) return 0; + // Check kernel first since it is often the only thing needed, + // then we never have to parse and setup the module deps map. + // It will be reported as the very first thing. + if (setup_all_deps && ! strcmp (modname, "kernel")) + { + if ((offline_search_modname != NULL + && ! strcmp (offline_search_modname, "kernel")) + || (offline_search_names.size() == 1 + && *offline_search_names.begin() == "kernel")) + setup_dwfl_done = true; + + offline_modules_found++; + return 1; + } + // If offline_search_modname is setup use it (either as regexp or // explicit module/kernel name) and ignore offline_search_names. // Otherwise use offline_search_names exclusively. @@ -96,31 +121,27 @@ setup_dwfl_report_kernel_p(const char* modname, const char* filename) return match_p; } else - { /* non-wildcard mode */ - if (offline_modules_found) - return -1; // Done, only one name needed and found it. - - /* Reject mismatching module names */ + { /* non-wildcard mode, reject mismatching module names */ if (strcmp(modname, offline_search_modname)) return 0; else { + // Done, only one name needed and found it. offline_modules_found++; + setup_dwfl_done = true; return 1; } } } else - { /* find all in set mode */ - if (offline_search_names.size() == offline_modules_found) - return -1; - - /* Reject mismatching module names */ + { /* find all in set mode, reject mismatching module names */ if (offline_search_names.find(modname) == offline_search_names.end()) return 0; else { offline_modules_found++; + if (offline_search_names.size() == offline_modules_found) + setup_dwfl_done = true; return 1; } } @@ -168,6 +189,7 @@ setup_dwfl_kernel (unsigned *modules_found, systemtap_session &s) // We always need this, even when offline_search_modname is NULL // and offline_search_names is empty because we still might want // the kernel vmlinux reported. + setup_dwfl_done = false; int rc = dwfl_linux_kernel_report_offline (dwfl, elfutils_kernel_path.c_str(), &setup_dwfl_report_kernel_p); @@ -306,7 +328,8 @@ setup_dwfl_user(std::vector<std::string>::const_iterator &begin, return user_dwfl; } -bool is_user_module(const std::string &m) +bool +is_user_module(const std::string &m) { return m[0] == '/' && m.rfind(".ko", m.length() - 1) != m.length() - 3; } |