diff options
author | Dave Brolley <brolley@redhat.com> | 2009-04-02 12:38:15 -0400 |
---|---|---|
committer | Dave Brolley <brolley@redhat.com> | 2009-04-02 12:38:15 -0400 |
commit | 2f53f831393d2f0db3d54260c2a7882eff17905c (patch) | |
tree | ba140bbad1fd4acaa7c2253949a2b2ade53952a2 | |
parent | 2f54c4fe5a3aa21b4d5c38edabf83f3cdad0177d (diff) | |
parent | 15a78144473940a4e7c685cc57ba09a92f2293c6 (diff) | |
download | systemtap-steved-2f53f831393d2f0db3d54260c2a7882eff17905c.tar.gz systemtap-steved-2f53f831393d2f0db3d54260c2a7882eff17905c.tar.xz systemtap-steved-2f53f831393d2f0db3d54260c2a7882eff17905c.zip |
Merge branch 'master' of git://sources.redhat.com/git/systemtap
Conflicts:
configure
47 files changed, 689 insertions, 366 deletions
diff --git a/Makefile.in b/Makefile.in index 495bed87..f14918ee 100644 --- a/Makefile.in +++ b/Makefile.in @@ -78,7 +78,7 @@ DIST_COMMON = INSTALL NEWS README AUTHORS $(srcdir)/Makefile.in \ $(top_srcdir)/man/stapprobes.tcp.3stap.in \ $(top_srcdir)/man/stapprobes.udp.3stap.in \ $(top_srcdir)/initscript/systemtap.in $(srcdir)/run-stap.in \ - depcomp $(oldinclude_HEADERS) + $(srcdir)/run-staprun.in depcomp $(oldinclude_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ @@ -95,7 +95,7 @@ CONFIG_CLEAN_FILES = stap.1 stapprobes.3stap stapfuncs.3stap \ man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap \ man/stapprobes.signal.3stap man/stapprobes.socket.3stap \ man/stapprobes.tcp.3stap man/stapprobes.udp.3stap \ - initscript/systemtap run-stap + initscript/systemtap run-stap run-staprun @BUILD_SERVER_TRUE@am__EXEEXT_1 = stap-client-connect$(EXEEXT) \ @BUILD_SERVER_TRUE@ stap-server-connect$(EXEEXT) am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(pkglibexecdir)" \ @@ -238,6 +238,7 @@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ PIECFLAGS = @PIECFLAGS@ PIECXXFLAGS = @PIECXXFLAGS@ PIELDFLAGS = @PIELDFLAGS@ @@ -486,6 +487,8 @@ initscript/systemtap: $(top_builddir)/config.status $(top_srcdir)/initscript/sys cd $(top_builddir) && $(SHELL) ./config.status $@ run-stap: $(top_builddir)/config.status $(srcdir)/run-stap.in cd $(top_builddir) && $(SHELL) ./config.status $@ +run-staprun: $(top_builddir)/config.status $(srcdir)/run-staprun.in + cd $(top_builddir) && $(SHELL) ./config.status $@ install-binPROGRAMS: $(bin_PROGRAMS) @$(NORMAL_INSTALL) test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" @@ -1,3 +1,10 @@ +* What's new + +- The --skip-badvars option now also suppresses run-time error + messages that would otherwise result from erroneous memory accesses. + Such accesses can originate from $context expressions fueled by + erroneous debug data, or by kernel_{long,string,...}() tapset calls. + * What's new in version 0.9.5 - New probes process().insn and process().insn.block that allows diff --git a/buildrun.cxx b/buildrun.cxx index aafb8a6d..949f0859 100644 --- a/buildrun.cxx +++ b/buildrun.cxx @@ -59,7 +59,7 @@ run_make_cmd(systemtap_session& s, string& make_cmd) make_cmd += " -s >/dev/null 2>&1"; if (s.verbose > 1) clog << "Running " << make_cmd << endl; - rc = system (make_cmd.c_str()); + rc = stap_system (make_cmd.c_str()); return rc; } @@ -234,7 +234,7 @@ kernel_built_uprobes (systemtap_session& s) { string grep_cmd = string ("/bin/grep -q unregister_uprobe ") + s.kernel_build_tree + string ("/Module.symvers"); - int rc = system (grep_cmd.c_str()); + int rc = stap_system (grep_cmd.c_str()); return (rc == 0); } @@ -285,7 +285,7 @@ copy_uprobes_symbols (systemtap_session& s) string uprobes_home = s.runtime_path + "/uprobes"; string cp_cmd = string("/bin/cp ") + uprobes_home + string("/Module.symvers ") + s.tmpdir; - int rc = system (cp_cmd.c_str()); + int rc = stap_system (cp_cmd.c_str()); return rc; } @@ -350,7 +350,7 @@ run_pass (systemtap_session& s) if (s.verbose>1) clog << "Running " << staprun_cmd << endl; - rc = system (staprun_cmd.c_str ()); + rc = stap_system (staprun_cmd.c_str ()); return rc; } @@ -706,6 +706,7 @@ EGREP U ANSI2KNR RANLIB +PERL PIELDFLAGS PIECFLAGS PIECXXFLAGS @@ -5824,6 +5825,47 @@ fi +# Extract the first word of "perl", so it can be a program name with args. +set dummy perl; ac_word=$2 +{ echo "$as_me:$LINENO: checking for $ac_word" >&5 +echo $ECHO_N "checking for $ac_word... $ECHO_C" >&6; } +if test "${ac_cv_path_PERL+set}" = set; then + echo $ECHO_N "(cached) $ECHO_C" >&6 +else + case $PERL in + [\\/]* | ?:[\\/]*) + ac_cv_path_PERL="$PERL" # Let the user override the test with a path. + ;; + *) + as_save_IFS=$IFS; IFS=$PATH_SEPARATOR +for as_dir in $PATH +do + IFS=$as_save_IFS + test -z "$as_dir" && as_dir=. + for ac_exec_ext in '' $ac_executable_extensions; do + if { test -f "$as_dir/$ac_word$ac_exec_ext" && $as_test_x "$as_dir/$ac_word$ac_exec_ext"; }; then + ac_cv_path_PERL="$as_dir/$ac_word$ac_exec_ext" + echo "$as_me:$LINENO: found $as_dir/$ac_word$ac_exec_ext" >&5 + break 2 + fi +done +done +IFS=$as_save_IFS + + ;; +esac +fi +PERL=$ac_cv_path_PERL +if test -n "$PERL"; then + { echo "$as_me:$LINENO: result: $PERL" >&5 +echo "${ECHO_T}$PERL" >&6; } +else + { echo "$as_me:$LINENO: result: no" >&5 +echo "${ECHO_T}no" >&6; } +fi + + + # Check whether --enable-perfmon was given. if test "${enable_perfmon+set}" = set; then enableval=$enable_perfmon; @@ -7882,6 +7924,8 @@ subdirs="$subdirs testsuite" ac_config_files="$ac_config_files run-stap" +ac_config_files="$ac_config_files run-staprun" + cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -8548,6 +8592,7 @@ do "man/stapprobes.udp.3stap") CONFIG_FILES="$CONFIG_FILES man/stapprobes.udp.3stap" ;; "initscript/systemtap") CONFIG_FILES="$CONFIG_FILES initscript/systemtap" ;; "run-stap") CONFIG_FILES="$CONFIG_FILES run-stap" ;; + "run-staprun") CONFIG_FILES="$CONFIG_FILES run-staprun" ;; *) { { echo "$as_me:$LINENO: error: invalid argument: $ac_config_target" >&5 echo "$as_me: error: invalid argument: $ac_config_target" >&2;} @@ -8702,11 +8747,11 @@ EGREP!$EGREP$ac_delim U!$U$ac_delim ANSI2KNR!$ANSI2KNR$ac_delim RANLIB!$RANLIB$ac_delim +PERL!$PERL$ac_delim PIELDFLAGS!$PIELDFLAGS$ac_delim PIECFLAGS!$PIECFLAGS$ac_delim PIECXXFLAGS!$PIECXXFLAGS$ac_delim sqlite3_LIBS!$sqlite3_LIBS$ac_delim -staplog_CPPFLAGS!$staplog_CPPFLAGS$ac_delim _ACEOF if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 97; then @@ -8748,6 +8793,7 @@ _ACEOF ac_delim='%!_!# ' for ac_last_try in false false false false false :; do cat >conf$$subs.sed <<_ACEOF +staplog_CPPFLAGS!$staplog_CPPFLAGS$ac_delim BUILD_CRASHMOD_TRUE!$BUILD_CRASHMOD_TRUE$ac_delim BUILD_CRASHMOD_FALSE!$BUILD_CRASHMOD_FALSE$ac_delim have_latex!$have_latex$ac_delim @@ -8777,7 +8823,7 @@ LIBOBJS!$LIBOBJS$ac_delim LTLIBOBJS!$LTLIBOBJS$ac_delim _ACEOF - if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 27; then + if test `sed -n "s/.*$ac_delim\$/X/p" conf$$subs.sed | grep -c X` = 28; then break elif $ac_last_try; then { { echo "$as_me:$LINENO: error: could not make $CONFIG_STATUS" >&5 @@ -9344,6 +9390,7 @@ echo "$as_me: error: cannot create directory $as_dir" >&2;} done ;; "run-stap":F) chmod +x run-stap ;; + "run-staprun":F) chmod +x run-staprun ;; esac done # for ac_tag diff --git a/configure.ac b/configure.ac index 0c6a43d1..465d2dd7 100644 --- a/configure.ac +++ b/configure.ac @@ -25,6 +25,8 @@ AC_PROG_MAKE_SET AC_SUBST(CFLAGS) AC_SUBST(CXXFLAGS) +AC_PATH_PROG(PERL, perl) + dnl Handle the perfmon option. AC_ARG_ENABLE([perfmon], AS_HELP_STRING([--enable-perfmon@<:@=DIRECTORY@:>@], @@ -362,6 +364,7 @@ AC_CONFIG_HEADERS([config.h:config.in]) AC_CONFIG_FILES(Makefile doc/Makefile doc/SystemTap_Tapset_Reference/Makefile stap.1 stapprobes.3stap stapfuncs.3stap stapvars.3stap stapex.3stap staprun.8 stap-server.8 man/stapprobes.iosched.3stap man/stapprobes.netdev.3stap man/stapprobes.nfs.3stap man/stapprobes.nfsd.3stap man/stapprobes.pagefault.3stap man/stapprobes.process.3stap man/stapprobes.rpc.3stap man/stapprobes.scsi.3stap man/stapprobes.signal.3stap man/stapprobes.socket.3stap man/stapprobes.tcp.3stap man/stapprobes.udp.3stap initscript/systemtap) AC_CONFIG_SUBDIRS(testsuite) AC_CONFIG_FILES([run-stap], [chmod +x run-stap]) +AC_CONFIG_FILES([run-staprun], [chmod +x run-staprun]) AC_OUTPUT if test "${prefix}" = "/usr/local"; then diff --git a/doc/Makefile.in b/doc/Makefile.in index eafd7ca7..beb5553e 100644 --- a/doc/Makefile.in +++ b/doc/Makefile.in @@ -101,6 +101,7 @@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ PIECFLAGS = @PIECFLAGS@ PIECXXFLAGS = @PIECXXFLAGS@ PIELDFLAGS = @PIELDFLAGS@ diff --git a/doc/SystemTap_Tapset_Reference/Makefile.in b/doc/SystemTap_Tapset_Reference/Makefile.in index 30ca4b17..d4bcf8b0 100644 --- a/doc/SystemTap_Tapset_Reference/Makefile.in +++ b/doc/SystemTap_Tapset_Reference/Makefile.in @@ -104,6 +104,7 @@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ +PERL = @PERL@ PIECFLAGS = @PIECFLAGS@ PIECXXFLAGS = @PIECXXFLAGS@ PIELDFLAGS = @PIELDFLAGS@ @@ -174,6 +174,7 @@ find_script_hash (systemtap_session& s, const string& script, const hash &base) h.add(s.ignore_vmlinux); // --ignore-vmlinux h.add(s.ignore_dwarf); // --ignore-dwarf h.add(s.consult_symtab); // --kelf, --kmap + h.add(s.skip_badvars); // --skip-badvars if (!s.kernel_symtab_path.empty()) // --kmap { h.add(s.kernel_symtab_path); diff --git a/includes/sys/sdt.h b/includes/sys/sdt.h index ba75076b..c3fa16d9 100644 --- a/includes/sys/sdt.h +++ b/includes/sys/sdt.h @@ -39,6 +39,19 @@ #endif #define STAP_LABEL(a,b) STAP_CONCAT(a,b) +/* Taking the address of a local label and/or referencing alloca prevents the + containing function from being inlined, which keeps the parameters visible. */ + +#if __GNUC__ == 4 && __GNUC_MINOR__ <= 1 +#include <alloca.h> +#define STAP_UNINLINE alloca((size_t)0) +#else +#define STAP_UNINLINE +#endif + +#define STAP_UNINLINE_LABEL(label) \ + __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label + #define STAP_PROBE_(probe) \ do { \ STAP_PROBE_DATA(probe); \ @@ -46,13 +59,11 @@ do { \ "\tnop"); \ } while (0) -/* Taking the address of a local label prevents the containing function - from being inlined, which keeps the parameters visible. */ - #define STAP_PROBE1_(probe,label,parm1) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -61,9 +72,10 @@ do { \ #define STAP_PROBE2_(probe,label,parm1,parm2) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -72,10 +84,11 @@ do { \ #define STAP_PROBE3_(probe,label,parm1,parm2,parm3) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ - volatile __typeof__((parm1)) arg1 = parm1; \ + STAP_UNINLINE_LABEL(label); \ + volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -84,11 +97,12 @@ do { \ #define STAP_PROBE4_(probe,label,parm1,parm2,parm3,parm4) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ volatile __typeof__((parm4)) arg4 = parm4; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -97,12 +111,13 @@ do { \ #define STAP_PROBE5_(probe,label,parm1,parm2,parm3,parm4,parm5) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ volatile __typeof__((parm4)) arg4 = parm4; \ volatile __typeof__((parm5)) arg5 = parm5; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -111,13 +126,14 @@ do { \ #define STAP_PROBE6_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ volatile __typeof__((parm4)) arg4 = parm4; \ volatile __typeof__((parm5)) arg5 = parm5; \ volatile __typeof__((parm6)) arg6 = parm6; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -126,7 +142,7 @@ do { \ #define STAP_PROBE7_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ @@ -134,6 +150,7 @@ do { \ volatile __typeof__((parm5)) arg5 = parm5; \ volatile __typeof__((parm6)) arg6 = parm6; \ volatile __typeof__((parm7)) arg7 = parm7; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -142,7 +159,7 @@ do { \ #define STAP_PROBE8_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ @@ -151,6 +168,7 @@ do { \ volatile __typeof__((parm6)) arg6 = parm6; \ volatile __typeof__((parm7)) arg7 = parm7; \ volatile __typeof__((parm8)) arg8 = parm8; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -159,7 +177,7 @@ do { \ #define STAP_PROBE9_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ @@ -169,6 +187,7 @@ do { \ volatile __typeof__((parm7)) arg7 = parm7; \ volatile __typeof__((parm8)) arg8 = parm8; \ volatile __typeof__((parm9)) arg9 = parm9; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -177,7 +196,7 @@ do { \ #define STAP_PROBE10_(probe,label,parm1,parm2,parm3,parm4,parm5,parm6,parm7,parm8,parm9,parm10) \ do { \ - __extension__ static volatile long labelval __attribute__ ((unused)) = (long) &&label; \ + STAP_UNINLINE_LABEL(label); \ volatile __typeof__((parm1)) arg1 = parm1; \ volatile __typeof__((parm2)) arg2 = parm2; \ volatile __typeof__((parm3)) arg3 = parm3; \ @@ -188,6 +207,7 @@ do { \ volatile __typeof__((parm8)) arg8 = parm8; \ volatile __typeof__((parm9)) arg9 = parm9; \ volatile __typeof__((parm10)) arg10 = parm10; \ + STAP_UNINLINE; \ STAP_PROBE_DATA(probe); \ label: \ __asm__ volatile ("2:\n" \ @@ -36,8 +36,6 @@ extern "C" { #include <sys/times.h> #include <sys/time.h> #include <sys/stat.h> -#include <sys/types.h> -#include <sys/wait.h> #include <time.h> #include <elfutils/libdwfl.h> #include <getopt.h> @@ -297,14 +295,9 @@ int pending_interrupts; extern "C" void handle_interrupt (int sig) { - if (pending_interrupts == 0) - kill (0, sig); // Forward signals to child processes if any. - + kill_stap_spawn(sig); pending_interrupts ++; - // NB: the "2" below is intended to skip the effect of the self-induced - // deferred signal coming from the kill() above. - - if (pending_interrupts > 2) // XXX: should be configurable? time-based? + if (pending_interrupts > 1) // XXX: should be configurable? time-based? { char msg[] = "Too many interrupts received, exiting.\n"; int rc = write (2, msg, sizeof(msg)-1); @@ -328,7 +321,7 @@ setup_signals (sighandler_t handler) sigaddset (&sa.sa_mask, SIGINT); sigaddset (&sa.sa_mask, SIGTERM); } - sa.sa_flags = 0; + sa.sa_flags = SA_RESTART; sigaction (SIGHUP, &sa, NULL); sigaction (SIGPIPE, &sa, NULL); @@ -336,62 +329,10 @@ setup_signals (sighandler_t handler) sigaction (SIGTERM, &sa, NULL); } -pid_t runner_pid; -int runner (int, char * const []); - -// Passes on signals to runner process. -// In practise passes signal to runner process process group, -// since run_pass() uses system() to spawn child processes, -// which makes the process ignore SIGINT during the command run. -extern "C" -void waiter_handler (int sig) -{ - // Process group is negative process id. - kill (-1 * runner_pid, sig); -} - -// Just sits there till the runner exits and then exits the same way. -void waiter() -{ - int status; - setup_signals (&waiter_handler); - while (waitpid (runner_pid, &status, 0) != runner_pid); - - // Exit as our runner child exitted. - if (WIFEXITED(status)) - exit (WEXITSTATUS(status)); - - // Or simulate as if we were killed by the same signal. - if (WIFSIGNALED(status)) - { - int sig = WTERMSIG(status); - signal (sig, SIG_DFL); - raise (sig); - } - - // Should not happen, exit as if error. - exit(-1); -} int main (int argc, char * const argv []) { - // Fork to make sure runner gets its own process group, while - // the waiter sits in the original process group of the shell - // and forwards any signals. - runner_pid = fork (); - if (runner_pid == 0) - return runner (argc, argv); - if (runner_pid > 0) - waiter (); - - perror ("couldn't fork"); - exit (-1); -} - -int -runner (int argc, char * const argv []) -{ string cmdline_script; // -e PROGRAM string script_file; // FILE bool have_script = false; @@ -943,16 +884,6 @@ runner (int argc, char * const argv []) // directory. s.translated_source = string(s.tmpdir) + "/" + s.module_name + ".c"; - // We want a new process group so we can use kill (0, sig) to send a - // signal to all children (but not the parent). As done in - // handle_interrupt (). - if (setpgrp() != 0) - { - const char* e = strerror (errno); - if (! s.suppress_warnings) - cerr << "Warning: failed to set new process group: " << e << endl; - } - // Set up our handler to catch routine signals, to allow clean // and reasonably timely exit. setup_signals(&handle_interrupt); @@ -1311,7 +1242,7 @@ pass_5: string cleanupcmd = "rm -rf "; cleanupcmd += s.tmpdir; if (s.verbose>1) clog << "Running " << cleanupcmd << endl; - int status = system (cleanupcmd.c_str()); + int status = stap_system (cleanupcmd.c_str()); if (status != 0 && s.verbose>1) clog << "Cleanup command failed, status: " << status << endl; } diff --git a/run-stap.in b/run-stap.in index dfb53ab2..1bfb6a77 100644 --- a/run-stap.in +++ b/run-stap.in @@ -19,11 +19,8 @@ esac # Set all the variables to find the source and build trees. SYSTEMTAP_TAPSET="${srcdir}/tapset" SYSTEMTAP_RUNTIME="${srcdir}/runtime" -SYSTEMTAP_STAPIO="${builddir}/stapio" -SYSTEMTAP_STAPRUN="sudo 'SYSTEMTAP_STAPIO=$SYSTEMTAP_STAPIO' \ - 'SYSTEMTAP_STAPRUN=${builddir}/staprun' \ - ${builddir}/staprun" -export SYSTEMTAP_TAPSET SYSTEMTAP_RUNTIME SYSTEMTAP_STAPRUN SYSTEMTAP_STAPIO +SYSTEMTAP_STAPRUN="sudo -P builddir='${builddir}' ${builddir}/run-staprun" +export SYSTEMTAP_TAPSET SYSTEMTAP_RUNTIME SYSTEMTAP_STAPRUN # If there were private elfutils libs built, use them. if [ -d "$rundir/lib-elfutils" ]; then diff --git a/run-staprun.in b/run-staprun.in new file mode 100644 index 00000000..0b5f795b --- /dev/null +++ b/run-staprun.in @@ -0,0 +1,13 @@ +#!@PERL@ -w + +# Reset real IDs to those we had before we were sudo-invoked. +# This gives staprun the IDs it expects from a setuid exec. +$< = $ENV{'SUDO_UID'}; +$( = $ENV{'SUDO_GID'}; + +$ENV{'SYSTEMTAP_STAPRUN'} = "sudo '$ENV{'builddir'}/staprun'"; +$ENV{'SYSTEMTAP_STAPIO'} = "$ENV{'builddir'}/stapio"; + +exec { "$ENV{'builddir'}/staprun" } ('staprun', @ARGV); + +exit; diff --git a/runtime/loc2c-runtime.h b/runtime/loc2c-runtime.h index 16ddb950..eaf47cad 100644 --- a/runtime/loc2c-runtime.h +++ b/runtime/loc2c-runtime.h @@ -62,6 +62,10 @@ must work right for kernel addresses, and can use whatever existing machine-specific kernel macros are convenient. */ +#if STP_SKIP_BADVARS +#define DEREF_FAULT(addr) ({0; }) +#define STORE_DEREF_FAULT(addr) ({0; }) +#else #define DEREF_FAULT(addr) ({ \ snprintf(c->error_buffer, sizeof(c->error_buffer), \ "kernel read fault at 0x%p (%s)", (void *)(intptr_t)(addr), #addr); \ @@ -75,7 +79,7 @@ c->last_error = c->error_buffer; \ goto deref_fault; \ }) - +#endif #if defined (STAPCONF_X86_UNIREGS) && defined (__i386__) diff --git a/runtime/runtime.h b/runtime/runtime.h index fc5d454f..822562a2 100644 --- a/runtime/runtime.h +++ b/runtime/runtime.h @@ -86,6 +86,9 @@ static struct #include "io.c" #include "arith.c" #include "copy.c" + +#include "task_finder.c" + #include "sym.c" #ifdef STP_PERFMON #include "perf.c" diff --git a/runtime/sym.c b/runtime/sym.c index 1d88a862..d0c5d9fd 100644 --- a/runtime/sym.c +++ b/runtime/sym.c @@ -20,6 +20,40 @@ * @{ */ +/* Callback that needs to be registered (in tapsets.cxx for + emit_module_init) for every user task path or pid for which we + might need symbols or unwind info. */ +static int _stp_tf_vm_cb(struct stap_task_finder_target *tgt, + struct task_struct *tsk, + int map_p, char *vm_path, + unsigned long vm_start, unsigned long vm_end, + unsigned long vm_pgoff) +{ + int i; +#ifdef DEBUG_TASK_FINDER_VMA + _stp_dbug(__FUNCTION__, __LINE__, "vm_cb: tsk %d:%d path %s, start 0x%08lx, end 0x%08lx, offset 0x%lx\n", tsk->pid, map_p, vm_path, vm_start, vm_end, vm_pgoff); +#endif + if (map_p) + { + struct _stp_module *module = NULL; + if (vm_path != NULL) + for (i = 0; i < _stp_num_modules; i++) + if (strcmp(vm_path, _stp_modules[i]->path) == 0) + { +#ifdef DEBUG_TASK_FINDER_VMA + _stp_dbug(__FUNCTION__, __LINE__, "vm_cb: matched path %s to module\n", vm_path); +#endif + module = _stp_modules[i]; + break; + } + stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff, module); + } + else + stap_remove_vma_map_info(tsk, vm_start, vm_end, vm_pgoff); + + return 0; +} + /* XXX: this needs to be address-space-specific. */ static unsigned long _stp_module_relocate(const char *module, const char *section, unsigned long offset) { @@ -76,11 +110,33 @@ static unsigned long _stp_module_relocate(const char *module, const char *sectio if found, return NULL otherwise. XXX: needs to be address-space-specific. */ static struct _stp_module *_stp_mod_sec_lookup(unsigned long addr, + struct task_struct *task, struct _stp_section **sec) { + void *user = NULL; struct _stp_module *m = NULL; unsigned midx = 0; unsigned long closest_section_offset = ~0; + + // Try vma matching first if task given. + if (task) + { + unsigned long vm_start = 0; + if (stap_find_vma_map_info(task, addr, + &vm_start, NULL, + NULL, &user) == 0) + if (user != NULL) + { + m = (struct _stp_module *)user; + *sec = &m->sections[0]; // XXX check actual section and relocate + dbug_sym(1, "found section %s in module %s at 0x%lx\n", + m->sections[0].name, m->name, vm_start); + if (strcmp(".dynamic", m->sections[0].name) == 0) + m->sections[0].addr = vm_start; // cheat... + return m; + } + } + for (midx = 0; midx < _stp_num_modules; midx++) { unsigned secidx; @@ -108,14 +164,15 @@ static const char *_stp_kallsyms_lookup(unsigned long addr, unsigned long *symbo unsigned long *offset, const char **modname, /* char ** secname? */ - char *namebuf) + char *namebuf, + struct task_struct *task) { struct _stp_module *m = NULL; struct _stp_section *sec = NULL; struct _stp_symbol *s = NULL; unsigned end, begin = 0; - m = _stp_mod_sec_lookup(addr, &sec); + m = _stp_mod_sec_lookup(addr, task, &sec); if (unlikely (m == NULL || sec == NULL)) return NULL; @@ -240,7 +297,7 @@ static void _stp_symbol_print(unsigned long address) const char *name; unsigned long offset, size; - name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL); + name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, NULL); _stp_printf("%p", (int64_t) address); @@ -265,7 +322,7 @@ static int _stp_func_print(unsigned long address, int verbose, int exact) else exstr = " (inexact)"; - name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL); + name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, NULL); if (name) { if (verbose) { @@ -281,13 +338,15 @@ static int _stp_func_print(unsigned long address, int verbose, int exact) return 0; } -static void _stp_symbol_snprint(char *str, size_t len, unsigned long address) +static void _stp_symbol_snprint(char *str, size_t len, unsigned long address, + struct task_struct *task) { const char *modname; const char *name; unsigned long offset, size; - name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL); + name = _stp_kallsyms_lookup(address, &size, &offset, &modname, NULL, + task); if (name) strlcpy(str, name, len); else diff --git a/runtime/task_finder.c b/runtime/task_finder.c index 7949a81f..3507c669 100644 --- a/runtime/task_finder.c +++ b/runtime/task_finder.c @@ -2,8 +2,32 @@ #define TASK_FINDER_C #if ! defined(CONFIG_UTRACE) -#error "Need CONFIG_UTRACE!" -#endif +/* Dummy definitions for use in sym.c */ +struct stap_task_finder_target { }; + +static int +stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, + unsigned long vm_end, unsigned long vm_pgoff, + void *user) +{ + return 0; +} + +static int +stap_remove_vma_map_info(struct task_struct *tsk, unsigned long vm_start, + unsigned long vm_end, unsigned long vm_pgoff) +{ + return 0; +} + +static int +stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, + unsigned long *vm_start, unsigned long *vm_end, + unsigned long *vm_pgoff, void **user) +{ + return ESRCH; +} +#else #include <linux/utrace.h> @@ -69,40 +93,6 @@ typedef int (*stap_task_finder_vm_callback)(struct stap_task_finder_target *tgt, unsigned long vm_end, unsigned long vm_pgoff); -static int __stp_tf_vm_cb(struct stap_task_finder_target *tgt, - struct task_struct *tsk, - int map_p, char *vm_path, - unsigned long vm_start, - unsigned long vm_end, - unsigned long vm_pgoff) -{ - int i; -#ifdef DEBUG_TASK_FINDER_VMA - _stp_dbug(__FUNCTION__, __LINE__, - "vm_cb: tsk %d:%d path %s, start 0x%08lx, end 0x%08lx, offset 0x%lx\n", - tsk->pid, map_p, vm_path, vm_start, vm_end, vm_pgoff); -#endif - if (map_p) { - struct _stp_module *module = NULL; - if (vm_path != NULL) - for (i = 0; i < _stp_num_modules; i++) - if (strcmp(vm_path, _stp_modules[i]->path) == 0) - { -#ifdef DEBUG_TASK_FINDER_VMA - _stp_dbug(__FUNCTION__, __LINE__, - "vm_cb: matched path %s to module\n", vm_path); -#endif - module = _stp_modules[i]; - break; - } - stap_add_vma_map_info(tsk, vm_start, vm_end, vm_pgoff, module); - } - else { - stap_remove_vma_map_info(tsk, vm_start, vm_end, vm_pgoff); - } - return 0; -} - struct stap_task_finder_target { /* private: */ struct list_head list; /* __stp_task_finder_list linkage */ @@ -1392,4 +1382,6 @@ stap_stop_task_finder(void) } +#endif /* defined(CONFIG_UTRACE) */ + #endif /* TASK_FINDER_C */ diff --git a/runtime/task_finder_vma.c b/runtime/task_finder_vma.c index 83b206e5..ed9c6f4f 100644 --- a/runtime/task_finder_vma.c +++ b/runtime/task_finder_vma.c @@ -1,13 +1,19 @@ #include <linux/list.h> #include <linux/jhash.h> -#include <linux/mutex.h> +#include <linux/spinlock.h> // When handling memcpy() syscall tracing to notice memory map // changes, we need to cache memcpy() entry parameter values for // processing at memcpy() exit. -// __stp_tf_vma_mutex protects the hash table. -static DEFINE_MUTEX(__stp_tf_vma_mutex); +// __stp_tf_vma_lock protects the hash table. +// Documentation/spinlocks.txt suggest we can be a bit more clever +// if we guarantee that in interrupt context we only read, not write +// the datastructures. We should never change the hash table or the +// contents in interrupt context (which should only ever call +// stap_find_vma_map_info for getting stored vma info). So we might +// want to look into that if this seems a bottleneck. +static DEFINE_RWLOCK(__stp_tf_vma_lock); #define __STP_TF_HASH_BITS 4 #define __STP_TF_TABLE_SIZE (1 << __STP_TF_HASH_BITS) @@ -26,8 +32,8 @@ struct __stp_tf_vma_entry { unsigned long vm_pgoff; // Is that enough? Should we store a dcookie for vm_file? - // Module that this vma entry is mapped from, if any. - struct _stp_module *module; + // User data (possibly stp_module) + void *user; }; static struct __stp_tf_vma_entry @@ -40,23 +46,24 @@ static struct hlist_head __stp_tf_vma_table[__STP_TF_TABLE_SIZE]; static struct hlist_head __stp_tf_vma_map[__STP_TF_TABLE_SIZE]; // __stp_tf_vma_initialize(): Initialize the free list. Grabs the -// mutex. +// spinlock. static void __stp_tf_vma_initialize(void) { int i; struct hlist_head *head = &__stp_tf_vma_free_list[0]; - mutex_lock(&__stp_tf_vma_mutex); + unsigned long flags; + write_lock_irqsave(&__stp_tf_vma_lock, flags); for (i = 0; i < TASK_FINDER_VMA_ENTRY_ITEMS; i++) { hlist_add_head(&__stp_tf_vma_free_list_items[i].hlist, head); } - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); } // __stp_tf_vma_get_free_entry(): Returns an entry from the free list -// or NULL. The __stp_tf_vma_mutex must be locked before calling this +// or NULL. The __stp_tf_vma_lock must be write locked before calling this // function. static struct __stp_tf_vma_entry * __stp_tf_vma_get_free_entry(void) @@ -77,7 +84,7 @@ __stp_tf_vma_get_free_entry(void) // __stp_tf_vma_put_free_entry(): Puts an entry back on the free -// list. The __stp_tf_vma_mutex must be locked before calling this +// list. The __stp_tf_vma_lock must be write locked before calling this // function. static void __stp_tf_vma_put_free_entry(struct __stp_tf_vma_entry *entry) @@ -101,7 +108,7 @@ __stp_tf_vma_hash(struct task_struct *tsk, unsigned long addr) // Get vma_entry if the vma is present in the vma hash table. -// Returns NULL if not present. +// Returns NULL if not present. Takes a read lock on __stp_tf_vma_lock. static struct __stp_tf_vma_entry * __stp_tf_get_vma_entry(struct task_struct *tsk, unsigned long addr) { @@ -109,20 +116,22 @@ __stp_tf_get_vma_entry(struct task_struct *tsk, unsigned long addr) struct hlist_node *node; struct __stp_tf_vma_entry *entry; - mutex_lock(&__stp_tf_vma_mutex); + unsigned long flags; + read_lock_irqsave(&__stp_tf_vma_lock, flags); head = &__stp_tf_vma_table[__stp_tf_vma_hash(tsk, addr)]; hlist_for_each_entry(entry, node, head, hlist) { if (tsk->pid == entry->pid && addr == entry->addr) { - mutex_unlock(&__stp_tf_vma_mutex); + read_unlock_irqrestore(&__stp_tf_vma_lock, flags); return entry; } } - mutex_unlock(&__stp_tf_vma_mutex); + read_unlock_irqrestore(&__stp_tf_vma_lock, flags); return NULL; } // Add the vma info to the vma hash table. +// Takes a write lock on __stp_tf_vma_lock. static int __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr, struct vm_area_struct *vma) @@ -131,7 +140,8 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr, struct hlist_node *node; struct __stp_tf_vma_entry *entry; - mutex_lock(&__stp_tf_vma_mutex); + unsigned long flags; + write_lock_irqsave(&__stp_tf_vma_lock, flags); head = &__stp_tf_vma_table[__stp_tf_vma_hash(tsk, addr)]; hlist_for_each_entry(entry, node, head, hlist) { if (tsk->pid == entry->pid @@ -141,7 +151,7 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr, "vma (pid: %d, vm_start: 0x%lx) present?\n", tsk->pid, vma->vm_start); #endif - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); return -EBUSY; /* Already there */ } } @@ -149,7 +159,7 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr, // Get an element from the free list. entry = __stp_tf_vma_get_free_entry(); if (!entry) { - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); return -ENOMEM; } entry->pid = tsk->pid; @@ -158,11 +168,12 @@ __stp_tf_add_vma(struct task_struct *tsk, unsigned long addr, entry->vm_end = vma->vm_end; entry->vm_pgoff = vma->vm_pgoff; hlist_add_head(&entry->hlist, head); - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); return 0; } // Remove the vma entry from the vma hash table. +// Takes a write lock on __stp_tf_vma_lock. static int __stp_tf_remove_vma_entry(struct __stp_tf_vma_entry *entry) { @@ -171,10 +182,11 @@ __stp_tf_remove_vma_entry(struct __stp_tf_vma_entry *entry) int found = 0; if (entry != NULL) { - mutex_lock(&__stp_tf_vma_mutex); + unsigned long flags; + write_lock_irqsave(&__stp_tf_vma_lock, flags); hlist_del(&entry->hlist); __stp_tf_vma_put_free_entry(entry); - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); } return 0; } @@ -189,7 +201,7 @@ __stp_tf_vma_map_hash(struct task_struct *tsk) } // Get vma_entry if the vma is present in the vma map hash table. -// Returns NULL if not present. The __stp_tf_vma_mutex must be locked +// Returns NULL if not present. The __stp_tf_vma_lock must be read locked // before calling this function. static struct __stp_tf_vma_entry * __stp_tf_get_vma_map_entry_internal(struct task_struct *tsk, @@ -214,13 +226,16 @@ __stp_tf_get_vma_map_entry_internal(struct task_struct *tsk, static int stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, unsigned long vm_end, unsigned long vm_pgoff, - struct _stp_module *module) + void *user) { struct hlist_head *head; struct hlist_node *node; struct __stp_tf_vma_entry *entry; - mutex_lock(&__stp_tf_vma_mutex); + unsigned long flags; + // Take a write lock, since we are most likely going to write + // after reading. + write_lock_irqsave(&__stp_tf_vma_lock, flags); entry = __stp_tf_get_vma_map_entry_internal(tsk, vm_start); if (entry != NULL) { #if 0 @@ -228,14 +243,14 @@ stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, "vma (pid: %d, vm_start: 0x%lx) present?\n", tsk->pid, entry->vm_start); #endif - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); return -EBUSY; /* Already there */ } // Get an element from the free list. entry = __stp_tf_vma_get_free_entry(); if (!entry) { - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); return -ENOMEM; } @@ -245,11 +260,11 @@ stap_add_vma_map_info(struct task_struct *tsk, unsigned long vm_start, entry->vm_start = vm_start; entry->vm_end = vm_end; entry->vm_pgoff = vm_pgoff; - entry->module = module; + entry->user = user; head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; hlist_add_head(&entry->hlist, head); - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); return 0; } @@ -263,23 +278,26 @@ stap_remove_vma_map_info(struct task_struct *tsk, unsigned long vm_start, struct hlist_node *node; struct __stp_tf_vma_entry *entry; - mutex_lock(&__stp_tf_vma_mutex); + // Take a write lock since we are most likely going to delete + // after reading. + unsigned long flags; + write_lock_irqsave(&__stp_tf_vma_lock, flags); entry = __stp_tf_get_vma_map_entry_internal(tsk, vm_start); if (entry != NULL) { hlist_del(&entry->hlist); __stp_tf_vma_put_free_entry(entry); } - mutex_unlock(&__stp_tf_vma_mutex); + write_unlock_irqrestore(&__stp_tf_vma_lock, flags); return 0; } // Finds vma info if the vma is present in the vma map hash table. -// Returns ESRCH if not present. The __stp_tf_vma_mutex must *not* be +// Returns ESRCH if not present. The __stp_tf_vma_lock must *not* be // locked before calling this function. static int stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, unsigned long *vm_start, unsigned long *vm_end, - unsigned long *vm_pgoff) + unsigned long *vm_pgoff, void **user) { struct hlist_head *head; struct hlist_node *node; @@ -287,7 +305,8 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, struct __stp_tf_vma_entry *found_entry = NULL; int rc = ESRCH; - mutex_lock(&__stp_tf_vma_mutex); + unsigned long flags; + read_lock_irqsave(&__stp_tf_vma_lock, flags); head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; hlist_for_each_entry(entry, node, head, hlist) { if (tsk->pid == entry->pid @@ -304,31 +323,10 @@ stap_find_vma_map_info(struct task_struct *tsk, unsigned long vm_addr, *vm_end = found_entry->vm_end; if (vm_pgoff != NULL) *vm_pgoff = found_entry->vm_pgoff; + if (user != NULL) + *user = found_entry->user; rc = 0; } - mutex_unlock(&__stp_tf_vma_mutex); + read_unlock_irqrestore(&__stp_tf_vma_lock, flags); return rc; } - -// Get vma_entry of the address (vm_start/vm_end) if the vma is -// present in the vma hash table containing. -// Returns NULL if not present. -static struct __stp_tf_vma_entry * -__stp_tf_get_vma_entry_addr(struct task_struct *tsk, unsigned long addr) -{ - struct hlist_head *head; - struct hlist_node *node; - struct __stp_tf_vma_entry *entry; - - mutex_lock(&__stp_tf_vma_mutex); - head = &__stp_tf_vma_map[__stp_tf_vma_map_hash(tsk)]; - hlist_for_each_entry(entry, node, head, hlist) { - if (tsk->pid == entry->pid - && addr >= entry->vm_start && addr < entry->vm_end) { - mutex_unlock(&__stp_tf_vma_mutex); - return entry; - } - } - mutex_unlock(&__stp_tf_vma_mutex); - return NULL; -} diff --git a/tapset/context-symbols.stp b/tapset/context-symbols.stp index a3aae408..4c200aa8 100644 --- a/tapset/context-symbols.stp +++ b/tapset/context-symbols.stp @@ -66,7 +66,7 @@ function probefunc:string () %{ /* pure */ #else ((unsigned long)REG_IP(CONTEXT->regs) >= (unsigned long)PAGE_OFFSET)) { #endif - _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, REG_IP(CONTEXT->regs)); + _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, REG_IP(CONTEXT->regs), current); if (THIS->__retvalue[0] == '.') /* powerpc symbol has a dot*/ strlcpy(THIS->__retvalue,THIS->__retvalue + 1,MAXSTRINGLEN); } else { @@ -94,3 +94,8 @@ function probemod:string () %{ /* pure */ THIS->__retvalue[0] = '\0'; } %} + +function symbolname:string (addr:long) %{ /* pure */ + _stp_symbol_snprint(THIS->__retvalue, MAXSTRINGLEN, THIS->addr, + current); +%} diff --git a/tapset/context-unwind.stp b/tapset/context-unwind.stp index 90d4e0f4..a976f8b6 100644 --- a/tapset/context-unwind.stp +++ b/tapset/context-unwind.stp @@ -56,7 +56,8 @@ function backtrace:string () %{ /* pure */ function caller:string() %{ /* pure */ if (CONTEXT->pi) _stp_symbol_snprint( THIS->__retvalue, MAXSTRINGLEN, - (unsigned long)_stp_ret_addr_r(CONTEXT->pi)); + (unsigned long)_stp_ret_addr_r(CONTEXT->pi), + current); else strlcpy(THIS->__retvalue,"unknown",MAXSTRINGLEN); %} diff --git a/tapset/i686/syscalls.stp b/tapset/i686/syscalls.stp index 8e69f622..2a89c19d 100644 --- a/tapset/i686/syscalls.stp +++ b/tapset/i686/syscalls.stp @@ -119,7 +119,7 @@ probe syscall.set_zone_reclaim.return = # probe syscall.sigaltstack = kernel.function("sys_sigaltstack") { name = "sigaltstack" - ussp = %( kernel_vr < "2.6.25" %? $ebx %: $bx %) + ussp = %( kernel_vr < "2.6.25" %? $ebx %: %( kernel_vr < "2.6.29" %? $bx %: $regs->bx %) %) argstr = sprintf("%p", ussp) } probe syscall.sigaltstack.return = kernel.function("sys_sigaltstack").return { diff --git a/tapsets.cxx b/tapsets.cxx index 50ee563a..1b55684b 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -5812,7 +5812,8 @@ dwarf_builder::build(systemtap_session & sess, && dw->function_name_matches_pattern (probe_name.c_str(), location->components[1]->arg->tok->content.c_str()))) - ; + { + } else continue; const token* sv_tok = location->components[1]->arg->tok; @@ -5833,7 +5834,7 @@ dwarf_builder::build(systemtap_session & sess, return; } - if (probe_type == dwarf_no_probes) + else if (probe_type == dwarf_no_probes) { location->components[1]->functor = TOK_FUNCTION; location->components[1]->arg = new literal_string("*"); @@ -6229,6 +6230,27 @@ module_info::~module_info() delete sym_table; } +// Helper function to emit vma tracker callback _stp_tf_vm_cb. +static void +emit_vma_callback_probe_decl (systemtap_session& s, + string path, + int64_t pid) +{ + s.op->newline() << "{"; + if (pid == 0) + { + s.op->line() << " .pathname=\"" << path << "\","; + s.op->line() << " .pid=0,"; + } + else + { + s.op->line() << " .pathname=NULL,"; + s.op->line() << " .pid=" << pid << ","; + } + s.op->line() << " .callback=NULL,"; + s.op->line() << " .vm_callback=&_stp_tf_vm_cb,"; + s.op->line() << " },"; +} // ------------------------------------------------------------------------ @@ -6432,7 +6454,6 @@ itrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(); s.op->newline() << "/* ---- itrace probes ---- */"; - s.op->newline() << "#include \"task_finder.c\""; s.op->newline() << "struct stap_itrace_probe {"; s.op->indent(1); s.op->newline() << "struct stap_task_finder_target tgt;"; @@ -6474,6 +6495,25 @@ itrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(-1) << "return rc;"; s.op->newline(-1) << "}"; + // Emit vma callbacks. + s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; + s.op->newline() << "static struct stap_task_finder_target stap_itrace_vmcbs[] = {"; + s.op->indent(1); + if (! probes_by_path.empty()) + { + for (p_b_path_iterator it = probes_by_path.begin(); + it != probes_by_path.end(); it++) + emit_vma_callback_probe_decl (s, it->first, (int64_t)0); + } + if (! probes_by_pid.empty()) + { + for (p_b_pid_iterator it = probes_by_pid.begin(); + it != probes_by_pid.end(); it++) + emit_vma_callback_probe_decl (s, "", it->first); + } + s.op->newline(-1) << "};"; + s.op->newline() << "#endif"; + s.op->newline() << "static struct stap_itrace_probe stap_itrace_probes[] = {"; s.op->indent(1); @@ -6515,11 +6555,37 @@ itrace_derived_probe_group::emit_module_init (systemtap_session& s) return; s.op->newline(); + s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; + s.op->newline() << "/* ---- itrace vma callbacks ---- */"; + s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_itrace_vmcbs); i++) {"; + s.op->indent(1); + s.op->newline() << "struct stap_task_finder_target *r = &stap_itrace_vmcbs[i];"; + s.op->newline() << "rc = stap_register_task_finder_target(r);"; + s.op->newline(-1) << "}"; + s.op->newline() << "#endif"; + + s.op->newline(); s.op->newline() << "/* ---- itrace probes ---- */"; s.op->newline() << "for (i=0; i<" << num_probes << "; i++) {"; s.op->indent(1); s.op->newline() << "struct stap_itrace_probe *p = &stap_itrace_probes[i];"; + + // 'arch_has_single_step' needs to be defined for either single step mode + // or branch mode. + s.op->newline() << "if (!arch_has_single_step()) {"; + s.op->indent(1); + s.op->newline() << "_stp_error (\"insn probe init: arch does not support step mode\");"; + s.op->newline() << "rc = -EPERM;"; + s.op->newline() << "break;"; + s.op->newline(-1) << "}"; + s.op->newline() << "if (!p->single_step && !arch_has_block_step()) {"; + s.op->indent(1); + s.op->newline() << "_stp_error (\"insn probe init: arch does not support block step mode\");"; + s.op->newline() << "rc = -EPERM;"; + s.op->newline() << "break;"; + s.op->newline(-1) << "}"; + s.op->newline() << "rc = stap_register_task_finder_target(&p->tgt);"; s.op->newline(-1) << "}"; } @@ -6580,9 +6646,6 @@ private: bool flags_seen[UDPF_NFLAGS]; void emit_probe_decl (systemtap_session& s, utrace_derived_probe *p); - void emit_vm_callback_probe_decl (systemtap_session& s, bool has_path, - string path, int64_t pid, - string vm_callback); public: utrace_derived_probe_group(): num_probes(0), flags_seen() { } @@ -6964,40 +7027,6 @@ utrace_derived_probe_group::emit_probe_decl (systemtap_session& s, void -utrace_derived_probe_group::emit_vm_callback_probe_decl (systemtap_session& s, - bool has_path, - string path, - int64_t pid, - string vm_callback) -{ - s.op->newline() << "{"; - s.op->line() << " .tgt={"; - - if (has_path) - { - s.op->line() << " .pathname=\"" << path << "\","; - s.op->line() << " .pid=0,"; - } - else - { - s.op->line() << " .pathname=NULL,"; - s.op->line() << " .pid=" << pid << ","; - } - - s.op->line() << " .callback=NULL,"; - s.op->line() << " .vm_callback=&" << vm_callback << ","; - s.op->line() << " },"; - s.op->line() << " .pp=\"internal\","; - s.op->line() << " .ph=NULL,"; - s.op->line() << " .flags=(UDPF_NONE),"; - s.op->line() << " .ops={ NULL },"; - s.op->line() << " .events=0,"; - s.op->line() << " .engine_attached=0,"; - s.op->line() << " },"; -} - - -void utrace_derived_probe_group::emit_module_decls (systemtap_session& s) { if (probes_by_path.empty() && probes_by_pid.empty()) @@ -7005,7 +7034,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(); s.op->newline() << "/* ---- utrace probes ---- */"; - s.op->newline() << "#include \"task_finder.c\""; s.op->newline() << "enum utrace_derived_probe_flags {"; s.op->indent(1); @@ -7213,6 +7241,25 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "return rc;"; s.op->newline(-1) << "}"; + // Emit vma callbacks. + s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; + s.op->newline() << "static struct stap_task_finder_target stap_utrace_vmcbs[] = {"; + s.op->indent(1); + if (! probes_by_path.empty()) + { + for (p_b_path_iterator it = probes_by_path.begin(); + it != probes_by_path.end(); it++) + emit_vma_callback_probe_decl (s, it->first, (int64_t)0); + } + if (! probes_by_pid.empty()) + { + for (p_b_pid_iterator it = probes_by_pid.begin(); + it != probes_by_pid.end(); it++) + emit_vma_callback_probe_decl (s, "", it->first); + } + s.op->newline(-1) << "};"; + s.op->newline() << "#endif"; + s.op->newline() << "static struct stap_utrace_probe stap_utrace_probes[] = {"; s.op->indent(1); @@ -7222,12 +7269,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) for (p_b_path_iterator it = probes_by_path.begin(); it != probes_by_path.end(); it++) { - // Emit a "fake" probe decl that is really a hook for to get - // our vm_callback called. - string path = it->first; - emit_vm_callback_probe_decl (s, true, path, (int64_t)0, - "__stp_tf_vm_cb"); - for (unsigned i = 0; i < it->second.size(); i++) { utrace_derived_probe *p = it->second[i]; @@ -7242,11 +7283,6 @@ utrace_derived_probe_group::emit_module_decls (systemtap_session& s) for (p_b_pid_iterator it = probes_by_pid.begin(); it != probes_by_pid.end(); it++) { - // Emit a "fake" probe decl that is really a hook for to get - // our vm_callback called. - emit_vm_callback_probe_decl (s, false, "", it->first, - "__stp_tf_vm_cb"); - for (unsigned i = 0; i < it->second.size(); i++) { utrace_derived_probe *p = it->second[i]; @@ -7265,6 +7301,15 @@ utrace_derived_probe_group::emit_module_init (systemtap_session& s) return; s.op->newline(); + s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; + s.op->newline() << "/* ---- utrace vma callbacks ---- */"; + s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_utrace_vmcbs); i++) {"; + s.op->indent(1); + s.op->newline() << "struct stap_task_finder_target *r = &stap_utrace_vmcbs[i];"; + s.op->newline() << "rc = stap_register_task_finder_target(r);"; + s.op->newline(-1) << "}"; + s.op->newline() << "#endif"; + s.op->newline() << "/* ---- utrace probes ---- */"; s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_utrace_probes); i++) {"; s.op->indent(1); @@ -7494,7 +7539,6 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline() << "#else"; s.op->newline() << "#include \"uprobes/uprobes.h\""; s.op->newline() << "#endif"; - s.op->newline() << "#include \"task_finder.c\""; s.op->newline() << "#ifndef MULTIPLE_UPROBES"; s.op->newline() << "#define MULTIPLE_UPROBES 256"; // maximum possible armed uprobes per process() probe point @@ -7512,6 +7556,21 @@ uprobe_derived_probe_group::emit_module_decls (systemtap_session& s) s.op->newline(-1) << "} stap_uprobes [MAXUPROBES];"; s.op->newline() << "DEFINE_MUTEX(stap_uprobes_lock);"; // protects against concurrent registration/unregistration + // Emit vma callbacks. + s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; + s.op->newline() << "static struct stap_task_finder_target stap_uprobe_vmcbs[] = {"; + s.op->indent(1); + for (unsigned i = 0; i < probes.size(); i++) + { + uprobe_derived_probe* p = probes[i]; + if (p->pid != 0) + emit_vma_callback_probe_decl (s, "", p->pid); + else + emit_vma_callback_probe_decl (s, p->module, (int64_t)0); + } + s.op->newline(-1) << "};"; + s.op->newline() << "#endif"; + s.op->newline() << "static struct stap_uprobe_spec {"; s.op->newline(1) << "struct stap_task_finder_target finder;"; s.op->newline() << "unsigned long address;"; @@ -7712,6 +7771,15 @@ void uprobe_derived_probe_group::emit_module_init (systemtap_session& s) { if (probes.empty()) return; + s.op->newline() << "#ifdef STP_NEED_VMA_TRACKER"; + s.op->newline() << "/* ---- uprobe vma callbacks ---- */"; + s.op->newline() << "for (i=0; i<ARRAY_SIZE(stap_uprobe_vmcbs); i++) {"; + s.op->indent(1); + s.op->newline() << "struct stap_task_finder_target *r = &stap_uprobe_vmcbs[i];"; + s.op->newline() << "rc = stap_register_task_finder_target(r);"; + s.op->newline(-1) << "}"; + s.op->newline() << "#endif"; + s.op->newline() << "/* ---- user probes ---- */"; s.op->newline() << "for (j=0; j<MAXUPROBES; j++) {"; diff --git a/testsuite/buildok/twentysix.stp b/testsuite/buildok/twentysix.stp deleted file mode 100755 index 3fb7526f..00000000 --- a/testsuite/buildok/twentysix.stp +++ /dev/null @@ -1,7 +0,0 @@ -#! stap -up4 - -global a -probe begin -{ - a [1,2,3,4,5,6] = 0 -} diff --git a/testsuite/lib/stap_run.exp b/testsuite/lib/stap_run.exp index a4beaa12..3043eeed 100644 --- a/testsuite/lib/stap_run.exp +++ b/testsuite/lib/stap_run.exp @@ -30,6 +30,7 @@ proc stap_run { TEST_NAME {LOAD_GEN_FUNCTION ""} {OUTPUT_CHECK_STRING ""} args } if [file readable $test_file_name] { lappend cmd $test_file_name } + send_log "executing: $cmd\n" eval spawn $cmd expect { -timeout 180 diff --git a/testsuite/lib/systemtap.exp b/testsuite/lib/systemtap.exp index 554e88ed..5311be7b 100644 --- a/testsuite/lib/systemtap.exp +++ b/testsuite/lib/systemtap.exp @@ -16,6 +16,16 @@ proc use_server_p {} { } +proc utrace_p {} { + set path "/proc/kallsyms" + if {! [catch {exec grep -q utrace_attach $path} dummy]} { + return 1 + } else { + return 0 + } +} + + proc print_systemtap_version {} { set version [exec /bin/uname -r] set location "/boot/vmlinux-$version" diff --git a/testsuite/systemtap.base/bz5274.exp b/testsuite/systemtap.base/bz5274.exp index 92441e9e..2f76a43f 100755 --- a/testsuite/systemtap.base/bz5274.exp +++ b/testsuite/systemtap.base/bz5274.exp @@ -17,14 +17,7 @@ if {! [installtest_p]} { return } -# Try to find utrace_attach symbol in /proc/kallsyms -# copy from utrace_p5.exp -set utrace_support_found 0 -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} -if {$utrace_support_found == 0} { +if {![utrace_p]} { catch {exec rm -f $test} untested "$test -p5" return diff --git a/testsuite/systemtap.base/bz6850.exp b/testsuite/systemtap.base/bz6850.exp index b96ed95c..32ecdaf5 100644 --- a/testsuite/systemtap.base/bz6850.exp +++ b/testsuite/systemtap.base/bz6850.exp @@ -3,14 +3,7 @@ set test bz6850 catch {exec gcc -g -o bz6850 $srcdir/$subdir/bz6850.c} err if {$err == "" && [file exists bz6850]} then { pass "$test compile" } else { fail "$test compile" } -# Try to find utrace_attach symbol in /proc/kallsyms -# copy from utrace_p5.exp -set utrace_support_found 0 -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} -if {$utrace_support_found == 0} { +if {![utrace_p]} { catch {exec rm -f $test} untested "$test -p4" untested "$test -p5" diff --git a/testsuite/systemtap.base/itrace.exp b/testsuite/systemtap.base/itrace.exp index e215bfe7..5da0dfaf 100644 --- a/testsuite/systemtap.base/itrace.exp +++ b/testsuite/systemtap.base/itrace.exp @@ -2,7 +2,6 @@ # Initialize variables -set utrace_support_found 0 set exepath "[pwd]/ls_[pid]" set itrace1_script { @@ -48,6 +47,26 @@ set itrace2_script { } set itrace2_script_output "itraced = 5\r\n" +set itrace3_script { + global branches = 0 + probe begin + { + printf("systemtap starting probe\n") + } + probe process("%s").insn.block + { + branches += 1 + if (branches == 5) + exit() + } + + + probe end { printf("systemtap ending probe\n") + printf("itraced block mode = %%d\n", branches) + } +} +set itrace3_script_output "itraced block mode = 5\r\n" + # Set up our own copy of /bin/ls, to make testing for a particular # executable easy. We can't use 'ln' here, since we might be creating @@ -72,14 +91,8 @@ proc run_ls_5_sec {} { } -# Try to find utrace_attach symbol in /proc/kallsyms -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} - set TEST_NAME "itrace1" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested $TEST_NAME @@ -90,7 +103,7 @@ if {$utrace_support_found == 0} { set TEST_NAME "itrace2" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested $TEST_NAME @@ -99,5 +112,16 @@ if {$utrace_support_found == 0} { stap_run $TEST_NAME run_ls_5_sec $itrace2_script_output -e $script } +set TEST_NAME "itrace3" +if {![utrace_p]} { + untested "$TEST_NAME : no kernel utrace support found" +} elseif {![installtest_p]} { + untested $TEST_NAME +} else { + send_log "ATTENTION: if arch_has_block_step is not defined for this arch, this testcase will fail\n" + set script [format $itrace3_script $exepath] + stap_run $TEST_NAME run_ls_5_sec $itrace3_script_output -e $script +} + # Cleanup exec rm -f $exepath diff --git a/testsuite/systemtap.base/labels.exp b/testsuite/systemtap.base/labels.exp index 6db81c54..2f79a502 100644 --- a/testsuite/systemtap.base/labels.exp +++ b/testsuite/systemtap.base/labels.exp @@ -1,14 +1,6 @@ set test "labels" if {![installtest_p]} {untested $test; return} - -# Try to find utrace_attach symbol in /proc/kallsyms -# copy from utrace_p5.exp -set utrace_support_found 0 -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} -if {$utrace_support_found == 0} { untested "$test"; return } +if {![utrace_p]} { untested $test; return } # Compile a C program to use as the user-space probing target set label_srcpath "[pwd]/labels.c" diff --git a/testsuite/systemtap.base/sdt.exp b/testsuite/systemtap.base/sdt.exp index 46fa5a28..c3aed91e 100644 --- a/testsuite/systemtap.base/sdt.exp +++ b/testsuite/systemtap.base/sdt.exp @@ -36,7 +36,7 @@ if { $res != "" } { pass "compiling $test.c $extra_flag" } -if {[installtest_p]} { +if {[installtest_p] && [utrace_p]} { stap_run3 "$test $extra_flag" $srcdir/$subdir/$test.stp $testprog -c ./$testprog } else { untested "$test $extra_flag" @@ -61,7 +61,7 @@ if { $res != "" } { pass "compiling $test.c c++ $extra_flag" } -if {[installtest_p]} { +if {[installtest_p] && [utrace_p]} { stap_run3 "$test c++ $extra_flag" $srcdir/$subdir/$test.stp $testprog -c ./$testprog } else { untested "$test c++ $extra_flag" diff --git a/testsuite/systemtap.base/static_uprobes.exp b/testsuite/systemtap.base/static_uprobes.exp index 820626b8..07ff83e9 100644 --- a/testsuite/systemtap.base/static_uprobes.exp +++ b/testsuite/systemtap.base/static_uprobes.exp @@ -124,15 +124,7 @@ if { $res != "" } { } if {![installtest_p]} {untested $test; return} - -# Try to find utrace_attach symbol in /proc/kallsyms -# copy from utrace_p5.exp -set utrace_support_found 0 -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$test" catch {exec rm -f $sup_srcpath} return @@ -196,7 +188,7 @@ set ok 0 spawn stap -l "process(\"./sdt_types.x\").mark(\"*\")" expect { -timeout 180 - -re {mark\(\".*\"\)} { incr ok; exp_continue } + -re {mark\(\"[a-z_]+\"\)} { incr ok; exp_continue } timeout { fail "$test C (timeout)" } eof { } } diff --git a/testsuite/systemtap.base/uprobes.exp b/testsuite/systemtap.base/uprobes.exp index 89250e7b..6344cbf0 100644 --- a/testsuite/systemtap.base/uprobes.exp +++ b/testsuite/systemtap.base/uprobes.exp @@ -18,14 +18,7 @@ if [file exists $path] then { pass "$test prep" } else { fail "$test prep" } catch {exec gcc -g -o jennie jennie.c} err if {$err == "" && [file exists jennie]} then { pass "$test compile" } else { fail "$test compile" } -# Try to find utrace_attach symbol in /proc/kallsyms -# copy from utrace_p5.exp -set utrace_support_found 0 -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$test -p4"; untested "$test -p5" catch {exec rm -f jennie.c jennie} return diff --git a/testsuite/systemtap.base/uprobes_lib.exp b/testsuite/systemtap.base/uprobes_lib.exp index ae1b72e8..63ef957a 100644 --- a/testsuite/systemtap.base/uprobes_lib.exp +++ b/testsuite/systemtap.base/uprobes_lib.exp @@ -10,21 +10,23 @@ set testflags "additional_flags=-g additional_flags=-O" set testlibflags "$testflags additional_flags=-fPIC additional_flags=-shared" set maintestflags "$testflags additional_flags=-L$testlibdir additional_flags=-l$testlibname additional_flags=-Wl,-rpath,$testlibdir" -# Only run on make installcheck -if {! [installtest_p]} { untested "$test"; return } - # Compile our test program and library. set res [target_compile $testsrclib $testso executable $testlibflags] if { $res != "" } { verbose "target_compile for $testso failed: $res" 2 - fail "unable to compile $testsrclib" + fail "$test compile $testsrclib" return +} else { + pass "$test compile $testsrclib" } + set res [target_compile $testsrc $testexe executable $maintestflags] if { $res != "" } { verbose "target_compile failed: $res" 2 - fail "unable to compile $testsrc" + fail "$test compile $testsrc" return +} else { + pass "$test compile $testsrc" } # XXX main_func needs another/extra test. Disabled for now. @@ -33,6 +35,9 @@ if { $res != "" } { # lib_func} set ::result_string {lib_func} +# Only run on make installcheck +if {! [installtest_p]} { untested "$test"; return } +if {! [utrace_p]} { untested $test; return } stap_run2 $srcdir/$subdir/$test.stp -c $testexe #exec rm -f $testexe $testso diff --git a/testsuite/systemtap.base/utrace_p4.exp b/testsuite/systemtap.base/utrace_p4.exp index 1467d9c8..8d323a8a 100644 --- a/testsuite/systemtap.base/utrace_p4.exp +++ b/testsuite/systemtap.base/utrace_p4.exp @@ -7,8 +7,6 @@ # utrace doesn't exist in the kernel, marks the tests as 'untested'. # Initialize variables -set utrace_support_found 0 - set begin_script {"probe process(\"/bin/ls\").begin { print(\"ls begin\") }"} set end_script {"probe process(\"/bin/ls\").end { print(\"ls end\") }"} set syscall_script {"probe process(\"/bin/ls\").syscall { printf(\"|%d\", \$syscall) }"} @@ -24,18 +22,12 @@ set pid_syscall_return_script {"probe process(123).syscall.return { printf(\"|%d set pid_thread_begin_script {"probe process(123).thread.begin { print(\"123 thread.begin\") }"} set pid_thread_end_script {"probe process(123).thread.end { print(\"123 thread.end\") }"} -# Try to find utrace_attach symbol in /proc/kallsyms -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} - # # Do some utrace compile tests. # set TEST_NAME "UTRACE_P4_01" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a begin script using a path @@ -43,7 +35,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_01_pid" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a begin script using a pid @@ -51,7 +43,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_02" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a end script using a path @@ -59,7 +51,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_02_pid" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a end script using a pid @@ -67,7 +59,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_03" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a syscall script using a path @@ -75,7 +67,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_03_pid" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a syscall script using a pid @@ -83,7 +75,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_04" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a syscall return script using a path @@ -91,7 +83,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_04_pid" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling a syscall return script using a pid @@ -99,7 +91,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_05" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an thread.begin script using a path @@ -107,7 +99,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_05_pid" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an thread.begin script using a pid @@ -115,7 +107,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_06" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an thread.end script using a path @@ -123,7 +115,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_06_pid" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an thread.end script using a pid @@ -131,7 +123,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P4_07" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } else { # Try compiling an system-wide begin script diff --git a/testsuite/systemtap.base/utrace_p5.exp b/testsuite/systemtap.base/utrace_p5.exp index 33281350..3d432dc3 100644 --- a/testsuite/systemtap.base/utrace_p5.exp +++ b/testsuite/systemtap.base/utrace_p5.exp @@ -1,7 +1,6 @@ # Utrace run (pass 5) tests. # Initialize variables -set utrace_support_found 0 set exepath "[pwd]/cat_[pid]" set multi_srcpath "$srcdir/systemtap.base/utrace_p5_multi.c" set multi_exepath "[pwd]/utrace_p5_multi_[pid]" @@ -90,12 +89,6 @@ set bz6841_script { } set bz6841_script_output ".+ issues syscall \\d+ times\r\n" -# Try to find utrace_attach symbol in /proc/kallsyms -set path "/proc/kallsyms" -if {! [catch {exec grep -q utrace_attach $path} dummy]} { - set utrace_support_found 1 -} - # Set up our own copy of /bin/cat, to make testing for a particular # executable easy. We can't use 'ln' here, since we might be creating # a cross-device link. We can't use 'ln -s' here, since the kernel @@ -138,7 +131,7 @@ proc run_utrace_p5_multi {} { } set TEST_NAME "UTRACE_P5_01" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" @@ -148,7 +141,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P5_02" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" @@ -158,7 +151,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P5_03" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" @@ -168,7 +161,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P5_04" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" @@ -178,7 +171,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P5_05" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" @@ -189,7 +182,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P5_06" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" @@ -200,7 +193,7 @@ if {$utrace_support_found == 0} { } set TEST_NAME "UTRACE_P5_07" -if {$utrace_support_found == 0} { +if {![utrace_p]} { untested "$TEST_NAME : no kernel utrace support found" } elseif {![installtest_p]} { untested "$TEST_NAME" diff --git a/testsuite/systemtap.context/args.tcl b/testsuite/systemtap.context/args.tcl index 7cb79cdf..cffaeaef 100644 --- a/testsuite/systemtap.context/args.tcl +++ b/testsuite/systemtap.context/args.tcl @@ -1,6 +1,6 @@ spawn stap $srcdir/$subdir/args.stp expect { - -timeout 240 + -timeout 60 "READY" { exec echo 1 > /proc/stap_test_cmd expect { diff --git a/testsuite/systemtap.context/backtrace.tcl b/testsuite/systemtap.context/backtrace.tcl index ca60c369..6edda812 100644 --- a/testsuite/systemtap.context/backtrace.tcl +++ b/testsuite/systemtap.context/backtrace.tcl @@ -8,7 +8,7 @@ set m6 0 spawn stap -DMAXSTRINGLEN=256 $srcdir/$subdir/backtrace.stp #exp_internal 1 expect { - -timeout 240 + -timeout 60 "Systemtap probe: begin\r\n" { pass "backtrace of begin probe" exec echo 0 > /proc/stap_test_cmd diff --git a/testsuite/systemtap.context/context.exp b/testsuite/systemtap.context/context.exp index 010db445..cec09b29 100644 --- a/testsuite/systemtap.context/context.exp +++ b/testsuite/systemtap.context/context.exp @@ -80,6 +80,7 @@ if {[build_modules] == 0} { } foreach test $testlist { + send_log "sourcing: $srcdir/$subdir/$test.tcl\n" source $srcdir/$subdir/$test.tcl } diff --git a/testsuite/systemtap.context/num_args.tcl b/testsuite/systemtap.context/num_args.tcl index 7d12b433..62ac8dd3 100644 --- a/testsuite/systemtap.context/num_args.tcl +++ b/testsuite/systemtap.context/num_args.tcl @@ -3,7 +3,7 @@ foreach arglist $arglists { set tag [concat numeric $arglist] eval spawn stap $arglist $srcdir/$subdir/num_args.stp expect { - -timeout 240 + -timeout 60 "READY" { exec echo 1 > /proc/stap_test_cmd expect { diff --git a/testsuite/systemtap.context/pid.tcl b/testsuite/systemtap.context/pid.tcl index a2c091f1..70a87345 100644 --- a/testsuite/systemtap.context/pid.tcl +++ b/testsuite/systemtap.context/pid.tcl @@ -2,7 +2,7 @@ set tests [list execname pexecname pid ppid tid uid euid gid egid] spawn stap $srcdir/$subdir/pid.stp #exp_internal 1 expect { - -timeout 240 + -timeout 60 "READY" { set pid [exec echo 1 > /proc/stap_test_cmd &] set ppid {[0-9]*} diff --git a/testsuite/systemtap.context/usymbols.c b/testsuite/systemtap.context/usymbols.c new file mode 100644 index 00000000..7c590724 --- /dev/null +++ b/testsuite/systemtap.context/usymbols.c @@ -0,0 +1,39 @@ +/* usymbol test case + * Copyright (C) 2008, Red Hat Inc. + * + * This file is part of systemtap, and is free software. You can + * redistribute it and/or modify it under the terms of the GNU General + * Public License (GPL); either version 2, or (at your option) any + * later version. + * + * Uses signal to tranfer user space addresses into the kernel where a + * probe on sigaction will extract them and produce the symbols. To + * poke into the executable we get the sa_handler from the main executable, + * and then the library through calling signal. + * + * FIXME. We call into the library to get the right symbol. If we + * register the handler from the main executable. We need to handle + * @plt symbols (setting a handler in the main executable that is in a + * shared library will have the @plt address, not the address inside + * the shared library). + */ + +#include <signal.h> +typedef void (*sighandler_t)(int); + +// function from our library +int lib_main (void); + +void +main_handler (int signum) +{ + /* dummy handler, just used for the address... */ +} + +int +main (int argc, char *argv[], char *envp[]) +{ + // Use SIGFPE since we never expect that to be triggered. + signal(SIGFPE, main_handler); + lib_main(); +} diff --git a/testsuite/systemtap.context/usymbols.exp b/testsuite/systemtap.context/usymbols.exp new file mode 100644 index 00000000..82f68b67 --- /dev/null +++ b/testsuite/systemtap.context/usymbols.exp @@ -0,0 +1,83 @@ +set test "./usymbols" +set testpath "$srcdir/$subdir" +set testsrc "$testpath/usymbols.c" +set testsrclib "$testpath/usymbols_lib.c" +set testexe "[pwd]/usymbols" +set testlibname "usymbols" +set testlibdir "[pwd]" +set testso "$testlibdir/lib${testlibname}.so" +set testflags "additional_flags=-g additional_flags=-O" +set testlibflags "testflags additional_flags=-fPIC additional_flags=-shared" +set maintestflags "$testflags additional_flags=-L$testlibdir additional_flags=-l$testlibname additional_flags=-Wl,-rpath,$testlibdir" + +# Only run on make installcheck and utrace present. +if {! [installtest_p]} { untested "$test"; return } +if {! [utrace_p]} { untested "$test"; return } + +# Compile our test program and library. +set res [target_compile $testsrclib $testso executable $testlibflags] +if { $res != "" } { + verbose "target_compile for $testso failed: $res" 2 + fail "unable to compile $testsrclib" + return +} +set res [target_compile $testsrc $testexe executable $maintestflags] +if { $res != "" } { + verbose "target_compile failed: $res" 2 + fail "unable to compile $testsrc" + return +} + +# We need the execname() trick to work around (the workaround of) PR6964 +# otherwise we get also the rt_sigactions of stapio. Get the handler +# (comes from the executable or the library). +set testscript { + probe syscall.rt_sigaction { + if (pid() == target() && execname() == "%s") { + handler = $act->sa_handler; + printf("handler: %%s\n", symbolname(handler)); + } + } + /* track through uprobes, so as to make sure we have the symbols */ + probe process("%s").function("*") { printf(""); } +} + +set output {handler: main_handler +handler: lib_handler} + +# Got to run stap with both the exe and the libraries used as -d args. +# XXX Note how we need the fully resolved (absolute) path... +set script [format $testscript usymbols $testexe] +catch {eval exec [concat ldd $testexe | grep $testlibname]} libpath +set libpath [lindex [split $libpath " "] 2] +send_log "libpath: $libpath\n" +if {[string equal "link" [file type $libpath]]} { + set libpath [file join [file dirname $libpath] [file readlink $libpath]] +} +send_log "libpath: $libpath\n" + +# XXX Cheat, explicitly add STP_NEED_VMA_TRACKER +set cmd [concat stap -DSTP_NEED_VMA_TRACKER -d $libpath -d $testexe -c $testexe -e {$script}] +send_log "cmd: $cmd\n" +catch {eval exec $cmd} res +send_log "cmd output: $res\n" + +set n 0 +set m [llength [split $output "\n"]] +set expected [split $output "\n"] +foreach line [split $res "\n"] { + if {![string equal $line [lindex $expected $n]]} { + fail usymbols + send_log "line [expr $n + 1]: expected \"[lindex $expected $n]\", " + send_log "Got \"$line\"\n" + return + } + incr n +} +if { $n != $m } { + fail usymbols + send_log "Got \"$n\" lines, expected \"$m\" lines\n" +} else { + pass usymbols +} +exec rm -f $testexe $testso diff --git a/testsuite/systemtap.context/usymbols_lib.c b/testsuite/systemtap.context/usymbols_lib.c new file mode 100644 index 00000000..faccb39b --- /dev/null +++ b/testsuite/systemtap.context/usymbols_lib.c @@ -0,0 +1,29 @@ +/* usymbol test case - library helper + * Copyright (C) 2008, Red Hat Inc. + * + * This file is part of systemtap, and is free software. You can + * redistribute it and/or modify it under the terms of the GNU General + * Public License (GPL); either version 2, or (at your option) any + * later version. + * + * Uses signal to tranfer user space addresses into the kernel where a + * probe on sigaction will extract them and produce the symbols. To + * poke into the executable we get the sa_handler set through signal + * from this library. + */ + +#include <signal.h> +typedef void (*sighandler_t)(int); + +void +lib_handler (int signum) +{ + /* dummy handler, just used for the address... */ +} + +void +lib_main () +{ + // Use SIGFPE since we never expect that to be triggered. + signal(SIGFPE, lib_handler); +} diff --git a/testsuite/systemtap.pass1-4/buildok.exp b/testsuite/systemtap.pass1-4/buildok.exp index 08d50fb5..12275c1d 100644 --- a/testsuite/systemtap.pass1-4/buildok.exp +++ b/testsuite/systemtap.pass1-4/buildok.exp @@ -6,12 +6,12 @@ foreach file [lsort [glob -nocomplain $srcdir/$self/*.stp]] { # some tests are known to fail. switch $test { buildok/perfmon01.stp {setup_kfail 909 *-*-*} - buildok/twentysix.stp {setup_kfail 4105 *-*-*} buildok/twentyseven.stp {setup_kfail 4166 *-*-*} buildok/sched_test.stp {setup_kfail 1155 *-*-*} buildok/process_test.stp {setup_kfail 1155 *-*-*} buildok/rpc-all-probes.stp {setup_kfail 4413 *-*-*} buildok/nfs-all-probes.stp {setup_kfail 4413 *-*-*} + buildok/per-process-syscall.stp {if {![utrace_p]} { setup_kfail 9999 *-*-*} } } if {$rc == 0} { pass $test } else { fail $test } } diff --git a/testsuite/systemtap.server/server.exp b/testsuite/systemtap.server/server.exp index c2c60b97..d2dd0f16 100644 --- a/testsuite/systemtap.server/server.exp +++ b/testsuite/systemtap.server/server.exp @@ -16,7 +16,6 @@ foreach file [lsort [glob -nocomplain $srcdir/$self/*.stp]] { # some tests are known to fail. switch $test { "buildok/perfmon01.stp with server" {setup_kfail 909 *-*-*} - "buildok/twentysix.stp with server" {setup_kfail 4105 *-*-*} "buildok/twentyseven.stp with server" {setup_kfail 4166 *-*-*} "buildok/sched_test.stp with server" {setup_kfail 1155 *-*-*} "buildok/process_test.stp with server" {setup_kfail 1155 *-*-*} diff --git a/translate.cxx b/translate.cxx index 47fffd1e..9085349e 100644 --- a/translate.cxx +++ b/translate.cxx @@ -4955,6 +4955,8 @@ translate_pass (systemtap_session& s) s.op->newline() << "#define STP_OVERLOAD"; s.op->newline() << "#endif"; + s.op->newline() << "#define STP_SKIP_BADVARS " << (s.skip_badvars ? 1 : 0); + if (s.bulk_mode) s.op->newline() << "#define STP_BULKMODE"; @@ -20,13 +20,15 @@ #include <cerrno> extern "C" { -#include <sys/types.h> -#include <sys/stat.h> +#include <fcntl.h> #include <pwd.h> -#include <unistd.h> +#include <spawn.h> #include <stdio.h> #include <stdlib.h> -#include <fcntl.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/wait.h> +#include <unistd.h> } using namespace std; @@ -294,4 +296,35 @@ git_revision(const string& path) return revision; } + +static pid_t spawned_pid = 0; + +// Runs a command with a saved PID, so we can kill it from the signal handler +int +stap_system(const char *command) +{ + const char * argv[] = { "sh", "-c", command, NULL }; + int ret, status; + + spawned_pid = 0; + ret = posix_spawn(&spawned_pid, "/bin/sh", NULL, NULL, + const_cast<char **>(argv), environ); + if (ret == 0) + { + if (waitpid(spawned_pid, &status, 0) == spawned_pid) + ret = WIFEXITED(status) ? WEXITSTATUS(status) : 128 + WTERMSIG(status); + else + ret = errno; + } + spawned_pid = 0; + return ret; +} + +// Send a signal to our spawned command +int +kill_stap_spawn(int sig) +{ + return spawned_pid ? kill(spawned_pid, sig) : 0; +} + /* vim: set sw=2 ts=8 cino=>4,n-2,{2,^-2,t0,(0,u0,w1,M1 : */ @@ -14,6 +14,8 @@ void tokenize(const std::string& str, std::vector<std::string>& tokens, std::string find_executable(const std::string& name); const std::string cmdstr_quoted(const std::string& cmd); std::string git_revision(const std::string& path); +int stap_system(const char *command); +int kill_stap_spawn(int sig); // stringification generics |