From: Nikita Kalyazin Date: Mon, 23 Apr 2012 06:40:44 +0000 (+0400) Subject: Kernel on-the-go probes feature implemented (#313) X-Git-Tag: Tizen_SDK_2.3~803 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=fc202d935d33d0286069129b1127d7446883bc9e;p=kernel%2Fswap-modules.git Kernel on-the-go probes feature implemented (#313) Related to 76986670c32162d5d12c741a08bcec4fe935941a (#252). Interface: int install_kern_otg_probe(unsigned long addr, unsigned long pre_handler, unsigned long jp_handler, unsigned long rp_handler); --- diff --git a/driver/probes_manager.c b/driver/probes_manager.c index fd7188c..14c3bd9 100644 --- a/driver/probes_manager.c +++ b/driver/probes_manager.c @@ -202,6 +202,9 @@ detach_selected_probes (void) hlist_for_each_entry_rcu (p, node, &kernel_probes, hlist) unregister_kernel_probe (p); + hlist_for_each_entry_rcu (p, node, &otg_kernel_probes, hlist) { + unregister_kernel_probe(p); + } return 0; } @@ -288,6 +291,24 @@ int reset_probes() kfree(p); } + hlist_for_each_entry_safe (p, node, tnode, &otg_kernel_probes, hlist) { + if (p->addr == pf_addr) { + probes_flags &= ~PROBE_FLAG_PF_INSTLD; + pf_probe = NULL; + } else if (p->addr == exit_addr) { + probes_flags &= ~PROBE_FLAG_EXIT_INSTLD; + exit_probe = NULL; + } else if (p->addr == fork_addr) { + probes_flags &= ~PROBE_FLAG_FORK_INSTLD; + fork_probe = NULL; + } else if (p->addr == exec_addr) { + probes_flags &= ~PROBE_FLAG_EXEC_INSTLD; + exec_probe = NULL; + } + hlist_del(node); + kfree(p); + } + return 0; } @@ -510,3 +531,67 @@ int is_pf_installed_by_user(void) return (probes_flags & PROBE_FLAG_PF_INSTLD) ? 1: 0; } EXPORT_SYMBOL_GPL(is_pf_installed_by_user); + +int install_kern_otg_probe(unsigned long addr, + unsigned long pre_handler, + unsigned long jp_handler, + unsigned long rp_handler) +{ + kernel_probe_t *new_probe = NULL; + kernel_probe_t *probe; + int ret = 0; + + probe = find_probe(addr); + if (probe) { + /* It is not a problem if we have already registered + this probe before */ + return 0; + } + + new_probe = kmalloc(sizeof (kernel_probe_t), GFP_ATOMIC); + if (!new_probe) { + EPRINTF("No memory for new probe"); + return -1; + } + memset(new_probe, 0, sizeof(kernel_probe_t)); + + new_probe->addr = addr; + new_probe->jprobe.kp.addr = new_probe->retprobe.kp.addr = (kprobe_opcode_t *)addr; + new_probe->jprobe.priv_arg = new_probe->retprobe.priv_arg = new_probe; + + if (pre_handler) { + new_probe->jprobe.pre_entry = pre_handler; + } else { + new_probe->jprobe.pre_entry = + (kprobe_pre_entry_handler_t) + def_jprobe_event_pre_handler; + } + + if (jp_handler) { + new_probe->jprobe.entry = jp_handler; + } else { + new_probe->jprobe.entry = + (kprobe_opcode_t *) + def_jprobe_event_handler; + } + + if (rp_handler) { + new_probe->retprobe.handler = rp_handler; + } else { + new_probe->retprobe.handler = + (kretprobe_handler_t) + def_retprobe_event_handler; + } + + INIT_HLIST_NODE (&new_probe->hlist); + hlist_add_head_rcu (&new_probe->hlist, &kernel_probes); + + ret = register_kernel_probe(new_probe); + if (ret) { + EPRINTF("Cannot set kernel probe at addr %p", addr); + return -1; + } + + return 0; +} +EXPORT_SYMBOL_GPL(install_kern_otg_probe); diff --git a/driver/probes_manager.h b/driver/probes_manager.h index 33de035..91df48b 100644 --- a/driver/probes_manager.h +++ b/driver/probes_manager.h @@ -47,6 +47,10 @@ extern int def_retprobe_event_handler (struct kretprobe_instance *probe, struct void dbi_install_user_handlers(void); void dbi_uninstall_user_handlers(void); int is_pf_installed_by_user(void); +int install_kern_otg_probe(unsigned long addr, + unsigned long pre_handler, + unsigned long jp_handler, + unsigned long rp_handler); extern unsigned long pf_addr; extern unsigned long exit_addr; diff --git a/driver/storage.c b/driver/storage.c index 5764300..38358cf 100644 --- a/driver/storage.c +++ b/driver/storage.c @@ -34,6 +34,7 @@ char *deps; char *bundle; unsigned int inst_pid = 0; struct hlist_head kernel_probes; +struct hlist_head otg_kernel_probes; int event_mask = 0L; struct cond cond_list; int paused = 0; /* a state after a stop condition (events are not collected) */ @@ -1356,7 +1357,8 @@ int storage_init (void) return -1; } - INIT_HLIST_HEAD (&kernel_probes); + INIT_HLIST_HEAD(&kernel_probes); + INIT_HLIST_HEAD(&otg_kernel_probes); INIT_LIST_HEAD(&otg_us_proc_info); return 0; diff --git a/driver/storage.h b/driver/storage.h index 8ae7ecd..49bbfed 100644 --- a/driver/storage.h +++ b/driver/storage.h @@ -119,6 +119,9 @@ extern char *p_buffer; // list of selected non-predefined kernel probes extern struct hlist_head kernel_probes; +/* list of on-the-go installed kernel probes */ +extern struct hlist_head otg_kernel_probes; + extern struct list_head otg_us_proc_info; // event mask