aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-11-10 22:51:04 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-11 01:30:18 -0500
commit57f395a7eabb913d3605d7392be5bdb0837c9f3d (patch)
tree141135524cbdb9fa27b48f361443a91b10726f7d
parent8671dab9d5b2f0b444b8d09792384dccbfd43d14 (diff)
perf tools: Split up build id saving into fetch and write
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>
-rw-r--r--tools/perf/util/event.h7
-rw-r--r--tools/perf/util/header.c41
-rw-r--r--tools/perf/util/symbol.c34
-rw-r--r--tools/perf/util/symbol.h1
4 files changed, 59 insertions, 24 deletions
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index 34c6fcb82d92..1f771ce3a957 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -69,6 +69,13 @@ struct build_id_event {
69 char filename[]; 69 char filename[];
70}; 70};
71 71
72struct build_id_list {
73 struct build_id_event event;
74 struct list_head list;
75 const char *dso_name;
76 int len;
77};
78
72typedef union event_union { 79typedef union event_union {
73 struct perf_event_header header; 80 struct perf_event_header header;
74 struct ip_event ip; 81 struct ip_event ip;
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index a4d0bbef9a43..2f702c23f71a 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -174,29 +174,18 @@ static void do_write(int fd, void *buf, size_t size)
174 } 174 }
175} 175}
176 176
177static bool write_buildid_table(int fd) 177static void write_buildid_table(int fd, struct list_head *id_head)
178{ 178{
179 struct dso *pos; 179 struct build_id_list *iter, *next;
180 bool have_buildid = false; 180
181 181 list_for_each_entry_safe(iter, next, id_head, list) {
182 list_for_each_entry(pos, &dsos, node) { 182 struct build_id_event *b = &iter->event;
183 struct build_id_event b;
184 size_t len;
185
186 if (filename__read_build_id(pos->long_name,
187 &b.build_id,
188 sizeof(b.build_id)) < 0)
189 continue;
190 have_buildid = true;
191 memset(&b.header, 0, sizeof(b.header));
192 len = strlen(pos->long_name) + 1;
193 len = ALIGN(len, 64);
194 b.header.size = sizeof(b) + len;
195 do_write(fd, &b, sizeof(b));
196 do_write(fd, pos->long_name, len);
197 }
198 183
199 return have_buildid; 184 do_write(fd, b, sizeof(*b));
185 do_write(fd, (void *)iter->dso_name, iter->len);
186 list_del(&iter->list);
187 free(iter);
188 }
200} 189}
201 190
202static void 191static void
@@ -226,10 +215,14 @@ perf_header__adds_write(struct perf_header *self, int fd, bool at_exit)
226 } 215 }
227 216
228 if (at_exit) { 217 if (at_exit) {
229 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 218 LIST_HEAD(id_list);
230 if (write_buildid_table(fd)) 219
220 if (fetch_build_id_table(&id_list)) {
221 lseek(fd, self->data_offset + self->data_size, SEEK_SET);
231 perf_header__set_feat(self, HEADER_BUILD_ID); 222 perf_header__set_feat(self, HEADER_BUILD_ID);
232 lseek(fd, cur_offset, SEEK_SET); 223 write_buildid_table(fd, &id_list);
224 lseek(fd, cur_offset, SEEK_SET);
225 }
233 } 226 }
234}; 227};
235 228
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index a2e95ce1f223..9c286db62003 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -851,6 +851,40 @@ out_close:
851 return err; 851 return err;
852} 852}
853 853
854bool fetch_build_id_table(struct list_head *head)
855{
856 bool have_buildid = false;
857 struct dso *pos;
858
859 list_for_each_entry(pos, &dsos, node) {
860 struct build_id_list *new;
861 struct build_id_event b;
862 size_t len;
863
864 if (filename__read_build_id(pos->long_name,
865 &b.build_id,
866 sizeof(b.build_id)) < 0)
867 continue;
868 have_buildid = true;
869 memset(&b.header, 0, sizeof(b.header));
870 len = strlen(pos->long_name) + 1;
871 len = ALIGN(len, 64);
872 b.header.size = sizeof(b) + len;
873
874 new = malloc(sizeof(*new));
875 if (!new)
876 die("No memory\n");
877
878 memcpy(&new->event, &b, sizeof(b));
879 new->dso_name = pos->long_name;
880 new->len = len;
881
882 list_add_tail(&new->list, head);
883 }
884
885 return have_buildid;
886}
887
854int filename__read_build_id(const char *filename, void *bf, size_t size) 888int filename__read_build_id(const char *filename, void *bf, size_t size)
855{ 889{
856 int fd, err = -1; 890 int fd, err = -1;
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index f8c1899af483..0a34a5493f1b 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -86,6 +86,7 @@ char dso__symtab_origin(const struct dso *self);
86void dso__set_build_id(struct dso *self, void *build_id); 86void dso__set_build_id(struct dso *self, void *build_id);
87 87
88int filename__read_build_id(const char *filename, void *bf, size_t size); 88int filename__read_build_id(const char *filename, void *bf, size_t size);
89bool fetch_build_id_table(struct list_head *head);
89int build_id__sprintf(u8 *self, int len, char *bf); 90int build_id__sprintf(u8 *self, int len, char *bf);
90 91
91int load_kernel(symbol_filter_t filter); 92int load_kernel(symbol_filter_t filter);