[Fwd: Re: [PATCH] Return probe]
Ananth N Mavinakayanahalli
amavin@redhat.com
Fri Apr 29 21:07:00 GMT 2005
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 *) ®s->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?
More information about the Systemtap
mailing list