linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Adrian Hunter <adrian.hunter@intel.com>
To: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>,
	linux-kernel@vger.kernel.org, David Ahern <dsahern@gmail.com>,
	Frederic Weisbecker <fweisbec@gmail.com>,
	Jiri Olsa <jolsa@redhat.com>, Namhyung Kim <namhyung@gmail.com>,
	Paul Mackerras <paulus@samba.org>,
	Stephane Eranian <eranian@google.com>
Subject: [PATCH 31/31] perf tools: Add support for 32-bit compatibility VDSOs
Date: Thu, 31 Jul 2014 09:01:14 +0300	[thread overview]
Message-ID: <1406786474-9306-32-git-send-email-adrian.hunter@intel.com> (raw)
In-Reply-To: <1406786474-9306-1-git-send-email-adrian.hunter@intel.com>

'perf record' post-processes the event stream  to create
a list of build-ids for object files for which sample
events have been recorded.  That results in those object
files being recorded in the build-id cache.

In the case of VDSO, perf tools reads it from memory
and copies it into a temporary file, which as decribed
above, gets added to the build-id cache.

Then when the perf.data file is processed by other
tools, the build-id of VDSO is listed in the perf.data
file and the VDSO can be read from the build-id cache.
In that case the name of the map, the short name of the
DSO, and the entry in the build-id cache are all
"[vdso]".

However, in the 64-bit case, there also can be 32-bit
compatibility VDSOs.

A previous patch added programs "perf-read-vdso32" and
"perf read-vdsox32".  This patch uses those programs to
read the correct VDSO for a thread and create a
temporary file just as for the 64-bit VDSO.  The map
name and the entry in the build-id cache are still
"[vdso]" but the DSO short name becomes "[vdso32]"
and "[vdsox32]" respectively.

Signed-off-by: Adrian Hunter <adrian.hunter@intel.com>
---
 tools/perf/util/vdso.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++-
 tools/perf/util/vdso.h |   4 +-
 2 files changed, 172 insertions(+), 2 deletions(-)

diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index adca693..b721f4c 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -12,6 +12,7 @@
 #include "util.h"
 #include "symbol.h"
 #include "machine.h"
+#include "thread.h"
 #include "linux/string.h"
 #include "debug.h"
 
@@ -22,10 +23,15 @@ struct vdso_file {
 	bool error;
 	char temp_file_name[sizeof(VDSO__TEMP_FILE_NAME)];
 	const char *dso_name;
+	const char *read_prog;
 };
 
 struct vdso_info {
 	struct vdso_file vdso;
+#if BITS_PER_LONG == 64
+	struct vdso_file vdso32;
+	struct vdso_file vdsox32;
+#endif
 };
 
 static struct vdso_info *vdso_info__new(void)
@@ -35,6 +41,18 @@ static struct vdso_info *vdso_info__new(void)
 			.temp_file_name = VDSO__TEMP_FILE_NAME,
 			.dso_name = DSO__NAME_VDSO,
 		},
+#if BITS_PER_LONG == 64
+		.vdso32  = {
+			.temp_file_name = VDSO__TEMP_FILE_NAME,
+			.dso_name = DSO__NAME_VDSO32,
+			.read_prog = "perf-read-vdso32",
+		},
+		.vdsox32  = {
+			.temp_file_name = VDSO__TEMP_FILE_NAME,
+			.dso_name = DSO__NAME_VDSOX32,
+			.read_prog = "perf-read-vdsox32",
+		},
+#endif
 	};
 
 	return memdup(&vdso_info_init, sizeof(vdso_info_init));
@@ -117,6 +135,12 @@ void vdso__exit(struct machine *machine)
 
 	if (vdso_info->vdso.found)
 		unlink(vdso_info->vdso.temp_file_name);
+#if BITS_PER_LONG == 64
+	if (vdso_info->vdso32.found)
+		unlink(vdso_info->vdso.temp_file_name);
+	if (vdso_info->vdsox32.found)
+		unlink(vdso_info->vdso.temp_file_name);
+#endif
 
 	zfree(&machine->vdso_info);
 }
@@ -135,6 +159,143 @@ static struct dso *vdso__new(struct machine *machine, const char *short_name,
 	return dso;
 }
 
+#if BITS_PER_LONG == 64
+
+static enum dso_type machine__thread_dso_type(struct machine *machine,
+					      struct thread *thread)
+{
+	enum dso_type dso_type = DSO__TYPE_UNKNOWN;
+	struct map *map;
+	struct dso *dso;
+
+	map = map_groups__first(thread->mg, MAP__FUNCTION);
+	for (; map ; map = map_groups__next(map)) {
+		dso = map->dso;
+		if (!dso || dso->long_name[0] != '/')
+			continue;
+		dso_type = dso__type(dso, machine);
+		if (dso_type != DSO__TYPE_UNKNOWN)
+			break;
+	}
+
+	return dso_type;
+}
+
+static int vdso__do_copy_compat(FILE *f, int fd)
+{
+	char buf[4096];
+	size_t count;
+
+	while (1) {
+		count = fread(buf, 1, sizeof(buf), f);
+		if (ferror(f))
+			return -errno;
+		if (feof(f))
+			break;
+		if (count && writen(fd, buf, count) != (ssize_t)count)
+			return -errno;
+	}
+
+	return 0;
+}
+
+static int vdso__copy_compat(const char *prog, int fd)
+{
+	FILE *f;
+	int err;
+
+	f = popen(prog, "r");
+	if (!f)
+		return -errno;
+
+	err = vdso__do_copy_compat(f, fd);
+
+	if (pclose(f) == -1)
+		return -errno;
+
+	return err;
+}
+
+static int vdso__create_compat_file(const char *prog, char *temp_name)
+{
+	int fd, err;
+
+	fd = mkstemp(temp_name);
+	if (fd < 0)
+		return -errno;
+
+	err = vdso__copy_compat(prog, fd);
+
+	if (close(fd) == -1)
+		return -errno;
+
+	return err;
+}
+
+static const char *vdso__get_compat_file(struct vdso_file *vdso_file)
+{
+	int err;
+
+	if (vdso_file->found)
+		return vdso_file->temp_file_name;
+
+	if (vdso_file->error)
+		return NULL;
+
+	err = vdso__create_compat_file(vdso_file->read_prog,
+				       vdso_file->temp_file_name);
+	if (err) {
+		pr_err("%s failed, error %d\n", vdso_file->read_prog, err);
+		vdso_file->error = true;
+		return NULL;
+	}
+
+	vdso_file->found = true;
+
+	return vdso_file->temp_file_name;
+}
+
+static struct dso *vdso__findnew_compat(struct machine *machine,
+					struct vdso_file *vdso_file)
+{
+	const char *file_name;
+	struct dso *dso;
+
+	dso = dsos__find(&machine->user_dsos, vdso_file->dso_name, true);
+	if (dso)
+		return dso;
+
+	file_name = vdso__get_compat_file(vdso_file);
+	if (!file_name)
+		return NULL;
+
+	return vdso__new(machine, vdso_file->dso_name, file_name);
+}
+
+static int vdso__dso_findnew_compat(struct machine *machine,
+				    struct thread *thread,
+				    struct vdso_info *vdso_info,
+				    struct dso **dso)
+{
+	enum dso_type dso_type;
+
+	dso_type = machine__thread_dso_type(machine, thread);
+	switch (dso_type) {
+	case DSO__TYPE_32BIT:
+		*dso = vdso__findnew_compat(machine, &vdso_info->vdso32);
+		return 1;
+	case DSO__TYPE_X32BIT:
+		*dso = vdso__findnew_compat(machine, &vdso_info->vdsox32);
+		return 1;
+	case DSO__TYPE_UNKNOWN:
+	case DSO__TYPE_64BIT:
+	default:
+		return 0;
+	}
+}
+
+#endif
+
 struct dso *vdso__dso_findnew(struct machine *machine,
 			      struct thread *thread __maybe_unused)
 {
@@ -148,6 +309,11 @@ struct dso *vdso__dso_findnew(struct machine *machine,
 	if (!vdso_info)
 		return NULL;
 
+#if BITS_PER_LONG == 64
+	if (vdso__dso_findnew_compat(machine, thread, vdso_info, &dso))
+		return dso;
+#endif
+
 	dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true);
 	if (!dso) {
 		char *file;
@@ -164,5 +330,7 @@ struct dso *vdso__dso_findnew(struct machine *machine,
 
 bool dso__is_vdso(struct dso *dso)
 {
-	return !strcmp(dso->short_name, DSO__NAME_VDSO);
+	return !strcmp(dso->short_name, DSO__NAME_VDSO) ||
+	       !strcmp(dso->short_name, DSO__NAME_VDSO32) ||
+	       !strcmp(dso->short_name, DSO__NAME_VDSOX32);
 }
diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h
index af9d692..d97da16 100644
--- a/tools/perf/util/vdso.h
+++ b/tools/perf/util/vdso.h
@@ -7,7 +7,9 @@
 
 #define VDSO__MAP_NAME "[vdso]"
 
-#define DSO__NAME_VDSO "[vdso]"
+#define DSO__NAME_VDSO    "[vdso]"
+#define DSO__NAME_VDSO32  "[vdso32]"
+#define DSO__NAME_VDSOX32 "[vdsox32]"
 
 static inline bool is_vdso_map(const char *filename)
 {
-- 
1.8.3.2


  parent reply	other threads:[~2014-07-31  6:03 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-07-31  6:00 [PATCH 00/31] perf tools: Yet more preparation for call graph from Intel BTS Adrian Hunter
2014-07-31  6:00 ` [PATCH 01/31] perf tools: Identify which comms are from exec Adrian Hunter
2014-08-14  8:51   ` [tip:perf/core] " tip-bot for Adrian Hunter
2014-07-31  6:00 ` [PATCH 02/31] perf tools: Add machine__thread_exec_comm() Adrian Hunter
2014-08-14  8:51   ` [tip:perf/core] perf machine: " tip-bot for Adrian Hunter
2014-07-31  6:00 ` [PATCH 03/31] perf tools: Fix missing label symbols Adrian Hunter
2014-08-14  8:50   ` [tip:perf/core] perf symbols: " tip-bot for Adrian Hunter
2014-07-31  6:00 ` [PATCH 04/31] perf tools: Add machine__kernel_ip() Adrian Hunter
2014-07-31  6:00 ` [PATCH 05/31] perf tools: Let a user specify a PMU event without any config terms Adrian Hunter
2014-07-31  6:00 ` [PATCH 06/31] perf tools: Let default config be defined for a PMU Adrian Hunter
2014-09-19  5:20   ` [tip:perf/core] " tip-bot for Adrian Hunter
2014-07-31  6:00 ` [PATCH 07/31] perf tools: Add perf_pmu__scan_file() Adrian Hunter
2014-09-19  5:21   ` [tip:perf/core] " tip-bot for Adrian Hunter
2014-07-31  6:00 ` [PATCH 08/31] perf evlist: Add 'system_wide' option Adrian Hunter
2014-08-14  8:50   ` [tip:perf/core] " tip-bot for Adrian Hunter
2014-07-31  6:00 ` [PATCH 09/31] perf evlist: Add perf_evlist__set_tracking_event() Adrian Hunter
2014-08-14  8:50   ` [tip:perf/core] perf evlist: Add perf_evlist__set_tracking_event( ) tip-bot for Adrian Hunter
2014-07-31  6:00 ` [PATCH 10/31] perf tools: Add id index Adrian Hunter
2014-07-31  6:00 ` [PATCH 11/31] perf pmu: Let pmu's with no events show up on perf list Adrian Hunter
2014-07-31  6:00 ` [PATCH 12/31] perf session: Add perf_session__deliver_synth_event() Adrian Hunter
2014-07-31  6:00 ` [PATCH 13/31] perf evlist: Add perf_evlist__enable_event_idx() Adrian Hunter
2014-08-14  8:52   ` [tip:perf/core] " tip-bot for Adrian Hunter
2014-07-31  6:00 ` [PATCH 14/31] perf session: Add perf_session__peek_event() Adrian Hunter
2014-08-14  8:50   ` [tip:perf/core] " tip-bot for Adrian Hunter
2014-07-31  6:00 ` [PATCH 15/31] perf tools: Add a thread stack for synthesizing call chains Adrian Hunter
2014-07-31  6:00 ` [PATCH 16/31] perf script: Allow callchains if any event samples them Adrian Hunter
2014-08-14  8:51   ` [tip:perf/core] " tip-bot for Adrian Hunter
2014-07-31  6:01 ` [PATCH 17/31] perf tools: Add facility to export data in database-friendly way Adrian Hunter
2014-07-31  6:01 ` [PATCH 18/31] perf tools: Add helpers for calling Python objects Adrian Hunter
2014-08-14  8:51   ` [tip:perf/core] perf script python: " tip-bot for Adrian Hunter
2014-07-31  6:01 ` [PATCH 19/31] perf tools: Extend Python script interface to export data in a database-friendly way Adrian Hunter
2014-07-31  6:01 ` [PATCH 20/31] perf tools: Add Python script to export to postgresql Adrian Hunter
2014-07-31  6:01 ` [PATCH 21/31] perf tools: Add flags and insn_len to struct sample Adrian Hunter
2014-08-14  8:51   ` [tip:perf/core] " tip-bot for Adrian Hunter
2014-07-31  6:01 ` [PATCH 22/31] perf tools: Add branch type to db export Adrian Hunter
2014-07-31  6:01 ` [PATCH 23/31] perf tools: Add branch_type and in_tx to Python export Adrian Hunter
2014-07-31  6:01 ` [PATCH 24/31] perf tools: Enhance the thread stack to output call/return data Adrian Hunter
2014-07-31  6:01 ` [PATCH 25/31] perf tools: Add call information to the database export API Adrian Hunter
2014-07-31  6:01 ` [PATCH 26/31] perf tools: Add call information to Python export Adrian Hunter
2014-07-31  6:01 ` [PATCH 27/31] perf tools: Add 'flush' callback to scripting API Adrian Hunter
2014-07-31  6:01 ` [PATCH 28/31] perf tools: Defer export of comms that were not 'set' Adrian Hunter
2014-07-31  6:01 ` [PATCH 29/31] perf tools: Add perf-with-kcore script Adrian Hunter
2014-09-19  5:20   ` [tip:perf/core] " tip-bot for Adrian Hunter
2014-07-31  6:01 ` [PATCH 30/31] perf tools: Build programs to copy 32-bit compatibility VDSOs Adrian Hunter
2014-07-31  6:01 ` Adrian Hunter [this message]
2014-08-04 21:58 ` [PATCH 00/31] perf tools: Yet more preparation for call graph from Intel BTS Arnaldo Carvalho de Melo
2014-08-05 17:13   ` Adrian Hunter

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=1406786474-9306-32-git-send-email-adrian.hunter@intel.com \
    --to=adrian.hunter@intel.com \
    --cc=acme@kernel.org \
    --cc=dsahern@gmail.com \
    --cc=eranian@google.com \
    --cc=fweisbec@gmail.com \
    --cc=jolsa@redhat.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=namhyung@gmail.com \
    --cc=paulus@samba.org \
    --cc=peterz@infradead.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).