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 2/4] perf inject: add jitdump mmap injection support
Date: Sat, 21 Feb 2015 12:31:53 +0900 [thread overview]
Message-ID: <20150221033153.GB2388@danjae> (raw)
In-Reply-To: <1424295628-12529-3-git-send-email-eranian@google.com>
On Wed, Feb 18, 2015 at 10:40:26PM +0100, Stephane Eranian wrote:
> This patch adds a -j jitdump option to perf inject.
>
> This options injects MMAP records into the perf.data
> file to cover the jitted code mmaps. It also emits
> ELF images for each function in the jidump file.
> Those images are created where the jitdump file is.
> The MMAP records point to that location as well.
>
> Typical flow:
> $ java -agentpath:libpjvmti.so java_class
> $ perf inject -j ~/.debug/jit/java-jit-20140514.XXAb0e5C/jit-7640.dump \
> -i perf.data \
> -o perf.data.jitted
>
> $ perf report -i perf.data.jitted
>
> Note that jitdump.h support is not limited to Java, it works with
> any jitted environment modified to emit the jitdump file format,
> include those where code can be jitted multiple times and moved
> around.
>
> The jitdump.h format is adapted from the Oprofile project.
>
> Signed-off-by: Stephane Eranian <eranian@google.com>
> ---
> tools/perf/Documentation/perf-inject.txt | 11 +
> tools/perf/Makefile.perf | 6 +-
> tools/perf/builtin-inject.c | 205 ++++++++++++++
> tools/perf/util/genelf.c | 463 +++++++++++++++++++++++++++++++
> tools/perf/util/genelf.h | 6 +
> tools/perf/util/jit.h | 27 ++
> tools/perf/util/jitdump.c | 233 ++++++++++++++++
> tools/perf/util/jitdump.h | 92 ++++++
> 8 files changed, 1042 insertions(+), 1 deletion(-)
> create mode 100644 tools/perf/util/genelf.c
> create mode 100644 tools/perf/util/genelf.h
> create mode 100644 tools/perf/util/jit.h
> create mode 100644 tools/perf/util/jitdump.c
> create mode 100644 tools/perf/util/jitdump.h
>
> diff --git a/tools/perf/Documentation/perf-inject.txt b/tools/perf/Documentation/perf-inject.txt
> index dc7442c..237f195 100644
> --- a/tools/perf/Documentation/perf-inject.txt
> +++ b/tools/perf/Documentation/perf-inject.txt
> @@ -40,6 +40,17 @@ OPTIONS
> Merge sched_stat and sched_switch for getting events where and how long
> tasks slept. sched_switch contains a callchain where a task slept and
> sched_stat contains a timeslice how long a task slept.
> +-j::
> +--jit::
> + Merge a jitdump file into the perf.data file by adding mmap records to
> + cover jitted code and emit ELF images for each jitted function. The ELF
> + images are saved in the same directory as the jidump. Use -E to suppress
> + ELF images generation.
> +-E::
> +--jit-disable-elf::
> + When used with -, it prevents creating the ELF images for each jitted
> + function. Only the jitted code mmap records are injected into the perf.data
> + file. Option as no effect when -j is not used.
>
> --kallsyms=<file>::
> kallsyms pathname
> diff --git a/tools/perf/Makefile.perf b/tools/perf/Makefile.perf
> index 53a44be..d405632 100644
> --- a/tools/perf/Makefile.perf
> +++ b/tools/perf/Makefile.perf
> @@ -324,6 +324,7 @@ LIB_H += util/perf_regs.h
> LIB_H += util/unwind.h
> LIB_H += util/vdso.h
> LIB_H += util/tsc.h
> +LIB_H += util/jitdump.h
> LIB_H += ui/helpline.h
> LIB_H += ui/progress.h
> LIB_H += ui/util.h
> @@ -412,6 +413,8 @@ 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)util/jitdump.o
> +LIB_OBJS += $(OUTPUT)util/genelf.o
>
> LIB_OBJS += $(OUTPUT)ui/setup.o
> LIB_OBJS += $(OUTPUT)ui/helpline.o
> @@ -498,7 +501,8 @@ BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
> BUILTIN_OBJS += $(OUTPUT)tests/builtin-test.o
> BUILTIN_OBJS += $(OUTPUT)builtin-mem.o
>
> -PERFLIBS = $(LIB_FILE) $(LIBAPIKFS) $(LIBTRACEEVENT)
> +PERFLIBS = $(LIB_FILE) $(LIBAPIKFS) $(LIBTRACEEVENT) -lcrypto
> +
This should be guarded by a feature test.
>
> # We choose to avoid "if .. else if .. else .. endif endif"
> # because maintaining the nesting to match is a pain. If
[SNIP]
> +static int jit_repipe_code_load(struct perf_inject *inject, union jr_entry *jr)
> +{
> + struct perf_sample sample;
> + union perf_event *event;
> + unsigned long code, addr;
> + size_t size;
> + const char *sym;
> + uint32_t count;
> + int ret, csize;
> + pid_t pid;
> + struct {
> + u32 pid, tid;
> + u64 time;
> + } *id;
> +
> + pid = jr->load.pid;
> + csize = jr->load.code_size;
> + addr = jr->load.code_addr;
> + sym = (void *)((unsigned long)jr + sizeof(jr->load));
> + code = (unsigned long)jr + jr->load.p.total_size - csize;
> + count = jr->load.code_index;
> +
> + /*
> + * +16 to account for sample_id_all (hack)
> + */
Why not use perf_evlist__id_hdr_size() ?
> + event = malloc(sizeof(*event) + 16);
> + if (!event)
> + return -1;
> +
> + memset(event, 0, sizeof(*event));
> +
> + size = snprintf(event->mmap.filename, PATH_MAX, "%s/jitted-%d-%u",
> + inject->jit_dir,
> + pid,
> + count) + 1;
> + size = PERF_ALIGN(size, sizeof(u64));
> + if (!inject->jit_disable_elf) {
> + ret = jit_emit_elf(event->mmap.filename, sym, code, csize);
> + if (ret) {
> + free(event);
> + return -1;
> + }
> + }
> +
> + event->mmap.header.type = PERF_RECORD_MMAP;
> + event->mmap.header.misc = PERF_RECORD_MISC_USER;
> + //event->mmap.header.size = sizeof(event->mmap) + 16;
> + event->mmap.header.size = (sizeof(event->mmap) -
> + (sizeof(event->mmap.filename) - size) + 16); //machine->id_hdr_size);
> + event->mmap.pgoff = 0;
> + event->mmap.start = addr;
> + event->mmap.len = csize;
> + event->mmap.pid = pid;
> + event->mmap.tid = jr->load.tid;
> +
> + id = (void *)((unsigned long)event + event->mmap.header.size - 16);
> + id->pid = pid;
> + id->tid = jr->load.tid;
> + id->time = jr->load.p.timestamp;
> +
> + memset(&sample, 0, sizeof(sample));
> + sample.time = id->time;
> +
> + return perf_event__repipe_synth(&inject->tool, event);
> +}
[SNIP]
> diff --git a/tools/perf/util/genelf.c b/tools/perf/util/genelf.c
> new file mode 100644
> index 0000000..a6f9e43
> --- /dev/null
> +++ b/tools/perf/util/genelf.c
> @@ -0,0 +1,463 @@
> +/*
> + * genelf.c
> + * Copyright (C) 2014, Google, Inc
> + *
> + * Contributed by:
> + * Stephane Eranian <eranian@gmail.com>
> + *
> + * Released under the GPL v2. (and only v2, not any later version)
> + */
> +
> +#include <sys/types.h>
> +#include <stdio.h>
> +#include <getopt.h>
> +#include <stddef.h>
> +#include <libelf.h>
> +#include <string.h>
> +#include <stdlib.h>
> +#include <fcntl.h>
> +#include <err.h>
> +
> +#include "perf.h"
> +#include "genelf.h"
> +
> +#define JVMTI
> +#define BUILD_ID_MD5
> +#undef BUILD_ID_SHA /* does not seem to work well when linked with Java */
> +#undef BUILD_ID_URANDOM /* different uuid for each run */
> +
> +#ifdef BUILD_ID_SHA
> +#include <openssl/sha.h>
> +#endif
> +
> +#ifdef BUILD_ID_MD5
> +#include <openssl/md5.h>
> +#endif
> +
> +#if defined(__arm__)
> +#define GEN_ELF_ARCH EM_ARM
> +#define GEN_ELF_ENDIAN ELFDATA2LSB
> +#define GEN_ELF_CLASS ELFCLASS32
> +#elif defined(__x86_64__)
> +#define GEN_ELF_ARCH EM_X86_64
> +#define GEN_ELF_ENDIAN ELFDATA2LSB
> +#define GEN_ELF_CLASS ELFCLASS64
> +#elif defined(__i386__)
> +#define GEN_ELF_ARCH EM_386
> +#define GEN_ELF_ENDIAN ELFDATA2LSB
> +#define GEN_ELF_CLASS ELFCLASS32
> +#elif defined(__ppcle__)
> +#define GEN_ELF_ARCH EM_PPC
> +#define GEN_ELF_ENDIAN ELFDATA2LSB
> +#define GEN_ELF_CLASS ELFCLASS64
> +#elif defined(__powerpc__)
> +#define GEN_ELF_ARCH EM_PPC64
> +#define GEN_ELF_ENDIAN ELFDATA2MSB
> +#define GEN_ELF_CLASS ELFCLASS64
> +#elif defined(__powerpcle__)
> +#define GEN_ELF_ARCH EM_PPC64
> +#define GEN_ELF_ENDIAN ELFDATA2LSB
> +#define GEN_ELF_CLASS ELFCLASS64
> +#else
> +#error "unsupported architecture"
> +#endif
This makes other arch like s390 or sparc cannot build perf, right?
Thanks,
Namhyung
> +
> +#if GEN_ELF_CLASS == ELFCLASS64
> +#define elf_newehdr elf64_newehdr
> +#define elf_getshdr elf64_getshdr
> +#define Elf_Ehdr Elf64_Ehdr
> +#define Elf_Shdr Elf64_Shdr
> +#define Elf_Sym Elf64_Sym
> +#define ELF_ST_TYPE(a) ELF64_ST_TYPE(a)
> +#define ELF_ST_BIND(a) ELF64_ST_BIND(a)
> +#define ELF_ST_VIS(a) ELF64_ST_VISIBILITY(a)
> +#else
> +#define elf_newehdr elf32_newehdr
> +#define elf_getshdr elf32_getshdr
> +#define Elf_Ehdr Elf32_Ehdr
> +#define Elf_Shdr Elf32_Shdr
> +#define Elf_Sym Elf32_Sym
> +#define ELF_ST_TYPE(a) ELF32_ST_TYPE(a)
> +#define ELF_ST_BIND(a) ELF32_ST_BIND(a)
> +#define ELF_ST_VIS(a) ELF32_ST_VISIBILITY(a)
> +#endif
next prev parent reply other threads:[~2015-02-21 3:32 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
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 [this message]
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=20150221033153.GB2388@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.