diff options
author | Dave Brolley <brolley@redhat.com> | 2010-01-07 14:00:49 -0500 |
---|---|---|
committer | Dave Brolley <brolley@redhat.com> | 2010-01-07 14:00:49 -0500 |
commit | af7b183c32c627b1934e9be2d028d7c4ff1a1d2e (patch) | |
tree | a1670ad0f02f3ebb47ef2aca648ff7d6afc4e5db | |
parent | a0626e2e2ea13b6fc974157fb71fe6d48f4c7ec0 (diff) | |
parent | 4bd4d40e19f7ba203d5e380965210181648f560a (diff) | |
download | systemtap-steved-af7b183c32c627b1934e9be2d028d7c4ff1a1d2e.tar.gz systemtap-steved-af7b183c32c627b1934e9be2d028d7c4ff1a1d2e.tar.xz systemtap-steved-af7b183c32c627b1934e9be2d028d7c4ff1a1d2e.zip |
Merge branch 'master' of ssh://sources.redhat.com/git/systemtap
36 files changed, 631 insertions, 490 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: 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 @@ -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 */, 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 <unistd.h> #include <sys/syscall.h> # 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 <sys/syscall.h> @@ -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<depth>; */ 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? } diff --git a/runtime/alloc.c b/runtime/alloc.c index fa85fc41..b2578e06 100644 --- a/runtime/alloc.c +++ b/runtime/alloc.c @@ -172,18 +172,100 @@ 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 STP_MAXMEMORY 8192 */ +/* + * 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. + * + * 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 to + * 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 STP_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 STP_MAXMEMORY + if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) + > (STP_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 +276,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 STP_MAXMEMORY + if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) + > (STP_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 +301,21 @@ static void *_stp_kzalloc(size_t size) } #else /* LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,15) */ { + void *ret; +#ifdef STP_MAXMEMORY + if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) + > (STP_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 +326,21 @@ static void *_stp_kzalloc(size_t size) static void *_stp_vmalloc(unsigned long size) { + void *ret; +#ifdef STP_MAXMEMORY + if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) + > (STP_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 +361,14 @@ static void *_stp_alloc_percpu(size_t size) if (size > _STP_MAX_PERCPU_SIZE) return NULL; +#ifdef STP_MAXMEMORY + if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + + (size * num_online_cpus())) + > (STP_MAXMEMORY * 1024)) { + return NULL; + } +#endif + #ifdef STAPCONF_ALLOC_PERCPU_ALIGN ret = __alloc_percpu(size, 8); #else @@ -287,6 +398,12 @@ static void *_stp_alloc_percpu(size_t size) static void *_stp_kmalloc_node(size_t size, int node) { void *ret; +#ifdef STP_MAXMEMORY + if ((_STP_MODULE_CORE_SIZE + _stp_allocated_memory + size) + > (STP_MAXMEMORY * 1024)) { + return NULL; + } +#endif #ifdef DEBUG_MEM ret = kmalloc_node(size + MEM_DEBUG_SIZE, STP_ALLOC_FLAGS, node); if (likely(ret)) { 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/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/ ", " <systemtap@sources.redhat.com> . .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/ ", " <systemtap@sources.redhat.com> . .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/ ", " <systemtap@sources.redhat.com> . .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/ ", " <systemtap@sources.redhat.com> . .hy @@ -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/ , <systemtap@sources.redhat.com> . .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/ ", " <systemtap@sources.redhat.com> . .hy 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 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<derived_probe *> & 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..4c15c5ac 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: " @@ -4735,6 +4699,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 @@ -4802,7 +4767,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 +4811,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/buildok/irq.stp b/testsuite/buildok/irq.stp index 7f1c2ab6..7f1c2ab6 100644..100755 --- a/testsuite/buildok/irq.stp +++ b/testsuite/buildok/irq.stp diff --git a/testsuite/buildok/logging.stp b/testsuite/buildok/logging.stp index 636770c7..636770c7 100644..100755 --- a/testsuite/buildok/logging.stp +++ b/testsuite/buildok/logging.stp diff --git a/testsuite/buildok/pr10678.stp b/testsuite/buildok/pr10678.stp index 4ce8fb99..4ce8fb99 100644..100755 --- a/testsuite/buildok/pr10678.stp +++ b/testsuite/buildok/pr10678.stp diff --git a/testsuite/buildok/scheduler-test-tracepoints.stp b/testsuite/buildok/scheduler-test-tracepoints.stp index a660c367..a660c367 100644..100755 --- a/testsuite/buildok/scheduler-test-tracepoints.stp +++ b/testsuite/buildok/scheduler-test-tracepoints.stp diff --git a/testsuite/buildok/semicolon.stp b/testsuite/buildok/semicolon.stp index 0ec41956..0ec41956 100644..100755 --- a/testsuite/buildok/semicolon.stp +++ b/testsuite/buildok/semicolon.stp diff --git a/testsuite/buildok/vm.tracepoints.kmalloc.stp b/testsuite/buildok/vm.tracepoints.kmalloc.stp index f723737c..f723737c 100644..100755 --- a/testsuite/buildok/vm.tracepoints.kmalloc.stp +++ b/testsuite/buildok/vm.tracepoints.kmalloc.stp diff --git a/testsuite/buildok/vm.tracepoints.stp b/testsuite/buildok/vm.tracepoints.stp index 6ed747d7..6ed747d7 100644..100755 --- a/testsuite/buildok/vm.tracepoints.stp +++ b/testsuite/buildok/vm.tracepoints.stp 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/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 ] 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 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} { 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-- } 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) +} |