From 3bd0d4df7ccfd9afe7771441b26d8baaaf180e29 Mon Sep 17 00:00:00 2001 From: Rajan Arora Date: Wed, 11 Mar 2009 18:44:21 -0400 Subject: PR 7071: Optional $context variables fix * tapsets.cxx (dwarf_var_expanding_visitor::visit_target_symbol): Substitute erroneous target symbol with literal 0 if session level flag, skip_badvars is set. * session.h (struct systemtap_session): New flag: skip_badvars. * main.cxx: Command line argument --skip-badvars added. * stap.1.in: Entry for new option --skip-badvars. * NEWS: Added blurb for new option now available. * testsuite/semok/badvar.stp: Test case to check added functionality. --- NEWS | 5 +++++ main.cxx | 7 +++++++ session.h | 3 +++ stap.1.in | 3 +++ tapsets.cxx | 37 +++++++++++++++++++++++++------------ testsuite/semok/badvar.stp | 7 +++++++ 6 files changed, 50 insertions(+), 12 deletions(-) create mode 100755 testsuite/semok/badvar.stp diff --git a/NEWS b/NEWS index 08705c81..74fd1df5 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,10 @@ * What's new +- Variables unavailable in current context may be skipped by setting a + session level flag with command line option --skip-badvars now available. + This will simply substitute the otherwise error causing variable with a + literal 0 and print a warning message when the substitution has been made. + * What's new in version 0.9 - Typecasting is now supported using the @cast operator. A script can diff --git a/main.cxx b/main.cxx index b494ba2b..890f65bc 100644 --- a/main.cxx +++ b/main.cxx @@ -134,6 +134,8 @@ usage (systemtap_session& s, int exitcode) #endif // Formerly present --ignore-{vmlinux,dwarf} options are for testsuite use // only, and don't belong in the eyesight of a plain user. + << " --skip-badvars" << endl + << " overlook context of bad $ variables" << endl << endl ; @@ -431,12 +433,14 @@ main (int argc, char * const argv []) #define LONG_OPT_IGNORE_VMLINUX 3 #define LONG_OPT_IGNORE_DWARF 4 #define LONG_OPT_VERBOSE_PASS 5 +#define LONG_OPT_SKIP_BADVARS 6 // NB: also see find_hash(), usage(), switch stmt below, stap.1 man page static struct option long_options[] = { { "kelf", 0, &long_opt, LONG_OPT_KELF }, { "kmap", 2, &long_opt, LONG_OPT_KMAP }, { "ignore-vmlinux", 0, &long_opt, LONG_OPT_IGNORE_VMLINUX }, { "ignore-dwarf", 0, &long_opt, LONG_OPT_IGNORE_DWARF }, + { "skip-badvars", 0, &long_opt, LONG_OPT_SKIP_BADVARS }, { "vp", 1, &long_opt, LONG_OPT_VERBOSE_PASS }, { NULL, 0, NULL, 0 } }; @@ -698,6 +702,9 @@ main (int argc, char * const argv []) // NB: we don't do this: s.last_pass = strlen(optarg); break; } + case LONG_OPT_SKIP_BADVARS: + s.skip_badvars = true; + break; default: cerr << "Internal error parsing command arguments." << endl; usage(s, 1); diff --git a/session.h b/session.h index bc99385b..ec6c2e3e 100644 --- a/session.h +++ b/session.h @@ -123,6 +123,9 @@ struct systemtap_session bool ignore_vmlinux; bool ignore_dwarf; + // Skip bad $ vars + bool skip_badvars; + // temporary directory for module builds etc. // hazardous - it is "rm -rf"'d at exit std::string tmpdir; diff --git a/stap.1.in b/stap.1.in index 546bebb8..5a2e35f9 100644 --- a/stap.1.in +++ b/stap.1.in @@ -230,6 +230,9 @@ nor the kernel debugging information can be found. .TP .B \-\-ignore\-dwarf For testing, act as though vmlinux and modules lack debugging information. +.TP +.B \-\-skip\-badvars +Ignore out of context variables and substitute with literal 0. .SH ARGUMENTS diff --git a/tapsets.cxx b/tapsets.cxx index b1d0b04e..dce73534 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -4842,18 +4842,31 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) } catch (const semantic_error& er) { - // We suppress this error message, and pass the unresolved - // target_symbol to the next pass. We hope that this value ends - // up not being referenced after all, so it can be optimized out - // quietly. - provide (e); - semantic_error* saveme = new semantic_error (er); // copy it - saveme->tok1 = e->tok; // XXX: token not passed to q.dw code generation routines - // NB: we can have multiple errors, since a $target variable - // may be expanded in several different contexts: - // function ("*") { $var } - saveme->chain = e->saved_conversion_error; - e->saved_conversion_error = saveme; + if (!q.sess.skip_badvars) + { + // We suppress this error message, and pass the unresolved + // target_symbol to the next pass. We hope that this value ends + // up not being referenced after all, so it can be optimized out + // quietly. + provide (e); + semantic_error* saveme = new semantic_error (er); // copy it + saveme->tok1 = e->tok; // XXX: token not passed to q.dw code generation routines + // NB: we can have multiple errors, since a $target variable + // may be expanded in several different contexts: + // function ("*") { $var } + saveme->chain = e->saved_conversion_error; + e->saved_conversion_error = saveme; + } + else + { + // Upon user request for ignoring context, the symbol is replaced + // with a literal 0 and a warning message displayed + literal_number* ln_zero = new literal_number (0); + ln_zero->tok = e->tok; + provide (ln_zero); + q.sess.print_warning ("Bad variable being substituted with literal 0", + e->tok); + } delete fdecl; delete ec; return; diff --git a/testsuite/semok/badvar.stp b/testsuite/semok/badvar.stp new file mode 100755 index 00000000..b3bd2d67 --- /dev/null +++ b/testsuite/semok/badvar.stp @@ -0,0 +1,7 @@ +#! stap --skip-badvars + +probe syscall.read { + if ($foo == 0) + printf ("Voila! It works..\n") + exit () +} -- cgit From ec80b3969d33e4d54e97ead4286bdb018e2f1f97 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Wed, 11 Mar 2009 22:11:09 -0400 Subject: improve sdt.h compatibility and test suite Replaced cpp VA_ARGS in sdt.h with explicit enumeration of arguments (since with -pedantic, cpp has no varargs), and added a few more cflags variants to the sdt.exp test case. --- includes/sys/sdt.h | 40 ++++++++++++++++++++-------------------- testsuite/systemtap.base/sdt.c | 2 ++ testsuite/systemtap.base/sdt.exp | 25 ++++++++++++++----------- 3 files changed, 36 insertions(+), 31 deletions(-) diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h index dc2950f0..d6c90192 100644 --- a/includes/sys/sdt.h +++ b/includes/sys/sdt.h @@ -196,26 +196,26 @@ label: \ #define STAP_PROBE(provider,probe) \ STAP_PROBE_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER)) -#define STAP_PROBE1(provider,probe,...) \ - STAP_PROBE1_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),__VA_ARGS__) -#define STAP_PROBE2(provider,probe,...) \ - STAP_PROBE2_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),__VA_ARGS__) -#define STAP_PROBE3(provider,probe,...) \ - STAP_PROBE3_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),__VA_ARGS__) -#define STAP_PROBE4(provider,probe,...) \ - STAP_PROBE4_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),__VA_ARGS__) -#define STAP_PROBE5(provider,probe,...) \ - STAP_PROBE5_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),__VA_ARGS__) -#define STAP_PROBE6(provider,probe,...) \ - STAP_PROBE6_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),__VA_ARGS__) -#define STAP_PROBE7(provider,probe,...) \ - STAP_PROBE7_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),__VA_ARGS__) -#define STAP_PROBE8(provider,probe,...) \ - STAP_PROBE8_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),__VA_ARGS__) -#define STAP_PROBE9(provider,probe,...) \ - STAP_PROBE9_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),__VA_ARGS__) -#define STAP_PROBE10(provider,probe,...) \ - STAP_PROBE10_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),__VA_ARGS__) +#define STAP_PROBE1(provider,probe,parm1) \ + STAP_PROBE1_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1)) +#define STAP_PROBE2(provider,probe,parm1,parm2) \ + STAP_PROBE2_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2)) +#define STAP_PROBE3(provider,probe,parm1,parm2,parm3) \ + STAP_PROBE3_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3)) +#define STAP_PROBE4(provider,probe,parm1,parm2,parm3,parm4) \ + STAP_PROBE4_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4)) +#define STAP_PROBE5(provider,probe,parm1,parm2,parm3,parm4,parm5) \ + STAP_PROBE5_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5)) +#define STAP_PROBE6(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6) \ + STAP_PROBE6_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6)) +#define STAP_PROBE7(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ + STAP_PROBE7_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7)) +#define STAP_PROBE8(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ + STAP_PROBE8_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8)) +#define STAP_PROBE9(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ + STAP_PROBE9_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8),(parm9)) +#define STAP_PROBE10(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ + STAP_PROBE10_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8),(parm9),(parm10)) #define DTRACE_PROBE(provider,probe) \ STAP_PROBE(provider,probe) diff --git a/testsuite/systemtap.base/sdt.c b/testsuite/systemtap.base/sdt.c index 46f68664..7c7398e5 100644 --- a/testsuite/systemtap.base/sdt.c +++ b/testsuite/systemtap.base/sdt.c @@ -65,5 +65,7 @@ main (int argc, char **argv) call8(a, b, c, d, e, f, g, h); call9(a, b, c, d, e, f, g, h, i); call10(a, b, c, d, e, f, g, h, i, j); + (void) argv; + (void) argc; return 0; } diff --git a/testsuite/systemtap.base/sdt.exp b/testsuite/systemtap.base/sdt.exp index 09aaaf8d..74818beb 100644 --- a/testsuite/systemtap.base/sdt.exp +++ b/testsuite/systemtap.base/sdt.exp @@ -10,31 +10,33 @@ set ::result_string {1 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 10} -set extra_flags {{""} {additional_flags=-ansi}} +set extra_flags {{""} {additional_flags=-std=gnu89} {additional_flags=-ansi} {additional_flags=-pedantic}} # Iterate extra_flags, trying each with C and C++ for {set i 0} {$i < [llength $extra_flags]} {incr i} { +set extra_flag [lindex $extra_flags $i] + # C set test_flags "additional_flags=-g" set test_flags "$test_flags additional_flags=-I$srcdir/../includes/sys" -set test_flags "$test_flags additional_flags=-std=gnu89" set test_flags "$test_flags additional_flags=-Wall" -set test_flags "$test_flags additional_flags=-Wdeclaration-after-statement" +set test_flags "$test_flags additional_flags=-Wextra" set test_flags "$test_flags additional_flags=-Werror" -set res [target_compile $srcdir/$subdir/$test.c $test.prog executable [concat $test_flags " " [lindex $extra_flags $i]]] +set res [target_compile $srcdir/$subdir/$test.c $test.prog executable "$test_flags $extra_flag"] if { $res != "" } { verbose "target_compile failed: $res" 2 - fail "compiling $test.c" + fail "compiling $test.c $extra_flag" return } else { - pass "compiling $test.c" + pass "compiling $test.c $extra_flag" } if {[installtest_p]} { +# XXX: we need distinct test names for these stap_run2 $srcdir/$subdir/$test.stp -c ./$test.prog } else { - untested "$test" + untested "$test $extra_flag" } # C++ @@ -44,19 +46,20 @@ set test_flags "$test_flags additional_flags=-Wall" set test_flags "$test_flags additional_flags=-Werror" set test_flags "$test_flags additional_flags=-x additional_flags=c++" -set res [target_compile $srcdir/$subdir/$test.c $test.prog executable [concat $test_flags [lindex $extra_flags $i]]] +set res [target_compile $srcdir/$subdir/$test.c $test.prog executable "$test_flags $extra_flag"] if { $res != "" } { verbose "target_compile failed: $res" 2 - fail "compiling $test.c" + fail "compiling $test.c c++ $extra_flag" return } else { - pass "compiling $test.c" + pass "compiling $test.c c++ $extra_flag" } if {[installtest_p]} { +# XXX: we need distinct test names for these stap_run2 $srcdir/$subdir/$test.stp -c ./$test.prog } else { - untested "$test" + untested "$test c++ $extra_flag" } } -- cgit From 49462d1bcec68365e3ac96fc5c11c83ab7a8abd6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 11 Mar 2009 20:07:07 -0700 Subject: Add simple testcases for @cast --- testsuite/semok/cast.stp | 13 +++++++++++++ testsuite/systemtap.base/cast.exp | 4 ++++ testsuite/systemtap.base/cast.stp | 22 ++++++++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100755 testsuite/semok/cast.stp create mode 100644 testsuite/systemtap.base/cast.exp create mode 100644 testsuite/systemtap.base/cast.stp diff --git a/testsuite/semok/cast.stp b/testsuite/semok/cast.stp new file mode 100755 index 00000000..93da18ef --- /dev/null +++ b/testsuite/semok/cast.stp @@ -0,0 +1,13 @@ +#! stap -p2 + +probe begin { + // basic @cast test, with and without specifying kernel + println(@cast(0, "task_struct")->tgid) + println(@cast(0, "task_struct", "kernel")->tgid) + + // check module-search paths + println(@cast(0, "task_struct", "foo:kernel:bar")->tgid) + + // would be nice to test usermode @cast too, + // but who knows what debuginfo is installed... +} diff --git a/testsuite/systemtap.base/cast.exp b/testsuite/systemtap.base/cast.exp new file mode 100644 index 00000000..df3246e8 --- /dev/null +++ b/testsuite/systemtap.base/cast.exp @@ -0,0 +1,4 @@ +set test "cast" +set ::result_string {PID OK +execname OK} +stap_run2 $srcdir/$subdir/$test.stp diff --git a/testsuite/systemtap.base/cast.stp b/testsuite/systemtap.base/cast.stp new file mode 100644 index 00000000..bec0cc9b --- /dev/null +++ b/testsuite/systemtap.base/cast.stp @@ -0,0 +1,22 @@ +probe begin +{ + curr = task_current() + + // Compare PIDs + pid = pid() + cast_pid = @cast(curr, "task_struct")->tgid + if (pid == cast_pid) + println("PID OK") + else + printf("PID %d != %d\n", pid, cast_pid) + + // Compare execnames + name = execname() + cast_name = kernel_string(@cast(curr, "task_struct")->comm) + if (name == cast_name) + println("execname OK") + else + printf("execname \"%s\" != \"%s\"\n", name, cast_name) + + exit() +} -- cgit From 139dee87b8824df4d7562a980e886a6e6f0b8308 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 11 Mar 2009 20:07:22 -0700 Subject: Fix @cast module splitting The new semok testcase exposed that the module splitting wasn't properly setting substr boundaries. Instead of passing the end position, it's supposed to pass the number of characters (end - begin). Oops. --- tapsets.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tapsets.cxx b/tapsets.cxx index dce73534..7f6ca721 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -5017,7 +5017,7 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e) // split the module string by ':' for alternatives size_t mod_begin = mod_end + 1; mod_end = e->module.find(':', mod_begin); - string module = e->module.substr(mod_begin, mod_end); + string module = e->module.substr(mod_begin, mod_end - mod_begin); // NB: This uses '/' to distinguish between kernel modules and userspace, // which means that userspace modules won't get any PATH searching. -- cgit From 6769e48794cfbeda3957f691077fb9d65f3e87bc Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 11 Mar 2009 20:30:58 -0700 Subject: Add test to compile and run all tracepoints This checks that kernel.trace("*") will compile, with all context variables accessed as well. For kernels without tracepoints, it will just hit a "begin" and quit. This doesn't ensure that kernel.trace("*") will always find something when it should, though... --- testsuite/systemtap.base/tracepoints.exp | 3 +++ testsuite/systemtap.base/tracepoints.stp | 23 +++++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 testsuite/systemtap.base/tracepoints.exp create mode 100644 testsuite/systemtap.base/tracepoints.stp diff --git a/testsuite/systemtap.base/tracepoints.exp b/testsuite/systemtap.base/tracepoints.exp new file mode 100644 index 00000000..bea461c4 --- /dev/null +++ b/testsuite/systemtap.base/tracepoints.exp @@ -0,0 +1,3 @@ +set test "tracepoints" +set ::result_string {tracepoints OK} +stap_run2 $srcdir/$subdir/$test.stp diff --git a/testsuite/systemtap.base/tracepoints.stp b/testsuite/systemtap.base/tracepoints.stp new file mode 100644 index 00000000..bdb4d730 --- /dev/null +++ b/testsuite/systemtap.base/tracepoints.stp @@ -0,0 +1,23 @@ +// This checks that we can compile and register every tracepoint +// we can find, along with all of their context variables. +global hits +probe all_tracepoints = kernel.trace("*") +{ + if ($$name . $$vars . $$parms == "") + next + + // Allow it to quit once we hit our hundredth tracepoint + if (++hits < 100) + next +} + +// If there aren't any tracepoints in the kernel, +// we use "begin" instead to quit right away. +probe all_tracepoints!, begin { + println("tracepoints OK") + exit() +} + +// give hits a use so there's no warning +// when we don't have tracepoints +probe never { hits++ } -- cgit From 96b030fe8a0bb0297d23638e2975a3e9eb2b85b6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 12 Mar 2009 10:11:59 -0700 Subject: Simplify tracepoint registrations Instead of registering tracepoints with the deeply-nested if-tree, which was cluttering the module_init/exit, this now emits normalized reg/unreg functions for each tracepoint probes. Now the module_init/exit can be a simple loop like all of the other probe types. --- tapsets.cxx | 71 +++++++++++++++++++++++++++++++++++++------------------------ 1 file changed, 43 insertions(+), 28 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index 7f6ca721..b02e2cce 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -9732,12 +9732,15 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s) if (probes.empty()) return; - s.op->newline() << "/* ---- tracepointer probes ---- */"; + s.op->newline() << "/* ---- tracepoint probes ---- */"; + s.op->newline(); for (unsigned i = 0; i < probes.size(); ++i) { tracepoint_derived_probe *p = probes[i]; - s.op->newline(); + + // emit a separate entry function for each probe, since tracepoints + // don't provide any sort of context pointer. s.op->newline() << "#include <" << p->header << ">"; s.op->newline() << "static void enter_tracepoint_probe_" << i << "("; for (unsigned j = 0; j < p->args.size(); ++j) @@ -9765,8 +9768,34 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << p->name << " (c);"; common_probe_entryfn_epilogue (s.op); s.op->newline(-1) << "}"; + + // emit normalized registration functions + s.op->newline() << "static int register_tracepoint_probe_" << i << "(void) {"; + s.op->newline(1) << "return register_trace_" << p->tracepoint_name + << "(enter_tracepoint_probe_" << i << ");"; + s.op->newline(-1) << "}"; + s.op->newline() << "static int unregister_tracepoint_probe_" << i << "(void) {"; + s.op->newline(1) << "return unregister_trace_" << p->tracepoint_name + << "(enter_tracepoint_probe_" << i << ");"; + s.op->newline(-1) << "}"; s.op->newline(); } + + // emit an array of registration functions for easy init/shutdown + s.op->newline() << "static struct stap_tracepoint_probe {"; + s.op->newline(1) << "int (*reg)(void);"; + s.op->newline(0) << "int (*unreg)(void);"; + s.op->newline(-1) << "} stap_tracepoint_probes[] = {"; + s.op->indent(1); + for (unsigned i = 0; i < probes.size(); ++i) + { + s.op->newline () << "{"; + s.op->line() << " .reg=®ister_tracepoint_probe_" << i << ","; + s.op->line() << " .unreg=&unregister_tracepoint_probe_" << i; + s.op->line() << " },"; + } + s.op->newline(-1) << "};"; + s.op->newline(); } @@ -9777,28 +9806,14 @@ tracepoint_derived_probe_group::emit_module_init (systemtap_session &s) return; s.op->newline() << "/* init tracepoint probes */"; - - // We can't use a simple runtime loop because the probe registration - // functions are distinct inlines. Instead, this will generate nesting as - // deep as the number of probe points. Gotos are also possible, but the end - // result is the same. - - for (unsigned i = 0; i < probes.size(); ++i) - { - s.op->newline() << "if (!rc) {"; - s.op->newline(1) << "probe_point = " - << lex_cast_qstring (*probes[i]->sole_location()) << ";"; - s.op->newline() << "rc = register_trace_" << probes[i]->tracepoint_name - << "(enter_tracepoint_probe_" << i << ");"; - } - - for (unsigned i = probes.size() - 1; i < probes.size(); --i) - { - s.op->newline() << "if (rc)"; - s.op->newline(1) << "unregister_trace_" << probes[i]->tracepoint_name - << "(enter_tracepoint_probe_" << i << ");"; - s.op->newline(-2) << "}"; - } + s.op->newline() << "for (i=0; i<" << probes.size() << "; i++) {"; + s.op->newline(1) << "rc = stap_tracepoint_probes[i].reg();"; + s.op->newline() << "if (rc) {"; + s.op->newline(1) << "for (j=i-1; j>=0; j--)"; // partial rollback + s.op->newline(1) << "stap_tracepoint_probes[j].unreg();"; + s.op->newline(-1) << "break;"; // don't attempt to register any more probes + s.op->newline(-1) << "}"; + s.op->newline(-1) << "}"; // This would be technically proper (on those autoconf-detectable // kernels that include this function in tracepoint.h), however we @@ -9817,10 +9832,10 @@ tracepoint_derived_probe_group::emit_module_exit (systemtap_session& s) if (probes.empty()) return; - s.op->newline() << "/* deregister tracepointer probes */"; - for (unsigned i = 0; i < probes.size(); ++i) - s.op->newline() << "unregister_trace_" << probes[i]->tracepoint_name - << "(enter_tracepoint_probe_" << i << ");"; + s.op->newline() << "/* deregister tracepoint probes */"; + s.op->newline() << "for (i=0; i<" << probes.size() << "; i++)"; + s.op->newline(1) << "stap_tracepoint_probes[i].unreg();"; + s.op->indent(-1); // Not necessary: see above. -- cgit From fafd79e3a65854c8e7b3c0048e044af9741a0fff Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 13 Mar 2009 14:44:54 +0100 Subject: Introduce stap_run3 for distinct test names. * testsuite/lib/stap_run2.exp: Add stap_run3, called from stap_run2. * testsuite/systemtap.base/sdt.exp: Use stap_run3, for distinct test names. --- testsuite/lib/stap_run2.exp | 23 +++++++++++++++++++---- testsuite/systemtap.base/sdt.exp | 6 ++---- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/testsuite/lib/stap_run2.exp b/testsuite/lib/stap_run2.exp index cb1c6615..b734a1e7 100644 --- a/testsuite/lib/stap_run2.exp +++ b/testsuite/lib/stap_run2.exp @@ -10,12 +10,27 @@ proc stap_run2 { TEST_NAME args } { # zap the srcdir prefix - set test_file_name $TEST_NAME + set TEST_FILE $TEST_NAME set TEST_NAME [regsub {.*/testsuite/} $TEST_NAME ""] - + if {[llength $args] == 0} { + stap_run3 $TEST_NAME $TEST_FILE + } else { + stap_run3 $TEST_NAME $TEST_FILE $args + } +} + +# stap_run3 TEST_NAME TEST_FILE +# TEST_NAME is the name of the test as shown in PASS/FAIL/SKIPPED messages. +# TEST_FILE is the path to the current test +# Additional arguments are passed to stap as-is. +# +# global result_string must be set to the expected output + +proc stap_run3 { TEST_NAME TEST_FILE args } { if {[info procs installtest_p] != "" && ![installtest_p]} { untested $TEST_NAME; return } - - set cmd [concat stap $args $test_file_name] + + set cmd [concat stap $args $TEST_FILE] + send_log "executing: $cmd\n" catch {eval exec $cmd} res set n 0 diff --git a/testsuite/systemtap.base/sdt.exp b/testsuite/systemtap.base/sdt.exp index 74818beb..9e5dfc37 100644 --- a/testsuite/systemtap.base/sdt.exp +++ b/testsuite/systemtap.base/sdt.exp @@ -33,8 +33,7 @@ if { $res != "" } { } if {[installtest_p]} { -# XXX: we need distinct test names for these - stap_run2 $srcdir/$subdir/$test.stp -c ./$test.prog + stap_run3 "$test $extra_flag" $srcdir/$subdir/$test.stp -c ./$test.prog } else { untested "$test $extra_flag" } @@ -56,8 +55,7 @@ if { $res != "" } { } if {[installtest_p]} { -# XXX: we need distinct test names for these - stap_run2 $srcdir/$subdir/$test.stp -c ./$test.prog + stap_run3 "$test c++ $extra_flag" $srcdir/$subdir/$test.stp -c ./$test.prog } else { untested "$test c++ $extra_flag" } -- cgit From b16858f1452b4f111beb80875a5967dc8dff30fe Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 13 Mar 2009 14:49:55 +0100 Subject: Add -O2 and -O3 as extra test flags to sdt. * testsuite/systemtap.base/sdt.exp: Add -O2, -O3. --- testsuite/systemtap.base/sdt.exp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/systemtap.base/sdt.exp b/testsuite/systemtap.base/sdt.exp index 9e5dfc37..a0220202 100644 --- a/testsuite/systemtap.base/sdt.exp +++ b/testsuite/systemtap.base/sdt.exp @@ -10,7 +10,7 @@ set ::result_string {1 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 10} -set extra_flags {{""} {additional_flags=-std=gnu89} {additional_flags=-ansi} {additional_flags=-pedantic}} +set extra_flags {{""} {additional_flags=-std=gnu89} {additional_flags=-ansi} {additional_flags=-pedantic} {additional_flags=-O2} {additional_flags="-O3"}} # Iterate extra_flags, trying each with C and C++ for {set i 0} {$i < [llength $extra_flags]} {incr i} { -- cgit From 2497c78e8aa704366683dad56fc8d749a5e92f52 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 13 Mar 2009 14:54:26 +0100 Subject: Add -ansi -pedantic pair to sdt test. * testsuite/systemtap.base/sdt.exp: Add additional_flags -ansi together with -pedantic. --- testsuite/systemtap.base/sdt.exp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/systemtap.base/sdt.exp b/testsuite/systemtap.base/sdt.exp index a0220202..21b94810 100644 --- a/testsuite/systemtap.base/sdt.exp +++ b/testsuite/systemtap.base/sdt.exp @@ -10,7 +10,7 @@ set ::result_string {1 1 2 3 4 5 6 7 8 9 1 2 3 4 5 6 7 8 9 10} -set extra_flags {{""} {additional_flags=-std=gnu89} {additional_flags=-ansi} {additional_flags=-pedantic} {additional_flags=-O2} {additional_flags="-O3"}} +set extra_flags {{""} {additional_flags=-std=gnu89} {additional_flags=-ansi} {additional_flags=-pedantic} {additional_flags=-ansi additional_flags=-pedantic} {additional_flags=-O2} {additional_flags="-O3"}} # Iterate extra_flags, trying each with C and C++ for {set i 0} {$i < [llength $extra_flags]} {incr i} { -- cgit From 52aeb26b8d83c26e00adaf70bbf5a3a828689fb2 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 12 Mar 2009 17:12:38 -0700 Subject: PR9947: move runtime cleanup out of the work queue The kernel lockdep checking found a possible deadlock if a forced rmmod tried to destroy _stp_work_queue at the same time that the work queue was unregistering tracepoints. An unlikely scenario, but still possible. Now the work queue will just issue a STP_REQUEST_EXIT down to usermode, and usermode will echo back an STP_EXIT that triggers the actual probe cleanup. This way the unregistrations are happening in exactly the same context as the registrations were. --- runtime/staprun/mainloop.c | 8 ++++++++ runtime/transport/control.c | 7 ++++++- runtime/transport/transport.c | 20 ++++++++++++++++---- runtime/transport/transport_msgs.h | 8 +++++--- 4 files changed, 35 insertions(+), 8 deletions(-) diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c index 29eb4f1f..db6ef6b7 100644 --- a/runtime/staprun/mainloop.c +++ b/runtime/staprun/mainloop.c @@ -477,6 +477,14 @@ int stp_main_loop(void) cleanup_and_exit(0); break; } + case STP_REQUEST_EXIT: + { + /* module asks us to start exiting, so send STP_EXIT */ + dbug(2, "got STP_REQUEST_EXIT\n"); + int32_t rc, btype = STP_EXIT; + rc = write(control_channel, &btype, sizeof(btype)); + break; + } case STP_START: { struct _stp_msg_start *t = (struct _stp_msg_start *)data; diff --git a/runtime/transport/control.c b/runtime/transport/control.c index edde244d..680d7306 100644 --- a/runtime/transport/control.c +++ b/runtime/transport/control.c @@ -13,6 +13,8 @@ static _stp_mempool_t *_stp_pool_q; static struct list_head _stp_ctl_ready_q; static DEFINE_SPINLOCK(_stp_ctl_ready_lock); +static void _stp_cleanup_and_exit(int send_exit); + static ssize_t _stp_ctl_write_cmd(struct file *file, const char __user *buf, size_t count, loff_t *ppos) { u32 type; @@ -46,7 +48,7 @@ static ssize_t _stp_ctl_write_cmd(struct file *file, const char __user *buf, siz } break; case STP_EXIT: - _stp_exit_flag = 1; + _stp_cleanup_and_exit(1); break; case STP_BULK: #ifdef STP_BULKMODE @@ -93,6 +95,9 @@ static void _stp_ctl_write_dbug(int type, void *data, int len) case STP_TRANSPORT: _dbug("sending STP_TRANSPORT\n"); break; + case STP_REQUEST_EXIT: + _dbug("sending STP_REQUEST_EXIT\n"); + break; default: _dbug("ERROR: unknown message type: %d\n", type); break; diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c index 7fcebd42..762c0a92 100644 --- a/runtime/transport/transport.c +++ b/runtime/transport/transport.c @@ -25,7 +25,6 @@ static struct utt_trace *_stp_utt = NULL; static unsigned int utt_seq = 1; static int _stp_probes_started = 0; static pid_t _stp_target = 0; -static int _stp_exit_called = 0; static int _stp_exit_flag = 0; #include "control.h" #ifdef STP_OLD_TRANSPORT @@ -89,13 +88,14 @@ static void _stp_handle_start(struct _stp_msg_start *st) /* when someone does /sbin/rmmod on a loaded systemtap module. */ static void _stp_cleanup_and_exit(int send_exit) { - if (!_stp_exit_called) { + static int called = 0; + if (!called) { int failures; dbug_trans(1, "cleanup_and_exit (%d)\n", send_exit); _stp_exit_flag = 1; /* we only want to do this stuff once */ - _stp_exit_called = 1; + called = 1; if (_stp_probes_started) { dbug_trans(1, "calling probe_exit\n"); @@ -119,6 +119,18 @@ static void _stp_cleanup_and_exit(int send_exit) } } +static void _stp_request_exit(void) +{ + static int called = 0; + if (!called) { + /* we only want to do this once */ + called = 1; + dbug_trans(1, "ctl_send STP_REQUEST_EXIT\n"); + _stp_ctl_send(STP_REQUEST_EXIT, NULL, 0); + dbug_trans(1, "done with ctl_send STP_REQUEST_EXIT\n"); + } +} + /* * Called when stapio closes the control channel. */ @@ -169,7 +181,7 @@ static void _stp_work_queue(void *data) /* if exit flag is set AND we have finished with probe_start() */ if (unlikely(_stp_exit_flag && _stp_probes_started)) - _stp_cleanup_and_exit(1); + _stp_request_exit(); if (likely(_stp_attached)) queue_delayed_work(_stp_wq, &_stp_work, STP_WORK_TIMER); } diff --git a/runtime/transport/transport_msgs.h b/runtime/transport/transport_msgs.h index 596f4925..0d9a5983 100644 --- a/runtime/transport/transport_msgs.h +++ b/runtime/transport/transport_msgs.h @@ -21,19 +21,20 @@ struct _stp_trace { enum { STP_START, - STP_EXIT, + STP_EXIT, STP_OOB_DATA, STP_SYSTEM, STP_TRANSPORT, STP_CONNECT, - STP_DISCONNECT, + STP_DISCONNECT, STP_BULK, STP_READY, - STP_RELOCATION, + STP_RELOCATION, /** deprecated STP_OLD_TRANSPORT **/ STP_BUF_INFO, STP_SUBBUFS_CONSUMED, STP_REALTIME_DATA, + STP_REQUEST_EXIT, STP_MAX_CMD }; @@ -52,6 +53,7 @@ static const char *_stp_command_name[] = { "STP_BUF_INFO", "STP_SUBBUFS_CONSUMED", "STP_REALTIME_DATA", + "STP_REQUEST_EXIT", }; #endif /* DEBUG_TRANS */ -- cgit From 436b47f678c2fc5397ed66a1eddf6b419cc6585b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 13 Mar 2009 16:22:04 -0700 Subject: Move lookup_bad_addr call in STAPCONF_PROBE_KERNEL With most of the implementations, kread/kwrite call deref/store_deref, and so it makes sense to have lookup_bad_addr in the latter as an underlying address check. However, in the STAPCONF_PROBE_KERNEL case that uses probe_kernel_read and probe_kernel_write, the roles are reversed, so lookup_bad_addr needs to be in kread/kwrite. Also note that __deref_bad and __store_deref_bad should only be used in cases that can be determined at compile time. These turn into invalid symbols which prevent the module from loading. (They might be better replaced with compile-time assertions.) --- runtime/loc2c-runtime.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h index 0af19edc..92c017d3 100644 --- a/runtime/loc2c-runtime.h +++ b/runtime/loc2c-runtime.h @@ -187,22 +187,22 @@ #define kread(ptr) ({ \ typeof(*(ptr)) _v; \ - if (probe_kernel_read((void *)&_v, (void *)(ptr), sizeof(*(ptr)))) \ - DEREF_FAULT(ptr); \ + if (lookup_bad_addr((unsigned long)(ptr)) || \ + probe_kernel_read((void *)&_v, (void *)(ptr), sizeof(*(ptr)))) \ + DEREF_FAULT(ptr); \ _v; \ }) #define kwrite(ptr, value) ({ \ typeof(*(ptr)) _v; \ _v = (typeof(*(ptr)))(value); \ - if (probe_kernel_write((void *)(ptr), (void *)&_v, sizeof(*(ptr)))) \ - STORE_DEREF_FAULT(ptr); \ + if (lookup_bad_addr((unsigned long)addr) || \ + probe_kernel_write((void *)(ptr), (void *)&_v, sizeof(*(ptr)))) \ + STORE_DEREF_FAULT(ptr); \ }) #define deref(size, addr) ({ \ intptr_t _i; \ - if (lookup_bad_addr((unsigned long)addr)) \ - __deref_bad(); \ switch (size) { \ case 1: _i = kread((u8 *)(addr)); break; \ case 2: _i = kread((u16 *)(addr)); break; \ @@ -215,8 +215,6 @@ }) #define store_deref(size, addr, value) ({ \ - if (lookup_bad_addr((unsigned long)addr)) \ - __store_deref_bad(); \ switch (size) { \ case 1: kwrite((u8 *)(addr), (value)); break; \ case 2: kwrite((u16 *)(addr), (value)); break; \ -- cgit From 354c462465ffc80fc9a55beb9d6066cfa6048bc1 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Fri, 13 Mar 2009 23:12:19 -0400 Subject: Add missing . --- doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml b/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml index 555fa7e6..5d8cdfee 100644 --- a/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml +++ b/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml @@ -227,7 +227,7 @@ probe process.create = kernel.function("copy_process").return **/ -To override the automatically-generated Synopsis content, use: +To override the automatically-generated Synopsis content, use: * Synopsis: -- cgit From 20f933f0749322bc9787cc1972698a7aeffb08df Mon Sep 17 00:00:00 2001 From: William Cohen Date: Sat, 14 Mar 2009 08:46:52 -0400 Subject: Fixups to allow Tapset_Reference_guide documentation to build. --- doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml b/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml index 5d8cdfee..01e4c358 100644 --- a/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml +++ b/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml @@ -62,11 +62,13 @@ beginning of those functions: + probe process.exec = kernel.function("do_execve"), kernel.function("compat_do_execve") {probe body} + Try to place probes on stable interfaces (i.e., functions @@ -102,6 +104,7 @@ kernel.function("compat_do_execve") defined in task.stp. + probe process.create = kernel.function("copy_process").return { @@ -109,6 +112,7 @@ probe process.create = kernel.function("copy_process").return new_pid = task_pid(task) } + It is not advisable to write probes for every function. Most SystemTap users @@ -191,6 +195,7 @@ probe process.create = kernel.function("copy_process").return The specified format for documenting tapsets is as follows: + /** * probe tapset.name - Short summary of what the tapset does. @@ -209,9 +214,11 @@ probe process.create = kernel.function("copy_process").return * A paragraph that will appear under the heading "Header". **/ - + + For example: + /** * probe vm.write_shared_copy- Page copy for shared page write. @@ -226,17 +233,21 @@ probe process.create = kernel.function("copy_process").return * always preceded by a vm.shared_write. **/ + To override the automatically-generated Synopsis content, use: + * Synopsis: - * Synopsis string + * New Synopsis string * + For example: + /** * probe signal.handle - Fires when the signal handler is invoked @@ -247,6 +258,7 @@ probe process.create = kernel.function("copy_process").return * sigset_t *oldset, struct pt_regs * regs)</programlisting> */ + It is recommended that you use the <programlisting> tag in -- cgit From bb64f40b58a64a9ae065dba5058463ac604c3896 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sun, 15 Mar 2009 15:29:01 +0100 Subject: Move vma module tracking from pr6866 branch to master. * tapsets.cxx (utrace_derived_probe_group::emit_module_decls): Always emit vm callback probe for __stp_tf_vm_cb. * runtime/task_finder.c (__stp_tf_vm_cb): Always expose, move _stp_dbug statements under ifdef DEBUG_TASK_FINDER_VMA. Find and record corresponding module when vm_path not NULL. * runtime/task_finder_vma.c (struct __stp_tf_vma_entry): Add _stp_module. (stap_add_vma_map_info): Add _stp_module argument and assign. (__stp_tf_get_vma_entry_addr): New static function to get the __stp_tf_vma_entry given an address. --- runtime/task_finder.c | 22 ++++++++++++++++------ runtime/task_finder_vma.c | 30 +++++++++++++++++++++++++++++- tapsets.cxx | 4 ---- 3 files changed, 45 insertions(+), 11 deletions(-) diff --git a/runtime/task_finder.c b/runtime/task_finder.c index 9db713c3..ae381a41 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -55,7 +55,6 @@ typedef int (*stap_task_finder_vm_callback)(struct stap_task_finder_target *tgt, unsigned long vm_end, unsigned long vm_pgoff); -#ifdef DEBUG_TASK_FINDER_VMA static int __stp_tf_vm_cb(struct stap_task_finder_target *tgt, struct task_struct *tsk, int map_p, char *vm_path, @@ -63,21 +62,32 @@ static int __stp_tf_vm_cb(struct stap_task_finder_target *tgt, unsigned long vm_end, unsigned long vm_pgoff) { + int i; +#ifdef DEBUG_TASK_FINDER_VMA _stp_dbug(__FUNCTION__, __LINE__, "vm_cb: tsk %d:%d path %s, start 0x%08lx, end 0x%08lx, offset 0x%lx\n", tsk->pid, map_p, vm_path, vm_start, vm_end, vm_pgoff); +#endif if (map_p) { - // FIXME: What should we do with vm_path? We can't save - // the vm_path pointer itself, but we don't have any - // storage space allocated to save it in... - stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff); + struct _stp_module *module = NULL; + if (vm_path != NULL) + for (i = 0; i < _stp_num_modules; i++) + if (strcmp(vm_path, _stp_modules[i]->name) == 0) + { +#ifdef DEBUG_TASK_FINDER_VMA + _stp_dbug(__FUNCTION__, __LINE__, + "vm_cb: matched path %s to module\n", vm_path); +#endif + module = _stp_modules[i]; + break; + } + stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff, module); } else { stap_remove_vma_map_info(tsk, vm_start, vm_end, vm_pgoff); } return 0; } -#endif struct stap_task_finder_target { /* private: */ diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c index 4dce4be8..87a32fe5 100644 --- a/runtime/task_finder_vma.c +++ b/runtime/task_finder_vma.c @@ -25,6 +25,9 @@ struct __stp_tf_vma_entry { unsigned long vm_end; unsigned long vm_pgoff; // Is that enough? Should we store a dcookie for vm_file? + + // Module that this vma entry is mapped from, if any. + struct _stp_module *module; }; static struct __stp_tf_vma_entry @@ -211,7 +214,8 @@ __stp_tf_get_vma_map_entry_internal(struct task_struct *tsk, // Add the vma info to the vma map hash table. static int stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, - unsigned long vm_end, unsigned long vm_pgoff) + unsigned long vm_end, unsigned long vm_pgoff, + struct _stp_module *module) { struct hlist_head *head; struct hlist_node *node; @@ -242,6 +246,7 @@ stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, entry->vm_start = vm_start; entry->vm_end = vm_end; entry->vm_pgoff = vm_pgoff; + entry->module = module; head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; hlist_add_head(&entry->hlist, head); @@ -305,3 +310,26 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, mutex_unlock(&__stp_tf_vma_mutex); return rc; } + +// Get vma_entry of the address (vm_start/vm_end) if the vma is +// present in the vma hash table containing. +// Returns NULL if not present. +static struct __stp_tf_vma_entry * +__stp_tf_get_vma_entry_addr(struct task_struct *tsk, unsigned long addr) +{ + struct hlist_head *head; + struct hlist_node *node; + struct __stp_tf_vma_entry *entry; + + mutex_lock(&__stp_tf_vma_mutex); + head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; + hlist_for_each_entry(entry, node, head, hlist) { + if (tsk->pid == entry->pid + && addr >= entry->vm_start && addr < entry->vm_end) { + mutex_unlock(&__stp_tf_vma_mutex); + return entry; + } + } + mutex_unlock(&__stp_tf_vma_mutex); + return NULL; +} diff --git a/tapsets.cxx b/tapsets.cxx index b02e2cce..6efcb3af 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -7172,10 +7172,8 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) // Emit a "fake" probe decl that is really a hook for to get // our vm_callback called. string path = it->first; - s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA"; emit_vm_callback_probe_decl (s, true, path, (int64_t)0, "__stp_tf_vm_cb"); - s.op->newline() << "#endif"; for (unsigned i = 0; i < it->second.size(); i++) { @@ -7193,10 +7191,8 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) { // Emit a "fake" probe decl that is really a hook for to get // our vm_callback called. - s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA"; emit_vm_callback_probe_decl (s, false, "", it->first, "__stp_tf_vm_cb"); - s.op->newline() << "#endif"; for (unsigned i = 0; i < it->second.size(); i++) { -- cgit From 01cf527352f3bff6783b622d4ce1bbca63c44fc4 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:02:58 +1000 Subject: added description for memory tapset --- doc/SystemTap_Tapset_Reference/tapsets.tmpl | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/doc/SystemTap_Tapset_Reference/tapsets.tmpl b/doc/SystemTap_Tapset_Reference/tapsets.tmpl index 798cfb3b..8f791c6a 100644 --- a/doc/SystemTap_Tapset_Reference/tapsets.tmpl +++ b/doc/SystemTap_Tapset_Reference/tapsets.tmpl @@ -141,13 +141,17 @@ Memory Tapset + + This family of probe points is used to probe memory-related events. + It contains the following probe points: + !Itapset/memory.stp IO Scheduler Tapset - This family of probe points is used to probe the IO scheduler activities. + This family of probe points is used to probe IO scheduler activities. It contains the following probe points: !Itapset/ioscheduler.stp @@ -156,7 +160,7 @@ SCSI Tapset - This family of probe points is used to probe the SCSI activities. + This family of probe points is used to probe SCSI activities. It contains the following probe points: !Itapset/scsi.stp @@ -203,7 +207,7 @@ Process Tapset - This family of probe points is used to probe the process activities. + This family of probe points is used to probe process activities. It contains the following probe points: !Itapset/process.stp -- cgit From bc06a632db6ac4634b95c98f3ff355c89d9e20db Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:21:50 +1000 Subject: fixed format of non-grabbable comments (for Tapset Reference Guide), added tapsetdescription for man page generator (in development) --- tapset/context.stp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tapset/context.stp b/tapset/context.stp index 7fd961c8..f4b0207a 100644 --- a/tapset/context.stp +++ b/tapset/context.stp @@ -6,7 +6,11 @@ // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. - +// +// Context functions provide additional information about where an event occurred. These functions can +//provide information such as a backtrace to where the event occured and the current register values for the +//processor. +// /** * sfunction print_regs - Print a register dump. */ -- cgit From 920c7355ae85ccfb2df3b93b3703619891598dc1 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:21:50 +1000 Subject: fixed format of non-grabbable comments (for Tapset Reference Guide), added tapsetdescription for man page generator (in development) --- tapset/context-symbols.stp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tapset/context-symbols.stp b/tapset/context-symbols.stp index 46eab841..4a08ec60 100644 --- a/tapset/context-symbols.stp +++ b/tapset/context-symbols.stp @@ -6,7 +6,11 @@ // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. - +// +// Context functions provide additional information about where an event occurred. These functions can +//provide information such as a backtrace to where the event occured and the current register values for the +//processor. +// %{ #ifndef STP_NEED_SYMBOL_DATA #define STP_NEED_SYMBOL_DATA 1 -- cgit From 37bb6cc0978855325f856bbd343d7dc253cf6851 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:21:50 +1000 Subject: fixed format of non-grabbable comments (for Tapset Reference Guide), added tapsetdescription for man page generator (in development) --- tapset/context-unwind.stp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tapset/context-unwind.stp b/tapset/context-unwind.stp index a0836ed6..5c1253b8 100644 --- a/tapset/context-unwind.stp +++ b/tapset/context-unwind.stp @@ -6,7 +6,11 @@ // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. - +// +// Context functions provide additional information about where an event occurred. These functions can +//provide information such as a backtrace to where the event occured and the current register values for the +//processor. +// %{ #ifndef STP_NEED_UNWIND_DATA #define STP_NEED_UNWIND_DATA 1 -- cgit From a67f272c3b053b26cb263f2eb661cb080c41575a Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:21:51 +1000 Subject: fixed format of non-grabbable comments (for Tapset Reference Guide), added tapsetdescription for man page generator (in development) --- tapset/timestamp.stp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tapset/timestamp.stp b/tapset/timestamp.stp index ce8f7558..0b9d350a 100644 --- a/tapset/timestamp.stp +++ b/tapset/timestamp.stp @@ -6,7 +6,11 @@ // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. - +// +// Each timestamp function returns a value to indicate when a function is executed. These +//returned values can then be used to indicate when an event occurred, provide an ordering for events, +//or compute the amount of time elapsed between two time stamps. +// /** * sfunction get_cycles - Processor cycle count. * -- cgit From dfef45032efa63eeb208af3f8a06b7ecf7f0d424 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:21:51 +1000 Subject: fixed format of non-grabbable comments (for Tapset Reference Guide), added tapsetdescription for man page generator (in development) --- tapset/memory.stp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tapset/memory.stp b/tapset/memory.stp index 961cca38..9dbe3fba 100644 --- a/tapset/memory.stp +++ b/tapset/memory.stp @@ -6,6 +6,9 @@ // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. +// +// This family of probe points is used to probe memory-related events. +// %{ #include %} @@ -97,7 +100,7 @@ function addr_to_node:long(addr:long) %{ /* pure */ } %} -/* Return whether a page to be copied is a zero page. */ +// Return whether a page to be copied is a zero page. function _IS_ZERO_PAGE:long(from:long, vaddr:long) %{ /* pure */ THIS->__retvalue = (THIS->from == (long) ZERO_PAGE(THIS->vaddr)); %} -- cgit From 00db8e7c02006c1b68fb97b768cbb4a8e08d3a30 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:21:51 +1000 Subject: fixed format of non-grabbable comments (for Tapset Reference Guide), added tapsetdescription for man page generator (in development) --- tapset/ioscheduler.stp | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/tapset/ioscheduler.stp b/tapset/ioscheduler.stp index d7a71aca..875ccea9 100644 --- a/tapset/ioscheduler.stp +++ b/tapset/ioscheduler.stp @@ -5,15 +5,17 @@ // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. - +// +// This family of probe points is used to probe IO scheduler activities. +// %{ #include #include %} /** - * probe ioscheduler.elv_next_request - Retrieve request from request queue - * @elevator_name: The elevator name + * probe ioscheduler.elv_next_request - Fires when a request is retrieved from the request queue + * @elevator_name: The type of I/O elevator currently enabled */ probe ioscheduler.elv_next_request = kernel.function("elv_next_request") @@ -26,7 +28,7 @@ probe ioscheduler.elv_next_request } /** - * probe ioscheduler.elv_next_request.return - Return from retrieving a request + * probe ioscheduler.elv_next_request.return - Fires when a request retrieval issues a return signal * @req: Address of the request * @req_flags: Request flags * @disk_major: Disk major number of the request @@ -58,14 +60,14 @@ probe ioscheduler.elv_next_request.return } /** - * probe ioscheduler.elv_add_request - Add a request into request queue - * @elevator_name: The elevator name + * probe ioscheduler.elv_add_request -A request was added to the request queue + * @elevator_name: The type of I/O elevator currently enabled * @req: Address of the request * @req_flags: Request flags * @disk_major: Disk major number of the request * @disk_minor: Disk minor number of the request */ -/* when a request is added to the request queue */ +// when a request is added to the request queue probe ioscheduler.elv_add_request = kernel.function("__elv_add_request") { @@ -96,8 +98,8 @@ probe ioscheduler.elv_add_request } /** - * probe ioscheduler.elv_completed_request - Request is completed - * @elevator_name: The elevator name + * probe ioscheduler.elv_completed_request - Fires when a request is completed + * @elevator_name: The type of I/O elevator currently enabled * @req: Address of the request * @req_flags: Request flags * @disk_major: Disk major number of the request -- cgit From 2f440553d602cb3e2903803539216739b21b4c42 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:21:51 +1000 Subject: fixed format of non-grabbable comments (for Tapset Reference Guide), added tapsetdescription for man page generator (in development) --- tapset/scsi.stp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tapset/scsi.stp b/tapset/scsi.stp index 6d332e8b..8ff3dcca 100644 --- a/tapset/scsi.stp +++ b/tapset/scsi.stp @@ -5,7 +5,9 @@ // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. - +// +// This family of probe points is used to probe SCSI activities. +// %{ #include #include @@ -21,7 +23,7 @@ * @disk_minor: The minor number of the disk (-1 if no information) * @device_state: The current state of the device. */ -/* FIXME describe the device_state */ +// FIXME describe the device_state probe scsi.ioentry = module("scsi_mod").function("scsi_prep_fn@drivers/scsi/scsi_lib.c")?, kernel.function("scsi_prep_fn@drivers/scsi/scsi_lib.c")? @@ -107,7 +109,7 @@ probe scsi.iodone * the device * @goodbytes: The bytes completed. */ -/* mid-layer processes the completed IO */ +// mid-layer processes the completed IO probe scsi.iocompleted = module("scsi_mod").function("scsi_io_completion@drivers/scsi/scsi_lib.c")?, kernel.function("scsi_io_completion@drivers/scsi/scsi_lib.c")? -- cgit From ca54881115073d5d1ebcc46d489cf51abf4ba4ac Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:21:51 +1000 Subject: fixed format of non-grabbable comments (for Tapset Reference Guide), added tapsetdescription for man page generator (in development) --- tapset/networking.stp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/tapset/networking.stp b/tapset/networking.stp index a147441a..f6d78536 100644 --- a/tapset/networking.stp +++ b/tapset/networking.stp @@ -5,7 +5,9 @@ // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. - +// +// This family of probe points is used to probe the activities of the network device. +// /** * probe netdev.receive - Data recieved from network device. * @dev_name: The name of the device. e.g: eth0, ath1. @@ -49,7 +51,7 @@ /// /// /// -/* Main device receive routine, be called when packet arrives on network device */ +// Main device receive routine, be called when packet arrives on network device probe netdev.receive = kernel.function("netif_receive_skb") { @@ -67,7 +69,7 @@ probe netdev.receive * @truesize: The size of the the data to be transmitted. * */ -/* Queue a buffer for transmission to a network device */ +// Queue a buffer for transmission to a network device probe netdev.transmit = kernel.function("dev_queue_xmit") { -- cgit From 869a8e9b1bd528c8fe8b19ea502c1931fd28a7ef Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:21:51 +1000 Subject: fixed format of non-grabbable comments (for Tapset Reference Guide), added tapsetdescription for man page generator (in development) --- tapset/tcp.stp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tapset/tcp.stp b/tapset/tcp.stp index 995d6abc..1375f115 100644 --- a/tapset/tcp.stp +++ b/tapset/tcp.stp @@ -7,7 +7,9 @@ // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. - +// +// This family of probe points is used to probe events that occur in the TCP layer, +// %{ #include #include -- cgit From 3082f44232feada1111a850bfac5b2c182ced5de Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:21:51 +1000 Subject: fixed format of non-grabbable comments (for Tapset Reference Guide), added tapsetdescription for man page generator (in development) --- tapset/udp.stp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tapset/udp.stp b/tapset/udp.stp index 707cf77d..f2b19a7f 100644 --- a/tapset/udp.stp +++ b/tapset/udp.stp @@ -5,7 +5,9 @@ // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. - +// +// This family of probe points is used to probe events that occur in the UDP layer. +// %{ #include #include -- cgit From 3214f0aa1ca69297cfbffb4616c70c8118c20b5f Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:21:52 +1000 Subject: fixed format of non-grabbable comments (for Tapset Reference Guide), added tapsetdescription for man page generator (in development) --- tapset/socket.stp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tapset/socket.stp b/tapset/socket.stp index 3271d4f7..93730f9f 100644 --- a/tapset/socket.stp +++ b/tapset/socket.stp @@ -5,7 +5,9 @@ // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. - +// +// This family of probe points is used to probe socket activities. +// %{ #include #include -- cgit From b94a533da01cf4a66c7925f095659fb5732a23b3 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:21:52 +1000 Subject: fixed format of non-grabbable comments (for Tapset Reference Guide), added tapsetdescription for man page generator (in development) --- tapset/process.stp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tapset/process.stp b/tapset/process.stp index ca49aa67..e39f740a 100644 --- a/tapset/process.stp +++ b/tapset/process.stp @@ -5,7 +5,9 @@ // redistribute it and/or modify it under the terms of the GNU General // Public License (GPL); either version 2, or (at your option) any // later version. - +// +// This family of probe points is used to probe process-related activities. +// function _IS_ERR:long(ptr:long) %{ /* pure */ THIS->__retvalue = IS_ERR((const void *)(long)THIS->ptr); -- cgit From bfa3d6708bb6ddcb27155ab3cc904b9c85a60e95 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:21:52 +1000 Subject: fixed format of non-grabbable comments (for Tapset Reference Guide), added tapsetdescription for man page generator (in development) --- tapset/signal.stp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tapset/signal.stp b/tapset/signal.stp index 8fb6fe57..bde9160c 100644 --- a/tapset/signal.stp +++ b/tapset/signal.stp @@ -8,13 +8,15 @@ // Public License (GPL); either version 2, or (at your option) any // later version. // -// Note : Since there are so many signals sent to processes at any give -// point, it's better to filter the information according to the -// requirements. For example, filter only for a particular signal -// (if sig==2) or filter only for a particular process -// (if pid_name==stap). // - +// +// This family of probe points is used to probe signal activities. +// Since there are so many signals sent to processes at any give +// point, it's advisable to filter the information according to the +// requirements. For example, filter only for a particular signal +// (if sig==2) or filter only for a particular process +// (if pid_name==stap). +// /** * probe signal.send- Fires when a system call or kernel function sends a signal to a process. -- cgit From 39aa0af411c2ce1a7ba7f252fcd6924637a1f824 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 14:23:14 +1000 Subject: minor edits --- doc/SystemTap_Tapset_Reference/tapsets.tmpl | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/SystemTap_Tapset_Reference/tapsets.tmpl b/doc/SystemTap_Tapset_Reference/tapsets.tmpl index 8f791c6a..892d30a9 100644 --- a/doc/SystemTap_Tapset_Reference/tapsets.tmpl +++ b/doc/SystemTap_Tapset_Reference/tapsets.tmpl @@ -117,8 +117,8 @@ Context Functions The context functions provide additional information about where - the event occurred. - These functions can provide information such as a backtrace + an event occurred. + These functions can provide information such as a backtrace to where the event occured and the current register values for the processor. @@ -132,9 +132,9 @@ Each timestamp function returns a value to indicate when a function is executed. - Thus, these returned values can be used to indicate - when an event occurs, provide an ordering for events, or compute - the amount of time elapsed between to time stamps. + These returned values can then be used to indicate + when an event occurred, provide an ordering for events, or compute + the amount of time elapsed between two time stamps. !Itapset/timestamp.stp @@ -207,7 +207,7 @@ Process Tapset - This family of probe points is used to probe process activities. + This family of probe points is used to probe process-related activities. It contains the following probe points: !Itapset/process.stp -- cgit From ecbe2ee5c2aef01d0c99256a5c9adbf2e8db16d0 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 15:32:54 +1000 Subject: minor edit --- tapset/signal.stp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/tapset/signal.stp b/tapset/signal.stp index bde9160c..a2ebe145 100644 --- a/tapset/signal.stp +++ b/tapset/signal.stp @@ -11,11 +11,10 @@ // // // This family of probe points is used to probe signal activities. -// Since there are so many signals sent to processes at any give -// point, it's advisable to filter the information according to the +// Since there are so many signals sent to processes at any given +// point, it is advisable to filter the information according to the // requirements. For example, filter only for a particular signal -// (if sig==2) or filter only for a particular process -// (if pid_name==stap). +// (if sig==2) or for a particular process (if pid_name==stap). // /** -- cgit From 810f66c21bc8e4b1403ed57eeb4b9bfdea6ef5b9 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 16:01:28 +1000 Subject: minor edits to ensure uniformity in manpage generator --- tapset/signal.stp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tapset/signal.stp b/tapset/signal.stp index a2ebe145..265fd04e 100644 --- a/tapset/signal.stp +++ b/tapset/signal.stp @@ -130,24 +130,24 @@ probe _signal.send.part3 = kernel.function("send_sigqueue") * Possible __group_send_sig_info and * specific_send_sig_info return values are as follows; * - * 0 - The signal is sucessfully sent to a process, + * 0 -- The signal is sucessfully sent to a process, * which means that * <1> the signal was ignored by the receiving process, * <2> this is a non-RT signal and the system already has one queued, and * <3> the signal was successfully added to the sigqueue of the receiving process. * - * -EAGAIN - The sigqueue of the receiving process is + * -EAGAIN -- The sigqueue of the receiving process is * overflowing, the signal was RT, and the signal was sent by a user using something other * than kill() * * Possible send_group_sigqueue and * send_sigqueue return values are as follows; * - * 0 - The signal was either sucessfully added into the + * 0 -- The signal was either sucessfully added into the * sigqueue of the receiving process, or a SI_TIMER entry is already * queued (in which case, the overrun count will be simply incremented). * - * 1 - The signal was ignored by the receiving process. + * 1 -- The signal was ignored by the receiving process. * * * -1 - (send_sigqueue only) The task was marked -- cgit From 8552ab0f6699553a519a8f96d4356ac17f031230 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Mon, 16 Mar 2009 18:32:11 +1000 Subject: almost done, script generates man pages of stapprobes based on what we add to Tapset_Reference_Guide --- doc/Tapset_Reference_Guide/manpager.sh | 103 +++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 doc/Tapset_Reference_Guide/manpager.sh diff --git a/doc/Tapset_Reference_Guide/manpager.sh b/doc/Tapset_Reference_Guide/manpager.sh new file mode 100644 index 00000000..9aede5c4 --- /dev/null +++ b/doc/Tapset_Reference_Guide/manpager.sh @@ -0,0 +1,103 @@ +#!/bin/bash +# This script builds the man pages from comments in tapsets. As such, the man page content +# generated herein should be in sync with Tapset Reference Guide + +# cleanup +rm -rf manpages + +# create working directory +mkdir manpages ; + +# create list of man pages to generate; should be in sync with Tapset Reference Guide +cat ../SystemTap_Tapset_Reference/tapsets.tmpl | grep ^\!Itapset > manpageus ; +sed -i -e 's/\!Itapset\///g' manpageus ; + +# copy list of man pages into working directory +for i in `cat manpageus` ; do cp ../../tapset/$i manpages ; done ; + +# enter workdir +# rm manpageus ; +cd manpages ; + +# copy tapsetdescriptions, then clean +for i in `ls`; do sed -n '/\/\/ /,/\/\/ <\/tapsetdescription>/ s/.*/&/w temp' < $i ; +mv temp $i.tapsetdescription ; +sed -i -e 's/\/\/ //g' $i.tapsetdescription ; +sed -i -e 's/\/\/ <\/tapsetdescription>//g' $i.tapsetdescription ; +sed -i -e 's/\/\///g' $i.tapsetdescription ; +done + +# strip all tapset files to just comments; but first, make sure all comments are exactly 1 space before * +for i in `ls | grep -v tapsetdescription` ; do sed -i -e 's/^ \*/ \*/g' $i; done ; +for i in `ls | grep -v tapsetdescription` ; do sed -i -e '/^ \*/!d' $i; done ; +# rename all tapsets (remove .stp filename suffix), create templates +for i in `ls | grep -v tapsetdescription` ; do echo $i > tempname ; sed -i -e 's/.stp//g' tempname ; mv $i `cat tempname` ; mv tempname $i ; done ; +# clean all tapsetdescriptions (remove excess spaces) +# for i in `ls | grep tapsetdescription` ; do perl -p -i -e 's|^\n||g' $i ; done ; + +for i in `ls | grep -v .stp | grep -v tapsetdescription` ; +do echo ".\" -*- nroff -*-" >> $i.template ; +echo ".TH STAPPROBES.manpagename 5 @DATE@ "IBM"" >> $i.template ; +echo ".SH NAME" >> $i.template ; +echo "stapprobes."`cat $i.stp`" \- systemtap "`cat $i.stp`" probe points" >> $i.template ; +echo " " >> $i.template ; +echo ".\" macros" >> $i.template ; +echo ".de SAMPLE" >> $i.template ; +echo ".br" >> $i.template ; +echo ".RS" >> $i.template ; +echo ".nf" >> $i.template ; +echo ".nh" >> $i.template ; +echo ".." >> $i.template ; +echo ".de ESAMPLE" >> $i.template ; +echo ".hy" >> $i.template ; +echo ".fi" >> $i.template ; +echo ".RE" >> $i.template ; +echo ".." >> $i.template ; +echo " " >> $i.template ; +echo ".SH DESCRIPTION" >> $i.template ; +cat $i.stp.tapsetdescription >> $i.template ; +echo ".P" >> $i.template ; +echo ".TP" >> $i.template ; +done + +for i in `ls | grep -v .stp | grep -v tapsetdescription | grep -v template` ; +do cp $i $i.manpagebody ; +perl -p -i -e 's| \* sfunction|.B|g' $i.manpagebody ; +perl -p -i -e 's| \* probe|.B|g' $i.manpagebody ; +perl -p -i -e 's| -|\n\t|g' $i.manpagebody ; +perl -p -i -e 's|(^\t[^\n]*)\n|$1\n\n.B Arguments:|g' $i.manpagebody ; +perl -p -i -e 's| \* @([^:]*):|.I $1 \n|g' $i.manpagebody ; +perl -p -i -e 's| \* ([^:]*):|.B $1 \n|g' $i.manpagebody ; +perl -p -i -e 's| \* ||g' $i.manpagebody ; +perl -p -i -e 's|.B Arguments: \*|.B No Arguments:\n\n.B Description:|g' $i.manpagebody ; +perl -p -i -e 's|.B Arguments:.I|.B Arguments:\n.I|g' $i.manpagebody ; +perl -p -i -e 's|^ \*/|\n.P\n.TP|g' $i.manpagebody ; +perl -p -i -e 's|\.I|\n\n.I|g' $i.manpagebody ; +perl -p -i -e 's|.B Context|\n.B Context|g' $i.manpagebody ; +#perl -p -i -e 's|^[^*]*\*|.P|g' $i.manpagebody ; +done + +# generate footer template +mv ../manpageus . +sed -i -e 's/.stp//g' manpageus +echo ".SH SEE ALSO" >> footer +echo ".IR stap (1)," >> footer +echo ".IR stapprobes (5)," >> footer +for i in `cat manpageus`; do echo ".IR stapprobes."$i" (5)," >> footer ; done + +# assemble parts +for i in `cat manpageus`; do +cat $i.template >> stapprobes.$i.5.in ; +cat $i.manpagebody >> stapprobes.$i.5.in ; +cat footer >> stapprobes.$i.5.in ; +done + +# cleanup +for i in `cat manpageus`; do +perl -p -i -e 's|.B Description:/|\n.P\n.TP|g' stapprobes.$i.5.in ; +done + + +# perl -p -i -e 's|||g' $i.manpagebody +# use to move marked strings. +# sed -n '/\/\/ /,/\/\/ <\/tapsetdescription>/ s/.*/&/w bleh' < ioscheduler \ No newline at end of file -- cgit From 1bb61ae1fd02086560f5cd019db320b5a217ba05 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 16 Mar 2009 14:19:20 +0100 Subject: Add workaround for dwfl_module_build_id bug with elfutils < 0.140. * translate.cxx (dump_unwindsyms): Check elfutils version and whether build_id_vaddr < base, and if so add main_bias to address. --- translate.cxx | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/translate.cxx b/translate.cxx index 17c37dc3..f4c28536 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4497,17 +4497,35 @@ dump_unwindsyms (Dwfl_Module *m, // see https://bugzilla.redhat.com/show_bug.cgi?id=465872 // and http://sourceware.org/ml/systemtap/2008-q4/msg00579.html #ifdef _ELFUTILS_PREREQ -#if _ELFUTILS_PREREQ(0,138) + #if _ELFUTILS_PREREQ(0,138) // Let's standardize to the buggy "end of build-id bits" behavior. build_id_vaddr += build_id_len; + #endif + #if !_ELFUTILS_PREREQ(0,141) + #define NEED_ELFUTILS_BUILDID_WORKAROUND + #endif +#else + #define NEED_ELFUTILS_BUILDID_WORKAROUND #endif + + // And check for another workaround needed. + // see https://bugzilla.redhat.com/show_bug.cgi?id=489439 + // and http://sourceware.org/ml/systemtap/2009-q1/msg00513.html +#ifdef NEED_ELFUTILS_BUILDID_WORKAROUND + if (build_id_vaddr < base && dwfl_module_relocations (m) == 1) + { + GElf_Addr main_bias; + dwfl_module_getelf (m, &main_bias); + build_id_vaddr += main_bias; + } #endif - if (c->session.verbose > 1) { - clog << "Found build-id in " << name - << ", length " << build_id_len; - clog << ", end at 0x" << hex << build_id_vaddr - << dec << endl; - } + if (c->session.verbose > 1) + { + clog << "Found build-id in " << name + << ", length " << build_id_len; + clog << ", end at 0x" << hex << build_id_vaddr + << dec << endl; + } } // Look up the relocation basis for symbols -- cgit From 5d369d06fa39e4769fb3364ba29f588f3d995c24 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Mon, 16 Mar 2009 11:27:59 -0400 Subject: Edit signal.stp documentation comments. --- tapset/signal.stp | 174 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 105 insertions(+), 69 deletions(-) diff --git a/tapset/signal.stp b/tapset/signal.stp index 265fd04e..711ee70f 100644 --- a/tapset/signal.stp +++ b/tapset/signal.stp @@ -18,7 +18,7 @@ // /** - * probe signal.send- Fires when a system call or kernel function sends a signal to a process. + * probe signal.send - Signal being sent to a process * Arguments: * @sig: The number of the signal * @sig_name: A string representation of the signal @@ -28,7 +28,8 @@ * @task: A task handle to the signal recipient * @sinfo: The address of siginfo struct * @shared: Indicates whether the signal is shared by the thread group - * @send2queue- Indicates whether the signal is sent to an existing sigqueue + * @send2queue: Indicates whether the signal is sent to an existing + * sigqueue * @name: The name of the function used to send out the signal * * Context: @@ -115,14 +116,14 @@ probe _signal.send.part3 = kernel.function("send_sigqueue") } /** - * probe signal.send.return - Fires when a signal sent to a process returns. + * probe signal.send.return - Signal being sent to a process completed * @retstr: The return value to either __group_send_sig_info, - * specific_send_sig_info, or send_sigqueue. - * Refer to the Description of this probe for more information about the return - * values of each function call. + * specific_send_sig_info, + * or send_sigqueue * @shared: Indicates whether the sent signal is shared by the thread group. - * @send2queue: Indicates whether the sent signal was sent to an existing sigqueue - * @name: The name of the function used to send out the signal. + * @send2queue: Indicates whether the sent signal was sent to an + * existing sigqueue + * @name: The name of the function used to send out the signal * * Context: * The signal's sender. (correct?) @@ -233,7 +234,7 @@ probe _signal.send.part3.return = kernel.function("send_sigqueue").return } /** - * probe signal.checkperm - Fires when a permission check is performed on a sent signal + * probe signal.checkperm - Check being performed on a sent signal * @sig: The number of the signal * @sig_name: A string representation of the signal * @sig_pid: The PID of the process receiving the signal @@ -241,7 +242,8 @@ probe _signal.send.part3.return = kernel.function("send_sigqueue").return * @si_code: Indicates the signal type * @task: A task handle to the signal recipient * @sinfo: The address of the siginfo structure - * @name: Name of the probe point; default value is signal.checkperm + * @name: Name of the probe point; default value is + * signal.checkperm */ probe signal.checkperm = kernel.function("check_kill_permission") { @@ -262,6 +264,12 @@ probe signal.checkperm = kernel.function("check_kill_permission") si_code="SI_USER or SI_TIMER or SI_ASYNCIO" } +/** + * probe signal.checkperm.return - Check performed on a sent signal completed + * @name: Name of the probe point; default value is + * signal.checkperm + * @retstr: Return value as a string + */ probe signal.checkperm.return = kernel.function("check_kill_permission").return { name = "signal.checkperm" @@ -270,15 +278,15 @@ probe signal.checkperm.return = kernel.function("check_kill_permission").return /** - * probe signal.wakeup - Wakes up a sleeping process, making it ready for new active signals - * @sig_pid: The PID of the process you wish to wake - * @pid_name: Name of the process you wish to wake - * @resume: Indicates whether to wake up a task in a STOPPED or - * TRACED state + * probe signal.wakeup - Sleeping process being wakened for signal + * @sig_pid: The PID of the process to wake + * @pid_name: Name of the process to wake + * @resume: Indicates whether to wake up a task in a + * STOPPED or TRACED state * @state_mask: A string representation indicating the mask - * of task states you wish to wake. Possible values are TASK_INTERRUPTIBLE, - * TASK_STOPPED, TASK_TRACED, - * and TASK_INTERRUPTIBLE. + * of task states to wake. Possible values are + * TASK_INTERRUPTIBLE, TASK_STOPPED, + * TASK_TRACED, and TASK_INTERRUPTIBLE. */ probe signal.wakeup = kernel.function("signal_wake_up") { @@ -294,8 +302,7 @@ probe signal.wakeup = kernel.function("signal_wake_up") /** - * probe signal.check_ignored - Fires when a system call or kernel function checks whether a - * signal was ignored or not + * probe signal.check_ignored - Checking to see signal is ignored * @sig_pid: The PID of the process receiving the signal * @pid_name: Name of the process receiving the signal * @sig: The number of the signal @@ -309,6 +316,12 @@ probe signal.check_ignored = kernel.function("sig_ignored") sig_name = _signal_name($sig) } +/** + * probe signal.check_ignored.return - Check to see signal is ignored completed + * @name: Name of the probe point; default value is + * signal.checkperm + * @retstr: Return value as a string + */ probe signal.check_ignored.return = kernel.function("sig_ignored").return ? { name = "sig_ignored" @@ -334,8 +347,7 @@ probe signal.handle_stop = kernel.function("handle_stop_signal") /** - * probe signal.force_segv - Fires when a system call, kernel function, or process sent a - * SIGSEGV as a result of problems it encountered while handling a received signal + * probe signal.force_segv - Forcing send of SIGSEGV * @sig_pid: The PID of the process receiving the signal * @pid_name: Name of the process receiving the signal * @sig: The number of the signal @@ -361,6 +373,12 @@ probe _signal.force_segv.part2 = kernel.function("force_sigsegv_info") ? sig_name = _signal_name($sig) } +/** + * probe signal.force_segv.return - Forcing send of SIGSEGV complete + * @name: Name of the probe point; default value is + * force_sigsegv + * @retstr: Return value as a string + */ probe signal.force_segv.return = kernel.function("force_sigsegv").return, kernel.function("force_sigsegv_info").return ? @@ -371,9 +389,8 @@ probe signal.force_segv.return = /** - * probe signal.syskill - Fires when the kernel function sys_kill - * sends a kill signal to a process - * @pid: The PID of the process receiving the kill signal + * probe signal.syskill - Sending kill signal to a process + * @pid: The PID of the process receiving the signal * @sig: The specific signal sent to the process */ probe signal.syskill = syscall.kill @@ -381,33 +398,43 @@ probe signal.syskill = syscall.kill sig_name = _signal_name($sig) } +/** + * probe signal.syskill.return - Sending kill signal completed + */ probe signal.syskill.return = syscall.kill.return { } + /** - * probe signal.sys_tkill - Fires when tkill sends a kill signal - * to a process that is part of a thread group + * probe signal.sys_tkill - Sending a kill signal to a thread * @pid: The PID of the process receiving the kill signal * @sig: The specific signal sent to the process + * @sig_name: The specific signal sent to the process + * * The tkill call is analogous to kill(2), * except that it also allows a process within a specific thread group to - * be targetted. Such processes are targetted through their unique thread IDs (TID). + * be targetted. Such processes are targetted through their unique + * thread IDs (TID). */ probe signal.systkill = syscall.tkill { sig_name = _signal_name($sig) } +/** + * probe signal.systkill.return - Sending kill signal to a thread completed + */ probe signal.systkill.return = syscall.tkill.return { } /** - * probe signal.sys_tgkill - Fires when the kernel function tgkill - * sends a kill signal to a specific thread group + * probe signal.sys_tgkill - Sending kill signal to a thread group * @pid: The PID of the thread receiving the kill signal * @tgid: The thread group ID of the thread receiving the kill signal * @sig: The specific kill signal sent to the process + * @sig_name: A string representation of the signal + * * The tgkill call is similar to tkill, * except that it also allows the caller to specify the thread group ID of * the thread to be signalled. This protects against TID reuse. @@ -417,12 +444,15 @@ probe signal.systgkill = syscall.tgkill sig_name = _signal_name($sig) } +/** + * probe signal.sys_tgkill.return - Sending kill signal to a thread group completed + */ probe signal.systgkill.return = syscall.tgkill.return { } /** - * probe signal.send_sig_queue - Fires when a signal is queued to a process + * probe signal.send_sig_queue - Queuing a signal to a process * @sig: The queued signal * @sig_name: A string representation of the signal * @sig_pid: The PID of the process to which the signal is queued @@ -440,6 +470,10 @@ probe signal.send_sig_queue = sigqueue_addr = $q } +/** + * probe signal.send_sig_queue.return - Queuing a signal to a process completed + * @retstr: Return value as a string + */ probe signal.send_sig_queue.return = kernel.function("send_sigqueue").return, kernel.function("send_group_sigqueue").return ? @@ -449,25 +483,25 @@ probe signal.send_sig_queue.return = /** - * probe signal.pending - Fires when the SIGPENDING system call is used; - * this normally occurs when the do_sigpending kernel function is executed - * @sigset_add: The address of the user-space signal set (sigset_t) - * @sigset_size: The size of the user-space signal set. - * - * Synopsis: - * long do_sigpending(void __user *set, unsigned long sigsetsize) + * probe signal.pending - Examining pending signal + * @sigset_add: The address of the user-space signal set + * (sigset_t) + * @sigset_size: The size of the user-space signal set * * This probe is used to examine a set of signals pending for delivery - * to a specific thread. + * to a specific thread. This normally occurs when the + * do_sigpending kernel function is executed. */ -// long do_sigpending(void __user *set, unsigned long sigsetsize) - probe signal.pending = kernel.function("do_sigpending") { sigset_add=$set sigset_size=$sigsetsize } +/** + * probe signal.pending.return - Examination of pending signal completed + * @retstr: Return value as a string + */ probe signal.pending.return = kernel.function("do_sigpending").return { retstr = returnstr(1) @@ -475,22 +509,17 @@ probe signal.pending.return = kernel.function("do_sigpending").return /** - * probe signal.handle - Fires when the signal handler is invoked + * probe signal.handle - Signal handler being invoked * @sig: The signal number that invoked the signal handler * @sinfo: The address of the siginfo table - * @sig_code: The si_code value of the siginfo signal - * @ka_addr: The address of the k_sigaction table associated with the signal + * @sig_code: The si_code value of the + * siginfo signal + * @ka_addr: The address of the k_sigaction table + * associated with the signal * @oldset_addr: The address of the bitmask array of blocked signals * @regs: The address of the kernel-mode stack area * @sig_mode: Indicates whether the signal was a user-mode or kernel-mode signal - * - * Synopsis: - * static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, - * sigset_t *oldset, struct pt_regs * regs) */ -//static int handle_signal(unsigned long sig, siginfo_t *info, struct k_sigaction *ka, -// sigset_t *oldset, struct pt_regs * regs) - probe signal.handle = kernel.function("handle_signal") { sig = $sig @@ -509,6 +538,10 @@ probe signal.handle = kernel.function("handle_signal") sig_mode = "Kernel Mode Signal" } +/** + * probe signal.handle.return - Signal handler invocation completed + * @retstr: Return value as a string + */ probe signal.handle.return = kernel.function("handle_signal").return ? { retstr = returnstr(1) @@ -516,11 +549,12 @@ probe signal.handle.return = kernel.function("handle_signal").return ? /** - * probe signal.do_action - Initiates a trace when a thread is about to examine - * and change a signal action + * probe signal.do_action - Examining or changing a signal action * @sig: The signal to be examined/changed - * @sigact_addr: The address of the new sigaction struct associated with the signal - * @oldsigact_addr: The address of the old sigaction struct associated with the signal + * @sigact_addr: The address of the new sigaction + * struct associated with the signal + * @oldsigact_addr: The address of the old sigaction + * struct associated with the signal * @sa_handler: The new handler of the signal * @sa_mask: The new mask of the signal */ @@ -536,6 +570,10 @@ probe signal.do_action = kernel.function("do_sigaction") } } +/** + * probe signal.do_action.return - Examining or changing a signal action completed + * @retstr: Return value as a string + */ probe signal.do_action.return = kernel.function("do_sigaction").return { retstr = returnstr(1) @@ -555,16 +593,17 @@ function __get_action_mask:long(act:long) %{ /* pure */ /** - * probe signal.procmask - Initiates a trace when a thread is about to examine and change blocked signals + * probe signal.procmask - Examining or changing blocked signals * @how: Indicates how to change the blocked signals; possible values are * SIG_BLOCK=0 (for blocking signals), * SIG_UNBLOCK=1 (for unblocking signals), and * SIG_SETMASK=2 for setting the signal mask. - * @sigset_addr: The address of the signal set (sigset_t) to be implemented - * @oldsigset_addr: The old address of the signal set (sigset_t) - * @sigset: The actual value to be set for sigset_t (correct?) - * Synopsis: - * int sigprocmask(int how, sigset_t *set, sigset_t *oldset) + * @sigset_addr: The address of the signal set (sigset_t) + * to be implemented + * @oldsigset_addr: The old address of the signal set + * (sigset_t) + * @sigset: The actual value to be set for sigset_t + * (correct?) */ probe signal.procmask = kernel.function("sigprocmask") { @@ -592,16 +631,13 @@ probe signal.procmask.return = kernel.function("sigprocmask").return /** - * probe signal.flush - Fires when all pending signals for a task are flushed + * probe signal.flush - Flusing all pending signals for a task * @task: The task handler of the process performing the flush - * @sig_pid: The PID of the process associated with the task performing the flush - * @pid_name: The name of the process associated with the task performing the flush - * - * Synopsis: - * void flush_signals(struct task_struct *t) + * @sig_pid: The PID of the process associated with the task + * performing the flush + * @pid_name: The name of the process associated with the task + * performing the flush */ -//void flush_signals(struct task_struct *t) - probe signal.flush = kernel.function("flush_signals") { task = $t -- cgit From 86758d5f2b838d5769c7ace15269a4ebc422f94a Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 16 Mar 2009 18:13:07 -0700 Subject: Fix regression in tracepoint unregistration Commit 96b030fe reorganized the tracepoint registration calls by creating generic wrappers that return int. However, the older tracepoint implementation (as found in RHEL5.3) returned void for unreg, so this was failing pass-4. Since we can't handle unregistration failures anyway, this change just makes the generic unregister function return void instead. As noted in the newly-added comment, it should be safe for us to ignore unreg failures. --- tapsets.cxx | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index 6efcb3af..2f940b29 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -9770,8 +9770,13 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(1) << "return register_trace_" << p->tracepoint_name << "(enter_tracepoint_probe_" << i << ");"; s.op->newline(-1) << "}"; - s.op->newline() << "static int unregister_tracepoint_probe_" << i << "(void) {"; - s.op->newline(1) << "return unregister_trace_" << p->tracepoint_name + + // NB: we're not prepared to deal with unreg failures. However, failures + // can only occur if the tracepoint doesn't exist (yet?), or if we + // weren't even registered. The former should be OKed by the initial + // registration call, and the latter is safe to ignore. + s.op->newline() << "static void unregister_tracepoint_probe_" << i << "(void) {"; + s.op->newline(1) << "(void) unregister_trace_" << p->tracepoint_name << "(enter_tracepoint_probe_" << i << ");"; s.op->newline(-1) << "}"; s.op->newline(); @@ -9780,7 +9785,7 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s) // emit an array of registration functions for easy init/shutdown s.op->newline() << "static struct stap_tracepoint_probe {"; s.op->newline(1) << "int (*reg)(void);"; - s.op->newline(0) << "int (*unreg)(void);"; + s.op->newline(0) << "void (*unreg)(void);"; s.op->newline(-1) << "} stap_tracepoint_probes[] = {"; s.op->indent(1); for (unsigned i = 0; i < probes.size(); ++i) -- cgit From 924a2ea21d0276229a752e58e5c5c1a9346648be Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 16 Mar 2009 18:36:44 -0700 Subject: PR9951: Prevent GCC warnings in deref() In some configurations, GCC was warning about a possible use of _v in the deref macros. I could not reproduce the error, but the only case where _v is not written is if lookup_bad_addr rejects the address, in which case we will hit DEREF_FAULT and _v won't be used. Now we're priming _v=0 anyway, so GCC has no right to complain... --- runtime/loc2c-runtime.h | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h index 92c017d3..16ddb950 100644 --- a/runtime/loc2c-runtime.h +++ b/runtime/loc2c-runtime.h @@ -186,7 +186,7 @@ */ #define kread(ptr) ({ \ - typeof(*(ptr)) _v; \ + typeof(*(ptr)) _v = 0; \ if (lookup_bad_addr((unsigned long)(ptr)) || \ probe_kernel_read((void *)&_v, (void *)(ptr), sizeof(*(ptr)))) \ DEREF_FAULT(ptr); \ @@ -202,14 +202,13 @@ }) #define deref(size, addr) ({ \ - intptr_t _i; \ + intptr_t _i = 0; \ switch (size) { \ case 1: _i = kread((u8 *)(addr)); break; \ case 2: _i = kread((u16 *)(addr)); break; \ case 4: _i = kread((u32 *)(addr)); break; \ case 8: _i = kread((u64 *)(addr)); break; \ default: __deref_bad(); \ - /* uninitialized _i should also be caught by -Werror */ \ } \ _i; \ }) @@ -235,7 +234,7 @@ extern void __store_deref_bad(void); ({ \ int _bad = 0; \ u8 _b; u16 _w; u32 _l; \ - intptr_t _v; \ + intptr_t _v = 0; \ if (lookup_bad_addr((unsigned long)addr)) \ _bad = 1; \ else \ @@ -275,7 +274,7 @@ extern void __store_deref_bad(void); ({ \ int _bad = 0; \ u8 _b; u16 _w; u32 _l; u64 _q; \ - intptr_t _v; \ + intptr_t _v = 0; \ if (lookup_bad_addr((unsigned long)addr)) \ _bad = 1; \ else \ @@ -392,7 +391,7 @@ extern void __store_deref_bad(void); #define deref(size, addr) \ ({ \ int _bad = 0; \ - intptr_t _v; \ + intptr_t _v = 0; \ if (lookup_bad_addr((unsigned long)addr)) \ _bad = 1; \ else \ -- cgit From bdca08879745471fdb86991a8e7276900aaaf066 Mon Sep 17 00:00:00 2001 From: Wenji Huang Date: Mon, 16 Mar 2009 18:21:41 -0400 Subject: Add pid-based data lookup function. Two functions pid2task and pid2execname. --- tapset/task.stp | 24 ++++++++++++++++++++++++ testsuite/buildok/task-embedded.stp | 4 +++- testsuite/buildok/task_test.stp | 2 ++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/tapset/task.stp b/tapset/task.stp index 07337156..f1a10b0a 100644 --- a/tapset/task.stp +++ b/tapset/task.stp @@ -63,6 +63,30 @@ function task_pid:long (task:long) } +// Return the task of the given process id +function pid2task:long (pid:long) %{ /* pure */ + struct task_struct *t = NULL; + pid_t t_pid = (pid_t)(long)THIS->pid; + rcu_read_lock(); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24) + t = find_task_by_vpid (t_pid); +#else + t = find_task_by_pid (t_pid); +#endif + rcu_read_unlock(); + THIS->__retvalue = (long)t; + CATCH_DEREF_FAULT(); +%} + +// Return the name of the given process id +function pid2execname:string (pid:long) { + tsk = pid2task(pid) + if (tsk) + return task_execname(tsk) + return "" +} + + // Return the thread id of the given task function task_tid:long (task:long) { diff --git a/testsuite/buildok/task-embedded.stp b/testsuite/buildok/task-embedded.stp index 4d1f5300..d35f3e0d 100755 --- a/testsuite/buildok/task-embedded.stp +++ b/testsuite/buildok/task-embedded.stp @@ -14,6 +14,8 @@ probe begin { task_nice (0) + task_cpu (0) + task_open_file_handles (0) + - task_max_file_handles (0)) + task_max_file_handles (0) + + pid2task(0)) print (task_execname (0)) + print (pid2execname (0)) } diff --git a/testsuite/buildok/task_test.stp b/testsuite/buildok/task_test.stp index c8da7da5..792f96ea 100755 --- a/testsuite/buildok/task_test.stp +++ b/testsuite/buildok/task_test.stp @@ -16,5 +16,7 @@ probe begin { log(sprint(task_cpu(c))) log(sprint(task_open_file_handles(c))) log(sprint(task_max_file_handles(c))) + log(sprint(pid2task(pid()))) + log(sprint(pid2execname(pid()))) exit() } -- cgit From 983449d2c555c85825041fe3bbf7fd2478531a0b Mon Sep 17 00:00:00 2001 From: ddomingo Date: Tue, 17 Mar 2009 13:41:40 +1000 Subject: almost done, output clean, just a few more improvements --- doc/Tapset_Reference_Guide/manpager.sh | 106 +++++++++++++++++++-------------- 1 file changed, 62 insertions(+), 44 deletions(-) diff --git a/doc/Tapset_Reference_Guide/manpager.sh b/doc/Tapset_Reference_Guide/manpager.sh index 9aede5c4..16ee441f 100644 --- a/doc/Tapset_Reference_Guide/manpager.sh +++ b/doc/Tapset_Reference_Guide/manpager.sh @@ -3,78 +3,79 @@ # generated herein should be in sync with Tapset Reference Guide # cleanup -rm -rf manpages +rm -rf workingdir # create working directory -mkdir manpages ; +mkdir workingdir ; # create list of man pages to generate; should be in sync with Tapset Reference Guide cat ../SystemTap_Tapset_Reference/tapsets.tmpl | grep ^\!Itapset > manpageus ; sed -i -e 's/\!Itapset\///g' manpageus ; # copy list of man pages into working directory -for i in `cat manpageus` ; do cp ../../tapset/$i manpages ; done ; +for i in `cat manpageus` ; do cp ../../tapset/$i workingdir ; done ; # enter workdir -# rm manpageus ; -cd manpages ; +cd workingdir ; # copy tapsetdescriptions, then clean -for i in `ls`; do sed -n '/\/\/ /,/\/\/ <\/tapsetdescription>/ s/.*/&/w temp' < $i ; +for i in `cat ../manpageus`; do +sed -n '/\/\/ /,/\/\/ <\/tapsetdescription>/ s/.*/&/w temp' < $i ; mv temp $i.tapsetdescription ; sed -i -e 's/\/\/ //g' $i.tapsetdescription ; sed -i -e 's/\/\/ <\/tapsetdescription>//g' $i.tapsetdescription ; sed -i -e 's/\/\///g' $i.tapsetdescription ; done -# strip all tapset files to just comments; but first, make sure all comments are exactly 1 space before * -for i in `ls | grep -v tapsetdescription` ; do sed -i -e 's/^ \*/ \*/g' $i; done ; -for i in `ls | grep -v tapsetdescription` ; do sed -i -e '/^ \*/!d' $i; done ; +# strip all tapset files to just comments; but all comments must be exactly 1 space before and after "*" +for i in `cat ../manpageus` ; do sed -i -e 's/^ \*/ \*/g' $i; +sed -i -e 's/^ \* / \* /g' $i; +# mark the start of each probe entry (sub "/**") +perl -p -i -e 's|^/\*\*| *probestart|g' $i; +sed -i -e '/^ \*/!d' $i; # rename all tapsets (remove .stp filename suffix), create templates -for i in `ls | grep -v tapsetdescription` ; do echo $i > tempname ; sed -i -e 's/.stp//g' tempname ; mv $i `cat tempname` ; mv tempname $i ; done ; +echo $i > tempname ; +sed -i -e 's/.stp//g' tempname ; +mv $i `cat tempname` ; mv tempname $i ; +done ; # clean all tapsetdescriptions (remove excess spaces) # for i in `ls | grep tapsetdescription` ; do perl -p -i -e 's|^\n||g' $i ; done ; -for i in `ls | grep -v .stp | grep -v tapsetdescription` ; -do echo ".\" -*- nroff -*-" >> $i.template ; +# create man page headers +for i in `ls | grep -v .stp | grep -v tapsetdescription` ; do +#echo ".\" -*- nroff -*-" >> $i.template ; echo ".TH STAPPROBES.manpagename 5 @DATE@ "IBM"" >> $i.template ; echo ".SH NAME" >> $i.template ; echo "stapprobes."`cat $i.stp`" \- systemtap "`cat $i.stp`" probe points" >> $i.template ; echo " " >> $i.template ; -echo ".\" macros" >> $i.template ; -echo ".de SAMPLE" >> $i.template ; -echo ".br" >> $i.template ; -echo ".RS" >> $i.template ; -echo ".nf" >> $i.template ; -echo ".nh" >> $i.template ; -echo ".." >> $i.template ; -echo ".de ESAMPLE" >> $i.template ; -echo ".hy" >> $i.template ; -echo ".fi" >> $i.template ; -echo ".RE" >> $i.template ; -echo ".." >> $i.template ; -echo " " >> $i.template ; echo ".SH DESCRIPTION" >> $i.template ; cat $i.stp.tapsetdescription >> $i.template ; +echo " " >> $i.template ; +#echo " " >> $i.template ; +echo ".SH PROBES" >> $i.template ; +echo ".br" >> $i.template ; echo ".P" >> $i.template ; echo ".TP" >> $i.template ; done +# MOST IMPORTANT: clean man page body! for i in `ls | grep -v .stp | grep -v tapsetdescription | grep -v template` ; -do cp $i $i.manpagebody ; -perl -p -i -e 's| \* sfunction|.B|g' $i.manpagebody ; -perl -p -i -e 's| \* probe|.B|g' $i.manpagebody ; -perl -p -i -e 's| -|\n\t|g' $i.manpagebody ; -perl -p -i -e 's|(^\t[^\n]*)\n|$1\n\n.B Arguments:|g' $i.manpagebody ; -perl -p -i -e 's| \* @([^:]*):|.I $1 \n|g' $i.manpagebody ; -perl -p -i -e 's| \* ([^:]*):|.B $1 \n|g' $i.manpagebody ; -perl -p -i -e 's| \* ||g' $i.manpagebody ; -perl -p -i -e 's|.B Arguments: \*|.B No Arguments:\n\n.B Description:|g' $i.manpagebody ; -perl -p -i -e 's|.B Arguments:.I|.B Arguments:\n.I|g' $i.manpagebody ; -perl -p -i -e 's|^ \*/|\n.P\n.TP|g' $i.manpagebody ; -perl -p -i -e 's|\.I|\n\n.I|g' $i.manpagebody ; -perl -p -i -e 's|.B Context|\n.B Context|g' $i.manpagebody ; -#perl -p -i -e 's|^[^*]*\*|.P|g' $i.manpagebody ; +do cp $i $i.tmp ; +perl -p -i -e 's| \* sfunction|.BR|g' $i.tmp ; +perl -p -i -e 's| \* probe|.BR|g' $i.tmp ; +perl -p -i -e 's| -|\ninitlinehere|g' $i.tmp ; +perl -p -i -e 's|^initlinehere([^\n]*)\n|\n.br\n$1\n\n.B Arguments:|g' $i.tmp ; +perl -p -i -e 's| \* @([^:]*):|\n.I $1\n.br\n|g' $i.tmp ; +perl -p -i -e 's| \* ([^:]*):|\n.BR $1:\n.br\n|g' $i.tmp ; +perl -p -i -e 's|\*probestart|\n.P\n.TP|g' $i.tmp ; +perl -p -i -e 's|\.I|\n\n.I|g' $i.tmp ; +# special formatting for Arguments header +perl -p -i -e 's|.B Arguments: \*\/||g' $i.tmp ; +perl -p -i -e 's|.B Arguments: \*|.B Description:|g' $i.tmp ; + +cat $i.tmp | +perl -p -e 'undef $/;s|.B Arguments:\n.B|.B|msg' | +perl -p -e 'undef $/;s|\n\n\n|\n\n|msg' > $i.manpagebody ; done # generate footer template @@ -87,17 +88,34 @@ for i in `cat manpageus`; do echo ".IR stapprobes."$i" (5)," >> footer ; done # assemble parts for i in `cat manpageus`; do -cat $i.template >> stapprobes.$i.5.in ; -cat $i.manpagebody >> stapprobes.$i.5.in ; -cat footer >> stapprobes.$i.5.in ; +cat $i.template >> $i.5 ; +cat $i.manpagebody >> $i.5 ; +cat footer >> $i.5 ; done # cleanup for i in `cat manpageus`; do -perl -p -i -e 's|.B Description:/|\n.P\n.TP|g' stapprobes.$i.5.in ; +# context.stp +perl -p -i -e 's|.B Description:/|\n.P\n.TP|g' $i.5 ; +perl -p -i -e 's|.B Description:|.B Description:\n\n |g' $i.5 ; +cat $i.5 | perl -p -e 'undef $/;s|\.B Arguments:\n\n\.B |.B|msg' | +perl -p -e 'undef $/;s|\n \* ||msg' > stapprobes.$i.5.in ; +# cleanup all remaining stars, excess initial whitespace, and trailing "/" per line +perl -p -i -e 's|^ \*||g' stapprobes.$i.5.in; +perl -p -i -e 's|^ ||g' stapprobes.$i.5.in; +perl -p -i -e 's|^/||g' stapprobes.$i.5.in; done +# file cleanup +rm `ls | grep -v stapprobes` + +# perl -p -i -e 's|||g' stapprobes.$i.5.in ; # perl -p -i -e 's|||g' $i.manpagebody # use to move marked strings. -# sed -n '/\/\/ /,/\/\/ <\/tapsetdescription>/ s/.*/&/w bleh' < ioscheduler \ No newline at end of file +# sed -n '/\/\/ /,/\/\/ <\/tapsetdescription>/ s/.*/&/w bleh' < ioscheduler +# remove excess initial whitespace for each line +# perl -p -i -e 's|^ ||g' stapprobes.$i.5.in; +# convert tags +# perl -p -i -e 's|]*>|\n|g' stapprobes.$i.5.in ; +# perl -p -i -e 's|<[^>]*>|\n.B |g' stapprobes.$i.5.in ; \ No newline at end of file -- cgit From bdc56b7c2a00cf360d0b7cd92ed5bea836c4223b Mon Sep 17 00:00:00 2001 From: ddomingo Date: Tue, 17 Mar 2009 13:42:14 +1000 Subject: minor edits --- doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml b/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml index 01e4c358..d497eae6 100644 --- a/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml +++ b/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml @@ -276,7 +276,7 @@ probe process.create = kernel.function("copy_process").return emphasis programlisting remark (tagged strings will appear in Publican beta - builds of the document. + builds of the document) -- cgit From d518b0c2e446ff74096e5cd00b00f39220485909 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Tue, 17 Mar 2009 13:42:34 +1000 Subject: minor edits --- tapset/context.stp | 70 +++++++++++++++++------------------------------------- 1 file changed, 22 insertions(+), 48 deletions(-) diff --git a/tapset/context.stp b/tapset/context.stp index f4b0207a..66ca813f 100644 --- a/tapset/context.stp +++ b/tapset/context.stp @@ -21,37 +21,28 @@ function print_regs () %{ %} /** - * sfunction execname - Execname of current processes - * - * Return the name of the current process. + * sfunction execname - Returns the execname of a target process (or group of processes). */ function execname:string () %{ /* pure */ strlcpy (THIS->__retvalue, current->comm, MAXSTRINGLEN); %} /** - * sfunction pid - Process ID of current process - * - * - * Return the id of the current process. + * sfunction pid - Returns the ID of a target process. */ function pid:long () %{ /* pure */ THIS->__retvalue = current->tgid; %} /** - * sfunction tid - Thread ID of current process - * - * Return the id of the current thread. + * sfunction tid - Returns the thread ID of a target process. */ function tid:long () %{ /* pure */ THIS->__retvalue = current->pid; %} /** - * sfunction ppid - Parent Process ID of current process - * - * Return the id of the parent process. + * sfunction ppid - Returns the process ID of a target process's parent process. */ function ppid:long () %{ /* pure */ #if defined(STAPCONF_REAL_PARENT) @@ -62,9 +53,7 @@ function ppid:long () %{ /* pure */ %} /** - * sfunction pexecname - Execname of the parent process. - * - * Return the name of the parent process. + * sfunction pexecname - Returns the execname of a target process's parent process. */ function pexecname:string () %{ /* pure */ #if defined(STAPCONF_REAL_PARENT) @@ -75,9 +64,7 @@ function pexecname:string () %{ /* pure */ %} /** - * sfunction gid - Group ID of current process - * - * Return the gid of the current process. + * sfunction gid - Returns the group ID of a target process. */ function gid:long () %{ /* pure */ #ifdef STAPCONF_TASK_UID @@ -88,9 +75,7 @@ function gid:long () %{ /* pure */ %} /** - * sfunction egid - Effective gid of the current process. - * - * Return the effective gid of the current process. + * sfunction egid - Returns the effective gid of a target process. */ function egid:long () %{ /* pure */ #ifdef STAPCONF_TASK_UID @@ -101,9 +86,7 @@ function egid:long () %{ /* pure */ %} /** - * sfunction uid -User ID of the current process. - * - * Return the uid of the current process. + * sfunction uid - Returns the user ID of a target process. */ function uid:long () %{ /* pure */ #ifdef STAPCONF_TASK_UID @@ -114,9 +97,7 @@ function uid:long () %{ /* pure */ %} /** - * sfunction euid - Effective User ID of the current process. - * - * Return the effective uid of the current process. + * sfunction euid - Return the effective uid of a target process. */ function euid:long () %{ /* pure */ #ifdef STAPCONF_TASK_UID @@ -132,26 +113,23 @@ function cpuid:long () %{ /* pure */ %} /** - * sfunction cpu - The current cpu number. - * - * Return the current cpu number. + * sfunction cpu - Returns the current cpu number. */ function cpu:long () %{ /* pure */ THIS->__retvalue = smp_processor_id(); %} /** - * sfunction pp - Current probe point - * - * Return the probe point associated with the currently running - * probe handler, including alias and wildcard expansion effects. + * sfunction pp - Return the probe point associated with the currently running probe handler, including alias and wildcard expansion effects + * Context: + * The current probe point. */ function pp:string () %{ /* pure */ strlcpy (THIS->__retvalue, CONTEXT->probe_point, MAXSTRINGLEN); %} /** - * sfunction registers_valid - Register information valid + * sfunction registers_valid - Determines validity of register() and u_register() in current context. * * Return 1 if register() and u_register() can be used * in the current context, or 0 otherwise. @@ -163,7 +141,7 @@ function registers_valid:long () %{ /* pure */ %} /** - * sfunction user_mode - User Mode + * sfunction user_mode - Determines if probe point occurs in user-mode. * * Return 1 if the probe point occurred in user-mode. */ @@ -180,7 +158,7 @@ function user_mode:long () %{ /* pure */ /* currently a user-mode address? */ %} /** - * sfunction is_return - Is return probe + * sfunction is_return - Determines if probe point is a return probe. * * Return 1 if the probe point is a return probe. * Deprecated. @@ -193,9 +171,7 @@ function is_return:long () %{ /* pure */ %} /** - * sfunction target - Target pid - * - * Return the pid of the target process. + * sfunction target - Return the process ID of the target process. */ function target:long () %{ /* pure */ THIS->__retvalue = _stp_target; @@ -224,18 +200,16 @@ function stp_pid:long () %{ /* pure */ %} /** - * sfunction stack_size - Size of kernel stack - * - * Return the size of the kernel stack. + * sfunction stack_size - Return the size of the kernel stack. */ function stack_size:long () %{ /* pure */ THIS->__retvalue = THREAD_SIZE; %} /** - * sfunction stack_used - Current amount of kernel stack used + * sfunction stack_used - Returns the amount of kernel stack used. * - * Return how many bytes are currently used in the kernel stack. + * Determines how many bytes are currently used in the kernel stack. */ function stack_used:long () %{ /* pure */ char a; @@ -243,9 +217,9 @@ function stack_used:long () %{ /* pure */ %} /** - * sfunction stack_unused - Amount of kernel stack currently available + * sfunction stack_unused - Returns the amount of kernel stack currently available * - * Return how many bytes are currently available in the kernel stack. + * Determines how many bytes are currently available in the kernel stack. */ function stack_unused:long () %{ /* pure */ char a; -- cgit From ca9c813990b17f9a5d01e3f39350bcced9dc7260 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Tue, 17 Mar 2009 13:48:08 +1000 Subject: further cleanup for formatting --- tapset/udp.stp | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/tapset/udp.stp b/tapset/udp.stp index f2b19a7f..2255074a 100644 --- a/tapset/udp.stp +++ b/tapset/udp.stp @@ -17,12 +17,12 @@ /** * probe udp.sendmsg - Fires whenever a process sends a UDP message - * @name: Name of this probe - * @sock: Network socket - * @size: Number of bytes to send + * @name: The name of this probe + * @sock: Network socket used by the process + * @size: Number of bytes sent by the process * * Context: - * The process which sends a udp message + * The process which sent a UDP message */ probe udp.sendmsg = kernel.function("udp_sendmsg") { name = "udp.sendmsg" @@ -32,11 +32,11 @@ probe udp.sendmsg = kernel.function("udp_sendmsg") { /** * probe udp.sendmsg.return - Fires whenever an attempt to send a UDP message is completed - * @name: Name of this probe - * @size: Number of bytes sent + * @name: The name of this probe + * @size: Number of bytes sent by the process * * Context: - * The process which sends a udp message + * The process which sent a UDP message */ probe udp.sendmsg.return = kernel.function("udp_sendmsg").return { name = "udp.sendmsg" @@ -45,12 +45,12 @@ probe udp.sendmsg.return = kernel.function("udp_sendmsg").return { /** * probe udp.recvmsg - Fires whenever a UDP message is received - * @name: Name of this probe - * @sock: Network socket - * @size: Number of bytes received + * @name: The name of this probe + * @sock: Network socket used by the process + * @size: Number of bytes received by the process * * Context: - * The process which receives a udp message + * The process which received a UDP message */ probe udp.recvmsg = kernel.function("udp_recvmsg") { name = "udp.recvmsg" @@ -59,12 +59,12 @@ probe udp.recvmsg = kernel.function("udp_recvmsg") { } /** - * probe udp.recvmsg.return - An attempt to receive a UDP message received has been completed - * @name: Name of this probe - * @size: Number of bytes received + * probe udp.recvmsg.return - Fires whenever an attempt to receive a UDP message received is completed + * @name: The name of this probe + * @size: Number of bytes received by the process * * Context: - * The process which receives a udp message + * The process which received a UDP message */ probe udp.recvmsg.return = kernel.function("udp_recvmsg").return { name = "udp.recvmsg" @@ -72,13 +72,13 @@ probe udp.recvmsg.return = kernel.function("udp_recvmsg").return { } /** - * probe udp.disconnect - A process requests for UPD to be UDP disconnected - * @name: Name of this probe - * @sock: Network socket + * probe udp.disconnect - Fires when a process requests for a UDP disconnection + * @name: The name of this probe + * @sock: Network socket used by the process * @flags: Flags (e.g. FIN, etc) * * Context: - * The process which disconnects UDP + * The process which requests a UDP disconnection */ probe udp.disconnect = kernel.function("udp_disconnect") { name = "udp.disconnect" @@ -88,11 +88,11 @@ probe udp.disconnect = kernel.function("udp_disconnect") { /** * probe udp.disconnect.return - UDP has been disconnected successfully - * @name: Name of this probe + * @name: The name of this probe * @ret: Error code (0: no error) * * Context: - * The process which disconnects udp + * The process which requested a UDP disconnection */ probe udp.disconnect.return = kernel.function("udp_disconnect").return { name = "udp.disconnect" -- cgit From 929a278ec01bc14630d247788352a2aaab372ddd Mon Sep 17 00:00:00 2001 From: ddomingo Date: Tue, 17 Mar 2009 13:56:21 +1000 Subject: further cleanup for formatting --- tapset/scsi.stp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tapset/scsi.stp b/tapset/scsi.stp index 8ff3dcca..1c52355a 100644 --- a/tapset/scsi.stp +++ b/tapset/scsi.stp @@ -47,8 +47,8 @@ probe scsi.ioentry * @dev_id: The scsi device id * @device_state: The current state of the device. * @data_direction: The data_direction specifies whether this command is from/to - * the device. 0 (DMA_BIDIRECTIONAL), 1 (DMA_TO_DEVICE), - * 2 (DMA_FROM_DEVICE), 3 (DMA_NONE) + * the device. 0 (DMA_BIDIRECTIONAL), 1 (DMA_TO_DEVICE), + * 2 (DMA_FROM_DEVICE), 3 (DMA_NONE) * @request_buffer: The request buffer address * @req_bufflen: The request buffer length */ @@ -81,7 +81,7 @@ probe scsi.iodispatching * @dev_id: The scsi device id * @device_state: The current state of the device * @data_direction: The data_direction specifies whether this command is - * from/to the device. + * from/to the device. */ probe scsi.iodone = module("scsi_mod").function("scsi_done@drivers/scsi/scsi.c")?, @@ -106,7 +106,7 @@ probe scsi.iodone * @dev_id: The scsi device id * @device_state: The current state of the device * @data_direction: The data_direction specifies whether this command is from/to - * the device + * the device * @goodbytes: The bytes completed. */ // mid-layer processes the completed IO -- cgit From 11f44635b6964dd7a7753da6722fa4750573d0ca Mon Sep 17 00:00:00 2001 From: ddomingo Date: Tue, 17 Mar 2009 14:43:19 +1000 Subject: working copy --- doc/Tapset_Reference_Guide/manpager.sh | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/doc/Tapset_Reference_Guide/manpager.sh b/doc/Tapset_Reference_Guide/manpager.sh index 16ee441f..0876121a 100644 --- a/doc/Tapset_Reference_Guide/manpager.sh +++ b/doc/Tapset_Reference_Guide/manpager.sh @@ -99,11 +99,19 @@ for i in `cat manpageus`; do perl -p -i -e 's|.B Description:/|\n.P\n.TP|g' $i.5 ; perl -p -i -e 's|.B Description:|.B Description:\n\n |g' $i.5 ; cat $i.5 | perl -p -e 'undef $/;s|\.B Arguments:\n\n\.B |.B|msg' | -perl -p -e 'undef $/;s|\n \* ||msg' > stapprobes.$i.5.in ; +perl -p -e 'undef $/;s|\n \* | |msg' > stapprobes.$i.5.in ; # cleanup all remaining stars, excess initial whitespace, and trailing "/" per line perl -p -i -e 's|^ \*||g' stapprobes.$i.5.in; perl -p -i -e 's|^ ||g' stapprobes.$i.5.in; perl -p -i -e 's|^/||g' stapprobes.$i.5.in; +# convert tags +perl -p -i -e 's|]*>|\n|g' stapprobes.$i.5.in ; +perl -p -i -e 's|<[^>]*>|\n.B |g' stapprobes.$i.5.in ; +# cleanup remaining excess whitespace +perl -p -i -e 's|\t\t| |g' stapprobes.$i.5.in; +perl -p -i -e 's|^ ||g' stapprobes.$i.5.in; +#sed -i -e 's/$/ /g' stapprobes.$i.5.in; +#sed -i -e 's|$ | |g' stapprobes.$i.5.in; done # file cleanup -- cgit From 83b85c2b0be729352bae4ea204d814b377b32fcf Mon Sep 17 00:00:00 2001 From: ddomingo Date: Tue, 17 Mar 2009 15:13:23 +1000 Subject: minor edits --- tapset/context-symbols.stp | 11 ++++------- tapset/context-unwind.stp | 10 +++++----- tapset/context.stp | 5 +++-- tapset/ioscheduler.stp | 2 +- tapset/memory.stp | 8 ++++---- tapset/scsi.stp | 5 +++-- 6 files changed, 20 insertions(+), 21 deletions(-) diff --git a/tapset/context-symbols.stp b/tapset/context-symbols.stp index 4a08ec60..babaa3ef 100644 --- a/tapset/context-symbols.stp +++ b/tapset/context-symbols.stp @@ -22,8 +22,9 @@ * @stk: String with list of hexidecimal addresses. (FIXME) * * Perform a symbolic lookup of the addresses in the given string, - * which is assumed to be the result of a prior call to + * which is assumed to be the result of a prior call to * backtrace(). + * * Print one line per address, including the address, the * name of the function containing the address, and an estimate of * its position within that function. Return nothing. @@ -40,9 +41,7 @@ function print_stack(stk:string) %{ %} /** - * sfunction probefunc - Function probed - * - * Return the probe point's function name, if known. + * sfunction probefunc - Return the probe point's function name, if known. */ function probefunc:string () %{ /* pure */ char *ptr, *start; @@ -76,9 +75,7 @@ function probefunc:string () %{ /* pure */ %} /** - * sfunction probemod - Module probed - * - * Return the probe point's module name, if known. + * sfunction probemod - Return the probe point's module name, if known. */ function probemod:string () %{ /* pure */ char *ptr, *start; diff --git a/tapset/context-unwind.stp b/tapset/context-unwind.stp index 5c1253b8..90d4e0f4 100644 --- a/tapset/context-unwind.stp +++ b/tapset/context-unwind.stp @@ -23,7 +23,7 @@ /** * sfunction print_backtrace - Print stack back trace * - * Equivalent to print_stack(backtrace()), + * Equivalent to print_stack(backtrace()), * except that deeper stack nesting may be supported. Return nothing. */ function print_backtrace () %{ @@ -37,8 +37,8 @@ function print_backtrace () %{ /** * sfunction backtrace - Hex backtrace of current stack * - * Return a string of hex addresses that are a backtrace of the - * stack. It may be truncated due to maximum string length. + * Return a string of hex addresses that are a backtrace of the + * stack. Output may be truncated as per maximum string length. */ function backtrace:string () %{ /* pure */ if (CONTEXT->regs) @@ -50,7 +50,7 @@ function backtrace:string () %{ /* pure */ /** * sfunction caller - Return name and address of calling function * - * Return the address and name of the calling function. + * Return the address and name of the calling function. * Works only for return probes at this time. */ function caller:string() %{ /* pure */ @@ -64,7 +64,7 @@ function caller:string() %{ /* pure */ /** * sfunction caller_addr - Return caller address * - * Return the address of the calling function. + * Return the address of the calling function. * Works only for return probes at this time. */ function caller_addr:long () %{ /* pure */ diff --git a/tapset/context.stp b/tapset/context.stp index 66ca813f..9f4be0e6 100644 --- a/tapset/context.stp +++ b/tapset/context.stp @@ -120,7 +120,8 @@ function cpu:long () %{ /* pure */ %} /** - * sfunction pp - Return the probe point associated with the currently running probe handler, including alias and wildcard expansion effects + * sfunction pp - Return the probe point associated with the currently running probe handler, + * including alias and wildcard expansion effects * Context: * The current probe point. */ @@ -217,7 +218,7 @@ function stack_used:long () %{ /* pure */ %} /** - * sfunction stack_unused - Returns the amount of kernel stack currently available + * sfunction stack_unused - Returns the amount of kernel stack currently available. * * Determines how many bytes are currently available in the kernel stack. */ diff --git a/tapset/ioscheduler.stp b/tapset/ioscheduler.stp index 875ccea9..a79ae752 100644 --- a/tapset/ioscheduler.stp +++ b/tapset/ioscheduler.stp @@ -60,7 +60,7 @@ probe ioscheduler.elv_next_request.return } /** - * probe ioscheduler.elv_add_request -A request was added to the request queue + * probe ioscheduler.elv_add_request - A request was added to the request queue * @elevator_name: The type of I/O elevator currently enabled * @req: Address of the request * @req_flags: Request flags diff --git a/tapset/memory.stp b/tapset/memory.stp index 9dbe3fba..83875aa4 100644 --- a/tapset/memory.stp +++ b/tapset/memory.stp @@ -56,7 +56,7 @@ function vm_fault_contains:long (value:long, test:long) /** * probe vm.pagefault - Records that a page fault occurred. * @address: The address of the faulting memory access; i.e. the address that caused the page fault. - * @write_access: Indicates whether this was a write or read access; 1 indicates a write, + * @write_access: Indicates whether this was a write or read access; 1 indicates a write, * while 0 indicates a read. * * Context: The process which triggered the fault @@ -113,8 +113,8 @@ function _IS_ZERO_PAGE:long(from:long, vaddr:long) %{ /* pure */ * Context: * The context is the process attempting the write. * - * Fires when a process attempts to write to a shared page. - * If a copy is necessary, this will be followed by a + * Fires when a process attempts to write to a shared page. + * If a copy is necessary, this will be followed by a * vm.write_shared_copy. */ probe vm.write_shared = kernel.function("do_wp_page") { @@ -122,7 +122,7 @@ probe vm.write_shared = kernel.function("do_wp_page") { } /** - * probe vm.write_shared_copy- Page copy for shared page write. + * probe vm.write_shared_copy - Page copy for shared page write. * @address: The address of the shared write. * @zero: Boolean indicating whether it is a zero page * (can do a clear instead of a copy). diff --git a/tapset/scsi.stp b/tapset/scsi.stp index 1c52355a..f8859be2 100644 --- a/tapset/scsi.stp +++ b/tapset/scsi.stp @@ -46,8 +46,8 @@ probe scsi.ioentry * @lun: The lun number * @dev_id: The scsi device id * @device_state: The current state of the device. - * @data_direction: The data_direction specifies whether this command is from/to - * the device. 0 (DMA_BIDIRECTIONAL), 1 (DMA_TO_DEVICE), + * @data_direction: The data_direction specifies whether this command is from/to the device. + * 0 (DMA_BIDIRECTIONAL), 1 (DMA_TO_DEVICE), * 2 (DMA_FROM_DEVICE), 3 (DMA_NONE) * @request_buffer: The request buffer address * @req_bufflen: The request buffer length @@ -142,3 +142,4 @@ function get_devstate_from_req:long(var:long) sdev = @cast(var, "request_queue", "kernel:scsi_mod")->queuedata return @cast(sdev, "scsi_device", "kernel:scsi_mod")->sdev_state } +g \ No newline at end of file -- cgit From d8ad52f9739264779d2efc7dad8b7e2cfe785868 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Tue, 17 Mar 2009 15:14:30 +1000 Subject: minor edits --- tapset/context-symbols.stp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tapset/context-symbols.stp b/tapset/context-symbols.stp index babaa3ef..a3aae408 100644 --- a/tapset/context-symbols.stp +++ b/tapset/context-symbols.stp @@ -18,7 +18,7 @@ %} // weirdness with print_stack, argument appears in build as undescribed /** - * sfunction print_stack - Print out stack from string + * sfunction print_stack - Print out stack from string. * @stk: String with list of hexidecimal addresses. (FIXME) * * Perform a symbolic lookup of the addresses in the given string, -- cgit From 701a5a1c9f8c815830d5e91b62cce7098f29f549 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Tue, 17 Mar 2009 15:28:38 +1000 Subject: working copy, still existing issues with Description headers, will work on it tom --- doc/Tapset_Reference_Guide/manpager.sh | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/doc/Tapset_Reference_Guide/manpager.sh b/doc/Tapset_Reference_Guide/manpager.sh index 0876121a..2b9873b7 100644 --- a/doc/Tapset_Reference_Guide/manpager.sh +++ b/doc/Tapset_Reference_Guide/manpager.sh @@ -44,7 +44,7 @@ done ; # create man page headers for i in `ls | grep -v .stp | grep -v tapsetdescription` ; do #echo ".\" -*- nroff -*-" >> $i.template ; -echo ".TH STAPPROBES.manpagename 5 @DATE@ "IBM"" >> $i.template ; +echo ".TH STAPPROBES."$i" 5 @DATE@ "IBM"" >> $i.template ; echo ".SH NAME" >> $i.template ; echo "stapprobes."`cat $i.stp`" \- systemtap "`cat $i.stp`" probe points" >> $i.template ; echo " " >> $i.template ; @@ -98,25 +98,27 @@ for i in `cat manpageus`; do # context.stp perl -p -i -e 's|.B Description:/|\n.P\n.TP|g' $i.5 ; perl -p -i -e 's|.B Description:|.B Description:\n\n |g' $i.5 ; -cat $i.5 | perl -p -e 'undef $/;s|\.B Arguments:\n\n\.B |.B|msg' | +# convert tags +perl -p -i -e 's|]*>([^.])|$1\n|g' $i.5 ; +perl -p -i -e 's|<[^>]*>|\n.B |g' $i.5 ; +cat $i.5 | +perl -p -e 'undef $/;s|\.B Arguments:\n\n\.B |.B|msg' | +# for tagged commands followed by periods +perl -p -e 'undef $/;s|\n\.B \.|.\n|msg' | perl -p -e 'undef $/;s|\n \* | |msg' > stapprobes.$i.5.in ; # cleanup all remaining stars, excess initial whitespace, and trailing "/" per line perl -p -i -e 's|^ \*||g' stapprobes.$i.5.in; -perl -p -i -e 's|^ ||g' stapprobes.$i.5.in; +perl -p -i -e 's|^[ ]*||g' stapprobes.$i.5.in; perl -p -i -e 's|^/||g' stapprobes.$i.5.in; -# convert tags -perl -p -i -e 's|]*>|\n|g' stapprobes.$i.5.in ; -perl -p -i -e 's|<[^>]*>|\n.B |g' stapprobes.$i.5.in ; # cleanup remaining excess whitespace perl -p -i -e 's|\t\t| |g' stapprobes.$i.5.in; perl -p -i -e 's|^ ||g' stapprobes.$i.5.in; -#sed -i -e 's/$/ /g' stapprobes.$i.5.in; -#sed -i -e 's|$ | |g' stapprobes.$i.5.in; +sed -i -e 's/ / /g' stapprobes.$i.5.in; done # file cleanup rm `ls | grep -v stapprobes` - +#mv workingdir final_manpages # perl -p -i -e 's|||g' stapprobes.$i.5.in ; # perl -p -i -e 's|||g' $i.manpagebody -- cgit From 4e7c048f5184ffcb06bc64d8be6e859156c8af97 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Tue, 17 Mar 2009 15:28:43 +1000 Subject: minor edits --- tapset/socket.stp | 70 +++++++++++++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 38 deletions(-) diff --git a/tapset/socket.stp b/tapset/socket.stp index 93730f9f..0f01b8d4 100644 --- a/tapset/socket.stp +++ b/tapset/socket.stp @@ -67,8 +67,8 @@ probe socket.receive = socket.recvmsg.return, ### FUNCTION SPECIFIC SEND/RECEIVE PROBES ### -/* - * probe socket.sendmsg - Message being sent on socket +/** + * probe socket.sendmsg - Message is currently being sent on a socket. * @name: Name of this probe * @size: Message size in bytes * @protocol: Protocol value @@ -95,7 +95,7 @@ probe socket.sendmsg = kernel.function ("sock_sendmsg") } /** - * probe socket.sendmsg.return - Return from Message being sent on socket + * probe socket.sendmsg.return - Return from socket.sendmsg. * @name: Name of this probe * @size: Size of message sent (in bytes) or error code if success = 0 * @protocol: Protocol value @@ -151,7 +151,7 @@ probe socket.recvmsg = kernel.function ("sock_recvmsg") type = $sock->type } -/* +/** * probe socket.recvmsg.return - Return from Message being received on socket * @name: Name of this probe * @size: Size of message received (in bytes) or error code if success = 0 @@ -198,14 +198,14 @@ probe socket.recvmsg.return = kernel.function ("sock_recvmsg").return * Fires at the beginning of sending a message on a socket * via the sock_aio_write() function */ -/* - * 2.6.9~2.6.15: - * static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t size, loff_t pos); - * 2.6.16~2.6.18: - * static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t count, loff_t pos); - * 2.6.19~2.6.26: - * static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos); - */ +// +// 2.6.9~2.6.15: +// static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t size, loff_t pos); +// 2.6.16~2.6.18: +// static ssize_t sock_aio_write(struct kiocb *iocb, const char __user *ubuf, size_t count, loff_t pos); +// 2.6.19~2.6.26: +// static ssize_t sock_aio_write(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos); + probe socket.aio_write = kernel.function ("sock_aio_write") { name = "socket.aio_write" @@ -272,14 +272,14 @@ probe socket.aio_write.return = kernel.function ("sock_aio_write").return * Fires at the beginning of receiving a message on a socket * via the sock_aio_read() function */ -/* - * 2.6.9~2.6.15: - * static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf, size_t size, loff_t pos); - * 2.6.16~2.6.18: - * static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf, size_t count, loff_t pos); - * 2.6.19~2.6.26: - * static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos); - */ +// +// 2.6.9~2.6.15: +// static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf, size_t size, loff_t pos); +// 2.6.16~2.6.18: +// static ssize_t sock_aio_read(struct kiocb *iocb, char __user *ubuf, size_t count, loff_t pos); +// 2.6.19~2.6.26: +// static ssize_t sock_aio_read(struct kiocb *iocb, const struct iovec *iov, unsigned long nr_segs, loff_t pos); + probe socket.aio_read = kernel.function ("sock_aio_read") { name = "socket.aio_read" @@ -543,18 +543,16 @@ probe socket.close.return = kernel.function ("sock_release").return ####### PROTOCOL HELPER FUNCTIONS ######## -/* - * sock_prot_num2str - * Given a protocol number, return a string representation. +/** + * sfunction sock_prot_num2str - Given a protocol number, return a string representation. */ function sock_prot_num2str:string (proto:long) { return (proto in _prot_num2str ? _prot_num2str[proto] : "UNDEF") } -/* - * sock_prot_str2num - * Given a protocol name (string), return the corresponding protocol number. +/** + * sfunction sock_prot_str2num - Given a protocol name (string), return the corresponding protocol number. */ function sock_prot_str2num:long (proto:string) { @@ -563,18 +561,16 @@ function sock_prot_str2num:long (proto:string) ######### PROTOCOL FAMILY HELPER FUNCTIONS ########### -/* - * sock_fam_num2str - * Given a protocol family number, return a string representation. +/** + * sfunction sock_fam_num2str - Given a protocol family number, return a string representation. */ function sock_fam_num2str:string (family:long) { return (family in _fam_num2str ? _fam_num2str[family] : "UNDEF") } -/* - * sock_fam_str2num - * Given a protocol family name (string), return the corresponding +/** + * sfunction sock_fam_str2num - Given a protocol family name (string), return the corresponding * protocol family number. */ function sock_fam_str2num:long (family:string) @@ -584,18 +580,16 @@ function sock_fam_str2num:long (family:string) ######### SOCKET STATE HELPER FUNCTIONS ########## -/* - * sock_state_num2str - * Given a socket state number, return a string representation. +/** + * sfunction sock_state_num2str - Given a socket state number, return a string representation. */ function sock_state_num2str:string (state:long) { return (state in _state_num2str ? _state_num2str[state] : "UNDEF") } -/* - * sock_state_str2num - * Given a socket state string, return the corresponding state number. +/** + * sfunction sock_state_str2num - Given a socket state string, return the corresponding state number. */ function sock_state_str2num:long (state:string) { -- cgit From dcb8ea7a7d1461bef3ea56ebf65d07e8ff998a00 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 17 Mar 2009 12:50:43 +0100 Subject: Remove trailing 'g' from scsi.stp file. * tapset/scsi.stp: Remove 'g' at end of file. --- tapset/scsi.stp | 1 - 1 file changed, 1 deletion(-) diff --git a/tapset/scsi.stp b/tapset/scsi.stp index f8859be2..e1457739 100644 --- a/tapset/scsi.stp +++ b/tapset/scsi.stp @@ -142,4 +142,3 @@ function get_devstate_from_req:long(var:long) sdev = @cast(var, "request_queue", "kernel:scsi_mod")->queuedata return @cast(sdev, "scsi_device", "kernel:scsi_mod")->sdev_state } -g \ No newline at end of file -- cgit From 30cb532a560ed152b86506b80490e99195970271 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 17 Mar 2009 13:50:33 +0100 Subject: Get the canonical path of the main file for comparison at runtime. When given directly by the user through -d or in case of the kernel name and path might differ. path should be used for matching. * runtime/sym.h (_stp_module): Add path field. * runtime/task_finder.c (__stp_tf_vm_cb): Use module path to compare vm_path. * translate.cxx (dump_unwindsyms): Output canonical path. --- runtime/sym.h | 1 + runtime/task_finder.c | 2 +- translate.cxx | 9 +++++++++ 3 files changed, 11 insertions(+), 1 deletion(-) diff --git a/runtime/sym.h b/runtime/sym.h index e642cab4..586b10ca 100644 --- a/runtime/sym.h +++ b/runtime/sym.h @@ -25,6 +25,7 @@ struct _stp_section { struct _stp_module { const char* name; + const char* path; /* canonical path used for runtime matching. */ struct _stp_section *sections; unsigned num_sections; diff --git a/runtime/task_finder.c b/runtime/task_finder.c index ae381a41..38f9145d 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -72,7 +72,7 @@ static int __stp_tf_vm_cb(struct stap_task_finder_target *tgt, struct _stp_module *module = NULL; if (vm_path != NULL) for (i = 0; i < _stp_num_modules; i++) - if (strcmp(vm_path, _stp_modules[i]->name) == 0) + if (strcmp(vm_path, _stp_modules[i]->path) == 0) { #ifdef DEBUG_TASK_FINDER_VMA _stp_dbug(__FUNCTION__, __LINE__, diff --git a/translate.cxx b/translate.cxx index f4c28536..377a11fb 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4700,6 +4700,15 @@ dump_unwindsyms (Dwfl_Module *m, c->output << "static struct _stp_module _stp_module_" << stpmod_idx << " = {\n"; c->output << ".name = " << lex_cast_qstring (modname) << ", \n"; + + // Get the canonical path of the main file for comparison at runtime. + // When given directly by the user through -d or in case of the kernel + // name and path might differ. path should be used for matching. + const char *mainfile; + dwfl_module_info (m, NULL, NULL, NULL, NULL, NULL, &mainfile, NULL); + mainfile = canonicalize_file_name(mainfile); + c->output << ".path = " << lex_cast_qstring (mainfile) << ",\n"; + c->output << ".dwarf_module_base = 0x" << hex << base << dec << ", \n"; if (unwind != NULL) -- cgit From 67aada05e69728327de1c7b8aeeaa0193668bed8 Mon Sep 17 00:00:00 2001 From: Stan Cox Date: Tue, 17 Mar 2009 11:38:08 -0400 Subject: Improve static_uprobes.exp * systemtap.base/static_uprobes.exp: Compile with -x c++. Test .probes absence. --- testsuite/systemtap.base/static_uprobes.exp | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/testsuite/systemtap.base/static_uprobes.exp b/testsuite/systemtap.base/static_uprobes.exp index a4bd5e2c..b4214436 100644 --- a/testsuite/systemtap.base/static_uprobes.exp +++ b/testsuite/systemtap.base/static_uprobes.exp @@ -1,5 +1,4 @@ - -set test "sduprobes" +set test "static_uprobes" # Compile a C program to use as the user-space probing target set sup_srcpath "[pwd]/static_uprobes.c" @@ -115,9 +114,7 @@ if { $res != "" } { pass "$test compiling C -g" } -spawn mv $sup_srcpath "[pwd]/static_uprobes.cc" -set sup_srcpath "[pwd]/static_uprobes.cc" -set sup_flags "$sup_flags c++" +set sup_flags "$sup_flags additional_flags=-x additional_flags=c++" set res [target_compile $sup_srcpath $supcplus_exepath executable $sup_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 @@ -163,9 +160,9 @@ if {$ok == 5} { pass "$test C" } { fail "$test C ($ok)" } set ok 0 -# spawn objcopy -R .probes $supcplus_exepath $sup_exepath -verbose -log "cp $supcplus_exepath $sup_exepath" -spawn cp $supcplus_exepath $sup_exepath +# Test setting a probe without .probes using only dwarf label info +verbose -log "objcopy -R .probes $supcplus_exepath $sup_exepath" +spawn objcopy -R .probes $supcplus_exepath $sup_exepath verbose -log "spawn stap -c $sup_exepath $sup_stppath" spawn stap -c $sup_exepath $sup_stppath expect { @@ -182,7 +179,4 @@ wait if {$ok == 5} { pass "$test C++" } { fail "$test C++ ($ok)" } -# catch {exec rm -f $sup_srcpath $sup_exepath $supcplus_exepath $sup_hpath $sup_stppath} - -# It's not so important to clean up, and it's unhelpful if -# one needs to diagnose a test failure. +catch {exec rm -f $sup_srcpath $sup_exepath $supcplus_exepath $sup_dpath $sup_hpath $sup_stppath} -- cgit From 67f8611b9ed9e40a7be946601293ac5b42c52686 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Tue, 17 Mar 2009 16:45:30 -0400 Subject: Replace systemtap.samples/ioblocktest.stp with ioblktime.stp. --- testsuite/systemtap.examples/index.html | 3 +++ testsuite/systemtap.examples/index.txt | 13 +++++++++++ testsuite/systemtap.examples/io/ioblktime.meta | 13 +++++++++++ testsuite/systemtap.examples/io/ioblktime.stp | 29 +++++++++++++++++++++++++ testsuite/systemtap.examples/keyword-index.html | 3 +++ testsuite/systemtap.examples/keyword-index.txt | 13 +++++++++++ testsuite/systemtap.samples/ioblocktest.exp | 11 ---------- testsuite/systemtap.samples/ioblocktest.stp | 12 ---------- 8 files changed, 74 insertions(+), 23 deletions(-) create mode 100644 testsuite/systemtap.examples/io/ioblktime.meta create mode 100755 testsuite/systemtap.examples/io/ioblktime.stp delete mode 100644 testsuite/systemtap.samples/ioblocktest.exp delete mode 100644 testsuite/systemtap.samples/ioblocktest.stp diff --git a/testsuite/systemtap.examples/index.html b/testsuite/systemtap.examples/index.html index 7b76baa1..0f4b2572 100644 --- a/testsuite/systemtap.examples/index.html +++ b/testsuite/systemtap.examples/index.html @@ -58,6 +58,9 @@ keywords: DISK
  • io/io_submit.stp - Tally Reschedule Reason During AIO io_submit Call
    keywords: IO BACKTRACE

    When a reschedule occurs during an AIO io_submit call, accumulate the traceback in a histogram. When the script exits prints out a sorted list from most common to least common backtrace.

  • +
  • io/ioblktime.stp - Average Time Block IO Requests Spend in Queue
    +keywords: IO
    +

    The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script compute the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many oustanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line.

  • io/iostats.stp - List Executables Reading and Writing the Most Data
    keywords: IO PROFILING

    The iostat.stp script measures the amount of data successfully read and written by all the executables on the system. The output is sorted from most greatest sum of bytes read and written by an executable to the least. The output contains the count of operations (opens, reads, and writes), the totals and averages for the number of bytes read and written.

  • diff --git a/testsuite/systemtap.examples/index.txt b/testsuite/systemtap.examples/index.txt index fdcd3b31..e31baf4f 100644 --- a/testsuite/systemtap.examples/index.txt +++ b/testsuite/systemtap.examples/index.txt @@ -52,6 +52,19 @@ keywords: io backtrace list from most common to least common backtrace. +io/ioblktime.stp - Average Time Block IO Requests Spend in Queue +keywords: io + + The ioblktime.stp script tracks the amount of time that each block IO + requests spend waiting for completion. The script compute the average + time waiting time for block IO per device and prints list every 10 + seconds. In some cases there can be too many oustanding block IO + operations and the script may exceed the default number of + MAXMAPENTRIES allowed. In this case the allowed number can be + increased with "-DMAXMAPENTRIES=10000" option on the stap command + line. + + io/iostats.stp - List Executables Reading and Writing the Most Data keywords: io profiling diff --git a/testsuite/systemtap.examples/io/ioblktime.meta b/testsuite/systemtap.examples/io/ioblktime.meta new file mode 100644 index 00000000..18a8b168 --- /dev/null +++ b/testsuite/systemtap.examples/io/ioblktime.meta @@ -0,0 +1,13 @@ +title: Average Time Block IO Requests Spend in Queue +name: ioblktime.stp +version: 1.0 +author: William Cohen +keywords: io +subsystem: kernel +status: production +exit: user-controlled +output: sorted-list +scope: system-wide +description: The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script computes the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many oustanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line. +test_check: stap -p4 ioblktime.stp +test_installcheck: stap ioblktime.stp -c "sleep 1" diff --git a/testsuite/systemtap.examples/io/ioblktime.stp b/testsuite/systemtap.examples/io/ioblktime.stp new file mode 100755 index 00000000..5ff59cf7 --- /dev/null +++ b/testsuite/systemtap.examples/io/ioblktime.stp @@ -0,0 +1,29 @@ +#! /usr/bin/env stap + +global req_time, etimes + +probe ioblock.request +{ + req_time[$bio] = gettimeofday_us() +} + +probe ioblock.end +{ + t = gettimeofday_us() + s = req_time[$bio] + delete req_time[$bio] + if (s) { + etimes[devname, bio_rw_str(rw)] <<< t - s + } +} + +probe timer.s(10), end { + printf("\033[2J\033[1;1H") /* clear screen */ + printf("%10s %3s %10s %10s %10s\n", + "device", "rw", "total (us)", "count", "avg (us)") + foreach ([dev,rw] in etimes - limit 20) { + printf("%10s %3s %10d %10d %10d\n", dev, rw, + @sum(etimes[dev,rw]), @count(etimes[dev,rw]), @avg(etimes[dev,rw])) + } + delete etimes +} diff --git a/testsuite/systemtap.examples/keyword-index.html b/testsuite/systemtap.examples/keyword-index.html index b3ea0943..75768709 100644 --- a/testsuite/systemtap.examples/keyword-index.html +++ b/testsuite/systemtap.examples/keyword-index.html @@ -102,6 +102,9 @@ keywords: INTERRUPT io/io_submit.stp - Tally Reschedule Reason During AIO io_submit Call
    keywords: IO BACKTRACE

    When a reschedule occurs during an AIO io_submit call, accumulate the traceback in a histogram. When the script exits prints out a sorted list from most common to least common backtrace.

    +
  • io/ioblktime.stp - Average Time Block IO Requests Spend in Queue
    +keywords: IO
    +

    The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script compute the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many oustanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line.

  • io/iostats.stp - List Executables Reading and Writing the Most Data
    keywords: IO PROFILING

    The iostat.stp script measures the amount of data successfully read and written by all the executables on the system. The output is sorted from most greatest sum of bytes read and written by an executable to the least. The output contains the count of operations (opens, reads, and writes), the totals and averages for the number of bytes read and written.

  • diff --git a/testsuite/systemtap.examples/keyword-index.txt b/testsuite/systemtap.examples/keyword-index.txt index 5f382e75..d3a9617f 100644 --- a/testsuite/systemtap.examples/keyword-index.txt +++ b/testsuite/systemtap.examples/keyword-index.txt @@ -125,6 +125,19 @@ keywords: io backtrace list from most common to least common backtrace. +io/ioblktime.stp - Average Time Block IO Requests Spend in Queue +keywords: io + + The ioblktime.stp script tracks the amount of time that each block IO + requests spend waiting for completion. The script compute the average + time waiting time for block IO per device and prints list every 10 + seconds. In some cases there can be too many oustanding block IO + operations and the script may exceed the default number of + MAXMAPENTRIES allowed. In this case the allowed number can be + increased with "-DMAXMAPENTRIES=10000" option on the stap command + line. + + io/iostats.stp - List Executables Reading and Writing the Most Data keywords: io profiling diff --git a/testsuite/systemtap.samples/ioblocktest.exp b/testsuite/systemtap.samples/ioblocktest.exp deleted file mode 100644 index b5ab54c7..00000000 --- a/testsuite/systemtap.samples/ioblocktest.exp +++ /dev/null @@ -1,11 +0,0 @@ -# Test the functionality of the various ioblock probes. - -set test "ioblocktest" - -proc sleep_ten_secs {} { - after 10000; - return 0; -} - -set output_string "ioblock: \\S+\t\\d+\t\[RW]\t\[01]\r\n" -stap_run $srcdir/$subdir/$test.stp sleep_ten_secs $output_string diff --git a/testsuite/systemtap.samples/ioblocktest.stp b/testsuite/systemtap.samples/ioblocktest.stp deleted file mode 100644 index f8a1c568..00000000 --- a/testsuite/systemtap.samples/ioblocktest.stp +++ /dev/null @@ -1,12 +0,0 @@ -#! stap -global teststr -probe begin { println("systemtap starting probe") } - -probe ioblock.request, ioblock.end { - teststr = sprintf("ioblock: %s\t%d\t%s\t%d\n", devname, sector, - bio_rw_str(rw), bio_rw_num(rw)) -} -probe end { - println("systemtap ending probe") - printf("%s", teststr) -} -- cgit From 98b35fa37e2d00fae488f37ccf124c0899fcdcbf Mon Sep 17 00:00:00 2001 From: ddomingo Date: Wed, 18 Mar 2009 15:29:03 +1000 Subject: final copy, for review --- doc/Tapset_Reference_Guide/manpager.sh | 102 +++++++++++++++------------------ 1 file changed, 46 insertions(+), 56 deletions(-) diff --git a/doc/Tapset_Reference_Guide/manpager.sh b/doc/Tapset_Reference_Guide/manpager.sh index 2b9873b7..6c2d204e 100644 --- a/doc/Tapset_Reference_Guide/manpager.sh +++ b/doc/Tapset_Reference_Guide/manpager.sh @@ -3,7 +3,7 @@ # generated herein should be in sync with Tapset Reference Guide # cleanup -rm -rf workingdir +rm -rf man_pages # create working directory mkdir workingdir ; @@ -38,8 +38,6 @@ echo $i > tempname ; sed -i -e 's/.stp//g' tempname ; mv $i `cat tempname` ; mv tempname $i ; done ; -# clean all tapsetdescriptions (remove excess spaces) -# for i in `ls | grep tapsetdescription` ; do perl -p -i -e 's|^\n||g' $i ; done ; # create man page headers for i in `ls | grep -v .stp | grep -v tapsetdescription` ; do @@ -59,73 +57,65 @@ echo ".TP" >> $i.template ; done # MOST IMPORTANT: clean man page body! -for i in `ls | grep -v .stp | grep -v tapsetdescription | grep -v template` ; -do cp $i $i.tmp ; +sed -i -e 's/\.stp$//g' ../manpageus ; +for i in `cat ../manpageus` ; +do mv $i $i.tmp ; perl -p -i -e 's| \* sfunction|.BR|g' $i.tmp ; perl -p -i -e 's| \* probe|.BR|g' $i.tmp ; perl -p -i -e 's| -|\ninitlinehere|g' $i.tmp ; -perl -p -i -e 's|^initlinehere([^\n]*)\n|\n.br\n$1\n\n.B Arguments:|g' $i.tmp ; -perl -p -i -e 's| \* @([^:]*):|\n.I $1\n.br\n|g' $i.tmp ; -perl -p -i -e 's| \* ([^:]*):|\n.BR $1:\n.br\n|g' $i.tmp ; +perl -p -i -e 's|^initlinehere([^\n]*)\n|$1\n |g' $i.tmp ; +perl -p -i -e 's| \* @([^:]*):|\n.I $1:\n|g' $i.tmp ; +perl -p -i -e 's| \* ([^:]*):|\n.BR $1:\n|g' $i.tmp ; +perl -p -i -e 's| \* ||g' $i.tmp perl -p -i -e 's|\*probestart|\n.P\n.TP|g' $i.tmp ; -perl -p -i -e 's|\.I|\n\n.I|g' $i.tmp ; -# special formatting for Arguments header -perl -p -i -e 's|.B Arguments: \*\/||g' $i.tmp ; -perl -p -i -e 's|.B Arguments: \*|.B Description:|g' $i.tmp ; - -cat $i.tmp | -perl -p -e 'undef $/;s|.B Arguments:\n.B|.B|msg' | -perl -p -e 'undef $/;s|\n\n\n|\n\n|msg' > $i.manpagebody ; +perl -p -i -e 's|\.I|\n.I|g' $i.tmp ; +# remove empty lines +sed -i -e '/^$/d' $i.tmp ; +sed -i -e '/^$/d' $i.tmp ; +sed -i -e 's/^[ \t]*//g' $i.tmp ; +# process Description headers +perl -p -i -e 's|^\*[^/]|\n.BR Description:\n|g' $i.tmp ; +perl -p -i -e 'undef $/;s|\.BR Description:\n\.BR|.BR|g' $i.tmp ; +perl -p -i -e 'undef $/;s|\.BR Description:\n\*\/||g' $i.tmp ; +# process Argument headers +perl -p -i -e 'undef $/;s|\n\n.I|\n.br\n.BR Arguments:\n.I|g' $i.tmp ; +# clean up formatting of arguments +perl -p -i -e 's|^.I([^:]*:)|\n.br\n.br\n.IR$1\n.br\n\t|g' $i.tmp ; done +# make tags work +for i in `cat ../manpageus` ; do +perl -p -i -e 's|]*>([^.])|$1\n|g' $i.tmp ; +perl -p -i -e 's|<[^>]*>|\n.B |g' $i.tmp ; +# the previous two statements create excess empty lines, remove some of them +sed -i -e '/^$/d' $i.tmp ; +# increase whitespace between some headers +perl -p -i -e 's|^\.BR ([^:]*:)|\n.br\n.BR $1\n.br\n|g' $i.tmp +done + # generate footer template -mv ../manpageus . -sed -i -e 's/.stp//g' manpageus echo ".SH SEE ALSO" >> footer echo ".IR stap (1)," >> footer echo ".IR stapprobes (5)," >> footer -for i in `cat manpageus`; do echo ".IR stapprobes."$i" (5)," >> footer ; done +for i in `cat ../manpageus`; do echo ".IR stapprobes."$i" (5)," >> footer ; done # assemble parts -for i in `cat manpageus`; do -cat $i.template >> $i.5 ; -cat $i.manpagebody >> $i.5 ; -cat footer >> $i.5 ; +for i in `cat ../manpageus`; do +cat $i.template >> stapprobes.$i.5 ; +cat $i.tmp >> stapprobes.$i.5 ; +cat footer >> stapprobes.$i.5 ; +# final polish +sed -i -e 's/\*\/$//g' stapprobes.$i.5 ; done # cleanup -for i in `cat manpageus`; do -# context.stp -perl -p -i -e 's|.B Description:/|\n.P\n.TP|g' $i.5 ; -perl -p -i -e 's|.B Description:|.B Description:\n\n |g' $i.5 ; -# convert tags -perl -p -i -e 's|]*>([^.])|$1\n|g' $i.5 ; -perl -p -i -e 's|<[^>]*>|\n.B |g' $i.5 ; -cat $i.5 | -perl -p -e 'undef $/;s|\.B Arguments:\n\n\.B |.B|msg' | -# for tagged commands followed by periods -perl -p -e 'undef $/;s|\n\.B \.|.\n|msg' | -perl -p -e 'undef $/;s|\n \* | |msg' > stapprobes.$i.5.in ; -# cleanup all remaining stars, excess initial whitespace, and trailing "/" per line -perl -p -i -e 's|^ \*||g' stapprobes.$i.5.in; -perl -p -i -e 's|^[ ]*||g' stapprobes.$i.5.in; -perl -p -i -e 's|^/||g' stapprobes.$i.5.in; -# cleanup remaining excess whitespace -perl -p -i -e 's|\t\t| |g' stapprobes.$i.5.in; -perl -p -i -e 's|^ ||g' stapprobes.$i.5.in; -sed -i -e 's/ / /g' stapprobes.$i.5.in; +for i in `ls | grep -v 'stapprobes.*.5'` ; do +rm $i ; done -# file cleanup -rm `ls | grep -v stapprobes` -#mv workingdir final_manpages -# perl -p -i -e 's|||g' stapprobes.$i.5.in ; - -# perl -p -i -e 's|||g' $i.manpagebody -# use to move marked strings. -# sed -n '/\/\/ /,/\/\/ <\/tapsetdescription>/ s/.*/&/w bleh' < ioscheduler -# remove excess initial whitespace for each line -# perl -p -i -e 's|^ ||g' stapprobes.$i.5.in; -# convert tags -# perl -p -i -e 's|]*>|\n|g' stapprobes.$i.5.in ; -# perl -p -i -e 's|<[^>]*>|\n.B |g' stapprobes.$i.5.in ; \ No newline at end of file +rm ../manpageus ; +cd .. +mv workingdir man_pages +echo " " +echo "Finished! man pages generated in ./man_pages." +echo " " \ No newline at end of file -- cgit From 8391565d6f48a6fea6f5ea29dcc8790125039278 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Wed, 18 Mar 2009 15:29:19 +1000 Subject: minor edits --- tapset/signal.stp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tapset/signal.stp b/tapset/signal.stp index 711ee70f..e8470a9c 100644 --- a/tapset/signal.stp +++ b/tapset/signal.stp @@ -31,7 +31,7 @@ * @send2queue: Indicates whether the signal is sent to an existing * sigqueue * @name: The name of the function used to send out the signal - * + * * Context: * The signal's sender. * @@ -124,10 +124,10 @@ probe _signal.send.part3 = kernel.function("send_sigqueue") * @send2queue: Indicates whether the sent signal was sent to an * existing sigqueue * @name: The name of the function used to send out the signal - * + * * Context: * The signal's sender. (correct?) - * + * * Possible __group_send_sig_info and * specific_send_sig_info return values are as follows; * @@ -139,19 +139,18 @@ probe _signal.send.part3 = kernel.function("send_sigqueue") * * -EAGAIN -- The sigqueue of the receiving process is * overflowing, the signal was RT, and the signal was sent by a user using something other - * than kill() - * + * than kill(). + * * Possible send_group_sigqueue and * send_sigqueue return values are as follows; - * + * * 0 -- The signal was either sucessfully added into the * sigqueue of the receiving process, or a SI_TIMER entry is already * queued (in which case, the overrun count will be simply incremented). * * 1 -- The signal was ignored by the receiving process. * - * - * -1 - (send_sigqueue only) The task was marked + * -1 -- (send_sigqueue only) The task was marked * exiting, allowing * posix_timer_event to redirect it to the group * leader. * -- cgit From 715bb1ea4a7823580a4f6641c5a03d66735b57a1 Mon Sep 17 00:00:00 2001 From: ddomingo Date: Wed, 18 Mar 2009 15:45:23 +1000 Subject: minor edit --- doc/Tapset_Reference_Guide/manpager.sh | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/doc/Tapset_Reference_Guide/manpager.sh b/doc/Tapset_Reference_Guide/manpager.sh index 6c2d204e..0051d208 100644 --- a/doc/Tapset_Reference_Guide/manpager.sh +++ b/doc/Tapset_Reference_Guide/manpager.sh @@ -8,7 +8,7 @@ rm -rf man_pages # create working directory mkdir workingdir ; -# create list of man pages to generate; should be in sync with Tapset Reference Guide +# create list of man pages to generate cat ../SystemTap_Tapset_Reference/tapsets.tmpl | grep ^\!Itapset > manpageus ; sed -i -e 's/\!Itapset\///g' manpageus ; @@ -49,7 +49,6 @@ echo " " >> $i.template ; echo ".SH DESCRIPTION" >> $i.template ; cat $i.stp.tapsetdescription >> $i.template ; echo " " >> $i.template ; -#echo " " >> $i.template ; echo ".SH PROBES" >> $i.template ; echo ".br" >> $i.template ; echo ".P" >> $i.template ; -- cgit From bc1a99dfcf9cd081ddf37f362dc1af2158c016b8 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 18 Mar 2009 11:42:53 +0100 Subject: Don't mutex_unlock in __stp_tf_get_vma_map_entry_internal. All callers of __stp_tf_get_vma_map_entry_internal lock and unlock the mutex correctly themselves in all cases. This unlock would trigger a double unlock. * runtime/task_finder_vma.c (__stp_tf_get_vma_map_entry_internal): Don't mutex_unlock(&__stp_tf_vma_mutex). --- runtime/task_finder_vma.c | 1 - 1 file changed, 1 deletion(-) diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c index 87a32fe5..83b206e5 100644 --- a/runtime/task_finder_vma.c +++ b/runtime/task_finder_vma.c @@ -203,7 +203,6 @@ __stp_tf_get_vma_map_entry_internal(struct task_struct *tsk, hlist_for_each_entry(entry, node, head, hlist) { if (tsk->pid == entry->pid && vm_start == entry->addr) { - mutex_unlock(&__stp_tf_vma_mutex); return entry; } } -- cgit From c32faac1fd0249ddd6265cf80c07a24e06d9aa0f Mon Sep 17 00:00:00 2001 From: Maynard Johnson Date: Wed, 18 Mar 2009 12:59:33 -0500 Subject: Fix for spinlock bad magic error with itrace probe point --- runtime/itrace.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/runtime/itrace.c b/runtime/itrace.c index ed32b0bc..da874f63 100644 --- a/runtime/itrace.c +++ b/runtime/itrace.c @@ -275,6 +275,7 @@ static int usr_itrace_init(int single_step, pid_t tid, struct stap_itrace_probe struct itrace_info *ui; struct task_struct *tsk; + spin_lock_init(&itrace_lock); rcu_read_lock(); tsk = find_task_by_vpid(tid); if (!tsk) { @@ -293,11 +294,6 @@ static int usr_itrace_init(int single_step, pid_t tid, struct stap_itrace_probe put_task_struct(tsk); rcu_read_unlock(); - spin_lock_init(&itrace_lock); - - /* set initial state */ - spin_lock(&itrace_lock); - spin_unlock(&itrace_lock); printk(KERN_INFO "usr_itrace_init: completed for tid = %d\n", tid); return 0; @@ -314,7 +310,6 @@ void static remove_usr_itrace_info(struct itrace_info *ui) if (debug) printk(KERN_INFO "remove_usr_itrace_info: tid=%d\n", ui->tid); - spin_lock(&itrace_lock); if (ui->tsk && ui->engine) { status = utrace_control(ui->tsk, ui->engine, UTRACE_DETACH); if (status < 0 && status != -ESRCH && status != -EALREADY) @@ -322,6 +317,7 @@ void static remove_usr_itrace_info(struct itrace_info *ui) "utrace_control(UTRACE_DETACH) returns %d\n", status); } + spin_lock(&itrace_lock); list_del(&ui->link); spin_unlock(&itrace_lock); kfree(ui); -- cgit From bd1b2d37ccaa09c2516a2874f2eba90a2c61c432 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Wed, 18 Mar 2009 14:47:36 -0400 Subject: Make manpager.sh executable. --- doc/Tapset_Reference_Guide/manpager.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 doc/Tapset_Reference_Guide/manpager.sh diff --git a/doc/Tapset_Reference_Guide/manpager.sh b/doc/Tapset_Reference_Guide/manpager.sh old mode 100644 new mode 100755 -- cgit From cd3891cba6326df5ecfe4067f80e86390c759303 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Wed, 18 Mar 2009 16:19:33 -0400 Subject: Put man pages from tapset in 3stap (PR9870). --- Makefile.in | 1 + doc/Makefile.in | 1 + doc/SystemTap_Tapset_Reference/Makefile.am | 6 +++--- doc/SystemTap_Tapset_Reference/Makefile.in | 7 ++++--- scripts/kernel-doc | 4 ++-- 5 files changed, 11 insertions(+), 8 deletions(-) diff --git a/Makefile.in b/Makefile.in index 73ef5bac..12a5e6ea 100644 --- a/Makefile.in +++ b/Makefile.in @@ -288,6 +288,7 @@ staplog_CPPFLAGS = @staplog_CPPFLAGS@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ diff --git a/doc/Makefile.in b/doc/Makefile.in index 93753666..e23a6699 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -163,6 +163,7 @@ staplog_CPPFLAGS = @staplog_CPPFLAGS@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ PDF_FILES = tutorial.pdf langref.pdf diff --git a/doc/SystemTap_Tapset_Reference/Makefile.am b/doc/SystemTap_Tapset_Reference/Makefile.am index 9e7d2069..68dfd971 100644 --- a/doc/SystemTap_Tapset_Reference/Makefile.am +++ b/doc/SystemTap_Tapset_Reference/Makefile.am @@ -2,7 +2,7 @@ ## process this file with automake to produce Makefile.in DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap -MAN_INSTALL_DIR = $(DESTDIR)$(mandir)/man5 +MAN_INSTALL_DIR = $(DESTDIR)$(mandir)/man3stap HTML_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap/tapsets @@ -36,7 +36,7 @@ tapsets.pdf: tapsets.xml xmlto pdf tapsets.xml stamp-mandocs: tapsets.xml - xmlto man -o man5 tapsets.xml + xmlto man -o man3stap tapsets.xml touch stamp-mandocs #FIXME need to figure out where to install things appropriately @@ -45,7 +45,7 @@ install-data-hook: $(MKDIR_P) $(DOC_INSTALL_DIR) $(INSTALL_DATA) tapsets.pdf $(DOC_INSTALL_DIR) $(MKDIR_P) $(MAN_INSTALL_DIR) - $(INSTALL_DATA) man5/* $(MAN_INSTALL_DIR) + $(INSTALL_DATA) man3stap/* $(MAN_INSTALL_DIR) $(MKDIR_P) $(HTML_INSTALL_DIR) $(INSTALL_DATA) tapsets/* $(HTML_INSTALL_DIR) endif diff --git a/doc/SystemTap_Tapset_Reference/Makefile.in b/doc/SystemTap_Tapset_Reference/Makefile.in index 84d2114c..2f8a5294 100644 --- a/doc/SystemTap_Tapset_Reference/Makefile.in +++ b/doc/SystemTap_Tapset_Reference/Makefile.in @@ -166,10 +166,11 @@ staplog_CPPFLAGS = @staplog_CPPFLAGS@ subdirs = @subdirs@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ DOC_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap -MAN_INSTALL_DIR = $(DESTDIR)$(mandir)/man5 +MAN_INSTALL_DIR = $(DESTDIR)$(mandir)/man3stap HTML_INSTALL_DIR = $(DESTDIR)$(datadir)/doc/systemtap/tapsets SRCTREE = $(abs_top_srcdir)/ DOCPROC = $(abs_builddir)/docproc @@ -429,7 +430,7 @@ uninstall-am: @BUILD_REFDOCS_TRUE@ xmlto pdf tapsets.xml @BUILD_REFDOCS_TRUE@stamp-mandocs: tapsets.xml -@BUILD_REFDOCS_TRUE@ xmlto man -o man5 tapsets.xml +@BUILD_REFDOCS_TRUE@ xmlto man -o man3stap tapsets.xml @BUILD_REFDOCS_TRUE@ touch stamp-mandocs #FIXME need to figure out where to install things appropriately @@ -438,7 +439,7 @@ uninstall-am: @BUILD_REFDOCS_TRUE@ $(MKDIR_P) $(DOC_INSTALL_DIR) @BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) tapsets.pdf $(DOC_INSTALL_DIR) @BUILD_REFDOCS_TRUE@ $(MKDIR_P) $(MAN_INSTALL_DIR) -@BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) man5/* $(MAN_INSTALL_DIR) +@BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) man3stap/* $(MAN_INSTALL_DIR) @BUILD_REFDOCS_TRUE@ $(MKDIR_P) $(HTML_INSTALL_DIR) @BUILD_REFDOCS_TRUE@ $(INSTALL_DATA) tapsets/* $(HTML_INSTALL_DIR) # Tell versions [3.59,3.63) of GNU make to not export all variables. diff --git a/scripts/kernel-doc b/scripts/kernel-doc index add4ba3c..9947882d 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -981,7 +981,7 @@ sub output_probe_xml(%) { print "\n"; print "\n"; print " ".$args{'probe'}."\n"; - print " 5\n"; + print " 3stap\n"; # print " " . $kernelversion . "\n"; print "\n"; print "\n"; @@ -1039,7 +1039,7 @@ sub output_sfunction_xml(%) { print "\n"; print "\n"; print " ".$args{'sfunction'}."\n"; - print " 5\n"; + print " 3stap\n"; # print " " . $kernelversion . "\n"; print "\n"; print "\n"; -- cgit From fab6ce30772ec0c45f7d5e295a6e09c95971e9f5 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Wed, 18 Mar 2009 16:56:07 -0400 Subject: Adjust systemtap.spec to include the relocated man pages (PR980). --- systemtap.spec | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/systemtap.spec b/systemtap.spec index 7277f92a..ad1889c7 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -1,4 +1,4 @@ -%{!?release: %define release 1} +%{!?release: %define release 2} %{!?with_sqlite: %define with_sqlite 1} %{!?with_docs: %define with_docs 1} %{!?with_crash: %define with_crash 0} @@ -252,6 +252,7 @@ exit 0 %{_bindir}/stap-report %{_mandir}/man1/* %{_mandir}/man5/* +%{_mandir}/man3stap/* %dir %{_datadir}/%{name} %{_datadir}/%{name}/runtime @@ -317,6 +318,9 @@ exit 0 %changelog +* Wed Mar 18 2009 Will Cohen - 0.9-2 +- Add location of man pages. + * Tue Feb 17 2009 Frank Ch. Eigler - 0.9-1 - Upstream release. -- cgit From 8df306c4443bd9dd1397bab6cba7f61cb2d88af9 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 18 Mar 2009 18:51:17 -0700 Subject: Support tracepoints with no arguments LTTng has a few tracepoints without any arguments, which caused our compile to fail, claiming that our entry function was not a declaration. This just adds an explicit (void) argument list for that case. --- tapsets.cxx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tapsets.cxx b/tapsets.cxx index 2f940b29..2548625b 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -9739,6 +9739,8 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s) // don't provide any sort of context pointer. s.op->newline() << "#include <" << p->header << ">"; s.op->newline() << "static void enter_tracepoint_probe_" << i << "("; + if (p->args.size() == 0) + s.op->line() << "void"; for (unsigned j = 0; j < p->args.size(); ++j) { if (j > 0) -- cgit From 219e62c7eeca850d2898fdbfb6b74719195274a6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 18 Mar 2009 19:04:54 -0700 Subject: PR9959: improve tracepoint arg type-naming dwarf_type_name now works with more argument types. There were three cases that I needed to improve: - For "const struct foo*", the debuginfo has a const-DIE named "foo" chained to a struct-DIE named "foo", so we can't assume that seeing a name means we're down to the base type. The recursion now decends until it explicitly sees a base_type, typedef, struct, or union. - For "void*", the debuginfo has a pointer-DIE without any DW_AT_type after. Now I'm just catching that failed lookup and writing in "void". - For "va_list", the debuginfo actually resolves to an internal type "struct __va_list_tag*", but that struct has no declaration at the source level. I'm just hacking that exact case to say "va_list" instead, but it would be nice to find something cleaner... We'll probably still have problems if any tracepoint uses a function- pointer argument, but so far I've only seen that as a "void*", which we now handle ok. --- tapsets.cxx | 40 ++++++++++++++++++++++++++-------------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index 2548625b..a4da7811 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -9586,32 +9586,39 @@ tracepoint_derived_probe::tracepoint_derived_probe (systemtap_session& s, static bool dwarf_type_name(Dwarf_Die& type_die, string& c_type) { - // if this die has a direct name, then we're done - const char *diename = dwarf_diename_integrate(&type_die); - if (diename != NULL) + // if we've gotten down to a basic type, then we're done + bool done = true; + switch (dwarf_tag(&type_die)) { - switch (dwarf_tag(&type_die)) - { - case DW_TAG_structure_type: - c_type.append("struct "); - break; - case DW_TAG_union_type: - c_type.append("union "); - break; - } - c_type.append(diename); + case DW_TAG_structure_type: + c_type.append("struct "); + break; + case DW_TAG_union_type: + c_type.append("union "); + break; + case DW_TAG_typedef: + case DW_TAG_base_type: + break; + default: + done = false; + break; + } + if (done) + { + c_type.append(dwarf_diename_integrate(&type_die)); return true; } // otherwise, this die is a type modifier. // recurse into the referent type + // if it can't be named, just call it "void" Dwarf_Attribute subtype_attr; Dwarf_Die subtype_die; if (!dwarf_attr_integrate(&type_die, DW_AT_type, &subtype_attr) || !dwarf_formref_die(&subtype_attr, &subtype_die) || !dwarf_type_name(subtype_die, c_type)) - return false; + c_type = "void"; const char *suffix = NULL; switch (dwarf_tag(&type_die)) @@ -9632,6 +9639,11 @@ dwarf_type_name(Dwarf_Die& type_die, string& c_type) return false; } c_type.append(suffix); + + // XXX HACK! The va_list isn't usable as found in the debuginfo... + if (c_type == "struct __va_list_tag*") + c_type = "va_list"; + return true; } -- cgit From dcaa1a657cef72dec518f7376b5d856ef8f01076 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 18 Mar 2009 20:05:56 -0700 Subject: PR9959: hide tracepoint arguments of unknown type We always have to know the type name of tracepoint arguments, so we can declare the right function callback, but we can suppress access to those types which we don't (yet) know how to read. --- tapsets.cxx | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index a4da7811..42be4556 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -9231,9 +9231,9 @@ mark_builder::build(systemtap_session & sess, struct tracepoint_arg { string name, c_type; - bool used, isptr; + bool usable, used, isptr; Dwarf_Die type_die; - tracepoint_arg(): used(false), isptr(false) {} + tracepoint_arg(): usable(false), used(false), isptr(false) {} }; struct tracepoint_derived_probe: public derived_probe @@ -9285,7 +9285,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) // search for a tracepoint parameter matching this name tracepoint_arg *arg = NULL; for (unsigned i = 0; i < args.size(); ++i) - if (args[i].name == argname) + if (args[i].usable && args[i].name == argname) { arg = &args[i]; arg->used = true; @@ -9504,6 +9504,8 @@ tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) for (unsigned i = 0; i < args.size(); ++i) { + if (!args[i].usable) + continue; if (i > 0) pf->raw_components += " "; pf->raw_components += args[i].name; @@ -9649,28 +9651,29 @@ dwarf_type_name(Dwarf_Die& type_die, string& c_type) static bool -resolve_tracepoint_arg_type(Dwarf_Die& type_die, bool& isptr) +resolve_tracepoint_arg_type(tracepoint_arg& arg) { Dwarf_Attribute type_attr; - switch (dwarf_tag(&type_die)) + switch (dwarf_tag(&arg.type_die)) { case DW_TAG_typedef: case DW_TAG_const_type: case DW_TAG_volatile_type: // iterate on the referent type - return (dwarf_attr_integrate(&type_die, DW_AT_type, &type_attr) - && dwarf_formref_die(&type_attr, &type_die) - && resolve_tracepoint_arg_type(type_die, isptr)); + return (dwarf_attr_integrate(&arg.type_die, DW_AT_type, &type_attr) + && dwarf_formref_die(&type_attr, &arg.type_die) + && resolve_tracepoint_arg_type(arg)); case DW_TAG_base_type: // base types will simply be treated as script longs - isptr = false; + arg.isptr = false; return true; case DW_TAG_pointer_type: - // pointers can be either script longs, - // or dereferenced with their referent type - isptr = true; - return (dwarf_attr_integrate(&type_die, DW_AT_type, &type_attr) - && dwarf_formref_die(&type_attr, &type_die)); + // pointers can be treated as script longs, + // and if we know their type, they can also be dereferenced + if (dwarf_attr_integrate(&arg.type_die, DW_AT_type, &type_attr) + && dwarf_formref_die(&type_attr, &arg.type_die)) + arg.isptr = true; + return true; default: // should we consider other types too? return false; @@ -9694,12 +9697,12 @@ tracepoint_derived_probe::build_args(dwflpp& dw, Dwarf_Die& func_die) Dwarf_Attribute type_attr; if (!dwarf_attr_integrate (&arg, DW_AT_type, &type_attr) || !dwarf_formref_die (&type_attr, &tparg.type_die) - || !dwarf_type_name(tparg.type_die, tparg.c_type) - || !resolve_tracepoint_arg_type(tparg.type_die, tparg.isptr)) + || !dwarf_type_name(tparg.type_die, tparg.c_type)) throw semantic_error ("cannot get type of tracepoint '" + tracepoint_name + "' parameter '" + tparg.name + "'"); + tparg.usable = resolve_tracepoint_arg_type(tparg); args.push_back(tparg); if (sess.verbose > 4) clog << "found parameter for tracepoint '" << tracepoint_name @@ -9712,8 +9715,9 @@ tracepoint_derived_probe::build_args(dwflpp& dw, Dwarf_Die& func_die) void tracepoint_derived_probe::printargs(std::ostream &o) const { - for (unsigned i = 0; i < args.size(); ++i) - o << " $" << args[i].name << ":" << args[i].c_type; + for (unsigned i = 0; i < args.size(); ++i) + if (args[i].usable) + o << " $" << args[i].name << ":" << args[i].c_type; } void -- cgit From a1e3976f68658d0cf985449e0e67c960b398e7e5 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Thu, 19 Mar 2009 10:38:33 -0400 Subject: Only include man3stap pages if documentation built. --- systemtap.spec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/systemtap.spec b/systemtap.spec index ad1889c7..4eca3451 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -246,13 +246,13 @@ exit 0 %if %{with_docs} %doc docs.installed/*.pdf %doc docs.installed/tapsets +%{_mandir}/man3stap/* %endif %{_bindir}/stap %{_bindir}/stap-report %{_mandir}/man1/* %{_mandir}/man5/* -%{_mandir}/man3stap/* %dir %{_datadir}/%{name} %{_datadir}/%{name}/runtime -- cgit From 601915ab6aebff06bfc830be3b0f69976a486d9d Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Thu, 19 Mar 2009 11:27:19 -0400 Subject: add runtime/autoconf magic for itrace on pre-find_task_by_vpid kernels --- buildrun.cxx | 1 + runtime/autoconf-find-task-pid.c | 6 ++++++ 2 files changed, 7 insertions(+) create mode 100644 runtime/autoconf-find-task-pid.c diff --git a/buildrun.cxx b/buildrun.cxx index b9d648ef..0e9e0e17 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -148,6 +148,7 @@ compile_pass (systemtap_session& s) output_autoconf(s, o, "autoconf-vm-area.c", "STAPCONF_VM_AREA", NULL); output_autoconf(s, o, "autoconf-procfs-owner.c", "STAPCONF_PROCFS_OWNER", NULL); output_autoconf(s, o, "autoconf-alloc-percpu-align.c", "STAPCONF_ALLOC_PERCPU_ALIGN", NULL); + output_autoconf(s, o, "autoconf-find-task-pid.c", "STAPCONF_FIND_TASK_PID", NULL); #if 0 /* NB: For now, the performance hit of probe_kernel_read/write (vs. our diff --git a/runtime/autoconf-find-task-pid.c b/runtime/autoconf-find-task-pid.c new file mode 100644 index 00000000..549d5ac3 --- /dev/null +++ b/runtime/autoconf-find-task-pid.c @@ -0,0 +1,6 @@ +#include + +void foo (pid_t k) { + struct task_struct *tsk = find_task_by_pid (k); + (void) tsk; +} -- cgit From da049631393c37bad502ffac08a3805778c8d60d Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Thu, 19 Mar 2009 11:28:04 -0400 Subject: start of rhel5 compatibility for itrace --- runtime/itrace.c | 42 +++++++++++++++++++++++++++++++++++++++++- runtime/utrace_compatibility.h | 9 ++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/runtime/itrace.c b/runtime/itrace.c index da874f63..3d9ded2f 100644 --- a/runtime/itrace.c +++ b/runtime/itrace.c @@ -1,6 +1,7 @@ /* * user space instruction tracing * Copyright (C) 2005, 2006, 2007, 2008, 2009 IBM Corp. + * Copyright (C) 2009 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General @@ -19,6 +20,7 @@ #include #include #include "uprobes/uprobes.h" +#include "utrace_compatibility.h" #ifndef put_task_struct #define put_task_struct(t) \ @@ -55,7 +57,7 @@ struct itrace_info { struct list_head link; }; -static u32 debug = 1; +static u32 debug = 0 /* 1 */; static LIST_HEAD(usr_itrace_info); static spinlock_t itrace_lock; @@ -118,10 +120,15 @@ static int __access_process_vm(struct task_struct *tsk, unsigned long addr, void return buf - old_buf; } +#ifdef UTRACE_ORIG_VERSION +static u32 usr_itrace_report_quiesce(struct utrace_attached_engine *engine, + struct task_struct *tsk) +#else static u32 usr_itrace_report_quiesce(enum utrace_resume_action action, struct utrace_attached_engine *engine, struct task_struct *tsk, unsigned long event) +#endif { int status; struct itrace_info *ui; @@ -129,10 +136,23 @@ static u32 usr_itrace_report_quiesce(enum utrace_resume_action action, ui = rcu_dereference(engine->data); WARN_ON(!ui); +#ifdef UTRACE_ORIG_VERSION + return (ui->step_flag); // XXX XXX XXX +#else return (event == 0 ? ui->step_flag : UTRACE_RESUME); +#endif } +#ifdef UTRACE_ORIG_VERSION +static u32 usr_itrace_report_signal( + struct utrace_attached_engine *engine, + struct task_struct *tsk, + struct pt_regs *regs, + u32 action, siginfo_t *info, + const struct k_sigaction *orig_ka, + struct k_sigaction *return_ka) +#else static u32 usr_itrace_report_signal(u32 action, struct utrace_attached_engine *engine, struct task_struct *tsk, @@ -140,6 +160,7 @@ static u32 usr_itrace_report_signal(u32 action, siginfo_t *info, const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) +#endif { struct itrace_info *ui; u32 return_flags; @@ -174,16 +195,31 @@ static u32 usr_itrace_report_signal(u32 action, return return_flags; } + + +#ifdef UTRACE_ORIG_VERSION +static u32 usr_itrace_report_clone( + struct utrace_attached_engine *engine, + struct task_struct *parent, + unsigned long clone_flags, + struct task_struct *child) +#else static u32 usr_itrace_report_clone(enum utrace_resume_action action, struct utrace_attached_engine *engine, struct task_struct *parent, unsigned long clone_flags, struct task_struct *child) +#endif { return UTRACE_RESUME; } +#ifdef UTRACE_ORIG_VERSION +static u32 usr_itrace_report_death(struct utrace_attached_engine *e, + struct task_struct *tsk) +#else static u32 usr_itrace_report_death(struct utrace_attached_engine *e, struct task_struct *tsk, bool group_dead, int signal) +#endif { struct itrace_info *ui = rcu_dereference(e->data); WARN_ON(!ui); @@ -277,7 +313,11 @@ static int usr_itrace_init(int single_step, pid_t tid, struct stap_itrace_probe spin_lock_init(&itrace_lock); rcu_read_lock(); +#ifdef STAPCONF_FIND_TASK_PID + tsk = find_task_by_pid(tid); +#else tsk = find_task_by_vpid(tid); +#endif if (!tsk) { printk(KERN_ERR "usr_itrace_init: Cannot find process %d\n", tid); rcu_read_unlock(); diff --git a/runtime/utrace_compatibility.h b/runtime/utrace_compatibility.h index 00b841d2..4a70da42 100644 --- a/runtime/utrace_compatibility.h +++ b/runtime/utrace_compatibility.h @@ -1,6 +1,6 @@ /* * utrace compatibility defines and inlines - * Copyright (C) 2008 Red Hat Inc. + * Copyright (C) 2008-2009 Red Hat Inc. * * This file is part of systemtap, and is free software. You can * redistribute it and/or modify it under the terms of the GNU General @@ -28,6 +28,8 @@ enum utrace_resume_action { UTRACE_STOP = UTRACE_ACTION_QUIESCE, UTRACE_RESUME = UTRACE_ACTION_RESUME, UTRACE_DETACH = UTRACE_ACTION_DETACH, + UTRACE_SINGLESTEP = UTRACE_ACTION_SINGLESTEP, + UTRACE_BLOCKSTEP = UTRACE_ACTION_BLOCKSTEP, }; static inline struct utrace_attached_engine * @@ -48,6 +50,11 @@ utrace_control(struct task_struct *target, case UTRACE_STOP: return utrace_set_flags(target, engine, (engine->flags | UTRACE_ACTION_QUIESCE)); + case UTRACE_SINGLESTEP: + case UTRACE_BLOCKSTEP: + return utrace_set_flags(target, engine, + engine->flags | action); + default: return -EINVAL; } -- cgit From 0afb7073fa08980ecf9a80018d18a5148c2f686e Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Thu, 19 Mar 2009 11:32:48 -0400 Subject: rename process().itrace -> process().insn introduce process().insn.block --- stapprobes.5.in | 13 +++++++++---- tapsets.cxx | 13 ++++++++++--- testsuite/systemtap.base/itrace.exp | 7 ++----- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/stapprobes.5.in b/stapprobes.5.in index 70d045c4..f4a872cb 100644 --- a/stapprobes.5.in +++ b/stapprobes.5.in @@ -407,8 +407,10 @@ process.syscall process(PID).syscall.return process("PATH").syscall.return process.syscall.return -process(PID).itrace -process("PATH").itrace +process(PID).insn +process("PATH").insn +process(PID).insn.block +process("PATH").insn.block process("PATH").mark("LABEL") .ESAMPLE .PP @@ -443,8 +445,11 @@ in the .BR $return context variable. A -.B .itrace -probe gets called for every single step of the process described by PID or PATH. +.B .insn +probe gets called for every single-stepped instruction of the process described by PID or PATH. +A +.B .insn.block +probe gets called for every block-stepped instruction of the process described by PID or PATH. A .B .mark probe gets called via a static probe which is defined in the diff --git a/tapsets.cxx b/tapsets.cxx index 42be4556..894a7447 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6240,6 +6240,9 @@ task_finder_derived_probe_group::emit_module_exit (systemtap_session& s) // ------------------------------------------------------------------------ +static string TOK_INSN("insn"); +static string TOK_BLOCK("block"); + struct itrace_derived_probe: public derived_probe { bool has_path; @@ -6314,7 +6317,7 @@ struct itrace_builder: public derived_probe_builder // XXX: PR 6445 needs !has_path && !has_pid support assert (has_path || has_pid); - single_step = 1; + single_step = ! has_null_param (parameters, TOK_BLOCK); // If we have a path, we need to validate it. if (has_path) @@ -10791,9 +10794,13 @@ register_standard_tapsets(systemtap_session & s) ->bind(new utrace_builder ()); // itrace user-space probes - s.pattern_root->bind_str(TOK_PROCESS)->bind("itrace") + s.pattern_root->bind_str(TOK_PROCESS)->bind(TOK_INSN) + ->bind(new itrace_builder ()); + s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_INSN) + ->bind(new itrace_builder ()); + s.pattern_root->bind_str(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK) ->bind(new itrace_builder ()); - s.pattern_root->bind_num(TOK_PROCESS)->bind("itrace") + s.pattern_root->bind_num(TOK_PROCESS)->bind(TOK_INSN)->bind(TOK_BLOCK) ->bind(new itrace_builder ()); // marker-based parts diff --git a/testsuite/systemtap.base/itrace.exp b/testsuite/systemtap.base/itrace.exp index f19af977..e215bfe7 100644 --- a/testsuite/systemtap.base/itrace.exp +++ b/testsuite/systemtap.base/itrace.exp @@ -1,8 +1,5 @@ # itrace test -# temporarily disabled -return - # Initialize variables set utrace_support_found 0 @@ -11,7 +8,7 @@ set exepath "[pwd]/ls_[pid]" set itrace1_script { global instrs = 0 probe begin { printf("systemtap starting probe\n") } - probe process("%s").itrace + probe process("%s").insn { instrs += 1 if (instrs == 5) @@ -28,7 +25,7 @@ set itrace1_script_output "itraced = 5\r\n" set itrace2_script { global instrs = 0, itrace_on = 0, start_timer = 0 probe begin { start_timer = 1; printf("systemtap starting probe\n") } - probe process("%s").itrace if (itrace_on) + probe process("%s").insn if (itrace_on) { instrs += 1 if (instrs == 5) -- cgit From 59b30bda24855bc46608a126efad8e150196721c Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Thu, 19 Mar 2009 12:31:54 -0400 Subject: BZ490802, remove bumpspec-unfriendly %{release} macro logic --- systemtap.spec | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/systemtap.spec b/systemtap.spec index 4eca3451..540a9d93 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -1,4 +1,3 @@ -%{!?release: %define release 2} %{!?with_sqlite: %define with_sqlite 1} %{!?with_docs: %define with_docs 1} %{!?with_crash: %define with_crash 0} @@ -6,9 +5,9 @@ %{!?elfutils_version: %define elfutils_version 0.127} Name: systemtap -# for version, see also configure.ac Version: 0.9 -Release: %{release}%{?dist} +Release: 3%{?dist} +# for version, see also configure.ac Summary: Instrumentation System Group: Development/System License: GPLv2+ -- cgit From e2ae0696f7b8cbbafad87a8739c0cc450f7ee887 Mon Sep 17 00:00:00 2001 From: Lubomir Rintel Date: Thu, 19 Mar 2009 13:02:19 -0400 Subject: Disable kprobe blacklist in guru mode. --- NEWS | 5 +++++ tapsets.cxx | 14 +++++++++++--- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index 74fd1df5..fff8afc9 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,10 @@ * What's new +- In guru mode (-g), the kernel probing blacklist is disabled, leaving + only a subset - the kernel's own internal kprobe blacklist - to attempt + to filter out areas unsafe to probe. The differences may be enough to + probe more interrupt handlers. + - Variables unavailable in current context may be skipped by setting a session level flag with command line option --skip-badvars now available. This will simply substitute the otherwise error causing variable with a diff --git a/tapsets.cxx b/tapsets.cxx index 894a7447..6de6271b 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -3521,9 +3521,17 @@ dwarf_query::blacklisted_p(const string& funcname, if (! (goodfn && goodfile)) { - if (sess.verbose>1) - clog << " skipping - blacklisted"; - return true; + if (sess.guru_mode) + { + if (sess.verbose>1) + clog << " guru mode enabled - ignoring blacklist"; + } + else + { + if (sess.verbose>1) + clog << " skipping - blacklisted"; + return true; + } } // This probe point is not blacklisted. -- cgit From d0cd971e70eba3781a95862223d1f7d45e2f5135 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 19 Mar 2009 22:22:25 +0100 Subject: Throw type into semantic_error message of @cast when not found. * tapsets.cxx (dwarf_cast_expanding_visitor::visit_cast_op): Add type to msg added to semantic_error when thrown. --- tapsets.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tapsets.cxx b/tapsets.cxx index 6de6271b..103c39fa 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -5067,7 +5067,8 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e) // cast_op to the next pass. We hope that this value ends // up not being referenced after all, so it can be optimized out // quietly. - semantic_error* er = new semantic_error ("type definition not found", e->tok); + string msg = "type definition '" + e->type + "' not found"; + semantic_error* er = new semantic_error (msg, e->tok); // NB: we can have multiple errors, since a @cast // may be expanded in several different contexts: // function ("*") { @cast(...) } -- cgit From c15b608343c5a0de8558b31650ed001177fb3892 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 19 Mar 2009 22:59:57 +0100 Subject: Allow @cast on "struct " and "union " (by ignoring them). * parse.cxx (parser::parse_symbol): Strip off "struct " or "union " from cop->type. --- parse.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/parse.cxx b/parse.cxx index ac7e652c..a26d594c 100644 --- a/parse.cxx +++ b/parse.cxx @@ -2341,6 +2341,12 @@ parser::parse_symbol () cop->operand = parse_expression (); expect_op(","); expect_unknown(tok_string, cop->type); + // types never start with "struct" or "union", + // so gobble it up. + if (cop->type.compare(0, 7, "struct ") == 0) + cop->type = cop->type.substr(7); + if (cop->type.compare(0, 6, "union ") == 0) + cop->type = cop->type.substr(6); if (peek_op (",")) { next(); -- cgit From ad370dccd460ebfc66f21d3d16f44807d789484f Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 19 Mar 2009 16:23:02 -0700 Subject: PR9960: support tracepoint struct/union value arg If a tracepoint arg is a structure or union that is passed by value, then this takes the address of the parameter so it can be used like a pointer in the rest of our code. --- tapsets.cxx | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index 103c39fa..a8653d8a 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -9242,7 +9242,7 @@ mark_builder::build(systemtap_session & sess, struct tracepoint_arg { - string name, c_type; + string name, c_type, typecast; bool usable, used, isptr; Dwarf_Die type_die; tracepoint_arg(): usable(false), used(false), isptr(false) {} @@ -9345,6 +9345,9 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) if (lvalue && (!dw.sess.guru_mode || e->components.empty())) throw semantic_error("write to tracepoint variable '" + e->base_name + "' not permitted", e->tok); + // XXX: if a struct/union arg is passed by value, then writing to its fields + // is also meaningless until you dereference past a pointer member. It's + // harder to detect and prevent that though... if (e->components.empty()) { @@ -9685,6 +9688,14 @@ resolve_tracepoint_arg_type(tracepoint_arg& arg) if (dwarf_attr_integrate(&arg.type_die, DW_AT_type, &type_attr) && dwarf_formref_die(&type_attr, &arg.type_die)) arg.isptr = true; + arg.typecast = "(intptr_t)"; + return true; + case DW_TAG_structure_type: + case DW_TAG_union_type: + // for structs/unions which are passed by value, we turn it into + // a pointer that can be dereferenced. + arg.isptr = true; + arg.typecast = "(intptr_t)&"; return true; default: // should we consider other types too? @@ -9787,8 +9798,7 @@ tracepoint_derived_probe_group::emit_module_decls (systemtap_session& s) { s.op->newline() << "c->locals[0]." << p->name << ".__tracepoint_arg_" << p->args[j].name << " = (int64_t)"; - if (p->args[j].isptr) - s.op->line() << "(intptr_t)"; + s.op->line() << p->args[j].typecast; s.op->line() << "__tracepoint_arg_" << p->args[j].name << ";"; } s.op->newline() << p->name << " (c);"; -- cgit From d2bb12d37037345a77e90aa83512075d78ae968f Mon Sep 17 00:00:00 2001 From: Wenji Huang Date: Wed, 18 Mar 2009 11:17:25 -0400 Subject: PR9940: avoid duplicated calling of uprobes in shared libraries Add map_p argument to __stp_call_vm_callbacks_with_vma to well tune the vma callback. Signed-off-by: Wenji Huang --- runtime/task_finder.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/runtime/task_finder.c b/runtime/task_finder.c index 38f9145d..2b408763 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -1026,6 +1026,7 @@ __stp_utrace_task_finder_target_syscall_entry(enum utrace_resume_action action, static void __stp_call_vm_callbacks_with_vma(struct stap_task_finder_target *tgt, struct task_struct *tsk, + int map_p, struct vm_area_struct *vma) { char *mmpath_buf; @@ -1052,7 +1053,7 @@ __stp_call_vm_callbacks_with_vma(struct stap_task_finder_target *tgt, rc, (int)tsk->pid); } else { - __stp_call_vm_callbacks(tgt, tsk, 1, mmpath, + __stp_call_vm_callbacks(tgt, tsk, map_p, mmpath, vma->vm_start, vma->vm_end, (vma->vm_pgoff << PAGE_SHIFT)); } @@ -1145,7 +1146,7 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action, down_read(&mm->mmap_sem); vma = __stp_find_file_based_vma(mm, rv); if (vma != NULL) { - __stp_call_vm_callbacks_with_vma(tgt, tsk, vma); + __stp_call_vm_callbacks_with_vma(tgt, tsk, 0, vma); } up_read(&mm->mmap_sem); mmput(mm); @@ -1218,6 +1219,7 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action, && vma->vm_end <= entry->vm_end) { __stp_call_vm_callbacks_with_vma(tgt, tsk, + 1, vma); if (vma->vm_end >= entry->vm_end) break; -- cgit From 0cf9ea606eb7677a1241595f7568dd4a6c243ef2 Mon Sep 17 00:00:00 2001 From: Mahesh J Salgaonkar Date: Fri, 20 Mar 2009 11:04:47 +0530 Subject: Removed #if defined. Format '%llx' works fine for all Arch --- tapset/aux_syscalls.stp | 7 ------- 1 file changed, 7 deletions(-) diff --git a/tapset/aux_syscalls.stp b/tapset/aux_syscalls.stp index d2e43903..87ea4e04 100644 --- a/tapset/aux_syscalls.stp +++ b/tapset/aux_syscalls.stp @@ -322,17 +322,10 @@ function _struct_sockaddr_u:string(uaddr:long, len:long) } else if ((sa->sa_family == AF_PACKET)&&(len == sizeof(struct sockaddr_ll))) { - /* FIXME. This needs tested */ struct sockaddr_ll *sll = (struct sockaddr_ll *)buf; -#if defined(__powerpc__) || defined(__ia64__) || defined(__s390x__) - snprintf(str, strlen, "{AF_PACKET, proto=%d, ind=%d, hatype=%d, pkttype=%d, halen=%d, addr=0x%lx}", - (int)sll->sll_protocol, sll->sll_ifindex, (int)sll->sll_hatype, (int)sll->sll_pkttype, - (int)sll->sll_halen, *(uint64_t *)sll->sll_addr); -#else snprintf(str, strlen, "{AF_PACKET, proto=%d, ind=%d, hatype=%d, pkttype=%d, halen=%d, addr=0x%llx}", (int)sll->sll_protocol, sll->sll_ifindex, (int)sll->sll_hatype, (int)sll->sll_pkttype, (int)sll->sll_halen, *(uint64_t *)sll->sll_addr); -#endif } else { -- cgit From f0b8d2671fa56e0e1dcb4cc09fd6f7edf70f8fa3 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 20 Mar 2009 11:54:15 -0400 Subject: PR6930: staprun: supports error message to syslog Add an interface (eprintf) to output error messages to syslogd, because staprun has no stderr after detaching from console. --- runtime/staprun/common.c | 21 +++++++++++++++++++++ runtime/staprun/mainloop.c | 2 +- runtime/staprun/staprun.h | 18 +++++++++++------- 3 files changed, 33 insertions(+), 8 deletions(-) diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c index fd16b4b8..b8860248 100644 --- a/runtime/staprun/common.c +++ b/runtime/staprun/common.c @@ -344,3 +344,24 @@ int send_request(int type, void *data, int len) if (rc < 0) return rc; return (rc != len+4); } + +#include + +static int use_syslog = 0; + +void eprintf(const char *fmt, ...) +{ + va_list va; + va_start(va, fmt); + if (use_syslog) + vsyslog(LOG_ERR, fmt, va); + else + vfprintf(stderr, fmt, va); + va_end(va); +} + +void switch_syslog(const char *name) +{ + openlog(name, LOG_PID, LOG_DAEMON); + use_syslog = 1; +} diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c index db6ef6b7..e91e6302 100644 --- a/runtime/staprun/mainloop.c +++ b/runtime/staprun/mainloop.c @@ -468,7 +468,7 @@ int stp_main_loop(void) } #endif case STP_OOB_DATA: - fputs((char *)data, stderr); + eprintf("%s", (char *)data); break; case STP_EXIT: { diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h index 84cf63fc..4c43e3ee 100644 --- a/runtime/staprun/staprun.h +++ b/runtime/staprun/staprun.h @@ -33,31 +33,35 @@ #include #include #include +#include /* Include config.h to pick up dependency for --prefix usage. */ #include "config.h" -#define dbug(level, args...) {if (verbose>=level) {fprintf(stderr,"%s:%s:%d ",__name__,__FUNCTION__, __LINE__); fprintf(stderr,args);}} +extern void eprintf(const char *fmt, ...); +extern void switch_syslog(const char *name); + +#define dbug(level, args...) do {if (verbose>=level) {eprintf("%s:%s:%d ",__name__,__FUNCTION__, __LINE__); eprintf(args);}} while (0) extern char *__name__; /* print to stderr */ -#define err(args...) fprintf(stderr,args) +#define err(args...) eprintf(args) /* better perror() */ #define perr(args...) do { \ int _errno = errno; \ - fputs("ERROR: ", stderr); \ - fprintf(stderr, args); \ - fprintf(stderr, ": %s\n", strerror(_errno)); \ + eprintf("ERROR: "); \ + eprintf(args); \ + eprintf(": %s\n", strerror(_errno)); \ } while (0) /* Error messages. Use these for serious errors, not informational messages to stderr. */ -#define _err(args...) do {fprintf(stderr,"%s:%s:%d: ERROR: ",__name__, __FUNCTION__, __LINE__); fprintf(stderr,args);} while(0) +#define _err(args...) do {eprintf("%s:%s:%d: ERROR: ",__name__, __FUNCTION__, __LINE__); eprintf(args);} while(0) #define _perr(args...) do { \ int _errno = errno; \ _err(args); \ - fprintf(stderr, ": %s\n", strerror(_errno)); \ + eprintf(": %s\n", strerror(_errno)); \ } while (0) #define overflow_error() _err("Internal buffer overflow. Please file a bug report.\n") -- cgit From 54892f28a2747079fae4aa35b80598cbb993a4c3 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 20 Mar 2009 11:59:06 -0400 Subject: PR6930: stapio: run in background as a daemon Add '-D'(daemon mode) option to staprun/stapio for daemon mode. In this mode, stapio shows just its pid and detachs from console. Since it has no stdio, this mode requires -o option. stapio will exit when it receives SIGTERM or detects some error. --- runtime/staprun/common.c | 52 ++++++++++++++++++++++++++++++++++++++++++---- runtime/staprun/mainloop.c | 35 +++++++++++++++++++++++++++++++ runtime/staprun/staprun.h | 1 + 3 files changed, 84 insertions(+), 4 deletions(-) diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c index b8860248..a1b70d3b 100644 --- a/runtime/staprun/common.c +++ b/runtime/staprun/common.c @@ -27,6 +27,7 @@ int attach_mod; int delete_mod; int load_only; int need_uprobes; +int daemon_mode; /* module variables */ char *modname = NULL; @@ -35,6 +36,21 @@ char *modoptions[MAXMODOPTIONS]; int control_channel = -1; /* NB: fd==0 possible */ +static char path_buf[PATH_MAX]; +static char *get_abspath(char *path) +{ + int len; + if (path[0] == '/') + return path; + + len = strlen(getcwd(path_buf, PATH_MAX)); + if (len + 2 + strlen(path) >= PATH_MAX) + return NULL; + path_buf[len] = '/'; + strcpy(&path_buf[len + 1], path); + return path_buf; +} + void parse_args(int argc, char **argv) { int c; @@ -49,8 +65,9 @@ void parse_args(int argc, char **argv) delete_mod = 0; load_only = 0; need_uprobes = 0; + daemon_mode = 0; - while ((c = getopt(argc, argv, "ALuvb:t:dc:o:x:")) != EOF) { + while ((c = getopt(argc, argv, "ALuvb:t:dc:o:x:D")) != EOF) { switch (c) { case 'u': need_uprobes = 1; @@ -85,11 +102,20 @@ void parse_args(int argc, char **argv) case 'L': load_only = 1; break; + case 'D': + daemon_mode = 1; + break; default: usage(argv[0]); } } - + if (outfile_name) { + outfile_name = get_abspath(outfile_name); + if (outfile_name == NULL) { + err("File name is too long.\n"); + usage(argv[0]); + } + } if (attach_mod && load_only) { err("You can't specify the '-A' and '-L' options together.\n"); usage(argv[0]); @@ -118,12 +144,29 @@ void parse_args(int argc, char **argv) err("You can't specify the '-c' and '-x' options together.\n"); usage(argv[0]); } + + if (daemon_mode && load_only) { + err("You can't specify the '-D' and '-L' options together.\n"); + usage(argv[0]); + } + if (daemon_mode && delete_mod) { + err("You can't specify the '-D' and '-d' options together.\n"); + usage(argv[0]); + } + if (daemon_mode && target_cmd) { + err("You can't specify the '-D' and '-c' options together.\n"); + usage(argv[0]); + } + if (daemon_mode && outfile_name == NULL) { + err("You have to specify output FILE with '-D' option.\n"); + usage(argv[0]); + } } void usage(char *prog) { - err("\n%s [-v] [-c cmd ] [-x pid] [-u user]\n" - "\t[-A|-L] [-b bufsize] [-o FILE] MODULE [module-options]\n", prog); + err("\n%s [-v] [-c cmd ] [-x pid] [-u user] [-A|-L|-d]\n" + "\t[-b bufsize] [-o FILE [-D]] MODULE [module-options]\n", prog); err("-v Increase verbosity.\n"); err("-c cmd Command \'cmd\' will be run and staprun will\n"); err(" exit when it does. The '_stp_target' variable\n"); @@ -140,6 +183,7 @@ void usage(char *prog) err("-d Delete a module. Only detached or unused modules\n"); err(" the user has permission to access will be deleted. Use \"*\"\n"); err(" (quoted) to delete all unused modules.\n"); + err("-D Run in background. This requires '-o' option.\n"); err("MODULE can be either a module name or a module path. If a\n"); err("module name is used, it is looked for in the following\n"); err("directory: /lib/modules/`uname -r`/systemtap\n"); diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c index e91e6302..b0d88073 100644 --- a/runtime/staprun/mainloop.c +++ b/runtime/staprun/mainloop.c @@ -318,6 +318,41 @@ int init_stapio(void) if (target_cmd) start_cmd(); + /* Run in background */ + if (daemon_mode) { + pid_t pid; + int ret; + dbug(2, "daemonizing stapio\n"); + + /* daemonize */ + ret = daemon(0, 1); /* don't close stdout at this time. */ + if (ret) { + err("Failed to daemonize stapio\n"); + return -1; + } + + /* change error messages to syslog. */ + switch_syslog("stapio"); + + /* show new pid */ + pid = getpid(); + fprintf(stdout, "%d\n", pid); + fflush(stdout); + + /* redirect all outputs to /dev/null */ + ret = open("/dev/null", O_RDWR); + if (ret < 0) { + err("Failed to open /dev/null\n"); + return -1; + } + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); + dup2(ret, STDOUT_FILENO); + dup2(ret, STDERR_FILENO); + close(ret); + } + return 0; } diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h index 4c43e3ee..b380cebd 100644 --- a/runtime/staprun/staprun.h +++ b/runtime/staprun/staprun.h @@ -157,6 +157,7 @@ extern int attach_mod; extern int delete_mod; extern int load_only; extern int need_uprobes; +extern int daemon_mode; /* getopt variables */ extern char *optarg; -- cgit From 52064a4bd37f8d81e1f488fe9d32fe6ccee63bd7 Mon Sep 17 00:00:00 2001 From: Breno Leitao Date: Fri, 20 Mar 2009 11:40:04 -0400 Subject: Added functions to grab IP source and destination from a socket, and functions to grab TCP source and destination port from a socket. Also, used this function inside some TCP probe functions, as recvmsg, to provide a richer set of fields. --- tapset/ip.stp | 32 ++++++++++++++++++++++++++ tapset/tcp.stp | 34 ++++++++++++++++++++++++++++ testsuite/systemtap.examples/network/tcp.stp | 11 +++++++++ 3 files changed, 77 insertions(+) create mode 100644 tapset/ip.stp create mode 100644 testsuite/systemtap.examples/network/tcp.stp diff --git a/tapset/ip.stp b/tapset/ip.stp new file mode 100644 index 00000000..1e2e263c --- /dev/null +++ b/tapset/ip.stp @@ -0,0 +1,32 @@ +// IP tapset +// Copyright (C) 2009, IBM Inc. +// Author : Breno Leitao +// +// This file is free software. You can redistribute it and/or modify it under +// the terms of the GNU General Public License (GPL), version 2. +// +// Based on previous work done by Arnaldo Carvalho de Melo + +/** + * sfunction ip_ntop - returns a string representation from an integer IP number + * @addr: the ip represented as an integer + */ +function ip_ntop:string (addr:long) +%{ + __be32 ip; + + ip = THIS->addr; + snprintf(THIS->__retvalue, MAXSTRINGLEN, NIPQUAD_FMT, NIPQUAD(ip)); +%} + +/* return the source IP address for a given sock */ +function __ip_sock_saddr:long (sock:long) +{ + return @cast(sock, "inet_sock")->saddr +} + +/* return the destination IP address for a given sock */ +function __ip_sock_daddr:long (sock:long) +{ + return @cast(sock, "inet_sock")->daddr +} diff --git a/tapset/tcp.stp b/tapset/tcp.stp index 1375f115..bb96b0cb 100644 --- a/tapset/tcp.stp +++ b/tapset/tcp.stp @@ -73,6 +73,16 @@ function tcp_ts_get_info_state:long(sock:long) CATCH_DEREF_FAULT(); %} +/* return the TCP destination port for a given sock */ +function __tcp_sock_dport:long (sock:long){ + return @cast(sock, "inet_sock")->dport +} + +/* return the TCP source port for a given sock */ +function __tcp_sock_sport:long (sock:long){ + return @cast(sock, "inet_sock")->sport +} + global sockstate[13], sockstate_init_p function tcp_sockstate_str:string (state:long) { if (! sockstate_init_p) { @@ -182,6 +192,10 @@ probe tcp.sendmsg.return = kernel.function("tcp_sendmsg").return { * @name: Name of this probe * @sock: Network socket * @size: Number of bytes to be received + * @saddr: A string representing the source IP address + * @daddr: A string representing the destination IP address + * @sport: TCP source port + * @dport: TCP destination port * Context: * The process which receives a tcp message */ @@ -189,12 +203,20 @@ probe tcp.recvmsg = kernel.function("tcp_recvmsg") { name = "tcp.recvmsg" sock = $sk size = $len + saddr = ip_ntop(__ip_sock_saddr($sk)) + daddr = ip_ntop(__ip_sock_daddr($sk)) + sport = __tcp_sock_sport($sk) + dport = __tcp_sock_dport($sk) } /** * probe tcp.recvmsg.return - Receiving TCP message complete * @name: Name of this probe * @size: Number of bytes received or error code if an error occurred. + * @saddr: A string representing the source IP address + * @daddr: A string representing the destination IP address + * @sport: TCP source port + * @dport: TCP destination port * * Context: * The process which receives a tcp message @@ -202,6 +224,10 @@ probe tcp.recvmsg = kernel.function("tcp_recvmsg") { probe tcp.recvmsg.return = kernel.function("tcp_recvmsg").return { name = "tcp.recvmsg" size = $return + saddr = ip_ntop(__ip_sock_saddr($sk)) + daddr = ip_ntop(__ip_sock_daddr($sk)) + sport = __tcp_sock_sport($sk) + dport = __tcp_sock_dport($sk) } /** @@ -209,6 +235,10 @@ probe tcp.recvmsg.return = kernel.function("tcp_recvmsg").return { * @name: Name of this probe * @sock: Network socket * @flags: TCP flags (e.g. FIN, etc) + * @saddr: A string representing the source IP address + * @daddr: A string representing the destination IP address + * @sport: TCP source port + * @dport: TCP destination port * * Context: * The process which disconnects tcp @@ -217,6 +247,10 @@ probe tcp.disconnect = kernel.function("tcp_disconnect") { name = "tcp.disconnect" sock = $sk flags = $flags + saddr = ip_ntop(__ip_sock_saddr($sk)) + daddr = ip_ntop(__ip_sock_daddr($sk)) + sport = __tcp_sock_sport($sk) + dport = __tcp_sock_dport($sk) } /** diff --git a/testsuite/systemtap.examples/network/tcp.stp b/testsuite/systemtap.examples/network/tcp.stp new file mode 100644 index 00000000..ebe72a1c --- /dev/null +++ b/testsuite/systemtap.examples/network/tcp.stp @@ -0,0 +1,11 @@ +//A simple TCP tapset example + +probe begin { + printf("Expected IP 7.91.205.21 .... %s\n", ip_ntop(123456789)) + printf("Expected IP 58.222.104.177 .... %s\n", ip_ntop(987654321)) + printf("Expected IP 9.3.191.111 ... %s\n", ip_ntop(151240559)) +} + +probe tcp.recvmsg { + printf("received a message from %s on port %d from port %d\n", saddr, dport, sport) +} -- cgit From 7e402c4915c373e7818cf6218b0877a102fd7ff6 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Fri, 20 Mar 2009 11:41:02 -0400 Subject: removed authorblock from tapset reference guide; added ip.stp to template --- doc/SystemTap_Tapset_Reference/tapsets.tmpl | 39 +++-------------------------- 1 file changed, 4 insertions(+), 35 deletions(-) diff --git a/doc/SystemTap_Tapset_Reference/tapsets.tmpl b/doc/SystemTap_Tapset_Reference/tapsets.tmpl index 892d30a9..21706ea2 100644 --- a/doc/SystemTap_Tapset_Reference/tapsets.tmpl +++ b/doc/SystemTap_Tapset_Reference/tapsets.tmpl @@ -5,23 +5,10 @@ SystemTap Tapset Reference Manual - - - - William - Cohen - - -
    - wcohen@redhat.com -
    -
    -
    -
    - 2008, 2009 - Red Hat, Inc. + 2008-2009 + Red Hat, Inc. and others @@ -170,11 +157,12 @@ Networking Tapset This family of probe points is used to probe the activities of - the network device, TCP layer, and UDP layer. + the network device and protocol layers. !Itapset/networking.stp !Itapset/tcp.stp !Itapset/udp.stp +!Itapset/ip.stp
    @@ -185,25 +173,6 @@ !Itapset/socket.stp - Process Tapset -- cgit From acd56c22068963ad48f39890f5307600ff7d5278 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 20 Mar 2009 12:11:30 -0400 Subject: PR6930: stapio: support file switching Add file-switching option(-S size[,N]) to stapio. This option has two arguments, 'size' and 'N', and requires -o option. - When the size of output file exceeds specified 'size'MB, staprun switches output file to the next file. For this purpose, all output file has a serial number as a suffix only when user specifies this option. - Using this option in bulk mode, the output file name will be 'FILE_cpuX.SERIAL'. - When the number of files exceeds specified N, staprun removes the oldest file. This argument can be omitted. --- runtime/staprun/common.c | 30 ++++++++++++++- runtime/staprun/mainloop.c | 15 ++------ runtime/staprun/relay.c | 69 +++++++++++++++++++++++++++++++++- runtime/staprun/relay_old.c | 92 ++++++++++++++++++++++++++++++++++++++++++++- runtime/staprun/staprun.h | 6 ++- 5 files changed, 195 insertions(+), 17 deletions(-) diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c index a1b70d3b..194488ef 100644 --- a/runtime/staprun/common.c +++ b/runtime/staprun/common.c @@ -28,6 +28,8 @@ int delete_mod; int load_only; int need_uprobes; int daemon_mode; +off_t fsize_max; +int fnum_max; /* module variables */ char *modname = NULL; @@ -54,6 +56,7 @@ static char *get_abspath(char *path) void parse_args(int argc, char **argv) { int c; + char *s; /* Initialize option variables. */ verbose = 0; @@ -66,8 +69,10 @@ void parse_args(int argc, char **argv) load_only = 0; need_uprobes = 0; daemon_mode = 0; + fsize_max = 0; + fnum_max = 0; - while ((c = getopt(argc, argv, "ALuvb:t:dc:o:x:D")) != EOF) { + while ((c = getopt(argc, argv, "ALuvb:t:dc:o:x:S:D")) != EOF) { switch (c) { case 'u': need_uprobes = 1; @@ -105,6 +110,16 @@ void parse_args(int argc, char **argv) case 'D': daemon_mode = 1; break; + case 'S': + fsize_max = strtoul(optarg, &s, 10); + fsize_max <<= 20; + if (s[0] == ',') + fnum_max = (int)strtoul(&s[1], &s, 10); + if (s[0] != '\0') { + err("Invalid file size option '%s'.\n", optarg); + usage(argv[0]); + } + break; default: usage(argv[0]); } @@ -161,12 +176,16 @@ void parse_args(int argc, char **argv) err("You have to specify output FILE with '-D' option.\n"); usage(argv[0]); } + if (outfile_name == NULL && fsize_max != 0) { + err("You have to specify output FILE with '-S' option.\n"); + usage(argv[0]); + } } void usage(char *prog) { err("\n%s [-v] [-c cmd ] [-x pid] [-u user] [-A|-L|-d]\n" - "\t[-b bufsize] [-o FILE [-D]] MODULE [module-options]\n", prog); + "\t[-b bufsize] [-o FILE [-D] [-S size[,N]]] MODULE [module-options]\n", prog); err("-v Increase verbosity.\n"); err("-c cmd Command \'cmd\' will be run and staprun will\n"); err(" exit when it does. The '_stp_target' variable\n"); @@ -184,6 +203,13 @@ void usage(char *prog) err(" the user has permission to access will be deleted. Use \"*\"\n"); err(" (quoted) to delete all unused modules.\n"); err("-D Run in background. This requires '-o' option.\n"); + err("-S size[,N] Switches output file to next file when the size\n"); + err(" of file reaches the specified size. The value\n"); + err(" should be an integer greater than 1 which is\n"); + err(" assumed to be the maximum file size in MB.\n"); + err(" When the number of output files reaches N, it\n"); + err(" switches to the first output file. You can omit\n"); + err(" the second argument.\n"); err("MODULE can be either a module name or a module path. If a\n"); err("module name is used, it is looked for in the following\n"); err("directory: /lib/modules/`uname -r`/systemtap\n"); diff --git a/runtime/staprun/mainloop.c b/runtime/staprun/mainloop.c index b0d88073..c80bbba4 100644 --- a/runtime/staprun/mainloop.c +++ b/runtime/staprun/mainloop.c @@ -489,18 +489,11 @@ int stp_main_loop(void) switch (type) { #ifdef STP_OLD_TRANSPORT case STP_REALTIME_DATA: - { - ssize_t bw = write(out_fd[0], data, nb); - if (bw >= 0 && bw != nb) { - nb = nb - bw; - bw = write(out_fd[0], data, nb); - } - if (bw != nb) { - _perr("write error (nb=%ld)", (long)nb); - cleanup_and_exit(0); - } - break; + if (write_realtime_data(data, nb)) { + _perr("write error (nb=%ld)", (long)nb); + cleanup_and_exit(0); } + break; #endif case STP_OOB_DATA: eprintf("%s", (char *)data); diff --git a/runtime/staprun/relay.c b/runtime/staprun/relay.c index 19621933..891913b0 100644 --- a/runtime/staprun/relay.c +++ b/runtime/staprun/relay.c @@ -44,6 +44,52 @@ static int ppoll(struct pollfd *fds, nfds_t nfds, } #endif +int make_outfile_name(char *buf, int max, int fnum, int cpu) +{ + if (bulkmode) { + /* special case: for testing we sometimes want to write to /dev/null */ + if (strcmp(outfile_name, "/dev/null") == 0) { + strcpy(buf, "/dev/null"); + } else { + if (snprintf_chk(buf, max, "%s_cpu%d.%d", + outfile_name, cpu, fnum)) + return -1; + } + } else { + /* stream mode */ + if (snprintf_chk(buf, max, "%s.%d", outfile_name, fnum)) + return -1; + } + return 0; +} + +static int open_outfile(int fnum, int cpu, int remove_file) +{ + char buf[PATH_MAX]; + if (!outfile_name) { + _err("-S is set without -o. Please file a bug report.\n"); + return -1; + } + + if (remove_file) { + /* remove oldest file */ + if (make_outfile_name(buf, PATH_MAX, fnum - fnum_max, cpu) < 0) + return -1; + remove(buf); /* don't care */ + } + + if (make_outfile_name(buf, PATH_MAX, fnum, cpu) < 0) + return -1; + out_fd[cpu] = open (buf, O_CREAT|O_TRUNC|O_WRONLY, 0666); + if (out_fd[cpu] < 0) { + perr("Couldn't open output file %s", buf); + return -1; + } + if (set_clexec(out_fd[cpu]) < 0) + return -1; + return 0; +} + /** * reader_thread - per-cpu channel buffer reader */ @@ -57,6 +103,9 @@ static void *reader_thread(void *data) struct timespec tim = {.tv_sec=0, .tv_nsec=200000000}, *timeout = &tim; sigset_t sigs; struct sigaction sa; + off_t wsize = 0; + int fnum = 0; + int remove_file = 0; sigemptyset(&sigs); sigaddset(&sigs,SIGUSR2); @@ -99,6 +148,19 @@ static void *reader_thread(void *data) } } while ((rc = read(relay_fd[cpu], buf, sizeof(buf))) > 0) { + wsize += rc; + /* Switching file */ + if (fsize_max && wsize > fsize_max) { + close(out_fd[cpu]); + fnum++; + if (fnum_max && fnum == fnum_max) + remove_file = 1; + if (open_outfile(fnum, cpu, remove_file) < 0) { + perr("Couldn't open file for cpu %d, exiting.", cpu); + return(NULL); + } + wsize = 0; + } if (write(out_fd[cpu], buf, rc) != rc) { perr("Couldn't write to output %d for cpu %d, exiting.", out_fd[cpu], cpu); return(NULL); @@ -163,7 +225,12 @@ int init_relayfs(void) return -1; } - if (bulkmode) { + if (fsize_max) { + /* switch file mode */ + for (i = 0; i < ncpus; i++) + if (open_outfile(0, i, 0) < 0) + return -1; + } else if (bulkmode) { for (i = 0; i < ncpus; i++) { if (outfile_name) { /* special case: for testing we sometimes want to write to /dev/null */ diff --git a/runtime/staprun/relay_old.c b/runtime/staprun/relay_old.c index bd746f19..25ba93bf 100644 --- a/runtime/staprun/relay_old.c +++ b/runtime/staprun/relay_old.c @@ -23,6 +23,14 @@ static int bulkmode = 0; unsigned subbuf_size = 0; unsigned n_subbufs = 0; +struct switchfile_ctrl_block { + off_t wsize; + int fnum; + int rmfile; +}; + +static struct switchfile_ctrl_block global_scb = {0, 0, 0}; + /* per-cpu buffer info */ static struct buf_status { @@ -70,6 +78,36 @@ void close_oldrelayfs(int detach) close_relayfs_files(i); } +static int open_oldoutfile(int fnum, int cpu, int remove_file) +{ + char buf[PATH_MAX]; + if (outfile_name) { + if (remove_file) { + /* remove oldest file */ + if (make_outfile_name(buf, PATH_MAX, fnum - fnum_max, + cpu) < 0) + return -1; + remove(buf); /* don't care */ + } + if (make_outfile_name(buf, PATH_MAX, fnum, cpu) < 0) + return -1; + } else if (bulkmode) { + if (sprintf_chk(buf, "stpd_cpu%d.%d", cpu, fnum)) + return -1; + } else { /* stream mode */ + out_fd[cpu] = STDOUT_FILENO; + return 0; + } + + out_fd[cpu] = open (buf, O_CREAT|O_TRUNC|O_WRONLY, 0666); + if (out_fd[cpu] < 0) { + perr("Couldn't open output file %s", buf); + return -1; + } + if (set_clexec(out_fd[cpu]) < 0) + return -1; + return 0; +} /** * open_relayfs_files - open and mmap buffer and open output file. * Returns -1 on unexpected failure, 0 if file not found, 1 on success. @@ -104,6 +142,11 @@ static int open_relayfs_files(int cpu, const char *relay_filebase, const char *p return -1; } + if (fsize_max) { + if (open_oldoutfile(0, cpu, 0) < 0) + goto err2; + goto opened; + } if (outfile_name) { /* special case: for testing we sometimes want to * write to /dev/null */ @@ -126,6 +169,7 @@ static int open_relayfs_files(int cpu, const char *relay_filebase, const char *p perr("Couldn't open output file %s", tmp); goto err2; } +opened: total_bufsize = subbuf_size * n_subbufs; relay_buffer[cpu] = mmap(NULL, total_bufsize, PROT_READ, @@ -155,7 +199,8 @@ err1: /** * process_subbufs - write ready subbufs to disk */ -static int process_subbufs(struct _stp_buf_info *info) +static int process_subbufs(struct _stp_buf_info *info, + struct switchfile_ctrl_block *scb) { unsigned subbufs_ready, start_subbuf, end_subbuf, subbuf_idx, i; int len, cpu = info->cpu; @@ -173,6 +218,18 @@ static int process_subbufs(struct _stp_buf_info *info) padding = *((unsigned *)subbuf_ptr); subbuf_ptr += sizeof(padding); len = (subbuf_size - sizeof(padding)) - padding; + scb->wsize += len; + if (fsize_max && scb->wsize > fsize_max) { + fclose(percpu_tmpfile[cpu]); + scb->fnum ++; + if (fnum_max && scb->fnum == fnum_max) + scb->rmfile = 1; + if (open_oldoutfile(scb->fnum, cpu, scb->rmfile) < 0) { + perr("Couldn't open file for cpu %d, exiting.", cpu); + exit(1); + } + scb->wsize = 0; + } if (len) { if (fwrite_unlocked (subbuf_ptr, len, 1, percpu_tmpfile[cpu]) != 1) { _perr("Couldn't write to output file for cpu %d, exiting:", cpu); @@ -196,6 +253,7 @@ static void *reader_thread(void *data) struct _stp_consumed_info consumed_info; unsigned subbufs_consumed; cpu_set_t cpu_mask; + struct switchfile_ctrl_block scb = {0, 0, 0}; CPU_ZERO(&cpu_mask); CPU_SET(cpu, &cpu_mask); @@ -217,7 +275,7 @@ static void *reader_thread(void *data) } rc = read(proc_fd[cpu], &status[cpu].info, sizeof(struct _stp_buf_info)); - subbufs_consumed = process_subbufs(&status[cpu].info); + subbufs_consumed = process_subbufs(&status[cpu].info, &scb); if (subbufs_consumed) { if (subbufs_consumed > status[cpu].max_backlog) status[cpu].max_backlog = subbufs_consumed; @@ -232,6 +290,33 @@ static void *reader_thread(void *data) } while (1); } +/** + * write_realtime_data - write realtime data packet to disk + */ +int write_realtime_data(void *data, ssize_t nb) +{ + ssize_t bw; + global_scb.wsize += nb; + if (fsize_max && global_scb.wsize > fsize_max) { + close(out_fd[0]); + global_scb.fnum++; + if (fnum_max && global_scb.fnum == fnum_max) + global_scb.rmfile = 1; + if (open_oldoutfile(global_scb.fnum, 0, + global_scb.rmfile) < 0) { + perr("Couldn't open file, exiting."); + return -1; + } + global_scb.wsize = 0; + } + bw = write(out_fd[0], data, nb); + if (bw >= 0 && bw != nb) { + nb = nb - bw; + bw = write(out_fd[0], data, nb); + } + return bw != nb; +} + /** * init_relayfs - create files and threads for relayfs processing * @@ -249,6 +334,9 @@ int init_oldrelayfs(void) bulkmode = 1; if (!bulkmode) { + if (fsize_max) + return open_oldoutfile(0, 0, 0); + if (outfile_name) { out_fd[0] = open (outfile_name, O_CREAT|O_TRUNC|O_WRONLY, 0666); if (out_fd[0] < 0 || set_clexec(out_fd[0]) < 0) { diff --git a/runtime/staprun/staprun.h b/runtime/staprun/staprun.h index b380cebd..6d0f9179 100644 --- a/runtime/staprun/staprun.h +++ b/runtime/staprun/staprun.h @@ -9,7 +9,7 @@ * * Copyright (C) 2005-2008 Red Hat Inc. */ - +#define _FILE_OFFSET_BITS 64 #include #include #include @@ -117,7 +117,9 @@ int init_relayfs(void); void close_relayfs(void); int init_oldrelayfs(void); void close_oldrelayfs(int); +int write_realtime_data(void *data, ssize_t nb); void setup_signals(void); +int make_outfile_name(char *buf, int max, int fnum, int cpu); /* staprun_funcs.c */ void setup_staprun_signals(void); const char *moderror(int err); @@ -158,6 +160,8 @@ extern int delete_mod; extern int load_only; extern int need_uprobes; extern int daemon_mode; +extern off_t fsize_max; +extern int fnum_max; /* getopt variables */ extern char *optarg; -- cgit From 701c41be909697d5ab36f7604a1f3620c7d04abc Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 20 Mar 2009 13:31:18 -0400 Subject: PR6930: stap: supports on-file flight recorder options Add on-file flight recorder options (the combination of -F and -o, and -S option) to stap command, and change manpages and NEWS. - Both of -F and -o is specified, stap passes -D option to staprun. - stap just passes -S option to staprun. --- NEWS | 17 +++++++++++++++++ buildrun.cxx | 5 ++++- main.cxx | 10 ++++++++-- session.h | 1 + stap.1.in | 16 +++++++++++++--- staprun.8.in | 15 ++++++++++++++- 6 files changed, 57 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index fff8afc9..d85ec2c0 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,22 @@ * What's new +- On-file flight recorder is supported. It allows stap to record huge + trace log on the disk and to run in background. + Passing -F option with -o option runs stap in background mode. In this + mode, staprun is detached from console, and stap itself shows staprun's + pid and exits. + Specifying the max size and the max number of log files are also available + by passing -S option. This option has one or two arguments seperated by + a comma. The first argument is the max size of a log file in MB. If the + size of a log file exceeds it, stap switches to the next log file + automatically. The second is how many files are kept on the disk. If the + number of log files exceeds it, the oldest log file is removed + automatically. The second argument can be omitted. + + For example, this will record output on log files each of them is smaller + than 1024MB and keep last 3 logs, in background. + % stap -F -o /tmp/staplog -S 1024,3 script.stp + - In guru mode (-g), the kernel probing blacklist is disabled, leaving only a subset - the kernel's own internal kprobe blacklist - to attempt to filter out areas unsafe to probe. The differences may be enough to diff --git a/buildrun.cxx b/buildrun.cxx index 0e9e0e17..e3634545 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -329,7 +329,10 @@ run_pass (systemtap_session& s) staprun_cmd += "-u "; if (s.load_only) - staprun_cmd += "-L "; + staprun_cmd += (s.output_file.empty() ? "-L " : "-D "); + + if (!s.size_option.empty()) + staprun_cmd += "-S " + s.size_option + " "; staprun_cmd += s.tmpdir + "/" + s.module_name + ".ko"; diff --git a/main.cxx b/main.cxx index 890f65bc..6f4064a5 100644 --- a/main.cxx +++ b/main.cxx @@ -111,7 +111,9 @@ usage (systemtap_session& s, int exitcode) << " -o FILE send script output to file, instead of stdout" << endl << " -c CMD start the probes, run CMD, and exit when it finishes" << endl << " -x PID sets target() to PID" << endl - << " -F load module and start probes, then detach" << endl + << " -F run as on-file flight recorder with -o." << endl + << " run as on-memory flight recorder without -o." << endl + << " -S size[,n] set maximum of the size and the number of files." << endl << " -d OBJECT add unwind/symbol data for OBJECT file"; if (s.unwindsym_modules.size() == 0) clog << endl; @@ -444,7 +446,7 @@ main (int argc, char * const argv []) { "vp", 1, &long_opt, LONG_OPT_VERBOSE_PASS }, { NULL, 0, NULL, 0 } }; - int grc = getopt_long (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:L:F", + int grc = getopt_long (argc, argv, "hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:L:FS:", long_options, NULL); if (grc < 0) break; @@ -628,6 +630,10 @@ main (int argc, char * const argv []) s.macros.push_back (string (optarg)); break; + case 'S': + s.size_option = string (optarg); + break; + case 'q': s.tapset_compile_coverage = true; break; diff --git a/session.h b/session.h index ec6c2e3e..820b819e 100644 --- a/session.h +++ b/session.h @@ -90,6 +90,7 @@ struct systemtap_session std::string module_name; std::string stapconf_name; std::string output_file; + std::string size_option; std::string cmd; int target_pid; int last_pass; diff --git a/stap.1.in b/stap.1.in index 5a2e35f9..f997b788 100644 --- a/stap.1.in +++ b/stap.1.in @@ -175,7 +175,7 @@ even if they do not have an explicit probe placed into them. .TP .BI \-o " FILE" Send standard output to named file. In bulk mode, percpu files will -start with FILE_ followed by the cpu number. +start with FILE_ (FILE_cpu with -F) followed by the cpu number. .TP .BI \-c " CMD" Start the probes, run CMD, and exit when CMD finishes. @@ -193,8 +193,18 @@ and aliases. Similar to "-l", but list probe points and script-level local variables. .TP .BI \-F -Load module and start probes, then detach from the module leaving the -probes running. +Without -o option, load module and start probes, then detach from the module +leaving the probes running. +With -o option, run staprun in background as a daemon and show it's pid. +.TP +.BI \-S " size[,N]" +Sets the maximum size of output file and the maximum number of output files. +If the size of output file will exceed +.B size +, systemtap switches output file to the next file. And if the number of +output files exceed +.B N +, systemtap removes the oldest output file. You can omit the second argument. .TP .B \-\-kelf For names and addresses of functions to probe, diff --git a/staprun.8.in b/staprun.8.in index c7e77dc4..68b5c947 100644 --- a/staprun.8.in +++ b/staprun.8.in @@ -52,7 +52,8 @@ The '_stp_target' variable will be set to PID. .TP .B \-o FILE Send output to FILE. If the module uses bulk mode, the output will -be in percpu files FILE_x where 'x' is the cpu number. +be in percpu files FILE_x(FILE_cpux in backgroud and bulk mode) +where 'x' is the cpu number. .TP .B \-b BUFFER_SIZE The systemtap module will specify a buffer size. @@ -73,6 +74,18 @@ Attach to loaded systemtap module. Delete a module. Only detached or unused modules the user has permission to access will be deleted. Use "*" (quoted) to delete all unused modules. +.TP +.BI \-D +Run staprun in background as a daemon and show it's pid. +.TP +.BI \-S " size[,N]" +Sets the maximum size of output file and the maximum number of output files. +If the size of output file will exceed +.B size +, systemtap switches output file to the next file. And if the number of +output files exceed +.B N +, systemtap removes the oldest output file. You can omit the second argument. .SH ARGUMENTS .B MODULE -- cgit From dc6e1d97c43aa173549ad00bb78d7ea86ec90c95 Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 20 Mar 2009 13:33:34 -0400 Subject: PR6930: initscript: support on-file flight recorder Modify systemtap initscript to support on-file flight recoder options. --- initscript/README.initscript | 2 +- initscript/systemtap.in | 22 +++++++++++++--------- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/initscript/README.initscript b/initscript/README.initscript index f566cf71..ee11f3be 100644 --- a/initscript/README.initscript +++ b/initscript/README.initscript @@ -1,5 +1,5 @@ Systemtap initscript -Version 0.2 +Version 0.2.1 Author: Masami Hiramatsu INDEX diff --git a/initscript/systemtap.in b/initscript/systemtap.in index eaa1d969..918455d6 100644 --- a/initscript/systemtap.in +++ b/initscript/systemtap.in @@ -287,7 +287,7 @@ stap_getopt () { # opts # TODO: support quoted options getopt -s bash -u \ -l 'kelf,kmap::,ignore-vmlinux,ignore-dwarf,vp:' \ - -o 'hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:L:F' -- $@ + -o 'hVMvtp:I:e:o:R:r:m:kgPc:x:D:bs:uqwl:d:L:FS:' -- $@ ret=$? [ $ret -ne 0 ] && slog "Failed to parse parameters. ($@)" return $ret @@ -301,9 +301,9 @@ get_compile_opts () { # opts for o in $opts; do if [ $skip -ne 0 ]; then skip=0; continue; fi case $o in - -p|-m|-r|-c|-x|-e|-s|-o) + -p|-m|-r|-c|-x|-e|-s|-o|-S) skip=1 ;; - -h|-V|-k) + -h|-V|-k|-F) ;; *) echo -n $o" " ;; @@ -312,14 +312,16 @@ get_compile_opts () { # opts } get_run_opts () { # normalized_opts - local opts o show + local opts o show mode opts=`stap_getopt $*` [ $? -ne 0 ] && return 1 + mode='-L' show=0 for o in $opts; do case $o in - -c|-x|-s|-o) + -c|-x|-s|-o|-S) [ $o == '-s' ] && o='-b' + [ $o == '-o' ] && mode='-D' echo -n $o" " show=1 ;; @@ -331,6 +333,7 @@ get_run_opts () { # normalized_opts ;; esac done + echo -n $mode } prepare_cache_dir () { @@ -461,11 +464,12 @@ start_script () { # script return 1 fi pushd "$tmpdir" &> /dev/null - logex $STAPRUN -L $opts "$CACHE_PATH/$s.ko" + eval log \"Exec: $STAPRUN $opts $CACHE_PATH/$s.ko\" + $STAPRUN $opts "$CACHE_PATH/$s.ko" 2>> "$LOG_FILE" > ./pid ret=$? + [ x`cat ./pid` = x ] && echo 0 > ./pid if [ $ret -eq 0 ]; then - # TODO: store daemon pid after supporting on-file flight recorder - echo 0 > "$STAT_PATH/$s" + logex cp -f ./pid "$STAT_PATH/$s" fi popd &> /dev/null rm -rf "$tmpdir" @@ -524,7 +528,7 @@ stop_script () { # script p=`get_daemon_pid $1` if [ $p -ne 0 ]; then - logex killall -TERM $p + logex kill -TERM $p else logex $STAPRUN -d "$1" fi -- cgit From 04ae1b090781725631ba3477ff77721b012cdaba Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Fri, 20 Mar 2009 13:38:29 -0400 Subject: PR9821: staprun supports subset of strftime. Add strftime subset format support for output file name to systemtap. This format will be evaluated when opening a new output file. --- main.cxx | 4 +- runtime/staprun/common.c | 119 +++++++++++++++++++++++++++++++++++++++++++- runtime/staprun/relay.c | 89 +++++++++++++++++++++++++++------ runtime/staprun/relay_old.c | 50 +++++++++++++------ runtime/staprun/staprun.h | 6 ++- stap.1.in | 2 + staprun.8.in | 4 +- 7 files changed, 240 insertions(+), 34 deletions(-) diff --git a/main.cxx b/main.cxx index 6f4064a5..cdcae41a 100644 --- a/main.cxx +++ b/main.cxx @@ -108,7 +108,9 @@ usage (systemtap_session& s, int exitcode) << " " << s.kernel_build_tree << endl << " -m MODULE set probe module name, instead of " << endl << " " << s.module_name << endl - << " -o FILE send script output to file, instead of stdout" << endl + << " -o FILE send script output to file, instead of stdout. This supports" << endl + << " a subset of strftime(3) (%%,%C,%Y,%y,%m,%d,%e,%F,%H,%I,%j,%k," << endl + << " %l,%M,%S,%R,%T,%u,%w) for FILE." << endl << " -c CMD start the probes, run CMD, and exit when it finishes" << endl << " -x PID sets target() to PID" << endl << " -F run as on-file flight recorder with -o." << endl diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c index 194488ef..8200ec9d 100644 --- a/runtime/staprun/common.c +++ b/runtime/staprun/common.c @@ -53,6 +53,113 @@ static char *get_abspath(char *path) return path_buf; } +int stap_strfloctime(char *buf, size_t max, const char *fmt, time_t t) +{ + char *c = buf; + const char *c2 = fmt, *end = buf + max; + int ret, num; + struct tm tm; + if (buf == NULL || fmt == NULL || max <= 1) + return -EINVAL; + localtime_r(&t, &tm); + + while (*c2 != '\0'){ + if (c + 1 >= end) + return -EINVAL; + if (*c2 != '%') { + *c++ = *c2++; + continue; + } + c2++; + switch (*c2++) { + case '%': + *c++ = '%'; + break; + case 'Y': + num = tm.tm_year + 1900; + goto numbering; + case 'y': + num = tm.tm_year % 100; + goto numbering02; + case 'C': + num = ((tm.tm_year + 1900 - 1) / 100) + 1; + goto numbering; + case 'm': + num = tm.tm_mon + 1; + goto numbering02; + case 'd': + num = tm.tm_mday; + goto numbering02; + case 'e': + num = tm.tm_mday; + goto numbering; + case 'F': + ret = snprintf(c, end - c, "%d-%02d-%02d", + tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday); + if (ret < 0) return ret; + c += ret; + break; + case 'H': + num = tm.tm_hour; + goto numbering02; + case 'I': + num = tm.tm_hour % 12; + if (num == 0) num = 12; + goto numbering02; + case 'j': + ret = snprintf(c, end - c, "%03d", tm.tm_yday); + if (ret < 0) return ret; + c += ret; + break; + case 'k': + num = tm.tm_hour; + goto numbering; + case 'l': + num = tm.tm_hour % 12; + if (num == 0) num = 12; + goto numbering; + case 'M': + num = tm.tm_min; + goto numbering02; + case 'S': + num = tm.tm_sec; + goto numbering02; + case 'R': + ret = snprintf(c, end - c, "%02d:%02d", + tm.tm_hour, tm.tm_min); + if (ret < 0) return ret; + c += ret; + break; + case 'T': + ret = snprintf(c, end - c, "%02d:%02d:%02d", + tm.tm_hour, tm.tm_min, tm.tm_sec); + if (ret < 0) return ret; + c += ret; + break; + case 'u': + num = tm.tm_wday == 0 ? 7 : tm.tm_wday; + goto numbering; + case 'w': + num = tm.tm_wday; + goto numbering; + default: + return -EINVAL; + } + continue; +numbering: + ret = snprintf(c, end - c, "%d", num); + if (ret < 0) return ret; + c += ret; + continue; +numbering02: + ret = snprintf(c, end - c, "%02d", num); + if (ret < 0) return ret; + c += ret; + } + *c = '\0'; + return c - buf; +} + void parse_args(int argc, char **argv) { int c; @@ -125,11 +232,19 @@ void parse_args(int argc, char **argv) } } if (outfile_name) { + char tmp[PATH_MAX]; + int ret; outfile_name = get_abspath(outfile_name); if (outfile_name == NULL) { err("File name is too long.\n"); usage(argv[0]); } + ret = stap_strfloctime(tmp, PATH_MAX - 18, /* = _cpuNNN.SSSSSSSSSS */ + outfile_name, time(NULL)); + if (ret < 0) { + err("Filename format is invalid or too long.\n"); + usage(argv[0]); + } } if (attach_mod && load_only) { err("You can't specify the '-A' and '-L' options together.\n"); @@ -191,7 +306,9 @@ void usage(char *prog) err(" exit when it does. The '_stp_target' variable\n"); err(" will contain the pid for the command.\n"); err("-x pid Sets the '_stp_target' variable to pid.\n"); - err("-o FILE Send output to FILE.\n"); + err("-o FILE Send output to FILE. This supports a subset of\n"); + err(" strftime(3) (%%%%,%%C,%%Y,%%y,%%m,%%d,%%e,%%F,%%H,%%I\n"); + err(" %%j,%%k,%%l,%%M,%%S,%%R,%%T,%%u,%%w) for FILE.\n"); err("-b buffer size The systemtap module specifies a buffer size.\n"); err(" Setting one here will override that value. The\n"); err(" value should be an integer between 1 and 4095 \n"); diff --git a/runtime/staprun/relay.c b/runtime/staprun/relay.c index 891913b0..50f295b5 100644 --- a/runtime/staprun/relay.c +++ b/runtime/staprun/relay.c @@ -17,6 +17,9 @@ static pthread_t reader[NR_CPUS]; static int relay_fd[NR_CPUS]; static int bulkmode = 0; static volatile int stop_threads = 0; +static time_t *time_backlog[NR_CPUS]; +static int backlog_order=0; +#define BACKLOG_MASK ((1 << backlog_order) - 1) /* * ppoll exists in glibc >= 2.4 @@ -44,20 +47,52 @@ static int ppoll(struct pollfd *fds, nfds_t nfds, } #endif -int make_outfile_name(char *buf, int max, int fnum, int cpu) +int init_backlog(int cpu) { + int order = 0; + if (!fnum_max) + return 0; + while (fnum_max >> order) order++; + if (fnum_max == 1<<(order-1)) order--; + time_backlog[cpu] = (time_t *)calloc(1< Date: Fri, 20 Mar 2009 15:50:00 -0400 Subject: tweak NEWS blurb wording on --skip-badvars --- NEWS | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/NEWS b/NEWS index d85ec2c0..7670f681 100644 --- a/NEWS +++ b/NEWS @@ -23,9 +23,9 @@ probe more interrupt handlers. - Variables unavailable in current context may be skipped by setting a - session level flag with command line option --skip-badvars now available. - This will simply substitute the otherwise error causing variable with a - literal 0 and print a warning message when the substitution has been made. + session level flag with command line option --skip-badvars now available. + This replaces any dwarf $variable expressions that could not be resolved + with literal numeric zeros, along with a warning message. * What's new in version 0.9 -- cgit From 9c73606142525f521a44c4907832b2d1e1f3c659 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Fri, 20 Mar 2009 16:30:02 -0400 Subject: PR9967: don't count -DINTERRUPTIBLE=1 reentrancy against MAXSKIPPED * tapsets.cxx (common_probe_entryfn_prologue): Become conditional on !INTERRUPTIBLE. * translate.cxx (emit_module_exit): Still print skipped_count_reentrant with -t, even if skipped_count was zero. --- stap.1.in | 3 ++- tapsets.cxx | 4 +++- translate.cxx | 5 +++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/stap.1.in b/stap.1.in index 50c092ee..7efa9239 100644 --- a/stap.1.in +++ b/stap.1.in @@ -1056,7 +1056,8 @@ means that the first error will exit the script. MAXSKIPPED Maximum number of skipped probes before an exit is triggered, default 100. Running systemtap with \-t (timing) mode gives more details about skipped -probes. +probes. With the default \-DINTERRUPTIBLE=1 setting, probes skipped due to +reentrancy are not accumulated against this limit. .TP MINSTACKSPACE Minimum number of free kernel stack bytes required in order to diff --git a/tapsets.cxx b/tapsets.cxx index a8653d8a..bc567491 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -206,7 +206,9 @@ common_probe_entryfn_prologue (translator_output* o, string statestr, o->newline() << "c = per_cpu_ptr (contexts, smp_processor_id());"; o->newline() << "if (atomic_inc_return (& c->busy) != 1) {"; - o->newline(1) << "atomic_inc (& skipped_count);"; + o->newline(1) << "#if !INTERRUPTIBLE"; + o->newline() << "atomic_inc (& skipped_count);"; + o->newline() << "#endif"; o->newline() << "#ifdef STP_TIMING"; o->newline() << "atomic_inc (& skipped_count_reentrant);"; o->newline() << "#ifdef DEBUG_REENTRANCY"; diff --git a/translate.cxx b/translate.cxx index 377a11fb..e7c23672 100644 --- a/translate.cxx +++ b/translate.cxx @@ -1360,9 +1360,10 @@ c_unparser::emit_module_exit () o->newline() << "#endif"; } - // print final error/reentrancy counts if non-zero + // print final error/skipped counts if non-zero o->newline() << "if (atomic_read (& skipped_count) || " - << "atomic_read (& error_count)) {"; + << "atomic_read (& error_count) || " + << "atomic_read (& skipped_count_reentrant)) {"; // PR9967 o->newline(1) << "_stp_warn (\"Number of errors: %d, " << "skipped probes: %d\\n\", " << "(int) atomic_read (& error_count), " -- cgit From 422735b3ec857e812097566e28950aa3313892b4 Mon Sep 17 00:00:00 2001 From: Stan Cox Date: Fri, 20 Mar 2009 16:30:19 -0400 Subject: Define static user probe point using asm instead of c. * includes/sys/sdt.h (STAP_PROBE_DATA): New. Define the probe point using asm instead of c. (STAP_PROBEN): Use it. * testsuite/systemtap.base/sdt.exp: Continue if a compile fails. * testsuite/systemtap.base/static_uprobes.exp: Don't test setting probe without .probes section. --- includes/sys/sdt.h | 123 +++++++++++----------------- testsuite/systemtap.base/sdt.exp | 6 +- testsuite/systemtap.base/static_uprobes.exp | 12 ++- 3 files changed, 64 insertions(+), 77 deletions(-) diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h index d6c90192..5b92eeb3 100644 --- a/includes/sys/sdt.h +++ b/includes/sys/sdt.h @@ -13,35 +13,23 @@ #include #include -#if _LP64 -#define STAP_PROBE_STRUCT_ARG(arg) \ - __uint64_t arg -#else -#define STAP_PROBE_STRUCT_ARG(arg) \ - long arg __attribute__ ((aligned(8))) -#endif - -#define STAP_SENTINEL 0x31425250 - -#define STAP_PROBE_STRUCT(probe,argc) \ -struct _probe_ ## probe \ -{ \ - int probe_type; \ - STAP_PROBE_STRUCT_ARG (probe_name); \ - STAP_PROBE_STRUCT_ARG (probe_arg); \ -}; \ -static char probe ## _ ## probe_name [] \ - __attribute__ ((section (".probes"))) \ - = #probe; \ -__extension__ static volatile struct _probe_ ## probe _probe_ ## probe __attribute__ ((section (".probes"))) = {STAP_SENTINEL,(size_t)& probe ## _ ## probe_name[0],argc}; - -/* The goto _probe_ prevents the label from "drifting" */ -#define STAP_LABEL_REF(probe, label) \ - if (__builtin_expect(_probe_ ## probe.probe_type < 0, 0)) \ - goto label; +#define STAP_PROBE_DATA_(probe,label) \ + __asm__ volatile (".section .probes\n" \ + "\t.align 4\n" \ + label "_name:\n\t.asciz " #probe "\n" \ + "\t.align 4\n" \ + "\t.int 0x31425250\n" \ + "\t.align 8\n" \ + "\t.quad " label "_name\n" \ + "\t.quad " label "\n" \ + "\t.previous\n") + +#define STAP_PROBE_DATA(probe,label) \ + STAP_PROBE_DATA_(#probe,label) /* These baroque macros are used to create a unique label */ #define STAP_CONCAT(a,b) a ## b +#define STAP_CONCATSTR(a,b) #a #b #define STAP_LABEL_PREFIX(p) _stapprobe1_ ## p /* __COUNTER__ is not present in gcc 4.1 */ #if __GNUC__ == 4 && __GNUC_MINOR__ >= 3 @@ -49,88 +37,80 @@ __extension__ static volatile struct _probe_ ## probe _probe_ ## probe __attribu #else #define STAP_COUNTER STAP_CONCAT(__,LINE__) #endif -#define STAP_LABEL(a,b) STAP_CONCAT(a,b) +#define STAP_LABEL(a,b) STAP_CONCATSTR(a,b) #define STAP_PROBE_(probe,label) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ - STAP_LABEL_REF(probe,label); \ -label: \ - __asm__ volatile ("nop"); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop"); \ } while (0) -#define STAP_PROBE1_(probe,label,parm1) \ +#define STAP_PROBE1_(probe,label,parm1) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ -label: \ - __asm__ volatile ("nop /* %0 */" :: "X"( arg1)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 */" :: "X"(arg1)); \ } while (0) #define STAP_PROBE2_(probe,label,parm1,parm2) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ -label: \ - __asm__ volatile ("nop /* %0 %1 */" :: "X"(arg1), "X"(arg2)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 */" :: "X"(arg1), "X"(arg2)); \ } while (0) #define STAP_PROBE3_(probe,label,parm1,parm2,parm3) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ -label: \ - __asm__ volatile ("nop /* %0 %1 %2 */" :: "X"(arg1), "X"(arg2), "X"(arg3)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 */" :: "X"(arg1), "X"(arg2), "X"(arg3)); \ } while (0) #define STAP_PROBE4_(probe,label,parm1,parm2,parm3,parm4) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ volatile __typeof__((parm4)) arg4 __attribute__ ((unused)) = parm4; \ -label: \ - __asm__ volatile ("nop /* %0 %1 %2 %3 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 %3 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4)); \ } while (0) #define STAP_PROBE5_(probe,label,parm1,parm2,parm3,parm4,parm5) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ volatile __typeof__((parm4)) arg4 __attribute__ ((unused)) = parm4; \ volatile __typeof__((parm5)) arg5 __attribute__ ((unused)) = parm5; \ -label: \ - __asm__ volatile ("nop /* %0 %1 %2 %3 %4 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 %3 %4 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5)); \ } while (0) #define STAP_PROBE6_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ volatile __typeof__((parm4)) arg4 __attribute__ ((unused)) = parm4; \ volatile __typeof__((parm5)) arg5 __attribute__ ((unused)) = parm5; \ volatile __typeof__((parm6)) arg6 __attribute__ ((unused)) = parm6; \ -label: \ - __asm__ volatile ("nop" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 %3 %4 %5 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6)); \ } while (0) -#define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ +#define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ @@ -138,14 +118,13 @@ do { \ volatile __typeof__((parm5)) arg5 __attribute__ ((unused)) = parm5; \ volatile __typeof__((parm6)) arg6 __attribute__ ((unused)) = parm6; \ volatile __typeof__((parm7)) arg7 __attribute__ ((unused)) = parm7; \ -label: \ - __asm__ volatile ("nop" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 %3 %4 %5 %6 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7)); \ } while (0) #define STAP_PROBE8_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ @@ -154,14 +133,13 @@ do { \ volatile __typeof__((parm6)) arg6 __attribute__ ((unused)) = parm6; \ volatile __typeof__((parm7)) arg7 __attribute__ ((unused)) = parm7; \ volatile __typeof__((parm8)) arg8 __attribute__ ((unused)) = parm8; \ -label: \ - __asm__ volatile ("nop" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8)); \ } while (0) #define STAP_PROBE9_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ @@ -171,14 +149,13 @@ do { \ volatile __typeof__((parm7)) arg7 __attribute__ ((unused)) = parm7; \ volatile __typeof__((parm8)) arg8 __attribute__ ((unused)) = parm8; \ volatile __typeof__((parm9)) arg9 __attribute__ ((unused)) = parm9; \ -label: \ - __asm__ volatile ("nop" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8), "X"(arg9)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 %8 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8), "X"(arg9)); \ } while (0) #define STAP_PROBE10_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ do { \ - STAP_PROBE_STRUCT(probe,(size_t)&& label) \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ @@ -189,9 +166,9 @@ do { \ volatile __typeof__((parm8)) arg8 __attribute__ ((unused)) = parm8; \ volatile __typeof__((parm9)) arg9 __attribute__ ((unused)) = parm9; \ volatile __typeof__((parm10)) arg10 __attribute__ ((unused)) = parm10; \ -label: \ - __asm__ volatile ("nop" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8), "X"(arg9), "X"(arg10)); \ - STAP_LABEL_REF(probe,label); \ + STAP_PROBE_DATA(probe,label); \ + __asm__ volatile (label ":\n" \ + "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8), "X"(arg9), "X"(arg10)); \ } while (0) #define STAP_PROBE(provider,probe) \ diff --git a/testsuite/systemtap.base/sdt.exp b/testsuite/systemtap.base/sdt.exp index 21b94810..a398d795 100644 --- a/testsuite/systemtap.base/sdt.exp +++ b/testsuite/systemtap.base/sdt.exp @@ -27,7 +27,8 @@ set res [target_compile $srcdir/$subdir/$test.c $test.prog executable "$test_fla if { $res != "" } { verbose "target_compile failed: $res" 2 fail "compiling $test.c $extra_flag" - return + untested "$test $extra_flag" + continue } else { pass "compiling $test.c $extra_flag" } @@ -49,7 +50,8 @@ set res [target_compile $srcdir/$subdir/$test.c $test.prog executable "$test_fla if { $res != "" } { verbose "target_compile failed: $res" 2 fail "compiling $test.c c++ $extra_flag" - return + untested "$test $extra_flag" + continue } else { pass "compiling $test.c c++ $extra_flag" } diff --git a/testsuite/systemtap.base/static_uprobes.exp b/testsuite/systemtap.base/static_uprobes.exp index b4214436..e407440e 100644 --- a/testsuite/systemtap.base/static_uprobes.exp +++ b/testsuite/systemtap.base/static_uprobes.exp @@ -103,7 +103,11 @@ if {[installtest_p]} { set sdtdir $srcdir/../includes } -set sup_flags "additional_flags=-I$sdtdir additional_flags=-g additional_flags=-O additional_flags=-I." +set sup_flags "additional_flags=-I$srcdir/../includes/sys" +set sup_flags "$sup_flags additional_flags=-I$sdtdir" +set sup_flags "$sup_flags additional_flags=-g" +set sup_flags "$sup_flags additional_flags=-O" +set sup_flags "$sup_flags additional_flags=-I." set res [target_compile $sup_srcpath $sup_exepath executable $sup_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 @@ -177,6 +181,10 @@ expect { wait -if {$ok == 5} { pass "$test C++" } { fail "$test C++ ($ok)" } +# we now generate the probes via asm so there is no label debug info +if {$ok == 5} { pass "$test C++" } { xfail "$test C++ ($ok)" } +if { $verbose == 0 } { catch {exec rm -f $sup_srcpath $sup_exepath $supcplus_exepath $sup_dpath $sup_hpath $sup_stppath} +} + -- cgit From 11dc6a07aa2aa1c7da1738c20cbc5c19f878374b Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Fri, 20 Mar 2009 19:13:45 -0400 Subject: fix build regression w/o -t * translate.cxx (emit_common_header): Always emit atomic_t skipped_* counters. --- translate.cxx | 2 -- 1 file changed, 2 deletions(-) diff --git a/translate.cxx b/translate.cxx index e7c23672..40bb82c2 100644 --- a/translate.cxx +++ b/translate.cxx @@ -867,12 +867,10 @@ c_unparser::emit_common_header () o->newline() << "static atomic_t session_state = ATOMIC_INIT (STAP_SESSION_STARTING);"; o->newline() << "static atomic_t error_count = ATOMIC_INIT (0);"; o->newline() << "static atomic_t skipped_count = ATOMIC_INIT (0);"; - o->newline() << "#ifdef STP_TIMING"; o->newline() << "static atomic_t skipped_count_lowstack = ATOMIC_INIT (0);"; o->newline() << "static atomic_t skipped_count_reentrant = ATOMIC_INIT (0);"; o->newline() << "static atomic_t skipped_count_uprobe_reg = ATOMIC_INIT (0);"; o->newline() << "static atomic_t skipped_count_uprobe_unreg = ATOMIC_INIT (0);"; - o->newline() << "#endif"; o->newline(); o->newline() << "struct context {"; o->newline(1) << "atomic_t busy;"; -- cgit From a1c66a0f3d8795fbcf49ce936dee3c5645f0bfa6 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Fri, 20 Mar 2009 19:26:58 -0400 Subject: support tracepoint extraction for kernel build trees built with O=/path * buildrun.cxx (make_tracequery): Also search source/include/trace/*.h. --- buildrun.cxx | 30 +++++++++++++++++------------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/buildrun.cxx b/buildrun.cxx index e3634545..6a266bd2 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -384,21 +384,25 @@ make_tracequery(systemtap_session& s, string& name) // dynamically pull in all tracepoint headers from include/trace/ glob_t trace_glob; - string glob_str(s.kernel_build_tree + "/include/trace/*.h"); - glob(glob_str.c_str(), 0, NULL, &trace_glob); - for (unsigned i = 0; i < trace_glob.gl_pathc; ++i) + string globs[2] = { "/include/trace/*.h", "/source/include/trace/*.h" }; + for (unsigned z=0; z<2; z++) { - string header(basename(trace_glob.gl_pathv[i])); - - // filter out a few known "internal-only" headers - if (header == "trace_events.h") - continue; - if (header.find("_event_types.h") != string::npos) - continue; - - osrc << "#include " << endl; + string glob_str(s.kernel_build_tree + globs[z]); + glob(glob_str.c_str(), 0, NULL, &trace_glob); + for (unsigned i = 0; i < trace_glob.gl_pathc; ++i) + { + string header(basename(trace_glob.gl_pathv[i])); + + // filter out a few known "internal-only" headers + if (header == "trace_events.h") + continue; + if (header.find("_event_types.h") != string::npos) + continue; + + osrc << "#include " << endl; + } + globfree(&trace_glob); } - globfree(&trace_glob); // finish up the module source osrc << "#endif /* CONFIG_TRACEPOINTS */" << endl; -- cgit From b278033a7e4632a414502b63ba51fcce36f44f94 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 20 Mar 2009 16:35:06 -0700 Subject: Cache the tracepoint query results To use tracepoints, we build a "tracequery" module that compiles debuginfo for all available tracepoints in the user's kernel. That's a bit of a cumbersome step to do during pass-2 though. This change adds tracequery caching so we only need to compile it once. --- hash.cxx | 18 ++++++++++++++++++ hash.h | 1 + session.h | 1 + tapsets.cxx | 34 +++++++++++++++++++++++++++++++++- 4 files changed, 53 insertions(+), 1 deletion(-) diff --git a/hash.cxx b/hash.cxx index 61caa356..b8d5a0e4 100644 --- a/hash.cxx +++ b/hash.cxx @@ -237,4 +237,22 @@ find_hash (systemtap_session& s, const string& script) find_script_hash(s, script, base); } + +void +find_tracequery_hash (systemtap_session& s) +{ + hash h; + get_base_hash(s, h); + + // The basic hash should be good enough for the tracepoint query module + + // Get the directory path to store our cached module + string result, hashdir; + h.result(result); + if (!create_hashdir(s, result, hashdir)) + return; + + s.tracequery_path = hashdir + "/tracequery_" + result + ".ko"; +} + /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ diff --git a/hash.h b/hash.h index d386ad03..0fe95e27 100644 --- a/hash.h +++ b/hash.h @@ -35,5 +35,6 @@ public: }; void find_hash (systemtap_session& s, const std::string& script); +void find_tracequery_hash (systemtap_session& s); /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ diff --git a/session.h b/session.h index 820b819e..cbbae6b2 100644 --- a/session.h +++ b/session.h @@ -117,6 +117,7 @@ struct systemtap_session std::string cache_path; std::string hash_path; std::string stapconf_path; + std::string tracequery_path; // dwarfless operation bool consult_symtab; diff --git a/tapsets.cxx b/tapsets.cxx index bc567491..e9ade595 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -18,6 +18,7 @@ #include "buildrun.h" #include "dwarf_wrappers.h" #include "auto_free.h" +#include "hash.h" #include #include @@ -9993,12 +9994,43 @@ tracepoint_builder::init_dw(systemtap_session& s) if (dw != NULL) return true; + if (s.use_cache) + { + // see if the cached module exists + find_tracequery_hash(s); + if (!s.tracequery_path.empty()) + { + int fd = open(s.tracequery_path.c_str(), O_RDONLY); + if (fd != -1) + { + if (s.verbose > 2) + clog << "Pass 2: using cached " << s.tracequery_path << endl; + + dw = new dwflpp(s); + dw->setup_user(s.tracequery_path); + close(fd); + return true; + } + } + } + + // no cached module, time to make it string tracequery_ko; int rc = make_tracequery(s, tracequery_ko); if (rc != 0) return false; - // TODO cache tracequery.ko + if (s.use_cache) + { + // try to save tracequery in the cache + if (s.verbose > 2) + clog << "Copying " << tracequery_ko + << " to " << s.tracequery_path << endl; + if (copy_file(tracequery_ko.c_str(), + s.tracequery_path.c_str()) != 0) + cerr << "Copy failed (\"" << tracequery_ko << "\" to \"" + << s.tracequery_path << "\"): " << strerror(errno) << endl; + } dw = new dwflpp(s); dw->setup_user(tracequery_ko); -- cgit From ccd65d4a6f99ded6bfc05deee39f9d20816ca8a6 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 20 Mar 2009 17:12:15 -0700 Subject: Document @cast module search paths --- NEWS | 5 +++++ stap.1.in | 10 ++++++---- 2 files changed, 11 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 7670f681..4a65bacb 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,10 @@ * What's new +- Typecasting with @cast now supports modules search paths, which is + useful in case there are multiple places where the type definition + may be found. For example: + @cast(sdev, "scsi_device", "kernel:scsi_mod")->sdev_state + - On-file flight recorder is supported. It allows stap to record huge trace log on the disk and to run in background. Passing -F option with -o option runs stap in background mode. In this diff --git a/stap.1.in b/stap.1.in index 7efa9239..c562c8b7 100644 --- a/stap.1.in +++ b/stap.1.in @@ -788,10 +788,12 @@ and dereference the .I member value. The optional .I module -tells the translator where to look for information about that type. If -the module is not specified, it will default either to the probe module -for dwarf probes, or to "kernel" for functions and all other probes -types. +tells the translator where to look for information about that type. +Multiple modules may be specified as a list with +.IR : +separators. If the module is not specified, it will default either to +the probe module for dwarf probes, or to "kernel" for functions and all +other probes types. .PP When in guru mode, the translator will also allow scripts to assign new values to members of typecasted pointers. -- cgit From b1a4288cb2293d59010e3c0183f582b65b7e163e Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 20 Mar 2009 17:49:32 -0700 Subject: Add a tracepoint NEWS blurb --- NEWS | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/NEWS b/NEWS index 4a65bacb..7ae93675 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,12 @@ * What's new +- Kernel tracepoints are now supported for probing predefined kernel + events without any debuginfo. Tracepoints incur less overhead than + kprobes, and context parameters are available with full type + information. Any kernel 2.6.28 and later should have defined + tracepoints. Try the following to see what's available: + $ stap -L 'kernel.trace("*")' + - Typecasting with @cast now supports modules search paths, which is useful in case there are multiple places where the type definition may be found. For example: -- cgit From b08db79a21adfb5e2fb38b711269a7d0125d1d53 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 20 Mar 2009 17:51:47 -0700 Subject: Update a few new AUTHORS --- AUTHORS | 3 +++ 1 file changed, 3 insertions(+) diff --git a/AUTHORS b/AUTHORS index 6a20ef72..0ed3ed04 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,6 +1,7 @@ Ananth N Mavinakayanahalli Anil Keshavamurthy Anithra Janakiraman +Breno Leitao Charles Spirakis Dan Horak Dave Brolley @@ -21,6 +22,8 @@ K.Prasad Kent Sebastian Kevin Stafford Li Guanglei +Lubomir Rintel +Mahesh J Salgaonkar Mark McLoughlin Mark Wielaard Martin Hunt -- cgit From a99eea4f68db917268b83ab75574c832b646bd65 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Sat, 21 Mar 2009 08:39:57 -0400 Subject: sdt.exp: save intermediate sdt.h-client executables for analysis * testsuite/lib/stap_run2.exp (stap_run3): Put supplied stap extra arguments after the .stp script name, not before, so that @1/such arguments can be substituted within. --- testsuite/lib/stap_run2.exp | 2 +- testsuite/systemtap.base/sdt.exp | 14 +++++++++----- testsuite/systemtap.base/sdt.stp | 20 ++++++++++---------- 3 files changed, 20 insertions(+), 16 deletions(-) diff --git a/testsuite/lib/stap_run2.exp b/testsuite/lib/stap_run2.exp index b734a1e7..d1f02c83 100644 --- a/testsuite/lib/stap_run2.exp +++ b/testsuite/lib/stap_run2.exp @@ -29,7 +29,7 @@ proc stap_run2 { TEST_NAME args } { proc stap_run3 { TEST_NAME TEST_FILE args } { if {[info procs installtest_p] != "" && ![installtest_p]} { untested $TEST_NAME; return } - set cmd [concat stap $args $TEST_FILE] + set cmd [concat stap $TEST_FILE $args] send_log "executing: $cmd\n" catch {eval exec $cmd} res diff --git a/testsuite/systemtap.base/sdt.exp b/testsuite/systemtap.base/sdt.exp index a398d795..46fa5a28 100644 --- a/testsuite/systemtap.base/sdt.exp +++ b/testsuite/systemtap.base/sdt.exp @@ -15,6 +15,7 @@ set extra_flags {{""} {additional_flags=-std=gnu89} {additional_flags=-ansi} {ad # Iterate extra_flags, trying each with C and C++ for {set i 0} {$i < [llength $extra_flags]} {incr i} { set extra_flag [lindex $extra_flags $i] +set testprog "sdt.c.exe.$i" # C set test_flags "additional_flags=-g" @@ -23,7 +24,9 @@ set test_flags "$test_flags additional_flags=-Wall" set test_flags "$test_flags additional_flags=-Wextra" set test_flags "$test_flags additional_flags=-Werror" -set res [target_compile $srcdir/$subdir/$test.c $test.prog executable "$test_flags $extra_flag"] +set saveidx 0 + +set res [target_compile $srcdir/$subdir/$test.c $testprog executable "$test_flags $extra_flag"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "compiling $test.c $extra_flag" @@ -34,19 +37,21 @@ if { $res != "" } { } if {[installtest_p]} { - stap_run3 "$test $extra_flag" $srcdir/$subdir/$test.stp -c ./$test.prog + stap_run3 "$test $extra_flag" $srcdir/$subdir/$test.stp $testprog -c ./$testprog } else { untested "$test $extra_flag" } # C++ +set testprog "sdt.cxx.exe.$i" + set test_flags "additional_flags=-g" set test_flags "$test_flags additional_flags=-I$srcdir/../includes/sys" set test_flags "$test_flags additional_flags=-Wall" set test_flags "$test_flags additional_flags=-Werror" set test_flags "$test_flags additional_flags=-x additional_flags=c++" -set res [target_compile $srcdir/$subdir/$test.c $test.prog executable "$test_flags $extra_flag"] +set res [target_compile $srcdir/$subdir/$test.c $testprog executable "$test_flags $extra_flag"] if { $res != "" } { verbose "target_compile failed: $res" 2 fail "compiling $test.c c++ $extra_flag" @@ -57,10 +62,9 @@ if { $res != "" } { } if {[installtest_p]} { - stap_run3 "$test c++ $extra_flag" $srcdir/$subdir/$test.stp -c ./$test.prog + stap_run3 "$test c++ $extra_flag" $srcdir/$subdir/$test.stp $testprog -c ./$testprog } else { untested "$test c++ $extra_flag" } } -catch {exec rm -f $test.prog} diff --git a/testsuite/systemtap.base/sdt.stp b/testsuite/systemtap.base/sdt.stp index 1f075bca..5df1fdc9 100644 --- a/testsuite/systemtap.base/sdt.stp +++ b/testsuite/systemtap.base/sdt.stp @@ -1,49 +1,49 @@ -probe process("sdt.prog").mark("mark_a") +probe process(@1).mark("mark_a") { printf("%d\n", $arg1); } -probe process("sdt.prog").mark("mark_b") +probe process(@1).mark("mark_b") { printf("%d %d\n", $arg1, $arg2); } -probe process("sdt.prog").mark("mark_c") +probe process(@1).mark("mark_c") { printf("%d %d %d\n", $arg1, $arg2, $arg3); } -probe process("sdt.prog").mark("mark_d") +probe process(@1).mark("mark_d") { printf("%d %d %d %d\n", $arg1, $arg2, $arg3, $arg4); } -probe process("sdt.prog").mark("mark_e") +probe process(@1).mark("mark_e") { printf("%d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5); } -probe process("sdt.prog").mark("mark_f") +probe process(@1).mark("mark_f") { printf("%d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6); } -probe process("sdt.prog").mark("mark_g") +probe process(@1).mark("mark_g") { printf("%d %d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7); } -probe process("sdt.prog").mark("mark_h") +probe process(@1).mark("mark_h") { printf("%d %d %d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8); } -probe process("sdt.prog").mark("mark_i") +probe process(@1).mark("mark_i") { printf("%d %d %d %d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8, $arg9); } -probe process("sdt.prog").mark("mark_j") +probe process(@1).mark("mark_j") { printf("%d %d %d %d %d %d %d %d %d %d\n", $arg1, $arg2, $arg3, $arg4, $arg5, $arg6, $arg7, $arg8, $arg9, $arg10); } -- cgit From 1fa23e70a939c20664d7ae6ee5ef66b51835e0ee Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Sun, 22 Mar 2009 11:20:23 -0400 Subject: PR9974: adapt to utrace_connected_engine -> utrace_engine Adjusted all headers that #include to follow with: /* PR9974: Adapt to struct renaming. */ --- runtime/itrace.c | 6 ++++++ runtime/task_finder.c | 6 ++++++ runtime/uprobes2/uprobes.c | 6 ++++++ runtime/uprobes2/uprobes.h | 5 +++++ runtime/utrace_compatibility.h | 5 +++++ 5 files changed, 28 insertions(+) diff --git a/runtime/itrace.c b/runtime/itrace.c index 3d9ded2f..618cbff0 100644 --- a/runtime/itrace.c +++ b/runtime/itrace.c @@ -18,6 +18,12 @@ #include #include #include + +/* PR9974: Adapt to struct renaming. */ +#ifdef UTRACE_API_VERSION +#define utrace_attached_engine utrace_engine +#endif + #include #include "uprobes/uprobes.h" #include "utrace_compatibility.h" diff --git a/runtime/task_finder.c b/runtime/task_finder.c index 2b408763..3f4908cb 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -6,6 +6,12 @@ #endif #include + +/* PR9974: Adapt to struct renaming. */ +#ifdef UTRACE_API_VERSION +#define utrace_attached_engine utrace_engine +#endif + #include #include #include diff --git a/runtime/uprobes2/uprobes.c b/runtime/uprobes2/uprobes.c index af187fc9..a0e9f2fe 100644 --- a/runtime/uprobes2/uprobes.c +++ b/runtime/uprobes2/uprobes.c @@ -29,6 +29,12 @@ #include #include #define UPROBES_IMPLEMENTATION 1 + +/* PR9974: Adapt to struct renaming. */ +#ifdef UTRACE_API_VERSION +#define utrace_attached_engine utrace_engine +#endif + #include "uprobes.h" #include #include diff --git a/runtime/uprobes2/uprobes.h b/runtime/uprobes2/uprobes.h index 11d01f5c..112e29e2 100644 --- a/runtime/uprobes2/uprobes.h +++ b/runtime/uprobes2/uprobes.h @@ -23,6 +23,11 @@ #include #include +/* Adapt to struct renaming. */ +#ifdef UTRACE_API_VERSION +#define utrace_attached_engine utrace_engine +#endif + struct pt_regs; enum uprobe_type { diff --git a/runtime/utrace_compatibility.h b/runtime/utrace_compatibility.h index 4a70da42..5521a5c2 100644 --- a/runtime/utrace_compatibility.h +++ b/runtime/utrace_compatibility.h @@ -13,6 +13,11 @@ #include +/* PR9974: Adapt to struct renaming. */ +#ifdef UTRACE_API_VERSION +#define utrace_attached_engine utrace_engine +#endif + #ifdef UTRACE_ACTION_RESUME /* -- cgit From 407658581b73f4f4a99e002f085a06c4ebb0864b Mon Sep 17 00:00:00 2001 From: Stan Cox Date: Mon, 23 Mar 2009 10:10:03 -0400 Subject: Make .probes 32 bit aware and simplify label handling. * includes/sys/sdt.h (STAP_PROBE_DATA_): Use gas local labels which avoids a mysql problem when a function containing a probe is inlined. Make the data placement 32 bit aware. --- includes/sys/sdt.h | 118 +++++++++++++++++++++++++---------------------------- 1 file changed, 56 insertions(+), 62 deletions(-) diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h index 5b92eeb3..3da4ff66 100644 --- a/includes/sys/sdt.h +++ b/includes/sys/sdt.h @@ -13,90 +13,84 @@ #include #include -#define STAP_PROBE_DATA_(probe,label) \ +#define STAP_PROBE_DATA_(probe,dataop) \ __asm__ volatile (".section .probes\n" \ - "\t.align 4\n" \ - label "_name:\n\t.asciz " #probe "\n" \ + "\t.align 8\n" \ + "1:\n\t.asciz " #probe "\n" \ "\t.align 4\n" \ "\t.int 0x31425250\n" \ - "\t.align 8\n" \ - "\t.quad " label "_name\n" \ - "\t.quad " label "\n" \ + "\t.align 8\n" \ + "\t" #dataop " 1b\n" \ + "\t.align 8\n" \ + "\t" #dataop " 2f\n" \ "\t.previous\n") -#define STAP_PROBE_DATA(probe,label) \ - STAP_PROBE_DATA_(#probe,label) - -/* These baroque macros are used to create a unique label */ -#define STAP_CONCAT(a,b) a ## b -#define STAP_CONCATSTR(a,b) #a #b -#define STAP_LABEL_PREFIX(p) _stapprobe1_ ## p -/* __COUNTER__ is not present in gcc 4.1 */ -#if __GNUC__ == 4 && __GNUC_MINOR__ >= 3 -#define STAP_COUNTER STAP_CONCAT(__,COUNTER__) +#if _LP64 +#define STAP_PROBE_DATA(probe) \ + STAP_PROBE_DATA_(#probe,.quad) #else -#define STAP_COUNTER STAP_CONCAT(__,LINE__) +#define STAP_PROBE_DATA(probe) \ + STAP_PROBE_DATA_(#probe,.long) #endif -#define STAP_LABEL(a,b) STAP_CONCATSTR(a,b) -#define STAP_PROBE_(probe,label) \ +#define STAP_PROBE_(probe) \ do { \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop"); \ } while (0) -#define STAP_PROBE1_(probe,label,parm1) \ +#define STAP_PROBE1_(probe,parm1) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 */" :: "X"(arg1)); \ } while (0) -#define STAP_PROBE2_(probe,label,parm1,parm2) \ +#define STAP_PROBE2_(probe,parm1,parm2) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 */" :: "X"(arg1), "X"(arg2)); \ } while (0) -#define STAP_PROBE3_(probe,label,parm1,parm2,parm3) \ +#define STAP_PROBE3_(probe,parm1,parm2,parm3) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 */" :: "X"(arg1), "X"(arg2), "X"(arg3)); \ } while (0) -#define STAP_PROBE4_(probe,label,parm1,parm2,parm3,parm4) \ +#define STAP_PROBE4_(probe,parm1,parm2,parm3,parm4) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ volatile __typeof__((parm4)) arg4 __attribute__ ((unused)) = parm4; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 %3 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4)); \ } while (0) -#define STAP_PROBE5_(probe,label,parm1,parm2,parm3,parm4,parm5) \ +#define STAP_PROBE5_(probe,parm1,parm2,parm3,parm4,parm5) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ volatile __typeof__((parm3)) arg3 __attribute__ ((unused)) = parm3; \ volatile __typeof__((parm4)) arg4 __attribute__ ((unused)) = parm4; \ volatile __typeof__((parm5)) arg5 __attribute__ ((unused)) = parm5; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 %3 %4 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5)); \ } while (0) -#define STAP_PROBE6_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6) \ +#define STAP_PROBE6_(probe,parm1,parm2,parm3,parm4,parm5,parm6) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ @@ -104,12 +98,12 @@ do { \ volatile __typeof__((parm4)) arg4 __attribute__ ((unused)) = parm4; \ volatile __typeof__((parm5)) arg5 __attribute__ ((unused)) = parm5; \ volatile __typeof__((parm6)) arg6 __attribute__ ((unused)) = parm6; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 %3 %4 %5 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6)); \ } while (0) -#define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ +#define STAP_PROBE7_(probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ @@ -118,12 +112,12 @@ do { \ volatile __typeof__((parm5)) arg5 __attribute__ ((unused)) = parm5; \ volatile __typeof__((parm6)) arg6 __attribute__ ((unused)) = parm6; \ volatile __typeof__((parm7)) arg7 __attribute__ ((unused)) = parm7; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 %3 %4 %5 %6 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7)); \ } while (0) -#define STAP_PROBE8_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ +#define STAP_PROBE8_(probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ @@ -133,12 +127,12 @@ do { \ volatile __typeof__((parm6)) arg6 __attribute__ ((unused)) = parm6; \ volatile __typeof__((parm7)) arg7 __attribute__ ((unused)) = parm7; \ volatile __typeof__((parm8)) arg8 __attribute__ ((unused)) = parm8; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8)); \ } while (0) -#define STAP_PROBE9_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ +#define STAP_PROBE9_(probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ @@ -149,12 +143,12 @@ do { \ volatile __typeof__((parm7)) arg7 __attribute__ ((unused)) = parm7; \ volatile __typeof__((parm8)) arg8 __attribute__ ((unused)) = parm8; \ volatile __typeof__((parm9)) arg9 __attribute__ ((unused)) = parm9; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 %8 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8), "X"(arg9)); \ } while (0) -#define STAP_PROBE10_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ +#define STAP_PROBE10_(probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ do { \ volatile __typeof__((parm1)) arg1 __attribute__ ((unused)) = parm1; \ volatile __typeof__((parm2)) arg2 __attribute__ ((unused)) = parm2; \ @@ -166,33 +160,33 @@ do { \ volatile __typeof__((parm8)) arg8 __attribute__ ((unused)) = parm8; \ volatile __typeof__((parm9)) arg9 __attribute__ ((unused)) = parm9; \ volatile __typeof__((parm10)) arg10 __attribute__ ((unused)) = parm10; \ - STAP_PROBE_DATA(probe,label); \ - __asm__ volatile (label ":\n" \ + STAP_PROBE_DATA(probe); \ + __asm__ volatile ("2:\n" \ "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 */" :: "X"(arg1), "X"(arg2), "X"(arg3), "X"(arg4), "X"(arg5), "X"(arg6), "X"(arg7), "X"(arg8), "X"(arg9), "X"(arg10)); \ } while (0) #define STAP_PROBE(provider,probe) \ - STAP_PROBE_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER)) + STAP_PROBE_(probe) #define STAP_PROBE1(provider,probe,parm1) \ - STAP_PROBE1_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1)) + STAP_PROBE1_(probe,(parm1)) #define STAP_PROBE2(provider,probe,parm1,parm2) \ - STAP_PROBE2_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2)) + STAP_PROBE2_(probe,(parm1),(parm2)) #define STAP_PROBE3(provider,probe,parm1,parm2,parm3) \ - STAP_PROBE3_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3)) + STAP_PROBE3_(probe,(parm1),(parm2),(parm3)) #define STAP_PROBE4(provider,probe,parm1,parm2,parm3,parm4) \ - STAP_PROBE4_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4)) + STAP_PROBE4_(probe,(parm1),(parm2),(parm3),(parm4)) #define STAP_PROBE5(provider,probe,parm1,parm2,parm3,parm4,parm5) \ - STAP_PROBE5_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5)) + STAP_PROBE5_(probe,(parm1),(parm2),(parm3),(parm4),(parm5)) #define STAP_PROBE6(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6) \ - STAP_PROBE6_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6)) + STAP_PROBE6_(probe,(parm1),(parm2),(parm3),(parm4),(parm5),(parm6)) #define STAP_PROBE7(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ - STAP_PROBE7_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7)) + STAP_PROBE7_(probe,(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7)) #define STAP_PROBE8(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ - STAP_PROBE8_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8)) + STAP_PROBE8_(probe,(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8)) #define STAP_PROBE9(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ - STAP_PROBE9_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8),(parm9)) + STAP_PROBE9_(probe,(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8),(parm9)) #define STAP_PROBE10(provider,probe,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ - STAP_PROBE10_(probe,STAP_LABEL(STAP_LABEL_PREFIX(probe),STAP_COUNTER),(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8),(parm9),(parm10)) + STAP_PROBE10_(probe,(parm1),(parm2),(parm3),(parm4),(parm5),(parm6),(parm7),(parm8),(parm9),(parm10)) #define DTRACE_PROBE(provider,probe) \ STAP_PROBE(provider,probe) -- cgit From d4db5608dbc31868a2041f20ea3f473eef3e61fd Mon Sep 17 00:00:00 2001 From: William Cohen Date: Mon, 23 Mar 2009 11:16:13 -0400 Subject: Add missing escape in kernel-doc create_sparameterlist() matching. --- scripts/kernel-doc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/kernel-doc b/scripts/kernel-doc index 9947882d..92178910 100755 --- a/scripts/kernel-doc +++ b/scripts/kernel-doc @@ -1774,7 +1774,7 @@ sub create_sparameterlist($$$) { my $param; foreach my $arg (split($splitter, $args)) { - if ($arg =~ m/s*([\w]+)\s*:?\s*([\w]*)/) { + if ($arg =~ m/\s*([\w]+)\s*:?\s*([\w]*)/) { $param = $1; $type = $2; push_parameter($param, $type, $file); -- cgit