From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 13099 invoked by alias); 20 Apr 2015 10:31:06 -0000 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 Received: (qmail 13040 invoked by uid 89); 20 Apr 2015 10:31:05 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.3 required=5.0 tests=AWL,BAYES_00,KAM_LAZY_DOMAIN_SECURITY,T_RP_MATCHES_RCVD autolearn=no version=3.3.2 X-HELO: e23smtp06.au.ibm.com Received: from e23smtp06.au.ibm.com (HELO e23smtp06.au.ibm.com) (202.81.31.148) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Mon, 20 Apr 2015 10:31:04 +0000 Received: from /spool/local by e23smtp06.au.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Mon, 20 Apr 2015 20:31:01 +1000 Received: from d23dlp02.au.ibm.com (202.81.31.213) by e23smtp06.au.ibm.com (202.81.31.212) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Mon, 20 Apr 2015 20:30:58 +1000 Received: from d23relay10.au.ibm.com (d23relay10.au.ibm.com [9.190.26.77]) by d23dlp02.au.ibm.com (Postfix) with ESMTP id 858112BB004D for ; Mon, 20 Apr 2015 20:30:58 +1000 (EST) Received: from d23av03.au.ibm.com (d23av03.au.ibm.com [9.190.234.97]) by d23relay10.au.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t3KAUoVI45744150 for ; Mon, 20 Apr 2015 20:30:58 +1000 Received: from d23av03.au.ibm.com (localhost [127.0.0.1]) by d23av03.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t3KAUOqo004261 for ; Mon, 20 Apr 2015 20:30:25 +1000 Received: from localhost.in.ibm.com ([9.124.35.27]) by d23av03.au.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t3KATsvu003065; Mon, 20 Apr 2015 20:30:22 +1000 From: Hemant Kumar To: systemtap@sourceware.org Cc: mjw@redhat.com, naveen.n.rao@linux.vnet.ibm.com, ulrich.weigand@de.ibm.com, uweigand@gcc.gnu.org, anton@samba.org, fche@redhat.com, Hemant Kumar Subject: [PATCH v4 3/3] Fix: Priotirize symbol table lookup for ppc64le Date: Mon, 20 Apr 2015 10:31:00 -0000 Message-Id: <1429525764-23471-3-git-send-email-hemant@linux.vnet.ibm.com> In-Reply-To: <1429525764-23471-1-git-send-email-hemant@linux.vnet.ibm.com> References: <1429525764-23471-1-git-send-email-hemant@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15042010-0021-0000-0000-0000011DF059 X-IsSubscribed: yes X-SW-Source: 2015-q2/txt/msg00048.txt.bz2 PPC64 ELF ABI v2 has a Global entry point and a local entry point for the functions. We need the Local entry point in order to probe these functions. However, the DIE for these functions in debuginfo return the function.entrypc which is same as the global entry point. The local entry point is not encoded in the debuginfo of the ELFs. The offset to local entry point is however encoded in the st_other field of these symbols in the symbol table. We need to use this field to adjust the sym.st_value to actually point to the local entry point instead of the global entry point. This patch is in relation to this bug : https://sourceware.org/bugzilla/show_bug.cgi?id=17638 So, while adding symbols to the sym_table, we add an offset of PPC64_LOCAL_ENTRY_OFFSET(sym.st_other) to st_value. And when the function address is queried in query_dwarf_func(), we give priority to the cached sym_table, where we can retrieve the adjusted entry address of the function. If we don't get any address from the symbol table, then we proceed to get from the debuginfo. Macro definition PPC64_LOCAL_ENTRY_OFFSET has been picked up from glibc. It won't be defined if we are building systemtap on a machine having older elf.h and hence, won't recognize PPC64_LOCAL_ENTRY_OFFSET. Signed-off-by: Hemant Kumar --- tapsets.cxx | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 70 insertions(+), 2 deletions(-) diff --git a/tapsets.cxx b/tapsets.cxx index c96c542..ef11f8a 100644 --- a/tapsets.cxx +++ b/tapsets.cxx @@ -66,7 +66,17 @@ extern "C" { using namespace std; using namespace __gnu_cxx; - +// for elf.h where PPC64_LOCAL_ENTRY_OFFSET isn't defined +#ifndef PPC64_LOCAL_ENTRY_OFFSET +#define STO_PPC64_LOCAL_BIT 5 +#define STO_PPC64_LOCAL_MASK (7 << STO_PPC64_LOCAL_BIT) +#define PPC64_LOCAL_ENTRY_OFFSET(other) \ + (((1 << (((other) & STO_PPC64_LOCAL_MASK) >> STO_PPC64_LOCAL_BIT)) >> 2) << 2) +#endif +// for elf.h where EF_PPC64_ABI isn't defined +#ifndef EF_PPC64_ABI +#define EF_PPC64_ABI 3 +#endif // ------------------------------------------------------------------------ @@ -2050,6 +2060,18 @@ query_dwarf_inline_instance (Dwarf_Die * die, dwarf_query * q) } } +static bool +is_filtered_func_exists (func_info_map_t filtered, func_info *fi) +{ + for (unsigned i = 0; i < filtered.size(); i++) + { + if ((filtered[i].entrypc == fi->entrypc) && (filtered[i].name == fi->name)) + return true; + } + + return false; +} + static int query_dwarf_func (Dwarf_Die * func, dwarf_query * q) { @@ -2100,7 +2122,35 @@ query_dwarf_func (Dwarf_Die * func, dwarf_query * q) q->dw.function_line (&func.decl_line); Dwarf_Addr entrypc; - if (q->dw.function_entrypc (&entrypc)) + + func.entrypc = 0; + Dwarf_Addr bias; + Dwfl_Module *mod = q->dw.module; + Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias)) + ?: dwfl_module_getelf (mod, &bias)); + + GElf_Ehdr ehdr_mem; + GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem); + if (em == NULL) throw SEMANTIC_ERROR (_("Couldn't get elf header")); + + /* Giving priority to sym_table for ppc64*/ + if ((em->e_machine == EM_PPC64) && ((em->e_flags & EF_PPC64_ABI) == 2) + && (q->dw.mod_info->sym_table)) + { + set *fis; + fis = q->dw.mod_info->sym_table->lookup_symbol(func.name); + if (fis && !fis->empty()) + { + for (set::iterator it=fis->begin(); it!=fis->end() ; ++it) + { + func.entrypc = (*it)->addr; + if (is_filtered_func_exists(q->filtered_functions, &func)) + continue; + q->filtered_functions.push_back(func); + } + } + } + else if (!func.entrypc && q->dw.function_entrypc (&entrypc)) { func.entrypc = entrypc; q->filtered_functions.push_back (func); @@ -8140,6 +8190,14 @@ symbol_table::get_from_elf() int syments = dwfl_module_getsymtab(mod); assert(syments); prepare_section_rejection(mod); + Dwarf_Addr bias; + Elf* elf = (dwarf_getelf (dwfl_module_getdwarf (mod, &bias)) + ?: dwfl_module_getelf (mod, &bias)); + + GElf_Ehdr ehdr_mem; + GElf_Ehdr* em = gelf_getehdr (elf, &ehdr_mem); + if (em == NULL) throw SEMANTIC_ERROR (_("Couldn't get elf header")); + for (int i = 1; i < syments; ++i) { GElf_Sym sym; @@ -8168,6 +8226,16 @@ symbol_table::get_from_elf() addr = sym.st_value; reject = reject_section(section); #endif + /* + * For ELF ABI v2 on PPC64 LE, we need to adjust sym.st_value corresponding + * to the bits of sym.st_other. These bits will tell us what's the offset + * of the local entry point from the global entry point. + * + * st_other field is currently only used with ABIv2 on ppc64 + */ + if ((em->e_machine == EM_PPC64) && ((em->e_flags & EF_PPC64_ABI) == 2) + && (GELF_ST_TYPE(sym.st_info) == STT_FUNC) && sym.st_other) + addr += PPC64_LOCAL_ENTRY_OFFSET(sym.st_other); if (name && GELF_ST_TYPE(sym.st_info) == STT_FUNC) add_symbol(name, (GELF_ST_BIND(sym.st_info) == STB_WEAK), -- 1.9.3