struct kprobe_builder: public derived_probe_builder
{
- kprobe_builder() {}
+private:
+ bool cache_initialized;
+ vector<string> function_name_cache;
+
+ void load_function_name_cache(systemtap_session & sess);
+
+public:
+ kprobe_builder(): cache_initialized(false) {}
+
+ void build_no_more (systemtap_session &s)
+ {
+ if (! function_name_cache.empty())
+ {
+ if (s.verbose > 3)
+ clog << _("kprobe_builder releasing cache") << endl;
+ function_name_cache.clear();
+ }
+ }
+
virtual void build(systemtap_session & sess,
probe * base,
probe_point * location,
};
+void
+kprobe_builder::load_function_name_cache(systemtap_session &sess)
+{
+ if (! cache_initialized)
+ {
+ cache_initialized = true;
+ string system_map_path = sess.kernel_build_tree + "/System.map";
+ ifstream system_map;
+
+ system_map.open(system_map_path.c_str(), ifstream::in);
+ if (! system_map.is_open())
+ {
+ string system_map_path2 = "/boot/System.map-" + sess.kernel_release;
+
+ system_map.clear();
+ system_map.open(system_map_path2.c_str(), ifstream::in);
+ if (! system_map.is_open())
+ {
+ if (sess.verbose > 3)
+ //TRANSLATORS: specific path cannot be opened
+ clog << system_map_path << _(" and ")
+ << system_map_path2 << _(" cannot be opened: ")
+ << strerror(errno) << endl;
+ return;
+ }
+ }
+
+ string address, type, name;
+ do
+ {
+ system_map >> address >> type >> name;
+
+ if (sess.verbose > 3)
+ clog << "'" << address << "' '" << type << "' '" << name
+ << "'" << endl;
+
+ // 'T'/'t' are text code symbols
+ if (type != "t" && type != "T")
+ continue;
+
+ // FIXME: better things to do here - look for _stext before
+ // remembering symbols. Also:
+ // - stop remembering names at ???
+ // - what about __kprobes_text_start/__kprobes_text_end?
+ function_name_cache.push_back(name);
+ }
+ while (! system_map.eof());
+ system_map.close();
+ }
+}
+
void
kprobe_builder::build(systemtap_session & sess,
probe * base,
if (has_function_str)
{
- if (has_module_str)
- function_string_val = module_string_val + ":" + function_string_val;
+ if (has_module_str)
+ {
+ function_string_val = module_string_val + ":" + function_string_val;
+ derived_probe *dp
+ = new kprobe_derived_probe (base, location, function_string_val,
+ 0, has_return, has_statement_num,
+ has_maxactive, has_path, has_library,
+ maxactive_val, path_tgt, library_tgt);
+ finished_results.push_back (dp);
+ }
+ else
+ {
+ load_function_name_cache(sess);
- finished_results.push_back (new kprobe_derived_probe (base,
- location, function_string_val,
- 0, has_return,
- has_statement_num,
- has_maxactive,
- has_path,
- has_library,
- maxactive_val,
- path_tgt,
- library_tgt));
+ // Search function name list for matching names
+ for (vector<string>::const_iterator it = function_name_cache.begin();
+ it != function_name_cache.end(); it++)
+ {
+ // Below, "rc" has negative polarity: zero iff matching.
+ int rc = fnmatch(function_string_val.c_str(), (*it).c_str(), 0);
+ if (! rc)
+ {
+ derived_probe *dp
+ = new kprobe_derived_probe (base, location, *it,
+ 0, has_return,
+ has_statement_num,
+ has_maxactive, has_path,
+ has_library, maxactive_val,
+ path_tgt, library_tgt);
+ finished_results.push_back (dp);
+ }
+ }
+ }
}
else
{