summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordsmith <dsmith>2006-10-11 14:56:09 +0000
committerdsmith <dsmith>2006-10-11 14:56:09 +0000
commit1d3a40b69576b5509671647e556b79ff5d6d17b7 (patch)
tree3d412ded6c556114fbd683076a5585a2a909fc1b
parent6e5aef4f27a2d02de416539062987acbf209e841 (diff)
downloadsystemtap-steved-1d3a40b69576b5509671647e556b79ff5d6d17b7.tar.gz
systemtap-steved-1d3a40b69576b5509671647e556b79ff5d6d17b7.tar.xz
systemtap-steved-1d3a40b69576b5509671647e556b79ff5d6d17b7.zip
2006-10-11 David Smith <dsmith@redhat.com>
* tapsets.cxx (in_kprobes_function): New function that looks up the values of '__kprobes_text_start' and '__kprobes_text_end' in the kernel to be able to automatically exclude functions marked as '__kprobes' (BZ# 2639). (blacklisted_p): Calls in_kprobes_function(). (query_kernel_module): Utility function that finds the kernel module. * session.h (struct systemtap_session): Added kprobes_text variables - kprobes_text_initialized, kprobes_text_start, and kprobes_text_end. * elaborate.cxx (systemtap_session::systemtap_session): kprobes_text variables get initialized.
-rw-r--r--ChangeLog14
-rw-r--r--elaborate.cxx5
-rw-r--r--session.h9
-rw-r--r--tapsets.cxx89
4 files changed, 116 insertions, 1 deletions
diff --git a/ChangeLog b/ChangeLog
index 5a62eb46..ae8a6b1d 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2006-10-11 David Smith <dsmith@redhat.com>
+
+ * tapsets.cxx (in_kprobes_function): New function that looks up
+ the values of '__kprobes_text_start' and '__kprobes_text_end' in
+ the kernel to be able to automatically exclude functions marked as
+ '__kprobes' (BZ# 2639).
+ (blacklisted_p): Calls in_kprobes_function().
+ (query_kernel_module): Utility function that finds the kernel module.
+ * session.h (struct systemtap_session): Added kprobes_text
+ variables - kprobes_text_initialized, kprobes_text_start, and
+ kprobes_text_end.
+ * elaborate.cxx (systemtap_session::systemtap_session):
+ kprobes_text variables get initialized.
+
2006-10-10 Roland McGrath <roland@redhat.com>
* systemtap.spec.in (elfutils_version): Require 0.124 now.
diff --git a/elaborate.cxx b/elaborate.cxx
index c3b9cbe9..99126fb5 100644
--- a/elaborate.cxx
+++ b/elaborate.cxx
@@ -997,7 +997,10 @@ semantic_pass (systemtap_session& s)
systemtap_session::systemtap_session ():
pattern_root(new match_node),
- user_file (0), op (0), up (0), num_errors (0)
+ user_file (0), op (0), up (0),
+ kprobes_text_initialized (false),
+ kprobes_text_start (0), kprobes_text_end (0),
+ num_errors (0)
{
}
diff --git a/session.h b/session.h
index fa8d375a..75e13136 100644
--- a/session.h
+++ b/session.h
@@ -16,6 +16,10 @@
#include <sstream>
#include <map>
+extern "C" {
+#include <elfutils/libdw.h>
+}
+
// forward decls for all referenced systemtap types
struct match_node;
@@ -109,6 +113,11 @@ struct systemtap_session
translator_output* op;
unparser* up;
+ // kprobes_text data
+ bool kprobes_text_initialized;
+ Dwarf_Addr kprobes_text_start;
+ Dwarf_Addr kprobes_text_end;
+
unsigned num_errors;
// void print_error (const parse_error& e);
void print_error (const semantic_error& e);
diff --git a/tapsets.cxx b/tapsets.cxx
index 199f71a0..d2d4b9c2 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -2285,6 +2285,68 @@ target_variable_flavour_calculating_visitor::visit_target_symbol (target_symbol
}
+// Forward declaration.
+static int query_kernel_module (Dwfl_Module *, void **, const char *,
+ Dwarf_Addr, void *);
+
+
+static bool
+in_kprobes_function(systemtap_session& sess, Dwarf_Addr addr)
+{
+ if (! sess.kprobes_text_initialized)
+ {
+ // Only attempt kprobes_text_start/kprobes_text_end
+ // initialization once
+ sess.kprobes_text_initialized = true;
+
+ dwflpp *kernel_dw = new dwflpp(sess);
+ assert(kernel_dw);
+ kernel_dw->setup(true);
+
+ Dwfl_Module *m = NULL;
+ kernel_dw->iterate_over_modules(&query_kernel_module, &m);
+ assert(m);
+ kernel_dw->focus_on_module(m);
+
+ // Look through the symbol table for "__kprobes_text_{start,end}"
+ int syments = dwfl_module_getsymtab(kernel_dw->module);
+ assert(syments);
+ for (int i = 1; i < syments; ++i)
+ {
+ GElf_Sym sym;
+ const char *name = dwfl_module_getsym(kernel_dw->module, i,
+ &sym, NULL);
+
+ // Look for a symbol that starts with "__kprobes_text_"
+ if (name != NULL
+ && strncmp(name, "__kprobes_text_", 15) == 0)
+ {
+ // Match either "__kprobes_text_start" or "__kprobes_text_end"
+ if (strcmp(name, "__kprobes_text_start") == 0)
+ sess.kprobes_text_start = sym.st_value;
+ else if (strcmp(name, "__kprobes_text_end") == 0)
+ sess.kprobes_text_end = sym.st_value;
+
+ // If we've got both values, quit processing symbols.
+ if (sess.kprobes_text_start != 0 && sess.kprobes_text_end != 0)
+ i = syments;
+ }
+ }
+
+ if (kernel_dw)
+ delete kernel_dw;
+ }
+
+ if (sess.kprobes_text_start != 0 && sess.kprobes_text_end != 0)
+ {
+ // If the probe point address is anywhere in the __kprobes
+ // address range, we can't use this probe point.
+ if (addr >= sess.kprobes_text_start && addr < sess.kprobes_text_end)
+ return true;
+ }
+ return false;
+}
+
bool
dwarf_query::blacklisted_p(string const & funcname,
@@ -2351,6 +2413,15 @@ dwarf_query::blacklisted_p(string const & funcname,
}
}
+ // Check for function marked '__kprobes'.
+ if (in_kprobes_function(sess, addr))
+ {
+ if (sess.verbose>1)
+ clog << "skipping function '" << funcname << "' base 0x"
+ << hex << addr << dec << " is a function marked '__kprobes'\n";
+ return true;
+ }
+
// Check probe point against blacklist. XXX: This has to be
// properly generalized, perhaps via a table populated from script
// files. A "noprobe kernel.function("...")" construct might do
@@ -2826,6 +2897,24 @@ query_kernel_exists (Dwfl_Module *mod __attribute__ ((unused)),
static int
+query_kernel_module (Dwfl_Module *mod,
+ void **userdata __attribute__ ((unused)),
+ const char *name,
+ Dwarf_Addr base __attribute__ ((unused)),
+ void *arg)
+{
+ if (TOK_KERNEL == name)
+ {
+ Dwfl_Module **m = (Dwfl_Module **)arg;
+
+ *m = mod;
+ return DWARF_CB_ABORT;
+ }
+ return DWARF_CB_OK;
+}
+
+
+static int
query_module (Dwfl_Module *mod __attribute__ ((unused)),
void **userdata __attribute__ ((unused)),
const char *name, Dwarf_Addr base,