diff options
-rw-r--r-- | buildrun.cxx | 1 | ||||
-rw-r--r-- | doc/SystemTap_Tapset_Reference/tapsets.tmpl | 8 | ||||
-rw-r--r-- | main.cxx | 64 | ||||
-rw-r--r-- | runtime/autoconf-x86-gs.c | 5 | ||||
-rw-r--r-- | tapset/i686/registers.stp | 50 | ||||
-rw-r--r-- | tapset/socket.stp | 6 | ||||
-rw-r--r-- | tapsets.cxx | 15 | ||||
-rw-r--r-- | testsuite/systemtap.base/static_uprobes.exp | 38 | ||||
-rw-r--r-- | testsuite/systemtap.base/x86_gs.exp | 12 | ||||
-rw-r--r-- | testsuite/systemtap.base/x86_gs.stp | 10 |
10 files changed, 184 insertions, 25 deletions
diff --git a/buildrun.cxx b/buildrun.cxx index 505589cf..aafb8a6d 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -152,6 +152,7 @@ compile_pass (systemtap_session& s) 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); + output_autoconf(s, o, "autoconf-x86-gs.c", "STAPCONF_X86_GS", NULL); #if 0 /* NB: For now, the performance hit of probe_kernel_read/write (vs. our diff --git a/doc/SystemTap_Tapset_Reference/tapsets.tmpl b/doc/SystemTap_Tapset_Reference/tapsets.tmpl index 21706ea2..b7c0713b 100644 --- a/doc/SystemTap_Tapset_Reference/tapsets.tmpl +++ b/doc/SystemTap_Tapset_Reference/tapsets.tmpl @@ -11,6 +11,14 @@ <holder>Red Hat, Inc. and others</holder> </copyright> + <authorgroup> + <author> + <othername>SystemTap</othername> + <contrib>Hackers</contrib> + </author> + </authorgroup> + + <legalnotice> <para> This documentation is free software; you can redistribute @@ -36,6 +36,8 @@ extern "C" { #include <sys/times.h> #include <sys/time.h> #include <sys/stat.h> +#include <sys/types.h> +#include <sys/wait.h> #include <time.h> #include <elfutils/libdwfl.h> #include <getopt.h> @@ -330,10 +332,62 @@ setup_signals (sighandler_t handler) sigaction (SIGTERM, &sa, NULL); } +pid_t runner_pid; +int runner (int, char * const []); + +// Passes on signals to runner process. +// In practise passes signal to runner process process group, +// since run_pass() uses system() to spawn child processes, +// which makes the process ignore SIGINT during the command run. +extern "C" +void waiter_handler (int sig) +{ + // Process group is negative process id. + kill (-1 * runner_pid, sig); +} + +// Just sits there till the runner exits and then exits the same way. +void waiter() +{ + int status; + setup_signals (&waiter_handler); + while (waitpid (runner_pid, &status, 0) != runner_pid); + + // Exit as our runner child exitted. + if (WIFEXITED(status)) + exit (WEXITSTATUS(status)); + + // Or simulate as if we were killed by the same signal. + if (WIFSIGNALED(status)) + { + int sig = WTERMSIG(status); + signal (sig, SIG_DFL); + raise (sig); + } + + // Should not happen, exit as if error. + exit(-1); +} int main (int argc, char * const argv []) { + // Fork to make sure runner gets its own process group, while + // the waiter sits in the original process group of the shell + // and forwards any signals. + runner_pid = fork (); + if (runner_pid == 0) + return runner (argc, argv); + if (runner_pid > 0) + waiter (); + + perror ("couldn't fork"); + exit (-1); +} + +int +runner (int argc, char * const argv []) +{ string cmdline_script; // -e PROGRAM string script_file; // FILE bool have_script = false; @@ -884,6 +938,16 @@ main (int argc, char * const argv []) // directory. s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c"; + // We want a new process group so we can use kill (0, sig) to send a + // signal to all children (but not the parent). As done in + // handle_interrupt (). + if (setpgrp() != 0) + { + const char* e = strerror (errno); + if (! s.suppress_warnings) + cerr << "Warning: failed to set new process group: " << e << endl; + } + // Set up our handler to catch routine signals, to allow clean // and reasonably timely exit. setup_signals(&handle_interrupt); diff --git a/runtime/autoconf-x86-gs.c b/runtime/autoconf-x86-gs.c new file mode 100644 index 00000000..f4dda795 --- /dev/null +++ b/runtime/autoconf-x86-gs.c @@ -0,0 +1,5 @@ +#include <asm/ptrace.h> + +#if defined (__i386__) +struct pt_regs regs = {.gs = 0x0}; +#endif diff --git a/tapset/i686/registers.stp b/tapset/i686/registers.stp index a6e5694e..997376dc 100644 --- a/tapset/i686/registers.stp +++ b/tapset/i686/registers.stp @@ -1,25 +1,39 @@ global _reg_offsets, _stp_regs_registered, _sp_offset, _ss_offset +function test_x86_gs:long() %{ /* pure */ +#ifdef STAPCONF_X86_GS + THIS->__retvalue = 1; +#else + THIS->__retvalue = 0; +#endif +%} + function _stp_register_regs() { + /* Same order as pt_regs */ - _reg_offsets["ebx"] = 0 _reg_offsets["bx"] = 0 - _reg_offsets["ecx"] = 4 _reg_offsets["cx"] = 4 - _reg_offsets["edx"] = 8 _reg_offsets["dx"] = 8 - _reg_offsets["esi"] = 12 _reg_offsets["si"] = 12 - _reg_offsets["edi"] = 16 _reg_offsets["di"] = 16 - _reg_offsets["ebp"] = 20 _reg_offsets["bp"] = 20 - _reg_offsets["eax"] = 24 _reg_offsets["ax"] = 24 - _reg_offsets["xds"] = 28 _reg_offsets["ds"] = 28 - _reg_offsets["xes"] = 32 _reg_offsets["es"] = 32 - _reg_offsets["xfs"] = 36 _reg_offsets["fs"] = 36 - _reg_offsets["orig_eax"] = 40 _reg_offsets["orig_ax"] = 40 - _reg_offsets["eip"] = 44 _reg_offsets["ip"] = 44 - _reg_offsets["xcs"] = 48 _reg_offsets["cs"] = 48 - _reg_offsets["eflags"] = 52 _reg_offsets["flags"] = 52 - _reg_offsets["esp"] = 56 _reg_offsets["sp"] = 56 - _reg_offsets["xss"] = 60 _reg_offsets["ss"] = 60 - _sp_offset = 56 - _ss_offset = 60 + _reg_offsets["ebx"] = 0 _reg_offsets["bx"] = 0 + _reg_offsets["ecx"] = 4 _reg_offsets["cx"] = 4 + _reg_offsets["edx"] = 8 _reg_offsets["dx"] = 8 + _reg_offsets["esi"] = 12 _reg_offsets["si"] = 12 + _reg_offsets["edi"] = 16 _reg_offsets["di"] = 16 + _reg_offsets["ebp"] = 20 _reg_offsets["bp"] = 20 + _reg_offsets["eax"] = 24 _reg_offsets["ax"] = 24 + _reg_offsets["xds"] = 28 _reg_offsets["ds"] = 28 + _reg_offsets["xes"] = 32 _reg_offsets["es"] = 32 + _reg_offsets["xfs"] = 36 _reg_offsets["fs"] = 36 + gs_incr = 0 +if (test_x86_gs()) { + gs_incr = 4 + _reg_offsets["xgs"] = 40 _reg_offsets["gs"] = 40 +} + _reg_offsets["orig_eax"] = 40 + gs_incr _reg_offsets["orig_ax"] = 40 + gs_incr + _reg_offsets["eip"] = 44 + gs_incr _reg_offsets["ip"] = 44 + gs_incr + _reg_offsets["xcs"] = 48 + gs_incr _reg_offsets["cs"] = 48 + gs_incr + _reg_offsets["eflags"] = 52 + gs_incr _reg_offsets["flags"] = 52 + gs_incr + _reg_offsets["esp"] = 56 + gs_incr _reg_offsets["sp"] = 56 + gs_incr + _reg_offsets["xss"] = 60 + gs_incr _reg_offsets["ss"] = 60 + gs_incr + _sp_offset = 56 + gs_incr + _ss_offset = 60 + gs_incr _stp_regs_registered = 1 } diff --git a/tapset/socket.stp b/tapset/socket.stp index 0f01b8d4..de778d7c 100644 --- a/tapset/socket.stp +++ b/tapset/socket.stp @@ -545,6 +545,7 @@ probe socket.close.return = kernel.function ("sock_release").return /** * sfunction sock_prot_num2str - Given a protocol number, return a string representation. + * @proto: The protocol number. */ function sock_prot_num2str:string (proto:long) { @@ -553,6 +554,7 @@ function sock_prot_num2str:string (proto:long) /** * sfunction sock_prot_str2num - Given a protocol name (string), return the corresponding protocol number. + * @proto: The protocol name. */ function sock_prot_str2num:long (proto:string) { @@ -563,6 +565,7 @@ function sock_prot_str2num:long (proto:string) /** * sfunction sock_fam_num2str - Given a protocol family number, return a string representation. + * @family: The family number. */ function sock_fam_num2str:string (family:long) { @@ -572,6 +575,7 @@ function sock_fam_num2str:string (family:long) /** * sfunction sock_fam_str2num - Given a protocol family name (string), return the corresponding * protocol family number. + * @family: The family name. */ function sock_fam_str2num:long (family:string) { @@ -582,6 +586,7 @@ function sock_fam_str2num:long (family:string) /** * sfunction sock_state_num2str - Given a socket state number, return a string representation. + * @state: The state number. */ function sock_state_num2str:string (state:long) { @@ -590,6 +595,7 @@ function sock_state_num2str:string (state:long) /** * sfunction sock_state_str2num - Given a socket state string, return the corresponding state number. + * @state: The state name. */ function sock_state_str2num:long (state:string) { diff --git a/tapsets.cxx b/tapsets.cxx index 690d7e28..50ee563a 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -5806,16 +5806,29 @@ dwarf_builder::build(systemtap_session & sess, probe_arg = *((__uint64_t*)((char*)pdata->d_buf + probe_scn_offset)); if (probe_scn_offset % (sizeof(__uint64_t)*2)) probe_scn_offset = (probe_scn_offset + sizeof(__uint64_t)*2) - (probe_scn_offset % (sizeof(__uint64_t)*2)); - if (strcmp (location->components[1]->arg->tok->content.c_str(), probe_name.c_str()) != 0) + if ((strcmp (location->components[1]->arg->tok->content.c_str(), + probe_name.c_str()) == 0) + || (dw->name_has_wildcard (location->components[1]->arg->tok->content.c_str()) + && dw->function_name_matches_pattern + (probe_name.c_str(), + location->components[1]->arg->tok->content.c_str()))) + ; + else continue; const token* sv_tok = location->components[1]->arg->tok; location->components[1]->functor = TOK_STATEMENT; location->components[1]->arg = new literal_number((int)probe_arg); location->components[1]->arg->tok = sv_tok; ((literal_map_t&)parameters)[TOK_STATEMENT] = location->components[1]->arg; + dwarf_query q(sess, base, location, *dw, parameters, finished_results); q.has_mark = true; dw->query_modules(&q); + if (sess.listing_mode) + { + finished_results.back()->locations[0]->components[1]->functor = TOK_MARK; + finished_results.back()->locations[0]->components[1]->arg = new literal_string (probe_name.c_str()); + } } return; } diff --git a/testsuite/systemtap.base/static_uprobes.exp b/testsuite/systemtap.base/static_uprobes.exp index 620d5576..820626b8 100644 --- a/testsuite/systemtap.base/static_uprobes.exp +++ b/testsuite/systemtap.base/static_uprobes.exp @@ -1,5 +1,7 @@ set test "static_uprobes" +# Test miscellaneous features of .mark probes + # Compile a C program to use as the user-space probing target set sup_srcpath "[pwd]/static_uprobes.c" set sup_exepath "[pwd]/static_uprobes.x" @@ -80,6 +82,9 @@ provider static_uprobes { }; " close $fp + +# Test dtrace + if {[installtest_p]} { set dtrace $env(SYSTEMTAP_PATH)/dtrace } else { @@ -90,9 +95,9 @@ if {[catch {exec $dtrace -h -s $sup_dpath} res]} { } catch {exec rm -f $sup_dpath} if {[file exists $sup_hpath]} then { - pass "$test generating header" + pass "$test dtrace" } else { - fail "$test generating header" + fail "$test dtrace" catch {exec rm -f $sup_srcpath $sup_hpath $sup_stppath} return } @@ -133,6 +138,8 @@ if {$utrace_support_found == 0} { return } +# Run stap on executable built with dtrace generated header file + set ok 0 verbose -log "spawn stap -c $sup_exepath $sup_stppath" @@ -151,14 +158,16 @@ wait if {$ok == 5} { pass "$test C" } { fail "$test C ($ok)" } +# Test passing various C types to .mark probes + set sup_flags "$sup_flags additional_flags=-O0" set res [target_compile $srcdir/$subdir/sdt_types.c sdt_types.x executable $sup_flags] if { $res != "" } { verbose "target_compile failed: $res" 2 - fail "$test compiling -g" + fail "$test compiling types -g" return } else { - pass "$test compiling -g" + pass "$test compiling types -g" } set ok 0 @@ -176,9 +185,26 @@ expect { wait if { $ok != 0 } { - fail $fail + fail "$test $fail" +} else { + pass "$test types" +} + +# Test .mark probe wildcard matching + +set ok 0 +spawn stap -l "process(\"./sdt_types.x\").mark(\"*\")" +expect { + -timeout 180 + -re {mark\(\".*\"\)} { incr ok; exp_continue } + timeout { fail "$test C (timeout)" } + eof { } +} + +if { $ok == 45 } { + pass "$test wildcard" } else { - pass types + fail "$test wildcard ($ok)" } if { $verbose == 0 } { diff --git a/testsuite/systemtap.base/x86_gs.exp b/testsuite/systemtap.base/x86_gs.exp new file mode 100644 index 00000000..98ab3051 --- /dev/null +++ b/testsuite/systemtap.base/x86_gs.exp @@ -0,0 +1,12 @@ +set test "x86_gs" +if {![installtest_p]} { untested $test; return } +set arch [exec uname -m] +if {$arch!="i686"} { untested $test; return } +spawn stap $srcdir/$subdir/x86_gs.stp +expect { + -timeout 60 + -re "0\r\n" { pass $test } + -re "140\r\n" { pass $test } + eof { fail $test } + timeout { fail "$test unexpected timeout" } +} diff --git a/testsuite/systemtap.base/x86_gs.stp b/testsuite/systemtap.base/x86_gs.stp new file mode 100644 index 00000000..68b58512 --- /dev/null +++ b/testsuite/systemtap.base/x86_gs.stp @@ -0,0 +1,10 @@ +#! stap + +# test x86 gs register + +probe begin { + if (!_stp_regs_registered) + _stp_register_regs() + printf("%d\n",test_x86_gs() * 100 + _reg_offsets["gs"]) /* 0 or 140 */ + exit() +} |