diff options
author | Frank Ch. Eigler <fche@elastic.org> | 2008-05-17 18:32:37 -0400 |
---|---|---|
committer | Frank Ch. Eigler <fche@elastic.org> | 2008-05-17 18:32:37 -0400 |
commit | 332ddc9f7354fe51c32c504087575b3ea2b70990 (patch) | |
tree | 63a82b6d7fbf7ed591b9c3746e05a724aff8e2af | |
parent | 0fe2b97c7b967d833b5588dbf1ef763bb4440ed3 (diff) | |
parent | 277f2b79b02bf69a1d72d05b06086b07bcc6a113 (diff) | |
download | systemtap-steved-332ddc9f7354fe51c32c504087575b3ea2b70990.tar.gz systemtap-steved-332ddc9f7354fe51c32c504087575b3ea2b70990.tar.xz systemtap-steved-332ddc9f7354fe51c32c504087575b3ea2b70990.zip |
Merge commit 'origin/master' into pr6429-comp-unwindsyms
* commit 'origin/master':
suppress "pass-2 failed" messages from "stap -l FOOBAR"; just produce empty output
make the mod_cu_function_cache a hash_map instead of map for more go-go
PR5643: function caching for much faster syscall.* pass-2 processing
Fixed PR 6499 (utrace probe crash).
note "make installcheck" in post-build checkout
Ignores signals when removing the temporary directory.
Add appropriate ChangeLog entry for earlier checkin.
-rw-r--r-- | ChangeLog | 28 | ||||
-rw-r--r-- | README | 1 | ||||
-rw-r--r-- | elaborate.cxx | 14 | ||||
-rw-r--r-- | main.cxx | 35 | ||||
-rw-r--r-- | runtime/ChangeLog | 11 | ||||
-rw-r--r-- | runtime/task_finder.c | 32 | ||||
-rw-r--r-- | tapsets.cxx | 116 | ||||
-rw-r--r-- | testsuite/systemtap.examples/ChangeLog | 6 |
8 files changed, 179 insertions, 64 deletions
@@ -1,3 +1,31 @@ +2008-05-17 Frank Ch. Eigler <fche@elastic.org> + + * elaborate.cxx (semantic_pass): Error on #probes=0, but not in + listing mode. + (semantic_pass_optimize[12]): Remove inappropriate check from here. + +2008-05-17 Frank Ch. Eigler <fche@elastic.org> + + * tapsets.cxx (cu_function_cache_t): Switch to <ext/hash_map>s, + since these tables tend to get pretty big. + +2008-05-16 Frank Ch. Eigler <fche@elastic.org> + + PR 5643 + * tapsets.cxx (cu_function_cache_t): Reorganize into + mod:cu->function->DIE lookup table. Consider merging into symtab + later. + (mark_dwarf_redudancies): Adapt. + (iterate_over_functions): Rewrite. + (dwarf_builder::build): Cache kprobes etc. symbol addresses. + * elaborate.cxx (systemtap_session ctor): Clear additional POD fields. + +2008-05-15 David Smith <dsmith@redhat.com> + + * main.cxx (setup_signals): New function. + (main): Calls setup_signals() to setup signal handling. When + removing the temporary directory, ignore signals. + 2008-05-13 Ananth N Mavinakayanahalli <ananth@in.ibm.com> PR 5955. * parse.cxx (parser::parse_global): accept ";" terminated globals @@ -41,6 +41,7 @@ Build steps: ./configure --with-elfutils=PATCHED-ELFUTILS-DIR [other autoconf options] make all check sudo make install + sudo make installcheck Tips: diff --git a/elaborate.cxx b/elaborate.cxx index 306baff1..9a817cba 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -1159,6 +1159,9 @@ semantic_pass (systemtap_session& s) if (rc == 0 && ! s.unoptimized) rc = semantic_pass_optimize2 (s); if (rc == 0) rc = semantic_pass_vars (s); if (rc == 0) rc = semantic_pass_stats (s); + + if (s.probes.size() == 0 && !s.listing_mode) + throw semantic_error ("no probes found"); } catch (const semantic_error& e) { @@ -1188,7 +1191,10 @@ systemtap_session::systemtap_session (): hrtimer_derived_probes(0), perfmon_derived_probes(0), procfs_derived_probes(0), - op (0), up (0) + op (0), up (0), + sym_kprobes_text_start (0), + sym_kprobes_text_end (0), + sym_stext (0) { } @@ -2136,9 +2142,6 @@ semantic_pass_optimize1 (systemtap_session& s) semantic_pass_opt4 (s, relaxed_p); } - if (s.probes.size() == 0) - throw semantic_error ("no probes found"); - return rc; } @@ -2161,9 +2164,6 @@ semantic_pass_optimize2 (systemtap_session& s) semantic_pass_opt5 (s, relaxed_p); } - if (s.probes.size() == 0) - throw semantic_error ("no probes found"); - return rc; } @@ -253,7 +253,7 @@ printscript(systemtap_session& s, ostream& o) } } } - } +} int pending_interrupts; @@ -272,6 +272,30 @@ void handle_interrupt (int /* sig */) } +void +setup_signals (sighandler_t handler) +{ + struct sigaction sa; + + sa.sa_handler = handler; + sigemptyset (&sa.sa_mask); + if (handler != SIG_IGN) + { + sigaddset (&sa.sa_mask, SIGHUP); + sigaddset (&sa.sa_mask, SIGPIPE); + sigaddset (&sa.sa_mask, SIGINT); + sigaddset (&sa.sa_mask, SIGTERM); + } + sa.sa_flags = 0; + sa.sa_restorer = NULL; + + sigaction (SIGHUP, &sa, NULL); + sigaction (SIGPIPE, &sa, NULL); + sigaction (SIGINT, &sa, NULL); + sigaction (SIGTERM, &sa, NULL); +} + + int main (int argc, char * const argv []) { @@ -713,10 +737,7 @@ main (int argc, char * const argv []) // Set up our handler to catch routine signals, to allow clean // and reasonably timely exit. - signal (SIGHUP, handle_interrupt); - signal (SIGPIPE, handle_interrupt); - signal (SIGINT, handle_interrupt); - signal (SIGTERM, handle_interrupt); + setup_signals(&handle_interrupt); struct tms tms_before; times (& tms_before); @@ -1037,6 +1058,10 @@ pass_5: clog << "Keeping temporary directory \"" << s.tmpdir << "\"" << endl; else { + // Ignore signals while we're deleting the temporary directory. + setup_signals (SIG_IGN); + + // Remove the temporary directory. string cleanupcmd = "rm -rf "; cleanupcmd += s.tmpdir; if (s.verbose>1) clog << "Running " << cleanupcmd << endl; diff --git a/runtime/ChangeLog b/runtime/ChangeLog index aab6a862..bdf6e56d 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,14 @@ +2008-05-16 David Smith <dsmith@redhat.com> + + PR 6499. + * task_finder.c (stap_register_task_finder_target): Added error + check. + (__stp_utrace_task_finder_report_clone): Ditto. + (stap_utrace_detach_ops): Uses do_each_thread/while_each_thread + instead of for_each_process (which only iterated among process + group leaders instead of all threads). + (stap_start_task_finder): Ditto. + 2008-05-08 David Smith <dsmith@redhat.com> PR 6500. diff --git a/runtime/task_finder.c b/runtime/task_finder.c index 2c27e4a3..e78caab6 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -44,6 +44,9 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt) struct stap_task_finder_target *tgt = NULL; int found_node = 0; + if (new_tgt == NULL) + return EFAULT; + if (new_tgt->pathname != NULL) new_tgt->pathlen = strlen(new_tgt->pathname); else @@ -85,13 +88,13 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt) static void stap_utrace_detach_ops(struct utrace_engine_ops *ops) { - struct task_struct *tsk; + struct task_struct *grp, *tsk; struct utrace_attached_engine *engine; long error = 0; pid_t pid = 0; rcu_read_lock(); - for_each_process(tsk) { + do_each_thread(grp, tsk) { struct mm_struct *mm; if (tsk->pid <= 1) @@ -106,7 +109,7 @@ stap_utrace_detach_ops(struct utrace_engine_ops *ops) error = -PTR_ERR(engine); if (error != ENOENT) { pid = tsk->pid; - break; + goto udo_err; } error = 0; } @@ -114,7 +117,8 @@ stap_utrace_detach_ops(struct utrace_engine_ops *ops) utrace_detach(tsk, engine); } } - } + } while_each_thread(grp, tsk); +udo_err: rcu_read_unlock(); if (error != 0) { @@ -322,7 +326,7 @@ __stp_utrace_task_finder_report_clone(struct utrace_attached_engine *engine, // Grab the path associated with the new task mmpath = __stp_get_mm_path(mm, mmpath_buf, PATH_MAX); mmput(mm); /* We're done with mm */ - if (IS_ERR(mmpath)) { + if (mmpath == NULL || IS_ERR(mmpath)) { rc = -PTR_ERR(mmpath); _stp_error("Unable to get path (error %d) for pid %d", rc, (int)child->pid); @@ -407,7 +411,7 @@ int stap_start_task_finder(void) { int rc = 0; - struct task_struct *tsk; + struct task_struct *grp, *tsk; char *mmpath_buf; mmpath_buf = _stp_kmalloc(PATH_MAX); @@ -419,13 +423,12 @@ stap_start_task_finder(void) atomic_set(&__stp_task_finder_state, __STP_TF_RUNNING); rcu_read_lock(); - for_each_process(tsk) { + do_each_thread(grp, tsk) { struct mm_struct *mm; char *mmpath; size_t mmpathlen; struct list_head *tgt_node; - /* Attach to the thread */ rc = __stp_utrace_attach(tsk, &__stp_utrace_task_finder_ops, 0, __STP_UTRACE_TASK_FINDER_EVENTS); if (rc == EPERM) { @@ -436,7 +439,7 @@ stap_start_task_finder(void) } else if (rc != 0) { /* If we get a real error, quit. */ - break; + goto stf_err; } /* Grab the path associated with this task. */ @@ -448,11 +451,11 @@ stap_start_task_finder(void) } mmpath = __stp_get_mm_path(mm, mmpath_buf, PATH_MAX); mmput(mm); /* We're done with mm */ - if (IS_ERR(mmpath)) { + if (mmpath == NULL || IS_ERR(mmpath)) { rc = -PTR_ERR(mmpath); _stp_error("Unable to get path (error %d) for pid %d", rc, (int)tsk->pid); - break; + goto stf_err; } /* Check the thread's exe's path/pid against our list. */ @@ -487,7 +490,7 @@ stap_start_task_finder(void) if (rc != 0) { _stp_error("attach callback for %d failed: %d", (int)tsk->pid, rc); - break; + goto stf_err; } // Set up thread death notification. @@ -495,11 +498,12 @@ stap_start_task_finder(void) cb_tgt, __STP_UTRACE_ATTACHED_TASK_EVENTS); if (rc != 0 && rc != EPERM) - break; + goto stf_err; cb_tgt->engine_attached = 1; } } - } + } while_each_thread(grp, tsk); + stf_err: rcu_read_unlock(); _stp_kfree(mmpath_buf); diff --git a/tapsets.cxx b/tapsets.cxx index d6867e35..0ba22331 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -20,6 +20,7 @@ #include <deque> #include <iostream> #include <map> +#include <ext/hash_map> #include <set> #include <sstream> #include <stdexcept> @@ -54,6 +55,7 @@ extern "C" { #endif using namespace std; +using namespace __gnu_cxx; // ------------------------------------------------------------------------ @@ -535,7 +537,12 @@ module_cache }; typedef struct module_cache module_cache_t; -typedef map<string, vector<Dwarf_Die>*> cu_function_cache_t; +struct stringhash { + size_t operator() (const string& s) const { hash<const char*> h; return h(s.c_str()); } +}; + +typedef hash_map<string,Dwarf_Die,stringhash> cu_function_cache_t; +typedef hash_map<string,cu_function_cache_t*,stringhash> mod_cu_function_cache_t; // module:cu -> function -> die struct symbol_table @@ -1111,40 +1118,18 @@ struct dwflpp // ----------------------------------------------------------------- - cu_function_cache_t cu_function_cache; + mod_cu_function_cache_t cu_function_cache; static int cu_function_caching_callback (Dwarf_Die* func, void *arg) { - vector<Dwarf_Die>* v = static_cast<vector<Dwarf_Die>*>(arg); - v->push_back (* func); + cu_function_cache_t* v = static_cast<cu_function_cache_t*>(arg); + string function_name = dwarf_diename(func); + (*v)[function_name] = * func; return DWARF_CB_OK; } int iterate_over_functions (int (* callback)(Dwarf_Die * func, void * arg), - void * data) - { - int rc = DWARF_CB_OK; - assert (module); - assert (cu); - - string key = module_name + ":" + cu_name; - vector<Dwarf_Die>* v = cu_function_cache[key]; - if (v == 0) - { - v = new vector<Dwarf_Die>; - cu_function_cache[key] = v; - dwarf_getfuncs (cu, cu_function_caching_callback, v, 0); - } - - for (unsigned i=0; i<v->size(); i++) - { - Dwarf_Die die = v->at(i); - rc = (*callback)(& die, data); - if (rc != DWARF_CB_OK) break; - } - return rc; - } - + void * data); bool has_single_line_record (dwarf_query * q, char const * srcfile, int lineno); @@ -2489,6 +2474,58 @@ dwflpp::has_single_line_record (dwarf_query * q, char const * srcfile, int linen } +int +dwflpp::iterate_over_functions (int (* callback)(Dwarf_Die * func, void * arg), + void * data) +{ + int rc = DWARF_CB_OK; + assert (module); + assert (cu); + dwarf_query * q = static_cast<dwarf_query *>(data); + + string key = module_name + ":" + cu_name; + cu_function_cache_t *v = cu_function_cache[key]; + if (v == 0) + { + v = new cu_function_cache_t; + cu_function_cache[key] = v; + dwarf_getfuncs (cu, cu_function_caching_callback, v, 0); + if (q->sess.verbose > 4) + clog << "function cache " << key << " size " << v->size() << endl; + } + + string subkey = q->function; + if (v->find(subkey) != v->end()) + { + Dwarf_Die die = v->find(subkey)->second; + if (q->sess.verbose > 4) + clog << "function cache " << key << " hit " << subkey << endl; + return (*callback)(& die, data); + } + else if (name_has_wildcard (subkey)) + { + for (cu_function_cache_t::iterator it = v->begin(); it != v->end(); it++) + { + string func_name = it->first; + Dwarf_Die die = it->second; + if (function_name_matches_pattern (func_name, subkey)) + { + if (q->sess.verbose > 4) + clog << "function cache " << key << " match " << func_name << " vs " << subkey << endl; + + rc = (*callback)(& die, data); + if (rc != DWARF_CB_OK) break; + } + } + } + else // not a wildcard and no match in this CU + { + // do nothing + } + return rc; +} + + struct dwarf_builder: public derived_probe_builder { @@ -4584,10 +4621,13 @@ dwarf_builder::build(systemtap_session & sess, kern_dw->iterate_over_modules(&query_kernel_module, &km); if (km) { - sess.sym_kprobes_text_start = lookup_symbol_address (km, "__kprobes_text_start"); - sess.sym_kprobes_text_end = lookup_symbol_address (km, "__kprobes_text_end"); - sess.sym_stext = lookup_symbol_address (km, "_stext"); - + if (! sess.sym_kprobes_text_start) + sess.sym_kprobes_text_start = lookup_symbol_address (km, "__kprobes_text_start"); + if (! sess.sym_kprobes_text_end) + sess.sym_kprobes_text_end = lookup_symbol_address (km, "__kprobes_text_end"); + if (! sess.sym_stext) + sess.sym_stext = lookup_symbol_address (km, "_stext"); + if (sess.verbose > 2) { clog << "control symbols:" @@ -4775,21 +4815,21 @@ symbol_table::mark_dwarf_redundancies(dwflpp *dw) // vector of Dwarf_Dies, one per function. string module_prefix = string(mod_info->name) + ":"; - cu_function_cache_t::iterator cu; + mod_cu_function_cache_t::iterator cu; for (cu = dw->cu_function_cache.begin(); - cu != dw->cu_function_cache.end(); cu++) + cu != dw->cu_function_cache.end(); cu++) { string key = cu->first; if (key.find(module_prefix) == 0) { // Found a compilation unit in the module of interest. // Mark all its functions in the symbol table. - vector<Dwarf_Die>* v = cu->second; + cu_function_cache_t* v = cu->second; assert(v); - for (unsigned f=0; f < v->size(); f++) + for (cu_function_cache_t::iterator fc = v->begin(); fc != v->end(); fc++) { - Dwarf_Die func = v->at(f); - string func_name = dwarf_diename(&func); + Dwarf_Die func = fc->second; + string func_name = fc->first; // == dwarf_diename(&func); // map_by_name[func_name]->die = func; map<string, func_info*>::iterator i = map_by_name.find(func_name); // Func names can show up in the dwarf but not the symtab (!). diff --git a/testsuite/systemtap.examples/ChangeLog b/testsuite/systemtap.examples/ChangeLog index 8d8c2ca1..41b70135 100644 --- a/testsuite/systemtap.examples/ChangeLog +++ b/testsuite/systemtap.examples/ChangeLog @@ -1,3 +1,9 @@ +2008-05-09 William Cohen <wcohen@redhat.com> + + * syscalls_by_pid.meta, syscalls_by_proc.meta: + * sigmon.meta, sig_by_pid.meta, sig_by_proc.meta: + * socket-trace.meta: New. + 2008-05-08 William Cohen <wcohen@redhat.com> * iotime.meta: New. |