diff options
60 files changed, 1352 insertions, 353 deletions
diff --git a/doc/SystemTap_Tapset_Reference/tapsets.tmpl b/doc/SystemTap_Tapset_Reference/tapsets.tmpl index 7e9d4784..448d4b20 100644 --- a/doc/SystemTap_Tapset_Reference/tapsets.tmpl +++ b/doc/SystemTap_Tapset_Reference/tapsets.tmpl @@ -113,7 +113,7 @@ The context functions provide additional information about where an event occurred. These functions can provide information such as a backtrace to - where the event occured + where the event occurred and the current register values for the processor. </para> !Itapset/context.stp @@ -202,7 +202,7 @@ <title>Directory-entry (dentry) Tapset</title> <para> This family of functions is used to map kernel VFS - directory entriy pointers to file or full path names. + directory entry pointers to file or full path names. </para> !Itapset/dentry.stp </chapter> diff --git a/doc/langref.tex b/doc/langref.tex index 9a56e5f2..29de4534 100644 --- a/doc/langref.tex +++ b/doc/langref.tex @@ -910,6 +910,48 @@ function, use \textbf{.statement} probes. Do not use wildcards in to not register. Also, run statement probes in guru mode only. +\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 +\texttt{\textit{MODNAME}}. There are four probe point variants +supported by the translator: +\begin{vindent} +\begin{verbatim} +procfs("PATH").read +procfs("PATH").write +procfs.read +procfs.write +\end{verbatim} +\end{vindent} + +\texttt{PATH} is the file name to be created, relative to +\texttt{/proc/systemtap/MODNAME}. If no \texttt{PATH} is specified +(as in the last two variants in the previous list), \texttt{PATH} +defaults to "command". + +When a user reads \texttt{/proc/systemtap/MODNAME/PATH}, the +corresponding procfs read probe is triggered. Assign the string data +to be read to a variable named \texttt{\$value}, as follows: +\begin{vindent} +\begin{verbatim} +procfs("PATH").read { $value = "100\n" } +\end{verbatim} +\end{vindent} + +When a user writes into \texttt{/proc/systemtap/MODNAME/PATH}, the +corresponding procfs write probe is triggered. The data the user +wrote is available in the string variable named \texttt{\$value}, as +follows: +\begin{vindent} +\begin{verbatim} +procfs("PATH").write { printf("User wrote: %s", $value) } +\end{verbatim} +\end{vindent} + + \subsection{Marker probes} \index{marker probes} This family of probe points connects to static probe markers inserted @@ -950,6 +992,75 @@ For more information about marker probes, see \url{http://sourceware.org/systemtap/wiki/UsingMarkers}. +\subsection{Syscall probes} +\label{sec:syscall} +\index{syscall probes} +The \texttt{syscall.*} aliases define several hundred probes. They +use the following syntax: +\begin{vindent} +\begin{verbatim} +syscall.NAME +syscall.NAME.return +\end{verbatim} +\end{vindent} + +Generally, two probes are defined for each normal system call as +listed in the syscalls(2) manual page: one for entry and one for +return. System calls that never return do not have a +corresponding \texttt{.return} probe. + +Each probe alias defines a variety of variables. Look at the tapset +source code to find the most reliable source of variable definitions. +Generally, each variable listed in the standard manual page is +available as a script-level variable. For example, +\texttt{syscall.open} exposes file name, flags, and mode. In addition, +a standard suite of variables is available at most aliases, as follows: + +\begin{itemize} +\item \texttt{argstr}: A pretty-printed form of the entire argument + list, without parentheses. +\item \texttt{name}: The name of the system call. +\item \texttt{retstr}: For return probes, a pretty-printed form of the + system call result. +\end{itemize} + +Not all probe aliases obey all of these general guidelines. Please +report exceptions that you encounter as a bug. + + +\subsection{Tracepoints} +\label{sec:tracepoints} +\index{tracepoints} + +This family of probe points hooks to static probing tracepoints +inserted into the kernel or kernel modules. As with marker probes, +these tracepoints are special macro calls inserted by kernel +developers to make probing faster and more reliable than with +DWARF-based probes. DWARF debugging information is not required to +probe tracepoints. Tracepoints have more strongly-typed parameters +than marker probes. + +Tracepoint probes begin with \texttt{kernel}. The next part names the +tracepoint itself: \texttt{trace("name")}. The tracepoint +\texttt{name} string, which can contain wildcard characters, is +matched against the names defined by the kernel developers in the +tracepoint header files. + +The handler associated with a tracepoint-based probe can read the +optional parameters specified at the macro call site. These +parameters are named according to the declaration by the tracepoint +author. For example, the tracepoint probe +\texttt{kernel.trace("sched\_switch")} provides the parameters +\texttt{\$rq}, \texttt{\$prev}, and \texttt{\$next}. If the parameter +is a complex type such as a struct pointer, then a script can access +fields with the same syntax as DWARF \texttt{\$target} variables. +Tracepoint parameters cannot be modified; however, in guru mode a +script can modify fields of parameters. + +The name of the tracepoint is available in \texttt{\$\$name}, and a +string of \texttt{name=value} pairs for all parameters of the +tracepoint is available in \texttt{\$\$vars} or \texttt{\$\$parms}. + \subsection{Timer probes} \index{timer probes} @@ -267,9 +267,29 @@ dwflpp::function_name_matches(const string& pattern) bool -dwflpp::function_name_final_match(const string& pattern) +dwflpp::function_scope_matches(const vector<string> scopes) { - return module_name_final_match (pattern); + // walk up the containing scopes + Dwarf_Die* die = function; + for (int i = scopes.size() - 1; i >= 0; --i) + { + die = get_parent_scope(die); + + // check if this scope matches, and prepend it if so + // NB: a NULL die is the global scope, compared as "" + string name = dwarf_diename(die) ?: ""; + if (name_has_wildcard(scopes[i]) ? + function_name_matches_pattern(name, scopes[i]) : + name == scopes[i]) + function_name = name + "::" + function_name; + else + return false; + + // make sure there's no more if we're at the global scope + if (!die && i > 0) + return false; + } + return true; } @@ -598,6 +618,9 @@ dwflpp::cache_die_parents(cu_die_parent_cache_t* parents, Dwarf_Die* die) case DW_TAG_entry_point: case DW_TAG_inlined_subroutine: case DW_TAG_subprogram: + case DW_TAG_namespace: + case DW_TAG_class_type: + case DW_TAG_structure_type: parents->insert(make_pair(child.addr, *die)); cache_die_parents(parents, &child); break; @@ -750,6 +773,34 @@ dwflpp::getscopes(Dwarf_Addr pc) } +Dwarf_Die* +dwflpp::get_parent_scope(Dwarf_Die* die) +{ + Dwarf_Die specification; + if (dwarf_attr_die(die, DW_AT_specification, &specification)) + die = &specification; + + cu_die_parent_cache_t *parents = get_die_parents(); + cu_die_parent_cache_t::iterator it = parents->find(die->addr); + while (it != parents->end()) + { + Dwarf_Die* scope = &it->second; + switch (dwarf_tag (scope)) + { + case DW_TAG_namespace: + case DW_TAG_class_type: + case DW_TAG_structure_type: + return scope; + + default: + break; + } + it = parents->find(scope->addr); + } + return NULL; +} + + int dwflpp::global_alias_caching_callback(Dwarf_Die *die, void *arg) { @@ -1681,11 +1732,12 @@ dwflpp::translate_location(struct obstack *pool, #if !_ELFUTILS_PREREQ (0,142) if (dwarf_whatattr (attr) == DW_AT_data_member_location) { - Dwarf_Op offset_loc = { .atom = DW_OP_plus_uconst }; + Dwarf_Op offset_loc; + offset_loc.atom = DW_OP_plus_uconst; if (dwarf_formudata (attr, &offset_loc.number) == 0) return c_translate_location (pool, &loc2c_error, this, &loc2c_emit_address, 1, 0, pc, - &offset_loc, 1, NULL, NULL); + &offset_loc, 1, NULL, NULL, NULL); } #endif @@ -1722,7 +1774,7 @@ dwflpp::translate_location(struct obstack *pool, return c_translate_location (pool, &loc2c_error, this, &loc2c_emit_address, 1, 0 /* PR9768 */, - pc, expr, len, tail, fb_attr, cfa_ops); + pc, attr, expr, len, tail, fb_attr, cfa_ops); } @@ -2345,7 +2397,7 @@ dwflpp::literal_stmt_for_return (Dwarf_Die *scope_die, struct location *head = c_translate_location (&pool, &loc2c_error, this, &loc2c_emit_address, 1, 0 /* PR9768 */, - pc, locops, nlocops, + pc, NULL, locops, nlocops, &tail, NULL, NULL); /* Translate the ->bar->baz[NN] parts. */ @@ -192,7 +192,7 @@ struct dwflpp bool function_name_matches_pattern(const std::string& name, const std::string& pattern); bool function_name_matches(const std::string& pattern); - bool function_name_final_match(const std::string& pattern); + bool function_scope_matches(const std::vector<std::string> scopes); void iterate_over_modules(int (* callback)(Dwfl_Module *, void **, const char *, Dwarf_Addr, @@ -305,6 +305,8 @@ private: void cache_die_parents(cu_die_parent_cache_t* parents, Dwarf_Die* die); cu_die_parent_cache_t *get_die_parents(); + Dwarf_Die* get_parent_scope(Dwarf_Die* die); + /* The global alias cache is used to resolve any DIE found in a * module that is stubbed out with DW_AT_declaration with a defining * DIE found in a different module. The current assumption is that diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h index ddcc74e5..01308474 100644 --- a/includes/sys/sdt.h +++ b/includes/sys/sdt.h @@ -42,6 +42,13 @@ #define STAP_PROBE_DATA(probe, guard, arg) \ STAP_PROBE_DATA_(#probe,guard,arg) +#if defined STAP_HAS_SEMAPHORES && defined EXPERIMENTAL_UTRACE_SDT +#define STAP_SEMAPHORE(probe) \ + if ( probe ## _semaphore ) +#else +#define STAP_SEMAPHORE(probe) ; +#endif + #if ! (defined EXPERIMENTAL_UTRACE_SDT || defined EXPERIMENTAL_KPROBE_SDT) /* These baroque macros are used to create a unique label. */ @@ -81,6 +88,7 @@ do { \ } while (0) #define STAP_PROBE1_(probe,label,parm1) \ +STAP_SEMAPHORE(probe) \ do { \ volatile __typeof__((parm1)) arg1 = parm1; \ STAP_UNINLINE; \ @@ -90,6 +98,7 @@ do { \ } while (0) #define STAP_PROBE2_(probe,label,parm1,parm2) \ +STAP_SEMAPHORE(probe) \ do { \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ @@ -100,6 +109,7 @@ do { \ } while (0) #define STAP_PROBE3_(probe,label,parm1,parm2,parm3) \ +STAP_SEMAPHORE(probe) \ do { \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ @@ -111,6 +121,7 @@ do { \ } while (0) #define STAP_PROBE4_(probe,label,parm1,parm2,parm3,parm4) \ +STAP_SEMAPHORE(probe) \ do { \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ @@ -123,6 +134,7 @@ do { \ } while (0) #define STAP_PROBE5_(probe,label,parm1,parm2,parm3,parm4,parm5) \ +STAP_SEMAPHORE(probe) \ do { \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ @@ -136,6 +148,7 @@ do { \ } while (0) #define STAP_PROBE6_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6) \ +STAP_SEMAPHORE(probe) \ do { \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ @@ -150,6 +163,7 @@ do { \ } while (0) #define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ +STAP_SEMAPHORE(probe) \ do { \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ @@ -165,6 +179,7 @@ do { \ } while (0) #define STAP_PROBE8_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ +STAP_SEMAPHORE(probe) \ do { \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ @@ -181,6 +196,7 @@ do { \ } while (0) #define STAP_PROBE9_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ +STAP_SEMAPHORE(probe) \ do { \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ @@ -198,6 +214,7 @@ do { \ } while (0) #define STAP_PROBE10_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ +STAP_SEMAPHORE(probe) \ do { \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ @@ -232,18 +249,21 @@ extern long int syscall (long int __sysno, ...) __THROW; #include <sys/syscall.h> #define STAP_PROBE_(probe) \ +STAP_SEMAPHORE(probe) \ do { \ - STAP_PROBE_DATA(probe,STAP_SYSCALL,0); \ + STAP_PROBE_DATA(probe,STAP_GUARD,0); \ syscall (STAP_SYSCALL, #probe, STAP_GUARD); \ } while (0) #define STAP_PROBE1_(probe,label,parm1) \ +STAP_SEMAPHORE(probe) \ do { \ STAP_PROBE_DATA(probe,STAP_GUARD,1); \ syscall (STAP_SYSCALL, #probe, STAP_GUARD, (size_t)parm1); \ } while (0) #define STAP_PROBE2_(probe,label,parm1,parm2) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8)));} \ @@ -253,16 +273,18 @@ do { \ } while (0) #define STAP_PROBE3_(probe,label,parm1,parm2,parm3) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ size_t arg3 __attribute__((aligned(8)));} \ stap_probe3_args = {(size_t)parm1, (size_t)parm2, (size_t)parm3}; \ STAP_PROBE_DATA(probe,STAP_GUARD,3); \ - syscall (STAP_SYSCALL, #probe, STAP_GUARD, &stap_probe3_args); \ + syscall (STAP_SYSCALL, #probe, STAP_GUARD, &stap_probe3_args); \ } while (0) #define STAP_PROBE4_(probe,label,parm1,parm2,parm3,parm4) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ @@ -270,10 +292,11 @@ do { \ size_t arg4 __attribute__((aligned(8)));} \ stap_probe4_args = {(size_t)parm1, (size_t)parm2, (size_t)parm3, (size_t)parm4}; \ STAP_PROBE_DATA(probe,STAP_GUARD,4); \ - syscall (STAP_SYSCALL, #probe, STAP_GUARD,&stap_probe4_args); \ + syscall (STAP_SYSCALL, #probe, STAP_GUARD,&stap_probe4_args); \ } while (0) #define STAP_PROBE5_(probe,label,parm1,parm2,parm3,parm4,parm5) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ @@ -287,6 +310,7 @@ do { \ } while (0) #define STAP_PROBE6_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ @@ -301,6 +325,7 @@ do { \ } while (0) #define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ @@ -316,6 +341,7 @@ do { \ } while (0) #define STAP_PROBE8_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ @@ -332,6 +358,7 @@ do { \ } while (0) #define STAP_PROBE9_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ @@ -349,6 +376,7 @@ do { \ } while (0) #define STAP_PROBE10_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ +STAP_SEMAPHORE(probe) \ do { \ __extension__ struct {size_t arg1 __attribute__((aligned(8))); \ size_t arg2 __attribute__((aligned(8))); \ @@ -362,7 +390,7 @@ do { \ size_t arg10 __attribute__((aligned(8)));} \ stap_probe10_args = {(size_t)parm1, (size_t)parm2, (size_t)parm3, (size_t)parm4, \ (size_t)parm5, (size_t)parm6, (size_t)parm7, (size_t)parm8, (size_t)parm9, (size_t)parm10}; \ - STAP_PROBE_DATA(probe,STAP_GUARD,10); \ + STAP_PROBE_DATA(probe,STAP_GUARD,10); \ syscall (STAP_SYSCALL, #probe, STAP_GUARD, &stap_probe10_args); \ } while (0) diff --git a/initscript/systemtap.in b/initscript/systemtap.in index 21bcd65b..b3d6e868 100644 --- a/initscript/systemtap.in +++ b/initscript/systemtap.in @@ -1,17 +1,17 @@ #!/bin/bash # -# systemtap Startup script for systemtap scrips +# systemtap Startup script for SystemTap scripts # # chkconfig: - 00 99 -# description: Systemtap is a programable kernel/application tracing tool. +# description: SystemTap is a programmable kernel/application tracing tool. # config: /etc/systemtap/config # config: /etc/systemtap/conf.d ### BEGIN INIT INFO -# Provides: Systemtap scripts startup +# Provides: SystemTap scripts startup # Required-Start: $local_fs # Required-Stop: $local_fs -# Short-Description: start and stop systemtap scripts -# Description: Systemtap is a programable kernel/application tracing tool. +# Short-Description: Start and stop SystemTap scripts +# Description: SystemTap is a programmable kernel/application tracing tool. ### END INIT INFO # Source function library. @@ -231,7 +231,7 @@ might_fail () { # message exitcode } might_success () { # message if [ $NR_FAILS -ne 0 ]; then - log "Warning: $NR_FAILS failure occured." + log "Warning: $NR_FAILS failure occurred." do_warning "$1" else do_success "$1" diff --git a/loc2c-test.c b/loc2c-test.c index b8883876..495a95f1 100644 --- a/loc2c-test.c +++ b/loc2c-test.c @@ -136,7 +136,7 @@ handle_variable (Dwarf_Die *lscopes, int lnscopes, int out, struct location *head, *tail = NULL; head = c_translate_location (&pool, &fail, NULL, NULL, - 1, cubias, pc, locexpr, locexpr_len, + 1, cubias, pc, &attr_mem, locexpr, locexpr_len, &tail, fb_attr, cfa_ops); if (dwarf_attr_integrate (vardie, DW_AT_type, &attr_mem) == NULL) @@ -238,7 +238,8 @@ handle_variable (Dwarf_Die *lscopes, int lnscopes, int out, Dwarf_Op offset_loc = { .atom = DW_OP_plus_uconst }; if (dwarf_formudata (&attr_mem, &offset_loc.number) == 0) c_translate_location (&pool, NULL, NULL, NULL, - 1, cubias, pc, &offset_loc, 1, + 1, cubias, pc, &attr_mem, + &offset_loc, 1, &tail, NULL, NULL); else #endif @@ -246,7 +247,8 @@ handle_variable (Dwarf_Die *lscopes, int lnscopes, int out, locexpr = get_location (cubias, pc, &attr_mem, &locexpr_len); c_translate_location (&pool, NULL, NULL, NULL, - 1, cubias, pc, locexpr, locexpr_len, + 1, cubias, pc, &attr_mem, + locexpr, locexpr_len, &tail, NULL, NULL); } } @@ -151,7 +151,7 @@ lose (struct location *loc, static const char * translate (struct obstack *pool, int indent, Dwarf_Addr addrbias, - const Dwarf_Op *expr, const size_t len, + Dwarf_Attribute *attr, const Dwarf_Op *expr, const size_t len, struct location *input, bool *need_fb, size_t *loser, struct location *loc) @@ -553,6 +553,23 @@ translate (struct obstack *pool, int indent, Dwarf_Addr addrbias, } break; + case DW_OP_implicit_value: + if (attr == NULL) + DIE ("DW_OP_implicit_value used in invalid context (no DWARF attribute, ABI return value location?)"); + +#if _ELFUTILS_PREREQ (0, 143) + { + Dwarf_Block block; + Dwarf_Op *op = (Dwarf_Op *) &expr[i]; + if (dwarf_getlocation_implicit_value (attr, op, &block) != 0) + DIE ("dwarf_getlocation_implicit_value failed"); + + /* XXX insert real support here */ + } +#endif + DIE ("DW_OP_implicit_value not supported"); + break; + case DW_OP_call_frame_cfa: // We pick this out when processing DW_AT_frame_base in // so it really shouldn't turn up here. @@ -604,6 +621,7 @@ location_from_address (struct obstack *pool, void (*emit_address) (void *fail_arg, struct obstack *, Dwarf_Addr), int indent, Dwarf_Addr dwbias, + Dwarf_Attribute *attr, const Dwarf_Op *expr, size_t len, Dwarf_Addr address, struct location **input, Dwarf_Attribute *fb_attr, const Dwarf_Op *cfa_ops) @@ -617,7 +635,7 @@ location_from_address (struct obstack *pool, bool need_fb = false; size_t loser; - const char *failure = translate (pool, indent + 1, dwbias, expr, len, + const char *failure = translate (pool, indent + 1, dwbias, attr, expr, len, *input, &need_fb, &loser, loc); if (failure != NULL) return lose (loc, failure, expr, loser); @@ -665,7 +683,7 @@ location_from_address (struct obstack *pool, fb_ops = fb_expr; loc->frame_base = alloc_location (pool, loc); - failure = translate (pool, indent + 1, dwbias, fb_ops, fb_len, NULL, + failure = translate (pool, indent + 1, dwbias, attr, fb_ops, fb_len, NULL, NULL, &loser, loc->frame_base); if (failure != NULL) return lose (loc, failure, fb_expr, loser); @@ -681,11 +699,11 @@ location_from_address (struct obstack *pool, /* Translate a location starting from a non-address "on the top of the stack". The *INPUT location is a register name or noncontiguous object specification, and this expression wants to find the "address" - of an object relative to that "address". */ + of an object (or the actual value) relative to that "address". */ static struct location * location_relative (struct obstack *pool, - int indent, Dwarf_Addr dwbias, + int indent, Dwarf_Addr dwbias, Dwarf_Attribute *attr, const Dwarf_Op *expr, size_t len, Dwarf_Addr address, struct location **input, Dwarf_Attribute *fb_attr, const Dwarf_Op *cfa_ops) @@ -818,7 +836,7 @@ location_relative (struct obstack *pool, /* This started from a register, but now it's following a pointer. So we can do the translation starting from address here. */ return location_from_address (pool, NULL, NULL, NULL, indent, dwbias, - expr, len, address, input, fb_attr, + attr, expr, len, address, input, fb_attr, cfa_ops); @@ -976,7 +994,7 @@ location_relative (struct obstack *pool, computations now have an address to start with. So we can punt to the address computation generator. */ loc = location_from_address (pool, NULL, NULL, NULL, - indent, dwbias, + indent, dwbias, attr, &expr[i + 1], len - i - 1, address, input, fb_attr, cfa_ops); @@ -1061,6 +1079,7 @@ c_translate_location (struct obstack *pool, void (*emit_address) (void *fail_arg, struct obstack *, Dwarf_Addr), int indent, Dwarf_Addr dwbias, Dwarf_Addr pc_address, + Dwarf_Attribute *attr, const Dwarf_Op *expr, size_t len, struct location **input, Dwarf_Attribute *fb_attr, const Dwarf_Op *cfa_ops) @@ -1074,16 +1093,17 @@ c_translate_location (struct obstack *pool, This expression will compute starting with that on the stack. */ return location_from_address (pool, fail, fail_arg, emit_address ?: &default_emit_address, - indent, dwbias, expr, len, pc_address, + indent, dwbias, attr, expr, len, pc_address, input, fb_attr, cfa_ops); case loc_noncontiguous: case loc_register: case loc_value: /* The starting point is not an address computation, but a - register. We can only handle limited computations from here. */ - return location_relative (pool, indent, dwbias, expr, len, pc_address, - input, fb_attr, cfa_ops); + register or implicit value. We can only handle limited + computations from here. */ + return location_relative (pool, indent, dwbias, attr, expr, len, + pc_address, input, fb_attr, cfa_ops); default: abort (); @@ -12,7 +12,9 @@ struct location; /* Opaque */ as the starting location, begin from scratch if *INPUT is null. If DW_OP_fbreg is used, it may have a subfragment computing from the FB_ATTR location expression. The call_frame might need to be - calculated by the cfa_ops for the given pc_address. + calculated by the cfa_ops for the given pc_address. If known the + locattr provides the attribute from which the locexpr array was + retrieved. On errors, call FAIL, which should not return. Any later errors will use FAIL and FAIL_ARG from the first c_translate_location call. @@ -32,6 +34,7 @@ struct location *c_translate_location (struct obstack *, int indent, Dwarf_Addr bias, Dwarf_Addr pc_address, + Dwarf_Attribute *attr, const Dwarf_Op *locexpr, size_t locexprlen, struct location **input, diff --git a/man/stapprobes.netdev.3stap.in b/man/stapprobes.netdev.3stap.in index 9b2e57ed..ff09f150 100644 --- a/man/stapprobes.netdev.3stap.in +++ b/man/stapprobes.netdev.3stap.in @@ -70,7 +70,7 @@ Fires when the network device wants to transmit a buffer The protocol of this packet. .I truesize - The size of the the data to be transmitted. + The size of the data to be transmitted. .SH SEE ALSO .IR stap (1), diff --git a/man/stapprobes.snmp.3stap.in b/man/stapprobes.snmp.3stap.in index 3c606932..95da75c9 100644 --- a/man/stapprobes.snmp.3stap.in +++ b/man/stapprobes.snmp.3stap.in @@ -23,7 +23,7 @@ This family of probe points enhances the Linux system's implementation of the Si by allowing the user to collect per-socket statistics. SNMP data is collected in the Linux kernel by counting various events occurring in the networking subsystem. Linux provides one counter for each type of event, thus providing a system-wide collection of network statistics. These statistics can be viewed with the command: .B netstat -s. -The probpoints defined in the SNMP group of tapsets allow users to aberrate each SNMP counter into groups of counters. For example, the user may count SNMP events for a single network socket or for a group of sockets. +The probe points defined in the SNMP group of tapsets allow users to aberrate each SNMP counter into groups of counters. For example, the user may count SNMP events for a single network socket or for a group of sockets. Severals SNMP tapsets have been created. Each tapset represents a single layer of the network stack and defines a group of counters called management information blocks or MIBs. Currently tapsets are provided that support MIBS for IP, TCP layers and the enhanced linux MIB. See the file /usr/include/linux/snmp.h for a list of MIBS supported by linux. diff --git a/runtime/access_process_vm.h b/runtime/access_process_vm.h new file mode 100644 index 00000000..70489d48 --- /dev/null +++ b/runtime/access_process_vm.h @@ -0,0 +1,54 @@ +/* + * The kernel's access_process_vm is not exported in kernel.org kernels, although + * some distros export it on some architectures. To workaround this inconsistency, + * we copied and pasted it here. Fortunately, everything it calls is exported. + */ +#include <linux/pagemap.h> +#include <asm/cacheflush.h> +static int __access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write) +{ + struct mm_struct *mm; + struct vm_area_struct *vma; + struct page *page; + void *old_buf = buf; + + mm = get_task_mm(tsk); + if (!mm) + return 0; + + down_read(&mm->mmap_sem); + /* ignore errors, just check how much was sucessfully transfered */ + while (len) { + int bytes, ret, offset; + void *maddr; + + ret = get_user_pages(tsk, mm, addr, 1, + write, 1, &page, &vma); + if (ret <= 0) + break; + + bytes = len; + offset = addr & (PAGE_SIZE-1); + if (bytes > PAGE_SIZE-offset) + bytes = PAGE_SIZE-offset; + + maddr = kmap(page); + if (write) { + copy_to_user_page(vma, page, addr, + maddr + offset, buf, bytes); + set_page_dirty_lock(page); + } else { + copy_from_user_page(vma, page, addr, + buf, maddr + offset, bytes); + } + kunmap(page); + page_cache_release(page); + len -= bytes; + buf += bytes; + addr += bytes; + } + up_read(&mm->mmap_sem); + mmput(mm); + + return buf - old_buf; +} diff --git a/runtime/addr-map.c b/runtime/addr-map.c index a9aa8d88..35de7a64 100644 --- a/runtime/addr-map.c +++ b/runtime/addr-map.c @@ -115,6 +115,10 @@ lookup_bad_addr(unsigned long addr, size_t size) return 1; #ifndef STP_PRIVILEGED + /* Unprivileged users must not access memory while the context + does not refer to their own process. */ + if (! is_myproc ()) + return 1; /* Unprivileged users must not access kernel space memory. */ if (addr + size > TASK_SIZE) return 1; diff --git a/runtime/itrace.c b/runtime/itrace.c index 6fe39db4..03e1e403 100644 --- a/runtime/itrace.c +++ b/runtime/itrace.c @@ -77,60 +77,8 @@ static struct itrace_info *create_itrace_info( struct task_struct *tsk, u32 step_flag, struct stap_itrace_probe *itrace_probe); -/* - * The kernel's access_process_vm is not exported in kernel.org kernels, although - * some distros export it on some architectures. To workaround this inconsistency, - * we copied and pasted it here. Fortunately, everything it calls is exported. - */ -#include <linux/pagemap.h> -#include <asm/cacheflush.h> -static int __access_process_vm(struct task_struct *tsk, unsigned long addr, void *buf, int len, int write) -{ - struct mm_struct *mm; - struct vm_area_struct *vma; - struct page *page; - void *old_buf = buf; - - mm = get_task_mm(tsk); - if (!mm) - return 0; - - down_read(&mm->mmap_sem); - /* ignore errors, just check how much was sucessfully transfered */ - while (len) { - int bytes, ret, offset; - void *maddr; - ret = get_user_pages(tsk, mm, addr, 1, - write, 1, &page, &vma); - if (ret <= 0) - break; - - bytes = len; - offset = addr & (PAGE_SIZE-1); - if (bytes > PAGE_SIZE-offset) - bytes = PAGE_SIZE-offset; - - maddr = kmap(page); - if (write) { - copy_to_user_page(vma, page, addr, - maddr + offset, buf, bytes); - set_page_dirty_lock(page); - } else { - copy_from_user_page(vma, page, addr, - buf, maddr + offset, bytes); - } - kunmap(page); - page_cache_release(page); - len -= bytes; - buf += bytes; - addr += bytes; - } - up_read(&mm->mmap_sem); - mmput(mm); - - return buf - old_buf; -} +/* Note: __access_process_vm moved to access_process_vm.h */ #ifdef UTRACE_ORIG_VERSION static u32 usr_itrace_report_quiesce(struct utrace_attached_engine *engine, diff --git a/runtime/print.c b/runtime/print.c index 945f7a72..335403fb 100644 --- a/runtime/print.c +++ b/runtime/print.c @@ -225,7 +225,11 @@ static void _stp_print_kernel_info(char *vstr, int ctx, int num_probes) #ifdef DEBUG_MEM "+alloc" #endif - ", probes: %d\n", + ", probes: %d" +#ifndef STP_PRIVILEGED + ", unpriv-uid: %d" +#endif + "\n", THIS_MODULE->name, vstr, #ifndef STAPCONF_GRSECURITY @@ -242,7 +246,11 @@ static void _stp_print_kernel_info(char *vstr, int ctx, int num_probes) #ifdef DEBUG_MEM _stp_allocated_memory - _stp_allocated_net_memory, #endif - num_probes); + num_probes +#ifndef STP_PRIVILEGED + , _stp_uid +#endif + ); } /** @} */ diff --git a/runtime/runtime.h b/runtime/runtime.h index 064ded7b..7087d435 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -54,6 +54,32 @@ static void _stp_warn (const char *fmt, ...) __attribute__ ((format (printf, 1, static void _stp_exit(void); + + +/* unprivileged user support */ + +#ifdef STAPCONF_TASK_UID +#define STP_CURRENT_EUID (current->euid) +#else +#define STP_CURRENT_EUID (task_euid(current)) +#endif + +#define is_myproc() (STP_CURRENT_EUID == _stp_uid) + +#ifndef STP_PRIVILEGED +#define assert_is_myproc() do { \ + if (! is_myproc()) { \ + snprintf (CONTEXT->error_buffer, MAXSTRINGLEN, "semi-privileged tapset function called without is_myproc checking for pid %d (euid %d)", \ + current->tgid, STP_CURRENT_EUID); \ + CONTEXT->last_error = CONTEXT->error_buffer; \ + goto out; \ + } } while (0) +#else +#define assert_is_myproc() do {} while (0) +#endif + + + #include "debug.h" /* atomic globals */ @@ -106,6 +132,8 @@ static struct #endif #include "addr-map.c" + + /* Support functions for int64_t module parameters. */ static int param_set_int64_t(const char *val, struct kernel_param *kp) { diff --git a/runtime/uprobes2/uprobes.c b/runtime/uprobes2/uprobes.c index 07ad3984..edf882a6 100644 --- a/runtime/uprobes2/uprobes.c +++ b/runtime/uprobes2/uprobes.c @@ -17,6 +17,7 @@ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * Copyright (C) IBM Corporation, 2006 + * Copyright (C) Red Hat, Inc. 2009 */ #include <linux/types.h> #include <linux/hash.h> @@ -28,6 +29,8 @@ #include <linux/kref.h> #include <linux/utrace.h> #include <linux/regset.h> +#include <linux/file.h> +#include <linux/version.h> #define UPROBES_IMPLEMENTATION 1 /* PR9974: Adapt to struct renaming. */ @@ -1387,6 +1390,9 @@ static noinline unsigned long uprobe_setup_ssol_vma(unsigned long nbytes) unsigned long addr; struct mm_struct *mm; struct vm_area_struct *vma; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) + struct file *file; +#endif BUG_ON(nbytes & ~PAGE_MASK); if ((addr = find_old_ssol_vma()) != 0) @@ -1400,17 +1406,40 @@ static noinline unsigned long uprobe_setup_ssol_vma(unsigned long nbytes) * Find the end of the top mapping and skip a page. * If there is no space for PAGE_SIZE above * that, mmap will ignore our address hint. + * + * We allocate a "fake" unlinked shmem file because anonymous + * memory might not be granted execute permission when the selinux + * security hooks have their way. Only do this for 2.6.28 or higher + * since shmem_file_setup() isn't exported before that. */ vma = rb_entry(rb_last(&mm->mm_rb), struct vm_area_struct, vm_rb); addr = vma->vm_end + PAGE_SIZE; +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) + file = shmem_file_setup("uprobes/ssol", nbytes, VM_NORESERVE); + if (file) { + addr = do_mmap_pgoff(file, addr, nbytes, PROT_EXEC, + MAP_PRIVATE, 0); + fput(file); + } + if (!file || addr & ~PAGE_MASK) { +#else addr = do_mmap_pgoff(NULL, addr, nbytes, PROT_EXEC, MAP_PRIVATE|MAP_ANONYMOUS, 0); if (addr & ~PAGE_MASK) { +#endif up_write(&mm->mmap_sem); mmput(mm); - printk(KERN_ERR "Uprobes failed to allocate a vma for" - " pid/tgid %d/%d for single-stepping out of line.\n", - current->pid, current->tgid); +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,28) + if (!file) + printk(KERN_ERR "Uprobes shmem_file_setup failed while" + " allocating vma for pid/tgid %d/%d for" + " single-stepping out of line.\n", + current->pid, current->tgid); + else +#endif + printk(KERN_ERR "Uprobes failed to allocate a vma for" + " pid/tgid %d/%d for single-stepping out of" + " line.\n", current->pid, current->tgid); return addr; } @@ -221,6 +221,10 @@ struct systemtap_session void print_error_source (std::ostream&, std::string&, const token* tok); void print_warning (const std::string& w, const token* tok = 0); + + // Location of semaphores to activate sdt probes + std::map<Dwarf_Addr, derived_probe*> sdt_semaphore_addr; + // NB: It is very important for all of the above (and below) fields // to be cleared in the systemtap_session ctor (elaborate.cxx) // and/or main.cxx(main). diff --git a/tapset-utrace.cxx b/tapset-utrace.cxx index 22682776..639f0c20 100644 --- a/tapset-utrace.cxx +++ b/tapset-utrace.cxx @@ -716,6 +716,21 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s, break; } s.op->line() << " .engine_attached=0,"; + map<Dwarf_Addr, derived_probe*>::iterator its; + if (s.sdt_semaphore_addr.empty()) + s.op->line() << " .sdt_sem_address=(unsigned long)0x0,"; + else + for (its = s.sdt_semaphore_addr.begin(); + its != s.sdt_semaphore_addr.end(); + its++) + { + if (p == ((struct utrace_derived_probe*)(its->second))) + { + s.op->line() << " .sdt_sem_address=(unsigned long)0x" << hex << its->first << dec << "ULL,"; + break; + } + } + s.op->line() << " .tsk=0,"; s.op->line() << " },"; } @@ -750,6 +765,8 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "struct utrace_engine_ops ops;"; s.op->newline() << "unsigned long events;"; s.op->newline() << "int engine_attached;"; + s.op->newline() << "struct task_struct *tsk;"; + s.op->newline() << "unsigned long sdt_sem_address;"; s.op->newline(-1) << "};"; @@ -872,6 +889,15 @@ 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_address != 0) {"; + s.op->newline(1) << "size_t sdt_semaphore;"; + s.op->newline() << "p->tsk = tsk;"; + s.op->newline() << "__access_process_vm (tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);"; + s.op->newline() << "sdt_semaphore += 1;"; + s.op->newline() << "__access_process_vm (tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);"; + s.op->newline(-1) << "}"; + s.op->newline(-1) << "}"; // Since this engine could be attached to multiple threads, don't @@ -1017,6 +1043,26 @@ utrace_derived_probe_group::emit_module_exit (systemtap_session& s) s.op->newline() << "stap_utrace_detach_ops(&p->ops);"; s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; + + int sem_idx = 0; + if (! s.sdt_semaphore_addr.empty()) + for (p_b_path_iterator it = probes_by_path.begin(); + it != probes_by_path.end(); it++) + { + s.op->newline() << "{"; + s.op->indent(1); + s.op->newline() << "size_t sdt_semaphore;"; + s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_utrace_probes); i++) {"; + s.op->newline(1) << "struct stap_utrace_probe *p = &stap_utrace_probes[i];"; + + s.op->newline() << "__access_process_vm (p->tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);"; + s.op->newline() << "sdt_semaphore -= 1;"; + s.op->newline() << "__access_process_vm (p->tsk, p->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);"; + + s.op->newline(-1) << "}"; + s.op->newline(-1) << "}"; + sem_idx += it->second.size() - 1; + } } diff --git a/tapset/DEVGUIDE b/tapset/DEVGUIDE index 693521a8..5d7c8658 100644 --- a/tapset/DEVGUIDE +++ b/tapset/DEVGUIDE @@ -244,6 +244,23 @@ potentially be invalid. If you're not sure, err on the side of caution. The cost of using kread() is small compared to the cost of your tapset inadvertently crashing a system! +Add the string + /* pure */ +into the body of the embedded-C function if it has no side-effects +such as changing external state, so that systemtap could elide +(optimize away) a call to the function if its results are unused. + +Add the string + /* unprivileged */ +into the body of the embedded-C function, only if it is safe for use +by unprivileged users. In general, this requires the function to be +absolutely robust with respect to its inputs, and expose/modify no +information except that belonging to the user's own processes. +(The assert_is_myproc() macro may help enforce this.) Roughly +speaking, it should only perform operations that the same user +could already do from ordinary userspace interfaces. + + Review & Submission ------------------- All new tapsets and major changes should be reviewed "early and often" diff --git a/tapset/context-symbols.stp b/tapset/context-symbols.stp index e4406d9b..3ec7a866 100644 --- a/tapset/context-symbols.stp +++ b/tapset/context-symbols.stp @@ -8,7 +8,7 @@ // later version. // <tapsetdescription> // Context functions provide additional information about where an event occurred. These functions can -//provide information such as a backtrace to where the event occured and the current register values for the +//provide information such as a backtrace to where the event occurred and the current register values for the //processor. // </tapsetdescription> %{ @@ -19,7 +19,7 @@ /** * sfunction print_stack - Print out stack from string. - * @stk: String with list of hexidecimal addresses. + * @stk: String with list of hexadecimal addresses. * * Perform a symbolic lookup of the addresses in the given string, * which is assumed to be the result of a prior call to @@ -138,7 +138,7 @@ function symname:string (addr: long) %{ /* pure */ * Description: Returns the (function) symbol name associated with the * given address if known, plus the module name (between brackets) and * the offset inside the module, plus the size of the symbol function. - * If any element is not known it will be ommitted and if the symbol name + * If any element is not known it will be omitted and if the symbol name * is unknown it will return the hex string for the given address. */ function symdata:string (addr: long) %{ /* pure */ diff --git a/tapset/context-unwind.stp b/tapset/context-unwind.stp index d6654d25..4ad45dba 100644 --- a/tapset/context-unwind.stp +++ b/tapset/context-unwind.stp @@ -8,7 +8,7 @@ // later version. // <tapsetdescription> // Context functions provide additional information about where an event occurred. These functions can -//provide information such as a backtrace to where the event occured and the current register values for the +//provide information such as a backtrace to where the event occurred and the current register values for the //processor. // </tapsetdescription> %{ diff --git a/tapset/context.stp b/tapset/context.stp index 92c325ce..226e3ee5 100644 --- a/tapset/context.stp +++ b/tapset/context.stp @@ -7,8 +7,8 @@ // Public License (GPL); either version 2, or (at your option) any // later version. // <tapsetdescription> -// Context functions provide additional information about where an event occurred. These functions can -//provide information such as a backtrace to where the event occured and the current register values for the +// Context functions provide additional information about where an event occurred. These functions can +//provide information such as a backtrace to where the event occurred and the current register values for the //processor. // </tapsetdescription> @@ -34,28 +34,28 @@ function print_regs () %{ /** * sfunction execname - Returns the execname of a target process (or group of processes). */ -function execname:string () %{ /* pure */ +function execname:string () %{ /* pure */ /* unprivileged */ strlcpy (THIS->__retvalue, current->comm, MAXSTRINGLEN); %} /** * sfunction pid - Returns the ID of a target process. */ -function pid:long () %{ /* pure */ +function pid:long () %{ /* pure */ /* unprivileged */ THIS->__retvalue = current->tgid; %} /** * sfunction tid - Returns the thread ID of a target process. */ -function tid:long () %{ /* pure */ +function tid:long () %{ /* pure */ /* unprivileged */ THIS->__retvalue = current->pid; %} /** * sfunction ppid - Returns the process ID of a target process's parent process. */ -function ppid:long () %{ /* pure */ +function ppid:long () %{ /* pure */ /* unprivileged */ #if defined(STAPCONF_REAL_PARENT) THIS->__retvalue = current->real_parent->tgid; #else @@ -66,7 +66,7 @@ function ppid:long () %{ /* pure */ /** * sfunction pgrp - Returns the process group ID of the current process. */ -function pgrp:long () %{ /* pure */ +function pgrp:long () %{ /* pure */ /* unprivileged */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) struct signal_struct *ss = kread( &(current->signal) ); THIS->__retvalue = kread ( &(ss->pgrp) ); @@ -78,11 +78,11 @@ function pgrp:long () %{ /* pure */ /** * sfunction sid - Returns the session ID of the current process. - * + * * The session ID of a process is the process group ID of the session * leader. Session ID is stored in the signal_struct since Kernel 2.6.0. */ -function sid:long () %{ /* pure */ +function sid:long () %{ /* pure */ /* unprivileged */ #if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24) struct signal_struct *ss = kread( &(current->signal) ); THIS->__retvalue = kread ( &(ss->session) ); @@ -95,7 +95,7 @@ function sid:long () %{ /* pure */ /** * sfunction pexecname - Returns the execname of a target process's parent process. */ -function pexecname:string () %{ /* pure */ +function pexecname:string () %{ /* pure */ /* unprivileged */ #if defined(STAPCONF_REAL_PARENT) strlcpy (THIS->__retvalue, current->real_parent->comm, MAXSTRINGLEN); #else @@ -106,61 +106,59 @@ function pexecname:string () %{ /* pure */ /** * sfunction gid - Returns the group ID of a target process. */ -function gid:long () %{ /* pure */ +function gid:long () %{ /* pure */ /* unprivileged */ #ifdef STAPCONF_TASK_UID - THIS->__retvalue = current->gid; + THIS->__retvalue = current->gid; #else - THIS->__retvalue = current_gid(); + THIS->__retvalue = current_gid(); #endif %} /** * sfunction egid - Returns the effective gid of a target process. */ -function egid:long () %{ /* pure */ +function egid:long () %{ /* pure */ /* unprivileged */ #ifdef STAPCONF_TASK_UID - THIS->__retvalue = current->egid; + THIS->__retvalue = current->egid; #else - THIS->__retvalue = current_egid(); + THIS->__retvalue = current_egid(); #endif %} /** * sfunction uid - Returns the user ID of a target process. */ -function uid:long () %{ /* pure */ +function uid:long () %{ /* pure */ /* unprivileged */ #ifdef STAPCONF_TASK_UID - THIS->__retvalue = current->uid; + THIS->__retvalue = current->uid; #else - THIS->__retvalue = current_uid(); + THIS->__retvalue = current_uid(); #endif %} /** * sfunction euid - Return the effective uid of a target process. */ -function euid:long () %{ /* pure */ +function euid:long () %{ /* pure */ /* unprivileged */ #ifdef STAPCONF_TASK_UID - THIS->__retvalue = current->euid; + THIS->__retvalue = current->euid; #else - THIS->__retvalue = current_euid(); + THIS->__retvalue = current_euid(); #endif %} + /** - * sfunction is_myproc - Determines if the current probe point has occurred in - * the user's own process. + * sfunction is_myproc - Determines if the current probe point has occurred in the user's own process. * * Return 1 if the current probe point has occurred in the user's own process. */ function is_myproc:long () %{ /* pure */ /* unprivileged */ -#ifdef STAPCONF_TASK_UID - THIS->__retvalue = (current->euid == _stp_uid); -#else - THIS->__retvalue = (task_euid(current) == _stp_uid); -#endif + THIS->__retvalue = is_myproc(); %} + + // cpuid() is not documented function cpuid:long () %{ /* pure */ THIS->__retvalue = smp_processor_id(); @@ -169,7 +167,7 @@ function cpuid:long () %{ /* pure */ /** * sfunction cpu - Returns the current cpu number. */ -function cpu:long () %{ /* pure */ +function cpu:long () %{ /* pure */ /* unprivileged */ THIS->__retvalue = smp_processor_id(); %} @@ -177,9 +175,9 @@ function cpu:long () %{ /* pure */ * sfunction pp - Return the probe point associated with the currently running probe handler, * including alias and wildcard expansion effects * Context: - * The current probe point. + * The current probe point. */ -function pp:string () %{ /* pure */ +function pp:string () %{ /* pure */ /* unprivileged */ strlcpy (THIS->__retvalue, CONTEXT->probe_point, MAXSTRINGLEN); %} @@ -191,7 +189,7 @@ function pp:string () %{ /* pure */ * For example, <command>registers_valid()</command> returns 0 * when called from a begin or end probe. */ -function registers_valid:long () %{ /* pure */ +function registers_valid:long () %{ /* pure */ /* unprivileged */ THIS->__retvalue = (CONTEXT->regs != NULL); %} @@ -200,7 +198,7 @@ function registers_valid:long () %{ /* pure */ * * Return 1 if the probe point occurred in user-mode. */ -function user_mode:long () %{ /* pure */ /* currently a user-mode address? */ +function user_mode:long () %{ /* pure */ /* unprivileged */ if (CONTEXT->regs) { #if defined(__i386__) || defined(__x86_64__) THIS->__retvalue = (uint64_t) user_mode_vm (CONTEXT->regs); @@ -221,14 +219,14 @@ function user_mode:long () %{ /* pure */ /* currently a user-mode address? */ function is_return:long () %{ /* pure */ if (CONTEXT->pi) THIS->__retvalue = 1; - else - THIS->__retvalue = 0; + else + THIS->__retvalue = 0; %} /** * sfunction target - Return the process ID of the target process. */ -function target:long () %{ /* pure */ +function target:long () %{ /* pure */ /* unprivileged */ THIS->__retvalue = _stp_target; %} @@ -239,7 +237,7 @@ function target:long () %{ /* pure */ /// <remark>FIXME: need description.</remark> /// </para> ///</formalpara> -function module_name:string () %{ /* pure */ +function module_name:string () %{ /* pure */ /* unprivileged */ strlcpy(THIS->__retvalue, THIS_MODULE->name, MAXSTRINGLEN); %} @@ -285,14 +283,15 @@ function stack_unused:long () %{ /* pure */ * sfunction uaddr - User space address of current running task. EXPERIMENTAL. * * Description: Returns the address in userspace that the current - * task was at when the probe occured. When the current running task + * task was at when the probe occurred. When the current running task * isn't a user space thread, or the address cannot be found, zero * is returned. Can be used to see where the current task is combined * with usymname() or symdata(). Often the task will be in the VDSO * where it entered the kernel. FIXME - need VDSO tracking support #10080. */ -function uaddr:long () %{ /* pure */ +function uaddr:long () %{ /* pure */ /* unprivileged */ int64_t addr = 0; + assert_is_myproc(); if (current->mm) { struct pt_regs *uregs; diff --git a/tapset/conversions.stp b/tapset/conversions.stp index fdf00bd3..a218025b 100644 --- a/tapset/conversions.stp +++ b/tapset/conversions.stp @@ -1,5 +1,5 @@ // conversions tapset -// Copyright (C) 2005-2008 Red Hat Inc. +// Copyright (C) 2005-2009 Red Hat Inc. // Copyright (C) 2007 Intel Corporation. // // This file is part of systemtap, and is free software. You can @@ -79,15 +79,18 @@ deref_fault: /* branched to from kread() */ function user_string:string (addr:long) { return user_string2 (addr, "<unknown>") } -function user_string2:string (addr:long, err_msg:string) %{ /* pure */ +function user_string2:string (addr:long, err_msg:string) %{ /* pure */ /* unprivileged */ + assert_is_myproc(); if (_stp_strncpy_from_user (THIS->__retvalue, (const char __user*) (uintptr_t) THIS->addr, MAXSTRINGLEN) < 0) strlcpy (THIS->__retvalue, THIS->err_msg, MAXSTRINGLEN); %} -function user_string_warn:string (addr:long) %{ /* pure */ - long rc = _stp_strncpy_from_user (THIS->__retvalue, +function user_string_warn:string (addr:long) %{ /* pure */ /* unprivileged */ + long rc; + assert_is_myproc(); + rc = _stp_strncpy_from_user (THIS->__retvalue, (const char __user*) (uintptr_t) THIS->addr, MAXSTRINGLEN); if (rc < 0) { // NB: using error_buffer to get local space for the warning, but we're @@ -100,7 +103,8 @@ function user_string_warn:string (addr:long) %{ /* pure */ } %} -function user_string_quoted:string (addr:long) %{ /* pure */ +function user_string_quoted:string (addr:long) %{ /* pure */ /* unprivileged */ + assert_is_myproc(); if (THIS->addr == 0) strlcpy (THIS->__retvalue, "NULL", MAXSTRINGLEN); else @@ -113,8 +117,9 @@ function user_string_n:string (addr:long, n:long) { return user_string_n2(addr, n, "<unknown>") } -function user_string_n2:string (addr:long, n:long, err_msg:string) %{ /* pure */ +function user_string_n2:string (addr:long, n:long, err_msg:string) %{ /* pure */ /* unprivileged */ long len = THIS->n + 1; + assert_is_myproc(); len = (len > MAXSTRINGLEN) ? MAXSTRINGLEN : len; if (_stp_strncpy_from_user(THIS->__retvalue, (char __user *) (uintptr_t) THIS->addr, @@ -124,10 +129,11 @@ function user_string_n2:string (addr:long, n:long, err_msg:string) %{ /* pure */ THIS->__retvalue[len - 1] = '\0'; %} -function user_string_n_warn:string (addr:long, n:long) %{ /* pure */ +function user_string_n_warn:string (addr:long, n:long) %{ /* pure */ /* unprivileged */ long len = THIS->n + 1; long rc; + assert_is_myproc(); len = (len > MAXSTRINGLEN) ? MAXSTRINGLEN : len; rc = _stp_strncpy_from_user(THIS->__retvalue, (char __user *) (uintptr_t) THIS->addr, len); @@ -143,8 +149,10 @@ function user_string_n_warn:string (addr:long, n:long) %{ /* pure */ THIS->__retvalue[len - 1] = '\0'; %} -function user_string_n_quoted:string (addr:long, n:long) %{ /* pure */ - long len = THIS->n + 1; +function user_string_n_quoted:string (addr:long, n:long) %{ /* pure */ /* unprivileged */ + long len; + assert_is_myproc(); + len = THIS->n + 1; if (THIS->addr == 0) strlcpy(THIS->__retvalue, "NULL", MAXSTRINGLEN); else @@ -155,7 +163,8 @@ function user_string_n_quoted:string (addr:long, n:long) %{ /* pure */ // When userspace data is not accessible, the following functions return 0 -function user_short:long (addr:long) %{ /* pure */ +function user_short:long (addr:long) %{ /* pure */ /* unprivileged */ + assert_is_myproc(); if (!access_ok(VERIFY_READ, (short *) (intptr_t) THIS->addr, sizeof(short))) goto fault; if (__stp_get_user(THIS->__retvalue, (short *) (intptr_t) THIS->addr)) { @@ -164,7 +173,8 @@ fault: } %} -function user_short_warn:long (addr:long) %{ /* pure */ +function user_short_warn:long (addr:long) %{ /* pure */ /* unprivileged */ + assert_is_myproc(); if (!access_ok(VERIFY_READ, (short *) (intptr_t) THIS->addr, sizeof(short))) goto fault; if (__stp_get_user(THIS->__retvalue, (short *) (intptr_t) THIS->addr)) { @@ -176,7 +186,8 @@ fault: } %} -function user_int:long (addr:long) %{ /* pure */ +function user_int:long (addr:long) %{ /* pure */ /* unprivileged */ + assert_is_myproc(); if (!access_ok(VERIFY_READ, (int *) (intptr_t) THIS->addr, sizeof(int))) goto fault; if (__stp_get_user(THIS->__retvalue, (int *) (intptr_t) THIS->addr)) { @@ -185,7 +196,8 @@ fault: } %} -function user_int_warn:long (addr:long) %{ /* pure */ +function user_int_warn:long (addr:long) %{ /* pure */ /* unprivileged */ + assert_is_myproc(); if (!access_ok(VERIFY_READ, (int *) (intptr_t) THIS->addr, sizeof(int))) goto fault; if (__stp_get_user(THIS->__retvalue, (int *) (intptr_t) THIS->addr)) { @@ -197,7 +209,8 @@ fault: } %} -function user_long:long (addr:long) %{ /* pure */ +function user_long:long (addr:long) %{ /* pure */ /* unprivileged */ + assert_is_myproc(); if (!access_ok(VERIFY_READ, (long *) (intptr_t) THIS->addr, sizeof(long))) goto fault; if (__stp_get_user(THIS->__retvalue, (long *) (intptr_t) THIS->addr)) { @@ -206,7 +219,8 @@ fault: } %} -function user_long_warn:long (addr:long) %{ /* pure */ +function user_long_warn:long (addr:long) %{ /* pure */ /* unprivileged */ + assert_is_myproc(); if (!access_ok(VERIFY_READ, (long *) (intptr_t) THIS->addr, sizeof(long))) goto fault; if (__stp_get_user(THIS->__retvalue, (long *) (intptr_t) THIS->addr)) { @@ -218,7 +232,8 @@ fault: } %} -function user_char:long (addr:long) %{ /* pure */ +function user_char:long (addr:long) %{ /* pure */ /* unprivileged */ + assert_is_myproc(); if (!access_ok(VERIFY_READ, (char *) (intptr_t) THIS->addr, sizeof(char))) goto fault; if (__stp_get_user(THIS->__retvalue, (char *) (intptr_t) THIS->addr)) { @@ -227,7 +242,8 @@ fault: } %} -function user_char_warn:long (addr:long) %{ /* pure */ +function user_char_warn:long (addr:long) %{ /* pure */ /* unprivileged */ + assert_is_myproc(); if (!access_ok(VERIFY_READ, (char *) (intptr_t) THIS->addr, sizeof(char))) goto fault; if (__stp_get_user(THIS->__retvalue, (char *) (intptr_t) THIS->addr)) { diff --git a/tapset/networking.stp b/tapset/networking.stp index f6d78536..0c9d8afb 100644 --- a/tapset/networking.stp +++ b/tapset/networking.stp @@ -8,11 +8,17 @@ // <tapsetdescription> // This family of probe points is used to probe the activities of the network device. // </tapsetdescription> + +/* A function that returns the device name given the net_device struct */ +function get_netdev_name:string (addr:long) { + return kernel_string(@cast(addr, "net_device")->name) +} + /** - * probe netdev.receive - Data recieved from network device. + * probe netdev.receive - Data received from network device. * @dev_name: The name of the device. e.g: eth0, ath1. * @length: The length of the receiving buffer. - * @protocol: Protocol of recieved packet. + * @protocol: Protocol of received packet. * */ /// <varlistentry><term>protocol</term> @@ -66,7 +72,7 @@ probe netdev.receive * @dev_name: The name of the device. e.g: eth0, ath1. * @length: The length of the transmit buffer. * @protocol: The protocol of this packet. - * @truesize: The size of the the data to be transmitted. + * @truesize: The size of the data to be transmitted. * */ // Queue a buffer for transmission to a network device @@ -78,3 +84,174 @@ probe netdev.transmit protocol = $skb->protocol truesize = $skb->truesize } + +/** + * probe netdev.change_mtu - Called when the netdev MTU is changed + * @dev_name: The device that will have the MTU changed + * @old_mtu: The current MTU + * @new_mtu: The new MTU + */ +probe netdev.change_mtu + = kernel.function("dev_set_mtu") +{ + old_mtu = $dev->mtu + new_mtu = $new_mtu + dev_name = get_netdev_name($dev) +} + +/** + * probe netdev.open - Called when the device is opened + * @dev_name: The device that is going to be opened + */ +probe netdev.open + = kernel.function("dev_open") +{ + dev_name = get_netdev_name($dev) +} + +/** + * probe netdev.close - Called when the device is closed + * @dev_name: The device that is going to be closed + */ +probe netdev.close + = kernel.function("dev_close") +{ + dev_name = get_netdev_name($dev) +} + +/** + * probe netdev.hard_transmit - Called when the devices is going to TX (hard) + * @dev_name: The device scheduled to transmit + * @protocol: The protocol used in the transmission + * @length: The length of the transmit buffer. + * @truesize: The size of the data to be transmitted. + */ +probe netdev.hard_transmit + = kernel.function("dev_hard_start_xmit") +{ + dev_name = get_netdev_name($dev) + protocol = $skb->protocol + length = $skb->len + truesize = $skb->truesize +} + +/** + * probe netdev.rx - Called when the device is going to receive a packet + * @dev_name: The device received the packet + * @protocol: The packet protocol + */ +probe netdev.rx + = kernel.function("netif_rx") +{ + netdev = $skb->dev + dev_name = get_netdev_name(netdev) + protocol = $skb->protocol +} + +/** + * probe netdev.change_rx_flag - Called when the device RX flag will be changed + * @dev_name: The device that will be changed + * @flags: The new flags + */ +probe netdev.change_rx_flag + = kernel.function("dev_change_rx_flags") +{ + dev_name = get_netdev_name($dev) + flags = $flags +} + +/** + * probe netdev.set_promiscuity - Called when the device enters/leaves promiscuity + * @dev_name: The device that is entering/leaving promiscuity mode + * @enable: If the device is entering promiscuity mode + * @disable: If the device is leaving promiscuity mode + * @inc: Count the number of promiscuity openers + */ +probe netdev.set_promiscuity + = kernel.function("dev_set_promiscuity") +{ + dev_name = get_netdev_name($dev) + if ($inc){ + enable = 1 + } else { + disable = 1 + } + inc = $inc +} + +/** + * probe netdev.ioctl - Called when the device suffers an IOCTL + * @cmd: The IOCTL request + * @arg: The IOCTL argument (usually the netdev interface) + */ +probe netdev.ioctl + = kernel.function("dev_ioctl") +{ + cmd = $cmd + arg = user_string($arg) +} + +/** + * probe netdev.register - Called when the device is registered + * @dev_name: The device that is going to be registered + */ +probe netdev.register + = kernel.function("register_netdevice"), + kernel.function("register_netdev") +{ + dev_name = get_netdev_name($dev) +} + +/** + * probe netdev.unregister - Called when the device is being unregistered + * @dev_name: The device that is going to be unregistered + */ +probe netdev.unregister + = kernel.function("unregister_netdev") +{ + dev_name = get_netdev_name($dev) +} + +/** + * probe netdev.get_stats - Called when someone asks the device statistics + * @dev_name: The device that is going to provide the statistics + */ +probe netdev.get_stats + = kernel.function("dev_get_stats") +{ + dev_name = get_netdev_name($dev) +} + +/** + * probe netdev.change_mac - Called when the netdev_name has the MAC changed + * @dev_name: The device that will have the MTU changed + * @mac_len: The MAC length + * @old_mac: The current MAC address + * @new_mac: The new MAC address + */ +probe netdev.change_mac + = kernel.function("dev_set_mac_address") +{ + dev_name = get_netdev_name($dev) + mac_len = $dev->addr_len + + // Old MAC Address + zero = $dev->dev_addr[0] + one = $dev->dev_addr[1] + two = $dev->dev_addr[2] + three =$dev->dev_addr[3] + four = $dev->dev_addr[4] + five = $dev->dev_addr[5] + old_mac = sprintf("%02x:%02x:%02x:%02x:%02x:%02x", + zero, one, two, three, four, five) + + // New MAC Address + zero = $sa->sa_data[0] + one = $sa->sa_data[1] + two = $sa->sa_data[2] + three =$sa->sa_data[3] + four =$sa->sa_data[4] + five = $sa->sa_data[5] + new_mac = sprintf("%02x:%02x:%02x:%02x:%02x:%02x", + zero, one, two, three, four, five) +} diff --git a/tapset/signal.stp b/tapset/signal.stp index 02c761c3..2e10af0c 100644 --- a/tapset/signal.stp +++ b/tapset/signal.stp @@ -414,7 +414,7 @@ probe signal.syskill.return = syscall.kill.return * * The <command>tkill</command> call is analogous to <command>kill(2)</command>, * except that it also allows a process within a specific thread group to - * be targetted. Such processes are targetted through their unique + * be targeted. Such processes are targeted through their unique * thread IDs (TID). */ probe signal.systkill = syscall.tkill @@ -632,7 +632,7 @@ probe signal.procmask.return = kernel.function("sigprocmask").return /** - * probe signal.flush - Flusing all pending signals for a task + * probe signal.flush - Flushing all pending signals for a task * @task: The task handler of the process performing the flush * @sig_pid: The PID of the process associated with the task * performing the flush diff --git a/tapset/socket.stp b/tapset/socket.stp index de778d7c..b4d4981c 100644 --- a/tapset/socket.stp +++ b/tapset/socket.stp @@ -81,7 +81,7 @@ probe socket.receive = socket.recvmsg.return, * The message sender * * Fires at the beginning of sending a message on a socket - * via the the sock_sendmsg() function + * via the sock_sendmsg() function */ probe socket.sendmsg = kernel.function ("sock_sendmsg") { diff --git a/tapset/string.stp b/tapset/string.stp index 4b0a2a0d..92750b6b 100644 --- a/tapset/string.stp +++ b/tapset/string.stp @@ -8,7 +8,7 @@ * @param s string * @return Returns the length of the string. */ -function strlen:long(s:string) %{ /* pure */ +function strlen:long(s:string) %{ /* pure */ /* unprivileged */ THIS->__retvalue = strlen(THIS->s); %} @@ -19,7 +19,7 @@ function strlen:long(s:string) %{ /* pure */ * @param length Length of string to return. * @return Returns the substring. */ -function substr:string(str:string,start:long, length:long) %{ /* pure */ +function substr:string(str:string,start:long, length:long) %{ /* pure */ /* unprivileged */ int length = THIS->length >= MAXSTRINGLEN ? MAXSTRINGLEN : THIS->length + 1; if (THIS->start >= 0 && length > 0 && THIS->start < strlen(THIS->str)) strlcpy(THIS->__retvalue, THIS->str + THIS->start, length); @@ -31,7 +31,7 @@ function substr:string(str:string,start:long, length:long) %{ /* pure */ * @param pos the given position. 0 = start of the string * @return Returns the char in given position of string. */ -function stringat:long(str:string, pos:long) %{ /* pure */ +function stringat:long(str:string, pos:long) %{ /* pure */ /* unprivileged */ if (THIS->pos >= 0 && THIS->pos < strlen(THIS->str)) THIS->__retvalue = THIS->str[THIS->pos]; else @@ -44,7 +44,7 @@ function stringat:long(str:string, pos:long) %{ /* pure */ * @param s2 string * @return Returns 1 if s2 is in s1. Otherwise 0. */ -function isinstr:long(s1:string,s2:string) %{ /* pure */ +function isinstr:long(s1:string,s2:string) %{ /* pure */ /* unprivileged */ if (strstr(THIS->s1,THIS->s2) != NULL) THIS->__retvalue = 1; else @@ -58,13 +58,13 @@ function isinstr:long(s1:string,s2:string) %{ /* pure */ * replaced by the corresponding escape sequence in the returned * string. */ -function text_str:string(input:string) -%{ /* pure */ +function text_str:string(input:string) +%{ /* pure */ /* unprivileged */ _stp_text_str(THIS->__retvalue, THIS->input, 0, 0, 0); %} function text_strn:string(input:string, len:long, quoted:long) -%{ /* pure */ +%{ /* pure */ /* unprivileged */ _stp_text_str(THIS->__retvalue, THIS->input, THIS->len, THIS->quoted, 0); %} @@ -77,7 +77,7 @@ function text_strn:string(input:string, len:long, quoted:long) * delim Token delimiter. Set of characters that delimit the tokens. */ function tokenize:string(input:string, delim:string) -%{ /* pure */ +%{ /* unprivileged */ static char str[MAXSTRINGLEN]; static char *str_start; static char *str_end; @@ -106,7 +106,7 @@ function tokenize:string(input:string, delim:string) * @return Returns the parent string with substrings replaced. Else returns parent string. */ function str_replace:string (prnt_str:string, srch_str:string, rplc_str:string) -%{ +%{ /* pure */ /* unprivileged */ char *ptr = THIS->prnt_str; char *ptr_base = THIS->prnt_str; int strlen_srch_str = strlen(THIS->srch_str); @@ -135,7 +135,7 @@ function str_replace:string (prnt_str:string, srch_str:string, rplc_str:string) * base The base to use */ function strtol:long(str:string, base:long) -%{ /* pure */ +%{ /* pure */ /* unprivileged */ THIS->__retvalue = simple_strtol(THIS->str, NULL, THIS->base); %} diff --git a/tapset/timestamp_gtod.stp b/tapset/timestamp_gtod.stp index b916a3b1..acf525f0 100644 --- a/tapset/timestamp_gtod.stp +++ b/tapset/timestamp_gtod.stp @@ -17,7 +17,7 @@ * * Return the number of nanoseconds since the UNIX epoch. */ -function gettimeofday_ns:long () %{ /* pure */ +function gettimeofday_ns:long () %{ /* pure */ /* unprivileged */ /* NOTE: we can't use do_gettimeofday because we could be called from a * context where xtime_lock is already held. See bug #2525. */ THIS->__retvalue = _stp_gettimeofday_ns(); diff --git a/tapset/ucontext-symbols.stp b/tapset/ucontext-symbols.stp index 5502f5cd..e884a36b 100644 --- a/tapset/ucontext-symbols.stp +++ b/tapset/ucontext-symbols.stp @@ -9,7 +9,7 @@ // <tapsetdescription> // User context symbol functions provide additional information about // addresses from an application. These functions can provide -// information about the user space map (library) that the event occured or +// information about the user space map (library) that the event occurred or // the function symbol of an address. // </tapsetdescription> @@ -43,17 +43,18 @@ function usymname:string (addr: long) %{ /* pure */ * given address in the current task if known, plus the module name * (between brackets) and the offset inside the module (shared library), * plus the size of the symbol function. If any element is not known it - * will be ommitted and if the symbol name is unknown it will return the + * will be omitted and if the symbol name is unknown it will return the * hex string for the given address. */ -function usymdata:string (addr: long) %{ /* pure */ +function usymdata:string (addr: long) %{ /* pure */ /* unprivileged */ + assert_is_myproc(); _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr, current, 1); %} /** * sfunction print_ustack - Print out stack for the current task from string. EXPERIMENTAL! - * @stk: String with list of hexidecimal addresses for the current task. + * @stk: String with list of hexadecimal addresses for the current task. * * Perform a symbolic lookup of the addresses in the given string, * which is assumed to be the result of a prior call to @@ -63,9 +64,10 @@ function usymdata:string (addr: long) %{ /* pure */ * name of the function containing the address, and an estimate of * its position within that function. Return nothing. */ -function print_ustack(stk:string) %{ +function print_ustack(stk:string) %{ /* pure */ /* unprivileged */ char *ptr = THIS->stk; char *tok = strsep(&ptr, " "); + assert_is_myproc(); while (tok && *tok) { _stp_print_char(' '); _stp_usymbol_print (simple_strtol(tok, NULL, 16), current); diff --git a/tapset/ucontext-unwind.stp b/tapset/ucontext-unwind.stp index df275d4b..e1a8ade3 100644 --- a/tapset/ucontext-unwind.stp +++ b/tapset/ucontext-unwind.stp @@ -24,7 +24,8 @@ * Equivalent to <command>print_ustack(ubacktrace())</command>, * except that deeper stack nesting may be supported. Return nothing. */ -function print_ubacktrace () %{ +function print_ubacktrace () %{ /* unprivileged */ + assert_is_myproc(); if (CONTEXT->regs) { _stp_stack_print(CONTEXT->regs, 1, CONTEXT->pi, MAXTRACE, current); @@ -41,7 +42,8 @@ function print_ubacktrace () %{ * string length. Returns empty string when current probe point cannot * determine user backtrace. */ -function ubacktrace:string () %{ /* pure */ +function ubacktrace:string () %{ /* pure */ /* unprivileged */ + assert_is_myproc(); if (CONTEXT->regs) _stp_stack_snprint (THIS->__retvalue, MAXSTRINGLEN, CONTEXT->regs, 0, CONTEXT->pi, MAXTRACE, diff --git a/tapset/utrace.stp b/tapset/utrace.stp index 0d26ed5f..4f841b30 100644 --- a/tapset/utrace.stp +++ b/tapset/utrace.stp @@ -4,23 +4,38 @@ #include "syscall.h" %} -function _utrace_syscall_nr:long () %{ /* pure */ - THIS->__retvalue = syscall_get_nr(current, CONTEXT->regs); +function _utrace_syscall_nr:long () %{ /* pure */ /* unprivileged */ + assert_is_myproc(); + if (! CONTEXT->regs) { + CONTEXT->last_error = "invalid call without context registers"; + } else { + THIS->__retvalue = syscall_get_nr(current, CONTEXT->regs); + } %} -function _utrace_syscall_arg:long (n:long) %{ /* pure */ +function _utrace_syscall_arg:long (n:long) %{ /* pure */ /* unprivileged */ unsigned long arg = 0; - syscall_get_arguments(current, CONTEXT->regs, (int)THIS->n, 1, &arg); + assert_is_myproc(); + if (! CONTEXT->regs) { + CONTEXT->last_error = "invalid call without context registers"; + } else { + syscall_get_arguments(current, CONTEXT->regs, (int)THIS->n, 1, &arg); + } THIS->__retvalue = arg; %} -function _utrace_syscall_return:long () %{ /* pure */ +function _utrace_syscall_return:long () %{ /* pure */ /* unprivileged */ /* * Here's the reason for the "unsigned long" cast. Since all * values inside systemtap are 64-bit numbers, return values were * getting sign extended. This caused return values to not match * up with the same values passes as arguments. */ - THIS->__retvalue = (unsigned long)syscall_get_return_value(current, + assert_is_myproc(); + if (! CONTEXT->regs) { + CONTEXT->last_error = "invalid call without context registers"; + } else { + THIS->__retvalue = (unsigned long)syscall_get_return_value(current, CONTEXT->regs); + } %} diff --git a/tapsets.cxx b/tapsets.cxx index 977a92fa..53f8ace5 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -591,8 +591,9 @@ struct dwarf_query : public base_query enum dbinfo_reqt dbinfo_reqt; enum dbinfo_reqt assess_dbinfo_reqt(); - function_spec_type parse_function_spec(string & spec); + void parse_function_spec(const string & spec); function_spec_type spec_type; + vector<string> scopes; string function; string file; line_t line_type; @@ -697,9 +698,9 @@ dwarf_query::dwarf_query(probe * base_probe, has_mark = false; if (has_function_str) - spec_type = parse_function_spec(function_str_val); + parse_function_spec(function_str_val); else if (has_statement_str) - spec_type = parse_function_spec(statement_str_val); + parse_function_spec(statement_str_val); dbinfo_reqt = assess_dbinfo_reqt(); query_done = false; @@ -869,93 +870,124 @@ dwarf_query::handle_query_module() } -function_spec_type -dwarf_query::parse_function_spec(string & spec) +void +dwarf_query::parse_function_spec(const string & spec) { - string::const_iterator i = spec.begin(), e = spec.end(); + size_t src_pos, line_pos, dash_pos, scope_pos, next_scope_pos; - function.clear(); - file.clear(); - line[0] = 0; - line[1] = 0; - - while (i != e && *i != '@') + // look for named scopes + scope_pos = 0; + next_scope_pos = spec.find("::"); + while (next_scope_pos != string::npos) { - if (*i == ':' || *i == '+') - goto bad; - function += *i++; + scopes.push_back(spec.substr(scope_pos, next_scope_pos - scope_pos)); + scope_pos = next_scope_pos + 2; + next_scope_pos = spec.find("::", scope_pos); } - if (i == e) + // look for a source separator + src_pos = spec.find('@', scope_pos); + if (src_pos == string::npos) { - if (sess.verbose>2) - clog << "parsed '" << spec - << "' -> func '" << function - << "'\n"; - return function_alone; + function = spec.substr(scope_pos); + spec_type = function_alone; } - - if (i++ == e) - goto bad; - - while (i != e && *i != ':' && *i != '+') - file += *i++; - if (*i == ':') + else { - if (*(i + 1) == '*') - line_type = WILDCARD; + function = spec.substr(scope_pos, src_pos - scope_pos); + + // look for a line-number separator + line_pos = spec.find_first_of(":+", src_pos); + if (line_pos == string::npos) + { + file = spec.substr(src_pos + 1); + spec_type = function_and_file; + } else - line_type = ABSOLUTE; - } - else if (*i == '+') - line_type = RELATIVE; + { + file = spec.substr(src_pos + 1, line_pos - src_pos - 1); + + // classify the line spec + spec_type = function_file_and_line; + if (spec[line_pos] == '+') + line_type = RELATIVE; + else if (spec[line_pos + 1] == '*' && + spec.length() == line_pos + 2) + line_type = WILDCARD; + else + line_type = ABSOLUTE; - if (i == e) - { - if (sess.verbose>2) - clog << "parsed '" << spec - << "' -> func '"<< function - << "', file '" << file - << "'\n"; - return function_and_file; + if (line_type != WILDCARD) + try + { + // try to parse either N or N-M + dash_pos = spec.find('-', line_pos + 1); + if (dash_pos == string::npos) + line[0] = line[1] = lex_cast<int>(spec.substr(line_pos + 1)); + else + { + line_type = RANGE; + line[0] = lex_cast<int>(spec.substr(line_pos + 1, + dash_pos - line_pos - 1)); + line[1] = lex_cast<int>(spec.substr(dash_pos + 1)); + } + } + catch (runtime_error & exn) + { + goto bad; + } + } } - if (i++ == e) + if (function.empty() || + (spec_type != function_alone && file.empty())) goto bad; - try + if (sess.verbose > 2) { - if (line_type != WILDCARD) - { - string::const_iterator dash = i; + clog << "parsed '" << spec << "'"; - while (dash != e && *dash != '-') - dash++; - if (dash == e) - line[0] = line[1] = lex_cast<int>(string(i, e)); - else - { - line_type = RANGE; - line[0] = lex_cast<int>(string(i, dash)); - line[1] = lex_cast<int>(string(dash + 1, e)); - } - } + if (!scopes.empty()) + clog << ", scope '" << scopes[0] << "'"; + for (unsigned i = 1; i < scopes.size(); ++i) + clog << "::'" << scopes[i] << "'"; - if (sess.verbose>2) - clog << "parsed '" << spec - << "' -> func '"<< function - << "', file '" << file - << "', line " << line << "\n"; - return function_file_and_line; - } - catch (runtime_error & exn) - { - goto bad; + clog << ", func '" << function << "'"; + + if (spec_type != function_alone) + clog << ", file '" << file << "'"; + + if (spec_type == function_file_and_line) + { + clog << ", line "; + switch (line_type) + { + case ABSOLUTE: + clog << line[0]; + break; + + case RELATIVE: + clog << "+" << line[0]; + break; + + case RANGE: + clog << line[0] << " - " << line[1]; + break; + + case WILDCARD: + clog << "*"; + break; + } + } + + clog << endl; } - bad: - throw semantic_error("malformed specification '" + spec + "'", - base_probe->tok); + return; + +bad: + throw semantic_error("malformed specification '" + spec + "'", + base_probe->tok); } @@ -1335,6 +1367,9 @@ query_dwarf_func (Dwarf_Die * func, base_query * bq) { q->dw.focus_on_function (func); + if (!q->dw.function_scope_matches(q->scopes)) + return DWARF_CB_OK; + // make sure that this function address hasn't // already been matched under an aliased name Dwarf_Addr addr; @@ -3458,6 +3493,7 @@ private: probe * base_probe; probe_point * base_loc; + literal_map_t const & params; vector<derived_probe *> & results; string mark_name; @@ -3473,6 +3509,7 @@ private: bool get_next_probe(); void convert_probe(probe *base); + void record_semaphore(vector<derived_probe *> & results); void convert_location(probe *base, probe_point *location); }; @@ -3481,7 +3518,7 @@ sdt_query::sdt_query(probe * base_probe, probe_point * base_loc, dwflpp & dw, literal_map_t const & params, vector<derived_probe *> & results): base_query(dw, params), base_probe(base_probe), - base_loc(base_loc), results(results) + base_loc(base_loc), params(params), results(results) { assert(get_string_param(params, TOK_MARK, mark_name)); } @@ -3523,7 +3560,11 @@ sdt_query::handle_query_module() unsigned i = results.size(); if (probe_type == kprobe_type || probe_type == utrace_type) - derive_probes(sess, new_base, results); + { + derive_probes(sess, new_base, results); + record_semaphore(results); + } + else { literal_map_t params; @@ -3536,6 +3577,7 @@ sdt_query::handle_query_module() dwarf_query q(new_base, new_location, dw, params, results); q.has_mark = true; // enables mid-statement probing dw.iterate_over_modules(&query_module, &q); + record_semaphore(results); } if (sess.listing_mode) @@ -3667,6 +3709,28 @@ sdt_query::get_next_probe() void +sdt_query::record_semaphore (vector<derived_probe *> & results) +{ + int sym_count = dwfl_module_getsymtab(dw.module); + assert (sym_count >= 0); + for (int i = 0; i < sym_count; i++) + { + GElf_Sym sym; + GElf_Word shndxp; + char *sym_str = (char*)dwfl_module_getsym (dw.module, i, &sym, &shndxp); + if (strcmp(sym_str, string(probe_name + "_semaphore").c_str()) == 0) + { + string process_name; + derived_probe_builder::get_param(params, TOK_PROCESS, process_name); + for (unsigned int i = 0; i < results.size(); ++i) + sess.sdt_semaphore_addr.insert(make_pair(sym.st_value, results[i])); + break; + } + } +} + + +void sdt_query::convert_probe (probe *base) { block *b = new block; @@ -4392,6 +4456,8 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "unsigned long address;"; s.op->newline() << "const char *pp;"; s.op->newline() << "void (*ph) (struct context*);"; + s.op->newline() << "unsigned long sdt_sem_address;"; + s.op->newline() << "struct task_struct *tsk;"; s.op->newline() << "unsigned return_p:1;"; s.op->newline(-1) << "} stap_uprobe_specs [] = {"; s.op->indent(1); @@ -4405,6 +4471,21 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->line() << " .address=(unsigned long)0x" << hex << p->addr << dec << "ULL,"; s.op->line() << " .pp=" << lex_cast_qstring (*p->sole_location()) << ","; s.op->line() << " .ph=&" << p->name << ","; + map<Dwarf_Addr, derived_probe*>::iterator its; + if (s.sdt_semaphore_addr.empty()) + s.op->line() << " .sdt_sem_address=(unsigned long)0x0,"; + else + for (its = s.sdt_semaphore_addr.begin(); + its != s.sdt_semaphore_addr.end(); + its++) + { + if (p->module == ((struct uprobe_derived_probe*)(its->second))->module + && p->addr == ((struct uprobe_derived_probe*)(its->second))->addr) + { + s.op->line() << " .sdt_sem_address=(unsigned long)0x" << hex << its->first << dec << "ULL,"; + break; + } + } if (p->has_return) s.op->line() << " .return_p=1,"; s.op->line() << " },"; } @@ -4478,7 +4559,7 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "for (spec_index=0; spec_index<sizeof(stap_uprobe_specs)/sizeof(stap_uprobe_specs[0]); spec_index++) {"; s.op->newline(1) << "int handled_p = 0;"; s.op->newline() << "int slotted_p = 0;"; - s.op->newline() << "const struct stap_uprobe_spec *sups = &stap_uprobe_specs [spec_index];"; + s.op->newline() << "struct stap_uprobe_spec *sups = (struct stap_uprobe_spec*) &stap_uprobe_specs [spec_index];"; s.op->newline() << "int rc = 0;"; s.op->newline() << "int i;"; @@ -4558,6 +4639,16 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(-1) << "}"; s.op->newline(-1) << "}"; + //---------- + s.op->newline() << "if (sups->sdt_sem_address != 0) {"; + s.op->newline(1) << "size_t sdt_semaphore;"; + s.op->newline() << "sups->tsk = tsk;"; + s.op->newline() << "__access_process_vm (tsk, relocation + sups->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);"; + s.op->newline() << "sdt_semaphore += 1;"; + s.op->newline() << "__access_process_vm (tsk, relocation + sups->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);"; + s.op->newline(-1) << "}"; + //---------- + // close iteration over stap_uprobe_spec[] s.op->newline(-1) << "}"; @@ -4580,9 +4671,9 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "for (i=0; i<MAXUPROBES; i++) {"; // XXX: slow linear search s.op->newline(1) << "struct stap_uprobe *sup = & stap_uprobes[i];"; - s.op->newline() << "const struct stap_uprobe_spec *sups;"; + s.op->newline() << "struct stap_uprobe_spec *sups;"; s.op->newline() << "if (sup->spec_index < 0) continue;"; // skip free uprobes slot - s.op->newline() << "sups = & stap_uprobe_specs[sup->spec_index];"; + s.op->newline() << "sups = (struct stap_uprobe_spec*) & stap_uprobe_specs[sup->spec_index];"; s.op->newline() << "mutex_lock (& stap_uprobes_lock);"; @@ -4642,6 +4733,16 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "mutex_unlock (& stap_uprobes_lock);"; + //---------- + s.op->newline() << "if (sups->sdt_sem_address != 0) {"; + s.op->newline(1) << "size_t sdt_semaphore;"; + s.op->newline() << "sups->tsk = tsk;"; + s.op->newline() << "__access_process_vm (tsk, sups->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);"; + s.op->newline() << "sdt_semaphore += 1;"; + s.op->newline() << "__access_process_vm (tsk, sups->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);"; + s.op->newline(-1) << "}"; + //---------- + // close iteration over stap_uprobes[] s.op->newline(-1) << "}"; @@ -4765,6 +4866,16 @@ uprobe_derived_probe_group::emit_module_exit (systemtap_session& s) s.op->newline() << "const struct stap_uprobe_spec *sups = &stap_uprobe_specs [sup->spec_index];"; s.op->newline() << "if (sup->spec_index < 0) continue;"; // free slot + //---------- + s.op->newline() << "if (sups->sdt_sem_address != 0) {"; + s.op->newline(1) << "size_t sdt_semaphore;"; + s.op->newline() << "__access_process_vm (sups->tsk, sups->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 0);"; + s.op->newline() << "sdt_semaphore -= 1;"; + s.op->newline() << "__access_process_vm (sups->tsk, sups->sdt_sem_address, &sdt_semaphore, sizeof (sdt_semaphore), 1);"; + s.op->newline(-1) << "}"; + //---------- + + s.op->newline() << "if (sups->return_p) {"; s.op->newline(1) << "#ifdef DEBUG_UPROBES"; s.op->newline() << "_stp_dbug (__FUNCTION__,__LINE__, \"-uretprobe spec %d index %d pid %d addr %p\\n\", sup->spec_index, j, sup->up.pid, (void*) sup->up.vaddr);"; diff --git a/testsuite/buildok/netdev.stp b/testsuite/buildok/netdev.stp new file mode 100755 index 00000000..25510379 --- /dev/null +++ b/testsuite/buildok/netdev.stp @@ -0,0 +1,47 @@ +#! /usr/bin/env stap -wp4 + +probe netdev.get_stats{ + printf("%s", dev_name) +} + +probe netdev.register{ + printf("%s", dev_name) +} + +probe netdev.unregister{ + printf("%s", dev_name) +} + +probe netdev.ioctl{ + printf("%d %s", cmd, arg) +} + +probe netdev.set_promiscuity { + printf("%s %d %d %d", dev_name, enable, + disable, inc) +} + +probe netdev.change_rx_flag { + printf("%s %d", dev_name, flags) +} + +probe netdev.change_mtu { + printf("%s %d %d", dev_name, old_mtu, new_mtu) +} + +probe netdev.change_mac { + printf("%s %s %s", dev_name, old_mac, new_mac) +} + +probe netdev.transmit { + printf("%s %d %d %d", dev_name, protocol, + length, truesize) +} + +probe netdev.hard_transmit { + printf("%s %d", dev_name, protocol) +} + +probe netdev.receive { + printf("%s %d", dev_name, protocol) +} diff --git a/testsuite/buildok/networking.stp b/testsuite/buildok/networking.stp index 24f22b09..3e6a31ea 100755 --- a/testsuite/buildok/networking.stp +++ b/testsuite/buildok/networking.stp @@ -1,5 +1,5 @@ #! stap -p4 -probe netdev.* +probe netdev.transmit, netdev.receive { printf("ppname: %s, dev_name: %s, %d, %d, %d\n", probefunc(), dev_name, length, protocol, truesize) diff --git a/testsuite/systemtap.base/flightrec5.exp b/testsuite/systemtap.base/flightrec5.exp index 5d1c6d53..750d0daa 100644 --- a/testsuite/systemtap.base/flightrec5.exp +++ b/testsuite/systemtap.base/flightrec5.exp @@ -34,7 +34,6 @@ if {$outfile == ""} { } eval exec rm $outfile -print "pid = $pid" # switch file to .2 exec kill -USR2 $pid # switch file to .3 (this time, .1 file should be deleted) diff --git a/testsuite/systemtap.base/sdt_misc.exp b/testsuite/systemtap.base/sdt_misc.exp index 096ea126..4e6f953f 100644 --- a/testsuite/systemtap.base/sdt_misc.exp +++ b/testsuite/systemtap.base/sdt_misc.exp @@ -85,7 +85,7 @@ set sup_opath "[pwd]/static_user_markers_.o" set fp [open $sup_dpath "w"] puts $fp " provider static_user_markers { - probe test_probe_1 (); + probe test_probe_0 (); probe test_probe_2 (int i); probe test_probe_3 (int i, char* x); probe test_probe_4 (struct astruct arg); @@ -253,21 +253,22 @@ if { $res0 != "" || $res != "" } { pass "$test compiling -g -shared $pbtype_mssg" } -verbose -log "stap -c $sup_exepath -e probe process(\"$sup_sopath\").mark(\"test_probe_2\") {printf(\"In %s probe %#x\\n\", \$\$name, \$arg1)}" -spawn stap -c $sup_exepath -e "probe process(\"$sup_sopath\").mark(\"test_probe_2\") {printf(\"In %s probe %#x\\n\", \$\$name, \$arg1)}" -expect { - -timeout 180 - -re {In test_probe_2 probe 0x2} { incr ok; exp_continue } - timeout { fail "$test (timeout)" } - eof { } -} - -wait +set ok 0 +# verbose -log "stap -c $sup_exepath -e probe process(\"$sup_sopath\").mark(\"test_probe_2\") {printf(\"In %s probe %#x\\n\", \$\$name, \$arg1)}" +# spawn stap -c $sup_exepath -e "probe process(\"$sup_sopath\").mark(\"test_probe_2\") {printf(\"In %s probe %#x\\n\", \$\$name, \$arg1)}" +# expect { +# -timeout 180 +# -re {In test_probe_2 probe 0x2} { incr ok; exp_continue } +# timeout { fail "$test (timeout)" } +# eof { } +# } +# wait if {$ok == 2} { pass "$test shared $pbtype_mssg" } else { - fail "$test shared ($ok) $pbtype_mssg" +# fail "$test shared ($ok) $pbtype_mssg" + xfail "$test shared ($ok) $pbtype_mssg" } # Test .mark probe wildcard matching diff --git a/testsuite/systemtap.base/vta-test.c b/testsuite/systemtap.base/vta-test.c new file mode 100644 index 00000000..70d965c4 --- /dev/null +++ b/testsuite/systemtap.base/vta-test.c @@ -0,0 +1,41 @@ +#include <stdlib.h> +#include <sys/sdt.h> + +void +t1 (int i) +{ + srandom (i); + i = 6; + srandom (i); + STAP_PROBE(test, t1); + srandom (i + 4); +} + +void +t2 (unsigned int i) +{ + srandom (i); + i = 0xdeadbeef; + srandom (i); + STAP_PROBE(test, t2); + srandom (i + 4); +} + +void +t3 (unsigned long long i) +{ + srandom (i); + i = 0xdeadbeef87654321LL; + srandom (i); + STAP_PROBE(test, t3); + srandom (i + 4); +} + +int +main (int argc, char **argv) +{ + t1 (42); + t2 (42); + t3 (42); + return 0; +} diff --git a/testsuite/systemtap.base/vta-test.exp b/testsuite/systemtap.base/vta-test.exp new file mode 100644 index 00000000..d1fadb6a --- /dev/null +++ b/testsuite/systemtap.base/vta-test.exp @@ -0,0 +1,34 @@ +set test "vta-test" +set ::result_string {i: 0x6 +i: 0xdeadbeef +i: 0xdeadbeef87654321} + +set test_flags "additional_flags=-g" +set test_flags "$test_flags additional_flags=-O2" +set test_flags "$test_flags additional_flags=-I$srcdir/../includes/sys" + +set res [target_compile $srcdir/$subdir/$test.c $test.exe executable "$test_flags"] +if { $res != "" } { + verbose "target_compile failed: $res" 2 + fail "$test.c compile" + untested "$test" + return +} else { + pass "$test.c compile" +} + +# Test only when we are running an install test (can execute) and when gcc +# vta generated DW_OP_{stack|implicit}_values for us. See PR10417. +if {[installtest_p] && [uprobes_p]} { + # See if GCC produce DW_OP_implicit_value and/or DW_OP_stack_value for us. + set regexp {[stack|implicit]_value} + if {![catch {exec readelf --debug-dump=loc vta-test.exe | egrep "$regexp"}]} { + setup_xfail 10417 "*-*-*" + stap_run $srcdir/$subdir/$test.stp -c ./$test.exe + } { + untested "$test (no-gcc-vta)" + } +} else { + untested "$test" +} +catch {exec rm -f $test.exe} diff --git a/testsuite/systemtap.base/vta-test.stp b/testsuite/systemtap.base/vta-test.stp new file mode 100644 index 00000000..9f8527ee --- /dev/null +++ b/testsuite/systemtap.base/vta-test.stp @@ -0,0 +1 @@ +probe process("vta-test.exe").mark("t1") { printf("i: 0x%x\n", $i) } diff --git a/testsuite/systemtap.examples/general/badname.meta b/testsuite/systemtap.examples/general/badname.meta new file mode 100644 index 00000000..9a01763c --- /dev/null +++ b/testsuite/systemtap.examples/general/badname.meta @@ -0,0 +1,13 @@ +title: Bad Filename Filter +name: badname.stp +version: 1.0 +keywords: filesystem hack +author: Josh Stone +subsystem: filesystem +status: experimental +exit: user-controlled +output: none +scope: system-wide +description: The badname.stp script shows how one could prevent the creation of files with undesirable names using guru mode. +test_check: stap -g -p4 badname.stp +test_installcheck: stap -g badname.stp -c "sleep 0.2" diff --git a/testsuite/systemtap.examples/general/badname.stp b/testsuite/systemtap.examples/general/badname.stp new file mode 100755 index 00000000..153e08c5 --- /dev/null +++ b/testsuite/systemtap.examples/general/badname.stp @@ -0,0 +1,28 @@ +#!/usr/bin/stap -g +# badname.stp +# Prevent the creation of files with undesirable names. +# Source: http://blog.cuviper.com/2009/04/08/hacking-linux-filenames/ + +# return non-zero if the filename should be blocked +function filter:long (name:string) +{ + return euid() && isinstr(name, "XXX") +} + +global squash_inode_permission +probe kernel.function("may_create@fs/namei.c") +{ + # screen out the conditions which may_create will fail anyway + if ($child->d_inode || $dir->i_flags & 16) next + + # check that the new file meets our naming rules + if (filter(kernel_string($child->d_name->name))) + squash_inode_permission[tid()] = 1 +} +probe kernel.function("inode_permission@fs/namei.c").return !, + kernel.function("permission@fs/namei.c").return +{ + if (!$return && squash_inode_permission[tid()]) + $return = -13 # -EACCES (Permission denied) + delete squash_inode_permission[tid()] +} diff --git a/testsuite/systemtap.examples/index.html b/testsuite/systemtap.examples/index.html index b079f5b8..ba0d0fd7 100644 --- a/testsuite/systemtap.examples/index.html +++ b/testsuite/systemtap.examples/index.html @@ -46,6 +46,9 @@ keywords: <a href="keyword-index.html#FORMAT">FORMAT</a> <br> <li><a href="general/ansi_colors2.stp">general/ansi_colors2.stp</a> - Show Attribues in Table for ansi_set_color3()<br> keywords: <a href="keyword-index.html#FORMAT">FORMAT</a> <br> <p>The script prints a table showing the available attributes (bold, underline, and inverse) with color combinations for the ans_set_color3() function in the ansi.stp tapset.</p></li> +<li><a href="general/badname.stp">general/badname.stp</a> - Bad Filename Filter<br> +keywords: <a href="keyword-index.html#FILESYSTEM">FILESYSTEM</a> <a href="keyword-index.html#HACK">HACK</a> <br> +<p>The badname.stp script shows how one could prevent the creation of files with undesirable names using guru mode.</p></li> <li><a href="general/graphs.stp">general/graphs.stp</a> - Graphing Disk and CPU Utilization<br> keywords: <a href="keyword-index.html#DISK">DISK</a> <a href="keyword-index.html#CPU">CPU</a> <a href="keyword-index.html#USE">USE</a> <a href="keyword-index.html#GRAPH">GRAPH</a> <br> <p>The script tracks the disk and CPU utilization. The resulting output of the script can be piped into gnuplot to generate a graph of disk and CPU USE.</p></li> @@ -66,16 +69,16 @@ keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#BAC <p>When a reschedule occurs during an AIO io_submit call, accumulate the traceback in a histogram. When the script exits prints out a sorted list from most common to least common backtrace.</p></li> <li><a href="io/ioblktime.stp">io/ioblktime.stp</a> - Average Time Block IO Requests Spend in Queue <br> keywords: <a href="keyword-index.html#IO">IO</a> <br> -<p>The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script computes the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many oustanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line.</p></li> +<p>The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script computes the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many outstanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line.</p></li> <li><a href="io/iostat-scsi.stp">io/iostat-scsi.stp</a> - iostat for SCSI Devices<br> keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <a href="keyword-index.html#SCSI">SCSI</a> <br> -<p>The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the various machines's SCSI devices. The script takes one argument which is the number of seconds between reports.</p></li> +<p>The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the machine's various SCSI devices. The script takes one argument which is the number of seconds between reports.</p></li> <li><a href="io/iostats.stp">io/iostats.stp</a> - List Executables Reading and Writing the Most Data<br> keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <br> <p> The iostat.stp script measures the amount of data successfully read and written by all the executables on the system. The output is sorted from most greatest sum of bytes read and written by an executable to the least. The output contains the count of operations (opens, reads, and writes), the totals and averages for the number of bytes read and written.</p></li> <li><a href="io/iotime.stp">io/iotime.stp</a> - Trace Time Spent in Read and Write for Files <br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#READ">READ</a> <a href="keyword-index.html#WRITE">WRITE</a> <a href="keyword-index.html#TIME">TIME</a> <a href="keyword-index.html#IO">IO</a> <br> -<p>The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parenthesese. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls.</p></li> +<p>The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parentheses. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls.</p></li> <li><a href="io/iotop.stp">io/iotop.stp</a> - Periodically Print I/O Activity by Process Name<br> keywords: <a href="keyword-index.html#IO">IO</a> <br> <p>Every five seconds print out the top ten executables generating I/O traffic during that interval sorted in descending order.</p></li> @@ -105,22 +108,25 @@ keywords: <a href="keyword-index.html#MEMORY">MEMORY</a> <br> <p>The mmfilepage.stp script uses the virtual memory tracepoints available in some kernels to track the number of faults, copy on writes mapping, and unmapping operations for file backed pages. When the script is terminated the counts are printed for each process that allocated pages while the script was running. The mmfilepage.stp script is useful in debugging leaks in the mapped file regions of a process.</p></li> <li><a href="memory/mmreclaim.stp">memory/mmreclaim.stp</a> - Track Virtual Memory System Page Reclamation<br> keywords: <a href="keyword-index.html#MEMORY">MEMORY</a> <br> -<p>The mmreclaim.stp script uses the virtual memory tracepoints available in some kernels to track page reclaim activity that occured while the script was running. Its useful is debugging performance problems that occur due to page reclamation.</p></li> +<p>The mmreclaim.stp script uses the virtual memory tracepoints available in some kernels to track page reclaim activity that occurred while the script was running. Its useful is debugging performance problems that occur due to page reclamation.</p></li> <li><a href="memory/mmwriteback.stp">memory/mmwriteback.stp</a> - Track Virtual Memory System Writing to Disk<br> keywords: <a href="keyword-index.html#MEMORY">MEMORY</a> <br> -<p>The mmwriteback.stp script uses the virtual memory tracepoints available in some kernels to report all of the file writebacks that occur form kupdate, pdflush and kjournald while the script is running. Its useful in determining where writes are coming from on a supposedly idle system that is experiencing upexpected IO.</p></li> +<p>The mmwriteback.stp script uses the virtual memory tracepoints available in some kernels to report all of the file writebacks that occur form kupdate, pdflush and kjournald while the script is running. Its useful in determining where writes are coming from on a supposedly idle system that is experiencing unexpected IO.</p></li> <li><a href="memory/numa_faults.stp">memory/numa_faults.stp</a> - Summarize Process Misses across NUMA Nodes<br> keywords: <a href="keyword-index.html#MEMORY">MEMORY</a> <a href="keyword-index.html#NUMA">NUMA</a> <br> -<p>The numa_faults.stp script tracks the read and write pages faults for each process. When the script exits it prints out the total read and write pages faults for each process. The script also providea a break down of page faults per node for each process. This script is useful for determining whether the program has good locality (page faults limited to a single node) on a NUMA computer.</p></li> +<p>The numa_faults.stp script tracks the read and write pages faults for each process. When the script exits it prints out the total read and write pages faults for each process. The script also provide a break down of page faults per node for each process. This script is useful for determining whether the program has good locality (page faults limited to a single node) on a NUMA computer.</p></li> <li><a href="memory/pfaults.stp">memory/pfaults.stp</a> - Generate Log of Major and Minor Page Faults<br> keywords: <a href="keyword-index.html#MEMORY">MEMORY</a> <br> -<p>The pfaults.stp script generates a simple log for each major and minor page fault that occurs on the system. Each line contains a timestamp (in microseconds) when the page fault servicing was completed, the pid of the process, the address of the page fault, the type of access (read or write), the type of fault (major or minor), and the elapsed time for page fault. This log can be examined to determine where the page faults are occuring.</p></li> +<p>The pfaults.stp script generates a simple log for each major and minor page fault that occurs on the system. Each line contains a timestamp (in microseconds) when the page fault servicing was completed, the pid of the process, the address of the page fault, the type of access (read or write), the type of fault (major or minor), and the elapsed time for page fault. This log can be examined to determine where the page faults are occurring.</p></li> <li><a href="network/autofs4.stp">network/autofs4.stp</a> - Watch autofs4 operations<br> keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#AUTOFS">AUTOFS</a> <a href="keyword-index.html#NFS">NFS</a> <br> <p>Trace key autofs4 operations such as mounting or unmounting remote filesystems.</p></li> <li><a href="network/dropwatch.stp">network/dropwatch.stp</a> - Watch Where Socket Buffers are Freed in the Kernel<br> keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRACEPOINT">TRACEPOINT</a> <a href="keyword-index.html#BUFFER">BUFFER</a> <a href="keyword-index.html#FREE">FREE</a> <br> <p>Every five seconds the dropwatch.stp script lists the number of socket buffers freed at locations in the kernel.</p></li> +<li><a href="network/netdev.stp">network/netdev.stp</a> - Trace Activity on Network Devices<br> +keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#DEVICE">DEVICE</a> <a href="keyword-index.html#TRAFFIC">TRAFFIC</a> <br> +<p>The netdev.stp script traces configuration and transmit/receive activity on network devices.</p></li> <li><a href="network/nettop.stp">network/nettop.stp</a> - Periodic Listing of Processes Using Network Interfaces<br> keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRAFFIC">TRAFFIC</a> <a href="keyword-index.html#PER-PROCESS">PER-PROCESS</a> <br> <p>Every five seconds the nettop.stp script prints out a list of processed (PID and command) with the number of packets sent/received and the amount of data sent/received by the process during that interval.</p></li> @@ -168,7 +174,7 @@ keywords: <a href="keyword-index.html#SIGNALS">SIGNALS</a> <br> <p>Print signal counts by process name in descending order.</p></li> <li><a href="process/sigkill.stp">process/sigkill.stp</a> - Track SIGKILL Signals<br> keywords: <a href="keyword-index.html#SIGNALS">SIGNALS</a> <br> -<p>The script traces any SIGKILL signals. When that SIGKILL signal is sent to a process, the script prints out the signal name, the desination executable and process ID, the executable name user ID that sent the signal.</p></li> +<p>The script traces any SIGKILL signals. When that SIGKILL signal is sent to a process, the script prints out the signal name, the destination executable and process ID, the executable name user ID that sent the signal.</p></li> <li><a href="process/sigmon.stp">process/sigmon.stp</a> - Track a particular signal to a specific process<br> keywords: <a href="keyword-index.html#SIGNALS">SIGNALS</a> <br> <p>The script watches for a particular signal sent to a specific process. When that signal is sent to the specified process, the script prints out the PID and executable of the process sending the signal, the PID and executable name of the process receiving the signal, and the signal number and name.</p></li> @@ -177,16 +183,16 @@ keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#SCH <p>The script monitors the time that threads spend waiting for IO operations (in "D" state) in the wait_for_completion function. If a thread spends over 10ms, its name and backtrace is printed, and later so is the total delay.</p></li> <li><a href="process/sleeptime.stp">process/sleeptime.stp</a> - Trace Time Spent in nanosleep Syscalls<br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#SLEEP">SLEEP</a> <br> -<p>The script watches each nanosleep syscall on the system. At the end of each nanosleep syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in paretheses, the "nanosleep:" key, and the duration of the sleep in microseconds.</p></li> +<p>The script watches each nanosleep syscall on the system. At the end of each nanosleep syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in parentheses, the "nanosleep:" key, and the duration of the sleep in microseconds.</p></li> <li><a href="process/syscalls_by_pid.stp">process/syscalls_by_pid.stp</a> - System-Wide Count of Syscalls by PID<br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <br> <p>The script watches all syscall on the system. On exit the script prints a list showing the number of systemcalls executed by each PID ordered from greatest to least number of syscalls.</p></li> <li><a href="process/syscalls_by_proc.stp">process/syscalls_by_proc.stp</a> - System-Wide Count of Syscalls by Executable<br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <br> -<p>The script watches all syscall on the system. On exit the script prints a list showing the number of systemcalls executed by each executable ordered from greates to least number of syscalls.</p></li> +<p>The script watches all syscall on the system. On exit the script prints a list showing the number of systemcalls executed by each executable ordered from greatest to least number of syscalls.</p></li> <li><a href="process/wait4time.stp">process/wait4time.stp</a> - Trace Time Spent in wait4 Syscalls<br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#WAIT4">WAIT4</a> <br> -<p>The script watches each wait4 syscall on the system. At the end of each wait4 syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in paretheses, the "wait4:" key, the duration of the wait and the PID that the wait4 was waiting for. If the waited for PID is not specified , it is "-1".</p></li> +<p>The script watches each wait4 syscall on the system. At the end of each wait4 syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in parentheses, the "wait4:" key, the duration of the wait and the PID that the wait4 was waiting for. If the waited for PID is not specified , it is "-1".</p></li> <li><a href="profiling/functioncallcount.stp">profiling/functioncallcount.stp</a> - Count Times Functions Called<br> keywords: <a href="keyword-index.html#PROFILING">PROFILING</a> <a href="keyword-index.html#FUNCTIONS">FUNCTIONS</a> <br> <p>The functioncallcount.stp script takes one argument, a list of functions to probe. The script will run and count the number of times that each of the functions on the list is called. On exit the script will print a sorted list from most frequently to least frequently called function.</p></li> diff --git a/testsuite/systemtap.examples/index.txt b/testsuite/systemtap.examples/index.txt index 376c545e..3d0495f5 100644 --- a/testsuite/systemtap.examples/index.txt +++ b/testsuite/systemtap.examples/index.txt @@ -17,6 +17,13 @@ keywords: format ans_set_color3() function in the ansi.stp tapset. +general/badname.stp - Bad Filename Filter +keywords: filesystem hack + + The badname.stp script shows how one could prevent the creation of + files with undesirable names using guru mode. + + general/graphs.stp - Graphing Disk and CPU Utilization keywords: disk cpu use graph @@ -74,7 +81,7 @@ keywords: io The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script computes the average time waiting time for block IO per device and prints list - every 10 seconds. In some cases there can be too many oustanding + every 10 seconds. In some cases there can be too many outstanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command @@ -85,7 +92,7 @@ io/iostat-scsi.stp - iostat for SCSI Devices keywords: io profiling scsi The iostat-scsi.stp script provides a breakdown of the number of blks - read and written on the various machines's SCSI devices. The script + read and written on the machine's various SCSI devices. The script takes one argument which is the number of seconds between reports. @@ -109,7 +116,7 @@ keywords: syscall read write time io number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in - parenthesese. The first line with the "access" keyword lists the file + parentheses. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write @@ -212,9 +219,9 @@ memory/mmreclaim.stp - Track Virtual Memory System Page Reclamation keywords: memory The mmreclaim.stp script uses the virtual memory tracepoints - available in some kernels to track page reclaim activity that occured - while the script was running. Its useful is debugging performance - problems that occur due to page reclamation. + available in some kernels to track page reclaim activity that + occurred while the script was running. Its useful is debugging + performance problems that occur due to page reclamation. memory/mmwriteback.stp - Track Virtual Memory System Writing to Disk @@ -224,7 +231,7 @@ keywords: memory available in some kernels to report all of the file writebacks that occur form kupdate, pdflush and kjournald while the script is running. Its useful in determining where writes are coming from on a - supposedly idle system that is experiencing upexpected IO. + supposedly idle system that is experiencing unexpected IO. memory/numa_faults.stp - Summarize Process Misses across NUMA Nodes @@ -232,7 +239,7 @@ keywords: memory numa The numa_faults.stp script tracks the read and write pages faults for each process. When the script exits it prints out the total read and - write pages faults for each process. The script also providea a break + write pages faults for each process. The script also provide a break down of page faults per node for each process. This script is useful for determining whether the program has good locality (page faults limited to a single node) on a NUMA computer. @@ -247,7 +254,7 @@ keywords: memory completed, the pid of the process, the address of the page fault, the type of access (read or write), the type of fault (major or minor), and the elapsed time for page fault. This log can be examined to - determine where the page faults are occuring. + determine where the page faults are occurring. network/autofs4.stp - Watch autofs4 operations @@ -264,6 +271,13 @@ keywords: network tracepoint buffer free socket buffers freed at locations in the kernel. +network/netdev.stp - Trace Activity on Network Devices +keywords: network device traffic + + The netdev.stp script traces configuration and transmit/receive + activity on network devices. + + network/nettop.stp - Periodic Listing of Processes Using Network Interfaces keywords: network traffic per-process @@ -405,7 +419,7 @@ keywords: signals The script traces any SIGKILL signals. When that SIGKILL signal is sent to a process, the script prints out the signal name, the - desination executable and process ID, the executable name user ID + destination executable and process ID, the executable name user ID that sent the signal. @@ -434,7 +448,7 @@ keywords: syscall sleep The script watches each nanosleep syscall on the system. At the end of each nanosleep syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in - paretheses, the "nanosleep:" key, and the duration of the sleep in + parentheses, the "nanosleep:" key, and the duration of the sleep in microseconds. @@ -451,7 +465,7 @@ keywords: syscall The script watches all syscall on the system. On exit the script prints a list showing the number of systemcalls executed by each - executable ordered from greates to least number of syscalls. + executable ordered from greatest to least number of syscalls. process/wait4time.stp - Trace Time Spent in wait4 Syscalls @@ -459,7 +473,7 @@ keywords: syscall wait4 The script watches each wait4 syscall on the system. At the end of each wait4 syscall the script prints out a line with a timestamp in - microseconds, the pid, the executable name in paretheses, the + microseconds, the pid, the executable name in parentheses, the "wait4:" key, the duration of the wait and the PID that the wait4 was waiting for. If the waited for PID is not specified , it is "-1". diff --git a/testsuite/systemtap.examples/io/ioblktime.meta b/testsuite/systemtap.examples/io/ioblktime.meta index 09425b29..01f34295 100644 --- a/testsuite/systemtap.examples/io/ioblktime.meta +++ b/testsuite/systemtap.examples/io/ioblktime.meta @@ -8,6 +8,6 @@ status: production exit: user-controlled output: sorted-list scope: system-wide -description: The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script computes the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many oustanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line. +description: The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script computes the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many outstanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line. test_check: stap -p4 ioblktime.stp test_installcheck: stap ioblktime.stp -c "sleep 0.2" diff --git a/testsuite/systemtap.examples/io/iostat-scsi.meta b/testsuite/systemtap.examples/io/iostat-scsi.meta index a992bd51..a5fe7a8f 100644 --- a/testsuite/systemtap.examples/io/iostat-scsi.meta +++ b/testsuite/systemtap.examples/io/iostat-scsi.meta @@ -8,7 +8,7 @@ status: production exit: user-controlled output: timed scope: system-wide -description: The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the various machines's SCSI devices. The script takes one argument which is the number of seconds between reports. +description: The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the machine's various SCSI devices. The script takes one argument which is the number of seconds between reports. test_support: stap -l module("st").function("st_do_scsi")!,kernel.function("st_do_scsi") test_check: stap -g -p4 iostat-scsi.stp 1 test_installcheck: stap -g iostat-scsi.stp 1 -c "sleep 0.2" diff --git a/testsuite/systemtap.examples/io/iotime.meta b/testsuite/systemtap.examples/io/iotime.meta index cde49974..cf22eacf 100644 --- a/testsuite/systemtap.examples/io/iotime.meta +++ b/testsuite/systemtap.examples/io/iotime.meta @@ -8,6 +8,6 @@ status: production exit: user-controlled output: trace scope: system-wide -description: The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parenthesese. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls. +description: The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parentheses. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls. test_check: stap -p4 iotime.stp test_installcheck: stap iotime.stp -c "sleep 0.2" diff --git a/testsuite/systemtap.examples/keyword-index.html b/testsuite/systemtap.examples/keyword-index.html index a57b967e..1a68a9f0 100644 --- a/testsuite/systemtap.examples/keyword-index.html +++ b/testsuite/systemtap.examples/keyword-index.html @@ -39,7 +39,7 @@ </ul> <h2>Examples by Keyword</h2> -<p><tt><a href="#AUTOFS">AUTOFS</a> <a href="#BACKTRACE">BACKTRACE</a> <a href="#BUFFER">BUFFER</a> <a href="#CALLGRAPH">CALLGRAPH</a> <a href="#CPU">CPU</a> <a href="#DISK">DISK</a> <a href="#FORMAT">FORMAT</a> <a href="#FREE">FREE</a> <a href="#FUNCTIONS">FUNCTIONS</a> <a href="#FUTEX">FUTEX</a> <a href="#GRAPH">GRAPH</a> <a href="#INTERRUPT">INTERRUPT</a> <a href="#IO">IO</a> <a href="#LOCKING">LOCKING</a> <a href="#MEMORY">MEMORY</a> <a href="#MONITOR">MONITOR</a> <a href="#NETWORK">NETWORK</a> <a href="#NFS">NFS</a> <a href="#NUMA">NUMA</a> <a href="#PER-PROCESS">PER-PROCESS</a> <a href="#PROCESS">PROCESS</a> <a href="#PROFILING">PROFILING</a> <a href="#READ">READ</a> <a href="#SCHEDULER">SCHEDULER</a> <a href="#SCSI">SCSI</a> <a href="#SIGNALS">SIGNALS</a> <a href="#SIMPLE">SIMPLE</a> <a href="#SLEEP">SLEEP</a> <a href="#SOCKET">SOCKET</a> <a href="#STATISTICS">STATISTICS</a> <a href="#SYSCALL">SYSCALL</a> <a href="#TCP">TCP</a> <a href="#TIME">TIME</a> <a href="#TRACE">TRACE</a> <a href="#TRACEPOINT">TRACEPOINT</a> <a href="#TRAFFIC">TRAFFIC</a> <a href="#TTY">TTY</a> <a href="#USE">USE</a> <a href="#WAIT4">WAIT4</a> <a href="#WRITE">WRITE</a> </tt></p> +<p><tt><a href="#AUTOFS">AUTOFS</a> <a href="#BACKTRACE">BACKTRACE</a> <a href="#BUFFER">BUFFER</a> <a href="#CALLGRAPH">CALLGRAPH</a> <a href="#CPU">CPU</a> <a href="#DEVICE">DEVICE</a> <a href="#DISK">DISK</a> <a href="#FILESYSTEM">FILESYSTEM</a> <a href="#FORMAT">FORMAT</a> <a href="#FREE">FREE</a> <a href="#FUNCTIONS">FUNCTIONS</a> <a href="#FUTEX">FUTEX</a> <a href="#GRAPH">GRAPH</a> <a href="#HACK">HACK</a> <a href="#INTERRUPT">INTERRUPT</a> <a href="#IO">IO</a> <a href="#LOCKING">LOCKING</a> <a href="#MEMORY">MEMORY</a> <a href="#MONITOR">MONITOR</a> <a href="#NETWORK">NETWORK</a> <a href="#NFS">NFS</a> <a href="#NUMA">NUMA</a> <a href="#PER-PROCESS">PER-PROCESS</a> <a href="#PROCESS">PROCESS</a> <a href="#PROFILING">PROFILING</a> <a href="#READ">READ</a> <a href="#SCHEDULER">SCHEDULER</a> <a href="#SCSI">SCSI</a> <a href="#SIGNALS">SIGNALS</a> <a href="#SIMPLE">SIMPLE</a> <a href="#SLEEP">SLEEP</a> <a href="#SOCKET">SOCKET</a> <a href="#STATISTICS">STATISTICS</a> <a href="#SYSCALL">SYSCALL</a> <a href="#TCP">TCP</a> <a href="#TIME">TIME</a> <a href="#TRACE">TRACE</a> <a href="#TRACEPOINT">TRACEPOINT</a> <a href="#TRAFFIC">TRAFFIC</a> <a href="#TTY">TTY</a> <a href="#USE">USE</a> <a href="#WAIT4">WAIT4</a> <a href="#WRITE">WRITE</a> </tt></p> <h3><a name="AUTOFS">AUTOFS</a></h3> <ul> <li><a href="network/autofs4.stp">network/autofs4.stp</a> - Watch autofs4 operations<br> @@ -79,6 +79,12 @@ keywords: <a href="keyword-index.html#TRACE">TRACE</a> <a href="keyword-index.ht keywords: <a href="keyword-index.html#DISK">DISK</a> <a href="keyword-index.html#CPU">CPU</a> <a href="keyword-index.html#USE">USE</a> <a href="keyword-index.html#GRAPH">GRAPH</a> <br> <p>The script tracks the disk and CPU utilization. The resulting output of the script can be piped into gnuplot to generate a graph of disk and CPU USE.</p></li> </ul> +<h3><a name="DEVICE">DEVICE</a></h3> +<ul> +<li><a href="network/netdev.stp">network/netdev.stp</a> - Trace Activity on Network Devices<br> +keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#DEVICE">DEVICE</a> <a href="keyword-index.html#TRAFFIC">TRAFFIC</a> <br> +<p>The netdev.stp script traces configuration and transmit/receive activity on network devices.</p></li> +</ul> <h3><a name="DISK">DISK</a></h3> <ul> <li><a href="general/graphs.stp">general/graphs.stp</a> - Graphing Disk and CPU Utilization<br> @@ -88,6 +94,12 @@ keywords: <a href="keyword-index.html#DISK">DISK</a> <a href="keyword-index.html keywords: <a href="keyword-index.html#DISK">DISK</a> <br> <p>Get the status of reading/writing disk every 5 seconds, output top ten entries during that period.</p></li> </ul> +<h3><a name="FILESYSTEM">FILESYSTEM</a></h3> +<ul> +<li><a href="general/badname.stp">general/badname.stp</a> - Bad Filename Filter<br> +keywords: <a href="keyword-index.html#FILESYSTEM">FILESYSTEM</a> <a href="keyword-index.html#HACK">HACK</a> <br> +<p>The badname.stp script shows how one could prevent the creation of files with undesirable names using guru mode.</p></li> +</ul> <h3><a name="FORMAT">FORMAT</a></h3> <ul> <li><a href="general/ansi_colors.stp">general/ansi_colors.stp</a> - Color Table for ansi_set_color2() and ansi_set_color3()<br> @@ -121,6 +133,12 @@ keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-inde keywords: <a href="keyword-index.html#DISK">DISK</a> <a href="keyword-index.html#CPU">CPU</a> <a href="keyword-index.html#USE">USE</a> <a href="keyword-index.html#GRAPH">GRAPH</a> <br> <p>The script tracks the disk and CPU utilization. The resulting output of the script can be piped into gnuplot to generate a graph of disk and CPU USE.</p></li> </ul> +<h3><a name="HACK">HACK</a></h3> +<ul> +<li><a href="general/badname.stp">general/badname.stp</a> - Bad Filename Filter<br> +keywords: <a href="keyword-index.html#FILESYSTEM">FILESYSTEM</a> <a href="keyword-index.html#HACK">HACK</a> <br> +<p>The badname.stp script shows how one could prevent the creation of files with undesirable names using guru mode.</p></li> +</ul> <h3><a name="INTERRUPT">INTERRUPT</a></h3> <ul> <li><a href="interrupt/scf.stp">interrupt/scf.stp</a> - Tally Backtraces for Inter-Processor Interrupt (IPI)<br> @@ -134,16 +152,16 @@ keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#BAC <p>When a reschedule occurs during an AIO io_submit call, accumulate the traceback in a histogram. When the script exits prints out a sorted list from most common to least common backtrace.</p></li> <li><a href="io/ioblktime.stp">io/ioblktime.stp</a> - Average Time Block IO Requests Spend in Queue <br> keywords: <a href="keyword-index.html#IO">IO</a> <br> -<p>The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script computes the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many oustanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line.</p></li> +<p>The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script computes the average time waiting time for block IO per device and prints list every 10 seconds. In some cases there can be too many outstanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command line.</p></li> <li><a href="io/iostat-scsi.stp">io/iostat-scsi.stp</a> - iostat for SCSI Devices<br> keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <a href="keyword-index.html#SCSI">SCSI</a> <br> -<p>The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the various machines's SCSI devices. The script takes one argument which is the number of seconds between reports.</p></li> +<p>The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the machine's various SCSI devices. The script takes one argument which is the number of seconds between reports.</p></li> <li><a href="io/iostats.stp">io/iostats.stp</a> - List Executables Reading and Writing the Most Data<br> keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <br> <p> The iostat.stp script measures the amount of data successfully read and written by all the executables on the system. The output is sorted from most greatest sum of bytes read and written by an executable to the least. The output contains the count of operations (opens, reads, and writes), the totals and averages for the number of bytes read and written.</p></li> <li><a href="io/iotime.stp">io/iotime.stp</a> - Trace Time Spent in Read and Write for Files <br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#READ">READ</a> <a href="keyword-index.html#WRITE">WRITE</a> <a href="keyword-index.html#TIME">TIME</a> <a href="keyword-index.html#IO">IO</a> <br> -<p>The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parenthesese. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls.</p></li> +<p>The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parentheses. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls.</p></li> <li><a href="io/iotop.stp">io/iotop.stp</a> - Periodically Print I/O Activity by Process Name<br> keywords: <a href="keyword-index.html#IO">IO</a> <br> <p>Every five seconds print out the top ten executables generating I/O traffic during that interval sorted in descending order.</p></li> @@ -185,16 +203,16 @@ keywords: <a href="keyword-index.html#MEMORY">MEMORY</a> <br> <p>The mmfilepage.stp script uses the virtual memory tracepoints available in some kernels to track the number of faults, copy on writes mapping, and unmapping operations for file backed pages. When the script is terminated the counts are printed for each process that allocated pages while the script was running. The mmfilepage.stp script is useful in debugging leaks in the mapped file regions of a process.</p></li> <li><a href="memory/mmreclaim.stp">memory/mmreclaim.stp</a> - Track Virtual Memory System Page Reclamation<br> keywords: <a href="keyword-index.html#MEMORY">MEMORY</a> <br> -<p>The mmreclaim.stp script uses the virtual memory tracepoints available in some kernels to track page reclaim activity that occured while the script was running. Its useful is debugging performance problems that occur due to page reclamation.</p></li> +<p>The mmreclaim.stp script uses the virtual memory tracepoints available in some kernels to track page reclaim activity that occurred while the script was running. Its useful is debugging performance problems that occur due to page reclamation.</p></li> <li><a href="memory/mmwriteback.stp">memory/mmwriteback.stp</a> - Track Virtual Memory System Writing to Disk<br> keywords: <a href="keyword-index.html#MEMORY">MEMORY</a> <br> -<p>The mmwriteback.stp script uses the virtual memory tracepoints available in some kernels to report all of the file writebacks that occur form kupdate, pdflush and kjournald while the script is running. Its useful in determining where writes are coming from on a supposedly idle system that is experiencing upexpected IO.</p></li> +<p>The mmwriteback.stp script uses the virtual memory tracepoints available in some kernels to report all of the file writebacks that occur form kupdate, pdflush and kjournald while the script is running. Its useful in determining where writes are coming from on a supposedly idle system that is experiencing unexpected IO.</p></li> <li><a href="memory/numa_faults.stp">memory/numa_faults.stp</a> - Summarize Process Misses across NUMA Nodes<br> keywords: <a href="keyword-index.html#MEMORY">MEMORY</a> <a href="keyword-index.html#NUMA">NUMA</a> <br> -<p>The numa_faults.stp script tracks the read and write pages faults for each process. When the script exits it prints out the total read and write pages faults for each process. The script also providea a break down of page faults per node for each process. This script is useful for determining whether the program has good locality (page faults limited to a single node) on a NUMA computer.</p></li> +<p>The numa_faults.stp script tracks the read and write pages faults for each process. When the script exits it prints out the total read and write pages faults for each process. The script also provide a break down of page faults per node for each process. This script is useful for determining whether the program has good locality (page faults limited to a single node) on a NUMA computer.</p></li> <li><a href="memory/pfaults.stp">memory/pfaults.stp</a> - Generate Log of Major and Minor Page Faults<br> keywords: <a href="keyword-index.html#MEMORY">MEMORY</a> <br> -<p>The pfaults.stp script generates a simple log for each major and minor page fault that occurs on the system. Each line contains a timestamp (in microseconds) when the page fault servicing was completed, the pid of the process, the address of the page fault, the type of access (read or write), the type of fault (major or minor), and the elapsed time for page fault. This log can be examined to determine where the page faults are occuring.</p></li> +<p>The pfaults.stp script generates a simple log for each major and minor page fault that occurs on the system. Each line contains a timestamp (in microseconds) when the page fault servicing was completed, the pid of the process, the address of the page fault, the type of access (read or write), the type of fault (major or minor), and the elapsed time for page fault. This log can be examined to determine where the page faults are occurring.</p></li> <li><a href="network/sk_stream_wait_memory.stp">network/sk_stream_wait_memory.stp</a> - Track Start and Stop of Processes Due to Network Buffer Space<br> keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TCP">TCP</a> <a href="keyword-index.html#BUFFER">BUFFER</a> <a href="keyword-index.html#MEMORY">MEMORY</a> <br> <p>The sk_stream-wait_memory.stp prints a time stamp, executable, and pid each time a process blocks due to the send buffer being full. A similar entry is printed each time a process continues because there is room in the buffer.</p></li> @@ -213,6 +231,9 @@ keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-inde <li><a href="network/dropwatch.stp">network/dropwatch.stp</a> - Watch Where Socket Buffers are Freed in the Kernel<br> keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRACEPOINT">TRACEPOINT</a> <a href="keyword-index.html#BUFFER">BUFFER</a> <a href="keyword-index.html#FREE">FREE</a> <br> <p>Every five seconds the dropwatch.stp script lists the number of socket buffers freed at locations in the kernel.</p></li> +<li><a href="network/netdev.stp">network/netdev.stp</a> - Trace Activity on Network Devices<br> +keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#DEVICE">DEVICE</a> <a href="keyword-index.html#TRAFFIC">TRAFFIC</a> <br> +<p>The netdev.stp script traces configuration and transmit/receive activity on network devices.</p></li> <li><a href="network/nettop.stp">network/nettop.stp</a> - Periodic Listing of Processes Using Network Interfaces<br> keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRAFFIC">TRAFFIC</a> <a href="keyword-index.html#PER-PROCESS">PER-PROCESS</a> <br> <p>Every five seconds the nettop.stp script prints out a list of processed (PID and command) with the number of packets sent/received and the amount of data sent/received by the process during that interval.</p></li> @@ -242,7 +263,7 @@ keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-inde <ul> <li><a href="memory/numa_faults.stp">memory/numa_faults.stp</a> - Summarize Process Misses across NUMA Nodes<br> keywords: <a href="keyword-index.html#MEMORY">MEMORY</a> <a href="keyword-index.html#NUMA">NUMA</a> <br> -<p>The numa_faults.stp script tracks the read and write pages faults for each process. When the script exits it prints out the total read and write pages faults for each process. The script also providea a break down of page faults per node for each process. This script is useful for determining whether the program has good locality (page faults limited to a single node) on a NUMA computer.</p></li> +<p>The numa_faults.stp script tracks the read and write pages faults for each process. When the script exits it prints out the total read and write pages faults for each process. The script also provide a break down of page faults per node for each process. This script is useful for determining whether the program has good locality (page faults limited to a single node) on a NUMA computer.</p></li> </ul> <h3><a name="PER-PROCESS">PER-PROCESS</a></h3> <ul> @@ -269,7 +290,7 @@ keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <a href="keyword-inde <ul> <li><a href="io/iostat-scsi.stp">io/iostat-scsi.stp</a> - iostat for SCSI Devices<br> keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <a href="keyword-index.html#SCSI">SCSI</a> <br> -<p>The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the various machines's SCSI devices. The script takes one argument which is the number of seconds between reports.</p></li> +<p>The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the machine's various SCSI devices. The script takes one argument which is the number of seconds between reports.</p></li> <li><a href="io/iostats.stp">io/iostats.stp</a> - List Executables Reading and Writing the Most Data<br> keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <br> <p> The iostat.stp script measures the amount of data successfully read and written by all the executables on the system. The output is sorted from most greatest sum of bytes read and written by an executable to the least. The output contains the count of operations (opens, reads, and writes), the totals and averages for the number of bytes read and written.</p></li> @@ -293,7 +314,7 @@ keywords: <a href="keyword-index.html#PROFILING">PROFILING</a> <br> <ul> <li><a href="io/iotime.stp">io/iotime.stp</a> - Trace Time Spent in Read and Write for Files <br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#READ">READ</a> <a href="keyword-index.html#WRITE">WRITE</a> <a href="keyword-index.html#TIME">TIME</a> <a href="keyword-index.html#IO">IO</a> <br> -<p>The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parenthesese. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls.</p></li> +<p>The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parentheses. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls.</p></li> </ul> <h3><a name="SCHEDULER">SCHEDULER</a></h3> <ul> @@ -317,7 +338,7 @@ keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#SCH <ul> <li><a href="io/iostat-scsi.stp">io/iostat-scsi.stp</a> - iostat for SCSI Devices<br> keywords: <a href="keyword-index.html#IO">IO</a> <a href="keyword-index.html#PROFILING">PROFILING</a> <a href="keyword-index.html#SCSI">SCSI</a> <br> -<p>The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the various machines's SCSI devices. The script takes one argument which is the number of seconds between reports.</p></li> +<p>The iostat-scsi.stp script provides a breakdown of the number of blks read and written on the machine's various SCSI devices. The script takes one argument which is the number of seconds between reports.</p></li> </ul> <h3><a name="SIGNALS">SIGNALS</a></h3> <ul> @@ -329,7 +350,7 @@ keywords: <a href="keyword-index.html#SIGNALS">SIGNALS</a> <br> <p>Print signal counts by process name in descending order.</p></li> <li><a href="process/sigkill.stp">process/sigkill.stp</a> - Track SIGKILL Signals<br> keywords: <a href="keyword-index.html#SIGNALS">SIGNALS</a> <br> -<p>The script traces any SIGKILL signals. When that SIGKILL signal is sent to a process, the script prints out the signal name, the desination executable and process ID, the executable name user ID that sent the signal.</p></li> +<p>The script traces any SIGKILL signals. When that SIGKILL signal is sent to a process, the script prints out the signal name, the destination executable and process ID, the executable name user ID that sent the signal.</p></li> <li><a href="process/sigmon.stp">process/sigmon.stp</a> - Track a particular signal to a specific process<br> keywords: <a href="keyword-index.html#SIGNALS">SIGNALS</a> <br> <p>The script watches for a particular signal sent to a specific process. When that signal is sent to the specified process, the script prints out the PID and executable of the process sending the signal, the PID and executable name of the process receiving the signal, and the signal number and name.</p></li> @@ -344,7 +365,7 @@ keywords: <a href="keyword-index.html#SIMPLE">SIMPLE</a> <br> <ul> <li><a href="process/sleeptime.stp">process/sleeptime.stp</a> - Trace Time Spent in nanosleep Syscalls<br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#SLEEP">SLEEP</a> <br> -<p>The script watches each nanosleep syscall on the system. At the end of each nanosleep syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in paretheses, the "nanosleep:" key, and the duration of the sleep in microseconds.</p></li> +<p>The script watches each nanosleep syscall on the system. At the end of each nanosleep syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in parentheses, the "nanosleep:" key, and the duration of the sleep in microseconds.</p></li> </ul> <h3><a name="SOCKET">SOCKET</a></h3> <ul> @@ -365,7 +386,7 @@ keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-inde <ul> <li><a href="io/iotime.stp">io/iotime.stp</a> - Trace Time Spent in Read and Write for Files <br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#READ">READ</a> <a href="keyword-index.html#WRITE">WRITE</a> <a href="keyword-index.html#TIME">TIME</a> <a href="keyword-index.html#IO">IO</a> <br> -<p>The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parenthesese. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls.</p></li> +<p>The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parentheses. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls.</p></li> <li><a href="process/errsnoop.stp">process/errsnoop.stp</a> - tabulate system call errors<br> keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <a href="keyword-index.html#SYSCALL">SYSCALL</a> <br> <p>The script prints a periodic tabular report about failing system calls, by process and by syscall failure. The first optional argument specifies the reporting interval (in seconds, default 5); the second optional argument gives a screen height (number of lines in the report, default 20).</p></li> @@ -374,16 +395,16 @@ keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-inde <p>The script watches the futex syscall on the system. On exit the futexes address, the number of contentions, and the average time for each contention on the futex are printed from lowest pid number to highest.</p></li> <li><a href="process/sleeptime.stp">process/sleeptime.stp</a> - Trace Time Spent in nanosleep Syscalls<br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#SLEEP">SLEEP</a> <br> -<p>The script watches each nanosleep syscall on the system. At the end of each nanosleep syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in paretheses, the "nanosleep:" key, and the duration of the sleep in microseconds.</p></li> +<p>The script watches each nanosleep syscall on the system. At the end of each nanosleep syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in parentheses, the "nanosleep:" key, and the duration of the sleep in microseconds.</p></li> <li><a href="process/syscalls_by_pid.stp">process/syscalls_by_pid.stp</a> - System-Wide Count of Syscalls by PID<br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <br> <p>The script watches all syscall on the system. On exit the script prints a list showing the number of systemcalls executed by each PID ordered from greatest to least number of syscalls.</p></li> <li><a href="process/syscalls_by_proc.stp">process/syscalls_by_proc.stp</a> - System-Wide Count of Syscalls by Executable<br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <br> -<p>The script watches all syscall on the system. On exit the script prints a list showing the number of systemcalls executed by each executable ordered from greates to least number of syscalls.</p></li> +<p>The script watches all syscall on the system. On exit the script prints a list showing the number of systemcalls executed by each executable ordered from greatest to least number of syscalls.</p></li> <li><a href="process/wait4time.stp">process/wait4time.stp</a> - Trace Time Spent in wait4 Syscalls<br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#WAIT4">WAIT4</a> <br> -<p>The script watches each wait4 syscall on the system. At the end of each wait4 syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in paretheses, the "wait4:" key, the duration of the wait and the PID that the wait4 was waiting for. If the waited for PID is not specified , it is "-1".</p></li> +<p>The script watches each wait4 syscall on the system. At the end of each wait4 syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in parentheses, the "wait4:" key, the duration of the wait and the PID that the wait4 was waiting for. If the waited for PID is not specified , it is "-1".</p></li> </ul> <h3><a name="TCP">TCP</a></h3> <ul> @@ -398,7 +419,7 @@ keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-inde <ul> <li><a href="io/iotime.stp">io/iotime.stp</a> - Trace Time Spent in Read and Write for Files <br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#READ">READ</a> <a href="keyword-index.html#WRITE">WRITE</a> <a href="keyword-index.html#TIME">TIME</a> <a href="keyword-index.html#IO">IO</a> <br> -<p>The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parenthesese. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls.</p></li> +<p>The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parentheses. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls.</p></li> <li><a href="process/schedtimes.stp">process/schedtimes.stp</a> - Track Time Processes Spend in Various States using Tracepoints<br> keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <a href="keyword-index.html#SCHEDULER">SCHEDULER</a> <a href="keyword-index.html#TIME">TIME</a> <a href="keyword-index.html#TRACEPOINT">TRACEPOINT</a> <br> <p>The schedtimes.stp script instruments the scheduler to track the amount of time that each process spends running, sleeping, queued, and waiting for io. On exit the script prints out the accumulated time for each state of processes observed. Optionally, this script can be used with the '-c' or '-x' options to focus on a specific PID.</p></li> @@ -420,6 +441,9 @@ keywords: <a href="keyword-index.html#PROCESS">PROCESS</a> <a href="keyword-inde </ul> <h3><a name="TRAFFIC">TRAFFIC</a></h3> <ul> +<li><a href="network/netdev.stp">network/netdev.stp</a> - Trace Activity on Network Devices<br> +keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#DEVICE">DEVICE</a> <a href="keyword-index.html#TRAFFIC">TRAFFIC</a> <br> +<p>The netdev.stp script traces configuration and transmit/receive activity on network devices.</p></li> <li><a href="network/nettop.stp">network/nettop.stp</a> - Periodic Listing of Processes Using Network Interfaces<br> keywords: <a href="keyword-index.html#NETWORK">NETWORK</a> <a href="keyword-index.html#TRAFFIC">TRAFFIC</a> <a href="keyword-index.html#PER-PROCESS">PER-PROCESS</a> <br> <p>Every five seconds the nettop.stp script prints out a list of processed (PID and command) with the number of packets sent/received and the amount of data sent/received by the process during that interval.</p></li> @@ -443,13 +467,13 @@ keywords: <a href="keyword-index.html#DISK">DISK</a> <a href="keyword-index.html <ul> <li><a href="process/wait4time.stp">process/wait4time.stp</a> - Trace Time Spent in wait4 Syscalls<br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#WAIT4">WAIT4</a> <br> -<p>The script watches each wait4 syscall on the system. At the end of each wait4 syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in paretheses, the "wait4:" key, the duration of the wait and the PID that the wait4 was waiting for. If the waited for PID is not specified , it is "-1".</p></li> +<p>The script watches each wait4 syscall on the system. At the end of each wait4 syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in parentheses, the "wait4:" key, the duration of the wait and the PID that the wait4 was waiting for. If the waited for PID is not specified , it is "-1".</p></li> </ul> <h3><a name="WRITE">WRITE</a></h3> <ul> <li><a href="io/iotime.stp">io/iotime.stp</a> - Trace Time Spent in Read and Write for Files <br> keywords: <a href="keyword-index.html#SYSCALL">SYSCALL</a> <a href="keyword-index.html#READ">READ</a> <a href="keyword-index.html#WRITE">WRITE</a> <a href="keyword-index.html#TIME">TIME</a> <a href="keyword-index.html#IO">IO</a> <br> -<p>The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parenthesese. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls.</p></li> +<p>The script watches each open, close, read, and write syscalls on the system. For each file the scripts observes opened it accumulates the amount of wall clock time spend in read and write operations and the number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in parentheses. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write syscalls.</p></li> </ul> </td> </tr> diff --git a/testsuite/systemtap.examples/keyword-index.txt b/testsuite/systemtap.examples/keyword-index.txt index 4f1ce8f2..056b553a 100644 --- a/testsuite/systemtap.examples/keyword-index.txt +++ b/testsuite/systemtap.examples/keyword-index.txt @@ -80,6 +80,15 @@ keywords: disk cpu use graph and CPU USE. += DEVICE = + +network/netdev.stp - Trace Activity on Network Devices +keywords: network device traffic + + The netdev.stp script traces configuration and transmit/receive + activity on network devices. + + = DISK = general/graphs.stp - Graphing Disk and CPU Utilization @@ -97,6 +106,15 @@ keywords: disk ten entries during that period. += FILESYSTEM = + +general/badname.stp - Bad Filename Filter +keywords: filesystem hack + + The badname.stp script shows how one could prevent the creation of + files with undesirable names using guru mode. + + = FORMAT = general/ansi_colors.stp - Color Table for ansi_set_color2() and ansi_set_color3() @@ -157,6 +175,15 @@ keywords: disk cpu use graph and CPU USE. += HACK = + +general/badname.stp - Bad Filename Filter +keywords: filesystem hack + + The badname.stp script shows how one could prevent the creation of + files with undesirable names using guru mode. + + = INTERRUPT = interrupt/scf.stp - Tally Backtraces for Inter-Processor Interrupt (IPI) @@ -185,7 +212,7 @@ keywords: io The ioblktime.stp script tracks the amount of time that each block IO requests spend waiting for completion. The script computes the average time waiting time for block IO per device and prints list - every 10 seconds. In some cases there can be too many oustanding + every 10 seconds. In some cases there can be too many outstanding block IO operations and the script may exceed the default number of MAXMAPENTRIES allowed. In this case the allowed number can be increased with "-DMAXMAPENTRIES=10000" option on the stap command @@ -196,7 +223,7 @@ io/iostat-scsi.stp - iostat for SCSI Devices keywords: io profiling scsi The iostat-scsi.stp script provides a breakdown of the number of blks - read and written on the various machines's SCSI devices. The script + read and written on the machine's various SCSI devices. The script takes one argument which is the number of seconds between reports. @@ -220,7 +247,7 @@ keywords: syscall read write time io number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in - parenthesese. The first line with the "access" keyword lists the file + parentheses. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write @@ -345,9 +372,9 @@ memory/mmreclaim.stp - Track Virtual Memory System Page Reclamation keywords: memory The mmreclaim.stp script uses the virtual memory tracepoints - available in some kernels to track page reclaim activity that occured - while the script was running. Its useful is debugging performance - problems that occur due to page reclamation. + available in some kernels to track page reclaim activity that + occurred while the script was running. Its useful is debugging + performance problems that occur due to page reclamation. memory/mmwriteback.stp - Track Virtual Memory System Writing to Disk @@ -357,7 +384,7 @@ keywords: memory available in some kernels to report all of the file writebacks that occur form kupdate, pdflush and kjournald while the script is running. Its useful in determining where writes are coming from on a - supposedly idle system that is experiencing upexpected IO. + supposedly idle system that is experiencing unexpected IO. memory/numa_faults.stp - Summarize Process Misses across NUMA Nodes @@ -365,7 +392,7 @@ keywords: memory numa The numa_faults.stp script tracks the read and write pages faults for each process. When the script exits it prints out the total read and - write pages faults for each process. The script also providea a break + write pages faults for each process. The script also provide a break down of page faults per node for each process. This script is useful for determining whether the program has good locality (page faults limited to a single node) on a NUMA computer. @@ -380,7 +407,7 @@ keywords: memory completed, the pid of the process, the address of the page fault, the type of access (read or write), the type of fault (major or minor), and the elapsed time for page fault. This log can be examined to - determine where the page faults are occuring. + determine where the page faults are occurring. network/sk_stream_wait_memory.stp - Track Start and Stop of Processes Due to Network Buffer Space @@ -418,6 +445,13 @@ keywords: network tracepoint buffer free socket buffers freed at locations in the kernel. +network/netdev.stp - Trace Activity on Network Devices +keywords: network device traffic + + The netdev.stp script traces configuration and transmit/receive + activity on network devices. + + network/nettop.stp - Periodic Listing of Processes Using Network Interfaces keywords: network traffic per-process @@ -490,7 +524,7 @@ keywords: memory numa The numa_faults.stp script tracks the read and write pages faults for each process. When the script exits it prints out the total read and - write pages faults for each process. The script also providea a break + write pages faults for each process. The script also provide a break down of page faults per node for each process. This script is useful for determining whether the program has good locality (page faults limited to a single node) on a NUMA computer. @@ -551,7 +585,7 @@ io/iostat-scsi.stp - iostat for SCSI Devices keywords: io profiling scsi The iostat-scsi.stp script provides a breakdown of the number of blks - read and written on the various machines's SCSI devices. The script + read and written on the machine's various SCSI devices. The script takes one argument which is the number of seconds between reports. @@ -624,7 +658,7 @@ keywords: syscall read write time io number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in - parenthesese. The first line with the "access" keyword lists the file + parentheses. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write @@ -689,7 +723,7 @@ io/iostat-scsi.stp - iostat for SCSI Devices keywords: io profiling scsi The iostat-scsi.stp script provides a breakdown of the number of blks - read and written on the various machines's SCSI devices. The script + read and written on the machine's various SCSI devices. The script takes one argument which is the number of seconds between reports. @@ -712,7 +746,7 @@ keywords: signals The script traces any SIGKILL signals. When that SIGKILL signal is sent to a process, the script prints out the signal name, the - desination executable and process ID, the executable name user ID + destination executable and process ID, the executable name user ID that sent the signal. @@ -743,7 +777,7 @@ keywords: syscall sleep The script watches each nanosleep syscall on the system. At the end of each nanosleep syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in - paretheses, the "nanosleep:" key, and the duration of the sleep in + parentheses, the "nanosleep:" key, and the duration of the sleep in microseconds. @@ -792,7 +826,7 @@ keywords: syscall read write time io number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in - parenthesese. The first line with the "access" keyword lists the file + parentheses. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write @@ -824,7 +858,7 @@ keywords: syscall sleep The script watches each nanosleep syscall on the system. At the end of each nanosleep syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in - paretheses, the "nanosleep:" key, and the duration of the sleep in + parentheses, the "nanosleep:" key, and the duration of the sleep in microseconds. @@ -841,7 +875,7 @@ keywords: syscall The script watches all syscall on the system. On exit the script prints a list showing the number of systemcalls executed by each - executable ordered from greates to least number of syscalls. + executable ordered from greatest to least number of syscalls. process/wait4time.stp - Trace Time Spent in wait4 Syscalls @@ -849,7 +883,7 @@ keywords: syscall wait4 The script watches each wait4 syscall on the system. At the end of each wait4 syscall the script prints out a line with a timestamp in - microseconds, the pid, the executable name in paretheses, the + microseconds, the pid, the executable name in parentheses, the "wait4:" key, the duration of the wait and the PID that the wait4 was waiting for. If the waited for PID is not specified , it is "-1". @@ -886,7 +920,7 @@ keywords: syscall read write time io number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in - parenthesese. The first line with the "access" keyword lists the file + parentheses. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write @@ -937,6 +971,13 @@ keywords: process scheduler time tracepoint = TRAFFIC = +network/netdev.stp - Trace Activity on Network Devices +keywords: network device traffic + + The netdev.stp script traces configuration and transmit/receive + activity on network devices. + + network/nettop.stp - Periodic Listing of Processes Using Network Interfaces keywords: network traffic per-process @@ -981,7 +1022,7 @@ keywords: syscall wait4 The script watches each wait4 syscall on the system. At the end of each wait4 syscall the script prints out a line with a timestamp in - microseconds, the pid, the executable name in paretheses, the + microseconds, the pid, the executable name in parentheses, the "wait4:" key, the duration of the wait and the PID that the wait4 was waiting for. If the waited for PID is not specified , it is "-1". @@ -997,7 +1038,7 @@ keywords: syscall read write time io number of bytes read and written. When a file is closed the script prints out a pair of lines for the file. Both lines begin with a timestamp in microseconds, the PID number, and the executable name in - parenthesese. The first line with the "access" keyword lists the file + parentheses. The first line with the "access" keyword lists the file name, the attempted number of bytes for the read and write operations. The second line with the "iotime" keyword list the file name and the number of microseconds accumulated in the read and write diff --git a/testsuite/systemtap.examples/memory/mmreclaim.meta b/testsuite/systemtap.examples/memory/mmreclaim.meta index c3b9cfc6..c301d302 100644 --- a/testsuite/systemtap.examples/memory/mmreclaim.meta +++ b/testsuite/systemtap.examples/memory/mmreclaim.meta @@ -8,7 +8,7 @@ status: experimental exit: user-controlled output: sorted-list scope: system-wide -description: The mmreclaim.stp script uses the virtual memory tracepoints available in some kernels to track page reclaim activity that occured while the script was running. Its useful is debugging performance problems that occur due to page reclamation. +description: The mmreclaim.stp script uses the virtual memory tracepoints available in some kernels to track page reclaim activity that occurred while the script was running. Its useful is debugging performance problems that occur due to page reclamation. test_support: stap -l kernel.trace("mm_directreclaim_reclaimall"),kernel.trace("mm_pagereclaim_shrinkinactive"),kernel.trace("mm_pagereclaim_free"),kernel.trace("mm_pagereclaim_pgout"),kernel.trace("mm_pagereclaim_shrinkactive_a2a"),kernel.trace("mm_pagereclaim_shrinkinactive_i2a"),kernel.trace("mm_pagereclaim_shrinkactive_a2i"),kernel.trace("mm_pagereclaim_shrinkinactive_i2i") test_check: stap -p4 mmreclaim.stp test_installcheck: stap mmreclaim.stp -c "sleep 0.2" diff --git a/testsuite/systemtap.examples/memory/mmwriteback.meta b/testsuite/systemtap.examples/memory/mmwriteback.meta index 1ad4947c..dbcaa476 100644 --- a/testsuite/systemtap.examples/memory/mmwriteback.meta +++ b/testsuite/systemtap.examples/memory/mmwriteback.meta @@ -8,7 +8,7 @@ status: experimental exit: user-controlled output: sorted-list scope: system-wide -description: The mmwriteback.stp script uses the virtual memory tracepoints available in some kernels to report all of the file writebacks that occur form kupdate, pdflush and kjournald while the script is running. Its useful in determining where writes are coming from on a supposedly idle system that is experiencing upexpected IO. +description: The mmwriteback.stp script uses the virtual memory tracepoints available in some kernels to report all of the file writebacks that occur form kupdate, pdflush and kjournald while the script is running. Its useful in determining where writes are coming from on a supposedly idle system that is experiencing unexpected IO. test_support: stap -l kernel.trace("mm_pdflush_bgwriteout"),kernel.trace("mm_pdflush_kupdate"),kernel.trace("mm_pagereclaim_pgout") test_check: stap -p4 mmwriteback.stp test_installcheck: stap mmwriteback.stp -c "sleep 0.2" diff --git a/testsuite/systemtap.examples/memory/numa_faults.meta b/testsuite/systemtap.examples/memory/numa_faults.meta index 51da3fc7..afd95e07 100644 --- a/testsuite/systemtap.examples/memory/numa_faults.meta +++ b/testsuite/systemtap.examples/memory/numa_faults.meta @@ -8,6 +8,6 @@ status: production exit: user-controlled output: list scope: system-wide -description: The numa_faults.stp script tracks the read and write pages faults for each process. When the script exits it prints out the total read and write pages faults for each process. The script also providea a break down of page faults per node for each process. This script is useful for determining whether the program has good locality (page faults limited to a single node) on a NUMA computer. +description: The numa_faults.stp script tracks the read and write pages faults for each process. When the script exits it prints out the total read and write pages faults for each process. The script also provide a break down of page faults per node for each process. This script is useful for determining whether the program has good locality (page faults limited to a single node) on a NUMA computer. test_check: stap -p4 numa_faults.stp test_installcheck: stap numa_faults.stp -c "sleep 0.2" diff --git a/testsuite/systemtap.examples/memory/pfaults.meta b/testsuite/systemtap.examples/memory/pfaults.meta index 480e3b24..827e3816 100644 --- a/testsuite/systemtap.examples/memory/pfaults.meta +++ b/testsuite/systemtap.examples/memory/pfaults.meta @@ -8,6 +8,6 @@ status: production exit: user-controlled output: sorted-list scope: system-wide -description: The pfaults.stp script generates a simple log for each major and minor page fault that occurs on the system. Each line contains a timestamp (in microseconds) when the page fault servicing was completed, the pid of the process, the address of the page fault, the type of access (read or write), the type of fault (major or minor), and the elapsed time for page fault. This log can be examined to determine where the page faults are occuring. +description: The pfaults.stp script generates a simple log for each major and minor page fault that occurs on the system. Each line contains a timestamp (in microseconds) when the page fault servicing was completed, the pid of the process, the address of the page fault, the type of access (read or write), the type of fault (major or minor), and the elapsed time for page fault. This log can be examined to determine where the page faults are occurring. test_check: stap -p4 pfaults.stp test_installcheck: stap pfaults.stp -c "sleep 0.2" diff --git a/testsuite/systemtap.examples/network/netdev.meta b/testsuite/systemtap.examples/network/netdev.meta new file mode 100644 index 00000000..e467a66a --- /dev/null +++ b/testsuite/systemtap.examples/network/netdev.meta @@ -0,0 +1,13 @@ +title: Trace Activity on Network Devices +name: netdev.stp +version: 1.0 +author: Breno Leitao +keywords: network device traffic +subsystem: network +status: production +exit: user-controlled +output: trace +scope: system-wide +description: The netdev.stp script traces configuration and transmit/receive activity on network devices. +test_check: stap -p4 netdev.stp +test_installcheck: stap netdev.stp -c "sleep 0.2" diff --git a/testsuite/systemtap.examples/network/netdev.stp b/testsuite/systemtap.examples/network/netdev.stp new file mode 100755 index 00000000..faf4d2ae --- /dev/null +++ b/testsuite/systemtap.examples/network/netdev.stp @@ -0,0 +1,58 @@ +#! /usr/bin/env stap + +############################################################ +# netdev.stp +# Author: Breno Leitao <leitao@linux.vnet.ibm.com> +# An example script to show how a netdev works and its +# functions +############################################################ + + +probe netdev.get_stats{ + printf("%s was asked for statistics structure\n", dev_name) +} + +probe netdev.register{ + printf("Registering netdev_name %s\n", dev_name) +} + +probe netdev.unregister{ + printf("Unregistering netdev %s\n", dev_name) +} + +probe netdev.ioctl{ + printf("Netdev ioctl raised with param: %d and arg: %s\n", cmd, arg) +} + +probe netdev.set_promiscuity { + if (enable) + printf("Device %s entering in promiscuous mode\n", dev_name) + else + printf("Device %s leaving promiscuous mode\n", dev_name) +} + +probe netdev.change_rx_flag { + printf("Device %s is changing its RX flags to %d\n", dev_name, flags) +} + +probe netdev.change_mtu { + printf("Changing MTU on device %s from %d to %d\n", dev_name, + old_mtu, new_mtu) +} + +probe netdev.change_mac { + printf("Changing MAC address on device %s from %s to %s\n", + dev_name, old_mac, new_mac) +} + +probe netdev.transmit { + printf("Device %s is sending (queued) a packet with protocol %d\n", dev_name, protocol) +} + +probe netdev.hard_transmit { + printf("Device %s is sending (hard) a packet with protocol %d\n", dev_name, protocol) +} + +probe netdev.rx { + printf("Device %s received a packet with protocol %d\n", dev_name, protocol) +} diff --git a/testsuite/systemtap.examples/process/sigkill.meta b/testsuite/systemtap.examples/process/sigkill.meta index b0e04ce8..b9c83f15 100644 --- a/testsuite/systemtap.examples/process/sigkill.meta +++ b/testsuite/systemtap.examples/process/sigkill.meta @@ -8,7 +8,7 @@ status: production exit: user-controlled output: trace scope: systemwide -description: The script traces any SIGKILL signals. When that SIGKILL signal is sent to a process, the script prints out the signal name, the desination executable and process ID, the executable name user ID that sent the signal. +description: The script traces any SIGKILL signals. When that SIGKILL signal is sent to a process, the script prints out the signal name, the destination executable and process ID, the executable name user ID that sent the signal. arg_1: The name of the signal to look for on selected process. test_check: stap -p4 sigkill.stp test_installcheck: stap sigkill.stp -c "sleep 0.2" diff --git a/testsuite/systemtap.examples/process/sleeptime.meta b/testsuite/systemtap.examples/process/sleeptime.meta index 7318c7aa..e5aa4f35 100644 --- a/testsuite/systemtap.examples/process/sleeptime.meta +++ b/testsuite/systemtap.examples/process/sleeptime.meta @@ -8,6 +8,6 @@ status: production exit: user-controlled output: trace scope: system-wide -description: The script watches each nanosleep syscall on the system. At the end of each nanosleep syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in paretheses, the "nanosleep:" key, and the duration of the sleep in microseconds. +description: The script watches each nanosleep syscall on the system. At the end of each nanosleep syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in parentheses, the "nanosleep:" key, and the duration of the sleep in microseconds. test_check: stap -p4 sleeptime.stp test_installcheck: stap sleeptime.stp -c "sleep 0.2" diff --git a/testsuite/systemtap.examples/process/syscalls_by_proc.meta b/testsuite/systemtap.examples/process/syscalls_by_proc.meta index 42668bc8..6bb6a650 100644 --- a/testsuite/systemtap.examples/process/syscalls_by_proc.meta +++ b/testsuite/systemtap.examples/process/syscalls_by_proc.meta @@ -8,6 +8,6 @@ status: production exit: user-controlled output: sorted-list on-exit scope: system-wide -description: The script watches all syscall on the system. On exit the script prints a list showing the number of systemcalls executed by each executable ordered from greates to least number of syscalls. +description: The script watches all syscall on the system. On exit the script prints a list showing the number of systemcalls executed by each executable ordered from greatest to least number of syscalls. test_check: stap -p4 syscalls_by_proc.stp test_installcheck: stap syscalls_by_proc.stp -c "sleep 0.2" diff --git a/testsuite/systemtap.examples/process/wait4time.meta b/testsuite/systemtap.examples/process/wait4time.meta index e798014b..a9c9089a 100644 --- a/testsuite/systemtap.examples/process/wait4time.meta +++ b/testsuite/systemtap.examples/process/wait4time.meta @@ -8,6 +8,6 @@ status: production exit: user-controlled output: trace scope: system-wide -description: The script watches each wait4 syscall on the system. At the end of each wait4 syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in paretheses, the "wait4:" key, the duration of the wait and the PID that the wait4 was waiting for. If the waited for PID is not specified , it is "-1". +description: The script watches each wait4 syscall on the system. At the end of each wait4 syscall the script prints out a line with a timestamp in microseconds, the pid, the executable name in parentheses, the "wait4:" key, the duration of the wait and the PID that the wait4 was waiting for. If the waited for PID is not specified , it is "-1". test_check: stap -p4 wait4time.stp test_installcheck: stap wait4time.stp -c "sleep 0.2" diff --git a/translate.cxx b/translate.cxx index e32f932a..04a92476 100644 --- a/translate.cxx +++ b/translate.cxx @@ -5268,6 +5268,7 @@ translate_pass (systemtap_session& s) s.op->newline() << "#include <linux/version.h>"; // s.op->newline() << "#include <linux/compile.h>"; s.op->newline() << "#include \"loc2c-runtime.h\" "; + s.op->newline() << "#include \"access_process_vm.h\" "; // XXX: old 2.6 kernel hack s.op->newline() << "#ifndef read_trylock"; |