From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751209AbdBBLME (ORCPT ); Thu, 2 Feb 2017 06:12:04 -0500 Received: from mx0a-001b2d01.pphosted.com ([148.163.156.1]:60940 "EHLO mx0a-001b2d01.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751060AbdBBLMC (ORCPT ); Thu, 2 Feb 2017 06:12:02 -0500 From: Ravi Bangoria To: acme@redhat.com, alexis.berlemont@gmail.com, linux-kernel@vger.kernel.org Cc: peterz@infradead.org, mingo@redhat.com, alexander.shishkin@linux.intel.com, mpe@ellerman.id.au, naveen.n.rao@linux.vnet.ibm.com, mhiramat@kernel.org, maddy@linux.vnet.ibm.com, Ravi Bangoria Subject: [PATCH 3/5] perf/sdt/x86: Move OP parser to tools/perf/arch/x86/ Date: Thu, 2 Feb 2017 16:41:41 +0530 X-Mailer: git-send-email 2.9.3 In-Reply-To: <20170202111143.14319-1-ravi.bangoria@linux.vnet.ibm.com> References: <20161214000732.1710-1-alexis.berlemont@gmail.com> <20170202111143.14319-1-ravi.bangoria@linux.vnet.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 17020211-0032-0000-0000-000001DDCD9F X-IBM-AV-DETECTION: SAVI=unused REMOTE=unused XFE=unused x-cbparentid: 17020211-0033-0000-0000-0000120DE489 Message-Id: <20170202111143.14319-4-ravi.bangoria@linux.vnet.ibm.com> X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2017-02-02_07:,, signatures=0 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 spamscore=0 suspectscore=2 malwarescore=0 phishscore=0 adultscore=0 bulkscore=0 classifier=spam adjust=0 reason=mlx scancount=1 engine=8.0.1-1612050000 definitions=main-1702020105 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org SDT marker argument is in N@OP format. N is the size of argument and OP is the actual assembly operand. OP is arch dependent component and hence it's parsing logic also should be placed under tools/perf/arch/. Signed-off-by: Ravi Bangoria --- tools/perf/arch/x86/util/perf_regs.c | 93 ++++++++++++++++++++++++- tools/perf/util/perf_regs.c | 9 ++- tools/perf/util/perf_regs.h | 7 +- tools/perf/util/probe-file.c | 127 +++++++++-------------------------- 4 files changed, 134 insertions(+), 102 deletions(-) diff --git a/tools/perf/arch/x86/util/perf_regs.c b/tools/perf/arch/x86/util/perf_regs.c index d8a8dcf..34fcb0d 100644 --- a/tools/perf/arch/x86/util/perf_regs.c +++ b/tools/perf/arch/x86/util/perf_regs.c @@ -3,6 +3,7 @@ #include "../../perf.h" #include "../../util/util.h" #include "../../util/perf_regs.h" +#include "../../util/debug.h" const struct sample_reg sample_reg_masks[] = { SMPL_REG(AX, PERF_REG_X86_AX), @@ -87,7 +88,16 @@ static const struct sdt_name_reg sdt_reg_renamings[] = { SDT_NAME_REG_END, }; -int sdt_rename_register(char **pdesc, char *old_name) +bool arch_sdt_probe_arg_supp(void) +{ + return true; +} + +/* + * The table sdt_reg_renamings is used for adjusting gcc/gas-generated + * registers before filling the uprobe tracer interface. + */ +static int sdt_rename_register(char **pdesc, char *old_name) { const struct sdt_name_reg *rnames = sdt_reg_renamings; char *new_desc, *old_desc = *pdesc; @@ -129,3 +139,84 @@ int sdt_rename_register(char **pdesc, char *old_name) return 0; } + +/* + * x86 specific implementation + * return value: + * <0 : error + * 0 : success + * >0 : skip + */ +int arch_sdt_probe_parse_op(char **desc, const char **prefix) +{ + char *tmp; + int ret = 0; + + /* + * The uprobe tracer format does not support all the addressing + * modes (notably: in x86 the scaled mode); so, we detect ',' + * characters, if there is just one, there is no use converting + * the sdt arg into a uprobe one. + * + * Also it does not support constants; if we find one in the + * current argument, let's skip the argument. + */ + if (strchr(*desc, ',') || strchr(*desc, '$')) { + pr_debug4("Skipping unsupported SDT argument; %s\n", *desc); + return 1; + } + + /* + * If the argument addressing mode is indirect, we must check + * a few things... + */ + tmp = strchr(*desc, '('); + if (tmp) { + int j; + + /* + * ...if the addressing mode is indirect with a + * positive offset (ex.: "1608(%ax)"), we need to add + * a '+' prefix so as to be compliant with uprobe + * format. + */ + if ((*desc)[0] != '+' && (*desc)[0] != '-') + *prefix = ((*desc)[0] == '(') ? "+0" : "+"; + + /* + * ...or if the addressing mode is indirect with a symbol + * as offset, the argument will not be supported by + * the uprobe tracer format; so, let's skip this one. + */ + for (j = 0; j < tmp - *desc; j++) { + if ((*desc)[j] != '+' && (*desc)[j] != '-' && + !isdigit((*desc)[j])) { + pr_debug4("Skipping unsupported SDT argument; " + "%s\n", *desc); + return 1; + } + } + } + + /* + * The uprobe parser does not support all gas register names; + * so, we have to replace them (ex. for x86_64: %rax -> %ax); + * the loop below looks for the register names (starting with + * a '%' and tries to perform the needed renamings. + */ + tmp = strchr(*desc, '%'); + while (tmp) { + size_t offset = tmp - *desc; + + ret = sdt_rename_register(desc, *desc + offset); + if (ret < 0) + return ret; + + /* + * The *desc pointer might have changed; so, let's not + * try to reuse tmp for next lookup + */ + tmp = strchr(*desc + offset + 1, '%'); + } + return 0; +} diff --git a/tools/perf/util/perf_regs.c b/tools/perf/util/perf_regs.c index a37e593..f2b3d0d 100644 --- a/tools/perf/util/perf_regs.c +++ b/tools/perf/util/perf_regs.c @@ -6,8 +6,13 @@ const struct sample_reg __weak sample_reg_masks[] = { SMPL_REG_END }; -int __weak sdt_rename_register(char **pdesc __maybe_unused, - char *old_name __maybe_unused) +bool __weak arch_sdt_probe_arg_supp(void) +{ + return false; +} + +int __weak arch_sdt_probe_parse_op(char **op_ptr __maybe_unused, + const char **prefix __maybe_unused) { return 0; } diff --git a/tools/perf/util/perf_regs.h b/tools/perf/util/perf_regs.h index 7544a15..86a2961 100644 --- a/tools/perf/util/perf_regs.h +++ b/tools/perf/util/perf_regs.h @@ -15,11 +15,8 @@ struct sample_reg { extern const struct sample_reg sample_reg_masks[]; -/* - * The table sdt_reg_renamings is used for adjusting gcc/gas-generated - * registers before filling the uprobe tracer interface. - */ -int sdt_rename_register(char **pdesc, char *old_name); +bool arch_sdt_probe_arg_supp(void); +int arch_sdt_probe_parse_op(char **op_ptr, const char **prefix); #ifdef HAVE_PERF_REGS_SUPPORT #include diff --git a/tools/perf/util/probe-file.c b/tools/perf/util/probe-file.c index d8a169e..38eca3c 100644 --- a/tools/perf/util/probe-file.c +++ b/tools/perf/util/probe-file.c @@ -693,6 +693,25 @@ static const char * const type_to_suffix[] = { "", ":u8", ":u16", "", ":u32", "", "", "", ":u64" }; +/* + * Isolate the string number and convert it into a decimal value; + * this will be an index to get suffix of the uprobe name (defining + * the type) + */ +static int sdt_probe_parse_n(char *n_ptr, const char **suffix) +{ + long type_idx; + + type_idx = strtol(n_ptr, NULL, 10); + if (type_idx < -8 || type_idx > 8) { + pr_debug4("Failed to get a valid sdt type\n"); + return -1; + } + + *suffix = type_to_suffix[type_idx + 8]; + return 0; +} + static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg) { char *tmp, *desc = strdup(arg); @@ -704,109 +723,29 @@ static int synthesize_sdt_probe_arg(struct strbuf *buf, int i, const char *arg) return ret; } + /* + * Argument is in N@OP format. N is size of the argument and OP is + * the actual assembly operand. N can be omitted; in that case + * argument is just OP(without @). + */ tmp = strchr(desc, '@'); if (tmp) { - long type_idx; - /* - * Isolate the string number and convert it into a - * binary value; this will be an index to get suffix - * of the uprobe name (defining the type) - */ tmp[0] = '\0'; - type_idx = strtol(desc, NULL, 10); - /* Check that the conversion went OK */ - if (type_idx == LONG_MIN || type_idx == LONG_MAX) { - pr_debug4("Failed to parse sdt type\n"); - goto error; - } - /* Check that the converted value is OK */ - if (type_idx < -8 || type_idx > 8) { - pr_debug4("Failed to get a valid sdt type\n"); - goto error; - } - suffix = type_to_suffix[type_idx + 8]; - /* Get rid of the sdt prefix which is now useless */ tmp++; - memmove(desc, tmp, strlen(tmp) + 1); - } - /* - * The uprobe tracer format does not support all the - * addressing modes (notably: in x86 the scaled mode); so, we - * detect ',' characters, if there is just one, there is no - * use converting the sdt arg into a uprobe one. - */ - if (strchr(desc, ',')) { - pr_debug4("Skipping unsupported SDT argument; %s\n", desc); - goto out; - } - - /* - * If the argument addressing mode is indirect, we must check - * a few things... - */ - tmp = strchr(desc, '('); - if (tmp) { - int j; - - /* - * ...if the addressing mode is indirect with a - * positive offset (ex.: "1608(%ax)"), we need to add - * a '+' prefix so as to be compliant with uprobe - * format. - */ - if (desc[0] != '+' && desc[0] != '-') - prefix = "+"; - - /* - * ...or if the addressing mode is indirect with a symbol - * as offset, the argument will not be supported by - * the uprobe tracer format; so, let's skip this one. - */ - for (j = 0; j < tmp - desc; j++) { - if (desc[j] != '+' && desc[j] != '-' && - !isdigit(desc[j])) { - pr_debug4("Skipping unsupported SDT argument; " - "%s\n", desc); - goto out; - } - } - } - - /* - * The uprobe tracer format does not support constants; if we - * find one in the current argument, let's skip the argument. - */ - if (strchr(desc, '$')) { - pr_debug4("Skipping unsupported SDT argument; %s\n", desc); - goto out; - } - - /* - * The uprobe parser does not support all gas register names; - * so, we have to replace them (ex. for x86_64: %rax -> %ax); - * the loop below looks for the register names (starting with - * a '%' and tries to perform the needed renamings. - */ - tmp = strchr(desc, '%'); - while (tmp) { - size_t offset = tmp - desc; - - ret = sdt_rename_register(&desc, desc + offset); - if (ret < 0) + if (sdt_probe_parse_n(desc, &suffix)) goto error; - - /* - * The desc pointer might have changed; so, let's not - * try to reuse tmp for next lookup - */ - tmp = strchr(desc + offset + 1, '%'); + memmove(desc, tmp, strlen(tmp) + 1); } - if (strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0) + ret = arch_sdt_probe_parse_op(&desc, &prefix); + if (ret < 0) + goto error; + + if (ret == 0 && + strbuf_addf(buf, " arg%d=%s%s%s", i + 1, prefix, desc, suffix) < 0) goto error; -out: ret = 0; error: free(desc); @@ -829,7 +768,7 @@ static char *synthesize_sdt_probe_command(struct sdt_note *note, sdt_note__get_addr(note)) < 0) goto error; - if (!note->args) + if (!note->args || !arch_sdt_probe_arg_supp()) goto out; if (note->args) { -- 2.9.3