aboutsummaryrefslogtreecommitdiffstats
path: root/tools/perf
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2011-04-19 01:55:58 -0400
committerIngo Molnar <mingo@elte.hu>2011-04-19 01:56:17 -0400
commit68d2cf25d39324c54b5e42de7915c623a0917abe (patch)
treeff1291450d7e6630bc77ec1363c3db8d74fa58b0 /tools/perf
parent176fcc5c5f0131504a55e1e1d35389c49a9177c2 (diff)
parent5d2cd90922c778908bd0cd669e572a5b5eafd737 (diff)
Merge branch 'perf/urgent' into perf/core
Merge reason: we'll be queueing up dependent changes. Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'tools/perf')
-rw-r--r--tools/perf/Makefile8
-rw-r--r--tools/perf/builtin-record.c13
-rw-r--r--tools/perf/builtin-stat.c7
-rw-r--r--tools/perf/builtin-test.c10
-rw-r--r--tools/perf/builtin-top.c3
-rw-r--r--tools/perf/util/cgroup.c2
-rw-r--r--tools/perf/util/evlist.c14
-rw-r--r--tools/perf/util/evsel.c27
-rw-r--r--tools/perf/util/evsel.h6
-rw-r--r--tools/perf/util/probe-event.c19
-rw-r--r--tools/perf/util/probe-finder.c159
-rw-r--r--tools/perf/util/python.c9
-rw-r--r--tools/perf/util/setup.py7
-rw-r--r--tools/perf/util/string.c2
-rw-r--r--tools/perf/util/symbol.c2
-rw-r--r--tools/perf/util/ui/browsers/annotate.c6
-rw-r--r--tools/perf/util/ui/browsers/hists.c2
17 files changed, 180 insertions, 116 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 158c30e8210c..207dee5c5b16 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -165,8 +165,12 @@ grep-libs = $(filter -l%,$(1))
165strip-libs = $(filter-out -l%,$(1)) 165strip-libs = $(filter-out -l%,$(1))
166 166
167$(OUTPUT)python/perf.so: $(PYRF_OBJS) 167$(OUTPUT)python/perf.so: $(PYRF_OBJS)
168 $(QUIET_GEN)python util/setup.py --quiet build_ext --build-lib='$(OUTPUT)python' \ 168 $(QUIET_GEN)( \
169 --build-temp='$(OUTPUT)python/temp' 169 export CFLAGS="$(BASIC_CFLAGS)"; \
170 python util/setup.py --quiet build_ext --build-lib='$(OUTPUT)python' \
171 --build-temp='$(OUTPUT)python/temp' \
172 )
173
170# 174#
171# No Perl scripts right now: 175# No Perl scripts right now:
172# 176#
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index db6adecf46f1..416538248a4b 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -41,7 +41,7 @@ static u64 user_interval = ULLONG_MAX;
41static u64 default_interval = 0; 41static u64 default_interval = 0;
42 42
43static unsigned int page_size; 43static unsigned int page_size;
44static unsigned int mmap_pages = 128; 44static unsigned int mmap_pages = UINT_MAX;
45static unsigned int user_freq = UINT_MAX; 45static unsigned int user_freq = UINT_MAX;
46static int freq = 1000; 46static int freq = 1000;
47static int output; 47static int output;
@@ -163,6 +163,7 @@ static void config_attr(struct perf_evsel *evsel, struct perf_evlist *evlist)
163 struct perf_event_attr *attr = &evsel->attr; 163 struct perf_event_attr *attr = &evsel->attr;
164 int track = !evsel->idx; /* only the first counter needs these */ 164 int track = !evsel->idx; /* only the first counter needs these */
165 165
166 attr->inherit = !no_inherit;
166 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 167 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
167 PERF_FORMAT_TOTAL_TIME_RUNNING | 168 PERF_FORMAT_TOTAL_TIME_RUNNING |
168 PERF_FORMAT_ID; 169 PERF_FORMAT_ID;
@@ -251,6 +252,9 @@ static void open_counters(struct perf_evlist *evlist)
251{ 252{
252 struct perf_evsel *pos; 253 struct perf_evsel *pos;
253 254
255 if (evlist->cpus->map[0] < 0)
256 no_inherit = true;
257
254 list_for_each_entry(pos, &evlist->entries, node) { 258 list_for_each_entry(pos, &evlist->entries, node) {
255 struct perf_event_attr *attr = &pos->attr; 259 struct perf_event_attr *attr = &pos->attr;
256 /* 260 /*
@@ -271,8 +275,7 @@ static void open_counters(struct perf_evlist *evlist)
271retry_sample_id: 275retry_sample_id:
272 attr->sample_id_all = sample_id_all_avail ? 1 : 0; 276 attr->sample_id_all = sample_id_all_avail ? 1 : 0;
273try_again: 277try_again:
274 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group, 278 if (perf_evsel__open(pos, evlist->cpus, evlist->threads, group) < 0) {
275 !no_inherit) < 0) {
276 int err = errno; 279 int err = errno;
277 280
278 if (err == EPERM || err == EACCES) { 281 if (err == EPERM || err == EACCES) {
@@ -513,6 +516,10 @@ static int __cmd_record(int argc, const char **argv)
513 if (have_tracepoints(&evsel_list->entries)) 516 if (have_tracepoints(&evsel_list->entries))
514 perf_header__set_feat(&session->header, HEADER_TRACE_INFO); 517 perf_header__set_feat(&session->header, HEADER_TRACE_INFO);
515 518
519 /* 512 kiB: default amount of unprivileged mlocked memory */
520 if (mmap_pages == UINT_MAX)
521 mmap_pages = (512 * 1024) / page_size;
522
516 if (forks) { 523 if (forks) {
517 child_pid = fork(); 524 child_pid = fork();
518 if (child_pid < 0) { 525 if (child_pid < 0) {
diff --git a/tools/perf/builtin-stat.c b/tools/perf/builtin-stat.c
index e2109f9b43eb..03f0e45f1479 100644
--- a/tools/perf/builtin-stat.c
+++ b/tools/perf/builtin-stat.c
@@ -167,16 +167,17 @@ static int create_perf_stat_counter(struct perf_evsel *evsel)
167 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED | 167 attr->read_format = PERF_FORMAT_TOTAL_TIME_ENABLED |
168 PERF_FORMAT_TOTAL_TIME_RUNNING; 168 PERF_FORMAT_TOTAL_TIME_RUNNING;
169 169
170 attr->inherit = !no_inherit;
171
170 if (system_wide) 172 if (system_wide)
171 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false, false); 173 return perf_evsel__open_per_cpu(evsel, evsel_list->cpus, false);
172 174
173 attr->inherit = !no_inherit;
174 if (target_pid == -1 && target_tid == -1) { 175 if (target_pid == -1 && target_tid == -1) {
175 attr->disabled = 1; 176 attr->disabled = 1;
176 attr->enable_on_exec = 1; 177 attr->enable_on_exec = 1;
177 } 178 }
178 179
179 return perf_evsel__open_per_thread(evsel, evsel_list->threads, false, false); 180 return perf_evsel__open_per_thread(evsel, evsel_list->threads, false);
180} 181}
181 182
182/* 183/*
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 1b2106c58f66..11e3c8458362 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -290,7 +290,7 @@ static int test__open_syscall_event(void)
290 goto out_thread_map_delete; 290 goto out_thread_map_delete;
291 } 291 }
292 292
293 if (perf_evsel__open_per_thread(evsel, threads, false, false) < 0) { 293 if (perf_evsel__open_per_thread(evsel, threads, false) < 0) {
294 pr_debug("failed to open counter: %s, " 294 pr_debug("failed to open counter: %s, "
295 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 295 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
296 strerror(errno)); 296 strerror(errno));
@@ -303,7 +303,7 @@ static int test__open_syscall_event(void)
303 } 303 }
304 304
305 if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) { 305 if (perf_evsel__read_on_cpu(evsel, 0, 0) < 0) {
306 pr_debug("perf_evsel__open_read_on_cpu\n"); 306 pr_debug("perf_evsel__read_on_cpu\n");
307 goto out_close_fd; 307 goto out_close_fd;
308 } 308 }
309 309
@@ -365,7 +365,7 @@ static int test__open_syscall_event_on_all_cpus(void)
365 goto out_thread_map_delete; 365 goto out_thread_map_delete;
366 } 366 }
367 367
368 if (perf_evsel__open(evsel, cpus, threads, false, false) < 0) { 368 if (perf_evsel__open(evsel, cpus, threads, false) < 0) {
369 pr_debug("failed to open counter: %s, " 369 pr_debug("failed to open counter: %s, "
370 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 370 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
371 strerror(errno)); 371 strerror(errno));
@@ -418,7 +418,7 @@ static int test__open_syscall_event_on_all_cpus(void)
418 continue; 418 continue;
419 419
420 if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) { 420 if (perf_evsel__read_on_cpu(evsel, cpu, 0) < 0) {
421 pr_debug("perf_evsel__open_read_on_cpu\n"); 421 pr_debug("perf_evsel__read_on_cpu\n");
422 err = -1; 422 err = -1;
423 break; 423 break;
424 } 424 }
@@ -529,7 +529,7 @@ static int test__basic_mmap(void)
529 529
530 perf_evlist__add(evlist, evsels[i]); 530 perf_evlist__add(evlist, evsels[i]);
531 531
532 if (perf_evsel__open(evsels[i], cpus, threads, false, false) < 0) { 532 if (perf_evsel__open(evsels[i], cpus, threads, false) < 0) {
533 pr_debug("failed to open counter: %s, " 533 pr_debug("failed to open counter: %s, "
534 "tweak /proc/sys/kernel/perf_event_paranoid?\n", 534 "tweak /proc/sys/kernel/perf_event_paranoid?\n",
535 strerror(errno)); 535 strerror(errno));
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index fc1273e976c5..7e3d6e310bf8 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -845,9 +845,10 @@ static void start_counters(struct perf_evlist *evlist)
845 } 845 }
846 846
847 attr->mmap = 1; 847 attr->mmap = 1;
848 attr->inherit = inherit;
848try_again: 849try_again:
849 if (perf_evsel__open(counter, top.evlist->cpus, 850 if (perf_evsel__open(counter, top.evlist->cpus,
850 top.evlist->threads, group, inherit) < 0) { 851 top.evlist->threads, group) < 0) {
851 int err = errno; 852 int err = errno;
852 853
853 if (err == EPERM || err == EACCES) { 854 if (err == EPERM || err == EACCES) {
diff --git a/tools/perf/util/cgroup.c b/tools/perf/util/cgroup.c
index 9fea75535221..96bee5c46008 100644
--- a/tools/perf/util/cgroup.c
+++ b/tools/perf/util/cgroup.c
@@ -13,7 +13,7 @@ cgroupfs_find_mountpoint(char *buf, size_t maxlen)
13{ 13{
14 FILE *fp; 14 FILE *fp;
15 char mountpoint[MAX_PATH+1], tokens[MAX_PATH+1], type[MAX_PATH+1]; 15 char mountpoint[MAX_PATH+1], tokens[MAX_PATH+1], type[MAX_PATH+1];
16 char *token, *saved_ptr; 16 char *token, *saved_ptr = NULL;
17 int found = 0; 17 int found = 0;
18 18
19 fp = fopen("/proc/mounts", "r"); 19 fp = fopen("/proc/mounts", "r");
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index d852cefa20de..45da8d186b49 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -12,6 +12,7 @@
12#include "evlist.h" 12#include "evlist.h"
13#include "evsel.h" 13#include "evsel.h"
14#include "util.h" 14#include "util.h"
15#include "debug.h"
15 16
16#include <sys/mman.h> 17#include <sys/mman.h>
17 18
@@ -250,15 +251,19 @@ int perf_evlist__alloc_mmap(struct perf_evlist *evlist)
250 return evlist->mmap != NULL ? 0 : -ENOMEM; 251 return evlist->mmap != NULL ? 0 : -ENOMEM;
251} 252}
252 253
253static int __perf_evlist__mmap(struct perf_evlist *evlist, int cpu, int prot, 254static int __perf_evlist__mmap(struct perf_evlist *evlist, struct perf_evsel *evsel,
254 int mask, int fd) 255 int cpu, int prot, int mask, int fd)
255{ 256{
256 evlist->mmap[cpu].prev = 0; 257 evlist->mmap[cpu].prev = 0;
257 evlist->mmap[cpu].mask = mask; 258 evlist->mmap[cpu].mask = mask;
258 evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot, 259 evlist->mmap[cpu].base = mmap(NULL, evlist->mmap_len, prot,
259 MAP_SHARED, fd, 0); 260 MAP_SHARED, fd, 0);
260 if (evlist->mmap[cpu].base == MAP_FAILED) 261 if (evlist->mmap[cpu].base == MAP_FAILED) {
262 if (evlist->cpus->map[cpu] == -1 && evsel->attr.inherit)
263 ui__warning("Inherit is not allowed on per-task "
264 "events using mmap.\n");
261 return -1; 265 return -1;
266 }
262 267
263 perf_evlist__add_pollfd(evlist, fd); 268 perf_evlist__add_pollfd(evlist, fd);
264 return 0; 269 return 0;
@@ -312,7 +317,8 @@ int perf_evlist__mmap(struct perf_evlist *evlist, int pages, bool overwrite)
312 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT, 317 if (ioctl(fd, PERF_EVENT_IOC_SET_OUTPUT,
313 FD(first_evsel, cpu, 0)) != 0) 318 FD(first_evsel, cpu, 0)) != 0)
314 goto out_unmap; 319 goto out_unmap;
315 } else if (__perf_evlist__mmap(evlist, cpu, prot, mask, fd) < 0) 320 } else if (__perf_evlist__mmap(evlist, evsel, cpu,
321 prot, mask, fd) < 0)
316 goto out_unmap; 322 goto out_unmap;
317 323
318 if ((evsel->attr.read_format & PERF_FORMAT_ID) && 324 if ((evsel->attr.read_format & PERF_FORMAT_ID) &&
diff --git a/tools/perf/util/evsel.c b/tools/perf/util/evsel.c
index 662596afd7f1..d6fd59beb860 100644
--- a/tools/perf/util/evsel.c
+++ b/tools/perf/util/evsel.c
@@ -175,7 +175,7 @@ int __perf_evsel__read(struct perf_evsel *evsel,
175} 175}
176 176
177static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 177static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
178 struct thread_map *threads, bool group, bool inherit) 178 struct thread_map *threads, bool group)
179{ 179{
180 int cpu, thread; 180 int cpu, thread;
181 unsigned long flags = 0; 181 unsigned long flags = 0;
@@ -192,19 +192,6 @@ static int __perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
192 192
193 for (cpu = 0; cpu < cpus->nr; cpu++) { 193 for (cpu = 0; cpu < cpus->nr; cpu++) {
194 int group_fd = -1; 194 int group_fd = -1;
195 /*
196 * Don't allow mmap() of inherited per-task counters. This
197 * would create a performance issue due to all children writing
198 * to the same buffer.
199 *
200 * FIXME:
201 * Proper fix is not to pass 'inherit' to perf_evsel__open*,
202 * but a 'flags' parameter, with 'group' folded there as well,
203 * then introduce a PERF_O_{MMAP,GROUP,INHERIT} enum, and if
204 * O_MMAP is set, emit a warning if cpu < 0 and O_INHERIT is
205 * set. Lets go for the minimal fix first tho.
206 */
207 evsel->attr.inherit = (cpus->map[cpu] >= 0) && inherit;
208 195
209 for (thread = 0; thread < threads->nr; thread++) { 196 for (thread = 0; thread < threads->nr; thread++) {
210 197
@@ -253,7 +240,7 @@ static struct {
253}; 240};
254 241
255int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 242int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
256 struct thread_map *threads, bool group, bool inherit) 243 struct thread_map *threads, bool group)
257{ 244{
258 if (cpus == NULL) { 245 if (cpus == NULL) {
259 /* Work around old compiler warnings about strict aliasing */ 246 /* Work around old compiler warnings about strict aliasing */
@@ -263,19 +250,19 @@ int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
263 if (threads == NULL) 250 if (threads == NULL)
264 threads = &empty_thread_map.map; 251 threads = &empty_thread_map.map;
265 252
266 return __perf_evsel__open(evsel, cpus, threads, group, inherit); 253 return __perf_evsel__open(evsel, cpus, threads, group);
267} 254}
268 255
269int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 256int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
270 struct cpu_map *cpus, bool group, bool inherit) 257 struct cpu_map *cpus, bool group)
271{ 258{
272 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group, inherit); 259 return __perf_evsel__open(evsel, cpus, &empty_thread_map.map, group);
273} 260}
274 261
275int perf_evsel__open_per_thread(struct perf_evsel *evsel, 262int perf_evsel__open_per_thread(struct perf_evsel *evsel,
276 struct thread_map *threads, bool group, bool inherit) 263 struct thread_map *threads, bool group)
277{ 264{
278 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group, inherit); 265 return __perf_evsel__open(evsel, &empty_cpu_map.map, threads, group);
279} 266}
280 267
281static int perf_event__parse_id_sample(const union perf_event *event, u64 type, 268static int perf_event__parse_id_sample(const union perf_event *event, u64 type,
diff --git a/tools/perf/util/evsel.h b/tools/perf/util/evsel.h
index 6710ab538342..f79bb2c09a6c 100644
--- a/tools/perf/util/evsel.h
+++ b/tools/perf/util/evsel.h
@@ -81,11 +81,11 @@ void perf_evsel__free_id(struct perf_evsel *evsel);
81void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads); 81void perf_evsel__close_fd(struct perf_evsel *evsel, int ncpus, int nthreads);
82 82
83int perf_evsel__open_per_cpu(struct perf_evsel *evsel, 83int perf_evsel__open_per_cpu(struct perf_evsel *evsel,
84 struct cpu_map *cpus, bool group, bool inherit); 84 struct cpu_map *cpus, bool group);
85int perf_evsel__open_per_thread(struct perf_evsel *evsel, 85int perf_evsel__open_per_thread(struct perf_evsel *evsel,
86 struct thread_map *threads, bool group, bool inherit); 86 struct thread_map *threads, bool group);
87int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus, 87int perf_evsel__open(struct perf_evsel *evsel, struct cpu_map *cpus,
88 struct thread_map *threads, bool group, bool inherit); 88 struct thread_map *threads, bool group);
89 89
90#define perf_evsel__match(evsel, t, c) \ 90#define perf_evsel__match(evsel, t, c) \
91 (evsel->attr.type == PERF_TYPE_##t && \ 91 (evsel->attr.type == PERF_TYPE_##t && \
diff --git a/tools/perf/util/probe-event.c b/tools/perf/util/probe-event.c
index 5ddee66020a7..f0223166e761 100644
--- a/tools/perf/util/probe-event.c
+++ b/tools/perf/util/probe-event.c
@@ -234,7 +234,6 @@ static int try_to_find_probe_trace_events(struct perf_probe_event *pev,
234 234
235 /* Searching trace events corresponding to probe event */ 235 /* Searching trace events corresponding to probe event */
236 ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs); 236 ntevs = find_probe_trace_events(fd, pev, tevs, max_tevs);
237 close(fd);
238 237
239 if (ntevs > 0) { /* Succeeded to find trace events */ 238 if (ntevs > 0) { /* Succeeded to find trace events */
240 pr_debug("find %d probe_trace_events.\n", ntevs); 239 pr_debug("find %d probe_trace_events.\n", ntevs);
@@ -388,7 +387,6 @@ int show_line_range(struct line_range *lr, const char *module)
388 } 387 }
389 388
390 ret = find_line_range(fd, lr); 389 ret = find_line_range(fd, lr);
391 close(fd);
392 if (ret == 0) { 390 if (ret == 0) {
393 pr_warning("Specified source line is not found.\n"); 391 pr_warning("Specified source line is not found.\n");
394 return -ENOENT; 392 return -ENOENT;
@@ -512,19 +510,18 @@ int show_available_vars(struct perf_probe_event *pevs, int npevs,
512 if (ret < 0) 510 if (ret < 0)
513 return ret; 511 return ret;
514 512
515 fd = open_vmlinux(module);
516 if (fd < 0) {
517 pr_warning("Failed to open debug information file.\n");
518 return fd;
519 }
520
521 setup_pager(); 513 setup_pager();
522 514
523 for (i = 0; i < npevs && ret >= 0; i++) 515 for (i = 0; i < npevs && ret >= 0; i++) {
516 fd = open_vmlinux(module);
517 if (fd < 0) {
518 pr_warning("Failed to open debug information file.\n");
519 ret = fd;
520 break;
521 }
524 ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter, 522 ret = show_available_vars_at(fd, &pevs[i], max_vls, _filter,
525 externs); 523 externs);
526 524 }
527 close(fd);
528 return ret; 525 return ret;
529} 526}
530 527
diff --git a/tools/perf/util/probe-finder.c b/tools/perf/util/probe-finder.c
index ff416b85f7e8..a7c7145a8d4f 100644
--- a/tools/perf/util/probe-finder.c
+++ b/tools/perf/util/probe-finder.c
@@ -273,6 +273,25 @@ static const char *cu_get_comp_dir(Dwarf_Die *cu_die)
273 return dwarf_formstring(&attr); 273 return dwarf_formstring(&attr);
274} 274}
275 275
276/* Get a line number and file name for given address */
277static int cu_find_lineinfo(Dwarf_Die *cudie, unsigned long addr,
278 const char **fname, int *lineno)
279{
280 Dwarf_Line *line;
281 Dwarf_Addr laddr;
282
283 line = dwarf_getsrc_die(cudie, (Dwarf_Addr)addr);
284 if (line && dwarf_lineaddr(line, &laddr) == 0 &&
285 addr == (unsigned long)laddr && dwarf_lineno(line, lineno) == 0) {
286 *fname = dwarf_linesrc(line, NULL, NULL);
287 if (!*fname)
288 /* line number is useless without filename */
289 *lineno = 0;
290 }
291
292 return *lineno ?: -ENOENT;
293}
294
276/* Compare diename and tname */ 295/* Compare diename and tname */
277static bool die_compare_name(Dwarf_Die *dw_die, const char *tname) 296static bool die_compare_name(Dwarf_Die *dw_die, const char *tname)
278{ 297{
@@ -497,7 +516,20 @@ static int __die_find_inline_cb(Dwarf_Die *die_mem, void *data)
497static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr, 516static Dwarf_Die *die_find_inlinefunc(Dwarf_Die *sp_die, Dwarf_Addr addr,
498 Dwarf_Die *die_mem) 517 Dwarf_Die *die_mem)
499{ 518{
500 return die_find_child(sp_die, __die_find_inline_cb, &addr, die_mem); 519 Dwarf_Die tmp_die;
520
521 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr, &tmp_die);
522 if (!sp_die)
523 return NULL;
524
525 /* Inlined function could be recursive. Trace it until fail */
526 while (sp_die) {
527 memcpy(die_mem, sp_die, sizeof(Dwarf_Die));
528 sp_die = die_find_child(sp_die, __die_find_inline_cb, &addr,
529 &tmp_die);
530 }
531
532 return die_mem;
501} 533}
502 534
503/* Walker on lines (Note: line number will not be sorted) */ 535/* Walker on lines (Note: line number will not be sorted) */
@@ -1395,6 +1427,10 @@ static int probe_point_search_cb(Dwarf_Die *sp_die, void *data)
1395 !die_compare_name(sp_die, pp->function)) 1427 !die_compare_name(sp_die, pp->function))
1396 return DWARF_CB_OK; 1428 return DWARF_CB_OK;
1397 1429
1430 /* Check declared file */
1431 if (pp->file && strtailcmp(pp->file, dwarf_decl_file(sp_die)))
1432 return DWARF_CB_OK;
1433
1398 pf->fname = dwarf_decl_file(sp_die); 1434 pf->fname = dwarf_decl_file(sp_die);
1399 if (pp->line) { /* Function relative line */ 1435 if (pp->line) { /* Function relative line */
1400 dwarf_decl_line(sp_die, &pf->lno); 1436 dwarf_decl_line(sp_die, &pf->lno);
@@ -1483,6 +1519,7 @@ static int find_probes(int fd, struct probe_finder *pf)
1483 if (!dbg) { 1519 if (!dbg) {
1484 pr_warning("No debug information found in the vmlinux - " 1520 pr_warning("No debug information found in the vmlinux - "
1485 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1521 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
1522 close(fd); /* Without dwfl_end(), fd isn't closed. */
1486 return -EBADF; 1523 return -EBADF;
1487 } 1524 }
1488 1525
@@ -1741,11 +1778,9 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1741 Dwarf_Die cudie, spdie, indie; 1778 Dwarf_Die cudie, spdie, indie;
1742 Dwarf *dbg = NULL; 1779 Dwarf *dbg = NULL;
1743 Dwfl *dwfl = NULL; 1780 Dwfl *dwfl = NULL;
1744 Dwarf_Line *line; 1781 Dwarf_Addr _addr, baseaddr, bias = 0;
1745 Dwarf_Addr laddr, eaddr, bias = 0; 1782 const char *fname = NULL, *func = NULL, *tmp;
1746 const char *tmp; 1783 int baseline = 0, lineno = 0, ret = 0;
1747 int lineno, ret = 0;
1748 bool found = false;
1749 1784
1750 /* Open the live linux kernel */ 1785 /* Open the live linux kernel */
1751 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias); 1786 dbg = dwfl_init_live_kernel_dwarf(addr, &dwfl, &bias);
@@ -1766,68 +1801,79 @@ int find_perf_probe_point(unsigned long addr, struct perf_probe_point *ppt)
1766 goto end; 1801 goto end;
1767 } 1802 }
1768 1803
1769 /* Find a corresponding line */ 1804 /* Find a corresponding line (filename and lineno) */
1770 line = dwarf_getsrc_die(&cudie, (Dwarf_Addr)addr); 1805 cu_find_lineinfo(&cudie, addr, &fname, &lineno);
1771 if (line) { 1806 /* Don't care whether it failed or not */
1772 if (dwarf_lineaddr(line, &laddr) == 0 &&
1773 (Dwarf_Addr)addr == laddr &&
1774 dwarf_lineno(line, &lineno) == 0) {
1775 tmp = dwarf_linesrc(line, NULL, NULL);
1776 if (tmp) {
1777 ppt->line = lineno;
1778 ppt->file = strdup(tmp);
1779 if (ppt->file == NULL) {
1780 ret = -ENOMEM;
1781 goto end;
1782 }
1783 found = true;
1784 }
1785 }
1786 }
1787 1807
1788 /* Find a corresponding function */ 1808 /* Find a corresponding function (name, baseline and baseaddr) */
1789 if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) { 1809 if (die_find_real_subprogram(&cudie, (Dwarf_Addr)addr, &spdie)) {
1810 /* Get function entry information */
1790 tmp = dwarf_diename(&spdie); 1811 tmp = dwarf_diename(&spdie);
1791 if (!tmp || dwarf_entrypc(&spdie, &eaddr) != 0) 1812 if (!tmp ||
1792 goto end; 1813 dwarf_entrypc(&spdie, &baseaddr) != 0 ||
1793 1814 dwarf_decl_line(&spdie, &baseline) != 0)
1794 if (ppt->line) { 1815 goto post;
1795 if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr, 1816 func = tmp;
1796 &indie)) { 1817
1797 /* addr in an inline function */ 1818 if (addr == (unsigned long)baseaddr)
1819 /* Function entry - Relative line number is 0 */
1820 lineno = baseline;
1821 else if (die_find_inlinefunc(&spdie, (Dwarf_Addr)addr,
1822 &indie)) {
1823 if (dwarf_entrypc(&indie, &_addr) == 0 &&
1824 _addr == addr)
1825 /*
1826 * addr is at an inline function entry.
1827 * In this case, lineno should be the call-site
1828 * line number.
1829 */
1830 lineno = die_get_call_lineno(&indie);
1831 else {
1832 /*
1833 * addr is in an inline function body.
1834 * Since lineno points one of the lines
1835 * of the inline function, baseline should
1836 * be the entry line of the inline function.
1837 */
1798 tmp = dwarf_diename(&indie); 1838 tmp = dwarf_diename(&indie);
1799 if (!tmp) 1839 if (tmp &&
1800 goto end; 1840 dwarf_decl_line(&spdie, &baseline) == 0)
1801 ret = dwarf_decl_line(&indie, &lineno); 1841 func = tmp;
1802 } else {
1803 if (eaddr == addr) { /* Function entry */
1804 lineno = ppt->line;
1805 ret = 0;
1806 } else
1807 ret = dwarf_decl_line(&spdie, &lineno);
1808 }
1809 if (ret == 0) {
1810 /* Make a relative line number */
1811 ppt->line -= lineno;
1812 goto found;
1813 } 1842 }
1814 } 1843 }
1815 /* We don't have a line number, let's use offset */ 1844 }
1816 ppt->offset = addr - (unsigned long)eaddr; 1845
1817found: 1846post:
1818 ppt->function = strdup(tmp); 1847 /* Make a relative line number or an offset */
1848 if (lineno)
1849 ppt->line = lineno - baseline;
1850 else if (func)
1851 ppt->offset = addr - (unsigned long)baseaddr;
1852
1853 /* Duplicate strings */
1854 if (func) {
1855 ppt->function = strdup(func);
1819 if (ppt->function == NULL) { 1856 if (ppt->function == NULL) {
1820 ret = -ENOMEM; 1857 ret = -ENOMEM;
1821 goto end; 1858 goto end;
1822 } 1859 }
1823 found = true;
1824 } 1860 }
1825 1861 if (fname) {
1862 ppt->file = strdup(fname);
1863 if (ppt->file == NULL) {
1864 if (ppt->function) {
1865 free(ppt->function);
1866 ppt->function = NULL;
1867 }
1868 ret = -ENOMEM;
1869 goto end;
1870 }
1871 }
1826end: 1872end:
1827 if (dwfl) 1873 if (dwfl)
1828 dwfl_end(dwfl); 1874 dwfl_end(dwfl);
1829 if (ret >= 0) 1875 if (ret == 0 && (fname || func))
1830 ret = found ? 1 : 0; 1876 ret = 1; /* Found a point */
1831 return ret; 1877 return ret;
1832} 1878}
1833 1879
@@ -1895,6 +1941,10 @@ static int line_range_search_cb(Dwarf_Die *sp_die, void *data)
1895 struct line_finder *lf = param->data; 1941 struct line_finder *lf = param->data;
1896 struct line_range *lr = lf->lr; 1942 struct line_range *lr = lf->lr;
1897 1943
1944 /* Check declared file */
1945 if (lr->file && strtailcmp(lr->file, dwarf_decl_file(sp_die)))
1946 return DWARF_CB_OK;
1947
1898 if (dwarf_tag(sp_die) == DW_TAG_subprogram && 1948 if (dwarf_tag(sp_die) == DW_TAG_subprogram &&
1899 die_compare_name(sp_die, lr->function)) { 1949 die_compare_name(sp_die, lr->function)) {
1900 lf->fname = dwarf_decl_file(sp_die); 1950 lf->fname = dwarf_decl_file(sp_die);
@@ -1947,6 +1997,7 @@ int find_line_range(int fd, struct line_range *lr)
1947 if (!dbg) { 1997 if (!dbg) {
1948 pr_warning("No debug information found in the vmlinux - " 1998 pr_warning("No debug information found in the vmlinux - "
1949 "please rebuild with CONFIG_DEBUG_INFO=y.\n"); 1999 "please rebuild with CONFIG_DEBUG_INFO=y.\n");
2000 close(fd); /* Without dwfl_end(), fd isn't closed. */
1950 return -EBADF; 2001 return -EBADF;
1951 } 2002 }
1952 2003
diff --git a/tools/perf/util/python.c b/tools/perf/util/python.c
index a9f2d7e1204d..f5e38451fdc5 100644
--- a/tools/perf/util/python.c
+++ b/tools/perf/util/python.c
@@ -498,11 +498,11 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
498 struct cpu_map *cpus = NULL; 498 struct cpu_map *cpus = NULL;
499 struct thread_map *threads = NULL; 499 struct thread_map *threads = NULL;
500 PyObject *pcpus = NULL, *pthreads = NULL; 500 PyObject *pcpus = NULL, *pthreads = NULL;
501 int group = 0, overwrite = 0; 501 int group = 0, inherit = 0;
502 static char *kwlist[] = {"cpus", "threads", "group", "overwrite", NULL, NULL}; 502 static char *kwlist[] = {"cpus", "threads", "group", "inherit", NULL, NULL};
503 503
504 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist, 504 if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOii", kwlist,
505 &pcpus, &pthreads, &group, &overwrite)) 505 &pcpus, &pthreads, &group, &inherit))
506 return NULL; 506 return NULL;
507 507
508 if (pthreads != NULL) 508 if (pthreads != NULL)
@@ -511,7 +511,8 @@ static PyObject *pyrf_evsel__open(struct pyrf_evsel *pevsel,
511 if (pcpus != NULL) 511 if (pcpus != NULL)
512 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus; 512 cpus = ((struct pyrf_cpu_map *)pcpus)->cpus;
513 513
514 if (perf_evsel__open(evsel, cpus, threads, group, overwrite) < 0) { 514 evsel->attr.inherit = inherit;
515 if (perf_evsel__open(evsel, cpus, threads, group) < 0) {
515 PyErr_SetFromErrno(PyExc_OSError); 516 PyErr_SetFromErrno(PyExc_OSError);
516 return NULL; 517 return NULL;
517 } 518 }
diff --git a/tools/perf/util/setup.py b/tools/perf/util/setup.py
index e24ffadb20b2..bbc982f5dd8b 100644
--- a/tools/perf/util/setup.py
+++ b/tools/perf/util/setup.py
@@ -1,13 +1,18 @@
1#!/usr/bin/python2 1#!/usr/bin/python2
2 2
3from distutils.core import setup, Extension 3from distutils.core import setup, Extension
4from os import getenv
5
6cflags = ['-fno-strict-aliasing', '-Wno-write-strings']
7cflags += getenv('CFLAGS', '').split()
4 8
5perf = Extension('perf', 9perf = Extension('perf',
6 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c', 10 sources = ['util/python.c', 'util/ctype.c', 'util/evlist.c',
7 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c', 11 'util/evsel.c', 'util/cpumap.c', 'util/thread_map.c',
8 'util/util.c', 'util/xyarray.c', 'util/cgroup.c'], 12 'util/util.c', 'util/xyarray.c', 'util/cgroup.c'],
9 include_dirs = ['util/include'], 13 include_dirs = ['util/include'],
10 extra_compile_args = ['-fno-strict-aliasing', '-Wno-write-strings']) 14 extra_compile_args = cflags,
15 )
11 16
12setup(name='perf', 17setup(name='perf',
13 version='0.1', 18 version='0.1',
diff --git a/tools/perf/util/string.c b/tools/perf/util/string.c
index 8fc0bd3a3a4a..b9a985dadd08 100644
--- a/tools/perf/util/string.c
+++ b/tools/perf/util/string.c
@@ -85,7 +85,7 @@ out:
85 85
86/* 86/*
87 * Helper function for splitting a string into an argv-like array. 87 * Helper function for splitting a string into an argv-like array.
88 * originaly copied from lib/argv_split.c 88 * originally copied from lib/argv_split.c
89 */ 89 */
90static const char *skip_sep(const char *cp) 90static const char *skip_sep(const char *cp)
91{ 91{
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 8f73907a959e..f06c10f092ba 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -2406,6 +2406,8 @@ int symbol__init(void)
2406 if (symbol_conf.initialized) 2406 if (symbol_conf.initialized)
2407 return 0; 2407 return 0;
2408 2408
2409 symbol_conf.priv_size = ALIGN(symbol_conf.priv_size, sizeof(u64));
2410
2409 elf_version(EV_CURRENT); 2411 elf_version(EV_CURRENT);
2410 if (symbol_conf.sort_by_name) 2412 if (symbol_conf.sort_by_name)
2411 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) - 2413 symbol_conf.priv_size += (sizeof(struct symbol_name_rb_node) -
diff --git a/tools/perf/util/ui/browsers/annotate.c b/tools/perf/util/ui/browsers/annotate.c
index 8c17a8730e4a..15633d608133 100644
--- a/tools/perf/util/ui/browsers/annotate.c
+++ b/tools/perf/util/ui/browsers/annotate.c
@@ -256,10 +256,9 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
256 int refresh) 256 int refresh)
257{ 257{
258 struct objdump_line *pos, *n; 258 struct objdump_line *pos, *n;
259 struct annotation *notes = symbol__annotation(sym); 259 struct annotation *notes;
260 struct annotate_browser browser = { 260 struct annotate_browser browser = {
261 .b = { 261 .b = {
262 .entries = &notes->src->source,
263 .refresh = ui_browser__list_head_refresh, 262 .refresh = ui_browser__list_head_refresh,
264 .seek = ui_browser__list_head_seek, 263 .seek = ui_browser__list_head_seek,
265 .write = annotate_browser__write, 264 .write = annotate_browser__write,
@@ -281,6 +280,8 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
281 280
282 ui_helpline__push("Press <- or ESC to exit"); 281 ui_helpline__push("Press <- or ESC to exit");
283 282
283 notes = symbol__annotation(sym);
284
284 list_for_each_entry(pos, &notes->src->source, node) { 285 list_for_each_entry(pos, &notes->src->source, node) {
285 struct objdump_line_rb_node *rbpos; 286 struct objdump_line_rb_node *rbpos;
286 size_t line_len = strlen(pos->line); 287 size_t line_len = strlen(pos->line);
@@ -291,6 +292,7 @@ int symbol__tui_annotate(struct symbol *sym, struct map *map, int evidx,
291 rbpos->idx = browser.b.nr_entries++; 292 rbpos->idx = browser.b.nr_entries++;
292 } 293 }
293 294
295 browser.b.entries = &notes->src->source,
294 browser.b.width += 18; /* Percentage */ 296 browser.b.width += 18; /* Percentage */
295 ret = annotate_browser__run(&browser, evidx, refresh); 297 ret = annotate_browser__run(&browser, evidx, refresh);
296 list_for_each_entry_safe(pos, n, &notes->src->source, node) { 298 list_for_each_entry_safe(pos, n, &notes->src->source, node) {
diff --git a/tools/perf/util/ui/browsers/hists.c b/tools/perf/util/ui/browsers/hists.c
index 798efdca3ead..5d767c622dfc 100644
--- a/tools/perf/util/ui/browsers/hists.c
+++ b/tools/perf/util/ui/browsers/hists.c
@@ -851,7 +851,7 @@ static int perf_evsel__hists_browse(struct perf_evsel *evsel,
851 goto out_free_stack; 851 goto out_free_stack;
852 case 'a': 852 case 'a':
853 if (browser->selection == NULL || 853 if (browser->selection == NULL ||
854 browser->selection->map == NULL || 854 browser->selection->sym == NULL ||
855 browser->selection->map->dso->annotate_warned) 855 browser->selection->map->dso->annotate_warned)
856 continue; 856 continue;
857 goto do_annotate; 857 goto do_annotate;