From bbafcb1e9cff0ca06c7b8e615def02183e8a67f1 Mon Sep 17 00:00:00 2001 From: Stan Cox Date: Mon, 4 Jan 2010 16:20:44 -0500 Subject: Purge sdt utrace support. * sdt.h (UTRACE_SDT): Remove. * tapset-utrace.cxx (utrace_derived_probe): Remove has_library and library. (utrace_derived_probe_group::emit_probe_decl): Remove mmap_callback, sdt_sem_offset, and sdt_sem_address. (utrace_derived_probe_group::emit_module_decls): Remove sdt_sem_offset and sdt_sem_address support. * tapsets.cxx (sdt_var_expanding_visitor): Remove utrace_probe. (sdt_query::handle_query_module) Remove utrace_type. (sdt_query::convert_probe): Likewise. * postgres.exp: Remove utrace testing. * sdt.exp: Likewise. * sdt_misc.exp: Likewise. --- includes/sys/sdt.h | 9 +-- tapset-utrace.cxx | 109 +++------------------------------- tapsets.cxx | 77 ++++++++---------------- testsuite/systemtap.apps/postgres.exp | 9 +-- testsuite/systemtap.base/sdt.exp | 4 +- testsuite/systemtap.base/sdt_misc.exp | 4 +- 6 files changed, 40 insertions(+), 172 deletions(-) diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h index 7c23d55a..882a0d8b 100644 --- a/includes/sys/sdt.h +++ b/includes/sys/sdt.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2005-2009 Red Hat Inc. +/* Copyright (C) 2005-2010 Red Hat Inc. This file is part of systemtap, and is free software in the public domain. */ @@ -49,7 +49,7 @@ #define STAP_SEMAPHORE(probe) #endif -#if ! (defined EXPERIMENTAL_UTRACE_SDT || defined EXPERIMENTAL_KPROBE_SDT) +#if ! defined EXPERIMENTAL_KPROBE_SDT /* These baroque macros are used to create a unique label. */ #define STAP_CONCAT(a,b) a ## b @@ -222,7 +222,7 @@ do STAP_SEMAPHORE(probe) { \ STAP_NOP "/* %0 %1 %2 %3 %4 %5 %6 %7 %8 %9 */" :: "g"(arg1), "g"(arg2), "g"(arg3), "g"(arg4), "g"(arg5), "g"(arg6), "g"(arg7), "g"(arg8), "g"(arg9), "g"(arg10)); \ } while (0) -#else /* ! (defined EXPERIMENTAL_UTRACE_SDT || defined EXPERIMENTAL_KPROBE_SDT) */ +#else /* ! defined EXPERIMENTAL_KPROBE_SDT */ #include #include # if defined (__USE_ANSI) @@ -231,9 +231,6 @@ extern long int syscall (long int __sysno, ...) __THROW; # if defined EXPERIMENTAL_KPROBE_SDT # define STAP_SYSCALL __NR_getegid # define STAP_GUARD 0x32425250 -# elif defined EXPERIMENTAL_UTRACE_SDT -# define STAP_SYSCALL 0xbead -# define STAP_GUARD 0x33425250 # endif #include diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx index e3a6fd5b..fc2fbc1d 100644 --- a/tapset-utrace.cxx +++ b/tapset-utrace.cxx @@ -1,5 +1,5 @@ // utrace tapset -// Copyright (C) 2005-2009 Red Hat Inc. +// Copyright (C) 2005-2010 Red Hat Inc. // Copyright (C) 2005-2007 Intel Corporation. // Copyright (C) 2008 James.Bottomley@HansenPartnership.com // @@ -29,7 +29,6 @@ static const string TOK_END("end"); static const string TOK_THREAD("thread"); static const string TOK_SYSCALL("syscall"); static const string TOK_RETURN("return"); -static const string TOK_LIBRARY("library"); // ------------------------------------------------------------------------ @@ -60,8 +59,8 @@ struct utrace_derived_probe: public derived_probe bool target_symbol_seen; utrace_derived_probe (systemtap_session &s, probe* p, probe_point* l, - bool hp, string &pn, bool hl, string &ln, - int64_t pd, enum utrace_derived_probe_flags f); + bool hp, string &pn, int64_t pd, + enum utrace_derived_probe_flags f); void join_group (systemtap_session& s); void emit_unprivileged_assertion (translator_output*); @@ -118,10 +117,10 @@ struct utrace_var_expanding_visitor: public var_expanding_visitor utrace_derived_probe::utrace_derived_probe (systemtap_session &s, probe* p, probe_point* l, - bool hp, string &pn, bool hl, string &ln, - int64_t pd, enum utrace_derived_probe_flags f): + bool hp, string &pn, int64_t pd, + enum utrace_derived_probe_flags f): derived_probe (p, new probe_point (*l) /* .components soon rewritten */ ), - has_path(hp), path(pn), has_library(hl), library(ln), pid(pd), flags(f), + has_path(hp), path(pn), pid(pd), flags(f), target_symbol_seen(false) { if (s.kernel_config["CONFIG_UTRACE"] != string("y")) @@ -602,11 +601,9 @@ struct utrace_builder: public derived_probe_builder vector & finished_results) { string path; - string lib; int64_t pid; bool has_path = get_param (parameters, TOK_PROCESS, path); - bool has_lib = get_param (parameters, TOK_LIBRARY, lib); bool has_pid = get_param (parameters, TOK_PROCESS, pid); enum utrace_derived_probe_flags flags = UDPF_NONE; @@ -652,11 +649,9 @@ struct utrace_builder: public derived_probe_builder // XXX: could we use /proc/$pid/exe in unwindsym_modules and elsewhere? } - if (has_lib) - lib = find_executable (lib, "LD_LIBRARY_PATH"); finished_results.push_back(new utrace_derived_probe(sess, base, location, - has_path, path, has_lib, lib, pid, + has_path, path, pid, flags)); } @@ -755,27 +750,7 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s, break; } s.op->line() << " .engine_attached=0,"; - - if (p->sdt_semaphore_addr != 0) - s.op->line() << " .sdt_sem_offset=(unsigned long)0x" - << hex << p->sdt_semaphore_addr << dec << "ULL,"; - s.op->line() << " .sdt_sem_address=0,"; - s.op->line() << " .tsk=0,"; s.op->line() << " },"; - - if (p->has_library && p->sdt_semaphore_addr != 0) - { - s.op->newline() << "{"; - s.op->line() << " .tgt={"; - s.op->line() << " .procname=\"" << p->path << "\","; - s.op->line() << " .mmap_callback=&stap_utrace_mmap_found,"; - s.op->line() << " },"; - s.op->line() << " .pathname=\"" << p->library << "\","; - s.op->line() << " .sdt_sem_offset=(unsigned long)0x" - << hex << p->sdt_semaphore_addr << dec << "ULL,"; - s.op->line() << " .sdt_sem_address=0,"; - s.op->line() << " },"; - } } @@ -809,12 +784,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "enum utrace_derived_probe_flags flags;"; s.op->newline() << "struct utrace_engine_ops ops;"; s.op->newline() << "unsigned long events;"; - s.op->newline() << "struct task_struct *tsk;"; - s.op->newline() << "unsigned long sdt_sem_offset;"; - // FIXME: if this probe is attached to more than 1 task, having 1 - // address here won't work - s.op->newline() << "unsigned long sdt_sem_address;"; - s.op->newline(0) << "const char *pathname;"; s.op->newline(-1) << "};"; @@ -941,24 +910,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "break;"; s.op->indent(-1); s.op->newline(-1) << "}"; - - s.op->newline() << "if (p->sdt_sem_offset && p->sdt_sem_address == 0) {"; - s.op->indent(1); - // If the probe is in the executable itself, the offset *is* the address. - s.op->newline() << "p->sdt_sem_address = p->sdt_sem_offset;"; - s.op->newline(-1) << "}"; - - // Before writing to the semaphore, we need to check for VM_WRITE access. - s.op->newline() << "if (p->sdt_sem_address) {"; - s.op->newline(1) << "size_t sdt_semaphore;"; - // XXX p could get registered to more than one task! - s.op->newline() << "p->tsk = tsk;"; - - s.op->newline() << "if (get_user (sdt_semaphore, (unsigned short __user *) p->sdt_sem_address) == 0) {"; - s.op->newline(1) << "sdt_semaphore ++;"; - s.op->newline() << "put_user (sdt_semaphore, (unsigned short __user *) p->sdt_sem_address);"; - s.op->newline(-1) << "}"; - s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; // Since this engine could be attached to multiple threads, don't @@ -1022,40 +973,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "return rc;"; s.op->newline(-1) << "}"; - // The task_finder_mmap_callback - s.op->newline() << "static int stap_utrace_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_utrace_probe *p = container_of(tgt, struct stap_utrace_probe, tgt);"; - s.op->newline() << "int rc = 0;"; - // the shared library we're interested in - s.op->newline() << "if (path == NULL || strcmp (path, p->pathname)) return 0;"; - s.op->newline() << "if (p->sdt_sem_address == 0) {"; - s.op->indent(1); - // If the probe is in the executable itself, the offset *is* the - // address. - s.op->newline() << "if (vm_flags & VM_EXECUTABLE) {"; - s.op->indent(1); - s.op->newline() << "p->sdt_sem_address = addr + p->sdt_sem_offset;"; - s.op->newline(-1) << "}"; - // If the probe is in a .so, we have to calculate the address. - s.op->newline() << "else {"; - s.op->indent(1); - s.op->newline() << "p->sdt_sem_address = (addr - offset) + p->sdt_sem_offset;"; - s.op->newline(-1) << "}"; - s.op->newline(-1) << "}"; - - s.op->newline() << "if (p->sdt_sem_address && (vm_flags & VM_WRITE)) {"; - s.op->newline(1) << "unsigned short sdt_semaphore = 0;"; // NB: fixed size - s.op->newline() << "if (get_user (sdt_semaphore, (unsigned short __user *) p->sdt_sem_address) == 0) {"; - s.op->newline(1) << "sdt_semaphore ++;"; - s.op->newline() << "#ifdef DEBUG_UTRACE"; - s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"+semaphore %#x @ %#lx\\n\", sdt_semaphore, p->sdt_sem_address);"; - s.op->newline() << "#endif"; - s.op->newline() << "put_user (sdt_semaphore, (unsigned short __user *) p->sdt_sem_address);"; - s.op->newline(-1) << "}"; - s.op->newline(-1) << "}"; - s.op->newline() << "return 0;"; - s.op->newline(-1) << "}"; - s.op->newline() << "static struct stap_utrace_probe stap_utrace_probes[] = {"; s.op->indent(1); @@ -1126,18 +1043,8 @@ utrace_derived_probe_group::emit_module_exit (systemtap_session& s) s.op->newline() << "if (p->engine_attached) {"; s.op->newline(1) << "stap_utrace_detach_ops(&p->ops);"; - // Before writing to the semaphore, we need to check for VM_WRITE access. - s.op->newline() << "if (p->sdt_sem_address) {"; - s.op->newline(1) << "size_t sdt_semaphore;"; - // XXX p could get registered to more than one task! - s.op->newline() << "if (get_user (sdt_semaphore, (unsigned short __user *) p->sdt_sem_address) == 0) {"; - s.op->newline(1) << "sdt_semaphore --;"; - s.op->newline() << "put_user (sdt_semaphore, (unsigned short __user *) p->sdt_sem_address);"; - s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; - - s.op->newline(-1) << "}"; } @@ -1166,8 +1073,6 @@ register_tapset_utrace(systemtap_session& s) ->bind(builder); roots[i]->bind(TOK_SYSCALL)->bind(TOK_RETURN) ->bind(builder); - roots[i]->bind_str(TOK_LIBRARY)->bind(TOK_SYSCALL) - ->bind(builder); } } diff --git a/tapsets.cxx b/tapsets.cxx index bac47761..f0859b21 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -1,5 +1,5 @@ // tapset resolution -// Copyright (C) 2005-2009 Red Hat Inc. +// Copyright (C) 2005-2010 Red Hat Inc. // Copyright (C) 2005-2007 Intel Corporation. // Copyright (C) 2008 James.Bottomley@HansenPartnership.com // @@ -3579,9 +3579,9 @@ dwarf_derived_probe_group::emit_module_exit (systemtap_session& s) struct sdt_var_expanding_visitor: public var_expanding_visitor { sdt_var_expanding_visitor(string & process_name, string & probe_name, - int arg_count, bool have_reg_args, bool utrace_probe): + int arg_count, bool have_reg_args): process_name (process_name), probe_name (probe_name), - have_reg_args (have_reg_args), utrace_probe (utrace_probe), + have_reg_args (have_reg_args), arg_count (arg_count) { assert(!have_reg_args || (arg_count >= 0 && arg_count <= 10)); @@ -3589,7 +3589,6 @@ struct sdt_var_expanding_visitor: public var_expanding_visitor string & process_name; string & probe_name; bool have_reg_args; - bool utrace_probe; int arg_count; void visit_target_symbol (target_symbol* e); @@ -3624,10 +3623,10 @@ sdt_var_expanding_visitor::visit_target_symbol (target_symbol *e) // First two args are hidden: 1. pointer to probe name 2. task id if (arg_count < 2) { - fc->function = utrace_probe ? "_utrace_syscall_arg" : "ulong_arg"; + fc->function = "ulong_arg"; fc->type = pe_long; fc->tok = e->tok; - literal_number* num = new literal_number(argno + (utrace_probe ? 1 : 2)); + literal_number* num = new literal_number(argno + 2); num->tok = e->tok; fc->args.push_back(num); } @@ -3638,9 +3637,9 @@ sdt_var_expanding_visitor::visit_target_symbol (target_symbol *e) binary_expression *be = new binary_expression; be->tok = e->tok; functioncall *get_arg1 = new functioncall; - get_arg1->function = utrace_probe ? "_utrace_syscall_arg" : "pointer_arg"; + get_arg1->function = "pointer_arg"; get_arg1->tok = e->tok; - literal_number* num = new literal_number((utrace_probe ? 2 : 3)); + literal_number* num = new literal_number(3); num->tok = e->tok; get_arg1->args.push_back(num); @@ -3687,7 +3686,6 @@ private: { uprobe_type = 0x31425250, // "PRB1" kprobe_type = 0x32425250, // "PRB2" - utrace_type = 0x33425250, // "PRB3" } probe_type; probe * base_probe; @@ -3749,9 +3747,6 @@ sdt_query::handle_query_module() case kprobe_type: clog << "kprobe" << endl; break; - case utrace_type: - clog << "utrace" << endl; - break; } } probe *new_base = new probe(*base_probe); @@ -3760,7 +3755,7 @@ sdt_query::handle_query_module() new_base->body = deep_copy_visitor::deep_copy(base_probe->body); bool have_reg_args = false; - if (probe_type == kprobe_type || probe_type == utrace_type) + if (probe_type == kprobe_type) { convert_probe(new_base); have_reg_args = true; @@ -3768,13 +3763,12 @@ sdt_query::handle_query_module() // Expand the local variables in the probe body sdt_var_expanding_visitor svv (module_val, probe_name, - probe_arg, have_reg_args, - probe_type == utrace_type); + probe_arg, have_reg_args); svv.replace (new_base->body); unsigned i = results.size(); - if (probe_type == kprobe_type || probe_type == utrace_type) + if (probe_type == kprobe_type) derive_probes(sess, new_base, results); else @@ -3889,8 +3883,7 @@ sdt_query::get_next_probe() } *pbe; __uint32_t *type = (__uint32_t*) ((char*)pdata->d_buf + probe_scn_offset); probe_type = (enum probe_types)*type; - if (probe_type != uprobe_type && probe_type != kprobe_type - && probe_type != utrace_type) + if (probe_type != uprobe_type && probe_type != kprobe_type) { // Unless this is a mangled .probes section, this happens // because the name of the probe comes first, followed by @@ -3963,28 +3956,7 @@ sdt_query::convert_probe (probe *base) } #endif - if (probe_type == utrace_type) - { - // Generate: if ($syscall != 0xbead) next; - if_statement *issc = new if_statement; - issc->thenblock = new next_statement; - issc->elseblock = NULL; - issc->tok = b->tok; - comparison *besc = new comparison; - besc->op = "!="; - besc->tok = b->tok; - functioncall* n = new functioncall; - n->tok = b->tok; - n->function = "_utrace_syscall_nr"; - n->referent = 0; - besc->left = n; - literal_number* fake_syscall = new literal_number(0xbead); - fake_syscall->tok = b->tok; - besc->right = fake_syscall; - issc->condition = besc; - b->statements.push_back(issc); - } - else if (probe_type == kprobe_type) + if (probe_type == kprobe_type) { // Generate: if (arg2 != kprobe_type) next; if_statement *istid = new if_statement; @@ -4012,9 +3984,9 @@ sdt_query::convert_probe (probe *base) // Generate: if (arg1 != mark("label")) next; functioncall *fc = new functioncall; - fc->function = (probe_type == utrace_type) ? "_utrace_syscall_arg" : "ulong_arg"; + fc->function = "ulong_arg"; fc->tok = b->tok; - literal_number* num = new literal_number((probe_type == utrace_type) ? 0 : 1); + literal_number* num = new literal_number(1); num->tok = b->tok; fc->args.push_back(num); @@ -4065,14 +4037,6 @@ sdt_query::convert_location (probe *base, probe_point *location) location->components[i]->arg = new literal_string("*getegid*"); break; - case utrace_type: - if (sess.verbose > 3) - clog << "probe_type == utrace_type" << endl; - // process("executable").syscall - location->components[i]->functor = "syscall"; - location->components[i]->arg = NULL; - break; - default: if (sess.verbose > 3) clog << "probe_type == use_uprobe_no_dwarf, use label name: " @@ -4802,7 +4766,7 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "if (likely(sups->tfi != tfi)) continue;"; // skip probes with an address beyond this map event; should not // happen unless a shlib/exec got mmapped in weirdly piecemeal - s.op->newline() << "if (likely(sups->address >= length)) continue;"; + s.op->newline() << "if (likely(sups->address >= length)) continue;"; // Found a uprobe_spec for this stap_uprobe_tf. Need to lock the // stap_uprobes[] array to allocate a free spot, but then we can @@ -4846,7 +4810,16 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "sdt_sem_address[spec_index] = relocation + sups->sdt_sem_offset;"; s.op->newline() << "sdt_sem_tid[spec_index] = tsk->tgid;"; s.op->newline(-1) << "}"; - // If the probe is in a .so, we have to calculate the address. + // If the probe is in a .so, we have to calculate the address + // when the initial mmap maps the entire solib, e.g. + // 7f089885a000-7f089885b000 rw-p- libtcl.so + // A subsequent mmap maps in the writeable segment where the + // semaphore control variable lives, which is when the variable is set. + // 7f089850d000-7f0898647000 r-xp- libtcl.so + // 7f0898647000-7f0898846000 ---p libtcl.so + // 7f0898846000-7f089885b000 rw-p- libtcl.so + // If the task changes, then recalculate the address. + s.op->newline() << "else {"; s.op->indent(1); s.op->newline() << "sdt_sem_address[spec_index] = (relocation - offset) + sups->sdt_sem_offset;"; diff --git a/testsuite/systemtap.apps/postgres.exp b/testsuite/systemtap.apps/postgres.exp index b7f522a1..9d3c18c3 100644 --- a/testsuite/systemtap.apps/postgres.exp +++ b/testsuite/systemtap.apps/postgres.exp @@ -122,14 +122,7 @@ cd postgresql-8.3.6/ mkdir bld;cd bld ../configure --enable-dtrace --prefix=$postgresdir # sed -i -e 's/ifeq (\$(PORTNAME), solaris)/ifeq (\$(enable_dtrace), yes)/' src/backend/Makefile -sed -i -e 's/^CFLAGS = -O2.*\$/& -g -DEXPERIMENTAL_UTRACE_SDT/' src/Makefile.global -make -make install -run_tests utrace - -sed -i -e 's/UTRACE/KPROBE/' src/Makefile.global -(cd src/backend/utils/ - make clean) +sed -i -e 's/^CFLAGS = -O2.*\$/& -g -DEXPERIMENTAL_KPROBE_SDT/' src/Makefile.global make make install run_tests kprobe diff --git a/testsuite/systemtap.base/sdt.exp b/testsuite/systemtap.base/sdt.exp index ea025391..8a77cc06 100644 --- a/testsuite/systemtap.base/sdt.exp +++ b/testsuite/systemtap.base/sdt.exp @@ -12,8 +12,8 @@ set ::result_string {1 set extra_flags {{""} {additional_flags=-std=gnu89} {additional_flags=-ansi} {additional_flags=-pedantic} {additional_flags=-ansi additional_flags=-pedantic} {additional_flags=-O2} {additional_flags="-O3"}} -set pbtype_flags {{""} {additional_flags=-DEXPERIMENTAL_UTRACE_SDT} {additional_flags=-DEXPERIMENTAL_KPROBE_SDT}} -set pbtype_mssgs {{uprobe} {utrace} {kprobe}} +set pbtype_flags {{""} {additional_flags=-DEXPERIMENTAL_KPROBE_SDT}} +set pbtype_mssgs {{uprobe} {kprobe}} # Iterate pbtype_flags for {set p 0} {$p < [llength $pbtype_flags]} {incr p} { diff --git a/testsuite/systemtap.base/sdt_misc.exp b/testsuite/systemtap.base/sdt_misc.exp index 062181a5..8a0cdea2 100644 --- a/testsuite/systemtap.base/sdt_misc.exp +++ b/testsuite/systemtap.base/sdt_misc.exp @@ -136,8 +136,8 @@ if {[installtest_p]} { set sdtdir $srcdir/../includes } -set pbtype_flags {{""} {additional_flags=-O additional_flags=-DEXPERIMENTAL_UTRACE_SDT} {additional_flags=-O additional_flags=-DEXPERIMENTAL_KPROBE_SDT}} -set pbtype_mssgs {{uprobe} {utrace} {kprobe}} +set pbtype_flags {{""} {additional_flags=-O additional_flags=-DEXPERIMENTAL_KPROBE_SDT}} +set pbtype_mssgs {{uprobe} {kprobe}} # Iterate pbtype_flags for {set i 0} {$i < [llength $pbtype_flags]} {incr i} { -- cgit From 74b3bfdddf44251273fae4e957885e1de9269687 Mon Sep 17 00:00:00 2001 From: Robb Romans Date: Mon, 4 Jan 2010 15:55:55 -0600 Subject: Reformat/change per Josh's email comments. --- doc/langref.tex | 130 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 77 insertions(+), 53 deletions(-) diff --git a/doc/langref.tex b/doc/langref.tex index d034c7e7..0f5b92d2 100644 --- a/doc/langref.tex +++ b/doc/langref.tex @@ -686,6 +686,7 @@ kernel.function("no_such_function") ? \subsection{Built-in probe point types (DWARF probes)} \index{built-in probes} \index{dwarf probes} +\label{dwarfprobes} This family of probe points uses symbolic debugging information for the target kernel or module, as may be found in executables that have not been stripped, or in the separate \textbf{debuginfo} packages. They allow @@ -914,51 +915,31 @@ to not register. Also, run statement probes in guru mode only. \index{userspace probing} \index{process} Support for userspace probing is supported on kernels that are -configured to include the utrace extensions. At the time this -document is written, Red Hat and CentOS distributions provide kernels -with utrace support enabled. For more information about utrace, see +configured to include the utrace extensions. Red Hat and CentOS +distributions provide kernels with utrace support enabled. For more +information about utrace, see \url{http://people.redhat.com/roland/utrace/}. -Userspace probing has several forms. A non-symbolic probe point such -as \newline\texttt{process(PID).statement(ADDRESS).absolute} is -analogous to \texttt{kernel.statement(ADDRESS).absolute} in that both -use raw, unverified virtual addresses and provide no -\texttt{\$variables}. The target \texttt{PID} parameter must identify -a running process and \texttt{ADDRESS} must identify a valid -instruction address. All threads of the listed process will be -probed. This is a guru-level probe. - -You can probe non-symbolic user-kernel interface events handled by -utrace. The following constructs are available: +\subsubsection{Begin/end variants} +\label{sec:beginendvariants} +Constructs: \begin{vindent} \begin{verbatim} -process(PID).begin -process("PATH").begin process.begin -process(PID).thread.begin -process("PATH").thread.begin +process("PATH").begin +process(PID).begin + process.thread.begin -process(PID).end -process("PATH").end +process("PATH").thread.begin +process(PID).thread.begin + process.end -process(PID).thread.end -process("PATH").thread.end +process("PATH").end +process(PID).end + process.thread.end -process(PID).syscall -process("PATH").syscall -process.syscall -process(PID).syscall.return -process("PATH").syscall.return -process.syscall.return -process(PID).insn -process("PATH").insn.block -process(PID).insn.block -process("PATH").insn -process("PATH").mark("LABEL") -process("PATH").function("NAME") -process("PATH").statement("*@FILE.c:123") -process("PATH").function("*").return -process("PATH").function("myfun").label("foo") +process("PATH").thread.end +process(PID).thread.end \end{verbatim} \end{vindent} @@ -977,6 +958,21 @@ The \texttt{.end} variant is called when a process described by The \texttt{.thread.end} variant is called when a thread described by \texttt{PID} or \texttt{PATH} dies. +\subsubsection{Syscall variants} +\label{sec:syscallvariants} +Constructs: +\begin{vindent} +\begin{verbatim} +process.syscall +process("PATH").syscall +process(PID).syscall + +process.syscall.return +process("PATH").syscall.return +process(PID).syscall.return +\end{verbatim} +\end{vindent} + The \texttt{.syscall} variant is called when a thread described by \texttt{PID} or \texttt{PATH} makes a system call. The system call number is available in the \texttt{\$syscall} context variable. The @@ -990,14 +986,10 @@ system call number is available in the \texttt{\$syscall} context variable. The return value of the system call is available in the \texttt{\$return} context variable. -The \texttt{.mark} variant is called from a static probe which is -defined in the application. For more information, see -\S\S\ref{staticuserspace}. -In addition, full symbolic source-level probes in userspace programs -and shared libraries are supported. These are exactly analogous to -the symbolic DWARF-based kernel or module probes described previously -and expose similar contextual \texttt{\$-variables}. +\subsubsection{Function/statement variants} +\label{sec:function-statement} +Constructs: \begin{vindent} \begin{verbatim} process("PATH").function("NAME") @@ -1007,11 +999,18 @@ process("PATH").function("myfun").label("foo") \end{verbatim} \end{vindent} +Full symbolic source-level probes in userspace programs and shared +libraries are supported. These are exactly analogous to the symbolic +DWARF-based kernel or module probes described previously and expose +similar contextual \texttt{\$-variables}. See +Section~\ref{dwarfprobes} for more information + +\subsubsection{Process probe paths} +\label{sec:paths} For all process probes, \texttt{PATH} names refer to executables that -are searched the same way that shells do: either the explicit path -specified, or relative to the working directory if they begin with a -dot-slash (./) character sequence. Otherwise, \texttt{\$PATH} is -searched. For example, the following probe syntax: +are searched the same way that shells do: the explicit path specified +if the path name begins with a slash (/) character sequence; otherwise +\texttt{\$PATH} is searched. For example, the following probe syntax: \begin{vindent} \begin{verbatim} probe process("ls").syscall {} @@ -1031,8 +1030,12 @@ If a process probe is specified without a \texttt{PID} or \texttt{PATH} parameter, all user threads are probed. However, if systemtap is invoked in target process mode, process probes are restricted to the process hierarchy associated with the target -process. +process. If stap is running in \texttt{--unprivileged} mode, only +processes owned by the current user are selected. + +\subsubsection{Target process mode} +\label{sec:targetprocessmode} Target process mode (invoked with \texttt{stap -c CMD} or \texttt{-x PID}) implicitly restricts all \texttt{process.*} probes to the given child process. It does not affect \texttt{kernel.*} or other @@ -1073,6 +1076,18 @@ the target command and descendants only. You can use \texttt{\$\$vars} and others. You can provide the location of debug information to the stap command with the \texttt{-d DIRECTORY} option. +\subsubsection{Instruction probes} +\label{sec:insnprobes} +Constructs: +\begin{vindent} +\begin{verbatim} +process("PATH").insn +process(PID).insn + +process("PATH").insn.block +process(PID).insn.block +\end{verbatim} +\end{vindent} The \texttt{process().insn} and \texttt{process().insn.block} probes inspect the process after each instruction or block of instructions is executed. These probes are not implemented on all architectures. If @@ -1095,11 +1110,10 @@ $ stap -e 'global steps; probe process("/bin/ls").insn {steps++} \end{verbatim} \end{vindent} -Using this feature can slow process execution. - +Using this feature will significantly slow process execution. \subsubsection{Static userspace probing} -\label{staticuserspace} +\label{sec:staticuserspace} You can probe symbolic static instrumentation compiled into programs and shared libraries with the following syntax: \begin{vindent} @@ -1147,11 +1161,21 @@ To run, this script requires debugging information for the named program and utrace support in the kernel. If you see a "pass 4a-time" build failure, check that your kernel supports utrace. +\subsubsection{Absolute variant} +\label{sec:absolutevariant} +A non-symbolic probe point such as +\texttt{process(PID).statement(ADDRESS).absolute} is analogous to +\newline\texttt{kernel.statement(ADDRESS).absolute} in that both use +raw, unverified virtual addresses and provide no \texttt{\$variables}. +The target \texttt{PID} parameter must identify a running process and +\texttt{ADDRESS} must identify a valid instruction address. All +threads of the listed process will be probed. This is a guru-level +probe. + \subsection{PROCFS probes} \index{PROCFS probes} - These probe points allow procfs pseudo-files in \texttt{/proc/systemtap/\textit{MODNAME}} to be created, read and written. Specify the name of the systemtap module as -- cgit From c232b6d78fb94df3dea3ea2076a3cf34e8de99a4 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 5 Jan 2010 10:29:27 +0100 Subject: Make publican invocation make -j safe. publican isn't make -j safe. So cheat a little, always create pdf and html at the same time, then make html depend on pdf build for copying. * doc/beginners/Makefile.am ($(SBG).pdf): Also generate html version. ($(SBG).html): Depend on pdf version, then copy. * doc/beginners/Makefile.in: Regenerated. --- doc/beginners/Makefile.am | 7 ++++--- doc/beginners/Makefile.in | 9 +++++---- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/doc/beginners/Makefile.am b/doc/beginners/Makefile.am index 29ffeaba..e3055967 100644 --- a/doc/beginners/Makefile.am +++ b/doc/beginners/Makefile.am @@ -13,12 +13,13 @@ BEGIN_INSTALL_DIR = $(DOC_INSTALL_DIR)/$(SBG) if BUILD_PUBLICAN all: $(SBG).pdf $(SBG)/index.html +# publican isn't make -j safe. So cheat a little, always create pdf and html +# at the same time, then make html depend on pdf build for copying. $(SBG).pdf: - publican build --formats=pdf --langs=en-US && \ + publican build --formats=pdf,html --langs=en-US && \ mv build/en-US/pdf/*$(SBG)*.pdf $(SBG).pdf -$(SBG)/index.html: - publican build --formats=html --langs=en-US && \ +$(SBG)/index.html: $(SBG).pdf mv build/en-US/html $(SBG) clean-local: diff --git a/doc/beginners/Makefile.in b/doc/beginners/Makefile.in index 2bae95f3..58cfb266 100644 --- a/doc/beginners/Makefile.in +++ b/doc/beginners/Makefile.in @@ -1,4 +1,4 @@ -# Makefile.in generated by automake 1.11 from Makefile.am. +# Makefile.in generated by automake 1.11.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, @@ -370,12 +370,13 @@ uninstall-am: uninstall-local @BUILD_PUBLICAN_TRUE@all: $(SBG).pdf $(SBG)/index.html +# publican isn't make -j safe. So cheat a little, always create pdf and html +# at the same time, then make html depend on pdf build for copying. @BUILD_PUBLICAN_TRUE@$(SBG).pdf: -@BUILD_PUBLICAN_TRUE@ publican build --formats=pdf --langs=en-US && \ +@BUILD_PUBLICAN_TRUE@ publican build --formats=pdf,html --langs=en-US && \ @BUILD_PUBLICAN_TRUE@ mv build/en-US/pdf/*$(SBG)*.pdf $(SBG).pdf -@BUILD_PUBLICAN_TRUE@$(SBG)/index.html: -@BUILD_PUBLICAN_TRUE@ publican build --formats=html --langs=en-US && \ +@BUILD_PUBLICAN_TRUE@$(SBG)/index.html: $(SBG).pdf @BUILD_PUBLICAN_TRUE@ mv build/en-US/html $(SBG) @BUILD_PUBLICAN_TRUE@clean-local: -- cgit From 23312a05753e948f7053beccc3dedfbe407a660a Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Tue, 5 Jan 2010 11:45:52 +0100 Subject: PR10732 declaration.exp empty-struct fails, resolve-fail passes erroneously. * testsuite/systemtap.base/declaration.exp: Remove test. --- testsuite/systemtap.base/declaration.exp | 20 -------------------- 1 file changed, 20 deletions(-) delete mode 100644 testsuite/systemtap.base/declaration.exp diff --git a/testsuite/systemtap.base/declaration.exp b/testsuite/systemtap.base/declaration.exp deleted file mode 100644 index f7452a14..00000000 --- a/testsuite/systemtap.base/declaration.exp +++ /dev/null @@ -1,20 +0,0 @@ -# Declaration tests. Specifically looking for resolution of -# DW_AT_declaration from another module - -set TEST_NAME "empty-struct resolve-fail" - -# this test just makes sure $device is still stubbed with DW_AT_declaration -set failscript { - probe\ module(\"libata\").function(\"ata_qc_issue\")\ \{\ print(\$qc->\$scsicmd->\$device->\$host->\$host_no)\ \}; -} - -stap_compile $TEST_NAME 0 $failscript - -set TEST_NAME "empty-struct resolve-pass" - -set passscript { - probe\ module(\"scsi_mod\").function(\"scsi_request_fn\")\ \{print(\$q)\} -} - -setup_xfail 10732 "*-*-*" -stap_compile $TEST_NAME 1 [concat $passscript $failscript ] -- cgit From 21e8e579ef10942bf2db3e1514026a6d132b1502 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Tue, 5 Jan 2010 15:18:57 +0100 Subject: bz6436 backtraces from uprobes This implements proper unwinding from uprobes in the presence of uretprobe trampolines. * runtime/stack.c (_stp_stack_print): Rework for uprobe context case and refactor a bit. * runtime/uprobes2/uprobes.h (GET_PC_URETPROBE_NONE): new constant * runtime/uprobes2/uprobes.c (uprobe_get_pc): Support translating the trampoline function from uprobe context in addition to uretprobe context. * runtime/uprobes/uprobes.h (GET_PC_URETPROBE_NONE): ditto * runtime/uprobes/uprobes.c (uprobe_get_pc): ditto * tapsets.cxx (uprobe_derived_probe_group::emit_module_decls): Initialize ri in context to GET_PC_URETPROBE_NONE in generated enter_uprobe_probe. * testsuite/systemtap.context/fib.stp: Add an option to do a backtrace on function entry. * testsuite/systemtap.context/fib.exp: Test backtrace in function entry (uprobe) probes. --- runtime/stack.c | 18 ++++++---- runtime/uprobes/uprobes.c | 71 +++++++++++++++++++++---------------- runtime/uprobes/uprobes.h | 4 +++ runtime/uprobes2/uprobes.c | 71 +++++++++++++++++++++---------------- runtime/uprobes2/uprobes.h | 4 +++ tapsets.cxx | 1 + testsuite/systemtap.context/fib.exp | 14 ++++++++ testsuite/systemtap.context/fib.stp | 3 ++ 8 files changed, 117 insertions(+), 69 deletions(-) diff --git a/runtime/stack.c b/runtime/stack.c index 50dde6e1..612fa010 100644 --- a/runtime/stack.c +++ b/runtime/stack.c @@ -132,25 +132,29 @@ static void _stp_stack_print(struct pt_regs *regs, int verbose, struct kretprobe _stp_print("\nReturning to : "); } _stp_symbol_print((unsigned long)_stp_ret_addr_r(pi)); - } else if (ri) { -#ifdef CONFIG_UTRACE /* as a proxy for presence of uprobes */ + _stp_print_char('\n'); +#ifdef CONFIG_UTRACE /* as a proxy for presence of uprobes... */ + } else if (ri && ri != GET_PC_URETPROBE_NONE) { if (verbose == SYM_VERBOSE_FULL) { _stp_print("Returning from: "); - _stp_usymbol_print(ri->rp->u.vaddr, tsk); /* otherwise this dereference fails */ + /* ... otherwise this dereference fails */ + _stp_usymbol_print(ri->rp->u.vaddr, tsk); _stp_print("\nReturning to : "); _stp_usymbol_print(ri->ret_addr, tsk); + _stp_print_char('\n'); } else _stp_func_print(ri->ret_addr, verbose, 0, tsk); #endif + } else if (verbose == SYM_VERBOSE_BRIEF) { + _stp_func_print(REG_IP(regs), verbose, 0, tsk); } else { _stp_print_char(' '); if (tsk) - _stp_usymbol_print(REG_IP(regs), tsk); + _stp_usymbol_print(REG_IP(regs), tsk); else - _stp_symbol_print(REG_IP(regs)); - } - if (verbose != SYM_VERBOSE_BRIEF) + _stp_symbol_print(REG_IP(regs)); _stp_print_char('\n'); + } } else if (pi) _stp_printf("%p %p ", (int64_t)(long)_stp_ret_addr_r(pi), (int64_t) REG_IP(regs)); else diff --git a/runtime/uprobes/uprobes.c b/runtime/uprobes/uprobes.c index cdb98707..5ccc7102 100644 --- a/runtime/uprobes/uprobes.c +++ b/runtime/uprobes/uprobes.c @@ -2599,37 +2599,46 @@ static void uretprobe_set_trampoline(struct uprobe_process *uproc, unsigned long uprobe_get_pc(struct uretprobe_instance *ri, unsigned long pc, unsigned long sp) { - struct uretprobe *rp; - struct uprobe_kimg *uk; - struct uprobe_process *uproc; - unsigned long trampoline_addr; - struct hlist_node *r; - struct uretprobe_instance *ret_inst; - - if (!ri) - return 0; - rp = ri->rp; - uk = (struct uprobe_kimg *)rp->u.kdata; - if (!uk) - return 0; - uproc = uk->ppt->uproc; - if (IS_ERR(uproc->uretprobe_trampoline_addr)) - return pc; - trampoline_addr = (unsigned long)uproc->uretprobe_trampoline_addr; - if (pc != trampoline_addr) - return pc; - r = &ri->hlist; - hlist_for_each_entry_from(ret_inst, r, hlist) { - if (ret_inst->ret_addr == trampoline_addr) - continue; - /* First handler with a stack pointer lower than the - address (or equal) must be the one. */ - if (ret_inst->sp == sp || compare_stack_ptrs(ret_inst->sp, sp)) - return ret_inst->ret_addr; - } - printk(KERN_ERR "Original return address for trampoline not found at " - "0x%lx pid/tgid=%d/%d\n", sp, current->pid, current->tgid); - return 0; + struct uretprobe *rp; + struct uprobe_kimg *uk; + struct uprobe_task *utask; + struct uprobe_process *uproc; + unsigned long trampoline_addr; + struct hlist_node *r; + struct uretprobe_instance *ret_inst; + + if (!ri) + return 0; + if (ri == GET_PC_URETPROBE_NONE) { + utask = uprobe_find_utask(current); + if (!utask) + return 0; + uproc = utask->uproc; + r = utask->uretprobe_instances.first; + } else { + rp = ri->rp; + uk = (struct uprobe_kimg *)rp->u.kdata; + if (!uk) + return 0; + uproc = uk->ppt->uproc; + r = &ri->hlist; + } + if (IS_ERR(uproc->uretprobe_trampoline_addr)) + return pc; + trampoline_addr = (unsigned long)uproc->uretprobe_trampoline_addr; + if (pc != trampoline_addr) + return pc; + hlist_for_each_entry_from(ret_inst, r, hlist) { + if (ret_inst->ret_addr == trampoline_addr) + continue; + /* First handler with a stack pointer lower than the + address (or equal) must be the one. */ + if (ret_inst->sp == sp || compare_stack_ptrs(ret_inst->sp, sp)) + return ret_inst->ret_addr; + } + printk(KERN_ERR "Original return address for trampoline not found at " + "0x%lx pid/tgid=%d/%d\n", sp, current->pid, current->tgid); + return 0; } EXPORT_SYMBOL_GPL(uprobe_get_pc); diff --git a/runtime/uprobes/uprobes.h b/runtime/uprobes/uprobes.h index e888f9e8..80725f23 100644 --- a/runtime/uprobes/uprobes.h +++ b/runtime/uprobes/uprobes.h @@ -99,7 +99,11 @@ extern void unmap_uretprobe(struct uretprobe *rp); * Given a program counter, translate it back to the original address * if it is the address of the trampoline. sp is the stack pointer for * the frame that corresponds to the address. + * + * When not called from a uretprobe hander, pass GET_PC_URETPROBE_NONE + * instead of a uretprobe_instance. */ +#define GET_PC_URETPROBE_NONE ((struct uretprobe_instance *)-1L) extern unsigned long uprobe_get_pc(struct uretprobe_instance *ri, unsigned long pc, unsigned long sp); diff --git a/runtime/uprobes2/uprobes.c b/runtime/uprobes2/uprobes.c index 02941e26..623855ff 100644 --- a/runtime/uprobes2/uprobes.c +++ b/runtime/uprobes2/uprobes.c @@ -2840,37 +2840,46 @@ static void uretprobe_set_trampoline(struct uprobe_process *uproc, unsigned long uprobe_get_pc(struct uretprobe_instance *ri, unsigned long pc, unsigned long sp) { - struct uretprobe *rp; - struct uprobe_kimg *uk; - struct uprobe_process *uproc; - unsigned long trampoline_addr; - struct hlist_node *r; - struct uretprobe_instance *ret_inst; - - if (!ri) - return 0; - rp = ri->rp; - uk = (struct uprobe_kimg *)rp->u.kdata; - if (!uk) - return 0; - uproc = uk->ppt->uproc; - if (IS_ERR(uproc->uretprobe_trampoline_addr)) - return pc; - trampoline_addr = (unsigned long)uproc->uretprobe_trampoline_addr; - if (pc != trampoline_addr) - return pc; - r = &ri->hlist; - hlist_for_each_entry_from(ret_inst, r, hlist) { - if (ret_inst->ret_addr == trampoline_addr) - continue; - /* First handler with a stack pointer lower than the - address (or equal) must be the one. */ - if (ret_inst->sp == sp || compare_stack_ptrs(ret_inst->sp, sp)) - return ret_inst->ret_addr; - } - printk(KERN_ERR "Original return address for trampoline not found at " - "0x%lx pid/tgid=%d/%d\n", sp, current->pid, current->tgid); - return 0; + struct uretprobe *rp; + struct uprobe_kimg *uk; + struct uprobe_task *utask; + struct uprobe_process *uproc; + unsigned long trampoline_addr; + struct hlist_node *r; + struct uretprobe_instance *ret_inst; + + if (!ri) + return 0; + if (ri == GET_PC_URETPROBE_NONE) { + utask = uprobe_find_utask(current); + if (!utask) + return 0; + uproc = utask->uproc; + r = utask->uretprobe_instances.first; + } else { + rp = ri->rp; + uk = (struct uprobe_kimg *)rp->u.kdata; + if (!uk) + return 0; + uproc = uk->ppt->uproc; + r = &ri->hlist; + } + if (IS_ERR(uproc->uretprobe_trampoline_addr)) + return pc; + trampoline_addr = (unsigned long)uproc->uretprobe_trampoline_addr; + if (pc != trampoline_addr) + return pc; + hlist_for_each_entry_from(ret_inst, r, hlist) { + if (ret_inst->ret_addr == trampoline_addr) + continue; + /* First handler with a stack pointer lower than the + address (or equal) must be the one. */ + if (ret_inst->sp == sp || compare_stack_ptrs(ret_inst->sp, sp)) + return ret_inst->ret_addr; + } + printk(KERN_ERR "Original return address for trampoline not found at " + "0x%lx pid/tgid=%d/%d\n", sp, current->pid, current->tgid); + return 0; } EXPORT_SYMBOL_GPL(uprobe_get_pc); diff --git a/runtime/uprobes2/uprobes.h b/runtime/uprobes2/uprobes.h index 5d2a826e..c4e1f59c 100644 --- a/runtime/uprobes2/uprobes.h +++ b/runtime/uprobes2/uprobes.h @@ -92,7 +92,11 @@ extern void unmap_uretprobe(struct uretprobe *rp); * Given a program counter, translate it back to the original address * if it is the address of the trampoline. sp is the stack pointer for * the frame that corresponds to the address. + * + * When not called from a uretprobe hander, pass GET_PC_URETPROBE_NONE + * instead of a uretprobe_instance. */ +#define GET_PC_URETPROBE_NONE ((struct uretprobe_instance *)-1L) extern unsigned long uprobe_get_pc(struct uretprobe_instance *ri, unsigned long pc, unsigned long sp); diff --git a/tapsets.cxx b/tapsets.cxx index bac47761..0936eacd 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -4735,6 +4735,7 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "if (sup->spec_index < 0 ||" << "sup->spec_index >= " << probes.size() << ") return;"; // XXX: should not happen s.op->newline() << "c->regs = regs;"; + s.op->newline() << "c->ri = GET_PC_URETPROBE_NONE;"; // Make it look like the IP is set as it would in the actual user // task when calling real probe handler. Reset IP regs on return, so diff --git a/testsuite/systemtap.context/fib.exp b/testsuite/systemtap.context/fib.exp index cc4d75a1..5026e5d0 100644 --- a/testsuite/systemtap.context/fib.exp +++ b/testsuite/systemtap.context/fib.exp @@ -35,3 +35,17 @@ expect { } wait if {$fibcalls == 18 && $maincalls == 2} { pass "$test ($fibcalls $maincalls)" } { fail "$test ($fibcalls $maincalls)" } + +spawn stap -c "$testexe 10" -- $teststp --entry +set fibcalls 0 +set maincalls 0 +expect { + -timeout 120 + -re {^fib[^\r\n]*[\r\n]} { incr fibcalls; exp_continue } + -re {^main[^\r\n]*[\r\n]} { incr maincalls; exp_continue } + -re {^[^\r\n]*[\r\n]} {exp_continue} + timeout { fail "$test (timeout)" } + eof { } +} +wait +if {$fibcalls == 55 && $maincalls == 10} { pass "$test ($fibcalls $maincalls)" } { fail "$test ($fibcalls $maincalls)" } diff --git a/testsuite/systemtap.context/fib.stp b/testsuite/systemtap.context/fib.stp index 85c2fc1d..fe2415f5 100644 --- a/testsuite/systemtap.context/fib.stp +++ b/testsuite/systemtap.context/fib.stp @@ -5,13 +5,16 @@ probe process("fib").function("fib").call { depth++ if (depth > max_depth) { max_depth = depth + %( $# > 0 %? print_ubacktrace_brief(); printf("\n") %) } } probe process("fib").function("fib").return { + %( $# == 0 %? if (depth == max_depth) { print_ubacktrace_brief() printf("\n") } + %) depth-- } -- cgit From 11059140a279e954e175d9c2e34ab4ea4670130d Mon Sep 17 00:00:00 2001 From: Roland McGrath Date: Tue, 5 Jan 2010 12:50:12 -0800 Subject: %define -> %global in .spec file * systemtap.spec: Use %global in place of %define throughout, it's the recommended syntax. --- systemtap.spec | 64 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/systemtap.spec b/systemtap.spec index 2ae99e58..17eff400 100644 --- a/systemtap.spec +++ b/systemtap.spec @@ -1,14 +1,14 @@ -%{!?with_sqlite: %define with_sqlite 1} -%{!?with_docs: %define with_docs 1} -%{!?with_crash: %define with_crash 0} -%{!?with_rpm: %define with_rpm 1} -%{!?with_bundled_elfutils: %define with_bundled_elfutils 0} -%{!?elfutils_version: %define elfutils_version 0.127} -%{!?pie_supported: %define pie_supported 1} -%{!?with_grapher: %define with_grapher 1} -%{!?with_boost: %define with_boost 0} -%{!?with_publican: %define with_publican 1} -%{!?publican_brand: %define publican_brand fedora} +%{!?with_sqlite: %global with_sqlite 1} +%{!?with_docs: %global with_docs 1} +%{!?with_crash: %global with_crash 0} +%{!?with_rpm: %global with_rpm 1} +%{!?with_bundled_elfutils: %global with_bundled_elfutils 0} +%{!?elfutils_version: %global elfutils_version 0.127} +%{!?pie_supported: %global pie_supported 1} +%{!?with_grapher: %global with_grapher 1} +%{!?with_boost: %global with_boost 0} +%{!?with_publican: %global with_publican 1} +%{!?publican_brand: %global publican_brand fedora} Name: systemtap Version: 1.1 @@ -48,7 +48,7 @@ BuildRequires: nss-devel nss-tools pkgconfig Source1: elfutils-%{elfutils_version}.tar.gz Patch1: elfutils-portability.patch BuildRequires: m4 -%define setup_elfutils -a1 +%global setup_elfutils -a1 %else BuildRequires: elfutils-devel >= %{elfutils_version} %endif @@ -193,63 +193,63 @@ cd .. %if %{with_bundled_elfutils} # Build our own copy of elfutils. -%define elfutils_config --with-elfutils=elfutils-%{elfutils_version} +%global elfutils_config --with-elfutils=elfutils-%{elfutils_version} # We have to prevent the standard dependency generation from identifying # our private elfutils libraries in our provides and requires. -%define _use_internal_dependency_generator 0 -%define filter_eulibs() /bin/sh -c "%{1} | sed '/libelf/d;/libdw/d;/libebl/d'" -%define __find_provides %{filter_eulibs /usr/lib/rpm/find-provides} -%define __find_requires %{filter_eulibs /usr/lib/rpm/find-requires} +%global _use_internal_dependency_generator 0 +%global filter_eulibs() /bin/sh -c "%{1} | sed '/libelf/d;/libdw/d;/libebl/d'" +%global __find_provides %{filter_eulibs /usr/lib/rpm/find-provides} +%global __find_requires %{filter_eulibs /usr/lib/rpm/find-requires} # This will be needed for running stap when not installed, for the test suite. -%define elfutils_mflags LD_LIBRARY_PATH=`pwd`/lib-elfutils +%global elfutils_mflags LD_LIBRARY_PATH=`pwd`/lib-elfutils %endif # Enable/disable the sqlite coverage testing support %if %{with_sqlite} -%define sqlite_config --enable-sqlite +%global sqlite_config --enable-sqlite %else -%define sqlite_config --disable-sqlite +%global sqlite_config --disable-sqlite %endif # Enable/disable the crash extension %if %{with_crash} -%define crash_config --enable-crash +%global crash_config --enable-crash %else -%define crash_config --disable-crash +%global crash_config --disable-crash %endif # Enable/disable the code to find and suggest needed rpms %if %{with_rpm} -%define rpm_config --with-rpm +%global rpm_config --with-rpm %else -%define rpm_config --without-rpm +%global rpm_config --without-rpm %endif %if %{with_docs} -%define docs_config --enable-docs +%global docs_config --enable-docs %else -%define docs_config --disable-docs +%global docs_config --disable-docs %endif # Enable pie as configure defaults to disabling it %if %{pie_supported} -%define pie_config --enable-pie +%global pie_config --enable-pie %else -%define pie_config --disable-pie +%global pie_config --disable-pie %endif %if %{with_grapher} -%define grapher_config --enable-grapher +%global grapher_config --enable-grapher %else -%define grapher_config --disable-grapher +%global grapher_config --disable-grapher %endif %if %{with_publican} -%define publican_config --enable-publican --with-publican-brand=%{publican_brand} +%global publican_config --enable-publican --with-publican-brand=%{publican_brand} %else -%define publican_config --disable-publican +%global publican_config --disable-publican %endif -- cgit From de0c57f3a607f31b4860bc7392d3ce5b9a693a7a Mon Sep 17 00:00:00 2001 From: David Smith Date: Tue, 5 Jan 2010 15:22:21 -0600 Subject: Partial PR 10848 fix. Added '-DMAXMEMORY=NUM' processing. * runtime/alloc.c (_stp_mem_debug_validate): New debug function. (_stp_kmalloc): Added MAXMEMORY code to check size of memory used by module. (_stp_kzalloc): Ditto. (_stp_vmalloc): Ditto. (_stp_alloc_percpu): Ditto. (_stp_kmalloc_node): Ditto. --- runtime/alloc.c | 132 ++++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 124 insertions(+), 8 deletions(-) diff --git a/runtime/alloc.c b/runtime/alloc.c index fa85fc41..810ec5d5 100644 --- a/runtime/alloc.c +++ b/runtime/alloc.c @@ -172,18 +172,99 @@ static void _stp_mem_debug_free(void *addr, enum _stp_memtype type) return; } + +static void _stp_mem_debug_validate(void *addr) +{ + int found = 0; + struct list_head *p, *tmp; + struct _stp_mem_entry *m = NULL; + + spin_lock(&_stp_mem_lock); + list_for_each_safe(p, tmp, &_stp_mem_list) { + m = list_entry(p, struct _stp_mem_entry, list); + if (m->addr == addr) { + found = 1; + break; + } + } + spin_unlock(&_stp_mem_lock); + if (!found) { + printk("SYSTEMTAP ERROR: Couldn't validate memory %p\n", + addr); + return; + } + if (m->magic != MEM_MAGIC) { + printk("SYSTEMTAP ERROR: Memory at %p corrupted!!\n", addr); + return; + } + + switch (m->type) { + case MEM_KMALLOC: + _stp_check_mem_fence(addr, m->len); + break; + case MEM_PERCPU: + /* do nothing */ + break; + case MEM_VMALLOC: + _stp_check_mem_fence(addr, m->len); + break; + default: + printk("SYSTEMTAP ERROR: Attempted to validate memory at addr %p len=%d with unknown allocation type.\n", addr, (int)m->len); + } + + return; +} +#endif + +/* #define MAXMEMORY 8192 */ +/* + * If MAXMEMORY is defined to a value (stap -DMAXMEMORY=8192 ...) then + * every memory allocation is checked to make sure the systemtap + * module doesn't use more than MAXMEMORY of memory. MAXMEMORY is + * specified in kilobytes, so, for example, '8192' means that the + * systemtap module won't use more than 8 megabytes of memory. + * + * Note 1: This size does include the size of the module itself, plus + * any additional allocations. + * + * Note 2: Since we can't be ensured that the module transport is set + * up when a memory allocation problem happens, this code can't + * directly report an error back to a user (so instead it uses + * 'printk'). If the modules transport has been set up, the code that + * calls the memory allocation functions + * (_stp_kmalloc/_stp_kzalloc/etc.) should report an error directly wto + * the user. + * + * Note 3: This only tracks direct allocations by the systemtap + * runtime. This does not track indirect allocations (such as done by + * kprobes/uprobes/etc. internals). + */ + +#ifdef MAXMEMORY +#ifndef STAPCONF_GRSECURITY +#define _STP_MODULE_CORE_SIZE (THIS_MODULE->core_size) +#else +#define _STP_MODULE_CORE_SIZE (THIS_MODULE->core_size_rw) +#endif #endif static void *_stp_kmalloc(size_t size) { + void *ret; +#ifdef MAXMEMORY + if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) + > (MAXMEMORY * 1024)) { + return NULL; + } +#endif #ifdef DEBUG_MEM - void *ret = kmalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS); + ret = kmalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS); if (likely(ret)) { _stp_allocated_memory += size; ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC); } #else - void *ret = kmalloc(size, STP_ALLOC_FLAGS); + ret = kmalloc(size, STP_ALLOC_FLAGS); if (likely(ret)) { _stp_allocated_memory += size; } @@ -194,15 +275,22 @@ static void *_stp_kmalloc(size_t size) static void *_stp_kzalloc(size_t size) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) { + void *ret; +#ifdef MAXMEMORY + if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) + > (MAXMEMORY * 1024)) { + return NULL; + } +#endif #ifdef DEBUG_MEM - void *ret = kmalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS); + ret = kmalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS); if (likely(ret)) { _stp_allocated_memory += size; ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC); memset (ret, 0, size); } #else - void *ret = kmalloc(size, STP_ALLOC_FLAGS); + ret = kmalloc(size, STP_ALLOC_FLAGS); if (likely(ret)) { _stp_allocated_memory += size; memset (ret, 0, size); @@ -212,14 +300,21 @@ static void *_stp_kzalloc(size_t size) } #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) */ { + void *ret; +#ifdef MAXMEMORY + if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) + > (MAXMEMORY * 1024)) { + return NULL; + } +#endif #ifdef DEBUG_MEM - void *ret = kzalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS); + ret = kzalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS); if (likely(ret)) { _stp_allocated_memory += size; ret = _stp_mem_debug_setup(ret, size, MEM_KMALLOC); } #else - void *ret = kzalloc(size, STP_ALLOC_FLAGS); + ret = kzalloc(size, STP_ALLOC_FLAGS); if (likely(ret)) { _stp_allocated_memory += size; } @@ -230,14 +325,21 @@ static void *_stp_kzalloc(size_t size) static void *_stp_vmalloc(unsigned long size) { + void *ret; +#ifdef MAXMEMORY + if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) + > (MAXMEMORY * 1024)) { + return NULL; + } +#endif #ifdef DEBUG_MEM - void *ret = __vmalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS, PAGE_KERNEL); + ret = __vmalloc(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS, PAGE_KERNEL); if (likely(ret)) { _stp_allocated_memory += size; ret = _stp_mem_debug_setup(ret, size, MEM_VMALLOC); } #else - void *ret = __vmalloc(size, STP_ALLOC_FLAGS, PAGE_KERNEL); + ret = __vmalloc(size, STP_ALLOC_FLAGS, PAGE_KERNEL); if (likely(ret)) { _stp_allocated_memory += size; } @@ -258,6 +360,14 @@ static void *_stp_alloc_percpu(size_t size) if (size > _STP_MAX_PERCPU_SIZE) return NULL; +#ifdef MAXMEMORY + if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + + (size * num_online_cpus())) + > (MAXMEMORY * 1024)) { + return NULL; + } +#endif + #ifdef STAPCONF_ALLOC_PERCPU_ALIGN ret = __alloc_percpu(size, 8); #else @@ -287,6 +397,12 @@ static void *_stp_alloc_percpu(size_t size) static void *_stp_kmalloc_node(size_t size, int node) { void *ret; +#ifdef MAXMEMORY + if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) + > (MAXMEMORY * 1024)) { + return NULL; + } +#endif #ifdef DEBUG_MEM ret = kmalloc_node(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS, node); if (likely(ret)) { -- cgit From 53d480f81d7c8232b2bfd5728baddcef50fe67ff Mon Sep 17 00:00:00 2001 From: Wenji Huang Date: Wed, 6 Jan 2010 16:14:09 +0800 Subject: Manual cleanup Fix typos and comment unused text. --- stap-authorize-server-cert.8.in | 4 +- stap-authorize-signing-cert.8.in | 4 +- stap-client.8.in | 5 +- stap-server.8.in | 2 +- stap.1.in | 156 +++++++++++++++++++-------------------- staprun.8.in | 2 +- 6 files changed, 85 insertions(+), 88 deletions(-) diff --git a/stap-authorize-server-cert.8.in b/stap-authorize-server-cert.8.in index 5fae0237..6ea245b1 100644 --- a/stap-authorize-server-cert.8.in +++ b/stap-authorize-server-cert.8.in @@ -52,7 +52,7 @@ server\[aq]s certificate database. On the server host, for servers started by the \fIstap\-server\fR service, this database can be found in \fI/var/lib/stap\-server/.systemtap/ssl/server/\fR. -Ror servers run by other non\-root users, +For servers run by other non\-root users, this database can be found in .I $HOME/.systemtap/ssl/server/\fP. For root users (EUID=0), it can be found in @@ -112,7 +112,7 @@ Server certificate for servers started by the \fIstap\-server\fR service. .IR certutil .SH BUGS -Use the Bugzilla link off of the project web page or our mailing list. +Use the Bugzilla link of the project web page or our mailing list. .nh .BR http://sources.redhat.com/systemtap/ ", " . .hy diff --git a/stap-authorize-signing-cert.8.in b/stap-authorize-signing-cert.8.in index db9f49c5..d1157544 100644 --- a/stap-authorize-signing-cert.8.in +++ b/stap-authorize-signing-cert.8.in @@ -49,7 +49,7 @@ server\[aq]s certificate database. On the server host, for servers started by the \fIstap\-server\fR service, this database can be found in \fI/var/lib/stap\-server/.systemtap/ssl/server/\fR. -Ror servers run by other non\-root users, +For servers run by other non\-root users, this database can be found in .I $HOME/.systemtap/ssl/server/\fP. For root users (EUID=0), it can be found in @@ -101,7 +101,7 @@ Signing certificate for servers started by the \fIstap\-server\fR service. .IR certutil .SH BUGS -Use the Bugzilla link off of the project web page or our mailing list. +Use the Bugzilla link of the project web page or our mailing list. .nh .BR http://sources.redhat.com/systemtap/ ", " . .hy diff --git a/stap-client.8.in b/stap-client.8.in index c8db45ee..f4ca86f6 100644 --- a/stap-client.8.in +++ b/stap-client.8.in @@ -129,7 +129,8 @@ manual page for more details. .PP The trustworthiness of other servers may also be asserted for the duration of one invocation of \fIstap\-client\fR -by using the.B \-\-ssl +by using the +.B \-\-ssl option one or more times (see .I OPTIONS above). Servers whose certificates are contained in the additional databases @@ -226,7 +227,7 @@ Server certificate for servers started by the \fIstap\-server\fR service. .IR certutil .SH BUGS -Use the Bugzilla link off of the project web page or our mailing list. +Use the Bugzilla link of the project web page or our mailing list. .nh .BR http://sources.redhat.com/systemtap/ ", " . .hy diff --git a/stap-server.8.in b/stap-server.8.in index 3994a17d..1c69ca1c 100644 --- a/stap-server.8.in +++ b/stap-server.8.in @@ -403,7 +403,7 @@ Location of installed kernels. .IR certutil .SH BUGS -Use the Bugzilla link off of the project web page or our mailing list. +Use the Bugzilla link of the project web page or our mailing list. .nh .BR http://sources.redhat.com/systemtap/ ", " . .hy diff --git a/stap.1.in b/stap.1.in index 4be443b7..6706ad7f 100644 --- a/stap.1.in +++ b/stap.1.in @@ -215,41 +215,36 @@ If the size of output file will exceed output files exceed .B N , systemtap removes the oldest output file. You can omit the second argument. -.TP -.B \-\-kelf -For names and addresses of functions to probe, -consult the symbol tables in the kernel and modules. -This can be useful if your kernel and/or modules were compiled -without debugging information, or the function you want to probe -is in an assembly-language file built without debugging information. -See the -.B "MAKING DO WITH SYMBOL TABLES" -section for more information. -.TP -.BI \-\-kmap [=FILE] -For names and addresses of kernel functions to probe, -consult the symbol table in the indicated text file. -The default is /boot/System.map-VERSION. -The contents of this file should be in the form of the default output from -.IR nm (1). -Only symbols of type T or t are used. -If you specify /proc/kallsyms or some other file in that format, -where lines for module symbols contain a fourth column, -reading of the symbol table stops with the first module symbol -(which should be right after the last kernel symbol). -As with -.BR \-\-kelf , -the symbol table in each module's .ko file will also be consulted. -See the -.B "MAKING DO WITH SYMBOL TABLES" -section for more information. -.TP -.B \-\-ignore\-vmlinux -For testing, act as though neither the uncompressed kernel (vmlinux) -nor the kernel debugging information can be found. -.TP -.B \-\-ignore\-dwarf -For testing, act as though vmlinux and modules lack debugging information. +\" PR6864: disable temporarily +\".TP +\".B \-\-kelf +\"For names and addresses of functions to probe, +\"consult the symbol tables in the kernel and modules. +\"This can be useful if your kernel and/or modules were compiled +\"without debugging information, or the function you want to probe +\"is in an assembly-language file built without debugging information. +\"See the +\".B "MAKING DO WITH SYMBOL TABLES" +\"section for more information. +\".TP +\".BI \-\-kmap [=FILE] +\"For names and addresses of kernel functions to probe, +\"consult the symbol table in the indicated text file. +\"The default is /boot/System.map-VERSION. +\"The contents of this file should be in the form of the default output from +\".IR nm (1). +\"Only symbols of type T or t are used. +\"If you specify /proc/kallsyms or some other file in that format, +\"where lines for module symbols contain a fourth column, +\"reading of the symbol table stops with the first module symbol +\"(which should be right after the last kernel symbol). +\"As with +\".BR \-\-kelf , +\"the symbol table in each module's .ko file will also be consulted. +\"See the +\".B "MAKING DO WITH SYMBOL TABLES" +\"section for more information. +\" --ignore-{vmlinux,dwarf} shouldn't be visible .TP .B \-\-skip\-badvars Ignore out of context variables and substitute with literal 0. @@ -361,7 +356,7 @@ variables usable. .PP The TRUE-TOKENS and FALSE-TOKENS are zero or more general parser tokens (possibly including nested preprocessor conditionals), and are -pasted into the input stream if the condition is true or false. For +passed into the input stream if the condition is true or false. For example, the following code induces a parse error unless the target kernel version is newer than 2.6.5: .SAMPLE @@ -391,7 +386,7 @@ invocation. .PP Scalar variables are implicitly typed as either string or integer. Associative arrays also have a string or integer value, and a -a tuple of strings and/or integers serving as a key. Here are a +tuple of strings and/or integers serving as a key. Here are a few basic expressions. .SAMPLE var1 = 5 @@ -1168,48 +1163,49 @@ have overloaded the system and an exit is triggered. By default, overload processing is turned on for all modules. If you would like to disable overload processing, define STP_NO_OVERLOAD. -.SH MAKING DO WITH SYMBOL TABLES -Systemtap performs best when it has access to the debugging information -associated with your kernel and modules. -However, if this information is not available, -systemtap can still support probing of function entries and returns -using symbols read from vmlinux and/or the modules in /lib/modules. -Systemtap can also read the kernel symbol table from a text file -such as /boot/System.map or /proc/kallsyms. -See the -.B \-\-kelf -and -.B \-\-kmap -options. -.PP -If systemtap finds relevant debugging information, -it will use it even if you specify -.B \-\-kelf -or -.BR \-\-kmap . -.PP -Without debugging information, systemtap cannot support the -following types of language constructs: -.IP \(bu 4 -probe specifications that refer to source files or line numbers -.IP \(bu 4 -probe specifications that refer to inline functions -.IP \(bu 4 -statements that refer to $target variables -.IP \(bu 4 -statements that refer to @cast() variables -.IP \(bu 4 -tapset-defined variables defined using any of the above constructs. -In particular, at this writing, -the prologue blocks for certain aliases in the syscall tapset -(e.g., syscall.open) contain "if" statements that refer to $target variables. -If your script refers to any such aliases, -systemtap must have access to the kernel's debugging information. -.PP -Most T and t symbols correspond to function entry points, but some do not. -Based only on the symbol table, systemtap cannot tell the difference. -Placing return probes on symbols that aren't entry points -will most likely lead to kernel stack corruption. +.\" PR6864: disable temporarily +.\".SH MAKING DO WITH SYMBOL TABLES +.\"Systemtap performs best when it has access to the debugging information +.\"associated with your kernel and modules. +.\"However, if this information is not available, +.\"systemtap can still support probing of function entries and returns +.\"using symbols read from vmlinux and/or the modules in /lib/modules. +.\"Systemtap can also read the kernel symbol table from a text file +.\"such as /boot/System.map or /proc/kallsyms. +.\"See the +.\".B \-\-kelf +.\"and +.\".B \-\-kmap +.\"options. +.\".PP +.\"If systemtap finds relevant debugging information, +.\"it will use it even if you specify +.\".B \-\-kelf +.\"or +.\".BR \-\-kmap . +.\".PP +.\"Without debugging information, systemtap cannot support the +.\"following types of language constructs: +.\".IP \(bu 4 +.\"probe specifications that refer to source files or line numbers +.\".IP \(bu 4 +.\"probe specifications that refer to inline functions +.\".IP \(bu 4 +.\"statements that refer to $target variables +.\".IP \(bu 4 +.\"statements that refer to @cast() variables +.\".IP \(bu 4 +.\"tapset-defined variables defined using any of the above constructs. +.\"In particular, at this writing, +.\"the prologue blocks for certain aliases in the syscall tapset +.\"(e.g., syscall.open) contain "if" statements that refer to $target variables. +.\"If your script refers to any such aliases, +.\"systemtap must have access to the kernel's debugging information. +.\".PP +.\"Most T and t symbols correspond to function entry points, but some do not. +.\"Based only on the symbol table, systemtap cannot tell the difference. +.\"Placing return probes on symbols that aren't entry points +.\"will most likely lead to kernel stack corruption. .SH FILES .\" consider autoconf-substituting these directories @@ -1263,7 +1259,7 @@ unloading. .IR gdb (1) .SH BUGS -Use the Bugzilla link off of the project web page or our mailing list. +Use the Bugzilla link of the project web page or our mailing list. .nh .BR http://sources.redhat.com/systemtap/ , . .hy diff --git a/staprun.8.in b/staprun.8.in index ee071945..7ddedd1c 100644 --- a/staprun.8.in +++ b/staprun.8.in @@ -215,7 +215,7 @@ user and not be world writable. .IR stapex (3stap) .SH BUGS -Use the Bugzilla link off of the project web page or our mailing list. +Use the Bugzilla link of the project web page or our mailing list. .nh .BR http://sources.redhat.com/systemtap/ ", " . .hy -- cgit From d6b183074686940e8533b6fa377b098ec87a7f12 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Wed, 6 Jan 2010 16:24:56 +0100 Subject: Fix get_cfa_ops failure on shared libraries. The fix for PR10923 (fafeaf) wasn't completely correct. All cfa lookups need to be done through the relative pc (without bias) of the module we are looking in. * dwflpp.cxx (translate_location): Call get_cfa_ops with relative pc. --- dwflpp.cxx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/dwflpp.cxx b/dwflpp.cxx index 4fb0d54e..0d41dab8 100644 --- a/dwflpp.cxx +++ b/dwflpp.cxx @@ -1729,9 +1729,9 @@ dwflpp::translate_location(struct obstack *pool, e->tok); } - // get_cfa_ops works on the dw address space, pc is relative to current - // module, so add do need to add module_bias. - Dwarf_Op *cfa_ops = get_cfa_ops (pc + module_bias); + // pc is relative to current module, which is what get_cfa_ops + // and c_translate_location expects. + Dwarf_Op *cfa_ops = get_cfa_ops (pc); return c_translate_location (pool, &loc2c_error, this, &loc2c_emit_address, 1, 0 /* PR9768 */, -- cgit From 6ac9e2adb81122c92aa180d628a1d6c226ada6aa Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Wed, 6 Jan 2010 17:27:25 +0100 Subject: grapher example with backtraces in events * testsuite/systemtap.examples/profiling/graphcall.stp : new file --- testsuite/systemtap.examples/profiling/graphcall.stp | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 testsuite/systemtap.examples/profiling/graphcall.stp diff --git a/testsuite/systemtap.examples/profiling/graphcall.stp b/testsuite/systemtap.examples/profiling/graphcall.stp new file mode 100644 index 00000000..db96b728 --- /dev/null +++ b/testsuite/systemtap.examples/profiling/graphcall.stp @@ -0,0 +1,19 @@ +#! /usr/bin/env stap + +# When the output of this script is fed to stapgraph, it produces a +# mousable event line with events at each call of interest. When the +# event is hovered over, the backtrace is displayed in stapgraph. + +probe begin +{ + printf("%%DataSet:call 75 ff0000 discreet\n") + printf("call %%Title:Calls to %s\n", @2) + printf ("call %%XAxisTitle:Time\n") + printf ("%%LineEnd:0\n") +} + +probe process(@1).function(@2).call { + printf("call %d ", gettimeofday_ms()) + print_ubacktrace_brief(); + printf("%c", 0) +} -- cgit From e0c56962dbc24692c699f7f9ba3bf267c3807921 Mon Sep 17 00:00:00 2001 From: William Cohen Date: Thu, 7 Jan 2010 10:20:55 -0500 Subject: Make all buildok tests executable. --- testsuite/buildok/irq.stp | 0 testsuite/buildok/logging.stp | 0 testsuite/buildok/pr10678.stp | 0 testsuite/buildok/scheduler-test-tracepoints.stp | 0 testsuite/buildok/semicolon.stp | 0 testsuite/buildok/vm.tracepoints.kmalloc.stp | 0 testsuite/buildok/vm.tracepoints.stp | 0 7 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 testsuite/buildok/irq.stp mode change 100644 => 100755 testsuite/buildok/logging.stp mode change 100644 => 100755 testsuite/buildok/pr10678.stp mode change 100644 => 100755 testsuite/buildok/scheduler-test-tracepoints.stp mode change 100644 => 100755 testsuite/buildok/semicolon.stp mode change 100644 => 100755 testsuite/buildok/vm.tracepoints.kmalloc.stp mode change 100644 => 100755 testsuite/buildok/vm.tracepoints.stp diff --git a/testsuite/buildok/irq.stp b/testsuite/buildok/irq.stp old mode 100644 new mode 100755 diff --git a/testsuite/buildok/logging.stp b/testsuite/buildok/logging.stp old mode 100644 new mode 100755 diff --git a/testsuite/buildok/pr10678.stp b/testsuite/buildok/pr10678.stp old mode 100644 new mode 100755 diff --git a/testsuite/buildok/scheduler-test-tracepoints.stp b/testsuite/buildok/scheduler-test-tracepoints.stp old mode 100644 new mode 100755 diff --git a/testsuite/buildok/semicolon.stp b/testsuite/buildok/semicolon.stp old mode 100644 new mode 100755 diff --git a/testsuite/buildok/vm.tracepoints.kmalloc.stp b/testsuite/buildok/vm.tracepoints.kmalloc.stp old mode 100644 new mode 100755 diff --git a/testsuite/buildok/vm.tracepoints.stp b/testsuite/buildok/vm.tracepoints.stp old mode 100644 new mode 100755 -- cgit From 9fa29c5277f3e3f4525ff3335a2cbc2b518c2010 Mon Sep 17 00:00:00 2001 From: Mark Wielaard Date: Thu, 7 Jan 2010 17:54:28 +0100 Subject: Fix multi-piece constant failure in vta-test.exp on 32bit systems. Commit 73b5e9 "Make sure loc2c declare_noncontig_union for different locs don't overlap", wasn't complete. It only took into account having a piece becuase of a noncontiguous loc and a constant loc together. But pieces can be nested deeper (newer gcc outputs multiple constant locations for one piece on 32bit systems). This patch keeps track of the piece declaration depth. Another approach could have been to have each sub-piece in its own local scope, but keeping track of the depth and naming the temporary unions distinct fitted the current code better. It currently only supports a depth of 10. An error will be emitted if a location construct needs more than 10 pieces to be assembled. * loc2c.c (declare_noncontig_union): Take depth argument. Always use the same name for the union (u_pieces). (translate_base_fetch): Take depth argument. Use it to calculate union names. (translate_base_store): Likewise. (c_translate_fetch): Pass in depth zero. (c_translate_store): Likewise. (c_translate_pointer): Likewise. (c_translate_pointer_store): Likewise. --- loc2c.c | 76 ++++++++++++++++++++++++++++++++--------------------------------- 1 file changed, 38 insertions(+), 38 deletions(-) diff --git a/loc2c.c b/loc2c.c index a7473784..161df763 100644 --- a/loc2c.c +++ b/loc2c.c @@ -1530,12 +1530,16 @@ discontiguify (struct obstack *pool, int indent, struct location *loc, uint32_t p4; } pieces __attribute__ ((packed)); uint64_t whole; - } u; + } u_pieces; */ static void declare_noncontig_union (struct obstack *pool, int indent, - struct location **input, struct location *loc) + struct location **input, struct location *loc, + int depth) { + if (depth > 9) + FAIL (loc, N_("declaring noncontig union for depth > 9, too many pieces")); + obstack_printf (pool, "%*sunion {\n", indent++ * 2, ""); obstack_printf (pool, "%*schar bytes[%" PRIu64 "];\n", @@ -1561,17 +1565,7 @@ declare_noncontig_union (struct obstack *pool, int indent, obstack_printf (pool, "%*suint%" PRIu64 "_t whole;\n", indent * 2, "", loc->byte_size * 8); - // Different loc types could be in the same syntactical scope, so - // should be named differently. - const char *uname; - if (loc->type == loc_noncontiguous) - uname = "u_pieces"; - else if (loc->type == loc_constant) - uname = "u_const"; - else - abort(); - - obstack_printf (pool, "%*s} %s;\n", --indent * 2, "", uname); + obstack_printf (pool, "%*s} u_pieces%d;\n", --indent * 2, "", depth); loc = new_synthetic_loc (pool, *input, false); loc->type = loc_decl; @@ -1642,7 +1636,8 @@ get_bitfield (struct location *loc, static void translate_base_fetch (struct obstack *pool, int indent, Dwarf_Word byte_size, bool signed_p, - struct location **input, const char *target) + struct location **input, const char *target, + int depth) { bool deref = false; @@ -1650,10 +1645,12 @@ translate_base_fetch (struct obstack *pool, int indent, { struct location *p = (*input)->pieces; - declare_noncontig_union (pool, indent, input, *input); + declare_noncontig_union (pool, indent, input, *input, depth); Dwarf_Word offset = 0; - char piece[sizeof "u_pieces.pieces.p" + 20] = "u_pieces.pieces.p"; + char piece[sizeof "u_pieces?.pieces.p" + 20] = "u_pieces?.pieces.p"; + piece[8] = (char) ('0' + depth); + int pdepth = depth + 1; while (p != NULL) { struct location *newp = obstack_alloc (pool, sizeof *newp); @@ -1662,18 +1659,19 @@ translate_base_fetch (struct obstack *pool, int indent, (*input)->next = newp; *input = newp; - snprintf (&piece[sizeof "u_pieces.pieces.p" - 1], 20, + snprintf (&piece[sizeof "u_pieces?.pieces.p" - 1], 20, "%" PRIu64, offset); translate_base_fetch (pool, indent, p->byte_size, signed_p /* ? */, - input, piece); + input, piece, pdepth); (*input)->type = loc_fragment; offset += p->byte_size; p = p->next; + pdepth++; } - obstack_printf (pool, "%*s%s = u_pieces.whole;\n", indent * 2, - "", target); + obstack_printf (pool, "%*s%s = u_pieces%d.whole;\n", indent * 2, + "", target, depth); } else if ((*input)->type == loc_constant) { @@ -1681,14 +1679,14 @@ translate_base_fetch (struct obstack *pool, int indent, const size_t byte_size = (*input)->byte_size; size_t i; - declare_noncontig_union (pool, indent, input, *input); + declare_noncontig_union (pool, indent, input, *input, depth); for (i = 0; i < byte_size; ++i) - obstack_printf (pool, "%*su_const.bytes[%zu] = %#x;\n", indent * 2, - "", i, constant_block[i]); + obstack_printf (pool, "%*su_pieces%d.bytes[%zu] = %#x;\n", indent * 2, + "", depth, i, constant_block[i]); - obstack_printf (pool, "%*s%s = u_const.whole;\n", indent * 2, - "", target); + obstack_printf (pool, "%*s%s = u_pieces%d.whole;\n", indent * 2, + "", target, depth); } else switch (byte_size) @@ -1761,7 +1759,7 @@ c_translate_fetch (struct obstack *pool, int indent, /* This is a bit field. Fetch the containing base type into a temporary variable. */ - translate_base_fetch (pool, indent, byte_size, signed_p, input, "tmp"); + translate_base_fetch (pool, indent, byte_size, signed_p, input, "tmp", 0); (*input)->type = loc_fragment; (*input)->address.declare = "tmp"; @@ -1778,7 +1776,7 @@ c_translate_fetch (struct obstack *pool, int indent, *input = loc; } else - translate_base_fetch (pool, indent, byte_size, signed_p, input, target); + translate_base_fetch (pool, indent, byte_size, signed_p, input, target, 0); } /* Translate a fragment to store RVALUE into the base-type value of @@ -1786,24 +1784,26 @@ c_translate_fetch (struct obstack *pool, int indent, static void translate_base_store (struct obstack *pool, int indent, Dwarf_Word byte_size, struct location **input, struct location *store_loc, - const char *rvalue) + const char *rvalue, int depth) { bool deref = false; if (store_loc->type == loc_noncontiguous) { - declare_noncontig_union (pool, indent, input, store_loc); + declare_noncontig_union (pool, indent, input, store_loc, depth); - obstack_printf (pool, "%*su_pieces.whole = %s;\n", indent * 2, - "", rvalue); + obstack_printf (pool, "%*su_pieces%d.whole = %s;\n", indent * 2, + "", depth, rvalue); struct location *loc = new_synthetic_loc (pool, *input, deref); loc->type = loc_fragment; (*input)->next = loc; *input = loc; Dwarf_Word offset = 0; - char piece[sizeof "u_pieces.pieces.p" + 20] = "u_pieces.pieces.p"; + char piece[sizeof "u_pieces?.pieces.p" + 20] = "u_pieces?.pieces.p"; + piece[8] = (char) ('0' + depth); struct location *p; + int pdepth = depth + 1; for (p = store_loc->pieces; p != NULL; p = p->next) { struct location *newp = obstack_alloc (pool, sizeof *newp); @@ -1812,10 +1812,10 @@ translate_base_store (struct obstack *pool, int indent, Dwarf_Word byte_size, (*input)->next = newp; *input = newp; - snprintf (&piece[sizeof "u_pieces.pieces.p" - 1], 20, "%" PRIu64, + snprintf (&piece[sizeof "u_pieces?.pieces.p" - 1], 20, "%" PRIu64, offset); translate_base_store (pool, indent, - p->byte_size, input, *input, piece); + p->byte_size, input, *input, piece, pdepth++); (*input)->type = loc_fragment; offset += p->byte_size; @@ -1884,7 +1884,7 @@ c_translate_store (struct obstack *pool, int indent, /* This is a bit field. Fetch the containing base type into a temporary variable. */ - translate_base_fetch (pool, indent, byte_size, signed_p, input, "tmp"); + translate_base_fetch (pool, indent, byte_size, signed_p, input, "tmp", 0); (*input)->type = loc_fragment; (*input)->address.declare = "tmp"; @@ -1905,7 +1905,7 @@ c_translate_store (struct obstack *pool, int indent, rvalue = "tmp"; } - translate_base_store (pool, indent, byte_size, input, store_loc, rvalue); + translate_base_store (pool, indent, byte_size, input, store_loc, rvalue, 0); } /* Translate a fragment to dereference the given pointer type, @@ -1935,7 +1935,7 @@ c_translate_pointer (struct obstack *pool, int indent, bool signed_p = false; /* XXX: Does not matter? */ - translate_base_fetch (pool, indent + 1, byte_size, signed_p, input, "addr"); + translate_base_fetch (pool, indent + 1, byte_size, signed_p, input, "addr", 0); (*input)->type = loc_address; } @@ -2003,7 +2003,7 @@ c_translate_pointer_store (struct obstack *pool, int indent, dwarf_errmsg (-1)); translate_base_store (pool, indent + 1, byte_size, - input, *input, rvalue); + input, *input, rvalue, 0); // XXX: what about multiple-location lvalues? } -- cgit From 4bd4d40e19f7ba203d5e380965210181648f560a Mon Sep 17 00:00:00 2001 From: David Smith Date: Thu, 7 Jan 2010 12:14:44 -0600 Subject: Partial PR 10848 fix. Added testcase for STP_MAXMEMORY. * runtime/alloc.c (_stp_kmalloc): Renamed 'MAXMEMORY' to 'STP_MAXMEMORY'. (_stp_kzalloc): Ditto. (_stp_vmalloc): Ditto. (_stp_alloc_percpu): Ditto. (_stp_kmalloc_node): Ditto. * testsuite/systemtap.base/maxmemory.exp: New test for STP_MAXMEMORY. --- runtime/alloc.c | 41 ++++++++-------- testsuite/systemtap.base/maxmemory.exp | 86 ++++++++++++++++++++++++++++++++++ 2 files changed, 107 insertions(+), 20 deletions(-) create mode 100644 testsuite/systemtap.base/maxmemory.exp diff --git a/runtime/alloc.c b/runtime/alloc.c index 810ec5d5..b2578e06 100644 --- a/runtime/alloc.c +++ b/runtime/alloc.c @@ -216,13 +216,14 @@ static void _stp_mem_debug_validate(void *addr) } #endif -/* #define MAXMEMORY 8192 */ +/* #define STP_MAXMEMORY 8192 */ /* - * If MAXMEMORY is defined to a value (stap -DMAXMEMORY=8192 ...) then - * every memory allocation is checked to make sure the systemtap - * module doesn't use more than MAXMEMORY of memory. MAXMEMORY is - * specified in kilobytes, so, for example, '8192' means that the - * systemtap module won't use more than 8 megabytes of memory. + * If STP_MAXMEMORY is defined to a value (stap -DSTP_MAXMEMORY=8192 + * ...) then every memory allocation is checked to make sure the + * systemtap module doesn't use more than STP_MAXMEMORY of memory. + * STP_MAXMEMORY is specified in kilobytes, so, for example, '8192' + * means that the systemtap module won't use more than 8 megabytes of + * memory. * * Note 1: This size does include the size of the module itself, plus * any additional allocations. @@ -232,7 +233,7 @@ static void _stp_mem_debug_validate(void *addr) * directly report an error back to a user (so instead it uses * 'printk'). If the modules transport has been set up, the code that * calls the memory allocation functions - * (_stp_kmalloc/_stp_kzalloc/etc.) should report an error directly wto + * (_stp_kmalloc/_stp_kzalloc/etc.) should report an error directly to * the user. * * Note 3: This only tracks direct allocations by the systemtap @@ -240,7 +241,7 @@ static void _stp_mem_debug_validate(void *addr) * kprobes/uprobes/etc. internals). */ -#ifdef MAXMEMORY +#ifdef STP_MAXMEMORY #ifndef STAPCONF_GRSECURITY #define _STP_MODULE_CORE_SIZE (THIS_MODULE->core_size) #else @@ -251,9 +252,9 @@ static void _stp_mem_debug_validate(void *addr) static void *_stp_kmalloc(size_t size) { void *ret; -#ifdef MAXMEMORY +#ifdef STP_MAXMEMORY if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) - > (MAXMEMORY * 1024)) { + > (STP_MAXMEMORY * 1024)) { return NULL; } #endif @@ -276,9 +277,9 @@ static void *_stp_kzalloc(size_t size) #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,15) { void *ret; -#ifdef MAXMEMORY +#ifdef STP_MAXMEMORY if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) - > (MAXMEMORY * 1024)) { + > (STP_MAXMEMORY * 1024)) { return NULL; } #endif @@ -301,9 +302,9 @@ static void *_stp_kzalloc(size_t size) #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) */ { void *ret; -#ifdef MAXMEMORY +#ifdef STP_MAXMEMORY if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) - > (MAXMEMORY * 1024)) { + > (STP_MAXMEMORY * 1024)) { return NULL; } #endif @@ -326,9 +327,9 @@ static void *_stp_kzalloc(size_t size) static void *_stp_vmalloc(unsigned long size) { void *ret; -#ifdef MAXMEMORY +#ifdef STP_MAXMEMORY if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) - > (MAXMEMORY * 1024)) { + > (STP_MAXMEMORY * 1024)) { return NULL; } #endif @@ -360,10 +361,10 @@ static void *_stp_alloc_percpu(size_t size) if (size > _STP_MAX_PERCPU_SIZE) return NULL; -#ifdef MAXMEMORY +#ifdef STP_MAXMEMORY if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + (size * num_online_cpus())) - > (MAXMEMORY * 1024)) { + > (STP_MAXMEMORY * 1024)) { return NULL; } #endif @@ -397,9 +398,9 @@ static void *_stp_alloc_percpu(size_t size) static void *_stp_kmalloc_node(size_t size, int node) { void *ret; -#ifdef MAXMEMORY +#ifdef STP_MAXMEMORY if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) - > (MAXMEMORY * 1024)) { + > (STP_MAXMEMORY * 1024)) { return NULL; } #endif diff --git a/testsuite/systemtap.base/maxmemory.exp b/testsuite/systemtap.base/maxmemory.exp new file mode 100644 index 00000000..20827edf --- /dev/null +++ b/testsuite/systemtap.base/maxmemory.exp @@ -0,0 +1,86 @@ +if {![installtest_p]} {untested "MAXMEMORY"; return} + +set script { + global k + + probe begin { + print("systemtap starting probe\n") + k["foo"] = 0 + } + + probe kernel.function("vfs_read"), kernel.function("vfs_write") { + k["foo"]++ + } + probe end { + print("systemtap ending probe\n") + } +} + +# stap_run_maxmemory TEST_NAME EXPECT_ERROR +# TEST_NAME is the name of the current test +# EXPECT_ERROR lets us know to expect an error or not +# +# Additional arguments are passed to stap as-is. +proc stap_run_maxmemory { TEST_NAME EXPECT_ERROR args } { + + set cmd [concat {stap -v} $args] + eval spawn $cmd + expect { + -timeout 150 + -re {^Pass\ [1234]: [^\r]+real\ ms\.\r\n} {exp_continue} + -re {^Pass\ ([34]): using cached [^\r]+\r\n} {exp_continue} + -re {^Pass 5: starting run.\r\n} {exp_continue} + -re {^Error inserting module[^\r]+\r\n} { + if {$EXPECT_ERROR} { + pass "$TEST_NAME received expected insert module error" + } else { + fail "$TEST_NAME unexpected insert module error" + } + } + -re {ERROR: [^\r]+ allocation failed\r\n} { + if {$EXPECT_ERROR} { + pass "$TEST_NAME received expected allocation error" + } else { + fail "$TEST_NAME unexpected allocation error" + } + } + -re "^systemtap starting probe\r\n" { + exec kill -INT -[exp_pid] + + expect { + -timeout 10 + -re {^systemtap ending probe\r\n} { + if {$EXPECT_ERROR} { + fail "$TEST_NAME didn't receive expected allocation error" + } else { + pass "$TEST_NAME didn't receive allocation error" + } + } + -re {ERROR: .+ allocation failed\r\n} { + if {$EXPECT_ERROR} { + pass "$TEST_NAME received expected allocation error" + } else { + fail "$TEST_NAME received an unexpected allocation error" + } + } + } + } + -re "semantic error:" { fail "$TEST_NAME compilation" } + timeout { fail "$TEST_NAME startup (timeout)"; + exec kill -INT -[exp_pid] } + eof { fail "$TEST_NAME startup (eof)" } + } + catch close + wait +} + +# MAXMEMORY1 tests to make sure normal operation doesn't receive a +# max memory error +set test "MAXMEMORY1" +stap_run_maxmemory $test 0 -u -e $script + +# MAXMEMORY2 is the same script, but we're adjusting STP_MAXMEMORY to +# a low value so that we *will* get an allocation error or an insert +# module error. +set test "MAXMEMORY2" +stap_run_maxmemory $test 1 -u -DSTP_MAXMEMORY=200 -e $script -- cgit