diff options
-rw-r--r-- | tools/perf/Makefile | 1 | ||||
-rw-r--r-- | tools/perf/builtin-annotate.c | 79 | ||||
-rw-r--r-- | tools/perf/builtin-record.c | 1 | ||||
-rw-r--r-- | tools/perf/builtin-report.c | 124 | ||||
-rw-r--r-- | tools/perf/util/callchain.h | 1 | ||||
-rw-r--r-- | tools/perf/util/event.h | 30 | ||||
-rw-r--r-- | tools/perf/util/map.c | 97 | ||||
-rw-r--r-- | tools/perf/util/symbol.h | 1 | ||||
-rw-r--r-- | tools/perf/util/util.h | 1 |
9 files changed, 137 insertions, 198 deletions
diff --git a/tools/perf/Makefile b/tools/perf/Makefile index 2aee21baf785..cb9033d3f72f 100644 --- a/tools/perf/Makefile +++ b/tools/perf/Makefile | |||
@@ -340,6 +340,7 @@ LIB_OBJS += util/header.o | |||
340 | LIB_OBJS += util/callchain.o | 340 | LIB_OBJS += util/callchain.o |
341 | LIB_OBJS += util/values.o | 341 | LIB_OBJS += util/values.o |
342 | LIB_OBJS += util/debug.o | 342 | LIB_OBJS += util/debug.o |
343 | LIB_OBJS += util/map.o | ||
343 | 344 | ||
344 | BUILTIN_OBJS += builtin-annotate.o | 345 | BUILTIN_OBJS += builtin-annotate.o |
345 | BUILTIN_OBJS += builtin-help.o | 346 | BUILTIN_OBJS += builtin-help.o |
diff --git a/tools/perf/builtin-annotate.c b/tools/perf/builtin-annotate.c index fee663adeea2..543c4524f8c2 100644 --- a/tools/perf/builtin-annotate.c +++ b/tools/perf/builtin-annotate.c | |||
@@ -51,83 +51,6 @@ struct sym_ext { | |||
51 | char *path; | 51 | char *path; |
52 | }; | 52 | }; |
53 | 53 | ||
54 | struct map { | ||
55 | struct list_head node; | ||
56 | u64 start; | ||
57 | u64 end; | ||
58 | u64 pgoff; | ||
59 | u64 (*map_ip)(struct map *, u64); | ||
60 | struct dso *dso; | ||
61 | }; | ||
62 | |||
63 | static u64 map__map_ip(struct map *map, u64 ip) | ||
64 | { | ||
65 | return ip - map->start + map->pgoff; | ||
66 | } | ||
67 | |||
68 | static u64 vdso__map_ip(struct map *map __used, u64 ip) | ||
69 | { | ||
70 | return ip; | ||
71 | } | ||
72 | |||
73 | static struct map *map__new(struct mmap_event *event) | ||
74 | { | ||
75 | struct map *self = malloc(sizeof(*self)); | ||
76 | |||
77 | if (self != NULL) { | ||
78 | const char *filename = event->filename; | ||
79 | |||
80 | self->start = event->start; | ||
81 | self->end = event->start + event->len; | ||
82 | self->pgoff = event->pgoff; | ||
83 | |||
84 | self->dso = dsos__findnew(filename); | ||
85 | if (self->dso == NULL) | ||
86 | goto out_delete; | ||
87 | |||
88 | if (self->dso == vdso) | ||
89 | self->map_ip = vdso__map_ip; | ||
90 | else | ||
91 | self->map_ip = map__map_ip; | ||
92 | } | ||
93 | return self; | ||
94 | out_delete: | ||
95 | free(self); | ||
96 | return NULL; | ||
97 | } | ||
98 | |||
99 | static struct map *map__clone(struct map *self) | ||
100 | { | ||
101 | struct map *map = malloc(sizeof(*self)); | ||
102 | |||
103 | if (!map) | ||
104 | return NULL; | ||
105 | |||
106 | memcpy(map, self, sizeof(*self)); | ||
107 | |||
108 | return map; | ||
109 | } | ||
110 | |||
111 | static int map__overlap(struct map *l, struct map *r) | ||
112 | { | ||
113 | if (l->start > r->start) { | ||
114 | struct map *t = l; | ||
115 | l = r; | ||
116 | r = t; | ||
117 | } | ||
118 | |||
119 | if (l->end > r->start) | ||
120 | return 1; | ||
121 | |||
122 | return 0; | ||
123 | } | ||
124 | |||
125 | static size_t map__fprintf(struct map *self, FILE *fp) | ||
126 | { | ||
127 | return fprintf(fp, " %Lx-%Lx %Lx %s\n", | ||
128 | self->start, self->end, self->pgoff, self->dso->name); | ||
129 | } | ||
130 | |||
131 | 54 | ||
132 | struct thread { | 55 | struct thread { |
133 | struct rb_node rb_node; | 56 | struct rb_node rb_node; |
@@ -797,7 +720,7 @@ static int | |||
797 | process_mmap_event(event_t *event, unsigned long offset, unsigned long head) | 720 | process_mmap_event(event_t *event, unsigned long offset, unsigned long head) |
798 | { | 721 | { |
799 | struct thread *thread = threads__findnew(event->mmap.pid); | 722 | struct thread *thread = threads__findnew(event->mmap.pid); |
800 | struct map *map = map__new(&event->mmap); | 723 | struct map *map = map__new(&event->mmap, NULL, 0); |
801 | 724 | ||
802 | dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", | 725 | dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", |
803 | (void *)(offset + head), | 726 | (void *)(offset + head), |
diff --git a/tools/perf/builtin-record.c b/tools/perf/builtin-record.c index 718b8f7b6aac..106c6abd1c38 100644 --- a/tools/perf/builtin-record.c +++ b/tools/perf/builtin-record.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include "util/string.h" | 15 | #include "util/string.h" |
16 | 16 | ||
17 | #include "util/header.h" | 17 | #include "util/header.h" |
18 | #include "util/event.h" | ||
18 | 19 | ||
19 | #include <unistd.h> | 20 | #include <unistd.h> |
20 | #include <sched.h> | 21 | #include <sched.h> |
diff --git a/tools/perf/builtin-report.c b/tools/perf/builtin-report.c index 1efefcc2ffdf..93945ecdac86 100644 --- a/tools/perf/builtin-report.c +++ b/tools/perf/builtin-report.c | |||
@@ -67,6 +67,10 @@ static char callchain_default_opt[] = "fractal,0.5"; | |||
67 | 67 | ||
68 | static int callchain; | 68 | static int callchain; |
69 | 69 | ||
70 | static char __cwd[PATH_MAX]; | ||
71 | static char *cwd = __cwd; | ||
72 | static int cwdlen; | ||
73 | |||
70 | static | 74 | static |
71 | struct callchain_param callchain_param = { | 75 | struct callchain_param callchain_param = { |
72 | .mode = CHAIN_GRAPH_REL, | 76 | .mode = CHAIN_GRAPH_REL, |
@@ -102,124 +106,6 @@ static int repsep_fprintf(FILE *fp, const char *fmt, ...) | |||
102 | return n; | 106 | return n; |
103 | } | 107 | } |
104 | 108 | ||
105 | |||
106 | |||
107 | static char __cwd[PATH_MAX]; | ||
108 | static char *cwd = __cwd; | ||
109 | static int cwdlen; | ||
110 | |||
111 | static int strcommon(const char *pathname) | ||
112 | { | ||
113 | int n = 0; | ||
114 | |||
115 | while (n < cwdlen && pathname[n] == cwd[n]) | ||
116 | ++n; | ||
117 | |||
118 | return n; | ||
119 | } | ||
120 | |||
121 | struct map { | ||
122 | struct list_head node; | ||
123 | u64 start; | ||
124 | u64 end; | ||
125 | u64 pgoff; | ||
126 | u64 (*map_ip)(struct map *, u64); | ||
127 | struct dso *dso; | ||
128 | }; | ||
129 | |||
130 | static u64 map__map_ip(struct map *map, u64 ip) | ||
131 | { | ||
132 | return ip - map->start + map->pgoff; | ||
133 | } | ||
134 | |||
135 | static u64 vdso__map_ip(struct map *map __used, u64 ip) | ||
136 | { | ||
137 | return ip; | ||
138 | } | ||
139 | |||
140 | static inline int is_anon_memory(const char *filename) | ||
141 | { | ||
142 | return strcmp(filename, "//anon") == 0; | ||
143 | } | ||
144 | |||
145 | static struct map *map__new(struct mmap_event *event) | ||
146 | { | ||
147 | struct map *self = malloc(sizeof(*self)); | ||
148 | |||
149 | if (self != NULL) { | ||
150 | const char *filename = event->filename; | ||
151 | char newfilename[PATH_MAX]; | ||
152 | int anon; | ||
153 | |||
154 | if (cwd) { | ||
155 | int n = strcommon(filename); | ||
156 | |||
157 | if (n == cwdlen) { | ||
158 | snprintf(newfilename, sizeof(newfilename), | ||
159 | ".%s", filename + n); | ||
160 | filename = newfilename; | ||
161 | } | ||
162 | } | ||
163 | |||
164 | anon = is_anon_memory(filename); | ||
165 | |||
166 | if (anon) { | ||
167 | snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid); | ||
168 | filename = newfilename; | ||
169 | } | ||
170 | |||
171 | self->start = event->start; | ||
172 | self->end = event->start + event->len; | ||
173 | self->pgoff = event->pgoff; | ||
174 | |||
175 | self->dso = dsos__findnew(filename); | ||
176 | if (self->dso == NULL) | ||
177 | goto out_delete; | ||
178 | |||
179 | if (self->dso == vdso || anon) | ||
180 | self->map_ip = vdso__map_ip; | ||
181 | else | ||
182 | self->map_ip = map__map_ip; | ||
183 | } | ||
184 | return self; | ||
185 | out_delete: | ||
186 | free(self); | ||
187 | return NULL; | ||
188 | } | ||
189 | |||
190 | static struct map *map__clone(struct map *self) | ||
191 | { | ||
192 | struct map *map = malloc(sizeof(*self)); | ||
193 | |||
194 | if (!map) | ||
195 | return NULL; | ||
196 | |||
197 | memcpy(map, self, sizeof(*self)); | ||
198 | |||
199 | return map; | ||
200 | } | ||
201 | |||
202 | static int map__overlap(struct map *l, struct map *r) | ||
203 | { | ||
204 | if (l->start > r->start) { | ||
205 | struct map *t = l; | ||
206 | l = r; | ||
207 | r = t; | ||
208 | } | ||
209 | |||
210 | if (l->end > r->start) | ||
211 | return 1; | ||
212 | |||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | static size_t map__fprintf(struct map *self, FILE *fp) | ||
217 | { | ||
218 | return fprintf(fp, " %Lx-%Lx %Lx %s\n", | ||
219 | self->start, self->end, self->pgoff, self->dso->name); | ||
220 | } | ||
221 | |||
222 | |||
223 | struct thread { | 109 | struct thread { |
224 | struct rb_node rb_node; | 110 | struct rb_node rb_node; |
225 | struct list_head maps; | 111 | struct list_head maps; |
@@ -1474,7 +1360,7 @@ static int | |||
1474 | process_mmap_event(event_t *event, unsigned long offset, unsigned long head) | 1360 | process_mmap_event(event_t *event, unsigned long offset, unsigned long head) |
1475 | { | 1361 | { |
1476 | struct thread *thread = threads__findnew(event->mmap.pid); | 1362 | struct thread *thread = threads__findnew(event->mmap.pid); |
1477 | struct map *map = map__new(&event->mmap); | 1363 | struct map *map = map__new(&event->mmap, cwd, cwdlen); |
1478 | 1364 | ||
1479 | dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", | 1365 | dprintf("%p [%p]: PERF_EVENT_MMAP %d: [%p(%p) @ %p]: %s\n", |
1480 | (void *)(offset + head), | 1366 | (void *)(offset + head), |
diff --git a/tools/perf/util/callchain.h b/tools/perf/util/callchain.h index a926ae4f5a16..43cf3ea9e088 100644 --- a/tools/perf/util/callchain.h +++ b/tools/perf/util/callchain.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include "../perf.h" | 4 | #include "../perf.h" |
5 | #include <linux/list.h> | 5 | #include <linux/list.h> |
6 | #include <linux/rbtree.h> | 6 | #include <linux/rbtree.h> |
7 | #include "util.h" | ||
7 | #include "symbol.h" | 8 | #include "symbol.h" |
8 | 9 | ||
9 | enum chain_mode { | 10 | enum chain_mode { |
diff --git a/tools/perf/util/event.h b/tools/perf/util/event.h index 91e2fe589f27..d26dc887ce52 100644 --- a/tools/perf/util/event.h +++ b/tools/perf/util/event.h | |||
@@ -1,4 +1,8 @@ | |||
1 | #ifndef __PERF_EVENT_H | ||
2 | #define __PERF_EVENT_H | ||
1 | #include "../perf.h" | 3 | #include "../perf.h" |
4 | #include "util.h" | ||
5 | #include <linux/list.h> | ||
2 | 6 | ||
3 | struct ip_event { | 7 | struct ip_event { |
4 | struct perf_event_header header; | 8 | struct perf_event_header header; |
@@ -52,3 +56,29 @@ typedef union event_union { | |||
52 | struct lost_event lost; | 56 | struct lost_event lost; |
53 | struct read_event read; | 57 | struct read_event read; |
54 | } event_t; | 58 | } event_t; |
59 | |||
60 | struct map { | ||
61 | struct list_head node; | ||
62 | u64 start; | ||
63 | u64 end; | ||
64 | u64 pgoff; | ||
65 | u64 (*map_ip)(struct map *, u64); | ||
66 | struct dso *dso; | ||
67 | }; | ||
68 | |||
69 | static inline u64 map__map_ip(struct map *map, u64 ip) | ||
70 | { | ||
71 | return ip - map->start + map->pgoff; | ||
72 | } | ||
73 | |||
74 | static inline u64 vdso__map_ip(struct map *map __used, u64 ip) | ||
75 | { | ||
76 | return ip; | ||
77 | } | ||
78 | |||
79 | struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen); | ||
80 | struct map *map__clone(struct map *self); | ||
81 | int map__overlap(struct map *l, struct map *r); | ||
82 | size_t map__fprintf(struct map *self, FILE *fp); | ||
83 | |||
84 | #endif | ||
diff --git a/tools/perf/util/map.c b/tools/perf/util/map.c new file mode 100644 index 000000000000..804e02382739 --- /dev/null +++ b/tools/perf/util/map.c | |||
@@ -0,0 +1,97 @@ | |||
1 | #include "event.h" | ||
2 | #include "symbol.h" | ||
3 | #include <stdlib.h> | ||
4 | #include <string.h> | ||
5 | #include <stdio.h> | ||
6 | |||
7 | static inline int is_anon_memory(const char *filename) | ||
8 | { | ||
9 | return strcmp(filename, "//anon") == 0; | ||
10 | } | ||
11 | |||
12 | static int strcommon(const char *pathname, char *cwd, int cwdlen) | ||
13 | { | ||
14 | int n = 0; | ||
15 | |||
16 | while (n < cwdlen && pathname[n] == cwd[n]) | ||
17 | ++n; | ||
18 | |||
19 | return n; | ||
20 | } | ||
21 | |||
22 | struct map *map__new(struct mmap_event *event, char *cwd, int cwdlen) | ||
23 | { | ||
24 | struct map *self = malloc(sizeof(*self)); | ||
25 | |||
26 | if (self != NULL) { | ||
27 | const char *filename = event->filename; | ||
28 | char newfilename[PATH_MAX]; | ||
29 | int anon; | ||
30 | |||
31 | if (cwd) { | ||
32 | int n = strcommon(filename, cwd, cwdlen); | ||
33 | |||
34 | if (n == cwdlen) { | ||
35 | snprintf(newfilename, sizeof(newfilename), | ||
36 | ".%s", filename + n); | ||
37 | filename = newfilename; | ||
38 | } | ||
39 | } | ||
40 | |||
41 | anon = is_anon_memory(filename); | ||
42 | |||
43 | if (anon) { | ||
44 | snprintf(newfilename, sizeof(newfilename), "/tmp/perf-%d.map", event->pid); | ||
45 | filename = newfilename; | ||
46 | } | ||
47 | |||
48 | self->start = event->start; | ||
49 | self->end = event->start + event->len; | ||
50 | self->pgoff = event->pgoff; | ||
51 | |||
52 | self->dso = dsos__findnew(filename); | ||
53 | if (self->dso == NULL) | ||
54 | goto out_delete; | ||
55 | |||
56 | if (self->dso == vdso || anon) | ||
57 | self->map_ip = vdso__map_ip; | ||
58 | else | ||
59 | self->map_ip = map__map_ip; | ||
60 | } | ||
61 | return self; | ||
62 | out_delete: | ||
63 | free(self); | ||
64 | return NULL; | ||
65 | } | ||
66 | |||
67 | struct map *map__clone(struct map *self) | ||
68 | { | ||
69 | struct map *map = malloc(sizeof(*self)); | ||
70 | |||
71 | if (!map) | ||
72 | return NULL; | ||
73 | |||
74 | memcpy(map, self, sizeof(*self)); | ||
75 | |||
76 | return map; | ||
77 | } | ||
78 | |||
79 | int map__overlap(struct map *l, struct map *r) | ||
80 | { | ||
81 | if (l->start > r->start) { | ||
82 | struct map *t = l; | ||
83 | l = r; | ||
84 | r = t; | ||
85 | } | ||
86 | |||
87 | if (l->end > r->start) | ||
88 | return 1; | ||
89 | |||
90 | return 0; | ||
91 | } | ||
92 | |||
93 | size_t map__fprintf(struct map *self, FILE *fp) | ||
94 | { | ||
95 | return fprintf(fp, " %Lx-%Lx %Lx %s\n", | ||
96 | self->start, self->end, self->pgoff, self->dso->name); | ||
97 | } | ||
diff --git a/tools/perf/util/symbol.h b/tools/perf/util/symbol.h index f3490fcd40ee..50f723571241 100644 --- a/tools/perf/util/symbol.h +++ b/tools/perf/util/symbol.h | |||
@@ -6,6 +6,7 @@ | |||
6 | #include <linux/list.h> | 6 | #include <linux/list.h> |
7 | #include <linux/rbtree.h> | 7 | #include <linux/rbtree.h> |
8 | #include "module.h" | 8 | #include "module.h" |
9 | #include "event.h" | ||
9 | 10 | ||
10 | struct symbol { | 11 | struct symbol { |
11 | struct rb_node rb_node; | 12 | struct rb_node rb_node; |
diff --git a/tools/perf/util/util.h b/tools/perf/util/util.h index be4b52cca2c3..d61a6f037631 100644 --- a/tools/perf/util/util.h +++ b/tools/perf/util/util.h | |||
@@ -83,7 +83,6 @@ | |||
83 | #include <inttypes.h> | 83 | #include <inttypes.h> |
84 | #include "../../../include/linux/magic.h" | 84 | #include "../../../include/linux/magic.h" |
85 | 85 | ||
86 | #include "event.h" | ||
87 | 86 | ||
88 | #ifndef NO_ICONV | 87 | #ifndef NO_ICONV |
89 | #include <iconv.h> | 88 | #include <iconv.h> |