summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMark Wielaard <mjw@redhat.com>2009-09-29 16:45:37 +0200
committerMark Wielaard <mjw@redhat.com>2009-09-29 16:45:37 +0200
commit68983551cc9390aa2bddd8e62ed0f0e3eca1edb6 (patch)
tree98dc1f189dac99351989f7167b84a88f39d6a86c
parent497f19d74912d0b6adf729f88509c71a45cacdd4 (diff)
downloadsystemtap-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.cxx25
-rw-r--r--dwflpp.h3
-rw-r--r--setupdwfl.cxx90
-rw-r--r--setupdwfl.h33
-rw-r--r--translate.cxx15
5 files changed, 114 insertions, 52 deletions
diff --git a/dwflpp.cxx b/dwflpp.cxx
index b8e39b69..c611dbe3 100644
--- a/dwflpp.cxx
+++ b/dwflpp.cxx
@@ -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);
diff --git a/dwflpp.h b/dwflpp.h
index 979ec868..226b84d8 100644
--- a/dwflpp.h
+++ b/dwflpp.h
@@ -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);