/
usr
/
share
/
systemtap
/
runtime
/
linux
/
/usr/share/systemtap/runtime/linux
mkdir
upload
Name
Size
Mode
Actions
uprobes/
-
0755
rm
uprobes2/
-
0755
rm
access_process_vm.h
4311
0644
edit
dl
rm
addr-map.c
9749
0644
edit
dl
rm
alloc.c
15900
0644
edit
dl
rm
arith.c
16799
0644
edit
dl
rm
autoconf-514-panic.c
68
0644
edit
dl
rm
autoconf-access_ok_2args.c
90
0644
edit
dl
rm
autoconf-alloc-percpu-align.c
118
0644
edit
dl
rm
autoconf-asm-syscall.c
51
0644
edit
dl
rm
autoconf-atomic_fetch_add_unless.c
94
0644
edit
dl
rm
autoconf-bio-bi_opf.c
824
0644
edit
dl
rm
autoconf-blk-types.c
359
0644
edit
dl
rm
autoconf-compat-utimbuf.c
53
0644
edit
dl
rm
autoconf-compat_sigaction.c
448
0644
edit
dl
rm
autoconf-constant-tsc.c
63
0644
edit
dl
rm
autoconf-cpu-clock.c
1277
0644
edit
dl
rm
autoconf-dpath-path.c
121
0644
edit
dl
rm
autoconf-files_lookup_fd_raw.c
136
0644
edit
dl
rm
autoconf-from_kuid_munged.c
191
0644
edit
dl
rm
autoconf-fs_supers-hlist.c
354
0644
edit
dl
rm
autoconf-generated-compile.c
56
0644
edit
dl
rm
autoconf-genhd.c
201
0644
edit
dl
rm
autoconf-get-kretprobe.c
107
0644
edit
dl
rm
autoconf-get_user_pages-flags.c
1549
0644
edit
dl
rm
autoconf-get_user_pages-notask_struct.c
1301
0644
edit
dl
rm
autoconf-get_user_pages_remote-flags.c
1550
0644
edit
dl
rm
autoconf-get_user_pages_remote-flags_locked.c
1331
0644
edit
dl
rm
autoconf-get_user_pages_remote-notask_struct.c
1438
0644
edit
dl
rm
autoconf-grsecurity.c
219
0644
edit
dl
rm
autoconf-hlist-4args.c
296
0644
edit
dl
rm
autoconf-hlist_add_tail_rcu.c
112
0644
edit
dl
rm
autoconf-hrtimer-getset-expires.c
126
0644
edit
dl
rm
autoconf-hrtimer-rel.c
87
0644
edit
dl
rm
autoconf-hw_breakpoint_context.c
315
0644
edit
dl
rm
autoconf-inode-private.c
173
0644
edit
dl
rm
autoconf-inode-rwsem.c
172
0644
edit
dl
rm
autoconf-inode-uretprobes.c
264
0644
edit
dl
rm
autoconf-kernel_read-new-args.c
1030
0644
edit
dl
rm
autoconf-kprobe-symbol-name.c
90
0644
edit
dl
rm
autoconf-ktime-get-real.c
98
0644
edit
dl
rm
autoconf-linux-sched_headers.c
1678
0644
edit
dl
rm
autoconf-local-clock.c
1282
0644
edit
dl
rm
autoconf-lockdown-debugfs.c
102
0644
edit
dl
rm
autoconf-lockdown-kernel.c
90
0644
edit
dl
rm
autoconf-mm-context-vdso-base.c
117
0644
edit
dl
rm
autoconf-mm-context-vdso.c
114
0644
edit
dl
rm
autoconf-mm-shmempages.c
72
0644
edit
dl
rm
autoconf-mmap_lock.c
175
0644
edit
dl
rm
autoconf-module-sect-attrs.c
158
0644
edit
dl
rm
autoconf-module_layout.c
52
0644
edit
dl
rm
autoconf-mod_kallsyms.c
51
0644
edit
dl
rm
autoconf-nameidata.c
96
0644
edit
dl
rm
autoconf-netfilter-4_1.c
769
0644
edit
dl
rm
autoconf-netfilter-4_4.c
1460
0644
edit
dl
rm
autoconf-netfilter-313b.c
602
0644
edit
dl
rm
autoconf-netfilter.c
422
0644
edit
dl
rm
autoconf-old-inode-uprobes.c
357
0644
edit
dl
rm
autoconf-oneachcpu-retry.c
957
0644
edit
dl
rm
autoconf-pagefault_disable.c
137
0644
edit
dl
rm
autoconf-pde_data.c
226
0644
edit
dl
rm
autoconf-perf-structpid.c
444
0644
edit
dl
rm
autoconf-procfs-owner.c
158
0644
edit
dl
rm
autoconf-proc_ops.c
566
0644
edit
dl
rm
autoconf-rcu_is_watching.c
385
0644
edit
dl
rm
autoconf-real-parent.c
427
0644
edit
dl
rm
autoconf-regset.c
239
0644
edit
dl
rm
autoconf-relay-umode_t.c
730
0644
edit
dl
rm
autoconf-relay_buf-per_cpu_ptr.c
920
0644
edit
dl
rm
autoconf-ring_buffer-flags.c
112
0644
edit
dl
rm
autoconf-ring_buffer_lost_events.c
296
0644
edit
dl
rm
autoconf-ring_buffer_read_prepare.c
181
0644
edit
dl
rm
autoconf-save-stack-trace-no-bp.c
498
0644
edit
dl
rm
autoconf-save-stack-trace.c
501
0644
edit
dl
rm
autoconf-set_fs.c
221
0644
edit
dl
rm
autoconf-smpcall-4args.c
166
0644
edit
dl
rm
autoconf-smpcall-5args.c
169
0644
edit
dl
rm
autoconf-stack-trace-save-regs.c
176
0644
edit
dl
rm
autoconf-stacktrace_ops-int-address.c
409
0644
edit
dl
rm
autoconf-stacktrace_ops-warning.c
188
0644
edit
dl
rm
autoconf-syscall_get_args_3args.c
239
0644
edit
dl
rm
autoconf-task-state.c
550
0644
edit
dl
rm
autoconf-task-uid.c
152
0644
edit
dl
rm
autoconf-task_work-struct.c
219
0644
edit
dl
rm
autoconf-time32-old.c
52
0644
edit
dl
rm
autoconf-time32.c
53
0644
edit
dl
rm
autoconf-timerfd.c
232
0644
edit
dl
rm
autoconf-trace-printk.c
151
0644
edit
dl
rm
autoconf-tracepoint-has-data.c
493
0644
edit
dl
rm
autoconf-tracepoint-strings.c
233
0644
edit
dl
rm
autoconf-uaccess.c
28
0644
edit
dl
rm
autoconf-uapi-mount.c
52
0644
edit
dl
rm
autoconf-udelay_simple.c
90
0644
edit
dl
rm
autoconf-uidgid.c
50
0644
edit
dl
rm
autoconf-unwind-stack-trace.c
326
0644
edit
dl
rm
autoconf-uprobe-get-pc.c
374
0644
edit
dl
rm
autoconf-utrace-regset.c
273
0644
edit
dl
rm
autoconf-utrace-via-tracepoints.c
1712
0644
edit
dl
rm
autoconf-vm-area-pte.c
141
0644
edit
dl
rm
autoconf-walk-stack.c
217
0644
edit
dl
rm
autoconf-x86-fs.c
90
0644
edit
dl
rm
autoconf-x86-gs.c
90
0644
edit
dl
rm
autoconf-x86-uniregs.c
140
0644
edit
dl
rm
autoconf-x86-xfs.c
91
0644
edit
dl
rm
common_session_state.h
3249
0644
edit
dl
rm
compat_net.h
858
0644
edit
dl
rm
compat_structs.h
4409
0644
edit
dl
rm
compat_unistd.h
68384
0644
edit
dl
rm
copy.c
2717
0644
edit
dl
rm
debug.h
2978
0644
edit
dl
rm
io.c
5291
0644
edit
dl
rm
itrace.c
14874
0644
edit
dl
rm
kprobes.c
25126
0644
edit
dl
rm
loc2c-runtime.h
29874
0644
edit
dl
rm
map_list.h
1220
0644
edit
dl
rm
map_runtime.h
5266
0644
edit
dl
rm
namespaces.h
7128
0644
edit
dl
rm
netfilter.c
1410
0644
edit
dl
rm
perf.c
7596
0644
edit
dl
rm
perf.h
1272
0644
edit
dl
rm
perf_event_counter_context.c
336
0644
edit
dl
rm
perf_probe_handler_nmi.c
278
0644
edit
dl
rm
perf_read.h
959
0644
edit
dl
rm
print.c
11402
0644
edit
dl
rm
probe_lock.h
1807
0644
edit
dl
rm
regs-ia64.c
3741
0644
edit
dl
rm
regs.c
13490
0644
edit
dl
rm
runtime.h
12591
0644
edit
dl
rm
runtime_context.h
6089
0644
edit
dl
rm
runtime_defines.h
1041
0644
edit
dl
rm
stap_mmap_lock.h
343
0644
edit
dl
rm
stat_runtime.h
1774
0644
edit
dl
rm
stp_tls.h
1181
0644
edit
dl
rm
stp_tracepoint.c
11481
0644
edit
dl
rm
stp_tracepoint.h
2270
0644
edit
dl
rm
syscalls-common.h
976
0644
edit
dl
rm
task_finder.c
53860
0644
edit
dl
rm
task_finder2.c
57640
0644
edit
dl
rm
task_finder_map.c
5194
0644
edit
dl
rm
task_finder_stubs.c
2442
0644
edit
dl
rm
task_work_compatibility.h
1283
0644
edit
dl
rm
timer.c
2200
0644
edit
dl
rm
timer.h
1383
0644
edit
dl
rm
timer_compatibility.h
2317
0644
edit
dl
rm
uprobes-common.c
15573
0644
edit
dl
rm
uprobes-common.h
1653
0644
edit
dl
rm
uprobes-inc.h
484
0644
edit
dl
rm
uprobes-inode.c
34086
0644
edit
dl
rm
Edit:
/usr/share/systemtap/runtime/linux/kprobes.c
(25126B)
/* -*- linux-c -*- * Common functions for using kprobes * Copyright (C) 2014-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 * Public License (GPL); either version 2, or (at your option) any * later version. */ #ifndef _KPROBES_C_ #define _KPROBES_C_ // Warn of misconfigured kernels #if !defined(CONFIG_KPROBES) #error "Need CONFIG_KPROBES!" #endif // PR26074: if kallsyms_on_each_symbol() is not exported we try to get it via relocations. // Need to define the runtime.h variable here to check if it's defined from kprobes.c. // (This code would go in a header if it were used anywhere else.) // // PR11514: kallsyms_on_each_symbol() should not be used on PPC64. #ifndef CONFIG_PPC64 #define STAPCONF_KALLSYMS_ON_EACH_SYMBOL #if !defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL_EXPORTED) extern void *_stp_kallsyms_on_each_symbol; #endif #endif #if defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL) && defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL_EXPORTED) #define USE_KALLSYMS_ON_EACH_SYMBOL (1) #elif defined(STAPCONF_KALLSYMS_ON_EACH_SYMBOL) // XXX May not be available; if available, is passed through relocation: #define USE_KALLSYMS_ON_EACH_SYMBOL (_stp_kallsyms_on_each_symbol != NULL) #else #define USE_KALLSYMS_ON_EACH_SYMBOL (0) #endif #include <linux/kprobes.h> #include <linux/module.h> #ifdef DEBUG_KPROBES #define dbug_stapkp(args...) do { \ _stp_dbug(__FUNCTION__, __LINE__, args); \ } while (0) #define dbug_stapkp_cond(cond, args...) do { \ if (cond) \ dbug_stapkp(args); \ } while (0) #else #define dbug_stapkp(args...) do { } while (0) #define dbug_stapkp_cond(cond, args...) do { } while (0) #endif #ifndef KRETACTIVE #define KRETACTIVE (max(15, 6 * (int)num_possible_cpus())) #endif // This shouldn't happen, but check as a precaution. If we're on kver >= 2.6.30, // then we must also have STP_ON_THE_FLY_TIMER_ENABLE (which is turned on for // kver >= 2.6.17, see translate_pass()). This indicates that the background // timer is available and thus that kprobes can be armed/disarmed on-the-fly. #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) \ && !defined(STP_ON_THE_FLY_TIMER_ENABLE) #error "STP_ON_THE_FLY_TIMER_ENABLE undefined" #endif // NB: this struct is set up by the stapkp_prepare_* functions prior to // registering and zero'ed out again after each unregister struct stap_kprobe { union { struct kprobe kp; struct kretprobe krp; } u; #ifdef __ia64__ // PR6028: We register a second dummy probe at the same address so that the // kernel uses aggr_kprobe. This is needed ensure that the bspcache is always // valid. struct kprobe dummy; #endif }; struct stap_kprobe_probe { const unsigned return_p:1; const unsigned maxactive_p:1; const unsigned optional_p:1; unsigned registered_p:1; const unsigned short maxactive_val; // data saved in the kretprobe_instance packet const unsigned short saved_longs; const unsigned short saved_strings; // These macros declare the module and section strings as either const char[] // or const char * const. Their actual types are determined at translate-time // in dwarf_derived_probe_group::emit_module_decls(). STAP_KPROBE_PROBE_STR_module; STAP_KPROBE_PROBE_STR_section; // For the majority of dwarf-based kprobes, we'll use address-based // probing. But, for dwarf-based kprobes in modules, we need to // switch to using symbol_name+offset (on kernels that support // symbol_name+offset probing). const unsigned long address; // Note we can't really check for STAPCONF_KPROBE_SYMBOL_NAME here, // since that complicates the init logic too much. const char *symbol_name; unsigned int offset; const struct stap_probe * const probe; const struct stap_probe * const entry_probe; struct stap_kprobe * const kprobe; }; // Forward declare the main entry functions (stap-generated) static int enter_kprobe_probe(struct kprobe *inst, struct pt_regs *regs); static int enter_kretprobe_common(struct kretprobe_instance *inst, struct pt_regs *regs, int entry); // Helper entry functions for kretprobes static int enter_kretprobe_probe(struct kretprobe_instance *inst, struct pt_regs *regs) { return enter_kretprobe_common(inst, regs, 0); } static int enter_kretprobe_entry_probe(struct kretprobe_instance *inst, struct pt_regs *regs) { return enter_kretprobe_common(inst, regs, 1); } static unsigned long stapkp_relocate_addr(struct stap_kprobe_probe *skp) { return _stp_kmodule_relocate(skp->module, skp->section, skp->address); } static int stapkp_prepare_kprobe(struct stap_kprobe_probe *skp) { struct kprobe *kp = &skp->kprobe->u.kp; unsigned long addr = 0; // PR28557 Try a pass resolving the address now with the currently // known module/section addresses within our own stap-symbols tables. addr = stapkp_relocate_addr(skp); if (addr != 0) { kp->addr = (void*) addr; } // fall back to kallsyms-based or kernel kprobes-delegated symbolic // registration else if (skp->symbol_name) { // 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 (USE_KALLSYMS_ON_EACH_SYMBOL && kp->addr == 0) return 4; else if (!USE_KALLSYMS_ON_EACH_SYMBOL) { // 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 <minipli@googlemail.com> // 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; } } // NB: success paths need to come here, to set the pre_handler 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; } static int stapkp_arch_register_kprobe(struct stap_kprobe_probe *skp) { int ret = 0; struct kprobe *kp = &skp->kprobe->u.kp; #ifndef __ia64__ ret = register_kprobe(kp); if (ret == 0) { if (skp->symbol_name) dbug_stapkp("+kprobe %s+%u\n", kp->symbol_name, kp->offset); else dbug_stapkp("+kprobe %p\n", kp->addr); } #else // PR6028 ret = register_kprobe(&skp->kprobe->dummy); if (ret == 0) { ret = register_kprobe(kp); if (ret != 0) unregister_kprobe(&skp->kprobe->dummy); } dbug_stapkp_cond(ret == 0, "+kprobe %p\n", skp->kprobe->dummy.addr); dbug_stapkp_cond(ret == 0, "+kprobe %p\n", kp->addr); #endif skp->registered_p = (ret ? 0 : 1); return ret; } static int stapkp_register_kprobe(struct stap_kprobe_probe *skp) { int ret = stapkp_prepare_kprobe(skp); if (ret == 0) ret = stapkp_arch_register_kprobe(skp); dbug_stapkp("stapkp_register_kprobe module %s addr 0x%lx rc %d\n", skp->module, (unsigned long)skp->address, ret); return ret; } static int stapkp_prepare_kretprobe(struct stap_kprobe_probe *skp) { struct kretprobe *krp = &skp->kprobe->u.krp; unsigned long addr = 0; // PR28557 Try a pass resolving the address now with the currently // known module/section addresses within our own stap-symbols tables. addr = stapkp_relocate_addr(skp); if (addr != 0) { krp->kp.addr = (void*) addr; } // fall back to kallsyms-based or kernel kprobes-delegated symbolic // registration else if (skp->symbol_name) { if (USE_KALLSYMS_ON_EACH_SYMBOL && krp->kp.addr == 0) return 4; else if (!USE_KALLSYMS_ON_EACH_SYMBOL) { #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; } } 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_arch_register_kretprobe(struct stap_kprobe_probe *skp) { int ret = 0; struct kretprobe *krp = &skp->kprobe->u.krp; #ifndef __ia64__ ret = register_kretprobe(krp); dbug_stapkp_cond(ret == 0, "+kretprobe %p\n", krp->kp.addr); #else // PR6028 ret = register_kprobe(&skp->kprobe->dummy); if (ret == 0) { ret = register_kretprobe(krp); if (ret != 0) unregister_kprobe(&skp->kprobe->dummy); } dbug_stapkp_cond(ret == 0, "+kprobe %p\n", skp->kprobe->dummy.addr); dbug_stapkp_cond(ret == 0, "+kretprobe %p\n", krp->kp.addr); #endif skp->registered_p = (ret ? 0 : 1); return ret; } static int stapkp_register_kretprobe(struct stap_kprobe_probe *skp) { int ret = stapkp_prepare_kretprobe(skp); if (ret == 0) ret = stapkp_arch_register_kretprobe(skp); return ret; } static int stapkp_register_probe(struct stap_kprobe_probe *skp) { dbug_stapkp("stapkp_register_probe module %s addr 0x%lx reg %d\n", skp->module, (unsigned long)skp->address, skp->registered_p); if (skp->registered_p) return 0; return skp->return_p ? stapkp_register_kretprobe(skp) : stapkp_register_kprobe(skp); } static void stapkp_add_missed(struct stap_kprobe_probe *skp) { if (skp->return_p) { struct kretprobe *krp = &skp->kprobe->u.krp; atomic_add(krp->nmissed, skipped_count()); #ifdef STP_TIMING if (krp->nmissed) _stp_warn ("Skipped due to missed kretprobe/1 on '%s': %d\n", skp->probe->pp, krp->nmissed); #endif atomic_add(krp->kp.nmissed, skipped_count()); #ifdef STP_TIMING if (krp->kp.nmissed) _stp_warn ("Skipped due to missed kretprobe/2 on '%s': %lu\n", skp->probe->pp, krp->kp.nmissed); #endif } else { struct kprobe *kp = &skp->kprobe->u.kp; atomic_add (kp->nmissed, skipped_count()); #ifdef STP_TIMING if (kp->nmissed) _stp_warn ("Skipped due to missed kprobe on '%s': %lu\n", skp->probe->pp, kp->nmissed); #endif } } static void stapkp_unregister_probe(struct stap_kprobe_probe *skp) { struct stap_kprobe *sk = skp->kprobe; if (!skp->registered_p) return; if (skp->return_p) { unregister_kretprobe (&sk->u.krp); if (skp->symbol_name) dbug_stapkp("-kretprobe %s:%d\n", sk->u.krp.kp.symbol_name, sk->u.krp.kp.offset); else dbug_stapkp("-kretprobe %p\n", sk->u.krp.kp.addr); } else { unregister_kprobe (&sk->u.kp); if (skp->symbol_name) dbug_stapkp("-kprobe %s:%u\n", sk->u.kp.symbol_name, sk->u.kp.offset); else dbug_stapkp("-kprobe %p\n", sk->u.kp.addr); } #if defined(__ia64__) unregister_kprobe (&sk->dummy); dbug_stapkp("-kprobe %p\n", sk->dummy.addr); #endif 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 (sk->u.krp.kp.symbol_name != NULL) kfree(sk->u.krp.kp.symbol_name); } else { if (sk->u.kp.symbol_name != NULL) kfree(sk->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(sk, 0, sizeof(struct stap_kprobe)); } #if defined(STAPCONF_UNREGISTER_KPROBES) // The actual size is set later on in // generic_kprobe_derived_probe_group::emit_module_decls(). static void * stap_unreg_kprobes[]; enum collect_type { COLLECT_KPROBES, #if defined(__ia64__) COLLECT_DUMMYS, #endif COLLECT_KRETPROBES }; static size_t stapkp_collect_registered_probes(struct stap_kprobe_probe *probes, size_t nprobes, enum collect_type type) { size_t i, j; j = 0; for (i = 0; i < nprobes; i++) { struct stap_kprobe_probe *skp = &probes[i]; struct stap_kprobe *sk = skp->kprobe; if (!skp->registered_p) continue; if (type == COLLECT_KPROBES && !skp->return_p) stap_unreg_kprobes[j++] = &sk->u.kp; else if (type == COLLECT_KRETPROBES && skp->return_p) stap_unreg_kprobes[j++] = &sk->u.krp; #if defined(__ia64__) else if (type == COLLECT_DUMMYS) stap_unreg_kprobes[j++] = &sk->dummy; #endif } return j; } 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)); } } #endif /* STAPCONF_UNREGISTER_KPROBES */ static void stapkp_unregister_probes(struct stap_kprobe_probe *probes, size_t nprobes) { #if defined(STAPCONF_UNREGISTER_KPROBES) // Unregister using batch mode stapkp_batch_unregister_probes(probes, nprobes); #else // We'll have to unregister them one by one size_t i; for (i = 0; i < nprobes; i++) { struct stap_kprobe_probe *skp = &probes[i]; if (!skp->registered_p) continue; stapkp_unregister_probe(skp); } #endif } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) static int stapkp_enabled(struct stap_kprobe_probe *skp) { if (!skp->registered_p) return 0; return skp->return_p ? !kprobe_disabled(&skp->kprobe->u.krp.kp) : !kprobe_disabled(&skp->kprobe->u.kp); } static int stapkp_should_enable_probe(struct stap_kprobe_probe *skp) { return skp->registered_p && !stapkp_enabled(skp) && skp->probe->cond_enabled; } 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_should_disable_probe(struct stap_kprobe_probe *skp) { return skp->registered_p && stapkp_enabled(skp) && !skp->probe->cond_enabled; } static int stapkp_disable_probe(struct stap_kprobe_probe *skp) { int ret = 0; dbug_otf("disabling (k%sprobe) pidx %zu\n", skp->return_p ? "ret" : "", skp->probe->index); ret = skp->return_p ? disable_kretprobe(&skp->kprobe->u.krp) : disable_kprobe(&skp->kprobe->u.kp); if (ret != 0) { stapkp_unregister_probe(skp); dbug_otf("failed to disable (k%sprobe) pidx %zu (rc %d)\n", skp->return_p ? "ret" : "", skp->probe->index, ret); } return ret; } static int stapkp_refresh_probe(struct stap_kprobe_probe *skp) { if (stapkp_should_enable_probe(skp)) return stapkp_enable_probe(skp); if (stapkp_should_disable_probe(skp)) return stapkp_disable_probe(skp); return 0; } #endif /* LINUX_VERSION_CODE >= 2.6.30 */ struct stapkp_symbol_data { struct stap_kprobe_probe *probes; size_t nprobes; /* number of probes in "probes" */ size_t probe_max; /* number of probes to process */ const char *modname; }; static int stapkp_symbol_callback(void *data, const char *name, struct module *mod, unsigned long addr) { struct stapkp_symbol_data *sd = data; size_t i; if ((mod && sd->modname && strcmp(mod->name, sd->modname) != 0) || (!mod && sd->modname)) return 0; for (i = 0; i < sd->nprobes; i++) { struct stap_kprobe_probe *skp = &sd->probes[i]; int update_addr = 0; if (! skp->symbol_name) continue; // If (1) We're probing a module symbol and we're in that module // and the names match; or (2) we're probing a symbol in the // kernel and the names match, then update the k[ret]probe // address. if (mod && skp->module && strcmp(mod->name, skp->module) == 0) { char *colon = strchr(skp->symbol_name, ':'); if (colon != NULL && strcmp(name, colon+1) == 0) update_addr = 1; } else if (!mod && (skp->module == NULL || skp->module[0] == '\0') && strcmp(name, skp->symbol_name) == 0) update_addr = 1; if (update_addr) { if (skp->return_p) skp->kprobe->u.krp.kp.addr = (void *)(addr + skp->offset); else skp->kprobe->u.kp.addr = (void *)(addr + skp->offset); // Note that we could have more than 1 probe at the same // symbol (with the same or differing offsets), so we can't // return here. // // But we can quit if we've processed all the needed probes. --sd->probe_max; if (sd->probe_max == 0) return -1; } } return 0; } static int stapkp_init(struct stap_kprobe_probe *probes, size_t nprobes) { size_t i; if (USE_KALLSYMS_ON_EACH_SYMBOL) { // If we have any symbol_name+offset probes, we need to try to // convert those into address-based probes. size_t probe_max = 0; for (i = 0; i < nprobes; i++) { struct stap_kprobe_probe *skp = &probes[i]; if (! skp->symbol_name) continue; ++probe_max; } if (probe_max > 0) { // Here we're going to try to convert any symbol_name+offset // probes into address probes. struct stapkp_symbol_data sd; dbug_stapkp("looking up %lu probes\n", probe_max); sd.probes = probes; sd.nprobes = nprobes; sd.probe_max = probe_max; sd.modname = NULL; #ifdef STAPCONF_MODULE_MUTEX mutex_lock(&module_mutex); #endif preempt_disable(); kallsyms_on_each_symbol(stapkp_symbol_callback, &sd); preempt_enable(); #ifdef STAPCONF_MODULE_MUTEX mutex_unlock(&module_mutex); #endif dbug_stapkp("found %lu probes\n", sd.probe_max); } } for (i = 0; i < nprobes; i++) { struct stap_kprobe_probe *skp = &probes[i]; int rc = 0; rc = stapkp_register_probe(skp); if (rc == 1) // failed to relocate addr? continue; // don't fuss about it, module probably not loaded // NB: We keep going even if a probe failed to register (PR6749). We only // warn about it if it wasn't optional and isn't in a module. if (rc && !skp->optional_p && ((skp->module == NULL) || skp->module[0] == '\0' || strcmp(skp->module, "kernel") == 0)) { if (skp->symbol_name) _stp_warn("probe %s (%s+%u) registration error [man warning::pass5] (rc %d)", skp->probe->pp, skp->symbol_name, skp->offset, rc); else _stp_warn("probe %s (address 0x%lx) registration error [man warning::pass5] (rc %d)", skp->probe->pp, stapkp_relocate_addr(skp), rc); } } return 0; } /* stapkp_refresh is called for two reasons: either a kprobe needs to be * enabled/disabled (modname is NULL), or a module has been loaded/unloaded and * kprobes need to be registered/unregistered (modname is !NULL). */ static void stapkp_refresh(const char *modname, struct stap_kprobe_probe *probes, size_t nprobes) { size_t i; dbug_stapkp("refresh %lu probes with module %s\n", nprobes, modname ?: "?"); if (USE_KALLSYMS_ON_EACH_SYMBOL) { if (modname) { size_t probe_max = 0; for (i = 0; i < nprobes; i++) { struct stap_kprobe_probe *skp = &probes[i]; // If this probe is in the same module that is being // loaded/unloaded and the probe is symbol_name+offset based // and it isn't registered (so the module must be loaded), // try to convert all probes in the same module to // address-based probes. if (skp->module && strcmp(modname, skp->module) == 0 && skp->symbol_name && skp->registered_p == 0) ++probe_max; } if (probe_max > 0) { struct stapkp_symbol_data sd; sd.probes = probes; sd.nprobes = nprobes; sd.probe_max = probe_max; sd.modname = modname; #ifdef STAPCONF_MODULE_MUTEX mutex_lock(&module_mutex); #endif preempt_disable(); kallsyms_on_each_symbol(stapkp_symbol_callback, &sd); preempt_enable(); #ifdef STAPCONF_MODULE_MUTEX mutex_unlock(&module_mutex); #endif } } } for (i = 0; i < nprobes; i++) { struct stap_kprobe_probe *skp = &probes[i]; // was this probe's target module loaded/unloaded if (modname && skp->module && strcmp(modname, skp->module) == 0) { int rc; unsigned long addr = (! skp->symbol_name ? stapkp_relocate_addr(skp) : 0); // module being loaded? if (skp->registered_p == 0 && (addr != 0 || skp->symbol_name)) stapkp_register_probe(skp); // module/section being unloaded? else if (skp->registered_p == 1 && addr == 0) stapkp_unregister_probe(skp); } #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30) else if (stapkp_should_enable_probe(skp) || stapkp_should_disable_probe(skp)) { stapkp_refresh_probe(skp); } #endif } } static void stapkp_exit(struct stap_kprobe_probe *probes, size_t nprobes) { stapkp_unregister_probes(probes, nprobes); } #endif /* _KPROBES_C_ */
Save
cmd:
run