2009-11-16 18:33:01

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 1/5] perf symbols: pass the offset to perf_header__read_build_ids

From: Arnaldo Carvalho de Melo <[email protected]>

Cc: Frederic Weisbecker <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/data_map.c | 3 +--
tools/perf/util/data_map.h | 2 +-
tools/perf/util/header.c | 2 +-
3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
index aacb814..14cb846 100644
--- a/tools/perf/util/data_map.c
+++ b/tools/perf/util/data_map.c
@@ -70,11 +70,10 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
}
}

-int perf_header__read_build_ids(int input, off_t size)
+int perf_header__read_build_ids(int input, off_t offset, off_t size)
{
struct build_id_event bev;
char filename[PATH_MAX];
- off_t offset = lseek(input, 0, SEEK_CUR);
off_t limit = offset + size;
int err = -1;

diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h
index 20b4037..ae036ec 100644
--- a/tools/perf/util/data_map.h
+++ b/tools/perf/util/data_map.h
@@ -27,6 +27,6 @@ int mmap_dispatch_perf_file(struct perf_header **pheader,
int full_paths,
int *cwdlen,
char **cwd);
-int perf_header__read_build_ids(int input, off_t file_size);
+int perf_header__read_build_ids(int input, off_t offset, off_t file_size);

#endif
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ebed4f4..ca0d657 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -359,7 +359,7 @@ static void perf_header__adds_read(struct perf_header *self, int fd)

buildid_sec = &feat_sec[idx++];
lseek(fd, buildid_sec->offset, SEEK_SET);
- if (perf_header__read_build_ids(fd, buildid_sec->size))
+ if (perf_header__read_build_ids(fd, buildid_sec->offset, buildid_sec->size))
pr_debug("failed to read buildids, continuing...\n");
}

--
1.6.2.5


2009-11-16 18:32:54

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 2/5] perf tools: debug.h needs to include event.h for event_t

From: Arnaldo Carvalho de Melo <[email protected]>

Cc: Frederic Weisbecker <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/debug.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index e8b18a1..c6c24c5 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -2,6 +2,8 @@
#ifndef __PERF_DEBUG_H
#define __PERF_DEBUG_H

+#include "event.h"
+
extern int verbose;
extern int dump_trace;

--
1.6.2.5

2009-11-16 18:32:53

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 3/5] perf tools: Generalize perf_header__adds_read

From: Arnaldo Carvalho de Melo <[email protected]>

Renaming it to perf_header__process_sections and passing a callback to
handle each feature.

The next changesets will introduce 'perf buildid-list' that will handle
just the HEADER_BUILD_ID table, ignoring all the other features.

Cc: Frederic Weisbecker <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/header.c | 123 ++++++++++++++++++++++++++--------------------
tools/perf/util/header.h | 31 +++++++++++-
2 files changed, 98 insertions(+), 56 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ca0d657..d8416f0 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -128,26 +128,11 @@ static const char *__perf_magic = "PERFFILE";

#define PERF_MAGIC (*(u64 *)__perf_magic)

-struct perf_file_section {
- u64 offset;
- u64 size;
-};
-
struct perf_file_attr {
struct perf_event_attr attr;
struct perf_file_section ids;
};

-struct perf_file_header {
- u64 magic;
- u64 size;
- u64 attr_size;
- struct perf_file_section attrs;
- struct perf_file_section data;
- struct perf_file_section event_types;
- DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
-};
-
void perf_header__set_feat(struct perf_header *self, int feat)
{
set_bit(feat, self->adds_features);
@@ -324,21 +309,23 @@ static void do_read(int fd, void *buf, size_t size)
}
}

-static void perf_header__adds_read(struct perf_header *self, int fd)
+int perf_header__process_sections(struct perf_header *self, int fd,
+ int (*process)(struct perf_file_section *self,
+ int feat, int fd))
{
struct perf_file_section *feat_sec;
int nr_sections;
int sec_size;
int idx = 0;
-
+ int err = 0, feat = 1;

nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
if (!nr_sections)
- return;
+ return 0;

feat_sec = calloc(sizeof(*feat_sec), nr_sections);
if (!feat_sec)
- die("No memory");
+ return -1;

sec_size = sizeof(*feat_sec) * nr_sections;

@@ -346,25 +333,73 @@ static void perf_header__adds_read(struct perf_header *self, int fd)

do_read(fd, feat_sec, sec_size);

- if (perf_header__has_feat(self, HEADER_TRACE_INFO)) {
- struct perf_file_section *trace_sec;
+ while (idx < nr_sections && feat < HEADER_LAST_FEATURE) {
+ if (perf_header__has_feat(self, feat)) {
+ struct perf_file_section *sec = &feat_sec[idx++];

- trace_sec = &feat_sec[idx++];
- lseek(fd, trace_sec->offset, SEEK_SET);
- trace_report(fd);
+ err = process(sec, feat, fd);
+ if (err < 0)
+ break;
+ }
+ ++feat;
}

- if (perf_header__has_feat(self, HEADER_BUILD_ID)) {
- struct perf_file_section *buildid_sec;
+ free(feat_sec);
+ return err;
+};

- buildid_sec = &feat_sec[idx++];
- lseek(fd, buildid_sec->offset, SEEK_SET);
- if (perf_header__read_build_ids(fd, buildid_sec->offset, buildid_sec->size))
- pr_debug("failed to read buildids, continuing...\n");
+int perf_file_header__read(struct perf_file_header *self,
+ struct perf_header *ph, int fd)
+{
+ lseek(fd, 0, SEEK_SET);
+ do_read(fd, self, sizeof(*self));
+
+ if (self->magic != PERF_MAGIC ||
+ self->attr_size != sizeof(struct perf_file_attr))
+ return -1;
+
+ if (self->size != sizeof(*self)) {
+ /* Support the previous format */
+ if (self->size == offsetof(typeof(*self), adds_features))
+ bitmap_zero(self->adds_features, HEADER_FEAT_BITS);
+ else
+ return -1;
}

- free(feat_sec);
-};
+ memcpy(&ph->adds_features, &self->adds_features,
+ sizeof(self->adds_features));
+
+ ph->event_offset = self->event_types.offset;
+ ph->event_size = self->event_types.size;
+ ph->data_offset = self->data.offset;
+ ph->data_size = self->data.size;
+ return 0;
+}
+
+static int perf_file_section__process(struct perf_file_section *self,
+ int feat, int fd)
+{
+ if (lseek(fd, self->offset, SEEK_SET) < 0) {
+ pr_debug("Failed to lseek to %Ld offset for feature %d, "
+ "continuing...\n", self->offset, feat);
+ return 0;
+ }
+
+ switch (feat) {
+ case HEADER_TRACE_INFO:
+ trace_report(fd);
+ break;
+
+ case HEADER_BUILD_ID:
+ if (perf_header__read_build_ids(fd, self->offset, self->size))
+ pr_debug("Failed to read buildids, continuing...\n");
+ break;
+ default:
+ pr_debug("unknown feature %d, continuing...\n", feat);
+ }
+
+ return 0;
+}

struct perf_header *perf_header__read(int fd)
{
@@ -372,23 +407,11 @@ struct perf_header *perf_header__read(int fd)
struct perf_file_header f_header;
struct perf_file_attr f_attr;
u64 f_id;
-
int nr_attrs, nr_ids, i, j;

- lseek(fd, 0, SEEK_SET);
- do_read(fd, &f_header, sizeof(f_header));
-
- if (f_header.magic != PERF_MAGIC ||
- f_header.attr_size != sizeof(f_attr))
+ if (perf_file_header__read(&f_header, self, fd) < 0)
die("incompatible file format");

- if (f_header.size != sizeof(f_header)) {
- /* Support the previous format */
- if (f_header.size == offsetof(typeof(f_header), adds_features))
- bitmap_zero(f_header.adds_features, HEADER_FEAT_BITS);
- else
- die("incompatible file format");
- }
nr_attrs = f_header.attrs.size / sizeof(f_attr);
lseek(fd, f_header.attrs.offset, SEEK_SET);

@@ -422,15 +445,7 @@ struct perf_header *perf_header__read(int fd)
event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
}

- memcpy(&self->adds_features, &f_header.adds_features, sizeof(f_header.adds_features));
-
- self->event_offset = f_header.event_types.offset;
- self->event_size = f_header.event_types.size;
-
- self->data_offset = f_header.data.offset;
- self->data_size = f_header.data.size;
-
- perf_header__adds_read(self, fd);
+ perf_header__process_sections(self, fd, perf_file_section__process);

lseek(fd, self->data_offset, SEEK_SET);

diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index a22d70b..f1b3bf7 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -15,11 +15,34 @@ struct perf_header_attr {
off_t id_offset;
};

-#define HEADER_TRACE_INFO 1
-#define HEADER_BUILD_ID 2
+enum {
+ HEADER_TRACE_INFO = 1,
+ HEADER_BUILD_ID,
+ HEADER_LAST_FEATURE,
+};

#define HEADER_FEAT_BITS 256

+struct perf_file_section {
+ u64 offset;
+ u64 size;
+};
+
+struct perf_file_header {
+ u64 magic;
+ u64 size;
+ u64 attr_size;
+ struct perf_file_section attrs;
+ struct perf_file_section data;
+ struct perf_file_section event_types;
+ DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
+};
+
+struct perf_header;
+
+int perf_file_header__read(struct perf_file_header *self,
+ struct perf_header *ph, int fd);
+
struct perf_header {
int frozen;
int attrs, size;
@@ -54,4 +77,8 @@ bool perf_header__has_feat(const struct perf_header *self, int feat);

struct perf_header *perf_header__new(void);

+int perf_header__process_sections(struct perf_header *self, int fd,
+ int (*process)(struct perf_file_section *self,
+ int feat, int fd));
+
#endif /* __PERF_HEADER_H */
--
1.6.2.5

2009-11-16 18:32:48

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 4/5] perf tools: Introduce dsos__fprintf_buildid

From: Arnaldo Carvalho de Melo <[email protected]>

To print the buildids in the list of dsos. Will be used by 'perf
buildid-list'

Cc: Frederic Weisbecker <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/util/symbol.c | 30 ++++++++++++++++++++++++++----
tools/perf/util/symbol.h | 2 ++
2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 93e4b52..53de9c4 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -212,14 +212,21 @@ int build_id__sprintf(u8 *self, int len, char *bf)
return raw - self;
}

-size_t dso__fprintf(struct dso *self, FILE *fp)
+size_t dso__fprintf_buildid(struct dso *self, FILE *fp)
{
char sbuild_id[BUILD_ID_SIZE * 2 + 1];
- struct rb_node *nd;
- size_t ret;

build_id__sprintf(self->build_id, sizeof(self->build_id), sbuild_id);
- ret = fprintf(fp, "dso: %s (%s)\n", self->short_name, sbuild_id);
+ return fprintf(fp, "%s", sbuild_id);
+}
+
+size_t dso__fprintf(struct dso *self, FILE *fp)
+{
+ struct rb_node *nd;
+ size_t ret = fprintf(fp, "dso: %s (", self->short_name);
+
+ ret += dso__fprintf_buildid(self, fp);
+ ret += fprintf(fp, ")\n");

for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) {
struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
@@ -1428,6 +1435,21 @@ void dsos__fprintf(FILE *fp)
dso__fprintf(pos, fp);
}

+size_t dsos__fprintf_buildid(FILE *fp)
+{
+ struct dso *pos;
+ size_t ret = 0;
+
+ list_for_each_entry(pos, &dsos, node) {
+ ret += dso__fprintf_buildid(pos, fp);
+ if (verbose)
+ ret += fprintf(fp, " %s\n", pos->long_name);
+ else
+ ret += fprintf(fp, "\n");
+ }
+ return ret;
+}
+
int load_kernel(symbol_filter_t filter)
{
if (dsos__load_kernel(vmlinux_name, filter, modules) <= 0)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 0a34a54..51c5a4a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -80,7 +80,9 @@ int dsos__load_kernel(const char *vmlinux, symbol_filter_t filter, int modules);
struct dso *dsos__findnew(const char *name);
int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
void dsos__fprintf(FILE *fp);
+size_t dsos__fprintf_buildid(FILE *fp);

+size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
size_t dso__fprintf(struct dso *self, FILE *fp);
char dso__symtab_origin(const struct dso *self);
void dso__set_build_id(struct dso *self, void *build_id);
--
1.6.2.5

2009-11-16 18:32:53

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [PATCH 5/5] perf buildid-list: New plumbing command

From: Arnaldo Carvalho de Melo <[email protected]>

With this we can list the buildids in a perf.data file so that we can
pipe them to other, distro specific tools that from the buildids can
figure out separate packages (foo-debuginfo) where we can find the
matching symtabs so that perf report can do its job.

E.g:

[acme@doppio linux-2.6-tip]$ perf buildid-list | head -5
8e08b117e5458ad3f85da16d42d0fc5cd21c5869
520c2387a587cc5acfcf881e27dba1caaeab4b1f
ec8dd400904ddfcac8b1c343263a790f977159dc
7caedbca5a6d8ab39a7fe44bd28c07d3e14a3f3f
379bb828fd08859dbea73279f04abefabc95a6a3
[acme@doppio linux-2.6-tip]$ perf buildid-list -v | head -5
8e08b117e5458ad3f85da16d42d0fc5cd21c5869 /sbin/init
520c2387a587cc5acfcf881e27dba1caaeab4b1f /lib64/ld-2.10.1.so
ec8dd400904ddfcac8b1c343263a790f977159dc /lib64/libc-2.10.1.so
7caedbca5a6d8ab39a7fe44bd28c07d3e14a3f3f /sbin/udevd
379bb828fd08859dbea73279f04abefabc95a6a3 /lib64/libdl-2.10.1.so
[acme@doppio linux-2.6-tip]$

Cc: Frederic Weisbecker <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
---
tools/perf/Documentation/perf-buildid-list.txt | 34 +++++++
tools/perf/Makefile | 1 +
tools/perf/builtin-buildid-list.c | 116 ++++++++++++++++++++++++
tools/perf/builtin.h | 1 +
tools/perf/command-list.txt | 1 +
tools/perf/perf.c | 1 +
6 files changed, 154 insertions(+), 0 deletions(-)
create mode 100644 tools/perf/Documentation/perf-buildid-list.txt
create mode 100644 tools/perf/builtin-buildid-list.c

diff --git a/tools/perf/Documentation/perf-buildid-list.txt b/tools/perf/Documentation/perf-buildid-list.txt
new file mode 100644
index 0000000..abab34e
--- /dev/null
+++ b/tools/perf/Documentation/perf-buildid-list.txt
@@ -0,0 +1,34 @@
+perf-buildid-list(1)
+====================
+
+NAME
+----
+perf-buildid-list - List the buildids in a perf.data file
+
+SYNOPSIS
+--------
+[verse]
+'perf buildid-list <options>'
+
+DESCRIPTION
+-----------
+This command displays the buildids found in a perf.data file, so that other
+tools can be used to fetch packages with matching symbol tables for use by
+perf report.
+
+OPTIONS
+-------
+-i::
+--input=::
+ Input file name. (default: perf.data)
+-f::
+--force::
+ Don't do ownership validation.
+-v::
+--verbose::
+ Be more verbose, showing the name of the DSOs after the buildids.
+
+SEE ALSO
+--------
+linkperf:perf-record[1], linkperf:perf-top[1],
+linkperf:perf-report[1]
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index cd42c97..3dbb5c5 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -431,6 +431,7 @@ BUILTIN_OBJS += bench/sched-pipe.o

BUILTIN_OBJS += builtin-help.o
BUILTIN_OBJS += builtin-sched.o
+BUILTIN_OBJS += builtin-buildid-list.o
BUILTIN_OBJS += builtin-list.o
BUILTIN_OBJS += builtin-record.o
BUILTIN_OBJS += builtin-report.o
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
new file mode 100644
index 0000000..2e377e1
--- /dev/null
+++ b/tools/perf/builtin-buildid-list.c
@@ -0,0 +1,116 @@
+/*
+ * builtin-buildid-list.c
+ *
+ * Builtin buildid-list command: list buildids in perf.data
+ *
+ * Copyright (C) 2009, Red Hat Inc.
+ * Copyright (C) 2009, Arnaldo Carvalho de Melo <[email protected]>
+ */
+#include "builtin.h"
+#include "perf.h"
+#include "util/cache.h"
+#include "util/data_map.h"
+#include "util/debug.h"
+#include "util/header.h"
+#include "util/parse-options.h"
+#include "util/symbol.h"
+
+static char const *input_name = "perf.data";
+static int force;
+
+static const char *const buildid_list_usage[] = {
+ "perf report [<options>]",
+ NULL
+};
+
+static const struct option options[] = {
+ OPT_STRING('i', "input", &input_name, "file",
+ "input file name"),
+ OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
+ OPT_BOOLEAN('v', "verbose", &verbose,
+ "be more verbose (show counter open errors, etc)"),
+ OPT_END()
+};
+
+static int perf_file_section__process_buildids(struct perf_file_section *self,
+ int feat, int fd)
+{
+ if (feat != HEADER_BUILD_ID)
+ return 0;
+
+ if (lseek(fd, self->offset, SEEK_SET) < 0) {
+ pr_warning("Failed to lseek to %Ld offset for buildids!\n",
+ self->offset);
+ return -1;
+ }
+
+ if (perf_header__read_build_ids(fd, self->offset, self->size)) {
+ pr_warning("Failed to read buildids!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __cmd_buildid_list(void)
+{
+ int err = -1;
+ struct perf_header *header;
+ struct perf_file_header f_header;
+ struct stat input_stat;
+ int input = open(input_name, O_RDONLY);
+
+ if (input < 0) {
+ pr_err("failed to open file: %s", input_name);
+ if (!strcmp(input_name, "perf.data"))
+ pr_err(" (try 'perf record' first)");
+ pr_err("\n");
+ goto out;
+ }
+
+ err = fstat(input, &input_stat);
+ if (err < 0) {
+ perror("failed to stat file");
+ goto out_close;
+ }
+
+ if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
+ pr_err("file %s not owned by current user or root\n",
+ input_name);
+ goto out_close;
+ }
+
+ if (!input_stat.st_size) {
+ pr_info("zero-sized file, nothing to do!\n");
+ goto out_close;
+ }
+
+ err = -1;
+ header = perf_header__new();
+ if (header == NULL)
+ goto out_close;
+
+ if (perf_file_header__read(&f_header, header, input) < 0) {
+ pr_warning("incompatible file format");
+ goto out_close;
+ }
+
+ err = perf_header__process_sections(header, input,
+ perf_file_section__process_buildids);
+
+ if (err < 0)
+ goto out_close;
+
+ dsos__fprintf_buildid(stdout);
+out_close:
+ close(input);
+out:
+ return err;
+}
+
+int cmd_buildid_list(int argc, const char **argv, const char *prefix __used)
+{
+ argc = parse_options(argc, argv, options, buildid_list_usage, 0);
+ setup_pager();
+ return __cmd_buildid_list();
+}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index d4fe12d..9b02d85 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -16,6 +16,7 @@ extern int check_pager_config(const char *cmd);

extern int cmd_annotate(int argc, const char **argv, const char *prefix);
extern int cmd_bench(int argc, const char **argv, const char *prefix);
+extern int cmd_buildid_list(int argc, const char **argv, const char *prefix);
extern int cmd_help(int argc, const char **argv, const char *prefix);
extern int cmd_sched(int argc, const char **argv, const char *prefix);
extern int cmd_list(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 1642a88..983ae29 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -4,6 +4,7 @@
#
perf-annotate mainporcelain common
perf-bench mainporcelain common
+perf-build-list mainporcelain common
perf-list mainporcelain common
perf-sched mainporcelain common
perf-record mainporcelain common
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 9cd55b9..89b82ac 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -287,6 +287,7 @@ static void handle_internal_command(int argc, const char **argv)
static struct cmd_struct commands[] = {
{ "help", cmd_help, 0 },
{ "list", cmd_list, 0 },
+ { "buildid-list", cmd_buildid_list, 0 },
{ "record", cmd_record, 0 },
{ "report", cmd_report, 0 },
{ "bench", cmd_bench, 0 },
--
1.6.2.5

2009-11-16 18:58:47

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH 5/5] perf buildid-list: New plumbing command

On Mon, Nov 16, 2009 at 04:32:45PM -0200, Arnaldo Carvalho de Melo wrote:
> From: Arnaldo Carvalho de Melo <[email protected]>
>
> With this we can list the buildids in a perf.data file so that we can
> pipe them to other, distro specific tools that from the buildids can
> figure out separate packages (foo-debuginfo) where we can find the
> matching symtabs so that perf report can do its job.
>
> E.g:
>
> [acme@doppio linux-2.6-tip]$ perf buildid-list | head -5
> 8e08b117e5458ad3f85da16d42d0fc5cd21c5869
> 520c2387a587cc5acfcf881e27dba1caaeab4b1f
> ec8dd400904ddfcac8b1c343263a790f977159dc
> 7caedbca5a6d8ab39a7fe44bd28c07d3e14a3f3f
> 379bb828fd08859dbea73279f04abefabc95a6a3
> [acme@doppio linux-2.6-tip]$ perf buildid-list -v | head -5
> 8e08b117e5458ad3f85da16d42d0fc5cd21c5869 /sbin/init
> 520c2387a587cc5acfcf881e27dba1caaeab4b1f /lib64/ld-2.10.1.so
> ec8dd400904ddfcac8b1c343263a790f977159dc /lib64/libc-2.10.1.so
> 7caedbca5a6d8ab39a7fe44bd28c07d3e14a3f3f /sbin/udevd
> 379bb828fd08859dbea73279f04abefabc95a6a3 /lib64/libdl-2.10.1.so


I would rather see the effect of this -v option as the default.
It's very useful to see the dso resolved but hashes alone
don't pay much.

2009-11-16 19:02:18

by Frederic Weisbecker

[permalink] [raw]
Subject: Re: [PATCH 3/5] perf tools: Generalize perf_header__adds_read

On Mon, Nov 16, 2009 at 04:32:43PM -0200, Arnaldo Carvalho de Melo wrote:
> From: Arnaldo Carvalho de Melo <[email protected]>
>
> Renaming it to perf_header__process_sections and passing a callback to
> handle each feature.
>
> The next changesets will introduce 'perf buildid-list' that will handle
> just the HEADER_BUILD_ID table, ignoring all the other features.
>
> Cc: Frederic Weisbecker <[email protected]>
> Cc: Mike Galbraith <[email protected]>
> Cc: Paul Mackerras <[email protected]>
> Cc: Peter Zijlstra <[email protected]>
> Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>


Looks much proper this way, indeed :)

2009-11-16 19:41:14

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH 5/5] perf buildid-list: New plumbing command

Em Mon, Nov 16, 2009 at 07:58:52PM +0100, Frederic Weisbecker escreveu:
> On Mon, Nov 16, 2009 at 04:32:45PM -0200, Arnaldo Carvalho de Melo wrote:
> > With this we can list the buildids in a perf.data file so that we can
> > pipe them to other, distro specific tools that from the buildids can
> > figure out separate packages (foo-debuginfo) where we can find the
> > matching symtabs so that perf report can do its job.
> > E.g:
> > [acme@doppio linux-2.6-tip]$ perf buildid-list | head -2
> > 8e08b117e5458ad3f85da16d42d0fc5cd21c5869
> > 520c2387a587cc5acfcf881e27dba1caaeab4b1f
> > [acme@doppio linux-2.6-tip]$ perf buildid-list -v | head -2
> > 8e08b117e5458ad3f85da16d42d0fc5cd21c5869 /sbin/init
> > 520c2387a587cc5acfcf881e27dba1caaeab4b1f /lib64/ld-2.10.1.so
>
> I would rather see the effect of this -v option as the default.
> It's very useful to see the dso resolved but hashes alone
> don't pay much.

I disagree, the main purpose of this command is equivalent to 'git
rev-list':

[acme@doppio linux-2.6-tip]$ git rev-list HEAD^^..
089242a8c826aac1c827bb797475b9852fe0db49
18e3a75dc47d8397bbf0936ec8e3ebdecada7ba1
[acme@doppio linux-2.6-tip]$

I.e. provide content keys that then will be used by distro specific
porcelain to get the matching -debuginfo packages with the symtabs.

- Arnaldo

2009-11-16 20:58:26

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 5/5] perf buildid-list: New plumbing command


* Arnaldo Carvalho de Melo <[email protected]> wrote:

> Em Mon, Nov 16, 2009 at 07:58:52PM +0100, Frederic Weisbecker escreveu:
> > On Mon, Nov 16, 2009 at 04:32:45PM -0200, Arnaldo Carvalho de Melo wrote:
> > > With this we can list the buildids in a perf.data file so that we can
> > > pipe them to other, distro specific tools that from the buildids can
> > > figure out separate packages (foo-debuginfo) where we can find the
> > > matching symtabs so that perf report can do its job.
> > > E.g:
> > > [acme@doppio linux-2.6-tip]$ perf buildid-list | head -2
> > > 8e08b117e5458ad3f85da16d42d0fc5cd21c5869
> > > 520c2387a587cc5acfcf881e27dba1caaeab4b1f
> > > [acme@doppio linux-2.6-tip]$ perf buildid-list -v | head -2
> > > 8e08b117e5458ad3f85da16d42d0fc5cd21c5869 /sbin/init
> > > 520c2387a587cc5acfcf881e27dba1caaeab4b1f /lib64/ld-2.10.1.so
> >
> > I would rather see the effect of this -v option as the default.
> > It's very useful to see the dso resolved but hashes alone
> > don't pay much.
>
> I disagree, the main purpose of this command is equivalent to 'git
> rev-list':
>
> [acme@doppio linux-2.6-tip]$ git rev-list HEAD^^..
> 089242a8c826aac1c827bb797475b9852fe0db49
> 18e3a75dc47d8397bbf0936ec8e3ebdecada7ba1
> [acme@doppio linux-2.6-tip]$
>
> I.e. provide content keys that then will be used by distro specific
> porcelain to get the matching -debuginfo packages with the symtabs.

Hm, i'd say that's a (small) bug in Git.

Porcelain can add flags just fine to get 'raw' behavior - so in general
we want to default the most human friendly parameters to the most
human-readable output format.

Ingo

2009-11-16 21:02:57

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 5/5] perf buildid-list: New plumbing command


* Arnaldo Carvalho de Melo <[email protected]> wrote:

> +++ b/tools/perf/command-list.txt
> @@ -4,6 +4,7 @@
> #
> perf-annotate mainporcelain common
> perf-bench mainporcelain common
> +perf-build-list mainporcelain common

s/build-list/buildid-list

Ingo

2009-11-16 21:04:04

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH 5/5] perf buildid-list: New plumbing command

Em Mon, Nov 16, 2009 at 09:58:20PM +0100, Ingo Molnar escreveu:
>
> * Arnaldo Carvalho de Melo <[email protected]> wrote:
>
> > Em Mon, Nov 16, 2009 at 07:58:52PM +0100, Frederic Weisbecker escreveu:
> > > On Mon, Nov 16, 2009 at 04:32:45PM -0200, Arnaldo Carvalho de Melo wrote:
> > > > With this we can list the buildids in a perf.data file so that we can
> > > > pipe them to other, distro specific tools that from the buildids can
> > > > figure out separate packages (foo-debuginfo) where we can find the
> > > > matching symtabs so that perf report can do its job.
> > > > E.g:
> > > > [acme@doppio linux-2.6-tip]$ perf buildid-list | head -2
> > > > 8e08b117e5458ad3f85da16d42d0fc5cd21c5869
> > > > 520c2387a587cc5acfcf881e27dba1caaeab4b1f
> > > > [acme@doppio linux-2.6-tip]$ perf buildid-list -v | head -2
> > > > 8e08b117e5458ad3f85da16d42d0fc5cd21c5869 /sbin/init
> > > > 520c2387a587cc5acfcf881e27dba1caaeab4b1f /lib64/ld-2.10.1.so
> > >
> > > I would rather see the effect of this -v option as the default.
> > > It's very useful to see the dso resolved but hashes alone
> > > don't pay much.
> >
> > I disagree, the main purpose of this command is equivalent to 'git
> > rev-list':
> >
> > [acme@doppio linux-2.6-tip]$ git rev-list HEAD^^..
> > 089242a8c826aac1c827bb797475b9852fe0db49
> > 18e3a75dc47d8397bbf0936ec8e3ebdecada7ba1
> > [acme@doppio linux-2.6-tip]$
> >
> > I.e. provide content keys that then will be used by distro specific
> > porcelain to get the matching -debuginfo packages with the symtabs.
>
> Hm, i'd say that's a (small) bug in Git.
>
> Porcelain can add flags just fine to get 'raw' behavior - so in general
> we want to default the most human friendly parameters to the most
> human-readable output format.

Well, no strong feelings here, make it the other way around and the most
usual case will just ignore those extra characters :-)

- Arnaldo

2009-11-16 21:05:22

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: Re: [PATCH 5/5] perf buildid-list: New plumbing command

Em Mon, Nov 16, 2009 at 10:02:42PM +0100, Ingo Molnar escreveu:
>
> * Arnaldo Carvalho de Melo <[email protected]> wrote:
>
> > +++ b/tools/perf/command-list.txt
> > @@ -4,6 +4,7 @@
> > #
> > perf-annotate mainporcelain common
> > perf-bench mainporcelain common
> > +perf-build-list mainporcelain common
>
> s/build-list/buildid-list

Ooops, do you want me to resent the whole series or can you please fix
this up while merging? :)

- Arnaldo

2009-11-16 21:05:42

by Peter Zijlstra

[permalink] [raw]
Subject: Re: [PATCH 5/5] perf buildid-list: New plumbing command

On Mon, 2009-11-16 at 17:41 -0200, Arnaldo Carvalho de Melo wrote:
> Em Mon, Nov 16, 2009 at 07:58:52PM +0100, Frederic Weisbecker escreveu:
> > On Mon, Nov 16, 2009 at 04:32:45PM -0200, Arnaldo Carvalho de Melo wrote:
> > > With this we can list the buildids in a perf.data file so that we can
> > > pipe them to other, distro specific tools that from the buildids can
> > > figure out separate packages (foo-debuginfo) where we can find the
> > > matching symtabs so that perf report can do its job.
> > > E.g:
> > > [acme@doppio linux-2.6-tip]$ perf buildid-list | head -2
> > > 8e08b117e5458ad3f85da16d42d0fc5cd21c5869
> > > 520c2387a587cc5acfcf881e27dba1caaeab4b1f
> > > [acme@doppio linux-2.6-tip]$ perf buildid-list -v | head -2
> > > 8e08b117e5458ad3f85da16d42d0fc5cd21c5869 /sbin/init
> > > 520c2387a587cc5acfcf881e27dba1caaeab4b1f /lib64/ld-2.10.1.so
> >
> > I would rather see the effect of this -v option as the default.
> > It's very useful to see the dso resolved but hashes alone
> > don't pay much.
>
> I disagree, the main purpose of this command is equivalent to 'git
> rev-list':
>
> [acme@doppio linux-2.6-tip]$ git rev-list HEAD^^..
> 089242a8c826aac1c827bb797475b9852fe0db49
> 18e3a75dc47d8397bbf0936ec8e3ebdecada7ba1
> [acme@doppio linux-2.6-tip]$
>
> I.e. provide content keys that then will be used by distro specific
> porcelain to get the matching -debuginfo packages with the symtabs.

I'm pretty sure such distro specific muck can trivially ignore the
second column.

And the output is much _much_ more useful when it has the dso listed.

2009-11-16 21:06:40

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 5/5] perf buildid-list: New plumbing command


* Arnaldo Carvalho de Melo <[email protected]> wrote:

> Em Mon, Nov 16, 2009 at 10:02:42PM +0100, Ingo Molnar escreveu:
> >
> > * Arnaldo Carvalho de Melo <[email protected]> wrote:
> >
> > > +++ b/tools/perf/command-list.txt
> > > @@ -4,6 +4,7 @@
> > > #
> > > perf-annotate mainporcelain common
> > > perf-bench mainporcelain common
> > > +perf-build-list mainporcelain common
> >
> > s/build-list/buildid-list
>
> Ooops, do you want me to resent the whole series or can you please fix
> this up while merging? :)

already fixed :)

Ingo

2009-11-16 21:07:47

by Ingo Molnar

[permalink] [raw]
Subject: Re: [PATCH 5/5] perf buildid-list: New plumbing command


* Arnaldo Carvalho de Melo <[email protected]> wrote:

> Em Mon, Nov 16, 2009 at 09:58:20PM +0100, Ingo Molnar escreveu:
> >
> > * Arnaldo Carvalho de Melo <[email protected]> wrote:
> >
> > > Em Mon, Nov 16, 2009 at 07:58:52PM +0100, Frederic Weisbecker escreveu:
> > > > On Mon, Nov 16, 2009 at 04:32:45PM -0200, Arnaldo Carvalho de Melo wrote:
> > > > > With this we can list the buildids in a perf.data file so that we can
> > > > > pipe them to other, distro specific tools that from the buildids can
> > > > > figure out separate packages (foo-debuginfo) where we can find the
> > > > > matching symtabs so that perf report can do its job.
> > > > > E.g:
> > > > > [acme@doppio linux-2.6-tip]$ perf buildid-list | head -2
> > > > > 8e08b117e5458ad3f85da16d42d0fc5cd21c5869
> > > > > 520c2387a587cc5acfcf881e27dba1caaeab4b1f
> > > > > [acme@doppio linux-2.6-tip]$ perf buildid-list -v | head -2
> > > > > 8e08b117e5458ad3f85da16d42d0fc5cd21c5869 /sbin/init
> > > > > 520c2387a587cc5acfcf881e27dba1caaeab4b1f /lib64/ld-2.10.1.so
> > > >
> > > > I would rather see the effect of this -v option as the default.
> > > > It's very useful to see the dso resolved but hashes alone
> > > > don't pay much.
> > >
> > > I disagree, the main purpose of this command is equivalent to 'git
> > > rev-list':
> > >
> > > [acme@doppio linux-2.6-tip]$ git rev-list HEAD^^..
> > > 089242a8c826aac1c827bb797475b9852fe0db49
> > > 18e3a75dc47d8397bbf0936ec8e3ebdecada7ba1
> > > [acme@doppio linux-2.6-tip]$
> > >
> > > I.e. provide content keys that then will be used by distro specific
> > > porcelain to get the matching -debuginfo packages with the symtabs.
> >
> > Hm, i'd say that's a (small) bug in Git.
> >
> > Porcelain can add flags just fine to get 'raw' behavior - so in general
> > we want to default the most human friendly parameters to the most
> > human-readable output format.
>
> Well, no strong feelings here, make it the other way around and the
> most usual case will just ignore those extra characters :-)

i looked briefly but it didnt seem obvious to invert 'verbose' (which is
library shared), and i have the excuse of it being late here - so i'll
leave it up to you in a followup patch :-)

Ingo

2009-11-16 21:12:44

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [tip:perf/core] perf symbols: Pass the offset to perf_header__read_build_ids()

Commit-ID: 84fe8488ade7922afa9f3aa77c22d2d92beb9660
Gitweb: http://git.kernel.org/tip/84fe8488ade7922afa9f3aa77c22d2d92beb9660
Author: Arnaldo Carvalho de Melo <[email protected]>
AuthorDate: Mon, 16 Nov 2009 16:32:41 -0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Mon, 16 Nov 2009 22:05:49 +0100

perf symbols: Pass the offset to perf_header__read_build_ids()

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/util/data_map.c | 3 +--
tools/perf/util/data_map.h | 2 +-
tools/perf/util/header.c | 2 +-
3 files changed, 3 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
index aacb814..14cb846 100644
--- a/tools/perf/util/data_map.c
+++ b/tools/perf/util/data_map.c
@@ -70,11 +70,10 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
}
}

-int perf_header__read_build_ids(int input, off_t size)
+int perf_header__read_build_ids(int input, off_t offset, off_t size)
{
struct build_id_event bev;
char filename[PATH_MAX];
- off_t offset = lseek(input, 0, SEEK_CUR);
off_t limit = offset + size;
int err = -1;

diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h
index 20b4037..ae036ec 100644
--- a/tools/perf/util/data_map.h
+++ b/tools/perf/util/data_map.h
@@ -27,6 +27,6 @@ int mmap_dispatch_perf_file(struct perf_header **pheader,
int full_paths,
int *cwdlen,
char **cwd);
-int perf_header__read_build_ids(int input, off_t file_size);
+int perf_header__read_build_ids(int input, off_t offset, off_t file_size);

#endif
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ebed4f4..ca0d657 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -359,7 +359,7 @@ static void perf_header__adds_read(struct perf_header *self, int fd)

buildid_sec = &feat_sec[idx++];
lseek(fd, buildid_sec->offset, SEEK_SET);
- if (perf_header__read_build_ids(fd, buildid_sec->size))
+ if (perf_header__read_build_ids(fd, buildid_sec->offset, buildid_sec->size))
pr_debug("failed to read buildids, continuing...\n");
}

2009-11-16 21:12:36

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [tip:perf/core] perf tools: Debug.h needs to include event.h for event_t

Commit-ID: 8f41146aedf803856fb6477056e3960cb9ba8f9c
Gitweb: http://git.kernel.org/tip/8f41146aedf803856fb6477056e3960cb9ba8f9c
Author: Arnaldo Carvalho de Melo <[email protected]>
AuthorDate: Mon, 16 Nov 2009 16:32:42 -0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Mon, 16 Nov 2009 22:05:50 +0100

perf tools: Debug.h needs to include event.h for event_t

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/util/debug.h | 2 ++
1 files changed, 2 insertions(+), 0 deletions(-)

diff --git a/tools/perf/util/debug.h b/tools/perf/util/debug.h
index e8b18a1..c6c24c5 100644
--- a/tools/perf/util/debug.h
+++ b/tools/perf/util/debug.h
@@ -2,6 +2,8 @@
#ifndef __PERF_DEBUG_H
#define __PERF_DEBUG_H

+#include "event.h"
+
extern int verbose;
extern int dump_trace;

2009-11-16 21:10:59

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [tip:perf/core] perf tools: Generalize perf_header__adds_read()

Commit-ID: 37562eac3767c7f07bb1a1329708ff6453e47570
Gitweb: http://git.kernel.org/tip/37562eac3767c7f07bb1a1329708ff6453e47570
Author: Arnaldo Carvalho de Melo <[email protected]>
AuthorDate: Mon, 16 Nov 2009 16:32:43 -0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Mon, 16 Nov 2009 22:05:50 +0100

perf tools: Generalize perf_header__adds_read()

Renaming it to perf_header__process_sections() and passing a
callback to handle each feature.

The next changesets will introduce 'perf buildid-list' that will
handle just the HEADER_BUILD_ID table, ignoring all the other
features.

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
Acked-by: Frederic Weisbecker <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/util/header.c | 123 ++++++++++++++++++++++++++--------------------
tools/perf/util/header.h | 31 +++++++++++-
2 files changed, 98 insertions(+), 56 deletions(-)

diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index ca0d657..d8416f0 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -128,26 +128,11 @@ static const char *__perf_magic = "PERFFILE";

#define PERF_MAGIC (*(u64 *)__perf_magic)

-struct perf_file_section {
- u64 offset;
- u64 size;
-};
-
struct perf_file_attr {
struct perf_event_attr attr;
struct perf_file_section ids;
};

-struct perf_file_header {
- u64 magic;
- u64 size;
- u64 attr_size;
- struct perf_file_section attrs;
- struct perf_file_section data;
- struct perf_file_section event_types;
- DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
-};
-
void perf_header__set_feat(struct perf_header *self, int feat)
{
set_bit(feat, self->adds_features);
@@ -324,21 +309,23 @@ static void do_read(int fd, void *buf, size_t size)
}
}

-static void perf_header__adds_read(struct perf_header *self, int fd)
+int perf_header__process_sections(struct perf_header *self, int fd,
+ int (*process)(struct perf_file_section *self,
+ int feat, int fd))
{
struct perf_file_section *feat_sec;
int nr_sections;
int sec_size;
int idx = 0;
-
+ int err = 0, feat = 1;

nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
if (!nr_sections)
- return;
+ return 0;

feat_sec = calloc(sizeof(*feat_sec), nr_sections);
if (!feat_sec)
- die("No memory");
+ return -1;

sec_size = sizeof(*feat_sec) * nr_sections;

@@ -346,25 +333,73 @@ static void perf_header__adds_read(struct perf_header *self, int fd)

do_read(fd, feat_sec, sec_size);

- if (perf_header__has_feat(self, HEADER_TRACE_INFO)) {
- struct perf_file_section *trace_sec;
+ while (idx < nr_sections && feat < HEADER_LAST_FEATURE) {
+ if (perf_header__has_feat(self, feat)) {
+ struct perf_file_section *sec = &feat_sec[idx++];

- trace_sec = &feat_sec[idx++];
- lseek(fd, trace_sec->offset, SEEK_SET);
- trace_report(fd);
+ err = process(sec, feat, fd);
+ if (err < 0)
+ break;
+ }
+ ++feat;
}

- if (perf_header__has_feat(self, HEADER_BUILD_ID)) {
- struct perf_file_section *buildid_sec;
+ free(feat_sec);
+ return err;
+};

- buildid_sec = &feat_sec[idx++];
- lseek(fd, buildid_sec->offset, SEEK_SET);
- if (perf_header__read_build_ids(fd, buildid_sec->offset, buildid_sec->size))
- pr_debug("failed to read buildids, continuing...\n");
+int perf_file_header__read(struct perf_file_header *self,
+ struct perf_header *ph, int fd)
+{
+ lseek(fd, 0, SEEK_SET);
+ do_read(fd, self, sizeof(*self));
+
+ if (self->magic != PERF_MAGIC ||
+ self->attr_size != sizeof(struct perf_file_attr))
+ return -1;
+
+ if (self->size != sizeof(*self)) {
+ /* Support the previous format */
+ if (self->size == offsetof(typeof(*self), adds_features))
+ bitmap_zero(self->adds_features, HEADER_FEAT_BITS);
+ else
+ return -1;
}

- free(feat_sec);
-};
+ memcpy(&ph->adds_features, &self->adds_features,
+ sizeof(self->adds_features));
+
+ ph->event_offset = self->event_types.offset;
+ ph->event_size = self->event_types.size;
+ ph->data_offset = self->data.offset;
+ ph->data_size = self->data.size;
+ return 0;
+}
+
+static int perf_file_section__process(struct perf_file_section *self,
+ int feat, int fd)
+{
+ if (lseek(fd, self->offset, SEEK_SET) < 0) {
+ pr_debug("Failed to lseek to %Ld offset for feature %d, "
+ "continuing...\n", self->offset, feat);
+ return 0;
+ }
+
+ switch (feat) {
+ case HEADER_TRACE_INFO:
+ trace_report(fd);
+ break;
+
+ case HEADER_BUILD_ID:
+ if (perf_header__read_build_ids(fd, self->offset, self->size))
+ pr_debug("Failed to read buildids, continuing...\n");
+ break;
+ default:
+ pr_debug("unknown feature %d, continuing...\n", feat);
+ }
+
+ return 0;
+}

struct perf_header *perf_header__read(int fd)
{
@@ -372,23 +407,11 @@ struct perf_header *perf_header__read(int fd)
struct perf_file_header f_header;
struct perf_file_attr f_attr;
u64 f_id;
-
int nr_attrs, nr_ids, i, j;

- lseek(fd, 0, SEEK_SET);
- do_read(fd, &f_header, sizeof(f_header));
-
- if (f_header.magic != PERF_MAGIC ||
- f_header.attr_size != sizeof(f_attr))
+ if (perf_file_header__read(&f_header, self, fd) < 0)
die("incompatible file format");

- if (f_header.size != sizeof(f_header)) {
- /* Support the previous format */
- if (f_header.size == offsetof(typeof(f_header), adds_features))
- bitmap_zero(f_header.adds_features, HEADER_FEAT_BITS);
- else
- die("incompatible file format");
- }
nr_attrs = f_header.attrs.size / sizeof(f_attr);
lseek(fd, f_header.attrs.offset, SEEK_SET);

@@ -422,15 +445,7 @@ struct perf_header *perf_header__read(int fd)
event_count = f_header.event_types.size / sizeof(struct perf_trace_event_type);
}

- memcpy(&self->adds_features, &f_header.adds_features, sizeof(f_header.adds_features));
-
- self->event_offset = f_header.event_types.offset;
- self->event_size = f_header.event_types.size;
-
- self->data_offset = f_header.data.offset;
- self->data_size = f_header.data.size;
-
- perf_header__adds_read(self, fd);
+ perf_header__process_sections(self, fd, perf_file_section__process);

lseek(fd, self->data_offset, SEEK_SET);

diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index a22d70b..f1b3bf7 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -15,11 +15,34 @@ struct perf_header_attr {
off_t id_offset;
};

-#define HEADER_TRACE_INFO 1
-#define HEADER_BUILD_ID 2
+enum {
+ HEADER_TRACE_INFO = 1,
+ HEADER_BUILD_ID,
+ HEADER_LAST_FEATURE,
+};

#define HEADER_FEAT_BITS 256

+struct perf_file_section {
+ u64 offset;
+ u64 size;
+};
+
+struct perf_file_header {
+ u64 magic;
+ u64 size;
+ u64 attr_size;
+ struct perf_file_section attrs;
+ struct perf_file_section data;
+ struct perf_file_section event_types;
+ DECLARE_BITMAP(adds_features, HEADER_FEAT_BITS);
+};
+
+struct perf_header;
+
+int perf_file_header__read(struct perf_file_header *self,
+ struct perf_header *ph, int fd);
+
struct perf_header {
int frozen;
int attrs, size;
@@ -54,4 +77,8 @@ bool perf_header__has_feat(const struct perf_header *self, int feat);

struct perf_header *perf_header__new(void);

+int perf_header__process_sections(struct perf_header *self, int fd,
+ int (*process)(struct perf_file_section *self,
+ int feat, int fd));
+
#endif /* __PERF_HEADER_H */

2009-11-16 21:11:11

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [tip:perf/core] perf tools: Introduce dsos__fprintf_buildid

Commit-ID: 9e03eb2d512e7f3a1e562d4b922aa8b1891750b6
Gitweb: http://git.kernel.org/tip/9e03eb2d512e7f3a1e562d4b922aa8b1891750b6
Author: Arnaldo Carvalho de Melo <[email protected]>
AuthorDate: Mon, 16 Nov 2009 16:32:44 -0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Mon, 16 Nov 2009 22:05:51 +0100

perf tools: Introduce dsos__fprintf_buildid

To print the buildids in the list of dsos. Will be used by 'perf
buildid-list'

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/util/symbol.c | 30 ++++++++++++++++++++++++++----
tools/perf/util/symbol.h | 2 ++
2 files changed, 28 insertions(+), 4 deletions(-)

diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 93e4b52..53de9c4 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -212,14 +212,21 @@ int build_id__sprintf(u8 *self, int len, char *bf)
return raw - self;
}

-size_t dso__fprintf(struct dso *self, FILE *fp)
+size_t dso__fprintf_buildid(struct dso *self, FILE *fp)
{
char sbuild_id[BUILD_ID_SIZE * 2 + 1];
- struct rb_node *nd;
- size_t ret;

build_id__sprintf(self->build_id, sizeof(self->build_id), sbuild_id);
- ret = fprintf(fp, "dso: %s (%s)\n", self->short_name, sbuild_id);
+ return fprintf(fp, "%s", sbuild_id);
+}
+
+size_t dso__fprintf(struct dso *self, FILE *fp)
+{
+ struct rb_node *nd;
+ size_t ret = fprintf(fp, "dso: %s (", self->short_name);
+
+ ret += dso__fprintf_buildid(self, fp);
+ ret += fprintf(fp, ")\n");

for (nd = rb_first(&self->syms); nd; nd = rb_next(nd)) {
struct symbol *pos = rb_entry(nd, struct symbol, rb_node);
@@ -1428,6 +1435,21 @@ void dsos__fprintf(FILE *fp)
dso__fprintf(pos, fp);
}

+size_t dsos__fprintf_buildid(FILE *fp)
+{
+ struct dso *pos;
+ size_t ret = 0;
+
+ list_for_each_entry(pos, &dsos, node) {
+ ret += dso__fprintf_buildid(pos, fp);
+ if (verbose)
+ ret += fprintf(fp, " %s\n", pos->long_name);
+ else
+ ret += fprintf(fp, "\n");
+ }
+ return ret;
+}
+
int load_kernel(symbol_filter_t filter)
{
if (dsos__load_kernel(vmlinux_name, filter, modules) <= 0)
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index 0a34a54..51c5a4a 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -80,7 +80,9 @@ int dsos__load_kernel(const char *vmlinux, symbol_filter_t filter, int modules);
struct dso *dsos__findnew(const char *name);
int dso__load(struct dso *self, struct map *map, symbol_filter_t filter);
void dsos__fprintf(FILE *fp);
+size_t dsos__fprintf_buildid(FILE *fp);

+size_t dso__fprintf_buildid(struct dso *self, FILE *fp);
size_t dso__fprintf(struct dso *self, FILE *fp);
char dso__symtab_origin(const struct dso *self);
void dso__set_build_id(struct dso *self, void *build_id);

2009-11-16 21:12:55

by Arnaldo Carvalho de Melo

[permalink] [raw]
Subject: [tip:perf/core] perf buildid-list: New plumbing command

Commit-ID: c34984b2bbc77596c97c333539bffc90d2033178
Gitweb: http://git.kernel.org/tip/c34984b2bbc77596c97c333539bffc90d2033178
Author: Arnaldo Carvalho de Melo <[email protected]>
AuthorDate: Mon, 16 Nov 2009 16:32:45 -0200
Committer: Ingo Molnar <[email protected]>
CommitDate: Mon, 16 Nov 2009 22:05:51 +0100

perf buildid-list: New plumbing command

With this we can list the buildids in a perf.data file so that
we can pipe them to other, distro specific tools that from the
buildids can figure out separate packages (foo-debuginfo) where
we can find the matching symtabs so that perf report can do its
job.

E.g:

[acme@doppio linux-2.6-tip]$ perf buildid-list | head -5
8e08b117e5458ad3f85da16d42d0fc5cd21c5869
520c2387a587cc5acfcf881e27dba1caaeab4b1f
ec8dd400904ddfcac8b1c343263a790f977159dc
7caedbca5a6d8ab39a7fe44bd28c07d3e14a3f3f
379bb828fd08859dbea73279f04abefabc95a6a3
[acme@doppio linux-2.6-tip]$ perf buildid-list -v | head -5
8e08b117e5458ad3f85da16d42d0fc5cd21c5869 /sbin/init
520c2387a587cc5acfcf881e27dba1caaeab4b1f /lib64/ld-2.10.1.so
ec8dd400904ddfcac8b1c343263a790f977159dc /lib64/libc-2.10.1.so
7caedbca5a6d8ab39a7fe44bd28c07d3e14a3f3f /sbin/udevd
379bb828fd08859dbea73279f04abefabc95a6a3 /lib64/libdl-2.10.1.so
[acme@doppio linux-2.6-tip]$

Signed-off-by: Arnaldo Carvalho de Melo <[email protected]>
Cc: Frederic Weisbecker <[email protected]>
Cc: Mike Galbraith <[email protected]>
Cc: Paul Mackerras <[email protected]>
Cc: Peter Zijlstra <[email protected]>
LKML-Reference: <[email protected]>
Signed-off-by: Ingo Molnar <[email protected]>
---
tools/perf/Documentation/perf-buildid-list.txt | 34 +++++++
tools/perf/Makefile | 1 +
tools/perf/builtin-buildid-list.c | 116 ++++++++++++++++++++++++
tools/perf/builtin.h | 1 +
tools/perf/command-list.txt | 1 +
tools/perf/perf.c | 1 +
6 files changed, 154 insertions(+), 0 deletions(-)

diff --git a/tools/perf/Documentation/perf-buildid-list.txt b/tools/perf/Documentation/perf-buildid-list.txt
new file mode 100644
index 0000000..abab34e
--- /dev/null
+++ b/tools/perf/Documentation/perf-buildid-list.txt
@@ -0,0 +1,34 @@
+perf-buildid-list(1)
+====================
+
+NAME
+----
+perf-buildid-list - List the buildids in a perf.data file
+
+SYNOPSIS
+--------
+[verse]
+'perf buildid-list <options>'
+
+DESCRIPTION
+-----------
+This command displays the buildids found in a perf.data file, so that other
+tools can be used to fetch packages with matching symbol tables for use by
+perf report.
+
+OPTIONS
+-------
+-i::
+--input=::
+ Input file name. (default: perf.data)
+-f::
+--force::
+ Don't do ownership validation.
+-v::
+--verbose::
+ Be more verbose, showing the name of the DSOs after the buildids.
+
+SEE ALSO
+--------
+linkperf:perf-record[1], linkperf:perf-top[1],
+linkperf:perf-report[1]
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index f7cd896..46a58a8 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -430,6 +430,7 @@ BUILTIN_OBJS += bench/sched-pipe.o

BUILTIN_OBJS += builtin-help.o
BUILTIN_OBJS += builtin-sched.o
+BUILTIN_OBJS += builtin-buildid-list.o
BUILTIN_OBJS += builtin-list.o
BUILTIN_OBJS += builtin-record.o
BUILTIN_OBJS += builtin-report.o
diff --git a/tools/perf/builtin-buildid-list.c b/tools/perf/builtin-buildid-list.c
new file mode 100644
index 0000000..2e377e1
--- /dev/null
+++ b/tools/perf/builtin-buildid-list.c
@@ -0,0 +1,116 @@
+/*
+ * builtin-buildid-list.c
+ *
+ * Builtin buildid-list command: list buildids in perf.data
+ *
+ * Copyright (C) 2009, Red Hat Inc.
+ * Copyright (C) 2009, Arnaldo Carvalho de Melo <[email protected]>
+ */
+#include "builtin.h"
+#include "perf.h"
+#include "util/cache.h"
+#include "util/data_map.h"
+#include "util/debug.h"
+#include "util/header.h"
+#include "util/parse-options.h"
+#include "util/symbol.h"
+
+static char const *input_name = "perf.data";
+static int force;
+
+static const char *const buildid_list_usage[] = {
+ "perf report [<options>]",
+ NULL
+};
+
+static const struct option options[] = {
+ OPT_STRING('i', "input", &input_name, "file",
+ "input file name"),
+ OPT_BOOLEAN('f', "force", &force, "don't complain, do it"),
+ OPT_BOOLEAN('v', "verbose", &verbose,
+ "be more verbose (show counter open errors, etc)"),
+ OPT_END()
+};
+
+static int perf_file_section__process_buildids(struct perf_file_section *self,
+ int feat, int fd)
+{
+ if (feat != HEADER_BUILD_ID)
+ return 0;
+
+ if (lseek(fd, self->offset, SEEK_SET) < 0) {
+ pr_warning("Failed to lseek to %Ld offset for buildids!\n",
+ self->offset);
+ return -1;
+ }
+
+ if (perf_header__read_build_ids(fd, self->offset, self->size)) {
+ pr_warning("Failed to read buildids!\n");
+ return -1;
+ }
+
+ return 0;
+}
+
+static int __cmd_buildid_list(void)
+{
+ int err = -1;
+ struct perf_header *header;
+ struct perf_file_header f_header;
+ struct stat input_stat;
+ int input = open(input_name, O_RDONLY);
+
+ if (input < 0) {
+ pr_err("failed to open file: %s", input_name);
+ if (!strcmp(input_name, "perf.data"))
+ pr_err(" (try 'perf record' first)");
+ pr_err("\n");
+ goto out;
+ }
+
+ err = fstat(input, &input_stat);
+ if (err < 0) {
+ perror("failed to stat file");
+ goto out_close;
+ }
+
+ if (!force && input_stat.st_uid && (input_stat.st_uid != geteuid())) {
+ pr_err("file %s not owned by current user or root\n",
+ input_name);
+ goto out_close;
+ }
+
+ if (!input_stat.st_size) {
+ pr_info("zero-sized file, nothing to do!\n");
+ goto out_close;
+ }
+
+ err = -1;
+ header = perf_header__new();
+ if (header == NULL)
+ goto out_close;
+
+ if (perf_file_header__read(&f_header, header, input) < 0) {
+ pr_warning("incompatible file format");
+ goto out_close;
+ }
+
+ err = perf_header__process_sections(header, input,
+ perf_file_section__process_buildids);
+
+ if (err < 0)
+ goto out_close;
+
+ dsos__fprintf_buildid(stdout);
+out_close:
+ close(input);
+out:
+ return err;
+}
+
+int cmd_buildid_list(int argc, const char **argv, const char *prefix __used)
+{
+ argc = parse_options(argc, argv, options, buildid_list_usage, 0);
+ setup_pager();
+ return __cmd_buildid_list();
+}
diff --git a/tools/perf/builtin.h b/tools/perf/builtin.h
index f0cd5b1..e97954a 100644
--- a/tools/perf/builtin.h
+++ b/tools/perf/builtin.h
@@ -16,6 +16,7 @@ extern int check_pager_config(const char *cmd);

extern int cmd_annotate(int argc, const char **argv, const char *prefix);
extern int cmd_bench(int argc, const char **argv, const char *prefix);
+extern int cmd_buildid_list(int argc, const char **argv, const char *prefix);
extern int cmd_help(int argc, const char **argv, const char *prefix);
extern int cmd_sched(int argc, const char **argv, const char *prefix);
extern int cmd_list(int argc, const char **argv, const char *prefix);
diff --git a/tools/perf/command-list.txt b/tools/perf/command-list.txt
index 981c40b..d37b16c 100644
--- a/tools/perf/command-list.txt
+++ b/tools/perf/command-list.txt
@@ -4,6 +4,7 @@
#
perf-annotate mainporcelain common
perf-bench mainporcelain common
+perf-buildid-list mainporcelain common
perf-list mainporcelain common
perf-sched mainporcelain common
perf-record mainporcelain common
diff --git a/tools/perf/perf.c b/tools/perf/perf.c
index 8936786..53359eb 100644
--- a/tools/perf/perf.c
+++ b/tools/perf/perf.c
@@ -287,6 +287,7 @@ static void handle_internal_command(int argc, const char **argv)
static struct cmd_struct commands[] = {
{ "help", cmd_help, 0 },
{ "list", cmd_list, 0 },
+ { "buildid-list", cmd_buildid_list, 0 },
{ "record", cmd_record, 0 },
{ "report", cmd_report, 0 },
{ "bench", cmd_bench, 0 },