aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2015-04-11 02:31:19 -0400
committerIngo Molnar <mingo@kernel.org>2015-04-11 02:31:19 -0400
commit5dafd7cb96ec75454eb1fcbf993000bf41175f13 (patch)
treef0d3281f2d9b5ff8beb6209e5e226778a5d803b6 /tools
parent51ab7155c08baf45cc2aa911961e5b78422e478f (diff)
parent7b8283b56d9fb36106ff1c459dfd399a20bd374d (diff)
Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux into perf/core
Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo: New user visible features: - Support multiple probes on different binaries on the same command line (Masami Hiramatsu) User visible changes: - Fix synthesizing fork_event.ppid for non-main thread (David Ahern) - Fix cross-endian analysis (David Ahern) - Fix segfault in 'perf buildid-list' when show DSOs with hits (He Kuang) Infrastructure changes: - Fix type for references to data_head/tail (David Ahern) - Fix error path to do closedir() when synthesizing threads (Arnaldo Carvalho de Melo) Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com> Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/perf/builtin-probe.c19
-rw-r--r--tools/perf/builtin-record.c4
-rw-r--r--tools/perf/util/build-id.c8
-rw-r--r--tools/perf/util/event.c31
-rw-r--r--tools/perf/util/evlist.c6
-rw-r--r--tools/perf/util/evlist.h9
-rw-r--r--tools/perf/util/header.c5
-rw-r--r--tools/perf/util/machine.c4
-rw-r--r--tools/perf/util/machine.h1
-rw-r--r--tools/perf/util/probe-event.c5
-rw-r--r--tools/perf/util/probe-event.h6
11 files changed, 61 insertions, 37 deletions
diff --git a/tools/perf/builtin-probe.c b/tools/perf/builtin-probe.c
index 921bb6942503..f7b1af67e9f6 100644
--- a/tools/perf/builtin-probe.c
+++ b/tools/perf/builtin-probe.c
@@ -56,6 +56,7 @@ static struct {
56 bool mod_events; 56 bool mod_events;
57 bool uprobes; 57 bool uprobes;
58 bool quiet; 58 bool quiet;
59 bool target_used;
59 int nevents; 60 int nevents;
60 struct perf_probe_event events[MAX_PROBES]; 61 struct perf_probe_event events[MAX_PROBES];
61 struct strlist *dellist; 62 struct strlist *dellist;
@@ -78,6 +79,12 @@ static int parse_probe_event(const char *str)
78 } 79 }
79 80
80 pev->uprobes = params.uprobes; 81 pev->uprobes = params.uprobes;
82 if (params.target) {
83 pev->target = strdup(params.target);
84 if (!pev->target)
85 return -ENOMEM;
86 params.target_used = true;
87 }
81 88
82 /* Parse a perf-probe command into event */ 89 /* Parse a perf-probe command into event */
83 ret = parse_perf_probe_command(str, pev); 90 ret = parse_perf_probe_command(str, pev);
@@ -102,6 +109,7 @@ static int set_target(const char *ptr)
102 params.target = strdup(ptr); 109 params.target = strdup(ptr);
103 if (!params.target) 110 if (!params.target)
104 return -ENOMEM; 111 return -ENOMEM;
112 params.target_used = false;
105 113
106 found = 1; 114 found = 1;
107 buf = ptr + (strlen(ptr) - 3); 115 buf = ptr + (strlen(ptr) - 3);
@@ -178,7 +186,7 @@ static int opt_set_target(const struct option *opt, const char *str,
178 int ret = -ENOENT; 186 int ret = -ENOENT;
179 char *tmp; 187 char *tmp;
180 188
181 if (str && !params.target) { 189 if (str) {
182 if (!strcmp(opt->long_name, "exec")) 190 if (!strcmp(opt->long_name, "exec"))
183 params.uprobes = true; 191 params.uprobes = true;
184#ifdef HAVE_DWARF_SUPPORT 192#ifdef HAVE_DWARF_SUPPORT
@@ -200,7 +208,9 @@ static int opt_set_target(const struct option *opt, const char *str,
200 if (!tmp) 208 if (!tmp)
201 return -ENOMEM; 209 return -ENOMEM;
202 } 210 }
211 free(params.target);
203 params.target = tmp; 212 params.target = tmp;
213 params.target_used = false;
204 ret = 0; 214 ret = 0;
205 } 215 }
206 216
@@ -485,9 +495,14 @@ __cmd_probe(int argc, const char **argv, const char *prefix __maybe_unused)
485 } 495 }
486 496
487 if (params.nevents) { 497 if (params.nevents) {
498 /* Ensure the last given target is used */
499 if (params.target && !params.target_used) {
500 pr_warning(" Error: -x/-m must follow the probe definitions.\n");
501 usage_with_options(probe_usage, options);
502 }
503
488 ret = add_perf_probe_events(params.events, params.nevents, 504 ret = add_perf_probe_events(params.events, params.nevents,
489 params.max_probe_points, 505 params.max_probe_points,
490 params.target,
491 params.force_add); 506 params.force_add);
492 if (ret < 0) { 507 if (ret < 0) {
493 pr_err_with_code(" Error: Failed to add events.", ret); 508 pr_err_with_code(" Error: Failed to add events.", ret);
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index ac610488d2e1..c3efdfb630b5 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -70,8 +70,8 @@ static int process_synthesized_event(struct perf_tool *tool,
70static int record__mmap_read(struct record *rec, int idx) 70static int record__mmap_read(struct record *rec, int idx)
71{ 71{
72 struct perf_mmap *md = &rec->evlist->mmap[idx]; 72 struct perf_mmap *md = &rec->evlist->mmap[idx];
73 unsigned int head = perf_mmap__read_head(md); 73 u64 head = perf_mmap__read_head(md);
74 unsigned int old = md->prev; 74 u64 old = md->prev;
75 unsigned char *data = md->base + page_size; 75 unsigned char *data = md->base + page_size;
76 unsigned long size; 76 unsigned long size;
77 void *buf; 77 void *buf;
diff --git a/tools/perf/util/build-id.c b/tools/perf/util/build-id.c
index f7fb2587df69..61867dff5d5a 100644
--- a/tools/perf/util/build-id.c
+++ b/tools/perf/util/build-id.c
@@ -59,12 +59,8 @@ static int perf_event__exit_del_thread(struct perf_tool *tool __maybe_unused,
59 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid, 59 dump_printf("(%d:%d):(%d:%d)\n", event->fork.pid, event->fork.tid,
60 event->fork.ppid, event->fork.ptid); 60 event->fork.ppid, event->fork.ptid);
61 61
62 if (thread) { 62 if (thread)
63 rb_erase(&thread->rb_node, &machine->threads); 63 machine__remove_thread(machine, thread);
64 if (machine->last_match == thread)
65 thread__zput(machine->last_match);
66 thread__put(thread);
67 }
68 64
69 return 0; 65 return 0;
70} 66}
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 5516236df6ab..ff866c4d2e2f 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -183,8 +183,18 @@ static int perf_event__synthesize_fork(struct perf_tool *tool,
183{ 183{
184 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size); 184 memset(&event->fork, 0, sizeof(event->fork) + machine->id_hdr_size);
185 185
186 event->fork.ppid = ppid; 186 /*
187 event->fork.ptid = ppid; 187 * for main thread set parent to ppid from status file. For other
188 * threads set parent pid to main thread. ie., assume main thread
189 * spawns all threads in a process
190 */
191 if (tgid == pid) {
192 event->fork.ppid = ppid;
193 event->fork.ptid = ppid;
194 } else {
195 event->fork.ppid = tgid;
196 event->fork.ptid = tgid;
197 }
188 event->fork.pid = tgid; 198 event->fork.pid = tgid;
189 event->fork.tid = pid; 199 event->fork.tid = pid;
190 event->fork.header.type = PERF_RECORD_FORK; 200 event->fork.header.type = PERF_RECORD_FORK;
@@ -377,6 +387,7 @@ static int __event__synthesize_thread(union perf_event *comm_event,
377 DIR *tasks; 387 DIR *tasks;
378 struct dirent dirent, *next; 388 struct dirent dirent, *next;
379 pid_t tgid, ppid; 389 pid_t tgid, ppid;
390 int rc = 0;
380 391
381 /* special case: only send one comm event using passed in pid */ 392 /* special case: only send one comm event using passed in pid */
382 if (!full) { 393 if (!full) {
@@ -404,38 +415,38 @@ static int __event__synthesize_thread(union perf_event *comm_event,
404 415
405 while (!readdir_r(tasks, &dirent, &next) && next) { 416 while (!readdir_r(tasks, &dirent, &next) && next) {
406 char *end; 417 char *end;
407 int rc = 0;
408 pid_t _pid; 418 pid_t _pid;
409 419
410 _pid = strtol(dirent.d_name, &end, 10); 420 _pid = strtol(dirent.d_name, &end, 10);
411 if (*end) 421 if (*end)
412 continue; 422 continue;
413 423
424 rc = -1;
414 if (perf_event__prepare_comm(comm_event, _pid, machine, 425 if (perf_event__prepare_comm(comm_event, _pid, machine,
415 &tgid, &ppid) != 0) 426 &tgid, &ppid) != 0)
416 return -1; 427 break;
417 428
418 if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid, 429 if (perf_event__synthesize_fork(tool, fork_event, _pid, tgid,
419 ppid, process, machine) < 0) 430 ppid, process, machine) < 0)
420 return -1; 431 break;
421 /* 432 /*
422 * Send the prepared comm event 433 * Send the prepared comm event
423 */ 434 */
424 if (process(tool, comm_event, &synth_sample, machine) != 0) 435 if (process(tool, comm_event, &synth_sample, machine) != 0)
425 return -1; 436 break;
426 437
438 rc = 0;
427 if (_pid == pid) { 439 if (_pid == pid) {
428 /* process the parent's maps too */ 440 /* process the parent's maps too */
429 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid, 441 rc = perf_event__synthesize_mmap_events(tool, mmap_event, pid, tgid,
430 process, machine, mmap_data); 442 process, machine, mmap_data);
443 if (rc)
444 break;
431 } 445 }
432
433 if (rc)
434 return rc;
435 } 446 }
436 447
437 closedir(tasks); 448 closedir(tasks);
438 return 0; 449 return rc;
439} 450}
440 451
441int perf_event__synthesize_thread_map(struct perf_tool *tool, 452int perf_event__synthesize_thread_map(struct perf_tool *tool,
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index 76ef7ee62640..080be93eea96 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -634,8 +634,8 @@ static struct perf_evsel *perf_evlist__event2evsel(struct perf_evlist *evlist,
634union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx) 634union perf_event *perf_evlist__mmap_read(struct perf_evlist *evlist, int idx)
635{ 635{
636 struct perf_mmap *md = &evlist->mmap[idx]; 636 struct perf_mmap *md = &evlist->mmap[idx];
637 unsigned int head = perf_mmap__read_head(md); 637 u64 head = perf_mmap__read_head(md);
638 unsigned int old = md->prev; 638 u64 old = md->prev;
639 unsigned char *data = md->base + page_size; 639 unsigned char *data = md->base + page_size;
640 union perf_event *event = NULL; 640 union perf_event *event = NULL;
641 641
@@ -716,7 +716,7 @@ void perf_evlist__mmap_consume(struct perf_evlist *evlist, int idx)
716 struct perf_mmap *md = &evlist->mmap[idx]; 716 struct perf_mmap *md = &evlist->mmap[idx];
717 717
718 if (!evlist->overwrite) { 718 if (!evlist->overwrite) {
719 unsigned int old = md->prev; 719 u64 old = md->prev;
720 720
721 perf_mmap__write_tail(md, old); 721 perf_mmap__write_tail(md, old);
722 } 722 }
diff --git a/tools/perf/util/evlist.h b/tools/perf/util/evlist.h
index fb19c47b8aac..b5cce95d644e 100644
--- a/tools/perf/util/evlist.h
+++ b/tools/perf/util/evlist.h
@@ -27,7 +27,7 @@ struct perf_mmap {
27 void *base; 27 void *base;
28 int mask; 28 int mask;
29 int refcnt; 29 int refcnt;
30 unsigned int prev; 30 u64 prev;
31 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8))); 31 char event_copy[PERF_SAMPLE_MAX_SIZE] __attribute__((aligned(8)));
32}; 32};
33 33
@@ -189,16 +189,15 @@ size_t perf_evlist__fprintf(struct perf_evlist *evlist, FILE *fp);
189int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size); 189int perf_evlist__strerror_open(struct perf_evlist *evlist, int err, char *buf, size_t size);
190int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size); 190int perf_evlist__strerror_mmap(struct perf_evlist *evlist, int err, char *buf, size_t size);
191 191
192static inline unsigned int perf_mmap__read_head(struct perf_mmap *mm) 192static inline u64 perf_mmap__read_head(struct perf_mmap *mm)
193{ 193{
194 struct perf_event_mmap_page *pc = mm->base; 194 struct perf_event_mmap_page *pc = mm->base;
195 int head = ACCESS_ONCE(pc->data_head); 195 u64 head = ACCESS_ONCE(pc->data_head);
196 rmb(); 196 rmb();
197 return head; 197 return head;
198} 198}
199 199
200static inline void perf_mmap__write_tail(struct perf_mmap *md, 200static inline void perf_mmap__write_tail(struct perf_mmap *md, u64 tail)
201 unsigned long tail)
202{ 201{
203 struct perf_event_mmap_page *pc = md->base; 202 struct perf_event_mmap_page *pc = md->base;
204 203
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index fff3b2a455ae..918fd8ae2d80 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -2504,8 +2504,11 @@ int perf_session__read_header(struct perf_session *session)
2504 if (read_attr(fd, header, &f_attr) < 0) 2504 if (read_attr(fd, header, &f_attr) < 0)
2505 goto out_errno; 2505 goto out_errno;
2506 2506
2507 if (header->needs_swap) 2507 if (header->needs_swap) {
2508 f_attr.ids.size = bswap_64(f_attr.ids.size);
2509 f_attr.ids.offset = bswap_64(f_attr.ids.offset);
2508 perf_event__attr_swap(&f_attr.attr); 2510 perf_event__attr_swap(&f_attr.attr);
2511 }
2509 2512
2510 tmp = lseek(fd, 0, SEEK_CUR); 2513 tmp = lseek(fd, 0, SEEK_CUR);
2511 evsel = perf_evsel__new(&f_attr.attr); 2514 evsel = perf_evsel__new(&f_attr.attr);
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 9c380a2caa54..527e032e24f6 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -14,8 +14,6 @@
14#include "unwind.h" 14#include "unwind.h"
15#include "linux/hash.h" 15#include "linux/hash.h"
16 16
17static void machine__remove_thread(struct machine *machine, struct thread *th);
18
19static void dsos__init(struct dsos *dsos) 17static void dsos__init(struct dsos *dsos)
20{ 18{
21 INIT_LIST_HEAD(&dsos->head); 19 INIT_LIST_HEAD(&dsos->head);
@@ -1256,7 +1254,7 @@ out_problem:
1256 return 0; 1254 return 0;
1257} 1255}
1258 1256
1259static void machine__remove_thread(struct machine *machine, struct thread *th) 1257void machine__remove_thread(struct machine *machine, struct thread *th)
1260{ 1258{
1261 if (machine->last_match == th) 1259 if (machine->last_match == th)
1262 thread__zput(machine->last_match); 1260 thread__zput(machine->last_match);
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index e2faf3b47e7b..6d64cedb9d1e 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -120,6 +120,7 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid);
120void machine__exit(struct machine *machine); 120void machine__exit(struct machine *machine);
121void machine__delete_threads(struct machine *machine); 121void machine__delete_threads(struct machine *machine);
122void machine__delete(struct machine *machine); 122void machine__delete(struct machine *machine);
123void machine__remove_thread(struct machine *machine, struct thread *th);
123 124
124struct branch_info *sample__resolve_bstack(struct perf_sample *sample, 125struct branch_info *sample__resolve_bstack(struct perf_sample *sample,
125 struct addr_location *al); 126 struct addr_location *al);
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index b78851732a71..30545ce2c712 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -1906,6 +1906,7 @@ void clear_perf_probe_event(struct perf_probe_event *pev)
1906 1906
1907 free(pev->event); 1907 free(pev->event);
1908 free(pev->group); 1908 free(pev->group);
1909 free(pev->target);
1909 clear_perf_probe_point(&pev->point); 1910 clear_perf_probe_point(&pev->point);
1910 1911
1911 for (i = 0; i < pev->nargs; i++) { 1912 for (i = 0; i < pev->nargs; i++) {
@@ -2654,7 +2655,7 @@ struct __event_package {
2654}; 2655};
2655 2656
2656int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 2657int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
2657 int max_tevs, const char *target, bool force_add) 2658 int max_tevs, bool force_add)
2658{ 2659{
2659 int i, j, ret; 2660 int i, j, ret;
2660 struct __event_package *pkgs; 2661 struct __event_package *pkgs;
@@ -2678,7 +2679,7 @@ int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
2678 ret = convert_to_probe_trace_events(pkgs[i].pev, 2679 ret = convert_to_probe_trace_events(pkgs[i].pev,
2679 &pkgs[i].tevs, 2680 &pkgs[i].tevs,
2680 max_tevs, 2681 max_tevs,
2681 target); 2682 pkgs[i].pev->target);
2682 if (ret < 0) 2683 if (ret < 0)
2683 goto end; 2684 goto end;
2684 pkgs[i].ntevs = ret; 2685 pkgs[i].ntevs = ret;
diff --git a/tools/perf/util/probe-event.h b/tools/perf/util/probe-event.h
index e01e9943139f..d6b783447be9 100644
--- a/tools/perf/util/probe-event.h
+++ b/tools/perf/util/probe-event.h
@@ -73,7 +73,8 @@ struct perf_probe_event {
73 char *group; /* Group name */ 73 char *group; /* Group name */
74 struct perf_probe_point point; /* Probe point */ 74 struct perf_probe_point point; /* Probe point */
75 int nargs; /* Number of arguments */ 75 int nargs; /* Number of arguments */
76 bool uprobes; 76 bool uprobes; /* Uprobe event flag */
77 char *target; /* Target binary */
77 struct perf_probe_arg *args; /* Arguments */ 78 struct perf_probe_arg *args; /* Arguments */
78}; 79};
79 80
@@ -124,8 +125,7 @@ extern int line_range__init(struct line_range *lr);
124extern const char *kernel_get_module_path(const char *module); 125extern const char *kernel_get_module_path(const char *module);
125 126
126extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs, 127extern int add_perf_probe_events(struct perf_probe_event *pevs, int npevs,
127 int max_probe_points, const char *module, 128 int max_probe_points, bool force_add);
128 bool force_add);
129extern int del_perf_probe_events(struct strlist *dellist); 129extern int del_perf_probe_events(struct strlist *dellist);
130extern int show_perf_probe_events(void); 130extern int show_perf_probe_events(void);
131extern int show_line_range(struct line_range *lr, const char *module, 131extern int show_line_range(struct line_range *lr, const char *module,