static int stapkp_prepare_kprobe(struct stap_dwarf_probe *sdp) { struct kprobe *kp = &sdp->kprobe->u.kp; unsigned long addr = stapkp_relocate_addr(sdp); if (addr == 0) return 1; kp->addr = (void *) addr; kp->pre_handler = &enter_kprobe_probe; #ifdef __ia64__ // PR6028 sdp->kprobe->dummy.addr = kp->addr; sdp->kprobe->dummy.pre_handler = NULL; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) if (!sdp->probe->cond_enabled) { kp->flags |= KPROBE_FLAG_DISABLED; dbug_otf("registering as disabled (kprobe) pidx %zu\n", sdp->probe->index); } #endif return 0; }
static int stapkp_prepare_kretprobe(struct stap_kprobe_probe *skp) { struct kretprobe *krp = &skp->kprobe->u.krp; unsigned long addr = 0; if (! skp->symbol_name) { addr = stapkp_relocate_addr(skp); if (addr == 0) return 1; krp->kp.addr = (void *) addr; } else { #ifdef STAPCONF_KALLSYMS_ON_EACH_SYMBOL if (krp->kp.addr == 0) return 1; #else #if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) if (krp->kp.symbol_name == NULL) krp->kp.symbol_name = kstrdup(skp->symbol_name, STP_ALLOC_FLAGS); #else krp->kp.symbol_name = (typeof(krp->kp.symbol_name))skp->symbol_name; #endif krp->kp.offset = skp->offset; #endif } if (skp->maxactive_p) krp->maxactive = skp->maxactive_val; else krp->maxactive = KRETACTIVE; krp->handler = &enter_kretprobe_probe; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) if (skp->entry_probe) { krp->entry_handler = &enter_kretprobe_entry_probe; krp->data_size = skp->saved_longs * sizeof(int64_t) + skp->saved_strings * MAXSTRINGLEN; } #endif #ifdef __ia64__ // PR6028 skp->kprobe->dummy.addr = krp->kp.addr; skp->kprobe->dummy.pre_handler = NULL; skp->kprobe->dummy.symbol_name = krp->kp.symbol_name; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) if (!skp->probe->cond_enabled) { krp->kp.flags |= KPROBE_FLAG_DISABLED; dbug_otf("registering as disabled (kretprobe) pidx %zu\n", skp->probe->index); } #endif return 0; }
static int stapkp_disable_probe(struct stap_dwarf_probe *sdp) { int ret = 0; dbug_otf("disabling (k%sprobe) pidx %zu\n", sdp->return_p ? "ret" : "", sdp->probe->index); ret = sdp->return_p ? disable_kretprobe(&sdp->kprobe->u.krp) : disable_kprobe(&sdp->kprobe->u.kp); if (ret != 0) { stapkp_unregister_probe(sdp); dbug_otf("failed to disable (k%sprobe) pidx %zu (rc %d)\n", sdp->return_p ? "ret" : "", sdp->probe->index, ret); } return ret; }
static int stapkp_enable_probe(struct stap_kprobe_probe *skp) { int ret = 0; dbug_otf("enabling (k%sprobe) pidx %zu\n", skp->return_p ? "ret" : "", skp->probe->index); ret = skp->return_p ? enable_kretprobe(&skp->kprobe->u.krp) : enable_kprobe(&skp->kprobe->u.kp); if (ret != 0) { stapkp_unregister_probe(skp); dbug_otf("failed to enable (k%sprobe) pidx %zu (rc %d)\n", skp->return_p ? "ret" : "", skp->probe->index, ret); } return ret; }
static int stapkp_prepare_kretprobe(struct stap_dwarf_probe *sdp) { struct kretprobe *krp = &sdp->kprobe->u.krp; unsigned long addr = stapkp_relocate_addr(sdp); if (addr == 0) return 1; krp->kp.addr = (void *) addr; if (sdp->maxactive_p) krp->maxactive = sdp->maxactive_val; else krp->maxactive = KRETACTIVE; krp->handler = &enter_kretprobe_probe; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,25) if (sdp->entry_probe) { krp->entry_handler = &enter_kretprobe_entry_probe; krp->data_size = sdp->saved_longs * sizeof(int64_t) + sdp->saved_strings * MAXSTRINGLEN; } #endif #ifdef __ia64__ // PR6028 sdp->kprobe->dummy.addr = krp->kp.addr; sdp->kprobe->dummy.pre_handler = NULL; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) if (!sdp->probe->cond_enabled) { krp->kp.flags |= KPROBE_FLAG_DISABLED; dbug_otf("registering as disabled (kretprobe) pidx %zu\n", sdp->probe->index); } #endif return 0; }
static int stapkp_prepare_kprobe(struct stap_kprobe_probe *skp) { struct kprobe *kp = &skp->kprobe->u.kp; unsigned long addr = 0; if (! skp->symbol_name) { addr = stapkp_relocate_addr(skp); if (addr == 0) return 1; kp->addr = (void *) addr; } else { #ifdef STAPCONF_KALLSYMS_ON_EACH_SYMBOL // If we're doing symbolic name + offset probing (that gets // converted to an address), it doesn't really matter if the // symbol is in a module and the module isn't loaded right // now. The registration will fail, but will get tried again // when the module is loaded. if (kp->addr == 0) return 1; #else // If we don't have kallsyms_on_each_symbol(), we'll use // symbol_name+offset probing and let // register_kprobe()/register_kretprobe() call // kallsyms_lookup_name() for us. However, on kernels < 3.11, // module_kallsyms_lookup_name() (called from // kallsyms_lookup_name()) has a bug where it modifies its // argument. So, for those kernels we'll workaround the bug by // duplicating the string (so we go from read-only memory in the // initialized struct data to read-write allocated memory). The // memory gets freed when the probe is unregistered. // // This bug was fixed in kernel 3.11+ by the following commit: // // commit 4f6de4d51f4a3ab06a85e91e708cc89a513ef30c // Author: Mathias Krause <*****@*****.**> // Date: Tue Jul 2 15:35:11 2013 +0930 // // module: don't modify argument of module_kallsyms_lookup_name() #if LINUX_VERSION_CODE < KERNEL_VERSION(3,11,0) if (kp->symbol_name == NULL) kp->symbol_name = kstrdup(skp->symbol_name, STP_ALLOC_FLAGS); #else kp->symbol_name = (typeof(kp->symbol_name))skp->symbol_name; #endif kp->offset = skp->offset; #endif } kp->pre_handler = &enter_kprobe_probe; #ifdef __ia64__ // PR6028 skp->kprobe->dummy.addr = kp->addr; skp->kprobe->dummy.pre_handler = NULL; skp->kprobe->dummy.symbol_name = kp->symbol_name; #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) if (!skp->probe->cond_enabled) { kp->flags |= KPROBE_FLAG_DISABLED; dbug_otf("registering as disabled (kprobe) pidx %zu\n", skp->probe->index); } #endif return 0; }