public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [patch 1/1] Allow a jprobe to coexist with muliple kprobes
@ 2005-06-02  9:46 Prasanna S Panchamukhi
  2005-06-02 10:23 ` Dipankar Sarma
  0 siblings, 1 reply; 3+ messages in thread
From: Prasanna S Panchamukhi @ 2005-06-02  9:46 UTC (permalink / raw)
  To: akpm, ak, davem, amavin; +Cc: linux-kernel, systemtap

Hi,

Please provide your comments on the patch below. This patch has
been tested on i386 and x86_64 architecture.

Thanks
Prasanna

Presently either multiple kprobes or only one jprobe could be inserted. This
patch removes the above limitation and allows one jprobe and multiple kprobes to
coexist at the same address. 

Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com>
Signed-off-by: Ananth N Mavinakayanhalli <amavin@redhat.com>


---

 linux-2.6.12-rc5-mm2-prasanna/kernel/kprobes.c |   61 ++++++++++++++++++++-----
 1 files changed, 51 insertions(+), 10 deletions(-)

diff -puN kernel/kprobes.c~jprobe-kprobe-can-coexist kernel/kprobes.c
--- linux-2.6.12-rc5-mm2/kernel/kprobes.c~jprobe-kprobe-can-coexist	2005-06-02 11:53:58.000000000 +0530
+++ linux-2.6.12-rc5-mm2-prasanna/kernel/kprobes.c	2005-06-02 11:53:58.000000000 +0530
@@ -89,9 +89,10 @@ int aggr_pre_handler(struct kprobe *p, s
 	list_for_each_entry(kp, &p->list, list) {
 		if (kp->pre_handler) {
 			curr_kprobe = kp;
-			kp->pre_handler(kp, regs);
-			curr_kprobe = NULL;
+			if (kp->pre_handler(kp, regs))
+				return 1;
 		}
+		curr_kprobe = NULL;
 	}
 	return 0;
 }
@@ -124,6 +125,19 @@ int aggr_fault_handler(struct kprobe *p,
 	return 0;
 }
 
+int aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct kprobe *kp = curr_kprobe;
+	if (curr_kprobe && kp->break_handler) {
+		if (kp->break_handler(kp, regs)) {
+			curr_kprobe = NULL;
+			return 1;
+		}
+	}
+	curr_kprobe = NULL;
+	return 0;
+}
+
 struct kprobe trampoline_p = {
 		.addr = (kprobe_opcode_t *) &kretprobe_trampoline,
 		.pre_handler = trampoline_probe_handler,
@@ -257,18 +271,45 @@ inline void free_rp_inst(struct kretprob
 }
 
 /*
+ * Keep all fields in the kprobe consistent
+ */
+static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
+{
+	memcpy(&p->opcode, &old_p->opcode, sizeof(kprobe_opcode_t));
+	memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_specific_insn));
+}
+
+/*
+* Add the new probe to old_p->list. Fail if this is the
+* second jprobe at the address - two jprobes can't coexist
+*/
+static int add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
+{
+        struct kprobe *kp;
+
+	if (p->break_handler) {
+		list_for_each_entry(kp, &old_p->list, list) {
+			if (kp->break_handler)
+				return -EEXIST;
+		}
+		list_add_tail(&p->list, &old_p->list);
+	} else
+		list_add(&p->list, &old_p->list);
+	return 0;
+}
+
+/*
  * Fill in the required fields of the "manager kprobe". Replace the
  * earlier kprobe in the hlist with the manager kprobe
  */
 static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
 {
+	copy_kprobe(p, ap);
 	ap->addr = p->addr;
-	memcpy(&ap->opcode, &p->opcode, sizeof(kprobe_opcode_t));
-	memcpy(&ap->ainsn, &p->ainsn, sizeof(struct arch_specific_insn));
-
 	ap->pre_handler = aggr_pre_handler;
 	ap->post_handler = aggr_post_handler;
 	ap->fault_handler = aggr_fault_handler;
+	ap->break_handler = aggr_break_handler;
 
 	INIT_LIST_HEAD(&ap->list);
 	list_add(&p->list, &ap->list);
@@ -289,16 +330,16 @@ static int register_aggr_kprobe(struct k
 	int ret = 0;
 	struct kprobe *ap;
 
-	if (old_p->break_handler || p->break_handler) {
-		ret = -EEXIST;	/* kprobe and jprobe can't (yet) coexist */
-	} else if (old_p->pre_handler == aggr_pre_handler) {
-		list_add(&p->list, &old_p->list);
+	if (old_p->pre_handler == aggr_pre_handler) {
+		copy_kprobe(old_p, p);
+		ret = add_new_kprobe(old_p, p);
 	} else {
 		ap = kcalloc(1, sizeof(struct kprobe), GFP_ATOMIC);
 		if (!ap)
 			return -ENOMEM;
 		add_aggr_kprobe(ap, old_p);
-		list_add(&p->list, &ap->list);
+		copy_kprobe(ap, p);
+		ret = add_new_kprobe(ap, p);
 	}
 	return ret;
 }

_
-- 

Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<prasanna@in.ibm.com>

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [patch 1/1] Allow a jprobe to coexist with muliple kprobes
  2005-06-02  9:46 [patch 1/1] Allow a jprobe to coexist with muliple kprobes Prasanna S Panchamukhi
@ 2005-06-02 10:23 ` Dipankar Sarma
  2005-06-02 12:26   ` Prasanna S Panchamukhi
  0 siblings, 1 reply; 3+ messages in thread
From: Dipankar Sarma @ 2005-06-02 10:23 UTC (permalink / raw)
  To: Prasanna S Panchamukhi; +Cc: akpm, ak, davem, amavin, linux-kernel, systemtap

On Thu, Jun 02, 2005 at 03:16:30PM +0530, Prasanna S Panchamukhi wrote:
> Hi,
> 
> +int aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
> +{
> +	struct kprobe *kp = curr_kprobe;

Any reason why this or other handler functions can't be static ?

Thanks
Dipankar

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [patch 1/1] Allow a jprobe to coexist with muliple kprobes
  2005-06-02 10:23 ` Dipankar Sarma
@ 2005-06-02 12:26   ` Prasanna S Panchamukhi
  0 siblings, 0 replies; 3+ messages in thread
From: Prasanna S Panchamukhi @ 2005-06-02 12:26 UTC (permalink / raw)
  To: Dipankar Sarma; +Cc: akpm, ak, davem, amavin, linux-kernel, systemtap

Hi,

> > +int aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
> > +{
> > +	struct kprobe *kp = curr_kprobe;
> 
> Any reason why this or other handler functions can't be static ?
> 

Good catch, this handler can be made static. I have modified the patch as per 
your comments. Other handlers can also be made static, I will send out another 
patch for that.

Thanks
Prasanna

Presently either multiple kprobes or only one jprobe could be inserted. This
patch removes the above limitation and allows one jprobe and multiple kprobes to
coexist at the same address. However multiple jprobes cannot coexist with 
multiple kprobes. Currently I am working on the prototype to allow multiple 
jprobes coexist with multiple kprobes.

Signed-off-by: Ananth N Mavinakayanhalli <amavin@redhat.com>
Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com>


---

 linux-2.6.12-rc5-mm2-prasanna/kernel/kprobes.c |   61 ++++++++++++++++++++-----
 1 files changed, 51 insertions(+), 10 deletions(-)

diff -puN kernel/kprobes.c~jprobe-kprobe-can-coexist kernel/kprobes.c
--- linux-2.6.12-rc5-mm2/kernel/kprobes.c~jprobe-kprobe-can-coexist	2005-06-02 17:48:31.000000000 +0530
+++ linux-2.6.12-rc5-mm2-prasanna/kernel/kprobes.c	2005-06-02 17:49:12.000000000 +0530
@@ -89,9 +89,10 @@ int aggr_pre_handler(struct kprobe *p, s
 	list_for_each_entry(kp, &p->list, list) {
 		if (kp->pre_handler) {
 			curr_kprobe = kp;
-			kp->pre_handler(kp, regs);
-			curr_kprobe = NULL;
+			if (kp->pre_handler(kp, regs))
+				return 1;
 		}
+		curr_kprobe = NULL;
 	}
 	return 0;
 }
@@ -124,6 +125,19 @@ int aggr_fault_handler(struct kprobe *p,
 	return 0;
 }
 
+static int aggr_break_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct kprobe *kp = curr_kprobe;
+	if (curr_kprobe && kp->break_handler) {
+		if (kp->break_handler(kp, regs)) {
+			curr_kprobe = NULL;
+			return 1;
+		}
+	}
+	curr_kprobe = NULL;
+	return 0;
+}
+
 struct kprobe trampoline_p = {
 		.addr = (kprobe_opcode_t *) &kretprobe_trampoline,
 		.pre_handler = trampoline_probe_handler,
@@ -257,18 +271,45 @@ inline void free_rp_inst(struct kretprob
 }
 
 /*
+ * Keep all fields in the kprobe consistent
+ */
+static inline void copy_kprobe(struct kprobe *old_p, struct kprobe *p)
+{
+	memcpy(&p->opcode, &old_p->opcode, sizeof(kprobe_opcode_t));
+	memcpy(&p->ainsn, &old_p->ainsn, sizeof(struct arch_specific_insn));
+}
+
+/*
+* Add the new probe to old_p->list. Fail if this is the
+* second jprobe at the address - two jprobes can't coexist
+*/
+static int add_new_kprobe(struct kprobe *old_p, struct kprobe *p)
+{
+        struct kprobe *kp;
+
+	if (p->break_handler) {
+		list_for_each_entry(kp, &old_p->list, list) {
+			if (kp->break_handler)
+				return -EEXIST;
+		}
+		list_add_tail(&p->list, &old_p->list);
+	} else
+		list_add(&p->list, &old_p->list);
+	return 0;
+}
+
+/*
  * Fill in the required fields of the "manager kprobe". Replace the
  * earlier kprobe in the hlist with the manager kprobe
  */
 static inline void add_aggr_kprobe(struct kprobe *ap, struct kprobe *p)
 {
+	copy_kprobe(p, ap);
 	ap->addr = p->addr;
-	memcpy(&ap->opcode, &p->opcode, sizeof(kprobe_opcode_t));
-	memcpy(&ap->ainsn, &p->ainsn, sizeof(struct arch_specific_insn));
-
 	ap->pre_handler = aggr_pre_handler;
 	ap->post_handler = aggr_post_handler;
 	ap->fault_handler = aggr_fault_handler;
+	ap->break_handler = aggr_break_handler;
 
 	INIT_LIST_HEAD(&ap->list);
 	list_add(&p->list, &ap->list);
@@ -289,16 +330,16 @@ static int register_aggr_kprobe(struct k
 	int ret = 0;
 	struct kprobe *ap;
 
-	if (old_p->break_handler || p->break_handler) {
-		ret = -EEXIST;	/* kprobe and jprobe can't (yet) coexist */
-	} else if (old_p->pre_handler == aggr_pre_handler) {
-		list_add(&p->list, &old_p->list);
+	if (old_p->pre_handler == aggr_pre_handler) {
+		copy_kprobe(old_p, p);
+		ret = add_new_kprobe(old_p, p);
 	} else {
 		ap = kcalloc(1, sizeof(struct kprobe), GFP_ATOMIC);
 		if (!ap)
 			return -ENOMEM;
 		add_aggr_kprobe(ap, old_p);
-		list_add(&p->list, &ap->list);
+		copy_kprobe(ap, p);
+		ret = add_new_kprobe(ap, p);
 	}
 	return ret;
 }

_
-- 

Prasanna S Panchamukhi
Linux Technology Center
India Software Labs, IBM Bangalore
Ph: 91-80-25044636
<prasanna@in.ibm.com>

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2005-06-02 12:21 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2005-06-02  9:46 [patch 1/1] Allow a jprobe to coexist with muliple kprobes Prasanna S Panchamukhi
2005-06-02 10:23 ` Dipankar Sarma
2005-06-02 12:26   ` Prasanna S Panchamukhi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox