diff --git a/.gitignore b/.gitignore index f9912e2..e7ffaca 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/systemtap-2.8.tar.gz +SOURCES/systemtap-3.0.tar.gz diff --git a/.systemtap.metadata b/.systemtap.metadata index ffb86ad..5b324b7 100644 --- a/.systemtap.metadata +++ b/.systemtap.metadata @@ -1 +1 @@ -95034e8243e1f9fd33b765afda06546083df1b7f SOURCES/systemtap-2.8.tar.gz +5ef3a2d9945b0f6bae0061e33811e25e5138f5b7 SOURCES/systemtap-3.0.tar.gz diff --git a/SOURCES/june-robust.patch b/SOURCES/june-robust.patch deleted file mode 100644 index 8dead9f..0000000 --- a/SOURCES/june-robust.patch +++ /dev/null @@ -1,132 +0,0 @@ -commit 81bde8f873216c116988a98a0804dd79009b3d40 -Author: Mark Wielaard -Date: Mon Jun 22 16:57:59 2015 +0200 - - runtime/unwind.c: Also sanity check DWARF regno for DW_CFA_restore[_extended]. - - When processCFI wanted to restore a register state to its initial value it - wasn't checking whether the register was actually interesting (or existing). - DWARF_REG_MAP might return a marker (9999) that we don't know or don't care - about this register. This was checked in all the set_*_rule functions, but - not in the case we reset the rule of the register. Add this check also for - DW_CFA_restore[_extended]. - -diff --git a/runtime/unwind.c b/runtime/unwind.c -index d38363b..4dbab33 100644 ---- a/runtime/unwind.c -+++ b/runtime/unwind.c -@@ -426,7 +426,8 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, - value, DWARF_REG_MAP(value)); - value = DWARF_REG_MAP(value); - } -- memcpy(®_STATE.regs[value], &state->cie_regs[value], sizeof(struct unwind_item)); -+ if (value < ARRAY_SIZE(REG_STATE.regs)) -+ memcpy(®_STATE.regs[value], &state->cie_regs[value], sizeof(struct unwind_item)); - break; - case DW_CFA_undefined: - value = get_uleb128(&ptr.p8, end); -@@ -641,7 +642,8 @@ static int processCFI(const u8 *start, const u8 *end, unsigned long targetLoc, - value, DWARF_REG_MAP(value)); - value = DWARF_REG_MAP(value); - } -- memcpy(®_STATE.regs[value], &state->cie_regs[value], sizeof(struct unwind_item)); -+ if (value < ARRAY_SIZE(REG_STATE.regs)) -+ memcpy(®_STATE.regs[value], &state->cie_regs[value], sizeof(struct unwind_item)); - break; - } - dbug_unwind(1, "targetLoc=%lx state->loc=%lx\n", targetLoc, state->loc); - -commit db6670607f9ba837a7a7af8a0ea076595e9eca1d -Author: David Smith -Date: Tue Jun 30 15:24:54 2015 -0500 - - Two small stat code fixes found by source analysis. - - * runtime/stat-common.c (_stp_stat_print_histogram_buf): Fixed small - potential overflow problem by widening values. - * runtime/stat.c (_stp_stat_init): Fixed missing 'va_end' call in an error - situation. - -diff --git a/runtime/stat-common.c b/runtime/stat-common.c -index f8372ac..4491b27 100644 ---- a/runtime/stat-common.c -+++ b/runtime/stat-common.c -@@ -261,10 +261,10 @@ static void _stp_stat_print_histogram_buf(char *buf, size_t size, Hist st, - val_prefix = "<"; - } else if (i == st->buckets-1) { - /* overflow */ -- val = st->start + (i - 2) * st->interval; -+ val = st->start + (int64_t)(i - 2) * st->interval; - val_prefix = ">"; - } else -- val = st->start + (i - 1) * st->interval; -+ val = st->start + (int64_t)(i - 1) * st->interval; - } else - val = _stp_bucket_to_val(i); - -diff --git a/runtime/stat.c b/runtime/stat.c -index 63ffccc..fa5939b 100644 ---- a/runtime/stat.c -+++ b/runtime/stat.c -@@ -71,8 +71,10 @@ static Stat _stp_stat_init (int type, ...) - interval = va_arg(ap, int); - - buckets = _stp_stat_calc_buckets(stop, start, interval); -- if (!buckets) -+ if (!buckets) { -+ va_end (ap); - return NULL; -+ } - } - va_end (ap); - } - -commit 39c6af0c27dfd5cdd71ee60e1667d40d101ff8ac -Author: Mark Wielaard -Date: Tue Jun 30 21:54:28 2015 +0200 - - unwind.c (compute_expr): Don't fallthrough after div/mod/shr. - - When processing DW_OP_div, DW_OP_mod or DW_OP_shr compute_expr - would accidentially fallthrough to the next case statement causing - the DWARF value stack to contain wrong values. - -diff --git a/runtime/unwind.c b/runtime/unwind.c -index 4dbab33..b5c8f6f 100644 ---- a/runtime/unwind.c -+++ b/runtime/unwind.c -@@ -1036,6 +1036,7 @@ static int compute_expr(const u8 *expr, struct unwind_frame_info *frame, - if (b == 0) - goto divzero; - PUSH (a % b); -+ break; - } - - case DW_OP_div: { -@@ -1044,12 +1045,14 @@ static int compute_expr(const u8 *expr, struct unwind_frame_info *frame, - if (b == 0) - goto divzero; - PUSH (a / b); -+ break; - } - - case DW_OP_shr: { - unsigned long b = POP; - unsigned long a = POP; - PUSH (a >> b); -+ break; - } - - case DW_OP_not: -diff --git a/runtime/unwind/unwind.h b/runtime/unwind/unwind.h -index e81e741..d72f68d 100644 ---- a/runtime/unwind/unwind.h -+++ b/runtime/unwind/unwind.h -@@ -157,6 +157,7 @@ static unsigned long read_ptr_sect(const u8 **pLoc, const void *end, - #else - BUILD_BUG_ON(sizeof(u32) != sizeof(value)); - #endif -+ /* fallthrough, see above. */ - case DW_EH_PE_absptr: - if (compat_task) - { diff --git a/SOURCES/rhbz1237098.patch b/SOURCES/rhbz1237098.patch deleted file mode 100644 index eea1698..0000000 --- a/SOURCES/rhbz1237098.patch +++ /dev/null @@ -1,157 +0,0 @@ -commit 6121861509bf5862b2869c71c7d1bbf618f45d46 -Author: Josh Stone -Date: Mon Jul 6 11:35:51 2015 -0700 - - PR18555: prefer linkage_name to match the symtab - - DW_AT_name is usually only the same as the symbol table for C. C++ - names are mangled, which may be given by DW_AT_linkage_name. So if we - want to compare a DWARF subprogram to the symbol table by name, we - should prefer the linkage name when it's available. - - This mattered especially for ppc64le, where query_dwarf_func was trying - to apply the global/local symbol offset. When we took a DWARF C++ - function and tried to find that name in the symbol table for its offset, - there was no match, so the function wouldn't be resolved at all. - - Now that lookup uses the linkage name. If there's still no match, like - with a stripped symbol table, then it falls through to just use DWARF's - entrypc as usual. - - This patch also maintains the raw "addr" and offset "entrypc" separately - for symbol table functions, so for instance update_symtab can still - compare the original address. - -diff --git a/tapsets.cxx b/tapsets.cxx -index fed4166..54f9d3d 100644 ---- a/tapsets.cxx -+++ b/tapsets.cxx -@@ -415,7 +415,7 @@ symbol_table - // Set to SHN_UNDEF if there is no such section. - GElf_Word opd_section; - void add_symbol(const char *name, bool weak, bool descriptor, -- Dwarf_Addr addr, Dwarf_Addr *high_addr); -+ Dwarf_Addr addr, Dwarf_Addr entrypc); - enum info_status get_from_elf(); - void prepare_section_rejection(Dwfl_Module *mod); - bool reject_section(GElf_Word section); -@@ -1068,19 +1068,19 @@ query_symtab_func_info (func_info & fi, dwarf_query * q) - { - assert(null_die(&fi.die)); - -- Dwarf_Addr addr = fi.addr; -+ Dwarf_Addr entrypc = fi.entrypc; - - // Now compensate for the dw bias because the addresses come -- // from dwfl_module_symtab, so fi->addr is NOT a normal dw address. -+ // from dwfl_module_symtab, so fi->entrypc is NOT a normal dw address. - q->dw.get_module_dwarf(false, false); -- addr -= q->dw.module_bias; -+ entrypc -= q->dw.module_bias; - - // If there are already probes in this module, lets not duplicate. - // This can come from other weak symbols/aliases or existing -- // matches from Dwarf DIE functions. Try to add this addr to the -+ // matches from Dwarf DIE functions. Try to add this entrypc to the - // collection, and only continue if it was new. -- if (q->alias_dupes.insert(addr).second) -- query_func_info(addr, fi, q); -+ if (q->alias_dupes.insert(entrypc).second) -+ query_func_info(entrypc, fi, q); - } - - void -@@ -2059,7 +2059,7 @@ query_dwarf_inline_instance (Dwarf_Die * die, dwarf_query * q) - } - - static bool --is_filtered_func_exists (func_info_map_t filtered, func_info *fi) -+is_filtered_func_exists (func_info_map_t const& filtered, func_info *fi) - { - for (unsigned i = 0; i < filtered.size(); i++) - { -@@ -2135,16 +2135,22 @@ query_dwarf_func (Dwarf_Die * func, dwarf_query * q) - if ((em->e_machine == EM_PPC64) && ((em->e_flags & EF_PPC64_ABI) == 2) - && (q->dw.mod_info->sym_table)) - { -- set fis = q->dw.mod_info->sym_table->lookup_symbol(func.name); -+ /* The linkage name is the best match for the symbol table. */ -+ const string& linkage_name = dwarf_linkage_name(&func.die) -+ ?: dwarf_diename(&func.die) ?: 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)->addr; -+ func.entrypc = (*it)->entrypc; - if (is_filtered_func_exists(q->filtered_functions, &func)) - continue; - q->filtered_functions.push_back(func); - } - } -- else if (!func.entrypc && q->dw.function_entrypc (&entrypc)) -+ -+ /* If not ppc64 or not found in sym_table, try it directly. */ -+ if (!func.entrypc && q->dw.function_entrypc (&entrypc)) - { - func.entrypc = entrypc; - q->filtered_functions.push_back (func); -@@ -8201,7 +8207,7 @@ symbol_table::~symbol_table() - - void - symbol_table::add_symbol(const char *name, bool weak, bool descriptor, -- Dwarf_Addr addr, Dwarf_Addr* /*high_addr*/) -+ Dwarf_Addr addr, Dwarf_Addr entrypc) - { - /* Does the target architecture have function descriptors? - Then we want to filter them out. When seeing a symbol with a name -@@ -8224,6 +8230,7 @@ symbol_table::add_symbol(const char *name, bool weak, bool descriptor, - } - - func_info *fi = new func_info(); -+ fi->entrypc = entrypc; - fi->addr = addr; - fi->name = name; - fi->weak = weak; -@@ -8288,7 +8295,6 @@ symbol_table::reject_section(GElf_Word section) - enum info_status - symbol_table::get_from_elf() - { -- Dwarf_Addr high_addr = 0; - Dwfl_Module *mod = mod_info->mod; - int syments = dwfl_module_getsymtab(mod); - assert(syments); -@@ -8336,13 +8342,14 @@ symbol_table::get_from_elf() - * - * 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) -- addr += PPC64_LOCAL_ENTRY_OFFSET(sym.st_other); -+ entrypc += PPC64_LOCAL_ENTRY_OFFSET(sym.st_other); - - if (name && GELF_ST_TYPE(sym.st_info) == STT_FUNC) - add_symbol(name, (GELF_ST_BIND(sym.st_info) == STB_WEAK), -- reject, addr, &high_addr); -+ reject, addr, entrypc); - if (name && GELF_ST_TYPE(sym.st_info) == STT_OBJECT - && GELF_ST_BIND(sym.st_info) == STB_GLOBAL) - globals[name] = addr; -@@ -8486,12 +8493,13 @@ module_info::update_symtab(cu_function_cache_t *funcs) - continue; - } - -- // XXX We may want to make additional efforts to match mangled elf names -- // to dwarf too. MIPS_linkage_name can help, but that's sometimes -+ // We need to make additional efforts to match mangled elf names to dwarf -+ // too. DW_AT_linkage_name (or w/ MIPS) can help, but that's sometimes - // missing, so we may also need to try matching by address. See also the - // notes about _Z in dwflpp::iterate_over_functions(). -+ const string& name = dwarf_linkage_name(&func->second) ?: func->first; - -- set fis = sym_table->lookup_symbol(func->first); -+ set fis = sym_table->lookup_symbol(name); - if (fis.empty()) - continue; - diff --git a/SOURCES/rhbz1242368.patch b/SOURCES/rhbz1242368.patch new file mode 100644 index 0000000..2ec1be8 --- /dev/null +++ b/SOURCES/rhbz1242368.patch @@ -0,0 +1,338 @@ +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/rhbz1242992.patch b/SOURCES/rhbz1242992.patch deleted file mode 100644 index d01e26b..0000000 --- a/SOURCES/rhbz1242992.patch +++ /dev/null @@ -1,91 +0,0 @@ -commit 00ddbc6920530ed042260719e4faf690c2d38541 -Author: Lukas Berk -Date: Wed Jul 15 10:46:27 2015 -0400 - - Add ppc64le to java/Makefile.* - - java/Makefile.am - add JAVA_ARCH override for ppc64le - java/Makefile.in - add JAVA_ARCH override for ppc64le - -diff --git a/java/Makefile.am b/java/Makefile.am -index bd1efe8..2d5bba0 100644 ---- a/java/Makefile.am -+++ b/java/Makefile.am -@@ -10,6 +10,7 @@ override JAVA_ARCH:=$(JAVA_ARCH:i%86=i386) - override JAVA_ARCH:=$(JAVA_ARCH:sparcv9=sparc) - override JAVA_ARCH:=$(JAVA_ARCH:sparc64=sparcv9) - override JAVA_ARCH:=$(JAVA_ARCH:arm%=arm) -+override JAVA_ARCH:=$(JAVA_ARCH:powerpc64le%=ppc64le) - override JAVA_ARCH:=$(JAVA_ARCH:powerpc64%=ppc64) - - # XXX: perhaps autoconfigure the following? -diff --git a/java/Makefile.in b/java/Makefile.in -index 5e9f5a7..f98c79b 100644 ---- a/java/Makefile.in -+++ b/java/Makefile.in -@@ -725,6 +725,7 @@ override JAVA_ARCH:=$(JAVA_ARCH:i%86=i386) - override JAVA_ARCH:=$(JAVA_ARCH:sparcv9=sparc) - override JAVA_ARCH:=$(JAVA_ARCH:sparc64=sparcv9) - override JAVA_ARCH:=$(JAVA_ARCH:arm%=arm) -+override JAVA_ARCH:=$(JAVA_ARCH:powerpc64le%=ppc64le) - override JAVA_ARCH:=$(JAVA_ARCH:powerpc64%=ppc64) - @HAVE_JAVA_TRUE@$(HELPERSDT).class: $(srcdir)/$(HELPERSDT).java - @HAVE_JAVA_TRUE@ $(JAVAC) -d . $(srcdir)/$(HELPERSDT).java - -commit 5e5ec35cf1470bd52aca1bb73e76d205dcce01fc -Author: Lukas Berk -Date: Wed Jul 15 11:22:17 2015 -0400 - - systemtap.spec changes for ppc64{be,le} java helper library symlinking - - systemtap.spec - remove special clauses ppc64{be,le} linking - -diff --git a/systemtap.spec b/systemtap.spec -index 39f2130..23d1173 100644 ---- a/systemtap.spec -+++ b/systemtap.spec -@@ -775,12 +775,8 @@ exit 0 - - %triggerin runtime-java -- java-1.7.0-openjdk, java-1.6.0-openjdk - for f in %{_libexecdir}/systemtap/libHelperSDT_*.so; do -- %ifarch %{ix86} ppc64 ppc64le -- %ifarch ppc64 ppc64le -- arch=ppc64 -- %else -- arch=i386 -- %endif -+ %ifarch %{ix86} -+ arch=i386 - %else - arch=`basename $f | cut -f2 -d_ | cut -f1 -d.` - %endif -@@ -794,12 +790,8 @@ done - - %triggerun runtime-java -- java-1.7.0-openjdk, java-1.6.0-openjdk - for f in %{_libexecdir}/systemtap/libHelperSDT_*.so; do -- %ifarch %{ix86} ppc64 ppc64le -- %ifarch ppc64 ppc64le -- arch=ppc64 -- %else -- arch=i386 -- %endif -+ %ifarch %{ix86} -+ arch=i386 - %else - arch=`basename $f | cut -f2 -d_ | cut -f1 -d.` - %endif -@@ -812,12 +804,8 @@ done - %triggerpostun runtime-java -- java-1.7.0-openjdk, java-1.6.0-openjdk - # Restore links for any JDKs remaining after a package removal: - for f in %{_libexecdir}/systemtap/libHelperSDT_*.so; do -- %ifarch %{ix86} ppc64 ppc64le -- %ifarch ppc64 ppc64le -- arch=ppc64 -- %else -- arch=i386 -- %endif -+ %ifarch %{ix86} -+ arch=i386 - %else - arch=`basename $f | cut -f2 -d_ | cut -f1 -d.` - %endif diff --git a/SOURCES/rhbz1248159.patch b/SOURCES/rhbz1248159.patch deleted file mode 100644 index 57a3b0e..0000000 --- a/SOURCES/rhbz1248159.patch +++ /dev/null @@ -1,76 +0,0 @@ -commit 7cfb10eca050964b22bc8f25dd4682b409434078 -Author: Martin Cermak -Date: Fri Jul 31 17:40:18 2015 +0200 - - Fix PR18711 by updating the netfilter code for new rhel-7.2 kernels. - - * buildrun.cxx (compile_pass): Add new netfilter autoconf test. - * runtime/linux/autoconf-netfilter-313b.c: New autoconf test. - * tapset-netfilter.cxx: (emit_module_decls): Add support for new - netfilter code backported to kernel-3.10.0-284.el7. - -diff --git a/buildrun.cxx b/buildrun.cxx -index e4b2697..d7a431d 100644 ---- a/buildrun.cxx -+++ b/buildrun.cxx -@@ -385,6 +385,7 @@ compile_pass (systemtap_session& s) - output_autoconf(s, o, "autoconf-fs_supers-hlist.c", "STAPCONF_FS_SUPERS_HLIST", NULL); - output_autoconf(s, o, "autoconf-compat_sigaction.c", "STAPCONF_COMPAT_SIGACTION", NULL); - output_autoconf(s, o, "autoconf-netfilter.c", "STAPCONF_NETFILTER_V313", NULL); -+ output_autoconf(s, o, "autoconf-netfilter-313b.c", "STAPCONF_NETFILTER_V313B", NULL); - output_autoconf(s, o, "autoconf-netfilter-4_1.c", "STAPCONF_NETFILTER_V41", NULL); - output_autoconf(s, o, "autoconf-smpcall-5args.c", "STAPCONF_SMPCALL_5ARGS", NULL); - output_autoconf(s, o, "autoconf-smpcall-4args.c", "STAPCONF_SMPCALL_4ARGS", NULL); -diff --git a/runtime/linux/autoconf-netfilter-313b.c b/runtime/linux/autoconf-netfilter-313b.c -new file mode 100644 -index 0000000..3b18830 ---- /dev/null -+++ b/runtime/linux/autoconf-netfilter-313b.c -@@ -0,0 +1,22 @@ -+#include -+ -+// Similarly to autoconf-netfilter-4_1.c, this autoconf test covers -+// backport of kernel patch 238e54c9cb9385a1ba99e92801f3615a2fb398b6 -+// to kernel-3.10.0-284.el7 per rhbz1230935#c4 as patch no 119478. -+// This fixes PR18711. -+ -+unsigned int -+new_style_hook(const struct nf_hook_ops *ops, -+ struct sk_buff *skb, -+ const struct net_device *nf_in, -+ const struct net_device *nf_out, -+ const struct nf_hook_state *state) -+{ -+ (void) ops; (void) skb; (void) nf_in; (void) nf_out; (void) state; -+ return 0; -+} -+ -+struct nf_hook_ops netfilter_ops = { -+ .hook = new_style_hook -+}; -+ -diff --git a/tapset-netfilter.cxx b/tapset-netfilter.cxx -index 12df8d7..a820b8d 100644 ---- a/tapset-netfilter.cxx -+++ b/tapset-netfilter.cxx -@@ -277,6 +277,11 @@ netfilter_derived_probe_group::emit_module_decls (systemtap_session& s) - s.op->newline() << "(const struct nf_hook_ops *nf_ops, struct sk_buff *nf_skb, const struct net_device *nf_in, const struct net_device *nf_out, int (*nf_okfn)(struct sk_buff *))"; - s.op->newline() << "{"; - -+ s.op->newline() << "#elif defined(STAPCONF_NETFILTER_V313B)"; -+ -+ s.op->newline() << "(const struct nf_hook_ops *nf_ops, struct sk_buff *nf_skb, const struct net_device *nf_in, const struct net_device *nf_out, const struct nf_hook_state *nf_state)"; -+ s.op->newline() << "{"; -+ - s.op->newline() << "#elif LINUX_VERSION_CODE > KERNEL_VERSION(2,6,22)"; - - s.op->newline() << "(unsigned int nf_hooknum, struct sk_buff *nf_skb, const struct net_device *nf_in, const struct net_device *nf_out, int (*nf_okfn)(struct sk_buff *))"; -@@ -291,7 +296,7 @@ netfilter_derived_probe_group::emit_module_decls (systemtap_session& s) - s.op->newline(-1) << "#endif"; - s.op->newline(1) << "const struct stap_probe * const stp = & stap_probes[" << np->session_index << "];"; - s.op->newline() << "int nf_verdict = NF_ACCEPT;"; // default NF_ACCEPT, to be used by $verdict context var -- s.op->newline() << "#if defined(STAPCONF_NETFILTER_V313) || defined(STAPCONF_NETFILTER_V41)"; -+ s.op->newline() << "#if defined(STAPCONF_NETFILTER_V313) || defined(STAPCONF_NETFILTER_V313B) || defined(STAPCONF_NETFILTER_V41)"; - s.op->newline() << "unsigned int nf_hooknum = nf_ops->hooknum;"; - s.op->newline() << "#endif"; - s.op->newline() << "#ifdef STAPCONF_NETFILTER_V41"; diff --git a/SOURCES/rhbz1252436.patch b/SOURCES/rhbz1252436.patch deleted file mode 100644 index 4c6a4bb..0000000 --- a/SOURCES/rhbz1252436.patch +++ /dev/null @@ -1,68 +0,0 @@ -commit 86f726b7785a035a2d6bc9ec2642c46621587d23 -Author: David Smith -Date: Tue Jul 7 14:01:27 2015 -0500 - - Fixed PR18634 by getting timer probes to compile on rawhide. - - * runtime/linux/timer.c (_stp_hrtimer_init): If STAPCONF_HRTIMER_GET_RES - isn't defined, meaning hrtimer_get_res() doesn't exist, just use the - 'hrtimer_resolution' variable. - * buildrun.cxx (compile_pass): Add an export test for hrtimer_get_res(). - * translate.cxx (emit_common_header): Remove generated inclusion of - linux/hrtimer.h. - * runtime/linux/timer.h: Add inclusion of linux/hrtimer.h. - -diff --git a/buildrun.cxx b/buildrun.cxx -index 37b989f..e4b2697 100644 ---- a/buildrun.cxx -+++ b/buildrun.cxx -@@ -310,6 +310,7 @@ compile_pass (systemtap_session& s) - o << "$(STAPCONF_HEADER):" << endl; - o << "\t@echo -n > $@" << endl; - output_autoconf(s, o, "autoconf-hrtimer-rel.c", "STAPCONF_HRTIMER_REL", NULL); -+ output_exportconf(s, o, "hrtimer_get_res", "STAPCONF_HRTIMER_GET_RES"); - output_autoconf(s, o, "autoconf-generated-compile.c", "STAPCONF_GENERATED_COMPILE", NULL); - output_autoconf(s, o, "autoconf-hrtimer-getset-expires.c", "STAPCONF_HRTIMER_GETSET_EXPIRES", NULL); - output_autoconf(s, o, "autoconf-inode-private.c", "STAPCONF_INODE_PRIVATE", NULL); -diff --git a/runtime/linux/timer.c b/runtime/linux/timer.c -index 03d8f3f..f24a5ee 100644 ---- a/runtime/linux/timer.c -+++ b/runtime/linux/timer.c -@@ -15,9 +15,13 @@ - - static void _stp_hrtimer_init(void) - { -+#if defined(STAPCONF_HRTIMER_GET_RES) - struct timespec res; - hrtimer_get_res (CLOCK_MONOTONIC, &res); - stap_hrtimer_resolution = timespec_to_ns(&res); -+#else -+ stap_hrtimer_resolution = hrtimer_resolution; -+#endif - } - - -diff --git a/runtime/linux/timer.h b/runtime/linux/timer.h -index e9a5271..e7e0bb6 100644 ---- a/runtime/linux/timer.h -+++ b/runtime/linux/timer.h -@@ -15,6 +15,7 @@ - #if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,17) - #error "hrtimers not implemented" - #else /* kernel version >= 2.6.17 */ -+#include - - static unsigned long stap_hrtimer_resolution = 0; - -diff --git a/translate.cxx b/translate.cxx -index 390a73e..6e335b2 100644 ---- a/translate.cxx -+++ b/translate.cxx -@@ -1177,7 +1177,6 @@ c_unparser::emit_common_header () - o->newline(-1) << "}"; - - o->newline( 0) << "#ifdef STP_ON_THE_FLY_TIMER_ENABLE"; -- o->newline( 0) << "#include "; - o->newline( 0) << "#include \"timer.h\""; - o->newline( 0) << "static struct hrtimer module_refresh_timer;"; - diff --git a/SOURCES/rhbz1254856.patch b/SOURCES/rhbz1254856.patch deleted file mode 100644 index 2e38e1f..0000000 --- a/SOURCES/rhbz1254856.patch +++ /dev/null @@ -1,71 +0,0 @@ -commit 3fc11ed07bad37dfefc866e24d92682d7ef1d819 -Author: David Smith -Date: Thu Aug 20 11:27:53 2015 -0500 - - Fix PR18856 by making nfsd.close optional. - - * tapset/linux/nfsd.stp: Make nfsd.close optional in nfsd.entries (and add - it optionally to nfsd.return), since the underlying probe point no - longer exists in kernels 4.2+. Also add nfsd.proc.commit.return to - nfsd.proc.return (to match nfsd.proc). - * testsuite/buildok/nfsd-detailed.stp: Make nfsd.close tests optional. - -diff --git a/tapset/linux/nfsd.stp b/tapset/linux/nfsd.stp -index 7aebb9c..71956a1 100644 ---- a/tapset/linux/nfsd.stp -+++ b/tapset/linux/nfsd.stp -@@ -211,6 +211,7 @@ probe nfsd.proc.entries = nfsd.proc.lookup, - probe nfsd.proc.return = nfsd.proc.lookup.return, - nfsd.proc.read.return, - nfsd.proc.write.return, -+ nfsd.proc.commit.return, - nfsd.proc.remove.return, - nfsd.proc.rename.return, - nfsd.proc.create.return -@@ -1064,7 +1065,7 @@ probe nfsd.entries = nfsd.open, - nfsd.createv3, - nfsd.unlink, - nfsd.rename, -- nfsd.close -+ nfsd.close ? - {} - - probe nfsd.return = nfsd.open.return, -@@ -1075,7 +1076,8 @@ probe nfsd.return = nfsd.open.return, - nfsd.create.return, - nfsd.createv3.return, - nfsd.unlink.return, -- nfsd.rename.return -+ nfsd.rename.return, -+ nfsd.close.return ? - {} - - /** -@@ -1113,6 +1115,8 @@ probe nfsd.open.return = kernel.function("nfsd_open").return !, - * probe nfsd.close - NFS server closing a file for client - * - * @filename: file name -+ * -+ * This probe point does not exist in kernels starting with 4.2. - */ - probe nfsd.close = __nfsd.call_close ?, __nfsd.inlined_close ? - { -diff --git a/testsuite/buildok/nfsd-detailed.stp b/testsuite/buildok/nfsd-detailed.stp -index 627f3a2..f862079 100755 ---- a/testsuite/buildok/nfsd-detailed.stp -+++ b/testsuite/buildok/nfsd-detailed.stp -@@ -229,12 +229,12 @@ probe nfsd.open.return - # nfsd.close tests - # - --probe nfsd.close -+probe nfsd.close ? - { - printf("%s(%s)\n", name, argstr) - printf("%s\n", client_ip) - } --probe nfsd.close.return -+probe nfsd.close.return ? - { - printf("%s(%s)\n", name, retstr) - } diff --git a/SOURCES/rhbz1257399.patch b/SOURCES/rhbz1257399.patch deleted file mode 100644 index 7d8d815..0000000 --- a/SOURCES/rhbz1257399.patch +++ /dev/null @@ -1,530 +0,0 @@ -commit 0caa975190e4d2b19e7b65a0b23a7700522aa5d7 -Author: Frank Ch. Eigler -Date: Mon Aug 31 11:17:33 2015 -0400 - - PR18889 part: improve module-notification related debug tracing - - -DDEBUG_KPROBES -DDEBUG_SYMBOLS -DDEBUG_STP_ON_THE_FLY recommended. - -diff --git a/runtime/linux/kprobes.c b/runtime/linux/kprobes.c -index 47eb29a..54c224e 100644 ---- a/runtime/linux/kprobes.c -+++ b/runtime/linux/kprobes.c -@@ -567,6 +567,8 @@ stapkp_refresh(const char *modname, - { - size_t i; - -+ dbug_stapkp("refresh %lu probes with module %s\n", nprobes, modname ?: "?"); -+ - for (i = 0; i < nprobes; i++) { - - struct stap_dwarf_probe *sdp = &probes[i]; -diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c -index fe576c1..9ea2b5b 100644 ---- a/runtime/transport/symbols.c -+++ b/runtime/transport/symbols.c -@@ -1,7 +1,7 @@ --/* -*- linux-c -*- -+/* -*- linux-c -*- - * symbols.c - stp symbol and module functions - * -- * Copyright (C) Red Hat Inc, 2006-2012 -+ * Copyright (C) Red Hat Inc, 2006-2015 - * - * This file is part of systemtap, and is free software. You can - * redistribute it and/or modify it under the terms of the GNU General -@@ -121,10 +121,26 @@ static unsigned _stp_module_nsections (struct module_sect_attrs *attrs) - static int _stp_module_notifier (struct notifier_block * nb, - unsigned long val, void *data) - { -+ struct module *mod = data; -+ struct module_sect_attrs *attrs; -+ unsigned i, nsections; -+ -+ (void) attrs; -+ (void) i; -+ (void) nsections; -+ -+ if (!mod) { // so as to avoid null pointer checks later -+ WARN_ON (!mod); -+ return NOTIFY_DONE; -+ } -+ -+ dbug_sym(1, "module notify %lu %s attrs %p\n", -+ val, mod->name, mod->sect_attrs); -+ - /* Prior to 2.6.11, struct module contained a module_sections - attribute vector rather than module_sect_attrs. Prior to - 2.6.19, module_sect_attrs lacked a number-of-sections -- field. Past 3.8, MODULE_STATE_COMING is sent too early to -+ field. Past 3.8, MODULE_STATE_COMING is sent too early to - let us probe module init functions. - - Without CONFIG_KALLSYMS, we don't get any of the -@@ -132,11 +148,6 @@ static int _stp_module_notifier (struct notifier_block * nb, - that directly? */ - - #if defined(CONFIG_KALLSYMS) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,11) -- struct module *mod = data; -- struct module_sect_attrs *attrs; -- unsigned i, nsections; -- WARN_ON (!mod); -- - if (val == MODULE_STATE_COMING || - val == MODULE_STATE_LIVE) { - /* A module is arriving or has arrived. Register all -@@ -145,6 +156,7 @@ static int _stp_module_notifier (struct notifier_block * nb, - did the fishie go? */ - - attrs = mod->sect_attrs; -+ dbug_sym(1, "module_sect_attrs: %p\n", attrs); - if (attrs == NULL) // until add_sect_attrs(), may be zero - return NOTIFY_DONE; // remain ignorant - -@@ -153,7 +165,7 @@ static int _stp_module_notifier (struct notifier_block * nb, - int init_p = (strstr(attrs->attrs[i].name, "init.") != NULL); - int init_gone_p = (val == MODULE_STATE_LIVE); // likely already unloaded - -- _stp_kmodule_update_address(mod->name, -+ _stp_kmodule_update_address(mod->name, - attrs->attrs[i].name, - ((init_p && init_gone_p) ? 0 : attrs->attrs[i].address)); - } -@@ -161,7 +173,7 @@ static int _stp_module_notifier (struct notifier_block * nb, - /* Verify build-id. */ - if (_stp_kmodule_check (mod->name)) - _stp_kmodule_update_address(mod->name, NULL, 0); /* Pretend it was never here. */ -- } -+ } - else if (val == MODULE_STATE_GOING) { - /* Unregister all sections. */ - _stp_kmodule_update_address(mod->name, NULL, 0); - -commit 2278079efc01124dd509241f6c6eadbd6e19cb2a -Author: Frank Ch. Eigler -Date: Mon Aug 31 17:46:43 2015 -0400 - - PR18889 part: module-init notification via module_{load,free} tracepoints - - Investigating RHBZ1257399 et al., we found that module_notifier is - being called too early after kernel commit #4982223e51. This - precludes normal module section-address computation and thus kprobe - emplacement. This patch adds hooking into the module_{load,free} - tracepoints in parallel, because on some kernels (RHEL7.1.Z+) they - occur at just the right time. - - On the downside, on recent LKML kernels, attaching to those - tracepoints requires EXPORT_TRACEPOINT_SYMBOL_GPL's, so until that is - done (or another workaround made), LKML kernels will still miss out on - module-init probing. - -diff --git a/buildrun.cxx b/buildrun.cxx -index d7a431d..6d66b5a 100644 ---- a/buildrun.cxx -+++ b/buildrun.cxx -@@ -1,5 +1,5 @@ - // build/run probes --// Copyright (C) 2005-2014 Red Hat Inc. -+// Copyright (C) 2005-2015 Red Hat Inc. - // - // This file is part of systemtap, and is free software. You can - // redistribute it and/or modify it under the terms of the GNU General -@@ -377,8 +377,10 @@ compile_pass (systemtap_session& s) - output_exportconf(s, o, "proc_create_data", "STAPCONF_PROC_CREATE_DATA"); - output_exportconf(s, o, "PDE_DATA", "STAPCONF_PDE_DATA"); - output_autoconf(s, o, "autoconf-module-sect-attrs.c", "STAPCONF_MODULE_SECT_ATTRS", NULL); -- - output_autoconf(s, o, "autoconf-utrace-via-tracepoints.c", "STAPCONF_UTRACE_VIA_TRACEPOINTS", NULL); -+ output_autoconf(s, o, "autoconf-module-tracepoints.c", "STAPCONF_MODULE_TRACEPOINT", NULL); -+ output_exportconf(s, o, "__tracepoint_module_load", "STAPCONF_MODULE_TRACEPOINT_EXPORT_LOAD"); -+ output_exportconf(s, o, "__tracepoint_module_free", "STAPCONF_MODULE_TRACEPOINT_EXPORT_FREE"); - output_autoconf(s, o, "autoconf-task_work-struct.c", "STAPCONF_TASK_WORK_STRUCT", NULL); - output_autoconf(s, o, "autoconf-vm-area-pte.c", "STAPCONF_VM_AREA_PTE", NULL); - output_autoconf(s, o, "autoconf-relay-umode_t.c", "STAPCONF_RELAY_UMODE_T", NULL); -diff --git a/runtime/linux/autoconf-module-tracepoints.c b/runtime/linux/autoconf-module-tracepoints.c -new file mode 100644 -index 0000000..77b938e ---- /dev/null -+++ b/runtime/linux/autoconf-module-tracepoints.c -@@ -0,0 +1,31 @@ -+#include -+#include -+ -+// NB: in kernels which do have the requisite pieces, just unconfigured, then -+// everything below will compile just fine, only returning ENOSYS at runtime. -+// To get the compile-time error that autoconf needs, check it directly: -+#ifndef CONFIG_TRACEPOINTS -+#error "CONFIG_TRACEPOINTS is not enabled" -+#endif -+ -+// presuming void *data-parametrized tracepoint callback api -+ -+void __module_load(void *cb_data, struct module* mod) -+{ -+ (void) cb_data; -+ (void) mod; -+ return; -+} -+ -+void __module_free(void *cb_data, struct module* mod) -+{ -+ (void) cb_data; -+ (void) mod; -+ return; -+} -+ -+void __autoconf_func(void) -+{ -+ (void) register_trace_module_load(__module_load, NULL); -+ (void) register_trace_module_free(__module_free, NULL); -+} -diff --git a/runtime/transport/symbols.c b/runtime/transport/symbols.c -index 9ea2b5b..4266e5d 100644 ---- a/runtime/transport/symbols.c -+++ b/runtime/transport/symbols.c -@@ -125,6 +125,7 @@ static int _stp_module_notifier (struct notifier_block * nb, - struct module_sect_attrs *attrs; - unsigned i, nsections; - -+ (void) nb; - (void) attrs; - (void) i; - (void) nsections; -@@ -191,6 +192,21 @@ static int _stp_module_notifier (struct notifier_block * nb, - return NOTIFY_DONE; - } - -+ -+#ifdef STAPCONF_MODULE_TRACEPOINT -+/* We just delegate to the canonical notifier function */ -+static void _stp_module_load_tp(void *data, struct module* mod) -+{ -+ (void) _stp_module_notifier (NULL, MODULE_STATE_COMING, mod); -+ -+} -+static void _stp_module_free_tp(void *data, struct module* mod) -+{ -+ (void) _stp_module_notifier (NULL, MODULE_STATE_GOING, mod); -+} -+#endif -+ -+ - static int _stp_module_update_self (void) - { - /* Only bother if we need unwinding and have module_sect_attrs. */ -diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c -index 54e9b41..e069a3d 100644 ---- a/runtime/transport/transport.c -+++ b/runtime/transport/transport.c -@@ -21,6 +21,23 @@ - #include - #include - #include "../uidgid_compatibility.h" -+#ifdef STAPCONF_MODULE_TRACEPOINT -+#include -+#endif -+ -+/* PR18889: After 3.17, commit #de7b2973903c6, tracepoints are -+ attached by symbol-address rather than by name string. That means -+ they must be EXPORT_TRACEPOINT_SYMBOL_GPL'd for a tracepoint -+ [un]register operation. On RHEL7 kernels with out that commit -+ backported, we can do a tracepoint attach even without the exports. */ -+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) -+#if defined(STAPCONF_MODULE_TRACEPOINT) && defined(STAPCONF_MODULE_TRACEPOINT_EXPORT_LOAD) && defined(STAPCONF_MODULE_TRACEPOINT_EXPORT_FREE) -+#define STAP_USE_MODULE_TRACEPOINTS -+#endif -+#elif defined(STAPCONF_MODULE_TRACEPOINT) -+#define STAP_USE_MODULE_TRACEPOINTS -+#endif -+ - - static int _stp_exit_flag = 0; - -@@ -83,6 +100,11 @@ static void systemtap_module_exit(void); - static int systemtap_module_init(void); - - static int _stp_module_notifier_active = 0; -+#ifdef STAPCONF_MODULE_TRACEPOINT -+/* callbacks in runtime/transport/symbols.c */ -+static void _stp_module_load_tp(void *data, struct module* mod); -+static void _stp_module_free_tp(void *data, struct module* mod); -+#endif - static int _stp_module_notifier (struct notifier_block * nb, - unsigned long val, void *data); - static struct notifier_block _stp_module_notifier_nb = { -@@ -158,11 +180,30 @@ static void _stp_handle_start(struct _stp_msg_start *st) - failed: something nasty has happened, and - we want no further probing started. PR16766 */ - if (!_stp_module_notifier_active) { -- int rc = register_module_notifier(& _stp_module_notifier_nb); -- if (rc == 0) -- _stp_module_notifier_active = 1; -- else -- _stp_warn ("Cannot register module notifier (%d)\n", rc); -+#ifdef STAP_USE_MODULE_TRACEPOINTS -+ int rc0 = register_trace_module_load (& _stp_module_load_tp, NULL); -+ if (rc0) -+ _stp_warn ("Cannot register module load tracepoint (%d)\n", rc0); -+ else { -+ int rc1 = register_trace_module_free (& _stp_module_free_tp, NULL); -+ if (rc1) { -+ _stp_warn ("Cannot register module free tracepoint (%d)\n", rc1); -+ unregister_trace_module_load(& _stp_module_load_tp, NULL); -+ } else { -+#endif -+ int rc = register_module_notifier(& _stp_module_notifier_nb); -+ if (rc == 0) -+ _stp_module_notifier_active = 1; -+ else { -+ _stp_warn ("Cannot register module notifier (%d)\n", rc); -+#ifdef STAP_USE_MODULE_TRACEPOINTS -+ unregister_trace_module_load(& _stp_module_load_tp, NULL); -+ unregister_trace_module_free(& _stp_module_free_tp, NULL); -+ -+ } -+ } -+#endif -+ } - } - } - -@@ -198,7 +239,12 @@ static void _stp_cleanup_and_exit(int send_exit) - - /* Unregister the module notifier. */ - if (_stp_module_notifier_active) { -- int rc = unregister_module_notifier(& _stp_module_notifier_nb); -+ int rc; -+#ifdef STAP_USE_MODULE_TRACEPOINTS -+ unregister_trace_module_load(& _stp_module_load_tp, NULL); -+ unregister_trace_module_free(& _stp_module_free_tp, NULL); -+#endif -+ rc = unregister_module_notifier(& _stp_module_notifier_nb); - if (rc) - _stp_warn("module_notifier unregister error %d", rc); - _stp_module_notifier_active = 0; - -commit 2e67c14dad1c661d2ce0b0ed218b371c1af218ba -Author: Frank Ch. Eigler -Date: Wed Sep 2 11:16:46 2015 -0400 - - PR18889: switch to STP_TRACEPOINT* frontend for kernel tracepoint registration - - jistone kindly reminded that the runtime/stp_tracepoint.[ch] machinery - allows us to attach to kernel tracepoints, whether on string- or - tp*-based kernel APIs, and whether or not the tp* objects are - EXPORT_TRACEPOINT_SYMBOL_GPL'd. Let's use those; presto we get - module-init probing back on kernels oldish and newish. - -diff --git a/buildrun.cxx b/buildrun.cxx -index 6d66b5a..2ca5933 100644 ---- a/buildrun.cxx -+++ b/buildrun.cxx -@@ -379,8 +379,6 @@ compile_pass (systemtap_session& s) - output_autoconf(s, o, "autoconf-module-sect-attrs.c", "STAPCONF_MODULE_SECT_ATTRS", NULL); - output_autoconf(s, o, "autoconf-utrace-via-tracepoints.c", "STAPCONF_UTRACE_VIA_TRACEPOINTS", NULL); - output_autoconf(s, o, "autoconf-module-tracepoints.c", "STAPCONF_MODULE_TRACEPOINT", NULL); -- output_exportconf(s, o, "__tracepoint_module_load", "STAPCONF_MODULE_TRACEPOINT_EXPORT_LOAD"); -- output_exportconf(s, o, "__tracepoint_module_free", "STAPCONF_MODULE_TRACEPOINT_EXPORT_FREE"); - output_autoconf(s, o, "autoconf-task_work-struct.c", "STAPCONF_TASK_WORK_STRUCT", NULL); - output_autoconf(s, o, "autoconf-vm-area-pte.c", "STAPCONF_VM_AREA_PTE", NULL); - output_autoconf(s, o, "autoconf-relay-umode_t.c", "STAPCONF_RELAY_UMODE_T", NULL); -diff --git a/runtime/transport/transport.c b/runtime/transport/transport.c -index e069a3d..db7de46 100644 ---- a/runtime/transport/transport.c -+++ b/runtime/transport/transport.c -@@ -1,8 +1,8 @@ --/* -*- linux-c -*- -+/* -*- linux-c -*- - * transport.c - stp transport functions - * - * Copyright (C) IBM Corporation, 2005 -- * Copyright (C) Red Hat Inc, 2005-2014 -+ * Copyright (C) Red Hat Inc, 2005-2015 - * Copyright (C) Intel Corporation, 2006 - * - * This file is part of systemtap, and is free software. You can -@@ -23,19 +23,7 @@ - #include "../uidgid_compatibility.h" - #ifdef STAPCONF_MODULE_TRACEPOINT - #include --#endif -- --/* PR18889: After 3.17, commit #de7b2973903c6, tracepoints are -- attached by symbol-address rather than by name string. That means -- they must be EXPORT_TRACEPOINT_SYMBOL_GPL'd for a tracepoint -- [un]register operation. On RHEL7 kernels with out that commit -- backported, we can do a tracepoint attach even without the exports. */ --#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,17,0) --#if defined(STAPCONF_MODULE_TRACEPOINT) && defined(STAPCONF_MODULE_TRACEPOINT_EXPORT_LOAD) && defined(STAPCONF_MODULE_TRACEPOINT_EXPORT_FREE) --#define STAP_USE_MODULE_TRACEPOINTS --#endif --#elif defined(STAPCONF_MODULE_TRACEPOINT) --#define STAP_USE_MODULE_TRACEPOINTS -+#include "../linux/stp_tracepoint.h" - #endif - - -@@ -149,7 +137,7 @@ static void _stp_handle_start(struct _stp_msg_start *st) - // protect against excessive or premature startup - handle_startup = (! _stp_start_called && ! _stp_exit_called); - _stp_start_called = 1; -- -+ - if (handle_startup) { - dbug_trans(1, "stp_handle_start\n"); - -@@ -180,15 +168,15 @@ static void _stp_handle_start(struct _stp_msg_start *st) - failed: something nasty has happened, and - we want no further probing started. PR16766 */ - if (!_stp_module_notifier_active) { --#ifdef STAP_USE_MODULE_TRACEPOINTS -- int rc0 = register_trace_module_load (& _stp_module_load_tp, NULL); -+#ifdef STAPCONF_MODULE_TRACEPOINT -+ int rc0 = STP_TRACE_REGISTER(module_load, & _stp_module_load_tp); - if (rc0) - _stp_warn ("Cannot register module load tracepoint (%d)\n", rc0); - else { -- int rc1 = register_trace_module_free (& _stp_module_free_tp, NULL); -+ int rc1 = STP_TRACE_REGISTER(module_free, & _stp_module_free_tp); - if (rc1) { - _stp_warn ("Cannot register module free tracepoint (%d)\n", rc1); -- unregister_trace_module_load(& _stp_module_load_tp, NULL); -+ STP_TRACE_UNREGISTER(module_load, & _stp_module_load_tp); - } else { - #endif - int rc = register_module_notifier(& _stp_module_notifier_nb); -@@ -196,10 +184,9 @@ static void _stp_handle_start(struct _stp_msg_start *st) - _stp_module_notifier_active = 1; - else { - _stp_warn ("Cannot register module notifier (%d)\n", rc); --#ifdef STAP_USE_MODULE_TRACEPOINTS -- unregister_trace_module_load(& _stp_module_load_tp, NULL); -- unregister_trace_module_free(& _stp_module_free_tp, NULL); -- -+#ifdef STAPCONF_MODULE_TRACEPOINT -+ STP_TRACE_UNREGISTER(module_load, & _stp_module_load_tp); -+ STP_TRACE_UNREGISTER(module_free, & _stp_module_free_tp); - } - } - #endif -@@ -240,9 +227,9 @@ static void _stp_cleanup_and_exit(int send_exit) - /* Unregister the module notifier. */ - if (_stp_module_notifier_active) { - int rc; --#ifdef STAP_USE_MODULE_TRACEPOINTS -- unregister_trace_module_load(& _stp_module_load_tp, NULL); -- unregister_trace_module_free(& _stp_module_free_tp, NULL); -+#ifdef STAPCONF_MODULE_TRACEPOINT -+ STP_TRACE_UNREGISTER(module_load, & _stp_module_load_tp); -+ STP_TRACE_UNREGISTER(module_free, & _stp_module_free_tp); - #endif - rc = unregister_module_notifier(& _stp_module_notifier_nb); - if (rc) -@@ -380,7 +367,7 @@ static void _stp_ctl_work_callback(unsigned long val) - * _stp_transport_close - close ctl and relayfs channels - * - * This is called automatically when the module is unloaded. -- * -+ * - */ - static void _stp_transport_close(void) - { -@@ -397,7 +384,7 @@ static void _stp_transport_close(void) - - /** - * _stp_transport_init() is called from the module initialization. -- * It does the bare minimum to exchange commands with staprun -+ * It does the bare minimum to exchange commands with staprun - */ - static int _stp_transport_init(void) - { -@@ -657,7 +644,7 @@ static struct dentry *_stp_get_module_dir(void) - static int _stp_transport_fs_init(const char *module_name) - { - struct dentry *root_dir; -- -+ - dbug_trans(1, "entry\n"); - if (module_name == NULL) - return -1; - -commit 578f5f6f6792fc92d74539a927cd85de5bcbb4dd -Author: Frank Ch. Eigler -Date: Wed Sep 2 11:52:31 2015 -0400 - - PR18889 testing: already done by modules_out_of_tree.exp - - Ditch bz6503, given that it wasn't reliable. - -diff --git a/testsuite/systemtap.base/bz6503.exp b/testsuite/systemtap.base/bz6503.exp -deleted file mode 100644 -index 5d4d2d0..0000000 ---- a/testsuite/systemtap.base/bz6503.exp -+++ /dev/null -@@ -1,55 +0,0 @@ --# Note that this test is *really* testing the bug fix for pr6503: --# permit probes on module .init and __exit functions --# --# --# Not BZ6503: --# ypserve does not work --# --# --# Unfortunately, PR17249 indicates that module-init probes --# have subsequently broken (due to kernel notification timing --# changes). --# -- --set test bz6503 -- --if {! [installtest_p]} { -- untested "$test" -- return --} -- --# If we aren't root, make sure the test still succeeds. --set effective_pid [exec /usr/bin/id -u] --if {$effective_pid != 0} { -- set root_cmd "sudo " --} else { -- set root_cmd "" --} -- -- --# jffs2/ext2/fat/vfat should cover a span of kernels. --# --# Note that this test might fail if there is a filesystem of one of --# these types already mounted. The filesystem mount will be --# unaffected (since the module can't be removed). --spawn stap -t $srcdir/$subdir/bz6503.stp -c "( ($root_cmd /sbin/modprobe jffs2; $root_cmd /sbin/modprobe ext2; $root_cmd /sbin/modprobe fat; $root_cmd /sbin/modprobe vfat); wait; ($root_cmd /sbin/rmmod jffs2; $root_cmd /sbin/rmmod ext2; $root_cmd /sbin/rmmod vfat; $root_cmd /sbin/rmmod fat); wait) 2>/dev/null" -- --set ok 0 --set ko 0 --expect { -- -timeout 60 -- timeout { fail "$test (timeout)" } -- -re {^-----[^\r\n]*\r\n} { exp_continue } -- -re {^module[^\r\n]*hits:[^\r\n]*\r\n} { incr ok; exp_continue } -- -re {^WARNING:[\r\n]*\r\n} { incr ko; exp_continue } -- -re {^ERROR:[\r\n]*\r\n} { incr ko; exp_continue } -- eof { } --} --catch { close} ; catch { wait } -- --# Mark kernels without module refresh support as xfail --if {![module_refresh_p]} { setup_xfail *-*-* } -- --if {$ok > 0 && $ko == 0} then { pass "$test $ok" } else { fail "$test $ok $ko"} -- -- -diff --git a/testsuite/systemtap.base/bz6503.stp b/testsuite/systemtap.base/bz6503.stp -deleted file mode 100644 -index 409149f..0000000 ---- a/testsuite/systemtap.base/bz6503.stp -+++ /dev/null -@@ -1,5 +0,0 @@ --probe module("jffs2").function("*").call ?, -- module("ext2").function("*").call ?, -- module("fat").function("*").call ?, -- module("vfat").function("*").call ?, -- never { } diff --git a/SOURCES/rhbz1269062.patch b/SOURCES/rhbz1269062.patch new file mode 100644 index 0000000..40fc02a --- /dev/null +++ b/SOURCES/rhbz1269062.patch @@ -0,0 +1,22 @@ +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 new file mode 100644 index 0000000..e758265 --- /dev/null +++ b/SOURCES/rhbz1312169.patch @@ -0,0 +1,33 @@ +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 new file mode 100644 index 0000000..f278c90 --- /dev/null +++ b/SOURCES/rhbz1337416.patch @@ -0,0 +1,578 @@ +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 new file mode 100644 index 0000000..8a74218 --- /dev/null +++ b/SOURCES/rhbz1346112.patch @@ -0,0 +1,62 @@ +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 new file mode 100644 index 0000000..15052ec --- /dev/null +++ b/SOURCES/rhbz1365550.patch @@ -0,0 +1,52 @@ +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 new file mode 100644 index 0000000..bbe92e6 --- /dev/null +++ b/SOURCES/rhbz1376515.patch @@ -0,0 +1,281 @@ +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 034da44..01f3a55 100644 --- a/SPECS/systemtap.spec +++ b/SPECS/systemtap.spec @@ -1,9 +1,12 @@ %{!?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 %{!?with_crash: %global with_crash 0} @@ -34,6 +37,7 @@ %{!?with_openssl: %global with_openssl 0} %endif %{!?with_pyparsing: %global with_pyparsing 0%{?fedora} >= 18 || 0%{?rhel} >= 7} +%{!?with_python3: %global with_python3 0%{?fedora} >= 23} %ifarch ppc64le aarch64 %global with_virthost 0 @@ -60,8 +64,8 @@ %define dracutstap %{_prefix}/lib/dracut/modules.d/99stap Name: systemtap -Version: 2.8 -Release: 10%{?dist} +Version: 3.0 +Release: 7%{?dist} # for version, see also configure.ac @@ -108,6 +112,9 @@ BuildRequires: libselinux-devel %if %{with_sqlite} BuildRequires: sqlite-devel %endif +%if %{with_monitor} +BuildRequires: json-c-devel ncurses-devel +%endif # Needed for libstd++ < 4.0, without %if %{with_boost} BuildRequires: boost-devel @@ -127,15 +134,20 @@ BuildRequires: m4 BuildRequires: elfutils-devel >= %{elfutils_version} %endif %if %{with_docs} -BuildRequires: /usr/bin/latex /usr/bin/dvips /usr/bin/ps2pdf latex2html +BuildRequires: /usr/bin/latex /usr/bin/dvips /usr/bin/ps2pdf %if 0%{?fedora} >= 18 || 0%{?rhel} >= 7 -BuildRequires: tex(fullpage.sty) tex(fancybox.sty) tex(bchr7t.tfm) +BuildRequires: tex(fullpage.sty) tex(fancybox.sty) tex(bchr7t.tfm) tex(graphicx.sty) %endif +# For the html.sty mentioned in the .tex files, even though latex2html is +# not run during the build, only during manual scripts/update-docs runs: +BuildRequires: latex2html +%if %{with_htmldocs} # On F10, xmlto's pdf support was broken off into a sub-package, # called 'xmlto-tex'. To avoid a specific F10 BuildReq, we'll do a # file-based buildreq on '/usr/share/xmlto/format/fo/pdf'. BuildRequires: xmlto /usr/share/xmlto/format/fo/pdf %endif +%endif %if %{with_emacsvim} BuildRequires: emacs %endif @@ -146,14 +158,18 @@ BuildRequires: jpackage-utils java-devel BuildRequires: libvirt-devel >= 1.0.2 BuildRequires: libxml2-devel %endif +BuildRequires: readline-devel +%if 0%{?rhel} <= 5 +BuildRequires: ncurses-devel +%endif -Patch1: rhbz1237098.patch -Patch2: june-robust.patch -Patch3: rhbz1242992.patch -Patch4: rhbz1248159.patch -Patch5: rhbz1252436.patch -Patch6: rhbz1254856.patch -Patch7: rhbz1257399.patch +Patch10: rhbz1242368.patch +Patch11: rhbz1346112.patch +Patch12: rhbz1269062.patch +Patch13: rhbz1337416.patch +Patch14: rhbz1365550.patch +Patch15: rhbz1312169.patch +Patch16: rhbz1376515.patch # Install requirements Requires: systemtap-client = %{version}-%{release} @@ -272,8 +288,12 @@ Group: Development/System License: GPLv2+ and Public Domain URL: http://sourceware.org/systemtap/ %if %{with_pyparsing} +%if %{with_python3} +Requires: python3-pyparsing +%else Requires: pyparsing %endif +%endif %description sdt-devel This package includes the header file used for static @@ -299,8 +319,12 @@ Requires: strace # 'nmap-ncat'). So, we'll do a file-based require. Requires: /usr/bin/nc %ifnarch ia64 ppc64le aarch64 +%if 0%{?fedora} >= 21 || 0%{?rhel} >= 8 +# no prelink +%else Requires: prelink %endif +%endif # testsuite/systemtap.server/client.exp needs avahi Requires: avahi %if %{with_crash} @@ -318,6 +342,10 @@ Requires: /usr/lib/libc.so %if 0%{?fedora} >= 18 Requires: stress %endif +# The following "meta" files for the systemtap examples run "perf": +# testsuite/systemtap.examples/hw_watch_addr.meta +# testsuite/systemtap.examples/memory/hw_watch_sym.meta +Requires: perf %description testsuite This package includes the dejagnu-based systemtap stress self-testing @@ -382,13 +410,6 @@ systemtap-runtime-virthost machine to execute systemtap scripts. %prep %setup -q %{?setup_elfutils} -%patch1 -p1 -%patch2 -p1 -%patch3 -p1 -%patch4 -p1 -%patch5 -p1 -%patch6 -p1 -%patch7 -p1 %if %{with_bundled_elfutils} cd elfutils-%{elfutils_version} @@ -400,6 +421,14 @@ find . \( -name configure -o -name config.h.in \) -print | xargs touch cd .. %endif +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 +%patch15 -p1 +%patch16 -p1 + %build %if %{with_bundled_elfutils} @@ -446,7 +475,11 @@ cd .. %endif %if %{with_docs} -%global docs_config --enable-docs +%if %{with_htmldocs} +%global docs_config --enable-docs --enable-htmldocs +%else +%global docs_config --enable-docs --disable-htmldocs +%endif %else %global docs_config --disable-docs %endif @@ -474,10 +507,18 @@ cd .. %if %{with_dracut} %global dracut_config --with-dracutstap=%{dracutstap} %else -%global dracut_config +%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} --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} --disable-silent-rules --with-extra-version="rpm %{version}-%{release}" make %{?_smp_mflags} %if %{with_emacsvim} @@ -488,6 +529,11 @@ make %{?_smp_mflags} rm -rf ${RPM_BUILD_ROOT} make DESTDIR=$RPM_BUILD_ROOT install %find_lang %{name} +for dir in $(ls -1d $RPM_BUILD_ROOT%{_mandir}/{??,??_??}) ; do + dir=$(echo $dir | sed -e "s|^$RPM_BUILD_ROOT||") + lang=$(basename $dir) + 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 @@ -495,8 +541,8 @@ make DESTDIR=$RPM_BUILD_ROOT install # %doc directive. mv $RPM_BUILD_ROOT%{_datadir}/doc/systemtap/examples examples -# Fix paths in the example & testsuite scripts -find examples testsuite -type f -name '*.stp' -print0 | xargs -0 sed -i -r -e '1s@^#!.+stap@#!%{_bindir}/stap@' +# Fix paths in the example scripts. +find 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 @@ -520,9 +566,11 @@ cp -rp testsuite $RPM_BUILD_ROOT%{_datadir}/systemtap # %doc directive. mkdir docs.installed mv $RPM_BUILD_ROOT%{_datadir}/doc/systemtap/*.pdf docs.installed/ +%if %{with_htmldocs} mv $RPM_BUILD_ROOT%{_datadir}/doc/systemtap/tapsets docs.installed/ mv $RPM_BUILD_ROOT%{_datadir}/doc/systemtap/SystemTap_Beginners_Guide docs.installed/ %endif +%endif mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/stap-server mkdir -p $RPM_BUILD_ROOT%{_localstatedir}/lib/stap-server @@ -631,11 +679,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 @@ -780,7 +823,7 @@ exit 0 %triggerin runtime-java -- java-1.8.0-openjdk, java-1.7.0-openjdk, java-1.6.0-openjdk for f in %{_libexecdir}/systemtap/libHelperSDT_*.so; do %ifarch %{ix86} - arch=i386 + arch=i386 %else arch=`basename $f | cut -f2 -d_ | cut -f1 -d.` %endif @@ -795,7 +838,7 @@ done %triggerun runtime-java -- java-1.8.0-openjdk, java-1.7.0-openjdk, java-1.6.0-openjdk for f in %{_libexecdir}/systemtap/libHelperSDT_*.so; do %ifarch %{ix86} - arch=i386 + arch=i386 %else arch=`basename $f | cut -f2 -d_ | cut -f1 -d.` %endif @@ -809,7 +852,7 @@ done # Restore links for any JDKs remaining after a package removal: for f in %{_libexecdir}/systemtap/libHelperSDT_*.so; do %ifarch %{ix86} - arch=i386 + arch=i386 %else arch=`basename $f | cut -f2 -d_ | cut -f1 -d.` %endif @@ -933,9 +976,11 @@ done %license COPYING %if %{with_docs} %doc docs.installed/*.pdf +%if %{with_htmldocs} %doc docs.installed/tapsets/*.html %doc docs.installed/SystemTap_Beginners_Guide %endif +%endif %{_bindir}/stap %{_bindir}/stap-prep %{_bindir}/stap-report @@ -1022,6 +1067,29 @@ done # http://sourceware.org/systemtap/wiki/SystemTapReleases %changelog +* Mon Sep 19 2016 Frank Ch. Eigler - 3.0-7 +- rhbz1376515 ppc64le probe point / parameter value fix + +* Wed Aug 24 2016 Frank Ch. Eigler - 3.0-6 +- rhbz1346112 delay tls cert creation redux + +* Thu Aug 11 2016 Frank Ch. Eigler - 3.0-5 +- rhbz1312169 stap-prep debuginfo-install improvement + +* Tue Aug 09 2016 Frank Ch. Eigler - 3.0-4 +- rhbz1365550 PR19874 alarm(60) in staprun system() + +* Thu Jul 21 2016 Frank Ch. Eigler - 3.0-3 +- rhbz1346112 delay tls cert creation +- rhbz1269062 null elevator +- rhbz1337416 'count' tapset variable - autocast/@defined + +* Wed May 04 2016 Frank Ch. Eigler - 3.0-2 +- 4 upstream patches for kernel lockdep hygiene, bz1242368 + +* Tue May 03 2016 Frank Ch. Eigler - 3.0-1 +- Upstream release. + * Wed Sep 02 2015 Frank Ch. Eigler - 2.8-10 - rhbz1257399: module-init probes