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: [Fwd: Re: [PATCH] Return probe]


Hien Nguyen wrote:
Hi Prasanna,
Here's the new retprobe patch, this patch should apply to linix-2.6.12-rc2-mm2 + Anandth's multihadler (the one posted on LKML).


Thanks for your suggestions.

Hien,


Some comments...

Thanks,
Ananth

...

+struct kprobe trampoline_p = {
+		.addr = (kprobe_opcode_t *) &kretprobe_trampoline,
+		.pre_handler = trampoline_probe_handler,
+		.post_handler = trampoline_post_handler
+};
+
+struct kretprobe_instance * get_free_rp_inst(struct kretprobe *rp)
+{
+	struct hlist_node *node;
+	struct kretprobe_instance *ri;
+	hlist_for_each_entry(ri, node, &rp->free_instances, uflist)
+		return ri;
+	return NULL;
+}	
+
+struct kretprobe_instance * get_used_rp_inst(struct kretprobe *rp)

Please make this consistent everywhere.. kretprobe_instance *get_used_..


....

+struct kretprobe_instance *get_rp_inst_tsk(struct task_struct *tk)
+{
+	struct task_struct *tsk;
+	struct hlist_head *head;
+	struct hlist_node *node;
+	struct kretprobe_instance *ri;
+
+	head = &kretprobe_inst_table[hash_ptr(tk, KPROBE_HASH_BITS)];
+	

Whitespace mangling.. here and a lot of other places.


+ hlist_for_each_entry(ri, node, head, hlist) {
+ tsk = arch_get_kprobe_task(ri->stack_addr);
+ if (tsk == tk)
+ return ri;
+ }
+ return NULL;
+}
+
+/*
+ * This function is called from do_exit or do_execv when task tk's stack is
+ * about to be recycled. Recycle any function-return probe instances + * associated with this task. These represent probed functions that have + * been called but may never return.
+ */
+void kprobe_flush_task(struct task_struct *tk)
+{
+ unsigned long flags = 0;
+ struct kretprobe_instance *ri;
+
+ if (!arch_supports_kretprobes)
+ return;
+
+ spin_lock_irqsave(&kprobe_lock, flags);
+ while ((ri = get_rp_inst_tsk(tk)) != NULL) {
+ /* TODO: arch specific */
+ *((unsigned long *)(ri->stack_addr)) = (unsigned long) ri->ret_addr;

Coding style (limit to 80 chars) here and a few other places


+		recycle_rp_inst(ri);
+	}	
+	spin_unlock_irqrestore(&kprobe_lock, flags);	
+}
+
+/*
+ * This kprobe pre_handler is registered with every kretprobe. When probe
+ * hits it will set up the return probe.
+ */
+int pre_handler_kretprobe(struct kprobe *p, struct pt_regs *regs)
+{
+	struct kretprobe *rp = container_of(p, struct kretprobe, kp);
+
+	/*TODO: consider to only swap the RA after the last pre_handler fired */
+	arch_prepare_kretprobe(rp, regs);
+	return 0;
+}
+
+inline void free_rp_inst(struct kretprobe *rp)
+{
+	struct kretprobe_instance *ri;
+	while((ri = get_free_rp_inst(rp)) != NULL) {

Coding style - while ( not while(


+ hlist_del(&ri->uflist);
+ kfree(ri);
+ }
+}
+
/* * Fill in the required fields of the "manager kprobe". Replace the * earlier kprobe in the hlist with the manager kprobe
@@ -260,16 +402,75 @@
unregister_kprobe(&jp->kp);
}
+int register_kretprobe(struct kretprobe *rp)
+{
+ int ret = 0;
+ struct kretprobe_instance *inst;
+ int i;
+
+ if (!arch_supports_kretprobes)
+ return -ENOSYS;
+
+ rp->kp.pre_handler = pre_handler_kretprobe;
+
+ /* Pre-allocate memory for max kretprobe instances */
+ if (rp->maxactive <= 0) {
+#ifdef CONFIG_PREEMPT
+ rp->maxactive = max(10, 2 * NR_CPUS);
+#else
+ rp->maxactive = NR_CPUS;
+#endif
+ } + INIT_HLIST_HEAD(&rp->used_instances);
+ INIT_HLIST_HEAD(&rp->free_instances);
+ for (i = 0; i < rp->maxactive; i++) {
+ inst = kmalloc(sizeof(struct kretprobe_instance), GFP_KERNEL);
+ if (inst == NULL) {
+ free_rp_inst(rp);
+ return -ENOMEM;
+ }
+ INIT_HLIST_NODE(&inst->uflist);
+ hlist_add_head(&inst->uflist, &rp->free_instances);
+ }
+
+ rp->nmissed = 0;
+ /* Establish function entry probe point */
+ if ((ret = register_kprobe(&rp->kp)) != 0) {
+ free_rp_inst(rp);
+ }

Coding style... no braces for single line conditionals


....

+struct task_struct  *arch_get_kprobe_task(void *ptr)
+{
+	return ((struct thread_info *) (((unsigned long) ptr) & (~(THREAD_SIZE -1))))->task;

80 columns.. split after the unary/logical operator


...

+ * Called when we hit the probe point at kretprobe_trampoline
+ */ +int trampoline_probe_handler(struct kprobe *p, struct pt_regs *regs)
+{
+ struct task_struct *tsk;
+ struct kretprobe_instance *ri;
+ struct hlist_head *head;
+ struct hlist_node *node;
+ unsigned long *sara = ((unsigned long *) &regs->esp) - 1;
+
+ tsk = arch_get_kprobe_task(sara);
+ head = kretprobe_inst_table_head(tsk);
+
+ hlist_for_each_entry(ri, node, head, hlist)
+ if (ri->stack_addr == sara && ri->rp) + ri->rp->handler(ri, regs);

Unconditional call - what if the user did not define a ->handler?



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