diff --git a/.gitignore b/.gitignore index e7ffaca..24e112d 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/systemtap-3.0.tar.gz +SOURCES/systemtap-3.1.tar.gz diff --git a/.systemtap.metadata b/.systemtap.metadata index 5b324b7..be8f989 100644 --- a/.systemtap.metadata +++ b/.systemtap.metadata @@ -1 +1 @@ -5ef3a2d9945b0f6bae0061e33811e25e5138f5b7 SOURCES/systemtap-3.0.tar.gz +2927ee7e780b45e47d770798f80dfd5be62e095d SOURCES/systemtap-3.1.tar.gz diff --git a/SOURCES/bz1425568.1.patch b/SOURCES/bz1425568.1.patch new file mode 100644 index 0000000..d90332b --- /dev/null +++ b/SOURCES/bz1425568.1.patch @@ -0,0 +1,50 @@ +commit d09defa86b31bd665a3a148ed15713aced8ae227 +Author: David Smith +Date: Thu Mar 9 11:11:49 2017 -0600 + + Add PR19021 test case to task_dentry_path.exp. + +diff --git a/testsuite/systemtap.base/task_dentry_path.exp b/testsuite/systemtap.base/task_dentry_path.exp +index 9bb7b9d..00b9e02 100644 +--- a/testsuite/systemtap.base/task_dentry_path.exp ++++ b/testsuite/systemtap.base/task_dentry_path.exp +@@ -3,7 +3,8 @@ + # unmounted synthentic filesystem, it would go into an infinite loop + # (until killed by MAXACTION). + +-set test "task_dentry_path" ++set test_base "task_dentry_path" ++set test "${test_base}" + + # Only run on make installcheck + if {! [installtest_p]} { untested "$test"; return } +@@ -18,3 +19,17 @@ expect { + } + catch {close}; catch {wait} + if {$ok == 1} { fail "$test ($ok)" } { pass "$test ($ok)" } ++ ++# Test the fix for PR19021 - the tapset function task_dentry_path() ++# should handle more than just files. ++set test "${test_base}2" ++spawn stap $srcdir/$subdir/$test.stp -c "echo hi | cat > /dev/null" ++set ok 0 ++expect { ++ -timeout 150 ++ -re {^pipe:\[[0-9]+\]\r\n} { incr ok; exp_continue } ++ timeout { fail "$test (timeout)" } ++ eof { } ++} ++catch {close}; catch {wait} ++if {$ok == 1} { pass "$test" } { fail "$test ($ok)" } +diff --git a/testsuite/systemtap.base/task_dentry_path2.stp b/testsuite/systemtap.base/task_dentry_path2.stp +new file mode 100644 +index 0000000..3fc9db4 +--- /dev/null ++++ b/testsuite/systemtap.base/task_dentry_path2.stp +@@ -0,0 +1,6 @@ ++probe kernel.function("pipe_read") { ++ t = task_current() ++ println(task_dentry_path(t, $iocb->ki_filp->f_path->dentry, ++ $iocb->ki_filp->f_path->mnt)) ++ exit() ++} diff --git a/SOURCES/bz1425568.2.patch b/SOURCES/bz1425568.2.patch new file mode 100644 index 0000000..c9893b8 --- /dev/null +++ b/SOURCES/bz1425568.2.patch @@ -0,0 +1,175 @@ +commit 6b4d1fcbfa2e9706749cd549ea30df2b67716a0f +Author: David Smith +Date: Fri Mar 10 10:15:48 2017 -0600 + + Fix BZ1425568 by updating task_dentry_path() to handle chroot(). + + * tapset/linux/dentry.stp (task_dentry_path): Fix task_dentry_path when + called on a target executable that has run chroot(). + * testsuite/systemtap.base/task_dentry_path.exp: Add test for chroot'ed + executable. + * testsuite/systemtap.base/task_dentry_path3.stp: New test. + +diff --git a/tapset/linux/dentry.stp b/tapset/linux/dentry.stp +index 589260e..0bc4753 100644 +--- a/tapset/linux/dentry.stp ++++ b/tapset/linux/dentry.stp +@@ -190,6 +190,10 @@ function real_mount:long(vfsmnt:long) + * @dentry: direntry pointer. + * @vfsmnt: vfsmnt pointer. + */ ++/* ++ * Note that this function is based on __d_path() in RHEL6-era kernels ++ * and prepend_path() in RHEL7+ kernels. ++ */ + function task_dentry_path:string(task:long,dentry:long,vfsmnt:long) + { + /* +@@ -207,6 +211,7 @@ function task_dentry_path:string(task:long,dentry:long,vfsmnt:long) + */ + dentry = & @cast(dentry, "dentry") + vfsmnt = & @cast(vfsmnt, "vfsmount") ++ + if (@type_member_defined("dentry", d_op->d_dname) + && dentry->d_op && dentry->d_op->d_dname + && (!__dentry_IS_ROOT(dentry) || dentry != vfsmnt->mnt_root)) { +@@ -242,26 +247,34 @@ function task_dentry_path:string(task:long,dentry:long,vfsmnt:long) + root_vfsmnt = @cast(task, "task_struct")->fs->root->mnt + } + +- while (1) { +- # If we've found the right dentry/vfsmnt, we're done. +- if (dentry == root_dentry && vfsmnt == root_vfsmnt) +- break; ++ if (@type_member_defined("mount", mnt_parent)) { ++ mnt = &@cast(real_mount(vfsmnt), "mount") ++ if (mnt == 0) ++ return "" ++ } + ++ # If we've found the right dentry/vfsmnt, we're done. ++ while (dentry != root_dentry || vfsmnt == root_vfsmnt) { + if (dentry == vfsmnt->mnt_root || __dentry_IS_ROOT(dentry)) { +- if (! @type_member_defined("vfsmount", mnt_parent)) { +- mnt = & @cast(real_mount(vfsmnt), "mount") +- if (mnt == 0) +- return "" ++ /* Escaped? */ ++ if (dentry != vfsmnt->mnt_root) { ++ return "" ++ } + ++ /* RHEL7+ kernels */ ++ if (! @type_member_defined("vfsmount", mnt_parent)) { + /* Global root? */ +- if (mnt->mnt_parent == vfsmnt) +- return sprintf("%s%s", +- d_name(mnt->mnt_mountpoint), +- name) +- +- dentry = mnt->mnt_mountpoint +- vfsmnt = & mnt->mnt_parent->mnt ++ if (mnt != mnt->mnt_parent) { ++ dentry = mnt->mnt_mountpoint ++ vfsmnt = & mnt->mnt_parent->mnt ++ mnt = mnt->mnt_parent ++ if (mnt == 0) ++ return "" ++ continue ++ } ++ break + } ++ /* RHEL6-era kernels */ + else { + /* Global root? */ + if (vfsmnt->mnt_parent == vfsmnt) +@@ -271,11 +284,11 @@ function task_dentry_path:string(task:long,dentry:long,vfsmnt:long) + + dentry = vfsmnt->mnt_mountpoint + vfsmnt = vfsmnt->mnt_parent ++ continue + } +- continue; + } +- name = __dentry_prepend(dentry, name); +- dentry = dentry->d_parent; ++ name = __dentry_prepend(dentry, name) ++ dentry = dentry->d_parent + } + + return sprintf("/%s", name); +diff --git a/testsuite/systemtap.base/task_dentry_path.exp b/testsuite/systemtap.base/task_dentry_path.exp +index 00b9e02..3630401 100644 +--- a/testsuite/systemtap.base/task_dentry_path.exp ++++ b/testsuite/systemtap.base/task_dentry_path.exp +@@ -5,6 +5,8 @@ + + set test_base "task_dentry_path" + set test "${test_base}" ++set test_name "$test_base (infinite loop)" ++set am_root [expr 0 == [exec id -u]] + + # Only run on make installcheck + if {! [installtest_p]} { untested "$test"; return } +@@ -14,22 +16,45 @@ set ok 0 + expect { + -timeout 150 + -re {ERROR.*MAXACTION} { incr ok; exp_continue } +- timeout { fail "$test (timeout)" } ++ timeout { fail "$test_name (timeout)" } + eof { } + } + catch {close}; catch {wait} +-if {$ok == 1} { fail "$test ($ok)" } { pass "$test ($ok)" } ++if {$ok == 1} { fail "$test_name ($ok)" } { pass "$test_name" } + + # Test the fix for PR19021 - the tapset function task_dentry_path() + # should handle more than just files. + set test "${test_base}2" ++set test_name "$test_base (synthetic files)" + spawn stap $srcdir/$subdir/$test.stp -c "echo hi | cat > /dev/null" + set ok 0 + expect { + -timeout 150 + -re {^pipe:\[[0-9]+\]\r\n} { incr ok; exp_continue } +- timeout { fail "$test (timeout)" } ++ timeout { fail "$test_name (timeout)" } + eof { } + } + catch {close}; catch {wait} +-if {$ok == 1} { pass "$test" } { fail "$test ($ok)" } ++if {$ok == 1} { pass "$test_name" } { fail "$test_name ($ok)" } ++ ++# Test the fix for BZ1425568 - systemtap task_dentry_path crashes ++# under chroot. ++set test "${test_base}3" ++set test_name "$test_base (chroot)" ++ ++# We've got to be root to successfully do a 'chroot'. ++if {!$am_root} { ++ untested "$test_name" ++} else { ++ set curdir [pwd] ++ spawn stap $srcdir/$subdir/$test.stp -c "perl -e 'chroot(qw(/tmp))'" ++ set ok 0 ++ expect { ++ -timeout 150 ++ -re "^${curdir}\r\n" { incr ok; exp_continue } ++ timeout { fail "$test_name (timeout)" } ++ eof { } ++ } ++ catch {close}; catch {wait} ++ if {$ok == 1} { pass "$test_name" } { fail "$test_name ($ok)" } ++} +diff --git a/testsuite/systemtap.base/task_dentry_path3.stp b/testsuite/systemtap.base/task_dentry_path3.stp +new file mode 100644 +index 0000000..b04eb6b +--- /dev/null ++++ b/testsuite/systemtap.base/task_dentry_path3.stp +@@ -0,0 +1,6 @@ ++probe kprocess.exit ++{ ++ t = task_current() ++ println(task_dentry_path(t, @cast(t, "task_struct")->fs->pwd->dentry, ++ @cast(t,"task_struct")->fs->pwd->mnt)) ++} diff --git a/SOURCES/bz1428120.patch b/SOURCES/bz1428120.patch new file mode 100644 index 0000000..080e3a0 --- /dev/null +++ b/SOURCES/bz1428120.patch @@ -0,0 +1,26 @@ +commit 237f3f9f43ecf4e8233836f16b0288ec6988414f +Author: David Smith +Date: Thu Mar 2 11:14:47 2017 -0600 + + Update lookup_bad_addr() for platforms where user_addr_max() doesn't exist. + + * runtime/linux/addr-map.c (lookup_bad_addr): Handle platforms (like + s390x) where in_task() exists, but user_addr_max() doesn't. + +diff --git a/runtime/linux/addr-map.c b/runtime/linux/addr-map.c +index b1b9bb0..c868604 100644 +--- a/runtime/linux/addr-map.c ++++ b/runtime/linux/addr-map.c +@@ -53,7 +53,11 @@ lookup_bad_addr(const int type, const unsigned long addr, const size_t size) + #else + if (size == 0 || ULONG_MAX - addr < size - 1 + || (in_task() && !access_ok(type, (void *)addr, size)) +- || (!in_task() && ((user_addr_max() - size) < addr))) ++ || (!in_task() ++#if defined(user_addr_max) ++ && ((user_addr_max() - size) < addr) ++#endif ++ )) + return 1; + #endif + diff --git a/SOURCES/bz1430828.patch b/SOURCES/bz1430828.patch new file mode 100644 index 0000000..b809be5 --- /dev/null +++ b/SOURCES/bz1430828.patch @@ -0,0 +1,268 @@ +commit 4ed3fbc366d168806f94a615f3339b4d2fbd5a75 +Author: David Smith +Date: Wed Mar 22 15:51:56 2017 -0500 + + Fixed BZ1430828 by replacing task_exe_file() with current_exe_file(). + + * tapset/linux/task.stp (current_exe_file): New function. + (task_exe_file): Deprecate and rewrite in terms of + current_exe_file(). This keeps us from potentially accessing task->mm in + an unsafe manner. + * testsuite/buildok/task-embedded.stp: Updated. + * testsuite/systemtap.base/task_paths.exp: Ditto. + * testsuite/systemtap.base/task_paths.stp: Ditto. + * doc/SystemTap_Tapset_Reference/man3/function::task_exe_file.3stap: + Ditto. + * doc/SystemTap_Tapset_Reference/man3/function::current_exe_file.3stap: + New file. + +diff --git a/doc/SystemTap_Tapset_Reference/man3/function::current_exe_file.3stap b/doc/SystemTap_Tapset_Reference/man3/function::current_exe_file.3stap +new file mode 100644 +index 0000000..60ab1fa +--- /dev/null ++++ b/doc/SystemTap_Tapset_Reference/man3/function::current_exe_file.3stap +@@ -0,0 +1,46 @@ ++'\" t ++.\" Title: function::current_exe_file ++.\" Author: ++.\" Generator: DocBook XSL Stylesheets v1.78.1 ++.\" Date: March 2017 ++.\" Manual: Context Functions ++.\" Source: SystemTap Tapset Reference ++.\" Language: English ++.\" ++.TH "FUNCTION::CURRENT_EX" "3stap" "March 2017" "SystemTap Tapset Reference" "Context Functions" ++.\" ----------------------------------------------------------------- ++.\" * Define some portability stuff ++.\" ----------------------------------------------------------------- ++.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++.\" http://bugs.debian.org/507673 ++.\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html ++.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ++.ie \n(.g .ds Aq \(aq ++.el .ds Aq ' ++.\" ----------------------------------------------------------------- ++.\" * set default formatting ++.\" ----------------------------------------------------------------- ++.\" disable hyphenation ++.nh ++.\" disable justification (adjust text to left margin only) ++.ad l ++.\" ----------------------------------------------------------------- ++.\" * MAIN CONTENT STARTS HERE * ++.\" ----------------------------------------------------------------- ++.SH "NAME" ++function::current_exe_file \- get the file struct pointer for the current task\*(Aqs executable file ++.SH "SYNOPSIS" ++.sp ++.nf ++ current_exe_file:long() ++.fi ++.SH "ARGUMENTS" ++.PP ++None ++.SH "DESCRIPTION" ++.PP ++This function returns the file struct pointer for the ++current task\*(Aqs executable file\&. Note that the file struct pointer ++isn\*(Aqt locked on return\&. The return value of this function can be passed to ++.IR function::fullpath_struct_file (3stap) ++to get the path from the file struct\&. +diff --git a/doc/SystemTap_Tapset_Reference/man3/function::task_exe_file.3stap b/doc/SystemTap_Tapset_Reference/man3/function::task_exe_file.3stap +index bcc648b..55fe5d7 100644 +--- a/doc/SystemTap_Tapset_Reference/man3/function::task_exe_file.3stap ++++ b/doc/SystemTap_Tapset_Reference/man3/function::task_exe_file.3stap +@@ -40,3 +40,8 @@ function::task_exe_file \- get the file struct pointer for a task\*(Aqs executab + .RS 4 + task_struct pointer\&. + .RE ++.SH "DESCRIPTION" ++.PP ++This function returns the file struct pointer for a task\*(Aqs executable file\&. Deprecated in SystemTap 3\&.2 and removed in SystemTap 3\&.3\&. ++.SH SEE ALSO\n ++.IR function::current_exe_file (3stap) +diff --git a/tapset/linux/task.stp b/tapset/linux/task.stp +index 12e2868..5467e05 100644 +--- a/tapset/linux/task.stp ++++ b/tapset/linux/task.stp +@@ -781,39 +781,46 @@ function task_cwd_path:long(task:long) + %} + + /** +- * sfunction task_cwd_path - get the file struct pointer for a task's executable file ++ * sfunction current_exe_file - get the file struct pointer for the current task's executable file + * +- * @task: task_struct pointer. ++ * Description: This function returns the file struct pointer for the ++ * current task's executable file. Note that the file struct pointer ++ * isn't locked on return. The return value of this function can be ++ * passed to fullpath_struct_file() to get the path from the file ++ * struct. + */ +-function task_exe_file:long(task:long) ++function current_exe_file:long() + %{ /* pure */ +- struct task_struct *task +- = (struct task_struct *)(unsigned long)STAP_ARG_task; +- struct mm_struct *mm = NULL; + struct file *exe_file = NULL; + +- // Before using the task_struct pointer, make sure it is valid +- // to read. +- (void)kderef_buffer(NULL, task, sizeof(struct task_struct)); +- +- // OK, we now know it is valid to read. But, is it really a +- // task struct? +- if (!_stp_task_struct_valid(task)) { +- STAP_ERROR ("invalid task struct pointer"); ++ if (current == NULL) { ++ STAP_ERROR ("No current task"); + } + +- // We'd like to call get_task_mm()/mmput() here, but they can +- // sleep. So, let's hope incrementing the task's usage (by +- // calling get_task_struct) is enough to keep the mm around. +- get_task_struct(task); +- mm = task->mm; +- if (mm) +- exe_file = stap_find_exe_file(mm); +- put_task_struct(task); +- +- if (exe_file) { +- STAP_RETURN((unsigned long)exe_file); +- fput(exe_file); ++ // Since we're stopped inside current, it isn't going away. So ++ // don't bother incrementing the task's usage count by calling ++ // get_task_struct()/put_task_struct(). We also don't need to ++ // bother to try to lock current->mm. ++ if (current->mm) { ++ exe_file = stap_find_exe_file(current->mm); ++ if (exe_file) { ++ STAP_RETVALUE = (unsigned long)exe_file; ++ fput(exe_file); ++ } + } +- CATCH_DEREF_FAULT(); + %} ++ ++%(systemtap_v <= "3.2" %? ++/** ++ * sfunction task_exe_file - get the file struct pointer for a task's executable file ++ * ++ * @task: task_struct pointer. ++ */ ++function task_exe_file:long(task:long) ++{ ++ if (task == task_current()) { ++ return current_exe_file() ++ } ++ error("Only the exe file for the current task can be returned") ++} ++%) +diff --git a/testsuite/buildok/task-embedded.stp b/testsuite/buildok/task-embedded.stp +index 6b7983f..c3264b5 100755 +--- a/testsuite/buildok/task-embedded.stp ++++ b/testsuite/buildok/task-embedded.stp +@@ -25,7 +25,10 @@ probe begin { + pid2task(0) + + task_fd_lookup(0, 0) + + task_cwd_path(0) + +- task_exe_file(0)) ++%(systemtap_v <= "3.2" %? ++ task_exe_file(0) + ++%) ++ current_exe_file()) + print (task_execname (0)) + print (pid2execname (0)) + } +diff --git a/testsuite/systemtap.base/task_paths.exp b/testsuite/systemtap.base/task_paths.exp +index 0d885ee..a803680 100644 +--- a/testsuite/systemtap.base/task_paths.exp ++++ b/testsuite/systemtap.base/task_paths.exp +@@ -36,7 +36,7 @@ if {$found_cwd == 0 && ![min_kernel_vers_p 2.6.25]} { + setup_kfail NO_CWD *-*-* + } + +-if {$found_cwd == 3 && $found_stapio == 2 && $found_error == 4 ++if {$found_cwd == 2 && $found_stapio == 1 && $found_error == 2 + && $found_whoami == 1} { + pass "$test" + } else { +diff --git a/testsuite/systemtap.base/task_paths.stp b/testsuite/systemtap.base/task_paths.stp +index be088a8..dfefa55 100644 +--- a/testsuite/systemtap.base/task_paths.stp ++++ b/testsuite/systemtap.base/task_paths.stp +@@ -12,29 +12,8 @@ probe begin + } + try + { +- file = task_exe_file(task) +- printf("current exe: %s\n", fullpath_struct_file(task, file)) +- } +- catch (msg) { +- printf("ERROR: %s\n", msg) +- } +- +- # Now print the value of cwd/exe for our target pid. Note that at +- # this point, the target exe path will still be stapio - the exec +- # hasn't happened yet. +- try +- { +- task = pid2task(target()) +- path = task_cwd_path(task) +- printf("target cwd: %s\n", fullpath_struct_path(path)) +- } +- catch (msg) { +- printf("ERROR: %s\n", msg) +- } +- try +- { +- file = task_exe_file(task) +- printf("target exe: %s\n", fullpath_struct_file(task, file)) ++ file = current_exe_file() ++ printf("current exe: %s\n", fullpath_struct_file(task_current(), file)) + } + catch (msg) { + printf("ERROR: %s\n", msg) +@@ -51,15 +30,6 @@ probe begin + catch (msg) { + printf("ERROR: %s\n", msg) + } +- try +- { +- file = task_exe_file(task) +- printf("file: %p\n", file) +- printf("%s\n", fullpath_struct_file(task, file)) +- } +- catch (msg) { +- printf("ERROR: %s\n", msg) +- } + + # Now let's try using a task pointer of -1, which should also + # fail. +@@ -72,14 +42,6 @@ probe begin + catch (msg) { + printf("ERROR: %s\n", msg) + } +- try +- { +- file = task_exe_file(task) +- printf("%s\n", fullpath_struct_file(task, file)) +- } +- catch (msg) { +- printf("ERROR: %s\n", msg) +- } + } + + probe syscall.geteuid, syscall.getuid +@@ -99,8 +61,8 @@ probe syscall.geteuid, syscall.getuid + } + try + { +- file = task_exe_file(task) +- printf("current exe: %s\n", fullpath_struct_file(task, file)) ++ file = current_exe_file() ++ printf("current exe: %s\n", fullpath_struct_file(task_current(), file)) + } + catch (msg) { + printf("ERROR: %s\n", msg) diff --git a/SOURCES/bz1431263.1.patch b/SOURCES/bz1431263.1.patch new file mode 100644 index 0000000..8fc9e60 --- /dev/null +++ b/SOURCES/bz1431263.1.patch @@ -0,0 +1,72 @@ +commit d0b322eddb2f0f248ced58df8e8448c6e557c81e +Author: David Smith +Date: Tue Mar 21 15:49:11 2017 -0500 + + BZ1431263: Fix hardware breakpoint probe handler return types. + + * tapsets.cxx (hwbkpt_derived_probe_group::emit_module_decls): Fix + hardware breakpoint probe handler return type - changed from 'int' to + 'void' to match the kernel. + (hwbkpt_derived_probe_group::emit_module_init): Ditto. + +diff --git a/tapsets.cxx b/tapsets.cxx +index 54793db..32dfde3 100644 +--- a/tapsets.cxx ++++ b/tapsets.cxx +@@ -10191,12 +10191,12 @@ hwbkpt_derived_probe_group::emit_module_decls (systemtap_session& s) + + // Forward declare the master entry functions + s.op->newline() << "#ifdef STAPCONF_PERF_HANDLER_NMI"; +- s.op->newline() << "static int enter_hwbkpt_probe (struct perf_event *bp,"; ++ s.op->newline() << "static void enter_hwbkpt_probe (struct perf_event *bp,"; + s.op->line() << " int nmi,"; + s.op->line() << " struct perf_sample_data *data,"; + s.op->line() << " struct pt_regs *regs);"; + s.op->newline() << "#else"; +- s.op->newline() << "static int enter_hwbkpt_probe (struct perf_event *bp,"; ++ s.op->newline() << "static void enter_hwbkpt_probe (struct perf_event *bp,"; + s.op->line() << " struct perf_sample_data *data,"; + s.op->line() << " struct pt_regs *regs);"; + s.op->newline() << "#endif"; +@@ -10253,17 +10253,17 @@ hwbkpt_derived_probe_group::emit_module_decls (systemtap_session& s) + // Emit the hwbkpt callback function + s.op->newline() ; + s.op->newline() << "#ifdef STAPCONF_PERF_HANDLER_NMI"; +- s.op->newline() << "static int enter_hwbkpt_probe (struct perf_event *bp,"; ++ s.op->newline() << "static void enter_hwbkpt_probe (struct perf_event *bp,"; + s.op->line() << " int nmi,"; + s.op->line() << " struct perf_sample_data *data,"; + s.op->line() << " struct pt_regs *regs) {"; + s.op->newline() << "#else"; +- s.op->newline() << "static int enter_hwbkpt_probe (struct perf_event *bp,"; ++ s.op->newline() << "static void enter_hwbkpt_probe (struct perf_event *bp,"; + s.op->line() << " struct perf_sample_data *data,"; + s.op->line() << " struct pt_regs *regs) {"; + s.op->newline() << "#endif"; + s.op->newline(1) << "unsigned int i;"; +- s.op->newline() << "if (bp->attr.type != PERF_TYPE_BREAKPOINT) return -1;"; ++ s.op->newline() << "if (bp->attr.type != PERF_TYPE_BREAKPOINT) return;"; + s.op->newline() << "for (i=0; i<" << hwbkpt_probes.size() << "; i++) {"; + s.op->newline(1) << "struct perf_event_attr *hp = & stap_hwbkpt_probe_array[i];"; + // XXX: why not match stap_hwbkpt_ret_array[i] against bp instead? +@@ -10281,7 +10281,7 @@ hwbkpt_derived_probe_group::emit_module_decls (systemtap_session& s) + common_probe_entryfn_epilogue (s, true, otf_safe_context(s)); + s.op->newline(-1) << "}"; + s.op->newline(-1) << "}"; +- s.op->newline() << "return 0;"; ++ s.op->newline() << "return;"; + s.op->newline(-1) << "}"; + } + +@@ -10333,9 +10333,9 @@ hwbkpt_derived_probe_group::emit_module_init (systemtap_session& s) + + s.op->newline() << "probe_point = skp->probe->pp;"; // for error messages + s.op->newline() << "#ifdef STAPCONF_HW_BREAKPOINT_CONTEXT"; +- s.op->newline() << "stap_hwbkpt_ret_array[i] = register_wide_hw_breakpoint(hp, (void *)&enter_hwbkpt_probe, NULL);"; ++ s.op->newline() << "stap_hwbkpt_ret_array[i] = register_wide_hw_breakpoint(hp, &enter_hwbkpt_probe, NULL);"; + s.op->newline() << "#else"; +- s.op->newline() << "stap_hwbkpt_ret_array[i] = register_wide_hw_breakpoint(hp, (void *)&enter_hwbkpt_probe);"; ++ s.op->newline() << "stap_hwbkpt_ret_array[i] = register_wide_hw_breakpoint(hp, &enter_hwbkpt_probe);"; + s.op->newline() << "#endif"; + s.op->newline() << "rc = 0;"; + s.op->newline() << "if (IS_ERR(stap_hwbkpt_ret_array[i])) {"; diff --git a/SOURCES/bz1431263.2.patch b/SOURCES/bz1431263.2.patch new file mode 100644 index 0000000..df18980 --- /dev/null +++ b/SOURCES/bz1431263.2.patch @@ -0,0 +1,26 @@ +commit 26f262a7b2712a98d12261b12a5729d9d5e7cb0b +Author: David Smith +Date: Thu Mar 23 16:21:37 2017 -0500 + + BZ1431263: Disable kernel.data probes on arm64. + + * tapsets.cxx (hwbkpt_builder::build): On arm64, hardware breakpoint + probes continually get triggered. So, disable them. + +diff --git a/tapsets.cxx b/tapsets.cxx +index 32dfde3..9be2d04 100644 +--- a/tapsets.cxx ++++ b/tapsets.cxx +@@ -10392,6 +10392,12 @@ hwbkpt_builder::build(systemtap_session & sess, + throw SEMANTIC_ERROR (_("CONFIG_HAVE_HW_BREAKPOINT not available on this kernel"), + location->components[0]->tok); + ++ // See BZ1431263 (on aarch64, running the hw_watch_addr.stp ++ // systemtap examples cause a stuck CPU). ++ if (sess.architecture == string("arm64")) ++ throw SEMANTIC_ERROR (_("kernel.data probes are not supported on arm64 kernels"), ++ location->components[0]->tok); ++ + has_addr = get_param (parameters, TOK_HWBKPT, hwbkpt_address); + has_symbol_str = get_param (parameters, TOK_HWBKPT, symbol_str_val); + has_len = get_param (parameters, TOK_LENGTH, len); diff --git a/SOURCES/bz1431263.3.patch b/SOURCES/bz1431263.3.patch new file mode 100644 index 0000000..90625bf --- /dev/null +++ b/SOURCES/bz1431263.3.patch @@ -0,0 +1,65 @@ +commit 5a540e9f35dd91d26ea342d5b53a1f2d52109f72 +Author: David Smith +Date: Mon Mar 27 10:32:50 2017 -0500 + + BZ1431263: Always use HW_BREAKPOINT_LEN_* macros. + + * tapsets.cxx (hwbkpt_derived_probe_group::emit_module_init): Always use + HW_BREAKPOINT_LEN_* macros, not just on x86_64. + +diff --git a/tapsets.cxx b/tapsets.cxx +index 9be2d04..ccd7cbb 100644 +--- a/tapsets.cxx ++++ b/tapsets.cxx +@@ -10305,31 +10305,26 @@ hwbkpt_derived_probe_group::emit_module_init (systemtap_session& s) + s.op->newline(-1) << "}"; + s.op->newline() << "hp->bp_type = skp->atype;"; + +- // On x86 & x86-64, hp->bp_len is not just a number but a macro/enum (!?!). +- if (s.architecture == "i386" || s.architecture == "x86_64" ) +- { +- s.op->newline() << "switch(skp->len) {"; +- s.op->newline() << "case 1:"; +- s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_1;"; +- s.op->newline() << "break;"; +- s.op->newline(-1) << "case 2:"; +- s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_2;"; +- s.op->newline() << "break;"; +- s.op->newline(-1) << "case 3:"; +- s.op->newline() << "case 4:"; +- s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_4;"; +- s.op->newline() << "break;"; +- s.op->newline(-1) << "case 5:"; +- s.op->newline() << "case 6:"; +- s.op->newline() << "case 7:"; +- s.op->newline() << "case 8:"; +- s.op->newline() << "default:"; // XXX: could instead reject +- s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_8;"; +- s.op->newline() << "break;"; +- s.op->newline(-1) << "}"; +- } +- else // other architectures presumed straightforward +- s.op->newline() << "hp->bp_len = skp->len;"; ++ // Convert actual len to bp len. ++ s.op->newline() << "switch(skp->len) {"; ++ s.op->newline() << "case 1:"; ++ s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_1;"; ++ s.op->newline() << "break;"; ++ s.op->newline(-1) << "case 2:"; ++ s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_2;"; ++ s.op->newline() << "break;"; ++ s.op->newline(-1) << "case 3:"; ++ s.op->newline() << "case 4:"; ++ s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_4;"; ++ s.op->newline() << "break;"; ++ s.op->newline(-1) << "case 5:"; ++ s.op->newline() << "case 6:"; ++ s.op->newline() << "case 7:"; ++ s.op->newline() << "case 8:"; ++ s.op->newline() << "default:"; // XXX: could instead reject ++ s.op->newline(1) << "hp->bp_len = HW_BREAKPOINT_LEN_8;"; ++ s.op->newline() << "break;"; ++ s.op->newline(-1) << "}"; + + s.op->newline() << "probe_point = skp->probe->pp;"; // for error messages + s.op->newline() << "#ifdef STAPCONF_HW_BREAKPOINT_CONTEXT"; diff --git a/SOURCES/bz1431263.4.patch b/SOURCES/bz1431263.4.patch new file mode 100644 index 0000000..504e1e7 --- /dev/null +++ b/SOURCES/bz1431263.4.patch @@ -0,0 +1,31 @@ +commit 77c4dcf7aa81f59532859783e4775143ebf17a23 +Author: David Smith +Date: Mon Mar 27 11:16:53 2017 -0500 + + BZ1431263: Remove "too many hardware breakpoint probes" warning. + + * tapsets.cxx (hwbkpt_derived_probe_group::enroll): Remove warning about + too many hardware breakpoint probes, since we can't really know how many + this system supports until we try to register them. + +diff --git a/tapsets.cxx b/tapsets.cxx +index ccd7cbb..c80e831 100644 +--- a/tapsets.cxx ++++ b/tapsets.cxx +@@ -10166,16 +10166,6 @@ void hwbkpt_derived_probe::join_group (systemtap_session& s) + void hwbkpt_derived_probe_group::enroll (hwbkpt_derived_probe* p, systemtap_session& s) + { + hwbkpt_probes.push_back (p); +- +- unsigned max_hwbkpt_probes_by_arch = 0; +- if (s.architecture == "i386" || s.architecture == "x86_64") +- max_hwbkpt_probes_by_arch = 4; +- else if (s.architecture == "s390") +- max_hwbkpt_probes_by_arch = 1; +- +- if (hwbkpt_probes.size() >= max_hwbkpt_probes_by_arch) +- s.print_warning (_F("Too many hardware breakpoint probes requested for %s (%zu vs. %u)", +- s.architecture.c_str(), hwbkpt_probes.size(), max_hwbkpt_probes_by_arch)); + } + + void diff --git a/SOURCES/bz1431263.5.patch b/SOURCES/bz1431263.5.patch new file mode 100644 index 0000000..bf02b0f --- /dev/null +++ b/SOURCES/bz1431263.5.patch @@ -0,0 +1,21 @@ +commit 5177a6c84d9378d705755844dc5f2b212de49a8c +Author: David Smith +Date: Mon Mar 27 11:36:42 2017 -0500 + + Fix BZ1431263 commit by removing unused arg. + + * tapsets.cxx (enroll): Remove unused systemtap_session argument. + +diff --git a/tapsets.cxx b/tapsets.cxx +index c80e831..2274ae6 100644 +--- a/tapsets.cxx ++++ b/tapsets.cxx +@@ -10163,7 +10163,7 @@ void hwbkpt_derived_probe::join_group (systemtap_session& s) + this->group = s.hwbkpt_derived_probes; + } + +-void hwbkpt_derived_probe_group::enroll (hwbkpt_derived_probe* p, systemtap_session& s) ++void hwbkpt_derived_probe_group::enroll (hwbkpt_derived_probe* p, systemtap_session&) + { + hwbkpt_probes.push_back (p); + } diff --git a/SOURCES/bz1433391.patch b/SOURCES/bz1433391.patch new file mode 100644 index 0000000..0a93018 --- /dev/null +++ b/SOURCES/bz1433391.patch @@ -0,0 +1,58 @@ +commit 9989c537437c3cfffae61e33bbe4fe60ac1c7eed +Author: David Smith +Date: Tue Mar 28 16:36:30 2017 -0500 + + Workaround parser issue in nfs_proc.stp. + + * tapset/linux/nfs_proc.stp (nfs.proc3.read_done): To avoid parser issues, + split up @choose_defined() code into two separate if statements. Note + that this is a workaround until we can fix the parser issue. + (nfs.proc4.read_done): Ditto. + +diff --git a/tapset/linux/nfs_proc.stp b/tapset/linux/nfs_proc.stp +index 2c0bd8d..140e643 100644 +--- a/tapset/linux/nfs_proc.stp ++++ b/tapset/linux/nfs_proc.stp +@@ -889,10 +889,15 @@ probe nfs.proc3.read_done = kernel.function("nfs3_read_done") !, + module("nfs").function("nfs3_read_done") ?, + module("nfsv3").function("nfs3_read_done") ? + { +- if (@defined($hdr) || @defined($data)) { # kernels >= 2.6.10 +- server_ip = @_nfs_data_server_ip(@choose_defined($hdr, $data)) +- prot = @_nfs_data_prot(@choose_defined($hdr, $data)) +- count = @_nfs_data_res_count(@choose_defined($hdr, $data)) ++ if (@defined($hdr)) { # kernels >= 3.17 ++ server_ip = @_nfs_data_server_ip($hdr) ++ prot = @_nfs_data_prot($hdr) ++ count = @_nfs_data_res_count($hdr) ++ } ++ else if (@defined($data)) { # kernels >= 2.6.10 ++ server_ip = @_nfs_data_server_ip($data) ++ prot = @_nfs_data_prot($data) ++ count = @_nfs_data_res_count($data) + } + else { + server_ip = @_nfs_data_server_ip($task->tk_calldata) +@@ -923,11 +928,17 @@ probe nfs.proc4.read_done = kernel.function("nfs4_read_done") !, + module("nfs").function("nfs4_read_done") ?, + module("nfsv4").function("nfs4_read_done") ? + { +- if (@defined($hdr) || @defined($data)) { # kernels >= 2.6.10 +- server_ip = @_nfs_data_server_ip(@choose_defined($hdr, $data)) +- prot = @_nfs_data_prot(@choose_defined($hdr, $data)) +- count = @_nfs_data_res_count(@choose_defined($hdr, $data)) +- timestamp = @_nfs_data_timestamp(@choose_defined($hdr, $data)) ++ if (@defined($hdr)) { # kernels >= 3.17 ++ server_ip = @_nfs_data_server_ip($hdr) ++ prot = @_nfs_data_prot($hdr) ++ count = @_nfs_data_res_count($hdr) ++ timestamp = @_nfs_data_timestamp($hdr) ++ } ++ else if (@defined($data)) { # kernels >= 2.6.10 ++ server_ip = @_nfs_data_server_ip($data) ++ prot = @_nfs_data_prot($data) ++ count = @_nfs_data_res_count($data) ++ timestamp = @_nfs_data_timestamp($data) + } + else { + server_ip = @_nfs_data_server_ip($task->tk_calldata) diff --git a/SOURCES/bz1436845.patch b/SOURCES/bz1436845.patch new file mode 100644 index 0000000..2c2f5f2 --- /dev/null +++ b/SOURCES/bz1436845.patch @@ -0,0 +1,95 @@ +commit 438b5a402b6a93dd426f8c18de6fe3708c265328 +Author: Stan Cox +Date: Tue Mar 28 14:39:14 2017 -0400 + + Adapt stapdyn to the dyninst 9.3.1 library search model. + + stapdyn/dynutil.cxx (check_dyninst_rt): Use DYNINST_REWRITER_PATHS + and appendenv + + util.c, util.h: New: appendenv. + +diff --git a/stapdyn/dynutil.cxx b/stapdyn/dynutil.cxx +index cd2ae11..47a1e91 100644 +--- a/stapdyn/dynutil.cxx ++++ b/stapdyn/dynutil.cxx +@@ -61,17 +61,28 @@ guess_dyninst_rt(void) + return libdyninstAPI_RT; + } + ++ + // Check that environment DYNINSTAPI_RT_LIB exists and is a valid file. + // If not, try to guess a good value and set it. + bool + check_dyninst_rt(void) + { + static const char rt_env_name[] = "DYNINSTAPI_RT_LIB"; +- const char* rt_env = getenv(rt_env_name); ++ static const char dyn_rw_env_name[] = "DYNINST_REWRITER_PATHS"; ++ ++ char* rt_env = getenv(rt_env_name); + if (rt_env) + { + if (file_exists(rt_env)) +- return true; ++ { ++ if (appendenv(dyn_rw_env_name, rt_env) != 0) ++ { ++ int olderrno = errno; ++ staperror() << "Can't set " << dyn_rw_env_name << ": " << strerror(olderrno); ++ return false; ++ } ++ return true; ++ } + staperror() << "Invalid " << rt_env_name << ": \"" << rt_env << "\"" << endl; + } + +@@ -82,7 +93,7 @@ check_dyninst_rt(void) + return false; + } + +- if (setenv(rt_env_name, rt.c_str(), 1) != 0) ++ if (appendenv(dyn_rw_env_name, rt) != 0) + { + int olderrno = errno; + staperror() << "Can't set " << rt_env_name << ": " << strerror(olderrno); +diff --git a/util.cxx b/util.cxx +index a1c8363..9157fb9 100644 +--- a/util.cxx ++++ b/util.cxx +@@ -228,6 +228,23 @@ remove_file_or_dir (const char *name) + return 0; + } + ++ ++int ++appendenv (const char *env_name, const string source) ++{ ++ string dirname = source.substr(0, source.rfind("/")); ++ char *env = getenv(env_name); ++ string new_env; ++ ++ if (env) ++ new_env = string (env) + ":" + dirname; ++ else ++ new_env = dirname; ++ ++ return setenv(env_name, new_env.c_str(), 1); ++} ++ ++ + /* Obtain the gid of the given group. */ + gid_t get_gid (const char *group_name) + { +diff --git a/util.h b/util.h +index d7e0cfb..482f719 100644 +--- a/util.h ++++ b/util.h +@@ -77,6 +77,7 @@ bool copy_file(const std::string& src, const std::string& dest, + int create_dir(const char *dir, int mode = 0777); + int remove_file_or_dir(const char *dir); + extern "C" gid_t get_gid (const char *group_name); ++int appendenv (const char *env_name, const std::string source); + bool in_group_id (gid_t target_gid); + std::string getmemusage (); + void tokenize(const std::string& str, std::vector& tokens, diff --git a/SOURCES/rhbz1242368.patch b/SOURCES/rhbz1242368.patch deleted file mode 100644 index 2ec1be8..0000000 --- a/SOURCES/rhbz1242368.patch +++ /dev/null @@ -1,338 +0,0 @@ -commit 03b9fdf4ce26b4e39a3e755fc717fe4e5ab773dd -Author: David Smith -Date: Thu Apr 28 10:20:47 2016 -0500 - - Fix PR19954 by avoiding "suspicious RCU usage" message. - - * runtime/transport/symbols.c (_stp_module_update_self): Properly handle - RCU locking when retrieving the 'kallsyms' member of the module - structure. - -diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c -index cb7964f..98b0239 100644 ---- a/runtime/transport/symbols.c -+++ b/runtime/transport/symbols.c -@@ -249,7 +249,12 @@ static int _stp_module_update_self (void) - } - else if (!strcmp(".symtab", attr->name)) { - #ifdef STAPCONF_MOD_KALLSYMS -- struct mod_kallsyms *kallsyms = rcu_dereference_sched(mod->kallsyms); -+ struct mod_kallsyms *kallsyms; -+ -+ rcu_read_lock_sched(); -+ kallsyms = rcu_dereference_sched(mod->kallsyms); -+ rcu_read_unlock_sched(); -+ - if (attr->address == (unsigned long) kallsyms->symtab) - _stp_module_self.sections[0].size = - kallsyms->num_symtab * sizeof(kallsyms->symtab[0]); -commit c8db32343c9b8012fa348cf4f8f104617960f793 -Author: David Smith -Date: Thu Apr 28 10:59:50 2016 -0500 - - Improved fake utrace locking. - - * runtime/stp_utrace.c: Fixed potential locking issues by changing the - 'task_work_added' and 'report_work_added' members of 'struct - utrace' to be atomic variables. In the process, I also renamed - 'task_work_added' to 'resume_work_added'. As atomice variables, they can - be modified without locking the utrace struct. Also renamed the 'work' - member of 'struct utrace' to 'resume_work' (to match up with - 'resume_work_added'). - -diff --git a/runtime/stp_utrace.c b/runtime/stp_utrace.c -index a8afc0d..bb2d663 100644 ---- a/runtime/stp_utrace.c -+++ b/runtime/stp_utrace.c -@@ -66,17 +66,23 @@ struct utrace { - unsigned int vfork_stop:1; /* need utrace_stop() before vfork wait */ - unsigned int death:1; /* in utrace_report_death() now */ - unsigned int reap:1; /* release_task() has run */ -- unsigned int pending_attach:1; /* need splice_attaching() */ -- unsigned int task_work_added:1; /* called task_work_add() on 'work' */ -- unsigned int report_work_added:1; /* called task_work_add() -- * on 'report_work' */ -+ unsigned int pending_attach:1; /* need splice_attaching() */ -+ -+ /* We need the '*_work_added' variables to be atomic so they -+ * can be modified without locking the utrace struct. This is -+ * typically done in atomic context where we can't grab the -+ * lock. */ -+ atomic_t resume_work_added; /* called task_work_add() on -+ * 'resume_work' */ -+ atomic_t report_work_added; /* called task_work_add() on -+ * 'report_work' */ - - unsigned long utrace_flags; - - struct hlist_node hlist; /* task_utrace_table linkage */ - struct task_struct *task; - -- struct task_work work; -+ struct task_work resume_work; - struct task_work report_work; - }; - -@@ -349,17 +355,20 @@ static int utrace_exit(void) - static void - stp_task_notify_resume(struct task_struct *target, struct utrace *utrace) - { -- if (! utrace->task_work_added) { -- int rc = stp_task_work_add(target, &utrace->work); -- if (rc == 0) { -- utrace->task_work_added = 1; -- } -- /* stp_task_work_add() returns -ESRCH if the task has -- * already passed exit_task_work(). Just ignore this -- * error. */ -- else if (rc != -ESRCH) { -- printk(KERN_ERR "%s:%d - task_work_add() returned %d\n", -- __FUNCTION__, __LINE__, rc); -+ if (atomic_add_unless(&utrace->resume_work_added, 1, 1)) { -+ int rc = stp_task_work_add(target, &utrace->resume_work); -+ if (rc != 0) { -+ atomic_set(&utrace->report_work_added, 0); -+ -+ /* stp_task_work_add() returns -ESRCH if the -+ * task has already passed -+ * exit_task_work(). Just ignore this -+ * error. */ -+ if (rc != -ESRCH) { -+ printk(KERN_ERR -+ "%s:%d - task_work_add() returned %d\n", -+ __FUNCTION__, __LINE__, rc); -+ } - } - } - } -@@ -394,8 +403,9 @@ static void utrace_cleanup(struct utrace *utrace) - list_del(&engine->entry); - kmem_cache_free(utrace_engine_cachep, engine); - } -+ stp_spin_unlock(&utrace->lock); - -- if (utrace->task_work_added) { -+ if (atomic_add_unless(&utrace->resume_work_added, -1, 0)) { - #ifdef STP_TF_DEBUG - if (stp_task_work_cancel(utrace->task, &utrace_resume) == NULL) - printk(KERN_ERR "%s:%d - task_work_cancel() failed? task %p, %d, %s\n", -@@ -406,9 +416,8 @@ static void utrace_cleanup(struct utrace *utrace) - #else - stp_task_work_cancel(utrace->task, &utrace_resume); - #endif -- utrace->task_work_added = 0; - } -- if (utrace->report_work_added) { -+ if (atomic_add_unless(&utrace->report_work_added, -1, 0)) { - #ifdef STP_TF_DEBUG - if (stp_task_work_cancel(utrace->task, &utrace_report_work) == NULL) - printk(KERN_ERR "%s:%d - task_work_cancel() failed? task %p, %d, %s\n", -@@ -419,9 +428,7 @@ static void utrace_cleanup(struct utrace *utrace) - #else - stp_task_work_cancel(utrace->task, &utrace_report_work); - #endif -- utrace->report_work_added = 0; - } -- stp_spin_unlock(&utrace->lock); - - /* Free the struct utrace itself. */ - kmem_cache_free(utrace_cachep, utrace); -@@ -522,8 +529,10 @@ static bool utrace_task_alloc(struct task_struct *task) - INIT_LIST_HEAD(&utrace->attaching); - utrace->resume = UTRACE_RESUME; - utrace->task = task; -- stp_init_task_work(&utrace->work, &utrace_resume); -+ stp_init_task_work(&utrace->resume_work, &utrace_resume); - stp_init_task_work(&utrace->report_work, &utrace_report_work); -+ atomic_set(&utrace->resume_work_added, 0); -+ atomic_set(&utrace->report_work_added, 0); - - stp_spin_lock(&task_utrace_lock); - u = __task_utrace_struct(task); -@@ -558,8 +567,8 @@ static void utrace_free(struct utrace *utrace) - stp_spin_unlock(&task_utrace_lock); - - /* Free the utrace struct. */ -- stp_spin_lock(&utrace->lock); - #ifdef STP_TF_DEBUG -+ stp_spin_lock(&utrace->lock); - if (unlikely(utrace->reporting) - || unlikely(!list_empty(&utrace->attached)) - || unlikely(!list_empty(&utrace->attaching))) -@@ -567,27 +576,31 @@ static void utrace_free(struct utrace *utrace) - __FUNCTION__, __LINE__, utrace->reporting, - list_empty(&utrace->attached), - list_empty(&utrace->attaching)); -+ stp_spin_unlock(&utrace->lock); - #endif - -- if (utrace->task_work_added) { -- if (stp_task_work_cancel(utrace->task, &utrace_resume) == NULL) -- printk(KERN_ERR "%s:%d - task_work_cancel() failed? task %p, %d, %s\n", -+ if (atomic_add_unless(&utrace->resume_work_added, -1, 0)) { -+ if ((stp_task_work_cancel(utrace->task, &utrace_resume) -+ == NULL) -+ && (utrace->task->flags & ~PF_EXITING) -+ && (utrace->task->exit_state == 0)) -+ printk(KERN_ERR "%s:%d * task_work_cancel() failed? task %p, %d, %s, 0x%lx 0x%x\n", - __FUNCTION__, __LINE__, utrace->task, - utrace->task->tgid, - (utrace->task->comm ? utrace->task->comm -- : "UNKNOWN")); -- utrace->task_work_added = 0; -- } -- if (utrace->report_work_added) { -- if (stp_task_work_cancel(utrace->task, &utrace_report_work) == NULL) -- printk(KERN_ERR "%s:%d - task_work_cancel() failed? task %p, %d, %s\n", -+ : "UNKNOWN"), utrace->task->state, utrace->task->exit_state); -+ } -+ if (atomic_add_unless(&utrace->report_work_added, -1, 0)) { -+ if ((stp_task_work_cancel(utrace->task, &utrace_report_work) -+ == NULL) -+ && (utrace->task->flags & ~PF_EXITING) -+ && (utrace->task->exit_state == 0)) -+ printk(KERN_ERR "%s:%d ** task_work_cancel() failed? task %p, %d, %s, 0x%lx, 0x%x\n", - __FUNCTION__, __LINE__, utrace->task, - utrace->task->tgid, - (utrace->task->comm ? utrace->task->comm -- : "UNKNOWN")); -- utrace->report_work_added = 0; -+ : "UNKNOWN"), utrace->task->state, utrace->task->exit_state); - } -- stp_spin_unlock(&utrace->lock); - - kmem_cache_free(utrace_cachep, utrace); - } -@@ -2257,7 +2270,7 @@ static void utrace_report_death(void *cb_data __attribute__ ((unused)), - * of detach bookkeeping. - */ - if (in_atomic() || irqs_disabled()) { -- if (! utrace->report_work_added) { -+ if (atomic_add_unless(&utrace->report_work_added, 1, 1)) { - int rc; - #ifdef STP_TF_DEBUG - printk(KERN_ERR "%s:%d - adding task_work\n", -@@ -2265,17 +2278,17 @@ static void utrace_report_death(void *cb_data __attribute__ ((unused)), - #endif - rc = stp_task_work_add(task, - &utrace->report_work); -- if (rc == 0) { -- utrace->report_work_added = 1; -- } -- /* stp_task_work_add() returns -ESRCH if the -- * task has already passed -- * exit_task_work(). Just ignore this -- * error. */ -- else if (rc != -ESRCH) { -- printk(KERN_ERR -- "%s:%d - task_work_add() returned %d\n", -- __FUNCTION__, __LINE__, rc); -+ if (rc != 0) { -+ atomic_set(&utrace->report_work_added, 0); -+ /* stp_task_work_add() returns -ESRCH -+ * if the task has already passed -+ * exit_task_work(). Just ignore this -+ * error. */ -+ if (rc != -ESRCH) { -+ printk(KERN_ERR -+ "%s:%d - task_work_add() returned %d\n", -+ __FUNCTION__, __LINE__, rc); -+ } - } - } - } -@@ -2337,13 +2350,13 @@ static void utrace_resume(struct task_work *work) - * instantaneous (where 'task_utrace_struct()' has to do a - * hash lookup). - */ -- struct utrace *utrace = container_of(work, struct utrace, work); -+ struct utrace *utrace = container_of(work, struct utrace, resume_work); - struct task_struct *task = current; - INIT_REPORT(report); - struct utrace_engine *engine; - - might_sleep(); -- utrace->task_work_added = 0; -+ atomic_set(&utrace->resume_work_added, 0); - - /* Make sure the task isn't exiting. */ - if (task->flags & PF_EXITING) { -@@ -2436,8 +2449,8 @@ static void utrace_report_work(struct task_work *work) - __FUNCTION__, __LINE__, in_atomic(), irqs_disabled()); - #endif - might_sleep(); -- utrace->report_work_added = 0; - -+ atomic_set(&utrace->report_work_added, 0); - stp_spin_lock(&utrace->lock); - BUG_ON(utrace->death); - utrace->death = 1; -commit 0859b50e3ac4782e53c4c10b82c6e24174378bd4 -Author: Mateusz Guzik -Date: Mon May 2 12:28:55 2016 -0500 - - Plug preempt leak in _stp_runtime_entryfn_put/get_context. - - If _stp_runtime_entryfn_get_context returns a context, preemption - counter is always incremented. On the other hand - _stp_runtime_entryfn_put_context only decrements the counter if the - passed context matches the one currently set on the cpu. - - The context can be set to NULL by _stp_runtime_contexts_free, making the - comparison false and in effect leading to a leak, e.g.: - timer: _stp_ctl_work_callback+0x0/0x1e0[stap_af8544c7eb51251ef8c - 377abff659b05_25070] preempt leak: 00000101 -> 00000102 - -diff --git a/runtime/linux/runtime_context.h b/runtime/linux/runtime_context.h -index c9ffe18..9d325da 100644 ---- a/runtime/linux/runtime_context.h -+++ b/runtime/linux/runtime_context.h -@@ -80,11 +80,12 @@ static struct context * _stp_runtime_entryfn_get_context(void) - - static inline void _stp_runtime_entryfn_put_context(struct context *c) - { -- if (c && c == _stp_runtime_get_context()) { -- atomic_dec(&c->busy); -+ if (c) { -+ if (c == _stp_runtime_get_context()) -+ atomic_dec(&c->busy); -+ /* else, warn about bad state? */ - preempt_enable_no_resched(); - } -- /* else, warn about bad state? */ - return; - } - -commit 0beafcec9a2971d466419d430d13fdb2c4f50d94 -Author: David Smith -Date: Tue May 3 13:23:58 2016 -0500 - - Fix PR20040 by keeping the task_exe_file function from sleeping. - - * tapset/linux/task.stp: No longer call get_task_mm()/mmput(), so that the - function won't sleep and cause kernel bugs. - -diff --git a/tapset/linux/task.stp b/tapset/linux/task.stp -index 9b204f5..774cf58 100644 ---- a/tapset/linux/task.stp -+++ b/tapset/linux/task.stp -@@ -795,13 +795,14 @@ function task_exe_file:long(task:long) - STAP_ERROR ("invalid task struct pointer"); - } - -+ // We'd like to call get_task_mm()/mmput() here, but they can -+ // sleep. So, let's hope incrementing the task's usage (by -+ // calling get_task_struct) is enough to keep the mm around. - get_task_struct(task); -- mm = get_task_mm(task); -- put_task_struct(task); -- if (mm) { -+ mm = task->mm; -+ if (mm) - exe_file = stap_find_exe_file(mm); -- mmput(mm); -- } -+ put_task_struct(task); - - if (exe_file) { - STAP_RETURN((unsigned long)exe_file); diff --git a/SOURCES/rhbz1269062.patch b/SOURCES/rhbz1269062.patch deleted file mode 100644 index 40fc02a..0000000 --- a/SOURCES/rhbz1269062.patch +++ /dev/null @@ -1,22 +0,0 @@ -commit a32189c495cf4dbb71fa497adcaa2ab31aad7021 -Author: Martin Cermak -Date: Wed Jun 29 19:03:11 2016 +0200 - - Avoid null pointer exception in the ioscheduler.elv_add_request probe. - - This update makes the ioscheduler.elv_add_request probe gracefully handle - situation where $q->elevator is NULL (RHBZ1269062). - -diff --git a/tapset/linux/ioscheduler.stp b/tapset/linux/ioscheduler.stp -index 00d75a5..121fde8 100644 ---- a/tapset/linux/ioscheduler.stp -+++ b/tapset/linux/ioscheduler.stp -@@ -149,7 +149,7 @@ probe ioscheduler.elv_add_request.tp = kernel.trace("block_rq_insert") ? - { - name = "elv_add_request" - q = $q -- elevator_name = kernel_string( -+ elevator_name = ($q->elevator == 0) ? "" : kernel_string( - @choose_defined($q->elevator->type->elevator_name, - @choose_defined($q->elevator->elevator_type->elevator_name, - $q->elevator->elevator_name)), "") diff --git a/SOURCES/rhbz1312169.patch b/SOURCES/rhbz1312169.patch deleted file mode 100644 index e758265..0000000 --- a/SOURCES/rhbz1312169.patch +++ /dev/null @@ -1,33 +0,0 @@ -commit 63a758b4890e729195fde868e34d0015cda8b065 -Author: Frank Ch. Eigler -Date: Thu Aug 11 13:40:55 2016 -0400 - - RHBZ1312169: make stap-prep fall back to debuginfo-install - - On some fedora / rhel boxes and their repo selections, - "debuginfo-install" can sometimes fetch the right files - even if "yum install" cannot. - -diff --git a/stap-prep b/stap-prep -index 5c233bf..ca9adff 100755 ---- a/stap-prep -+++ b/stap-prep -@@ -26,13 +26,17 @@ KERN_ARCH=`uname -m` - KERN_REV=`echo $UNAME | sed s/.$KERN_ARCH//` # strip arch from uname - CANDIDATES="$KERNEL-$KERN_REV.$KERN_ARCH \ - $KERNEL-devel-$KERN_REV.$KERN_ARCH \ -+ yum-utils \ - $KERNEL-debuginfo-$KERN_REV.$KERN_ARCH" - NEEDED=`rpm --qf "%{name}-%{version}-%{release}.%{arch}\n" \ - -q $CANDIDATES | grep "is not installed" | awk '{print $2}'` - if [ "$NEEDED" != "" ]; then - echo -e "Need to install the following packages:\n$NEEDED" - if [ `id -u` = "0" ]; then #attempt to install -- yum install -y --enablerepo=\* $NEEDED -+ yum install -y --enablerepo=\* $NEEDED || -+ (if expr "$NEEDED" : ".*debuginfo.*" >/dev/null; -+ then debuginfo-install -y $KERNEL-$KERN_REV.$KERN_ARCH; -+ fi) - rpm -q $NEEDED - check_error $? "problem installing rpm(s) $NEEDED" - fi diff --git a/SOURCES/rhbz1337416.patch b/SOURCES/rhbz1337416.patch deleted file mode 100644 index f278c90..0000000 --- a/SOURCES/rhbz1337416.patch +++ /dev/null @@ -1,578 +0,0 @@ -commit 056cb27baac1ce3ab4d675dbbe4881afde801ca3 -Author: Frank Ch. Eigler -Date: Wed Jun 22 11:43:33 2016 -0400 - - PR18079: support nested autocast / @defined - - We now perform const-folding & dead-code-elision during the type - resolution loop, whenever an autocast expression gets evaluated. This - way, @defined(foo()->mm) type expressions can work as nature intended. - - This requires @defined() not to be short-circuit evaluated to 0 during - a random const_folding process, so a flag is introduced to control its - preservation or collapsing. For the last (assert_resolvability) pass - in the type resolution loop, this flag is set to true, so that - genuinely unresolvable @defined($expressions) do get mapped to 0 in - time for a last elision. - -diff --git a/elaborate.cxx b/elaborate.cxx -index 4a375d9..a1088a1 100644 ---- a/elaborate.cxx -+++ b/elaborate.cxx -@@ -3984,9 +3984,10 @@ struct const_folder: public update_visitor - { - systemtap_session& session; - bool& relaxed_p; -- -- const_folder(systemtap_session& s, bool& r): -- session(s), relaxed_p(r), last_number(0), last_string(0) {} -+ bool collapse_defines_p; -+ -+ const_folder(systemtap_session& s, bool& r, bool collapse_defines = false): -+ session(s), relaxed_p(r), collapse_defines_p(collapse_defines), last_number(0), last_string(0) {} - - literal_number* last_number; - literal_number* get_number(expression*& e); -@@ -4506,15 +4507,26 @@ const_folder::visit_ternary_expression (ternary_expression* e) - void - const_folder::visit_defined_op (defined_op* e) - { -- // If a @defined makes it this far, then it is, de facto, undefined. -- -- if (session.verbose>2) -- clog << _("Collapsing untouched @defined check ") << *e->tok << endl; -- relaxed_p = false; -+ // If a @defined makes it this far, then it was not resolved by -+ // previous efforts. We could assume that therefore it is a big fat -+ // zero, but for the @defined(autocast) case PR18079, this just -+ // means that we didn't know yet. - -- literal_number* n = new literal_number (0); -- n->tok = e->tok; -- n->visit (this); -+ if (collapse_defines_p) -+ { -+ if (session.verbose>2) -+ clog << _("Collapsing untouched @defined check ") << *e->tok << endl; -+ relaxed_p = false; -+ literal_number* n = new literal_number (0); -+ n->tok = e->tok; -+ n->visit (this); -+ } -+ else -+ { -+ if (session.verbose>2) -+ clog << _("Preserving unresolved @defined check ") << *e->tok << endl; -+ provide (e); -+ } - } - - void -@@ -5387,6 +5399,21 @@ semantic_pass_types (systemtap_session& s) - ti.current_probe = 0; - ti.current_function = fd; - ti.t = pe_unknown; -+ -+ if (ti.assert_resolvability) -+ { -+ // PR18079, rerun the const-folder / dead-block-remover -+ // one last time, in case an unresolvable -+ // @defined($foobar) still persists. This should map -+ // those to 0. -+ bool relaxed_p; -+ const_folder cf (s, relaxed_p, true); // NB: true -+ cf.replace (fd->body); -+ dead_control_remover dc (s, relaxed_p); -+ fd->body->visit (&dc); -+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag -+ } -+ - fd->body->visit (& ti); - // NB: we don't have to assert a known type for - // functions here, to permit a "void" function. -@@ -5402,6 +5429,16 @@ semantic_pass_types (systemtap_session& s) - { - autocast_expanding_visitor aev (ti); - aev.replace (fd->body); -+ -+ // PR18079, rerun the const-folder / dead-block-remover -+ // in case autocast evaluation enabled a @defined() -+ bool relaxed_p; -+ const_folder cf (s, relaxed_p); -+ cf.replace (fd->body); -+ dead_control_remover dc (s, relaxed_p); -+ fd->body->visit (&dc); -+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag -+ - ti.num_available_autocasts = 0; - } - } -@@ -5420,6 +5457,21 @@ semantic_pass_types (systemtap_session& s) - ti.current_function = 0; - ti.current_probe = pn; - ti.t = pe_unknown; -+ -+ if (ti.assert_resolvability) -+ { -+ // PR18079, rerun the const-folder / dead-block-remover -+ // one last time, in case an unresolvable -+ // @defined($foobar) still persists. This should map -+ // those to 0. -+ bool relaxed_p; -+ const_folder cf (s, relaxed_p, true); // NB: true -+ cf.replace (pn->body); -+ dead_control_remover dc (s, relaxed_p); -+ pn->body->visit (&dc); -+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag -+ } -+ - pn->body->visit (& ti); - for (unsigned i=0; i < pn->locals.size(); ++i) - ti.check_local (pn->locals[i]); -@@ -5429,6 +5481,16 @@ semantic_pass_types (systemtap_session& s) - { - autocast_expanding_visitor aev (ti); - aev.replace (pn->body); -+ -+ // PR18079, rerun the const-folder / dead-block-remover -+ // in case autocast evaluation enabled a @defined() -+ bool relaxed_p; -+ const_folder cf (s, relaxed_p); -+ cf.replace (pn->body); -+ dead_control_remover dc (s, relaxed_p); -+ pn->body->visit (&dc); -+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag -+ - ti.num_available_autocasts = 0; - } - -@@ -5907,7 +5969,15 @@ typeresolution_info::visit_target_symbol (target_symbol* e) - // later unused-expression-elimination pass didn't get rid of it - // either. So we have a target symbol that is believed to be of - // genuine use, yet unresolved by the provider. -- -+ // -+ // PR18079, or it can happen if a $target expression is nested within -+ // a @defined() test that has not yet been resolved (but can be soon). -+ if (! assert_resolvability) -+ { -+ num_still_unresolved ++; -+ return; -+ } -+ - if (session.verbose > 2) - { - clog << _("Resolution problem with "); -@@ -5974,7 +6044,15 @@ typeresolution_info::visit_atvar_op (atvar_op* e) - void - typeresolution_info::visit_defined_op (defined_op* e) - { -- throw SEMANTIC_ERROR(_("unexpected @defined"), e->tok); -+ // PR18079: if a @defined is still around, it may have a parameter that -+ // wasn't resolvable one way or another earlier. Maybe an autocast_op. -+ // Let's give it a visit just in case. -+ e->operand->visit(this); -+ -+ if (assert_resolvability) -+ throw SEMANTIC_ERROR(_("unexpected @defined"), e->tok); -+ else -+ num_still_unresolved ++; - } - - -diff --git a/testsuite/semok/autocast14.stp b/testsuite/semok/autocast14.stp -index 55c06c4..1b32d80 100755 ---- a/testsuite/semok/autocast14.stp -+++ b/testsuite/semok/autocast14.stp -@@ -1,7 +1,7 @@ - #! stap -p2 - --probe oneshot --{ -+ -+@define STUFF %( - // precheck, it should work with @cast - if (!@defined(@task(0)->mm)) { - println($cast_failed_mm) -@@ -17,4 +17,16 @@ probe oneshot - if (@defined(task_current()->systemtap)) { - println($autocast_succeeded_systemtap) - } -+%) -+ -+ -+probe oneshot -+{ -+ @STUFF -+ foo() // from a function too, to test PR18079 function processing - } -+ -+function foo () -+{ -+ @STUFF -+} -\ No newline at end of file - -commit 0eda9cd7c9fe3cf7622f6bcf5e9cfba9fdf537dd -Author: Josh Stone -Date: Wed Jun 22 12:09:05 2016 -0700 - - Increase the difficulty of semok/autocast14.stp - -diff --git a/testsuite/semok/autocast14.stp b/testsuite/semok/autocast14.stp -index 1b32d80..b9488d7 100755 ---- a/testsuite/semok/autocast14.stp -+++ b/testsuite/semok/autocast14.stp -@@ -17,6 +17,19 @@ - if (@defined(task_current()->systemtap)) { - println($autocast_succeeded_systemtap) - } -+ -+ // Test that autocast can resolve on the results of @defined -+ mm1 = @choose_defined($nonsense, task_current())->mm; -+ mm2 = @choose_defined(task_current(), $nonsense)->mm; -+ println(mm1 == mm2) -+ -+ // Test an even deeper level of @defined -+ if (!@defined(mm1->mmap) || !@defined(mm2->mmap)) { -+ println($autocast_failed_mm_mmap) -+ } -+ if (@defined(mm1->systemtap) || @defined(mm2->systemtap)) { -+ println($autocast_succeeded_mm_systemtap) -+ } - %) - - -@@ -29,4 +42,4 @@ probe oneshot - function foo () - { - @STUFF --} -\ No newline at end of file -+} - -commit 048b546d5645abb6e6ef5148c4ddbd170600e1d3 -Author: Josh Stone -Date: Fri Jul 8 18:21:49 2016 -0700 - - Tweak autocast-defined interactions further - - - collapse basic @defined($foo) right away. - - last-ditch collapse other @defined(expr) to 1 or 0 depending on pe_unknown. - - run that last-ditch effort *before* turning on assert_resolvability. - - only run extra dead_control_remover for optimized runs - - in var_expanding_visitor, pass *any* unchanged expr through, so they - may be decided later. (e.g. for @choose_defined ternaries) - -diff --git a/elaborate.cxx b/elaborate.cxx -index a1088a1..fd6ccce 100644 ---- a/elaborate.cxx -+++ b/elaborate.cxx -@@ -3987,7 +3987,8 @@ struct const_folder: public update_visitor - bool collapse_defines_p; - - const_folder(systemtap_session& s, bool& r, bool collapse_defines = false): -- session(s), relaxed_p(r), collapse_defines_p(collapse_defines), last_number(0), last_string(0) {} -+ session(s), relaxed_p(r), collapse_defines_p(collapse_defines), -+ last_number(0), last_string(0), last_target_symbol(0) {} - - literal_number* last_number; - literal_number* get_number(expression*& e); -@@ -4011,6 +4012,9 @@ struct const_folder: public update_visitor - void visit_concatenation (concatenation* e); - void visit_ternary_expression (ternary_expression* e); - void visit_defined_op (defined_op* e); -+ -+ target_symbol* last_target_symbol; -+ target_symbol* get_target_symbol(expression*& e); - void visit_target_symbol (target_symbol* e); - }; - -@@ -4511,15 +4515,35 @@ const_folder::visit_defined_op (defined_op* e) - // previous efforts. We could assume that therefore it is a big fat - // zero, but for the @defined(autocast) case PR18079, this just - // means that we didn't know yet. -+ int64_t value = 0; -+ bool collapse_this = false; - -- if (collapse_defines_p) -+ // We do know that plain target_symbols aren't going anywhere though. -+ if (get_target_symbol (e->operand)) -+ { -+ if (session.verbose>2) -+ clog << _("Collapsing target_symbol @defined check ") << *e->tok << endl; -+ collapse_this = true; -+ } -+ else if (collapse_defines_p && relaxed_p) - { - if (session.verbose>2) - clog << _("Collapsing untouched @defined check ") << *e->tok << endl; -- relaxed_p = false; -- literal_number* n = new literal_number (0); -- n->tok = e->tok; -- n->visit (this); -+ -+ // If we got to an expression with a known type, call it defined. -+ if (e->operand->type != pe_unknown) -+ value = 1; -+ collapse_this = true; -+ } -+ -+ if (collapse_this) -+ { -+ // Don't be greedy... we'll only collapse one at a time so type -+ // resolution can have another go at it. -+ relaxed_p = false; -+ literal_number* n = new literal_number (value); -+ n->tok = e->tok; -+ n->visit (this); - } - else - { -@@ -4529,6 +4553,13 @@ const_folder::visit_defined_op (defined_op* e) - } - } - -+target_symbol* -+const_folder::get_target_symbol(expression*& e) -+{ -+ replace (e); -+ return (e == last_target_symbol) ? last_target_symbol : NULL; -+} -+ - void - const_folder::visit_target_symbol (target_symbol* e) - { -@@ -4545,7 +4576,10 @@ const_folder::visit_target_symbol (target_symbol* e) - relaxed_p = false; - } - else -- update_visitor::visit_target_symbol (e); -+ { -+ update_visitor::visit_target_symbol (e); -+ last_target_symbol = e; -+ } - } - - static int initial_typeres_pass(systemtap_session& s); -@@ -5400,20 +5434,6 @@ semantic_pass_types (systemtap_session& s) - ti.current_function = fd; - ti.t = pe_unknown; - -- if (ti.assert_resolvability) -- { -- // PR18079, rerun the const-folder / dead-block-remover -- // one last time, in case an unresolvable -- // @defined($foobar) still persists. This should map -- // those to 0. -- bool relaxed_p; -- const_folder cf (s, relaxed_p, true); // NB: true -- cf.replace (fd->body); -- dead_control_remover dc (s, relaxed_p); -- fd->body->visit (&dc); -- (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag -- } -- - fd->body->visit (& ti); - // NB: we don't have to assert a known type for - // functions here, to permit a "void" function. -@@ -5431,13 +5451,19 @@ semantic_pass_types (systemtap_session& s) - aev.replace (fd->body); - - // PR18079, rerun the const-folder / dead-block-remover -- // in case autocast evaluation enabled a @defined() -- bool relaxed_p; -- const_folder cf (s, relaxed_p); -- cf.replace (fd->body); -- dead_control_remover dc (s, relaxed_p); -- fd->body->visit (&dc); -- (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag -+ // if autocast evaluation enabled a @defined() -+ if (aev.count_replaced_defined_ops() > 0) -+ { -+ bool relaxed_p = true; -+ const_folder cf (s, relaxed_p); -+ cf.replace (fd->body); -+ if (! s.unoptimized) -+ { -+ dead_control_remover dc (s, relaxed_p); -+ fd->body->visit (&dc); -+ } -+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag -+ } - - ti.num_available_autocasts = 0; - } -@@ -5458,20 +5484,6 @@ semantic_pass_types (systemtap_session& s) - ti.current_probe = pn; - ti.t = pe_unknown; - -- if (ti.assert_resolvability) -- { -- // PR18079, rerun the const-folder / dead-block-remover -- // one last time, in case an unresolvable -- // @defined($foobar) still persists. This should map -- // those to 0. -- bool relaxed_p; -- const_folder cf (s, relaxed_p, true); // NB: true -- cf.replace (pn->body); -- dead_control_remover dc (s, relaxed_p); -- pn->body->visit (&dc); -- (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag -- } -- - pn->body->visit (& ti); - for (unsigned i=0; i < pn->locals.size(); ++i) - ti.check_local (pn->locals[i]); -@@ -5483,13 +5495,19 @@ semantic_pass_types (systemtap_session& s) - aev.replace (pn->body); - - // PR18079, rerun the const-folder / dead-block-remover -- // in case autocast evaluation enabled a @defined() -- bool relaxed_p; -- const_folder cf (s, relaxed_p); -- cf.replace (pn->body); -- dead_control_remover dc (s, relaxed_p); -- pn->body->visit (&dc); -- (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag -+ // if autocast evaluation enabled a @defined() -+ if (aev.count_replaced_defined_ops() > 0) -+ { -+ bool relaxed_p = true; -+ const_folder cf (s, relaxed_p); -+ cf.replace (pn->body); -+ if (! s.unoptimized) -+ { -+ dead_control_remover dc (s, relaxed_p); -+ pn->body->visit (&dc); -+ } -+ (void) relaxed_p; // we judge success later by num_still_unresolved, not this flag -+ } - - ti.num_available_autocasts = 0; - } -@@ -5526,9 +5544,27 @@ semantic_pass_types (systemtap_session& s) - break; // successfully - else if (! ti.assert_resolvability) - { -- ti.assert_resolvability = true; // last pass, with error msgs -- if (s.verbose > 0) -- ti.mismatch_complexity = 0; // print every kind of mismatch -+ // PR18079, before we go asserting anything, try to nullify any -+ // still-unresolved @defined ops. -+ bool relaxed_p = true; -+ const_folder cf (s, relaxed_p, true); // NB: true -+ -+ for (auto it = s.probes.begin(); it != s.probes.end(); ++it) -+ cf.replace ((*it)->body); -+ for (auto it = s.functions.begin(); it != s.functions.end(); ++it) -+ cf.replace (it->second->body); -+ -+ if (! s.unoptimized) -+ semantic_pass_dead_control (s, relaxed_p); -+ -+ if (! relaxed_p) -+ ti.mismatch_complexity = 0; // reset for next pass -+ else -+ { -+ ti.assert_resolvability = true; // last pass, with error msgs -+ if (s.verbose > 0) -+ ti.mismatch_complexity = 0; // print every kind of mismatch -+ } - } - else - { // unsuccessful conclusion -diff --git a/tapsets.cxx b/tapsets.cxx -index 069966b..6d82069 100644 ---- a/tapsets.cxx -+++ b/tapsets.cxx -@@ -2835,7 +2835,8 @@ private: - unsigned var_expanding_visitor::tick = 0; - - --var_expanding_visitor::var_expanding_visitor (): op() -+var_expanding_visitor::var_expanding_visitor (): -+ replaced_defined_ops(0), op() - { - // FIXME: for the time being, by default we only support plain '$foo - // = bar', not '+=' or any other op= variant. This is fixable, but a -@@ -2964,6 +2965,7 @@ var_expanding_visitor::visit_delete_statement (delete_statement* s) - void - var_expanding_visitor::visit_defined_op (defined_op* e) - { -+ expression * const old_operand = e->operand; - bool resolved = true; - - defined_ops.push (e); -@@ -2999,11 +3001,12 @@ var_expanding_visitor::visit_defined_op (defined_op* e) - target_symbol* tsym = dynamic_cast (e->operand); - if (tsym && tsym->saved_conversion_error) // failing - resolved = false; -- else if (tsym) // unresolved but not marked failing -+ else if (e->operand == old_operand) // unresolved but not marked failing - { - // There are some visitors that won't touch certain target_symbols, - // e.g. dwarf_var_expanding_visitor won't resolve @cast. We should - // leave it for now so some other visitor can have a chance. -+ defined_ops.pop (); - provide (e); - return; - } -@@ -3017,6 +3020,7 @@ var_expanding_visitor::visit_defined_op (defined_op* e) - literal_number* ln = new literal_number (resolved ? 1 : 0); - ln->tok = e->tok; - provide (ln); -+ ++replaced_defined_ops; - } - - -diff --git a/tapsets.h b/tapsets.h -index d630dbb..cb73a7e 100644 ---- a/tapsets.h -+++ b/tapsets.h -@@ -61,11 +61,6 @@ public: - - struct var_expanding_visitor: public update_visitor - { -- static unsigned tick; -- std::stack defined_ops; -- std::set valid_ops; -- interned_string* op; -- - var_expanding_visitor (); - void visit_assignment (assignment* e); - void visit_pre_crement (pre_crement* e); -@@ -73,6 +68,15 @@ struct var_expanding_visitor: public update_visitor - void visit_delete_statement (delete_statement* s); - void visit_defined_op (defined_op* e); - -+ unsigned count_replaced_defined_ops () { return replaced_defined_ops; } -+ -+protected: -+ static unsigned tick; -+ unsigned replaced_defined_ops; -+ std::stack defined_ops; -+ std::set valid_ops; -+ interned_string* op; -+ - void provide_lvalue_call(functioncall* fcall); - - private: -diff --git a/testsuite/semok/autocast14.stp b/testsuite/semok/autocast14.stp -index b9488d7..18028e8 100755 ---- a/testsuite/semok/autocast14.stp -+++ b/testsuite/semok/autocast14.stp -@@ -30,6 +30,13 @@ - if (@defined(mm1->systemtap) || @defined(mm2->systemtap)) { - println($autocast_succeeded_mm_systemtap) - } -+ -+ // Test that autocast can resolve through nested @defined -+ // (especially that the ternary isn't automatically "defined") -+ mm3 = @choose_defined(@choose_defined($nonsense, $wut), task_current())->mm; -+ mm4 = @choose_defined(@choose_defined($nonsense, task_current()), $wut)->mm; -+ mm5 = @choose_defined(@choose_defined(task_current(), $nonsense), $wut)->mm; -+ println(mm3 == mm4 && mm4 == mm5) - %) - - diff --git a/SOURCES/rhbz1346112.patch b/SOURCES/rhbz1346112.patch deleted file mode 100644 index 8a74218..0000000 --- a/SOURCES/rhbz1346112.patch +++ /dev/null @@ -1,62 +0,0 @@ -commit be665e77eb7cd88a3d15676945bec7def3eb73d5 -Author: Frank Ch. Eigler -Date: Wed Jun 15 10:58:01 2016 -0400 - - RHBZ1346112: let stap-server create ssl-cert on first run rather than install - - This way different container-images get different certs. - -diff --git a/stap-server b/stap-server -index 939c503..c39ae49 100644 ---- a/stap-server -+++ b/stap-server -@@ -500,6 +500,19 @@ prepare_stat_dir () { - return 0 - } - -+prepare_certs () { -+ if [ "$USER" != "`id -un`" ]; then -+ if ! runuser -s /bin/bash - $USER -c 'test -f $HOME/.systemtap/ssl/server/stap.cert'; then -+ runuser -s /bin/bash - $USER -c %{_libexecdir}/systemtap/stap-gen-cert >/dev/null -+ fi -+ else -+ if ! test -f $HOME/.systemtap/ssl/server/stap.cert; then -+ ${PKGLIBEXECDIR}stap-gen-cert -+ fi -+ fi -+} -+ -+ - prepare_log_dir () { - local log_path=`dirname "$1"` - if [ ! -d "$log_path" ]; then -@@ -859,6 +872,13 @@ start_server () { - fi - fi - -+ # Create certificates for this server -+ prepare_certs -+ if [ $? -ne 0 ]; then -+ echo $"Failed to make certificates ($USER .systemtap/ssl/server/stap.cert)" >&2 -+ exit 1 -+ fi -+ - # Create the log directory for this server - prepare_log_dir "$LOG" - if [ $? -ne 0 ]; then -diff --git a/systemtap.spec b/systemtap.spec -index 1630fba..84bf041 100644 ---- a/systemtap.spec -+++ b/systemtap.spec -@@ -658,11 +658,6 @@ test -e %{_localstatedir}/log/stap-server/log || { - chmod 644 %{_localstatedir}/log/stap-server/log - chown stap-server:stap-server %{_localstatedir}/log/stap-server/log - } --# If it does not already exist, as stap-server, generate the certificate --# used for signing and for ssl. --if test ! -e ~stap-server/.systemtap/ssl/server/stap.cert; then -- runuser -s /bin/sh - stap-server -c %{_libexecdir}/systemtap/stap-gen-cert >/dev/null --fi - # Prepare the service - %if %{with_systemd} - # Note, Fedora policy doesn't allow network services enabled by default diff --git a/SOURCES/rhbz1365550.patch b/SOURCES/rhbz1365550.patch deleted file mode 100644 index 15052ec..0000000 --- a/SOURCES/rhbz1365550.patch +++ /dev/null @@ -1,52 +0,0 @@ -commit 10c48d46fa482b8cc762592aaee6c7cc178356e7 -Author: Frank Ch. Eigler -Date: Mon Mar 28 08:54:11 2016 -0400 - - PR19874: reset 60s alarm for "stap -c CMD" - - Brown paper bag bug. Test case included. - -diff --git a/staprun/mainloop.c b/staprun/mainloop.c -index 82c0c74..874fbd8 100644 ---- a/staprun/mainloop.c -+++ b/staprun/mainloop.c -@@ -281,6 +281,7 @@ void start_cmd(void) - raise (SIGCONT); /* Harmless; just passes control to parent. */ - #endif /* !WORKAROUND_BZ467568 */ - -+ alarm(0); /* clear alarms */ - dbug(1, "execing target_cmd %s\n", target_cmd); - - /* Note that execvp() is not a direct system call; it does a $PATH -diff --git a/testsuite/systemtap.base/staprunwait.exp b/testsuite/systemtap.base/staprunwait.exp -new file mode 100644 -index 0000000..fc71973 ---- /dev/null -+++ b/testsuite/systemtap.base/staprunwait.exp -@@ -0,0 +1,17 @@ -+set test staprunwait -+ -+if {! [installtest_p]} { untested $test; return } -+ -+foreach runtime [get_runtime_list] { -+ if {$runtime != ""} { -+ set ok [catch {exec stap $srcdir/$subdir/$test.stp --runtime=$runtime -c "sleep 120"} foo] -+ } else { -+ set ok [catch {exec stap $srcdir/$subdir/$test.stp -c "sleep 120"} foo] -+ } -+ verbose -log "$ok $foo" -+ if {$ok != 0} { -+ fail "$test $runtime" -+ } else { -+ pass "$test $runtime" -+ } -+} -diff --git a/testsuite/systemtap.base/staprunwait.stp b/testsuite/systemtap.base/staprunwait.stp -new file mode 100644 -index 0000000..91cbc92 ---- /dev/null -+++ b/testsuite/systemtap.base/staprunwait.stp -@@ -0,0 +1,3 @@ -+#! /usr/bin/env stap -+ -+probe timer.s(10) { println(ctime()) } diff --git a/SOURCES/rhbz1376515.patch b/SOURCES/rhbz1376515.patch deleted file mode 100644 index bbe92e6..0000000 --- a/SOURCES/rhbz1376515.patch +++ /dev/null @@ -1,281 +0,0 @@ -From fced4ba337a4eddb4163994834a122e62c6efdfb Mon Sep 17 00:00:00 2001 -From: Ravi Bangoria -Date: Wed, 14 Sep 2016 13:32:51 +0530 -Subject: [PATCH 1/2] ppc64le: Store correct function entry address in - symbol_table - -PPC64 ELF ABI v2 has a Global Entry Point and a Local Entry Point for -the functions. Debuginfo of ELF contains GEP which is same as entrypc -while symbol table contains GEP and offset, from which we can calculate -LEP. LEP is used to call function within single CU, when TOC pointer -update is not required. Placing a probe on LEP catches call from both -the GEP and the LEP but, by default, systemtap probes on GEP. - -For ppc64le, Systemtap stores LEP in symbol table and prioritize symbol -table over debuginfo. But, storing LEP in symbol table has couple of -regression effect. As LEP is only required at a time of adding a probe, -don't store it in symbol table. - -No need to prioritize symbol table as well because debuginfo and symbol -table both will contain Global Entry Point. - -Revert commit b4c6a4b1cd00 ("Prioritize symbol table lookup for ppc64le") -partially. - -Signed-off-by: Ravi Bangoria ---- - tapsets.cxx | 62 +------------------------------------------------------------ - 1 file changed, 1 insertion(+), 61 deletions(-) - -diff --git a/tapsets.cxx b/tapsets.cxx -index 4167678..a887e1f 100644 ---- a/tapsets.cxx -+++ b/tapsets.cxx -@@ -2134,18 +2134,6 @@ query_dwarf_inline_instance (Dwarf_Die * die, dwarf_query * q) - } - } - --static bool --is_filtered_func_exists (func_info_map_t const& filtered, func_info *fi) --{ -- for (unsigned i = 0; i < filtered.size(); i++) -- { -- if ((filtered[i].entrypc == fi->entrypc) && (filtered[i].name == fi->name)) -- return true; -- } -- -- return false; --} -- - static int - query_dwarf_func (Dwarf_Die * func, dwarf_query * q) - { -@@ -2198,37 +2186,7 @@ query_dwarf_func (Dwarf_Die * func, dwarf_query * q) - q->dw.function_line (&func.decl_line); - - Dwarf_Addr entrypc; -- -- func.entrypc = 0; -- Dwarf_Addr bias; -- Dwfl_Module *mod = q->dw.module; -- Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias)) -- ?: dwfl_module_getelf (mod, &bias)); -- -- GElf_Ehdr ehdr_mem; -- GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem); -- if (em == NULL) throw SEMANTIC_ERROR (_("Couldn't get elf header")); -- -- /* Giving priority to sym_table for ppc64*/ -- if ((em->e_machine == EM_PPC64) && ((em->e_flags & EF_PPC64_ABI) == 2) -- && (q->dw.mod_info->sym_table)) -- { -- /* The linkage name is the best match for the symbol table. */ -- const string& linkage_name = dwarf_linkage_name(&func.die) -- ?: dwarf_diename(&func.die) ?: (string)func.name; -- -- set fis = q->dw.mod_info->sym_table->lookup_symbol(linkage_name); -- for (set::iterator it=fis.begin(); it!=fis.end() ; ++it) -- { -- func.entrypc = (*it)->entrypc; -- if (is_filtered_func_exists(q->filtered_functions, &func)) -- continue; -- q->filtered_functions.push_back(func); -- } -- } -- -- /* If not ppc64 or not found in sym_table, try it directly. */ -- if (!func.entrypc && q->dw.function_entrypc (&entrypc)) -+ if (q->dw.function_entrypc (&entrypc)) - { - func.entrypc = entrypc; - q->filtered_functions.push_back (func); -@@ -8448,13 +8406,6 @@ symbol_table::get_from_elf() - int syments = dwfl_module_getsymtab(mod); - assert(syments); - prepare_section_rejection(mod); -- Dwarf_Addr bias; -- Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias)) -- ?: dwfl_module_getelf (mod, &bias)); -- -- GElf_Ehdr ehdr_mem; -- GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem); -- if (em == NULL) throw SEMANTIC_ERROR (_("Couldn't get elf header")); - - for (int i = 1; i < syments; ++i) - { -@@ -8487,18 +8438,7 @@ symbol_table::get_from_elf() - continue; - interned_string name = n; - -- /* -- * For ELF ABI v2 on PPC64 LE, we need to adjust sym.st_value corresponding -- * to the bits of sym.st_other. These bits will tell us what's the offset -- * of the local entry point from the global entry point. -- * -- * st_other field is currently only used with ABIv2 on ppc64 -- */ - Dwarf_Addr entrypc = addr; -- if ((em->e_machine == EM_PPC64) && ((em->e_flags & EF_PPC64_ABI) == 2) -- && (GELF_ST_TYPE(sym.st_info) == STT_FUNC) && sym.st_other) -- entrypc += PPC64_LOCAL_ENTRY_OFFSET(sym.st_other); -- - if (GELF_ST_TYPE(sym.st_info) == STT_FUNC) - add_symbol(name, (GELF_ST_BIND(sym.st_info) == STB_WEAK), - reject, addr, entrypc); --- -1.8.3.1 - -From 1b83a55a0272f2eb0bdcd5809fb630e1f369d400 Mon Sep 17 00:00:00 2001 -From: Ravi Bangoria -Date: Wed, 14 Sep 2016 13:36:00 +0530 -Subject: [PATCH 2/2] ppc64le: Fix LEP usage for probing - -PPC64 ELF ABI v2 has a Global Entry Point and a Local Entry Point for -the functions. Debuginfo of ELF contains GEP which is same as entrypc -while symbol table contains GEP and offset, from which we can calculate -LEP. LEP is used to call function within single CU, when TOC pointer -update is not required. Placing a probe on LEP catches call from both -the GEP and the LEP but, by default, systemtap probes on GEP. - -Commit b4c6a4b1cd00 ("Prioritize symbol table lookup for ppc64le") solve -this issue by storing LEP in symbol table and prioritizing symbol table -over debuginfo for ppc64le. - -But there are few regression effect of this patch. Couple of examples -are given below. - -1. If target program is compiled without optimization and user is -interested in function parameter, systemtap should probe after function -prologue. But above patch forces probe on LEP and which result in garbage -value of function parameter will get recorded. - - $ make verbose=1 installcheck RUNTESTFLAGS='at_var.exp -v --debug' - ... - # of expected passes 1 - # of unexpected failures 1 - -2. Probe on shared library function with parameter is failing at Pass 2. - - $ make verbose=1 installcheck RUNTESTFLAGS='exelib.exp -v --debug' - ... - # of expected passes 10 - # of unexpected failures 64 - -3. When symbol_name with offset is used to register kprobe, kernel itself -will find LEP and adds offset to it. Systemtap using LEP to find offset -is resulting in offset being added two times. - GEP + lep_offset (by systemtap) + lep_offset (by kernel) - -This can be solved by calculating LEP only at a time of adding a probe. -That will make effect of LEP local to that area and won't have any -regression effect. - -After applying patch: - - $ make verbose=1 installcheck RUNTESTFLAGS='at_var.exp -v --debug' - ... - # of expected passes 2 - - $ make verbose=1 installcheck RUNTESTFLAGS='exelib.exp -v --debug' - ... - # of expected passes 74 - -Signed-off-by: Ravi Bangoria ---- - tapsets.cxx | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- - 1 file changed, 59 insertions(+), 1 deletion(-) - -diff --git a/tapsets.cxx b/tapsets.cxx -index a887e1f..30aebb9 100644 ---- a/tapsets.cxx -+++ b/tapsets.cxx -@@ -1376,6 +1376,59 @@ string path_remove_sysroot(const systemtap_session& sess, const string& path) - return retval; - } - -+/* -+ * Convert 'Global Entry Point' to 'Local Entry Point'. -+ * -+ * if @gep contains next address after prologue, don't change it. -+ * -+ * For ELF ABI v2 on PPC64 LE, we need to adjust sym.st_value corresponding -+ * to the bits of sym.st_other. These bits will tell us what's the offset -+ * of the local entry point from the global entry point. -+ * -+ * st_other field is currently only used with ABIv2 on ppc64 -+ */ -+static Dwarf_Addr -+get_lep(dwarf_query *q, Dwarf_Addr gep) -+{ -+ Dwarf_Addr bias; -+ Dwfl_Module *mod = q->dw.module; -+ Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias)) -+ ?: dwfl_module_getelf (mod, &bias)); -+ -+ GElf_Ehdr ehdr_mem; -+ GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem); -+ if (em == NULL) -+ throw SEMANTIC_ERROR (_("Couldn't get elf header")); -+ -+ if (!(em->e_machine == EM_PPC64) || !((em->e_flags & EF_PPC64_ABI) == 2)) -+ return gep; -+ -+ int syments = dwfl_module_getsymtab(mod); -+ for (int i = 1; i < syments; ++i) -+ { -+ GElf_Sym sym; -+ GElf_Word section; -+ GElf_Addr addr; -+ -+#if _ELFUTILS_PREREQ (0, 158) -+ dwfl_module_getsym_info (mod, i, &sym, &addr, §ion, NULL, NULL); -+#else -+ dwfl_module_getsym (mod, i, &sym, §ion); -+ addr = sym.st_value; -+#endif -+ -+ /* -+ * Symbol table contains module_bias + offset. Substract module_bias -+ * to compare offset with gep. -+ */ -+ if ((addr - bias) == gep && (GELF_ST_TYPE(sym.st_info) == STT_FUNC) -+ && sym.st_other) -+ return gep + PPC64_LOCAL_ENTRY_OFFSET(sym.st_other); -+ } -+ -+ return gep; -+} -+ - void - dwarf_query::add_probe_point(interned_string dw_funcname, - interned_string filename, -@@ -1384,12 +1437,14 @@ dwarf_query::add_probe_point(interned_string dw_funcname, - Dwarf_Addr addr) - { - interned_string reloc_section; // base section for relocation purposes -+ Dwarf_Addr orig_addr = addr; - Dwarf_Addr reloc_addr; // relocated - interned_string module = dw.module_name; // "kernel" or other - interned_string funcname = dw_funcname; - - assert (! has_absolute); // already handled in dwarf_builder::build() - -+ addr = get_lep(this, addr); - reloc_addr = dw.relocate_address(addr, reloc_section); - - // If we originally used the linkage name, then let's call it that way -@@ -1455,7 +1510,10 @@ dwarf_query::add_probe_point(interned_string dw_funcname, - - symbol_table *sym_table = mi->sym_table; - func_info *symbol = sym_table->get_func_containing_address(addr); -- Dwarf_Addr offset = addr - symbol->addr; -+ -+ // Do not use LEP to find offset here. When 'symbol_name' -+ // is used to register probe, kernel itself will find LEP. -+ Dwarf_Addr offset = orig_addr - symbol->addr; - results.push_back (new dwarf_derived_probe(funcname, filename, - line, module, - reloc_section, addr, --- -1.8.3.1 - diff --git a/SPECS/systemtap.spec b/SPECS/systemtap.spec index 01f3a55..ad42aa8 100644 --- a/SPECS/systemtap.spec +++ b/SPECS/systemtap.spec @@ -1,14 +1,9 @@ %{!?with_sqlite: %global with_sqlite 1} -%ifarch ppc64le -# rhbz1252103 = rhbz1243784 -%{!?with_docs: %global with_docs 0} -%else %{!?with_docs: %global with_docs 1} -%endif %{!?with_htmldocs: %global with_htmldocs 0} %{!?with_monitor: %global with_monitor 1} # crash is not available -%ifarch ppc ppc64 %{sparc} aarch64 ppc64le +%ifarch ppc ppc64 %{sparc} aarch64 ppc64le %{mips} %{!?with_crash: %global with_crash 0} %else %{!?with_crash: %global with_crash 1} @@ -28,7 +23,7 @@ %{!?with_java: %global with_java 0%{?fedora} >= 19 || 0%{?rhel} >= 7} %{!?with_virthost: %global with_virthost 0%{?fedora} >= 19 || 0%{?rhel} >= 7} %{!?with_virtguest: %global with_virtguest 1} -%{!?with_dracut: %global with_dracut 0%{?fedora} >= 19 || 0%{?rhel} >= 7} +%{!?with_dracut: %global with_dracut 0%{?fedora} >= 19 || 0%{?rhel} >= 6} %ifarch x86_64 %{!?with_mokutil: %global with_mokutil 0%{?fedora} >= 18 || 0%{?rhel} >= 7} %{!?with_openssl: %global with_openssl 0%{?fedora} >= 18 || 0%{?rhel} >= 7} @@ -38,6 +33,8 @@ %endif %{!?with_pyparsing: %global with_pyparsing 0%{?fedora} >= 18 || 0%{?rhel} >= 7} %{!?with_python3: %global with_python3 0%{?fedora} >= 23} +%{!?with_python2_probes: %global with_python2_probes 1} +%{!?with_python3_probes: %global with_python3_probes 0%{?fedora} >= 23} %ifarch ppc64le aarch64 %global with_virthost 0 @@ -61,11 +58,21 @@ %endif %endif -%define dracutstap %{_prefix}/lib/dracut/modules.d/99stap +%if 0%{?fedora} >= 19 || 0%{?rhel} >= 7 + %define dracutstap %{_prefix}/lib/dracut/modules.d/99stap +%else + %define dracutstap %{_prefix}/share/dracut/modules.d/99stap +%endif + +%if 0%{?rhel} >= 6 + %define dracutbindir /sbin +%else + %define dracutbindir %{_bindir} +%endif Name: systemtap -Version: 3.0 -Release: 7%{?dist} +Version: 3.1 +Release: 3%{?dist} # for version, see also configure.ac @@ -82,6 +89,8 @@ Release: 7%{?dist} # systemtap-runtime-java libHelperSDT.so, HelperSDT.jar, stapbm, req:-runtime # systemtap-runtime-virthost /usr/bin/stapvirt, req:libvirt req:libxml2 # systemtap-runtime-virtguest udev rules, init scripts/systemd service, req:-runtime +# systemtap-runtime-python2 HelperSDT python2 module, req:-runtime +# systemtap-runtime-python3 HelperSDT python3 module, req:-runtime # # Typical scenarios: # @@ -104,16 +113,21 @@ Source: ftp://sourceware.org/pub/systemtap/releases/systemtap-%{version}.tar.gz BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) BuildRequires: gcc-c++ BuildRequires: gettext-devel -BuildRequires: nss-devel avahi-devel pkgconfig +BuildRequires: pkgconfig(nss) +BuildRequires: pkgconfig(avahi-client) %if %{with_dyninst} BuildRequires: dyninst-devel >= 8.0 -BuildRequires: libselinux-devel +BuildRequires: pkgconfig(libselinux) %endif %if %{with_sqlite} BuildRequires: sqlite-devel %endif %if %{with_monitor} -BuildRequires: json-c-devel ncurses-devel +BuildRequires: pkgconfig(json-c) +BuildRequires: pkgconfig(ncurses) +%endif +%if %{with_systemd} +BuildRequires: systemd %endif # Needed for libstd++ < 4.0, without %if %{with_boost} @@ -123,7 +137,7 @@ BuildRequires: boost-devel BuildRequires: crash-devel zlib-devel %endif %if %{with_rpm} -BuildRequires: rpm-devel glibc-headers +BuildRequires: rpm-devel %endif %if %{with_bundled_elfutils} Source1: elfutils-%{elfutils_version}.tar.gz @@ -155,21 +169,34 @@ BuildRequires: emacs BuildRequires: jpackage-utils java-devel %endif %if %{with_virthost} -BuildRequires: libvirt-devel >= 1.0.2 -BuildRequires: libxml2-devel +# BuildRequires: libvirt-devel >= 1.0.2 +BuildRequires: pkgconfig(libvirt) +BuildRequires: pkgconfig(libxml-2.0) %endif BuildRequires: readline-devel %if 0%{?rhel} <= 5 -BuildRequires: ncurses-devel +BuildRequires: pkgconfig(ncurses) +%endif +%if %{with_python2_probes} +BuildRequires: python-devel +BuildRequires: python-setuptools +%endif +%if %{with_python3_probes} +BuildRequires: python3-devel +BuildRequires: python3-setuptools %endif -Patch10: rhbz1242368.patch -Patch11: rhbz1346112.patch -Patch12: rhbz1269062.patch -Patch13: rhbz1337416.patch -Patch14: rhbz1365550.patch -Patch15: rhbz1312169.patch -Patch16: rhbz1376515.patch +Patch10: bz1428120.patch +Patch11: bz1425568.1.patch +Patch12: bz1425568.2.patch +Patch13: bz1431263.1.patch +Patch14: bz1431263.2.patch +Patch15: bz1431263.3.patch +Patch16: bz1431263.4.patch +Patch17: bz1431263.5.patch +Patch18: bz1430828.patch +Patch19: bz1433391.patch +Patch20: bz1436845.patch # Install requirements Requires: systemtap-client = %{version}-%{release} @@ -203,6 +230,9 @@ BuildRequires: nss-devel avahi-devel %if %{with_openssl} Requires: openssl %endif +%if %{with_systemd} +Requires: systemd +%endif %description server This is the remote script compilation server component of systemtap. @@ -215,10 +245,11 @@ Summary: Programmable system-wide instrumentation system - development headers, Group: Development/System License: GPLv2+ URL: http://sourceware.org/systemtap/ -# Alternate kernel packages kernel-PAE-devel et al. have a virtual -# provide for kernel-devel, so this requirement does the right thing, -# at least past RHEL4. -Requires: kernel-devel +# The virtual provide 'kernel-devel-uname-r' tries to get the right +# kernel variant (kernel-PAE, kernel-debug, etc.) devel package +# installed. +Requires: kernel-devel-uname-r +%{?fedora:Suggests: kernel-devel} Requires: gcc make # Suggest: kernel-debuginfo @@ -334,6 +365,12 @@ Requires: crash %if %{with_java} Requires: systemtap-runtime-java = %{version}-%{release} %endif +%if %{with_python2_probes} +Requires: systemtap-runtime-python2 = %{version}-%{release} +%endif +%if %{with_python3_probes} +Requires: systemtap-runtime-python3 = %{version}-%{release} +%endif %ifarch x86_64 Requires: /usr/lib/libc.so # ... and /usr/lib/libgcc_s.so.* @@ -369,6 +406,32 @@ that probe Java processes running on the OpenJDK 1.6 and OpenJDK 1.7 runtimes using Byteman. %endif +%if %{with_python2_probes} +%package runtime-python2 +Summary: Systemtap Python 2 Runtime Support +Group: Development/System +License: GPLv2+ +URL: http://sourceware.org/systemtap/ +Requires: systemtap-runtime = %{version}-%{release} + +%description runtime-python2 +This package includes support files needed to run systemtap scripts +that probe python 2 processes. +%endif + +%if %{with_python3_probes} +%package runtime-python3 +Summary: Systemtap Python 3 Runtime Support +Group: Development/System +License: GPLv2+ +URL: http://sourceware.org/systemtap/ +Requires: systemtap-runtime = %{version}-%{release} + +%description runtime-python3 +This package includes support files needed to run systemtap scripts +that probe python 3 processes. +%endif + %if %{with_virthost} %package runtime-virthost Summary: Systemtap Cross-VM Instrumentation - host @@ -428,6 +491,10 @@ cd .. %patch14 -p1 %patch15 -p1 %patch16 -p1 +%patch17 -p1 +%patch18 -p1 +%patch19 -p1 +%patch20 -p1 %build @@ -498,6 +565,22 @@ cd .. %global java_config --without-java %endif +%if %{with_python3} +%global python3_config --with-python3 +%else +%global python3_config --without-python3 +%endif +%if %{with_python2_probes} +%global python2_probes_config --with-python2-probes +%else +%global python2_probes_config --without-python2-probes +%endif +%if %{with_python3_probes} +%global python3_probes_config --with-python3-probes +%else +%global python3_probes_config --without-python3-probes +%endif + %if %{with_virthost} %global virt_config --enable-virt %else @@ -505,20 +588,15 @@ cd .. %endif %if %{with_dracut} -%global dracut_config --with-dracutstap=%{dracutstap} +%global dracut_config --with-dracutstap=%{dracutstap} --with-dracutbindir=%{dracutbindir} %else %global dracut_config %{nil} %endif -%if %{with_python3} -%global python3_config --with-python3 -%else -%global python3_config --without-python3 -%endif # We don't ship compileworthy python code, just oddball samples %global py_auto_byte_compile 0 -%configure %{?elfutils_config} %{dyninst_config} %{sqlite_config} %{crash_config} %{docs_config} %{pie_config} %{rpm_config} %{java_config} %{virt_config} %{dracut_config} %{python3_config} --disable-silent-rules --with-extra-version="rpm %{version}-%{release}" +%configure %{?elfutils_config} %{dyninst_config} %{sqlite_config} %{crash_config} %{docs_config} %{pie_config} %{rpm_config} %{java_config} %{virt_config} %{dracut_config} %{python3_config} %{python2_probes_config} %{python3_probes_config} --disable-silent-rules --with-extra-version="rpm %{version}-%{release}" make %{?_smp_mflags} %if %{with_emacsvim} @@ -535,14 +613,10 @@ for dir in $(ls -1d $RPM_BUILD_ROOT%{_mandir}/{??,??_??}) ; do echo "%%lang($lang) $dir/man*/*" >> %{name}.lang done -# We want the examples in the special doc dir, not the build install dir. -# We build it in place and then move it away so it doesn't get installed -# twice. rpm can specify itself where the (versioned) docs go with the -# %doc directive. -mv $RPM_BUILD_ROOT%{_datadir}/doc/systemtap/examples examples +ln -s %{_datadir}/systemtap/examples # Fix paths in the example scripts. -find examples -type f -name '*.stp' -print0 | xargs -0 sed -i -r -e '1s@^#!.+stap@#!%{_bindir}/stap@' +find $RPM_BUILD_ROOT%{_datadir}/systemtap/examples -type f -name '*.stp' -print0 | xargs -0 sed -i -r -e '1s@^#!.+stap@#!%{_bindir}/stap@' # To make rpmlint happy, remove any .gitignore files in the testsuite. find testsuite -type f -name '.gitignore' -print0 | xargs -0 rm -f @@ -633,6 +707,8 @@ done %if %{with_dracut} mkdir -p $RPM_BUILD_ROOT%{dracutstap} install -p -m 755 initscript/99stap/module-setup.sh $RPM_BUILD_ROOT%{dracutstap} + install -p -m 755 initscript/99stap/install $RPM_BUILD_ROOT%{dracutstap} + install -p -m 755 initscript/99stap/check $RPM_BUILD_ROOT%{dracutstap} install -p -m 755 initscript/99stap/start-staprun.sh $RPM_BUILD_ROOT%{dracutstap} touch $RPM_BUILD_ROOT%{dracutstap}/params.conf %endif @@ -937,6 +1013,13 @@ done %{_emacs_sitestartdir}/systemtap-init.el %{_datadir}/vim/vimfiles/*/*.vim %endif +# Notice that the stap-resolve-module-function.py file is used by +# *both* the python2 and python3 subrpms. Both subrpms use that same +# python script to help list python probes. +%if %{with_python3_probes} || %{with_python2_probes} +%{_libexecdir}/systemtap/python/stap-resolve-module-function.py +%exclude %{_libexecdir}/systemtap/python/stap-resolve-module-function.py? +%endif %files runtime -f systemtap.lang @@ -971,7 +1054,8 @@ done %files client -f systemtap.lang %defattr(-,root,root) -%doc README README.unprivileged AUTHORS NEWS examples +%doc README README.unprivileged AUTHORS NEWS +%{_datadir}/systemtap/examples %{!?_licensedir:%global license %%doc} %license COPYING %if %{with_docs} @@ -1039,6 +1123,17 @@ done %{_libexecdir}/systemtap/stapbm %endif +%if %{with_python2_probes} +%files runtime-python2 +%{python_sitearch}/HelperSDT +%{python_sitearch}/HelperSDT-*.egg-info +%endif +%if %{with_python3_probes} +%files runtime-python3 +%{python3_sitearch}/HelperSDT +%{python3_sitearch}/HelperSDT-*.egg-info +%endif + %if %{with_virthost} %files runtime-virthost %{_mandir}/man1/stapvirt.1* @@ -1066,7 +1161,23 @@ done # - Upstream release, see wiki page below for detailed notes. # http://sourceware.org/systemtap/wiki/SystemTapReleases +# PRERELEASE %changelog +* Thu Mar 30 2017 David Smith - 3.1-3 +- Added patches for: +- rhbz1425568 task_dentry_path() fix +- rhbz1431263 arm64 hardware breakpoint crash fix +- rhbz1430828 replace task_exe_file() with current_exe_file() +- rhbz1436845 adapt stapdyn to the dyninst 9.3.1 library search model +- rhbz1433391 workaround parser issue in nfs_proc.stp +- rhbz1428120 update lookup_bad_addr() + +* Wed Mar 15 2017 Stan Cox - 3.1-2 +- rebuilt + +* Fri Feb 17 2017 Frank Ch. Eigler - 3.1-1 +- Upstream release. + * Mon Sep 19 2016 Frank Ch. Eigler - 3.0-7 - rhbz1376515 ppc64le probe point / parameter value fix