summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Ch. Eigler <fche@elastic.org>2008-05-17 18:32:37 -0400
committerFrank Ch. Eigler <fche@elastic.org>2008-05-17 18:32:37 -0400
commit332ddc9f7354fe51c32c504087575b3ea2b70990 (patch)
tree63a82b6d7fbf7ed591b9c3746e05a724aff8e2af
parent0fe2b97c7b967d833b5588dbf1ef763bb4440ed3 (diff)
parent277f2b79b02bf69a1d72d05b06086b07bcc6a113 (diff)
downloadsystemtap-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--ChangeLog28
-rw-r--r--README1
-rw-r--r--elaborate.cxx14
-rw-r--r--main.cxx35
-rw-r--r--runtime/ChangeLog11
-rw-r--r--runtime/task_finder.c32
-rw-r--r--tapsets.cxx116
-rw-r--r--testsuite/systemtap.examples/ChangeLog6
8 files changed, 179 insertions, 64 deletions
diff --git a/ChangeLog b/ChangeLog
index 13f6254e..92aad43b 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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
diff --git a/README b/README
index addb7187..b36d7241 100644
--- a/README
+++ b/README
@@ -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;
}
diff --git a/main.cxx b/main.cxx
index ea140f0f..dc638459 100644
--- a/main.cxx
+++ b/main.cxx
@@ -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.