From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 17047 invoked by alias); 17 Dec 2009 09:40:04 -0000 Received: (qmail 16980 invoked by uid 22791); 17 Dec 2009 09:40:03 -0000 X-SWARE-Spam-Status: No, hits=-2.6 required=5.0 tests=BAYES_00,SPF_HELO_PASS,SPF_PASS X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Thu, 17 Dec 2009 09:39:59 +0000 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id nBH9dvZk029542 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Thu, 17 Dec 2009 04:39:57 -0500 Received: from colt.bricoworks.com (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id nBH9dth2018053 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Thu, 17 Dec 2009 04:39:57 -0500 Message-ID: <4B29FC6B.5090303@redhat.com> Date: Thu, 17 Dec 2009 09:40:00 -0000 From: Tim Moore User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.4pre) Gecko/20091014 Fedora/3.0-2.8.b4.fc11 Thunderbird/3.0b4 MIME-Version: 1.0 To: systemtap@sourceware.org Subject: Fwd: rfc on unwinding through uretprobe trampoline Content-Type: multipart/mixed; boundary="------------080908020406060200020509" X-IsSubscribed: yes Mailing-List: contact systemtap-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Post: List-Help: , Sender: systemtap-owner@sourceware.org X-SW-Source: 2009-q4/txt/msg00962.txt.bz2 This is a multi-part message in MIME format. --------------080908020406060200020509 Content-Type: text/plain; charset=ISO-8859-1 Content-Transfer-Encoding: 7bit Content-length: 748 Sorry if this is a repeat. Tim -------- Original Message -------- Subject: rfc on unwinding through uretprobe trampoline Date: Wed, 16 Dec 2009 18:10:49 +0100 From: Tim Moore To: external-perftools-list@redhat.com I wrote the following code to assist with doing backtraces though any uretprobe trampolines that might be on the stack. It has a significant limitation: it only works when called from a uretprobe handler. This lets the code bypass any lookup, and consequent locking, of the uprobes proc and thread structures. I'm wondering if this function is sufficiently useful to check in, or whether a general function that works from anywhere is what's needed. Other comments about the code are welcome too. Thanks, Tim --------------080908020406060200020509 Content-Type: text/plain; name="0001-function-to-translate-from-the-uretprobe-trampoline.patch" Content-Transfer-Encoding: 7bit Content-Disposition: attachment; filename*0="0001-function-to-translate-from-the-uretprobe-trampoline.pat"; filename*1="ch" Content-length: 3055 >From 2e7f844220b9419b2f05234b07c56bcdedf7afb2 Mon Sep 17 00:00:00 2001 From: Tim Moore Date: Wed, 16 Dec 2009 18:00:34 +0100 Subject: [PATCH] function to translate from the uretprobe trampoline back to the original return address * runtime/uprobes2/uprobes.c (uprobe_get_pc): new function --- runtime/uprobes2/uprobes.c | 38 ++++++++++++++++++++++++++++++++++++++ runtime/uprobes2/uprobes.h | 8 ++++++++ 2 files changed, 46 insertions(+), 0 deletions(-) diff --git a/runtime/uprobes2/uprobes.c b/runtime/uprobes2/uprobes.c index bf45475..4c3a9c9 100644 --- a/runtime/uprobes2/uprobes.c +++ b/runtime/uprobes2/uprobes.c @@ -2810,6 +2810,44 @@ static void uretprobe_set_trampoline(struct uprobe_process *uproc, } } +unsigned long uprobe_get_pc(struct uretprobe_instance *ri, unsigned long pc, + unsigned long sp) +{ + struct uretprobe *rp; + struct uprobe_kimg *uk; + struct uprobe_process *uproc; + unsigned long trampoline_addr; + struct hlist_node *r; + struct uretprobe_instance *ret_inst; + + if (!ri) + return 0; + rp = ri->rp; + uk = (struct uprobe_kimg *)rp->u.kdata; + if (!uk) + return 0; + uproc = uk->ppt->uproc; + if (IS_ERR(uproc->uretprobe_trampoline_addr)) + return pc; + trampoline_addr = (unsigned long)uproc->uretprobe_trampoline_addr; + if (pc != trampoline_addr) + return pc; + r = &ri->hlist; + hlist_for_each_entry_from(ret_inst, r, hlist) { + if (ret_inst->ret_addr == trampoline_addr) + continue; + /* First handler with a stack pointer lower than the + address (or equal) must be the one. */ + if (ret_inst->sp == sp || compare_stack_ptrs(ret_inst->sp, sp)) + return ret_inst->ret_addr; + } + printk(KERN_ERR "Original return address for trampoline not found at " + "0x%lx pid/tgid=%d/%d\n", sp, current->pid, current->tgid); + return 0; +} + +EXPORT_SYMBOL_GPL(uprobe_get_pc); + #else /* ! CONFIG_URETPROBES */ static void uretprobe_handle_entry(struct uprobe *u, struct pt_regs *regs, diff --git a/runtime/uprobes2/uprobes.h b/runtime/uprobes2/uprobes.h index ae0692f..5d2a826 100644 --- a/runtime/uprobes2/uprobes.h +++ b/runtime/uprobes2/uprobes.h @@ -88,6 +88,14 @@ extern void unregister_uretprobe(struct uretprobe *rp); /* For PRs 9940, 6852... */ extern void unmap_uprobe(struct uprobe *u); extern void unmap_uretprobe(struct uretprobe *rp); +/* + * Given a program counter, translate it back to the original address + * if it is the address of the trampoline. sp is the stack pointer for + * the frame that corresponds to the address. + */ +extern unsigned long uprobe_get_pc(struct uretprobe_instance *ri, + unsigned long pc, + unsigned long sp); #ifdef UPROBES_IMPLEMENTATION -- 1.6.2.5 --------------080908020406060200020509--