From d2f4d7286629da6e9f1b844beefb141a4d3ef2c3 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 10 Dec 2008 20:39:45 +0100 Subject: PR6866: First pass at translating addresses to symbol names through vma. --- ChangeLog | 7 ++++ runtime/ChangeLog | 11 +++++ runtime/runtime.h | 18 +++++++++ runtime/sym.c | 32 ++++++++++++--- runtime/task_finder.c | 22 +++++++--- runtime/task_finder_vma.c | 38 ++++++++++++------ tapset/ChangeLog | 7 ++++ tapset/context-symbols.stp | 8 ++++ tapset/context-unwind.stp | 3 +- tapsets.cxx | 4 +- testsuite/ChangeLog | 5 +++ testsuite/systemtap.context/usymbols.c | 41 +++++++++++++++++++ testsuite/systemtap.context/usymbols.exp | 69 ++++++++++++++++++++++++++++++++ 13 files changed, 238 insertions(+), 27 deletions(-) create mode 100644 testsuite/systemtap.context/usymbols.c create mode 100644 testsuite/systemtap.context/usymbols.exp diff --git a/ChangeLog b/ChangeLog index 6b31fb76..c46c0ef2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,10 @@ +2008-12-10 Mark Wielaard + + * tapsets.cxx + (utrace_derived_probe_group::emit_vm_callback_probe_decl): + Test for STP_NEED_TASK_FINDER_VMA to enable + emit_vm_callback_probe_decl. + 2008-12-09 Frank Ch. Eigler PR6961 diff --git a/runtime/ChangeLog b/runtime/ChangeLog index 3f88bae2..d83ac12c 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,14 @@ +2008-12-10 Mark Wielaard + + * runtime.h: Define __stp_tf_vma_entry here. + * sym.c (_stp_mod_sec_lookup): Try vma matching first if task given. + (_stp_kallsyms_lookup): Take an optional task. + (_stp_symbol_snprint): Likewise. + task_finder.c (__stp_tf_vm_cb): Use vm_path to match and attach + module to vma entry. + task_finder_vma.c (stap_add_vma_map_info): Take an optional module. + (__stp_tf_get_vma_entry_addr): New lookup function. + 2008-12-09 Frank Ch. Eigler * time.c (_stp_gettimeofday_ns): Protect some more against freq=0. diff --git a/runtime/runtime.h b/runtime/runtime.h index 3b3e117d..055d3f27 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -86,6 +86,24 @@ static struct #include "io.c" #include "arith.c" #include "copy.c" + +/* Lifted task_finder, internal details used in sym.c - XXX */ +struct __stp_tf_vma_entry { + struct hlist_node hlist; + + pid_t pid; + unsigned long addr; + unsigned long vm_start; + unsigned long vm_end; + unsigned long vm_pgoff; + // Is that enough? Should we store a dcookie for vm_file? + + // Module that this vma entry is mapped from, if any. + struct _stp_module *module; +}; +static struct __stp_tf_vma_entry * +__stp_tf_get_vma_entry_addr(struct task_struct *, unsigned long); + #include "sym.c" #ifdef STP_PERFMON #include "perf.c" diff --git a/runtime/sym.c b/runtime/sym.c index 06ac14a5..9b295f58 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -77,11 +77,28 @@ unsigned long _stp_module_relocate(const char *module, const char *section, unsi 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 + 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; @@ -109,7 +126,8 @@ 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; @@ -117,7 +135,7 @@ static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbo unsigned long flags; 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; @@ -242,7 +260,7 @@ 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); @@ -267,7 +285,7 @@ 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) { @@ -283,13 +301,15 @@ int _stp_func_print(unsigned long address, int verbose, int exact) return 0; } -void _stp_symbol_snprint(char *str, size_t len, unsigned long address) +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/runtime/task_finder.c b/runtime/task_finder.c index 25fad1a4..1e0a8474 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -55,7 +55,6 @@ typedef int (*stap_task_finder_vm_callback)(struct stap_task_finder_target *tgt, unsigned long vm_end, unsigned long vm_pgoff); -#ifdef DEBUG_TASK_FINDER_VMA int __stp_tf_vm_cb(struct stap_task_finder_target *tgt, struct task_struct *tsk, int map_p, char *vm_path, @@ -63,21 +62,32 @@ int __stp_tf_vm_cb(struct stap_task_finder_target *tgt, unsigned long vm_end, unsigned long vm_pgoff) { + int i; +#ifdef DEBUG_TASK_FINDER_VMA _stp_dbug(__FUNCTION__, __LINE__, "vm_cb: tsk %d:%d path %s, start 0x%08lx, end 0x%08lx, offset 0x%lx\n", tsk->pid, map_p, vm_path, vm_start, vm_end, vm_pgoff); +#endif if (map_p) { - // FIXME: What should we do with vm_path? We can't save - // the vm_path pointer itself, but we don't have any - // storage space allocated to save it in... - stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff); + struct _stp_module *module = NULL; + if (vm_path != NULL) + for (i = 0; i < _stp_num_modules; i++) + if (strcmp(vm_path, _stp_modules[i]->name) == 0) + { +#ifdef DEBUG_TASK_FINDER_VMA + _stp_dbug(__FUNCTION__, __LINE__, + "vm_cb: matched path %s to module\n", vm_path); +#endif + module = _stp_modules[i]; + break; + } + stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff, module); } else { stap_remove_vma_map_info(tsk, vm_start, vm_end, vm_pgoff); } return 0; } -#endif struct stap_task_finder_target { /* private: */ diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c index 4dce4be8..b65d9ea4 100644 --- a/runtime/task_finder_vma.c +++ b/runtime/task_finder_vma.c @@ -16,17 +16,6 @@ static DEFINE_MUTEX(__stp_tf_vma_mutex); #define TASK_FINDER_VMA_ENTRY_ITEMS 100 #endif -struct __stp_tf_vma_entry { - struct hlist_node hlist; - - pid_t pid; - unsigned long addr; - unsigned long vm_start; - unsigned long vm_end; - unsigned long vm_pgoff; - // Is that enough? Should we store a dcookie for vm_file? -}; - static struct __stp_tf_vma_entry __stp_tf_vma_free_list_items[TASK_FINDER_VMA_ENTRY_ITEMS]; @@ -211,7 +200,8 @@ __stp_tf_get_vma_map_entry_internal(struct task_struct *tsk, // Add the vma info to the vma map hash table. static int stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, - unsigned long vm_end, unsigned long vm_pgoff) + unsigned long vm_end, unsigned long vm_pgoff, + struct _stp_module *module) { struct hlist_head *head; struct hlist_node *node; @@ -242,6 +232,7 @@ stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, entry->vm_start = vm_start; entry->vm_end = vm_end; entry->vm_pgoff = vm_pgoff; + entry->module = module; head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; hlist_add_head(&entry->hlist, head); @@ -305,3 +296,26 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, mutex_unlock(&__stp_tf_vma_mutex); return rc; } + +// Get vma_entry of the address (vm_start/vm_end) if the vma is +// present in the vma hash table containing. +// Returns NULL if not present. +static struct __stp_tf_vma_entry * +__stp_tf_get_vma_entry_addr(struct task_struct *tsk, unsigned long addr) +{ + struct hlist_head *head; + struct hlist_node *node; + struct __stp_tf_vma_entry *entry; + + mutex_lock(&__stp_tf_vma_mutex); + head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; + hlist_for_each_entry(entry, node, head, hlist) { + if (tsk->pid == entry->pid + && addr >= entry->vm_start && addr < entry->vm_end) { + mutex_unlock(&__stp_tf_vma_mutex); + return entry; + } + } + mutex_unlock(&__stp_tf_vma_mutex); + return NULL; +} diff --git a/tapset/ChangeLog b/tapset/ChangeLog index 626ad67b..30634bcc 100644 --- a/tapset/ChangeLog +++ b/tapset/ChangeLog @@ -1,3 +1,10 @@ +2008-12-10 Mark Wielaard + + * context-symbols.stp: Define STP_NEED_TASK_FINDER_VMA. + (symbolname): New function. + * context-unwind.stp (caller): Pass current task to + _stp_symbol_snprint. + 2008-12-09 Frank Ch. Eigler PR 6961. diff --git a/tapset/context-symbols.stp b/tapset/context-symbols.stp index 79645f4f..fbb51767 100644 --- a/tapset/context-symbols.stp +++ b/tapset/context-symbols.stp @@ -11,6 +11,9 @@ #ifndef STP_NEED_SYMBOL_DATA #define STP_NEED_SYMBOL_DATA 1 #endif +#ifndef STP_NEED_TASK_FINDER_VMA +#define STP_NEED_TASK_FINDER_VMA 1 +#endif %} /** @@ -93,3 +96,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 4c5ed34b..59d111ee 100644 --- a/tapset/context-unwind.stp +++ b/tapset/context-unwind.stp @@ -51,7 +51,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 4d9a021d..9fe1d236 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6800,7 +6800,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) // Emit a "fake" probe decl that is really a hook for to get // our vm_callback called. string path = it->first; - s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA"; + s.op->newline() << "#ifdef STP_NEED_TASK_FINDER_VMA"; emit_vm_callback_probe_decl (s, true, path, (int64_t)0, "__stp_tf_vm_cb"); s.op->newline() << "#endif"; @@ -6821,7 +6821,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) { // Emit a "fake" probe decl that is really a hook for to get // our vm_callback called. - s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA"; + s.op->newline() << "#ifdef STP_NEED_TASK_FINDER_VMA"; emit_vm_callback_probe_decl (s, false, "", it->first, "__stp_tf_vm_cb"); s.op->newline() << "#endif"; diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog index 8e174efc..44261176 100644 --- a/testsuite/ChangeLog +++ b/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2008-12-10 Mark Wielaard + + * systemtap.context/usymbols.c: New test program. + * systemtap.context/usymbols.exp: New dejagnu test. + 2008-12-09 Frank Ch. Eigler PR6961. diff --git a/testsuite/systemtap.context/usymbols.c b/testsuite/systemtap.context/usymbols.c new file mode 100644 index 00000000..f8ee05b5 --- /dev/null +++ b/testsuite/systemtap.context/usymbols.c @@ -0,0 +1,41 @@ +/* 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, to poke into glibc + * we get the sa_restorer fields in the stap script. + * + * XXX - Seems sa_restorer isn't set on all architectures. should use + * our own shared library and set signal handler from there. Also + * 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 +typedef void (*sighandler_t)(int); + +void +handler (int signum) +{ + /* dummy handler, just used for the address... */ +} + +sighandler_t +libc_handler (void *func) +{ + return (sighandler_t) func; +} + +int +main (int argc, char *argv[], char *envp[]) +{ + // Use SIGFPE since we never expect that to be triggered. + signal(SIGFPE, handler); +} diff --git a/testsuite/systemtap.context/usymbols.exp b/testsuite/systemtap.context/usymbols.exp new file mode 100644 index 00000000..ebaa058e --- /dev/null +++ b/testsuite/systemtap.context/usymbols.exp @@ -0,0 +1,69 @@ +set test "./usymbols" +set testpath "$srcdir/$subdir" +set testsrc "$testpath/usymbols.c" +set testexe "[pwd]/usymbols" +set testflags "additional_flags=-g additional_flags=-O" + +# Only run on make installcheck +if {! [installtest_p]} { untested "$test -p5"; return } + +# Compile out test program +set res [target_compile $testsrc $testexe executable $testflags] +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) and the restorer (comes from glibc). +set testscript { + probe syscall.rt_sigaction { + if (pid() == target() && execname() == "%s") { + handler = $act->sa_handler; + printf("handler: %%s\n", symbolname(handler)); + restorer = $act->sa_restorer; + printf("restorer: %%s\n", symbolname(restorer)); + } + } + probe process("%s").syscall { printf(""); /* XXX trigger tracker */ } +} + +set output {handler: handler +restorer: __restore_rt} + +# 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 libc.so]} libc +set libc [lindex [split $libc " "] 2] +send_log "libc: $libc\n" +if {[string equal "link" [file type $libc]]} { + set libc [file join [file dirname $libc] [file readlink $libc]] +} +send_log "libc: $libc\n" +set cmd [concat stap -d $libc -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 -- cgit From 13d343c0c39e334cf11ee06cbc0f3ec01d440f41 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 15 Dec 2008 14:50:29 +0100 Subject: Work around buggy dwfl_module_relocate_address in dump_unwindsyms. --- ChangeLog | 5 +++++ translate.cxx | 23 ++++++++++++++++++++--- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index c46c0ef2..9cb4949d 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2008-12-15 Mark Wielaard + + * translate.cxx (dump_unwindsyms): Work around buggy + dwfl_module_relocate_address. + 2008-12-10 Mark Wielaard * tapsets.cxx diff --git a/translate.cxx b/translate.cxx index 27f6a04b..bb976d59 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4523,9 +4523,26 @@ dump_unwindsyms (Dwfl_Module *m, if (n > 0) // only try to relocate if there exist relocation bases { - int ki = dwfl_module_relocate_address (m, &sym_addr); - dwfl_assert ("dwfl_module_relocate_address", ki >= 0); - secname = dwfl_module_relocation_info (m, ki, NULL); + // libdwfl up to 0.137 could miscalculate the relocated + // address for shared ET_DYN files (n > 0). Luckily + // dwfl_module_address_section does work correctly. + // Then we just need to add the section offset to get + // the (relative) address of the symbol when mapped in. + Dwarf_Addr bias; + Elf_Scn *sec; + GElf_Shdr *shdr, shdr_mem; + GElf_Ehdr *ehdr, ehdr_mem; + Elf *elf; + sec = dwfl_module_address_section (m, &sym_addr, &bias); + dwfl_assert ("dwfl_module_address_section", sec != NULL); + shdr = gelf_getshdr(sec, &shdr_mem); + sym_addr += shdr->sh_offset; + elf = dwfl_module_getelf (m, &bias); + ehdr = gelf_getehdr(elf, &ehdr_mem); + if (ehdr->e_type == ET_DYN) + secname = ""; + else + secname = elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name); } if (n == 1 && modname == "kernel") -- cgit From 204038b16193de78eeb333fde0cce6081d9d1fcd Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 15 Dec 2008 17:51:49 +0100 Subject: Always include task_finder.c and enable emit_vm_callback_probe_decl. --- ChangeLog | 6 ++++++ runtime/ChangeLog | 7 +++++++ runtime/runtime.h | 17 +---------------- runtime/sym.c | 4 +++- runtime/task_finder_vma.c | 14 ++++++++++++++ tapsets.cxx | 6 ------ 6 files changed, 31 insertions(+), 23 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9cb4949d..9e83e978 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2008-12-15 Mark Wielaard + + * tapsets.cxx (utrace_derived_probe_group::emit_module_decls): + Always enable emit_vm_callback_probe_decl, don't test for + STP_NEED_TASK_FINDER_VMA. Don't include task_finder.c. + 2008-12-15 Mark Wielaard * translate.cxx (dump_unwindsyms): Work around buggy diff --git a/runtime/ChangeLog b/runtime/ChangeLog index d83ac12c..b9a2a058 100644 --- a/runtime/ChangeLog +++ b/runtime/ChangeLog @@ -1,3 +1,10 @@ +2008-12-15 Mark Wielaard + + * runtime.h: Just include task_finder.c instead of defining parts + of it here. + * sym.c (_stp_mod_sec_lookup): Add dbug_sym statements. + * task_finder_vma.c: Define __stp_tf_vma_entry here. + 2008-12-10 Mark Wielaard * runtime.h: Define __stp_tf_vma_entry here. diff --git a/runtime/runtime.h b/runtime/runtime.h index 055d3f27..3ca43dc4 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -87,22 +87,7 @@ static struct #include "arith.c" #include "copy.c" -/* Lifted task_finder, internal details used in sym.c - XXX */ -struct __stp_tf_vma_entry { - struct hlist_node hlist; - - pid_t pid; - unsigned long addr; - unsigned long vm_start; - unsigned long vm_end; - unsigned long vm_pgoff; - // Is that enough? Should we store a dcookie for vm_file? - - // Module that this vma entry is mapped from, if any. - struct _stp_module *module; -}; -static struct __stp_tf_vma_entry * -__stp_tf_get_vma_entry_addr(struct task_struct *, unsigned long); +#include "task_finder.c" #include "sym.c" #ifdef STP_PERFMON diff --git a/runtime/sym.c b/runtime/sym.c index 9b295f58..82eef17d 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -92,7 +92,9 @@ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr, if (entry != NULL && entry->module != NULL) { m = entry->module; - *sec = & m->sections[0]; // XXX check actual section and relocate + *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; diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c index b65d9ea4..87a32fe5 100644 --- a/runtime/task_finder_vma.c +++ b/runtime/task_finder_vma.c @@ -16,6 +16,20 @@ static DEFINE_MUTEX(__stp_tf_vma_mutex); #define TASK_FINDER_VMA_ENTRY_ITEMS 100 #endif +struct __stp_tf_vma_entry { + struct hlist_node hlist; + + pid_t pid; + unsigned long addr; + unsigned long vm_start; + unsigned long vm_end; + unsigned long vm_pgoff; + // Is that enough? Should we store a dcookie for vm_file? + + // Module that this vma entry is mapped from, if any. + struct _stp_module *module; +}; + static struct __stp_tf_vma_entry __stp_tf_vma_free_list_items[TASK_FINDER_VMA_ENTRY_ITEMS]; diff --git a/tapsets.cxx b/tapsets.cxx index 9fe1d236..fe4dad55 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6578,7 +6578,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); @@ -6800,10 +6799,8 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) // Emit a "fake" probe decl that is really a hook for to get // our vm_callback called. string path = it->first; - s.op->newline() << "#ifdef STP_NEED_TASK_FINDER_VMA"; emit_vm_callback_probe_decl (s, true, path, (int64_t)0, "__stp_tf_vm_cb"); - s.op->newline() << "#endif"; for (unsigned i = 0; i < it->second.size(); i++) { @@ -6821,10 +6818,8 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) { // Emit a "fake" probe decl that is really a hook for to get // our vm_callback called. - s.op->newline() << "#ifdef STP_NEED_TASK_FINDER_VMA"; emit_vm_callback_probe_decl (s, false, "", it->first, "__stp_tf_vm_cb"); - s.op->newline() << "#endif"; for (unsigned i = 0; i < it->second.size(); i++) { @@ -7073,7 +7068,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 -- cgit From 3a5153c5590a89d6c0b70fc2c13554190b8c3be8 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 15 Dec 2008 18:04:36 +0100 Subject: context-symbols.stp (probefunc): Call _stp_symbol_snprint with current task. --- tapset/ChangeLog | 5 +++++ tapset/context-symbols.stp | 5 +---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/tapset/ChangeLog b/tapset/ChangeLog index 30634bcc..d1d2064c 100644 --- a/tapset/ChangeLog +++ b/tapset/ChangeLog @@ -1,3 +1,8 @@ +2008-12-15 Mark Wielaard + + * context-symbols.stp (probefunc): Call _stp_symbol_snprint with + current task. + 2008-12-10 Mark Wielaard * context-symbols.stp: Define STP_NEED_TASK_FINDER_VMA. diff --git a/tapset/context-symbols.stp b/tapset/context-symbols.stp index fbb51767..bd9a93b9 100644 --- a/tapset/context-symbols.stp +++ b/tapset/context-symbols.stp @@ -11,9 +11,6 @@ #ifndef STP_NEED_SYMBOL_DATA #define STP_NEED_SYMBOL_DATA 1 #endif -#ifndef STP_NEED_TASK_FINDER_VMA -#define STP_NEED_TASK_FINDER_VMA 1 -#endif %} /** @@ -66,7 +63,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 { -- cgit From 6e44f060ffb5fff8d3987024d8facfb7997a3b25 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Mon, 15 Dec 2008 18:20:04 +0100 Subject: Compile and use helper usymbols_lib.c library for usymbols.exp test. --- testsuite/ChangeLog | 6 +++++ testsuite/systemtap.context/usymbols.c | 28 ++++++++++----------- testsuite/systemtap.context/usymbols.exp | 40 +++++++++++++++++++----------- testsuite/systemtap.context/usymbols_lib.c | 29 ++++++++++++++++++++++ 4 files changed, 73 insertions(+), 30 deletions(-) create mode 100644 testsuite/systemtap.context/usymbols_lib.c diff --git a/testsuite/ChangeLog b/testsuite/ChangeLog index 44261176..9ce0fd10 100644 --- a/testsuite/ChangeLog +++ b/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2008-12-15 Mark Wielaard + + * systemtap.context/usymbols.c: Call helper library. + * systemtap.context/usymbols_lib.c: New file. + * systemtap.context/usymbols.exp: Compile and use helper library. + 2008-12-10 Mark Wielaard * systemtap.context/usymbols.c: New test program. diff --git a/testsuite/systemtap.context/usymbols.c b/testsuite/systemtap.context/usymbols.c index f8ee05b5..7c590724 100644 --- a/testsuite/systemtap.context/usymbols.c +++ b/testsuite/systemtap.context/usymbols.c @@ -8,34 +8,32 @@ * * 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, to poke into glibc - * we get the sa_restorer fields in the stap script. + * poke into the executable we get the sa_handler from the main executable, + * and then the library through calling signal. * - * XXX - Seems sa_restorer isn't set on all architectures. should use - * our own shared library and set signal handler from there. Also - * 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). + * 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 typedef void (*sighandler_t)(int); +// function from our library +int lib_main (void); + void -handler (int signum) +main_handler (int signum) { /* dummy handler, just used for the address... */ } -sighandler_t -libc_handler (void *func) -{ - return (sighandler_t) func; -} - int main (int argc, char *argv[], char *envp[]) { // Use SIGFPE since we never expect that to be triggered. - signal(SIGFPE, handler); + signal(SIGFPE, main_handler); + lib_main(); } diff --git a/testsuite/systemtap.context/usymbols.exp b/testsuite/systemtap.context/usymbols.exp index ebaa058e..6892fc21 100644 --- a/testsuite/systemtap.context/usymbols.exp +++ b/testsuite/systemtap.context/usymbols.exp @@ -1,14 +1,26 @@ 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 out test program -set res [target_compile $testsrc $testexe executable $testflags] +# 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" @@ -17,33 +29,31 @@ if { $res != "" } { # 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) and the restorer (comes from glibc). +# (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)); - restorer = $act->sa_restorer; - printf("restorer: %%s\n", symbolname(restorer)); } } probe process("%s").syscall { printf(""); /* XXX trigger tracker */ } } -set output {handler: handler -restorer: __restore_rt} +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 libc.so]} libc -set libc [lindex [split $libc " "] 2] -send_log "libc: $libc\n" -if {[string equal "link" [file type $libc]]} { - set libc [file join [file dirname $libc] [file readlink $libc]] +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 "libc: $libc\n" -set cmd [concat stap -d $libc -d $testexe -c $testexe -e {$script}] +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" @@ -66,4 +76,4 @@ if { $n != $m } { } else { pass usymbols } -exec rm -f $testexe +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 +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); +} -- cgit From 2ef32a58a934e28aae94e57124ac362490f3e4eb Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 16 Dec 2008 14:57:58 +0100 Subject: Simplify dwfl_module_relocate_address workaround. --- ChangeLog | 5 +++++ translate.cxx | 38 ++++++++++++++++++-------------------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/ChangeLog b/ChangeLog index 9e83e978..5fd9c0ad 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,8 @@ +2008-12-16 Mark Wielaard + + * translate.cxx (dump_unwindsyms): Simplify + dwfl_module_relocate_address workaround. + 2008-12-15 Mark Wielaard * tapsets.cxx (utrace_derived_probe_group::emit_module_decls): diff --git a/translate.cxx b/translate.cxx index bb976d59..c1ced9ec 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4523,26 +4523,24 @@ dump_unwindsyms (Dwfl_Module *m, if (n > 0) // only try to relocate if there exist relocation bases { - // libdwfl up to 0.137 could miscalculate the relocated - // address for shared ET_DYN files (n > 0). Luckily - // dwfl_module_address_section does work correctly. - // Then we just need to add the section offset to get - // the (relative) address of the symbol when mapped in. - Dwarf_Addr bias; - Elf_Scn *sec; - GElf_Shdr *shdr, shdr_mem; - GElf_Ehdr *ehdr, ehdr_mem; - Elf *elf; - sec = dwfl_module_address_section (m, &sym_addr, &bias); - dwfl_assert ("dwfl_module_address_section", sec != NULL); - shdr = gelf_getshdr(sec, &shdr_mem); - sym_addr += shdr->sh_offset; - elf = dwfl_module_getelf (m, &bias); - ehdr = gelf_getehdr(elf, &ehdr_mem); - if (ehdr->e_type == ET_DYN) - secname = ""; - else - secname = elf_strptr (elf, ehdr->e_shstrndx, shdr->sh_name); + Dwarf_Addr save_addr = sym_addr; + int ki = dwfl_module_relocate_address (m, &sym_addr); + dwfl_assert ("dwfl_module_relocate_address", ki >= 0); + secname = dwfl_module_relocation_info (m, ki, NULL); + + // For ET_DYN files (secname == "") we do ignore the + // dwfl_module_relocate_address adjustment. libdwfl + // up to 0.137 would substract the wrong bias. And + // we are not actually interested in the bias adjustment. + // We just want the address relative to the start of the + // segment as loaded into memory. + if (ki == 0 && secname != NULL && secname[0] == '\0') + { + Dwarf_Addr start; + dwfl_module_info (m, NULL, &start, + NULL, NULL, NULL, NULL, NULL); + sym_addr = save_addr - start; + } } if (n == 1 && modname == "kernel") -- cgit From 750b1f2f5c84acaf0776de5239dc81e2e95c1dec Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 17 Dec 2008 17:22:23 +0100 Subject: dump_unwindsyms: Adjust against correct p_vaddr. --- ChangeLog | 4 ++++ translate.cxx | 28 ++++++++++++++++++++-------- 2 files changed, 24 insertions(+), 8 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5fd9c0ad..f993fd08 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,7 @@ +2008-12-17 Mark Wielaard + + * translate.cxx (dump_unwindsyms): Adjust against correct p_vaddr. + 2008-12-16 Mark Wielaard * translate.cxx (dump_unwindsyms): Simplify diff --git a/translate.cxx b/translate.cxx index c1ced9ec..1640d87e 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4523,24 +4523,36 @@ dump_unwindsyms (Dwfl_Module *m, if (n > 0) // only try to relocate if there exist relocation bases { - Dwarf_Addr save_addr = sym_addr; + Dwarf_Addr bias, save_addr = sym_addr; + GElf_Ehdr *ehdr, ehdr_mem; + GElf_Phdr *phdr = NULL, phdr_mem; + Elf *elf = dwfl_module_getelf (m, &bias); + int idx; int ki = dwfl_module_relocate_address (m, &sym_addr); dwfl_assert ("dwfl_module_relocate_address", ki >= 0); secname = dwfl_module_relocation_info (m, ki, NULL); // For ET_DYN files (secname == "") we do ignore the // dwfl_module_relocate_address adjustment. libdwfl - // up to 0.137 would substract the wrong bias. And - // we are not actually interested in the bias adjustment. + // up to 0.137 would substract the wrong bias. + if (ki == 0 && secname != NULL && secname[0] == '\0') + sym_addr = save_addr - bias; + // We just want the address relative to the start of the // segment as loaded into memory. - if (ki == 0 && secname != NULL && secname[0] == '\0') + ehdr = gelf_getehdr(elf, &ehdr_mem); + for (idx = 0; idx < ehdr->e_phnum; idx++) { - Dwarf_Addr start; - dwfl_module_info (m, NULL, &start, - NULL, NULL, NULL, NULL, NULL); - sym_addr = save_addr - start; + phdr = gelf_getphdr (elf, idx, &phdr_mem); + if (phdr != NULL + && phdr->p_type == PT_LOAD + && phdr->p_flags & PF_X + && sym_addr >= phdr->p_vaddr + && sym_addr < phdr->p_vaddr + phdr->p_memsz) + break; } + if (phdr != NULL && idx < ehdr->e_phnum) + sym_addr -= phdr->p_vaddr; } if (n == 1 && modname == "kernel") -- cgit From 524c6f82b0a3c010d0fd6a67b1afcfbf55b789a6 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 21 Feb 2009 00:28:18 +0100 Subject: Adjust ET_DYN symbol addresses against module base. * translate.cxx (dump_unwindsyms): Adjust sym_addr for ET_DYN always against module base as workaround for buggy elfutils < 0.138. --- translate.cxx | 44 +++++++++++++------------------------------- 1 file changed, 13 insertions(+), 31 deletions(-) diff --git a/translate.cxx b/translate.cxx index f2ebf762..530b077d 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4551,37 +4551,19 @@ dump_unwindsyms (Dwfl_Module *m, if (n > 0) // only try to relocate if there exist relocation bases { - Dwarf_Addr bias, save_addr = sym_addr; - GElf_Ehdr *ehdr, ehdr_mem; - GElf_Phdr *phdr = NULL, phdr_mem; - Elf *elf = dwfl_module_getelf (m, &bias); - int idx; - int ki = dwfl_module_relocate_address (m, &sym_addr); - dwfl_assert ("dwfl_module_relocate_address", ki >= 0); - secname = dwfl_module_relocation_info (m, ki, NULL); - - // For ET_DYN files (secname == "") we do ignore the - // dwfl_module_relocate_address adjustment. libdwfl - // up to 0.137 would substract the wrong bias. - if (ki == 0 && secname != NULL && secname[0] == '\0') - sym_addr = save_addr - bias; - - // We just want the address relative to the start of the - // segment as loaded into memory. - ehdr = gelf_getehdr(elf, &ehdr_mem); - for (idx = 0; idx < ehdr->e_phnum; idx++) - { - phdr = gelf_getphdr (elf, idx, &phdr_mem); - if (phdr != NULL - && phdr->p_type == PT_LOAD - && phdr->p_flags & PF_X - && sym_addr >= phdr->p_vaddr - && sym_addr < phdr->p_vaddr + phdr->p_memsz) - break; - } - if (phdr != NULL && idx < ehdr->e_phnum) - sym_addr -= phdr->p_vaddr; - } + Dwarf_Addr save_addr = sym_addr; + int ki = dwfl_module_relocate_address (m, &sym_addr); + dwfl_assert ("dwfl_module_relocate_address", ki >= 0); + secname = dwfl_module_relocation_info (m, ki, NULL); + + // For ET_DYN files (secname == "") we do ignore the + // dwfl_module_relocate_address adjustment. libdwfl + // up to 0.137 would substract the wrong bias. So we do + // it ourself, it is always just the module base address + // in this case. + if (ki == 0 && secname != NULL && secname[0] == '\0') + sym_addr = save_addr - base; + } if (n == 1 && modname == "kernel") { -- cgit From 67af0ab2fac61cce5a9a271c385939b5a8c77f87 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 18 Mar 2009 11:32:36 +0100 Subject: Make stap_run send_log of command to execute. * testsuite/lib/stap_run.exp (tap_run): Add send_log of cmd. --- testsuite/lib/stap_run.exp | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/lib/stap_run.exp b/testsuite/lib/stap_run.exp index a4beaa12..3043eeed 100644 --- a/testsuite/lib/stap_run.exp +++ b/testsuite/lib/stap_run.exp @@ -30,6 +30,7 @@ proc stap_run { TEST_NAME {LOAD_GEN_FUNCTION ""} {OUTPUT_CHECK_STRING ""} args } if [file readable $test_file_name] { lappend cmd $test_file_name } + send_log "executing: $cmd\n" eval spawn $cmd expect { -timeout 180 -- cgit From cb1468beb7b34ad988280fea9fb7c4558b47341a Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 18 Mar 2009 12:27:13 +0100 Subject: Replace mutex in task_finder_vma with rwlock to be interrupt context safe. * runtime/task_finder_vma.c: Replace all mutex calls with appropriate read or write (un)lock calls. --- runtime/task_finder_vma.c | 82 +++++++++++++++++++++++++++++------------------ 1 file changed, 51 insertions(+), 31 deletions(-) diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c index 83b206e5..a210d92e 100644 --- a/runtime/task_finder_vma.c +++ b/runtime/task_finder_vma.c @@ -1,13 +1,19 @@ #include #include -#include +#include // When handling memcpy() syscall tracing to notice memory map // changes, we need to cache memcpy() entry parameter values for // processing at memcpy() exit. -// __stp_tf_vma_mutex protects the hash table. -static DEFINE_MUTEX(__stp_tf_vma_mutex); +// __stp_tf_vma_lock protects the hash table. +// Documentation/spinlocks.txt suggest we can be a bit more clever +// if we guarantee that in interrupt context we only read, not write +// the datastructures. We should never change the hash table or the +// contents in interrupt context (which should only ever call +// __stp_tf_get_vma_entry_addr for symbol lookup). So we might want +// to look into that if this seems a bottleneck. +static DEFINE_RWLOCK(__stp_tf_vma_lock); #define __STP_TF_HASH_BITS 4 #define __STP_TF_TABLE_SIZE (1 << __STP_TF_HASH_BITS) @@ -40,23 +46,24 @@ static struct hlist_head __stp_tf_vma_table[__STP_TF_TABLE_SIZE]; static struct hlist_head __stp_tf_vma_map[__STP_TF_TABLE_SIZE]; // __stp_tf_vma_initialize(): Initialize the free list. Grabs the -// mutex. +// spinlock. static void __stp_tf_vma_initialize(void) { int i; struct hlist_head *head = &__stp_tf_vma_free_list[0]; - mutex_lock(&__stp_tf_vma_mutex); + unsigned long flags; + write_lock_irqsave(&__stp_tf_vma_lock, flags); for (i = 0; i < TASK_FINDER_VMA_ENTRY_ITEMS; i++) { hlist_add_head(&__stp_tf_vma_free_list_items[i].hlist, head); } - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); } // __stp_tf_vma_get_free_entry(): Returns an entry from the free list -// or NULL. The __stp_tf_vma_mutex must be locked before calling this +// or NULL. The __stp_tf_vma_lock must be write locked before calling this // function. static struct __stp_tf_vma_entry * __stp_tf_vma_get_free_entry(void) @@ -77,7 +84,7 @@ __stp_tf_vma_get_free_entry(void) // __stp_tf_vma_put_free_entry(): Puts an entry back on the free -// list. The __stp_tf_vma_mutex must be locked before calling this +// list. The __stp_tf_vma_lock must be write locked before calling this // function. static void __stp_tf_vma_put_free_entry(struct __stp_tf_vma_entry *entry) @@ -101,7 +108,7 @@ __stp_tf_vma_hash(struct task_struct *tsk, unsigned long addr) // Get vma_entry if the vma is present in the vma hash table. -// Returns NULL if not present. +// Returns NULL if not present. Takes a read lock on __stp_tf_vma_lock. static struct __stp_tf_vma_entry * __stp_tf_get_vma_entry(struct task_struct *tsk, unsigned long addr) { @@ -109,20 +116,22 @@ __stp_tf_get_vma_entry(struct task_struct *tsk, unsigned long addr) struct hlist_node *node; struct __stp_tf_vma_entry *entry; - mutex_lock(&__stp_tf_vma_mutex); + unsigned long flags; + read_lock_irqsave(&__stp_tf_vma_lock, flags); head = &__stp_tf_vma_table[__stp_tf_vma_hash(tsk, addr)]; hlist_for_each_entry(entry, node, head, hlist) { if (tsk->pid == entry->pid && addr == entry->addr) { - mutex_unlock(&__stp_tf_vma_mutex); + read_unlock_irqrestore(&__stp_tf_vma_lock, flags); return entry; } } - mutex_unlock(&__stp_tf_vma_mutex); + read_unlock_irqrestore(&__stp_tf_vma_lock, flags); return NULL; } // Add the vma info to the vma hash table. +// Takes a write lock on __stp_tf_vma_lock. static int __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr, struct vm_area_struct *vma) @@ -131,7 +140,8 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr, struct hlist_node *node; struct __stp_tf_vma_entry *entry; - mutex_lock(&__stp_tf_vma_mutex); + unsigned long flags; + write_lock_irqsave(&__stp_tf_vma_lock, flags); head = &__stp_tf_vma_table[__stp_tf_vma_hash(tsk, addr)]; hlist_for_each_entry(entry, node, head, hlist) { if (tsk->pid == entry->pid @@ -141,7 +151,7 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr, "vma (pid: %d, vm_start: 0x%lx) present?\n", tsk->pid, vma->vm_start); #endif - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); return -EBUSY; /* Already there */ } } @@ -149,7 +159,7 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr, // Get an element from the free list. entry = __stp_tf_vma_get_free_entry(); if (!entry) { - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); return -ENOMEM; } entry->pid = tsk->pid; @@ -158,11 +168,12 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr, entry->vm_end = vma->vm_end; entry->vm_pgoff = vma->vm_pgoff; hlist_add_head(&entry->hlist, head); - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); return 0; } // Remove the vma entry from the vma hash table. +// Takes a write lock on __stp_tf_vma_lock. static int __stp_tf_remove_vma_entry(struct __stp_tf_vma_entry *entry) { @@ -171,10 +182,11 @@ __stp_tf_remove_vma_entry(struct __stp_tf_vma_entry *entry) int found = 0; if (entry != NULL) { - mutex_lock(&__stp_tf_vma_mutex); + unsigned long flags; + write_lock_irqsave(&__stp_tf_vma_lock, flags); hlist_del(&entry->hlist); __stp_tf_vma_put_free_entry(entry); - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); } return 0; } @@ -189,7 +201,7 @@ __stp_tf_vma_map_hash(struct task_struct *tsk) } // Get vma_entry if the vma is present in the vma map hash table. -// Returns NULL if not present. The __stp_tf_vma_mutex must be locked +// Returns NULL if not present. The __stp_tf_vma_lock must be read locked // before calling this function. static struct __stp_tf_vma_entry * __stp_tf_get_vma_map_entry_internal(struct task_struct *tsk, @@ -220,7 +232,10 @@ stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, struct hlist_node *node; struct __stp_tf_vma_entry *entry; - mutex_lock(&__stp_tf_vma_mutex); + unsigned long flags; + // Take a write lock, since we are most likely going to write + // after reading. + write_lock_irqsave(&__stp_tf_vma_lock, flags); entry = __stp_tf_get_vma_map_entry_internal(tsk, vm_start); if (entry != NULL) { #if 0 @@ -228,14 +243,14 @@ stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, "vma (pid: %d, vm_start: 0x%lx) present?\n", tsk->pid, entry->vm_start); #endif - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); return -EBUSY; /* Already there */ } // Get an element from the free list. entry = __stp_tf_vma_get_free_entry(); if (!entry) { - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); return -ENOMEM; } @@ -249,7 +264,7 @@ stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; hlist_add_head(&entry->hlist, head); - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); return 0; } @@ -263,18 +278,21 @@ stap_remove_vma_map_info(struct task_struct *tsk, unsigned long vm_start, struct hlist_node *node; struct __stp_tf_vma_entry *entry; - mutex_lock(&__stp_tf_vma_mutex); + // Take a write lock since we are most likely going to delete + // after reading. + unsigned long flags; + write_lock_irqsave(&__stp_tf_vma_lock, flags); entry = __stp_tf_get_vma_map_entry_internal(tsk, vm_start); if (entry != NULL) { hlist_del(&entry->hlist); __stp_tf_vma_put_free_entry(entry); } - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); return 0; } // Finds vma info if the vma is present in the vma map hash table. -// Returns ESRCH if not present. The __stp_tf_vma_mutex must *not* be +// Returns ESRCH if not present. The __stp_tf_vma_lock must *not* be // locked before calling this function. static int stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, @@ -287,7 +305,8 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, struct __stp_tf_vma_entry *found_entry = NULL; int rc = ESRCH; - mutex_lock(&__stp_tf_vma_mutex); + unsigned long flags; + read_lock_irqsave(&__stp_tf_vma_lock, flags); head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; hlist_for_each_entry(entry, node, head, hlist) { if (tsk->pid == entry->pid @@ -306,7 +325,7 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, *vm_pgoff = found_entry->vm_pgoff; rc = 0; } - mutex_unlock(&__stp_tf_vma_mutex); + read_unlock_irqrestore(&__stp_tf_vma_lock, flags); return rc; } @@ -320,15 +339,16 @@ __stp_tf_get_vma_entry_addr(struct task_struct *tsk, unsigned long addr) struct hlist_node *node; struct __stp_tf_vma_entry *entry; - mutex_lock(&__stp_tf_vma_mutex); + unsigned long flags; + read_lock_irqsave(&__stp_tf_vma_lock, flags); head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; hlist_for_each_entry(entry, node, head, hlist) { if (tsk->pid == entry->pid && addr >= entry->vm_start && addr < entry->vm_end) { - mutex_unlock(&__stp_tf_vma_mutex); + read_unlock_irqrestore(&__stp_tf_vma_lock, flags); return entry; } } - mutex_unlock(&__stp_tf_vma_mutex); + read_unlock_irqrestore(&__stp_tf_vma_lock, flags); return NULL; } -- cgit From 1882152af71f8339c91751ee17c97f1c4d18660a Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 19 Mar 2009 14:28:14 +0100 Subject: Get rid of __stp_tf_get_vma_entry_addr function. * runtime/task_finder_vma.c (__stp_tf_get_vma_entry_addr): Deleted. (struct __stp_tf_vma_entry): Replace module by user void* field. (stap_add_vma_map_info): Take a void *user arg. (stap_find_vma_map_info): Take a void **user arg. * runtime/sym.c (_stp_mod_sec_lookup): Use stap_find_vma_map_info. --- runtime/sym.c | 28 ++++++++++++++++------------ runtime/task_finder_vma.c | 40 +++++++++------------------------------- 2 files changed, 25 insertions(+), 43 deletions(-) diff --git a/runtime/sym.c b/runtime/sym.c index 3788544e..1fe3f818 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -79,25 +79,29 @@ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr, struct task_struct *task, struct _stp_section **sec) { + void *user; 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; + unsigned long vm_start; 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; - } + + if (stap_find_vma_map_info(task, addr, + &vm_start, NULL, + NULL, &user) == 0) + if (user != NULL) + { + m = (struct _stp_module *)user; + *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, vm_start); + if (strcmp(".dynamic", m->sections[0].name) == 0) + m->sections[0].addr = vm_start; // cheat... + return m; + } } for (midx = 0; midx < _stp_num_modules; midx++) diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c index a210d92e..ed9c6f4f 100644 --- a/runtime/task_finder_vma.c +++ b/runtime/task_finder_vma.c @@ -11,8 +11,8 @@ // if we guarantee that in interrupt context we only read, not write // the datastructures. We should never change the hash table or the // contents in interrupt context (which should only ever call -// __stp_tf_get_vma_entry_addr for symbol lookup). So we might want -// to look into that if this seems a bottleneck. +// stap_find_vma_map_info for getting stored vma info). So we might +// want to look into that if this seems a bottleneck. static DEFINE_RWLOCK(__stp_tf_vma_lock); #define __STP_TF_HASH_BITS 4 @@ -32,8 +32,8 @@ struct __stp_tf_vma_entry { unsigned long vm_pgoff; // Is that enough? Should we store a dcookie for vm_file? - // Module that this vma entry is mapped from, if any. - struct _stp_module *module; + // User data (possibly stp_module) + void *user; }; static struct __stp_tf_vma_entry @@ -226,7 +226,7 @@ __stp_tf_get_vma_map_entry_internal(struct task_struct *tsk, static int stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, unsigned long vm_end, unsigned long vm_pgoff, - struct _stp_module *module) + void *user) { struct hlist_head *head; struct hlist_node *node; @@ -260,7 +260,7 @@ stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, entry->vm_start = vm_start; entry->vm_end = vm_end; entry->vm_pgoff = vm_pgoff; - entry->module = module; + entry->user = user; head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; hlist_add_head(&entry->hlist, head); @@ -297,7 +297,7 @@ stap_remove_vma_map_info(struct task_struct *tsk, unsigned long vm_start, static int stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, unsigned long *vm_start, unsigned long *vm_end, - unsigned long *vm_pgoff) + unsigned long *vm_pgoff, void **user) { struct hlist_head *head; struct hlist_node *node; @@ -323,32 +323,10 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, *vm_end = found_entry->vm_end; if (vm_pgoff != NULL) *vm_pgoff = found_entry->vm_pgoff; + if (user != NULL) + *user = found_entry->user; rc = 0; } read_unlock_irqrestore(&__stp_tf_vma_lock, flags); return rc; } - -// Get vma_entry of the address (vm_start/vm_end) if the vma is -// present in the vma hash table containing. -// Returns NULL if not present. -static struct __stp_tf_vma_entry * -__stp_tf_get_vma_entry_addr(struct task_struct *tsk, unsigned long addr) -{ - struct hlist_head *head; - struct hlist_node *node; - struct __stp_tf_vma_entry *entry; - - unsigned long flags; - read_lock_irqsave(&__stp_tf_vma_lock, flags); - head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; - hlist_for_each_entry(entry, node, head, hlist) { - if (tsk->pid == entry->pid - && addr >= entry->vm_start && addr < entry->vm_end) { - read_unlock_irqrestore(&__stp_tf_vma_lock, flags); - return entry; - } - } - read_unlock_irqrestore(&__stp_tf_vma_lock, flags); - return NULL; -} -- cgit From bfd5b4a50e6797da88a11eb6a52c185d2826a0d1 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 19 Mar 2009 14:51:33 +0100 Subject: Initialize user and vm_start before use. * runtime/sym.c (_stp_mod_sec_lookup): Initialize user and vm_start. --- runtime/sym.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/runtime/sym.c b/runtime/sym.c index 1fe3f818..ed108f08 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -79,16 +79,15 @@ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr, struct task_struct *task, struct _stp_section **sec) { - void *user; + void *user = NULL; struct _stp_module *m = NULL; unsigned midx = 0; unsigned long closest_section_offset = ~0; // Try vma matching first if task given. - unsigned long vm_start; if (task) { - + unsigned long vm_start = 0; if (stap_find_vma_map_info(task, addr, &vm_start, NULL, NULL, &user) == 0) -- cgit From 5e94ef56760c087784e485c35521a6e438cfc3e5 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 19 Mar 2009 16:51:02 +0100 Subject: Remove __stp_tf_vm_cb from task_finder interface. * runtime/task_finder.c (__stp_tf_vm_cb): Removed. * tapsets.cxx (utrace_derived_probe_group::emit_module_decls): Output task finder vma callback and hook it. --- runtime/task_finder.c | 34 ---------------------------------- tapsets.cxx | 45 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 43 insertions(+), 36 deletions(-) diff --git a/runtime/task_finder.c b/runtime/task_finder.c index 38f9145d..1db2bc2a 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -55,40 +55,6 @@ typedef int (*stap_task_finder_vm_callback)(struct stap_task_finder_target *tgt, unsigned long vm_end, unsigned long vm_pgoff); -static int __stp_tf_vm_cb(struct stap_task_finder_target *tgt, - struct task_struct *tsk, - int map_p, char *vm_path, - unsigned long vm_start, - unsigned long vm_end, - unsigned long vm_pgoff) -{ - int i; -#ifdef DEBUG_TASK_FINDER_VMA - _stp_dbug(__FUNCTION__, __LINE__, - "vm_cb: tsk %d:%d path %s, start 0x%08lx, end 0x%08lx, offset 0x%lx\n", - tsk->pid, map_p, vm_path, vm_start, vm_end, vm_pgoff); -#endif - if (map_p) { - struct _stp_module *module = NULL; - if (vm_path != NULL) - for (i = 0; i < _stp_num_modules; i++) - if (strcmp(vm_path, _stp_modules[i]->path) == 0) - { -#ifdef DEBUG_TASK_FINDER_VMA - _stp_dbug(__FUNCTION__, __LINE__, - "vm_cb: matched path %s to module\n", vm_path); -#endif - module = _stp_modules[i]; - break; - } - stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff, module); - } - else { - stap_remove_vma_map_info(tsk, vm_start, vm_end, vm_pgoff); - } - return 0; -} - struct stap_task_finder_target { /* private: */ struct list_head list; /* __stp_task_finder_list linkage */ diff --git a/tapsets.cxx b/tapsets.cxx index 632e8d95..89e011c4 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -7159,6 +7159,47 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "return rc;"; s.op->newline(-1) << "}"; + // Output task finder vma callback + s.op->newline() << "static int _stp_tf_vm_cb(struct stap_task_finder_target *tgt, struct task_struct *tsk, int map_p, char *vm_path, unsigned long vm_start, unsigned long vm_end, unsigned long vm_pgoff) {"; + s.op->indent(1); + s.op->newline() << "int i;"; + s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA"; + s.op->indent(1); + s.op->newline() << "_stp_dbug(__FUNCTION__, __LINE__, \"vm_cb: tsk %d:%d path %s, start 0x%08lx, end 0x%08lx, offset 0x%lx\\n\", tsk->pid, map_p, vm_path, vm_start, vm_end, vm_pgoff);"; + s.op->indent(-1); + s.op->newline() << "#endif"; + s.op->newline() << "if (map_p) {"; + s.op->indent(1); + s.op->newline() << "struct _stp_module *module = NULL;"; + s.op->newline() << "if (vm_path != NULL)"; + s.op->indent(1); + s.op->newline() << "for (i = 0; i < _stp_num_modules; i++)"; + s.op->indent(1); + s.op->newline() << "if (strcmp(vm_path, _stp_modules[i]->path) == 0) {"; + s.op->indent(1); + s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA"; + s.op->indent(1); + s.op->newline() << "_stp_dbug(__FUNCTION__, __LINE__, \"vm_cb: matched path %s to module\\n\", vm_path);"; + s.op->indent(-1); + s.op->newline() << "#endif"; + s.op->newline() << "module = _stp_modules[i];"; + s.op->newline() << "break;"; + s.op->indent(-1); + s.op->newline() << "}"; + s.op->indent(-2); + // XXX Check return value + s.op->newline() << "stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff, module);"; + s.op->indent(-1); + s.op->newline() << "} else {"; + s.op->indent(1); + // XXX Check return value + s.op->newline() << "stap_remove_vma_map_info(tsk, vm_start, vm_end, vm_pgoff);"; + s.op->indent(-1); + s.op->newline() << "}"; + s.op->newline() << "return 0;"; + s.op->indent(-1); + s.op->newline() << "}"; + s.op->newline() << "static struct stap_utrace_probe stap_utrace_probes[] = {"; s.op->indent(1); @@ -7172,7 +7213,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) // our vm_callback called. string path = it->first; emit_vm_callback_probe_decl (s, true, path, (int64_t)0, - "__stp_tf_vm_cb"); + "_stp_tf_vm_cb"); for (unsigned i = 0; i < it->second.size(); i++) { @@ -7191,7 +7232,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) // Emit a "fake" probe decl that is really a hook for to get // our vm_callback called. emit_vm_callback_probe_decl (s, false, "", it->first, - "__stp_tf_vm_cb"); + "_stp_tf_vm_cb"); for (unsigned i = 0; i < it->second.size(); i++) { -- cgit From 3bbd893b113a2b67162b98e7b207d9bd1eeda035 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 20 Mar 2009 11:45:06 +0100 Subject: Don't double include task_finder.c. * tapsets.cxx (itrace_derived_probe_group::emit_module_decls): Don't emit another include task_finder.c. Already done through runtime.h. --- tapsets.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/tapsets.cxx b/tapsets.cxx index d7b55e33..52eb1edf 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6391,7 +6391,6 @@ itrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(); s.op->newline() << "/* ---- itrace probes ---- */"; - s.op->newline() << "#include \"task_finder.c\""; s.op->newline() << "struct stap_itrace_probe {"; s.op->indent(1); s.op->newline() << "struct stap_task_finder_target tgt;"; -- cgit From f735e6054d182b589750db65a906c1851faa9d75 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 20 Mar 2009 13:30:58 +0100 Subject: Move _stp_tf_vm_cb to sym.c. * tapsets.cxx (utrace_derived_probe_group::emit_module_decls): Remove output task finder vma callback _stp_tf_vm_cb. * runtime/sym.c (_stp_tf_vm_cb): And add it here. --- runtime/sym.c | 34 ++++++++++++++++++++++++++++++++++ tapsets.cxx | 41 ----------------------------------------- 2 files changed, 34 insertions(+), 41 deletions(-) diff --git a/runtime/sym.c b/runtime/sym.c index ed108f08..d0c5d9fd 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -20,6 +20,40 @@ * @{ */ +/* Callback that needs to be registered (in tapsets.cxx for + emit_module_init) for every user task path or pid for which we + might need symbols or unwind info. */ +static int _stp_tf_vm_cb(struct stap_task_finder_target *tgt, + struct task_struct *tsk, + int map_p, char *vm_path, + unsigned long vm_start, unsigned long vm_end, + unsigned long vm_pgoff) +{ + int i; +#ifdef DEBUG_TASK_FINDER_VMA + _stp_dbug(__FUNCTION__, __LINE__, "vm_cb: tsk %d:%d path %s, start 0x%08lx, end 0x%08lx, offset 0x%lx\n", tsk->pid, map_p, vm_path, vm_start, vm_end, vm_pgoff); +#endif + if (map_p) + { + struct _stp_module *module = NULL; + if (vm_path != NULL) + for (i = 0; i < _stp_num_modules; i++) + if (strcmp(vm_path, _stp_modules[i]->path) == 0) + { +#ifdef DEBUG_TASK_FINDER_VMA + _stp_dbug(__FUNCTION__, __LINE__, "vm_cb: matched path %s to module\n", vm_path); +#endif + module = _stp_modules[i]; + break; + } + stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff, module); + } + else + stap_remove_vma_map_info(tsk, vm_start, vm_end, vm_pgoff); + + return 0; +} + /* XXX: this needs to be address-space-specific. */ static unsigned long _stp_module_relocate(const char *module, const char *section, unsigned long offset) { diff --git a/tapsets.cxx b/tapsets.cxx index 52eb1edf..c8852f0f 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -7170,47 +7170,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "return rc;"; s.op->newline(-1) << "}"; - // Output task finder vma callback - s.op->newline() << "static int _stp_tf_vm_cb(struct stap_task_finder_target *tgt, struct task_struct *tsk, int map_p, char *vm_path, unsigned long vm_start, unsigned long vm_end, unsigned long vm_pgoff) {"; - s.op->indent(1); - s.op->newline() << "int i;"; - s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA"; - s.op->indent(1); - s.op->newline() << "_stp_dbug(__FUNCTION__, __LINE__, \"vm_cb: tsk %d:%d path %s, start 0x%08lx, end 0x%08lx, offset 0x%lx\\n\", tsk->pid, map_p, vm_path, vm_start, vm_end, vm_pgoff);"; - s.op->indent(-1); - s.op->newline() << "#endif"; - s.op->newline() << "if (map_p) {"; - s.op->indent(1); - s.op->newline() << "struct _stp_module *module = NULL;"; - s.op->newline() << "if (vm_path != NULL)"; - s.op->indent(1); - s.op->newline() << "for (i = 0; i < _stp_num_modules; i++)"; - s.op->indent(1); - s.op->newline() << "if (strcmp(vm_path, _stp_modules[i]->path) == 0) {"; - s.op->indent(1); - s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA"; - s.op->indent(1); - s.op->newline() << "_stp_dbug(__FUNCTION__, __LINE__, \"vm_cb: matched path %s to module\\n\", vm_path);"; - s.op->indent(-1); - s.op->newline() << "#endif"; - s.op->newline() << "module = _stp_modules[i];"; - s.op->newline() << "break;"; - s.op->indent(-1); - s.op->newline() << "}"; - s.op->indent(-2); - // XXX Check return value - s.op->newline() << "stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff, module);"; - s.op->indent(-1); - s.op->newline() << "} else {"; - s.op->indent(1); - // XXX Check return value - s.op->newline() << "stap_remove_vma_map_info(tsk, vm_start, vm_end, vm_pgoff);"; - s.op->indent(-1); - s.op->newline() << "}"; - s.op->newline() << "return 0;"; - s.op->indent(-1); - s.op->newline() << "}"; - s.op->newline() << "static struct stap_utrace_probe stap_utrace_probes[] = {"; s.op->indent(1); -- cgit From feec037da31161fdd4fa8cac7159ec7c99cc46a0 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 20 Mar 2009 14:17:44 +0100 Subject: Explicitly emit utrace vma callbacks. * tapsets.cxx (utrace_derived_probe_group::emit_vm_callback_probe_decl): Removed. (emit_vma_callback_probe_decl): New static helper function. (utrace_derived_probe_group::emit_module_decls): Emit vma callbacks. (utrace_derived_probe_group::emit_module_init): Activate vma callbacks. --- tapsets.cxx | 93 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 45 insertions(+), 48 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index c8852f0f..a668f016 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6188,6 +6188,27 @@ module_info::~module_info() delete sym_table; } +// Helper function to emit vma tracker callback _stp_tf_vm_cb. +static void +emit_vma_callback_probe_decl (systemtap_session& s, + string path, + int64_t pid) +{ + s.op->newline() << "{"; + if (pid == 0) + { + s.op->line() << " .pathname=\"" << path << "\","; + s.op->line() << " .pid=0,"; + } + else + { + s.op->line() << " .pathname=NULL,"; + s.op->line() << " .pid=" << pid << ","; + } + s.op->line() << " .callback=NULL,"; + s.op->line() << " .vm_callback=&_stp_tf_vm_cb,"; + s.op->line() << " },"; +} // ------------------------------------------------------------------------ @@ -6538,9 +6559,6 @@ private: bool flags_seen[UDPF_NFLAGS]; void emit_probe_decl (systemtap_session& s, utrace_derived_probe *p); - void emit_vm_callback_probe_decl (systemtap_session& s, bool has_path, - string path, int64_t pid, - string vm_callback); public: utrace_derived_probe_group(): num_probes(0), flags_seen() { } @@ -6921,40 +6939,6 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s, } -void -utrace_derived_probe_group::emit_vm_callback_probe_decl (systemtap_session& s, - bool has_path, - string path, - int64_t pid, - string vm_callback) -{ - s.op->newline() << "{"; - s.op->line() << " .tgt={"; - - if (has_path) - { - s.op->line() << " .pathname=\"" << path << "\","; - s.op->line() << " .pid=0,"; - } - else - { - s.op->line() << " .pathname=NULL,"; - s.op->line() << " .pid=" << pid << ","; - } - - s.op->line() << " .callback=NULL,"; - s.op->line() << " .vm_callback=&" << vm_callback << ","; - s.op->line() << " },"; - s.op->line() << " .pp=\"internal\","; - s.op->line() << " .ph=NULL,"; - s.op->line() << " .flags=(UDPF_NONE),"; - s.op->line() << " .ops={ NULL },"; - s.op->line() << " .events=0,"; - s.op->line() << " .engine_attached=0,"; - s.op->line() << " },"; -} - - void utrace_derived_probe_group::emit_module_decls (systemtap_session& s) { @@ -7170,6 +7154,23 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "return rc;"; s.op->newline(-1) << "}"; + // Emit vma callbacks. + s.op->newline() << "static struct stap_task_finder_target stap_utrace_vmcbs[] = {"; + s.op->indent(1); + if (! probes_by_path.empty()) + { + for (p_b_path_iterator it = probes_by_path.begin(); + it != probes_by_path.end(); it++) + emit_vma_callback_probe_decl (s, it->first, (int64_t)0); + } + if (! probes_by_pid.empty()) + { + for (p_b_pid_iterator it = probes_by_pid.begin(); + it != probes_by_pid.end(); it++) + emit_vma_callback_probe_decl (s, "", it->first); + } + s.op->newline(-1) << "};"; + s.op->newline() << "static struct stap_utrace_probe stap_utrace_probes[] = {"; s.op->indent(1); @@ -7179,12 +7180,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) for (p_b_path_iterator it = probes_by_path.begin(); it != probes_by_path.end(); it++) { - // Emit a "fake" probe decl that is really a hook for to get - // our vm_callback called. - string path = it->first; - emit_vm_callback_probe_decl (s, true, path, (int64_t)0, - "_stp_tf_vm_cb"); - for (unsigned i = 0; i < it->second.size(); i++) { utrace_derived_probe *p = it->second[i]; @@ -7199,11 +7194,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) for (p_b_pid_iterator it = probes_by_pid.begin(); it != probes_by_pid.end(); it++) { - // Emit a "fake" probe decl that is really a hook for to get - // our vm_callback called. - emit_vm_callback_probe_decl (s, false, "", it->first, - "_stp_tf_vm_cb"); - for (unsigned i = 0; i < it->second.size(); i++) { utrace_derived_probe *p = it->second[i]; @@ -7222,6 +7212,13 @@ utrace_derived_probe_group::emit_module_init (systemtap_session& s) return; s.op->newline(); + s.op->newline() << "/* ---- utrace vma callbacks ---- */"; + s.op->newline() << "for (i=0; iindent(1); + s.op->newline() << "struct stap_task_finder_target *r = &stap_utrace_vmcbs[i];"; + s.op->newline() << "rc = stap_register_task_finder_target(r);"; + s.op->newline(-1) << "}"; + s.op->newline() << "/* ---- utrace probes ---- */"; s.op->newline() << "for (i=0; iindent(1); -- cgit From 8813a27cd47e035806cb3d859cfd95d3e0fb76bc Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 20 Mar 2009 14:33:38 +0100 Subject: Emit vma callbacks for itrace. * tapsets.cxx (itrace_derived_probe_group::emit_module_decls): Emit vma callbacks. (itrace_derived_probe_group::emit_module_init): Activate vma callbacks. --- tapsets.cxx | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/tapsets.cxx b/tapsets.cxx index a668f016..8118c838 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6453,6 +6453,23 @@ itrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(-1) << "return rc;"; s.op->newline(-1) << "}"; + // Emit vma callbacks. + s.op->newline() << "static struct stap_task_finder_target stap_itrace_vmcbs[] = {"; + s.op->indent(1); + if (! probes_by_path.empty()) + { + for (p_b_path_iterator it = probes_by_path.begin(); + it != probes_by_path.end(); it++) + emit_vma_callback_probe_decl (s, it->first, (int64_t)0); + } + if (! probes_by_pid.empty()) + { + for (p_b_pid_iterator it = probes_by_pid.begin(); + it != probes_by_pid.end(); it++) + emit_vma_callback_probe_decl (s, "", it->first); + } + s.op->newline(-1) << "};"; + s.op->newline() << "static struct stap_itrace_probe stap_itrace_probes[] = {"; s.op->indent(1); @@ -6493,6 +6510,14 @@ itrace_derived_probe_group::emit_module_init (systemtap_session& s) if (probes_by_path.empty() && probes_by_pid.empty()) return; + s.op->newline(); + s.op->newline() << "/* ---- itrace vma callbacks ---- */"; + s.op->newline() << "for (i=0; iindent(1); + s.op->newline() << "struct stap_task_finder_target *r = &stap_itrace_vmcbs[i];"; + s.op->newline() << "rc = stap_register_task_finder_target(r);"; + s.op->newline(-1) << "}"; + s.op->newline(); s.op->newline() << "/* ---- itrace probes ---- */"; -- cgit From c9a05b1c5a3219dcc6b9f4060b98e76a67f5795b Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 20 Mar 2009 14:57:00 +0100 Subject: Emit vma callbacks for uprobes. * tapsets.cxx (uprobe_derived_probe_group::emit_module_decls): Emit vma callbacks. (uprobe_derived_probe_group::emit_module_init): Activate vma callbacks. * testsuite/systemtap.context/usymbols.exp: Track through uprobes, so as to make sure we have the symbols. --- tapsets.cxx | 20 ++++++++++++++++++++ testsuite/systemtap.context/usymbols.exp | 3 ++- 2 files changed, 22 insertions(+), 1 deletion(-) diff --git a/tapsets.cxx b/tapsets.cxx index 8118c838..d6f89563 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -7490,6 +7490,19 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(-1) << "} stap_uprobes [MAXUPROBES];"; s.op->newline() << "DEFINE_MUTEX(stap_uprobes_lock);"; // protects against concurrent registration/unregistration + // Emit vma callbacks. + s.op->newline() << "static struct stap_task_finder_target stap_uprobe_vmcbs[] = {"; + s.op->indent(1); + for (unsigned i = 0; i < probes.size(); i++) + { + uprobe_derived_probe* p = probes[i]; + if (p->pid != 0) + emit_vma_callback_probe_decl (s, "", p->pid); + else + emit_vma_callback_probe_decl (s, p->module, (int64_t)0); + } + s.op->newline(-1) << "};"; + s.op->newline() << "static struct stap_uprobe_spec {"; s.op->newline(1) << "struct stap_task_finder_target finder;"; s.op->newline() << "unsigned long address;"; @@ -7690,6 +7703,13 @@ void uprobe_derived_probe_group::emit_module_init (systemtap_session& s) { if (probes.empty()) return; + s.op->newline() << "/* ---- uprobe vma callbacks ---- */"; + s.op->newline() << "for (i=0; iindent(1); + s.op->newline() << "struct stap_task_finder_target *r = &stap_uprobe_vmcbs[i];"; + s.op->newline() << "rc = stap_register_task_finder_target(r);"; + s.op->newline(-1) << "}"; + s.op->newline() << "/* ---- user probes ---- */"; s.op->newline() << "for (j=0; j Date: Wed, 1 Apr 2009 11:26:01 -0400 Subject: semok/badvar.stp test: add stap -p2 as for other semok tests --- testsuite/semok/badvar.stp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testsuite/semok/badvar.stp b/testsuite/semok/badvar.stp index b3bd2d67..677187a3 100755 --- a/testsuite/semok/badvar.stp +++ b/testsuite/semok/badvar.stp @@ -1,7 +1,9 @@ -#! stap --skip-badvars +#! /bin/sh +stap -p2 --skip-badvars -e ' probe syscall.read { if ($foo == 0) printf ("Voila! It works..\n") exit () } +' -- cgit From 76eb4a5d7a17bd8c37a679590c55b94e200042d0 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Wed, 1 Apr 2009 11:30:50 -0400 Subject: PR4105: support up to 9 (up from 5) array index dimensions * runtime/map-gen.c, pmap-gen.c: Hand-expand arity 6..9 cases throughout. * testsuite/buildok/thirty.stp: New test. * testsuite/buildko/two.stp: New test. An Alan Smithee patch. --- runtime/map-gen.c | 291 ++++++++++++++++++++++++++++++++++++ runtime/pmap-gen.c | 343 +++++++++++++++++++++++++++++++++++++++++++ testsuite/buildko/two.stp | 14 ++ testsuite/buildok/thirty.stp | 49 +++++++ 4 files changed, 697 insertions(+) create mode 100644 testsuite/buildko/two.stp create mode 100644 testsuite/buildok/thirty.stp diff --git a/runtime/map-gen.c b/runtime/map-gen.c index c4bdf2c7..fdb75089 100644 --- a/runtime/map-gen.c +++ b/runtime/map-gen.c @@ -26,6 +26,14 @@ #define JOIN5x(a,b,c,d,e,f) a##_##b##c##d##e##f #define JOIN6(a,b,c,d,e,f,g) JOIN6x(a,b,c,d,e,f,g) #define JOIN6x(a,b,c,d,e,f,g) a##_##b##c##d##e##f##g +#define JOIN7(a,b,c,d,e,f,g,h) JOIN7x(a,b,c,d,e,f,g,h) +#define JOIN7x(a,b,c,d,e,f,g,h) a##_##b##c##d##e##f##g##h +#define JOIN8(a,b,c,d,e,f,g,h,i) JOIN8x(a,b,c,d,e,f,g,h,i) +#define JOIN8x(a,b,c,d,e,f,g,h,i) a##_##b##c##d##e##f##g##h##i +#define JOIN9(a,b,c,d,e,f,g,h,i,j) JOIN9x(a,b,c,d,e,f,g,h,i,j) +#define JOIN9x(a,b,c,d,e,f,g,h,i,j) a##_##b##c##d##e##f##g##h##i##j +#define JOIN10(a,b,c,d,e,f,g,h,i,j,k) JOIN10x(a,b,c,d,e,f,g,h,i,j,k) +#define JOIN10x(a,b,c,d,e,f,g,h,i,j,k) a##_##b##c##d##e##f##g##h##i##j##k #include "map.h" @@ -162,6 +170,113 @@ #define KEY5_HASH JOIN(KEY5NAME,hash) #endif /* defined(KEY5_TYPE) */ +#if defined (KEY6_TYPE) +#undef KEY_ARITY +#define KEY_ARITY 6 +#if KEY6_TYPE == STRING +#define KEY6TYPE char* +#define KEY6NAME str +#define KEY6N s +#define KEY6STOR char key6[MAP_STRING_LENGTH] +#define KEY6CPY(m) str_copy(m->key6, key6) +#else +#define KEY6TYPE int64_t +#define KEY6NAME int64 +#define KEY6N i +#define KEY6STOR int64_t key6 +#define KEY6CPY(m) m->key6=key6 +#endif +#define KEY6_EQ_P JOIN(KEY6NAME,eq_p) +#define KEY6_HASH JOIN(KEY6NAME,hash) +#endif /* defined(KEY6_TYPE) */ + +#if defined (KEY7_TYPE) +#undef KEY_ARITY +#define KEY_ARITY 7 +#if KEY7_TYPE == STRING +#define KEY7TYPE char* +#define KEY7NAME str +#define KEY7N s +#define KEY7STOR char key7[MAP_STRING_LENGTH] +#define KEY7CPY(m) str_copy(m->key7, key7) +#else +#define KEY7TYPE int64_t +#define KEY7NAME int64 +#define KEY7N i +#define KEY7STOR int64_t key7 +#define KEY7CPY(m) m->key7=key7 +#endif +#define KEY7_EQ_P JOIN(KEY7NAME,eq_p) +#define KEY7_HASH JOIN(KEY7NAME,hash) +#endif /* defined(KEY7_TYPE) */ + +#if defined (KEY7_TYPE) +#undef KEY_ARITY +#define KEY_ARITY 7 +#if KEY7_TYPE == STRING +#define KEY7TYPE char* +#define KEY7NAME str +#define KEY7N s +#define KEY7STOR char key7[MAP_STRING_LENGTH] +#define KEY7CPY(m) str_copy(m->key7, key7) +#else +#define KEY7TYPE int64_t +#define KEY7NAME int64 +#define KEY7N i +#define KEY7STOR int64_t key7 +#define KEY7CPY(m) m->key7=key7 +#endif +#define KEY7_EQ_P JOIN(KEY7NAME,eq_p) +#define KEY7_HASH JOIN(KEY7NAME,hash) +#endif /* defined(KEY7_TYPE) */ + +#if defined (KEY8_TYPE) +#undef KEY_ARITY +#define KEY_ARITY 8 +#if KEY8_TYPE == STRING +#define KEY8TYPE char* +#define KEY8NAME str +#define KEY8N s +#define KEY8STOR char key8[MAP_STRING_LENGTH] +#define KEY8CPY(m) str_copy(m->key8, key8) +#else +#define KEY8TYPE int64_t +#define KEY8NAME int64 +#define KEY8N i +#define KEY8STOR int64_t key8 +#define KEY8CPY(m) m->key8=key8 +#endif +#define KEY8_EQ_P JOIN(KEY8NAME,eq_p) +#define KEY8_HASH JOIN(KEY8NAME,hash) +#endif /* defined(KEY8_TYPE) */ + +#if defined (KEY9_TYPE) +#undef KEY_ARITY +#define KEY_ARITY 9 +#if KEY9_TYPE == STRING +#define KEY9TYPE char* +#define KEY9NAME str +#define KEY9N s +#define KEY9STOR char key9[MAP_STRING_LENGTH] +#define KEY9CPY(m) str_copy(m->key9, key9) +#else +#define KEY9TYPE int64_t +#define KEY9NAME int64 +#define KEY9N i +#define KEY9STOR int64_t key9 +#define KEY9CPY(m) m->key9=key9 +#endif +#define KEY9_EQ_P JOIN(KEY9NAME,eq_p) +#define KEY9_HASH JOIN(KEY9NAME,hash) +#endif /* defined(KEY9_TYPE) */ + +/* Not so many, cowboy! */ +#if defined (KEY10_TYPE) +#error "excessive key arity == too many array indexes" +#endif + + + #if KEY_ARITY == 1 #define KEYSYM(x) JOIN2(x,KEY1N,VALN) #define ALLKEYS(x) x##1 @@ -187,6 +302,26 @@ #define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5 #define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5 #define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);} +#elif KEY_ARITY == 6 +#define KEYSYM(x) JOIN7(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,VALN) +#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6 +#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6 +#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);} +#elif KEY_ARITY == 7 +#define KEYSYM(x) JOIN8(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,VALN) +#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7 +#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7 +#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);} +#elif KEY_ARITY == 8 +#define KEYSYM(x) JOIN9(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,KEY8N,VALN) +#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8 +#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7, KEY8TYPE x##8 +#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);KEY8CPY(m);} +#elif KEY_ARITY == 9 +#define KEYSYM(x) JOIN10(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,KEY8N,KEY9N,VALN) +#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8, x##9 +#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7, KEY8TYPE x##8, KEY9TYPE x##9 +#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);KEY8CPY(m);KEY9CPY(m);} #endif /* */ @@ -208,6 +343,18 @@ struct KEYSYM(map_node) { KEY4STOR; #if KEY_ARITY > 4 KEY5STOR; +#if KEY_ARITY > 5 + KEY6STOR; +#if KEY_ARITY > 6 + KEY7STOR; +#if KEY_ARITY > 7 + KEY8STOR; +#if KEY_ARITY > 8 + KEY9STOR; +#endif +#endif +#endif +#endif #endif #endif #endif @@ -266,6 +413,34 @@ static key_data KEYSYM(map_get_key) (struct map_node *mn, int n, int *type) if (type) *type = type_to_enum(KEY5TYPE); break; +#if KEY_ARITY > 5 + case 6: + ptr = (key_data)m->key6; + if (type) + *type = type_to_enum(KEY6TYPE); + break; +#if KEY_ARITY > 6 + case 7: + ptr = (key_data)m->key7; + if (type) + *type = type_to_enum(KEY7TYPE); + break; +#if KEY_ARITY > 7 + case 8: + ptr = (key_data)m->key8; + if (type) + *type = type_to_enum(KEY8TYPE); + break; +#if KEY_ARITY > 8 + case 9: + ptr = (key_data)m->key9; + if (type) + *type = type_to_enum(KEY9TYPE); + break; +#endif +#endif +#endif +#endif #endif #endif #endif @@ -309,6 +484,34 @@ static unsigned int KEYSYM(keycheck) (ALLKEYSD(key)) if (key5 == NULL) return 0; #endif + +#if KEY_ARITY > 5 +#if KEY6_TYPE == STRING + if (key6 == NULL) + return 0; +#endif + +#if KEY_ARITY > 6 +#if KEY7_TYPE == STRING + if (key7 == NULL) + return 0; +#endif + +#if KEY_ARITY > 7 +#if KEY8_TYPE == STRING + if (key8 == NULL) + return 0; +#endif + +#if KEY_ARITY > 8 +#if KEY9_TYPE == STRING + if (key9 == NULL) + return 0; +#endif +#endif +#endif +#endif +#endif #endif #endif #endif @@ -327,6 +530,18 @@ static unsigned int KEYSYM(hash) (ALLKEYSD(key)) hash ^= KEY4_HASH(key4); #if KEY_ARITY > 4 hash ^= KEY5_HASH(key5); +#if KEY_ARITY > 5 + hash ^= KEY6_HASH(key6); +#if KEY_ARITY > 6 + hash ^= KEY7_HASH(key7); +#if KEY_ARITY > 7 + hash ^= KEY8_HASH(key8); +#if KEY_ARITY > 8 + hash ^= KEY9_HASH(key9); +#endif +#endif +#endif +#endif #endif #endif #endif @@ -411,6 +626,18 @@ static int KEYSYM(__stp_map_set) (MAP map, ALLKEYSD(key), VSTYPE val, int add) && KEY4_EQ_P(n->key4, key4) #if KEY_ARITY > 4 && KEY5_EQ_P(n->key5, key5) +#if KEY_ARITY > 5 + && KEY6_EQ_P(n->key6, key6) +#if KEY_ARITY > 6 + && KEY7_EQ_P(n->key7, key7) +#if KEY_ARITY > 7 + && KEY8_EQ_P(n->key8, key8) +#if KEY_ARITY > 8 + && KEY9_EQ_P(n->key9, key9) +#endif +#endif +#endif +#endif #endif #endif #endif @@ -462,6 +689,18 @@ static VALTYPE KEYSYM(_stp_map_get) (MAP map, ALLKEYSD(key)) && KEY4_EQ_P(n->key4, key4) #if KEY_ARITY > 4 && KEY5_EQ_P(n->key5, key5) +#if KEY_ARITY > 5 + && KEY6_EQ_P(n->key6, key6) +#if KEY_ARITY > 6 + && KEY7_EQ_P(n->key7, key7) +#if KEY_ARITY > 7 + && KEY8_EQ_P(n->key8, key8) +#if KEY_ARITY > 8 + && KEY9_EQ_P(n->key9, key9) +#endif +#endif +#endif +#endif #endif #endif #endif @@ -498,6 +737,18 @@ static int KEYSYM(_stp_map_del) (MAP map, ALLKEYSD(key)) && KEY4_EQ_P(n->key4, key4) #if KEY_ARITY > 4 && KEY5_EQ_P(n->key5, key5) +#if KEY_ARITY > 5 + && KEY6_EQ_P(n->key6, key6) +#if KEY_ARITY > 6 + && KEY7_EQ_P(n->key7, key7) +#if KEY_ARITY > 7 + && KEY8_EQ_P(n->key8, key8) +#if KEY_ARITY > 8 + && KEY9_EQ_P(n->key9, key9) +#endif +#endif +#endif +#endif #endif #endif #endif @@ -535,6 +786,18 @@ static int KEYSYM(_stp_map_exists) (MAP map, ALLKEYSD(key)) && KEY4_EQ_P(n->key4, key4) #if KEY_ARITY > 4 && KEY5_EQ_P(n->key5, key5) +#if KEY_ARITY > 5 + && KEY6_EQ_P(n->key6, key6) +#if KEY_ARITY > 6 + && KEY7_EQ_P(n->key7, key7) +#if KEY_ARITY > 7 + && KEY8_EQ_P(n->key8, key8) +#if KEY_ARITY > 8 + && KEY9_EQ_P(n->key9, key9) +#endif +#endif +#endif +#endif #endif #endif #endif @@ -582,6 +845,34 @@ static int KEYSYM(_stp_map_exists) (MAP map, ALLKEYSD(key)) #undef KEY5STOR #undef KEY5CPY +#undef KEY6NAME +#undef KEY6N +#undef KEY6TYPE +#undef KEY6_TYPE +#undef KEY6STOR +#undef KEY6CPY + +#undef KEY7NAME +#undef KEY7N +#undef KEY7TYPE +#undef KEY7_TYPE +#undef KEY7STOR +#undef KEY7CPY + +#undef KEY8NAME +#undef KEY8N +#undef KEY8TYPE +#undef KEY8_TYPE +#undef KEY8STOR +#undef KEY8CPY + +#undef KEY9NAME +#undef KEY9N +#undef KEY9TYPE +#undef KEY9_TYPE +#undef KEY9STOR +#undef KEY9CPY + #undef KEY_ARITY #undef ALLKEYS #undef ALLKEYSD diff --git a/runtime/pmap-gen.c b/runtime/pmap-gen.c index 86c3dc42..c95adc6b 100644 --- a/runtime/pmap-gen.c +++ b/runtime/pmap-gen.c @@ -26,6 +26,14 @@ #define JOIN5x(a,b,c,d,e,f) a##_##b##c##d##e##f #define JOIN6(a,b,c,d,e,f,g) JOIN6x(a,b,c,d,e,f,g) #define JOIN6x(a,b,c,d,e,f,g) a##_##b##c##d##e##f##g +#define JOIN7(a,b,c,d,e,f,g,h) JOIN7x(a,b,c,d,e,f,g,h) +#define JOIN7x(a,b,c,d,e,f,g,h) a##_##b##c##d##e##f##g##h +#define JOIN8(a,b,c,d,e,f,g,h,i) JOIN8x(a,b,c,d,e,f,g,h,i) +#define JOIN8x(a,b,c,d,e,f,g,h,i) a##_##b##c##d##e##f##g##h##i +#define JOIN9(a,b,c,d,e,f,g,h,i,j) JOIN9x(a,b,c,d,e,f,g,h,i,j) +#define JOIN9x(a,b,c,d,e,f,g,h,i,j) a##_##b##c##d##e##f##g##h##i##j +#define JOIN10(a,b,c,d,e,f,g,h,i,j,k) JOIN10x(a,b,c,d,e,f,g,h,i,j,k) +#define JOIN10x(a,b,c,d,e,f,g,h,i,j,k) a##_##b##c##d##e##f##g##h##i##j##k #include "map.h" @@ -162,6 +170,113 @@ #define KEY5_HASH JOIN(KEY5NAME,hash) #endif /* defined(KEY5_TYPE) */ +#if defined (KEY6_TYPE) +#undef KEY_ARITY +#define KEY_ARITY 6 +#if KEY6_TYPE == STRING +#define KEY6TYPE char* +#define KEY6NAME str +#define KEY6N s +#define KEY6STOR char key6[MAP_STRING_LENGTH] +#define KEY6CPY(m) str_copy(m->key6, key6) +#else +#define KEY6TYPE int64_t +#define KEY6NAME int64 +#define KEY6N i +#define KEY6STOR int64_t key6 +#define KEY6CPY(m) m->key6=key6 +#endif +#define KEY6_EQ_P JOIN(KEY6NAME,eq_p) +#define KEY6_HASH JOIN(KEY6NAME,hash) +#endif /* defined(KEY6_TYPE) */ + +#if defined (KEY7_TYPE) +#undef KEY_ARITY +#define KEY_ARITY 7 +#if KEY7_TYPE == STRING +#define KEY7TYPE char* +#define KEY7NAME str +#define KEY7N s +#define KEY7STOR char key7[MAP_STRING_LENGTH] +#define KEY7CPY(m) str_copy(m->key7, key7) +#else +#define KEY7TYPE int64_t +#define KEY7NAME int64 +#define KEY7N i +#define KEY7STOR int64_t key7 +#define KEY7CPY(m) m->key7=key7 +#endif +#define KEY7_EQ_P JOIN(KEY7NAME,eq_p) +#define KEY7_HASH JOIN(KEY7NAME,hash) +#endif /* defined(KEY7_TYPE) */ + +#if defined (KEY7_TYPE) +#undef KEY_ARITY +#define KEY_ARITY 7 +#if KEY7_TYPE == STRING +#define KEY7TYPE char* +#define KEY7NAME str +#define KEY7N s +#define KEY7STOR char key7[MAP_STRING_LENGTH] +#define KEY7CPY(m) str_copy(m->key7, key7) +#else +#define KEY7TYPE int64_t +#define KEY7NAME int64 +#define KEY7N i +#define KEY7STOR int64_t key7 +#define KEY7CPY(m) m->key7=key7 +#endif +#define KEY7_EQ_P JOIN(KEY7NAME,eq_p) +#define KEY7_HASH JOIN(KEY7NAME,hash) +#endif /* defined(KEY7_TYPE) */ + +#if defined (KEY8_TYPE) +#undef KEY_ARITY +#define KEY_ARITY 8 +#if KEY8_TYPE == STRING +#define KEY8TYPE char* +#define KEY8NAME str +#define KEY8N s +#define KEY8STOR char key8[MAP_STRING_LENGTH] +#define KEY8CPY(m) str_copy(m->key8, key8) +#else +#define KEY8TYPE int64_t +#define KEY8NAME int64 +#define KEY8N i +#define KEY8STOR int64_t key8 +#define KEY8CPY(m) m->key8=key8 +#endif +#define KEY8_EQ_P JOIN(KEY8NAME,eq_p) +#define KEY8_HASH JOIN(KEY8NAME,hash) +#endif /* defined(KEY8_TYPE) */ + +#if defined (KEY9_TYPE) +#undef KEY_ARITY +#define KEY_ARITY 9 +#if KEY9_TYPE == STRING +#define KEY9TYPE char* +#define KEY9NAME str +#define KEY9N s +#define KEY9STOR char key9[MAP_STRING_LENGTH] +#define KEY9CPY(m) str_copy(m->key9, key9) +#else +#define KEY9TYPE int64_t +#define KEY9NAME int64 +#define KEY9N i +#define KEY9STOR int64_t key9 +#define KEY9CPY(m) m->key9=key9 +#endif +#define KEY9_EQ_P JOIN(KEY9NAME,eq_p) +#define KEY9_HASH JOIN(KEY9NAME,hash) +#endif /* defined(KEY9_TYPE) */ + +/* Not so many, cowboy! */ +#if defined (KEY10_TYPE) +#error "excessive key arity == too many array indexes" +#endif + + + #if KEY_ARITY == 1 #define KEYSYM(x) JOIN2(x,KEY1N,VALN) #define ALLKEYS(x) x##1 @@ -187,6 +302,26 @@ #define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5 #define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5 #define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);} +#elif KEY_ARITY == 6 +#define KEYSYM(x) JOIN7(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,VALN) +#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6 +#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6 +#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);} +#elif KEY_ARITY == 7 +#define KEYSYM(x) JOIN8(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,VALN) +#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7 +#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7 +#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);} +#elif KEY_ARITY == 8 +#define KEYSYM(x) JOIN9(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,KEY8N,VALN) +#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8 +#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7, KEY8TYPE x##8 +#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);KEY8CPY(m);} +#elif KEY_ARITY == 9 +#define KEYSYM(x) JOIN10(x,KEY1N,KEY2N,KEY3N,KEY4N,KEY5N,KEY6N,KEY7N,KEY8N,KEY9N,VALN) +#define ALLKEYS(x) x##1, x##2, x##3, x##4, x##5, x##6, x##7, x##8, x##9 +#define ALLKEYSD(x) KEY1TYPE x##1, KEY2TYPE x##2, KEY3TYPE x##3, KEY4TYPE x##4, KEY5TYPE x##5, KEY6TYPE x##6, KEY7TYPE x##7, KEY8TYPE x##8, KEY9TYPE x##9 +#define KEYCPY(m) {KEY1CPY(m);KEY2CPY(m);KEY3CPY(m);KEY4CPY(m);KEY5CPY(m);KEY6CPY(m);KEY7CPY(m);KEY8CPY(m);KEY9CPY(m);} #endif /* */ @@ -208,6 +343,18 @@ struct KEYSYM(pmap_node) { KEY4STOR; #if KEY_ARITY > 4 KEY5STOR; +#if KEY_ARITY > 5 + KEY6STOR; +#if KEY_ARITY > 6 + KEY7STOR; +#if KEY_ARITY > 7 + KEY8STOR; +#if KEY_ARITY > 8 + KEY9STOR; +#endif +#endif +#endif +#endif #endif #endif #endif @@ -238,6 +385,18 @@ static int KEYSYM(pmap_key_cmp) (struct map_node *m1, struct map_node *m2) && KEY4_EQ_P(n1->key4, n2->key4) #if KEY_ARITY > 4 && KEY5_EQ_P(n1->key5, n2->key5) +#if KEY_ARITY > 5 + && KEY6_EQ_P(n1->key6, n2->key6) +#if KEY_ARITY > 6 + && KEY7_EQ_P(n1->key7, n2->key7) +#if KEY_ARITY > 7 + && KEY8_EQ_P(n1->key8, n2->key8) +#if KEY_ARITY > 8 + && KEY9_EQ_P(n1->key9, n2->key9) +#endif +#endif +#endif +#endif #endif #endif #endif @@ -282,6 +441,34 @@ static void KEYSYM(pmap_copy_keys) (struct map_node *m1, struct map_node *m2) #else dst->key5 = src->key5; #endif +#if KEY_ARITY > 5 +#if KEY6_TYPE == STRING + str_copy (dst->key6, src->key6); +#else + dst->key6 = src->key6; +#endif +#if KEY_ARITY > 6 +#if KEY7_TYPE == STRING + str_copy (dst->key7, src->key7); +#else + dst->key7 = src->key7; +#endif +#if KEY_ARITY > 7 +#if KEY8_TYPE == STRING + str_copy (dst->key8, src->key8); +#else + dst->key8 = src->key8; +#endif +#if KEY_ARITY > 8 +#if KEY9_TYPE == STRING + str_copy (dst->key9, src->key9); +#else + dst->key9 = src->key9; +#endif +#endif +#endif +#endif +#endif #endif #endif #endif @@ -330,6 +517,34 @@ static key_data KEYSYM(pmap_get_key) (struct map_node *mn, int n, int *type) if (type) *type = type_to_enum(KEY5TYPE); break; +#if KEY_ARITY > 5 + case 6: + ptr = (key_data)m->key6; + if (type) + *type = type_to_enum(KEY6TYPE); + break; +#if KEY_ARITY > 6 + case 7: + ptr = (key_data)m->key7; + if (type) + *type = type_to_enum(KEY7TYPE); + break; +#if KEY_ARITY > 7 + case 8: + ptr = (key_data)m->key8; + if (type) + *type = type_to_enum(KEY8TYPE); + break; +#if KEY_ARITY > 8 + case 9: + ptr = (key_data)m->key9; + if (type) + *type = type_to_enum(KEY9TYPE); + break; +#endif +#endif +#endif +#endif #endif #endif #endif @@ -373,6 +588,34 @@ static unsigned int KEYSYM(pkeycheck) (ALLKEYSD(key)) if (key5 == NULL) return 0; #endif + +#if KEY_ARITY > 5 +#if KEY6_TYPE == STRING + if (key6 == NULL) + return 0; +#endif + +#if KEY_ARITY > 6 +#if KEY7_TYPE == STRING + if (key7 == NULL) + return 0; +#endif + +#if KEY_ARITY > 7 +#if KEY8_TYPE == STRING + if (key8 == NULL) + return 0; +#endif + +#if KEY_ARITY > 8 +#if KEY9_TYPE == STRING + if (key9 == NULL) + return 0; +#endif +#endif +#endif +#endif +#endif #endif #endif #endif @@ -391,6 +634,18 @@ static unsigned int KEYSYM(phash) (ALLKEYSD(key)) hash ^= KEY4_HASH(key4); #if KEY_ARITY > 4 hash ^= KEY5_HASH(key5); +#if KEY_ARITY > 5 + hash ^= KEY6_HASH(key6); +#if KEY_ARITY > 6 + hash ^= KEY7_HASH(key7); +#if KEY_ARITY > 7 + hash ^= KEY8_HASH(key8); +#if KEY_ARITY > 8 + hash ^= KEY9_HASH(key9); +#endif +#endif +#endif +#endif #endif #endif #endif @@ -504,6 +759,18 @@ static int KEYSYM(__stp_pmap_set) (MAP map, ALLKEYSD(key), VSTYPE val, int add) && KEY4_EQ_P(n->key4, key4) #if KEY_ARITY > 4 && KEY5_EQ_P(n->key5, key5) +#if KEY_ARITY > 5 + && KEY6_EQ_P(n->key6, key6) +#if KEY_ARITY > 6 + && KEY7_EQ_P(n->key7, key7) +#if KEY_ARITY > 7 + && KEY8_EQ_P(n->key8, key8) +#if KEY_ARITY > 8 + && KEY9_EQ_P(n->key9, key9) +#endif +#endif +#endif +#endif #endif #endif #endif @@ -587,6 +854,18 @@ static VALTYPE KEYSYM(_stp_pmap_get_cpu) (PMAP pmap, ALLKEYSD(key)) && KEY4_EQ_P(n->key4, key4) #if KEY_ARITY > 4 && KEY5_EQ_P(n->key5, key5) +#if KEY_ARITY > 5 + && KEY6_EQ_P(n->key6, key6) +#if KEY_ARITY > 6 + && KEY7_EQ_P(n->key7, key7) +#if KEY_ARITY > 7 + && KEY8_EQ_P(n->key8, key8) +#if KEY_ARITY > 8 + && KEY9_EQ_P(n->key9, key9) +#endif +#endif +#endif +#endif #endif #endif #endif @@ -637,6 +916,18 @@ static VALTYPE KEYSYM(_stp_pmap_get) (PMAP pmap, ALLKEYSD(key)) && KEY4_EQ_P(n->key4, key4) #if KEY_ARITY > 4 && KEY5_EQ_P(n->key5, key5) +#if KEY_ARITY > 5 + && KEY6_EQ_P(n->key6, key6) +#if KEY_ARITY > 6 + && KEY7_EQ_P(n->key7, key7) +#if KEY_ARITY > 7 + && KEY8_EQ_P(n->key8, key8) +#if KEY_ARITY > 8 + && KEY9_EQ_P(n->key9, key9) +#endif +#endif +#endif +#endif #endif #endif #endif @@ -669,6 +960,18 @@ static VALTYPE KEYSYM(_stp_pmap_get) (PMAP pmap, ALLKEYSD(key)) && KEY4_EQ_P(n->key4, key4) #if KEY_ARITY > 4 && KEY5_EQ_P(n->key5, key5) +#if KEY_ARITY > 5 + && KEY6_EQ_P(n->key6, key6) +#if KEY_ARITY > 6 + && KEY7_EQ_P(n->key7, key7) +#if KEY_ARITY > 7 + && KEY8_EQ_P(n->key8, key8) +#if KEY_ARITY > 8 + && KEY9_EQ_P(n->key9, key9) +#endif +#endif +#endif +#endif #endif #endif #endif @@ -723,6 +1026,18 @@ static int KEYSYM(__stp_pmap_del) (MAP map, ALLKEYSD(key)) && KEY4_EQ_P(n->key4, key4) #if KEY_ARITY > 4 && KEY5_EQ_P(n->key5, key5) +#if KEY_ARITY > 5 + && KEY6_EQ_P(n->key6, key6) +#if KEY_ARITY > 6 + && KEY7_EQ_P(n->key7, key7) +#if KEY_ARITY > 7 + && KEY8_EQ_P(n->key8, key8) +#if KEY_ARITY > 8 + && KEY9_EQ_P(n->key9, key9) +#endif +#endif +#endif +#endif #endif #endif #endif @@ -788,6 +1103,34 @@ static int KEYSYM(_stp_pmap_del) (PMAP pmap, ALLKEYSD(key)) #undef KEY5STOR #undef KEY5CPY +#undef KEY6NAME +#undef KEY6N +#undef KEY6TYPE +#undef KEY6_TYPE +#undef KEY6STOR +#undef KEY6CPY + +#undef KEY7NAME +#undef KEY7N +#undef KEY7TYPE +#undef KEY7_TYPE +#undef KEY7STOR +#undef KEY7CPY + +#undef KEY8NAME +#undef KEY8N +#undef KEY8TYPE +#undef KEY8_TYPE +#undef KEY8STOR +#undef KEY8CPY + +#undef KEY9NAME +#undef KEY9N +#undef KEY9TYPE +#undef KEY9_TYPE +#undef KEY9STOR +#undef KEY9CPY + #undef KEY_ARITY #undef ALLKEYS #undef ALLKEYSD diff --git a/testsuite/buildko/two.stp b/testsuite/buildko/two.stp new file mode 100644 index 00000000..25350dc0 --- /dev/null +++ b/testsuite/buildko/two.stp @@ -0,0 +1,14 @@ +#! stap -p4 + +# tests overwide arrays +global a10 +global b10 +global c10 +global d10 + +probe begin { + a10[0,"a",0,"a",0,"a",0,"a",0,"a"]="a"; + b10["b",0,"b",0,"b",0,"b",0,"b",0]=0; + c10[0,"a",0,"a",0,"a",0,"a",0,"a"]<<<0; + d10["b",0,"b",0,"b",0,"b",0,"b",0]<<<0; +} diff --git a/testsuite/buildok/thirty.stp b/testsuite/buildok/thirty.stp new file mode 100644 index 00000000..042bae56 --- /dev/null +++ b/testsuite/buildok/thirty.stp @@ -0,0 +1,49 @@ +#! stap -p4 + +# tests wide arrays +global a1, a2, a3, a4, a5, a6, a7, a8, a9 +global b1, b2, b3, b4, b5, b6, b7, b8, b9 +global c1, c2, c3, c4, c5, c6, c7, c8, c9 +global d1, d2, d3, d4, d5, d6, d7, d8, d9 + +probe begin { + a1[0]="a"; + a2[0,"a"]="a"; + a3[0,"a",0]="a"; + a4[0,"a",0,"a"]="a"; + a5[0,"a",0,"a",0]="a"; + a6[0,"a",0,"a",0,"a"]="a"; + a7[0,"a",0,"a",0,"a",0]="a"; + a8[0,"a",0,"a",0,"a",0,"a"]="a"; + a9[0,"a",0,"a",0,"a",0,"a",0]="a"; + + b1["b"]=0; + b2["b",0]=0; + b3["b",0,"b"]=0; + b4["b",0,"b",0]=0; + b5["b",0,"b",0,"b"]=0; + b6["b",0,"b",0,"b",0]=0; + b7["b",0,"b",0,"b",0,"b"]=0; + b8["b",0,"b",0,"b",0,"b",0]=0; + b9["b",0,"b",0,"b",0,"b",0,"b"]=0; + + c1[0]<<<0; + c2[0,"a"]<<<0; + c3[0,"a",0]<<<0; + c4[0,"a",0,"a"]<<<0; + c5[0,"a",0,"a",0]<<<0; + c6[0,"a",0,"a",0,"a"]<<<0; + c7[0,"a",0,"a",0,"a",0]<<<0; + c8[0,"a",0,"a",0,"a",0,"a"]<<<0; + c9[0,"a",0,"a",0,"a",0,"a",0]<<<0; + + d1["b"]<<<0; + d2["b",0]<<<0; + d3["b",0,"b"]<<<0; + d4["b",0,"b",0]<<<0; + d5["b",0,"b",0,"b"]<<<0; + d6["b",0,"b",0,"b",0]<<<0; + d7["b",0,"b",0,"b",0,"b"]<<<0; + d8["b",0,"b",0,"b",0,"b",0]<<<0; + d9["b",0,"b",0,"b",0,"b",0,"b"]<<<0; +} -- cgit From a63eb2802d09a6e004173cfbbb0bb9fdf8b486b9 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 1 Apr 2009 12:25:14 +0200 Subject: context.exp: log which subtest is being sourced. --- testsuite/systemtap.context/context.exp | 1 + 1 file changed, 1 insertion(+) diff --git a/testsuite/systemtap.context/context.exp b/testsuite/systemtap.context/context.exp index 010db445..cec09b29 100644 --- a/testsuite/systemtap.context/context.exp +++ b/testsuite/systemtap.context/context.exp @@ -80,6 +80,7 @@ if {[build_modules] == 0} { } foreach test $testlist { + send_log "sourcing: $srcdir/$subdir/$test.tcl\n" source $srcdir/$subdir/$test.tcl } -- cgit From f34b7eea333adc0bc9dc8e51445c2bbc39e9bc82 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 1 Apr 2009 12:31:50 +0200 Subject: testsuite/systemtap.context/*.tcl: Don't wait 4 whole minutes for timeout. --- testsuite/systemtap.context/args.tcl | 2 +- testsuite/systemtap.context/backtrace.tcl | 2 +- testsuite/systemtap.context/num_args.tcl | 2 +- testsuite/systemtap.context/pid.tcl | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/testsuite/systemtap.context/args.tcl b/testsuite/systemtap.context/args.tcl index 7cb79cdf..cffaeaef 100644 --- a/testsuite/systemtap.context/args.tcl +++ b/testsuite/systemtap.context/args.tcl @@ -1,6 +1,6 @@ spawn stap $srcdir/$subdir/args.stp expect { - -timeout 240 + -timeout 60 "READY" { exec echo 1 > /proc/stap_test_cmd expect { diff --git a/testsuite/systemtap.context/backtrace.tcl b/testsuite/systemtap.context/backtrace.tcl index ca60c369..6edda812 100644 --- a/testsuite/systemtap.context/backtrace.tcl +++ b/testsuite/systemtap.context/backtrace.tcl @@ -8,7 +8,7 @@ set m6 0 spawn stap -DMAXSTRINGLEN=256 $srcdir/$subdir/backtrace.stp #exp_internal 1 expect { - -timeout 240 + -timeout 60 "Systemtap probe: begin\r\n" { pass "backtrace of begin probe" exec echo 0 > /proc/stap_test_cmd diff --git a/testsuite/systemtap.context/num_args.tcl b/testsuite/systemtap.context/num_args.tcl index 7d12b433..62ac8dd3 100644 --- a/testsuite/systemtap.context/num_args.tcl +++ b/testsuite/systemtap.context/num_args.tcl @@ -3,7 +3,7 @@ foreach arglist $arglists { set tag [concat numeric $arglist] eval spawn stap $arglist $srcdir/$subdir/num_args.stp expect { - -timeout 240 + -timeout 60 "READY" { exec echo 1 > /proc/stap_test_cmd expect { diff --git a/testsuite/systemtap.context/pid.tcl b/testsuite/systemtap.context/pid.tcl index a2c091f1..70a87345 100644 --- a/testsuite/systemtap.context/pid.tcl +++ b/testsuite/systemtap.context/pid.tcl @@ -2,7 +2,7 @@ set tests [list execname pexecname pid ppid tid uid euid gid egid] spawn stap $srcdir/$subdir/pid.stp #exp_internal 1 expect { - -timeout 240 + -timeout 60 "READY" { set pid [exec echo 1 > /proc/stap_test_cmd &] set ppid {[0-9]*} -- cgit From 952ce18c9672046c052fc77d5da8f98e8ae75735 Mon Sep 17 00:00:00 2001 From: Stan Cox Date: Wed, 1 Apr 2009 15:48:24 -0400 Subject: Use alloca trick to keep argN active on GCC 4.1. * includes/sys/sdt.h (STAP_UNINLINE): New. (STAP_UNINLINE_LABEL): New. static_uprobes.exp: Match using charset instead of .* --- includes/sys/sdt.h | 48 ++++++++++++++++++++--------- tapsets.cxx | 5 +-- testsuite/systemtap.base/static_uprobes.exp | 2 +- 3 files changed, 38 insertions(+), 17 deletions(-) diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h index ba75076b..c3fa16d9 100644 --- a/includes/sys/sdt.h +++ b/includes/sys/sdt.h @@ -39,6 +39,19 @@ #endif #define STAP_LABEL(a,b) STAP_CONCAT(a,b) +/* Taking the address of a local label and/or referencing alloca prevents the + containing function from being inlined, which keeps the parameters visible. */ + +#if __GNUC__ == 4 && __GNUC_MINOR__ <= 1 +#include +#define STAP_UNINLINE alloca((size_t)0) +#else +#define STAP_UNINLINE +#endif + +#define STAP_UNINLINE_LABEL(label) \ + __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label + #define STAP_PROBE_(probe) \ do { \ STAP_PROBE_DATA(probe); \ @@ -46,13 +59,11 @@ do { \ "\tnop"); \ } while (0) -/* Taking the address of a local label prevents the containing function - from being inlined, which keeps the parameters visible. */ - #define STAP_PROBE1_(probe,label,parm1) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -61,9 +72,10 @@ do { \ #define STAP_PROBE2_(probe,label,parm1,parm2) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -72,10 +84,11 @@ do { \ #define STAP_PROBE3_(probe,label,parm1,parm2,parm3) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ - volatile __typeof__((parm1)) arg1 = parm1; \ + STAP_UNINLINE_LABEL(label); \ + volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -84,11 +97,12 @@ do { \ #define STAP_PROBE4_(probe,label,parm1,parm2,parm3,parm4) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ volatile __typeof__((parm4)) arg4 = parm4; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -97,12 +111,13 @@ do { \ #define STAP_PROBE5_(probe,label,parm1,parm2,parm3,parm4,parm5) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ volatile __typeof__((parm4)) arg4 = parm4; \ volatile __typeof__((parm5)) arg5 = parm5; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -111,13 +126,14 @@ do { \ #define STAP_PROBE6_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ volatile __typeof__((parm4)) arg4 = parm4; \ volatile __typeof__((parm5)) arg5 = parm5; \ volatile __typeof__((parm6)) arg6 = parm6; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -126,7 +142,7 @@ do { \ #define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ @@ -134,6 +150,7 @@ do { \ volatile __typeof__((parm5)) arg5 = parm5; \ volatile __typeof__((parm6)) arg6 = parm6; \ volatile __typeof__((parm7)) arg7 = parm7; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -142,7 +159,7 @@ do { \ #define STAP_PROBE8_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ @@ -151,6 +168,7 @@ do { \ volatile __typeof__((parm6)) arg6 = parm6; \ volatile __typeof__((parm7)) arg7 = parm7; \ volatile __typeof__((parm8)) arg8 = parm8; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -159,7 +177,7 @@ do { \ #define STAP_PROBE9_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ @@ -169,6 +187,7 @@ do { \ volatile __typeof__((parm7)) arg7 = parm7; \ volatile __typeof__((parm8)) arg8 = parm8; \ volatile __typeof__((parm9)) arg9 = parm9; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -177,7 +196,7 @@ do { \ #define STAP_PROBE10_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ @@ -188,6 +207,7 @@ do { \ volatile __typeof__((parm8)) arg8 = parm8; \ volatile __typeof__((parm9)) arg9 = parm9; \ volatile __typeof__((parm10)) arg10 = parm10; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ diff --git a/tapsets.cxx b/tapsets.cxx index 50ee563a..449d7cc0 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -5812,7 +5812,8 @@ dwarf_builder::build(systemtap_session & sess, && 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; @@ -5833,7 +5834,7 @@ dwarf_builder::build(systemtap_session & sess, return; } - if (probe_type == dwarf_no_probes) + else if (probe_type == dwarf_no_probes) { location->components[1]->functor = TOK_FUNCTION; location->components[1]->arg = new literal_string("*"); diff --git a/testsuite/systemtap.base/static_uprobes.exp b/testsuite/systemtap.base/static_uprobes.exp index 820626b8..d6b6e1e3 100644 --- a/testsuite/systemtap.base/static_uprobes.exp +++ b/testsuite/systemtap.base/static_uprobes.exp @@ -196,7 +196,7 @@ set ok 0 spawn stap -l "process(\"./sdt_types.x\").mark(\"*\")" expect { -timeout 180 - -re {mark\(\".*\"\)} { incr ok; exp_continue } + -re {mark\(\"[a-z_]+\"\)} { incr ok; exp_continue } timeout { fail "$test C (timeout)" } eof { } } -- cgit From dd1636396623adacdb9e6502adabd9195ae7ef33 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 1 Apr 2009 22:40:04 +0200 Subject: Wrap vma callbacks in STP_NEED_VMA_TRACKER. Will be defined by new ucontext symbol stapset. * tapset.cxx: Wrap all vma callbacks in STP_NEED_VMA_TRACKER. * testsuite/systemtap.context/usymbols.exp: Define STP_NEED_VMA_TRACKER explicitly for now. --- tapsets.cxx | 12 ++++++++++++ testsuite/systemtap.context/usymbols.exp | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/tapsets.cxx b/tapsets.cxx index 143edc64..0ee7054a 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6457,6 +6457,7 @@ itrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(-1) << "}"; // Emit vma callbacks. + s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; s.op->newline() << "static struct stap_task_finder_target stap_itrace_vmcbs[] = {"; s.op->indent(1); if (! probes_by_path.empty()) @@ -6472,6 +6473,7 @@ itrace_derived_probe_group::emit_module_decls (systemtap_session& s) emit_vma_callback_probe_decl (s, "", it->first); } s.op->newline(-1) << "};"; + s.op->newline() << "#endif"; s.op->newline() << "static struct stap_itrace_probe stap_itrace_probes[] = {"; s.op->indent(1); @@ -6514,12 +6516,14 @@ itrace_derived_probe_group::emit_module_init (systemtap_session& s) return; s.op->newline(); + s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; s.op->newline() << "/* ---- itrace vma callbacks ---- */"; s.op->newline() << "for (i=0; iindent(1); s.op->newline() << "struct stap_task_finder_target *r = &stap_itrace_vmcbs[i];"; s.op->newline() << "rc = stap_register_task_finder_target(r);"; s.op->newline(-1) << "}"; + s.op->newline() << "#endif"; s.op->newline(); s.op->newline() << "/* ---- itrace probes ---- */"; @@ -7183,6 +7187,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(-1) << "}"; // Emit vma callbacks. + s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; s.op->newline() << "static struct stap_task_finder_target stap_utrace_vmcbs[] = {"; s.op->indent(1); if (! probes_by_path.empty()) @@ -7198,6 +7203,7 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) emit_vma_callback_probe_decl (s, "", it->first); } s.op->newline(-1) << "};"; + s.op->newline() << "#endif"; s.op->newline() << "static struct stap_utrace_probe stap_utrace_probes[] = {"; s.op->indent(1); @@ -7240,6 +7246,7 @@ utrace_derived_probe_group::emit_module_init (systemtap_session& s) return; s.op->newline(); + s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; s.op->newline() << "/* ---- utrace vma callbacks ---- */"; s.op->newline() << "for (i=0; iindent(1); @@ -7253,6 +7260,7 @@ utrace_derived_probe_group::emit_module_init (systemtap_session& s) s.op->newline() << "struct stap_utrace_probe *p = &stap_utrace_probes[i];"; s.op->newline() << "rc = stap_register_task_finder_target(&p->tgt);"; s.op->newline(-1) << "}"; + s.op->newline() << "#endif"; // rollback all utrace probes s.op->newline() << "if (rc) {"; @@ -7494,6 +7502,7 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "DEFINE_MUTEX(stap_uprobes_lock);"; // protects against concurrent registration/unregistration // Emit vma callbacks. + s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; s.op->newline() << "static struct stap_task_finder_target stap_uprobe_vmcbs[] = {"; s.op->indent(1); for (unsigned i = 0; i < probes.size(); i++) @@ -7505,6 +7514,7 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) emit_vma_callback_probe_decl (s, p->module, (int64_t)0); } s.op->newline(-1) << "};"; + s.op->newline() << "#endif"; s.op->newline() << "static struct stap_uprobe_spec {"; s.op->newline(1) << "struct stap_task_finder_target finder;"; @@ -7706,12 +7716,14 @@ void uprobe_derived_probe_group::emit_module_init (systemtap_session& s) { if (probes.empty()) return; + s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; s.op->newline() << "/* ---- uprobe vma callbacks ---- */"; s.op->newline() << "for (i=0; iindent(1); s.op->newline() << "struct stap_task_finder_target *r = &stap_uprobe_vmcbs[i];"; s.op->newline() << "rc = stap_register_task_finder_target(r);"; s.op->newline(-1) << "}"; + s.op->newline() << "#endif"; s.op->newline() << "/* ---- user probes ---- */"; diff --git a/testsuite/systemtap.context/usymbols.exp b/testsuite/systemtap.context/usymbols.exp index 65f0a263..f95fd896 100644 --- a/testsuite/systemtap.context/usymbols.exp +++ b/testsuite/systemtap.context/usymbols.exp @@ -54,7 +54,9 @@ 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}] + +# XXX Cheat, explicitly add STP_NEED_VMA_TRACKER +set cmd [concat stap -DSTP_NEED_VMA_TRACKER -d $libpath -d $testexe -c $testexe -e {$script}] send_log "cmd: $cmd\n" catch {eval exec $cmd} res send_log "cmd output: $res\n" -- cgit From ae65abfb3d6c807f63adb11c060b1ca56b779c02 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Wed, 1 Apr 2009 17:20:05 -0400 Subject: PR10020 sys_sigaltstack param change The new code uses a %( kernel_v < "2.6.29" %) conditional to look at the passed pt_regs instead of named *bx parameters. A more general solution will be needed at some point. --- tapset/i686/syscalls.stp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tapset/i686/syscalls.stp b/tapset/i686/syscalls.stp index 8e69f622..2a89c19d 100644 --- a/tapset/i686/syscalls.stp +++ b/tapset/i686/syscalls.stp @@ -119,7 +119,7 @@ probe syscall.set_zone_reclaim.return = # probe syscall.sigaltstack = kernel.function("sys_sigaltstack") { name = "sigaltstack" - ussp = %( kernel_vr < "2.6.25" %? $ebx %: $bx %) + ussp = %( kernel_vr < "2.6.25" %? $ebx %: %( kernel_vr < "2.6.29" %? $bx %: $regs->bx %) %) argstr = sprintf("%p", ussp) } probe syscall.sigaltstack.return = kernel.function("sys_sigaltstack").return { -- cgit From 110b061ee15d15f9195af1e265da2e5d0066f8cc Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 1 Apr 2009 23:30:18 +0200 Subject: Move #endif for STP_NEED_VMA_TRACKER up to not cover other utrace callbacks. * tapsets.cxx (utrace_derived_probe_group::emit_module_init): Correct #endif. --- tapsets.cxx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tapsets.cxx b/tapsets.cxx index d36c362e..352930ee 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -7292,6 +7292,7 @@ utrace_derived_probe_group::emit_module_init (systemtap_session& s) s.op->newline() << "struct stap_task_finder_target *r = &stap_utrace_vmcbs[i];"; s.op->newline() << "rc = stap_register_task_finder_target(r);"; s.op->newline(-1) << "}"; + s.op->newline() << "#endif"; s.op->newline() << "/* ---- utrace probes ---- */"; s.op->newline() << "for (i=0; inewline() << "struct stap_utrace_probe *p = &stap_utrace_probes[i];"; s.op->newline() << "rc = stap_register_task_finder_target(&p->tgt);"; s.op->newline(-1) << "}"; - s.op->newline() << "#endif"; // rollback all utrace probes s.op->newline() << "if (rc) {"; -- cgit From 4cc40e829870dd6a1d9714706d38f5fd4b2ec982 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 1 Apr 2009 14:49:12 -0700 Subject: PR10016: Purge stap of all pgrp and system() usage We hereby no longer try to manipulate process groups in any way. We don't set a private process group, and we never kill() our entire group either. Instead of using system(), we now have a stap_system() which saves the child PID, so when we get a terminating signal we can pass it along to the child. Signals sent through the TTY have always worked, since the TTY sends it to the entire pgrp. However, if we're running as part of a wrapper script or GUI, which may not have a separate process group for stap, we still would like to allow "kill -TERM $STAPPID" to terminate stap nicely. There's still a short window of failure in the time that staprun is active, because we can't kill a setuid process from a user process. Once staprun drops privileges and execs to stapio though, everything should work fine. --- buildrun.cxx | 8 +++---- main.cxx | 77 ++++-------------------------------------------------------- util.cxx | 41 ++++++++++++++++++++++++++++---- util.h | 2 ++ 4 files changed, 47 insertions(+), 81 deletions(-) diff --git a/buildrun.cxx b/buildrun.cxx index 97357692..71a34c96 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -56,7 +56,7 @@ run_make_cmd(systemtap_session& s, string& make_cmd) make_cmd += " -s >/dev/null 2>&1"; if (s.verbose > 1) clog << "Running " << make_cmd << endl; - rc = system (make_cmd.c_str()); + rc = stap_system (make_cmd.c_str()); return rc; } @@ -223,7 +223,7 @@ kernel_built_uprobes (systemtap_session& s) { string grep_cmd = string ("/bin/grep -q unregister_uprobe ") + s.kernel_build_tree + string ("/Module.symvers"); - int rc = system (grep_cmd.c_str()); + int rc = stap_system (grep_cmd.c_str()); return (rc == 0); } @@ -274,7 +274,7 @@ copy_uprobes_symbols (systemtap_session& s) string uprobes_home = s.runtime_path + "/uprobes"; string cp_cmd = string("/bin/cp ") + uprobes_home + string("/Module.symvers ") + s.tmpdir; - int rc = system (cp_cmd.c_str()); + int rc = stap_system (cp_cmd.c_str()); return rc; } @@ -339,7 +339,7 @@ run_pass (systemtap_session& s) if (s.verbose>1) clog << "Running " << staprun_cmd << endl; - rc = system (staprun_cmd.c_str ()); + rc = stap_system (staprun_cmd.c_str ()); return rc; } diff --git a/main.cxx b/main.cxx index 3b88a1c8..794a5891 100644 --- a/main.cxx +++ b/main.cxx @@ -36,8 +36,6 @@ extern "C" { #include #include #include -#include -#include #include #include #include @@ -293,14 +291,9 @@ int pending_interrupts; extern "C" void handle_interrupt (int sig) { - if (pending_interrupts == 0) - kill (0, sig); // Forward signals to child processes if any. - + kill_stap_spawn(sig); pending_interrupts ++; - // NB: the "2" below is intended to skip the effect of the self-induced - // deferred signal coming from the kill() above. - - if (pending_interrupts > 2) // XXX: should be configurable? time-based? + if (pending_interrupts > 1) // XXX: should be configurable? time-based? { char msg[] = "Too many interrupts received, exiting.\n"; int rc = write (2, msg, sizeof(msg)-1); @@ -324,7 +317,7 @@ setup_signals (sighandler_t handler) sigaddset (&sa.sa_mask, SIGINT); sigaddset (&sa.sa_mask, SIGTERM); } - sa.sa_flags = 0; + sa.sa_flags = SA_RESTART; sigaction (SIGHUP, &sa, NULL); sigaction (SIGPIPE, &sa, NULL); @@ -332,61 +325,9 @@ 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 @@ -899,16 +840,6 @@ runner (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); @@ -1251,7 +1182,7 @@ pass_5: string cleanupcmd = "rm -rf "; cleanupcmd += s.tmpdir; if (s.verbose>1) clog << "Running " << cleanupcmd << endl; - int status = system (cleanupcmd.c_str()); + int status = stap_system (cleanupcmd.c_str()); if (status != 0 && s.verbose>1) clog << "Cleanup command failed, status: " << status << endl; } diff --git a/util.cxx b/util.cxx index 68cc27f7..5fa7a5f2 100644 --- a/util.cxx +++ b/util.cxx @@ -20,13 +20,15 @@ #include extern "C" { -#include -#include +#include #include -#include +#include #include #include -#include +#include +#include +#include +#include } using namespace std; @@ -275,4 +277,35 @@ git_revision(const string& path) return revision; } + +static pid_t spawned_pid = 0; + +// Runs a command with a saved PID, so we can kill it from the signal handler +int +stap_system(const char *command) +{ + const char * argv[] = { "sh", "-c", command, NULL }; + int ret, status; + + spawned_pid = 0; + ret = posix_spawn(&spawned_pid, "/bin/sh", NULL, NULL, + const_cast(argv), environ); + if (ret == 0) + { + if (waitpid(spawned_pid, &status, 0) == spawned_pid) + ret = WIFEXITED(status) ? WEXITSTATUS(status) : 128 + WTERMSIG(status); + else + ret = errno; + } + spawned_pid = 0; + return ret; +} + +// Send a signal to our spawned command +int +kill_stap_spawn(int sig) +{ + return spawned_pid ? kill(spawned_pid, sig) : 0; +} + /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ diff --git a/util.h b/util.h index d385be02..7c557049 100644 --- a/util.h +++ b/util.h @@ -13,6 +13,8 @@ void tokenize(const std::string& str, std::vector& tokens, std::string find_executable(const std::string& name); const std::string cmdstr_quoted(const std::string& cmd); std::string git_revision(const std::string& path); +int stap_system(const char *command); +int kill_stap_spawn(int sig); // stringification generics -- cgit From 489afa702639fd10e9756795bd516d939766247d Mon Sep 17 00:00:00 2001 From: Maynard Johnson Date: Wed, 1 Apr 2009 09:51:57 -0500 Subject: Fix runtime/itrace.c to call arch_has_*_step() prior to calling utrace_control As Roland pointed out in his Mar 31 reply to a posting of mine (subject: Re: Testing insn.block probe point uncovers possible utrace bug), utrace_control() documents that the caller must ensure that arch_has_single_step and arch_has_block_step are defined before trying to use those step modes. The attached patch addresses that issue. I've tested this patch on x86_64 arch, and a block step test runs successfully, since block step is supported on that arch. Testing on ppc64 arch, the test fails as expected (since block step is not supported on ppc64 yet) with: "ERROR: callback for failed: 1" which is sent to stdderr and "usr_itrace_init: arch does not support block step mode" which is sent to the system log. This isn't the most user-friendly way of surfacing an error. Perhaps the stap runtime could have a set of defined return codes that would be mapped to strings so the user can get an idea of what the error is without looking in the system log. But that's a side issue, of course. Regards, -Maynard --- runtime/itrace.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/runtime/itrace.c b/runtime/itrace.c index 97ba427e..69f3bf74 100644 --- a/runtime/itrace.c +++ b/runtime/itrace.c @@ -318,6 +318,19 @@ static int usr_itrace_init(int single_step, pid_t tid, struct stap_itrace_probe struct task_struct *tsk; spin_lock_init(&itrace_lock); + + /* 'arch_has_single_step' needs to be defined for either single step mode + * or branch mode. + */ + if (!arch_has_single_step()) { + printk(KERN_ERR "usr_itrace_init: arch does not support step mode\n"); + return 1; + } + if (!single_step && !arch_has_block_step()) { + printk(KERN_ERR "usr_itrace_init: arch does not support block step mode\n"); + return 1; + } + rcu_read_lock(); #ifdef STAPCONF_FIND_TASK_PID tsk = find_task_by_pid(tid); -- cgit From f3921e808cc95592308727d011d7718f053008e2 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 1 Apr 2009 16:39:12 -0700 Subject: Revert "Fix runtime/itrace.c to call arch_has_*_step() prior to calling utrace_control" This reverts commit 489afa702639fd10e9756795bd516d939766247d. --- runtime/itrace.c | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/runtime/itrace.c b/runtime/itrace.c index 69f3bf74..97ba427e 100644 --- a/runtime/itrace.c +++ b/runtime/itrace.c @@ -318,19 +318,6 @@ static int usr_itrace_init(int single_step, pid_t tid, struct stap_itrace_probe struct task_struct *tsk; spin_lock_init(&itrace_lock); - - /* 'arch_has_single_step' needs to be defined for either single step mode - * or branch mode. - */ - if (!arch_has_single_step()) { - printk(KERN_ERR "usr_itrace_init: arch does not support step mode\n"); - return 1; - } - if (!single_step && !arch_has_block_step()) { - printk(KERN_ERR "usr_itrace_init: arch does not support block step mode\n"); - return 1; - } - rcu_read_lock(); #ifdef STAPCONF_FIND_TASK_PID tsk = find_task_by_pid(tid); -- cgit From 3598cf014bdeab592a365f570664ae970714985d Mon Sep 17 00:00:00 2001 From: Maynard Johnson Date: Wed, 1 Apr 2009 15:26:25 -0500 Subject: Fix for insn probe: Call arch_has_*_step() prior to calling utrace_control The attached patch is version 2 for the problem I reported earlier today. Frank, is this more what you had in mind? With this patch, there's no need for the user to look at the system log. Error messages are sent to stderr: ERROR: insn probe init: arch does not support block step mode ERROR: probe process("/test").function("doit1@/test.c:22").return registration error (rc -1) -Maynard --- tapsets.cxx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/tapsets.cxx b/tapsets.cxx index 352930ee..1b55684b 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6570,6 +6570,22 @@ itrace_derived_probe_group::emit_module_init (systemtap_session& s) s.op->newline() << "for (i=0; i<" << num_probes << "; i++) {"; s.op->indent(1); s.op->newline() << "struct stap_itrace_probe *p = &stap_itrace_probes[i];"; + + // 'arch_has_single_step' needs to be defined for either single step mode + // or branch mode. + s.op->newline() << "if (!arch_has_single_step()) {"; + s.op->indent(1); + s.op->newline() << "_stp_error (\"insn probe init: arch does not support step mode\");"; + s.op->newline() << "rc = -EPERM;"; + s.op->newline() << "break;"; + s.op->newline(-1) << "}"; + s.op->newline() << "if (!p->single_step && !arch_has_block_step()) {"; + s.op->indent(1); + s.op->newline() << "_stp_error (\"insn probe init: arch does not support block step mode\");"; + s.op->newline() << "rc = -EPERM;"; + s.op->newline() << "break;"; + s.op->newline(-1) << "}"; + s.op->newline() << "rc = stap_register_task_finder_target(&p->tgt);"; s.op->newline(-1) << "}"; } -- cgit From 055f682bed95348cabb20868d62c4e575b84d02a Mon Sep 17 00:00:00 2001 From: Maynard Johnson Date: Wed, 1 Apr 2009 11:22:53 -0500 Subject: Add insn.block testcase to itrace.exp in testsuite Earlier today, I posted a runtime patch for the insn.block probe point. Once that patch is committed, the insn.block probe can be safely tested on any architecture. The attached patch adds such a testcase to the testsuite. Regards, -Maynard --- testsuite/systemtap.base/itrace.exp | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/testsuite/systemtap.base/itrace.exp b/testsuite/systemtap.base/itrace.exp index e215bfe7..d330a337 100644 --- a/testsuite/systemtap.base/itrace.exp +++ b/testsuite/systemtap.base/itrace.exp @@ -48,6 +48,27 @@ set itrace2_script { } set itrace2_script_output "itraced = 5\r\n" +set itrace3_script { + global branches = 0 + probe begin + { + printf("systemtap starting probe\n") + printf("ATTENTION: if arch_has_block_step is not defined for this arch, this testcase will fail\n") + } + probe process("%s").insn.block + { + branches += 1 + if (branches == 5) + exit() + } + + + probe end { printf("systemtap ending probe\n") + printf("itraced block mode = %%d\n", branches) + } +} +set itrace3_script_output "itraced block mode = 5\r\n" + # Set up our own copy of /bin/ls, to make testing for a particular # executable easy. We can't use 'ln' here, since we might be creating @@ -99,5 +120,15 @@ if {$utrace_support_found == 0} { stap_run $TEST_NAME run_ls_5_sec $itrace2_script_output -e $script } +set TEST_NAME "itrace3" +if {$utrace_support_found == 0} { + untested "$TEST_NAME : no kernel utrace support found" +} elseif {![installtest_p]} { + untested $TEST_NAME +} else { + set script [format $itrace3_script $exepath] + stap_run $TEST_NAME run_ls_5_sec $itrace3_script_output -e $script +} + # Cleanup exec rm -f $exepath -- cgit From 1fd65aa57e608b544122b4aacdfae9cce6cb89dc Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 1 Apr 2009 17:01:53 -0700 Subject: Move testcase itrace3's warning into expect As it was, the ATTENTION was causing expect mismatches even when the test worked fine. The warning is served just as well from the expect script before starting the test. --- testsuite/systemtap.base/itrace.exp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/systemtap.base/itrace.exp b/testsuite/systemtap.base/itrace.exp index d330a337..504253fe 100644 --- a/testsuite/systemtap.base/itrace.exp +++ b/testsuite/systemtap.base/itrace.exp @@ -53,7 +53,6 @@ set itrace3_script { probe begin { printf("systemtap starting probe\n") - printf("ATTENTION: if arch_has_block_step is not defined for this arch, this testcase will fail\n") } probe process("%s").insn.block { @@ -126,6 +125,7 @@ if {$utrace_support_found == 0} { } elseif {![installtest_p]} { untested $TEST_NAME } else { + send_log "ATTENTION: if arch_has_block_step is not defined for this arch, this testcase will fail\n" set script [format $itrace3_script $exepath] stap_run $TEST_NAME run_ls_5_sec $itrace3_script_output -e $script } -- cgit From 83ff01c2f669c66100a5cf7531dda9410a8ff6ce Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Wed, 1 Apr 2009 20:33:51 -0400 Subject: introduce [utrace_p] as dejagnu check for utrace presence in kernel * testsuite/lib/systemtap.exp: Define here. * testsuite/systemtap.*/*.exp: Use it here. Eliminate duplicated utrace_support_present logic. --- testsuite/lib/systemtap.exp | 10 +++++++++ testsuite/systemtap.base/bz5274.exp | 9 +------- testsuite/systemtap.base/bz6850.exp | 9 +------- testsuite/systemtap.base/itrace.exp | 11 ++-------- testsuite/systemtap.base/labels.exp | 10 +-------- testsuite/systemtap.base/static_uprobes.exp | 10 +-------- testsuite/systemtap.base/uprobes.exp | 9 +------- testsuite/systemtap.base/uprobes_lib.exp | 15 ++++++++----- testsuite/systemtap.base/utrace_p4.exp | 34 +++++++++++------------------ testsuite/systemtap.base/utrace_p5.exp | 21 ++++++------------ testsuite/systemtap.pass1-4/buildok.exp | 1 + 11 files changed, 48 insertions(+), 91 deletions(-) diff --git a/testsuite/lib/systemtap.exp b/testsuite/lib/systemtap.exp index 554e88ed..5311be7b 100644 --- a/testsuite/lib/systemtap.exp +++ b/testsuite/lib/systemtap.exp @@ -16,6 +16,16 @@ proc use_server_p {} { } +proc utrace_p {} { + set path "/proc/kallsyms" + if {! [catch {exec grep -q utrace_attach $path} dummy]} { + return 1 + } else { + return 0 + } +} + + proc print_systemtap_version {} { set version [exec /bin/uname -r] set location "/boot/vmlinux-$version" diff --git a/testsuite/systemtap.base/bz5274.exp b/testsuite/systemtap.base/bz5274.exp index 92441e9e..2f76a43f 100755 --- a/testsuite/systemtap.base/bz5274.exp +++ b/testsuite/systemtap.base/bz5274.exp @@ -17,14 +17,7 @@ if {! [installtest_p]} { return } -# Try to find utrace_attach symbol in /proc/kallsyms -# copy from utrace_p5.exp -set utrace_support_found 0 -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} -if {$utrace_support_found == 0} { +if {![utrace_p]} { catch {exec rm -f $test} untested "$test -p5" return diff --git a/testsuite/systemtap.base/bz6850.exp b/testsuite/systemtap.base/bz6850.exp index b96ed95c..32ecdaf5 100644 --- a/testsuite/systemtap.base/bz6850.exp +++ b/testsuite/systemtap.base/bz6850.exp @@ -3,14 +3,7 @@ set test bz6850 catch {exec gcc -g -o bz6850 $srcdir/$subdir/bz6850.c} err if {$err == "" && [file exists bz6850]} then { pass "$test compile" } else { fail "$test compile" } -# Try to find utrace_attach symbol in /proc/kallsyms -# copy from utrace_p5.exp -set utrace_support_found 0 -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} -if {$utrace_support_found == 0} { +if {![utrace_p]} { catch {exec rm -f $test} untested "$test -p4" untested "$test -p5" diff --git a/testsuite/systemtap.base/itrace.exp b/testsuite/systemtap.base/itrace.exp index 504253fe..c7da39c8 100644 --- a/testsuite/systemtap.base/itrace.exp +++ b/testsuite/systemtap.base/itrace.exp @@ -2,7 +2,6 @@ # Initialize variables -set utrace_support_found 0 set exepath "[pwd]/ls_[pid]" set itrace1_script { @@ -92,14 +91,8 @@ proc run_ls_5_sec {} { } -# Try to find utrace_attach symbol in /proc/kallsyms -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} - set TEST_NAME "itrace1" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested $TEST_NAME @@ -110,7 +103,7 @@ if {$utrace_support_found == 0} { set TEST_NAME "itrace2" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested $TEST_NAME diff --git a/testsuite/systemtap.base/labels.exp b/testsuite/systemtap.base/labels.exp index 6db81c54..2f79a502 100644 --- a/testsuite/systemtap.base/labels.exp +++ b/testsuite/systemtap.base/labels.exp @@ -1,14 +1,6 @@ set test "labels" if {![installtest_p]} {untested $test; return} - -# Try to find utrace_attach symbol in /proc/kallsyms -# copy from utrace_p5.exp -set utrace_support_found 0 -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} -if {$utrace_support_found == 0} { untested "$test"; return } +if {![utrace_p]} { untested $test; return } # Compile a C program to use as the user-space probing target set label_srcpath "[pwd]/labels.c" diff --git a/testsuite/systemtap.base/static_uprobes.exp b/testsuite/systemtap.base/static_uprobes.exp index d6b6e1e3..07ff83e9 100644 --- a/testsuite/systemtap.base/static_uprobes.exp +++ b/testsuite/systemtap.base/static_uprobes.exp @@ -124,15 +124,7 @@ if { $res != "" } { } if {![installtest_p]} {untested $test; return} - -# Try to find utrace_attach symbol in /proc/kallsyms -# copy from utrace_p5.exp -set utrace_support_found 0 -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$test" catch {exec rm -f $sup_srcpath} return diff --git a/testsuite/systemtap.base/uprobes.exp b/testsuite/systemtap.base/uprobes.exp index 89250e7b..6344cbf0 100644 --- a/testsuite/systemtap.base/uprobes.exp +++ b/testsuite/systemtap.base/uprobes.exp @@ -18,14 +18,7 @@ if [file exists $path] then { pass "$test prep" } else { fail "$test prep" } catch {exec gcc -g -o jennie jennie.c} err if {$err == "" && [file exists jennie]} then { pass "$test compile" } else { fail "$test compile" } -# Try to find utrace_attach symbol in /proc/kallsyms -# copy from utrace_p5.exp -set utrace_support_found 0 -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$test -p4"; untested "$test -p5" catch {exec rm -f jennie.c jennie} return diff --git a/testsuite/systemtap.base/uprobes_lib.exp b/testsuite/systemtap.base/uprobes_lib.exp index ae1b72e8..63ef957a 100644 --- a/testsuite/systemtap.base/uprobes_lib.exp +++ b/testsuite/systemtap.base/uprobes_lib.exp @@ -10,21 +10,23 @@ 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"; 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" + 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 "unable to compile $testsrc" + fail "$test compile $testsrc" return +} else { + pass "$test compile $testsrc" } # XXX main_func needs another/extra test. Disabled for now. @@ -33,6 +35,9 @@ if { $res != "" } { # lib_func} set ::result_string {lib_func} +# Only run on make installcheck +if {! [installtest_p]} { untested "$test"; return } +if {! [utrace_p]} { untested $test; return } stap_run2 $srcdir/$subdir/$test.stp -c $testexe #exec rm -f $testexe $testso diff --git a/testsuite/systemtap.base/utrace_p4.exp b/testsuite/systemtap.base/utrace_p4.exp index 1467d9c8..8d323a8a 100644 --- a/testsuite/systemtap.base/utrace_p4.exp +++ b/testsuite/systemtap.base/utrace_p4.exp @@ -7,8 +7,6 @@ # utrace doesn't exist in the kernel, marks the tests as 'untested'. # Initialize variables -set utrace_support_found 0 - set begin_script {"probe process(\"/bin/ls\").begin { print(\"ls begin\") }"} set end_script {"probe process(\"/bin/ls\").end { print(\"ls end\") }"} set syscall_script {"probe process(\"/bin/ls\").syscall { printf(\"|%d\", \$syscall) }"} @@ -24,18 +22,12 @@ set pid_syscall_return_script {"probe process(123).syscall.return { printf(\"|%d set pid_thread_begin_script {"probe process(123).thread.begin { print(\"123 thread.begin\") }"} set pid_thread_end_script {"probe process(123).thread.end { print(\"123 thread.end\") }"} -# Try to find utrace_attach symbol in /proc/kallsyms -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} - # # Do some utrace compile tests. # set TEST_NAME "UTRACE_P4_01" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a begin script using a path @@ -43,7 +35,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_01_pid" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a begin script using a pid @@ -51,7 +43,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_02" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a end script using a path @@ -59,7 +51,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_02_pid" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a end script using a pid @@ -67,7 +59,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_03" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a syscall script using a path @@ -75,7 +67,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_03_pid" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a syscall script using a pid @@ -83,7 +75,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_04" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a syscall return script using a path @@ -91,7 +83,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_04_pid" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a syscall return script using a pid @@ -99,7 +91,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_05" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an thread.begin script using a path @@ -107,7 +99,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_05_pid" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an thread.begin script using a pid @@ -115,7 +107,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_06" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an thread.end script using a path @@ -123,7 +115,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_06_pid" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an thread.end script using a pid @@ -131,7 +123,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_07" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an system-wide begin script diff --git a/testsuite/systemtap.base/utrace_p5.exp b/testsuite/systemtap.base/utrace_p5.exp index 33281350..3d432dc3 100644 --- a/testsuite/systemtap.base/utrace_p5.exp +++ b/testsuite/systemtap.base/utrace_p5.exp @@ -1,7 +1,6 @@ # Utrace run (pass 5) tests. # Initialize variables -set utrace_support_found 0 set exepath "[pwd]/cat_[pid]" set multi_srcpath "$srcdir/systemtap.base/utrace_p5_multi.c" set multi_exepath "[pwd]/utrace_p5_multi_[pid]" @@ -90,12 +89,6 @@ set bz6841_script { } set bz6841_script_output ".+ issues syscall \\d+ times\r\n" -# Try to find utrace_attach symbol in /proc/kallsyms -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} - # Set up our own copy of /bin/cat, to make testing for a particular # executable easy. We can't use 'ln' here, since we might be creating # a cross-device link. We can't use 'ln -s' here, since the kernel @@ -138,7 +131,7 @@ proc run_utrace_p5_multi {} { } set TEST_NAME "UTRACE_P5_01" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" @@ -148,7 +141,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P5_02" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" @@ -158,7 +151,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P5_03" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" @@ -168,7 +161,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P5_04" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" @@ -178,7 +171,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P5_05" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" @@ -189,7 +182,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P5_06" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" @@ -200,7 +193,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P5_07" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" diff --git a/testsuite/systemtap.pass1-4/buildok.exp b/testsuite/systemtap.pass1-4/buildok.exp index 08d50fb5..3731fc06 100644 --- a/testsuite/systemtap.pass1-4/buildok.exp +++ b/testsuite/systemtap.pass1-4/buildok.exp @@ -12,6 +12,7 @@ foreach file [lsort [glob -nocomplain $srcdir/$self/*.stp]] { buildok/process_test.stp {setup_kfail 1155 *-*-*} buildok/rpc-all-probes.stp {setup_kfail 4413 *-*-*} buildok/nfs-all-probes.stp {setup_kfail 4413 *-*-*} + buildok/per-process-syscall.stp {if {![utrace_p]} { setup_kfail 9999 *-*-*} } } if {$rc == 0} { pass $test } else { fail $test } } -- cgit From 3c960a7cfa61cbde19c0ad88045c8c1f6405ed87 Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Wed, 1 Apr 2009 18:11:48 -0700 Subject: Fix sudo magic wrappers for run-stap devel script. --- configure | 46 ++++++++++++++++++++++++++++++++++++++++++++++ configure.ac | 3 +++ run-stap.in | 6 ++---- run-stapio.in | 10 ++++++++++ run-staprun.sh | 6 ++++++ 5 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 run-stapio.in create mode 100755 run-staprun.sh diff --git a/configure b/configure index a63b6557..58406bee 100755 --- a/configure +++ b/configure @@ -667,6 +667,7 @@ sqlite3_LIBS PIECXXFLAGS PIECFLAGS PIELDFLAGS +PERL RANLIB ANSI2KNR U @@ -5971,6 +5972,47 @@ fi +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 +$as_echo_n "checking for $ac_word... " >&6; } +if test "${ac_cv_path_PERL+set}" = set; then + $as_echo_n "(cached) " >&6 +else + case $PERL in + [\\/]* | ?:[\\/]*) + ac_cv_path_PERL="$PERL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext" + $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +PERL=$ac_cv_path_PERL +if test -n "$PERL"; then + { $as_echo "$as_me:$LINENO: result: $PERL" >&5 +$as_echo "$PERL" >&6; } +else + { $as_echo "$as_me:$LINENO: result: no" >&5 +$as_echo "no" >&6; } +fi + + + # Check whether --enable-perfmon was given. if test "${enable_perfmon+set}" = set; then enableval=$enable_perfmon; @@ -8082,6 +8124,8 @@ subdirs="$subdirs testsuite" ac_config_files="$ac_config_files run-stap" +ac_config_files="$ac_config_files run-stapio" + cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -8783,6 +8827,7 @@ do "man/stapprobes.udp.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.udp.3stap" ;; "initscript/systemtap") CONFIG_FILES="$CONFIG_FILES initscript/systemtap" ;; "run-stap") CONFIG_FILES="$CONFIG_FILES run-stap" ;; + "run-stapio") CONFIG_FILES="$CONFIG_FILES run-stapio" ;; *) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 $as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;} @@ -9562,6 +9607,7 @@ $as_echo "$as_me: error: cannot create directory $as_dir" >&2;} done ;; "run-stap":F) chmod +x run-stap ;; + "run-stapio":F) chmod +x run-stapio ;; esac done # for ac_tag diff --git a/configure.ac b/configure.ac index eab206a2..5e15539e 100644 --- a/configure.ac +++ b/configure.ac @@ -25,6 +25,8 @@ AC_PROG_MAKE_SET AC_SUBST(CFLAGS) AC_SUBST(CXXFLAGS) +AC_PATH_PROG(PERL, perl) + dnl Handle the perfmon option. AC_ARG_ENABLE([perfmon], AS_HELP_STRING([--enable-perfmon@<:@=DIRECTORY@:>@], @@ -359,6 +361,7 @@ AC_CONFIG_HEADERS([config.h:config.in]) AC_CONFIG_FILES(Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.process.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap initscript/systemtap) AC_CONFIG_SUBDIRS(testsuite) AC_CONFIG_FILES([run-stap], [chmod +x run-stap]) +AC_CONFIG_FILES([run-stapio], [chmod +x run-stapio]) AC_OUTPUT if test "${prefix}" = "/usr/local"; then diff --git a/run-stap.in b/run-stap.in index dfb53ab2..f8ee9287 100644 --- a/run-stap.in +++ b/run-stap.in @@ -19,10 +19,8 @@ esac # Set all the variables to find the source and build trees. SYSTEMTAP_TAPSET="${srcdir}/tapset" SYSTEMTAP_RUNTIME="${srcdir}/runtime" -SYSTEMTAP_STAPIO="${builddir}/stapio" -SYSTEMTAP_STAPRUN="sudo 'SYSTEMTAP_STAPIO=$SYSTEMTAP_STAPIO' \ - 'SYSTEMTAP_STAPRUN=${builddir}/staprun' \ - ${builddir}/staprun" +SYSTEMTAP_STAPRUN="builddir='$builddir' ${srcdir}/run-staprun.sh" +SYSTEMTAP_STAPIO="${srcdir}/run-stapio" export SYSTEMTAP_TAPSET SYSTEMTAP_RUNTIME SYSTEMTAP_STAPRUN SYSTEMTAP_STAPIO # If there were private elfutils libs built, use them. diff --git a/run-stapio.in b/run-stapio.in new file mode 100644 index 00000000..554c2d33 --- /dev/null +++ b/run-stapio.in @@ -0,0 +1,10 @@ +#!@PERL@ -w + +# Reset real IDs to those we had before running sudo in run-staprun.sh. +# This gives stapio the IDs it expects from a setuid exec. +$< = $ENV{'SUDO_UID'}; +$( = $ENV{'SUDO_GID'}; + +exec { "$ENV{'builddir'}/stapio" } ('stapio', @ARGV); + +exit; diff --git a/run-staprun.sh b/run-staprun.sh new file mode 100755 index 00000000..688dfa78 --- /dev/null +++ b/run-staprun.sh @@ -0,0 +1,6 @@ +#!/bin/sh + +exec sudo env builddir="${builddir}" \ + SYSTEMTAP_STAPIO="${builddir}/run-stapio" \ + SYSTEMTAP_STAPRUN="$0" \ + "${builddir}/staprun" ${1+"$@"} -- cgit From 5717eaeb49421506ed323f8473790aaf74389237 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Wed, 1 Apr 2009 22:16:28 -0400 Subject: PR4105: removing redundant buildok/twentysix.stp test --- testsuite/buildok/twentysix.stp | 7 ------- testsuite/systemtap.pass1-4/buildok.exp | 1 - testsuite/systemtap.server/server.exp | 1 - 3 files changed, 9 deletions(-) delete mode 100755 testsuite/buildok/twentysix.stp diff --git a/testsuite/buildok/twentysix.stp b/testsuite/buildok/twentysix.stp deleted file mode 100755 index 3fb7526f..00000000 --- a/testsuite/buildok/twentysix.stp +++ /dev/null @@ -1,7 +0,0 @@ -#! stap -up4 - -global a -probe begin -{ - a [1,2,3,4,5,6] = 0 -} diff --git a/testsuite/systemtap.pass1-4/buildok.exp b/testsuite/systemtap.pass1-4/buildok.exp index 3731fc06..12275c1d 100644 --- a/testsuite/systemtap.pass1-4/buildok.exp +++ b/testsuite/systemtap.pass1-4/buildok.exp @@ -6,7 +6,6 @@ foreach file [lsort [glob -nocomplain $srcdir/$self/*.stp]] { # some tests are known to fail. switch $test { buildok/perfmon01.stp {setup_kfail 909 *-*-*} - buildok/twentysix.stp {setup_kfail 4105 *-*-*} buildok/twentyseven.stp {setup_kfail 4166 *-*-*} buildok/sched_test.stp {setup_kfail 1155 *-*-*} buildok/process_test.stp {setup_kfail 1155 *-*-*} diff --git a/testsuite/systemtap.server/server.exp b/testsuite/systemtap.server/server.exp index c2c60b97..d2dd0f16 100644 --- a/testsuite/systemtap.server/server.exp +++ b/testsuite/systemtap.server/server.exp @@ -16,7 +16,6 @@ foreach file [lsort [glob -nocomplain $srcdir/$self/*.stp]] { # some tests are known to fail. switch $test { "buildok/perfmon01.stp with server" {setup_kfail 909 *-*-*} - "buildok/twentysix.stp with server" {setup_kfail 4105 *-*-*} "buildok/twentyseven.stp with server" {setup_kfail 4166 *-*-*} "buildok/sched_test.stp with server" {setup_kfail 1155 *-*-*} "buildok/process_test.stp with server" {setup_kfail 1155 *-*-*} -- cgit From 65ffc3f32328473cb74aa5c7eca7e46bb82bd7fb Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 1 Apr 2009 19:41:55 -0700 Subject: Fix the magic run-stap wrappers even more --- configure | 6 +++--- configure.ac | 2 +- run-stap.in | 5 ++--- run-stapio.in | 10 ---------- run-staprun.in | 13 +++++++++++++ run-staprun.sh | 6 ------ 6 files changed, 19 insertions(+), 23 deletions(-) delete mode 100644 run-stapio.in create mode 100644 run-staprun.in delete mode 100755 run-staprun.sh diff --git a/configure b/configure index 58406bee..33655cc2 100755 --- a/configure +++ b/configure @@ -8124,7 +8124,7 @@ subdirs="$subdirs testsuite" ac_config_files="$ac_config_files run-stap" -ac_config_files="$ac_config_files run-stapio" +ac_config_files="$ac_config_files run-staprun" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure @@ -8827,7 +8827,7 @@ do "man/stapprobes.udp.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.udp.3stap" ;; "initscript/systemtap") CONFIG_FILES="$CONFIG_FILES initscript/systemtap" ;; "run-stap") CONFIG_FILES="$CONFIG_FILES run-stap" ;; - "run-stapio") CONFIG_FILES="$CONFIG_FILES run-stapio" ;; + "run-staprun") CONFIG_FILES="$CONFIG_FILES run-staprun" ;; *) { { $as_echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 $as_echo "$as_me: error: invalid argument: $ac_config_target" >&2;} @@ -9607,7 +9607,7 @@ $as_echo "$as_me: error: cannot create directory $as_dir" >&2;} done ;; "run-stap":F) chmod +x run-stap ;; - "run-stapio":F) chmod +x run-stapio ;; + "run-staprun":F) chmod +x run-staprun ;; esac done # for ac_tag diff --git a/configure.ac b/configure.ac index 5e15539e..9b66a724 100644 --- a/configure.ac +++ b/configure.ac @@ -361,7 +361,7 @@ AC_CONFIG_HEADERS([config.h:config.in]) AC_CONFIG_FILES(Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.process.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap initscript/systemtap) AC_CONFIG_SUBDIRS(testsuite) AC_CONFIG_FILES([run-stap], [chmod +x run-stap]) -AC_CONFIG_FILES([run-stapio], [chmod +x run-stapio]) +AC_CONFIG_FILES([run-staprun], [chmod +x run-staprun]) AC_OUTPUT if test "${prefix}" = "/usr/local"; then diff --git a/run-stap.in b/run-stap.in index f8ee9287..1bfb6a77 100644 --- a/run-stap.in +++ b/run-stap.in @@ -19,9 +19,8 @@ esac # Set all the variables to find the source and build trees. SYSTEMTAP_TAPSET="${srcdir}/tapset" SYSTEMTAP_RUNTIME="${srcdir}/runtime" -SYSTEMTAP_STAPRUN="builddir='$builddir' ${srcdir}/run-staprun.sh" -SYSTEMTAP_STAPIO="${srcdir}/run-stapio" -export SYSTEMTAP_TAPSET SYSTEMTAP_RUNTIME SYSTEMTAP_STAPRUN SYSTEMTAP_STAPIO +SYSTEMTAP_STAPRUN="sudo -P builddir='${builddir}' ${builddir}/run-staprun" +export SYSTEMTAP_TAPSET SYSTEMTAP_RUNTIME SYSTEMTAP_STAPRUN # If there were private elfutils libs built, use them. if [ -d "$rundir/lib-elfutils" ]; then diff --git a/run-stapio.in b/run-stapio.in deleted file mode 100644 index 554c2d33..00000000 --- a/run-stapio.in +++ /dev/null @@ -1,10 +0,0 @@ -#!@PERL@ -w - -# Reset real IDs to those we had before running sudo in run-staprun.sh. -# This gives stapio the IDs it expects from a setuid exec. -$< = $ENV{'SUDO_UID'}; -$( = $ENV{'SUDO_GID'}; - -exec { "$ENV{'builddir'}/stapio" } ('stapio', @ARGV); - -exit; diff --git a/run-staprun.in b/run-staprun.in new file mode 100644 index 00000000..0b5f795b --- /dev/null +++ b/run-staprun.in @@ -0,0 +1,13 @@ +#!@PERL@ -w + +# Reset real IDs to those we had before we were sudo-invoked. +# This gives staprun the IDs it expects from a setuid exec. +$< = $ENV{'SUDO_UID'}; +$( = $ENV{'SUDO_GID'}; + +$ENV{'SYSTEMTAP_STAPRUN'} = "sudo '$ENV{'builddir'}/staprun'"; +$ENV{'SYSTEMTAP_STAPIO'} = "$ENV{'builddir'}/stapio"; + +exec { "$ENV{'builddir'}/staprun" } ('staprun', @ARGV); + +exit; diff --git a/run-staprun.sh b/run-staprun.sh deleted file mode 100755 index 688dfa78..00000000 --- a/run-staprun.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/bin/sh - -exec sudo env builddir="${builddir}" \ - SYSTEMTAP_STAPIO="${builddir}/run-stapio" \ - SYSTEMTAP_STAPRUN="$0" \ - "${builddir}/staprun" ${1+"$@"} -- cgit From dcfd7fed7088871f46d9da7183e485877fb2d81f Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Wed, 1 Apr 2009 22:50:47 -0400 Subject: PR10019: --skip-badvars to suppress run-time memory errors too * NEWS: Note this change. * hash.cxx (find_script_hash): Add s.skip_badvars into hash. * translate.cxx (translate_pass): Emit STP_SKIP_BADVARS. * runtime/loc2c-runtime.h (DEREF_FAULT, STORE_DEREF_FAULT): Provide dummy implementation if STP_SKIP_BADVARS. --- NEWS | 7 +++++++ hash.cxx | 1 + runtime/loc2c-runtime.h | 6 +++++- translate.cxx | 2 ++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index ec204442..96e14b70 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,10 @@ +* What's new + +- The --skip-badvars option now also suppresses run-time error + messages that would otherwise result from erroneous memory accesses. + Such accesses can originate from $context expressions fueled by + erroneous debug data, or by kernel_{long,string,...}() tapset calls. + * What's new in version 0.9.5 - New probes process().insn and process().insn.block that allows diff --git a/hash.cxx b/hash.cxx index 3ff6848d..01013c43 100644 --- a/hash.cxx +++ b/hash.cxx @@ -174,6 +174,7 @@ find_script_hash (systemtap_session& s, const string& script, const hash &base) h.add(s.ignore_vmlinux); // --ignore-vmlinux h.add(s.ignore_dwarf); // --ignore-dwarf h.add(s.consult_symtab); // --kelf, --kmap + h.add(s.skip_badvars); // --skip-badvars if (!s.kernel_symtab_path.empty()) // --kmap { h.add(s.kernel_symtab_path); diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h index 16ddb950..eaf47cad 100644 --- a/runtime/loc2c-runtime.h +++ b/runtime/loc2c-runtime.h @@ -62,6 +62,10 @@ must work right for kernel addresses, and can use whatever existing machine-specific kernel macros are convenient. */ +#if STP_SKIP_BADVARS +#define DEREF_FAULT(addr) ({0; }) +#define STORE_DEREF_FAULT(addr) ({0; }) +#else #define DEREF_FAULT(addr) ({ \ snprintf(c->error_buffer, sizeof(c->error_buffer), \ "kernel read fault at 0x%p (%s)", (void *)(intptr_t)(addr), #addr); \ @@ -75,7 +79,7 @@ c->last_error = c->error_buffer; \ goto deref_fault; \ }) - +#endif #if defined (STAPCONF_X86_UNIREGS) && defined (__i386__) diff --git a/translate.cxx b/translate.cxx index 47fffd1e..9085349e 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4955,6 +4955,8 @@ translate_pass (systemtap_session& s) s.op->newline() << "#define STP_OVERLOAD"; s.op->newline() << "#endif"; + s.op->newline() << "#define STP_SKIP_BADVARS " << (s.skip_badvars ? 1 : 0); + if (s.bulk_mode) s.op->newline() << "#define STP_BULKMODE"; -- cgit From 5ff8be611e2460ad5e0a15e1cd0936c38e518c7f Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 2 Apr 2009 13:49:12 +0200 Subject: Make task_finder.c compiler if ! defined (CONFIG_UTRACE). * runtime/task-finder.c: If ! defined (CONFIG_UTRACE) define dummy noop API for sym.c consisting of struct stap_task_finder_target, stap_add_vma_map_info, stap_remove_vma_map_info and stap_find_vma_map_info. --- runtime/task_finder.c | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/runtime/task_finder.c b/runtime/task_finder.c index 44dca296..3507c669 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -2,8 +2,32 @@ #define TASK_FINDER_C #if ! defined(CONFIG_UTRACE) -#error "Need CONFIG_UTRACE!" -#endif +/* Dummy definitions for use in sym.c */ +struct stap_task_finder_target { }; + +static int +stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, + unsigned long vm_end, unsigned long vm_pgoff, + void *user) +{ + return 0; +} + +static int +stap_remove_vma_map_info(struct task_struct *tsk, unsigned long vm_start, + unsigned long vm_end, unsigned long vm_pgoff) +{ + return 0; +} + +static int +stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, + unsigned long *vm_start, unsigned long *vm_end, + unsigned long *vm_pgoff, void **user) +{ + return ESRCH; +} +#else #include @@ -1358,4 +1382,6 @@ stap_stop_task_finder(void) } +#endif /* defined(CONFIG_UTRACE) */ + #endif /* TASK_FINDER_C */ -- cgit From 253b87b64211fe41e06b162ea11948ccad101ba7 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 2 Apr 2009 14:42:02 +0200 Subject: Check for utrace in usymbols.exp. --- testsuite/systemtap.context/usymbols.exp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/testsuite/systemtap.context/usymbols.exp b/testsuite/systemtap.context/usymbols.exp index f95fd896..82f68b67 100644 --- a/testsuite/systemtap.context/usymbols.exp +++ b/testsuite/systemtap.context/usymbols.exp @@ -10,8 +10,9 @@ 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 } +# Only run on make installcheck and utrace present. +if {! [installtest_p]} { untested "$test"; return } +if {! [utrace_p]} { untested "$test"; return } # Compile our test program and library. set res [target_compile $testsrclib $testso executable $testlibflags] -- cgit From ab16aae80b49823e96b31e7ab47fcdb3a199412f Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 2 Apr 2009 14:48:37 +0200 Subject: PR9995: Test for [installtest_p] && [utrace_p]. --- testsuite/systemtap.base/sdt.exp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/systemtap.base/sdt.exp b/testsuite/systemtap.base/sdt.exp index 46fa5a28..c3aed91e 100644 --- a/testsuite/systemtap.base/sdt.exp +++ b/testsuite/systemtap.base/sdt.exp @@ -36,7 +36,7 @@ if { $res != "" } { pass "compiling $test.c $extra_flag" } -if {[installtest_p]} { +if {[installtest_p] && [utrace_p]} { stap_run3 "$test $extra_flag" $srcdir/$subdir/$test.stp $testprog -c ./$testprog } else { untested "$test $extra_flag" @@ -61,7 +61,7 @@ if { $res != "" } { pass "compiling $test.c c++ $extra_flag" } -if {[installtest_p]} { +if {[installtest_p] && [utrace_p]} { stap_run3 "$test c++ $extra_flag" $srcdir/$subdir/$test.stp $testprog -c ./$testprog } else { untested "$test c++ $extra_flag" -- cgit From 15a78144473940a4e7c685cc57ba09a92f2293c6 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 2 Apr 2009 16:26:50 +0200 Subject: itrace.exp: s/utrace_support_found/utrace_p/ --- testsuite/systemtap.base/itrace.exp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/systemtap.base/itrace.exp b/testsuite/systemtap.base/itrace.exp index c7da39c8..5da0dfaf 100644 --- a/testsuite/systemtap.base/itrace.exp +++ b/testsuite/systemtap.base/itrace.exp @@ -113,7 +113,7 @@ if {![utrace_p]} { } set TEST_NAME "itrace3" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested $TEST_NAME -- cgit From b2b336288ce9e92a21efe7dcd314f604bc97be29 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 2 Apr 2009 18:42:38 +0200 Subject: PR6580: Implement symname, symdata and modname context functions. This adds a couple of the suggested context/stack revamp functions from PR6580. In particular it replaces the symbolname() function that sneaked in with the pr6866 branch merge with the suggested symname(). * runtime/sym.c (_stp_mod_sec_lookup): Make section optional. (_stp_symbol_snprint): Provide a way to get optional module info. * tapset/context-symbols.stp: Replace symbolname() with symname(), add modname() and symdata(). (probemod): Implement pc based fallback. * tapset/context-unwind.stp (caller): Adjust for _stp_symbol_snprint change. * testsuite/systemtap.context/usymbols.exp: Use new symname. * testsuite/buildok/modname.stp: New test. * testsuite/buildok/symdata.stp: Likewise. * testsuite/buildok/symname.stp: Likewise. --- runtime/sym.c | 26 ++++++++++---- tapset/context-symbols.stp | 60 ++++++++++++++++++++++++++++---- tapset/context-unwind.stp | 2 +- testsuite/buildok/modname.stp | 8 +++++ testsuite/buildok/symdata.stp | 8 +++++ testsuite/buildok/symname.stp | 8 +++++ testsuite/systemtap.context/usymbols.exp | 2 +- 7 files changed, 98 insertions(+), 16 deletions(-) create mode 100755 testsuite/buildok/modname.stp create mode 100755 testsuite/buildok/symdata.stp create mode 100755 testsuite/buildok/symname.stp diff --git a/runtime/sym.c b/runtime/sym.c index d0c5d9fd..ecd64fee 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -106,8 +106,8 @@ static unsigned long _stp_module_relocate(const char *module, const char *sectio } -/* Return module owner and fills in closest section of the address - if found, return NULL otherwise. +/* Return module owner and, if sec != NULL, fills in closest section + of the address 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, @@ -151,7 +151,8 @@ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr, { closest_section_offset = this_section_offset; m = _stp_modules[midx]; - *sec = & m->sections[secidx]; + if (sec) + *sec = & m->sections[secidx]; } } } @@ -338,8 +339,15 @@ static int _stp_func_print(unsigned long address, int verbose, int exact) return 0; } +/** Puts symbolic information of an address in a string. + * @param src The string to fill in. + * @param len The length of the given src string. + * @param address The address to lookup. + * @param add_mod Whether to include module name information if found. + */ + static void _stp_symbol_snprint(char *str, size_t len, unsigned long address, - struct task_struct *task) + struct task_struct *task, int add_mod) { const char *modname; const char *name; @@ -347,9 +355,13 @@ static void _stp_symbol_snprint(char *str, size_t len, unsigned long address, name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, task); - if (name) - strlcpy(str, name, len); - else + if (name) { + if (add_mod && modname && *modname) + _stp_printf("%s %s+%#lx/%#lx\n", + name, modname, offset, size); + else + strlcpy(str, name, len); + } else _stp_snprintf(str, len, "%p", (int64_t) address); } diff --git a/tapset/context-symbols.stp b/tapset/context-symbols.stp index 4c200aa8..66d9fea2 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), current); + _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, REG_IP(CONTEXT->regs), current, 0); if (THIS->__retvalue[0] == '.') /* powerpc symbol has a dot*/ strlcpy(THIS->__retvalue,THIS->__retvalue + 1,MAXSTRINGLEN); } else { @@ -89,13 +89,59 @@ function probemod:string () %{ /* pure */ while (*ptr != '"' && --len && *ptr) *dst++ = *ptr++; *dst = 0; - } else { - /* XXX: need a PC- and symbol-table-based fallback. */ - THIS->__retvalue[0] = '\0'; - } + } else if (CONTEXT->regs) { + struct _stp_module *m; + m = _stp_mod_sec_lookup (REG_IP(CONTEXT->regs), current, NULL); + if (m && m->name) + strlcpy (THIS->__retvalue, m->name, MAXSTRINGLEN); + else + strlcpy (THIS->__retvalue, "", MAXSTRINGLEN); + } else + strlcpy (THIS->__retvalue, "", MAXSTRINGLEN); %} -function symbolname:string (addr:long) %{ /* pure */ +/** + * sfunction modname - Return the kernel module name loaded at the address. + * @addr: The address. + * + * Description: Returns the module name associated with the given + * address if known. If not known it will return the string "". + * If the address was not in a kernel module, but in the kernel itself, + * then the string "kernel" will be returned. + */ +function modname:string (addr: long) %{ /* pure */ + struct _stp_module *m; + m = _stp_mod_sec_lookup (THIS->addr, current, NULL); + if (m && m->name) + strlcpy (THIS->__retvalue, m->name, MAXSTRINGLEN); + else + strlcpy (THIS->__retvalue, "", MAXSTRINGLEN); +%} + +/** + * sfunction symname - Return the symbol associated with the given address. + * @addr: The address to translate. + * + * Description: Returns the (function) symbol name associated with the + * given address if known. If not known it will return the hex string + * representation of addr. + */ +function symname:string (addr: long) %{ /* pure */ + _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr, + current, 0); +%} + +/** + * sfunction symdata - Return the symbol and module offset for the address. + * @addr: The address to translate. + * + * Description: Returns the (function) symbol name associated with the + * given address if known, plus the module name (between brackets) and + * the offset inside the module, plus the size of the symbol function. + * If any element is not known it will be ommitted and if the symbol name + * is unknown it will return the hex string for the given address. + */ +function symdata:string (addr: long) %{ /* pure */ _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr, - current); + current, 1); %} diff --git a/tapset/context-unwind.stp b/tapset/context-unwind.stp index a976f8b6..b3d19e29 100644 --- a/tapset/context-unwind.stp +++ b/tapset/context-unwind.stp @@ -57,7 +57,7 @@ function caller:string() %{ /* pure */ if (CONTEXT->pi) _stp_symbol_snprint( THIS->__retvalue, MAXSTRINGLEN, (unsigned long)_stp_ret_addr_r(CONTEXT->pi), - current); + current, 0); else strlcpy(THIS->__retvalue,"unknown",MAXSTRINGLEN); %} diff --git a/testsuite/buildok/modname.stp b/testsuite/buildok/modname.stp new file mode 100755 index 00000000..02229301 --- /dev/null +++ b/testsuite/buildok/modname.stp @@ -0,0 +1,8 @@ +#! stap -p4 +# +# Test the translatability for modname() +# +probe begin +{ + log(modname(0)) +} diff --git a/testsuite/buildok/symdata.stp b/testsuite/buildok/symdata.stp new file mode 100755 index 00000000..d7e803a9 --- /dev/null +++ b/testsuite/buildok/symdata.stp @@ -0,0 +1,8 @@ +#! stap -p4 +# +# Test the translatability for symdata() +# +probe begin +{ + log(symdata(0)) +} diff --git a/testsuite/buildok/symname.stp b/testsuite/buildok/symname.stp new file mode 100755 index 00000000..e082d1a5 --- /dev/null +++ b/testsuite/buildok/symname.stp @@ -0,0 +1,8 @@ +#! stap -p4 +# +# Test the translatability for symname() +# +probe begin +{ + log(symname(0)) +} diff --git a/testsuite/systemtap.context/usymbols.exp b/testsuite/systemtap.context/usymbols.exp index 82f68b67..8af20126 100644 --- a/testsuite/systemtap.context/usymbols.exp +++ b/testsuite/systemtap.context/usymbols.exp @@ -35,7 +35,7 @@ set testscript { probe syscall.rt_sigaction { if (pid() == target() && execname() == "%s") { handler = $act->sa_handler; - printf("handler: %%s\n", symbolname(handler)); + printf("handler: %%s\n", symname(handler)); } } /* track through uprobes, so as to make sure we have the symbols */ -- cgit From a7d25c487ad74dc60bbbd93a2f689e0f0a047273 Mon Sep 17 00:00:00 2001 From: Stan Cox Date: Thu, 2 Apr 2009 15:15:22 -0400 Subject: Rewrite stmt_rel.exp to only rely on -l output. * testsuite/systemtap.base/stmt_rel.exp: Rewrite. --- testsuite/systemtap.base/stmt_rel.exp | 44 +++++++++++++++++++--- testsuite/systemtap.base/stmt_rel.stp | 71 ----------------------------------- 2 files changed, 38 insertions(+), 77 deletions(-) delete mode 100644 testsuite/systemtap.base/stmt_rel.stp diff --git a/testsuite/systemtap.base/stmt_rel.exp b/testsuite/systemtap.base/stmt_rel.exp index be51fef9..ec12e484 100644 --- a/testsuite/systemtap.base/stmt_rel.exp +++ b/testsuite/systemtap.base/stmt_rel.exp @@ -1,8 +1,40 @@ -# test integer limits. Set and print variables and print constants. - set test "stmt_rel" -set ::result_string {PASS bio_init -PASS line number -PASS wildcard} -stap_run2 $srcdir/$subdir/$test.stp +set line1 "" +spawn stap -l "kernel.statement(\"bio_init@fs/bio.c+2\")" +expect { + -timeout 180 + -re {[0-9][0-9][0-9]} { regexp "\[0-9\]\[0-9\]\[0-9\]" $expect_out(0,string) line1; } + timeout { fail "$test C (timeout)" } + eof { } +} + +set line2 "" +spawn stap -l "kernel.statement(\"bio_init@fs/bio.c+3\")" +expect { + -timeout 180 + -re {[0-9][0-9][0-9]} { regexp "\[0-9\]\[0-9\]\[0-9\]" $expect_out(0,string) line2; } + timeout { fail "$test C (timeout)" } + eof { } +} + +if { $line1 < $line2 } { + pass "$test line numbers" +} else { + fail "$test line numbers" +} + +set ok 0 +spawn stap -l "kernel.statement(\"bio_init@fs/bio.c:*\")" +expect { + -timeout 180 + -re {[0-9][0-9][0-9]} { incr ok; exp_continue } + timeout { fail "$test C (timeout)" } + eof { } +} + +if { $ok == 3 } { + pass "$test wildcard" +} else { + fail "$test wildcard ($ok)" +} diff --git a/testsuite/systemtap.base/stmt_rel.stp b/testsuite/systemtap.base/stmt_rel.stp deleted file mode 100644 index cfe77317..00000000 --- a/testsuite/systemtap.base/stmt_rel.stp +++ /dev/null @@ -1,71 +0,0 @@ -global stack2pp, stack2func, stack3pp, stack3func -global wildcardpp, wild_count - -probe kernel.statement("bio_init@fs/bio.c+2") { - # stack2 = tokenize(backtrace(), " ") - stack2func = probefunc() - stack2pp = pp() -} -probe kernel.statement("bio_init@fs/bio.c+3") { - # stack3 = tokenize(backtrace(), " " ) - stack3func = probefunc() - stack3pp = pp() -} - -probe kernel.statement("bio_put@fs/bio.c:*") { - line = tokenize(pp(),":") - line = tokenize("",":") - line = substr(line,0,strlen(line)-2) - wildcardpp[strtol(line,10)]++ - - if (wild_count++ <= 10) { - next - } - - stack2pp = tokenize(stack2pp,":") - stack2pp = tokenize("",":") - stack3pp = tokenize(stack3pp,":") - stack3pp = tokenize("",":") - - stack2line = strtol (substr(stack2pp,0,strlen(stack2pp)-2), 10) - stack3line = strtol (substr(stack3pp,0,strlen(stack3pp)-2), 10) - - # Did functions for both bio_init probes match? - if (stack2func == stack3func) { - printf ("PASS %s\n", stack2func) - } - else { - printf ("FAIL %s %s\n", stack2func, stack3func) - } - - # Was line # for bio_init probe +2 < line # for bio_init probe +3? - if ((stack2line + 1) == stack3line) { - printf ("PASS line number\n") - } - else { - printf ("FAIL line number %d %d\n", stack2line, stack3line) - } - - # This test does not take optimized code into account - # Was address for bio_init probe +2 < address for bio_init probe +3? - # if (stack2 < stack3) { - # printf ("PASS address\n") - # } - # else { - # printf ("FAIL address %s %s\n", stack2, stack3) - # } - - # Did wildcard probe hit at least 4 different statements? - foreach ([i] in wildcardpp) { - statement_count += 1 - } - if (statement_count >= 4) { - printf ("PASS wildcard\n") - } - else - { - printf ("FAIL wildcard %d\n", statement_count) - } - - exit() -} -- cgit From b51455af34a99768cc3a6ce50b251132f5fe752e Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 2 Apr 2009 12:16:12 -0700 Subject: Disable ccache during kernel module builds Our module builds always have a 0% ccache hit rate, because the compiler commands always include the randomized tmpdir. Thus, I'm setting CCACHE_DISABLE=1 so ccache never saves these one-use objects. (Besides, we already have our own caching in place for this stuff...) --- buildrun.cxx | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/buildrun.cxx b/buildrun.cxx index 71a34c96..bcd4c1fe 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -48,6 +48,12 @@ run_make_cmd(systemtap_session& s, string& make_cmd) cerr << "unsetenv failed: " << e << endl; } + // Disable ccache to avoid saving files that will never be reused. + // (ccache is useless to us, because our compiler commands always + // include the randomized tmpdir path.) + // It's not critical if this fails, so the return is ignored. + (void) setenv("CCACHE_DISABLE", "1", 0); + if (s.verbose > 2) make_cmd += " V=1"; else if (s.verbose > 1) -- cgit From 49be62cc7130e60947bbae90b6bf177e173c8b29 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 2 Apr 2009 23:19:27 +0200 Subject: runtime/syscall.h: Forward declare __ia64_fetch_register. --- runtime/syscall.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/runtime/syscall.h b/runtime/syscall.h index ae451070..bd480a0c 100644 --- a/runtime/syscall.h +++ b/runtime/syscall.h @@ -261,6 +261,9 @@ __stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs, #endif #if defined(__ia64__) +/* Defined in regs-ia64.c. Forward declaration for ____stp_user_syscall_arg. */ +static long * __ia64_fetch_register(int, struct pt_regs *, unsigned long **); + #define __stp_user_syscall_arg(task, regs, n) \ ____stp_user_syscall_arg(task, regs, n, &c->unwaddr) -- cgit From 35ca8082a77e00173c94fe5fdcbd013b111033f2 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Thu, 2 Apr 2009 17:40:58 -0400 Subject: Revert "runtime/syscall.h: Forward declare __ia64_fetch_register." This reverts commit 49be62cc7130e60947bbae90b6bf177e173c8b29. --- runtime/syscall.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/runtime/syscall.h b/runtime/syscall.h index bd480a0c..ae451070 100644 --- a/runtime/syscall.h +++ b/runtime/syscall.h @@ -261,9 +261,6 @@ __stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs, #endif #if defined(__ia64__) -/* Defined in regs-ia64.c. Forward declaration for ____stp_user_syscall_arg. */ -static long * __ia64_fetch_register(int, struct pt_regs *, unsigned long **); - #define __stp_user_syscall_arg(task, regs, n) \ ____stp_user_syscall_arg(task, regs, n, &c->unwaddr) -- cgit From 093421c6ba933754aa52cf6399aae5b8f86d86d9 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Thu, 2 Apr 2009 17:41:20 -0400 Subject: Reorder includes so regs.c and regs-ia64.c included before task_finder.c. --- runtime/runtime.h | 2 ++ translate.cxx | 2 -- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/runtime.h b/runtime/runtime.h index 822562a2..0a656b78 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -86,6 +86,8 @@ static struct #include "io.c" #include "arith.c" #include "copy.c" +#include "regs.c" +#include "regs-ia64.c" #include "task_finder.c" diff --git a/translate.cxx b/translate.cxx index 9085349e..cab37487 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4967,9 +4967,7 @@ translate_pass (systemtap_session& s) s.op->newline() << "#define STP_PERFMON"; s.op->newline() << "#include \"runtime.h\""; - s.op->newline() << "#include \"regs.c\""; s.op->newline() << "#include \"stack.c\""; - s.op->newline() << "#include \"regs-ia64.c\""; s.op->newline() << "#include \"stat.c\""; s.op->newline() << "#include "; s.op->newline() << "#include "; -- cgit From 5aa1f218c5ff8a459c324ac64ee7a9b8046e683d Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 2 Apr 2009 18:44:34 -0400 Subject: Fix a bug in file size limitation code. This fixes a bug in stapio, which checks written data size and switches new file when it exceeds a limit. The problem is that written-data-size counter ignores the first written-data size when switching files. So, actual file size always exceeds the limit. This changes stapio to initialize written-data-size counter with the size of the data which will be written in new file. --- runtime/staprun/relay.c | 2 +- runtime/staprun/relay_old.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/staprun/relay.c b/runtime/staprun/relay.c index 50f295b5..694cb27e 100644 --- a/runtime/staprun/relay.c +++ b/runtime/staprun/relay.c @@ -200,7 +200,7 @@ static void *reader_thread(void *data) perr("Couldn't open file for cpu %d, exiting.", cpu); return(NULL); } - wsize = 0; + wsize = rc; } if (write(out_fd[cpu], buf, rc) != rc) { perr("Couldn't write to output %d for cpu %d, exiting.", out_fd[cpu], cpu); diff --git a/runtime/staprun/relay_old.c b/runtime/staprun/relay_old.c index ef8fd0da..469a5831 100644 --- a/runtime/staprun/relay_old.c +++ b/runtime/staprun/relay_old.c @@ -241,7 +241,7 @@ static int process_subbufs(struct _stp_buf_info *info, perr("Couldn't open file for cpu %d, exiting.", cpu); exit(1); } - scb->wsize = 0; + scb->wsize = len; } if (len) { if (fwrite_unlocked (subbuf_ptr, len, 1, percpu_tmpfile[cpu]) != 1) { @@ -320,7 +320,7 @@ int write_realtime_data(void *data, ssize_t nb) perr("Couldn't open file, exiting."); return -1; } - global_scb.wsize = 0; + global_scb.wsize = nb; } bw = write(out_fd[0], data, nb); if (bw >= 0 && bw != nb) { -- cgit From b9e80fe13706ae1c820e565e9b26f00b5f5a8dca Mon Sep 17 00:00:00 2001 From: Masami Hiramatsu Date: Thu, 2 Apr 2009 18:44:34 -0400 Subject: Fix strftime format bug This fixes bugs in strftime-subset function. This modifies %C, %l and %j to fit the output of date command. --- runtime/staprun/common.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/runtime/staprun/common.c b/runtime/staprun/common.c index 8200ec9d..26b166c2 100644 --- a/runtime/staprun/common.c +++ b/runtime/staprun/common.c @@ -82,7 +82,7 @@ int stap_strfloctime(char *buf, size_t max, const char *fmt, time_t t) num = tm.tm_year % 100; goto numbering02; case 'C': - num = ((tm.tm_year + 1900 - 1) / 100) + 1; + num = ((tm.tm_year + 1900) / 100); goto numbering; case 'm': num = tm.tm_mon + 1; @@ -107,7 +107,7 @@ int stap_strfloctime(char *buf, size_t max, const char *fmt, time_t t) if (num == 0) num = 12; goto numbering02; case 'j': - ret = snprintf(c, end - c, "%03d", tm.tm_yday); + ret = snprintf(c, end - c, "%03d", tm.tm_yday + 1); if (ret < 0) return ret; c += ret; break; @@ -117,7 +117,10 @@ int stap_strfloctime(char *buf, size_t max, const char *fmt, time_t t) case 'l': num = tm.tm_hour % 12; if (num == 0) num = 12; - goto numbering; + ret = snprintf(c, end - c, "%2d", num); + if (ret < 0) return ret; + c += ret; + break; case 'M': num = tm.tm_min; goto numbering02; -- cgit From b516e13ac098181536ae7281a8263e8f5b3553eb Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 2 Apr 2009 18:59:03 -0700 Subject: Really fix run-stap this time, I promise! --- configure | 42 ----------------------------------------- configure.ac | 2 -- run-stap.in | 2 +- run-staprun.in | 29 +++++++++++++++++++--------- runtime/staprun/staprun_funcs.c | 15 ++++++++++++++- 5 files changed, 35 insertions(+), 55 deletions(-) diff --git a/configure b/configure index 33655cc2..03763d5a 100755 --- a/configure +++ b/configure @@ -667,7 +667,6 @@ sqlite3_LIBS PIECXXFLAGS PIECFLAGS PIELDFLAGS -PERL RANLIB ANSI2KNR U @@ -5972,47 +5971,6 @@ fi -# Extract the first word of "perl", so it can be a program name with args. -set dummy perl; ac_word=$2 -{ $as_echo "$as_me:$LINENO: checking for $ac_word" >&5 -$as_echo_n "checking for $ac_word... " >&6; } -if test "${ac_cv_path_PERL+set}" = set; then - $as_echo_n "(cached) " >&6 -else - case $PERL in - [\\/]* | ?:[\\/]*) - ac_cv_path_PERL="$PERL" # Let the user override the test with a path. - ;; - *) - as_save_IFS=$IFS; IFS=$PATH_SEPARATOR -for as_dir in $PATH -do - IFS=$as_save_IFS - test -z "$as_dir" && as_dir=. - for ac_exec_ext in '' $ac_executable_extensions; do - if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then - ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext" - $as_echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 - break 2 - fi -done -done -IFS=$as_save_IFS - - ;; -esac -fi -PERL=$ac_cv_path_PERL -if test -n "$PERL"; then - { $as_echo "$as_me:$LINENO: result: $PERL" >&5 -$as_echo "$PERL" >&6; } -else - { $as_echo "$as_me:$LINENO: result: no" >&5 -$as_echo "no" >&6; } -fi - - - # Check whether --enable-perfmon was given. if test "${enable_perfmon+set}" = set; then enableval=$enable_perfmon; diff --git a/configure.ac b/configure.ac index 9b66a724..ee8ae61f 100644 --- a/configure.ac +++ b/configure.ac @@ -25,8 +25,6 @@ AC_PROG_MAKE_SET AC_SUBST(CFLAGS) AC_SUBST(CXXFLAGS) -AC_PATH_PROG(PERL, perl) - dnl Handle the perfmon option. AC_ARG_ENABLE([perfmon], AS_HELP_STRING([--enable-perfmon@<:@=DIRECTORY@:>@], diff --git a/run-stap.in b/run-stap.in index 1bfb6a77..8b150ece 100644 --- a/run-stap.in +++ b/run-stap.in @@ -19,7 +19,7 @@ esac # Set all the variables to find the source and build trees. SYSTEMTAP_TAPSET="${srcdir}/tapset" SYSTEMTAP_RUNTIME="${srcdir}/runtime" -SYSTEMTAP_STAPRUN="sudo -P builddir='${builddir}' ${builddir}/run-staprun" +SYSTEMTAP_STAPRUN="${builddir}/run-staprun" export SYSTEMTAP_TAPSET SYSTEMTAP_RUNTIME SYSTEMTAP_STAPRUN # If there were private elfutils libs built, use them. diff --git a/run-staprun.in b/run-staprun.in index 0b5f795b..e0615556 100644 --- a/run-staprun.in +++ b/run-staprun.in @@ -1,13 +1,24 @@ -#!@PERL@ -w +#!/bin/sh -# Reset real IDs to those we had before we were sudo-invoked. -# This gives staprun the IDs it expects from a setuid exec. -$< = $ENV{'SUDO_UID'}; -$( = $ENV{'SUDO_GID'}; +srcdir='@abs_top_srcdir@' +builddir='@abs_top_builddir@' -$ENV{'SYSTEMTAP_STAPRUN'} = "sudo '$ENV{'builddir'}/staprun'"; -$ENV{'SYSTEMTAP_STAPIO'} = "$ENV{'builddir'}/stapio"; +rundir="${0%/*}" +[ "$rundir" == "$0" ] || builddir="$rundir" -exec { "$ENV{'builddir'}/staprun" } ('staprun', @ARGV); +# Absolutify the paths. +case "$srcdir" in +/*) ;; +*) srcdir=`cd "$srcdir" && pwd` || exit ;; +esac +case "$builddir" in +/*) ;; +*) builddir=`cd "$builddir" && pwd` || exit ;; +esac -exit; +exec sudo -P "SYSTEMTAP_STAPIO=${builddir}/stapio" \ + "SYSTEMTAP_STAPRUN=${builddir}/run-staprun" \ + "SYSTEMTAP_RUNTIME=${srcdir}/runtime" \ + "SYSTEMTAP_REAL_UID=`id -ru`" \ + "SYSTEMTAP_REAL_GID=`id -rg`" \ + ${builddir}/staprun ${1+"$@"} diff --git a/runtime/staprun/staprun_funcs.c b/runtime/staprun/staprun_funcs.c index e94e5d13..49b37988 100644 --- a/runtime/staprun/staprun_funcs.c +++ b/runtime/staprun/staprun_funcs.c @@ -316,8 +316,21 @@ int check_permissions(void) int path_check = 0; /* If we're root, we can do anything. */ - if (getuid() == 0) + if (getuid() == 0) { + /* ... like overriding the real UID */ + const char *env_id = getenv("SYSTEMTAP_REAL_UID"); + if (env_id && setreuid(atoi(env_id), -1)) + err("WARNING: couldn't set staprun UID to '%s': %s", + env_id, strerror(errno)); + + /* ... or overriding the real GID */ + env_id = getenv("SYSTEMTAP_REAL_GID"); + if (env_id && setregid(atoi(env_id), -1)) + err("WARNING: couldn't set staprun GID to '%s': %s", + env_id, strerror(errno)); + return 1; + } /* Lookup the gid for group "stapdev" */ errno = 0; -- cgit From 85cd50d2a532d78ae1b0281c4baea3c4af396e2b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Thu, 2 Apr 2009 22:41:18 -0700 Subject: Add a .gitignore for uprobes --- runtime/uprobes/.gitignore | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 runtime/uprobes/.gitignore diff --git a/runtime/uprobes/.gitignore b/runtime/uprobes/.gitignore new file mode 100644 index 00000000..c8172c41 --- /dev/null +++ b/runtime/uprobes/.gitignore @@ -0,0 +1,7 @@ +/*.o +/*.cmd +/.tmp_versions +/Module.* +/modules.order +/uprobes.ko +/uprobes.mod.c -- cgit From 08dc41a50c508544bc18d384a65a137056a98195 Mon Sep 17 00:00:00 2001 From: Eugene Teo Date: Fri, 3 Apr 2009 23:18:14 +0800 Subject: Improvements to errno tapset This adds an errno_p() function that will return an absolute errno if it is valid, or zero if it is not. It also simplifies the if statement in the errno_str() function. --- tapset/errno.stp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/tapset/errno.stp b/tapset/errno.stp index eda9bff1..011ff7e2 100644 --- a/tapset/errno.stp +++ b/tapset/errno.stp @@ -345,12 +345,20 @@ static const int Maxerrno = sizeof(errlist)/sizeof(char *); function errno_str:string (err:long) %{ /* pure */ long e = THIS->err; - if (e < 0 && e > -Maxerrno && errlist[-e]) - strlcpy (THIS->__retvalue, errlist[-e], MAXSTRINGLEN); - else if (e > 0 && e < Maxerrno && errlist[e]) + e = (e > 0 ? e : -e); + if (e > 0 && e < Maxerrno && errlist[e]) strlcpy (THIS->__retvalue, errlist[e], MAXSTRINGLEN); %} +function errno_p:long (err:long) %{ /* pure */ + long e = THIS->err; + e = (e > 0 ? e : -e); + if (e > 0 && e < Maxerrno && errlist[e]) + THIS->__retvalue = e; + else + THIS->__retvalue = 0; +%} + %{ static long _stp_returnval(struct pt_regs *regs) { if (regs) { -- cgit From 8c1b9e271c944f64fc11fa9679c653b84ceaa77c Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Fri, 3 Apr 2009 11:35:35 -0400 Subject: make skip-badvars warning message sensitive to -w suppression --- tapsets.cxx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index 1b55684b..c81285e2 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -4906,8 +4906,9 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) literal_number* ln_zero = new literal_number (0); ln_zero->tok = e->tok; provide (ln_zero); - q.sess.print_warning ("Bad variable being substituted with literal 0", - e->tok); + if (!q.sess.suppress_warnings) + q.sess.print_warning ("Bad $context variable being substituted with literal 0", + e->tok); } delete fdecl; delete ec; -- cgit From 8e6c3aa3d61109b0276e96cdbc9ffdde60a5ac0a Mon Sep 17 00:00:00 2001 From: Eugene Teo Date: Fri, 3 Apr 2009 23:46:43 +0800 Subject: New ANSI escape sequences tapset This adds a new tapset for ANSI escape sequences. It is based on an existing tapset that was written by Masami Hiramatsu for the stapgames project. This also adds a version of ansi_color.stp script that displays other attributes other than the bold effect. --- tapset/ansi.stp | 70 ++++++++++++++++++++++ .../systemtap.examples/general/ansi_colors2.stp | 31 ++++++++++ 2 files changed, 101 insertions(+) create mode 100644 tapset/ansi.stp create mode 100644 testsuite/systemtap.examples/general/ansi_colors2.stp diff --git a/tapset/ansi.stp b/tapset/ansi.stp new file mode 100644 index 00000000..0152fb37 --- /dev/null +++ b/tapset/ansi.stp @@ -0,0 +1,70 @@ +# ANSI escape sequences tapset +# Copyright (C) 2009 Red Hat, Inc., Eugene Teo +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# Based on some previous work done by Masami Hiramatsu for stapgames. +# Reference: http://en.wikipedia.org/wiki/ANSI_escape_code +# + +function ansi_clear_screen() { + print("\033[1;1H\033[J") +} + +# Foreground colors | Background colors +# Black 30 | Black 40 +# Blue 34 | Red 41 +# Green 32 | Green 42 +# Cyan 36 | Yellow 43 +# Red 31 | Blue 44 +# Purple 35 | Magenta 45 +# Brown 33 | Cyan 46 +# Light Gray 37 | White 47 +function ansi_set_color(fg:long) { + printf("\033[%dm", fg) +} + +function ansi_set_color2(fg:long, bg:long) { + printf("\033[%d;%dm", bg, fg) +} + +# All attributes off 0 +# Intensity: Bold 1 +# Underline: Single 4 +# Blink: Slow 5 +# Blink: Rapid 6 +# Image: Negative 7 +function ansi_set_color3(fg:long, bg:long, attr:long) { + attr_str = attr ? sprintf(";%dm", attr) : "m" + printf("\033[%d;%d%s", bg, fg, attr_str) +} + +function ansi_reset_color() { + ansi_set_color3(0, 0, 0) +} + +function ansi_new_line() { + printf("\12") +} + +function ansi_cursor_move(x:long, y:long) { + printf("\033[%d;%dH", y, x) +} + +function ansi_cursor_hide() { + print("\033[>5I") +} + +function ansi_cursor_save() { + print("\033[s") +} + +function ansi_cursor_restore() { + print("\033[u") +} + +function ansi_cursor_show() { + print("\033[>5h") +} diff --git a/testsuite/systemtap.examples/general/ansi_colors2.stp b/testsuite/systemtap.examples/general/ansi_colors2.stp new file mode 100644 index 00000000..5f1b102e --- /dev/null +++ b/testsuite/systemtap.examples/general/ansi_colors2.stp @@ -0,0 +1,31 @@ +#!/usr/bin/env stap +# ansi_colors2.stp +# Copyright (C) 2009 Red Hat, Inc., Eugene Teo +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# + +probe begin { + printf("a \\ b |"); + for (c = 40; c < 48; c++) + printf(" %d ", c); + ansi_new_line() + for (l = 0; l < 71; l++) + printf("-"); + ansi_new_line() + + for (r = 30; r < 38; r++) + # this displays more attributes + for (t = 0; t < 8; !t ? ++t : t+=3) { + printf("%d |", r); + for (c = 40; c < 48; c++) { + ansi_set_color3(r, c, t) + printf(" Colors ") + ansi_reset_color() + } + ansi_new_line() + } + exit(); +} -- cgit From a8e88602f1c7cbe302542d5af427d354d7d457ba Mon Sep 17 00:00:00 2001 From: Eugene Teo Date: Fri, 3 Apr 2009 23:54:23 +0800 Subject: Update scripts to use the new ANSI tapset This updates the example scripts to use the new ANSI escape sequences tapset. It also adds the copyright header that was missing in ansi_colors.stp for a long time. --- .../systemtap.examples/general/ansi_colors.stp | 43 +++++++++++++--------- testsuite/systemtap.examples/io/ioblktime.stp | 2 +- testsuite/systemtap.examples/profiling/timeout.stp | 2 +- 3 files changed, 28 insertions(+), 19 deletions(-) diff --git a/testsuite/systemtap.examples/general/ansi_colors.stp b/testsuite/systemtap.examples/general/ansi_colors.stp index ae954e69..02c7c847 100755 --- a/testsuite/systemtap.examples/general/ansi_colors.stp +++ b/testsuite/systemtap.examples/general/ansi_colors.stp @@ -1,21 +1,30 @@ -#! /usr/bin/env stap +#!/usr/bin/env stap +# ansi_colors.stp +# Copyright (C) 2006-2009 Red Hat, Inc., Eugene Teo +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# probe begin { - printf("a \\ b |"); - for (c = 40; c < 48; c++) - printf(" %d ", c); - printf("\12"); - for (l = 0; l < 71; l++) - printf("-"); - printf("\12"); + printf("a \\ b |"); + for (c = 40; c < 48; c++) + printf(" %d ", c); + ansi_new_line() + for (l = 0; l < 71; l++) + printf("-"); + ansi_new_line() - for (r = 30; r < 38; r++) - for (t = 0; t < 2; t++) { - printf("%d |", r); - for (c = 40; c < 48; c++) - printf("\033[%d;%d%s %s \033[0;0m", - r, c, !t ? "m" : ";1m", !t ? "Normal" : "Bold "); - printf("\12"); - } - exit(); + for (r = 30; r < 38; r++) + for (t = 0; t < 2; t++) { + printf("%d |", r); + for (c = 40; c < 48; c++) { + ansi_set_color3(r, c, t) + printf(" %s ", !t ? "Normal" : "Bold ") + ansi_reset_color() + } + ansi_new_line() + } + exit(); } diff --git a/testsuite/systemtap.examples/io/ioblktime.stp b/testsuite/systemtap.examples/io/ioblktime.stp index 5ff59cf7..d6267b3e 100755 --- a/testsuite/systemtap.examples/io/ioblktime.stp +++ b/testsuite/systemtap.examples/io/ioblktime.stp @@ -18,7 +18,7 @@ probe ioblock.end } probe timer.s(10), end { - printf("\033[2J\033[1;1H") /* clear screen */ + ansi_clear_screen() printf("%10s %3s %10s %10s %10s\n", "device", "rw", "total (us)", "count", "avg (us)") foreach ([dev,rw] in etimes - limit 20) { diff --git a/testsuite/systemtap.examples/profiling/timeout.stp b/testsuite/systemtap.examples/profiling/timeout.stp index 48d6d21d..7af4a88f 100755 --- a/testsuite/systemtap.examples/profiling/timeout.stp +++ b/testsuite/systemtap.examples/profiling/timeout.stp @@ -90,7 +90,7 @@ probe syscall.exit { } probe timer.s(1) { - printf("\033[2J\033[1;1H") /* clear screen */ + ansi_clear_screen() printf (" uid | poll select epoll itimer futex nanosle signal| process\n") foreach (p in timeout_count- limit 20) { printf ("%5d |%7d %7d %7d %7d %7d %7d %7d| %-.38s\n", p, -- cgit From d1ec6e13b6f971ea23fb3203460384836c04b3c0 Mon Sep 17 00:00:00 2001 From: Eugene Teo Date: Fri, 3 Apr 2009 23:56:19 +0800 Subject: Make ansi_colors2.stp script executable --- testsuite/systemtap.examples/general/ansi_colors2.stp | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 testsuite/systemtap.examples/general/ansi_colors2.stp diff --git a/testsuite/systemtap.examples/general/ansi_colors2.stp b/testsuite/systemtap.examples/general/ansi_colors2.stp old mode 100644 new mode 100755 -- cgit From cc20d8532b08f7755642ecb30f22126f7ac332c2 Mon Sep 17 00:00:00 2001 From: Eugene Teo Date: Fri, 3 Apr 2009 13:47:57 -0400 Subject: new process/errsnoop.stp sample script --- testsuite/systemtap.examples/index.html | 5 ++- testsuite/systemtap.examples/index.txt | 18 +++++++-- testsuite/systemtap.examples/keyword-index.html | 13 ++++++- testsuite/systemtap.examples/keyword-index.txt | 30 +++++++++++++-- testsuite/systemtap.examples/process/errsnoop.meta | 7 ++++ testsuite/systemtap.examples/process/errsnoop.stp | 43 ++++++++++++++++++++++ 6 files changed, 105 insertions(+), 11 deletions(-) create mode 100644 testsuite/systemtap.examples/process/errsnoop.meta create mode 100644 testsuite/systemtap.examples/process/errsnoop.stp diff --git a/testsuite/systemtap.examples/index.html b/testsuite/systemtap.examples/index.html index 0f4b2572..9880c5b6 100644 --- a/testsuite/systemtap.examples/index.html +++ b/testsuite/systemtap.examples/index.html @@ -60,7 +60,7 @@ keywords: IO io/ioblktime.stp - Average Time Block IO Requests Spend in Queue
keywords: IO
-

The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script compute the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many oustanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line.

+

The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script computes the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many oustanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line.

  • io/iostats.stp - List Executables Reading and Writing the Most Data
    keywords: IO PROFILING

    The iostat.stp script measures the amount of data successfully read and written by all the executables on the system. The output is sorted from most greatest sum of bytes read and written by an executable to the least. The output contains the count of operations (opens, reads, and writes), the totals and averages for the number of bytes read and written.

  • @@ -91,6 +91,9 @@ keywords: NETWORK network/tcp_connections.stp - Track Creation of Incoming TCP Connections
    keywords: NETWORK TCP SOCKET

    The tcp_connections.stp script prints information for each new incoming TCP connection accepted by the computer. The information includes the UID, the command accepting the connection, the PID of the command, the port the connection is on, and the IP address of the originator of the request.

    +
  • process/errsnoop.stp - tabulate system call errors
    +keywords: PROCESS SYSCALL
    +

    The script prints a periodic tabular report about failing system calls, by process and by syscall failure. The first optional argument specifies the reporting interval (in seconds, default 5); the second optional argument gives a screen height (number of lines in the report, default 20).

  • process/futexes.stp - System-Wide Futex Contention
    keywords: SYSCALL LOCKING FUTEX

    The script watches the futex syscall on the system. On exit the futexes address, the number of contentions, and the average time for each contention on the futex are printed from lowest pid number to highest.

  • diff --git a/testsuite/systemtap.examples/index.txt b/testsuite/systemtap.examples/index.txt index e31baf4f..96ac5ab0 100644 --- a/testsuite/systemtap.examples/index.txt +++ b/testsuite/systemtap.examples/index.txt @@ -56,10 +56,10 @@ io/ioblktime.stp - Average Time Block IO Requests Spend in Queue keywords: io The ioblktime.stp script tracks the amount of time that each block IO - requests spend waiting for completion. The script compute the average - time waiting time for block IO per device and prints list every 10 - seconds. In some cases there can be too many oustanding block IO - operations and the script may exceed the default number of + requests spend waiting for completion. The script computes the + average time waiting time for block IO per device and prints list + every 10 seconds. In some cases there can be too many oustanding + block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line. @@ -166,6 +166,16 @@ keywords: network tcp socket originator of the request. +process/errsnoop.stp - tabulate system call errors +keywords: process syscall + + The script prints a periodic tabular report about failing system + calls, by process and by syscall failure. The first optional + argument specifies the reporting interval (in seconds, default 5); + the second optional argument gives a screen height (number of lines + in the report, default 20). + + process/futexes.stp - System-Wide Futex Contention keywords: syscall locking futex diff --git a/testsuite/systemtap.examples/keyword-index.html b/testsuite/systemtap.examples/keyword-index.html index 75768709..78d467cd 100644 --- a/testsuite/systemtap.examples/keyword-index.html +++ b/testsuite/systemtap.examples/keyword-index.html @@ -39,7 +39,7 @@

    Examples by Keyword

    -

    BACKTRACE CALLGRAPH CPU DISK FUNCTIONS FUTEX GRAPH INTERRUPT IO LOCKING MEMORY NETWORK PER-PROCESS PROFILING READ SCHEDULER SIGNALS SIMPLE SLEEP SOCKET SYSCALL TCP TIME TRACE TRAFFIC USE WAIT4 WRITE

    +

    BACKTRACE CALLGRAPH CPU DISK FUNCTIONS FUTEX GRAPH INTERRUPT IO LOCKING MEMORY NETWORK PER-PROCESS PROCESS PROFILING READ SCHEDULER SIGNALS SIMPLE SLEEP SOCKET SYSCALL TCP TIME TRACE TRAFFIC USE WAIT4 WRITE

    BACKTRACE

    • interrupt/scf.stp - Tally Backtraces for Inter-Processor Interrupt (IPI)
      @@ -104,7 +104,7 @@ keywords: IO io/ioblktime.stp - Average Time Block IO Requests Spend in Queue
      keywords: IO
      -

      The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script compute the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many oustanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line.

    • +

      The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script computes the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many oustanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line.

    • io/iostats.stp - List Executables Reading and Writing the Most Data
      keywords: IO PROFILING

      The iostat.stp script measures the amount of data successfully read and written by all the executables on the system. The output is sorted from most greatest sum of bytes read and written by an executable to the least. The output contains the count of operations (opens, reads, and writes), the totals and averages for the number of bytes read and written.

    • @@ -157,6 +157,12 @@ keywords: NETWORK NETWORK TRAFFIC PER-PROCESS

      Every five seconds the nettop.stp script prints out a list of processed (PID and command) with the number of packets sent/received and the amount of data sent/received by the process during that interval.

    +

    PROCESS

    +
      +
    • process/errsnoop.stp - tabulate system call errors
      +keywords: PROCESS SYSCALL
      +

      The script prints a periodic tabular report about failing system calls, by process and by syscall failure. The first optional argument specifies the reporting interval (in seconds, default 5); the second optional argument gives a screen height (number of lines in the report, default 20).

    • +

    PROFILING

    • io/iostats.stp - List Executables Reading and Writing the Most Data
      @@ -231,6 +237,9 @@ keywords: NETWORK io/iotime.stp - Trace Time Spent in Read and Write for Files
      keywords: SYSCALL READ WRITE TIME IO

      The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parenthesese. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls.

    • +
    • process/errsnoop.stp - tabulate system call errors
      +keywords: PROCESS SYSCALL
      +

      The script prints a periodic tabular report about failing system calls, by process and by syscall failure. The first optional argument specifies the reporting interval (in seconds, default 5); the second optional argument gives a screen height (number of lines in the report, default 20).

    • process/futexes.stp - System-Wide Futex Contention
      keywords: SYSCALL LOCKING FUTEX

      The script watches the futex syscall on the system. On exit the futexes address, the number of contentions, and the average time for each contention on the futex are printed from lowest pid number to highest.

    • diff --git a/testsuite/systemtap.examples/keyword-index.txt b/testsuite/systemtap.examples/keyword-index.txt index d3a9617f..17334252 100644 --- a/testsuite/systemtap.examples/keyword-index.txt +++ b/testsuite/systemtap.examples/keyword-index.txt @@ -129,10 +129,10 @@ io/ioblktime.stp - Average Time Block IO Requests Spend in Queue keywords: io The ioblktime.stp script tracks the amount of time that each block IO - requests spend waiting for completion. The script compute the average - time waiting time for block IO per device and prints list every 10 - seconds. In some cases there can be too many oustanding block IO - operations and the script may exceed the default number of + requests spend waiting for completion. The script computes the + average time waiting time for block IO per device and prints list + every 10 seconds. In some cases there can be too many oustanding + block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line. @@ -274,6 +274,18 @@ keywords: network traffic per-process interval. += PROCESS = + +process/errsnoop.stp - tabulate system call errors +keywords: process syscall + + The script prints a periodic tabular report about failing system + calls, by process and by syscall failure. The first optional + argument specifies the reporting interval (in seconds, default 5); + the second optional argument gives a screen height (number of lines + in the report, default 20). + + = PROFILING = io/iostats.stp - List Executables Reading and Writing the Most Data @@ -458,6 +470,16 @@ keywords: syscall read write time io syscalls. +process/errsnoop.stp - tabulate system call errors +keywords: process syscall + + The script prints a periodic tabular report about failing system + calls, by process and by syscall failure. The first optional + argument specifies the reporting interval (in seconds, default 5); + the second optional argument gives a screen height (number of lines + in the report, default 20). + + process/futexes.stp - System-Wide Futex Contention keywords: syscall locking futex diff --git a/testsuite/systemtap.examples/process/errsnoop.meta b/testsuite/systemtap.examples/process/errsnoop.meta new file mode 100644 index 00000000..34b8cb7c --- /dev/null +++ b/testsuite/systemtap.examples/process/errsnoop.meta @@ -0,0 +1,7 @@ +title: tabulate system call errors +name: errsnoop.stp +keywords: process syscall +subsystem: general +description: The script prints a periodic tabular report about failing system calls, by process and by syscall failure. The first optional argument specifies the reporting interval (in seconds, default 5); the second optional argument gives a screen height (number of lines in the report, default 20). +test_check: stap -p4 errsnoop.stp +test_installcheck: stap errsnoop.stp 1 10 -c "sleep 3" diff --git a/testsuite/systemtap.examples/process/errsnoop.stp b/testsuite/systemtap.examples/process/errsnoop.stp new file mode 100644 index 00000000..d9fba3b7 --- /dev/null +++ b/testsuite/systemtap.examples/process/errsnoop.stp @@ -0,0 +1,43 @@ +#!/usr/bin/env stap +# errsnoop.stp +# Copyright (C) 2009 Red Hat, Inc., Eugene Teo +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# attack "stupid userspace" apps +# + +global error, trace + +probe syscall.* { + # assume syscall don't nest + trace[tid()] = argstr +} + +probe syscall.*.return { + errno = errno_p(returnval()) + if (errno != 0) { + t = tid() + argstr = trace[t] + delete trace[t] + + error[name, execname(), pid(), errno, argstr] <<< 1 + } +} + +probe timer.s(%( $# > 0 %? $1 %: 5 %)) { + ansi_clear_screen() + printf("%17s %15s %5s %4s %-12s %s\n", + "SYSCALL", "PROCESS", "PID", "HITS", "ERRSTR", "ARGSTR") + foreach([fn, comm, pid, errno, argstr] in error- limit %( $# > 1 %? $2 %: 20 %)) { + errstr = sprintf("%3d (%s)", errno, errno_str(errno)) + printf("%17s %15s %5d %4d %-12s %s\n", fn, comm, pid, + @count(error[fn, comm, pid, errno, argstr]), +# errstr, substr(argstr,0,22)) # within cols#80 + errstr, argstr) + + } + delete error +} -- cgit From 0e0b566a5c6de7e824067963f3c516d09d9962d3 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Fri, 3 Apr 2009 14:38:19 -0400 Subject: Describe the ansi_colors.stp and ansi_colors2.stp. Label tables appropriately. --- testsuite/systemtap.examples/general/ansi_colors.meta | 13 +++++++++++++ testsuite/systemtap.examples/general/ansi_colors.stp | 6 +++--- testsuite/systemtap.examples/general/ansi_colors2.meta | 13 +++++++++++++ testsuite/systemtap.examples/general/ansi_colors2.stp | 6 +++--- testsuite/systemtap.examples/index.html | 6 ++++++ testsuite/systemtap.examples/index.txt | 16 ++++++++++++++++ testsuite/systemtap.examples/keyword-index.html | 11 ++++++++++- testsuite/systemtap.examples/keyword-index.txt | 18 ++++++++++++++++++ 8 files changed, 82 insertions(+), 7 deletions(-) create mode 100644 testsuite/systemtap.examples/general/ansi_colors.meta create mode 100644 testsuite/systemtap.examples/general/ansi_colors2.meta diff --git a/testsuite/systemtap.examples/general/ansi_colors.meta b/testsuite/systemtap.examples/general/ansi_colors.meta new file mode 100644 index 00000000..2818c235 --- /dev/null +++ b/testsuite/systemtap.examples/general/ansi_colors.meta @@ -0,0 +1,13 @@ +title: Color Table for ansi_set_color2() and ansi_set_color3() +name: ansi_colors.stp +version: 1.0 +author: Eugene Teo +keywords: format +subsystem: none +status: production +exit: fixed +output: text +scope: system-wide +description: The script prints a table showing the available color combinations for the ansi_set_color2() and ans_set_color3() functions in the ansi.stp tapset. +test_check: stap -p4 ansi_colors.stp +test_installcheck: stap ansi_colors.stp diff --git a/testsuite/systemtap.examples/general/ansi_colors.stp b/testsuite/systemtap.examples/general/ansi_colors.stp index 02c7c847..01e58b9c 100755 --- a/testsuite/systemtap.examples/general/ansi_colors.stp +++ b/testsuite/systemtap.examples/general/ansi_colors.stp @@ -8,17 +8,17 @@ # probe begin { - printf("a \\ b |"); + printf("fg,t \\ bg |"); for (c = 40; c < 48; c++) printf(" %d ", c); ansi_new_line() - for (l = 0; l < 71; l++) + for (l = 0; l < 75; l++) printf("-"); ansi_new_line() for (r = 30; r < 38; r++) for (t = 0; t < 2; t++) { - printf("%d |", r); + printf(" %2d,%1d |", r, t); for (c = 40; c < 48; c++) { ansi_set_color3(r, c, t) printf(" %s ", !t ? "Normal" : "Bold ") diff --git a/testsuite/systemtap.examples/general/ansi_colors2.meta b/testsuite/systemtap.examples/general/ansi_colors2.meta new file mode 100644 index 00000000..4ccaf4e3 --- /dev/null +++ b/testsuite/systemtap.examples/general/ansi_colors2.meta @@ -0,0 +1,13 @@ +title: Show Attribues in Table for ansi_set_color3() +name: ansi_colors2.stp +version: 1.0 +author: Eugene Teo +keywords: format +subsystem: none +status: production +exit: fixed +output: text +scope: system-wide +description: The script prints a table showing the available attributes (bold, underline, and inverse) with color combinations for the ans_set_color3() function in the ansi.stp tapset. +test_check: stap -p4 ansi_colors2.stp +test_installcheck: stap ansi_colors2.stp diff --git a/testsuite/systemtap.examples/general/ansi_colors2.stp b/testsuite/systemtap.examples/general/ansi_colors2.stp index 5f1b102e..fadcf011 100755 --- a/testsuite/systemtap.examples/general/ansi_colors2.stp +++ b/testsuite/systemtap.examples/general/ansi_colors2.stp @@ -8,18 +8,18 @@ # probe begin { - printf("a \\ b |"); + printf("fg,t \\ bg |"); for (c = 40; c < 48; c++) printf(" %d ", c); ansi_new_line() - for (l = 0; l < 71; l++) + for (l = 0; l < 75; l++) printf("-"); ansi_new_line() for (r = 30; r < 38; r++) # this displays more attributes for (t = 0; t < 8; !t ? ++t : t+=3) { - printf("%d |", r); + printf(" %2d,%1d |", r, t); for (c = 40; c < 48; c++) { ansi_set_color3(r, c, t) printf(" Colors ") diff --git a/testsuite/systemtap.examples/index.html b/testsuite/systemtap.examples/index.html index 9880c5b6..3287458a 100644 --- a/testsuite/systemtap.examples/index.html +++ b/testsuite/systemtap.examples/index.html @@ -40,6 +40,12 @@

      All Examples

        +
      • general/ansi_colors.stp - Color Table for ansi_set_color2() and ansi_set_color3()
        +keywords: FORMAT
        +

        The script prints a table showing the available color combinations for the ansi_set_color2() and ans_set_color3() functions in the ansi.stp tapset.

      • +
      • general/ansi_colors2.stp - Show Attribues in Table for ansi_set_color3()
        +keywords: FORMAT
        +

        The script prints a table showing the available attributes (bold, underline, and inverse) with color combinations for the ans_set_color3() function in the ansi.stp tapset.

      • general/graphs.stp - Graphing Disk and CPU Utilization
        keywords: DISK CPU USE GRAPH

        The script tracks the disk and CPU utilization. The resulting output of the script can be piped into gnuplot to generate a graph of disk and CPU USE.

      • diff --git a/testsuite/systemtap.examples/index.txt b/testsuite/systemtap.examples/index.txt index 96ac5ab0..d538d760 100644 --- a/testsuite/systemtap.examples/index.txt +++ b/testsuite/systemtap.examples/index.txt @@ -1,6 +1,22 @@ SYSTEMTAP EXAMPLES INDEX (see also keyword-index.txt) +general/ansi_colors.stp - Color Table for ansi_set_color2() and ansi_set_color3() +keywords: format + + The script prints a table showing the available color combinations + for the ansi_set_color2() and ans_set_color3() functions in the + ansi.stp tapset. + + +general/ansi_colors2.stp - Show Attribues in Table for ansi_set_color3() +keywords: format + + The script prints a table showing the available attributes (bold, + underline, and inverse) with color combinations for the + ans_set_color3() function in the ansi.stp tapset. + + general/graphs.stp - Graphing Disk and CPU Utilization keywords: disk cpu use graph diff --git a/testsuite/systemtap.examples/keyword-index.html b/testsuite/systemtap.examples/keyword-index.html index 78d467cd..2254fd25 100644 --- a/testsuite/systemtap.examples/keyword-index.html +++ b/testsuite/systemtap.examples/keyword-index.html @@ -39,7 +39,7 @@

      Examples by Keyword

      -

      BACKTRACE CALLGRAPH CPU DISK FUNCTIONS FUTEX GRAPH INTERRUPT IO LOCKING MEMORY NETWORK PER-PROCESS PROCESS PROFILING READ SCHEDULER SIGNALS SIMPLE SLEEP SOCKET SYSCALL TCP TIME TRACE TRAFFIC USE WAIT4 WRITE

      +

      BACKTRACE CALLGRAPH CPU DISK FORMAT FUNCTIONS FUTEX GRAPH INTERRUPT IO LOCKING MEMORY NETWORK PER-PROCESS PROCESS PROFILING READ SCHEDULER SIGNALS SIMPLE SLEEP SOCKET SYSCALL TCP TIME TRACE TRAFFIC USE WAIT4 WRITE

      BACKTRACE

      • interrupt/scf.stp - Tally Backtraces for Inter-Processor Interrupt (IPI)
        @@ -73,6 +73,15 @@ keywords: DISK DISK

        Get the status of reading/writing disk every 5 seconds, output top ten entries during that period.

      +

      FORMAT

      +
        +
      • general/ansi_colors.stp - Color Table for ansi_set_color2() and ansi_set_color3()
        +keywords: FORMAT
        +

        The script prints a table showing the available color combinations for the ansi_set_color2() and ans_set_color3() functions in the ansi.stp tapset.

      • +
      • general/ansi_colors2.stp - Show Attribues in Table for ansi_set_color3()
        +keywords: FORMAT
        +

        The script prints a table showing the available attributes (bold, underline, and inverse) with color combinations for the ans_set_color3() function in the ansi.stp tapset.

      • +

      FUNCTIONS

      • profiling/functioncallcount.stp - Count Times Functions Called
        diff --git a/testsuite/systemtap.examples/keyword-index.txt b/testsuite/systemtap.examples/keyword-index.txt index 17334252..8fd8e0d8 100644 --- a/testsuite/systemtap.examples/keyword-index.txt +++ b/testsuite/systemtap.examples/keyword-index.txt @@ -70,6 +70,24 @@ keywords: disk ten entries during that period. += FORMAT = + +general/ansi_colors.stp - Color Table for ansi_set_color2() and ansi_set_color3() +keywords: format + + The script prints a table showing the available color combinations + for the ansi_set_color2() and ans_set_color3() functions in the + ansi.stp tapset. + + +general/ansi_colors2.stp - Show Attribues in Table for ansi_set_color3() +keywords: format + + The script prints a table showing the available attributes (bold, + underline, and inverse) with color combinations for the + ans_set_color3() function in the ansi.stp tapset. + + = FUNCTIONS = profiling/functioncallcount.stp - Count Times Functions Called -- cgit From a53e0eeb262399f79c0b1b219c7d5f96c2c10fb4 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Fri, 3 Apr 2009 14:41:14 -0400 Subject: Correct column heading from uid to pid. --- testsuite/systemtap.examples/profiling/timeout.stp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/testsuite/systemtap.examples/profiling/timeout.stp b/testsuite/systemtap.examples/profiling/timeout.stp index 7af4a88f..8054b364 100755 --- a/testsuite/systemtap.examples/profiling/timeout.stp +++ b/testsuite/systemtap.examples/profiling/timeout.stp @@ -91,7 +91,7 @@ probe syscall.exit { probe timer.s(1) { ansi_clear_screen() - printf (" uid | poll select epoll itimer futex nanosle signal| process\n") + printf (" pid | poll select epoll itimer futex nanosle signal| process\n") foreach (p in timeout_count- limit 20) { printf ("%5d |%7d %7d %7d %7d %7d %7d %7d| %-.38s\n", p, poll_timeout[p], select_timeout[p], -- cgit From 1bcb8a30c3c138373c2b21a5d3820d132dacf162 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 3 Apr 2009 13:32:22 -0700 Subject: PR10032: Trigger cleanup after relay thread errors When the relay threads encounter an error, they now send SIGTERM to the rest of the process before the thread exit, so we get a clean shutdown. For EPIPE in particular, error messages are also suppressed. --- runtime/staprun/relay.c | 17 ++++++++++++----- runtime/staprun/relay_old.c | 18 +++++++++++++----- 2 files changed, 25 insertions(+), 10 deletions(-) diff --git a/runtime/staprun/relay.c b/runtime/staprun/relay.c index 694cb27e..b9796241 100644 --- a/runtime/staprun/relay.c +++ b/runtime/staprun/relay.c @@ -185,7 +185,7 @@ static void *reader_thread(void *data) dbug(3, "cpu=%d poll=%d errno=%d\n", cpu, rc, errno); if (errno != EINTR) { _perr("poll error"); - return(NULL); + goto error_out; } } while ((rc = read(relay_fd[cpu], buf, sizeof(buf))) > 0) { @@ -198,17 +198,24 @@ static void *reader_thread(void *data) remove_file = 1; if (open_outfile(fnum, cpu, remove_file) < 0) { perr("Couldn't open file for cpu %d, exiting.", cpu); - return(NULL); + goto error_out; } wsize = rc; } if (write(out_fd[cpu], buf, rc) != rc) { - perr("Couldn't write to output %d for cpu %d, exiting.", out_fd[cpu], cpu); - return(NULL); + if (errno != EPIPE) + perr("Couldn't write to output %d for cpu %d, exiting.", out_fd[cpu], cpu); + goto error_out; } } } while (!stop_threads); - dbug(3, "exiting thread %d\n", cpu); + dbug(3, "exiting thread for cpu %d\n", cpu); + return(NULL); + +error_out: + /* Signal the main thread that we need to quit */ + kill(getpid(), SIGTERM); + dbug(2, "exiting thread for cpu %d after error\n", cpu); return(NULL); } diff --git a/runtime/staprun/relay_old.c b/runtime/staprun/relay_old.c index 469a5831..33d2daf3 100644 --- a/runtime/staprun/relay_old.c +++ b/runtime/staprun/relay_old.c @@ -239,14 +239,15 @@ static int process_subbufs(struct _stp_buf_info *info, scb->rmfile = 1; if (open_oldoutfile(scb->fnum, cpu, scb->rmfile) < 0) { perr("Couldn't open file for cpu %d, exiting.", cpu); - exit(1); + return -1; } scb->wsize = len; } if (len) { if (fwrite_unlocked (subbuf_ptr, len, 1, percpu_tmpfile[cpu]) != 1) { - _perr("Couldn't write to output file for cpu %d, exiting:", cpu); - exit(1); + if (errno != EPIPE) + _perr("Couldn't write to output file for cpu %d, exiting:", cpu); + return -1; } } subbufs_consumed++; @@ -281,14 +282,17 @@ static void *reader_thread(void *data) if (rc < 0) { if (errno != EINTR) { _perr("poll error"); - exit(1); + break; } err("WARNING: poll warning: %s\n", strerror(errno)); rc = 0; } rc = read(proc_fd[cpu], &status[cpu].info, sizeof(struct _stp_buf_info)); - subbufs_consumed = process_subbufs(&status[cpu].info, &scb); + rc = process_subbufs(&status[cpu].info, &scb); + if (rc < 0) + break; + subbufs_consumed = rc; if (subbufs_consumed) { if (subbufs_consumed > status[cpu].max_backlog) status[cpu].max_backlog = subbufs_consumed; @@ -301,6 +305,10 @@ static void *reader_thread(void *data) if (status[cpu].info.flushing) pthread_exit(NULL); } while (1); + + /* Signal the main thread that we need to quit */ + kill(getpid(), SIGTERM); + pthread_exit(NULL); } /** -- cgit From 8a03658eed54ff02494107f0ca55081f352df75b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 3 Apr 2009 14:50:18 -0700 Subject: PR5163: Assign need_uprobes during pass-2 We were doing this in pass-3, which means it was never set for cached runs, and so staprun didn't get the -u flag. Now need_probes is set as soon as a uprobe_derived_probe is saved into the session in pass-2. --- tapsets.cxx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index c81285e2..f6d73714 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -7500,6 +7500,10 @@ uprobe_derived_probe::join_group (systemtap_session& s) s.uprobe_derived_probes = new uprobe_derived_probe_group (); s.uprobe_derived_probes->enroll (this); task_finder_derived_probe_group::create_session_group (s); + + // Ask buildrun.cxx to build extra module if needed, and + // signal staprun to load that module + s.need_uprobes = true; } @@ -7532,8 +7536,6 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) if (probes.empty()) return; s.op->newline() << "/* ---- user probes ---- */"; - s.need_uprobes = true; // Ask buildrun.cxx to build extra module if needed - // If uprobes isn't in the kernel, pull it in from the runtime. s.op->newline() << "#if defined(CONFIG_UPROBES) || defined(CONFIG_UPROBES_MODULE)"; s.op->newline() << "#include "; -- cgit From 4e1801d37ecda01c75181a345dcd07a23cd64da0 Mon Sep 17 00:00:00 2001 From: Eugeniy Meshcheryakov Date: Sat, 4 Apr 2009 21:36:52 +0200 Subject: Make examples executable --- testsuite/systemtap.examples/network/tcp.stp | 0 testsuite/systemtap.examples/process/errsnoop.stp | 0 2 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 testsuite/systemtap.examples/network/tcp.stp mode change 100644 => 100755 testsuite/systemtap.examples/process/errsnoop.stp diff --git a/testsuite/systemtap.examples/network/tcp.stp b/testsuite/systemtap.examples/network/tcp.stp old mode 100644 new mode 100755 diff --git a/testsuite/systemtap.examples/process/errsnoop.stp b/testsuite/systemtap.examples/process/errsnoop.stp old mode 100644 new mode 100755 -- cgit From f68afd7e0d3404a1b830982ec0eed0b1e392b203 Mon Sep 17 00:00:00 2001 From: Eugeniy Meshcheryakov Date: Sat, 4 Apr 2009 21:58:06 +0200 Subject: Remove extra commas in SEE ALSO sections --- man/stapprobes.iosched.3stap.in | 2 +- man/stapprobes.netdev.3stap.in | 2 +- man/stapprobes.nfs.3stap.in | 2 +- man/stapprobes.nfsd.3stap.in | 2 +- man/stapprobes.pagefault.3stap.in | 2 +- man/stapprobes.process.3stap.in | 2 +- man/stapprobes.rpc.3stap.in | 2 +- man/stapprobes.scsi.3stap.in | 2 +- man/stapprobes.signal.3stap.in | 2 +- man/stapprobes.tcp.3stap.in | 2 +- man/stapprobes.udp.3stap.in | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/man/stapprobes.iosched.3stap.in b/man/stapprobes.iosched.3stap.in index e08dce8c..873251ac 100644 --- a/man/stapprobes.iosched.3stap.in +++ b/man/stapprobes.iosched.3stap.in @@ -96,5 +96,5 @@ Fires when a request is completed .SH SEE ALSO .IR stap (1), -.IR stapprobes (3stap), +.IR stapprobes (3stap) diff --git a/man/stapprobes.netdev.3stap.in b/man/stapprobes.netdev.3stap.in index c25fbd44..9b2e57ed 100644 --- a/man/stapprobes.netdev.3stap.in +++ b/man/stapprobes.netdev.3stap.in @@ -74,4 +74,4 @@ Fires when the network device wants to transmit a buffer .SH SEE ALSO .IR stap (1), -.IR stapprobes (3stap), +.IR stapprobes (3stap) diff --git a/man/stapprobes.nfs.3stap.in b/man/stapprobes.nfs.3stap.in index b6a81cde..579af533 100644 --- a/man/stapprobes.nfs.3stap.in +++ b/man/stapprobes.nfs.3stap.in @@ -1232,5 +1232,5 @@ Fires whenever nfs client renames a file on server .SH SEE ALSO .IR stap (1), -.IR stapprobes (3stap), +.IR stapprobes (3stap) diff --git a/man/stapprobes.nfsd.3stap.in b/man/stapprobes.nfsd.3stap.in index d3aea639..239d3b94 100644 --- a/man/stapprobes.nfsd.3stap.in +++ b/man/stapprobes.nfsd.3stap.in @@ -509,5 +509,5 @@ Fires whenever server receives NFS operation from client .SH SEE ALSO .IR stap (1), -.IR stapprobes (3stap), +.IR stapprobes (3stap) diff --git a/man/stapprobes.pagefault.3stap.in b/man/stapprobes.pagefault.3stap.in index b1c53a19..7d4f266e 100644 --- a/man/stapprobes.pagefault.3stap.in +++ b/man/stapprobes.pagefault.3stap.in @@ -36,5 +36,5 @@ Fires when there is a pagefault .SH SEE ALSO .IR stap (1), -.IR stapprobes (3stap), +.IR stapprobes (3stap) diff --git a/man/stapprobes.process.3stap.in b/man/stapprobes.process.3stap.in index 3b5e751d..aa8089e8 100644 --- a/man/stapprobes.process.3stap.in +++ b/man/stapprobes.process.3stap.in @@ -102,5 +102,5 @@ process waits in a zombie state. .SH SEE ALSO .IR stap (1), -.IR stapprobes (3stap), +.IR stapprobes (3stap) diff --git a/man/stapprobes.rpc.3stap.in b/man/stapprobes.rpc.3stap.in index a2622fe5..6061b206 100644 --- a/man/stapprobes.rpc.3stap.in +++ b/man/stapprobes.rpc.3stap.in @@ -579,5 +579,5 @@ Fires when a task is to be delayed .SH SEE ALSO .IR stap (1), -.IR stapprobes (3stap), +.IR stapprobes (3stap) diff --git a/man/stapprobes.scsi.3stap.in b/man/stapprobes.scsi.3stap.in index b595105a..afe16541 100644 --- a/man/stapprobes.scsi.3stap.in +++ b/man/stapprobes.scsi.3stap.in @@ -147,5 +147,5 @@ block device I/O requests .SH SEE ALSO .IR stap (1), -.IR stapprobes (3stap), +.IR stapprobes (3stap) diff --git a/man/stapprobes.signal.3stap.in b/man/stapprobes.signal.3stap.in index f42a7781..9b7ccd5f 100644 --- a/man/stapprobes.signal.3stap.in +++ b/man/stapprobes.signal.3stap.in @@ -505,5 +505,5 @@ Fires when flush all pending signals for a task .SH SEE ALSO .IR stap (1), -.IR stapprobes (3stap), +.IR stapprobes (3stap) diff --git a/man/stapprobes.tcp.3stap.in b/man/stapprobes.tcp.3stap.in index 3e607b69..88603f58 100644 --- a/man/stapprobes.tcp.3stap.in +++ b/man/stapprobes.tcp.3stap.in @@ -98,5 +98,5 @@ Fires when returning from tcp.disconnect .SH SEE ALSO .IR stap (1), -.IR stapprobes (3stap), +.IR stapprobes (3stap) diff --git a/man/stapprobes.udp.3stap.in b/man/stapprobes.udp.3stap.in index 3fbfd3e7..dae11578 100644 --- a/man/stapprobes.udp.3stap.in +++ b/man/stapprobes.udp.3stap.in @@ -98,5 +98,5 @@ Fires when returning from udp.disconnect .SH SEE ALSO .IR stap (1), -.IR stapprobes (3stap), +.IR stapprobes (3stap) -- cgit From a03c97419b5192fd594afb1f84e9ae4d0801e3a9 Mon Sep 17 00:00:00 2001 From: Eugene Teo Date: Sun, 5 Apr 2009 11:52:44 +0800 Subject: Amend process/errsnoop.stp shebang --- testsuite/systemtap.examples/process/errsnoop.stp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/testsuite/systemtap.examples/process/errsnoop.stp b/testsuite/systemtap.examples/process/errsnoop.stp index d9fba3b7..a3f17b77 100755 --- a/testsuite/systemtap.examples/process/errsnoop.stp +++ b/testsuite/systemtap.examples/process/errsnoop.stp @@ -1,4 +1,5 @@ -#!/usr/bin/env stap +#!/bin/sh +//usr/bin/env stap -DMAXMAPENTRIES=20480 $0 $@; exit $? # errsnoop.stp # Copyright (C) 2009 Red Hat, Inc., Eugene Teo # -- cgit From 009b315e209db7ab3569c54950afe31b6172b174 Mon Sep 17 00:00:00 2001 From: Eugeniy Meshcheryakov Date: Mon, 6 Apr 2009 17:42:18 +0200 Subject: Make install-scripts depend on install-binSCRIPTS This is needed for running make with -j. Fixes Debian bug #522800. --- Makefile.am | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Makefile.am b/Makefile.am index 580c4178..b4d97e9a 100644 --- a/Makefile.am +++ b/Makefile.am @@ -122,7 +122,8 @@ if BUILD_SERVER install-exec-local: install-scripts PHONIES += install-scripts -install-scripts: +# scripts should be installed before this rule is run +install-scripts: install-binSCRIPTS for f in $(bin_SCRIPTS); do \ sed -i -e "/INSTALL-HOOK/d;s,exec_prefix=,exec_prefix=$(exec_prefix)/bin/,;s,sysconfdir=.*,sysconfdir=$(sysconfdir)," $(DESTDIR)$(bindir)/$$f; \ done -- cgit From c905968022ea42d4957dee5df78fcd219c8ea9f1 Mon Sep 17 00:00:00 2001 From: Eugeniy Meshcheryakov Date: Mon, 6 Apr 2009 17:43:44 +0200 Subject: Run autoreconf --- Makefile.in | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Makefile.in b/Makefile.in index 7f880e7f..42bdec7c 100644 --- a/Makefile.in +++ b/Makefile.in @@ -72,7 +72,7 @@ DIST_COMMON = INSTALL NEWS README AUTHORS $(srcdir)/Makefile.in \ $(top_srcdir)/man/stapprobes.tcp.3stap.in \ $(top_srcdir)/man/stapprobes.udp.3stap.in \ $(top_srcdir)/initscript/systemtap.in $(srcdir)/run-stap.in \ - depcomp $(oldinclude_HEADERS) + $(srcdir)/run-staprun.in depcomp $(oldinclude_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -89,7 +89,7 @@ CONFIG_CLEAN_FILES = stap.1 stapprobes.3stap stapfuncs.3stap \ man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap \ man/stapprobes.signal.3stap man/stapprobes.socket.3stap \ man/stapprobes.tcp.3stap man/stapprobes.udp.3stap \ - initscript/systemtap run-stap + initscript/systemtap run-stap run-staprun @BUILD_SERVER_TRUE@am__EXEEXT_1 = stap-client-connect$(EXEEXT) \ @BUILD_SERVER_TRUE@ stap-server-connect$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkglibexecdir)" \ @@ -475,6 +475,8 @@ initscript/systemtap: $(top_builddir)/config.status $(top_srcdir)/initscript/sys cd $(top_builddir) && $(SHELL) ./config.status $@ run-stap: $(top_builddir)/config.status $(srcdir)/run-stap.in cd $(top_builddir) && $(SHELL) ./config.status $@ +run-staprun: $(top_builddir)/config.status $(srcdir)/run-staprun.in + cd $(top_builddir) && $(SHELL) ./config.status $@ install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @@ -1468,7 +1470,8 @@ cscope: @BUILD_ELFUTILS_TRUE@install-exec-local: install-elfutils @BUILD_SERVER_TRUE@install-exec-local: install-scripts -@BUILD_SERVER_TRUE@install-scripts: +# scripts should be installed before this rule is run +@BUILD_SERVER_TRUE@install-scripts: install-binSCRIPTS @BUILD_SERVER_TRUE@ for f in $(bin_SCRIPTS); do \ @BUILD_SERVER_TRUE@ sed -i -e "/INSTALL-HOOK/d;s,exec_prefix=,exec_prefix=$(exec_prefix)/bin/,;s,sysconfdir=.*,sysconfdir=$(sysconfdir)," $(DESTDIR)$(bindir)/$$f; \ @BUILD_SERVER_TRUE@ done -- cgit From b4c34c261909065b97dfccfd6df996897457193c Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Mon, 6 Apr 2009 19:40:13 -0400 Subject: PR10037: add target_symbol token to $context error messages * tapsets.cxx (many foo-translate-bar): Add const target_symbol* parameter, for ->tok use when constructing semantic_errors. --- tapsets.cxx | 145 +++++++++++++++++++++++++++++++++--------------------------- 1 file changed, 81 insertions(+), 64 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index f6d73714..c4348a29 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -1796,6 +1796,7 @@ struct dwflpp find_variable_and_frame_base (Dwarf_Die *scope_die, Dwarf_Addr pc, string const & local, + const target_symbol *e, Dwarf_Die *vardie, Dwarf_Attribute *fb_attr_mem) { @@ -1823,7 +1824,8 @@ struct dwflpp + (dwarf_diename(scope_die) ?: "") + "(" + (dwarf_diename(cu) ?: "") + ")")) - + " while searching for local '" + local + "'"); + + " while searching for local '" + local + "'", + e->tok); } int declaring_scope = dwarf_getscopevar (scopes, nscopes, @@ -1841,7 +1843,8 @@ struct dwflpp + (dwarf_diename(scope_die) ?: "") + "(" + (dwarf_diename(cu) ?: "") + ")")) - + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")"))); + + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")), + e->tok); } for (int inner = 0; inner < nscopes; ++inner) @@ -1868,7 +1871,8 @@ struct dwflpp translate_location(struct obstack *pool, Dwarf_Attribute *attr, Dwarf_Addr pc, Dwarf_Attribute *fb_attr, - struct location **tail) + struct location **tail, + const target_symbol *e) { Dwarf_Op *expr; size_t len; @@ -1887,12 +1891,13 @@ struct dwflpp /* Fall through. */ case 0: /* Shouldn't happen. */ - throw semantic_error ("not accessible at this address"); + throw semantic_error ("not accessible at this address", e->tok); default: /* Shouldn't happen. */ case -1: throw semantic_error (string ("dwarf_getlocation_addr failed") + - string (dwarf_errmsg (-1))); + string (dwarf_errmsg (-1)), + e->tok); } return c_translate_location (pool, &loc2c_error, this, @@ -1976,8 +1981,7 @@ struct dwflpp translate_components(struct obstack *pool, struct location **tail, Dwarf_Addr pc, - vector > const & components, + const target_symbol *e, Dwarf_Die *vardie, Dwarf_Die *die_mem, Dwarf_Attribute *attr_mem) @@ -1996,7 +2000,7 @@ struct dwflpp static unsigned int dwarf_error_count ; // keeps track of no of dwarf errors static semantic_error saved_dwarf_error(""); - while (i < components.size()) + while (i < e->components.size()) { /* XXX: This would be desirable, but we don't get the target_symbol token, and printing that gives us the file:line number too early anyway. */ @@ -2017,8 +2021,8 @@ struct dwflpp break; case DW_TAG_pointer_type: - if (components[i].first == target_symbol::comp_literal_array_index) - throw semantic_error ("cannot index pointer"); + if (e->components[i].first == target_symbol::comp_literal_array_index) + throw semantic_error ("cannot index pointer", e->tok); // XXX: of course, we should support this the same way C does, // by explicit pointer arithmetic etc. PR4166. @@ -2026,16 +2030,17 @@ struct dwflpp break; case DW_TAG_array_type: - if (components[i].first == target_symbol::comp_literal_array_index) + if (e->components[i].first == target_symbol::comp_literal_array_index) { c_translate_array (pool, 1, 0 /* PR9768 */, die, tail, - NULL, lex_cast(components[i].second)); + NULL, lex_cast(e->components[i].second)); ++i; } else throw semantic_error("bad field '" - + components[i].second - + "' for array type"); + + e->components[i].second + + "' for array type", + e->tok); break; case DW_TAG_structure_type: @@ -2046,7 +2051,8 @@ struct dwflpp Dwarf_Die *tmpdie = dwflpp::declaration_resolve(dwarf_diename(die)); if (tmpdie == NULL) throw semantic_error ("unresolved struct " - + string (dwarf_diename_integrate (die) ?: "")); + + string (dwarf_diename_integrate (die) ?: ""), + e->tok); *die_mem = *tmpdie; } switch (dwarf_child (die, die_mem)) @@ -2057,7 +2063,8 @@ struct dwflpp default: /* Shouldn't happen */ throw semantic_error (string (typetag == DW_TAG_union_type ? "union" : "struct") + string (dwarf_diename_integrate (die) ?: "") - + string (dwarf_errmsg (-1))); + + string (dwarf_errmsg (-1)), + e->tok); break; case 0: @@ -2066,7 +2073,7 @@ struct dwflpp while (dwarf_tag (die) != DW_TAG_member || ({ const char *member = dwarf_diename_integrate (die); - member == NULL || string(member) != components[i].second; })) + member == NULL || string(member) != e->components[i].second; })) { if ( dwarf_diename (die) == NULL ) // handling Anonymous structs/unions { @@ -2079,19 +2086,19 @@ struct dwflpp { dwarf_error_flag ++ ; dwarf_error_count ++; - throw semantic_error(" Error in obtaining type attribute for "+ string(dwarf_diename(&temp_die)?:"")); + throw semantic_error(" Error in obtaining type attribute for "+ string(dwarf_diename(&temp_die)?:""), e->tok); } if ( !dwarf_formref_die (&temp_attr, &temp_die)) { dwarf_error_flag ++ ; dwarf_error_count ++; - throw semantic_error(" Error in decoding DW_AT_type attribute for " + string(dwarf_diename(&temp_die)?:"")); + throw semantic_error(" Error in decoding DW_AT_type attribute for " + string(dwarf_diename(&temp_die)?:""), e->tok); } func_call_level ++ ; - Dwarf_Die *result_die = translate_components(pool, tail, pc, components, &temp_die, &temp_die_2, &temp_attr ); + Dwarf_Die *result_die = translate_components(pool, tail, pc, e, &temp_die, &temp_die_2, &temp_attr); func_call_level -- ; @@ -2129,34 +2136,38 @@ struct dwflpp but just use the containing union's location. */ if (typetag != DW_TAG_union_type) throw semantic_error ("no location for field '" - + components[i].second - + "' :" + string(dwarf_errmsg (-1))); + + e->components[i].second + + "' :" + string(dwarf_errmsg (-1)), + e->tok); } else - translate_location (pool, attr_mem, pc, NULL, tail); + translate_location (pool, attr_mem, pc, NULL, tail, e); ++i; break; case DW_TAG_base_type: throw semantic_error ("field '" - + components[i].second + + e->components[i].second + "' vs. base type " - + string(dwarf_diename_integrate (die) ?: "")); + + string(dwarf_diename_integrate (die) ?: ""), + e->tok); break; case -1: - throw semantic_error ("cannot find type: " + string(dwarf_errmsg (-1))); + throw semantic_error ("cannot find type: " + string(dwarf_errmsg (-1)), + e->tok); break; default: throw semantic_error (string(dwarf_diename_integrate (die) ?: "") + ": unexpected type tag " - + lex_cast(dwarf_tag (die))); + + lex_cast(dwarf_tag (die)), + e->tok); break; } /* Now iterate on the type in DIE's attribute. */ if (dwarf_attr_integrate (die, DW_AT_type, attr_mem) == NULL) - throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1))); + throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)), e->tok); die = dwarf_formref_die (attr_mem, die_mem); } return die; @@ -2165,23 +2176,23 @@ struct dwflpp Dwarf_Die * resolve_unqualified_inner_typedie (Dwarf_Die *typedie_mem, - Dwarf_Attribute *attr_mem) + Dwarf_Attribute *attr_mem, + const target_symbol *e) { - ; Dwarf_Die *typedie; int typetag = 0; while (1) { typedie = dwarf_formref_die (attr_mem, typedie_mem); if (typedie == NULL) - throw semantic_error ("cannot get type: " + string(dwarf_errmsg (-1))); + throw semantic_error ("cannot get type: " + string(dwarf_errmsg (-1)), e->tok); typetag = dwarf_tag (typedie); if (typetag != DW_TAG_typedef && typetag != DW_TAG_const_type && typetag != DW_TAG_volatile_type) break; if (dwarf_attr_integrate (typedie, DW_AT_type, attr_mem) == NULL) - throw semantic_error ("cannot get type of pointee: " + string(dwarf_errmsg (-1))); + throw semantic_error ("cannot get type of pointee: " + string(dwarf_errmsg (-1)), e->tok); } return typedie; } @@ -2194,6 +2205,7 @@ struct dwflpp Dwarf_Die *die, Dwarf_Attribute *attr_mem, bool lvalue, + const target_symbol *e, string &, string &, exp_type & ty) @@ -2207,7 +2219,7 @@ struct dwflpp char const *dname; string diestr; - typedie = resolve_unqualified_inner_typedie (&typedie_mem, attr_mem); + typedie = resolve_unqualified_inner_typedie (&typedie_mem, attr_mem, e); typetag = dwarf_tag (typedie); /* Then switch behavior depending on the type of fetch/store we @@ -2220,7 +2232,7 @@ struct dwflpp diestr = (dname != NULL) ? dname : ""; throw semantic_error ("unsupported type tag " + lex_cast(typetag) - + " for " + diestr); + + " for " + diestr, e->tok); break; case DW_TAG_structure_type: @@ -2228,7 +2240,7 @@ struct dwflpp dname = dwarf_diename(die); diestr = (dname != NULL) ? dname : ""; throw semantic_error ("struct/union '" + diestr - + "' is being accessed instead of a member of the struct/union"); + + "' is being accessed instead of a member of the struct/union", e->tok); break; case DW_TAG_enumeration_type: @@ -2247,7 +2259,7 @@ struct dwflpp { // clog << "bad type1 " << encoding << " diestr" << endl; throw semantic_error ("unsupported type (mystery encoding " + lex_cast(encoding) + ")" + - " for " + diestr); + " for " + diestr, e->tok); } if (encoding == DW_ATE_float @@ -2256,7 +2268,7 @@ struct dwflpp { // clog << "bad type " << encoding << " diestr" << endl; throw semantic_error ("unsupported type (encoding " + lex_cast(encoding) + ")" + - " for " + diestr); + " for " + diestr, e->tok); } } @@ -2278,7 +2290,7 @@ struct dwflpp Dwarf_Word pointee_encoding; Dwarf_Word pointee_byte_size = 0; - pointee_typedie = resolve_unqualified_inner_typedie (&pointee_typedie_mem, attr_mem); + pointee_typedie = resolve_unqualified_inner_typedie (&pointee_typedie_mem, attr_mem, e); if (dwarf_attr_integrate (pointee_typedie, DW_AT_byte_size, attr_mem)) dwarf_formudata (attr_mem, &pointee_byte_size); @@ -2290,7 +2302,7 @@ struct dwflpp { ty = pe_long; if (typetag == DW_TAG_array_type) - throw semantic_error ("cannot write to array address"); + throw semantic_error ("cannot write to array address", e->tok); assert (typetag == DW_TAG_pointer_type); c_translate_pointer_store (pool, 1, 0 /* PR9768 */, typedie, tail, "THIS->value"); @@ -2355,15 +2367,14 @@ struct dwflpp literal_stmt_for_local (Dwarf_Die *scope_die, Dwarf_Addr pc, string const & local, - vector > const & components, + const target_symbol *e, bool lvalue, exp_type & ty) { Dwarf_Die vardie; Dwarf_Attribute fb_attr_mem, *fb_attr = NULL; - fb_attr = find_variable_and_frame_base (scope_die, pc, local, + fb_attr = find_variable_and_frame_base (scope_die, pc, local, e, &vardie, &fb_attr_mem); if (sess.verbose>2) @@ -2379,7 +2390,8 @@ struct dwflpp "attribute for local '" + local + "' (dieoffset: " + lex_cast_hex(dwarf_dieoffset (&vardie)) - + ")"); + + ")", + e->tok); } #define obstack_chunk_alloc malloc @@ -2392,17 +2404,19 @@ struct dwflpp /* Given $foo->bar->baz[NN], translate the location of foo. */ struct location *head = translate_location (&pool, - &attr_mem, pc, fb_attr, &tail); + &attr_mem, pc, fb_attr, &tail, + e); if (dwarf_attr_integrate (&vardie, DW_AT_type, &attr_mem) == NULL) throw semantic_error("failed to retrieve type " - "attribute for local '" + local + "'"); + "attribute for local '" + local + "'", + e->tok); /* Translate the ->bar->baz[NN] parts. */ Dwarf_Die die_mem, *die = NULL; die = dwarf_formref_die (&attr_mem, &die_mem); - die = translate_components (&pool, &tail, pc, components, + die = translate_components (&pool, &tail, pc, e, die, &die_mem, &attr_mem); if(!die) { @@ -2412,7 +2426,8 @@ struct dwflpp print_members(die,alternatives); throw semantic_error("unable to find local '" + local + "'" + " near pc " + lex_cast_hex(pc) - + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")"))); + + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")), + e->tok); } /* Translate the assignment part, either @@ -2423,7 +2438,7 @@ struct dwflpp string prelude, postlude; translate_final_fetch_or_store (&pool, &tail, module_bias, - die, &attr_mem, lvalue, + die, &attr_mem, lvalue, e, prelude, postlude, ty); /* Write the translation to a string. */ @@ -2434,8 +2449,7 @@ struct dwflpp string literal_stmt_for_return (Dwarf_Die *scope_die, Dwarf_Addr pc, - vector > const & components, + const target_symbol *e, bool lvalue, exp_type & ty) { @@ -2460,7 +2474,8 @@ struct dwflpp " for " + string(dwarf_diename(scope_die) ?: "") + "(" + string(dwarf_diename(cu) ?: "") - + ")"); + + ")", + e->tok); } // the function has no return value (e.g. "void" in C) else if (nlocops == 0) @@ -2468,7 +2483,8 @@ struct dwflpp throw semantic_error("function " + string(dwarf_diename(scope_die) ?: "") + "(" + string(dwarf_diename(cu) ?: "") - + ") has no return value"); + + ") has no return value", + e->tok); } struct location *head = c_translate_location (&pool, &loc2c_error, this, @@ -2486,7 +2502,7 @@ struct dwflpp Dwarf_Die *vardie = dwarf_formref_die (attr, &vardie_mem); Dwarf_Die die_mem, *die = NULL; - die = translate_components (&pool, &tail, pc, components, + die = translate_components (&pool, &tail, pc, e, vardie, &die_mem, &attr_mem); if(!die) { @@ -2500,7 +2516,8 @@ struct dwflpp + string(dwarf_diename(scope_die) ?: "") + "(" + string(dwarf_diename(cu) ?: "") + ")" - + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")"))); + + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")), + e->tok); } @@ -2512,7 +2529,7 @@ struct dwflpp string prelude, postlude; translate_final_fetch_or_store (&pool, &tail, module_bias, - die, &attr_mem, lvalue, + die, &attr_mem, lvalue, e, prelude, postlude, ty); /* Write the translation to a string. */ @@ -2522,8 +2539,7 @@ struct dwflpp string literal_stmt_for_pointer (Dwarf_Die *type_die, - vector > const & components, + const target_symbol *e, bool lvalue, exp_type & ty) { @@ -2545,7 +2561,7 @@ struct dwflpp Dwarf_Attribute attr_mem; Dwarf_Die die_mem, *die = NULL; - die = translate_components (&pool, &tail, 0, components, + die = translate_components (&pool, &tail, 0, e, type_die, &die_mem, &attr_mem); if(!die) { @@ -2554,7 +2570,8 @@ struct dwflpp print_members(die ?: type_die, alternatives); throw semantic_error("unable to find member for struct " + string(dwarf_diename(die ?: type_die) ?: "") - + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")"))); + + (alternatives.str() == "" ? "" : (" (alternatives:" + alternatives.str () + ")")), + e->tok); } @@ -2566,7 +2583,7 @@ struct dwflpp string prelude, postlude; translate_final_fetch_or_store (&pool, &tail, module_bias, - die, &attr_mem, lvalue, + die, &attr_mem, lvalue, e, prelude, postlude, ty); /* Write the translation to a string. */ @@ -4865,7 +4882,7 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) { ec->code = q.dw.literal_stmt_for_return (scope_die, addr, - e->components, + e, lvalue, fdecl->type); } @@ -4874,7 +4891,7 @@ dwarf_var_expanding_visitor::visit_target_symbol (target_symbol *e) ec->code = q.dw.literal_stmt_for_local (scope_die, addr, e->base_name.substr(1), - e->components, + e, lvalue, fdecl->type); } @@ -5008,7 +5025,7 @@ dwarf_cast_query::handle_query_cu(Dwarf_Die * cudie) { try { - code = dw.literal_stmt_for_pointer (type_die, e.components, + code = dw.literal_stmt_for_pointer (type_die, &e, lvalue, pe_type); } catch (const semantic_error& e) @@ -9509,7 +9526,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) try { - ec->code = dw.literal_stmt_for_pointer (&arg->type_die, e->components, + ec->code = dw.literal_stmt_for_pointer (&arg->type_die, e, lvalue, fdecl->type); } catch (const semantic_error& er) -- cgit From 3e3bd7b6b9dd2ba282990f39d60e3ad5ecfec023 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 6 Apr 2009 16:11:30 -0700 Subject: PR10026: Read marker/tracepoint args directly We already stash the context variables for markers and tracepoints into the locals for the probe body, but then we were using separate functions to read those locals for each particular probe body. This patch instead teaches the unparser how to emit the local name directly for those context variables. The resulting code from the translator is much simpler now. --- elaborate.cxx | 3 +++ elaborate.h | 5 ++++ staptree.h | 1 + tapsets.cxx | 86 +++++++++++++++++++---------------------------------------- translate.cxx | 7 ++++- 5 files changed, 43 insertions(+), 59 deletions(-) diff --git a/elaborate.cxx b/elaborate.cxx index 34e6ab16..323261c7 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -3392,6 +3392,9 @@ typeresolution_info::visit_symbol (symbol* e) void typeresolution_info::visit_target_symbol (target_symbol* e) { + if (!e->probe_context_var.empty()) + return; + // This occurs only if a target symbol was not resolved over in // tapset.cxx land, that error was properly suppressed, and the // later unused-expression-elimination pass didn't get rid of it diff --git a/elaborate.h b/elaborate.h index 0ad5b4b2..d927177b 100644 --- a/elaborate.h +++ b/elaborate.h @@ -129,6 +129,11 @@ struct derived_probe: public probe void printsig_nested (std::ostream &o) const; virtual void collect_derivation_chain (std::vector &probes_list); + virtual void print_dupe_stamp(std::ostream&) {} + // To aid duplication elimination, print a stamp which uniquely identifies + // the code that will be added to the probe body. (Doesn't need to be the + // actual code...) + virtual void emit_probe_context_vars (translator_output*) {} // From within unparser::emit_common_header, add any extra variables // to this probe's context locals. diff --git a/staptree.h b/staptree.h index 5125cd85..7e9506bb 100644 --- a/staptree.h +++ b/staptree.h @@ -231,6 +231,7 @@ struct target_symbol: public symbol }; std::string base_name; std::vector > components; + std::string probe_context_var; semantic_error* saved_conversion_error; target_symbol(): saved_conversion_error (0) {} void print (std::ostream& o) const; diff --git a/tapsets.cxx b/tapsets.cxx index c4348a29..0ff26be8 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -8671,6 +8671,7 @@ struct mark_derived_probe: public derived_probe bool target_symbol_seen; void join_group (systemtap_session& s); + void print_dupe_stamp (ostream& o); void emit_probe_context_vars (translator_output* o); void initialize_probe_context_vars (translator_output* o); void printargs (std::ostream &o) const; @@ -8774,36 +8775,9 @@ mark_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) // Remember that we've seen a target variable. target_symbol_seen = true; - // Synthesize a function. - functiondecl *fdecl = new functiondecl; - fdecl->tok = e->tok; - embeddedcode *ec = new embeddedcode; - ec->tok = e->tok; - - string fname = string("_mark_tvar_get") - + "_" + e->base_name.substr(1) - + "_" + lex_cast(tick++); - - if (mark_args[argnum-1]->stp_type == pe_long) - ec->code = string("THIS->__retvalue = CONTEXT->locals[0].") - + probe_name + string(".__mark_arg") - + lex_cast(argnum) + string (";"); - else - ec->code = string("strlcpy (THIS->__retvalue, CONTEXT->locals[0].") - + probe_name + string(".__mark_arg") - + lex_cast(argnum) + string (", MAXSTRINGLEN);"); - ec->code += "/* pure */"; - fdecl->name = fname; - fdecl->body = ec; - fdecl->type = mark_args[argnum-1]->stp_type; - sess.functions[fdecl->name]=fdecl; - - // Synthesize a functioncall. - functioncall* n = new functioncall; - n->tok = e->tok; - n->function = fname; - n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - provide (n); + e->probe_context_var = "__mark_arg" + lex_cast(argnum); + e->type = mark_args[argnum-1]->stp_type; + provide (e); } @@ -9053,6 +9027,15 @@ mark_derived_probe::join_group (systemtap_session& s) } +void +mark_derived_probe::print_dupe_stamp (ostream& o) +{ + if (target_symbol_seen) + for (unsigned i = 0; i < mark_args.size(); i++) + o << mark_args[i]->c_type << " __mark_arg" << (i+1) << endl; +} + + void mark_derived_probe::emit_probe_context_vars (translator_output* o) { @@ -9391,6 +9374,7 @@ struct tracepoint_derived_probe: public derived_probe void build_args(dwflpp& dw, Dwarf_Die& func_die); void printargs (std::ostream &o) const; void join_group (systemtap_session& s); + void print_dupe_stamp(ostream& o); void emit_probe_context_vars (translator_output* o); }; @@ -9480,33 +9464,10 @@ tracepoint_var_expanding_visitor::visit_target_symbol_arg (target_symbol* e) if (e->components.empty()) { - // Synthesize a simple function to grab the parameter - functiondecl *fdecl = new functiondecl; - fdecl->tok = e->tok; - embeddedcode *ec = new embeddedcode; - ec->tok = e->tok; - - string fname = (string("_tracepoint_tvar_get") - + "_" + e->base_name.substr(1) - + "_" + lex_cast(tick++)); - - fdecl->name = fname; - fdecl->body = ec; - fdecl->type = pe_long; - - ec->code = (string("THIS->__retvalue = CONTEXT->locals[0].") - + probe_name + string(".__tracepoint_arg_") - + arg->name + string (";/* pure */")); - - dw.sess.functions[fdecl->name] = fdecl; - - // Synthesize a functioncall. - functioncall* n = new functioncall; - n->tok = e->tok; - n->function = fname; - n->referent = 0; // NB: must not resolve yet, to ensure inclusion in session - - provide (n); + // Just grab the value from the probe locals + e->probe_context_var = "__tracepoint_arg_" + arg->name; + e->type = pe_long; + provide (e); } else { @@ -9629,7 +9590,6 @@ tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) } else if (e->base_name == "$$vars" || e->base_name == "$$parms") { - target_symbol *tsym = new target_symbol; print_format* pf = new print_format; // Convert $$vars to sprintf of a list of vars which we recursively evaluate @@ -9653,6 +9613,7 @@ tracepoint_var_expanding_visitor::visit_target_symbol_context (target_symbol* e) if (i > 0) pf->raw_components += " "; pf->raw_components += args[i].name; + target_symbol *tsym = new target_symbol; tsym->tok = e->tok; tsym->base_name = "$" + args[i].name; @@ -9882,6 +9843,15 @@ tracepoint_derived_probe::join_group (systemtap_session& s) } +void +tracepoint_derived_probe::print_dupe_stamp(ostream& o) +{ + for (unsigned i = 0; i < args.size(); i++) + if (args[i].used) + o << "__tracepoint_arg_" << args[i].name << endl; +} + + void tracepoint_derived_probe::emit_probe_context_vars (translator_output* o) { diff --git a/translate.cxx b/translate.cxx index cab37487..c42097bb 100644 --- a/translate.cxx +++ b/translate.cxx @@ -918,6 +918,7 @@ c_unparser::emit_common_header () ostringstream oss; oss << "c->statp = & time_" << dp->basest()->name << ";" << endl; // -t anti-dupe oss << "# needs_global_locks: " << dp->needs_global_locks () << endl; + dp->print_dupe_stamp (oss); dp->body->print(oss); // NB: dependent probe conditions *could* be listed here, but don't need to be. // That's because they're only dependent on the probe body, which is already @@ -1507,6 +1508,7 @@ c_unparser::emit_probe (derived_probe* v) // be very different with or without -t. oss << "c->statp = & time_" << v->basest()->name << ";" << endl; + v->print_dupe_stamp (oss); v->body->print(oss); // Since the generated C changes based on whether or not the probe @@ -3488,7 +3490,10 @@ c_unparser_assignment::visit_symbol (symbol *e) void c_unparser::visit_target_symbol (target_symbol* e) { - throw semantic_error("cannot translate general target-symbol expression", e->tok); + if (!e->probe_context_var.empty()) + o->line() << "l->" << e->probe_context_var; + else + throw semantic_error("cannot translate general cast expression", e->tok); } -- cgit From 782040b3f07a908790c074d94c6253c9966c18b2 Mon Sep 17 00:00:00 2001 From: David Smith Date: Tue, 7 Apr 2009 08:23:14 -0500 Subject: PR 9940. Rearchitected task_finder.c a bit. 2009-04-07 David Smith PR 9940. * tapsets.cxx (emit_vma_callback_probe_decl): Initialized new callbacks. (utrace_derived_probe_group::emit_probe_decl): Ditto. (uprobe_derived_probe_group::emit_module_decls): Uses new callback. Makes sure mapping is executable before trying to set a probe in it. (itrace_derived_probe_group::emit_module_init): Calls _stp_sym_init(). (utrace_derived_probe_group::emit_module_init): Ditto. (uprobe_derived_probe_group::emit_module_init): Ditto. * runtime/sym.c: Moved task_finder_vma.c inclusion here from task_finder.c. (_stp_sym_init): New function. (_stp_tf_mmap_cb): New function that replaces _stp_tf_vm_cb. (_stp_tf_munmap_cb): Ditto. * runtime/task_finder.c: Removed task_finder_vma.c inclusion. Split vm_callback into 3 callbacks: mmap_callback, munmap_callback, and mprotect_callback. (stap_register_task_finder_target): Initializes new events variables for the new callbacks. (__STP_TASK_VM_BASE_EVENTS): No longer specifies syscall entry events. (__stp_call_mmap_callbacks): New function. (__stp_call_mmap_callbacks_with_vma): Ditto. (__stp_call_munmap_callbacks): Ditto. (__stp_call_mprotect_callbacks): Ditto. (__stp_call_vm_callbacks): Removed. (__stp_utrace_task_finder_target_quiesce): Calls __stp_call_mmap_callbacks() instead of __stp_call_vm_callbacks(). (__stp_utrace_task_finder_target_syscall_entry): Removed function. (__stp_utrace_task_finder_target_syscall_exit): Reports raw mmap()/mprotect()/munmap() events. --- runtime/sym.c | 68 ++++--- runtime/task_finder.c | 491 ++++++++++++++++++++++---------------------------- tapsets.cxx | 31 ++-- 3 files changed, 281 insertions(+), 309 deletions(-) diff --git a/runtime/sym.c b/runtime/sym.c index ecd64fee..69c3fe26 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -13,6 +13,7 @@ #define _STP_SYM_C_ #include "string.c" +#include "task_finder_vma.c" /** @file sym.c * @addtogroup sym Symbolic Functions @@ -20,38 +21,59 @@ * @{ */ +static void _stp_sym_init(void) +{ + static int initialized = 0; + if (! initialized) { + __stp_tf_vma_initialize(); + initialized = 1; + } +} + /* Callback that needs to be registered (in tapsets.cxx for emit_module_init) for every user task path or pid for which we might need symbols or unwind info. */ -static int _stp_tf_vm_cb(struct stap_task_finder_target *tgt, - struct task_struct *tsk, - int map_p, char *vm_path, - unsigned long vm_start, unsigned long vm_end, - unsigned long vm_pgoff) +static int _stp_tf_mmap_cb(struct stap_task_finder_target *tgt, + struct task_struct *tsk, + char *path, + unsigned long addr, + unsigned long length, + unsigned long offset, + unsigned long vm_flags) { - int i; + int i; + struct _stp_module *module = NULL; + #ifdef DEBUG_TASK_FINDER_VMA - _stp_dbug(__FUNCTION__, __LINE__, "vm_cb: tsk %d:%d path %s, start 0x%08lx, end 0x%08lx, offset 0x%lx\n", tsk->pid, map_p, vm_path, vm_start, vm_end, vm_pgoff); + _stp_dbug(__FUNCTION__, __LINE__, + "mmap_cb: tsk %d path %s, addr 0x%08lx, length 0x%08lx, offset 0x%lx, flags 0x%lx\n", + tsk->pid, path, addr, length, offset, flags); #endif - if (map_p) - { - struct _stp_module *module = NULL; - if (vm_path != NULL) - for (i = 0; i < _stp_num_modules; i++) - if (strcmp(vm_path, _stp_modules[i]->path) == 0) - { + if (path != NULL) { + for (i = 0; i < _stp_num_modules; i++) { + if (strcmp(path, _stp_modules[i]->path) == 0) + { #ifdef DEBUG_TASK_FINDER_VMA - _stp_dbug(__FUNCTION__, __LINE__, "vm_cb: matched path %s to module\n", vm_path); + _stp_dbug(__FUNCTION__, __LINE__, + "vm_cb: matched path %s to module\n", + path); #endif - module = _stp_modules[i]; - break; - } - stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff, module); - } - else - stap_remove_vma_map_info(tsk, vm_start, vm_end, vm_pgoff); + module = _stp_modules[i]; + break; + } + } + } + stap_add_vma_map_info(tsk, addr, addr + length, offset, module); + return 0; +} - return 0; +static int _stp_tf_munmap_cb(struct stap_task_finder_target *tgt, + struct task_struct *tsk, + unsigned long addr, + unsigned long length) +{ + stap_remove_vma_map_info(tsk, addr, addr + length, 0); + return 0; } /* XXX: this needs to be address-space-specific. */ diff --git a/runtime/task_finder.c b/runtime/task_finder.c index 3507c669..69b6246b 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -2,32 +2,8 @@ #define TASK_FINDER_C #if ! defined(CONFIG_UTRACE) -/* Dummy definitions for use in sym.c */ -struct stap_task_finder_target { }; - -static int -stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, - unsigned long vm_end, unsigned long vm_pgoff, - void *user) -{ - return 0; -} - -static int -stap_remove_vma_map_info(struct task_struct *tsk, unsigned long vm_start, - unsigned long vm_end, unsigned long vm_pgoff) -{ - return 0; -} - -static int -stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, - unsigned long *vm_start, unsigned long *vm_end, - unsigned long *vm_pgoff, void **user) -{ - return ESRCH; -} -#else +#error "Need CONFIG_UTRACE!" +#endif #include @@ -42,7 +18,6 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, #include "syscall.h" #include "utrace_compatibility.h" -#include "task_finder_vma.c" static LIST_HEAD(__stp_task_finder_list); @@ -86,12 +61,26 @@ typedef int (*stap_task_finder_callback)(struct stap_task_finder_target *tgt, int register_p, int process_p); -typedef int (*stap_task_finder_vm_callback)(struct stap_task_finder_target *tgt, - struct task_struct *tsk, - int map_p, char *vm_path, - unsigned long vm_start, - unsigned long vm_end, - unsigned long vm_pgoff); +typedef int +(*stap_task_finder_mmap_callback)(struct stap_task_finder_target *tgt, + struct task_struct *tsk, + char *path, + unsigned long addr, + unsigned long length, + unsigned long offset, + unsigned long vm_flags); +typedef int +(*stap_task_finder_munmap_callback)(struct stap_task_finder_target *tgt, + struct task_struct *tsk, + unsigned long addr, + unsigned long length); + +typedef int +(*stap_task_finder_mprotect_callback)(struct stap_task_finder_target *tgt, + struct task_struct *tsk, + unsigned long addr, + unsigned long length, + int prot); struct stap_task_finder_target { /* private: */ @@ -100,14 +89,18 @@ struct stap_task_finder_target { struct list_head callback_list; struct utrace_engine_ops ops; unsigned engine_attached:1; - unsigned vm_events:1; + unsigned mmap_events:1; + unsigned munmap_events:1; + unsigned mprotect_events:1; size_t pathlen; /* public: */ const char *pathname; pid_t pid; stap_task_finder_callback callback; - stap_task_finder_vm_callback vm_callback; + stap_task_finder_mmap_callback mmap_callback; + stap_task_finder_munmap_callback munmap_callback; + stap_task_finder_mprotect_callback mprotect_callback; }; #ifdef UTRACE_ORIG_VERSION @@ -133,19 +126,6 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action, unsigned long event); #endif -#ifdef UTRACE_ORIG_VERSION -static u32 -__stp_utrace_task_finder_target_syscall_entry(struct utrace_attached_engine *engine, - struct task_struct *tsk, - struct pt_regs *regs); -#else -static u32 -__stp_utrace_task_finder_target_syscall_entry(enum utrace_resume_action action, - struct utrace_attached_engine *engine, - struct task_struct *tsk, - struct pt_regs *regs); -#endif - #ifdef UTRACE_ORIG_VERSION static u32 __stp_utrace_task_finder_target_syscall_exit(struct utrace_attached_engine *engine, @@ -179,12 +159,12 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt) // Make sure everything is initialized properly. new_tgt->engine_attached = 0; - new_tgt->vm_events = 0; + new_tgt->mmap_events = 0; + new_tgt->munmap_events = 0; + new_tgt->mprotect_events = 0; memset(&new_tgt->ops, 0, sizeof(new_tgt->ops)); new_tgt->ops.report_death = &__stp_utrace_task_finder_target_death; new_tgt->ops.report_quiesce = &__stp_utrace_task_finder_target_quiesce; - new_tgt->ops.report_syscall_entry = \ - &__stp_utrace_task_finder_target_syscall_entry; new_tgt->ops.report_syscall_exit = \ &__stp_utrace_task_finder_target_syscall_exit; @@ -216,9 +196,13 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt) // Add this target to the callback list for this task. list_add_tail(&new_tgt->callback_list, &tgt->callback_list_head); - // If the new target has a vm_callback, remember this. - if (new_tgt->vm_callback != NULL) - tgt->vm_events = 1; + // If the new target has any m* callbacks, remember this. + if (new_tgt->mmap_callback != NULL) + tgt->mmap_events = 1; + if (new_tgt->munmap_callback != NULL) + tgt->munmap_events = 1; + if (new_tgt->mprotect_callback != NULL) + tgt->mprotect_events = 1; return 0; } @@ -401,15 +385,14 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen) /* * __STP_TASK_BASE_EVENTS: base events for stap_task_finder_target's - * without vm_callback's + * without map callback's * * __STP_TASK_VM_BASE_EVENTS: base events for - * stap_task_finder_target's with vm_callback's + * stap_task_finder_target's with map callback's */ #define __STP_TASK_BASE_EVENTS (UTRACE_EVENT(DEATH)) #define __STP_TASK_VM_BASE_EVENTS (__STP_TASK_BASE_EVENTS \ - | UTRACE_EVENT(SYSCALL_ENTRY)\ | UTRACE_EVENT(SYSCALL_EXIT)) /* @@ -421,8 +404,10 @@ __stp_get_mm_path(struct mm_struct *mm, char *buf, int buflen) #define __STP_ATTACHED_TASK_EVENTS (__STP_TASK_BASE_EVENTS \ | UTRACE_EVENT(QUIESCE)) -#define __STP_ATTACHED_TASK_BASE_EVENTS(tgt) \ - ((tgt)->vm_events ? __STP_TASK_VM_BASE_EVENTS : __STP_TASK_BASE_EVENTS) +#define __STP_ATTACHED_TASK_BASE_EVENTS(tgt) \ + (((tgt)->mmap_events || (tgt)->munmap_events \ + || (tgt)->mprotect_events) \ + ? __STP_TASK_VM_BASE_EVENTS : __STP_TASK_BASE_EVENTS) static int __stp_utrace_attach(struct task_struct *tsk, @@ -538,11 +523,113 @@ __stp_call_callbacks(struct stap_task_finder_target *tgt, } } +static void +__stp_call_mmap_callbacks(struct stap_task_finder_target *tgt, + struct task_struct *tsk, char *path, + unsigned long addr, unsigned long length, + unsigned long offset, unsigned long vm_flags) +{ + struct list_head *cb_node; + int rc; + + if (tgt == NULL || tsk == NULL) + return; + +#ifdef DEBUG_TASK_FINDER_VMA + _stp_dbug(__FUNCTION__, __LINE__, + "pid %d, a/l/o/p/path 0x%lx 0x%lx 0x%lx %c%c%c%c %s\n", + tsk->pid, addr, length, offset, + vm_flags & VM_READ ? 'r' : '-', + vm_flags & VM_WRITE ? 'w' : '-', + vm_flags & VM_EXEC ? 'x' : '-', + vm_flags & VM_MAYSHARE ? 's' : 'p', + path); +#endif + list_for_each(cb_node, &tgt->callback_list_head) { + struct stap_task_finder_target *cb_tgt; + + cb_tgt = list_entry(cb_node, struct stap_task_finder_target, + callback_list); + if (cb_tgt == NULL || cb_tgt->mmap_callback == NULL) + continue; + + rc = cb_tgt->mmap_callback(cb_tgt, tsk, path, addr, length, + offset, vm_flags); + if (rc != 0) { + _stp_error("mmap callback for %d failed: %d", + (int)tsk->pid, rc); + } + } +} + +static void +__stp_call_mmap_callbacks_with_vma(struct stap_task_finder_target *tgt, + struct task_struct *tsk, + struct vm_area_struct *vma) +{ + char *mmpath_buf; + char *mmpath; + int rc; + + // Allocate space for a path + mmpath_buf = _stp_kmalloc(PATH_MAX); + if (mmpath_buf == NULL) { + _stp_error("Unable to allocate space for path"); + return; + } + + // Grab the path associated with this vma. +#ifdef STAPCONF_DPATH_PATH + mmpath = d_path(&(vma->vm_file->f_path), mmpath_buf, PATH_MAX); +#else + mmpath = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt, + mmpath_buf, PATH_MAX); +#endif + if (mmpath == NULL || IS_ERR(mmpath)) { + rc = -PTR_ERR(mmpath); + _stp_error("Unable to get path (error %d) for pid %d", + rc, (int)tsk->pid); + } + else { + __stp_call_mmap_callbacks(tgt, tsk, mmpath, vma->vm_start, + vma->vm_end - vma->vm_start, + (vma->vm_pgoff << PAGE_SHIFT), + vma->vm_flags); + } + _stp_kfree(mmpath_buf); +} + +static inline void +__stp_call_munmap_callbacks(struct stap_task_finder_target *tgt, + struct task_struct *tsk, unsigned long addr, + unsigned long length) +{ + struct list_head *cb_node; + int rc; + + if (tgt == NULL || tsk == NULL) + return; + + list_for_each(cb_node, &tgt->callback_list_head) { + struct stap_task_finder_target *cb_tgt; + + cb_tgt = list_entry(cb_node, struct stap_task_finder_target, + callback_list); + if (cb_tgt == NULL || cb_tgt->munmap_callback == NULL) + continue; + + rc = cb_tgt->munmap_callback(cb_tgt, tsk, addr, length); + if (rc != 0) { + _stp_error("munmap callback for %d failed: %d", + (int)tsk->pid, rc); + } + } +} + static inline void -__stp_call_vm_callbacks(struct stap_task_finder_target *tgt, - struct task_struct *tsk, int map_p, char *vm_path, - unsigned long vm_start, unsigned long vm_end, - unsigned long vm_pgoff) +__stp_call_mprotect_callbacks(struct stap_task_finder_target *tgt, + struct task_struct *tsk, unsigned long addr, + unsigned long length, int prot) { struct list_head *cb_node; int rc; @@ -555,13 +642,13 @@ __stp_call_vm_callbacks(struct stap_task_finder_target *tgt, cb_tgt = list_entry(cb_node, struct stap_task_finder_target, callback_list); - if (cb_tgt == NULL || cb_tgt->vm_callback == NULL) + if (cb_tgt == NULL || cb_tgt->mprotect_callback == NULL) continue; - rc = cb_tgt->vm_callback(cb_tgt, tsk, map_p, vm_path, - vm_start, vm_end, vm_pgoff); + rc = cb_tgt->mprotect_callback(cb_tgt, tsk, addr, length, + prot); if (rc != 0) { - _stp_error("vm callback for %d failed: %d", + _stp_error("mprotect callback for %d failed: %d", (int)tsk->pid, rc); } } @@ -888,16 +975,16 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action, __stp_call_callbacks(tgt, tsk, 1, (tsk->pid == tsk->tgid)); /* If this is just a thread other than the thread group leader, - don't bother inform vm_callback clients about its memory map, + don't bother inform map callback clients about its memory map, since they will simply duplicate each other. */ - if (tgt->vm_events == 1 && tsk->tgid == tsk->pid) { + if (tgt->mmap_events == 1 && tsk->tgid == tsk->pid) { struct mm_struct *mm; char *mmpath_buf; char *mmpath; struct vm_area_struct *vma; int rc; - /* Call the vm_callback for every vma associated with + /* Call the mmap_callback for every vma associated with * a file. */ mm = get_task_mm(tsk); if (! mm) @@ -924,12 +1011,13 @@ __stp_utrace_task_finder_target_quiesce(enum utrace_resume_action action, mmpath_buf, PATH_MAX); #endif if (mmpath) { - __stp_call_vm_callbacks(tgt, tsk, 1, - mmpath, - vma->vm_start, - vma->vm_end, - (vma->vm_pgoff - << PAGE_SHIFT)); + __stp_call_mmap_callbacks(tgt, tsk, + mmpath, + vma->vm_start, + vma->vm_end - vma->vm_start, + (vma->vm_pgoff + << PAGE_SHIFT), + vma->vm_flags); } else { _stp_dbug(__FUNCTION__, __LINE__, @@ -962,112 +1050,6 @@ __stp_find_file_based_vma(struct mm_struct *mm, unsigned long addr) return vma; } -#ifdef UTRACE_ORIG_VERSION -static u32 -__stp_utrace_task_finder_target_syscall_entry(struct utrace_attached_engine *engine, - struct task_struct *tsk, - struct pt_regs *regs) -#else -static u32 -__stp_utrace_task_finder_target_syscall_entry(enum utrace_resume_action action, - struct utrace_attached_engine *engine, - struct task_struct *tsk, - struct pt_regs *regs) -#endif -{ - struct stap_task_finder_target *tgt = engine->data; - unsigned long syscall_no; - struct mm_struct *mm; - struct vm_area_struct *vma; - unsigned long *arg0_addr, arg0; - int rc; -#if defined(__ia64__) - struct { unsigned long *unwaddr; } _c = {.unwaddr = NULL}, *c = &_c; -#endif - - if (atomic_read(&__stp_task_finder_state) != __STP_TF_RUNNING) { - debug_task_finder_detach(); - return UTRACE_DETACH; - } - - if (tgt == NULL || tgt->vm_events == 0) - return UTRACE_RESUME; - - // See if syscall is one we're interested in. - // - // FIXME: do we need to handle mremap()? - syscall_no = __stp_user_syscall_nr(regs); - if (syscall_no != MMAP_SYSCALL_NO(tsk) - && syscall_no != MMAP2_SYSCALL_NO(tsk) - && syscall_no != MPROTECT_SYSCALL_NO(tsk) - && syscall_no != MUNMAP_SYSCALL_NO(tsk)) - return UTRACE_RESUME; - - __stp_tf_handler_start(); - - // We need the first syscall argument to see what address - // we're operating on. - arg0_addr = __stp_user_syscall_arg(tsk, regs, 0); - if ((rc = __stp_get_user(arg0, arg0_addr)) != 0) { - _stp_error("couldn't read syscall arg 0 for pid %d: %d", - tsk->pid, rc); - } - else if (arg0 != (unsigned long)NULL) { - mm = get_task_mm(tsk); - if (mm) { - down_read(&mm->mmap_sem); - - // If we can find a matching vma associated - // with a file, save off its details. - vma = __stp_find_file_based_vma(mm, arg0); - if (vma != NULL) { - __stp_tf_add_vma(tsk, arg0, vma); - } - - up_read(&mm->mmap_sem); - mmput(mm); - } - } - __stp_tf_handler_end(); - return UTRACE_RESUME; -} - -static void -__stp_call_vm_callbacks_with_vma(struct stap_task_finder_target *tgt, - struct task_struct *tsk, - struct vm_area_struct *vma) -{ - char *mmpath_buf; - char *mmpath; - int rc; - - // Allocate space for a path - mmpath_buf = _stp_kmalloc(PATH_MAX); - if (mmpath_buf == NULL) { - _stp_error("Unable to allocate space for path"); - return; - } - - // Grab the path associated with this vma. -#ifdef STAPCONF_DPATH_PATH - mmpath = d_path(&(vma->vm_file->f_path), mmpath_buf, PATH_MAX); -#else - mmpath = d_path(vma->vm_file->f_dentry, vma->vm_file->f_vfsmnt, - mmpath_buf, PATH_MAX); -#endif - if (mmpath == NULL || IS_ERR(mmpath)) { - rc = -PTR_ERR(mmpath); - _stp_error("Unable to get path (error %d) for pid %d", - rc, (int)tsk->pid); - } - else { - __stp_call_vm_callbacks(tgt, tsk, 1, mmpath, - vma->vm_start, vma->vm_end, - (vma->vm_pgoff << PAGE_SHIFT)); - } - _stp_kfree(mmpath_buf); -} - #ifdef UTRACE_ORIG_VERSION static u32 __stp_utrace_task_finder_target_syscall_exit(struct utrace_attached_engine *engine, @@ -1084,11 +1066,12 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action, struct stap_task_finder_target *tgt = engine->data; unsigned long syscall_no; unsigned long *rv_addr, rv; - unsigned long *arg0_addr, arg0; + unsigned long *arg_addr, arg0; + unsigned long arg1 = 0; + unsigned long arg2 = 0; int rc; struct mm_struct *mm; struct vm_area_struct *vma; - struct __stp_tf_vma_entry *entry = NULL; #if defined(__ia64__) struct { unsigned long *unwaddr; } _c = {.unwaddr = NULL}, *c = &_c; #endif @@ -1098,7 +1081,7 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action, return UTRACE_DETACH; } - if (tgt == NULL || tgt->vm_events == 0) + if (tgt == NULL) return UTRACE_RESUME; // See if syscall is one we're interested in. @@ -1111,6 +1094,16 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action, && syscall_no != MUNMAP_SYSCALL_NO(tsk)) return UTRACE_RESUME; + // The syscall is one we're interested in, but do we have a + // handler for it? + if (((syscall_no == MMAP_SYSCALL_NO(tsk) + || syscall_no == MMAP2_SYSCALL_NO(tsk)) && tgt->mmap_events == 0) + || (syscall_no == MPROTECT_SYSCALL_NO(tsk) + && tgt->mprotect_events == 0) + || (syscall_no == MUNMAP_SYSCALL_NO(tsk) + && tgt->munmap_events == 0)) + return UTRACE_RESUME; + // Get return value rv_addr = __stp_user_syscall_return_value(tsk, regs); if ((rc = __stp_get_user(rv, rv_addr)) != 0) { @@ -1121,8 +1114,8 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action, // We need the first syscall argument to see what address we // were operating on. - arg0_addr = __stp_user_syscall_arg(tsk, regs, 0); - if ((rc = __stp_get_user(arg0, arg0_addr)) != 0) { + arg_addr = __stp_user_syscall_arg(tsk, regs, 0); + if ((rc = __stp_get_user(arg0, arg_addr)) != 0) { _stp_error("couldn't read syscall arg 0 for pid %d: %d", tsk->pid, rc); return UTRACE_RESUME; @@ -1141,105 +1134,57 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action, #endif __stp_tf_handler_start(); - // Try to find the vma info we might have saved. - if (arg0 != (unsigned long)NULL) - entry = __stp_tf_get_vma_entry(tsk, arg0); + if (syscall_no == MUNMAP_SYSCALL_NO(tsk)) { + // We need the 2nd syscall argument for the length. + arg_addr = __stp_user_syscall_arg(tsk, regs, 1); + if ((rc = __stp_get_user(arg1, arg_addr)) != 0) { + _stp_error("couldn't read syscall arg 1 for pid %d: %d", + tsk->pid, rc); + goto syscall_exit_done; + } + // Call the callbacks + __stp_call_munmap_callbacks(tgt, tsk, arg0, arg1); + } + else if (syscall_no == MMAP_SYSCALL_NO(tsk) + || syscall_no == MMAP2_SYSCALL_NO(tsk)) { - // If entry is NULL, this means we didn't find a file based - // vma to store in the syscall_entry routine. This could mean - // we just created a new vma. - if (entry == NULL) { mm = get_task_mm(tsk); if (mm) { down_read(&mm->mmap_sem); vma = __stp_find_file_based_vma(mm, rv); - if (vma != NULL) { - __stp_call_vm_callbacks_with_vma(tgt, tsk, vma); + + // Call the callbacks + if (vma) { + __stp_call_mmap_callbacks_with_vma(tgt, tsk, + vma); } + up_read(&mm->mmap_sem); mmput(mm); } } - // If we found saved vma information, try to match it up with - // what currently exists. else { -#ifdef DEBUG_TASK_FINDER_VMA - _stp_dbug(__FUNCTION__, __LINE__, - "** found stored vma 0x%lx/0x%lx/0x%lx!\n", - entry->vm_start, entry->vm_end, entry->vm_pgoff); -#endif - mm = get_task_mm(tsk); - if (mm) { - down_read(&mm->mmap_sem); - vma = __stp_find_file_based_vma(mm, entry->vm_start); - - // We couldn't find the vma at all. The - // original vma was deleted. - if (vma == NULL) { - // FIXME: We'll need to figure out to - // retrieve the path of a deleted - // vma. - - __stp_call_vm_callbacks(tgt, tsk, 0, NULL, - entry->vm_start, - entry->vm_end, - (entry->vm_pgoff - << PAGE_SHIFT)); - } - - // If nothing has changed, there is no - // need to call the callback. - else if (vma->vm_start == entry->vm_start - && vma->vm_end == entry->vm_end - && vma->vm_pgoff == entry->vm_pgoff) { - // do nothing - } + // We need the 2nd syscall argument for the length. + arg_addr = __stp_user_syscall_arg(tsk, regs, 1); + if ((rc = __stp_get_user(arg1, arg_addr)) != 0) { + _stp_error("couldn't read syscall arg 1 for pid %d: %d", + tsk->pid, rc); + goto syscall_exit_done; + } - // The original vma has been changed. It is - // possible that calling mprotect (e.g.) split - // up an existing vma into 2 or 3 new vma's - // (assuming it protected a portion of the - // original vma at the beginning, middle, or - // end). Try to determine what happened. - else { - unsigned long tmp; - - // First report that the original vma - // is gone. - // - // FIXME: We'll need to figure out to - // retrieve the path of a deleted - // vma. - __stp_call_vm_callbacks(tgt, tsk, 0, NULL, - entry->vm_start, - entry->vm_end, - (entry->vm_pgoff - << PAGE_SHIFT)); - - // Now find all the new vma's that - // made up the original vma's address - // space and call the callback on each - // new vma. - tmp = entry->vm_start; - while (((vma = __stp_find_file_based_vma(mm, - tmp)) - != NULL) - && vma->vm_end <= entry->vm_end) { - __stp_call_vm_callbacks_with_vma(tgt, - tsk, - vma); - if (vma->vm_end >= entry->vm_end) - break; - tmp = vma->vm_end; - } - } - up_read(&mm->mmap_sem); - mmput(mm); + // We need the 3nd syscall argument for the protection. + arg_addr = __stp_user_syscall_arg(tsk, regs, 2); + if ((rc = __stp_get_user(arg2, arg_addr)) != 0) { + _stp_error("couldn't read syscall arg 2 for pid %d: %d", + tsk->pid, rc); + goto syscall_exit_done; } - // Cleanup by deleting the saved vma info. - __stp_tf_remove_vma_entry(entry); + // Call the callbacks + __stp_call_mprotect_callbacks(tgt, tsk, arg0, arg1, arg2); } + +syscall_exit_done: __stp_tf_handler_end(); return UTRACE_RESUME; } @@ -1264,8 +1209,6 @@ stap_start_task_finder(void) return ENOMEM; } - __stp_tf_vma_initialize(); - atomic_set(&__stp_task_finder_state, __STP_TF_RUNNING); rcu_read_lock(); @@ -1382,6 +1325,4 @@ stap_stop_task_finder(void) } -#endif /* defined(CONFIG_UTRACE) */ - #endif /* TASK_FINDER_C */ diff --git a/tapsets.cxx b/tapsets.cxx index 0ff26be8..57322882 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6248,7 +6248,7 @@ module_info::~module_info() delete sym_table; } -// Helper function to emit vma tracker callback _stp_tf_vm_cb. +// Helper function to emit vma tracker callbacks. static void emit_vma_callback_probe_decl (systemtap_session& s, string path, @@ -6266,7 +6266,9 @@ emit_vma_callback_probe_decl (systemtap_session& s, s.op->line() << " .pid=" << pid << ","; } s.op->line() << " .callback=NULL,"; - s.op->line() << " .vm_callback=&_stp_tf_vm_cb,"; + s.op->line() << " .mmap_callback=&_stp_tf_mmap_cb,"; + s.op->line() << " .munmap_callback=&_stp_tf_munmap_cb,"; + s.op->line() << " .mprotect_callback=NULL,"; s.op->line() << " },"; } @@ -6574,6 +6576,7 @@ itrace_derived_probe_group::emit_module_init (systemtap_session& s) s.op->newline(); s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; + s.op->newline() << "_stp_sym_init();"; s.op->newline() << "/* ---- itrace vma callbacks ---- */"; s.op->newline() << "for (i=0; iindent(1); @@ -6988,7 +6991,9 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s, } s.op->line() << " .callback=&_stp_utrace_probe_cb,"; - s.op->line() << " .vm_callback=NULL,"; + s.op->line() << " .mmap_callback=NULL,"; + s.op->line() << " .munmap_callback=NULL,"; + s.op->line() << " .mprotect_callback=NULL,"; s.op->line() << " },"; s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ","; s.op->line() << " .ph=&" << p->name << ","; @@ -7320,6 +7325,7 @@ utrace_derived_probe_group::emit_module_init (systemtap_session& s) s.op->newline(); s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; + s.op->newline() << "_stp_sym_init();"; s.op->newline() << "/* ---- utrace vma callbacks ---- */"; s.op->newline() << "for (i=0; iindent(1); @@ -7762,23 +7768,25 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(0) << "return stap_uprobe_change (tsk, register_p, 0, sups);"; s.op->newline(-1) << "}"; - // The task_finder_vm_callback we use for ET_DYN targets. + // The task_finder_mmap_callback we use for ET_DYN targets. s.op->newline(); - s.op->newline() << "static int stap_uprobe_vmchange_found (struct stap_task_finder_target *tgt, struct task_struct *tsk, int map_p, char *vm_path, unsigned long vm_start, unsigned long vm_end, unsigned long vm_pgoff) {"; + s.op->newline() << "static int stap_uprobe_mmap_found (struct stap_task_finder_target *tgt, struct task_struct *tsk, char *path, unsigned long addr, unsigned long length, unsigned long offset, unsigned long vm_flags) {"; s.op->newline(1) << "struct stap_uprobe_spec *sups = container_of(tgt, struct stap_uprobe_spec, finder);"; // 1 - shared libraries' executable segments load from offset 0 - ld.so convention - s.op->newline() << "if (vm_pgoff != 0) return 0;"; + s.op->newline() << "if (offset != 0) return 0;"; // 2 - the shared library we're interested in - s.op->newline() << "if (vm_path == NULL || strcmp (vm_path, sups->pathname)) return 0;"; + s.op->newline() << "if (path == NULL || strcmp (path, sups->pathname)) return 0;"; // 3 - probe address within the mapping limits; test should not fail - s.op->newline() << "if (vm_end <= vm_start + sups->address) return 0;"; + s.op->newline() << "if (sups->address >= addr && sups->address < (addr + length)) return 0;"; + // 4 - mapping should be executable + s.op->newline() << "if (!(vm_flags & VM_EXEC)) return 0;"; s.op->newline() << "#ifdef DEBUG_TASK_FINDER_VMA"; - s.op->newline() << "printk (KERN_INFO \"vmchange pid %d map_p %d path %s vms %p vme %p vmp %p\\n\", tsk->tgid, map_p, vm_path, (void*) vm_start, (void*) vm_end, (void*) vm_pgoff);"; + s.op->newline() << "printk (KERN_INFO \"vmchange pid %d path %s addr %p length %lu offset %p\\n\", tsk->tgid, path, (void *) addr, length, (void*) offset);"; s.op->newline() << "printk (KERN_INFO \"sups %p pp %s path %s address %p\\n\", sups, sups->pp, sups->pathname ?: \"\", (void*) sups->address);"; s.op->newline() << "#endif"; - s.op->newline(0) << "return stap_uprobe_change (tsk, map_p, vm_start, sups);"; + s.op->newline(0) << "return stap_uprobe_change (tsk, 1, addr, sups);"; s.op->newline(-1) << "}"; s.op->assert_0_indent(); @@ -7792,6 +7800,7 @@ uprobe_derived_probe_group::emit_module_init (systemtap_session& s) { if (probes.empty()) return; s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; + s.op->newline() << "_stp_sym_init();"; s.op->newline() << "/* ---- uprobe vma callbacks ---- */"; s.op->newline() << "for (i=0; iindent(1); @@ -7815,7 +7824,7 @@ uprobe_derived_probe_group::emit_module_init (systemtap_session& s) s.op->newline(1) << "struct stap_uprobe_spec *sups = & stap_uprobe_specs[i];"; s.op->newline() << "probe_point = sups->pp;"; // for error messages s.op->newline() << "if (sups->finder.pathname) sups->finder.callback = & stap_uprobe_process_found;"; - s.op->newline() << "else if (sups->pathname) sups->finder.vm_callback = & stap_uprobe_vmchange_found;"; + s.op->newline() << "else if (sups->pathname) sups->finder.mmap_callback = & stap_uprobe_mmap_found;"; s.op->newline() << "rc = stap_register_task_finder_target (& sups->finder);"; // NB: if (rc), there is no need (XXX: nor any way) to clean up any -- cgit From fc204b30292a3a5f1aa602171dc44d937cb2c20f Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 7 Apr 2009 12:25:53 +0200 Subject: Create usymname and usymdata variant that trigger STP_NEED_VMA_TRACKER. * tapset/context-symbols.stp (syname, symdata): Pass NULL for kernel address. * tapset/ucontext-symbols.stp: New file defining usymname and usymdata. * testsuite/systemtap.context/usymbols.exp: Use usymname, remove STP_NEED_VMA_TRACKER hack. * testsuite/buildok/usymdata.stp: New test. * testsuite/buildok/usymname.stp: Likewise. --- tapset/context-symbols.stp | 4 +-- tapset/ucontext-symbols.stp | 52 ++++++++++++++++++++++++++++++++ testsuite/buildok/usymdata.stp | 8 +++++ testsuite/buildok/usymname.stp | 8 +++++ testsuite/systemtap.context/usymbols.exp | 5 ++- 5 files changed, 72 insertions(+), 5 deletions(-) create mode 100644 tapset/ucontext-symbols.stp create mode 100755 testsuite/buildok/usymdata.stp create mode 100755 testsuite/buildok/usymname.stp diff --git a/tapset/context-symbols.stp b/tapset/context-symbols.stp index 66d9fea2..783f1b7b 100644 --- a/tapset/context-symbols.stp +++ b/tapset/context-symbols.stp @@ -128,7 +128,7 @@ function modname:string (addr: long) %{ /* pure */ */ function symname:string (addr: long) %{ /* pure */ _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr, - current, 0); + NULL, 0); %} /** @@ -143,5 +143,5 @@ function symname:string (addr: long) %{ /* pure */ */ function symdata:string (addr: long) %{ /* pure */ _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr, - current, 1); + NULL, 1); %} diff --git a/tapset/ucontext-symbols.stp b/tapset/ucontext-symbols.stp new file mode 100644 index 00000000..3813a8bf --- /dev/null +++ b/tapset/ucontext-symbols.stp @@ -0,0 +1,52 @@ +// User context symbols 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. + +// +// User context symbol functions provide additional information about +// addresses from an application. These functions can provide +// information about the user space map (library) that the event occured or +// the function symbol of an address. +// + +%{ +#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 usymname - Return the symbol of an address in the current task. + * @addr: The address to translate. + * + * Description: Returns the (function) symbol name associated with the + * given address if known. If not known it will return the hex string + * representation of addr. + */ +function usymname:string (addr: long) %{ /* pure */ + _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr, + current, 0); +%} + +/** + * sfunction usymdata - Return the symbol and module offset of an address. + * @addr: The address to translate. + * + * Description: Returns the (function) symbol name associated with the + * given address in the current task if known, plus the module name + * (between brackets) and the offset inside the module (shared library), + * plus the size of the symbol function. If any element is not known it + * will be ommitted and if the symbol name is unknown it will return the + * hex string for the given address. + */ +function usymdata:string (addr: long) %{ /* pure */ + _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr, + current, 1); +%} diff --git a/testsuite/buildok/usymdata.stp b/testsuite/buildok/usymdata.stp new file mode 100755 index 00000000..48c1f36f --- /dev/null +++ b/testsuite/buildok/usymdata.stp @@ -0,0 +1,8 @@ +#! stap -p4 +# +# Test the translatability for usymdata() +# +probe begin +{ + log(usymdata(0)) +} diff --git a/testsuite/buildok/usymname.stp b/testsuite/buildok/usymname.stp new file mode 100755 index 00000000..57e3f9c2 --- /dev/null +++ b/testsuite/buildok/usymname.stp @@ -0,0 +1,8 @@ +#! stap -p4 +# +# Test the translatability for usymname() +# +probe begin +{ + log(usymname(0)) +} diff --git a/testsuite/systemtap.context/usymbols.exp b/testsuite/systemtap.context/usymbols.exp index 8af20126..39b3b442 100644 --- a/testsuite/systemtap.context/usymbols.exp +++ b/testsuite/systemtap.context/usymbols.exp @@ -35,7 +35,7 @@ set testscript { probe syscall.rt_sigaction { if (pid() == target() && execname() == "%s") { handler = $act->sa_handler; - printf("handler: %%s\n", symname(handler)); + printf("handler: %%s\n", usymname(handler)); } } /* track through uprobes, so as to make sure we have the symbols */ @@ -56,8 +56,7 @@ if {[string equal "link" [file type $libpath]]} { } send_log "libpath: $libpath\n" -# XXX Cheat, explicitly add STP_NEED_VMA_TRACKER -set cmd [concat stap -DSTP_NEED_VMA_TRACKER -d $libpath -d $testexe -c $testexe -e {$script}] +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" -- cgit From 92f6f03ee1823624f518fd6f9942f91ea88f1fe8 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 7 Apr 2009 14:17:09 +0200 Subject: Track VMA per pid (group_leader/tgid). * runtime/sym.c (_stp_tf_vm_cb): Add and remove tsk->group_leader. (_stp_mod_sec_lookup): find vma for task->group_leader. --- runtime/sym.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/runtime/sym.c b/runtime/sym.c index 69c3fe26..0268f1ab 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -46,8 +46,8 @@ static int _stp_tf_mmap_cb(struct stap_task_finder_target *tgt, #ifdef DEBUG_TASK_FINDER_VMA _stp_dbug(__FUNCTION__, __LINE__, - "mmap_cb: tsk %d path %s, addr 0x%08lx, length 0x%08lx, offset 0x%lx, flags 0x%lx\n", - tsk->pid, path, addr, length, offset, flags); + "mmap_cb: tsk %d:%d path %s, addr 0x%08lx, length 0x%08lx, offset 0x%lx, flags 0x%lx\n", + tsk->pid, tsk->tgid, path, addr, length, offset, flags); #endif if (path != NULL) { for (i = 0; i < _stp_num_modules; i++) { @@ -63,7 +63,8 @@ static int _stp_tf_mmap_cb(struct stap_task_finder_target *tgt, } } } - stap_add_vma_map_info(tsk, addr, addr + length, offset, module); + stap_add_vma_map_info(tsk->group_leader, addr, addr + length, offset, + module); return 0; } @@ -72,7 +73,7 @@ static int _stp_tf_munmap_cb(struct stap_task_finder_target *tgt, unsigned long addr, unsigned long length) { - stap_remove_vma_map_info(tsk, addr, addr + length, 0); + stap_remove_vma_map_info(tsk->group_leader, addr, addr + length, 0); return 0; } @@ -144,7 +145,7 @@ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr, if (task) { unsigned long vm_start = 0; - if (stap_find_vma_map_info(task, addr, + if (stap_find_vma_map_info(task->group_leader, addr, &vm_start, NULL, NULL, &user) == 0) if (user != NULL) -- cgit From 53ad27be6e5829546dba9a61cfee1d043eaafa70 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 7 Apr 2009 14:59:59 +0200 Subject: Add valid interval in error message when timer probe out of range. * tapsets.cxx (hrtimer_derived_probe): Take scale argument, add interval/scale to semantic_error message. (timer_builder): Set and pass scale. --- tapsets.cxx | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index 57322882..04402a27 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -10201,11 +10201,16 @@ struct hrtimer_derived_probe: public derived_probe int64_t interval, randomize; - hrtimer_derived_probe (probe* p, probe_point* l, int64_t i, int64_t r): + hrtimer_derived_probe (probe* p, probe_point* l, int64_t i, int64_t r, + int64_t scale): derived_probe (p, l), interval (i), randomize (r) { if ((i < min_ns_interval) || (i > max_ns_interval)) - throw semantic_error("interval value out of range"); + throw semantic_error(string("interval value out of range (") + + lex_cast(scale < min_ns_interval + ? min_ns_interval/scale : 1) + + "," + + lex_cast(max_ns_interval/scale) + ")"); // randomize = 0 means no randomization if ((r < 0) || (r > i)) @@ -10383,7 +10388,7 @@ timer_builder::build(systemtap_session & sess, literal_map_t const & parameters, vector & finished_results) { - int64_t period, rand=0; + int64_t scale=1, period, rand=0; if (!get_param(parameters, "randomize", rand)) rand = 0; @@ -10404,20 +10409,23 @@ timer_builder::build(systemtap_session & sess, else if (get_param(parameters, "s", period) || get_param(parameters, "sec", period)) { - period *= 1000000000; - rand *= 1000000000; + scale = 1000000000; + period *= scale; + rand *= scale; } else if (get_param(parameters, "ms", period) || get_param(parameters, "msec", period)) { - period *= 1000000; - rand *= 1000000; + scale = 1000000; + period *= scale; + rand *= scale; } else if (get_param(parameters, "us", period) || get_param(parameters, "usec", period)) { - period *= 1000; - rand *= 1000; + scale = 1000; + period *= scale; + rand *= scale; } else if (get_param(parameters, "ns", period) || get_param(parameters, "nsec", period)) @@ -10440,7 +10448,7 @@ timer_builder::build(systemtap_session & sess, } else finished_results.push_back( - new hrtimer_derived_probe(base, location, period, rand)); + new hrtimer_derived_probe(base, location, period, rand, scale)); } void -- cgit From a7f1270e24a77ab8338604ab14ee928a421f89a0 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Tue, 7 Apr 2009 14:46:28 -0400 Subject: Fix so publicanized Tapset Reference manual can be generated again. --- doc/Tapset_Reference_Guide/publicanize.sh | 107 +++++++++++++++++++++--------- 1 file changed, 77 insertions(+), 30 deletions(-) diff --git a/doc/Tapset_Reference_Guide/publicanize.sh b/doc/Tapset_Reference_Guide/publicanize.sh index d4da6e02..0d1b134e 100755 --- a/doc/Tapset_Reference_Guide/publicanize.sh +++ b/doc/Tapset_Reference_Guide/publicanize.sh @@ -1,26 +1,74 @@ #!/bin/bash +INFILE="../SystemTap_Tapset_Reference/tapsets.xml" +OUTFILE="en-US/Tapset_Reference_Guide.xml" +TMPFILE='mktemp' || exit 1 +TMPFILE2='mktemp' || exit 1 -#copy the automated tapsets.xml -cp ../SystemTap_Tapset_Reference/tapsets.xml temp.xml ; +do_help() +{ + echo "publicanize.sh: usage: + -?/--help this message + -i/--input=file input file name + -o/--output=file output file name +" >&2 +} + + +#process optional arguments -i -o +while [ "$#" -ne 0 ] +do + arg=`printf %s $1 | awk -F= '{print $1}'` + val=`printf %s $1 | awk -F= '{print $2}'` + shift + if test -z "$val"; then + local possibleval=$1 + printf %s $1 "$possibleval" | grep ^- >/dev/null 2>&1 + if test "$?" != "0"; then + val=$possibleval + if [ "$#" -ge 1 ]; then + shift + fi + fi + fi + + case "$arg" in + -i|--input) + INFILE=$val + ;; + -o|--output) + OUTFILE=$val + ;; + -\?|--help) + do_help + exit 0 + ;; + *) + echo "Unknown option \"$arg\". See opcontrol --help" >&2 + exit 1 + ;; + esac +done + + +#copy the generated tapsets.xml +cp $INFILE $TMPFILE || exit 1 #remove all excess whitespace -sed -i -e 's/^\s*//g' temp.xml ; +sed -i -e 's/^\s*//g' $TMPFILE -#remove marked Intro (starthere to endhere), then copy it to en-US -sed '/starthere/,/endhere/d' temp.xml > Tapset_Reference_Guide.xml -cp Tapset_Reference_Guide.xml en-US/Tapset_Reference_Guide.xml; -rm Tapset_Reference_Guide.xml +#remove marked Intro (starthere to endhere) +sed -i -e '/starthere/,/endhere/d' $TMPFILE #re-convert programlisting tags -sed -i -e 's/<programlisting>//g' en-US/Tapset_Reference_Guide.xml; -sed -i -e 's/<\/programlisting>/<\/programlisting>/g' en-US/Tapset_Reference_Guide.xml; +sed -i -e 's/<programlisting>//g' $TMPFILE +sed -i -e 's/<\/programlisting>/<\/programlisting>/g' $TMPFILE #replace header -cat en-US/Tapset_Reference_Guide.xml | +cat $TMPFILE | perl -p -e 'undef $/;s|\nSystemTap Tapset Reference Manual|\n|msg' | -perl -p -e 'undef $/;s|\n\nWilliam\nCohen\n\n\n
        \nwcohen\@redhat.com\n
        \n
        \n
        \n
        ||msg' | -perl -p -e 'undef $/;s|\n2008, 2009\nRed Hat, Inc.\n||msg' | +perl -p -e 'undef $/;s|\n\nSystemTap\nHackers\n\n||msg' | +perl -p -e 'undef $/;s|\n2008-2009\nRed Hat, Inc. and others\n||msg' | perl -p -e 'undef $/;s|\n\nThis documentation is free software\; you can redistribute\nit and/or modify it under the terms of the GNU General Public\nLicense version 2 as published by the Free Software Foundation.\n||msg' | perl -p -e 'undef $/;s|\nThis program is distributed in the hope that it will be\nuseful, but WITHOUT ANY WARRANTY; without even the implied\nwarranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\nSee the GNU General Public License for more details.\n||msg' | perl -p -e 'undef $/;s|\nYou should have received a copy of the GNU General Public\nLicense along with this program; if not, write to the Free\nSoftware Foundation, Inc., 59 Temple Place, Suite 330, Boston,\nMA 02111-1307 USA\n||msg' | @@ -32,34 +80,33 @@ perl -p -e 'undef $/;s|\n|\nfunction < perl -p -e 'undef $/;s|\n||msg' | perl -p -e 'undef $/;s|\n\n||msg' | perl -p -e 'undef $/;s|\n||msg' | -perl -p -e 'undef $/;s|\n||msg' > clean.xml +perl -p -e 'undef $/;s|\n|
        |msg' > $TMPFILE2 #replace Intro with my own -perl -p -i -e 's||\n|g' clean.xml +perl -p -i -e 's||\n|g' $TMPFILE2 #for tapset name format section -#perl -p -i -e 'undef $/;s|\nname:return \(parameters\)\ndefinition\n|\nfunction/probe tapset_name:return \(parameters\)\n|msg' clean.xml -#perl -p -i -e 's|In this guide, tapset definitions appear in the following format:|In this guide, the synopsis of each tapset appears in the following format:|g' clean.xml -#perl -p -i -e 's||\n|g' clean.xml +#perl -p -i -e 'undef $/;s|\nname:return \(parameters\)\ndefinition\n|\nfunction/probe tapset_name:return \(parameters\)\n|msg' $TMPFILE2 +#perl -p -i -e 's|In this guide, tapset definitions appear in the following format:|In this guide, the synopsis of each tapset appears in the following format:|g' $TMPFILE2 +#perl -p -i -e 's||\n|g' $TMPFILE2 -cp clean.xml en-US/Tapset_Reference_Guide.xml -rm clean.xml - # statements change synopsis tags, as they are still currently unfixed in publican-redhat -sed -i -e 's/refsynopsisdiv>/refsect1>/g' en-US/Tapset_Reference_Guide.xml; -sed -i -e 's/refsect1>/refsection>/g' en-US/Tapset_Reference_Guide.xml; -sed -i -e 's/synopsis>/programlisting>\n/g' en-US/Tapset_Reference_Guide.xml; +sed -i -e 's/refsynopsisdiv>/refsect1>/g' $TMPFILE2 +sed -i -e 's/refsect1>/refsection>/g' $TMPFILE2 +sed -i -e 's/synopsis>/programlisting>\n/g' $TMPFILE2 # re-convert tags -sed -i -e 's/<emphasis>//g' en-US/Tapset_Reference_Guide.xml; -sed -i -e 's/<\/emphasis>/<\/emphasis>/g' en-US/Tapset_Reference_Guide.xml; +sed -i -e 's/<emphasis>//g' $TMPFILE2 +sed -i -e 's/<\/emphasis>/<\/emphasis>/g' $TMPFILE2 -sed -i -e 's/<remark>//g' en-US/Tapset_Reference_Guide.xml; -sed -i -e 's/<\/remark>/<\/remark>/g' en-US/Tapset_Reference_Guide.xml; +sed -i -e 's/<remark>//g' $TMPFILE2 +sed -i -e 's/<\/remark>/<\/remark>/g' $TMPFILE2 -sed -i -e 's/<command>//g' en-US/Tapset_Reference_Guide.xml; -sed -i -e 's/<\/command>/<\/command>/g' en-US/Tapset_Reference_Guide.xml; +sed -i -e 's/<command>//g' $TMPFILE2 +sed -i -e 's/<\/command>/<\/command>/g' $TMPFILE2 #useful marker script; moves content between starthere and endhere to file target -#sed -n '/starthere/,/endhere/ s/.*/&/w target' Tapset_Reference_Guide.xml \ No newline at end of file +#sed -n '/starthere/,/endhere/ s/.*/&/w target' $TMPFILE2 + +mv $TMPFILE2 $OUTFILE -- cgit From 48cde708db9e1662047def94c2dfd7ffe28aa765 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 8 Apr 2009 10:59:27 +0200 Subject: Add uaddr() context tapset function. * tapset/context.stp (uaddr): New sfunction. * testsuite/buildok/uaddr.stp: New test. --- tapset/context.stp | 25 +++++++++++++++++++++++++ testsuite/buildok/uaddr.stp | 8 ++++++++ 2 files changed, 33 insertions(+) create mode 100755 testsuite/buildok/uaddr.stp diff --git a/tapset/context.stp b/tapset/context.stp index 9f4be0e6..36d68c8d 100644 --- a/tapset/context.stp +++ b/tapset/context.stp @@ -11,6 +11,11 @@ //provide information such as a backtrace to where the event occured and the current register values for the //processor. // + +%{ +#include +%} + /** * sfunction print_regs - Print a register dump. */ @@ -227,3 +232,23 @@ function stack_unused:long () %{ /* pure */ THIS->__retvalue = (long)&a & (THREAD_SIZE-1); %} +/** + * sfunction uaddr - User space address of current running task. + * + * 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. + */ +function uaddr:long () %{ /* pure */ + int64_t addr = 0; + if (current->mm) + { + struct pt_regs *uregs; + uregs = task_pt_regs(current); + if (uregs) + addr = (int64_t) REG_IP(uregs); + } + THIS->__retvalue = addr; +%} + diff --git a/testsuite/buildok/uaddr.stp b/testsuite/buildok/uaddr.stp new file mode 100755 index 00000000..8acfc495 --- /dev/null +++ b/testsuite/buildok/uaddr.stp @@ -0,0 +1,8 @@ +#! stap -p4 +# +# Test the translatability for uaddr() +# +probe begin +{ + printf("uaddr: 0x%x\n", uaddr()) +} -- cgit From 07cee54d6fb720d4300972aaff9300ac8028c88d Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 8 Apr 2009 11:11:34 +0200 Subject: Use _stp_snprintf in _stp_symbol_snprint. * runtime/sym.c (_stp_symbol_snprint): Use _stp_snprintf, no _stp_printf. --- runtime/sym.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/runtime/sym.c b/runtime/sym.c index 0268f1ab..835e1b46 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -380,8 +380,8 @@ static void _stp_symbol_snprint(char *str, size_t len, unsigned long address, task); if (name) { if (add_mod && modname && *modname) - _stp_printf("%s %s+%#lx/%#lx\n", - name, modname, offset, size); + _stp_snprintf(str, len, "%s %s+%#lx/%#lx", + name, modname, offset, size); else strlcpy(str, name, len); } else -- cgit From dc31eb39ab70d9d6b81d1ab02fd49795a4d8f2d0 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 8 Apr 2009 12:35:01 +0200 Subject: Omit symbols that have suspicious addresses (before base) from symbol table. * translate.cxx (dump_unwindsyms): Filter out sym.st_value < base values. --- translate.cxx | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/translate.cxx b/translate.cxx index c42097bb..3442703d 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4576,10 +4576,13 @@ dump_unwindsyms (Dwfl_Module *m, // PC's, so we omit undefined or "fake" absolute addresses. // These fake absolute addresses occur in some older i386 // kernels to indicate they are vDSO symbols, not real - // functions in the kernel. + // functions in the kernel. We also omit symbols that have + // suspicious addresses (before base). if ((GELF_ST_TYPE (sym.st_info) == STT_FUNC || GELF_ST_TYPE (sym.st_info) == STT_OBJECT) // PR10000: also need .data - && !(sym.st_shndx == SHN_UNDEF || sym.st_shndx == SHN_ABS)) + && !(sym.st_shndx == SHN_UNDEF + || sym.st_shndx == SHN_ABS + || sym.st_value < base)) { Dwarf_Addr sym_addr = sym.st_value; const char *secname = NULL; -- cgit From 3dd58c2ac312fc16aa38124987081adbd6697629 Mon Sep 17 00:00:00 2001 From: Eugeniy Meshcheryakov Date: Wed, 8 Apr 2009 16:57:39 +0200 Subject: Fix stats for processes that only transmitted data without receiving --- testsuite/systemtap.examples/network/nettop.stp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/testsuite/systemtap.examples/network/nettop.stp b/testsuite/systemtap.examples/network/nettop.stp index 15b4d62a..b84e4882 100755 --- a/testsuite/systemtap.examples/network/nettop.stp +++ b/testsuite/systemtap.examples/network/nettop.stp @@ -1,6 +1,7 @@ #! /usr/bin/env stap global ifxmit, ifrecv +global ifmerged probe netdev.transmit { @@ -19,6 +20,12 @@ function print_activity() "XMIT_KB", "RECV_KB", "COMMAND") foreach ([pid, dev, exec, uid] in ifrecv-) { + ifmerged[pid, dev, exec, uid] = 1; + } + foreach ([pid, dev, exec, uid] in ifxmit-) { + ifmerged[pid, dev, exec, uid] = 1; + } + foreach ([pid, dev, exec, uid] in ifmerged-) { n_xmit = @count(ifxmit[pid, dev, exec, uid]) n_recv = @count(ifrecv[pid, dev, exec, uid]) printf("%5d %5d %-7s %7d %7d %7d %7d %-15s\n", @@ -32,6 +39,7 @@ function print_activity() delete ifxmit delete ifrecv + delete ifmerged } probe timer.ms(5000), end, error -- cgit From cfde3cb1fdda81a5156df2f39201518d815c2710 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Wed, 8 Apr 2009 12:29:29 -0400 Subject: tweak nettop.stp demo to sort by accumulated counts despite merging --- testsuite/systemtap.examples/network/nettop.stp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/testsuite/systemtap.examples/network/nettop.stp b/testsuite/systemtap.examples/network/nettop.stp index b84e4882..e96548f1 100755 --- a/testsuite/systemtap.examples/network/nettop.stp +++ b/testsuite/systemtap.examples/network/nettop.stp @@ -19,11 +19,11 @@ function print_activity() "PID", "UID", "DEV", "XMIT_PK", "RECV_PK", "XMIT_KB", "RECV_KB", "COMMAND") - foreach ([pid, dev, exec, uid] in ifrecv-) { - ifmerged[pid, dev, exec, uid] = 1; + foreach ([pid, dev, exec, uid] in ifrecv) { + ifmerged[pid, dev, exec, uid] += @count(ifrecv[pid,dev,exec,uid]); } - foreach ([pid, dev, exec, uid] in ifxmit-) { - ifmerged[pid, dev, exec, uid] = 1; + foreach ([pid, dev, exec, uid] in ifxmit) { + ifmerged[pid, dev, exec, uid] += @count(ifxmit[pid,dev,exec,uid]); } foreach ([pid, dev, exec, uid] in ifmerged-) { n_xmit = @count(ifxmit[pid, dev, exec, uid]) -- cgit From 0b113a7a70d617c5e67807c9a897b196db4b3b7a Mon Sep 17 00:00:00 2001 From: Stan Cox Date: Wed, 8 Apr 2009 12:36:37 -0400 Subject: Do not do a partial name comparison for .label. * tapsets.cxx (dwflpp::iterate_over_cu_labels): Compare with strcmp not strncmp. --- tapsets.cxx | 2 +- testsuite/systemtap.base/labels.exp | 15 ++++++++------- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index 04402a27..b12d7711 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -1369,7 +1369,7 @@ struct dwflpp function_name = name; } else if (tag == DW_TAG_label && name != 0 - && ((strncmp(name, sym, strlen(sym)) == 0) + && ((strcmp(name, sym) == 0) || (name_has_wildcard (sym) && function_name_matches_pattern (name, sym)))) { diff --git a/testsuite/systemtap.base/labels.exp b/testsuite/systemtap.base/labels.exp index 2f79a502..f389f08c 100644 --- a/testsuite/systemtap.base/labels.exp +++ b/testsuite/systemtap.base/labels.exp @@ -18,7 +18,7 @@ main () char *c; init_an_int: a = 2; -init_another_int: +init_an_int_again: b = 3; c = \"abc\"; ptr_inited: @@ -32,6 +32,7 @@ set fp [open $label_stppath "w"] puts $fp " probe process(\"labels.x\").function(\"main*@labels.c\").label(\"init_*\") {printf (\"VARS %s\\n\",\$\$vars)} probe process(\"labels.x\").function(\"main*@labels.c\").label(\"ptr_inited\") {printf (\"VARS %s\\n\",\$\$vars)} +probe process(\"labels.x\").function(\"main*@labels.c\").label(\"init_an_int\") {printf (\"init_an_int\\n\")} " close $fp @@ -55,12 +56,12 @@ spawn stap -c $label_exepath $label_stppath wait expect { -timeout 180 - -re {VARS a=0x0 b=0x0.*VARS a=0x2 b=0x0.*VARS a=0x2 b=0x3 c=0x[a-f01-9]} { incr ok; exp_continue } + -re {VARS a=0x0 b=0x0.*init_an_int.*VARS a=0x2 b=0x0.*VARS a=0x2 b=0x3 c=0x[a-f01-9]} { incr ok; exp_continue } timeout { fail "$test (timeout)" } eof { } } -if {$ok == 1} { pass "$test exe .label" } { fail "$test exe .label" } +if {$ok == 1} { pass "$test exe .label" } { fail "$test exe .label $ok" } # address of label in an executable @@ -68,7 +69,7 @@ set label_shpath "[pwd]/label.sh" set fp [open $label_shpath "w"] puts $fp " readelf --debug-dump $label_exepath | awk \" -/init_another_int/ {have_label=1} +/init_an_int_again/ {have_label=1} /DW_AT_low_pc/ {if (have_label) {print \$3;exit;}} \" " @@ -103,7 +104,7 @@ if { $res != "" } { # label in a shared object -spawn stap -p2 -l "process\(\"$label_sopath\"\).function\(\"\*\"\).label\(\"init_another_int\"\)" +spawn stap -p2 -l "process\(\"$label_sopath\"\).function\(\"\*\"\).label\(\"init_an_int_again\"\)" expect { -timeout 180 -re {process.*function} { incr ok; exp_continue } @@ -111,7 +112,7 @@ expect { eof { } } -if {$ok == 1} { pass "$test so .label" } { fail "$test so .label" } +if {$ok == 1} { pass "$test so .label" } { fail "$test so .label $ok" } # address of label in a shared object @@ -119,7 +120,7 @@ set label_shpath "[pwd]/label.sh" set fp [open $label_shpath "w"] puts $fp " readelf --debug-dump $label_sopath | awk \" -/init_another_int/ {have_label=1} +/init_an_int_again/ {have_label=1} /DW_AT_low_pc/ {if (have_label) {print \$3;exit;}} \" " -- cgit From 55c0f2bfefb04915622dd3688bba59da1addaec8 Mon Sep 17 00:00:00 2001 From: David Smith Date: Wed, 8 Apr 2009 12:41:55 -0500 Subject: Only includes task_finder.c when needed. 2009-04-08 David Smith * tapsets.cxx (itrace_derived_probe_group::emit_module_decls): Added inclusion of task_finder.c back. Unconditionally including it when not needed causes all systemtap scripts to fail on kernels with no utrace support. (utrace_derived_probe_group::emit_module_decls): Ditto. (uprobe_derived_probe_group::emit_module_decls): Ditto. * runtime/runtime.h: Removed unconditional inclusion of task_finder.c. --- runtime/runtime.h | 2 -- tapsets.cxx | 22 ++++++++++++++++++++++ 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/runtime/runtime.h b/runtime/runtime.h index 0a656b78..70fe4dce 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -89,8 +89,6 @@ static struct #include "regs.c" #include "regs-ia64.c" -#include "task_finder.c" - #include "sym.c" #ifdef STP_PERFMON #include "perf.c" diff --git a/tapsets.cxx b/tapsets.cxx index 04402a27..a7bda5f5 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6474,6 +6474,14 @@ itrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(); s.op->newline() << "/* ---- itrace probes ---- */"; + + // Note that we can potentially include task_finder.c multiple times + // in the generated code. That is OK, since task_finder.c has guard + // macros to prevent defining things multiple times. If we include + // task_finder.c unconditionally, stap can't be used on systems + // without utrace. + s.op->newline() << "#include \"task_finder.c\""; + s.op->newline() << "struct stap_itrace_probe {"; s.op->indent(1); s.op->newline() << "struct stap_task_finder_target tgt;"; @@ -7058,6 +7066,13 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(); s.op->newline() << "/* ---- utrace probes ---- */"; + // Note that we can potentially include task_finder.c multiple times + // in the generated code. That is OK, since task_finder.c has guard + // macros to prevent defining things multiple times. If we include + // task_finder.c unconditionally, stap can't be used on systems + // without utrace. + s.op->newline() << "#include \"task_finder.c\""; + s.op->newline() << "enum utrace_derived_probe_flags {"; s.op->indent(1); s.op->newline() << "UDPF_NONE,"; @@ -7566,6 +7581,13 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "#include \"uprobes/uprobes.h\""; s.op->newline() << "#endif"; + // Note that we can potentially include task_finder.c multiple times + // in the generated code. That is OK, since task_finder.c has guard + // macros to prevent defining things multiple times. If we include + // task_finder.c unconditionally, stap can't be used on systems + // without utrace. + 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 // or apprx. max number of processes mapping a shared library -- cgit From 117bcbe45ff448c0913007d31cfa2be78caeb4ba Mon Sep 17 00:00:00 2001 From: David Smith Date: Wed, 8 Apr 2009 13:14:24 -0500 Subject: Added '#ifdef STP_NEED_VMA_TRACKER' around code that needs it. 2009-04-08 David Smith * runtime/sym.c: Added '#ifdef STP_NEED_VMA_TRACKER' around code that needs it. --- runtime/sym.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runtime/sym.c b/runtime/sym.c index 835e1b46..7b918428 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -30,6 +30,7 @@ static void _stp_sym_init(void) } } +#ifdef STP_NEED_VMA_TRACKER /* Callback that needs to be registered (in tapsets.cxx for emit_module_init) for every user task path or pid for which we might need symbols or unwind info. */ @@ -76,6 +77,7 @@ static int _stp_tf_munmap_cb(struct stap_task_finder_target *tgt, stap_remove_vma_map_info(tsk->group_leader, addr, addr + length, 0); return 0; } +#endif /* XXX: this needs to be address-space-specific. */ static unsigned long _stp_module_relocate(const char *module, const char *section, unsigned long offset) @@ -128,7 +130,6 @@ static unsigned long _stp_module_relocate(const char *module, const char *sectio return 0; } - /* Return module owner and, if sec != NULL, fills in closest section of the address if found, return NULL otherwise. XXX: needs to be address-space-specific. */ -- cgit From 0af51b594e033a9d7148be6428f7365f2fcd1663 Mon Sep 17 00:00:00 2001 From: David Smith Date: Wed, 8 Apr 2009 15:31:49 -0500 Subject: Better error handling in 'setup_server'. 2009-04-08 David Smith * lib/systemtap.exp (setup_server): Better error handling. --- testsuite/lib/systemtap.exp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/lib/systemtap.exp b/testsuite/lib/systemtap.exp index 5311be7b..98108fa5 100644 --- a/testsuite/lib/systemtap.exp +++ b/testsuite/lib/systemtap.exp @@ -85,7 +85,7 @@ proc setup_server {} { # Make sure that the necessary resources are available to run the client/server. if {[installtest_p]} then { - if {[exec /usr/bin/which stap-client-connect] == ""} then { + if {[catch {exec /usr/bin/which stap-client-connect} dummy]} then { print "Unable to start a server: stap-client-connect is not found in PATH" return 0 } @@ -93,7 +93,7 @@ proc setup_server {} { print "Unable to start a server: [exec pwd]/../stap-client-connect is not found" return 0 } - if {[exec /usr/bin/which avahi-publish-service] == ""} then { + if {[catch {exec /usr/bin/which avahi-publish-service} dummy]} then { print "Unable to start a server: avahi-publish-service is not found in PATH" return 0 } -- cgit From e87251e16921a2d52a35212278e45f0c0af1cc5d Mon Sep 17 00:00:00 2001 From: Stan Cox Date: Wed, 8 Apr 2009 17:19:04 -0400 Subject: Consider function when handling .label * tapsets.cxx(dwflpp::iterate_over_cu_labels): New parameter function. Do wildcard match for function. * testsuite/systemtap.base/labels.exp: Test .label function handling. --- tapsets.cxx | 37 ++++++++++++++++++++++++------------- testsuite/systemtap.base/labels.exp | 13 ++++++++++--- 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index 694490d8..32cd8494 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -1339,7 +1339,8 @@ struct dwflpp } void - iterate_over_cu_labels (string label_val, Dwarf_Die *cu, void *data, + iterate_over_cu_labels (string label_val, string function, Dwarf_Die *cu, + void *data, void (* callback)(const string &, const char *, int, @@ -1364,14 +1365,30 @@ struct dwflpp Dwarf_Attribute *attr = dwarf_attr (&die, DW_AT_name, &attr_mem); int tag = dwarf_tag(&die); const char *name = dwarf_formstring (attr); - if (tag == DW_TAG_subprogram && name != 0) + if (name == 0) + continue; + switch (tag) { + case DW_TAG_label: + break; + case DW_TAG_subprogram: function_name = name; + default: + if (dwarf_haschildren (&die)) + iterate_over_cu_labels (label_val, function, &die, q, callback); + continue; } - else if (tag == DW_TAG_label && name != 0 - && ((strcmp(name, sym) == 0) - || (name_has_wildcard (sym) - && function_name_matches_pattern (name, sym)))) + + if (strcmp(function_name.c_str(), function.c_str()) == 0 + || (name_has_wildcard(function) + && function_name_matches_pattern (function_name, function))) + { + } + else + continue; + if (strcmp(name, sym) == 0 + || (name_has_wildcard(sym) + && function_name_matches_pattern (name, sym))) { const char *file = dwarf_decl_file (&die); // Get the line number for this label @@ -1406,16 +1423,10 @@ struct dwflpp callback(function_name.c_str(), file, (int)dline, &scopes[1], stmt_addr, q); } - if (dwarf_haschildren (&die) && tag != DW_TAG_structure_type - && tag != DW_TAG_union_type) - { - iterate_over_cu_labels (label_val, &die, q, callback); - } } while (dwarf_siblingof (&die, &die) == 0); } - void collect_srcfiles_matching (string const & pattern, set & filtered_srcfiles) { @@ -4110,7 +4121,7 @@ query_cu (Dwarf_Die * cudie, void * arg) { // If we have a pattern string with target *label*, we // have to look at labels in all the matched srcfiles. - q->dw.iterate_over_cu_labels (q->label_val, q->dw.cu, q, query_statement); + q->dw.iterate_over_cu_labels (q->label_val, q->function, q->dw.cu, q, query_statement); } else { diff --git a/testsuite/systemtap.base/labels.exp b/testsuite/systemtap.base/labels.exp index f389f08c..268bb320 100644 --- a/testsuite/systemtap.base/labels.exp +++ b/testsuite/systemtap.base/labels.exp @@ -10,9 +10,16 @@ set label_flags "additional_flags=-g" set fp [open $label_srcpath "w"] puts $fp " int +foo () +{ +init_an_int: + return 1; +} +int main () { sleep(5); + foo(); int a = 0; int b = 0; char *c; @@ -30,9 +37,9 @@ close $fp set label_stppath "[pwd]/labels.stp" set fp [open $label_stppath "w"] puts $fp " -probe process(\"labels.x\").function(\"main*@labels.c\").label(\"init_*\") {printf (\"VARS %s\\n\",\$\$vars)} -probe process(\"labels.x\").function(\"main*@labels.c\").label(\"ptr_inited\") {printf (\"VARS %s\\n\",\$\$vars)} -probe process(\"labels.x\").function(\"main*@labels.c\").label(\"init_an_int\") {printf (\"init_an_int\\n\")} +probe process(\"labels.x\").function(\"main@labels.c\").label(\"init_*\") {printf (\"VARS %s\\n\",\$\$vars)} +probe process(\"labels.x\").function(\"main@labels.c\").label(\"ptr_inited\") {printf (\"VARS %s\\n\",\$\$vars)} +probe process(\"labels.x\").function(\"main@labels.c\").label(\"init_an_int\") {printf (\"init_an_int\\n\")} " close $fp -- cgit From 30450585dd7d50224abef863ed8bae0950740fdb Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 8 Apr 2009 18:11:34 +0200 Subject: Add main executable symbol uprobe to uprobes_lib.exp test. There was nothing wrong with the probe itself, but because the body was empty the compiler optimised away the actual call... * testsuite/systemtap.base/uprobes_lib.exp: Activate main exe probe, expect more output. * testsuite/systemtap.base/uprobes_lib.stp: Also probe main and main_lib. * testsuite/systemtap.base/uprobes_exe.c: Put some code in main_func. * testsuite/systemtap.base/uprobes_lib.c: Likewise for lib_func. --- testsuite/systemtap.base/uprobes_exe.c | 8 +++++--- testsuite/systemtap.base/uprobes_lib.c | 3 ++- testsuite/systemtap.base/uprobes_lib.exp | 13 ++++++++----- testsuite/systemtap.base/uprobes_lib.stp | 10 ++++++++-- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/testsuite/systemtap.base/uprobes_exe.c b/testsuite/systemtap.base/uprobes_exe.c index 447434c6..b4811335 100644 --- a/testsuite/systemtap.base/uprobes_exe.c +++ b/testsuite/systemtap.base/uprobes_exe.c @@ -15,13 +15,15 @@ int lib_main (void); void main_func (int foo) { - ; // nothing here... + if (foo > 1) + main_func (foo - 1); + else + lib_main(); } int main (int argc, char *argv[], char *envp[]) { - main_func(1); - lib_main(); + main_func (3); return 0; } diff --git a/testsuite/systemtap.base/uprobes_lib.c b/testsuite/systemtap.base/uprobes_lib.c index c9d70625..25297b6b 100644 --- a/testsuite/systemtap.base/uprobes_lib.c +++ b/testsuite/systemtap.base/uprobes_lib.c @@ -10,7 +10,8 @@ void lib_func (int bar) { - ; // nothing here... + if (bar > 1) + lib_func (bar - 1); } void diff --git a/testsuite/systemtap.base/uprobes_lib.exp b/testsuite/systemtap.base/uprobes_lib.exp index 63ef957a..313c01b6 100644 --- a/testsuite/systemtap.base/uprobes_lib.exp +++ b/testsuite/systemtap.base/uprobes_lib.exp @@ -29,11 +29,14 @@ if { $res != "" } { pass "$test compile $testsrc" } -# XXX main_func needs another/extra test. Disabled for now. -# Enable (and in uprobes_lib.stp) after PR9940 is fixed. -# set ::result_string {main_func -# lib_func} -set ::result_string {lib_func} +set ::result_string {main +main_func +main_func +main_func +lib_main +lib_func +lib_func +lib_func} # Only run on make installcheck if {! [installtest_p]} { untested "$test"; return } diff --git a/testsuite/systemtap.base/uprobes_lib.stp b/testsuite/systemtap.base/uprobes_lib.stp index bc6cc249..459351a4 100644 --- a/testsuite/systemtap.base/uprobes_lib.stp +++ b/testsuite/systemtap.base/uprobes_lib.stp @@ -1,8 +1,14 @@ -/* - Not activated probe... Seems always skipped? +probe process("uprobes_exe").function("main") { + printf("main\n"); +} + probe process("uprobes_exe").function("main_func") { printf("main_func\n"); } -*/ + +probe process("libuprobes_lib.so").function("lib_main") { + printf("lib_main\n"); +} probe process("libuprobes_lib.so").function("lib_func") { printf("lib_func\n"); -- cgit From 9b11ea1ccc742f6a594be6a9777e618bdcbfebed Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 8 Apr 2009 19:27:42 +0200 Subject: Fix DEBUG_TASK_FINDER_VMA compilation. * runtime/sym.c (_stp_tf_mmap_cb): We get passed vm_flags, not flags. --- runtime/sym.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/sym.c b/runtime/sym.c index 7b918428..8de01bc8 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -48,7 +48,7 @@ static int _stp_tf_mmap_cb(struct stap_task_finder_target *tgt, #ifdef DEBUG_TASK_FINDER_VMA _stp_dbug(__FUNCTION__, __LINE__, "mmap_cb: tsk %d:%d path %s, addr 0x%08lx, length 0x%08lx, offset 0x%lx, flags 0x%lx\n", - tsk->pid, tsk->tgid, path, addr, length, offset, flags); + tsk->pid, tsk->tgid, path, addr, length, offset, vm_flags); #endif if (path != NULL) { for (i = 0; i < _stp_num_modules; i++) { -- cgit From 8c39e6ee099a479b3f8e25bad1272085369970a9 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 8 Apr 2009 23:35:21 +0200 Subject: Make sure code using the vma tracker compiles again. * runtime/runtime.h: Include task_finder.c. * runtime/sym.c: Always define task_finder callbacks for usage in tapsets. * runtime/task_finder.c: Define dummy stap_task_finder_target when ! defined(CONFIG_UTRACE). * tapsets.cxx: Never include task_finder.c directly. --- runtime/runtime.h | 2 ++ runtime/sym.c | 2 -- runtime/task_finder.c | 7 ++++--- tapsets.cxx | 21 --------------------- 4 files changed, 6 insertions(+), 26 deletions(-) diff --git a/runtime/runtime.h b/runtime/runtime.h index 70fe4dce..0a656b78 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -89,6 +89,8 @@ static struct #include "regs.c" #include "regs-ia64.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 8de01bc8..a2cdd0ff 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -30,7 +30,6 @@ static void _stp_sym_init(void) } } -#ifdef STP_NEED_VMA_TRACKER /* Callback that needs to be registered (in tapsets.cxx for emit_module_init) for every user task path or pid for which we might need symbols or unwind info. */ @@ -77,7 +76,6 @@ static int _stp_tf_munmap_cb(struct stap_task_finder_target *tgt, stap_remove_vma_map_info(tsk->group_leader, addr, addr + length, 0); return 0; } -#endif /* XXX: this needs to be address-space-specific. */ static unsigned long _stp_module_relocate(const char *module, const char *section, unsigned long offset) diff --git a/runtime/task_finder.c b/runtime/task_finder.c index 69b6246b..55a896ee 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -2,8 +2,9 @@ #define TASK_FINDER_C #if ! defined(CONFIG_UTRACE) -#error "Need CONFIG_UTRACE!" -#endif +/* Dummy definitions for use in sym.c */ +struct stap_task_finder_target { }; +#else #include @@ -1324,5 +1325,5 @@ stap_stop_task_finder(void) debug_task_finder_report(); } - +#endif /* defined(CONFIG_UTRACE) */ #endif /* TASK_FINDER_C */ diff --git a/tapsets.cxx b/tapsets.cxx index 32cd8494..2316a777 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -6486,13 +6486,6 @@ itrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(); s.op->newline() << "/* ---- itrace probes ---- */"; - // Note that we can potentially include task_finder.c multiple times - // in the generated code. That is OK, since task_finder.c has guard - // macros to prevent defining things multiple times. If we include - // task_finder.c unconditionally, stap can't be used on systems - // without utrace. - s.op->newline() << "#include \"task_finder.c\""; - s.op->newline() << "struct stap_itrace_probe {"; s.op->indent(1); s.op->newline() << "struct stap_task_finder_target tgt;"; @@ -7077,13 +7070,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(); s.op->newline() << "/* ---- utrace probes ---- */"; - // Note that we can potentially include task_finder.c multiple times - // in the generated code. That is OK, since task_finder.c has guard - // macros to prevent defining things multiple times. If we include - // task_finder.c unconditionally, stap can't be used on systems - // without utrace. - s.op->newline() << "#include \"task_finder.c\""; - s.op->newline() << "enum utrace_derived_probe_flags {"; s.op->indent(1); s.op->newline() << "UDPF_NONE,"; @@ -7592,13 +7578,6 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "#include \"uprobes/uprobes.h\""; s.op->newline() << "#endif"; - // Note that we can potentially include task_finder.c multiple times - // in the generated code. That is OK, since task_finder.c has guard - // macros to prevent defining things multiple times. If we include - // task_finder.c unconditionally, stap can't be used on systems - // without utrace. - 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 // or apprx. max number of processes mapping a shared library -- cgit From 86872ea4cdc4ce7b4546975125fc7be7c7a6e0ec Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 9 Apr 2009 14:22:03 +0200 Subject: Make new stap_task_finder_targets chain on correct list. * runtime/task_finder.c (stap_register_task_finder_target): Also check both pathlen are zero. --- runtime/task_finder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/task_finder.c b/runtime/task_finder.c index 55a896ee..433a042a 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -179,7 +179,7 @@ stap_register_task_finder_target(struct stap_task_finder_target *new_tgt) && strcmp(tgt->pathname, new_tgt->pathname) == 0) /* pid-based target (a specific pid or all * pids) */ - || (new_tgt->pathlen == 0 + || (new_tgt->pathlen == 0 && tgt->pathlen == 0 && tgt->pid == new_tgt->pid))) { found_node = 1; break; -- cgit From 18ac9f367a2e63335dfbdc8f5e8a97de4e40dbe4 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 9 Apr 2009 14:26:07 +0200 Subject: Add tests for probefunc(), usymname(), uaddr() versus shared libraries. * testsuite/systemtap.base/uprobes_uname.exp: New file. * testsuite/systemtap.base/uprobes_uname.stp: Likewise. --- testsuite/systemtap.base/uprobes_uname.exp | 46 ++++++++++++++++++++++++++++++ testsuite/systemtap.base/uprobes_uname.stp | 7 +++++ 2 files changed, 53 insertions(+) create mode 100644 testsuite/systemtap.base/uprobes_uname.exp create mode 100644 testsuite/systemtap.base/uprobes_uname.stp diff --git a/testsuite/systemtap.base/uprobes_uname.exp b/testsuite/systemtap.base/uprobes_uname.exp new file mode 100644 index 00000000..65e1ff70 --- /dev/null +++ b/testsuite/systemtap.base/uprobes_uname.exp @@ -0,0 +1,46 @@ +set test "uprobes_uname" +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 } +stap_run2 $srcdir/$subdir/$test.stp -c $testexe + +#exec rm -f $testexe $testso diff --git a/testsuite/systemtap.base/uprobes_uname.stp b/testsuite/systemtap.base/uprobes_uname.stp new file mode 100644 index 00000000..a44d78d3 --- /dev/null +++ b/testsuite/systemtap.base/uprobes_uname.stp @@ -0,0 +1,7 @@ +probe process("uprobes_exe").function("*") { + printf("exe: %s=%s\n",probefunc(), usymname(uaddr())); +} + +probe process("libuprobes_lib.so").function("*") { + printf("lib: %s=%s\n",probefunc(), usymname(uaddr())); +} -- cgit From 52356a26e1825acbd9146337ffdbed9b0e173f2b Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 9 Apr 2009 18:20:32 +0200 Subject: Make simple probes work even without KPROBES in the kernel. Without KPROBES very little works atm. But stack.c file is unconditionally imported, while these two functions are only used through context-unwind.stp. This at least lets us do simple sanity checks on "plain" kernels. * runtime/stack.c (_stp_stack_print, _stp_stack_snprint): Wrap in #if defined (CONFIG_KPROBES). --- runtime/stack.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/runtime/stack.c b/runtime/stack.c index f6b1cd08..68fb9b1f 100644 --- a/runtime/stack.c +++ b/runtime/stack.c @@ -97,6 +97,12 @@ static void _stp_stack_print_fallback(unsigned long stack, int verbose, int leve &print_data); } #endif + +// Without KPROBES very little works atm. +// But this file is unconditionally imported, while these two functions are only +// used through context-unwind.stp. +#if defined (CONFIG_KPROBES) + /** Prints the stack backtrace * @param regs A pointer to the struct pt_regs. */ @@ -141,6 +147,8 @@ static void _stp_stack_snprint(char *str, int size, struct pt_regs *regs, int ve pb->len = 0; } +#endif /* CONFIG_KPROBES */ + /** Prints the user stack backtrace * @param str string * @returns Same string as was input with trace info appended, -- cgit From d5cd287f7860df8752f93de93fcd1cc68884d56b Mon Sep 17 00:00:00 2001 From: David Smith Date: Thu, 9 Apr 2009 12:06:05 -0500 Subject: Uses when available. 2009-04-09 David Smith * buildrun.cxx (compile_pass): Compile autoconf test for . * runtime/autoconf-asm-syscall.c: New "autoconf" test the presence of . * runtime/syscall.h: If exists, use it. Otherwise, use our private copy of the functions for each architecture. (syscall_get_nr): Renamed from __stp_user_syscall_nr(). (syscall_get_return_value): Renamed from __stp_user_syscall_return_value(). (syscall_get_arguments): Renamed from __stp_user_syscall_arg(). * runtime/task_finder.c (__stp_utrace_task_finder_target_syscall_exit): Uses new syscall.h functions. * tapset/utrace.stp: Ditto. --- buildrun.cxx | 2 + runtime/autoconf-asm-syscall.c | 2 + runtime/syscall.h | 298 ++++++++++++++++++++++++++--------------- runtime/task_finder.c | 56 ++------ tapset/utrace.stp | 8 +- 5 files changed, 214 insertions(+), 152 deletions(-) create mode 100644 runtime/autoconf-asm-syscall.c diff --git a/buildrun.cxx b/buildrun.cxx index bcd4c1fe..82ac9d4e 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -165,6 +165,8 @@ compile_pass (systemtap_session& s) #endif output_autoconf(s, o, "autoconf-save-stack-trace.c", "STAPCONF_KERNEL_STACKTRACE", NULL); + output_autoconf(s, o, "autoconf-asm-syscall.c", + "STAPCONF_ASM_SYSCALL_H", NULL); o << module_cflags << " += -include $(STAPCONF_HEADER)" << endl; diff --git a/runtime/autoconf-asm-syscall.c b/runtime/autoconf-asm-syscall.c new file mode 100644 index 00000000..bf7a273f --- /dev/null +++ b/runtime/autoconf-asm-syscall.c @@ -0,0 +1,2 @@ +#include + diff --git a/runtime/syscall.h b/runtime/syscall.h index ae451070..6d22ba83 100644 --- a/runtime/syscall.h +++ b/runtime/syscall.h @@ -1,5 +1,6 @@ -/* syscall defines and inlines - * Copyright (C) 2008 Red Hat Inc. +/* + * syscall defines and inlines + * Copyright (C) 2008-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 @@ -89,9 +90,17 @@ #error "Unimplemented architecture" #endif +#ifdef STAPCONF_ASM_SYSCALL_H + +/* If the system has asm/syscall.h, use defines from it. */ +#include + +#else /* !STAPCONF_ASM_SYSCALL_H */ + +/* If the system doesn't have asm/syscall.h, use our defines. */ #if defined(__i386__) || defined(__x86_64__) -static inline unsigned long -__stp_user_syscall_nr(struct pt_regs *regs) +static inline long +syscall_get_nr(struct task_struct *task, struct pt_regs *regs) { #if defined(STAPCONF_X86_UNIREGS) return regs->orig_ax; @@ -104,37 +113,37 @@ __stp_user_syscall_nr(struct pt_regs *regs) #endif #if defined(__powerpc__) -static inline unsigned long -__stp_user_syscall_nr(struct pt_regs *regs) +static inline long +syscall_get_nr(struct task_struct *task, struct pt_regs *regs) { return regs->gpr[0]; } #endif #if defined(__ia64__) -static inline unsigned long -__stp_user_syscall_nr(struct pt_regs *regs) +static inline long +syscall_get_nr(struct task_struct *task, struct pt_regs *regs) { return regs->r15; } #endif #if defined(__s390__) || defined(__s390x__) -static inline unsigned long -__stp_user_syscall_nr(struct pt_regs *regs) +static inline long +syscall_get_nr(struct task_struct *task, struct pt_regs *regs) { - // might need to be 'orig_gpr2' + // might need to be 'orig_gpr2' return regs->gprs[2]; } #endif #if defined(__i386__) || defined(__x86_64__) -static inline long * -__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs) +static inline long +syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) { #ifdef CONFIG_IA32_EMULATION // This code works, but isn't what we need. Since -// __stp_user_syscall_arg() doesn't sign-extend, a value passed in as +// syscall_get_syscall_arg() doesn't sign-extend, a value passed in as // an argument and then returned won't compare correctly anymore. So, // for now, disable this code. # if 0 @@ -145,158 +154,233 @@ __stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs) # endif #endif #if defined(STAPCONF_X86_UNIREGS) - return ®s->ax; + return regs->ax; #elif defined(__x86_64__) - return ®s->rax; + return regs->rax; #elif defined (__i386__) - return ®s->eax; + return regs->eax; #endif } #endif #if defined(__powerpc__) -static inline long * -__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs) +static inline long +syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) { - return ®s->gpr[3]; + return regs->gpr[3]; } #endif #if defined(__ia64__) -static inline long * -__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs) +static inline long +syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) { - return ®s->r8; + return regs->r8; } #endif #if defined(__s390__) || defined(__s390x__) -static inline long * -__stp_user_syscall_return_value(struct task_struct *task, struct pt_regs *regs) +static inline long +syscall_get_return_value(struct task_struct *task, struct pt_regs *regs) { - return ®s->gprs[2]; + return regs->gprs[2]; } #endif #if defined(__i386__) || defined(__x86_64__) -static inline long * -__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs, - unsigned int n) +static inline void +syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, + unsigned int i, unsigned int n, unsigned long *args) { -#if defined(__i386__) - if (n > 5) { - _stp_error("syscall arg > 5"); - return NULL; + if (i + n > 6) { + _stp_error("invalid syscall arg request"); + return; } +#if defined(__i386__) #if defined(STAPCONF_X86_UNIREGS) - return ®s->bx + n; + memcpy(args, ®s->bx + i, n * sizeof(args[0])); #else - return ®s->ebx + n; + memcpy(args, ®s->ebx + i, n * sizeof(args[0])); #endif #elif defined(__x86_64__) #ifdef CONFIG_IA32_EMULATION - if (test_tsk_thread_flag(task, TIF_IA32)) - switch (n) { + if (test_tsk_thread_flag(task, TIF_IA32)) { + switch (i) { #if defined(STAPCONF_X86_UNIREGS) - case 0: return ®s->bx; - case 1: return ®s->cx; - case 2: return ®s->dx; - case 3: return ®s->si; - case 4: return ®s->di; - case 5: return ®s->bp; + case 0: + if (!n--) break; + *args++ = regs->bx; + case 1: + if (!n--) break; + *args++ = regs->cx; + case 2: + if (!n--) break; + *args++ = regs->dx; + case 3: + if (!n--) break; + *args++ = regs->si; + case 4: + if (!n--) break; + *args++ = regs->di; + case 5: + if (!n--) break; + *args++ = regs->bp; #else - case 0: return ®s->rbx; - case 1: return ®s->rcx; - case 2: return ®s->rdx; - case 3: return ®s->rsi; - case 4: return ®s->rdi; - case 5: return ®s->rbp; + case 0: + if (!n--) break; + *args++ = regs->rbx; + case 1: + if (!n--) break; + *args++ = regs->rcx; + case 2: + if (!n--) break; + *args++ = regs->rdx; + case 3: + if (!n--) break; + *args++ = regs->rsi; + case 4: + if (!n--) break; + *args++ = regs->rdi; + case 5: + if (!n--) break; + *args++ = regs->rbp; #endif - default: - _stp_error("syscall arg > 5"); - return NULL; } + return; + } #endif /* CONFIG_IA32_EMULATION */ - switch (n) { + switch (i) { #if defined(STAPCONF_X86_UNIREGS) - case 0: return ®s->di; - case 1: return ®s->si; - case 2: return ®s->dx; - case 3: return ®s->r10; - case 4: return ®s->r8; - case 5: return ®s->r9; + case 0: + if (!n--) break; + *args++ = regs->di; + case 1: + if (!n--) break; + *args++ = regs->si; + case 2: + if (!n--) break; + *args++ = regs->dx; + case 3: + if (!n--) break; + *args++ = regs->r10; + case 4: + if (!n--) break; + *args++ = regs->r8; + case 5: + if (!n--) break; + *args++ = regs->r9; #else - case 0: return ®s->rdi; - case 1: return ®s->rsi; - case 2: return ®s->rdx; - case 3: return ®s->r10; - case 4: return ®s->r8; - case 5: return ®s->r9; + case 0: + if (!n--) break; + *args++ = regs->rdi; + case 1: + if (!n--) break; + *args++ = regs->rsi; + case 2: + if (!n--) break; + *args++ = regs->rdx; + case 3: + if (!n--) break; + *args++ = regs->r10; + case 4: + if (!n--) break; + *args++ = regs->r8; + case 5: + if (!n--) break; + *args++ = regs->r9; #endif - default: - _stp_error("syscall arg > 5"); - return NULL; } #endif /* CONFIG_X86_32 */ + return; } #endif #if defined(__powerpc__) -static inline long * -__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs, - unsigned int n) +static inline void +syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, + unsigned int i, unsigned int n, unsigned long *args) { - switch (n) { - case 0: return ®s->gpr[3]; - case 1: return ®s->gpr[4]; - case 2: return ®s->gpr[5]; - case 3: return ®s->gpr[6]; - case 4: return ®s->gpr[7]; - case 5: return ®s->gpr[8]; - default: - _stp_error("syscall arg > 5"); - return NULL; + if (i + n > 6) { + _stp_error("invalid syscall arg request"); + return; } + memcpy(args, ®s->gpr[3 + i], n * sizeof(args[0])); } #endif #if defined(__ia64__) -#define __stp_user_syscall_arg(task, regs, n) \ - ____stp_user_syscall_arg(task, regs, n, &c->unwaddr) +#define syscall_get_arguments(task, regs, i, n, args) \ + __ia64_syscall_get_arguments(task, regs, i, n, args, &c->unwaddr) -static inline long * -____stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs, - unsigned int n, unsigned long **cache) +static inline void +__ia64_syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, + unsigned int i, unsigned int n, + unsigned long *args, unsigned long **cache) { - if (n > 5) { - _stp_error("syscall arg > 5"); - return NULL; + if (i + n > 6) { + _stp_error("invalid syscall arg request"); + return; + } + switch (i) { + case 0: + if (!n--) break; + *args++ = *__ia64_fetch_register(i + 32, regs, cache); + case 1: + if (!n--) break; + *args++ = *__ia64_fetch_register(i + 33, regs, cache); + case 2: + if (!n--) break; + *args++ = *__ia64_fetch_register(i + 34, regs, cache); + case 3: + if (!n--) break; + *args++ = *__ia64_fetch_register(i + 35, regs, cache); + case 4: + if (!n--) break; + *args++ = *__ia64_fetch_register(i + 36, regs, cache); + case 5: + if (!n--) break; + *args++ = *__ia64_fetch_register(i + 37, regs, cache); } - return __ia64_fetch_register(n + 32, regs, cache); } #endif #if defined(__s390__) || defined(__s390x__) -static inline long * -__stp_user_syscall_arg(struct task_struct *task, struct pt_regs *regs, - unsigned int n) +static inline void +syscall_get_arguments(struct task_struct *task, struct pt_regs *regs, + unsigned int i, unsigned int n, unsigned long *args) { - /* If we were returning a value, we could check for TIF_31BIT - * here and cast the value with '(u32)' to make sure it got - * down to 32bits. But, since we're returning an address, - * there isn't much we can do. */ - switch (n) { - case 0: return ®s->orig_gpr2; - case 1: return ®s->gprs[3]; - case 2: return ®s->gprs[4]; - case 3: return ®s->gprs[5]; - case 4: return ®s->gprs[6]; - case 5: return ®s->args[0]; - default: - _stp_error("syscall arg > 5"); - return NULL; + unsigned long mask = -1UL; + + if (i + n > 6) { + _stp_error("invalid syscall arg request"); + return; + } +#ifdef CONFIG_COMPAT + if (test_tsk_thread_flag(task, TIF_31BIT)) + mask = 0xffffffff; +#endif + switch (i) { + case 0: + if (!n--) break; + *args++ = regs->orig_gpr2 & mask; + case 1: + if (!n--) break; + *args++ = regs->gprs[3] & mask; + case 2: + if (!n--) break; + *args++ = regs->gprs[4] & mask; + case 3: + if (!n--) break; + *args++ = regs->gprs[5] & mask; + case 4: + if (!n--) break; + *args++ = regs->gprs[6] & mask; + case 5: + if (!n--) break; + *args++ = regs->args[0] & mask; } } #endif +#endif /* !STAPCONF_ASM_SYSCALL_H */ #endif /* _SYSCALL_H_ */ diff --git a/runtime/task_finder.c b/runtime/task_finder.c index 433a042a..fa6c296e 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -1065,11 +1065,9 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action, #endif { struct stap_task_finder_target *tgt = engine->data; - unsigned long syscall_no; - unsigned long *rv_addr, rv; - unsigned long *arg_addr, arg0; - unsigned long arg1 = 0; - unsigned long arg2 = 0; + long syscall_no; + unsigned long rv; + unsigned long args[3]; int rc; struct mm_struct *mm; struct vm_area_struct *vma; @@ -1088,7 +1086,7 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action, // See if syscall is one we're interested in. // // FIXME: do we need to handle mremap()? - syscall_no = __stp_user_syscall_nr(regs); + syscall_no = syscall_get_nr(tsk, regs); if (syscall_no != MMAP_SYSCALL_NO(tsk) && syscall_no != MMAP2_SYSCALL_NO(tsk) && syscall_no != MPROTECT_SYSCALL_NO(tsk) @@ -1106,21 +1104,11 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action, return UTRACE_RESUME; // Get return value - rv_addr = __stp_user_syscall_return_value(tsk, regs); - if ((rc = __stp_get_user(rv, rv_addr)) != 0) { - _stp_error("couldn't read syscall return value for pid %d: %d", - tsk->pid, rc); - return UTRACE_RESUME; - } + rv = syscall_get_return_value(tsk, regs); // We need the first syscall argument to see what address we // were operating on. - arg_addr = __stp_user_syscall_arg(tsk, regs, 0); - if ((rc = __stp_get_user(arg0, arg_addr)) != 0) { - _stp_error("couldn't read syscall arg 0 for pid %d: %d", - tsk->pid, rc); - return UTRACE_RESUME; - } + syscall_get_arguments(tsk, regs, 0, 1, args); #ifdef DEBUG_TASK_FINDER_VMA _stp_dbug(__FUNCTION__, __LINE__, @@ -1131,20 +1119,15 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action, : ((syscall_no == MPROTECT_SYSCALL_NO(tsk)) ? "mprotect" : ((syscall_no == MUNMAP_SYSCALL_NO(tsk)) ? "munmap" : "UNKNOWN")))), - arg0, rv); + args[0], rv); #endif __stp_tf_handler_start(); if (syscall_no == MUNMAP_SYSCALL_NO(tsk)) { // We need the 2nd syscall argument for the length. - arg_addr = __stp_user_syscall_arg(tsk, regs, 1); - if ((rc = __stp_get_user(arg1, arg_addr)) != 0) { - _stp_error("couldn't read syscall arg 1 for pid %d: %d", - tsk->pid, rc); - goto syscall_exit_done; - } + syscall_get_arguments(tsk, regs, 1, 1, &args[1]); // Call the callbacks - __stp_call_munmap_callbacks(tgt, tsk, arg0, arg1); + __stp_call_munmap_callbacks(tgt, tsk, args[0], args[1]); } else if (syscall_no == MMAP_SYSCALL_NO(tsk) || syscall_no == MMAP2_SYSCALL_NO(tsk)) { @@ -1165,24 +1148,13 @@ __stp_utrace_task_finder_target_syscall_exit(enum utrace_resume_action action, } } else { - // We need the 2nd syscall argument for the length. - arg_addr = __stp_user_syscall_arg(tsk, regs, 1); - if ((rc = __stp_get_user(arg1, arg_addr)) != 0) { - _stp_error("couldn't read syscall arg 1 for pid %d: %d", - tsk->pid, rc); - goto syscall_exit_done; - } - - // We need the 3nd syscall argument for the protection. - arg_addr = __stp_user_syscall_arg(tsk, regs, 2); - if ((rc = __stp_get_user(arg2, arg_addr)) != 0) { - _stp_error("couldn't read syscall arg 2 for pid %d: %d", - tsk->pid, rc); - goto syscall_exit_done; - } + // We need the 2nd syscall argument for the length and + // the 3rd argument for the protection. + syscall_get_arguments(tsk, regs, 1, 2, &args[1]); // Call the callbacks - __stp_call_mprotect_callbacks(tgt, tsk, arg0, arg1, arg2); + __stp_call_mprotect_callbacks(tgt, tsk, args[0], args[1], + args[2]); } syscall_exit_done: diff --git a/tapset/utrace.stp b/tapset/utrace.stp index 34cb32c5..00f427e6 100644 --- a/tapset/utrace.stp +++ b/tapset/utrace.stp @@ -6,13 +6,15 @@ %} function _utrace_syscall_nr:long () %{ - THIS->__retvalue = __stp_user_syscall_nr(CONTEXT->regs); /* pure */ + THIS->__retvalue = syscall_get_nr(current, CONTEXT->regs); /* pure */ %} function _utrace_syscall_arg:long (n:long) %{ - THIS->__retvalue = *__stp_user_syscall_arg(current, CONTEXT->regs, (int)THIS->n); /* pure */ + unsigned long arg = 0; /* pure */ + syscall_get_arguments(current, CONTEXT->regs, (int)THIS->n, 1, &arg); + THIS->__retvalue = arg; %} function _utrace_syscall_return:long () %{ - THIS->__retvalue = *__stp_user_syscall_return_value(current, CONTEXT->regs); /* pure */ + THIS->__retvalue = syscall_get_return_value(current, CONTEXT->regs); /* pure */ %} -- cgit From d6377d4452bb469ea97dc6747cd02cfb1df4af27 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 9 Apr 2009 23:18:46 +0200 Subject: Cleanup symbol table sanity checking. * translate.cxx (dump_unwindsyms): Get and check against module end, only check STT_FUNC && SHN_ABS for kernel, check shndxp for non-allocated section. --- translate.cxx | 45 +++++++++++++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 16 deletions(-) diff --git a/translate.cxx b/translate.cxx index 3442703d..a22e9a5b 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4486,7 +4486,7 @@ dump_unwindsyms (Dwfl_Module *m, // In the future, we'll also care about data symbols. int syments = dwfl_module_getsymtab(m); - assert(syments); + dwfl_assert ("Getting symbol table for " + modname, syments >= 0); //extract build-id from debuginfo file int build_id_len = 0; @@ -4532,6 +4532,10 @@ dump_unwindsyms (Dwfl_Module *m, } } + // Use end as sanity check when resolving symbol addresses. + Dwarf_Addr end; + dwfl_module_info (m, NULL, NULL, &end, NULL, NULL, NULL, NULL); + // Look up the relocation basis for symbols int n = dwfl_module_relocations (m); @@ -4546,10 +4550,11 @@ dump_unwindsyms (Dwfl_Module *m, Dwarf_Addr extra_offset = 0; - for (int i = 1 /* XXX: why not 0? */ ; i < syments; ++i) + for (int i = 0; i < syments; ++i) { GElf_Sym sym; - const char *name = dwfl_module_getsym(m, i, &sym, NULL); + GElf_Word shndxp; + const char *name = dwfl_module_getsym(m, i, &sym, &shndxp); if (name) { // NB: Yey, we found the kernel's _stext value. @@ -4572,17 +4577,15 @@ dump_unwindsyms (Dwfl_Module *m, clog << "Found kernel _stext extra offset 0x" << hex << extra_offset << dec << endl; } - // We only need the function symbols to identify kernel-mode - // PC's, so we omit undefined or "fake" absolute addresses. - // These fake absolute addresses occur in some older i386 - // kernels to indicate they are vDSO symbols, not real - // functions in the kernel. We also omit symbols that have - // suspicious addresses (before base). + // We are only interested in "real" symbols. + // We omit symbols that have suspicious addresses (before base, + // or after end). if ((GELF_ST_TYPE (sym.st_info) == STT_FUNC || GELF_ST_TYPE (sym.st_info) == STT_OBJECT) // PR10000: also need .data - && !(sym.st_shndx == SHN_UNDEF - || sym.st_shndx == SHN_ABS - || sym.st_value < base)) + && !(sym.st_shndx == SHN_UNDEF // Value undefined, + || shndxp == (GElf_Word) -1 // in a non-allocated section, + || sym.st_value >= end // beyond current module, + || sym.st_value < base)) // before first section. { Dwarf_Addr sym_addr = sym.st_value; const char *secname = NULL; @@ -4607,6 +4610,16 @@ dump_unwindsyms (Dwfl_Module *m, { // This is a symbol within a (possibly relocatable) // kernel image. + + // We only need the function symbols to identify kernel-mode + // PC's, so we omit undefined or "fake" absolute addresses. + // These fake absolute addresses occur in some older i386 + // kernels to indicate they are vDSO symbols, not real + // functions in the kernel. We also omit symbols that have + if (GELF_ST_TYPE (sym.st_info) == STT_FUNC + && sym.st_shndx == SHN_ABS) + continue; + secname = "_stext"; // NB: don't subtract session.sym_stext, which could be inconveniently NULL. // Instead, sym_addr will get compensated later via extra_offset. @@ -4666,10 +4679,10 @@ dump_unwindsyms (Dwfl_Module *m, // There would be only a small benefit to warning. A user // likely can't do anything about this; backtraces for the // affected module would just get all icky heuristicy. -#if 0 - c->session.print_warning ("No unwind data for " + modname - + ", " + dwfl_errmsg (-1)); -#endif + // So only report in verbose mode. + if (c->session.verbose > 2) + c->session.print_warning ("No unwind data for " + modname + + ", " + dwfl_errmsg (-1)); } for (unsigned secidx = 0; secidx < seclist.size(); secidx++) -- cgit From 412e8ec0dadbc0010c865f9a285a748b8d08c053 Mon Sep 17 00:00:00 2001 From: Wenji Huang Date: Thu, 9 Apr 2009 23:48:39 -0400 Subject: Make stmt_rel.exp have good compatibility --- testsuite/systemtap.base/stmt_rel.exp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/testsuite/systemtap.base/stmt_rel.exp b/testsuite/systemtap.base/stmt_rel.exp index ec12e484..619c91a5 100644 --- a/testsuite/systemtap.base/stmt_rel.exp +++ b/testsuite/systemtap.base/stmt_rel.exp @@ -33,7 +33,9 @@ expect { eof { } } -if { $ok == 3 } { +# bio_init drifts a bit in different kernels. +# maybe 3, 4 or 15 lines in it. +if { $ok >= 3 } { pass "$test wildcard" } else { fail "$test wildcard ($ok)" -- cgit From 6d6dbe278ad5fab5d33273b38c1ad137380a3e1e Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Fri, 10 Apr 2009 22:55:26 +0200 Subject: Fix unwind _stp_mod_sec_lookup. * runtime/unwind.c (unwind): Pass current to _stp_mod_sec_lookup(). --- runtime/unwind.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/runtime/unwind.c b/runtime/unwind.c index 9c704e28..f7b19def 100644 --- a/runtime/unwind.c +++ b/runtime/unwind.c @@ -581,7 +581,7 @@ static int unwind(struct unwind_frame_info *frame) if (UNW_PC(frame) == 0) return -EINVAL; - m = _stp_mod_sec_lookup (pc, &s); + m = _stp_mod_sec_lookup (pc, current, &s); if (unlikely(m == NULL)) { dbug_unwind(1, "No module found for pc=%lx", pc); return -EINVAL; -- cgit From a6f6008cf0034b8580f67851f742dd0ada0d683c Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sat, 11 Apr 2009 13:08:06 +0200 Subject: Prefer dwarf unwinder on i386 and x86_64. * runtime/runtime.h: Move up and enable check for STP_USE_DWARF_UNWINDER. --- runtime/runtime.h | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/runtime/runtime.h b/runtime/runtime.h index 0a656b78..f333756e 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -66,6 +66,11 @@ static struct #define MAXTRACE 20 #endif +/* dwarf unwinder only tested so far on i386 and x86_64. */ +#if (defined(__i386__) || defined(__x86_64__)) +#define STP_USE_DWARF_UNWINDER +#endif + #ifdef CONFIG_FRAME_POINTER /* Just because frame pointers are available does not mean we can trust them. */ #ifndef STP_USE_DWARF_UNWINDER @@ -73,13 +78,6 @@ static struct #endif #endif -/* dwarf unwinder only tested so far on i386 and x86_64, - but globally disabled for now */ -#if 0 -// !defined(STP_USE_FRAME_BUFFER) && (defined(__i386__) || defined(__x86_64__)) -#define STP_USE_DWARF_UNWINDER -#endif - #include "alloc.c" #include "print.c" #include "string.c" -- cgit From f38b2e7385b3395dc589af5bde137971adf84f27 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Sun, 12 Apr 2009 23:46:48 +0200 Subject: Don't redefine STP_USE_DWARF_UNWINDER. * runtime/runtime.h: STP_USE_DWARF_UNWINDER don't redefine. --- runtime/runtime.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/runtime/runtime.h b/runtime/runtime.h index f333756e..c2e927cc 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -68,8 +68,10 @@ static struct /* dwarf unwinder only tested so far on i386 and x86_64. */ #if (defined(__i386__) || defined(__x86_64__)) +#ifndef STP_USE_DWARF_UNWINDER #define STP_USE_DWARF_UNWINDER #endif +#endif #ifdef CONFIG_FRAME_POINTER /* Just because frame pointers are available does not mean we can trust them. */ -- cgit From f5f4f6b9712d3a93e42d5c2f81d21bf229d65ab6 Mon Sep 17 00:00:00 2001 From: Eugeniy Meshcheryakov Date: Mon, 13 Apr 2009 21:05:25 +0200 Subject: add a space --- dtrace | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dtrace b/dtrace index fd7b4b99..ca95b678 100755 --- a/dtrace +++ b/dtrace @@ -94,7 +94,7 @@ class provider: ######################################################################## def usage (): - print "Usage " + sys.argv[0] + "[-h | -G] -s File.d -o File {Files}" + print "Usage " + sys.argv[0] + " [-h | -G] -s File.d -o File {Files}" sys.exit(1) def open_file (arg): -- cgit From 8ca27b7dc58bf14e86cd40ae6246962fa580966d Mon Sep 17 00:00:00 2001 From: Stan Cox Date: Mon, 13 Apr 2009 17:51:58 -0400 Subject: Improve -l output for .label * tapsets.cxx (iterate_over_cu_labels): Treat -l specially so the output of a .label can be improved. * labels.stp: Test -l --- tapsets.cxx | 21 +++++++++++++++------ testsuite/systemtap.base/labels.exp | 15 +++++++++++++++ 2 files changed, 30 insertions(+), 6 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index 2316a777..774821c7 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -1339,8 +1339,12 @@ struct dwflpp } void - iterate_over_cu_labels (string label_val, string function, Dwarf_Die *cu, - void *data, + iterate_over_cu_labels (string label_val, + string function, + Dwarf_Die *cu, + vector & results, + probe_point *base_loc, + void *data, void (* callback)(const string &, const char *, int, @@ -1375,7 +1379,7 @@ struct dwflpp function_name = name; default: if (dwarf_haschildren (&die)) - iterate_over_cu_labels (label_val, function, &die, q, callback); + iterate_over_cu_labels (label_val, function, &die, results, base_loc, q, callback); continue; } @@ -1420,8 +1424,13 @@ struct dwflpp int nscopes = 0; nscopes = dwarf_getscopes_die (&die, &scopes); if (nscopes > 1) - callback(function_name.c_str(), file, - (int)dline, &scopes[1], stmt_addr, q); + { + callback(function_name.c_str(), file, + (int)dline, &scopes[1], stmt_addr, q); + if (sess.listing_mode) + results.back()->locations[0]->components.push_back + (new probe_point::component(TOK_LABEL, new literal_string (name))); + } } } while (dwarf_siblingof (&die, &die) == 0); @@ -4121,7 +4130,7 @@ query_cu (Dwarf_Die * cudie, void * arg) { // If we have a pattern string with target *label*, we // have to look at labels in all the matched srcfiles. - q->dw.iterate_over_cu_labels (q->label_val, q->function, q->dw.cu, q, query_statement); + q->dw.iterate_over_cu_labels (q->label_val, q->function, q->dw.cu, q->results, q->base_loc, q, query_statement); } else { diff --git a/testsuite/systemtap.base/labels.exp b/testsuite/systemtap.base/labels.exp index 268bb320..88ed4619 100644 --- a/testsuite/systemtap.base/labels.exp +++ b/testsuite/systemtap.base/labels.exp @@ -55,8 +55,23 @@ if { $res != "" } { pass "compiling labels.c -g" } +# list of labels + +spawn stap -l "process(\"$label_exepath\").function(\"*\").label(\"*\")" + +wait +expect { + -timeout 180 + -re {process.*function.*labels.c:5...label..init_an_int.*process.*function.*labels.c:16...label..init_an_int.*process.*function.*labels.c:18...label..init_an_int_again} { incr ok; exp_continue } + timeout { fail "$test (timeout)" } + eof { } +} + +if {$ok == 1} { pass "$test -l .label" } { fail "$test -l .label $ok" } + # label in an executable +set ok 0 verbose -log "spawn stap -c $label_exepath $label_stppath" spawn stap -c $label_exepath $label_stppath -- cgit From 675e4d2a0635f822e8258c3f219c6dda685c67cf Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 13 Apr 2009 14:46:54 -0700 Subject: PR10049: Restore better errors for $return In commit c4ce66a1 I shifted some of the variable accesses around, and that caused the error messages for $return variables to lose context. The root problem in this case was that dwarf_attr didn't find the type attribute, and that failure wasn't immediately caught. Now that result is checked so we can provide a proper error message. While I'm at it, changing that lookup to dwarf_attr_integrate is enough to make the $return value usable again, at least for the reported test case. --- tapsets.cxx | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index 774821c7..094ae358 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -2434,13 +2434,12 @@ struct dwflpp /* Translate the ->bar->baz[NN] parts. */ - Dwarf_Die die_mem, *die = NULL; - die = dwarf_formref_die (&attr_mem, &die_mem); + Dwarf_Die die_mem, *die = dwarf_formref_die (&attr_mem, &die_mem); die = translate_components (&pool, &tail, pc, e, die, &die_mem, &attr_mem); if(!die) { - die = dwarf_formref_die (&attr_mem, &vardie); + die = dwarf_formref_die (&attr_mem, &die_mem); stringstream alternatives; if (die != NULL) print_members(die,alternatives); @@ -2516,17 +2515,19 @@ struct dwflpp /* Translate the ->bar->baz[NN] parts. */ Dwarf_Attribute attr_mem; - Dwarf_Attribute *attr = dwarf_attr (scope_die, DW_AT_type, &attr_mem); - - Dwarf_Die vardie_mem; - Dwarf_Die *vardie = dwarf_formref_die (attr, &vardie_mem); + if (dwarf_attr_integrate (scope_die, DW_AT_type, &attr_mem) == NULL) + throw semantic_error("failed to retrieve return value type attribute for " + + string(dwarf_diename(scope_die) ?: "") + + "(" + string(dwarf_diename(cu) ?: "") + + ")", + e->tok); - Dwarf_Die die_mem, *die = NULL; + Dwarf_Die die_mem, *die = dwarf_formref_die (&attr_mem, &die_mem); die = translate_components (&pool, &tail, pc, e, - vardie, &die_mem, &attr_mem); + die, &die_mem, &attr_mem); if(!die) { - die = dwarf_formref_die (&attr_mem, vardie); + die = dwarf_formref_die (&attr_mem, &die_mem); stringstream alternatives; if (die != NULL) print_members(die,alternatives); -- cgit From b9c2e81cc7a62336ec1daf374cb3411add772ab4 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 13 Apr 2009 19:50:23 -0700 Subject: PR10067: fix bitfield access * tapsets.cxx (dwflpp::translate_components): Eliminate the extra die-dereference at the end of the loop (a regression from @casts). * runtime/loc2c-runtime.h (store_bitfield): Use the target as the representative type, since the base is always int64_t. Also be a bit more aggressive with masking and parentheses. * testsuite/systemtap.base/bitfield.*: New test for R/W bitfields. --- runtime/loc2c-runtime.h | 11 +++++---- tapsets.cxx | 7 ++++-- testsuite/systemtap.base/bitfield.exp | 3 +++ testsuite/systemtap.base/bitfield.stp | 46 +++++++++++++++++++++++++++++++++++ 4 files changed, 60 insertions(+), 7 deletions(-) create mode 100644 testsuite/systemtap.base/bitfield.exp create mode 100644 testsuite/systemtap.base/bitfield.stp diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h index eaf47cad..620e1615 100644 --- a/runtime/loc2c-runtime.h +++ b/runtime/loc2c-runtime.h @@ -29,11 +29,12 @@ & (((__typeof (base)) 1 << (nbits)) - 1)) #define store_bitfield(target, base, higherbits, nbits) \ - target = (target \ - &~ ((((__typeof (base)) 1 << (nbits)) - 1) \ - << (sizeof (base) * 8 - (higherbits) - (nbits))) \ - | ((__typeof (base)) (base) \ - << (sizeof (base) * 8 - (higherbits) - (nbits)))) + target = ((target \ + &~ ((((__typeof (target)) 1 << (nbits)) - 1) \ + << (sizeof (target) * 8 - (higherbits) - (nbits)))) \ + | ((((__typeof (target)) (base)) \ + & (((__typeof (target)) 1 << (nbits)) - 1)) \ + << (sizeof (target) * 8 - (higherbits) - (nbits)))) /* Given a DWARF register number, fetch its intptr_t (long) value from the diff --git a/tapsets.cxx b/tapsets.cxx index 094ae358..c63151e1 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -2006,7 +2006,7 @@ struct dwflpp Dwarf_Die *die_mem, Dwarf_Attribute *attr_mem) { - Dwarf_Die *die = die_mem; + Dwarf_Die *die = NULL; Dwarf_Die struct_die; Dwarf_Attribute temp_attr; @@ -2015,6 +2015,9 @@ struct dwflpp if (vardie) *die_mem = *vardie; + if (e->components.empty()) + return die_mem; + static unsigned int func_call_level ; static unsigned int dwarf_error_flag ; // indicates current error is dwarf error static unsigned int dwarf_error_count ; // keeps track of no of dwarf errors @@ -2031,6 +2034,7 @@ struct dwflpp obstack_printf (pool, "c->last_stmt = %s;", lex_cast_qstring(piece).c_str()); #endif + die = die ? dwarf_formref_die (attr_mem, die_mem) : die_mem; const int typetag = dwarf_tag (die); switch (typetag) { @@ -2188,7 +2192,6 @@ struct dwflpp /* Now iterate on the type in DIE's attribute. */ if (dwarf_attr_integrate (die, DW_AT_type, attr_mem) == NULL) throw semantic_error ("cannot get type of field: " + string(dwarf_errmsg (-1)), e->tok); - die = dwarf_formref_die (attr_mem, die_mem); } return die; } diff --git a/testsuite/systemtap.base/bitfield.exp b/testsuite/systemtap.base/bitfield.exp new file mode 100644 index 00000000..16451369 --- /dev/null +++ b/testsuite/systemtap.base/bitfield.exp @@ -0,0 +1,3 @@ +# test that bitfield r/w works correctly +set test "bitfield" +stap_run $srcdir/$subdir/$test.stp no_load $all_pass_string -g diff --git a/testsuite/systemtap.base/bitfield.stp b/testsuite/systemtap.base/bitfield.stp new file mode 100644 index 00000000..c2ff4929 --- /dev/null +++ b/testsuite/systemtap.base/bitfield.stp @@ -0,0 +1,46 @@ +%{ +#include +static struct tcphdr foo = {0}; +%} + +function get_ptr:long() %{ THIS->__retvalue = (long)&foo; /* pure */ %} +function get_ack:long() %{ THIS->__retvalue = foo.ack; /* pure */ %} +function get_urg:long() %{ THIS->__retvalue = foo.urg; /* pure */ %} + +function check:long(ack:long, urg:long) { + ptr = get_ptr() + + /* set the bits with cast */ + @cast(ptr, "tcphdr")->ack = ack + @cast(ptr, "tcphdr")->urg = urg + + /* check that reading with embedded-C is ok */ + real_ack = get_ack() + real_urg = get_urg() + errors = (ack != real_ack) + (urg != real_urg) + + /* check that reading with a cast is ok */ + cast_ack = @cast(ptr, "tcphdr")->ack + cast_urg = @cast(ptr, "tcphdr")->urg + errors += (ack != cast_ack) + (urg != cast_urg) + + if (errors) + printf("bitfield had %d errors; expect(%d%d), real(%d%d), cast(%d%d)\n", + errors, ack, urg, real_ack, real_urg, cast_ack, cast_urg) + + return errors +} + +probe begin { + println("systemtap starting probe") + + errors = check(0, 0) + errors += check(0, 1) + errors += check(1, 0) + errors += check(1, 1) + + println("systemtap ending probe") + if (errors == 0) + println("systemtap test success") + exit() +} -- cgit From 7175b49227fb1f71f3bdd6060ef9f6499e42f035 Mon Sep 17 00:00:00 2001 From: "Frank Ch. Eigler" Date: Tue, 14 Apr 2009 13:13:43 -0400 Subject: PR10070: don't warn about side-effect-free probes in -t (timing) mode * elaborate.cxx (semantic_pass_opt4): Filter warning on s.timing. --- elaborate.cxx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/elaborate.cxx b/elaborate.cxx index 323261c7..b760173f 100644 --- a/elaborate.cxx +++ b/elaborate.cxx @@ -2433,7 +2433,8 @@ void semantic_pass_opt4 (systemtap_session& s, bool& relaxed_p) p->body = duv.require(p->body, true); if (p->body == 0) { - if (! s.suppress_warnings) + if (! s.suppress_warnings + && ! s.timing) // PR10070 s.print_warning ("side-effect-free probe '" + p->name + "'", p->tok); p->body = new null_statement(); -- cgit From 60ad8ebae62f472a9f089f51053a2d0d66c67a95 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 14 Apr 2009 19:30:56 +0200 Subject: Keep track of relocation section sizes. * runtime/sym.h (_stp_section): Add size field. * translate.cxx (dump_unwindsyms): Get start of module address space, turn seclist into vector of secname, size pairs, track relocation section size, or add module address range if no sections, output size in _stp_section list. --- runtime/sym.h | 1 + translate.cxx | 58 +++++++++++++++++++++++++++++++++++++++++++--------------- 2 files changed, 44 insertions(+), 15 deletions(-) diff --git a/runtime/sym.h b/runtime/sym.h index 586b10ca..80c334fb 100644 --- a/runtime/sym.h +++ b/runtime/sym.h @@ -18,6 +18,7 @@ struct _stp_symbol { struct _stp_section { const char *name; unsigned long addr; /* XXX: belongs in per-address-space tables */ + unsigned long size; /* length of the address space module covers. */ struct _stp_symbol *symbols; /* ordered by address */ unsigned num_symbols; }; diff --git a/translate.cxx b/translate.cxx index a22e9a5b..d81287ee 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4532,9 +4532,14 @@ dump_unwindsyms (Dwfl_Module *m, } } - // Use end as sanity check when resolving symbol addresses. - Dwarf_Addr end; - dwfl_module_info (m, NULL, NULL, &end, NULL, NULL, NULL, NULL); + // Get the canonical path of the main file for comparison at runtime. + // When given directly by the user through -d or in case of the kernel + // name and path might differ. path should be used for matching. + // Use end as sanity check when resolving symbol addresses and to + // calculate size for .dynamic and .absolute sections. + const char *mainfile; + Dwarf_Addr start, end; + dwfl_module_info (m, NULL, &start, &end, NULL, NULL, &mainfile, NULL); // Look up the relocation basis for symbols int n = dwfl_module_relocations (m); @@ -4545,7 +4550,8 @@ dump_unwindsyms (Dwfl_Module *m, // XXX: unfortunate duplication with tapsets.cxx:emit_address() typedef map addrmap_t; // NB: plain map, sorted by address - vector seclist; // encountered relocation bases (section names) + vector > seclist; // encountered relocation bases + // (section names and sizes) map addrmap; // per-relocation-base sorted addrmap Dwarf_Addr extra_offset = 0; @@ -4588,11 +4594,11 @@ dump_unwindsyms (Dwfl_Module *m, || sym.st_value < base)) // before first section. { Dwarf_Addr sym_addr = sym.st_value; + Dwarf_Addr save_addr = sym_addr; const char *secname = NULL; if (n > 0) // only try to relocate if there exist relocation bases { - Dwarf_Addr save_addr = sym_addr; int ki = dwfl_module_relocate_address (m, &sym_addr); dwfl_assert ("dwfl_module_relocate_address", ki >= 0); secname = dwfl_module_relocation_info (m, ki, NULL); @@ -4645,10 +4651,31 @@ dump_unwindsyms (Dwfl_Module *m, // Compute our section number unsigned secidx; for (secidx=0; secidxsh_size; + } + seclist.push_back (make_pair(secname,size)); + } (addrmap[secidx])[sym_addr] = name; } @@ -4709,12 +4736,17 @@ dump_unwindsyms (Dwfl_Module *m, } c->output << "static struct _stp_section _stp_module_" << stpmod_idx<< "_sections[] = {\n"; + // For the kernel, executables (ET_EXEC) or shared libraries (ET_DYN) + // there is just one section that covers the whole address space of + // the module. For kernel modules (ET_REL) there can be multiple + // sections that get relocated separately. for (unsigned secidx = 0; secidx < seclist.size(); secidx++) { c->output << "{\n" - << ".name = " << lex_cast_qstring(seclist[secidx]) << ",\n" + << ".name = " << lex_cast_qstring(seclist[secidx].first) << ",\n" + << ".size = 0x" << hex << seclist[secidx].second << dec << ",\n" << ".symbols = _stp_module_" << stpmod_idx << "_symbols_" << secidx << ",\n" - << ".num_symbols = sizeof(_stp_module_" << stpmod_idx << "_symbols_" << secidx << ")/sizeof(struct _stp_symbol)\n" + << ".num_symbols = " << addrmap[secidx].size() << "\n" << "},\n"; } c->output << "};\n"; @@ -4722,11 +4754,6 @@ dump_unwindsyms (Dwfl_Module *m, c->output << "static struct _stp_module _stp_module_" << stpmod_idx << " = {\n"; c->output << ".name = " << lex_cast_qstring (modname) << ", \n"; - // Get the canonical path of the main file for comparison at runtime. - // When given directly by the user through -d or in case of the kernel - // name and path might differ. path should be used for matching. - const char *mainfile; - dwfl_module_info (m, NULL, NULL, NULL, NULL, NULL, &mainfile, NULL); mainfile = canonicalize_file_name(mainfile); c->output << ".path = " << lex_cast_qstring (mainfile) << ",\n"; @@ -4861,7 +4888,8 @@ emit_symbol_data (systemtap_session& s) { NULL, /* dwfl_linux_kernel_find_elf, */ dwfl_standard_find_debuginfo, - dwfl_offline_section_address, + NULL, /* ET_REL not supported for user space, only ET_EXEC and ET_DYN. + dwfl_offline_section_address, */ (char **) & debuginfo_path }; -- cgit From 5e868ddd8263d2f7b61a702891252cc2bacb1c07 Mon Sep 17 00:00:00 2001 From: Andre Detsch Date: Tue, 14 Apr 2009 14:23:59 -0300 Subject: Add new TCP and IP functions This patch adds some basic functions to the IP and TCP tapsets. Mainly, it's possible to get the iphdr and tcphdr from a sk_buff structure. As a consequence, a TCP probe called tcp.receive() was created and is probed every time a TCP packet is received, and a lot of useful fields is available, as the TCP flags. Also a small example that works like tcpdump for received TCP packets was created. This patch was tested on x86 and ppc machines, on 2.6.18 kernel and also on mainline one. Signed-off-by: Breno Leitao Signed-off-by: Andre Detsch Signed-off-by: Josh Stone --- tapset/ip.stp | 46 +++++++++++ tapset/tcp.stp | 94 ++++++++++++++++++++++ .../systemtap.examples/network/tcpdumplike.stp | 12 +++ 3 files changed, 152 insertions(+) create mode 100644 testsuite/systemtap.examples/network/tcpdumplike.stp diff --git a/tapset/ip.stp b/tapset/ip.stp index 1e2e263c..299d88d2 100644 --- a/tapset/ip.stp +++ b/tapset/ip.stp @@ -7,6 +7,10 @@ // // Based on previous work done by Arnaldo Carvalho de Melo +%{ +#include +%} + /** * sfunction ip_ntop - returns a string representation from an integer IP number * @addr: the ip represented as an integer @@ -30,3 +34,45 @@ function __ip_sock_daddr:long (sock:long) { return @cast(sock, "inet_sock")->daddr } + +/* Get the IP header for recent (> 2.6.21) kernels */ +function __get_skb_iphdr_new:long(skb:long) +%{ /* pure */ + struct sk_buff *skb; + skb = (struct sk_buff *)(long)THIS->skb; + /* as done by skb_network_header() */ + #ifdef NET_SKBUFF_DATA_USES_OFFSET + THIS->__retvalue = (long)(kread(&(skb->head)) + kread(&(skb->network_header))); + #else + THIS->__retvalue = (long)kread(&(skb->network_header)); + #endif + CATCH_DEREF_FAULT(); +%} + +/* Get the IP header from a sk_buff struct */ +function __get_skb_iphdr:long(skb:long){ +%( kernel_v < "2.6.21" %? + iphdr = @cast(skb, "sk_buff")->nh->raw + return iphdr +%: + return __get_skb_iphdr_new(skb) +%) +} + +/* return the source next layer protocol for a given sk_buff structure */ +function __ip_skb_proto:long (iphdr) +{ + return @cast(iphdr, "iphdr")->protocol +} + +/* return the source IP address for a given sk_buff structure */ +function __ip_skb_saddr:long (iphdr) +{ + return @cast(iphdr, "iphdr")->saddr +} + +/* return the destination IP address for a given skb */ +function __ip_skb_daddr:long (iphdr) +{ + return @cast(iphdr, "iphdr")->daddr +} diff --git a/tapset/tcp.stp b/tapset/tcp.stp index bb96b0cb..2c5dce7e 100644 --- a/tapset/tcp.stp +++ b/tapset/tcp.stp @@ -15,6 +15,7 @@ #include #include #include +#include %} // Get retransmission timeout in usecs. RTO is initialized from default @@ -78,6 +79,70 @@ function __tcp_sock_dport:long (sock:long){ return @cast(sock, "inet_sock")->dport } +/* returns the TCP header for recent (<2.6.21) kernel */ +function __get_skb_tcphdr_new:long(skb:long) +%{ /* pure */ + struct sk_buff *skb; + skb = (struct sk_buff *)(long)THIS->skb; + /* as done by skb_transport_header() */ + #ifdef NET_SKBUFF_DATA_USES_OFFSET + THIS->__retvalue = (long)(kread(&(skb->head)) + kread(&(skb->transport_header))); + #else + THIS->__retvalue = (long)kread(&(skb->transport_header)); + #endif + CATCH_DEREF_FAULT(); +%} + +/* returns the TCP header for a given sk_buff structure */ +function __get_skb_tcphdr:long(skb:long){ +%( kernel_v < "2.6.21" %? + tcphdr = @cast(skb, "sk_buff")->h->raw + return tcphdr +%: + return __get_skb_tcphdr_new(skb) +%) +} + +/* returns TCP URG flag for a given sk_buff structure */ +function __tcp_skb_urg:long (tcphdr){ + return @cast(tcphdr, "tcphdr")->urg +} + +/* returns TCP ACK flag for a given sk_buff structure */ +function __tcp_skb_ack:long (tcphdr){ + return @cast(tcphdr, "tcphdr")->ack +} + +/* returns TCP PSH flag for a given sk_buff structure */ +function __tcp_skb_psh:long (tcphdr){ + return @cast(tcphdr, "tcphdr")->psh +} + +/* returns TCP RST flag for a given sk_buff structure */ +function __tcp_skb_rst:long (tcphdr){ + return @cast(tcphdr, "tcphdr")->rst +} + +/* returns TCP SYN flag for a given sk_buff structure */ +function __tcp_skb_syn:long (tcphdr){ + return @cast(tcphdr, "tcphdr")->syn +} + +/* returns TCP FIN flag for a given sk_buff structure */ +function __tcp_skb_fin:long (tcphdr){ + return @cast(tcphdr, "tcphdr")->fin +} + +/* returns TCP source port for a given sk_buff structure */ +function __tcp_skb_sport:long (tcphdr){ + return ntohs(@cast(tcphdr, "tcphdr")->source) +} + +/* returns TCP destination port for a given sk_buff structure */ +function __tcp_skb_dport:long (tcphdr){ + return @cast(tcphdr, "tcphdr")->dest +} + /* return the TCP source port for a given sock */ function __tcp_sock_sport:long (sock:long){ return @cast(sock, "inet_sock")->sport @@ -300,3 +365,32 @@ probe tcp.setsockopt.return = kernel.function("tcp_setsockopt").return { ret = $return } +/** + * probe tcp.receive - Called when a TCP packet is received + * @saddr: A string representing the source IP address + * @daddr: A string representing the destination IP address + * @sport: TCP source port + * @dport: TCP destination port + * @urg: TCP URG flag + * @ack: TCP ACK flag + * @psh: TCP PSH flag + * @rst: TCP RST flag + * @syn: TCP SYN flag + * @fin: TCP FIN flag + */ +probe tcp.receive = kernel.function("tcp_v4_rcv") { + iphdr = __get_skb_iphdr($skb) + saddr = ip_ntop(__ip_skb_saddr(iphdr)) + daddr = ip_ntop(__ip_skb_daddr(iphdr)) + protocol = __ip_skb_proto(iphdr) + + tcphdr = __get_skb_tcphdr($skb) + dport = __tcp_skb_dport(tcphdr) + sport = __tcp_skb_sport(tcphdr) + urg = __tcp_skb_urg(tcphdr) + ack = __tcp_skb_ack(tcphdr) + psh = __tcp_skb_psh(tcphdr) + rst = __tcp_skb_rst(tcphdr) + syn = __tcp_skb_syn(tcphdr) + fin = __tcp_skb_fin(tcphdr) +} diff --git a/testsuite/systemtap.examples/network/tcpdumplike.stp b/testsuite/systemtap.examples/network/tcpdumplike.stp new file mode 100644 index 00000000..4026e7a7 --- /dev/null +++ b/testsuite/systemtap.examples/network/tcpdumplike.stp @@ -0,0 +1,12 @@ +// A TCP dump like example + +probe begin, timer.s(1) { + printf("-----------------------------------------------------------------\n"); + printf(" Source IP Dest IP SPort DPort U A P R S F \n"); + printf("-----------------------------------------------------------------\n"); +} + +probe tcp.receive { + printf(" %15s %15s %5d %5d %d %d %d %d %d %d\n", + saddr, daddr, sport, dport, urg, ack, psh, rst, syn, fin) +} -- cgit From 03e6d58fa0f0e7f9dae71c6aefe0d0ef01153214 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 14 Apr 2009 10:53:44 -0700 Subject: Add Andre Detsch to AUTHORS --- AUTHORS | 1 + 1 file changed, 1 insertion(+) diff --git a/AUTHORS b/AUTHORS index 0ed3ed04..a6e54c7b 100644 --- a/AUTHORS +++ b/AUTHORS @@ -1,4 +1,5 @@ Ananth N Mavinakayanahalli +Andre Detsch Anil Keshavamurthy Anithra Janakiraman Breno Leitao -- cgit From 4787e8398f4d0376f31cffc0771b71f5bbdd9d52 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 14 Apr 2009 19:54:38 +0200 Subject: Only set sec in _stp_mod_sec_lookup when not NULL. * runtime/sym.c (_stp_mod_sec_lookup): Only set sec when not NULL. --- runtime/sym.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/runtime/sym.c b/runtime/sym.c index a2cdd0ff..fc9b2e80 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -150,7 +150,8 @@ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr, if (user != NULL) { m = (struct _stp_module *)user; - *sec = &m->sections[0]; // XXX check actual section and relocate + if (sec) + *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, vm_start); if (strcmp(".dynamic", m->sections[0].name) == 0) -- cgit From b9c1e0228f6c629e278820caf40870cdad285441 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 14 Apr 2009 11:00:05 -0700 Subject: Make tcpdumplike.stp executable --- testsuite/systemtap.examples/network/tcpdumplike.stp | 2 ++ 1 file changed, 2 insertions(+) mode change 100644 => 100755 testsuite/systemtap.examples/network/tcpdumplike.stp diff --git a/testsuite/systemtap.examples/network/tcpdumplike.stp b/testsuite/systemtap.examples/network/tcpdumplike.stp old mode 100644 new mode 100755 index 4026e7a7..533c71b9 --- a/testsuite/systemtap.examples/network/tcpdumplike.stp +++ b/testsuite/systemtap.examples/network/tcpdumplike.stp @@ -1,3 +1,5 @@ +#! /usr/bin/env stap + // A TCP dump like example probe begin, timer.s(1) { -- cgit From 891e4fb2d5bf81b540b66b126b2ba78d1b7f459b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 14 Apr 2009 11:49:15 -0700 Subject: Adjust NEWS indentation --- NEWS | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/NEWS b/NEWS index 96e14b70..02f00367 100644 --- a/NEWS +++ b/NEWS @@ -7,20 +7,20 @@ * What's new in version 0.9.5 - - New probes process().insn and process().insn.block that allows - inspection of the process after each instruction or block of - instructions executed. So to count the total number of instructions - a process executes during a run do something like: - $ stap -e 'global steps; probe process("/bin/ls").insn {steps++} - probe end {printf("Total instructions: %d\n", steps);}' \ - -c /bin/ls - This feature can slow down execution of a process somewhat. - - - Systemtap probes and function man pages extracted from the tapsets - are now available under 3stap. To show the page for probe vm.pagefault - or the stap function pexecname do: - $ man 3stap vm.pagefault - $ man 3stap pexecname +- New probes process().insn and process().insn.block that allows + inspection of the process after each instruction or block of + instructions executed. So to count the total number of instructions + a process executes during a run do something like: + $ stap -e 'global steps; probe process("/bin/ls").insn {steps++} + probe end {printf("Total instructions: %d\n", steps);}' \ + -c /bin/ls + This feature can slow down execution of a process somewhat. + +- Systemtap probes and function man pages extracted from the tapsets + are now available under 3stap. To show the page for probe vm.pagefault + or the stap function pexecname do: + $ man 3stap vm.pagefault + $ man 3stap pexecname - Kernel tracepoints are now supported for probing predefined kernel events without any debuginfo. Tracepoints incur less overhead than -- cgit From c1af604e1c626b90834113ba7d71c4a2ea1bda68 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 14 Apr 2009 20:58:26 +0200 Subject: Make sure addr falls inside section in _stp_mod_sec_lookup. * runtime/sym.c (_stp_mod_sec_lookup): Use section size to match addr. Only return exact matches, not just closes offset. --- runtime/sym.c | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/runtime/sym.c b/runtime/sym.c index fc9b2e80..f6f97ac2 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -136,9 +136,7 @@ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr, struct _stp_section **sec) { void *user = NULL; - struct _stp_module *m = NULL; unsigned midx = 0; - unsigned long closest_section_offset = ~0; // Try vma matching first if task given. if (task) @@ -149,7 +147,7 @@ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr, NULL, &user) == 0) if (user != NULL) { - m = (struct _stp_module *)user; + struct _stp_module *m = (struct _stp_module *)user; if (sec) *sec = &m->sections[0]; // XXX check actual section and relocate dbug_sym(1, "found section %s in module %s at 0x%lx\n", @@ -165,21 +163,19 @@ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr, unsigned secidx; for (secidx = 0; secidx < _stp_modules[midx]->num_sections; secidx++) { - unsigned long this_section_addr; - unsigned long this_section_offset; - this_section_addr = _stp_modules[midx]->sections[secidx].addr; - if (addr < this_section_addr) continue; - this_section_offset = addr - this_section_addr; - if (this_section_offset < closest_section_offset) - { - closest_section_offset = this_section_offset; - m = _stp_modules[midx]; + unsigned long sec_addr; + unsigned long sec_size; + sec_addr = _stp_modules[midx]->sections[secidx].addr; + sec_size = _stp_modules[midx]->sections[secidx].size; + if (addr >= sec_addr && addr < sec_addr + sec_size) + { if (sec) - *sec = & m->sections[secidx]; + *sec = & _stp_modules[midx]->sections[secidx]; + return _stp_modules[midx]; } } } - return m; + return NULL; } -- cgit From 1f65cc4ffd1bd362b10d7f07d1cb9c4e7de68027 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 14 Apr 2009 12:34:12 -0700 Subject: PR9953: split up the two process.* tapsets 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 their kernel perspective on processes. --- Makefile.am | 2 +- Makefile.in | 8 +- NEWS | 5 + configure | 4 +- configure.ac | 2 +- doc/SystemTap_Beginners_Guide/en-US/References.xml | 2 +- doc/SystemTap_Tapset_Reference/tapsets.tmpl | 6 +- .../en-US/Tapset_Dev_Guide.xml | 4 +- man/stapprobes.kprocess.3stap.in | 106 +++++++++++++++++++ man/stapprobes.process.3stap.in | 106 ------------------- tapset/DEVGUIDE | 6 +- tapset/kprocess.stp | 115 +++++++++++++++++++++ tapset/process.stp | 115 --------------------- testsuite/buildok/process-all-probes.stp | 12 +-- testsuite/buildok/process_test.stp | 12 +-- .../systemtap.examples/process/proc_snoop.stp | 12 +-- testsuite/systemtap.stress/whitelist.exp | 1 + 17 files changed, 262 insertions(+), 256 deletions(-) create mode 100644 man/stapprobes.kprocess.3stap.in delete mode 100644 man/stapprobes.process.3stap.in create mode 100644 tapset/kprocess.stp delete mode 100644 tapset/process.stp diff --git a/Makefile.am b/Makefile.am index b4d97e9a..f5fedae1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -17,7 +17,7 @@ stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap \ staprun.8 \ man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap \ man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap \ -man/stapprobes.pagefault.3stap man/stapprobes.process.3stap \ +man/stapprobes.pagefault.3stap man/stapprobes.kprocess.3stap \ man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap \ man/stapprobes.signal.3stap man/stapprobes.socket.3stap \ man/stapprobes.tcp.3stap man/stapprobes.udp.3stap diff --git a/Makefile.in b/Makefile.in index 42bdec7c..a953be51 100644 --- a/Makefile.in +++ b/Makefile.in @@ -64,7 +64,7 @@ DIST_COMMON = INSTALL NEWS README AUTHORS $(srcdir)/Makefile.in \ $(top_srcdir)/man/stapprobes.nfs.3stap.in \ $(top_srcdir)/man/stapprobes.nfsd.3stap.in \ $(top_srcdir)/man/stapprobes.pagefault.3stap.in \ - $(top_srcdir)/man/stapprobes.process.3stap.in \ + $(top_srcdir)/man/stapprobes.kprocess.3stap.in \ $(top_srcdir)/man/stapprobes.rpc.3stap.in \ $(top_srcdir)/man/stapprobes.scsi.3stap.in \ $(top_srcdir)/man/stapprobes.signal.3stap.in \ @@ -85,7 +85,7 @@ CONFIG_CLEAN_FILES = stap.1 stapprobes.3stap stapfuncs.3stap \ stapvars.3stap stapex.3stap staprun.8 stap-server.8 \ man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap \ man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap \ - man/stapprobes.pagefault.3stap man/stapprobes.process.3stap \ + man/stapprobes.pagefault.3stap man/stapprobes.kprocess.3stap \ man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap \ man/stapprobes.signal.3stap man/stapprobes.socket.3stap \ man/stapprobes.tcp.3stap man/stapprobes.udp.3stap \ @@ -303,7 +303,7 @@ man_MANS = stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap \ stapex.3stap staprun.8 man/stapprobes.iosched.3stap \ man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap \ man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap \ - man/stapprobes.process.3stap man/stapprobes.rpc.3stap \ + man/stapprobes.kprocess.3stap man/stapprobes.rpc.3stap \ man/stapprobes.scsi.3stap man/stapprobes.signal.3stap \ man/stapprobes.socket.3stap man/stapprobes.tcp.3stap \ man/stapprobes.udp.3stap $(am__append_1) @@ -457,7 +457,7 @@ man/stapprobes.nfsd.3stap: $(top_builddir)/config.status $(top_srcdir)/man/stapp cd $(top_builddir) && $(SHELL) ./config.status $@ man/stapprobes.pagefault.3stap: $(top_builddir)/config.status $(top_srcdir)/man/stapprobes.pagefault.3stap.in cd $(top_builddir) && $(SHELL) ./config.status $@ -man/stapprobes.process.3stap: $(top_builddir)/config.status $(top_srcdir)/man/stapprobes.process.3stap.in +man/stapprobes.kprocess.3stap: $(top_builddir)/config.status $(top_srcdir)/man/stapprobes.kprocess.3stap.in cd $(top_builddir) && $(SHELL) ./config.status $@ man/stapprobes.rpc.3stap: $(top_builddir)/config.status $(top_srcdir)/man/stapprobes.rpc.3stap.in cd $(top_builddir) && $(SHELL) ./config.status $@ diff --git a/NEWS b/NEWS index 02f00367..37a424d8 100644 --- a/NEWS +++ b/NEWS @@ -1,5 +1,10 @@ * What's new +- 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 + their kernel perspective on processes. + - The --skip-badvars option now also suppresses run-time error messages that would otherwise result from erroneous memory accesses. Such accesses can originate from $context expressions fueled by diff --git a/configure b/configure index 03763d5a..852dc786 100755 --- a/configure +++ b/configure @@ -8074,7 +8074,7 @@ _ACEOF ac_config_headers="$ac_config_headers config.h:config.in" -ac_config_files="$ac_config_files Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.process.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap initscript/systemtap" +ac_config_files="$ac_config_files Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.kprocess.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap initscript/systemtap" @@ -8776,7 +8776,7 @@ do "man/stapprobes.nfs.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.nfs.3stap" ;; "man/stapprobes.nfsd.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.nfsd.3stap" ;; "man/stapprobes.pagefault.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.pagefault.3stap" ;; - "man/stapprobes.process.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.process.3stap" ;; + "man/stapprobes.kprocess.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.kprocess.3stap" ;; "man/stapprobes.rpc.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.rpc.3stap" ;; "man/stapprobes.scsi.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.scsi.3stap" ;; "man/stapprobes.signal.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.signal.3stap" ;; diff --git a/configure.ac b/configure.ac index ee8ae61f..a953e156 100644 --- a/configure.ac +++ b/configure.ac @@ -356,7 +356,7 @@ dnl Don't use this directly (when not given it is set to NONE). AC_DEFINE_UNQUOTED(STAP_PREFIX, "$prefix", [configure prefix location]) AC_CONFIG_HEADERS([config.h:config.in]) -AC_CONFIG_FILES(Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.process.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap initscript/systemtap) +AC_CONFIG_FILES(Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.kprocess.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap initscript/systemtap) AC_CONFIG_SUBDIRS(testsuite) AC_CONFIG_FILES([run-stap], [chmod +x run-stap]) AC_CONFIG_FILES([run-staprun], [chmod +x run-staprun]) diff --git a/doc/SystemTap_Beginners_Guide/en-US/References.xml b/doc/SystemTap_Beginners_Guide/en-US/References.xml index ff993df2..6ab74f17 100644 --- a/doc/SystemTap_Beginners_Guide/en-US/References.xml +++ b/doc/SystemTap_Beginners_Guide/en-US/References.xml @@ -43,7 +43,7 @@ The stapprobes man page enumerates a variety of probe points supported by SystemTap, along with additional aliases defined by the SystemTap tapset library. The bottom of the man page includes a list of other man pages enumerating similar probe points for specific system components, such as - stapprobes.scsi, stapprobes.process, + stapprobes.scsi, stapprobes.kprocess, stapprobes.signal, etc. diff --git a/doc/SystemTap_Tapset_Reference/tapsets.tmpl b/doc/SystemTap_Tapset_Reference/tapsets.tmpl index b7c0713b..19a8e02f 100644 --- a/doc/SystemTap_Tapset_Reference/tapsets.tmpl +++ b/doc/SystemTap_Tapset_Reference/tapsets.tmpl @@ -181,13 +181,13 @@ !Itapset/socket.stp - - Process Tapset + + Kernel Process Tapset This family of probe points is used to probe process-related activities. It contains the following probe points: -!Itapset/process.stp +!Itapset/kprocess.stp Signal Tapset diff --git a/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml b/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml index d497eae6..293a0dc3 100644 --- a/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml +++ b/doc/Tapset_Reference_Guide/en-US/Tapset_Dev_Guide.xml @@ -64,7 +64,7 @@ -probe process.exec = kernel.function("do_execve"), +probe kprocess.exec = kernel.function("do_execve"), kernel.function("compat_do_execve") {probe body} @@ -106,7 +106,7 @@ kernel.function("compat_do_execve") -probe process.create = kernel.function("copy_process").return +probe kprocess.create = kernel.function("copy_process").return { task = $return new_pid = task_pid(task) diff --git a/man/stapprobes.kprocess.3stap.in b/man/stapprobes.kprocess.3stap.in new file mode 100644 index 00000000..4f5e7903 --- /dev/null +++ b/man/stapprobes.kprocess.3stap.in @@ -0,0 +1,106 @@ +.\" -*- nroff -*- +.TH STAPPROBES.KPROCESS 3stap @DATE@ "Intel, IBM" +.SH NAME +stapprobes.kprocess \- systemtap kernel process probe points + +.\" macros +.de SAMPLE +.br +.RS +.nf +.nh +.. +.de ESAMPLE +.hy +.fi +.RE +.. + +.SH DESCRIPTION + +This family of probe points is used to probe the kernel's process activities. +It contains the following probe points: + +.P +.TP +.B kprocess.create + +Fires whenever a new process is successfully created, either as a +result of one of the fork syscall variants, or a new kernel thread. + +.B Arguments: + +.I task + a handle to the newly created process + +.I new_pid + pid of the newly created process + +.P +.TP +.B kprocess.start + +Fires immediately before a new process begins execution. + +.B Arguments: + +.I N/A + +.P +.TP +.B kprocess.exec + +Fires whenever a process attempts to exec to a new program + +.B Arguments: + +.I filename + the path to the new executable + +.P +.TP +.B kprocess.exec_complete + +Fires at the completion of an exec call + +.B Arguments: + +.I errno + the error number resulting from the exec + +.I success + a boolean indicating whether the exec was successful + +.P +.TP +.B kprocess.exit + +Fires when a process terminates. This will always be followed by a +kprocess.release, though the latter may be delayed if the process +waits in a zombie state. + +.B Arguments: + +.I code + the exit code of the process + +.P +.TP +.B kprocess.release + +Fires when a process is released from the kernel. This always +follows a kprocess.exit, though it may be delayed somewhat if the +process waits in a zombie state. + +.B Arguments: + +.I task + a task handle to the process being released + +.I pid + pid of the process being released + +.SH SEE ALSO +.IR stap (1), +.IR stapprobes (3stap) + diff --git a/man/stapprobes.process.3stap.in b/man/stapprobes.process.3stap.in deleted file mode 100644 index aa8089e8..00000000 --- a/man/stapprobes.process.3stap.in +++ /dev/null @@ -1,106 +0,0 @@ -.\" -*- nroff -*- -.TH STAPPROBES.PROCESS 3stap @DATE@ "Intel, IBM" -.SH NAME -stapprobes.process \- systemtap process probe points - -.\" macros -.de SAMPLE -.br -.RS -.nf -.nh -.. -.de ESAMPLE -.hy -.fi -.RE -.. - -.SH DESCRIPTION - -This family of probe points is used to probe the process activities. -It contains the following probe points: - -.P -.TP -.B process.create - -Fires whenever a new process is successfully created, either as a -result of one of the fork syscall variants, or a new kernel thread. - -.B Arguments: - -.I task - a handle to the newly created process - -.I new_pid - pid of the newly created process - -.P -.TP -.B process.start - -Fires immediately before a new process begins execution. - -.B Arguments: - -.I N/A - -.P -.TP -.B process.exec - -Fires whenever a process attempts to exec to a new program - -.B Arguments: - -.I filename - the path to the new executable - -.P -.TP -.B process.exec_complete - -Fires at the completion of an exec call - -.B Arguments: - -.I errno - the error number resulting from the exec - -.I success - a boolean indicating whether the exec was successful - -.P -.TP -.B process.exit - -Fires when a process terminates. This will always be followed by a -process.release, though the latter may be delayed if the process -waits in a zombie state. - -.B Arguments: - -.I code - the exit code of the process - -.P -.TP -.B process.release - -Fires when a process is released from the kernel. This always -follows a process.exit, though it may be delayed somewhat if the -process waits in a zombie state. - -.B Arguments: - -.I task - a task handle to the process being released - -.I pid - pid of the process being released - -.SH SEE ALSO -.IR stap (1), -.IR stapprobes (3stap) - diff --git a/tapset/DEVGUIDE b/tapset/DEVGUIDE index e6bc3fb8..693521a8 100644 --- a/tapset/DEVGUIDE +++ b/tapset/DEVGUIDE @@ -59,8 +59,8 @@ For example, process execs can occur in either the do_execve() or the compat_do_execve() functions. The following alias inserts probes at the beginning of those functions: -probe process.exec = kernel.function("do_execve"), - kernel.function("compat_do_execve") { +probe kprocess.exec = kernel.function("do_execve"), + kernel.function("compat_do_execve") { < probe body > } @@ -87,7 +87,7 @@ process is retrieved by calling task_pid() and passing it the task_struct pointer. In this case, the auxiliary function is an embedded C function that's defined in the task tapset (task.stp). -probe process.create = kernel.function("copy_process").return { +probe kprocess.create = kernel.function("copy_process").return { task = $return new_pid = task_pid(task) } diff --git a/tapset/kprocess.stp b/tapset/kprocess.stp new file mode 100644 index 00000000..316e03ce --- /dev/null +++ b/tapset/kprocess.stp @@ -0,0 +1,115 @@ +// kernel process tapset +// Copyright (C) 2006 Intel Corporation. +// +// 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. +// +// This family of probe points is used to probe process-related activities. +// + +function _IS_ERR:long(ptr:long) %{ /* pure */ + THIS->__retvalue = IS_ERR((const void *)(long)THIS->ptr); +%} + + +/** + * probe kprocess.create - Fires whenever a new process is successfully created + * @new_pid: The PID of the newly created process + * + * Context: + * Parent of the created process. + * + * Fires whenever a new process is successfully created, either as a result of + * fork (or one of its syscall variants), or a new kernel thread. + */ +probe kprocess.create = kernel.function("copy_process").return { + task = $return + if (_IS_ERR(task)) next + new_pid = task_pid(task) +} + + +/** + * probe kprocess.start - Starting new process + * + * Context: + * Newly created process. + * + * Fires immediately before a new process begins execution. + * + */ +probe kprocess.start = kernel.function("schedule_tail") { } + + +/** + * probe kprocess.exec - Attempt to exec to a new program + * @filename: The path to the new executable + * + * Context: + * The caller of exec. + * + * Fires whenever a process attempts to exec to a new program. + */ +probe kprocess.exec = + kernel.function("do_execve"), + kernel.function("compat_do_execve") ? +{ + filename = kernel_string($filename) +} + + +/** + * probe kprocess.exec_complete - Return from exec to a new program + * @errno: The error number resulting from the exec + * @success: A boolean indicating whether the exec was successful + * + * Context: + * On success, the context of the new executable. + * On failure, remains in the context of the caller. + * + * Fires at the completion of an exec call. + */ +probe kprocess.exec_complete = + kernel.function("do_execve").return, + kernel.function("compat_do_execve").return ? +{ + errno = $return + success = (errno >= 0) +} + + +/** + * probe kprocess.exit - Exit from process + * @code: The exit code of the process + * + * Context: + * The process which is terminating. + * + * Fires when a process terminates. This will always be followed by a + * kprocess.release, though the latter may be delayed if the process waits in a + * zombie state. + */ +probe kprocess.exit = kernel.function("do_exit") { + code = $code +} + + +/** + * probe kprocess.release - Process released + * @task: A task handle to the process being released + * @pid: PID of the process being released + * + * Context: + * The context of the parent, if it wanted notification of this process' + * termination, else the context of the process itself. + * + * Fires when a process is released from the kernel. This always follows a + * kprocess.exit, though it may be delayed somewhat if the process waits in a + * zombie state. + */ +probe kprocess.release = kernel.function("release_task") { + task = $p + pid = $p->pid; +} diff --git a/tapset/process.stp b/tapset/process.stp deleted file mode 100644 index e39f740a..00000000 --- a/tapset/process.stp +++ /dev/null @@ -1,115 +0,0 @@ -// process tapset -// Copyright (C) 2006 Intel Corporation. -// -// 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. -// -// This family of probe points is used to probe process-related activities. -// - -function _IS_ERR:long(ptr:long) %{ /* pure */ - THIS->__retvalue = IS_ERR((const void *)(long)THIS->ptr); -%} - - -/** - * probe process.create - Fires whenever a new process is successfully created - * @new_pid: The PID of the newly created process - * - * Context: - * Parent of the created process. - * - * Fires whenever a new process is successfully created, either as a result of - * fork (or one of its syscall variants), or a new kernel thread. - */ -probe process.create = kernel.function("copy_process").return { - task = $return - if (_IS_ERR(task)) next - new_pid = task_pid(task) -} - - -/** - * probe process.start - Starting new process - * - * Context: - * Newly created process. - * - * Fires immediately before a new process begins execution. - * - */ -probe process.start = kernel.function("schedule_tail") { } - - -/** - * probe process.exec - Attempt to exec to a new program - * @filename: The path to the new executable - * - * Context: - * The caller of exec. - * - * Fires whenever a process attempts to exec to a new program. - */ -probe process.exec = - kernel.function("do_execve"), - kernel.function("compat_do_execve") ? -{ - filename = kernel_string($filename) -} - - -/** - * probe process.exec_complete - Return from exec to a new program - * @errno: The error number resulting from the exec - * @success: A boolean indicating whether the exec was successful - * - * Context: - * On success, the context of the new executable. - * On failure, remains in the context of the caller. - * - * Fires at the completion of an exec call. - */ -probe process.exec_complete = - kernel.function("do_execve").return, - kernel.function("compat_do_execve").return ? -{ - errno = $return - success = (errno >= 0) -} - - -/** - * probe process.exit - Exit from process - * @code: The exit code of the process - * - * Context: - * The process which is terminating. - * - * Fires when a process terminates. This will always be followed by a - * process.release, though the latter may be delayed if the process waits in a - * zombie state. - */ -probe process.exit = kernel.function("do_exit") { - code = $code -} - - -/** - * probe process.release - Process released - * @task: A task handle to the process being released - * @pid: PID of the process being released - * - * Context: - * The context of the parent, if it wanted notification of this process' - * termination, else the context of the process itself. - * - * Fires when a process is released from the kernel. This always follows a - * process.exit, though it may be delayed somewhat if the process waits in a - * zombie state. - */ -probe process.release = kernel.function("release_task") { - task = $p - pid = $p->pid; -} diff --git a/testsuite/buildok/process-all-probes.stp b/testsuite/buildok/process-all-probes.stp index 91a96514..c754462b 100755 --- a/testsuite/buildok/process-all-probes.stp +++ b/testsuite/buildok/process-all-probes.stp @@ -2,11 +2,11 @@ // Tests if all probes in the process tapset are resolvable. -probe process.create, - process.start, - process.exec, - process.exec_complete, - process.exit, - process.release +probe kprocess.create, + kprocess.start, + kprocess.exec, + kprocess.exec_complete, + kprocess.exit, + kprocess.release { } diff --git a/testsuite/buildok/process_test.stp b/testsuite/buildok/process_test.stp index 90de8b69..ba3fadf1 100755 --- a/testsuite/buildok/process_test.stp +++ b/testsuite/buildok/process_test.stp @@ -1,31 +1,31 @@ #! stap -p4 -probe process.create { +probe kprocess.create { log(pp()) log(sprint(task)) } -probe process.start { +probe kprocess.start { log(pp()) } -probe process.exec { +probe kprocess.exec { log(pp()) log(filename) } -probe process.exec_complete { +probe kprocess.exec_complete { log(pp()) log(sprint(errno)) log(sprint(success)) } -probe process.exit { +probe kprocess.exit { log(pp()) log(sprint(code)) } -probe process.release { +probe kprocess.release { log(pp()) log(sprint(task)) } diff --git a/testsuite/systemtap.examples/process/proc_snoop.stp b/testsuite/systemtap.examples/process/proc_snoop.stp index 06425d45..9a3768c2 100755 --- a/testsuite/systemtap.examples/process/proc_snoop.stp +++ b/testsuite/systemtap.examples/process/proc_snoop.stp @@ -18,30 +18,30 @@ function id:string(task:long) { task_execname(task)) } -probe process.create { +probe kprocess.create { report(sprintf("create %s", id(task))) } -probe process.start { +probe kprocess.start { report("start") } -probe process.exec { +probe kprocess.exec { report(sprintf("exec %s", filename)) } -probe process.exec_complete { +probe kprocess.exec_complete { if (success) report("exec success") else report(sprintf("exec failed %d (%s)", errno, errno_str(errno))) } -probe process.exit { +probe kprocess.exit { report(sprintf("exit %d", code)) } -probe process.release { +probe kprocess.release { report(sprintf("remove %s", id(task))) } diff --git a/testsuite/systemtap.stress/whitelist.exp b/testsuite/systemtap.stress/whitelist.exp index 4a31c124..70973978 100644 --- a/testsuite/systemtap.stress/whitelist.exp +++ b/testsuite/systemtap.stress/whitelist.exp @@ -96,6 +96,7 @@ set init_probes_all_script { udp.*.return, tcp.*, tcp.*.return, + kprocess.*, process.*, nfs.fop.*, nfs.aop.*, -- cgit From 7a51212ca1895b85f400fafe0e5198525996af1d Mon Sep 17 00:00:00 2001 From: William Cohen Date: Tue, 14 Apr 2009 17:37:19 -0400 Subject: Minor formatting to avoid line wrap, added tcpdumplike.meta file, and regenerated index files. --- testsuite/systemtap.examples/index.html | 3 +++ testsuite/systemtap.examples/index.txt | 8 ++++++++ testsuite/systemtap.examples/keyword-index.html | 6 ++++++ testsuite/systemtap.examples/keyword-index.txt | 16 ++++++++++++++++ testsuite/systemtap.examples/network/tcpdumplike.meta | 12 ++++++++++++ testsuite/systemtap.examples/network/tcpdumplike.stp | 10 +++++----- 6 files changed, 50 insertions(+), 5 deletions(-) create mode 100644 testsuite/systemtap.examples/network/tcpdumplike.meta diff --git a/testsuite/systemtap.examples/index.html b/testsuite/systemtap.examples/index.html index 3287458a..a03b8dcc 100644 --- a/testsuite/systemtap.examples/index.html +++ b/testsuite/systemtap.examples/index.html @@ -97,6 +97,9 @@ keywords: NETWORK network/tcp_connections.stp - Track Creation of Incoming TCP Connections
        keywords: NETWORK TCP SOCKET

        The tcp_connections.stp script prints information for each new incoming TCP connection accepted by the computer. The information includes the UID, the command accepting the connection, the PID of the command, the port the connection is on, and the IP address of the originator of the request.

      • +
      • network/tcpdumplike.stp - Dump of Received TCP Packets
        +keywords: NETWORK TRAFFIC
        +

        The tcpdumplike.stp prints out a line for each TCP packet received. Each line includes the source and destination IP addresses, the source and destination ports, and flags.

      • process/errsnoop.stp - tabulate system call errors
        keywords: PROCESS SYSCALL

        The script prints a periodic tabular report about failing system calls, by process and by syscall failure. The first optional argument specifies the reporting interval (in seconds, default 5); the second optional argument gives a screen height (number of lines in the report, default 20).

      • diff --git a/testsuite/systemtap.examples/index.txt b/testsuite/systemtap.examples/index.txt index d538d760..d24232e7 100644 --- a/testsuite/systemtap.examples/index.txt +++ b/testsuite/systemtap.examples/index.txt @@ -182,6 +182,14 @@ keywords: network tcp socket originator of the request. +network/tcpdumplike.stp - Dump of Received TCP Packets +keywords: network traffic + + The tcpdumplike.stp prints out a line for each TCP packet received. + Each line includes the source and destination IP addresses, the + source and destination ports, and flags. + + process/errsnoop.stp - tabulate system call errors keywords: process syscall diff --git a/testsuite/systemtap.examples/keyword-index.html b/testsuite/systemtap.examples/keyword-index.html index 2254fd25..e65ed19d 100644 --- a/testsuite/systemtap.examples/keyword-index.html +++ b/testsuite/systemtap.examples/keyword-index.html @@ -159,6 +159,9 @@ keywords: NETWORK network/tcp_connections.stp - Track Creation of Incoming TCP Connections
        keywords: NETWORK TCP SOCKET

        The tcp_connections.stp script prints information for each new incoming TCP connection accepted by the computer. The information includes the UID, the command accepting the connection, the PID of the command, the port the connection is on, and the IP address of the originator of the request.

        +
      • network/tcpdumplike.stp - Dump of Received TCP Packets
        +keywords: NETWORK TRAFFIC
        +

        The tcpdumplike.stp prints out a line for each TCP packet received. Each line includes the source and destination IP addresses, the source and destination ports, and flags.

      PER-PROCESS

        @@ -288,6 +291,9 @@ keywords: TRACE network/nettop.stp - Periodic Listing of Processes Using Network Interfaces
        keywords: NETWORK TRAFFIC PER-PROCESS

        Every five seconds the nettop.stp script prints out a list of processed (PID and command) with the number of packets sent/received and the amount of data sent/received by the process during that interval.

        +
      • network/tcpdumplike.stp - Dump of Received TCP Packets
        +keywords: NETWORK TRAFFIC
        +

        The tcpdumplike.stp prints out a line for each TCP packet received. Each line includes the source and destination IP addresses, the source and destination ports, and flags.

      USE

        diff --git a/testsuite/systemtap.examples/keyword-index.txt b/testsuite/systemtap.examples/keyword-index.txt index 8fd8e0d8..40b5276f 100644 --- a/testsuite/systemtap.examples/keyword-index.txt +++ b/testsuite/systemtap.examples/keyword-index.txt @@ -281,6 +281,14 @@ keywords: network tcp socket originator of the request. +network/tcpdumplike.stp - Dump of Received TCP Packets +keywords: network traffic + + The tcpdumplike.stp prints out a line for each TCP packet received. + Each line includes the source and destination IP addresses, the + source and destination ports, and flags. + + = PER-PROCESS = network/nettop.stp - Periodic Listing of Processes Using Network Interfaces @@ -597,6 +605,14 @@ keywords: network traffic per-process interval. +network/tcpdumplike.stp - Dump of Received TCP Packets +keywords: network traffic + + The tcpdumplike.stp prints out a line for each TCP packet received. + Each line includes the source and destination IP addresses, the + source and destination ports, and flags. + + = USE = general/graphs.stp - Graphing Disk and CPU Utilization diff --git a/testsuite/systemtap.examples/network/tcpdumplike.meta b/testsuite/systemtap.examples/network/tcpdumplike.meta new file mode 100644 index 00000000..8fb9fccb --- /dev/null +++ b/testsuite/systemtap.examples/network/tcpdumplike.meta @@ -0,0 +1,12 @@ +title: Dump of Received TCP Packets +name: tcpdumplike.stp +version: 1.0 +author: anonymous +keywords: network traffic +subsystem: network +status: production +exit: user-controlled +output: timed +scope: system-wide +description: The tcpdumplike.stp prints out a line for each TCP packet received. Each line includes the source and destination IP addresses, the source and destination ports, and flags. +test_installcheck: stap tcpdumplike.stp -c "sleep 1" diff --git a/testsuite/systemtap.examples/network/tcpdumplike.stp b/testsuite/systemtap.examples/network/tcpdumplike.stp index 533c71b9..de3899d6 100755 --- a/testsuite/systemtap.examples/network/tcpdumplike.stp +++ b/testsuite/systemtap.examples/network/tcpdumplike.stp @@ -3,12 +3,12 @@ // A TCP dump like example probe begin, timer.s(1) { - printf("-----------------------------------------------------------------\n"); - printf(" Source IP Dest IP SPort DPort U A P R S F \n"); - printf("-----------------------------------------------------------------\n"); + printf("-----------------------------------------------------------------\n") + printf(" Source IP Dest IP SPort DPort U A P R S F \n") + printf("-----------------------------------------------------------------\n") } probe tcp.receive { - printf(" %15s %15s %5d %5d %d %d %d %d %d %d\n", - saddr, daddr, sport, dport, urg, ack, psh, rst, syn, fin) + printf(" %15s %15s %5d %5d %d %d %d %d %d %d\n", + saddr, daddr, sport, dport, urg, ack, psh, rst, syn, fin) } -- cgit