summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--runtime/runtime.h3
-rw-r--r--runtime/sym.c34
-rw-r--r--tapset/context-symbols.stp7
-rw-r--r--tapset/context-unwind.stp3
-rw-r--r--tapsets.cxx2
-rw-r--r--testsuite/systemtap.context/usymbols.c39
-rw-r--r--testsuite/systemtap.context/usymbols.exp79
-rw-r--r--testsuite/systemtap.context/usymbols_lib.c29
8 files changed, 186 insertions, 10 deletions
diff --git a/runtime/runtime.h b/runtime/runtime.h
index fc5d454f..822562a2 100644
--- a/runtime/runtime.h
+++ b/runtime/runtime.h
@@ -86,6 +86,9 @@ static struct
#include "io.c"
#include "arith.c"
#include "copy.c"
+
+#include "task_finder.c"
+
#include "sym.c"
#ifdef STP_PERFMON
#include "perf.c"
diff --git a/runtime/sym.c b/runtime/sym.c
index 1d88a862..3788544e 100644
--- a/runtime/sym.c
+++ b/runtime/sym.c
@@ -76,11 +76,30 @@ static unsigned long _stp_module_relocate(const char *module, const char *sectio
if found, return NULL otherwise.
XXX: needs to be address-space-specific. */
static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr,
+ struct task_struct *task,
struct _stp_section **sec)
{
struct _stp_module *m = NULL;
unsigned midx = 0;
unsigned long closest_section_offset = ~0;
+
+ // Try vma matching first if task given.
+ struct __stp_tf_vma_entry *entry;
+ if (task)
+ {
+ entry = __stp_tf_get_vma_entry_addr(task, addr);
+ if (entry != NULL && entry->module != NULL)
+ {
+ m = entry->module;
+ *sec = &m->sections[0]; // XXX check actual section and relocate
+ dbug_sym(1, "found section %s in module %s at 0x%lx\n",
+ m->sections[0].name, m->name, entry->vm_start);
+ if (strcmp(".dynamic", m->sections[0].name) == 0)
+ m->sections[0].addr = entry->vm_start; // cheat...
+ return m;
+ }
+ }
+
for (midx = 0; midx < _stp_num_modules; midx++)
{
unsigned secidx;
@@ -108,14 +127,15 @@ static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbo
unsigned long *offset,
const char **modname,
/* char ** secname? */
- char *namebuf)
+ char *namebuf,
+ struct task_struct *task)
{
struct _stp_module *m = NULL;
struct _stp_section *sec = NULL;
struct _stp_symbol *s = NULL;
unsigned end, begin = 0;
- m = _stp_mod_sec_lookup(addr, &sec);
+ m = _stp_mod_sec_lookup(addr, task, &sec);
if (unlikely (m == NULL || sec == NULL))
return NULL;
@@ -240,7 +260,7 @@ static void _stp_symbol_print(unsigned long address)
const char *name;
unsigned long offset, size;
- name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL);
+ name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, NULL);
_stp_printf("%p", (int64_t) address);
@@ -265,7 +285,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);
+ name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, NULL);
if (name) {
if (verbose) {
@@ -281,13 +301,15 @@ static int _stp_func_print(unsigned long address, int verbose, int exact)
return 0;
}
-static void _stp_symbol_snprint(char *str, size_t len, unsigned long address)
+static void _stp_symbol_snprint(char *str, size_t len, 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);
+ name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL,
+ task);
if (name)
strlcpy(str, name, len);
else
diff --git a/tapset/context-symbols.stp b/tapset/context-symbols.stp
index a3aae408..4c200aa8 100644
--- a/tapset/context-symbols.stp
+++ b/tapset/context-symbols.stp
@@ -66,7 +66,7 @@ function probefunc:string () %{ /* pure */
#else
((unsigned long)REG_IP(CONTEXT->regs) >= (unsigned long)PAGE_OFFSET)) {
#endif
- _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, REG_IP(CONTEXT->regs));
+ _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, REG_IP(CONTEXT->regs), current);
if (THIS->__retvalue[0] == '.') /* powerpc symbol has a dot*/
strlcpy(THIS->__retvalue,THIS->__retvalue + 1,MAXSTRINGLEN);
} else {
@@ -94,3 +94,8 @@ function probemod:string () %{ /* pure */
THIS->__retvalue[0] = '\0';
}
%}
+
+function symbolname:string (addr:long) %{ /* pure */
+ _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr,
+ current);
+%}
diff --git a/tapset/context-unwind.stp b/tapset/context-unwind.stp
index 90d4e0f4..a976f8b6 100644
--- a/tapset/context-unwind.stp
+++ b/tapset/context-unwind.stp
@@ -56,7 +56,8 @@ function backtrace:string () %{ /* pure */
function caller:string() %{ /* pure */
if (CONTEXT->pi)
_stp_symbol_snprint( THIS->__retvalue, MAXSTRINGLEN,
- (unsigned long)_stp_ret_addr_r(CONTEXT->pi));
+ (unsigned long)_stp_ret_addr_r(CONTEXT->pi),
+ current);
else
strlcpy(THIS->__retvalue,"unknown",MAXSTRINGLEN);
%}
diff --git a/tapsets.cxx b/tapsets.cxx
index 2f940b29..632e8d95 100644
--- a/tapsets.cxx
+++ b/tapsets.cxx
@@ -6952,7 +6952,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline();
s.op->newline() << "/* ---- utrace probes ---- */";
- s.op->newline() << "#include \"task_finder.c\"";
s.op->newline() << "enum utrace_derived_probe_flags {";
s.op->indent(1);
@@ -7441,7 +7440,6 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s)
s.op->newline() << "#else";
s.op->newline() << "#include \"uprobes/uprobes.h\"";
s.op->newline() << "#endif";
- s.op->newline() << "#include \"task_finder.c\"";
s.op->newline() << "#ifndef MULTIPLE_UPROBES";
s.op->newline() << "#define MULTIPLE_UPROBES 256"; // maximum possible armed uprobes per process() probe point
diff --git a/testsuite/systemtap.context/usymbols.c b/testsuite/systemtap.context/usymbols.c
new file mode 100644
index 00000000..7c590724
--- /dev/null
+++ b/testsuite/systemtap.context/usymbols.c
@@ -0,0 +1,39 @@
+/* usymbol test case
+ * Copyright (C) 2008, 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.
+ *
+ * Uses signal to tranfer user space addresses into the kernel where a
+ * probe on sigaction will extract them and produce the symbols. To
+ * poke into the executable we get the sa_handler from the main executable,
+ * and then the library through calling signal.
+ *
+ * FIXME. We call into the library to get the right symbol. If we
+ * register the handler from the main executable. We need to handle
+ * @plt symbols (setting a handler in the main executable that is in a
+ * shared library will have the @plt address, not the address inside
+ * the shared library).
+ */
+
+#include <signal.h>
+typedef void (*sighandler_t)(int);
+
+// function from our library
+int lib_main (void);
+
+void
+main_handler (int signum)
+{
+ /* dummy handler, just used for the address... */
+}
+
+int
+main (int argc, char *argv[], char *envp[])
+{
+ // Use SIGFPE since we never expect that to be triggered.
+ signal(SIGFPE, main_handler);
+ lib_main();
+}
diff --git a/testsuite/systemtap.context/usymbols.exp b/testsuite/systemtap.context/usymbols.exp
new file mode 100644
index 00000000..6892fc21
--- /dev/null
+++ b/testsuite/systemtap.context/usymbols.exp
@@ -0,0 +1,79 @@
+set test "./usymbols"
+set testpath "$srcdir/$subdir"
+set testsrc "$testpath/usymbols.c"
+set testsrclib "$testpath/usymbols_lib.c"
+set testexe "[pwd]/usymbols"
+set testlibname "usymbols"
+set testlibdir "[pwd]"
+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"
+
+# Only run on make installcheck
+if {! [installtest_p]} { untested "$test -p5"; return }
+
+# 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 "unable to compile $testsrclib"
+ return
+}
+set res [target_compile $testsrc $testexe executable $maintestflags]
+if { $res != "" } {
+ verbose "target_compile failed: $res" 2
+ fail "unable to compile $testsrc"
+ return
+}
+
+# We need the execname() trick to work around (the workaround of) PR6964
+# otherwise we get also the rt_sigactions of stapio. Get the handler
+# (comes from the executable or the library).
+set testscript {
+ probe syscall.rt_sigaction {
+ if (pid() == target() && execname() == "%s") {
+ handler = $act->sa_handler;
+ printf("handler: %%s\n", symbolname(handler));
+ }
+ }
+ probe process("%s").syscall { printf(""); /* XXX trigger tracker */ }
+}
+
+set output {handler: main_handler
+handler: lib_handler}
+
+# Got to run stap with both the exe and the libraries used as -d args.
+# XXX Note how we need the fully resolved (absolute) path...
+set script [format $testscript usymbols $testexe]
+catch {eval exec [concat ldd $testexe | grep $testlibname]} libpath
+set libpath [lindex [split $libpath " "] 2]
+send_log "libpath: $libpath\n"
+if {[string equal "link" [file type $libpath]]} {
+ set libpath [file join [file dirname $libpath] [file readlink $libpath]]
+}
+send_log "libpath: $libpath\n"
+set cmd [concat stap -d $libpath -d $testexe -c $testexe -e {$script}]
+send_log "cmd: $cmd\n"
+catch {eval exec $cmd} res
+send_log "cmd output: $res\n"
+
+set n 0
+set m [llength [split $output "\n"]]
+set expected [split $output "\n"]
+foreach line [split $res "\n"] {
+ if {![string equal $line [lindex $expected $n]]} {
+ fail usymbols
+ send_log "line [expr $n + 1]: expected \"[lindex $expected $n]\", "
+ send_log "Got \"$line\"\n"
+ return
+ }
+ incr n
+}
+if { $n != $m } {
+ fail usymbols
+ send_log "Got \"$n\" lines, expected \"$m\" lines\n"
+} else {
+ pass usymbols
+}
+exec rm -f $testexe $testso
diff --git a/testsuite/systemtap.context/usymbols_lib.c b/testsuite/systemtap.context/usymbols_lib.c
new file mode 100644
index 00000000..faccb39b
--- /dev/null
+++ b/testsuite/systemtap.context/usymbols_lib.c
@@ -0,0 +1,29 @@
+/* usymbol test case - library helper
+ * Copyright (C) 2008, 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.
+ *
+ * Uses signal to tranfer user space addresses into the kernel where a
+ * probe on sigaction will extract them and produce the symbols. To
+ * poke into the executable we get the sa_handler set through signal
+ * from this library.
+ */
+
+#include <signal.h>
+typedef void (*sighandler_t)(int);
+
+void
+lib_handler (int signum)
+{
+ /* dummy handler, just used for the address... */
+}
+
+void
+lib_main ()
+{
+ // Use SIGFPE since we never expect that to be triggered.
+ signal(SIGFPE, lib_handler);
+}