perf tools: Split up build id saving into fetch and write
authorFrederic Weisbecker <fweisbec@gmail.com>
Wed, 11 Nov 2009 03:51:04 +0000 (04:51 +0100)
committerIngo Molnar <mingo@elte.hu>
Wed, 11 Nov 2009 06:30:18 +0000 (07:30 +0100)
We are saving the build id once we stop the profiling. And only
after doing that we know if we need to set that feature in the
header through the feature bitmap.

But if we want a proper feature support in the headers, using a
rule of offset/size pairs in sections, we need to know in
advance how many features we need to set in the headers, so that
we can reserve rooms for their section headers.

The current state doesn't allow that, as it forces us to first
save the build-ids to the file right after the datas instead of
planning any structured layout.

That's why this splits up the build-ids processing in two parts:
one that fetches the build-ids from the Dso objects, and one
that saves them into the file.

Signed-off-by: Frederic Weisbecker <fweisbec@gmail.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Hitoshi Mitake <mitake@dcl.info.waseda.ac.jp>
LKML-Reference: <1257911467-28276-3-git-send-email-fweisbec@gmail.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
tools/perf/util/event.h
tools/perf/util/header.c
tools/perf/util/symbol.c
tools/perf/util/symbol.h

index 34c6fcb82d927757058f249982e3215ca962e8d4..1f771ce3a95793c29abf14106e91408d86f319d6 100644 (file)
@@ -69,6 +69,13 @@ struct build_id_event {
        char                     filename[];
 };
 
+struct build_id_list {
+       struct build_id_event   event;
+       struct list_head        list;
+       const char              *dso_name;
+       int                     len;
+};
+
 typedef union event_union {
        struct perf_event_header        header;
        struct ip_event                 ip;
index a4d0bbef9a4394d62497ccf29dc36e8b7e6bacef..2f702c23f71ac5f48eb28d88922133b493328bd2 100644 (file)
@@ -174,29 +174,18 @@ static void do_write(int fd, void *buf, size_t size)
        }
 }
 
-static bool write_buildid_table(int fd)
+static void write_buildid_table(int fd, struct list_head *id_head)
 {
-       struct dso *pos;
-       bool have_buildid = false;
-
-       list_for_each_entry(pos, &dsos, node) {
-               struct build_id_event b;
-               size_t len;
-
-               if (filename__read_build_id(pos->long_name,
-                                           &b.build_id,
-                                           sizeof(b.build_id)) < 0)
-                       continue;
-               have_buildid = true;
-               memset(&b.header, 0, sizeof(b.header));
-               len = strlen(pos->long_name) + 1;
-               len = ALIGN(len, 64);
-               b.header.size = sizeof(b) + len;
-               do_write(fd, &b, sizeof(b));
-               do_write(fd, pos->long_name, len);
-       }
+       struct build_id_list *iter, *next;
+
+       list_for_each_entry_safe(iter, next, id_head, list) {
+               struct build_id_event *b = &iter->event;
 
-       return have_buildid;
+               do_write(fd, b, sizeof(*b));
+               do_write(fd, (void *)iter->dso_name, iter->len);
+               list_del(&iter->list);
+               free(iter);
+       }
 }
 
 static void
@@ -226,10 +215,14 @@ perf_header__adds_write(struct perf_header *self, int fd, bool at_exit)
        }
 
        if (at_exit) {
-               lseek(fd, self->data_offset + self->data_size, SEEK_SET);
-               if (write_buildid_table(fd))
+               LIST_HEAD(id_list);
+
+               if (fetch_build_id_table(&id_list)) {
+                       lseek(fd, self->data_offset + self->data_size, SEEK_SET);
                        perf_header__set_feat(self, HEADER_BUILD_ID);
-               lseek(fd, cur_offset, SEEK_SET);
+                       write_buildid_table(fd, &id_list);
+                       lseek(fd, cur_offset, SEEK_SET);
+               }
        }
 };
 
index a2e95ce1f223c26da40e21c730d6cc9192c789e6..9c286db6200357533855c42e44a104d8b7fa2b3c 100644 (file)
@@ -851,6 +851,40 @@ out_close:
        return err;
 }
 
+bool fetch_build_id_table(struct list_head *head)
+{
+       bool have_buildid = false;
+       struct dso *pos;
+
+       list_for_each_entry(pos, &dsos, node) {
+               struct build_id_list *new;
+               struct build_id_event b;
+               size_t len;
+
+               if (filename__read_build_id(pos->long_name,
+                                           &b.build_id,
+                                           sizeof(b.build_id)) < 0)
+                       continue;
+               have_buildid = true;
+               memset(&b.header, 0, sizeof(b.header));
+               len = strlen(pos->long_name) + 1;
+               len = ALIGN(len, 64);
+               b.header.size = sizeof(b) + len;
+
+               new = malloc(sizeof(*new));
+               if (!new)
+                       die("No memory\n");
+
+               memcpy(&new->event, &b, sizeof(b));
+               new->dso_name = pos->long_name;
+               new->len = len;
+
+               list_add_tail(&new->list, head);
+       }
+
+       return have_buildid;
+}
+
 int filename__read_build_id(const char *filename, void *bf, size_t size)
 {
        int fd, err = -1;
index f8c1899af4835c7f373b5f39549a5c16a6ddb87b..0a34a5493f1bf98a2e4044f410ef8a7fb68078f5 100644 (file)
@@ -86,6 +86,7 @@ char dso__symtab_origin(const struct dso *self);
 void dso__set_build_id(struct dso *self, void *build_id);
 
 int filename__read_build_id(const char *filename, void *bf, size_t size);
+bool fetch_build_id_table(struct list_head *head);
 int build_id__sprintf(u8 *self, int len, char *bf);
 
 int load_kernel(symbol_filter_t filter);