2 * Dynamic Binary Instrumentation Module based on KProbes
3 * modules/kprobe/dbi_uprobes.h
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 * Copyright (C) Samsung Electronics, 2006-2010
21 * 2008-2009 Alexey Gerenkov <a.gerenkov@samsung.com> User-Space
22 * Probes initial implementation; Support x86/ARM/MIPS for both user and kernel spaces.
23 * 2010 Ekaterina Gorelkina <e.gorelkina@samsung.com>: redesign module for separating core and arch parts
28 #include <linux/hash.h>
29 #include <linux/mempolicy.h>
30 #include <linux/module.h>
32 #include "dbi_uprobes.h"
33 #include "dbi_insn_slots.h"
34 #include "dbi_kdebug.h"
36 extern atomic_t kprobe_count;
37 extern struct hlist_head kprobe_table[KPROBE_TABLE_SIZE];
38 extern struct hlist_head kretprobe_inst_table[KPROBE_TABLE_SIZE];
39 extern spinlock_t kretprobe_lock;
41 extern struct kretprobe *sched_rp;
43 struct hlist_head uprobe_insn_slot_table[KPROBE_TABLE_SIZE];
46 int __register_uprobe (struct kprobe *p, struct task_struct *task, int atomic, unsigned long called_from)
54 DBPRINTF ("p->addr = 0x%p p = 0x%p\n", p->addr, p);
56 p->mod_refcounted = 0;
58 #ifdef KPROBES_PROFILE
59 p->start_tm.tv_sec = p->start_tm.tv_usec = 0;
60 p->hnd_tm_sum.tv_sec = p->hnd_tm_sum.tv_usec = 0;
65 old_p = get_kprobe (p->addr, p->tgid, NULL);
68 ret = register_aggr_kprobe (old_p, p);
70 atomic_inc (&kprobe_count);
73 if ((ret = arch_prepare_uprobe (p, task, atomic)) != 0)
78 DBPRINTF ("before out ret = 0x%x\n", ret);
80 INIT_HLIST_NODE (&p->hlist);
81 hlist_add_head_rcu (&p->hlist, &kprobe_table[hash_ptr (p->addr, KPROBE_HASH_BITS)]);
83 INIT_HLIST_NODE (&p->is_hlist);
84 hlist_add_head_rcu (&p->is_hlist, &uprobe_insn_slot_table[hash_ptr (p->ainsn.insn, KPROBE_HASH_BITS)]);
86 arch_arm_uprobe (p, task);
88 DBPRINTF ("out ret = 0x%x\n", ret);
93 void unregister_uprobe (struct kprobe *p, struct task_struct *task, int atomic)
95 unregister_kprobe (p, task, atomic);
99 int register_ujprobe (struct task_struct *task, struct mm_struct *mm, struct jprobe *jp, int atomic)
103 /* Todo: Verify probepoint is a function entry point */
104 jp->kp.pre_handler = setjmp_pre_handler;
105 jp->kp.break_handler = longjmp_break_handler;
107 ret = __register_uprobe (&jp->kp, task, atomic,
108 (unsigned long) __builtin_return_address (0));
113 void unregister_ujprobe (struct task_struct *task, struct jprobe *jp, int atomic)
115 unregister_uprobe (&jp->kp, task, atomic);
118 int register_uretprobe (struct task_struct *task, struct mm_struct *mm, struct kretprobe *rp, int atomic)
121 struct kretprobe_instance *inst;
124 DBPRINTF ("START\n");
126 rp->kp.pre_handler = pre_handler_kretprobe;
127 rp->kp.post_handler = NULL;
128 rp->kp.fault_handler = NULL;
129 rp->kp.break_handler = NULL;
133 /* Pre-allocate memory for max kretprobe instances */
134 if (rp->maxactive <= 0)
136 #if 1//def CONFIG_PREEMPT
137 rp->maxactive = max (10, 2 * NR_CPUS);
139 rp->maxactive = NR_CPUS;
142 INIT_HLIST_HEAD (&rp->used_instances);
143 INIT_HLIST_HEAD (&rp->free_instances);
144 for (i = 0; i < rp->maxactive; i++)
146 inst = kmalloc (sizeof (struct kretprobe_instance), GFP_KERNEL);
153 INIT_HLIST_NODE (&inst->uflist);
154 hlist_add_head (&inst->uflist, &rp->free_instances);
159 /* Establish function exit probe point */
160 if ((ret = arch_prepare_uretprobe (rp, task)) != 0)
162 /* Establish function entry probe point */
163 if ((ret = __register_uprobe (&rp->kp, task, atomic,
164 (unsigned long) __builtin_return_address (0))) != 0)
170 arch_arm_uretprobe (rp, task);//vmas[1], pages[1], kaddrs[1]);
176 void unregister_uretprobe (struct task_struct *task, struct kretprobe *rp, int atomic)
179 struct kretprobe_instance *ri;
180 struct kretprobe *rp2 = NULL;
182 spin_lock_irqsave (&kretprobe_lock, flags);
183 if (hlist_empty (&rp->used_instances))
185 // if there are no used retprobe instances (i.e. function is not entered) - disarm retprobe
186 arch_disarm_uretprobe (rp, task);//vmas[1], pages[1], kaddrs[1]);
190 rp2 = clone_kretprobe (rp);
192 DBPRINTF ("unregister_uretprobe addr %p: failed to clone retprobe!", rp->kp.addr);
195 DBPRINTF ("initiating deferred retprobe deletion addr %p", rp->kp.addr);
196 printk ("initiating deferred retprobe deletion addr %p\n", rp->kp.addr);
201 while ((ri = get_used_rp_inst (rp)) != NULL)
205 hlist_del (&ri->uflist);
207 spin_unlock_irqrestore (&kretprobe_lock, flags);
210 unregister_uprobe (&rp->kp, task, atomic);
213 void unregister_all_uprobes (struct task_struct *task, int atomic)
215 struct hlist_head *head;
216 struct hlist_node *node, *tnode;
220 for(i = 0; i < KPROBE_TABLE_SIZE; i++){
221 head = &kprobe_table[i];
222 hlist_for_each_entry_safe (p, node, tnode, head, hlist){
223 if(p->tgid == task->tgid){
224 printk("unregister_all_uprobes: delete uprobe at %pf for %s/%d\n", p->addr, task->comm, task->pid);
225 unregister_uprobe (p, task, atomic);
229 purge_garbage_uslots(task, atomic);
232 void init_uprobes_insn_slots(int i)
234 INIT_HLIST_HEAD (&uprobe_insn_slot_table[i]);
237 void uprobe_return (void)
239 arch_uprobe_return();
243 EXPORT_SYMBOL_GPL (uprobe_return);
244 EXPORT_SYMBOL_GPL (register_ujprobe);
245 EXPORT_SYMBOL_GPL (unregister_ujprobe);
246 EXPORT_SYMBOL_GPL (register_uretprobe);
247 EXPORT_SYMBOL_GPL (unregister_uretprobe);
248 EXPORT_SYMBOL_GPL (unregister_all_uprobes);