static void stapkp_batch_unregister_probes(struct stap_kprobe_probe *probes, size_t nprobes) { size_t i, n; n = stapkp_collect_registered_probes(probes, nprobes, COLLECT_KPROBES); unregister_kprobes((struct kprobe **)stap_unreg_kprobes, n); dbug_stapkp_cond(n > 0, "-kprobe * %zd\n", n); n = stapkp_collect_registered_probes(probes, nprobes, COLLECT_KRETPROBES); unregister_kretprobes((struct kretprobe **)stap_unreg_kprobes, n); dbug_stapkp_cond(n > 0, "-kretprobe * %zd\n", n); #ifdef __ia64__ n = stapkp_collect_registered_probes(probes, nprobes, COLLECT_DUMMYS); unregister_kprobes((struct kprobe **)stap_unreg_kprobes, n); dbug_stapkp_cond(n > 0, "-kprobe * %zd\n", n); #endif // Now for all of those we just unregistered, we need to update registered_p // and account for (and possibly report) missed hits. for (i = 0; i < nprobes; i++) { struct stap_kprobe_probe *skp = &probes[i]; if (!skp->registered_p) continue; skp->registered_p = 0; stapkp_add_missed(skp); #if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) if (skp->symbol_name != NULL) { if (skp->return_p) { if (skp->kprobe->u.krp.kp.symbol_name != NULL) kfree(skp->kprobe->u.krp.kp.symbol_name); } else { if (skp->kprobe->u.kp.symbol_name != NULL) kfree(skp->kprobe->u.kp.symbol_name); } } #endif // PR16861: kprobes may have left some things in the k[ret]probe struct. // Let's reset it to be sure it's safe for re-use. memset(skp->kprobe, 0, sizeof(struct stap_kprobe)); } }
static void stapkp_batch_unregister_probes(struct stap_dwarf_probe *probes, size_t nprobes) { size_t i, n; n = stapkp_collect_registered_probes(probes, nprobes, COLLECT_KPROBES); unregister_kprobes((struct kprobe **)stap_unreg_kprobes, n); dbug_stapkp_cond(n > 0, "-kprobe * %zd\n", n); n = stapkp_collect_registered_probes(probes, nprobes, COLLECT_KRETPROBES); unregister_kretprobes((struct kretprobe **)stap_unreg_kprobes, n); dbug_stapkp_cond(n > 0, "-kretprobe * %zd\n", n); #ifdef __ia64__ n = stapkp_collect_registered_probes(probes, nprobes, COLLECT_DUMMYS); unregister_kprobes((struct kprobe **)stap_unreg_kprobes, n); dbug_stapkp_cond(n > 0, "-kprobe * %zd\n", n); #endif // Now for all of those we just unregistered, we need to update registered_p // and account for (and possibly report) missed hits. for (i = 0; i < nprobes; i++) { struct stap_dwarf_probe *sdp = &probes[i]; if (!sdp->registered_p) continue; sdp->registered_p = 0; stapkp_add_missed(sdp); // PR16861: kprobes may have left some things in the k[ret]probe struct. // Let's reset it to be sure it's safe for re-use. memset(sdp->kprobe, 0, sizeof(struct stap_dwarf_kprobe)); } }
static int test_kprobes(void) { int ret; struct kprobe *kps[2] = {&kp, &kp2}; /* */ kp.addr = NULL; kp.flags = 0; ret = register_kprobes(kps, 2); if (ret < 0) { printk(KERN_ERR "Kprobe smoke test failed: " "register_kprobes returned %d\n", ret); return ret; } preh_val = 0; posth_val = 0; ret = target(rand1); if (preh_val == 0) { printk(KERN_ERR "Kprobe smoke test failed: " "kprobe pre_handler not called\n"); handler_errors++; } if (posth_val == 0) { printk(KERN_ERR "Kprobe smoke test failed: " "kprobe post_handler not called\n"); handler_errors++; } preh_val = 0; posth_val = 0; ret = target2(rand1); if (preh_val == 0) { printk(KERN_ERR "Kprobe smoke test failed: " "kprobe pre_handler2 not called\n"); handler_errors++; } if (posth_val == 0) { printk(KERN_ERR "Kprobe smoke test failed: " "kprobe post_handler2 not called\n"); handler_errors++; } unregister_kprobes(kps, 2); return 0; }