summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Brolley <brolley@redhat.com>2009-04-23 14:16:36 -0400
committerDave Brolley <brolley@redhat.com>2009-04-23 14:16:36 -0400
commitfb6d28283bd7ea63364a008d32c53687a694642f (patch)
treeaa2d8faf381be8ba016cf4fb18a4d01da464ac60
parente8aa2f848123598fa8c2110804b250cba1286271 (diff)
parent819ec23db74427d0249596959c938673f424f831 (diff)
downloadsystemtap-steved-fb6d28283bd7ea63364a008d32c53687a694642f.tar.gz
systemtap-steved-fb6d28283bd7ea63364a008d32c53687a694642f.tar.xz
systemtap-steved-fb6d28283bd7ea63364a008d32c53687a694642f.zip
Merge branch 'master' of git://sources.redhat.com/git/systemtap
Conflicts: Makefile.in
-rw-r--r--Makefile.am4
-rw-r--r--Makefile.in5
-rw-r--r--NEWS15
-rw-r--r--doc/SystemTap_Tapset_Reference/Makefile.am3
-rw-r--r--doc/SystemTap_Tapset_Reference/Makefile.in3
-rw-r--r--includes/sys/sdt.h10
-rw-r--r--main.cxx3
-rw-r--r--runtime/staprun/common.c112
-rw-r--r--runtime/syscall.h13
-rw-r--r--stap.1.in3
-rw-r--r--staprun.8.in3
-rw-r--r--tapset/context.stp6
-rw-r--r--tapsets.cxx11
-rw-r--r--tapsets.h1
-rw-r--r--testsuite/systemtap.base/flightrec1.exp43
-rw-r--r--testsuite/systemtap.base/flightrec2.exp69
-rw-r--r--testsuite/systemtap.base/flightrec2.stp5
-rw-r--r--testsuite/systemtap.base/kprobes.exp2
-rw-r--r--testsuite/systemtap.base/kprobes.stp10
-rw-r--r--testsuite/systemtap.base/strftime.exp49
-rw-r--r--translate.cxx2
21 files changed, 244 insertions, 128 deletions
diff --git a/Makefile.am b/Makefile.am
index a80b8ce8..7779c0eb 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -137,7 +137,7 @@ staprun_SOURCES = runtime/staprun/staprun.c runtime/staprun/staprun_funcs.c\
runtime/staprun/ctl.c runtime/staprun/common.c
staprun_CPPFLAGS = $(AM_CPPFLAGS)
-staprun_CFLAGS = @PROCFLAGS@ $(AM_CFLAGS) @PIECFLAGS@ -DSINGLE_THREADED -fno-strict-aliasing
+staprun_CFLAGS = @PROCFLAGS@ $(AM_CFLAGS) @PIECFLAGS@ -DSINGLE_THREADED -fno-strict-aliasing -fno-builtin-strftime
staprun_LDFLAGS = $(AM_LDFLAGS) @PIELDFLAGS@
staprun_LDADD = @PROCFLAGS@
@@ -151,7 +151,7 @@ stapio_SOURCES = runtime/staprun/stapio.c \
runtime/staprun/mainloop.c runtime/staprun/common.c \
runtime/staprun/ctl.c \
runtime/staprun/relay.c runtime/staprun/relay_old.c
-stapio_CFLAGS = @PROCFLAGS@ $(AM_CFLAGS) @PIECFLAGS@ -fno-strict-aliasing
+stapio_CFLAGS = @PROCFLAGS@ $(AM_CFLAGS) @PIECFLAGS@ -fno-strict-aliasing -fno-builtin-strftime
stapio_LDFLAGS = $(AM_LDFLAGS) @PIELDFLAGS@
stapio_LDADD = @PROCFLAGS@ -lpthread
diff --git a/Makefile.in b/Makefile.in
index e2f30aa1..d847610a 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -353,7 +353,8 @@ staprun_SOURCES = runtime/staprun/staprun.c \
runtime/staprun/common.c $(am__append_14)
staprun_CPPFLAGS = $(AM_CPPFLAGS)
staprun_CFLAGS = @PROCFLAGS@ $(AM_CFLAGS) @PIECFLAGS@ \
- -DSINGLE_THREADED -fno-strict-aliasing $(am__append_15)
+ -DSINGLE_THREADED -fno-strict-aliasing -fno-builtin-strftime \
+ $(am__append_15)
staprun_LDFLAGS = $(AM_LDFLAGS) @PIELDFLAGS@
staprun_LDADD = @PROCFLAGS@ $(am__append_16)
stapio_SOURCES = runtime/staprun/stapio.c \
@@ -361,7 +362,7 @@ stapio_SOURCES = runtime/staprun/stapio.c \
runtime/staprun/ctl.c \
runtime/staprun/relay.c runtime/staprun/relay_old.c
-stapio_CFLAGS = @PROCFLAGS@ $(AM_CFLAGS) @PIECFLAGS@ -fno-strict-aliasing
+stapio_CFLAGS = @PROCFLAGS@ $(AM_CFLAGS) @PIECFLAGS@ -fno-strict-aliasing -fno-builtin-strftime
stapio_LDFLAGS = $(AM_LDFLAGS) @PIELDFLAGS@
stapio_LDADD = @PROCFLAGS@ -lpthread
@BUILD_SERVER_TRUE@stap_client_connect_SOURCES = stap-client-connect.c
diff --git a/NEWS b/NEWS
index 8ec00f2b..88076db3 100644
--- a/NEWS
+++ b/NEWS
@@ -21,6 +21,21 @@
Probing of absolute statements can be done using the
kprobe.statement(ADDRESS).absolute construct.
+- EXPERIMENTAL support for user process unwinding. A new collection of
+ tapset functions have been added to handle user space backtraces from
+ probe points that support them (currently process and timer probes -
+ for timer probes test whether or not in user space first with the
+ already existing user_mode() function). The new tapset functions are:
+ uaddr - User space address of current running task.
+ usymname - Return the symbol of an address in the current task.
+ usymdata - Return the symbol and module offset of an address.
+ print_ustack - Print out stack for the current task from string.
+ print_ubacktrace - Print stack back trace for current task.
+ ubacktrace - Hex backtrace of current task stack.
+ Please read http://sourceware.org/ml/systemtap/2009-q2/msg00364.html
+ on the current restrictions and possible changes in the future and
+ give feedback if you want to influence future developments.
+
* What's new in version 0.9.5
- New probes process().insn and process().insn.block that allows
diff --git a/doc/SystemTap_Tapset_Reference/Makefile.am b/doc/SystemTap_Tapset_Reference/Makefile.am
index b21bfcd6..087ca887 100644
--- a/doc/SystemTap_Tapset_Reference/Makefile.am
+++ b/doc/SystemTap_Tapset_Reference/Makefile.am
@@ -32,7 +32,10 @@ stamp-htmldocs: tapsets.xml
xmlto html -o tapsets tapsets.xml
touch stamp-htmldocs
+# bump up the allocated space so "xmlto pdf" works
tapsets.pdf: tapsets.xml
+ export pool_size=2000000
+ export hash_size=120000
xmlto pdf tapsets.xml
stamp-mandocs: tapsets.xml
diff --git a/doc/SystemTap_Tapset_Reference/Makefile.in b/doc/SystemTap_Tapset_Reference/Makefile.in
index d569c298..bdd7ff20 100644
--- a/doc/SystemTap_Tapset_Reference/Makefile.in
+++ b/doc/SystemTap_Tapset_Reference/Makefile.in
@@ -429,7 +429,10 @@ uninstall-am:
@BUILD_REFDOCS_TRUE@ xmlto html -o tapsets tapsets.xml
@BUILD_REFDOCS_TRUE@ touch stamp-htmldocs
+# bump up the allocated space so "xmlto pdf" works
@BUILD_REFDOCS_TRUE@tapsets.pdf: tapsets.xml
+@BUILD_REFDOCS_TRUE@ export pool_size=2000000
+@BUILD_REFDOCS_TRUE@ export hash_size=120000
@BUILD_REFDOCS_TRUE@ xmlto pdf tapsets.xml
@BUILD_REFDOCS_TRUE@stamp-mandocs: tapsets.xml
diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h
index e5265ff1..c2242303 100644
--- a/includes/sys/sdt.h
+++ b/includes/sys/sdt.h
@@ -13,6 +13,12 @@
#include <string.h>
#include <sys/types.h>
+#ifdef __LP64__
+#define STAP_PROBE_ADDR "\t.quad "
+#else
+#define STAP_PROBE_ADDR "\t.long "
+#endif
+
#define STAP_PROBE_DATA_(probe) \
__asm__ volatile (".section .probes\n" \
"\t.align 8\n" \
@@ -20,9 +26,9 @@
"\t.align 4\n" \
"\t.int 0x31425250\n" \
"\t.align 8\n" \
- "\t.quad 1b\n" \
+ STAP_PROBE_ADDR "1b\n" \
"\t.align 8\n" \
- "\t.quad 2f\n" \
+ STAP_PROBE_ADDR "2f\n" \
"\t.previous\n")
#define STAP_PROBE_DATA(probe) \
diff --git a/main.cxx b/main.cxx
index 73945242..745d81e5 100644
--- a/main.cxx
+++ b/main.cxx
@@ -109,8 +109,7 @@ usage (systemtap_session& s, int exitcode)
<< " -m MODULE set probe module name, instead of " << endl
<< " " << s.module_name << 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
+ << " strftime(3) formats 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 6c199616..644dfa53 100644
--- a/runtime/staprun/common.c
+++ b/runtime/staprun/common.c
@@ -56,112 +56,15 @@ static char *get_abspath(char *path)
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;
+ size_t ret;
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) / 100);
- 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 + 1);
- 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;
- ret = snprintf(c, end - c, "%2d", num);
- if (ret < 0) return ret;
- c += ret;
- break;
- 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;
+ ret = strftime(buf, max, fmt, &tm);
+ if (ret == 0)
+ return -EINVAL;
+ return (int)ret;
}
void parse_args(int argc, char **argv)
@@ -310,9 +213,8 @@ 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. 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("-o FILE Send output to FILE. This supports strftime(3)\n");
+ err(" formats 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/syscall.h b/runtime/syscall.h
index ffc21efc..38b523e1 100644
--- a/runtime/syscall.h
+++ b/runtime/syscall.h
@@ -345,6 +345,10 @@ struct syscall_get_set_args {
int rw;
};
+#define CFM_SOF(cfm) ((cfm) & 0x7f) /* Size of frame */
+#define CFM_SOL(cfm) (((cfm) >> 7) & 0x7f) /* Size of locals */
+#define CFM_OUT(cfm) (CFM_SOF(cfm) - CFM_SOL(cfm)) /* Size of outputs */
+
static void syscall_get_set_args_cb(struct unw_frame_info *info, void *data)
{
struct syscall_get_set_args *args = data;
@@ -361,15 +365,18 @@ static void syscall_get_set_args_cb(struct unw_frame_info *info, void *data)
count = 0;
if (in_syscall(pt))
- count = min_t(int, args->n, cfm & 0x7f);
+ /* args->i + args->n must be less equal than nr outputs */
+ count = min_t(int, args->n, CFM_OUT(cfm) - args->i);
for (i = 0; i < count; i++) {
+ /* Skips dirties and locals */
if (args->rw)
- *ia64_rse_skip_regs(krbs, ndirty + i + args->i) =
+ *ia64_rse_skip_regs(krbs,
+ ndirty + CFM_SOL(cfm) + args->i + i) =
args->args[i];
else
args->args[i] = *ia64_rse_skip_regs(krbs,
- ndirty + i + args->i);
+ ndirty + CFM_SOL(cfm) + args->i + i);
}
if (!args->rw) {
diff --git a/stap.1.in b/stap.1.in
index 82a62b6d..aed473d7 100644
--- a/stap.1.in
+++ b/stap.1.in
@@ -181,8 +181,7 @@ even if they do not have an explicit probe placed into them.
.BI \-o " FILE"
Send standard output to named file. In bulk mode, percpu files will
start with FILE_ (FILE_cpu with -F) followed by the cpu number.
-This supports a subset of strftime(3) (%%, %C, %Y, %y, %m, %d, %e, %F,
-%H, %I, %j, %l, %M, %S, %R, %T, %u, %w) for FILE.
+This supports strftime(3) formats for FILE.
.TP
.BI \-c " CMD"
Start the probes, run CMD, and exit when CMD finishes.
diff --git a/staprun.8.in b/staprun.8.in
index 5d2a72a6..b9993288 100644
--- a/staprun.8.in
+++ b/staprun.8.in
@@ -53,8 +53,7 @@ The '_stp_target' variable will be set to PID.
.B \-o FILE
Send output to FILE. If the module uses bulk mode, the output will
be in percpu files FILE_x(FILE_cpux in backgroud and bulk mode)
-where 'x' is the cpu number. This supports a subset of strftime(3)
-(%%, %C, %Y, %y, %m, %d, %e, %F, %H, %I, %j, %l, %M, %S, %R, %T, %u, %w)
+where 'x' is the cpu number. This supports strftime(3) formats
for FILE.
.TP
.B \-b BUFFER_SIZE
diff --git a/tapset/context.stp b/tapset/context.stp
index 36d68c8d..6fad3740 100644
--- a/tapset/context.stp
+++ b/tapset/context.stp
@@ -233,12 +233,14 @@ function stack_unused:long () %{ /* pure */
%}
/**
- * sfunction uaddr - User space address of current running task.
+ * sfunction uaddr - User space address of current running task. EXPERIMENTAL.
*
* Description: Returns the address in userspace that the current
* task was at when the probe occured. When the current running task
* isn't a user space thread, or the address cannot be found, zero
- * is returned.
+ * is returned. Can be used to see where the current task is combined
+ * with usymname() or symdata(). Often the task will be in the VDSO
+ * where it entered the kernel. FIXME - need VDSO tracking support #10080.
*/
function uaddr:long () %{ /* pure */
int64_t addr = 0;
diff --git a/tapsets.cxx b/tapsets.cxx
index 40d4e901..fd991787 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -668,6 +668,15 @@ enum line_t { ABSOLUTE, RELATIVE, RANGE, WILDCARD };
typedef vector<inline_instance_info> inline_instance_map_t;
typedef vector<func_info> func_info_map_t;
+
+// PR 9941 introduces the need for a predicate
+
+int dwfl_report_offline_predicate (const char* modname, const char* filename)
+{
+ if (pending_interrupts) { return -1; }
+ return 1;
+}
+
struct dwflpp
{
systemtap_session & sess;
@@ -946,7 +955,7 @@ struct dwflpp
int rc = dwfl_linux_kernel_report_offline (dwfl,
elfutils_kernel_path.c_str(),
- NULL);
+ &dwfl_report_offline_predicate);
if (debuginfo_needed)
dwfl_assert (string("missing ") + sess.architecture +
diff --git a/tapsets.h b/tapsets.h
index 7165244b..406a69d9 100644
--- a/tapsets.h
+++ b/tapsets.h
@@ -17,6 +17,7 @@ struct derived_probe_group;
void register_standard_tapsets(systemtap_session& sess);
std::vector<derived_probe_group*> all_session_groups(systemtap_session& s);
+int dwfl_report_offline_predicate (const char* modname, const char* filename);
#endif // TAPSETS_H
diff --git a/testsuite/systemtap.base/flightrec1.exp b/testsuite/systemtap.base/flightrec1.exp
new file mode 100644
index 00000000..c32a77f2
--- /dev/null
+++ b/testsuite/systemtap.base/flightrec1.exp
@@ -0,0 +1,43 @@
+set test "flightrec1"
+if {![installtest_p]} { untested $test; return }
+
+# run stapio in background mode
+spawn stap -F -o $test.out -we {probe begin {}}
+# check whether stap outputs stapio pid
+set pid 0
+expect {
+ -timeout 240
+ -re {([0-9]+)\r\n} {
+ pass "$test (flight recorder option)"
+ set pid $expect_out(1,string)
+ exp_continue}
+ timeout { fail "$test (timeout)" }
+ eof { }
+}
+wait
+if {$pid == 0} {
+ fail "$test (no pid)"
+ return -1
+}
+
+# check whether stapio is running in background
+spawn ps -o cmd hc $pid
+expect {
+ -timeout 10
+ "stapio" {pass "$test (stapio in background)"} # don't contine
+ timeout { fail "$test (timeout)"}
+ eof { fail "$test (stapio was not found)" }
+}
+wait
+
+exec kill -TERM $pid
+
+# check output file
+if {[catch {exec rm $test.out}]} {
+ fail "$test (no output file)"
+ return -1
+} else {
+ pass "$test (output file)"
+}
+
+
diff --git a/testsuite/systemtap.base/flightrec2.exp b/testsuite/systemtap.base/flightrec2.exp
new file mode 100644
index 00000000..a22ef415
--- /dev/null
+++ b/testsuite/systemtap.base/flightrec2.exp
@@ -0,0 +1,69 @@
+set test "flightrec2"
+if {![installtest_p]} { untested $test; return }
+
+# cleanup
+system "rm -f flightlog.out*"
+
+set pid 0
+# check -S option
+spawn stap -F -o flightlog.out -S 1,3 $srcdir/$subdir/$test.stp
+expect {
+ -timeout 240
+ -re {([0-9]+)\r\n} {
+ pass "$test (-S option)"
+ set pid $expect_out(1,string)
+ exp_continue}
+ timeout { fail "$test (timeout)"}
+ eof { }
+}
+wait
+if {$pid == 0} {
+ fail "$test (no pid)"
+ return -1
+}
+
+exec sleep 4
+set scnt 0
+set cnt1 0
+# wait for log files
+spawn ls -sk1
+expect {
+ -timeout 100
+ -re {([0-9]+) flightlog\.out\.[0-9]+} {
+ incr cnt1;
+ if {$expect_out(1,string) <= 1028} {incr scnt}
+ # 1024 + 4(for inode blocks?)
+ exp_continue}
+ timeout { fail "$test (logfile timeout)"}
+}
+wait
+exec sleep 3
+set cnt2 0
+# wait for log files
+spawn ls -sk1
+expect {
+ -timeout 100
+ -re {([0-9]+) flightlog\.out\.[0-9]+} {
+ incr cnt2;
+ if {$expect_out(1,string) <= 1028} {incr scnt}
+ exp_continue}
+ timeout { fail "$test (logfile timeout)"}
+}
+wait
+# check logfile number
+if {$cnt1 == 3 && $cnt2 == 3} {
+ pass "$test (log file numbers limitation)"
+} else {
+ fail "$test (log file numbers ($cnt1, $cnt2))"
+}
+# check logfile size
+if {$scnt == 6} {
+ pass "$test (log file size limitation)"
+} else {
+ fail "$test (log file size ($scnt))"
+}
+exec kill -TERM $pid
+# wait for exiting...
+exec sleep 1
+system "rm -f flightlog.out*"
+
diff --git a/testsuite/systemtap.base/flightrec2.stp b/testsuite/systemtap.base/flightrec2.stp
new file mode 100644
index 00000000..9d745f4b
--- /dev/null
+++ b/testsuite/systemtap.base/flightrec2.stp
@@ -0,0 +1,5 @@
+probe timer.ms(1)
+{
+ for (j = 0; j < 100; j++)
+ printf("1234567890\n")
+}
diff --git a/testsuite/systemtap.base/kprobes.exp b/testsuite/systemtap.base/kprobes.exp
index 240ecd82..635930f8 100644
--- a/testsuite/systemtap.base/kprobes.exp
+++ b/testsuite/systemtap.base/kprobes.exp
@@ -1,2 +1,2 @@
set test "kprobes"
-stap_run $srcdir/$subdir/$test.stp
+stap_run $srcdir/$subdir/$test.stp no_load "probe point hit"
diff --git a/testsuite/systemtap.base/kprobes.stp b/testsuite/systemtap.base/kprobes.stp
index 62c18347..884b321c 100644
--- a/testsuite/systemtap.base/kprobes.stp
+++ b/testsuite/systemtap.base/kprobes.stp
@@ -3,19 +3,23 @@
* Probe to test the functionality of kprobe-based probes
* (Dwarfless Probing)
*/
+global hit_str
probe begin
{
- println("\n Systemtap starting probe");
+ println("systemtap starting probe");
+ hit_str = ""
}
probe kprobe.function("vfs_read")
{
- printf("\n probe point hit");
+ hit_str = "probe point hit"
exit();
}
probe end
{
- println("\n Systemtap starting probe");
+ println("systemtap ending probe");
+ println(hit_str);
+ delete hit_str;
}
diff --git a/testsuite/systemtap.base/strftime.exp b/testsuite/systemtap.base/strftime.exp
new file mode 100644
index 00000000..ad9e471d
--- /dev/null
+++ b/testsuite/systemtap.base/strftime.exp
@@ -0,0 +1,49 @@
+set test "strftime"
+if {![installtest_p]} { untested $test; return }
+# cleanup
+system "rm -f %*"
+
+# check %S and %T
+set format %%%S_%T
+exec stap -o $format -we {probe begin {println("hello");exit()}}
+
+spawn ls -1
+set ok 0
+expect {
+ -re {%([0-9][0-9])_[0-9][0-9]:[0-9][0-9]:\1} {incr ok}
+ eof { }
+}
+wait
+
+if {$ok == 1} {
+ pass "$test (%S and %T)"
+} else {
+ fail "$test (%S and %T)"
+}
+
+# check except for %S and %T
+set format %%,%C,%Y,%y,%m,%d,%e,%F,%H,%I,%j,%k,%l,%M,%R,%u,%w
+
+set date1 [exec date +$format]
+# run stapio with strftime
+exec stap -o $format -we {probe begin {println("hello");exit()}}
+# check whether stap outputs stapio pid
+set date2 [exec date +$format]
+
+spawn ls -1
+set ok 0
+expect {
+ $date1 {incr ok}
+ $date2 {incr ok}
+ eof { }
+}
+wait
+
+if {$ok == 1} {
+ pass "$test (except %S and %T)"
+} else {
+ fail "$test (except %S and %T)"
+}
+
+# cleanup
+system "rm -f %*"
diff --git a/translate.cxx b/translate.cxx
index b704b3a6..0423d4ce 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -4901,7 +4901,7 @@ emit_symbol_data (systemtap_session& s)
int rc = dwfl_linux_kernel_report_offline (dwfl,
elfutils_kernel_path.c_str(),
- NULL /* XXX: filtering callback */);
+ &dwfl_report_offline_predicate);
dwfl_report_end (dwfl, NULL, NULL);
if (rc == 0) // tolerate missing data; will warn user about it anyway
{