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 "dbi_uprobes.h"
29 #include "dbi_insn_slots.h"
30 #include "dbi_kdebug.h"
32 #include <linux/hash.h>
33 #include <linux/mempolicy.h>
34 #include <linux/module.h>
36 struct hlist_head uprobe_insn_slot_table[KPROBE_TABLE_SIZE];
39 #define DEBUG_PRINT_HASH_TABLE 0
41 #if DEBUG_PRINT_HASH_TABLE
42 void print_kprobe_hash_table(void)
45 struct hlist_head *head;
46 struct hlist_node *node;
50 for (i = 0; i < KPROBE_TABLE_SIZE; ++i) {
51 head = &kprobe_table[i];
52 swap_hlist_for_each_entry_rcu (p, node, head, is_hlist_arm) {
53 printk("####### find K tgid=%u, addr=%x\n",
59 void print_kretprobe_hash_table(void)
62 struct hlist_head *head;
63 struct hlist_node *node;
67 for (i = 0; i < KPROBE_TABLE_SIZE; ++i) {
68 head = &kretprobe_inst_table[i];
69 swap_hlist_for_each_entry_rcu (p, node, head, is_hlist_arm) {
70 printk("####### find KR tgid=%u, addr=%x\n",
76 void print_uprobe_hash_table(void)
79 struct hlist_head *head;
80 struct hlist_node *node;
84 for (i = 0; i < KPROBE_TABLE_SIZE; ++i) {
85 head = &uprobe_insn_slot_table[i];
86 swap_hlist_for_each_entry_rcu (p, node, head, is_hlist_arm) {
87 printk("####### find U tgid=%u, addr=%x\n",
95 static void add_uprobe_table(struct kprobe *p)
98 INIT_HLIST_NODE(&p->is_hlist_arm);
99 hlist_add_head_rcu(&p->is_hlist_arm, &uprobe_insn_slot_table[hash_ptr (p->ainsn.insn_arm, KPROBE_HASH_BITS)]);
100 INIT_HLIST_NODE(&p->is_hlist_thumb);
101 hlist_add_head_rcu(&p->is_hlist_thumb, &uprobe_insn_slot_table[hash_ptr (p->ainsn.insn_thumb, KPROBE_HASH_BITS)]);
102 #else /* CONFIG_ARM */
103 INIT_HLIST_NODE(&p->is_hlist);
104 hlist_add_head_rcu(&p->is_hlist, &uprobe_insn_slot_table[hash_ptr (p->ainsn.insn, KPROBE_HASH_BITS)]);
105 #endif /* CONFIG_ARM */
109 static int __register_uprobe(struct kprobe *p, struct task_struct *task, int atomic)
112 struct kprobe *old_p;
118 DBPRINTF("p->addr = 0x%p p = 0x%p\n", p->addr, p);
120 // thumb address = address-1;
121 #if defined(CONFIG_ARM)
122 // TODO: must be corrected in 'bundle'
123 if ((unsigned long) p->addr & 0x01) {
124 p->addr = (kprobe_opcode_t *)((unsigned long)p->addr & 0xfffffffe);
128 p->mod_refcounted = 0;
130 INIT_LIST_HEAD(&p->list);
131 #ifdef KPROBES_PROFILE
132 p->start_tm.tv_sec = p->start_tm.tv_usec = 0;
133 p->hnd_tm_sum.tv_sec = p->hnd_tm_sum.tv_usec = 0;
137 // get the first item
138 old_p = get_kprobe(p->addr, p->tgid);
141 p->safe_arm = old_p->safe_arm;
142 p->safe_thumb = old_p->safe_thumb;
144 ret = register_aggr_kprobe(old_p, p);
146 atomic_inc(&kprobe_count);
149 DBPRINTF("goto out\n", ret);
153 ret = arch_prepare_uprobe(p, task, atomic);
155 DBPRINTF("goto out\n", ret);
159 DBPRINTF ("before out ret = 0x%x\n", ret);
161 // TODO: add uprobe (must be in function)
162 INIT_HLIST_NODE(&p->hlist);
163 hlist_add_head_rcu(&p->hlist, &kprobe_table[hash_ptr (p->addr, KPROBE_HASH_BITS)]);
165 arch_arm_uprobe(p, task);
168 DBPRINTF("out ret = 0x%x\n", ret);
172 void unregister_uprobe(struct kprobe *p, struct task_struct *task, int atomic)
174 dbi_unregister_kprobe (p, task);
178 int dbi_register_ujprobe(struct task_struct *task, struct jprobe *jp, int atomic)
182 /* Todo: Verify probepoint is a function entry point */
183 jp->kp.pre_handler = setjmp_pre_handler;
184 jp->kp.break_handler = longjmp_break_handler;
186 ret = __register_uprobe(&jp->kp, task, atomic);
191 void dbi_unregister_ujprobe(struct task_struct *task, struct jprobe *jp, int atomic)
193 unregister_uprobe(&jp->kp, task, atomic);
195 * Here is an attempt to unregister even those probes that have not been
196 * installed (hence not added to the hlist).
197 * So if we try to delete them from the hlist we will get NULL pointer
198 * dereference error. That is why we check whether this node
199 * really belongs to the hlist.
202 if (!(hlist_unhashed(&jp->kp.is_hlist_arm))) {
203 hlist_del_rcu(&jp->kp.is_hlist_arm);
205 if (!(hlist_unhashed(&jp->kp.is_hlist_thumb))) {
206 hlist_del_rcu(&jp->kp.is_hlist_thumb);
208 #else /* CONFIG_ARM */
209 if (!(hlist_unhashed(&jp->kp.is_hlist))) {
210 hlist_del_rcu(&jp->kp.is_hlist);
212 #endif /* CONFIG_ARM */
215 int dbi_register_uretprobe(struct task_struct *task, struct kretprobe *rp, int atomic)
218 struct kretprobe_instance *inst;
220 DBPRINTF ("START\n");
222 rp->kp.pre_handler = pre_handler_kretprobe;
223 rp->kp.post_handler = NULL;
224 rp->kp.fault_handler = NULL;
225 rp->kp.break_handler = NULL;
229 /* Pre-allocate memory for max kretprobe instances */
230 if (rp->maxactive <= 0) {
231 #if 1//def CONFIG_PREEMPT
232 rp->maxactive = max(10, 2 * NR_CPUS);
234 rp->maxactive = NR_CPUS;
238 INIT_HLIST_HEAD(&rp->used_instances);
239 INIT_HLIST_HEAD(&rp->free_instances);
241 for (i = 0; i < rp->maxactive; i++) {
242 inst = kmalloc(sizeof(*inst), GFP_KERNEL);
249 INIT_HLIST_NODE(&inst->uflist);
250 hlist_add_head(&inst->uflist, &rp->free_instances);
255 /* Establish function exit probe point */
256 ret = arch_prepare_uretprobe(rp, task);
261 /* Establish function entry probe point */
262 ret = __register_uprobe(&rp->kp, task, atomic);
268 arch_arm_uretprobe(rp, task);
273 int dbi_disarm_urp_inst(struct kretprobe_instance *ri, struct task_struct *rm_task)
275 struct task_struct *task = rm_task ? rm_task : ri->task;
276 unsigned long *tramp;
277 unsigned long *sp = (unsigned long *)((long)ri->sp & ~1);
278 unsigned long *stack = sp - RETPROBE_STACK_DEPTH + 1;
279 unsigned long *found = NULL;
280 unsigned long *buf[RETPROBE_STACK_DEPTH];
283 /* Understand function mode */
284 if ((long)ri->sp & 1) {
285 tramp = (unsigned long *)
286 ((unsigned long)ri->rp->kp.ainsn.insn + 0x1b);
288 tramp = (unsigned long *)
289 (ri->rp->kp.ainsn.insn + UPROBES_TRAMP_RET_BREAK_IDX);
292 retval = read_proc_vm_atomic(task, (unsigned long)stack, buf, sizeof(buf));
293 if (retval != sizeof(buf)) {
294 printk("---> %s (%d/%d): failed to read stack from %08lx",
295 task->comm, task->tgid, task->pid, (unsigned long)stack);
300 /* search the stack from the bottom */
301 for (i = RETPROBE_STACK_DEPTH - 1; i >= 0; i--) {
302 if (buf[i] == tramp) {
309 printk("---> %s (%d/%d): trampoline found at %08lx (%08lx /%+d) - %p\n",
310 task->comm, task->tgid, task->pid,
311 (unsigned long)found, (unsigned long)sp,
312 found - sp, ri->rp->kp.addr);
313 retval = write_proc_vm_atomic(task, (unsigned long)found, &ri->ret_addr,
314 sizeof(ri->ret_addr));
315 if (retval != sizeof(ri->ret_addr)) {
316 printk("---> %s (%d/%d): failed to write value to %08lx",
317 task->comm, task->tgid, task->pid, (unsigned long)found);
323 struct pt_regs *uregs = task_pt_regs(ri->task);
324 unsigned long ra = dbi_get_ret_addr(uregs);
325 if (ra == (unsigned long)tramp) {
326 printk("---> %s (%d/%d): trampoline found at lr = %08lx - %p\n",
327 task->comm, task->tgid, task->pid, ra, ri->rp->kp.addr);
328 dbi_set_ret_addr(uregs, (unsigned long)tramp);
331 printk("---> %s (%d/%d): trampoline NOT found at sp = %08lx, lr = %08lx - %p\n",
332 task->comm, task->tgid, task->pid,
333 (unsigned long)sp, ra, ri->rp->kp.addr);
342 void dbi_unregister_uretprobe(struct task_struct *task, struct kretprobe *rp, int atomic, int not_rp2)
345 struct kretprobe_instance *ri;
346 struct kretprobe *rp2 = NULL;
348 spin_lock_irqsave (&kretprobe_lock, flags);
350 while ((ri = get_used_rp_inst(rp)) != NULL) {
351 if (dbi_disarm_urp_inst(ri, NULL) != 0)
352 /*panic*/printk("%s (%d/%d): cannot disarm urp instance (%08lx)\n",
353 ri->task->comm, ri->task->tgid, ri->task->pid,
354 (unsigned long)rp->kp.addr);
358 if (hlist_empty(&rp->used_instances) || not_rp2) {
359 struct kprobe *p = &rp->kp;
360 // if there are no used retprobe instances (i.e. function is not entered) - disarm retprobe
361 arch_disarm_uretprobe(rp, task);//vmas[1], pages[1], kaddrs[1]);
363 if (!(hlist_unhashed(&p->is_hlist_arm))) {
364 hlist_del_rcu(&p->is_hlist_arm);
367 if (!(hlist_unhashed(&p->is_hlist_thumb))) {
368 hlist_del_rcu(&p->is_hlist_thumb);
370 #else /* CONFIG_ARM */
371 if (!(hlist_unhashed(&p->is_hlist))) {
372 hlist_del_rcu(&p->is_hlist);
374 #endif /* CONFIG_ARM */
376 struct kprobe *new_p = NULL;
377 struct kprobe *p = &rp->kp;
378 rp2 = clone_kretprobe(rp);
380 DBPRINTF ("dbi_unregister_uretprobe addr %p: failed to clone retprobe!", rp->kp.addr);
382 DBPRINTF ("initiating deferred retprobe deletion addr %p", rp->kp.addr);
383 printk ("initiating deferred retprobe deletion addr %p\n", rp->kp.addr);
384 arch_disarm_uprobe(&rp->kp, task);
388 * As we cloned retprobe we have to update the entry in the insn slot
392 if (!(hlist_unhashed(&p->is_hlist_arm))) {
393 hlist_del_rcu(&p->is_hlist_arm);
395 if (!(hlist_unhashed(&p->is_hlist_thumb))) {
396 hlist_del_rcu(&p->is_hlist_thumb);
398 #else /* CONFIG_ARM */
399 if (!(hlist_unhashed(&p->is_hlist))) {
400 hlist_del_rcu(&p->is_hlist);
402 #endif /* CONFIG_ARM */
404 add_uprobe_table(new_p);
407 while ((ri = get_used_rp_inst(rp)) != NULL) {
410 hlist_del(&ri->uflist);
413 spin_unlock_irqrestore(&kretprobe_lock, flags);
416 unregister_uprobe(&rp->kp, task, atomic);
419 void dbi_unregister_all_uprobes(struct task_struct *task, int atomic)
421 struct hlist_head *head;
422 struct hlist_node *node, *tnode;
426 for (i = 0; i < KPROBE_TABLE_SIZE; ++i) {
427 head = &kprobe_table[i];
428 swap_hlist_for_each_entry_safe(p, node, tnode, head, hlist) {
429 if (p->tgid == task->tgid) {
430 printk("dbi_unregister_all_uprobes: delete uprobe at %p[%lx] for %s/%d\n",
431 p->addr, (unsigned long)p->opcode, task->comm, task->pid);
432 unregister_uprobe(p, task, atomic);
438 void init_uprobes_insn_slots(int i)
440 INIT_HLIST_HEAD(&uprobe_insn_slot_table[i]);
443 void dbi_uprobe_return(void)
445 dbi_arch_uprobe_return();
449 EXPORT_SYMBOL_GPL(dbi_uprobe_return);
450 EXPORT_SYMBOL_GPL(dbi_register_ujprobe);
451 EXPORT_SYMBOL_GPL(dbi_unregister_ujprobe);
452 EXPORT_SYMBOL_GPL(dbi_register_uretprobe);
453 EXPORT_SYMBOL_GPL(dbi_unregister_uretprobe);
454 EXPORT_SYMBOL_GPL(dbi_unregister_all_uprobes);