aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorFrederic Weisbecker <fweisbec@gmail.com>2009-11-10 22:51:07 -0500
committerIngo Molnar <mingo@elte.hu>2009-11-11 01:30:19 -0500
commit9e827dd00a94136b944a538bede67c944d0b740a (patch)
tree216a995921b8741461667bfdce8acc595a99685f /tools/perf
parent3e13ab2d83b6867a20663c73c184f29c2fde1558 (diff)
perf tools: Bring linear set of section headers for features
Build a set of section headers for features right after the datas. Each implemented feature will have one of such section header that provides the offset and the size of the data manipulated by the feature. The trace informations have moved after the data and are recorded on exit time. The new layout is as follows: ----------------------- ___ [ magic ] | [ header size ] | [ attr size ] | [ attr content offset ] | [ attr content size ] | [ data offset ] File Headers [ data size ] | [ event_types offset ] | [ event_types size ] | [ feature bitmap ] v [ attr section ] [ events section ] ___ [ X ] | [ X ] | [ X ] Datas [ X ] | [ X ] v ___ [ Feature 1 offset ] | [ Feature 1 size ] Features headers [ Feature 2 offset ] | [ Feature 2 size ] v [ Feature 1 content ] [ Feature 2 content ] ----------------------- We have as many feature's section headers as we have features in use for the current file. Say Feat 1 and Feat 3 are used by the file, but not Feat 2. Then the feature headers will be like follows: [ Feature 1 offset ] | [ Feature 1 size ] Features headers [ Feature 3 offset ] | [ Feature 3 size ] v There is no hole to cover Feature 2 that is not in use here. We only need to cover the needed headers in order, from the lowest feature bit to the highest. Currently we have two features: HEADER_TRACE_INFO and HEADER_BUILD_ID. Both have their contents that follow the feature headers. Putting the contents right after the feature headers is not mandatory though. While we keep the feature headers right after the data and in order, their offsets can point everywhere. We have just put the two above feature contents in the end of the file for convenience. The purpose of this layout change is to have a file format that scales while keeping it simple: having such linear feature headers is less error prone wrt forward/backward compatibility as the content of a feature can be put anywhere, its location can even change by the time, it's fine because its headers will tell where it is. And we know how to find these headers, following the above rules. 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-6-git-send-email-fweisbec@gmail.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/util/data_map.c11
-rw-r--r--tools/perf/util/data_map.h3
-rw-r--r--tools/perf/util/header.c110
-rw-r--r--tools/perf/util/include/linux/bitmap.h1
-rw-r--r--tools/perf/util/include/linux/ctype.h2
-rw-r--r--tools/perf/util/util.h3
6 files changed, 85 insertions, 45 deletions
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c
index 66e58aaecce3..aacb814a4eff 100644
--- a/tools/perf/util/data_map.c
+++ b/tools/perf/util/data_map.c
@@ -70,18 +70,15 @@ process_event(event_t *event, unsigned long offset, unsigned long head)
70 } 70 }
71} 71}
72 72
73int perf_header__read_build_ids(const struct perf_header *self, 73int perf_header__read_build_ids(int input, off_t size)
74 int input, off_t file_size)
75{ 74{
76 off_t offset = self->data_offset + self->data_size;
77 struct build_id_event bev; 75 struct build_id_event bev;
78 char filename[PATH_MAX]; 76 char filename[PATH_MAX];
77 off_t offset = lseek(input, 0, SEEK_CUR);
78 off_t limit = offset + size;
79 int err = -1; 79 int err = -1;
80 80
81 if (lseek(input, offset, SEEK_SET) < 0) 81 while (offset < limit) {
82 return -1;
83
84 while (offset < file_size) {
85 struct dso *dso; 82 struct dso *dso;
86 ssize_t len; 83 ssize_t len;
87 84
diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h
index c4122810e489..20b4037a8236 100644
--- a/tools/perf/util/data_map.h
+++ b/tools/perf/util/data_map.h
@@ -27,7 +27,6 @@ int mmap_dispatch_perf_file(struct perf_header **pheader,
27 int full_paths, 27 int full_paths,
28 int *cwdlen, 28 int *cwdlen,
29 char **cwd); 29 char **cwd);
30int perf_header__read_build_ids(const struct perf_header *self, 30int perf_header__read_build_ids(int input, off_t file_size);
31 int input, off_t file_size);
32 31
33#endif 32#endif
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 9709d38113b1..ebed4f44ed36 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -186,41 +186,58 @@ static void write_buildid_table(int fd, struct list_head *id_head)
186} 186}
187 187
188static void 188static void
189perf_header__adds_write(struct perf_header *self, int fd, bool at_exit) 189perf_header__adds_write(struct perf_header *self, int fd)
190{ 190{
191 struct perf_file_section trace_sec; 191 LIST_HEAD(id_list);
192 u64 cur_offset = lseek(fd, 0, SEEK_CUR); 192 int nr_sections;
193 struct perf_file_section *feat_sec;
194 int sec_size;
195 u64 sec_start;
196 int idx = 0;
197
198 if (fetch_build_id_table(&id_list))
199 perf_header__set_feat(self, HEADER_BUILD_ID);
200
201 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
202 if (!nr_sections)
203 return;
204
205 feat_sec = calloc(sizeof(*feat_sec), nr_sections);
206 if (!feat_sec)
207 die("No memory");
208
209 sec_size = sizeof(*feat_sec) * nr_sections;
210
211 sec_start = self->data_offset + self->data_size;
212 lseek(fd, sec_start + sec_size, SEEK_SET);
193 213
194 if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { 214 if (perf_header__has_feat(self, HEADER_TRACE_INFO)) {
215 struct perf_file_section *trace_sec;
216
217 trace_sec = &feat_sec[idx++];
218
195 /* Write trace info */ 219 /* Write trace info */
196 trace_sec.offset = lseek(fd, sizeof(trace_sec), SEEK_CUR); 220 trace_sec->offset = lseek(fd, 0, SEEK_CUR);
197 read_tracing_data(fd, attrs, nr_counters); 221 read_tracing_data(fd, attrs, nr_counters);
198 trace_sec.size = lseek(fd, 0, SEEK_CUR) - trace_sec.offset; 222 trace_sec->size = lseek(fd, 0, SEEK_CUR) - trace_sec->offset;
199
200 /* Write trace info headers */
201 lseek(fd, cur_offset, SEEK_SET);
202 do_write(fd, &trace_sec, sizeof(trace_sec));
203
204 /*
205 * Update cur_offset. So that other (future)
206 * features can set their own infos in this place. But if we are
207 * the only feature, at least that seeks to the place the data
208 * should begin.
209 */
210 cur_offset = lseek(fd, trace_sec.offset + trace_sec.size, SEEK_SET);
211 } 223 }
212 224
213 if (at_exit) {
214 LIST_HEAD(id_list);
215 225
216 if (fetch_build_id_table(&id_list)) { 226 if (perf_header__has_feat(self, HEADER_BUILD_ID)) {
217 lseek(fd, self->data_offset + self->data_size, SEEK_SET); 227 struct perf_file_section *buildid_sec;
218 perf_header__set_feat(self, HEADER_BUILD_ID); 228
219 write_buildid_table(fd, &id_list); 229 buildid_sec = &feat_sec[idx++];
220 lseek(fd, cur_offset, SEEK_SET); 230
221 } 231 /* Write build-ids */
232 buildid_sec->offset = lseek(fd, 0, SEEK_CUR);
233 write_buildid_table(fd, &id_list);
234 buildid_sec->size = lseek(fd, 0, SEEK_CUR) - buildid_sec->offset;
222 } 235 }
223}; 236
237 lseek(fd, sec_start, SEEK_SET);
238 do_write(fd, feat_sec, sec_size);
239 free(feat_sec);
240}
224 241
225void perf_header__write(struct perf_header *self, int fd, bool at_exit) 242void perf_header__write(struct perf_header *self, int fd, bool at_exit)
226{ 243{
@@ -260,10 +277,11 @@ void perf_header__write(struct perf_header *self, int fd, bool at_exit)
260 if (events) 277 if (events)
261 do_write(fd, events, self->event_size); 278 do_write(fd, events, self->event_size);
262 279
263 perf_header__adds_write(self, fd, at_exit);
264
265 self->data_offset = lseek(fd, 0, SEEK_CUR); 280 self->data_offset = lseek(fd, 0, SEEK_CUR);
266 281
282 if (at_exit)
283 perf_header__adds_write(self, fd);
284
267 f_header = (struct perf_file_header){ 285 f_header = (struct perf_file_header){
268 .magic = PERF_MAGIC, 286 .magic = PERF_MAGIC,
269 .size = sizeof(f_header), 287 .size = sizeof(f_header),
@@ -308,22 +326,44 @@ static void do_read(int fd, void *buf, size_t size)
308 326
309static void perf_header__adds_read(struct perf_header *self, int fd) 327static void perf_header__adds_read(struct perf_header *self, int fd)
310{ 328{
329 struct perf_file_section *feat_sec;
330 int nr_sections;
331 int sec_size;
332 int idx = 0;
333
334
335 nr_sections = bitmap_weight(self->adds_features, HEADER_FEAT_BITS);
336 if (!nr_sections)
337 return;
338
339 feat_sec = calloc(sizeof(*feat_sec), nr_sections);
340 if (!feat_sec)
341 die("No memory");
342
343 sec_size = sizeof(*feat_sec) * nr_sections;
344
345 lseek(fd, self->data_offset + self->data_size, SEEK_SET);
346
347 do_read(fd, feat_sec, sec_size);
348
311 if (perf_header__has_feat(self, HEADER_TRACE_INFO)) { 349 if (perf_header__has_feat(self, HEADER_TRACE_INFO)) {
312 struct perf_file_section trace_sec; 350 struct perf_file_section *trace_sec;
313 351
314 do_read(fd, &trace_sec, sizeof(trace_sec)); 352 trace_sec = &feat_sec[idx++];
315 lseek(fd, trace_sec.offset, SEEK_SET); 353 lseek(fd, trace_sec->offset, SEEK_SET);
316 trace_report(fd); 354 trace_report(fd);
317 lseek(fd, trace_sec.offset + trace_sec.size, SEEK_SET);
318 } 355 }
319 356
320 if (perf_header__has_feat(self, HEADER_BUILD_ID)) { 357 if (perf_header__has_feat(self, HEADER_BUILD_ID)) {
321 struct stat input_stat; 358 struct perf_file_section *buildid_sec;
322 359
323 fstat(fd, &input_stat); 360 buildid_sec = &feat_sec[idx++];
324 if (perf_header__read_build_ids(self, fd, input_stat.st_size)) 361 lseek(fd, buildid_sec->offset, SEEK_SET);
362 if (perf_header__read_build_ids(fd, buildid_sec->size))
325 pr_debug("failed to read buildids, continuing...\n"); 363 pr_debug("failed to read buildids, continuing...\n");
326 } 364 }
365
366 free(feat_sec);
327}; 367};
328 368
329struct perf_header *perf_header__read(int fd) 369struct perf_header *perf_header__read(int fd)
diff --git a/tools/perf/util/include/linux/bitmap.h b/tools/perf/util/include/linux/bitmap.h
index 821c1033bccf..94507639a8c4 100644
--- a/tools/perf/util/include/linux/bitmap.h
+++ b/tools/perf/util/include/linux/bitmap.h
@@ -1,2 +1,3 @@
1#include "../../../../include/linux/bitmap.h" 1#include "../../../../include/linux/bitmap.h"
2#include "../../../../include/asm-generic/bitops/find.h" 2#include "../../../../include/asm-generic/bitops/find.h"
3#include <linux/errno.h>
diff --git a/tools/perf/util/include/linux/ctype.h b/tools/perf/util/include/linux/ctype.h
index bae5783282ef..a53d4ee1e0b7 100644
--- a/tools/perf/util/include/linux/ctype.h
+++ b/tools/perf/util/include/linux/ctype.h
@@ -1 +1 @@
#include "../../../../include/linux/ctype.h" #include "../util.h"
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h
index 9de2329dd44d..7bd5bdaeb235 100644
--- a/tools/perf/util/util.h
+++ b/tools/perf/util/util.h
@@ -306,6 +306,7 @@ static inline int has_extension(const char *filename, const char *ext)
306#undef isascii 306#undef isascii
307#undef isspace 307#undef isspace
308#undef isdigit 308#undef isdigit
309#undef isxdigit
309#undef isalpha 310#undef isalpha
310#undef isprint 311#undef isprint
311#undef isalnum 312#undef isalnum
@@ -323,6 +324,8 @@ extern unsigned char sane_ctype[256];
323#define isascii(x) (((x) & ~0x7f) == 0) 324#define isascii(x) (((x) & ~0x7f) == 0)
324#define isspace(x) sane_istest(x,GIT_SPACE) 325#define isspace(x) sane_istest(x,GIT_SPACE)
325#define isdigit(x) sane_istest(x,GIT_DIGIT) 326#define isdigit(x) sane_istest(x,GIT_DIGIT)
327#define isxdigit(x) \
328 (sane_istest(toupper(x), GIT_ALPHA | GIT_DIGIT) && toupper(x) < 'G')
326#define isalpha(x) sane_istest(x,GIT_ALPHA) 329#define isalpha(x) sane_istest(x,GIT_ALPHA)
327#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT) 330#define isalnum(x) sane_istest(x,GIT_ALPHA | GIT_DIGIT)
328#define isprint(x) sane_istest(x,GIT_PRINT) 331#define isprint(x) sane_istest(x,GIT_PRINT)