aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorIngo Molnar <mingo@kernel.org>2014-07-28 04:09:03 -0400
committerIngo Molnar <mingo@kernel.org>2014-07-28 04:09:03 -0400
commit068f1d3f45546f4bb24e9be67231db1be296f0c8 (patch)
treeedd13e6585cc2dbd301760193fd854d653032e34 /tools
parentf4be073db878d0e79f74bc36f1642847781791a0 (diff)
parentdcabb507fd3a2b19aed6b4068e2a954f5fd8de45 (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: Infrastructure changes: o More prep work to support Intel PT: (Adrian Hunter) - Polishing 'script' BTS output - 'inject' can specify --kallsym - VDSO is per machine, not a global var - Expose data addr lookup functions previously private to 'script' - Large mmap fixes in events processing o Fix build on gcc 4.4.7 (Arnaldo Carvalho de Melo) o Event ordering fixes (Jiri Olsa) o Include standard stringify macros in power pc code (Sukadev Bhattiprolu) 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/Documentation/perf-inject.txt3
-rw-r--r--tools/perf/arch/powerpc/util/header.c4
-rw-r--r--tools/perf/arch/x86/util/tsc.c9
-rw-r--r--tools/perf/builtin-inject.c2
-rw-r--r--tools/perf/builtin-record.c7
-rw-r--r--tools/perf/builtin-script.c60
-rw-r--r--tools/perf/builtin-trace.c2
-rw-r--r--tools/perf/tests/perf-time-to-tsc.c9
-rw-r--r--tools/perf/util/cloexec.c9
-rw-r--r--tools/perf/util/dso.c70
-rw-r--r--tools/perf/util/dso.h25
-rw-r--r--tools/perf/util/event.c42
-rw-r--r--tools/perf/util/event.h10
-rw-r--r--tools/perf/util/header.c51
-rw-r--r--tools/perf/util/header.h2
-rw-r--r--tools/perf/util/machine.c58
-rw-r--r--tools/perf/util/machine.h8
-rw-r--r--tools/perf/util/map.c9
-rw-r--r--tools/perf/util/map.h5
-rw-r--r--tools/perf/util/session.c25
-rw-r--r--tools/perf/util/symbol-elf.c35
-rw-r--r--tools/perf/util/symbol-minimal.c21
-rw-r--r--tools/perf/util/symbol.h2
-rw-r--r--tools/perf/util/thread.c1
-rw-r--r--tools/perf/util/thread.h1
-rw-r--r--tools/perf/util/tsc.c5
-rw-r--r--tools/perf/util/tsc.h1
-rw-r--r--tools/perf/util/vdso.c96
-rw-r--r--tools/perf/util/vdso.h13
29 files changed, 470 insertions, 115 deletions
diff --git a/tools/perf/Documentation/perf-inject.txt b/tools/perf/Documentation/perf-inject.txt
index a00a34276c54..dc7442cf3d7f 100644
--- a/tools/perf/Documentation/perf-inject.txt
+++ b/tools/perf/Documentation/perf-inject.txt
@@ -41,6 +41,9 @@ OPTIONS
41 tasks slept. sched_switch contains a callchain where a task slept and 41 tasks slept. sched_switch contains a callchain where a task slept and
42 sched_stat contains a timeslice how long a task slept. 42 sched_stat contains a timeslice how long a task slept.
43 43
44--kallsyms=<file>::
45 kallsyms pathname
46
44SEE ALSO 47SEE ALSO
45-------- 48--------
46linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1] 49linkperf:perf-record[1], linkperf:perf-report[1], linkperf:perf-archive[1]
diff --git a/tools/perf/arch/powerpc/util/header.c b/tools/perf/arch/powerpc/util/header.c
index 2f7073d107fd..6c1b8a75db09 100644
--- a/tools/perf/arch/powerpc/util/header.c
+++ b/tools/perf/arch/powerpc/util/header.c
@@ -5,9 +5,7 @@
5#include <string.h> 5#include <string.h>
6 6
7#include "../../util/header.h" 7#include "../../util/header.h"
8 8#include "../../util/util.h"
9#define __stringify_1(x) #x
10#define __stringify(x) __stringify_1(x)
11 9
12#define mfspr(rn) ({unsigned long rval; \ 10#define mfspr(rn) ({unsigned long rval; \
13 asm volatile("mfspr %0," __stringify(rn) \ 11 asm volatile("mfspr %0," __stringify(rn) \
diff --git a/tools/perf/arch/x86/util/tsc.c b/tools/perf/arch/x86/util/tsc.c
index 3655f24c3170..fd2868490d00 100644
--- a/tools/perf/arch/x86/util/tsc.c
+++ b/tools/perf/arch/x86/util/tsc.c
@@ -37,3 +37,12 @@ int perf_read_tsc_conversion(const struct perf_event_mmap_page *pc,
37 37
38 return 0; 38 return 0;
39} 39}
40
41u64 rdtsc(void)
42{
43 unsigned int low, high;
44
45 asm volatile("rdtsc" : "=a" (low), "=d" (high));
46
47 return low | ((u64)high) << 32;
48}
diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c
index cf6a605a13e8..9a02807387d6 100644
--- a/tools/perf/builtin-inject.c
+++ b/tools/perf/builtin-inject.c
@@ -439,6 +439,8 @@ int cmd_inject(int argc, const char **argv, const char *prefix __maybe_unused)
439 "where and how long tasks slept"), 439 "where and how long tasks slept"),
440 OPT_INCR('v', "verbose", &verbose, 440 OPT_INCR('v', "verbose", &verbose,
441 "be more verbose (show build ids, etc)"), 441 "be more verbose (show build ids, etc)"),
442 OPT_STRING(0, "kallsyms", &symbol_conf.kallsyms_name, "file",
443 "kallsyms pathname"),
442 OPT_END() 444 OPT_END()
443 }; 445 };
444 const char * const inject_usage[] = { 446 const char * const inject_usage[] = {
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c
index 378b85b731a7..4869050e7194 100644
--- a/tools/perf/builtin-record.c
+++ b/tools/perf/builtin-record.c
@@ -238,6 +238,7 @@ static struct perf_event_header finished_round_event = {
238 238
239static int record__mmap_read_all(struct record *rec) 239static int record__mmap_read_all(struct record *rec)
240{ 240{
241 u64 bytes_written = rec->bytes_written;
241 int i; 242 int i;
242 int rc = 0; 243 int rc = 0;
243 244
@@ -250,7 +251,11 @@ static int record__mmap_read_all(struct record *rec)
250 } 251 }
251 } 252 }
252 253
253 if (perf_header__has_feat(&rec->session->header, HEADER_TRACING_DATA)) 254 /*
255 * Mark the round finished in case we wrote
256 * at least one event.
257 */
258 if (bytes_written != rec->bytes_written)
254 rc = record__write(rec, &finished_round_event, sizeof(finished_round_event)); 259 rc = record__write(rec, &finished_round_event, sizeof(finished_round_event));
255 260
256out: 261out:
diff --git a/tools/perf/builtin-script.c b/tools/perf/builtin-script.c
index 9e9c91f5b7fa..f57035b89c15 100644
--- a/tools/perf/builtin-script.c
+++ b/tools/perf/builtin-script.c
@@ -358,27 +358,6 @@ static void print_sample_start(struct perf_sample *sample,
358 } 358 }
359} 359}
360 360
361static bool is_bts_event(struct perf_event_attr *attr)
362{
363 return ((attr->type == PERF_TYPE_HARDWARE) &&
364 (attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
365 (attr->sample_period == 1));
366}
367
368static bool sample_addr_correlates_sym(struct perf_event_attr *attr)
369{
370 if ((attr->type == PERF_TYPE_SOFTWARE) &&
371 ((attr->config == PERF_COUNT_SW_PAGE_FAULTS) ||
372 (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN) ||
373 (attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ)))
374 return true;
375
376 if (is_bts_event(attr))
377 return true;
378
379 return false;
380}
381
382static void print_sample_addr(union perf_event *event, 361static void print_sample_addr(union perf_event *event,
383 struct perf_sample *sample, 362 struct perf_sample *sample,
384 struct machine *machine, 363 struct machine *machine,
@@ -386,24 +365,13 @@ static void print_sample_addr(union perf_event *event,
386 struct perf_event_attr *attr) 365 struct perf_event_attr *attr)
387{ 366{
388 struct addr_location al; 367 struct addr_location al;
389 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
390 368
391 printf("%16" PRIx64, sample->addr); 369 printf("%16" PRIx64, sample->addr);
392 370
393 if (!sample_addr_correlates_sym(attr)) 371 if (!sample_addr_correlates_sym(attr))
394 return; 372 return;
395 373
396 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION, 374 perf_event__preprocess_sample_addr(event, sample, machine, thread, &al);
397 sample->addr, &al);
398 if (!al.map)
399 thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE,
400 sample->addr, &al);
401
402 al.cpu = sample->cpu;
403 al.sym = NULL;
404
405 if (al.map)
406 al.sym = map__find_symbol(al.map, al.addr, NULL);
407 375
408 if (PRINT_FIELD(SYM)) { 376 if (PRINT_FIELD(SYM)) {
409 printf(" "); 377 printf(" ");
@@ -427,25 +395,35 @@ static void print_sample_bts(union perf_event *event,
427 struct addr_location *al) 395 struct addr_location *al)
428{ 396{
429 struct perf_event_attr *attr = &evsel->attr; 397 struct perf_event_attr *attr = &evsel->attr;
398 bool print_srcline_last = false;
430 399
431 /* print branch_from information */ 400 /* print branch_from information */
432 if (PRINT_FIELD(IP)) { 401 if (PRINT_FIELD(IP)) {
433 if (!symbol_conf.use_callchain) 402 unsigned int print_opts = output[attr->type].print_ip_opts;
434 printf(" "); 403
435 else 404 if (symbol_conf.use_callchain && sample->callchain) {
436 printf("\n"); 405 printf("\n");
437 perf_evsel__print_ip(evsel, sample, al, 406 } else {
438 output[attr->type].print_ip_opts, 407 printf(" ");
408 if (print_opts & PRINT_IP_OPT_SRCLINE) {
409 print_srcline_last = true;
410 print_opts &= ~PRINT_IP_OPT_SRCLINE;
411 }
412 }
413 perf_evsel__print_ip(evsel, sample, al, print_opts,
439 PERF_MAX_STACK_DEPTH); 414 PERF_MAX_STACK_DEPTH);
440 } 415 }
441 416
442 printf(" => ");
443
444 /* print branch_to information */ 417 /* print branch_to information */
445 if (PRINT_FIELD(ADDR) || 418 if (PRINT_FIELD(ADDR) ||
446 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) && 419 ((evsel->attr.sample_type & PERF_SAMPLE_ADDR) &&
447 !output[attr->type].user_set)) 420 !output[attr->type].user_set)) {
421 printf(" => ");
448 print_sample_addr(event, sample, al->machine, thread, attr); 422 print_sample_addr(event, sample, al->machine, thread, attr);
423 }
424
425 if (print_srcline_last)
426 map__fprintf_srcline(al->map, al->addr, "\n ", stdout);
449 427
450 printf("\n"); 428 printf("\n");
451} 429}
diff --git a/tools/perf/builtin-trace.c b/tools/perf/builtin-trace.c
index c4a5a7d7b2cf..a6c375224f46 100644
--- a/tools/perf/builtin-trace.c
+++ b/tools/perf/builtin-trace.c
@@ -1994,10 +1994,10 @@ static int perf_evlist__add_pgfault(struct perf_evlist *evlist,
1994 struct perf_event_attr attr = { 1994 struct perf_event_attr attr = {
1995 .type = PERF_TYPE_SOFTWARE, 1995 .type = PERF_TYPE_SOFTWARE,
1996 .mmap_data = 1, 1996 .mmap_data = 1,
1997 .sample_period = 1,
1998 }; 1997 };
1999 1998
2000 attr.config = config; 1999 attr.config = config;
2000 attr.sample_period = 1;
2001 2001
2002 event_attr_init(&attr); 2002 event_attr_init(&attr);
2003 2003
diff --git a/tools/perf/tests/perf-time-to-tsc.c b/tools/perf/tests/perf-time-to-tsc.c
index 0372f6edca20..f238442b238a 100644
--- a/tools/perf/tests/perf-time-to-tsc.c
+++ b/tools/perf/tests/perf-time-to-tsc.c
@@ -25,15 +25,6 @@
25 } \ 25 } \
26} 26}
27 27
28static u64 rdtsc(void)
29{
30 unsigned int low, high;
31
32 asm volatile("rdtsc" : "=a" (low), "=d" (high));
33
34 return low | ((u64)high) << 32;
35}
36
37/** 28/**
38 * test__perf_time_to_tsc - test converting perf time to TSC. 29 * test__perf_time_to_tsc - test converting perf time to TSC.
39 * 30 *
diff --git a/tools/perf/util/cloexec.c b/tools/perf/util/cloexec.c
index c5d05ec17220..6a37be53a5d2 100644
--- a/tools/perf/util/cloexec.c
+++ b/tools/perf/util/cloexec.c
@@ -1,3 +1,4 @@
1#include <sched.h>
1#include "util.h" 2#include "util.h"
2#include "../perf.h" 3#include "../perf.h"
3#include "cloexec.h" 4#include "cloexec.h"
@@ -14,9 +15,13 @@ static int perf_flag_probe(void)
14 }; 15 };
15 int fd; 16 int fd;
16 int err; 17 int err;
18 int cpu = sched_getcpu();
19
20 if (cpu < 0)
21 cpu = 0;
17 22
18 /* check cloexec flag */ 23 /* check cloexec flag */
19 fd = sys_perf_event_open(&attr, 0, -1, -1, 24 fd = sys_perf_event_open(&attr, -1, cpu, -1,
20 PERF_FLAG_FD_CLOEXEC); 25 PERF_FLAG_FD_CLOEXEC);
21 err = errno; 26 err = errno;
22 27
@@ -30,7 +35,7 @@ static int perf_flag_probe(void)
30 err, strerror(err)); 35 err, strerror(err));
31 36
32 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */ 37 /* not supported, confirm error related to PERF_FLAG_FD_CLOEXEC */
33 fd = sys_perf_event_open(&attr, 0, -1, -1, 0); 38 fd = sys_perf_event_open(&attr, -1, cpu, -1, 0);
34 err = errno; 39 err = errno;
35 40
36 if (WARN_ONCE(fd < 0, 41 if (WARN_ONCE(fd < 0,
diff --git a/tools/perf/util/dso.c b/tools/perf/util/dso.c
index fc006fed8877..90d02c661dd4 100644
--- a/tools/perf/util/dso.c
+++ b/tools/perf/util/dso.c
@@ -216,7 +216,7 @@ static int open_dso(struct dso *dso, struct machine *machine)
216{ 216{
217 int fd = __open_dso(dso, machine); 217 int fd = __open_dso(dso, machine);
218 218
219 if (fd > 0) { 219 if (fd >= 0) {
220 dso__list_add(dso); 220 dso__list_add(dso);
221 /* 221 /*
222 * Check if we crossed the allowed number 222 * Check if we crossed the allowed number
@@ -331,26 +331,44 @@ int dso__data_fd(struct dso *dso, struct machine *machine)
331 }; 331 };
332 int i = 0; 332 int i = 0;
333 333
334 if (dso->data.status == DSO_DATA_STATUS_ERROR)
335 return -1;
336
334 if (dso->data.fd >= 0) 337 if (dso->data.fd >= 0)
335 return dso->data.fd; 338 goto out;
336 339
337 if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND) { 340 if (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND) {
338 dso->data.fd = open_dso(dso, machine); 341 dso->data.fd = open_dso(dso, machine);
339 return dso->data.fd; 342 goto out;
340 } 343 }
341 344
342 do { 345 do {
343 int fd;
344
345 dso->binary_type = binary_type_data[i++]; 346 dso->binary_type = binary_type_data[i++];
346 347
347 fd = open_dso(dso, machine); 348 dso->data.fd = open_dso(dso, machine);
348 if (fd >= 0) 349 if (dso->data.fd >= 0)
349 return dso->data.fd = fd; 350 goto out;
350 351
351 } while (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND); 352 } while (dso->binary_type != DSO_BINARY_TYPE__NOT_FOUND);
353out:
354 if (dso->data.fd >= 0)
355 dso->data.status = DSO_DATA_STATUS_OK;
356 else
357 dso->data.status = DSO_DATA_STATUS_ERROR;
352 358
353 return -EINVAL; 359 return dso->data.fd;
360}
361
362bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by)
363{
364 u32 flag = 1 << by;
365
366 if (dso->data.status_seen & flag)
367 return true;
368
369 dso->data.status_seen |= flag;
370
371 return false;
354} 372}
355 373
356static void 374static void
@@ -526,6 +544,28 @@ static int data_file_size(struct dso *dso)
526 return 0; 544 return 0;
527} 545}
528 546
547/**
548 * dso__data_size - Return dso data size
549 * @dso: dso object
550 * @machine: machine object
551 *
552 * Return: dso data size
553 */
554off_t dso__data_size(struct dso *dso, struct machine *machine)
555{
556 int fd;
557
558 fd = dso__data_fd(dso, machine);
559 if (fd < 0)
560 return fd;
561
562 if (data_file_size(dso))
563 return -1;
564
565 /* For now just estimate dso data size is close to file size */
566 return dso->data.file_size;
567}
568
529static ssize_t data_read_offset(struct dso *dso, u64 offset, 569static ssize_t data_read_offset(struct dso *dso, u64 offset,
530 u8 *data, ssize_t size) 570 u8 *data, ssize_t size)
531{ 571{
@@ -701,6 +741,7 @@ struct dso *dso__new(const char *name)
701 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; 741 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
702 dso->data.cache = RB_ROOT; 742 dso->data.cache = RB_ROOT;
703 dso->data.fd = -1; 743 dso->data.fd = -1;
744 dso->data.status = DSO_DATA_STATUS_UNKNOWN;
704 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND; 745 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
705 dso->binary_type = DSO_BINARY_TYPE__NOT_FOUND; 746 dso->binary_type = DSO_BINARY_TYPE__NOT_FOUND;
706 dso->is_64_bit = (sizeof(void *) == 8); 747 dso->is_64_bit = (sizeof(void *) == 8);
@@ -899,3 +940,14 @@ size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp)
899 940
900 return ret; 941 return ret;
901} 942}
943
944enum dso_type dso__type(struct dso *dso, struct machine *machine)
945{
946 int fd;
947
948 fd = dso__data_fd(dso, machine);
949 if (fd < 0)
950 return DSO__TYPE_UNKNOWN;
951
952 return dso__type_fd(fd);
953}
diff --git a/tools/perf/util/dso.h b/tools/perf/util/dso.h
index c239e86541a3..5e463c0964d4 100644
--- a/tools/perf/util/dso.h
+++ b/tools/perf/util/dso.h
@@ -5,6 +5,7 @@
5#include <linux/rbtree.h> 5#include <linux/rbtree.h>
6#include <stdbool.h> 6#include <stdbool.h>
7#include <linux/types.h> 7#include <linux/types.h>
8#include <linux/bitops.h>
8#include "map.h" 9#include "map.h"
9#include "build-id.h" 10#include "build-id.h"
10 11
@@ -40,6 +41,23 @@ enum dso_swap_type {
40 DSO_SWAP__YES, 41 DSO_SWAP__YES,
41}; 42};
42 43
44enum dso_data_status {
45 DSO_DATA_STATUS_ERROR = -1,
46 DSO_DATA_STATUS_UNKNOWN = 0,
47 DSO_DATA_STATUS_OK = 1,
48};
49
50enum dso_data_status_seen {
51 DSO_DATA_STATUS_SEEN_ITRACE,
52};
53
54enum dso_type {
55 DSO__TYPE_UNKNOWN,
56 DSO__TYPE_64BIT,
57 DSO__TYPE_32BIT,
58 DSO__TYPE_X32BIT,
59};
60
43#define DSO__SWAP(dso, type, val) \ 61#define DSO__SWAP(dso, type, val) \
44({ \ 62({ \
45 type ____r = val; \ 63 type ____r = val; \
@@ -104,6 +122,8 @@ struct dso {
104 struct { 122 struct {
105 struct rb_root cache; 123 struct rb_root cache;
106 int fd; 124 int fd;
125 int status;
126 u32 status_seen;
107 size_t file_size; 127 size_t file_size;
108 struct list_head open_entry; 128 struct list_head open_entry;
109 } data; 129 } data;
@@ -154,6 +174,7 @@ int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type t
154 * The dso__data_* external interface provides following functions: 174 * The dso__data_* external interface provides following functions:
155 * dso__data_fd 175 * dso__data_fd
156 * dso__data_close 176 * dso__data_close
177 * dso__data_size
157 * dso__data_read_offset 178 * dso__data_read_offset
158 * dso__data_read_addr 179 * dso__data_read_addr
159 * 180 *
@@ -191,11 +212,13 @@ int dso__read_binary_type_filename(const struct dso *dso, enum dso_binary_type t
191int dso__data_fd(struct dso *dso, struct machine *machine); 212int dso__data_fd(struct dso *dso, struct machine *machine);
192void dso__data_close(struct dso *dso); 213void dso__data_close(struct dso *dso);
193 214
215off_t dso__data_size(struct dso *dso, struct machine *machine);
194ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine, 216ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
195 u64 offset, u8 *data, ssize_t size); 217 u64 offset, u8 *data, ssize_t size);
196ssize_t dso__data_read_addr(struct dso *dso, struct map *map, 218ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
197 struct machine *machine, u64 addr, 219 struct machine *machine, u64 addr,
198 u8 *data, ssize_t size); 220 u8 *data, ssize_t size);
221bool dso__data_status_seen(struct dso *dso, enum dso_data_status_seen by);
199 222
200struct map *dso__new_map(const char *name); 223struct map *dso__new_map(const char *name);
201struct dso *dso__kernel_findnew(struct machine *machine, const char *name, 224struct dso *dso__kernel_findnew(struct machine *machine, const char *name,
@@ -230,4 +253,6 @@ static inline bool dso__is_kcore(struct dso *dso)
230 253
231void dso__free_a2l(struct dso *dso); 254void dso__free_a2l(struct dso *dso);
232 255
256enum dso_type dso__type(struct dso *dso, struct machine *machine);
257
233#endif /* __PERF_DSO */ 258#endif /* __PERF_DSO */
diff --git a/tools/perf/util/event.c b/tools/perf/util/event.c
index 7e0e8ae568ec..1398c83d896d 100644
--- a/tools/perf/util/event.c
+++ b/tools/perf/util/event.c
@@ -874,3 +874,45 @@ int perf_event__preprocess_sample(const union perf_event *event,
874 874
875 return 0; 875 return 0;
876} 876}
877
878bool is_bts_event(struct perf_event_attr *attr)
879{
880 return attr->type == PERF_TYPE_HARDWARE &&
881 (attr->config & PERF_COUNT_HW_BRANCH_INSTRUCTIONS) &&
882 attr->sample_period == 1;
883}
884
885bool sample_addr_correlates_sym(struct perf_event_attr *attr)
886{
887 if (attr->type == PERF_TYPE_SOFTWARE &&
888 (attr->config == PERF_COUNT_SW_PAGE_FAULTS ||
889 attr->config == PERF_COUNT_SW_PAGE_FAULTS_MIN ||
890 attr->config == PERF_COUNT_SW_PAGE_FAULTS_MAJ))
891 return true;
892
893 if (is_bts_event(attr))
894 return true;
895
896 return false;
897}
898
899void perf_event__preprocess_sample_addr(union perf_event *event,
900 struct perf_sample *sample,
901 struct machine *machine,
902 struct thread *thread,
903 struct addr_location *al)
904{
905 u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
906
907 thread__find_addr_map(thread, machine, cpumode, MAP__FUNCTION,
908 sample->addr, al);
909 if (!al->map)
910 thread__find_addr_map(thread, machine, cpumode, MAP__VARIABLE,
911 sample->addr, al);
912
913 al->cpu = sample->cpu;
914 al->sym = NULL;
915
916 if (al->map)
917 al->sym = map__find_symbol(al->map, al->addr, NULL);
918}
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h
index e5dd40addb30..94d6976180da 100644
--- a/tools/perf/util/event.h
+++ b/tools/perf/util/event.h
@@ -288,6 +288,16 @@ int perf_event__preprocess_sample(const union perf_event *event,
288 struct addr_location *al, 288 struct addr_location *al,
289 struct perf_sample *sample); 289 struct perf_sample *sample);
290 290
291struct thread;
292
293bool is_bts_event(struct perf_event_attr *attr);
294bool sample_addr_correlates_sym(struct perf_event_attr *attr);
295void perf_event__preprocess_sample_addr(union perf_event *event,
296 struct perf_sample *sample,
297 struct machine *machine,
298 struct thread *thread,
299 struct addr_location *al);
300
291const char *perf_event__name(unsigned int id); 301const char *perf_event__name(unsigned int id);
292 302
293size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type, 303size_t perf_event__sample_event_size(const struct perf_sample *sample, u64 type,
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 893f8e2df928..158c787ce0c4 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -200,6 +200,47 @@ static int write_buildid(const char *name, size_t name_len, u8 *build_id,
200 return write_padded(fd, name, name_len + 1, len); 200 return write_padded(fd, name, name_len + 1, len);
201} 201}
202 202
203static int __dsos__hit_all(struct list_head *head)
204{
205 struct dso *pos;
206
207 list_for_each_entry(pos, head, node)
208 pos->hit = true;
209
210 return 0;
211}
212
213static int machine__hit_all_dsos(struct machine *machine)
214{
215 int err;
216
217 err = __dsos__hit_all(&machine->kernel_dsos);
218 if (err)
219 return err;
220
221 return __dsos__hit_all(&machine->user_dsos);
222}
223
224int dsos__hit_all(struct perf_session *session)
225{
226 struct rb_node *nd;
227 int err;
228
229 err = machine__hit_all_dsos(&session->machines.host);
230 if (err)
231 return err;
232
233 for (nd = rb_first(&session->machines.guests); nd; nd = rb_next(nd)) {
234 struct machine *pos = rb_entry(nd, struct machine, rb_node);
235
236 err = machine__hit_all_dsos(pos);
237 if (err)
238 return err;
239 }
240
241 return 0;
242}
243
203static int __dsos__write_buildid_table(struct list_head *head, 244static int __dsos__write_buildid_table(struct list_head *head,
204 struct machine *machine, 245 struct machine *machine,
205 pid_t pid, u16 misc, int fd) 246 pid_t pid, u16 misc, int fd)
@@ -215,9 +256,9 @@ static int __dsos__write_buildid_table(struct list_head *head,
215 if (!pos->hit) 256 if (!pos->hit)
216 continue; 257 continue;
217 258
218 if (is_vdso_map(pos->short_name)) { 259 if (dso__is_vdso(pos)) {
219 name = (char *) VDSO__MAP_NAME; 260 name = pos->short_name;
220 name_len = sizeof(VDSO__MAP_NAME) + 1; 261 name_len = pos->short_name_len + 1;
221 } else if (dso__is_kcore(pos)) { 262 } else if (dso__is_kcore(pos)) {
222 machine__mmap_name(machine, nm, sizeof(nm)); 263 machine__mmap_name(machine, nm, sizeof(nm));
223 name = nm; 264 name = nm;
@@ -298,7 +339,7 @@ int build_id_cache__add_s(const char *sbuild_id, const char *debugdir,
298 339
299 len = scnprintf(filename, size, "%s%s%s", 340 len = scnprintf(filename, size, "%s%s%s",
300 debugdir, slash ? "/" : "", 341 debugdir, slash ? "/" : "",
301 is_vdso ? VDSO__MAP_NAME : realname); 342 is_vdso ? DSO__NAME_VDSO : realname);
302 if (mkdir_p(filename, 0755)) 343 if (mkdir_p(filename, 0755))
303 goto out_free; 344 goto out_free;
304 345
@@ -386,7 +427,7 @@ static int dso__cache_build_id(struct dso *dso, struct machine *machine,
386 const char *debugdir) 427 const char *debugdir)
387{ 428{
388 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/'; 429 bool is_kallsyms = dso->kernel && dso->long_name[0] != '/';
389 bool is_vdso = is_vdso_map(dso->short_name); 430 bool is_vdso = dso__is_vdso(dso);
390 const char *name = dso->long_name; 431 const char *name = dso->long_name;
391 char nm[PATH_MAX]; 432 char nm[PATH_MAX];
392 433
diff --git a/tools/perf/util/header.h b/tools/perf/util/header.h
index d08cfe499404..8f5cbaea64a5 100644
--- a/tools/perf/util/header.h
+++ b/tools/perf/util/header.h
@@ -151,6 +151,8 @@ int perf_event__process_build_id(struct perf_tool *tool,
151 struct perf_session *session); 151 struct perf_session *session);
152bool is_perf_magic(u64 magic); 152bool is_perf_magic(u64 magic);
153 153
154int dsos__hit_all(struct perf_session *session);
155
154/* 156/*
155 * arch specific callback 157 * arch specific callback
156 */ 158 */
diff --git a/tools/perf/util/machine.c b/tools/perf/util/machine.c
index 93c8b6fbc799..16bba9fff2c8 100644
--- a/tools/perf/util/machine.c
+++ b/tools/perf/util/machine.c
@@ -8,6 +8,7 @@
8#include "sort.h" 8#include "sort.h"
9#include "strlist.h" 9#include "strlist.h"
10#include "thread.h" 10#include "thread.h"
11#include "vdso.h"
11#include <stdbool.h> 12#include <stdbool.h>
12#include <symbol/kallsyms.h> 13#include <symbol/kallsyms.h>
13#include "unwind.h" 14#include "unwind.h"
@@ -23,6 +24,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
23 INIT_LIST_HEAD(&machine->dead_threads); 24 INIT_LIST_HEAD(&machine->dead_threads);
24 machine->last_match = NULL; 25 machine->last_match = NULL;
25 26
27 machine->vdso_info = NULL;
28
26 machine->kmaps.machine = machine; 29 machine->kmaps.machine = machine;
27 machine->pid = pid; 30 machine->pid = pid;
28 31
@@ -45,6 +48,8 @@ int machine__init(struct machine *machine, const char *root_dir, pid_t pid)
45 thread__set_comm(thread, comm, 0); 48 thread__set_comm(thread, comm, 0);
46 } 49 }
47 50
51 machine->current_tid = NULL;
52
48 return 0; 53 return 0;
49} 54}
50 55
@@ -103,7 +108,9 @@ void machine__exit(struct machine *machine)
103 map_groups__exit(&machine->kmaps); 108 map_groups__exit(&machine->kmaps);
104 dsos__delete(&machine->user_dsos); 109 dsos__delete(&machine->user_dsos);
105 dsos__delete(&machine->kernel_dsos); 110 dsos__delete(&machine->kernel_dsos);
111 vdso__exit(machine);
106 zfree(&machine->root_dir); 112 zfree(&machine->root_dir);
113 zfree(&machine->current_tid);
107} 114}
108 115
109void machine__delete(struct machine *machine) 116void machine__delete(struct machine *machine)
@@ -1092,14 +1099,14 @@ int machine__process_mmap2_event(struct machine *machine,
1092 else 1099 else
1093 type = MAP__FUNCTION; 1100 type = MAP__FUNCTION;
1094 1101
1095 map = map__new(&machine->user_dsos, event->mmap2.start, 1102 map = map__new(machine, event->mmap2.start,
1096 event->mmap2.len, event->mmap2.pgoff, 1103 event->mmap2.len, event->mmap2.pgoff,
1097 event->mmap2.pid, event->mmap2.maj, 1104 event->mmap2.pid, event->mmap2.maj,
1098 event->mmap2.min, event->mmap2.ino, 1105 event->mmap2.min, event->mmap2.ino,
1099 event->mmap2.ino_generation, 1106 event->mmap2.ino_generation,
1100 event->mmap2.prot, 1107 event->mmap2.prot,
1101 event->mmap2.flags, 1108 event->mmap2.flags,
1102 event->mmap2.filename, type); 1109 event->mmap2.filename, type, thread);
1103 1110
1104 if (map == NULL) 1111 if (map == NULL)
1105 goto out_problem; 1112 goto out_problem;
@@ -1142,11 +1149,11 @@ int machine__process_mmap_event(struct machine *machine, union perf_event *event
1142 else 1149 else
1143 type = MAP__FUNCTION; 1150 type = MAP__FUNCTION;
1144 1151
1145 map = map__new(&machine->user_dsos, event->mmap.start, 1152 map = map__new(machine, event->mmap.start,
1146 event->mmap.len, event->mmap.pgoff, 1153 event->mmap.len, event->mmap.pgoff,
1147 event->mmap.pid, 0, 0, 0, 0, 0, 0, 1154 event->mmap.pid, 0, 0, 0, 0, 0, 0,
1148 event->mmap.filename, 1155 event->mmap.filename,
1149 type); 1156 type, thread);
1150 1157
1151 if (map == NULL) 1158 if (map == NULL)
1152 goto out_problem; 1159 goto out_problem;
@@ -1481,3 +1488,46 @@ int __machine__synthesize_threads(struct machine *machine, struct perf_tool *too
1481 /* command specified */ 1488 /* command specified */
1482 return 0; 1489 return 0;
1483} 1490}
1491
1492pid_t machine__get_current_tid(struct machine *machine, int cpu)
1493{
1494 if (cpu < 0 || cpu >= MAX_NR_CPUS || !machine->current_tid)
1495 return -1;
1496
1497 return machine->current_tid[cpu];
1498}
1499
1500int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
1501 pid_t tid)
1502{
1503 struct thread *thread;
1504
1505 if (cpu < 0)
1506 return -EINVAL;
1507
1508 if (!machine->current_tid) {
1509 int i;
1510
1511 machine->current_tid = calloc(MAX_NR_CPUS, sizeof(pid_t));
1512 if (!machine->current_tid)
1513 return -ENOMEM;
1514 for (i = 0; i < MAX_NR_CPUS; i++)
1515 machine->current_tid[i] = -1;
1516 }
1517
1518 if (cpu >= MAX_NR_CPUS) {
1519 pr_err("Requested CPU %d too large. ", cpu);
1520 pr_err("Consider raising MAX_NR_CPUS\n");
1521 return -EINVAL;
1522 }
1523
1524 machine->current_tid[cpu] = tid;
1525
1526 thread = machine__findnew_thread(machine, pid, tid);
1527 if (!thread)
1528 return -ENOMEM;
1529
1530 thread->cpu = cpu;
1531
1532 return 0;
1533}
diff --git a/tools/perf/util/machine.h b/tools/perf/util/machine.h
index c8c74a119398..b972824e6294 100644
--- a/tools/perf/util/machine.h
+++ b/tools/perf/util/machine.h
@@ -20,6 +20,8 @@ union perf_event;
20 20
21extern const char *ref_reloc_sym_names[]; 21extern const char *ref_reloc_sym_names[];
22 22
23struct vdso_info;
24
23struct machine { 25struct machine {
24 struct rb_node rb_node; 26 struct rb_node rb_node;
25 pid_t pid; 27 pid_t pid;
@@ -28,11 +30,13 @@ struct machine {
28 struct rb_root threads; 30 struct rb_root threads;
29 struct list_head dead_threads; 31 struct list_head dead_threads;
30 struct thread *last_match; 32 struct thread *last_match;
33 struct vdso_info *vdso_info;
31 struct list_head user_dsos; 34 struct list_head user_dsos;
32 struct list_head kernel_dsos; 35 struct list_head kernel_dsos;
33 struct map_groups kmaps; 36 struct map_groups kmaps;
34 struct map *vmlinux_maps[MAP__NR_TYPES]; 37 struct map *vmlinux_maps[MAP__NR_TYPES];
35 symbol_filter_t symbol_filter; 38 symbol_filter_t symbol_filter;
39 pid_t *current_tid;
36}; 40};
37 41
38static inline 42static inline
@@ -191,4 +195,8 @@ int machine__synthesize_threads(struct machine *machine, struct target *target,
191 perf_event__process, data_mmap); 195 perf_event__process, data_mmap);
192} 196}
193 197
198pid_t machine__get_current_tid(struct machine *machine, int cpu);
199int machine__set_current_tid(struct machine *machine, int cpu, pid_t pid,
200 pid_t tid);
201
194#endif /* __PERF_MACHINE_H */ 202#endif /* __PERF_MACHINE_H */
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index 845f627e45f4..31b8905dd863 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -13,6 +13,7 @@
13#include "build-id.h" 13#include "build-id.h"
14#include "util.h" 14#include "util.h"
15#include "debug.h" 15#include "debug.h"
16#include "machine.h"
16#include <linux/string.h> 17#include <linux/string.h>
17 18
18const char *map_type__name[MAP__NR_TYPES] = { 19const char *map_type__name[MAP__NR_TYPES] = {
@@ -137,10 +138,10 @@ void map__init(struct map *map, enum map_type type,
137 map->erange_warned = false; 138 map->erange_warned = false;
138} 139}
139 140
140struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, 141struct map *map__new(struct machine *machine, u64 start, u64 len,
141 u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, 142 u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
142 u64 ino_gen, u32 prot, u32 flags, char *filename, 143 u64 ino_gen, u32 prot, u32 flags, char *filename,
143 enum map_type type) 144 enum map_type type, struct thread *thread)
144{ 145{
145 struct map *map = malloc(sizeof(*map)); 146 struct map *map = malloc(sizeof(*map));
146 147
@@ -173,9 +174,9 @@ struct map *map__new(struct list_head *dsos__list, u64 start, u64 len,
173 174
174 if (vdso) { 175 if (vdso) {
175 pgoff = 0; 176 pgoff = 0;
176 dso = vdso__dso_findnew(dsos__list); 177 dso = vdso__dso_findnew(machine, thread);
177 } else 178 } else
178 dso = __dsos__findnew(dsos__list, filename); 179 dso = __dsos__findnew(&machine->user_dsos, filename);
179 180
180 if (dso == NULL) 181 if (dso == NULL)
181 goto out_delete; 182 goto out_delete;
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index 22d13a219590..2f83954af050 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -104,6 +104,7 @@ u64 map__rip_2objdump(struct map *map, u64 rip);
104u64 map__objdump_2mem(struct map *map, u64 ip); 104u64 map__objdump_2mem(struct map *map, u64 ip);
105 105
106struct symbol; 106struct symbol;
107struct thread;
107 108
108/* map__for_each_symbol - iterate over the symbols in the given map 109/* map__for_each_symbol - iterate over the symbols in the given map
109 * 110 *
@@ -119,10 +120,10 @@ typedef int (*symbol_filter_t)(struct map *map, struct symbol *sym);
119 120
120void map__init(struct map *map, enum map_type type, 121void map__init(struct map *map, enum map_type type,
121 u64 start, u64 end, u64 pgoff, struct dso *dso); 122 u64 start, u64 end, u64 pgoff, struct dso *dso);
122struct map *map__new(struct list_head *dsos__list, u64 start, u64 len, 123struct map *map__new(struct machine *machine, u64 start, u64 len,
123 u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino, 124 u64 pgoff, u32 pid, u32 d_maj, u32 d_min, u64 ino,
124 u64 ino_gen, u32 prot, u32 flags, 125 u64 ino_gen, u32 prot, u32 flags,
125 char *filename, enum map_type type); 126 char *filename, enum map_type type, struct thread *thread);
126struct map *map__new2(u64 start, struct dso *dso, enum map_type type); 127struct map *map__new2(u64 start, struct dso *dso, enum map_type type);
127void map__delete(struct map *map); 128void map__delete(struct map *map);
128struct map *map__clone(struct map *map); 129struct map *map__clone(struct map *map);
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index eac14ce0ae8d..88dfef70c13d 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -14,7 +14,6 @@
14#include "util.h" 14#include "util.h"
15#include "cpumap.h" 15#include "cpumap.h"
16#include "perf_regs.h" 16#include "perf_regs.h"
17#include "vdso.h"
18 17
19static int perf_session__open(struct perf_session *session) 18static int perf_session__open(struct perf_session *session)
20{ 19{
@@ -156,7 +155,6 @@ void perf_session__delete(struct perf_session *session)
156 if (session->file) 155 if (session->file)
157 perf_data_file__close(session->file); 156 perf_data_file__close(session->file);
158 free(session); 157 free(session);
159 vdso__exit();
160} 158}
161 159
162static int process_event_synth_tracing_data_stub(struct perf_tool *tool 160static int process_event_synth_tracing_data_stub(struct perf_tool *tool
@@ -511,6 +509,7 @@ static int flush_sample_queue(struct perf_session *s,
511 os->last_flush = iter->timestamp; 509 os->last_flush = iter->timestamp;
512 list_del(&iter->list); 510 list_del(&iter->list);
513 list_add(&iter->list, &os->sample_cache); 511 list_add(&iter->list, &os->sample_cache);
512 os->nr_samples--;
514 513
515 if (show_progress) 514 if (show_progress)
516 ui_progress__update(&prog, 1); 515 ui_progress__update(&prog, 1);
@@ -523,8 +522,6 @@ static int flush_sample_queue(struct perf_session *s,
523 list_entry(head->prev, struct sample_queue, list); 522 list_entry(head->prev, struct sample_queue, list);
524 } 523 }
525 524
526 os->nr_samples = 0;
527
528 return 0; 525 return 0;
529} 526}
530 527
@@ -994,8 +991,10 @@ static int perf_session_deliver_event(struct perf_session *session,
994 } 991 }
995} 992}
996 993
997static int perf_session__process_user_event(struct perf_session *session, union perf_event *event, 994static s64 perf_session__process_user_event(struct perf_session *session,
998 struct perf_tool *tool, u64 file_offset) 995 union perf_event *event,
996 struct perf_tool *tool,
997 u64 file_offset)
999{ 998{
1000 int fd = perf_data_file__fd(session->file); 999 int fd = perf_data_file__fd(session->file);
1001 int err; 1000 int err;
@@ -1037,7 +1036,7 @@ static void event_swap(union perf_event *event, bool sample_id_all)
1037 swap(event, sample_id_all); 1036 swap(event, sample_id_all);
1038} 1037}
1039 1038
1040static int perf_session__process_event(struct perf_session *session, 1039static s64 perf_session__process_event(struct perf_session *session,
1041 union perf_event *event, 1040 union perf_event *event,
1042 struct perf_tool *tool, 1041 struct perf_tool *tool,
1043 u64 file_offset) 1042 u64 file_offset)
@@ -1148,7 +1147,7 @@ static int __perf_session__process_pipe_events(struct perf_session *session,
1148 union perf_event *event; 1147 union perf_event *event;
1149 uint32_t size, cur_size = 0; 1148 uint32_t size, cur_size = 0;
1150 void *buf = NULL; 1149 void *buf = NULL;
1151 int skip = 0; 1150 s64 skip = 0;
1152 u64 head; 1151 u64 head;
1153 ssize_t err; 1152 ssize_t err;
1154 void *p; 1153 void *p;
@@ -1277,13 +1276,13 @@ int __perf_session__process_events(struct perf_session *session,
1277 u64 file_size, struct perf_tool *tool) 1276 u64 file_size, struct perf_tool *tool)
1278{ 1277{
1279 int fd = perf_data_file__fd(session->file); 1278 int fd = perf_data_file__fd(session->file);
1280 u64 head, page_offset, file_offset, file_pos; 1279 u64 head, page_offset, file_offset, file_pos, size;
1281 int err, mmap_prot, mmap_flags, map_idx = 0; 1280 int err, mmap_prot, mmap_flags, map_idx = 0;
1282 size_t mmap_size; 1281 size_t mmap_size;
1283 char *buf, *mmaps[NUM_MMAPS]; 1282 char *buf, *mmaps[NUM_MMAPS];
1284 union perf_event *event; 1283 union perf_event *event;
1285 uint32_t size;
1286 struct ui_progress prog; 1284 struct ui_progress prog;
1285 s64 skip;
1287 1286
1288 perf_tool__fill_defaults(tool); 1287 perf_tool__fill_defaults(tool);
1289 1288
@@ -1344,7 +1343,8 @@ more:
1344 size = event->header.size; 1343 size = event->header.size;
1345 1344
1346 if (size < sizeof(struct perf_event_header) || 1345 if (size < sizeof(struct perf_event_header) ||
1347 perf_session__process_event(session, event, tool, file_pos) < 0) { 1346 (skip = perf_session__process_event(session, event, tool, file_pos))
1347 < 0) {
1348 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n", 1348 pr_err("%#" PRIx64 " [%#x]: failed to process type: %d\n",
1349 file_offset + head, event->header.size, 1349 file_offset + head, event->header.size,
1350 event->header.type); 1350 event->header.type);
@@ -1352,6 +1352,9 @@ more:
1352 goto out_err; 1352 goto out_err;
1353 } 1353 }
1354 1354
1355 if (skip)
1356 size += skip;
1357
1355 head += size; 1358 head += size;
1356 file_pos += size; 1359 file_pos += size;
1357 1360
diff --git a/tools/perf/util/symbol-elf.c b/tools/perf/util/symbol-elf.c
index cef8f426356e..d75349979e65 100644
--- a/tools/perf/util/symbol-elf.c
+++ b/tools/perf/util/symbol-elf.c
@@ -622,7 +622,7 @@ int symsrc__init(struct symsrc *ss, struct dso *dso, const char *name,
622 GElf_Shdr shdr; 622 GElf_Shdr shdr;
623 ss->adjust_symbols = (ehdr.e_type == ET_EXEC || 623 ss->adjust_symbols = (ehdr.e_type == ET_EXEC ||
624 ehdr.e_type == ET_REL || 624 ehdr.e_type == ET_REL ||
625 is_vdso_map(dso->short_name) || 625 dso__is_vdso(dso) ||
626 elf_section_by_name(elf, &ehdr, &shdr, 626 elf_section_by_name(elf, &ehdr, &shdr,
627 ".gnu.prelink_undo", 627 ".gnu.prelink_undo",
628 NULL) != NULL); 628 NULL) != NULL);
@@ -1028,6 +1028,39 @@ int file__read_maps(int fd, bool exe, mapfn_t mapfn, void *data,
1028 return err; 1028 return err;
1029} 1029}
1030 1030
1031enum dso_type dso__type_fd(int fd)
1032{
1033 enum dso_type dso_type = DSO__TYPE_UNKNOWN;
1034 GElf_Ehdr ehdr;
1035 Elf_Kind ek;
1036 Elf *elf;
1037
1038 elf = elf_begin(fd, PERF_ELF_C_READ_MMAP, NULL);
1039 if (elf == NULL)
1040 goto out;
1041
1042 ek = elf_kind(elf);
1043 if (ek != ELF_K_ELF)
1044 goto out_end;
1045
1046 if (gelf_getclass(elf) == ELFCLASS64) {
1047 dso_type = DSO__TYPE_64BIT;
1048 goto out_end;
1049 }
1050
1051 if (gelf_getehdr(elf, &ehdr) == NULL)
1052 goto out_end;
1053
1054 if (ehdr.e_machine == EM_X86_64)
1055 dso_type = DSO__TYPE_X32BIT;
1056 else
1057 dso_type = DSO__TYPE_32BIT;
1058out_end:
1059 elf_end(elf);
1060out:
1061 return dso_type;
1062}
1063
1031static int copy_bytes(int from, off_t from_offs, int to, off_t to_offs, u64 len) 1064static int copy_bytes(int from, off_t from_offs, int to, off_t to_offs, u64 len)
1032{ 1065{
1033 ssize_t r; 1066 ssize_t r;
diff --git a/tools/perf/util/symbol-minimal.c b/tools/perf/util/symbol-minimal.c
index 101f55d407d0..c9541fea9514 100644
--- a/tools/perf/util/symbol-minimal.c
+++ b/tools/perf/util/symbol-minimal.c
@@ -305,6 +305,27 @@ static int fd__is_64_bit(int fd)
305 return e_ident[EI_CLASS] == ELFCLASS64; 305 return e_ident[EI_CLASS] == ELFCLASS64;
306} 306}
307 307
308enum dso_type dso__type_fd(int fd)
309{
310 Elf64_Ehdr ehdr;
311 int ret;
312
313 ret = fd__is_64_bit(fd);
314 if (ret < 0)
315 return DSO__TYPE_UNKNOWN;
316
317 if (ret)
318 return DSO__TYPE_64BIT;
319
320 if (readn(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
321 return DSO__TYPE_UNKNOWN;
322
323 if (ehdr.e_machine == EM_X86_64)
324 return DSO__TYPE_X32BIT;
325
326 return DSO__TYPE_32BIT;
327}
328
308int dso__load_sym(struct dso *dso, struct map *map __maybe_unused, 329int dso__load_sym(struct dso *dso, struct map *map __maybe_unused,
309 struct symsrc *ss, 330 struct symsrc *ss,
310 struct symsrc *runtime_ss __maybe_unused, 331 struct symsrc *runtime_ss __maybe_unused,
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index ee2d3ccd3ad1..e7295e93cff9 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -243,6 +243,8 @@ struct symbol *dso__find_symbol_by_name(struct dso *dso, enum map_type type,
243struct symbol *dso__first_symbol(struct dso *dso, enum map_type type); 243struct symbol *dso__first_symbol(struct dso *dso, enum map_type type);
244struct symbol *dso__next_symbol(struct symbol *sym); 244struct symbol *dso__next_symbol(struct symbol *sym);
245 245
246enum dso_type dso__type_fd(int fd);
247
246int filename__read_build_id(const char *filename, void *bf, size_t size); 248int filename__read_build_id(const char *filename, void *bf, size_t size);
247int sysfs__read_build_id(const char *filename, void *bf, size_t size); 249int sysfs__read_build_id(const char *filename, void *bf, size_t size);
248int modules__parse(const char *filename, void *arg, 250int modules__parse(const char *filename, void *arg,
diff --git a/tools/perf/util/thread.c b/tools/perf/util/thread.c
index 9692c06a9e21..12c7a253a63c 100644
--- a/tools/perf/util/thread.c
+++ b/tools/perf/util/thread.c
@@ -34,6 +34,7 @@ struct thread *thread__new(pid_t pid, pid_t tid)
34 thread->pid_ = pid; 34 thread->pid_ = pid;
35 thread->tid = tid; 35 thread->tid = tid;
36 thread->ppid = -1; 36 thread->ppid = -1;
37 thread->cpu = -1;
37 INIT_LIST_HEAD(&thread->comm_list); 38 INIT_LIST_HEAD(&thread->comm_list);
38 39
39 comm_str = malloc(32); 40 comm_str = malloc(32);
diff --git a/tools/perf/util/thread.h b/tools/perf/util/thread.h
index 3c0c2724f82c..716b7723cce2 100644
--- a/tools/perf/util/thread.h
+++ b/tools/perf/util/thread.h
@@ -17,6 +17,7 @@ struct thread {
17 pid_t pid_; /* Not all tools update this */ 17 pid_t pid_; /* Not all tools update this */
18 pid_t tid; 18 pid_t tid;
19 pid_t ppid; 19 pid_t ppid;
20 int cpu;
20 char shortname[3]; 21 char shortname[3];
21 bool comm_set; 22 bool comm_set;
22 bool dead; /* if set thread has exited */ 23 bool dead; /* if set thread has exited */
diff --git a/tools/perf/util/tsc.c b/tools/perf/util/tsc.c
index ef4749836ce9..4d4210d4e13d 100644
--- a/tools/perf/util/tsc.c
+++ b/tools/perf/util/tsc.c
@@ -23,3 +23,8 @@ u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc)
23 return tc->time_zero + quot * tc->time_mult + 23 return tc->time_zero + quot * tc->time_mult +
24 ((rem * tc->time_mult) >> tc->time_shift); 24 ((rem * tc->time_mult) >> tc->time_shift);
25} 25}
26
27u64 __weak rdtsc(void)
28{
29 return 0;
30}
diff --git a/tools/perf/util/tsc.h b/tools/perf/util/tsc.h
index 4eca84887c8a..a8b78f1b3243 100644
--- a/tools/perf/util/tsc.h
+++ b/tools/perf/util/tsc.h
@@ -7,5 +7,6 @@
7 7
8u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc); 8u64 perf_time_to_tsc(u64 ns, struct perf_tsc_conversion *tc);
9u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc); 9u64 tsc_to_perf_time(u64 cyc, struct perf_tsc_conversion *tc);
10u64 rdtsc(void);
10 11
11#endif 12#endif
diff --git a/tools/perf/util/vdso.c b/tools/perf/util/vdso.c
index 290582452da3..adca69384fcc 100644
--- a/tools/perf/util/vdso.c
+++ b/tools/perf/util/vdso.c
@@ -11,11 +11,34 @@
11#include "vdso.h" 11#include "vdso.h"
12#include "util.h" 12#include "util.h"
13#include "symbol.h" 13#include "symbol.h"
14#include "machine.h"
14#include "linux/string.h" 15#include "linux/string.h"
15#include "debug.h" 16#include "debug.h"
16 17
17static bool vdso_found; 18#define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX"
18static char vdso_file[] = "/tmp/perf-vdso.so-XXXXXX"; 19
20struct vdso_file {
21 bool found;
22 bool error;
23 char temp_file_name[sizeof(VDSO__TEMP_FILE_NAME)];
24 const char *dso_name;
25};
26
27struct vdso_info {
28 struct vdso_file vdso;
29};
30
31static struct vdso_info *vdso_info__new(void)
32{
33 static const struct vdso_info vdso_info_init = {
34 .vdso = {
35 .temp_file_name = VDSO__TEMP_FILE_NAME,
36 .dso_name = DSO__NAME_VDSO,
37 },
38 };
39
40 return memdup(&vdso_info_init, sizeof(vdso_info_init));
41}
19 42
20static int find_vdso_map(void **start, void **end) 43static int find_vdso_map(void **start, void **end)
21{ 44{
@@ -48,7 +71,7 @@ static int find_vdso_map(void **start, void **end)
48 return !found; 71 return !found;
49} 72}
50 73
51static char *get_file(void) 74static char *get_file(struct vdso_file *vdso_file)
52{ 75{
53 char *vdso = NULL; 76 char *vdso = NULL;
54 char *buf = NULL; 77 char *buf = NULL;
@@ -56,10 +79,10 @@ static char *get_file(void)
56 size_t size; 79 size_t size;
57 int fd; 80 int fd;
58 81
59 if (vdso_found) 82 if (vdso_file->found)
60 return vdso_file; 83 return vdso_file->temp_file_name;
61 84
62 if (find_vdso_map(&start, &end)) 85 if (vdso_file->error || find_vdso_map(&start, &end))
63 return NULL; 86 return NULL;
64 87
65 size = end - start; 88 size = end - start;
@@ -68,45 +91,78 @@ static char *get_file(void)
68 if (!buf) 91 if (!buf)
69 return NULL; 92 return NULL;
70 93
71 fd = mkstemp(vdso_file); 94 fd = mkstemp(vdso_file->temp_file_name);
72 if (fd < 0) 95 if (fd < 0)
73 goto out; 96 goto out;
74 97
75 if (size == (size_t) write(fd, buf, size)) 98 if (size == (size_t) write(fd, buf, size))
76 vdso = vdso_file; 99 vdso = vdso_file->temp_file_name;
77 100
78 close(fd); 101 close(fd);
79 102
80 out: 103 out:
81 free(buf); 104 free(buf);
82 105
83 vdso_found = (vdso != NULL); 106 vdso_file->found = (vdso != NULL);
107 vdso_file->error = !vdso_file->found;
84 return vdso; 108 return vdso;
85} 109}
86 110
87void vdso__exit(void) 111void vdso__exit(struct machine *machine)
88{ 112{
89 if (vdso_found) 113 struct vdso_info *vdso_info = machine->vdso_info;
90 unlink(vdso_file); 114
115 if (!vdso_info)
116 return;
117
118 if (vdso_info->vdso.found)
119 unlink(vdso_info->vdso.temp_file_name);
120
121 zfree(&machine->vdso_info);
91} 122}
92 123
93struct dso *vdso__dso_findnew(struct list_head *head) 124static struct dso *vdso__new(struct machine *machine, const char *short_name,
125 const char *long_name)
94{ 126{
95 struct dso *dso = dsos__find(head, VDSO__MAP_NAME, true); 127 struct dso *dso;
96 128
129 dso = dso__new(short_name);
130 if (dso != NULL) {
131 dsos__add(&machine->user_dsos, dso);
132 dso__set_long_name(dso, long_name, false);
133 }
134
135 return dso;
136}
137
138struct dso *vdso__dso_findnew(struct machine *machine,
139 struct thread *thread __maybe_unused)
140{
141 struct vdso_info *vdso_info;
142 struct dso *dso;
143
144 if (!machine->vdso_info)
145 machine->vdso_info = vdso_info__new();
146
147 vdso_info = machine->vdso_info;
148 if (!vdso_info)
149 return NULL;
150
151 dso = dsos__find(&machine->user_dsos, DSO__NAME_VDSO, true);
97 if (!dso) { 152 if (!dso) {
98 char *file; 153 char *file;
99 154
100 file = get_file(); 155 file = get_file(&vdso_info->vdso);
101 if (!file) 156 if (!file)
102 return NULL; 157 return NULL;
103 158
104 dso = dso__new(VDSO__MAP_NAME); 159 dso = vdso__new(machine, DSO__NAME_VDSO, file);
105 if (dso != NULL) {
106 dsos__add(head, dso);
107 dso__set_long_name(dso, file, false);
108 }
109 } 160 }
110 161
111 return dso; 162 return dso;
112} 163}
164
165bool dso__is_vdso(struct dso *dso)
166{
167 return !strcmp(dso->short_name, DSO__NAME_VDSO);
168}
diff --git a/tools/perf/util/vdso.h b/tools/perf/util/vdso.h
index 0f76e7caf6f8..af9d6929a215 100644
--- a/tools/perf/util/vdso.h
+++ b/tools/perf/util/vdso.h
@@ -7,12 +7,21 @@
7 7
8#define VDSO__MAP_NAME "[vdso]" 8#define VDSO__MAP_NAME "[vdso]"
9 9
10#define DSO__NAME_VDSO "[vdso]"
11
10static inline bool is_vdso_map(const char *filename) 12static inline bool is_vdso_map(const char *filename)
11{ 13{
12 return !strcmp(filename, VDSO__MAP_NAME); 14 return !strcmp(filename, VDSO__MAP_NAME);
13} 15}
14 16
15struct dso *vdso__dso_findnew(struct list_head *head); 17struct dso;
16void vdso__exit(void); 18
19bool dso__is_vdso(struct dso *dso);
20
21struct machine;
22struct thread;
23
24struct dso *vdso__dso_findnew(struct machine *machine, struct thread *thread);
25void vdso__exit(struct machine *machine);
17 26
18#endif /* __PERF_VDSO__ */ 27#endif /* __PERF_VDSO__ */