diff options
author | Mark Wielaard <mjw@redhat.com> | 2009-09-29 16:45:37 +0200 |
---|---|---|
committer | Mark Wielaard <mjw@redhat.com> | 2009-09-29 16:45:37 +0200 |
commit | 68983551cc9390aa2bddd8e62ed0f0e3eca1edb6 (patch) | |
tree | 98dc1f189dac99351989f7167b84a88f39d6a86c | |
parent | 497f19d74912d0b6adf729f88509c71a45cacdd4 (diff) | |
download | systemtap-steved-68983551cc9390aa2bddd8e62ed0f0e3eca1edb6.tar.gz systemtap-steved-68983551cc9390aa2bddd8e62ed0f0e3eca1edb6.tar.xz systemtap-steved-68983551cc9390aa2bddd8e62ed0f0e3eca1edb6.zip |
Cache Dwfl's for reuse between pass 2 and pass 3.
* setupdwfl.h: Introduce DwflPtr.
* setupdwfl.cxx: Cache kernel_dwfl and user_dwfl. Keep track of last used
module strings. Return cached versions if same query used.
* dwflpp.h: Use DwflPtr instead of Dwfl*.
* dwflpp.cxx: Use DwflPtr and don't dwfl_end().
* translate.cxx: Likewise. Run through dwfl_getmodules() with returned
ptr offset.
-rw-r--r-- | dwflpp.cxx | 25 | ||||
-rw-r--r-- | dwflpp.h | 3 | ||||
-rw-r--r-- | setupdwfl.cxx | 90 | ||||
-rw-r--r-- | setupdwfl.h | 33 | ||||
-rw-r--r-- | translate.cxx | 15 |
5 files changed, 114 insertions, 52 deletions
@@ -70,7 +70,7 @@ static string TOK_KERNEL("kernel"); dwflpp::dwflpp(systemtap_session & session, const string& name, bool kernel_p): sess(session), module(NULL), module_bias(0), mod_info(NULL), - module_start(0), module_end(0), cu(NULL), dwfl(NULL), + module_start(0), module_end(0), cu(NULL), module_dwarf(NULL), function(NULL), blacklist_enabled(false) { if (kernel_p) @@ -86,7 +86,7 @@ dwflpp::dwflpp(systemtap_session & session, const string& name, bool kernel_p): dwflpp::dwflpp(systemtap_session & session, const vector<string>& names, bool kernel_p): sess(session), module(NULL), module_bias(0), mod_info(NULL), - module_start(0), module_end(0), cu(NULL), dwfl(NULL), + module_start(0), module_end(0), cu(NULL), module_dwarf(NULL), function(NULL), blacklist_enabled(false) { if (kernel_p) @@ -103,8 +103,7 @@ dwflpp::~dwflpp() delete_map(global_alias_cache); delete_map(cu_die_parent_cache); - if (dwfl) - dwfl_end(dwfl); + dwfl_ptr.reset(); } @@ -208,7 +207,7 @@ Dwarf_Die * dwflpp::query_cu_containing_address(Dwarf_Addr a) { Dwarf_Addr bias; - assert(dwfl); + assert(dwfl_ptr.get()->dwfl); assert(module); get_module_dwarf(); @@ -303,7 +302,7 @@ dwflpp::setup_kernel(const string& name, bool debuginfo_needed) sess.module_cache = new module_cache (); unsigned offline_search_matches = 0; - dwfl = setup_dwfl_kernel(name, &offline_search_matches, sess); + dwfl_ptr = setup_dwfl_kernel(name, &offline_search_matches, sess); if (offline_search_matches < 1) { @@ -328,9 +327,9 @@ dwflpp::setup_kernel(const vector<string> &names, bool debuginfo_needed) unsigned offline_search_matches = 0; set<string> offline_search_names(names.begin(), names.end()); - dwfl = setup_dwfl_kernel(offline_search_names, - &offline_search_matches, - sess); + dwfl_ptr = setup_dwfl_kernel(offline_search_names, + &offline_search_matches, + sess); if (offline_search_matches < offline_search_names.size()) { @@ -355,14 +354,14 @@ dwflpp::setup_user(const vector<string>& modules, bool debuginfo_needed) sess.module_cache = new module_cache (); vector<string>::const_iterator it = modules.begin(); - dwfl = setup_dwfl_user(it, modules.end(), debuginfo_needed); + dwfl_ptr = setup_dwfl_user(it, modules.end(), debuginfo_needed); if (debuginfo_needed && it != modules.end()) dwfl_assert (string("missing process ") + *it + string(" ") + sess.architecture + string(" debuginfo"), - dwfl); + dwfl_ptr.get()->dwfl); } void @@ -371,7 +370,7 @@ dwflpp::iterate_over_modules(int (* callback)(Dwfl_Module *, void **, void *), base_query *data) { - dwfl_getmodules (dwfl, callback, data, 0); + dwfl_getmodules (dwfl_ptr.get()->dwfl, callback, data, 0); // Don't complain if we exited dwfl_getmodules early. // This could be a $target variable error that will be @@ -1457,7 +1456,7 @@ dwflpp::emit_address (struct obstack *pool, Dwarf_Addr address) // Turn this address into a section-relative offset if it should be one. // We emit a comment approximating the variable+offset expression that // relocatable module probing code will need to have. - Dwfl_Module *mod = dwfl_addrmodule (dwfl, address); + Dwfl_Module *mod = dwfl_addrmodule (dwfl_ptr.get()->dwfl, address); dwfl_assert ("dwfl_addrmodule", mod); const char *modname = dwfl_module_info (mod, NULL, NULL, NULL, NULL, NULL, NULL, NULL); @@ -16,6 +16,7 @@ #include "elaborate.h" #include "session.h" #include "unordered.h" +#include "setupdwfl.h" #include <cstring> #include <iostream> @@ -286,7 +287,7 @@ struct dwflpp private: - Dwfl * dwfl; + DwflPtr dwfl_ptr; // These are "current" values we focus on. Dwarf * module_dwarf; diff --git a/setupdwfl.cxx b/setupdwfl.cxx index f5a306be..c6cfba6e 100644 --- a/setupdwfl.cxx +++ b/setupdwfl.cxx @@ -50,13 +50,22 @@ static const Dwfl_Callbacks user_callbacks = using namespace std; +// Store last kernel and user Dwfl for reuse since they are often +// re-requested (in phase 2 and then in phase 3). +static DwflPtr kernel_dwfl; +static DwflPtr user_dwfl; + // Setup in setup_dwfl_kernel(), for use in setup_dwfl_report_kernel_p(). // Either offline_search_modname or offline_search_names is // used. When offline_search_modname is not NULL then // offline_search_names is ignored. static const char *offline_search_modname; static set<string> offline_search_names; -static unsigned *offline_modules_found; +static unsigned offline_modules_found; + +// Kept for user_dwfl cache, user modules don't allow wildcards, so +// just keep the set of module strings. +static set<string> user_modset; // Set up our offline search for kernel modules. We don't want the // offline search iteration to do a complete search of the kernel @@ -83,12 +92,12 @@ setup_dwfl_report_kernel_p(const char* modname, const char* filename) // In the wildcard case, we don't short-circuit (return -1) // analogously to dwflpp::module_name_final_match(). if (match_p) - (*offline_modules_found)++; + offline_modules_found++; return match_p; } else { /* non-wildcard mode */ - if (*offline_modules_found) + if (offline_modules_found) return -1; // Done, only one name needed and found it. /* Reject mismatching module names */ @@ -96,14 +105,14 @@ setup_dwfl_report_kernel_p(const char* modname, const char* filename) return 0; else { - (*offline_modules_found)++; + offline_modules_found++; return 1; } } } else { /* find all in set mode */ - if (offline_search_names.empty()) + if (offline_search_names.size() == offline_modules_found) return -1; /* Reject mismatching module names */ @@ -111,14 +120,13 @@ setup_dwfl_report_kernel_p(const char* modname, const char* filename) return 0; else { - offline_search_names.erase(modname); - (*offline_modules_found)++; + offline_modules_found++; return 1; } } } -static Dwfl * +static DwflPtr setup_dwfl_kernel (unsigned *modules_found, systemtap_session &s) { Dwfl *dwfl = dwfl_begin (&kernel_callbacks); @@ -141,8 +149,7 @@ setup_dwfl_kernel (unsigned *modules_found, systemtap_session &s) else elfutils_kernel_path = s.kernel_build_tree; - offline_modules_found = modules_found; - *offline_modules_found = 0; + offline_modules_found = 0; // First try to report full path modules. set<string>::iterator it = offline_search_names.begin(); @@ -153,8 +160,7 @@ setup_dwfl_kernel (unsigned *modules_found, systemtap_session &s) const char *cname = (*it).c_str(); Dwfl_Module *mod = dwfl_report_offline (dwfl, cname, cname, -1); if (mod) - (*offline_modules_found)++; - offline_search_names.erase(it); + offline_modules_found++; } it++; } @@ -176,10 +182,15 @@ setup_dwfl_kernel (unsigned *modules_found, systemtap_session &s) // run time. See the dwarf_derived_probe ctor and its caller. dwfl_assert ("dwfl_report_end", dwfl_report_end(dwfl, NULL, NULL)); - return dwfl; + *modules_found = offline_modules_found; + + StapDwfl *stap_dwfl = new StapDwfl(dwfl); + kernel_dwfl = DwflPtr(stap_dwfl); + + return kernel_dwfl; } -Dwfl* +DwflPtr setup_dwfl_kernel(const std::string &name, unsigned *found, systemtap_session &s) @@ -189,31 +200,55 @@ setup_dwfl_kernel(const std::string &name, /* Support full path kernel modules, these cannot be regular expressions, so just put them in the search set. */ - if (name[0] == '/') + if (name[0] == '/' || ! dwflpp::name_has_wildcard (modname)) { names.insert(name); modname = NULL; } + if (kernel_dwfl != NULL + && offline_search_modname == modname + && offline_search_names == names) + { + *found = offline_modules_found; + return kernel_dwfl; + } + offline_search_modname = modname; offline_search_names = names; return setup_dwfl_kernel(found, s); } -Dwfl* +DwflPtr setup_dwfl_kernel(const std::set<std::string> &names, unsigned *found, systemtap_session &s) { + if (kernel_dwfl != NULL + && offline_search_modname == NULL + && offline_search_names == names) + { + *found = offline_modules_found; + return kernel_dwfl; + } + offline_search_modname = NULL; offline_search_names = names; return setup_dwfl_kernel(found, s); } -Dwfl* +DwflPtr setup_dwfl_user(const std::string &name) { + if (user_dwfl != NULL + && user_modset.size() == 1 + && (*user_modset.begin()) == name) + return user_dwfl; + + user_modset.clear(); + user_modset.insert(name); + Dwfl *dwfl = dwfl_begin (&user_callbacks); dwfl_assert("dwfl_begin", dwfl); dwfl_report_begin (dwfl); @@ -227,14 +262,25 @@ setup_dwfl_user(const std::string &name) dwfl_end(dwfl); dwfl = NULL; } - return dwfl; + + StapDwfl *stap_dwfl = new StapDwfl(dwfl); + user_dwfl = DwflPtr(stap_dwfl); + + return user_dwfl; } -Dwfl* +DwflPtr setup_dwfl_user(std::vector<std::string>::const_iterator &begin, const std::vector<std::string>::const_iterator &end, bool all_needed) { + // See if we have this dwfl already cached + set<string> modset(begin, end); + if (user_dwfl != NULL && modset == user_modset) + return user_dwfl; + + user_modset = modset; + Dwfl *dwfl = dwfl_begin (&user_callbacks); dwfl_assert("dwfl_begin", dwfl); dwfl_report_begin (dwfl); @@ -253,7 +299,11 @@ setup_dwfl_user(std::vector<std::string>::const_iterator &begin, } if (dwfl) dwfl_assert ("dwfl_report_end", dwfl_report_end(dwfl, NULL, NULL)); - return dwfl; + + StapDwfl *stap_dwfl = new StapDwfl(dwfl); + user_dwfl = DwflPtr(stap_dwfl); + + return user_dwfl; } bool is_user_module(const std::string &m) diff --git a/setupdwfl.h b/setupdwfl.h index 67a66397..743ce668 100644 --- a/setupdwfl.h +++ b/setupdwfl.h @@ -16,21 +16,32 @@ #include <string> #include <vector> +#include <tr1/memory> + extern "C" { #include <elfutils/libdwfl.h> } -Dwfl *setup_dwfl_kernel(const std::string &name, - unsigned *found, - systemtap_session &s); -Dwfl *setup_dwfl_kernel(const std::set<std::string> &names, - unsigned *found, - systemtap_session &s); - -Dwfl* setup_dwfl_user(const std::string &name); -Dwfl* setup_dwfl_user(std::vector<std::string>::const_iterator &begin, - const std::vector<std::string>::const_iterator &end, - bool all_needed); +struct StapDwfl +{ +public: + StapDwfl(Dwfl *d) : dwfl(d) { } + ~StapDwfl() { if (dwfl) dwfl_end (dwfl); } + Dwfl *dwfl; +}; +typedef std::tr1::shared_ptr<StapDwfl> DwflPtr; + +DwflPtr setup_dwfl_kernel(const std::string &name, + unsigned *found, + systemtap_session &s); +DwflPtr setup_dwfl_kernel(const std::set<std::string> &names, + unsigned *found, + systemtap_session &s); + +DwflPtr setup_dwfl_user(const std::string &name); +DwflPtr setup_dwfl_user(std::vector<std::string>::const_iterator &begin, + const std::vector<std::string>::const_iterator &end, + bool all_needed); // user-space files must be full paths and not end in .ko bool is_user_module(const std::string &m); diff --git a/translate.cxx b/translate.cxx index 0f53dc78..a3246d9c 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4962,7 +4962,8 @@ emit_symbol_data (systemtap_session& s) offline searches. */ offline_search_modules.insert (foo); } - Dwfl *dwfl = setup_dwfl_kernel (offline_search_modules, &count, s); + DwflPtr dwfl_ptr = setup_dwfl_kernel (offline_search_modules, &count, s); + Dwfl *dwfl = dwfl_ptr.get()->dwfl; dwfl_assert("all kernel modules found", count >= offline_search_modules.size()); @@ -4971,12 +4972,11 @@ emit_symbol_data (systemtap_session& s) { if (pending_interrupts) return; if (ctx.undone_unwindsym_modules.empty()) break; - off = dwfl_getmodules (dwfl, &dump_unwindsyms, (void *) &ctx, 0); + off = dwfl_getmodules (dwfl, &dump_unwindsyms, (void *) &ctx, off); } while (off > 0); dwfl_assert("dwfl_getmodules", off == 0); - dwfl_end(dwfl); - + dwfl_ptr.reset(); // ---- step 2: process any user modules (files) listed for (std::set<std::string>::iterator it = s.unwindsym_modules.begin(); @@ -4986,7 +4986,8 @@ emit_symbol_data (systemtap_session& s) string modname = *it; assert (modname.length() != 0); if (! is_user_module (modname)) continue; - Dwfl *dwfl = setup_dwfl_user (modname); + DwflPtr dwfl_ptr = setup_dwfl_user (modname); + Dwfl *dwfl = dwfl_ptr.get()->dwfl; if (dwfl != NULL) // tolerate missing data; will warn below { ptrdiff_t off = 0; @@ -4994,12 +4995,12 @@ emit_symbol_data (systemtap_session& s) { if (pending_interrupts) return; if (ctx.undone_unwindsym_modules.empty()) break; - off = dwfl_getmodules (dwfl, &dump_unwindsyms, (void *) &ctx, 0); + off = dwfl_getmodules (dwfl, &dump_unwindsyms, (void *) &ctx, off); } while (off > 0); dwfl_assert("dwfl_getmodules", off == 0); } - dwfl_end(dwfl); + dwfl_ptr.reset(); } emit_symbol_data_done (&ctx, s); |