diff options
author | dsmith <dsmith> | 2006-10-11 14:56:09 +0000 |
---|---|---|
committer | dsmith <dsmith> | 2006-10-11 14:56:09 +0000 |
commit | 1d3a40b69576b5509671647e556b79ff5d6d17b7 (patch) | |
tree | 3d412ded6c556114fbd683076a5585a2a909fc1b | |
parent | 6e5aef4f27a2d02de416539062987acbf209e841 (diff) | |
download | systemtap-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-- | ChangeLog | 14 | ||||
-rw-r--r-- | elaborate.cxx | 5 | ||||
-rw-r--r-- | session.h | 9 | ||||
-rw-r--r-- | tapsets.cxx | 89 |
4 files changed, 116 insertions, 1 deletions
@@ -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) { } @@ -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, |