diff options
author | Josh Stone <jistone@redhat.com> | 2009-07-20 18:01:40 -0700 |
---|---|---|
committer | Josh Stone <jistone@redhat.com> | 2009-07-20 18:08:15 -0700 |
commit | f982c59b2c2b1c25684213c816a69f18a98fea8a (patch) | |
tree | e0d9894b1fc114d79cc25a6a417d311a0c65f430 | |
parent | 9a193b06eb0e5ca463576e4fa9e8da0a70022a4a (diff) | |
download | systemtap-steved-f982c59b2c2b1c25684213c816a69f18a98fea8a.tar.gz systemtap-steved-f982c59b2c2b1c25684213c816a69f18a98fea8a.tar.xz systemtap-steved-f982c59b2c2b1c25684213c816a69f18a98fea8a.zip |
PR10424: Consider each tracepoint header separately
With the current monolithic tracepoint query module, a failure in any of
the discovered tracepoint headers means that you can't use any of the
others either. This patch creates a separate query module for each
header so they can pass or fail independently.
* buildrun.cxx (make_tracequery): take a single header name instead of
globbing for everything we can find.
* hash.cxx (find_tracequery_hash): name the header file we're hashing.
* tapsets.cxx (tracepoint_query::handle_query_func): make sure we don't
duplicate tracepoints found through different headers.
(tracepoint_builder::get_tracequery_module): get a header's module
(tracepoint_builder::init_dw): glob for all tracepoint headers, and
feed all their modules into dwflpp.
-rw-r--r-- | buildrun.cxx | 49 | ||||
-rw-r--r-- | buildrun.h | 1 | ||||
-rw-r--r-- | hash.cxx | 5 | ||||
-rw-r--r-- | hash.h | 2 | ||||
-rw-r--r-- | tapsets.cxx | 78 |
5 files changed, 83 insertions, 52 deletions
diff --git a/buildrun.cxx b/buildrun.cxx index 5967066e..e4b4b7bf 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -27,7 +27,6 @@ extern "C" { #include <unistd.h> #include <string.h> #include <errno.h> -#include <glob.h> } @@ -382,10 +381,15 @@ run_pass (systemtap_session& s) // Build a tiny kernel module to query tracepoints int -make_tracequery(systemtap_session& s, string& name, const vector<string>& extra_headers) +make_tracequery(systemtap_session& s, string& name, + const std::string& header, + const vector<string>& extra_headers) { + static unsigned tick = 0; + string basename("tracequery_kmod_" + lex_cast<string>(++tick)); + // create a subdirectory for the module - string dir(s.tmpdir + "/tracequery"); + string dir(s.tmpdir + "/" + basename); if (create_dir(dir.c_str()) != 0) { if (! s.suppress_warnings) @@ -393,18 +397,18 @@ make_tracequery(systemtap_session& s, string& name, const vector<string>& extra_ return 1; } - name = dir + "/tracequery.ko"; + name = dir + "/" + basename + ".ko"; // create a simple Makefile string makefile(dir + "/Makefile"); ofstream omf(makefile.c_str()); // force debuginfo generation, and relax implicit functions omf << "EXTRA_CFLAGS := -g -Wno-implicit-function-declaration" << endl; - omf << "obj-m := tracequery.o" << endl; + omf << "obj-m := " + basename + ".o" << endl; omf.close(); // create our source file - string source(dir + "/tracequery.c"); + string source(dir + "/" + basename + ".c"); ofstream osrc(source.c_str()); osrc << "#ifdef CONFIG_TRACEPOINTS" << endl; osrc << "#include <linux/tracepoint.h>" << endl; @@ -424,37 +428,8 @@ make_tracequery(systemtap_session& s, string& name, const vector<string>& extra_ for (unsigned z=0; z<extra_headers.size(); z++) osrc << "#include <" << extra_headers[z] << ">\n"; - // dynamically pull in all tracepoint headers from include/trace/ - glob_t trace_glob; - string globs[] = { - "/include/trace/*.h", - "/include/trace/events/*.h", - "/source/include/trace/*.h", - "/source/include/trace/events/*.h", - }; - for (unsigned z = 0; z < sizeof(globs) / sizeof(globs[0]); z++) - { - string glob_str(s.kernel_build_tree + globs[z]); - glob(glob_str.c_str(), 0, NULL, &trace_glob); - for (unsigned i = 0; i < trace_glob.gl_pathc; ++i) - { - string header(trace_glob.gl_pathv[i]); - size_t root_pos = header.rfind("/include/"); - assert(root_pos != string::npos); - header.erase(0, root_pos + 9); - - // filter out a few known "internal-only" headers - if (header.find("/ftrace.h") != string::npos) - continue; - if (header.find("/trace_events.h") != string::npos) - continue; - if (header.find("_event_types.h") != string::npos) - continue; - - osrc << "#include <" << header << ">" << endl; - } - globfree(&trace_glob); - } + // add the requested tracepoint header + osrc << "#include <" << header << ">" << endl; // finish up the module source osrc << "#endif /* CONFIG_TRACEPOINTS */" << endl; @@ -15,6 +15,7 @@ int compile_pass (systemtap_session& s); int run_pass (systemtap_session& s); int make_tracequery(systemtap_session& s, std::string& name, + const std::string& header, const std::vector<std::string>& extra_headers); int make_typequery(systemtap_session& s, std::string& module); @@ -257,12 +257,13 @@ find_hash (systemtap_session& s, const string& script) string -find_tracequery_hash (systemtap_session& s) +find_tracequery_hash (systemtap_session& s, const string& header) { hash h; get_base_hash(s, h); - // The basic hash should be good enough for the tracepoint query module + // Add the tracepoint header to the computed hash + h.add_file(header); // Get the directory path to store our cached module string result, hashdir; @@ -36,7 +36,7 @@ public: }; void find_hash (systemtap_session& s, const std::string& script); -std::string find_tracequery_hash (systemtap_session& s); +std::string find_tracequery_hash (systemtap_session& s, const std::string& header); std::string find_typequery_hash (systemtap_session& s, const std::string& name); /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ diff --git a/tapsets.cxx b/tapsets.cxx index bb6f0daa..b9684641 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -5603,6 +5603,7 @@ struct tracepoint_query : public base_query probe * base_probe; probe_point * base_loc; vector<derived_probe *> & results; + set<string> probed_names; void handle_query_module(); int handle_query_cu(Dwarf_Die * cudie); @@ -5639,6 +5640,12 @@ tracepoint_query::handle_query_func(Dwarf_Die * func) assert(dw.function_name.compare(0, 10, "stapprobe_") == 0); string tracepoint_instance = dw.function_name.substr(10); + + // check for duplicates -- sometimes tracepoint headers may be indirectly + // included in more than one of our tracequery modules. + if (!probed_names.insert(tracepoint_instance).second) + return DWARF_CB_OK; + derived_probe *dp = new tracepoint_derived_probe (dw.sess, dw, *func, tracepoint_instance, base_probe, base_loc); @@ -5670,6 +5677,7 @@ struct tracepoint_builder: public derived_probe_builder private: dwflpp *dw; bool init_dw(systemtap_session& s); + string get_tracequery_module(systemtap_session& s, const string& header); public: @@ -5691,17 +5699,15 @@ public: }; -bool -tracepoint_builder::init_dw(systemtap_session& s) +string +tracepoint_builder::get_tracequery_module(systemtap_session& s, + const string& header) { - if (dw != NULL) - return true; - string tracequery_path; if (s.use_cache) { // see if the cached module exists - tracequery_path = find_tracequery_hash(s); + tracequery_path = find_tracequery_hash(s, header); if (!tracequery_path.empty()) { int fd = open(tracequery_path.c_str(), O_RDONLY); @@ -5709,19 +5715,23 @@ tracepoint_builder::init_dw(systemtap_session& s) { if (s.verbose > 2) clog << "Pass 2: using cached " << tracequery_path << endl; - - dw = new dwflpp(s, tracequery_path, false); close(fd); - return true; + return tracequery_path; } } } // no cached module, time to make it + + size_t root_pos = header.rfind("/include/"); + string short_header = (root_pos != string::npos) ? + header.substr(root_pos + 9) : header; + string tracequery_ko; - int rc = make_tracequery(s, tracequery_ko, tracepoint_extra_headers()); + int rc = make_tracequery(s, tracequery_ko, short_header, + tracepoint_extra_headers()); if (rc != 0) - return false; + return ""; if (s.use_cache) { @@ -5734,8 +5744,52 @@ tracepoint_builder::init_dw(systemtap_session& s) cerr << "Copy failed (\"" << tracequery_ko << "\" to \"" << tracequery_path << "\"): " << strerror(errno) << endl; } + return tracequery_ko; +} + + +bool +tracepoint_builder::init_dw(systemtap_session& s) +{ + if (dw != NULL) + return true; + + vector<string> tracequery_modules; + + glob_t trace_glob; + string globs[] = { + "/include/trace/*.h", + "/include/trace/events/*.h", + "/source/include/trace/*.h", + "/source/include/trace/events/*.h", + }; + for (unsigned z = 0; z < sizeof(globs) / sizeof(globs[0]); z++) + { + string glob_str(s.kernel_build_tree + globs[z]); + glob(glob_str.c_str(), 0, NULL, &trace_glob); + for (unsigned i = 0; i < trace_glob.gl_pathc; ++i) + { + string header(trace_glob.gl_pathv[i]); + + // filter out a few known "internal-only" headers + if (header.find("/ftrace.h") != string::npos) + continue; + if (header.find("/trace_events.h") != string::npos) + continue; + if (header.find("_event_types.h") != string::npos) + continue; + + string tracequery_path = get_tracequery_module(s, header); + if (!tracequery_path.empty()) + tracequery_modules.push_back(tracequery_path); + } + globfree(&trace_glob); + } + + // TODO: consider other sources of tracepoint headers too, like from + // a command-line parameter or some environment or .systemtaprc - dw = new dwflpp(s, tracequery_ko, false); + dw = new dwflpp(s, tracequery_modules); return true; } |