aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/lib/traceevent/.gitignore1
-rw-r--r--tools/lib/traceevent/Makefile14
-rw-r--r--tools/perf/Makefile4
-rw-r--r--tools/perf/builtin-test.c4
-rw-r--r--tools/perf/builtin-top.c2
-rw-r--r--tools/perf/ui/browsers/hists.c4
-rw-r--r--tools/perf/util/annotate.c15
-rw-r--r--tools/perf/util/dso-test-data.c153
-rw-r--r--tools/perf/util/evlist.c2
-rw-r--r--tools/perf/util/header.c6
-rw-r--r--tools/perf/util/hist.c7
-rw-r--r--tools/perf/util/map.c41
-rw-r--r--tools/perf/util/map.h1
-rw-r--r--tools/perf/util/parse-events.c2
-rw-r--r--tools/perf/util/session.c5
-rw-r--r--tools/perf/util/symbol.c447
-rw-r--r--tools/perf/util/symbol.h54
-rw-r--r--tools/perf/util/target.c11
18 files changed, 657 insertions, 116 deletions
diff --git a/tools/lib/traceevent/.gitignore b/tools/lib/traceevent/.gitignore
new file mode 100644
index 000000000000..35f56be5a4cd
--- /dev/null
+++ b/tools/lib/traceevent/.gitignore
@@ -0,0 +1 @@
TRACEEVENT-CFLAGS
diff --git a/tools/lib/traceevent/Makefile b/tools/lib/traceevent/Makefile
index 46c2f6b7b123..14131cb0522d 100644
--- a/tools/lib/traceevent/Makefile
+++ b/tools/lib/traceevent/Makefile
@@ -207,7 +207,7 @@ libtraceevent.so: $(PEVENT_LIB_OBJS)
207libtraceevent.a: $(PEVENT_LIB_OBJS) 207libtraceevent.a: $(PEVENT_LIB_OBJS)
208 $(Q)$(do_build_static_lib) 208 $(Q)$(do_build_static_lib)
209 209
210$(PEVENT_LIB_OBJS): %.o: $(src)/%.c 210$(PEVENT_LIB_OBJS): %.o: $(src)/%.c TRACEEVENT-CFLAGS
211 $(Q)$(do_fpic_compile) 211 $(Q)$(do_fpic_compile)
212 212
213define make_version.h 213define make_version.h
@@ -272,6 +272,16 @@ ifneq ($(dep_includes),)
272 include $(dep_includes) 272 include $(dep_includes)
273endif 273endif
274 274
275### Detect environment changes
276TRACK_CFLAGS = $(subst ','\'',$(CFLAGS)):$(ARCH):$(CROSS_COMPILE)
277
278TRACEEVENT-CFLAGS: force
279 @FLAGS='$(TRACK_CFLAGS)'; \
280 if test x"$$FLAGS" != x"`cat TRACEEVENT-CFLAGS 2>/dev/null`" ; then \
281 echo 1>&2 " * new build flags or cross compiler"; \
282 echo "$$FLAGS" >TRACEEVENT-CFLAGS; \
283 fi
284
275tags: force 285tags: force
276 $(RM) tags 286 $(RM) tags
277 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \ 287 find . -name '*.[ch]' | xargs ctags --extra=+f --c-kinds=+px \
@@ -297,7 +307,7 @@ install: install_lib
297 307
298clean: 308clean:
299 $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d 309 $(RM) *.o *~ $(TARGETS) *.a *.so $(VERSION_FILES) .*.d
300 $(RM) tags TAGS 310 $(RM) TRACEEVENT-CFLAGS tags TAGS
301 311
302endif # skip-makefile 312endif # skip-makefile
303 313
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 75d74e5db8d5..77f124fe57ad 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -354,6 +354,7 @@ LIB_OBJS += $(OUTPUT)util/usage.o
354LIB_OBJS += $(OUTPUT)util/wrapper.o 354LIB_OBJS += $(OUTPUT)util/wrapper.o
355LIB_OBJS += $(OUTPUT)util/sigchain.o 355LIB_OBJS += $(OUTPUT)util/sigchain.o
356LIB_OBJS += $(OUTPUT)util/symbol.o 356LIB_OBJS += $(OUTPUT)util/symbol.o
357LIB_OBJS += $(OUTPUT)util/dso-test-data.o
357LIB_OBJS += $(OUTPUT)util/color.o 358LIB_OBJS += $(OUTPUT)util/color.o
358LIB_OBJS += $(OUTPUT)util/pager.o 359LIB_OBJS += $(OUTPUT)util/pager.o
359LIB_OBJS += $(OUTPUT)util/header.o 360LIB_OBJS += $(OUTPUT)util/header.o
@@ -803,6 +804,9 @@ $(OUTPUT)ui/browsers/map.o: ui/browsers/map.c $(OUTPUT)PERF-CFLAGS
803$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS 804$(OUTPUT)util/rbtree.o: ../../lib/rbtree.c $(OUTPUT)PERF-CFLAGS
804 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $< 805 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -DETC_PERFCONFIG='"$(ETC_PERFCONFIG_SQ)"' $<
805 806
807$(OUTPUT)util/parse-events.o: util/parse-events.c $(OUTPUT)PERF-CFLAGS
808 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) -Wno-redundant-decls $<
809
806$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS 810$(OUTPUT)util/scripting-engines/trace-event-perl.o: util/scripting-engines/trace-event-perl.c $(OUTPUT)PERF-CFLAGS
807 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $< 811 $(QUIET_CC)$(CC) -o $@ -c $(ALL_CFLAGS) $(PERL_EMBED_CCOPTS) -Wno-redundant-decls -Wno-strict-prototypes -Wno-unused-parameter -Wno-shadow $<
808 812
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 5ce30305462b..d909eb74a0eb 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -1142,6 +1142,10 @@ static struct test {
1142 .func = test__perf_pmu, 1142 .func = test__perf_pmu,
1143 }, 1143 },
1144 { 1144 {
1145 .desc = "Test dso data interface",
1146 .func = dso__test_data,
1147 },
1148 {
1145 .func = NULL, 1149 .func = NULL,
1146 }, 1150 },
1147}; 1151};
diff --git a/tools/perf/builtin-top.c b/tools/perf/builtin-top.c
index e3cab5f088f8..35e86c6df713 100644
--- a/tools/perf/builtin-top.c
+++ b/tools/perf/builtin-top.c
@@ -125,7 +125,7 @@ static int perf_top__parse_source(struct perf_top *top, struct hist_entry *he)
125 /* 125 /*
126 * We can't annotate with just /proc/kallsyms 126 * We can't annotate with just /proc/kallsyms
127 */ 127 */
128 if (map->dso->symtab_type == SYMTAB__KALLSYMS) { 128 if (map->dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) {
129 pr_err("Can't annotate %s: No vmlinux file was found in the " 129 pr_err("Can't annotate %s: No vmlinux file was found in the "
130 "path\n", sym->name); 130 "path\n", sym->name);
131 sleep(1); 131 sleep(1);
diff --git a/tools/perf/ui/browsers/hists.c b/tools/perf/ui/browsers/hists.c
index 482f0517b61e..413bd62eedb1 100644
--- a/tools/perf/ui/browsers/hists.c
+++ b/tools/perf/ui/browsers/hists.c
@@ -978,8 +978,8 @@ static int hist_browser__dump(struct hist_browser *browser)
978 fp = fopen(filename, "w"); 978 fp = fopen(filename, "w");
979 if (fp == NULL) { 979 if (fp == NULL) {
980 char bf[64]; 980 char bf[64];
981 strerror_r(errno, bf, sizeof(bf)); 981 const char *err = strerror_r(errno, bf, sizeof(bf));
982 ui_helpline__fpush("Couldn't write to %s: %s", filename, bf); 982 ui_helpline__fpush("Couldn't write to %s: %s", filename, err);
983 return -1; 983 return -1;
984 } 984 }
985 985
diff --git a/tools/perf/util/annotate.c b/tools/perf/util/annotate.c
index 8069dfb5ba77..3a282c0057d2 100644
--- a/tools/perf/util/annotate.c
+++ b/tools/perf/util/annotate.c
@@ -426,7 +426,18 @@ int symbol__alloc_hist(struct symbol *sym)
426{ 426{
427 struct annotation *notes = symbol__annotation(sym); 427 struct annotation *notes = symbol__annotation(sym);
428 const size_t size = symbol__size(sym); 428 const size_t size = symbol__size(sym);
429 size_t sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64)); 429 size_t sizeof_sym_hist;
430
431 /* Check for overflow when calculating sizeof_sym_hist */
432 if (size > (SIZE_MAX - sizeof(struct sym_hist)) / sizeof(u64))
433 return -1;
434
435 sizeof_sym_hist = (sizeof(struct sym_hist) + size * sizeof(u64));
436
437 /* Check for overflow in zalloc argument */
438 if (sizeof_sym_hist > (SIZE_MAX - sizeof(*notes->src))
439 / symbol_conf.nr_events)
440 return -1;
430 441
431 notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist); 442 notes->src = zalloc(sizeof(*notes->src) + symbol_conf.nr_events * sizeof_sym_hist);
432 if (notes->src == NULL) 443 if (notes->src == NULL)
@@ -777,7 +788,7 @@ fallback:
777 free_filename = false; 788 free_filename = false;
778 } 789 }
779 790
780 if (dso->symtab_type == SYMTAB__KALLSYMS) { 791 if (dso->symtab_type == DSO_BINARY_TYPE__KALLSYMS) {
781 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id "; 792 char bf[BUILD_ID_SIZE * 2 + 16] = " with build id ";
782 char *build_id_msg = NULL; 793 char *build_id_msg = NULL;
783 794
diff --git a/tools/perf/util/dso-test-data.c b/tools/perf/util/dso-test-data.c
new file mode 100644
index 000000000000..541cdc72c7df
--- /dev/null
+++ b/tools/perf/util/dso-test-data.c
@@ -0,0 +1,153 @@
1#include "util.h"
2
3#include <stdlib.h>
4#include <sys/types.h>
5#include <sys/stat.h>
6#include <fcntl.h>
7#include <string.h>
8
9#include "symbol.h"
10
11#define TEST_ASSERT_VAL(text, cond) \
12do { \
13 if (!(cond)) { \
14 pr_debug("FAILED %s:%d %s\n", __FILE__, __LINE__, text); \
15 return -1; \
16 } \
17} while (0)
18
19static char *test_file(int size)
20{
21 static char buf_templ[] = "/tmp/test-XXXXXX";
22 char *templ = buf_templ;
23 int fd, i;
24 unsigned char *buf;
25
26 fd = mkostemp(templ, O_CREAT|O_WRONLY|O_TRUNC);
27
28 buf = malloc(size);
29 if (!buf) {
30 close(fd);
31 return NULL;
32 }
33
34 for (i = 0; i < size; i++)
35 buf[i] = (unsigned char) ((int) i % 10);
36
37 if (size != write(fd, buf, size))
38 templ = NULL;
39
40 close(fd);
41 return templ;
42}
43
44#define TEST_FILE_SIZE (DSO__DATA_CACHE_SIZE * 20)
45
46struct test_data_offset {
47 off_t offset;
48 u8 data[10];
49 int size;
50};
51
52struct test_data_offset offsets[] = {
53 /* Fill first cache page. */
54 {
55 .offset = 10,
56 .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
57 .size = 10,
58 },
59 /* Read first cache page. */
60 {
61 .offset = 10,
62 .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
63 .size = 10,
64 },
65 /* Fill cache boundary pages. */
66 {
67 .offset = DSO__DATA_CACHE_SIZE - DSO__DATA_CACHE_SIZE % 10,
68 .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
69 .size = 10,
70 },
71 /* Read cache boundary pages. */
72 {
73 .offset = DSO__DATA_CACHE_SIZE - DSO__DATA_CACHE_SIZE % 10,
74 .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
75 .size = 10,
76 },
77 /* Fill final cache page. */
78 {
79 .offset = TEST_FILE_SIZE - 10,
80 .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
81 .size = 10,
82 },
83 /* Read final cache page. */
84 {
85 .offset = TEST_FILE_SIZE - 10,
86 .data = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 },
87 .size = 10,
88 },
89 /* Read final cache page. */
90 {
91 .offset = TEST_FILE_SIZE - 3,
92 .data = { 7, 8, 9, 0, 0, 0, 0, 0, 0, 0 },
93 .size = 3,
94 },
95};
96
97int dso__test_data(void)
98{
99 struct machine machine;
100 struct dso *dso;
101 char *file = test_file(TEST_FILE_SIZE);
102 size_t i;
103
104 TEST_ASSERT_VAL("No test file", file);
105
106 memset(&machine, 0, sizeof(machine));
107
108 dso = dso__new((const char *)file);
109
110 /* Basic 10 bytes tests. */
111 for (i = 0; i < ARRAY_SIZE(offsets); i++) {
112 struct test_data_offset *data = &offsets[i];
113 ssize_t size;
114 u8 buf[10];
115
116 memset(buf, 0, 10);
117 size = dso__data_read_offset(dso, &machine, data->offset,
118 buf, 10);
119
120 TEST_ASSERT_VAL("Wrong size", size == data->size);
121 TEST_ASSERT_VAL("Wrong data", !memcmp(buf, data->data, 10));
122 }
123
124 /* Read cross multiple cache pages. */
125 {
126 ssize_t size;
127 int c;
128 u8 *buf;
129
130 buf = malloc(TEST_FILE_SIZE);
131 TEST_ASSERT_VAL("ENOMEM\n", buf);
132
133 /* First iteration to fill caches, second one to read them. */
134 for (c = 0; c < 2; c++) {
135 memset(buf, 0, TEST_FILE_SIZE);
136 size = dso__data_read_offset(dso, &machine, 10,
137 buf, TEST_FILE_SIZE);
138
139 TEST_ASSERT_VAL("Wrong size",
140 size == (TEST_FILE_SIZE - 10));
141
142 for (i = 0; i < (size_t)size; i++)
143 TEST_ASSERT_VAL("Wrong data",
144 buf[i] == (i % 10));
145 }
146
147 free(buf);
148 }
149
150 dso__delete(dso);
151 unlink(file);
152 return 0;
153}
diff --git a/tools/perf/util/evlist.c b/tools/perf/util/evlist.c
index f74e9560350e..3edfd3483816 100644
--- a/tools/perf/util/evlist.c
+++ b/tools/perf/util/evlist.c
@@ -214,7 +214,7 @@ int perf_evlist__add_tracepoints(struct perf_evlist *evlist,
214 attrs[i].type = PERF_TYPE_TRACEPOINT; 214 attrs[i].type = PERF_TYPE_TRACEPOINT;
215 attrs[i].config = err; 215 attrs[i].config = err;
216 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME | 216 attrs[i].sample_type = (PERF_SAMPLE_RAW | PERF_SAMPLE_TIME |
217 PERF_SAMPLE_CPU); 217 PERF_SAMPLE_CPU | PERF_SAMPLE_PERIOD);
218 attrs[i].sample_period = 1; 218 attrs[i].sample_period = 1;
219 } 219 }
220 220
diff --git a/tools/perf/util/header.c b/tools/perf/util/header.c
index 5a47aba46759..3a6d20443330 100644
--- a/tools/perf/util/header.c
+++ b/tools/perf/util/header.c
@@ -1212,6 +1212,12 @@ static void print_event_desc(struct perf_header *ph, int fd, FILE *fp)
1212 attr.exclude_user, 1212 attr.exclude_user,
1213 attr.exclude_kernel); 1213 attr.exclude_kernel);
1214 1214
1215 fprintf(fp, ", excl_host = %d, excl_guest = %d",
1216 attr.exclude_host,
1217 attr.exclude_guest);
1218
1219 fprintf(fp, ", precise_ip = %d", attr.precise_ip);
1220
1215 if (nr) 1221 if (nr)
1216 fprintf(fp, ", id = {"); 1222 fprintf(fp, ", id = {");
1217 1223
diff --git a/tools/perf/util/hist.c b/tools/perf/util/hist.c
index 514e2a4b367d..f247ef2789a4 100644
--- a/tools/perf/util/hist.c
+++ b/tools/perf/util/hist.c
@@ -708,7 +708,7 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
708 bool printed = false; 708 bool printed = false;
709 struct rb_node *node; 709 struct rb_node *node;
710 int i = 0; 710 int i = 0;
711 int ret; 711 int ret = 0;
712 712
713 /* 713 /*
714 * If have one single callchain root, don't bother printing 714 * If have one single callchain root, don't bother printing
@@ -747,8 +747,11 @@ static size_t callchain__fprintf_graph(FILE *fp, struct rb_root *root,
747 root = &cnode->rb_root; 747 root = &cnode->rb_root;
748 } 748 }
749 749
750 return __callchain__fprintf_graph(fp, root, total_samples, 750 ret += __callchain__fprintf_graph(fp, root, total_samples,
751 1, 1, left_margin); 751 1, 1, left_margin);
752 ret += fprintf(fp, "\n");
753
754 return ret;
752} 755}
753 756
754static size_t __callchain__fprintf_flat(FILE *fp, 757static size_t __callchain__fprintf_flat(FILE *fp,
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c
index a1f4e3669142..cc33486ad9e2 100644
--- a/tools/perf/util/map.c
+++ b/tools/perf/util/map.c
@@ -7,6 +7,8 @@
7#include <stdio.h> 7#include <stdio.h>
8#include <unistd.h> 8#include <unistd.h>
9#include "map.h" 9#include "map.h"
10#include "thread.h"
11#include "strlist.h"
10 12
11const char *map_type__name[MAP__NR_TYPES] = { 13const char *map_type__name[MAP__NR_TYPES] = {
12 [MAP__FUNCTION] = "Functions", 14 [MAP__FUNCTION] = "Functions",
@@ -585,7 +587,21 @@ int machine__init(struct machine *self, const char *root_dir, pid_t pid)
585 self->kmaps.machine = self; 587 self->kmaps.machine = self;
586 self->pid = pid; 588 self->pid = pid;
587 self->root_dir = strdup(root_dir); 589 self->root_dir = strdup(root_dir);
588 return self->root_dir == NULL ? -ENOMEM : 0; 590 if (self->root_dir == NULL)
591 return -ENOMEM;
592
593 if (pid != HOST_KERNEL_ID) {
594 struct thread *thread = machine__findnew_thread(self, pid);
595 char comm[64];
596
597 if (thread == NULL)
598 return -ENOMEM;
599
600 snprintf(comm, sizeof(comm), "[guest/%d]", pid);
601 thread__set_comm(thread, comm);
602 }
603
604 return 0;
589} 605}
590 606
591static void dsos__delete(struct list_head *self) 607static void dsos__delete(struct list_head *self)
@@ -680,7 +696,15 @@ struct machine *machines__findnew(struct rb_root *self, pid_t pid)
680 (symbol_conf.guestmount)) { 696 (symbol_conf.guestmount)) {
681 sprintf(path, "%s/%d", symbol_conf.guestmount, pid); 697 sprintf(path, "%s/%d", symbol_conf.guestmount, pid);
682 if (access(path, R_OK)) { 698 if (access(path, R_OK)) {
683 pr_err("Can't access file %s\n", path); 699 static struct strlist *seen;
700
701 if (!seen)
702 seen = strlist__new(true, NULL);
703
704 if (!strlist__has_entry(seen, path)) {
705 pr_err("Can't access file %s\n", path);
706 strlist__add(seen, path);
707 }
684 machine = NULL; 708 machine = NULL;
685 goto out; 709 goto out;
686 } 710 }
@@ -714,3 +738,16 @@ char *machine__mmap_name(struct machine *self, char *bf, size_t size)
714 738
715 return bf; 739 return bf;
716} 740}
741
742void machines__set_id_hdr_size(struct rb_root *machines, u16 id_hdr_size)
743{
744 struct rb_node *node;
745 struct machine *machine;
746
747 for (node = rb_first(machines); node; node = rb_next(node)) {
748 machine = rb_entry(node, struct machine, rb_node);
749 machine->id_hdr_size = id_hdr_size;
750 }
751
752 return;
753}
diff --git a/tools/perf/util/map.h b/tools/perf/util/map.h
index c14c665d9a25..03a1e9b08b21 100644
--- a/tools/perf/util/map.h
+++ b/tools/perf/util/map.h
@@ -151,6 +151,7 @@ struct machine *machines__add(struct rb_root *self, pid_t pid,
151struct machine *machines__find_host(struct rb_root *self); 151struct machine *machines__find_host(struct rb_root *self);
152struct machine *machines__find(struct rb_root *self, pid_t pid); 152struct machine *machines__find(struct rb_root *self, pid_t pid);
153struct machine *machines__findnew(struct rb_root *self, pid_t pid); 153struct machine *machines__findnew(struct rb_root *self, pid_t pid);
154void machines__set_id_hdr_size(struct rb_root *self, u16 id_hdr_size);
154char *machine__mmap_name(struct machine *self, char *bf, size_t size); 155char *machine__mmap_name(struct machine *self, char *bf, size_t size);
155int machine__init(struct machine *self, const char *root_dir, pid_t pid); 156int machine__init(struct machine *self, const char *root_dir, pid_t pid);
156void machine__exit(struct machine *self); 157void machine__exit(struct machine *self);
diff --git a/tools/perf/util/parse-events.c b/tools/perf/util/parse-events.c
index 1aa721d7c10f..74a5af4d33ec 100644
--- a/tools/perf/util/parse-events.c
+++ b/tools/perf/util/parse-events.c
@@ -377,6 +377,7 @@ static int add_tracepoint(struct list_head **list, int *idx,
377 attr.sample_type |= PERF_SAMPLE_RAW; 377 attr.sample_type |= PERF_SAMPLE_RAW;
378 attr.sample_type |= PERF_SAMPLE_TIME; 378 attr.sample_type |= PERF_SAMPLE_TIME;
379 attr.sample_type |= PERF_SAMPLE_CPU; 379 attr.sample_type |= PERF_SAMPLE_CPU;
380 attr.sample_type |= PERF_SAMPLE_PERIOD;
380 attr.sample_period = 1; 381 attr.sample_period = 1;
381 382
382 snprintf(name, MAX_NAME_LEN, "%s:%s", sys_name, evt_name); 383 snprintf(name, MAX_NAME_LEN, "%s:%s", sys_name, evt_name);
@@ -489,6 +490,7 @@ int parse_events_add_breakpoint(struct list_head **list, int *idx,
489 attr.bp_len = HW_BREAKPOINT_LEN_4; 490 attr.bp_len = HW_BREAKPOINT_LEN_4;
490 491
491 attr.type = PERF_TYPE_BREAKPOINT; 492 attr.type = PERF_TYPE_BREAKPOINT;
493 attr.sample_period = 1;
492 494
493 return add_event(list, idx, &attr, NULL); 495 return add_event(list, idx, &attr, NULL);
494} 496}
diff --git a/tools/perf/util/session.c b/tools/perf/util/session.c
index 8e485592ca20..8e4f0755d2aa 100644
--- a/tools/perf/util/session.c
+++ b/tools/perf/util/session.c
@@ -87,6 +87,7 @@ void perf_session__update_sample_type(struct perf_session *self)
87 self->sample_id_all = perf_evlist__sample_id_all(self->evlist); 87 self->sample_id_all = perf_evlist__sample_id_all(self->evlist);
88 self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist); 88 self->id_hdr_size = perf_evlist__id_hdr_size(self->evlist);
89 self->host_machine.id_hdr_size = self->id_hdr_size; 89 self->host_machine.id_hdr_size = self->id_hdr_size;
90 machines__set_id_hdr_size(&self->machines, self->id_hdr_size);
90} 91}
91 92
92int perf_session__create_kernel_maps(struct perf_session *self) 93int perf_session__create_kernel_maps(struct perf_session *self)
@@ -918,7 +919,9 @@ static struct machine *
918{ 919{
919 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK; 920 const u8 cpumode = event->header.misc & PERF_RECORD_MISC_CPUMODE_MASK;
920 921
921 if (cpumode == PERF_RECORD_MISC_GUEST_KERNEL && perf_guest) { 922 if (perf_guest &&
923 ((cpumode == PERF_RECORD_MISC_GUEST_KERNEL) ||
924 (cpumode == PERF_RECORD_MISC_GUEST_USER))) {
922 u32 pid; 925 u32 pid;
923 926
924 if (event->header.type == PERF_RECORD_MMAP) 927 if (event->header.type == PERF_RECORD_MMAP)
diff --git a/tools/perf/util/symbol.c b/tools/perf/util/symbol.c
index 50958bbeb26a..fdad4eeeb429 100644
--- a/tools/perf/util/symbol.c
+++ b/tools/perf/util/symbol.c
@@ -29,6 +29,7 @@
29#define NT_GNU_BUILD_ID 3 29#define NT_GNU_BUILD_ID 3
30#endif 30#endif
31 31
32static void dso_cache__free(struct rb_root *root);
32static bool dso__build_id_equal(const struct dso *dso, u8 *build_id); 33static bool dso__build_id_equal(const struct dso *dso, u8 *build_id);
33static int elf_read_build_id(Elf *elf, void *bf, size_t size); 34static int elf_read_build_id(Elf *elf, void *bf, size_t size);
34static void dsos__add(struct list_head *head, struct dso *dso); 35static void dsos__add(struct list_head *head, struct dso *dso);
@@ -48,6 +49,31 @@ struct symbol_conf symbol_conf = {
48 .symfs = "", 49 .symfs = "",
49}; 50};
50 51
52static enum dso_binary_type binary_type_symtab[] = {
53 DSO_BINARY_TYPE__KALLSYMS,
54 DSO_BINARY_TYPE__GUEST_KALLSYMS,
55 DSO_BINARY_TYPE__JAVA_JIT,
56 DSO_BINARY_TYPE__DEBUGLINK,
57 DSO_BINARY_TYPE__BUILD_ID_CACHE,
58 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
59 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
60 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
61 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
62 DSO_BINARY_TYPE__GUEST_KMODULE,
63 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
64 DSO_BINARY_TYPE__NOT_FOUND,
65};
66
67#define DSO_BINARY_TYPE__SYMTAB_CNT sizeof(binary_type_symtab)
68
69static enum dso_binary_type binary_type_data[] = {
70 DSO_BINARY_TYPE__BUILD_ID_CACHE,
71 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
72 DSO_BINARY_TYPE__NOT_FOUND,
73};
74
75#define DSO_BINARY_TYPE__DATA_CNT sizeof(binary_type_data)
76
51int dso__name_len(const struct dso *dso) 77int dso__name_len(const struct dso *dso)
52{ 78{
53 if (!dso) 79 if (!dso)
@@ -318,7 +344,9 @@ struct dso *dso__new(const char *name)
318 dso__set_short_name(dso, dso->name); 344 dso__set_short_name(dso, dso->name);
319 for (i = 0; i < MAP__NR_TYPES; ++i) 345 for (i = 0; i < MAP__NR_TYPES; ++i)
320 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT; 346 dso->symbols[i] = dso->symbol_names[i] = RB_ROOT;
321 dso->symtab_type = SYMTAB__NOT_FOUND; 347 dso->cache = RB_ROOT;
348 dso->symtab_type = DSO_BINARY_TYPE__NOT_FOUND;
349 dso->data_type = DSO_BINARY_TYPE__NOT_FOUND;
322 dso->loaded = 0; 350 dso->loaded = 0;
323 dso->sorted_by_name = 0; 351 dso->sorted_by_name = 0;
324 dso->has_build_id = 0; 352 dso->has_build_id = 0;
@@ -352,6 +380,7 @@ void dso__delete(struct dso *dso)
352 free((char *)dso->short_name); 380 free((char *)dso->short_name);
353 if (dso->lname_alloc) 381 if (dso->lname_alloc)
354 free(dso->long_name); 382 free(dso->long_name);
383 dso_cache__free(&dso->cache);
355 free(dso); 384 free(dso);
356} 385}
357 386
@@ -806,9 +835,9 @@ int dso__load_kallsyms(struct dso *dso, const char *filename,
806 symbols__fixup_end(&dso->symbols[map->type]); 835 symbols__fixup_end(&dso->symbols[map->type]);
807 836
808 if (dso->kernel == DSO_TYPE_GUEST_KERNEL) 837 if (dso->kernel == DSO_TYPE_GUEST_KERNEL)
809 dso->symtab_type = SYMTAB__GUEST_KALLSYMS; 838 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KALLSYMS;
810 else 839 else
811 dso->symtab_type = SYMTAB__KALLSYMS; 840 dso->symtab_type = DSO_BINARY_TYPE__KALLSYMS;
812 841
813 return dso__split_kallsyms(dso, map, filter); 842 return dso__split_kallsyms(dso, map, filter);
814} 843}
@@ -1660,32 +1689,110 @@ out:
1660char dso__symtab_origin(const struct dso *dso) 1689char dso__symtab_origin(const struct dso *dso)
1661{ 1690{
1662 static const char origin[] = { 1691 static const char origin[] = {
1663 [SYMTAB__KALLSYMS] = 'k', 1692 [DSO_BINARY_TYPE__KALLSYMS] = 'k',
1664 [SYMTAB__JAVA_JIT] = 'j', 1693 [DSO_BINARY_TYPE__JAVA_JIT] = 'j',
1665 [SYMTAB__DEBUGLINK] = 'l', 1694 [DSO_BINARY_TYPE__DEBUGLINK] = 'l',
1666 [SYMTAB__BUILD_ID_CACHE] = 'B', 1695 [DSO_BINARY_TYPE__BUILD_ID_CACHE] = 'B',
1667 [SYMTAB__FEDORA_DEBUGINFO] = 'f', 1696 [DSO_BINARY_TYPE__FEDORA_DEBUGINFO] = 'f',
1668 [SYMTAB__UBUNTU_DEBUGINFO] = 'u', 1697 [DSO_BINARY_TYPE__UBUNTU_DEBUGINFO] = 'u',
1669 [SYMTAB__BUILDID_DEBUGINFO] = 'b', 1698 [DSO_BINARY_TYPE__BUILDID_DEBUGINFO] = 'b',
1670 [SYMTAB__SYSTEM_PATH_DSO] = 'd', 1699 [DSO_BINARY_TYPE__SYSTEM_PATH_DSO] = 'd',
1671 [SYMTAB__SYSTEM_PATH_KMODULE] = 'K', 1700 [DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE] = 'K',
1672 [SYMTAB__GUEST_KALLSYMS] = 'g', 1701 [DSO_BINARY_TYPE__GUEST_KALLSYMS] = 'g',
1673 [SYMTAB__GUEST_KMODULE] = 'G', 1702 [DSO_BINARY_TYPE__GUEST_KMODULE] = 'G',
1674 }; 1703 };
1675 1704
1676 if (dso == NULL || dso->symtab_type == SYMTAB__NOT_FOUND) 1705 if (dso == NULL || dso->symtab_type == DSO_BINARY_TYPE__NOT_FOUND)
1677 return '!'; 1706 return '!';
1678 return origin[dso->symtab_type]; 1707 return origin[dso->symtab_type];
1679} 1708}
1680 1709
1710int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
1711 char *root_dir, char *file, size_t size)
1712{
1713 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1714 int ret = 0;
1715
1716 switch (type) {
1717 case DSO_BINARY_TYPE__DEBUGLINK: {
1718 char *debuglink;
1719
1720 strncpy(file, dso->long_name, size);
1721 debuglink = file + dso->long_name_len;
1722 while (debuglink != file && *debuglink != '/')
1723 debuglink--;
1724 if (*debuglink == '/')
1725 debuglink++;
1726 filename__read_debuglink(dso->long_name, debuglink,
1727 size - (debuglink - file));
1728 }
1729 break;
1730 case DSO_BINARY_TYPE__BUILD_ID_CACHE:
1731 /* skip the locally configured cache if a symfs is given */
1732 if (symbol_conf.symfs[0] ||
1733 (dso__build_id_filename(dso, file, size) == NULL))
1734 ret = -1;
1735 break;
1736
1737 case DSO_BINARY_TYPE__FEDORA_DEBUGINFO:
1738 snprintf(file, size, "%s/usr/lib/debug%s.debug",
1739 symbol_conf.symfs, dso->long_name);
1740 break;
1741
1742 case DSO_BINARY_TYPE__UBUNTU_DEBUGINFO:
1743 snprintf(file, size, "%s/usr/lib/debug%s",
1744 symbol_conf.symfs, dso->long_name);
1745 break;
1746
1747 case DSO_BINARY_TYPE__BUILDID_DEBUGINFO:
1748 if (!dso->has_build_id) {
1749 ret = -1;
1750 break;
1751 }
1752
1753 build_id__sprintf(dso->build_id,
1754 sizeof(dso->build_id),
1755 build_id_hex);
1756 snprintf(file, size,
1757 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
1758 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
1759 break;
1760
1761 case DSO_BINARY_TYPE__SYSTEM_PATH_DSO:
1762 snprintf(file, size, "%s%s",
1763 symbol_conf.symfs, dso->long_name);
1764 break;
1765
1766 case DSO_BINARY_TYPE__GUEST_KMODULE:
1767 snprintf(file, size, "%s%s%s", symbol_conf.symfs,
1768 root_dir, dso->long_name);
1769 break;
1770
1771 case DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE:
1772 snprintf(file, size, "%s%s", symbol_conf.symfs,
1773 dso->long_name);
1774 break;
1775
1776 default:
1777 case DSO_BINARY_TYPE__KALLSYMS:
1778 case DSO_BINARY_TYPE__GUEST_KALLSYMS:
1779 case DSO_BINARY_TYPE__JAVA_JIT:
1780 case DSO_BINARY_TYPE__NOT_FOUND:
1781 ret = -1;
1782 break;
1783 }
1784
1785 return ret;
1786}
1787
1681int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter) 1788int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1682{ 1789{
1683 int size = PATH_MAX;
1684 char *name; 1790 char *name;
1685 int ret = -1; 1791 int ret = -1;
1686 int fd; 1792 int fd;
1793 u_int i;
1687 struct machine *machine; 1794 struct machine *machine;
1688 const char *root_dir; 1795 char *root_dir = (char *) "";
1689 int want_symtab; 1796 int want_symtab;
1690 1797
1691 dso__set_loaded(dso, map->type); 1798 dso__set_loaded(dso, map->type);
@@ -1700,7 +1807,7 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1700 else 1807 else
1701 machine = NULL; 1808 machine = NULL;
1702 1809
1703 name = malloc(size); 1810 name = malloc(PATH_MAX);
1704 if (!name) 1811 if (!name)
1705 return -1; 1812 return -1;
1706 1813
@@ -1719,81 +1826,27 @@ int dso__load(struct dso *dso, struct map *map, symbol_filter_t filter)
1719 } 1826 }
1720 1827
1721 ret = dso__load_perf_map(dso, map, filter); 1828 ret = dso__load_perf_map(dso, map, filter);
1722 dso->symtab_type = ret > 0 ? SYMTAB__JAVA_JIT : 1829 dso->symtab_type = ret > 0 ? DSO_BINARY_TYPE__JAVA_JIT :
1723 SYMTAB__NOT_FOUND; 1830 DSO_BINARY_TYPE__NOT_FOUND;
1724 return ret; 1831 return ret;
1725 } 1832 }
1726 1833
1834 if (machine)
1835 root_dir = machine->root_dir;
1836
1727 /* Iterate over candidate debug images. 1837 /* Iterate over candidate debug images.
1728 * On the first pass, only load images if they have a full symtab. 1838 * On the first pass, only load images if they have a full symtab.
1729 * Failing that, do a second pass where we accept .dynsym also 1839 * Failing that, do a second pass where we accept .dynsym also
1730 */ 1840 */
1731 want_symtab = 1; 1841 want_symtab = 1;
1732restart: 1842restart:
1733 for (dso->symtab_type = SYMTAB__DEBUGLINK; 1843 for (i = 0; i < DSO_BINARY_TYPE__SYMTAB_CNT; i++) {
1734 dso->symtab_type != SYMTAB__NOT_FOUND;
1735 dso->symtab_type++) {
1736 switch (dso->symtab_type) {
1737 case SYMTAB__DEBUGLINK: {
1738 char *debuglink;
1739 strncpy(name, dso->long_name, size);
1740 debuglink = name + dso->long_name_len;
1741 while (debuglink != name && *debuglink != '/')
1742 debuglink--;
1743 if (*debuglink == '/')
1744 debuglink++;
1745 filename__read_debuglink(dso->long_name, debuglink,
1746 size - (debuglink - name));
1747 }
1748 break;
1749 case SYMTAB__BUILD_ID_CACHE:
1750 /* skip the locally configured cache if a symfs is given */
1751 if (symbol_conf.symfs[0] ||
1752 (dso__build_id_filename(dso, name, size) == NULL)) {
1753 continue;
1754 }
1755 break;
1756 case SYMTAB__FEDORA_DEBUGINFO:
1757 snprintf(name, size, "%s/usr/lib/debug%s.debug",
1758 symbol_conf.symfs, dso->long_name);
1759 break;
1760 case SYMTAB__UBUNTU_DEBUGINFO:
1761 snprintf(name, size, "%s/usr/lib/debug%s",
1762 symbol_conf.symfs, dso->long_name);
1763 break;
1764 case SYMTAB__BUILDID_DEBUGINFO: {
1765 char build_id_hex[BUILD_ID_SIZE * 2 + 1];
1766 1844
1767 if (!dso->has_build_id) 1845 dso->symtab_type = binary_type_symtab[i];
1768 continue;
1769 1846
1770 build_id__sprintf(dso->build_id, 1847 if (dso__binary_type_file(dso, dso->symtab_type,
1771 sizeof(dso->build_id), 1848 root_dir, name, PATH_MAX))
1772 build_id_hex); 1849 continue;
1773 snprintf(name, size,
1774 "%s/usr/lib/debug/.build-id/%.2s/%s.debug",
1775 symbol_conf.symfs, build_id_hex, build_id_hex + 2);
1776 }
1777 break;
1778 case SYMTAB__SYSTEM_PATH_DSO:
1779 snprintf(name, size, "%s%s",
1780 symbol_conf.symfs, dso->long_name);
1781 break;
1782 case SYMTAB__GUEST_KMODULE:
1783 if (map->groups && machine)
1784 root_dir = machine->root_dir;
1785 else
1786 root_dir = "";
1787 snprintf(name, size, "%s%s%s", symbol_conf.symfs,
1788 root_dir, dso->long_name);
1789 break;
1790
1791 case SYMTAB__SYSTEM_PATH_KMODULE:
1792 snprintf(name, size, "%s%s", symbol_conf.symfs,
1793 dso->long_name);
1794 break;
1795 default:;
1796 }
1797 1850
1798 /* Name is now the name of the next image to try */ 1851 /* Name is now the name of the next image to try */
1799 fd = open(name, O_RDONLY); 1852 fd = open(name, O_RDONLY);
@@ -2010,9 +2063,9 @@ struct map *machine__new_module(struct machine *machine, u64 start,
2010 return NULL; 2063 return NULL;
2011 2064
2012 if (machine__is_host(machine)) 2065 if (machine__is_host(machine))
2013 dso->symtab_type = SYMTAB__SYSTEM_PATH_KMODULE; 2066 dso->symtab_type = DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE;
2014 else 2067 else
2015 dso->symtab_type = SYMTAB__GUEST_KMODULE; 2068 dso->symtab_type = DSO_BINARY_TYPE__GUEST_KMODULE;
2016 map_groups__insert(&machine->kmaps, map); 2069 map_groups__insert(&machine->kmaps, map);
2017 return map; 2070 return map;
2018} 2071}
@@ -2564,8 +2617,15 @@ int machine__create_kernel_maps(struct machine *machine)
2564 __machine__create_kernel_maps(machine, kernel) < 0) 2617 __machine__create_kernel_maps(machine, kernel) < 0)
2565 return -1; 2618 return -1;
2566 2619
2567 if (symbol_conf.use_modules && machine__create_modules(machine) < 0) 2620 if (symbol_conf.use_modules && machine__create_modules(machine) < 0) {
2568 pr_debug("Problems creating module maps, continuing anyway...\n"); 2621 if (machine__is_host(machine))
2622 pr_debug("Problems creating module maps, "
2623 "continuing anyway...\n");
2624 else
2625 pr_debug("Problems creating module maps for guest %d, "
2626 "continuing anyway...\n", machine->pid);
2627 }
2628
2569 /* 2629 /*
2570 * Now that we have all the maps created, just set the ->end of them: 2630 * Now that we have all the maps created, just set the ->end of them:
2571 */ 2631 */
@@ -2905,3 +2965,218 @@ struct map *dso__new_map(const char *name)
2905 2965
2906 return map; 2966 return map;
2907} 2967}
2968
2969static int open_dso(struct dso *dso, struct machine *machine)
2970{
2971 char *root_dir = (char *) "";
2972 char *name;
2973 int fd;
2974
2975 name = malloc(PATH_MAX);
2976 if (!name)
2977 return -ENOMEM;
2978
2979 if (machine)
2980 root_dir = machine->root_dir;
2981
2982 if (dso__binary_type_file(dso, dso->data_type,
2983 root_dir, name, PATH_MAX)) {
2984 free(name);
2985 return -EINVAL;
2986 }
2987
2988 fd = open(name, O_RDONLY);
2989 free(name);
2990 return fd;
2991}
2992
2993int dso__data_fd(struct dso *dso, struct machine *machine)
2994{
2995 int i = 0;
2996
2997 if (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND)
2998 return open_dso(dso, machine);
2999
3000 do {
3001 int fd;
3002
3003 dso->data_type = binary_type_data[i++];
3004
3005 fd = open_dso(dso, machine);
3006 if (fd >= 0)
3007 return fd;
3008
3009 } while (dso->data_type != DSO_BINARY_TYPE__NOT_FOUND);
3010
3011 return -EINVAL;
3012}
3013
3014static void
3015dso_cache__free(struct rb_root *root)
3016{
3017 struct rb_node *next = rb_first(root);
3018
3019 while (next) {
3020 struct dso_cache *cache;
3021
3022 cache = rb_entry(next, struct dso_cache, rb_node);
3023 next = rb_next(&cache->rb_node);
3024 rb_erase(&cache->rb_node, root);
3025 free(cache);
3026 }
3027}
3028
3029static struct dso_cache*
3030dso_cache__find(struct rb_root *root, u64 offset)
3031{
3032 struct rb_node **p = &root->rb_node;
3033 struct rb_node *parent = NULL;
3034 struct dso_cache *cache;
3035
3036 while (*p != NULL) {
3037 u64 end;
3038
3039 parent = *p;
3040 cache = rb_entry(parent, struct dso_cache, rb_node);
3041 end = cache->offset + DSO__DATA_CACHE_SIZE;
3042
3043 if (offset < cache->offset)
3044 p = &(*p)->rb_left;
3045 else if (offset >= end)
3046 p = &(*p)->rb_right;
3047 else
3048 return cache;
3049 }
3050 return NULL;
3051}
3052
3053static void
3054dso_cache__insert(struct rb_root *root, struct dso_cache *new)
3055{
3056 struct rb_node **p = &root->rb_node;
3057 struct rb_node *parent = NULL;
3058 struct dso_cache *cache;
3059 u64 offset = new->offset;
3060
3061 while (*p != NULL) {
3062 u64 end;
3063
3064 parent = *p;
3065 cache = rb_entry(parent, struct dso_cache, rb_node);
3066 end = cache->offset + DSO__DATA_CACHE_SIZE;
3067
3068 if (offset < cache->offset)
3069 p = &(*p)->rb_left;
3070 else if (offset >= end)
3071 p = &(*p)->rb_right;
3072 }
3073
3074 rb_link_node(&new->rb_node, parent, p);
3075 rb_insert_color(&new->rb_node, root);
3076}
3077
3078static ssize_t
3079dso_cache__memcpy(struct dso_cache *cache, u64 offset,
3080 u8 *data, u64 size)
3081{
3082 u64 cache_offset = offset - cache->offset;
3083 u64 cache_size = min(cache->size - cache_offset, size);
3084
3085 memcpy(data, cache->data + cache_offset, cache_size);
3086 return cache_size;
3087}
3088
3089static ssize_t
3090dso_cache__read(struct dso *dso, struct machine *machine,
3091 u64 offset, u8 *data, ssize_t size)
3092{
3093 struct dso_cache *cache;
3094 ssize_t ret;
3095 int fd;
3096
3097 fd = dso__data_fd(dso, machine);
3098 if (fd < 0)
3099 return -1;
3100
3101 do {
3102 u64 cache_offset;
3103
3104 ret = -ENOMEM;
3105
3106 cache = zalloc(sizeof(*cache) + DSO__DATA_CACHE_SIZE);
3107 if (!cache)
3108 break;
3109
3110 cache_offset = offset & DSO__DATA_CACHE_MASK;
3111 ret = -EINVAL;
3112
3113 if (-1 == lseek(fd, cache_offset, SEEK_SET))
3114 break;
3115
3116 ret = read(fd, cache->data, DSO__DATA_CACHE_SIZE);
3117 if (ret <= 0)
3118 break;
3119
3120 cache->offset = cache_offset;
3121 cache->size = ret;
3122 dso_cache__insert(&dso->cache, cache);
3123
3124 ret = dso_cache__memcpy(cache, offset, data, size);
3125
3126 } while (0);
3127
3128 if (ret <= 0)
3129 free(cache);
3130
3131 close(fd);
3132 return ret;
3133}
3134
3135static ssize_t dso_cache_read(struct dso *dso, struct machine *machine,
3136 u64 offset, u8 *data, ssize_t size)
3137{
3138 struct dso_cache *cache;
3139
3140 cache = dso_cache__find(&dso->cache, offset);
3141 if (cache)
3142 return dso_cache__memcpy(cache, offset, data, size);
3143 else
3144 return dso_cache__read(dso, machine, offset, data, size);
3145}
3146
3147ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
3148 u64 offset, u8 *data, ssize_t size)
3149{
3150 ssize_t r = 0;
3151 u8 *p = data;
3152
3153 do {
3154 ssize_t ret;
3155
3156 ret = dso_cache_read(dso, machine, offset, p, size);
3157 if (ret < 0)
3158 return ret;
3159
3160 /* Reached EOF, return what we have. */
3161 if (!ret)
3162 break;
3163
3164 BUG_ON(ret > size);
3165
3166 r += ret;
3167 p += ret;
3168 offset += ret;
3169 size -= ret;
3170
3171 } while (size);
3172
3173 return r;
3174}
3175
3176ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
3177 struct machine *machine, u64 addr,
3178 u8 *data, ssize_t size)
3179{
3180 u64 offset = map->map_ip(map, addr);
3181 return dso__data_read_offset(dso, machine, offset, data, size);
3182}
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h
index a884b99017f0..1fe733a1e21f 100644
--- a/tools/perf/util/symbol.h
+++ b/tools/perf/util/symbol.h
@@ -155,6 +155,21 @@ struct addr_location {
155 s32 cpu; 155 s32 cpu;
156}; 156};
157 157
158enum dso_binary_type {
159 DSO_BINARY_TYPE__KALLSYMS = 0,
160 DSO_BINARY_TYPE__GUEST_KALLSYMS,
161 DSO_BINARY_TYPE__JAVA_JIT,
162 DSO_BINARY_TYPE__DEBUGLINK,
163 DSO_BINARY_TYPE__BUILD_ID_CACHE,
164 DSO_BINARY_TYPE__FEDORA_DEBUGINFO,
165 DSO_BINARY_TYPE__UBUNTU_DEBUGINFO,
166 DSO_BINARY_TYPE__BUILDID_DEBUGINFO,
167 DSO_BINARY_TYPE__SYSTEM_PATH_DSO,
168 DSO_BINARY_TYPE__GUEST_KMODULE,
169 DSO_BINARY_TYPE__SYSTEM_PATH_KMODULE,
170 DSO_BINARY_TYPE__NOT_FOUND,
171};
172
158enum dso_kernel_type { 173enum dso_kernel_type {
159 DSO_TYPE_USER = 0, 174 DSO_TYPE_USER = 0,
160 DSO_TYPE_KERNEL, 175 DSO_TYPE_KERNEL,
@@ -167,19 +182,31 @@ enum dso_swap_type {
167 DSO_SWAP__YES, 182 DSO_SWAP__YES,
168}; 183};
169 184
185#define DSO__DATA_CACHE_SIZE 4096
186#define DSO__DATA_CACHE_MASK ~(DSO__DATA_CACHE_SIZE - 1)
187
188struct dso_cache {
189 struct rb_node rb_node;
190 u64 offset;
191 u64 size;
192 char data[0];
193};
194
170struct dso { 195struct dso {
171 struct list_head node; 196 struct list_head node;
172 struct rb_root symbols[MAP__NR_TYPES]; 197 struct rb_root symbols[MAP__NR_TYPES];
173 struct rb_root symbol_names[MAP__NR_TYPES]; 198 struct rb_root symbol_names[MAP__NR_TYPES];
199 struct rb_root cache;
174 enum dso_kernel_type kernel; 200 enum dso_kernel_type kernel;
175 enum dso_swap_type needs_swap; 201 enum dso_swap_type needs_swap;
202 enum dso_binary_type symtab_type;
203 enum dso_binary_type data_type;
176 u8 adjust_symbols:1; 204 u8 adjust_symbols:1;
177 u8 has_build_id:1; 205 u8 has_build_id:1;
178 u8 hit:1; 206 u8 hit:1;
179 u8 annotate_warned:1; 207 u8 annotate_warned:1;
180 u8 sname_alloc:1; 208 u8 sname_alloc:1;
181 u8 lname_alloc:1; 209 u8 lname_alloc:1;
182 unsigned char symtab_type;
183 u8 sorted_by_name; 210 u8 sorted_by_name;
184 u8 loaded; 211 u8 loaded;
185 u8 build_id[BUILD_ID_SIZE]; 212 u8 build_id[BUILD_ID_SIZE];
@@ -253,21 +280,6 @@ size_t dso__fprintf_symbols_by_name(struct dso *dso,
253 enum map_type type, FILE *fp); 280 enum map_type type, FILE *fp);
254size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp); 281size_t dso__fprintf(struct dso *dso, enum map_type type, FILE *fp);
255 282
256enum symtab_type {
257 SYMTAB__KALLSYMS = 0,
258 SYMTAB__GUEST_KALLSYMS,
259 SYMTAB__JAVA_JIT,
260 SYMTAB__DEBUGLINK,
261 SYMTAB__BUILD_ID_CACHE,
262 SYMTAB__FEDORA_DEBUGINFO,
263 SYMTAB__UBUNTU_DEBUGINFO,
264 SYMTAB__BUILDID_DEBUGINFO,
265 SYMTAB__SYSTEM_PATH_DSO,
266 SYMTAB__GUEST_KMODULE,
267 SYMTAB__SYSTEM_PATH_KMODULE,
268 SYMTAB__NOT_FOUND,
269};
270
271char dso__symtab_origin(const struct dso *dso); 283char dso__symtab_origin(const struct dso *dso);
272void dso__set_long_name(struct dso *dso, char *name); 284void dso__set_long_name(struct dso *dso, char *name);
273void dso__set_build_id(struct dso *dso, void *build_id); 285void dso__set_build_id(struct dso *dso, void *build_id);
@@ -304,4 +316,14 @@ bool symbol_type__is_a(char symbol_type, enum map_type map_type);
304 316
305size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp); 317size_t machine__fprintf_vmlinux_path(struct machine *machine, FILE *fp);
306 318
319int dso__binary_type_file(struct dso *dso, enum dso_binary_type type,
320 char *root_dir, char *file, size_t size);
321
322int dso__data_fd(struct dso *dso, struct machine *machine);
323ssize_t dso__data_read_offset(struct dso *dso, struct machine *machine,
324 u64 offset, u8 *data, ssize_t size);
325ssize_t dso__data_read_addr(struct dso *dso, struct map *map,
326 struct machine *machine, u64 addr,
327 u8 *data, ssize_t size);
328int dso__test_data(void);
307#endif /* __PERF_SYMBOL */ 329#endif /* __PERF_SYMBOL */
diff --git a/tools/perf/util/target.c b/tools/perf/util/target.c
index 1064d5b148ad..3f59c496e64c 100644
--- a/tools/perf/util/target.c
+++ b/tools/perf/util/target.c
@@ -110,8 +110,17 @@ int perf_target__strerror(struct perf_target *target, int errnum,
110 int idx; 110 int idx;
111 const char *msg; 111 const char *msg;
112 112
113 BUG_ON(buflen > 0);
114
113 if (errnum >= 0) { 115 if (errnum >= 0) {
114 strerror_r(errnum, buf, buflen); 116 const char *err = strerror_r(errnum, buf, buflen);
117
118 if (err != buf) {
119 size_t len = strlen(err);
120 char *c = mempcpy(buf, err, min(buflen - 1, len));
121 *c = '\0';
122 }
123
115 return 0; 124 return 0;
116 } 125 }
117 126