Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752155AbbBVCCY (ORCPT ); Sat, 21 Feb 2015 21:02:24 -0500 Received: from mail-oi0-f41.google.com ([209.85.218.41]:34685 "EHLO mail-oi0-f41.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752028AbbBVCCU (ORCPT ); Sat, 21 Feb 2015 21:02:20 -0500 MIME-Version: 1.0 In-Reply-To: <20150221031705.GA2388@danjae> References: <1424295628-12529-1-git-send-email-eranian@google.com> <1424295628-12529-2-git-send-email-eranian@google.com> <20150221031705.GA2388@danjae> Date: Sat, 21 Feb 2015 21:02:18 -0500 Message-ID: Subject: Re: [PATCH v3 1/4] perf tools: add Java demangling support From: Stephane Eranian To: Namhyung Kim Cc: LKML , Arnaldo Carvalho de Melo , Peter Zijlstra , "mingo@elte.hu" , "ak@linux.intel.com" , Jiri Olsa , Rose Belcher , Sukadev Bhattiprolu , Sonny Rao , John Mccutchan , David Ahern , Adrian Hunter , Pawel Moll Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 12324 Lines: 358 On Fri, Feb 20, 2015 at 10:17 PM, Namhyung Kim wrote: > > Hi Stephane, > > On Wed, Feb 18, 2015 at 10:40:25PM +0100, Stephane Eranian wrote: > > Add Java function descriptor demangling support. > > Something bfd cannot do. > > > > Use the JAVA_DEMANGLE_NORET flag to avoid decoding the > > return type of functions. > > > > Signed-off-by: Stephane Eranian > > --- > > tools/perf/Makefile.perf | 2 + > > tools/perf/util/demangle-java.c | 199 ++++++++++++++++++++++++++++++++++++++++ > > tools/perf/util/demangle-java.h | 10 ++ > > tools/perf/util/symbol-elf.c | 3 + > > tools/perf/util/symbol.c | 6 +- > > 5 files changed, 219 insertions(+), 1 deletion(-) > > create mode 100644 tools/perf/util/demangle-java.c > > create mode 100644 tools/perf/util/demangle-java.h > > > > diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf > > index aa6a504..53a44be 100644 > > --- a/tools/perf/Makefile.perf > > +++ b/tools/perf/Makefile.perf > > @@ -331,6 +331,7 @@ LIB_H += ui/ui.h > > LIB_H += util/data.h > > LIB_H += util/kvm-stat.h > > LIB_H += util/thread-stack.h > > +LIB_H += util/demangle-java.h > > > > LIB_OBJS += $(OUTPUT)util/abspath.o > > LIB_OBJS += $(OUTPUT)util/alias.o > > @@ -410,6 +411,7 @@ LIB_OBJS += $(OUTPUT)util/data.o > > LIB_OBJS += $(OUTPUT)util/tsc.o > > LIB_OBJS += $(OUTPUT)util/cloexec.o > > LIB_OBJS += $(OUTPUT)util/thread-stack.o > > +LIB_OBJS += $(OUTPUT)util/demangle-java.o > > > > LIB_OBJS += $(OUTPUT)ui/setup.o > > LIB_OBJS += $(OUTPUT)ui/helpline.o > > diff --git a/tools/perf/util/demangle-java.c b/tools/perf/util/demangle-java.c > > new file mode 100644 > > index 0000000..79d5484 > > --- /dev/null > > +++ b/tools/perf/util/demangle-java.c > > @@ -0,0 +1,199 @@ > > +#include > > +#include > > +#include > > +#include "util.h" > > +#include "debug.h" > > +#include "symbol.h" > > + > > +#include "demangle-java.h" > > + > > +enum { > > + MODE_PREFIX=0, > > + MODE_CLASS=1, > > + MODE_FUNC=2, > > + MODE_TYPE=3, > > + MODE_CTYPE=3, /* class arg */ > > +}; > > + > > +#define BASE_ENT(c, n) [c-'A']=n > > +static const char *base_types['Z'-'A' + 1]={ > > + BASE_ENT('B', "byte" ), > > + BASE_ENT('C', "char" ), > > + BASE_ENT('D', "double" ), > > + BASE_ENT('F', "float" ), > > + BASE_ENT('I', "int" ), > > + BASE_ENT('J', "long" ), > > + BASE_ENT('S', "short" ), > > + BASE_ENT('Z', "bool" ), > > +}; > > + > > +/* > > + * demangle Java symbol between str and end positions and stores > > + * up to maxlen characters into buf. The parser starts in mode. > > + * > > + * Use MODE_PREFIX to process entire prototype till end position > > So this still includes the argument (type) right? I just worry about > that it might fill up the precious screen width of TUI like C++ > symbols did before.. > > Yes, because just like C++, argument type are part of signature of the function. int Foo(int a) vs int Foo(float). Not the same code. > > > + * Use MODE_TYPE to process return type if str starts on return type char > > What about MODE_CTYPE? I cannot find where it's used.. > > CTYPE is ued internally. > > > + * > > + * Return: > > + * success: buf > > + * error : NULL > > + */ > > +static char * > > +__demangle_java_sym(const char *str, const char *end, char *buf, int maxlen, int mode) > > +{ > > + int rlen = 0; > > + int array = 0; > > + int narg = 0; > > + const char *q; > > + > > + if (!end) > > + end = str + strlen(str); > > + > > + for (q = str; q != end; q++) { > > + > > + if (rlen == (maxlen - 1)) > > + break; > > + > > + switch (*q) { > > + case 'L': > > + if (mode == MODE_PREFIX || mode == MODE_CTYPE) { > > + if (mode == MODE_CTYPE) { > > + if (narg) > > + rlen += snprintf(buf+rlen, maxlen - rlen, ", "); > > + narg++; > > + } > > + rlen += snprintf(buf+rlen, maxlen - rlen, "class "); > > + if (mode == MODE_PREFIX) > > + mode = MODE_CLASS; > > + } else > > + buf[rlen++] = *q; > > + break; > > + case 'B': > > + case 'C': > > + case 'D': > > + case 'F': > > + case 'I': > > + case 'J': > > + case 'S': > > + case 'Z': > > + if (mode == MODE_TYPE) { > > + if (narg) > > + rlen += snprintf(buf+rlen, maxlen - rlen, ", "); > > + rlen += snprintf(buf+rlen, maxlen - rlen, "%s", base_types[*q - 'A']); > > + while(array--) > > + rlen += snprintf(buf+rlen, maxlen - rlen, "[]"); > > + array = 0; > > + narg++; > > + } else > > + buf[rlen++] = *q; > > + break; > > + case 'V': > > + if (mode == MODE_TYPE) { > > + rlen += snprintf(buf+rlen, maxlen - rlen, "void"); > > + while(array--) > > + rlen += snprintf(buf+rlen, maxlen - rlen, "[]"); > > + array = 0; > > + } else > > + buf[rlen++] = *q; > > + break; > > + case '[': > > + if (mode != MODE_TYPE) > > + goto error; > > + array++; > > + break; > > + case '(': > > + if (mode != MODE_FUNC) > > + goto error; > > + buf[rlen++] = *q; > > + mode = MODE_TYPE; > > + break; > > + case ')': > > + if (mode != MODE_TYPE) > > + goto error; > > + buf[rlen++] = *q; > > + narg = 0; > > + break; > > + case ';': > > + if (mode != MODE_CLASS && mode != MODE_CTYPE) > > + goto error; > > + /* safe because at least one other char to process */ > > + if (isalpha(*(q+1))) > > + rlen += snprintf(buf+rlen, maxlen - rlen, "."); > > + if (mode == MODE_CLASS) > > + mode = MODE_FUNC; > > + else if (mode == MODE_CTYPE) > > + mode = MODE_TYPE; > > + break; > > + case '/': > > + if (mode != MODE_CLASS && mode != MODE_CTYPE) > > + goto error; > > + rlen += snprintf(buf+rlen, maxlen - rlen, "."); > > + break; > > + default : > > + buf[rlen++] = *q; > > + } > > + } > > + buf[rlen] = '\0'; > > + return buf; > > +error: > > + return NULL; > > +} > > + > > +/* > > + * Demangle Java function signature (openJDK, not GCJ) > > + * input: > > + * str: string to parse. String is not modified > > + * flags: comobination of JAVA_DEMANGLE_* flags to modify demangling > > + * return: > > + * if input can be demangled, then a newly allocated string is returned. > > + * if input cannot be demangled, then NULL is returned > > + * > > + * Note: caller is responsible for freeing demangled string > > + */ > > +char * > > +java_demangle_sym(const char *str, int flags) > > +{ > > + char *buf, *ptr; > > + char *p; > > + size_t len, l1 = 0; > > + > > + if (!str) > > + return NULL; > > + > > + /* find start of retunr type */ > > + p = strrchr(str, ')'); > > + if (!p) > > + return NULL; > > + > > + /* > > + * expansion factor estimated to 3x > > + */ > > + len = strlen(str) * 3 + 1; > > + buf = malloc(len); > > + if (!buf) > > + return NULL; > > + > > + buf[0] = '\0'; > > + if (!(flags & JAVA_DEMANGLE_NORET)) { > > + /* > > + * get return type first > > + */ > > + ptr = __demangle_java_sym(p+1, NULL, buf, len, MODE_TYPE); > > + if (!ptr) > > + goto error; > > + > > + /* add space between return type and function prototype */ > > + l1 = strlen(buf); > > + buf[l1++] = ' '; > > + } > > + > > + /* process function up to return type */ > > + ptr = __demangle_java_sym(str, p + 1, buf + l1, len - l1, MODE_PREFIX); > > + if (!ptr) > > + goto error; > > + > > + return buf; > > +error: > > + free(buf); > > + return NULL; > > +} > > diff --git a/tools/perf/util/demangle-java.h b/tools/perf/util/demangle-java.h > > new file mode 100644 > > index 0000000..a981c1f > > --- /dev/null > > +++ b/tools/perf/util/demangle-java.h > > @@ -0,0 +1,10 @@ > > +#ifndef __PERF_DEMANGLE_JAVA > > +#define __PERF_DEMANGLE_JAVA 1 > > +/* > > + * demangle function flags > > + */ > > +#define JAVA_DEMANGLE_NORET 0x1 /* do not process return type */ > > + > > +char * java_demangle_sym(const char *str, int flags); > > + > > +#endif /* __PERF_DEMANGLE_JAVA */ > > diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c > > index b24f9d8..73b3e8f 100644 > > --- a/tools/perf/util/symbol-elf.c > > +++ b/tools/perf/util/symbol-elf.c > > @@ -6,6 +6,7 @@ > > #include > > > > #include "symbol.h" > > +#include "demangle-java.h" > > #include "machine.h" > > #include "vdso.h" > > #include > > @@ -1019,6 +1020,8 @@ int dso__load_sym(struct dso *dso, struct map *map, > > demangle_flags = DMGL_PARAMS | DMGL_ANSI; > > > > demangled = bfd_demangle(NULL, elf_name, demangle_flags); > > + if (demangled == NULL) > > + demangled = java_demangle_sym(elf_name, JAVA_DEMANGLE_NORET); > > if (demangled != NULL) > > elf_name = demangled; > > } > > diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c > > index a690668..3bc779b 100644 > > --- a/tools/perf/util/symbol.c > > +++ b/tools/perf/util/symbol.c > > @@ -9,6 +9,7 @@ > > #include > > #include > > #include > > +#include > > Wouldn't it break build on systems don't have the bfd devel package? > And I don't see why it's needed here.. > > I will fix that in v4. > > > #include "build-id.h" > > #include "util.h" > > #include "debug.h" > > @@ -1257,6 +1258,7 @@ static int dso__load_perf_map(struct dso *dso, struct map *map, > > u64 start, size; > > struct symbol *sym; > > int line_len, len; > > + char *name; > > > > line_len = getline(&line, &n, file); > > if (line_len < 0) > > @@ -1279,7 +1281,9 @@ static int dso__load_perf_map(struct dso *dso, struct map *map, > > if (len + 2 >= line_len) > > continue; > > > > - sym = symbol__new(start, size, STB_GLOBAL, line + len); > > + name = line + len; > > + > > + sym = symbol__new(start, size, STB_GLOBAL, name); > > I think this file is not a part of this changeset. > Removed. > > Thanks, > Namhyung > > > > > > if (sym == NULL) > > goto out_delete_line; > > -- > > 1.9.1 > > -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/