summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--buildrun.cxx1
-rw-r--r--doc/SystemTap_Tapset_Reference/tapsets.tmpl8
-rw-r--r--main.cxx64
-rw-r--r--runtime/autoconf-x86-gs.c5
-rw-r--r--tapset/i686/registers.stp50
-rw-r--r--tapset/socket.stp6
-rw-r--r--tapsets.cxx15
-rw-r--r--testsuite/systemtap.base/static_uprobes.exp38
-rw-r--r--testsuite/systemtap.base/x86_gs.exp12
-rw-r--r--testsuite/systemtap.base/x86_gs.stp10
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
diff --git a/main.cxx b/main.cxx
index fcb4cd51..ceabbac5 100644
--- a/main.cxx
+++ b/main.cxx
@@ -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()
+}