kprobes += function-return probes
PATCH 1/2 kprobes += function-return probes
This patch adds function-return probes (AKA exit probes) to kprobes. When establishing a probepoint at the entry to a function, you can also establish a handler to be run when the function returns.
The subsequent post give example of how function-return probes can be used.
Two new registration interfaces are added to kprobes:
int register_kretprobe(struct kprobe *kp, struct rprobe *rp);
Registers a probepoint at the entry to the function whose address is kp->addr. Each time that function returns, rp->handler will be run.
int register_jretprobe(struct jprobe *jp, struct rprobe *rp);
Like register_kretprobe, except a jprobe is established for the probed function.
To unregister, you still use unregister_kprobe or unregister_jprobe. To probe only a function's returns, call register_kretprobe() and specify NULL handlers for the kprobe.
The following fields of struct retprobe are of interest to the user:
handler - This function is run after the ret instruction executes, but before control returns to the return address in the caller.
maxactive - The maximum number of instances of the probed function that can be active concurrently. For example, if the function is non-recursive and is called with a spinlock or mutex held, maxactive = 1 should be enough. If the function is non-recursive and can never relinquish the CPU (e.g., via a semaphore or preemption), NR_CPUS should be enough. maxactive is used to determine how many rprobe_instance objects to allocate for this particular probed function. If maxactive <= 0, it is set to a default value. See register_kretprobe().
nmissed - Initialized to zero when the rprobe is registered, and incremented every time the probed function is entered but there is no rprobe_instance object available for establishing the function-return probe.
kprobe - When the rprobe is registered, this field is set to the kprobe at the entry to the function.
tmp/linux-2.6.12-rc1.mm3.works/include/linux/kprobes.h renamed from include/linux/kprobes.h +68 -0
@@ -25,6 +25,9 @@* Rusty Russell). * 2004-July Suparna Bhattacharya <[email protected]> added jumper probes * interface to access function arguments. +* 2005-Mar Hien Nguyen <[email protected]> and Jim Keniston +* <[email protected]> Added function-return probes, aka exit +* probes. */ #include <linux/config.h> #include <linux/list.h>
@@ -34,12 +37,15 @@struct kprobe ;struct pt_regs ; +struct retprobe_instance ;typedef int (*kprobe_pre_handler_t ) (struct kprobe *,struct pt_regs *);typedef int (*kprobe_break_handler_t ) (struct kprobe *,struct pt_regs *);typedef void (*kprobe_post_handler_t ) (struct kprobe *,struct pt_regs *,unsigned long flags);typedef int (*kprobe_fault_handler_t ) (struct kprobe *,struct pt_regs *,int trapnr); +typedef int (*retprobe_handler_t ) (struct retprobe_instance *,struct pt_regs *); +struct kprobe {struct hlist_node hlist;
@@ -65,6 +71,9 @@/* copy of the original instruction */ struct arch_specific_insn ainsn; + +/* point to retprobe */ +struct retprobe *rp; };/*
@@ -82,6 +91,49 @@kprobe_opcode_t *entry;/* probe handling code to jump to */ }; +#ifdef arch_supports_retprobes +extern int trampoline_probe_handler (struct kprobe *p,struct pt_regs *regs); +extern struct task_struct *arch_get_kprobe_task (void *ptr); +#else +#define arch_supports_retprobes 0 +static void retprobe_trampoline (void ) +{ +} +static int trampoline_probe_handler (struct kprobe *p,struct pt_regs *regs) +{ +return 0 ; +} +#define arch_get_kprobe_task (ptr) ((struct task_struct *)NULL) +#endif +/* +* Function-return probe - +* Note: +* User needs to provide a handler function, and initialize maxactive. +* maxactive - The maximum number of instances of the probed function that +* can be active concurrently. +* nmissed - tracks the number of times the probed function's return was +* ignored, due to maxactive being too low. +* +*/ +struct retprobe { +retprobe_handler_t handler; +int maxactive; +int nmissed; +int num_ri_running; +int unregistering; +struct kprobe *kprobe; +struct retprobe_instance *instances;/* allocated memory */ +struct list_head free_instances; +}; + +struct retprobe_instance { +struct list_head list; +struct hlist_node hlist; +struct retprobe *rp; +void *ret_addr; +void *stack_addr; +}; +#ifdef CONFIG_KPROBES /* Locks kprobe: irq must be disabled */ void lock_kprobes (void );
@@ -110,6 +162,14 @@void unregister_jprobe (struct jprobe *p);void jprobe_return (void ); +int register_kretprobe (struct kprobe *p,struct retprobe *rp); +int register_jretprobe (struct jprobe *p,struct retprobe *rp); + +struct retprobe_instance *get_free_rp_inst (struct retprobe *rp); +struct retprobe_instance *get_rp_inst (void *sara); +void add_retprobe_inst_to_hash (struct retprobe_instance *ri); +void kprobe_flush_task (struct task_struct *tk); +void recycle_retprobe_instance (struct retprobe_instance *ri);#else static inline int kprobe_running (void ) {
@@ -132,5 +192,13 @@static inline void jprobe_return (void ) { } +static inline int register_kretprobe (struct kprobe *p,struct retprobe *rp) +{ +return -ENOSYS ; +} +static inline int register_jretprobe (struct jprobe *p,struct retprobe *rp) +{ +return -ENOSYS ; +}#endif #endif /* _LINUX_KPROBES_H */
tmp/linux-2.6.12-rc1.mm3.works/kernel/kprobes.c renamed from kernel/kprobes.c +204 -1
258 lines not on this page · raw message
tmp/linux-2.6.12-rc1.mm3.works/arch/i386/kernel/kprobes.c renamed from arch/i386/kernel/kprobes.c +67 -0
97 lines not on this page · raw message
tmp/linux-2.6.12-rc1.mm3.works/arch/i386/kernel/entry.S renamed from arch/i386/kernel/entry.S +11 -0
@@ -136,6 +136,17 @@ .previous +#ifdef CONFIG_KPROBES +/* + * For function-return probes, init_retprobes() establishes a probepoint + * here. When a retprobed function returns, this probe is hit and + * trampoline_probe_handler() runs, calling the retprobe's handler. + */ +ENTRY(retprobe_trampoline) + nop +/* NOT REACHED */ +#endif + ENTRY(ret_from_fork) pushl %eax call schedule_tail
tmp/linux-2.6.12-rc1.mm3.works/arch/i386/kernel/process.c renamed from arch/i386/kernel/process.c +17 -2
@@ -39,6 +39,7 @@#include <linux/kallsyms.h> #include <linux/ptrace.h> #include <linux/random.h> +#include <linux/kprobes.h> #include <asm/uaccess.h> #include <asm/pgtable.h>
@@ -371,7 +372,14 @@ {struct task_struct *tsk = current;struct thread_struct *t = &tsk->thread; - +#ifdef CONFIG_KPROBES +/* +* Remove function-return probe instances associated with this task +* and put them back on the free list. Do not insert an exit probe for +* this function, it will be disabled by kprobe_flush_task if you do. +*/ +kprobe_flush_task (tsk); +#endif /* The process may have allocated an io port bitmap... nuke it. */ if (unlikely (NULL != t->io_bitmap_ptr)) {int cpu =get_cpu ();
@@ -395,7 +403,14 @@void flush_thread (void ) {struct task_struct *tsk = current; - +#ifdef CONFIG_KPROBES +/* +* Remove function-return probe instances associated with this task +* and put them back on the free list. Do not insert an exit probe for +* this function, it will be disabled by kprobe_flush_task if you do. +*/ +kprobe_flush_task (tsk); +#endif memset (tsk->thread.debugreg,0 ,sizeof (unsigned long )*8 );memset (tsk->thread.tls_array,0 ,sizeof (tsk->thread.tls_array));/*
tmp/linux-2.6.12-rc1.mm3.works/include/asm-i386/kprobes.h renamed from include/asm-i386/kprobes.h +3 -0
@@ -39,6 +39,9 @@ : (((unsigned long)current_thread_info()) + THREAD_SIZE - (ADDR)))#define JPROBE_ENTRY (pentry) (kprobe_opcode_t *)pentry +#define arch_supports_retprobes 1 + +asmlinkage void retprobe_trampoline(void) __asm__("retprobe_trampoline");/* Architecture specific copy of original instruction*/ struct arch_specific_insn {