From: Namhyung Kim <namhyung@kernel.org>
To: Stephane Eranian <eranian@google.com>
Cc: linux-kernel@vger.kernel.org, acme@redhat.com,
peterz@infradead.org, mingo@elte.hu, ak@linux.intel.com,
jolsa@redhat.com, cel@us.ibm.com, sukadev@linux.vnet.ibm.com,
sonnyrao@chromium.org, johnmccutchan@google.com,
dsahern@gmail.com, adrian.hunter@intel.com, pawel.moll@arm.com
Subject: Re: [PATCH v3 1/4] perf tools: add Java demangling support
Date: Sat, 21 Feb 2015 12:17:05 +0900 [thread overview]
Message-ID: <20150221031705.GA2388@danjae> (raw)
In-Reply-To: <1424295628-12529-2-git-send-email-eranian@google.com>
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 <eranian@google.com>
> ---
> 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 <sys/types.h>
> +#include <stdio.h>
> +#include <string.h>
> +#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..
> + * 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..
> + *
> + * 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 <inttypes.h>
>
> #include "symbol.h"
> +#include "demangle-java.h"
> #include "machine.h"
> #include "vdso.h"
> #include <symbol/kallsyms.h>
> @@ -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 <fcntl.h>
> #include <unistd.h>
> #include <inttypes.h>
> +#include <bfd.h>
Wouldn't it break build on systems don't have the bfd devel package?
And I don't see why it's needed here..
> #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.
Thanks,
Namhyung
>
> if (sym == NULL)
> goto out_delete_line;
> --
> 1.9.1
>
next prev parent reply other threads:[~2015-02-21 3:17 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-02-18 21:40 [PATCH v3 0/4] perf: add support for profiling jitted code Stephane Eranian
2015-02-18 21:40 ` [PATCH v3 1/4] perf tools: add Java demangling support Stephane Eranian
2015-02-21 3:17 ` Namhyung Kim [this message]
2015-02-22 2:02 ` Stephane Eranian
2015-02-18 21:40 ` [PATCH v3 2/4] perf inject: add jitdump mmap injection support Stephane Eranian
2015-02-21 3:31 ` Namhyung Kim
2015-02-18 21:40 ` [PATCH v3 3/4] perf tools: add JVMTI agent library Stephane Eranian
2015-02-18 21:40 ` [PATCH v3 4/4] perf: Use monotonic clock as a source for timestamps Stephane Eranian
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150221031705.GA2388@danjae \
--to=namhyung@kernel.org \
--cc=acme@redhat.com \
--cc=adrian.hunter@intel.com \
--cc=ak@linux.intel.com \
--cc=cel@us.ibm.com \
--cc=dsahern@gmail.com \
--cc=eranian@google.com \
--cc=johnmccutchan@google.com \
--cc=jolsa@redhat.com \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@elte.hu \
--cc=pawel.moll@arm.com \
--cc=peterz@infradead.org \
--cc=sonnyrao@chromium.org \
--cc=sukadev@linux.vnet.ibm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.