From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756560AbbJINUr (ORCPT ); Fri, 9 Oct 2015 09:20:47 -0400 Received: from mga01.intel.com ([192.55.52.88]:27935 "EHLO mga01.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754783AbbJINUp (ORCPT ); Fri, 9 Oct 2015 09:20:45 -0400 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.17,657,1437462000"; d="scan'208";a="823139072" Subject: Re: [PATCH v7 3/5] perf inject: add jitdump mmap injection support To: Stephane Eranian , linux-kernel@vger.kernel.org References: <1443681949-6534-1-git-send-email-eranian@google.com> <1443681949-6534-4-git-send-email-eranian@google.com> Cc: acme@redhat.com, peterz@infradead.org, mingo@elte.hu, ak@linux.intel.com, jolsa@redhat.com, namhyung@kernel.org, cel@us.ibm.com, dsahern@gmail.com, johnmccutchan@google.com, brendan.d.gregg@gmail.com From: Adrian Hunter Organization: Intel Finland Oy, Registered Address: PL 281, 00181 Helsinki, Business Identity Code: 0357606 - 4, Domiciled in Helsinki Message-ID: <5617BE62.8070409@intel.com> Date: Fri, 9 Oct 2015 16:17:22 +0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.3.0 MIME-Version: 1.0 In-Reply-To: <1443681949-6534-4-git-send-email-eranian@google.com> Content-Type: text/plain; charset=windows-1252 Content-Transfer-Encoding: 7bit Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On 01/10/15 09:45, Stephane Eranian wrote: > This patch adds a --jit 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: > $ perf record -k mono -- java -agentpath:libpjvmti.so java_class > $ perf inject --jit -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. > > The genelf.c (ELF binary generation) depends on MD5 hash > encoding for the buildid. To enable this, libssl-dev must > be installed. If not, then genelf.c defaults to using > urandom to generate the buildid, which is not ideal. > The Makefile auto-detects the presence on libssl-dev. > > This version mmaps the jitdump file to create a marker > MMAP record in the perf.data file. The marker is used to detect > jitdump and cause perf inject to inject the jitted mmaps and > generate ELF images for jitted functions. > > Signed-off-by: Stephane Eranian > --- > +static int jit_repipe_code_load(struct jit_buf_desc *jd, union jr_entry *jr) > +{ > + struct perf_sample sample; > + union perf_event *event; > + struct perf_tool *tool = jd->session->tool; > + uint64_t code, addr; > + char *filename; > + struct stat st; > + size_t size; > + u16 idr_size; > + const char *sym; > + uint32_t count; > + int ret, csize; > + pid_t pid, tid; > + struct { > + u32 pid, tid; > + u64 time; > + } *id; > + > + pid = jr->load.pid; > + tid = jr->load.tid; > + 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; > + idr_size = jd->machine->id_hdr_size; > + /* > + * +16 to account for sample_id_all (hack) > + */ > + event = calloc(1, sizeof(*event) + idr_size); > + if (!event) > + return -1; > + > + filename = event->mmap2.filename; > + size = snprintf(filename, PATH_MAX, "%s/jitted-%d-%u.so", > + jd->dir, > + pid, > + count); > + > + size++; /* for \0 */ > + > + size = PERF_ALIGN(size, sizeof(u64)); > + > + ret = jit_emit_elf(filename, sym, addr, (const void *)code, csize); > + > + if (jd->debug_data && jd->nr_debug_entries) { > + free(jd->debug_data); > + jd->debug_data = NULL; > + jd->nr_debug_entries = 0; > + } > + > + if (ret) { > + free(event); > + return -1; > + } > + if (stat(filename, &st)) > + memset(&st, 0, sizeof(stat)); > + > + event->mmap2.header.type = PERF_RECORD_MMAP2; > + event->mmap2.header.misc = PERF_RECORD_MISC_USER; > + event->mmap2.header.size = (sizeof(event->mmap2) - > + (sizeof(event->mmap2.filename) - size) + idr_size); > + > + event->mmap2.pgoff = 0; I was testing this with Intel PT but getting decoding errors. I think the problem is here, as described below, but I will look at it more next week. event->mmap2.pgoff = 0 says that the code running at 'addr' can be found at offset 0 in the elf file, which is not correct. The MMAP event has to inform where in the file the code is. > + event->mmap2.start = addr; > + event->mmap2.len = csize; > + event->mmap2.pid = pid; > + event->mmap2.tid = tid; > + event->mmap2.ino = st.st_ino; > + event->mmap2.maj = major(st.st_dev); > + event->mmap2.min = minor(st.st_dev); > + event->mmap2.prot = st.st_mode; > + event->mmap2.flags = MAP_SHARED; > + event->mmap2.ino_generation = 1; > + > + id = (void *)((unsigned long)event + event->mmap.header.size - idr_size); > + if (jd->sample_type & PERF_SAMPLE_TID) { > + id->pid = pid; > + id->tid = tid; > + } > + if (jd->sample_type & PERF_SAMPLE_TIME) > + id->time = jr->load.p.timestamp; > + > + /* > + * create pseudo sample to induce dso hit increment > + * use first address as sample address > + */ > + memset(&sample, 0, sizeof(sample)); > + sample.pid = pid; > + sample.tid = tid; > + sample.time = id->time; > + sample.ip = addr; > + > + ret = perf_event__process_mmap2(tool, event, &sample, jd->machine, jd->session); > + if (ret) > + return ret; > + > + ret = jit_inject_event(jd, event); > + /* > + * mark dso as use to generate buildid in the header > + */ > + if (!ret) > + build_id__mark_dso_hit(tool, event, &sample, NULL, jd->machine); > + > + return ret;