This is the mail archive of the systemtap@sources.redhat.com mailing list for the systemtap project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [RFC] Design + prototype: Multiple kprobes at an address - take 2


Hi,

Please find the patch to provide multiple handlers feature.

Your comments are welcome!


Thanks
Prasanna

Here is an attempt to provide multiple handlers feature as an addon patch over
the existing kprobes infrastructure without even changing existing kprobes
infrastructure. This patch introduces two new interface
register_multiprobe(struct mult_handler *mh); and 
unregister_multiprobe(struct mult_handler *mh);

register_multiprobe(struct mult_handler *mh): 
	User has to allocate mult_handler (defined in kprobes.h) and pass
the pointer to register_multiprobe();
This routine does some housekeeping by storing reference to individual
handlers and registering kprobes with common handler if the user requests for
the first time at a given address. On subsequenct calls to insert probes on
the same address, this routines just adds the individual handlers to the list
without registering the kprobes.
unregister_multiprobe(struct mult_handler *mh);
	User has to pass the mult_handler pointer to unregister.
This routine just check if the he is the only active user and calls unregister
kprobes. If there are more active users, it just removes the individual hanlders
inserted by this user from the list.

Signed-off-by: Prasanna S Panchamukhi <prasanna@in.ibm.com>


---

 linux-2.6.12-rc2-prasanna/include/linux/kprobes.h |   20 ++
 linux-2.6.12-rc2-prasanna/kernel/kprobes.c        |  172 ++++++++++++++++++++++
 2 files changed, 192 insertions(+)

diff -puN kernel/kprobes.c~kprobes-layered-multiple-handlers kernel/kprobes.c
--- linux-2.6.12-rc2/kernel/kprobes.c~kprobes-layered-multiple-handlers	2005-04-07 19:35:54.000000000 +0530
+++ linux-2.6.12-rc2-prasanna/kernel/kprobes.c	2005-04-07 19:36:21.000000000 +0530
@@ -27,6 +27,9 @@
  *		interface to access function arguments.
  * 2004-Sep	Prasanna S Panchamukhi <prasanna@in.ibm.com> Changed Kprobes
  *		exceptions notifier to be first on the priority list.
+ * 2005-April	Prasanna S Panchamukhi <prasanna@in.ibm.com> Added multiple
+ *		hanlders feature as an addon interface over existing kprobes
+ *		interface.
  */
 #include <linux/kprobes.h>
 #include <linux/spinlock.h>
@@ -44,6 +47,7 @@ static struct hlist_head kprobe_table[KP
 
 unsigned int kprobe_cpu = NR_CPUS;
 static DEFINE_SPINLOCK(kprobe_lock);
+static DEFINE_SPINLOCK(multprobe_lock);
 
 /* Locks kprobe: irqs must be disabled */
 void lock_kprobes(void)
@@ -116,6 +120,172 @@ void unregister_kprobe(struct kprobe *p)
 	spin_unlock_irqrestore(&kprobe_lock, flags);
 }
 
+
+/* common kprobes pre handler that gets control when the registered probe
+ * gets fired. This routines is wrapper over the insereted multiple handlers
+ * at a given address and calls individual handlers.
+ */
+int comm_pre_handler(struct kprobe *p, struct pt_regs *regs)
+{
+	struct mult_probe *mp;
+	struct hlist_node *node;
+	struct hlist_head *head;
+	unsigned long flags;
+
+	spin_lock_irqsave(&multprobe_lock, flags);
+	mp = container_of(p, struct mult_probe, comm_probe);
+	if (!mp)
+		goto out;
+	head = &mp->head;
+	hlist_for_each(node, head) {
+		struct mult_handler *mh =
+				hlist_entry(node, struct mult_handler, hlist);
+		if (mh->kp.pre_handler)
+			mh->kp.pre_handler(&mh->kp, regs);
+	}
+out:
+	spin_unlock_irqrestore(&multprobe_lock, flags);
+	return 0;
+}
+
+/* common kprobes post handler that gets control when the registered probe
+ * gets fired. This routines is wrapper over the insereted multiple handlers
+ * at a given address and calls individual handlers.
+ */
+void comm_post_handler(struct kprobe *p, struct pt_regs *regs,
+						unsigned long flags)
+{
+	struct mult_probe *mp;
+	struct hlist_node *node;
+	struct hlist_head *head;
+	unsigned long lflags = 0;
+
+	spin_lock_irqsave(&multprobe_lock, lflags);
+	if (!(mp = container_of(p, struct mult_probe, comm_probe))) {
+		spin_unlock_irqrestore(&multprobe_lock, lflags);
+		return;
+	}
+	head = &mp->head;
+	hlist_for_each(node, head) {
+		struct mult_handler *mh =
+				hlist_entry(node, struct mult_handler, hlist);
+		if (mh->kp.post_handler)
+			mh->kp.post_handler(&mh->kp, regs, flags);
+	}
+	spin_unlock_irqrestore(&multprobe_lock, lflags);
+	return;
+}
+
+/* common kprobes fault handler that gets control when the registered probe
+ * gets fired. This routines is wrapper over the inserted multiple handlers
+ * at a given address and calls individual handlers.
+ */
+int comm_fault_handler(struct kprobe *p, struct pt_regs *regs, int trapnr)
+{
+	struct mult_probe *mp;
+	struct hlist_node *node;
+	struct hlist_head *head;
+	unsigned long flags;
+
+	spin_lock_irqsave(&multprobe_lock, flags);
+	if (!(mp = container_of(p, struct mult_probe, comm_probe)))
+		goto out;
+
+	head = &mp->head;
+	hlist_for_each(node, head) {
+		struct mult_handler *mh =
+				hlist_entry(node, struct mult_handler, hlist);
+		if (mh->kp.fault_handler)
+			mh->kp.fault_handler(&mh->kp, regs, trapnr);
+	}
+out:
+	spin_unlock_irqrestore(&multprobe_lock, flags);
+	return 1;
+}
+
+/* New interface to support multiple handlers feature without even changing a
+ * single line of exiting kprobes interface and data structures. This routines
+ * accepts pointer to mult_handler structure, user has to allocate
+ * multi_handler structure and pass the pointer. This routine basically checks
+ * and registers the kprobes common handlers if the user is inserting a probe
+ * for the first time and saves the references to individual kprobes handlers.
+ * On subsequent call to this routine to insert multiple handler at the same
+ * address, it just adds the mult_handler structure to the list.
+ */
+int register_multiprobe(struct mult_handler *multh)
+{
+	struct mult_probe *multp = NULL;
+	struct kprobe *temp = NULL;
+	unsigned long flags = 0, flags1 = 0;
+	int ret = 0;
+
+	spin_lock_irqsave(&multprobe_lock, flags);
+
+	spin_lock_irqsave(&kprobe_lock, flags1);
+	temp = get_kprobe(multh->kp.addr);
+	spin_unlock_irqrestore(&kprobe_lock, flags1);
+	if (temp == NULL) {
+		multp = kmalloc(sizeof(struct mult_probe), GFP_ATOMIC);
+		if (!multp) {
+			ret = -ENOMEM;
+			goto out;
+		}
+		multp->comm_probe.addr = multh->kp.addr;
+		multp->comm_probe.pre_handler = comm_pre_handler;
+		multp->comm_probe.post_handler = comm_post_handler;
+		multp->comm_probe.fault_handler = comm_fault_handler;
+		INIT_HLIST_HEAD(&multp->head);
+		register_kprobe(&multp->comm_probe);
+	} else {
+		multp = container_of(temp, struct mult_probe, comm_probe);
+		if (!multp) {
+			ret = -EEXIST;
+			goto out;
+		}
+	}
+	INIT_HLIST_NODE(&multh->hlist);
+	hlist_add_head(&multh->hlist, &multp->head);
+out:
+	spin_unlock_irqrestore(&multprobe_lock, flags);
+	return ret;
+}
+
+/* New interface to remove a inserted kprobe if multiple handlers are defined
+ * for a given address. This routine accepts just a pointer to multi_handler
+ * structure. This routines checks and unregisters the probe, if the user trying
+ * to remove a probe is only the active user. If there are more active user
+ * registerd, it just deletes the multi_handler structure from the list.
+ */
+int unregister_multiprobe(struct mult_handler *multh)
+{
+	struct mult_probe *multp;
+	struct kprobe *temp;
+	unsigned long flags = 0, flags1 = 0;
+	int ret = -EEXIST;
+
+	spin_lock_irqsave(&multprobe_lock, flags);
+	spin_lock_irqsave(&kprobe_lock, flags1);
+	temp = get_kprobe(multh->kp.addr);
+	spin_unlock_irqrestore(&kprobe_lock, flags1);
+
+	if (!temp)
+		goto out;
+
+	if (!(multp = container_of(temp, struct mult_probe, comm_probe)))
+		goto out;
+
+	hlist_del(&multh->hlist);
+
+	if (hlist_empty(&multp->head)) {
+		unregister_kprobe(&multp->comm_probe);
+		kfree(multp);
+	}
+	ret = 0;
+out:
+	spin_unlock_irqrestore(&multprobe_lock, flags);
+	return ret;
+}
+
 static struct notifier_block kprobe_exceptions_nb = {
 	.notifier_call = kprobe_exceptions_notify,
 	.priority = 0x7fffffff /* we need to notified first */
@@ -155,3 +325,5 @@ EXPORT_SYMBOL_GPL(unregister_kprobe);
 EXPORT_SYMBOL_GPL(register_jprobe);
 EXPORT_SYMBOL_GPL(unregister_jprobe);
 EXPORT_SYMBOL_GPL(jprobe_return);
+EXPORT_SYMBOL_GPL(register_multiprobe);
+EXPORT_SYMBOL_GPL(unregister_multiprobe);
diff -puN include/linux/kprobes.h~kprobes-layered-multiple-handlers include/linux/kprobes.h
--- linux-2.6.12-rc2/include/linux/kprobes.h~kprobes-layered-multiple-handlers	2005-04-07 19:35:54.000000000 +0530
+++ linux-2.6.12-rc2-prasanna/include/linux/kprobes.h	2005-04-07 19:35:54.000000000 +0530
@@ -82,6 +82,26 @@ struct jprobe {
 	kprobe_opcode_t *entry;	/* probe handling code to jump to */
 };
 
+/*
+ * Addon feature to specify multiple handlers at a given address. Two new
+ * objects are defined mult_handler and mult_probe, which use the existing
+ * kprobes object. The way it works is by defining common handlers at a given
+ * address and by storing individual multiple handlers in the list for a given
+ * address. Later when probe is fired, control is passed to common handlers,
+ * where individual registered pre, post handlers get called.
+ */
+
+struct mult_handler {
+	struct hlist_node hlist;
+	struct kprobe kp; /*individual kprobes structure*/
+};
+
+struct mult_probe {
+	struct hlist_head head;
+	/*common kprobes object where common pre and post handlers are defined*/
+	struct kprobe comm_probe;
+};
+
 #ifdef CONFIG_KPROBES
 /* Locks kprobe: irq must be disabled */
 void lock_kprobes(void);

_
-- 

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


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]