diff options
author | Ingo Molnar <mingo@elte.hu> | 2009-12-14 03:16:49 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-12-14 03:16:49 -0500 |
commit | cc0104e877fff32865a67b256d3a9ce52ff15790 (patch) | |
tree | 18779442274e81607822ecb0905c55ac4ce6a163 /tools/perf/util | |
parent | 16620e0f1990fa6d896a639449c4b3d678458464 (diff) | |
parent | f40542532e96dda5506eb76badea322f2ae4731c (diff) |
Merge branch 'linus' into tracing/urgent
Conflicts:
kernel/trace/trace_kprobe.c
Merge reason: resolve the conflict.
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf/util')
-rw-r--r-- | tools/perf/util/data_map.c | 4 | ||||
-rw-r--r-- | tools/perf/util/data_map.h | 2 | ||||
-rw-r--r-- | tools/perf/util/event.c | 67 | ||||
-rw-r--r-- | tools/perf/util/event.h | 17 | ||||
-rw-r--r-- | tools/perf/util/header.c | 9 | ||||
-rw-r--r-- | tools/perf/util/parse-events.c | 17 | ||||
-rw-r--r-- | tools/perf/util/parse-options.c | 3 | ||||
-rw-r--r-- | tools/perf/util/probe-event.c | 133 | ||||
-rw-r--r-- | tools/perf/util/probe-event.h | 1 | ||||
-rw-r--r-- | tools/perf/util/probe-finder.c | 2 | ||||
-rw-r--r-- | tools/perf/util/symbol.c | 5 | ||||
-rw-r--r-- | tools/perf/util/trace-event-parse.c | 4 | ||||
-rw-r--r-- | tools/perf/util/trace-event-perl.c | 67 | ||||
-rw-r--r-- | tools/perf/util/trace-event-perl.h | 4 | ||||
-rw-r--r-- | tools/perf/util/trace-event-read.c | 3 |
15 files changed, 286 insertions, 52 deletions
diff --git a/tools/perf/util/data_map.c b/tools/perf/util/data_map.c index ca0bedf637c2..59b65d0bd7c1 100644 --- a/tools/perf/util/data_map.c +++ b/tools/perf/util/data_map.c | |||
@@ -100,11 +100,11 @@ process_event(event_t *event, unsigned long offset, unsigned long head) | |||
100 | } | 100 | } |
101 | } | 101 | } |
102 | 102 | ||
103 | int perf_header__read_build_ids(int input, off_t offset, off_t size) | 103 | int perf_header__read_build_ids(int input, u64 offset, u64 size) |
104 | { | 104 | { |
105 | struct build_id_event bev; | 105 | struct build_id_event bev; |
106 | char filename[PATH_MAX]; | 106 | char filename[PATH_MAX]; |
107 | off_t limit = offset + size; | 107 | u64 limit = offset + size; |
108 | int err = -1; | 108 | int err = -1; |
109 | 109 | ||
110 | while (offset < limit) { | 110 | while (offset < limit) { |
diff --git a/tools/perf/util/data_map.h b/tools/perf/util/data_map.h index 3180ff7e3633..258a87bcc4fb 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, | |||
27 | int full_paths, | 27 | int full_paths, |
28 | int *cwdlen, | 28 | int *cwdlen, |
29 | char **cwd); | 29 | char **cwd); |
30 | int perf_header__read_build_ids(int input, off_t offset, off_t file_size); | 30 | int perf_header__read_build_ids(int input, u64 offset, u64 file_size); |
31 | 31 | ||
32 | #endif | 32 | #endif |
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c index 414b89d1bde9..4dcecafa85dc 100644 --- a/tools/perf/util/event.c +++ b/tools/perf/util/event.c | |||
@@ -310,3 +310,70 @@ int event__preprocess_sample(const event_t *self, struct addr_location *al, | |||
310 | al->level == 'H' ? "[hypervisor]" : "<not found>"); | 310 | al->level == 'H' ? "[hypervisor]" : "<not found>"); |
311 | return 0; | 311 | return 0; |
312 | } | 312 | } |
313 | |||
314 | int event__parse_sample(event_t *event, u64 type, struct sample_data *data) | ||
315 | { | ||
316 | u64 *array = event->sample.array; | ||
317 | |||
318 | if (type & PERF_SAMPLE_IP) { | ||
319 | data->ip = event->ip.ip; | ||
320 | array++; | ||
321 | } | ||
322 | |||
323 | if (type & PERF_SAMPLE_TID) { | ||
324 | u32 *p = (u32 *)array; | ||
325 | data->pid = p[0]; | ||
326 | data->tid = p[1]; | ||
327 | array++; | ||
328 | } | ||
329 | |||
330 | if (type & PERF_SAMPLE_TIME) { | ||
331 | data->time = *array; | ||
332 | array++; | ||
333 | } | ||
334 | |||
335 | if (type & PERF_SAMPLE_ADDR) { | ||
336 | data->addr = *array; | ||
337 | array++; | ||
338 | } | ||
339 | |||
340 | if (type & PERF_SAMPLE_ID) { | ||
341 | data->id = *array; | ||
342 | array++; | ||
343 | } | ||
344 | |||
345 | if (type & PERF_SAMPLE_STREAM_ID) { | ||
346 | data->stream_id = *array; | ||
347 | array++; | ||
348 | } | ||
349 | |||
350 | if (type & PERF_SAMPLE_CPU) { | ||
351 | u32 *p = (u32 *)array; | ||
352 | data->cpu = *p; | ||
353 | array++; | ||
354 | } | ||
355 | |||
356 | if (type & PERF_SAMPLE_PERIOD) { | ||
357 | data->period = *array; | ||
358 | array++; | ||
359 | } | ||
360 | |||
361 | if (type & PERF_SAMPLE_READ) { | ||
362 | pr_debug("PERF_SAMPLE_READ is unsuported for now\n"); | ||
363 | return -1; | ||
364 | } | ||
365 | |||
366 | if (type & PERF_SAMPLE_CALLCHAIN) { | ||
367 | data->callchain = (struct ip_callchain *)array; | ||
368 | array += 1 + data->callchain->nr; | ||
369 | } | ||
370 | |||
371 | if (type & PERF_SAMPLE_RAW) { | ||
372 | u32 *p = (u32 *)array; | ||
373 | data->raw_size = *p; | ||
374 | p++; | ||
375 | data->raw_data = p; | ||
376 | } | ||
377 | |||
378 | return 0; | ||
379 | } | ||
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index a4cc8105cf67..c7a78eef8e52 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -56,11 +56,25 @@ struct read_event { | |||
56 | u64 id; | 56 | u64 id; |
57 | }; | 57 | }; |
58 | 58 | ||
59 | struct sample_event{ | 59 | struct sample_event { |
60 | struct perf_event_header header; | 60 | struct perf_event_header header; |
61 | u64 array[]; | 61 | u64 array[]; |
62 | }; | 62 | }; |
63 | 63 | ||
64 | struct sample_data { | ||
65 | u64 ip; | ||
66 | u32 pid, tid; | ||
67 | u64 time; | ||
68 | u64 addr; | ||
69 | u64 id; | ||
70 | u64 stream_id; | ||
71 | u32 cpu; | ||
72 | u64 period; | ||
73 | struct ip_callchain *callchain; | ||
74 | u32 raw_size; | ||
75 | void *raw_data; | ||
76 | }; | ||
77 | |||
64 | #define BUILD_ID_SIZE 20 | 78 | #define BUILD_ID_SIZE 20 |
65 | 79 | ||
66 | struct build_id_event { | 80 | struct build_id_event { |
@@ -155,5 +169,6 @@ int event__process_task(event_t *self); | |||
155 | struct addr_location; | 169 | struct addr_location; |
156 | int event__preprocess_sample(const event_t *self, struct addr_location *al, | 170 | int event__preprocess_sample(const event_t *self, struct addr_location *al, |
157 | symbol_filter_t filter); | 171 | symbol_filter_t filter); |
172 | int event__parse_sample(event_t *event, u64 type, struct sample_data *data); | ||
158 | 173 | ||
159 | #endif /* __PERF_RECORD_H */ | 174 | #endif /* __PERF_RECORD_H */ |
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c index 4805e6dfd23c..59a9c0b3033e 100644 --- a/tools/perf/util/header.c +++ b/tools/perf/util/header.c | |||
@@ -187,7 +187,9 @@ static int do_write(int fd, const void *buf, size_t size) | |||
187 | 187 | ||
188 | static int __dsos__write_buildid_table(struct list_head *head, int fd) | 188 | static int __dsos__write_buildid_table(struct list_head *head, int fd) |
189 | { | 189 | { |
190 | #define NAME_ALIGN 64 | ||
190 | struct dso *pos; | 191 | struct dso *pos; |
192 | static const char zero_buf[NAME_ALIGN]; | ||
191 | 193 | ||
192 | list_for_each_entry(pos, head, node) { | 194 | list_for_each_entry(pos, head, node) { |
193 | int err; | 195 | int err; |
@@ -197,14 +199,17 @@ static int __dsos__write_buildid_table(struct list_head *head, int fd) | |||
197 | if (!pos->has_build_id) | 199 | if (!pos->has_build_id) |
198 | continue; | 200 | continue; |
199 | len = pos->long_name_len + 1; | 201 | len = pos->long_name_len + 1; |
200 | len = ALIGN(len, 64); | 202 | len = ALIGN(len, NAME_ALIGN); |
201 | memset(&b, 0, sizeof(b)); | 203 | memset(&b, 0, sizeof(b)); |
202 | memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); | 204 | memcpy(&b.build_id, pos->build_id, sizeof(pos->build_id)); |
203 | b.header.size = sizeof(b) + len; | 205 | b.header.size = sizeof(b) + len; |
204 | err = do_write(fd, &b, sizeof(b)); | 206 | err = do_write(fd, &b, sizeof(b)); |
205 | if (err < 0) | 207 | if (err < 0) |
206 | return err; | 208 | return err; |
207 | err = do_write(fd, pos->long_name, len); | 209 | err = do_write(fd, pos->long_name, pos->long_name_len + 1); |
210 | if (err < 0) | ||
211 | return err; | ||
212 | err = do_write(fd, zero_buf, len - pos->long_name_len - 1); | ||
208 | if (err < 0) | 213 | if (err < 0) |
209 | return err; | 214 | return err; |
210 | } | 215 | } |
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c index 9e5dbd66d34d..e5bc0fb016b2 100644 --- a/tools/perf/util/parse-events.c +++ b/tools/perf/util/parse-events.c | |||
@@ -197,7 +197,7 @@ struct tracepoint_path *tracepoint_id_to_path(u64 config) | |||
197 | if (id == config) { | 197 | if (id == config) { |
198 | closedir(evt_dir); | 198 | closedir(evt_dir); |
199 | closedir(sys_dir); | 199 | closedir(sys_dir); |
200 | path = zalloc(sizeof(path)); | 200 | path = zalloc(sizeof(*path)); |
201 | path->system = malloc(MAX_EVENT_LENGTH); | 201 | path->system = malloc(MAX_EVENT_LENGTH); |
202 | if (!path->system) { | 202 | if (!path->system) { |
203 | free(path); | 203 | free(path); |
@@ -467,7 +467,6 @@ parse_subsystem_tracepoint_event(char *sys_name, char *flags) | |||
467 | while ((evt_ent = readdir(evt_dir))) { | 467 | while ((evt_ent = readdir(evt_dir))) { |
468 | char event_opt[MAX_EVOPT_LEN + 1]; | 468 | char event_opt[MAX_EVOPT_LEN + 1]; |
469 | int len; | 469 | int len; |
470 | unsigned int rem = MAX_EVOPT_LEN; | ||
471 | 470 | ||
472 | if (!strcmp(evt_ent->d_name, ".") | 471 | if (!strcmp(evt_ent->d_name, ".") |
473 | || !strcmp(evt_ent->d_name, "..") | 472 | || !strcmp(evt_ent->d_name, "..") |
@@ -475,20 +474,12 @@ parse_subsystem_tracepoint_event(char *sys_name, char *flags) | |||
475 | || !strcmp(evt_ent->d_name, "filter")) | 474 | || !strcmp(evt_ent->d_name, "filter")) |
476 | continue; | 475 | continue; |
477 | 476 | ||
478 | len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s", sys_name, | 477 | len = snprintf(event_opt, MAX_EVOPT_LEN, "%s:%s%s%s", sys_name, |
479 | evt_ent->d_name); | 478 | evt_ent->d_name, flags ? ":" : "", |
479 | flags ?: ""); | ||
480 | if (len < 0) | 480 | if (len < 0) |
481 | return EVT_FAILED; | 481 | return EVT_FAILED; |
482 | 482 | ||
483 | rem -= len; | ||
484 | if (flags) { | ||
485 | if (rem < strlen(flags) + 1) | ||
486 | return EVT_FAILED; | ||
487 | |||
488 | strcat(event_opt, ":"); | ||
489 | strcat(event_opt, flags); | ||
490 | } | ||
491 | |||
492 | if (parse_events(NULL, event_opt, 0)) | 483 | if (parse_events(NULL, event_opt, 0)) |
493 | return EVT_FAILED; | 484 | return EVT_FAILED; |
494 | } | 485 | } |
diff --git a/tools/perf/util/parse-options.c b/tools/perf/util/parse-options.c index 6d8af48c925e..efebd5b476b3 100644 --- a/tools/perf/util/parse-options.c +++ b/tools/perf/util/parse-options.c | |||
@@ -430,6 +430,9 @@ int usage_with_options_internal(const char * const *usagestr, | |||
430 | pos = fprintf(stderr, " "); | 430 | pos = fprintf(stderr, " "); |
431 | if (opts->short_name) | 431 | if (opts->short_name) |
432 | pos += fprintf(stderr, "-%c", opts->short_name); | 432 | pos += fprintf(stderr, "-%c", opts->short_name); |
433 | else | ||
434 | pos += fprintf(stderr, " "); | ||
435 | |||
433 | if (opts->long_name && opts->short_name) | 436 | if (opts->long_name && opts->short_name) |
434 | pos += fprintf(stderr, ", "); | 437 | pos += fprintf(stderr, ", "); |
435 | if (opts->long_name) | 438 | if (opts->long_name) |
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c index cd7fbda5e2a5..d14a4585bcaf 100644 --- a/tools/perf/util/probe-event.c +++ b/tools/perf/util/probe-event.c | |||
@@ -48,6 +48,9 @@ | |||
48 | 48 | ||
49 | /* If there is no space to write, returns -E2BIG. */ | 49 | /* If there is no space to write, returns -E2BIG. */ |
50 | static int e_snprintf(char *str, size_t size, const char *format, ...) | 50 | static int e_snprintf(char *str, size_t size, const char *format, ...) |
51 | __attribute__((format(printf, 3, 4))); | ||
52 | |||
53 | static int e_snprintf(char *str, size_t size, const char *format, ...) | ||
51 | { | 54 | { |
52 | int ret; | 55 | int ret; |
53 | va_list ap; | 56 | va_list ap; |
@@ -258,7 +261,7 @@ int synthesize_perf_probe_event(struct probe_point *pp) | |||
258 | ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->function, | 261 | ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->function, |
259 | offs, pp->retprobe ? "%return" : "", line); | 262 | offs, pp->retprobe ? "%return" : "", line); |
260 | else | 263 | else |
261 | ret = e_snprintf(buf, MAX_CMDLEN, "%s%s%s%s", pp->file, line); | 264 | ret = e_snprintf(buf, MAX_CMDLEN, "%s%s", pp->file, line); |
262 | if (ret <= 0) | 265 | if (ret <= 0) |
263 | goto error; | 266 | goto error; |
264 | len = ret; | 267 | len = ret; |
@@ -373,14 +376,32 @@ static void clear_probe_point(struct probe_point *pp) | |||
373 | free(pp->args); | 376 | free(pp->args); |
374 | for (i = 0; i < pp->found; i++) | 377 | for (i = 0; i < pp->found; i++) |
375 | free(pp->probes[i]); | 378 | free(pp->probes[i]); |
376 | memset(pp, 0, sizeof(pp)); | 379 | memset(pp, 0, sizeof(*pp)); |
380 | } | ||
381 | |||
382 | /* Show an event */ | ||
383 | static void show_perf_probe_event(const char *group, const char *event, | ||
384 | const char *place, struct probe_point *pp) | ||
385 | { | ||
386 | int i; | ||
387 | char buf[128]; | ||
388 | |||
389 | e_snprintf(buf, 128, "%s:%s", group, event); | ||
390 | printf(" %-40s (on %s", buf, place); | ||
391 | |||
392 | if (pp->nr_args > 0) { | ||
393 | printf(" with"); | ||
394 | for (i = 0; i < pp->nr_args; i++) | ||
395 | printf(" %s", pp->args[i]); | ||
396 | } | ||
397 | printf(")\n"); | ||
377 | } | 398 | } |
378 | 399 | ||
379 | /* List up current perf-probe events */ | 400 | /* List up current perf-probe events */ |
380 | void show_perf_probe_events(void) | 401 | void show_perf_probe_events(void) |
381 | { | 402 | { |
382 | unsigned int i; | 403 | unsigned int i; |
383 | int fd; | 404 | int fd, nr; |
384 | char *group, *event; | 405 | char *group, *event; |
385 | struct probe_point pp; | 406 | struct probe_point pp; |
386 | struct strlist *rawlist; | 407 | struct strlist *rawlist; |
@@ -393,8 +414,13 @@ void show_perf_probe_events(void) | |||
393 | for (i = 0; i < strlist__nr_entries(rawlist); i++) { | 414 | for (i = 0; i < strlist__nr_entries(rawlist); i++) { |
394 | ent = strlist__entry(rawlist, i); | 415 | ent = strlist__entry(rawlist, i); |
395 | parse_trace_kprobe_event(ent->s, &group, &event, &pp); | 416 | parse_trace_kprobe_event(ent->s, &group, &event, &pp); |
417 | /* Synthesize only event probe point */ | ||
418 | nr = pp.nr_args; | ||
419 | pp.nr_args = 0; | ||
396 | synthesize_perf_probe_event(&pp); | 420 | synthesize_perf_probe_event(&pp); |
397 | printf("[%s:%s]\t%s\n", group, event, pp.probes[0]); | 421 | pp.nr_args = nr; |
422 | /* Show an event */ | ||
423 | show_perf_probe_event(group, event, pp.probes[0], &pp); | ||
398 | free(group); | 424 | free(group); |
399 | free(event); | 425 | free(event); |
400 | clear_probe_point(&pp); | 426 | clear_probe_point(&pp); |
@@ -404,21 +430,28 @@ void show_perf_probe_events(void) | |||
404 | } | 430 | } |
405 | 431 | ||
406 | /* Get current perf-probe event names */ | 432 | /* Get current perf-probe event names */ |
407 | static struct strlist *get_perf_event_names(int fd) | 433 | static struct strlist *get_perf_event_names(int fd, bool include_group) |
408 | { | 434 | { |
409 | unsigned int i; | 435 | unsigned int i; |
410 | char *group, *event; | 436 | char *group, *event; |
437 | char buf[128]; | ||
411 | struct strlist *sl, *rawlist; | 438 | struct strlist *sl, *rawlist; |
412 | struct str_node *ent; | 439 | struct str_node *ent; |
413 | 440 | ||
414 | rawlist = get_trace_kprobe_event_rawlist(fd); | 441 | rawlist = get_trace_kprobe_event_rawlist(fd); |
415 | 442 | ||
416 | sl = strlist__new(false, NULL); | 443 | sl = strlist__new(true, NULL); |
417 | for (i = 0; i < strlist__nr_entries(rawlist); i++) { | 444 | for (i = 0; i < strlist__nr_entries(rawlist); i++) { |
418 | ent = strlist__entry(rawlist, i); | 445 | ent = strlist__entry(rawlist, i); |
419 | parse_trace_kprobe_event(ent->s, &group, &event, NULL); | 446 | parse_trace_kprobe_event(ent->s, &group, &event, NULL); |
420 | strlist__add(sl, event); | 447 | if (include_group) { |
448 | if (e_snprintf(buf, 128, "%s:%s", group, event) < 0) | ||
449 | die("Failed to copy group:event name."); | ||
450 | strlist__add(sl, buf); | ||
451 | } else | ||
452 | strlist__add(sl, event); | ||
421 | free(group); | 453 | free(group); |
454 | free(event); | ||
422 | } | 455 | } |
423 | 456 | ||
424 | strlist__delete(rawlist); | 457 | strlist__delete(rawlist); |
@@ -426,24 +459,30 @@ static struct strlist *get_perf_event_names(int fd) | |||
426 | return sl; | 459 | return sl; |
427 | } | 460 | } |
428 | 461 | ||
429 | static int write_trace_kprobe_event(int fd, const char *buf) | 462 | static void write_trace_kprobe_event(int fd, const char *buf) |
430 | { | 463 | { |
431 | int ret; | 464 | int ret; |
432 | 465 | ||
466 | pr_debug("Writing event: %s\n", buf); | ||
433 | ret = write(fd, buf, strlen(buf)); | 467 | ret = write(fd, buf, strlen(buf)); |
434 | if (ret <= 0) | 468 | if (ret <= 0) |
435 | die("Failed to create event."); | 469 | die("Failed to write event: %s", strerror(errno)); |
436 | else | ||
437 | printf("Added new event: %s\n", buf); | ||
438 | |||
439 | return ret; | ||
440 | } | 470 | } |
441 | 471 | ||
442 | static void get_new_event_name(char *buf, size_t len, const char *base, | 472 | static void get_new_event_name(char *buf, size_t len, const char *base, |
443 | struct strlist *namelist) | 473 | struct strlist *namelist) |
444 | { | 474 | { |
445 | int i, ret; | 475 | int i, ret; |
446 | for (i = 0; i < MAX_EVENT_INDEX; i++) { | 476 | |
477 | /* Try no suffix */ | ||
478 | ret = e_snprintf(buf, len, "%s", base); | ||
479 | if (ret < 0) | ||
480 | die("snprintf() failed: %s", strerror(-ret)); | ||
481 | if (!strlist__has_entry(namelist, buf)) | ||
482 | return; | ||
483 | |||
484 | /* Try to add suffix */ | ||
485 | for (i = 1; i < MAX_EVENT_INDEX; i++) { | ||
447 | ret = e_snprintf(buf, len, "%s_%d", base, i); | 486 | ret = e_snprintf(buf, len, "%s_%d", base, i); |
448 | if (ret < 0) | 487 | if (ret < 0) |
449 | die("snprintf() failed: %s", strerror(-ret)); | 488 | die("snprintf() failed: %s", strerror(-ret)); |
@@ -464,7 +503,7 @@ void add_trace_kprobe_events(struct probe_point *probes, int nr_probes) | |||
464 | 503 | ||
465 | fd = open_kprobe_events(O_RDWR, O_APPEND); | 504 | fd = open_kprobe_events(O_RDWR, O_APPEND); |
466 | /* Get current event names */ | 505 | /* Get current event names */ |
467 | namelist = get_perf_event_names(fd); | 506 | namelist = get_perf_event_names(fd, false); |
468 | 507 | ||
469 | for (j = 0; j < nr_probes; j++) { | 508 | for (j = 0; j < nr_probes; j++) { |
470 | pp = probes + j; | 509 | pp = probes + j; |
@@ -476,9 +515,73 @@ void add_trace_kprobe_events(struct probe_point *probes, int nr_probes) | |||
476 | PERFPROBE_GROUP, event, | 515 | PERFPROBE_GROUP, event, |
477 | pp->probes[i]); | 516 | pp->probes[i]); |
478 | write_trace_kprobe_event(fd, buf); | 517 | write_trace_kprobe_event(fd, buf); |
518 | printf("Added new event:\n"); | ||
519 | /* Get the first parameter (probe-point) */ | ||
520 | sscanf(pp->probes[i], "%s", buf); | ||
521 | show_perf_probe_event(PERFPROBE_GROUP, event, | ||
522 | buf, pp); | ||
479 | /* Add added event name to namelist */ | 523 | /* Add added event name to namelist */ |
480 | strlist__add(namelist, event); | 524 | strlist__add(namelist, event); |
481 | } | 525 | } |
482 | } | 526 | } |
527 | /* Show how to use the event. */ | ||
528 | printf("\nYou can now use it on all perf tools, such as:\n\n"); | ||
529 | printf("\tperf record -e %s:%s -a sleep 1\n\n", PERFPROBE_GROUP, event); | ||
530 | |||
531 | strlist__delete(namelist); | ||
532 | close(fd); | ||
533 | } | ||
534 | |||
535 | static void del_trace_kprobe_event(int fd, const char *group, | ||
536 | const char *event, struct strlist *namelist) | ||
537 | { | ||
538 | char buf[128]; | ||
539 | |||
540 | if (e_snprintf(buf, 128, "%s:%s", group, event) < 0) | ||
541 | die("Failed to copy event."); | ||
542 | if (!strlist__has_entry(namelist, buf)) { | ||
543 | pr_warning("Warning: event \"%s\" is not found.\n", buf); | ||
544 | return; | ||
545 | } | ||
546 | /* Convert from perf-probe event to trace-kprobe event */ | ||
547 | if (e_snprintf(buf, 128, "-:%s/%s", group, event) < 0) | ||
548 | die("Failed to copy event."); | ||
549 | |||
550 | write_trace_kprobe_event(fd, buf); | ||
551 | printf("Remove event: %s:%s\n", group, event); | ||
552 | } | ||
553 | |||
554 | void del_trace_kprobe_events(struct strlist *dellist) | ||
555 | { | ||
556 | int fd; | ||
557 | unsigned int i; | ||
558 | const char *group, *event; | ||
559 | char *p, *str; | ||
560 | struct str_node *ent; | ||
561 | struct strlist *namelist; | ||
562 | |||
563 | fd = open_kprobe_events(O_RDWR, O_APPEND); | ||
564 | /* Get current event names */ | ||
565 | namelist = get_perf_event_names(fd, true); | ||
566 | |||
567 | for (i = 0; i < strlist__nr_entries(dellist); i++) { | ||
568 | ent = strlist__entry(dellist, i); | ||
569 | str = strdup(ent->s); | ||
570 | if (!str) | ||
571 | die("Failed to copy event."); | ||
572 | p = strchr(str, ':'); | ||
573 | if (p) { | ||
574 | group = str; | ||
575 | *p = '\0'; | ||
576 | event = p + 1; | ||
577 | } else { | ||
578 | group = PERFPROBE_GROUP; | ||
579 | event = str; | ||
580 | } | ||
581 | del_trace_kprobe_event(fd, group, event, namelist); | ||
582 | free(str); | ||
583 | } | ||
584 | strlist__delete(namelist); | ||
483 | close(fd); | 585 | close(fd); |
484 | } | 586 | } |
587 | |||
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h index 0c6fe56fe38a..f752159124ae 100644 --- a/tools/perf/util/probe-event.h +++ b/tools/perf/util/probe-event.h | |||
@@ -10,6 +10,7 @@ extern void parse_trace_kprobe_event(const char *str, char **group, | |||
10 | char **event, struct probe_point *pp); | 10 | char **event, struct probe_point *pp); |
11 | extern int synthesize_trace_kprobe_event(struct probe_point *pp); | 11 | extern int synthesize_trace_kprobe_event(struct probe_point *pp); |
12 | extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes); | 12 | extern void add_trace_kprobe_events(struct probe_point *probes, int nr_probes); |
13 | extern void del_trace_kprobe_events(struct strlist *dellist); | ||
13 | extern void show_perf_probe_events(void); | 14 | extern void show_perf_probe_events(void); |
14 | 15 | ||
15 | /* Maximum index number of event-name postfix */ | 16 | /* Maximum index number of event-name postfix */ |
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c index 293cdfc1b8ca..4585f1d86792 100644 --- a/tools/perf/util/probe-finder.c +++ b/tools/perf/util/probe-finder.c | |||
@@ -106,7 +106,7 @@ static int strtailcmp(const char *s1, const char *s2) | |||
106 | { | 106 | { |
107 | int i1 = strlen(s1); | 107 | int i1 = strlen(s1); |
108 | int i2 = strlen(s2); | 108 | int i2 = strlen(s2); |
109 | while (--i1 > 0 && --i2 > 0) { | 109 | while (--i1 >= 0 && --i2 >= 0) { |
110 | if (s1[i1] != s2[i2]) | 110 | if (s1[i1] != s2[i2]) |
111 | return s1[i1] - s2[i2]; | 111 | return s1[i1] - s2[i2]; |
112 | } | 112 | } |
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c index fffcb937cdcb..e7508ad3450f 100644 --- a/tools/perf/util/symbol.c +++ b/tools/perf/util/symbol.c | |||
@@ -938,8 +938,9 @@ static bool __dsos__read_build_ids(struct list_head *head) | |||
938 | 938 | ||
939 | bool dsos__read_build_ids(void) | 939 | bool dsos__read_build_ids(void) |
940 | { | 940 | { |
941 | return __dsos__read_build_ids(&dsos__kernel) || | 941 | bool kbuildids = __dsos__read_build_ids(&dsos__kernel), |
942 | __dsos__read_build_ids(&dsos__user); | 942 | ubuildids = __dsos__read_build_ids(&dsos__user); |
943 | return kbuildids || ubuildids; | ||
943 | } | 944 | } |
944 | 945 | ||
945 | /* | 946 | /* |
diff --git a/tools/perf/util/trace-event-parse.c b/tools/perf/util/trace-event-parse.c index 0302405aa2ca..c5c32be040bf 100644 --- a/tools/perf/util/trace-event-parse.c +++ b/tools/perf/util/trace-event-parse.c | |||
@@ -177,7 +177,7 @@ void parse_proc_kallsyms(char *file, unsigned int size __unused) | |||
177 | func_count++; | 177 | func_count++; |
178 | } | 178 | } |
179 | 179 | ||
180 | func_list = malloc_or_die(sizeof(*func_list) * func_count + 1); | 180 | func_list = malloc_or_die(sizeof(*func_list) * (func_count + 1)); |
181 | 181 | ||
182 | i = 0; | 182 | i = 0; |
183 | while (list) { | 183 | while (list) { |
@@ -1477,7 +1477,7 @@ process_fields(struct event *event, struct print_flag_sym **list, char **tok) | |||
1477 | goto out_free; | 1477 | goto out_free; |
1478 | 1478 | ||
1479 | field = malloc_or_die(sizeof(*field)); | 1479 | field = malloc_or_die(sizeof(*field)); |
1480 | memset(field, 0, sizeof(field)); | 1480 | memset(field, 0, sizeof(*field)); |
1481 | 1481 | ||
1482 | value = arg_eval(arg); | 1482 | value = arg_eval(arg); |
1483 | field->value = strdup(value); | 1483 | field->value = strdup(value); |
diff --git a/tools/perf/util/trace-event-perl.c b/tools/perf/util/trace-event-perl.c index 51e833fd58c3..a5ffe60db5d6 100644 --- a/tools/perf/util/trace-event-perl.c +++ b/tools/perf/util/trace-event-perl.c | |||
@@ -32,9 +32,6 @@ | |||
32 | 32 | ||
33 | void xs_init(pTHX); | 33 | void xs_init(pTHX); |
34 | 34 | ||
35 | void boot_Perf__Trace__Context(pTHX_ CV *cv); | ||
36 | void boot_DynaLoader(pTHX_ CV *cv); | ||
37 | |||
38 | void xs_init(pTHX) | 35 | void xs_init(pTHX) |
39 | { | 36 | { |
40 | const char *file = __FILE__; | 37 | const char *file = __FILE__; |
@@ -573,26 +570,72 @@ struct scripting_ops perl_scripting_ops = { | |||
573 | .generate_script = perl_generate_script, | 570 | .generate_script = perl_generate_script, |
574 | }; | 571 | }; |
575 | 572 | ||
576 | #ifdef NO_LIBPERL | 573 | static void print_unsupported_msg(void) |
577 | void setup_perl_scripting(void) | ||
578 | { | 574 | { |
579 | fprintf(stderr, "Perl scripting not supported." | 575 | fprintf(stderr, "Perl scripting not supported." |
580 | " Install libperl and rebuild perf to enable it. e.g. " | 576 | " Install libperl and rebuild perf to enable it.\n" |
581 | "apt-get install libperl-dev (ubuntu), yum install " | 577 | "For example:\n # apt-get install libperl-dev (ubuntu)" |
582 | "perl-ExtUtils-Embed (Fedora), etc.\n"); | 578 | "\n # yum install perl-ExtUtils-Embed (Fedora)" |
579 | "\n etc.\n"); | ||
583 | } | 580 | } |
584 | #else | 581 | |
585 | void setup_perl_scripting(void) | 582 | static int perl_start_script_unsupported(const char *script __unused) |
583 | { | ||
584 | print_unsupported_msg(); | ||
585 | |||
586 | return -1; | ||
587 | } | ||
588 | |||
589 | static int perl_stop_script_unsupported(void) | ||
590 | { | ||
591 | return 0; | ||
592 | } | ||
593 | |||
594 | static void perl_process_event_unsupported(int cpu __unused, | ||
595 | void *data __unused, | ||
596 | int size __unused, | ||
597 | unsigned long long nsecs __unused, | ||
598 | char *comm __unused) | ||
599 | { | ||
600 | } | ||
601 | |||
602 | static int perl_generate_script_unsupported(const char *outfile __unused) | ||
603 | { | ||
604 | print_unsupported_msg(); | ||
605 | |||
606 | return -1; | ||
607 | } | ||
608 | |||
609 | struct scripting_ops perl_scripting_unsupported_ops = { | ||
610 | .name = "Perl", | ||
611 | .start_script = perl_start_script_unsupported, | ||
612 | .stop_script = perl_stop_script_unsupported, | ||
613 | .process_event = perl_process_event_unsupported, | ||
614 | .generate_script = perl_generate_script_unsupported, | ||
615 | }; | ||
616 | |||
617 | static void register_perl_scripting(struct scripting_ops *scripting_ops) | ||
586 | { | 618 | { |
587 | int err; | 619 | int err; |
588 | err = script_spec_register("Perl", &perl_scripting_ops); | 620 | err = script_spec_register("Perl", scripting_ops); |
589 | if (err) | 621 | if (err) |
590 | die("error registering Perl script extension"); | 622 | die("error registering Perl script extension"); |
591 | 623 | ||
592 | err = script_spec_register("pl", &perl_scripting_ops); | 624 | err = script_spec_register("pl", scripting_ops); |
593 | if (err) | 625 | if (err) |
594 | die("error registering pl script extension"); | 626 | die("error registering pl script extension"); |
595 | 627 | ||
596 | scripting_context = malloc(sizeof(struct scripting_context)); | 628 | scripting_context = malloc(sizeof(struct scripting_context)); |
597 | } | 629 | } |
630 | |||
631 | #ifdef NO_LIBPERL | ||
632 | void setup_perl_scripting(void) | ||
633 | { | ||
634 | register_perl_scripting(&perl_scripting_unsupported_ops); | ||
635 | } | ||
636 | #else | ||
637 | void setup_perl_scripting(void) | ||
638 | { | ||
639 | register_perl_scripting(&perl_scripting_ops); | ||
640 | } | ||
598 | #endif | 641 | #endif |
diff --git a/tools/perf/util/trace-event-perl.h b/tools/perf/util/trace-event-perl.h index 8fe0d866fe1a..e88fb26137bb 100644 --- a/tools/perf/util/trace-event-perl.h +++ b/tools/perf/util/trace-event-perl.h | |||
@@ -34,9 +34,13 @@ typedef int INTERP; | |||
34 | #define dXSUB_SYS | 34 | #define dXSUB_SYS |
35 | #define pTHX_ | 35 | #define pTHX_ |
36 | static inline void newXS(const char *a, void *b, const char *c) {} | 36 | static inline void newXS(const char *a, void *b, const char *c) {} |
37 | static void boot_Perf__Trace__Context(pTHX_ CV *cv) {} | ||
38 | static void boot_DynaLoader(pTHX_ CV *cv) {} | ||
37 | #else | 39 | #else |
38 | #include <EXTERN.h> | 40 | #include <EXTERN.h> |
39 | #include <perl.h> | 41 | #include <perl.h> |
42 | void boot_Perf__Trace__Context(pTHX_ CV *cv); | ||
43 | void boot_DynaLoader(pTHX_ CV *cv); | ||
40 | typedef PerlInterpreter * INTERP; | 44 | typedef PerlInterpreter * INTERP; |
41 | #endif | 45 | #endif |
42 | 46 | ||
diff --git a/tools/perf/util/trace-event-read.c b/tools/perf/util/trace-event-read.c index 342dfdd43f87..1744422cafcb 100644 --- a/tools/perf/util/trace-event-read.c +++ b/tools/perf/util/trace-event-read.c | |||
@@ -145,8 +145,9 @@ static void read_proc_kallsyms(void) | |||
145 | if (!size) | 145 | if (!size) |
146 | return; | 146 | return; |
147 | 147 | ||
148 | buf = malloc_or_die(size); | 148 | buf = malloc_or_die(size + 1); |
149 | read_or_die(buf, size); | 149 | read_or_die(buf, size); |
150 | buf[size] = '\0'; | ||
150 | 151 | ||
151 | parse_proc_kallsyms(buf, size); | 152 | parse_proc_kallsyms(buf, size); |
152 | 153 | ||