summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Brolley <brolley@redhat.com>2009-04-22 11:57:40 -0400
committerDave Brolley <brolley@redhat.com>2009-04-22 11:57:40 -0400
commitbc815e0692536da04956f038f5f79941579f8d74 (patch)
tree98b0f8cfdd90c225f5b5fede18352caee5d9a546
parent88e8da383e47adafc9e75c4f10aecd0ce4ad959f (diff)
parent247f1e1fa09953347a4e5313ae0022f151316dae (diff)
downloadsystemtap-steved-bc815e0692536da04956f038f5f79941579f8d74.tar.gz
systemtap-steved-bc815e0692536da04956f038f5f79941579f8d74.tar.xz
systemtap-steved-bc815e0692536da04956f038f5f79941579f8d74.zip
Merge branch 'master' of git://sources.redhat.com/git/systemtap
-rw-r--r--NEWS5
-rw-r--r--buildrun.cxx54
-rw-r--r--buildrun.h6
-rw-r--r--includes/sys/sdt.h26
-rw-r--r--runtime/stack-arm.c3
-rw-r--r--runtime/stack-i386.c25
-rw-r--r--runtime/stack-ia64.c3
-rw-r--r--runtime/stack-ppc64.c3
-rw-r--r--runtime/stack-s390.c3
-rw-r--r--runtime/stack-x86_64.c23
-rw-r--r--runtime/stack.c34
-rw-r--r--runtime/sym.c31
-rw-r--r--runtime/unwind.c22
-rw-r--r--runtime/uprobes2/uprobes.c3
-rw-r--r--stap.1.in9
-rw-r--r--stapprobes.3stap.in42
-rw-r--r--tapset/context-symbols.stp4
-rw-r--r--tapset/context-unwind.stp4
-rw-r--r--tapset/ucontext-symbols.stp27
-rw-r--r--tapset/ucontext-unwind.stp52
-rw-r--r--tapsets.cxx40
-rwxr-xr-xtestsuite/buildok/ustack.stp10
-rwxr-xr-xtestsuite/parseko/utrace01.stp2
-rwxr-xr-xtestsuite/semko/utrace01.stp4
-rwxr-xr-xtestsuite/semko/utrace03.stp2
-rwxr-xr-xtestsuite/semko/utrace04.stp4
-rwxr-xr-xtestsuite/semko/utrace08.stp4
-rwxr-xr-xtestsuite/semko/utrace09.stp4
-rwxr-xr-xtestsuite/semko/utrace10.stp4
-rwxr-xr-xtestsuite/semko/utrace11.stp4
-rwxr-xr-xtestsuite/semko/utrace12.stp4
-rwxr-xr-xtestsuite/semko/utrace13.stp4
-rwxr-xr-xtestsuite/semok/cast.stp4
-rwxr-xr-xtestsuite/semok/utrace01.stp4
-rw-r--r--testsuite/systemtap.base/cast.stp4
-rw-r--r--testsuite/systemtap.base/uprobes_ustack.exp97
-rw-r--r--testsuite/systemtap.base/uprobes_ustack.stp35
-rw-r--r--testsuite/systemtap.context/backtrace.tcl1
-rw-r--r--testsuite/systemtap.examples/index.html2
-rw-r--r--testsuite/systemtap.examples/index.txt2
-rw-r--r--testsuite/systemtap.examples/keyword-index.html2
-rw-r--r--testsuite/systemtap.examples/keyword-index.txt2
-rw-r--r--testsuite/systemtap.examples/process/sigmon.meta4
-rw-r--r--translate.cxx6
44 files changed, 462 insertions, 166 deletions
diff --git a/NEWS b/NEWS
index 2a713ba6..8ec00f2b 100644
--- a/NEWS
+++ b/NEWS
@@ -1,5 +1,10 @@
* What's new
+- @cast can now determine its type information using an explicit header
+ specification. For example:
+ @cast(tv, "timeval", "<sys/time.h>")->tv_sec
+ @cast(task, "task_struct", "kernel<linux/sched.h>")->tgid
+
- The overlapping process.* tapsets are now separated. Those probe points
documented in stapprobes(3stap) remain the same. Those that were formerly
in stapprobes.process(3stap) have been renamed to kprocess, to reflect
diff --git a/buildrun.cxx b/buildrun.cxx
index 3814013f..30a602b3 100644
--- a/buildrun.cxx
+++ b/buildrun.cxx
@@ -381,7 +381,8 @@ make_tracequery(systemtap_session& s, string& name, const vector<string>& extra_
// create a simple Makefile
string makefile(dir + "/Makefile");
ofstream omf(makefile.c_str());
- omf << "EXTRA_CFLAGS := -g" << endl; // force debuginfo generation
+ // force debuginfo generation, and relax implicit functions
+ omf << "EXTRA_CFLAGS := -g -Wno-implicit-function-declaration" << endl;
omf << "obj-m := tracequery.o" << endl;
omf.close();
@@ -401,10 +402,6 @@ make_tracequery(systemtap_session& s, string& name, const vector<string>& extra_
osrc << "#define DEFINE_TRACE(name, proto, args) \\" << endl;
osrc << " DECLARE_TRACE(name, TPPROTO(proto), TPARGS(args))" << endl;
- // some headers may have been pulled in already indirectly, so we need this
- // to ensure that they still use our definition
- osrc << "#define TRACE_HEADER_MULTI_READ 1" << endl;
-
// PR9993: Add extra headers to work around undeclared types in individual
// include/trace/foo.h files
for (unsigned z=0; z<extra_headers.size(); z++)
@@ -456,7 +453,7 @@ make_tracequery(systemtap_session& s, string& name, const vector<string>& extra_
// Build a tiny kernel module to query type information
-int
+static int
make_typequery_kmod(systemtap_session& s, const string& header, string& name)
{
static unsigned tick = 0;
@@ -477,7 +474,16 @@ make_typequery_kmod(systemtap_session& s, const string& header, string& name)
string makefile(dir + "/Makefile");
ofstream omf(makefile.c_str());
omf << "EXTRA_CFLAGS := -g -fno-eliminate-unused-debug-types" << endl;
+
+ // NB: We use -include instead of #include because that gives us more power.
+ // Using #include searches relative to the source's path, which in this case
+ // is /tmp/..., so that's not helpful. Using -include will search relative
+ // to the cwd, which will be the kernel build root. This means if you have a
+ // full kernel build tree, it's possible to get at types that aren't in the
+ // normal include path, e.g.:
+ // @cast(foo, "bsd_acct_struct", "kernel<kernel/acct.c>")->...
omf << "CFLAGS_" << basename << ".o := -include " << header << endl;
+
omf << "obj-m := " + basename + ".o" << endl;
omf.close();
@@ -496,7 +502,7 @@ make_typequery_kmod(systemtap_session& s, const string& header, string& name)
// Build a tiny user module to query type information
-int
+static int
make_typequery_umod(systemtap_session& s, const string& header, string& name)
{
static unsigned tick = 0;
@@ -504,6 +510,11 @@ make_typequery_umod(systemtap_session& s, const string& header, string& name)
name = s.tmpdir + "/typequery_umod_" + lex_cast<string>(++tick) + ".so";
// make the module
+ //
+ // NB: As with kmod, using -include makes relative paths more useful. The
+ // cwd in this case will be the cwd of stap itself though, which may be
+ // trickier to deal with. It might be better to "cd `dirname $script`"
+ // first...
string cmd = "gcc -shared -g -fno-eliminate-unused-debug-types -o "
+ name + " -xc /dev/null -include " + header;
if (s.verbose < 4)
@@ -511,4 +522,33 @@ make_typequery_umod(systemtap_session& s, const string& header, string& name)
return stap_system (cmd.c_str());
}
+
+int
+make_typequery(systemtap_session& s, string& module)
+{
+ int rc;
+ string new_module;
+
+ if (module[module.size() - 1] != '>')
+ return -1;
+
+ if (module[0] == '<')
+ {
+ string header = module.substr(1, module.size() - 2);
+ rc = make_typequery_umod(s, header, new_module);
+ }
+ else if (module.compare(0, 7, "kernel<") == 0)
+ {
+ string header = module.substr(7, module.size() - 8);
+ rc = make_typequery_kmod(s, header, new_module);
+ }
+ else
+ return -1;
+
+ if (!rc)
+ module = new_module;
+
+ return rc;
+}
+
/* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */
diff --git a/buildrun.h b/buildrun.h
index fb33b4c8..7fa4ccfc 100644
--- a/buildrun.h
+++ b/buildrun.h
@@ -14,9 +14,9 @@
int compile_pass (systemtap_session& s);
int run_pass (systemtap_session& s);
-int make_tracequery(systemtap_session& s, std::string& name, const std::vector<std::string>& extra_headers);
-int make_typequery_kmod(systemtap_session& s, const std::string& header, std::string& name);
-int make_typequery_umod(systemtap_session& s, const std::string& header, std::string& name);
+int make_tracequery(systemtap_session& s, std::string& name,
+ const std::vector<std::string>& extra_headers);
+int make_typequery(systemtap_session& s, std::string& module);
#endif // BUILDRUN_H
diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h
index c3fa16d9..e5265ff1 100644
--- a/includes/sys/sdt.h
+++ b/includes/sys/sdt.h
@@ -20,9 +20,9 @@
"\t.align 4\n" \
"\t.int 0x31425250\n" \
"\t.align 8\n" \
- "\t.long 1b\n" \
+ "\t.quad 1b\n" \
"\t.align 8\n" \
- "\t.long 2f\n" \
+ "\t.quad 2f\n" \
"\t.previous\n")
#define STAP_PROBE_DATA(probe) \
@@ -56,7 +56,7 @@
do { \
STAP_PROBE_DATA(probe); \
__asm__ volatile ("2:\n" \
- "\tnop"); \
+ "\tnop 0"); \
} while (0)
#define STAP_PROBE1_(probe,label,parm1) \
@@ -67,7 +67,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop /* %0 */" :: "g"(arg1)); \
+ "\tnop 0 /* %0 */" :: "g"(arg1)); \
} while (0)
#define STAP_PROBE2_(probe,label,parm1,parm2) \
@@ -79,7 +79,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop /* %0 %1 */" :: "g"(arg1), "g"(arg2)); \
+ "\tnop 0 /* %0 %1 */" :: "g"(arg1), "g"(arg2)); \
} while (0)
#define STAP_PROBE3_(probe,label,parm1,parm2,parm3) \
@@ -92,7 +92,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop /* %0 %1 %2 */" :: "g"(arg1), "g"(arg2), "g"(arg3)); \
+ "\tnop 0 /* %0 %1 %2 */" :: "g"(arg1), "g"(arg2), "g"(arg3)); \
} while (0)
#define STAP_PROBE4_(probe,label,parm1,parm2,parm3,parm4) \
@@ -106,7 +106,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop /* %0 %1 %2 %3 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4)); \
+ "\tnop 0 /* %0 %1 %2 %3 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4)); \
} while (0)
#define STAP_PROBE5_(probe,label,parm1,parm2,parm3,parm4,parm5) \
@@ -121,7 +121,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop /* %0 %1 %2 %3 %4 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5)); \
+ "\tnop 0 /* %0 %1 %2 %3 %4 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5)); \
} while (0)
#define STAP_PROBE6_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6) \
@@ -137,7 +137,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop /* %0 %1 %2 %3 %4 %5 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6)); \
+ "\tnop 0 /* %0 %1 %2 %3 %4 %5 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6)); \
} while (0)
#define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \
@@ -154,7 +154,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop /* %0 %1 %2 %3 %4 %5 %6 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7)); \
+ "\tnop 0 /* %0 %1 %2 %3 %4 %5 %6 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7)); \
} while (0)
#define STAP_PROBE8_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \
@@ -172,7 +172,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8)); \
+ "\tnop 0 /* %0 %1 %2 %3 %4 %5 %6 %7 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8)); \
} while (0)
#define STAP_PROBE9_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \
@@ -191,7 +191,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 %8 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8), "g"(arg9)); \
+ "\tnop 0 /* %0 %1 %2 %3 %4 %5 %6 %7 %8 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8), "g"(arg9)); \
} while (0)
#define STAP_PROBE10_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \
@@ -211,7 +211,7 @@ do { \
STAP_PROBE_DATA(probe); \
label: \
__asm__ volatile ("2:\n" \
- "\tnop /* %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8), "g"(arg9), "g"(arg10)); \
+ "\tnop 0 /* %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8), "g"(arg9), "g"(arg10)); \
} while (0)
#define STAP_PROBE(provider,probe) \
diff --git a/runtime/stack-arm.c b/runtime/stack-arm.c
index 9b0b772d..fcff0a3b 100644
--- a/runtime/stack-arm.c
+++ b/runtime/stack-arm.c
@@ -31,7 +31,8 @@ static int __init find_str_pc_offset(void)
}
-static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
+static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels,
+ struct task_struct *tsk)
{
#ifdef STP_USE_FRAME_POINTER
int pc_offset = find_str_pc_offset();
diff --git a/runtime/stack-i386.c b/runtime/stack-i386.c
index 5a18c9d8..69623765 100644
--- a/runtime/stack-i386.c
+++ b/runtime/stack-i386.c
@@ -23,14 +23,15 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose, int leve
/* cannot access stack. give up. */
return;
}
- if (_stp_func_print(addr, verbose, 0))
+ if (_stp_func_print(addr, verbose, 0, NULL))
levels--;
stack++;
}
}
#endif
-static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
+static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels,
+ struct task_struct *tsk)
{
unsigned long context = (unsigned long)&REG_SP(regs) & ~(THREAD_SIZE - 1);
@@ -43,7 +44,7 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
/* cannot access stack. give up. */
return;
}
- _stp_func_print(addr, verbose, 1);
+ _stp_func_print(addr, verbose, 1, NULL);
if (unlikely(_stp_read_address(next_fp, (unsigned long *)fp, KERNEL_DS))) {
/* cannot access stack. give up. */
return;
@@ -60,19 +61,23 @@ static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
struct unwind_frame_info info;
arch_unw_init_frame_info(&info, regs);
- while (levels && !arch_unw_user_mode(&info)) {
- int ret = unwind(&info);
+ while (levels && (tsk || !arch_unw_user_mode(&info))) {
+ int ret = unwind(&info, tsk);
dbug_unwind(1, "ret=%d PC=%lx SP=%lx\n", ret, UNW_PC(&info), UNW_SP(&info));
if (ret == 0) {
- _stp_func_print(UNW_PC(&info), verbose, 1);
+ _stp_func_print(UNW_PC(&info), verbose, 1, tsk);
levels--;
continue;
}
- /* If an error happened or we hit a kretprobe trampoline, use fallback backtrace */
- /* FIXME: is there a way to unwind across kretprobe trampolines? */
- if (ret < 0 || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline))
+ /* If an error happened or we hit a kretprobe trampoline,
+ * use fallback backtrace, unless user task backtrace.
+ * FIXME: is there a way to unwind across kretprobe
+ * trampolines? */
+ if ((ret < 0
+ || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline))
+ && ! (tsk || arch_unw_user_mode(&info)))
_stp_stack_print_fallback(UNW_SP(&info), verbose, levels);
- break;
+ return;
}
#else /* ! STP_USE_DWARF_UNWINDER */
_stp_stack_print_fallback((unsigned long)&REG_SP(regs), verbose, levels);
diff --git a/runtime/stack-ia64.c b/runtime/stack-ia64.c
index ca9d25a6..a04355fa 100644
--- a/runtime/stack-ia64.c
+++ b/runtime/stack-ia64.c
@@ -48,7 +48,8 @@ static void __stp_show_stack_addr(struct unw_frame_info *info, void *arg)
} while (unw_unwind(info) >= 0);
}
-static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
+static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels,
+ struct task_struct *tsk)
{
unsigned long *stack = (unsigned long *)&REG_SP(regs);
struct dump_para para;
diff --git a/runtime/stack-ppc64.c b/runtime/stack-ppc64.c
index 3dc38526..3267194e 100644
--- a/runtime/stack-ppc64.c
+++ b/runtime/stack-ppc64.c
@@ -7,7 +7,8 @@
* later version.
*/
-static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels)
+static void __stp_stack_print (struct pt_regs *regs, int verbose, int levels,
+ struct task_struct *tsk)
{
unsigned long ip, newsp, lr = 0;
int count = 0;
diff --git a/runtime/stack-s390.c b/runtime/stack-s390.c
index c9654102..14e9b7d8 100644
--- a/runtime/stack-s390.c
+++ b/runtime/stack-s390.c
@@ -66,7 +66,8 @@ __stp_show_stack (unsigned long sp, unsigned long low,
}
static void __stp_stack_print (struct pt_regs *regs,
- int verbose, int levels)
+ int verbose, int levels,
+ struct task_struct *tsk)
{
unsigned long *_sp = (unsigned long *)&REG_SP(regs);
unsigned long sp = (unsigned long)_sp;
diff --git a/runtime/stack-x86_64.c b/runtime/stack-x86_64.c
index 03d88ef0..9afdf38a 100644
--- a/runtime/stack-x86_64.c
+++ b/runtime/stack-x86_64.c
@@ -19,7 +19,7 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose, int leve
/* cannot access stack. give up. */
return;
}
- if (_stp_func_print(addr, verbose, 0))
+ if (_stp_func_print(addr, verbose, 0, NULL))
levels--;
stack++;
}
@@ -27,26 +27,31 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose, int leve
#endif
-static void __stp_stack_print(struct pt_regs *regs, int verbose, int levels)
+static void __stp_stack_print(struct pt_regs *regs, int verbose, int levels,
+ struct task_struct *tsk)
{
#ifdef STP_USE_DWARF_UNWINDER
// FIXME: large stack allocation
struct unwind_frame_info info;
arch_unw_init_frame_info(&info, regs);
- while (levels && !arch_unw_user_mode(&info)) {
- int ret = unwind(&info);
+ while (levels && (tsk || !arch_unw_user_mode(&info))) {
+ int ret = unwind(&info, tsk);
dbug_unwind(1, "ret=%d PC=%lx SP=%lx\n", ret, UNW_PC(&info), UNW_SP(&info));
if (ret == 0) {
- _stp_func_print(UNW_PC(&info), verbose, 1);
+ _stp_func_print(UNW_PC(&info), verbose, 1, tsk);
levels--;
continue;
}
- /* If an error happened or we hit a kretprobe trampoline, use fallback backtrace */
- /* FIXME: is there a way to unwind across kretprobe trampolines? */
- if (ret < 0 || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline))
+ /* If an error happened or we hit a kretprobe trampoline,
+ * use fallback backtrace, unless user task backtrace.
+ * FIXME: is there a way to unwind across kretprobe
+ * trampolines? */
+ if ((ret < 0
+ || (ret > 0 && UNW_PC(&info) == _stp_kretprobe_trampoline))
+ && ! (tsk || arch_unw_user_mode(&info)))
_stp_stack_print_fallback(UNW_SP(&info), verbose, levels);
- break;
+ return;
}
#else /* ! STP_USE_DWARF_UNWINDER */
_stp_stack_print_fallback(REG_SP(regs), verbose, levels);
diff --git a/runtime/stack.c b/runtime/stack.c
index 68fb9b1f..042f44c7 100644
--- a/runtime/stack.c
+++ b/runtime/stack.c
@@ -1,6 +1,6 @@
/* -*- linux-c -*-
* Stack tracing functions
- * Copyright (C) 2005-2008 Red Hat Inc.
+ * Copyright (C) 2005-2009 Red Hat Inc.
* Copyright (C) 2005 Intel Corporation.
*
* This file is part of systemtap, and is free software. You can
@@ -77,7 +77,7 @@ static void print_stack_address(void *data, unsigned long addr, int reliable)
{
struct print_stack_data *sdata = data;
if (sdata->level++ < sdata->max_level)
- _stp_func_print(addr,sdata->verbose, 0);
+ _stp_func_print(addr, sdata->verbose, 0, NULL);
}
static const struct stacktrace_ops print_stack_ops = {
@@ -107,7 +107,7 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose, int leve
* @param regs A pointer to the struct pt_regs.
*/
-static void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe_instance *pi, int levels)
+static void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe_instance *pi, int levels, struct task_struct *tsk)
{
if (verbose) {
/* print the current address */
@@ -118,7 +118,10 @@ static void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe
_stp_symbol_print((unsigned long)_stp_ret_addr_r(pi));
} else {
_stp_print_char(' ');
- _stp_symbol_print(REG_IP(regs));
+ if (tsk)
+ _stp_usymbol_print(REG_IP(regs), tsk);
+ else
+ _stp_symbol_print(REG_IP(regs));
}
_stp_print_char('\n');
} else if (pi)
@@ -126,7 +129,7 @@ static void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe
else
_stp_printf("%p ", (int64_t) REG_IP(regs));
- __stp_stack_print(regs, verbose, levels);
+ __stp_stack_print(regs, verbose, levels, tsk);
}
/** Writes stack backtrace to a string
@@ -135,37 +138,20 @@ static void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe
* @param regs A pointer to the struct pt_regs.
* @returns void
*/
-static void _stp_stack_snprint(char *str, int size, struct pt_regs *regs, int verbose, struct kretprobe_instance *pi, int levels)
+static void _stp_stack_snprint(char *str, int size, struct pt_regs *regs, int verbose, struct kretprobe_instance *pi, int levels, struct task_struct *tsk)
{
/* To get a string, we use a simple trick. First flush the print buffer, */
/* then call _stp_stack_print, then copy the result into the output string */
/* and clear the print buffer. */
_stp_pbuf *pb = per_cpu_ptr(Stp_pbuf, smp_processor_id());
_stp_print_flush();
- _stp_stack_print(regs, verbose, pi, levels);
+ _stp_stack_print(regs, verbose, pi, levels, tsk);
strlcpy(str, pb->buf, size < (int)pb->len ? size : (int)pb->len);
pb->len = 0;
}
#endif /* CONFIG_KPROBES */
-/** Prints the user stack backtrace
- * @param str string
- * @returns Same string as was input with trace info appended,
- * @note Currently limited to a depth of two. Works from jprobes and kprobes.
- */
-#if 0
-static void _stp_ustack_print(char *str)
-{
- struct pt_regs *nregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)current->thread_info)) - 1;
- _stp_printf("%p : [user]\n", (int64_t) REG_IP(nregs));
- if (REG_SP(nregs))
- _stp_printf("%p : [user]\n", (int64_t) (*(unsigned long *)REG_SP(nregs)));
-}
-#endif /* 0 */
-
-/** @} */
-
void _stp_stack_print_tsk(struct task_struct *tsk, int verbose, int levels)
{
#if defined(STAPCONF_KERNEL_STACKTRACE)
diff --git a/runtime/sym.c b/runtime/sym.c
index f6f97ac2..013edd0c 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -329,8 +329,35 @@ static void _stp_symbol_print(unsigned long address)
}
}
+/** Print an user space address from a specific task symbolically.
+ * @param address The address to lookup.
+ * @param task The address to lookup.
+ * @note Symbolic lookups should not normally be done within
+ * a probe because it is too time-consuming. Use at module exit time.
+ */
+
+static void _stp_usymbol_print(unsigned long address, struct task_struct *task)
+{
+ const char *modname;
+ const char *name;
+ unsigned long offset, size;
+
+ name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL,
+ task);
+
+ _stp_printf("%p", (int64_t) address);
+
+ if (name) {
+ if (modname && *modname)
+ _stp_printf(" : %s+%#lx/%#lx [%s]", name, offset, size, modname);
+ else
+ _stp_printf(" : %s+%#lx/%#lx", name, offset, size);
+ }
+}
+
/* Like _stp_symbol_print, except only print if the address is a valid function address */
-static int _stp_func_print(unsigned long address, int verbose, int exact)
+static int _stp_func_print(unsigned long address, int verbose, int exact,
+ struct task_struct *task)
{
const char *modname;
const char *name;
@@ -342,7 +369,7 @@ static int _stp_func_print(unsigned long address, int verbose, int exact)
else
exstr = " (inexact)";
- name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, NULL);
+ name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, task);
if (name) {
if (verbose) {
diff --git a/runtime/unwind.c b/runtime/unwind.c
index 41af72a7..aacd56f1 100644
--- a/runtime/unwind.c
+++ b/runtime/unwind.c
@@ -435,12 +435,18 @@ adjustStartLoc (unsigned long startLoc,
struct _stp_module *m,
struct _stp_section *s)
{
- if (startLoc && (strcmp (m->name, "kernel") != 0))
- {
- startLoc = _stp_module_relocate (m->name, s->name,
- startLoc);
- startLoc -= m->dwarf_module_base;
- }
+ /* XXX - some, or all, of this should really be done by
+ _stp_module_relocate. */
+ if (startLoc == 0
+ || strcmp (m->name, "kernel") == 0
+ || strcmp (s->name, ".absolute") == 0)
+ return startLoc;
+
+ if (strcmp (s->name, ".dynamic") == 0)
+ return startLoc + s->addr;
+
+ startLoc = _stp_module_relocate (m->name, s->name, startLoc);
+ startLoc -= m->dwarf_module_base;
return startLoc;
}
@@ -562,7 +568,7 @@ static char *_stp_eh_enc_name(signed type)
/* Unwind to previous to frame. Returns 0 if successful, negative
* number in case of an error. A positive return means unwinding is finished;
* don't try to fallback to dumping addresses on the stack. */
-static int unwind(struct unwind_frame_info *frame)
+static int unwind(struct unwind_frame_info *frame, struct task_struct *tsk)
{
#define FRAME_REG(r, t) (((t *)frame)[reg_info[r].offs])
const u32 *fde, *cie = NULL;
@@ -581,7 +587,7 @@ static int unwind(struct unwind_frame_info *frame)
if (UNW_PC(frame) == 0)
return -EINVAL;
- m = _stp_mod_sec_lookup (pc, current, &s);
+ m = _stp_mod_sec_lookup (pc, tsk, &s);
if (unlikely(m == NULL)) {
dbug_unwind(1, "No module found for pc=%lx", pc);
return -EINVAL;
diff --git a/runtime/uprobes2/uprobes.c b/runtime/uprobes2/uprobes.c
index 9ea05349..07ad3984 100644
--- a/runtime/uprobes2/uprobes.c
+++ b/runtime/uprobes2/uprobes.c
@@ -2239,7 +2239,8 @@ static u32 uprobe_report_exit(enum utrace_resume_action action,
}
}
up_read(&uproc->rwsem);
- if (utask->state == UPTASK_TRAMPOLINE_HIT)
+ if (utask->state == UPTASK_TRAMPOLINE_HIT ||
+ utask->state == UPTASK_BP_HIT)
uprobe_decref_process(uproc);
}
diff --git a/stap.1.in b/stap.1.in
index a5a8ab84..82a62b6d 100644
--- a/stap.1.in
+++ b/stap.1.in
@@ -800,6 +800,15 @@ 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
+The translator can create its own module with type information from a header
+surrounded by angle brackets, in case normal debuginfo is not available. For
+kernel headers, prefix it with "kernel" to use the appropriate build system.
+All other headers are build with default GCC parameters into a user module.
+.SAMPLE
+@cast(tv, "timeval", "<sys/time.h>")->tv_sec
+@cast(task, "task_struct", "kernel<linux/sched.h>")->tgid
+.ESAMPLE
+.PP
When in guru mode, the translator will also allow scripts to assign new
values to members of typecasted pointers.
.PP
diff --git a/stapprobes.3stap.in b/stapprobes.3stap.in
index e60a8fe4..b3066611 100644
--- a/stapprobes.3stap.in
+++ b/stapprobes.3stap.in
@@ -412,10 +412,14 @@ contain wildcards, or the probe will not be registered.
Also, statement probes must be run under guru-mode only.
-
.SS USER-SPACE
-Early prototype support for user-space probing is available in the
-form of a non-symbolic probe point:
+Support for user-space probing is available for kernels
+that are configured with the utrace extensions. See
+.SAMPLE
+http://people.redhat.com/roland/utrace/
+.ESAMPLE
+.PP
+There are several forms. First, a non-symbolic probe point:
.SAMPLE
process(PID).statement(ADDRESS).absolute
.ESAMPLE
@@ -427,7 +431,8 @@ no $variables. The target PID parameter must identify a running
process, and ADDRESS should identify a valid instruction address.
All threads of that process will be probed.
.PP
-Additional user-space probing is available in the following forms:
+Second, non-symbolic user-kernel interface events handled by
+utrace may be probed:
.SAMPLE
process(PID).begin
process("PATH").begin
@@ -451,7 +456,6 @@ process(PID).insn
process("PATH").insn
process(PID).insn.block
process("PATH").insn.block
-process("PATH").mark("LABEL")
.ESAMPLE
.PP
A
@@ -490,6 +494,15 @@ probe gets called for every single-stepped instruction of the process described
A
.B .insn.block
probe gets called for every block-stepped instruction of the process described by PID or PATH.
+
+.PP
+Third, symbolic static instrumentation compiled into programs and
+shared libraries may be
+probed:
+.SAMPLE
+process("PATH").mark("LABEL")
+.ESAMPLE
+.PP
A
.B .mark
probe gets called via a static probe which is defined in the
@@ -501,14 +514,29 @@ for probes with 2 arguments, and so on.
The arguments of the probe are available in the context variables
$arg1, $arg2, ... An alternative to using the STAP_PROBE macros is to
use the dtrace script to create custom macros.
+
.PP
-Note that
+Finally, full symbolic source-level probes in user-space programs
+and shared libraries are supported. These are exactly analogous
+to the symbolic DWARF-based kernel/module probes described above,
+and expose similar contextual $-variables.
+.SAMPLE
+process("PATH").function("NAME")
+process("PATH").statement("*@FILE.c:123")
+process("PATH").function("*").return
+process("PATH").function("myfun").label("foo")
+.ESAMPLE
+
+.PP
+Note that for all process probes,
.I PATH
names refer to executables that are searched the same way shells do: relative
to the working directory if they contain a "/" character, otherwise in
.BR $PATH .
If a process probe is specified without a PID or PATH, all user
-threads are probed.
+threads are probed. PATH may sometimes name a shared library
+in which case all processes that map that shared library may be
+probed.
.SS PROCFS
diff --git a/tapset/context-symbols.stp b/tapset/context-symbols.stp
index 783f1b7b..e4406d9b 100644
--- a/tapset/context-symbols.stp
+++ b/tapset/context-symbols.stp
@@ -16,10 +16,10 @@
#define STP_NEED_SYMBOL_DATA 1
#endif
%}
-// weirdness with print_stack, argument appears in build as undescribed
+
/**
* sfunction print_stack - Print out stack from string.
- * @stk: String with list of hexidecimal addresses. (FIXME)
+ * @stk: String with list of hexidecimal addresses.
*
* Perform a symbolic lookup of the addresses in the given string,
* which is assumed to be the result of a prior call to
diff --git a/tapset/context-unwind.stp b/tapset/context-unwind.stp
index b3d19e29..f1e99dc8 100644
--- a/tapset/context-unwind.stp
+++ b/tapset/context-unwind.stp
@@ -28,7 +28,7 @@
*/
function print_backtrace () %{
if (CONTEXT->regs) {
- _stp_stack_print(CONTEXT->regs, 1, CONTEXT->pi, MAXTRACE);
+ _stp_stack_print(CONTEXT->regs, 1, CONTEXT->pi, MAXTRACE, NULL);
} else {
_stp_printf("Systemtap probe: %s\n", CONTEXT->probe_point);
}
@@ -42,7 +42,7 @@ function print_backtrace () %{
*/
function backtrace:string () %{ /* pure */
if (CONTEXT->regs)
- _stp_stack_snprint (THIS->__retvalue, MAXSTRINGLEN, CONTEXT->regs, 0, CONTEXT->pi, MAXTRACE);
+ _stp_stack_snprint (THIS->__retvalue, MAXSTRINGLEN, CONTEXT->regs, 0, CONTEXT->pi, MAXTRACE, NULL);
else
strlcpy (THIS->__retvalue, "", MAXSTRINGLEN);
%}
diff --git a/tapset/ucontext-symbols.stp b/tapset/ucontext-symbols.stp
index 3813a8bf..5502f5cd 100644
--- a/tapset/ucontext-symbols.stp
+++ b/tapset/ucontext-symbols.stp
@@ -23,7 +23,7 @@
%}
/**
- * sfunction usymname - Return the symbol of an address in the current task.
+ * sfunction usymname - Return the symbol of an address in the current task. EXPERIMENTAL!
* @addr: The address to translate.
*
* Description: Returns the (function) symbol name associated with the
@@ -36,7 +36,7 @@ function usymname:string (addr: long) %{ /* pure */
%}
/**
- * sfunction usymdata - Return the symbol and module offset of an address.
+ * sfunction usymdata - Return the symbol and module offset of an address. EXPERIMENTAL!
* @addr: The address to translate.
*
* Description: Returns the (function) symbol name associated with the
@@ -50,3 +50,26 @@ function usymdata:string (addr: long) %{ /* pure */
_stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr,
current, 1);
%}
+
+/**
+ * sfunction print_ustack - Print out stack for the current task from string. EXPERIMENTAL!
+ * @stk: String with list of hexidecimal addresses for the current task.
+ *
+ * Perform a symbolic lookup of the addresses in the given string,
+ * which is assumed to be the result of a prior call to
+ * <command>ubacktrace()</command> for the current task.
+ *
+ * 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.
+ */
+function print_ustack(stk:string) %{
+ char *ptr = THIS->stk;
+ char *tok = strsep(&ptr, " ");
+ while (tok && *tok) {
+ _stp_print_char(' ');
+ _stp_usymbol_print (simple_strtol(tok, NULL, 16), current);
+ _stp_print_char('\n');
+ tok = strsep(&ptr, " ");
+ }
+%}
diff --git a/tapset/ucontext-unwind.stp b/tapset/ucontext-unwind.stp
new file mode 100644
index 00000000..0801f1c9
--- /dev/null
+++ b/tapset/ucontext-unwind.stp
@@ -0,0 +1,52 @@
+// User context unwind tapset
+// 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
+// Public License (GPL); either version 2, or (at your option) any
+// later version.
+
+%{
+#ifndef STP_NEED_UNWIND_DATA
+#define STP_NEED_UNWIND_DATA 1
+#endif
+#ifndef STP_NEED_SYMBOL_DATA
+#define STP_NEED_SYMBOL_DATA 1
+#endif
+#ifndef STP_NEED_VMA_TRACKER
+#define STP_NEED_VMA_TRACKER 1
+#endif
+%}
+
+/**
+ * sfunction print_ubacktrace - Print stack back trace for current task. EXPERIMENTAL!
+ *
+ * Equivalent to <command>print_ustack(ubacktrace())</command>,
+ * except that deeper stack nesting may be supported. Return nothing.
+ */
+function print_ubacktrace () %{
+ if (CONTEXT->regs) {
+ _stp_stack_print(CONTEXT->regs, 1, CONTEXT->pi, MAXTRACE,
+ current);
+ } else {
+ _stp_printf("Systemtap probe: %s\n", CONTEXT->probe_point);
+ }
+%}
+
+/**
+ * sfunction ubacktrace - Hex backtrace of current task stack. EXPERIMENTAL!
+ *
+ * Return a string of hex addresses that are a backtrace of the
+ * stack of the current task. Output may be truncated as per maximum
+ * string length. Returns empty string when current probe point cannot
+ * determine user backtrace.
+ */
+
+function ubacktrace:string () %{ /* pure */
+ if (CONTEXT->regs)
+ _stp_stack_snprint (THIS->__retvalue, MAXSTRINGLEN,
+ CONTEXT->regs, 0, CONTEXT->pi, MAXTRACE,
+ current);
+ else
+ strlcpy (THIS->__retvalue, "", MAXSTRINGLEN);
+%}
diff --git a/tapsets.cxx b/tapsets.cxx
index deb9044c..a46512fc 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -5143,11 +5143,10 @@ struct dwarf_cast_expanding_visitor: public var_expanding_visitor
void dwarf_cast_expanding_visitor::filter_special_modules(string& module)
{
- // look for "kmod<path/to/header>" or "umod<path/to/header>"
+ // look for "<path/to/header>" or "kernel<path/to/header>"
// for those cases, build a module including that header
- if (module.rfind('>') == module.size() - 1 &&
- (module.compare(0, 5, "kmod<") == 0 ||
- module.compare(0, 5, "umod<") == 0))
+ if (module[module.size() - 1] == '>' &&
+ (module[0] == '<' || module.compare(0, 7, "kernel<") == 0))
{
string cached_module;
if (s.use_cache)
@@ -5169,25 +5168,17 @@ void dwarf_cast_expanding_visitor::filter_special_modules(string& module)
}
// no cached module, time to make it
- int rc;
- string new_module, header = module.substr(5, module.size() - 6);
- if (module[0] == 'k')
- rc = make_typequery_kmod(s, header, new_module);
- else
- rc = make_typequery_umod(s, header, new_module);
- if (rc == 0)
+ if (make_typequery(s, module) == 0)
{
- module = new_module;
-
if (s.use_cache)
{
// try to save typequery in the cache
if (s.verbose > 2)
- clog << "Copying " << new_module
+ clog << "Copying " << module
<< " to " << cached_module << endl;
- if (copy_file(new_module.c_str(),
+ if (copy_file(module.c_str(),
cached_module.c_str()) != 0)
- cerr << "Copy failed (\"" << new_module << "\" to \""
+ cerr << "Copy failed (\"" << module << "\" to \""
<< cached_module << "\"): " << strerror(errno) << endl;
}
}
@@ -5206,13 +5197,13 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e)
string code;
exp_type type = pe_long;
- size_t mod_end = ~0;
- do
+
+ // split the module string by ':' for alternatives
+ vector<string> modules;
+ tokenize(e->module, modules, ":");
+ for (unsigned i = 0; code.empty() && i < modules.size(); ++i)
{
- // 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 - mod_begin);
+ string& module = modules[i];
filter_special_modules(module);
// NB: This uses '/' to distinguish between kernel modules and userspace,
@@ -5267,7 +5258,6 @@ void dwarf_cast_expanding_visitor::visit_cast_op (cast_op* e)
dwarf_cast_query q (*dw, module, *e, lvalue, type, code);
dw->query_modules(&q);
}
- while (code.empty() && mod_end != string::npos);
if (code.empty())
{
@@ -5993,7 +5983,7 @@ dwarf_builder::build(systemtap_session & sess,
if (probe_scn_offset % (sizeof(__uint64_t)))
probe_scn_offset += sizeof(__uint64_t) - (probe_scn_offset % sizeof(__uint64_t));
- probe_name = ((char*)((long)(pdata->d_buf) + (long)(*((int*)((long)pdata->d_buf + probe_scn_offset)) - probe_scn_addr)));
+ probe_name = ((char*)((long)(pdata->d_buf) + (long)(*((long*)((char*)pdata->d_buf + probe_scn_offset)) - probe_scn_addr)));
probe_scn_offset += sizeof(void*);
if (probe_scn_offset % (sizeof(__uint64_t)))
probe_scn_offset += sizeof(__uint64_t) - (probe_scn_offset % sizeof(__uint64_t));
@@ -6012,7 +6002,7 @@ dwarf_builder::build(systemtap_session & sess,
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 = new literal_number((long)probe_arg);
location->components[1]->arg->tok = sv_tok;
((literal_map_t&)parameters)[TOK_STATEMENT] = location->components[1]->arg;
diff --git a/testsuite/buildok/ustack.stp b/testsuite/buildok/ustack.stp
new file mode 100755
index 00000000..23af0bff
--- /dev/null
+++ b/testsuite/buildok/ustack.stp
@@ -0,0 +1,10 @@
+#! stap -p4
+#
+# Test the translatability for ubacktrace(), print_ustack()
+# and print_ubacktrace()
+#
+probe begin
+{
+ print_ustack(ubacktrace());
+ print_ubacktrace();
+}
diff --git a/testsuite/parseko/utrace01.stp b/testsuite/parseko/utrace01.stp
index 1cb4227f..9f3619b5 100755
--- a/testsuite/parseko/utrace01.stp
+++ b/testsuite/parseko/utrace01.stp
@@ -1,4 +1,4 @@
#! stap -p2
# process NAME must be a string
-probe process(/bin/cat).death { }
+probe process(/bin/cat).end { }
diff --git a/testsuite/semko/utrace01.stp b/testsuite/semko/utrace01.stp
deleted file mode 100755
index a4707008..00000000
--- a/testsuite/semko/utrace01.stp
+++ /dev/null
@@ -1,4 +0,0 @@
-#! stap -p2
-
-# missing process NAME|PID
-probe process.death { }
diff --git a/testsuite/semko/utrace03.stp b/testsuite/semko/utrace03.stp
index c682410b..92177ffd 100755
--- a/testsuite/semko/utrace03.stp
+++ b/testsuite/semko/utrace03.stp
@@ -1,4 +1,4 @@
#! stap -p2
# invalid probe type
-probe process("/bin/cat").death.return { }
+probe process("/bin/cat").end.return { }
diff --git a/testsuite/semko/utrace04.stp b/testsuite/semko/utrace04.stp
index 6345f9f6..1d26a43c 100755
--- a/testsuite/semko/utrace04.stp
+++ b/testsuite/semko/utrace04.stp
@@ -1,4 +1,4 @@
#! stap -p2
-# death probes don't support target symbols
-probe process("/bin/cat").death.return { print($syscall) }
+# end probes don't support target symbols
+probe process("/bin/cat").end { print($syscall) }
diff --git a/testsuite/semko/utrace08.stp b/testsuite/semko/utrace08.stp
deleted file mode 100755
index a558a5be..00000000
--- a/testsuite/semko/utrace08.stp
+++ /dev/null
@@ -1,4 +0,0 @@
-#! stap -p2
-
-# process path must be absolute
-probe process("cat").death { }
diff --git a/testsuite/semko/utrace09.stp b/testsuite/semko/utrace09.stp
deleted file mode 100755
index 60c49cd2..00000000
--- a/testsuite/semko/utrace09.stp
+++ /dev/null
@@ -1,4 +0,0 @@
-#! stap -p2
-
-# process path must be absolute
-probe process("/foo/../bar").death { }
diff --git a/testsuite/semko/utrace10.stp b/testsuite/semko/utrace10.stp
deleted file mode 100755
index b46baea9..00000000
--- a/testsuite/semko/utrace10.stp
+++ /dev/null
@@ -1,4 +0,0 @@
-#! stap -p2
-
-# path can't contain an empty component
-probe process("/foo//bar").death { }
diff --git a/testsuite/semko/utrace11.stp b/testsuite/semko/utrace11.stp
deleted file mode 100755
index d78b602c..00000000
--- a/testsuite/semko/utrace11.stp
+++ /dev/null
@@ -1,4 +0,0 @@
-#! stap -p2
-
-# path can't end with '/'
-probe process("/foo/bar/").death { }
diff --git a/testsuite/semko/utrace12.stp b/testsuite/semko/utrace12.stp
deleted file mode 100755
index 478aa1d3..00000000
--- a/testsuite/semko/utrace12.stp
+++ /dev/null
@@ -1,4 +0,0 @@
-#! stap -p2
-
-# path can't end with '.'
-probe process("/foo/bar/.").death { }
diff --git a/testsuite/semko/utrace13.stp b/testsuite/semko/utrace13.stp
deleted file mode 100755
index 16cc0391..00000000
--- a/testsuite/semko/utrace13.stp
+++ /dev/null
@@ -1,4 +0,0 @@
-#! stap -p2
-
-# path can't end with '..'
-probe process("/foo/bar/..").death { }
diff --git a/testsuite/semok/cast.stp b/testsuite/semok/cast.stp
index d30823cd..769335f2 100755
--- a/testsuite/semok/cast.stp
+++ b/testsuite/semok/cast.stp
@@ -12,6 +12,6 @@ probe begin {
// but who knows what debuginfo is installed...
// check modules generated from headers
- println(@cast(0, "task_struct", "kmod<linux/sched.h>")->tgid)
- println(@cast(0, "timeval", "umod<sys/time.h>")->tv_sec)
+ println(@cast(0, "task_struct", "kernel<linux/sched.h>")->tgid)
+ println(@cast(0, "timeval", "<sys/time.h>")->tv_sec)
}
diff --git a/testsuite/semok/utrace01.stp b/testsuite/semok/utrace01.stp
new file mode 100755
index 00000000..864bdf15
--- /dev/null
+++ b/testsuite/semok/utrace01.stp
@@ -0,0 +1,4 @@
+#! stap -p2
+
+# process path doesn't need to be absolute
+probe process("cat").end { }
diff --git a/testsuite/systemtap.base/cast.stp b/testsuite/systemtap.base/cast.stp
index 33a14a28..6298a06d 100644
--- a/testsuite/systemtap.base/cast.stp
+++ b/testsuite/systemtap.base/cast.stp
@@ -11,7 +11,7 @@ probe begin
printf("PID %d != %d\n", pid, cast_pid)
// Compare PIDs using a generated kernel module
- cast_pid = @cast(curr, "task_struct", "kmod<linux/sched.h>")->tgid
+ cast_pid = @cast(curr, "task_struct", "kernel<linux/sched.h>")->tgid
if (pid == cast_pid)
println("PID2 OK")
else
@@ -27,7 +27,7 @@ probe begin
// Compare tv_sec using a generated user module
sec = 42
- cast_sec = @cast(get_timeval(sec), "timeval", "umod<sys/time.h>")->tv_sec
+ cast_sec = @cast(get_timeval(sec), "timeval", "<sys/time.h>")->tv_sec
if (sec == cast_sec)
println("tv_sec OK")
else
diff --git a/testsuite/systemtap.base/uprobes_ustack.exp b/testsuite/systemtap.base/uprobes_ustack.exp
new file mode 100644
index 00000000..bfc435e9
--- /dev/null
+++ b/testsuite/systemtap.base/uprobes_ustack.exp
@@ -0,0 +1,97 @@
+set test "uprobes_ustack"
+set testpath "$srcdir/$subdir"
+set testsrc "$testpath/uprobes_exe.c"
+set testsrclib "$testpath/uprobes_lib.c"
+set testexe "./uprobes_exe"
+set testlibname "uprobes_lib"
+set testlibdir "."
+set testso "$testlibdir/lib${testlibname}.so"
+set testflags "additional_flags=-g additional_flags=-O"
+set testlibflags "$testflags additional_flags=-fPIC additional_flags=-shared"
+set maintestflags "$testflags additional_flags=-L$testlibdir additional_flags=-l$testlibname additional_flags=-Wl,-rpath,$testlibdir"
+
+# Compile our test program and library.
+set res [target_compile $testsrclib $testso executable $testlibflags]
+if { $res != "" } {
+ verbose "target_compile for $testso failed: $res" 2
+ fail "$test compile $testsrclib"
+ return
+} else {
+ pass "$test compile $testsrclib"
+}
+
+set res [target_compile $testsrc $testexe executable $maintestflags]
+if { $res != "" } {
+ verbose "target_compile failed: $res" 2
+ fail "$test compile $testsrc"
+ return
+} else {
+ pass "$test compile $testsrc"
+}
+
+set ::result_string {exe: main=main
+exe: main_func=main_func
+exe: main_func=main_func
+exe: main_func=main_func
+lib: lib_main=lib_main
+lib: lib_func=lib_func
+lib: lib_func=lib_func
+lib: lib_func=lib_func}
+
+# Only run on make installcheck
+if {! [installtest_p]} { untested "$test"; return }
+if {! [utrace_p]} { untested $test; return }
+
+# Output is:
+#print_ubacktrace exe 0
+# 0x080484ba : main_func+0xa/0x29 [.../uprobes_exe]
+# 0x080484f6 : main+0x1d/0x37 [.../uprobes_exe]
+#print_ustack exe 1
+# 0x080484ba : main_func+0xa/0x29 [.../uprobes_exe]
+# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe]
+# 0x080484f6 : main+0x1d/0x37 [.../uprobes_exe]
+#print_ubacktrace lib 2
+# 0x00db2422 : lib_func+0x16/0x2b [.../libuprobes_lib.so]
+# 0x00db2455 : lib_main+0x1e/0x29 [.../libuprobes_lib.so]
+# 0x080484d0 : main_func+0x20/0x29 [.../uprobes_exe]
+# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe]
+# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe]
+# 0x080484f6 : main+0x1d/0x37 [.../uprobes_exe]
+#print_ustack lib 3
+# 0x00db2422 : lib_func+0x16/0x2b [.../libuprobes_lib.so]
+# 0x00db2431 : lib_func+0x25/0x2b [.../libuprobes_lib.so]
+# 0x00db2455 : lib_main+0x1e/0x29 [.../libuprobes_lib.so]
+# 0x080484d0 : main_func+0x20/0x29 [.../uprobes_exe]
+# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe]
+# 0x080484c9 : main_func+0x19/0x29 [.../uprobes_exe]
+# 0x080484f6 : main+0x1d/0x37 [.../uprobes_exe]
+
+set print 0
+set main 0
+set main_func 0
+set lib_main 0
+set lib_func 0
+# Needs extra space since on 64bit the last ubacktrace string is
+# 7 entries * (16 hex + 2 for 0x + 1 space) = 133 chars.
+# Default MAXSTRINGLEN is 128 chars.
+spawn stap -DMAXSTRINGLEN=133 $srcdir/$subdir/$test.stp -c $testexe
+
+wait
+expect {
+ -timeout 60
+ -re {^print_[^\r\n]+\r\n} {incr print; exp_continue}
+ -re {^ 0x[a-f0-9]+ : main\+0x[^\r\n]+\r\n} {incr main; exp_continue}
+ -re {^ 0x[a-f0-9]+ : main_func\+0x[^\r\n]+\r\n} {incr main_func; exp_continue}
+ -re {^ 0x[a-f0-9]+ : lib_main\+0x[^\r\n]+\r\n} {incr lib_main; exp_continue}
+ -re {^ 0x[a-f0-9]+ : lib_func\+0x[^\r\n]+\r\n} {incr lib_func; exp_continue}
+ timeout { fail "$test (timeout)" }
+ eof { }
+}
+
+if {$print == 4} {pass "$test print"} {fail "$test print ($print)"}
+if {$main == 4} {pass "$test main"} {fail "$test main ($main)"}
+if {$main_func == 9} {pass "$test main_func"} {fail "$test main_func ($main_func)"}
+if {$lib_main == 2} {pass "$test lib_main"} {fail "$test lib_main ($lib_main)"}
+if {$lib_func == 3} {pass "$test lib_func"} {fail "$test lib_func ($lib_func)"}
+
+#exec rm -f $testexe $testso
diff --git a/testsuite/systemtap.base/uprobes_ustack.stp b/testsuite/systemtap.base/uprobes_ustack.stp
new file mode 100644
index 00000000..6de03b42
--- /dev/null
+++ b/testsuite/systemtap.base/uprobes_ustack.stp
@@ -0,0 +1,35 @@
+// Prints backtrace from lib through exe twice using diffent ustack functions.
+
+global hits = 0;
+
+probe process("uprobes_exe").function("main_func")
+{
+ if (hits == 0)
+ {
+ log("print_ubacktrace exe 0");
+ print_ubacktrace();
+ hits++;
+ }
+ else if (hits == 1)
+ {
+ log("print_ustack exe 1");
+ print_ustack(ubacktrace());
+ hits++;
+ }
+}
+
+probe process("libuprobes_lib.so").function("lib_func")
+{
+ if (hits == 2)
+ {
+ log("print_ubacktrace lib 2");
+ print_ubacktrace();
+ hits++;
+ }
+ else if (hits == 3)
+ {
+ log("print_ustack lib 3");
+ print_ustack(ubacktrace());
+ hits++;
+ }
+}
diff --git a/testsuite/systemtap.context/backtrace.tcl b/testsuite/systemtap.context/backtrace.tcl
index 6edda812..975e6c4d 100644
--- a/testsuite/systemtap.context/backtrace.tcl
+++ b/testsuite/systemtap.context/backtrace.tcl
@@ -5,6 +5,7 @@ set m4 0
set m5 0
set m6 0
+#spawn stap -d kernel -d systemtap_test_module1 -DMAXSTRINGLEN=256 $srcdir/$subdir/backtrace.stp
spawn stap -DMAXSTRINGLEN=256 $srcdir/$subdir/backtrace.stp
#exp_internal 1
expect {
diff --git a/testsuite/systemtap.examples/index.html b/testsuite/systemtap.examples/index.html
index a2dc7d5c..0df681ac 100644
--- a/testsuite/systemtap.examples/index.html
+++ b/testsuite/systemtap.examples/index.html
@@ -121,7 +121,7 @@ keywords: <a href="keyword-index.html#SIGNALS">SIGNALS</a> <br>
<li><a href="process/sigkill.stp">process/sigkill.stp</a> - Track SIGKILL Signals<br>
keywords: <a href="keyword-index.html#SIGNALS">SIGNALS</a> <br>
<p>The script traces any SIGKILL signals. When that SIGKILL signal is sent to a process, the script prints out the signal name, the desination executable and process ID, the executable name user ID that sent the signal.</p></li>
-<li><a href="process/syscalls_by_pid.stp">process/syscalls_by_pid.stp</a> - System-Wide Count of Syscalls by PID<br>
+<li><a href="process/sigmon.stp">process/sigmon.stp</a> - Track a particular signal to a specific process<br>
keywords: <a href="keyword-index.html#SIGNALS">SIGNALS</a> <br>
<p>The script watches for a particular signal sent to a specific process. When that signal is sent to the specified process, the script prints out the PID and executable of the process sending the signal, the PID and executable name of the process receiving the signal, and the signal number and name.</p></li>
<li><a href="process/sleepingBeauties.stp">process/sleepingBeauties.stp</a> - Generating Backtraces of Threads Waiting for IO Operations<br>
diff --git a/testsuite/systemtap.examples/index.txt b/testsuite/systemtap.examples/index.txt
index 2f85628a..fa344933 100644
--- a/testsuite/systemtap.examples/index.txt
+++ b/testsuite/systemtap.examples/index.txt
@@ -245,7 +245,7 @@ keywords: signals
that sent the signal.
-process/syscalls_by_pid.stp - System-Wide Count of Syscalls by PID
+process/sigmon.stp - Track a particular signal to a specific process
keywords: signals
The script watches for a particular signal sent to a specific
diff --git a/testsuite/systemtap.examples/keyword-index.html b/testsuite/systemtap.examples/keyword-index.html
index 473c0091..7edbec21 100644
--- a/testsuite/systemtap.examples/keyword-index.html
+++ b/testsuite/systemtap.examples/keyword-index.html
@@ -234,7 +234,7 @@ keywords: <a href="keyword-index.html#SIGNALS">SIGNALS</a> <br>
<li><a href="process/sigkill.stp">process/sigkill.stp</a> - Track SIGKILL Signals<br>
keywords: <a href="keyword-index.html#SIGNALS">SIGNALS</a> <br>
<p>The script traces any SIGKILL signals. When that SIGKILL signal is sent to a process, the script prints out the signal name, the desination executable and process ID, the executable name user ID that sent the signal.</p></li>
-<li><a href="process/syscalls_by_pid.stp">process/syscalls_by_pid.stp</a> - System-Wide Count of Syscalls by PID<br>
+<li><a href="process/sigmon.stp">process/sigmon.stp</a> - Track a particular signal to a specific process<br>
keywords: <a href="keyword-index.html#SIGNALS">SIGNALS</a> <br>
<p>The script watches for a particular signal sent to a specific process. When that signal is sent to the specified process, the script prints out the PID and executable of the process sending the signal, the PID and executable name of the process receiving the signal, and the signal number and name.</p></li>
</ul>
diff --git a/testsuite/systemtap.examples/keyword-index.txt b/testsuite/systemtap.examples/keyword-index.txt
index 1d5add5f..b53e776f 100644
--- a/testsuite/systemtap.examples/keyword-index.txt
+++ b/testsuite/systemtap.examples/keyword-index.txt
@@ -449,7 +449,7 @@ keywords: signals
that sent the signal.
-process/syscalls_by_pid.stp - System-Wide Count of Syscalls by PID
+process/sigmon.stp - Track a particular signal to a specific process
keywords: signals
The script watches for a particular signal sent to a specific
diff --git a/testsuite/systemtap.examples/process/sigmon.meta b/testsuite/systemtap.examples/process/sigmon.meta
index 18834997..fe192248 100644
--- a/testsuite/systemtap.examples/process/sigmon.meta
+++ b/testsuite/systemtap.examples/process/sigmon.meta
@@ -1,5 +1,5 @@
-title: System-Wide Count of Syscalls by PID
-name: syscalls_by_pid.stp
+title: Track a particular signal to a specific process
+name: sigmon.stp
version: 1.0
author: IBM
keywords: signals
diff --git a/translate.cxx b/translate.cxx
index 79c05d4b..b704b3a6 100644
--- a/translate.cxx
+++ b/translate.cxx
@@ -4689,11 +4689,7 @@ dump_unwindsyms (Dwfl_Module *m,
// absolute, dynamic or kernel have just one relocation
// section, which covers the whole module address range.
unsigned size;
- if (secidx == 0
- && (n == 0
- || (n == 1
- && (strcmp(secname, ".dynamic") == 0
- || strcmp(secname, "_stext") == 0))))
+ if (n <= 1)
size = end - start;
else
{