X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=kernel%2Fkprobes.c;h=4a331aed086604fa05ba72b10bc836ee64657bf4;hb=6a77f38946aaee1cd85eeec6cf4229b204c15071;hp=ca4e28b4c6a759ab535bf94fe2c1b20d6377e084;hpb=87fc8d1bb10cd459024a742c6a10961fefcef18f;p=linux-2.6.git diff --git a/kernel/kprobes.c b/kernel/kprobes.c index ca4e28b4c..4a331aed0 100644 --- a/kernel/kprobes.c +++ b/kernel/kprobes.c @@ -43,7 +43,7 @@ static struct hlist_head kprobe_table[KPROBE_TABLE_SIZE]; unsigned int kprobe_cpu = NR_CPUS; -static spinlock_t kprobe_lock = SPIN_LOCK_UNLOCKED; +static DEFINE_SPINLOCK(kprobe_lock); /* Locks kprobe: irqs must be disabled */ void lock_kprobes(void) @@ -76,30 +76,37 @@ struct kprobe *get_kprobe(void *addr) int register_kprobe(struct kprobe *p) { int ret = 0; - unsigned long flags; + unsigned long flags = 0; + if ((ret = arch_prepare_kprobe(p)) != 0) { + goto out; + } spin_lock_irqsave(&kprobe_lock, flags); INIT_HLIST_NODE(&p->hlist); if (get_kprobe(p->addr)) { ret = -EEXIST; goto out; } + arch_copy_kprobe(p); + hlist_add_head(&p->hlist, &kprobe_table[hash_ptr(p->addr, KPROBE_HASH_BITS)]); - arch_prepare_kprobe(p); p->opcode = *p->addr; *p->addr = BREAKPOINT_INSTRUCTION; flush_icache_range((unsigned long) p->addr, (unsigned long) p->addr + sizeof(kprobe_opcode_t)); out: spin_unlock_irqrestore(&kprobe_lock, flags); + if (ret == -EEXIST) + arch_remove_kprobe(p); return ret; } void unregister_kprobe(struct kprobe *p) { unsigned long flags; + arch_remove_kprobe(p); spin_lock_irqsave(&kprobe_lock, flags); *p->addr = p->opcode; hlist_del(&p->hlist);